diff --git a/.changeset/neat-carrots-camp.md b/.changeset/neat-carrots-camp.md new file mode 100644 index 000000000000..0253c49f451b --- /dev/null +++ b/.changeset/neat-carrots-camp.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/sdk': patch +--- + +Minor optimizations and improvements to FPAC functions. diff --git a/.circleci/config.yml b/.circleci/config.yml index e6ad1637312b..2e0e84ac42e9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,15 +3,35 @@ version: 2.1 parameters: ci_builder_image: type: string - default: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:v0.40.0 + default: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:v0.43.0 + ci_builder_rust_image: + type: string + default: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder-rust:latest base_image: type: string - default: ubuntu-2204:2022.07.1 + default: default + # The dispatch parameters are used to manually dispatch pipelines that normally only run post-merge on develop + # from the CircleCI UI. Example configuration: + # when: + # or: + # - equal: [ "develop", <> ] + # - equal: [ true, <> ] + # Add a new `*_dispatch` parameter for any pipeline you want manual dispatch for. + main_dispatch: + type: boolean + default: true # default to running main in case the manual run cancelled an automatic run + fault_proofs_dispatch: + type: boolean + default: false + kontrol_dispatch: + type: boolean + default: false orbs: go: circleci/go@1.8.0 gcp-cli: circleci/gcp-cli@3.0.1 slack: circleci/slack@4.10.1 + shellcheck: circleci/shellcheck@3.2.0 commands: gcp-oidc-authenticate: description: "Authenticate with GCP using a CircleCI OIDC token." @@ -53,31 +73,43 @@ commands: gcloud auth login --brief --cred-file "<< parameters.gcp_cred_config_file_path >>" # Configure ADC echo "export GOOGLE_APPLICATION_CREDENTIALS='<< parameters.gcp_cred_config_file_path >>'" | tee -a "$BASH_ENV" + check-changed: description: "Conditionally halts a step if certain modules change" parameters: patterns: type: string description: "Comma-separated list of dependencies" + no_go_deps: + type: string + default: "" + description: "If set, does not trigger on `go.mod` / `go.sum` changes." steps: - run: name: "Check for changes" + environment: + CHECK_CHANGED_NO_GO_DEPS: "<>" command: | cd ops/check-changed pip3 install -r requirements.txt python3 main.py "<>" + notify-failures-on-develop: description: "Notify Slack" parameters: channel: type: string default: C03N11M0BBN + mentions: + type: string + default: "" steps: - slack/notify: channel: << parameters.channel >> event: fail template: basic_fail_1 branch_pattern: develop + mentions: "<< parameters.mentions >>" jobs: cannon-go-lint-and-test: @@ -87,7 +119,7 @@ jobs: steps: - checkout - check-changed: - patterns: cannon,packages/contracts-bedrock/src/cannon,op-preimage + patterns: cannon,packages/contracts-bedrock/src/cannon,op-preimage,go.mod - run: name: prep Cannon results dir command: mkdir -p /tmp/test-results @@ -130,15 +162,19 @@ jobs: resource_class: xlarge steps: - checkout + - run: + name: "Check L1 geth version" + command: ./ops/scripts/geth-version-checker.sh || (echo "geth version is wrong, update ci-builder"; false) - run: name: git submodules command: make submodules - - check-changed: - patterns: op-chain-ops,packages/,op-node - restore_cache: name: Restore PNPM Package Cache keys: - pnpm-packages-v2-{{ checksum "pnpm-lock.yaml" }} + - restore_cache: + name: Restore Go modules cache + key: gomod-{{ checksum "go.sum" }} # Fetch node_modules into the pnpm store # This will cache node_modules based on pnpm-lock so other steps can instantly install them with `pnpm install --prefer-offline` # --prefer-offline installs node_modules instantly by just reading from cache if it exists rather than fetching from network @@ -164,6 +200,21 @@ jobs: environment: FOUNDRY_PROFILE: ci command: pnpm build + - run: + name: Generate FPAC allocs + command: DEVNET_FPAC="true" make devnet-allocs + - run: + name: Copy FPAC allocs to .devnet-fpac + command: cp -r .devnet/ .devnet-fault-proofs/ + - run: + name: Generate Plasma allocs + command: DEVNET_PLASMA="true" make devnet-allocs + - run: + name: Copy Plasma allocs to .devnet-plasma + command: cp -r .devnet/ .devnet-plasma/ + - run: + name: Generate non-FPAC allocs + command: make devnet-allocs - persist_to_workspace: root: "." paths: @@ -173,6 +224,14 @@ jobs: - "packages/contracts-bedrock/forge-artifacts" - "packages/contracts-bedrock/tsconfig.tsbuildinfo" - "packages/contracts-bedrock/tsconfig.build.tsbuildinfo" + - ".devnet/allocs-l1.json" + - ".devnet/addresses.json" + - ".devnet-fault-proofs/allocs-l1.json" + - ".devnet-fault-proofs/addresses.json" + - ".devnet-plasma/allocs-l1.json" + - ".devnet-plasma/addresses.json" + - "packages/contracts-bedrock/deploy-config/devnetL1.json" + - "packages/contracts-bedrock/deployments/devnetL1" docker-build: environment: @@ -234,13 +293,6 @@ jobs: - "<>" steps: - gcp-oidc-authenticate - # Below is CircleCI recommended way of specifying nameservers on an Ubuntu box: - # https://support.circleci.com/hc/en-us/articles/7323511028251-How-to-set-custom-DNS-on-Ubuntu-based-images-using-netplan - - run: sudo sed -i '13 i \ \ \ \ \ \ \ \ \ \ \ \ nameservers:' /etc/netplan/50-cloud-init.yaml - - run: sudo sed -i '14 i \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ addresses:' /etc/netplan/50-cloud-init.yaml - - run: sudo sed -i "s/addresses:/ addresses":" [8.8.8.8, 8.8.4.4] /g" /etc/netplan/50-cloud-init.yaml - - run: cat /etc/netplan/50-cloud-init.yaml - - run: sudo netplan apply - run: name: Build command: | @@ -317,6 +369,35 @@ jobs: name: Tag command: | ./ops/scripts/ci-docker-tag-op-stack-release.sh <>/<> $CIRCLE_TAG $CIRCLE_SHA1 + - when: + condition: + and: + - or: + - "<>" + - "<>" + - equal: [develop, << pipeline.git.branch >>] + steps: + - gcp-oidc-authenticate: + service_account_email: GCP_SERVICE_ATTESTOR_ACCOUNT_EMAIL + - run: + name: Sign + command: | + git clone https://github.com/ethereum-optimism/binary_signer + cd binary_signer/signer + git checkout tags/v1.0.3 + + IMAGE_PATH="<>/<>/<>:<>" + echo $IMAGE_PATH + pip3 install -r requirements.txt + + python3 ./sign_image.py --command="sign"\ + --attestor-project-name="$ATTESTOR_PROJECT_NAME"\ + --attestor-name="$ATTESTOR_NAME"\ + --image-path="$IMAGE_PATH"\ + --signer-logging-level="INFO"\ + --attestor-key-id="//cloudkms.googleapis.com/v1/projects/$ATTESTOR_PROJECT_NAME/locations/global/keyRings/$ATTESTOR_NAME-key-ring/cryptoKeys/$ATTESTOR_NAME-key/cryptoKeyVersions/1" + + contracts-bedrock-coverage: @@ -374,7 +455,7 @@ jobs: working_directory: packages/contracts-bedrock - run: name: run tests - command: STRICT_DEPLOYMENT=false pnpm test + command: pnpm test environment: FOUNDRY_PROFILE: ci working_directory: packages/contracts-bedrock @@ -396,11 +477,16 @@ jobs: - attach_workspace: { at: "." } - check-changed: patterns: contracts-bedrock,op-node + - setup_remote_docker: + docker_layer_caching: true # populate node modules from the cache - run: name: Install dependencies command: pnpm install:ci # Note: this step needs to come first because one of the later steps modifies the cache & forces a contracts rebuild + - run: + name: forge version + command: forge --version - run: name: semver lock command: | @@ -419,8 +505,7 @@ jobs: - run: name: gas snapshot command: | - forge --version - STRICT_DEPLOYMENT=false pnpm gas-snapshot --check || echo "export GAS_SNAPSHOT_STATUS=1" >> "$BASH_ENV" + pnpm gas-snapshot --check || echo "export GAS_SNAPSHOT_STATUS=1" >> "$BASH_ENV" environment: FOUNDRY_PROFILE: ci working_directory: packages/contracts-bedrock @@ -440,12 +525,12 @@ jobs: name: check statuses command: | if [[ "$LINT_STATUS" -ne 0 ]]; then - FAILED=1 echo "Linting failed, see job output for details." + FAILED=1 fi if [[ "$GAS_SNAPSHOT_STATUS" -ne 0 ]]; then - FAILED=1 echo "Gas snapshot failed, see job output for details." + FAILED=1 fi if [[ "$SEMVER_LOCK_STATUS" -ne 0 ]]; then echo "Semver lock failed, see job output for details." @@ -467,19 +552,6 @@ jobs: exit 1 fi - contracts-bedrock-slither: - docker: - - image: <> - resource_class: medium - steps: - - checkout - - check-changed: - patterns: contracts-bedrock - - run: - name: slither - command: pnpm slither:check - working_directory: packages/contracts-bedrock - contracts-bedrock-validate-spaces: docker: - image: <> @@ -795,40 +867,72 @@ jobs: go-e2e-test: parameters: + fpac: + type: string + default: '' module: description: Go Module Name type: string target: description: The make target to execute type: string - cannon_enabled: - description: Whether to include cannon tests - default: true + parallelism: + description: Number of parallel test runs + type: integer + default: 6 + notify: + description: Whether to notify on failure type: boolean + default: false + mentions: + description: Slack user or group to mention when notifying of failures + type: string + default: "" + environment: + DEVNET_FPAC: 'false' + OP_E2E_USE_FPAC: 'false' docker: - image: <> resource_class: xlarge - # Note: Tests are split between runs manually. - # Tests default to run on the first executor but can be moved to the second with: - # InitParallel(t, UseExecutor(1)) - # Any tests assigned to an executor greater than the number available automatically use the last executor. - # Executor indexes start from 0 - parallelism: 2 + parallelism: <> steps: - checkout + - when: + condition: + equal: ['-fault-proofs', <>] + steps: + - run: + name: Set DEVNET_FPAC = true + command: echo 'export DEVNET_FPAC=true' >> $BASH_ENV + - run: + name: Set OP_E2E_USE_FPAC = true + command: echo 'export OP_E2E_USE_FPAC=true' >> $BASH_ENV + - when: + condition: + equal: ['-plasma', <>] + steps: + - run: + name: Set OP_E2E_USE_PLASMA = true + command: echo 'export OP_E2E_USE_PLASMA=true' >> $BASH_ENV - check-changed: patterns: op-(.+),cannon,contracts-bedrock - run: name: prep results dir command: mkdir -p /tmp/test-results + - restore_cache: + name: Restore Go modules cache + key: gomod-{{ checksum "go.sum" }} + - restore_cache: + name: Restore Go build cache + key: golang-build-cache - attach_workspace: at: /tmp/workspace - run: name: Load devnet-allocs command: | mkdir -p .devnet - cp /tmp/workspace/.devnet/allocs-l1.json .devnet/allocs-l1.json - cp /tmp/workspace/.devnet/addresses.json .devnet/addresses.json + cp /tmp/workspace/.devnet<>/allocs-l1.json .devnet/allocs-l1.json + cp /tmp/workspace/.devnet<>/addresses.json .devnet/addresses.json cp /tmp/workspace/packages/contracts-bedrock/deploy-config/devnetL1.json packages/contracts-bedrock/deploy-config/devnetL1.json cp -r /tmp/workspace/packages/contracts-bedrock/deployments/devnetL1 packages/contracts-bedrock/deployments/devnetL1 - run: @@ -840,7 +944,10 @@ jobs: command: | mkdir -p /testlogs - export OP_E2E_CANNON_ENABLED="<>" + # The below env var gets overridden when running make test-cannon, but we + # need to explicitly set it here to prevent Cannon from running when we don't + # want it to. + export OP_E2E_CANNON_ENABLED="false" # Note: We don't use circle CI test splits because we need to split by test name, not by package. There is an additional # constraint that gotestsum does not currently (nor likely will) accept files from different pacakges when building. JUNIT_FILE=/tmp/test-results/<>_<>.xml make <> 2>&1 | tee /testlogs/test.log @@ -850,6 +957,11 @@ jobs: when: always - store_test_results: path: /tmp/test-results + - when: + condition: "<>" + steps: + - notify-failures-on-develop: + mentions: "<>" go-lint-test-build: parameters: @@ -896,12 +1008,29 @@ jobs: working_directory: <> indexer-tests: + parameters: + fpac: + type: string + default: '' + environment: + DEVNET_FPAC: 'false' + OP_E2E_USE_FPAC: 'false' docker: - image: <> - image: cimg/postgres:14.1 resource_class: xlarge steps: - checkout + - when: + condition: + equal: ['fault-proofs', <>] + steps: + - run: + name: Set DEVNET_FPAC = true + command: echo 'export DEVNET_FPAC=true' >> $BASH_ENV + - run: + name: Set OP_E2E_USE_FPAC = true + command: echo 'export OP_E2E_USE_FPAC=true' >> $BASH_ENV - check-changed: patterns: indexer - run: @@ -999,11 +1128,23 @@ jobs: devnet: machine: image: <> + parameters: + fpac: + type: string environment: DOCKER_BUILDKIT: 1 DEVNET_NO_BUILD: 'true' + # Default value; Can be overridden. + DEVNET_FPAC: 'false' steps: - checkout + - when: + condition: + equal: ['-fault-proofs', <>] + steps: + - run: + name: Set DEVNET_FPAC = true + command: echo 'export DEVNET_FPAC=true' >> $BASH_ENV - check-changed: patterns: op-(.+),packages,ops-bedrock,bedrock-devnet - run: @@ -1014,6 +1155,14 @@ jobs: sudo tar -C /usr/local -xzf go1.21.1.linux-amd64.tar.gz export PATH=$PATH:/usr/local/go/bin go version + - run: + name: Install Geth + command: | + wget https://gethstore.blob.core.windows.net/builds/geth-alltools-linux-amd64-1.13.4-3f907d6a.tar.gz + # geth only provides md5 sums sadly + echo 'c2e3d38372cb8081ed01591246a7556f geth-alltools-linux-amd64-1.13.4-3f907d6a.tar.gz' | md5sum -c - + tar -xzvf geth-alltools-linux-amd64-1.13.4-3f907d6a.tar.gz + sudo cp geth-alltools-linux-amd64-1.13.4-3f907d6a/* /usr/local/bin - run: name: foundryup command: | @@ -1041,44 +1190,31 @@ jobs: - run: name: git submodules command: make submodules - - run: - name: Install and build - command: | - pnpm install:ci && pnpm build - attach_workspace: - at: /tmp/workspace - - run: - name: Load cannon pre-state - command: | - mkdir -p op-program/bin - cp /tmp/workspace/op-program/bin/prestate.json op-program/bin/prestate.json - cp /tmp/workspace/op-program/bin/meta.json op-program/bin/meta.json - cp /tmp/workspace/op-program/bin/prestate-proof.json op-program/bin/prestate-proof.json - - run: - name: Load devnet-allocs - command: | - mkdir -p .devnet - cp /tmp/workspace/.devnet/allocs-l1.json .devnet/allocs-l1.json - cp /tmp/workspace/.devnet/addresses.json .devnet/addresses.json - cp /tmp/workspace/packages/contracts-bedrock/deploy-config/devnetL1.json packages/contracts-bedrock/deploy-config/devnetL1.json - cp -r /tmp/workspace/packages/contracts-bedrock/deployments/devnetL1 packages/contracts-bedrock/deployments/devnetL1 + at: "." - run: name: Load and tag docker images command: | IMAGE_BASE_PREFIX="us-docker.pkg.dev/oplabs-tools-artifacts/images" # Load from previous docker-build job - docker load < "/tmp/workspace/op-stack-go.tar" - docker load < "/tmp/workspace/op-node.tar" - docker load < "/tmp/workspace/op-proposer.tar" - docker load < "/tmp/workspace/op-batcher.tar" + docker load < "./op-stack-go.tar" + docker load < "./op-node.tar" + docker load < "./op-proposer.tar" + docker load < "./op-batcher.tar" # rename to the tags that the docker-compose of the devnet expects docker tag "$IMAGE_BASE_PREFIX/op-stack-go:<>" "$IMAGE_BASE_PREFIX/op-stack-go:devnet" docker tag "$IMAGE_BASE_PREFIX/op-node:<>" "$IMAGE_BASE_PREFIX/op-node:devnet" docker tag "$IMAGE_BASE_PREFIX/op-proposer:<>" "$IMAGE_BASE_PREFIX/op-proposer:devnet" docker tag "$IMAGE_BASE_PREFIX/op-batcher:<>" "$IMAGE_BASE_PREFIX/op-batcher:devnet" + - run: + name: pnpm i + command: | + pnpm i && pnpm build - run: name: Bring up the stack - command: make devnet-up + command: | + # Specify like this to avoid a forced rebuild of the contracts + devnet L1 + PYTHONPATH=./bedrock-devnet python3 ./bedrock-devnet/main.py --monorepo-dir=. - run: name: Test the stack command: make devnet-test @@ -1107,12 +1243,23 @@ jobs: command: | docker logs ops-bedrock-op-proposer-1 || echo "No logs." when: on_fail + - run: + name: Dump op-challenger logs + command: | + docker logs ops-bedrock-op-challenger-1 || echo "No logs." + when: on_fail - run: name: Log deployment artifact command: | cat broadcast/Deploy.s.sol/900/run-latest.json || echo "No deployment file found" when: on_fail working_directory: packages/contracts-bedrock + - run: + name: Log devnet config + command: | + cat deploy-config/devnetL1.json || echo "No devnet config found" + when: on_fail + working_directory: packages/contracts-bedrock - run: name: Log artifacts directory command: | @@ -1183,27 +1330,25 @@ jobs: - run: command: go mod download name: Download Go module dependencies + - run: + name: "Go mod tidy" + command: make mod-tidy && git diff --exit-code + - run: + name: run Go linter + command: | + # Identify how many cores it defaults to + golangci-lint --help | grep concurrency + make lint-go + working_directory: . - save_cache: key: << parameters.key >>-{{ checksum "<< parameters.file >>" }} name: Save Go modules cache paths: - "/go/pkg/mod" - go-mod-tidy: - docker: - - image: <> - steps: - - checkout - - restore_cache: - name: Restore Go modules cache - key: gomod-{{ checksum "go.sum" }} - - run: - name: "Go mod tidy" - command: make mod-tidy && git diff --exit-code - op-service-rethdb-tests: docker: - - image: <> + - image: <> steps: - checkout - check-changed: @@ -1242,7 +1387,10 @@ jobs: bedrock-go-tests: # just a helper, that depends on all the actual test jobs docker: - - image: <> + # Use a smaller base image to avoid pulling the huge ci-builder + # image which is not needed for this job and sometimes misses + # the cache. + - image: cimg/base:2024.01 resource_class: medium steps: - run: echo Done @@ -1253,11 +1401,12 @@ jobs: steps: - checkout - run: - name: verify-goerli + name: verify-sepolia command: | - make verify-goerli + make verify-sepolia working_directory: op-program - - notify-failures-on-develop + - notify-failures-on-develop: + mentions: "@proofs-squad" op-program-compat: docker: @@ -1270,9 +1419,9 @@ jobs: - restore_cache: key: golang-build-cache - run: - name: compat-goerli + name: compat-sepolia command: | - make run-goerli-verify + make verify-compat working_directory: op-program check-generated-mocks-op-node: @@ -1330,7 +1479,8 @@ jobs: name: Checkout Submodule command: make submodules - check-changed: - patterns: contracts-bedrock/test/kontrol,contracts-bedrock/src/L1/OptimismPortal\.sol + no_go_deps: "true" + patterns: contracts-bedrock/test/kontrol,contracts-bedrock/src/L1/OptimismPortal\.sol,contracts-bedrock/src/L1/L1CrossDomainMessenger\.sol,contracts-bedrock/src/L1/L1ERC721Bridge\.sol,contracts-bedrock/src/L1/L1StandardBridge\.sol,contracts-bedrock/src/L1/ResourceMetering\.sol,contracts-bedrock/src/universal/StandardBridge\.sol,contracts-bedrock/src/universal/ERC721Bridge\.sol,contracts-bedrock/src/universal/CrossDomainMessenger\.sol - setup_remote_docker: docker_layer_caching: true - run: @@ -1338,15 +1488,25 @@ jobs: command: pnpm test:kontrol working_directory: ./packages/contracts-bedrock - store_artifacts: - path: ./packages/contracts-bedrock/kontrol-results_latest.tar.gz + path: ./packages/contracts-bedrock/test/kontrol/logs/kontrol-results_latest.tar.gz + - store_test_results: + path: ./packages/contracts-bedrock + - notify-failures-on-develop workflows: main: when: - not: - equal: [ scheduled_pipeline, << pipeline.trigger_source >> ] + and: + - or: + # Trigger on new commits + - equal: [ webhook, << pipeline.trigger_source >> ] + # Trigger on manual triggers if explicitly requested + - equal: [ true, << pipeline.parameters.main_dispatch >> ] + - not: + equal: [ scheduled_pipeline, << pipeline.trigger_source >> ] jobs: - - pnpm-monorepo + - pnpm-monorepo: + name: pnpm-monorepo - js-lint-test: name: common-ts-tests coverage_flag: common-ts-tests @@ -1366,7 +1526,6 @@ workflows: - contracts-bedrock-checks: requires: - pnpm-monorepo - - contracts-bedrock-slither - contracts-bedrock-validate-spaces: requires: - pnpm-monorepo @@ -1406,123 +1565,136 @@ workflows: name: proxyd-tests binary_name: proxyd working_directory: proxyd - - indexer-tests - - l1-geth-version-check + - indexer-tests: + name: indexer-tests<< matrix.fpac >> + matrix: + parameters: + fpac: ["", "-fault-proofs"] - semgrep-scan - go-mod-download - - go-mod-tidy: - requires: ["go-mod-download"] - - devnet-allocs: # devnet-allocs uses op-node genesis sub-command - requires: - - "go-mod-tidy" - - l1-geth-version-check - - go-lint: # we combine most of the go-lint work for two reasons: (1) warm up the Go build cache, (2) reduce sum of lint time - name: op-stack-go-lint - requires: [ "go-mod-tidy" ] - fuzz-golang: name: op-challenger-fuzz package_name: op-challenger on_changes: op-challenger - requires: ["op-stack-go-lint"] + requires: ["go-mod-download"] - fuzz-golang: name: op-node-fuzz package_name: op-node on_changes: op-node - requires: ["op-stack-go-lint"] + requires: ["go-mod-download"] - fuzz-golang: name: op-service-fuzz package_name: op-service on_changes: op-service - requires: ["op-stack-go-lint"] + requires: ["go-mod-download"] - fuzz-golang: name: op-chain-ops-fuzz package_name: op-chain-ops on_changes: op-chain-ops,op-bindings - requires: ["op-stack-go-lint"] + requires: ["go-mod-download"] - fuzz-golang: name: cannon-fuzz package_name: cannon on_changes: cannon,packages/contracts-bedrock/src/cannon - requires: ["op-stack-go-lint"] + requires: ["go-mod-download"] - go-test: name: op-heartbeat-tests module: op-heartbeat - requires: [ "op-stack-go-lint" ] + requires: [ "go-mod-download" ] - go-test: name: op-batcher-tests module: op-batcher - requires: ["op-stack-go-lint"] + requires: ["go-mod-download"] - go-test: name: op-bindings-tests module: op-bindings - requires: ["op-stack-go-lint"] + requires: ["go-mod-download"] - go-test: name: op-chain-ops-tests module: op-chain-ops - requires: ["op-stack-go-lint"] + requires: ["go-mod-download"] - go-test: name: op-node-tests module: op-node - requires: ["op-stack-go-lint"] + requires: ["go-mod-download"] - go-test: name: op-proposer-tests module: op-proposer - requires: ["op-stack-go-lint"] + requires: ["go-mod-download"] - go-test: name: op-challenger-tests module: op-challenger - requires: ["op-stack-go-lint"] + requires: ["go-mod-download"] + - go-test: + name: op-dispute-mon-tests + module: op-dispute-mon + requires: ["go-mod-download"] - go-test: name: op-conductor-tests module: op-conductor - requires: ["op-stack-go-lint"] + requires: ["go-mod-download"] - go-test: name: op-program-tests module: op-program - requires: ["op-stack-go-lint"] + requires: ["go-mod-download"] - go-test: name: op-service-tests module: op-service - requires: ["op-stack-go-lint"] - - op-service-rethdb-tests: + requires: ["go-mod-download"] + - go-e2e-test: + name: op-e2e-HTTP-tests<< matrix.fpac >> + matrix: + parameters: + fpac: ["", "-fault-proofs"] + module: op-e2e + target: test-http + parallelism: 4 requires: - - op-stack-go-lint + - go-mod-download + - pnpm-monorepo - go-e2e-test: - name: op-e2e-WS-tests + name: op-e2e-action-tests<< matrix.fpac >> + matrix: + parameters: + fpac: ["", "-fault-proofs", "-plasma"] module: op-e2e - target: test-ws + target: test-actions + parallelism: 1 requires: - - op-stack-go-lint - - devnet-allocs + - go-mod-download + - pnpm-monorepo - go-e2e-test: - name: op-e2e-HTTP-tests + name: op-e2e-fault-proof-tests module: op-e2e - target: test-http - cannon_enabled: false + target: test-fault-proofs + parallelism: 4 requires: - - op-stack-go-lint - - devnet-allocs + - pnpm-monorepo + - cannon-prestate - go-e2e-test: - name: op-e2e-ext-geth-tests + name: op-e2e-ext-geth-tests<< matrix.fpac >> + matrix: + parameters: + fpac: ["", "-fault-proofs"] module: op-e2e target: test-external-geth - cannon_enabled: false requires: - - op-stack-go-lint - - devnet-allocs - - l1-geth-version-check + - go-mod-download + - pnpm-monorepo + - op-service-rethdb-tests: + requires: + - go-mod-download - op-program-compat: requires: - op-program-tests - bedrock-go-tests: requires: - go-mod-download - - go-mod-tidy - cannon-build-test-vectors - cannon-go-lint-and-test - check-generated-mocks-op-node - check-generated-mocks-op-service - - op-stack-go-lint + - go-mod-download - op-batcher-tests - op-bindings-tests - op-chain-ops-tests @@ -1530,14 +1702,16 @@ workflows: - op-node-tests - op-proposer-tests - op-challenger-tests + - op-dispute-mon-tests - op-conductor-tests - op-program-tests - op-program-compat - op-service-tests - - op-e2e-WS-tests + - op-service-rethdb-tests - op-e2e-HTTP-tests + - op-e2e-fault-proof-tests + - op-e2e-action-tests - op-e2e-ext-geth-tests - - op-service-rethdb-tests - docker-build: # just to warm up the cache (other jobs run in parallel) name: op-stack-go-docker-build docker_name: op-stack-go @@ -1573,6 +1747,12 @@ workflows: docker_tags: <>,<> requires: ['op-stack-go-docker-build'] save_image_tag: <> # for devnet later + - docker-build: + name: op-dispute-mon-docker-build + docker_name: op-dispute-mon + docker_tags: <>,<> + requires: ['op-stack-go-docker-build'] + save_image_tag: <> # for devnet later - docker-build: name: op-conductor-docker-build docker_name: op-conductor @@ -1586,14 +1766,17 @@ workflows: requires: ['op-stack-go-docker-build'] save_image_tag: <> # for devnet later - cannon-prestate: - requires: ["op-stack-go-lint"] + requires: + - go-mod-download - devnet: + matrix: + parameters: + fpac: ["legacy", "fault-proofs"] requires: - - op-node-docker-build + - pnpm-monorepo - op-batcher-docker-build - op-proposer-docker-build - - l1-geth-version-check - - devnet-allocs + - op-node-docker-build - cannon-prestate - docker-build: name: indexer-docker-build @@ -1607,7 +1790,13 @@ workflows: - check-generated-mocks-op-service - cannon-go-lint-and-test - cannon-build-test-vectors - - kontrol-tests + - shellcheck/check: + name: shell-check + # We don't need the `exclude` key as the orb detects the `.shellcheckrc` + dir: . + ignore-dirs: + ./packages/contracts-bedrock/lib + release: when: not: @@ -1617,14 +1806,14 @@ workflows: type: approval filters: tags: - only: /^(proxyd|chain-mon|indexer|ci-builder|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)\/v.*/ + only: /^(proxyd|chain-mon|indexer|ci-builder(-rust)?|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)\/v.*/ branches: ignore: /.*/ - docker-build: # just to warm up the cache (other jobs run in parallel) name: op-stack-go-docker-build-release filters: tags: - only: /^(proxyd|chain-mon|indexer|ci-builder|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)\/v.*/ + only: /^(proxyd|chain-mon|indexer|ci-builder(-rust)?|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)\/v.*/ branches: ignore: /.*/ docker_name: op-stack-go @@ -1707,6 +1896,21 @@ workflows: release: true context: - oplabs-gcr-release + - docker-build: + name: op-dispute-mon-docker-release + filters: + tags: + only: /^op-dispute-mon\/v.*/ + branches: + ignore: /.*/ + docker_name: op-dispute-mon + docker_tags: <> + requires: ['op-stack-go-docker-build-release'] + platforms: "linux/amd64,linux/arm64" + publish: true + release: true + context: + - oplabs-gcr-release - docker-build: name: op-conductor-docker-release filters: @@ -1799,6 +2003,22 @@ workflows: - oplabs-gcr requires: - hold + - docker-build: + name: ci-builder-rust-docker-release + filters: + tags: + only: /^ci-builder-rust\/v.*/ + branches: + ignore: /.*/ + docker_name: ci-builder-rust + docker_tags: <>,latest + publish: true + release: true + resource_class: xlarge + context: + - oplabs-gcr + requires: + - hold - docker-build: name: ufm-metamask-docker-release filters: @@ -1833,6 +2053,49 @@ workflows: - slack - oplabs-fpp-nodes + develop-fault-proofs: + when: + and: + - or: + - equal: [ "develop", <> ] + - equal: [ true, <> ] + - not: + equal: [ scheduled_pipeline, << pipeline.trigger_source >> ] + jobs: + - go-mod-download + - cannon-prestate: + requires: + - go-mod-download + - pnpm-monorepo: + name: pnpm-monorepo + requires: + - go-mod-download + - go-e2e-test: + name: op-e2e-cannon-tests + module: op-e2e + target: test-cannon + parallelism: 4 + notify: true + mentions: "@proofs-squad" + requires: + - pnpm-monorepo + - cannon-prestate + context: + - slack + + develop-kontrol-tests: + when: + and: + - or: + - equal: [ "develop", <> ] + - equal: [ true, <> ] + - not: + equal: [ scheduled_pipeline, << pipeline.trigger_source >> ] + jobs: + - kontrol-tests: + context: + - slack + scheduled-docker-publish: when: equal: [ build_hourly, <> ] @@ -1895,6 +2158,16 @@ workflows: context: - oplabs-gcr - slack + - docker-build: + name: op-dispute-mon-docker-publish + docker_name: op-dispute-mon + docker_tags: <>,<> + requires: [ 'op-stack-go-docker-build-publish' ] + platforms: "linux/amd64,linux/arm64" + publish: true + context: + - oplabs-gcr + - slack - docker-build: name: op-conductor-docker-publish docker_name: op-conductor diff --git a/.eslintrc.js b/.eslintrc.js index af5b30881efa..0152c354b87f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -113,7 +113,6 @@ module.exports = { indent: 'off', 'jsdoc/check-alignment': 'error', 'jsdoc/check-indentation': 'error', - 'jsdoc/newline-after-description': 'error', 'linebreak-style': 'off', 'max-classes-per-file': 'off', 'max-len': 'off', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f1bf6f7c8eb7..9bfa44258161 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -12,6 +12,7 @@ /op-bootnode @ethereum-optimism/go-reviewers /op-chain-ops @ethereum-optimism/go-reviewers /op-challenger @ethereum-optimism/go-reviewers +/op-dispute-mon @ethereum-optimism/go-reviewers /op-e2e @ethereum-optimism/go-reviewers /op-heartbeat @ethereum-optimism/go-reviewers /op-node @ethereum-optimism/go-reviewers @@ -22,12 +23,13 @@ /op-service @ethereum-optimism/go-reviewers /op-wheel @ethereum-optimism/go-reviewers /ops-bedrock @ethereum-optimism/go-reviewers +/op-conductor @0x00101010 @zhwrd @mslipper # Ops -/.circleci @ethereum-optimism/infra-reviewers -/.github @ethereum-optimism/infra-reviewers -/ops @ethereum-optimism/infra-reviewers -/docker-bake.hcl @ethereum-optimism/infra-reviewers +/.circleci @ethereum-optimism/monorepo-ops-reviewers +/.github @ethereum-optimism/monorepo-ops-reviewers +/ops @ethereum-optimism/monorepo-ops-reviewers +/docker-bake.hcl @ethereum-optimism/monorepo-ops-reviewers # Misc /proxyd @ethereum-optimism/infra-reviewers diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index b695d65254f3..f45efa027414 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -7,7 +7,7 @@ runs: uses: pnpm/action-setup@v2 with: version: 8.6.5 - - name: Setup node 16.x + - name: Setup node uses: actions/setup-node@v3 with: node-version-file: .nvmrc diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a7442b6bd044..e2c739a570d5 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,36 +1,54 @@ version: 2 updates: - - package-ecosystem: docker + - package-ecosystem: "docker" directory: "/ops-bedrock" schedule: - interval: daily + interval: "daily" + day: "tuesday" + time: "14:30" + timezone: "America/New_York" open-pull-requests-limit: 10 + commit-message: + prefix: "dependabot(docker): " labels: - - M-dependabot + - "M-dependabot" - - package-ecosystem: github-actions + - package-ecosystem: "github-actions" directory: "/" schedule: - interval: daily + interval: "weekly" + day: "tuesday" + time: "14:30" + timezone: "America/New_York" open-pull-requests-limit: 10 + commit-message: + prefix: "dependabot(actions): " labels: - - M-dependabot + - "M-dependabot" - - package-ecosystem: npm + - package-ecosystem: "npm" directory: "/" schedule: - interval: daily - time: "16:30" + interval: "weekly" + day: "tuesday" + time: "14:30" timezone: "America/New_York" open-pull-requests-limit: 10 - versioning-strategy: auto + versioning-strategy: "auto" + commit-message: + prefix: "dependabot(npm): " labels: - - M-dependabot + - "M-dependabot" - - package-ecosystem: gomod + - package-ecosystem: "gomod" directory: "/" schedule: - interval: daily + interval: "daily" + day: "tuesday" + time: "14:30" + timezone: "America/New_York" open-pull-requests-limit: 10 + commit-message: + prefix: "dependabot(gomod): " labels: - - M-dependabot + - "M-dependabot" diff --git a/.github/workflows/release-snapshot.yml b/.github/workflows/release-snapshot.yml index e6811be3f781..372c970e2b99 100644 --- a/.github/workflows/release-snapshot.yml +++ b/.github/workflows/release-snapshot.yml @@ -29,6 +29,11 @@ jobs: env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Verify NPM Token is valid + run: npm whoami + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Publish snapshots uses: seek-oss/changesets-snapshot@v0 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 963d32e58925..469db26b5d3a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,11 +41,23 @@ jobs: - name: Setup uses: ./.github/actions/setup + - name: Check if NPM_TOKEN is set + id: check_token + run: | + if [ -z "${{ secrets.NPM_TOKEN }}" ]; then + echo "NPM_TOKEN is not set. Is it set it in your repository secrets?" + exit 1 + fi + shell: bash + - name: Set deployment token run: npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}" env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Verify NPM Token is valid + run: npm whoami + # Makes a pr to publish the changesets that when # merged will publish to npm # see https://github.com/changesets/action diff --git a/.github/workflows/slither.yml b/.github/workflows/slither.yml new file mode 100644 index 000000000000..f8935a75070a --- /dev/null +++ b/.github/workflows/slither.yml @@ -0,0 +1,39 @@ +name: 'Slither Analysis' + +on: + workflow_dispatch: + pull_request: + push: + branches: + - develop + +jobs: + slither-analyze: + runs-on: ubuntu-latest + container: + image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:v0.43.0 + steps: + - uses: actions/checkout@v4 + + # Workaround to prevent slither-action from trying to install JS deps. + # Without this step, it detects the `package.json`, and since there is no + # lockfile it defaults `npm install` which fails due to the preinstall + # script to enforce pnpm. https://github.com/crytic/slither-action/issues/44#issuecomment-1338183656 + - name: Remove package.json + run: rm packages/contracts-bedrock/package.json + + - name: Run Slither + uses: crytic/slither-action@v0.3.1 + id: slither + with: + target: packages/contracts-bedrock + slither-config: packages/contracts-bedrock/slither.config.json + fail-on: config + sarif: results.sarif + slither-args: --triage-database packages/contracts-bedrock/slither.db.json + + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@v3 + if: always() + with: + sarif_file: ${{ steps.slither.outputs.sarif }} diff --git a/.github/workflows/tag-service.yml b/.github/workflows/tag-service.yml index 683501bf1d78..35e2c6d8c805 100644 --- a/.github/workflows/tag-service.yml +++ b/.github/workflows/tag-service.yml @@ -19,6 +19,7 @@ on: type: choice options: - ci-builder + - ci-builder-rust - indexer - op-heartbeat - chain-mon @@ -26,9 +27,12 @@ on: - op-batcher - op-proposer - op-challenger + - op-program + - op-dispute-mon - op-ufm - proxyd - ufm-metamask + - op-contracts prerelease: description: Increment major/minor/patch as prerelease? required: false diff --git a/.go-version b/.go-version new file mode 100644 index 000000000000..d2ab029d32c6 --- /dev/null +++ b/.go-version @@ -0,0 +1 @@ +1.21 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bb547bb64868..c854c6eb91eb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -164,7 +164,7 @@ docker compose logs --follow Before running tests: **follow the above instructions to get everything built.** -#### Running unit tests +#### Running unit tests (typescript) Run unit tests for all packages in parallel via: @@ -179,6 +179,16 @@ cd packages/package-to-test pnpm test ``` +#### Running unit tests (Go) + +Change directory to the package you want to run tests for. Then: +```shell +go test ./... +``` + +#### Running e2e tests (Go) +See [this document](./op-e2e/README.md) + #### Running contract static analysis We perform static analysis with [`slither`](https://github.com/crytic/slither). diff --git a/Makefile b/Makefile index a12a8cdb4089..2573851088b2 100644 --- a/Makefile +++ b/Makefile @@ -82,6 +82,10 @@ op-challenger: make -C ./op-challenger op-challenger .PHONY: op-challenger +op-dispute-mon: + make -C ./op-dispute-mon op-dispute-mon +.PHONY: op-dispute-mon + op-program: make -C ./op-program op-program .PHONY: op-program @@ -107,6 +111,7 @@ mod-tidy: # # See https://proxy.golang.org/ for more info. export GOPRIVATE="github.com/ethereum-optimism" && go mod tidy + make -C ./op-ufm mod-tidy .PHONY: mod-tidy clean: @@ -132,9 +137,6 @@ devnet-up: pre-devnet PYTHONPATH=./bedrock-devnet $(PYTHON) ./bedrock-devnet/main.py --monorepo-dir=. .PHONY: devnet-up -# alias for devnet-up -devnet-up-deploy: devnet-up - devnet-test: pre-devnet PYTHONPATH=./bedrock-devnet $(PYTHON) ./bedrock-devnet/main.py --monorepo-dir=. --test .PHONY: devnet-test diff --git a/README.md b/README.md index ca471f52e4ab..9c189f9662c2 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,25 @@
+ + +**Table of Contents** + +- [What is Optimism?](#what-is-optimism) +- [Documentation](#documentation) +- [Specification](#specification) +- [Community](#community) +- [Contributing](#contributing) +- [Security Policy and Vulnerability Reporting](#security-policy-and-vulnerability-reporting) +- [Directory Structure](#directory-structure) +- [Development and Release Process](#development-and-release-process) + - [Overview](#overview) + - [Production Releases](#production-releases) + - [Development branch](#development-branch) +- [License](#license) + + + ## What is Optimism? [Optimism](https://www.optimism.io/) is a project dedicated to scaling Ethereum's technology and expanding its ability to coordinate people from across the world to build effective decentralized economies and governance systems. The [Optimism Collective](https://app.optimism.io/announcement) builds open-source software for running L2 blockchains and aims to address key governance and economic challenges in the wider cryptocurrency ecosystem. Optimism operates on the principle of **impact=profit**, the idea that individuals who positively impact the Collective should be proportionally rewarded with profit. **Change the incentives and you change the world.** @@ -16,7 +35,7 @@ In this repository, you'll find numerous core components of the OP Stack, the de ## Documentation - If you want to build on top of OP Mainnet, refer to the [Optimism Documentation](https://docs.optimism.io) -- If you want to build your own OP Stack based blockchain, refer to the [OP Stack Guide](https://docs.optimism.io/stack/getting-started) +- If you want to build your own OP Stack based blockchain, refer to the [OP Stack Guide](https://docs.optimism.io/stack/getting-started), and make sure to understand this repository's [Development and Release Process](#development-and-release-process) ## Specification @@ -31,7 +50,7 @@ Governance discussion can also be found on the [Optimism Governance Forum](https Read through [CONTRIBUTING.md](./CONTRIBUTING.md) for a general overview of the contributing process for this repository. Use the [Developer Quick Start](./CONTRIBUTING.md#development-quick-start) to get your development environment set up to start working on the Optimism Monorepo. -Then check out the list of [Good First Issues](https://github.com/ethereum-optimism/optimism/labels/D-good-first-issue) to find something fun to work on! +Then check out the list of [Good First Issues](https://github.com/ethereum-optimism/optimism/issues?q=is:open+is:issue+label:D-good-first-issue) to find something fun to work on! Typo fixes are welcome; however, please create a single commit with all of the typo fixes & batch as many fixes together in a PR as possible. Spammy PRs will be closed. ## Security Policy and Vulnerability Reporting @@ -44,8 +63,8 @@ The Optimism Immunefi program offers up to $2,000,042 for in-scope critical vuln
 ├── docs: A collection of documents including audits and post-mortems
-├── op-bindings: Go bindings for Bedrock smart contracts.
 ├── op-batcher: L2-Batch Submitter, submits bundles of batches to L1
+├── op-bindings: Go bindings for Bedrock smart contracts.
 ├── op-bootnode: Standalone op-node discovery bootnode
 ├── op-chain-ops: State surgery utilities
 ├── op-challenger: Dispute game challenge agent
@@ -56,83 +75,78 @@ The Optimism Immunefi program offers up to $2,000,042 for in-scope critical vuln
 ├── op-program: Fault proof program
 ├── op-proposer: L2-Output Submitter, submits proposals to L1
 ├── op-service: Common codebase utilities
+├── op-ufm: Simulations for monitoring end-to-end transaction latency
 ├── op-wheel: Database utilities
+├── ops: Various operational packages
 ├── ops-bedrock: Bedrock devnet work
 ├── packages
 │   ├── chain-mon: Chain monitoring services
 │   ├── common-ts: Common tools for building apps in TypeScript
-│   ├── contracts-ts: ABI and Address constants
 │   ├── contracts-bedrock: Bedrock smart contracts
+│   ├── contracts-ts: ABI and Address constants
 │   ├── core-utils: Low-level utilities that make building Optimism easier
-│   └── sdk: provides a set of tools for interacting with Optimism
-└── proxyd: Configurable RPC request router and proxy
+│   ├── fee-estimation: Tools for estimating gas on OP chains
+│   ├── sdk: provides a set of tools for interacting with Optimism
+│   └── web3js-plugin: Adds functions to estimate L1 and L2 gas
+├── proxyd: Configurable RPC request router and proxy
+├── specs: Specs of the rollup starting at the Bedrock upgrade
+└── ufm-test-services: Runs a set of tasks to generate metrics
 
-## Branching Model - -### Active Branches - -| Branch | Status | -| --------------- | -------------------------------------------------------------------------------- | -| [master](https://github.com/ethereum-optimism/optimism/tree/master/) | Accepts PRs from `develop` when intending to deploy to production. | -| [develop](https://github.com/ethereum-optimism/optimism/tree/develop/) | Accepts PRs that are compatible with `master` OR from `release/X.X.X` branches. | -| release/X.X.X | Accepts PRs for all changes, particularly those not backwards compatible with `develop` and `master`. | +## Development and Release Process ### Overview -This repository generally follows [this Git branching model](https://nvie.com/posts/a-successful-git-branching-model/). -Please read the linked post if you're planning to make frequent PRs into this repository. - -### Production branch - -The production branch is `master`. -The `master` branch contains the code for latest "stable" releases. -Updates from `master` **always** come from the `develop` branch. - -### Development branch - -The primary development branch is [`develop`](https://github.com/ethereum-optimism/optimism/tree/develop/). -`develop` contains the most up-to-date software that remains backwards compatible with the latest experimental [network deployments](https://community.optimism.io/docs/useful-tools/networks/). -If you're making a backwards compatible change, please direct your pull request towards `develop`. +Please read this section if you're planning to fork this repository, or make frequent PRs into this repository. -**Changes to contracts within `packages/contracts-bedrock/src` are usually NOT considered backwards compatible and SHOULD be made against a release candidate branch**. -Some exceptions to this rule exist for cases in which we absolutely must deploy some new contract after a release candidate branch has already been fully deployed. -If you're changing or adding a contract and you're unsure about which branch to make a PR into, default to using the latest release candidate branch. -See below for info about release candidate branches. +### Production Releases -### Release candidate branches +Production releases are always tags, versioned as `/v`. +For example, an `op-node` release might be versioned as `op-node/v1.1.2`, and smart contract releases might be versioned as `op-contracts/v1.0.0`. +Release candidates are versioned in the format `op-node/v1.1.2-rc.1`. +We always start with `rc.1` rather than `rc`. -Branches marked `release/X.X.X` are **release candidate branches**. -Changes that are not backwards compatible and all changes to contracts within `packages/contracts-bedrock/src` MUST be directed towards a release candidate branch. -Release candidates are merged into `develop` and then into `master` once they've been fully deployed. -We may sometimes have more than one active `release/X.X.X` branch if we're in the middle of a deployment. -See table in the **Active Branches** section above to find the right branch to target. +For contract releases, refer to the GitHub release notes for a given release, which will list the specific contracts being released—not all contracts are considered production ready within a release, and many are under active development. -## Releases +Tags of the form `v`, such as `v1.1.4`, indicate releases of all Go code only, and **DO NOT** include smart contracts. +This naming scheme is required by Golang. +In the above list, this means these `v`. You may need to set `PYTHONPATH` to this directory if you are invoking the script from somewhere other than `bedrock-devnet`. +The easiest way to invoke this script is to run `make devnet-up` from the root of this repository. Otherwise, to use this script run `python3 main.py --monorepo-dir=`. You may need to set `PYTHONPATH` to this directory if you are invoking the script from somewhere other than `bedrock-devnet`. diff --git a/bedrock-devnet/devnet/__init__.py b/bedrock-devnet/devnet/__init__.py index 3408c707dbc3..5b6502942ebf 100644 --- a/bedrock-devnet/devnet/__init__.py +++ b/bedrock-devnet/devnet/__init__.py @@ -8,6 +8,7 @@ import datetime import time import shutil +import sys import http.client import gzip from multiprocessing import Process, Queue @@ -26,20 +27,49 @@ log = logging.getLogger() +# Global environment variables +DEVNET_NO_BUILD = os.getenv('DEVNET_NO_BUILD') == "true" +DEVNET_FPAC = os.getenv('DEVNET_FPAC') == "true" +DEVNET_PLASMA = os.getenv('DEVNET_PLASMA') == "true" + class Bunch: def __init__(self, **kwds): self.__dict__.update(kwds) +# class ChildProcess: +# def __init__(self, func, *args): +# self.errq = Queue() +# self.process = Process(target=self._func, args=(func, args)) + +# def _func(self, func, args): +# try: +# func(*args) +# except Exception as e: +# self.errq.put(e) + +# def start(self): +# self.process.start() + +# def join(self): +# self.process.join() + +# def get_error(self): +# return self.errq.get() if not self.errq.empty() else None + class ChildProcess: def __init__(self, func, *args): self.errq = Queue() self.process = Process(target=self._func, args=(func, args)) def _func(self, func, args): + # Redirect stdout and stderr to the parent process's stdout and stderr + os.dup2(sys.__stdout__.fileno(), sys.stdout.fileno()) + os.dup2(sys.__stderr__.fileno(), sys.stderr.fileno()) + try: func(*args) except Exception as e: - self.errq.put(str(e)) + self.errq.put(e) def start(self): self.process.start() @@ -58,6 +88,7 @@ def main(): devnet_dir = pjoin(monorepo_dir, '.devnet') contracts_bedrock_dir = pjoin(monorepo_dir, 'packages', 'contracts-bedrock') deployment_dir = pjoin(contracts_bedrock_dir, 'deployments', 'devnetL1') + forge_dump_path = pjoin(contracts_bedrock_dir, 'Deploy-900.json') op_node_dir = pjoin(args.monorepo_dir, 'op-node') ops_bedrock_dir = pjoin(monorepo_dir, 'ops-bedrock') deploy_config_dir = pjoin(contracts_bedrock_dir, 'deploy-config') @@ -71,6 +102,7 @@ def main(): devnet_dir=devnet_dir, contracts_bedrock_dir=contracts_bedrock_dir, deployment_dir=deployment_dir, + forge_dump_path=forge_dump_path, l1_deployments_path=pjoin(deployment_dir, '.deploy'), deploy_config_dir=deploy_config_dir, devnet_config_path=devnet_config_path, @@ -102,7 +134,7 @@ def main(): git_date = subprocess.run(['git', 'show', '-s', "--format=%ct"], capture_output=True, text=True).stdout.strip() # CI loads the images from workspace, and does not otherwise know the images are good as-is - if os.getenv('DEVNET_NO_BUILD') == "true": + if DEVNET_NO_BUILD: log.info('Skipping docker images build') else: log.info(f'Building docker images for git commit {git_commit} ({git_date})') @@ -117,67 +149,31 @@ def main(): log.info('Devnet starting') devnet_deploy(paths) - -def deploy_contracts(paths): - wait_up(8545) - wait_for_rpc_server('127.0.0.1:8545') - res = eth_accounts('127.0.0.1:8545') - - response = json.loads(res) - account = response['result'][0] - log.info(f'Deploying with {account}') - - # send some ether to the create2 deployer account - run_command([ - 'cast', 'send', '--from', account, - '--rpc-url', 'http://127.0.0.1:8545', - '--unlocked', '--value', '5ether', '0x3fAB184622Dc19b6109349B94811493BF2a45362' - ], env={}, cwd=paths.contracts_bedrock_dir) - - # deploy the create2 deployer - run_command([ - 'cast', 'publish', '--rpc-url', 'http://127.0.0.1:8545', - '0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222' - ], env={}, cwd=paths.contracts_bedrock_dir) - - fqn = 'scripts/Deploy.s.sol:Deploy' - run_command([ - 'forge', 'script', fqn, '--sender', account, - '--rpc-url', 'http://127.0.0.1:8545', '--broadcast', - '--unlocked', '--with-gas-price', '100000000000' - ], env={}, cwd=paths.contracts_bedrock_dir) - - shutil.copy(paths.l1_deployments_path, paths.addresses_json_path) - def init_devnet_l1_deploy_config(paths, update_timestamp=False): deploy_config = read_json(paths.devnet_config_template_path) if update_timestamp: deploy_config['l1GenesisBlockTimestamp'] = '{:#x}'.format(int(time.time())) + if DEVNET_FPAC: + deploy_config['useFaultProofs'] = True + deploy_config['faultGameMaxDuration'] = 10 + if DEVNET_PLASMA: + deploy_config['usePlasma'] = True write_json(paths.devnet_config_path, deploy_config) def devnet_l1_genesis(paths): log.info('Generating L1 genesis state') init_devnet_l1_deploy_config(paths) - geth = subprocess.Popen([ - 'anvil', '-a', '10', '--port', '8545', '--chain-id', '1337', '--disable-block-gas-limit', - '--gas-price', '0', '--base-fee', '1', '--block-time', '1' - ]) - - try: - forge = ChildProcess(deploy_contracts, paths) - forge.start() - forge.join() - err = forge.get_error() - if err: - raise Exception(f"Exception occurred in child process: {err}") + fqn = 'scripts/Deploy.s.sol:Deploy' + run_command([ + 'forge', 'script', '--chain-id', '900', fqn, "--sig", "runWithStateDump()" + ], env={}, cwd=paths.contracts_bedrock_dir) - res = anvil_dumpState('127.0.0.1:8545') - allocs = convert_anvil_dump(res) - write_json(paths.allocs_path, allocs) - finally: - geth.terminate() + forge_dump = read_json(paths.forge_dump_path) + write_json(paths.allocs_path, { "accounts": forge_dump }) + os.remove(paths.forge_dump_path) + shutil.copy(paths.l1_deployments_path, paths.addresses_json_path) # Bring up the devnet where the contracts are deployed to L1 def devnet_deploy(paths): @@ -185,7 +181,11 @@ def devnet_deploy(paths): log.info('L1 genesis already generated.') else: log.info('Generating L1 genesis.') - if os.path.exists(paths.allocs_path) == False: + if os.path.exists(paths.allocs_path) == False or DEVNET_FPAC == True: + # If this is the FPAC devnet then we need to generate the allocs + # file here always. This is because CI will run devnet-allocs + # without DEVNET_FPAC=true which means the allocs will be wrong. + # Re-running this step means the allocs will be correct. devnet_l1_genesis(paths) # It's odd that we want to regenerate the devnetL1.json file with @@ -225,77 +225,50 @@ def devnet_deploy(paths): rollup_config = read_json(paths.rollup_config_path) addresses = read_json(paths.addresses_json_path) + # Start the L2. log.info('Bringing up L2.') run_command(['docker', 'compose', 'up', '-d', 'l2'], cwd=paths.ops_bedrock_dir, env={ 'PWD': paths.ops_bedrock_dir }) + + # Wait for the L2 to be available. wait_up(9545) wait_for_rpc_server('127.0.0.1:9545') + # Print out the addresses being used for easier debugging. l2_output_oracle = addresses['L2OutputOracleProxy'] - log.info(f'Using L2OutputOracle {l2_output_oracle}') + dispute_game_factory = addresses['DisputeGameFactoryProxy'] batch_inbox_address = rollup_config['batch_inbox_address'] + log.info(f'Using L2OutputOracle {l2_output_oracle}') + log.info(f'Using DisputeGameFactory {dispute_game_factory}') log.info(f'Using batch inbox {batch_inbox_address}') - log.info('Bringing up `op-node`, `op-proposer` and `op-batcher`.') - run_command(['docker', 'compose', 'up', '-d', 'op-node', 'op-proposer', 'op-batcher'], cwd=paths.ops_bedrock_dir, env={ + # Set up the base docker environment. + docker_env = { 'PWD': paths.ops_bedrock_dir, - 'L2OO_ADDRESS': l2_output_oracle, 'SEQUENCER_BATCH_INBOX_ADDRESS': batch_inbox_address - }) - - log.info('Bringing up `artifact-server`') - run_command(['docker', 'compose', 'up', '-d', 'artifact-server'], cwd=paths.ops_bedrock_dir, env={ - 'PWD': paths.ops_bedrock_dir - }) - - log.info('Devnet ready.') - + } + + # Selectively set the L2OO_ADDRESS or DGF_ADDRESS if using FPAC. + # Must be done selectively because op-proposer throws if both are set. + if DEVNET_FPAC: + docker_env['DGF_ADDRESS'] = dispute_game_factory + docker_env['DG_TYPE'] = '0' + docker_env['PROPOSAL_INTERVAL'] = '10s' + else: + docker_env['L2OO_ADDRESS'] = l2_output_oracle -def eth_accounts(url): - log.info(f'Fetch eth_accounts {url}') - conn = http.client.HTTPConnection(url) - headers = {'Content-type': 'application/json'} - body = '{"id":2, "jsonrpc":"2.0", "method": "eth_accounts", "params":[]}' - conn.request('POST', '/', body, headers) - response = conn.getresponse() - data = response.read().decode() - conn.close() - return data + # Bring up the rest of the services. + log.info('Bringing up `op-node`, `op-proposer` and `op-batcher`.') + run_command(['docker', 'compose', 'up', '-d', 'op-node', 'op-proposer', 'op-batcher', 'artifact-server'], cwd=paths.ops_bedrock_dir, env=docker_env) + # Optionally bring up op-challenger. + if DEVNET_FPAC: + log.info('Bringing up `op-challenger`.') + run_command(['docker', 'compose', 'up', '-d', 'op-challenger'], cwd=paths.ops_bedrock_dir, env=docker_env) -def anvil_dumpState(url): - log.info(f'Fetch debug_dumpBlock {url}') - conn = http.client.HTTPConnection(url) - headers = {'Content-type': 'application/json'} - body = '{"id":3, "jsonrpc":"2.0", "method": "anvil_dumpState", "params":[]}' - conn.request('POST', '/', body, headers) - data = conn.getresponse().read() - # Anvil returns a JSON-RPC response with a hex-encoded "result" field - result = json.loads(data.decode('utf-8'))['result'] - result_bytes = bytes.fromhex(result[2:]) - uncompressed = gzip.decompress(result_bytes).decode() - return json.loads(uncompressed) - -def convert_anvil_dump(dump): - accounts = dump['accounts'] - - for account in accounts.values(): - bal = account['balance'] - account['balance'] = str(int(bal, 16)) - - if 'storage' in account: - storage = account['storage'] - storage_keys = list(storage.keys()) - for key in storage_keys: - value = storage[key] - del storage[key] - storage[pad_hex(key)] = pad_hex(value) - - return dump - -def pad_hex(input): - return '0x' + input.replace('0x', '').zfill(64) + # Fin. + log.info('Devnet ready.') def wait_for_rpc_server(url): log.info(f'Waiting for RPC server at {url}') @@ -374,21 +347,53 @@ def run_command_preset(command: CommandPreset): proc.kill() return proc.returncode - -def run_command(args, check=True, shell=False, cwd=None, env=None, timeout=None): +# def run_command(args, check=True, shell=False, cwd=None, env=None): +# env = env if env else {} +# completed_process = subprocess.run( +# args, +# check=False, # Handle the check manually for custom error messages +# shell=shell, +# env={**os.environ, **env}, +# cwd=cwd, +# stderr=subprocess.PIPE, # Capture stderr +# text=True # Convert output to string +# ) + +# # Check if the subprocess was successful +# if check and completed_process.returncode != 0: +# # Raise an exception with stderr as the error message +# raise subprocess.CalledProcessError( +# completed_process.returncode, +# completed_process.args, +# stderr=completed_process.stderr.strip() +# ) + +# return completed_process + + +def run_command(args, check=True, shell=False, cwd=None, env=None): env = env if env else {} - return subprocess.run( + completed_process = subprocess.run( args, - check=check, + check=False, # Handle the check manually for custom error messages shell=shell, - env={ - **os.environ, - **env - }, + env={**os.environ, **env}, cwd=cwd, - timeout=timeout + # Removed the stderr=subprocess.PIPE to allow stderr to be output to the caller's stderr + text=True # Convert output to string ) + # Check if the subprocess was successful + if check and completed_process.returncode != 0: + # Raise an exception with return code and command arguments + raise subprocess.CalledProcessError( + completed_process.returncode, + completed_process.args + # Removed stderr from the exception to avoid duplicating error messages + ) + + return completed_process + def wait_up(port, retries=10, wait_secs=1): for i in range(0, retries): diff --git a/cannon/cmd/load_elf.go b/cannon/cmd/load_elf.go index 5cfc3078e905..7c41fc3c0ef6 100644 --- a/cannon/cmd/load_elf.go +++ b/cannon/cmd/load_elf.go @@ -7,6 +7,7 @@ import ( "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" ) var ( @@ -66,10 +67,10 @@ func LoadELF(ctx *cli.Context) error { if err != nil { return fmt.Errorf("failed to compute program metadata: %w", err) } - if err := writeJSON[*mipsevm.Metadata](ctx.Path(LoadELFMetaFlag.Name), meta); err != nil { + if err := jsonutil.WriteJSON[*mipsevm.Metadata](ctx.Path(LoadELFMetaFlag.Name), meta, OutFilePerm); err != nil { return fmt.Errorf("failed to output metadata: %w", err) } - return writeJSON[*mipsevm.State](ctx.Path(LoadELFOutFlag.Name), state) + return jsonutil.WriteJSON[*mipsevm.State](ctx.Path(LoadELFOutFlag.Name), state, OutFilePerm) } var LoadELFCommand = &cli.Command{ diff --git a/cannon/cmd/log.go b/cannon/cmd/log.go index cc829bb2e71e..04e168b9ecfb 100644 --- a/cannon/cmd/log.go +++ b/cannon/cmd/log.go @@ -3,14 +3,11 @@ package cmd import ( "io" + "golang.org/x/exp/slog" + "github.com/ethereum/go-ethereum/log" ) -func Logger(w io.Writer, lvl log.Lvl) log.Logger { - h := log.StreamHandler(w, log.LogfmtFormat()) - h = log.SyncHandler(h) - h = log.LvlFilterHandler(lvl, h) - l := log.New() - l.SetHandler(h) - return l +func Logger(w io.Writer, lvl slog.Level) log.Logger { + return log.NewLogger(log.LogfmtHandlerWithLevel(w, lvl)) } diff --git a/cannon/cmd/matcher.go b/cannon/cmd/matcher.go index 2f0267c143b2..b569ef6df6bd 100644 --- a/cannon/cmd/matcher.go +++ b/cannon/cmd/matcher.go @@ -4,11 +4,13 @@ import ( "fmt" "strconv" "strings" - - "github.com/ethereum-optimism/optimism/cannon/mipsevm" ) -type StepMatcher func(st *mipsevm.State) bool +type VMState interface { + GetStep() uint64 +} + +type StepMatcher func(st VMState) bool type StepMatcherFlag struct { repr string @@ -26,11 +28,11 @@ func MustStepMatcherFlag(pattern string) *StepMatcherFlag { func (m *StepMatcherFlag) Set(value string) error { m.repr = value if value == "" || value == "never" { - m.matcher = func(st *mipsevm.State) bool { + m.matcher = func(st VMState) bool { return false } } else if value == "always" { - m.matcher = func(st *mipsevm.State) bool { + m.matcher = func(st VMState) bool { return true } } else if strings.HasPrefix(value, "=") { @@ -38,16 +40,16 @@ func (m *StepMatcherFlag) Set(value string) error { if err != nil { return fmt.Errorf("failed to parse step number: %w", err) } - m.matcher = func(st *mipsevm.State) bool { - return st.Step == when + m.matcher = func(st VMState) bool { + return st.GetStep() == when } } else if strings.HasPrefix(value, "%") { when, err := strconv.ParseUint(value[1:], 0, 64) if err != nil { return fmt.Errorf("failed to parse step interval number: %w", err) } - m.matcher = func(st *mipsevm.State) bool { - return st.Step%when == 0 + m.matcher = func(st VMState) bool { + return st.GetStep()%when == 0 } } else { return fmt.Errorf("unrecognized step matcher: %q", value) @@ -61,7 +63,7 @@ func (m *StepMatcherFlag) String() string { func (m *StepMatcherFlag) Matcher() StepMatcher { if m.matcher == nil { // Set(value) is not called for omitted inputs, default to never matching. - return func(st *mipsevm.State) bool { + return func(st VMState) bool { return false } } diff --git a/cannon/cmd/run.go b/cannon/cmd/run.go index cf54300e3a1b..dd77eea1ac68 100644 --- a/cannon/cmd/run.go +++ b/cannon/cmd/run.go @@ -5,6 +5,9 @@ import ( "fmt" "os" "os/exec" + "slices" + "strconv" + "strings" "time" "github.com/ethereum/go-ethereum/common" @@ -16,6 +19,7 @@ import ( "github.com/ethereum-optimism/optimism/cannon/mipsevm" preimage "github.com/ethereum-optimism/optimism/op-preimage" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" ) var ( @@ -64,14 +68,19 @@ var ( Value: new(StepMatcherFlag), Required: false, } + RunStopAtPreimageFlag = &cli.StringFlag{ + Name: "stop-at-preimage", + Usage: "stop at the first preimage request matching this key", + Required: false, + } RunStopAtPreimageTypeFlag = &cli.StringFlag{ Name: "stop-at-preimage-type", - Usage: "stop at the first preimage request matching this type (must be either 'any', 'local' or 'global')", + Usage: "stop at the first preimage request matching this type", Required: false, } - RunStopAtPreimageKeyFlag = &cli.StringFlag{ - Name: "stop-at-preimage-key", - Usage: "stop at the first step that requests the specified preimage key", + RunStopAtPreimageLargerThanFlag = &cli.StringFlag{ + Name: "stop-at-preimage-larger-than", + Usage: "stop at the first step that requests a preimage larger than the specified size (in bytes)", Required: false, } RunMetaFlag = &cli.PathFlag{ @@ -90,6 +99,8 @@ var ( Name: "pprof.cpu", Usage: "enable pprof cpu profiling", } + + OutFilePerm = os.FileMode(0o755) ) type Proof struct { @@ -234,20 +245,53 @@ func Run(ctx *cli.Context) error { defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.CPUProfile).Stop() } - state, err := loadJSON[mipsevm.State](ctx.Path(RunInputFlag.Name)) + state, err := jsonutil.LoadJSON[mipsevm.State](ctx.Path(RunInputFlag.Name)) if err != nil { return err } - l := Logger(os.Stderr, log.LvlInfo) + l := Logger(os.Stderr, log.LevelInfo) outLog := &mipsevm.LoggingWriter{Name: "program std-out", Log: l} errLog := &mipsevm.LoggingWriter{Name: "program std-err", Log: l} - stopAtPreimageType := ctx.String(RunStopAtPreimageTypeFlag.Name) - if stopAtPreimageType != "" && stopAtPreimageType != "any" && stopAtPreimageType != "local" && stopAtPreimageType != "global" { - return fmt.Errorf("invalid preimage type %q, must be either 'any', 'local' or 'global'", stopAtPreimageType) + stopAtAnyPreimage := false + var stopAtPreimageKeyPrefix []byte + stopAtPreimageOffset := uint32(0) + if ctx.IsSet(RunStopAtPreimageFlag.Name) { + val := ctx.String(RunStopAtPreimageFlag.Name) + parts := strings.Split(val, "@") + if len(parts) > 2 { + return fmt.Errorf("invalid %v: %v", RunStopAtPreimageFlag.Name, val) + } + stopAtPreimageKeyPrefix = common.FromHex(parts[0]) + if len(parts) == 2 { + x, err := strconv.ParseUint(parts[1], 10, 32) + if err != nil { + return fmt.Errorf("invalid preimage offset: %w", err) + } + stopAtPreimageOffset = uint32(x) + } + } else { + switch ctx.String(RunStopAtPreimageTypeFlag.Name) { + case "local": + stopAtPreimageKeyPrefix = []byte{byte(preimage.LocalKeyType)} + case "keccak": + stopAtPreimageKeyPrefix = []byte{byte(preimage.Keccak256KeyType)} + case "sha256": + stopAtPreimageKeyPrefix = []byte{byte(preimage.Sha256KeyType)} + case "blob": + stopAtPreimageKeyPrefix = []byte{byte(preimage.BlobKeyType)} + case "precompile": + stopAtPreimageKeyPrefix = []byte{byte(preimage.PrecompileKeyType)} + case "any": + stopAtAnyPreimage = true + case "": + // 0 preimage type is forbidden so will not stop at any preimage + default: + return fmt.Errorf("invalid preimage type %q", ctx.String(RunStopAtPreimageTypeFlag.Name)) + } } - stopAtPreimageKey := common.HexToHash(ctx.String(RunStopAtPreimageKeyFlag.Name)) + stopAtPreimageLargerThan := ctx.Int(RunStopAtPreimageLargerThanFlag.Name) // split CLI args after first '--' args := ctx.Args().Slice() @@ -284,7 +328,7 @@ func Run(ctx *cli.Context) error { l.Info("no metadata file specified, defaulting to empty metadata") meta = &mipsevm.Metadata{Symbols: nil} // provide empty metadata by default } else { - if m, err := loadJSON[mipsevm.Metadata](metaPath); err != nil { + if m, err := jsonutil.LoadJSON[mipsevm.Metadata](metaPath); err != nil { return fmt.Errorf("failed to load metadata: %w", err) } else { meta = m @@ -333,17 +377,16 @@ func Run(ctx *cli.Context) error { } if stopAt(state) { + l.Info("Reached stop at") break } if snapshotAt(state) { - if err := writeJSON(fmt.Sprintf(snapshotFmt, step), state); err != nil { + if err := jsonutil.WriteJSON(fmt.Sprintf(snapshotFmt, step), state, OutFilePerm); err != nil { return fmt.Errorf("failed to write state snapshot: %w", err) } } - prevPreimageOffset := state.PreimageOffset - if proofAt(state) { preStateHash, err := state.EncodeWitness().StateHash() if err != nil { @@ -369,7 +412,7 @@ func Run(ctx *cli.Context) error { proof.OracleValue = witness.PreimageValue proof.OracleOffset = witness.PreimageOffset } - if err := writeJSON(fmt.Sprintf(proofFmt, step), proof); err != nil { + if err := jsonutil.WriteJSON(fmt.Sprintf(proofFmt, step), proof, OutFilePerm); err != nil { return fmt.Errorf("failed to write proof data: %w", err) } } else { @@ -379,26 +422,28 @@ func Run(ctx *cli.Context) error { } } - if preimageRead := state.PreimageOffset > prevPreimageOffset; preimageRead { - if stopAtPreimageType == "any" { + lastPreimageKey, lastPreimageValue, lastPreimageOffset := us.LastPreimage() + if lastPreimageOffset != ^uint32(0) { + if stopAtAnyPreimage { + l.Info("Stopping at preimage read") break } - if stopAtPreimageType != "" { - keyType := byte(preimage.LocalKeyType) - if stopAtPreimageType == "global" { - keyType = byte(preimage.Keccak256KeyType) - } - if state.PreimageKey.Bytes()[0] == keyType { + if len(stopAtPreimageKeyPrefix) > 0 && + slices.Equal(lastPreimageKey[:len(stopAtPreimageKeyPrefix)], stopAtPreimageKeyPrefix) { + if stopAtPreimageOffset == lastPreimageOffset { + l.Info("Stopping at preimage read", "keyPrefix", common.Bytes2Hex(stopAtPreimageKeyPrefix), "offset", lastPreimageOffset) break } } - if (stopAtPreimageKey != common.Hash{}) && state.PreimageKey == stopAtPreimageKey { + if stopAtPreimageLargerThan != 0 && len(lastPreimageValue) > stopAtPreimageLargerThan { + l.Info("Stopping at preimage read", "size", len(lastPreimageValue), "min", stopAtPreimageLargerThan) break } } } + l.Info("Execution stopped", "exited", state.Exited, "code", state.ExitCode) - if err := writeJSON(ctx.Path(RunOutputFlag.Name), state); err != nil { + if err := jsonutil.WriteJSON(ctx.Path(RunOutputFlag.Name), state, OutFilePerm); err != nil { return fmt.Errorf("failed to write state output: %w", err) } return nil @@ -417,8 +462,9 @@ var RunCommand = &cli.Command{ RunSnapshotAtFlag, RunSnapshotFmtFlag, RunStopAtFlag, + RunStopAtPreimageFlag, RunStopAtPreimageTypeFlag, - RunStopAtPreimageKeyFlag, + RunStopAtPreimageLargerThanFlag, RunMetaFlag, RunInfoAtFlag, RunPProfCPU, diff --git a/cannon/cmd/witness.go b/cannon/cmd/witness.go index d92a27779180..c2f38daa3621 100644 --- a/cannon/cmd/witness.go +++ b/cannon/cmd/witness.go @@ -5,6 +5,7 @@ import ( "os" "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" "github.com/urfave/cli/v2" ) @@ -25,7 +26,7 @@ var ( func Witness(ctx *cli.Context) error { input := ctx.Path(WitnessInputFlag.Name) output := ctx.Path(WitnessOutputFlag.Name) - state, err := loadJSON[mipsevm.State](input) + state, err := jsonutil.LoadJSON[mipsevm.State](input) if err != nil { return fmt.Errorf("invalid input state (%v): %w", input, err) } diff --git a/cannon/docs/README.md b/cannon/docs/README.md index db7fd379c555..90fbcd34dbd6 100644 --- a/cannon/docs/README.md +++ b/cannon/docs/README.md @@ -45,7 +45,7 @@ There are 3 types of witness data involved in onchain execution: ### Packed State The Packed State is provided in every executed onchain instruction. -See [Cannon VM Specs](../../specs/cannon-fault-proof-vm.md#state) for +See [Cannon VM Specs](https://github.com/ethereum-optimism/specs/blob/main/specs/experimental/fault-proof/cannon-fault-proof-vm.md#state) for details on the state structure. The packed state is small! The `State` data can be packed in such a small amount of EVM words, @@ -99,10 +99,10 @@ since all sibling data that is combined with the new leaf value was already auth ### Pre-image data Pre-image data is accessed through syscalls exclusively. -The OP-stack fault-proof [Pre-image Oracle specs](../../specs/fault-proof.md#pre-image-oracle) +The OP-stack fault-proof [Pre-image Oracle specs](https://github.com/ethereum-optimism/specs/blob/main/specs/fault-proof.md#pre-image-oracle) define the ABI for communicating pre-images. -This ABI is implemented by the VM by intercepting the `read`/`write` syscalls to specific file descriptors. See [Cannon VM Specs](../../specs/cannon-fault-proof-vm.md#io) for more details. +This ABI is implemented by the VM by intercepting the `read`/`write` syscalls to specific file descriptors. See [Cannon VM Specs](https://github.com/ethereum-optimism/specs/blob/main/specs/cannon-fault-proof-vm.md#io) for more details. The data is loaded into `PreimageOracle.sol` using the respective loading function based on the pre-image type. And then retrieved during execution of the `read` syscall. diff --git a/cannon/example/claim/go.mod b/cannon/example/claim/go.mod index dcf894c5e5c0..8a286a3e4a05 100644 --- a/cannon/example/claim/go.mod +++ b/cannon/example/claim/go.mod @@ -7,8 +7,8 @@ toolchain go1.21.1 require github.com/ethereum-optimism/optimism v0.0.0 require ( - golang.org/x/crypto v0.18.0 // indirect - golang.org/x/sys v0.16.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect ) replace github.com/ethereum-optimism/optimism v0.0.0 => ../../.. diff --git a/cannon/example/claim/go.sum b/cannon/example/claim/go.sum index 6a34fa90c22a..f5cfc4a02848 100644 --- a/cannon/example/claim/go.sum +++ b/cannon/example/claim/go.sum @@ -2,11 +2,11 @@ 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cannon/mipsevm/evm.go b/cannon/mipsevm/evm.go index bb49be85d7e4..27bd085b70a6 100644 --- a/cannon/mipsevm/evm.go +++ b/cannon/mipsevm/evm.go @@ -52,9 +52,14 @@ type Addresses struct { } func NewEVMEnv(contracts *Contracts, addrs *Addresses) (*vm.EVM, *state.StateDB) { - chainCfg := params.MainnetChainConfig - offsetBlocks := uint64(1000) // blocks after shanghai fork - bc := &testChain{startTime: *chainCfg.ShanghaiTime + offsetBlocks*12} + // Temporary hack until Cancun is activated on mainnet + cpy := *params.MainnetChainConfig + chainCfg := &cpy // don't modify the global chain config + // Activate Cancun for EIP-4844 KZG point evaluation precompile + cancunActivation := *chainCfg.ShanghaiTime + 10 + chainCfg.CancunTime = &cancunActivation + offsetBlocks := uint64(1000) // blocks after cancun fork + bc := &testChain{startTime: *chainCfg.CancunTime + offsetBlocks*12} header := bc.GetHeader(common.Hash{}, 17034870+offsetBlocks) db := rawdb.NewMemoryDatabase() statedb := state.NewDatabase(db) diff --git a/cannon/mipsevm/evm_test.go b/cannon/mipsevm/evm_test.go index 86fd29cc5217..274521edce1e 100644 --- a/cannon/mipsevm/evm_test.go +++ b/cannon/mipsevm/evm_test.go @@ -9,7 +9,6 @@ import ( "math/big" "os" "path" - "strings" "testing" "time" @@ -42,20 +41,25 @@ func MarkdownTracer() vm.EVMLogger { } type MIPSEVM struct { - env *vm.EVM - evmState *state.StateDB - addrs *Addresses + env *vm.EVM + evmState *state.StateDB + addrs *Addresses + localOracle PreimageOracle } func NewMIPSEVM(contracts *Contracts, addrs *Addresses) *MIPSEVM { env, evmState := NewEVMEnv(contracts, addrs) - return &MIPSEVM{env, evmState, addrs} + return &MIPSEVM{env, evmState, addrs, nil} } func (m *MIPSEVM) SetTracer(tracer vm.EVMLogger) { m.env.Config.Tracer = tracer } +func (m *MIPSEVM) SetLocalOracle(oracle PreimageOracle) { + m.localOracle = oracle +} + // Step is a pure function that computes the poststate from the VM state encoded in the StepWitness. func (m *MIPSEVM) Step(t *testing.T, stepWitness *StepWitness) []byte { sender := common.Address{0x13, 0x37} @@ -66,7 +70,7 @@ func (m *MIPSEVM) Step(t *testing.T, stepWitness *StepWitness) []byte { if stepWitness.HasPreimage() { t.Logf("reading preimage key %x at offset %d", stepWitness.PreimageKey, stepWitness.PreimageOffset) - poInput, err := encodePreimageOracleInput(t, stepWitness, LocalContext{}) + poInput, err := encodePreimageOracleInput(t, stepWitness, LocalContext{}, m.localOracle) require.NoError(t, err, "encode preimage oracle input") _, leftOverGas, err := m.env.Call(vm.AccountRef(sender), m.addrs.Oracle, poInput, startingGas, big.NewInt(0)) require.NoErrorf(t, err, "evm should not fail, took %d gas", startingGas-leftOverGas) @@ -100,7 +104,7 @@ func encodeStepInput(t *testing.T, wit *StepWitness, localContext LocalContext) return input } -func encodePreimageOracleInput(t *testing.T, wit *StepWitness, localContext LocalContext) ([]byte, error) { +func encodePreimageOracleInput(t *testing.T, wit *StepWitness, localContext LocalContext, localOracle PreimageOracle) ([]byte, error) { if wit.PreimageKey == ([32]byte{}) { return nil, errors.New("cannot encode pre-image oracle input, witness has no pre-image to proof") } @@ -132,6 +136,21 @@ func encodePreimageOracleInput(t *testing.T, wit *StepWitness, localContext Loca wit.PreimageValue[8:]) require.NoError(t, err) return input, nil + case preimage.PrecompileKeyType: + if localOracle == nil { + return nil, fmt.Errorf("local oracle is required for precompile preimages") + } + preimage := localOracle.GetPreimage(preimage.Keccak256Key(wit.PreimageKey).PreimageKey()) + precompile := common.BytesToAddress(preimage[:20]) + callInput := preimage[20:] + input, err := preimageAbi.Pack( + "loadPrecompilePreimagePart", + new(big.Int).SetUint64(uint64(wit.PreimageOffset)), + precompile, + callInput, + ) + require.NoError(t, err) + return input, nil default: return nil, fmt.Errorf("unsupported pre-image type %d, cannot prepare preimage with key %x offset %d for oracle", wit.PreimageKey[0], wit.PreimageKey, wit.PreimageOffset) @@ -147,15 +166,13 @@ func TestEVM(t *testing.T) { for _, f := range testFiles { t.Run(f.Name(), func(t *testing.T) { - var oracle PreimageOracle - if strings.HasPrefix(f.Name(), "oracle") { - oracle = staticOracle(t, []byte("hello world")) - } + oracle := selectOracleFixture(t, f.Name()) // Short-circuit early for exit_group.bin exitGroup := f.Name() == "exit_group.bin" evm := NewMIPSEVM(contracts, addrs) evm.SetTracer(tracer) + evm.SetLocalOracle(oracle) fn := path.Join("open_mips_tests/test/bin", f.Name()) programMem, err := os.ReadFile(fn) @@ -185,8 +202,8 @@ func TestEVM(t *testing.T) { // verify the post-state matches. // TODO: maybe more readable to decode the evmPost state, and do attribute-wise comparison. goPost := goState.state.EncodeWitness() - require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), - "mipsevm produced different state than EVM") + require.Equalf(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), + "mipsevm produced different state than EVM at step %d", state.Step) } if exitGroup { require.NotEqual(t, uint32(endAddr), goState.state.PC, "must not reach end") diff --git a/cannon/mipsevm/fuzz_evm_test.go b/cannon/mipsevm/fuzz_evm_test.go index 60be06b29658..404d4e028af0 100644 --- a/cannon/mipsevm/fuzz_evm_test.go +++ b/cannon/mipsevm/fuzz_evm_test.go @@ -322,6 +322,7 @@ func FuzzStateHintRead(f *testing.F) { require.Equal(t, preStateRoot, state.Memory.MerkleRoot()) require.Equal(t, uint64(1), state.Step) require.Equal(t, preStatePreimageKey, state.PreimageKey) + require.Equal(t, expectedRegisters, state.Registers) evm := NewMIPSEVM(contracts, addrs) evmPost := evm.Step(t, stepWitness) @@ -439,6 +440,7 @@ func FuzzStateHintWrite(f *testing.F) { require.Equal(t, preStateRoot, state.Memory.MerkleRoot()) require.Equal(t, uint64(1), state.Step) require.Equal(t, preStatePreimageKey, state.PreimageKey) + require.Equal(t, expectedRegisters, state.Registers) evm := NewMIPSEVM(contracts, addrs) evmPost := evm.Step(t, stepWitness) @@ -471,9 +473,9 @@ func FuzzStatePreimageWrite(f *testing.F) { expectedRegisters := state.Registers sz := 4 - (addr & 0x3) if sz < count { - sz = count + count = sz } - expectedRegisters[2] = sz + expectedRegisters[2] = count oracle := staticOracle(t, preimageData) goState := NewInstrumentedState(state, oracle, os.Stdout, os.Stderr) @@ -491,6 +493,7 @@ func FuzzStatePreimageWrite(f *testing.F) { require.Equal(t, preStateRoot, state.Memory.MerkleRoot()) require.Equal(t, uint64(1), state.Step) require.Equal(t, uint32(0), state.PreimageOffset) + require.Equal(t, expectedRegisters, state.Registers) evm := NewMIPSEVM(contracts, addrs) evmPost := evm.Step(t, stepWitness) diff --git a/cannon/mipsevm/instrumented.go b/cannon/mipsevm/instrumented.go index 4e090b8014e1..fc276effd89f 100644 --- a/cannon/mipsevm/instrumented.go +++ b/cannon/mipsevm/instrumented.go @@ -80,3 +80,7 @@ func (m *InstrumentedState) Step(proof bool) (wit *StepWitness, err error) { } return } + +func (m *InstrumentedState) LastPreimage() ([32]byte, []byte, uint32) { + return m.lastPreimageKey, m.lastPreimage, m.lastPreimageOffset +} diff --git a/cannon/mipsevm/open_mips_tests/test/bin/oracle_kzg.bin b/cannon/mipsevm/open_mips_tests/test/bin/oracle_kzg.bin new file mode 100644 index 000000000000..20a642fa430c Binary files /dev/null and b/cannon/mipsevm/open_mips_tests/test/bin/oracle_kzg.bin differ diff --git a/cannon/mipsevm/open_mips_tests/test/oracle_kzg.asm b/cannon/mipsevm/open_mips_tests/test/oracle_kzg.asm new file mode 100644 index 000000000000..8faf349bf3ab --- /dev/null +++ b/cannon/mipsevm/open_mips_tests/test/oracle_kzg.asm @@ -0,0 +1,102 @@ +.section .test, "x" + .balign 4 + .set noreorder + .global test + .ent test + +# load hash at 0x30001000 +# point evaluation precompile input - 01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a +# 0x0a44472c cb798bc5 954fc466 e6ee2c31 e1ca8a87 d000966c 629d679a 4a29921f = keccak(address(0xa) ++ precompile_input) +# 0x0644472c cb798bc5 954fc466 e6ee2c31 e1ca8a87 d000966c 629d679a 4a29921f = keccak(address(0xa) ++ precompile_input).key (precompile) +test: + lui $s0, 0x3000 + ori $s0, 0x1000 + + lui $t0, 0x0644 + ori $t0, 0x472c + sw $t0, 0($s0) + lui $t0, 0xcb79 + ori $t0, 0x8bc5 + sw $t0, 4($s0) + lui $t0, 0x954f + ori $t0, 0xc466 + sw $t0, 8($s0) + lui $t0, 0xe6ee + ori $t0, 0x2c31 + sw $t0, 0xc($s0) + lui $t0, 0xe1ca + ori $t0, 0x8a87 + sw $t0, 0x10($s0) + lui $t0, 0xd000 + ori $t0, 0x966c + sw $t0, 0x14($s0) + lui $t0, 0x629d + ori $t0, 0x679a + sw $t0, 0x18($s0) + lui $t0, 0x4a29 + ori $t0, 0x921f + sw $t0, 0x1c($s0) + +# preimage request - write(fdPreimageWrite, preimageData, 32) + li $a0, 6 + li $a1, 0x30001000 + li $t0, 8 + li $a2, 4 +$writeloop: + li $v0, 4004 + syscall + addiu $a1, $a1, 4 + addiu $t0, $t0, -1 + bnez $t0, $writeloop + nop + +# preimage response to 0x30002000 - read(fdPreimageRead, addr, count) +# read preimage length + li $a0, 5 + li $a1, 0x31000000 + li $a2, 4 + li $v0, 4003 + syscall + li $a1, 0x31000004 + li $v0, 4003 + syscall +# read the 1 byte precompile status and 3 bytes of return data + li $a1, 0x31000008 + li $v0, 4003 + syscall + nop + +# length at 0x31000000. We also check that the lower 32 bits are zero + lui $s1, 0x3100 + lw $t0, 0($s1) + sltiu $t6, $t0, 1 + li $s1, 0x31000004 + lw $t0, 0($s1) +# should be 1 + len(blobPrecompileReturnValue) = 65 + li $t4, 65 + subu $t5, $t0, $t4 + sltiu $v0, $t5, 1 + and $v0, $v0, $t6 + +# data at 0x31000008 +# first byte is 01 status. Next 3 bytes are 0 + lw $t0, 4($s1) + lui $t4, 0x0100 + ori $t4, 0x0000 + subu $t5, $t0, $t4 + sltiu $v1, $t5, 1 + and $v0, $v0, $v1 + +# save results + lui $s0, 0xbfff # Load the base address 0xbffffff0 + ori $s0, 0xfff0 + ori $s1, $0, 1 # Prepare the 'done' status + + sw $v0, 8($s0) # Set the test result + sw $s1, 4($s0) # Set 'done' + +$done: + jr $ra + nop + + .end test diff --git a/cannon/mipsevm/state.go b/cannon/mipsevm/state.go index f6f68914376e..fea495218a58 100644 --- a/cannon/mipsevm/state.go +++ b/cannon/mipsevm/state.go @@ -42,6 +42,8 @@ type State struct { LastHint hexutil.Bytes `json:"lastHint,omitempty"` } +func (s *State) GetStep() uint64 { return s.Step } + func (s *State) VMStatus() uint8 { return vmStatus(s.Exited, s.ExitCode) } @@ -81,7 +83,7 @@ const ( func (sw StateWitness) StateHash() (common.Hash, error) { if len(sw) != 226 { - return common.Hash{}, fmt.Errorf("Invalid witness length. Got %d, expected at least 88", len(sw)) + return common.Hash{}, fmt.Errorf("Invalid witness length. Got %d, expected 226", len(sw)) } hash := crypto.Keccak256Hash(sw) diff --git a/cannon/mipsevm/state_test.go b/cannon/mipsevm/state_test.go index 2e866cde574a..b430398c389b 100644 --- a/cannon/mipsevm/state_test.go +++ b/cannon/mipsevm/state_test.go @@ -31,10 +31,7 @@ func TestState(t *testing.T) { for _, f := range testFiles { t.Run(f.Name(), func(t *testing.T) { - var oracle PreimageOracle - if strings.HasPrefix(f.Name(), "oracle") { - oracle = staticOracle(t, []byte("hello world")) - } + oracle := selectOracleFixture(t, f.Name()) // Short-circuit early for exit_group.bin exitGroup := f.Name() == "exit_group.bin" @@ -269,3 +266,38 @@ func staticOracle(t *testing.T, preimageData []byte) *testOracle { }, } } + +func staticPrecompileOracle(t *testing.T, precompile common.Address, input []byte, result []byte) *testOracle { + return &testOracle{ + hint: func(v []byte) {}, + getPreimage: func(k [32]byte) []byte { + keyData := append(precompile.Bytes(), input...) + switch k[0] { + case byte(preimage.Keccak256KeyType): + if k != preimage.Keccak256Key(crypto.Keccak256Hash(keyData)).PreimageKey() { + t.Fatalf("invalid preimage request for %x", k) + } + return keyData + case byte(preimage.PrecompileKeyType): + if k != preimage.PrecompileKey(crypto.Keccak256Hash(keyData)).PreimageKey() { + t.Fatalf("invalid preimage request for %x", k) + } + return result + } + panic("unreachable") + }, + } +} + +func selectOracleFixture(t *testing.T, programName string) PreimageOracle { + if strings.HasPrefix(programName, "oracle_kzg") { + precompile := common.BytesToAddress([]byte{0xa}) + input := common.FromHex("01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a") + blobPrecompileReturnValue := common.FromHex("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001") + return staticPrecompileOracle(t, precompile, input, append([]byte{0x1}, blobPrecompileReturnValue...)) + } else if strings.HasPrefix(programName, "oracle") { + return staticOracle(t, []byte("hello world")) + } else { + return nil + } +} diff --git a/docker-bake.hcl b/docker-bake.hcl index 279d0d2bd5d7..027f2adff683 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -93,6 +93,19 @@ target "op-challenger" { tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/op-challenger:${tag}"] } +target "op-dispute-mon" { + dockerfile = "Dockerfile" + context = "./op-dispute-mon" + args = { + OP_STACK_GO_BUILDER = "op-stack-go" + } + contexts = { + op-stack-go: "target:op-stack-go" + } + platforms = split(",", PLATFORMS) + tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/op-dispute-mon:${tag}"] +} + target "op-conductor" { dockerfile = "Dockerfile" context = "./op-conductor" @@ -203,9 +216,18 @@ target "ci-builder" { dockerfile = "./ops/docker/ci-builder/Dockerfile" context = "." platforms = split(",", PLATFORMS) + target="base-builder" tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/ci-builder:${tag}"] } +target "ci-builder-rust" { + dockerfile = "./ops/docker/ci-builder/Dockerfile" + context = "." + platforms = split(",", PLATFORMS) + target="rust-builder" + tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/ci-builder-rust:${tag}"] +} + target "contracts-bedrock" { dockerfile = "./ops/docker/Dockerfile.packages" context = "." diff --git a/docs/security-reviews/2023_12_Trust_SuperchainConfigUpgrade.pdf b/docs/security-reviews/2023_12_Trust_SuperchainConfigUpgrade.pdf new file mode 100644 index 000000000000..b03c4491621f Binary files /dev/null and b/docs/security-reviews/2023_12_Trust_SuperchainConfigUpgrade.pdf differ diff --git a/docs/security-reviews/2024_02-MCP_L1-Cantina.pdf b/docs/security-reviews/2024_02-MCP_L1-Cantina.pdf new file mode 100644 index 000000000000..69f4891dd7ff Binary files /dev/null and b/docs/security-reviews/2024_02-MCP_L1-Cantina.pdf differ diff --git a/endpoint-monitor/endpoint_monitor.go b/endpoint-monitor/endpoint_monitor.go index 675a287a31f4..b08b8c199e59 100644 --- a/endpoint-monitor/endpoint_monitor.go +++ b/endpoint-monitor/endpoint_monitor.go @@ -36,7 +36,7 @@ func Main(version string) func(cliCtx *cli.Context) error { } l := oplog.NewLogger(oplog.AppOut(cliCtx), cfg.LogConfig) - oplog.SetGlobalLogHandler(l.GetHandler()) + oplog.SetGlobalLogHandler(l.Handler()) endpointMonitor := NewEndpointMonitor(cfg, l) l.Info(fmt.Sprintf("starting endpoint monitor with checkInterval=%s checkDuration=%s", cfg.CheckInterval, cfg.CheckDuration)) diff --git a/go.mod b/go.mod index 28066b41d480..a121a895959e 100644 --- a/go.mod +++ b/go.mod @@ -4,50 +4,57 @@ go 1.21 require ( github.com/BurntSushi/toml v1.3.2 + github.com/Layr-Labs/eigenda v0.6.1 + github.com/Layr-Labs/eigenda/api v0.6.1 github.com/btcsuite/btcd v0.24.0 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 + github.com/cockroachdb/pebble v0.0.0-20231018212520-f6cde3fc2fa4 + github.com/consensys/gnark-crypto v0.12.1 + github.com/crate-crypto/go-kzg-4844 v0.7.0 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 - github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240103191009-655947053753 - github.com/ethereum/go-ethereum v1.13.5 + github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240306093353-c557df8e6f41 + github.com/ethereum/go-ethereum v1.13.14 github.com/fsnotify/fsnotify v1.7.0 - github.com/go-chi/chi/v5 v5.0.11 + github.com/go-chi/chi/v5 v5.0.12 github.com/go-chi/docgen v1.2.0 github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb github.com/google/go-cmp v0.6.0 github.com/google/gofuzz v1.2.1-0.20220503160820-4a35382e8fc8 - github.com/google/uuid v1.5.0 + github.com/google/uuid v1.6.0 github.com/hashicorp/go-multierror v1.1.1 - github.com/hashicorp/golang-lru/v2 v2.0.5 - github.com/hashicorp/raft v1.6.0 + github.com/hashicorp/golang-lru/v2 v2.0.7 + github.com/hashicorp/raft v1.6.1 github.com/hashicorp/raft-boltdb v0.0.0-20231211162105-6c830fa4535e - github.com/holiman/uint256 v1.2.3 + github.com/holiman/uint256 v1.2.4 github.com/ipfs/go-datastore v0.6.0 github.com/ipfs/go-ds-leveldb v0.5.0 - github.com/jackc/pgtype v1.14.1 - github.com/jackc/pgx/v5 v5.5.2 + github.com/jackc/pgtype v1.14.2 + github.com/jackc/pgx/v5 v5.5.5 github.com/libp2p/go-libp2p v0.32.0 github.com/libp2p/go-libp2p-mplex v0.9.0 github.com/libp2p/go-libp2p-pubsub v0.10.0 github.com/libp2p/go-libp2p-testing v0.12.0 github.com/mattn/go-isatty v0.0.20 github.com/multiformats/go-base32 v0.1.0 - github.com/multiformats/go-multiaddr v0.12.1 + github.com/multiformats/go-multiaddr v0.12.2 github.com/multiformats/go-multiaddr-dns v0.3.1 github.com/olekukonko/tablewriter v0.0.5 github.com/onsi/gomega v1.31.1 github.com/pkg/errors v0.9.1 github.com/pkg/profile v1.7.0 - github.com/prometheus/client_golang v1.18.0 - github.com/stretchr/testify v1.8.4 + github.com/prometheus/client_golang v1.19.0 + github.com/stretchr/testify v1.9.0 github.com/urfave/cli/v2 v2.27.1 - golang.org/x/crypto v0.18.0 - golang.org/x/exp v0.0.0-20231006140011-7918f672742d + golang.org/x/crypto v0.21.0 + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/sync v0.6.0 - golang.org/x/term v0.16.0 + golang.org/x/term v0.18.0 golang.org/x/time v0.5.0 - gorm.io/driver/postgres v1.5.4 - gorm.io/gorm v1.25.5 + google.golang.org/grpc v1.59.0 + google.golang.org/protobuf v1.32.0 + gorm.io/driver/postgres v1.5.7 + gorm.io/gorm v1.25.8 ) require ( @@ -58,7 +65,7 @@ require ( github.com/armon/go-metrics v0.4.1 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.7.0 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/boltdb/bolt v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/btcsuite/btcd/btcutil v1.1.5 // indirect @@ -66,16 +73,13 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cockroachdb/errors v1.11.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/pebble v0.0.0-20231018212520-f6cde3fc2fa4 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/consensys/bavard v0.1.13 // indirect - github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80 // indirect - github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect @@ -88,15 +92,14 @@ require ( github.com/ethereum/c-kzg-4844 v0.4.0 // indirect github.com/fatih/color v1.13.0 // indirect github.com/felixge/fgprof v0.9.3 // indirect - github.com/fjl/memsize v0.0.1 // indirect + github.com/fjl/memsize v0.0.2 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect - github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b // indirect + github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/go-stack/stack v1.8.1 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gofrs/flock v0.8.1 // indirect @@ -109,13 +112,13 @@ require ( github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-bexpr v0.1.11 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.2 // indirect github.com/hashicorp/go-immutable-radix v1.0.0 // indirect github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-msgpack/v2 v2.1.1 // indirect github.com/hashicorp/golang-lru v0.5.0 // indirect github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect - github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 // indirect + github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect @@ -135,7 +138,7 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c // indirect github.com/klauspost/compress v1.17.2 // indirect - github.com/klauspost/cpuid/v2 v2.2.5 // indirect + github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/koron/go-ssdp v0.0.4 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect @@ -153,7 +156,6 @@ require ( github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect - github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/miekg/dns v1.1.56 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect @@ -178,7 +180,7 @@ require ( github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-20 v0.3.4 // indirect @@ -192,7 +194,7 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect @@ -203,15 +205,15 @@ require ( go.uber.org/automaxprocs v1.5.2 // indirect go.uber.org/dig v1.17.1 // indirect go.uber.org/fx v1.20.1 // indirect - go.uber.org/mock v0.3.0 // indirect + go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.16.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/mod v0.16.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.16.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -219,7 +221,8 @@ require ( rsc.io/tmplfunc v0.0.3 // indirect ) -replace github.com/ethereum/go-ethereum v1.13.5 => github.com/ethereum-optimism/op-geth v1.101305.2-rc.2.0.20240117002010-d5f142e54a0a +replace github.com/ethereum/go-ethereum v1.13.14 => github.com/ethereum-optimism/op-geth v1.101308.3-rc.1 + +// replace github.com/ethereum-optimism/superchain-registry/superchain => ../superchain-registry/superchain -//replace github.com/ethereum-optimism/superchain-registry/superchain => ../superchain-registry/superchain //replace github.com/ethereum/go-ethereum v1.13.5 => ../go-ethereum diff --git a/go.sum b/go.sum index cd4d5ba5f7de..f724f95a274f 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,10 @@ github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/Layr-Labs/eigenda v0.6.1 h1:uU04t+dsR5oHsbr+A5XIeJdyZIfNW3YvG03dMTKLSK4= +github.com/Layr-Labs/eigenda v0.6.1/go.mod h1:XongI0xM6ks66DzxvTpF2yi4x2QH0X2RgEbKl/WFebY= +github.com/Layr-Labs/eigenda/api v0.6.1 h1:TAstOttTmFZQoFlZtgu/rNktNOhx62TwRFMxGOhUx8M= +github.com/Layr-Labs/eigenda/api v0.6.1/go.mod h1:kVXqWM13s/1hXyv9QdHweWAbKin9MeOBbS4i8c9rLbU= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= @@ -42,8 +46,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 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/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= -github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= @@ -122,8 +126,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80 h1:DuBDHVjgGMPki7bAyh91+3cF1Vh34sAEdH8JQgbc2R0= -github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80/go.mod h1:gzbVz57IDJgQ9rLQwfSk696JGWof8ftznEL9GoAv3NI= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= @@ -170,18 +174,18 @@ github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/ github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs= -github.com/ethereum-optimism/op-geth v1.101305.2-rc.2.0.20240117002010-d5f142e54a0a h1:QX7fp0vyIFYefxCXP9h5iki+EPfdizIXCNeXS12EaZ4= -github.com/ethereum-optimism/op-geth v1.101305.2-rc.2.0.20240117002010-d5f142e54a0a/go.mod h1:HGpRaQiUONEEfsL/hq9/jg8YnR9TCHCPqjmaPoFBhto= -github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240103191009-655947053753 h1:DL667cfM6peU8H9Ut/uu9h9Bd4gQCcJrjq+yYsfYwjk= -github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240103191009-655947053753/go.mod h1:/70H/KqrtKcvWvNGVj6S3rAcLC+kUPr3t2aDmYIS+Xk= +github.com/ethereum-optimism/op-geth v1.101308.3-rc.1 h1:mC8PrDNTZJr7sYcm+FgaWFUy/LOZ0sS8+BxkglUoPkg= +github.com/ethereum-optimism/op-geth v1.101308.3-rc.1/go.mod h1:k0UbrLuOITLD8goCyA2xWebAL03n2BZUCfwos0rxz60= +github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240306093353-c557df8e6f41 h1:WKJvsRyW/YNgyT0P2x5U530ITOY8Dv9TrZnbliqSXd8= +github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240306093353-c557df8e6f41/go.mod h1:7xh2awFQqsiZxFrHKTgEd+InVfDRrkKVUIuK8SAFHp0= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= -github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= -github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA= +github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= @@ -194,8 +198,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b h1:vMT47RYsrftsHSTQhqXwC3BYflo38OLC3Y4LtXtLyU0= -github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b/go.mod h1:CDncRYVRSDqwakm282WEkjfaAj1hxU/v5RXxk5nXOiI= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= @@ -204,8 +208,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA= -github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= +github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/docgen v1.2.0 h1:da0Nq2PKU9W9pSOTUfVrKI1vIgTGpauo9cfh4Iwivek= github.com/go-chi/docgen v1.2.0/go.mod h1:G9W0G551cs2BFMSn/cnGwX+JBHEloAgo17MBhyrnhPI= github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= @@ -220,15 +224,14 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= @@ -293,8 +296,8 @@ github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b/go.mod h1:czg5+yv1E0Z github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -312,8 +315,8 @@ github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubC github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U+N8T+6Kz1AE= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.2 h1:NOtoftovWkDheyUM/8JW3QMiXyxJK3uHRK7wV04nD2I= +github.com/hashicorp/go-hclog v1.6.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= @@ -329,19 +332,19 @@ github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCO github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGNJAg1dcN2Fpfw= github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU= -github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4= -github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/raft v1.1.0/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= -github.com/hashicorp/raft v1.6.0 h1:tkIAORZy2GbJ2Trp5eUSggLXDPOJLXC+JJLNMMqtgtM= -github.com/hashicorp/raft v1.6.0/go.mod h1:Xil5pDgeGwRWuX4uPUmwa+7Vagg4N804dz6mhNi6S7o= +github.com/hashicorp/raft v1.6.1 h1:v/jm5fcYHvVkL0akByAp+IDdDSzCNCGhdO6VdB56HIM= +github.com/hashicorp/raft v1.6.1/go.mod h1:N1sKh6Vn47mrWvEArQgILTyng8GoDRNYlgKyK7PMjs0= github.com/hashicorp/raft-boltdb v0.0.0-20231211162105-6c830fa4535e h1:SK4y8oR4ZMHPvwVHryKI88kJPJda4UyWYvG5A6iEQxc= github.com/hashicorp/raft-boltdb v0.0.0-20231211162105-6c830fa4535e/go.mod h1:EMz/UIuG93P0MBeHh6CbXQAEe8ckVJLZjhD17lBzK5Q= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= -github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= @@ -404,15 +407,15 @@ github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01C github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.14.1 h1:LyDar7M2K0tShCWqzJ/ctzF1QC3Wzc9c8a6cHE0PFdc= -github.com/jackc/pgtype v1.14.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgtype v1.14.2 h1:QBdZQTKpPdBlw2AdKwHEyqUcm/lrl2cwWAHjCMyln/o= +github.com/jackc/pgtype v1.14.2/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c h1:Dznn52SgVIVst9UyOT9brctYUgxs+CvVfPaC3jKrA50= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v5 v5.5.2 h1:iLlpgp4Cp/gC9Xuscl7lFL1PhhW+ZLtXZcrfCt4C3tA= -github.com/jackc/pgx/v5 v5.5.2/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= +github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= @@ -439,8 +442,6 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c h1:AqsttAyEyIEsNz5WLRwuRwjiT5CMDUfLk6cFJDVPebs= github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -449,8 +450,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= +github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= @@ -538,8 +539,6 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= @@ -575,8 +574,8 @@ github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9 github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.12.1 h1:vm+BA/WZA8QZDp1pF1FWhi5CT3g1tbi5GJmqpb6wnlk= -github.com/multiformats/go-multiaddr v0.12.1/go.mod h1:7mPkiBMmLeFipt+nNSq9pHZUeJSt8lHBgH6yhj0YQzE= +github.com/multiformats/go-multiaddr v0.12.2 h1:9G9sTY/wCYajKa9lyfWPmpZAwe6oV+Wb1zcmMS1HG24= +github.com/multiformats/go-multiaddr v0.12.2/go.mod h1:GKyaTYjZRdcUhyOetrxTk9z0cW+jA/YrnqTOvKgi44M= github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= @@ -654,8 +653,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= -github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -665,8 +664,8 @@ github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7q github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -744,8 +743,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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= @@ -755,8 +754,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= @@ -803,10 +802,10 @@ go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk= go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= -go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= -go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= @@ -818,8 +817,8 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -841,11 +840,11 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -857,8 +856,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -887,8 +886,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -903,7 +902,6 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -946,7 +944,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/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-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -954,17 +951,18 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= 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= @@ -1024,10 +1022,14 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= 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= @@ -1036,8 +1038,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= @@ -1064,10 +1066,10 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/postgres v1.5.4 h1:Iyrp9Meh3GmbSuyIAGyjkN+n9K+GHX9b9MqsTL4EJCo= -gorm.io/driver/postgres v1.5.4/go.mod h1:Bgo89+h0CRcdA33Y6frlaHHVuTdOf87pmyzwW9C/BH0= -gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= -gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= +gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= +gorm.io/gorm v1.25.8 h1:WAGEZ/aEcznN4D03laj8DKnehe1e9gYQAjW8xyPRdeo= +gorm.io/gorm v1.25.8/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/indexer/Dockerfile b/indexer/Dockerfile index 4eb3118e7d4a..ac228dea8659 100644 --- a/indexer/Dockerfile +++ b/indexer/Dockerfile @@ -14,6 +14,7 @@ COPY ./indexer /app/indexer COPY ./op-bindings /app/op-bindings COPY ./op-service /app/op-service COPY ./op-node /app/op-node +COPY ./op-plasma /app/op-plasma COPY ./op-chain-ops /app/op-chain-ops COPY ./go.mod /app/go.mod COPY ./go.sum /app/go.sum diff --git a/indexer/api-ts/package.json b/indexer/api-ts/package.json index 99f9a4581d90..492e2fee3a4b 100644 --- a/indexer/api-ts/package.json +++ b/indexer/api-ts/package.json @@ -16,8 +16,8 @@ "LICENSE" ], "scripts": { - "clean": "rm -rf generated.ts indexer.cjs indexer.js", - "generate": "npm run clean && tygo generate && mv ../api/models/index.ts generated.ts && tsup", + "generate:clean": "rm -rf generated.ts indexer.cjs indexer.js", + "generate": "npm run generate:clean && tygo generate && mv ../api/models/index.ts generated.ts && tsup", "test": "vitest" }, "keywords": [ @@ -34,6 +34,6 @@ }, "devDependencies": { "tsup": "^8.0.1", - "vitest": "^1.0.1" + "vitest": "^1.2.2" } } diff --git a/indexer/api/api_test.go b/indexer/api/api_test.go index 39019a5db7bb..e69a22fbfcf4 100644 --- a/indexer/api/api_test.go +++ b/indexer/api/api_test.go @@ -104,7 +104,7 @@ func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalSum(database.WithdrawFilte } func TestHealthz(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) cfg := &Config{ DB: &TestDBConnector{BridgeTransfers: &MockBridgeTransfersView{}}, HTTPServer: apiConfig, @@ -122,7 +122,7 @@ func TestHealthz(t *testing.T) { } func TestL1BridgeDepositsHandler(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) cfg := &Config{ DB: &TestDBConnector{BridgeTransfers: &MockBridgeTransfersView{}}, HTTPServer: apiConfig, @@ -151,7 +151,7 @@ func TestL1BridgeDepositsHandler(t *testing.T) { } func TestL2BridgeWithdrawalsByAddressHandler(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) cfg := &Config{ DB: &TestDBConnector{BridgeTransfers: &MockBridgeTransfersView{}}, HTTPServer: apiConfig, diff --git a/indexer/cmd/indexer/cli.go b/indexer/cmd/indexer/cli.go index 153cae9da4fc..3e28a681ad42 100644 --- a/indexer/cmd/indexer/cli.go +++ b/indexer/cmd/indexer/cli.go @@ -2,6 +2,8 @@ package main import ( "context" + "fmt" + "math/big" "github.com/urfave/cli/v2" @@ -11,8 +13,10 @@ import ( "github.com/ethereum-optimism/optimism/indexer/api" "github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/database" + "github.com/ethereum-optimism/optimism/indexer/node" "github.com/ethereum-optimism/optimism/op-service/cliapp" oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/optimism/op-service/metrics" "github.com/ethereum-optimism/optimism/op-service/opio" ) @@ -30,11 +34,18 @@ var ( Usage: "path to migrations folder", EnvVars: []string{"INDEXER_MIGRATIONS_DIR"}, } + ReorgFlag = &cli.Uint64Flag{ + Name: "l1-height", + Aliases: []string{"height"}, + Usage: `the lowest l1 height that has been reorg'd. All L1 data and derived L2 state will be deleted. Since not all L1 blocks are + indexed, this will find the maximum indexed height <= the marker, which may result in slightly more deleted state.`, + Required: true, + } ) func runIndexer(ctx *cli.Context, shutdown context.CancelCauseFunc) (cliapp.Lifecycle, error) { log := oplog.NewLogger(oplog.AppOut(ctx), oplog.ReadCLIConfig(ctx)).New("role", "indexer") - oplog.SetGlobalLogHandler(log.GetHandler()) + oplog.SetGlobalLogHandler(log.Handler()) log.Info("running indexer...") cfg, err := config.LoadConfig(log, ctx.String(ConfigFlag.Name)) @@ -48,7 +59,7 @@ func runIndexer(ctx *cli.Context, shutdown context.CancelCauseFunc) (cliapp.Life func runApi(ctx *cli.Context, _ context.CancelCauseFunc) (cliapp.Lifecycle, error) { log := oplog.NewLogger(oplog.AppOut(ctx), oplog.ReadCLIConfig(ctx)).New("role", "api") - oplog.SetGlobalLogHandler(log.GetHandler()) + oplog.SetGlobalLogHandler(log.Handler()) log.Info("running api...") cfg, err := config.LoadConfig(log, ctx.String(ConfigFlag.Name)) @@ -71,7 +82,7 @@ func runMigrations(ctx *cli.Context) error { ctx.Context = opio.CancelOnInterrupt(ctx.Context) log := oplog.NewLogger(oplog.AppOut(ctx), oplog.ReadCLIConfig(ctx)).New("role", "migrations") - oplog.SetGlobalLogHandler(log.GetHandler()) + oplog.SetGlobalLogHandler(log.Handler()) log.Info("running migrations...") cfg, err := config.LoadConfig(log, ctx.String(ConfigFlag.Name)) @@ -91,11 +102,40 @@ func runMigrations(ctx *cli.Context) error { return db.ExecuteSQLMigration(migrationsDir) } +func runReorgDeletion(ctx *cli.Context) error { + fromL1Height := ctx.Uint64(ReorgFlag.Name) + + log := oplog.NewLogger(oplog.AppOut(ctx), oplog.ReadCLIConfig(ctx)).New("role", "reorg-deletion") + oplog.SetGlobalLogHandler(log.Handler()) + cfg, err := config.LoadConfig(log, ctx.String(ConfigFlag.Name)) + if err != nil { + return fmt.Errorf("failed to load config: %w", err) + } + + l1Clnt, err := node.DialEthClient(ctx.Context, cfg.RPCs.L1RPC, node.NewMetrics(metrics.NewRegistry(), "l1")) + if err != nil { + return fmt.Errorf("failed to dial L1 client: %w", err) + } + l1Header, err := l1Clnt.BlockHeaderByNumber(big.NewInt(int64(fromL1Height))) + if err != nil { + return fmt.Errorf("failed to query L1 header at height: %w", err) + } else if l1Header == nil { + return fmt.Errorf("no header found at height") + } + + db, err := database.NewDB(ctx.Context, log, cfg.DB) + if err != nil { + return fmt.Errorf("failed to connect to database: %w", err) + } + + defer db.Close() + return db.Transaction(func(db *database.DB) error { + return db.Blocks.DeleteReorgedState(l1Header.Time) + }) +} + func newCli(GitCommit string, GitDate string) *cli.App { - flags := []cli.Flag{ConfigFlag} - flags = append(flags, oplog.CLIFlags("INDEXER")...) - migrationFlags := []cli.Flag{MigrationsFlag, ConfigFlag} - migrationFlags = append(migrationFlags, oplog.CLIFlags("INDEXER")...) + flags := append([]cli.Flag{ConfigFlag}, oplog.CLIFlags("INDEXER")...) return &cli.App{ Version: params.VersionWithCommit(GitCommit, GitDate), Description: "An indexer of all optimism events with a serving api layer", @@ -115,10 +155,17 @@ func newCli(GitCommit string, GitDate string) *cli.App { }, { Name: "migrate", - Flags: migrationFlags, + Flags: append(flags, MigrationsFlag), Description: "Runs the database migrations", Action: runMigrations, }, + { + Name: "reorg-delete", + Aliases: []string{"reorg"}, + Flags: append(flags, ReorgFlag), + Description: "Deletes data that has been reorg'ed out of the canonical L1 chain", + Action: runReorgDeletion, + }, { Name: "version", Description: "print version", diff --git a/indexer/config/config.go b/indexer/config/config.go index 1c4b2b53310e..813e6c7c5d20 100644 --- a/indexer/config/config.go +++ b/indexer/config/config.go @@ -31,8 +31,9 @@ type L1Contracts struct { SystemConfigProxy common.Address `toml:"system-config"` // rollup state - OptimismPortalProxy common.Address `toml:"optimism-portal"` - L2OutputOracleProxy common.Address `toml:"l2-output-oracle"` + OptimismPortalProxy common.Address `toml:"optimism-portal"` + L2OutputOracleProxy common.Address `toml:"l2-output-oracle"` + DisputeGameFactoryProxy common.Address `toml:"dispute-game-factory"` // bridging L1CrossDomainMessengerProxy common.Address `toml:"l1-cross-domain-messenger"` diff --git a/indexer/config/config_test.go b/indexer/config/config_test.go index fedfe2189196..043016b09512 100644 --- a/indexer/config/config_test.go +++ b/indexer/config/config_test.go @@ -12,7 +12,7 @@ import ( ) func TestLoadConfig(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) tmpfile, err := os.CreateTemp("", "test.toml") require.NoError(t, err) defer os.Remove(tmpfile.Name()) @@ -98,6 +98,7 @@ func TestLoadConfigWithoutPreset(t *testing.T) { l2-output-oracle = "0x42097868233d1aa22e815a266982f2cf17685a27" l1-cross-domain-messenger = "0x420ce71c97B33Cc4729CF772ae268934F7ab5fA1" l1-standard-bridge = "0x4209fc46f92E8a1c0deC1b1747d010903E884bE1" + dispute-game-factory = "0x4209fc46f92E8a1c0deC1b1747d010903E884bE1" [rpcs] l1-rpc = "https://l1.example.com" @@ -112,7 +113,7 @@ func TestLoadConfigWithoutPreset(t *testing.T) { err = tmpfile.Close() require.NoError(t, err) - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) conf, err := LoadConfig(logger, tmpfile.Name()) require.NoError(t, err) @@ -146,7 +147,7 @@ func TestLoadConfigWithUnknownPreset(t *testing.T) { err = tmpfile.Close() require.NoError(t, err) - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) conf, err := LoadConfig(logger, tmpfile.Name()) require.Error(t, err) @@ -178,7 +179,7 @@ func TestLoadConfigPollingValues(t *testing.T) { err = tmpfile.Close() require.NoError(t, err) - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) conf, err := LoadConfig(logger, tmpfile.Name()) require.NoError(t, err) @@ -224,7 +225,7 @@ func TestLoadedConfigPresetPrecendence(t *testing.T) { err = tmpfile.Close() require.NoError(t, err) - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) conf, err := LoadConfig(logger, tmpfile.Name()) require.NoError(t, err) @@ -265,7 +266,7 @@ func TestLocalDevnet(t *testing.T) { err = tmpfile.Close() require.NoError(t, err) - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) conf, err := LoadConfig(logger, tmpfile.Name()) require.NoError(t, err) @@ -276,7 +277,7 @@ func TestLocalDevnet(t *testing.T) { } func TestThrowsOnUnknownKeys(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) tmpfile, err := os.CreateTemp("", "test.toml") require.NoError(t, err) defer os.Remove(tmpfile.Name()) diff --git a/indexer/config/presets.go b/indexer/config/presets.go index 17aa42d2eda1..a812b568e1f6 100644 --- a/indexer/config/presets.go +++ b/indexer/config/presets.go @@ -25,6 +25,7 @@ var Presets = map[int]Preset{ L1CrossDomainMessengerProxy: common.HexToAddress("0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1"), L1StandardBridgeProxy: common.HexToAddress("0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1"), L1ERC721BridgeProxy: common.HexToAddress("0x5a7749f83b81B301cAb5f48EB8516B986DAef23D"), + DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"), // pre-bedrock LegacyCanonicalTransactionChain: common.HexToAddress("0x5e4e65926ba27467555eb562121fac00d24e9dd2"), @@ -49,6 +50,7 @@ var Presets = map[int]Preset{ L1CrossDomainMessengerProxy: common.HexToAddress("0x5086d1eEF304eb5284A0f6720f79403b4e9bE294"), L1StandardBridgeProxy: common.HexToAddress("0x636Af16bf2f682dD3109e60102b8E1A089FedAa8"), L1ERC721BridgeProxy: common.HexToAddress("0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9"), + DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"), // pre-bedrock LegacyCanonicalTransactionChain: common.HexToAddress("0x607F755149cFEB3a14E1Dc3A4E2450Cde7dfb04D"), @@ -73,6 +75,7 @@ var Presets = map[int]Preset{ L1CrossDomainMessengerProxy: common.HexToAddress("0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef"), L1StandardBridgeProxy: common.HexToAddress("0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1"), L1ERC721BridgeProxy: common.HexToAddress("0xd83e03D576d23C9AEab8cC44Fa98d058D2176D1f"), + DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"), }, L1StartingHeight: 4071408, L1ConfirmationDepth: 10, @@ -91,6 +94,7 @@ var Presets = map[int]Preset{ L1CrossDomainMessengerProxy: common.HexToAddress("0x866E82a600A1414e583f7F13623F1aC5d58b0Afa"), L1StandardBridgeProxy: common.HexToAddress("0x3154Cf16ccdb4C6d922629664174b904d80F2C35"), L1ERC721BridgeProxy: common.HexToAddress("0x608d94945A64503E642E6370Ec598e519a2C1E53"), + DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"), }, L1StartingHeight: 17481768, L1ConfirmationDepth: 10, @@ -109,6 +113,7 @@ var Presets = map[int]Preset{ L1CrossDomainMessengerProxy: common.HexToAddress("0x8e5693140eA606bcEB98761d9beB1BC87383706D"), L1StandardBridgeProxy: common.HexToAddress("0xfA6D8Ee5BE770F84FC001D098C4bD604Fe01284a"), L1ERC721BridgeProxy: common.HexToAddress("0x5E0c967457347D5175bF82E8CCCC6480FCD7e568"), + DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"), }, L1StartingHeight: 8410981, L1ConfirmationDepth: 10, @@ -127,6 +132,7 @@ var Presets = map[int]Preset{ L1CrossDomainMessengerProxy: common.HexToAddress("0xC34855F4De64F1840e5686e64278da901e261f20"), L1StandardBridgeProxy: common.HexToAddress("0xfd0Bf71F60660E2f608ed56e1659C450eB113120"), L1ERC721BridgeProxy: common.HexToAddress("0x21eFD066e581FA55Ef105170Cc04d74386a09190"), + DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"), }, L1StartingHeight: 4370868, L1ConfirmationDepth: 10, @@ -145,6 +151,7 @@ var Presets = map[int]Preset{ L1CrossDomainMessengerProxy: common.HexToAddress("0xdC40a14d9abd6F410226f1E6de71aE03441ca506"), L1StandardBridgeProxy: common.HexToAddress("0x3e2Ea9B92B7E48A52296fD261dc26fd995284631"), L1ERC721BridgeProxy: common.HexToAddress("0x83A4521A3573Ca87f3a971B169C5A0E1d34481c3"), + DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"), }, L1StartingHeight: 17473923, L1ConfirmationDepth: 10, @@ -163,6 +170,7 @@ var Presets = map[int]Preset{ L1CrossDomainMessengerProxy: common.HexToAddress("0xD87342e16352D33170557A7dA1e5fB966a60FafC"), L1StandardBridgeProxy: common.HexToAddress("0x7CC09AC2452D6555d5e0C213Ab9E2d44eFbFc956"), L1ERC721BridgeProxy: common.HexToAddress("0x57C1C6b596ce90C0e010c358DD4Aa052404bB70F"), + DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"), }, L1StartingHeight: 8942381, L1ConfirmationDepth: 10, @@ -181,6 +189,7 @@ var Presets = map[int]Preset{ L1CrossDomainMessengerProxy: common.HexToAddress("0x97BAf688E5d0465E149d1d5B497Ca99392a6760e"), L1StandardBridgeProxy: common.HexToAddress("0xD0204B9527C1bA7bD765Fa5CCD9355d38338272b"), L1ERC721BridgeProxy: common.HexToAddress("0xaFF0F8aaB6Cc9108D34b3B8423C76d2AF434d115"), + DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"), }, L1StartingHeight: 17672702, L1ConfirmationDepth: 10, @@ -199,6 +208,7 @@ var Presets = map[int]Preset{ L1CrossDomainMessengerProxy: common.HexToAddress("0x97f3558Ce48FE71B8CeFA5497708A49531D5A8E1"), L1StandardBridgeProxy: common.HexToAddress("0xFaE6abCAF30D23e233AC7faF747F2fC3a5a6Bfa3"), L1ERC721BridgeProxy: common.HexToAddress("0xBA8397B6f255618D5985d0fB427D8c0496F3a5FA"), + DisputeGameFactoryProxy: common.HexToAddress("0x1111111111111111111111111111111111111111"), }, L1StartingHeight: 17672702, L1ConfirmationDepth: 10, diff --git a/indexer/database/blocks.go b/indexer/database/blocks.go index 4a01a216a488..0f89f92e6b3c 100644 --- a/indexer/database/blocks.go +++ b/indexer/database/blocks.go @@ -66,6 +66,8 @@ type BlocksDB interface { StoreL1BlockHeaders([]L1BlockHeader) error StoreL2BlockHeaders([]L2BlockHeader) error + + DeleteReorgedState(uint64) error } /** @@ -173,3 +175,24 @@ func (db *blocksDB) L2LatestBlockHeader() (*L2BlockHeader, error) { return &l2Header, nil } + +// Reorgs + +func (db *blocksDB) DeleteReorgedState(timestamp uint64) error { + db.log.Info("deleting reorg'd state", "from_timestamp", timestamp) + + // Delete reorg'd state. Block deletes cascades to all tables + l1Result := db.gorm.Delete(&L1BlockHeader{}, "timestamp >= ?", timestamp) + if l1Result.Error != nil { + return fmt.Errorf("unable to delete l1 state: %w", l1Result.Error) + } + db.log.Info("L1 blocks (& derived events/tables) deleted", "block_count", l1Result.RowsAffected) + + l2Result := db.gorm.Delete(&L2BlockHeader{}, "timestamp >= ?", timestamp) + if l2Result.Error != nil { + return fmt.Errorf("unable to delete l2 state: %w", l2Result.Error) + } + db.log.Info("L2 blocks (& derived events/tables) deleted", "block_count", l2Result.RowsAffected) + + return nil +} diff --git a/indexer/database/bridge_transactions.go b/indexer/database/bridge_transactions.go index 3cc6741993ec..10482b7e1c27 100644 --- a/indexer/database/bridge_transactions.go +++ b/indexer/database/bridge_transactions.go @@ -188,10 +188,11 @@ func (db *bridgeTransactionsDB) MarkL2TransactionWithdrawalProvenEvent(withdrawa if withdrawal.ProvenL1EventGUID != nil && withdrawal.ProvenL1EventGUID.ID() == provenL1EventGuid.ID() { return nil - } else if withdrawal.ProvenL1EventGUID != nil { - return fmt.Errorf("proven withdrawal %s re-proven with a different event %s", withdrawalHash, provenL1EventGuid) } + // Withdrawals can be re-proven in the event that the claim they were proven against was successfully + // challenged. Rather than track each individual dispute game, we allow the proven event to simply be + // overwritten. withdrawal.ProvenL1EventGUID = &provenL1EventGuid result := db.gorm.Save(&withdrawal) return result.Error diff --git a/indexer/database/mocks.go b/indexer/database/mocks.go index d6005185b1cb..07303c7c1e6c 100644 --- a/indexer/database/mocks.go +++ b/indexer/database/mocks.go @@ -76,6 +76,11 @@ func (m *MockBlocksDB) StoreL2BlockHeaders(headers []L2BlockHeader) error { return args.Error(1) } +func (m *MockBlocksDB) DeleteReorgedState(timestamp uint64) error { + args := m.Called(timestamp) + return args.Error(1) +} + // MockDB is a mock database that can be used for testing type MockDB struct { MockBlocks *MockBlocksDB diff --git a/indexer/e2e_tests/bridge_messages_e2e_test.go b/indexer/e2e_tests/bridge_messages_e2e_test.go index b7960258d7bd..b5a2cbc38856 100644 --- a/indexer/e2e_tests/bridge_messages_e2e_test.go +++ b/indexer/e2e_tests/bridge_messages_e2e_test.go @@ -6,6 +6,8 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" + e2etest_utils "github.com/ethereum-optimism/optimism/indexer/e2e_tests/utils" "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" @@ -34,7 +36,9 @@ func TestE2EBridgeL1CrossDomainMessenger(t *testing.T) { l1Opts.Value = big.NewInt(params.Ether) // (1) Send the Message - sentMsgTx, err := l1CrossDomainMessenger.SendMessage(l1Opts, aliceAddr, calldata, 100_000) + sentMsgTx, err := transactions.PadGasEstimate(l1Opts, 1.2, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return l1CrossDomainMessenger.SendMessage(opts, aliceAddr, calldata, 100_000) + }) require.NoError(t, err) sentMsgReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L1Client, sentMsgTx.Hash()) require.NoError(t, err) @@ -113,7 +117,9 @@ func TestE2EBridgeL2CrossDomainMessenger(t *testing.T) { l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig()) require.NoError(t, err) l1Opts.Value = l2Opts.Value - depositTx, err := optimismPortal.Receive(l1Opts) + depositTx, err := transactions.PadGasEstimate(l1Opts, 1.2, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return optimismPortal.Receive(opts) + }) require.NoError(t, err) depositReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash()) require.NoError(t, err) @@ -124,7 +130,9 @@ func TestE2EBridgeL2CrossDomainMessenger(t *testing.T) { require.NoError(t, err) // (1) Send the Message - sentMsgTx, err := l2CrossDomainMessenger.SendMessage(l2Opts, aliceAddr, calldata, 100_000) + sentMsgTx, err := transactions.PadGasEstimate(l2Opts, 1.2, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return l2CrossDomainMessenger.SendMessage(opts, aliceAddr, calldata, 100_000) + }) require.NoError(t, err) sentMsgReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L2Client, sentMsgTx.Hash()) require.NoError(t, err) @@ -161,7 +169,7 @@ func TestE2EBridgeL2CrossDomainMessenger(t *testing.T) { // (2) Process RelayedMessage on withdrawal finalization require.Nil(t, sentMessage.RelayedMessageEventGUID) - _, finalizedReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, sentMsgReceipt) + _, finalizedReceipt, _, _ := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, sentMsgReceipt) // wait for processor catchup require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { diff --git a/indexer/e2e_tests/bridge_transactions_e2e_test.go b/indexer/e2e_tests/bridge_transactions_e2e_test.go index e5e1a062d8c6..9a3fde152eb7 100644 --- a/indexer/e2e_tests/bridge_transactions_e2e_test.go +++ b/indexer/e2e_tests/bridge_transactions_e2e_test.go @@ -6,6 +6,8 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" + e2etest_utils "github.com/ethereum-optimism/optimism/indexer/e2e_tests/utils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" @@ -37,7 +39,9 @@ func TestE2EBridgeTransactionsOptimismPortalDeposits(t *testing.T) { // In the same deposit transaction, transfer, 0.5ETH to Bob. We do this to ensure we're only indexing // bridged funds from the source address versus any transferred value to a recipient in the same L2 transaction - depositTx, err := optimismPortal.DepositTransaction(l1Opts, bobAddr, big.NewInt(params.Ether/2), 100_000, false, calldata) + depositTx, err := transactions.PadGasEstimate(l1Opts, 1.2, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return optimismPortal.DepositTransaction(opts, bobAddr, big.NewInt(params.Ether/2), 100_000, false, calldata) + }) require.NoError(t, err) depositReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash()) require.NoError(t, err) @@ -92,7 +96,9 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) { l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig()) require.NoError(t, err) l1Opts.Value = l2Opts.Value - depositTx, err := optimismPortal.Receive(l1Opts) + depositTx, err := transactions.PadGasEstimate(l1Opts, 1.2, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return optimismPortal.Receive(opts) + }) require.NoError(t, err) depositReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash()) require.NoError(t, err) @@ -102,7 +108,9 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) { _, err = wait.ForReceiptOK(context.Background(), testSuite.L2Client, depositL2TxHash) require.NoError(t, err) - withdrawTx, err := l2ToL1MessagePasser.InitiateWithdrawal(l2Opts, aliceAddr, big.NewInt(100_000), calldata) + withdrawTx, err := transactions.PadGasEstimate(l2Opts, 1.2, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return l2ToL1MessagePasser.InitiateWithdrawal(opts, aliceAddr, big.NewInt(100_000), calldata) + }) require.NoError(t, err) withdrawReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L2Client, withdrawTx.Hash()) require.NoError(t, err) @@ -155,7 +163,7 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) { // Test Withdrawal Finalized require.Nil(t, withdraw.FinalizedL1EventGUID) - finalizeReceipt := op_e2e.FinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpCfg.Secrets.Alice, proveReceipt, withdrawParams) + finalizeReceipt, _, _ := op_e2e.FinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpCfg.Secrets.Alice, proveReceipt, withdrawParams) require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil @@ -186,7 +194,9 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserFailedWithdrawal(t *testing.T) require.NoError(t, err) l2Opts.Value = big.NewInt(params.Ether) - withdrawTx, err := l2ToL1MessagePasser.InitiateWithdrawal(l2Opts, aliceAddr, big.NewInt(100_000), nil) + withdrawTx, err := transactions.PadGasEstimate(l2Opts, 1.2, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return l2ToL1MessagePasser.InitiateWithdrawal(opts, aliceAddr, big.NewInt(100_000), nil) + }) require.NoError(t, err) withdrawReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L2Client, withdrawTx.Hash()) require.NoError(t, err) @@ -197,7 +207,7 @@ func TestE2EBridgeTransactionsL2ToL1MessagePasserFailedWithdrawal(t *testing.T) require.NoError(t, err) // Prove&Finalize withdrawal - _, finalizeReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, withdrawReceipt) + _, finalizeReceipt, _, _ := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, withdrawReceipt) require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil diff --git a/indexer/e2e_tests/bridge_transfers_e2e_test.go b/indexer/e2e_tests/bridge_transfers_e2e_test.go index d93ae5f20e76..7814d7c53fc8 100644 --- a/indexer/e2e_tests/bridge_transfers_e2e_test.go +++ b/indexer/e2e_tests/bridge_transfers_e2e_test.go @@ -38,7 +38,9 @@ func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) { l1Opts.Value = big.NewInt(params.Ether) // (1) Test Deposit Initiation - depositTx, err := l1StandardBridge.DepositETH(l1Opts, 200_000, []byte{byte(1)}) + depositTx, err := transactions.PadGasEstimate(l1Opts, 1.1, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return l1StandardBridge.DepositETH(opts, 200_000, []byte{byte(1)}) + }) require.NoError(t, err) depositReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash()) require.NoError(t, err) @@ -105,7 +107,9 @@ func TestE2EBridgeTransfersOptimismPortalETHReceive(t *testing.T) { l1Opts.Value = big.NewInt(params.Ether) // (1) Test Deposit Initiation - portalDepositTx, err := optimismPortal.Receive(l1Opts) + portalDepositTx, err := transactions.PadGasEstimate(l1Opts, 1.1, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return optimismPortal.Receive(opts) + }) require.NoError(t, err) portalDepositReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L1Client, portalDepositTx.Hash()) require.NoError(t, err) @@ -238,7 +242,9 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) { l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig()) require.NoError(t, err) l1Opts.Value = l2Opts.Value - depositTx, err := optimismPortal.Receive(l1Opts) + depositTx, err := transactions.PadGasEstimate(l1Opts, 1.2, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return optimismPortal.Receive(opts) + }) require.NoError(t, err) depositReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash()) require.NoError(t, err) @@ -249,7 +255,9 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) { require.NoError(t, err) // (1) Test Withdrawal Initiation - withdrawTx, err := l2StandardBridge.Withdraw(l2Opts, predeploys.LegacyERC20ETHAddr, l2Opts.Value, 200_000, []byte{byte(1)}) + withdrawTx, err := transactions.PadGasEstimate(l2Opts, 1.2, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return l2StandardBridge.Withdraw(opts, predeploys.LegacyERC20ETHAddr, l2Opts.Value, 200_000, []byte{byte(1)}) + }) require.NoError(t, err) withdrawReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L2Client, withdrawTx.Hash()) require.NoError(t, err) @@ -292,7 +300,7 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) { require.Empty(t, aliceWithdrawals.Withdrawals[0].FinalizedL1TransactionHash) // wait for processor catchup - proveReceipt, finalizeReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, withdrawReceipt) + proveReceipt, finalizeReceipt, _, _ := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, withdrawReceipt) require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil @@ -327,7 +335,9 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserETHReceive(t *testing.T) { l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig()) require.NoError(t, err) l1Opts.Value = l2Opts.Value - depositTx, err := optimismPortal.Receive(l1Opts) + depositTx, err := transactions.PadGasEstimate(l1Opts, 1.2, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return optimismPortal.Receive(opts) + }) require.NoError(t, err) depositReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash()) require.NoError(t, err) @@ -338,7 +348,9 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserETHReceive(t *testing.T) { require.NoError(t, err) // (1) Test Withdrawal Initiation - l2ToL1MessagePasserWithdrawTx, err := l2ToL1MessagePasser.Receive(l2Opts) + l2ToL1MessagePasserWithdrawTx, err := transactions.PadGasEstimate(l2Opts, 1.2, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return l2ToL1MessagePasser.Receive(opts) + }) require.NoError(t, err) l2ToL1WithdrawReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L2Client, l2ToL1MessagePasserWithdrawTx.Hash()) require.NoError(t, err) @@ -376,7 +388,7 @@ func TestE2EBridgeTransfersL2ToL1MessagePasserETHReceive(t *testing.T) { require.Empty(t, aliceWithdrawals.Withdrawals[0].FinalizedL1TransactionHash) // wait for processor catchup - proveReceipt, finalizeReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, l2ToL1WithdrawReceipt) + proveReceipt, finalizeReceipt, _, _ := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.OpSys, "sequencer", testSuite.OpCfg.Secrets.Alice, l2ToL1WithdrawReceipt) require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil @@ -532,7 +544,9 @@ func TestClientBridgeFunctions(t *testing.T) { mintSum = new(big.Int).Add(mintSum, depositTx.Value()) // (3.b) Initiate withdrawal transaction via L2ToL1MessagePasser contract - l2ToL1MessagePasserWithdrawTx, err := l2ToL1MessagePasser.Receive(l2Opts) + l2ToL1MessagePasserWithdrawTx, err := transactions.PadGasEstimate(l2Opts, 1.1, func(opts *bind.TransactOpts) (*types.Transaction, error) { + return l2ToL1MessagePasser.Receive(opts) + }) require.NoError(t, err) l2ToL1WithdrawReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L2Client, l2ToL1MessagePasserWithdrawTx.Hash()) require.NoError(t, err) @@ -587,7 +601,7 @@ func TestClientBridgeFunctions(t *testing.T) { s.proven = new(big.Int).Add(s.proven, actor.amt) - finalReceipt := op_e2e.FinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, actor.priv, proveReceipt, params) + finalReceipt, _, _ := op_e2e.FinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, actor.priv, proveReceipt, params) require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header seen := l1Header != nil && l1Header.Number.Uint64() >= finalReceipt.BlockNumber.Uint64() diff --git a/indexer/e2e_tests/etl_e2e_test.go b/indexer/e2e_tests/etl_e2e_test.go index 8d85ae9e77ac..fcde8b653709 100644 --- a/indexer/e2e_tests/etl_e2e_test.go +++ b/indexer/e2e_tests/etl_e2e_test.go @@ -8,7 +8,10 @@ import ( "github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-bindings/bindingspreview" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-node/withdrawals" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -24,9 +27,29 @@ func TestE2EETL(t *testing.T) { l2OutputOracle, err := bindings.NewL2OutputOracle(testSuite.OpCfg.L1Deployments.L2OutputOracleProxy, testSuite.L1Client) require.NoError(t, err) + disputeGameFactory, err := bindings.NewDisputeGameFactoryCaller(testSuite.OpCfg.L1Deployments.DisputeGameFactoryProxy, testSuite.L1Client) + require.NoError(t, err) + + optimismPortal, err := bindingspreview.NewOptimismPortal2Caller(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client) + require.NoError(t, err) + // wait for at least 10 L2 blocks posted on L1 require.NoError(t, wait.For(context.Background(), time.Second, func() (bool, error) { - l2Height, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{Context: context.Background()}) + var l2Height *big.Int + var err error + if e2eutils.UseFPAC() { + gameCount, err := disputeGameFactory.GameCount(&bind.CallOpts{Context: context.Background()}) + require.NoError(t, err) + if gameCount.Cmp(big.NewInt(0)) == 0 { + return false, nil + } + + latestGame, err := withdrawals.FindLatestGame(context.Background(), disputeGameFactory, optimismPortal) + require.NoError(t, err) + l2Height = new(big.Int).SetBytes(latestGame.ExtraData[0:32]) + } else { + l2Height, err = l2OutputOracle.LatestBlockNumber(&bind.CallOpts{Context: context.Background()}) + } return l2Height != nil && l2Height.Uint64() >= 9, err })) diff --git a/indexer/e2e_tests/reorg_e2e_test.go b/indexer/e2e_tests/reorg_e2e_test.go new file mode 100644 index 000000000000..a6245f47426e --- /dev/null +++ b/indexer/e2e_tests/reorg_e2e_test.go @@ -0,0 +1,92 @@ +package e2e_tests + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/indexer/database" + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-bindings/predeploys" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/require" +) + +func TestE2EReorgDeletion(t *testing.T) { + testSuite := createE2ETestSuite(t) + + // Conduct an L1 Deposit/Withdrawal through the standard bridge + // which touches the CDM and root bridge contracts. Thus we'll e2e + // test that the deletes appropriately cascades to all tables + + l1StandardBridge, err := bindings.NewL1StandardBridge(testSuite.OpCfg.L1Deployments.L1StandardBridgeProxy, testSuite.L1Client) + require.NoError(t, err) + l2StandardBridge, err := bindings.NewL2StandardBridge(predeploys.L2StandardBridgeAddr, testSuite.L2Client) + require.NoError(t, err) + + aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice + + l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig()) + require.NoError(t, err) + l2Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L2ChainIDBig()) + require.NoError(t, err) + + l1Opts.Value = big.NewInt(params.Ether) + l2Opts.Value = big.NewInt(params.Ether) + + // wait for an L1 block (depends on an emitted event -- L2OO) to get indexed as a reference point prior to deletion + require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { + latestL1Header, err := testSuite.DB.Blocks.L1LatestBlockHeader() + return latestL1Header != nil, err + })) + + depositTx, err := l1StandardBridge.DepositETH(l1Opts, 200_000, []byte{byte(1)}) + require.NoError(t, err) + depositReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash()) + require.NoError(t, err) + require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { + l1Header := testSuite.Indexer.BridgeProcessor.LastL1Header + return l1Header != nil && l1Header.Number.Uint64() >= depositReceipt.BlockNumber.Uint64(), nil + })) + deposits, err := testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr, "", 1) + require.NoError(t, err) + require.Len(t, deposits.Deposits, 1) + + withdrawTx, err := l2StandardBridge.Withdraw(l2Opts, predeploys.LegacyERC20ETHAddr, l2Opts.Value, 200_000, []byte{byte(1)}) + require.NoError(t, err) + withdrawReceipt, err := wait.ForReceiptOK(context.Background(), testSuite.L2Client, withdrawTx.Hash()) + require.NoError(t, err) + require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { + l2Header := testSuite.Indexer.BridgeProcessor.LastL2Header + return l2Header != nil && l2Header.Number.Uint64() >= withdrawReceipt.BlockNumber.Uint64(), nil + })) + withdrawals, err := testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr, "", 1) + require.NoError(t, err) + require.Len(t, withdrawals.Withdrawals, 1) + + // Stop the indexer and reorg out L1 state from the deposit transaction + // and implicitly the derived L2 state where the withdrawal was initiated + depositBlock, err := testSuite.DB.Blocks.L1BlockHeaderWithFilter(database.BlockHeader{Number: depositReceipt.BlockNumber}) + require.NoError(t, err) + require.NoError(t, testSuite.Indexer.Stop(context.Background())) + require.NoError(t, testSuite.DB.Blocks.DeleteReorgedState(deposits.Deposits[0].L1BridgeDeposit.Tx.Timestamp)) + + // L1 & L2 block state deleted appropriately + latestL1Header, err := testSuite.DB.Blocks.L2LatestBlockHeader() + require.NoError(t, err) + require.True(t, latestL1Header.Timestamp < depositBlock.Timestamp) + latestL2Header, err := testSuite.DB.Blocks.L2LatestBlockHeader() + require.NoError(t, err) + require.True(t, latestL2Header.Timestamp < depositBlock.Timestamp) + + // Deposits/Withdrawals deletes cascade appropriately from log deletion + deposits, err = testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr, "", 1) + require.NoError(t, err) + require.Len(t, deposits.Deposits, 0) + withdrawals, err = testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr, "", 1) + require.NoError(t, err) + require.Len(t, withdrawals.Withdrawals, 0) +} diff --git a/indexer/e2e_tests/setup.go b/indexer/e2e_tests/setup.go index 3049bb658bf3..ae7fc445f9b6 100644 --- a/indexer/e2e_tests/setup.go +++ b/indexer/e2e_tests/setup.go @@ -13,15 +13,17 @@ import ( "github.com/ethereum-optimism/optimism/indexer/client" "github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/database" - "github.com/prometheus/client_golang/prometheus" op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/metrics" "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" _ "github.com/jackc/pgx/v5/stdlib" + "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/require" ) @@ -56,7 +58,7 @@ func init() { // Disable the global logger. Ideally we'd like to dump geth // logs per-test but that's possible when running tests in // parallel as the root logger is shared. - log.Root().SetHandler(log.DiscardHandler()) + oplog.SetGlobalLogHandler(log.DiscardHandler()) } // createE2ETestSuite ... Create a new E2E test suite @@ -69,8 +71,6 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { // to reduce that number of idle routines when paused. t.Parallel() - // Bump up the block times to try minimize resource - // contention when parallel devnets are running opCfg := op_e2e.DefaultSystemConfig(t) // Unless specified, omit logs emitted by the various components @@ -78,8 +78,7 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { t.Log("set env 'ENABLE_ROLLUP_LOGS' to show rollup logs") for name := range opCfg.Loggers { t.Logf("discarding logs for %s", name) - noopLog := log.New() - noopLog.SetHandler(log.DiscardHandler()) + noopLog := log.NewLogger(log.DiscardHandler()) opCfg.Loggers[name] = noopLog } } @@ -108,13 +107,14 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { L1CrossDomainMessengerProxy: opCfg.L1Deployments.L1CrossDomainMessengerProxy, L1StandardBridgeProxy: opCfg.L1Deployments.L1StandardBridgeProxy, L1ERC721BridgeProxy: opCfg.L1Deployments.L1ERC721BridgeProxy, + DisputeGameFactoryProxy: opCfg.L1Deployments.DisputeGameFactoryProxy, }, }, HTTPServer: config.ServerConfig{Host: "127.0.0.1", Port: 0}, MetricsServer: config.ServerConfig{Host: "127.0.0.1", Port: 0}, } - indexerLog := testlog.Logger(t, log.LvlInfo).New("role", "indexer") + indexerLog := testlog.Logger(t, log.LevelInfo).New("role", "indexer") ix, err := indexer.NewIndexer(context.Background(), indexerLog, indexerCfg, func(cause error) { if cause != nil { t.Fatalf("indexer shut down with critical error: %v", cause) @@ -122,14 +122,17 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { }) require.NoError(t, err) require.NoError(t, ix.Start(context.Background()), "cleanly start indexer") - t.Cleanup(func() { - require.NoError(t, ix.Stop(context.Background()), "cleanly shut down indexer") - }) + t.Cleanup(func() { require.NoError(t, ix.Stop(context.Background())) }) + + dbLog := testlog.Logger(t, log.LvlInfo).New("role", "db") + db, err := database.NewDB(context.Background(), dbLog, indexerCfg.DB) + require.NoError(t, err) + t.Cleanup(func() { db.Close() }) // API Configuration and Start - apiLog := testlog.Logger(t, log.LvlInfo).New("role", "indexer_api") + apiLog := testlog.Logger(t, log.LevelInfo).New("role", "indexer_api") apiCfg := &api.Config{ - DB: &api.TestDBConnector{BridgeTransfers: ix.DB.BridgeTransfers}, // reuse the same DB + DB: &api.TestDBConnector{BridgeTransfers: db.BridgeTransfers}, // reuse the same DB HTTPServer: config.ServerConfig{Host: "127.0.0.1", Port: 0}, MetricsServer: config.ServerConfig{Host: "127.0.0.1", Port: 0}, } @@ -151,7 +154,7 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { t: t, MetricsRegistry: metrics.NewRegistry(), Client: client, - DB: ix.DB, + DB: db, Indexer: ix, OpCfg: &opCfg, OpSys: opSys, @@ -186,8 +189,7 @@ func setupTestDatabase(t *testing.T) string { Password: "", } - noopLog := log.New() - noopLog.SetHandler(log.DiscardHandler()) + noopLog := log.NewLogger(log.DiscardHandler()) db, err := database.NewDB(context.Background(), noopLog, dbConfig) require.NoError(t, err) defer db.Close() diff --git a/indexer/etl/l1_etl_test.go b/indexer/etl/l1_etl_test.go index 7ae204afe123..e57f16f6fd92 100644 --- a/indexer/etl/l1_etl_test.go +++ b/indexer/etl/l1_etl_test.go @@ -105,7 +105,7 @@ func TestL1ETLConstruction(t *testing.T) { t.Run(test.name, func(t *testing.T) { ts := test.construction() - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) cfg := Config{StartHeight: ts.start} etl, err := NewL1ETL(cfg, logger, ts.db.DB, etlMetrics, ts.client, ts.contracts, func(cause error) { diff --git a/indexer/indexer.go b/indexer/indexer.go index b1a9aadd204a..639871d018d1 100644 --- a/indexer/indexer.go +++ b/indexer/indexer.go @@ -80,6 +80,10 @@ func (ix *Indexer) Start(ctx context.Context) error { } func (ix *Indexer) Stop(ctx context.Context) error { + if ix.stopped.Load() { + return nil + } + var result error if ix.L1ETL != nil { @@ -128,9 +132,7 @@ func (ix *Indexer) Stop(ctx context.Context) error { } ix.stopped.Store(true) - ix.log.Info("indexer stopped") - return result } diff --git a/indexer/migrations/20230523_create_schema.sql b/indexer/migrations/20230523_create_schema.sql index 36641b21009b..7176c055bc3f 100644 --- a/indexer/migrations/20230523_create_schema.sql +++ b/indexer/migrations/20230523_create_schema.sql @@ -119,7 +119,10 @@ CREATE TABLE IF NOT EXISTS l2_transaction_withdrawals ( nonce UINT256 NOT NULL UNIQUE, initiated_l2_event_guid VARCHAR NOT NULL UNIQUE REFERENCES l2_contract_events(guid) ON DELETE CASCADE, - -- Multistep (bedrock) process of a withdrawal + -- Multistep (bedrock) process of a withdrawal. With permissionless-output proposals, `proven_l1_event_guid` + -- should be treated as the last known proven event. It may be the case (rare) that the proven state of this + -- withdrawal was invalidated via a fault proof. This case is considered "rare" a malicious outputs are + -- disincentivezed via the posted bond. proven_l1_event_guid VARCHAR UNIQUE REFERENCES l1_contract_events(guid) ON DELETE SET NULL ON UPDATE CASCADE, finalized_l1_event_guid VARCHAR UNIQUE REFERENCES l1_contract_events(guid) ON DELETE SET NULL ON UPDATE CASCADE, succeeded BOOLEAN, diff --git a/indexer/ops/docs/troubleshooting.md b/indexer/ops/docs/troubleshooting.md index 72b06b12bff1..3147b57e3145 100644 --- a/indexer/ops/docs/troubleshooting.md +++ b/indexer/ops/docs/troubleshooting.md @@ -18,7 +18,7 @@ This document provides a set of troubleshooting steps for common failure scenari Header traversal is a client abstraction that allows the indexer to sequentially traverse the chain via batches of blocks. The following are some common failure modes and how to resolve them: 1. `the HeaderTraversal and provider have diverged in state` This error occurs when the indexer is operating on a different block state than the node. This is typically caused by network reorgs and is the result of `l1-confirmation-depth` or `l2-confirmation-depth` values being set too low. To resolve this issue, - * Delete L1/L2 blocks in the database back to a last known valid height + * Delete blocks in the database back to a last known valid L1 height. See the `reorg-delete` command available in the cli that'll appropriately conduct the deletions. * Increase confirmation depth values * Restart the indexer diff --git a/indexer/processors/bridge/l1_bridge_processor.go b/indexer/processors/bridge/l1_bridge_processor.go index 826f49e3cd4e..80c0f829732d 100644 --- a/indexer/processors/bridge/l1_bridge_processor.go +++ b/indexer/processors/bridge/l1_bridge_processor.go @@ -170,6 +170,10 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metrics L1M return fmt.Errorf("missing indexed withdrawal! tx_hash = %s", provenWithdrawal.Event.TransactionHash) } + if withdrawal.ProvenL1EventGUID != nil && withdrawal.ProvenL1EventGUID.ID() != provenWithdrawals[i].Event.GUID.ID() { + log.Info("detected re-proven withdrawal", "tx_hash", provenWithdrawal.Event.TransactionHash.String()) + } + if err := db.BridgeTransactions.MarkL2TransactionWithdrawalProvenEvent(provenWithdrawal.WithdrawalHash, provenWithdrawals[i].Event.GUID); err != nil { return fmt.Errorf("failed to mark withdrawal as proven. tx_hash = %s: %w", provenWithdrawal.Event.TransactionHash, err) } diff --git a/op-batcher/batcher/batch_submitter.go b/op-batcher/batcher/batch_submitter.go index 8590d84b6a3d..a35b9ad1a186 100644 --- a/op-batcher/batcher/batch_submitter.go +++ b/op-batcher/batcher/batch_submitter.go @@ -25,7 +25,7 @@ func Main(version string) cliapp.LifecycleAction { } l := oplog.NewLogger(oplog.AppOut(cliCtx), cfg.LogConfig) - oplog.SetGlobalLogHandler(l.GetHandler()) + oplog.SetGlobalLogHandler(l.Handler()) opservice.ValidateEnvVars(flags.EnvVarPrefix, flags.Flags, l) l.Info("Initializing Batch Submitter") diff --git a/op-batcher/batcher/channel.go b/op-batcher/batcher/channel.go index ef327c184a97..0aaa194a73c4 100644 --- a/op-batcher/batcher/channel.go +++ b/op-batcher/batcher/channel.go @@ -12,7 +12,7 @@ import ( "github.com/ethereum/go-ethereum/log" ) -// channel is a lightweight wrapper around a channelBuilder which keeps track of pending +// channel is a lightweight wrapper around a ChannelBuilder which keeps track of pending // and confirmed transactions for a single channel. type channel struct { log log.Logger @@ -20,11 +20,11 @@ type channel struct { cfg ChannelConfig // pending channel builder - channelBuilder *channelBuilder - // Set of unconfirmed txID -> frame data. For tx resubmission - pendingTransactions map[txID]txData + channelBuilder *ChannelBuilder + // Set of unconfirmed txID -> tx data. For tx resubmission + pendingTransactions map[string]txData // Set of confirmed txID -> inclusion block. For determining if the channel is timed out - confirmedTransactions map[txID]eth.BlockID + confirmedTransactions map[string]eth.BlockID // True if confirmed TX list is updated. Set to false after updated min/max inclusion blocks. confirmedTxUpdated bool @@ -34,30 +34,31 @@ type channel struct { maxInclusionBlock uint64 } -func newChannel(log log.Logger, metr metrics.Metricer, cfg ChannelConfig, rollupCfg *rollup.Config) (*channel, error) { - cb, err := newChannelBuilder(cfg, *rollupCfg) +func newChannel(log log.Logger, metr metrics.Metricer, cfg ChannelConfig, rollupCfg *rollup.Config, latestL1OriginBlockNum uint64) (*channel, error) { + cb, err := NewChannelBuilder(cfg, *rollupCfg, latestL1OriginBlockNum) if err != nil { return nil, fmt.Errorf("creating new channel: %w", err) } + return &channel{ log: log, metr: metr, cfg: cfg, channelBuilder: cb, - pendingTransactions: make(map[txID]txData), - confirmedTransactions: make(map[txID]eth.BlockID), + pendingTransactions: make(map[string]txData), + confirmedTransactions: make(map[string]eth.BlockID), }, nil } // TxFailed records a transaction as failed. It will attempt to resubmit the data // in the failed transaction. -func (s *channel) TxFailed(id txID) { +func (s *channel) TxFailed(id string) { if data, ok := s.pendingTransactions[id]; ok { s.log.Trace("marked transaction as failed", "id", id) // Note: when the batcher is changed to send multiple frames per tx, // this needs to be changed to iterate over all frames of the tx data // and re-queue them. - s.channelBuilder.PushFrame(data.Frame()) + s.channelBuilder.PushFrames(data.Frames()...) delete(s.pendingTransactions, id) } else { s.log.Warn("unknown transaction marked as failed", "id", id) @@ -70,7 +71,7 @@ func (s *channel) TxFailed(id txID) { // a channel have been marked as confirmed on L1 the channel may be invalid & need to be // resubmitted. // This function may reset the pending channel if the pending channel has timed out. -func (s *channel) TxConfirmed(id txID, inclusionBlock eth.BlockID) (bool, []*types.Block) { +func (s *channel) TxConfirmed(id string, inclusionBlock eth.BlockID) (bool, []*types.Block) { s.metr.RecordBatchTxSubmitted() s.log.Debug("marked transaction as confirmed", "id", id, "block", inclusionBlock) if _, ok := s.pendingTransactions[id]; !ok { @@ -101,6 +102,11 @@ func (s *channel) TxConfirmed(id txID, inclusionBlock eth.BlockID) (bool, []*typ return false, nil } +// Timeout returns the channel timeout L1 block number. If there is no timeout set, it returns 0. +func (s *channel) Timeout() uint64 { + return s.channelBuilder.Timeout() +} + // updateInclusionBlocks finds the first & last confirmed tx and saves its inclusion numbers func (s *channel) updateInclusionBlocks() { if len(s.confirmedTransactions) == 0 || !s.confirmedTxUpdated { @@ -146,20 +152,33 @@ func (s *channel) ID() derive.ChannelID { return s.channelBuilder.ID() } +// NextTxData returns the next tx data packet. +// If cfg.MultiFrameTxs is false, it returns txData with a single frame. +// If cfg.MultiFrameTxs is true, it will read frames from its channel builder +// until it either doesn't have more frames or the target number of frames is reached. +// +// NextTxData should only be called after HasTxData returned true. func (s *channel) NextTxData() txData { - frame := s.channelBuilder.NextFrame() - - txdata := txData{frame} - id := txdata.ID() + nf := s.cfg.MaxFramesPerTx() + txdata := txData{frames: make([]frameData, 0, nf)} + for i := 0; i < nf && s.channelBuilder.HasFrame(); i++ { + frame := s.channelBuilder.NextFrame() + txdata.frames = append(txdata.frames, frame) + } - s.log.Trace("returning next tx data", "id", id) + id := txdata.ID().String() + s.log.Debug("returning next tx data", "id", id, "num_frames", len(txdata.frames)) s.pendingTransactions[id] = txdata return txdata } -func (s *channel) HasFrame() bool { - return s.channelBuilder.HasFrame() +func (s *channel) HasTxData() bool { + if s.IsFull() || !s.cfg.MultiFrameTxs { + return s.channelBuilder.HasFrame() + } + // collect enough frames if channel is not full yet + return s.channelBuilder.PendingFrames() >= int(s.cfg.MaxFramesPerTx()) } func (s *channel) IsFull() bool { @@ -170,8 +189,8 @@ func (s *channel) FullErr() error { return s.channelBuilder.FullErr() } -func (s *channel) RegisterL1Block(l1BlockNum uint64) { - s.channelBuilder.RegisterL1Block(l1BlockNum) +func (s *channel) CheckTimeout(l1BlockNum uint64) { + s.channelBuilder.CheckTimeout(l1BlockNum) } func (s *channel) AddBlock(block *types.Block) (*derive.L1BlockInfo, error) { @@ -202,6 +221,11 @@ func (s *channel) OutputFrames() error { return s.channelBuilder.OutputFrames() } +// LatestL1Origin returns the latest L1 block origin from all the L2 blocks that have been added to the channel +func (c *channel) LatestL1Origin() eth.BlockID { + return c.channelBuilder.LatestL1Origin() +} + func (s *channel) Close() { s.channelBuilder.Close() } diff --git a/op-batcher/batcher/channel_builder.go b/op-batcher/batcher/channel_builder.go index d1e84b98cc40..b55071f46908 100644 --- a/op-batcher/batcher/channel_builder.go +++ b/op-batcher/batcher/channel_builder.go @@ -7,9 +7,9 @@ import ( "io" "math" - "github.com/ethereum-optimism/optimism/op-batcher/compressor" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/core/types" ) @@ -34,66 +34,6 @@ func (e *ChannelFullError) Unwrap() error { return e.Err } -type ChannelConfig struct { - // Number of epochs (L1 blocks) per sequencing window, including the epoch - // L1 origin block itself - SeqWindowSize uint64 - // The maximum number of L1 blocks that the inclusion transactions of a - // channel's frames can span. - ChannelTimeout uint64 - - // Builder Config - - // MaxChannelDuration is the maximum duration (in #L1-blocks) to keep the - // channel open. This allows control over how long a channel is kept open - // during times of low transaction volume. - // - // If 0, duration checks are disabled. - MaxChannelDuration uint64 - // The batcher tx submission safety margin (in #L1-blocks) to subtract from - // a channel's timeout and sequencing window, to guarantee safe inclusion of - // a channel on L1. - SubSafetyMargin uint64 - // The maximum byte-size a frame can have. - MaxFrameSize uint64 - - // CompressorConfig contains the configuration for creating new compressors. - CompressorConfig compressor.Config - - // BatchType indicates whether the channel uses SingularBatch or SpanBatch. - BatchType uint -} - -// Check validates the [ChannelConfig] parameters. -func (cc *ChannelConfig) Check() error { - // The [ChannelTimeout] must be larger than the [SubSafetyMargin]. - // Otherwise, new blocks would always be considered timed out. - if cc.ChannelTimeout < cc.SubSafetyMargin { - return ErrInvalidChannelTimeout - } - - // If the [MaxFrameSize] is set to 0, the channel builder - // will infinitely loop when trying to create frames in the - // [channelBuilder.OutputFrames] function. - if cc.MaxFrameSize == 0 { - return errors.New("max frame size cannot be zero") - } - - // If the [MaxFrameSize] is less than [FrameV0OverHeadSize], the channel - // out will underflow the maxSize variable in the [derive.ChannelOut]. - // Since it is of type uint64, it will wrap around to a very large - // number, making the frame size extremely large. - if cc.MaxFrameSize < derive.FrameV0OverHeadSize { - return fmt.Errorf("max frame size %d is less than the minimum 23", cc.MaxFrameSize) - } - - if cc.BatchType > derive.SpanBatchType { - return fmt.Errorf("unrecognized batch type: %d", cc.BatchType) - } - - return nil -} - type frameID struct { chID derive.ChannelID frameNumber uint16 @@ -104,9 +44,9 @@ type frameData struct { id frameID } -// channelBuilder uses a ChannelOut to create a channel with output frame +// ChannelBuilder uses a ChannelOut to create a channel with output frame // size approximation. -type channelBuilder struct { +type ChannelBuilder struct { cfg ChannelConfig rollupCfg rollup.Config @@ -126,6 +66,8 @@ type channelBuilder struct { co derive.ChannelOut // list of blocks in the channel. Saved in case the channel must be rebuilt blocks []*types.Block + // latestL1Origin is the latest L1 origin of all the L2 blocks that have been added to the channel + latestL1Origin eth.BlockID // frames data queue, to be send as txs frames []frameData // total frames counter @@ -136,7 +78,7 @@ type channelBuilder struct { // newChannelBuilder creates a new channel builder or returns an error if the // channel out could not be created. -func newChannelBuilder(cfg ChannelConfig, rollupCfg rollup.Config) (*channelBuilder, error) { +func NewChannelBuilder(cfg ChannelConfig, rollupCfg rollup.Config, latestL1OriginBlockNum uint64) (*ChannelBuilder, error) { c, err := cfg.CompressorConfig.NewCompressor() if err != nil { return nil, err @@ -150,46 +92,45 @@ func newChannelBuilder(cfg ChannelConfig, rollupCfg rollup.Config) (*channelBuil return nil, err } - return &channelBuilder{ + cb := &ChannelBuilder{ cfg: cfg, rollupCfg: rollupCfg, co: co, - }, nil + } + + cb.updateDurationTimeout(latestL1OriginBlockNum) + + return cb, nil } -func (c *channelBuilder) ID() derive.ChannelID { +func (c *ChannelBuilder) ID() derive.ChannelID { return c.co.ID() } // InputBytes returns the total amount of input bytes added to the channel. -func (c *channelBuilder) InputBytes() int { +func (c *ChannelBuilder) InputBytes() int { return c.co.InputBytes() } // ReadyBytes returns the amount of bytes ready in the compression pipeline to // output into a frame. -func (c *channelBuilder) ReadyBytes() int { +func (c *ChannelBuilder) ReadyBytes() int { return c.co.ReadyBytes() } -func (c *channelBuilder) OutputBytes() int { +func (c *ChannelBuilder) OutputBytes() int { return c.outputBytes } // Blocks returns a backup list of all blocks that were added to the channel. It // can be used in case the channel needs to be rebuilt. -func (c *channelBuilder) Blocks() []*types.Block { +func (c *ChannelBuilder) Blocks() []*types.Block { return c.blocks } -// Reset resets the internal state of the channel builder so that it can be -// reused. Note that a new channel id is also generated by Reset. -func (c *channelBuilder) Reset() error { - c.blocks = c.blocks[:0] - c.frames = c.frames[:0] - c.timeout = 0 - c.fullErr = nil - return c.co.Reset() +// LatestL1Origin returns the latest L1 block origin from all the L2 blocks that have been added to the channel +func (c *ChannelBuilder) LatestL1Origin() eth.BlockID { + return c.latestL1Origin } // AddBlock adds a block to the channel compression pipeline. IsFull should be @@ -203,7 +144,7 @@ func (c *channelBuilder) Reset() error { // first transaction for subsequent use by the caller. // // Call OutputFrames() afterwards to create frames. -func (c *channelBuilder) AddBlock(block *types.Block) (*derive.L1BlockInfo, error) { +func (c *ChannelBuilder) AddBlock(block *types.Block) (*derive.L1BlockInfo, error) { if c.IsFull() { return nil, c.FullErr() } @@ -219,9 +160,17 @@ func (c *channelBuilder) AddBlock(block *types.Block) (*derive.L1BlockInfo, erro } else if err != nil { return l1info, fmt.Errorf("adding block to channel out: %w", err) } + c.blocks = append(c.blocks, block) c.updateSwTimeout(batch) + if l1info.Number > c.latestL1Origin.Number { + c.latestL1Origin = eth.BlockID{ + Hash: l1info.BlockHash, + Number: l1info.Number, + } + } + if err = c.co.FullErr(); err != nil { c.setFullErr(err) // Adding this block still worked, so don't return error, just mark as full @@ -232,19 +181,15 @@ func (c *channelBuilder) AddBlock(block *types.Block) (*derive.L1BlockInfo, erro // Timeout management -// RegisterL1Block should be called whenever a new L1-block is seen. -// -// It ensures proper tracking of all possible timeouts (max channel duration, -// close to consensus channel timeout, close to end of sequencing window). -func (c *channelBuilder) RegisterL1Block(l1BlockNum uint64) { - c.updateDurationTimeout(l1BlockNum) - c.checkTimeout(l1BlockNum) +// Timeout returns the block number of the channel timeout. If no timeout is set it returns 0 +func (c *ChannelBuilder) Timeout() uint64 { + return c.timeout } // FramePublished should be called whenever a frame of this channel got // published with the L1-block number of the block that the frame got included // in. -func (c *channelBuilder) FramePublished(l1BlockNum uint64) { +func (c *ChannelBuilder) FramePublished(l1BlockNum uint64) { timeout := l1BlockNum + c.cfg.ChannelTimeout - c.cfg.SubSafetyMargin c.updateTimeout(timeout, ErrChannelTimeoutClose) } @@ -254,7 +199,7 @@ func (c *channelBuilder) FramePublished(l1BlockNum uint64) { // forward if the derived timeout is earlier than the currently set timeout. // // It does nothing if the max channel duration is set to 0. -func (c *channelBuilder) updateDurationTimeout(l1BlockNum uint64) { +func (c *ChannelBuilder) updateDurationTimeout(l1BlockNum uint64) { if c.cfg.MaxChannelDuration == 0 { return } @@ -266,7 +211,7 @@ func (c *channelBuilder) updateDurationTimeout(l1BlockNum uint64) { // derived from the batch's origin L1 block. The timeout is only moved forward // if the derived sequencer window timeout is earlier than the currently set // timeout. -func (c *channelBuilder) updateSwTimeout(batch *derive.SingularBatch) { +func (c *ChannelBuilder) updateSwTimeout(batch *derive.SingularBatch) { timeout := uint64(batch.EpochNum) + c.cfg.SeqWindowSize - c.cfg.SubSafetyMargin c.updateTimeout(timeout, ErrSeqWindowClose) } @@ -276,30 +221,30 @@ func (c *channelBuilder) updateSwTimeout(batch *derive.SingularBatch) { // // If the timeout is updated, the provided reason will be set as the channel // full error reason in case the timeout is hit in the future. -func (c *channelBuilder) updateTimeout(timeoutBlockNum uint64, reason error) { +func (c *ChannelBuilder) updateTimeout(timeoutBlockNum uint64, reason error) { if c.timeout == 0 || c.timeout > timeoutBlockNum { c.timeout = timeoutBlockNum c.timeoutReason = reason } } -// checkTimeout checks if the channel is timed out at the given block number and +// CheckTimeout checks if the channel is timed out at the given block number and // in this case marks the channel as full, if it wasn't full already. -func (c *channelBuilder) checkTimeout(blockNum uint64) { - if !c.IsFull() && c.TimedOut(blockNum) { +func (c *ChannelBuilder) CheckTimeout(l1BlockNum uint64) { + if !c.IsFull() && c.TimedOut(l1BlockNum) { c.setFullErr(c.timeoutReason) } } // TimedOut returns whether the passed block number is after the timeout block // number. If no block timeout is set yet, it returns false. -func (c *channelBuilder) TimedOut(blockNum uint64) bool { +func (c *ChannelBuilder) TimedOut(blockNum uint64) bool { return c.timeout != 0 && blockNum >= c.timeout } // IsFull returns whether the channel is full. // FullErr returns the reason for the channel being full. -func (c *channelBuilder) IsFull() bool { +func (c *ChannelBuilder) IsFull() bool { return c.fullErr != nil } @@ -317,11 +262,11 @@ func (c *channelBuilder) IsFull() bool { // - ErrChannelTimeoutClose if the consensus channel timeout got too close, // - ErrSeqWindowClose if the end of the sequencer window got too close, // - ErrTerminated if the channel was explicitly terminated. -func (c *channelBuilder) FullErr() error { +func (c *ChannelBuilder) FullErr() error { return c.fullErr } -func (c *channelBuilder) setFullErr(err error) { +func (c *ChannelBuilder) setFullErr(err error) { c.fullErr = &ChannelFullError{Err: err} } @@ -333,7 +278,7 @@ func (c *channelBuilder) setFullErr(err error) { // pull readily available frames from the compression output. // If it is full, the channel is closed and all remaining // frames will be created, possibly with a small leftover frame. -func (c *channelBuilder) OutputFrames() error { +func (c *ChannelBuilder) OutputFrames() error { if c.IsFull() { err := c.closeAndOutputAllFrames() if err != nil { @@ -349,10 +294,10 @@ func (c *channelBuilder) OutputFrames() error { // // This is part of an optimization to already generate frames and send them off // as txs while still collecting blocks in the channel builder. -func (c *channelBuilder) outputReadyFrames() error { - // TODO: Decide whether we want to fill frames to max size and use target - // only for estimation, or use target size. - for c.co.ReadyBytes() >= int(c.cfg.MaxFrameSize) { +func (c *ChannelBuilder) outputReadyFrames() error { + // When creating a frame from the ready compression data, the frame overhead + // will be added to the total output size, so we can add it in the condition. + for c.co.ReadyBytes()+derive.FrameV0OverHeadSize >= int(c.cfg.MaxFrameSize) { if err := c.outputFrame(); err == io.EOF { return nil } else if err != nil { @@ -362,7 +307,7 @@ func (c *channelBuilder) outputReadyFrames() error { return nil } -func (c *channelBuilder) closeAndOutputAllFrames() error { +func (c *ChannelBuilder) closeAndOutputAllFrames() error { if err := c.co.Close(); err != nil { return fmt.Errorf("closing channel out: %w", err) } @@ -379,7 +324,7 @@ func (c *channelBuilder) closeAndOutputAllFrames() error { // outputFrame creates one new frame and adds it to the frames queue. // Note that compressed output data must be available on the underlying // ChannelOut, or an empty frame will be produced. -func (c *channelBuilder) outputFrame() error { +func (c *ChannelBuilder) outputFrame() error { var buf bytes.Buffer fn, err := c.co.OutputFrame(&buf, c.cfg.MaxFrameSize) if err != io.EOF && err != nil { @@ -409,7 +354,7 @@ func (c *channelBuilder) outputFrame() error { // Close immediately marks the channel as full with an ErrTerminated // if the channel is not already full. -func (c *channelBuilder) Close() { +func (c *ChannelBuilder) Close() { if !c.IsFull() { c.setFullErr(ErrTerminated) } @@ -417,7 +362,7 @@ func (c *channelBuilder) Close() { // TotalFrames returns the total number of frames that were created in this channel so far. // It does not decrease when the frames queue is being emptied. -func (c *channelBuilder) TotalFrames() int { +func (c *ChannelBuilder) TotalFrames() int { return c.numFrames } @@ -426,20 +371,20 @@ func (c *channelBuilder) TotalFrames() int { // // Call OutputFrames before to create new frames from the channel out // compression pipeline. -func (c *channelBuilder) HasFrame() bool { +func (c *ChannelBuilder) HasFrame() bool { return len(c.frames) > 0 } // PendingFrames returns the number of pending frames in the frames queue. // It is larger zero iff HasFrames() returns true. -func (c *channelBuilder) PendingFrames() int { +func (c *ChannelBuilder) PendingFrames() int { return len(c.frames) } // NextFrame returns the next available frame. // HasFrame must be called prior to check if there's a next frame available. // Panics if called when there's no next frame. -func (c *channelBuilder) NextFrame() frameData { +func (c *ChannelBuilder) NextFrame() frameData { if len(c.frames) == 0 { panic("no next frame") } @@ -449,11 +394,13 @@ func (c *channelBuilder) NextFrame() frameData { return f } -// PushFrame adds the frame back to the internal frames queue. Panics if not of +// PushFrames adds the frames back to the internal frames queue. Panics if not of // the same channel. -func (c *channelBuilder) PushFrame(frame frameData) { - if frame.id.chID != c.ID() { - panic("wrong channel") +func (c *ChannelBuilder) PushFrames(frames ...frameData) { + for _, f := range frames { + if f.id.chID != c.ID() { + panic("wrong channel") + } + c.frames = append(c.frames, f) } - c.frames = append(c.frames, frame) } diff --git a/op-batcher/batcher/channel_builder_test.go b/op-batcher/batcher/channel_builder_test.go index 734725d18a4a..4c428ee31f9e 100644 --- a/op-batcher/batcher/channel_builder_test.go +++ b/op-batcher/batcher/channel_builder_test.go @@ -3,13 +3,11 @@ package batcher import ( "bytes" "errors" - "fmt" "math" "math/big" "math/rand" "testing" - "github.com/ethereum-optimism/optimism/op-batcher/compressor" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" dtest "github.com/ethereum-optimism/optimism/op-node/rollup/derive/test" @@ -21,103 +19,16 @@ import ( "github.com/stretchr/testify/require" ) -var defaultTestChannelConfig = ChannelConfig{ - SeqWindowSize: 15, - ChannelTimeout: 40, - MaxChannelDuration: 1, - SubSafetyMargin: 4, - MaxFrameSize: 120000, - CompressorConfig: compressor.Config{ - TargetFrameSize: 100000, - TargetNumFrames: 1, - ApproxComprRatio: 0.4, - }, - BatchType: derive.SingularBatchType, -} +const latestL1BlockOrigin = 10 var defaultTestRollupConfig = rollup.Config{ Genesis: rollup.Genesis{L2: eth.BlockID{Number: 0}}, L2ChainID: big.NewInt(1234), } -// TestChannelConfig_Check tests the [ChannelConfig] [Check] function. -func TestChannelConfig_Check(t *testing.T) { - type test struct { - input ChannelConfig - assertion func(error) - } - - // Construct test cases that test the boundary conditions - zeroChannelConfig := defaultTestChannelConfig - zeroChannelConfig.MaxFrameSize = 0 - timeoutChannelConfig := defaultTestChannelConfig - timeoutChannelConfig.ChannelTimeout = 0 - timeoutChannelConfig.SubSafetyMargin = 1 - tests := []test{ - { - input: defaultTestChannelConfig, - assertion: func(output error) { - require.NoError(t, output) - }, - }, - { - input: timeoutChannelConfig, - assertion: func(output error) { - require.ErrorIs(t, output, ErrInvalidChannelTimeout) - }, - }, - { - input: zeroChannelConfig, - assertion: func(output error) { - require.EqualError(t, output, "max frame size cannot be zero") - }, - }, - } - for i := 1; i < derive.FrameV0OverHeadSize; i++ { - smallChannelConfig := defaultTestChannelConfig - smallChannelConfig.MaxFrameSize = uint64(i) - expectedErr := fmt.Sprintf("max frame size %d is less than the minimum 23", i) - tests = append(tests, test{ - input: smallChannelConfig, - assertion: func(output error) { - require.EqualError(t, output, expectedErr) - }, - }) - } - - // Run the table tests - for _, test := range tests { - test.assertion(test.input.Check()) - } -} - -// FuzzChannelConfig_CheckTimeout tests the [ChannelConfig] [Check] function -// with fuzzing to make sure that a [ErrInvalidChannelTimeout] is thrown when -// the [ChannelTimeout] is less than the [SubSafetyMargin]. -func FuzzChannelConfig_CheckTimeout(f *testing.F) { - for i := range [10]int{} { - f.Add(uint64(i+1), uint64(i)) - } - f.Fuzz(func(t *testing.T, channelTimeout uint64, subSafetyMargin uint64) { - // We only test where [ChannelTimeout] is less than the [SubSafetyMargin] - // So we cannot have [ChannelTimeout] be [math.MaxUint64] - if channelTimeout == math.MaxUint64 { - channelTimeout = math.MaxUint64 - 1 - } - if subSafetyMargin <= channelTimeout { - subSafetyMargin = channelTimeout + 1 - } - - channelConfig := defaultTestChannelConfig - channelConfig.ChannelTimeout = channelTimeout - channelConfig.SubSafetyMargin = subSafetyMargin - require.ErrorIs(t, channelConfig.Check(), ErrInvalidChannelTimeout) - }) -} - // addMiniBlock adds a minimal valid L2 block to the channel builder using the -// channelBuilder.AddBlock method. -func addMiniBlock(cb *channelBuilder) error { +// ChannelBuilder.AddBlock method. +func addMiniBlock(cb *ChannelBuilder) error { a := newMiniL2Block(0) _, err := cb.AddBlock(a) return err @@ -139,12 +50,19 @@ func newMiniL2Block(numTx int) *types.Block { // // If numTx > 0, that many empty DynamicFeeTxs will be added to the txs. func newMiniL2BlockWithNumberParent(numTx int, number *big.Int, parent common.Hash) *types.Block { + return newMiniL2BlockWithNumberParentAndL1Information(numTx, number, parent, 100, 0) +} + +// newMiniL2BlockWithNumberParentAndL1Information returns a minimal L2 block with a minimal valid L1InfoDeposit +// It allows you to specify the l1 block number and the block time in addition to the parameters exposed in newMiniL2Block. +func newMiniL2BlockWithNumberParentAndL1Information(numTx int, l2Number *big.Int, parent common.Hash, l1Number int64, blockTime uint64) *types.Block { l1Block := types.NewBlock(&types.Header{ BaseFee: big.NewInt(10), Difficulty: common.Big0, - Number: big.NewInt(100), + Number: big.NewInt(l1Number), + Time: blockTime, }, nil, nil, nil, trie.NewStackTrie(nil)) - l1InfoTx, err := derive.L1InfoDeposit(&defaultTestRollupConfig, eth.SystemConfig{}, 0, eth.BlockToInfo(l1Block), 0) + l1InfoTx, err := derive.L1InfoDeposit(&defaultTestRollupConfig, eth.SystemConfig{}, 0, eth.BlockToInfo(l1Block), blockTime) if err != nil { panic(err) } @@ -156,14 +74,14 @@ func newMiniL2BlockWithNumberParent(numTx int, number *big.Int, parent common.Ha } return types.NewBlock(&types.Header{ - Number: number, + Number: l2Number, ParentHash: parent, }, txs, nil, nil, trie.NewStackTrie(nil)) } // addTooManyBlocks adds blocks to the channel until it hits an error, // which is presumably ErrTooManyRLPBytes. -func addTooManyBlocks(cb *channelBuilder) error { +func addTooManyBlocks(cb *ChannelBuilder) error { rng := rand.New(rand.NewSource(1234)) for i := 0; i < 10_000; i++ { block := dtest.RandomL2BlockWithChainId(rng, 1000, defaultTestRollupConfig.L2ChainID) @@ -183,9 +101,9 @@ func FuzzDurationTimeoutZeroMaxChannelDuration(f *testing.F) { f.Add(uint64(i)) } f.Fuzz(func(t *testing.T, l1BlockNum uint64) { - channelConfig := defaultTestChannelConfig + channelConfig := defaultTestChannelConfig() channelConfig.MaxChannelDuration = 0 - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) cb.timeout = 0 cb.updateDurationTimeout(l1BlockNum) @@ -206,15 +124,15 @@ func FuzzChannelBuilder_DurationZero(f *testing.F) { } // Create the channel builder - channelConfig := defaultTestChannelConfig + channelConfig := defaultTestChannelConfig() channelConfig.MaxChannelDuration = maxChannelDuration - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) // Whenever the timeout is set to 0, the channel builder should have a duration timeout cb.timeout = 0 cb.updateDurationTimeout(l1BlockNum) - cb.checkTimeout(l1BlockNum + maxChannelDuration) + cb.CheckTimeout(l1BlockNum + maxChannelDuration) require.ErrorIs(t, cb.FullErr(), ErrMaxDurationReached) }) } @@ -233,9 +151,9 @@ func FuzzDurationTimeoutMaxChannelDuration(f *testing.F) { } // Create the channel builder - channelConfig := defaultTestChannelConfig + channelConfig := defaultTestChannelConfig() channelConfig.MaxChannelDuration = maxChannelDuration - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) // Whenever the timeout is greater than the l1BlockNum, @@ -248,7 +166,7 @@ func FuzzDurationTimeoutMaxChannelDuration(f *testing.F) { // That is, where the channel builder has a value set for the timeout // with no timeoutReason. This subsequently causes a panic when // a nil timeoutReason is used as an error (eg when calling FullErr). - cb.checkTimeout(l1BlockNum + maxChannelDuration) + cb.CheckTimeout(l1BlockNum + maxChannelDuration) require.ErrorIs(t, cb.FullErr(), ErrMaxDurationReached) } else { require.NoError(t, cb.FullErr()) @@ -266,10 +184,10 @@ func FuzzChannelCloseTimeout(f *testing.F) { } f.Fuzz(func(t *testing.T, l1BlockNum uint64, channelTimeout uint64, subSafetyMargin uint64, timeout uint64) { // Create the channel builder - channelConfig := defaultTestChannelConfig + channelConfig := defaultTestChannelConfig() channelConfig.ChannelTimeout = channelTimeout channelConfig.SubSafetyMargin = subSafetyMargin - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) // Check the timeout @@ -277,7 +195,7 @@ func FuzzChannelCloseTimeout(f *testing.F) { cb.FramePublished(l1BlockNum) calculatedTimeout := l1BlockNum + channelTimeout - subSafetyMargin if timeout > calculatedTimeout && calculatedTimeout != 0 { - cb.checkTimeout(calculatedTimeout) + cb.CheckTimeout(calculatedTimeout) require.ErrorIs(t, cb.FullErr(), ErrChannelTimeoutClose) } else { require.NoError(t, cb.FullErr()) @@ -294,17 +212,17 @@ func FuzzChannelZeroCloseTimeout(f *testing.F) { } f.Fuzz(func(t *testing.T, l1BlockNum uint64, channelTimeout uint64, subSafetyMargin uint64) { // Create the channel builder - channelConfig := defaultTestChannelConfig + channelConfig := defaultTestChannelConfig() channelConfig.ChannelTimeout = channelTimeout channelConfig.SubSafetyMargin = subSafetyMargin - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) // Check the timeout cb.timeout = 0 cb.FramePublished(l1BlockNum) calculatedTimeout := l1BlockNum + channelTimeout - subSafetyMargin - cb.checkTimeout(calculatedTimeout) + cb.CheckTimeout(calculatedTimeout) if cb.timeout != 0 { require.ErrorIs(t, cb.FullErr(), ErrChannelTimeoutClose) } @@ -321,10 +239,10 @@ func FuzzSeqWindowClose(f *testing.F) { } f.Fuzz(func(t *testing.T, epochNum uint64, seqWindowSize uint64, subSafetyMargin uint64, timeout uint64) { // Create the channel builder - channelConfig := defaultTestChannelConfig + channelConfig := defaultTestChannelConfig() channelConfig.SeqWindowSize = seqWindowSize channelConfig.SubSafetyMargin = subSafetyMargin - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) // Check the timeout @@ -332,7 +250,7 @@ func FuzzSeqWindowClose(f *testing.F) { cb.updateSwTimeout(&derive.SingularBatch{EpochNum: rollup.Epoch(epochNum)}) calculatedTimeout := epochNum + seqWindowSize - subSafetyMargin if timeout > calculatedTimeout && calculatedTimeout != 0 { - cb.checkTimeout(calculatedTimeout) + cb.CheckTimeout(calculatedTimeout) require.ErrorIs(t, cb.FullErr(), ErrSeqWindowClose) } else { require.NoError(t, cb.FullErr()) @@ -349,17 +267,17 @@ func FuzzSeqWindowZeroTimeoutClose(f *testing.F) { } f.Fuzz(func(t *testing.T, epochNum uint64, seqWindowSize uint64, subSafetyMargin uint64) { // Create the channel builder - channelConfig := defaultTestChannelConfig + channelConfig := defaultTestChannelConfig() channelConfig.SeqWindowSize = seqWindowSize channelConfig.SubSafetyMargin = subSafetyMargin - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) // Check the timeout cb.timeout = 0 cb.updateSwTimeout(&derive.SingularBatch{EpochNum: rollup.Epoch(epochNum)}) calculatedTimeout := epochNum + seqWindowSize - subSafetyMargin - cb.checkTimeout(calculatedTimeout) + cb.CheckTimeout(calculatedTimeout) if cb.timeout != 0 { require.ErrorIs(t, cb.FullErr(), ErrSeqWindowClose, "Sequence window close should be reached") } @@ -374,7 +292,6 @@ func TestChannelBuilderBatchType(t *testing.T) { {"ChannelBuilder_MaxRLPBytesPerChannel", ChannelBuilder_MaxRLPBytesPerChannel}, {"ChannelBuilder_OutputFramesMaxFrameIndex", ChannelBuilder_OutputFramesMaxFrameIndex}, {"ChannelBuilder_AddBlock", ChannelBuilder_AddBlock}, - {"ChannelBuilder_Reset", ChannelBuilder_Reset}, {"ChannelBuilder_PendingFrames_TotalFrames", ChannelBuilder_PendingFrames_TotalFrames}, {"ChannelBuilder_InputBytes", ChannelBuilder_InputBytes}, {"ChannelBuilder_OutputBytes", ChannelBuilder_OutputBytes}, @@ -396,13 +313,13 @@ func TestChannelBuilderBatchType(t *testing.T) { // TestChannelBuilder_NextFrame tests calling NextFrame on a ChannelBuilder with only one frame func TestChannelBuilder_NextFrame(t *testing.T) { - channelConfig := defaultTestChannelConfig + channelConfig := defaultTestChannelConfig() // Create a new channel builder - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) - // Mock the internals of `channelBuilder.outputFrame` + // Mock the internals of `ChannelBuilder.outputFrame` // to construct a single frame co := cb.co var buf bytes.Buffer @@ -410,7 +327,7 @@ func TestChannelBuilder_NextFrame(t *testing.T) { require.NoError(t, err) // Push one frame into to the channel builder - expectedTx := txID{chID: co.ID(), frameNumber: fn} + expectedTx := txID{frameID{chID: co.ID(), frameNumber: fn}} expectedBytes := buf.Bytes() frameData := frameData{ id: frameID{ @@ -419,14 +336,14 @@ func TestChannelBuilder_NextFrame(t *testing.T) { }, data: expectedBytes, } - cb.PushFrame(frameData) + cb.PushFrames(frameData) // There should only be 1 frame in the channel builder require.Equal(t, 1, cb.PendingFrames()) // We should be able to increment to the next frame constructedFrame := cb.NextFrame() - require.Equal(t, expectedTx, constructedFrame.id) + require.Equal(t, expectedTx[0], constructedFrame.id) require.Equal(t, expectedBytes, constructedFrame.data) require.Equal(t, 0, cb.PendingFrames()) @@ -436,13 +353,13 @@ func TestChannelBuilder_NextFrame(t *testing.T) { // TestChannelBuilder_OutputWrongFramePanic tests that a panic is thrown when a frame is pushed with an invalid frame id func TestChannelBuilder_OutputWrongFramePanic(t *testing.T) { - channelConfig := defaultTestChannelConfig + channelConfig := defaultTestChannelConfig() // Construct a channel builder - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) - // Mock the internals of `channelBuilder.outputFrame` + // Mock the internals of `ChannelBuilder.outputFrame` // to construct a single frame c, err := channelConfig.CompressorConfig.NewCompressor() require.NoError(t, err) @@ -462,17 +379,19 @@ func TestChannelBuilder_OutputWrongFramePanic(t *testing.T) { }, data: buf.Bytes(), } - cb.PushFrame(frame) + cb.PushFrames(frame) }) } -// TestChannelBuilder_OutputFramesWorks tests the [ChannelBuilder] OutputFrames is successful. -func TestChannelBuilder_OutputFramesWorks(t *testing.T) { - channelConfig := defaultTestChannelConfig - channelConfig.MaxFrameSize = 24 +// TestChannelBuilder_OutputFrames tests [ChannelBuilder.OutputFrames] for singular batches. +func TestChannelBuilder_OutputFrames(t *testing.T) { + channelConfig := defaultTestChannelConfig() + channelConfig.MaxFrameSize = derive.FrameV0OverHeadSize + 1 + channelConfig.TargetNumFrames = 1000 + channelConfig.InitNoneCompressor() // Construct the channel builder - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) require.False(t, cb.IsFull()) require.Equal(t, 0, cb.PendingFrames()) @@ -486,11 +405,9 @@ func TestChannelBuilder_OutputFramesWorks(t *testing.T) { // Let's add a block require.NoError(t, addMiniBlock(cb)) - require.NoError(t, cb.co.Flush()) // Check how many ready bytes - // There should be more than the max frame size ready - require.Greater(t, uint64(cb.co.ReadyBytes()), channelConfig.MaxFrameSize) + require.Greater(t, uint64(cb.co.ReadyBytes()+derive.FrameV0OverHeadSize), channelConfig.MaxFrameSize) require.Equal(t, 0, cb.PendingFrames()) // The channel should not be full @@ -507,15 +424,15 @@ func TestChannelBuilder_OutputFramesWorks(t *testing.T) { } } -// TestChannelBuilder_OutputFramesWorks tests the [ChannelBuilder] OutputFrames is successful. -func TestChannelBuilder_OutputFramesWorks_SpanBatch(t *testing.T) { - channelConfig := defaultTestChannelConfig - channelConfig.MaxFrameSize = 24 - channelConfig.CompressorConfig.TargetFrameSize = 50 +func TestChannelBuilder_OutputFrames_SpanBatch(t *testing.T) { + channelConfig := defaultTestChannelConfig() + channelConfig.MaxFrameSize = 20 + derive.FrameV0OverHeadSize + channelConfig.TargetNumFrames = 5 channelConfig.BatchType = derive.SpanBatchType + channelConfig.InitRatioCompressor(1) // Construct the channel builder - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) require.False(t, cb.IsFull()) require.Equal(t, 0, cb.PendingFrames()) @@ -542,14 +459,15 @@ func TestChannelBuilder_OutputFramesWorks_SpanBatch(t *testing.T) { require.True(t, cb.IsFull()) // Check how many ready bytes - // There should be more than the max frame size ready - require.Greater(t, uint64(cb.co.ReadyBytes()), channelConfig.MaxFrameSize) + require.GreaterOrEqual(t, + cb.co.ReadyBytes()+derive.FrameV0OverHeadSize, + int(channelConfig.MaxFrameSize)) require.Equal(t, 0, cb.PendingFrames()) // We should be able to output the frames require.NoError(t, cb.OutputFrames()) - // There should be many frames in the channel builder now + // There should be several frames in the channel builder now require.Greater(t, cb.PendingFrames(), 1) for i := 0; i < cb.numFrames-1; i++ { require.Len(t, cb.frames[i].data, int(channelConfig.MaxFrameSize)) @@ -557,18 +475,17 @@ func TestChannelBuilder_OutputFramesWorks_SpanBatch(t *testing.T) { require.LessOrEqual(t, len(cb.frames[len(cb.frames)-1].data), int(channelConfig.MaxFrameSize)) } -// ChannelBuilder_MaxRLPBytesPerChannel tests the [channelBuilder.OutputFrames] +// ChannelBuilder_MaxRLPBytesPerChannel tests the [ChannelBuilder.OutputFrames] // function errors when the max RLP bytes per channel is reached. func ChannelBuilder_MaxRLPBytesPerChannel(t *testing.T, batchType uint) { t.Parallel() - channelConfig := defaultTestChannelConfig + channelConfig := defaultTestChannelConfig() channelConfig.MaxFrameSize = derive.MaxRLPBytesPerChannel * 2 - channelConfig.CompressorConfig.TargetFrameSize = derive.MaxRLPBytesPerChannel * 2 - channelConfig.CompressorConfig.ApproxComprRatio = 1 + channelConfig.InitNoneCompressor() channelConfig.BatchType = batchType // Construct the channel builder - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) // Add a block that overflows the [ChannelOut] @@ -579,24 +496,23 @@ func ChannelBuilder_MaxRLPBytesPerChannel(t *testing.T, batchType uint) { // ChannelBuilder_OutputFramesMaxFrameIndex tests the [ChannelBuilder.OutputFrames] // function errors when the max frame index is reached. func ChannelBuilder_OutputFramesMaxFrameIndex(t *testing.T, batchType uint) { - channelConfig := defaultTestChannelConfig - channelConfig.MaxFrameSize = 24 - channelConfig.CompressorConfig.TargetNumFrames = 6000 - channelConfig.CompressorConfig.TargetFrameSize = 24 - channelConfig.CompressorConfig.ApproxComprRatio = 1 + channelConfig := defaultTestChannelConfig() + channelConfig.MaxFrameSize = derive.FrameV0OverHeadSize + 1 + channelConfig.TargetNumFrames = math.MaxUint16 + 1 + channelConfig.InitRatioCompressor(.1) channelConfig.BatchType = batchType rng := rand.New(rand.NewSource(123)) // Continuously add blocks until the max frame index is reached - // This should cause the [channelBuilder.OutputFrames] function + // This should cause the [ChannelBuilder.OutputFrames] function // to error - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) require.False(t, cb.IsFull()) require.Equal(t, 0, cb.PendingFrames()) for { - a := dtest.RandomL2BlockWithChainId(rng, 1, defaultTestRollupConfig.L2ChainID) + a := dtest.RandomL2BlockWithChainId(rng, 1000, defaultTestRollupConfig.L2ChainID) _, err = cb.AddBlock(a) if cb.IsFull() { fullErr := cb.FullErr() @@ -610,21 +526,55 @@ func ChannelBuilder_OutputFramesMaxFrameIndex(t *testing.T, batchType uint) { require.ErrorIs(t, cb.FullErr(), ErrMaxFrameIndex) } -// ChannelBuilder_AddBlock tests the AddBlock function +// TestChannelBuilder_FullShadowCompressor is a regression test testing that +// the shadow compressor is correctly marked as full if adding another block +// would produce a leftover frame. +// +// This test fails in multiple places if the subtraction of +// [derive.FrameV0OverHeadSize] in [MaxDataSize] is omitted, which has been the +// case before it got fixed it #9887. +func TestChannelBuilder_FullShadowCompressor(t *testing.T) { + require := require.New(t) + cfg := ChannelConfig{ + MaxFrameSize: 752, + TargetNumFrames: 1, + BatchType: derive.SpanBatchType, + } + cfg.InitShadowCompressor() + + cb, err := NewChannelBuilder(cfg, defaultTestRollupConfig, latestL1BlockOrigin) + require.NoError(err) + + rng := rand.New(rand.NewSource(420)) + a := dtest.RandomL2BlockWithChainId(rng, 1, defaultTestRollupConfig.L2ChainID) + _, err = cb.AddBlock(a) + require.NoError(err) + _, err = cb.AddBlock(a) + require.ErrorIs(err, derive.CompressorFullErr) + // without fix, adding the second block would succeed and then adding a + // third block would fail with full error and the compressor would be full. + + require.NoError(cb.OutputFrames()) + + require.True(cb.HasFrame()) + f := cb.NextFrame() + require.Less(len(f.data), int(cfg.MaxFrameSize)) // would fail without fix, full frame + + require.False(cb.HasFrame(), "no leftover frame expected") // would fail without fix +} + func ChannelBuilder_AddBlock(t *testing.T, batchType uint) { - channelConfig := defaultTestChannelConfig + channelConfig := defaultTestChannelConfig() channelConfig.BatchType = batchType // Lower the max frame size so that we can batch - channelConfig.MaxFrameSize = 20 - + channelConfig.MaxFrameSize = 20 + derive.FrameV0OverHeadSize + channelConfig.TargetNumFrames = 2 // Configure the Input Threshold params so we observe a full channel - channelConfig.CompressorConfig.TargetFrameSize = 20 - channelConfig.CompressorConfig.TargetNumFrames = 2 - channelConfig.CompressorConfig.ApproxComprRatio = 1 + channelConfig.InitRatioCompressor(1) // Construct the channel builder - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) // Add a nonsense block to the channel builder @@ -646,90 +596,44 @@ func ChannelBuilder_AddBlock(t *testing.T, batchType uint) { require.ErrorIs(t, addMiniBlock(cb), derive.CompressorFullErr) } -// ChannelBuilder_Reset tests the [Reset] function -func ChannelBuilder_Reset(t *testing.T, batchType uint) { - channelConfig := defaultTestChannelConfig - channelConfig.BatchType = batchType - - // Lower the max frame size so that we can batch - channelConfig.MaxFrameSize = 24 - channelConfig.CompressorConfig.TargetNumFrames = 1 - channelConfig.CompressorConfig.TargetFrameSize = 24 - channelConfig.CompressorConfig.ApproxComprRatio = 1 - - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) - require.NoError(t, err) - - // Add a nonsense block to the channel builder - require.NoError(t, addMiniBlock(cb)) - require.NoError(t, cb.co.Flush()) - - // Check the fields reset in the Reset function - require.Equal(t, 1, len(cb.blocks)) - require.Equal(t, 0, len(cb.frames)) - // Timeout should be updated in the AddBlock internal call to `updateSwTimeout` - timeout := uint64(100) + cb.cfg.SeqWindowSize - cb.cfg.SubSafetyMargin - require.Equal(t, timeout, cb.timeout) - require.Error(t, cb.fullErr) - - // Output frames so we can set the channel builder frames - require.NoError(t, cb.OutputFrames()) - - // Check the fields reset in the Reset function - require.Equal(t, 1, len(cb.blocks)) - require.Equal(t, timeout, cb.timeout) - require.Error(t, cb.fullErr) - require.Greater(t, len(cb.frames), 1) - - // Reset the channel builder - require.NoError(t, cb.Reset()) - - // Check the fields reset in the Reset function - require.Equal(t, 0, len(cb.blocks)) - require.Equal(t, 0, len(cb.frames)) - require.Equal(t, uint64(0), cb.timeout) - require.NoError(t, cb.fullErr) - require.Equal(t, 0, cb.co.InputBytes()) - require.Equal(t, 0, cb.co.ReadyBytes()) -} - -// TestBuilderRegisterL1Block tests the RegisterL1Block function -func TestBuilderRegisterL1Block(t *testing.T) { - channelConfig := defaultTestChannelConfig +func TestChannelBuilder_CheckTimeout(t *testing.T) { + channelConfig := defaultTestChannelConfig() // Construct the channel builder - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) - // Assert params modified in RegisterL1Block + // Assert timeout is setup correctly require.Equal(t, uint64(1), channelConfig.MaxChannelDuration) - require.Equal(t, uint64(0), cb.timeout) + require.Equal(t, latestL1BlockOrigin+channelConfig.MaxChannelDuration, cb.timeout) - // Register a new L1 block - cb.RegisterL1Block(uint64(100)) + // Check an L1 block which is after the timeout + blockNum := uint64(100) + cb.CheckTimeout(blockNum) + require.Greater(t, blockNum, cb.timeout) - // Assert params modified in RegisterL1Block + // Assert params not modified in CheckTimeout require.Equal(t, uint64(1), channelConfig.MaxChannelDuration) - require.Equal(t, uint64(101), cb.timeout) + require.Equal(t, latestL1BlockOrigin+channelConfig.MaxChannelDuration, cb.timeout) + require.ErrorIs(t, cb.FullErr(), ErrMaxDurationReached) } -// TestBuilderRegisterL1BlockZeroMaxChannelDuration tests the RegisterL1Block function -func TestBuilderRegisterL1BlockZeroMaxChannelDuration(t *testing.T) { - channelConfig := defaultTestChannelConfig +func TestChannelBuilder_CheckTimeoutZeroMaxChannelDuration(t *testing.T) { + channelConfig := defaultTestChannelConfig() // Set the max channel duration to 0 channelConfig.MaxChannelDuration = 0 // Construct the channel builder - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) - // Assert params modified in RegisterL1Block + // Without a max channel duration, timeout should not be set require.Equal(t, uint64(0), channelConfig.MaxChannelDuration) require.Equal(t, uint64(0), cb.timeout) - // Register a new L1 block - cb.RegisterL1Block(uint64(100)) + // Check a new L1 block which should not update the timeout + cb.CheckTimeout(uint64(100)) // Since the max channel duration is set to 0, // the L1 block register should not update the timeout @@ -737,38 +641,61 @@ func TestBuilderRegisterL1BlockZeroMaxChannelDuration(t *testing.T) { require.Equal(t, uint64(0), cb.timeout) } -// TestFramePublished tests the FramePublished function -func TestFramePublished(t *testing.T) { - channelConfig := defaultTestChannelConfig +func TestChannelBuilder_FramePublished(t *testing.T) { + cfg := defaultTestChannelConfig() + cfg.MaxChannelDuration = 10_000 + cfg.ChannelTimeout = 1000 + cfg.SubSafetyMargin = 100 // Construct the channel builder - cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig) + cb, err := NewChannelBuilder(cfg, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(t, err) + require.Equal(t, latestL1BlockOrigin+cfg.MaxChannelDuration, cb.timeout) - // Let's say the block number is fed in as 100 - // and the channel timeout is 1000 - l1BlockNum := uint64(100) - cb.cfg.ChannelTimeout = uint64(1000) - cb.cfg.SubSafetyMargin = 100 + priorTimeout := cb.timeout // Then the frame published will update the timeout + l1BlockNum := uint64(100) + require.Less(t, l1BlockNum, cb.timeout) cb.FramePublished(l1BlockNum) - // Now the timeout will be 1000 + // Now the timeout will be 1000, blockNum + channelTimeout - subSafetyMargin require.Equal(t, uint64(1000), cb.timeout) + require.Less(t, cb.timeout, priorTimeout) +} + +func TestChannelBuilder_LatestL1Origin(t *testing.T) { + cb, err := NewChannelBuilder(defaultTestChannelConfig(), defaultTestRollupConfig, latestL1BlockOrigin) + require.NoError(t, err) + require.Equal(t, eth.BlockID{}, cb.LatestL1Origin()) + + _, err = cb.AddBlock(newMiniL2BlockWithNumberParentAndL1Information(0, big.NewInt(1), common.Hash{}, 1, 100)) + require.NoError(t, err) + require.Equal(t, uint64(1), cb.LatestL1Origin().Number) + + _, err = cb.AddBlock(newMiniL2BlockWithNumberParentAndL1Information(0, big.NewInt(2), common.Hash{}, 1, 100)) + require.NoError(t, err) + require.Equal(t, uint64(1), cb.LatestL1Origin().Number) + + _, err = cb.AddBlock(newMiniL2BlockWithNumberParentAndL1Information(0, big.NewInt(3), common.Hash{}, 2, 110)) + require.NoError(t, err) + require.Equal(t, uint64(2), cb.LatestL1Origin().Number) + + _, err = cb.AddBlock(newMiniL2BlockWithNumberParentAndL1Information(0, big.NewInt(3), common.Hash{}, 1, 110)) + require.NoError(t, err) + require.Equal(t, uint64(2), cb.LatestL1Origin().Number) } func ChannelBuilder_PendingFrames_TotalFrames(t *testing.T, batchType uint) { const tnf = 9 rng := rand.New(rand.NewSource(94572314)) require := require.New(t) - cfg := defaultTestChannelConfig - cfg.CompressorConfig.TargetFrameSize = 1000 + cfg := defaultTestChannelConfig() cfg.MaxFrameSize = 1000 - cfg.CompressorConfig.TargetNumFrames = tnf - cfg.CompressorConfig.Kind = "shadow" + cfg.TargetNumFrames = tnf cfg.BatchType = batchType - cb, err := newChannelBuilder(cfg, defaultTestRollupConfig) + cfg.InitShadowCompressor() + cb, err := NewChannelBuilder(cfg, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(err) // initial builder should be empty @@ -805,14 +732,14 @@ func ChannelBuilder_PendingFrames_TotalFrames(t *testing.T, batchType uint) { func ChannelBuilder_InputBytes(t *testing.T, batchType uint) { require := require.New(t) rng := rand.New(rand.NewSource(4982432)) - cfg := defaultTestChannelConfig + cfg := defaultTestChannelConfig() cfg.BatchType = batchType var spanBatchBuilder *derive.SpanBatchBuilder if batchType == derive.SpanBatchType { chainId := big.NewInt(1234) spanBatchBuilder = derive.NewSpanBatchBuilder(uint64(0), chainId) } - cb, err := newChannelBuilder(cfg, defaultTestRollupConfig) + cb, err := NewChannelBuilder(cfg, defaultTestRollupConfig, latestL1BlockOrigin) require.NoError(err) require.Zero(cb.InputBytes()) @@ -842,14 +769,13 @@ func ChannelBuilder_InputBytes(t *testing.T, batchType uint) { func ChannelBuilder_OutputBytes(t *testing.T, batchType uint) { require := require.New(t) rng := rand.New(rand.NewSource(9860372)) - cfg := defaultTestChannelConfig - cfg.CompressorConfig.TargetFrameSize = 1000 + cfg := defaultTestChannelConfig() cfg.MaxFrameSize = 1000 - cfg.CompressorConfig.TargetNumFrames = 16 - cfg.CompressorConfig.ApproxComprRatio = 1.0 + cfg.TargetNumFrames = 16 cfg.BatchType = batchType - cb, err := newChannelBuilder(cfg, defaultTestRollupConfig) - require.NoError(err, "newChannelBuilder") + cfg.InitRatioCompressor(1.0) + cb, err := NewChannelBuilder(cfg, defaultTestRollupConfig, latestL1BlockOrigin) + require.NoError(err, "NewChannelBuilder") require.Zero(cb.OutputBytes()) diff --git a/op-batcher/batcher/channel_config.go b/op-batcher/batcher/channel_config.go new file mode 100644 index 000000000000..c6a0eec4c04c --- /dev/null +++ b/op-batcher/batcher/channel_config.go @@ -0,0 +1,119 @@ +package batcher + +import ( + "fmt" + + "github.com/ethereum-optimism/optimism/op-batcher/compressor" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" +) + +type ChannelConfig struct { + // Number of epochs (L1 blocks) per sequencing window, including the epoch + // L1 origin block itself + SeqWindowSize uint64 + // The maximum number of L1 blocks that the inclusion transactions of a + // channel's frames can span. + ChannelTimeout uint64 + + // Builder Config + + // MaxChannelDuration is the maximum duration (in #L1-blocks) to keep the + // channel open. This allows control over how long a channel is kept open + // during times of low transaction volume. + // + // If 0, duration checks are disabled. + MaxChannelDuration uint64 + // The batcher tx submission safety margin (in #L1-blocks) to subtract from + // a channel's timeout and sequencing window, to guarantee safe inclusion of + // a channel on L1. + SubSafetyMargin uint64 + // The maximum byte-size a frame can have. + MaxFrameSize uint64 + + // Target number of frames to create per channel. + // For blob transactions, this controls the number of blobs to target adding + // to each blob tx. + TargetNumFrames int + + // CompressorConfig contains the configuration for creating new compressors. + // It should not be set directly, but via the Init*Compressor methods after + // creating the ChannelConfig to guarantee a consistent configuration. + CompressorConfig compressor.Config + + // BatchType indicates whether the channel uses SingularBatch or SpanBatch. + BatchType uint + + // Whether to put all frames of a channel inside a single tx. + // Should only be used for blob transactions. + MultiFrameTxs bool +} + +// InitCompressorConfig (re)initializes the channel configuration's compressor +// configuration using the given values. The TargetOutputSize will be set to a +// value consistent with cc.TargetNumFrames and cc.MaxFrameSize. +// comprKind can be the empty string, in which case the default compressor will +// be used. +func (cc *ChannelConfig) InitCompressorConfig(approxComprRatio float64, comprKind string) { + cc.CompressorConfig = compressor.Config{ + // Compressor output size needs to account for frame encoding overhead + TargetOutputSize: MaxDataSize(cc.TargetNumFrames, cc.MaxFrameSize), + ApproxComprRatio: approxComprRatio, + Kind: comprKind, + } +} + +func (cc *ChannelConfig) InitRatioCompressor(approxComprRatio float64) { + cc.InitCompressorConfig(approxComprRatio, compressor.RatioKind) +} + +func (cc *ChannelConfig) InitShadowCompressor() { + cc.InitCompressorConfig(0, compressor.ShadowKind) +} + +func (cc *ChannelConfig) InitNoneCompressor() { + cc.InitCompressorConfig(0, compressor.NoneKind) +} + +func (cc *ChannelConfig) MaxFramesPerTx() int { + if !cc.MultiFrameTxs { + return 1 + } + return cc.TargetNumFrames +} + +// Check validates the [ChannelConfig] parameters. +func (cc *ChannelConfig) Check() error { + // The [ChannelTimeout] must be larger than the [SubSafetyMargin]. + // Otherwise, new blocks would always be considered timed out. + if cc.ChannelTimeout < cc.SubSafetyMargin { + return ErrInvalidChannelTimeout + } + + // The max frame size must at least be able to accommodate the constant + // frame overhead. + if cc.MaxFrameSize < derive.FrameV0OverHeadSize { + return fmt.Errorf("max frame size %d is less than the minimum %d", + cc.MaxFrameSize, derive.FrameV0OverHeadSize) + } + + if cc.BatchType > derive.SpanBatchType { + return fmt.Errorf("unrecognized batch type: %d", cc.BatchType) + } + + if nf := cc.TargetNumFrames; nf < 1 { + return fmt.Errorf("invalid number of frames %d", nf) + } + + return nil +} + +// MaxDataSize returns the maximum byte size of output data that can be packed +// into a channel with numFrames frames and frames of max size maxFrameSize. +// It accounts for the constant frame overhead. It panics if the maxFrameSize +// is smaller than [derive.FrameV0OverHeadSize]. +func MaxDataSize(numFrames int, maxFrameSize uint64) uint64 { + if maxFrameSize < derive.FrameV0OverHeadSize { + panic("max frame size smaller than frame overhead") + } + return uint64(numFrames) * (maxFrameSize - derive.FrameV0OverHeadSize) +} diff --git a/op-batcher/batcher/channel_config_test.go b/op-batcher/batcher/channel_config_test.go new file mode 100644 index 000000000000..a89d780ab558 --- /dev/null +++ b/op-batcher/batcher/channel_config_test.go @@ -0,0 +1,96 @@ +package batcher + +import ( + "fmt" + "math" + "testing" + + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + + "github.com/stretchr/testify/require" +) + +func defaultTestChannelConfig() ChannelConfig { + c := ChannelConfig{ + SeqWindowSize: 15, + ChannelTimeout: 40, + MaxChannelDuration: 1, + SubSafetyMargin: 4, + MaxFrameSize: 120_000, + TargetNumFrames: 1, + BatchType: derive.SingularBatchType, + } + c.InitRatioCompressor(0.4) + return c +} + +func TestChannelConfig_Check(t *testing.T) { + type test struct { + input func() ChannelConfig + assertion func(error) + } + + tests := []test{ + { + input: defaultTestChannelConfig, + assertion: func(output error) { + require.NoError(t, output) + }, + }, + { + input: func() ChannelConfig { + cfg := defaultTestChannelConfig() + cfg.ChannelTimeout = 0 + cfg.SubSafetyMargin = 1 + return cfg + }, + assertion: func(output error) { + require.ErrorIs(t, output, ErrInvalidChannelTimeout) + }, + }, + } + for i := 0; i < derive.FrameV0OverHeadSize; i++ { + expectedErr := fmt.Sprintf("max frame size %d is less than the minimum 23", i) + i := i // need to udpate Go version... + tests = append(tests, test{ + input: func() ChannelConfig { + cfg := defaultTestChannelConfig() + cfg.MaxFrameSize = uint64(i) + return cfg + }, + assertion: func(output error) { + require.EqualError(t, output, expectedErr) + }, + }) + } + + // Run the table tests + for _, test := range tests { + cfg := test.input() + test.assertion(cfg.Check()) + } +} + +// FuzzChannelConfig_CheckTimeout tests the [ChannelConfig.Check] function +// with fuzzing to make sure that a [ErrInvalidChannelTimeout] is thrown when +// the ChannelTimeout is less than the SubSafetyMargin. +func FuzzChannelConfig_CheckTimeout(f *testing.F) { + for i := range [10]int{} { + f.Add(uint64(i+1), uint64(i)) + } + f.Fuzz(func(t *testing.T, channelTimeout uint64, subSafetyMargin uint64) { + // We only test where [ChannelTimeout] is less than the [SubSafetyMargin] + // So we cannot have [ChannelTimeout] be [math.MaxUint64] + if channelTimeout == math.MaxUint64 { + channelTimeout = math.MaxUint64 - 1 + } + if subSafetyMargin <= channelTimeout { + subSafetyMargin = channelTimeout + 1 + } + + channelConfig := defaultTestChannelConfig() + channelConfig.ChannelTimeout = channelTimeout + channelConfig.SubSafetyMargin = subSafetyMargin + require.ErrorIs(t, channelConfig.Check(), ErrInvalidChannelTimeout) + }) +} diff --git a/op-batcher/batcher/channel_manager.go b/op-batcher/batcher/channel_manager.go index eae923738897..491837182acb 100644 --- a/op-batcher/batcher/channel_manager.go +++ b/op-batcher/batcher/channel_manager.go @@ -33,6 +33,8 @@ type channelManager struct { // All blocks since the last request for new tx data. blocks []*types.Block + // The latest L1 block from all the L2 blocks in the most recently closed channel + l1OriginLastClosedChannel eth.BlockID // last block hash - for reorg detection tip common.Hash @@ -41,7 +43,7 @@ type channelManager struct { // channels to read frame data from, for writing batches onchain channelQueue []*channel // used to lookup channels by tx ID upon tx success / failure - txChannels map[txID]*channel + txChannels map[string]*channel // if set to true, prevents production of any new channel frames closed bool @@ -53,29 +55,31 @@ func NewChannelManager(log log.Logger, metr metrics.Metricer, cfg ChannelConfig, metr: metr, cfg: cfg, rollupCfg: rollupCfg, - txChannels: make(map[txID]*channel), + txChannels: make(map[string]*channel), } } // Clear clears the entire state of the channel manager. // It is intended to be used before launching op-batcher and after an L2 reorg. -func (s *channelManager) Clear() { +func (s *channelManager) Clear(l1OriginLastClosedChannel eth.BlockID) { s.mu.Lock() defer s.mu.Unlock() s.log.Trace("clearing channel manager state") s.blocks = s.blocks[:0] + s.l1OriginLastClosedChannel = l1OriginLastClosedChannel s.tip = common.Hash{} s.closed = false s.currentChannel = nil s.channelQueue = nil - s.txChannels = make(map[txID]*channel) + s.txChannels = make(map[string]*channel) } // TxFailed records a transaction as failed. It will attempt to resubmit the data // in the failed transaction. -func (s *channelManager) TxFailed(id txID) { +func (s *channelManager) TxFailed(_id txID) { s.mu.Lock() defer s.mu.Unlock() + id := _id.String() if channel, ok := s.txChannels[id]; ok { delete(s.txChannels, id) channel.TxFailed(id) @@ -92,9 +96,10 @@ func (s *channelManager) TxFailed(id txID) { // a channel have been marked as confirmed on L1 the channel may be invalid & need to be // resubmitted. // This function may reset the pending channel if the pending channel has timed out. -func (s *channelManager) TxConfirmed(id txID, inclusionBlock eth.BlockID) { +func (s *channelManager) TxConfirmed(_id txID, inclusionBlock eth.BlockID) { s.mu.Lock() defer s.mu.Unlock() + id := _id.String() if channel, ok := s.txChannels[id]; ok { delete(s.txChannels, id) done, blocks := channel.TxConfirmed(id, inclusionBlock) @@ -130,40 +135,40 @@ func (s *channelManager) removePendingChannel(channel *channel) { // nextTxData pops off s.datas & handles updating the internal state func (s *channelManager) nextTxData(channel *channel) (txData, error) { - if channel == nil || !channel.HasFrame() { + if channel == nil || !channel.HasTxData() { s.log.Trace("no next tx data") return txData{}, io.EOF // TODO: not enough data error instead } tx := channel.NextTxData() - s.txChannels[tx.ID()] = channel + s.txChannels[tx.ID().String()] = channel return tx, nil } // TxData returns the next tx data that should be submitted to L1. // -// It currently only uses one frame per transaction. If the pending channel is +// If the pending channel is // full, it only returns the remaining frames of this channel until it got -// successfully fully sent to L1. It returns io.EOF if there's no pending frame. +// successfully fully sent to L1. It returns io.EOF if there's no pending tx data. func (s *channelManager) TxData(l1Head eth.BlockID) (txData, error) { s.mu.Lock() defer s.mu.Unlock() - var firstWithFrame *channel + var firstWithTxData *channel for _, ch := range s.channelQueue { - if ch.HasFrame() { - firstWithFrame = ch + if ch.HasTxData() { + firstWithTxData = ch break } } - dataPending := firstWithFrame != nil && firstWithFrame.HasFrame() - s.log.Debug("Requested tx data", "l1Head", l1Head, "data_pending", dataPending, "blocks_pending", len(s.blocks)) + dataPending := firstWithTxData != nil && firstWithTxData.HasTxData() + s.log.Debug("Requested tx data", "l1Head", l1Head, "txdata_pending", dataPending, "blocks_pending", len(s.blocks)) - // Short circuit if there is a pending frame or the channel manager is closed. + // Short circuit if there is pending tx data or the channel manager is closed. if dataPending || s.closed { - return s.nextTxData(firstWithFrame) + return s.nextTxData(firstWithTxData) } - // No pending frame, so we have to add new blocks to the channel + // No pending tx data, so we have to add new blocks to the channel // If we have no saved blocks, we will not be able to create valid frames if len(s.blocks) == 0 { @@ -198,15 +203,19 @@ func (s *channelManager) ensureChannelWithSpace(l1Head eth.BlockID) error { return nil } - pc, err := newChannel(s.log, s.metr, s.cfg, s.rollupCfg) + pc, err := newChannel(s.log, s.metr, s.cfg, s.rollupCfg, s.l1OriginLastClosedChannel.Number) + if err != nil { return fmt.Errorf("creating new channel: %w", err) } + s.currentChannel = pc s.channelQueue = append(s.channelQueue, pc) + s.log.Info("Created channel", "id", pc.ID(), "l1Head", l1Head, + "l1OriginLastClosedChannel", s.l1OriginLastClosedChannel, "blocks_pending", len(s.blocks), "batch_type", s.cfg.BatchType, "max_frame_size", s.cfg.MaxFrameSize, @@ -218,7 +227,7 @@ func (s *channelManager) ensureChannelWithSpace(l1Head eth.BlockID) error { // registerL1Block registers the given block at the pending channel. func (s *channelManager) registerL1Block(l1Head eth.BlockID) { - s.currentChannel.RegisterL1Block(l1Head.Number) + s.currentChannel.CheckTimeout(l1Head.Number) s.log.Debug("new L1-block registered at channel builder", "l1Head", l1Head, "channel_full", s.currentChannel.IsFull(), @@ -284,6 +293,11 @@ func (s *channelManager) outputFrames() error { return nil } + lastClosedL1Origin := s.currentChannel.LatestL1Origin() + if lastClosedL1Origin.Number > s.l1OriginLastClosedChannel.Number { + s.l1OriginLastClosedChannel = lastClosedL1Origin + } + inBytes, outBytes := s.currentChannel.InputBytes(), s.currentChannel.OutputBytes() s.metr.RecordChannelClosed( s.currentChannel.ID(), @@ -298,14 +312,17 @@ func (s *channelManager) outputFrames() error { if inBytes > 0 { comprRatio = float64(outBytes) / float64(inBytes) } + s.log.Info("Channel closed", "id", s.currentChannel.ID(), "blocks_pending", len(s.blocks), "num_frames", s.currentChannel.TotalFrames(), "input_bytes", inBytes, "output_bytes", outBytes, + "l1_origin", lastClosedL1Origin, "full_reason", s.currentChannel.FullErr(), "compr_ratio", comprRatio, + "latest_l1_origin", s.l1OriginLastClosedChannel, ) return nil } @@ -385,7 +402,7 @@ func (s *channelManager) Close() error { } } - if s.currentChannel.HasFrame() { + if s.currentChannel.HasTxData() { // Make it clear to the caller that there is remaining pending work. return ErrPendingAfterClose } diff --git a/op-batcher/batcher/channel_manager_test.go b/op-batcher/batcher/channel_manager_test.go index 80c70605366b..e029e69e658c 100644 --- a/op-batcher/batcher/channel_manager_test.go +++ b/op-batcher/batcher/channel_manager_test.go @@ -7,7 +7,6 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimism/op-batcher/compressor" "github.com/ethereum-optimism/optimism/op-batcher/metrics" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" @@ -20,6 +19,16 @@ import ( "github.com/stretchr/testify/require" ) +func channelManagerTestConfig(maxFrameSize uint64, batchType uint) ChannelConfig { + cfg := ChannelConfig{ + MaxFrameSize: maxFrameSize, + TargetNumFrames: 1, + BatchType: batchType, + } + cfg.InitRatioCompressor(1) + return cfg +} + func TestChannelManagerBatchType(t *testing.T) { tests := []struct { name string @@ -52,9 +61,9 @@ func TestChannelManagerBatchType(t *testing.T) { // ChannelManagerReturnsErrReorg ensures that the channel manager // detects a reorg when it has cached L1 blocks. func ChannelManagerReturnsErrReorg(t *testing.T, batchType uint) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) m := NewChannelManager(log, metrics.NoopMetrics, ChannelConfig{BatchType: batchType}, &rollup.Config{}) - m.Clear() + m.Clear(eth.BlockID{}) a := types.NewBlock(&types.Header{ Number: big.NewInt(0), @@ -83,20 +92,11 @@ func ChannelManagerReturnsErrReorg(t *testing.T, batchType uint) { // ChannelManagerReturnsErrReorgWhenDrained ensures that the channel manager // detects a reorg even if it does not have any blocks inside it. func ChannelManagerReturnsErrReorgWhenDrained(t *testing.T, batchType uint) { - log := testlog.Logger(t, log.LvlCrit) - m := NewChannelManager(log, metrics.NoopMetrics, - ChannelConfig{ - MaxFrameSize: 120_000, - CompressorConfig: compressor.Config{ - TargetFrameSize: 1, - TargetNumFrames: 1, - ApproxComprRatio: 1.0, - }, - BatchType: batchType, - }, - &rollup.Config{}, - ) - m.Clear() + log := testlog.Logger(t, log.LevelCrit) + cfg := channelManagerTestConfig(120_000, batchType) + cfg.CompressorConfig.TargetOutputSize = 1 // full on first block + m := NewChannelManager(log, metrics.NoopMetrics, cfg, &rollup.Config{}) + m.Clear(eth.BlockID{}) a := newMiniL2Block(0) x := newMiniL2BlockWithNumberParent(0, big.NewInt(1), common.Hash{0xff}) @@ -116,34 +116,25 @@ func ChannelManager_Clear(t *testing.T, batchType uint) { require := require.New(t) // Create a channel manager - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) rng := rand.New(rand.NewSource(time.Now().UnixNano())) - m := NewChannelManager(log, metrics.NoopMetrics, ChannelConfig{ - // Need to set the channel timeout here so we don't clear pending - // channels on confirmation. This would result in [TxConfirmed] - // clearing confirmed transactions, and resetting the pendingChannels map - ChannelTimeout: 10, - // Have to set the max frame size here otherwise the channel builder would not - // be able to output any frames - MaxFrameSize: 24, - CompressorConfig: compressor.Config{ - TargetFrameSize: 24, - TargetNumFrames: 1, - ApproxComprRatio: 1.0, - }, - BatchType: batchType, - }, - &defaultTestRollupConfig, - ) + cfg := channelManagerTestConfig(derive.FrameV0OverHeadSize+1, batchType) + // Need to set the channel timeout here so we don't clear pending + // channels on confirmation. This would result in [TxConfirmed] + // clearing confirmed transactions, and resetting the pendingChannels map + cfg.ChannelTimeout = 10 + cfg.InitRatioCompressor(1) + m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) // Channel Manager state should be empty by default require.Empty(m.blocks) + require.Equal(eth.BlockID{}, m.l1OriginLastClosedChannel) require.Equal(common.Hash{}, m.tip) require.Nil(m.currentChannel) require.Empty(m.channelQueue) require.Empty(m.txChannels) // Set the last block - m.Clear() + m.Clear(eth.BlockID{}) // Add a block to the channel manager a := derivetest.RandomL2BlockWithChainId(rng, 4, defaultTestRollupConfig.L2ChainID) @@ -165,9 +156,10 @@ func ChannelManager_Clear(t *testing.T, batchType uint) { // the list require.NoError(m.processBlocks()) require.NoError(m.currentChannel.channelBuilder.co.Flush()) - require.NoError(m.currentChannel.OutputFrames()) + require.NoError(m.outputFrames()) _, err := m.nextTxData(m.currentChannel) require.NoError(err) + require.NotNil(m.l1OriginLastClosedChannel) require.Len(m.blocks, 0) require.Equal(newL1Tip, m.tip) require.Len(m.currentChannel.pendingTransactions, 1) @@ -182,11 +174,15 @@ func ChannelManager_Clear(t *testing.T, batchType uint) { require.Len(m.blocks, 1) require.Equal(b.Hash(), m.tip) + safeL1Origin := eth.BlockID{ + Number: 123, + } // Clear the channel manager - m.Clear() + m.Clear(safeL1Origin) // Check that the entire channel manager state cleared require.Empty(m.blocks) + require.Equal(uint64(123), m.l1OriginLastClosedChannel.Number) require.Equal(common.Hash{}, m.tip) require.Nil(m.currentChannel) require.Empty(m.channelQueue) @@ -196,20 +192,11 @@ func ChannelManager_Clear(t *testing.T, batchType uint) { func ChannelManager_TxResend(t *testing.T, batchType uint) { require := require.New(t) rng := rand.New(rand.NewSource(time.Now().UnixNano())) - log := testlog.Logger(t, log.LvlError) - m := NewChannelManager(log, metrics.NoopMetrics, - ChannelConfig{ - MaxFrameSize: 120_000, - CompressorConfig: compressor.Config{ - TargetFrameSize: 1, - TargetNumFrames: 1, - ApproxComprRatio: 1.0, - }, - BatchType: batchType, - }, - &defaultTestRollupConfig, - ) - m.Clear() + log := testlog.Logger(t, log.LevelError) + cfg := channelManagerTestConfig(120_000, batchType) + cfg.CompressorConfig.TargetOutputSize = 1 // full on first block + m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) + m.Clear(eth.BlockID{}) a := derivetest.RandomL2BlockWithChainId(rng, 4, defaultTestRollupConfig.L2ChainID) @@ -217,7 +204,7 @@ func ChannelManager_TxResend(t *testing.T, batchType uint) { txdata0, err := m.TxData(eth.BlockID{}) require.NoError(err) - txdata0bytes := txdata0.Bytes() + txdata0bytes := txdata0.CallData() data0 := make([]byte, len(txdata0bytes)) // make sure we have a clone for later comparison copy(data0, txdata0bytes) @@ -232,7 +219,7 @@ func ChannelManager_TxResend(t *testing.T, batchType uint) { txdata1, err := m.TxData(eth.BlockID{}) require.NoError(err) - data1 := txdata1.Bytes() + data1 := txdata1.CallData() require.Equal(data1, data0) fs, err := derive.ParseFrames(data1) require.NoError(err) @@ -244,20 +231,12 @@ func ChannelManager_TxResend(t *testing.T, batchType uint) { func ChannelManagerCloseBeforeFirstUse(t *testing.T, batchType uint) { require := require.New(t) rng := rand.New(rand.NewSource(time.Now().UnixNano())) - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) m := NewChannelManager(log, metrics.NoopMetrics, - ChannelConfig{ - MaxFrameSize: 100, - ChannelTimeout: 1000, - CompressorConfig: compressor.Config{ - TargetFrameSize: 0, - ApproxComprRatio: 1.0, - }, - BatchType: batchType, - }, + channelManagerTestConfig(10000, batchType), &defaultTestRollupConfig, ) - m.Clear() + m.Clear(eth.BlockID{}) a := derivetest.RandomL2BlockWithChainId(rng, 4, defaultTestRollupConfig.L2ChainID) @@ -275,21 +254,12 @@ func ChannelManagerCloseBeforeFirstUse(t *testing.T, batchType uint) { // channel frames. func ChannelManagerCloseNoPendingChannel(t *testing.T, batchType uint) { require := require.New(t) - log := testlog.Logger(t, log.LvlCrit) - m := NewChannelManager(log, metrics.NoopMetrics, - ChannelConfig{ - MaxFrameSize: 100, - ChannelTimeout: 1000, - CompressorConfig: compressor.Config{ - TargetFrameSize: 1, - TargetNumFrames: 1, - ApproxComprRatio: 1.0, - }, - BatchType: batchType, - }, - &defaultTestRollupConfig, - ) - m.Clear() + log := testlog.Logger(t, log.LevelCrit) + cfg := channelManagerTestConfig(10000, batchType) + cfg.CompressorConfig.TargetOutputSize = 1 // full on first block + cfg.ChannelTimeout = 1000 + m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) + m.Clear(eth.BlockID{}) a := newMiniL2Block(0) b := newMiniL2BlockWithNumberParent(0, big.NewInt(1), a.Hash()) @@ -321,21 +291,11 @@ func ChannelManagerClosePendingChannel(t *testing.T, batchType uint) { // The number of batch txs depends on compression of the random data, hence the static test RNG seed. // Example of different RNG seed that creates less than 2 frames: 1698700588902821588 rng := rand.New(rand.NewSource(123)) - log := testlog.Logger(t, log.LvlError) - m := NewChannelManager(log, metrics.NoopMetrics, - ChannelConfig{ - MaxFrameSize: 10_000, - ChannelTimeout: 1_000, - CompressorConfig: compressor.Config{ - TargetNumFrames: 1, - TargetFrameSize: 10_000, - ApproxComprRatio: 1.0, - }, - BatchType: batchType, - }, - &defaultTestRollupConfig, - ) - m.Clear() + log := testlog.Logger(t, log.LevelError) + cfg := channelManagerTestConfig(10_000, batchType) + cfg.ChannelTimeout = 1000 + m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) + m.Clear(eth.BlockID{}) numTx := 20 // Adjust number of txs to make 2 frames a := derivetest.RandomL2BlockWithChainId(rng, numTx, defaultTestRollupConfig.L2ChainID) @@ -379,22 +339,15 @@ func TestChannelManager_Close_PartiallyPendingChannel(t *testing.T) { // The number of batch txs depends on compression of the random data, hence the static test RNG seed. // Example of different RNG seed that creates less than 2 frames: 1698700588902821588 rng := rand.New(rand.NewSource(123)) - log := testlog.Logger(t, log.LvlError) - const framesize = 2200 - m := NewChannelManager(log, metrics.NoopMetrics, - ChannelConfig{ - MaxFrameSize: framesize, - ChannelTimeout: 1000, - CompressorConfig: compressor.Config{ - TargetNumFrames: 100, - TargetFrameSize: framesize, - ApproxComprRatio: 1.0, - Kind: "none", - }, - }, - &defaultTestRollupConfig, - ) - m.Clear() + log := testlog.Logger(t, log.LevelError) + cfg := ChannelConfig{ + MaxFrameSize: 2200, + ChannelTimeout: 1000, + TargetNumFrames: 100, + } + cfg.InitNoneCompressor() + m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) + m.Clear(eth.BlockID{}) numTx := 3 // Adjust number of txs to make 2 frames a := derivetest.RandomL2BlockWithChainId(rng, numTx, defaultTestRollupConfig.L2ChainID) @@ -440,41 +393,93 @@ func TestChannelManager_Close_PartiallyPendingChannel(t *testing.T) { // have successfully landed on chain. func ChannelManagerCloseAllTxsFailed(t *testing.T, batchType uint) { require := require.New(t) - rng := rand.New(rand.NewSource(time.Now().UnixNano())) - log := testlog.Logger(t, log.LvlCrit) - m := NewChannelManager(log, metrics.NoopMetrics, - ChannelConfig{ - MaxFrameSize: 1000, - ChannelTimeout: 1000, - CompressorConfig: compressor.Config{ - TargetNumFrames: 100, - TargetFrameSize: 1000, - ApproxComprRatio: 1.0, - }, - BatchType: batchType, - }, &defaultTestRollupConfig, - ) - m.Clear() + rng := rand.New(rand.NewSource(1357)) + log := testlog.Logger(t, log.LevelCrit) + cfg := channelManagerTestConfig(100, batchType) + cfg.TargetNumFrames = 1000 + cfg.InitNoneCompressor() + m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) + m.Clear(eth.BlockID{}) - a := derivetest.RandomL2BlockWithChainId(rng, 50000, defaultTestRollupConfig.L2ChainID) + a := derivetest.RandomL2BlockWithChainId(rng, 1000, defaultTestRollupConfig.L2ChainID) err := m.AddL2Block(a) require.NoError(err, "Failed to add L2 block") - txdata, err := m.TxData(eth.BlockID{}) - require.NoError(err, "Expected channel manager to produce valid tx data") + drainTxData := func() (txdatas []txData) { + for { + txdata, err := m.TxData(eth.BlockID{}) + if err == io.EOF { + return + } + require.NoError(err, "Expected channel manager to produce valid tx data") + txdatas = append(txdatas, txdata) + } + } + + txdatas := drainTxData() + require.NotEmpty(txdatas) - m.TxFailed(txdata.ID()) + for _, txdata := range txdatas { + m.TxFailed(txdata.ID()) + } // Show that this data will continue to be emitted as long as the transaction // fails and the channel manager is not closed - txdata, err = m.TxData(eth.BlockID{}) - require.NoError(err, "Expected channel manager to re-attempt the failed transaction") + txdatas1 := drainTxData() + require.NotEmpty(txdatas) + require.ElementsMatch(txdatas, txdatas1, "expected same txdatas on re-attempt") - m.TxFailed(txdata.ID()) + for _, txdata := range txdatas1 { + m.TxFailed(txdata.ID()) + } require.NoError(m.Close(), "Expected to close channel manager gracefully") _, err = m.TxData(eth.BlockID{}) require.ErrorIs(err, io.EOF, "Expected closed channel manager to produce no more tx data") } + +func TestChannelManager_ChannelCreation(t *testing.T) { + l := testlog.Logger(t, log.LevelCrit) + const maxChannelDuration = 15 + cfg := channelManagerTestConfig(1000, derive.SpanBatchType) + cfg.MaxChannelDuration = maxChannelDuration + cfg.InitNoneCompressor() + + for _, tt := range []struct { + name string + safeL1Block eth.BlockID + expectedChannelTimeout uint64 + }{ + { + name: "UseSafeHeadWhenNoLastL1Block", + safeL1Block: eth.BlockID{ + Number: uint64(123), + }, + // Safe head + maxChannelDuration + expectedChannelTimeout: 123 + maxChannelDuration, + }, + { + name: "NoLastL1BlockNoSafeL1Block", + safeL1Block: eth.BlockID{ + Number: 0, + }, + // No timeout + expectedChannelTimeout: 0 + maxChannelDuration, + }, + } { + test := tt + t.Run(test.name, func(t *testing.T) { + m := NewChannelManager(l, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) + + m.l1OriginLastClosedChannel = test.safeL1Block + require.Nil(t, m.currentChannel) + + require.NoError(t, m.ensureChannelWithSpace(eth.BlockID{})) + + require.NotNil(t, m.currentChannel) + require.Equal(t, test.expectedChannelTimeout, m.currentChannel.Timeout()) + }) + } +} diff --git a/op-batcher/batcher/channel_test.go b/op-batcher/batcher/channel_test.go index 4524a069341c..71903eb370ca 100644 --- a/op-batcher/batcher/channel_test.go +++ b/op-batcher/batcher/channel_test.go @@ -14,15 +14,23 @@ import ( "github.com/stretchr/testify/require" ) +func singleFrameTxID(cid derive.ChannelID, fn uint16) txID { + return txID{frameID{chID: cid, frameNumber: fn}} +} + +func zeroFrameTxID(fn uint16) txID { + return txID{frameID{frameNumber: fn}} +} + // TestChannelTimeout tests that the channel manager // correctly identifies when a pending channel is timed out. func TestChannelTimeout(t *testing.T) { // Create a new channel manager with a ChannelTimeout - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) m := NewChannelManager(log, metrics.NoopMetrics, ChannelConfig{ ChannelTimeout: 100, }, &rollup.Config{}) - m.Clear() + m.Clear(eth.BlockID{}) // Pending channel is nil so is cannot be timed out require.Nil(t, m.currentChannel) @@ -39,8 +47,8 @@ func TestChannelTimeout(t *testing.T) { // Manually set a confirmed transactions // To avoid other methods clearing state - channel.confirmedTransactions[frameID{frameNumber: 0}] = eth.BlockID{Number: 0} - channel.confirmedTransactions[frameID{frameNumber: 1}] = eth.BlockID{Number: 99} + channel.confirmedTransactions[zeroFrameTxID(0).String()] = eth.BlockID{Number: 0} + channel.confirmedTransactions[zeroFrameTxID(1).String()] = eth.BlockID{Number: 99} channel.confirmedTxUpdated = true // Since the ChannelTimeout is 100, the @@ -50,9 +58,7 @@ func TestChannelTimeout(t *testing.T) { // Add a confirmed transaction with a higher number // than the ChannelTimeout - channel.confirmedTransactions[frameID{ - frameNumber: 2, - }] = eth.BlockID{ + channel.confirmedTransactions[zeroFrameTxID(2).String()] = eth.BlockID{ Number: 101, } channel.confirmedTxUpdated = true @@ -62,11 +68,11 @@ func TestChannelTimeout(t *testing.T) { require.True(t, timeout) } -// TestChannelNextTxData checks the nextTxData function. -func TestChannelNextTxData(t *testing.T) { - log := testlog.Logger(t, log.LvlCrit) +// TestChannelManager_NextTxData tests the nextTxData function. +func TestChannelManager_NextTxData(t *testing.T) { + log := testlog.Logger(t, log.LevelCrit) m := NewChannelManager(log, metrics.NoopMetrics, ChannelConfig{}, &rollup.Config{}) - m.Clear() + m.Clear(eth.BlockID{}) // Nil pending channel should return EOF returnedTxData, err := m.nextTxData(nil) @@ -92,30 +98,112 @@ func TestChannelNextTxData(t *testing.T) { frameNumber: uint16(0), }, } - channel.channelBuilder.PushFrame(frame) + channel.channelBuilder.PushFrames(frame) require.Equal(t, 1, channel.PendingFrames()) // Now the nextTxData function should return the frame returnedTxData, err = m.nextTxData(channel) - expectedTxData := txData{frame} - expectedChannelID := expectedTxData.ID() + expectedTxData := singleFrameTxData(frame) + expectedChannelID := expectedTxData.ID().String() require.NoError(t, err) require.Equal(t, expectedTxData, returnedTxData) require.Equal(t, 0, channel.PendingFrames()) require.Equal(t, expectedTxData, channel.pendingTransactions[expectedChannelID]) } +func TestChannel_NextTxData_singleFrameTx(t *testing.T) { + require := require.New(t) + const n = 6 + lgr := testlog.Logger(t, log.LevelWarn) + ch, err := newChannel(lgr, metrics.NoopMetrics, ChannelConfig{ + MultiFrameTxs: false, + TargetNumFrames: n, + }, &rollup.Config{}, latestL1BlockOrigin) + require.NoError(err) + chID := ch.ID() + + mockframes := makeMockFrameDatas(chID, n+1) + // put multiple frames into channel, but less than target + ch.channelBuilder.PushFrames(mockframes[:n-1]...) + + requireTxData := func(i int) { + require.True(ch.HasTxData(), "expected tx data %d", i) + txdata := ch.NextTxData() + require.Len(txdata.frames, 1) + frame := txdata.frames[0] + require.Len(frame.data, 1) + require.EqualValues(i, frame.data[0]) + require.Equal(frameID{chID: chID, frameNumber: uint16(i)}, frame.id) + } + + for i := 0; i < n-1; i++ { + requireTxData(i) + } + require.False(ch.HasTxData()) + + // put in last two + ch.channelBuilder.PushFrames(mockframes[n-1 : n+1]...) + for i := n - 1; i < n+1; i++ { + requireTxData(i) + } + require.False(ch.HasTxData()) +} + +func TestChannel_NextTxData_multiFrameTx(t *testing.T) { + require := require.New(t) + const n = 6 + lgr := testlog.Logger(t, log.LevelWarn) + ch, err := newChannel(lgr, metrics.NoopMetrics, ChannelConfig{ + MultiFrameTxs: true, + TargetNumFrames: n, + }, &rollup.Config{}, latestL1BlockOrigin) + require.NoError(err) + chID := ch.ID() + + mockframes := makeMockFrameDatas(chID, n+1) + // put multiple frames into channel, but less than target + ch.channelBuilder.PushFrames(mockframes[:n-1]...) + require.False(ch.HasTxData()) + + // put in last two + ch.channelBuilder.PushFrames(mockframes[n-1 : n+1]...) + require.True(ch.HasTxData()) + txdata := ch.NextTxData() + require.Len(txdata.frames, n) + for i := 0; i < n; i++ { + frame := txdata.frames[i] + require.Len(frame.data, 1) + require.EqualValues(i, frame.data[0]) + require.Equal(frameID{chID: chID, frameNumber: uint16(i)}, frame.id) + } + require.False(ch.HasTxData(), "no tx data expected with single pending frame") +} + +func makeMockFrameDatas(id derive.ChannelID, n int) []frameData { + fds := make([]frameData, 0, n) + for i := 0; i < n; i++ { + fds = append(fds, frameData{ + data: []byte{byte(i)}, + id: frameID{ + chID: id, + frameNumber: uint16(i), + }, + }) + } + return fds +} + // TestChannelTxConfirmed checks the [ChannelManager.TxConfirmed] function. func TestChannelTxConfirmed(t *testing.T) { // Create a channel manager - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) m := NewChannelManager(log, metrics.NoopMetrics, ChannelConfig{ // Need to set the channel timeout here so we don't clear pending // channels on confirmation. This would result in [TxConfirmed] // clearing confirmed transactions, and resetting the pendingChannels map ChannelTimeout: 10, }, &rollup.Config{}) - m.Clear() + m.Clear(eth.BlockID{}) // Let's add a valid pending transaction to the channel manager // So we can demonstrate that TxConfirmed's correctness @@ -128,15 +216,15 @@ func TestChannelTxConfirmed(t *testing.T) { frameNumber: uint16(0), }, } - m.currentChannel.channelBuilder.PushFrame(frame) + m.currentChannel.channelBuilder.PushFrames(frame) require.Equal(t, 1, m.currentChannel.PendingFrames()) returnedTxData, err := m.nextTxData(m.currentChannel) - expectedTxData := txData{frame} + expectedTxData := singleFrameTxData(frame) expectedChannelID := expectedTxData.ID() require.NoError(t, err) require.Equal(t, expectedTxData, returnedTxData) require.Equal(t, 0, m.currentChannel.PendingFrames()) - require.Equal(t, expectedTxData, m.currentChannel.pendingTransactions[expectedChannelID]) + require.Equal(t, expectedTxData, m.currentChannel.pendingTransactions[expectedChannelID.String()]) require.Len(t, m.currentChannel.pendingTransactions, 1) // An unknown pending transaction should not be marked as confirmed @@ -144,7 +232,7 @@ func TestChannelTxConfirmed(t *testing.T) { actualChannelID := m.currentChannel.ID() unknownChannelID := derive.ChannelID([derive.ChannelIDLength]byte{0x69}) require.NotEqual(t, actualChannelID, unknownChannelID) - unknownTxID := frameID{chID: unknownChannelID, frameNumber: 0} + unknownTxID := singleFrameTxID(unknownChannelID, 0) blockID := eth.BlockID{Number: 0, Hash: common.Hash{0x69}} m.TxConfirmed(unknownTxID, blockID) require.Empty(t, m.currentChannel.confirmedTransactions) @@ -156,15 +244,15 @@ func TestChannelTxConfirmed(t *testing.T) { m.TxConfirmed(expectedChannelID, blockID) require.Empty(t, m.currentChannel.pendingTransactions) require.Len(t, m.currentChannel.confirmedTransactions, 1) - require.Equal(t, blockID, m.currentChannel.confirmedTransactions[expectedChannelID]) + require.Equal(t, blockID, m.currentChannel.confirmedTransactions[expectedChannelID.String()]) } // TestChannelTxFailed checks the [ChannelManager.TxFailed] function. func TestChannelTxFailed(t *testing.T) { // Create a channel manager - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) m := NewChannelManager(log, metrics.NoopMetrics, ChannelConfig{}, &rollup.Config{}) - m.Clear() + m.Clear(eth.BlockID{}) // Let's add a valid pending transaction to the channel // manager so we can demonstrate correctness @@ -177,22 +265,22 @@ func TestChannelTxFailed(t *testing.T) { frameNumber: uint16(0), }, } - m.currentChannel.channelBuilder.PushFrame(frame) + m.currentChannel.channelBuilder.PushFrames(frame) require.Equal(t, 1, m.currentChannel.PendingFrames()) returnedTxData, err := m.nextTxData(m.currentChannel) - expectedTxData := txData{frame} + expectedTxData := singleFrameTxData(frame) expectedChannelID := expectedTxData.ID() require.NoError(t, err) require.Equal(t, expectedTxData, returnedTxData) require.Equal(t, 0, m.currentChannel.PendingFrames()) - require.Equal(t, expectedTxData, m.currentChannel.pendingTransactions[expectedChannelID]) + require.Equal(t, expectedTxData, m.currentChannel.pendingTransactions[expectedChannelID.String()]) require.Len(t, m.currentChannel.pendingTransactions, 1) // Trying to mark an unknown pending transaction as failed // shouldn't modify state - m.TxFailed(frameID{}) + m.TxFailed(zeroFrameTxID(0)) require.Equal(t, 0, m.currentChannel.PendingFrames()) - require.Equal(t, expectedTxData, m.currentChannel.pendingTransactions[expectedChannelID]) + require.Equal(t, expectedTxData, m.currentChannel.pendingTransactions[expectedChannelID.String()]) // Now we still have a pending transaction // Let's mark it as failed diff --git a/op-batcher/batcher/config.go b/op-batcher/batcher/config.go index 1a15c5d27e52..0fb33690171a 100644 --- a/op-batcher/batcher/config.go +++ b/op-batcher/batcher/config.go @@ -10,6 +10,8 @@ import ( "github.com/ethereum-optimism/optimism/op-batcher/compressor" "github.com/ethereum-optimism/optimism/op-batcher/flags" + plasma "github.com/ethereum-optimism/optimism/op-plasma" + "github.com/ethereum-optimism/optimism/op-service/eigenda" oplog "github.com/ethereum-optimism/optimism/op-service/log" opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" "github.com/ethereum-optimism/optimism/op-service/oppprof" @@ -51,8 +53,21 @@ type CLIConfig struct { MaxPendingTransactions uint64 // MaxL1TxSize is the maximum size of a batch tx submitted to L1. + // If using blobs, this setting is ignored and the max blob size is used. MaxL1TxSize uint64 + // The target number of frames to create per channel. Controls number of blobs + // per blob tx, if using Blob DA. + TargetNumFrames int + + // ApproxComprRatio to assume (only [compressor.RatioCompressor]). + // Should be slightly smaller than average from experiments to avoid the + // chances of creating a small additional leftover frame. + ApproxComprRatio float64 + + // Type of compressor to use. Must be one of [compressor.KindKeys]. + Compressor string + Stopped bool BatchType uint @@ -61,15 +76,21 @@ type CLIConfig struct { // the data availability type to use for posting batches, e.g. blobs vs calldata. DataAvailabilityType flags.DataAvailabilityType + // TestUseMaxTxSizeForBlobs allows to set the blob size with MaxL1TxSize. + // Should only be used for testing purposes. + TestUseMaxTxSizeForBlobs bool + // ActiveSequencerCheckDuration is the duration between checks to determine the active sequencer endpoint. ActiveSequencerCheckDuration time.Duration - TxMgrConfig txmgr.CLIConfig - LogConfig oplog.CLIConfig - MetricsConfig opmetrics.CLIConfig - PprofConfig oppprof.CLIConfig - CompressorConfig compressor.CLIConfig - RPC oprpc.CLIConfig + TxMgrConfig txmgr.CLIConfig + LogConfig oplog.CLIConfig + MetricsConfig opmetrics.CLIConfig + PprofConfig oppprof.CLIConfig + RPC oprpc.CLIConfig + PlasmaDA plasma.CLIConfig + DAConfig eigenda.CLIConfig + PrefixDerivationEnabled bool } func (c *CLIConfig) Check() error { @@ -89,11 +110,20 @@ func (c *CLIConfig) Check() error { return errors.New("must set PollInterval") } if c.MaxL1TxSize <= 1 { - return errors.New("MaxL1TxSize must be greater than 0") + return errors.New("MaxL1TxSize must be greater than 1") + } + if c.TargetNumFrames < 1 { + return errors.New("TargetNumFrames must be at least 1") + } + if c.Compressor == compressor.RatioKind && (c.ApproxComprRatio <= 0 || c.ApproxComprRatio > 1) { + return fmt.Errorf("invalid ApproxComprRatio %v for ratio compressor", c.ApproxComprRatio) } if c.BatchType > 1 { return fmt.Errorf("unknown batch type: %v", c.BatchType) } + if c.DataAvailabilityType == flags.BlobsType && c.TargetNumFrames > 6 { + return errors.New("too many frames for blob transactions, max 6") + } if !flags.ValidDataAvailabilityType(c.DataAvailabilityType) { return fmt.Errorf("unknown data availability type: %q", c.DataAvailabilityType) } @@ -126,6 +156,9 @@ func NewConfig(ctx *cli.Context) *CLIConfig { MaxPendingTransactions: ctx.Uint64(flags.MaxPendingTransactionsFlag.Name), MaxChannelDuration: ctx.Uint64(flags.MaxChannelDurationFlag.Name), MaxL1TxSize: ctx.Uint64(flags.MaxL1TxSizeBytesFlag.Name), + TargetNumFrames: ctx.Int(flags.TargetNumFramesFlag.Name), + ApproxComprRatio: ctx.Float64(flags.ApproxComprRatioFlag.Name), + Compressor: ctx.String(flags.CompressorFlag.Name), Stopped: ctx.Bool(flags.StoppedFlag.Name), BatchType: ctx.Uint(flags.BatchTypeFlag.Name), DataAvailabilityType: flags.DataAvailabilityType(ctx.String(flags.DataAvailabilityTypeFlag.Name)), @@ -134,7 +167,9 @@ func NewConfig(ctx *cli.Context) *CLIConfig { LogConfig: oplog.ReadCLIConfig(ctx), MetricsConfig: opmetrics.ReadCLIConfig(ctx), PprofConfig: oppprof.ReadCLIConfig(ctx), - CompressorConfig: compressor.ReadCLIConfig(ctx), RPC: oprpc.ReadCLIConfig(ctx), + PlasmaDA: plasma.ReadCLIConfig(ctx), + DAConfig: eigenda.ReadCLIConfig(ctx), + PrefixDerivationEnabled: ctx.Bool(flags.PrefixDerivationEnabledFlag.Name), } } diff --git a/op-batcher/batcher/config_test.go b/op-batcher/batcher/config_test.go index c6a0d1e1e647..18a6227e0011 100644 --- a/op-batcher/batcher/config_test.go +++ b/op-batcher/batcher/config_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/ethereum-optimism/optimism/op-batcher/batcher" + "github.com/ethereum-optimism/optimism/op-batcher/compressor" "github.com/ethereum-optimism/optimism/op-batcher/flags" "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/metrics" @@ -24,6 +25,8 @@ func validBatcherConfig() batcher.CLIConfig { PollInterval: time.Second, MaxPendingTransactions: 0, MaxL1TxSize: 10, + TargetNumFrames: 1, + Compressor: "shadow", Stopped: false, BatchType: 0, DataAvailabilityType: flags.CalldataType, @@ -70,7 +73,7 @@ func TestBatcherConfig(t *testing.T) { { name: "max L1 tx size too small", override: func(c *batcher.CLIConfig) { c.MaxL1TxSize = 0 }, - errString: "MaxL1TxSize must be greater than 0", + errString: "MaxL1TxSize must be greater than 1", }, { name: "invalid batch type close", @@ -87,6 +90,27 @@ func TestBatcherConfig(t *testing.T) { override: func(c *batcher.CLIConfig) { c.DataAvailabilityType = "foo" }, errString: "unknown data availability type: \"foo\"", }, + { + name: "zero TargetNumFrames", + override: func(c *batcher.CLIConfig) { c.TargetNumFrames = 0 }, + errString: "TargetNumFrames must be at least 1", + }, + { + name: "larger 6 TargetNumFrames for blobs", + override: func(c *batcher.CLIConfig) { + c.TargetNumFrames = 7 + c.DataAvailabilityType = flags.BlobsType + }, + errString: "too many frames for blob transactions, max 6", + }, + { + name: "invalid compr ratio for ratio compressor", + override: func(c *batcher.CLIConfig) { + c.ApproxComprRatio = 4.2 + c.Compressor = compressor.RatioKind + }, + errString: "invalid ApproxComprRatio 4.2 for ratio compressor", + }, } for _, test := range tests { diff --git a/op-batcher/batcher/driver.go b/op-batcher/batcher/driver.go index 919854c51999..ee3712bc30ef 100644 --- a/op-batcher/batcher/driver.go +++ b/op-batcher/batcher/driver.go @@ -10,16 +10,19 @@ import ( "sync" "time" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum-optimism/optimism/op-batcher/metrics" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + plasma "github.com/ethereum-optimism/optimism/op-plasma" "github.com/ethereum-optimism/optimism/op-service/dial" + "github.com/ethereum-optimism/optimism/op-service/eigenda" "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/proto/gen/op_service/v1" "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "google.golang.org/protobuf/proto" ) var ErrBatcherNotRunning = errors.New("batcher is not running") @@ -38,14 +41,17 @@ type RollupClient interface { // DriverSetup is the collection of input/output interfaces and configuration that the driver operates on. type DriverSetup struct { - Log log.Logger - Metr metrics.Metricer - RollupConfig *rollup.Config - Config BatcherConfig - Txmgr txmgr.TxManager - L1Client L1Client - EndpointProvider dial.L2EndpointProvider - ChannelConfig ChannelConfig + Log log.Logger + Metr metrics.Metricer + RollupConfig *rollup.Config + Config BatcherConfig + Txmgr txmgr.TxManager + L1Client L1Client + EndpointProvider dial.L2EndpointProvider + ChannelConfig ChannelConfig + PlasmaDA *plasma.DAClient + DA eigenda.IEigenDA + PrefixDerivationEnabled bool } // BatchSubmitter encapsulates a service responsible for submitting L2 tx @@ -91,7 +97,7 @@ func (l *BatchSubmitter) StartBatchSubmitting() error { l.shutdownCtx, l.cancelShutdownCtx = context.WithCancel(context.Background()) l.killCtx, l.cancelKillCtx = context.WithCancel(context.Background()) - l.state.Clear() + l.clearState(l.shutdownCtx) l.lastStoredBlock = eth.BlockID{} l.wg.Add(1) @@ -252,12 +258,36 @@ func (l *BatchSubmitter) calculateL2BlockRangeToStore(ctx context.Context) (eth. func (l *BatchSubmitter) loop() { defer l.wg.Done() + receiptsCh := make(chan txmgr.TxReceipt[txID]) + queue := txmgr.NewQueue[txID](l.killCtx, l.Txmgr, l.Config.MaxPendingTransactions) + + // start the receipt/result processing loop + receiptLoopDone := make(chan struct{}) + defer close(receiptLoopDone) // shut down receipt loop + go func() { + for { + select { + case r := <-receiptsCh: + l.Log.Info("handling receipt", "id", r.ID) + l.handleReceipt(r) + case <-receiptLoopDone: + l.Log.Info("receipt processing loop done") + return + } + } + }() + ticker := time.NewTicker(l.Config.PollInterval) defer ticker.Stop() - receiptsCh := make(chan txmgr.TxReceipt[txData]) - queue := txmgr.NewQueue[txData](l.killCtx, l.Txmgr, l.Config.MaxPendingTransactions) - + publishAndWait := func() { + l.publishStateToL1(queue, receiptsCh) + if !l.Txmgr.IsClosed() { + queue.Wait() + } else { + l.Log.Info("Txmgr is closed, remaining channel data won't be sent") + } + } for { select { case <-ticker.C: @@ -270,14 +300,18 @@ func (l *BatchSubmitter) loop() { l.Log.Error("Error closing the channel manager to handle a L2 reorg", "err", err) } } - l.publishStateToL1(queue, receiptsCh, true) - l.state.Clear() + // on reorg we want to publish all pending state then wait until each result clears before resetting + // the state. + publishAndWait() + l.clearState(l.shutdownCtx) continue } - l.publishStateToL1(queue, receiptsCh, false) - case r := <-receiptsCh: - l.handleReceipt(r) + l.publishStateToL1(queue, receiptsCh) case <-l.shutdownCtx.Done(): + if l.Txmgr.IsClosed() { + l.Log.Info("Txmgr is closed, remaining channel data won't be sent") + return + } // This removes any never-submitted pending channels, so these do not have to be drained with transactions. // Any remaining unfinished channel is terminated, so its data gets submitted. err := l.state.Close() @@ -288,49 +322,73 @@ func (l *BatchSubmitter) loop() { l.Log.Error("Error closing the channel manager on shutdown", "err", err) } } - l.publishStateToL1(queue, receiptsCh, true) + publishAndWait() l.Log.Info("Finished publishing all remaining channel data") return } } } -// publishStateToL1 loops through the block data loaded into `state` and -// submits the associated data to the L1 in the form of channel frames. -func (l *BatchSubmitter) publishStateToL1(queue *txmgr.Queue[txData], receiptsCh chan txmgr.TxReceipt[txData], drain bool) { - txDone := make(chan struct{}) - // send/wait and receipt reading must be on a separate goroutines to avoid deadlocks - go func() { - defer func() { - if drain { - // if draining, we wait for all transactions to complete - queue.Wait() - } - close(txDone) - }() - for { - err := l.publishTxToL1(l.killCtx, queue, receiptsCh) - if err != nil { - if drain && err != io.EOF { - l.Log.Error("error sending tx while draining state", "err", err) - } - return +// publishStateToL1 queues up all pending TxData to be published to the L1, returning when there is +// no more data to queue for publishing or if there was an error queing the data. +func (l *BatchSubmitter) publishStateToL1(queue *txmgr.Queue[txID], receiptsCh chan txmgr.TxReceipt[txID]) { + for { + // if the txmgr is closed, we stop the transaction sending + if l.Txmgr.IsClosed() { + l.Log.Info("Txmgr is closed, aborting state publishing") + return + } + err := l.publishTxToL1(l.killCtx, queue, receiptsCh) + if err != nil { + if err != io.EOF { + l.Log.Error("error publishing tx to l1", "err", err) } + return } - }() + } +} + +// clearState clears the state of the channel manager +func (l *BatchSubmitter) clearState(ctx context.Context) { + l.Log.Info("Clearing state") + defer l.Log.Info("State cleared") + + clearStateWithL1Origin := func() bool { + l1SafeOrigin, err := l.safeL1Origin(ctx) + if err != nil { + l.Log.Warn("Failed to query L1 safe origin, will retry", "err", err) + return false + } else { + l.Log.Info("Clearing state with safe L1 origin", "origin", l1SafeOrigin) + l.state.Clear(l1SafeOrigin) + return true + } + } + + // Attempt to set the L1 safe origin and clear the state, if fetching fails -- fall through to an infinite retry + if clearStateWithL1Origin() { + return + } + + tick := time.NewTicker(5 * time.Second) + defer tick.Stop() for { select { - case r := <-receiptsCh: - l.handleReceipt(r) - case <-txDone: + case <-tick.C: + if clearStateWithL1Origin() { + return + } + case <-ctx.Done(): + l.Log.Warn("Clearing state cancelled") + l.state.Clear(eth.BlockID{}) return } } } // publishTxToL1 submits a single state tx to the L1 -func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[txData], receiptsCh chan txmgr.TxReceipt[txData]) error { +func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[txID], receiptsCh chan txmgr.TxReceipt[txID]) error { // send all available transactions l1tip, err := l.l1Tip(ctx) if err != nil { @@ -341,6 +399,7 @@ func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[t // Collect next transaction data txdata, err := l.state.TxData(l1tip.ID()) + if err == io.EOF { l.Log.Trace("no transaction data available") return err @@ -349,23 +408,45 @@ func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[t return err } - if err = l.sendTransaction(txdata, queue, receiptsCh); err != nil { + if err = l.sendTransaction(ctx, txdata, queue, receiptsCh); err != nil { return fmt.Errorf("BatchSubmitter.sendTransaction failed: %w", err) } return nil } -// sendTransaction creates & submits a transaction to the batch inbox address with the given `txData`. -// It currently uses the underlying `txmgr` to handle transaction sending & price management. -// This is a blocking method. It should not be called concurrently. -func (l *BatchSubmitter) sendTransaction(txdata txData, queue *txmgr.Queue[txData], receiptsCh chan txmgr.TxReceipt[txData]) error { +func (l *BatchSubmitter) safeL1Origin(ctx context.Context) (eth.BlockID, error) { + ctx, cancel := context.WithTimeout(ctx, l.Config.NetworkTimeout) + defer cancel() + + c, err := l.EndpointProvider.RollupClient(ctx) + if err != nil { + log.Error("Failed to get rollup client", "err", err) + return eth.BlockID{}, fmt.Errorf("safe l1 origin: error getting rollup client: %w", err) + } + + status, err := c.SyncStatus(ctx) + if err != nil { + log.Error("Failed to get sync status", "err", err) + return eth.BlockID{}, fmt.Errorf("safe l1 origin: error getting sync status: %w", err) + } + + // If the safe L2 block origin is 0, we are at the genesis block and should use the L1 origin from the rollup config. + if status.SafeL2.L1Origin.Number == 0 { + return l.RollupConfig.Genesis.L1, nil + } + + return status.SafeL2.L1Origin, nil +} + +// sendTransaction creates & queues for sending a transaction to the batch inbox address with the given `txData`. +// The method will block if the queue's MaxPendingTransactions is exceeded. +func (l *BatchSubmitter) sendTransaction(ctx context.Context, txdata txData, queue *txmgr.Queue[txID], receiptsCh chan txmgr.TxReceipt[txID]) error { + var err error // Do the gas estimation offline. A value of 0 will cause the [txmgr] to estimate the gas limit. - data := txdata.Bytes() var candidate *txmgr.TxCandidate if l.Config.UseBlobs { - var err error - if candidate, err = l.blobTxCandidate(data); err != nil { + if candidate, err = l.blobTxCandidate(txdata); err != nil { // We could potentially fall through and try a calldata tx instead, but this would // likely result in the chain spending more in gas fees than it is tuned for, so best // to just fail. We do not expect this error to trigger unless there is a serious bug @@ -373,6 +454,73 @@ func (l *BatchSubmitter) sendTransaction(txdata txData, queue *txmgr.Queue[txDat return fmt.Errorf("could not create blob tx candidate: %w", err) } } else { + // sanity check + if nf := len(txdata.frames); nf != 1 { + l.Log.Crit("unexpected number of frames in calldata tx", "num_frames", nf) + } + data := txdata.CallData() + + var wrappedData []byte + blobInfo, err := l.DA.DisperseBlob(context.Background(), data) + if err != nil { // fallback to posting raw frame to calldata, although still within this proto wrapper + l.Log.Error("Unable to publish batch frameset to EigenDA, falling back to calldata", "err", err) + if l.PrefixDerivationEnabled { + // do not wrap + l.Log.Info("Prefix derivation enabled, not wrapping calldata with FrameRef") + wrappedData = data + } else { + calldataFrame := &op_service.CalldataFrame{ + Value: &op_service.CalldataFrame_Frame{ + Frame: data, + }, + } + wrappedData, err = proto.Marshal(calldataFrame) + if err != nil { + return err + } + } + } else { // happy path, post raw frame to eigenda then post frameRef to calldata + quorumIDs := make([]uint32, len(blobInfo.BlobHeader.BlobQuorumParams)) + for i := range quorumIDs { + quorumIDs[i] = blobInfo.BlobHeader.BlobQuorumParams[i].QuorumNumber + } + calldataFrame := &op_service.CalldataFrame{ + Value: &op_service.CalldataFrame_FrameRef{ + FrameRef: &op_service.FrameRef{ + BatchHeaderHash: blobInfo.BlobVerificationProof.BatchMetadata.BatchHeaderHash, + BlobIndex: blobInfo.BlobVerificationProof.BlobIndex, + ReferenceBlockNumber: blobInfo.BlobVerificationProof.BatchMetadata.BatchHeader.ReferenceBlockNumber, + QuorumIds: quorumIDs, + BlobLength: uint32(len(data)), + }, + }, + } + wrappedData, err = proto.Marshal(calldataFrame) + if err != nil { + return err + } + + if l.PrefixDerivationEnabled { + // prepend the derivation version to the data + l.Log.Info("Prepending derivation version to calldata") + wrappedData = append([]byte{eigenda.DerivationVersionEigenda}, wrappedData...) + } + } + + data = wrappedData + + // if plasma DA is enabled we post the txdata to the DA Provider and replace it with the commitment. + if l.Config.UsePlasma { + comm, err := l.PlasmaDA.SetInput(ctx, data) + if err != nil { + l.Log.Error("Failed to post input to Plasma DA", "error", err) + // requeue frame if we fail to post to the DA Provider so it can be retried + l.recordFailedTx(txdata.ID(), err) + return nil + } + // signal plasma commitment tx with TxDataVersion1 + data = comm.TxData() + } candidate = l.calldataTxCandidate(data) } @@ -384,29 +532,35 @@ func (l *BatchSubmitter) sendTransaction(txdata txData, queue *txmgr.Queue[txDat candidate.GasLimit = intrinsicGas } - queue.Send(txdata, *candidate, receiptsCh) + queue.Send(txdata.ID(), *candidate, receiptsCh) return nil } -func (l *BatchSubmitter) blobTxCandidate(data []byte) (*txmgr.TxCandidate, error) { - var b eth.Blob - if err := b.FromData(data); err != nil { - return nil, fmt.Errorf("data could not be converted to blob: %w", err) +func (l *BatchSubmitter) blobTxCandidate(data txData) (*txmgr.TxCandidate, error) { + blobs, err := data.Blobs() + if err != nil { + return nil, fmt.Errorf("generating blobs for tx data: %w", err) } + size := data.Len() + lastSize := len(data.frames[len(data.frames)-1].data) + l.Log.Info("building Blob transaction candidate", + "size", size, "last_size", lastSize, "num_blobs", len(blobs)) + l.Metr.RecordBlobUsedBytes(lastSize) return &txmgr.TxCandidate{ To: &l.RollupConfig.BatchInboxAddress, - Blobs: []*eth.Blob{&b}, + Blobs: blobs, }, nil } func (l *BatchSubmitter) calldataTxCandidate(data []byte) *txmgr.TxCandidate { + l.Log.Info("building Calldata transaction candidate", "size", len(data)) return &txmgr.TxCandidate{ To: &l.RollupConfig.BatchInboxAddress, TxData: data, } } -func (l *BatchSubmitter) handleReceipt(r txmgr.TxReceipt[txData]) { +func (l *BatchSubmitter) handleReceipt(r txmgr.TxReceipt[txID]) { // Record TX Status if r.Err != nil { l.recordFailedTx(r.ID, r.Err) @@ -423,15 +577,15 @@ func (l *BatchSubmitter) recordL1Tip(l1tip eth.L1BlockRef) { l.Metr.RecordLatestL1Block(l1tip) } -func (l *BatchSubmitter) recordFailedTx(txd txData, err error) { - l.Log.Warn("Transaction failed to send", logFields(txd, err)...) - l.state.TxFailed(txd.ID()) +func (l *BatchSubmitter) recordFailedTx(id txID, err error) { + l.Log.Warn("Transaction failed to send", logFields(id, err)...) + l.state.TxFailed(id) } -func (l *BatchSubmitter) recordConfirmedTx(txd txData, receipt *types.Receipt) { - l.Log.Info("Transaction confirmed", logFields(txd, receipt)...) +func (l *BatchSubmitter) recordConfirmedTx(id txID, receipt *types.Receipt) { + l.Log.Info("Transaction confirmed", logFields(id, receipt)...) l1block := eth.ReceiptBlockID(receipt) - l.state.TxConfirmed(txd.ID(), l1block) + l.state.TxConfirmed(id, l1block) } // l1Tip gets the current L1 tip as a L1BlockRef. The passed context is assumed @@ -449,8 +603,8 @@ func (l *BatchSubmitter) l1Tip(ctx context.Context) (eth.L1BlockRef, error) { func logFields(xs ...any) (fs []any) { for _, x := range xs { switch v := x.(type) { - case txData: - fs = append(fs, "frame_id", v.ID(), "data_len", v.Len()) + case txID: + fs = append(fs, "tx_id", v.String()) case *types.Receipt: fs = append(fs, "tx", v.TxHash, "block", eth.ReceiptBlockID(v)) case error: diff --git a/op-batcher/batcher/driver_test.go b/op-batcher/batcher/driver_test.go new file mode 100644 index 000000000000..df72fa28d49a --- /dev/null +++ b/op-batcher/batcher/driver_test.go @@ -0,0 +1,119 @@ +package batcher + +import ( + "context" + "errors" + "testing" + + "github.com/ethereum-optimism/optimism/op-batcher/metrics" + "github.com/ethereum-optimism/optimism/op-service/dial" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/testutils" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +type mockL2EndpointProvider struct { + ethClient *testutils.MockL2Client + ethClientErr error + rollupClient *testutils.MockRollupClient + rollupClientErr error +} + +func newEndpointProvider() *mockL2EndpointProvider { + return &mockL2EndpointProvider{ + ethClient: new(testutils.MockL2Client), + rollupClient: new(testutils.MockRollupClient), + } +} + +func (p *mockL2EndpointProvider) EthClient(context.Context) (dial.EthClientInterface, error) { + return p.ethClient, p.ethClientErr +} + +func (p *mockL2EndpointProvider) RollupClient(context.Context) (dial.RollupClientInterface, error) { + return p.rollupClient, p.rollupClientErr +} + +func (p *mockL2EndpointProvider) Close() {} + +const genesisL1Origin = uint64(123) + +func setup(t *testing.T) (*BatchSubmitter, *mockL2EndpointProvider) { + ep := newEndpointProvider() + + cfg := defaultTestRollupConfig + cfg.Genesis.L1.Number = genesisL1Origin + + return NewBatchSubmitter(DriverSetup{ + Log: testlog.Logger(t, log.LevelDebug), + Metr: metrics.NoopMetrics, + RollupConfig: &cfg, + EndpointProvider: ep, + }), ep +} + +func TestBatchSubmitter_SafeL1Origin(t *testing.T) { + bs, ep := setup(t) + + tests := []struct { + name string + currentSafeOrigin uint64 + failsToFetchSyncStatus bool + expectResult uint64 + expectErr bool + }{ + { + name: "ExistingSafeL1Origin", + currentSafeOrigin: 999, + expectResult: 999, + }, + { + name: "NoExistingSafeL1OriginUsesGenesis", + currentSafeOrigin: 0, + expectResult: genesisL1Origin, + }, + { + name: "ErrorFetchingSyncStatus", + failsToFetchSyncStatus: true, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.failsToFetchSyncStatus { + ep.rollupClient.ExpectSyncStatus(ð.SyncStatus{}, errors.New("failed to fetch sync status")) + + } else { + ep.rollupClient.ExpectSyncStatus(ð.SyncStatus{ + SafeL2: eth.L2BlockRef{ + L1Origin: eth.BlockID{ + Number: tt.currentSafeOrigin, + }, + }, + }, nil) + } + + id, err := bs.safeL1Origin(context.Background()) + + if tt.expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tt.expectResult, id.Number) + } + }) + } + +} + +func TestBatchSubmitter_SafeL1Origin_FailsToResolveRollupClient(t *testing.T) { + bs, ep := setup(t) + + ep.rollupClientErr = errors.New("failed to resolve rollup client") + + _, err := bs.safeL1Origin(context.Background()) + require.Error(t, err) +} diff --git a/op-batcher/batcher/service.go b/op-batcher/batcher/service.go index 570a051c7112..8a575c0dd2c9 100644 --- a/op-batcher/batcher/service.go +++ b/op-batcher/batcher/service.go @@ -16,9 +16,12 @@ import ( "github.com/ethereum-optimism/optimism/op-batcher/flags" "github.com/ethereum-optimism/optimism/op-batcher/metrics" "github.com/ethereum-optimism/optimism/op-batcher/rpc" + "github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/rollup" + plasma "github.com/ethereum-optimism/optimism/op-plasma" "github.com/ethereum-optimism/optimism/op-service/cliapp" "github.com/ethereum-optimism/optimism/op-service/dial" + "github.com/ethereum-optimism/optimism/op-service/eigenda" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/httputil" opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" @@ -27,9 +30,7 @@ import ( "github.com/ethereum-optimism/optimism/op-service/txmgr" ) -var ( - ErrAlreadyStopped = errors.New("already stopped") -) +var ErrAlreadyStopped = errors.New("already stopped") type BatcherConfig struct { NetworkTimeout time.Duration @@ -38,6 +39,10 @@ type BatcherConfig struct { // UseBlobs is true if the batcher should use blobs instead of calldata for posting blobs UseBlobs bool + + // UsePlasma is true if the rollup config has a DA challenge address so the batcher + // will post inputs to the Plasma DA server and post commitments to blobs or calldata. + UsePlasma bool } // BatcherService represents a full batch-submitter instance and its resources, @@ -48,6 +53,7 @@ type BatcherService struct { L1Client *ethclient.Client EndpointProvider dial.L2EndpointProvider TxManager txmgr.TxManager + PlasmaDA *plasma.DAClient BatcherConfig @@ -68,6 +74,9 @@ type BatcherService struct { stopped atomic.Bool NotSubmittingOnStart bool + + DA eigenda.IEigenDA + PrefixDerivationEnabled bool } // BatcherServiceFromCLIConfig creates a new BatcherService from a CLIConfig. @@ -110,6 +119,14 @@ func (bs *BatcherService) initFromCLIConfig(ctx context.Context, version string, if err := bs.initPProf(cfg); err != nil { return fmt.Errorf("failed to init profiling: %w", err) } + // init before driver + if err := bs.initPlasmaDA(cfg); err != nil { + return fmt.Errorf("failed to init plasma DA: %w", err) + } + if err := bs.initDA(cfg); err != nil { + return fmt.Errorf("failed to init DA: %w", err) + } + bs.PrefixDerivationEnabled = cfg.PrefixDerivationEnabled bs.initDriver() if err := bs.initRPCServer(cfg); err != nil { return fmt.Errorf("failed to start RPC server: %w", err) @@ -172,34 +189,62 @@ func (bs *BatcherService) initRollupConfig(ctx context.Context) error { if err := bs.RollupConfig.Check(); err != nil { return fmt.Errorf("invalid rollup config: %w", err) } + bs.RollupConfig.LogDescription(bs.Log, chaincfg.L2ChainIDToNetworkDisplayName) return nil } func (bs *BatcherService) initChannelConfig(cfg *CLIConfig) error { - bs.ChannelConfig = ChannelConfig{ + cc := ChannelConfig{ SeqWindowSize: bs.RollupConfig.SeqWindowSize, ChannelTimeout: bs.RollupConfig.ChannelTimeout, MaxChannelDuration: cfg.MaxChannelDuration, + MaxFrameSize: cfg.MaxL1TxSize - 1, // account for version byte prefix; reset for blobs + TargetNumFrames: cfg.TargetNumFrames, SubSafetyMargin: cfg.SubSafetyMargin, - CompressorConfig: cfg.CompressorConfig.Config(), BatchType: cfg.BatchType, } switch cfg.DataAvailabilityType { case flags.BlobsType: - bs.ChannelConfig.MaxFrameSize = eth.MaxBlobDataSize + if !cfg.TestUseMaxTxSizeForBlobs { + // account for version byte prefix + cc.MaxFrameSize = eth.MaxBlobDataSize - 1 + } + cc.MultiFrameTxs = true bs.UseBlobs = true case flags.CalldataType: - bs.ChannelConfig.MaxFrameSize = cfg.MaxL1TxSize bs.UseBlobs = false default: return fmt.Errorf("unknown data availability type: %v", cfg.DataAvailabilityType) } - bs.ChannelConfig.MaxFrameSize-- // subtract 1 byte for version - if err := bs.ChannelConfig.Check(); err != nil { + if bs.UsePlasma && cc.MaxFrameSize > plasma.MaxInputSize { + return fmt.Errorf("max frame size %d exceeds plasma max input size %d", cc.MaxFrameSize, plasma.MaxInputSize) + } + + cc.InitCompressorConfig(cfg.ApproxComprRatio, cfg.Compressor) + + if bs.UseBlobs && !bs.RollupConfig.IsEcotone(uint64(time.Now().Unix())) { + bs.Log.Error("Cannot use Blob data before Ecotone!") // log only, the batcher may not be actively running. + } + if !bs.UseBlobs && bs.RollupConfig.IsEcotone(uint64(time.Now().Unix())) { + bs.Log.Warn("Ecotone upgrade is active, but batcher is not configured to use Blobs!") + } + + if err := cc.Check(); err != nil { return fmt.Errorf("invalid channel configuration: %w", err) } + bs.Log.Info("Initialized channel-config", + "use_blobs", bs.UseBlobs, + "use_plasma", bs.UsePlasma, + "max_frame_size", cc.MaxFrameSize, + "target_num_frames", cc.TargetNumFrames, + "compressor", cc.CompressorConfig.Kind, + "max_channel_duration", cc.MaxChannelDuration, + "channel_timeout", cc.ChannelTimeout, + "batch_type", cc.BatchType, + "sub_safety_margin", cc.SubSafetyMargin) + bs.ChannelConfig = cc return nil } @@ -250,17 +295,32 @@ func (bs *BatcherService) initMetricsServer(cfg *CLIConfig) error { func (bs *BatcherService) initDriver() { bs.driver = NewBatchSubmitter(DriverSetup{ - Log: bs.Log, - Metr: bs.Metrics, - RollupConfig: bs.RollupConfig, - Config: bs.BatcherConfig, - Txmgr: bs.TxManager, - L1Client: bs.L1Client, - EndpointProvider: bs.EndpointProvider, - ChannelConfig: bs.ChannelConfig, + Log: bs.Log, + Metr: bs.Metrics, + RollupConfig: bs.RollupConfig, + Config: bs.BatcherConfig, + Txmgr: bs.TxManager, + L1Client: bs.L1Client, + EndpointProvider: bs.EndpointProvider, + ChannelConfig: bs.ChannelConfig, + PlasmaDA: bs.PlasmaDA, + DA: bs.DA, + PrefixDerivationEnabled: bs.PrefixDerivationEnabled, }) } +func (bs *BatcherService) initDA(cfg *CLIConfig) error { + bs.DA = &eigenda.EigenDA{ + Config: eigenda.Config{ + RPC: cfg.DAConfig.RPC, + StatusQueryTimeout: cfg.DAConfig.StatusQueryTimeout, + StatusQueryRetryInterval: cfg.DAConfig.StatusQueryRetryInterval, + }, + Log: bs.Log, + } + return nil +} + func (bs *BatcherService) initRPCServer(cfg *CLIConfig) error { server := oprpc.NewServer( cfg.RPC.ListenAddr, @@ -281,6 +341,16 @@ func (bs *BatcherService) initRPCServer(cfg *CLIConfig) error { return nil } +func (bs *BatcherService) initPlasmaDA(cfg *CLIConfig) error { + config := cfg.PlasmaDA + if err := config.Check(); err != nil { + return err + } + bs.PlasmaDA = config.NewDAClient() + bs.UsePlasma = config.Enabled + return nil +} + // Start runs once upon start of the batcher lifecycle, // and starts batch-submission work if the batcher is configured to start submit data on startup. func (bs *BatcherService) Start(_ context.Context) error { @@ -313,6 +383,12 @@ func (bs *BatcherService) Stop(ctx context.Context) error { } bs.Log.Info("Stopping batcher") + // close the TxManager first, so that new work is denied, in-flight work is cancelled as early as possible + // (transactions which are expected to be confirmed are still waited for) + if bs.TxManager != nil { + bs.TxManager.Close() + } + var result error if bs.driver != nil { if err := bs.driver.StopBatchSubmittingIfRunning(ctx); err != nil { @@ -336,9 +412,6 @@ func (bs *BatcherService) Stop(ctx context.Context) error { result = errors.Join(result, fmt.Errorf("failed to close balance metricer: %w", err)) } } - if bs.TxManager != nil { - bs.TxManager.Close() - } if bs.metricsSrv != nil { if err := bs.metricsSrv.Stop(ctx); err != nil { diff --git a/op-batcher/batcher/tx_data.go b/op-batcher/batcher/tx_data.go index d32d44be2c53..73e1adbbe179 100644 --- a/op-batcher/batcher/tx_data.go +++ b/op-batcher/batcher/tx_data.go @@ -2,8 +2,10 @@ package batcher import ( "fmt" + "strings" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-service/eth" ) // txData represents the data for a single transaction. @@ -12,47 +14,89 @@ import ( // might change in the future to allow for multiple frames from possibly // different channels. type txData struct { - frame frameData + frames []frameData } -// ID returns the id for this transaction data. It can be used as a map key. +func singleFrameTxData(frame frameData) txData { + return txData{frames: []frameData{frame}} +} + +// ID returns the id for this transaction data. Its String() can be used as a map key. func (td *txData) ID() txID { - return td.frame.id + id := make(txID, 0, len(td.frames)) + for _, f := range td.frames { + id = append(id, f.id) + } + return id +} + +// CallData returns the transaction data as calldata. +// It's a version byte (0) followed by the concatenated frames for this transaction. +func (td *txData) CallData() []byte { + data := make([]byte, 1, 1+td.Len()) + data[0] = derive.DerivationVersion0 + for _, f := range td.frames { + data = append(data, f.data...) + } + return data } -// Bytes returns the transaction data. It's a version byte (0) followed by the -// concatenated frames for this transaction. -func (td *txData) Bytes() []byte { - return append([]byte{derive.DerivationVersion0}, td.frame.data...) +func (td *txData) Blobs() ([]*eth.Blob, error) { + blobs := make([]*eth.Blob, 0, len(td.frames)) + for _, f := range td.frames { + var blob eth.Blob + if err := blob.FromData(append([]byte{derive.DerivationVersion0}, f.data...)); err != nil { + return nil, err + } + blobs = append(blobs, &blob) + } + return blobs, nil } -func (td *txData) Len() int { - return 1 + len(td.frame.data) +// Len returns the sum of all the sizes of data in all frames. +// Len only counts the data itself and doesn't account for the version byte(s). +func (td *txData) Len() (l int) { + for _, f := range td.frames { + l += len(f.data) + } + return l } // Frame returns the single frame of this tx data. -// -// Note: when the batcher is changed to possibly send multiple frames per tx, -// this should be changed to a func Frames() []frameData. -func (td *txData) Frame() frameData { - return td.frame +func (td *txData) Frames() []frameData { + return td.frames } // txID is an opaque identifier for a transaction. -// It's internal fields should not be inspected after creation & are subject to change. -// This ID must be trivially comparable & work as a map key. -// -// Note: transactions currently only hold a single frame, so it can be -// identified by the frame. This needs to be changed once the batcher is changed -// to send multiple frames per tx. -type txID = frameID +// Its internal fields should not be inspected after creation & are subject to change. +// Its String() can be used for comparisons and works as a map key. +type txID []frameID func (id txID) String() string { - return fmt.Sprintf("%s:%d", id.chID.String(), id.frameNumber) + return id.string(func(id derive.ChannelID) string { return id.String() }) } // TerminalString implements log.TerminalStringer, formatting a string for console // output during logging. func (id txID) TerminalString() string { - return fmt.Sprintf("%s:%d", id.chID.TerminalString(), id.frameNumber) + return id.string(func(id derive.ChannelID) string { return id.TerminalString() }) +} + +func (id txID) string(chIDStringer func(id derive.ChannelID) string) string { + var ( + sb strings.Builder + curChID derive.ChannelID + ) + for _, f := range id { + if f.chID == curChID { + sb.WriteString(fmt.Sprintf("+%d", f.frameNumber)) + } else { + if curChID != (derive.ChannelID{}) { + sb.WriteString("|") + } + curChID = f.chID + sb.WriteString(fmt.Sprintf("%s:%d", chIDStringer(f.chID), f.frameNumber)) + } + } + return sb.String() } diff --git a/op-batcher/batcher/tx_data_test.go b/op-batcher/batcher/tx_data_test.go new file mode 100644 index 000000000000..317aafc375f6 --- /dev/null +++ b/op-batcher/batcher/tx_data_test.go @@ -0,0 +1,60 @@ +package batcher + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestTxID_String(t *testing.T) { + for _, test := range []struct { + desc string + id txID + expStr string + }{ + { + desc: "empty", + id: []frameID{}, + expStr: "", + }, + { + desc: "nil", + id: nil, + expStr: "", + }, + { + desc: "single", + id: []frameID{{ + chID: [16]byte{0: 0xca, 15: 0xaf}, + frameNumber: 42, + }}, + expStr: "ca0000000000000000000000000000af:42", + }, + { + desc: "multi", + id: []frameID{ + { + chID: [16]byte{0: 0xca, 15: 0xaf}, + frameNumber: 42, + }, + { + chID: [16]byte{0: 0xca, 15: 0xaf}, + frameNumber: 33, + }, + { + chID: [16]byte{0: 0xbe, 15: 0xef}, + frameNumber: 0, + }, + { + chID: [16]byte{0: 0xbe, 15: 0xef}, + frameNumber: 128, + }, + }, + expStr: "ca0000000000000000000000000000af:42+33|be0000000000000000000000000000ef:0+128", + }, + } { + t.Run(test.desc, func(t *testing.T) { + require.Equal(t, test.expStr, test.id.String()) + }) + } +} diff --git a/op-batcher/compressor/cli.go b/op-batcher/compressor/cli.go deleted file mode 100644 index 575662d03f21..000000000000 --- a/op-batcher/compressor/cli.go +++ /dev/null @@ -1,78 +0,0 @@ -package compressor - -import ( - "strings" - - opservice "github.com/ethereum-optimism/optimism/op-service" - "github.com/urfave/cli/v2" -) - -const ( - TargetL1TxSizeBytesFlagName = "target-l1-tx-size-bytes" - TargetNumFramesFlagName = "target-num-frames" - ApproxComprRatioFlagName = "approx-compr-ratio" - KindFlagName = "compressor" -) - -func CLIFlags(envPrefix string) []cli.Flag { - return []cli.Flag{ - &cli.Uint64Flag{ - Name: TargetL1TxSizeBytesFlagName, - Usage: "The target size of a batch tx submitted to L1.", - Value: 100_000, - EnvVars: opservice.PrefixEnvVar(envPrefix, "TARGET_L1_TX_SIZE_BYTES"), - }, - &cli.IntFlag{ - Name: TargetNumFramesFlagName, - Usage: "The target number of frames to create per channel", - Value: 1, - EnvVars: opservice.PrefixEnvVar(envPrefix, "TARGET_NUM_FRAMES"), - }, - &cli.Float64Flag{ - Name: ApproxComprRatioFlagName, - Usage: "The approximate compression ratio (<= 1.0)", - Value: 0.4, - EnvVars: opservice.PrefixEnvVar(envPrefix, "APPROX_COMPR_RATIO"), - }, - &cli.StringFlag{ - Name: KindFlagName, - Usage: "The type of compressor. Valid options: " + strings.Join(KindKeys, ", "), - EnvVars: opservice.PrefixEnvVar(envPrefix, "COMPRESSOR"), - Value: ShadowKind, - }, - } -} - -type CLIConfig struct { - // TargetL1TxSizeBytes to target when creating channel frames. Note that if the - // realized compression ratio is worse than the approximate, more frames may - // actually be created. This also depends on how close the target is to the - // max frame size. - TargetL1TxSizeBytes uint64 - // TargetNumFrames to create in this channel. If the realized compression ratio - // is worse than approxComprRatio, additional leftover frame(s) might get created. - TargetNumFrames int - // ApproxComprRatio to assume. Should be slightly smaller than average from - // experiments to avoid the chances of creating a small additional leftover frame. - ApproxComprRatio float64 - // Type of compressor to use. Must be one of KindKeys. - Kind string -} - -func (c *CLIConfig) Config() Config { - return Config{ - TargetFrameSize: c.TargetL1TxSizeBytes - 1, // subtract 1 byte for version - TargetNumFrames: c.TargetNumFrames, - ApproxComprRatio: c.ApproxComprRatio, - Kind: c.Kind, - } -} - -func ReadCLIConfig(ctx *cli.Context) CLIConfig { - return CLIConfig{ - Kind: ctx.String(KindFlagName), - TargetL1TxSizeBytes: ctx.Uint64(TargetL1TxSizeBytesFlagName), - TargetNumFrames: ctx.Int(TargetNumFramesFlagName), - ApproxComprRatio: ctx.Float64(ApproxComprRatioFlagName), - } -} diff --git a/op-batcher/compressor/compressors.go b/op-batcher/compressor/compressors.go index 5d2e9d0561e7..1a6d64da13e6 100644 --- a/op-batcher/compressor/compressors.go +++ b/op-batcher/compressor/compressors.go @@ -10,6 +10,10 @@ const ( RatioKind = "ratio" ShadowKind = "shadow" NoneKind = "none" + + // CloseOverheadZlib is the number of final bytes a [zlib.Writer] call writes + // to the output buffer. + CloseOverheadZlib = 9 ) var Kinds = map[string]FactoryFunc{ diff --git a/op-batcher/compressor/compressors_test.go b/op-batcher/compressor/compressors_test.go new file mode 100644 index 000000000000..ed6d852d0411 --- /dev/null +++ b/op-batcher/compressor/compressors_test.go @@ -0,0 +1,25 @@ +package compressor + +import ( + "bytes" + "compress/zlib" + "io" + "math/rand" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestCloseOverheadZlib(t *testing.T) { + var buf bytes.Buffer + z := zlib.NewWriter(&buf) + rng := rand.New(rand.NewSource(420)) + _, err := io.CopyN(z, rng, 0xff) + require.NoError(t, err) + + require.NoError(t, z.Flush()) + fsize := buf.Len() + require.NoError(t, z.Close()) + csize := buf.Len() + require.Equal(t, CloseOverheadZlib, csize-fsize) +} diff --git a/op-batcher/compressor/config.go b/op-batcher/compressor/config.go index 1ab42347d007..8befc43812ae 100644 --- a/op-batcher/compressor/config.go +++ b/op-batcher/compressor/config.go @@ -5,16 +5,13 @@ import ( ) type Config struct { - // TargetFrameSize to target when creating channel frames. Note that if the - // realized compression ratio is worse than the approximate, more frames may - // actually be created. This also depends on how close the target is to the - // max frame size. - TargetFrameSize uint64 - // TargetNumFrames to create in this channel. If the realized compression ratio - // is worse than approxComprRatio, additional leftover frame(s) might get created. - TargetNumFrames int - // ApproxComprRatio to assume. Should be slightly smaller than average from - // experiments to avoid the chances of creating a small additional leftover frame. + // TargetOutputSize is the target size that the compressed data should reach. + // The shadow compressor guarantees that the compressed data stays below + // this bound. The ratio compressor might go over. + TargetOutputSize uint64 + // ApproxComprRatio to assume (only ratio compressor). Should be slightly smaller + // than average from experiments to avoid the chances of creating a small + // additional leftover frame. ApproxComprRatio float64 // Kind of compressor to use. Must be one of KindKeys. If unset, NewCompressor // will default to RatioKind. diff --git a/op-batcher/compressor/non_compressor.go b/op-batcher/compressor/non_compressor.go index 6b1a9fc3376f..ee9d4d618cab 100644 --- a/op-batcher/compressor/non_compressor.go +++ b/op-batcher/compressor/non_compressor.go @@ -44,7 +44,7 @@ func (t *NonCompressor) Write(p []byte) (int, error) { if err != nil { return 0, err } - if uint64(t.buf.Len()) > t.config.TargetFrameSize*uint64(t.config.TargetNumFrames) { + if uint64(t.buf.Len()) > t.config.TargetOutputSize { t.fullErr = derive.CompressorFullErr } return n, nil diff --git a/op-batcher/compressor/non_compressor_test.go b/op-batcher/compressor/non_compressor_test.go index c6fc440b1d8a..972582469a99 100644 --- a/op-batcher/compressor/non_compressor_test.go +++ b/op-batcher/compressor/non_compressor_test.go @@ -10,8 +10,7 @@ import ( func TestNonCompressor(t *testing.T) { require := require.New(t) c, err := NewNonCompressor(Config{ - TargetFrameSize: 1000, - TargetNumFrames: 100, + TargetOutputSize: 100000, }) require.NoError(err) diff --git a/op-batcher/compressor/ratio_compressor.go b/op-batcher/compressor/ratio_compressor.go index 6e726ae8a53e..5c4de94edf55 100644 --- a/op-batcher/compressor/ratio_compressor.go +++ b/op-batcher/compressor/ratio_compressor.go @@ -74,7 +74,7 @@ func (t *RatioCompressor) FullErr() error { // InputThreshold calculates the input data threshold in bytes from the given // parameters. func (t *RatioCompressor) InputThreshold() uint64 { - return uint64(float64(t.config.TargetNumFrames) * float64(t.config.TargetFrameSize) / t.config.ApproxComprRatio) + return uint64(float64(t.config.TargetOutputSize) / t.config.ApproxComprRatio) } // inputTargetReached says whether the target amount of input data has been diff --git a/op-batcher/compressor/ratio_compressor_test.go b/op-batcher/compressor/ratio_compressor_test.go index 0691a9d5f12a..27e377a234d6 100644 --- a/op-batcher/compressor/ratio_compressor_test.go +++ b/op-batcher/compressor/ratio_compressor_test.go @@ -1,6 +1,7 @@ package compressor_test import ( + "fmt" "math" "testing" @@ -8,106 +9,46 @@ import ( "github.com/stretchr/testify/require" ) -// TestInputThreshold tests the [ChannelConfig.InputThreshold] -// function using a table-driven testing approach. -func TestInputThreshold(t *testing.T) { - type testInput struct { - TargetFrameSize uint64 - TargetNumFrames int - ApproxComprRatio float64 - } - - // Construct test cases that test the boundary conditions +func TestChannelConfig_InputThreshold(t *testing.T) { tests := []struct { - input testInput - assertion func(uint64) + targetOutputSize uint64 + approxComprRatio float64 + expInputThreshold uint64 + assertion func(uint64) // optional, for more complex assertion }{ { - input: testInput{ - TargetFrameSize: 1, - TargetNumFrames: 1, - ApproxComprRatio: 0.4, - }, - assertion: func(output uint64) { - require.Equal(t, uint64(2), output) - }, + targetOutputSize: 1, + approxComprRatio: 0.4, + expInputThreshold: 2, }, { - input: testInput{ - TargetFrameSize: 1, - TargetNumFrames: 100000, - ApproxComprRatio: 0.4, - }, - assertion: func(output uint64) { - require.Equal(t, uint64(250_000), output) - }, + targetOutputSize: 1, + approxComprRatio: 1, + expInputThreshold: 1, }, { - input: testInput{ - TargetFrameSize: 1, - TargetNumFrames: 1, - ApproxComprRatio: 1, - }, - assertion: func(output uint64) { - require.Equal(t, uint64(1), output) - }, + targetOutputSize: 100_000, + approxComprRatio: 0.4, + expInputThreshold: 250_000, }, { - input: testInput{ - TargetFrameSize: 1, - TargetNumFrames: 1, - ApproxComprRatio: 2, - }, - assertion: func(output uint64) { - require.Equal(t, uint64(0), output) - }, + targetOutputSize: 1, + approxComprRatio: 0.4, + expInputThreshold: 2, }, { - input: testInput{ - TargetFrameSize: 100000, - TargetNumFrames: 1, - ApproxComprRatio: 0.4, - }, - assertion: func(output uint64) { - require.Equal(t, uint64(250_000), output) - }, + targetOutputSize: 100_000, + approxComprRatio: 0.4, + expInputThreshold: 250_000, }, { - input: testInput{ - TargetFrameSize: 1, - TargetNumFrames: 100000, - ApproxComprRatio: 0.4, - }, - assertion: func(output uint64) { - require.Equal(t, uint64(250_000), output) - }, + targetOutputSize: 1, + approxComprRatio: 0.000001, + expInputThreshold: 1_000_000, }, { - input: testInput{ - TargetFrameSize: 100000, - TargetNumFrames: 100000, - ApproxComprRatio: 0.4, - }, - assertion: func(output uint64) { - require.Equal(t, uint64(25_000_000_000), output) - }, - }, - { - input: testInput{ - TargetFrameSize: 1, - TargetNumFrames: 1, - ApproxComprRatio: 0.000001, - }, - assertion: func(output uint64) { - require.Equal(t, uint64(1_000_000), output) - }, - }, - { - input: testInput{ - TargetFrameSize: 0, - TargetNumFrames: 0, - ApproxComprRatio: 0, - }, + targetOutputSize: 0, + approxComprRatio: 0, assertion: func(output uint64) { // Need to allow for NaN depending on the machine architecture require.True(t, output == uint64(0) || output == uint64(math.NaN())) @@ -116,14 +57,19 @@ func TestInputThreshold(t *testing.T) { } // Validate each test case - for _, tt := range tests { - comp, err := compressor.NewRatioCompressor(compressor.Config{ - TargetFrameSize: tt.input.TargetFrameSize, - TargetNumFrames: tt.input.TargetNumFrames, - ApproxComprRatio: tt.input.ApproxComprRatio, + for i, tt := range tests { + t.Run(fmt.Sprintf("test-%d", i), func(t *testing.T) { + comp, err := compressor.NewRatioCompressor(compressor.Config{ + TargetOutputSize: tt.targetOutputSize, + ApproxComprRatio: tt.approxComprRatio, + }) + require.NoError(t, err) + got := comp.(*compressor.RatioCompressor).InputThreshold() + if tt.assertion != nil { + tt.assertion(got) + } else { + require.Equal(t, tt.expInputThreshold, got) + } }) - require.NoError(t, err) - got := comp.(*compressor.RatioCompressor).InputThreshold() - tt.assertion(got) } } diff --git a/op-batcher/compressor/shadow_compressor.go b/op-batcher/compressor/shadow_compressor.go index 9cd6b387015d..9fadb914de25 100644 --- a/op-batcher/compressor/shadow_compressor.go +++ b/op-batcher/compressor/shadow_compressor.go @@ -67,21 +67,19 @@ func (t *ShadowCompressor) Write(p []byte) (int, error) { return 0, err } newBound := t.bound + uint64(len(p)) - cap := t.config.TargetFrameSize * uint64(t.config.TargetNumFrames) - if newBound > cap { + if newBound > t.config.TargetOutputSize { // Do not flush the buffer unless there's some chance we will be over the size limit. // This reduces CPU but more importantly it makes the shadow compression ratio more // closely reflect the ultimate compression ratio. - err = t.shadowCompress.Flush() - if err != nil { + if err = t.shadowCompress.Flush(); err != nil { return 0, err } - newBound = uint64(t.shadowBuf.Len()) + 4 // + 4 is to account for the digest written on close() - if newBound > cap { + newBound = uint64(t.shadowBuf.Len()) + CloseOverheadZlib + if newBound > t.config.TargetOutputSize { t.fullErr = derive.CompressorFullErr if t.Len() > 0 { // only return an error if we've already written data to this compressor before - // (otherwise individual blocks over the target would never be written) + // (otherwise single blocks over the target would never be written) return 0, t.fullErr } } diff --git a/op-batcher/compressor/shadow_compressor_test.go b/op-batcher/compressor/shadow_compressor_test.go index 3d5cdb26b4d9..eb0efea0f13c 100644 --- a/op-batcher/compressor/shadow_compressor_test.go +++ b/op-batcher/compressor/shadow_compressor_test.go @@ -11,55 +11,49 @@ import ( "github.com/stretchr/testify/require" ) -var r *rand.Rand +var r = rand.New(rand.NewSource(99)) -func init() { - r = rand.New(rand.NewSource(99)) -} - -func randomBytes(t *testing.T, length int) []byte { +func randomBytes(length int) []byte { b := make([]byte, length) _, err := r.Read(b) - require.NoError(t, err) + // Rand.Read always returns nil error + if err != nil { + panic(err) + } return b } func TestShadowCompressor(t *testing.T) { tests := []struct { - name string - targetFrameSize uint64 - targetNumFrames int - data [][]byte - errs []error - fullErr error + name string + targetOutputSize uint64 + data [][]byte + errs []error + fullErr error }{{ - name: "no data", - targetFrameSize: 1, - targetNumFrames: 1, - data: [][]byte{}, - errs: []error{}, - fullErr: nil, + name: "no data", + targetOutputSize: 1 + derive.FrameV0OverHeadSize, + data: [][]byte{}, + errs: []error{}, + fullErr: nil, }, { - name: "large first block", - targetFrameSize: 1, - targetNumFrames: 1, - data: [][]byte{bytes.Repeat([]byte{0}, 1024)}, - errs: []error{nil}, - fullErr: derive.CompressorFullErr, + name: "large first block", + targetOutputSize: 1 + derive.FrameV0OverHeadSize, + data: [][]byte{bytes.Repeat([]byte{0}, 1024)}, + errs: []error{nil}, + fullErr: derive.CompressorFullErr, }, { - name: "large second block", - targetFrameSize: 1, - targetNumFrames: 1, - data: [][]byte{bytes.Repeat([]byte{0}, 512), bytes.Repeat([]byte{0}, 1024)}, - errs: []error{nil, derive.CompressorFullErr}, - fullErr: derive.CompressorFullErr, + name: "large second block", + targetOutputSize: 1 + derive.FrameV0OverHeadSize, + data: [][]byte{bytes.Repeat([]byte{0}, 512), bytes.Repeat([]byte{0}, 1024)}, + errs: []error{nil, derive.CompressorFullErr}, + fullErr: derive.CompressorFullErr, }, { - name: "random data", - targetFrameSize: 1 << 17, - targetNumFrames: 1, - data: [][]byte{randomBytes(t, (1<<17)-1000), randomBytes(t, 512), randomBytes(t, 512)}, - errs: []error{nil, nil, derive.CompressorFullErr}, - fullErr: derive.CompressorFullErr, + name: "random data", + targetOutputSize: 1 << 17, + data: [][]byte{randomBytes((1 << 17) - 1000), randomBytes(512), randomBytes(512)}, + errs: []error{nil, nil, derive.CompressorFullErr}, + fullErr: derive.CompressorFullErr, }} for _, test := range tests { test := test @@ -68,8 +62,7 @@ func TestShadowCompressor(t *testing.T) { require.Equal(t, len(test.errs), len(test.data), "invalid test case: len(data) != len(errs)") sc, err := NewShadowCompressor(Config{ - TargetFrameSize: test.targetFrameSize, - TargetNumFrames: test.targetNumFrames, + TargetOutputSize: test.targetOutputSize, }) require.NoError(t, err) @@ -118,22 +111,21 @@ func TestShadowCompressor(t *testing.T) { // TestBoundInaccruateForLargeRandomData documents where our bounding heuristic starts to fail // (writing at least 128k of random data) func TestBoundInaccurateForLargeRandomData(t *testing.T) { - var sizeLimit int = 1 << 17 + const sizeLimit = 1 << 17 sc, err := NewShadowCompressor(Config{ - TargetFrameSize: uint64(sizeLimit + 100), - TargetNumFrames: 1, + TargetOutputSize: sizeLimit + 100, }) require.NoError(t, err) - _, err = sc.Write(randomBytes(t, sizeLimit+1)) + _, err = sc.Write(randomBytes(sizeLimit + 1)) require.NoError(t, err) err = sc.Close() require.NoError(t, err) require.Greater(t, uint64(sc.Len()), sc.(*ShadowCompressor).bound) sc.Reset() - _, err = sc.Write(randomBytes(t, sizeLimit)) + _, err = sc.Write(randomBytes(sizeLimit)) require.NoError(t, err) err = sc.Close() require.NoError(t, err) diff --git a/op-batcher/flags/flags.go b/op-batcher/flags/flags.go index 549fa1026a31..7ad7e25a50e2 100644 --- a/op-batcher/flags/flags.go +++ b/op-batcher/flags/flags.go @@ -2,12 +2,16 @@ package flags import ( "fmt" + "strings" "time" "github.com/urfave/cli/v2" + "golang.org/x/exp/slices" "github.com/ethereum-optimism/optimism/op-batcher/compressor" + plasma "github.com/ethereum-optimism/optimism/op-plasma" opservice "github.com/ethereum-optimism/optimism/op-service" + "github.com/ethereum-optimism/optimism/op-service/eigenda" openum "github.com/ethereum-optimism/optimism/op-service/enum" oplog "github.com/ethereum-optimism/optimism/op-service/log" opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" @@ -68,20 +72,45 @@ var ( } MaxL1TxSizeBytesFlag = &cli.Uint64Flag{ Name: "max-l1-tx-size-bytes", - Usage: "The maximum size of a batch tx submitted to L1.", - Value: 120_000, + Usage: "The maximum size of a batch tx submitted to L1. Ignored for blobs, where max blob size will be used.", + Value: 120_000, // will be overwritten to max for blob da-type EnvVars: prefixEnvVars("MAX_L1_TX_SIZE_BYTES"), } + TargetNumFramesFlag = &cli.IntFlag{ + Name: "target-num-frames", + Usage: "The target number of frames to create per channel. Controls number of blobs per blob tx, if using Blob DA.", + Value: 1, + EnvVars: prefixEnvVars("TARGET_NUM_FRAMES"), + } + ApproxComprRatioFlag = &cli.Float64Flag{ + Name: "approx-compr-ratio", + Usage: "The approximate compression ratio (<= 1.0). Only relevant for ratio compressor.", + Value: 0.6, + EnvVars: prefixEnvVars("APPROX_COMPR_RATIO"), + } + CompressorFlag = &cli.StringFlag{ + Name: "compressor", + Usage: "The type of compressor. Valid options: " + strings.Join(compressor.KindKeys, ", "), + EnvVars: prefixEnvVars("COMPRESSOR"), + Value: compressor.ShadowKind, + Action: func(_ *cli.Context, s string) error { + if !slices.Contains(compressor.KindKeys, s) { + return fmt.Errorf("unsupported compressor: %s", s) + } + return nil + }, + } StoppedFlag = &cli.BoolFlag{ Name: "stopped", Usage: "Initialize the batcher in a stopped state. The batcher can be started using the admin_startBatcher RPC", EnvVars: prefixEnvVars("STOPPED"), } BatchTypeFlag = &cli.UintFlag{ - Name: "batch-type", - Usage: "The batch type. 0 for SingularBatch and 1 for SpanBatch.", - Value: 0, - EnvVars: prefixEnvVars("BATCH_TYPE"), + Name: "batch-type", + Usage: "The batch type. 0 for SingularBatch and 1 for SpanBatch.", + Value: 0, + EnvVars: prefixEnvVars("BATCH_TYPE"), + DefaultText: "singular", } DataAvailabilityTypeFlag = &cli.GenericFlag{ Name: "data-availability-type", @@ -99,6 +128,12 @@ var ( Value: 2 * time.Minute, EnvVars: prefixEnvVars("ACTIVE_SEQUENCER_CHECK_DURATION"), } + PrefixDerivationEnabledFlag = &cli.BoolFlag{ + Name: "da-prefix-derivation-enabled", + Usage: "Enable prefix derivation", + Value: false, + EnvVars: prefixEnvVars("DA_PREFIX_DERIVATION_ENABLED"), + } // Legacy Flags SequencerHDPathFlag = txmgr.SequencerHDPathFlag ) @@ -115,11 +150,15 @@ var optionalFlags = []cli.Flag{ MaxPendingTransactionsFlag, MaxChannelDurationFlag, MaxL1TxSizeBytesFlag, + TargetNumFramesFlag, + ApproxComprRatioFlag, + CompressorFlag, StoppedFlag, SequencerHDPathFlag, BatchTypeFlag, DataAvailabilityTypeFlag, ActiveSequencerCheckDurationFlag, + PrefixDerivationEnabledFlag, } func init() { @@ -128,7 +167,8 @@ func init() { optionalFlags = append(optionalFlags, opmetrics.CLIFlags(EnvVarPrefix)...) optionalFlags = append(optionalFlags, oppprof.CLIFlags(EnvVarPrefix)...) optionalFlags = append(optionalFlags, txmgr.CLIFlags(EnvVarPrefix)...) - optionalFlags = append(optionalFlags, compressor.CLIFlags(EnvVarPrefix)...) + optionalFlags = append(optionalFlags, plasma.CLIFlags(EnvVarPrefix, "")...) + optionalFlags = append(optionalFlags, eigenda.CLIFlags(EnvVarPrefix)...) Flags = append(requiredFlags, optionalFlags...) } diff --git a/op-batcher/metrics/metrics.go b/op-batcher/metrics/metrics.go index 6a250fb0c327..25cef0ec405f 100644 --- a/op-batcher/metrics/metrics.go +++ b/op-batcher/metrics/metrics.go @@ -46,6 +46,8 @@ type Metricer interface { RecordBatchTxSuccess() RecordBatchTxFailed() + RecordBlobUsedBytes(num int) + Document() []opmetrics.DocumentedMetric } @@ -79,6 +81,8 @@ type Metrics struct { channelOutputBytesTotal prometheus.Counter batcherTxEvs opmetrics.EventVec + + blobUsedBytes prometheus.Histogram } var _ Metricer = (*Metrics)(nil) @@ -181,6 +185,12 @@ func NewMetrics(procName string) *Metrics { Name: "output_bytes_total", Help: "Total number of compressed output bytes from a channel.", }), + blobUsedBytes: factory.NewHistogram(prometheus.HistogramOpts{ + Namespace: ns, + Name: "blob_used_bytes", + Help: "Blob size in bytes being submitted.", + Buckets: prometheus.LinearBuckets(0.0, eth.MaxBlobDataSize/13, 13), + }), batcherTxEvs: opmetrics.NewEventVec(factory, ns, "", "batcher_tx", "BatcherTx", []string{"stage"}), } @@ -304,6 +314,10 @@ func (m *Metrics) RecordBatchTxFailed() { m.batcherTxEvs.Record(TxStageFailed) } +func (m *Metrics) RecordBlobUsedBytes(num int) { + m.blobUsedBytes.Observe(float64(num)) +} + // estimateBatchSize estimates the size of the batch func estimateBatchSize(block *types.Block) uint64 { size := uint64(70) // estimated overhead of batch metadata diff --git a/op-batcher/metrics/noop.go b/op-batcher/metrics/noop.go index dc68bebda786..36594efe47c7 100644 --- a/op-batcher/metrics/noop.go +++ b/op-batcher/metrics/noop.go @@ -42,6 +42,7 @@ func (*noopMetrics) RecordChannelTimedOut(derive.ChannelID) {} func (*noopMetrics) RecordBatchTxSubmitted() {} func (*noopMetrics) RecordBatchTxSuccess() {} func (*noopMetrics) RecordBatchTxFailed() {} +func (*noopMetrics) RecordBlobUsedBytes(int) {} func (*noopMetrics) StartBalanceMetrics(log.Logger, *ethclient.Client, common.Address) io.Closer { return nil } diff --git a/op-bindings/Makefile b/op-bindings/Makefile index aec823f4a7ac..7066489f6a20 100644 --- a/op-bindings/Makefile +++ b/op-bindings/Makefile @@ -1,9 +1,11 @@ SHELL := /usr/bin/env bash pkg := bindings +pkg-preview := bindingspreview monorepo-base := $(shell dirname $(realpath .)) contracts-dir := $(monorepo-base)/packages/contracts-bedrock contracts-list := ./artifacts.json +contracts-list-preview := ./artifacts-preview.json log-level := info ETHERSCAN_APIKEY_ETH ?= ETHERSCAN_APIKEY_OP ?= @@ -21,9 +23,9 @@ compile: forge clean && \ pnpm build -bindings: bindgen-local +bindings: bindgen-local bindgen-preview -bindings-build: bindgen-generate-local +bindings-build: bindgen-generate-local bindgen-generate-preview bindgen: compile bindgen-generate-all @@ -53,6 +55,18 @@ bindgen-generate-local: local \ --forge-artifacts $(contracts-dir)/forge-artifacts +bindgen-preview: compile bindgen-generate-preview + +bindgen-generate-preview: + go run ./cmd \ + generate \ + --metadata-out ./$(pkg-preview) \ + --bindings-package $(pkg-preview) \ + --contracts-list $(contracts-list-preview) \ + --log.level $(log-level) \ + local \ + --forge-artifacts $(contracts-dir)/forge-artifacts + bindgen-remote: go run ./cmd/ \ generate \ diff --git a/op-bindings/artifacts-preview.json b/op-bindings/artifacts-preview.json new file mode 100644 index 000000000000..9d1630f96d2f --- /dev/null +++ b/op-bindings/artifacts-preview.json @@ -0,0 +1,6 @@ +{ + "local": [ + "OptimismPortal2" + ], + "remote": [] +} diff --git a/op-bindings/artifacts.json b/op-bindings/artifacts.json index 8885d9a38ac4..ec22fbc34b75 100644 --- a/op-bindings/artifacts.json +++ b/op-bindings/artifacts.json @@ -19,7 +19,6 @@ "L1FeeVault", "OptimismMintableERC20Factory", "OptimismMintableERC20", - "LegacyERC20ETH", "Proxy", "ProxyAdmin", "LegacyMessagePasser", @@ -27,6 +26,7 @@ "WETH9", "DeployerWhitelist", "L1BlockNumber", + "DelayedWETH", "DisputeGameFactory", "FaultDisputeGame", "AlphabetVM", @@ -42,7 +42,8 @@ "DelayedVetoable", "ISemver", "StorageSetter", - "SuperchainConfig" + "SuperchainConfig", + "DataAvailabilityChallenge" ], "remote": [ { diff --git a/op-bindings/ast/canonicalize.go b/op-bindings/ast/canonicalize.go index f0b69ae578e0..eae1a431b428 100644 --- a/op-bindings/ast/canonicalize.go +++ b/op-bindings/ast/canonicalize.go @@ -63,7 +63,7 @@ func CanonicalizeASTIDs(in *solc.StorageLayout, monorepoBase string) *solc.Stora continue } - // The storage types include the size when its a fixed size. + // The storage types include the size when it's a fixed size. // This is subject to breaking in the future if a type with // an ast id is added in a fixed storage type. We don't want // to skip a type with `_storage` in it if it has a subtype diff --git a/op-bindings/bindgen/README.md b/op-bindings/bindgen/README.md index 0939f038fb4e..914c54df94c2 100644 --- a/op-bindings/bindgen/README.md +++ b/op-bindings/bindgen/README.md @@ -33,12 +33,12 @@ If you're running the CLI inside the Optimism monorepo, please make sure you've # Running BindGen -BindGen can be ran one of two ways: +BindGen can be run in one of two ways: 1. Using the provided [Makefile](../Makefile) which defaults some of the required flags 2. Executing the CLI directly with `go run`, or building a Go binary and executing it -Before executing BindGen, please review the [artifacts.json](../artifacts.json) file which specifies what contracts BindGen should generate Go bindings and metadata files for. More information on how to configure `artifacts.json` can be found [here](). +Before executing BindGen, please review the [artifacts.json](../artifacts.json) file which specifies what contracts BindGen should generate Go bindings and metadata files for. More information on how to configure `artifacts.json` can be found [here](#anatomy-of-artifactsjson). ## Using the Makefile Commands @@ -118,7 +118,7 @@ Command | Description -------- | -------------------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------------------ `all` | Generates bindings for both local and remotely sourced contracts. | [Global Flags](#global-flags) | `bindgen generate [global-flags] all [local-flags] [remote-flags]` `local` | Generates bindings for contracts with locally available Forge artifacts. | [Local Flags](#local-flags) | `bindgen generate [global-flags] local [local-flags]` -`remote` | Generates bindings for contracts who's metadata is sourced from Etherscan. | [Remote Flags](#remote-flags) | `bindgen generate [global-flags] remote [remote-flags]` +`remote` | Generates bindings for contracts whose metadata is sourced from Etherscan. | [Remote Flags](#remote-flags) | `bindgen generate [global-flags] remote [remote-flags]` The following displays how the CLI can be invoked from the monorepo root: @@ -163,7 +163,7 @@ Flag | Type | Description **Note** While we encourage hacking on the OP stack, we are not actively looking to integrate more contracts to the official OP stack genesis. -BindGen uses the provided `contracts-list` to generate Go bindings and metadata files which are used when building the L2 genesis. The first step in adding a new preinstall to L2 genesis is adding the contract to your `contracts-list` (by default this list if [artifacts.json](../artifacts.json)). +BindGen uses the provided `contracts-list` to generate Go bindings and metadata files which are used when building the L2 genesis. The first step in adding a new preinstall to L2 genesis is adding the contract to your `contracts-list` (by default this list is [artifacts.json](../artifacts.json)). ## Anatomy of `artifacts.json` @@ -207,7 +207,7 @@ Below is a condensed version of the default [artifacts.json](../artifacts.json) ### `"local"` Contracts -The first property of this JSON object, `"local"`, specifies the name of the contracts that have locally available Forge artifacts which BindGen will use to generate Go bindings and metadata files. This property specifies an array of strings where each string corresponds to the name of the contract which is used in the name of it's corresponding Forge artifact. +The first property of this JSON object, `"local"`, specifies the name of the contracts that have locally available Forge artifacts which BindGen will use to generate Go bindings and metadata files. This property specifies an array of strings where each string corresponds to the name of the contract which is used in the name of its corresponding Forge artifact. For example, the first contract listed in the default contract list is `SystemConfig`. After running `pnpm build` in the [contract-bedrock](../../packages/contracts-bedrock/), you'll have a [forge-artifacts](../../packages/contracts-bedrock/forge-artifacts/) directory where you can find [SystemConfig.sol](../../packages/contracts-bedrock/forge-artifacts/SystemConfig.sol/). Inside is the Forge artifacts BindGen will use to generate the Go bindings and metadata file. @@ -253,7 +253,7 @@ Name | Description `deploymentSalt` | If the contract was deployed using CREATE2 or a CREATE2 proxy deployer, here is where you specify the salt that was used for creation `deployer` | The address used to deploy the contract, used to mimic CREATE2 deployments `abi` | The ABI of the contract, required if the contract is **not** verified on Etherscan -`initBytecode` | The initialization bytecode for the contract, required if the contract is apart of the initialization of another contract (i.e. the `input` data of the deployment transaction contains initialization bytecode other than what belongs to the specific contract you're adding) +`initBytecode` | The initialization bytecode for the contract, required if the contract is a part of the initialization of another contract (i.e. the `input` data of the deployment transaction contains initialization bytecode other than what belongs to the specific contract you're adding) ### Adding A New `"remote"` Contract @@ -291,7 +291,7 @@ switch contract.Name { ... ``` -If you contract is verified on Etherscan, doesn't contain any Solidity `immutable`s, and doesn't require any special handling, than you most likely can add your contract's `name` to the first switch case. The will use the `standardHandler` which: +If your contract is verified on Etherscan, doesn't contain any Solidity `immutable`s, and doesn't require any special handling, then you most likely can add your contract's `name` to the first switch case. Then will use the `standardHandler` which: 1. Fetches the required contract metadata from Etherscan (i.e. initialization and deployed bytecode, ABI, deployment transaction hash, etc.) 2. Compares the retrieved deployed bytecode from Etherscan against the response of `eth_codeAt` from an RPC node for each network specified in `RemoteContract.deployments` (this is a sanity check to verify Etherscan is returning correct data) @@ -304,9 +304,9 @@ If you contract is verified on Etherscan, doesn't contain any Solidity `immutabl All other default `"remote"` contract have some variation of the above execution flow depending on the nuances of each contract. For example: -- `Create2Deployer`'s initialization and deployed bytecode is expected to differ from it's Optimism Mainnet deployment -- `MultiSend_v130` has an `immutable` Solidity variable the resolves to `address(this)`, so we can't use the deployment bytecode from Ethereum Mainnet, we must get it's deployment bytecode from Optimism Mainnet -- `SenderCreator` is deployed by `EntryPoint`, so it's initialization bytecode is provided in [artifacts.json](../artifacts.json) and not being fetched from Etherscan like other contracts +- `Create2Deployer`'s initialization and deployed bytecode is expected to differ from its Optimism Mainnet deployment +- `MultiSend_v130` has an `immutable` Solidity variable the resolves to `address(this)`, so we can't use the deployment bytecode from Ethereum Mainnet, we must get its deployment bytecode from Optimism Mainnet +- `SenderCreator` is deployed by `EntryPoint`, so its initialization bytecode is provided in [artifacts.json](../artifacts.json) and not being fetched from Etherscan like other contracts #### Contracts that Don't Make Good Preinstalls @@ -317,7 +317,7 @@ Not every contract can be added as a preinstall, and some contracts have nuances - Related to above, contracts that may become deprecated/unsupported relatively soon - As mentioned above, you're limited to options A, B, or C - Upgradeable Contracts - - While it's certainly feasible to preinstall an upgradeable contract, great care should be taken to minimize security risks to users if the contract is upgraded to a malicious or buggy implementation. Understanding who has the ability to upgrade the contract is key to avoiding this. Additionally, user's might be expecting a preinstall to do something and may be caught off guard if the implementation was upgraded without their knowledge + - While it's certainly feasible to preinstall an upgradeable contract, great care should be taken to minimize security risks to users if the contract is upgraded to a malicious or buggy implementation. Understanding who has the ability to upgrade the contract is key to avoiding this. Additionally, users might be expecting a preinstall to do something and may be caught off guard if the implementation was upgraded without their knowledge - Contracts with Privileged Roles and Configuration Parameters - Similar to the upgradeable contracts, simply having an owner or other privileged role with the ability to make configuration changes can present a security risk and result in unexpected different behaviors across chains. - Contracts that have dependencies diff --git a/op-bindings/bindings/alphabetvm.go b/op-bindings/bindings/alphabetvm.go index baa34bc0e74a..7f0607b6cee1 100644 --- a/op-bindings/bindings/alphabetvm.go +++ b/op-bindings/bindings/alphabetvm.go @@ -30,8 +30,8 @@ var ( // AlphabetVMMetaData contains all meta data concerning the AlphabetVM contract. var AlphabetVMMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_absolutePrestate\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"oracle\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIPreimageOracle\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"step\",\"inputs\":[{\"name\":\"_stateData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_localContext\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"postState_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"}]", - Bin: "0x60a060405234801561001057600080fd5b506040516138c53803806138c583398101604081905261002f916100a0565b6080819052604051600090819061004590610093565b9182526020820152604001604051809103906000f08015801561006c573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216919091179055506100b9565b6132ee806105d783390190565b6000602082840312156100b257600080fd5b5051919050565b6080516105046100d3600039600060af01526105046000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80637dc0d1d01461003b578063e14ced3214610085575b600080fd5b60005461005b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610098610093366004610395565b6100a6565b60405190815260200161007c565b600080600060087f0000000000000000000000000000000000000000000000000000000000000000901b600889896040516100e2929190610409565b6040518091039020901b036101d9576000805473ffffffffffffffffffffffffffffffffffffffff1663e03110e161011b60048861029f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526004810191909152600060248201526044016040805180830381865afa158015610175573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101999190610419565b50640ffffffff0607c82901c169350905063ffffffff608082901c1660006101c38a8c018c61043d565b90506101cf8582610485565b9350505050610206565b6101e58789018961049d565b9092509050816101f4816104bf565b9250508080610202906104bf565b9150505b6040805160208101849052908101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001798975050505050505050565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617610345818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b60008083601f84011261035e57600080fd5b50813567ffffffffffffffff81111561037657600080fd5b60208301915083602082850101111561038e57600080fd5b9250929050565b6000806000806000606086880312156103ad57600080fd5b853567ffffffffffffffff808211156103c557600080fd5b6103d189838a0161034c565b909750955060208801359150808211156103ea57600080fd5b506103f78882890161034c565b96999598509660400135949350505050565b8183823760009101908152919050565b6000806040838503121561042c57600080fd5b505080516020909101519092909150565b60006020828403121561044f57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561049857610498610456565b500190565b600080604083850312156104b057600080fd5b50508035926020909101359150565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036104f0576104f0610456565b506001019056fea164736f6c634300080f000a60c06040523480156200001157600080fd5b50604051620032ee380380620032ee8339810160408190526200003491620000f3565b60a0829052608081905260005b6200004f600160106200012e565b811015620000ea57600381601081106200006d576200006d62000148565b01546003826010811062000085576200008562000148565b0154604080516020810193909352820152606001604051602081830303815290604052805190602001206003826001620000c091906200015e565b60108110620000d357620000d362000148565b015580620000e18162000179565b91505062000041565b50505062000195565b600080604083850312156200010757600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b60008282101562000143576200014362000118565b500390565b634e487b7160e01b600052603260045260246000fd5b6000821982111562000174576200017462000118565b500190565b6000600182016200018e576200018e62000118565b5060010190565b60805160a051613125620001c9600039600081816103db015261175501526000818161044f015261100201526131256000f3fe608060405234801561001057600080fd5b50600436106101a35760003560e01c80638dc4be11116100ee578063dd24f9bf11610097578063ec5efcbc11610071578063ec5efcbc1461043a578063f3f480d91461044d578063faf37bc714610473578063fef2b4ed1461048657600080fd5b8063dd24f9bf146103d9578063e03110e1146103ff578063e15926111461042757600080fd5b8063b4801e61116100c8578063b4801e61146103ab578063d18534b5146103be578063da35c664146103d157600080fd5b80638dc4be111461032b5780639d53a6481461033e578063b2e67ba81461038057600080fd5b806361238bde116101505780637ac547671161012a5780637ac54767146102ae5780638542cf50146102c1578063882856ef146102ff57600080fd5b806361238bde146102455780636551927b146102705780637917de1d1461029b57600080fd5b80633909af5c116101815780633909af5c146102155780634d52b4c91461022a57806352f0f3ad1461023257600080fd5b8063013cf08b146101a85780630359a563146101ec5780632055b36b1461020d575b600080fd5b6101bb6101b6366004612768565b6104a6565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b6101ff6101fa3660046127aa565b6104eb565b6040519081526020016101e3565b6101ff601081565b6102286102233660046129a5565b610623565b005b6101ff610871565b6101ff610240366004612a91565b61088c565b6101ff610253366004612acc565b600160209081526000928352604080842090915290825290205481565b6101ff61027e3660046127aa565b601560209081526000928352604080842090915290825290205481565b6102286102a9366004612b30565b610961565b6101ff6102bc366004612768565b610def565b6102ef6102cf366004612acc565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016101e3565b61031261030d366004612bcc565b610e06565b60405167ffffffffffffffff90911681526020016101e3565b610228610339366004612bff565b610e60565b6101ff61034c3660046127aa565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601760209081526040808320938352929052205490565b6101ff61038e3660046127aa565b601660209081526000928352604080842090915290825290205481565b6101ff6103b9366004612bcc565b610f5b565b6102286103cc3660046129a5565b610f8d565b6013546101ff565b7f00000000000000000000000000000000000000000000000000000000000000006101ff565b61041261040d366004612acc565b611358565b604080519283526020830191909152016101e3565b610228610435366004612bff565b611449565b610228610448366004612c4b565b611551565b7f00000000000000000000000000000000000000000000000000000000000000006101ff565b610228610481366004612ce4565b6116cb565b6101ff610494366004612768565b60006020819052908152604090205481565b601381815481106104b657600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061052e9060601c63ffffffff1690565b63ffffffff16905060005b601081101561061b57816001166001036105c15773ffffffffffffffffffffffffffffffffffffffff851660009081526014602090815260408083208784529091529020816010811061058e5761058e612d20565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610602565b82600382601081106105d5576105d5612d20565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c908061061381612d7e565b915050610539565b505092915050565b600061062f8a8a6104eb565b905061065286868360208b013561064d6106488d612db6565b6118de565b61191e565b80156106705750610670838383602088013561064d6106488a612db6565b6106a6576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8660400135886040516020016106bc9190612e85565b6040516020818303038152906040528051906020012014610709576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161071f9190612ec3565b14610756576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61079e886107648680612edb565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197f92505050565b6107a788611ada565b8360400135886040516020016107bd9190612e85565b604051602081830303815290604052805190602001200361080a576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505073ffffffffffffffffffffffffffffffffffffffff9590951660009081526015602090815260408083209683529590529390932080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117905550505050565b600161087f60106002613062565b610889919061306e565b81565b60006108988686612376565b90506108a5836008612ec3565b8211806108b25750602083115b156108e9576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b6060811561097a576109738686612423565b90506109b4565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b8154815260200190600101908083116109e157505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610a628260601c63ffffffff1690565b63ffffffff169050333214610aa3576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ab38260801c63ffffffff1690565b63ffffffff16600003610af2576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610afc8260c01c90565b67ffffffffffffffff1615610b3d576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610b76576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b8389898d88866124ac565b83516020850160888204881415608883061715610ba8576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610c58578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610c4d576001821615610c2d5782818b0152610c4d565b8981015160009081526020938452604090209260019290921c9101610c10565b505050608801610bb5565b50505050600160106002610c6c9190613062565b610c76919061306e565b811115610caf576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d24610cc28360401c63ffffffff1690565b610cd29063ffffffff168a612ec3565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b91508415610d4f5777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b1791505b3360009081526014602090815260408083208e84529091529020610d75908460106126de565b50503360008181526017602090815260408083208e8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055928252601581528282209c82529b909b52909920989098555050505050505050565b60038160108110610dff57600080fd5b0154905081565b60176020528260005260406000206020528160005260406000208181548110610e2e57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b604435600080600883018610610e7e5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa905080610eab57600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b60146020528260005260406000206020528160005260406000208160108110610f8357600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff811615611000576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061102b8260c01c90565b61103f9067ffffffffffffffff164261306e565b11611076576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006110828b8b6104eb565b905061109b87878360208c013561064d6106488e612db6565b80156110b957506110b9848483602089013561064d6106488b612db6565b6110ef576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016111059190612e85565b6040516020818303038152906040528051906020012014611152576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460200135886020013560016111689190612ec3565b14158061119a575060016111828360601c63ffffffff1690565b61118c9190613085565b63ffffffff16856020013514155b156111d1576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006111e38360801c63ffffffff1690565b63ffffffff169050806111fc8460401c63ffffffff1690565b63ffffffff1614611239576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112478a6107648880612edb565b6112508a611ada565b600061125b8b6125ff565b9050600061126f8560a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601660008f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008e8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555082600080848152602001908152602001600020819055505050505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166113e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546113fd816008612ec3565b611408856020612ec3565b106114265783611419826008612ec3565b611423919061306e565b91505b506000938452600160209081526040808620948652939052919092205492909150565b6044356000806008830186106114675763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b600061155d86866104eb565b9050611576838383602088013561064d6106488a612db6565b6115ac576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840135156115e8576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115f061271c565b6115fe816107648780612edb565b61160781611ada565b84604001358160405160200161161d9190612e85565b604051602081830303815290604052805190602001200361166a576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505073ffffffffffffffffffffffffffffffffffffffff9290921660009081526015602090815260408083209383529290522080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117905550565b333214611704576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61170f8160086130aa565b63ffffffff168263ffffffff1610611753576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff1610156117b3576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152601560209081526040808320878452825280832080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660a09790971b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff169690961760809590951b9490941790945582518084019093529082529181019283526013805460018101825592525160029091027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0908101805473ffffffffffffffffffffffffffffffffffffffff9093167fffffffffffffffffffffffff00000000000000000000000000000000000000009093169290921790915590517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a09190910155565b6000816000015182602001518360400151604051602001611901939291906130d2565b604051602081830303815290604052805190602001209050919050565b60008160005b6010811015611972578060051b880135600186831c16600181146119575760008481526020839052604090209350611968565b600082815260208590526040902093505b5050600101611924565b5090931495945050505050565b608881511461198d57600080fd5b6020810160208301611a0e565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050611a08816119f3868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b611a1a6000838361199a565b611a266001838361199a565b611a326002838361199a565b611a3e6003838361199a565b611a4a6004838361199a565b611a566005838361199a565b611a626006838361199a565b611a6e6007838361199a565b611a7a6008838361199a565b611a866009838361199a565b611a92600a838361199a565b611a9e600b838361199a565b611aaa600c838361199a565b611ab6600d838361199a565b611ac2600e838361199a565b611ace600f838361199a565b611a086010838361199a565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e00160405160208183030381529060405290506020820160208201612256565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c611c8d8660011b67ffffffffffffffff1690565b18188584603f1c611ca88660011b67ffffffffffffffff1690565b18188584603f1c611cc38660011b67ffffffffffffffff1690565b181895508483603f1c611ce08560011b67ffffffffffffffff1690565b181894508387603f1c611cfd8960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525050505050565b61207d81611bd0565b805160208201805160408401805160608601805160808801805167ffffffffffffffff871986168a188116808c528619851689188216909952831982169095188516909552841988169091188316909152941990921618811690925260a08301805160c0808601805160e0880180516101008a0180516101208c018051861985168a188d16909a528319821686188c16909652801989169092188a169092528619861618881690529219909216909218841690526101408401805161016086018051610180880180516101a08a0180516101c08c0180518619851689188d169099528319821686188c16909652801988169092188a169092528519851618881690529119909116909118841690526101e08401805161020086018051610220880180516102408a0180516102608c0180518619851689188d169099528319821686188c16909652801988169092188a16909252851985161888169052911990911690911884169052610280840180516102a0860180516102c0880180516102e08a0180516103008c0180518619851689188d169099528319821686188c16909652801988169092188a16909252851985161888169052911990911690911884169052600386901b850151901c9081189091168252611a08565b61226260008284612074565b61226e60018284612074565b61227a60028284612074565b61228660038284612074565b61229260048284612074565b61229e60058284612074565b6122aa60068284612074565b6122b660078284612074565b6122c260088284612074565b6122ce60098284612074565b6122da600a8284612074565b6122e6600b8284612074565b6122f2600c8284612074565b6122fe600d8284612074565b61230a600e8284612074565b612316600f8284612074565b61232260108284612074565b61232e60118284612074565b61233a60128284612074565b61234660138284612074565b61235260148284612074565b61235e60158284612074565b61236a60168284612074565b611a0860178284612074565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83161761241c818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612481576088829003850160808582017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01536001845160001a1784538652612493565b60018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b60006124be8260a01c63ffffffff1690565b67ffffffffffffffff16905060006124dc8360801c63ffffffff1690565b63ffffffff16905060006124f68460401c63ffffffff1690565b63ffffffff16905060088310801561250c575080155b156125405760c082901b6000908152883560085283513382526016602090815260408084208a8552909152909120556125f5565b6008831015801561255e57508061255860088561306e565b93508310155b8015612572575061256f8782612ec3565b83105b156125f5576000612583828561306e565b905087612591826020612ec3565b1015801561259d575085155b156125d4576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526016602090815260408083208a845290915290209089013590555b5050505050505050565b6000612682565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff006126308360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff000061265d8360101b67ffffffffffffffff1690565b1617905060008160201c61267b8360201b67ffffffffffffffff1690565b1792915050565b6080820151602083019061269a90612606565b612606565b60408201516126a890612606565b60401b176126c061269560018460059190911b015190565b825160809190911b906126d290612606565b60c01b17179392505050565b826010810192821561270c579160200282015b8281111561270c5782518255916020019190600101906126f1565b50612718929150612734565b5090565b604051806020016040528061272f612749565b905290565b5b808211156127185760008155600101612735565b6040518061032001604052806019906020820280368337509192915050565b60006020828403121561277a57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146127a557600080fd5b919050565b600080604083850312156127bd57600080fd5b6127c683612781565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612827576128276127d4565b60405290565b6040516060810167ffffffffffffffff81118282101715612827576128276127d4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612897576128976127d4565b604052919050565b60006103208083850312156128b357600080fd5b604051602080820167ffffffffffffffff83821081831117156128d8576128d86127d4565b8160405283955087601f8801126128ee57600080fd5b6128f6612803565b948701949150818886111561290a57600080fd5b875b8681101561293257803583811681146129255760008081fd5b845292840192840161290c565b50909352509295945050505050565b60006060828403121561295357600080fd5b50919050565b60008083601f84011261296b57600080fd5b50813567ffffffffffffffff81111561298357600080fd5b6020830191508360208260051b850101111561299e57600080fd5b9250929050565b60008060008060008060008060006103e08a8c0312156129c457600080fd5b6129cd8a612781565b985060208a013597506129e38b60408c0161289f565b96506103608a013567ffffffffffffffff80821115612a0157600080fd5b612a0d8d838e01612941565b97506103808c0135915080821115612a2457600080fd5b612a308d838e01612959565b90975095506103a08c0135915080821115612a4a57600080fd5b612a568d838e01612941565b94506103c08c0135915080821115612a6d57600080fd5b50612a7a8c828d01612959565b915080935050809150509295985092959850929598565b600080600080600060a08688031215612aa957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060408385031215612adf57600080fd5b50508035926020909101359150565b60008083601f840112612b0057600080fd5b50813567ffffffffffffffff811115612b1857600080fd5b60208301915083602082850101111561299e57600080fd5b600080600080600080600060a0888a031215612b4b57600080fd5b8735965060208801359550604088013567ffffffffffffffff80821115612b7157600080fd5b612b7d8b838c01612aee565b909750955060608a0135915080821115612b9657600080fd5b50612ba38a828b01612959565b90945092505060808801358015158114612bbc57600080fd5b8091505092959891949750929550565b600080600060608486031215612be157600080fd5b612bea84612781565b95602085013595506040909401359392505050565b600080600060408486031215612c1457600080fd5b83359250602084013567ffffffffffffffff811115612c3257600080fd5b612c3e86828701612aee565b9497909650939450505050565b600080600080600060808688031215612c6357600080fd5b612c6c86612781565b945060208601359350604086013567ffffffffffffffff80821115612c9057600080fd5b612c9c89838a01612941565b94506060880135915080821115612cb257600080fd5b50612cbf88828901612959565b969995985093965092949392505050565b803563ffffffff811681146127a557600080fd5b600080600060608486031215612cf957600080fd5b83359250612d0960208501612cd0565b9150612d1760408501612cd0565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612daf57612daf612d4f565b5060010190565b600060608236031215612dc857600080fd5b612dd061282d565b823567ffffffffffffffff80821115612de857600080fd5b9084019036601f830112612dfb57600080fd5b8135602082821115612e0f57612e0f6127d4565b612e3f817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612850565b92508183523681838601011115612e5557600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b6019811015612eba57825167ffffffffffffffff16825260209283019290910190600101612e91565b50505092915050565b60008219821115612ed657612ed6612d4f565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612f1057600080fd5b83018035915067ffffffffffffffff821115612f2b57600080fd5b60200191503681900382131561299e57600080fd5b600181815b80851115612f9957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115612f7f57612f7f612d4f565b80851615612f8c57918102915b93841c9390800290612f45565b509250929050565b600082612fb05750600161305c565b81612fbd5750600061305c565b8160018114612fd35760028114612fdd57612ff9565b600191505061305c565b60ff841115612fee57612fee612d4f565b50506001821b61305c565b5060208310610133831016604e8410600b841016171561301c575081810a61305c565b6130268383612f40565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561305857613058612d4f565b0290505b92915050565b600061241c8383612fa1565b60008282101561308057613080612d4f565b500390565b600063ffffffff838116908316818110156130a2576130a2612d4f565b039392505050565b600063ffffffff8083168185168083038211156130c9576130c9612d4f565b01949350505050565b6000845160005b818110156130f357602081880181015185830152016130d9565b81811115613102576000828501525b509190910192835250602082015260400191905056fea164736f6c634300080f000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_absolutePrestate\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_oracle\",\"type\":\"address\",\"internalType\":\"contractPreimageOracle\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"oracle\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIPreimageOracle\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"step\",\"inputs\":[{\"name\":\"_stateData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_localContext\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"postState_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"}]", + Bin: "0x60a060405234801561001057600080fd5b506040516105d23803806105d283398101604081905261002f91610059565b608091909152600080546001600160a01b0319166001600160a01b03909216919091179055610096565b6000806040838503121561006c57600080fd5b825160208401519092506001600160a01b038116811461008b57600080fd5b809150509250929050565b6080516105226100b0600039600060af01526105226000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80637dc0d1d01461003b578063e14ced3214610085575b600080fd5b60005461005b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61009861009336600461039c565b6100a6565b60405190815260200161007c565b600080600060087f0000000000000000000000000000000000000000000000000000000000000000901b600889896040516100e2929190610410565b6040518091039020901b036101e0576000805473ffffffffffffffffffffffffffffffffffffffff1663e03110e161011b6004886102a6565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526004810191909152600060248201526044016040805180830381865afa158015610175573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101999190610420565b50905060006101b3600163ffffffff608085901c16610473565b600481901b9450905060006101ca8a8c018c61048a565b90506101d685826104a3565b935050505061020d565b6101ec878901896104bb565b9092509050816101fb816104dd565b9250508080610209906104dd565b9150505b6040805160208101849052908101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001798975050505050505050565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83161761034c818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b60008083601f84011261036557600080fd5b50813567ffffffffffffffff81111561037d57600080fd5b60208301915083602082850101111561039557600080fd5b9250929050565b6000806000806000606086880312156103b457600080fd5b853567ffffffffffffffff808211156103cc57600080fd5b6103d889838a01610353565b909750955060208801359150808211156103f157600080fd5b506103fe88828901610353565b96999598509660400135949350505050565b8183823760009101908152919050565b6000806040838503121561043357600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561048557610485610444565b500390565b60006020828403121561049c57600080fd5b5035919050565b600082198211156104b6576104b6610444565b500190565b600080604083850312156104ce57600080fd5b50508035926020909101359150565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361050e5761050e610444565b506001019056fea164736f6c634300080f000a", } // AlphabetVMABI is the input ABI used to generate the binding from. @@ -43,7 +43,7 @@ var AlphabetVMABI = AlphabetVMMetaData.ABI var AlphabetVMBin = AlphabetVMMetaData.Bin // DeployAlphabetVM deploys a new Ethereum contract, binding an instance of AlphabetVM to it. -func DeployAlphabetVM(auth *bind.TransactOpts, backend bind.ContractBackend, _absolutePrestate [32]byte) (common.Address, *types.Transaction, *AlphabetVM, error) { +func DeployAlphabetVM(auth *bind.TransactOpts, backend bind.ContractBackend, _absolutePrestate [32]byte, _oracle common.Address) (common.Address, *types.Transaction, *AlphabetVM, error) { parsed, err := AlphabetVMMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -52,7 +52,7 @@ func DeployAlphabetVM(auth *bind.TransactOpts, backend bind.ContractBackend, _ab return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AlphabetVMBin), backend, _absolutePrestate) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(AlphabetVMBin), backend, _absolutePrestate, _oracle) if err != nil { return common.Address{}, nil, nil, err } diff --git a/op-bindings/bindings/alphabetvm_more.go b/op-bindings/bindings/alphabetvm_more.go index 50f496846303..7f4302fbc669 100644 --- a/op-bindings/bindings/alphabetvm_more.go +++ b/op-bindings/bindings/alphabetvm_more.go @@ -13,7 +13,7 @@ const AlphabetVMStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\": var AlphabetVMStorageLayout = new(solc.StorageLayout) -var AlphabetVMDeployedBin = "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80637dc0d1d01461003b578063e14ced3214610085575b600080fd5b60005461005b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610098610093366004610395565b6100a6565b60405190815260200161007c565b600080600060087f0000000000000000000000000000000000000000000000000000000000000000901b600889896040516100e2929190610409565b6040518091039020901b036101d9576000805473ffffffffffffffffffffffffffffffffffffffff1663e03110e161011b60048861029f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526004810191909152600060248201526044016040805180830381865afa158015610175573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101999190610419565b50640ffffffff0607c82901c169350905063ffffffff608082901c1660006101c38a8c018c61043d565b90506101cf8582610485565b9350505050610206565b6101e58789018961049d565b9092509050816101f4816104bf565b9250508080610202906104bf565b9150505b6040805160208101849052908101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001798975050505050505050565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617610345818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b60008083601f84011261035e57600080fd5b50813567ffffffffffffffff81111561037657600080fd5b60208301915083602082850101111561038e57600080fd5b9250929050565b6000806000806000606086880312156103ad57600080fd5b853567ffffffffffffffff808211156103c557600080fd5b6103d189838a0161034c565b909750955060208801359150808211156103ea57600080fd5b506103f78882890161034c565b96999598509660400135949350505050565b8183823760009101908152919050565b6000806040838503121561042c57600080fd5b505080516020909101519092909150565b60006020828403121561044f57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561049857610498610456565b500190565b600080604083850312156104b057600080fd5b50508035926020909101359150565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036104f0576104f0610456565b506001019056fea164736f6c634300080f000a" +var AlphabetVMDeployedBin = "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80637dc0d1d01461003b578063e14ced3214610085575b600080fd5b60005461005b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61009861009336600461039c565b6100a6565b60405190815260200161007c565b600080600060087f0000000000000000000000000000000000000000000000000000000000000000901b600889896040516100e2929190610410565b6040518091039020901b036101e0576000805473ffffffffffffffffffffffffffffffffffffffff1663e03110e161011b6004886102a6565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526004810191909152600060248201526044016040805180830381865afa158015610175573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101999190610420565b50905060006101b3600163ffffffff608085901c16610473565b600481901b9450905060006101ca8a8c018c61048a565b90506101d685826104a3565b935050505061020d565b6101ec878901896104bb565b9092509050816101fb816104dd565b9250508080610209906104dd565b9150505b6040805160208101849052908101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001798975050505050505050565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83161761034c818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b60008083601f84011261036557600080fd5b50813567ffffffffffffffff81111561037d57600080fd5b60208301915083602082850101111561039557600080fd5b9250929050565b6000806000806000606086880312156103b457600080fd5b853567ffffffffffffffff808211156103cc57600080fd5b6103d889838a01610353565b909750955060208801359150808211156103f157600080fd5b506103fe88828901610353565b96999598509660400135949350505050565b8183823760009101908152919050565b6000806040838503121561043357600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561048557610485610444565b500390565b60006020828403121561049c57600080fd5b5035919050565b600082198211156104b6576104b6610444565b500190565b600080604083850312156104ce57600080fd5b50508035926020909101359150565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361050e5761050e610444565b506001019056fea164736f6c634300080f000a" func init() { diff --git a/op-bindings/bindings/dataavailabilitychallenge.go b/op-bindings/bindings/dataavailabilitychallenge.go new file mode 100644 index 000000000000..cbd8dd6edcec --- /dev/null +++ b/op-bindings/bindings/dataavailabilitychallenge.go @@ -0,0 +1,1678 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package bindings + +import ( + "errors" + "math/big" + "strings" + + ethereum "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 +) + +// Challenge is an auto generated low-level Go binding around an user-defined struct. +type Challenge struct { + Challenger common.Address + LockedBond *big.Int + StartBlock *big.Int + ResolvedBlock *big.Int +} + +// DataAvailabilityChallengeMetaData contains all meta data concerning the DataAvailabilityChallenge contract. +var DataAvailabilityChallengeMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"balances\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"bondSize\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"challenge\",\"inputs\":[{\"name\":\"challengedBlockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"challengedCommitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"challengeWindow\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"deposit\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"fixedResolutionCost\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getChallenge\",\"inputs\":[{\"name\":\"challengedBlockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"challengedCommitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structChallenge\",\"components\":[{\"name\":\"challenger\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"lockedBond\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"startBlock\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"resolvedBlock\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getChallengeStatus\",\"inputs\":[{\"name\":\"challengedBlockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"challengedCommitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumChallengeStatus\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_challengeWindow\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_resolveWindow\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_bondSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_resolverRefundPercentage\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resolve\",\"inputs\":[{\"name\":\"challengedBlockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"challengedCommitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"resolveData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resolveWindow\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"resolverRefundPercentage\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setBondSize\",\"inputs\":[{\"name\":\"_bondSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setResolverRefundPercentage\",\"inputs\":[{\"name\":\"_resolverRefundPercentage\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"unlockBond\",\"inputs\":[{\"name\":\"challengedBlockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"challengedCommitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"validateCommitment\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"variableResolutionCost\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"variableResolutionCostPrecision\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"withdraw\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"BalanceChanged\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"balance\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ChallengeStatusChanged\",\"inputs\":[{\"name\":\"challengedBlockNumber\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"challengedCommitment\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"},{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"enumChallengeStatus\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RequiredBondSizeChanged\",\"inputs\":[{\"name\":\"challengeWindow\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ResolverRefundPercentageChanged\",\"inputs\":[{\"name\":\"resolverRefundPercentage\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"BondTooLow\",\"inputs\":[{\"name\":\"balance\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"required\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ChallengeExists\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ChallengeNotActive\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ChallengeNotExpired\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ChallengeWindowNotOpen\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidCommitmentLength\",\"inputs\":[{\"name\":\"commitmentType\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"expectedLength\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"actualLength\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"InvalidInputData\",\"inputs\":[{\"name\":\"providedDataCommitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"expectedCommitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"type\":\"error\",\"name\":\"InvalidResolverRefundPercentage\",\"inputs\":[{\"name\":\"invalidResolverRefundPercentage\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"UnknownCommitmentType\",\"inputs\":[{\"name\":\"commitmentType\",\"type\":\"uint8\",\"internalType\":\"uint8\"}]},{\"type\":\"error\",\"name\":\"WithdrawalFailed\",\"inputs\":[]}]", + Bin: "0x60806040523480156200001157600080fd5b506200002461dead60008080806200002a565b62000392565b600054610100900460ff16158080156200004b5750600054600160ff909116105b806200007b575062000068306200018c60201b6200100e1760201c565b1580156200007b575060005460ff166001145b620000e45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000108576000805461ff0019166101001790555b620001126200019b565b60658590556066849055620001278362000203565b620001328262000248565b6200013d866200027d565b801562000184576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6001600160a01b03163b151590565b600054610100900460ff16620001f75760405162461bcd60e51b815260206004820152602b602482015260008051602062001d7783398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000db565b62000201620002cf565b565b6200020d62000336565b60678190556040518181527f4468d695a0389e5f9e8ef0c9aee6d84e74cc0d0e0a28c8413badb54697d1bbae9060200160405180910390a150565b6200025262000336565b60648111156200027857604051622d549d60e71b815260048101829052602401620000db565b606855565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166200032b5760405162461bcd60e51b815260206004820152602b602482015260008051602062001d7783398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000db565b62000201336200027d565b6033546001600160a01b03163314620002015760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620000db565b6119d580620003a26000396000f3fe6080604052600436106101845760003560e01c8063848afb3d116100d6578063956118521161007f578063d7d04e5411610059578063d7d04e5414610459578063f2fde38b14610479578063f92ad2191461049957600080fd5b80639561185214610427578063a03aafbf1461043e578063d0e30db01461045157600080fd5b80638ecb85e1116100b05780638ecb85e1146103d157806393988233146103e757806393fb19441461040757600080fd5b8063848afb3d1461031d578063861a1412146103865780638da5cb5b1461039c57600080fd5b80634ebaf3ce11610138578063715018a611610112578063715018a6146102bb57806379e8a8b3146102d05780637ae929d9146102fd57600080fd5b80634ebaf3ce1461023957806354fd4d501461024f5780637099c581146102a557600080fd5b806327e235e31161016957806327e235e3146101d7578063336409fd146102045780633ccfd60b1461022457600080fd5b806321cf39ee1461019857806323c30f59146101c157600080fd5b36610193576101916104b9565b005b600080fd5b3480156101a457600080fd5b506101ae60665481565b6040519081526020015b60405180910390f35b3480156101cd57600080fd5b506101ae61410081565b3480156101e357600080fd5b506101ae6101f2366004611539565b60696020526000908152604090205481565b34801561021057600080fd5b5061019161021f366004611554565b610527565b34801561023057600080fd5b50610191610577565b34801561024557600080fd5b506101ae6103e881565b34801561025b57600080fd5b506102986040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101b891906115d8565b3480156102b157600080fd5b506101ae60675481565b3480156102c757600080fd5b50610191610611565b3480156102dc57600080fd5b506102f06102eb366004611634565b610625565b6040516101b891906116ea565b34801561030957600080fd5b506101916103183660046116f8565b6106e8565b34801561032957600080fd5b5061033d610338366004611634565b610884565b6040516101b89190815173ffffffffffffffffffffffffffffffffffffffff16815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561039257600080fd5b506101ae60655481565b3480156103a857600080fd5b5060335460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101b8565b3480156103dd57600080fd5b506101ae60685481565b3480156103f357600080fd5b50610191610402366004611634565b610940565b34801561041357600080fd5b50610191610422366004611772565b610a72565b34801561043357600080fd5b506101ae62011cdd81565b61019161044c366004611634565b610b0f565b6101916104b9565b34801561046557600080fd5b50610191610474366004611554565b610d58565b34801561048557600080fd5b50610191610494366004611539565b610d9b565b3480156104a557600080fd5b506101916104b43660046117b4565b610e52565b33600090815260696020526040812080543492906104d8908490611825565b909155505033600081815260696020908152604091829020548251938452908301527fa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05910160405180910390a1565b61052f61102a565b6064811115610572576040517f16aa4e80000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b606855565b336000818152606960209081526040808320805490849055815194855291840192909252917fa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05910160405180910390a160006105d4335a846110ab565b90508061060d576040517f27fcd9d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b61061961102a565b61062360006110c1565b565b6000838152606a60205260408082209051829190610646908690869061183d565b9081526040805160209281900383018120608082018352805473ffffffffffffffffffffffffffffffffffffffff16808352600182015494830194909452600281015492820192909252600390910154606082015291506106ab5760009150506106e1565b6060810151156106bf5760029150506106e1565b6106cc8160400151611138565b156106db5760019150506106e1565b60039150505b9392505050565b6106f28484610a72565b60016106ff868686610625565b600381111561071057610710611680565b14610747576040517fbeb11d3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006107538585611151565b9050606060ff82166107a15761079e84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061116992505050565b90505b85856040516107b192919061183d565b60405180910390208180519060200120146107fe578086866040517f1a0bbf9f00000000000000000000000000000000000000000000000000000000815260040161056993929190611896565b6000878152606a6020526040808220905161081c908990899061183d565b908152604051908190036020018120436003820155915088907fc5d8c630ba2fdacb1db24c4599df78c7fb8cf97b5aecde34939597f6697bb1ad90610867908a908a906002906118c6565b60405180910390a261087a81853361119c565b5050505050505050565b6108c56040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081525090565b6000848152606a60205260409081902090516108e4908590859061183d565b908152604080519182900360209081018320608084018352805473ffffffffffffffffffffffffffffffffffffffff16845260018101549184019190915260028101549183019190915260030154606082015290509392505050565b600361094d848484610625565b600381111561095e5761095e611680565b14610995576040517f151f07fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152606a602052604080822090516109b3908590859061183d565b90815260408051602092819003830190206001810154815473ffffffffffffffffffffffffffffffffffffffff16600090815260699094529183208054919450919290610a01908490611825565b9091555050600060018201819055815473ffffffffffffffffffffffffffffffffffffffff1680825260696020908152604092839020548351928352908201527fa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05910160405180910390a150505050565b6000610a7e8383611151565b905060ff8116610ad85760218214610ad3576040517ffd9a7e5b000000000000000000000000000000000000000000000000000000008152600060048201526021602482015260448101839052606401610569565b505050565b6040517f81ff071300000000000000000000000000000000000000000000000000000000815260ff82166004820152602401610569565b610b198282610a72565b610b216104b9565b606754336000908152606960205260409020541015610b895733600090815260696020526040908190205460675491517e0155b50000000000000000000000000000000000000000000000000000000081526105699290600401918252602082015260400190565b6000610b96848484610625565b6003811115610ba757610ba7611680565b14610bde576040517f9bb6c64e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610be7836113bc565b610c1d576040517ff9e0d1f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6067543360009081526069602052604081208054909190610c3f9084906118f1565b9250508190555060405180608001604052803373ffffffffffffffffffffffffffffffffffffffff16815260200160675481526020014381526020016000815250606a60008581526020019081526020016000208383604051610ca392919061183d565b9081526040805160209281900383018120845181547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161781559284015160018085019190915591840151600284015560609093015160039092019190915584917fc5d8c630ba2fdacb1db24c4599df78c7fb8cf97b5aecde34939597f6697bb1ad91610d4b91869186916118c6565b60405180910390a2505050565b610d6061102a565b60678190556040518181527f4468d695a0389e5f9e8ef0c9aee6d84e74cc0d0e0a28c8413badb54697d1bbae9060200160405180910390a150565b610da361102a565b73ffffffffffffffffffffffffffffffffffffffff8116610e46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610569565b610e4f816110c1565b50565b600054610100900460ff1615808015610e725750600054600160ff909116105b80610e8c5750303b158015610e8c575060005460ff166001145b610f18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610569565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610f7657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610f7e6113d6565b60658590556066849055610f9183610d58565b610f9a82610527565b610fa3866110c1565b801561100657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610623576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610569565b600080600080600080868989f195945050505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000606654826111489190611825565b43111592915050565b600061115d8284611908565b60f81c90505b92915050565b80516020918201206040805160009381019390935260218084019290925280518084039092018252604190920190915290565b6001830154835473ffffffffffffffffffffffffffffffffffffffff166000486103e86111cb61410088611950565b6111d5919061198d565b6111e29062011cdd611825565b6111ec9190611950565b90508083111561129e5761120081846118f1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526069602052604081208054909190611235908490611825565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152606960209081526040918290205482519384529083015291935083917fa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05910160405180910390a15b60006064606854836112b09190611950565b6112ba919061198d565b9050838111156112c75750825b80156113745773ffffffffffffffffffffffffffffffffffffffff851660009081526069602052604081208054839290611302908490611825565b90915550611312905081856118f1565b73ffffffffffffffffffffffffffffffffffffffff8616600081815260696020908152604091829020548251938452908301529195507fa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05910160405180910390a15b83156113a95760405160009085156108fc0290869083818181858288f193505050501580156113a7573d6000803e3d6000fd5b505b6000876001018190555050505050505050565b600081431015801561116357506065546111489083611825565b600054610100900460ff1661146d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610569565b610623600054610100900460ff16611507576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610569565b610623336110c1565b803573ffffffffffffffffffffffffffffffffffffffff8116811461153457600080fd5b919050565b60006020828403121561154b57600080fd5b6106e182611510565b60006020828403121561156657600080fd5b5035919050565b6000815180845260005b8181101561159357602081850181015186830182015201611577565b818111156115a5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006106e1602083018461156d565b60008083601f8401126115fd57600080fd5b50813567ffffffffffffffff81111561161557600080fd5b60208301915083602082850101111561162d57600080fd5b9250929050565b60008060006040848603121561164957600080fd5b83359250602084013567ffffffffffffffff81111561166757600080fd5b611673868287016115eb565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106116e6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6020810161116382846116af565b60008060008060006060868803121561171057600080fd5b85359450602086013567ffffffffffffffff8082111561172f57600080fd5b61173b89838a016115eb565b9096509450604088013591508082111561175457600080fd5b50611761888289016115eb565b969995985093965092949392505050565b6000806020838503121561178557600080fd5b823567ffffffffffffffff81111561179c57600080fd5b6117a8858286016115eb565b90969095509350505050565b600080600080600060a086880312156117cc57600080fd5b6117d586611510565b97602087013597506040870135966060810135965060800135945092505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115611838576118386117f6565b500190565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6040815260006118a9604083018661156d565b82810360208401526118bc81858761184d565b9695505050505050565b6040815260006118da60408301858761184d565b90506118e960208301846116af565b949350505050565b600082821015611903576119036117f6565b500390565b7fff0000000000000000000000000000000000000000000000000000000000000081358181169160018510156119485780818660010360031b1b83161692505b505092915050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611988576119886117f6565b500290565b6000826119c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", +} + +// DataAvailabilityChallengeABI is the input ABI used to generate the binding from. +// Deprecated: Use DataAvailabilityChallengeMetaData.ABI instead. +var DataAvailabilityChallengeABI = DataAvailabilityChallengeMetaData.ABI + +// DataAvailabilityChallengeBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use DataAvailabilityChallengeMetaData.Bin instead. +var DataAvailabilityChallengeBin = DataAvailabilityChallengeMetaData.Bin + +// DeployDataAvailabilityChallenge deploys a new Ethereum contract, binding an instance of DataAvailabilityChallenge to it. +func DeployDataAvailabilityChallenge(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *DataAvailabilityChallenge, error) { + parsed, err := DataAvailabilityChallengeMetaData.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(DataAvailabilityChallengeBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &DataAvailabilityChallenge{DataAvailabilityChallengeCaller: DataAvailabilityChallengeCaller{contract: contract}, DataAvailabilityChallengeTransactor: DataAvailabilityChallengeTransactor{contract: contract}, DataAvailabilityChallengeFilterer: DataAvailabilityChallengeFilterer{contract: contract}}, nil +} + +// DataAvailabilityChallenge is an auto generated Go binding around an Ethereum contract. +type DataAvailabilityChallenge struct { + DataAvailabilityChallengeCaller // Read-only binding to the contract + DataAvailabilityChallengeTransactor // Write-only binding to the contract + DataAvailabilityChallengeFilterer // Log filterer for contract events +} + +// DataAvailabilityChallengeCaller is an auto generated read-only Go binding around an Ethereum contract. +type DataAvailabilityChallengeCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DataAvailabilityChallengeTransactor is an auto generated write-only Go binding around an Ethereum contract. +type DataAvailabilityChallengeTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DataAvailabilityChallengeFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type DataAvailabilityChallengeFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DataAvailabilityChallengeSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type DataAvailabilityChallengeSession struct { + Contract *DataAvailabilityChallenge // 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 +} + +// DataAvailabilityChallengeCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type DataAvailabilityChallengeCallerSession struct { + Contract *DataAvailabilityChallengeCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// DataAvailabilityChallengeTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type DataAvailabilityChallengeTransactorSession struct { + Contract *DataAvailabilityChallengeTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// DataAvailabilityChallengeRaw is an auto generated low-level Go binding around an Ethereum contract. +type DataAvailabilityChallengeRaw struct { + Contract *DataAvailabilityChallenge // Generic contract binding to access the raw methods on +} + +// DataAvailabilityChallengeCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type DataAvailabilityChallengeCallerRaw struct { + Contract *DataAvailabilityChallengeCaller // Generic read-only contract binding to access the raw methods on +} + +// DataAvailabilityChallengeTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type DataAvailabilityChallengeTransactorRaw struct { + Contract *DataAvailabilityChallengeTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewDataAvailabilityChallenge creates a new instance of DataAvailabilityChallenge, bound to a specific deployed contract. +func NewDataAvailabilityChallenge(address common.Address, backend bind.ContractBackend) (*DataAvailabilityChallenge, error) { + contract, err := bindDataAvailabilityChallenge(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &DataAvailabilityChallenge{DataAvailabilityChallengeCaller: DataAvailabilityChallengeCaller{contract: contract}, DataAvailabilityChallengeTransactor: DataAvailabilityChallengeTransactor{contract: contract}, DataAvailabilityChallengeFilterer: DataAvailabilityChallengeFilterer{contract: contract}}, nil +} + +// NewDataAvailabilityChallengeCaller creates a new read-only instance of DataAvailabilityChallenge, bound to a specific deployed contract. +func NewDataAvailabilityChallengeCaller(address common.Address, caller bind.ContractCaller) (*DataAvailabilityChallengeCaller, error) { + contract, err := bindDataAvailabilityChallenge(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &DataAvailabilityChallengeCaller{contract: contract}, nil +} + +// NewDataAvailabilityChallengeTransactor creates a new write-only instance of DataAvailabilityChallenge, bound to a specific deployed contract. +func NewDataAvailabilityChallengeTransactor(address common.Address, transactor bind.ContractTransactor) (*DataAvailabilityChallengeTransactor, error) { + contract, err := bindDataAvailabilityChallenge(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &DataAvailabilityChallengeTransactor{contract: contract}, nil +} + +// NewDataAvailabilityChallengeFilterer creates a new log filterer instance of DataAvailabilityChallenge, bound to a specific deployed contract. +func NewDataAvailabilityChallengeFilterer(address common.Address, filterer bind.ContractFilterer) (*DataAvailabilityChallengeFilterer, error) { + contract, err := bindDataAvailabilityChallenge(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &DataAvailabilityChallengeFilterer{contract: contract}, nil +} + +// bindDataAvailabilityChallenge binds a generic wrapper to an already deployed contract. +func bindDataAvailabilityChallenge(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(DataAvailabilityChallengeABI)) + 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 (_DataAvailabilityChallenge *DataAvailabilityChallengeRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _DataAvailabilityChallenge.Contract.DataAvailabilityChallengeCaller.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 (_DataAvailabilityChallenge *DataAvailabilityChallengeRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.DataAvailabilityChallengeTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_DataAvailabilityChallenge *DataAvailabilityChallengeRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.DataAvailabilityChallengeTransactor.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 (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _DataAvailabilityChallenge.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 (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.contract.Transact(opts, method, params...) +} + +// Balances is a free data retrieval call binding the contract method 0x27e235e3. +// +// Solidity: function balances(address ) view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCaller) Balances(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _DataAvailabilityChallenge.contract.Call(opts, &out, "balances", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Balances is a free data retrieval call binding the contract method 0x27e235e3. +// +// Solidity: function balances(address ) view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) Balances(arg0 common.Address) (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.Balances(&_DataAvailabilityChallenge.CallOpts, arg0) +} + +// Balances is a free data retrieval call binding the contract method 0x27e235e3. +// +// Solidity: function balances(address ) view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerSession) Balances(arg0 common.Address) (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.Balances(&_DataAvailabilityChallenge.CallOpts, arg0) +} + +// BondSize is a free data retrieval call binding the contract method 0x7099c581. +// +// Solidity: function bondSize() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCaller) BondSize(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _DataAvailabilityChallenge.contract.Call(opts, &out, "bondSize") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BondSize is a free data retrieval call binding the contract method 0x7099c581. +// +// Solidity: function bondSize() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) BondSize() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.BondSize(&_DataAvailabilityChallenge.CallOpts) +} + +// BondSize is a free data retrieval call binding the contract method 0x7099c581. +// +// Solidity: function bondSize() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerSession) BondSize() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.BondSize(&_DataAvailabilityChallenge.CallOpts) +} + +// ChallengeWindow is a free data retrieval call binding the contract method 0x861a1412. +// +// Solidity: function challengeWindow() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCaller) ChallengeWindow(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _DataAvailabilityChallenge.contract.Call(opts, &out, "challengeWindow") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ChallengeWindow is a free data retrieval call binding the contract method 0x861a1412. +// +// Solidity: function challengeWindow() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) ChallengeWindow() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.ChallengeWindow(&_DataAvailabilityChallenge.CallOpts) +} + +// ChallengeWindow is a free data retrieval call binding the contract method 0x861a1412. +// +// Solidity: function challengeWindow() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerSession) ChallengeWindow() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.ChallengeWindow(&_DataAvailabilityChallenge.CallOpts) +} + +// FixedResolutionCost is a free data retrieval call binding the contract method 0x95611852. +// +// Solidity: function fixedResolutionCost() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCaller) FixedResolutionCost(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _DataAvailabilityChallenge.contract.Call(opts, &out, "fixedResolutionCost") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// FixedResolutionCost is a free data retrieval call binding the contract method 0x95611852. +// +// Solidity: function fixedResolutionCost() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) FixedResolutionCost() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.FixedResolutionCost(&_DataAvailabilityChallenge.CallOpts) +} + +// FixedResolutionCost is a free data retrieval call binding the contract method 0x95611852. +// +// Solidity: function fixedResolutionCost() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerSession) FixedResolutionCost() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.FixedResolutionCost(&_DataAvailabilityChallenge.CallOpts) +} + +// GetChallenge is a free data retrieval call binding the contract method 0x848afb3d. +// +// Solidity: function getChallenge(uint256 challengedBlockNumber, bytes challengedCommitment) view returns((address,uint256,uint256,uint256)) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCaller) GetChallenge(opts *bind.CallOpts, challengedBlockNumber *big.Int, challengedCommitment []byte) (Challenge, error) { + var out []interface{} + err := _DataAvailabilityChallenge.contract.Call(opts, &out, "getChallenge", challengedBlockNumber, challengedCommitment) + + if err != nil { + return *new(Challenge), err + } + + out0 := *abi.ConvertType(out[0], new(Challenge)).(*Challenge) + + return out0, err + +} + +// GetChallenge is a free data retrieval call binding the contract method 0x848afb3d. +// +// Solidity: function getChallenge(uint256 challengedBlockNumber, bytes challengedCommitment) view returns((address,uint256,uint256,uint256)) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) GetChallenge(challengedBlockNumber *big.Int, challengedCommitment []byte) (Challenge, error) { + return _DataAvailabilityChallenge.Contract.GetChallenge(&_DataAvailabilityChallenge.CallOpts, challengedBlockNumber, challengedCommitment) +} + +// GetChallenge is a free data retrieval call binding the contract method 0x848afb3d. +// +// Solidity: function getChallenge(uint256 challengedBlockNumber, bytes challengedCommitment) view returns((address,uint256,uint256,uint256)) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerSession) GetChallenge(challengedBlockNumber *big.Int, challengedCommitment []byte) (Challenge, error) { + return _DataAvailabilityChallenge.Contract.GetChallenge(&_DataAvailabilityChallenge.CallOpts, challengedBlockNumber, challengedCommitment) +} + +// GetChallengeStatus is a free data retrieval call binding the contract method 0x79e8a8b3. +// +// Solidity: function getChallengeStatus(uint256 challengedBlockNumber, bytes challengedCommitment) view returns(uint8) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCaller) GetChallengeStatus(opts *bind.CallOpts, challengedBlockNumber *big.Int, challengedCommitment []byte) (uint8, error) { + var out []interface{} + err := _DataAvailabilityChallenge.contract.Call(opts, &out, "getChallengeStatus", challengedBlockNumber, challengedCommitment) + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// GetChallengeStatus is a free data retrieval call binding the contract method 0x79e8a8b3. +// +// Solidity: function getChallengeStatus(uint256 challengedBlockNumber, bytes challengedCommitment) view returns(uint8) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) GetChallengeStatus(challengedBlockNumber *big.Int, challengedCommitment []byte) (uint8, error) { + return _DataAvailabilityChallenge.Contract.GetChallengeStatus(&_DataAvailabilityChallenge.CallOpts, challengedBlockNumber, challengedCommitment) +} + +// GetChallengeStatus is a free data retrieval call binding the contract method 0x79e8a8b3. +// +// Solidity: function getChallengeStatus(uint256 challengedBlockNumber, bytes challengedCommitment) view returns(uint8) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerSession) GetChallengeStatus(challengedBlockNumber *big.Int, challengedCommitment []byte) (uint8, error) { + return _DataAvailabilityChallenge.Contract.GetChallengeStatus(&_DataAvailabilityChallenge.CallOpts, challengedBlockNumber, challengedCommitment) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _DataAvailabilityChallenge.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) Owner() (common.Address, error) { + return _DataAvailabilityChallenge.Contract.Owner(&_DataAvailabilityChallenge.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerSession) Owner() (common.Address, error) { + return _DataAvailabilityChallenge.Contract.Owner(&_DataAvailabilityChallenge.CallOpts) +} + +// ResolveWindow is a free data retrieval call binding the contract method 0x21cf39ee. +// +// Solidity: function resolveWindow() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCaller) ResolveWindow(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _DataAvailabilityChallenge.contract.Call(opts, &out, "resolveWindow") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ResolveWindow is a free data retrieval call binding the contract method 0x21cf39ee. +// +// Solidity: function resolveWindow() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) ResolveWindow() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.ResolveWindow(&_DataAvailabilityChallenge.CallOpts) +} + +// ResolveWindow is a free data retrieval call binding the contract method 0x21cf39ee. +// +// Solidity: function resolveWindow() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerSession) ResolveWindow() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.ResolveWindow(&_DataAvailabilityChallenge.CallOpts) +} + +// ResolverRefundPercentage is a free data retrieval call binding the contract method 0x8ecb85e1. +// +// Solidity: function resolverRefundPercentage() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCaller) ResolverRefundPercentage(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _DataAvailabilityChallenge.contract.Call(opts, &out, "resolverRefundPercentage") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ResolverRefundPercentage is a free data retrieval call binding the contract method 0x8ecb85e1. +// +// Solidity: function resolverRefundPercentage() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) ResolverRefundPercentage() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.ResolverRefundPercentage(&_DataAvailabilityChallenge.CallOpts) +} + +// ResolverRefundPercentage is a free data retrieval call binding the contract method 0x8ecb85e1. +// +// Solidity: function resolverRefundPercentage() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerSession) ResolverRefundPercentage() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.ResolverRefundPercentage(&_DataAvailabilityChallenge.CallOpts) +} + +// ValidateCommitment is a free data retrieval call binding the contract method 0x93fb1944. +// +// Solidity: function validateCommitment(bytes commitment) pure returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCaller) ValidateCommitment(opts *bind.CallOpts, commitment []byte) error { + var out []interface{} + err := _DataAvailabilityChallenge.contract.Call(opts, &out, "validateCommitment", commitment) + + if err != nil { + return err + } + + return err + +} + +// ValidateCommitment is a free data retrieval call binding the contract method 0x93fb1944. +// +// Solidity: function validateCommitment(bytes commitment) pure returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) ValidateCommitment(commitment []byte) error { + return _DataAvailabilityChallenge.Contract.ValidateCommitment(&_DataAvailabilityChallenge.CallOpts, commitment) +} + +// ValidateCommitment is a free data retrieval call binding the contract method 0x93fb1944. +// +// Solidity: function validateCommitment(bytes commitment) pure returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerSession) ValidateCommitment(commitment []byte) error { + return _DataAvailabilityChallenge.Contract.ValidateCommitment(&_DataAvailabilityChallenge.CallOpts, commitment) +} + +// VariableResolutionCost is a free data retrieval call binding the contract method 0x23c30f59. +// +// Solidity: function variableResolutionCost() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCaller) VariableResolutionCost(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _DataAvailabilityChallenge.contract.Call(opts, &out, "variableResolutionCost") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// VariableResolutionCost is a free data retrieval call binding the contract method 0x23c30f59. +// +// Solidity: function variableResolutionCost() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) VariableResolutionCost() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.VariableResolutionCost(&_DataAvailabilityChallenge.CallOpts) +} + +// VariableResolutionCost is a free data retrieval call binding the contract method 0x23c30f59. +// +// Solidity: function variableResolutionCost() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerSession) VariableResolutionCost() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.VariableResolutionCost(&_DataAvailabilityChallenge.CallOpts) +} + +// VariableResolutionCostPrecision is a free data retrieval call binding the contract method 0x4ebaf3ce. +// +// Solidity: function variableResolutionCostPrecision() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCaller) VariableResolutionCostPrecision(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _DataAvailabilityChallenge.contract.Call(opts, &out, "variableResolutionCostPrecision") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// VariableResolutionCostPrecision is a free data retrieval call binding the contract method 0x4ebaf3ce. +// +// Solidity: function variableResolutionCostPrecision() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) VariableResolutionCostPrecision() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.VariableResolutionCostPrecision(&_DataAvailabilityChallenge.CallOpts) +} + +// VariableResolutionCostPrecision is a free data retrieval call binding the contract method 0x4ebaf3ce. +// +// Solidity: function variableResolutionCostPrecision() view returns(uint256) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerSession) VariableResolutionCostPrecision() (*big.Int, error) { + return _DataAvailabilityChallenge.Contract.VariableResolutionCostPrecision(&_DataAvailabilityChallenge.CallOpts) +} + +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCaller) Version(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _DataAvailabilityChallenge.contract.Call(opts, &out, "version") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) Version() (string, error) { + return _DataAvailabilityChallenge.Contract.Version(&_DataAvailabilityChallenge.CallOpts) +} + +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeCallerSession) Version() (string, error) { + return _DataAvailabilityChallenge.Contract.Version(&_DataAvailabilityChallenge.CallOpts) +} + +// Challenge is a paid mutator transaction binding the contract method 0xa03aafbf. +// +// Solidity: function challenge(uint256 challengedBlockNumber, bytes challengedCommitment) payable returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactor) Challenge(opts *bind.TransactOpts, challengedBlockNumber *big.Int, challengedCommitment []byte) (*types.Transaction, error) { + return _DataAvailabilityChallenge.contract.Transact(opts, "challenge", challengedBlockNumber, challengedCommitment) +} + +// Challenge is a paid mutator transaction binding the contract method 0xa03aafbf. +// +// Solidity: function challenge(uint256 challengedBlockNumber, bytes challengedCommitment) payable returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) Challenge(challengedBlockNumber *big.Int, challengedCommitment []byte) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.Challenge(&_DataAvailabilityChallenge.TransactOpts, challengedBlockNumber, challengedCommitment) +} + +// Challenge is a paid mutator transaction binding the contract method 0xa03aafbf. +// +// Solidity: function challenge(uint256 challengedBlockNumber, bytes challengedCommitment) payable returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactorSession) Challenge(challengedBlockNumber *big.Int, challengedCommitment []byte) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.Challenge(&_DataAvailabilityChallenge.TransactOpts, challengedBlockNumber, challengedCommitment) +} + +// Deposit is a paid mutator transaction binding the contract method 0xd0e30db0. +// +// Solidity: function deposit() payable returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactor) Deposit(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DataAvailabilityChallenge.contract.Transact(opts, "deposit") +} + +// Deposit is a paid mutator transaction binding the contract method 0xd0e30db0. +// +// Solidity: function deposit() payable returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) Deposit() (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.Deposit(&_DataAvailabilityChallenge.TransactOpts) +} + +// Deposit is a paid mutator transaction binding the contract method 0xd0e30db0. +// +// Solidity: function deposit() payable returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactorSession) Deposit() (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.Deposit(&_DataAvailabilityChallenge.TransactOpts) +} + +// Initialize is a paid mutator transaction binding the contract method 0xf92ad219. +// +// Solidity: function initialize(address _owner, uint256 _challengeWindow, uint256 _resolveWindow, uint256 _bondSize, uint256 _resolverRefundPercentage) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactor) Initialize(opts *bind.TransactOpts, _owner common.Address, _challengeWindow *big.Int, _resolveWindow *big.Int, _bondSize *big.Int, _resolverRefundPercentage *big.Int) (*types.Transaction, error) { + return _DataAvailabilityChallenge.contract.Transact(opts, "initialize", _owner, _challengeWindow, _resolveWindow, _bondSize, _resolverRefundPercentage) +} + +// Initialize is a paid mutator transaction binding the contract method 0xf92ad219. +// +// Solidity: function initialize(address _owner, uint256 _challengeWindow, uint256 _resolveWindow, uint256 _bondSize, uint256 _resolverRefundPercentage) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) Initialize(_owner common.Address, _challengeWindow *big.Int, _resolveWindow *big.Int, _bondSize *big.Int, _resolverRefundPercentage *big.Int) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.Initialize(&_DataAvailabilityChallenge.TransactOpts, _owner, _challengeWindow, _resolveWindow, _bondSize, _resolverRefundPercentage) +} + +// Initialize is a paid mutator transaction binding the contract method 0xf92ad219. +// +// Solidity: function initialize(address _owner, uint256 _challengeWindow, uint256 _resolveWindow, uint256 _bondSize, uint256 _resolverRefundPercentage) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactorSession) Initialize(_owner common.Address, _challengeWindow *big.Int, _resolveWindow *big.Int, _bondSize *big.Int, _resolverRefundPercentage *big.Int) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.Initialize(&_DataAvailabilityChallenge.TransactOpts, _owner, _challengeWindow, _resolveWindow, _bondSize, _resolverRefundPercentage) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DataAvailabilityChallenge.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) RenounceOwnership() (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.RenounceOwnership(&_DataAvailabilityChallenge.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.RenounceOwnership(&_DataAvailabilityChallenge.TransactOpts) +} + +// Resolve is a paid mutator transaction binding the contract method 0x7ae929d9. +// +// Solidity: function resolve(uint256 challengedBlockNumber, bytes challengedCommitment, bytes resolveData) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactor) Resolve(opts *bind.TransactOpts, challengedBlockNumber *big.Int, challengedCommitment []byte, resolveData []byte) (*types.Transaction, error) { + return _DataAvailabilityChallenge.contract.Transact(opts, "resolve", challengedBlockNumber, challengedCommitment, resolveData) +} + +// Resolve is a paid mutator transaction binding the contract method 0x7ae929d9. +// +// Solidity: function resolve(uint256 challengedBlockNumber, bytes challengedCommitment, bytes resolveData) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) Resolve(challengedBlockNumber *big.Int, challengedCommitment []byte, resolveData []byte) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.Resolve(&_DataAvailabilityChallenge.TransactOpts, challengedBlockNumber, challengedCommitment, resolveData) +} + +// Resolve is a paid mutator transaction binding the contract method 0x7ae929d9. +// +// Solidity: function resolve(uint256 challengedBlockNumber, bytes challengedCommitment, bytes resolveData) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactorSession) Resolve(challengedBlockNumber *big.Int, challengedCommitment []byte, resolveData []byte) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.Resolve(&_DataAvailabilityChallenge.TransactOpts, challengedBlockNumber, challengedCommitment, resolveData) +} + +// SetBondSize is a paid mutator transaction binding the contract method 0xd7d04e54. +// +// Solidity: function setBondSize(uint256 _bondSize) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactor) SetBondSize(opts *bind.TransactOpts, _bondSize *big.Int) (*types.Transaction, error) { + return _DataAvailabilityChallenge.contract.Transact(opts, "setBondSize", _bondSize) +} + +// SetBondSize is a paid mutator transaction binding the contract method 0xd7d04e54. +// +// Solidity: function setBondSize(uint256 _bondSize) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) SetBondSize(_bondSize *big.Int) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.SetBondSize(&_DataAvailabilityChallenge.TransactOpts, _bondSize) +} + +// SetBondSize is a paid mutator transaction binding the contract method 0xd7d04e54. +// +// Solidity: function setBondSize(uint256 _bondSize) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactorSession) SetBondSize(_bondSize *big.Int) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.SetBondSize(&_DataAvailabilityChallenge.TransactOpts, _bondSize) +} + +// SetResolverRefundPercentage is a paid mutator transaction binding the contract method 0x336409fd. +// +// Solidity: function setResolverRefundPercentage(uint256 _resolverRefundPercentage) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactor) SetResolverRefundPercentage(opts *bind.TransactOpts, _resolverRefundPercentage *big.Int) (*types.Transaction, error) { + return _DataAvailabilityChallenge.contract.Transact(opts, "setResolverRefundPercentage", _resolverRefundPercentage) +} + +// SetResolverRefundPercentage is a paid mutator transaction binding the contract method 0x336409fd. +// +// Solidity: function setResolverRefundPercentage(uint256 _resolverRefundPercentage) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) SetResolverRefundPercentage(_resolverRefundPercentage *big.Int) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.SetResolverRefundPercentage(&_DataAvailabilityChallenge.TransactOpts, _resolverRefundPercentage) +} + +// SetResolverRefundPercentage is a paid mutator transaction binding the contract method 0x336409fd. +// +// Solidity: function setResolverRefundPercentage(uint256 _resolverRefundPercentage) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactorSession) SetResolverRefundPercentage(_resolverRefundPercentage *big.Int) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.SetResolverRefundPercentage(&_DataAvailabilityChallenge.TransactOpts, _resolverRefundPercentage) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _DataAvailabilityChallenge.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.TransferOwnership(&_DataAvailabilityChallenge.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.TransferOwnership(&_DataAvailabilityChallenge.TransactOpts, newOwner) +} + +// UnlockBond is a paid mutator transaction binding the contract method 0x93988233. +// +// Solidity: function unlockBond(uint256 challengedBlockNumber, bytes challengedCommitment) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactor) UnlockBond(opts *bind.TransactOpts, challengedBlockNumber *big.Int, challengedCommitment []byte) (*types.Transaction, error) { + return _DataAvailabilityChallenge.contract.Transact(opts, "unlockBond", challengedBlockNumber, challengedCommitment) +} + +// UnlockBond is a paid mutator transaction binding the contract method 0x93988233. +// +// Solidity: function unlockBond(uint256 challengedBlockNumber, bytes challengedCommitment) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) UnlockBond(challengedBlockNumber *big.Int, challengedCommitment []byte) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.UnlockBond(&_DataAvailabilityChallenge.TransactOpts, challengedBlockNumber, challengedCommitment) +} + +// UnlockBond is a paid mutator transaction binding the contract method 0x93988233. +// +// Solidity: function unlockBond(uint256 challengedBlockNumber, bytes challengedCommitment) returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactorSession) UnlockBond(challengedBlockNumber *big.Int, challengedCommitment []byte) (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.UnlockBond(&_DataAvailabilityChallenge.TransactOpts, challengedBlockNumber, challengedCommitment) +} + +// Withdraw is a paid mutator transaction binding the contract method 0x3ccfd60b. +// +// Solidity: function withdraw() returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactor) Withdraw(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DataAvailabilityChallenge.contract.Transact(opts, "withdraw") +} + +// Withdraw is a paid mutator transaction binding the contract method 0x3ccfd60b. +// +// Solidity: function withdraw() returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) Withdraw() (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.Withdraw(&_DataAvailabilityChallenge.TransactOpts) +} + +// Withdraw is a paid mutator transaction binding the contract method 0x3ccfd60b. +// +// Solidity: function withdraw() returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactorSession) Withdraw() (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.Withdraw(&_DataAvailabilityChallenge.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DataAvailabilityChallenge.contract.RawTransact(opts, nil) // calldata is disallowed for receive function +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeSession) Receive() (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.Receive(&_DataAvailabilityChallenge.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_DataAvailabilityChallenge *DataAvailabilityChallengeTransactorSession) Receive() (*types.Transaction, error) { + return _DataAvailabilityChallenge.Contract.Receive(&_DataAvailabilityChallenge.TransactOpts) +} + +// DataAvailabilityChallengeBalanceChangedIterator is returned from FilterBalanceChanged and is used to iterate over the raw logs and unpacked data for BalanceChanged events raised by the DataAvailabilityChallenge contract. +type DataAvailabilityChallengeBalanceChangedIterator struct { + Event *DataAvailabilityChallengeBalanceChanged // 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 *DataAvailabilityChallengeBalanceChangedIterator) 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(DataAvailabilityChallengeBalanceChanged) + 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(DataAvailabilityChallengeBalanceChanged) + 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 *DataAvailabilityChallengeBalanceChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DataAvailabilityChallengeBalanceChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DataAvailabilityChallengeBalanceChanged represents a BalanceChanged event raised by the DataAvailabilityChallenge contract. +type DataAvailabilityChallengeBalanceChanged struct { + Account common.Address + Balance *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterBalanceChanged is a free log retrieval operation binding the contract event 0xa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05. +// +// Solidity: event BalanceChanged(address account, uint256 balance) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) FilterBalanceChanged(opts *bind.FilterOpts) (*DataAvailabilityChallengeBalanceChangedIterator, error) { + + logs, sub, err := _DataAvailabilityChallenge.contract.FilterLogs(opts, "BalanceChanged") + if err != nil { + return nil, err + } + return &DataAvailabilityChallengeBalanceChangedIterator{contract: _DataAvailabilityChallenge.contract, event: "BalanceChanged", logs: logs, sub: sub}, nil +} + +// WatchBalanceChanged is a free log subscription operation binding the contract event 0xa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05. +// +// Solidity: event BalanceChanged(address account, uint256 balance) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) WatchBalanceChanged(opts *bind.WatchOpts, sink chan<- *DataAvailabilityChallengeBalanceChanged) (event.Subscription, error) { + + logs, sub, err := _DataAvailabilityChallenge.contract.WatchLogs(opts, "BalanceChanged") + 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(DataAvailabilityChallengeBalanceChanged) + if err := _DataAvailabilityChallenge.contract.UnpackLog(event, "BalanceChanged", 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 +} + +// ParseBalanceChanged is a log parse operation binding the contract event 0xa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05. +// +// Solidity: event BalanceChanged(address account, uint256 balance) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) ParseBalanceChanged(log types.Log) (*DataAvailabilityChallengeBalanceChanged, error) { + event := new(DataAvailabilityChallengeBalanceChanged) + if err := _DataAvailabilityChallenge.contract.UnpackLog(event, "BalanceChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DataAvailabilityChallengeChallengeStatusChangedIterator is returned from FilterChallengeStatusChanged and is used to iterate over the raw logs and unpacked data for ChallengeStatusChanged events raised by the DataAvailabilityChallenge contract. +type DataAvailabilityChallengeChallengeStatusChangedIterator struct { + Event *DataAvailabilityChallengeChallengeStatusChanged // 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 *DataAvailabilityChallengeChallengeStatusChangedIterator) 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(DataAvailabilityChallengeChallengeStatusChanged) + 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(DataAvailabilityChallengeChallengeStatusChanged) + 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 *DataAvailabilityChallengeChallengeStatusChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DataAvailabilityChallengeChallengeStatusChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DataAvailabilityChallengeChallengeStatusChanged represents a ChallengeStatusChanged event raised by the DataAvailabilityChallenge contract. +type DataAvailabilityChallengeChallengeStatusChanged struct { + ChallengedBlockNumber *big.Int + ChallengedCommitment []byte + Status uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterChallengeStatusChanged is a free log retrieval operation binding the contract event 0xc5d8c630ba2fdacb1db24c4599df78c7fb8cf97b5aecde34939597f6697bb1ad. +// +// Solidity: event ChallengeStatusChanged(uint256 indexed challengedBlockNumber, bytes challengedCommitment, uint8 status) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) FilterChallengeStatusChanged(opts *bind.FilterOpts, challengedBlockNumber []*big.Int) (*DataAvailabilityChallengeChallengeStatusChangedIterator, error) { + + var challengedBlockNumberRule []interface{} + for _, challengedBlockNumberItem := range challengedBlockNumber { + challengedBlockNumberRule = append(challengedBlockNumberRule, challengedBlockNumberItem) + } + + logs, sub, err := _DataAvailabilityChallenge.contract.FilterLogs(opts, "ChallengeStatusChanged", challengedBlockNumberRule) + if err != nil { + return nil, err + } + return &DataAvailabilityChallengeChallengeStatusChangedIterator{contract: _DataAvailabilityChallenge.contract, event: "ChallengeStatusChanged", logs: logs, sub: sub}, nil +} + +// WatchChallengeStatusChanged is a free log subscription operation binding the contract event 0xc5d8c630ba2fdacb1db24c4599df78c7fb8cf97b5aecde34939597f6697bb1ad. +// +// Solidity: event ChallengeStatusChanged(uint256 indexed challengedBlockNumber, bytes challengedCommitment, uint8 status) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) WatchChallengeStatusChanged(opts *bind.WatchOpts, sink chan<- *DataAvailabilityChallengeChallengeStatusChanged, challengedBlockNumber []*big.Int) (event.Subscription, error) { + + var challengedBlockNumberRule []interface{} + for _, challengedBlockNumberItem := range challengedBlockNumber { + challengedBlockNumberRule = append(challengedBlockNumberRule, challengedBlockNumberItem) + } + + logs, sub, err := _DataAvailabilityChallenge.contract.WatchLogs(opts, "ChallengeStatusChanged", challengedBlockNumberRule) + 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(DataAvailabilityChallengeChallengeStatusChanged) + if err := _DataAvailabilityChallenge.contract.UnpackLog(event, "ChallengeStatusChanged", 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 +} + +// ParseChallengeStatusChanged is a log parse operation binding the contract event 0xc5d8c630ba2fdacb1db24c4599df78c7fb8cf97b5aecde34939597f6697bb1ad. +// +// Solidity: event ChallengeStatusChanged(uint256 indexed challengedBlockNumber, bytes challengedCommitment, uint8 status) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) ParseChallengeStatusChanged(log types.Log) (*DataAvailabilityChallengeChallengeStatusChanged, error) { + event := new(DataAvailabilityChallengeChallengeStatusChanged) + if err := _DataAvailabilityChallenge.contract.UnpackLog(event, "ChallengeStatusChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DataAvailabilityChallengeInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the DataAvailabilityChallenge contract. +type DataAvailabilityChallengeInitializedIterator struct { + Event *DataAvailabilityChallengeInitialized // 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 *DataAvailabilityChallengeInitializedIterator) 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(DataAvailabilityChallengeInitialized) + 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(DataAvailabilityChallengeInitialized) + 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 *DataAvailabilityChallengeInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DataAvailabilityChallengeInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DataAvailabilityChallengeInitialized represents a Initialized event raised by the DataAvailabilityChallenge contract. +type DataAvailabilityChallengeInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) FilterInitialized(opts *bind.FilterOpts) (*DataAvailabilityChallengeInitializedIterator, error) { + + logs, sub, err := _DataAvailabilityChallenge.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &DataAvailabilityChallengeInitializedIterator{contract: _DataAvailabilityChallenge.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *DataAvailabilityChallengeInitialized) (event.Subscription, error) { + + logs, sub, err := _DataAvailabilityChallenge.contract.WatchLogs(opts, "Initialized") + 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(DataAvailabilityChallengeInitialized) + if err := _DataAvailabilityChallenge.contract.UnpackLog(event, "Initialized", 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 +} + +// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) ParseInitialized(log types.Log) (*DataAvailabilityChallengeInitialized, error) { + event := new(DataAvailabilityChallengeInitialized) + if err := _DataAvailabilityChallenge.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DataAvailabilityChallengeOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the DataAvailabilityChallenge contract. +type DataAvailabilityChallengeOwnershipTransferredIterator struct { + Event *DataAvailabilityChallengeOwnershipTransferred // 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 *DataAvailabilityChallengeOwnershipTransferredIterator) 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(DataAvailabilityChallengeOwnershipTransferred) + 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(DataAvailabilityChallengeOwnershipTransferred) + 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 *DataAvailabilityChallengeOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DataAvailabilityChallengeOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DataAvailabilityChallengeOwnershipTransferred represents a OwnershipTransferred event raised by the DataAvailabilityChallenge contract. +type DataAvailabilityChallengeOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*DataAvailabilityChallengeOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _DataAvailabilityChallenge.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &DataAvailabilityChallengeOwnershipTransferredIterator{contract: _DataAvailabilityChallenge.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *DataAvailabilityChallengeOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _DataAvailabilityChallenge.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + 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(DataAvailabilityChallengeOwnershipTransferred) + if err := _DataAvailabilityChallenge.contract.UnpackLog(event, "OwnershipTransferred", 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 +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) ParseOwnershipTransferred(log types.Log) (*DataAvailabilityChallengeOwnershipTransferred, error) { + event := new(DataAvailabilityChallengeOwnershipTransferred) + if err := _DataAvailabilityChallenge.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DataAvailabilityChallengeRequiredBondSizeChangedIterator is returned from FilterRequiredBondSizeChanged and is used to iterate over the raw logs and unpacked data for RequiredBondSizeChanged events raised by the DataAvailabilityChallenge contract. +type DataAvailabilityChallengeRequiredBondSizeChangedIterator struct { + Event *DataAvailabilityChallengeRequiredBondSizeChanged // 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 *DataAvailabilityChallengeRequiredBondSizeChangedIterator) 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(DataAvailabilityChallengeRequiredBondSizeChanged) + 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(DataAvailabilityChallengeRequiredBondSizeChanged) + 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 *DataAvailabilityChallengeRequiredBondSizeChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DataAvailabilityChallengeRequiredBondSizeChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DataAvailabilityChallengeRequiredBondSizeChanged represents a RequiredBondSizeChanged event raised by the DataAvailabilityChallenge contract. +type DataAvailabilityChallengeRequiredBondSizeChanged struct { + ChallengeWindow *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRequiredBondSizeChanged is a free log retrieval operation binding the contract event 0x4468d695a0389e5f9e8ef0c9aee6d84e74cc0d0e0a28c8413badb54697d1bbae. +// +// Solidity: event RequiredBondSizeChanged(uint256 challengeWindow) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) FilterRequiredBondSizeChanged(opts *bind.FilterOpts) (*DataAvailabilityChallengeRequiredBondSizeChangedIterator, error) { + + logs, sub, err := _DataAvailabilityChallenge.contract.FilterLogs(opts, "RequiredBondSizeChanged") + if err != nil { + return nil, err + } + return &DataAvailabilityChallengeRequiredBondSizeChangedIterator{contract: _DataAvailabilityChallenge.contract, event: "RequiredBondSizeChanged", logs: logs, sub: sub}, nil +} + +// WatchRequiredBondSizeChanged is a free log subscription operation binding the contract event 0x4468d695a0389e5f9e8ef0c9aee6d84e74cc0d0e0a28c8413badb54697d1bbae. +// +// Solidity: event RequiredBondSizeChanged(uint256 challengeWindow) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) WatchRequiredBondSizeChanged(opts *bind.WatchOpts, sink chan<- *DataAvailabilityChallengeRequiredBondSizeChanged) (event.Subscription, error) { + + logs, sub, err := _DataAvailabilityChallenge.contract.WatchLogs(opts, "RequiredBondSizeChanged") + 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(DataAvailabilityChallengeRequiredBondSizeChanged) + if err := _DataAvailabilityChallenge.contract.UnpackLog(event, "RequiredBondSizeChanged", 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 +} + +// ParseRequiredBondSizeChanged is a log parse operation binding the contract event 0x4468d695a0389e5f9e8ef0c9aee6d84e74cc0d0e0a28c8413badb54697d1bbae. +// +// Solidity: event RequiredBondSizeChanged(uint256 challengeWindow) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) ParseRequiredBondSizeChanged(log types.Log) (*DataAvailabilityChallengeRequiredBondSizeChanged, error) { + event := new(DataAvailabilityChallengeRequiredBondSizeChanged) + if err := _DataAvailabilityChallenge.contract.UnpackLog(event, "RequiredBondSizeChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DataAvailabilityChallengeResolverRefundPercentageChangedIterator is returned from FilterResolverRefundPercentageChanged and is used to iterate over the raw logs and unpacked data for ResolverRefundPercentageChanged events raised by the DataAvailabilityChallenge contract. +type DataAvailabilityChallengeResolverRefundPercentageChangedIterator struct { + Event *DataAvailabilityChallengeResolverRefundPercentageChanged // 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 *DataAvailabilityChallengeResolverRefundPercentageChangedIterator) 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(DataAvailabilityChallengeResolverRefundPercentageChanged) + 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(DataAvailabilityChallengeResolverRefundPercentageChanged) + 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 *DataAvailabilityChallengeResolverRefundPercentageChangedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DataAvailabilityChallengeResolverRefundPercentageChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DataAvailabilityChallengeResolverRefundPercentageChanged represents a ResolverRefundPercentageChanged event raised by the DataAvailabilityChallenge contract. +type DataAvailabilityChallengeResolverRefundPercentageChanged struct { + ResolverRefundPercentage *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterResolverRefundPercentageChanged is a free log retrieval operation binding the contract event 0xbbd8605de8f773fedb355c2fecd4b6b2e16a10a44e6676a63b375ac8f693758d. +// +// Solidity: event ResolverRefundPercentageChanged(uint256 resolverRefundPercentage) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) FilterResolverRefundPercentageChanged(opts *bind.FilterOpts) (*DataAvailabilityChallengeResolverRefundPercentageChangedIterator, error) { + + logs, sub, err := _DataAvailabilityChallenge.contract.FilterLogs(opts, "ResolverRefundPercentageChanged") + if err != nil { + return nil, err + } + return &DataAvailabilityChallengeResolverRefundPercentageChangedIterator{contract: _DataAvailabilityChallenge.contract, event: "ResolverRefundPercentageChanged", logs: logs, sub: sub}, nil +} + +// WatchResolverRefundPercentageChanged is a free log subscription operation binding the contract event 0xbbd8605de8f773fedb355c2fecd4b6b2e16a10a44e6676a63b375ac8f693758d. +// +// Solidity: event ResolverRefundPercentageChanged(uint256 resolverRefundPercentage) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) WatchResolverRefundPercentageChanged(opts *bind.WatchOpts, sink chan<- *DataAvailabilityChallengeResolverRefundPercentageChanged) (event.Subscription, error) { + + logs, sub, err := _DataAvailabilityChallenge.contract.WatchLogs(opts, "ResolverRefundPercentageChanged") + 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(DataAvailabilityChallengeResolverRefundPercentageChanged) + if err := _DataAvailabilityChallenge.contract.UnpackLog(event, "ResolverRefundPercentageChanged", 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 +} + +// ParseResolverRefundPercentageChanged is a log parse operation binding the contract event 0xbbd8605de8f773fedb355c2fecd4b6b2e16a10a44e6676a63b375ac8f693758d. +// +// Solidity: event ResolverRefundPercentageChanged(uint256 resolverRefundPercentage) +func (_DataAvailabilityChallenge *DataAvailabilityChallengeFilterer) ParseResolverRefundPercentageChanged(log types.Log) (*DataAvailabilityChallengeResolverRefundPercentageChanged, error) { + event := new(DataAvailabilityChallengeResolverRefundPercentageChanged) + if err := _DataAvailabilityChallenge.contract.UnpackLog(event, "ResolverRefundPercentageChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/op-bindings/bindings/dataavailabilitychallenge_more.go b/op-bindings/bindings/dataavailabilitychallenge_more.go new file mode 100644 index 000000000000..01d69710123b --- /dev/null +++ b/op-bindings/bindings/dataavailabilitychallenge_more.go @@ -0,0 +1,27 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package bindings + +import ( + "encoding/json" + + "github.com/ethereum-optimism/optimism/op-bindings/solc" +) + +const DataAvailabilityChallengeStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/L1/DataAvailabilityChallenge.sol:DataAvailabilityChallenge\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"src/L1/DataAvailabilityChallenge.sol:DataAvailabilityChallenge\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1002,\"contract\":\"src/L1/DataAvailabilityChallenge.sol:DataAvailabilityChallenge\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)50_storage\"},{\"astId\":1003,\"contract\":\"src/L1/DataAvailabilityChallenge.sol:DataAvailabilityChallenge\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":1004,\"contract\":\"src/L1/DataAvailabilityChallenge.sol:DataAvailabilityChallenge\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":1005,\"contract\":\"src/L1/DataAvailabilityChallenge.sol:DataAvailabilityChallenge\",\"label\":\"challengeWindow\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_uint256\"},{\"astId\":1006,\"contract\":\"src/L1/DataAvailabilityChallenge.sol:DataAvailabilityChallenge\",\"label\":\"resolveWindow\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_uint256\"},{\"astId\":1007,\"contract\":\"src/L1/DataAvailabilityChallenge.sol:DataAvailabilityChallenge\",\"label\":\"bondSize\",\"offset\":0,\"slot\":\"103\",\"type\":\"t_uint256\"},{\"astId\":1008,\"contract\":\"src/L1/DataAvailabilityChallenge.sol:DataAvailabilityChallenge\",\"label\":\"resolverRefundPercentage\",\"offset\":0,\"slot\":\"104\",\"type\":\"t_uint256\"},{\"astId\":1009,\"contract\":\"src/L1/DataAvailabilityChallenge.sol:DataAvailabilityChallenge\",\"label\":\"balances\",\"offset\":0,\"slot\":\"105\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":1010,\"contract\":\"src/L1/DataAvailabilityChallenge.sol:DataAvailabilityChallenge\",\"label\":\"challenges\",\"offset\":0,\"slot\":\"106\",\"type\":\"t_mapping(t_uint256,t_mapping(t_bytes_memory_ptr,t_struct(Challenge)1011_storage))\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\",\"base\":\"t_uint256\"},\"t_array(t_uint256)50_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\",\"base\":\"t_uint256\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes_memory_ptr\":{\"encoding\":\"bytes\",\"label\":\"bytes\",\"numberOfBytes\":\"32\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_mapping(t_bytes_memory_ptr,t_struct(Challenge)1011_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes =\u003e struct Challenge)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes_memory_ptr\",\"value\":\"t_struct(Challenge)1011_storage\"},\"t_mapping(t_uint256,t_mapping(t_bytes_memory_ptr,t_struct(Challenge)1011_storage))\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e mapping(bytes =\u003e struct Challenge))\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_mapping(t_bytes_memory_ptr,t_struct(Challenge)1011_storage)\"},\"t_struct(Challenge)1011_storage\":{\"encoding\":\"inplace\",\"label\":\"struct Challenge\",\"numberOfBytes\":\"128\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}" + +var DataAvailabilityChallengeStorageLayout = new(solc.StorageLayout) + +var DataAvailabilityChallengeDeployedBin = "0x6080604052600436106101845760003560e01c8063848afb3d116100d6578063956118521161007f578063d7d04e5411610059578063d7d04e5414610459578063f2fde38b14610479578063f92ad2191461049957600080fd5b80639561185214610427578063a03aafbf1461043e578063d0e30db01461045157600080fd5b80638ecb85e1116100b05780638ecb85e1146103d157806393988233146103e757806393fb19441461040757600080fd5b8063848afb3d1461031d578063861a1412146103865780638da5cb5b1461039c57600080fd5b80634ebaf3ce11610138578063715018a611610112578063715018a6146102bb57806379e8a8b3146102d05780637ae929d9146102fd57600080fd5b80634ebaf3ce1461023957806354fd4d501461024f5780637099c581146102a557600080fd5b806327e235e31161016957806327e235e3146101d7578063336409fd146102045780633ccfd60b1461022457600080fd5b806321cf39ee1461019857806323c30f59146101c157600080fd5b36610193576101916104b9565b005b600080fd5b3480156101a457600080fd5b506101ae60665481565b6040519081526020015b60405180910390f35b3480156101cd57600080fd5b506101ae61410081565b3480156101e357600080fd5b506101ae6101f2366004611539565b60696020526000908152604090205481565b34801561021057600080fd5b5061019161021f366004611554565b610527565b34801561023057600080fd5b50610191610577565b34801561024557600080fd5b506101ae6103e881565b34801561025b57600080fd5b506102986040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101b891906115d8565b3480156102b157600080fd5b506101ae60675481565b3480156102c757600080fd5b50610191610611565b3480156102dc57600080fd5b506102f06102eb366004611634565b610625565b6040516101b891906116ea565b34801561030957600080fd5b506101916103183660046116f8565b6106e8565b34801561032957600080fd5b5061033d610338366004611634565b610884565b6040516101b89190815173ffffffffffffffffffffffffffffffffffffffff16815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561039257600080fd5b506101ae60655481565b3480156103a857600080fd5b5060335460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101b8565b3480156103dd57600080fd5b506101ae60685481565b3480156103f357600080fd5b50610191610402366004611634565b610940565b34801561041357600080fd5b50610191610422366004611772565b610a72565b34801561043357600080fd5b506101ae62011cdd81565b61019161044c366004611634565b610b0f565b6101916104b9565b34801561046557600080fd5b50610191610474366004611554565b610d58565b34801561048557600080fd5b50610191610494366004611539565b610d9b565b3480156104a557600080fd5b506101916104b43660046117b4565b610e52565b33600090815260696020526040812080543492906104d8908490611825565b909155505033600081815260696020908152604091829020548251938452908301527fa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05910160405180910390a1565b61052f61102a565b6064811115610572576040517f16aa4e80000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b606855565b336000818152606960209081526040808320805490849055815194855291840192909252917fa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05910160405180910390a160006105d4335a846110ab565b90508061060d576040517f27fcd9d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b61061961102a565b61062360006110c1565b565b6000838152606a60205260408082209051829190610646908690869061183d565b9081526040805160209281900383018120608082018352805473ffffffffffffffffffffffffffffffffffffffff16808352600182015494830194909452600281015492820192909252600390910154606082015291506106ab5760009150506106e1565b6060810151156106bf5760029150506106e1565b6106cc8160400151611138565b156106db5760019150506106e1565b60039150505b9392505050565b6106f28484610a72565b60016106ff868686610625565b600381111561071057610710611680565b14610747576040517fbeb11d3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006107538585611151565b9050606060ff82166107a15761079e84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061116992505050565b90505b85856040516107b192919061183d565b60405180910390208180519060200120146107fe578086866040517f1a0bbf9f00000000000000000000000000000000000000000000000000000000815260040161056993929190611896565b6000878152606a6020526040808220905161081c908990899061183d565b908152604051908190036020018120436003820155915088907fc5d8c630ba2fdacb1db24c4599df78c7fb8cf97b5aecde34939597f6697bb1ad90610867908a908a906002906118c6565b60405180910390a261087a81853361119c565b5050505050505050565b6108c56040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081525090565b6000848152606a60205260409081902090516108e4908590859061183d565b908152604080519182900360209081018320608084018352805473ffffffffffffffffffffffffffffffffffffffff16845260018101549184019190915260028101549183019190915260030154606082015290509392505050565b600361094d848484610625565b600381111561095e5761095e611680565b14610995576040517f151f07fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152606a602052604080822090516109b3908590859061183d565b90815260408051602092819003830190206001810154815473ffffffffffffffffffffffffffffffffffffffff16600090815260699094529183208054919450919290610a01908490611825565b9091555050600060018201819055815473ffffffffffffffffffffffffffffffffffffffff1680825260696020908152604092839020548351928352908201527fa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05910160405180910390a150505050565b6000610a7e8383611151565b905060ff8116610ad85760218214610ad3576040517ffd9a7e5b000000000000000000000000000000000000000000000000000000008152600060048201526021602482015260448101839052606401610569565b505050565b6040517f81ff071300000000000000000000000000000000000000000000000000000000815260ff82166004820152602401610569565b610b198282610a72565b610b216104b9565b606754336000908152606960205260409020541015610b895733600090815260696020526040908190205460675491517e0155b50000000000000000000000000000000000000000000000000000000081526105699290600401918252602082015260400190565b6000610b96848484610625565b6003811115610ba757610ba7611680565b14610bde576040517f9bb6c64e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610be7836113bc565b610c1d576040517ff9e0d1f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6067543360009081526069602052604081208054909190610c3f9084906118f1565b9250508190555060405180608001604052803373ffffffffffffffffffffffffffffffffffffffff16815260200160675481526020014381526020016000815250606a60008581526020019081526020016000208383604051610ca392919061183d565b9081526040805160209281900383018120845181547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161781559284015160018085019190915591840151600284015560609093015160039092019190915584917fc5d8c630ba2fdacb1db24c4599df78c7fb8cf97b5aecde34939597f6697bb1ad91610d4b91869186916118c6565b60405180910390a2505050565b610d6061102a565b60678190556040518181527f4468d695a0389e5f9e8ef0c9aee6d84e74cc0d0e0a28c8413badb54697d1bbae9060200160405180910390a150565b610da361102a565b73ffffffffffffffffffffffffffffffffffffffff8116610e46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610569565b610e4f816110c1565b50565b600054610100900460ff1615808015610e725750600054600160ff909116105b80610e8c5750303b158015610e8c575060005460ff166001145b610f18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610569565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610f7657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610f7e6113d6565b60658590556066849055610f9183610d58565b610f9a82610527565b610fa3866110c1565b801561100657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610623576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610569565b600080600080600080868989f195945050505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000606654826111489190611825565b43111592915050565b600061115d8284611908565b60f81c90505b92915050565b80516020918201206040805160009381019390935260218084019290925280518084039092018252604190920190915290565b6001830154835473ffffffffffffffffffffffffffffffffffffffff166000486103e86111cb61410088611950565b6111d5919061198d565b6111e29062011cdd611825565b6111ec9190611950565b90508083111561129e5761120081846118f1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526069602052604081208054909190611235908490611825565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000818152606960209081526040918290205482519384529083015291935083917fa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05910160405180910390a15b60006064606854836112b09190611950565b6112ba919061198d565b9050838111156112c75750825b80156113745773ffffffffffffffffffffffffffffffffffffffff851660009081526069602052604081208054839290611302908490611825565b90915550611312905081856118f1565b73ffffffffffffffffffffffffffffffffffffffff8616600081815260696020908152604091829020548251938452908301529195507fa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05910160405180910390a15b83156113a95760405160009085156108fc0290869083818181858288f193505050501580156113a7573d6000803e3d6000fd5b505b6000876001018190555050505050505050565b600081431015801561116357506065546111489083611825565b600054610100900460ff1661146d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610569565b610623600054610100900460ff16611507576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610569565b610623336110c1565b803573ffffffffffffffffffffffffffffffffffffffff8116811461153457600080fd5b919050565b60006020828403121561154b57600080fd5b6106e182611510565b60006020828403121561156657600080fd5b5035919050565b6000815180845260005b8181101561159357602081850181015186830182015201611577565b818111156115a5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006106e1602083018461156d565b60008083601f8401126115fd57600080fd5b50813567ffffffffffffffff81111561161557600080fd5b60208301915083602082850101111561162d57600080fd5b9250929050565b60008060006040848603121561164957600080fd5b83359250602084013567ffffffffffffffff81111561166757600080fd5b611673868287016115eb565b9497909650939450505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106116e6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6020810161116382846116af565b60008060008060006060868803121561171057600080fd5b85359450602086013567ffffffffffffffff8082111561172f57600080fd5b61173b89838a016115eb565b9096509450604088013591508082111561175457600080fd5b50611761888289016115eb565b969995985093965092949392505050565b6000806020838503121561178557600080fd5b823567ffffffffffffffff81111561179c57600080fd5b6117a8858286016115eb565b90969095509350505050565b600080600080600060a086880312156117cc57600080fd5b6117d586611510565b97602087013597506040870135966060810135965060800135945092505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115611838576118386117f6565b500190565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6040815260006118a9604083018661156d565b82810360208401526118bc81858761184d565b9695505050505050565b6040815260006118da60408301858761184d565b90506118e960208301846116af565b949350505050565b600082821015611903576119036117f6565b500390565b7fff0000000000000000000000000000000000000000000000000000000000000081358181169160018510156119485780818660010360031b1b83161692505b505092915050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615611988576119886117f6565b500290565b6000826119c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c634300080f000a" + + +func init() { + if err := json.Unmarshal([]byte(DataAvailabilityChallengeStorageLayoutJSON), DataAvailabilityChallengeStorageLayout); err != nil { + panic(err) + } + + layouts["DataAvailabilityChallenge"] = DataAvailabilityChallengeStorageLayout + deployedBytecodes["DataAvailabilityChallenge"] = DataAvailabilityChallengeDeployedBin + immutableReferences["DataAvailabilityChallenge"] = false +} diff --git a/op-bindings/bindings/delayedvetoable.go b/op-bindings/bindings/delayedvetoable.go index dadfc3e8557f..989bb0278d20 100644 --- a/op-bindings/bindings/delayedvetoable.go +++ b/op-bindings/bindings/delayedvetoable.go @@ -30,8 +30,8 @@ var ( // DelayedVetoableMetaData contains all meta data concerning the DelayedVetoable contract. var DelayedVetoableMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"vetoer_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"initiator_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"target_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"operatingDelay_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"fallback\",\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"delay\",\"inputs\":[],\"outputs\":[{\"name\":\"delay_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initiator\",\"inputs\":[],\"outputs\":[{\"name\":\"initiator_\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"queuedAt\",\"inputs\":[{\"name\":\"callHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"queuedAt_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"target\",\"inputs\":[],\"outputs\":[{\"name\":\"target_\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"vetoer\",\"inputs\":[],\"outputs\":[{\"name\":\"vetoer_\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"DelayActivated\",\"inputs\":[{\"name\":\"delay\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Forwarded\",\"inputs\":[{\"name\":\"callHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initiated\",\"inputs\":[{\"name\":\"callHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Vetoed\",\"inputs\":[{\"name\":\"callHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyDelayed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ForwardingEarly\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TargetUnitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[{\"name\":\"expected\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"actual\",\"type\":\"address\",\"internalType\":\"address\"}]}]", - Bin: "0x61010060405234801561001157600080fd5b506040516108ff3803806108ff8339810160408190526100309161006e565b6001600160a01b0393841660a05291831660c05290911660805260e0526100b9565b80516001600160a01b038116811461006957600080fd5b919050565b6000806000806080858703121561008457600080fd5b61008d85610052565b935061009b60208601610052565b92506100a960408601610052565b6060959095015193969295505050565b60805160a05160c05160e0516107dc610123600039600061023f01526000818161015f01528181610205015281816102cd0152818161045801526105050152600081816101a001528181610384015261059d01526000818161057101526105ff01526107dc6000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063b912de5d11610050578063b912de5d14610111578063d4b8399214610124578063d8bff4401461012c57610072565b806354fd4d501461007c5780635c39fcc1146100ce5780636a42b8f8146100fb575b61007a610134565b005b6100b86040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c591906106a7565b60405180910390f35b6100d66104fb565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100c5565b610103610532565b6040519081526020016100c5565b61010361011f36600461071a565b610540565b6100d6610567565b6100d6610593565b361580156101425750600054155b15610298573373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015906101c357503373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614155b1561023d576040517f295a81c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660048201523360248201526044015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000060008190556040519081527febf28bfb587e28dfffd9173cf71c32ba5d3f0544a0117b5539c9b274a5bba2a89060200160405180910390a1565b600080366040516102aa929190610733565b60405190819003902090503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103065750600081815260016020526040902054155b1561036c5760005460000361031e5761031e816105bf565b6000818152600160205260408082204290555182917f87a332a414acbc7da074543639ce7ae02ff1ea72e88379da9f261b080beb5a139161036191903690610743565b60405180910390a250565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103be575060008181526001602052604090205415155b15610406576000818152600160205260408082208290555182917fbede6852c1d97d93ff557f676de76670cd0dec861e7fe8beb13aa0ba2b0ab0409161036191903690610743565b600081815260016020526040812054900361048b576040517f295a81c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152336024820152604401610234565b60008054828252600160205260409091205442916104a891610790565b10156104e0576040517f43dc986d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600160205260408120556104f8816105bf565b50565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b61052f610134565b90565b600033610527575060005490565b60003361055a575060009081526001602052604090205490565b610562610134565b919050565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b807f4c109d85bcd0bb5c735b4be850953d652afe4cd9aa2e0b1426a65a4dcb2e12296000366040516105f2929190610743565b60405180910390a26000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16600036604051610645929190610733565b6000604051808303816000865af19150503d8060008114610682576040519150601f19603f3d011682016040523d82523d6000602084013e610687565b606091505b50909250905081151560010361069f57805160208201f35b805160208201fd5b600060208083528351808285015260005b818110156106d4578581018301518582016040015282016106b8565b818111156106e6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561072c57600080fd5b5035919050565b8183823760009101908152919050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b600082198211156107ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea164736f6c634300080f000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"vetoer_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"initiator_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"target_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"operatingDelay_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"fallback\",\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"delay\",\"inputs\":[],\"outputs\":[{\"name\":\"delay_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initiator\",\"inputs\":[],\"outputs\":[{\"name\":\"initiator_\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"queuedAt\",\"inputs\":[{\"name\":\"callHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"queuedAt_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"target\",\"inputs\":[],\"outputs\":[{\"name\":\"target_\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"vetoer\",\"inputs\":[],\"outputs\":[{\"name\":\"vetoer_\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"DelayActivated\",\"inputs\":[{\"name\":\"delay\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Forwarded\",\"inputs\":[{\"name\":\"callHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initiated\",\"inputs\":[{\"name\":\"callHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Vetoed\",\"inputs\":[{\"name\":\"callHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"ForwardingEarly\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[{\"name\":\"expected\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"actual\",\"type\":\"address\",\"internalType\":\"address\"}]}]", + Bin: "0x61010060405234801561001157600080fd5b506040516108ff3803806108ff8339810160408190526100309161006e565b6001600160a01b0393841660a05291831660c05290911660805260e0526100b9565b80516001600160a01b038116811461006957600080fd5b919050565b6000806000806080858703121561008457600080fd5b61008d85610052565b935061009b60208601610052565b92506100a960408601610052565b6060959095015193969295505050565b60805160a05160c05160e0516107dc610123600039600061023f01526000818161015f01528181610205015281816102cd0152818161045801526105050152600081816101a001528181610384015261059d01526000818161057101526105ff01526107dc6000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063b912de5d11610050578063b912de5d14610111578063d4b8399214610124578063d8bff4401461012c57610072565b806354fd4d501461007c5780635c39fcc1146100ce5780636a42b8f8146100fb575b61007a610134565b005b6100b86040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c591906106a7565b60405180910390f35b6100d66104fb565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100c5565b610103610532565b6040519081526020016100c5565b61010361011f36600461071a565b610540565b6100d6610567565b6100d6610593565b361580156101425750600054155b15610298573373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015906101c357503373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614155b1561023d576040517f295a81c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660048201523360248201526044015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000060008190556040519081527febf28bfb587e28dfffd9173cf71c32ba5d3f0544a0117b5539c9b274a5bba2a89060200160405180910390a1565b600080366040516102aa929190610733565b60405190819003902090503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103065750600081815260016020526040902054155b1561036c5760005460000361031e5761031e816105bf565b6000818152600160205260408082204290555182917f87a332a414acbc7da074543639ce7ae02ff1ea72e88379da9f261b080beb5a139161036191903690610743565b60405180910390a250565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103be575060008181526001602052604090205415155b15610406576000818152600160205260408082208290555182917fbede6852c1d97d93ff557f676de76670cd0dec861e7fe8beb13aa0ba2b0ab0409161036191903690610743565b600081815260016020526040812054900361048b576040517f295a81c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152336024820152604401610234565b60008054828252600160205260409091205442916104a891610790565b11156104e0576040517f43dc986d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600160205260408120556104f8816105bf565b50565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b61052f610134565b90565b600033610527575060005490565b60003361055a575060009081526001602052604090205490565b610562610134565b919050565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b807f4c109d85bcd0bb5c735b4be850953d652afe4cd9aa2e0b1426a65a4dcb2e12296000366040516105f2929190610743565b60405180910390a26000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16600036604051610645929190610733565b6000604051808303816000865af19150503d8060008114610682576040519150601f19603f3d011682016040523d82523d6000602084013e610687565b606091505b50909250905081151560010361069f57805160208201f35b805160208201fd5b600060208083528351808285015260005b818110156106d4578581018301518582016040015282016106b8565b818111156106e6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561072c57600080fd5b5035919050565b8183823760009101908152919050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b600082198211156107ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea164736f6c634300080f000a", } // DelayedVetoableABI is the input ABI used to generate the binding from. diff --git a/op-bindings/bindings/delayedvetoable_more.go b/op-bindings/bindings/delayedvetoable_more.go index fcfcd2976fe4..447987519301 100644 --- a/op-bindings/bindings/delayedvetoable_more.go +++ b/op-bindings/bindings/delayedvetoable_more.go @@ -13,7 +13,7 @@ const DelayedVetoableStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contra var DelayedVetoableStorageLayout = new(solc.StorageLayout) -var DelayedVetoableDeployedBin = "0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063b912de5d11610050578063b912de5d14610111578063d4b8399214610124578063d8bff4401461012c57610072565b806354fd4d501461007c5780635c39fcc1146100ce5780636a42b8f8146100fb575b61007a610134565b005b6100b86040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c591906106a7565b60405180910390f35b6100d66104fb565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100c5565b610103610532565b6040519081526020016100c5565b61010361011f36600461071a565b610540565b6100d6610567565b6100d6610593565b361580156101425750600054155b15610298573373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015906101c357503373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614155b1561023d576040517f295a81c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660048201523360248201526044015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000060008190556040519081527febf28bfb587e28dfffd9173cf71c32ba5d3f0544a0117b5539c9b274a5bba2a89060200160405180910390a1565b600080366040516102aa929190610733565b60405190819003902090503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103065750600081815260016020526040902054155b1561036c5760005460000361031e5761031e816105bf565b6000818152600160205260408082204290555182917f87a332a414acbc7da074543639ce7ae02ff1ea72e88379da9f261b080beb5a139161036191903690610743565b60405180910390a250565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103be575060008181526001602052604090205415155b15610406576000818152600160205260408082208290555182917fbede6852c1d97d93ff557f676de76670cd0dec861e7fe8beb13aa0ba2b0ab0409161036191903690610743565b600081815260016020526040812054900361048b576040517f295a81c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152336024820152604401610234565b60008054828252600160205260409091205442916104a891610790565b10156104e0576040517f43dc986d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600160205260408120556104f8816105bf565b50565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b61052f610134565b90565b600033610527575060005490565b60003361055a575060009081526001602052604090205490565b610562610134565b919050565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b807f4c109d85bcd0bb5c735b4be850953d652afe4cd9aa2e0b1426a65a4dcb2e12296000366040516105f2929190610743565b60405180910390a26000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16600036604051610645929190610733565b6000604051808303816000865af19150503d8060008114610682576040519150601f19603f3d011682016040523d82523d6000602084013e610687565b606091505b50909250905081151560010361069f57805160208201f35b805160208201fd5b600060208083528351808285015260005b818110156106d4578581018301518582016040015282016106b8565b818111156106e6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561072c57600080fd5b5035919050565b8183823760009101908152919050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b600082198211156107ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea164736f6c634300080f000a" +var DelayedVetoableDeployedBin = "0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063b912de5d11610050578063b912de5d14610111578063d4b8399214610124578063d8bff4401461012c57610072565b806354fd4d501461007c5780635c39fcc1146100ce5780636a42b8f8146100fb575b61007a610134565b005b6100b86040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c591906106a7565b60405180910390f35b6100d66104fb565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100c5565b610103610532565b6040519081526020016100c5565b61010361011f36600461071a565b610540565b6100d6610567565b6100d6610593565b361580156101425750600054155b15610298573373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015906101c357503373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614155b1561023d576040517f295a81c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660048201523360248201526044015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000060008190556040519081527febf28bfb587e28dfffd9173cf71c32ba5d3f0544a0117b5539c9b274a5bba2a89060200160405180910390a1565b600080366040516102aa929190610733565b60405190819003902090503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103065750600081815260016020526040902054155b1561036c5760005460000361031e5761031e816105bf565b6000818152600160205260408082204290555182917f87a332a414acbc7da074543639ce7ae02ff1ea72e88379da9f261b080beb5a139161036191903690610743565b60405180910390a250565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103be575060008181526001602052604090205415155b15610406576000818152600160205260408082208290555182917fbede6852c1d97d93ff557f676de76670cd0dec861e7fe8beb13aa0ba2b0ab0409161036191903690610743565b600081815260016020526040812054900361048b576040517f295a81c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152336024820152604401610234565b60008054828252600160205260409091205442916104a891610790565b11156104e0576040517f43dc986d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600160205260408120556104f8816105bf565b50565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b61052f610134565b90565b600033610527575060005490565b60003361055a575060009081526001602052604090205490565b610562610134565b919050565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b807f4c109d85bcd0bb5c735b4be850953d652afe4cd9aa2e0b1426a65a4dcb2e12296000366040516105f2929190610743565b60405180910390a26000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16600036604051610645929190610733565b6000604051808303816000865af19150503d8060008114610682576040519150601f19603f3d011682016040523d82523d6000602084013e610687565b606091505b50909250905081151560010361069f57805160208201f35b805160208201fd5b600060208083528351808285015260005b818110156106d4578581018301518582016040015282016106b8565b818111156106e6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561072c57600080fd5b5035919050565b8183823760009101908152919050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b600082198211156107ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea164736f6c634300080f000a" func init() { diff --git a/op-bindings/bindings/delayedweth.go b/op-bindings/bindings/delayedweth.go new file mode 100644 index 000000000000..d4dc77699835 --- /dev/null +++ b/op-bindings/bindings/delayedweth.go @@ -0,0 +1,1860 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package bindings + +import ( + "errors" + "math/big" + "strings" + + ethereum "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 +) + +// DelayedWETHMetaData contains all meta data concerning the DelayedWETH contract. +var DelayedWETHMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_delay\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"guy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"config\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractSuperchainConfig\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"delay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"deposit\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"hold\",\"inputs\":[{\"name\":\"_guy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_config\",\"type\":\"address\",\"internalType\":\"contractSuperchainConfig\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"recover\",\"inputs\":[{\"name\":\"_wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"dst\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"dst\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"unlock\",\"inputs\":[{\"name\":\"_guy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"withdraw\",\"inputs\":[{\"name\":\"_wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdraw\",\"inputs\":[{\"name\":\"_guy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawals\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"timestamp\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"guy\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Deposit\",\"inputs\":[{\"name\":\"dst\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"dst\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Unwrap\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Withdrawal\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false}]", + Bin: "0x60a06040523480156200001157600080fd5b50604051620018b9380380620018b98339810160408190526200003491620002d7565b6080819052620000466000806200004d565b50620002f1565b600054610100900460ff16158080156200006e5750600054600160ff909116105b806200009e57506200008b30620001a760201b6200108e1760201c565b1580156200009e575060005460ff166001145b620001075760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200012b576000805461ff0019166101001790555b62000135620001b6565b62000140836200021e565b606880546001600160a01b0319166001600160a01b0384161790558015620001a2576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b600054610100900460ff16620002125760405162461bcd60e51b815260206004820152602b60248201526000805160206200189983398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000fe565b6200021c62000270565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620002cc5760405162461bcd60e51b815260206004820152602b60248201526000805160206200189983398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000fe565b6200021c336200021e565b600060208284031215620002ea57600080fd5b5051919050565b60805161158562000314600039600081816103430152610faf01526115856000f3fe6080604052600436106101845760003560e01c8063715018a6116100d6578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e1461052b578063f2fde38b14610563578063f3fef3a31461058357600080fd5b8063a9059cbb146104af578063cd47bde1146104cf578063d0e30db01461052357600080fd5b80638da5cb5b116100b05780638da5cb5b1461041b57806395d89b4114610446578063977a5ec51461048f57600080fd5b8063715018a61461039457806379502c55146103a95780637eee288d146103fb57600080fd5b80632e1a7d4d1161013857806354fd4d501161011257806354fd4d50146102eb5780636a42b8f81461033457806370a082311461036757600080fd5b80632e1a7d4d14610284578063313ce567146102a4578063485cc955146102cb57600080fd5b80630ca35682116101695780630ca356821461022757806318160ddd1461024757806323b872dd1461026457600080fd5b806306fdde0314610198578063095ea7b3146101f757600080fd5b36610193576101916105a3565b005b600080fd5b3480156101a457600080fd5b506101e16040518060400160405280600d81526020017f577261707065642045746865720000000000000000000000000000000000000081525081565b6040516101ee9190611387565b60405180910390f35b34801561020357600080fd5b5061021761021236600461141c565b6105fe565b60405190151581526020016101ee565b34801561023357600080fd5b50610191610242366004611448565b610677565b34801561025357600080fd5b50475b6040519081526020016101ee565b34801561027057600080fd5b5061021761027f366004611461565b610743565b34801561029057600080fd5b5061019161029f366004611448565b61095a565b3480156102b057600080fd5b506102b9601281565b60405160ff90911681526020016101ee565b3480156102d757600080fd5b506101916102e63660046114a2565b610967565b3480156102f757600080fd5b506101e16040518060400160405280600581526020017f302e322e3000000000000000000000000000000000000000000000000000000081525081565b34801561034057600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610256565b34801561037357600080fd5b506102566103823660046114db565b60656020526000908152604090205481565b3480156103a057600080fd5b50610191610b43565b3480156103b557600080fd5b506068546103d69073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ee565b34801561040757600080fd5b5061019161041636600461141c565b610b57565b34801561042757600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166103d6565b34801561045257600080fd5b506101e16040518060400160405280600481526020017f574554480000000000000000000000000000000000000000000000000000000081525081565b34801561049b57600080fd5b506101916104aa36600461141c565b610bab565b3480156104bb57600080fd5b506102176104ca36600461141c565b610c98565b3480156104db57600080fd5b5061050e6104ea3660046114a2565b60676020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101ee565b6101916105a3565b34801561053757600080fd5b506102566105463660046114a2565b606660209081526000928352604080842090915290825290205481565b34801561056f57600080fd5b5061019161057e3660046114db565b610cac565b34801561058f57600080fd5b5061019161059e36600461141c565b610d60565b33600090815260656020526040812080543492906105c2908490611527565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b33600081815260666020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106669086815260200190565b60405180910390a350600192915050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064015b60405180910390fd5b600047821061070c574761070e565b815b604051909150339082156108fc029083906000818181858888f1935050505015801561073e573d6000803e3d6000fd5b505050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526065602052604081205482111561077557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841633148015906107eb575073ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156108735773ffffffffffffffffffffffffffffffffffffffff8416600090815260666020908152604080832033845290915290205482111561082d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091528120805484929061086d90849061153f565b90915550505b73ffffffffffffffffffffffffffffffffffffffff8416600090815260656020526040812080548492906108a890849061153f565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600090815260656020526040812080548492906108e2908490611527565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161094891815260200190565b60405180910390a35060019392505050565b6109643382610d60565b50565b600054610100900460ff16158080156109875750600054600160ff909116105b806109a15750303b1580156109a1575060005460ff166001145b610a2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106f4565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a936110aa565b610a9c83611149565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055801561073e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b610b4b6111c0565b610b556000611149565b565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120426001820155805490918391839190610ba1908490611527565b9091555050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064016106f4565b73ffffffffffffffffffffffffffffffffffffffff821660008181526066602090815260408083203380855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050565b6000610ca5338484610743565b9392505050565b610cb46111c0565b73ffffffffffffffffffffffffffffffffffffffff8116610d57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106f4565b61096481611149565b606860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df19190611556565b15610e58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44656c61796564574554483a20636f6e7472616374206973207061757365640060448201526064016106f4565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290208054821115610f19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f44656c61796564574554483a20696e73756666696369656e7420756e6c6f636b60448201527f6564207769746864726177616c0000000000000000000000000000000000000060648201526084016106f4565b6000816001015411610fac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f44656c61796564574554483a207769746864726177616c206e6f7420756e6c6f60448201527f636b65640000000000000000000000000000000000000000000000000000000060648201526084016106f4565b427f00000000000000000000000000000000000000000000000000000000000000008260010154610fdd9190611527565b111561106b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f44656c61796564574554483a207769746864726177616c2064656c6179206e6f60448201527f74206d657400000000000000000000000000000000000000000000000000000060648201526084016106f4565b8181600001600082825461107f919061153f565b9091555061073e905082611241565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff16611141576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106f4565b610b556112e7565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610b55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106f4565b3360009081526065602052604090205481111561125d57600080fd5b336000908152606560205260408120805483929061127c90849061153f565b9091555050604051339082156108fc029083906000818181858888f193505050501580156112ae573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600054610100900460ff1661137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106f4565b610b5533611149565b600060208083528351808285015260005b818110156113b457858101830151858201604001528201611398565b818111156113c6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461096457600080fd5b6000806040838503121561142f57600080fd5b823561143a816113fa565b946020939093013593505050565b60006020828403121561145a57600080fd5b5035919050565b60008060006060848603121561147657600080fd5b8335611481816113fa565b92506020840135611491816113fa565b929592945050506040919091013590565b600080604083850312156114b557600080fd5b82356114c0816113fa565b915060208301356114d0816113fa565b809150509250929050565b6000602082840312156114ed57600080fd5b8135610ca5816113fa565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561153a5761153a6114f8565b500190565b600082821015611551576115516114f8565b500390565b60006020828403121561156857600080fd5b81518015158114610ca557600080fdfea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", +} + +// DelayedWETHABI is the input ABI used to generate the binding from. +// Deprecated: Use DelayedWETHMetaData.ABI instead. +var DelayedWETHABI = DelayedWETHMetaData.ABI + +// DelayedWETHBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use DelayedWETHMetaData.Bin instead. +var DelayedWETHBin = DelayedWETHMetaData.Bin + +// DeployDelayedWETH deploys a new Ethereum contract, binding an instance of DelayedWETH to it. +func DeployDelayedWETH(auth *bind.TransactOpts, backend bind.ContractBackend, _delay *big.Int) (common.Address, *types.Transaction, *DelayedWETH, error) { + parsed, err := DelayedWETHMetaData.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(DelayedWETHBin), backend, _delay) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &DelayedWETH{DelayedWETHCaller: DelayedWETHCaller{contract: contract}, DelayedWETHTransactor: DelayedWETHTransactor{contract: contract}, DelayedWETHFilterer: DelayedWETHFilterer{contract: contract}}, nil +} + +// DelayedWETH is an auto generated Go binding around an Ethereum contract. +type DelayedWETH struct { + DelayedWETHCaller // Read-only binding to the contract + DelayedWETHTransactor // Write-only binding to the contract + DelayedWETHFilterer // Log filterer for contract events +} + +// DelayedWETHCaller is an auto generated read-only Go binding around an Ethereum contract. +type DelayedWETHCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DelayedWETHTransactor is an auto generated write-only Go binding around an Ethereum contract. +type DelayedWETHTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DelayedWETHFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type DelayedWETHFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// DelayedWETHSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type DelayedWETHSession struct { + Contract *DelayedWETH // 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 +} + +// DelayedWETHCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type DelayedWETHCallerSession struct { + Contract *DelayedWETHCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// DelayedWETHTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type DelayedWETHTransactorSession struct { + Contract *DelayedWETHTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// DelayedWETHRaw is an auto generated low-level Go binding around an Ethereum contract. +type DelayedWETHRaw struct { + Contract *DelayedWETH // Generic contract binding to access the raw methods on +} + +// DelayedWETHCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type DelayedWETHCallerRaw struct { + Contract *DelayedWETHCaller // Generic read-only contract binding to access the raw methods on +} + +// DelayedWETHTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type DelayedWETHTransactorRaw struct { + Contract *DelayedWETHTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewDelayedWETH creates a new instance of DelayedWETH, bound to a specific deployed contract. +func NewDelayedWETH(address common.Address, backend bind.ContractBackend) (*DelayedWETH, error) { + contract, err := bindDelayedWETH(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &DelayedWETH{DelayedWETHCaller: DelayedWETHCaller{contract: contract}, DelayedWETHTransactor: DelayedWETHTransactor{contract: contract}, DelayedWETHFilterer: DelayedWETHFilterer{contract: contract}}, nil +} + +// NewDelayedWETHCaller creates a new read-only instance of DelayedWETH, bound to a specific deployed contract. +func NewDelayedWETHCaller(address common.Address, caller bind.ContractCaller) (*DelayedWETHCaller, error) { + contract, err := bindDelayedWETH(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &DelayedWETHCaller{contract: contract}, nil +} + +// NewDelayedWETHTransactor creates a new write-only instance of DelayedWETH, bound to a specific deployed contract. +func NewDelayedWETHTransactor(address common.Address, transactor bind.ContractTransactor) (*DelayedWETHTransactor, error) { + contract, err := bindDelayedWETH(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &DelayedWETHTransactor{contract: contract}, nil +} + +// NewDelayedWETHFilterer creates a new log filterer instance of DelayedWETH, bound to a specific deployed contract. +func NewDelayedWETHFilterer(address common.Address, filterer bind.ContractFilterer) (*DelayedWETHFilterer, error) { + contract, err := bindDelayedWETH(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &DelayedWETHFilterer{contract: contract}, nil +} + +// bindDelayedWETH binds a generic wrapper to an already deployed contract. +func bindDelayedWETH(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(DelayedWETHABI)) + 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 (_DelayedWETH *DelayedWETHRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _DelayedWETH.Contract.DelayedWETHCaller.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 (_DelayedWETH *DelayedWETHRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DelayedWETH.Contract.DelayedWETHTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_DelayedWETH *DelayedWETHRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _DelayedWETH.Contract.DelayedWETHTransactor.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 (_DelayedWETH *DelayedWETHCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _DelayedWETH.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 (_DelayedWETH *DelayedWETHTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DelayedWETH.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_DelayedWETH *DelayedWETHTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _DelayedWETH.Contract.contract.Transact(opts, method, params...) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address , address ) view returns(uint256) +func (_DelayedWETH *DelayedWETHCaller) Allowance(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error) { + var out []interface{} + err := _DelayedWETH.contract.Call(opts, &out, "allowance", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address , address ) view returns(uint256) +func (_DelayedWETH *DelayedWETHSession) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _DelayedWETH.Contract.Allowance(&_DelayedWETH.CallOpts, arg0, arg1) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address , address ) view returns(uint256) +func (_DelayedWETH *DelayedWETHCallerSession) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _DelayedWETH.Contract.Allowance(&_DelayedWETH.CallOpts, arg0, arg1) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address ) view returns(uint256) +func (_DelayedWETH *DelayedWETHCaller) BalanceOf(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _DelayedWETH.contract.Call(opts, &out, "balanceOf", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address ) view returns(uint256) +func (_DelayedWETH *DelayedWETHSession) BalanceOf(arg0 common.Address) (*big.Int, error) { + return _DelayedWETH.Contract.BalanceOf(&_DelayedWETH.CallOpts, arg0) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address ) view returns(uint256) +func (_DelayedWETH *DelayedWETHCallerSession) BalanceOf(arg0 common.Address) (*big.Int, error) { + return _DelayedWETH.Contract.BalanceOf(&_DelayedWETH.CallOpts, arg0) +} + +// Config is a free data retrieval call binding the contract method 0x79502c55. +// +// Solidity: function config() view returns(address) +func (_DelayedWETH *DelayedWETHCaller) Config(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _DelayedWETH.contract.Call(opts, &out, "config") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Config is a free data retrieval call binding the contract method 0x79502c55. +// +// Solidity: function config() view returns(address) +func (_DelayedWETH *DelayedWETHSession) Config() (common.Address, error) { + return _DelayedWETH.Contract.Config(&_DelayedWETH.CallOpts) +} + +// Config is a free data retrieval call binding the contract method 0x79502c55. +// +// Solidity: function config() view returns(address) +func (_DelayedWETH *DelayedWETHCallerSession) Config() (common.Address, error) { + return _DelayedWETH.Contract.Config(&_DelayedWETH.CallOpts) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_DelayedWETH *DelayedWETHCaller) Decimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _DelayedWETH.contract.Call(opts, &out, "decimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_DelayedWETH *DelayedWETHSession) Decimals() (uint8, error) { + return _DelayedWETH.Contract.Decimals(&_DelayedWETH.CallOpts) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_DelayedWETH *DelayedWETHCallerSession) Decimals() (uint8, error) { + return _DelayedWETH.Contract.Decimals(&_DelayedWETH.CallOpts) +} + +// Delay is a free data retrieval call binding the contract method 0x6a42b8f8. +// +// Solidity: function delay() view returns(uint256) +func (_DelayedWETH *DelayedWETHCaller) Delay(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _DelayedWETH.contract.Call(opts, &out, "delay") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Delay is a free data retrieval call binding the contract method 0x6a42b8f8. +// +// Solidity: function delay() view returns(uint256) +func (_DelayedWETH *DelayedWETHSession) Delay() (*big.Int, error) { + return _DelayedWETH.Contract.Delay(&_DelayedWETH.CallOpts) +} + +// Delay is a free data retrieval call binding the contract method 0x6a42b8f8. +// +// Solidity: function delay() view returns(uint256) +func (_DelayedWETH *DelayedWETHCallerSession) Delay() (*big.Int, error) { + return _DelayedWETH.Contract.Delay(&_DelayedWETH.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_DelayedWETH *DelayedWETHCaller) Name(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _DelayedWETH.contract.Call(opts, &out, "name") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_DelayedWETH *DelayedWETHSession) Name() (string, error) { + return _DelayedWETH.Contract.Name(&_DelayedWETH.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_DelayedWETH *DelayedWETHCallerSession) Name() (string, error) { + return _DelayedWETH.Contract.Name(&_DelayedWETH.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_DelayedWETH *DelayedWETHCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _DelayedWETH.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_DelayedWETH *DelayedWETHSession) Owner() (common.Address, error) { + return _DelayedWETH.Contract.Owner(&_DelayedWETH.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_DelayedWETH *DelayedWETHCallerSession) Owner() (common.Address, error) { + return _DelayedWETH.Contract.Owner(&_DelayedWETH.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_DelayedWETH *DelayedWETHCaller) Symbol(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _DelayedWETH.contract.Call(opts, &out, "symbol") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_DelayedWETH *DelayedWETHSession) Symbol() (string, error) { + return _DelayedWETH.Contract.Symbol(&_DelayedWETH.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_DelayedWETH *DelayedWETHCallerSession) Symbol() (string, error) { + return _DelayedWETH.Contract.Symbol(&_DelayedWETH.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_DelayedWETH *DelayedWETHCaller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _DelayedWETH.contract.Call(opts, &out, "totalSupply") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_DelayedWETH *DelayedWETHSession) TotalSupply() (*big.Int, error) { + return _DelayedWETH.Contract.TotalSupply(&_DelayedWETH.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_DelayedWETH *DelayedWETHCallerSession) TotalSupply() (*big.Int, error) { + return _DelayedWETH.Contract.TotalSupply(&_DelayedWETH.CallOpts) +} + +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_DelayedWETH *DelayedWETHCaller) Version(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _DelayedWETH.contract.Call(opts, &out, "version") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_DelayedWETH *DelayedWETHSession) Version() (string, error) { + return _DelayedWETH.Contract.Version(&_DelayedWETH.CallOpts) +} + +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_DelayedWETH *DelayedWETHCallerSession) Version() (string, error) { + return _DelayedWETH.Contract.Version(&_DelayedWETH.CallOpts) +} + +// Withdrawals is a free data retrieval call binding the contract method 0xcd47bde1. +// +// Solidity: function withdrawals(address , address ) view returns(uint256 amount, uint256 timestamp) +func (_DelayedWETH *DelayedWETHCaller) Withdrawals(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (struct { + Amount *big.Int + Timestamp *big.Int +}, error) { + var out []interface{} + err := _DelayedWETH.contract.Call(opts, &out, "withdrawals", arg0, arg1) + + outstruct := new(struct { + Amount *big.Int + Timestamp *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.Amount = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.Timestamp = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// Withdrawals is a free data retrieval call binding the contract method 0xcd47bde1. +// +// Solidity: function withdrawals(address , address ) view returns(uint256 amount, uint256 timestamp) +func (_DelayedWETH *DelayedWETHSession) Withdrawals(arg0 common.Address, arg1 common.Address) (struct { + Amount *big.Int + Timestamp *big.Int +}, error) { + return _DelayedWETH.Contract.Withdrawals(&_DelayedWETH.CallOpts, arg0, arg1) +} + +// Withdrawals is a free data retrieval call binding the contract method 0xcd47bde1. +// +// Solidity: function withdrawals(address , address ) view returns(uint256 amount, uint256 timestamp) +func (_DelayedWETH *DelayedWETHCallerSession) Withdrawals(arg0 common.Address, arg1 common.Address) (struct { + Amount *big.Int + Timestamp *big.Int +}, error) { + return _DelayedWETH.Contract.Withdrawals(&_DelayedWETH.CallOpts, arg0, arg1) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address guy, uint256 wad) returns(bool) +func (_DelayedWETH *DelayedWETHTransactor) Approve(opts *bind.TransactOpts, guy common.Address, wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.contract.Transact(opts, "approve", guy, wad) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address guy, uint256 wad) returns(bool) +func (_DelayedWETH *DelayedWETHSession) Approve(guy common.Address, wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Approve(&_DelayedWETH.TransactOpts, guy, wad) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address guy, uint256 wad) returns(bool) +func (_DelayedWETH *DelayedWETHTransactorSession) Approve(guy common.Address, wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Approve(&_DelayedWETH.TransactOpts, guy, wad) +} + +// Deposit is a paid mutator transaction binding the contract method 0xd0e30db0. +// +// Solidity: function deposit() payable returns() +func (_DelayedWETH *DelayedWETHTransactor) Deposit(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DelayedWETH.contract.Transact(opts, "deposit") +} + +// Deposit is a paid mutator transaction binding the contract method 0xd0e30db0. +// +// Solidity: function deposit() payable returns() +func (_DelayedWETH *DelayedWETHSession) Deposit() (*types.Transaction, error) { + return _DelayedWETH.Contract.Deposit(&_DelayedWETH.TransactOpts) +} + +// Deposit is a paid mutator transaction binding the contract method 0xd0e30db0. +// +// Solidity: function deposit() payable returns() +func (_DelayedWETH *DelayedWETHTransactorSession) Deposit() (*types.Transaction, error) { + return _DelayedWETH.Contract.Deposit(&_DelayedWETH.TransactOpts) +} + +// Hold is a paid mutator transaction binding the contract method 0x977a5ec5. +// +// Solidity: function hold(address _guy, uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHTransactor) Hold(opts *bind.TransactOpts, _guy common.Address, _wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.contract.Transact(opts, "hold", _guy, _wad) +} + +// Hold is a paid mutator transaction binding the contract method 0x977a5ec5. +// +// Solidity: function hold(address _guy, uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHSession) Hold(_guy common.Address, _wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Hold(&_DelayedWETH.TransactOpts, _guy, _wad) +} + +// Hold is a paid mutator transaction binding the contract method 0x977a5ec5. +// +// Solidity: function hold(address _guy, uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHTransactorSession) Hold(_guy common.Address, _wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Hold(&_DelayedWETH.TransactOpts, _guy, _wad) +} + +// Initialize is a paid mutator transaction binding the contract method 0x485cc955. +// +// Solidity: function initialize(address _owner, address _config) returns() +func (_DelayedWETH *DelayedWETHTransactor) Initialize(opts *bind.TransactOpts, _owner common.Address, _config common.Address) (*types.Transaction, error) { + return _DelayedWETH.contract.Transact(opts, "initialize", _owner, _config) +} + +// Initialize is a paid mutator transaction binding the contract method 0x485cc955. +// +// Solidity: function initialize(address _owner, address _config) returns() +func (_DelayedWETH *DelayedWETHSession) Initialize(_owner common.Address, _config common.Address) (*types.Transaction, error) { + return _DelayedWETH.Contract.Initialize(&_DelayedWETH.TransactOpts, _owner, _config) +} + +// Initialize is a paid mutator transaction binding the contract method 0x485cc955. +// +// Solidity: function initialize(address _owner, address _config) returns() +func (_DelayedWETH *DelayedWETHTransactorSession) Initialize(_owner common.Address, _config common.Address) (*types.Transaction, error) { + return _DelayedWETH.Contract.Initialize(&_DelayedWETH.TransactOpts, _owner, _config) +} + +// Recover is a paid mutator transaction binding the contract method 0x0ca35682. +// +// Solidity: function recover(uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHTransactor) Recover(opts *bind.TransactOpts, _wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.contract.Transact(opts, "recover", _wad) +} + +// Recover is a paid mutator transaction binding the contract method 0x0ca35682. +// +// Solidity: function recover(uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHSession) Recover(_wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Recover(&_DelayedWETH.TransactOpts, _wad) +} + +// Recover is a paid mutator transaction binding the contract method 0x0ca35682. +// +// Solidity: function recover(uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHTransactorSession) Recover(_wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Recover(&_DelayedWETH.TransactOpts, _wad) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_DelayedWETH *DelayedWETHTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DelayedWETH.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_DelayedWETH *DelayedWETHSession) RenounceOwnership() (*types.Transaction, error) { + return _DelayedWETH.Contract.RenounceOwnership(&_DelayedWETH.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_DelayedWETH *DelayedWETHTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _DelayedWETH.Contract.RenounceOwnership(&_DelayedWETH.TransactOpts) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address dst, uint256 wad) returns(bool) +func (_DelayedWETH *DelayedWETHTransactor) Transfer(opts *bind.TransactOpts, dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.contract.Transact(opts, "transfer", dst, wad) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address dst, uint256 wad) returns(bool) +func (_DelayedWETH *DelayedWETHSession) Transfer(dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Transfer(&_DelayedWETH.TransactOpts, dst, wad) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address dst, uint256 wad) returns(bool) +func (_DelayedWETH *DelayedWETHTransactorSession) Transfer(dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Transfer(&_DelayedWETH.TransactOpts, dst, wad) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address src, address dst, uint256 wad) returns(bool) +func (_DelayedWETH *DelayedWETHTransactor) TransferFrom(opts *bind.TransactOpts, src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.contract.Transact(opts, "transferFrom", src, dst, wad) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address src, address dst, uint256 wad) returns(bool) +func (_DelayedWETH *DelayedWETHSession) TransferFrom(src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.TransferFrom(&_DelayedWETH.TransactOpts, src, dst, wad) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address src, address dst, uint256 wad) returns(bool) +func (_DelayedWETH *DelayedWETHTransactorSession) TransferFrom(src common.Address, dst common.Address, wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.TransferFrom(&_DelayedWETH.TransactOpts, src, dst, wad) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_DelayedWETH *DelayedWETHTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _DelayedWETH.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_DelayedWETH *DelayedWETHSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _DelayedWETH.Contract.TransferOwnership(&_DelayedWETH.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_DelayedWETH *DelayedWETHTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _DelayedWETH.Contract.TransferOwnership(&_DelayedWETH.TransactOpts, newOwner) +} + +// Unlock is a paid mutator transaction binding the contract method 0x7eee288d. +// +// Solidity: function unlock(address _guy, uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHTransactor) Unlock(opts *bind.TransactOpts, _guy common.Address, _wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.contract.Transact(opts, "unlock", _guy, _wad) +} + +// Unlock is a paid mutator transaction binding the contract method 0x7eee288d. +// +// Solidity: function unlock(address _guy, uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHSession) Unlock(_guy common.Address, _wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Unlock(&_DelayedWETH.TransactOpts, _guy, _wad) +} + +// Unlock is a paid mutator transaction binding the contract method 0x7eee288d. +// +// Solidity: function unlock(address _guy, uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHTransactorSession) Unlock(_guy common.Address, _wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Unlock(&_DelayedWETH.TransactOpts, _guy, _wad) +} + +// Withdraw is a paid mutator transaction binding the contract method 0x2e1a7d4d. +// +// Solidity: function withdraw(uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHTransactor) Withdraw(opts *bind.TransactOpts, _wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.contract.Transact(opts, "withdraw", _wad) +} + +// Withdraw is a paid mutator transaction binding the contract method 0x2e1a7d4d. +// +// Solidity: function withdraw(uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHSession) Withdraw(_wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Withdraw(&_DelayedWETH.TransactOpts, _wad) +} + +// Withdraw is a paid mutator transaction binding the contract method 0x2e1a7d4d. +// +// Solidity: function withdraw(uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHTransactorSession) Withdraw(_wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Withdraw(&_DelayedWETH.TransactOpts, _wad) +} + +// Withdraw0 is a paid mutator transaction binding the contract method 0xf3fef3a3. +// +// Solidity: function withdraw(address _guy, uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHTransactor) Withdraw0(opts *bind.TransactOpts, _guy common.Address, _wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.contract.Transact(opts, "withdraw0", _guy, _wad) +} + +// Withdraw0 is a paid mutator transaction binding the contract method 0xf3fef3a3. +// +// Solidity: function withdraw(address _guy, uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHSession) Withdraw0(_guy common.Address, _wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Withdraw0(&_DelayedWETH.TransactOpts, _guy, _wad) +} + +// Withdraw0 is a paid mutator transaction binding the contract method 0xf3fef3a3. +// +// Solidity: function withdraw(address _guy, uint256 _wad) returns() +func (_DelayedWETH *DelayedWETHTransactorSession) Withdraw0(_guy common.Address, _wad *big.Int) (*types.Transaction, error) { + return _DelayedWETH.Contract.Withdraw0(&_DelayedWETH.TransactOpts, _guy, _wad) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_DelayedWETH *DelayedWETHTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _DelayedWETH.contract.RawTransact(opts, nil) // calldata is disallowed for receive function +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_DelayedWETH *DelayedWETHSession) Receive() (*types.Transaction, error) { + return _DelayedWETH.Contract.Receive(&_DelayedWETH.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_DelayedWETH *DelayedWETHTransactorSession) Receive() (*types.Transaction, error) { + return _DelayedWETH.Contract.Receive(&_DelayedWETH.TransactOpts) +} + +// DelayedWETHApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the DelayedWETH contract. +type DelayedWETHApprovalIterator struct { + Event *DelayedWETHApproval // 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 *DelayedWETHApprovalIterator) 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(DelayedWETHApproval) + 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(DelayedWETHApproval) + 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 *DelayedWETHApprovalIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DelayedWETHApprovalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DelayedWETHApproval represents a Approval event raised by the DelayedWETH contract. +type DelayedWETHApproval struct { + Src common.Address + Guy common.Address + Wad *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterApproval is a free log retrieval operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed src, address indexed guy, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) FilterApproval(opts *bind.FilterOpts, src []common.Address, guy []common.Address) (*DelayedWETHApprovalIterator, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + var guyRule []interface{} + for _, guyItem := range guy { + guyRule = append(guyRule, guyItem) + } + + logs, sub, err := _DelayedWETH.contract.FilterLogs(opts, "Approval", srcRule, guyRule) + if err != nil { + return nil, err + } + return &DelayedWETHApprovalIterator{contract: _DelayedWETH.contract, event: "Approval", logs: logs, sub: sub}, nil +} + +// WatchApproval is a free log subscription operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed src, address indexed guy, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *DelayedWETHApproval, src []common.Address, guy []common.Address) (event.Subscription, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + var guyRule []interface{} + for _, guyItem := range guy { + guyRule = append(guyRule, guyItem) + } + + logs, sub, err := _DelayedWETH.contract.WatchLogs(opts, "Approval", srcRule, guyRule) + 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(DelayedWETHApproval) + if err := _DelayedWETH.contract.UnpackLog(event, "Approval", 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 +} + +// ParseApproval is a log parse operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed src, address indexed guy, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) ParseApproval(log types.Log) (*DelayedWETHApproval, error) { + event := new(DelayedWETHApproval) + if err := _DelayedWETH.contract.UnpackLog(event, "Approval", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DelayedWETHDepositIterator is returned from FilterDeposit and is used to iterate over the raw logs and unpacked data for Deposit events raised by the DelayedWETH contract. +type DelayedWETHDepositIterator struct { + Event *DelayedWETHDeposit // 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 *DelayedWETHDepositIterator) 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(DelayedWETHDeposit) + 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(DelayedWETHDeposit) + 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 *DelayedWETHDepositIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DelayedWETHDepositIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DelayedWETHDeposit represents a Deposit event raised by the DelayedWETH contract. +type DelayedWETHDeposit struct { + Dst common.Address + Wad *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDeposit is a free log retrieval operation binding the contract event 0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c. +// +// Solidity: event Deposit(address indexed dst, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) FilterDeposit(opts *bind.FilterOpts, dst []common.Address) (*DelayedWETHDepositIterator, error) { + + var dstRule []interface{} + for _, dstItem := range dst { + dstRule = append(dstRule, dstItem) + } + + logs, sub, err := _DelayedWETH.contract.FilterLogs(opts, "Deposit", dstRule) + if err != nil { + return nil, err + } + return &DelayedWETHDepositIterator{contract: _DelayedWETH.contract, event: "Deposit", logs: logs, sub: sub}, nil +} + +// WatchDeposit is a free log subscription operation binding the contract event 0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c. +// +// Solidity: event Deposit(address indexed dst, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) WatchDeposit(opts *bind.WatchOpts, sink chan<- *DelayedWETHDeposit, dst []common.Address) (event.Subscription, error) { + + var dstRule []interface{} + for _, dstItem := range dst { + dstRule = append(dstRule, dstItem) + } + + logs, sub, err := _DelayedWETH.contract.WatchLogs(opts, "Deposit", dstRule) + 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(DelayedWETHDeposit) + if err := _DelayedWETH.contract.UnpackLog(event, "Deposit", 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 +} + +// ParseDeposit is a log parse operation binding the contract event 0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c. +// +// Solidity: event Deposit(address indexed dst, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) ParseDeposit(log types.Log) (*DelayedWETHDeposit, error) { + event := new(DelayedWETHDeposit) + if err := _DelayedWETH.contract.UnpackLog(event, "Deposit", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DelayedWETHInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the DelayedWETH contract. +type DelayedWETHInitializedIterator struct { + Event *DelayedWETHInitialized // 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 *DelayedWETHInitializedIterator) 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(DelayedWETHInitialized) + 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(DelayedWETHInitialized) + 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 *DelayedWETHInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DelayedWETHInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DelayedWETHInitialized represents a Initialized event raised by the DelayedWETH contract. +type DelayedWETHInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_DelayedWETH *DelayedWETHFilterer) FilterInitialized(opts *bind.FilterOpts) (*DelayedWETHInitializedIterator, error) { + + logs, sub, err := _DelayedWETH.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &DelayedWETHInitializedIterator{contract: _DelayedWETH.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_DelayedWETH *DelayedWETHFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *DelayedWETHInitialized) (event.Subscription, error) { + + logs, sub, err := _DelayedWETH.contract.WatchLogs(opts, "Initialized") + 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(DelayedWETHInitialized) + if err := _DelayedWETH.contract.UnpackLog(event, "Initialized", 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 +} + +// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_DelayedWETH *DelayedWETHFilterer) ParseInitialized(log types.Log) (*DelayedWETHInitialized, error) { + event := new(DelayedWETHInitialized) + if err := _DelayedWETH.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DelayedWETHOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the DelayedWETH contract. +type DelayedWETHOwnershipTransferredIterator struct { + Event *DelayedWETHOwnershipTransferred // 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 *DelayedWETHOwnershipTransferredIterator) 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(DelayedWETHOwnershipTransferred) + 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(DelayedWETHOwnershipTransferred) + 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 *DelayedWETHOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DelayedWETHOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DelayedWETHOwnershipTransferred represents a OwnershipTransferred event raised by the DelayedWETH contract. +type DelayedWETHOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_DelayedWETH *DelayedWETHFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*DelayedWETHOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _DelayedWETH.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &DelayedWETHOwnershipTransferredIterator{contract: _DelayedWETH.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_DelayedWETH *DelayedWETHFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *DelayedWETHOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _DelayedWETH.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + 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(DelayedWETHOwnershipTransferred) + if err := _DelayedWETH.contract.UnpackLog(event, "OwnershipTransferred", 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 +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_DelayedWETH *DelayedWETHFilterer) ParseOwnershipTransferred(log types.Log) (*DelayedWETHOwnershipTransferred, error) { + event := new(DelayedWETHOwnershipTransferred) + if err := _DelayedWETH.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DelayedWETHTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the DelayedWETH contract. +type DelayedWETHTransferIterator struct { + Event *DelayedWETHTransfer // 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 *DelayedWETHTransferIterator) 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(DelayedWETHTransfer) + 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(DelayedWETHTransfer) + 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 *DelayedWETHTransferIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DelayedWETHTransferIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DelayedWETHTransfer represents a Transfer event raised by the DelayedWETH contract. +type DelayedWETHTransfer struct { + Src common.Address + Dst common.Address + Wad *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransfer is a free log retrieval operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed src, address indexed dst, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) FilterTransfer(opts *bind.FilterOpts, src []common.Address, dst []common.Address) (*DelayedWETHTransferIterator, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + var dstRule []interface{} + for _, dstItem := range dst { + dstRule = append(dstRule, dstItem) + } + + logs, sub, err := _DelayedWETH.contract.FilterLogs(opts, "Transfer", srcRule, dstRule) + if err != nil { + return nil, err + } + return &DelayedWETHTransferIterator{contract: _DelayedWETH.contract, event: "Transfer", logs: logs, sub: sub}, nil +} + +// WatchTransfer is a free log subscription operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed src, address indexed dst, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *DelayedWETHTransfer, src []common.Address, dst []common.Address) (event.Subscription, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + var dstRule []interface{} + for _, dstItem := range dst { + dstRule = append(dstRule, dstItem) + } + + logs, sub, err := _DelayedWETH.contract.WatchLogs(opts, "Transfer", srcRule, dstRule) + 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(DelayedWETHTransfer) + if err := _DelayedWETH.contract.UnpackLog(event, "Transfer", 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 +} + +// ParseTransfer is a log parse operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed src, address indexed dst, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) ParseTransfer(log types.Log) (*DelayedWETHTransfer, error) { + event := new(DelayedWETHTransfer) + if err := _DelayedWETH.contract.UnpackLog(event, "Transfer", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DelayedWETHUnwrapIterator is returned from FilterUnwrap and is used to iterate over the raw logs and unpacked data for Unwrap events raised by the DelayedWETH contract. +type DelayedWETHUnwrapIterator struct { + Event *DelayedWETHUnwrap // 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 *DelayedWETHUnwrapIterator) 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(DelayedWETHUnwrap) + 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(DelayedWETHUnwrap) + 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 *DelayedWETHUnwrapIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DelayedWETHUnwrapIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DelayedWETHUnwrap represents a Unwrap event raised by the DelayedWETH contract. +type DelayedWETHUnwrap struct { + Src common.Address + Wad *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUnwrap is a free log retrieval operation binding the contract event 0x5dd085b6070b4cae004f84daafd199fd55b0bdfa11c3a802baffe89c2419d8c2. +// +// Solidity: event Unwrap(address indexed src, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) FilterUnwrap(opts *bind.FilterOpts, src []common.Address) (*DelayedWETHUnwrapIterator, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + + logs, sub, err := _DelayedWETH.contract.FilterLogs(opts, "Unwrap", srcRule) + if err != nil { + return nil, err + } + return &DelayedWETHUnwrapIterator{contract: _DelayedWETH.contract, event: "Unwrap", logs: logs, sub: sub}, nil +} + +// WatchUnwrap is a free log subscription operation binding the contract event 0x5dd085b6070b4cae004f84daafd199fd55b0bdfa11c3a802baffe89c2419d8c2. +// +// Solidity: event Unwrap(address indexed src, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) WatchUnwrap(opts *bind.WatchOpts, sink chan<- *DelayedWETHUnwrap, src []common.Address) (event.Subscription, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + + logs, sub, err := _DelayedWETH.contract.WatchLogs(opts, "Unwrap", srcRule) + 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(DelayedWETHUnwrap) + if err := _DelayedWETH.contract.UnpackLog(event, "Unwrap", 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 +} + +// ParseUnwrap is a log parse operation binding the contract event 0x5dd085b6070b4cae004f84daafd199fd55b0bdfa11c3a802baffe89c2419d8c2. +// +// Solidity: event Unwrap(address indexed src, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) ParseUnwrap(log types.Log) (*DelayedWETHUnwrap, error) { + event := new(DelayedWETHUnwrap) + if err := _DelayedWETH.contract.UnpackLog(event, "Unwrap", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// DelayedWETHWithdrawalIterator is returned from FilterWithdrawal and is used to iterate over the raw logs and unpacked data for Withdrawal events raised by the DelayedWETH contract. +type DelayedWETHWithdrawalIterator struct { + Event *DelayedWETHWithdrawal // 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 *DelayedWETHWithdrawalIterator) 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(DelayedWETHWithdrawal) + 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(DelayedWETHWithdrawal) + 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 *DelayedWETHWithdrawalIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *DelayedWETHWithdrawalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// DelayedWETHWithdrawal represents a Withdrawal event raised by the DelayedWETH contract. +type DelayedWETHWithdrawal struct { + Src common.Address + Wad *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterWithdrawal is a free log retrieval operation binding the contract event 0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65. +// +// Solidity: event Withdrawal(address indexed src, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) FilterWithdrawal(opts *bind.FilterOpts, src []common.Address) (*DelayedWETHWithdrawalIterator, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + + logs, sub, err := _DelayedWETH.contract.FilterLogs(opts, "Withdrawal", srcRule) + if err != nil { + return nil, err + } + return &DelayedWETHWithdrawalIterator{contract: _DelayedWETH.contract, event: "Withdrawal", logs: logs, sub: sub}, nil +} + +// WatchWithdrawal is a free log subscription operation binding the contract event 0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65. +// +// Solidity: event Withdrawal(address indexed src, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) WatchWithdrawal(opts *bind.WatchOpts, sink chan<- *DelayedWETHWithdrawal, src []common.Address) (event.Subscription, error) { + + var srcRule []interface{} + for _, srcItem := range src { + srcRule = append(srcRule, srcItem) + } + + logs, sub, err := _DelayedWETH.contract.WatchLogs(opts, "Withdrawal", srcRule) + 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(DelayedWETHWithdrawal) + if err := _DelayedWETH.contract.UnpackLog(event, "Withdrawal", 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 +} + +// ParseWithdrawal is a log parse operation binding the contract event 0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65. +// +// Solidity: event Withdrawal(address indexed src, uint256 wad) +func (_DelayedWETH *DelayedWETHFilterer) ParseWithdrawal(log types.Log) (*DelayedWETHWithdrawal, error) { + event := new(DelayedWETHWithdrawal) + if err := _DelayedWETH.contract.UnpackLog(event, "Withdrawal", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/op-bindings/bindings/delayedweth_more.go b/op-bindings/bindings/delayedweth_more.go new file mode 100644 index 000000000000..6cf91b0ae447 --- /dev/null +++ b/op-bindings/bindings/delayedweth_more.go @@ -0,0 +1,27 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package bindings + +import ( + "encoding/json" + + "github.com/ethereum-optimism/optimism/op-bindings/solc" +) + +const DelayedWETHStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/dispute/weth/DelayedWETH.sol:DelayedWETH\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"src/dispute/weth/DelayedWETH.sol:DelayedWETH\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1002,\"contract\":\"src/dispute/weth/DelayedWETH.sol:DelayedWETH\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)50_storage\"},{\"astId\":1003,\"contract\":\"src/dispute/weth/DelayedWETH.sol:DelayedWETH\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":1004,\"contract\":\"src/dispute/weth/DelayedWETH.sol:DelayedWETH\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":1005,\"contract\":\"src/dispute/weth/DelayedWETH.sol:DelayedWETH\",\"label\":\"balanceOf\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":1006,\"contract\":\"src/dispute/weth/DelayedWETH.sol:DelayedWETH\",\"label\":\"allowance\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":1007,\"contract\":\"src/dispute/weth/DelayedWETH.sol:DelayedWETH\",\"label\":\"withdrawals\",\"offset\":0,\"slot\":\"103\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_struct(WithdrawalRequest)1010_storage))\"},{\"astId\":1008,\"contract\":\"src/dispute/weth/DelayedWETH.sol:DelayedWETH\",\"label\":\"config\",\"offset\":0,\"slot\":\"104\",\"type\":\"t_contract(SuperchainConfig)1009\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\",\"base\":\"t_uint256\"},\"t_array(t_uint256)50_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\",\"base\":\"t_uint256\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_contract(SuperchainConfig)1009\":{\"encoding\":\"inplace\",\"label\":\"contract SuperchainConfig\",\"numberOfBytes\":\"20\"},\"t_mapping(t_address,t_mapping(t_address,t_struct(WithdrawalRequest)1010_storage))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e struct IDelayedWETH.WithdrawalRequest))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_struct(WithdrawalRequest)1010_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(WithdrawalRequest)1010_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e struct IDelayedWETH.WithdrawalRequest)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_struct(WithdrawalRequest)1010_storage\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_struct(WithdrawalRequest)1010_storage\":{\"encoding\":\"inplace\",\"label\":\"struct IDelayedWETH.WithdrawalRequest\",\"numberOfBytes\":\"64\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}" + +var DelayedWETHStorageLayout = new(solc.StorageLayout) + +var DelayedWETHDeployedBin = "0x6080604052600436106101845760003560e01c8063715018a6116100d6578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e1461052b578063f2fde38b14610563578063f3fef3a31461058357600080fd5b8063a9059cbb146104af578063cd47bde1146104cf578063d0e30db01461052357600080fd5b80638da5cb5b116100b05780638da5cb5b1461041b57806395d89b4114610446578063977a5ec51461048f57600080fd5b8063715018a61461039457806379502c55146103a95780637eee288d146103fb57600080fd5b80632e1a7d4d1161013857806354fd4d501161011257806354fd4d50146102eb5780636a42b8f81461033457806370a082311461036757600080fd5b80632e1a7d4d14610284578063313ce567146102a4578063485cc955146102cb57600080fd5b80630ca35682116101695780630ca356821461022757806318160ddd1461024757806323b872dd1461026457600080fd5b806306fdde0314610198578063095ea7b3146101f757600080fd5b36610193576101916105a3565b005b600080fd5b3480156101a457600080fd5b506101e16040518060400160405280600d81526020017f577261707065642045746865720000000000000000000000000000000000000081525081565b6040516101ee9190611387565b60405180910390f35b34801561020357600080fd5b5061021761021236600461141c565b6105fe565b60405190151581526020016101ee565b34801561023357600080fd5b50610191610242366004611448565b610677565b34801561025357600080fd5b50475b6040519081526020016101ee565b34801561027057600080fd5b5061021761027f366004611461565b610743565b34801561029057600080fd5b5061019161029f366004611448565b61095a565b3480156102b057600080fd5b506102b9601281565b60405160ff90911681526020016101ee565b3480156102d757600080fd5b506101916102e63660046114a2565b610967565b3480156102f757600080fd5b506101e16040518060400160405280600581526020017f302e322e3000000000000000000000000000000000000000000000000000000081525081565b34801561034057600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610256565b34801561037357600080fd5b506102566103823660046114db565b60656020526000908152604090205481565b3480156103a057600080fd5b50610191610b43565b3480156103b557600080fd5b506068546103d69073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ee565b34801561040757600080fd5b5061019161041636600461141c565b610b57565b34801561042757600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166103d6565b34801561045257600080fd5b506101e16040518060400160405280600481526020017f574554480000000000000000000000000000000000000000000000000000000081525081565b34801561049b57600080fd5b506101916104aa36600461141c565b610bab565b3480156104bb57600080fd5b506102176104ca36600461141c565b610c98565b3480156104db57600080fd5b5061050e6104ea3660046114a2565b60676020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101ee565b6101916105a3565b34801561053757600080fd5b506102566105463660046114a2565b606660209081526000928352604080842090915290825290205481565b34801561056f57600080fd5b5061019161057e3660046114db565b610cac565b34801561058f57600080fd5b5061019161059e36600461141c565b610d60565b33600090815260656020526040812080543492906105c2908490611527565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b33600081815260666020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106669086815260200190565b60405180910390a350600192915050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064015b60405180910390fd5b600047821061070c574761070e565b815b604051909150339082156108fc029083906000818181858888f1935050505015801561073e573d6000803e3d6000fd5b505050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526065602052604081205482111561077557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841633148015906107eb575073ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156108735773ffffffffffffffffffffffffffffffffffffffff8416600090815260666020908152604080832033845290915290205482111561082d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091528120805484929061086d90849061153f565b90915550505b73ffffffffffffffffffffffffffffffffffffffff8416600090815260656020526040812080548492906108a890849061153f565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600090815260656020526040812080548492906108e2908490611527565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161094891815260200190565b60405180910390a35060019392505050565b6109643382610d60565b50565b600054610100900460ff16158080156109875750600054600160ff909116105b806109a15750303b1580156109a1575060005460ff166001145b610a2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106f4565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610a8b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610a936110aa565b610a9c83611149565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055801561073e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b610b4b6111c0565b610b556000611149565b565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120426001820155805490918391839190610ba1908490611527565b9091555050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064016106f4565b73ffffffffffffffffffffffffffffffffffffffff821660008181526066602090815260408083203380855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050565b6000610ca5338484610743565b9392505050565b610cb46111c0565b73ffffffffffffffffffffffffffffffffffffffff8116610d57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106f4565b61096481611149565b606860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df19190611556565b15610e58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44656c61796564574554483a20636f6e7472616374206973207061757365640060448201526064016106f4565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290208054821115610f19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f44656c61796564574554483a20696e73756666696369656e7420756e6c6f636b60448201527f6564207769746864726177616c0000000000000000000000000000000000000060648201526084016106f4565b6000816001015411610fac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f44656c61796564574554483a207769746864726177616c206e6f7420756e6c6f60448201527f636b65640000000000000000000000000000000000000000000000000000000060648201526084016106f4565b427f00000000000000000000000000000000000000000000000000000000000000008260010154610fdd9190611527565b111561106b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f44656c61796564574554483a207769746864726177616c2064656c6179206e6f60448201527f74206d657400000000000000000000000000000000000000000000000000000060648201526084016106f4565b8181600001600082825461107f919061153f565b9091555061073e905082611241565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff16611141576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106f4565b610b556112e7565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610b55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106f4565b3360009081526065602052604090205481111561125d57600080fd5b336000908152606560205260408120805483929061127c90849061153f565b9091555050604051339082156108fc029083906000818181858888f193505050501580156112ae573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600054610100900460ff1661137e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106f4565b610b5533611149565b600060208083528351808285015260005b818110156113b457858101830151858201604001528201611398565b818111156113c6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461096457600080fd5b6000806040838503121561142f57600080fd5b823561143a816113fa565b946020939093013593505050565b60006020828403121561145a57600080fd5b5035919050565b60008060006060848603121561147657600080fd5b8335611481816113fa565b92506020840135611491816113fa565b929592945050506040919091013590565b600080604083850312156114b557600080fd5b82356114c0816113fa565b915060208301356114d0816113fa565b809150509250929050565b6000602082840312156114ed57600080fd5b8135610ca5816113fa565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561153a5761153a6114f8565b500190565b600082821015611551576115516114f8565b500390565b60006020828403121561156857600080fd5b81518015158114610ca557600080fdfea164736f6c634300080f000a" + + +func init() { + if err := json.Unmarshal([]byte(DelayedWETHStorageLayoutJSON), DelayedWETHStorageLayout); err != nil { + panic(err) + } + + layouts["DelayedWETH"] = DelayedWETHStorageLayout + deployedBytecodes["DelayedWETH"] = DelayedWETHDeployedBin + immutableReferences["DelayedWETH"] = true +} diff --git a/op-bindings/bindings/disputegamefactory.go b/op-bindings/bindings/disputegamefactory.go index 7d9127b704ff..acf988458001 100644 --- a/op-bindings/bindings/disputegamefactory.go +++ b/op-bindings/bindings/disputegamefactory.go @@ -28,10 +28,19 @@ var ( _ = event.NewSubscription ) +// IDisputeGameFactoryGameSearchResult is an auto generated low-level Go binding around an user-defined struct. +type IDisputeGameFactoryGameSearchResult struct { + Index *big.Int + Metadata [32]byte + Timestamp uint64 + RootClaim [32]byte + ExtraData []byte +} + // DisputeGameFactoryMetaData contains all meta data concerning the DisputeGameFactory contract. var DisputeGameFactoryMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"create\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint8\",\"internalType\":\"GameType\"},{\"name\":\"_rootClaim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"proxy_\",\"type\":\"address\",\"internalType\":\"contractIDisputeGame\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"gameAtIndex\",\"inputs\":[{\"name\":\"_index\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"gameType_\",\"type\":\"uint8\",\"internalType\":\"GameType\"},{\"name\":\"timestamp_\",\"type\":\"uint64\",\"internalType\":\"Timestamp\"},{\"name\":\"proxy_\",\"type\":\"address\",\"internalType\":\"contractIDisputeGame\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gameCount\",\"inputs\":[],\"outputs\":[{\"name\":\"gameCount_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gameImpls\",\"inputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"GameType\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIDisputeGame\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"games\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint8\",\"internalType\":\"GameType\"},{\"name\":\"_rootClaim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"proxy_\",\"type\":\"address\",\"internalType\":\"contractIDisputeGame\"},{\"name\":\"timestamp_\",\"type\":\"uint64\",\"internalType\":\"Timestamp\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getGameUUID\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint8\",\"internalType\":\"GameType\"},{\"name\":\"_rootClaim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"uuid_\",\"type\":\"bytes32\",\"internalType\":\"Hash\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"initBonds\",\"inputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"GameType\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setImplementation\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint8\",\"internalType\":\"GameType\"},{\"name\":\"_impl\",\"type\":\"address\",\"internalType\":\"contractIDisputeGame\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setInitBond\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint8\",\"internalType\":\"GameType\"},{\"name\":\"_initBond\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"DisputeGameCreated\",\"inputs\":[{\"name\":\"disputeProxy\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"gameType\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"GameType\"},{\"name\":\"rootClaim\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"Claim\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ImplementationSet\",\"inputs\":[{\"name\":\"impl\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"gameType\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"GameType\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"InitBondUpdated\",\"inputs\":[{\"name\":\"gameType\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"GameType\"},{\"name\":\"newBond\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"GameAlreadyExists\",\"inputs\":[{\"name\":\"uuid\",\"type\":\"bytes32\",\"internalType\":\"Hash\"}]},{\"type\":\"error\",\"name\":\"InsufficientBond\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoImplementation\",\"inputs\":[{\"name\":\"gameType\",\"type\":\"uint8\",\"internalType\":\"GameType\"}]}]", - Bin: "0x60806040523480156200001157600080fd5b506200001e600062000024565b62000292565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016260201b62000a3c1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b6200010c62000171565b6200011782620001d9565b80156200015e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001cd5760405162461bcd60e51b815260206004820152602b6024820152600080516020620012ff83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d76200022b565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620002875760405162461bcd60e51b815260206004820152602b6024820152600080516020620012ff83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d733620001d9565b61105d80620002a26000396000f3fe6080604052600436106100dd5760003560e01c8063bb8aa1fc1161007f578063c4d66de811610059578063c4d66de8146102ed578063dfa162d31461030d578063ed8bc95d14610350578063f2fde38b1461037d57600080fd5b8063bb8aa1fc1461021a578063c018126b14610278578063c49d52711461029857600080fd5b80634d1975b4116100bb5780634d1975b41461016f57806354fd4d5014610184578063715018a6146101da5780638da5cb5b146101ef57600080fd5b806326daafbe146100e25780633142e55e1461011557806345583b7a1461014d575b600080fd5b3480156100ee57600080fd5b506101026100fd366004610dd4565b61039d565b6040519081526020015b60405180910390f35b610128610123366004610dd4565b6103d6565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010c565b34801561015957600080fd5b5061016d610168366004610e7d565b610650565b005b34801561017b57600080fd5b50606854610102565b34801561019057600080fd5b506101cd6040518060400160405280600581526020017f302e302e3800000000000000000000000000000000000000000000000000000081525081565b60405161010c9190610eb4565b3480156101e657600080fd5b5061016d6106d7565b3480156101fb57600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610128565b34801561022657600080fd5b5061023a610235366004610f27565b6106eb565b6040805160ff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff169082015260600161010c565b34801561028457600080fd5b5061016d610293366004610f40565b61074d565b3480156102a457600080fd5b506102b86102b3366004610dd4565b610796565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161010c565b3480156102f957600080fd5b5061016d610308366004610f6a565b6107e9565b34801561031957600080fd5b50610128610328366004610f8e565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b34801561035c57600080fd5b5061010261036b366004610f8e565b60666020526000908152604090205481565b34801561038957600080fd5b5061016d610398366004610f6a565b610985565b6000848484846040516020016103b69493929190610fa9565b604051602081830303815290604052805190602001209050949350505050565b60ff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff1680610440576040517f44265d6f00000000000000000000000000000000000000000000000000000000815260ff871660048201526024015b60405180910390fd5b60ff861660009081526066602052604090205434101561048c576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104ef8585856040516020016104a493929190611007565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff831690610a58565b91508173ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561053957600080fd5b505af115801561054d573d6000803e3d6000fd5b505050505060006105608787878761039d565b600081815260676020526040902054909150156105ac576040517f014f6fe500000000000000000000000000000000000000000000000000000000815260048101829052602401610437565b60004260b81b60f889901b178417600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250889160ff8b169173ffffffffffffffffffffffffffffffffffffffff8816917ffad0599ff449d8d9685eadecca8cb9e00924c5fd8367c1c09469824939e1ffec9190a4505050949350505050565b610658610b8c565b60ff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917f623713f72f6e427a8044bb8b3bd6834357cf285decbaa21bcc73c1d0632c4d8491a35050565b6106df610b8c565b6106e96000610c0d565b565b60008060006107406068858154811061070657610706611021565b906000526020600020015460f881901c9167ffffffffffffffff60b883901c169173ffffffffffffffffffffffffffffffffffffffff1690565b9196909550909350915050565b610755610b8c565b60ff8216600081815260666020526040808220849055518392917f3d3603f30a8e965cf76ec29fb1f0563457ec8a7114c12180c60e7be8384201f191a35050565b60008060006107a78787878761039d565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860b89190911c67ffffffffffffffff16975095505050505050565b600054610100900460ff16158080156108095750600054600160ff909116105b806108235750303b158015610823575060005460ff166001145b6108af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610437565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561090d57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610915610c84565b61091e82610c0d565b801561098157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b61098d610b8c565b73ffffffffffffffffffffffffffffffffffffffff8116610a30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610437565b610a3981610c0d565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60006002825101603f8101600a81036040518360581b8260e81b177f6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d7300001781528660601b601e8201527f5af43d3d93803e603357fd5bf300000000000000000000000000000000000000603282015285519150603f8101602087015b60208410610b1057805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09093019260209182019101610ad3565b517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602085900360031b1b16815260f085901b9083015282816000f0945084610b7d577febfef1880000000000000000000000000000000000000000000000000000000060005260206000fd5b90910160405250909392505050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610437565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610d1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610437565b6106e9600054610100900460ff16610db5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610437565b6106e933610c0d565b803560ff81168114610dcf57600080fd5b919050565b60008060008060608587031215610dea57600080fd5b610df385610dbe565b935060208501359250604085013567ffffffffffffffff80821115610e1757600080fd5b818701915087601f830112610e2b57600080fd5b813581811115610e3a57600080fd5b886020828501011115610e4c57600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610a3957600080fd5b60008060408385031215610e9057600080fd5b610e9983610dbe565b91506020830135610ea981610e5b565b809150509250929050565b600060208083528351808285015260005b81811015610ee157858101830151858201604001528201610ec5565b81811115610ef3576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600060208284031215610f3957600080fd5b5035919050565b60008060408385031215610f5357600080fd5b610f5c83610dbe565b946020939093013593505050565b600060208284031215610f7c57600080fd5b8135610f8781610e5b565b9392505050565b600060208284031215610fa057600080fd5b610f8782610dbe565b60ff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b838152818360208301376000910160200190815292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", + ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"create\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint32\",\"internalType\":\"GameType\"},{\"name\":\"_rootClaim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"proxy_\",\"type\":\"address\",\"internalType\":\"contractIDisputeGame\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"findLatestGames\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint32\",\"internalType\":\"GameType\"},{\"name\":\"_start\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_n\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"games_\",\"type\":\"tuple[]\",\"internalType\":\"structIDisputeGameFactory.GameSearchResult[]\",\"components\":[{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"metadata\",\"type\":\"bytes32\",\"internalType\":\"GameId\"},{\"name\":\"timestamp\",\"type\":\"uint64\",\"internalType\":\"Timestamp\"},{\"name\":\"rootClaim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gameAtIndex\",\"inputs\":[{\"name\":\"_index\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"gameType_\",\"type\":\"uint32\",\"internalType\":\"GameType\"},{\"name\":\"timestamp_\",\"type\":\"uint64\",\"internalType\":\"Timestamp\"},{\"name\":\"proxy_\",\"type\":\"address\",\"internalType\":\"contractIDisputeGame\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gameCount\",\"inputs\":[],\"outputs\":[{\"name\":\"gameCount_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gameImpls\",\"inputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"GameType\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIDisputeGame\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"games\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint32\",\"internalType\":\"GameType\"},{\"name\":\"_rootClaim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"proxy_\",\"type\":\"address\",\"internalType\":\"contractIDisputeGame\"},{\"name\":\"timestamp_\",\"type\":\"uint64\",\"internalType\":\"Timestamp\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getGameUUID\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint32\",\"internalType\":\"GameType\"},{\"name\":\"_rootClaim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_extraData\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"uuid_\",\"type\":\"bytes32\",\"internalType\":\"Hash\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"initBonds\",\"inputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"GameType\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setImplementation\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint32\",\"internalType\":\"GameType\"},{\"name\":\"_impl\",\"type\":\"address\",\"internalType\":\"contractIDisputeGame\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setInitBond\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint32\",\"internalType\":\"GameType\"},{\"name\":\"_initBond\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"DisputeGameCreated\",\"inputs\":[{\"name\":\"disputeProxy\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"gameType\",\"type\":\"uint32\",\"indexed\":true,\"internalType\":\"GameType\"},{\"name\":\"rootClaim\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"Claim\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ImplementationSet\",\"inputs\":[{\"name\":\"impl\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"gameType\",\"type\":\"uint32\",\"indexed\":true,\"internalType\":\"GameType\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"InitBondUpdated\",\"inputs\":[{\"name\":\"gameType\",\"type\":\"uint32\",\"indexed\":true,\"internalType\":\"GameType\"},{\"name\":\"newBond\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"GameAlreadyExists\",\"inputs\":[{\"name\":\"uuid\",\"type\":\"bytes32\",\"internalType\":\"Hash\"}]},{\"type\":\"error\",\"name\":\"InsufficientBond\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoImplementation\",\"inputs\":[{\"name\":\"gameType\",\"type\":\"uint32\",\"internalType\":\"GameType\"}]}]", + Bin: "0x60806040523480156200001157600080fd5b506200001e600062000024565b62000292565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016260201b62000cdc1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b6200010c62000171565b6200011782620001d9565b80156200015e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001cd5760405162461bcd60e51b815260206004820152602b60248201526000805160206200180083398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d76200022b565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620002875760405162461bcd60e51b815260206004820152602b60248201526000805160206200180083398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d733620001d9565b61155e80620002a26000396000f3fe6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d610108366004611099565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110d0565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d6101973660046110eb565b61045e565b3480156101a857600080fd5b506101bc6101b7366004611115565b6104aa565b60405161017391906111c2565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600581526020017f302e322e3000000000000000000000000000000000000000000000000000000081525081565b604051610173919061127f565b34801561024a57600080fd5b5061025e610259366004611292565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110d0565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e3366004611292565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e366004611292565b6109ee565b34801561033f57600080fd5b5061035361034e366004611319565b610a27565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af366004611332565b610a89565b3480156103c057600080fd5b5061010d6103cf366004611332565b610c25565b6103dc610cf8565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610cf8565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f061134f565b600091825260209091200154905060e081901c67ffffffffffffffff60a083901c1673ffffffffffffffffffffffffffffffffffffffff831660ff808a16908416036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113ad565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106439190611478565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a516106859190611491565b815181106106955761069561134f565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ee565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610cf8565b6107536000610d79565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff8616600090815260666020526040902054341015610814576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610821600143611491565b4090506108898682878760405160200161083e94939291906114cf565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df0565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d357600080fd5b505af11580156108e7573d6000803e3d6000fd5b505050505060006108fa888888886109ee565b60008181526067602052604090205490915015610946576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a0794939291906114f0565b604051602081830303815290604052805190602001209050949350505050565b6000806000610a7c60688581548110610a4257610a4261134f565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9196909550909350915050565b600054610100900460ff1615808015610aa95750600054600160ff909116105b80610ac35750303b158015610ac3575060005460ff166001145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bad57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bb5610f24565b610bbe82610d79565b8015610c2157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c2d610cf8565b73ffffffffffffffffffffffffffffffffffffffff8116610cd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610cd981610d79565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006002825101603f8101600a81036040518360581b8260e81b177f6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d7300001781528660601b601e8201527f5af43d3d93803e603357fd5bf300000000000000000000000000000000000000603282015285519150603f8101602087015b60208410610ea857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09093019260209182019101610e6b565b517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602085900360031b1b16815260f085901b9083015282816000f0945084610f15577febfef1880000000000000000000000000000000000000000000000000000000060005260206000fd5b90910160405250909392505050565b600054610100900460ff16610fbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753600054610100900460ff16611055576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d79565b803563ffffffff8116811461107257600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cd957600080fd5b600080604083850312156110ac57600080fd5b6110b58361105e565b915060208301356110c581611077565b809150509250929050565b6000602082840312156110e257600080fd5b6106e78261105e565b600080604083850312156110fe57600080fd5b6111078361105e565b946020939093013593505050565b60008060006060848603121561112a57600080fd5b6111338461105e565b95602085013595506040909401359392505050565b60005b8381101561116357818101518382015260200161114b565b83811115611172576000848401525b50505050565b60008151808452611190816020860160208601611148565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611271578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a09185018290529061125d81860183611178565b9689019694505050908601906001016111e9565b509098975050505050505050565b6020815260006106e76020830184611178565b600080600080606085870312156112a857600080fd5b6112b18561105e565b935060208501359250604085013567ffffffffffffffff808211156112d557600080fd5b818701915087601f8301126112e957600080fd5b8135818111156112f857600080fd5b88602082850101111561130a57600080fd5b95989497505060200194505050565b60006020828403121561132b57600080fd5b5035919050565b60006020828403121561134457600080fd5b81356106e781611077565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113bf57600080fd5b815167ffffffffffffffff808211156113d757600080fd5b818401915084601f8301126113eb57600080fd5b8151818111156113fd576113fd61137e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156114435761144361137e565b8160405282815287602084870101111561145c57600080fd5b61146d836020830160208801611148565b979650505050505050565b60006020828403121561148a57600080fd5b5051919050565b6000828210156114ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b84815283602082015281836040830137600091016040019081529392505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", } // DisputeGameFactoryABI is the input ABI used to generate the binding from. @@ -201,11 +210,42 @@ func (_DisputeGameFactory *DisputeGameFactoryTransactorRaw) Transact(opts *bind. return _DisputeGameFactory.Contract.contract.Transact(opts, method, params...) } +// FindLatestGames is a free data retrieval call binding the contract method 0x254bd683. +// +// Solidity: function findLatestGames(uint32 _gameType, uint256 _start, uint256 _n) view returns((uint256,bytes32,uint64,bytes32,bytes)[] games_) +func (_DisputeGameFactory *DisputeGameFactoryCaller) FindLatestGames(opts *bind.CallOpts, _gameType uint32, _start *big.Int, _n *big.Int) ([]IDisputeGameFactoryGameSearchResult, error) { + var out []interface{} + err := _DisputeGameFactory.contract.Call(opts, &out, "findLatestGames", _gameType, _start, _n) + + if err != nil { + return *new([]IDisputeGameFactoryGameSearchResult), err + } + + out0 := *abi.ConvertType(out[0], new([]IDisputeGameFactoryGameSearchResult)).(*[]IDisputeGameFactoryGameSearchResult) + + return out0, err + +} + +// FindLatestGames is a free data retrieval call binding the contract method 0x254bd683. +// +// Solidity: function findLatestGames(uint32 _gameType, uint256 _start, uint256 _n) view returns((uint256,bytes32,uint64,bytes32,bytes)[] games_) +func (_DisputeGameFactory *DisputeGameFactorySession) FindLatestGames(_gameType uint32, _start *big.Int, _n *big.Int) ([]IDisputeGameFactoryGameSearchResult, error) { + return _DisputeGameFactory.Contract.FindLatestGames(&_DisputeGameFactory.CallOpts, _gameType, _start, _n) +} + +// FindLatestGames is a free data retrieval call binding the contract method 0x254bd683. +// +// Solidity: function findLatestGames(uint32 _gameType, uint256 _start, uint256 _n) view returns((uint256,bytes32,uint64,bytes32,bytes)[] games_) +func (_DisputeGameFactory *DisputeGameFactoryCallerSession) FindLatestGames(_gameType uint32, _start *big.Int, _n *big.Int) ([]IDisputeGameFactoryGameSearchResult, error) { + return _DisputeGameFactory.Contract.FindLatestGames(&_DisputeGameFactory.CallOpts, _gameType, _start, _n) +} + // GameAtIndex is a free data retrieval call binding the contract method 0xbb8aa1fc. // -// Solidity: function gameAtIndex(uint256 _index) view returns(uint8 gameType_, uint64 timestamp_, address proxy_) +// Solidity: function gameAtIndex(uint256 _index) view returns(uint32 gameType_, uint64 timestamp_, address proxy_) func (_DisputeGameFactory *DisputeGameFactoryCaller) GameAtIndex(opts *bind.CallOpts, _index *big.Int) (struct { - GameType uint8 + GameType uint32 Timestamp uint64 Proxy common.Address }, error) { @@ -213,7 +253,7 @@ func (_DisputeGameFactory *DisputeGameFactoryCaller) GameAtIndex(opts *bind.Call err := _DisputeGameFactory.contract.Call(opts, &out, "gameAtIndex", _index) outstruct := new(struct { - GameType uint8 + GameType uint32 Timestamp uint64 Proxy common.Address }) @@ -221,7 +261,7 @@ func (_DisputeGameFactory *DisputeGameFactoryCaller) GameAtIndex(opts *bind.Call return *outstruct, err } - outstruct.GameType = *abi.ConvertType(out[0], new(uint8)).(*uint8) + outstruct.GameType = *abi.ConvertType(out[0], new(uint32)).(*uint32) outstruct.Timestamp = *abi.ConvertType(out[1], new(uint64)).(*uint64) outstruct.Proxy = *abi.ConvertType(out[2], new(common.Address)).(*common.Address) @@ -231,9 +271,9 @@ func (_DisputeGameFactory *DisputeGameFactoryCaller) GameAtIndex(opts *bind.Call // GameAtIndex is a free data retrieval call binding the contract method 0xbb8aa1fc. // -// Solidity: function gameAtIndex(uint256 _index) view returns(uint8 gameType_, uint64 timestamp_, address proxy_) +// Solidity: function gameAtIndex(uint256 _index) view returns(uint32 gameType_, uint64 timestamp_, address proxy_) func (_DisputeGameFactory *DisputeGameFactorySession) GameAtIndex(_index *big.Int) (struct { - GameType uint8 + GameType uint32 Timestamp uint64 Proxy common.Address }, error) { @@ -242,9 +282,9 @@ func (_DisputeGameFactory *DisputeGameFactorySession) GameAtIndex(_index *big.In // GameAtIndex is a free data retrieval call binding the contract method 0xbb8aa1fc. // -// Solidity: function gameAtIndex(uint256 _index) view returns(uint8 gameType_, uint64 timestamp_, address proxy_) +// Solidity: function gameAtIndex(uint256 _index) view returns(uint32 gameType_, uint64 timestamp_, address proxy_) func (_DisputeGameFactory *DisputeGameFactoryCallerSession) GameAtIndex(_index *big.Int) (struct { - GameType uint8 + GameType uint32 Timestamp uint64 Proxy common.Address }, error) { @@ -282,10 +322,10 @@ func (_DisputeGameFactory *DisputeGameFactoryCallerSession) GameCount() (*big.In return _DisputeGameFactory.Contract.GameCount(&_DisputeGameFactory.CallOpts) } -// GameImpls is a free data retrieval call binding the contract method 0xdfa162d3. +// GameImpls is a free data retrieval call binding the contract method 0x1b685b9e. // -// Solidity: function gameImpls(uint8 ) view returns(address) -func (_DisputeGameFactory *DisputeGameFactoryCaller) GameImpls(opts *bind.CallOpts, arg0 uint8) (common.Address, error) { +// Solidity: function gameImpls(uint32 ) view returns(address) +func (_DisputeGameFactory *DisputeGameFactoryCaller) GameImpls(opts *bind.CallOpts, arg0 uint32) (common.Address, error) { var out []interface{} err := _DisputeGameFactory.contract.Call(opts, &out, "gameImpls", arg0) @@ -299,24 +339,24 @@ func (_DisputeGameFactory *DisputeGameFactoryCaller) GameImpls(opts *bind.CallOp } -// GameImpls is a free data retrieval call binding the contract method 0xdfa162d3. +// GameImpls is a free data retrieval call binding the contract method 0x1b685b9e. // -// Solidity: function gameImpls(uint8 ) view returns(address) -func (_DisputeGameFactory *DisputeGameFactorySession) GameImpls(arg0 uint8) (common.Address, error) { +// Solidity: function gameImpls(uint32 ) view returns(address) +func (_DisputeGameFactory *DisputeGameFactorySession) GameImpls(arg0 uint32) (common.Address, error) { return _DisputeGameFactory.Contract.GameImpls(&_DisputeGameFactory.CallOpts, arg0) } -// GameImpls is a free data retrieval call binding the contract method 0xdfa162d3. +// GameImpls is a free data retrieval call binding the contract method 0x1b685b9e. // -// Solidity: function gameImpls(uint8 ) view returns(address) -func (_DisputeGameFactory *DisputeGameFactoryCallerSession) GameImpls(arg0 uint8) (common.Address, error) { +// Solidity: function gameImpls(uint32 ) view returns(address) +func (_DisputeGameFactory *DisputeGameFactoryCallerSession) GameImpls(arg0 uint32) (common.Address, error) { return _DisputeGameFactory.Contract.GameImpls(&_DisputeGameFactory.CallOpts, arg0) } -// Games is a free data retrieval call binding the contract method 0xc49d5271. +// Games is a free data retrieval call binding the contract method 0x5f0150cb. // -// Solidity: function games(uint8 _gameType, bytes32 _rootClaim, bytes _extraData) view returns(address proxy_, uint64 timestamp_) -func (_DisputeGameFactory *DisputeGameFactoryCaller) Games(opts *bind.CallOpts, _gameType uint8, _rootClaim [32]byte, _extraData []byte) (struct { +// Solidity: function games(uint32 _gameType, bytes32 _rootClaim, bytes _extraData) view returns(address proxy_, uint64 timestamp_) +func (_DisputeGameFactory *DisputeGameFactoryCaller) Games(opts *bind.CallOpts, _gameType uint32, _rootClaim [32]byte, _extraData []byte) (struct { Proxy common.Address Timestamp uint64 }, error) { @@ -338,30 +378,30 @@ func (_DisputeGameFactory *DisputeGameFactoryCaller) Games(opts *bind.CallOpts, } -// Games is a free data retrieval call binding the contract method 0xc49d5271. +// Games is a free data retrieval call binding the contract method 0x5f0150cb. // -// Solidity: function games(uint8 _gameType, bytes32 _rootClaim, bytes _extraData) view returns(address proxy_, uint64 timestamp_) -func (_DisputeGameFactory *DisputeGameFactorySession) Games(_gameType uint8, _rootClaim [32]byte, _extraData []byte) (struct { +// Solidity: function games(uint32 _gameType, bytes32 _rootClaim, bytes _extraData) view returns(address proxy_, uint64 timestamp_) +func (_DisputeGameFactory *DisputeGameFactorySession) Games(_gameType uint32, _rootClaim [32]byte, _extraData []byte) (struct { Proxy common.Address Timestamp uint64 }, error) { return _DisputeGameFactory.Contract.Games(&_DisputeGameFactory.CallOpts, _gameType, _rootClaim, _extraData) } -// Games is a free data retrieval call binding the contract method 0xc49d5271. +// Games is a free data retrieval call binding the contract method 0x5f0150cb. // -// Solidity: function games(uint8 _gameType, bytes32 _rootClaim, bytes _extraData) view returns(address proxy_, uint64 timestamp_) -func (_DisputeGameFactory *DisputeGameFactoryCallerSession) Games(_gameType uint8, _rootClaim [32]byte, _extraData []byte) (struct { +// Solidity: function games(uint32 _gameType, bytes32 _rootClaim, bytes _extraData) view returns(address proxy_, uint64 timestamp_) +func (_DisputeGameFactory *DisputeGameFactoryCallerSession) Games(_gameType uint32, _rootClaim [32]byte, _extraData []byte) (struct { Proxy common.Address Timestamp uint64 }, error) { return _DisputeGameFactory.Contract.Games(&_DisputeGameFactory.CallOpts, _gameType, _rootClaim, _extraData) } -// GetGameUUID is a free data retrieval call binding the contract method 0x26daafbe. +// GetGameUUID is a free data retrieval call binding the contract method 0x96cd9720. // -// Solidity: function getGameUUID(uint8 _gameType, bytes32 _rootClaim, bytes _extraData) pure returns(bytes32 uuid_) -func (_DisputeGameFactory *DisputeGameFactoryCaller) GetGameUUID(opts *bind.CallOpts, _gameType uint8, _rootClaim [32]byte, _extraData []byte) ([32]byte, error) { +// Solidity: function getGameUUID(uint32 _gameType, bytes32 _rootClaim, bytes _extraData) pure returns(bytes32 uuid_) +func (_DisputeGameFactory *DisputeGameFactoryCaller) GetGameUUID(opts *bind.CallOpts, _gameType uint32, _rootClaim [32]byte, _extraData []byte) ([32]byte, error) { var out []interface{} err := _DisputeGameFactory.contract.Call(opts, &out, "getGameUUID", _gameType, _rootClaim, _extraData) @@ -375,24 +415,24 @@ func (_DisputeGameFactory *DisputeGameFactoryCaller) GetGameUUID(opts *bind.Call } -// GetGameUUID is a free data retrieval call binding the contract method 0x26daafbe. +// GetGameUUID is a free data retrieval call binding the contract method 0x96cd9720. // -// Solidity: function getGameUUID(uint8 _gameType, bytes32 _rootClaim, bytes _extraData) pure returns(bytes32 uuid_) -func (_DisputeGameFactory *DisputeGameFactorySession) GetGameUUID(_gameType uint8, _rootClaim [32]byte, _extraData []byte) ([32]byte, error) { +// Solidity: function getGameUUID(uint32 _gameType, bytes32 _rootClaim, bytes _extraData) pure returns(bytes32 uuid_) +func (_DisputeGameFactory *DisputeGameFactorySession) GetGameUUID(_gameType uint32, _rootClaim [32]byte, _extraData []byte) ([32]byte, error) { return _DisputeGameFactory.Contract.GetGameUUID(&_DisputeGameFactory.CallOpts, _gameType, _rootClaim, _extraData) } -// GetGameUUID is a free data retrieval call binding the contract method 0x26daafbe. +// GetGameUUID is a free data retrieval call binding the contract method 0x96cd9720. // -// Solidity: function getGameUUID(uint8 _gameType, bytes32 _rootClaim, bytes _extraData) pure returns(bytes32 uuid_) -func (_DisputeGameFactory *DisputeGameFactoryCallerSession) GetGameUUID(_gameType uint8, _rootClaim [32]byte, _extraData []byte) ([32]byte, error) { +// Solidity: function getGameUUID(uint32 _gameType, bytes32 _rootClaim, bytes _extraData) pure returns(bytes32 uuid_) +func (_DisputeGameFactory *DisputeGameFactoryCallerSession) GetGameUUID(_gameType uint32, _rootClaim [32]byte, _extraData []byte) ([32]byte, error) { return _DisputeGameFactory.Contract.GetGameUUID(&_DisputeGameFactory.CallOpts, _gameType, _rootClaim, _extraData) } -// InitBonds is a free data retrieval call binding the contract method 0xed8bc95d. +// InitBonds is a free data retrieval call binding the contract method 0x6593dc6e. // -// Solidity: function initBonds(uint8 ) view returns(uint256) -func (_DisputeGameFactory *DisputeGameFactoryCaller) InitBonds(opts *bind.CallOpts, arg0 uint8) (*big.Int, error) { +// Solidity: function initBonds(uint32 ) view returns(uint256) +func (_DisputeGameFactory *DisputeGameFactoryCaller) InitBonds(opts *bind.CallOpts, arg0 uint32) (*big.Int, error) { var out []interface{} err := _DisputeGameFactory.contract.Call(opts, &out, "initBonds", arg0) @@ -406,17 +446,17 @@ func (_DisputeGameFactory *DisputeGameFactoryCaller) InitBonds(opts *bind.CallOp } -// InitBonds is a free data retrieval call binding the contract method 0xed8bc95d. +// InitBonds is a free data retrieval call binding the contract method 0x6593dc6e. // -// Solidity: function initBonds(uint8 ) view returns(uint256) -func (_DisputeGameFactory *DisputeGameFactorySession) InitBonds(arg0 uint8) (*big.Int, error) { +// Solidity: function initBonds(uint32 ) view returns(uint256) +func (_DisputeGameFactory *DisputeGameFactorySession) InitBonds(arg0 uint32) (*big.Int, error) { return _DisputeGameFactory.Contract.InitBonds(&_DisputeGameFactory.CallOpts, arg0) } -// InitBonds is a free data retrieval call binding the contract method 0xed8bc95d. +// InitBonds is a free data retrieval call binding the contract method 0x6593dc6e. // -// Solidity: function initBonds(uint8 ) view returns(uint256) -func (_DisputeGameFactory *DisputeGameFactoryCallerSession) InitBonds(arg0 uint8) (*big.Int, error) { +// Solidity: function initBonds(uint32 ) view returns(uint256) +func (_DisputeGameFactory *DisputeGameFactoryCallerSession) InitBonds(arg0 uint32) (*big.Int, error) { return _DisputeGameFactory.Contract.InitBonds(&_DisputeGameFactory.CallOpts, arg0) } @@ -482,24 +522,24 @@ func (_DisputeGameFactory *DisputeGameFactoryCallerSession) Version() (string, e return _DisputeGameFactory.Contract.Version(&_DisputeGameFactory.CallOpts) } -// Create is a paid mutator transaction binding the contract method 0x3142e55e. +// Create is a paid mutator transaction binding the contract method 0x82ecf2f6. // -// Solidity: function create(uint8 _gameType, bytes32 _rootClaim, bytes _extraData) payable returns(address proxy_) -func (_DisputeGameFactory *DisputeGameFactoryTransactor) Create(opts *bind.TransactOpts, _gameType uint8, _rootClaim [32]byte, _extraData []byte) (*types.Transaction, error) { +// Solidity: function create(uint32 _gameType, bytes32 _rootClaim, bytes _extraData) payable returns(address proxy_) +func (_DisputeGameFactory *DisputeGameFactoryTransactor) Create(opts *bind.TransactOpts, _gameType uint32, _rootClaim [32]byte, _extraData []byte) (*types.Transaction, error) { return _DisputeGameFactory.contract.Transact(opts, "create", _gameType, _rootClaim, _extraData) } -// Create is a paid mutator transaction binding the contract method 0x3142e55e. +// Create is a paid mutator transaction binding the contract method 0x82ecf2f6. // -// Solidity: function create(uint8 _gameType, bytes32 _rootClaim, bytes _extraData) payable returns(address proxy_) -func (_DisputeGameFactory *DisputeGameFactorySession) Create(_gameType uint8, _rootClaim [32]byte, _extraData []byte) (*types.Transaction, error) { +// Solidity: function create(uint32 _gameType, bytes32 _rootClaim, bytes _extraData) payable returns(address proxy_) +func (_DisputeGameFactory *DisputeGameFactorySession) Create(_gameType uint32, _rootClaim [32]byte, _extraData []byte) (*types.Transaction, error) { return _DisputeGameFactory.Contract.Create(&_DisputeGameFactory.TransactOpts, _gameType, _rootClaim, _extraData) } -// Create is a paid mutator transaction binding the contract method 0x3142e55e. +// Create is a paid mutator transaction binding the contract method 0x82ecf2f6. // -// Solidity: function create(uint8 _gameType, bytes32 _rootClaim, bytes _extraData) payable returns(address proxy_) -func (_DisputeGameFactory *DisputeGameFactoryTransactorSession) Create(_gameType uint8, _rootClaim [32]byte, _extraData []byte) (*types.Transaction, error) { +// Solidity: function create(uint32 _gameType, bytes32 _rootClaim, bytes _extraData) payable returns(address proxy_) +func (_DisputeGameFactory *DisputeGameFactoryTransactorSession) Create(_gameType uint32, _rootClaim [32]byte, _extraData []byte) (*types.Transaction, error) { return _DisputeGameFactory.Contract.Create(&_DisputeGameFactory.TransactOpts, _gameType, _rootClaim, _extraData) } @@ -545,45 +585,45 @@ func (_DisputeGameFactory *DisputeGameFactoryTransactorSession) RenounceOwnershi return _DisputeGameFactory.Contract.RenounceOwnership(&_DisputeGameFactory.TransactOpts) } -// SetImplementation is a paid mutator transaction binding the contract method 0x45583b7a. +// SetImplementation is a paid mutator transaction binding the contract method 0x14f6b1a3. // -// Solidity: function setImplementation(uint8 _gameType, address _impl) returns() -func (_DisputeGameFactory *DisputeGameFactoryTransactor) SetImplementation(opts *bind.TransactOpts, _gameType uint8, _impl common.Address) (*types.Transaction, error) { +// Solidity: function setImplementation(uint32 _gameType, address _impl) returns() +func (_DisputeGameFactory *DisputeGameFactoryTransactor) SetImplementation(opts *bind.TransactOpts, _gameType uint32, _impl common.Address) (*types.Transaction, error) { return _DisputeGameFactory.contract.Transact(opts, "setImplementation", _gameType, _impl) } -// SetImplementation is a paid mutator transaction binding the contract method 0x45583b7a. +// SetImplementation is a paid mutator transaction binding the contract method 0x14f6b1a3. // -// Solidity: function setImplementation(uint8 _gameType, address _impl) returns() -func (_DisputeGameFactory *DisputeGameFactorySession) SetImplementation(_gameType uint8, _impl common.Address) (*types.Transaction, error) { +// Solidity: function setImplementation(uint32 _gameType, address _impl) returns() +func (_DisputeGameFactory *DisputeGameFactorySession) SetImplementation(_gameType uint32, _impl common.Address) (*types.Transaction, error) { return _DisputeGameFactory.Contract.SetImplementation(&_DisputeGameFactory.TransactOpts, _gameType, _impl) } -// SetImplementation is a paid mutator transaction binding the contract method 0x45583b7a. +// SetImplementation is a paid mutator transaction binding the contract method 0x14f6b1a3. // -// Solidity: function setImplementation(uint8 _gameType, address _impl) returns() -func (_DisputeGameFactory *DisputeGameFactoryTransactorSession) SetImplementation(_gameType uint8, _impl common.Address) (*types.Transaction, error) { +// Solidity: function setImplementation(uint32 _gameType, address _impl) returns() +func (_DisputeGameFactory *DisputeGameFactoryTransactorSession) SetImplementation(_gameType uint32, _impl common.Address) (*types.Transaction, error) { return _DisputeGameFactory.Contract.SetImplementation(&_DisputeGameFactory.TransactOpts, _gameType, _impl) } -// SetInitBond is a paid mutator transaction binding the contract method 0xc018126b. +// SetInitBond is a paid mutator transaction binding the contract method 0x1e334240. // -// Solidity: function setInitBond(uint8 _gameType, uint256 _initBond) returns() -func (_DisputeGameFactory *DisputeGameFactoryTransactor) SetInitBond(opts *bind.TransactOpts, _gameType uint8, _initBond *big.Int) (*types.Transaction, error) { +// Solidity: function setInitBond(uint32 _gameType, uint256 _initBond) returns() +func (_DisputeGameFactory *DisputeGameFactoryTransactor) SetInitBond(opts *bind.TransactOpts, _gameType uint32, _initBond *big.Int) (*types.Transaction, error) { return _DisputeGameFactory.contract.Transact(opts, "setInitBond", _gameType, _initBond) } -// SetInitBond is a paid mutator transaction binding the contract method 0xc018126b. +// SetInitBond is a paid mutator transaction binding the contract method 0x1e334240. // -// Solidity: function setInitBond(uint8 _gameType, uint256 _initBond) returns() -func (_DisputeGameFactory *DisputeGameFactorySession) SetInitBond(_gameType uint8, _initBond *big.Int) (*types.Transaction, error) { +// Solidity: function setInitBond(uint32 _gameType, uint256 _initBond) returns() +func (_DisputeGameFactory *DisputeGameFactorySession) SetInitBond(_gameType uint32, _initBond *big.Int) (*types.Transaction, error) { return _DisputeGameFactory.Contract.SetInitBond(&_DisputeGameFactory.TransactOpts, _gameType, _initBond) } -// SetInitBond is a paid mutator transaction binding the contract method 0xc018126b. +// SetInitBond is a paid mutator transaction binding the contract method 0x1e334240. // -// Solidity: function setInitBond(uint8 _gameType, uint256 _initBond) returns() -func (_DisputeGameFactory *DisputeGameFactoryTransactorSession) SetInitBond(_gameType uint8, _initBond *big.Int) (*types.Transaction, error) { +// Solidity: function setInitBond(uint32 _gameType, uint256 _initBond) returns() +func (_DisputeGameFactory *DisputeGameFactoryTransactorSession) SetInitBond(_gameType uint32, _initBond *big.Int) (*types.Transaction, error) { return _DisputeGameFactory.Contract.SetInitBond(&_DisputeGameFactory.TransactOpts, _gameType, _initBond) } @@ -678,15 +718,15 @@ func (it *DisputeGameFactoryDisputeGameCreatedIterator) Close() error { // DisputeGameFactoryDisputeGameCreated represents a DisputeGameCreated event raised by the DisputeGameFactory contract. type DisputeGameFactoryDisputeGameCreated struct { DisputeProxy common.Address - GameType uint8 + GameType uint32 RootClaim [32]byte Raw types.Log // Blockchain specific contextual infos } -// FilterDisputeGameCreated is a free log retrieval operation binding the contract event 0xfad0599ff449d8d9685eadecca8cb9e00924c5fd8367c1c09469824939e1ffec. +// FilterDisputeGameCreated is a free log retrieval operation binding the contract event 0x5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e35. // -// Solidity: event DisputeGameCreated(address indexed disputeProxy, uint8 indexed gameType, bytes32 indexed rootClaim) -func (_DisputeGameFactory *DisputeGameFactoryFilterer) FilterDisputeGameCreated(opts *bind.FilterOpts, disputeProxy []common.Address, gameType []uint8, rootClaim [][32]byte) (*DisputeGameFactoryDisputeGameCreatedIterator, error) { +// Solidity: event DisputeGameCreated(address indexed disputeProxy, uint32 indexed gameType, bytes32 indexed rootClaim) +func (_DisputeGameFactory *DisputeGameFactoryFilterer) FilterDisputeGameCreated(opts *bind.FilterOpts, disputeProxy []common.Address, gameType []uint32, rootClaim [][32]byte) (*DisputeGameFactoryDisputeGameCreatedIterator, error) { var disputeProxyRule []interface{} for _, disputeProxyItem := range disputeProxy { @@ -708,10 +748,10 @@ func (_DisputeGameFactory *DisputeGameFactoryFilterer) FilterDisputeGameCreated( return &DisputeGameFactoryDisputeGameCreatedIterator{contract: _DisputeGameFactory.contract, event: "DisputeGameCreated", logs: logs, sub: sub}, nil } -// WatchDisputeGameCreated is a free log subscription operation binding the contract event 0xfad0599ff449d8d9685eadecca8cb9e00924c5fd8367c1c09469824939e1ffec. +// WatchDisputeGameCreated is a free log subscription operation binding the contract event 0x5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e35. // -// Solidity: event DisputeGameCreated(address indexed disputeProxy, uint8 indexed gameType, bytes32 indexed rootClaim) -func (_DisputeGameFactory *DisputeGameFactoryFilterer) WatchDisputeGameCreated(opts *bind.WatchOpts, sink chan<- *DisputeGameFactoryDisputeGameCreated, disputeProxy []common.Address, gameType []uint8, rootClaim [][32]byte) (event.Subscription, error) { +// Solidity: event DisputeGameCreated(address indexed disputeProxy, uint32 indexed gameType, bytes32 indexed rootClaim) +func (_DisputeGameFactory *DisputeGameFactoryFilterer) WatchDisputeGameCreated(opts *bind.WatchOpts, sink chan<- *DisputeGameFactoryDisputeGameCreated, disputeProxy []common.Address, gameType []uint32, rootClaim [][32]byte) (event.Subscription, error) { var disputeProxyRule []interface{} for _, disputeProxyItem := range disputeProxy { @@ -758,9 +798,9 @@ func (_DisputeGameFactory *DisputeGameFactoryFilterer) WatchDisputeGameCreated(o }), nil } -// ParseDisputeGameCreated is a log parse operation binding the contract event 0xfad0599ff449d8d9685eadecca8cb9e00924c5fd8367c1c09469824939e1ffec. +// ParseDisputeGameCreated is a log parse operation binding the contract event 0x5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e35. // -// Solidity: event DisputeGameCreated(address indexed disputeProxy, uint8 indexed gameType, bytes32 indexed rootClaim) +// Solidity: event DisputeGameCreated(address indexed disputeProxy, uint32 indexed gameType, bytes32 indexed rootClaim) func (_DisputeGameFactory *DisputeGameFactoryFilterer) ParseDisputeGameCreated(log types.Log) (*DisputeGameFactoryDisputeGameCreated, error) { event := new(DisputeGameFactoryDisputeGameCreated) if err := _DisputeGameFactory.contract.UnpackLog(event, "DisputeGameCreated", log); err != nil { @@ -840,14 +880,14 @@ func (it *DisputeGameFactoryImplementationSetIterator) Close() error { // DisputeGameFactoryImplementationSet represents a ImplementationSet event raised by the DisputeGameFactory contract. type DisputeGameFactoryImplementationSet struct { Impl common.Address - GameType uint8 + GameType uint32 Raw types.Log // Blockchain specific contextual infos } -// FilterImplementationSet is a free log retrieval operation binding the contract event 0x623713f72f6e427a8044bb8b3bd6834357cf285decbaa21bcc73c1d0632c4d84. +// FilterImplementationSet is a free log retrieval operation binding the contract event 0xff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de. // -// Solidity: event ImplementationSet(address indexed impl, uint8 indexed gameType) -func (_DisputeGameFactory *DisputeGameFactoryFilterer) FilterImplementationSet(opts *bind.FilterOpts, impl []common.Address, gameType []uint8) (*DisputeGameFactoryImplementationSetIterator, error) { +// Solidity: event ImplementationSet(address indexed impl, uint32 indexed gameType) +func (_DisputeGameFactory *DisputeGameFactoryFilterer) FilterImplementationSet(opts *bind.FilterOpts, impl []common.Address, gameType []uint32) (*DisputeGameFactoryImplementationSetIterator, error) { var implRule []interface{} for _, implItem := range impl { @@ -865,10 +905,10 @@ func (_DisputeGameFactory *DisputeGameFactoryFilterer) FilterImplementationSet(o return &DisputeGameFactoryImplementationSetIterator{contract: _DisputeGameFactory.contract, event: "ImplementationSet", logs: logs, sub: sub}, nil } -// WatchImplementationSet is a free log subscription operation binding the contract event 0x623713f72f6e427a8044bb8b3bd6834357cf285decbaa21bcc73c1d0632c4d84. +// WatchImplementationSet is a free log subscription operation binding the contract event 0xff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de. // -// Solidity: event ImplementationSet(address indexed impl, uint8 indexed gameType) -func (_DisputeGameFactory *DisputeGameFactoryFilterer) WatchImplementationSet(opts *bind.WatchOpts, sink chan<- *DisputeGameFactoryImplementationSet, impl []common.Address, gameType []uint8) (event.Subscription, error) { +// Solidity: event ImplementationSet(address indexed impl, uint32 indexed gameType) +func (_DisputeGameFactory *DisputeGameFactoryFilterer) WatchImplementationSet(opts *bind.WatchOpts, sink chan<- *DisputeGameFactoryImplementationSet, impl []common.Address, gameType []uint32) (event.Subscription, error) { var implRule []interface{} for _, implItem := range impl { @@ -911,9 +951,9 @@ func (_DisputeGameFactory *DisputeGameFactoryFilterer) WatchImplementationSet(op }), nil } -// ParseImplementationSet is a log parse operation binding the contract event 0x623713f72f6e427a8044bb8b3bd6834357cf285decbaa21bcc73c1d0632c4d84. +// ParseImplementationSet is a log parse operation binding the contract event 0xff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de. // -// Solidity: event ImplementationSet(address indexed impl, uint8 indexed gameType) +// Solidity: event ImplementationSet(address indexed impl, uint32 indexed gameType) func (_DisputeGameFactory *DisputeGameFactoryFilterer) ParseImplementationSet(log types.Log) (*DisputeGameFactoryImplementationSet, error) { event := new(DisputeGameFactoryImplementationSet) if err := _DisputeGameFactory.contract.UnpackLog(event, "ImplementationSet", log); err != nil { @@ -992,15 +1032,15 @@ func (it *DisputeGameFactoryInitBondUpdatedIterator) Close() error { // DisputeGameFactoryInitBondUpdated represents a InitBondUpdated event raised by the DisputeGameFactory contract. type DisputeGameFactoryInitBondUpdated struct { - GameType uint8 + GameType uint32 NewBond *big.Int Raw types.Log // Blockchain specific contextual infos } -// FilterInitBondUpdated is a free log retrieval operation binding the contract event 0x3d3603f30a8e965cf76ec29fb1f0563457ec8a7114c12180c60e7be8384201f1. +// FilterInitBondUpdated is a free log retrieval operation binding the contract event 0x74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca. // -// Solidity: event InitBondUpdated(uint8 indexed gameType, uint256 indexed newBond) -func (_DisputeGameFactory *DisputeGameFactoryFilterer) FilterInitBondUpdated(opts *bind.FilterOpts, gameType []uint8, newBond []*big.Int) (*DisputeGameFactoryInitBondUpdatedIterator, error) { +// Solidity: event InitBondUpdated(uint32 indexed gameType, uint256 indexed newBond) +func (_DisputeGameFactory *DisputeGameFactoryFilterer) FilterInitBondUpdated(opts *bind.FilterOpts, gameType []uint32, newBond []*big.Int) (*DisputeGameFactoryInitBondUpdatedIterator, error) { var gameTypeRule []interface{} for _, gameTypeItem := range gameType { @@ -1018,10 +1058,10 @@ func (_DisputeGameFactory *DisputeGameFactoryFilterer) FilterInitBondUpdated(opt return &DisputeGameFactoryInitBondUpdatedIterator{contract: _DisputeGameFactory.contract, event: "InitBondUpdated", logs: logs, sub: sub}, nil } -// WatchInitBondUpdated is a free log subscription operation binding the contract event 0x3d3603f30a8e965cf76ec29fb1f0563457ec8a7114c12180c60e7be8384201f1. +// WatchInitBondUpdated is a free log subscription operation binding the contract event 0x74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca. // -// Solidity: event InitBondUpdated(uint8 indexed gameType, uint256 indexed newBond) -func (_DisputeGameFactory *DisputeGameFactoryFilterer) WatchInitBondUpdated(opts *bind.WatchOpts, sink chan<- *DisputeGameFactoryInitBondUpdated, gameType []uint8, newBond []*big.Int) (event.Subscription, error) { +// Solidity: event InitBondUpdated(uint32 indexed gameType, uint256 indexed newBond) +func (_DisputeGameFactory *DisputeGameFactoryFilterer) WatchInitBondUpdated(opts *bind.WatchOpts, sink chan<- *DisputeGameFactoryInitBondUpdated, gameType []uint32, newBond []*big.Int) (event.Subscription, error) { var gameTypeRule []interface{} for _, gameTypeItem := range gameType { @@ -1064,9 +1104,9 @@ func (_DisputeGameFactory *DisputeGameFactoryFilterer) WatchInitBondUpdated(opts }), nil } -// ParseInitBondUpdated is a log parse operation binding the contract event 0x3d3603f30a8e965cf76ec29fb1f0563457ec8a7114c12180c60e7be8384201f1. +// ParseInitBondUpdated is a log parse operation binding the contract event 0x74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca. // -// Solidity: event InitBondUpdated(uint8 indexed gameType, uint256 indexed newBond) +// Solidity: event InitBondUpdated(uint32 indexed gameType, uint256 indexed newBond) func (_DisputeGameFactory *DisputeGameFactoryFilterer) ParseInitBondUpdated(log types.Log) (*DisputeGameFactoryInitBondUpdated, error) { event := new(DisputeGameFactoryInitBondUpdated) if err := _DisputeGameFactory.contract.UnpackLog(event, "InitBondUpdated", log); err != nil { diff --git a/op-bindings/bindings/disputegamefactory_more.go b/op-bindings/bindings/disputegamefactory_more.go index 9d4b068ddaa2..2b84757b3efd 100644 --- a/op-bindings/bindings/disputegamefactory_more.go +++ b/op-bindings/bindings/disputegamefactory_more.go @@ -9,11 +9,11 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const DisputeGameFactoryStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1002,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)50_storage\"},{\"astId\":1003,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":1004,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":1005,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"gameImpls\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_mapping(t_userDefinedValueType(GameType)1011,t_contract(IDisputeGame)1009)\"},{\"astId\":1006,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"initBonds\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_mapping(t_userDefinedValueType(GameType)1011,t_uint256)\"},{\"astId\":1007,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"_disputeGames\",\"offset\":0,\"slot\":\"103\",\"type\":\"t_mapping(t_userDefinedValueType(Hash)1012,t_userDefinedValueType(GameId)1010)\"},{\"astId\":1008,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"_disputeGameList\",\"offset\":0,\"slot\":\"104\",\"type\":\"t_array(t_userDefinedValueType(GameId)1010)dyn_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\",\"base\":\"t_uint256\"},\"t_array(t_uint256)50_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\",\"base\":\"t_uint256\"},\"t_array(t_userDefinedValueType(GameId)1010)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"GameId[]\",\"numberOfBytes\":\"32\",\"base\":\"t_userDefinedValueType(GameId)1010\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_contract(IDisputeGame)1009\":{\"encoding\":\"inplace\",\"label\":\"contract IDisputeGame\",\"numberOfBytes\":\"20\"},\"t_mapping(t_userDefinedValueType(GameType)1011,t_contract(IDisputeGame)1009)\":{\"encoding\":\"mapping\",\"label\":\"mapping(GameType =\u003e contract IDisputeGame)\",\"numberOfBytes\":\"32\",\"key\":\"t_userDefinedValueType(GameType)1011\",\"value\":\"t_contract(IDisputeGame)1009\"},\"t_mapping(t_userDefinedValueType(GameType)1011,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(GameType =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_userDefinedValueType(GameType)1011\",\"value\":\"t_uint256\"},\"t_mapping(t_userDefinedValueType(Hash)1012,t_userDefinedValueType(GameId)1010)\":{\"encoding\":\"mapping\",\"label\":\"mapping(Hash =\u003e GameId)\",\"numberOfBytes\":\"32\",\"key\":\"t_userDefinedValueType(Hash)1012\",\"value\":\"t_userDefinedValueType(GameId)1010\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"},\"t_userDefinedValueType(GameId)1010\":{\"encoding\":\"inplace\",\"label\":\"GameId\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(GameType)1011\":{\"encoding\":\"inplace\",\"label\":\"GameType\",\"numberOfBytes\":\"1\"},\"t_userDefinedValueType(Hash)1012\":{\"encoding\":\"inplace\",\"label\":\"Hash\",\"numberOfBytes\":\"32\"}}}" +const DisputeGameFactoryStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1002,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)50_storage\"},{\"astId\":1003,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":1004,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":1005,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"gameImpls\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_mapping(t_userDefinedValueType(GameType)1011,t_contract(IDisputeGame)1009)\"},{\"astId\":1006,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"initBonds\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_mapping(t_userDefinedValueType(GameType)1011,t_uint256)\"},{\"astId\":1007,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"_disputeGames\",\"offset\":0,\"slot\":\"103\",\"type\":\"t_mapping(t_userDefinedValueType(Hash)1012,t_userDefinedValueType(GameId)1010)\"},{\"astId\":1008,\"contract\":\"src/dispute/DisputeGameFactory.sol:DisputeGameFactory\",\"label\":\"_disputeGameList\",\"offset\":0,\"slot\":\"104\",\"type\":\"t_array(t_userDefinedValueType(GameId)1010)dyn_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\",\"base\":\"t_uint256\"},\"t_array(t_uint256)50_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\",\"base\":\"t_uint256\"},\"t_array(t_userDefinedValueType(GameId)1010)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"GameId[]\",\"numberOfBytes\":\"32\",\"base\":\"t_userDefinedValueType(GameId)1010\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_contract(IDisputeGame)1009\":{\"encoding\":\"inplace\",\"label\":\"contract IDisputeGame\",\"numberOfBytes\":\"20\"},\"t_mapping(t_userDefinedValueType(GameType)1011,t_contract(IDisputeGame)1009)\":{\"encoding\":\"mapping\",\"label\":\"mapping(GameType =\u003e contract IDisputeGame)\",\"numberOfBytes\":\"32\",\"key\":\"t_userDefinedValueType(GameType)1011\",\"value\":\"t_contract(IDisputeGame)1009\"},\"t_mapping(t_userDefinedValueType(GameType)1011,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(GameType =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_userDefinedValueType(GameType)1011\",\"value\":\"t_uint256\"},\"t_mapping(t_userDefinedValueType(Hash)1012,t_userDefinedValueType(GameId)1010)\":{\"encoding\":\"mapping\",\"label\":\"mapping(Hash =\u003e GameId)\",\"numberOfBytes\":\"32\",\"key\":\"t_userDefinedValueType(Hash)1012\",\"value\":\"t_userDefinedValueType(GameId)1010\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"},\"t_userDefinedValueType(GameId)1010\":{\"encoding\":\"inplace\",\"label\":\"GameId\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(GameType)1011\":{\"encoding\":\"inplace\",\"label\":\"GameType\",\"numberOfBytes\":\"4\"},\"t_userDefinedValueType(Hash)1012\":{\"encoding\":\"inplace\",\"label\":\"Hash\",\"numberOfBytes\":\"32\"}}}" var DisputeGameFactoryStorageLayout = new(solc.StorageLayout) -var DisputeGameFactoryDeployedBin = "0x6080604052600436106100dd5760003560e01c8063bb8aa1fc1161007f578063c4d66de811610059578063c4d66de8146102ed578063dfa162d31461030d578063ed8bc95d14610350578063f2fde38b1461037d57600080fd5b8063bb8aa1fc1461021a578063c018126b14610278578063c49d52711461029857600080fd5b80634d1975b4116100bb5780634d1975b41461016f57806354fd4d5014610184578063715018a6146101da5780638da5cb5b146101ef57600080fd5b806326daafbe146100e25780633142e55e1461011557806345583b7a1461014d575b600080fd5b3480156100ee57600080fd5b506101026100fd366004610dd4565b61039d565b6040519081526020015b60405180910390f35b610128610123366004610dd4565b6103d6565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010c565b34801561015957600080fd5b5061016d610168366004610e7d565b610650565b005b34801561017b57600080fd5b50606854610102565b34801561019057600080fd5b506101cd6040518060400160405280600581526020017f302e302e3800000000000000000000000000000000000000000000000000000081525081565b60405161010c9190610eb4565b3480156101e657600080fd5b5061016d6106d7565b3480156101fb57600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610128565b34801561022657600080fd5b5061023a610235366004610f27565b6106eb565b6040805160ff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff169082015260600161010c565b34801561028457600080fd5b5061016d610293366004610f40565b61074d565b3480156102a457600080fd5b506102b86102b3366004610dd4565b610796565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161010c565b3480156102f957600080fd5b5061016d610308366004610f6a565b6107e9565b34801561031957600080fd5b50610128610328366004610f8e565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b34801561035c57600080fd5b5061010261036b366004610f8e565b60666020526000908152604090205481565b34801561038957600080fd5b5061016d610398366004610f6a565b610985565b6000848484846040516020016103b69493929190610fa9565b604051602081830303815290604052805190602001209050949350505050565b60ff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff1680610440576040517f44265d6f00000000000000000000000000000000000000000000000000000000815260ff871660048201526024015b60405180910390fd5b60ff861660009081526066602052604090205434101561048c576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104ef8585856040516020016104a493929190611007565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff831690610a58565b91508173ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561053957600080fd5b505af115801561054d573d6000803e3d6000fd5b505050505060006105608787878761039d565b600081815260676020526040902054909150156105ac576040517f014f6fe500000000000000000000000000000000000000000000000000000000815260048101829052602401610437565b60004260b81b60f889901b178417600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250889160ff8b169173ffffffffffffffffffffffffffffffffffffffff8816917ffad0599ff449d8d9685eadecca8cb9e00924c5fd8367c1c09469824939e1ffec9190a4505050949350505050565b610658610b8c565b60ff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917f623713f72f6e427a8044bb8b3bd6834357cf285decbaa21bcc73c1d0632c4d8491a35050565b6106df610b8c565b6106e96000610c0d565b565b60008060006107406068858154811061070657610706611021565b906000526020600020015460f881901c9167ffffffffffffffff60b883901c169173ffffffffffffffffffffffffffffffffffffffff1690565b9196909550909350915050565b610755610b8c565b60ff8216600081815260666020526040808220849055518392917f3d3603f30a8e965cf76ec29fb1f0563457ec8a7114c12180c60e7be8384201f191a35050565b60008060006107a78787878761039d565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860b89190911c67ffffffffffffffff16975095505050505050565b600054610100900460ff16158080156108095750600054600160ff909116105b806108235750303b158015610823575060005460ff166001145b6108af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610437565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561090d57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610915610c84565b61091e82610c0d565b801561098157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b61098d610b8c565b73ffffffffffffffffffffffffffffffffffffffff8116610a30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610437565b610a3981610c0d565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60006002825101603f8101600a81036040518360581b8260e81b177f6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d7300001781528660601b601e8201527f5af43d3d93803e603357fd5bf300000000000000000000000000000000000000603282015285519150603f8101602087015b60208410610b1057805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09093019260209182019101610ad3565b517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602085900360031b1b16815260f085901b9083015282816000f0945084610b7d577febfef1880000000000000000000000000000000000000000000000000000000060005260206000fd5b90910160405250909392505050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610437565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610d1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610437565b6106e9600054610100900460ff16610db5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610437565b6106e933610c0d565b803560ff81168114610dcf57600080fd5b919050565b60008060008060608587031215610dea57600080fd5b610df385610dbe565b935060208501359250604085013567ffffffffffffffff80821115610e1757600080fd5b818701915087601f830112610e2b57600080fd5b813581811115610e3a57600080fd5b886020828501011115610e4c57600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610a3957600080fd5b60008060408385031215610e9057600080fd5b610e9983610dbe565b91506020830135610ea981610e5b565b809150509250929050565b600060208083528351808285015260005b81811015610ee157858101830151858201604001528201610ec5565b81811115610ef3576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600060208284031215610f3957600080fd5b5035919050565b60008060408385031215610f5357600080fd5b610f5c83610dbe565b946020939093013593505050565b600060208284031215610f7c57600080fd5b8135610f8781610e5b565b9392505050565b600060208284031215610fa057600080fd5b610f8782610dbe565b60ff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b838152818360208301376000910160200190815292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a" +var DisputeGameFactoryDeployedBin = "0x6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d610108366004611099565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110d0565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d6101973660046110eb565b61045e565b3480156101a857600080fd5b506101bc6101b7366004611115565b6104aa565b60405161017391906111c2565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600581526020017f302e322e3000000000000000000000000000000000000000000000000000000081525081565b604051610173919061127f565b34801561024a57600080fd5b5061025e610259366004611292565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110d0565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e3366004611292565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e366004611292565b6109ee565b34801561033f57600080fd5b5061035361034e366004611319565b610a27565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af366004611332565b610a89565b3480156103c057600080fd5b5061010d6103cf366004611332565b610c25565b6103dc610cf8565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610cf8565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f061134f565b600091825260209091200154905060e081901c67ffffffffffffffff60a083901c1673ffffffffffffffffffffffffffffffffffffffff831660ff808a16908416036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113ad565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106439190611478565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a516106859190611491565b815181106106955761069561134f565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ee565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610cf8565b6107536000610d79565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff8616600090815260666020526040902054341015610814576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610821600143611491565b4090506108898682878760405160200161083e94939291906114cf565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df0565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d357600080fd5b505af11580156108e7573d6000803e3d6000fd5b505050505060006108fa888888886109ee565b60008181526067602052604090205490915015610946576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a0794939291906114f0565b604051602081830303815290604052805190602001209050949350505050565b6000806000610a7c60688581548110610a4257610a4261134f565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9196909550909350915050565b600054610100900460ff1615808015610aa95750600054600160ff909116105b80610ac35750303b158015610ac3575060005460ff166001145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bad57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bb5610f24565b610bbe82610d79565b8015610c2157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c2d610cf8565b73ffffffffffffffffffffffffffffffffffffffff8116610cd0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610cd981610d79565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006002825101603f8101600a81036040518360581b8260e81b177f6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d7300001781528660601b601e8201527f5af43d3d93803e603357fd5bf300000000000000000000000000000000000000603282015285519150603f8101602087015b60208410610ea857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09093019260209182019101610e6b565b517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602085900360031b1b16815260f085901b9083015282816000f0945084610f15577febfef1880000000000000000000000000000000000000000000000000000000060005260206000fd5b90910160405250909392505050565b600054610100900460ff16610fbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753600054610100900460ff16611055576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d79565b803563ffffffff8116811461107257600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cd957600080fd5b600080604083850312156110ac57600080fd5b6110b58361105e565b915060208301356110c581611077565b809150509250929050565b6000602082840312156110e257600080fd5b6106e78261105e565b600080604083850312156110fe57600080fd5b6111078361105e565b946020939093013593505050565b60008060006060848603121561112a57600080fd5b6111338461105e565b95602085013595506040909401359392505050565b60005b8381101561116357818101518382015260200161114b565b83811115611172576000848401525b50505050565b60008151808452611190816020860160208601611148565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611271578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a09185018290529061125d81860183611178565b9689019694505050908601906001016111e9565b509098975050505050505050565b6020815260006106e76020830184611178565b600080600080606085870312156112a857600080fd5b6112b18561105e565b935060208501359250604085013567ffffffffffffffff808211156112d557600080fd5b818701915087601f8301126112e957600080fd5b8135818111156112f857600080fd5b88602082850101111561130a57600080fd5b95989497505060200194505050565b60006020828403121561132b57600080fd5b5035919050565b60006020828403121561134457600080fd5b81356106e781611077565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113bf57600080fd5b815167ffffffffffffffff808211156113d757600080fd5b818401915084601f8301126113eb57600080fd5b8151818111156113fd576113fd61137e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156114435761144361137e565b8160405282815287602084870101111561145c57600080fd5b61146d836020830160208801611148565b979650505050505050565b60006020828403121561148a57600080fd5b5051919050565b6000828210156114ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b84815283602082015281836040830137600091016040019081529392505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a" func init() { diff --git a/op-bindings/bindings/faultdisputegame.go b/op-bindings/bindings/faultdisputegame.go index f3e77cdd8d3f..48bfae7bf838 100644 --- a/op-bindings/bindings/faultdisputegame.go +++ b/op-bindings/bindings/faultdisputegame.go @@ -30,8 +30,8 @@ var ( // FaultDisputeGameMetaData contains all meta data concerning the FaultDisputeGame contract. var FaultDisputeGameMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint8\",\"internalType\":\"GameType\"},{\"name\":\"_absolutePrestate\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_genesisBlockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_genesisOutputRoot\",\"type\":\"bytes32\",\"internalType\":\"Hash\"},{\"name\":\"_maxGameDepth\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_splitDepth\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_gameDuration\",\"type\":\"uint64\",\"internalType\":\"Duration\"},{\"name\":\"_vm\",\"type\":\"address\",\"internalType\":\"contractIBigStepper\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"absolutePrestate\",\"inputs\":[],\"outputs\":[{\"name\":\"absolutePrestate_\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addLocalData\",\"inputs\":[{\"name\":\"_ident\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_execLeafIdx\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"attack\",\"inputs\":[{\"name\":\"_parentIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"claimCredit\",\"inputs\":[{\"name\":\"_recipient\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"claimData\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"parentIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"counteredBy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"bond\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"position\",\"type\":\"uint128\",\"internalType\":\"Position\"},{\"name\":\"clock\",\"type\":\"uint128\",\"internalType\":\"Clock\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"claimDataLen\",\"inputs\":[],\"outputs\":[{\"name\":\"len_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createdAt\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"Timestamp\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"credit\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"defend\",\"inputs\":[{\"name\":\"_parentIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"extraData\",\"inputs\":[],\"outputs\":[{\"name\":\"extraData_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"gameData\",\"inputs\":[],\"outputs\":[{\"name\":\"gameType_\",\"type\":\"uint8\",\"internalType\":\"GameType\"},{\"name\":\"rootClaim_\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"extraData_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gameDuration\",\"inputs\":[],\"outputs\":[{\"name\":\"gameDuration_\",\"type\":\"uint64\",\"internalType\":\"Duration\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gameType\",\"inputs\":[],\"outputs\":[{\"name\":\"gameType_\",\"type\":\"uint8\",\"internalType\":\"GameType\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"genesisBlockNumber\",\"inputs\":[],\"outputs\":[{\"name\":\"genesisBlockNumber_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"genesisOutputRoot\",\"inputs\":[],\"outputs\":[{\"name\":\"genesisOutputRoot_\",\"type\":\"bytes32\",\"internalType\":\"Hash\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRequiredBond\",\"inputs\":[{\"name\":\"_position\",\"type\":\"uint128\",\"internalType\":\"Position\"}],\"outputs\":[{\"name\":\"requiredBond_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"l1Head\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"Hash\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"l2BlockNumber\",\"inputs\":[],\"outputs\":[{\"name\":\"l2BlockNumber_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"maxGameDepth\",\"inputs\":[],\"outputs\":[{\"name\":\"maxGameDepth_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"move\",\"inputs\":[{\"name\":\"_challengeIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_isAttack\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"resolve\",\"inputs\":[],\"outputs\":[{\"name\":\"status_\",\"type\":\"uint8\",\"internalType\":\"enumGameStatus\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resolveClaim\",\"inputs\":[{\"name\":\"_claimIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"resolvedAt\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"Timestamp\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"rootClaim\",\"inputs\":[],\"outputs\":[{\"name\":\"rootClaim_\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"splitDepth\",\"inputs\":[],\"outputs\":[{\"name\":\"splitDepth_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"status\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumGameStatus\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"step\",\"inputs\":[{\"name\":\"_claimIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_isAttack\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"_stateData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"vm\",\"inputs\":[],\"outputs\":[{\"name\":\"vm_\",\"type\":\"address\",\"internalType\":\"contractIBigStepper\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"Move\",\"inputs\":[{\"name\":\"parentIndex\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"claim\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"Claim\"},{\"name\":\"claimant\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Resolved\",\"inputs\":[{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"enumGameStatus\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BondTransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CannotDefendRootClaim\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClaimAboveSplit\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClaimAlreadyExists\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClaimAlreadyResolved\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClockNotExpired\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClockTimeExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"GameDepthExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"GameNotInProgress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InsufficientBond\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidLocalIdent\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidParent\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidPrestate\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSplitDepth\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OutOfOrderResolution\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedRootClaim\",\"inputs\":[{\"name\":\"rootClaim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}]},{\"type\":\"error\",\"name\":\"ValidStep\",\"inputs\":[]}]", - Bin: "0x6101806040523480156200001257600080fd5b5060405162003a4138038062003a41833981016040819052620000359162000098565b838310620000565760405163e62ccf3960e01b815260040160405180910390fd5b60ff90971661016052608095909552610120939093526101409190915260a05260c0526001600160401b031660e0526001600160a01b0316610100526200013a565b600080600080600080600080610100898b031215620000b657600080fd5b885160ff81168114620000c857600080fd5b60208a015160408b015160608c015160808d015160a08e015160c08f0151959d50939b509199509750955093506001600160401b03811681146200010b57600080fd5b60e08a01519092506001600160a01b03811681146200012957600080fd5b809150509295985092959890939650565b60805160a05160c05160e051610100516101205161014051610160516138076200023a6000396000818161049b0152611ffa0152600081816103d30152612bad0152600081816101e10152818161122c01528181611e2e0152611e640152600081816102e6015281816119180152611c1d01526000818161063d01528181610db4015261215801526000818161067001528181610be301528181610cac0152818161177301528181611e04015281816124ff01528181612739015281816128670152818161296f0152612a4b0152600081816106e701528181610c4f015281816116620152611794015260008181610463015261182a01526138076000f3fe6080604052600436106101cd5760003560e01c80638d450a95116100f7578063d5d44d8011610095578063f8f43ff611610064578063f8f43ff614610694578063fa24f743146106b4578063fa315aa9146106d8578063fdffbb281461070b57600080fd5b8063d5d44d80146105e1578063d8cc1a3c1461060e578063e1f0c3761461062e578063ec5e63081461066157600080fd5b8063c395e1ca116100d1578063c395e1ca14610502578063c55cd0c714610523578063c6f0308c14610536578063cf09e0d0146105c057600080fd5b80638d450a9514610454578063bbdc02db14610487578063bcef3b55146104c557600080fd5b8063609d33341161016f57806368800abf1161013e57806368800abf146103c45780638129fc1c146103f75780638980e0cc146103ff5780638b85902b1461041457600080fd5b8063609d33341461036657806360e274641461037b578063632247ea1461039b5780636361506d146103ae57600080fd5b80632810e1d6116101ab5780632810e1d61461029557806335fef567146102aa5780633a768463146102bf57806354fd4d501461031057600080fd5b80630356fe3a146101d257806319effeb414610214578063200d2ed21461025a575b600080fd5b3480156101de57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b34801561022057600080fd5b506000546102419068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161020b565b34801561026657600080fd5b5060005461028890700100000000000000000000000000000000900460ff1681565b60405161020b9190613244565b3480156102a157600080fd5b5061028861071e565b6102bd6102b8366004613285565b61091b565b005b3480156102cb57600080fd5b5060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161020b565b34801561031c57600080fd5b506103596040518060400160405280600681526020017f302e302e3234000000000000000000000000000000000000000000000000000081525081565b60405161020b9190613312565b34801561037257600080fd5b5061035961092b565b34801561038757600080fd5b506102bd610396366004613347565b61093d565b6102bd6103a9366004613380565b6109ed565b3480156103ba57600080fd5b5061020160015481565b3480156103d057600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610201565b6102bd6111e8565b34801561040b57600080fd5b50600254610201565b34801561042057600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360200135610201565b34801561046057600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610201565b34801561049357600080fd5b5060405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161020b565b3480156104d157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335610201565b34801561050e57600080fd5b5061020161051d3660046133b5565b50600090565b6102bd610531366004613285565b61150e565b34801561054257600080fd5b506105566105513660046133e7565b61151a565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161020b565b3480156105cc57600080fd5b506000546102419067ffffffffffffffff1681565b3480156105ed57600080fd5b506102016105fc366004613347565b60036020526000908152604090205481565b34801561061a57600080fd5b506102bd610629366004613449565b6115b1565b34801561063a57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610241565b34801561066d57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610201565b3480156106a057600080fd5b506102bd6106af3660046134d3565b611b8f565b3480156106c057600080fd5b506106c9611ff8565b60405161020b939291906134ff565b3480156106e457600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610201565b6102bd6107193660046133e7565b612055565b600080600054700100000000000000000000000000000000900460ff16600281111561074c5761074c613215565b14610783576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60065460ff166107bf576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106107eb576107eb61352a565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614610826576001610829565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156108da576108da613215565b0217905560028111156108ef576108ef613215565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a290565b610927828260006109ed565b5050565b606061093860208061241c565b905090565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260036020526040808220805490839055905190929083908381818185875af1925050503d80600081146109a8576040519150601f19603f3d011682016040523d82523d6000602084013e6109ad565b606091505b50509050806109e8576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60008054700100000000000000000000000000000000900460ff166002811115610a1957610a19613215565b14610a50576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110610a6557610a6561352a565b600091825260208083206040805160e0810182526005909402909101805463ffffffff808216865273ffffffffffffffffffffffffffffffffffffffff6401000000009092048216948601949094526001820154169184019190915260028101546fffffffffffffffffffffffffffffffff90811660608501526003820154608085015260049091015480821660a0850181905270010000000000000000000000000000000090910490911660c0840152919350909190610b2a90839086906124b316565b90506000610bca826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169050861580610c0c5750610c097f00000000000000000000000000000000000000000000000000000000000000006002613588565b81145b8015610c16575084155b15610c4d576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000811115610ca7576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cd27f00000000000000000000000000000000000000000000000000000000000000006001613588565b8103610ce457610ce4868885886124bb565b835160009063ffffffff90811614610d44576002856000015163ffffffff1681548110610d1357610d1361352a565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b60c0850151600090610d689067ffffffffffffffff165b67ffffffffffffffff1690565b67ffffffffffffffff1642610d92610d5b856fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16610da69190613588565b610db091906135a0565b90507f000000000000000000000000000000000000000000000000000000000000000060011c677fffffffffffffff1667ffffffffffffffff82161115610e23576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000604082901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615610ea1576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555050503360028c815481106111265761112661352a565b60009182526020808320600592830201805473ffffffffffffffffffffffffffffffffffffffff95909516640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909516949094179093558d82529091526040902060025461119c906001906135a0565b8154600181018355600092835260208320015560405133918c918e917f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be91a45050505050505050505050565b600654610100900460ff161561122a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360200135116112e1576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560048201526024015b60405180910390fd5b60463611156112f85763c407e0256000526004601cfd5b6040805160e08101825263ffffffff8152600060208201523291810191909152346fffffffffffffffffffffffffffffffff16606082015260029060808101367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335815260016020820152604001426fffffffffffffffffffffffffffffffff90811690915282546001808201855560009485526020808620855160059094020180549186015163ffffffff9094167fffffffffffffffff0000000000000000000000000000000000000000000000009092169190911764010000000073ffffffffffffffffffffffffffffffffffffffff94851602178155604085015181830180547fffffffffffffffffffffffff000000000000000000000000000000000000000016919094161790925560608401516002830180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169185169190911790556080840151600383015560a084015160c09094015193831670010000000000000000000000000000000094909316939093029190911760049091015581547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff16179091556114dc90436135a0565b40600155600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b610927828260016109ed565b6002818154811061152a57600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff1660028111156115dd576115dd613215565b14611614576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600287815481106116295761162961352a565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506116887f00000000000000000000000000000000000000000000000000000000000000006001613588565b611724826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1614611765576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808915611854576117b87f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006135a0565b6001901b6117d7846fffffffffffffffffffffffffffffffff16612673565b67ffffffffffffffff166117eb91906135e6565b156118285761181f61181060016fffffffffffffffffffffffffffffffff87166135fa565b865463ffffffff166000612719565b6003015461184a565b7f00000000000000000000000000000000000000000000000000000000000000005b915084905061187e565b6003850154915061187b6118106fffffffffffffffffffffffffffffffff8616600161362b565b90505b600882901b60088a8a60405161189592919061365f565b6040518091039020901b146118d6576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006118e18c6127fd565b905060006118f0836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e14ced329061196a908f908f908f908f908a906004016136b8565b6020604051808303816000875af1158015611989573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ad91906136f2565b600485015491149150600090600290611a58906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b611af4896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b611afe919061370b565b611b08919061372c565b67ffffffffffffffff161590508115158103611b50576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff166002811115611bbb57611bbb613215565b14611bf2576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600080611c018661282c565b93509350935093506000611c1785858585612c59565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611caa9190613753565b905060018903611d725773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a846001545b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af1158015611d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d6c91906136f2565b50611fed565b60028903611d9e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489611cd6565b60038903611dca5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487611cd6565b60048903611f425760006fffffffffffffffffffffffffffffffff861615611e6257611e286fffffffffffffffffffffffffffffffff87167f0000000000000000000000000000000000000000000000000000000000000000612d18565b611e52907f0000000000000000000000000000000000000000000000000000000000000000613588565b611e5d906001613588565b611e84565b7f00000000000000000000000000000000000000000000000000000000000000005b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af1158015611f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3b91906136f2565b5050611fed565b60058903611fbb576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390524660c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a401611d29565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335606061204e61092b565b9050909192565b60008054700100000000000000000000000000000000900460ff16600281111561208157612081613215565b146120b8576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600282815481106120cd576120cd61352a565b60009182526020822060059190910201600481015490925061210f90700100000000000000000000000000000000900460401c67ffffffffffffffff16610d5b565b600483015490915060009061214190700100000000000000000000000000000000900467ffffffffffffffff16610d5b565b61214b904261370b565b9050677fffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000060011c166121858284613770565b67ffffffffffffffff16116121c6576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526005602052604090208054851580156121e6575060065460ff165b1561221d576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8015801561222a57508515155b1561225c5760018501546122549073ffffffffffffffffffffffffffffffffffffffff1686612dcd565b505050505050565b6000805b8281101561233b57600084828154811061227c5761227c61352a565b60009182526020808320909101548083526005909152604090912054909150156122d2576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600282815481106122e7576122e761352a565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff1661232857339350505061233b565b50508061233490613793565b9050612260565b5061238373ffffffffffffffffffffffffffffffffffffffff821615612361578161237d565b600187015473ffffffffffffffffffffffffffffffffffffffff165b87612dcd565b85547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff83160217865560008781526005602052604081206123df916131db565b8660000361241357600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b50505050505050565b6060600061245384367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003613588565b90508267ffffffffffffffff1667ffffffffffffffff811115612478576124786137cb565b6040519080825280601f01601f1916602001820160405280156124a2576020820181803683370190505b509150828160208401375092915050565b151760011b90565b60006124da6fffffffffffffffffffffffffffffffff8416600161362b565b905060006124ea82866001612719565b9050600086901a83806125dd575061252360027f00000000000000000000000000000000000000000000000000000000000000006135e6565b60048301546002906125c7906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6125d1919061372c565b67ffffffffffffffff16145b156126355760ff8116600114806125f7575060ff81166002145b612630576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016112d8565b612413565b60ff811615612413576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016112d8565b600080612700837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600167ffffffffffffffff919091161b90920392915050565b600080826127625761275d6fffffffffffffffffffffffffffffffff86167f0000000000000000000000000000000000000000000000000000000000000000612eb8565b61277d565b61277d856fffffffffffffffffffffffffffffffff1661307f565b9050600284815481106127925761279261352a565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146127f557815460028054909163ffffffff169081106127e0576127e061352a565b906000526020600020906005020191506127a3565b509392505050565b600080600080600061280e8661282c565b935093509350935061282284848484612c59565b9695505050505050565b600080600080600085905060006002828154811061284c5761284c61352a565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000090612923906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1611612964576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000090612a2b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169250821115612aa757825463ffffffff16612a717f00000000000000000000000000000000000000000000000000000000000000006001613588565b8303612a7b578391505b60028181548110612a8e57612a8e61352a565b9060005260206000209060050201935080945050612968565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff16612b10612afb856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015612bf5576000612b48836fffffffffffffffffffffffffffffffff16612673565b67ffffffffffffffff161115612bab576000612b82612b7a60016fffffffffffffffffffffffffffffffff86166135fa565b896001612719565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50612bcf9050565b7f00000000000000000000000000000000000000000000000000000000000000009a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750612c4b565b6000612c17612b7a6fffffffffffffffffffffffffffffffff8516600161362b565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff84168103612cbf578282604051602001612ca29291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b604051602081830303815290604052805190602001209050612d10565b60408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a0016040516020818303038152906040528051906020012090505b949350505050565b600080612da5847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1690508083036001841b600180831b0386831b17039250505092915050565b60028101546fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff000000000000000000000000000000018101612e3d576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002820180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff17905573ffffffffffffffffffffffffffffffffffffffff831660009081526003602052604081208054839290612eae908490613588565b9091555050505050565b600081612f57846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1611612f98576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fa18361307f565b905081613040826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff16116130795761307661305d836001613588565b6fffffffffffffffffffffffffffffffff83169061312b565b90505b92915050565b60008119600183011681613113827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169390931c8015179392505050565b6000806131b8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169050808303600180821b0385821b179250505092915050565b50805460008255906000526020600020908101906131f991906131fc565b50565b5b8082111561321157600081556001016131fd565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061327f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561329857600080fd5b50508035926020909101359150565b6000815180845260005b818110156132cd576020818501810151868301820152016132b1565b818111156132df576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061307660208301846132a7565b73ffffffffffffffffffffffffffffffffffffffff811681146131f957600080fd5b60006020828403121561335957600080fd5b813561336481613325565b9392505050565b8035801515811461337b57600080fd5b919050565b60008060006060848603121561339557600080fd5b83359250602084013591506133ac6040850161336b565b90509250925092565b6000602082840312156133c757600080fd5b81356fffffffffffffffffffffffffffffffff8116811461336457600080fd5b6000602082840312156133f957600080fd5b5035919050565b60008083601f84011261341257600080fd5b50813567ffffffffffffffff81111561342a57600080fd5b60208301915083602082850101111561344257600080fd5b9250929050565b6000806000806000806080878903121561346257600080fd5b863595506134726020880161336b565b9450604087013567ffffffffffffffff8082111561348f57600080fd5b61349b8a838b01613400565b909650945060608901359150808211156134b457600080fd5b506134c189828a01613400565b979a9699509497509295939492505050565b6000806000606084860312156134e857600080fd5b505081359360208301359350604090920135919050565b60ff8416815282602082015260606040820152600061352160608301846132a7565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561359b5761359b613559565b500190565b6000828210156135b2576135b2613559565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826135f5576135f56135b7565b500690565b60006fffffffffffffffffffffffffffffffff8381169083168181101561362357613623613559565b039392505050565b60006fffffffffffffffffffffffffffffffff80831681851680830382111561365657613656613559565b01949350505050565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6060815260006136cc60608301878961366f565b82810360208401526136df81868861366f565b9150508260408301529695505050505050565b60006020828403121561370457600080fd5b5051919050565b600067ffffffffffffffff8381169083168181101561362357613623613559565b600067ffffffffffffffff80841680613747576137476135b7565b92169190910692915050565b60006020828403121561376557600080fd5b815161336481613325565b600067ffffffffffffffff80831681851680830382111561365657613656613559565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036137c4576137c4613559565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea164736f6c634300080f000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint32\",\"internalType\":\"GameType\"},{\"name\":\"_absolutePrestate\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_maxGameDepth\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_splitDepth\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_gameDuration\",\"type\":\"uint64\",\"internalType\":\"Duration\"},{\"name\":\"_vm\",\"type\":\"address\",\"internalType\":\"contractIBigStepper\"},{\"name\":\"_weth\",\"type\":\"address\",\"internalType\":\"contractIDelayedWETH\"},{\"name\":\"_anchorStateRegistry\",\"type\":\"address\",\"internalType\":\"contractIAnchorStateRegistry\"},{\"name\":\"_l2ChainId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"fallback\",\"stateMutability\":\"payable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"absolutePrestate\",\"inputs\":[],\"outputs\":[{\"name\":\"absolutePrestate_\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addLocalData\",\"inputs\":[{\"name\":\"_ident\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_execLeafIdx\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"attack\",\"inputs\":[{\"name\":\"_parentIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"claimCredit\",\"inputs\":[{\"name\":\"_recipient\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"claimData\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"parentIndex\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"counteredBy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"bond\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"position\",\"type\":\"uint128\",\"internalType\":\"Position\"},{\"name\":\"clock\",\"type\":\"uint128\",\"internalType\":\"Clock\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"claimDataLen\",\"inputs\":[],\"outputs\":[{\"name\":\"len_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"claimedBondFlag\",\"inputs\":[],\"outputs\":[{\"name\":\"claimedBondFlag_\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"createdAt\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"Timestamp\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"credit\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"defend\",\"inputs\":[{\"name\":\"_parentIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"extraData\",\"inputs\":[],\"outputs\":[{\"name\":\"extraData_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"gameData\",\"inputs\":[],\"outputs\":[{\"name\":\"gameType_\",\"type\":\"uint32\",\"internalType\":\"GameType\"},{\"name\":\"rootClaim_\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"extraData_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gameDuration\",\"inputs\":[],\"outputs\":[{\"name\":\"gameDuration_\",\"type\":\"uint64\",\"internalType\":\"Duration\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gameType\",\"inputs\":[],\"outputs\":[{\"name\":\"gameType_\",\"type\":\"uint32\",\"internalType\":\"GameType\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRequiredBond\",\"inputs\":[{\"name\":\"_position\",\"type\":\"uint128\",\"internalType\":\"Position\"}],\"outputs\":[{\"name\":\"requiredBond_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"l1Head\",\"inputs\":[],\"outputs\":[{\"name\":\"l1Head_\",\"type\":\"bytes32\",\"internalType\":\"Hash\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"l2BlockNumber\",\"inputs\":[],\"outputs\":[{\"name\":\"l2BlockNumber_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"l2ChainId\",\"inputs\":[],\"outputs\":[{\"name\":\"l2ChainId_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGameDepth\",\"inputs\":[],\"outputs\":[{\"name\":\"maxGameDepth_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"move\",\"inputs\":[{\"name\":\"_challengeIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_claim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"},{\"name\":\"_isAttack\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"resolve\",\"inputs\":[],\"outputs\":[{\"name\":\"status_\",\"type\":\"uint8\",\"internalType\":\"enumGameStatus\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"resolveClaim\",\"inputs\":[{\"name\":\"_claimIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"resolvedAt\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"Timestamp\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"rootClaim\",\"inputs\":[],\"outputs\":[{\"name\":\"rootClaim_\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"splitDepth\",\"inputs\":[],\"outputs\":[{\"name\":\"splitDepth_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"startingBlockNumber\",\"inputs\":[],\"outputs\":[{\"name\":\"startingBlockNumber_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"startingOutputRoot\",\"inputs\":[],\"outputs\":[{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"Hash\"},{\"name\":\"l2BlockNumber\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"startingRootHash\",\"inputs\":[],\"outputs\":[{\"name\":\"startingRootHash_\",\"type\":\"bytes32\",\"internalType\":\"Hash\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"status\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"enumGameStatus\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"step\",\"inputs\":[{\"name\":\"_claimIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_isAttack\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"_stateData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"vm\",\"inputs\":[],\"outputs\":[{\"name\":\"vm_\",\"type\":\"address\",\"internalType\":\"contractIBigStepper\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"weth\",\"inputs\":[],\"outputs\":[{\"name\":\"weth_\",\"type\":\"address\",\"internalType\":\"contractIDelayedWETH\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"Move\",\"inputs\":[{\"name\":\"parentIndex\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"claim\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"Claim\"},{\"name\":\"claimant\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Resolved\",\"inputs\":[{\"name\":\"status\",\"type\":\"uint8\",\"indexed\":true,\"internalType\":\"enumGameStatus\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AnchorRootNotFound\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BondTransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CannotDefendRootClaim\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClaimAboveSplit\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClaimAlreadyExists\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClaimAlreadyResolved\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClockNotExpired\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ClockTimeExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"DuplicateStep\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"GameDepthExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"GameNotInProgress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InsufficientBond\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidLocalIdent\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidParent\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidPrestate\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSplitDepth\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoCreditToClaim\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"OutOfOrderResolution\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnexpectedRootClaim\",\"inputs\":[{\"name\":\"rootClaim\",\"type\":\"bytes32\",\"internalType\":\"Claim\"}]},{\"type\":\"error\",\"name\":\"ValidStep\",\"inputs\":[]}]", + Bin: "0x6101a06040523480156200001257600080fd5b5060405162004988380380620049888339810160408190526200003591620000d0565b868610620000565760405163e62ccf3960e01b815260040160405180910390fd5b63ffffffff9098166101205260809690965260a09490945260c0929092526001600160401b031660e0526001600160a01b03908116610100529081166101405216610160526101805262000183565b6001600160a01b0381168114620000bb57600080fd5b50565b8051620000cb81620000a5565b919050565b60008060008060008060008060006101208a8c031215620000f057600080fd5b895163ffffffff811681146200010557600080fd5b60208b015160408c015160608d015160808e0151939c50919a50985096506001600160401b03811681146200013957600080fd5b60a08b01519095506200014c81620000a5565b93506200015c60c08b01620000be565b92506200016c60e08b01620000be565b91506101008a015190509295985092959850929598565b60805160a05160c05160e05161010051610120516101405161016051610180516146d7620002b1600039600081816106a7015261267d015260008181610a02015261157a01526000818161033801528181610b5701528181611430015281816119310152613b9d0152600081816105260152818161153901526127170152600081816102e401528181611fea01526123460152600081816106fa0152818161105b015261287501526000818161072d01528181610e4801528181610f1101528181611e450152818161254501528181612cb6015281816133f3015281816135210152818161362901526137050152600081816107cf01528181610eb401528181611aa301528181611b2901528181611d340152611e660152600081816104eb0152611efc01526146d76000f3fe6080604052600436106101ff5760003560e01c80638d450a951161010e578063d6ae3cd5116100a7578063f3f7214e11610079578063fa24f74311610061578063fa24f7431461079c578063fa315aa9146107c0578063fdffbb28146107f357005b8063f3f7214e14610751578063f8f43ff61461077c57005b8063d6ae3cd514610698578063d8cc1a3c146106cb578063e1f0c376146106eb578063ec5e63081461071e57005b8063c55cd0c7116100e0578063c55cd0c7146105ad578063c6f0308c146105c0578063cf09e0d01461064a578063d5d44d801461066b57005b80638d450a95146104dc578063bbdc02db1461050f578063bcef3b5514610550578063c395e1ca1461058d57005b806357da950e116101985780636361506d1161016a5780638129fc1c116101525780638129fc1c1461047f5780638980e0cc146104875780638b85902b1461049c57005b80636361506d1461042a57806370872aa51461046a57005b806357da950e146103b2578063609d3334146103e257806360e27464146103f7578063632247ea1461041757005b806335fef567116101d157806335fef567146102c25780633a768463146102d55780633fc8cef31461032957806354fd4d501461035c57005b806319effeb414610208578063200d2ed21461025357806325fc2ace1461028e5780632810e1d6146102ad57005b3661020657005b005b34801561021457600080fd5b506000546102359068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561025f57600080fd5b5060005461028190700100000000000000000000000000000000900460ff1681565b60405161024a9190613f78565b34801561029a57600080fd5b506006545b60405190815260200161024a565b3480156102b957600080fd5b50610281610806565b6102066102d0366004613fb9565b610a83565b3480156102e157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161024a565b34801561033557600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610304565b34801561036857600080fd5b506103a56040518060400160405280600581526020017f302e382e3100000000000000000000000000000000000000000000000000000081525081565b60405161024a9190614046565b3480156103be57600080fd5b506006546007546103cd919082565b6040805192835260208301919091520161024a565b3480156103ee57600080fd5b506103a5610a93565b34801561040357600080fd5b5061020661041236600461407b565b610aa6565b6102066104253660046140b4565b610c52565b34801561043657600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036020013561029f565b34801561047657600080fd5b5060075461029f565b6102066114ca565b34801561049357600080fd5b5060015461029f565b3480156104a857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036040013561029f565b3480156104e857600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061029f565b34801561051b57600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161024a565b34801561055c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033561029f565b34801561059957600080fd5b5061029f6105a83660046140e9565b6119f6565b6102066105bb366004613fb9565b611be0565b3480156105cc57600080fd5b506105e06105db36600461411b565b611bec565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161024a565b34801561065657600080fd5b506000546102359067ffffffffffffffff1681565b34801561067757600080fd5b5061029f61068636600461407b565b60026020526000908152604090205481565b3480156106a457600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061029f565b3480156106d757600080fd5b506102066106e636600461417d565b611c83565b3480156106f757600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610235565b34801561072a57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061029f565b34801561075d57600080fd5b506040516fffffffffffffffffffffffffffffffff815260200161024a565b34801561078857600080fd5b50610206610797366004614207565b6122b8565b3480156107a857600080fd5b506107b1612715565b60405161024a93929190614233565b3480156107cc57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061029f565b61020661080136600461411b565b612772565b600080600054700100000000000000000000000000000000900460ff16600281111561083457610834613f49565b1461086b576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055460ff166108a7576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660016000815481106108d3576108d3614261565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff161461090e576001610911565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156109c2576109c2613f49565b0217905560028111156109d7576109d7613f49565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610a6857600080fd5b505af1158015610a7c573d6000803e3d6000fd5b5050505090565b610a8f82826000610c52565b5050565b6060610aa160406020612bd3565b905090565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040812080549082905590819003610b0b576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063f3fef3a390604401600060405180830381600087803b158015610b9b57600080fd5b505af1158015610baf573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610c0d576040519150601f19603f3d011682016040523d82523d6000602084013e610c12565b606091505b5050905080610c4d576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60008054700100000000000000000000000000000000900460ff166002811115610c7e57610c7e613f49565b14610cb5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060018481548110610cca57610cca614261565b600091825260208083206040805160e0810182526005909402909101805463ffffffff808216865273ffffffffffffffffffffffffffffffffffffffff6401000000009092048216948601949094526001820154169184019190915260028101546fffffffffffffffffffffffffffffffff90811660608501526003820154608085015260049091015480821660a0850181905270010000000000000000000000000000000090910490911660c0840152919350909190610d8f9083908690612c6a16565b90506000610e2f826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169050861580610e715750610e6e7f000000000000000000000000000000000000000000000000000000000000000060026142bf565b81145b8015610e7b575084155b15610eb2576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000811115610f0c576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f377f000000000000000000000000000000000000000000000000000000000000000060016142bf565b8103610f4957610f4986888588612c72565b34610f53836119f6565b1115610f8b576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835160009063ffffffff90811614610feb576001856000015163ffffffff1681548110610fba57610fba614261565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b60c085015160009061100f9067ffffffffffffffff165b67ffffffffffffffff1690565b67ffffffffffffffff1642611039611002856fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff1661104d91906142bf565b61105791906142d7565b90507f000000000000000000000000000000000000000000000000000000000000000060011c677fffffffffffffff1667ffffffffffffffff821611156110ca576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000604082901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526003602052604090205490915060ff1615611148576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016003600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060016040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600460008c8152602001908152602001600020600180805490506113dd91906142d7565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263d0e30db09234926004808301939282900301818588803b15801561147557600080fd5b505af1158015611489573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a45050505050505050505050565b600554610100900460ff161561150c576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690637258a807906024016040805180830381865afa1580156115c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e491906142ee565b909250905081611620576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082018252838152602001829052600683905560078290558190367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90030135116116d2576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560048201526024015b60405180910390fd5b60663611156116e95763c407e0256000526004601cfd5b6040805160e08101825263ffffffff808252600060208301818152328486019081526fffffffffffffffffffffffffffffffff34818116606088019081527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90033560808901908152600160a08a0181815242861660c08c0190815282548084018455928a529a5160059092027fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf681018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915594517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf787018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905590517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf8860180549185167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909216919091179055517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf9850155915195518116700100000000000000000000000000000000029516949094177fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfa9091015583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f00000000000000000000000000000000000000000000000000000000000000009092169363d0e30db093926004828101939282900301818588803b15801561197757600080fd5b505af115801561198b573d6000803e3d6000fd5b50506000805467ffffffffffffffff42167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009091161790555050600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055505050565b600080611a95836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1690507f0000000000000000000000000000000000000000000000000000000000000000811115611afb576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a80630bebc2006000611b168383614341565b9050670de0b6b3a76400006000611b4d827f0000000000000000000000000000000000000000000000000000000000000000614355565b90506000611b6b611b66670de0b6b3a764000086614355565b612e33565b90506000611b79848461308e565b90506000611b8783836130dd565b90506000611b948261310b565b90506000611bb382611bae670de0b6b3a76400008f614355565b6132f3565b90506000611bc18b836130dd565b9050611bcd818d614355565b9f9e505050505050505050505050505050565b610a8f82826001610c52565b60018181548110611bfc57600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115611caf57611caf613f49565b14611ce6576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060018781548110611cfb57611cfb614261565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050611d5a7f000000000000000000000000000000000000000000000000000000000000000060016142bf565b611df6826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1614611e37576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808915611f2657611e8a7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006142d7565b6001901b611ea9846fffffffffffffffffffffffffffffffff1661332d565b67ffffffffffffffff16611ebd9190614392565b15611efa57611ef1611ee260016fffffffffffffffffffffffffffffffff87166143a6565b865463ffffffff1660006133d3565b60030154611f1c565b7f00000000000000000000000000000000000000000000000000000000000000005b9150849050611f50565b60038501549150611f4d611ee26fffffffffffffffffffffffffffffffff861660016143d7565b90505b600882901b60088a8a604051611f6792919061440b565b6040518091039020901b14611fa8576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611fb38c6134b7565b90506000611fc2836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e14ced329061203c908f908f908f908f908a90600401614464565b6020604051808303816000875af115801561205b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207f919061449e565b60048501549114915060009060029061212a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6121c6896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6121d091906144b7565b6121da91906144d8565b67ffffffffffffffff161590508115158103612222576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff1615612279576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156122e4576122e4613f49565b1461231b576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061232a866134e6565b93509350935093506000612340858585856138f5565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d391906144ff565b9050600189036124cb5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461242f367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036020013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156124a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124c5919061449e565b5061270a565b600289036124f75773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961242f565b600389036125235773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761242f565b6004890361263f5760006125696fffffffffffffffffffffffffffffffff85167f00000000000000000000000000000000000000000000000000000000000000006139b4565b60075461257691906142bf565b6125819060016142bf565b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af1158015612614573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612638919061449e565b505061270a565b600589036126d8576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000000060c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a401612482565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335606061276b610a93565b9050909192565b60008054700100000000000000000000000000000000900460ff16600281111561279e5761279e613f49565b146127d5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600182815481106127ea576127ea614261565b60009182526020822060059190910201600481015490925061282c90700100000000000000000000000000000000900460401c67ffffffffffffffff16611002565b600483015490915060009061285e90700100000000000000000000000000000000900467ffffffffffffffff16611002565b61286890426144b7565b9050677fffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000060011c166128a2828461451c565b67ffffffffffffffff16116128e3576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000848152600460205260409020805485158015612903575060055460ff165b1561293a576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8015801561294757508515155b156129ac578454640100000000900473ffffffffffffffffffffffffffffffffffffffff166000811561297a5781612996565b600187015473ffffffffffffffffffffffffffffffffffffffff165b90506129a28188613a69565b5050505050505050565b60006fffffffffffffffffffffffffffffffff815b83811015612af25760008582815481106129dd576129dd614261565b6000918252602080832090910154808352600490915260409091205490915015612a33576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060018281548110612a4857612a48614261565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff16158015612aa1575060048101546fffffffffffffffffffffffffffffffff908116908516115b15612adf576001810154600482015473ffffffffffffffffffffffffffffffffffffffff90911695506fffffffffffffffffffffffffffffffff1693505b505080612aeb9061453f565b90506129c1565b50612b3a73ffffffffffffffffffffffffffffffffffffffff831615612b185782612b34565b600188015473ffffffffffffffffffffffffffffffffffffffff165b88613a69565b86547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8416021787556000888152600460205260408120612b9691613f0f565b876000036129a257600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555050505050505050565b60606000612c0a84367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036142bf565b90508267ffffffffffffffff1667ffffffffffffffff811115612c2f57612c2f614577565b6040519080825280601f01601f191660200182016040528015612c59576020820181803683370190505b509150828160208401375092915050565b151760011b90565b6000612c916fffffffffffffffffffffffffffffffff841660016143d7565b90506000612ca1828660016133d3565b9050600086901a8380612d945750612cda60027f0000000000000000000000000000000000000000000000000000000000000000614392565b6004830154600290612d7e906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b612d8891906144d8565b67ffffffffffffffff16145b15612dec5760ff811660011480612dae575060ff81166002145b612de7576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016116c9565b612e2a565b60ff811615612e2a576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016116c9565b50505050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213612e9257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a7640000021582026130cb57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156130fb5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361313957919050565b680755bf798b4a1bf1e582126131575763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613324670de0b6b3a76400008361330b86612e33565b61331591906145a6565b61331f9190614662565b61310b565b90505b92915050565b6000806133ba837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600167ffffffffffffffff919091161b90920392915050565b6000808261341c576134176fffffffffffffffffffffffffffffffff86167f0000000000000000000000000000000000000000000000000000000000000000613bf5565b613437565b613437856fffffffffffffffffffffffffffffffff16613db3565b90506001848154811061344c5761344c614261565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146134af57815460018054909163ffffffff1690811061349a5761349a614261565b9060005260206000209060050201915061345d565b509392505050565b60008060008060006134c8866134e6565b93509350935093506134dc848484846138f5565b9695505050505050565b600080600080600085905060006001828154811061350657613506614261565b600091825260209091206004600590920201908101549091507f0000000000000000000000000000000000000000000000000000000000000000906135dd906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff161161361e576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f0000000000000000000000000000000000000000000000000000000000000000906136e5906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff16925082111561376157825463ffffffff1661372b7f000000000000000000000000000000000000000000000000000000000000000060016142bf565b8303613735578391505b6001818154811061374857613748614261565b9060005260206000209060050201935080945050613622565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166137ca6137b5856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015613891576000613802836fffffffffffffffffffffffffffffffff1661332d565b67ffffffffffffffff16111561386557600061383c61383460016fffffffffffffffffffffffffffffffff86166143a6565b8960016133d3565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a5061386b9050565b6006549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff1697506138e7565b60006138b36138346fffffffffffffffffffffffffffffffff851660016143d7565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff8416810361395b57828260405160200161393e9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012090506139ac565b60408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a0016040516020818303038152906040528051906020012090505b949350505050565b600080613a41847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1690508083036001841b600180831b0386831b17039250505092915050565b60028101546fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff000000000000000000000000000000018101613ad9576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280830180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff17905573ffffffffffffffffffffffffffffffffffffffff84166000908152602091909152604081208054839290613b4c9084906142bf565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f00000000000000000000000000000000000000000000000000000000000000001690637eee288d90604401600060405180830381600087803b158015613be157600080fd5b505af1158015612e2a573d6000803e3d6000fd5b600081613c94846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1611613cd5576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613cde83613db3565b905081613d7d826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff161161332757613324613d9a8360016142bf565b6fffffffffffffffffffffffffffffffff831690613e5f565b60008119600183011681613e47827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169390931c8015179392505050565b600080613eec847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169050808303600180821b0385821b179250505092915050565b5080546000825590600052602060002090810190613f2d9190613f30565b50565b5b80821115613f455760008155600101613f31565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310613fb3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060408385031215613fcc57600080fd5b50508035926020909101359150565b6000815180845260005b8181101561400157602081850181015186830182015201613fe5565b81811115614013576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006133246020830184613fdb565b73ffffffffffffffffffffffffffffffffffffffff81168114613f2d57600080fd5b60006020828403121561408d57600080fd5b813561409881614059565b9392505050565b803580151581146140af57600080fd5b919050565b6000806000606084860312156140c957600080fd5b83359250602084013591506140e06040850161409f565b90509250925092565b6000602082840312156140fb57600080fd5b81356fffffffffffffffffffffffffffffffff8116811461409857600080fd5b60006020828403121561412d57600080fd5b5035919050565b60008083601f84011261414657600080fd5b50813567ffffffffffffffff81111561415e57600080fd5b60208301915083602082850101111561417657600080fd5b9250929050565b6000806000806000806080878903121561419657600080fd5b863595506141a66020880161409f565b9450604087013567ffffffffffffffff808211156141c357600080fd5b6141cf8a838b01614134565b909650945060608901359150808211156141e857600080fd5b506141f589828a01614134565b979a9699509497509295939492505050565b60008060006060848603121561421c57600080fd5b505081359360208301359350604090920135919050565b63ffffffff841681528260208201526060604082015260006142586060830184613fdb565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156142d2576142d2614290565b500190565b6000828210156142e9576142e9614290565b500390565b6000806040838503121561430157600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261435057614350614312565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561438d5761438d614290565b500290565b6000826143a1576143a1614312565b500690565b60006fffffffffffffffffffffffffffffffff838116908316818110156143cf576143cf614290565b039392505050565b60006fffffffffffffffffffffffffffffffff80831681851680830382111561440257614402614290565b01949350505050565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60608152600061447860608301878961441b565b828103602084015261448b81868861441b565b9150508260408301529695505050505050565b6000602082840312156144b057600080fd5b5051919050565b600067ffffffffffffffff838116908316818110156143cf576143cf614290565b600067ffffffffffffffff808416806144f3576144f3614312565b92169190910692915050565b60006020828403121561451157600080fd5b815161409881614059565b600067ffffffffffffffff80831681851680830382111561440257614402614290565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361457057614570614290565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156145e7576145e7614290565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561462257614622614290565b6000871292508782058712848416161561463e5761463e614290565b8785058712818416161561465457614654614290565b505050929093029392505050565b60008261467157614671614312565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156146c5576146c5614290565b50059056fea164736f6c634300080f000a", } // FaultDisputeGameABI is the input ABI used to generate the binding from. @@ -43,7 +43,7 @@ var FaultDisputeGameABI = FaultDisputeGameMetaData.ABI var FaultDisputeGameBin = FaultDisputeGameMetaData.Bin // DeployFaultDisputeGame deploys a new Ethereum contract, binding an instance of FaultDisputeGame to it. -func DeployFaultDisputeGame(auth *bind.TransactOpts, backend bind.ContractBackend, _gameType uint8, _absolutePrestate [32]byte, _genesisBlockNumber *big.Int, _genesisOutputRoot [32]byte, _maxGameDepth *big.Int, _splitDepth *big.Int, _gameDuration uint64, _vm common.Address) (common.Address, *types.Transaction, *FaultDisputeGame, error) { +func DeployFaultDisputeGame(auth *bind.TransactOpts, backend bind.ContractBackend, _gameType uint32, _absolutePrestate [32]byte, _maxGameDepth *big.Int, _splitDepth *big.Int, _gameDuration uint64, _vm common.Address, _weth common.Address, _anchorStateRegistry common.Address, _l2ChainId *big.Int) (common.Address, *types.Transaction, *FaultDisputeGame, error) { parsed, err := FaultDisputeGameMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -52,7 +52,7 @@ func DeployFaultDisputeGame(auth *bind.TransactOpts, backend bind.ContractBacken return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(FaultDisputeGameBin), backend, _gameType, _absolutePrestate, _genesisBlockNumber, _genesisOutputRoot, _maxGameDepth, _splitDepth, _gameDuration, _vm) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(FaultDisputeGameBin), backend, _gameType, _absolutePrestate, _maxGameDepth, _splitDepth, _gameDuration, _vm, _weth, _anchorStateRegistry, _l2ChainId) if err != nil { return common.Address{}, nil, nil, err } @@ -333,6 +333,37 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) ClaimDataLen() (*big.Int return _FaultDisputeGame.Contract.ClaimDataLen(&_FaultDisputeGame.CallOpts) } +// ClaimedBondFlag is a free data retrieval call binding the contract method 0xf3f7214e. +// +// Solidity: function claimedBondFlag() pure returns(uint128 claimedBondFlag_) +func (_FaultDisputeGame *FaultDisputeGameCaller) ClaimedBondFlag(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FaultDisputeGame.contract.Call(opts, &out, "claimedBondFlag") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ClaimedBondFlag is a free data retrieval call binding the contract method 0xf3f7214e. +// +// Solidity: function claimedBondFlag() pure returns(uint128 claimedBondFlag_) +func (_FaultDisputeGame *FaultDisputeGameSession) ClaimedBondFlag() (*big.Int, error) { + return _FaultDisputeGame.Contract.ClaimedBondFlag(&_FaultDisputeGame.CallOpts) +} + +// ClaimedBondFlag is a free data retrieval call binding the contract method 0xf3f7214e. +// +// Solidity: function claimedBondFlag() pure returns(uint128 claimedBondFlag_) +func (_FaultDisputeGame *FaultDisputeGameCallerSession) ClaimedBondFlag() (*big.Int, error) { + return _FaultDisputeGame.Contract.ClaimedBondFlag(&_FaultDisputeGame.CallOpts) +} + // CreatedAt is a free data retrieval call binding the contract method 0xcf09e0d0. // // Solidity: function createdAt() view returns(uint64) @@ -428,9 +459,9 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) ExtraData() ([]byte, err // GameData is a free data retrieval call binding the contract method 0xfa24f743. // -// Solidity: function gameData() view returns(uint8 gameType_, bytes32 rootClaim_, bytes extraData_) +// Solidity: function gameData() view returns(uint32 gameType_, bytes32 rootClaim_, bytes extraData_) func (_FaultDisputeGame *FaultDisputeGameCaller) GameData(opts *bind.CallOpts) (struct { - GameType uint8 + GameType uint32 RootClaim [32]byte ExtraData []byte }, error) { @@ -438,7 +469,7 @@ func (_FaultDisputeGame *FaultDisputeGameCaller) GameData(opts *bind.CallOpts) ( err := _FaultDisputeGame.contract.Call(opts, &out, "gameData") outstruct := new(struct { - GameType uint8 + GameType uint32 RootClaim [32]byte ExtraData []byte }) @@ -446,7 +477,7 @@ func (_FaultDisputeGame *FaultDisputeGameCaller) GameData(opts *bind.CallOpts) ( return *outstruct, err } - outstruct.GameType = *abi.ConvertType(out[0], new(uint8)).(*uint8) + outstruct.GameType = *abi.ConvertType(out[0], new(uint32)).(*uint32) outstruct.RootClaim = *abi.ConvertType(out[1], new([32]byte)).(*[32]byte) outstruct.ExtraData = *abi.ConvertType(out[2], new([]byte)).(*[]byte) @@ -456,9 +487,9 @@ func (_FaultDisputeGame *FaultDisputeGameCaller) GameData(opts *bind.CallOpts) ( // GameData is a free data retrieval call binding the contract method 0xfa24f743. // -// Solidity: function gameData() view returns(uint8 gameType_, bytes32 rootClaim_, bytes extraData_) +// Solidity: function gameData() view returns(uint32 gameType_, bytes32 rootClaim_, bytes extraData_) func (_FaultDisputeGame *FaultDisputeGameSession) GameData() (struct { - GameType uint8 + GameType uint32 RootClaim [32]byte ExtraData []byte }, error) { @@ -467,9 +498,9 @@ func (_FaultDisputeGame *FaultDisputeGameSession) GameData() (struct { // GameData is a free data retrieval call binding the contract method 0xfa24f743. // -// Solidity: function gameData() view returns(uint8 gameType_, bytes32 rootClaim_, bytes extraData_) +// Solidity: function gameData() view returns(uint32 gameType_, bytes32 rootClaim_, bytes extraData_) func (_FaultDisputeGame *FaultDisputeGameCallerSession) GameData() (struct { - GameType uint8 + GameType uint32 RootClaim [32]byte ExtraData []byte }, error) { @@ -509,16 +540,16 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) GameDuration() (uint64, // GameType is a free data retrieval call binding the contract method 0xbbdc02db. // -// Solidity: function gameType() view returns(uint8 gameType_) -func (_FaultDisputeGame *FaultDisputeGameCaller) GameType(opts *bind.CallOpts) (uint8, error) { +// Solidity: function gameType() view returns(uint32 gameType_) +func (_FaultDisputeGame *FaultDisputeGameCaller) GameType(opts *bind.CallOpts) (uint32, error) { var out []interface{} err := _FaultDisputeGame.contract.Call(opts, &out, "gameType") if err != nil { - return *new(uint8), err + return *new(uint32), err } - out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) return out0, err @@ -526,83 +557,21 @@ func (_FaultDisputeGame *FaultDisputeGameCaller) GameType(opts *bind.CallOpts) ( // GameType is a free data retrieval call binding the contract method 0xbbdc02db. // -// Solidity: function gameType() view returns(uint8 gameType_) -func (_FaultDisputeGame *FaultDisputeGameSession) GameType() (uint8, error) { +// Solidity: function gameType() view returns(uint32 gameType_) +func (_FaultDisputeGame *FaultDisputeGameSession) GameType() (uint32, error) { return _FaultDisputeGame.Contract.GameType(&_FaultDisputeGame.CallOpts) } // GameType is a free data retrieval call binding the contract method 0xbbdc02db. // -// Solidity: function gameType() view returns(uint8 gameType_) -func (_FaultDisputeGame *FaultDisputeGameCallerSession) GameType() (uint8, error) { +// Solidity: function gameType() view returns(uint32 gameType_) +func (_FaultDisputeGame *FaultDisputeGameCallerSession) GameType() (uint32, error) { return _FaultDisputeGame.Contract.GameType(&_FaultDisputeGame.CallOpts) } -// GenesisBlockNumber is a free data retrieval call binding the contract method 0x0356fe3a. -// -// Solidity: function genesisBlockNumber() view returns(uint256 genesisBlockNumber_) -func (_FaultDisputeGame *FaultDisputeGameCaller) GenesisBlockNumber(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _FaultDisputeGame.contract.Call(opts, &out, "genesisBlockNumber") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GenesisBlockNumber is a free data retrieval call binding the contract method 0x0356fe3a. -// -// Solidity: function genesisBlockNumber() view returns(uint256 genesisBlockNumber_) -func (_FaultDisputeGame *FaultDisputeGameSession) GenesisBlockNumber() (*big.Int, error) { - return _FaultDisputeGame.Contract.GenesisBlockNumber(&_FaultDisputeGame.CallOpts) -} - -// GenesisBlockNumber is a free data retrieval call binding the contract method 0x0356fe3a. -// -// Solidity: function genesisBlockNumber() view returns(uint256 genesisBlockNumber_) -func (_FaultDisputeGame *FaultDisputeGameCallerSession) GenesisBlockNumber() (*big.Int, error) { - return _FaultDisputeGame.Contract.GenesisBlockNumber(&_FaultDisputeGame.CallOpts) -} - -// GenesisOutputRoot is a free data retrieval call binding the contract method 0x68800abf. -// -// Solidity: function genesisOutputRoot() view returns(bytes32 genesisOutputRoot_) -func (_FaultDisputeGame *FaultDisputeGameCaller) GenesisOutputRoot(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _FaultDisputeGame.contract.Call(opts, &out, "genesisOutputRoot") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// GenesisOutputRoot is a free data retrieval call binding the contract method 0x68800abf. -// -// Solidity: function genesisOutputRoot() view returns(bytes32 genesisOutputRoot_) -func (_FaultDisputeGame *FaultDisputeGameSession) GenesisOutputRoot() ([32]byte, error) { - return _FaultDisputeGame.Contract.GenesisOutputRoot(&_FaultDisputeGame.CallOpts) -} - -// GenesisOutputRoot is a free data retrieval call binding the contract method 0x68800abf. -// -// Solidity: function genesisOutputRoot() view returns(bytes32 genesisOutputRoot_) -func (_FaultDisputeGame *FaultDisputeGameCallerSession) GenesisOutputRoot() ([32]byte, error) { - return _FaultDisputeGame.Contract.GenesisOutputRoot(&_FaultDisputeGame.CallOpts) -} - // GetRequiredBond is a free data retrieval call binding the contract method 0xc395e1ca. // -// Solidity: function getRequiredBond(uint128 _position) pure returns(uint256 requiredBond_) +// Solidity: function getRequiredBond(uint128 _position) view returns(uint256 requiredBond_) func (_FaultDisputeGame *FaultDisputeGameCaller) GetRequiredBond(opts *bind.CallOpts, _position *big.Int) (*big.Int, error) { var out []interface{} err := _FaultDisputeGame.contract.Call(opts, &out, "getRequiredBond", _position) @@ -619,21 +588,21 @@ func (_FaultDisputeGame *FaultDisputeGameCaller) GetRequiredBond(opts *bind.Call // GetRequiredBond is a free data retrieval call binding the contract method 0xc395e1ca. // -// Solidity: function getRequiredBond(uint128 _position) pure returns(uint256 requiredBond_) +// Solidity: function getRequiredBond(uint128 _position) view returns(uint256 requiredBond_) func (_FaultDisputeGame *FaultDisputeGameSession) GetRequiredBond(_position *big.Int) (*big.Int, error) { return _FaultDisputeGame.Contract.GetRequiredBond(&_FaultDisputeGame.CallOpts, _position) } // GetRequiredBond is a free data retrieval call binding the contract method 0xc395e1ca. // -// Solidity: function getRequiredBond(uint128 _position) pure returns(uint256 requiredBond_) +// Solidity: function getRequiredBond(uint128 _position) view returns(uint256 requiredBond_) func (_FaultDisputeGame *FaultDisputeGameCallerSession) GetRequiredBond(_position *big.Int) (*big.Int, error) { return _FaultDisputeGame.Contract.GetRequiredBond(&_FaultDisputeGame.CallOpts, _position) } // L1Head is a free data retrieval call binding the contract method 0x6361506d. // -// Solidity: function l1Head() view returns(bytes32) +// Solidity: function l1Head() pure returns(bytes32 l1Head_) func (_FaultDisputeGame *FaultDisputeGameCaller) L1Head(opts *bind.CallOpts) ([32]byte, error) { var out []interface{} err := _FaultDisputeGame.contract.Call(opts, &out, "l1Head") @@ -650,14 +619,14 @@ func (_FaultDisputeGame *FaultDisputeGameCaller) L1Head(opts *bind.CallOpts) ([3 // L1Head is a free data retrieval call binding the contract method 0x6361506d. // -// Solidity: function l1Head() view returns(bytes32) +// Solidity: function l1Head() pure returns(bytes32 l1Head_) func (_FaultDisputeGame *FaultDisputeGameSession) L1Head() ([32]byte, error) { return _FaultDisputeGame.Contract.L1Head(&_FaultDisputeGame.CallOpts) } // L1Head is a free data retrieval call binding the contract method 0x6361506d. // -// Solidity: function l1Head() view returns(bytes32) +// Solidity: function l1Head() pure returns(bytes32 l1Head_) func (_FaultDisputeGame *FaultDisputeGameCallerSession) L1Head() ([32]byte, error) { return _FaultDisputeGame.Contract.L1Head(&_FaultDisputeGame.CallOpts) } @@ -693,6 +662,37 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) L2BlockNumber() (*big.In return _FaultDisputeGame.Contract.L2BlockNumber(&_FaultDisputeGame.CallOpts) } +// L2ChainId is a free data retrieval call binding the contract method 0xd6ae3cd5. +// +// Solidity: function l2ChainId() view returns(uint256 l2ChainId_) +func (_FaultDisputeGame *FaultDisputeGameCaller) L2ChainId(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FaultDisputeGame.contract.Call(opts, &out, "l2ChainId") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// L2ChainId is a free data retrieval call binding the contract method 0xd6ae3cd5. +// +// Solidity: function l2ChainId() view returns(uint256 l2ChainId_) +func (_FaultDisputeGame *FaultDisputeGameSession) L2ChainId() (*big.Int, error) { + return _FaultDisputeGame.Contract.L2ChainId(&_FaultDisputeGame.CallOpts) +} + +// L2ChainId is a free data retrieval call binding the contract method 0xd6ae3cd5. +// +// Solidity: function l2ChainId() view returns(uint256 l2ChainId_) +func (_FaultDisputeGame *FaultDisputeGameCallerSession) L2ChainId() (*big.Int, error) { + return _FaultDisputeGame.Contract.L2ChainId(&_FaultDisputeGame.CallOpts) +} + // MaxGameDepth is a free data retrieval call binding the contract method 0xfa315aa9. // // Solidity: function maxGameDepth() view returns(uint256 maxGameDepth_) @@ -817,6 +817,113 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) SplitDepth() (*big.Int, return _FaultDisputeGame.Contract.SplitDepth(&_FaultDisputeGame.CallOpts) } +// StartingBlockNumber is a free data retrieval call binding the contract method 0x70872aa5. +// +// Solidity: function startingBlockNumber() view returns(uint256 startingBlockNumber_) +func (_FaultDisputeGame *FaultDisputeGameCaller) StartingBlockNumber(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FaultDisputeGame.contract.Call(opts, &out, "startingBlockNumber") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// StartingBlockNumber is a free data retrieval call binding the contract method 0x70872aa5. +// +// Solidity: function startingBlockNumber() view returns(uint256 startingBlockNumber_) +func (_FaultDisputeGame *FaultDisputeGameSession) StartingBlockNumber() (*big.Int, error) { + return _FaultDisputeGame.Contract.StartingBlockNumber(&_FaultDisputeGame.CallOpts) +} + +// StartingBlockNumber is a free data retrieval call binding the contract method 0x70872aa5. +// +// Solidity: function startingBlockNumber() view returns(uint256 startingBlockNumber_) +func (_FaultDisputeGame *FaultDisputeGameCallerSession) StartingBlockNumber() (*big.Int, error) { + return _FaultDisputeGame.Contract.StartingBlockNumber(&_FaultDisputeGame.CallOpts) +} + +// StartingOutputRoot is a free data retrieval call binding the contract method 0x57da950e. +// +// Solidity: function startingOutputRoot() view returns(bytes32 root, uint256 l2BlockNumber) +func (_FaultDisputeGame *FaultDisputeGameCaller) StartingOutputRoot(opts *bind.CallOpts) (struct { + Root [32]byte + L2BlockNumber *big.Int +}, error) { + var out []interface{} + err := _FaultDisputeGame.contract.Call(opts, &out, "startingOutputRoot") + + outstruct := new(struct { + Root [32]byte + L2BlockNumber *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.Root = *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + outstruct.L2BlockNumber = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// StartingOutputRoot is a free data retrieval call binding the contract method 0x57da950e. +// +// Solidity: function startingOutputRoot() view returns(bytes32 root, uint256 l2BlockNumber) +func (_FaultDisputeGame *FaultDisputeGameSession) StartingOutputRoot() (struct { + Root [32]byte + L2BlockNumber *big.Int +}, error) { + return _FaultDisputeGame.Contract.StartingOutputRoot(&_FaultDisputeGame.CallOpts) +} + +// StartingOutputRoot is a free data retrieval call binding the contract method 0x57da950e. +// +// Solidity: function startingOutputRoot() view returns(bytes32 root, uint256 l2BlockNumber) +func (_FaultDisputeGame *FaultDisputeGameCallerSession) StartingOutputRoot() (struct { + Root [32]byte + L2BlockNumber *big.Int +}, error) { + return _FaultDisputeGame.Contract.StartingOutputRoot(&_FaultDisputeGame.CallOpts) +} + +// StartingRootHash is a free data retrieval call binding the contract method 0x25fc2ace. +// +// Solidity: function startingRootHash() view returns(bytes32 startingRootHash_) +func (_FaultDisputeGame *FaultDisputeGameCaller) StartingRootHash(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _FaultDisputeGame.contract.Call(opts, &out, "startingRootHash") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// StartingRootHash is a free data retrieval call binding the contract method 0x25fc2ace. +// +// Solidity: function startingRootHash() view returns(bytes32 startingRootHash_) +func (_FaultDisputeGame *FaultDisputeGameSession) StartingRootHash() ([32]byte, error) { + return _FaultDisputeGame.Contract.StartingRootHash(&_FaultDisputeGame.CallOpts) +} + +// StartingRootHash is a free data retrieval call binding the contract method 0x25fc2ace. +// +// Solidity: function startingRootHash() view returns(bytes32 startingRootHash_) +func (_FaultDisputeGame *FaultDisputeGameCallerSession) StartingRootHash() ([32]byte, error) { + return _FaultDisputeGame.Contract.StartingRootHash(&_FaultDisputeGame.CallOpts) +} + // Status is a free data retrieval call binding the contract method 0x200d2ed2. // // Solidity: function status() view returns(uint8) @@ -910,6 +1017,37 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) Vm() (common.Address, er return _FaultDisputeGame.Contract.Vm(&_FaultDisputeGame.CallOpts) } +// Weth is a free data retrieval call binding the contract method 0x3fc8cef3. +// +// Solidity: function weth() view returns(address weth_) +func (_FaultDisputeGame *FaultDisputeGameCaller) Weth(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _FaultDisputeGame.contract.Call(opts, &out, "weth") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Weth is a free data retrieval call binding the contract method 0x3fc8cef3. +// +// Solidity: function weth() view returns(address weth_) +func (_FaultDisputeGame *FaultDisputeGameSession) Weth() (common.Address, error) { + return _FaultDisputeGame.Contract.Weth(&_FaultDisputeGame.CallOpts) +} + +// Weth is a free data retrieval call binding the contract method 0x3fc8cef3. +// +// Solidity: function weth() view returns(address weth_) +func (_FaultDisputeGame *FaultDisputeGameCallerSession) Weth() (common.Address, error) { + return _FaultDisputeGame.Contract.Weth(&_FaultDisputeGame.CallOpts) +} + // AddLocalData is a paid mutator transaction binding the contract method 0xf8f43ff6. // // Solidity: function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) returns() @@ -1099,6 +1237,48 @@ func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Step(_claimIndex *bi return _FaultDisputeGame.Contract.Step(&_FaultDisputeGame.TransactOpts, _claimIndex, _isAttack, _stateData, _proof) } +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_FaultDisputeGame *FaultDisputeGameTransactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) { + return _FaultDisputeGame.contract.RawTransact(opts, calldata) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_FaultDisputeGame *FaultDisputeGameSession) Fallback(calldata []byte) (*types.Transaction, error) { + return _FaultDisputeGame.Contract.Fallback(&_FaultDisputeGame.TransactOpts, calldata) +} + +// Fallback is a paid mutator transaction binding the contract fallback function. +// +// Solidity: fallback() payable returns() +func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Fallback(calldata []byte) (*types.Transaction, error) { + return _FaultDisputeGame.Contract.Fallback(&_FaultDisputeGame.TransactOpts, calldata) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_FaultDisputeGame *FaultDisputeGameTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FaultDisputeGame.contract.RawTransact(opts, nil) // calldata is disallowed for receive function +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_FaultDisputeGame *FaultDisputeGameSession) Receive() (*types.Transaction, error) { + return _FaultDisputeGame.Contract.Receive(&_FaultDisputeGame.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_FaultDisputeGame *FaultDisputeGameTransactorSession) Receive() (*types.Transaction, error) { + return _FaultDisputeGame.Contract.Receive(&_FaultDisputeGame.TransactOpts) +} + // FaultDisputeGameMoveIterator is returned from FilterMove and is used to iterate over the raw logs and unpacked data for Move events raised by the FaultDisputeGame contract. type FaultDisputeGameMoveIterator struct { Event *FaultDisputeGameMove // Event containing the contract specifics and raw log diff --git a/op-bindings/bindings/faultdisputegame_more.go b/op-bindings/bindings/faultdisputegame_more.go index 7f8ab2d6fd34..f2a2d88a23a6 100644 --- a/op-bindings/bindings/faultdisputegame_more.go +++ b/op-bindings/bindings/faultdisputegame_more.go @@ -9,11 +9,11 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const FaultDisputeGameStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"createdAt\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_userDefinedValueType(Timestamp)1017\"},{\"astId\":1001,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"resolvedAt\",\"offset\":8,\"slot\":\"0\",\"type\":\"t_userDefinedValueType(Timestamp)1017\"},{\"astId\":1002,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"status\",\"offset\":16,\"slot\":\"0\",\"type\":\"t_enum(GameStatus)1010\"},{\"astId\":1003,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"l1Head\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_userDefinedValueType(Hash)1015\"},{\"astId\":1004,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"claimData\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_array(t_struct(ClaimData)1011_storage)dyn_storage\"},{\"astId\":1005,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"credit\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":1006,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"claims\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_mapping(t_userDefinedValueType(ClaimHash)1013,t_bool)\"},{\"astId\":1007,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"subgames\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_mapping(t_uint256,t_array(t_uint256)dyn_storage)\"},{\"astId\":1008,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"subgameAtRootResolved\",\"offset\":0,\"slot\":\"6\",\"type\":\"t_bool\"},{\"astId\":1009,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"initialized\",\"offset\":1,\"slot\":\"6\",\"type\":\"t_bool\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_struct(ClaimData)1011_storage)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"struct IFaultDisputeGame.ClaimData[]\",\"numberOfBytes\":\"32\",\"base\":\"t_struct(ClaimData)1011_storage\"},\"t_array(t_uint256)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"uint256[]\",\"numberOfBytes\":\"32\",\"base\":\"t_uint256\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_enum(GameStatus)1010\":{\"encoding\":\"inplace\",\"label\":\"enum GameStatus\",\"numberOfBytes\":\"1\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_mapping(t_uint256,t_array(t_uint256)dyn_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e uint256[])\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_array(t_uint256)dyn_storage\"},\"t_mapping(t_userDefinedValueType(ClaimHash)1013,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(ClaimHash =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_userDefinedValueType(ClaimHash)1013\",\"value\":\"t_bool\"},\"t_struct(ClaimData)1011_storage\":{\"encoding\":\"inplace\",\"label\":\"struct IFaultDisputeGame.ClaimData\",\"numberOfBytes\":\"160\"},\"t_uint128\":{\"encoding\":\"inplace\",\"label\":\"uint128\",\"numberOfBytes\":\"16\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint32\":{\"encoding\":\"inplace\",\"label\":\"uint32\",\"numberOfBytes\":\"4\"},\"t_userDefinedValueType(Claim)1012\":{\"encoding\":\"inplace\",\"label\":\"Claim\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(ClaimHash)1013\":{\"encoding\":\"inplace\",\"label\":\"ClaimHash\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(Clock)1014\":{\"encoding\":\"inplace\",\"label\":\"Clock\",\"numberOfBytes\":\"16\"},\"t_userDefinedValueType(Hash)1015\":{\"encoding\":\"inplace\",\"label\":\"Hash\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(Position)1016\":{\"encoding\":\"inplace\",\"label\":\"Position\",\"numberOfBytes\":\"16\"},\"t_userDefinedValueType(Timestamp)1017\":{\"encoding\":\"inplace\",\"label\":\"Timestamp\",\"numberOfBytes\":\"8\"}}}" +const FaultDisputeGameStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"createdAt\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_userDefinedValueType(Timestamp)1018\"},{\"astId\":1001,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"resolvedAt\",\"offset\":8,\"slot\":\"0\",\"type\":\"t_userDefinedValueType(Timestamp)1018\"},{\"astId\":1002,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"status\",\"offset\":16,\"slot\":\"0\",\"type\":\"t_enum(GameStatus)1010\"},{\"astId\":1003,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"claimData\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_struct(ClaimData)1011_storage)dyn_storage\"},{\"astId\":1004,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"credit\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":1005,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"claims\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_mapping(t_userDefinedValueType(ClaimHash)1014,t_bool)\"},{\"astId\":1006,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"subgames\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_mapping(t_uint256,t_array(t_uint256)dyn_storage)\"},{\"astId\":1007,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"subgameAtRootResolved\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_bool\"},{\"astId\":1008,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"initialized\",\"offset\":1,\"slot\":\"5\",\"type\":\"t_bool\"},{\"astId\":1009,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"startingOutputRoot\",\"offset\":0,\"slot\":\"6\",\"type\":\"t_struct(OutputRoot)1012_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_struct(ClaimData)1011_storage)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"struct IFaultDisputeGame.ClaimData[]\",\"numberOfBytes\":\"32\",\"base\":\"t_struct(ClaimData)1011_storage\"},\"t_array(t_uint256)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"uint256[]\",\"numberOfBytes\":\"32\",\"base\":\"t_uint256\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_enum(GameStatus)1010\":{\"encoding\":\"inplace\",\"label\":\"enum GameStatus\",\"numberOfBytes\":\"1\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_mapping(t_uint256,t_array(t_uint256)dyn_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e uint256[])\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_array(t_uint256)dyn_storage\"},\"t_mapping(t_userDefinedValueType(ClaimHash)1014,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(ClaimHash =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_userDefinedValueType(ClaimHash)1014\",\"value\":\"t_bool\"},\"t_struct(ClaimData)1011_storage\":{\"encoding\":\"inplace\",\"label\":\"struct IFaultDisputeGame.ClaimData\",\"numberOfBytes\":\"160\"},\"t_struct(OutputRoot)1012_storage\":{\"encoding\":\"inplace\",\"label\":\"struct OutputRoot\",\"numberOfBytes\":\"64\"},\"t_uint128\":{\"encoding\":\"inplace\",\"label\":\"uint128\",\"numberOfBytes\":\"16\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint32\":{\"encoding\":\"inplace\",\"label\":\"uint32\",\"numberOfBytes\":\"4\"},\"t_userDefinedValueType(Claim)1013\":{\"encoding\":\"inplace\",\"label\":\"Claim\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(ClaimHash)1014\":{\"encoding\":\"inplace\",\"label\":\"ClaimHash\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(Clock)1015\":{\"encoding\":\"inplace\",\"label\":\"Clock\",\"numberOfBytes\":\"16\"},\"t_userDefinedValueType(Hash)1016\":{\"encoding\":\"inplace\",\"label\":\"Hash\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(Position)1017\":{\"encoding\":\"inplace\",\"label\":\"Position\",\"numberOfBytes\":\"16\"},\"t_userDefinedValueType(Timestamp)1018\":{\"encoding\":\"inplace\",\"label\":\"Timestamp\",\"numberOfBytes\":\"8\"}}}" var FaultDisputeGameStorageLayout = new(solc.StorageLayout) -var FaultDisputeGameDeployedBin = "0x6080604052600436106101cd5760003560e01c80638d450a95116100f7578063d5d44d8011610095578063f8f43ff611610064578063f8f43ff614610694578063fa24f743146106b4578063fa315aa9146106d8578063fdffbb281461070b57600080fd5b8063d5d44d80146105e1578063d8cc1a3c1461060e578063e1f0c3761461062e578063ec5e63081461066157600080fd5b8063c395e1ca116100d1578063c395e1ca14610502578063c55cd0c714610523578063c6f0308c14610536578063cf09e0d0146105c057600080fd5b80638d450a9514610454578063bbdc02db14610487578063bcef3b55146104c557600080fd5b8063609d33341161016f57806368800abf1161013e57806368800abf146103c45780638129fc1c146103f75780638980e0cc146103ff5780638b85902b1461041457600080fd5b8063609d33341461036657806360e274641461037b578063632247ea1461039b5780636361506d146103ae57600080fd5b80632810e1d6116101ab5780632810e1d61461029557806335fef567146102aa5780633a768463146102bf57806354fd4d501461031057600080fd5b80630356fe3a146101d257806319effeb414610214578063200d2ed21461025a575b600080fd5b3480156101de57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b34801561022057600080fd5b506000546102419068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161020b565b34801561026657600080fd5b5060005461028890700100000000000000000000000000000000900460ff1681565b60405161020b9190613244565b3480156102a157600080fd5b5061028861071e565b6102bd6102b8366004613285565b61091b565b005b3480156102cb57600080fd5b5060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161020b565b34801561031c57600080fd5b506103596040518060400160405280600681526020017f302e302e3234000000000000000000000000000000000000000000000000000081525081565b60405161020b9190613312565b34801561037257600080fd5b5061035961092b565b34801561038757600080fd5b506102bd610396366004613347565b61093d565b6102bd6103a9366004613380565b6109ed565b3480156103ba57600080fd5b5061020160015481565b3480156103d057600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610201565b6102bd6111e8565b34801561040b57600080fd5b50600254610201565b34801561042057600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360200135610201565b34801561046057600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610201565b34801561049357600080fd5b5060405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161020b565b3480156104d157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335610201565b34801561050e57600080fd5b5061020161051d3660046133b5565b50600090565b6102bd610531366004613285565b61150e565b34801561054257600080fd5b506105566105513660046133e7565b61151a565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161020b565b3480156105cc57600080fd5b506000546102419067ffffffffffffffff1681565b3480156105ed57600080fd5b506102016105fc366004613347565b60036020526000908152604090205481565b34801561061a57600080fd5b506102bd610629366004613449565b6115b1565b34801561063a57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610241565b34801561066d57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610201565b3480156106a057600080fd5b506102bd6106af3660046134d3565b611b8f565b3480156106c057600080fd5b506106c9611ff8565b60405161020b939291906134ff565b3480156106e457600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610201565b6102bd6107193660046133e7565b612055565b600080600054700100000000000000000000000000000000900460ff16600281111561074c5761074c613215565b14610783576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60065460ff166107bf576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106107eb576107eb61352a565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614610826576001610829565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156108da576108da613215565b0217905560028111156108ef576108ef613215565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a290565b610927828260006109ed565b5050565b606061093860208061241c565b905090565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260036020526040808220805490839055905190929083908381818185875af1925050503d80600081146109a8576040519150601f19603f3d011682016040523d82523d6000602084013e6109ad565b606091505b50509050806109e8576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60008054700100000000000000000000000000000000900460ff166002811115610a1957610a19613215565b14610a50576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110610a6557610a6561352a565b600091825260208083206040805160e0810182526005909402909101805463ffffffff808216865273ffffffffffffffffffffffffffffffffffffffff6401000000009092048216948601949094526001820154169184019190915260028101546fffffffffffffffffffffffffffffffff90811660608501526003820154608085015260049091015480821660a0850181905270010000000000000000000000000000000090910490911660c0840152919350909190610b2a90839086906124b316565b90506000610bca826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169050861580610c0c5750610c097f00000000000000000000000000000000000000000000000000000000000000006002613588565b81145b8015610c16575084155b15610c4d576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000811115610ca7576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cd27f00000000000000000000000000000000000000000000000000000000000000006001613588565b8103610ce457610ce4868885886124bb565b835160009063ffffffff90811614610d44576002856000015163ffffffff1681548110610d1357610d1361352a565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b60c0850151600090610d689067ffffffffffffffff165b67ffffffffffffffff1690565b67ffffffffffffffff1642610d92610d5b856fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16610da69190613588565b610db091906135a0565b90507f000000000000000000000000000000000000000000000000000000000000000060011c677fffffffffffffff1667ffffffffffffffff82161115610e23576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000604082901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615610ea1576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555050503360028c815481106111265761112661352a565b60009182526020808320600592830201805473ffffffffffffffffffffffffffffffffffffffff95909516640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909516949094179093558d82529091526040902060025461119c906001906135a0565b8154600181018355600092835260208320015560405133918c918e917f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be91a45050505050505050505050565b600654610100900460ff161561122a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360200135116112e1576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560048201526024015b60405180910390fd5b60463611156112f85763c407e0256000526004601cfd5b6040805160e08101825263ffffffff8152600060208201523291810191909152346fffffffffffffffffffffffffffffffff16606082015260029060808101367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335815260016020820152604001426fffffffffffffffffffffffffffffffff90811690915282546001808201855560009485526020808620855160059094020180549186015163ffffffff9094167fffffffffffffffff0000000000000000000000000000000000000000000000009092169190911764010000000073ffffffffffffffffffffffffffffffffffffffff94851602178155604085015181830180547fffffffffffffffffffffffff000000000000000000000000000000000000000016919094161790925560608401516002830180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169185169190911790556080840151600383015560a084015160c09094015193831670010000000000000000000000000000000094909316939093029190911760049091015581547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff16179091556114dc90436135a0565b40600155600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b610927828260016109ed565b6002818154811061152a57600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff1660028111156115dd576115dd613215565b14611614576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600287815481106116295761162961352a565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506116887f00000000000000000000000000000000000000000000000000000000000000006001613588565b611724826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1614611765576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808915611854576117b87f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006135a0565b6001901b6117d7846fffffffffffffffffffffffffffffffff16612673565b67ffffffffffffffff166117eb91906135e6565b156118285761181f61181060016fffffffffffffffffffffffffffffffff87166135fa565b865463ffffffff166000612719565b6003015461184a565b7f00000000000000000000000000000000000000000000000000000000000000005b915084905061187e565b6003850154915061187b6118106fffffffffffffffffffffffffffffffff8616600161362b565b90505b600882901b60088a8a60405161189592919061365f565b6040518091039020901b146118d6576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006118e18c6127fd565b905060006118f0836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e14ced329061196a908f908f908f908f908a906004016136b8565b6020604051808303816000875af1158015611989573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ad91906136f2565b600485015491149150600090600290611a58906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b611af4896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b611afe919061370b565b611b08919061372c565b67ffffffffffffffff161590508115158103611b50576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff166002811115611bbb57611bbb613215565b14611bf2576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600080611c018661282c565b93509350935093506000611c1785858585612c59565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611caa9190613753565b905060018903611d725773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a846001545b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af1158015611d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d6c91906136f2565b50611fed565b60028903611d9e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489611cd6565b60038903611dca5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487611cd6565b60048903611f425760006fffffffffffffffffffffffffffffffff861615611e6257611e286fffffffffffffffffffffffffffffffff87167f0000000000000000000000000000000000000000000000000000000000000000612d18565b611e52907f0000000000000000000000000000000000000000000000000000000000000000613588565b611e5d906001613588565b611e84565b7f00000000000000000000000000000000000000000000000000000000000000005b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af1158015611f17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3b91906136f2565b5050611fed565b60058903611fbb576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390524660c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a401611d29565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335606061204e61092b565b9050909192565b60008054700100000000000000000000000000000000900460ff16600281111561208157612081613215565b146120b8576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600282815481106120cd576120cd61352a565b60009182526020822060059190910201600481015490925061210f90700100000000000000000000000000000000900460401c67ffffffffffffffff16610d5b565b600483015490915060009061214190700100000000000000000000000000000000900467ffffffffffffffff16610d5b565b61214b904261370b565b9050677fffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000060011c166121858284613770565b67ffffffffffffffff16116121c6576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526005602052604090208054851580156121e6575060065460ff165b1561221d576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8015801561222a57508515155b1561225c5760018501546122549073ffffffffffffffffffffffffffffffffffffffff1686612dcd565b505050505050565b6000805b8281101561233b57600084828154811061227c5761227c61352a565b60009182526020808320909101548083526005909152604090912054909150156122d2576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600282815481106122e7576122e761352a565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff1661232857339350505061233b565b50508061233490613793565b9050612260565b5061238373ffffffffffffffffffffffffffffffffffffffff821615612361578161237d565b600187015473ffffffffffffffffffffffffffffffffffffffff165b87612dcd565b85547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff83160217865560008781526005602052604081206123df916131db565b8660000361241357600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b50505050505050565b6060600061245384367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003613588565b90508267ffffffffffffffff1667ffffffffffffffff811115612478576124786137cb565b6040519080825280601f01601f1916602001820160405280156124a2576020820181803683370190505b509150828160208401375092915050565b151760011b90565b60006124da6fffffffffffffffffffffffffffffffff8416600161362b565b905060006124ea82866001612719565b9050600086901a83806125dd575061252360027f00000000000000000000000000000000000000000000000000000000000000006135e6565b60048301546002906125c7906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6125d1919061372c565b67ffffffffffffffff16145b156126355760ff8116600114806125f7575060ff81166002145b612630576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016112d8565b612413565b60ff811615612413576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016112d8565b600080612700837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600167ffffffffffffffff919091161b90920392915050565b600080826127625761275d6fffffffffffffffffffffffffffffffff86167f0000000000000000000000000000000000000000000000000000000000000000612eb8565b61277d565b61277d856fffffffffffffffffffffffffffffffff1661307f565b9050600284815481106127925761279261352a565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146127f557815460028054909163ffffffff169081106127e0576127e061352a565b906000526020600020906005020191506127a3565b509392505050565b600080600080600061280e8661282c565b935093509350935061282284848484612c59565b9695505050505050565b600080600080600085905060006002828154811061284c5761284c61352a565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000090612923906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1611612964576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000090612a2b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169250821115612aa757825463ffffffff16612a717f00000000000000000000000000000000000000000000000000000000000000006001613588565b8303612a7b578391505b60028181548110612a8e57612a8e61352a565b9060005260206000209060050201935080945050612968565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff16612b10612afb856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015612bf5576000612b48836fffffffffffffffffffffffffffffffff16612673565b67ffffffffffffffff161115612bab576000612b82612b7a60016fffffffffffffffffffffffffffffffff86166135fa565b896001612719565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50612bcf9050565b7f00000000000000000000000000000000000000000000000000000000000000009a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750612c4b565b6000612c17612b7a6fffffffffffffffffffffffffffffffff8516600161362b565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff84168103612cbf578282604051602001612ca29291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b604051602081830303815290604052805190602001209050612d10565b60408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a0016040516020818303038152906040528051906020012090505b949350505050565b600080612da5847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1690508083036001841b600180831b0386831b17039250505092915050565b60028101546fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff000000000000000000000000000000018101612e3d576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002820180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff17905573ffffffffffffffffffffffffffffffffffffffff831660009081526003602052604081208054839290612eae908490613588565b9091555050505050565b600081612f57846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1611612f98576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fa18361307f565b905081613040826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff16116130795761307661305d836001613588565b6fffffffffffffffffffffffffffffffff83169061312b565b90505b92915050565b60008119600183011681613113827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169390931c8015179392505050565b6000806131b8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169050808303600180821b0385821b179250505092915050565b50805460008255906000526020600020908101906131f991906131fc565b50565b5b8082111561321157600081556001016131fd565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061327f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561329857600080fd5b50508035926020909101359150565b6000815180845260005b818110156132cd576020818501810151868301820152016132b1565b818111156132df576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061307660208301846132a7565b73ffffffffffffffffffffffffffffffffffffffff811681146131f957600080fd5b60006020828403121561335957600080fd5b813561336481613325565b9392505050565b8035801515811461337b57600080fd5b919050565b60008060006060848603121561339557600080fd5b83359250602084013591506133ac6040850161336b565b90509250925092565b6000602082840312156133c757600080fd5b81356fffffffffffffffffffffffffffffffff8116811461336457600080fd5b6000602082840312156133f957600080fd5b5035919050565b60008083601f84011261341257600080fd5b50813567ffffffffffffffff81111561342a57600080fd5b60208301915083602082850101111561344257600080fd5b9250929050565b6000806000806000806080878903121561346257600080fd5b863595506134726020880161336b565b9450604087013567ffffffffffffffff8082111561348f57600080fd5b61349b8a838b01613400565b909650945060608901359150808211156134b457600080fd5b506134c189828a01613400565b979a9699509497509295939492505050565b6000806000606084860312156134e857600080fd5b505081359360208301359350604090920135919050565b60ff8416815282602082015260606040820152600061352160608301846132a7565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561359b5761359b613559565b500190565b6000828210156135b2576135b2613559565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826135f5576135f56135b7565b500690565b60006fffffffffffffffffffffffffffffffff8381169083168181101561362357613623613559565b039392505050565b60006fffffffffffffffffffffffffffffffff80831681851680830382111561365657613656613559565b01949350505050565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6060815260006136cc60608301878961366f565b82810360208401526136df81868861366f565b9150508260408301529695505050505050565b60006020828403121561370457600080fd5b5051919050565b600067ffffffffffffffff8381169083168181101561362357613623613559565b600067ffffffffffffffff80841680613747576137476135b7565b92169190910692915050565b60006020828403121561376557600080fd5b815161336481613325565b600067ffffffffffffffff80831681851680830382111561365657613656613559565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036137c4576137c4613559565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea164736f6c634300080f000a" +var FaultDisputeGameDeployedBin = "0x6080604052600436106101ff5760003560e01c80638d450a951161010e578063d6ae3cd5116100a7578063f3f7214e11610079578063fa24f74311610061578063fa24f7431461079c578063fa315aa9146107c0578063fdffbb28146107f357005b8063f3f7214e14610751578063f8f43ff61461077c57005b8063d6ae3cd514610698578063d8cc1a3c146106cb578063e1f0c376146106eb578063ec5e63081461071e57005b8063c55cd0c7116100e0578063c55cd0c7146105ad578063c6f0308c146105c0578063cf09e0d01461064a578063d5d44d801461066b57005b80638d450a95146104dc578063bbdc02db1461050f578063bcef3b5514610550578063c395e1ca1461058d57005b806357da950e116101985780636361506d1161016a5780638129fc1c116101525780638129fc1c1461047f5780638980e0cc146104875780638b85902b1461049c57005b80636361506d1461042a57806370872aa51461046a57005b806357da950e146103b2578063609d3334146103e257806360e27464146103f7578063632247ea1461041757005b806335fef567116101d157806335fef567146102c25780633a768463146102d55780633fc8cef31461032957806354fd4d501461035c57005b806319effeb414610208578063200d2ed21461025357806325fc2ace1461028e5780632810e1d6146102ad57005b3661020657005b005b34801561021457600080fd5b506000546102359068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561025f57600080fd5b5060005461028190700100000000000000000000000000000000900460ff1681565b60405161024a9190613f78565b34801561029a57600080fd5b506006545b60405190815260200161024a565b3480156102b957600080fd5b50610281610806565b6102066102d0366004613fb9565b610a83565b3480156102e157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161024a565b34801561033557600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610304565b34801561036857600080fd5b506103a56040518060400160405280600581526020017f302e382e3100000000000000000000000000000000000000000000000000000081525081565b60405161024a9190614046565b3480156103be57600080fd5b506006546007546103cd919082565b6040805192835260208301919091520161024a565b3480156103ee57600080fd5b506103a5610a93565b34801561040357600080fd5b5061020661041236600461407b565b610aa6565b6102066104253660046140b4565b610c52565b34801561043657600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036020013561029f565b34801561047657600080fd5b5060075461029f565b6102066114ca565b34801561049357600080fd5b5060015461029f565b3480156104a857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036040013561029f565b3480156104e857600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061029f565b34801561051b57600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161024a565b34801561055c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033561029f565b34801561059957600080fd5b5061029f6105a83660046140e9565b6119f6565b6102066105bb366004613fb9565b611be0565b3480156105cc57600080fd5b506105e06105db36600461411b565b611bec565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161024a565b34801561065657600080fd5b506000546102359067ffffffffffffffff1681565b34801561067757600080fd5b5061029f61068636600461407b565b60026020526000908152604090205481565b3480156106a457600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061029f565b3480156106d757600080fd5b506102066106e636600461417d565b611c83565b3480156106f757600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610235565b34801561072a57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061029f565b34801561075d57600080fd5b506040516fffffffffffffffffffffffffffffffff815260200161024a565b34801561078857600080fd5b50610206610797366004614207565b6122b8565b3480156107a857600080fd5b506107b1612715565b60405161024a93929190614233565b3480156107cc57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061029f565b61020661080136600461411b565b612772565b600080600054700100000000000000000000000000000000900460ff16600281111561083457610834613f49565b1461086b576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055460ff166108a7576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660016000815481106108d3576108d3614261565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff161461090e576001610911565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156109c2576109c2613f49565b0217905560028111156109d7576109d7613f49565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610a6857600080fd5b505af1158015610a7c573d6000803e3d6000fd5b5050505090565b610a8f82826000610c52565b5050565b6060610aa160406020612bd3565b905090565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260026020526040812080549082905590819003610b0b576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063f3fef3a390604401600060405180830381600087803b158015610b9b57600080fd5b505af1158015610baf573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610c0d576040519150601f19603f3d011682016040523d82523d6000602084013e610c12565b606091505b5050905080610c4d576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60008054700100000000000000000000000000000000900460ff166002811115610c7e57610c7e613f49565b14610cb5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060018481548110610cca57610cca614261565b600091825260208083206040805160e0810182526005909402909101805463ffffffff808216865273ffffffffffffffffffffffffffffffffffffffff6401000000009092048216948601949094526001820154169184019190915260028101546fffffffffffffffffffffffffffffffff90811660608501526003820154608085015260049091015480821660a0850181905270010000000000000000000000000000000090910490911660c0840152919350909190610d8f9083908690612c6a16565b90506000610e2f826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169050861580610e715750610e6e7f000000000000000000000000000000000000000000000000000000000000000060026142bf565b81145b8015610e7b575084155b15610eb2576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000811115610f0c576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f377f000000000000000000000000000000000000000000000000000000000000000060016142bf565b8103610f4957610f4986888588612c72565b34610f53836119f6565b1115610f8b576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835160009063ffffffff90811614610feb576001856000015163ffffffff1681548110610fba57610fba614261565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b60c085015160009061100f9067ffffffffffffffff165b67ffffffffffffffff1690565b67ffffffffffffffff1642611039611002856fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff1661104d91906142bf565b61105791906142d7565b90507f000000000000000000000000000000000000000000000000000000000000000060011c677fffffffffffffff1667ffffffffffffffff821611156110ca576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000604082901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526003602052604090205490915060ff1615611148576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016003600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060016040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600460008c8152602001908152602001600020600180805490506113dd91906142d7565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263d0e30db09234926004808301939282900301818588803b15801561147557600080fd5b505af1158015611489573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a45050505050505050505050565b600554610100900460ff161561150c576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690637258a807906024016040805180830381865afa1580156115c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e491906142ee565b909250905081611620576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082018252838152602001829052600683905560078290558190367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90030135116116d2576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560048201526024015b60405180910390fd5b60663611156116e95763c407e0256000526004601cfd5b6040805160e08101825263ffffffff808252600060208301818152328486019081526fffffffffffffffffffffffffffffffff34818116606088019081527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90033560808901908152600160a08a0181815242861660c08c0190815282548084018455928a529a5160059092027fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf681018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915594517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf787018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905590517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf8860180549185167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909216919091179055517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf9850155915195518116700100000000000000000000000000000000029516949094177fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfa9091015583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f00000000000000000000000000000000000000000000000000000000000000009092169363d0e30db093926004828101939282900301818588803b15801561197757600080fd5b505af115801561198b573d6000803e3d6000fd5b50506000805467ffffffffffffffff42167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009091161790555050600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055505050565b600080611a95836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1690507f0000000000000000000000000000000000000000000000000000000000000000811115611afb576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a80630bebc2006000611b168383614341565b9050670de0b6b3a76400006000611b4d827f0000000000000000000000000000000000000000000000000000000000000000614355565b90506000611b6b611b66670de0b6b3a764000086614355565b612e33565b90506000611b79848461308e565b90506000611b8783836130dd565b90506000611b948261310b565b90506000611bb382611bae670de0b6b3a76400008f614355565b6132f3565b90506000611bc18b836130dd565b9050611bcd818d614355565b9f9e505050505050505050505050505050565b610a8f82826001610c52565b60018181548110611bfc57600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115611caf57611caf613f49565b14611ce6576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060018781548110611cfb57611cfb614261565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050611d5a7f000000000000000000000000000000000000000000000000000000000000000060016142bf565b611df6826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1614611e37576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808915611f2657611e8a7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006142d7565b6001901b611ea9846fffffffffffffffffffffffffffffffff1661332d565b67ffffffffffffffff16611ebd9190614392565b15611efa57611ef1611ee260016fffffffffffffffffffffffffffffffff87166143a6565b865463ffffffff1660006133d3565b60030154611f1c565b7f00000000000000000000000000000000000000000000000000000000000000005b9150849050611f50565b60038501549150611f4d611ee26fffffffffffffffffffffffffffffffff861660016143d7565b90505b600882901b60088a8a604051611f6792919061440b565b6040518091039020901b14611fa8576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611fb38c6134b7565b90506000611fc2836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e14ced329061203c908f908f908f908f908a90600401614464565b6020604051808303816000875af115801561205b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207f919061449e565b60048501549114915060009060029061212a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6121c6896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6121d091906144b7565b6121da91906144d8565b67ffffffffffffffff161590508115158103612222576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff1615612279576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156122e4576122e4613f49565b1461231b576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061232a866134e6565b93509350935093506000612340858585856138f5565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d391906144ff565b9050600189036124cb5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461242f367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036020013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156124a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124c5919061449e565b5061270a565b600289036124f75773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961242f565b600389036125235773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761242f565b6004890361263f5760006125696fffffffffffffffffffffffffffffffff85167f00000000000000000000000000000000000000000000000000000000000000006139b4565b60075461257691906142bf565b6125819060016142bf565b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af1158015612614573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612638919061449e565b505061270a565b600589036126d8576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000000060c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a401612482565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335606061276b610a93565b9050909192565b60008054700100000000000000000000000000000000900460ff16600281111561279e5761279e613f49565b146127d5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600182815481106127ea576127ea614261565b60009182526020822060059190910201600481015490925061282c90700100000000000000000000000000000000900460401c67ffffffffffffffff16611002565b600483015490915060009061285e90700100000000000000000000000000000000900467ffffffffffffffff16611002565b61286890426144b7565b9050677fffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000060011c166128a2828461451c565b67ffffffffffffffff16116128e3576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000848152600460205260409020805485158015612903575060055460ff165b1561293a576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8015801561294757508515155b156129ac578454640100000000900473ffffffffffffffffffffffffffffffffffffffff166000811561297a5781612996565b600187015473ffffffffffffffffffffffffffffffffffffffff165b90506129a28188613a69565b5050505050505050565b60006fffffffffffffffffffffffffffffffff815b83811015612af25760008582815481106129dd576129dd614261565b6000918252602080832090910154808352600490915260409091205490915015612a33576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060018281548110612a4857612a48614261565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff16158015612aa1575060048101546fffffffffffffffffffffffffffffffff908116908516115b15612adf576001810154600482015473ffffffffffffffffffffffffffffffffffffffff90911695506fffffffffffffffffffffffffffffffff1693505b505080612aeb9061453f565b90506129c1565b50612b3a73ffffffffffffffffffffffffffffffffffffffff831615612b185782612b34565b600188015473ffffffffffffffffffffffffffffffffffffffff165b88613a69565b86547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8416021787556000888152600460205260408120612b9691613f0f565b876000036129a257600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555050505050505050565b60606000612c0a84367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036142bf565b90508267ffffffffffffffff1667ffffffffffffffff811115612c2f57612c2f614577565b6040519080825280601f01601f191660200182016040528015612c59576020820181803683370190505b509150828160208401375092915050565b151760011b90565b6000612c916fffffffffffffffffffffffffffffffff841660016143d7565b90506000612ca1828660016133d3565b9050600086901a8380612d945750612cda60027f0000000000000000000000000000000000000000000000000000000000000000614392565b6004830154600290612d7e906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b612d8891906144d8565b67ffffffffffffffff16145b15612dec5760ff811660011480612dae575060ff81166002145b612de7576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016116c9565b612e2a565b60ff811615612e2a576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016116c9565b50505050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213612e9257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a7640000021582026130cb57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156130fb5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361313957919050565b680755bf798b4a1bf1e582126131575763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613324670de0b6b3a76400008361330b86612e33565b61331591906145a6565b61331f9190614662565b61310b565b90505b92915050565b6000806133ba837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600167ffffffffffffffff919091161b90920392915050565b6000808261341c576134176fffffffffffffffffffffffffffffffff86167f0000000000000000000000000000000000000000000000000000000000000000613bf5565b613437565b613437856fffffffffffffffffffffffffffffffff16613db3565b90506001848154811061344c5761344c614261565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146134af57815460018054909163ffffffff1690811061349a5761349a614261565b9060005260206000209060050201915061345d565b509392505050565b60008060008060006134c8866134e6565b93509350935093506134dc848484846138f5565b9695505050505050565b600080600080600085905060006001828154811061350657613506614261565b600091825260209091206004600590920201908101549091507f0000000000000000000000000000000000000000000000000000000000000000906135dd906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff161161361e576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f0000000000000000000000000000000000000000000000000000000000000000906136e5906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff16925082111561376157825463ffffffff1661372b7f000000000000000000000000000000000000000000000000000000000000000060016142bf565b8303613735578391505b6001818154811061374857613748614261565b9060005260206000209060050201935080945050613622565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166137ca6137b5856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015613891576000613802836fffffffffffffffffffffffffffffffff1661332d565b67ffffffffffffffff16111561386557600061383c61383460016fffffffffffffffffffffffffffffffff86166143a6565b8960016133d3565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a5061386b9050565b6006549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff1697506138e7565b60006138b36138346fffffffffffffffffffffffffffffffff851660016143d7565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff8416810361395b57828260405160200161393e9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012090506139ac565b60408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a0016040516020818303038152906040528051906020012090505b949350505050565b600080613a41847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1690508083036001841b600180831b0386831b17039250505092915050565b60028101546fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff000000000000000000000000000000018101613ad9576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280830180547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff17905573ffffffffffffffffffffffffffffffffffffffff84166000908152602091909152604081208054839290613b4c9084906142bf565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f00000000000000000000000000000000000000000000000000000000000000001690637eee288d90604401600060405180830381600087803b158015613be157600080fd5b505af1158015612e2a573d6000803e3d6000fd5b600081613c94846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1611613cd5576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613cde83613db3565b905081613d7d826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff161161332757613324613d9a8360016142bf565b6fffffffffffffffffffffffffffffffff831690613e5f565b60008119600183011681613e47827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169390931c8015179392505050565b600080613eec847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169050808303600180821b0385821b179250505092915050565b5080546000825590600052602060002090810190613f2d9190613f30565b50565b5b80821115613f455760008155600101613f31565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310613fb3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060408385031215613fcc57600080fd5b50508035926020909101359150565b6000815180845260005b8181101561400157602081850181015186830182015201613fe5565b81811115614013576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006133246020830184613fdb565b73ffffffffffffffffffffffffffffffffffffffff81168114613f2d57600080fd5b60006020828403121561408d57600080fd5b813561409881614059565b9392505050565b803580151581146140af57600080fd5b919050565b6000806000606084860312156140c957600080fd5b83359250602084013591506140e06040850161409f565b90509250925092565b6000602082840312156140fb57600080fd5b81356fffffffffffffffffffffffffffffffff8116811461409857600080fd5b60006020828403121561412d57600080fd5b5035919050565b60008083601f84011261414657600080fd5b50813567ffffffffffffffff81111561415e57600080fd5b60208301915083602082850101111561417657600080fd5b9250929050565b6000806000806000806080878903121561419657600080fd5b863595506141a66020880161409f565b9450604087013567ffffffffffffffff808211156141c357600080fd5b6141cf8a838b01614134565b909650945060608901359150808211156141e857600080fd5b506141f589828a01614134565b979a9699509497509295939492505050565b60008060006060848603121561421c57600080fd5b505081359360208301359350604090920135919050565b63ffffffff841681528260208201526060604082015260006142586060830184613fdb565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156142d2576142d2614290565b500190565b6000828210156142e9576142e9614290565b500390565b6000806040838503121561430157600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261435057614350614312565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561438d5761438d614290565b500290565b6000826143a1576143a1614312565b500690565b60006fffffffffffffffffffffffffffffffff838116908316818110156143cf576143cf614290565b039392505050565b60006fffffffffffffffffffffffffffffffff80831681851680830382111561440257614402614290565b01949350505050565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60608152600061447860608301878961441b565b828103602084015261448b81868861441b565b9150508260408301529695505050505050565b6000602082840312156144b057600080fd5b5051919050565b600067ffffffffffffffff838116908316818110156143cf576143cf614290565b600067ffffffffffffffff808416806144f3576144f3614312565b92169190910692915050565b60006020828403121561451157600080fd5b815161409881614059565b600067ffffffffffffffff80831681851680830382111561440257614402614290565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361457057614570614290565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156145e7576145e7614290565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561462257614622614290565b6000871292508782058712848416161561463e5761463e614290565b8785058712818416161561465457614654614290565b505050929093029392505050565b60008261467157614671614312565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156146c5576146c5614290565b50059056fea164736f6c634300080f000a" func init() { diff --git a/op-bindings/bindings/legacyerc20eth.go b/op-bindings/bindings/legacyerc20eth.go deleted file mode 100644 index 6d0ef99c1bad..000000000000 --- a/op-bindings/bindings/legacyerc20eth.go +++ /dev/null @@ -1,1381 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package bindings - -import ( - "errors" - "math/big" - "strings" - - ethereum "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 -) - -// LegacyERC20ETHMetaData contains all meta data concerning the LegacyERC20ETH contract. -var LegacyERC20ETHMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"BRIDGE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"REMOTE_TOKEN\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"_who\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"bridge\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"burn\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decreaseAllowance\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"increaseAllowance\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"l1Token\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"l2Bridge\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"mint\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"remoteToken\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"_interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"spender\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Burn\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Mint\",\"inputs\":[{\"name\":\"account\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false}]", - Bin: "0x60e06040523480156200001157600080fd5b5073420000000000000000000000000000000000001060006040518060400160405280600581526020016422ba3432b960d91b8152506040518060400160405280600381526020016208aa8960eb1b81525060128282816003908162000078919062000152565b50600462000087828262000152565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200021e565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620000d857607f821691505b602082108103620000f957634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200014d57600081815260208120601f850160051c81016020861015620001285750805b601f850160051c820191505b81811015620001495782815560010162000134565b5050505b505050565b81516001600160401b038111156200016e576200016e620000ad565b62000186816200017f8454620000c3565b84620000ff565b602080601f831160018114620001be5760008415620001a55750858301515b600019600386901b1c1916600185901b17855562000149565b600085815260208120601f198616915b82811015620001ef57888601518255948401946001909101908401620001ce565b50858210156200020e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c051610afe6200025c600039600061024401526000818161033d01526103d20152600081816101a901526103630152610afe6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610387578063e78cea921461033b578063ee9a31a2146103cd57600080fd5b8063ae1f6aaf1461033b578063c01e1bd614610361578063d6c0b2c41461036157600080fd5b80639dc29fac116100bd5780639dc29fac14610302578063a457c2d714610315578063a9059cbb1461032857600080fd5b806370a08231146102d257806395d89b41146102fa57600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004610905565b6103f4565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104e5565b60405161019b919061094e565b61018f6102133660046109ea565b610577565b6002545b60405190815260200161019b565b61018f610238366004610a14565b610607565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c3660046109ea565b610692565b61029461028f3660046109ea565b61071d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e0366004610a50565b73ffffffffffffffffffffffffffffffffffffffff163190565b6101f861077f565b6102946103103660046109ea565b61078e565b61018f6103233660046109ea565b6107f0565b61018f6103363660046109ea565b61087b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c610395366004610a6b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104ad57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104dc57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104f490610a9e565b80601f016020809104026020016040519081016040528092919081815260200182805461052090610a9e565b801561056d5780601f106105425761010080835404028352916020019161056d565b820191906000526020600020905b81548152906001019060200180831161055057829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4c656761637945524332304554483a20617070726f766520697320646973616260448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526000906084015b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4c656761637945524332304554483a207472616e7366657246726f6d2069732060448201527f64697361626c656400000000000000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a20696e637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206d696e742069732064697361626c656460448201526064016105fe565b6060600480546104f490610a9e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206275726e2069732064697361626c656460448201526064016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a206465637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4c656761637945524332304554483a207472616e73666572206973206469736160448201527f626c65640000000000000000000000000000000000000000000000000000000060648201526000906084016105fe565b60006020828403121561091757600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461094757600080fd5b9392505050565b600060208083528351808285015260005b8181101561097b5785810183015185820160400152820161095f565b8181111561098d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146109e557600080fd5b919050565b600080604083850312156109fd57600080fd5b610a06836109c1565b946020939093013593505050565b600080600060608486031215610a2957600080fd5b610a32846109c1565b9250610a40602085016109c1565b9150604084013590509250925092565b600060208284031215610a6257600080fd5b610947826109c1565b60008060408385031215610a7e57600080fd5b610a87836109c1565b9150610a95602084016109c1565b90509250929050565b600181811c90821680610ab257607f821691505b602082108103610aeb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b5091905056fea164736f6c634300080f000a", -} - -// LegacyERC20ETHABI is the input ABI used to generate the binding from. -// Deprecated: Use LegacyERC20ETHMetaData.ABI instead. -var LegacyERC20ETHABI = LegacyERC20ETHMetaData.ABI - -// LegacyERC20ETHBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use LegacyERC20ETHMetaData.Bin instead. -var LegacyERC20ETHBin = LegacyERC20ETHMetaData.Bin - -// DeployLegacyERC20ETH deploys a new Ethereum contract, binding an instance of LegacyERC20ETH to it. -func DeployLegacyERC20ETH(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *LegacyERC20ETH, error) { - parsed, err := LegacyERC20ETHMetaData.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(LegacyERC20ETHBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &LegacyERC20ETH{LegacyERC20ETHCaller: LegacyERC20ETHCaller{contract: contract}, LegacyERC20ETHTransactor: LegacyERC20ETHTransactor{contract: contract}, LegacyERC20ETHFilterer: LegacyERC20ETHFilterer{contract: contract}}, nil -} - -// LegacyERC20ETH is an auto generated Go binding around an Ethereum contract. -type LegacyERC20ETH struct { - LegacyERC20ETHCaller // Read-only binding to the contract - LegacyERC20ETHTransactor // Write-only binding to the contract - LegacyERC20ETHFilterer // Log filterer for contract events -} - -// LegacyERC20ETHCaller is an auto generated read-only Go binding around an Ethereum contract. -type LegacyERC20ETHCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LegacyERC20ETHTransactor is an auto generated write-only Go binding around an Ethereum contract. -type LegacyERC20ETHTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LegacyERC20ETHFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type LegacyERC20ETHFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// LegacyERC20ETHSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type LegacyERC20ETHSession struct { - Contract *LegacyERC20ETH // 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 -} - -// LegacyERC20ETHCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type LegacyERC20ETHCallerSession struct { - Contract *LegacyERC20ETHCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// LegacyERC20ETHTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type LegacyERC20ETHTransactorSession struct { - Contract *LegacyERC20ETHTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// LegacyERC20ETHRaw is an auto generated low-level Go binding around an Ethereum contract. -type LegacyERC20ETHRaw struct { - Contract *LegacyERC20ETH // Generic contract binding to access the raw methods on -} - -// LegacyERC20ETHCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type LegacyERC20ETHCallerRaw struct { - Contract *LegacyERC20ETHCaller // Generic read-only contract binding to access the raw methods on -} - -// LegacyERC20ETHTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type LegacyERC20ETHTransactorRaw struct { - Contract *LegacyERC20ETHTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewLegacyERC20ETH creates a new instance of LegacyERC20ETH, bound to a specific deployed contract. -func NewLegacyERC20ETH(address common.Address, backend bind.ContractBackend) (*LegacyERC20ETH, error) { - contract, err := bindLegacyERC20ETH(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &LegacyERC20ETH{LegacyERC20ETHCaller: LegacyERC20ETHCaller{contract: contract}, LegacyERC20ETHTransactor: LegacyERC20ETHTransactor{contract: contract}, LegacyERC20ETHFilterer: LegacyERC20ETHFilterer{contract: contract}}, nil -} - -// NewLegacyERC20ETHCaller creates a new read-only instance of LegacyERC20ETH, bound to a specific deployed contract. -func NewLegacyERC20ETHCaller(address common.Address, caller bind.ContractCaller) (*LegacyERC20ETHCaller, error) { - contract, err := bindLegacyERC20ETH(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &LegacyERC20ETHCaller{contract: contract}, nil -} - -// NewLegacyERC20ETHTransactor creates a new write-only instance of LegacyERC20ETH, bound to a specific deployed contract. -func NewLegacyERC20ETHTransactor(address common.Address, transactor bind.ContractTransactor) (*LegacyERC20ETHTransactor, error) { - contract, err := bindLegacyERC20ETH(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &LegacyERC20ETHTransactor{contract: contract}, nil -} - -// NewLegacyERC20ETHFilterer creates a new log filterer instance of LegacyERC20ETH, bound to a specific deployed contract. -func NewLegacyERC20ETHFilterer(address common.Address, filterer bind.ContractFilterer) (*LegacyERC20ETHFilterer, error) { - contract, err := bindLegacyERC20ETH(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &LegacyERC20ETHFilterer{contract: contract}, nil -} - -// bindLegacyERC20ETH binds a generic wrapper to an already deployed contract. -func bindLegacyERC20ETH(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := abi.JSON(strings.NewReader(LegacyERC20ETHABI)) - 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 (_LegacyERC20ETH *LegacyERC20ETHRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LegacyERC20ETH.Contract.LegacyERC20ETHCaller.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 (_LegacyERC20ETH *LegacyERC20ETHRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.LegacyERC20ETHTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_LegacyERC20ETH *LegacyERC20ETHRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.LegacyERC20ETHTransactor.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 (_LegacyERC20ETH *LegacyERC20ETHCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _LegacyERC20ETH.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 (_LegacyERC20ETH *LegacyERC20ETHTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_LegacyERC20ETH *LegacyERC20ETHTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.contract.Transact(opts, method, params...) -} - -// BRIDGE is a free data retrieval call binding the contract method 0xee9a31a2. -// -// Solidity: function BRIDGE() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) BRIDGE(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "BRIDGE") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// BRIDGE is a free data retrieval call binding the contract method 0xee9a31a2. -// -// Solidity: function BRIDGE() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHSession) BRIDGE() (common.Address, error) { - return _LegacyERC20ETH.Contract.BRIDGE(&_LegacyERC20ETH.CallOpts) -} - -// BRIDGE is a free data retrieval call binding the contract method 0xee9a31a2. -// -// Solidity: function BRIDGE() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) BRIDGE() (common.Address, error) { - return _LegacyERC20ETH.Contract.BRIDGE(&_LegacyERC20ETH.CallOpts) -} - -// REMOTETOKEN is a free data retrieval call binding the contract method 0x033964be. -// -// Solidity: function REMOTE_TOKEN() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) REMOTETOKEN(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "REMOTE_TOKEN") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// REMOTETOKEN is a free data retrieval call binding the contract method 0x033964be. -// -// Solidity: function REMOTE_TOKEN() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHSession) REMOTETOKEN() (common.Address, error) { - return _LegacyERC20ETH.Contract.REMOTETOKEN(&_LegacyERC20ETH.CallOpts) -} - -// REMOTETOKEN is a free data retrieval call binding the contract method 0x033964be. -// -// Solidity: function REMOTE_TOKEN() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) REMOTETOKEN() (common.Address, error) { - return _LegacyERC20ETH.Contract.REMOTETOKEN(&_LegacyERC20ETH.CallOpts) -} - -// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. -// -// Solidity: function allowance(address owner, address spender) view returns(uint256) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) Allowance(opts *bind.CallOpts, owner common.Address, spender common.Address) (*big.Int, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "allowance", owner, spender) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. -// -// Solidity: function allowance(address owner, address spender) view returns(uint256) -func (_LegacyERC20ETH *LegacyERC20ETHSession) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { - return _LegacyERC20ETH.Contract.Allowance(&_LegacyERC20ETH.CallOpts, owner, spender) -} - -// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. -// -// Solidity: function allowance(address owner, address spender) view returns(uint256) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { - return _LegacyERC20ETH.Contract.Allowance(&_LegacyERC20ETH.CallOpts, owner, spender) -} - -// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. -// -// Solidity: function balanceOf(address _who) view returns(uint256) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) BalanceOf(opts *bind.CallOpts, _who common.Address) (*big.Int, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "balanceOf", _who) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. -// -// Solidity: function balanceOf(address _who) view returns(uint256) -func (_LegacyERC20ETH *LegacyERC20ETHSession) BalanceOf(_who common.Address) (*big.Int, error) { - return _LegacyERC20ETH.Contract.BalanceOf(&_LegacyERC20ETH.CallOpts, _who) -} - -// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. -// -// Solidity: function balanceOf(address _who) view returns(uint256) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) BalanceOf(_who common.Address) (*big.Int, error) { - return _LegacyERC20ETH.Contract.BalanceOf(&_LegacyERC20ETH.CallOpts, _who) -} - -// Bridge is a free data retrieval call binding the contract method 0xe78cea92. -// -// Solidity: function bridge() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) Bridge(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "bridge") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Bridge is a free data retrieval call binding the contract method 0xe78cea92. -// -// Solidity: function bridge() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHSession) Bridge() (common.Address, error) { - return _LegacyERC20ETH.Contract.Bridge(&_LegacyERC20ETH.CallOpts) -} - -// Bridge is a free data retrieval call binding the contract method 0xe78cea92. -// -// Solidity: function bridge() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) Bridge() (common.Address, error) { - return _LegacyERC20ETH.Contract.Bridge(&_LegacyERC20ETH.CallOpts) -} - -// Decimals is a free data retrieval call binding the contract method 0x313ce567. -// -// Solidity: function decimals() view returns(uint8) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) Decimals(opts *bind.CallOpts) (uint8, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "decimals") - - if err != nil { - return *new(uint8), err - } - - out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) - - return out0, err - -} - -// Decimals is a free data retrieval call binding the contract method 0x313ce567. -// -// Solidity: function decimals() view returns(uint8) -func (_LegacyERC20ETH *LegacyERC20ETHSession) Decimals() (uint8, error) { - return _LegacyERC20ETH.Contract.Decimals(&_LegacyERC20ETH.CallOpts) -} - -// Decimals is a free data retrieval call binding the contract method 0x313ce567. -// -// Solidity: function decimals() view returns(uint8) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) Decimals() (uint8, error) { - return _LegacyERC20ETH.Contract.Decimals(&_LegacyERC20ETH.CallOpts) -} - -// L1Token is a free data retrieval call binding the contract method 0xc01e1bd6. -// -// Solidity: function l1Token() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) L1Token(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "l1Token") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// L1Token is a free data retrieval call binding the contract method 0xc01e1bd6. -// -// Solidity: function l1Token() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHSession) L1Token() (common.Address, error) { - return _LegacyERC20ETH.Contract.L1Token(&_LegacyERC20ETH.CallOpts) -} - -// L1Token is a free data retrieval call binding the contract method 0xc01e1bd6. -// -// Solidity: function l1Token() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) L1Token() (common.Address, error) { - return _LegacyERC20ETH.Contract.L1Token(&_LegacyERC20ETH.CallOpts) -} - -// L2Bridge is a free data retrieval call binding the contract method 0xae1f6aaf. -// -// Solidity: function l2Bridge() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) L2Bridge(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "l2Bridge") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// L2Bridge is a free data retrieval call binding the contract method 0xae1f6aaf. -// -// Solidity: function l2Bridge() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHSession) L2Bridge() (common.Address, error) { - return _LegacyERC20ETH.Contract.L2Bridge(&_LegacyERC20ETH.CallOpts) -} - -// L2Bridge is a free data retrieval call binding the contract method 0xae1f6aaf. -// -// Solidity: function l2Bridge() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) L2Bridge() (common.Address, error) { - return _LegacyERC20ETH.Contract.L2Bridge(&_LegacyERC20ETH.CallOpts) -} - -// Name is a free data retrieval call binding the contract method 0x06fdde03. -// -// Solidity: function name() view returns(string) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) Name(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "name") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -// Name is a free data retrieval call binding the contract method 0x06fdde03. -// -// Solidity: function name() view returns(string) -func (_LegacyERC20ETH *LegacyERC20ETHSession) Name() (string, error) { - return _LegacyERC20ETH.Contract.Name(&_LegacyERC20ETH.CallOpts) -} - -// Name is a free data retrieval call binding the contract method 0x06fdde03. -// -// Solidity: function name() view returns(string) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) Name() (string, error) { - return _LegacyERC20ETH.Contract.Name(&_LegacyERC20ETH.CallOpts) -} - -// RemoteToken is a free data retrieval call binding the contract method 0xd6c0b2c4. -// -// Solidity: function remoteToken() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) RemoteToken(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "remoteToken") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// RemoteToken is a free data retrieval call binding the contract method 0xd6c0b2c4. -// -// Solidity: function remoteToken() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHSession) RemoteToken() (common.Address, error) { - return _LegacyERC20ETH.Contract.RemoteToken(&_LegacyERC20ETH.CallOpts) -} - -// RemoteToken is a free data retrieval call binding the contract method 0xd6c0b2c4. -// -// Solidity: function remoteToken() view returns(address) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) RemoteToken() (common.Address, error) { - return _LegacyERC20ETH.Contract.RemoteToken(&_LegacyERC20ETH.CallOpts) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 _interfaceId) pure returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) SupportsInterface(opts *bind.CallOpts, _interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "supportsInterface", _interfaceId) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 _interfaceId) pure returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHSession) SupportsInterface(_interfaceId [4]byte) (bool, error) { - return _LegacyERC20ETH.Contract.SupportsInterface(&_LegacyERC20ETH.CallOpts, _interfaceId) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 _interfaceId) pure returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) SupportsInterface(_interfaceId [4]byte) (bool, error) { - return _LegacyERC20ETH.Contract.SupportsInterface(&_LegacyERC20ETH.CallOpts, _interfaceId) -} - -// Symbol is a free data retrieval call binding the contract method 0x95d89b41. -// -// Solidity: function symbol() view returns(string) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) Symbol(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "symbol") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -// Symbol is a free data retrieval call binding the contract method 0x95d89b41. -// -// Solidity: function symbol() view returns(string) -func (_LegacyERC20ETH *LegacyERC20ETHSession) Symbol() (string, error) { - return _LegacyERC20ETH.Contract.Symbol(&_LegacyERC20ETH.CallOpts) -} - -// Symbol is a free data retrieval call binding the contract method 0x95d89b41. -// -// Solidity: function symbol() view returns(string) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) Symbol() (string, error) { - return _LegacyERC20ETH.Contract.Symbol(&_LegacyERC20ETH.CallOpts) -} - -// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. -// -// Solidity: function totalSupply() view returns(uint256) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "totalSupply") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. -// -// Solidity: function totalSupply() view returns(uint256) -func (_LegacyERC20ETH *LegacyERC20ETHSession) TotalSupply() (*big.Int, error) { - return _LegacyERC20ETH.Contract.TotalSupply(&_LegacyERC20ETH.CallOpts) -} - -// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. -// -// Solidity: function totalSupply() view returns(uint256) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) TotalSupply() (*big.Int, error) { - return _LegacyERC20ETH.Contract.TotalSupply(&_LegacyERC20ETH.CallOpts) -} - -// Version is a free data retrieval call binding the contract method 0x54fd4d50. -// -// Solidity: function version() view returns(string) -func (_LegacyERC20ETH *LegacyERC20ETHCaller) Version(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _LegacyERC20ETH.contract.Call(opts, &out, "version") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -// Version is a free data retrieval call binding the contract method 0x54fd4d50. -// -// Solidity: function version() view returns(string) -func (_LegacyERC20ETH *LegacyERC20ETHSession) Version() (string, error) { - return _LegacyERC20ETH.Contract.Version(&_LegacyERC20ETH.CallOpts) -} - -// Version is a free data retrieval call binding the contract method 0x54fd4d50. -// -// Solidity: function version() view returns(string) -func (_LegacyERC20ETH *LegacyERC20ETHCallerSession) Version() (string, error) { - return _LegacyERC20ETH.Contract.Version(&_LegacyERC20ETH.CallOpts) -} - -// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. -// -// Solidity: function approve(address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHTransactor) Approve(opts *bind.TransactOpts, arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.contract.Transact(opts, "approve", arg0, arg1) -} - -// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. -// -// Solidity: function approve(address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHSession) Approve(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.Approve(&_LegacyERC20ETH.TransactOpts, arg0, arg1) -} - -// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. -// -// Solidity: function approve(address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHTransactorSession) Approve(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.Approve(&_LegacyERC20ETH.TransactOpts, arg0, arg1) -} - -// Burn is a paid mutator transaction binding the contract method 0x9dc29fac. -// -// Solidity: function burn(address , uint256 ) returns() -func (_LegacyERC20ETH *LegacyERC20ETHTransactor) Burn(opts *bind.TransactOpts, arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.contract.Transact(opts, "burn", arg0, arg1) -} - -// Burn is a paid mutator transaction binding the contract method 0x9dc29fac. -// -// Solidity: function burn(address , uint256 ) returns() -func (_LegacyERC20ETH *LegacyERC20ETHSession) Burn(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.Burn(&_LegacyERC20ETH.TransactOpts, arg0, arg1) -} - -// Burn is a paid mutator transaction binding the contract method 0x9dc29fac. -// -// Solidity: function burn(address , uint256 ) returns() -func (_LegacyERC20ETH *LegacyERC20ETHTransactorSession) Burn(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.Burn(&_LegacyERC20ETH.TransactOpts, arg0, arg1) -} - -// DecreaseAllowance is a paid mutator transaction binding the contract method 0xa457c2d7. -// -// Solidity: function decreaseAllowance(address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHTransactor) DecreaseAllowance(opts *bind.TransactOpts, arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.contract.Transact(opts, "decreaseAllowance", arg0, arg1) -} - -// DecreaseAllowance is a paid mutator transaction binding the contract method 0xa457c2d7. -// -// Solidity: function decreaseAllowance(address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHSession) DecreaseAllowance(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.DecreaseAllowance(&_LegacyERC20ETH.TransactOpts, arg0, arg1) -} - -// DecreaseAllowance is a paid mutator transaction binding the contract method 0xa457c2d7. -// -// Solidity: function decreaseAllowance(address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHTransactorSession) DecreaseAllowance(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.DecreaseAllowance(&_LegacyERC20ETH.TransactOpts, arg0, arg1) -} - -// IncreaseAllowance is a paid mutator transaction binding the contract method 0x39509351. -// -// Solidity: function increaseAllowance(address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHTransactor) IncreaseAllowance(opts *bind.TransactOpts, arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.contract.Transact(opts, "increaseAllowance", arg0, arg1) -} - -// IncreaseAllowance is a paid mutator transaction binding the contract method 0x39509351. -// -// Solidity: function increaseAllowance(address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHSession) IncreaseAllowance(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.IncreaseAllowance(&_LegacyERC20ETH.TransactOpts, arg0, arg1) -} - -// IncreaseAllowance is a paid mutator transaction binding the contract method 0x39509351. -// -// Solidity: function increaseAllowance(address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHTransactorSession) IncreaseAllowance(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.IncreaseAllowance(&_LegacyERC20ETH.TransactOpts, arg0, arg1) -} - -// Mint is a paid mutator transaction binding the contract method 0x40c10f19. -// -// Solidity: function mint(address , uint256 ) returns() -func (_LegacyERC20ETH *LegacyERC20ETHTransactor) Mint(opts *bind.TransactOpts, arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.contract.Transact(opts, "mint", arg0, arg1) -} - -// Mint is a paid mutator transaction binding the contract method 0x40c10f19. -// -// Solidity: function mint(address , uint256 ) returns() -func (_LegacyERC20ETH *LegacyERC20ETHSession) Mint(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.Mint(&_LegacyERC20ETH.TransactOpts, arg0, arg1) -} - -// Mint is a paid mutator transaction binding the contract method 0x40c10f19. -// -// Solidity: function mint(address , uint256 ) returns() -func (_LegacyERC20ETH *LegacyERC20ETHTransactorSession) Mint(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.Mint(&_LegacyERC20ETH.TransactOpts, arg0, arg1) -} - -// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. -// -// Solidity: function transfer(address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHTransactor) Transfer(opts *bind.TransactOpts, arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.contract.Transact(opts, "transfer", arg0, arg1) -} - -// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. -// -// Solidity: function transfer(address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHSession) Transfer(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.Transfer(&_LegacyERC20ETH.TransactOpts, arg0, arg1) -} - -// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. -// -// Solidity: function transfer(address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHTransactorSession) Transfer(arg0 common.Address, arg1 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.Transfer(&_LegacyERC20ETH.TransactOpts, arg0, arg1) -} - -// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. -// -// Solidity: function transferFrom(address , address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHTransactor) TransferFrom(opts *bind.TransactOpts, arg0 common.Address, arg1 common.Address, arg2 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.contract.Transact(opts, "transferFrom", arg0, arg1, arg2) -} - -// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. -// -// Solidity: function transferFrom(address , address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHSession) TransferFrom(arg0 common.Address, arg1 common.Address, arg2 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.TransferFrom(&_LegacyERC20ETH.TransactOpts, arg0, arg1, arg2) -} - -// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. -// -// Solidity: function transferFrom(address , address , uint256 ) returns(bool) -func (_LegacyERC20ETH *LegacyERC20ETHTransactorSession) TransferFrom(arg0 common.Address, arg1 common.Address, arg2 *big.Int) (*types.Transaction, error) { - return _LegacyERC20ETH.Contract.TransferFrom(&_LegacyERC20ETH.TransactOpts, arg0, arg1, arg2) -} - -// LegacyERC20ETHApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the LegacyERC20ETH contract. -type LegacyERC20ETHApprovalIterator struct { - Event *LegacyERC20ETHApproval // 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 *LegacyERC20ETHApprovalIterator) 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(LegacyERC20ETHApproval) - 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(LegacyERC20ETHApproval) - 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 *LegacyERC20ETHApprovalIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *LegacyERC20ETHApprovalIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// LegacyERC20ETHApproval represents a Approval event raised by the LegacyERC20ETH contract. -type LegacyERC20ETHApproval struct { - Owner common.Address - Spender common.Address - Value *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterApproval is a free log retrieval operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. -// -// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) -func (_LegacyERC20ETH *LegacyERC20ETHFilterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, spender []common.Address) (*LegacyERC20ETHApprovalIterator, error) { - - var ownerRule []interface{} - for _, ownerItem := range owner { - ownerRule = append(ownerRule, ownerItem) - } - var spenderRule []interface{} - for _, spenderItem := range spender { - spenderRule = append(spenderRule, spenderItem) - } - - logs, sub, err := _LegacyERC20ETH.contract.FilterLogs(opts, "Approval", ownerRule, spenderRule) - if err != nil { - return nil, err - } - return &LegacyERC20ETHApprovalIterator{contract: _LegacyERC20ETH.contract, event: "Approval", logs: logs, sub: sub}, nil -} - -// WatchApproval is a free log subscription operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. -// -// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) -func (_LegacyERC20ETH *LegacyERC20ETHFilterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *LegacyERC20ETHApproval, owner []common.Address, spender []common.Address) (event.Subscription, error) { - - var ownerRule []interface{} - for _, ownerItem := range owner { - ownerRule = append(ownerRule, ownerItem) - } - var spenderRule []interface{} - for _, spenderItem := range spender { - spenderRule = append(spenderRule, spenderItem) - } - - logs, sub, err := _LegacyERC20ETH.contract.WatchLogs(opts, "Approval", ownerRule, spenderRule) - 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(LegacyERC20ETHApproval) - if err := _LegacyERC20ETH.contract.UnpackLog(event, "Approval", 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 -} - -// ParseApproval is a log parse operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. -// -// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value) -func (_LegacyERC20ETH *LegacyERC20ETHFilterer) ParseApproval(log types.Log) (*LegacyERC20ETHApproval, error) { - event := new(LegacyERC20ETHApproval) - if err := _LegacyERC20ETH.contract.UnpackLog(event, "Approval", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// LegacyERC20ETHBurnIterator is returned from FilterBurn and is used to iterate over the raw logs and unpacked data for Burn events raised by the LegacyERC20ETH contract. -type LegacyERC20ETHBurnIterator struct { - Event *LegacyERC20ETHBurn // 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 *LegacyERC20ETHBurnIterator) 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(LegacyERC20ETHBurn) - 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(LegacyERC20ETHBurn) - 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 *LegacyERC20ETHBurnIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *LegacyERC20ETHBurnIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// LegacyERC20ETHBurn represents a Burn event raised by the LegacyERC20ETH contract. -type LegacyERC20ETHBurn struct { - Account common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterBurn is a free log retrieval operation binding the contract event 0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5. -// -// Solidity: event Burn(address indexed account, uint256 amount) -func (_LegacyERC20ETH *LegacyERC20ETHFilterer) FilterBurn(opts *bind.FilterOpts, account []common.Address) (*LegacyERC20ETHBurnIterator, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _LegacyERC20ETH.contract.FilterLogs(opts, "Burn", accountRule) - if err != nil { - return nil, err - } - return &LegacyERC20ETHBurnIterator{contract: _LegacyERC20ETH.contract, event: "Burn", logs: logs, sub: sub}, nil -} - -// WatchBurn is a free log subscription operation binding the contract event 0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5. -// -// Solidity: event Burn(address indexed account, uint256 amount) -func (_LegacyERC20ETH *LegacyERC20ETHFilterer) WatchBurn(opts *bind.WatchOpts, sink chan<- *LegacyERC20ETHBurn, account []common.Address) (event.Subscription, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _LegacyERC20ETH.contract.WatchLogs(opts, "Burn", accountRule) - 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(LegacyERC20ETHBurn) - if err := _LegacyERC20ETH.contract.UnpackLog(event, "Burn", 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 -} - -// ParseBurn is a log parse operation binding the contract event 0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5. -// -// Solidity: event Burn(address indexed account, uint256 amount) -func (_LegacyERC20ETH *LegacyERC20ETHFilterer) ParseBurn(log types.Log) (*LegacyERC20ETHBurn, error) { - event := new(LegacyERC20ETHBurn) - if err := _LegacyERC20ETH.contract.UnpackLog(event, "Burn", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// LegacyERC20ETHMintIterator is returned from FilterMint and is used to iterate over the raw logs and unpacked data for Mint events raised by the LegacyERC20ETH contract. -type LegacyERC20ETHMintIterator struct { - Event *LegacyERC20ETHMint // 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 *LegacyERC20ETHMintIterator) 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(LegacyERC20ETHMint) - 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(LegacyERC20ETHMint) - 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 *LegacyERC20ETHMintIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *LegacyERC20ETHMintIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// LegacyERC20ETHMint represents a Mint event raised by the LegacyERC20ETH contract. -type LegacyERC20ETHMint struct { - Account common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterMint is a free log retrieval operation binding the contract event 0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885. -// -// Solidity: event Mint(address indexed account, uint256 amount) -func (_LegacyERC20ETH *LegacyERC20ETHFilterer) FilterMint(opts *bind.FilterOpts, account []common.Address) (*LegacyERC20ETHMintIterator, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _LegacyERC20ETH.contract.FilterLogs(opts, "Mint", accountRule) - if err != nil { - return nil, err - } - return &LegacyERC20ETHMintIterator{contract: _LegacyERC20ETH.contract, event: "Mint", logs: logs, sub: sub}, nil -} - -// WatchMint is a free log subscription operation binding the contract event 0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885. -// -// Solidity: event Mint(address indexed account, uint256 amount) -func (_LegacyERC20ETH *LegacyERC20ETHFilterer) WatchMint(opts *bind.WatchOpts, sink chan<- *LegacyERC20ETHMint, account []common.Address) (event.Subscription, error) { - - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - - logs, sub, err := _LegacyERC20ETH.contract.WatchLogs(opts, "Mint", accountRule) - 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(LegacyERC20ETHMint) - if err := _LegacyERC20ETH.contract.UnpackLog(event, "Mint", 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 -} - -// ParseMint is a log parse operation binding the contract event 0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885. -// -// Solidity: event Mint(address indexed account, uint256 amount) -func (_LegacyERC20ETH *LegacyERC20ETHFilterer) ParseMint(log types.Log) (*LegacyERC20ETHMint, error) { - event := new(LegacyERC20ETHMint) - if err := _LegacyERC20ETH.contract.UnpackLog(event, "Mint", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// LegacyERC20ETHTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the LegacyERC20ETH contract. -type LegacyERC20ETHTransferIterator struct { - Event *LegacyERC20ETHTransfer // 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 *LegacyERC20ETHTransferIterator) 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(LegacyERC20ETHTransfer) - 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(LegacyERC20ETHTransfer) - 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 *LegacyERC20ETHTransferIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *LegacyERC20ETHTransferIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// LegacyERC20ETHTransfer represents a Transfer event raised by the LegacyERC20ETH contract. -type LegacyERC20ETHTransfer struct { - From common.Address - To common.Address - Value *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterTransfer is a free log retrieval operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. -// -// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) -func (_LegacyERC20ETH *LegacyERC20ETHFilterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*LegacyERC20ETHTransferIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _LegacyERC20ETH.contract.FilterLogs(opts, "Transfer", fromRule, toRule) - if err != nil { - return nil, err - } - return &LegacyERC20ETHTransferIterator{contract: _LegacyERC20ETH.contract, event: "Transfer", logs: logs, sub: sub}, nil -} - -// WatchTransfer is a free log subscription operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. -// -// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) -func (_LegacyERC20ETH *LegacyERC20ETHFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *LegacyERC20ETHTransfer, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _LegacyERC20ETH.contract.WatchLogs(opts, "Transfer", fromRule, toRule) - 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(LegacyERC20ETHTransfer) - if err := _LegacyERC20ETH.contract.UnpackLog(event, "Transfer", 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 -} - -// ParseTransfer is a log parse operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. -// -// Solidity: event Transfer(address indexed from, address indexed to, uint256 value) -func (_LegacyERC20ETH *LegacyERC20ETHFilterer) ParseTransfer(log types.Log) (*LegacyERC20ETHTransfer, error) { - event := new(LegacyERC20ETHTransfer) - if err := _LegacyERC20ETH.contract.UnpackLog(event, "Transfer", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/op-bindings/bindings/legacyerc20eth_more.go b/op-bindings/bindings/legacyerc20eth_more.go deleted file mode 100644 index 5cf0893d6c19..000000000000 --- a/op-bindings/bindings/legacyerc20eth_more.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package bindings - -import ( - "encoding/json" - - "github.com/ethereum-optimism/optimism/op-bindings/solc" -) - -const LegacyERC20ETHStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_balances\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":1001,\"contract\":\"src/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_allowances\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":1002,\"contract\":\"src/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_totalSupply\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":1003,\"contract\":\"src/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_name\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_string_storage\"},{\"astId\":1004,\"contract\":\"src/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_symbol\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_string_storage\"}],\"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) - -var LegacyERC20ETHDeployedBin = "0x608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610387578063e78cea921461033b578063ee9a31a2146103cd57600080fd5b8063ae1f6aaf1461033b578063c01e1bd614610361578063d6c0b2c41461036157600080fd5b80639dc29fac116100bd5780639dc29fac14610302578063a457c2d714610315578063a9059cbb1461032857600080fd5b806370a08231146102d257806395d89b41146102fa57600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004610905565b6103f4565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104e5565b60405161019b919061094e565b61018f6102133660046109ea565b610577565b6002545b60405190815260200161019b565b61018f610238366004610a14565b610607565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c3660046109ea565b610692565b61029461028f3660046109ea565b61071d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e0366004610a50565b73ffffffffffffffffffffffffffffffffffffffff163190565b6101f861077f565b6102946103103660046109ea565b61078e565b61018f6103233660046109ea565b6107f0565b61018f6103363660046109ea565b61087b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c610395366004610a6b565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104ad57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104dc57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104f490610a9e565b80601f016020809104026020016040519081016040528092919081815260200182805461052090610a9e565b801561056d5780601f106105425761010080835404028352916020019161056d565b820191906000526020600020905b81548152906001019060200180831161055057829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4c656761637945524332304554483a20617070726f766520697320646973616260448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526000906084015b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4c656761637945524332304554483a207472616e7366657246726f6d2069732060448201527f64697361626c656400000000000000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a20696e637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206d696e742069732064697361626c656460448201526064016105fe565b6060600480546104f490610a9e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4c656761637945524332304554483a206275726e2069732064697361626c656460448201526064016105fe565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4c656761637945524332304554483a206465637265617365416c6c6f77616e6360448201527f652069732064697361626c65640000000000000000000000000000000000000060648201526000906084016105fe565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4c656761637945524332304554483a207472616e73666572206973206469736160448201527f626c65640000000000000000000000000000000000000000000000000000000060648201526000906084016105fe565b60006020828403121561091757600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461094757600080fd5b9392505050565b600060208083528351808285015260005b8181101561097b5785810183015185820160400152820161095f565b8181111561098d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146109e557600080fd5b919050565b600080604083850312156109fd57600080fd5b610a06836109c1565b946020939093013593505050565b600080600060608486031215610a2957600080fd5b610a32846109c1565b9250610a40602085016109c1565b9150604084013590509250925092565b600060208284031215610a6257600080fd5b610947826109c1565b60008060408385031215610a7e57600080fd5b610a87836109c1565b9150610a95602084016109c1565b90509250929050565b600181811c90821680610ab257607f821691505b602082108103610aeb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b5091905056fea164736f6c634300080f000a" - - -func init() { - if err := json.Unmarshal([]byte(LegacyERC20ETHStorageLayoutJSON), LegacyERC20ETHStorageLayout); err != nil { - panic(err) - } - - layouts["LegacyERC20ETH"] = LegacyERC20ETHStorageLayout - deployedBytecodes["LegacyERC20ETH"] = LegacyERC20ETHDeployedBin - immutableReferences["LegacyERC20ETH"] = true -} diff --git a/op-bindings/bindings/mips.go b/op-bindings/bindings/mips.go index 57490a25fc2f..46eaa3505da1 100644 --- a/op-bindings/bindings/mips.go +++ b/op-bindings/bindings/mips.go @@ -30,8 +30,8 @@ var ( // MIPSMetaData contains all meta data concerning the MIPS contract. var MIPSMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_oracle\",\"type\":\"address\",\"internalType\":\"contractIPreimageOracle\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"BRK_START\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"oracle\",\"inputs\":[],\"outputs\":[{\"name\":\"oracle_\",\"type\":\"address\",\"internalType\":\"contractIPreimageOracle\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"step\",\"inputs\":[{\"name\":\"_stateData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_localContext\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"}]", - Bin: "0x60a060405234801561001057600080fd5b50604051611ec2380380611ec283398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051611e3161009160003960008181608501526115ef0152611e316000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063155633fe146100465780637dc0d1d01461006b578063e14ced32146100af575b600080fd5b610051634000000081565b60405163ffffffff90911681526020015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610062565b6100c26100bd366004611d2e565b6100d0565b604051908152602001610062565b60006100da611c5b565b608081146100e757600080fd5b604051610600146100f757600080fd5b6084871461010457600080fd5b6101a4851461011257600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a052605a880135901c6101c0526102006101e0819052606288019060005b60208110156101bd57823560e01c8252600490920191602090910190600101610199565b505050806101200151156101db576101d361061b565b915050610612565b6101408101805160010167ffffffffffffffff16905260608101516000906102039082610737565b9050603f601a82901c16600281148061022257508063ffffffff166003145b156102775760006002836303ffffff1663ffffffff16901b846080015163f00000001617905061026c8263ffffffff1660021461026057601f610263565b60005b60ff16826107f3565b945050505050610612565b6101608301516000908190601f601086901c81169190601587901c16602081106102a3576102a3611da2565b602002015192508063ffffffff851615806102c457508463ffffffff16601c145b156102fb578661016001518263ffffffff16602081106102e6576102e6611da2565b6020020151925050601f600b86901c166103b7565b60208563ffffffff16101561035d578463ffffffff16600c148061032557508463ffffffff16600d145b8061033657508463ffffffff16600e145b15610347578561ffff1692506103b7565b6103568661ffff1660106108e4565b92506103b7565b60288563ffffffff1610158061037957508463ffffffff166022145b8061038a57508463ffffffff166026145b156103b7578661016001518263ffffffff16602081106103ac576103ac611da2565b602002015192508190505b60048563ffffffff16101580156103d4575060088563ffffffff16105b806103e557508463ffffffff166001145b15610404576103f685878487610957565b975050505050505050610612565b63ffffffff6000602087831610610469576104248861ffff1660106108e4565b9095019463fffffffc861661043a816001610737565b915060288863ffffffff161015801561045a57508763ffffffff16603014155b1561046757809250600093505b505b600061047789888885610b67565b63ffffffff9081169150603f8a1690891615801561049c575060088163ffffffff1610155b80156104ae5750601c8163ffffffff16105b1561058b578063ffffffff16600814806104ce57508063ffffffff166009145b15610505576104f38163ffffffff166008146104ea57856104ed565b60005b896107f3565b9b505050505050505050505050610612565b8063ffffffff16600a03610525576104f3858963ffffffff8a16156112f7565b8063ffffffff16600b03610546576104f3858963ffffffff8a1615156112f7565b8063ffffffff16600c0361055d576104f38d6113dd565b60108163ffffffff161015801561057a5750601c8163ffffffff16105b1561058b576104f381898988611914565b8863ffffffff1660381480156105a6575063ffffffff861615155b156105db5760018b61016001518763ffffffff16602081106105ca576105ca611da2565b63ffffffff90921660209290920201525b8363ffffffff1663ffffffff146105f8576105f884600184611b0e565b610604858360016112f7565b9b5050505050505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a840152600092610200929091606283019190855b60208110156106ba57601c8601518452602090950194600490930192600101610696565b506000835283830384a06000945080600181146106da5760039550610702565b8280156106f257600181146106fb5760029650610700565b60009650610700565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b60008061074383611bb2565b9050600384161561075357600080fd5b6020810190358460051c8160005b601b8110156107b95760208501943583821c6001168015610789576001811461079e576107af565b600084815260208390526040902093506107af565b600082815260208590526040902093505b5050600101610761565b5060805191508181146107d457630badf00d60005260206000fd5b5050601f94909416601c0360031b9390931c63ffffffff169392505050565b60006107fd611c5b565b60809050806060015160040163ffffffff16816080015163ffffffff1614610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b60608101805160808301805163ffffffff9081169093528583169052908516156108dc57806008018261016001518663ffffffff16602081106108cb576108cb611da2565b63ffffffff90921660209290920201525b61061261061b565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182610941576000610943565b815b90861663ffffffff16179250505092915050565b6000610961611c5b565b608090506000816060015160040163ffffffff16826080015163ffffffff16146109e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f74000000000000000000000000604482015260640161087d565b8663ffffffff1660041480610a0257508663ffffffff166005145b15610a7e5760008261016001518663ffffffff1660208110610a2657610a26611da2565b602002015190508063ffffffff168563ffffffff16148015610a4e57508763ffffffff166004145b80610a7657508063ffffffff168563ffffffff1614158015610a7657508763ffffffff166005145b915050610afb565b8663ffffffff16600603610a9b5760008460030b13159050610afb565b8663ffffffff16600703610ab75760008460030b139050610afb565b8663ffffffff16600103610afb57601f601087901c166000819003610ae05760008560030b1291505b8063ffffffff16600103610af95760008560030b121591505b505b606082018051608084015163ffffffff169091528115610b41576002610b268861ffff1660106108e4565b63ffffffff90811690911b8201600401166080840152610b53565b60808301805160040163ffffffff1690525b610b5b61061b565b98975050505050505050565b6000603f601a86901c16801580610b96575060088163ffffffff1610158015610b965750600f8163ffffffff16105b15610fec57603f86168160088114610bdd5760098114610be657600a8114610bef57600b8114610bf857600c8114610c0157600d8114610c0a57600e8114610c1357610c18565b60209150610c18565b60219150610c18565b602a9150610c18565b602b9150610c18565b60249150610c18565b60259150610c18565b602691505b508063ffffffff16600003610c3f5750505063ffffffff8216601f600686901c161b6112ef565b8063ffffffff16600203610c655750505063ffffffff8216601f600686901c161c6112ef565b8063ffffffff16600303610c9b57601f600688901c16610c9163ffffffff8716821c60208390036108e4565b93505050506112ef565b8063ffffffff16600403610cbd5750505063ffffffff8216601f84161b6112ef565b8063ffffffff16600603610cdf5750505063ffffffff8216601f84161c6112ef565b8063ffffffff16600703610d1257610d098663ffffffff168663ffffffff16901c876020036108e4565b925050506112ef565b8063ffffffff16600803610d2a5785925050506112ef565b8063ffffffff16600903610d425785925050506112ef565b8063ffffffff16600a03610d5a5785925050506112ef565b8063ffffffff16600b03610d725785925050506112ef565b8063ffffffff16600c03610d8a5785925050506112ef565b8063ffffffff16600f03610da25785925050506112ef565b8063ffffffff16601003610dba5785925050506112ef565b8063ffffffff16601103610dd25785925050506112ef565b8063ffffffff16601203610dea5785925050506112ef565b8063ffffffff16601303610e025785925050506112ef565b8063ffffffff16601803610e1a5785925050506112ef565b8063ffffffff16601903610e325785925050506112ef565b8063ffffffff16601a03610e4a5785925050506112ef565b8063ffffffff16601b03610e625785925050506112ef565b8063ffffffff16602003610e7b575050508282016112ef565b8063ffffffff16602103610e94575050508282016112ef565b8063ffffffff16602203610ead575050508183036112ef565b8063ffffffff16602303610ec6575050508183036112ef565b8063ffffffff16602403610edf575050508282166112ef565b8063ffffffff16602503610ef8575050508282176112ef565b8063ffffffff16602603610f11575050508282186112ef565b8063ffffffff16602703610f2b57505050828217196112ef565b8063ffffffff16602a03610f5c578460030b8660030b12610f4d576000610f50565b60015b60ff16925050506112ef565b8063ffffffff16602b03610f84578463ffffffff168663ffffffff1610610f4d576000610f50565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e00000000000000000000000000604482015260640161087d565b50610f84565b8063ffffffff16601c0361107057603f86166002819003611012575050508282026112ef565b8063ffffffff166020148061102d57508063ffffffff166021145b15610fe6578063ffffffff16602003611044579419945b60005b6380000000871615611066576401fffffffe600197881b169601611047565b92506112ef915050565b8063ffffffff16600f0361109257505065ffffffff0000601083901b166112ef565b8063ffffffff166020036110ce576110c68560031660080260180363ffffffff168463ffffffff16901c60ff1660086108e4565b9150506112ef565b8063ffffffff16602103611103576110c68560021660080260100363ffffffff168463ffffffff16901c61ffff1660106108e4565b8063ffffffff1660220361113257505063ffffffff60086003851602811681811b198416918316901b176112ef565b8063ffffffff1660230361114957829150506112ef565b8063ffffffff1660240361117b578460031660080260180363ffffffff168363ffffffff16901c60ff169150506112ef565b8063ffffffff166025036111ae578460021660080260100363ffffffff168363ffffffff16901c61ffff169150506112ef565b8063ffffffff166026036111e057505063ffffffff60086003851602601803811681811c198416918316901c176112ef565b8063ffffffff1660280361121657505060ff63ffffffff60086003861602601803811682811b9091188316918416901b176112ef565b8063ffffffff1660290361124d57505061ffff63ffffffff60086002861602601003811682811b9091188316918416901b176112ef565b8063ffffffff16602a0361127c57505063ffffffff60086003851602811681811c198316918416901c176112ef565b8063ffffffff16602b0361129357839150506112ef565b8063ffffffff16602e036112c557505063ffffffff60086003851602601803811681811b198316918416901b176112ef565b8063ffffffff166030036112dc57829150506112ef565b8063ffffffff16603803610f8457839150505b949350505050565b6000611301611c5b565b506080602063ffffffff861610611374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c6964207265676973746572000000000000000000000000000000000000604482015260640161087d565b63ffffffff8516158015906113865750825b156113ba57838161016001518663ffffffff16602081106113a9576113a9611da2565b63ffffffff90921660209290920201525b60808101805163ffffffff8082166060850152600490910116905261061261061b565b60006113e7611c5b565b506101e051604081015160808083015160a084015160c09094015191936000928392919063ffffffff8616610ffa036114615781610fff81161561143057610fff811661100003015b8363ffffffff166000036114575760e08801805163ffffffff83820116909152955061145b565b8395505b506118d3565b8563ffffffff16610fcd0361147c57634000000094506118d3565b8563ffffffff166110180361149457600194506118d3565b8563ffffffff16611096036114ca57600161012088015260ff83166101008801526114bd61061b565b9998505050505050505050565b8563ffffffff16610fa3036117365763ffffffff8316156118d3577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb63ffffffff8416016116f05760006115258363fffffffc166001610737565b60208901519091508060001a60010361159457604080516000838152336020528d83526060902091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790505b6040808a015190517fe03110e10000000000000000000000000000000000000000000000000000000081526004810183905263ffffffff9091166024820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e03110e1906044016040805180830381865afa158015611635573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116599190611dd1565b91509150600386168060040382811015611671578092505b508186101561167e578591505b8260088302610100031c9250826008828460040303021b9250600180600883600403021b036001806008858560040303021b039150811981169050838119871617955050506116d58663fffffffc16600186611b0e565b60408b018051820163ffffffff169052975061173192505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd63ffffffff841601611725578094506118d3565b63ffffffff9450600993505b6118d3565b8563ffffffff16610fa4036118275763ffffffff831660011480611760575063ffffffff83166002145b80611771575063ffffffff83166004145b1561177e578094506118d3565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8416016117255760006117be8363fffffffc166001610737565b602089015190915060038416600403838110156117d9578093505b83900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193850293841b0116911b176020880152600060408801529350836118d3565b8563ffffffff16610fd7036118d3578163ffffffff166003036118c75763ffffffff8316158061185d575063ffffffff83166005145b8061186e575063ffffffff83166003145b1561187c57600094506118d3565b63ffffffff831660011480611897575063ffffffff83166002145b806118a8575063ffffffff83166006145b806118b9575063ffffffff83166004145b1561172557600194506118d3565b63ffffffff9450601693505b6101608701805163ffffffff808816604090920191909152905185821660e09091015260808801805180831660608b015260040190911690526114bd61061b565b600061191e611c5b565b506080600063ffffffff871660100361193c575060c0810151611aa5565b8663ffffffff1660110361195b5763ffffffff861660c0830152611aa5565b8663ffffffff16601203611974575060a0810151611aa5565b8663ffffffff166013036119935763ffffffff861660a0830152611aa5565b8663ffffffff166018036119c75763ffffffff600387810b9087900b02602081901c821660c08501521660a0830152611aa5565b8663ffffffff166019036119f85763ffffffff86811681871602602081901c821660c08501521660a0830152611aa5565b8663ffffffff16601a03611a4e578460030b8660030b81611a1b57611a1b611df5565b0763ffffffff1660c0830152600385810b9087900b81611a3d57611a3d611df5565b0563ffffffff1660a0830152611aa5565b8663ffffffff16601b03611aa5578463ffffffff168663ffffffff1681611a7757611a77611df5565b0663ffffffff90811660c084015285811690871681611a9857611a98611df5565b0463ffffffff1660a08301525b63ffffffff841615611ae057808261016001518563ffffffff1660208110611acf57611acf611da2565b63ffffffff90921660209290920201525b60808201805163ffffffff80821660608601526004909101169052611b0361061b565b979650505050505050565b6000611b1983611bb2565b90506003841615611b2957600080fd5b6020810190601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b811015611ba75760208401933582821c6001168015611b775760018114611b8c57611b9d565b60008581526020839052604090209450611b9d565b600082815260208690526040902094505b5050600101611b4f565b505060805250505050565b60ff8116610380026101a4810190369061052401811015611c55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f6174610000000000000000000000000000000000000000000000000000000000606482015260840161087d565b50919050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101611cc1611cc6565b905290565b6040518061040001604052806020906020820280368337509192915050565b60008083601f840112611cf757600080fd5b50813567ffffffffffffffff811115611d0f57600080fd5b602083019150836020828501011115611d2757600080fd5b9250929050565b600080600080600060608688031215611d4657600080fd5b853567ffffffffffffffff80821115611d5e57600080fd5b611d6a89838a01611ce5565b90975095506020880135915080821115611d8357600080fd5b50611d9088828901611ce5565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060408385031215611de457600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_oracle\",\"type\":\"address\",\"internalType\":\"contractIPreimageOracle\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"BRK_START\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"oracle\",\"inputs\":[],\"outputs\":[{\"name\":\"oracle_\",\"type\":\"address\",\"internalType\":\"contractIPreimageOracle\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"step\",\"inputs\":[{\"name\":\"_stateData\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_localContext\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"}]", + Bin: "0x60a060405234801561001057600080fd5b50604051611f89380380611f8983398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051611ef86100916000396000818160d901526116430152611ef86000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063155633fe1461005157806354fd4d50146100765780637dc0d1d0146100bf578063e14ced3214610103575b600080fd5b61005c634000000081565b60405163ffffffff90911681526020015b60405180910390f35b6100b26040518060400160405280600581526020017f302e312e3000000000000000000000000000000000000000000000000000000081525081565b60405161006d9190611d39565b60405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161006d565b610116610111366004611df5565b610124565b60405190815260200161006d565b600061012e611caf565b6080811461013b57600080fd5b6040516106001461014b57600080fd5b6084871461015857600080fd5b6101a4851461016657600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a052605a880135901c6101c0526102006101e0819052606288019060005b602081101561021157823560e01c82526004909201916020909101906001016101ed565b5050508061012001511561022f5761022761066f565b915050610666565b6101408101805160010167ffffffffffffffff1690526060810151600090610257908261078b565b9050603f601a82901c16600281148061027657508063ffffffff166003145b156102cb5760006002836303ffffff1663ffffffff16901b846080015163f0000000161790506102c08263ffffffff166002146102b457601f6102b7565b60005b60ff1682610847565b945050505050610666565b6101608301516000908190601f601086901c81169190601587901c16602081106102f7576102f7611e69565b602002015192508063ffffffff8516158061031857508463ffffffff16601c145b1561034f578661016001518263ffffffff166020811061033a5761033a611e69565b6020020151925050601f600b86901c1661040b565b60208563ffffffff1610156103b1578463ffffffff16600c148061037957508463ffffffff16600d145b8061038a57508463ffffffff16600e145b1561039b578561ffff16925061040b565b6103aa8661ffff166010610938565b925061040b565b60288563ffffffff161015806103cd57508463ffffffff166022145b806103de57508463ffffffff166026145b1561040b578661016001518263ffffffff166020811061040057610400611e69565b602002015192508190505b60048563ffffffff1610158015610428575060088563ffffffff16105b8061043957508463ffffffff166001145b156104585761044a858784876109ab565b975050505050505050610666565b63ffffffff60006020878316106104bd576104788861ffff166010610938565b9095019463fffffffc861661048e81600161078b565b915060288863ffffffff16101580156104ae57508763ffffffff16603014155b156104bb57809250600093505b505b60006104cb89888885610bbb565b63ffffffff9081169150603f8a169089161580156104f0575060088163ffffffff1610155b80156105025750601c8163ffffffff16105b156105df578063ffffffff166008148061052257508063ffffffff166009145b15610559576105478163ffffffff1660081461053e5785610541565b60005b89610847565b9b505050505050505050505050610666565b8063ffffffff16600a0361057957610547858963ffffffff8a161561134b565b8063ffffffff16600b0361059a57610547858963ffffffff8a16151561134b565b8063ffffffff16600c036105b1576105478d611431565b60108163ffffffff16101580156105ce5750601c8163ffffffff16105b156105df5761054781898988611968565b8863ffffffff1660381480156105fa575063ffffffff861615155b1561062f5760018b61016001518763ffffffff166020811061061e5761061e611e69565b63ffffffff90921660209290920201525b8363ffffffff1663ffffffff1461064c5761064c84600184611b62565b6106588583600161134b565b9b5050505050505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a840152600092610200929091606283019190855b602081101561070e57601c86015184526020909501946004909301926001016106ea565b506000835283830384a060009450806001811461072e5760039550610756565b828015610746576001811461074f5760029650610754565b60009650610754565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b60008061079783611c06565b905060038416156107a757600080fd5b6020810190358460051c8160005b601b81101561080d5760208501943583821c60011680156107dd57600181146107f257610803565b60008481526020839052604090209350610803565b600082815260208590526040902093505b50506001016107b5565b50608051915081811461082857630badf00d60005260206000fd5b5050601f94909416601c0360031b9390931c63ffffffff169392505050565b6000610851611caf565b60809050806060015160040163ffffffff16816080015163ffffffff16146108da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b60608101805160808301805163ffffffff90811690935285831690529085161561093057806008018261016001518663ffffffff166020811061091f5761091f611e69565b63ffffffff90921660209290920201525b61066661066f565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182610995576000610997565b815b90861663ffffffff16179250505092915050565b60006109b5611caf565b608090506000816060015160040163ffffffff16826080015163ffffffff1614610a3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f7400000000000000000000000060448201526064016108d1565b8663ffffffff1660041480610a5657508663ffffffff166005145b15610ad25760008261016001518663ffffffff1660208110610a7a57610a7a611e69565b602002015190508063ffffffff168563ffffffff16148015610aa257508763ffffffff166004145b80610aca57508063ffffffff168563ffffffff1614158015610aca57508763ffffffff166005145b915050610b4f565b8663ffffffff16600603610aef5760008460030b13159050610b4f565b8663ffffffff16600703610b0b5760008460030b139050610b4f565b8663ffffffff16600103610b4f57601f601087901c166000819003610b345760008560030b1291505b8063ffffffff16600103610b4d5760008560030b121591505b505b606082018051608084015163ffffffff169091528115610b95576002610b7a8861ffff166010610938565b63ffffffff90811690911b8201600401166080840152610ba7565b60808301805160040163ffffffff1690525b610baf61066f565b98975050505050505050565b6000603f601a86901c16801580610bea575060088163ffffffff1610158015610bea5750600f8163ffffffff16105b1561104057603f86168160088114610c315760098114610c3a57600a8114610c4357600b8114610c4c57600c8114610c5557600d8114610c5e57600e8114610c6757610c6c565b60209150610c6c565b60219150610c6c565b602a9150610c6c565b602b9150610c6c565b60249150610c6c565b60259150610c6c565b602691505b508063ffffffff16600003610c935750505063ffffffff8216601f600686901c161b611343565b8063ffffffff16600203610cb95750505063ffffffff8216601f600686901c161c611343565b8063ffffffff16600303610cef57601f600688901c16610ce563ffffffff8716821c6020839003610938565b9350505050611343565b8063ffffffff16600403610d115750505063ffffffff8216601f84161b611343565b8063ffffffff16600603610d335750505063ffffffff8216601f84161c611343565b8063ffffffff16600703610d6657610d5d8663ffffffff168663ffffffff16901c87602003610938565b92505050611343565b8063ffffffff16600803610d7e578592505050611343565b8063ffffffff16600903610d96578592505050611343565b8063ffffffff16600a03610dae578592505050611343565b8063ffffffff16600b03610dc6578592505050611343565b8063ffffffff16600c03610dde578592505050611343565b8063ffffffff16600f03610df6578592505050611343565b8063ffffffff16601003610e0e578592505050611343565b8063ffffffff16601103610e26578592505050611343565b8063ffffffff16601203610e3e578592505050611343565b8063ffffffff16601303610e56578592505050611343565b8063ffffffff16601803610e6e578592505050611343565b8063ffffffff16601903610e86578592505050611343565b8063ffffffff16601a03610e9e578592505050611343565b8063ffffffff16601b03610eb6578592505050611343565b8063ffffffff16602003610ecf57505050828201611343565b8063ffffffff16602103610ee857505050828201611343565b8063ffffffff16602203610f0157505050818303611343565b8063ffffffff16602303610f1a57505050818303611343565b8063ffffffff16602403610f3357505050828216611343565b8063ffffffff16602503610f4c57505050828217611343565b8063ffffffff16602603610f6557505050828218611343565b8063ffffffff16602703610f7f5750505082821719611343565b8063ffffffff16602a03610fb0578460030b8660030b12610fa1576000610fa4565b60015b60ff1692505050611343565b8063ffffffff16602b03610fd8578463ffffffff168663ffffffff1610610fa1576000610fa4565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e0000000000000000000000000060448201526064016108d1565b50610fd8565b8063ffffffff16601c036110c457603f8616600281900361106657505050828202611343565b8063ffffffff166020148061108157508063ffffffff166021145b1561103a578063ffffffff16602003611098579419945b60005b63800000008716156110ba576401fffffffe600197881b16960161109b565b9250611343915050565b8063ffffffff16600f036110e657505065ffffffff0000601083901b16611343565b8063ffffffff166020036111225761111a8560031660080260180363ffffffff168463ffffffff16901c60ff166008610938565b915050611343565b8063ffffffff166021036111575761111a8560021660080260100363ffffffff168463ffffffff16901c61ffff166010610938565b8063ffffffff1660220361118657505063ffffffff60086003851602811681811b198416918316901b17611343565b8063ffffffff1660230361119d5782915050611343565b8063ffffffff166024036111cf578460031660080260180363ffffffff168363ffffffff16901c60ff16915050611343565b8063ffffffff16602503611202578460021660080260100363ffffffff168363ffffffff16901c61ffff16915050611343565b8063ffffffff1660260361123457505063ffffffff60086003851602601803811681811c198416918316901c17611343565b8063ffffffff1660280361126a57505060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611343565b8063ffffffff166029036112a157505061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611343565b8063ffffffff16602a036112d057505063ffffffff60086003851602811681811c198316918416901c17611343565b8063ffffffff16602b036112e75783915050611343565b8063ffffffff16602e0361131957505063ffffffff60086003851602601803811681811b198316918416901b17611343565b8063ffffffff166030036113305782915050611343565b8063ffffffff16603803610fd857839150505b949350505050565b6000611355611caf565b506080602063ffffffff8616106113c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c696420726567697374657200000000000000000000000000000000000060448201526064016108d1565b63ffffffff8516158015906113da5750825b1561140e57838161016001518663ffffffff16602081106113fd576113fd611e69565b63ffffffff90921660209290920201525b60808101805163ffffffff8082166060850152600490910116905261066661066f565b600061143b611caf565b506101e051604081015160808083015160a084015160c09094015191936000928392919063ffffffff8616610ffa036114b55781610fff81161561148457610fff811661100003015b8363ffffffff166000036114ab5760e08801805163ffffffff8382011690915295506114af565b8395505b50611927565b8563ffffffff16610fcd036114d05763400000009450611927565b8563ffffffff16611018036114e85760019450611927565b8563ffffffff166110960361151e57600161012088015260ff831661010088015261151161066f565b9998505050505050505050565b8563ffffffff16610fa30361178a5763ffffffff831615611927577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb63ffffffff8416016117445760006115798363fffffffc16600161078b565b60208901519091508060001a6001036115e857604080516000838152336020528d83526060902091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790505b6040808a015190517fe03110e10000000000000000000000000000000000000000000000000000000081526004810183905263ffffffff9091166024820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e03110e1906044016040805180830381865afa158015611689573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ad9190611e98565b915091506003861680600403828110156116c5578092505b50818610156116d2578591505b8260088302610100031c9250826008828460040303021b9250600180600883600403021b036001806008858560040303021b039150811981169050838119871617955050506117298663fffffffc16600186611b62565b60408b018051820163ffffffff169052975061178592505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd63ffffffff84160161177957809450611927565b63ffffffff9450600993505b611927565b8563ffffffff16610fa40361187b5763ffffffff8316600114806117b4575063ffffffff83166002145b806117c5575063ffffffff83166004145b156117d257809450611927565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8416016117795760006118128363fffffffc16600161078b565b6020890151909150600384166004038381101561182d578093505b83900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193850293841b0116911b17602088015260006040880152935083611927565b8563ffffffff16610fd703611927578163ffffffff1660030361191b5763ffffffff831615806118b1575063ffffffff83166005145b806118c2575063ffffffff83166003145b156118d05760009450611927565b63ffffffff8316600114806118eb575063ffffffff83166002145b806118fc575063ffffffff83166006145b8061190d575063ffffffff83166004145b156117795760019450611927565b63ffffffff9450601693505b6101608701805163ffffffff808816604090920191909152905185821660e09091015260808801805180831660608b0152600401909116905261151161066f565b6000611972611caf565b506080600063ffffffff8716601003611990575060c0810151611af9565b8663ffffffff166011036119af5763ffffffff861660c0830152611af9565b8663ffffffff166012036119c8575060a0810151611af9565b8663ffffffff166013036119e75763ffffffff861660a0830152611af9565b8663ffffffff16601803611a1b5763ffffffff600387810b9087900b02602081901c821660c08501521660a0830152611af9565b8663ffffffff16601903611a4c5763ffffffff86811681871602602081901c821660c08501521660a0830152611af9565b8663ffffffff16601a03611aa2578460030b8660030b81611a6f57611a6f611ebc565b0763ffffffff1660c0830152600385810b9087900b81611a9157611a91611ebc565b0563ffffffff1660a0830152611af9565b8663ffffffff16601b03611af9578463ffffffff168663ffffffff1681611acb57611acb611ebc565b0663ffffffff90811660c084015285811690871681611aec57611aec611ebc565b0463ffffffff1660a08301525b63ffffffff841615611b3457808261016001518563ffffffff1660208110611b2357611b23611e69565b63ffffffff90921660209290920201525b60808201805163ffffffff80821660608601526004909101169052611b5761066f565b979650505050505050565b6000611b6d83611c06565b90506003841615611b7d57600080fd5b6020810190601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b811015611bfb5760208401933582821c6001168015611bcb5760018114611be057611bf1565b60008581526020839052604090209450611bf1565b600082815260208690526040902094505b5050600101611ba3565b505060805250505050565b60ff8116610380026101a4810190369061052401811015611ca9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f617461000000000000000000000000000000000000000000000000000000000060648201526084016108d1565b50919050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101611d15611d1a565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b81811015611d6657858101830151858201604001528201611d4a565b81811115611d78576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f840112611dbe57600080fd5b50813567ffffffffffffffff811115611dd657600080fd5b602083019150836020828501011115611dee57600080fd5b9250929050565b600080600080600060608688031215611e0d57600080fd5b853567ffffffffffffffff80821115611e2557600080fd5b611e3189838a01611dac565b90975095506020880135915080821115611e4a57600080fd5b50611e5788828901611dac565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060408385031215611eab57600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a", } // MIPSABI is the input ABI used to generate the binding from. @@ -263,6 +263,37 @@ func (_MIPS *MIPSCallerSession) Oracle() (common.Address, error) { return _MIPS.Contract.Oracle(&_MIPS.CallOpts) } +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_MIPS *MIPSCaller) Version(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _MIPS.contract.Call(opts, &out, "version") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_MIPS *MIPSSession) Version() (string, error) { + return _MIPS.Contract.Version(&_MIPS.CallOpts) +} + +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_MIPS *MIPSCallerSession) Version() (string, error) { + return _MIPS.Contract.Version(&_MIPS.CallOpts) +} + // Step is a paid mutator transaction binding the contract method 0xe14ced32. // // Solidity: function step(bytes _stateData, bytes _proof, bytes32 _localContext) returns(bytes32) diff --git a/op-bindings/bindings/mips_more.go b/op-bindings/bindings/mips_more.go index b8dc9f5403fd..3413ca05d789 100644 --- a/op-bindings/bindings/mips_more.go +++ b/op-bindings/bindings/mips_more.go @@ -13,7 +13,7 @@ const MIPSStorageLayoutJSON = "{\"storage\":null,\"types\":{}}" var MIPSStorageLayout = new(solc.StorageLayout) -var MIPSDeployedBin = "0x608060405234801561001057600080fd5b50600436106100415760003560e01c8063155633fe146100465780637dc0d1d01461006b578063e14ced32146100af575b600080fd5b610051634000000081565b60405163ffffffff90911681526020015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610062565b6100c26100bd366004611d2e565b6100d0565b604051908152602001610062565b60006100da611c5b565b608081146100e757600080fd5b604051610600146100f757600080fd5b6084871461010457600080fd5b6101a4851461011257600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a052605a880135901c6101c0526102006101e0819052606288019060005b60208110156101bd57823560e01c8252600490920191602090910190600101610199565b505050806101200151156101db576101d361061b565b915050610612565b6101408101805160010167ffffffffffffffff16905260608101516000906102039082610737565b9050603f601a82901c16600281148061022257508063ffffffff166003145b156102775760006002836303ffffff1663ffffffff16901b846080015163f00000001617905061026c8263ffffffff1660021461026057601f610263565b60005b60ff16826107f3565b945050505050610612565b6101608301516000908190601f601086901c81169190601587901c16602081106102a3576102a3611da2565b602002015192508063ffffffff851615806102c457508463ffffffff16601c145b156102fb578661016001518263ffffffff16602081106102e6576102e6611da2565b6020020151925050601f600b86901c166103b7565b60208563ffffffff16101561035d578463ffffffff16600c148061032557508463ffffffff16600d145b8061033657508463ffffffff16600e145b15610347578561ffff1692506103b7565b6103568661ffff1660106108e4565b92506103b7565b60288563ffffffff1610158061037957508463ffffffff166022145b8061038a57508463ffffffff166026145b156103b7578661016001518263ffffffff16602081106103ac576103ac611da2565b602002015192508190505b60048563ffffffff16101580156103d4575060088563ffffffff16105b806103e557508463ffffffff166001145b15610404576103f685878487610957565b975050505050505050610612565b63ffffffff6000602087831610610469576104248861ffff1660106108e4565b9095019463fffffffc861661043a816001610737565b915060288863ffffffff161015801561045a57508763ffffffff16603014155b1561046757809250600093505b505b600061047789888885610b67565b63ffffffff9081169150603f8a1690891615801561049c575060088163ffffffff1610155b80156104ae5750601c8163ffffffff16105b1561058b578063ffffffff16600814806104ce57508063ffffffff166009145b15610505576104f38163ffffffff166008146104ea57856104ed565b60005b896107f3565b9b505050505050505050505050610612565b8063ffffffff16600a03610525576104f3858963ffffffff8a16156112f7565b8063ffffffff16600b03610546576104f3858963ffffffff8a1615156112f7565b8063ffffffff16600c0361055d576104f38d6113dd565b60108163ffffffff161015801561057a5750601c8163ffffffff16105b1561058b576104f381898988611914565b8863ffffffff1660381480156105a6575063ffffffff861615155b156105db5760018b61016001518763ffffffff16602081106105ca576105ca611da2565b63ffffffff90921660209290920201525b8363ffffffff1663ffffffff146105f8576105f884600184611b0e565b610604858360016112f7565b9b5050505050505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a840152600092610200929091606283019190855b60208110156106ba57601c8601518452602090950194600490930192600101610696565b506000835283830384a06000945080600181146106da5760039550610702565b8280156106f257600181146106fb5760029650610700565b60009650610700565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b60008061074383611bb2565b9050600384161561075357600080fd5b6020810190358460051c8160005b601b8110156107b95760208501943583821c6001168015610789576001811461079e576107af565b600084815260208390526040902093506107af565b600082815260208590526040902093505b5050600101610761565b5060805191508181146107d457630badf00d60005260206000fd5b5050601f94909416601c0360031b9390931c63ffffffff169392505050565b60006107fd611c5b565b60809050806060015160040163ffffffff16816080015163ffffffff1614610886576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b60608101805160808301805163ffffffff9081169093528583169052908516156108dc57806008018261016001518663ffffffff16602081106108cb576108cb611da2565b63ffffffff90921660209290920201525b61061261061b565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182610941576000610943565b815b90861663ffffffff16179250505092915050565b6000610961611c5b565b608090506000816060015160040163ffffffff16826080015163ffffffff16146109e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f74000000000000000000000000604482015260640161087d565b8663ffffffff1660041480610a0257508663ffffffff166005145b15610a7e5760008261016001518663ffffffff1660208110610a2657610a26611da2565b602002015190508063ffffffff168563ffffffff16148015610a4e57508763ffffffff166004145b80610a7657508063ffffffff168563ffffffff1614158015610a7657508763ffffffff166005145b915050610afb565b8663ffffffff16600603610a9b5760008460030b13159050610afb565b8663ffffffff16600703610ab75760008460030b139050610afb565b8663ffffffff16600103610afb57601f601087901c166000819003610ae05760008560030b1291505b8063ffffffff16600103610af95760008560030b121591505b505b606082018051608084015163ffffffff169091528115610b41576002610b268861ffff1660106108e4565b63ffffffff90811690911b8201600401166080840152610b53565b60808301805160040163ffffffff1690525b610b5b61061b565b98975050505050505050565b6000603f601a86901c16801580610b96575060088163ffffffff1610158015610b965750600f8163ffffffff16105b15610fec57603f86168160088114610bdd5760098114610be657600a8114610bef57600b8114610bf857600c8114610c0157600d8114610c0a57600e8114610c1357610c18565b60209150610c18565b60219150610c18565b602a9150610c18565b602b9150610c18565b60249150610c18565b60259150610c18565b602691505b508063ffffffff16600003610c3f5750505063ffffffff8216601f600686901c161b6112ef565b8063ffffffff16600203610c655750505063ffffffff8216601f600686901c161c6112ef565b8063ffffffff16600303610c9b57601f600688901c16610c9163ffffffff8716821c60208390036108e4565b93505050506112ef565b8063ffffffff16600403610cbd5750505063ffffffff8216601f84161b6112ef565b8063ffffffff16600603610cdf5750505063ffffffff8216601f84161c6112ef565b8063ffffffff16600703610d1257610d098663ffffffff168663ffffffff16901c876020036108e4565b925050506112ef565b8063ffffffff16600803610d2a5785925050506112ef565b8063ffffffff16600903610d425785925050506112ef565b8063ffffffff16600a03610d5a5785925050506112ef565b8063ffffffff16600b03610d725785925050506112ef565b8063ffffffff16600c03610d8a5785925050506112ef565b8063ffffffff16600f03610da25785925050506112ef565b8063ffffffff16601003610dba5785925050506112ef565b8063ffffffff16601103610dd25785925050506112ef565b8063ffffffff16601203610dea5785925050506112ef565b8063ffffffff16601303610e025785925050506112ef565b8063ffffffff16601803610e1a5785925050506112ef565b8063ffffffff16601903610e325785925050506112ef565b8063ffffffff16601a03610e4a5785925050506112ef565b8063ffffffff16601b03610e625785925050506112ef565b8063ffffffff16602003610e7b575050508282016112ef565b8063ffffffff16602103610e94575050508282016112ef565b8063ffffffff16602203610ead575050508183036112ef565b8063ffffffff16602303610ec6575050508183036112ef565b8063ffffffff16602403610edf575050508282166112ef565b8063ffffffff16602503610ef8575050508282176112ef565b8063ffffffff16602603610f11575050508282186112ef565b8063ffffffff16602703610f2b57505050828217196112ef565b8063ffffffff16602a03610f5c578460030b8660030b12610f4d576000610f50565b60015b60ff16925050506112ef565b8063ffffffff16602b03610f84578463ffffffff168663ffffffff1610610f4d576000610f50565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e00000000000000000000000000604482015260640161087d565b50610f84565b8063ffffffff16601c0361107057603f86166002819003611012575050508282026112ef565b8063ffffffff166020148061102d57508063ffffffff166021145b15610fe6578063ffffffff16602003611044579419945b60005b6380000000871615611066576401fffffffe600197881b169601611047565b92506112ef915050565b8063ffffffff16600f0361109257505065ffffffff0000601083901b166112ef565b8063ffffffff166020036110ce576110c68560031660080260180363ffffffff168463ffffffff16901c60ff1660086108e4565b9150506112ef565b8063ffffffff16602103611103576110c68560021660080260100363ffffffff168463ffffffff16901c61ffff1660106108e4565b8063ffffffff1660220361113257505063ffffffff60086003851602811681811b198416918316901b176112ef565b8063ffffffff1660230361114957829150506112ef565b8063ffffffff1660240361117b578460031660080260180363ffffffff168363ffffffff16901c60ff169150506112ef565b8063ffffffff166025036111ae578460021660080260100363ffffffff168363ffffffff16901c61ffff169150506112ef565b8063ffffffff166026036111e057505063ffffffff60086003851602601803811681811c198416918316901c176112ef565b8063ffffffff1660280361121657505060ff63ffffffff60086003861602601803811682811b9091188316918416901b176112ef565b8063ffffffff1660290361124d57505061ffff63ffffffff60086002861602601003811682811b9091188316918416901b176112ef565b8063ffffffff16602a0361127c57505063ffffffff60086003851602811681811c198316918416901c176112ef565b8063ffffffff16602b0361129357839150506112ef565b8063ffffffff16602e036112c557505063ffffffff60086003851602601803811681811b198316918416901b176112ef565b8063ffffffff166030036112dc57829150506112ef565b8063ffffffff16603803610f8457839150505b949350505050565b6000611301611c5b565b506080602063ffffffff861610611374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c6964207265676973746572000000000000000000000000000000000000604482015260640161087d565b63ffffffff8516158015906113865750825b156113ba57838161016001518663ffffffff16602081106113a9576113a9611da2565b63ffffffff90921660209290920201525b60808101805163ffffffff8082166060850152600490910116905261061261061b565b60006113e7611c5b565b506101e051604081015160808083015160a084015160c09094015191936000928392919063ffffffff8616610ffa036114615781610fff81161561143057610fff811661100003015b8363ffffffff166000036114575760e08801805163ffffffff83820116909152955061145b565b8395505b506118d3565b8563ffffffff16610fcd0361147c57634000000094506118d3565b8563ffffffff166110180361149457600194506118d3565b8563ffffffff16611096036114ca57600161012088015260ff83166101008801526114bd61061b565b9998505050505050505050565b8563ffffffff16610fa3036117365763ffffffff8316156118d3577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb63ffffffff8416016116f05760006115258363fffffffc166001610737565b60208901519091508060001a60010361159457604080516000838152336020528d83526060902091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790505b6040808a015190517fe03110e10000000000000000000000000000000000000000000000000000000081526004810183905263ffffffff9091166024820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e03110e1906044016040805180830381865afa158015611635573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116599190611dd1565b91509150600386168060040382811015611671578092505b508186101561167e578591505b8260088302610100031c9250826008828460040303021b9250600180600883600403021b036001806008858560040303021b039150811981169050838119871617955050506116d58663fffffffc16600186611b0e565b60408b018051820163ffffffff169052975061173192505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd63ffffffff841601611725578094506118d3565b63ffffffff9450600993505b6118d3565b8563ffffffff16610fa4036118275763ffffffff831660011480611760575063ffffffff83166002145b80611771575063ffffffff83166004145b1561177e578094506118d3565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8416016117255760006117be8363fffffffc166001610737565b602089015190915060038416600403838110156117d9578093505b83900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193850293841b0116911b176020880152600060408801529350836118d3565b8563ffffffff16610fd7036118d3578163ffffffff166003036118c75763ffffffff8316158061185d575063ffffffff83166005145b8061186e575063ffffffff83166003145b1561187c57600094506118d3565b63ffffffff831660011480611897575063ffffffff83166002145b806118a8575063ffffffff83166006145b806118b9575063ffffffff83166004145b1561172557600194506118d3565b63ffffffff9450601693505b6101608701805163ffffffff808816604090920191909152905185821660e09091015260808801805180831660608b015260040190911690526114bd61061b565b600061191e611c5b565b506080600063ffffffff871660100361193c575060c0810151611aa5565b8663ffffffff1660110361195b5763ffffffff861660c0830152611aa5565b8663ffffffff16601203611974575060a0810151611aa5565b8663ffffffff166013036119935763ffffffff861660a0830152611aa5565b8663ffffffff166018036119c75763ffffffff600387810b9087900b02602081901c821660c08501521660a0830152611aa5565b8663ffffffff166019036119f85763ffffffff86811681871602602081901c821660c08501521660a0830152611aa5565b8663ffffffff16601a03611a4e578460030b8660030b81611a1b57611a1b611df5565b0763ffffffff1660c0830152600385810b9087900b81611a3d57611a3d611df5565b0563ffffffff1660a0830152611aa5565b8663ffffffff16601b03611aa5578463ffffffff168663ffffffff1681611a7757611a77611df5565b0663ffffffff90811660c084015285811690871681611a9857611a98611df5565b0463ffffffff1660a08301525b63ffffffff841615611ae057808261016001518563ffffffff1660208110611acf57611acf611da2565b63ffffffff90921660209290920201525b60808201805163ffffffff80821660608601526004909101169052611b0361061b565b979650505050505050565b6000611b1983611bb2565b90506003841615611b2957600080fd5b6020810190601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b811015611ba75760208401933582821c6001168015611b775760018114611b8c57611b9d565b60008581526020839052604090209450611b9d565b600082815260208690526040902094505b5050600101611b4f565b505060805250505050565b60ff8116610380026101a4810190369061052401811015611c55576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f6174610000000000000000000000000000000000000000000000000000000000606482015260840161087d565b50919050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101611cc1611cc6565b905290565b6040518061040001604052806020906020820280368337509192915050565b60008083601f840112611cf757600080fd5b50813567ffffffffffffffff811115611d0f57600080fd5b602083019150836020828501011115611d2757600080fd5b9250929050565b600080600080600060608688031215611d4657600080fd5b853567ffffffffffffffff80821115611d5e57600080fd5b611d6a89838a01611ce5565b90975095506020880135915080821115611d8357600080fd5b50611d9088828901611ce5565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060408385031215611de457600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a" +var MIPSDeployedBin = "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c8063155633fe1461005157806354fd4d50146100765780637dc0d1d0146100bf578063e14ced3214610103575b600080fd5b61005c634000000081565b60405163ffffffff90911681526020015b60405180910390f35b6100b26040518060400160405280600581526020017f302e312e3000000000000000000000000000000000000000000000000000000081525081565b60405161006d9190611d39565b60405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161006d565b610116610111366004611df5565b610124565b60405190815260200161006d565b600061012e611caf565b6080811461013b57600080fd5b6040516106001461014b57600080fd5b6084871461015857600080fd5b6101a4851461016657600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a052605a880135901c6101c0526102006101e0819052606288019060005b602081101561021157823560e01c82526004909201916020909101906001016101ed565b5050508061012001511561022f5761022761066f565b915050610666565b6101408101805160010167ffffffffffffffff1690526060810151600090610257908261078b565b9050603f601a82901c16600281148061027657508063ffffffff166003145b156102cb5760006002836303ffffff1663ffffffff16901b846080015163f0000000161790506102c08263ffffffff166002146102b457601f6102b7565b60005b60ff1682610847565b945050505050610666565b6101608301516000908190601f601086901c81169190601587901c16602081106102f7576102f7611e69565b602002015192508063ffffffff8516158061031857508463ffffffff16601c145b1561034f578661016001518263ffffffff166020811061033a5761033a611e69565b6020020151925050601f600b86901c1661040b565b60208563ffffffff1610156103b1578463ffffffff16600c148061037957508463ffffffff16600d145b8061038a57508463ffffffff16600e145b1561039b578561ffff16925061040b565b6103aa8661ffff166010610938565b925061040b565b60288563ffffffff161015806103cd57508463ffffffff166022145b806103de57508463ffffffff166026145b1561040b578661016001518263ffffffff166020811061040057610400611e69565b602002015192508190505b60048563ffffffff1610158015610428575060088563ffffffff16105b8061043957508463ffffffff166001145b156104585761044a858784876109ab565b975050505050505050610666565b63ffffffff60006020878316106104bd576104788861ffff166010610938565b9095019463fffffffc861661048e81600161078b565b915060288863ffffffff16101580156104ae57508763ffffffff16603014155b156104bb57809250600093505b505b60006104cb89888885610bbb565b63ffffffff9081169150603f8a169089161580156104f0575060088163ffffffff1610155b80156105025750601c8163ffffffff16105b156105df578063ffffffff166008148061052257508063ffffffff166009145b15610559576105478163ffffffff1660081461053e5785610541565b60005b89610847565b9b505050505050505050505050610666565b8063ffffffff16600a0361057957610547858963ffffffff8a161561134b565b8063ffffffff16600b0361059a57610547858963ffffffff8a16151561134b565b8063ffffffff16600c036105b1576105478d611431565b60108163ffffffff16101580156105ce5750601c8163ffffffff16105b156105df5761054781898988611968565b8863ffffffff1660381480156105fa575063ffffffff861615155b1561062f5760018b61016001518763ffffffff166020811061061e5761061e611e69565b63ffffffff90921660209290920201525b8363ffffffff1663ffffffff1461064c5761064c84600184611b62565b6106588583600161134b565b9b5050505050505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a840152600092610200929091606283019190855b602081101561070e57601c86015184526020909501946004909301926001016106ea565b506000835283830384a060009450806001811461072e5760039550610756565b828015610746576001811461074f5760029650610754565b60009650610754565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b60008061079783611c06565b905060038416156107a757600080fd5b6020810190358460051c8160005b601b81101561080d5760208501943583821c60011680156107dd57600181146107f257610803565b60008481526020839052604090209350610803565b600082815260208590526040902093505b50506001016107b5565b50608051915081811461082857630badf00d60005260206000fd5b5050601f94909416601c0360031b9390931c63ffffffff169392505050565b6000610851611caf565b60809050806060015160040163ffffffff16816080015163ffffffff16146108da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b60608101805160808301805163ffffffff90811690935285831690529085161561093057806008018261016001518663ffffffff166020811061091f5761091f611e69565b63ffffffff90921660209290920201525b61066661066f565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b0182610995576000610997565b815b90861663ffffffff16179250505092915050565b60006109b5611caf565b608090506000816060015160040163ffffffff16826080015163ffffffff1614610a3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f7400000000000000000000000060448201526064016108d1565b8663ffffffff1660041480610a5657508663ffffffff166005145b15610ad25760008261016001518663ffffffff1660208110610a7a57610a7a611e69565b602002015190508063ffffffff168563ffffffff16148015610aa257508763ffffffff166004145b80610aca57508063ffffffff168563ffffffff1614158015610aca57508763ffffffff166005145b915050610b4f565b8663ffffffff16600603610aef5760008460030b13159050610b4f565b8663ffffffff16600703610b0b5760008460030b139050610b4f565b8663ffffffff16600103610b4f57601f601087901c166000819003610b345760008560030b1291505b8063ffffffff16600103610b4d5760008560030b121591505b505b606082018051608084015163ffffffff169091528115610b95576002610b7a8861ffff166010610938565b63ffffffff90811690911b8201600401166080840152610ba7565b60808301805160040163ffffffff1690525b610baf61066f565b98975050505050505050565b6000603f601a86901c16801580610bea575060088163ffffffff1610158015610bea5750600f8163ffffffff16105b1561104057603f86168160088114610c315760098114610c3a57600a8114610c4357600b8114610c4c57600c8114610c5557600d8114610c5e57600e8114610c6757610c6c565b60209150610c6c565b60219150610c6c565b602a9150610c6c565b602b9150610c6c565b60249150610c6c565b60259150610c6c565b602691505b508063ffffffff16600003610c935750505063ffffffff8216601f600686901c161b611343565b8063ffffffff16600203610cb95750505063ffffffff8216601f600686901c161c611343565b8063ffffffff16600303610cef57601f600688901c16610ce563ffffffff8716821c6020839003610938565b9350505050611343565b8063ffffffff16600403610d115750505063ffffffff8216601f84161b611343565b8063ffffffff16600603610d335750505063ffffffff8216601f84161c611343565b8063ffffffff16600703610d6657610d5d8663ffffffff168663ffffffff16901c87602003610938565b92505050611343565b8063ffffffff16600803610d7e578592505050611343565b8063ffffffff16600903610d96578592505050611343565b8063ffffffff16600a03610dae578592505050611343565b8063ffffffff16600b03610dc6578592505050611343565b8063ffffffff16600c03610dde578592505050611343565b8063ffffffff16600f03610df6578592505050611343565b8063ffffffff16601003610e0e578592505050611343565b8063ffffffff16601103610e26578592505050611343565b8063ffffffff16601203610e3e578592505050611343565b8063ffffffff16601303610e56578592505050611343565b8063ffffffff16601803610e6e578592505050611343565b8063ffffffff16601903610e86578592505050611343565b8063ffffffff16601a03610e9e578592505050611343565b8063ffffffff16601b03610eb6578592505050611343565b8063ffffffff16602003610ecf57505050828201611343565b8063ffffffff16602103610ee857505050828201611343565b8063ffffffff16602203610f0157505050818303611343565b8063ffffffff16602303610f1a57505050818303611343565b8063ffffffff16602403610f3357505050828216611343565b8063ffffffff16602503610f4c57505050828217611343565b8063ffffffff16602603610f6557505050828218611343565b8063ffffffff16602703610f7f5750505082821719611343565b8063ffffffff16602a03610fb0578460030b8660030b12610fa1576000610fa4565b60015b60ff1692505050611343565b8063ffffffff16602b03610fd8578463ffffffff168663ffffffff1610610fa1576000610fa4565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e0000000000000000000000000060448201526064016108d1565b50610fd8565b8063ffffffff16601c036110c457603f8616600281900361106657505050828202611343565b8063ffffffff166020148061108157508063ffffffff166021145b1561103a578063ffffffff16602003611098579419945b60005b63800000008716156110ba576401fffffffe600197881b16960161109b565b9250611343915050565b8063ffffffff16600f036110e657505065ffffffff0000601083901b16611343565b8063ffffffff166020036111225761111a8560031660080260180363ffffffff168463ffffffff16901c60ff166008610938565b915050611343565b8063ffffffff166021036111575761111a8560021660080260100363ffffffff168463ffffffff16901c61ffff166010610938565b8063ffffffff1660220361118657505063ffffffff60086003851602811681811b198416918316901b17611343565b8063ffffffff1660230361119d5782915050611343565b8063ffffffff166024036111cf578460031660080260180363ffffffff168363ffffffff16901c60ff16915050611343565b8063ffffffff16602503611202578460021660080260100363ffffffff168363ffffffff16901c61ffff16915050611343565b8063ffffffff1660260361123457505063ffffffff60086003851602601803811681811c198416918316901c17611343565b8063ffffffff1660280361126a57505060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611343565b8063ffffffff166029036112a157505061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611343565b8063ffffffff16602a036112d057505063ffffffff60086003851602811681811c198316918416901c17611343565b8063ffffffff16602b036112e75783915050611343565b8063ffffffff16602e0361131957505063ffffffff60086003851602601803811681811b198316918416901b17611343565b8063ffffffff166030036113305782915050611343565b8063ffffffff16603803610fd857839150505b949350505050565b6000611355611caf565b506080602063ffffffff8616106113c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c696420726567697374657200000000000000000000000000000000000060448201526064016108d1565b63ffffffff8516158015906113da5750825b1561140e57838161016001518663ffffffff16602081106113fd576113fd611e69565b63ffffffff90921660209290920201525b60808101805163ffffffff8082166060850152600490910116905261066661066f565b600061143b611caf565b506101e051604081015160808083015160a084015160c09094015191936000928392919063ffffffff8616610ffa036114b55781610fff81161561148457610fff811661100003015b8363ffffffff166000036114ab5760e08801805163ffffffff8382011690915295506114af565b8395505b50611927565b8563ffffffff16610fcd036114d05763400000009450611927565b8563ffffffff16611018036114e85760019450611927565b8563ffffffff166110960361151e57600161012088015260ff831661010088015261151161066f565b9998505050505050505050565b8563ffffffff16610fa30361178a5763ffffffff831615611927577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb63ffffffff8416016117445760006115798363fffffffc16600161078b565b60208901519091508060001a6001036115e857604080516000838152336020528d83526060902091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790505b6040808a015190517fe03110e10000000000000000000000000000000000000000000000000000000081526004810183905263ffffffff9091166024820152600090819073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e03110e1906044016040805180830381865afa158015611689573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ad9190611e98565b915091506003861680600403828110156116c5578092505b50818610156116d2578591505b8260088302610100031c9250826008828460040303021b9250600180600883600403021b036001806008858560040303021b039150811981169050838119871617955050506117298663fffffffc16600186611b62565b60408b018051820163ffffffff169052975061178592505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd63ffffffff84160161177957809450611927565b63ffffffff9450600993505b611927565b8563ffffffff16610fa40361187b5763ffffffff8316600114806117b4575063ffffffff83166002145b806117c5575063ffffffff83166004145b156117d257809450611927565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8416016117795760006118128363fffffffc16600161078b565b6020890151909150600384166004038381101561182d578093505b83900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193850293841b0116911b17602088015260006040880152935083611927565b8563ffffffff16610fd703611927578163ffffffff1660030361191b5763ffffffff831615806118b1575063ffffffff83166005145b806118c2575063ffffffff83166003145b156118d05760009450611927565b63ffffffff8316600114806118eb575063ffffffff83166002145b806118fc575063ffffffff83166006145b8061190d575063ffffffff83166004145b156117795760019450611927565b63ffffffff9450601693505b6101608701805163ffffffff808816604090920191909152905185821660e09091015260808801805180831660608b0152600401909116905261151161066f565b6000611972611caf565b506080600063ffffffff8716601003611990575060c0810151611af9565b8663ffffffff166011036119af5763ffffffff861660c0830152611af9565b8663ffffffff166012036119c8575060a0810151611af9565b8663ffffffff166013036119e75763ffffffff861660a0830152611af9565b8663ffffffff16601803611a1b5763ffffffff600387810b9087900b02602081901c821660c08501521660a0830152611af9565b8663ffffffff16601903611a4c5763ffffffff86811681871602602081901c821660c08501521660a0830152611af9565b8663ffffffff16601a03611aa2578460030b8660030b81611a6f57611a6f611ebc565b0763ffffffff1660c0830152600385810b9087900b81611a9157611a91611ebc565b0563ffffffff1660a0830152611af9565b8663ffffffff16601b03611af9578463ffffffff168663ffffffff1681611acb57611acb611ebc565b0663ffffffff90811660c084015285811690871681611aec57611aec611ebc565b0463ffffffff1660a08301525b63ffffffff841615611b3457808261016001518563ffffffff1660208110611b2357611b23611e69565b63ffffffff90921660209290920201525b60808201805163ffffffff80821660608601526004909101169052611b5761066f565b979650505050505050565b6000611b6d83611c06565b90506003841615611b7d57600080fd5b6020810190601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b811015611bfb5760208401933582821c6001168015611bcb5760018114611be057611bf1565b60008581526020839052604090209450611bf1565b600082815260208690526040902094505b5050600101611ba3565b505060805250505050565b60ff8116610380026101a4810190369061052401811015611ca9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f617461000000000000000000000000000000000000000000000000000000000060648201526084016108d1565b50919050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101611d15611d1a565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b81811015611d6657858101830151858201604001528201611d4a565b81811115611d78576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f840112611dbe57600080fd5b50813567ffffffffffffffff811115611dd657600080fd5b602083019150836020828501011115611dee57600080fd5b9250929050565b600080600080600060608688031215611e0d57600080fd5b853567ffffffffffffffff80821115611e2557600080fd5b611e3189838a01611dac565b90975095506020880135915080821115611e4a57600080fd5b50611e5788828901611dac565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008060408385031215611eab57600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a" func init() { diff --git a/op-bindings/bindings/preimageoracle.go b/op-bindings/bindings/preimageoracle.go index f2cc5f7c7f2f..32744870529f 100644 --- a/op-bindings/bindings/preimageoracle.go +++ b/op-bindings/bindings/preimageoracle.go @@ -42,8 +42,8 @@ type PreimageOracleLeaf struct { // PreimageOracleMetaData contains all meta data concerning the PreimageOracle contract. var PreimageOracleMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_minProposalSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_challengePeriod\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"KECCAK_TREE_DEPTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAX_LEAF_COUNT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addLeavesLPP\",\"inputs\":[{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_inputStartBlock\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_stateCommitments\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"_finalize\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"challengeFirstLPP\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_postState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_postStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"challengeLPP\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_stateMatrix\",\"type\":\"tuple\",\"internalType\":\"structLibKeccak.StateMatrix\",\"components\":[{\"name\":\"state\",\"type\":\"uint64[25]\",\"internalType\":\"uint64[25]\"}]},{\"name\":\"_preState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_preStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"_postState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_postStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"challengePeriod\",\"inputs\":[],\"outputs\":[{\"name\":\"challengePeriod_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTreeRootLPP\",\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"treeRoot_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initLPP\",\"inputs\":[{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_partOffset\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"_claimedSize\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadKeccak256PreimagePart\",\"inputs\":[{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_preimage\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadLocalData\",\"inputs\":[{\"name\":\"_ident\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_localContext\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_word\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_size\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"key_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadSha256PreimagePart\",\"inputs\":[{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_preimage\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"minProposalSize\",\"inputs\":[],\"outputs\":[{\"name\":\"minProposalSize_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"preimageLengths\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"preimagePartOk\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"preimageParts\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBlocks\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBlocksLen\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"len_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBranches\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalCount\",\"inputs\":[],\"outputs\":[{\"name\":\"count_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalMetadata\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"LPPMetaData\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalParts\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposals\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"readPreimage\",\"inputs\":[{\"name\":\"_key\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_offset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"dat_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"datLen_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"squeezeLPP\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_stateMatrix\",\"type\":\"tuple\",\"internalType\":\"structLibKeccak.StateMatrix\",\"components\":[{\"name\":\"state\",\"type\":\"uint64[25]\",\"internalType\":\"uint64[25]\"}]},{\"name\":\"_preState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_preStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"_postState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_postStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"zeroHashes\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"error\",\"name\":\"ActiveProposal\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AlreadyFinalized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadProposal\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInputSize\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidPreimage\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidProof\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotEOA\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PartOffsetOOB\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PostStateMatches\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StatesNotContiguous\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TreeSizeOverflow\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongStartingBlock\",\"inputs\":[]}]", - Bin: "0x60c06040523480156200001157600080fd5b50604051620032ee380380620032ee8339810160408190526200003491620000f3565b60a0829052608081905260005b6200004f600160106200012e565b811015620000ea57600381601081106200006d576200006d62000148565b01546003826010811062000085576200008562000148565b0154604080516020810193909352820152606001604051602081830303815290604052805190602001206003826001620000c091906200015e565b60108110620000d357620000d362000148565b015580620000e18162000179565b91505062000041565b50505062000195565b600080604083850312156200010757600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b60008282101562000143576200014362000118565b500390565b634e487b7160e01b600052603260045260246000fd5b6000821982111562000174576200017462000118565b500190565b6000600182016200018e576200018e62000118565b5060010190565b60805160a051613125620001c9600039600081816103db015261175501526000818161044f015261100201526131256000f3fe608060405234801561001057600080fd5b50600436106101a35760003560e01c80638dc4be11116100ee578063dd24f9bf11610097578063ec5efcbc11610071578063ec5efcbc1461043a578063f3f480d91461044d578063faf37bc714610473578063fef2b4ed1461048657600080fd5b8063dd24f9bf146103d9578063e03110e1146103ff578063e15926111461042757600080fd5b8063b4801e61116100c8578063b4801e61146103ab578063d18534b5146103be578063da35c664146103d157600080fd5b80638dc4be111461032b5780639d53a6481461033e578063b2e67ba81461038057600080fd5b806361238bde116101505780637ac547671161012a5780637ac54767146102ae5780638542cf50146102c1578063882856ef146102ff57600080fd5b806361238bde146102455780636551927b146102705780637917de1d1461029b57600080fd5b80633909af5c116101815780633909af5c146102155780634d52b4c91461022a57806352f0f3ad1461023257600080fd5b8063013cf08b146101a85780630359a563146101ec5780632055b36b1461020d575b600080fd5b6101bb6101b6366004612768565b6104a6565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b6101ff6101fa3660046127aa565b6104eb565b6040519081526020016101e3565b6101ff601081565b6102286102233660046129a5565b610623565b005b6101ff610871565b6101ff610240366004612a91565b61088c565b6101ff610253366004612acc565b600160209081526000928352604080842090915290825290205481565b6101ff61027e3660046127aa565b601560209081526000928352604080842090915290825290205481565b6102286102a9366004612b30565b610961565b6101ff6102bc366004612768565b610def565b6102ef6102cf366004612acc565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016101e3565b61031261030d366004612bcc565b610e06565b60405167ffffffffffffffff90911681526020016101e3565b610228610339366004612bff565b610e60565b6101ff61034c3660046127aa565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601760209081526040808320938352929052205490565b6101ff61038e3660046127aa565b601660209081526000928352604080842090915290825290205481565b6101ff6103b9366004612bcc565b610f5b565b6102286103cc3660046129a5565b610f8d565b6013546101ff565b7f00000000000000000000000000000000000000000000000000000000000000006101ff565b61041261040d366004612acc565b611358565b604080519283526020830191909152016101e3565b610228610435366004612bff565b611449565b610228610448366004612c4b565b611551565b7f00000000000000000000000000000000000000000000000000000000000000006101ff565b610228610481366004612ce4565b6116cb565b6101ff610494366004612768565b60006020819052908152604090205481565b601381815481106104b657600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061052e9060601c63ffffffff1690565b63ffffffff16905060005b601081101561061b57816001166001036105c15773ffffffffffffffffffffffffffffffffffffffff851660009081526014602090815260408083208784529091529020816010811061058e5761058e612d20565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610602565b82600382601081106105d5576105d5612d20565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c908061061381612d7e565b915050610539565b505092915050565b600061062f8a8a6104eb565b905061065286868360208b013561064d6106488d612db6565b6118de565b61191e565b80156106705750610670838383602088013561064d6106488a612db6565b6106a6576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8660400135886040516020016106bc9190612e85565b6040516020818303038152906040528051906020012014610709576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161071f9190612ec3565b14610756576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61079e886107648680612edb565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197f92505050565b6107a788611ada565b8360400135886040516020016107bd9190612e85565b604051602081830303815290604052805190602001200361080a576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505073ffffffffffffffffffffffffffffffffffffffff9590951660009081526015602090815260408083209683529590529390932080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117905550505050565b600161087f60106002613062565b610889919061306e565b81565b60006108988686612376565b90506108a5836008612ec3565b8211806108b25750602083115b156108e9576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b6060811561097a576109738686612423565b90506109b4565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b8154815260200190600101908083116109e157505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610a628260601c63ffffffff1690565b63ffffffff169050333214610aa3576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ab38260801c63ffffffff1690565b63ffffffff16600003610af2576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610afc8260c01c90565b67ffffffffffffffff1615610b3d576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610b76576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b8389898d88866124ac565b83516020850160888204881415608883061715610ba8576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610c58578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610c4d576001821615610c2d5782818b0152610c4d565b8981015160009081526020938452604090209260019290921c9101610c10565b505050608801610bb5565b50505050600160106002610c6c9190613062565b610c76919061306e565b811115610caf576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d24610cc28360401c63ffffffff1690565b610cd29063ffffffff168a612ec3565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b91508415610d4f5777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b1791505b3360009081526014602090815260408083208e84529091529020610d75908460106126de565b50503360008181526017602090815260408083208e8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055928252601581528282209c82529b909b52909920989098555050505050505050565b60038160108110610dff57600080fd5b0154905081565b60176020528260005260406000206020528160005260406000208181548110610e2e57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b604435600080600883018610610e7e5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa905080610eab57600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b60146020528260005260406000206020528160005260406000208160108110610f8357600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff811615611000576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061102b8260c01c90565b61103f9067ffffffffffffffff164261306e565b11611076576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006110828b8b6104eb565b905061109b87878360208c013561064d6106488e612db6565b80156110b957506110b9848483602089013561064d6106488b612db6565b6110ef576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016111059190612e85565b6040516020818303038152906040528051906020012014611152576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460200135886020013560016111689190612ec3565b14158061119a575060016111828360601c63ffffffff1690565b61118c9190613085565b63ffffffff16856020013514155b156111d1576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006111e38360801c63ffffffff1690565b63ffffffff169050806111fc8460401c63ffffffff1690565b63ffffffff1614611239576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112478a6107648880612edb565b6112508a611ada565b600061125b8b6125ff565b9050600061126f8560a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601660008f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008e8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555082600080848152602001908152602001600020819055505050505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166113e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546113fd816008612ec3565b611408856020612ec3565b106114265783611419826008612ec3565b611423919061306e565b91505b506000938452600160209081526040808620948652939052919092205492909150565b6044356000806008830186106114675763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b600061155d86866104eb565b9050611576838383602088013561064d6106488a612db6565b6115ac576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840135156115e8576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115f061271c565b6115fe816107648780612edb565b61160781611ada565b84604001358160405160200161161d9190612e85565b604051602081830303815290604052805190602001200361166a576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505073ffffffffffffffffffffffffffffffffffffffff9290921660009081526015602090815260408083209383529290522080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117905550565b333214611704576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61170f8160086130aa565b63ffffffff168263ffffffff1610611753576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff1610156117b3576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152601560209081526040808320878452825280832080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660a09790971b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff169690961760809590951b9490941790945582518084019093529082529181019283526013805460018101825592525160029091027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0908101805473ffffffffffffffffffffffffffffffffffffffff9093167fffffffffffffffffffffffff00000000000000000000000000000000000000009093169290921790915590517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a09190910155565b6000816000015182602001518360400151604051602001611901939291906130d2565b604051602081830303815290604052805190602001209050919050565b60008160005b6010811015611972578060051b880135600186831c16600181146119575760008481526020839052604090209350611968565b600082815260208590526040902093505b5050600101611924565b5090931495945050505050565b608881511461198d57600080fd5b6020810160208301611a0e565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050611a08816119f3868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b611a1a6000838361199a565b611a266001838361199a565b611a326002838361199a565b611a3e6003838361199a565b611a4a6004838361199a565b611a566005838361199a565b611a626006838361199a565b611a6e6007838361199a565b611a7a6008838361199a565b611a866009838361199a565b611a92600a838361199a565b611a9e600b838361199a565b611aaa600c838361199a565b611ab6600d838361199a565b611ac2600e838361199a565b611ace600f838361199a565b611a086010838361199a565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e00160405160208183030381529060405290506020820160208201612256565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c611c8d8660011b67ffffffffffffffff1690565b18188584603f1c611ca88660011b67ffffffffffffffff1690565b18188584603f1c611cc38660011b67ffffffffffffffff1690565b181895508483603f1c611ce08560011b67ffffffffffffffff1690565b181894508387603f1c611cfd8960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525050505050565b61207d81611bd0565b805160208201805160408401805160608601805160808801805167ffffffffffffffff871986168a188116808c528619851689188216909952831982169095188516909552841988169091188316909152941990921618811690925260a08301805160c0808601805160e0880180516101008a0180516101208c018051861985168a188d16909a528319821686188c16909652801989169092188a169092528619861618881690529219909216909218841690526101408401805161016086018051610180880180516101a08a0180516101c08c0180518619851689188d169099528319821686188c16909652801988169092188a169092528519851618881690529119909116909118841690526101e08401805161020086018051610220880180516102408a0180516102608c0180518619851689188d169099528319821686188c16909652801988169092188a16909252851985161888169052911990911690911884169052610280840180516102a0860180516102c0880180516102e08a0180516103008c0180518619851689188d169099528319821686188c16909652801988169092188a16909252851985161888169052911990911690911884169052600386901b850151901c9081189091168252611a08565b61226260008284612074565b61226e60018284612074565b61227a60028284612074565b61228660038284612074565b61229260048284612074565b61229e60058284612074565b6122aa60068284612074565b6122b660078284612074565b6122c260088284612074565b6122ce60098284612074565b6122da600a8284612074565b6122e6600b8284612074565b6122f2600c8284612074565b6122fe600d8284612074565b61230a600e8284612074565b612316600f8284612074565b61232260108284612074565b61232e60118284612074565b61233a60128284612074565b61234660138284612074565b61235260148284612074565b61235e60158284612074565b61236a60168284612074565b611a0860178284612074565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83161761241c818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612481576088829003850160808582017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01536001845160001a1784538652612493565b60018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b60006124be8260a01c63ffffffff1690565b67ffffffffffffffff16905060006124dc8360801c63ffffffff1690565b63ffffffff16905060006124f68460401c63ffffffff1690565b63ffffffff16905060088310801561250c575080155b156125405760c082901b6000908152883560085283513382526016602090815260408084208a8552909152909120556125f5565b6008831015801561255e57508061255860088561306e565b93508310155b8015612572575061256f8782612ec3565b83105b156125f5576000612583828561306e565b905087612591826020612ec3565b1015801561259d575085155b156125d4576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526016602090815260408083208a845290915290209089013590555b5050505050505050565b6000612682565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff006126308360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff000061265d8360101b67ffffffffffffffff1690565b1617905060008160201c61267b8360201b67ffffffffffffffff1690565b1792915050565b6080820151602083019061269a90612606565b612606565b60408201516126a890612606565b60401b176126c061269560018460059190911b015190565b825160809190911b906126d290612606565b60c01b17179392505050565b826010810192821561270c579160200282015b8281111561270c5782518255916020019190600101906126f1565b50612718929150612734565b5090565b604051806020016040528061272f612749565b905290565b5b808211156127185760008155600101612735565b6040518061032001604052806019906020820280368337509192915050565b60006020828403121561277a57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146127a557600080fd5b919050565b600080604083850312156127bd57600080fd5b6127c683612781565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612827576128276127d4565b60405290565b6040516060810167ffffffffffffffff81118282101715612827576128276127d4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612897576128976127d4565b604052919050565b60006103208083850312156128b357600080fd5b604051602080820167ffffffffffffffff83821081831117156128d8576128d86127d4565b8160405283955087601f8801126128ee57600080fd5b6128f6612803565b948701949150818886111561290a57600080fd5b875b8681101561293257803583811681146129255760008081fd5b845292840192840161290c565b50909352509295945050505050565b60006060828403121561295357600080fd5b50919050565b60008083601f84011261296b57600080fd5b50813567ffffffffffffffff81111561298357600080fd5b6020830191508360208260051b850101111561299e57600080fd5b9250929050565b60008060008060008060008060006103e08a8c0312156129c457600080fd5b6129cd8a612781565b985060208a013597506129e38b60408c0161289f565b96506103608a013567ffffffffffffffff80821115612a0157600080fd5b612a0d8d838e01612941565b97506103808c0135915080821115612a2457600080fd5b612a308d838e01612959565b90975095506103a08c0135915080821115612a4a57600080fd5b612a568d838e01612941565b94506103c08c0135915080821115612a6d57600080fd5b50612a7a8c828d01612959565b915080935050809150509295985092959850929598565b600080600080600060a08688031215612aa957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060408385031215612adf57600080fd5b50508035926020909101359150565b60008083601f840112612b0057600080fd5b50813567ffffffffffffffff811115612b1857600080fd5b60208301915083602082850101111561299e57600080fd5b600080600080600080600060a0888a031215612b4b57600080fd5b8735965060208801359550604088013567ffffffffffffffff80821115612b7157600080fd5b612b7d8b838c01612aee565b909750955060608a0135915080821115612b9657600080fd5b50612ba38a828b01612959565b90945092505060808801358015158114612bbc57600080fd5b8091505092959891949750929550565b600080600060608486031215612be157600080fd5b612bea84612781565b95602085013595506040909401359392505050565b600080600060408486031215612c1457600080fd5b83359250602084013567ffffffffffffffff811115612c3257600080fd5b612c3e86828701612aee565b9497909650939450505050565b600080600080600060808688031215612c6357600080fd5b612c6c86612781565b945060208601359350604086013567ffffffffffffffff80821115612c9057600080fd5b612c9c89838a01612941565b94506060880135915080821115612cb257600080fd5b50612cbf88828901612959565b969995985093965092949392505050565b803563ffffffff811681146127a557600080fd5b600080600060608486031215612cf957600080fd5b83359250612d0960208501612cd0565b9150612d1760408501612cd0565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612daf57612daf612d4f565b5060010190565b600060608236031215612dc857600080fd5b612dd061282d565b823567ffffffffffffffff80821115612de857600080fd5b9084019036601f830112612dfb57600080fd5b8135602082821115612e0f57612e0f6127d4565b612e3f817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612850565b92508183523681838601011115612e5557600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b6019811015612eba57825167ffffffffffffffff16825260209283019290910190600101612e91565b50505092915050565b60008219821115612ed657612ed6612d4f565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612f1057600080fd5b83018035915067ffffffffffffffff821115612f2b57600080fd5b60200191503681900382131561299e57600080fd5b600181815b80851115612f9957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115612f7f57612f7f612d4f565b80851615612f8c57918102915b93841c9390800290612f45565b509250929050565b600082612fb05750600161305c565b81612fbd5750600061305c565b8160018114612fd35760028114612fdd57612ff9565b600191505061305c565b60ff841115612fee57612fee612d4f565b50506001821b61305c565b5060208310610133831016604e8410600b841016171561301c575081810a61305c565b6130268383612f40565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561305857613058612d4f565b0290505b92915050565b600061241c8383612fa1565b60008282101561308057613080612d4f565b500390565b600063ffffffff838116908316818110156130a2576130a2612d4f565b039392505050565b600063ffffffff8083168185168083038211156130c9576130c9612d4f565b01949350505050565b6000845160005b818110156130f357602081880181015185830152016130d9565b81811115613102576000828501525b509190910192835250602082015260400191905056fea164736f6c634300080f000a", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_minProposalSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_challengePeriod\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"KECCAK_TREE_DEPTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAX_LEAF_COUNT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MIN_BOND_SIZE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addLeavesLPP\",\"inputs\":[{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_inputStartBlock\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_stateCommitments\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"_finalize\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"challengeFirstLPP\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_postState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_postStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"challengeLPP\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_stateMatrix\",\"type\":\"tuple\",\"internalType\":\"structLibKeccak.StateMatrix\",\"components\":[{\"name\":\"state\",\"type\":\"uint64[25]\",\"internalType\":\"uint64[25]\"}]},{\"name\":\"_preState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_preStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"_postState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_postStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"challengePeriod\",\"inputs\":[],\"outputs\":[{\"name\":\"challengePeriod_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTreeRootLPP\",\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"treeRoot_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initLPP\",\"inputs\":[{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_partOffset\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"_claimedSize\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"loadBlobPreimagePart\",\"inputs\":[{\"name\":\"_z\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_y\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_commitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadKeccak256PreimagePart\",\"inputs\":[{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_preimage\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadLocalData\",\"inputs\":[{\"name\":\"_ident\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_localContext\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_word\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_size\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"key_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadPrecompilePreimagePart\",\"inputs\":[{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_precompile\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_input\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadSha256PreimagePart\",\"inputs\":[{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_preimage\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"minProposalSize\",\"inputs\":[],\"outputs\":[{\"name\":\"minProposalSize_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"preimageLengths\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"preimagePartOk\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"preimageParts\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBlocks\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBlocksLen\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"len_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBonds\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBranches\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalCount\",\"inputs\":[],\"outputs\":[{\"name\":\"count_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalMetadata\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"LPPMetaData\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalParts\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposals\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"readPreimage\",\"inputs\":[{\"name\":\"_key\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_offset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"dat_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"datLen_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"squeezeLPP\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_stateMatrix\",\"type\":\"tuple\",\"internalType\":\"structLibKeccak.StateMatrix\",\"components\":[{\"name\":\"state\",\"type\":\"uint64[25]\",\"internalType\":\"uint64[25]\"}]},{\"name\":\"_preState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_preStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"_postState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_postStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"zeroHashes\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"error\",\"name\":\"ActiveProposal\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AlreadyFinalized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadProposal\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BondTransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InsufficientBond\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInputSize\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidPreimage\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidProof\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotEOA\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PartOffsetOOB\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PostStateMatches\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StatesNotContiguous\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TreeSizeOverflow\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongStartingBlock\",\"inputs\":[]}]", + Bin: "0x60c06040523480156200001157600080fd5b50604051620039e6380380620039e68339810160408190526200003491620000f3565b60a0829052608081905260005b6200004f600160106200012e565b811015620000ea57600381601081106200006d576200006d62000148565b01546003826010811062000085576200008562000148565b0154604080516020810193909352820152606001604051602081830303815290604052805190602001206003826001620000c091906200015e565b60108110620000d357620000d362000148565b015580620000e18162000179565b91505062000041565b50505062000195565b600080604083850312156200010757600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b60008282101562000143576200014362000118565b500390565b634e487b7160e01b600052603260045260246000fd5b6000821982111562000174576200017462000118565b500190565b6000600182016200018e576200018e62000118565b5060010190565b60805160a05161381d620001c9600039600081816105ae0152611d3e01526000818161068e01526115a6015261381d6000f3fe6080604052600436106101cd5760003560e01c80638dc4be11116100f7578063dd24f9bf11610095578063ec5efcbc11610064578063ec5efcbc1461065f578063f3f480d91461067f578063faf37bc7146106b2578063fef2b4ed146106c557600080fd5b8063dd24f9bf1461059f578063ddcd58de146105d2578063e03110e11461060a578063e15926111461063f57600080fd5b8063b2e67ba8116100d1578063b2e67ba814610512578063b4801e611461054a578063d18534b51461056a578063da35c6641461058a57600080fd5b80638dc4be11146104835780639d53a648146104a35780639d7e8769146104f257600080fd5b806354fd4d501161016f5780637917de1d1161013e5780637917de1d146103bf5780637ac54767146103df5780638542cf50146103ff578063882856ef1461044a57600080fd5b806354fd4d50146102dd57806361238bde146103335780636551927b1461036b5780637051472e146103a357600080fd5b80632055b36b116101ab5780632055b36b146102735780633909af5c146102885780634d52b4c9146102a857806352f0f3ad146102bd57600080fd5b8063013cf08b146101d25780630359a5631461022357806304697c7814610251575b600080fd5b3480156101de57600080fd5b506101f26101ed366004612d1c565b6106f2565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561022f57600080fd5b5061024361023e366004612d5e565b610737565b60405190815260200161021a565b34801561025d57600080fd5b5061027161026c366004612dd1565b61086f565b005b34801561027f57600080fd5b50610243601081565b34801561029457600080fd5b506102716102a3366004612ff5565b6109a5565b3480156102b457600080fd5b50610243610bfc565b3480156102c957600080fd5b506102436102d83660046130e1565b610c17565b3480156102e957600080fd5b506103266040518060400160405280600581526020017f302e312e3000000000000000000000000000000000000000000000000000000081525081565b60405161021a9190613148565b34801561033f57600080fd5b5061024361034e366004613199565b600160209081526000928352604080842090915290825290205481565b34801561037757600080fd5b50610243610386366004612d5e565b601560209081526000928352604080842090915290825290205481565b3480156103af57600080fd5b506102436703782dace9d9000081565b3480156103cb57600080fd5b506102716103da3660046131bb565b610cec565b3480156103eb57600080fd5b506102436103fa366004612d1c565b6111dc565b34801561040b57600080fd5b5061043a61041a366004613199565b600260209081526000928352604080842090915290825290205460ff1681565b604051901515815260200161021a565b34801561045657600080fd5b5061046a610465366004613257565b6111f3565b60405167ffffffffffffffff909116815260200161021a565b34801561048f57600080fd5b5061027161049e36600461328a565b61124d565b3480156104af57600080fd5b506102436104be366004612d5e565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104fe57600080fd5b5061027161050d3660046132d6565b611348565b34801561051e57600080fd5b5061024361052d366004612d5e565b601760209081526000928352604080842090915290825290205481565b34801561055657600080fd5b50610243610565366004613257565b6114ff565b34801561057657600080fd5b50610271610585366004612ff5565b611531565b34801561059657600080fd5b50601354610243565b3480156105ab57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610243565b3480156105de57600080fd5b506102436105ed366004612d5e565b601660209081526000928352604080842090915290825290205481565b34801561061657600080fd5b5061062a610625366004613199565b6118f3565b6040805192835260208301919091520161021a565b34801561064b57600080fd5b5061027161065a36600461328a565b6119e4565b34801561066b57600080fd5b5061027161067a366004613362565b611aec565b34801561068b57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610243565b6102716106c03660046133fb565b611c72565b3480156106d157600080fd5b506102436106e0366004612d1c565b60006020819052908152604090205481565b6013818154811061070257600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061077a9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610867578160011660010361080d5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107da576107da613437565b0154604080516020810192909252810184905260600160405160208183030381529060405280519060200120925061084e565b826003826010811061082157610821613437565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c908061085f81613495565b915050610785565b505092915050565b600080600080608060146030823785878260140137601480870182207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06000000000000000000000000000000000000000000000000000000000000001794506000908190889084018b5afa94503d60010191506008820189106108fc5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e88017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208c8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209b83529a81528a82209290925593845283905296909120959095555050505050565b60006109b18a8a610737565b90506109d486868360208b01356109cf6109ca8d6134cd565b611edd565b611f1d565b80156109f257506109f283838360208801356109cf6109ca8a6134cd565b610a28576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b866040013588604051602001610a3e919061359c565b6040516020818303038152906040528051906020012014610a8b576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836020013587602001356001610aa191906135da565b14610ad8576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b2088610ae686806135f2565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f7e92505050565b610b29886120d9565b836040013588604051602001610b3f919061359c565b6040516020818303038152906040528051906020012003610b8c576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610bf08a8a33612881565b50505050505050505050565b6001610c0a60106002613779565b610c149190613785565b81565b6000610c23868661293a565b9050610c308360086135da565b821180610c3d5750602083115b15610c74576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610d0557610cfe86866129e7565b9050610d3f565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610d6c57505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610ded8260601c63ffffffff1690565b63ffffffff169050333214610e2e576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e3e8260801c63ffffffff1690565b63ffffffff16600003610e7d576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e878260c01c90565b67ffffffffffffffff1615610ec8576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610f01576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f0e89898d8886612a60565b83516020850160888204881415608883061715610f33576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610fe3578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610fd8576001821615610fb85782818b0152610fd8565b8981015160009081526020938452604090209260019290921c9101610f9b565b505050608801610f40565b50505050600160106002610ff79190613779565b6110019190613785565b81111561103a576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110af61104d8360401c63ffffffff1690565b61105d9063ffffffff168a6135da565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b9150841561113c5777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b1791506110e98260801c63ffffffff1690565b63ffffffff166110ff8360401c63ffffffff1690565b63ffffffff161461113c576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061116290846010612c92565b50503360008181526018602090815260408083208e8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055928252601581528282209c82529b909b52909920989098555050505050505050565b600381601081106111ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061121b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061126b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061129857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806113705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826113f2576309bde3396000526004601cfd5b602886106114085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061152757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156115a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006115cf8260c01c90565b6115e39067ffffffffffffffff1642613785565b1161161a576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006116268b8b610737565b905061163f87878360208c01356109cf6109ca8e6134cd565b801561165d575061165d84848360208901356109cf6109ca8b6134cd565b611693576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016116a9919061359c565b60405160208183030381529060405280519060200120146116f6576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161170c91906135da565b14158061173e575060016117268360601c63ffffffff1690565b611730919061379c565b63ffffffff16856020013514155b15611775576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61178389610ae687806135f2565b61178c896120d9565b60006117978a612bb3565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f020000000000000000000000000000000000000000000000000000000000000017905060006117ee8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d815260200190815260200160002054600160008481526020019081526020016000206000838152602001908152602001600020819055506118c08460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118e48d8d81612881565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff1661197c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546119988160086135da565b6119a38560206135da565b106119c157836119b48260086135da565b6119be9190613785565b91505b506000938452600160209081526040808620948652939052919092205492909150565b604435600080600883018610611a025763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b6000611af88686610737565b9050611b1183838360208801356109cf6109ca8a6134cd565b611b47576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611b83576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b8b612cd0565b611b9981610ae687806135f2565b611ba2816120d9565b846040013581604051602001611bb8919061359c565b6040516020818303038152906040528051906020012003611c05576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611c69878733612881565b50505050505050565b6703782dace9d90000341015611cb4576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611ced576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cf88160086137c1565b63ffffffff168263ffffffff1610611d3c576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff161015611d9c576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152601560209081526040808320878452825280832080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660a09790971b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff169690961760809590951b949094179094558251808401845282815280850186815260138054600181018255908452915160029092027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0908101805473ffffffffffffffffffffffffffffffffffffffff9094167fffffffffffffffffffffffff000000000000000000000000000000000000000090941693909317909255517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015590815260168352818120938152929091529020349055565b6000816000015182602001518360400151604051602001611f00939291906137e9565b604051602081830303815290604052805190602001209050919050565b60008160005b6010811015611f71578060051b880135600186831c1660018114611f565760008481526020839052604090209350611f67565b600082815260208590526040902093505b5050600101611f23565b5090931495945050505050565b6088815114611f8c57600080fd5b602081016020830161200d565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b171717905061200781611ff2868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b61201960008383611f99565b61202560018383611f99565b61203160028383611f99565b61203d60038383611f99565b61204960048383611f99565b61205560058383611f99565b61206160068383611f99565b61206d60078383611f99565b61207960088383611f99565b61208560098383611f99565b612091600a8383611f99565b61209d600b8383611f99565b6120a9600c8383611f99565b6120b5600d8383611f99565b6120c1600e8383611f99565b6120cd600f8383611f99565b61200760108383611f99565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e00160405160208183030381529060405290506020820160208201612761565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c61228c8660011b67ffffffffffffffff1690565b18188584603f1c6122a78660011b67ffffffffffffffff1690565b18188584603f1c6122c28660011b67ffffffffffffffff1690565b181895508483603f1c6122df8560011b67ffffffffffffffff1690565b181894508387603f1c6122fc8960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611c69565b6126fb600082612674565b612706600582612674565b612711600a82612674565b61271c600f82612674565b612727601482612674565b50565b612733816121cf565b61273c816126f0565b600383901b820151815160c09190911c9061200790821867ffffffffffffffff168352565b61276d6000828461272a565b6127796001828461272a565b6127856002828461272a565b6127916003828461272a565b61279d6004828461272a565b6127a96005828461272a565b6127b56006828461272a565b6127c16007828461272a565b6127cd6008828461272a565b6127d96009828461272a565b6127e5600a828461272a565b6127f1600b828461272a565b6127fd600c828461272a565b612809600d828461272a565b612815600e828461272a565b612821600f828461272a565b61282d6010828461272a565b6128396011828461272a565b6128456012828461272a565b6128516013828461272a565b61285d6014828461272a565b6128696015828461272a565b6128756016828461272a565b6120076017828461272a565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d80600081146128fa576040519150601f19603f3d011682016040523d82523d6000602084013e6128ff565b606091505b505090508061266d576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316176129e0818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612a305760888290038501848101848103803687375060806001820353506001845160001a1784538652612a47565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612a728260a01c63ffffffff1690565b67ffffffffffffffff1690506000612a908360801c63ffffffff1690565b63ffffffff1690506000612aaa8460401c63ffffffff1690565b63ffffffff169050600883108015612ac0575080155b15612af45760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612ba9565b60088310158015612b12575080612b0c600885613785565b93508310155b8015612b265750612b2387826135da565b83105b15612ba9576000612b378285613785565b905087612b458260206135da565b10158015612b51575085155b15612b88576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612c36565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612be48360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612c118360101b67ffffffffffffffff1690565b1617905060008160201c612c2f8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612c4e90612bba565b612bba565b6040820151612c5c90612bba565b60401b17612c74612c4960018460059190911b015190565b825160809190911b90612c8690612bba565b60c01b17179392505050565b8260108101928215612cc0579160200282015b82811115612cc0578251825591602001919060010190612ca5565b50612ccc929150612ce8565b5090565b6040518060200160405280612ce3612cfd565b905290565b5b80821115612ccc5760008155600101612ce9565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612d2e57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612d5957600080fd5b919050565b60008060408385031215612d7157600080fd5b612d7a83612d35565b946020939093013593505050565b60008083601f840112612d9a57600080fd5b50813567ffffffffffffffff811115612db257600080fd5b602083019150836020828501011115612dca57600080fd5b9250929050565b60008060008060608587031215612de757600080fd5b84359350612df760208601612d35565b9250604085013567ffffffffffffffff811115612e1357600080fd5b612e1f87828801612d88565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612e7e57612e7e612e2b565b60405290565b6040516060810167ffffffffffffffff81118282101715612e7e57612e7e612e2b565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612eee57612eee612e2b565b604052919050565b6000610320808385031215612f0a57600080fd5b604051602080820167ffffffffffffffff8382108183111715612f2f57612f2f612e2b565b8160405283955087601f880112612f4557600080fd5b612f4d612e5a565b9487019491508188861115612f6157600080fd5b875b86811015612f895780358381168114612f7c5760008081fd5b8452928401928401612f63565b50909352509295945050505050565b600060608284031215612faa57600080fd5b50919050565b60008083601f840112612fc257600080fd5b50813567ffffffffffffffff811115612fda57600080fd5b6020830191508360208260051b8501011115612dca57600080fd5b60008060008060008060008060006103e08a8c03121561301457600080fd5b61301d8a612d35565b985060208a013597506130338b60408c01612ef6565b96506103608a013567ffffffffffffffff8082111561305157600080fd5b61305d8d838e01612f98565b97506103808c013591508082111561307457600080fd5b6130808d838e01612fb0565b90975095506103a08c013591508082111561309a57600080fd5b6130a68d838e01612f98565b94506103c08c01359150808211156130bd57600080fd5b506130ca8c828d01612fb0565b915080935050809150509295985092959850929598565b600080600080600060a086880312156130f957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b8381101561313757818101518382015260200161311f565b838111156120075750506000910152565b602081526000825180602084015261316781604085016020870161311c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080604083850312156131ac57600080fd5b50508035926020909101359150565b600080600080600080600060a0888a0312156131d657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156131fc57600080fd5b6132088b838c01612d88565b909750955060608a013591508082111561322157600080fd5b5061322e8a828b01612fb0565b9094509250506080880135801515811461324757600080fd5b8091505092959891949750929550565b60008060006060848603121561326c57600080fd5b61327584612d35565b95602085013595506040909401359392505050565b60008060006040848603121561329f57600080fd5b83359250602084013567ffffffffffffffff8111156132bd57600080fd5b6132c986828701612d88565b9497909650939450505050565b600080600080600080600060a0888a0312156132f157600080fd5b8735965060208801359550604088013567ffffffffffffffff8082111561331757600080fd5b6133238b838c01612d88565b909750955060608a013591508082111561333c57600080fd5b506133498a828b01612d88565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561337a57600080fd5b61338386612d35565b945060208601359350604086013567ffffffffffffffff808211156133a757600080fd5b6133b389838a01612f98565b945060608801359150808211156133c957600080fd5b506133d688828901612fb0565b969995985093965092949392505050565b803563ffffffff81168114612d5957600080fd5b60008060006060848603121561341057600080fd5b83359250613420602085016133e7565b915061342e604085016133e7565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036134c6576134c6613466565b5060010190565b6000606082360312156134df57600080fd5b6134e7612e84565b823567ffffffffffffffff808211156134ff57600080fd5b9084019036601f83011261351257600080fd5b813560208282111561352657613526612e2b565b613556817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612ea7565b9250818352368183860101111561356c57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156135d157825167ffffffffffffffff168252602092830192909101906001016135a8565b50505092915050565b600082198211156135ed576135ed613466565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261362757600080fd5b83018035915067ffffffffffffffff82111561364257600080fd5b602001915036819003821315612dca57600080fd5b600181815b808511156136b057817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561369657613696613466565b808516156136a357918102915b93841c939080029061365c565b509250929050565b6000826136c757506001613773565b816136d457506000613773565b81600181146136ea57600281146136f457613710565b6001915050613773565b60ff84111561370557613705613466565b50506001821b613773565b5060208310610133831016604e8410600b8410161715613733575081810a613773565b61373d8383613657565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561376f5761376f613466565b0290505b92915050565b60006129e083836136b8565b60008282101561379757613797613466565b500390565b600063ffffffff838116908316818110156137b9576137b9613466565b039392505050565b600063ffffffff8083168185168083038211156137e0576137e0613466565b01949350505050565b600084516137fb81846020890161311c565b9190910192835250602082015260400191905056fea164736f6c634300080f000a", } // PreimageOracleABI is the input ABI used to generate the binding from. @@ -275,6 +275,37 @@ func (_PreimageOracle *PreimageOracleCallerSession) MAXLEAFCOUNT() (*big.Int, er return _PreimageOracle.Contract.MAXLEAFCOUNT(&_PreimageOracle.CallOpts) } +// MINBONDSIZE is a free data retrieval call binding the contract method 0x7051472e. +// +// Solidity: function MIN_BOND_SIZE() view returns(uint256) +func (_PreimageOracle *PreimageOracleCaller) MINBONDSIZE(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _PreimageOracle.contract.Call(opts, &out, "MIN_BOND_SIZE") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MINBONDSIZE is a free data retrieval call binding the contract method 0x7051472e. +// +// Solidity: function MIN_BOND_SIZE() view returns(uint256) +func (_PreimageOracle *PreimageOracleSession) MINBONDSIZE() (*big.Int, error) { + return _PreimageOracle.Contract.MINBONDSIZE(&_PreimageOracle.CallOpts) +} + +// MINBONDSIZE is a free data retrieval call binding the contract method 0x7051472e. +// +// Solidity: function MIN_BOND_SIZE() view returns(uint256) +func (_PreimageOracle *PreimageOracleCallerSession) MINBONDSIZE() (*big.Int, error) { + return _PreimageOracle.Contract.MINBONDSIZE(&_PreimageOracle.CallOpts) +} + // ChallengePeriod is a free data retrieval call binding the contract method 0xf3f480d9. // // Solidity: function challengePeriod() view returns(uint256 challengePeriod_) @@ -523,6 +554,37 @@ func (_PreimageOracle *PreimageOracleCallerSession) ProposalBlocksLen(_claimant return _PreimageOracle.Contract.ProposalBlocksLen(&_PreimageOracle.CallOpts, _claimant, _uuid) } +// ProposalBonds is a free data retrieval call binding the contract method 0xddcd58de. +// +// Solidity: function proposalBonds(address , uint256 ) view returns(uint256) +func (_PreimageOracle *PreimageOracleCaller) ProposalBonds(opts *bind.CallOpts, arg0 common.Address, arg1 *big.Int) (*big.Int, error) { + var out []interface{} + err := _PreimageOracle.contract.Call(opts, &out, "proposalBonds", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ProposalBonds is a free data retrieval call binding the contract method 0xddcd58de. +// +// Solidity: function proposalBonds(address , uint256 ) view returns(uint256) +func (_PreimageOracle *PreimageOracleSession) ProposalBonds(arg0 common.Address, arg1 *big.Int) (*big.Int, error) { + return _PreimageOracle.Contract.ProposalBonds(&_PreimageOracle.CallOpts, arg0, arg1) +} + +// ProposalBonds is a free data retrieval call binding the contract method 0xddcd58de. +// +// Solidity: function proposalBonds(address , uint256 ) view returns(uint256) +func (_PreimageOracle *PreimageOracleCallerSession) ProposalBonds(arg0 common.Address, arg1 *big.Int) (*big.Int, error) { + return _PreimageOracle.Contract.ProposalBonds(&_PreimageOracle.CallOpts, arg0, arg1) +} + // ProposalBranches is a free data retrieval call binding the contract method 0xb4801e61. // // Solidity: function proposalBranches(address , uint256 , uint256 ) view returns(bytes32) @@ -737,6 +799,37 @@ func (_PreimageOracle *PreimageOracleCallerSession) ReadPreimage(_key [32]byte, return _PreimageOracle.Contract.ReadPreimage(&_PreimageOracle.CallOpts, _key, _offset) } +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_PreimageOracle *PreimageOracleCaller) Version(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _PreimageOracle.contract.Call(opts, &out, "version") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_PreimageOracle *PreimageOracleSession) Version() (string, error) { + return _PreimageOracle.Contract.Version(&_PreimageOracle.CallOpts) +} + +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_PreimageOracle *PreimageOracleCallerSession) Version() (string, error) { + return _PreimageOracle.Contract.Version(&_PreimageOracle.CallOpts) +} + // ZeroHashes is a free data retrieval call binding the contract method 0x7ac54767. // // Solidity: function zeroHashes(uint256 ) view returns(bytes32) @@ -833,25 +926,46 @@ func (_PreimageOracle *PreimageOracleTransactorSession) ChallengeLPP(_claimant c // InitLPP is a paid mutator transaction binding the contract method 0xfaf37bc7. // -// Solidity: function initLPP(uint256 _uuid, uint32 _partOffset, uint32 _claimedSize) returns() +// Solidity: function initLPP(uint256 _uuid, uint32 _partOffset, uint32 _claimedSize) payable returns() func (_PreimageOracle *PreimageOracleTransactor) InitLPP(opts *bind.TransactOpts, _uuid *big.Int, _partOffset uint32, _claimedSize uint32) (*types.Transaction, error) { return _PreimageOracle.contract.Transact(opts, "initLPP", _uuid, _partOffset, _claimedSize) } // InitLPP is a paid mutator transaction binding the contract method 0xfaf37bc7. // -// Solidity: function initLPP(uint256 _uuid, uint32 _partOffset, uint32 _claimedSize) returns() +// Solidity: function initLPP(uint256 _uuid, uint32 _partOffset, uint32 _claimedSize) payable returns() func (_PreimageOracle *PreimageOracleSession) InitLPP(_uuid *big.Int, _partOffset uint32, _claimedSize uint32) (*types.Transaction, error) { return _PreimageOracle.Contract.InitLPP(&_PreimageOracle.TransactOpts, _uuid, _partOffset, _claimedSize) } // InitLPP is a paid mutator transaction binding the contract method 0xfaf37bc7. // -// Solidity: function initLPP(uint256 _uuid, uint32 _partOffset, uint32 _claimedSize) returns() +// Solidity: function initLPP(uint256 _uuid, uint32 _partOffset, uint32 _claimedSize) payable returns() func (_PreimageOracle *PreimageOracleTransactorSession) InitLPP(_uuid *big.Int, _partOffset uint32, _claimedSize uint32) (*types.Transaction, error) { return _PreimageOracle.Contract.InitLPP(&_PreimageOracle.TransactOpts, _uuid, _partOffset, _claimedSize) } +// LoadBlobPreimagePart is a paid mutator transaction binding the contract method 0x9d7e8769. +// +// Solidity: function loadBlobPreimagePart(uint256 _z, uint256 _y, bytes _commitment, bytes _proof, uint256 _partOffset) returns() +func (_PreimageOracle *PreimageOracleTransactor) LoadBlobPreimagePart(opts *bind.TransactOpts, _z *big.Int, _y *big.Int, _commitment []byte, _proof []byte, _partOffset *big.Int) (*types.Transaction, error) { + return _PreimageOracle.contract.Transact(opts, "loadBlobPreimagePart", _z, _y, _commitment, _proof, _partOffset) +} + +// LoadBlobPreimagePart is a paid mutator transaction binding the contract method 0x9d7e8769. +// +// Solidity: function loadBlobPreimagePart(uint256 _z, uint256 _y, bytes _commitment, bytes _proof, uint256 _partOffset) returns() +func (_PreimageOracle *PreimageOracleSession) LoadBlobPreimagePart(_z *big.Int, _y *big.Int, _commitment []byte, _proof []byte, _partOffset *big.Int) (*types.Transaction, error) { + return _PreimageOracle.Contract.LoadBlobPreimagePart(&_PreimageOracle.TransactOpts, _z, _y, _commitment, _proof, _partOffset) +} + +// LoadBlobPreimagePart is a paid mutator transaction binding the contract method 0x9d7e8769. +// +// Solidity: function loadBlobPreimagePart(uint256 _z, uint256 _y, bytes _commitment, bytes _proof, uint256 _partOffset) returns() +func (_PreimageOracle *PreimageOracleTransactorSession) LoadBlobPreimagePart(_z *big.Int, _y *big.Int, _commitment []byte, _proof []byte, _partOffset *big.Int) (*types.Transaction, error) { + return _PreimageOracle.Contract.LoadBlobPreimagePart(&_PreimageOracle.TransactOpts, _z, _y, _commitment, _proof, _partOffset) +} + // LoadKeccak256PreimagePart is a paid mutator transaction binding the contract method 0xe1592611. // // Solidity: function loadKeccak256PreimagePart(uint256 _partOffset, bytes _preimage) returns() @@ -894,6 +1008,27 @@ func (_PreimageOracle *PreimageOracleTransactorSession) LoadLocalData(_ident *bi return _PreimageOracle.Contract.LoadLocalData(&_PreimageOracle.TransactOpts, _ident, _localContext, _word, _size, _partOffset) } +// LoadPrecompilePreimagePart is a paid mutator transaction binding the contract method 0x04697c78. +// +// Solidity: function loadPrecompilePreimagePart(uint256 _partOffset, address _precompile, bytes _input) returns() +func (_PreimageOracle *PreimageOracleTransactor) LoadPrecompilePreimagePart(opts *bind.TransactOpts, _partOffset *big.Int, _precompile common.Address, _input []byte) (*types.Transaction, error) { + return _PreimageOracle.contract.Transact(opts, "loadPrecompilePreimagePart", _partOffset, _precompile, _input) +} + +// LoadPrecompilePreimagePart is a paid mutator transaction binding the contract method 0x04697c78. +// +// Solidity: function loadPrecompilePreimagePart(uint256 _partOffset, address _precompile, bytes _input) returns() +func (_PreimageOracle *PreimageOracleSession) LoadPrecompilePreimagePart(_partOffset *big.Int, _precompile common.Address, _input []byte) (*types.Transaction, error) { + return _PreimageOracle.Contract.LoadPrecompilePreimagePart(&_PreimageOracle.TransactOpts, _partOffset, _precompile, _input) +} + +// LoadPrecompilePreimagePart is a paid mutator transaction binding the contract method 0x04697c78. +// +// Solidity: function loadPrecompilePreimagePart(uint256 _partOffset, address _precompile, bytes _input) returns() +func (_PreimageOracle *PreimageOracleTransactorSession) LoadPrecompilePreimagePart(_partOffset *big.Int, _precompile common.Address, _input []byte) (*types.Transaction, error) { + return _PreimageOracle.Contract.LoadPrecompilePreimagePart(&_PreimageOracle.TransactOpts, _partOffset, _precompile, _input) +} + // LoadSha256PreimagePart is a paid mutator transaction binding the contract method 0x8dc4be11. // // Solidity: function loadSha256PreimagePart(uint256 _partOffset, bytes _preimage) returns() diff --git a/op-bindings/bindings/preimageoracle_more.go b/op-bindings/bindings/preimageoracle_more.go index 91c879882569..8a68057bd712 100644 --- a/op-bindings/bindings/preimageoracle_more.go +++ b/op-bindings/bindings/preimageoracle_more.go @@ -9,11 +9,11 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/solc" ) -const PreimageOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"preimageLengths\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_bytes32,t_uint256)\"},{\"astId\":1001,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"preimageParts\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes32))\"},{\"astId\":1002,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"preimagePartOk\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_bytes32,t_mapping(t_uint256,t_bool))\"},{\"astId\":1003,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"zeroHashes\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_array(t_bytes32)16_storage\"},{\"astId\":1004,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"proposals\",\"offset\":0,\"slot\":\"19\",\"type\":\"t_array(t_struct(LargePreimageProposalKeys)1009_storage)dyn_storage\"},{\"astId\":1005,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"proposalBranches\",\"offset\":0,\"slot\":\"20\",\"type\":\"t_mapping(t_address,t_mapping(t_uint256,t_array(t_bytes32)16_storage))\"},{\"astId\":1006,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"proposalMetadata\",\"offset\":0,\"slot\":\"21\",\"type\":\"t_mapping(t_address,t_mapping(t_uint256,t_userDefinedValueType(LPPMetaData)1010))\"},{\"astId\":1007,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"proposalParts\",\"offset\":0,\"slot\":\"22\",\"type\":\"t_mapping(t_address,t_mapping(t_uint256,t_bytes32))\"},{\"astId\":1008,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"proposalBlocks\",\"offset\":0,\"slot\":\"23\",\"type\":\"t_mapping(t_address,t_mapping(t_uint256,t_array(t_uint64)dyn_storage))\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_bytes32)16_storage\":{\"encoding\":\"inplace\",\"label\":\"bytes32[16]\",\"numberOfBytes\":\"512\",\"base\":\"t_bytes32\"},\"t_array(t_struct(LargePreimageProposalKeys)1009_storage)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"struct PreimageOracle.LargePreimageProposalKeys[]\",\"numberOfBytes\":\"32\",\"base\":\"t_struct(LargePreimageProposalKeys)1009_storage\"},\"t_array(t_uint64)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"uint64[]\",\"numberOfBytes\":\"32\",\"base\":\"t_uint64\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_address,t_mapping(t_uint256,t_array(t_bytes32)16_storage))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(uint256 =\u003e bytes32[16]))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_uint256,t_array(t_bytes32)16_storage)\"},\"t_mapping(t_address,t_mapping(t_uint256,t_array(t_uint64)dyn_storage))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(uint256 =\u003e uint64[]))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_uint256,t_array(t_uint64)dyn_storage)\"},\"t_mapping(t_address,t_mapping(t_uint256,t_bytes32))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(uint256 =\u003e bytes32))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_uint256,t_bytes32)\"},\"t_mapping(t_address,t_mapping(t_uint256,t_userDefinedValueType(LPPMetaData)1010))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(uint256 =\u003e LPPMetaData))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_uint256,t_userDefinedValueType(LPPMetaData)1010)\"},\"t_mapping(t_bytes32,t_mapping(t_uint256,t_bool))\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e mapping(uint256 =\u003e bool))\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_mapping(t_uint256,t_bool)\"},\"t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes32))\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e mapping(uint256 =\u003e bytes32))\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_mapping(t_uint256,t_bytes32)\"},\"t_mapping(t_bytes32,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_uint256\"},\"t_mapping(t_uint256,t_array(t_bytes32)16_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e bytes32[16])\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_array(t_bytes32)16_storage\"},\"t_mapping(t_uint256,t_array(t_uint64)dyn_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e uint64[])\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_array(t_uint64)dyn_storage\"},\"t_mapping(t_uint256,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_bool\"},\"t_mapping(t_uint256,t_bytes32)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e bytes32)\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_bytes32\"},\"t_mapping(t_uint256,t_userDefinedValueType(LPPMetaData)1010)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e LPPMetaData)\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_userDefinedValueType(LPPMetaData)1010\"},\"t_struct(LargePreimageProposalKeys)1009_storage\":{\"encoding\":\"inplace\",\"label\":\"struct PreimageOracle.LargePreimageProposalKeys\",\"numberOfBytes\":\"64\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"},\"t_userDefinedValueType(LPPMetaData)1010\":{\"encoding\":\"inplace\",\"label\":\"LPPMetaData\",\"numberOfBytes\":\"32\"}}}" +const PreimageOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"preimageLengths\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_bytes32,t_uint256)\"},{\"astId\":1001,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"preimageParts\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes32))\"},{\"astId\":1002,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"preimagePartOk\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_bytes32,t_mapping(t_uint256,t_bool))\"},{\"astId\":1003,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"zeroHashes\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_array(t_bytes32)16_storage\"},{\"astId\":1004,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"proposals\",\"offset\":0,\"slot\":\"19\",\"type\":\"t_array(t_struct(LargePreimageProposalKeys)1010_storage)dyn_storage\"},{\"astId\":1005,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"proposalBranches\",\"offset\":0,\"slot\":\"20\",\"type\":\"t_mapping(t_address,t_mapping(t_uint256,t_array(t_bytes32)16_storage))\"},{\"astId\":1006,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"proposalMetadata\",\"offset\":0,\"slot\":\"21\",\"type\":\"t_mapping(t_address,t_mapping(t_uint256,t_userDefinedValueType(LPPMetaData)1011))\"},{\"astId\":1007,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"proposalBonds\",\"offset\":0,\"slot\":\"22\",\"type\":\"t_mapping(t_address,t_mapping(t_uint256,t_uint256))\"},{\"astId\":1008,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"proposalParts\",\"offset\":0,\"slot\":\"23\",\"type\":\"t_mapping(t_address,t_mapping(t_uint256,t_bytes32))\"},{\"astId\":1009,\"contract\":\"src/cannon/PreimageOracle.sol:PreimageOracle\",\"label\":\"proposalBlocks\",\"offset\":0,\"slot\":\"24\",\"type\":\"t_mapping(t_address,t_mapping(t_uint256,t_array(t_uint64)dyn_storage))\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_bytes32)16_storage\":{\"encoding\":\"inplace\",\"label\":\"bytes32[16]\",\"numberOfBytes\":\"512\",\"base\":\"t_bytes32\"},\"t_array(t_struct(LargePreimageProposalKeys)1010_storage)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"struct PreimageOracle.LargePreimageProposalKeys[]\",\"numberOfBytes\":\"32\",\"base\":\"t_struct(LargePreimageProposalKeys)1010_storage\"},\"t_array(t_uint64)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"uint64[]\",\"numberOfBytes\":\"32\",\"base\":\"t_uint64\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_address,t_mapping(t_uint256,t_array(t_bytes32)16_storage))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(uint256 =\u003e bytes32[16]))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_uint256,t_array(t_bytes32)16_storage)\"},\"t_mapping(t_address,t_mapping(t_uint256,t_array(t_uint64)dyn_storage))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(uint256 =\u003e uint64[]))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_uint256,t_array(t_uint64)dyn_storage)\"},\"t_mapping(t_address,t_mapping(t_uint256,t_bytes32))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(uint256 =\u003e bytes32))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_uint256,t_bytes32)\"},\"t_mapping(t_address,t_mapping(t_uint256,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(uint256 =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_uint256,t_uint256)\"},\"t_mapping(t_address,t_mapping(t_uint256,t_userDefinedValueType(LPPMetaData)1011))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(uint256 =\u003e LPPMetaData))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_uint256,t_userDefinedValueType(LPPMetaData)1011)\"},\"t_mapping(t_bytes32,t_mapping(t_uint256,t_bool))\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e mapping(uint256 =\u003e bool))\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_mapping(t_uint256,t_bool)\"},\"t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes32))\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e mapping(uint256 =\u003e bytes32))\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_mapping(t_uint256,t_bytes32)\"},\"t_mapping(t_bytes32,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_uint256\"},\"t_mapping(t_uint256,t_array(t_bytes32)16_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e bytes32[16])\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_array(t_bytes32)16_storage\"},\"t_mapping(t_uint256,t_array(t_uint64)dyn_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e uint64[])\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_array(t_uint64)dyn_storage\"},\"t_mapping(t_uint256,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_bool\"},\"t_mapping(t_uint256,t_bytes32)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e bytes32)\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_bytes32\"},\"t_mapping(t_uint256,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_uint256\"},\"t_mapping(t_uint256,t_userDefinedValueType(LPPMetaData)1011)\":{\"encoding\":\"mapping\",\"label\":\"mapping(uint256 =\u003e LPPMetaData)\",\"numberOfBytes\":\"32\",\"key\":\"t_uint256\",\"value\":\"t_userDefinedValueType(LPPMetaData)1011\"},\"t_struct(LargePreimageProposalKeys)1010_storage\":{\"encoding\":\"inplace\",\"label\":\"struct PreimageOracle.LargePreimageProposalKeys\",\"numberOfBytes\":\"64\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"},\"t_userDefinedValueType(LPPMetaData)1011\":{\"encoding\":\"inplace\",\"label\":\"LPPMetaData\",\"numberOfBytes\":\"32\"}}}" var PreimageOracleStorageLayout = new(solc.StorageLayout) -var PreimageOracleDeployedBin = "0x608060405234801561001057600080fd5b50600436106101a35760003560e01c80638dc4be11116100ee578063dd24f9bf11610097578063ec5efcbc11610071578063ec5efcbc1461043a578063f3f480d91461044d578063faf37bc714610473578063fef2b4ed1461048657600080fd5b8063dd24f9bf146103d9578063e03110e1146103ff578063e15926111461042757600080fd5b8063b4801e61116100c8578063b4801e61146103ab578063d18534b5146103be578063da35c664146103d157600080fd5b80638dc4be111461032b5780639d53a6481461033e578063b2e67ba81461038057600080fd5b806361238bde116101505780637ac547671161012a5780637ac54767146102ae5780638542cf50146102c1578063882856ef146102ff57600080fd5b806361238bde146102455780636551927b146102705780637917de1d1461029b57600080fd5b80633909af5c116101815780633909af5c146102155780634d52b4c91461022a57806352f0f3ad1461023257600080fd5b8063013cf08b146101a85780630359a563146101ec5780632055b36b1461020d575b600080fd5b6101bb6101b6366004612768565b6104a6565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b6101ff6101fa3660046127aa565b6104eb565b6040519081526020016101e3565b6101ff601081565b6102286102233660046129a5565b610623565b005b6101ff610871565b6101ff610240366004612a91565b61088c565b6101ff610253366004612acc565b600160209081526000928352604080842090915290825290205481565b6101ff61027e3660046127aa565b601560209081526000928352604080842090915290825290205481565b6102286102a9366004612b30565b610961565b6101ff6102bc366004612768565b610def565b6102ef6102cf366004612acc565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016101e3565b61031261030d366004612bcc565b610e06565b60405167ffffffffffffffff90911681526020016101e3565b610228610339366004612bff565b610e60565b6101ff61034c3660046127aa565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601760209081526040808320938352929052205490565b6101ff61038e3660046127aa565b601660209081526000928352604080842090915290825290205481565b6101ff6103b9366004612bcc565b610f5b565b6102286103cc3660046129a5565b610f8d565b6013546101ff565b7f00000000000000000000000000000000000000000000000000000000000000006101ff565b61041261040d366004612acc565b611358565b604080519283526020830191909152016101e3565b610228610435366004612bff565b611449565b610228610448366004612c4b565b611551565b7f00000000000000000000000000000000000000000000000000000000000000006101ff565b610228610481366004612ce4565b6116cb565b6101ff610494366004612768565b60006020819052908152604090205481565b601381815481106104b657600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061052e9060601c63ffffffff1690565b63ffffffff16905060005b601081101561061b57816001166001036105c15773ffffffffffffffffffffffffffffffffffffffff851660009081526014602090815260408083208784529091529020816010811061058e5761058e612d20565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610602565b82600382601081106105d5576105d5612d20565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c908061061381612d7e565b915050610539565b505092915050565b600061062f8a8a6104eb565b905061065286868360208b013561064d6106488d612db6565b6118de565b61191e565b80156106705750610670838383602088013561064d6106488a612db6565b6106a6576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8660400135886040516020016106bc9190612e85565b6040516020818303038152906040528051906020012014610709576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161071f9190612ec3565b14610756576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61079e886107648680612edb565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197f92505050565b6107a788611ada565b8360400135886040516020016107bd9190612e85565b604051602081830303815290604052805190602001200361080a576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505073ffffffffffffffffffffffffffffffffffffffff9590951660009081526015602090815260408083209683529590529390932080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117905550505050565b600161087f60106002613062565b610889919061306e565b81565b60006108988686612376565b90506108a5836008612ec3565b8211806108b25750602083115b156108e9576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b6060811561097a576109738686612423565b90506109b4565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b8154815260200190600101908083116109e157505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610a628260601c63ffffffff1690565b63ffffffff169050333214610aa3576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ab38260801c63ffffffff1690565b63ffffffff16600003610af2576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610afc8260c01c90565b67ffffffffffffffff1615610b3d576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610b76576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b8389898d88866124ac565b83516020850160888204881415608883061715610ba8576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610c58578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610c4d576001821615610c2d5782818b0152610c4d565b8981015160009081526020938452604090209260019290921c9101610c10565b505050608801610bb5565b50505050600160106002610c6c9190613062565b610c76919061306e565b811115610caf576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d24610cc28360401c63ffffffff1690565b610cd29063ffffffff168a612ec3565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b91508415610d4f5777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b1791505b3360009081526014602090815260408083208e84529091529020610d75908460106126de565b50503360008181526017602090815260408083208e8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055928252601581528282209c82529b909b52909920989098555050505050505050565b60038160108110610dff57600080fd5b0154905081565b60176020528260005260406000206020528160005260406000208181548110610e2e57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b604435600080600883018610610e7e5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa905080610eab57600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b60146020528260005260406000206020528160005260406000208160108110610f8357600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff811615611000576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061102b8260c01c90565b61103f9067ffffffffffffffff164261306e565b11611076576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006110828b8b6104eb565b905061109b87878360208c013561064d6106488e612db6565b80156110b957506110b9848483602089013561064d6106488b612db6565b6110ef576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016111059190612e85565b6040516020818303038152906040528051906020012014611152576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460200135886020013560016111689190612ec3565b14158061119a575060016111828360601c63ffffffff1690565b61118c9190613085565b63ffffffff16856020013514155b156111d1576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006111e38360801c63ffffffff1690565b63ffffffff169050806111fc8460401c63ffffffff1690565b63ffffffff1614611239576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112478a6107648880612edb565b6112508a611ada565b600061125b8b6125ff565b9050600061126f8560a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601660008f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008e8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555082600080848152602001908152602001600020819055505050505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166113e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546113fd816008612ec3565b611408856020612ec3565b106114265783611419826008612ec3565b611423919061306e565b91505b506000938452600160209081526040808620948652939052919092205492909150565b6044356000806008830186106114675763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b600061155d86866104eb565b9050611576838383602088013561064d6106488a612db6565b6115ac576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840135156115e8576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115f061271c565b6115fe816107648780612edb565b61160781611ada565b84604001358160405160200161161d9190612e85565b604051602081830303815290604052805190602001200361166a576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505073ffffffffffffffffffffffffffffffffffffffff9290921660009081526015602090815260408083209383529290522080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117905550565b333214611704576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61170f8160086130aa565b63ffffffff168263ffffffff1610611753576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff1610156117b3576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152601560209081526040808320878452825280832080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660a09790971b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff169690961760809590951b9490941790945582518084019093529082529181019283526013805460018101825592525160029091027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0908101805473ffffffffffffffffffffffffffffffffffffffff9093167fffffffffffffffffffffffff00000000000000000000000000000000000000009093169290921790915590517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a09190910155565b6000816000015182602001518360400151604051602001611901939291906130d2565b604051602081830303815290604052805190602001209050919050565b60008160005b6010811015611972578060051b880135600186831c16600181146119575760008481526020839052604090209350611968565b600082815260208590526040902093505b5050600101611924565b5090931495945050505050565b608881511461198d57600080fd5b6020810160208301611a0e565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050611a08816119f3868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b611a1a6000838361199a565b611a266001838361199a565b611a326002838361199a565b611a3e6003838361199a565b611a4a6004838361199a565b611a566005838361199a565b611a626006838361199a565b611a6e6007838361199a565b611a7a6008838361199a565b611a866009838361199a565b611a92600a838361199a565b611a9e600b838361199a565b611aaa600c838361199a565b611ab6600d838361199a565b611ac2600e838361199a565b611ace600f838361199a565b611a086010838361199a565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e00160405160208183030381529060405290506020820160208201612256565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c611c8d8660011b67ffffffffffffffff1690565b18188584603f1c611ca88660011b67ffffffffffffffff1690565b18188584603f1c611cc38660011b67ffffffffffffffff1690565b181895508483603f1c611ce08560011b67ffffffffffffffff1690565b181894508387603f1c611cfd8960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525050505050565b61207d81611bd0565b805160208201805160408401805160608601805160808801805167ffffffffffffffff871986168a188116808c528619851689188216909952831982169095188516909552841988169091188316909152941990921618811690925260a08301805160c0808601805160e0880180516101008a0180516101208c018051861985168a188d16909a528319821686188c16909652801989169092188a169092528619861618881690529219909216909218841690526101408401805161016086018051610180880180516101a08a0180516101c08c0180518619851689188d169099528319821686188c16909652801988169092188a169092528519851618881690529119909116909118841690526101e08401805161020086018051610220880180516102408a0180516102608c0180518619851689188d169099528319821686188c16909652801988169092188a16909252851985161888169052911990911690911884169052610280840180516102a0860180516102c0880180516102e08a0180516103008c0180518619851689188d169099528319821686188c16909652801988169092188a16909252851985161888169052911990911690911884169052600386901b850151901c9081189091168252611a08565b61226260008284612074565b61226e60018284612074565b61227a60028284612074565b61228660038284612074565b61229260048284612074565b61229e60058284612074565b6122aa60068284612074565b6122b660078284612074565b6122c260088284612074565b6122ce60098284612074565b6122da600a8284612074565b6122e6600b8284612074565b6122f2600c8284612074565b6122fe600d8284612074565b61230a600e8284612074565b612316600f8284612074565b61232260108284612074565b61232e60118284612074565b61233a60128284612074565b61234660138284612074565b61235260148284612074565b61235e60158284612074565b61236a60168284612074565b611a0860178284612074565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83161761241c818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612481576088829003850160808582017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01536001845160001a1784538652612493565b60018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b60006124be8260a01c63ffffffff1690565b67ffffffffffffffff16905060006124dc8360801c63ffffffff1690565b63ffffffff16905060006124f68460401c63ffffffff1690565b63ffffffff16905060088310801561250c575080155b156125405760c082901b6000908152883560085283513382526016602090815260408084208a8552909152909120556125f5565b6008831015801561255e57508061255860088561306e565b93508310155b8015612572575061256f8782612ec3565b83105b156125f5576000612583828561306e565b905087612591826020612ec3565b1015801561259d575085155b156125d4576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526016602090815260408083208a845290915290209089013590555b5050505050505050565b6000612682565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff006126308360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff000061265d8360101b67ffffffffffffffff1690565b1617905060008160201c61267b8360201b67ffffffffffffffff1690565b1792915050565b6080820151602083019061269a90612606565b612606565b60408201516126a890612606565b60401b176126c061269560018460059190911b015190565b825160809190911b906126d290612606565b60c01b17179392505050565b826010810192821561270c579160200282015b8281111561270c5782518255916020019190600101906126f1565b50612718929150612734565b5090565b604051806020016040528061272f612749565b905290565b5b808211156127185760008155600101612735565b6040518061032001604052806019906020820280368337509192915050565b60006020828403121561277a57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146127a557600080fd5b919050565b600080604083850312156127bd57600080fd5b6127c683612781565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612827576128276127d4565b60405290565b6040516060810167ffffffffffffffff81118282101715612827576128276127d4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612897576128976127d4565b604052919050565b60006103208083850312156128b357600080fd5b604051602080820167ffffffffffffffff83821081831117156128d8576128d86127d4565b8160405283955087601f8801126128ee57600080fd5b6128f6612803565b948701949150818886111561290a57600080fd5b875b8681101561293257803583811681146129255760008081fd5b845292840192840161290c565b50909352509295945050505050565b60006060828403121561295357600080fd5b50919050565b60008083601f84011261296b57600080fd5b50813567ffffffffffffffff81111561298357600080fd5b6020830191508360208260051b850101111561299e57600080fd5b9250929050565b60008060008060008060008060006103e08a8c0312156129c457600080fd5b6129cd8a612781565b985060208a013597506129e38b60408c0161289f565b96506103608a013567ffffffffffffffff80821115612a0157600080fd5b612a0d8d838e01612941565b97506103808c0135915080821115612a2457600080fd5b612a308d838e01612959565b90975095506103a08c0135915080821115612a4a57600080fd5b612a568d838e01612941565b94506103c08c0135915080821115612a6d57600080fd5b50612a7a8c828d01612959565b915080935050809150509295985092959850929598565b600080600080600060a08688031215612aa957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060408385031215612adf57600080fd5b50508035926020909101359150565b60008083601f840112612b0057600080fd5b50813567ffffffffffffffff811115612b1857600080fd5b60208301915083602082850101111561299e57600080fd5b600080600080600080600060a0888a031215612b4b57600080fd5b8735965060208801359550604088013567ffffffffffffffff80821115612b7157600080fd5b612b7d8b838c01612aee565b909750955060608a0135915080821115612b9657600080fd5b50612ba38a828b01612959565b90945092505060808801358015158114612bbc57600080fd5b8091505092959891949750929550565b600080600060608486031215612be157600080fd5b612bea84612781565b95602085013595506040909401359392505050565b600080600060408486031215612c1457600080fd5b83359250602084013567ffffffffffffffff811115612c3257600080fd5b612c3e86828701612aee565b9497909650939450505050565b600080600080600060808688031215612c6357600080fd5b612c6c86612781565b945060208601359350604086013567ffffffffffffffff80821115612c9057600080fd5b612c9c89838a01612941565b94506060880135915080821115612cb257600080fd5b50612cbf88828901612959565b969995985093965092949392505050565b803563ffffffff811681146127a557600080fd5b600080600060608486031215612cf957600080fd5b83359250612d0960208501612cd0565b9150612d1760408501612cd0565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612daf57612daf612d4f565b5060010190565b600060608236031215612dc857600080fd5b612dd061282d565b823567ffffffffffffffff80821115612de857600080fd5b9084019036601f830112612dfb57600080fd5b8135602082821115612e0f57612e0f6127d4565b612e3f817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612850565b92508183523681838601011115612e5557600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b6019811015612eba57825167ffffffffffffffff16825260209283019290910190600101612e91565b50505092915050565b60008219821115612ed657612ed6612d4f565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612f1057600080fd5b83018035915067ffffffffffffffff821115612f2b57600080fd5b60200191503681900382131561299e57600080fd5b600181815b80851115612f9957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115612f7f57612f7f612d4f565b80851615612f8c57918102915b93841c9390800290612f45565b509250929050565b600082612fb05750600161305c565b81612fbd5750600061305c565b8160018114612fd35760028114612fdd57612ff9565b600191505061305c565b60ff841115612fee57612fee612d4f565b50506001821b61305c565b5060208310610133831016604e8410600b841016171561301c575081810a61305c565b6130268383612f40565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561305857613058612d4f565b0290505b92915050565b600061241c8383612fa1565b60008282101561308057613080612d4f565b500390565b600063ffffffff838116908316818110156130a2576130a2612d4f565b039392505050565b600063ffffffff8083168185168083038211156130c9576130c9612d4f565b01949350505050565b6000845160005b818110156130f357602081880181015185830152016130d9565b81811115613102576000828501525b509190910192835250602082015260400191905056fea164736f6c634300080f000a" +var PreimageOracleDeployedBin = "0x6080604052600436106101cd5760003560e01c80638dc4be11116100f7578063dd24f9bf11610095578063ec5efcbc11610064578063ec5efcbc1461065f578063f3f480d91461067f578063faf37bc7146106b2578063fef2b4ed146106c557600080fd5b8063dd24f9bf1461059f578063ddcd58de146105d2578063e03110e11461060a578063e15926111461063f57600080fd5b8063b2e67ba8116100d1578063b2e67ba814610512578063b4801e611461054a578063d18534b51461056a578063da35c6641461058a57600080fd5b80638dc4be11146104835780639d53a648146104a35780639d7e8769146104f257600080fd5b806354fd4d501161016f5780637917de1d1161013e5780637917de1d146103bf5780637ac54767146103df5780638542cf50146103ff578063882856ef1461044a57600080fd5b806354fd4d50146102dd57806361238bde146103335780636551927b1461036b5780637051472e146103a357600080fd5b80632055b36b116101ab5780632055b36b146102735780633909af5c146102885780634d52b4c9146102a857806352f0f3ad146102bd57600080fd5b8063013cf08b146101d25780630359a5631461022357806304697c7814610251575b600080fd5b3480156101de57600080fd5b506101f26101ed366004612d1c565b6106f2565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561022f57600080fd5b5061024361023e366004612d5e565b610737565b60405190815260200161021a565b34801561025d57600080fd5b5061027161026c366004612dd1565b61086f565b005b34801561027f57600080fd5b50610243601081565b34801561029457600080fd5b506102716102a3366004612ff5565b6109a5565b3480156102b457600080fd5b50610243610bfc565b3480156102c957600080fd5b506102436102d83660046130e1565b610c17565b3480156102e957600080fd5b506103266040518060400160405280600581526020017f302e312e3000000000000000000000000000000000000000000000000000000081525081565b60405161021a9190613148565b34801561033f57600080fd5b5061024361034e366004613199565b600160209081526000928352604080842090915290825290205481565b34801561037757600080fd5b50610243610386366004612d5e565b601560209081526000928352604080842090915290825290205481565b3480156103af57600080fd5b506102436703782dace9d9000081565b3480156103cb57600080fd5b506102716103da3660046131bb565b610cec565b3480156103eb57600080fd5b506102436103fa366004612d1c565b6111dc565b34801561040b57600080fd5b5061043a61041a366004613199565b600260209081526000928352604080842090915290825290205460ff1681565b604051901515815260200161021a565b34801561045657600080fd5b5061046a610465366004613257565b6111f3565b60405167ffffffffffffffff909116815260200161021a565b34801561048f57600080fd5b5061027161049e36600461328a565b61124d565b3480156104af57600080fd5b506102436104be366004612d5e565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104fe57600080fd5b5061027161050d3660046132d6565b611348565b34801561051e57600080fd5b5061024361052d366004612d5e565b601760209081526000928352604080842090915290825290205481565b34801561055657600080fd5b50610243610565366004613257565b6114ff565b34801561057657600080fd5b50610271610585366004612ff5565b611531565b34801561059657600080fd5b50601354610243565b3480156105ab57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610243565b3480156105de57600080fd5b506102436105ed366004612d5e565b601660209081526000928352604080842090915290825290205481565b34801561061657600080fd5b5061062a610625366004613199565b6118f3565b6040805192835260208301919091520161021a565b34801561064b57600080fd5b5061027161065a36600461328a565b6119e4565b34801561066b57600080fd5b5061027161067a366004613362565b611aec565b34801561068b57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610243565b6102716106c03660046133fb565b611c72565b3480156106d157600080fd5b506102436106e0366004612d1c565b60006020819052908152604090205481565b6013818154811061070257600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061077a9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610867578160011660010361080d5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107da576107da613437565b0154604080516020810192909252810184905260600160405160208183030381529060405280519060200120925061084e565b826003826010811061082157610821613437565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c908061085f81613495565b915050610785565b505092915050565b600080600080608060146030823785878260140137601480870182207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06000000000000000000000000000000000000000000000000000000000000001794506000908190889084018b5afa94503d60010191506008820189106108fc5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e88017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208c8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209b83529a81528a82209290925593845283905296909120959095555050505050565b60006109b18a8a610737565b90506109d486868360208b01356109cf6109ca8d6134cd565b611edd565b611f1d565b80156109f257506109f283838360208801356109cf6109ca8a6134cd565b610a28576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b866040013588604051602001610a3e919061359c565b6040516020818303038152906040528051906020012014610a8b576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836020013587602001356001610aa191906135da565b14610ad8576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b2088610ae686806135f2565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f7e92505050565b610b29886120d9565b836040013588604051602001610b3f919061359c565b6040516020818303038152906040528051906020012003610b8c576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610bf08a8a33612881565b50505050505050505050565b6001610c0a60106002613779565b610c149190613785565b81565b6000610c23868661293a565b9050610c308360086135da565b821180610c3d5750602083115b15610c74576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610d0557610cfe86866129e7565b9050610d3f565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610d6c57505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610ded8260601c63ffffffff1690565b63ffffffff169050333214610e2e576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e3e8260801c63ffffffff1690565b63ffffffff16600003610e7d576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e878260c01c90565b67ffffffffffffffff1615610ec8576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610f01576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f0e89898d8886612a60565b83516020850160888204881415608883061715610f33576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610fe3578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610fd8576001821615610fb85782818b0152610fd8565b8981015160009081526020938452604090209260019290921c9101610f9b565b505050608801610f40565b50505050600160106002610ff79190613779565b6110019190613785565b81111561103a576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110af61104d8360401c63ffffffff1690565b61105d9063ffffffff168a6135da565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b9150841561113c5777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b1791506110e98260801c63ffffffff1690565b63ffffffff166110ff8360401c63ffffffff1690565b63ffffffff161461113c576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061116290846010612c92565b50503360008181526018602090815260408083208e8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055928252601581528282209c82529b909b52909920989098555050505050505050565b600381601081106111ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061121b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061126b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061129857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806113705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826113f2576309bde3396000526004601cfd5b602886106114085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061152757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156115a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006115cf8260c01c90565b6115e39067ffffffffffffffff1642613785565b1161161a576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006116268b8b610737565b905061163f87878360208c01356109cf6109ca8e6134cd565b801561165d575061165d84848360208901356109cf6109ca8b6134cd565b611693576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016116a9919061359c565b60405160208183030381529060405280519060200120146116f6576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161170c91906135da565b14158061173e575060016117268360601c63ffffffff1690565b611730919061379c565b63ffffffff16856020013514155b15611775576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61178389610ae687806135f2565b61178c896120d9565b60006117978a612bb3565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f020000000000000000000000000000000000000000000000000000000000000017905060006117ee8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d815260200190815260200160002054600160008481526020019081526020016000206000838152602001908152602001600020819055506118c08460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118e48d8d81612881565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff1661197c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546119988160086135da565b6119a38560206135da565b106119c157836119b48260086135da565b6119be9190613785565b91505b506000938452600160209081526040808620948652939052919092205492909150565b604435600080600883018610611a025763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b6000611af88686610737565b9050611b1183838360208801356109cf6109ca8a6134cd565b611b47576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611b83576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b8b612cd0565b611b9981610ae687806135f2565b611ba2816120d9565b846040013581604051602001611bb8919061359c565b6040516020818303038152906040528051906020012003611c05576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611c69878733612881565b50505050505050565b6703782dace9d90000341015611cb4576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611ced576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cf88160086137c1565b63ffffffff168263ffffffff1610611d3c576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff161015611d9c576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152601560209081526040808320878452825280832080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660a09790971b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff169690961760809590951b949094179094558251808401845282815280850186815260138054600181018255908452915160029092027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0908101805473ffffffffffffffffffffffffffffffffffffffff9094167fffffffffffffffffffffffff000000000000000000000000000000000000000090941693909317909255517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015590815260168352818120938152929091529020349055565b6000816000015182602001518360400151604051602001611f00939291906137e9565b604051602081830303815290604052805190602001209050919050565b60008160005b6010811015611f71578060051b880135600186831c1660018114611f565760008481526020839052604090209350611f67565b600082815260208590526040902093505b5050600101611f23565b5090931495945050505050565b6088815114611f8c57600080fd5b602081016020830161200d565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b171717905061200781611ff2868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b61201960008383611f99565b61202560018383611f99565b61203160028383611f99565b61203d60038383611f99565b61204960048383611f99565b61205560058383611f99565b61206160068383611f99565b61206d60078383611f99565b61207960088383611f99565b61208560098383611f99565b612091600a8383611f99565b61209d600b8383611f99565b6120a9600c8383611f99565b6120b5600d8383611f99565b6120c1600e8383611f99565b6120cd600f8383611f99565b61200760108383611f99565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e00160405160208183030381529060405290506020820160208201612761565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c61228c8660011b67ffffffffffffffff1690565b18188584603f1c6122a78660011b67ffffffffffffffff1690565b18188584603f1c6122c28660011b67ffffffffffffffff1690565b181895508483603f1c6122df8560011b67ffffffffffffffff1690565b181894508387603f1c6122fc8960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611c69565b6126fb600082612674565b612706600582612674565b612711600a82612674565b61271c600f82612674565b612727601482612674565b50565b612733816121cf565b61273c816126f0565b600383901b820151815160c09190911c9061200790821867ffffffffffffffff168352565b61276d6000828461272a565b6127796001828461272a565b6127856002828461272a565b6127916003828461272a565b61279d6004828461272a565b6127a96005828461272a565b6127b56006828461272a565b6127c16007828461272a565b6127cd6008828461272a565b6127d96009828461272a565b6127e5600a828461272a565b6127f1600b828461272a565b6127fd600c828461272a565b612809600d828461272a565b612815600e828461272a565b612821600f828461272a565b61282d6010828461272a565b6128396011828461272a565b6128456012828461272a565b6128516013828461272a565b61285d6014828461272a565b6128696015828461272a565b6128756016828461272a565b6120076017828461272a565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d80600081146128fa576040519150601f19603f3d011682016040523d82523d6000602084013e6128ff565b606091505b505090508061266d576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316176129e0818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612a305760888290038501848101848103803687375060806001820353506001845160001a1784538652612a47565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612a728260a01c63ffffffff1690565b67ffffffffffffffff1690506000612a908360801c63ffffffff1690565b63ffffffff1690506000612aaa8460401c63ffffffff1690565b63ffffffff169050600883108015612ac0575080155b15612af45760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612ba9565b60088310158015612b12575080612b0c600885613785565b93508310155b8015612b265750612b2387826135da565b83105b15612ba9576000612b378285613785565b905087612b458260206135da565b10158015612b51575085155b15612b88576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612c36565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612be48360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612c118360101b67ffffffffffffffff1690565b1617905060008160201c612c2f8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612c4e90612bba565b612bba565b6040820151612c5c90612bba565b60401b17612c74612c4960018460059190911b015190565b825160809190911b90612c8690612bba565b60c01b17179392505050565b8260108101928215612cc0579160200282015b82811115612cc0578251825591602001919060010190612ca5565b50612ccc929150612ce8565b5090565b6040518060200160405280612ce3612cfd565b905290565b5b80821115612ccc5760008155600101612ce9565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612d2e57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612d5957600080fd5b919050565b60008060408385031215612d7157600080fd5b612d7a83612d35565b946020939093013593505050565b60008083601f840112612d9a57600080fd5b50813567ffffffffffffffff811115612db257600080fd5b602083019150836020828501011115612dca57600080fd5b9250929050565b60008060008060608587031215612de757600080fd5b84359350612df760208601612d35565b9250604085013567ffffffffffffffff811115612e1357600080fd5b612e1f87828801612d88565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612e7e57612e7e612e2b565b60405290565b6040516060810167ffffffffffffffff81118282101715612e7e57612e7e612e2b565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612eee57612eee612e2b565b604052919050565b6000610320808385031215612f0a57600080fd5b604051602080820167ffffffffffffffff8382108183111715612f2f57612f2f612e2b565b8160405283955087601f880112612f4557600080fd5b612f4d612e5a565b9487019491508188861115612f6157600080fd5b875b86811015612f895780358381168114612f7c5760008081fd5b8452928401928401612f63565b50909352509295945050505050565b600060608284031215612faa57600080fd5b50919050565b60008083601f840112612fc257600080fd5b50813567ffffffffffffffff811115612fda57600080fd5b6020830191508360208260051b8501011115612dca57600080fd5b60008060008060008060008060006103e08a8c03121561301457600080fd5b61301d8a612d35565b985060208a013597506130338b60408c01612ef6565b96506103608a013567ffffffffffffffff8082111561305157600080fd5b61305d8d838e01612f98565b97506103808c013591508082111561307457600080fd5b6130808d838e01612fb0565b90975095506103a08c013591508082111561309a57600080fd5b6130a68d838e01612f98565b94506103c08c01359150808211156130bd57600080fd5b506130ca8c828d01612fb0565b915080935050809150509295985092959850929598565b600080600080600060a086880312156130f957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b8381101561313757818101518382015260200161311f565b838111156120075750506000910152565b602081526000825180602084015261316781604085016020870161311c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080604083850312156131ac57600080fd5b50508035926020909101359150565b600080600080600080600060a0888a0312156131d657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156131fc57600080fd5b6132088b838c01612d88565b909750955060608a013591508082111561322157600080fd5b5061322e8a828b01612fb0565b9094509250506080880135801515811461324757600080fd5b8091505092959891949750929550565b60008060006060848603121561326c57600080fd5b61327584612d35565b95602085013595506040909401359392505050565b60008060006040848603121561329f57600080fd5b83359250602084013567ffffffffffffffff8111156132bd57600080fd5b6132c986828701612d88565b9497909650939450505050565b600080600080600080600060a0888a0312156132f157600080fd5b8735965060208801359550604088013567ffffffffffffffff8082111561331757600080fd5b6133238b838c01612d88565b909750955060608a013591508082111561333c57600080fd5b506133498a828b01612d88565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561337a57600080fd5b61338386612d35565b945060208601359350604086013567ffffffffffffffff808211156133a757600080fd5b6133b389838a01612f98565b945060608801359150808211156133c957600080fd5b506133d688828901612fb0565b969995985093965092949392505050565b803563ffffffff81168114612d5957600080fd5b60008060006060848603121561341057600080fd5b83359250613420602085016133e7565b915061342e604085016133e7565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036134c6576134c6613466565b5060010190565b6000606082360312156134df57600080fd5b6134e7612e84565b823567ffffffffffffffff808211156134ff57600080fd5b9084019036601f83011261351257600080fd5b813560208282111561352657613526612e2b565b613556817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612ea7565b9250818352368183860101111561356c57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156135d157825167ffffffffffffffff168252602092830192909101906001016135a8565b50505092915050565b600082198211156135ed576135ed613466565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261362757600080fd5b83018035915067ffffffffffffffff82111561364257600080fd5b602001915036819003821315612dca57600080fd5b600181815b808511156136b057817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561369657613696613466565b808516156136a357918102915b93841c939080029061365c565b509250929050565b6000826136c757506001613773565b816136d457506000613773565b81600181146136ea57600281146136f457613710565b6001915050613773565b60ff84111561370557613705613466565b50506001821b613773565b5060208310610133831016604e8410600b8410161715613733575081810a613773565b61373d8383613657565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561376f5761376f613466565b0290505b92915050565b60006129e083836136b8565b60008282101561379757613797613466565b500390565b600063ffffffff838116908316818110156137b9576137b9613466565b039392505050565b600063ffffffff8083168185168083038211156137e0576137e0613466565b01949350505050565b600084516137fb81846020890161311c565b9190910192835250602082015260400191905056fea164736f6c634300080f000a" func init() { diff --git a/op-bindings/bindings/registry.go b/op-bindings/bindings/registry.go index 4670c4332263..32e31e0a3f78 100644 --- a/op-bindings/bindings/registry.go +++ b/op-bindings/bindings/registry.go @@ -10,7 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" ) -// layouts respresents the set of storage layouts. It is populated in an init function. +// layouts represents the set of storage layouts. It is populated in an init function. var layouts = make(map[string]*solc.StorageLayout) // deployedBytecodes represents the set of deployed bytecodes. It is populated diff --git a/op-bindings/bindings/weth9.go b/op-bindings/bindings/weth9.go index a112611d0687..179a58ffb5f4 100644 --- a/op-bindings/bindings/weth9.go +++ b/op-bindings/bindings/weth9.go @@ -31,7 +31,7 @@ var ( // WETH9MetaData contains all meta data concerning the WETH9 contract. var WETH9MetaData = &bind.MetaData{ ABI: "[{\"type\":\"fallback\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"allowance\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"guy\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint8\",\"internalType\":\"uint8\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"deposit\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transfer\",\"inputs\":[{\"name\":\"dst\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"dst\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdraw\",\"inputs\":[{\"name\":\"wad\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"guy\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Deposit\",\"inputs\":[{\"name\":\"dst\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"dst\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Withdrawal\",\"inputs\":[{\"name\":\"src\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"wad\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false}]", - Bin: "0x60c0604052600d60808190526c2bb930b83832b21022ba3432b960991b60a090815261002e916000919061007a565b50604080518082019091526004808252630ae8aa8960e31b602090920191825261005a9160019161007a565b506002805460ff1916601217905534801561007457600080fd5b50610115565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100bb57805160ff19168380011785556100e8565b828001600101855582156100e8579182015b828111156100e85782518255916020019190600101906100cd565b506100f49291506100f8565b5090565b61011291905b808211156100f457600081556001016100fe565b90565b6107f9806101246000396000f3fe6080604052600436106100bc5760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146102cb578063d0e30db0146100bc578063dd62ed3e14610311576100bc565b8063313ce5671461024b57806370a082311461027657806395d89b41146102b6576100bc565b806318160ddd116100a557806318160ddd146101aa57806323b872dd146101d15780632e1a7d4d14610221576100bc565b806306fdde03146100c6578063095ea7b314610150575b6100c4610359565b005b3480156100d257600080fd5b506100db6103a8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101155781810151838201526020016100fd565b50505050905090810190601f1680156101425780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015c57600080fd5b506101966004803603604081101561017357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610454565b604080519115158252519081900360200190f35b3480156101b657600080fd5b506101bf6104c7565b60408051918252519081900360200190f35b3480156101dd57600080fd5b50610196600480360360608110156101f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356104cb565b34801561022d57600080fd5b506100c46004803603602081101561024457600080fd5b503561066b565b34801561025757600080fd5b50610260610700565b6040805160ff9092168252519081900360200190f35b34801561028257600080fd5b506101bf6004803603602081101561029957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610709565b3480156102c257600080fd5b506100db61071b565b3480156102d757600080fd5b50610196600480360360408110156102ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610793565b34801561031d57600080fd5b506101bf6004803603604081101561033457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166107a7565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b820191906000526020600020905b81548152906001019060200180831161042f57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156104fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610573575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105ed5773ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020548211156105b557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561068757600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156106c6573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b60006107a03384846104cb565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a72315820da81c51fd0d922de9c089035f567f35f651802d142623db49c311d681ade1c6064736f6c63430005110032", + Bin: "0x60c0604052600d60808190526c2bb930b83832b21022ba3432b960991b60a090815261002e916000919061007a565b50604080518082019091526004808252630ae8aa8960e31b602090920191825261005a9160019161007a565b506002805460ff1916601217905534801561007457600080fd5b50610115565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100bb57805160ff19168380011785556100e8565b828001600101855582156100e8579182015b828111156100e85782518255916020019190600101906100cd565b506100f49291506100f8565b5090565b61011291905b808211156100f457600081556001016100fe565b90565b6107f9806101246000396000f3fe6080604052600436106100bc5760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146102cb578063d0e30db0146100bc578063dd62ed3e14610311576100bc565b8063313ce5671461024b57806370a082311461027657806395d89b41146102b6576100bc565b806318160ddd116100a557806318160ddd146101aa57806323b872dd146101d15780632e1a7d4d14610221576100bc565b806306fdde03146100c6578063095ea7b314610150575b6100c4610359565b005b3480156100d257600080fd5b506100db6103a8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101155781810151838201526020016100fd565b50505050905090810190601f1680156101425780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015c57600080fd5b506101966004803603604081101561017357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610454565b604080519115158252519081900360200190f35b3480156101b657600080fd5b506101bf6104c7565b60408051918252519081900360200190f35b3480156101dd57600080fd5b50610196600480360360608110156101f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356104cb565b34801561022d57600080fd5b506100c46004803603602081101561024457600080fd5b503561066b565b34801561025757600080fd5b50610260610700565b6040805160ff9092168252519081900360200190f35b34801561028257600080fd5b506101bf6004803603602081101561029957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610709565b3480156102c257600080fd5b506100db61071b565b3480156102d757600080fd5b50610196600480360360408110156102ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610793565b34801561031d57600080fd5b506101bf6004803603604081101561033457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166107a7565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b820191906000526020600020905b81548152906001019060200180831161042f57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156104fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610573575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105ed5773ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020548211156105b557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561068757600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156106c6573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b60006107a03384846104cb565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a723158208cdf9e0c522e49d36150a8c7a071369551180dfcf54934aa47b2d43732920e8e64736f6c63430005110032", } // WETH9ABI is the input ABI used to generate the binding from. diff --git a/op-bindings/bindings/weth9_more.go b/op-bindings/bindings/weth9_more.go index 39d0247584cf..91efa104067d 100644 --- a/op-bindings/bindings/weth9_more.go +++ b/op-bindings/bindings/weth9_more.go @@ -13,7 +13,7 @@ const WETH9StorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src var WETH9StorageLayout = new(solc.StorageLayout) -var WETH9DeployedBin = "0x6080604052600436106100bc5760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146102cb578063d0e30db0146100bc578063dd62ed3e14610311576100bc565b8063313ce5671461024b57806370a082311461027657806395d89b41146102b6576100bc565b806318160ddd116100a557806318160ddd146101aa57806323b872dd146101d15780632e1a7d4d14610221576100bc565b806306fdde03146100c6578063095ea7b314610150575b6100c4610359565b005b3480156100d257600080fd5b506100db6103a8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101155781810151838201526020016100fd565b50505050905090810190601f1680156101425780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015c57600080fd5b506101966004803603604081101561017357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610454565b604080519115158252519081900360200190f35b3480156101b657600080fd5b506101bf6104c7565b60408051918252519081900360200190f35b3480156101dd57600080fd5b50610196600480360360608110156101f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356104cb565b34801561022d57600080fd5b506100c46004803603602081101561024457600080fd5b503561066b565b34801561025757600080fd5b50610260610700565b6040805160ff9092168252519081900360200190f35b34801561028257600080fd5b506101bf6004803603602081101561029957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610709565b3480156102c257600080fd5b506100db61071b565b3480156102d757600080fd5b50610196600480360360408110156102ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610793565b34801561031d57600080fd5b506101bf6004803603604081101561033457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166107a7565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b820191906000526020600020905b81548152906001019060200180831161042f57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156104fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610573575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105ed5773ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020548211156105b557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561068757600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156106c6573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b60006107a03384846104cb565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a72315820da81c51fd0d922de9c089035f567f35f651802d142623db49c311d681ade1c6064736f6c63430005110032" +var WETH9DeployedBin = "0x6080604052600436106100bc5760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146102cb578063d0e30db0146100bc578063dd62ed3e14610311576100bc565b8063313ce5671461024b57806370a082311461027657806395d89b41146102b6576100bc565b806318160ddd116100a557806318160ddd146101aa57806323b872dd146101d15780632e1a7d4d14610221576100bc565b806306fdde03146100c6578063095ea7b314610150575b6100c4610359565b005b3480156100d257600080fd5b506100db6103a8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101155781810151838201526020016100fd565b50505050905090810190601f1680156101425780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015c57600080fd5b506101966004803603604081101561017357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610454565b604080519115158252519081900360200190f35b3480156101b657600080fd5b506101bf6104c7565b60408051918252519081900360200190f35b3480156101dd57600080fd5b50610196600480360360608110156101f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356104cb565b34801561022d57600080fd5b506100c46004803603602081101561024457600080fd5b503561066b565b34801561025757600080fd5b50610260610700565b6040805160ff9092168252519081900360200190f35b34801561028257600080fd5b506101bf6004803603602081101561029957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610709565b3480156102c257600080fd5b506100db61071b565b3480156102d757600080fd5b50610196600480360360408110156102ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610793565b34801561031d57600080fd5b506101bf6004803603604081101561033457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166107a7565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b820191906000526020600020905b81548152906001019060200180831161042f57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156104fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610573575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105ed5773ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020548211156105b557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561068757600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156106c6573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b60006107a03384846104cb565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a723158208cdf9e0c522e49d36150a8c7a071369551180dfcf54934aa47b2d43732920e8e64736f6c63430005110032" func init() { diff --git a/op-bindings/bindingspreview/optimismportal2.go b/op-bindings/bindingspreview/optimismportal2.go new file mode 100644 index 000000000000..2afddfb9e1ea --- /dev/null +++ b/op-bindings/bindingspreview/optimismportal2.go @@ -0,0 +1,1612 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package bindingspreview + +import ( + "errors" + "math/big" + "strings" + + ethereum "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 +) + +// TypesOutputRootProof is an auto generated low-level Go binding around an user-defined struct. +type TypesOutputRootProof struct { + Version [32]byte + StateRoot [32]byte + MessagePasserStorageRoot [32]byte + LatestBlockhash [32]byte +} + +// TypesWithdrawalTransaction is an auto generated low-level Go binding around an user-defined struct. +type TypesWithdrawalTransaction struct { + Nonce *big.Int + Sender common.Address + Target common.Address + Value *big.Int + GasLimit *big.Int + Data []byte +} + +// OptimismPortal2MetaData contains all meta data concerning the OptimismPortal2 contract. +var OptimismPortal2MetaData = &bind.MetaData{ + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_proofMaturityDelaySeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_disputeGameFinalityDelaySeconds\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_initialRespectedGameType\",\"type\":\"uint32\",\"internalType\":\"GameType\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"GUARDIAN\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"SYSTEM_CONFIG\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractSystemConfig\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"blacklistDisputeGame\",\"inputs\":[{\"name\":\"_disputeGame\",\"type\":\"address\",\"internalType\":\"contractIDisputeGame\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"checkWithdrawal\",\"inputs\":[{\"name\":\"_withdrawalHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"depositTransaction\",\"inputs\":[{\"name\":\"_to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_gasLimit\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"_isCreation\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"disputeGameBlacklist\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIDisputeGame\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"disputeGameFactory\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractDisputeGameFactory\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"disputeGameFinalityDelaySeconds\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"donateETH\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"finalizeWithdrawalTransaction\",\"inputs\":[{\"name\":\"_tx\",\"type\":\"tuple\",\"internalType\":\"structTypes.WithdrawalTransaction\",\"components\":[{\"name\":\"nonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"finalizedWithdrawals\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"guardian\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_disputeGameFactory\",\"type\":\"address\",\"internalType\":\"contractDisputeGameFactory\"},{\"name\":\"_systemConfig\",\"type\":\"address\",\"internalType\":\"contractSystemConfig\"},{\"name\":\"_superchainConfig\",\"type\":\"address\",\"internalType\":\"contractSuperchainConfig\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"l2Sender\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"minimumGasLimit\",\"inputs\":[{\"name\":\"_byteCount\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"params\",\"inputs\":[],\"outputs\":[{\"name\":\"prevBaseFee\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"prevBoughtGas\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"prevBlockNum\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"paused\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proofMaturityDelaySeconds\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proveWithdrawalTransaction\",\"inputs\":[{\"name\":\"_tx\",\"type\":\"tuple\",\"internalType\":\"structTypes.WithdrawalTransaction\",\"components\":[{\"name\":\"nonce\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"sender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"target\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"gasLimit\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]},{\"name\":\"_disputeGameIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_outputRootProof\",\"type\":\"tuple\",\"internalType\":\"structTypes.OutputRootProof\",\"components\":[{\"name\":\"version\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"stateRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"messagePasserStorageRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"latestBlockhash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_withdrawalProof\",\"type\":\"bytes[]\",\"internalType\":\"bytes[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"provenWithdrawals\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"disputeGameProxy\",\"type\":\"address\",\"internalType\":\"contractIDisputeGame\"},{\"name\":\"timestamp\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"respectedGameType\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"GameType\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"respectedGameTypeUpdatedAt\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setRespectedGameType\",\"inputs\":[{\"name\":\"_gameType\",\"type\":\"uint32\",\"internalType\":\"GameType\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"superchainConfig\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractSuperchainConfig\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"systemConfig\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractSystemConfig\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TransactionDeposited\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"opaqueData\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"WithdrawalFinalized\",\"inputs\":[{\"name\":\"withdrawalHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"success\",\"type\":\"bool\",\"indexed\":false,\"internalType\":\"bool\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"WithdrawalProven\",\"inputs\":[{\"name\":\"withdrawalHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false}]", + Bin: "0x60c06040523480156200001157600080fd5b5060405162005e7938038062005e798339810160408190526200003491620002d3565b608083905260a0829052603b805463ffffffff191663ffffffff831617905562000061600080806200006a565b50505062000317565b600054610100900460ff16158080156200008b5750600054600160ff909116105b80620000bb5750620000a8306200020560201b620022f11760201c565b158015620000bb575060005460ff166001145b620001245760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000148576000805461ff0019166101001790555b603880546001600160a01b03199081166001600160a01b03878116919091179092556037805490911685831617905560358054610100600160a81b0319166101008584160217905560325416620001ae57603280546001600160a01b03191661dead1790555b620001b862000214565b8015620001ff576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054610100900460ff16620002815760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200011b565b600154600160c01b90046001600160401b0316600003620002d15760408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b02176001555b565b600080600060608486031215620002e957600080fd5b8351925060208401519150604084015163ffffffff811681146200030c57600080fd5b809150509250925092565b60805160a051615b2e6200034b6000396000818161045201526119ae01526000818161050c015261161f0152615b2e6000f3fe6080604052600436106101a55760003560e01c80638b4c40b0116100e1578063bf653a5c1161008a578063e965084c11610064578063e965084c146105f1578063e9e05c421461068d578063f0498750146106a0578063f2b4e617146106cb57600080fd5b8063bf653a5c146104fd578063c0c53b8b14610530578063cff0ab961461055057600080fd5b80639bf62d82116100bb5780639bf62d8214610480578063a14238e7146104ad578063a35d99df146104dd57600080fd5b80638b4c40b0146101ca5780638c3152e914610423578063952b27971461044357600080fd5b80634fd0434c1161014e578063724c184c11610128578063724c184c146103ae5780637af1906d146103c35780637d6be8dc146103e35780637fc485041461040357600080fd5b80634fd0434c1461030157806354fd4d50146103435780635c975abb1461039957600080fd5b8063452a93201161017f578063452a93201461028c57806345884d32146102a15780634870496f146102e157600080fd5b806333d7e2bd146101d157806335e80ab3146102285780633c9f397c1461025a57600080fd5b366101cc576101ca3334620186a06000604051806020016040528060008152506106f8565b005b600080fd5b3480156101dd57600080fd5b506037546101fe9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561023457600080fd5b506035546101fe90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561026657600080fd5b50603b546102779063ffffffff1681565b60405163ffffffff909116815260200161021f565b34801561029857600080fd5b506101fe610993565b3480156102ad57600080fd5b506102d16102bc366004614ecb565b603a6020526000908152604090205460ff1681565b604051901515815260200161021f565b3480156102ed57600080fd5b506101ca6102fc3660046150a3565b610a2b565b34801561030d57600080fd5b50603b5461032a90640100000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161021f565b34801561034f57600080fd5b5061038c6040518060400160405280600581526020017f332e332e3000000000000000000000000000000000000000000000000000000081525081565b60405161021f91906151f5565b3480156103a557600080fd5b506102d161129c565b3480156103ba57600080fd5b506101fe61132f565b3480156103cf57600080fd5b506101ca6103de366004615208565b611339565b3480156103ef57600080fd5b506101ca6103fe366004614ecb565b611b61565b34801561040f57600080fd5b506101ca61041e366004615233565b611c72565b34801561042f57600080fd5b506101ca61043e366004615250565b611da8565b34801561044f57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405190815260200161021f565b34801561048c57600080fd5b506032546101fe9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104b957600080fd5b506102d16104c8366004615208565b60336020526000908152604090205460ff1681565b3480156104e957600080fd5b5061032a6104f83660046152a3565b612085565b34801561050957600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610472565b34801561053c57600080fd5b506101ca61054b3660046152c0565b6120a4565b34801561055c57600080fd5b506001546105b8906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161021f565b3480156105fd57600080fd5b5061065861060c366004615208565b60396020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161021f565b6101ca61069b366004615319565b6106f8565b3480156106ac57600080fd5b5060375473ffffffffffffffffffffffffffffffffffffffff166101fe565b3480156106d757600080fd5b506038546101fe9073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905083156107af5773ffffffffffffffffffffffffffffffffffffffff8716156107af57604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b6107b98351612085565b67ffffffffffffffff168567ffffffffffffffff16101561085c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c000000000000000000000000000000000000000000000000000000000060648201526084016107a6565b6201d4c0835111156108ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c61726765000060448201526064016107a6565b333281146108eb575033731111000000000000000000000000000000001111015b60003488888888604051602001610906959493929190615398565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161097691906151f5565b60405180910390a4505061098a828261230d565b50505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2691906153fd565b905090565b610a3361129c565b15610a9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a207061757365640000000000000000000060448201526064016107a6565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610b59576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e74726163740060648201526084016107a6565b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa158015610bcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf1919061541a565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c67919061545c565b603b5490915060ff848116911614610d01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a20696e76616c69642067616d652074797060448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016107a6565b610d18610d1336889003880188615475565b61263a565b8114610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084016107a6565b6000610db189612696565b60008181526039602090815260409182902082518084019093525473ffffffffffffffffffffffffffffffffffffffff81168084527401000000000000000000000000000000000000000090910467ffffffffffffffff169183018290529293509091901580610ea0575060018173ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8d919061550a565b6002811115610e9e57610e9e6154db565b145b80610ed0575073ffffffffffffffffffffffffffffffffffffffff81166000908152603a602052604090205460ff165b80610f635750603b5463ffffffff1660ff16610f5d8273ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f54919061552b565b63ffffffff1690565b60ff1614155b611015576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152606060248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e2c20616e642074686560648201527f206f6c6420646973707574652067616d65206973206e6f7420696e76616c6964608482015260a4016107a6565b60408051602081018590526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506110de9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f01000000000000000000000000000000000000000000000000000000000000006020830152906110d48b8d615548565b8d604001356126c6565b61116a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f66000000000000000000000000000060648201526084016107a6565b60405180604001604052808773ffffffffffffffffffffffffffffffffffffffff1681526020014267ffffffffffffffff168152506039600086815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055509050508b6040015173ffffffffffffffffffffffffffffffffffffffff168c6020015173ffffffffffffffffffffffffffffffffffffffff16857f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6260405160405180910390a4505050505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561130b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2691906155cc565b6000610a26610993565b600081815260396020908152604080832081518083018352905473ffffffffffffffffffffffffffffffffffffffff81168083527401000000000000000000000000000000000000000090910467ffffffffffffffff1682850152808552603a90935292205460ff161561142f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652068617360448201527f206265656e20626c61636b6c697374656400000000000000000000000000000060648201526084016107a6565b816020015167ffffffffffffffff166000036114cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e20796574000000000000000000000000000060648201526084016107a6565b600061154e8273ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561151d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154191906155e9565b67ffffffffffffffff1690565b90508067ffffffffffffffff16836020015167ffffffffffffffff161161161d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4016107a6565b7f0000000000000000000000000000000000000000000000000000000000000000836020015167ffffffffffffffff16426116589190615635565b116116e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d61747572656420796574000000000000000000000060648201526084016107a6565b60028273ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611756919061550a565b6002811115611767576117676154db565b146117f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f686173206e6f74206265656e2066696e616c697a65642079657400000000000060648201526084016107a6565b603b5463ffffffff1660ff1661184e8373ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f30573d6000803e3d6000fd5b60ff16146118de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a20696e76616c69642067616d652074797060448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016107a6565b603b5467ffffffffffffffff640100000000909104811690821610156119ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652063726560448201527f61746564206265666f7265207265737065637465642067616d6520747970652060648201527f7761732075706461746564000000000000000000000000000000000000000000608482015260a4016107a6565b7f0000000000000000000000000000000000000000000000000000000000000000611a1b8373ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561151d573d6000803e3d6000fd5b611a2f9067ffffffffffffffff1642615635565b11611abc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d6761700000000000000000000000000000000000000000000060648201526084016107a6565b60008481526033602052604090205460ff1615611b5b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a6564000000000000000000000060648201526084016107a6565b50505050565b611b69610993565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4f7074696d69736d506f7274616c3a206f6e6c7920746865206775617264696160448201527f6e2063616e20626c61636b6c69737420646973707574652067616d657300000060648201526084016107a6565b73ffffffffffffffffffffffffffffffffffffffff166000908152603a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b611c7a610993565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4f7074696d69736d506f7274616c3a206f6e6c7920746865206775617264696160448201527f6e2063616e2073657420746865207265737065637465642067616d652074797060648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016107a6565b603b805463ffffffff929092167fffffffffffffffffffffffffffffffffffffffff000000000000000000000000909216919091176401000000004267ffffffffffffffff1602179055565b565b611db061129c565b15611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a207061757365640000000000000000000060448201526064016107a6565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14611ec0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e0060648201526084016107a6565b6000611ecb82612696565b9050611ed681611339565b600081815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558301516080840151606085015160a0860151611f78939291906126ea565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611fdd90841515815260200190565b60405180910390a280158015611ff35750326001145b15612080576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f640000000000000000000000000000000000000000000000000000000000000060648201526084016107a6565b505050565b600061209282601061564c565b61209e9061520861567c565b92915050565b600054610100900460ff16158080156120c45750600054600160ff909116105b806120de5750303b1580156120de575060005460ff166001145b61216a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107a6565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156121c857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff16610100858416021790556032541661228157603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b612289612748565b8015611b5b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090612343907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643615635565b9050600061234f61285b565b90506000816020015160ff16826000015163ffffffff1661237091906156d7565b905082156124a7576001546000906123a7908390700100000000000000000000000000000000900467ffffffffffffffff1661573f565b90506000836040015160ff16836123be91906157b3565b6001546123de9084906fffffffffffffffffffffffffffffffff166157b3565b6123e891906156d7565b600154909150600090612439906124129084906fffffffffffffffffffffffffffffffff1661586f565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff1661291c565b905060018611156124685761246561241282876040015160ff1660018a6124609190615635565b61293b565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548691906010906124da908490700100000000000000000000000000000000900467ffffffffffffffff1661567c565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156125bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d6974000060648201526084016107a6565b6001546000906125e9906fffffffffffffffffffffffffffffffff1667ffffffffffffffff88166158e3565b905060006125fb48633b9aca00612990565b6126059083615920565b905060005a6126149088615635565b9050808211156126305761263061262b8284615635565b6129a7565b5050505050505050565b60008160000151826020015183604001518460600151604051602001612679949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097612679979096959101615934565b6000806126d2866129d0565b90506126e081868686612a02565b9695505050505050565b60008060006126fa866000612a32565b905080612730576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff166127df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107a6565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff16600003611da65760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa1580156128f8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2691906159a1565b600061293161292b8585612a50565b83612a60565b90505b9392505050565b6000670de0b6b3a764000061297c61295385836156d7565b61296590670de0b6b3a764000061573f565b61297785670de0b6b3a76400006157b3565b612a6f565b61298690866157b3565b61293191906156d7565b6000818310156129a05781612934565b5090919050565b6000805a90505b825a6129ba9083615635565b1015612080576129c982615a5d565b91506129ae565b606081805190602001206040516020016129ec91815260200190565b6040516020818303038152906040529050919050565b6000612a2984612a13878686612aa0565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156129a05781612934565b60008183126129a05781612934565b6000612934670de0b6b3a764000083612a878661351e565b612a9191906157b3565b612a9b91906156d7565b613762565b60606000845111612b0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b6579000000000000000000000060448201526064016107a6565b6000612b18846139a1565b90506000612b2586613a8d565b9050600084604051602001612b3c91815260200190565b60405160208183030381529060405290506000805b8451811015613495576000858281518110612b6e57612b6e615a95565b602002602001015190508451831115612c09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e67746800000000000000000000000000000000000060648201526084016107a6565b82600003612cc25780518051602091820120604051612c5792612c3192910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612cbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016107a6565b612e19565b805151602011612d785780518051602091820120604051612cec92612c3192910190815260200190565b612cbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c20686173680000000000000000000000000000000000000000000000000060648201526084016107a6565b805184516020808701919091208251919092012014612e19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f652068617368000000000000000000000000000000000000000000000000000060648201526084016107a6565b612e2560106001615ac4565b816020015151036130015784518303612f9957612e5f8160200151601081518110612e5257612e52615a95565b6020026020010151613af0565b96506000875111612ef2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e636829000000000060648201526084016107a6565b60018651612f009190615635565b8214612f8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e63682900000000000060648201526084016107a6565b505050505050612934565b6000858481518110612fad57612fad615a95565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110612fd857612fd8615a95565b60200260200101519050612feb81613c50565b9550612ff8600186615ac4565b94505050613482565b6002816020015151036133fa57600061301982613c75565b905060008160008151811061303057613030615a95565b016020015160f81c90506000613047600283615adc565b613052906002615afe565b90506000613063848360ff16613c99565b905060006130718a89613c99565b9050600061307f8383613ccf565b905080835114613111576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b657900000000000060648201526084016107a6565b60ff851660021480613126575060ff85166003145b1561331557808251146131bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e64657200000060648201526084016107a6565b6131d58760200151600181518110612e5257612e52615a95565b9c5060008d5111613268576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c656166290000000000000060648201526084016107a6565b60018c516132769190615635565b8814613304576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c65616629000000000000000060648201526084016107a6565b505050505050505050505050612934565b60ff85161580613328575060ff85166001145b1561336757613354876020015160018151811061334757613347615a95565b6020026020010151613c50565b9950613360818a615ac4565b98506133ef565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e20707265666978000000000000000000000000000060648201526084016107a6565b505050505050613482565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f646500000000000000000000000000000000000000000000000060648201526084016107a6565b508061348d81615a5d565b915050612b51565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e747300000000000000000000000000000000000000000000000000000060648201526084016107a6565b6000808213613589576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016107a6565b6000606061359684613d83565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361379357506000919050565b680755bf798b4a1bf1e58212613805576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f57000000000000000000000000000000000000000060448201526064016107a6565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff8111156139bf576139bf614ee8565b604051908082528060200260200182016040528015613a0457816020015b60408051808201909152606080825260208201528152602001906001900390816139dd5790505b50915060005b81811015613a86576040518060400160405280858381518110613a2f57613a2f615a95565b60200260200101518152602001613a5e868481518110613a5157613a51615a95565b6020026020010151613e59565b815250838281518110613a7357613a73615a95565b6020908102919091010152600101613a0a565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613ae5578060011b82018184015160001a8060041c8253600f811660018301535050600101613ab7565b509295945050505050565b60606000806000613b0085613e6c565b919450925090506000816001811115613b1b57613b1b6154db565b14613ba8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d0000000000000060648201526084016107a6565b613bb28284615ac4565b855114613c41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e64657200000000000000000000000060648201526084016107a6565b612a29856020015184846148d9565b60606020826000015110613c6c57613c6782613af0565b61209e565b61209e8261496d565b606061209e613c948360200151600081518110612e5257612e52615a95565b613a8d565b606082518210613cb8575060408051602081019091526000815261209e565b6129348383848651613cca9190615635565b614983565b6000808251845110613ce2578251613ce5565b83515b90505b8082108015613d6c5750828281518110613d0457613d04615a95565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613d4357613d43615a95565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613d7c57816001019150613ce8565b5092915050565b6000808211613dee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016107a6565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606061209e613e6783614b5b565b614c44565b600080600080846000015111613f2a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016107a6565b6020840151805160001a607f8111613f4f5760006001600094509450945050506148d2565b60b7811161415d576000613f64608083615635565b90508087600001511161401f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a4016107a6565b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214158061409857507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b61414a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a4016107a6565b50600195509350600092506148d2915050565b60bf81116144ab57600061417260b783615635565b90508087600001511161422d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a4016107a6565b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361430b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a4016107a6565b600184015160088302610100031c603781116143cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a4016107a6565b6143d98184615ac4565b89511161448e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a4016107a6565b614499836001615ac4565b97509550600094506148d29350505050565b60f7811161458c5760006144c060c083615635565b90508087600001511161457b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a4016107a6565b6001955093508492506148d2915050565b600061459960f783615635565b905080876000015111614654576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a4016107a6565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a4016107a6565b600184015160088302610100031c603781116147f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a4016107a6565b6148008184615ac4565b8951116148b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a4016107a6565b6148c0836001615ac4565b97509550600194506148d29350505050565b9193909250565b60608167ffffffffffffffff8111156148f4576148f4614ee8565b6040519080825280601f01601f19166020018201604052801561491e576020820181803683370190505b50905081156129345760006149338486615ac4565b90506020820160005b8481101561495457828101518282015260200161493c565b84811115614963576000858301525b5050509392505050565b606061209e8260200151600084600001516148d9565b60608182601f0110156149f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016107a6565b828284011015614a5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016107a6565b81830184511015614acb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e647300000000000000000000000000000060448201526064016107a6565b606082158015614aea5760405191506000825260208201604052614b52565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614b23578051835260209283019201614b0b565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201526000825111614c26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016107a6565b50604080518082019091528151815260209182019181019190915290565b60606000806000614c5485613e6c565b919450925090506001816001811115614c6f57614c6f6154db565b14614cfc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d000000000000000060648201526084016107a6565b8451614d088385615ac4565b14614d95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e646572000000000000000000000000000060648201526084016107a6565b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614dac5790505093506000835b8651811015614e9a57600080614e1f6040518060400160405280858c60000151614e039190615635565b8152602001858c60200151614e189190615ac4565b9052613e6c565b509150915060405180604001604052808383614e3b9190615ac4565b8152602001848b60200151614e509190615ac4565b815250888581518110614e6557614e65615a95565b6020908102919091010152614e7b600185615ac4565b9350614e878183615ac4565b614e919084615ac4565b92505050614dd9565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614ec857600080fd5b50565b600060208284031215614edd57600080fd5b813561293481614ea6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5e57614f5e614ee8565b604052919050565b600082601f830112614f7757600080fd5b813567ffffffffffffffff811115614f9157614f91614ee8565b614fc260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f17565b818152846020838601011115614fd757600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561500657600080fd5b60405160c0810167ffffffffffffffff828210818311171561502a5761502a614ee8565b81604052829350843583526020850135915061504582614ea6565b8160208401526040850135915061505b82614ea6565b816040840152606085013560608401526080850135608084015260a085013591508082111561508957600080fd5b5061509685828601614f66565b60a0830152505092915050565b600080600080600085870360e08112156150bc57600080fd5b863567ffffffffffffffff808211156150d457600080fd5b6150e08a838b01614ff4565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561511957600080fd5b60408901955060c089013592508083111561513357600080fd5b828901925089601f84011261514757600080fd5b823591508082111561515857600080fd5b508860208260051b840101111561516e57600080fd5b959894975092955050506020019190565b60005b8381101561519a578181015183820152602001615182565b83811115611b5b5750506000910152565b600081518084526151c381602086016020860161517f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061293460208301846151ab565b60006020828403121561521a57600080fd5b5035919050565b63ffffffff81168114614ec857600080fd5b60006020828403121561524557600080fd5b813561293481615221565b60006020828403121561526257600080fd5b813567ffffffffffffffff81111561527957600080fd5b61528584828501614ff4565b949350505050565b67ffffffffffffffff81168114614ec857600080fd5b6000602082840312156152b557600080fd5b81356129348161528d565b6000806000606084860312156152d557600080fd5b83356152e081614ea6565b925060208401356152f081614ea6565b9150604084013561530081614ea6565b809150509250925092565b8015158114614ec857600080fd5b600080600080600060a0868803121561533157600080fd5b853561533c81614ea6565b94506020860135935060408601356153538161528d565b925060608601356153638161530b565b9150608086013567ffffffffffffffff81111561537f57600080fd5b61538b88828901614f66565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516153ec81604985016020870161517f565b919091016049019695505050505050565b60006020828403121561540f57600080fd5b815161293481614ea6565b60008060006060848603121561542f57600080fd5b835161543a81615221565b602085015190935061544b8161528d565b604085015190925061530081614ea6565b60006020828403121561546e57600080fd5b5051919050565b60006080828403121561548757600080fd5b6040516080810181811067ffffffffffffffff821117156154aa576154aa614ee8565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561551c57600080fd5b81516003811061293457600080fd5b60006020828403121561553d57600080fd5b815161293481615221565b600067ffffffffffffffff8084111561556357615563614ee8565b8360051b6020615574818301614f17565b86815291850191818101903684111561558c57600080fd5b865b848110156155c0578035868111156155a65760008081fd5b6155b236828b01614f66565b84525091830191830161558e565b50979650505050505050565b6000602082840312156155de57600080fd5b81516129348161530b565b6000602082840312156155fb57600080fd5b81516129348161528d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561564757615647615606565b500390565b600067ffffffffffffffff8083168185168183048111821515161561567357615673615606565b02949350505050565b600067ffffffffffffffff80831681851680830382111561569f5761569f615606565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826156e6576156e66156a8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561573a5761573a615606565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561577957615779615606565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156157ad576157ad615606565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156157f4576157f4615606565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561582f5761582f615606565b6000871292508782058712848416161561584b5761584b615606565b8785058712818416161561586157615861615606565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156158a9576158a9615606565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156158dd576158dd615606565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561591b5761591b615606565b500290565b60008261592f5761592f6156a8565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261597f60c08301846151ab565b98975050505050505050565b805160ff8116811461599c57600080fd5b919050565b600060c082840312156159b357600080fd5b60405160c0810181811067ffffffffffffffff821117156159d6576159d6614ee8565b60405282516159e481615221565b81526159f26020840161598b565b6020820152615a036040840161598b565b60408201526060830151615a1681615221565b60608201526080830151615a2981615221565b608082015260a08301516fffffffffffffffffffffffffffffffff81168114615a5157600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615a8e57615a8e615606565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008219821115615ad757615ad7615606565b500190565b600060ff831680615aef57615aef6156a8565b8060ff84160691505092915050565b600060ff821660ff841680821015615b1857615b18615606565b9003939250505056fea164736f6c634300080f000a", +} + +// OptimismPortal2ABI is the input ABI used to generate the binding from. +// Deprecated: Use OptimismPortal2MetaData.ABI instead. +var OptimismPortal2ABI = OptimismPortal2MetaData.ABI + +// OptimismPortal2Bin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use OptimismPortal2MetaData.Bin instead. +var OptimismPortal2Bin = OptimismPortal2MetaData.Bin + +// DeployOptimismPortal2 deploys a new Ethereum contract, binding an instance of OptimismPortal2 to it. +func DeployOptimismPortal2(auth *bind.TransactOpts, backend bind.ContractBackend, _proofMaturityDelaySeconds *big.Int, _disputeGameFinalityDelaySeconds *big.Int, _initialRespectedGameType uint32) (common.Address, *types.Transaction, *OptimismPortal2, error) { + parsed, err := OptimismPortal2MetaData.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(OptimismPortal2Bin), backend, _proofMaturityDelaySeconds, _disputeGameFinalityDelaySeconds, _initialRespectedGameType) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &OptimismPortal2{OptimismPortal2Caller: OptimismPortal2Caller{contract: contract}, OptimismPortal2Transactor: OptimismPortal2Transactor{contract: contract}, OptimismPortal2Filterer: OptimismPortal2Filterer{contract: contract}}, nil +} + +// OptimismPortal2 is an auto generated Go binding around an Ethereum contract. +type OptimismPortal2 struct { + OptimismPortal2Caller // Read-only binding to the contract + OptimismPortal2Transactor // Write-only binding to the contract + OptimismPortal2Filterer // Log filterer for contract events +} + +// OptimismPortal2Caller is an auto generated read-only Go binding around an Ethereum contract. +type OptimismPortal2Caller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OptimismPortal2Transactor is an auto generated write-only Go binding around an Ethereum contract. +type OptimismPortal2Transactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OptimismPortal2Filterer is an auto generated log filtering Go binding around an Ethereum contract events. +type OptimismPortal2Filterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// OptimismPortal2Session is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type OptimismPortal2Session struct { + Contract *OptimismPortal2 // 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 +} + +// OptimismPortal2CallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type OptimismPortal2CallerSession struct { + Contract *OptimismPortal2Caller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// OptimismPortal2TransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type OptimismPortal2TransactorSession struct { + Contract *OptimismPortal2Transactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// OptimismPortal2Raw is an auto generated low-level Go binding around an Ethereum contract. +type OptimismPortal2Raw struct { + Contract *OptimismPortal2 // Generic contract binding to access the raw methods on +} + +// OptimismPortal2CallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type OptimismPortal2CallerRaw struct { + Contract *OptimismPortal2Caller // Generic read-only contract binding to access the raw methods on +} + +// OptimismPortal2TransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type OptimismPortal2TransactorRaw struct { + Contract *OptimismPortal2Transactor // Generic write-only contract binding to access the raw methods on +} + +// NewOptimismPortal2 creates a new instance of OptimismPortal2, bound to a specific deployed contract. +func NewOptimismPortal2(address common.Address, backend bind.ContractBackend) (*OptimismPortal2, error) { + contract, err := bindOptimismPortal2(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &OptimismPortal2{OptimismPortal2Caller: OptimismPortal2Caller{contract: contract}, OptimismPortal2Transactor: OptimismPortal2Transactor{contract: contract}, OptimismPortal2Filterer: OptimismPortal2Filterer{contract: contract}}, nil +} + +// NewOptimismPortal2Caller creates a new read-only instance of OptimismPortal2, bound to a specific deployed contract. +func NewOptimismPortal2Caller(address common.Address, caller bind.ContractCaller) (*OptimismPortal2Caller, error) { + contract, err := bindOptimismPortal2(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &OptimismPortal2Caller{contract: contract}, nil +} + +// NewOptimismPortal2Transactor creates a new write-only instance of OptimismPortal2, bound to a specific deployed contract. +func NewOptimismPortal2Transactor(address common.Address, transactor bind.ContractTransactor) (*OptimismPortal2Transactor, error) { + contract, err := bindOptimismPortal2(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &OptimismPortal2Transactor{contract: contract}, nil +} + +// NewOptimismPortal2Filterer creates a new log filterer instance of OptimismPortal2, bound to a specific deployed contract. +func NewOptimismPortal2Filterer(address common.Address, filterer bind.ContractFilterer) (*OptimismPortal2Filterer, error) { + contract, err := bindOptimismPortal2(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &OptimismPortal2Filterer{contract: contract}, nil +} + +// bindOptimismPortal2 binds a generic wrapper to an already deployed contract. +func bindOptimismPortal2(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := abi.JSON(strings.NewReader(OptimismPortal2ABI)) + 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 (_OptimismPortal2 *OptimismPortal2Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OptimismPortal2.Contract.OptimismPortal2Caller.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 (_OptimismPortal2 *OptimismPortal2Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptimismPortal2.Contract.OptimismPortal2Transactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_OptimismPortal2 *OptimismPortal2Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OptimismPortal2.Contract.OptimismPortal2Transactor.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 (_OptimismPortal2 *OptimismPortal2CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _OptimismPortal2.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 (_OptimismPortal2 *OptimismPortal2TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptimismPortal2.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_OptimismPortal2 *OptimismPortal2TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _OptimismPortal2.Contract.contract.Transact(opts, method, params...) +} + +// GUARDIAN is a free data retrieval call binding the contract method 0x724c184c. +// +// Solidity: function GUARDIAN() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Caller) GUARDIAN(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "GUARDIAN") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GUARDIAN is a free data retrieval call binding the contract method 0x724c184c. +// +// Solidity: function GUARDIAN() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Session) GUARDIAN() (common.Address, error) { + return _OptimismPortal2.Contract.GUARDIAN(&_OptimismPortal2.CallOpts) +} + +// GUARDIAN is a free data retrieval call binding the contract method 0x724c184c. +// +// Solidity: function GUARDIAN() view returns(address) +func (_OptimismPortal2 *OptimismPortal2CallerSession) GUARDIAN() (common.Address, error) { + return _OptimismPortal2.Contract.GUARDIAN(&_OptimismPortal2.CallOpts) +} + +// SYSTEMCONFIG is a free data retrieval call binding the contract method 0xf0498750. +// +// Solidity: function SYSTEM_CONFIG() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Caller) SYSTEMCONFIG(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "SYSTEM_CONFIG") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// SYSTEMCONFIG is a free data retrieval call binding the contract method 0xf0498750. +// +// Solidity: function SYSTEM_CONFIG() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Session) SYSTEMCONFIG() (common.Address, error) { + return _OptimismPortal2.Contract.SYSTEMCONFIG(&_OptimismPortal2.CallOpts) +} + +// SYSTEMCONFIG is a free data retrieval call binding the contract method 0xf0498750. +// +// Solidity: function SYSTEM_CONFIG() view returns(address) +func (_OptimismPortal2 *OptimismPortal2CallerSession) SYSTEMCONFIG() (common.Address, error) { + return _OptimismPortal2.Contract.SYSTEMCONFIG(&_OptimismPortal2.CallOpts) +} + +// CheckWithdrawal is a free data retrieval call binding the contract method 0x7af1906d. +// +// Solidity: function checkWithdrawal(bytes32 _withdrawalHash) view returns() +func (_OptimismPortal2 *OptimismPortal2Caller) CheckWithdrawal(opts *bind.CallOpts, _withdrawalHash [32]byte) error { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "checkWithdrawal", _withdrawalHash) + + if err != nil { + return err + } + + return err + +} + +// CheckWithdrawal is a free data retrieval call binding the contract method 0x7af1906d. +// +// Solidity: function checkWithdrawal(bytes32 _withdrawalHash) view returns() +func (_OptimismPortal2 *OptimismPortal2Session) CheckWithdrawal(_withdrawalHash [32]byte) error { + return _OptimismPortal2.Contract.CheckWithdrawal(&_OptimismPortal2.CallOpts, _withdrawalHash) +} + +// CheckWithdrawal is a free data retrieval call binding the contract method 0x7af1906d. +// +// Solidity: function checkWithdrawal(bytes32 _withdrawalHash) view returns() +func (_OptimismPortal2 *OptimismPortal2CallerSession) CheckWithdrawal(_withdrawalHash [32]byte) error { + return _OptimismPortal2.Contract.CheckWithdrawal(&_OptimismPortal2.CallOpts, _withdrawalHash) +} + +// DisputeGameBlacklist is a free data retrieval call binding the contract method 0x45884d32. +// +// Solidity: function disputeGameBlacklist(address ) view returns(bool) +func (_OptimismPortal2 *OptimismPortal2Caller) DisputeGameBlacklist(opts *bind.CallOpts, arg0 common.Address) (bool, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "disputeGameBlacklist", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// DisputeGameBlacklist is a free data retrieval call binding the contract method 0x45884d32. +// +// Solidity: function disputeGameBlacklist(address ) view returns(bool) +func (_OptimismPortal2 *OptimismPortal2Session) DisputeGameBlacklist(arg0 common.Address) (bool, error) { + return _OptimismPortal2.Contract.DisputeGameBlacklist(&_OptimismPortal2.CallOpts, arg0) +} + +// DisputeGameBlacklist is a free data retrieval call binding the contract method 0x45884d32. +// +// Solidity: function disputeGameBlacklist(address ) view returns(bool) +func (_OptimismPortal2 *OptimismPortal2CallerSession) DisputeGameBlacklist(arg0 common.Address) (bool, error) { + return _OptimismPortal2.Contract.DisputeGameBlacklist(&_OptimismPortal2.CallOpts, arg0) +} + +// DisputeGameFactory is a free data retrieval call binding the contract method 0xf2b4e617. +// +// Solidity: function disputeGameFactory() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Caller) DisputeGameFactory(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "disputeGameFactory") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// DisputeGameFactory is a free data retrieval call binding the contract method 0xf2b4e617. +// +// Solidity: function disputeGameFactory() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Session) DisputeGameFactory() (common.Address, error) { + return _OptimismPortal2.Contract.DisputeGameFactory(&_OptimismPortal2.CallOpts) +} + +// DisputeGameFactory is a free data retrieval call binding the contract method 0xf2b4e617. +// +// Solidity: function disputeGameFactory() view returns(address) +func (_OptimismPortal2 *OptimismPortal2CallerSession) DisputeGameFactory() (common.Address, error) { + return _OptimismPortal2.Contract.DisputeGameFactory(&_OptimismPortal2.CallOpts) +} + +// DisputeGameFinalityDelaySeconds is a free data retrieval call binding the contract method 0x952b2797. +// +// Solidity: function disputeGameFinalityDelaySeconds() view returns(uint256) +func (_OptimismPortal2 *OptimismPortal2Caller) DisputeGameFinalityDelaySeconds(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "disputeGameFinalityDelaySeconds") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// DisputeGameFinalityDelaySeconds is a free data retrieval call binding the contract method 0x952b2797. +// +// Solidity: function disputeGameFinalityDelaySeconds() view returns(uint256) +func (_OptimismPortal2 *OptimismPortal2Session) DisputeGameFinalityDelaySeconds() (*big.Int, error) { + return _OptimismPortal2.Contract.DisputeGameFinalityDelaySeconds(&_OptimismPortal2.CallOpts) +} + +// DisputeGameFinalityDelaySeconds is a free data retrieval call binding the contract method 0x952b2797. +// +// Solidity: function disputeGameFinalityDelaySeconds() view returns(uint256) +func (_OptimismPortal2 *OptimismPortal2CallerSession) DisputeGameFinalityDelaySeconds() (*big.Int, error) { + return _OptimismPortal2.Contract.DisputeGameFinalityDelaySeconds(&_OptimismPortal2.CallOpts) +} + +// FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. +// +// Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) +func (_OptimismPortal2 *OptimismPortal2Caller) FinalizedWithdrawals(opts *bind.CallOpts, arg0 [32]byte) (bool, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "finalizedWithdrawals", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. +// +// Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) +func (_OptimismPortal2 *OptimismPortal2Session) FinalizedWithdrawals(arg0 [32]byte) (bool, error) { + return _OptimismPortal2.Contract.FinalizedWithdrawals(&_OptimismPortal2.CallOpts, arg0) +} + +// FinalizedWithdrawals is a free data retrieval call binding the contract method 0xa14238e7. +// +// Solidity: function finalizedWithdrawals(bytes32 ) view returns(bool) +func (_OptimismPortal2 *OptimismPortal2CallerSession) FinalizedWithdrawals(arg0 [32]byte) (bool, error) { + return _OptimismPortal2.Contract.FinalizedWithdrawals(&_OptimismPortal2.CallOpts, arg0) +} + +// Guardian is a free data retrieval call binding the contract method 0x452a9320. +// +// Solidity: function guardian() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Caller) Guardian(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "guardian") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Guardian is a free data retrieval call binding the contract method 0x452a9320. +// +// Solidity: function guardian() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Session) Guardian() (common.Address, error) { + return _OptimismPortal2.Contract.Guardian(&_OptimismPortal2.CallOpts) +} + +// Guardian is a free data retrieval call binding the contract method 0x452a9320. +// +// Solidity: function guardian() view returns(address) +func (_OptimismPortal2 *OptimismPortal2CallerSession) Guardian() (common.Address, error) { + return _OptimismPortal2.Contract.Guardian(&_OptimismPortal2.CallOpts) +} + +// L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. +// +// Solidity: function l2Sender() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Caller) L2Sender(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "l2Sender") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. +// +// Solidity: function l2Sender() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Session) L2Sender() (common.Address, error) { + return _OptimismPortal2.Contract.L2Sender(&_OptimismPortal2.CallOpts) +} + +// L2Sender is a free data retrieval call binding the contract method 0x9bf62d82. +// +// Solidity: function l2Sender() view returns(address) +func (_OptimismPortal2 *OptimismPortal2CallerSession) L2Sender() (common.Address, error) { + return _OptimismPortal2.Contract.L2Sender(&_OptimismPortal2.CallOpts) +} + +// MinimumGasLimit is a free data retrieval call binding the contract method 0xa35d99df. +// +// Solidity: function minimumGasLimit(uint64 _byteCount) pure returns(uint64) +func (_OptimismPortal2 *OptimismPortal2Caller) MinimumGasLimit(opts *bind.CallOpts, _byteCount uint64) (uint64, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "minimumGasLimit", _byteCount) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// MinimumGasLimit is a free data retrieval call binding the contract method 0xa35d99df. +// +// Solidity: function minimumGasLimit(uint64 _byteCount) pure returns(uint64) +func (_OptimismPortal2 *OptimismPortal2Session) MinimumGasLimit(_byteCount uint64) (uint64, error) { + return _OptimismPortal2.Contract.MinimumGasLimit(&_OptimismPortal2.CallOpts, _byteCount) +} + +// MinimumGasLimit is a free data retrieval call binding the contract method 0xa35d99df. +// +// Solidity: function minimumGasLimit(uint64 _byteCount) pure returns(uint64) +func (_OptimismPortal2 *OptimismPortal2CallerSession) MinimumGasLimit(_byteCount uint64) (uint64, error) { + return _OptimismPortal2.Contract.MinimumGasLimit(&_OptimismPortal2.CallOpts, _byteCount) +} + +// Params is a free data retrieval call binding the contract method 0xcff0ab96. +// +// Solidity: function params() view returns(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) +func (_OptimismPortal2 *OptimismPortal2Caller) Params(opts *bind.CallOpts) (struct { + PrevBaseFee *big.Int + PrevBoughtGas uint64 + PrevBlockNum uint64 +}, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "params") + + outstruct := new(struct { + PrevBaseFee *big.Int + PrevBoughtGas uint64 + PrevBlockNum uint64 + }) + if err != nil { + return *outstruct, err + } + + outstruct.PrevBaseFee = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.PrevBoughtGas = *abi.ConvertType(out[1], new(uint64)).(*uint64) + outstruct.PrevBlockNum = *abi.ConvertType(out[2], new(uint64)).(*uint64) + + return *outstruct, err + +} + +// Params is a free data retrieval call binding the contract method 0xcff0ab96. +// +// Solidity: function params() view returns(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) +func (_OptimismPortal2 *OptimismPortal2Session) Params() (struct { + PrevBaseFee *big.Int + PrevBoughtGas uint64 + PrevBlockNum uint64 +}, error) { + return _OptimismPortal2.Contract.Params(&_OptimismPortal2.CallOpts) +} + +// Params is a free data retrieval call binding the contract method 0xcff0ab96. +// +// Solidity: function params() view returns(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) +func (_OptimismPortal2 *OptimismPortal2CallerSession) Params() (struct { + PrevBaseFee *big.Int + PrevBoughtGas uint64 + PrevBlockNum uint64 +}, error) { + return _OptimismPortal2.Contract.Params(&_OptimismPortal2.CallOpts) +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_OptimismPortal2 *OptimismPortal2Caller) Paused(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "paused") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_OptimismPortal2 *OptimismPortal2Session) Paused() (bool, error) { + return _OptimismPortal2.Contract.Paused(&_OptimismPortal2.CallOpts) +} + +// Paused is a free data retrieval call binding the contract method 0x5c975abb. +// +// Solidity: function paused() view returns(bool) +func (_OptimismPortal2 *OptimismPortal2CallerSession) Paused() (bool, error) { + return _OptimismPortal2.Contract.Paused(&_OptimismPortal2.CallOpts) +} + +// ProofMaturityDelaySeconds is a free data retrieval call binding the contract method 0xbf653a5c. +// +// Solidity: function proofMaturityDelaySeconds() view returns(uint256) +func (_OptimismPortal2 *OptimismPortal2Caller) ProofMaturityDelaySeconds(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "proofMaturityDelaySeconds") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ProofMaturityDelaySeconds is a free data retrieval call binding the contract method 0xbf653a5c. +// +// Solidity: function proofMaturityDelaySeconds() view returns(uint256) +func (_OptimismPortal2 *OptimismPortal2Session) ProofMaturityDelaySeconds() (*big.Int, error) { + return _OptimismPortal2.Contract.ProofMaturityDelaySeconds(&_OptimismPortal2.CallOpts) +} + +// ProofMaturityDelaySeconds is a free data retrieval call binding the contract method 0xbf653a5c. +// +// Solidity: function proofMaturityDelaySeconds() view returns(uint256) +func (_OptimismPortal2 *OptimismPortal2CallerSession) ProofMaturityDelaySeconds() (*big.Int, error) { + return _OptimismPortal2.Contract.ProofMaturityDelaySeconds(&_OptimismPortal2.CallOpts) +} + +// ProvenWithdrawals is a free data retrieval call binding the contract method 0xe965084c. +// +// Solidity: function provenWithdrawals(bytes32 ) view returns(address disputeGameProxy, uint64 timestamp) +func (_OptimismPortal2 *OptimismPortal2Caller) ProvenWithdrawals(opts *bind.CallOpts, arg0 [32]byte) (struct { + DisputeGameProxy common.Address + Timestamp uint64 +}, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "provenWithdrawals", arg0) + + outstruct := new(struct { + DisputeGameProxy common.Address + Timestamp uint64 + }) + if err != nil { + return *outstruct, err + } + + outstruct.DisputeGameProxy = *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + outstruct.Timestamp = *abi.ConvertType(out[1], new(uint64)).(*uint64) + + return *outstruct, err + +} + +// ProvenWithdrawals is a free data retrieval call binding the contract method 0xe965084c. +// +// Solidity: function provenWithdrawals(bytes32 ) view returns(address disputeGameProxy, uint64 timestamp) +func (_OptimismPortal2 *OptimismPortal2Session) ProvenWithdrawals(arg0 [32]byte) (struct { + DisputeGameProxy common.Address + Timestamp uint64 +}, error) { + return _OptimismPortal2.Contract.ProvenWithdrawals(&_OptimismPortal2.CallOpts, arg0) +} + +// ProvenWithdrawals is a free data retrieval call binding the contract method 0xe965084c. +// +// Solidity: function provenWithdrawals(bytes32 ) view returns(address disputeGameProxy, uint64 timestamp) +func (_OptimismPortal2 *OptimismPortal2CallerSession) ProvenWithdrawals(arg0 [32]byte) (struct { + DisputeGameProxy common.Address + Timestamp uint64 +}, error) { + return _OptimismPortal2.Contract.ProvenWithdrawals(&_OptimismPortal2.CallOpts, arg0) +} + +// RespectedGameType is a free data retrieval call binding the contract method 0x3c9f397c. +// +// Solidity: function respectedGameType() view returns(uint32) +func (_OptimismPortal2 *OptimismPortal2Caller) RespectedGameType(opts *bind.CallOpts) (uint32, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "respectedGameType") + + if err != nil { + return *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) + + return out0, err + +} + +// RespectedGameType is a free data retrieval call binding the contract method 0x3c9f397c. +// +// Solidity: function respectedGameType() view returns(uint32) +func (_OptimismPortal2 *OptimismPortal2Session) RespectedGameType() (uint32, error) { + return _OptimismPortal2.Contract.RespectedGameType(&_OptimismPortal2.CallOpts) +} + +// RespectedGameType is a free data retrieval call binding the contract method 0x3c9f397c. +// +// Solidity: function respectedGameType() view returns(uint32) +func (_OptimismPortal2 *OptimismPortal2CallerSession) RespectedGameType() (uint32, error) { + return _OptimismPortal2.Contract.RespectedGameType(&_OptimismPortal2.CallOpts) +} + +// RespectedGameTypeUpdatedAt is a free data retrieval call binding the contract method 0x4fd0434c. +// +// Solidity: function respectedGameTypeUpdatedAt() view returns(uint64) +func (_OptimismPortal2 *OptimismPortal2Caller) RespectedGameTypeUpdatedAt(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "respectedGameTypeUpdatedAt") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// RespectedGameTypeUpdatedAt is a free data retrieval call binding the contract method 0x4fd0434c. +// +// Solidity: function respectedGameTypeUpdatedAt() view returns(uint64) +func (_OptimismPortal2 *OptimismPortal2Session) RespectedGameTypeUpdatedAt() (uint64, error) { + return _OptimismPortal2.Contract.RespectedGameTypeUpdatedAt(&_OptimismPortal2.CallOpts) +} + +// RespectedGameTypeUpdatedAt is a free data retrieval call binding the contract method 0x4fd0434c. +// +// Solidity: function respectedGameTypeUpdatedAt() view returns(uint64) +func (_OptimismPortal2 *OptimismPortal2CallerSession) RespectedGameTypeUpdatedAt() (uint64, error) { + return _OptimismPortal2.Contract.RespectedGameTypeUpdatedAt(&_OptimismPortal2.CallOpts) +} + +// SuperchainConfig is a free data retrieval call binding the contract method 0x35e80ab3. +// +// Solidity: function superchainConfig() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Caller) SuperchainConfig(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "superchainConfig") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// SuperchainConfig is a free data retrieval call binding the contract method 0x35e80ab3. +// +// Solidity: function superchainConfig() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Session) SuperchainConfig() (common.Address, error) { + return _OptimismPortal2.Contract.SuperchainConfig(&_OptimismPortal2.CallOpts) +} + +// SuperchainConfig is a free data retrieval call binding the contract method 0x35e80ab3. +// +// Solidity: function superchainConfig() view returns(address) +func (_OptimismPortal2 *OptimismPortal2CallerSession) SuperchainConfig() (common.Address, error) { + return _OptimismPortal2.Contract.SuperchainConfig(&_OptimismPortal2.CallOpts) +} + +// SystemConfig is a free data retrieval call binding the contract method 0x33d7e2bd. +// +// Solidity: function systemConfig() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Caller) SystemConfig(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "systemConfig") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// SystemConfig is a free data retrieval call binding the contract method 0x33d7e2bd. +// +// Solidity: function systemConfig() view returns(address) +func (_OptimismPortal2 *OptimismPortal2Session) SystemConfig() (common.Address, error) { + return _OptimismPortal2.Contract.SystemConfig(&_OptimismPortal2.CallOpts) +} + +// SystemConfig is a free data retrieval call binding the contract method 0x33d7e2bd. +// +// Solidity: function systemConfig() view returns(address) +func (_OptimismPortal2 *OptimismPortal2CallerSession) SystemConfig() (common.Address, error) { + return _OptimismPortal2.Contract.SystemConfig(&_OptimismPortal2.CallOpts) +} + +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_OptimismPortal2 *OptimismPortal2Caller) Version(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _OptimismPortal2.contract.Call(opts, &out, "version") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_OptimismPortal2 *OptimismPortal2Session) Version() (string, error) { + return _OptimismPortal2.Contract.Version(&_OptimismPortal2.CallOpts) +} + +// Version is a free data retrieval call binding the contract method 0x54fd4d50. +// +// Solidity: function version() view returns(string) +func (_OptimismPortal2 *OptimismPortal2CallerSession) Version() (string, error) { + return _OptimismPortal2.Contract.Version(&_OptimismPortal2.CallOpts) +} + +// BlacklistDisputeGame is a paid mutator transaction binding the contract method 0x7d6be8dc. +// +// Solidity: function blacklistDisputeGame(address _disputeGame) returns() +func (_OptimismPortal2 *OptimismPortal2Transactor) BlacklistDisputeGame(opts *bind.TransactOpts, _disputeGame common.Address) (*types.Transaction, error) { + return _OptimismPortal2.contract.Transact(opts, "blacklistDisputeGame", _disputeGame) +} + +// BlacklistDisputeGame is a paid mutator transaction binding the contract method 0x7d6be8dc. +// +// Solidity: function blacklistDisputeGame(address _disputeGame) returns() +func (_OptimismPortal2 *OptimismPortal2Session) BlacklistDisputeGame(_disputeGame common.Address) (*types.Transaction, error) { + return _OptimismPortal2.Contract.BlacklistDisputeGame(&_OptimismPortal2.TransactOpts, _disputeGame) +} + +// BlacklistDisputeGame is a paid mutator transaction binding the contract method 0x7d6be8dc. +// +// Solidity: function blacklistDisputeGame(address _disputeGame) returns() +func (_OptimismPortal2 *OptimismPortal2TransactorSession) BlacklistDisputeGame(_disputeGame common.Address) (*types.Transaction, error) { + return _OptimismPortal2.Contract.BlacklistDisputeGame(&_OptimismPortal2.TransactOpts, _disputeGame) +} + +// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. +// +// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_OptimismPortal2 *OptimismPortal2Transactor) DepositTransaction(opts *bind.TransactOpts, _to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _OptimismPortal2.contract.Transact(opts, "depositTransaction", _to, _value, _gasLimit, _isCreation, _data) +} + +// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. +// +// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_OptimismPortal2 *OptimismPortal2Session) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _OptimismPortal2.Contract.DepositTransaction(&_OptimismPortal2.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) +} + +// DepositTransaction is a paid mutator transaction binding the contract method 0xe9e05c42. +// +// Solidity: function depositTransaction(address _to, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data) payable returns() +func (_OptimismPortal2 *OptimismPortal2TransactorSession) DepositTransaction(_to common.Address, _value *big.Int, _gasLimit uint64, _isCreation bool, _data []byte) (*types.Transaction, error) { + return _OptimismPortal2.Contract.DepositTransaction(&_OptimismPortal2.TransactOpts, _to, _value, _gasLimit, _isCreation, _data) +} + +// DonateETH is a paid mutator transaction binding the contract method 0x8b4c40b0. +// +// Solidity: function donateETH() payable returns() +func (_OptimismPortal2 *OptimismPortal2Transactor) DonateETH(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptimismPortal2.contract.Transact(opts, "donateETH") +} + +// DonateETH is a paid mutator transaction binding the contract method 0x8b4c40b0. +// +// Solidity: function donateETH() payable returns() +func (_OptimismPortal2 *OptimismPortal2Session) DonateETH() (*types.Transaction, error) { + return _OptimismPortal2.Contract.DonateETH(&_OptimismPortal2.TransactOpts) +} + +// DonateETH is a paid mutator transaction binding the contract method 0x8b4c40b0. +// +// Solidity: function donateETH() payable returns() +func (_OptimismPortal2 *OptimismPortal2TransactorSession) DonateETH() (*types.Transaction, error) { + return _OptimismPortal2.Contract.DonateETH(&_OptimismPortal2.TransactOpts) +} + +// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0x8c3152e9. +// +// Solidity: function finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx) returns() +func (_OptimismPortal2 *OptimismPortal2Transactor) FinalizeWithdrawalTransaction(opts *bind.TransactOpts, _tx TypesWithdrawalTransaction) (*types.Transaction, error) { + return _OptimismPortal2.contract.Transact(opts, "finalizeWithdrawalTransaction", _tx) +} + +// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0x8c3152e9. +// +// Solidity: function finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx) returns() +func (_OptimismPortal2 *OptimismPortal2Session) FinalizeWithdrawalTransaction(_tx TypesWithdrawalTransaction) (*types.Transaction, error) { + return _OptimismPortal2.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal2.TransactOpts, _tx) +} + +// FinalizeWithdrawalTransaction is a paid mutator transaction binding the contract method 0x8c3152e9. +// +// Solidity: function finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx) returns() +func (_OptimismPortal2 *OptimismPortal2TransactorSession) FinalizeWithdrawalTransaction(_tx TypesWithdrawalTransaction) (*types.Transaction, error) { + return _OptimismPortal2.Contract.FinalizeWithdrawalTransaction(&_OptimismPortal2.TransactOpts, _tx) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc0c53b8b. +// +// Solidity: function initialize(address _disputeGameFactory, address _systemConfig, address _superchainConfig) returns() +func (_OptimismPortal2 *OptimismPortal2Transactor) Initialize(opts *bind.TransactOpts, _disputeGameFactory common.Address, _systemConfig common.Address, _superchainConfig common.Address) (*types.Transaction, error) { + return _OptimismPortal2.contract.Transact(opts, "initialize", _disputeGameFactory, _systemConfig, _superchainConfig) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc0c53b8b. +// +// Solidity: function initialize(address _disputeGameFactory, address _systemConfig, address _superchainConfig) returns() +func (_OptimismPortal2 *OptimismPortal2Session) Initialize(_disputeGameFactory common.Address, _systemConfig common.Address, _superchainConfig common.Address) (*types.Transaction, error) { + return _OptimismPortal2.Contract.Initialize(&_OptimismPortal2.TransactOpts, _disputeGameFactory, _systemConfig, _superchainConfig) +} + +// Initialize is a paid mutator transaction binding the contract method 0xc0c53b8b. +// +// Solidity: function initialize(address _disputeGameFactory, address _systemConfig, address _superchainConfig) returns() +func (_OptimismPortal2 *OptimismPortal2TransactorSession) Initialize(_disputeGameFactory common.Address, _systemConfig common.Address, _superchainConfig common.Address) (*types.Transaction, error) { + return _OptimismPortal2.Contract.Initialize(&_OptimismPortal2.TransactOpts, _disputeGameFactory, _systemConfig, _superchainConfig) +} + +// ProveWithdrawalTransaction is a paid mutator transaction binding the contract method 0x4870496f. +// +// Solidity: function proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx, uint256 _disputeGameIndex, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes[] _withdrawalProof) returns() +func (_OptimismPortal2 *OptimismPortal2Transactor) ProveWithdrawalTransaction(opts *bind.TransactOpts, _tx TypesWithdrawalTransaction, _disputeGameIndex *big.Int, _outputRootProof TypesOutputRootProof, _withdrawalProof [][]byte) (*types.Transaction, error) { + return _OptimismPortal2.contract.Transact(opts, "proveWithdrawalTransaction", _tx, _disputeGameIndex, _outputRootProof, _withdrawalProof) +} + +// ProveWithdrawalTransaction is a paid mutator transaction binding the contract method 0x4870496f. +// +// Solidity: function proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx, uint256 _disputeGameIndex, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes[] _withdrawalProof) returns() +func (_OptimismPortal2 *OptimismPortal2Session) ProveWithdrawalTransaction(_tx TypesWithdrawalTransaction, _disputeGameIndex *big.Int, _outputRootProof TypesOutputRootProof, _withdrawalProof [][]byte) (*types.Transaction, error) { + return _OptimismPortal2.Contract.ProveWithdrawalTransaction(&_OptimismPortal2.TransactOpts, _tx, _disputeGameIndex, _outputRootProof, _withdrawalProof) +} + +// ProveWithdrawalTransaction is a paid mutator transaction binding the contract method 0x4870496f. +// +// Solidity: function proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes) _tx, uint256 _disputeGameIndex, (bytes32,bytes32,bytes32,bytes32) _outputRootProof, bytes[] _withdrawalProof) returns() +func (_OptimismPortal2 *OptimismPortal2TransactorSession) ProveWithdrawalTransaction(_tx TypesWithdrawalTransaction, _disputeGameIndex *big.Int, _outputRootProof TypesOutputRootProof, _withdrawalProof [][]byte) (*types.Transaction, error) { + return _OptimismPortal2.Contract.ProveWithdrawalTransaction(&_OptimismPortal2.TransactOpts, _tx, _disputeGameIndex, _outputRootProof, _withdrawalProof) +} + +// SetRespectedGameType is a paid mutator transaction binding the contract method 0x7fc48504. +// +// Solidity: function setRespectedGameType(uint32 _gameType) returns() +func (_OptimismPortal2 *OptimismPortal2Transactor) SetRespectedGameType(opts *bind.TransactOpts, _gameType uint32) (*types.Transaction, error) { + return _OptimismPortal2.contract.Transact(opts, "setRespectedGameType", _gameType) +} + +// SetRespectedGameType is a paid mutator transaction binding the contract method 0x7fc48504. +// +// Solidity: function setRespectedGameType(uint32 _gameType) returns() +func (_OptimismPortal2 *OptimismPortal2Session) SetRespectedGameType(_gameType uint32) (*types.Transaction, error) { + return _OptimismPortal2.Contract.SetRespectedGameType(&_OptimismPortal2.TransactOpts, _gameType) +} + +// SetRespectedGameType is a paid mutator transaction binding the contract method 0x7fc48504. +// +// Solidity: function setRespectedGameType(uint32 _gameType) returns() +func (_OptimismPortal2 *OptimismPortal2TransactorSession) SetRespectedGameType(_gameType uint32) (*types.Transaction, error) { + return _OptimismPortal2.Contract.SetRespectedGameType(&_OptimismPortal2.TransactOpts, _gameType) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_OptimismPortal2 *OptimismPortal2Transactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _OptimismPortal2.contract.RawTransact(opts, nil) // calldata is disallowed for receive function +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_OptimismPortal2 *OptimismPortal2Session) Receive() (*types.Transaction, error) { + return _OptimismPortal2.Contract.Receive(&_OptimismPortal2.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_OptimismPortal2 *OptimismPortal2TransactorSession) Receive() (*types.Transaction, error) { + return _OptimismPortal2.Contract.Receive(&_OptimismPortal2.TransactOpts) +} + +// OptimismPortal2InitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the OptimismPortal2 contract. +type OptimismPortal2InitializedIterator struct { + Event *OptimismPortal2Initialized // 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 *OptimismPortal2InitializedIterator) 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(OptimismPortal2Initialized) + 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(OptimismPortal2Initialized) + 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 *OptimismPortal2InitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *OptimismPortal2InitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// OptimismPortal2Initialized represents a Initialized event raised by the OptimismPortal2 contract. +type OptimismPortal2Initialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_OptimismPortal2 *OptimismPortal2Filterer) FilterInitialized(opts *bind.FilterOpts) (*OptimismPortal2InitializedIterator, error) { + + logs, sub, err := _OptimismPortal2.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &OptimismPortal2InitializedIterator{contract: _OptimismPortal2.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_OptimismPortal2 *OptimismPortal2Filterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *OptimismPortal2Initialized) (event.Subscription, error) { + + logs, sub, err := _OptimismPortal2.contract.WatchLogs(opts, "Initialized") + 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(OptimismPortal2Initialized) + if err := _OptimismPortal2.contract.UnpackLog(event, "Initialized", 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 +} + +// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_OptimismPortal2 *OptimismPortal2Filterer) ParseInitialized(log types.Log) (*OptimismPortal2Initialized, error) { + event := new(OptimismPortal2Initialized) + if err := _OptimismPortal2.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// OptimismPortal2TransactionDepositedIterator is returned from FilterTransactionDeposited and is used to iterate over the raw logs and unpacked data for TransactionDeposited events raised by the OptimismPortal2 contract. +type OptimismPortal2TransactionDepositedIterator struct { + Event *OptimismPortal2TransactionDeposited // 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 *OptimismPortal2TransactionDepositedIterator) 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(OptimismPortal2TransactionDeposited) + 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(OptimismPortal2TransactionDeposited) + 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 *OptimismPortal2TransactionDepositedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *OptimismPortal2TransactionDepositedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// OptimismPortal2TransactionDeposited represents a TransactionDeposited event raised by the OptimismPortal2 contract. +type OptimismPortal2TransactionDeposited struct { + From common.Address + To common.Address + Version *big.Int + OpaqueData []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransactionDeposited is a free log retrieval operation binding the contract event 0xb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32. +// +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData) +func (_OptimismPortal2 *OptimismPortal2Filterer) FilterTransactionDeposited(opts *bind.FilterOpts, from []common.Address, to []common.Address, version []*big.Int) (*OptimismPortal2TransactionDepositedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + var versionRule []interface{} + for _, versionItem := range version { + versionRule = append(versionRule, versionItem) + } + + logs, sub, err := _OptimismPortal2.contract.FilterLogs(opts, "TransactionDeposited", fromRule, toRule, versionRule) + if err != nil { + return nil, err + } + return &OptimismPortal2TransactionDepositedIterator{contract: _OptimismPortal2.contract, event: "TransactionDeposited", logs: logs, sub: sub}, nil +} + +// WatchTransactionDeposited is a free log subscription operation binding the contract event 0xb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32. +// +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData) +func (_OptimismPortal2 *OptimismPortal2Filterer) WatchTransactionDeposited(opts *bind.WatchOpts, sink chan<- *OptimismPortal2TransactionDeposited, from []common.Address, to []common.Address, version []*big.Int) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + var versionRule []interface{} + for _, versionItem := range version { + versionRule = append(versionRule, versionItem) + } + + logs, sub, err := _OptimismPortal2.contract.WatchLogs(opts, "TransactionDeposited", fromRule, toRule, versionRule) + 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(OptimismPortal2TransactionDeposited) + if err := _OptimismPortal2.contract.UnpackLog(event, "TransactionDeposited", 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 +} + +// ParseTransactionDeposited is a log parse operation binding the contract event 0xb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32. +// +// Solidity: event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData) +func (_OptimismPortal2 *OptimismPortal2Filterer) ParseTransactionDeposited(log types.Log) (*OptimismPortal2TransactionDeposited, error) { + event := new(OptimismPortal2TransactionDeposited) + if err := _OptimismPortal2.contract.UnpackLog(event, "TransactionDeposited", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// OptimismPortal2WithdrawalFinalizedIterator is returned from FilterWithdrawalFinalized and is used to iterate over the raw logs and unpacked data for WithdrawalFinalized events raised by the OptimismPortal2 contract. +type OptimismPortal2WithdrawalFinalizedIterator struct { + Event *OptimismPortal2WithdrawalFinalized // 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 *OptimismPortal2WithdrawalFinalizedIterator) 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(OptimismPortal2WithdrawalFinalized) + 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(OptimismPortal2WithdrawalFinalized) + 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 *OptimismPortal2WithdrawalFinalizedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *OptimismPortal2WithdrawalFinalizedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// OptimismPortal2WithdrawalFinalized represents a WithdrawalFinalized event raised by the OptimismPortal2 contract. +type OptimismPortal2WithdrawalFinalized struct { + WithdrawalHash [32]byte + Success bool + Raw types.Log // Blockchain specific contextual infos +} + +// FilterWithdrawalFinalized is a free log retrieval operation binding the contract event 0xdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b. +// +// Solidity: event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success) +func (_OptimismPortal2 *OptimismPortal2Filterer) FilterWithdrawalFinalized(opts *bind.FilterOpts, withdrawalHash [][32]byte) (*OptimismPortal2WithdrawalFinalizedIterator, error) { + + var withdrawalHashRule []interface{} + for _, withdrawalHashItem := range withdrawalHash { + withdrawalHashRule = append(withdrawalHashRule, withdrawalHashItem) + } + + logs, sub, err := _OptimismPortal2.contract.FilterLogs(opts, "WithdrawalFinalized", withdrawalHashRule) + if err != nil { + return nil, err + } + return &OptimismPortal2WithdrawalFinalizedIterator{contract: _OptimismPortal2.contract, event: "WithdrawalFinalized", logs: logs, sub: sub}, nil +} + +// WatchWithdrawalFinalized is a free log subscription operation binding the contract event 0xdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b. +// +// Solidity: event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success) +func (_OptimismPortal2 *OptimismPortal2Filterer) WatchWithdrawalFinalized(opts *bind.WatchOpts, sink chan<- *OptimismPortal2WithdrawalFinalized, withdrawalHash [][32]byte) (event.Subscription, error) { + + var withdrawalHashRule []interface{} + for _, withdrawalHashItem := range withdrawalHash { + withdrawalHashRule = append(withdrawalHashRule, withdrawalHashItem) + } + + logs, sub, err := _OptimismPortal2.contract.WatchLogs(opts, "WithdrawalFinalized", withdrawalHashRule) + 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(OptimismPortal2WithdrawalFinalized) + if err := _OptimismPortal2.contract.UnpackLog(event, "WithdrawalFinalized", 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 +} + +// ParseWithdrawalFinalized is a log parse operation binding the contract event 0xdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b. +// +// Solidity: event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success) +func (_OptimismPortal2 *OptimismPortal2Filterer) ParseWithdrawalFinalized(log types.Log) (*OptimismPortal2WithdrawalFinalized, error) { + event := new(OptimismPortal2WithdrawalFinalized) + if err := _OptimismPortal2.contract.UnpackLog(event, "WithdrawalFinalized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// OptimismPortal2WithdrawalProvenIterator is returned from FilterWithdrawalProven and is used to iterate over the raw logs and unpacked data for WithdrawalProven events raised by the OptimismPortal2 contract. +type OptimismPortal2WithdrawalProvenIterator struct { + Event *OptimismPortal2WithdrawalProven // 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 *OptimismPortal2WithdrawalProvenIterator) 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(OptimismPortal2WithdrawalProven) + 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(OptimismPortal2WithdrawalProven) + 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 *OptimismPortal2WithdrawalProvenIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *OptimismPortal2WithdrawalProvenIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// OptimismPortal2WithdrawalProven represents a WithdrawalProven event raised by the OptimismPortal2 contract. +type OptimismPortal2WithdrawalProven struct { + WithdrawalHash [32]byte + From common.Address + To common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterWithdrawalProven is a free log retrieval operation binding the contract event 0x67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f62. +// +// Solidity: event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to) +func (_OptimismPortal2 *OptimismPortal2Filterer) FilterWithdrawalProven(opts *bind.FilterOpts, withdrawalHash [][32]byte, from []common.Address, to []common.Address) (*OptimismPortal2WithdrawalProvenIterator, error) { + + var withdrawalHashRule []interface{} + for _, withdrawalHashItem := range withdrawalHash { + withdrawalHashRule = append(withdrawalHashRule, withdrawalHashItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _OptimismPortal2.contract.FilterLogs(opts, "WithdrawalProven", withdrawalHashRule, fromRule, toRule) + if err != nil { + return nil, err + } + return &OptimismPortal2WithdrawalProvenIterator{contract: _OptimismPortal2.contract, event: "WithdrawalProven", logs: logs, sub: sub}, nil +} + +// WatchWithdrawalProven is a free log subscription operation binding the contract event 0x67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f62. +// +// Solidity: event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to) +func (_OptimismPortal2 *OptimismPortal2Filterer) WatchWithdrawalProven(opts *bind.WatchOpts, sink chan<- *OptimismPortal2WithdrawalProven, withdrawalHash [][32]byte, from []common.Address, to []common.Address) (event.Subscription, error) { + + var withdrawalHashRule []interface{} + for _, withdrawalHashItem := range withdrawalHash { + withdrawalHashRule = append(withdrawalHashRule, withdrawalHashItem) + } + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _OptimismPortal2.contract.WatchLogs(opts, "WithdrawalProven", withdrawalHashRule, fromRule, toRule) + 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(OptimismPortal2WithdrawalProven) + if err := _OptimismPortal2.contract.UnpackLog(event, "WithdrawalProven", 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 +} + +// ParseWithdrawalProven is a log parse operation binding the contract event 0x67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f62. +// +// Solidity: event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to) +func (_OptimismPortal2 *OptimismPortal2Filterer) ParseWithdrawalProven(log types.Log) (*OptimismPortal2WithdrawalProven, error) { + event := new(OptimismPortal2WithdrawalProven) + if err := _OptimismPortal2.contract.UnpackLog(event, "WithdrawalProven", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/op-bindings/bindingspreview/optimismportal2_more.go b/op-bindings/bindingspreview/optimismportal2_more.go new file mode 100644 index 000000000000..e3116244ee04 --- /dev/null +++ b/op-bindings/bindingspreview/optimismportal2_more.go @@ -0,0 +1,27 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package bindingspreview + +import ( + "encoding/json" + + "github.com/ethereum-optimism/optimism/op-bindings/solc" +) + +const OptimismPortal2StorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1002,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"params\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_struct(ResourceParams)1021_storage\"},{\"astId\":1003,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_array(t_uint256)48_storage\"},{\"astId\":1004,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"l2Sender\",\"offset\":0,\"slot\":\"50\",\"type\":\"t_address\"},{\"astId\":1005,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"finalizedWithdrawals\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":1006,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"spacer_52_0_32\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_bytes32\"},{\"astId\":1007,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"spacer_53_0_1\",\"offset\":0,\"slot\":\"53\",\"type\":\"t_bool\"},{\"astId\":1008,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"superchainConfig\",\"offset\":1,\"slot\":\"53\",\"type\":\"t_contract(SuperchainConfig)1018\"},{\"astId\":1009,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"spacer_54_0_20\",\"offset\":0,\"slot\":\"54\",\"type\":\"t_address\"},{\"astId\":1010,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"systemConfig\",\"offset\":0,\"slot\":\"55\",\"type\":\"t_contract(SystemConfig)1019\"},{\"astId\":1011,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"disputeGameFactory\",\"offset\":0,\"slot\":\"56\",\"type\":\"t_contract(DisputeGameFactory)1016\"},{\"astId\":1012,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"provenWithdrawals\",\"offset\":0,\"slot\":\"57\",\"type\":\"t_mapping(t_bytes32,t_struct(ProvenWithdrawal)1020_storage)\"},{\"astId\":1013,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"disputeGameBlacklist\",\"offset\":0,\"slot\":\"58\",\"type\":\"t_mapping(t_contract(IDisputeGame)1017,t_bool)\"},{\"astId\":1014,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"respectedGameType\",\"offset\":0,\"slot\":\"59\",\"type\":\"t_userDefinedValueType(GameType)1022\"},{\"astId\":1015,\"contract\":\"src/L1/OptimismPortal2.sol:OptimismPortal2\",\"label\":\"respectedGameTypeUpdatedAt\",\"offset\":4,\"slot\":\"59\",\"type\":\"t_uint64\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)48_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[48]\",\"numberOfBytes\":\"1536\",\"base\":\"t_uint256\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_contract(DisputeGameFactory)1016\":{\"encoding\":\"inplace\",\"label\":\"contract DisputeGameFactory\",\"numberOfBytes\":\"20\"},\"t_contract(IDisputeGame)1017\":{\"encoding\":\"inplace\",\"label\":\"contract IDisputeGame\",\"numberOfBytes\":\"20\"},\"t_contract(SuperchainConfig)1018\":{\"encoding\":\"inplace\",\"label\":\"contract SuperchainConfig\",\"numberOfBytes\":\"20\"},\"t_contract(SystemConfig)1019\":{\"encoding\":\"inplace\",\"label\":\"contract SystemConfig\",\"numberOfBytes\":\"20\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_mapping(t_bytes32,t_struct(ProvenWithdrawal)1020_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e struct OptimismPortal2.ProvenWithdrawal)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_struct(ProvenWithdrawal)1020_storage\"},\"t_mapping(t_contract(IDisputeGame)1017,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(contract IDisputeGame =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_contract(IDisputeGame)1017\",\"value\":\"t_bool\"},\"t_struct(ProvenWithdrawal)1020_storage\":{\"encoding\":\"inplace\",\"label\":\"struct OptimismPortal2.ProvenWithdrawal\",\"numberOfBytes\":\"32\"},\"t_struct(ResourceParams)1021_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\"},\"t_userDefinedValueType(GameType)1022\":{\"encoding\":\"inplace\",\"label\":\"GameType\",\"numberOfBytes\":\"4\"}}}" + +var OptimismPortal2StorageLayout = new(solc.StorageLayout) + +var OptimismPortal2DeployedBin = "0x6080604052600436106101a55760003560e01c80638b4c40b0116100e1578063bf653a5c1161008a578063e965084c11610064578063e965084c146105f1578063e9e05c421461068d578063f0498750146106a0578063f2b4e617146106cb57600080fd5b8063bf653a5c146104fd578063c0c53b8b14610530578063cff0ab961461055057600080fd5b80639bf62d82116100bb5780639bf62d8214610480578063a14238e7146104ad578063a35d99df146104dd57600080fd5b80638b4c40b0146101ca5780638c3152e914610423578063952b27971461044357600080fd5b80634fd0434c1161014e578063724c184c11610128578063724c184c146103ae5780637af1906d146103c35780637d6be8dc146103e35780637fc485041461040357600080fd5b80634fd0434c1461030157806354fd4d50146103435780635c975abb1461039957600080fd5b8063452a93201161017f578063452a93201461028c57806345884d32146102a15780634870496f146102e157600080fd5b806333d7e2bd146101d157806335e80ab3146102285780633c9f397c1461025a57600080fd5b366101cc576101ca3334620186a06000604051806020016040528060008152506106f8565b005b600080fd5b3480156101dd57600080fd5b506037546101fe9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561023457600080fd5b506035546101fe90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561026657600080fd5b50603b546102779063ffffffff1681565b60405163ffffffff909116815260200161021f565b34801561029857600080fd5b506101fe610993565b3480156102ad57600080fd5b506102d16102bc366004614ecb565b603a6020526000908152604090205460ff1681565b604051901515815260200161021f565b3480156102ed57600080fd5b506101ca6102fc3660046150a3565b610a2b565b34801561030d57600080fd5b50603b5461032a90640100000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161021f565b34801561034f57600080fd5b5061038c6040518060400160405280600581526020017f332e332e3000000000000000000000000000000000000000000000000000000081525081565b60405161021f91906151f5565b3480156103a557600080fd5b506102d161129c565b3480156103ba57600080fd5b506101fe61132f565b3480156103cf57600080fd5b506101ca6103de366004615208565b611339565b3480156103ef57600080fd5b506101ca6103fe366004614ecb565b611b61565b34801561040f57600080fd5b506101ca61041e366004615233565b611c72565b34801561042f57600080fd5b506101ca61043e366004615250565b611da8565b34801561044f57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405190815260200161021f565b34801561048c57600080fd5b506032546101fe9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104b957600080fd5b506102d16104c8366004615208565b60336020526000908152604090205460ff1681565b3480156104e957600080fd5b5061032a6104f83660046152a3565b612085565b34801561050957600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610472565b34801561053c57600080fd5b506101ca61054b3660046152c0565b6120a4565b34801561055c57600080fd5b506001546105b8906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161021f565b3480156105fd57600080fd5b5061065861060c366004615208565b60396020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161021f565b6101ca61069b366004615319565b6106f8565b3480156106ac57600080fd5b5060375473ffffffffffffffffffffffffffffffffffffffff166101fe565b3480156106d757600080fd5b506038546101fe9073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905083156107af5773ffffffffffffffffffffffffffffffffffffffff8716156107af57604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b6107b98351612085565b67ffffffffffffffff168567ffffffffffffffff16101561085c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c000000000000000000000000000000000000000000000000000000000060648201526084016107a6565b6201d4c0835111156108ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c61726765000060448201526064016107a6565b333281146108eb575033731111000000000000000000000000000000001111015b60003488888888604051602001610906959493929190615398565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161097691906151f5565b60405180910390a4505061098a828261230d565b50505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2691906153fd565b905090565b610a3361129c565b15610a9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a207061757365640000000000000000000060448201526064016107a6565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610b59576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e74726163740060648201526084016107a6565b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa158015610bcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf1919061541a565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c67919061545c565b603b5490915060ff848116911614610d01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a20696e76616c69642067616d652074797060448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016107a6565b610d18610d1336889003880188615475565b61263a565b8114610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084016107a6565b6000610db189612696565b60008181526039602090815260409182902082518084019093525473ffffffffffffffffffffffffffffffffffffffff81168084527401000000000000000000000000000000000000000090910467ffffffffffffffff169183018290529293509091901580610ea0575060018173ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8d919061550a565b6002811115610e9e57610e9e6154db565b145b80610ed0575073ffffffffffffffffffffffffffffffffffffffff81166000908152603a602052604090205460ff165b80610f635750603b5463ffffffff1660ff16610f5d8273ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f54919061552b565b63ffffffff1690565b60ff1614155b611015576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152606060248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e2c20616e642074686560648201527f206f6c6420646973707574652067616d65206973206e6f7420696e76616c6964608482015260a4016107a6565b60408051602081018590526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506110de9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f01000000000000000000000000000000000000000000000000000000000000006020830152906110d48b8d615548565b8d604001356126c6565b61116a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f66000000000000000000000000000060648201526084016107a6565b60405180604001604052808773ffffffffffffffffffffffffffffffffffffffff1681526020014267ffffffffffffffff168152506039600086815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055509050508b6040015173ffffffffffffffffffffffffffffffffffffffff168c6020015173ffffffffffffffffffffffffffffffffffffffff16857f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6260405160405180910390a4505050505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561130b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2691906155cc565b6000610a26610993565b600081815260396020908152604080832081518083018352905473ffffffffffffffffffffffffffffffffffffffff81168083527401000000000000000000000000000000000000000090910467ffffffffffffffff1682850152808552603a90935292205460ff161561142f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652068617360448201527f206265656e20626c61636b6c697374656400000000000000000000000000000060648201526084016107a6565b816020015167ffffffffffffffff166000036114cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e20796574000000000000000000000000000060648201526084016107a6565b600061154e8273ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561151d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061154191906155e9565b67ffffffffffffffff1690565b90508067ffffffffffffffff16836020015167ffffffffffffffff161161161d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4016107a6565b7f0000000000000000000000000000000000000000000000000000000000000000836020015167ffffffffffffffff16426116589190615635565b116116e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d61747572656420796574000000000000000000000060648201526084016107a6565b60028273ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611756919061550a565b6002811115611767576117676154db565b146117f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f686173206e6f74206265656e2066696e616c697a65642079657400000000000060648201526084016107a6565b603b5463ffffffff1660ff1661184e8373ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f30573d6000803e3d6000fd5b60ff16146118de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a20696e76616c69642067616d652074797060448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016107a6565b603b5467ffffffffffffffff640100000000909104811690821610156119ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652063726560448201527f61746564206265666f7265207265737065637465642067616d6520747970652060648201527f7761732075706461746564000000000000000000000000000000000000000000608482015260a4016107a6565b7f0000000000000000000000000000000000000000000000000000000000000000611a1b8373ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561151d573d6000803e3d6000fd5b611a2f9067ffffffffffffffff1642615635565b11611abc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d6761700000000000000000000000000000000000000000000060648201526084016107a6565b60008481526033602052604090205460ff1615611b5b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a6564000000000000000000000060648201526084016107a6565b50505050565b611b69610993565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4f7074696d69736d506f7274616c3a206f6e6c7920746865206775617264696160448201527f6e2063616e20626c61636b6c69737420646973707574652067616d657300000060648201526084016107a6565b73ffffffffffffffffffffffffffffffffffffffff166000908152603a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b611c7a610993565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4f7074696d69736d506f7274616c3a206f6e6c7920746865206775617264696160448201527f6e2063616e2073657420746865207265737065637465642067616d652074797060648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016107a6565b603b805463ffffffff929092167fffffffffffffffffffffffffffffffffffffffff000000000000000000000000909216919091176401000000004267ffffffffffffffff1602179055565b565b611db061129c565b15611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a207061757365640000000000000000000060448201526064016107a6565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14611ec0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e0060648201526084016107a6565b6000611ecb82612696565b9050611ed681611339565b600081815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558301516080840151606085015160a0860151611f78939291906126ea565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915082907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611fdd90841515815260200190565b60405180910390a280158015611ff35750326001145b15612080576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f640000000000000000000000000000000000000000000000000000000000000060648201526084016107a6565b505050565b600061209282601061564c565b61209e9061520861567c565b92915050565b600054610100900460ff16158080156120c45750600054600160ff909116105b806120de5750303b1580156120de575060005460ff166001145b61216a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107a6565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156121c857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff16610100858416021790556032541661228157603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b612289612748565b8015611b5b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090612343907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643615635565b9050600061234f61285b565b90506000816020015160ff16826000015163ffffffff1661237091906156d7565b905082156124a7576001546000906123a7908390700100000000000000000000000000000000900467ffffffffffffffff1661573f565b90506000836040015160ff16836123be91906157b3565b6001546123de9084906fffffffffffffffffffffffffffffffff166157b3565b6123e891906156d7565b600154909150600090612439906124129084906fffffffffffffffffffffffffffffffff1661586f565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff1661291c565b905060018611156124685761246561241282876040015160ff1660018a6124609190615635565b61293b565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548691906010906124da908490700100000000000000000000000000000000900467ffffffffffffffff1661567c565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156125bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d6974000060648201526084016107a6565b6001546000906125e9906fffffffffffffffffffffffffffffffff1667ffffffffffffffff88166158e3565b905060006125fb48633b9aca00612990565b6126059083615920565b905060005a6126149088615635565b9050808211156126305761263061262b8284615635565b6129a7565b5050505050505050565b60008160000151826020015183604001518460600151604051602001612679949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097612679979096959101615934565b6000806126d2866129d0565b90506126e081868686612a02565b9695505050505050565b60008060006126fa866000612a32565b905080612730576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff166127df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107a6565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff16600003611da65760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa1580156128f8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2691906159a1565b600061293161292b8585612a50565b83612a60565b90505b9392505050565b6000670de0b6b3a764000061297c61295385836156d7565b61296590670de0b6b3a764000061573f565b61297785670de0b6b3a76400006157b3565b612a6f565b61298690866157b3565b61293191906156d7565b6000818310156129a05781612934565b5090919050565b6000805a90505b825a6129ba9083615635565b1015612080576129c982615a5d565b91506129ae565b606081805190602001206040516020016129ec91815260200190565b6040516020818303038152906040529050919050565b6000612a2984612a13878686612aa0565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156129a05781612934565b60008183126129a05781612934565b6000612934670de0b6b3a764000083612a878661351e565b612a9191906157b3565b612a9b91906156d7565b613762565b60606000845111612b0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b6579000000000000000000000060448201526064016107a6565b6000612b18846139a1565b90506000612b2586613a8d565b9050600084604051602001612b3c91815260200190565b60405160208183030381529060405290506000805b8451811015613495576000858281518110612b6e57612b6e615a95565b602002602001015190508451831115612c09576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e67746800000000000000000000000000000000000060648201526084016107a6565b82600003612cc25780518051602091820120604051612c5792612c3192910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612cbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f74206861736800000060448201526064016107a6565b612e19565b805151602011612d785780518051602091820120604051612cec92612c3192910190815260200190565b612cbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c20686173680000000000000000000000000000000000000000000000000060648201526084016107a6565b805184516020808701919091208251919092012014612e19576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f652068617368000000000000000000000000000000000000000000000000000060648201526084016107a6565b612e2560106001615ac4565b816020015151036130015784518303612f9957612e5f8160200151601081518110612e5257612e52615a95565b6020026020010151613af0565b96506000875111612ef2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e636829000000000060648201526084016107a6565b60018651612f009190615635565b8214612f8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e63682900000000000060648201526084016107a6565b505050505050612934565b6000858481518110612fad57612fad615a95565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110612fd857612fd8615a95565b60200260200101519050612feb81613c50565b9550612ff8600186615ac4565b94505050613482565b6002816020015151036133fa57600061301982613c75565b905060008160008151811061303057613030615a95565b016020015160f81c90506000613047600283615adc565b613052906002615afe565b90506000613063848360ff16613c99565b905060006130718a89613c99565b9050600061307f8383613ccf565b905080835114613111576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b657900000000000060648201526084016107a6565b60ff851660021480613126575060ff85166003145b1561331557808251146131bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e64657200000060648201526084016107a6565b6131d58760200151600181518110612e5257612e52615a95565b9c5060008d5111613268576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c656166290000000000000060648201526084016107a6565b60018c516132769190615635565b8814613304576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c65616629000000000000000060648201526084016107a6565b505050505050505050505050612934565b60ff85161580613328575060ff85166001145b1561336757613354876020015160018151811061334757613347615a95565b6020026020010151613c50565b9950613360818a615ac4565b98506133ef565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e20707265666978000000000000000000000000000060648201526084016107a6565b505050505050613482565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f646500000000000000000000000000000000000000000000000060648201526084016107a6565b508061348d81615a5d565b915050612b51565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e747300000000000000000000000000000000000000000000000000000060648201526084016107a6565b6000808213613589576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016107a6565b6000606061359684613d83565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361379357506000919050565b680755bf798b4a1bf1e58212613805576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f57000000000000000000000000000000000000000060448201526064016107a6565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff8111156139bf576139bf614ee8565b604051908082528060200260200182016040528015613a0457816020015b60408051808201909152606080825260208201528152602001906001900390816139dd5790505b50915060005b81811015613a86576040518060400160405280858381518110613a2f57613a2f615a95565b60200260200101518152602001613a5e868481518110613a5157613a51615a95565b6020026020010151613e59565b815250838281518110613a7357613a73615a95565b6020908102919091010152600101613a0a565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613ae5578060011b82018184015160001a8060041c8253600f811660018301535050600101613ab7565b509295945050505050565b60606000806000613b0085613e6c565b919450925090506000816001811115613b1b57613b1b6154db565b14613ba8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d0000000000000060648201526084016107a6565b613bb28284615ac4565b855114613c41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e64657200000000000000000000000060648201526084016107a6565b612a29856020015184846148d9565b60606020826000015110613c6c57613c6782613af0565b61209e565b61209e8261496d565b606061209e613c948360200151600081518110612e5257612e52615a95565b613a8d565b606082518210613cb8575060408051602081019091526000815261209e565b6129348383848651613cca9190615635565b614983565b6000808251845110613ce2578251613ce5565b83515b90505b8082108015613d6c5750828281518110613d0457613d04615a95565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613d4357613d43615a95565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613d7c57816001019150613ce8565b5092915050565b6000808211613dee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e4544000000000000000000000000000000000000000000000060448201526064016107a6565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606061209e613e6783614b5b565b614c44565b600080600080846000015111613f2a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016107a6565b6020840151805160001a607f8111613f4f5760006001600094509450945050506148d2565b60b7811161415d576000613f64608083615635565b90508087600001511161401f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a4016107a6565b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214158061409857507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b61414a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a4016107a6565b50600195509350600092506148d2915050565b60bf81116144ab57600061417260b783615635565b90508087600001511161422d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a4016107a6565b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361430b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a4016107a6565b600184015160088302610100031c603781116143cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a4016107a6565b6143d98184615ac4565b89511161448e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a4016107a6565b614499836001615ac4565b97509550600094506148d29350505050565b60f7811161458c5760006144c060c083615635565b90508087600001511161457b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a4016107a6565b6001955093508492506148d2915050565b600061459960f783615635565b905080876000015111614654576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a4016107a6565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a4016107a6565b600184015160088302610100031c603781116147f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a4016107a6565b6148008184615ac4565b8951116148b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a4016107a6565b6148c0836001615ac4565b97509550600194506148d29350505050565b9193909250565b60608167ffffffffffffffff8111156148f4576148f4614ee8565b6040519080825280601f01601f19166020018201604052801561491e576020820181803683370190505b50905081156129345760006149338486615ac4565b90506020820160005b8481101561495457828101518282015260200161493c565b84811115614963576000858301525b5050509392505050565b606061209e8260200151600084600001516148d9565b60608182601f0110156149f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016107a6565b828284011015614a5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f7700000000000000000000000000000000000060448201526064016107a6565b81830184511015614acb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e647300000000000000000000000000000060448201526064016107a6565b606082158015614aea5760405191506000825260208201604052614b52565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614b23578051835260209283019201614b0b565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201526000825111614c26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a4016107a6565b50604080518082019091528151815260209182019181019190915290565b60606000806000614c5485613e6c565b919450925090506001816001811115614c6f57614c6f6154db565b14614cfc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d000000000000000060648201526084016107a6565b8451614d088385615ac4565b14614d95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e646572000000000000000000000000000060648201526084016107a6565b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614dac5790505093506000835b8651811015614e9a57600080614e1f6040518060400160405280858c60000151614e039190615635565b8152602001858c60200151614e189190615ac4565b9052613e6c565b509150915060405180604001604052808383614e3b9190615ac4565b8152602001848b60200151614e509190615ac4565b815250888581518110614e6557614e65615a95565b6020908102919091010152614e7b600185615ac4565b9350614e878183615ac4565b614e919084615ac4565b92505050614dd9565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614ec857600080fd5b50565b600060208284031215614edd57600080fd5b813561293481614ea6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5e57614f5e614ee8565b604052919050565b600082601f830112614f7757600080fd5b813567ffffffffffffffff811115614f9157614f91614ee8565b614fc260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f17565b818152846020838601011115614fd757600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561500657600080fd5b60405160c0810167ffffffffffffffff828210818311171561502a5761502a614ee8565b81604052829350843583526020850135915061504582614ea6565b8160208401526040850135915061505b82614ea6565b816040840152606085013560608401526080850135608084015260a085013591508082111561508957600080fd5b5061509685828601614f66565b60a0830152505092915050565b600080600080600085870360e08112156150bc57600080fd5b863567ffffffffffffffff808211156150d457600080fd5b6150e08a838b01614ff4565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561511957600080fd5b60408901955060c089013592508083111561513357600080fd5b828901925089601f84011261514757600080fd5b823591508082111561515857600080fd5b508860208260051b840101111561516e57600080fd5b959894975092955050506020019190565b60005b8381101561519a578181015183820152602001615182565b83811115611b5b5750506000910152565b600081518084526151c381602086016020860161517f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061293460208301846151ab565b60006020828403121561521a57600080fd5b5035919050565b63ffffffff81168114614ec857600080fd5b60006020828403121561524557600080fd5b813561293481615221565b60006020828403121561526257600080fd5b813567ffffffffffffffff81111561527957600080fd5b61528584828501614ff4565b949350505050565b67ffffffffffffffff81168114614ec857600080fd5b6000602082840312156152b557600080fd5b81356129348161528d565b6000806000606084860312156152d557600080fd5b83356152e081614ea6565b925060208401356152f081614ea6565b9150604084013561530081614ea6565b809150509250925092565b8015158114614ec857600080fd5b600080600080600060a0868803121561533157600080fd5b853561533c81614ea6565b94506020860135935060408601356153538161528d565b925060608601356153638161530b565b9150608086013567ffffffffffffffff81111561537f57600080fd5b61538b88828901614f66565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516153ec81604985016020870161517f565b919091016049019695505050505050565b60006020828403121561540f57600080fd5b815161293481614ea6565b60008060006060848603121561542f57600080fd5b835161543a81615221565b602085015190935061544b8161528d565b604085015190925061530081614ea6565b60006020828403121561546e57600080fd5b5051919050565b60006080828403121561548757600080fd5b6040516080810181811067ffffffffffffffff821117156154aa576154aa614ee8565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561551c57600080fd5b81516003811061293457600080fd5b60006020828403121561553d57600080fd5b815161293481615221565b600067ffffffffffffffff8084111561556357615563614ee8565b8360051b6020615574818301614f17565b86815291850191818101903684111561558c57600080fd5b865b848110156155c0578035868111156155a65760008081fd5b6155b236828b01614f66565b84525091830191830161558e565b50979650505050505050565b6000602082840312156155de57600080fd5b81516129348161530b565b6000602082840312156155fb57600080fd5b81516129348161528d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561564757615647615606565b500390565b600067ffffffffffffffff8083168185168183048111821515161561567357615673615606565b02949350505050565b600067ffffffffffffffff80831681851680830382111561569f5761569f615606565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826156e6576156e66156a8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561573a5761573a615606565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561577957615779615606565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156157ad576157ad615606565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156157f4576157f4615606565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561582f5761582f615606565b6000871292508782058712848416161561584b5761584b615606565b8785058712818416161561586157615861615606565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156158a9576158a9615606565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156158dd576158dd615606565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561591b5761591b615606565b500290565b60008261592f5761592f6156a8565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261597f60c08301846151ab565b98975050505050505050565b805160ff8116811461599c57600080fd5b919050565b600060c082840312156159b357600080fd5b60405160c0810181811067ffffffffffffffff821117156159d6576159d6614ee8565b60405282516159e481615221565b81526159f26020840161598b565b6020820152615a036040840161598b565b60408201526060830151615a1681615221565b60608201526080830151615a2981615221565b608082015260a08301516fffffffffffffffffffffffffffffffff81168114615a5157600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615a8e57615a8e615606565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008219821115615ad757615ad7615606565b500190565b600060ff831680615aef57615aef6156a8565b8060ff84160691505092915050565b600060ff821660ff841680821015615b1857615b18615606565b9003939250505056fea164736f6c634300080f000a" + + +func init() { + if err := json.Unmarshal([]byte(OptimismPortal2StorageLayoutJSON), OptimismPortal2StorageLayout); err != nil { + panic(err) + } + + layouts["OptimismPortal2"] = OptimismPortal2StorageLayout + deployedBytecodes["OptimismPortal2"] = OptimismPortal2DeployedBin + immutableReferences["OptimismPortal2"] = true +} diff --git a/op-bindings/bindingspreview/registry.go b/op-bindings/bindingspreview/registry.go new file mode 100644 index 000000000000..179f5761f025 --- /dev/null +++ b/op-bindings/bindingspreview/registry.go @@ -0,0 +1,128 @@ +package bindingspreview + +import ( + "fmt" + "strings" + + "github.com/ethereum-optimism/superchain-registry/superchain" + + "github.com/ethereum-optimism/optimism/op-bindings/solc" + "github.com/ethereum/go-ethereum/common" +) + +// layouts represents the set of storage layouts. It is populated in an init function. +var layouts = make(map[string]*solc.StorageLayout) + +// deployedBytecodes represents the set of deployed bytecodes. It is populated +// in an init function. +var deployedBytecodes = make(map[string]string) + +var initBytecodes = make(map[string]string) +var deploymentSalts = make(map[string]string) +var deployers = make(map[string]string) + +// immutableReferences represents the set of immutable references. It is populated +// in an init function. +var immutableReferences = make(map[string]bool) + +// Create2DeployerCodeHash represents the codehash of the Create2Deployer contract. +var Create2DeployerCodeHash = common.HexToHash("0xb0550b5b431e30d38000efb7107aaa0ade03d48a7198a140edda9d27134468b2") + +func init() { + code, err := superchain.LoadContractBytecode(superchain.Hash(Create2DeployerCodeHash)) + if err != nil { + panic(err) + } + deployedBytecodes["Create2Deployer"] = common.Bytes2Hex(code) +} + +// GetStorageLayout returns the storage layout of a contract by name. +func GetStorageLayout(name string) (*solc.StorageLayout, error) { + layout := layouts[name] + if layout == nil { + return nil, fmt.Errorf("%s: storage layout not found", name) + } + return layout, nil +} + +// GetDeployedBytecode returns the deployed bytecode of a contract by name. +func GetDeployedBytecode(name string) ([]byte, error) { + bc := deployedBytecodes[name] + if bc == "" { + return nil, fmt.Errorf("%s: deployed bytecode not found", name) + } + + if !isHex(bc) { + return nil, fmt.Errorf("%s: invalid deployed bytecode", name) + } + + return common.FromHex(bc), nil +} + +// HasImmutableReferences returns the immutable references of a contract by name. +func HasImmutableReferences(name string) (bool, error) { + has, ok := immutableReferences[name] + if !ok { + return false, fmt.Errorf("%s: immutable reference not found", name) + } + return has, nil +} + +func GetInitBytecode(name string) ([]byte, error) { + bc := initBytecodes[name] + if bc == "" { + return nil, fmt.Errorf("%s: init bytecode not found", name) + } + + if !isHex(bc) { + return nil, fmt.Errorf("%s: invalid init bytecode", name) + } + + return common.FromHex(bc), nil +} + +func GetDeployerAddress(name string) ([]byte, error) { + addr := deployers[name] + if addr == "" { + return nil, fmt.Errorf("%s: deployer address not found", name) + } + + if !common.IsHexAddress(addr) { + return nil, fmt.Errorf("%s: invalid deployer address", name) + } + + return common.FromHex(addr), nil +} + +func GetDeploymentSalt(name string) ([]byte, error) { + salt := deploymentSalts[name] + if salt == "" { + return nil, fmt.Errorf("%s: deployment salt not found", name) + } + + if !isHex(salt) { + return nil, fmt.Errorf("%s: invalid deployment salt", name) + } + + return common.FromHex(salt), nil +} + +// isHexCharacter returns bool of c being a valid hexadecimal. +func isHexCharacter(c byte) bool { + return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F') +} + +// isHex validates whether each byte is valid hexadecimal string. +func isHex(str string) bool { + if len(str)%2 != 0 { + return false + } + str = strings.TrimPrefix(str, "0x") + + for _, c := range []byte(str) { + if !isHexCharacter(c) { + return false + } + } + return true +} diff --git a/op-bindings/cmd/main.go b/op-bindings/cmd/main.go index 2916c386b61a..8c14f4fcda1d 100644 --- a/op-bindings/cmd/main.go +++ b/op-bindings/cmd/main.go @@ -72,7 +72,7 @@ func main() { func setupLogger(c *cli.Context) log.Logger { logger := oplog.NewLogger(oplog.AppOut(c), oplog.ReadCLIConfig(c)) - oplog.SetGlobalLogHandler(logger.GetHandler()) + oplog.SetGlobalLogHandler(logger.Handler()) return logger } diff --git a/op-bindings/predeploys/eip4788.go b/op-bindings/predeploys/eip4788.go index 667917944b18..de934e9bced2 100644 --- a/op-bindings/predeploys/eip4788.go +++ b/op-bindings/predeploys/eip4788.go @@ -10,6 +10,7 @@ import "github.com/ethereum/go-ethereum/common" // See https://goerli.etherscan.io/tx/0xdf52c2d3bbe38820fff7b5eaab3db1b91f8e1412b56497d88388fb5d4ea1fde0 // And https://eips.ethereum.org/EIPS/eip-4788 var ( - EIP4788ContractAddr = common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02") - EIP4788ContractCode = common.Hex2Bytes("0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500") + EIP4788ContractAddr = common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02") + EIP4788ContractCode = common.FromHex("0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500") + EIP4788ContractCodeHash = common.HexToHash("0xf57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c") ) diff --git a/op-bootnode/bootnode/entrypoint.go b/op-bootnode/bootnode/entrypoint.go index ca38cd3da597..0dcf356fa1f3 100644 --- a/op-bootnode/bootnode/entrypoint.go +++ b/op-bootnode/bootnode/entrypoint.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" opnode "github.com/ethereum-optimism/optimism/op-node" "github.com/ethereum-optimism/optimism/op-node/metrics" @@ -20,6 +21,7 @@ import ( oplog "github.com/ethereum-optimism/optimism/op-service/log" opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" "github.com/ethereum-optimism/optimism/op-service/opio" + oprpc "github.com/ethereum-optimism/optimism/op-service/rpc" ) type gossipNoop struct{} @@ -37,18 +39,18 @@ func (g *gossipConfig) P2PSequencerAddress() common.Address { type l2Chain struct{} func (l *l2Chain) PayloadByNumber(_ context.Context, _ uint64) (*eth.ExecutionPayloadEnvelope, error) { - return nil, nil + return nil, errors.New("P2P req/resp is not supported in bootnodes") } func Main(cliCtx *cli.Context) error { log.Info("Initializing bootnode") logCfg := oplog.ReadCLIConfig(cliCtx) logger := oplog.NewLogger(oplog.AppOut(cliCtx), logCfg) - oplog.SetGlobalLogHandler(logger.GetHandler()) + oplog.SetGlobalLogHandler(logger.Handler()) m := metrics.NewMetrics("default") ctx := context.Background() - config, err := opnode.NewRollupConfig(logger, cliCtx) + config, err := opnode.NewRollupConfigFromCLI(logger, cliCtx) if err != nil { return err } @@ -60,6 +62,10 @@ func Main(cliCtx *cli.Context) error { if err != nil { return fmt.Errorf("failed to load p2p config: %w", err) } + if p2pConfig.EnableReqRespSync { + logger.Warn("req-resp sync is enabled, bootnode does not support this feature") + p2pConfig.EnableReqRespSync = false + } p2pNode, err := p2p.NewNodeP2P(ctx, config, logger, p2pConfig, &gossipNoop{}, &l2Chain{}, &gossipConfig{}, m, false) if err != nil || p2pNode == nil { @@ -69,6 +75,29 @@ func Main(cliCtx *cli.Context) error { return fmt.Errorf("uninitialized discovery service") } + rpcCfg := oprpc.ReadCLIConfig(cliCtx) + if err := rpcCfg.Check(); err != nil { + return fmt.Errorf("failed to validate RPC config") + } + rpcServer := oprpc.NewServer(rpcCfg.ListenAddr, rpcCfg.ListenPort, "", oprpc.WithLogger(logger)) + if rpcCfg.EnableAdmin { + logger.Info("Admin RPC enabled but does nothing for the bootnode") + } + rpcServer.AddAPI(rpc.API{ + Namespace: p2p.NamespaceRPC, + Version: "", + Service: p2p.NewP2PAPIBackend(p2pNode, logger, m), + Authenticated: false, + }) + if err := rpcServer.Start(); err != nil { + return fmt.Errorf("failed to start the RPC server") + } + defer func() { + if err := rpcServer.Stop(); err != nil { + log.Error("failed to stop RPC server", "err", err) + } + }() + go p2pNode.DiscoveryProcess(ctx, logger, config, p2pConfig.TargetPeers()) metricsCfg := opmetrics.ReadCLIConfig(cliCtx) diff --git a/op-bootnode/flags/flags.go b/op-bootnode/flags/flags.go index 03e3e1889c61..5fbe0d538b33 100644 --- a/op-bootnode/flags/flags.go +++ b/op-bootnode/flags/flags.go @@ -7,17 +7,19 @@ import ( opflags "github.com/ethereum-optimism/optimism/op-service/flags" oplog "github.com/ethereum-optimism/optimism/op-service/log" opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" + oprpc "github.com/ethereum-optimism/optimism/op-service/rpc" ) const envVarPrefix = "OP_BOOTNODE" var Flags = []cli.Flag{ - opflags.CLINetworkFlag(envVarPrefix), - opflags.CLIRollupConfigFlag(envVarPrefix), + opflags.CLINetworkFlag(envVarPrefix, ""), + opflags.CLIRollupConfigFlag(envVarPrefix, ""), } func init() { Flags = append(Flags, flags.P2PFlags(envVarPrefix)...) Flags = append(Flags, opmetrics.CLIFlags(envVarPrefix)...) Flags = append(Flags, oplog.CLIFlags(envVarPrefix)...) + Flags = append(Flags, oprpc.CLIFlags(envVarPrefix)...) } diff --git a/op-chain-ops/Makefile b/op-chain-ops/Makefile index bcd56a2a159f..1e39aca41694 100644 --- a/op-chain-ops/Makefile +++ b/op-chain-ops/Makefile @@ -1,6 +1,12 @@ op-version-check: go build -o ./bin/op-version-check ./cmd/op-version-check/main.go +ecotone-scalar: + go build -o ./bin/ecotone-scalar ./cmd/ecotone-scalar/main.go + +receipt-reference-builder: + go build -o ./bin/receipt-reference-builder ./cmd/receipt-reference-builder/*.go + test: go test ./... diff --git a/op-chain-ops/cmd/check-canyon/main.go b/op-chain-ops/cmd/check-canyon/main.go index c6deeb87ced1..deb5270ed639 100644 --- a/op-chain-ops/cmd/check-canyon/main.go +++ b/op-chain-ops/cmd/check-canyon/main.go @@ -12,7 +12,9 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/client" "github.com/ethereum-optimism/optimism/op-service/eth" + oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/mattn/go-isatty" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" @@ -206,7 +208,10 @@ func CheckInactivation(f func(Args, bool) error, ctx Args, forkActivated bool, v } func main() { - logger := log.New() + color := isatty.IsTerminal(os.Stderr.Fd()) + handler := log.NewTerminalHandler(os.Stderr, color) + oplog.SetGlobalLogHandler(handler) + logger := log.NewLogger(handler) // Define the flag variables var ( diff --git a/op-chain-ops/cmd/check-delta/aggregate-channels.sh b/op-chain-ops/cmd/check-delta/aggregate-channels.sh index 12f7135acc36..e788ddc651af 100755 --- a/op-chain-ops/cmd/check-delta/aggregate-channels.sh +++ b/op-chain-ops/cmd/check-delta/aggregate-channels.sh @@ -33,6 +33,7 @@ singular_batch_count=0 channels_with_invalid_batches=() +# shellcheck disable=SC2016 batch_type_counter_jq_script='reduce .batch_types[] as $batch_type ( {"span_batch_count": 0, "singular_batch_count": 0}; if $batch_type == 1 then @@ -50,7 +51,7 @@ for file in "$directory_path"/*.json; do continue fi # check channels are ready - if [ $(jq -r ".is_ready" "$file") == "false" ] ; then + if [ "$(jq -r ".is_ready" "$file")" == "false" ] ; then # not ready channel have no batches so invalid_batches field is always false ((not_ready_channel_count++)) not_ready_channels+=("$file") @@ -59,12 +60,13 @@ for file in "$directory_path"/*.json; do ((ready_channel_count++)) fi # check channels contain invalid batches - if [ $(jq -r ".invalid_batches" "$file") == "true" ] ; then + if [ "$(jq -r ".invalid_batches" "$file")" == "true" ] ; then channels_with_invalid_batches+=("$file") fi # count singular batch count and span batch count jq_result=$(jq "$batch_type_counter_jq_script" "$file") - read span_batch_count_per_channel singular_batch_count_per_channel <<< $jq_result + # shellcheck disable=SC2162 + read span_batch_count_per_channel singular_batch_count_per_channel <<< "$jq_result" span_batch_count=$((span_batch_count+span_batch_count_per_channel)) singular_batch_count=$((singular_batch_count+singular_batch_count_per_channel)) done diff --git a/op-chain-ops/cmd/check-deploy-config/main.go b/op-chain-ops/cmd/check-deploy-config/main.go index 68659cfc7bdc..599f91611e01 100644 --- a/op-chain-ops/cmd/check-deploy-config/main.go +++ b/op-chain-ops/cmd/check-deploy-config/main.go @@ -9,11 +9,13 @@ import ( "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum/go-ethereum/log" ) func main() { - log.Root().SetHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(isatty.IsTerminal(os.Stderr.Fd())))) + color := isatty.IsTerminal(os.Stderr.Fd()) + oplog.SetGlobalLogHandler(log.NewTerminalHandler(os.Stderr, color)) app := &cli.App{ Name: "check-deploy-config", diff --git a/op-chain-ops/cmd/check-derivation/main.go b/op-chain-ops/cmd/check-derivation/main.go index a848db8a3ca2..499b128f8767 100644 --- a/op-chain-ops/cmd/check-derivation/main.go +++ b/op-chain-ops/cmd/check-derivation/main.go @@ -14,9 +14,11 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/client" "github.com/ethereum-optimism/optimism/op-service/eth" + oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/retry" "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/testutils" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" @@ -28,7 +30,8 @@ import ( ) func main() { - log.Root().SetHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(isatty.IsTerminal(os.Stderr.Fd())))) + color := isatty.IsTerminal(os.Stderr.Fd()) + oplog.SetGlobalLogHandler(log.NewTerminalHandler(os.Stderr, color)) app := cli.NewApp() app.Name = "check-derivation" @@ -157,7 +160,7 @@ func detectL2Reorg(cliCtx *cli.Context) error { return err } - var pollingInterval = cliCtx.Duration("polling-interval") + pollingInterval := cliCtx.Duration("polling-interval") // blockMap maps blockNumber to blockHash blockMap := make(map[uint64]common.Hash) var prevUnsafeHeadNum uint64 @@ -326,7 +329,7 @@ func checkConsolidation(cliCtx *cli.Context) error { if err != nil { return err } - var pollingInterval = cliCtx.Duration("polling-interval") + pollingInterval := cliCtx.Duration("polling-interval") privateKey, err := getPrivateKey(cliCtx) if err != nil { return err diff --git a/op-chain-ops/cmd/check-ecotone/main.go b/op-chain-ops/cmd/check-ecotone/main.go new file mode 100644 index 000000000000..507a20d211a3 --- /dev/null +++ b/op-chain-ops/cmd/check-ecotone/main.go @@ -0,0 +1,887 @@ +package main + +import ( + "context" + "crypto/ecdsa" + "crypto/rand" + "encoding/binary" + "errors" + "fmt" + "math/big" + "os" + "strings" + "time" + + "github.com/holiman/uint256" + "github.com/urfave/cli/v2" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/consensus/misc/eip4844" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/kzg4844" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-bindings/predeploys" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + op_service "github.com/ethereum-optimism/optimism/op-service" + "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/dial" + "github.com/ethereum-optimism/optimism/op-service/eth" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/optimism/op-service/opio" + "github.com/ethereum-optimism/optimism/op-service/retry" + "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum-optimism/optimism/op-service/txmgr" +) + +func main() { + app := cli.NewApp() + app.Name = "check-ecotone" + app.Usage = "Check Ecotone upgrade results." + app.Description = "Check Ecotone upgrade results." + app.Action = func(c *cli.Context) error { + return errors.New("see sub-commands") + } + app.Writer = os.Stdout + app.ErrWriter = os.Stderr + app.Commands = []*cli.Command{ + { + Name: "cancun", + Subcommands: []*cli.Command{ + makeCommand("eip-1153-tstore", checkEIP1153), + makeCommand("eip-4844-blobhash", checkBlobDataHash), + makeCommand("eip-4844-precompile", check4844Precompile), + makeCommand("eip-5656-mcopy", checkMcopy), + makeCommand("eip-6780-selfdestruct", checkSelfdestruct), + makeCommand("eip-4844-blobtx", checkBlobTxDenial), + makeCommand("eip-4788-root", checkBeaconBlockRoot), + makeCommand("eip-4788-contract", check4788Contract), + makeCommand("all", checkAllCancun), + }, + Flags: makeFlags(), + Action: makeCommandAction(checkAllCancun), + }, + makeCommand("upgrade", checkUpgradeTxs), + { + Name: "contracts", + Subcommands: []*cli.Command{ + makeCommand("l1block", checkL1Block), + makeCommand("gpo", checkGPO), + }, + }, + makeCommand("fees", checkL1Fees), + makeCommand("all", checkALL), + { + Name: "gen-key", + Action: func(c *cli.Context) error { + key, err := crypto.GenerateKey() + if err != nil { + return err + } + fmt.Println("address: " + crypto.PubkeyToAddress(key.PublicKey).String()) + return crypto.SaveECDSA("hotkey.txt", key) + }, + }, + } + + err := app.Run(os.Args) + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "Application failed: %v\n", err) + os.Exit(1) + } +} + +type actionEnv struct { + log log.Logger + l1 *ethclient.Client + l2 *ethclient.Client + rollupCl *sources.RollupClient + key *ecdsa.PrivateKey + addr common.Address + gasUsed uint64 + l1GasUsed uint64 +} + +func (ae *actionEnv) RecordGasUsed(rec *types.Receipt) { + ae.gasUsed += rec.GasUsed + ae.l1GasUsed += rec.L1GasUsed.Uint64() + ae.log.Debug("Recorded tx receipt gas", "gas_used", rec.GasUsed, "l1_gas_used", rec.L1GasUsed) +} + +type CheckAction func(ctx context.Context, env *actionEnv) error + +var ( + prefix = "CHECK_ECOTONE" + EndpointL1 = &cli.StringFlag{ + Name: "l1", + Usage: "L1 execution RPC endpoint", + EnvVars: op_service.PrefixEnvVar(prefix, "L1"), + Value: "http://localhost:8545", + } + EndpointL2 = &cli.StringFlag{ + Name: "l2", + Usage: "L2 execution RPC endpoint", + EnvVars: op_service.PrefixEnvVar(prefix, "L2"), + Value: "http://localhost:9545", + } + EndpointRollup = &cli.StringFlag{ + Name: "rollup", + Usage: "L2 rollup-node RPC endpoint", + EnvVars: op_service.PrefixEnvVar(prefix, "ROLLUP"), + Value: "http://localhost:5545", + } + AccountKey = &cli.StringFlag{ + Name: "account", + Usage: "Private key (hex-formatted string) of test account to perform test txs with", + EnvVars: op_service.PrefixEnvVar(prefix, "ACCOUNT"), + } +) + +func makeFlags() []cli.Flag { + flags := []cli.Flag{ + EndpointL1, + EndpointL2, + EndpointRollup, + AccountKey, + } + return append(flags, oplog.CLIFlags(prefix)...) +} + +func makeCommand(name string, fn CheckAction) *cli.Command { + return &cli.Command{ + Name: name, + Action: makeCommandAction(fn), + Flags: cliapp.ProtectFlags(makeFlags()), + } +} + +func makeCommandAction(fn CheckAction) func(c *cli.Context) error { + return func(c *cli.Context) error { + logCfg := oplog.ReadCLIConfig(c) + logger := oplog.NewLogger(c.App.Writer, logCfg) + + c.Context = opio.CancelOnInterrupt(c.Context) + l1Cl, err := ethclient.DialContext(c.Context, c.String(EndpointL1.Name)) + if err != nil { + return fmt.Errorf("failed to dial L1 RPC: %w", err) + } + l2Cl, err := ethclient.DialContext(c.Context, c.String(EndpointL2.Name)) + if err != nil { + return fmt.Errorf("failed to dial L2 RPC: %w", err) + } + rollupCl, err := dial.DialRollupClientWithTimeout(c.Context, time.Second*20, logger, c.String(EndpointRollup.Name)) + if err != nil { + return fmt.Errorf("failed to dial rollup node RPC: %w", err) + } + key, err := crypto.HexToECDSA(c.String(AccountKey.Name)) + if err != nil { + return fmt.Errorf("failed to parse test private key: %w", err) + } + if err := fn(c.Context, &actionEnv{ + log: logger, + l1: l1Cl, + l2: l2Cl, + rollupCl: rollupCl, + key: key, + addr: crypto.PubkeyToAddress(key.PublicKey), + }); err != nil { + return fmt.Errorf("command error: %w", err) + } + return nil + } +} + +// assuming a 0 (fail) or non-zero (success) on the stack, this performs a revert or self-destruct +func conditionalCode(data []byte) []byte { + suffix := []byte{ + // add jump dest + byte(vm.PUSH4), + 0xff, 0xff, 0xff, 0xff, + byte(vm.JUMPI), + // error case + byte(vm.PUSH0), + byte(vm.PUSH0), + byte(vm.REVERT), + // success case + byte(vm.JUMPDEST), + byte(vm.CALLER), + byte(vm.SELFDESTRUCT), + byte(vm.STOP), + } + binary.BigEndian.PutUint32(suffix[1:5], uint32(len(data))+9) + out := make([]byte, 0, len(data)+len(suffix)) + out = append(out, data...) + out = append(out, suffix...) + return out +} + +func checkEIP1153(ctx context.Context, env *actionEnv) error { + input := conditionalCode([]byte{ + // store 0xc0ffee at 0x42 + byte(vm.PUSH3), + 0xc0, 0xff, 0xee, + byte(vm.PUSH1), + 0x42, + byte(vm.TSTORE), + // retrieve it + byte(vm.PUSH1), + 0x42, + byte(vm.TLOAD), + // check value + byte(vm.PUSH3), + 0xc0, 0xff, 0xee, + byte(vm.EQ), + }) + if err := execTx(ctx, nil, input, false, env); err != nil { + return err + } + env.log.Info("eip-1153 transient storage test: success") + return nil +} + +func checkBlobDataHash(ctx context.Context, env *actionEnv) error { + // revert on non-blob tx + input := []byte{ + byte(vm.BLOBHASH), + } + if err := execTx(ctx, nil, input, true, env); err != nil { + return err + } + env.log.Info("4844 blob-data-hash test: success") + return nil +} + +// Deploy a contract that calls the EIP-4844 blob verification precompile with valid proof, +// and check if it verifies the proof successfully. +func check4844Precompile(ctx context.Context, env *actionEnv) error { + var x eth.Blob + if err := x.FromData(eth.Data("remember ethers phoenix")); err != nil { + return fmt.Errorf("failed to construct blob: %w", err) + } + commitment, err := x.ComputeKZGCommitment() + if err != nil { + return fmt.Errorf("failed to compute commitment: %w", err) + } + point := kzg4844.Point{} + proof, claim, err := kzg4844.ComputeProof(kzg4844.Blob(x), point) + if err != nil { + return fmt.Errorf("failed to compute proof: %w", err) + } + versionedHash := eth.KZGToVersionedHash(commitment) + + var inner []byte + mstore32 := func(v []byte, offset uint8) { + if len(v) != 32 { + panic("invalid v") + } + inner = append(inner, byte(vm.PUSH32)) + inner = append(inner, v...) + inner = append(inner, byte(vm.PUSH1), offset, byte(vm.MSTORE)) + } + + // prepare input in memory, following EIP-4844: + // versioned_hash = input[:32] + // z = input[32:64] + // y = input[64:96] + // commitment = input[96:144] + // proof = input[144:192] + // + // the call verify p(z) = y + mstore32(versionedHash[:], 0) // versioned hash + mstore32(point[:], 32) // z + mstore32(claim[:], 64) // y + mstore32(commitment[0:32], 96) + mstore32(append(append([]byte{}, commitment[32:48]...), proof[0:16]...), 96+32) + mstore32(proof[16:48], 144+16) + env.log.Info(fmt.Sprintf("4844 precompile test: verifying p(%x) == %x for commitment %x proof %x", point[:], claim[:], commitment[:], proof[:])) + + inner = append(inner, []byte{ + byte(vm.PUSH0), // retSize + byte(vm.PUSH0), // retOffset + byte(vm.PUSH1), // argsSize + byte(192), + byte(vm.PUSH0), // argsOffset + byte(vm.PUSH1), // precompile address + byte(0x0A), + byte(vm.GAS), // gas (supply all gas) + byte(vm.STATICCALL), // run call + // 0 will be on stack if call reverts, 1 otherwise + // now get the return-data size, and multiply it. To ensure size == 0 counts as failed call. + byte(vm.RETURNDATASIZE), + byte(vm.MUL), + }...) + + input := conditionalCode(inner) + if err := execTx(ctx, nil, input, false, env); err != nil { + return fmt.Errorf("precompile check failed: %w", err) + } + env.log.Info("eip-4844 precompile test: success") + return nil +} + +func check4788Contract(ctx context.Context, env *actionEnv) error { + head, err := env.l2.HeaderByNumber(ctx, nil) + if err != nil { + return err + } + // reverts on all-0 time input + if err := execTx(ctx, &predeploys.EIP4788ContractAddr, make([]byte, 32), true, env); err != nil { + return fmt.Errorf("expected revert on empty input: %w", err) + } + + conf, err := env.rollupCl.RollupConfig(ctx) + if err != nil { + return fmt.Errorf("config retrieval failed: %w", err) + } + t := head.Time + alignment := head.Time % conf.BlockTime + for i := 0; i < 20; i++ { + ti := t - uint64(i) + if !conf.IsEcotone(ti) { + continue + } + env.log.Info("Beacon block root query timestamp", "query_timestamp", ti) + // revert when timestamp doesn't exist (when not aligned it won't exist), + // or when we call it at the activation block and the contract was newly deployed + // (the beacon block root is processed at the start of the block, + // but the contract might not exist yet, during activation). + revert := ti%conf.BlockTime != alignment + if conf.IsEcotoneActivationBlock(ti) { + // if the contract already existed, then we deployed the nonce=1 contract during upgrade + code, err := env.l2.CodeAt(ctx, crypto.CreateAddress(derive.EIP4788From, 1), nil) + if err != nil { + return fmt.Errorf("failed to check code: %w", err) + } + revert = revert || len(code) == 0 + } + input := new(uint256.Int).SetUint64(ti).Bytes32() + if err := execTx(ctx, &predeploys.EIP4788ContractAddr, input[:], revert, env); err != nil { + return fmt.Errorf("failed at t = %d", ti) + } + } + env.log.Info("eip-4788 beacon block-roots contract test: success") + return nil +} + +func checkMcopy(ctx context.Context, env *actionEnv) error { + input := conditionalCode([]byte{ + // push info & mstore it + byte(vm.PUSH3), + 0xc0, 0xff, 0xee, + byte(vm.PUSH0), // store at 0 + byte(vm.MSTORE), + // copy the memory + byte(vm.PUSH1), // length + 0x2, // only copy the C0FF part + byte(vm.PUSH1), // src + 32 - 3, // right-aligned bytes3 + byte(vm.PUSH1), // dst + 0x42, + byte(vm.MCOPY), + byte(vm.PUSH1), // copy from destination + 0x42 - (32 - 3), // a little to the left, so it's left-padded + byte(vm.MLOAD), // load the memory from copied location + // check if it matches, with zero 3rd byte + byte(vm.PUSH3), + 0xc0, 0xff, 0x00, + byte(vm.EQ), + }) + if err := execTx(ctx, nil, input, false, env); err != nil { + return err + } + env.log.Info("eip-5656 mcopy test: success") + return nil +} + +func checkSelfdestruct(ctx context.Context, env *actionEnv) error { + input := conditionalCode([]byte{ + // prepare code in memory + byte(vm.PUSH2), // value + byte(vm.CALLER), + byte(vm.SELFDESTRUCT), + byte(vm.PUSH1), // offset + byte(vm.MSTORE), + // create contract + byte(vm.PUSH1), // size, just a 2 byte contract + 2, + byte(vm.PUSH0), // ETH value + byte(vm.PUSH0), // offset + byte(vm.CREATE), // pushes address on stack. Contract will immediately self-destruct + byte(vm.EXTCODESIZE), // size should be 0 + byte(vm.ISZERO), // check that it is + }) + if err := execTx(ctx, nil, input, false, env); err != nil { + return err + } + env.log.Info("eip-6780 self-destruct test: success") + return nil +} + +func execTx(ctx context.Context, to *common.Address, data []byte, expectRevert bool, env *actionEnv) error { + nonce, err := env.l2.PendingNonceAt(ctx, env.addr) + if err != nil { + return fmt.Errorf("pending nonce retrieval failed: %w", err) + } + head, err := env.l2.HeaderByNumber(context.Background(), nil) + if err != nil { + return fmt.Errorf("failed to retrieve head header: %w", err) + } + + tip := big.NewInt(params.GWei) + maxFee := new(big.Int).Mul(head.BaseFee, big.NewInt(2)) + maxFee = maxFee.Add(maxFee, tip) + + chainID, err := env.l2.ChainID(ctx) + if err != nil { + return fmt.Errorf("failed to get chainID: %w", err) + } + tx := types.NewTx(&types.DynamicFeeTx{ + ChainID: chainID, Nonce: nonce, + GasTipCap: tip, GasFeeCap: maxFee, Gas: 500000, To: to, Data: data, + }) + signer := types.NewCancunSigner(chainID) + signedTx, err := types.SignTx(tx, signer, env.key) + if err != nil { + return fmt.Errorf("failed to sign tx: %w", err) + } + + env.log.Info("sending tx", "txhash", signedTx.Hash(), "to", to, "data", hexutil.Bytes(data)) + if err := env.l2.SendTransaction(ctx, signedTx); err != nil { + return fmt.Errorf("failed to send tx: %w", err) + } + for i := 0; i < 30; i++ { + env.log.Info("checking confirmation...", "txhash", signedTx.Hash()) + receipt, err := env.l2.TransactionReceipt(context.Background(), signedTx.Hash()) + if err != nil { + if strings.Contains(err.Error(), "not found") { + env.log.Info("not found yet, waiting...") + time.Sleep(time.Second) + continue + } else { + return fmt.Errorf("error while checking tx receipt: %w", err) + } + } + env.RecordGasUsed(receipt) + if expectRevert { + if receipt.Status == types.ReceiptStatusFailed { + env.log.Info("tx reverted as expected", "txhash", signedTx.Hash()) + return nil + } else { + return fmt.Errorf("tx %s unexpectedly completed without revert", signedTx.Hash()) + } + } else { + if receipt.Status == types.ReceiptStatusSuccessful { + env.log.Info("tx confirmed", "txhash", signedTx.Hash()) + return nil + } else { + return fmt.Errorf("tx %s failed", signedTx.Hash()) + } + } + } + return fmt.Errorf("failed to confirm tx: %s", signedTx.Hash()) +} + +func checkBlobTxDenial(ctx context.Context, env *actionEnv) error { + // verify we cannot submit a blob tx to RPC + var blob eth.Blob + _, err := rand.Read(blob[:]) + if err != nil { + return fmt.Errorf("failed randomnes: %w", err) + } + // get the field-elements into a valid range + for i := 0; i < 4096; i++ { + blob[32*i] &= 0b0011_1111 + } + sidecar, blobHashes, err := txmgr.MakeSidecar([]*eth.Blob{&blob}) + if err != nil { + return fmt.Errorf("failed to make sidecar: %w", err) + } + latestHeader, err := env.l1.HeaderByNumber(ctx, nil) + if err != nil { + return fmt.Errorf("failed to get header: %w", err) + } + if latestHeader.ExcessBlobGas == nil { + return fmt.Errorf("the L1 block %s (time %d) is not ecotone yet", latestHeader.Hash(), latestHeader.Time) + } + blobBaseFee := eip4844.CalcBlobFee(*latestHeader.ExcessBlobGas) + blobFeeCap := new(uint256.Int).Mul(uint256.NewInt(2), uint256.MustFromBig(blobBaseFee)) + if blobFeeCap.Lt(uint256.NewInt(params.GWei)) { // ensure we meet 1 gwei geth tx-pool minimum + blobFeeCap = uint256.NewInt(params.GWei) + } + gasTipCap := big.NewInt(2 * params.GWei) + gasFeeCap := new(big.Int).Add(gasTipCap, new(big.Int).Mul(latestHeader.BaseFee, big.NewInt(2))) + + nonce, err := env.l2.PendingNonceAt(ctx, env.addr) + if err != nil { + return fmt.Errorf("failed to get pending nonce: %w", err) + } + rollupCfg, err := env.rollupCl.RollupConfig(ctx) + if err != nil { + return fmt.Errorf("failed to retrieve rollup config: %w", err) + } + txData := &types.BlobTx{ + To: rollupCfg.BatchInboxAddress, + Data: nil, + Gas: params.TxGas, // intrinsic gas only + BlobHashes: blobHashes, + Sidecar: sidecar, + ChainID: uint256.MustFromBig(rollupCfg.L2ChainID), + GasTipCap: uint256.MustFromBig(gasTipCap), + GasFeeCap: uint256.MustFromBig(gasFeeCap), + BlobFeeCap: blobFeeCap, + Value: uint256.NewInt(0), + Nonce: nonce, + } + // bypass signer filter by creating it manually and using the L2 chain ID + signer := types.NewCancunSigner(rollupCfg.L2ChainID) + tx, err := types.SignNewTx(env.key, signer, txData) + if err != nil { + return fmt.Errorf("failed to sign blob tx: %w", err) + } + err = env.l2.SendTransaction(ctx, tx) + if err == nil { + return errors.New("expected tx error, but got none") + } + if !strings.Contains(err.Error(), "transaction type not supported") { + return fmt.Errorf("unexpected tx submission error: %w", err) + } + env.log.Info("blob-tx denial test: success") + return nil +} + +func checkBeaconBlockRoot(ctx context.Context, env *actionEnv) error { + latest, err := env.l2.HeaderByNumber(ctx, nil) + if err != nil { + return fmt.Errorf("failed to get latest block: %w", err) + } + if latest.ParentBeaconRoot == nil { + return fmt.Errorf("block %d misses beacon block root", latest.Number) + } + beaconBlockRootsContract, err := env.l2.CodeAt(ctx, predeploys.EIP4788ContractAddr, nil) + if err != nil { + return fmt.Errorf("failed to retrieve beacon block root contract code: %w", err) + } + codeHash := crypto.Keccak256Hash(beaconBlockRootsContract) + if codeHash != predeploys.EIP4788ContractCodeHash { + return fmt.Errorf("unexpected 4788 contract code: %w", err) + } + + rollupCfg, err := env.rollupCl.RollupConfig(ctx) + if err != nil { + return fmt.Errorf("failed to retrieve rollup config: %w", err) + } + l2RPC := client.NewBaseRPCClient(env.l2.Client()) + l2EthCl, err := sources.NewL2Client(l2RPC, env.log, nil, + sources.L2ClientDefaultConfig(rollupCfg, false)) + if err != nil { + return fmt.Errorf("failed to create eth client") + } + result, err := l2EthCl.GetProof(ctx, predeploys.EIP4788ContractAddr, nil, eth.Unsafe) + if err != nil { + return fmt.Errorf("failed to get account proof to inspect storage-root") + } + if result.StorageHash == types.EmptyRootHash { + return fmt.Errorf("expected contract storage to be set, but got none (%s)", + result.StorageHash) + } + + payload, err := l2EthCl.PayloadByLabel(ctx, eth.Unsafe) + if err != nil { + return fmt.Errorf("failed to get head ref: %w", err) + } + if payload.ParentBeaconBlockRoot == nil { + return fmt.Errorf("payload %s misses parent beacon block root", payload.ExecutionPayload.ID()) + } + headRef, err := derive.PayloadToBlockRef(rollupCfg, payload.ExecutionPayload) + if err != nil { + return fmt.Errorf("failed to convert to block-ref: %w", err) + } + l1Header, err := retry.Do(ctx, 5, retry.Fixed(time.Second*12), func() (*types.Header, error) { + env.log.Info("retrieving L1 origin...", "l1", headRef.L1Origin) + return env.l1.HeaderByHash(ctx, headRef.L1Origin.Hash) + }) + if err != nil { + return fmt.Errorf("failed to retrieve L1 origin %s of L2 block %s: %w", headRef.L1Origin, headRef, err) + } + var l1ParentBeaconBlockRoot common.Hash // zero before Dencun activates on L1 + if l1Header.ParentBeaconRoot != nil { + l1ParentBeaconBlockRoot = *l1Header.ParentBeaconRoot + } + if l1ParentBeaconBlockRoot != *payload.ParentBeaconBlockRoot { + return fmt.Errorf("parent beacon block root mismatch, L1: %s, L2: %s", + l1ParentBeaconBlockRoot, *payload.ParentBeaconBlockRoot) + } + env.log.Info("beacon-block-root block-content test: success") + return nil +} + +func checkAllCancun(ctx context.Context, env *actionEnv) error { + if err := checkEIP1153(ctx, env); err != nil { + return fmt.Errorf("eip-1153 error: %w", err) + } + if err := checkBlobDataHash(ctx, env); err != nil { + return fmt.Errorf("eip-4844 blobhash error: %w", err) + } + if err := check4844Precompile(ctx, env); err != nil { + return fmt.Errorf("eip-4844 precompile error: %w", err) + } + if err := checkMcopy(ctx, env); err != nil { + return fmt.Errorf("eip-5656 mcopy error: %w", err) + } + if err := checkSelfdestruct(ctx, env); err != nil { + return fmt.Errorf("eip-6780 selfdestruct error: %w", err) + } + if err := checkBlobTxDenial(ctx, env); err != nil { + return fmt.Errorf("eip-4844 blob-tx denial error: %w", err) + } + if err := checkBeaconBlockRoot(ctx, env); err != nil { + return fmt.Errorf("eip-4788 beacon-block-roots error: %w", err) + } + if err := check4788Contract(ctx, env); err != nil { + return fmt.Errorf("eip-4788 contract check error: %w", err) + } + env.log.Info("completed Cancun feature tests successfully") + return nil +} + +func checkUpgradeTxs(ctx context.Context, env *actionEnv) error { + rollupCfg, err := env.rollupCl.RollupConfig(ctx) + if err != nil { + return fmt.Errorf("failed to retrieve rollup config: %w", err) + } + + activationBlockNum := rollupCfg.Genesis.L2.Number + + ((*rollupCfg.EcotoneTime - rollupCfg.Genesis.L2Time) / rollupCfg.BlockTime) + env.log.Info("upgrade block num", "num", activationBlockNum) + l2RPC := client.NewBaseRPCClient(env.l2.Client()) + l2EthCl, err := sources.NewL2Client(l2RPC, env.log, nil, + sources.L2ClientDefaultConfig(rollupCfg, false)) + if err != nil { + return fmt.Errorf("failed to create eth client") + } + activBlock, txs, err := l2EthCl.InfoAndTxsByNumber(ctx, activationBlockNum) + if err != nil { + return fmt.Errorf("failed to get activation block: %w", err) + } + if len(txs) < 7 { + return fmt.Errorf("expected at least 7 txs in Ecotone activation block, but got %d", len(txs)) + } + for i, tx := range txs { + if !tx.IsDepositTx() { + return fmt.Errorf("unexpected non-deposit tx in activation block, index %d, hash %s", i, tx.Hash()) + } + } + _, receipts, err := l2EthCl.FetchReceipts(ctx, activBlock.Hash()) + if err != nil { + return fmt.Errorf("failed to fetch receipts of activation block: %w", err) + } + for i, rec := range receipts { + if rec.Status != types.ReceiptStatusSuccessful { + return fmt.Errorf("failed tx receipt: %d", i) + } + switch i { + case 1, 2, 6: // 2 implementations + 4788 contract deployment + if rec.ContractAddress == (common.Address{}) { + return fmt.Errorf("expected contract deployment, but got none") + } + case 3, 4, 5: // proxy upgrades and setEcotone call + if rec.ContractAddress != (common.Address{}) { + return fmt.Errorf("unexpected contract deployment") + } + } + } + env.log.Info("upgrade-txs receipts test: success") + return nil +} + +func checkL1Block(ctx context.Context, env *actionEnv) error { + cl, err := bindings.NewL1Block(predeploys.L1BlockAddr, env.l2) + if err != nil { + return fmt.Errorf("failed to create bindings around L1Block contract: %w", err) + } + blobBaseFee, err := cl.BlobBaseFee(nil) + if err != nil { + return fmt.Errorf("failed to get blob basfee from L1Block contract: %w", err) + } + if big.NewInt(0).Cmp(blobBaseFee) == 0 { + return errors.New("blob basefee must never be 0, EIP specifies minimum of 1") + } + env.log.Info("l1-block-info test: success") + return nil +} + +func checkGPO(ctx context.Context, env *actionEnv) error { + cl, err := bindings.NewGasPriceOracle(predeploys.GasPriceOracleAddr, env.l2) + if err != nil { + return fmt.Errorf("failed to create bindings around L1Block contract: %w", err) + } + _, err = cl.Overhead(nil) + if err == nil || !strings.Contains(err.Error(), "revert") { + return fmt.Errorf("expected revert on legacy overhead attribute acccess, but got %w", err) + } + _, err = cl.Scalar(nil) + if err == nil || !strings.Contains(err.Error(), "revert") { + return fmt.Errorf("expected revert on legacy scalar attribute acccess, but got %w", err) + } + isEcotone, err := cl.IsEcotone(nil) + if err != nil { + return fmt.Errorf("failed to get ecotone status: %w", err) + } + if !isEcotone { + return fmt.Errorf("GPO is not set to ecotone: %w", err) + } + blobBaseFeeScalar, err := cl.BlobBaseFeeScalar(nil) + if err != nil { + return fmt.Errorf("unable to get blob basefee scalar: %w", err) + } + if blobBaseFeeScalar == 0 { + env.log.Warn("blob basefee scalar is set to 0. SystemConfig needs to emit scalar change to update.") + } + env.log.Info("GPO test: success") + return nil +} + +func checkL1Fees(ctx context.Context, env *actionEnv) error { + rollupCfg, err := env.rollupCl.RollupConfig(ctx) + if err != nil { + return fmt.Errorf("failed to retrieve rollup config: %w", err) + } + env.log.Info("making test tx", "addr", env.addr) + nonce, err := env.l2.PendingNonceAt(ctx, env.addr) + if err != nil { + return fmt.Errorf("failed to get pending nonce: %w", err) + } + env.log.Info("retrieved account nonce", "nonce", nonce) + l2RPC := client.NewBaseRPCClient(env.l2.Client()) + l2EthCl, err := sources.NewL2Client(l2RPC, env.log, nil, + sources.L2ClientDefaultConfig(rollupCfg, false)) + if err != nil { + return fmt.Errorf("failed to create eth client: %w", err) + } + head, err := env.l2.HeaderByNumber(ctx, nil) + if err != nil { + return fmt.Errorf("failed to get head: %w", err) + } + gasTip := big.NewInt(2 * params.GWei) + gasMaxFee := new(big.Int).Add( + new(big.Int).Mul(big.NewInt(2), head.BaseFee), gasTip) + to := common.Address{1, 2, 3, 5} + txData := &types.DynamicFeeTx{ + ChainID: rollupCfg.L2ChainID, + Nonce: nonce, + GasTipCap: gasTip, + GasFeeCap: gasMaxFee, + Gas: params.TxGas + 100, // some margin for the calldata + To: &to, + Value: big.NewInt(3 * params.GWei), + Data: []byte("hello"), + AccessList: nil, + } + tx, err := types.SignNewTx(env.key, types.NewLondonSigner(txData.ChainID), txData) + if err != nil { + return fmt.Errorf("failed to sign test tx: %w", err) + } + env.log.Info("signed tx", "txhash", tx.Hash()) + if err := env.l2.SendTransaction(ctx, tx); err != nil { + return fmt.Errorf("failed to send test tx: %w", err) + } + receipt, err := retry.Do(ctx, 20, retry.Fixed(time.Second*2), func() (*types.Receipt, error) { + return env.l2.TransactionReceipt(ctx, tx.Hash()) + }) + if err != nil { + return fmt.Errorf("failed to confirm tx %s timely: %w", tx.Hash(), err) + } + env.RecordGasUsed(receipt) + if receipt.Status != types.ReceiptStatusSuccessful { + return fmt.Errorf("transaction failed, L1 gas used: %d", receipt.L1GasUsed) + } + env.log.Info("got receipt", "hash", tx.Hash(), "block", receipt.BlockHash) + if receipt.FeeScalar != nil { + return fmt.Errorf("expected fee scalar attribute to be deprecated, but got %v", receipt.FeeScalar) + } + payload, err := l2EthCl.PayloadByHash(ctx, receipt.BlockHash) + if err != nil { + return fmt.Errorf("failed to get head ref: %w", err) + } + headRef, err := derive.PayloadToBlockRef(rollupCfg, payload.ExecutionPayload) + if err != nil { + return fmt.Errorf("failed to convert to block-ref: %w", err) + } + l1Header, err := retry.Do(ctx, 5, retry.Fixed(time.Second*12), func() (*types.Header, error) { + env.log.Info("retrieving L1 origin...", "l1", headRef.L1Origin) + return env.l1.HeaderByHash(ctx, headRef.L1Origin.Hash) + }) + if err != nil { + return fmt.Errorf("failed to retrieve L1 origin %s of L2 block %s: %w", headRef.L1Origin, headRef, err) + } + if receipt.L1GasPrice.Cmp(l1Header.BaseFee) != 0 { + return fmt.Errorf("L1 gas price does not include blob fee component: %d != %d", receipt.L1GasPrice, l1Header.BaseFee) + } + rawTx, err := tx.MarshalBinary() + if err != nil { + return fmt.Errorf("failed to encode tx: %w", err) + } + var zero, nonZero uint64 + for _, b := range rawTx { + if b == 0 { + zero += 1 + } else { + nonZero += 1 + } + } + expectedCalldataGas := zero*4 + nonZero*16 + env.log.Info("expecting fees", "calldatagas", expectedCalldataGas) + env.log.Info("paid fees", "l1_fee", receipt.L1Fee, "l1_basefee", receipt.L1GasPrice) + if new(big.Int).SetUint64(expectedCalldataGas).Cmp(receipt.L1GasUsed) != 0 { + return fmt.Errorf("expected %d L1 gas, but only spent %d", expectedCalldataGas, receipt.L1GasUsed) + } + if big.NewInt(0).Cmp(receipt.L1Fee) >= 0 { + return fmt.Errorf("calculated to low L1 fee: %d", receipt.L1Fee) + } + env.log.Info("L1 fees test: success") + return nil +} + +func checkALL(ctx context.Context, env *actionEnv) error { + bal, err := env.l2.BalanceAt(ctx, env.addr, nil) + if err != nil { + return fmt.Errorf("failed to check balance of account: %w", err) + } + env.log.Info("starting checks, tx account", "addr", env.addr, "balance_wei", bal) + + if err := checkAllCancun(ctx, env); err != nil { + return fmt.Errorf("failed: Cancun error: %w", err) + } + if err := checkUpgradeTxs(ctx, env); err != nil { + return fmt.Errorf("failed: Upgrade-tx error: %w", err) + } + if err := checkL1Block(ctx, env); err != nil { + return fmt.Errorf("failed: L1Block contract error: %w", err) + } + if err := checkGPO(ctx, env); err != nil { + return fmt.Errorf("failed: GPO contract error: %w", err) + } + if err := checkL1Fees(ctx, env); err != nil { + return fmt.Errorf("failed: L1 fees error: %w", err) + } + + finbal, err := env.l2.BalanceAt(ctx, env.addr, nil) + if err != nil { + return fmt.Errorf("failed to check final balance of account: %w", err) + } + env.log.Info("completed all tests successfully!", + "addr", env.addr, "balance_wei", finbal, + "spent_wei", new(big.Int).Sub(bal, finbal), + "gas_used_total", env.gasUsed, + "l1_gas_used_total", env.l1GasUsed, + ) + + return nil +} diff --git a/op-chain-ops/cmd/ecotone-scalar/README.md b/op-chain-ops/cmd/ecotone-scalar/README.md new file mode 100644 index 000000000000..2f533eea7b7f --- /dev/null +++ b/op-chain-ops/cmd/ecotone-scalar/README.md @@ -0,0 +1,20 @@ +# ecotone-scalar + +A CLI tool for computing the value of `scalar` to use after the Ecotone upgrade in a call to +`setGasConfig(scalar, overhead)` of the L1 `SystemConfigProxy` contract. After the Ecotone upgrade, the +overhead parameter is ignored, and the scalar parameter encodes a versioned `bytes32` that allows +configuring the base fee scalar and blob base fee scalars separately. + +#### Usage + +Build and run using the [Makefile](../../Makefile) `ecotone-scalar` target. Inside of `/op-chain-ops`, run: +```sh +make ecotone-scalar +``` +to create a binary in [../../bin/ecotone-scalar](../../bin/ecotone-scalar) that can +be executed, providing the `--scalar` and `--blob-scalar` flags to specify the base bee scalar and +blob base fee parameters respectively, for example: + +```sh +./bin/ecotone-scalar --scalar=7600 --blob-scalar=862000 +``` diff --git a/op-chain-ops/cmd/ecotone-scalar/main.go b/op-chain-ops/cmd/ecotone-scalar/main.go new file mode 100644 index 000000000000..53ee823fc0bc --- /dev/null +++ b/op-chain-ops/cmd/ecotone-scalar/main.go @@ -0,0 +1,40 @@ +package main + +import ( + "encoding/binary" + "flag" + "fmt" + "math" + "math/big" + "os" +) + +func main() { + var scalar, blobScalar uint + flag.UintVar(&scalar, "scalar", 0, "base fee scalar value for the gas config (uint32)") + flag.UintVar(&blobScalar, "blob-scalar", 0, "blob base fee scalar value for the gas config (uint32)") + flag.Parse() + + if scalar > math.MaxUint32 { + fmt.Fprintln(flag.CommandLine.Output(), "scalar out of uint32 range") + flag.Usage() + os.Exit(2) + } + if blobScalar > math.MaxUint32 { + fmt.Fprintln(flag.CommandLine.Output(), "blob-scalar out of uint32 range") + flag.Usage() + os.Exit(2) + } + + var n [32]byte + n[0] = 1 // version + binary.BigEndian.PutUint32(n[32-4:], uint32(scalar)) + binary.BigEndian.PutUint32(n[32-8:], uint32(blobScalar)) + i := new(big.Int).SetBytes(n[:]) + + fmt.Println("# base fee scalar :", scalar) + fmt.Println("# blob base fee scalar:", blobScalar) + fmt.Printf("# v1 hex encoding : 0x%x\n", n[:]) + fmt.Println("# uint value for the 'scalar' parameter in SystemConfigProxy.setGasConfig():") + fmt.Println(i) +} diff --git a/op-chain-ops/cmd/op-simulate/main.go b/op-chain-ops/cmd/op-simulate/main.go new file mode 100644 index 000000000000..04d9e5fe94f0 --- /dev/null +++ b/op-chain-ops/cmd/op-simulate/main.go @@ -0,0 +1,304 @@ +package main + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io/fs" + "math/big" + "os" + "path" + "time" + + "github.com/pkg/profile" + "github.com/urfave/cli/v2" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/beacon" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" + gstate "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + tracelogger "github.com/ethereum/go-ethereum/eth/tracers/logger" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" + + op_service "github.com/ethereum-optimism/optimism/op-service" + "github.com/ethereum-optimism/optimism/op-service/cliapp" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/optimism/op-service/opio" +) + +var EnvPrefix = "OP_SIMULATE" + +var ( + RPCFlag = &cli.StringFlag{ + Name: "rpc", + Usage: "RPC endpoint to fetch prestate from", + EnvVars: op_service.PrefixEnvVar(EnvPrefix, "RPC"), + Required: true, + } + TxFlag = &cli.StringFlag{ + Name: "tx", + Usage: "Transaction hash to trace and simulate", + EnvVars: op_service.PrefixEnvVar(EnvPrefix, "TX"), + Required: true, + } + ProfFlag = &cli.BoolFlag{ + Name: "profile", + Usage: "profile the tx processing", + EnvVars: op_service.PrefixEnvVar(EnvPrefix, "PROFILE"), + Required: false, + } +) + +func main() { + flags := []cli.Flag{ + RPCFlag, TxFlag, ProfFlag, + } + flags = append(flags, oplog.CLIFlags(EnvPrefix)...) + + app := cli.NewApp() + app.Name = "op-simulate" + app.Usage = "Simulate a tx locally." + app.Description = "Fetch a tx from an RPC and simulate it locally." + app.Flags = cliapp.ProtectFlags(flags) + app.Action = mainAction + app.Writer = os.Stdout + app.ErrWriter = os.Stderr + err := app.Run(os.Args) + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "Application failed: %v", err) + os.Exit(1) + } +} + +func mainAction(c *cli.Context) error { + ctx := opio.CancelOnInterrupt(c.Context) + logCfg := oplog.ReadCLIConfig(c) + logger := oplog.NewLogger(c.App.Writer, logCfg) + + endpoint := c.String(RPCFlag.Name) + cl, err := rpc.DialContext(ctx, endpoint) + if err != nil { + return fmt.Errorf("failed to dial RPC %q: %w", endpoint, err) + } + txHashStr := c.String(TxFlag.Name) + var txHash common.Hash + if err := txHash.UnmarshalText([]byte(txHashStr)); err != nil { + return fmt.Errorf("invalid tx hash: %q", txHashStr) + } + prestatesDir := "." + if err := fetchPrestate(ctx, cl, prestatesDir, txHash); err != nil { + return fmt.Errorf("failed to prepare prestate: %w", err) + } + chainConfig, err := fetchChainConfig(ctx, cl) + if err != nil { + return fmt.Errorf("failed to get chain config: %w", err) + } + tx, err := fetchTx(ctx, cl, txHash) + if err != nil { + return fmt.Errorf("failed to get TX: %w", err) + } + rec, err := fetchReceipt(ctx, cl, txHash) + if err != nil { + return fmt.Errorf("failed to get receipt: %w", err) + } + header, err := fetchHeader(ctx, cl, rec.BlockHash) + if err != nil { + return fmt.Errorf("failed to get block header: %w", err) + } + doProfile := c.Bool(ProfFlag.Name) + if err := simulate(ctx, logger, chainConfig, prestateTraceFile(prestatesDir, txHash), tx, header, doProfile); err != nil { + return fmt.Errorf("failed to simulate tx: %w", err) + } + return nil +} + +// TraceConfig is different than Geth TraceConfig, quicknode sin't flexible +type TraceConfig struct { + *tracelogger.Config + Tracer string `json:"tracer"` + Timeout *string `json:"timeout"` + // Config specific to given tracer. Note struct logger + // config are historically embedded in main object. + TracerConfig json.RawMessage +} + +func prestateTraceFile(dir string, txHash common.Hash) string { + return path.Join(dir, "prestate_"+txHash.String()+".json") +} + +func fetchPrestate(ctx context.Context, cl *rpc.Client, dir string, txHash common.Hash) error { + dest := prestateTraceFile(dir, txHash) + // check cache + _, err := os.Stat(dest) + if err == nil { + // already known file + return nil + } + if !errors.Is(err, fs.ErrNotExist) { + return fmt.Errorf("failed to check prestate file %q: %w", dest, err) + } + var result json.RawMessage + if err := cl.CallContext(ctx, &result, "debug_traceTransaction", txHash, TraceConfig{ + Config: &tracelogger.Config{ + EnableMemory: false, + DisableStack: true, + DisableStorage: true, + EnableReturnData: false, + Debug: false, + Limit: 0, + Overrides: nil, + }, + Tracer: "prestateTracer", + Timeout: nil, + TracerConfig: nil, + }); err != nil { + return fmt.Errorf("failed to retrieve prestate trace: %w", err) + } + if err := os.WriteFile(dest, result, 0644); err != nil { + return fmt.Errorf("failed to write prestate trace: %w", err) + } + return nil +} + +func fetchChainConfig(ctx context.Context, cl *rpc.Client) (*params.ChainConfig, error) { + // first try the chain-ID RPC, this is widely available on any RPC provider. + var idResult hexutil.Big + if err := cl.CallContext(ctx, &idResult, "eth_chainId"); err != nil { + return nil, fmt.Errorf("failed to retrieve chain ID: %w", err) + } + // if we recognize the chain ID, we can get the chain config + id := (*big.Int)(&idResult) + if id.IsUint64() { + cfg, err := params.LoadOPStackChainConfig(id.Uint64()) + if err == nil { + return cfg, nil + } + // ignore error, try to fetch chain config in full + } + // if not already recognized, then fetch the chain config manually + var config params.ChainConfig + if err := cl.CallContext(ctx, &config, "eth_chainConfig"); err != nil { + return nil, fmt.Errorf("failed to retrieve chain config: %w", err) + } + return &config, nil +} + +func fetchTx(ctx context.Context, cl *rpc.Client, txHash common.Hash) (*types.Transaction, error) { + tx, pending, err := ethclient.NewClient(cl).TransactionByHash(ctx, txHash) + if pending { + return nil, fmt.Errorf("tx %s is still pending", txHash) + } + return tx, err +} + +func fetchReceipt(ctx context.Context, cl *rpc.Client, txHash common.Hash) (*types.Receipt, error) { + return ethclient.NewClient(cl).TransactionReceipt(ctx, txHash) +} + +func fetchHeader(ctx context.Context, cl *rpc.Client, blockHash common.Hash) (*types.Header, error) { + return ethclient.NewClient(cl).HeaderByHash(ctx, blockHash) +} + +type DumpAccount struct { + Balance hexutil.Big `json:"balance"` + Nonce uint64 `json:"nonce"` + Code hexutil.Bytes `json:"code,omitempty"` + Storage map[common.Hash]common.Hash `json:"storage,omitempty"` +} + +func readDump(prestatePath string) (map[common.Address]DumpAccount, error) { + f, err := os.Open(prestatePath) + if err != nil { + return nil, fmt.Errorf("failed to load state data: %w", err) + } + var out map[common.Address]DumpAccount + if err := json.NewDecoder(f).Decode(&out); err != nil { + return nil, fmt.Errorf("failed to decode state data: %w", err) + } + return out, nil +} + +type simChainContext struct { + eng consensus.Engine + head *types.Header +} + +func (d *simChainContext) Engine() consensus.Engine { + return d.eng +} + +func (d *simChainContext) GetHeader(h common.Hash, n uint64) *types.Header { + if n == d.head.Number.Uint64() { + return d.head + } + panic(fmt.Errorf("header retrieval not supported, cannot fetch %s %d", h, n)) +} + +func simulate(ctx context.Context, logger log.Logger, conf *params.ChainConfig, + prestatePath string, tx *types.Transaction, header *types.Header, doProfile bool) error { + memDB := rawdb.NewMemoryDatabase() + stateDB := gstate.NewDatabase(memDB) + state, err := gstate.New(types.EmptyRootHash, stateDB, nil) + if err != nil { + return fmt.Errorf("failed to create in-memory state: %w", err) + } + dump, err := readDump(prestatePath) + if err != nil { + return fmt.Errorf("failed to read prestate: %w", err) + } + for addr, acc := range dump { + state.CreateAccount(addr) + state.SetBalance(addr, new(big.Int).Set((*big.Int)(&acc.Balance))) + state.SetNonce(addr, acc.Nonce) + state.SetCode(addr, acc.Code) + state.SetStorage(addr, acc.Storage) + } + + // load prestate data into memory db state + _, err = state.Commit(header.Number.Uint64()-1, true) + if err != nil { + return fmt.Errorf("failed to write state data to underlying DB: %w", err) + } + + rules := conf.Rules(header.Number, true, header.Time) + signer := types.MakeSigner(conf, header.Number, header.Time) + sender, err := signer.Sender(tx) + if err != nil { + return fmt.Errorf("failed to get tx sender: %w", err) + } + // prepare the state + precompiles := vm.ActivePrecompiles(rules) + state.Prepare(rules, sender, header.Coinbase, tx.To(), precompiles, tx.AccessList()) + state.SetTxContext(tx.Hash(), 0) + + cCtx := &simChainContext{eng: beacon.NewFaker(), head: header} + gp := core.GasPool(tx.Gas()) + usedGas := uint64(0) + vmConfig := vm.Config{} + + if doProfile { + prof := profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.CPUProfile) + defer prof.Stop() + } + + // run the transaction + start := time.Now() + receipt, err := core.ApplyTransaction(conf, cCtx, &sender, &gp, state, header, tx, &usedGas, vmConfig) + if err != nil { + return fmt.Errorf("failed to apply tx: %w", err) + } + end := time.Since(start) + logger.Info("processed tx", "elapsed", end, + "ok", receipt.Status == types.ReceiptStatusSuccessful, "logs", len(receipt.Logs)) + + return nil +} diff --git a/op-chain-ops/cmd/op-upgrade-mcp/main.go b/op-chain-ops/cmd/op-upgrade-mcp/main.go index fb9e25137cb0..2dd2dc8ca90d 100644 --- a/op-chain-ops/cmd/op-upgrade-mcp/main.go +++ b/op-chain-ops/cmd/op-upgrade-mcp/main.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-chain-ops/safe" "github.com/ethereum-optimism/optimism/op-chain-ops/upgrades" + oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/superchain-registry/superchain" ) @@ -22,6 +23,37 @@ import ( // Note that the key is the L2 chain id. This is because the L1 contracts must be specific // for a particular OP Stack chain and cannot currently be used by multiple chains. var deployments = map[uint64]superchain.ImplementationList{ + // OP Mainnet + 10: { + L1CrossDomainMessenger: superchain.VersionedContract{ + Version: "2.3.0", + Address: superchain.HexToAddress("0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65"), + }, + L1ERC721Bridge: superchain.VersionedContract{ + Version: "2.1.0", + Address: superchain.HexToAddress("0xAE2AF01232a6c4a4d3012C5eC5b1b35059caF10d"), + }, + L1StandardBridge: superchain.VersionedContract{ + Version: "2.1.0", + Address: superchain.HexToAddress("0x64B5a5Ed26DCb17370Ff4d33a8D503f0fbD06CfF"), + }, + OptimismPortal: superchain.VersionedContract{ + Version: "2.5.0", + Address: superchain.HexToAddress("0x2D778797049FE9259d947D1ED8e5442226dFB589"), + }, + SystemConfig: superchain.VersionedContract{ + Version: "1.12.0", + Address: superchain.HexToAddress("0xba2492e52F45651B60B8B38d4Ea5E2390C64Ffb1"), + }, + L2OutputOracle: superchain.VersionedContract{ + Version: "1.8.0", + Address: superchain.HexToAddress("0xF243BEd163251380e78068d317ae10f26042B292"), + }, + OptimismMintableERC20Factory: superchain.VersionedContract{ + Version: "1.9.0", + Address: superchain.HexToAddress("0xE01efbeb1089D1d1dB9c6c8b135C934C0734c846"), + }, + }, // OP Sepolia 11155420: { L1CrossDomainMessenger: superchain.VersionedContract{ @@ -56,7 +88,8 @@ var deployments = map[uint64]superchain.ImplementationList{ } func main() { - log.Root().SetHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(isatty.IsTerminal(os.Stderr.Fd())))) + color := isatty.IsTerminal(os.Stderr.Fd()) + oplog.SetGlobalLogHandler(log.NewTerminalHandler(os.Stderr, color)) app := &cli.App{ Name: "op-upgrade", diff --git a/op-chain-ops/cmd/op-upgrade/main.go b/op-chain-ops/cmd/op-upgrade/main.go index 164f27465f72..36e0d4111a01 100644 --- a/op-chain-ops/cmd/op-upgrade/main.go +++ b/op-chain-ops/cmd/op-upgrade/main.go @@ -19,12 +19,14 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/safe" "github.com/ethereum-optimism/optimism/op-chain-ops/upgrades" "github.com/ethereum-optimism/optimism/op-service/jsonutil" + oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/superchain-registry/superchain" ) func main() { - log.Root().SetHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(isatty.IsTerminal(os.Stderr.Fd())))) + color := isatty.IsTerminal(os.Stderr.Fd()) + oplog.SetGlobalLogHandler(log.NewTerminalHandler(os.Stderr, color)) app := &cli.App{ Name: "op-upgrade", @@ -79,11 +81,16 @@ func entrypoint(ctx *cli.Context) error { } superchainName := ctx.String("superchain-target") - if superchainName == "" { - superchainName, err = upgrades.ToSuperchainName(l1ChainID.Uint64()) - if err != nil { - return err - } + sc, ok := superchain.Superchains[superchainName] + if !ok { + return fmt.Errorf("superchain name %s not registered", superchainName) + } + + declaredChainID := sc.Config.L1.ChainID + + if declaredChainID != l1ChainID.Uint64() { + return fmt.Errorf("superchain %s has chainID %d, but the l1-rpc-url returned a chainId of %d", + superchainName, declaredChainID, l1ChainID.Uint64()) } chainIDs := ctx.Uint64Slice("chain-ids") @@ -168,14 +175,14 @@ func entrypoint(ctx *cli.Context) error { log.Info("L2OutputOracle", "version", versions.L2OutputOracle, "address", addresses.L2OutputOracleProxy) log.Info("OptimismMintableERC20Factory", "version", versions.OptimismMintableERC20Factory, "address", addresses.OptimismMintableERC20FactoryProxy) log.Info("OptimismPortal", "version", versions.OptimismPortal, "address", addresses.OptimismPortalProxy) - log.Info("SystemConfig", "version", versions.SystemConfig, "address", chainConfig.SystemConfigAddr) + log.Info("SystemConfig", "version", versions.SystemConfig, "address", addresses.SystemConfigProxy) implementations, ok := superchain.Implementations[l1ChainID.Uint64()] if !ok { return fmt.Errorf("no implementations for chain ID %d", l1ChainID.Uint64()) } - list, err := implementations.Resolve(superchain.SuperchainSemver) + list, err := implementations.Resolve(superchain.SuperchainSemver[superchainName]) if err != nil { return err } @@ -203,7 +210,7 @@ func entrypoint(ctx *cli.Context) error { // Write the batch to disk or stdout if outfile := ctx.Path("outfile"); outfile != "" { - if err := jsonutil.WriteJSON(outfile, batch); err != nil { + if err := jsonutil.WriteJSON(outfile, batch, 0o666); err != nil { return err } } else { diff --git a/op-chain-ops/cmd/op-version-check/main.go b/op-chain-ops/cmd/op-version-check/main.go index c161db3b1ff8..163ff8599ef5 100644 --- a/op-chain-ops/cmd/op-version-check/main.go +++ b/op-chain-ops/cmd/op-version-check/main.go @@ -14,6 +14,8 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/upgrades" "github.com/ethereum-optimism/optimism/op-service/jsonutil" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/superchain-registry/superchain" ) @@ -29,7 +31,8 @@ type ChainVersionCheck struct { } func main() { - log.Root().SetHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(isatty.IsTerminal(os.Stderr.Fd())))) + color := isatty.IsTerminal(os.Stderr.Fd()) + oplog.SetGlobalLogHandler(log.NewTerminalHandler(os.Stderr, color)) app := &cli.App{ Name: "op-version-check", @@ -105,12 +108,14 @@ func entrypoint(ctx *cli.Context) error { return fmt.Errorf("cannot fetch L1 chain ID: %w", err) } - superchainName, err := upgrades.ToSuperchainName(l1ChainID.Uint64()) - if err != nil { - return fmt.Errorf("error getting superchain name: %w", err) + sc, ok := superchain.Superchains[chainConfig.Superchain] + if !ok { + return fmt.Errorf("superchain name %s not registered", chainConfig.Superchain) } - if superchainName != chainConfig.Superchain { + declaredL1ChainID := sc.Config.L1.ChainID + + if l1ChainID.Uint64() != declaredL1ChainID { // L2 corresponds to a different superchain than L1, skip log.Info("Ignoring L1/L2", "l1-chain-id", l1ChainID, "l2-chain-id", l2ChainID) continue @@ -139,7 +144,7 @@ func entrypoint(ctx *cli.Context) error { contracts["L2OutputOracle"] = Contract{Version: versions.L2OutputOracle, Address: addresses.L2OutputOracleProxy} contracts["OptimismMintableERC20Factory"] = Contract{Version: versions.OptimismMintableERC20Factory, Address: addresses.OptimismMintableERC20FactoryProxy} contracts["OptimismPortal"] = Contract{Version: versions.OptimismPortal, Address: addresses.OptimismPortalProxy} - contracts["SystemConfig"] = Contract{Version: versions.SystemConfig, Address: chainConfig.SystemConfigAddr} + contracts["SystemConfig"] = Contract{Version: versions.SystemConfig, Address: addresses.SystemConfigProxy} contracts["ProxyAdmin"] = Contract{Version: "null", Address: addresses.ProxyAdmin} output = append(output, ChainVersionCheck{Name: chainConfig.Name, ChainID: l2ChainID, Contracts: contracts}) @@ -150,7 +155,7 @@ func entrypoint(ctx *cli.Context) error { } // Write contract versions to disk or stdout if outfile := ctx.Path("outfile"); outfile != "" { - if err := jsonutil.WriteJSON(outfile, output); err != nil { + if err := jsonutil.WriteJSON(outfile, output, 0o666); err != nil { return err } } else { diff --git a/op-chain-ops/cmd/protocol-version/main.go b/op-chain-ops/cmd/protocol-version/main.go index 7c4487437daa..a5bd6b434921 100644 --- a/op-chain-ops/cmd/protocol-version/main.go +++ b/op-chain-ops/cmd/protocol-version/main.go @@ -7,12 +7,14 @@ import ( "github.com/mattn/go-isatty" "github.com/urfave/cli/v2" + "golang.org/x/exp/slog" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" opservice "github.com/ethereum-optimism/optimism/op-service" + oplog "github.com/ethereum-optimism/optimism/op-service/log" ) const EnvPrefix = "OP_CHAIN_OPS_PROTOCOL_VERSION" @@ -51,7 +53,8 @@ var ( ) func main() { - log.Root().SetHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(isatty.IsTerminal(os.Stderr.Fd())))) + color := isatty.IsTerminal(os.Stderr.Fd()) + oplog.SetGlobalLogHandler(log.NewTerminalHandlerWithLevel(os.Stdout, slog.LevelDebug, color)) app := &cli.App{ Name: "protocol-version", diff --git a/op-chain-ops/cmd/receipt-reference-builder/README.md b/op-chain-ops/cmd/receipt-reference-builder/README.md new file mode 100644 index 000000000000..dea2aaa3a085 --- /dev/null +++ b/op-chain-ops/cmd/receipt-reference-builder/README.md @@ -0,0 +1,39 @@ +# Receipt Reference Tool + +Receipt Reference Tool is a data-pulling tool for operational use by Superchain operators of chains which have Post-Bedrock-Pre-Canyon activity. + +## Data Collection + +### Pull +The `pull` subcommand manages a collection of workers to request blocks from an RPC endpoint, and then checks each block for deposit transactions. Those transactions are built up into an aggregate data structure and written. + +### Merge +The `merge` subcommand targets an array of files, confirms that there is no gap in the processed block ranges, and then merges the aggregates into a single file. + +### Convert +The `convert` subcommand targets a single file and writes it as a new file in the requested format. + +### Print +`print` is a debug subcommand to read in a file and print it to screen. + +## Data Spec +The output data of this tool is an "aggregate". Each aggregate contains the following attributes +- Start Block, End Block +- Chain ID +- Results Map: + - Key of BlockNumber + - Value of Nonces as a slice + +Transaction Nonces are inserted to the value slice in the order they appear in the block. Transaction Nonces are only included if they are related to a user deposit. +Blocks which contain no deposit transactions have no key in the data. + +Users of this data can easily find if the data is appropriate for their network (using ChainID), covers a given block (using Start and End), and provides the nonces for user deposits. + +## Best Practices +This tool is designed with a static range of blocks in mind, the size of which is about 10 Million blocks. In order to get such a large body of data in one place, this tool is built for parallel execution and retries. + +To maximize parallel efficiency, a higher number of `-workers` can utilize more RPC requests per second. Additionally `-batch-size` can be increased to group more RPC requests together per network exchange. I am using 5 workers with 100 requests per batch. + +To avoid wasteful abandon of work already done, errors which are encountered by workers are noted, but do not stop the aggregation process. Jobs which fail are reinserted into the work queue with no maximum retry, and workers back off when encountering failures. This is all to allow an RPC endpoint to become temporarily unavailalbe while letting aggregation stay persistent. + +Even at high speed, collecting this much data can take several hours. You may benefit from planning a collection of smaller-sized runs, merging them with the `merge` subcommand as they become available. diff --git a/op-chain-ops/cmd/receipt-reference-builder/convert.go b/op-chain-ops/cmd/receipt-reference-builder/convert.go new file mode 100644 index 000000000000..79bf51d1b81b --- /dev/null +++ b/op-chain-ops/cmd/receipt-reference-builder/convert.go @@ -0,0 +1,46 @@ +package main + +import ( + "errors" + + "github.com/ethereum/go-ethereum/log" + "github.com/urfave/cli/v2" +) + +var convertCommand = &cli.Command{ + Name: "convert", + Usage: "convert an aggregate from one format to another", + Flags: []cli.Flag{FilesFlag, OutputFlag, InputFormatFlag, OutputFormatFlag}, + Action: convert, +} + +func convert(ctx *cli.Context) error { + log := log.New() + files := ctx.StringSlice("files") + if len(files) != 1 { + return errors.New("only one file is supported") + } + + if ctx.String("input-format") == ctx.String("output-format") { + log.Info("no conversion needed. specify different input and output formats") + return nil + } + + r := formats[ctx.String("input-format")] + w := formats[ctx.String("output-format")] + + for _, f := range files { + a, err := r.readAggregate(f) + if err != nil { + log.Error("failed to read aggregate", "file", f, "err", err) + return err + } + err = w.writeAggregate(a, ctx.String("output")) + if err != nil { + log.Error("failed to write aggregate", "file", f, "err", err) + return err + } + + } + return nil +} diff --git a/op-chain-ops/cmd/receipt-reference-builder/main.go b/op-chain-ops/cmd/receipt-reference-builder/main.go new file mode 100644 index 000000000000..0418e92193e7 --- /dev/null +++ b/op-chain-ops/cmd/receipt-reference-builder/main.go @@ -0,0 +1,112 @@ +package main + +import ( + "os" + "time" + + "github.com/mattn/go-isatty" + "github.com/urfave/cli/v2" + "golang.org/x/exp/slog" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + + opservice "github.com/ethereum-optimism/optimism/op-service" + oplog "github.com/ethereum-optimism/optimism/op-service/log" +) + +const EnvPrefix = "OP_CHAIN_OPS_RECEIPT_REFERENCE_BUILDER" + +var ( + StartFlag = &cli.Uint64Flag{ + Name: "start", + Usage: "the first block to include in data collection. INCLUSIVE", + } + EndFlag = &cli.Uint64Flag{ + Name: "end", + Usage: "the last block of the collection range. EXCLUSIVE", + } + RPCURLFlag = &cli.StringFlag{ + Name: "rpc-url", + Usage: "RPC URL to connect to", + EnvVars: opservice.PrefixEnvVar(EnvPrefix, "RPC_URL"), + } + BackoffFlag = &cli.DurationFlag{ + Name: "backoff", + Value: 30 * time.Second, + Usage: "how long to wait when a worker errors before retrying", + } + WorkerFlag = &cli.Uint64Flag{ + Name: "workers", + Value: 1, + Usage: "how many workers to use to fetch txs", + } + BatchSizeFlag = &cli.Uint64Flag{ + Name: "batch-size", + Value: 50, + Usage: "how many blocks to batch together for each worker", + } + OutputFlag = &cli.StringFlag{ + Name: "output", + Aliases: []string{"o"}, + Usage: "the file to write the results to", + } + FilesFlag = &cli.StringSliceFlag{ + Name: "files", + Aliases: []string{"f"}, + Usage: "the set of files to merge", + } + InputFormatFlag = &cli.StringFlag{ + Name: "input-format", + Aliases: []string{"if"}, + Value: "json", + Usage: "the format to read aggregate files: json, gob", + } + OutputFormatFlag = &cli.StringFlag{ + Name: "output-format", + Aliases: []string{"of"}, + Value: "json", + Usage: "the format to write the results in. Options: json, gob", + } + formats = map[string]aggregateReaderWriter{ + "json": jsonAggregateReaderWriter{}, + "gob": gobAggregateReaderWriter{}, + } + systemAddress = common.HexToAddress("0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001") + depositType = uint8(126) +) + +func main() { + color := isatty.IsTerminal(os.Stderr.Fd()) + oplog.SetGlobalLogHandler(log.NewTerminalHandlerWithLevel(os.Stdout, slog.LevelDebug, color)) + + app := &cli.App{ + Name: "receipt-reference-builder", + Usage: "Used to generate reference data for deposit receipts of pre-canyon blocks", + Flags: []cli.Flag{}, + Writer: os.Stdout, + } + + app.Commands = []*cli.Command{ + pullCommand, + mergeCommand, + convertCommand, + printCommand, + } + + if err := app.Run(os.Args); err != nil { + log.Crit("critical error", "err", err) + } +} + +type result struct { + BlockNumber uint64 `json:"blockNumber"` + Nonces []uint64 `json:"nonces"` +} + +type aggregate struct { + Results map[uint64][]uint64 `json:"results"` + ChainID uint64 `json:"chainId"` + First uint64 `json:"start"` + Last uint64 `json:"end"` +} diff --git a/op-chain-ops/cmd/receipt-reference-builder/merge.go b/op-chain-ops/cmd/receipt-reference-builder/merge.go new file mode 100644 index 000000000000..a269af2ae4b1 --- /dev/null +++ b/op-chain-ops/cmd/receipt-reference-builder/merge.go @@ -0,0 +1,105 @@ +package main + +import ( + "errors" + "sort" + + "github.com/ethereum/go-ethereum/log" + "github.com/urfave/cli/v2" +) + +var mergeCommand = &cli.Command{ + Name: "merge", + Usage: "Merge one or more output files into a single file. Later files take precedence per key", + Flags: []cli.Flag{FilesFlag, OutputFlag, InputFormatFlag, OutputFormatFlag}, + Action: merge, +} + +// merge merges one or more files into a single file +func merge(ctx *cli.Context) error { + log := log.New() + files := ctx.StringSlice("files") + if len(files) < 2 { + return errors.New("need at least two files to merge") + } + + log.Info("merging", "files", files) + reader, ok := formats[ctx.String("input-format")] + if !ok { + log.Error("Invalid Input Format. Defaulting to JSON", "Format", ctx.String("input-format")) + reader = formats["json"] + } + writer, ok := formats[ctx.String("output-format")] + if !ok { + log.Error("Invalid Output Format. Defaulting to JSON", "Format", ctx.String("output-format")) + writer = formats["json"] + } + + aggregates := []aggregate{} + for _, f := range files { + a, err := reader.readAggregate(f) + if err != nil { + log.Error("failed to read aggregate", "file", f, "err", err) + return err + } + aggregates = append(aggregates, a) + } + + // sort the aggregates by first block + sort.Sort(ByFirst(aggregates)) + + // check that the block ranges don't have a gap + err := checkBlockRanges(aggregates) + if err != nil { + log.Error("error evaluating block ranges", "err", err) + return err + } + + // merge the aggregates + merged := aggregates[0] + log.Info("aggregates info", "aggs", aggregates, "len", len(aggregates)) + for _, a := range aggregates[1:] { + merged = mergeAggregates(merged, a, log) + } + + // write the merged aggregate + err = writer.writeAggregate(merged, ctx.String("output")) + if err != nil { + log.Error("failed to write aggregate", "err", err) + return err + } + + return nil +} + +type ByFirst []aggregate + +func (a ByFirst) Len() int { return len(a) } +func (a ByFirst) Less(i, j int) bool { return a[i].First < a[j].First } +func (a ByFirst) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// checkBlockRanges checks that the block ranges don't have a gap +// this function assumes the aggregates are sorted by first block +func checkBlockRanges(aggregates []aggregate) error { + last := aggregates[0].Last + for _, a := range aggregates[1:] { + if a.First > last+1 { + return errors.New("gap in block ranges") + } + last = a.Last + } + return nil +} + +// mergeAggregates merges two aggregates +// this function assumes the aggregates are sorted by first block +func mergeAggregates(a1, a2 aggregate, log log.Logger) aggregate { + log.Info("merging", "a1", a1, "a2", a2) + // merge the results + for k, v := range a2.Results { + a1.Results[k] = v + } + a1.Last = a2.Last + log.Info("result", "aggregate", a1) + return a1 +} diff --git a/op-chain-ops/cmd/receipt-reference-builder/print.go b/op-chain-ops/cmd/receipt-reference-builder/print.go new file mode 100644 index 000000000000..4b823eac3b58 --- /dev/null +++ b/op-chain-ops/cmd/receipt-reference-builder/print.go @@ -0,0 +1,28 @@ +package main + +import ( + "github.com/ethereum/go-ethereum/log" + "github.com/urfave/cli/v2" +) + +var printCommand = &cli.Command{ + Name: "print", + Usage: "read an aggregate file and print it to stdout", + Flags: []cli.Flag{FilesFlag, InputFormatFlag}, + Action: print, +} + +func print(ctx *cli.Context) error { + log := log.New() + files := ctx.StringSlice("files") + r := formats[ctx.String("input-format")] + for _, f := range files { + a, err := r.readAggregate(f) + if err != nil { + log.Error("failed to read aggregate", "file", f, "err", err) + return err + } + log.Info("aggregate", "aggregate", a) + } + return nil +} diff --git a/op-chain-ops/cmd/receipt-reference-builder/pull.go b/op-chain-ops/cmd/receipt-reference-builder/pull.go new file mode 100644 index 000000000000..d6fa95eef33c --- /dev/null +++ b/op-chain-ops/cmd/receipt-reference-builder/pull.go @@ -0,0 +1,362 @@ +package main + +import ( + "context" + "errors" + "io" + "sync" + "time" + + "github.com/ethereum-optimism/optimism/op-service/dial" + "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" + "github.com/urfave/cli/v2" +) + +var pullCommand = &cli.Command{ + Name: "pull", + Usage: "Pull a range of blocks and extract nonces from all user deposits", + Flags: []cli.Flag{StartFlag, EndFlag, RPCURLFlag, WorkerFlag, OutputFlag, BackoffFlag, BatchSizeFlag, OutputFormatFlag}, + Action: pull, +} + +var MaxBatchSize uint64 = 100 + +// pull will pull a range of blocks and extract nonces from all user deposits +// it will start a number of workers to process blocks +// and runs an aggregation to collect the results +func pull(ctx *cli.Context) error { + timeout := 1 * time.Minute + log := log.New() + // create a new client + c, err := dial.DialEthClientWithTimeout( + ctx.Context, + timeout, + log, + ctx.String("rpc-url"), + ) + if err != nil { + log.Error("Failed to dial rollup client", "Err", err) + return err + } + + cid, err := c.ChainID(ctx.Context) + if err != nil { + log.Error("Failed to Get Chain ID", "Err", err) + return err + } + chainID := cid.Uint64() + + // record start time + startT := time.Now() + + resultChan := make(chan result) + errorChan := make(chan error) + + start := ctx.Uint64("start") + end := ctx.Uint64("end") + workers := ctx.Uint64("workers") + batchSize := ctx.Uint64("batch-size") + writer, ok := formats[ctx.String("output-format")] + if !ok { + log.Error("Invalid Output Format. Defaulting to JSON", "Format", ctx.String("output-format")) + writer = formats["json"] + } + + if batchSize > MaxBatchSize { + log.Warn("Batch Size Too Large, Reducing", "BatchSize", batchSize, "MaxBatchSize", MaxBatchSize) + batchSize = MaxBatchSize + } + + log.Info("Starting", "First", start, "Last", end, "Workers", workers, "BatchSize", batchSize) + + // first cut the work into ranges for batching + // and load the work into a channel + if batchSize > end-start { + log.Info("More Batch Size Than Required", "BatchSize", batchSize, "Blocks", end-start) + batchSize = end - start + } + batches := toBatches(start, end, batchSize) + workChan := make(chan batchRange, len(batches)) + for _, b := range batches { + workChan <- b + } + retryWorkChan := make(chan batchRange, len(batches)) + + // set the number of workers to the number of batches if there are more workers than batches + if workers > uint64(len(batches)) { + log.Info("More Workers Than Batches", "Workers", workers, "Batches", len(batches)) + workers = uint64(len(batches)) + } + + // start workers + wg := &sync.WaitGroup{} + for id := uint64(0); id < workers; id++ { + wg.Add(1) + go startWorker( + id, ctx, c, + workChan, + retryWorkChan, + resultChan, + errorChan, + log, + wg) + } + + // start a worker-waiter to end the aggregation + done := make(chan struct{}) + go func() { + wg.Wait() + log.Info("All Workers Finished") + done <- struct{}{} + }() + + // aggregate until the done signal is received + aggregateResults, err := startAggregator(resultChan, errorChan, done, log) + if err != nil { + log.Error("Errors Encountered During Aggregation. All Jobs Retried to Completion") + } + aggregateResults.First = start + aggregateResults.Last = end + aggregateResults.ChainID = chainID + + err = writer.writeAggregate(aggregateResults, ctx.String("output")) + if err != nil { + log.Error("Failed to Write Aggregate Results", "Err", err) + return err + } + + log.Info("Finished", "Duration", time.Since(startT)) + + return nil +} + +type batchRange struct { + Start uint64 + End uint64 +} + +// toBatches is a helper function to split a single large range into smaller batches +func toBatches(start, end, size uint64) []batchRange { + batches := []batchRange{} + for i := start; i < end; i += size { + if i+size > end { + batches = append(batches, batchRange{i, end}) + } else { + batches = append(batches, batchRange{i, i + size}) + } + } + return batches +} + +// splitBatchRange will split a batch range into two smaller ranges +// it is used to reduce pressure from large batches dynamically +func splitBatchRange(b batchRange) []batchRange { + size := b.End - b.Start + if size < 2 { + return []batchRange{b} + } + half := size / 2 + return []batchRange{ + {b.Start, b.Start + half}, + {b.Start + half, b.End}, + } +} + +// startAggregator will aggregate the results of the workers and return the aggregation once done +// it will receive results on the results channel, and chooses to include them in the aggregation if they are not empty +// it logs errors from the error channel and joins them as part of the return +func startAggregator(results chan result, errorChan chan error, done chan struct{}, log log.Logger) (aggregate, error) { + aggregateResults := aggregate{ + Results: make(map[uint64][]uint64), + } + var errs error + handled := 0 + errCount := 0 + for { + select { + case r := <-results: + handled += 1 + if len(r.Nonces) > 0 { + log.Info("Block Has Deposit Transactions", "Block", r.BlockNumber, "Nonces", r.Nonces, "Handled", handled) + aggregateResults.Results[r.BlockNumber] = r.Nonces + } + case err := <-errorChan: + log.Error("Got Error", "Err", err) + errCount += 1 + errs = errors.Join(errs, err) + case <-done: + // drain the results channel + // this is not very DRY, but it is the simplest way to do this + for len(results) > 0 { + r := <-results + handled += 1 + if len(r.Nonces) > 0 { + log.Info("Block Has Deposit Transactions", "Block", r.BlockNumber, "Nonces", r.Nonces, "Handled", handled) + aggregateResults.Results[r.BlockNumber] = r.Nonces + } + } + log.Info("Finished Aggregation", "ResultsHandled", handled, "ResultsMatched", len(aggregateResults.Results)) + return aggregateResults, errs + } + } +} + +// startWorker will start a worker to process blocks. +// callers should set up the wait group and call this function as a goroutine +// each worker will process blocks until the work channel is empty +// if the worker fails to process a work item, it will be returned to the work channel and the worker will sleep for the backoff duration +// workers return results to the results channel, from which they will be aggregated +func startWorker( + id uint64, + ctx *cli.Context, + c *ethclient.Client, + workChan chan batchRange, + retryWorkChan chan batchRange, + resultsChan chan result, + errorsChan chan error, + log log.Logger, + wg *sync.WaitGroup) { + + defer wg.Done() + log.Info("Starting Worker", "ID", id) + for { + select { + case <-ctx.Context.Done(): + log.Info("Context Done") + return + // retry work is work that has been tried at least once. it is prioritized equally to new work + case b := <-retryWorkChan: + log.Info("Got Retry Work", "Start", b.Start, "End", b.End) + doWork(*ctx, b, resultsChan, errorsChan, retryWorkChan, c, log) + case b := <-workChan: + log.Info("Got Work", "Start", b.Start, "End", b.End) + doWork(*ctx, b, resultsChan, errorsChan, retryWorkChan, c, log) + default: + log.Info("No More Work") + return + } + } +} + +func doWork(ctx cli.Context, b batchRange, resultsChan chan result, errorChan chan error, retryChan chan batchRange, c *ethclient.Client, log log.Logger) { + results, err := processBlockRange(ctx.Context, c, b, log) + if err != nil { + log.Error("Failed to Process Blocks") + errorChan <- err + newWork := splitBatchRange(b) + for _, w := range newWork { + retryChan <- w + } + log.Warn("Returned Failed Work to Retry Channel. Sleeping for Backoff Duration", "Backoff", ctx.Duration("backoff"), "Start", b.Start, "End", b.End) + time.Sleep(ctx.Duration("backoff")) + } else { + for _, r := range results { + resultsChan <- r + } + } +} + +// processBlockRange will process a range of blocks for user deposits +// it takes a batchRange and constructs a batchRPC request for the blocks +// it then processes each block's transactions for user deposits +// a list of results is returned for each block +func processBlockRange( + ctx context.Context, + c *ethclient.Client, + br batchRange, + log log.Logger) ([]result, error) { + + // turn the batch range into a list of block numbers + nums := []rpc.BlockNumber{} + for i := br.Start; i < br.End; i++ { + nums = append(nums, rpc.BlockNumber(i)) + } + + // get all blocks in the batch range + blocks, err := batchBlockByNumber(ctx, c, nums) + if err != nil { + log.Error("Failed to Get Batched Blocks", "Err", err) + return []result{}, err + } + log.Info("Got Blocks", "NumBlocks", len(blocks)) + + results := []result{} + // process each block for user deposits + for i := 0; i < len(blocks); i++ { + b := blocks[i] + matches := 0 + blockNumber := b.BlockID().Number + res := result{ + BlockNumber: blockNumber, + Nonces: []uint64{}, + } + // process each transaction in the block + for j := 0; j < len(b.Transactions); j++ { + tx := b.Transactions[j] + ok, err := checkTransaction(ctx, c, *tx, log) + if err != nil { + log.Error("Failed to Check Tx", "Err", err) + return []result{}, err + } + // if the transaction matches the criteria, add it to the results + if ok { + matches += 1 + res.Nonces = append(res.Nonces, *tx.EffectiveNonce()) + } + } + log.Info("Processed Block", "Block", blockNumber, "TxCount", len(b.Transactions), "UserDeposits", matches) + results = append(results, res) + } + return results, nil +} + +// batchBlockByNumber will batch a list of block numbers into a single batch rpc request +// it uses the iterative batch call to make the request +// and returns the results +func batchBlockByNumber(ctx context.Context, c *ethclient.Client, blockNumbers []rpc.BlockNumber) ([]*sources.RPCBlock, error) { + makeBlockByNumberRequest := func(blockNumber rpc.BlockNumber) (*sources.RPCBlock, rpc.BatchElem) { + out := new(sources.RPCBlock) + return out, rpc.BatchElem{ + Method: "eth_getBlockByNumber", + Args: []any{blockNumber, true}, + Result: &out, + } + } + batchReq := batching.NewIterativeBatchCall[rpc.BlockNumber, *sources.RPCBlock]( + blockNumbers, + makeBlockByNumberRequest, + c.Client().BatchCallContext, + c.Client().CallContext, + int(MaxBatchSize), + ) + for { + if err := batchReq.Fetch(ctx); err == io.EOF { + break + } else if err != nil { + log.Warn("Failed to Fetch Blocks", "Err", err, "Start", blockNumbers[0], "End", blockNumbers[len(blockNumbers)-1]) + return nil, err + } + } + return batchReq.Result() +} + +// checkTransaction will check if a transaction is a user deposit, and not initiated by the system address +func checkTransaction(ctx context.Context, c *ethclient.Client, tx types.Transaction, log log.Logger) (bool, error) { + from, err := types.Sender(types.LatestSignerForChainID(tx.ChainId()), &tx) + if err != nil { + log.Error("Failed to Get Sender", "Err", err) + return false, err + } + // we are filtering for deposit transactions which are not system transactions + if tx.Type() == depositType && + from != systemAddress { + log.Info("Got Transaction", "From", from, "Nonce", *tx.EffectiveNonce(), "Type", tx.Type()) + return true, nil + } + return false, nil +} diff --git a/op-chain-ops/cmd/receipt-reference-builder/readwrite.go b/op-chain-ops/cmd/receipt-reference-builder/readwrite.go new file mode 100644 index 000000000000..d556227c245e --- /dev/null +++ b/op-chain-ops/cmd/receipt-reference-builder/readwrite.go @@ -0,0 +1,78 @@ +package main + +import ( + "encoding/gob" + "encoding/json" + "fmt" + "os" +) + +type aggregateReaderWriter interface { + writeAggregate(a aggregate, o string) error + readAggregate(f string) (aggregate, error) +} + +type jsonAggregateReaderWriter struct{} + +// writeAggregate writes the aggregate to a file in json format +// if the output file is not specified, it will create a file based on the block range +func (w jsonAggregateReaderWriter) writeAggregate(a aggregate, o string) error { + if o == "" { + o = fmt.Sprintf("%d.%d-%d.json", a.ChainID, a.First, a.Last) + } + // write the results to a file + aggregateJson, err := json.Marshal(a) + if err != nil { + return err + } + err = os.WriteFile(o, aggregateJson, 0644) + return err +} + +// readAggregate reads the aggregate from a file in json format +func (w jsonAggregateReaderWriter) readAggregate(f string) (aggregate, error) { + // read the file + aggregateJson, err := os.ReadFile(f) + if err != nil { + return aggregate{}, err + } + var a aggregate + err = json.Unmarshal(aggregateJson, &a) + if err != nil { + return aggregate{}, err + } + return a, nil +} + +type gobAggregateReaderWriter struct{} + +// writeAggregate writes the aggregate to a file in gob format +// if the output file is not specified, it will creeate a file based on the block range +func (w gobAggregateReaderWriter) writeAggregate(a aggregate, o string) error { + if o == "" { + o = fmt.Sprintf("%d.%d-%d.gob", a.ChainID, a.First, a.Last) + } + file, err := os.Create(o) + if err != nil { + return err + } + defer file.Close() + + encoder := gob.NewEncoder(file) + err = encoder.Encode(&a) + return err +} + +// readAggregate reads the aggregate from a file in gob format +func (w gobAggregateReaderWriter) readAggregate(f string) (aggregate, error) { + file, err := os.Open(f) + if err != nil { + return aggregate{}, err + } + defer file.Close() + + a := aggregate{} + decoder := gob.NewDecoder(file) + err = decoder.Decode(&a) + return a, err +} diff --git a/op-chain-ops/cmd/registry-data/main.go b/op-chain-ops/cmd/registry-data/main.go index 75fc78dd93c5..1f33d65db8db 100644 --- a/op-chain-ops/cmd/registry-data/main.go +++ b/op-chain-ops/cmd/registry-data/main.go @@ -12,6 +12,7 @@ import ( opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/jsonutil" + oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" @@ -52,7 +53,8 @@ var ( ) func main() { - log.Root().SetHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(isatty.IsTerminal(os.Stderr.Fd())))) + color := isatty.IsTerminal(os.Stderr.Fd()) + oplog.SetGlobalLogHandler(log.NewTerminalHandler(os.Stderr, color)) app := &cli.App{ Name: "registry-data", diff --git a/op-chain-ops/deployer/deployer_test.go b/op-chain-ops/deployer/deployer_test.go index 8d42e6ccbcc3..0c937a768f9b 100644 --- a/op-chain-ops/deployer/deployer_test.go +++ b/op-chain-ops/deployer/deployer_test.go @@ -17,31 +17,31 @@ func TestCreate2Address(t *testing.T) { { name: "SafeL2", creatorAddress: common.HexToAddress("0x4e59b44847b379578588920cA78FbF26c0B4956C").Bytes(), - salt: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + salt: common.FromHex("0000000000000000000000000000000000000000000000000000000000000000"), expectedAddress: common.HexToAddress("0x3E5c63644E683549055b9Be8653de26E0B4CD36E"), }, { name: "MultiSendCallOnly", creatorAddress: common.HexToAddress("0x4e59b44847b379578588920cA78FbF26c0B4956C").Bytes(), - salt: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + salt: common.FromHex("0000000000000000000000000000000000000000000000000000000000000000"), expectedAddress: common.HexToAddress("0x40A2aCCbd92BCA938b02010E17A5b8929b49130D"), }, { name: "MultiSend", creatorAddress: common.HexToAddress("0x4e59b44847b379578588920cA78FbF26c0B4956C").Bytes(), - salt: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + salt: common.FromHex("0000000000000000000000000000000000000000000000000000000000000000"), expectedAddress: common.HexToAddress("0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761"), }, { name: "Permit2", creatorAddress: common.HexToAddress("0x4e59b44847b379578588920cA78FbF26c0B4956C").Bytes(), - salt: common.Hex2Bytes("0000000000000000000000000000000000000000d3af2663da51c10215000000"), + salt: common.FromHex("0000000000000000000000000000000000000000d3af2663da51c10215000000"), expectedAddress: common.HexToAddress("0x000000000022D473030F116dDEE9F6B43aC78BA3"), }, { name: "EntryPoint", creatorAddress: common.HexToAddress("0x4e59b44847b379578588920cA78FbF26c0B4956C").Bytes(), - salt: common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"), + salt: common.FromHex("0000000000000000000000000000000000000000000000000000000000000000"), expectedAddress: common.HexToAddress("0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"), }, } diff --git a/op-chain-ops/deployer/testdata.go b/op-chain-ops/deployer/testdata.go index 15d956583cb3..c7b802a139dc 100644 --- a/op-chain-ops/deployer/testdata.go +++ b/op-chain-ops/deployer/testdata.go @@ -9,15 +9,15 @@ import ( func getInitCode(contractName string) ([]byte, error) { switch contractName { case "SafeL2": - return common.Hex2Bytes("608060405234801561001057600080fd5b506001600481905550615cf880620000296000396000f3fe6080604052600436106101dc5760003560e01c8063affed0e011610102578063e19a9dd911610095578063f08a032311610064578063f08a032314611647578063f698da2514611698578063f8dc5dd9146116c3578063ffa1ad741461173e57610231565b8063e19a9dd91461139b578063e318b52b146113ec578063e75235b81461147d578063e86637db146114a857610231565b8063cc2f8452116100d1578063cc2f8452146110e8578063d4d9bdcd146111b5578063d8d11f78146111f0578063e009cfde1461132a57610231565b8063affed0e014610d94578063b4faba0914610dbf578063b63e800d14610ea7578063c4ca3a9c1461101757610231565b80635624b25b1161017a5780636a761202116101495780636a761202146109945780637d83297414610b50578063934f3a1114610bbf578063a0e67e2b14610d2857610231565b80635624b25b146107fb5780635ae6bd37146108b9578063610b592514610908578063694e80c31461095957610231565b80632f54bf6e116101b65780632f54bf6e146104d35780633408e4701461053a578063468721a7146105655780635229073f1461067a57610231565b80630d582f131461029e57806312fb68e0146102f95780632d9ad53d1461046c57610231565b36610231573373ffffffffffffffffffffffffffffffffffffffff167f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d346040518082815260200191505060405180910390a2005b34801561023d57600080fd5b5060007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b905080548061027257600080f35b36600080373360601b365260008060143601600080855af13d6000803e80610299573d6000fd5b3d6000f35b3480156102aa57600080fd5b506102f7600480360360408110156102c157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506117ce565b005b34801561030557600080fd5b5061046a6004803603608081101561031c57600080fd5b81019080803590602001909291908035906020019064010000000081111561034357600080fd5b82018360208201111561035557600080fd5b8035906020019184600183028401116401000000008311171561037757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803590602001906401000000008111156103da57600080fd5b8201836020820111156103ec57600080fd5b8035906020019184600183028401116401000000008311171561040e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190929190505050611bbe565b005b34801561047857600080fd5b506104bb6004803603602081101561048f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612440565b60405180821515815260200191505060405180910390f35b3480156104df57600080fd5b50610522600480360360208110156104f657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612512565b60405180821515815260200191505060405180910390f35b34801561054657600080fd5b5061054f6125e4565b6040518082815260200191505060405180910390f35b34801561057157600080fd5b506106626004803603608081101561058857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156105cf57600080fd5b8201836020820111156105e157600080fd5b8035906020019184600183028401116401000000008311171561060357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff1690602001909291905050506125f1565b60405180821515815260200191505060405180910390f35b34801561068657600080fd5b506107776004803603608081101561069d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156106e457600080fd5b8201836020820111156106f657600080fd5b8035906020019184600183028401116401000000008311171561071857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff1690602001909291905050506126fc565b60405180831515815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107bf5780820151818401526020810190506107a4565b50505050905090810190601f1680156107ec5780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b34801561080757600080fd5b5061083e6004803603604081101561081e57600080fd5b810190808035906020019092919080359060200190929190505050612732565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561087e578082015181840152602081019050610863565b50505050905090810190601f1680156108ab5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156108c557600080fd5b506108f2600480360360208110156108dc57600080fd5b81019080803590602001909291905050506127b9565b6040518082815260200191505060405180910390f35b34801561091457600080fd5b506109576004803603602081101561092b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506127d1565b005b34801561096557600080fd5b506109926004803603602081101561097c57600080fd5b8101908080359060200190929190505050612b63565b005b610b3860048036036101408110156109ab57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156109f257600080fd5b820183602082011115610a0457600080fd5b80359060200191846001830284011164010000000083111715610a2657600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610ab257600080fd5b820183602082011115610ac457600080fd5b80359060200191846001830284011164010000000083111715610ae657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612c9d565b60405180821515815260200191505060405180910390f35b348015610b5c57600080fd5b50610ba960048036036040811015610b7357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612edc565b6040518082815260200191505060405180910390f35b348015610bcb57600080fd5b50610d2660048036036060811015610be257600080fd5b810190808035906020019092919080359060200190640100000000811115610c0957600080fd5b820183602082011115610c1b57600080fd5b80359060200191846001830284011164010000000083111715610c3d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190640100000000811115610ca057600080fd5b820183602082011115610cb257600080fd5b80359060200191846001830284011164010000000083111715610cd457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612f01565b005b348015610d3457600080fd5b50610d3d612f90565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610d80578082015181840152602081019050610d65565b505050509050019250505060405180910390f35b348015610da057600080fd5b50610da9613139565b6040518082815260200191505060405180910390f35b348015610dcb57600080fd5b50610ea560048036036040811015610de257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610e1f57600080fd5b820183602082011115610e3157600080fd5b80359060200191846001830284011164010000000083111715610e5357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061313f565b005b348015610eb357600080fd5b506110156004803603610100811015610ecb57600080fd5b8101908080359060200190640100000000811115610ee857600080fd5b820183602082011115610efa57600080fd5b80359060200191846020830284011164010000000083111715610f1c57600080fd5b909192939192939080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610f6757600080fd5b820183602082011115610f7957600080fd5b80359060200191846001830284011164010000000083111715610f9b57600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613161565b005b34801561102357600080fd5b506110d26004803603608081101561103a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561108157600080fd5b82018360208201111561109357600080fd5b803590602001918460018302840111640100000000831117156110b557600080fd5b9091929391929390803560ff16906020019092919050505061331f565b6040518082815260200191505060405180910390f35b3480156110f457600080fd5b506111416004803603604081101561110b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613447565b60405180806020018373ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019060200280838360005b838110156111a0578082015181840152602081019050611185565b50505050905001935050505060405180910390f35b3480156111c157600080fd5b506111ee600480360360208110156111d857600080fd5b8101908080359060200190929190505050613639565b005b3480156111fc57600080fd5b50611314600480360361014081101561121457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561125b57600080fd5b82018360208201111561126d57600080fd5b8035906020019184600183028401116401000000008311171561128f57600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506137d8565b6040518082815260200191505060405180910390f35b34801561133657600080fd5b506113996004803603604081101561134d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613805565b005b3480156113a757600080fd5b506113ea600480360360208110156113be57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613b96565b005b3480156113f857600080fd5b5061147b6004803603606081101561140f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613c1a565b005b34801561148957600080fd5b5061149261428c565b6040518082815260200191505060405180910390f35b3480156114b457600080fd5b506115cc60048036036101408110156114cc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561151357600080fd5b82018360208201111561152557600080fd5b8035906020019184600183028401116401000000008311171561154757600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050614296565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561160c5780820151818401526020810190506115f1565b50505050905090810190601f1680156116395780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561165357600080fd5b506116966004803603602081101561166a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061443e565b005b3480156116a457600080fd5b506116ad61449f565b6040518082815260200191505060405180910390f35b3480156116cf57600080fd5b5061173c600480360360608110156116e657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061451d565b005b34801561174a57600080fd5b50611753614950565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015611793578082015181840152602081019050611778565b50505050905090810190601f1680156117c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6117d6614989565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156118405750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b801561187857503073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b6118ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146119eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506003600081548092919060010191905055507f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2682604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18060045414611bba57611bb981612b63565b5b5050565b611bd2604182614a2c90919063ffffffff16565b82511015611c48576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000808060008060005b8681101561243457611c648882614a66565b80945081955082965050505060008460ff16141561206d578260001c9450611c96604188614a2c90919063ffffffff16565b8260001c1015611d0e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8751611d2760208460001c614a9590919063ffffffff16565b1115611d9b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006020838a01015190508851611dd182611dc360208760001c614a9590919063ffffffff16565b614a9590919063ffffffff16565b1115611e45576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60606020848b010190506320c13b0b60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168773ffffffffffffffffffffffffffffffffffffffff166320c13b0b8d846040518363ffffffff1660e01b8152600401808060200180602001838103835285818151815260200191508051906020019080838360005b83811015611ee7578082015181840152602081019050611ecc565b50505050905090810190601f168015611f145780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015611f4d578082015181840152602081019050611f32565b50505050905090810190601f168015611f7a5780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015611f9957600080fd5b505afa158015611fad573d6000803e3d6000fd5b505050506040513d6020811015611fc357600080fd5b81019080805190602001909291905050507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612066576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b50506122b2565b60018460ff161415612181578260001c94508473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061210a57506000600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008c81526020019081526020016000205414155b61217c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6122b1565b601e8460ff1611156122495760018a60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c018281526020019150506040516020818303038152906040528051906020012060048603858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612238573d6000803e3d6000fd5b5050506020604051035194506122b0565b60018a85858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156122a3573d6000803e3d6000fd5b5050506020604051035194505b5b5b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161180156123795750600073ffffffffffffffffffffffffffffffffffffffff16600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b80156123b25750600173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b612424576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323600000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8495508080600101915050611c52565b50505050505050505050565b60008173ffffffffffffffffffffffffffffffffffffffff16600173ffffffffffffffffffffffffffffffffffffffff161415801561250b5750600073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156125dd5750600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000804690508091505090565b60007fb648d3644f584ed1c2232d53c46d87e693586486ad0d1175f8656013110b714e3386868686604051808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018060200183600181111561266b57fe5b8152602001828103825284818151815260200191508051906020019080838360005b838110156126a857808201518184015260208101905061268d565b50505050905090810190601f1680156126d55780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a16126f285858585614ab4565b9050949350505050565b6000606061270c868686866125f1565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b606060006020830267ffffffffffffffff8111801561275057600080fd5b506040519080825280601f01601f1916602001820160405280156127835781602001600182028036833780820191505090505b50905060005b838110156127ae57808501548060208302602085010152508080600101915050612789565b508091505092915050565b60076020528060005260406000206000915090505481565b6127d9614989565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156128435750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b6128b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146129b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844081604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b612b6b614989565b600354811115612be3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001811015612c5a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b806004819055507f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c936004546040518082815260200191505060405180910390a150565b6000606060055433600454604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405160208183030381529060405290507f66753cd2356569ee081232e3be8909b950e0a76c1f8460c3a5e3c2be32b11bed8d8d8d8d8d8d8d8d8d8d8d8c604051808d73ffffffffffffffffffffffffffffffffffffffff1681526020018c8152602001806020018a6001811115612d5057fe5b81526020018981526020018881526020018781526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff168152602001806020018060200184810384528e8e82818152602001925080828437600081840152601f19601f820116905080830192505050848103835286818151815260200191508051906020019080838360005b83811015612e0a578082015181840152602081019050612def565b50505050905090810190601f168015612e375780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b83811015612e70578082015181840152602081019050612e55565b50505050905090810190601f168015612e9d5780820380516001836020036101000a031916815260200191505b509f5050505050505050505050505050505060405180910390a1612eca8d8d8d8d8d8d8d8d8d8d8d614c9a565b9150509b9a5050505050505050505050565b6008602052816000526040600020602052806000526040600020600091509150505481565b6000600454905060008111612f7e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b612f8a84848484611bbe565b50505050565b6060600060035467ffffffffffffffff81118015612fad57600080fd5b50604051908082528060200260200182016040528015612fdc5781602001602082028036833780820191505090505b50905060008060026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614613130578083838151811061308757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508180600101925050613046565b82935050505090565b60055481565b600080825160208401855af4806000523d6020523d600060403e60403d016000fd5b6131ac8a8a80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050896151d7565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146131ea576131e9846156d7565b5b6132388787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050615706565b60008211156132525761325082600060018685615941565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b8960405180806020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281038252878782818152602001925060200280828437600081840152601f19601f820116905080830192505050965050505050505060405180910390a250505050505050505050565b6000805a9050613376878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050865a615b47565b61337f57600080fd5b60005a8203905080604051602001808281526020019150506040516020818303038152906040526040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561340c5780820151818401526020810190506133f1565b50505050905090810190601f1680156134395780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b606060008267ffffffffffffffff8111801561346257600080fd5b506040519080825280602002602001820160405280156134915781602001602082028036833780820191505090505b509150600080600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156135645750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561356f57508482105b1561362a578084838151811061358157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081806001019250506134fa565b80925081845250509250929050565b600073ffffffffffffffffffffffffffffffffffffffff16600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561373b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff16817ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c60405160405180910390a350565b60006137ed8c8c8c8c8c8c8c8c8c8c8c614296565b8051906020012090509b9a5050505050505050505050565b61380d614989565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156138775750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b6138e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146139e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427681604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15050565b613b9e614989565b60007f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b90508181557f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa282604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15050565b613c22614989565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015613c8c5750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b8015613cc457503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b613d36576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613e37576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015613ea15750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b613f13576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614013576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf82604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a17f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2681604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050565b6000600454905090565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d60405180838380828437808301925050509250505060405180910390208c8c8c8c8c8c8c604051602001808c81526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a815260200189815260200188600181111561432757fe5b81526020018781526020018681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019b505050505050505050505050604051602081830303815290604052805190602001209050601960f81b600160f81b6143b361449f565b8360405160200180857effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152600101847effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526001018381526020018281526020019450505050506040516020818303038152906040529150509b9a5050505050505050505050565b614446614989565b61444f816156d7565b7f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b081604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b60007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a7946921860001b6144cd6125e4565b30604051602001808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405160208183030381529060405280519060200120905090565b614525614989565b8060016003540310156145a0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415801561460a5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b61467c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461477c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600360008154809291906001900391905055507ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf82604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1806004541461494b5761494a81612b63565b5b505050565b6040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614614a2a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b600080831415614a3f5760009050614a60565b6000828402905082848281614a5057fe5b0414614a5b57600080fd5b809150505b92915050565b60008060008360410260208101860151925060408101860151915060ff60418201870151169350509250925092565b600080828401905083811015614aaa57600080fd5b8091505092915050565b6000600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015614b7f5750600073ffffffffffffffffffffffffffffffffffffffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b614bf1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b614bfe858585855a615b47565b90508015614c4e573373ffffffffffffffffffffffffffffffffffffffff167f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb860405160405180910390a2614c92565b3373ffffffffffffffffffffffffffffffffffffffff167facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37560405160405180910390a25b949350505050565b6000806000614cb48e8e8e8e8e8e8e8e8e8e600554614296565b905060056000815480929190600101919050555080805190602001209150614cdd828286612f01565b506000614ce8615b93565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614614ece578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b8152600401808d73ffffffffffffffffffffffffffffffffffffffff1681526020018c8152602001806020018a6001811115614d8b57fe5b81526020018981526020018881526020018781526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff168152602001806020018473ffffffffffffffffffffffffffffffffffffffff16815260200183810383528d8d82818152602001925080828437600081840152601f19601f820116905080830192505050838103825285818151815260200191508051906020019080838360005b83811015614e5d578082015181840152602081019050614e42565b50505050905090810190601f168015614e8a5780820380516001836020036101000a031916815260200191505b509e505050505050505050505050505050600060405180830381600087803b158015614eb557600080fd5b505af1158015614ec9573d6000803e3d6000fd5b505050505b6101f4614ef56109c48b01603f60408d0281614ee657fe5b04615bc490919063ffffffff16565b015a1015614f6b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60005a9050614fd48f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e60008d14614fc9578e614fcf565b6109c45a035b615b47565b9350614fe95a82615bde90919063ffffffff16565b90508380614ff8575060008a14155b80615004575060008814155b615076576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000808911156150905761508d828b8b8b8b615941565b90505b84156150da577f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e8482604051808381526020018281526020019250505060405180910390a161511a565b7f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d238482604051808381526020018281526020019250505060405180910390a15b5050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146151c6578073ffffffffffffffffffffffffffffffffffffffff16639327136883856040518363ffffffff1660e01b815260040180838152602001821515815260200192505050600060405180830381600087803b1580156151ad57600080fd5b505af11580156151c1573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b60006004541461524f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b81518111156152c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600181101561533d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006001905060005b835181101561564357600084828151811061535d57fe5b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156153d15750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561540957503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561544157508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b6154b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146155b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b80600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550809250508080600101915050615346565b506001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550825160038190555081600481905550505050565b60007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b90508181555050565b600073ffffffffffffffffffffffffffffffffffffffff1660016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614615808576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001806000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461593d576158ca8260008360015a615b47565b61593c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5050565b600080600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461597e5782615980565b325b9050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415615a98576159ea3a86106159c7573a6159c9565b855b6159dc888a614a9590919063ffffffff16565b614a2c90919063ffffffff16565b91508073ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050615a93576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b615b3d565b615abd85615aaf888a614a9590919063ffffffff16565b614a2c90919063ffffffff16565b9150615aca848284615bfe565b615b3c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5095945050505050565b6000600180811115615b5557fe5b836001811115615b6157fe5b1415615b7a576000808551602087018986f49050615b8a565b600080855160208701888a87f190505b95945050505050565b6000807f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b9050805491505090565b600081831015615bd45781615bd6565b825b905092915050565b600082821115615bed57600080fd5b600082840390508091505092915050565b60008063a9059cbb8484604051602401808373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050602060008251602084016000896127105a03f13d60008114615ca55760208114615cad5760009350615cb8565b819350615cb8565b600051158215171593505b505050939250505056fea2646970667358221220047fac33099ca576d1c4f1ac6a8abdb0396e42ad6a397d2cb2f4dc1624cc0c5b64736f6c63430007060033"), nil + return common.FromHex("608060405234801561001057600080fd5b506001600481905550615cf880620000296000396000f3fe6080604052600436106101dc5760003560e01c8063affed0e011610102578063e19a9dd911610095578063f08a032311610064578063f08a032314611647578063f698da2514611698578063f8dc5dd9146116c3578063ffa1ad741461173e57610231565b8063e19a9dd91461139b578063e318b52b146113ec578063e75235b81461147d578063e86637db146114a857610231565b8063cc2f8452116100d1578063cc2f8452146110e8578063d4d9bdcd146111b5578063d8d11f78146111f0578063e009cfde1461132a57610231565b8063affed0e014610d94578063b4faba0914610dbf578063b63e800d14610ea7578063c4ca3a9c1461101757610231565b80635624b25b1161017a5780636a761202116101495780636a761202146109945780637d83297414610b50578063934f3a1114610bbf578063a0e67e2b14610d2857610231565b80635624b25b146107fb5780635ae6bd37146108b9578063610b592514610908578063694e80c31461095957610231565b80632f54bf6e116101b65780632f54bf6e146104d35780633408e4701461053a578063468721a7146105655780635229073f1461067a57610231565b80630d582f131461029e57806312fb68e0146102f95780632d9ad53d1461046c57610231565b36610231573373ffffffffffffffffffffffffffffffffffffffff167f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d346040518082815260200191505060405180910390a2005b34801561023d57600080fd5b5060007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b905080548061027257600080f35b36600080373360601b365260008060143601600080855af13d6000803e80610299573d6000fd5b3d6000f35b3480156102aa57600080fd5b506102f7600480360360408110156102c157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506117ce565b005b34801561030557600080fd5b5061046a6004803603608081101561031c57600080fd5b81019080803590602001909291908035906020019064010000000081111561034357600080fd5b82018360208201111561035557600080fd5b8035906020019184600183028401116401000000008311171561037757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803590602001906401000000008111156103da57600080fd5b8201836020820111156103ec57600080fd5b8035906020019184600183028401116401000000008311171561040e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190929190505050611bbe565b005b34801561047857600080fd5b506104bb6004803603602081101561048f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612440565b60405180821515815260200191505060405180910390f35b3480156104df57600080fd5b50610522600480360360208110156104f657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612512565b60405180821515815260200191505060405180910390f35b34801561054657600080fd5b5061054f6125e4565b6040518082815260200191505060405180910390f35b34801561057157600080fd5b506106626004803603608081101561058857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156105cf57600080fd5b8201836020820111156105e157600080fd5b8035906020019184600183028401116401000000008311171561060357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff1690602001909291905050506125f1565b60405180821515815260200191505060405180910390f35b34801561068657600080fd5b506107776004803603608081101561069d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156106e457600080fd5b8201836020820111156106f657600080fd5b8035906020019184600183028401116401000000008311171561071857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803560ff1690602001909291905050506126fc565b60405180831515815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107bf5780820151818401526020810190506107a4565b50505050905090810190601f1680156107ec5780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b34801561080757600080fd5b5061083e6004803603604081101561081e57600080fd5b810190808035906020019092919080359060200190929190505050612732565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561087e578082015181840152602081019050610863565b50505050905090810190601f1680156108ab5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156108c557600080fd5b506108f2600480360360208110156108dc57600080fd5b81019080803590602001909291905050506127b9565b6040518082815260200191505060405180910390f35b34801561091457600080fd5b506109576004803603602081101561092b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506127d1565b005b34801561096557600080fd5b506109926004803603602081101561097c57600080fd5b8101908080359060200190929190505050612b63565b005b610b3860048036036101408110156109ab57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156109f257600080fd5b820183602082011115610a0457600080fd5b80359060200191846001830284011164010000000083111715610a2657600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610ab257600080fd5b820183602082011115610ac457600080fd5b80359060200191846001830284011164010000000083111715610ae657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612c9d565b60405180821515815260200191505060405180910390f35b348015610b5c57600080fd5b50610ba960048036036040811015610b7357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612edc565b6040518082815260200191505060405180910390f35b348015610bcb57600080fd5b50610d2660048036036060811015610be257600080fd5b810190808035906020019092919080359060200190640100000000811115610c0957600080fd5b820183602082011115610c1b57600080fd5b80359060200191846001830284011164010000000083111715610c3d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190640100000000811115610ca057600080fd5b820183602082011115610cb257600080fd5b80359060200191846001830284011164010000000083111715610cd457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612f01565b005b348015610d3457600080fd5b50610d3d612f90565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610d80578082015181840152602081019050610d65565b505050509050019250505060405180910390f35b348015610da057600080fd5b50610da9613139565b6040518082815260200191505060405180910390f35b348015610dcb57600080fd5b50610ea560048036036040811015610de257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610e1f57600080fd5b820183602082011115610e3157600080fd5b80359060200191846001830284011164010000000083111715610e5357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061313f565b005b348015610eb357600080fd5b506110156004803603610100811015610ecb57600080fd5b8101908080359060200190640100000000811115610ee857600080fd5b820183602082011115610efa57600080fd5b80359060200191846020830284011164010000000083111715610f1c57600080fd5b909192939192939080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115610f6757600080fd5b820183602082011115610f7957600080fd5b80359060200191846001830284011164010000000083111715610f9b57600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613161565b005b34801561102357600080fd5b506110d26004803603608081101561103a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561108157600080fd5b82018360208201111561109357600080fd5b803590602001918460018302840111640100000000831117156110b557600080fd5b9091929391929390803560ff16906020019092919050505061331f565b6040518082815260200191505060405180910390f35b3480156110f457600080fd5b506111416004803603604081101561110b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613447565b60405180806020018373ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818151815260200191508051906020019060200280838360005b838110156111a0578082015181840152602081019050611185565b50505050905001935050505060405180910390f35b3480156111c157600080fd5b506111ee600480360360208110156111d857600080fd5b8101908080359060200190929190505050613639565b005b3480156111fc57600080fd5b50611314600480360361014081101561121457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561125b57600080fd5b82018360208201111561126d57600080fd5b8035906020019184600183028401116401000000008311171561128f57600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506137d8565b6040518082815260200191505060405180910390f35b34801561133657600080fd5b506113996004803603604081101561134d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613805565b005b3480156113a757600080fd5b506113ea600480360360208110156113be57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613b96565b005b3480156113f857600080fd5b5061147b6004803603606081101561140f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613c1a565b005b34801561148957600080fd5b5061149261428c565b6040518082815260200191505060405180910390f35b3480156114b457600080fd5b506115cc60048036036101408110156114cc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561151357600080fd5b82018360208201111561152557600080fd5b8035906020019184600183028401116401000000008311171561154757600080fd5b9091929391929390803560ff169060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050614296565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561160c5780820151818401526020810190506115f1565b50505050905090810190601f1680156116395780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561165357600080fd5b506116966004803603602081101561166a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061443e565b005b3480156116a457600080fd5b506116ad61449f565b6040518082815260200191505060405180910390f35b3480156116cf57600080fd5b5061173c600480360360608110156116e657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061451d565b005b34801561174a57600080fd5b50611753614950565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015611793578082015181840152602081019050611778565b50505050905090810190601f1680156117c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6117d6614989565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156118405750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b801561187857503073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b6118ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146119eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506003600081548092919060010191905055507f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2682604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18060045414611bba57611bb981612b63565b5b5050565b611bd2604182614a2c90919063ffffffff16565b82511015611c48576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000808060008060005b8681101561243457611c648882614a66565b80945081955082965050505060008460ff16141561206d578260001c9450611c96604188614a2c90919063ffffffff16565b8260001c1015611d0e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8751611d2760208460001c614a9590919063ffffffff16565b1115611d9b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006020838a01015190508851611dd182611dc360208760001c614a9590919063ffffffff16565b614a9590919063ffffffff16565b1115611e45576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60606020848b010190506320c13b0b60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168773ffffffffffffffffffffffffffffffffffffffff166320c13b0b8d846040518363ffffffff1660e01b8152600401808060200180602001838103835285818151815260200191508051906020019080838360005b83811015611ee7578082015181840152602081019050611ecc565b50505050905090810190601f168015611f145780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019080838360005b83811015611f4d578082015181840152602081019050611f32565b50505050905090810190601f168015611f7a5780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015611f9957600080fd5b505afa158015611fad573d6000803e3d6000fd5b505050506040513d6020811015611fc357600080fd5b81019080805190602001909291905050507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612066576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b50506122b2565b60018460ff161415612181578260001c94508473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061210a57506000600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008c81526020019081526020016000205414155b61217c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6122b1565b601e8460ff1611156122495760018a60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c018281526020019150506040516020818303038152906040528051906020012060048603858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015612238573d6000803e3d6000fd5b5050506020604051035194506122b0565b60018a85858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156122a3573d6000803e3d6000fd5b5050506020604051035194505b5b5b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161180156123795750600073ffffffffffffffffffffffffffffffffffffffff16600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b80156123b25750600173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614155b612424576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330323600000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8495508080600101915050611c52565b50505050505050505050565b60008173ffffffffffffffffffffffffffffffffffffffff16600173ffffffffffffffffffffffffffffffffffffffff161415801561250b5750600073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141580156125dd5750600073ffffffffffffffffffffffffffffffffffffffff16600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b9050919050565b6000804690508091505090565b60007fb648d3644f584ed1c2232d53c46d87e693586486ad0d1175f8656013110b714e3386868686604051808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018060200183600181111561266b57fe5b8152602001828103825284818151815260200191508051906020019080838360005b838110156126a857808201518184015260208101905061268d565b50505050905090810190601f1680156126d55780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a16126f285858585614ab4565b9050949350505050565b6000606061270c868686866125f1565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b606060006020830267ffffffffffffffff8111801561275057600080fd5b506040519080825280601f01601f1916602001820160405280156127835781602001600182028036833780820191505090505b50905060005b838110156127ae57808501548060208302602085010152508080600101915050612789565b508091505092915050565b60076020528060005260406000206000915090505481565b6127d9614989565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156128435750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b6128b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146129b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844081604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b612b6b614989565b600354811115612be3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001811015612c5a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b806004819055507f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c936004546040518082815260200191505060405180910390a150565b6000606060055433600454604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405160208183030381529060405290507f66753cd2356569ee081232e3be8909b950e0a76c1f8460c3a5e3c2be32b11bed8d8d8d8d8d8d8d8d8d8d8d8c604051808d73ffffffffffffffffffffffffffffffffffffffff1681526020018c8152602001806020018a6001811115612d5057fe5b81526020018981526020018881526020018781526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff168152602001806020018060200184810384528e8e82818152602001925080828437600081840152601f19601f820116905080830192505050848103835286818151815260200191508051906020019080838360005b83811015612e0a578082015181840152602081019050612def565b50505050905090810190601f168015612e375780820380516001836020036101000a031916815260200191505b50848103825285818151815260200191508051906020019080838360005b83811015612e70578082015181840152602081019050612e55565b50505050905090810190601f168015612e9d5780820380516001836020036101000a031916815260200191505b509f5050505050505050505050505050505060405180910390a1612eca8d8d8d8d8d8d8d8d8d8d8d614c9a565b9150509b9a5050505050505050505050565b6008602052816000526040600020602052806000526040600020600091509150505481565b6000600454905060008111612f7e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b612f8a84848484611bbe565b50505050565b6060600060035467ffffffffffffffff81118015612fad57600080fd5b50604051908082528060200260200182016040528015612fdc5781602001602082028036833780820191505090505b50905060008060026000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614613130578083838151811061308757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508180600101925050613046565b82935050505090565b60055481565b600080825160208401855af4806000523d6020523d600060403e60403d016000fd5b6131ac8a8a80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050896151d7565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146131ea576131e9846156d7565b5b6132388787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050615706565b60008211156132525761325082600060018685615941565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b8960405180806020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281038252878782818152602001925060200280828437600081840152601f19601f820116905080830192505050965050505050505060405180910390a250505050505050505050565b6000805a9050613376878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050865a615b47565b61337f57600080fd5b60005a8203905080604051602001808281526020019150506040516020818303038152906040526040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561340c5780820151818401526020810190506133f1565b50505050905090810190601f1680156134395780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b606060008267ffffffffffffffff8111801561346257600080fd5b506040519080825280602002602001820160405280156134915781602001602082028036833780820191505090505b509150600080600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156135645750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561356f57508482105b1561362a578084838151811061358157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081806001019250506134fa565b80925081845250509250929050565b600073ffffffffffffffffffffffffffffffffffffffff16600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561373b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000838152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff16817ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c60405160405180910390a350565b60006137ed8c8c8c8c8c8c8c8c8c8c8c614296565b8051906020012090509b9a5050505050505050505050565b61380d614989565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156138775750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b6138e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146139e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427681604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15050565b613b9e614989565b60007f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b90508181557f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa282604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15050565b613c22614989565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015613c8c5750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b8015613cc457503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b613d36576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613e37576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614158015613ea15750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b613f13576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614614013576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf82604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a17f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2681604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1505050565b6000600454905090565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d60405180838380828437808301925050509250505060405180910390208c8c8c8c8c8c8c604051602001808c81526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a815260200189815260200188600181111561432757fe5b81526020018781526020018681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019b505050505050505050505050604051602081830303815290604052805190602001209050601960f81b600160f81b6143b361449f565b8360405160200180857effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152600101847effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526001018381526020018281526020019450505050506040516020818303038152906040529150509b9a5050505050505050505050565b614446614989565b61444f816156d7565b7f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b081604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b60007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a7946921860001b6144cd6125e4565b30604051602001808481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405160208183030381529060405280519060200120905090565b614525614989565b8060016003540310156145a0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415801561460a5750600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b61467c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461477c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303500000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600360008154809291906001900391905055507ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf82604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1806004541461494b5761494a81612b63565b5b505050565b6040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614614a2a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330333100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b600080831415614a3f5760009050614a60565b6000828402905082848281614a5057fe5b0414614a5b57600080fd5b809150505b92915050565b60008060008360410260208101860151925060408101860151915060ff60418201870151169350509250925092565b600080828401905083811015614aaa57600080fd5b8091505092915050565b6000600173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015614b7f5750600073ffffffffffffffffffffffffffffffffffffffff16600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b614bf1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b614bfe858585855a615b47565b90508015614c4e573373ffffffffffffffffffffffffffffffffffffffff167f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb860405160405180910390a2614c92565b3373ffffffffffffffffffffffffffffffffffffffff167facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37560405160405180910390a25b949350505050565b6000806000614cb48e8e8e8e8e8e8e8e8e8e600554614296565b905060056000815480929190600101919050555080805190602001209150614cdd828286612f01565b506000614ce8615b93565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614614ece578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b8152600401808d73ffffffffffffffffffffffffffffffffffffffff1681526020018c8152602001806020018a6001811115614d8b57fe5b81526020018981526020018881526020018781526020018673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff168152602001806020018473ffffffffffffffffffffffffffffffffffffffff16815260200183810383528d8d82818152602001925080828437600081840152601f19601f820116905080830192505050838103825285818151815260200191508051906020019080838360005b83811015614e5d578082015181840152602081019050614e42565b50505050905090810190601f168015614e8a5780820380516001836020036101000a031916815260200191505b509e505050505050505050505050505050600060405180830381600087803b158015614eb557600080fd5b505af1158015614ec9573d6000803e3d6000fd5b505050505b6101f4614ef56109c48b01603f60408d0281614ee657fe5b04615bc490919063ffffffff16565b015a1015614f6b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60005a9050614fd48f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e60008d14614fc9578e614fcf565b6109c45a035b615b47565b9350614fe95a82615bde90919063ffffffff16565b90508380614ff8575060008a14155b80615004575060008814155b615076576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000808911156150905761508d828b8b8b8b615941565b90505b84156150da577f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e8482604051808381526020018281526020019250505060405180910390a161511a565b7f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d238482604051808381526020018281526020019250505060405180910390a15b5050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146151c6578073ffffffffffffffffffffffffffffffffffffffff16639327136883856040518363ffffffff1660e01b815260040180838152602001821515815260200192505050600060405180830381600087803b1580156151ad57600080fd5b505af11580156151c1573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b60006004541461524f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b81518111156152c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600181101561533d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006001905060005b835181101561564357600084828151811061535d57fe5b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156153d15750600173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561540957503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b801561544157508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b6154b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303300000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146155b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475332303400000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b80600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550809250508080600101915050615346565b506001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550825160038190555081600481905550505050565b60007f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d560001b90508181555050565b600073ffffffffffffffffffffffffffffffffffffffff1660016000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614615808576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475331303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001806000600173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461593d576158ca8260008360015a615b47565b61593c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330303000000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5050565b600080600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461597e5782615980565b325b9050600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415615a98576159ea3a86106159c7573a6159c9565b855b6159dc888a614a9590919063ffffffff16565b614a2c90919063ffffffff16565b91508073ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050615a93576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313100000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b615b3d565b615abd85615aaf888a614a9590919063ffffffff16565b614a2c90919063ffffffff16565b9150615aca848284615bfe565b615b3c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f475330313200000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b5b5095945050505050565b6000600180811115615b5557fe5b836001811115615b6157fe5b1415615b7a576000808551602087018986f49050615b8a565b600080855160208701888a87f190505b95945050505050565b6000807f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c860001b9050805491505090565b600081831015615bd45781615bd6565b825b905092915050565b600082821115615bed57600080fd5b600082840390508091505092915050565b60008063a9059cbb8484604051602401808373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050602060008251602084016000896127105a03f13d60008114615ca55760208114615cad5760009350615cb8565b819350615cb8565b600051158215171593505b505050939250505056fea2646970667358221220047fac33099ca576d1c4f1ac6a8abdb0396e42ad6a397d2cb2f4dc1624cc0c5b64736f6c63430007060033"), nil case "MultiSendCallOnly": - return common.Hex2Bytes("608060405234801561001057600080fd5b5061019a806100206000396000f3fe60806040526004361061001e5760003560e01c80638d80ff0a14610023575b600080fd5b6100dc6004803603602081101561003957600080fd5b810190808035906020019064010000000081111561005657600080fd5b82018360208201111561006857600080fd5b8035906020019184600183028401116401000000008311171561008a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506100de565b005b805160205b8181101561015f578083015160f81c6001820184015160601c60158301850151603584018601516055850187016000856000811461012857600181146101385761013d565b6000808585888a5af1915061013d565b600080fd5b50600081141561014c57600080fd5b82605501870196505050505050506100e3565b50505056fea264697066735822122035246402746c96964495cae5b36461fd44dfb89f8e6cf6f6b8d60c0aa89f414864736f6c63430007060033"), nil + return common.FromHex("608060405234801561001057600080fd5b5061019a806100206000396000f3fe60806040526004361061001e5760003560e01c80638d80ff0a14610023575b600080fd5b6100dc6004803603602081101561003957600080fd5b810190808035906020019064010000000081111561005657600080fd5b82018360208201111561006857600080fd5b8035906020019184600183028401116401000000008311171561008a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506100de565b005b805160205b8181101561015f578083015160f81c6001820184015160601c60158301850151603584018601516055850187016000856000811461012857600181146101385761013d565b6000808585888a5af1915061013d565b600080fd5b50600081141561014c57600080fd5b82605501870196505050505050506100e3565b50505056fea264697066735822122035246402746c96964495cae5b36461fd44dfb89f8e6cf6f6b8d60c0aa89f414864736f6c63430007060033"), nil case "MultiSend": - return common.Hex2Bytes("60a060405234801561001057600080fd5b503073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b8152505060805160601c6102756100646000398060e052506102756000f3fe60806040526004361061001e5760003560e01c80638d80ff0a14610023575b600080fd5b6100dc6004803603602081101561003957600080fd5b810190808035906020019064010000000081111561005657600080fd5b82018360208201111561006857600080fd5b8035906020019184600183028401116401000000008311171561008a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506100de565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161415610183576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260308152602001806102106030913960400191505060405180910390fd5b805160205b8181101561020a578083015160f81c6001820184015160601c6015830185015160358401860151605585018701600085600081146101cd57600181146101dd576101e8565b6000808585888a5af191506101e8565b6000808585895af491505b5060008114156101f757600080fd5b8260550187019650505050505050610188565b50505056fe4d756c746953656e642073686f756c64206f6e6c792062652063616c6c6564207669612064656c656761746563616c6ca26469706673582212205c784303626eec02b71940b551976170b500a8a36cc5adcbeb2c19751a76d05464736f6c63430007060033"), nil + return common.FromHex("60a060405234801561001057600080fd5b503073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b8152505060805160601c6102756100646000398060e052506102756000f3fe60806040526004361061001e5760003560e01c80638d80ff0a14610023575b600080fd5b6100dc6004803603602081101561003957600080fd5b810190808035906020019064010000000081111561005657600080fd5b82018360208201111561006857600080fd5b8035906020019184600183028401116401000000008311171561008a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506100de565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff161415610183576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260308152602001806102106030913960400191505060405180910390fd5b805160205b8181101561020a578083015160f81c6001820184015160601c6015830185015160358401860151605585018701600085600081146101cd57600181146101dd576101e8565b6000808585888a5af191506101e8565b6000808585895af491505b5060008114156101f757600080fd5b8260550187019650505050505050610188565b50505056fe4d756c746953656e642073686f756c64206f6e6c792062652063616c6c6564207669612064656c656761746563616c6ca26469706673582212205c784303626eec02b71940b551976170b500a8a36cc5adcbeb2c19751a76d05464736f6c63430007060033"), nil case "Permit2": - return common.Hex2Bytes("60c0346100bb574660a052602081017f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681527f9ac997416e8ff9d2ff6bebeb7149f65cdae5e32e2b90440b566bb3044041d36a60408301524660608301523060808301526080825260a082019180831060018060401b038411176100a557826040525190206080526123c090816100c1823960805181611b47015260a05181611b210152f35b634e487b7160e01b600052604160045260246000fd5b600080fdfe6040608081526004908136101561001557600080fd5b600090813560e01c80630d58b1db1461126c578063137c29fe146110755780632a2d80d114610db75780632b67b57014610bde57806330f28b7a14610ade5780633644e51514610a9d57806336c7851614610a285780633ff9dcb1146109a85780634fe02b441461093f57806365d9723c146107ac57806387517c451461067a578063927da105146105c3578063cc53287f146104a3578063edd9444b1461033a5763fe8ec1a7146100c657600080fd5b346103365760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103365767ffffffffffffffff833581811161033257610114903690860161164b565b60243582811161032e5761012b903690870161161a565b6101336114e6565b9160843585811161032a5761014b9036908a016115c1565b98909560a43590811161032657610164913691016115c1565b969095815190610173826113ff565b606b82527f5065726d697442617463685769746e6573735472616e7366657246726f6d285460208301527f6f6b656e5065726d697373696f6e735b5d207065726d69747465642c61646472838301527f657373207370656e6465722c75696e74323536206e6f6e63652c75696e74323560608301527f3620646561646c696e652c000000000000000000000000000000000000000000608083015282519a8b9181610222602085018096611f93565b918237018a8152039961025b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09b8c8101835282611437565b5190209085515161026b81611ebb565b908a5b8181106102f95750506102f6999a6102ed9183516102a081610294602082018095611f66565b03848101835282611437565b519020602089810151858b015195519182019687526040820192909252336060820152608081019190915260a081019390935260643560c08401528260e081015b03908101835282611437565b51902093611cf7565b80f35b8061031161030b610321938c5161175e565b51612054565b61031b828661175e565b52611f0a565b61026e565b8880fd5b8780fd5b8480fd5b8380fd5b5080fd5b5091346103365760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103365767ffffffffffffffff9080358281116103325761038b903690830161164b565b60243583811161032e576103a2903690840161161a565b9390926103ad6114e6565b9160643590811161049f576103c4913691016115c1565b949093835151976103d489611ebb565b98885b81811061047d5750506102f697988151610425816103f9602082018095611f66565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611437565b5190206020860151828701519083519260208401947ffcf35f5ac6a2c28868dc44c302166470266239195f02b0ee408334829333b7668652840152336060840152608083015260a082015260a081526102ed8161141b565b808b61031b8261049461030b61049a968d5161175e565b9261175e565b6103d7565b8680fd5b5082346105bf57602090817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103325780359067ffffffffffffffff821161032e576104f49136910161161a565b929091845b848110610504578580f35b8061051a610515600193888861196c565b61197c565b61052f84610529848a8a61196c565b0161197c565b3389528385528589209173ffffffffffffffffffffffffffffffffffffffff80911692838b528652868a20911690818a5285528589207fffffffffffffffffffffffff000000000000000000000000000000000000000081541690558551918252848201527f89b1add15eff56b3dfe299ad94e01f2b52fbcb80ae1a3baea6ae8c04cb2b98a4853392a2016104f9565b8280fd5b50346103365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657610676816105ff6114a0565b936106086114c3565b6106106114e6565b73ffffffffffffffffffffffffffffffffffffffff968716835260016020908152848420928816845291825283832090871683528152919020549251938316845260a083901c65ffffffffffff169084015260d09190911c604083015281906060820190565b0390f35b50346103365760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610336576106b26114a0565b906106bb6114c3565b916106c46114e6565b65ffffffffffff926064358481169081810361032a5779ffffffffffff0000000000000000000000000000000000000000947fda9fa7c1b00402c17d0161b249b1ab8bbec047c5a52207b9c112deffd817036b94338a5260016020527fffffffffffff0000000000000000000000000000000000000000000000000000858b209873ffffffffffffffffffffffffffffffffffffffff809416998a8d5260205283878d209b169a8b8d52602052868c209486156000146107a457504216925b8454921697889360a01b16911617179055815193845260208401523392a480f35b905092610783565b5082346105bf5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf576107e56114a0565b906107ee6114c3565b9265ffffffffffff604435818116939084810361032a57338852602091600183528489209673ffffffffffffffffffffffffffffffffffffffff80911697888b528452858a20981697888a5283528489205460d01c93848711156109175761ffff9085840316116108f05750907f55eb90d810e1700b35a8e7e25395ff7f2b2259abd7415ca2284dfb1c246418f393929133895260018252838920878a528252838920888a5282528389209079ffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffff000000000000000000000000000000000000000000000000000083549260d01b16911617905582519485528401523392a480f35b84517f24d35a26000000000000000000000000000000000000000000000000000000008152fd5b5084517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b503461033657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610336578060209273ffffffffffffffffffffffffffffffffffffffff61098f6114a0565b1681528084528181206024358252845220549051908152f35b5082346105bf57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf577f3704902f963766a4e561bbaab6e6cdc1b1dd12f6e9e99648da8843b3f46b918d90359160243533855284602052818520848652602052818520818154179055815193845260208401523392a280f35b8234610a9a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a9a57610a606114a0565b610a686114c3565b610a706114e6565b6064359173ffffffffffffffffffffffffffffffffffffffff8316830361032e576102f6936117a1565b80fd5b503461033657817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657602090610ad7611b1e565b9051908152f35b508290346105bf576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf57610b1a3661152a565b90807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c36011261033257610b4c611478565b9160e43567ffffffffffffffff8111610bda576102f694610b6f913691016115c1565b939092610b7c8351612054565b6020840151828501519083519260208401947f939c21a48a8dbe3a9a2404a1d46691e4d39f6583d6ec6b35714604c986d801068652840152336060840152608083015260a082015260a08152610bd18161141b565b51902091611c25565b8580fd5b509134610336576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657610c186114a0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc360160c08112610332576080855191610c51836113e3565b1261033257845190610c6282611398565b73ffffffffffffffffffffffffffffffffffffffff91602435838116810361049f578152604435838116810361049f57602082015265ffffffffffff606435818116810361032a5788830152608435908116810361049f576060820152815260a435938285168503610bda576020820194855260c4359087830182815260e43567ffffffffffffffff811161032657610cfe90369084016115c1565b929093804211610d88575050918591610d786102f6999a610d7e95610d238851611fbe565b90898c511690519083519260208401947ff3841cd1ff0085026a6327b620b67997ce40f282c88a8e905a7a5626e310f3d086528401526060830152608082015260808152610d70816113ff565b519020611bd9565b916120c7565b519251169161199d565b602492508a51917fcd21db4f000000000000000000000000000000000000000000000000000000008352820152fd5b5091346103365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc93818536011261033257610df36114a0565b9260249081359267ffffffffffffffff9788851161032a578590853603011261049f578051978589018981108282111761104a578252848301358181116103265785019036602383011215610326578382013591610e50836115ef565b90610e5d85519283611437565b838252602093878584019160071b83010191368311611046578801905b828210610fe9575050508a526044610e93868801611509565b96838c01978852013594838b0191868352604435908111610fe557610ebb90369087016115c1565b959096804211610fba575050508998995151610ed681611ebb565b908b5b818110610f9757505092889492610d7892610f6497958351610f02816103f98682018095611f66565b5190209073ffffffffffffffffffffffffffffffffffffffff9a8b8b51169151928551948501957faf1b0d30d2cab0380e68f0689007e3254993c596f2fdd0aaa7f4d04f794408638752850152830152608082015260808152610d70816113ff565b51169082515192845b848110610f78578580f35b80610f918585610f8b600195875161175e565b5161199d565b01610f6d565b80610311610fac8e9f9e93610fb2945161175e565b51611fbe565b9b9a9b610ed9565b8551917fcd21db4f000000000000000000000000000000000000000000000000000000008352820152fd5b8a80fd5b6080823603126110465785608091885161100281611398565b61100b85611509565b8152611018838601611509565b838201526110278a8601611607565b8a8201528d611037818701611607565b90820152815201910190610e7a565b8c80fd5b84896041867f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5082346105bf576101407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf576110b03661152a565b91807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610332576110e2611478565b67ffffffffffffffff93906101043585811161049f5761110590369086016115c1565b90936101243596871161032a57611125610bd1966102f6983691016115c1565b969095825190611134826113ff565b606482527f5065726d69745769746e6573735472616e7366657246726f6d28546f6b656e5060208301527f65726d697373696f6e73207065726d69747465642c6164647265737320737065848301527f6e6465722c75696e74323536206e6f6e63652c75696e7432353620646561646c60608301527f696e652c0000000000000000000000000000000000000000000000000000000060808301528351948591816111e3602085018096611f93565b918237018b8152039361121c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe095868101835282611437565b5190209261122a8651612054565b6020878101518589015195519182019687526040820192909252336060820152608081019190915260a081019390935260e43560c08401528260e081016102e1565b5082346105bf576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033257813567ffffffffffffffff92838211610bda5736602383011215610bda5781013592831161032e576024906007368386831b8401011161049f57865b8581106112e5578780f35b80821b83019060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83360301126103265761139288876001946060835161132c81611398565b611368608461133c8d8601611509565b9485845261134c60448201611509565b809785015261135d60648201611509565b809885015201611509565b918291015273ffffffffffffffffffffffffffffffffffffffff80808093169516931691166117a1565b016112da565b6080810190811067ffffffffffffffff8211176113b457604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff8211176113b457604052565b60a0810190811067ffffffffffffffff8211176113b457604052565b60c0810190811067ffffffffffffffff8211176113b457604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176113b457604052565b60c4359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b600080fd5b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b6044359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc01906080821261149b576040805190611563826113e3565b8082941261149b57805181810181811067ffffffffffffffff8211176113b457825260043573ffffffffffffffffffffffffffffffffffffffff8116810361149b578152602435602082015282526044356020830152606435910152565b9181601f8401121561149b5782359167ffffffffffffffff831161149b576020838186019501011161149b57565b67ffffffffffffffff81116113b45760051b60200190565b359065ffffffffffff8216820361149b57565b9181601f8401121561149b5782359167ffffffffffffffff831161149b576020808501948460061b01011161149b57565b91909160608184031261149b576040805191611666836113e3565b8294813567ffffffffffffffff9081811161149b57830182601f8201121561149b578035611693816115ef565b926116a087519485611437565b818452602094858086019360061b8501019381851161149b579086899897969594939201925b8484106116e3575050505050855280820135908501520135910152565b90919293949596978483031261149b578851908982019082821085831117611730578a928992845261171487611509565b81528287013583820152815201930191908897969594936116c6565b602460007f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b80518210156117725760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b92919273ffffffffffffffffffffffffffffffffffffffff604060008284168152600160205282828220961695868252602052818120338252602052209485549565ffffffffffff8760a01c16804211611884575082871696838803611812575b5050611810955016926118b5565b565b878484161160001461184f57602488604051907ff96fb0710000000000000000000000000000000000000000000000000000000082526004820152fd5b7fffffffffffffffffffffffff000000000000000000000000000000000000000084846118109a031691161790553880611802565b602490604051907fd81b2f2e0000000000000000000000000000000000000000000000000000000082526004820152fd5b9060006064926020958295604051947f23b872dd0000000000000000000000000000000000000000000000000000000086526004860152602485015260448401525af13d15601f3d116001600051141617161561190e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152fd5b91908110156117725760061b0190565b3573ffffffffffffffffffffffffffffffffffffffff8116810361149b5790565b9065ffffffffffff908160608401511673ffffffffffffffffffffffffffffffffffffffff908185511694826020820151169280866040809401511695169560009187835260016020528383208984526020528383209916988983526020528282209184835460d01c03611af5579185611ace94927fc6a377bfc4eb120024a8ac08eef205be16b817020812c73223e81d1bdb9708ec98979694508715600014611ad35779ffffffffffff00000000000000000000000000000000000000009042165b60a01b167fffffffffffff00000000000000000000000000000000000000000000000000006001860160d01b1617179055519384938491604091949373ffffffffffffffffffffffffffffffffffffffff606085019616845265ffffffffffff809216602085015216910152565b0390a4565b5079ffffffffffff000000000000000000000000000000000000000087611a60565b600484517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b467f000000000000000000000000000000000000000000000000000000000000000003611b69577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86682527f9ac997416e8ff9d2ff6bebeb7149f65cdae5e32e2b90440b566bb3044041d36a604082015246606082015230608082015260808152611bd3816113ff565b51902090565b611be1611b1e565b906040519060208201927f190100000000000000000000000000000000000000000000000000000000000084526022830152604282015260428152611bd381611398565b9192909360a435936040840151804211611cc65750602084510151808611611c955750918591610d78611c6594611c60602088015186611e47565b611bd9565b73ffffffffffffffffffffffffffffffffffffffff809151511692608435918216820361149b57611810936118b5565b602490604051907f3728b83d0000000000000000000000000000000000000000000000000000000082526004820152fd5b602490604051907fcd21db4f0000000000000000000000000000000000000000000000000000000082526004820152fd5b959093958051519560409283830151804211611e175750848803611dee57611d2e918691610d7860209b611c608d88015186611e47565b60005b868110611d42575050505050505050565b611d4d81835161175e565b5188611d5a83878a61196c565b01359089810151808311611dbe575091818888886001968596611d84575b50505050505001611d31565b611db395611dad9273ffffffffffffffffffffffffffffffffffffffff6105159351169561196c565b916118b5565b803888888883611d78565b6024908651907f3728b83d0000000000000000000000000000000000000000000000000000000082526004820152fd5b600484517fff633a38000000000000000000000000000000000000000000000000000000008152fd5b6024908551907fcd21db4f0000000000000000000000000000000000000000000000000000000082526004820152fd5b9073ffffffffffffffffffffffffffffffffffffffff600160ff83161b9216600052600060205260406000209060081c6000526020526040600020818154188091551615611e9157565b60046040517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b90611ec5826115ef565b611ed26040519182611437565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611f0082946115ef565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611f375760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b805160208092019160005b828110611f7f575050505090565b835185529381019392810192600101611f71565b9081519160005b838110611fab575050016000815290565b8060208092840101518185015201611f9a565b60405160208101917f65626cad6cb96493bf6f5ebea28756c966f023ab9e8a83a7101849d5573b3678835273ffffffffffffffffffffffffffffffffffffffff8082511660408401526020820151166060830152606065ffffffffffff9182604082015116608085015201511660a082015260a0815260c0810181811067ffffffffffffffff8211176113b45760405251902090565b6040516020808201927f618358ac3db8dc274f0cd8829da7e234bd48cd73c4a740aede1adec9846d06a1845273ffffffffffffffffffffffffffffffffffffffff81511660408401520151606082015260608152611bd381611398565b919082604091031261149b576020823592013590565b6000843b61222e5750604182036121ac576120e4828201826120b1565b939092604010156117725760209360009360ff6040608095013560f81c5b60405194855216868401526040830152606082015282805260015afa156121a05773ffffffffffffffffffffffffffffffffffffffff806000511691821561217657160361214c57565b60046040517f815e1d64000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b6040513d6000823e3d90fd5b60408203612204576121c0918101906120b1565b91601b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84169360ff1c019060ff8211611f375760209360009360ff608094612102565b60046040517f4be6321b000000000000000000000000000000000000000000000000000000008152fd5b929391601f928173ffffffffffffffffffffffffffffffffffffffff60646020957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0604051988997889687947f1626ba7e000000000000000000000000000000000000000000000000000000009e8f8752600487015260406024870152816044870152868601378b85828601015201168101030192165afa9081156123a857829161232a575b507fffffffff000000000000000000000000000000000000000000000000000000009150160361230057565b60046040517fb0669cbc000000000000000000000000000000000000000000000000000000008152fd5b90506020813d82116123a0575b8161234460209383611437565b810103126103365751907fffffffff0000000000000000000000000000000000000000000000000000000082168203610a9a57507fffffffff0000000000000000000000000000000000000000000000000000000090386122d4565b3d9150612337565b6040513d84823e3d90fdfea164736f6c6343000811000a"), nil + return common.FromHex("60c0346100bb574660a052602081017f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681527f9ac997416e8ff9d2ff6bebeb7149f65cdae5e32e2b90440b566bb3044041d36a60408301524660608301523060808301526080825260a082019180831060018060401b038411176100a557826040525190206080526123c090816100c1823960805181611b47015260a05181611b210152f35b634e487b7160e01b600052604160045260246000fd5b600080fdfe6040608081526004908136101561001557600080fd5b600090813560e01c80630d58b1db1461126c578063137c29fe146110755780632a2d80d114610db75780632b67b57014610bde57806330f28b7a14610ade5780633644e51514610a9d57806336c7851614610a285780633ff9dcb1146109a85780634fe02b441461093f57806365d9723c146107ac57806387517c451461067a578063927da105146105c3578063cc53287f146104a3578063edd9444b1461033a5763fe8ec1a7146100c657600080fd5b346103365760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103365767ffffffffffffffff833581811161033257610114903690860161164b565b60243582811161032e5761012b903690870161161a565b6101336114e6565b9160843585811161032a5761014b9036908a016115c1565b98909560a43590811161032657610164913691016115c1565b969095815190610173826113ff565b606b82527f5065726d697442617463685769746e6573735472616e7366657246726f6d285460208301527f6f6b656e5065726d697373696f6e735b5d207065726d69747465642c61646472838301527f657373207370656e6465722c75696e74323536206e6f6e63652c75696e74323560608301527f3620646561646c696e652c000000000000000000000000000000000000000000608083015282519a8b9181610222602085018096611f93565b918237018a8152039961025b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09b8c8101835282611437565b5190209085515161026b81611ebb565b908a5b8181106102f95750506102f6999a6102ed9183516102a081610294602082018095611f66565b03848101835282611437565b519020602089810151858b015195519182019687526040820192909252336060820152608081019190915260a081019390935260643560c08401528260e081015b03908101835282611437565b51902093611cf7565b80f35b8061031161030b610321938c5161175e565b51612054565b61031b828661175e565b52611f0a565b61026e565b8880fd5b8780fd5b8480fd5b8380fd5b5080fd5b5091346103365760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103365767ffffffffffffffff9080358281116103325761038b903690830161164b565b60243583811161032e576103a2903690840161161a565b9390926103ad6114e6565b9160643590811161049f576103c4913691016115c1565b949093835151976103d489611ebb565b98885b81811061047d5750506102f697988151610425816103f9602082018095611f66565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611437565b5190206020860151828701519083519260208401947ffcf35f5ac6a2c28868dc44c302166470266239195f02b0ee408334829333b7668652840152336060840152608083015260a082015260a081526102ed8161141b565b808b61031b8261049461030b61049a968d5161175e565b9261175e565b6103d7565b8680fd5b5082346105bf57602090817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103325780359067ffffffffffffffff821161032e576104f49136910161161a565b929091845b848110610504578580f35b8061051a610515600193888861196c565b61197c565b61052f84610529848a8a61196c565b0161197c565b3389528385528589209173ffffffffffffffffffffffffffffffffffffffff80911692838b528652868a20911690818a5285528589207fffffffffffffffffffffffff000000000000000000000000000000000000000081541690558551918252848201527f89b1add15eff56b3dfe299ad94e01f2b52fbcb80ae1a3baea6ae8c04cb2b98a4853392a2016104f9565b8280fd5b50346103365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657610676816105ff6114a0565b936106086114c3565b6106106114e6565b73ffffffffffffffffffffffffffffffffffffffff968716835260016020908152848420928816845291825283832090871683528152919020549251938316845260a083901c65ffffffffffff169084015260d09190911c604083015281906060820190565b0390f35b50346103365760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610336576106b26114a0565b906106bb6114c3565b916106c46114e6565b65ffffffffffff926064358481169081810361032a5779ffffffffffff0000000000000000000000000000000000000000947fda9fa7c1b00402c17d0161b249b1ab8bbec047c5a52207b9c112deffd817036b94338a5260016020527fffffffffffff0000000000000000000000000000000000000000000000000000858b209873ffffffffffffffffffffffffffffffffffffffff809416998a8d5260205283878d209b169a8b8d52602052868c209486156000146107a457504216925b8454921697889360a01b16911617179055815193845260208401523392a480f35b905092610783565b5082346105bf5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf576107e56114a0565b906107ee6114c3565b9265ffffffffffff604435818116939084810361032a57338852602091600183528489209673ffffffffffffffffffffffffffffffffffffffff80911697888b528452858a20981697888a5283528489205460d01c93848711156109175761ffff9085840316116108f05750907f55eb90d810e1700b35a8e7e25395ff7f2b2259abd7415ca2284dfb1c246418f393929133895260018252838920878a528252838920888a5282528389209079ffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffff000000000000000000000000000000000000000000000000000083549260d01b16911617905582519485528401523392a480f35b84517f24d35a26000000000000000000000000000000000000000000000000000000008152fd5b5084517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b503461033657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610336578060209273ffffffffffffffffffffffffffffffffffffffff61098f6114a0565b1681528084528181206024358252845220549051908152f35b5082346105bf57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf577f3704902f963766a4e561bbaab6e6cdc1b1dd12f6e9e99648da8843b3f46b918d90359160243533855284602052818520848652602052818520818154179055815193845260208401523392a280f35b8234610a9a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a9a57610a606114a0565b610a686114c3565b610a706114e6565b6064359173ffffffffffffffffffffffffffffffffffffffff8316830361032e576102f6936117a1565b80fd5b503461033657817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657602090610ad7611b1e565b9051908152f35b508290346105bf576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf57610b1a3661152a565b90807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c36011261033257610b4c611478565b9160e43567ffffffffffffffff8111610bda576102f694610b6f913691016115c1565b939092610b7c8351612054565b6020840151828501519083519260208401947f939c21a48a8dbe3a9a2404a1d46691e4d39f6583d6ec6b35714604c986d801068652840152336060840152608083015260a082015260a08152610bd18161141b565b51902091611c25565b8580fd5b509134610336576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657610c186114a0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc360160c08112610332576080855191610c51836113e3565b1261033257845190610c6282611398565b73ffffffffffffffffffffffffffffffffffffffff91602435838116810361049f578152604435838116810361049f57602082015265ffffffffffff606435818116810361032a5788830152608435908116810361049f576060820152815260a435938285168503610bda576020820194855260c4359087830182815260e43567ffffffffffffffff811161032657610cfe90369084016115c1565b929093804211610d88575050918591610d786102f6999a610d7e95610d238851611fbe565b90898c511690519083519260208401947ff3841cd1ff0085026a6327b620b67997ce40f282c88a8e905a7a5626e310f3d086528401526060830152608082015260808152610d70816113ff565b519020611bd9565b916120c7565b519251169161199d565b602492508a51917fcd21db4f000000000000000000000000000000000000000000000000000000008352820152fd5b5091346103365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc93818536011261033257610df36114a0565b9260249081359267ffffffffffffffff9788851161032a578590853603011261049f578051978589018981108282111761104a578252848301358181116103265785019036602383011215610326578382013591610e50836115ef565b90610e5d85519283611437565b838252602093878584019160071b83010191368311611046578801905b828210610fe9575050508a526044610e93868801611509565b96838c01978852013594838b0191868352604435908111610fe557610ebb90369087016115c1565b959096804211610fba575050508998995151610ed681611ebb565b908b5b818110610f9757505092889492610d7892610f6497958351610f02816103f98682018095611f66565b5190209073ffffffffffffffffffffffffffffffffffffffff9a8b8b51169151928551948501957faf1b0d30d2cab0380e68f0689007e3254993c596f2fdd0aaa7f4d04f794408638752850152830152608082015260808152610d70816113ff565b51169082515192845b848110610f78578580f35b80610f918585610f8b600195875161175e565b5161199d565b01610f6d565b80610311610fac8e9f9e93610fb2945161175e565b51611fbe565b9b9a9b610ed9565b8551917fcd21db4f000000000000000000000000000000000000000000000000000000008352820152fd5b8a80fd5b6080823603126110465785608091885161100281611398565b61100b85611509565b8152611018838601611509565b838201526110278a8601611607565b8a8201528d611037818701611607565b90820152815201910190610e7a565b8c80fd5b84896041867f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5082346105bf576101407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf576110b03661152a565b91807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610332576110e2611478565b67ffffffffffffffff93906101043585811161049f5761110590369086016115c1565b90936101243596871161032a57611125610bd1966102f6983691016115c1565b969095825190611134826113ff565b606482527f5065726d69745769746e6573735472616e7366657246726f6d28546f6b656e5060208301527f65726d697373696f6e73207065726d69747465642c6164647265737320737065848301527f6e6465722c75696e74323536206e6f6e63652c75696e7432353620646561646c60608301527f696e652c0000000000000000000000000000000000000000000000000000000060808301528351948591816111e3602085018096611f93565b918237018b8152039361121c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe095868101835282611437565b5190209261122a8651612054565b6020878101518589015195519182019687526040820192909252336060820152608081019190915260a081019390935260e43560c08401528260e081016102e1565b5082346105bf576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033257813567ffffffffffffffff92838211610bda5736602383011215610bda5781013592831161032e576024906007368386831b8401011161049f57865b8581106112e5578780f35b80821b83019060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83360301126103265761139288876001946060835161132c81611398565b611368608461133c8d8601611509565b9485845261134c60448201611509565b809785015261135d60648201611509565b809885015201611509565b918291015273ffffffffffffffffffffffffffffffffffffffff80808093169516931691166117a1565b016112da565b6080810190811067ffffffffffffffff8211176113b457604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff8211176113b457604052565b60a0810190811067ffffffffffffffff8211176113b457604052565b60c0810190811067ffffffffffffffff8211176113b457604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176113b457604052565b60c4359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b600080fd5b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b6044359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc01906080821261149b576040805190611563826113e3565b8082941261149b57805181810181811067ffffffffffffffff8211176113b457825260043573ffffffffffffffffffffffffffffffffffffffff8116810361149b578152602435602082015282526044356020830152606435910152565b9181601f8401121561149b5782359167ffffffffffffffff831161149b576020838186019501011161149b57565b67ffffffffffffffff81116113b45760051b60200190565b359065ffffffffffff8216820361149b57565b9181601f8401121561149b5782359167ffffffffffffffff831161149b576020808501948460061b01011161149b57565b91909160608184031261149b576040805191611666836113e3565b8294813567ffffffffffffffff9081811161149b57830182601f8201121561149b578035611693816115ef565b926116a087519485611437565b818452602094858086019360061b8501019381851161149b579086899897969594939201925b8484106116e3575050505050855280820135908501520135910152565b90919293949596978483031261149b578851908982019082821085831117611730578a928992845261171487611509565b81528287013583820152815201930191908897969594936116c6565b602460007f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b80518210156117725760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b92919273ffffffffffffffffffffffffffffffffffffffff604060008284168152600160205282828220961695868252602052818120338252602052209485549565ffffffffffff8760a01c16804211611884575082871696838803611812575b5050611810955016926118b5565b565b878484161160001461184f57602488604051907ff96fb0710000000000000000000000000000000000000000000000000000000082526004820152fd5b7fffffffffffffffffffffffff000000000000000000000000000000000000000084846118109a031691161790553880611802565b602490604051907fd81b2f2e0000000000000000000000000000000000000000000000000000000082526004820152fd5b9060006064926020958295604051947f23b872dd0000000000000000000000000000000000000000000000000000000086526004860152602485015260448401525af13d15601f3d116001600051141617161561190e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152fd5b91908110156117725760061b0190565b3573ffffffffffffffffffffffffffffffffffffffff8116810361149b5790565b9065ffffffffffff908160608401511673ffffffffffffffffffffffffffffffffffffffff908185511694826020820151169280866040809401511695169560009187835260016020528383208984526020528383209916988983526020528282209184835460d01c03611af5579185611ace94927fc6a377bfc4eb120024a8ac08eef205be16b817020812c73223e81d1bdb9708ec98979694508715600014611ad35779ffffffffffff00000000000000000000000000000000000000009042165b60a01b167fffffffffffff00000000000000000000000000000000000000000000000000006001860160d01b1617179055519384938491604091949373ffffffffffffffffffffffffffffffffffffffff606085019616845265ffffffffffff809216602085015216910152565b0390a4565b5079ffffffffffff000000000000000000000000000000000000000087611a60565b600484517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b467f000000000000000000000000000000000000000000000000000000000000000003611b69577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86682527f9ac997416e8ff9d2ff6bebeb7149f65cdae5e32e2b90440b566bb3044041d36a604082015246606082015230608082015260808152611bd3816113ff565b51902090565b611be1611b1e565b906040519060208201927f190100000000000000000000000000000000000000000000000000000000000084526022830152604282015260428152611bd381611398565b9192909360a435936040840151804211611cc65750602084510151808611611c955750918591610d78611c6594611c60602088015186611e47565b611bd9565b73ffffffffffffffffffffffffffffffffffffffff809151511692608435918216820361149b57611810936118b5565b602490604051907f3728b83d0000000000000000000000000000000000000000000000000000000082526004820152fd5b602490604051907fcd21db4f0000000000000000000000000000000000000000000000000000000082526004820152fd5b959093958051519560409283830151804211611e175750848803611dee57611d2e918691610d7860209b611c608d88015186611e47565b60005b868110611d42575050505050505050565b611d4d81835161175e565b5188611d5a83878a61196c565b01359089810151808311611dbe575091818888886001968596611d84575b50505050505001611d31565b611db395611dad9273ffffffffffffffffffffffffffffffffffffffff6105159351169561196c565b916118b5565b803888888883611d78565b6024908651907f3728b83d0000000000000000000000000000000000000000000000000000000082526004820152fd5b600484517fff633a38000000000000000000000000000000000000000000000000000000008152fd5b6024908551907fcd21db4f0000000000000000000000000000000000000000000000000000000082526004820152fd5b9073ffffffffffffffffffffffffffffffffffffffff600160ff83161b9216600052600060205260406000209060081c6000526020526040600020818154188091551615611e9157565b60046040517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b90611ec5826115ef565b611ed26040519182611437565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611f0082946115ef565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611f375760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b805160208092019160005b828110611f7f575050505090565b835185529381019392810192600101611f71565b9081519160005b838110611fab575050016000815290565b8060208092840101518185015201611f9a565b60405160208101917f65626cad6cb96493bf6f5ebea28756c966f023ab9e8a83a7101849d5573b3678835273ffffffffffffffffffffffffffffffffffffffff8082511660408401526020820151166060830152606065ffffffffffff9182604082015116608085015201511660a082015260a0815260c0810181811067ffffffffffffffff8211176113b45760405251902090565b6040516020808201927f618358ac3db8dc274f0cd8829da7e234bd48cd73c4a740aede1adec9846d06a1845273ffffffffffffffffffffffffffffffffffffffff81511660408401520151606082015260608152611bd381611398565b919082604091031261149b576020823592013590565b6000843b61222e5750604182036121ac576120e4828201826120b1565b939092604010156117725760209360009360ff6040608095013560f81c5b60405194855216868401526040830152606082015282805260015afa156121a05773ffffffffffffffffffffffffffffffffffffffff806000511691821561217657160361214c57565b60046040517f815e1d64000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b6040513d6000823e3d90fd5b60408203612204576121c0918101906120b1565b91601b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84169360ff1c019060ff8211611f375760209360009360ff608094612102565b60046040517f4be6321b000000000000000000000000000000000000000000000000000000008152fd5b929391601f928173ffffffffffffffffffffffffffffffffffffffff60646020957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0604051988997889687947f1626ba7e000000000000000000000000000000000000000000000000000000009e8f8752600487015260406024870152816044870152868601378b85828601015201168101030192165afa9081156123a857829161232a575b507fffffffff000000000000000000000000000000000000000000000000000000009150160361230057565b60046040517fb0669cbc000000000000000000000000000000000000000000000000000000008152fd5b90506020813d82116123a0575b8161234460209383611437565b810103126103365751907fffffffff0000000000000000000000000000000000000000000000000000000082168203610a9a57507fffffffff0000000000000000000000000000000000000000000000000000000090386122d4565b3d9150612337565b6040513d84823e3d90fdfea164736f6c6343000811000a"), nil case "EntryPoint": - return common.Hex2Bytes("60a080604052346200008957600160025561022c8181016001600160401b038111838210176200007357829162005d18833903906000f080156200006757608052604051615c8990816200008f82396080518181816113df01528181613e9501526141b60152f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fdfe60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c634300081100336080806040523461001657610210908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c63570e1a361461002857600080fd5b346100c95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100c95760043567ffffffffffffffff918282116100c957366023830112156100c95781600401359283116100c95736602484840101116100c9576100c561009e84602485016100fc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b80fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90806014116101bb5767ffffffffffffffff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec82018381116101cd575b604051937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81600b8701160116850190858210908211176101c0575b604052808452602084019036848401116101bb576020946000600c819682946014880187378301015251923560601c5af19060005191156101b557565b60009150565b600080fd5b6101c86100cc565b610178565b6101d56100cc565b61013a56fea26469706673582212201927e80b76ab9b71c952137dd676621a9fdf520c25928815636594036eb1c40364736f6c63430008110033"), nil + return common.FromHex("60a080604052346200008957600160025561022c8181016001600160401b038111838210176200007357829162005d18833903906000f080156200006757608052604051615c8990816200008f82396080518181816113df01528181613e9501526141b60152f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fdfe60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c634300081100336080806040523461001657610210908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c63570e1a361461002857600080fd5b346100c95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100c95760043567ffffffffffffffff918282116100c957366023830112156100c95781600401359283116100c95736602484840101116100c9576100c561009e84602485016100fc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b80fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90806014116101bb5767ffffffffffffffff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec82018381116101cd575b604051937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81600b8701160116850190858210908211176101c0575b604052808452602084019036848401116101bb576020946000600c819682946014880187378301015251923560601c5af19060005191156101b557565b60009150565b600080fd5b6101c86100cc565b610178565b6101d56100cc565b61013a56fea26469706673582212201927e80b76ab9b71c952137dd676621a9fdf520c25928815636594036eb1c40364736f6c63430008110033"), nil default: return nil, fmt.Errorf("no initialization byte code available for contract: %s", contractName) } diff --git a/op-chain-ops/genesis/config.go b/op-chain-ops/genesis/config.go index 11273235f876..badf461d21c2 100644 --- a/op-chain-ops/genesis/config.go +++ b/op-chain-ops/genesis/config.go @@ -18,7 +18,6 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum-optimism/optimism/op-bindings/hardhat" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-chain-ops/immutables" "github.com/ethereum-optimism/optimism/op-chain-ops/state" @@ -198,10 +197,6 @@ type DeployConfig struct { // FaultGameAbsolutePrestate is the absolute prestate of Cannon. This is computed // by generating a proof from the 0th -> 1st instruction and grabbing the prestate from // the output JSON. All honest challengers should agree on the setup state of the program. - // TODO(clabby): Right now, the build of the `op-program` is nondeterministic, meaning that - // the binary must be distributed in order for honest actors to agree. In the future, we'll - // look to make the build deterministic so that users may build Cannon / the `op-program` - // from source. FaultGameAbsolutePrestate common.Hash `json:"faultGameAbsolutePrestate"` // FaultGameMaxDepth is the maximum depth of the position tree within the fault dispute game. // `2^{FaultGameMaxDepth}` is how many instructions the execution trace bisection game @@ -218,6 +213,8 @@ type DeployConfig struct { FaultGameGenesisOutputRoot common.Hash `json:"faultGameGenesisOutputRoot"` // FaultGameSplitDepth is the depth at which the fault dispute game splits from output roots to execution trace claims. FaultGameSplitDepth uint64 `json:"faultGameSplitDepth"` + // FaultGameWithdrawalDelay is the number of seconds that users must wait before withdrawing ETH from a fault game. + FaultGameWithdrawalDelay uint64 `json:"faultGameWithdrawalDelay"` // PreimageOracleMinProposalSize is the minimum number of bytes that a large preimage oracle proposal can be. PreimageOracleMinProposalSize uint64 `json:"preimageOracleMinProposalSize"` // PreimageOracleChallengePeriod is the number of seconds that challengers have to challenge a large preimage proposal. @@ -231,6 +228,33 @@ type DeployConfig struct { // RequiredProtocolVersion indicates the protocol version that // nodes are recommended to adopt, to stay in sync with the network. RecommendedProtocolVersion params.ProtocolVersion `json:"recommendedProtocolVersion"` + // ProofMaturityDelaySeconds is the number of seconds that a proof must be + // mature before it can be used to finalize a withdrawal. + ProofMaturityDelaySeconds uint64 `json:"proofMaturityDelaySeconds"` + // DisputeGameFinalityDelaySeconds is an additional number of seconds a + // dispute game must wait before it can be used to finalize a withdrawal. + DisputeGameFinalityDelaySeconds uint64 `json:"disputeGameFinalityDelaySeconds"` + // RespectedGameType is the dispute game type that the OptimismPortal + // contract will respect for finalizing withdrawals. + RespectedGameType uint32 `json:"respectedGameType"` + // UseFaultProofs is a flag that indicates if the system is using fault + // proofs instead of the older output oracle mechanism. + UseFaultProofs bool `json:"useFaultProofs"` + + // UsePlasma is a flag that indicates if the system is using op-plasma + UsePlasma bool `json:"usePlasma"` + // DAChallengeWindow represents the block interval during which the availability of a data commitment can be challenged. + DAChallengeWindow uint64 `json:"daChallengeWindow"` + // DAResolveWindow represents the block interval during which a data availability challenge can be resolved. + DAResolveWindow uint64 `json:"daResolveWindow"` + // DABondSize represents the required bond size to initiate a data availability challenge. + DABondSize uint64 `json:"daBondSize"` + // DAResolverRefundPercentage represents the percentage of the resolving cost to be refunded to the resolver + // such as 100 means 100% refund. + DAResolverRefundPercentage uint64 `json:"daResolverRefundPercentage"` + + // DAChallengeProxy represents the L1 address of the DataAvailabilityChallenge contract. + DAChallengeProxy common.Address `json:"daChallengeProxy"` // When Cancun activates. Relative to L1 genesis. L1CancunTimeOffset *hexutil.Uint64 `json:"l1CancunTimeOffset,omitempty"` @@ -375,6 +399,23 @@ func (d *DeployConfig) Check() error { if d.RecommendedProtocolVersion == (params.ProtocolVersion{}) { log.Warn("RecommendedProtocolVersion is empty") } + if d.ProofMaturityDelaySeconds == 0 { + log.Warn("ProofMaturityDelaySeconds is 0") + } + if d.DisputeGameFinalityDelaySeconds == 0 { + log.Warn("DisputeGameFinalityDelaySeconds is 0") + } + if d.UsePlasma { + if d.DAChallengeWindow == 0 { + return fmt.Errorf("%w: DAChallengeWindow cannot be 0 when using plasma mode", ErrInvalidDeployConfig) + } + if d.DAResolveWindow == 0 { + return fmt.Errorf("%w: DAResolveWindow cannot be 0 when using plasma mode", ErrInvalidDeployConfig) + } + if d.DAChallengeProxy == (common.Address{}) { + return fmt.Errorf("%w: DAChallengeContract cannot be empty when using plasma mode", ErrInvalidDeployConfig) + } + } // checkFork checks that fork A is before or at the same time as fork B checkFork := func(a, b *hexutil.Uint64, aName, bName string) error { if a == nil && b == nil { @@ -436,52 +477,7 @@ func (d *DeployConfig) SetDeployments(deployments *L1Deployments) { d.L1ERC721BridgeProxy = deployments.L1ERC721BridgeProxy d.SystemConfigProxy = deployments.SystemConfigProxy d.OptimismPortalProxy = deployments.OptimismPortalProxy -} - -// GetDeployedAddresses will get the deployed addresses of deployed L1 contracts -// required for the L2 genesis creation. -func (d *DeployConfig) GetDeployedAddresses(hh *hardhat.Hardhat) error { - if d.L1StandardBridgeProxy == (common.Address{}) { - l1StandardBridgeProxyDeployment, err := hh.GetDeployment("L1StandardBridgeProxy") - if err != nil { - return fmt.Errorf("cannot find L1StandardBridgeProxy artifact: %w", err) - } - d.L1StandardBridgeProxy = l1StandardBridgeProxyDeployment.Address - } - - if d.L1CrossDomainMessengerProxy == (common.Address{}) { - l1CrossDomainMessengerProxyDeployment, err := hh.GetDeployment("L1CrossDomainMessengerProxy") - if err != nil { - return fmt.Errorf("cannot find L1CrossDomainMessengerProxy artifact: %w", err) - } - d.L1CrossDomainMessengerProxy = l1CrossDomainMessengerProxyDeployment.Address - } - - if d.L1ERC721BridgeProxy == (common.Address{}) { - l1ERC721BridgeProxyDeployment, err := hh.GetDeployment("L1ERC721BridgeProxy") - if err != nil { - return fmt.Errorf("cannot find L1ERC721BridgeProxy artifact: %w", err) - } - d.L1ERC721BridgeProxy = l1ERC721BridgeProxyDeployment.Address - } - - if d.SystemConfigProxy == (common.Address{}) { - systemConfigProxyDeployment, err := hh.GetDeployment("SystemConfigProxy") - if err != nil { - return fmt.Errorf("cannot find SystemConfigProxy artifact: %w", err) - } - d.SystemConfigProxy = systemConfigProxyDeployment.Address - } - - if d.OptimismPortalProxy == (common.Address{}) { - optimismPortalProxyDeployment, err := hh.GetDeployment("OptimismPortalProxy") - if err != nil { - return fmt.Errorf("cannot find OptimismPortalProxy artifact: %w", err) - } - d.OptimismPortalProxy = optimismPortalProxyDeployment.Address - } - - return nil + d.DAChallengeProxy = deployments.DataAvailabilityChallengeProxy } func (d *DeployConfig) GovernanceEnabled() bool { @@ -596,6 +592,10 @@ func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHas EcotoneTime: d.EcotoneTime(l1StartBlock.Time()), FjordTime: d.FjordTime(l1StartBlock.Time()), InteropTime: d.InteropTime(l1StartBlock.Time()), + UsePlasma: d.UsePlasma, + DAChallengeAddress: d.DAChallengeProxy, + DAChallengeWindow: d.DAChallengeWindow, + DAResolveWindow: d.DAResolveWindow, }, nil } @@ -648,6 +648,8 @@ type L1Deployments struct { SystemConfigProxy common.Address `json:"SystemConfigProxy"` ProtocolVersions common.Address `json:"ProtocolVersions"` ProtocolVersionsProxy common.Address `json:"ProtocolVersionsProxy"` + DataAvailabilityChallenge common.Address `json:"DataAvailabilityChallenge"` + DataAvailabilityChallengeProxy common.Address `json:"DataAvailabilityChallengeProxy"` } // GetName will return the name of the contract given an address. @@ -665,7 +667,7 @@ func (d *L1Deployments) GetName(addr common.Address) string { } // Check will ensure that the L1Deployments are sane -func (d *L1Deployments) Check() error { +func (d *L1Deployments) Check(deployConfig *DeployConfig) error { val := reflect.ValueOf(d) if val.Kind() == reflect.Ptr { val = val.Elem() @@ -673,7 +675,14 @@ func (d *L1Deployments) Check() error { for i := 0; i < val.NumField(); i++ { name := val.Type().Field(i).Name // Skip the non production ready contracts - if name == "DisputeGameFactory" || name == "DisputeGameFactoryProxy" || name == "BlockOracle" { + if name == "DisputeGameFactory" || + name == "DisputeGameFactoryProxy" || + name == "BlockOracle" { + continue + } + if !deployConfig.UsePlasma && + (name == "DataAvailabilityChallenge" || + name == "DataAvailabilityChallengeProxy") { continue } if val.Field(i).Interface().(common.Address) == (common.Address{}) { @@ -731,13 +740,55 @@ func NewStateDump(path string) (*gstate.Dump, error) { return nil, fmt.Errorf("dump at %s not found: %w", path, err) } - var dump gstate.Dump - if err := json.Unmarshal(file, &dump); err != nil { + var fdump ForgeDump + if err := json.Unmarshal(file, &fdump); err != nil { return nil, fmt.Errorf("cannot unmarshal dump: %w", err) } + dump := (gstate.Dump)(fdump) return &dump, nil } +// ForgeDump is a simple alias for state.Dump that can read "nonce" as a hex string. +// It appears as if updates to foundry have changed the serialization of the state dump. +type ForgeDump gstate.Dump + +func (d *ForgeDump) UnmarshalJSON(b []byte) error { + type forgeDumpAccount struct { + Balance string `json:"balance"` + Nonce hexutil.Uint64 `json:"nonce"` + Root hexutil.Bytes `json:"root"` + CodeHash hexutil.Bytes `json:"codeHash"` + Code hexutil.Bytes `json:"code,omitempty"` + Storage map[common.Hash]string `json:"storage,omitempty"` + Address *common.Address `json:"address,omitempty"` + AddressHash hexutil.Bytes `json:"key,omitempty"` + } + type forgeDump struct { + Root string `json:"root"` + Accounts map[common.Address]forgeDumpAccount `json:"accounts"` + } + var dump forgeDump + if err := json.Unmarshal(b, &dump); err != nil { + return err + } + + d.Root = dump.Root + d.Accounts = make(map[string]gstate.DumpAccount) + for addr, acc := range dump.Accounts { + d.Accounts[addr.String()] = gstate.DumpAccount{ + Balance: acc.Balance, + Nonce: (uint64)(acc.Nonce), + Root: acc.Root, + CodeHash: acc.CodeHash, + Code: acc.Code, + Storage: acc.Storage, + Address: acc.Address, + AddressHash: acc.AddressHash, + } + } + return nil +} + // NewL2ImmutableConfig will create an ImmutableConfig given an instance of a // DeployConfig and a block. func NewL2ImmutableConfig(config *DeployConfig, block *types.Block) (*immutables.PredeploysImmutableConfig, error) { @@ -823,8 +874,7 @@ func NewL2ImmutableConfig(config *DeployConfig, block *types.Block) (*immutables return &cfg, nil } -// NewL2StorageConfig will create a StorageConfig given an instance of a -// Hardhat and a DeployConfig. +// NewL2StorageConfig will create a StorageConfig given an instance of a DeployConfig and genesis block. func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.StorageConfig, error) { storage := make(state.StorageConfig) diff --git a/op-chain-ops/genesis/genesis.go b/op-chain-ops/genesis/genesis.go index 70c9109f42c0..1919aac1f7e7 100644 --- a/op-chain-ops/genesis/genesis.go +++ b/op-chain-ops/genesis/genesis.go @@ -97,7 +97,7 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro return nil, fmt.Errorf("transition block extradata too long: %d", size) } - return &core.Genesis{ + genesis := &core.Genesis{ Config: &optimismChainConfig, Nonce: uint64(config.L2GenesisBlockNonce), Timestamp: block.Time(), @@ -111,7 +111,14 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro ParentHash: config.L2GenesisBlockParentHash, BaseFee: baseFee.ToInt(), Alloc: map[common.Address]core.GenesisAccount{}, - }, nil + } + + if optimismChainConfig.IsEcotone(genesis.Timestamp) { + genesis.BlobGasUsed = u64ptr(0) + genesis.ExcessBlobGas = u64ptr(0) + } + + return genesis, nil } // NewL1Genesis will create a new L1 genesis config diff --git a/op-chain-ops/genesis/layer_one.go b/op-chain-ops/genesis/layer_one.go index 40d1c96f9014..f697fdbc0a4d 100644 --- a/op-chain-ops/genesis/layer_one.go +++ b/op-chain-ops/genesis/layer_one.go @@ -1,7 +1,6 @@ package genesis import ( - "errors" "fmt" "math/big" @@ -9,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" gstate "github.com/ethereum/go-ethereum/core/state" @@ -44,7 +44,7 @@ func init() { // all of the state required for an Optimism network to function. // It is expected that the dump contains all of the required state to bootstrap // the L1 chain. -func BuildL1DeveloperGenesis(config *DeployConfig, dump *gstate.Dump, l1Deployments *L1Deployments, postProcess bool) (*core.Genesis, error) { +func BuildL1DeveloperGenesis(config *DeployConfig, dump *gstate.Dump, l1Deployments *L1Deployments) (*core.Genesis, error) { log.Info("Building developer L1 genesis block") genesis, err := NewL1Genesis(config) if err != nil { @@ -56,7 +56,16 @@ func BuildL1DeveloperGenesis(config *DeployConfig, dump *gstate.Dump, l1Deployme SetPrecompileBalances(memDB) if dump != nil { - for address, account := range dump.Accounts { + for addrstr, account := range dump.Accounts { + if !common.IsHexAddress(addrstr) { + // Changes in https://github.com/ethereum/go-ethereum/pull/28504 + // add accounts to the Dump with "pre()" as key + // if the address itself is nil. + // So depending on how `dump` was created, this might be a + // pre-image key, which we skip. + continue + } + address := common.HexToAddress(addrstr) name := "" if l1Deployments != nil { if n := l1Deployments.GetName(address); n != "" { @@ -67,7 +76,7 @@ func BuildL1DeveloperGenesis(config *DeployConfig, dump *gstate.Dump, l1Deployme memDB.CreateAccount(address) memDB.SetNonce(address, account.Nonce) - balance, ok := new(big.Int).SetString(account.Balance, 10) + balance, ok := math.ParseBig256(account.Balance) if !ok { return nil, fmt.Errorf("failed to parse balance for %s", address) } @@ -78,49 +87,7 @@ func BuildL1DeveloperGenesis(config *DeployConfig, dump *gstate.Dump, l1Deployme memDB.SetState(address, key, common.HexToHash(value)) } } - - // This should only be used if we are expecting Optimism specific state to be set - if postProcess { - if err := PostProcessL1DeveloperGenesis(memDB, l1Deployments); err != nil { - return nil, fmt.Errorf("failed to post process L1 developer genesis: %w", err) - } - } } return memDB.Genesis(), nil } - -// PostProcessL1DeveloperGenesis will apply post processing to the L1 genesis -// state. This is required to handle edge cases in the genesis generation. -// `block.number` is used during deployment and without specifically setting -// the value to 0, it will cause underflow reverts for deposits in testing. -func PostProcessL1DeveloperGenesis(stateDB *state.MemoryStateDB, deployments *L1Deployments) error { - log.Info("Post processing state") - - if stateDB == nil { - return errors.New("cannot post process nil stateDB") - } - if deployments == nil { - return errors.New("cannot post process dump with nil deployments") - } - - if !stateDB.Exist(deployments.OptimismPortalProxy) { - return fmt.Errorf("portal proxy doesn't exist at %s", deployments.OptimismPortalProxy) - } - - layout, err := bindings.GetStorageLayout("OptimismPortal") - if err != nil { - return errors.New("failed to get storage layout for OptimismPortal") - } - - entry, err := layout.GetStorageLayoutEntry("params") - if err != nil { - return errors.New("failed to get storage layout entry for OptimismPortal.params") - } - slot := common.BigToHash(big.NewInt(int64(entry.Slot))) - - stateDB.SetState(deployments.OptimismPortalProxy, slot, common.Hash{}) - log.Info("Post process update", "address", deployments.OptimismPortalProxy, "slot", slot.Hex(), "value", common.Hash{}.Hex()) - - return nil -} diff --git a/op-chain-ops/genesis/layer_one_test.go b/op-chain-ops/genesis/layer_one_test.go index be328632f9da..ba8a8f0c0fa1 100644 --- a/op-chain-ops/genesis/layer_one_test.go +++ b/op-chain-ops/genesis/layer_one_test.go @@ -43,7 +43,7 @@ func TestBuildL1DeveloperGenesis(t *testing.T) { deployments, err := NewL1Deployments("testdata/deploy.json") require.NoError(t, err) - genesis, err := BuildL1DeveloperGenesis(config, dump, nil, false) + genesis, err := BuildL1DeveloperGenesis(config, dump, nil) require.NoError(t, err) sim := backends.NewSimulatedBackend( diff --git a/op-chain-ops/genesis/testdata/allocs-l1.json b/op-chain-ops/genesis/testdata/allocs-l1.json index 5581316987c6..b103f8a387f1 100644 --- a/op-chain-ops/genesis/testdata/allocs-l1.json +++ b/op-chain-ops/genesis/testdata/allocs-l1.json @@ -2,63 +2,63 @@ "root": "c09d26bbbfff36314c8d562387f54768cc0d82b1ad5d2f8544c45e9a1b73cd82", "accounts": { "0x0000000000000000000000000000000000000001": { - "balance": "1", + "balance": "0x1", "nonce": 0, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "key": "0x1468288056310c82aa4c01a7e12a10f8111a0560e72b700555479031b86c357d" }, "0x0000000000000000000000000000000000000002": { - "balance": "1", + "balance": "0x1", "nonce": 0, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "key": "0xd52688a8f926c816ca1e079067caba944f158e764817b83fc43594370ca9cf62" }, "0x0000000000000000000000000000000000000003": { - "balance": "1", + "balance": "0x1", "nonce": 0, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "key": "0x5b70e80538acdabd6137353b0f9d8d149f4dba91e8be2e7946e409bfdbe685b9" }, "0x0000000000000000000000000000000000000004": { - "balance": "1", + "balance": "0x1", "nonce": 0, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "key": "0xa876da518a393dbd067dc72abfa08d475ed6447fca96d92ec3f9e7eba503ca61" }, "0x0000000000000000000000000000000000000005": { - "balance": "1", + "balance": "0x1", "nonce": 0, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "key": "0x421df1fa259221d02aa4956eb0d35ace318ca24c0a33a64c1af96cf67cf245b6" }, "0x0000000000000000000000000000000000000006": { - "balance": "1", + "balance": "0x1", "nonce": 0, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "key": "0x689802d6ed1a28b049e9d4fe5334c5902fd9bc00c42821c82f82ee2da10be908" }, "0x0000000000000000000000000000000000000007": { - "balance": "1", + "balance": "0x1", "nonce": 0, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "key": "0x8c3ab0970b73895b8c9959bae685c3a19f45eb5ad89d42b52a340ec4ac204d19" }, "0x0000000000000000000000000000000000000008": { - "balance": "1", + "balance": "0x1", "nonce": 0, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "key": "0x471703c5eda8644a64cec152c58f5aacec93d72fb0bfa705f0473f9043a8357c" }, "0x0000000000000000000000000000000000000009": { - "balance": "1", + "balance": "0x1", "nonce": 0, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", @@ -72,7 +72,7 @@ "key": "0x5e0651590c81426aa5f87b57e050b06ca0e3d1c7506a54ace1e923c08eda1d62" }, "0x36f4e85652236f9edaeba78bbe9d8c2b55ac5809": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0xaab9666c577be40942a2a1b7db7f1ef1e1a208ea6b7e33c906221efb78cc11c5", "codeHash": "0xaebd68b2a785d0af4b7e1f3e600efde438efa83b08f2ad8bcd9287322f396e5f", @@ -87,7 +87,7 @@ "key": "0xc5cde3f9919e46021264f96610e62970e8aa910e6457059ce4bfb1c48b16b59a" }, "0x4562938d6831437f37dd1bf5bbb7fe7a5f080eac": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0x3e8b25f39fd713daed2a41f440a2ffecf3e7a153bd7a230d053f36740f656433", "codeHash": "0x3f41be62f844a58153179eed8f6e351351a8a0b293f01383671e7ec136b3e40e", @@ -99,7 +99,7 @@ "key": "0xf16b24c51b2548da7804641166342e8b8662bebf66987ef3eb12dd7950821b74" }, "0x48204903b06a64e3c44b0260f875497ea5316a02": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0x408e9cd8a46cccdf81d7735aa9c93b5a97608fcc38000c6c8311e6d614c9cfc6", "codeHash": "0x1f958654ab06a152993e7a0ae7b6dbb0d4b19265cc9337b8789fe1353bd9dc35", @@ -112,7 +112,7 @@ "key": "0x2c94e39eab7e93ae2c81f6d3b7d4b3d6a6ffeb09b6493d7bb1642b2d00c2cf60" }, "0x6fb1869d7141c97cf28668fa0a338bdc892f53c0": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0x4c966b8eb461b1db77f4842a16a91b766d03a7f2699edfa8f25d23028b511260", "codeHash": "0xc7b46fc754979c0fd29ec7105b045a5705d172da4364b24a72e42e586906056f", @@ -124,7 +124,7 @@ "key": "0xe1a3b9b8f8403a487cd74384f01166a39e6b0740fb9cf546795fa82c12e0a716" }, "0x73317009f4fadafcda357f3a082c7b68f5f8732f": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0xdc2d8e78c5f46669754c0498c50471e7944dd5787b3acdbcb53858469ad4e1d3", "codeHash": "0x1f958654ab06a152993e7a0ae7b6dbb0d4b19265cc9337b8789fe1353bd9dc35", @@ -144,7 +144,7 @@ "key": "0xfbb20b1dbf403bf022cfca8b23242ebe79dc06744e9d5233cb6db43454746315" }, "0x7aeb97910d4070426c00e820de4137d6d2adf0ad": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0x5577b03f1a10efe1b976be229362e61ffc19859e866c7ca0d9e4887bc87b0800", "codeHash": "0x23ff3128727914b22a2753aafff02d897826166b869a027a11b851863d379ddf", @@ -156,7 +156,7 @@ "key": "0xd0a446c0ce66b5c711436c39fbeae531a05e9d698f32ddc8cd48d17fbe95feb0" }, "0x7ec3b539c97c98d503fb4fee3dd4ee885dc192cd": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0x0d625098e698c6d3b38ed38c3f00ea28361dc94fbf0e6cfd4c1ebc121cd9daac", @@ -164,7 +164,7 @@ "key": "0xd409335fac8e9e86a7a66c3720b403889062892385e5f09b7af7c5bee4f326fd" }, "0x7f325df611b236ee3ef469da4a74f776c787d1b3": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0x821e2556a290c86405f8160a2d662042a431ba456b9db265c79bb837c04be5f0", "codeHash": "0x8e91bdb75050d4b44b5fc5c557c6f3455bfc4b76686fd72d9087b51a3200aecf", @@ -175,7 +175,7 @@ "key": "0x7a0724a3db73dfc6e99d843345c7746c79a0f615a36e22824ad91209feb9cf81" }, "0x87658463f96977fc95a068f1a206d2c0cf2db575": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0x3bb571c9d6063b9c50dcf6f602d428dfd633dca39aba9ec607d4ce0505a362d5", @@ -183,7 +183,7 @@ "key": "0xbd5530d2a017fd01a7edb9efa8656fd9c2d34523524628fdfd649f3222cec07c" }, "0x9a7ecb1c67f88396d252725f3259e9d8027f1562": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "codeHash": "0x8b9df5a9eb6bb3280671bbc79f735d9d7009f8c0590c5cd0bc75a8e928068606", @@ -191,7 +191,7 @@ "key": "0x26ac7e215c5b48eb9f6162a5e7022d185b54b55d6d706b30e2777e9c6e06d565" }, "0xa051f227da1f5f1eecbfcdcd7316ce299a233760": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0x4bed30661c4ccc61a7009910d1386ad6903216e2275b55589afb851dcb70c294", "codeHash": "0x1f958654ab06a152993e7a0ae7b6dbb0d4b19265cc9337b8789fe1353bd9dc35", @@ -203,7 +203,7 @@ "key": "0xd8522a36052aeae781dd8c38910969dc4f51b91541455ac64a0936b69d848e6e" }, "0xa88b2060478401a52532814edde6819d101802e2": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0x68f4106f36ca6cb79380dcf1851f76be5dca9c34a9223a82032ccbba38eeb51a", "codeHash": "0x06643e7d44538ba353995b6b77634e1c5bd1282ae7902f2b1aceaec97cf572ed", @@ -217,7 +217,7 @@ "key": "0xdc2621e436cbec9ae124870f5ab25b65494a5accb952b75a94fda87636f6cd14" }, "0xb8d5d0fa6e413b5de72c38a0a187731171b4f341": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0x0ad3da5fea1ef359038ec861ffa336c2364bc170d36b136f0e8535f6cd29e283", "codeHash": "0x3921774d36fd85d9e41c25a60635dfe0f0e5d2162afb93292db8bb80c81ece78", @@ -231,7 +231,7 @@ "key": "0x212f20473e051f38a3e883e04c615db86c000c11b7afcc5d9736f30c2a634a78" }, "0xcf1a8a7f273da1bd3112750cc3691b46c541e8b7": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0xa67b52462cb55b02cdc3b77317c72ba356565052daa741c56db173834086bf29", "codeHash": "0x1f958654ab06a152993e7a0ae7b6dbb0d4b19265cc9337b8789fe1353bd9dc35", @@ -246,7 +246,7 @@ "key": "0x81f151b659eee15d57be7e42c54519f089683a2663c2d73e920317ec91831100" }, "0xd16dba9f860146f08c9ee83b891c138667021ec9": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0xd71f41c241891e04095a92d2faafea7012de6d509ce9b855c4aad8523d3abe94", "codeHash": "0x1f958654ab06a152993e7a0ae7b6dbb0d4b19265cc9337b8789fe1353bd9dc35", @@ -258,7 +258,7 @@ "key": "0x3c75634c38fdffac6bd90c0b6feb19aef829f6f952f8331c21b7694d21c185de" }, "0xec466e9a46914507c484dcc5caba1db787e34913": { - "balance": "0", + "balance": "0x0", "nonce": 1, "root": "0x82c7f6f047f8e47468199468dab7c7bff9e01ed86ddf466e930363f12781776e", "codeHash": "0x30dd4c41053621e6ecb9d600526b682dcce4370e8c206f016e2ad0ff4ea6b6c8", @@ -276,4 +276,4 @@ "key": "0xb4791e53424376e737591737af96068778ec34c34df6df5bb044678dee3a2887" } } -} \ No newline at end of file +} diff --git a/op-chain-ops/genesis/testdata/test-deploy-config-full.json b/op-chain-ops/genesis/testdata/test-deploy-config-full.json index c3d36153d440..65390c661acc 100644 --- a/op-chain-ops/genesis/testdata/test-deploy-config-full.json +++ b/op-chain-ops/genesis/testdata/test-deploy-config-full.json @@ -71,9 +71,20 @@ "faultGameGenesisBlock": 0, "faultGameGenesisOutputRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "faultGameSplitDepth": 0, + "faultGameWithdrawalDelay": 604800, "preimageOracleMinProposalSize": 1800000, "preimageOracleChallengePeriod": 86400, "systemConfigStartBlock": 0, "requiredProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", - "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000" + "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", + "proofMaturityDelaySeconds": 12, + "disputeGameFinalityDelaySeconds": 6, + "respectedGameType": 0, + "useFaultProofs": false, + "usePlasma": false, + "daBondSize": 0, + "daChallengeProxy": "0x0000000000000000000000000000000000000000", + "daChallengeWindow": 0, + "daResolveWindow": 0, + "daResolverRefundPercentage": 0 } diff --git a/op-chain-ops/immutables/immutables.go b/op-chain-ops/immutables/immutables.go index a3f9697936b5..ac945b77a337 100644 --- a/op-chain-ops/immutables/immutables.go +++ b/op-chain-ops/immutables/immutables.go @@ -192,10 +192,6 @@ func l2ImmutableDeployer(backend *backends.SimulatedBackend, opts *bind.Transact } switch deployment.Name { - case "L2CrossDomainMessenger": - _, tx, _, err = bindings.DeployL2CrossDomainMessenger(opts, backend) - case "L2StandardBridge": - _, tx, _, err = bindings.DeployL2StandardBridge(opts, backend) case "SequencerFeeVault": recipient, minimumWithdrawalAmount, withdrawalNetwork, err = prepareFeeVaultArguments(deployment) if err != nil { @@ -214,10 +210,6 @@ func l2ImmutableDeployer(backend *backends.SimulatedBackend, opts *bind.Transact return nil, err } _, tx, _, err = bindings.DeployL1FeeVault(opts, backend, recipient, minimumWithdrawalAmount, withdrawalNetwork) - case "OptimismMintableERC20Factory": - _, tx, _, err = bindings.DeployOptimismMintableERC20Factory(opts, backend) - case "L2ERC721Bridge": - _, tx, _, err = bindings.DeployL2ERC721Bridge(opts, backend) case "OptimismMintableERC721Factory": bridge, ok := deployment.Args[0].(common.Address) if !ok { diff --git a/op-chain-ops/state/memory_db.go b/op-chain-ops/state/memory_db.go index e7cd375eabe5..2e8c8470f839 100644 --- a/op-chain-ops/state/memory_db.go +++ b/op-chain-ops/state/memory_db.go @@ -16,7 +16,10 @@ import ( var _ vm.StateDB = (*MemoryStateDB)(nil) -var emptyCodeHash = crypto.Keccak256(nil) +var ( + emptyCodeHash = crypto.Keccak256(nil) + zeroAddr = common.Address{} +) // MemoryStateDB implements geth's StateDB interface // but operates on a core.Genesis so that a genesis.json @@ -28,7 +31,7 @@ type MemoryStateDB struct { func NewMemoryStateDB(genesis *core.Genesis) *MemoryStateDB { if genesis == nil { - genesis = core.DeveloperGenesisBlock(15_000_000, common.Address{}) + genesis = core.DeveloperGenesisBlock(15_000_000, &zeroAddr) } return &MemoryStateDB{ diff --git a/op-chain-ops/state/state.go b/op-chain-ops/state/state.go index 96156f1c13c5..b3788081c0cf 100644 --- a/op-chain-ops/state/state.go +++ b/op-chain-ops/state/state.go @@ -73,6 +73,7 @@ func ComputeStorageSlots(layout *solc.StorageLayout, values StorageValues) ([]*E for _, entry := range layout.Storage { if label == entry.Label { target = entry + break } } if target.Label == "" { diff --git a/op-chain-ops/upgrades/check.go b/op-chain-ops/upgrades/check.go index 6239c23a1451..5eb4fc79c4b9 100644 --- a/op-chain-ops/upgrades/check.go +++ b/op-chain-ops/upgrades/check.go @@ -42,7 +42,7 @@ func CheckL1(ctx context.Context, list *superchain.ImplementationList, backend b // CheckVersionedContract will check that the version of the deployed contract matches // the artifact in the superchain registry. func CheckVersionedContract(ctx context.Context, contract superchain.VersionedContract, backend bind.ContractBackend) error { - addr := common.HexToAddress(contract.Address.String()) + addr := common.Address(contract.Address) code, err := backend.CodeAt(ctx, addr, nil) if err != nil { return err @@ -65,31 +65,31 @@ func GetContractVersions(ctx context.Context, addresses *superchain.AddressList, var versions superchain.ContractVersions var err error - versions.L1CrossDomainMessenger, err = getVersion(ctx, common.HexToAddress(addresses.L1CrossDomainMessengerProxy.String()), backend) + versions.L1CrossDomainMessenger, err = getVersion(ctx, common.Address(addresses.L1CrossDomainMessengerProxy), backend) if err != nil { return versions, fmt.Errorf("L1CrossDomainMessenger: %w", err) } - versions.L1ERC721Bridge, err = getVersion(ctx, common.HexToAddress(addresses.L1ERC721BridgeProxy.String()), backend) + versions.L1ERC721Bridge, err = getVersion(ctx, common.Address(addresses.L1ERC721BridgeProxy), backend) if err != nil { return versions, fmt.Errorf("L1ERC721Bridge: %w", err) } - versions.L1StandardBridge, err = getVersion(ctx, common.HexToAddress(addresses.L1StandardBridgeProxy.String()), backend) + versions.L1StandardBridge, err = getVersion(ctx, common.Address(addresses.L1StandardBridgeProxy), backend) if err != nil { return versions, fmt.Errorf("L1StandardBridge: %w", err) } - versions.L2OutputOracle, err = getVersion(ctx, common.HexToAddress(addresses.L2OutputOracleProxy.String()), backend) + versions.L2OutputOracle, err = getVersion(ctx, common.Address(addresses.L2OutputOracleProxy), backend) if err != nil { return versions, fmt.Errorf("L2OutputOracle: %w", err) } - versions.OptimismMintableERC20Factory, err = getVersion(ctx, common.HexToAddress(addresses.OptimismMintableERC20FactoryProxy.String()), backend) + versions.OptimismMintableERC20Factory, err = getVersion(ctx, common.Address(addresses.OptimismMintableERC20FactoryProxy), backend) if err != nil { return versions, fmt.Errorf("OptimismMintableERC20Factory: %w", err) } - versions.OptimismPortal, err = getVersion(ctx, common.HexToAddress(addresses.OptimismPortalProxy.String()), backend) + versions.OptimismPortal, err = getVersion(ctx, common.Address(addresses.OptimismPortalProxy), backend) if err != nil { return versions, fmt.Errorf("OptimismPortal: %w", err) } - versions.SystemConfig, err = getVersion(ctx, common.HexToAddress(chainConfig.SystemConfigAddr.String()), backend) + versions.SystemConfig, err = getVersion(ctx, common.Address(addresses.SystemConfigProxy), backend) if err != nil { return versions, fmt.Errorf("SystemConfig: %w", err) } @@ -122,17 +122,3 @@ func cmpVersion(v1, v2 string) bool { } return v1 == v2 } - -// ToSuperchainName turns a base layer chain id into a superchain network name. -func ToSuperchainName(chainID uint64) (string, error) { - if chainID == 1 { - return "mainnet", nil - } - if chainID == 5 { - return "goerli", nil - } - if chainID == 11155111 { - return "sepolia", nil - } - return "", fmt.Errorf("unsupported chain ID %d", chainID) -} diff --git a/op-chain-ops/upgrades/l1.go b/op-chain-ops/upgrades/l1.go index f269fa36cc0c..56383710e919 100644 --- a/op-chain-ops/upgrades/l1.go +++ b/op-chain-ops/upgrades/l1.go @@ -86,11 +86,11 @@ func L1CrossDomainMessenger(batch *safe.Batch, implementations superchain.Implem return err } args := []any{ - common.HexToAddress(list.L1CrossDomainMessengerProxy.String()), + common.Address(list.L1CrossDomainMessengerProxy), storageSetterAddr, calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } @@ -101,7 +101,7 @@ func L1CrossDomainMessenger(batch *safe.Batch, implementations superchain.Implem return err } - l1CrossDomainMessenger, err := bindings.NewL1CrossDomainMessengerCaller(common.HexToAddress(list.L1CrossDomainMessengerProxy.String()), backend) + l1CrossDomainMessenger, err := bindings.NewL1CrossDomainMessengerCaller(common.Address(list.L1CrossDomainMessengerProxy), backend) if err != nil { return err } @@ -115,11 +115,11 @@ func L1CrossDomainMessenger(batch *safe.Batch, implementations superchain.Implem } if optimismPortal != common.Address(list.OptimismPortalProxy) { - return fmt.Errorf("upgrading L1CrossDomainMessenger: Portal address doesn't match config") + return fmt.Errorf("Portal address doesn't match config") } if otherMessenger != predeploys.L2CrossDomainMessengerAddr { - return fmt.Errorf("upgrading L1CrossDomainMessenger: OtherMessenger address doesn't match config") + return fmt.Errorf("OtherMessenger address doesn't match config") } calldata, err := l1CrossDomainMessengerABI.Pack("initialize", superchainConfigProxy, optimismPortal) @@ -128,12 +128,12 @@ func L1CrossDomainMessenger(batch *safe.Batch, implementations superchain.Implem } args := []any{ - common.HexToAddress(list.L1CrossDomainMessengerProxy.String()), - common.HexToAddress(implementations.L1CrossDomainMessenger.Address.String()), + common.Address(list.L1CrossDomainMessengerProxy), + common.Address(implementations.L1CrossDomainMessenger.Address), calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } @@ -168,11 +168,11 @@ func L1ERC721Bridge(batch *safe.Batch, implementations superchain.Implementation return fmt.Errorf("setBytes32: %w", err) } args := []any{ - common.HexToAddress(list.L1ERC721BridgeProxy.String()), + common.Address(list.L1ERC721BridgeProxy), storageSetterAddr, calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } @@ -183,7 +183,7 @@ func L1ERC721Bridge(batch *safe.Batch, implementations superchain.Implementation return err } - l1ERC721Bridge, err := bindings.NewL1ERC721BridgeCaller(common.HexToAddress(list.L1ERC721BridgeProxy.String()), backend) + l1ERC721Bridge, err := bindings.NewL1ERC721BridgeCaller(common.Address(list.L1ERC721BridgeProxy), backend) if err != nil { return err } @@ -197,11 +197,11 @@ func L1ERC721Bridge(batch *safe.Batch, implementations superchain.Implementation } if messenger != common.Address(list.L1CrossDomainMessengerProxy) { - return fmt.Errorf("upgrading L1ERC721Bridge: Messenger address doesn't match config") + return fmt.Errorf("Messenger address doesn't match config") } if otherBridge != predeploys.L2ERC721BridgeAddr { - return fmt.Errorf("upgrading L1ERC721Bridge: OtherBridge address doesn't match config") + return fmt.Errorf("OtherBridge address doesn't match config") } calldata, err := l1ERC721BridgeABI.Pack("initialize", messenger, superchainConfigProxy) @@ -210,12 +210,12 @@ func L1ERC721Bridge(batch *safe.Batch, implementations superchain.Implementation } args := []any{ - common.HexToAddress(list.L1ERC721BridgeProxy.String()), - common.HexToAddress(implementations.L1ERC721Bridge.Address.String()), + common.Address(list.L1ERC721BridgeProxy), + common.Address(implementations.L1ERC721Bridge.Address), calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } @@ -250,11 +250,11 @@ func L1StandardBridge(batch *safe.Batch, implementations superchain.Implementati return err } args := []any{ - common.HexToAddress(list.L1StandardBridgeProxy.String()), + common.Address(list.L1StandardBridgeProxy), storageSetterAddr, calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } @@ -265,7 +265,7 @@ func L1StandardBridge(batch *safe.Batch, implementations superchain.Implementati return err } - l1StandardBridge, err := bindings.NewL1StandardBridgeCaller(common.HexToAddress(list.L1StandardBridgeProxy.String()), backend) + l1StandardBridge, err := bindings.NewL1StandardBridgeCaller(common.Address(list.L1StandardBridgeProxy), backend) if err != nil { return err } @@ -281,11 +281,11 @@ func L1StandardBridge(batch *safe.Batch, implementations superchain.Implementati } if messenger != common.Address(list.L1CrossDomainMessengerProxy) { - return fmt.Errorf("upgrading L1StandardBridge: Messenger address doesn't match config") + return fmt.Errorf("Messenger address doesn't match config") } if otherBridge != predeploys.L2StandardBridgeAddr { - return fmt.Errorf("upgrading L1StandardBridge: OtherBridge address doesn't match config") + return fmt.Errorf("OtherBridge address doesn't match config") } calldata, err := l1StandardBridgeABI.Pack("initialize", messenger, superchainConfigProxy) @@ -294,12 +294,12 @@ func L1StandardBridge(batch *safe.Batch, implementations superchain.Implementati } args := []any{ - common.HexToAddress(list.L1StandardBridgeProxy.String()), - common.HexToAddress(implementations.L1StandardBridge.Address.String()), + common.Address(list.L1StandardBridgeProxy), + common.Address(implementations.L1StandardBridge.Address), calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } @@ -334,11 +334,11 @@ func L2OutputOracle(batch *safe.Batch, implementations superchain.Implementation return err } args := []any{ - common.HexToAddress(list.L2OutputOracleProxy.String()), + common.Address(list.L2OutputOracleProxy), storageSetterAddr, calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } @@ -349,7 +349,7 @@ func L2OutputOracle(batch *safe.Batch, implementations superchain.Implementation return err } - l2OutputOracle, err := bindings.NewL2OutputOracleCaller(common.HexToAddress(list.L2OutputOracleProxy.String()), backend) + l2OutputOracle, err := bindings.NewL2OutputOracleCaller(common.Address(list.L2OutputOracleProxy), backend) if err != nil { return err } @@ -391,15 +391,15 @@ func L2OutputOracle(batch *safe.Batch, implementations superchain.Implementation if config != nil { if l2OutputOracleSubmissionInterval.Uint64() != config.L2OutputOracleSubmissionInterval { - return fmt.Errorf("upgrading L2OutputOracle: L2OutputOracleSubmissionInterval address doesn't match config") + return fmt.Errorf("L2OutputOracleSubmissionInterval address doesn't match config") } if l2BlockTime.Uint64() != config.L2BlockTime { - return fmt.Errorf("upgrading L2OutputOracle: L2BlockTime address doesn't match config") + return fmt.Errorf("L2BlockTime address doesn't match config") } if l2OutputOracleStartingBlockNumber.Uint64() != config.L2OutputOracleStartingBlockNumber { - return fmt.Errorf("upgrading L2OutputOracle: L2OutputOracleStartingBlockNumber address doesn't match config") + return fmt.Errorf("L2OutputOracleStartingBlockNumber address doesn't match config") } if config.L2OutputOracleStartingTimestamp < 0 { @@ -407,19 +407,19 @@ func L2OutputOracle(batch *safe.Batch, implementations superchain.Implementation } if int(l2OutputOracleStartingTimestamp.Int64()) != config.L2OutputOracleStartingTimestamp { - return fmt.Errorf("upgrading L2OutputOracle: L2OutputOracleStartingTimestamp address doesn't match config") + return fmt.Errorf("L2OutputOracleStartingTimestamp address doesn't match config") } if l2OutputOracleProposer != config.L2OutputOracleProposer { - return fmt.Errorf("upgrading L2OutputOracle: L2OutputOracleProposer address doesn't match config") + return fmt.Errorf("L2OutputOracleProposer address doesn't match config") } if l2OutputOracleChallenger != config.L2OutputOracleChallenger { - return fmt.Errorf("upgrading L2OutputOracle: L2OutputOracleChallenger address doesn't match config") + return fmt.Errorf("L2OutputOracleChallenger address doesn't match config") } if finalizationPeriodSeconds.Uint64() != config.FinalizationPeriodSeconds { - return fmt.Errorf("upgrading L2OutputOracle: FinalizationPeriodSeconds address doesn't match config") + return fmt.Errorf("FinalizationPeriodSeconds address doesn't match config") } } @@ -438,12 +438,12 @@ func L2OutputOracle(batch *safe.Batch, implementations superchain.Implementation } args := []any{ - common.HexToAddress(list.L2OutputOracleProxy.String()), - common.HexToAddress(implementations.L2OutputOracle.Address.String()), + common.Address(list.L2OutputOracleProxy), + common.Address(implementations.L2OutputOracle.Address), calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } @@ -478,11 +478,11 @@ func OptimismMintableERC20Factory(batch *safe.Batch, implementations superchain. return err } args := []any{ - common.HexToAddress(list.OptimismMintableERC20FactoryProxy.String()), + common.Address(list.OptimismMintableERC20FactoryProxy), storageSetterAddr, calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } @@ -493,7 +493,7 @@ func OptimismMintableERC20Factory(batch *safe.Batch, implementations superchain. return err } - optimismMintableERC20Factory, err := bindings.NewOptimismMintableERC20FactoryCaller(common.HexToAddress(list.OptimismMintableERC20FactoryProxy.String()), backend) + optimismMintableERC20Factory, err := bindings.NewOptimismMintableERC20FactoryCaller(common.Address(list.OptimismMintableERC20FactoryProxy), backend) if err != nil { return err } @@ -504,7 +504,7 @@ func OptimismMintableERC20Factory(batch *safe.Batch, implementations superchain. } if bridge != common.Address(list.L1StandardBridgeProxy) { - return fmt.Errorf("upgrading OptimismMintableERC20Factory: Bridge address doesn't match config") + return fmt.Errorf("Bridge address doesn't match config") } calldata, err := optimismMintableERC20FactoryABI.Pack("initialize", bridge) @@ -513,12 +513,12 @@ func OptimismMintableERC20Factory(batch *safe.Batch, implementations superchain. } args := []any{ - common.HexToAddress(list.OptimismMintableERC20FactoryProxy.String()), - common.HexToAddress(implementations.OptimismMintableERC20Factory.Address.String()), + common.Address(list.OptimismMintableERC20FactoryProxy), + common.Address(implementations.OptimismMintableERC20Factory.Address), calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } @@ -553,11 +553,11 @@ func OptimismPortal(batch *safe.Batch, implementations superchain.Implementation return err } args := []any{ - common.HexToAddress(list.OptimismPortalProxy.String()), + common.Address(list.OptimismPortalProxy), storageSetterAddr, calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } @@ -568,7 +568,7 @@ func OptimismPortal(batch *safe.Batch, implementations superchain.Implementation return err } - optimismPortal, err := bindings.NewOptimismPortalCaller(common.HexToAddress(list.OptimismPortalProxy.String()), backend) + optimismPortal, err := bindings.NewOptimismPortalCaller(common.Address(list.OptimismPortalProxy), backend) if err != nil { return err } @@ -581,12 +581,12 @@ func OptimismPortal(batch *safe.Batch, implementations superchain.Implementation return err } - if l2OutputOracle != common.HexToAddress(list.L2OutputOracleProxy.String()) { - return fmt.Errorf("upgrading OptimismPortal: L2OutputOracle address doesn't match config") + if l2OutputOracle != common.Address(list.L2OutputOracleProxy) { + return fmt.Errorf("L2OutputOracle address doesn't match config") } - if systemConfig != common.HexToAddress(chainConfig.SystemConfigAddr.String()) { - return fmt.Errorf("upgrading OptimismPortal: SystemConfig address doesn't match config") + if systemConfig != common.Address(list.SystemConfigProxy) { + return fmt.Errorf("SystemConfig address doesn't match config") } calldata, err := optimismPortalABI.Pack("initialize", l2OutputOracle, systemConfig, superchainConfigProxy) @@ -595,12 +595,12 @@ func OptimismPortal(batch *safe.Batch, implementations superchain.Implementation } args := []any{ - common.HexToAddress(list.OptimismPortalProxy.String()), - common.HexToAddress(implementations.OptimismPortal.Address.String()), + common.Address(list.OptimismPortalProxy), + common.Address(implementations.OptimismPortal.Address), calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } @@ -646,11 +646,11 @@ func SystemConfig(batch *safe.Batch, implementations superchain.ImplementationLi return err } args := []any{ - common.HexToAddress(chainConfig.SystemConfigAddr.String()), + common.Address(list.SystemConfigProxy), storageSetterAddr, calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } @@ -661,7 +661,7 @@ func SystemConfig(batch *safe.Batch, implementations superchain.ImplementationLi return err } - systemConfig, err := bindings.NewSystemConfigCaller(common.HexToAddress(chainConfig.SystemConfigAddr.String()), backend) + systemConfig, err := bindings.NewSystemConfigCaller(common.Address(list.SystemConfigProxy), backend) if err != nil { return err } @@ -696,25 +696,47 @@ func SystemConfig(batch *safe.Batch, implementations superchain.ImplementationLi return err } - if config != nil { - if gasPriceOracleOverhead.Uint64() != config.GasPriceOracleOverhead { - return fmt.Errorf("upgrading SystemConfig: GasPriceOracleOverhead address doesn't match config") - } - if gasPriceOracleScalar.Uint64() != config.GasPriceOracleScalar { - return fmt.Errorf("upgrading SystemConfig: GasPriceOracleScalar address doesn't match config") - } - if batcherHash != common.BytesToHash(config.BatchSenderAddress.Bytes()) { - return fmt.Errorf("upgrading SystemConfig: BatchSenderAddress address doesn't match config") - } - if l2GenesisBlockGasLimit != uint64(config.L2GenesisBlockGasLimit) { - return fmt.Errorf("upgrading SystemConfig: L2GenesisBlockGasLimit address doesn't match config") - } - if p2pSequencerAddress != config.P2PSequencerAddress { - return fmt.Errorf("upgrading SystemConfig: P2PSequencerAddress address doesn't match config") - } - if finalSystemOwner != config.FinalSystemOwner { - return fmt.Errorf("upgrading SystemConfig: FinalSystemOwner address doesn't match config") - } + if gasPriceOracleOverhead.Uint64() != config.GasPriceOracleOverhead { + return fmt.Errorf("GasPriceOracleOverhead address doesn't match config") + } + if gasPriceOracleScalar.Uint64() != config.GasPriceOracleScalar { + return fmt.Errorf("GasPriceOracleScalar address doesn't match config") + } + if batcherHash != common.BytesToHash(config.BatchSenderAddress.Bytes()) { + return fmt.Errorf("BatchSenderAddress address doesn't match config") + } + if l2GenesisBlockGasLimit != uint64(config.L2GenesisBlockGasLimit) { + return fmt.Errorf("L2GenesisBlockGasLimit address doesn't match config") + } + if p2pSequencerAddress != config.P2PSequencerAddress { + return fmt.Errorf("P2PSequencerAddress address doesn't match config") + } + if finalSystemOwner != config.FinalSystemOwner { + return fmt.Errorf("FinalSystemOwner address doesn't match config") + } + + resourceConfig, err := systemConfig.ResourceConfig(&bind.CallOpts{}) + if err != nil { + return err + } + + if resourceConfig.MaxResourceLimit != genesis.DefaultResourceConfig.MaxResourceLimit { + return fmt.Errorf("DefaultResourceConfig MaxResourceLimit doesn't match contract MaxResourceLimit") + } + if resourceConfig.ElasticityMultiplier != genesis.DefaultResourceConfig.ElasticityMultiplier { + return fmt.Errorf("DefaultResourceConfig ElasticityMultiplier doesn't match contract ElasticityMultiplier") + } + if resourceConfig.BaseFeeMaxChangeDenominator != genesis.DefaultResourceConfig.BaseFeeMaxChangeDenominator { + return fmt.Errorf("DefaultResourceConfig BaseFeeMaxChangeDenominator doesn't match contract BaseFeeMaxChangeDenominator") + } + if resourceConfig.MinimumBaseFee != genesis.DefaultResourceConfig.MinimumBaseFee { + return fmt.Errorf("DefaultResourceConfig MinimumBaseFee doesn't match contract MinimumBaseFee") + } + if resourceConfig.SystemTxMaxGas != genesis.DefaultResourceConfig.SystemTxMaxGas { + return fmt.Errorf("DefaultResourceConfig SystemTxMaxGas doesn't match contract SystemTxMaxGas") + } + if resourceConfig.MaximumBaseFee.Cmp(genesis.DefaultResourceConfig.MaximumBaseFee) != 0 { + return fmt.Errorf("DefaultResourceConfig MaximumBaseFee doesn't match contract MaximumBaseFee") } calldata, err := systemConfigABI.Pack( @@ -741,12 +763,12 @@ func SystemConfig(batch *safe.Batch, implementations superchain.ImplementationLi } args := []any{ - common.HexToAddress(chainConfig.SystemConfigAddr.String()), - common.HexToAddress(implementations.SystemConfig.Address.String()), + common.Address(list.SystemConfigProxy), + common.Address(implementations.SystemConfig.Address), calldata, } - proxyAdmin := common.HexToAddress(list.ProxyAdmin.String()) + proxyAdmin := common.Address(list.ProxyAdmin) if err := batch.AddCall(proxyAdmin, common.Big0, upgradeAndCall, args, proxyAdminABI); err != nil { return err } diff --git a/op-challenger/README.md b/op-challenger/README.md index f05f7b54f01d..3d740dc5703e 100644 --- a/op-challenger/README.md +++ b/op-challenger/README.md @@ -1,48 +1,42 @@ # op-challenger -The `op-challenger` is a modular **op-stack** challenge agent -written in golang for dispute games including, but not limited to, attestation games, fault -games, and validity games. To learn more about dispute games, visit the -[fault proof specs](../specs/fault-proof.md). +The `op-challenger` is a modular **op-stack** challenge agent written in +golang for dispute games including, but not limited to,attestation games, +fault games, and validity games. To learn more about dispute games, visit +the [fault proof specs][proof-specs]. -## Quickstart - -First, clone this repo. Then run: - -```shell -cd op-challenger -make alphabet -``` +[proof-specs]: https://specs.optimism.io/experimental/fault-proof/index.html -This creates a local devnet, starts a dispute game using the simple alphabet trace type and runs two op-challenger -instances with differing views of the correct alphabet to play the game. +## Quickstart -Alternatively, you can build the `op-challenger` binary directly using the pre-configured -[Makefile](./Makefile) target by running `make build`, and then running `./bin/op-challenger --help` -to see a list of available options. +To build the `op-challenger`, run `make` (which executes the `make build` +[Makefile](./Makefile) target). To view a list of available commands and +options, run `./bin/op-challenger --help`. ## Usage -`op-challenger` is configurable via command line flags and environment variables. The help menu -shows the available config options and can be accessed by running `./op-challenger --help`. +`op-challenger` is configurable via command line flags and environment +variables. The help menu shows the available config options and can be +accessed by running `./op-challenger --help`. ### Running with Cannon on Local Devnet -To run `op-challenger` against the local devnet, first ensure the required components are built and the devnet is running. -From the top level of the repository run: - +To run `op-challenger` against the local devnet, first clean and run +the devnet from the root of the repository. ```shell make devnet-clean -make op-challenger make devnet-up ``` -Then start `op-challenger` with: +Then build the `op-challenger` with `make op-challenger`. + +Run the `op-challenger` with: ```shell DISPUTE_GAME_FACTORY=$(jq -r .DisputeGameFactoryProxy .devnet/addresses.json) ./op-challenger/bin/op-challenger \ --trace-type cannon \ --l1-eth-rpc http://localhost:8545 \ + --rollup-rpc http://localhost:9546 \ --game-factory-address $DISPUTE_GAME_FACTORY \ --datadir temp/challenger-data \ --cannon-rollup-config .devnet/rollup.json \ @@ -56,71 +50,61 @@ DISPUTE_GAME_FACTORY=$(jq -r .DisputeGameFactoryProxy .devnet/addresses.json) --num-confirmations 1 ``` -The mnemonic and hd-path above is a prefunded address on the devnet. The challenger respond to any created games by -posting the correct trace as the counter-claim. The scripts below can then be used to create and interact with games. - -## Scripts +The mnemonic and hd-path above is a prefunded address on the devnet. +The challenger will monitor dispute games and respond to any invalid +claims by posting the correct trace as the counter-claim. The commands +below can then be used to create and interact with games. -The [scripts](scripts) directory contains a collection of scripts to assist with manually creating and playing games. -This are not intended to be used in production, only to support manual testing and to aid with understanding how -dispute games work. They also serve as examples of how to use `cast` to manually interact with the dispute game -contracts. +## Subcommands -### Understanding Revert Reasons +The `op-challenger` has a few subcommands to interact with on-chain +fault dispute games. The subcommands support game creation, performing +game moves, and viewing fault dispute game data. They should not be +used in production and are intended to provide convenient manual testing. -When actions performed by these scripts fails, they typically print a message that includes the -abi encoded revert reason provided by the contract. e.g. - -``` -Error: -(code: 3, message: execution reverted, data: Some(String("0x67fe1950"))) -``` - -The `cast 4byte` command can be used to decode these revert reasons. e.g. +### create-game ```shell -$ cast 4byte 0x67fe1950 -GameNotInProgress() +./bin/op-challenger create-game \ + --l1-eth-rpc \ + --game-address \ + --output-root \ + --l2-block-num \ + ... ``` -### Dependencies - -These scripts assume that the following tools are installed and available on the current `PATH`: - -* `cast` (https://book.getfoundry.sh/cast/) -* `jq` (https://jqlang.github.io/jq/) -* `bash` +Starts a new fault dispute game that disputes the latest output proposal +in the L2 output oracle. -### [create_game.sh](scripts/create_game.sh) - -```shell -./scripts/create_game.sh ... -``` - -Starts a new fault dispute game that disputes the latest output proposal in the L2 output oracle. - -* `RPC_URL` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). +* `L1_ETH_RPC` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). * `GAME_FACTORY_ADDRESS` - the address of the dispute game factory contract on L1. * `OUTPUT_ROOT` a hex encoded 32 byte hash that is used as the proposed output root. * `L2_BLOCK_NUM` the L2 block number the proposed output root is from. -* `SIGNER_ARGS` the remaining args are past as arguments to `cast` when sending transactions. - These arguments must specify a way for `cast` to sign the transactions. +* `SIGNER_ARGS` the remaining args are past as arguments to `cast` when sending + transactions. These arguments must specify a way for `cast` to sign the transactions. See `cast send --help` for supported options. -Creating a dispute game requires sending two transactions. The first transaction creates a -checkpoint in the `BlockOracle` that records the L1 block that will be used as the L1 head -when generating the cannon execution trace. The second transaction then creates the actual -dispute game, specifying the disputed L2 block number and previously checkpointed L1 head block. +Optionally, you may specify the game type (aka "trace type") using the `--trace-type` +flag, which is set to the cannon trace type by default. + +### move -### [move.sh](scripts/move.sh) +The `move` subcommand can be run with either the `--attack` or `--defend` flag, +but not both. ```shell -./scripts/move.sh (attack|defend) ... +./bin/op-challenger move \ + --l1-eth-rpc \ + --game-address \ + --attack \ + --parent-index \ + --claim \ + ... ``` Performs a move to either attack or defend the latest claim in the specified game. -* `RPC_URL` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). +* `L1_ETH_RPC` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). * `GAME_ADDRESS` - the address of the dispute game to perform the move in. * `(attack|defend)` - the type of move to make. * `attack` indicates that the state hash in your local cannon trace differs to the state @@ -134,40 +118,47 @@ Performs a move to either attack or defend the latest claim in the specified gam These arguments must specify a way for `cast` to sign the transactions. See `cast send --help` for supported options. -### [resolve.sh](scripts/resolve.sh) +### resolve ```shell -./scripts/resolve.sh ... +./bin/op-challenger resolve \ + --l1-eth-rpc \ + --game-address \ + ... ``` -Resolves a dispute game. Note that this will fail if the dispute game has already been resolved -or if the clocks have not yet expired and further moves are possible. +Resolves a dispute game. Note that this will fail if the dispute game has already +been resolved or if the clocks have not yet expired and further moves are possible. If the game is resolved successfully, the result is printed. -* `RPC_URL` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). +* `L1_ETH_RPC` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). * `GAME_ADDRESS` - the address of the dispute game to resolve. * `SIGNER_ARGS` the remaining args are past as arguments to `cast` when sending transactions. These arguments must specify a way for `cast` to sign the transactions. See `cast send --help` for supported options. -### [list_games.sh](scripts/list_games.sh) +### list-games ```shell -./scripts/list_games.sh +./bin/op-challenger list-games \ + --l1-eth-rpc \ + --game-factory-address ``` Prints the games created by the game factory along with their current status. -* `RPC_URL` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). +* `L1_ETH_RPC` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). * `GAME_FACTORY_ADDRESS` - the address of the dispute game factory contract on L1. -### [list_claims.sh](scripts/list_claims.sh) +### list-claims ```shell -./scripts/list_claims.sh +./bin/op-challenger list-games \ + --l1-eth-rpc \ + --game-address ``` Prints the list of current claims in a dispute game. -* `RPC_URL` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). +* `L1_ETH_RPC` - the RPC endpoint of the L1 endpoint to use (e.g. `http://localhost:8545`). * `GAME_ADDRESS` - the address of the dispute game to list the move in. diff --git a/op-challenger/challenger.go b/op-challenger/challenger.go index 74451fdbadae..574f27fc74ec 100644 --- a/op-challenger/challenger.go +++ b/op-challenger/challenger.go @@ -15,6 +15,5 @@ func Main(ctx context.Context, logger log.Logger, cfg *config.Config) (cliapp.Li if err := cfg.Check(); err != nil { return nil, err } - srv, err := game.NewService(ctx, logger, cfg) - return srv, err + return game.NewService(ctx, logger, cfg) } diff --git a/op-challenger/challenger_test.go b/op-challenger/challenger_test.go index 2464e0dcf296..666e656e2c0f 100644 --- a/op-challenger/challenger_test.go +++ b/op-challenger/challenger_test.go @@ -12,7 +12,7 @@ import ( func TestMainShouldReturnErrorWhenConfigInvalid(t *testing.T) { cfg := &config.Config{} - app, err := Main(context.Background(), testlog.Logger(t, log.LvlInfo), cfg) + app, err := Main(context.Background(), testlog.Logger(t, log.LevelInfo), cfg) require.ErrorIs(t, err, cfg.Check()) require.Nil(t, app) } diff --git a/op-challenger/cmd/create_game.go b/op-challenger/cmd/create_game.go new file mode 100644 index 000000000000..7053b4eee3a8 --- /dev/null +++ b/op-challenger/cmd/create_game.go @@ -0,0 +1,85 @@ +package main + +import ( + "context" + "fmt" + + "github.com/ethereum-optimism/optimism/op-challenger/config" + "github.com/ethereum-optimism/optimism/op-challenger/flags" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" + opservice "github.com/ethereum-optimism/optimism/op-service" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" + "github.com/urfave/cli/v2" +) + +var ( + TraceTypeFlag = &cli.StringFlag{ + Name: "trace-type", + Usage: "Trace types to support.", + EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "TRACE_TYPE"), + Value: config.TraceTypeCannon.String(), + } + OutputRootFlag = &cli.StringFlag{ + Name: "output-root", + Usage: "The output root for the fault dispute game.", + EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "OUTPUT_ROOT"), + } + L2BlockNumFlag = &cli.StringFlag{ + Name: "l2-block-num", + Usage: "The l2 block number for the game.", + EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "L2_BLOCK_NUM"), + } +) + +func CreateGame(ctx *cli.Context) error { + outputRoot := common.HexToHash(ctx.String(OutputRootFlag.Name)) + traceType := ctx.Uint64(TraceTypeFlag.Name) + l2BlockNum := ctx.Uint64(L2BlockNumFlag.Name) + + contract, txMgr, err := NewContractWithTxMgr[*contracts.DisputeGameFactoryContract](ctx, flags.FactoryAddressFlag.Name, contracts.NewDisputeGameFactoryContract) + if err != nil { + return fmt.Errorf("failed to create dispute game factory bindings: %w", err) + } + + txCandidate, err := contract.CreateTx(uint32(traceType), outputRoot, l2BlockNum) + if err != nil { + return fmt.Errorf("failed to create tx: %w", err) + } + + rct, err := txMgr.Send(context.Background(), txCandidate) + if err != nil { + return fmt.Errorf("failed to send tx: %w", err) + } + fmt.Printf("Sent create transaction with status %v, tx_hash: %s\n", rct.Status, rct.TxHash.String()) + + fetchedGameAddr, err := contract.GetGameFromParameters(context.Background(), uint32(traceType), outputRoot, l2BlockNum) + if err != nil { + return fmt.Errorf("failed to call games: %w", err) + } + fmt.Printf("Fetched Game Address: %s\n", fetchedGameAddr.String()) + + return nil +} + +func createGameFlags() []cli.Flag { + cliFlags := []cli.Flag{ + flags.L1EthRpcFlag, + flags.FactoryAddressFlag, + OutputRootFlag, + L2BlockNumFlag, + } + cliFlags = append(cliFlags, txmgr.CLIFlagsWithDefaults(flags.EnvVarPrefix, txmgr.DefaultChallengerFlagValues)...) + cliFlags = append(cliFlags, oplog.CLIFlags(flags.EnvVarPrefix)...) + return cliFlags +} + +var CreateGameCommand = &cli.Command{ + Name: "create-game", + Usage: "Creates a dispute game via the factory", + Description: "Creates a dispute game via the factory", + Action: CreateGame, + Flags: createGameFlags(), + Hidden: true, +} diff --git a/op-challenger/cmd/list_claims.go b/op-challenger/cmd/list_claims.go index 52f3cb0a3863..6fb51a7e1bb7 100644 --- a/op-challenger/cmd/list_claims.go +++ b/op-challenger/cmd/list_claims.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum-optimism/optimism/op-service/dial" oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/urfave/cli/v2" ) @@ -17,7 +18,7 @@ var ( GameAddressFlag = &cli.StringFlag{ Name: "game-address", Usage: "Address of the fault game contract.", - EnvVars: opservice.PrefixEnvVar("OP_CHALLENGER", "GAME_FACTORY_ADDRESS"), + EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "GAME_ADDRESS"), } ) @@ -67,7 +68,7 @@ func listClaims(ctx context.Context, game *contracts.FaultDisputeGameContract) e return fmt.Errorf("failed to retrieve status: %w", err) } - claims, err := game.GetAllClaims(ctx) + claims, err := game.GetAllClaims(ctx, rpcblock.Latest) if err != nil { return fmt.Errorf("failed to retrieve claims: %w", err) } @@ -83,13 +84,13 @@ func listClaims(ctx context.Context, game *contracts.FaultDisputeGameContract) e return nil } -var listClaimsFlags = []cli.Flag{ - flags.L1EthRpcFlag, - GameAddressFlag, -} - -func init() { - listClaimsFlags = append(listClaimsFlags, oplog.CLIFlags("OP_CHALLENGER")...) +func listClaimsFlags() []cli.Flag { + cliFlags := []cli.Flag{ + flags.L1EthRpcFlag, + GameAddressFlag, + } + cliFlags = append(cliFlags, oplog.CLIFlags("OP_CHALLENGER")...) + return cliFlags } var ListClaimsCommand = &cli.Command{ @@ -97,6 +98,6 @@ var ListClaimsCommand = &cli.Command{ Usage: "List the claims in a dispute game", Description: "Lists the claims in a dispute game", Action: ListClaims, - Flags: listClaimsFlags, + Flags: listClaimsFlags(), Hidden: true, } diff --git a/op-challenger/cmd/list_games.go b/op-challenger/cmd/list_games.go index 52fc00f3b706..ce7ddb13cde9 100644 --- a/op-challenger/cmd/list_games.go +++ b/op-challenger/cmd/list_games.go @@ -100,13 +100,13 @@ func listGames(ctx context.Context, caller *batching.MultiCaller, factory *contr return nil } -var listGamesFlags = []cli.Flag{ - flags.L1EthRpcFlag, - flags.FactoryAddressFlag, -} - -func init() { - listGamesFlags = append(listGamesFlags, oplog.CLIFlags("OP_CHALLENGER")...) +func listGamesFlags() []cli.Flag { + cliFlags := []cli.Flag{ + flags.L1EthRpcFlag, + flags.FactoryAddressFlag, + } + cliFlags = append(cliFlags, oplog.CLIFlags("OP_CHALLENGER")...) + return cliFlags } var ListGamesCommand = &cli.Command{ @@ -114,6 +114,6 @@ var ListGamesCommand = &cli.Command{ Usage: "List the games created by a dispute game factory", Description: "Lists the games created by a dispute game factory", Action: ListGames, - Flags: listGamesFlags, + Flags: listGamesFlags(), Hidden: true, } diff --git a/op-challenger/cmd/main.go b/op-challenger/cmd/main.go index e6797219e516..292959049dbd 100644 --- a/op-challenger/cmd/main.go +++ b/op-challenger/cmd/main.go @@ -48,6 +48,9 @@ func run(ctx context.Context, args []string, action ConfiguredLifecycle) error { app.Commands = []*cli.Command{ ListGamesCommand, ListClaimsCommand, + CreateGameCommand, + MoveCommand, + ResolveCommand, } app.Action = cliapp.LifecycleCmd(func(ctx *cli.Context, close context.CancelCauseFunc) (cliapp.Lifecycle, error) { logger, err := setupLogging(ctx) @@ -68,6 +71,6 @@ func run(ctx context.Context, args []string, action ConfiguredLifecycle) error { func setupLogging(ctx *cli.Context) (log.Logger, error) { logCfg := oplog.ReadCLIConfig(ctx) logger := oplog.NewLogger(oplog.AppOut(ctx), logCfg) - oplog.SetGlobalLogHandler(logger.GetHandler()) + oplog.SetGlobalLogHandler(logger.Handler()) return logger, nil } diff --git a/op-challenger/cmd/main_test.go b/op-challenger/cmd/main_test.go index b27fdfc8b880..d8d5e0d4bce0 100644 --- a/op-challenger/cmd/main_test.go +++ b/op-challenger/cmd/main_test.go @@ -19,6 +19,7 @@ import ( var ( l1EthRpc = "http://example.com:8545" + l1Beacon = "http://example.com:9000" gameFactoryAddressValue = "0xbb00000000000000000000000000000000000000" cannonNetwork = "op-mainnet" otherCannonNetwork = "op-goerli" @@ -47,14 +48,14 @@ func TestLogLevel(t *testing.T) { func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) { cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet)) - defaultCfg := config.NewConfig(common.HexToAddress(gameFactoryAddressValue), l1EthRpc, datadir, config.TraceTypeAlphabet) + defaultCfg := config.NewConfig(common.HexToAddress(gameFactoryAddressValue), l1EthRpc, l1Beacon, datadir, config.TraceTypeAlphabet) // Add in the extra CLI options required when using alphabet trace type defaultCfg.RollupRpc = rollupRpc require.Equal(t, defaultCfg, cfg) } func TestDefaultConfigIsValid(t *testing.T) { - cfg := config.NewConfig(common.HexToAddress(gameFactoryAddressValue), l1EthRpc, datadir, config.TraceTypeAlphabet) + cfg := config.NewConfig(common.HexToAddress(gameFactoryAddressValue), l1EthRpc, l1Beacon, datadir, config.TraceTypeAlphabet) // Add in options that are required based on the specific trace type // To avoid needing to specify unused options, these aren't included in the params for NewConfig cfg.RollupRpc = rollupRpc @@ -74,6 +75,18 @@ func TestL1ETHRPCAddress(t *testing.T) { }) } +func TestL1Beacon(t *testing.T) { + t.Run("Required", func(t *testing.T) { + verifyArgsInvalid(t, "flag l1-beacon is required", addRequiredArgsExcept(config.TraceTypeAlphabet, "--l1-beacon")) + }) + + t.Run("Valid", func(t *testing.T) { + url := "http://example.com:8888" + cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--l1-beacon", "--l1-beacon="+url)) + require.Equal(t, url, cfg.L1Beacon) + }) +} + func TestTraceType(t *testing.T) { t.Run("Default", func(t *testing.T) { expectedDefault := config.TraceTypeCannon @@ -102,8 +115,10 @@ func TestMultipleTraceTypes(t *testing.T) { // Add extra trace types (cannon is already specified) args = append(args, "--trace-type", config.TraceTypeAlphabet.String()) + args = append(args, + "--trace-type", config.TraceTypePermissioned.String()) cfg := configForArgs(t, args) - require.Equal(t, []config.TraceType{config.TraceTypeCannon, config.TraceTypeAlphabet}, cfg.TraceTypes) + require.Equal(t, []config.TraceType{config.TraceTypeCannon, config.TraceTypeAlphabet, config.TraceTypePermissioned}, cfg.TraceTypes) }) t.Run("WithSomeOptions", func(t *testing.T) { argsMap := requiredArgs(config.TraceTypeCannon) @@ -188,6 +203,26 @@ func TestMaxConcurrency(t *testing.T) { }) } +func TestMaxPendingTx(t *testing.T) { + t.Run("Valid", func(t *testing.T) { + expected := uint64(345) + cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet, "--max-pending-tx", "345")) + require.Equal(t, expected, cfg.MaxPendingTx) + }) + + t.Run("Zero", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet, "--max-pending-tx", "0")) + require.Equal(t, uint64(0), cfg.MaxPendingTx) + }) + + t.Run("Invalid", func(t *testing.T) { + verifyArgsInvalid( + t, + "invalid value \"abc\" for flag -max-pending-tx", + addRequiredArgs(config.TraceTypeAlphabet, "--max-pending-tx", "abc")) + }) +} + func TestPollInterval(t *testing.T) { t.Run("UsesDefault", func(t *testing.T) { cfg := configForArgs(t, addRequiredArgs(config.TraceTypeCannon)) @@ -208,127 +243,193 @@ func TestPollInterval(t *testing.T) { }) } -func TestCannonBin(t *testing.T) { - t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { - configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-bin")) - }) +func TestCannonRequiredArgs(t *testing.T) { + for _, traceType := range []config.TraceType{config.TraceTypeCannon, config.TraceTypePermissioned} { + traceType := traceType + t.Run(fmt.Sprintf("TestCannonBin-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-bin")) + }) + + t.Run("Required", func(t *testing.T) { + verifyArgsInvalid(t, "flag cannon-bin is required", addRequiredArgsExcept(traceType, "--cannon-bin")) + }) + + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-bin", "--cannon-bin=./cannon")) + require.Equal(t, "./cannon", cfg.CannonBin) + }) + }) - t.Run("Required", func(t *testing.T) { - verifyArgsInvalid(t, "flag cannon-bin is required", addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-bin")) - }) + t.Run(fmt.Sprintf("TestCannonServer-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-server")) + }) - t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-bin", "--cannon-bin=./cannon")) - require.Equal(t, "./cannon", cfg.CannonBin) - }) -} + t.Run("Required", func(t *testing.T) { + verifyArgsInvalid(t, "flag cannon-server is required", addRequiredArgsExcept(traceType, "--cannon-server")) + }) -func TestCannonServer(t *testing.T) { - t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { - configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-server")) - }) + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-server", "--cannon-server=./op-program")) + require.Equal(t, "./op-program", cfg.CannonServer) + }) + }) - t.Run("Required", func(t *testing.T) { - verifyArgsInvalid(t, "flag cannon-server is required", addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-server")) - }) + t.Run(fmt.Sprintf("TestCannonAbsolutePrestate-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-prestate")) + }) - t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-server", "--cannon-server=./op-program")) - require.Equal(t, "./op-program", cfg.CannonServer) - }) -} + t.Run("Required", func(t *testing.T) { + verifyArgsInvalid(t, "flag cannon-prestate is required", addRequiredArgsExcept(traceType, "--cannon-prestate")) + }) -func TestCannonAbsolutePrestate(t *testing.T) { - t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { - configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-prestate")) - }) + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-prestate", "--cannon-prestate=./pre.json")) + require.Equal(t, "./pre.json", cfg.CannonAbsolutePreState) + }) + }) - t.Run("Required", func(t *testing.T) { - verifyArgsInvalid(t, "flag cannon-prestate is required", addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-prestate")) - }) + t.Run(fmt.Sprintf("TestCannonL2-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-l2")) + }) - t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-prestate", "--cannon-prestate=./pre.json")) - require.Equal(t, "./pre.json", cfg.CannonAbsolutePreState) - }) -} + t.Run("RequiredForCannonTrace", func(t *testing.T) { + verifyArgsInvalid(t, "flag cannon-l2 is required", addRequiredArgsExcept(traceType, "--cannon-l2")) + }) -func TestDataDir(t *testing.T) { - t.Run("RequiredForAlphabetTrace", func(t *testing.T) { - verifyArgsInvalid(t, "flag datadir is required", addRequiredArgsExcept(config.TraceTypeAlphabet, "--datadir")) - }) + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgs(traceType)) + require.Equal(t, cannonL2, cfg.CannonL2) + }) + }) - t.Run("RequiredForCannonTrace", func(t *testing.T) { - verifyArgsInvalid(t, "flag datadir is required", addRequiredArgsExcept(config.TraceTypeCannon, "--datadir")) - }) + t.Run(fmt.Sprintf("TestCannonSnapshotFreq-%v", traceType), func(t *testing.T) { + t.Run("UsesDefault", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgs(traceType)) + require.Equal(t, config.DefaultCannonSnapshotFreq, cfg.CannonSnapshotFreq) + }) + + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgs(traceType, "--cannon-snapshot-freq=1234")) + require.Equal(t, uint(1234), cfg.CannonSnapshotFreq) + }) + + t.Run("Invalid", func(t *testing.T) { + verifyArgsInvalid(t, "invalid value \"abc\" for flag -cannon-snapshot-freq", + addRequiredArgs(traceType, "--cannon-snapshot-freq=abc")) + }) + }) - t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--datadir", "--datadir=/foo/bar/cannon")) - require.Equal(t, "/foo/bar/cannon", cfg.Datadir) - }) -} + t.Run(fmt.Sprintf("TestCannonInfoFreq-%v", traceType), func(t *testing.T) { + t.Run("UsesDefault", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgs(traceType)) + require.Equal(t, config.DefaultCannonInfoFreq, cfg.CannonInfoFreq) + }) + + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgs(traceType, "--cannon-info-freq=1234")) + require.Equal(t, uint(1234), cfg.CannonInfoFreq) + }) + + t.Run("Invalid", func(t *testing.T) { + verifyArgsInvalid(t, "invalid value \"abc\" for flag -cannon-info-freq", + addRequiredArgs(traceType, "--cannon-info-freq=abc")) + }) + }) -func TestRollupRpc(t *testing.T) { - t.Run("RequiredForAlphabetTrace", func(t *testing.T) { - verifyArgsInvalid(t, "flag rollup-rpc is required", addRequiredArgsExcept(config.TraceTypeAlphabet, "--rollup-rpc")) - }) + t.Run(fmt.Sprintf("TestRequireEitherCannonNetworkOrRollupAndGenesis-%v", traceType), func(t *testing.T) { + verifyArgsInvalid( + t, + "flag cannon-network or cannon-rollup-config and cannon-l2-genesis is required", + addRequiredArgsExcept(traceType, "--cannon-network")) + verifyArgsInvalid( + t, + "flag cannon-network or cannon-rollup-config and cannon-l2-genesis is required", + addRequiredArgsExcept(traceType, "--cannon-network", "--cannon-rollup-config=rollup.json")) + verifyArgsInvalid( + t, + "flag cannon-network or cannon-rollup-config and cannon-l2-genesis is required", + addRequiredArgsExcept(traceType, "--cannon-network", "--cannon-l2-genesis=gensis.json")) + }) - t.Run("RequiredForCannonTrace", func(t *testing.T) { - verifyArgsInvalid(t, "flag rollup-rpc is required", addRequiredArgsExcept(config.TraceTypeCannon, "--rollup-rpc")) - }) + t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndRollup-%v", traceType), func(t *testing.T) { + verifyArgsInvalid( + t, + "flag cannon-network can not be used with cannon-rollup-config and cannon-l2-genesis", + addRequiredArgsExcept(traceType, "--cannon-network", + "--cannon-network", cannonNetwork, "--cannon-rollup-config=rollup.json")) + }) - t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgs(config.TraceTypeCannon)) - require.Equal(t, rollupRpc, cfg.RollupRpc) - }) -} + t.Run(fmt.Sprintf("TestCannonNetwork-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-network")) + }) -func TestCannonL2(t *testing.T) { - t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { - configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-l2")) - }) + t.Run("NotRequiredWhenRollupAndGenesIsSpecified", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-network", + "--cannon-rollup-config=rollup.json", "--cannon-l2-genesis=genesis.json")) + }) - t.Run("RequiredForCannonTrace", func(t *testing.T) { - verifyArgsInvalid(t, "flag cannon-l2 is required", addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-l2")) - }) + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-network", "--cannon-network", otherCannonNetwork)) + require.Equal(t, otherCannonNetwork, cfg.CannonNetwork) + }) + }) - t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgs(config.TraceTypeCannon)) - require.Equal(t, cannonL2, cfg.CannonL2) - }) -} + t.Run(fmt.Sprintf("TestCannonRollupConfig-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-rollup-config")) + }) -func TestCannonSnapshotFreq(t *testing.T) { - t.Run("UsesDefault", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgs(config.TraceTypeCannon)) - require.Equal(t, config.DefaultCannonSnapshotFreq, cfg.CannonSnapshotFreq) - }) + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-network", "--cannon-rollup-config=rollup.json", "--cannon-l2-genesis=genesis.json")) + require.Equal(t, "rollup.json", cfg.CannonRollupConfigPath) + }) + }) - t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgs(config.TraceTypeCannon, "--cannon-snapshot-freq=1234")) - require.Equal(t, uint(1234), cfg.CannonSnapshotFreq) - }) + t.Run(fmt.Sprintf("TestCannonL2Genesis-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-l2-genesis")) + }) - t.Run("Invalid", func(t *testing.T) { - verifyArgsInvalid(t, "invalid value \"abc\" for flag -cannon-snapshot-freq", - addRequiredArgs(config.TraceTypeCannon, "--cannon-snapshot-freq=abc")) - }) + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--cannon-network", "--cannon-rollup-config=rollup.json", "--cannon-l2-genesis=genesis.json")) + require.Equal(t, "genesis.json", cfg.CannonL2GenesisPath) + }) + }) + } } -func TestCannonInfoFreq(t *testing.T) { - t.Run("UsesDefault", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgs(config.TraceTypeCannon)) - require.Equal(t, config.DefaultCannonInfoFreq, cfg.CannonInfoFreq) - }) +func TestDataDir(t *testing.T) { + for _, traceType := range config.TraceTypes { + traceType := traceType + + t.Run(fmt.Sprintf("RequiredFor-%v", traceType), func(t *testing.T) { + verifyArgsInvalid(t, "flag datadir is required", addRequiredArgsExcept(traceType, "--datadir")) + }) + } t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgs(config.TraceTypeCannon, "--cannon-info-freq=1234")) - require.Equal(t, uint(1234), cfg.CannonInfoFreq) + cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--datadir", "--datadir=/foo/bar/cannon")) + require.Equal(t, "/foo/bar/cannon", cfg.Datadir) }) +} - t.Run("Invalid", func(t *testing.T) { - verifyArgsInvalid(t, "invalid value \"abc\" for flag -cannon-info-freq", - addRequiredArgs(config.TraceTypeCannon, "--cannon-info-freq=abc")) +func TestRollupRpc(t *testing.T) { + for _, traceType := range config.TraceTypes { + traceType := traceType + + t.Run(fmt.Sprintf("RequiredFor-%v", traceType), func(t *testing.T) { + verifyArgsInvalid(t, "flag rollup-rpc is required", addRequiredArgsExcept(traceType, "--rollup-rpc")) + }) + } + + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgs(config.TraceTypeCannon)) + require.Equal(t, rollupRpc, cfg.RollupRpc) }) } @@ -344,69 +445,68 @@ func TestGameWindow(t *testing.T) { }) t.Run("ParsesDefault", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet, "--game-window=264h")) + cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet, "--game-window=360h")) require.Equal(t, config.DefaultGameWindow, cfg.GameWindow) }) } -func TestRequireEitherCannonNetworkOrRollupAndGenesis(t *testing.T) { - verifyArgsInvalid( - t, - "flag cannon-network or cannon-rollup-config and cannon-l2-genesis is required", - addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network")) - verifyArgsInvalid( - t, - "flag cannon-network or cannon-rollup-config and cannon-l2-genesis is required", - addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network", "--cannon-rollup-config=rollup.json")) - verifyArgsInvalid( - t, - "flag cannon-network or cannon-rollup-config and cannon-l2-genesis is required", - addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network", "--cannon-l2-genesis=gensis.json")) -} - -func TestMustNotSpecifyNetworkAndRollup(t *testing.T) { - verifyArgsInvalid( - t, - "flag cannon-network can not be used with cannon-rollup-config and cannon-l2-genesis", - addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network", - "--cannon-network", cannonNetwork, "--cannon-rollup-config=rollup.json")) -} +func TestUnsafeAllowInvalidPrestate(t *testing.T) { + t.Run("DefaultsToFalse", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--unsafe-allow-invalid-prestate")) + require.False(t, cfg.AllowInvalidPrestate) + }) -func TestCannonNetwork(t *testing.T) { - t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { - configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-network")) + t.Run("EnabledWithNoValue", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgs(config.TraceTypeCannon, "--unsafe-allow-invalid-prestate")) + require.True(t, cfg.AllowInvalidPrestate) }) - t.Run("NotRequiredWhenRollupAndGenesIsSpecified", func(t *testing.T) { - configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network", - "--cannon-rollup-config=rollup.json", "--cannon-l2-genesis=genesis.json")) + t.Run("EnabledWithTrue", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgs(config.TraceTypeCannon, "--unsafe-allow-invalid-prestate=true")) + require.True(t, cfg.AllowInvalidPrestate) }) - t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network", "--cannon-network", otherCannonNetwork)) - require.Equal(t, otherCannonNetwork, cfg.CannonNetwork) + t.Run("DisabledWithFalse", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgs(config.TraceTypeCannon, "--unsafe-allow-invalid-prestate=false")) + require.False(t, cfg.AllowInvalidPrestate) }) } -func TestCannonRollupConfig(t *testing.T) { - t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { - configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-rollup-config")) +func TestAdditionalBondClaimants(t *testing.T) { + t.Run("DefaultsToEmpty", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--additional-bond-claimants")) + require.Empty(t, cfg.AdditionalBondClaimants) }) - t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network", "--cannon-rollup-config=rollup.json", "--cannon-l2-genesis=genesis.json")) - require.Equal(t, "rollup.json", cfg.CannonRollupConfigPath) + t.Run("Valid-Single", func(t *testing.T) { + claimant := common.Address{0xaa} + cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet, "--additional-bond-claimants", claimant.Hex())) + require.Contains(t, cfg.AdditionalBondClaimants, claimant) + require.Len(t, cfg.AdditionalBondClaimants, 1) }) -} -func TestCannonL2Genesis(t *testing.T) { - t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { - configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-l2-genesis")) + t.Run("Valid-Multiple", func(t *testing.T) { + claimant1 := common.Address{0xaa} + claimant2 := common.Address{0xbb} + claimant3 := common.Address{0xcc} + cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet, + "--additional-bond-claimants", fmt.Sprintf("%v,%v,%v", claimant1.Hex(), claimant2.Hex(), claimant3.Hex()))) + require.Contains(t, cfg.AdditionalBondClaimants, claimant1) + require.Contains(t, cfg.AdditionalBondClaimants, claimant2) + require.Contains(t, cfg.AdditionalBondClaimants, claimant3) + require.Len(t, cfg.AdditionalBondClaimants, 3) }) - t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--cannon-network", "--cannon-rollup-config=rollup.json", "--cannon-l2-genesis=genesis.json")) - require.Equal(t, "genesis.json", cfg.CannonL2GenesisPath) + t.Run("Invalid-Single", func(t *testing.T) { + verifyArgsInvalid(t, "invalid additional claimant", + addRequiredArgs(config.TraceTypeAlphabet, "--additional-bond-claimants", "nope")) + }) + + t.Run("Invalid-Multiple", func(t *testing.T) { + claimant1 := common.Address{0xaa} + claimant2 := common.Address{0xbb} + verifyArgsInvalid(t, "invalid additional claimant", + addRequiredArgs(config.TraceTypeAlphabet, "--additional-bond-claimants", fmt.Sprintf("%v,nope,%v", claimant1.Hex(), claimant2.Hex()))) }) } @@ -452,12 +552,13 @@ func addRequiredArgsExcept(traceType config.TraceType, name string, optionalArgs func requiredArgs(traceType config.TraceType) map[string]string { args := map[string]string{ "--l1-eth-rpc": l1EthRpc, + "--l1-beacon": l1Beacon, "--game-factory-address": gameFactoryAddressValue, "--trace-type": traceType.String(), "--datadir": datadir, } switch traceType { - case config.TraceTypeCannon: + case config.TraceTypeCannon, config.TraceTypePermissioned: addRequiredCannonArgs(args) case config.TraceTypeAlphabet: addRequiredOutputArgs(args) diff --git a/op-challenger/cmd/move.go b/op-challenger/cmd/move.go new file mode 100644 index 000000000000..a0854319ee7c --- /dev/null +++ b/op-challenger/cmd/move.go @@ -0,0 +1,99 @@ +package main + +import ( + "context" + "fmt" + + "github.com/ethereum-optimism/optimism/op-challenger/flags" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" + opservice "github.com/ethereum-optimism/optimism/op-service" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" + "github.com/urfave/cli/v2" +) + +var ( + AttackFlag = &cli.BoolFlag{ + Name: "attack", + Usage: "An attack move. If true, the defend flag must not be set.", + EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "ATTACK"), + } + DefendFlag = &cli.BoolFlag{ + Name: "defend", + Usage: "A defending move. If true, the attack flag must not be set.", + EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "DEFEND"), + } + ParentIndexFlag = &cli.StringFlag{ + Name: "parent-index", + Usage: "The index of the claim to move on.", + EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "PARENT_INDEX"), + } + ClaimFlag = &cli.StringFlag{ + Name: "claim", + Usage: "The claim hash.", + EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "CLAIM"), + } +) + +func Move(ctx *cli.Context) error { + attack := ctx.Bool(AttackFlag.Name) + defend := ctx.Bool(DefendFlag.Name) + parentIndex := ctx.Uint64(ParentIndexFlag.Name) + claim := common.HexToHash(ctx.String(ClaimFlag.Name)) + + if attack && defend { + return fmt.Errorf("both attack and defense flags cannot be set") + } + + contract, txMgr, err := NewContractWithTxMgr[*contracts.FaultDisputeGameContract](ctx, GameAddressFlag.Name, contracts.NewFaultDisputeGameContract) + if err != nil { + return fmt.Errorf("failed to create dispute game bindings: %w", err) + } + + var tx txmgr.TxCandidate + if attack { + tx, err = contract.AttackTx(parentIndex, claim) + if err != nil { + return fmt.Errorf("failed to create attack tx: %w", err) + } + } else if defend { + tx, err = contract.DefendTx(parentIndex, claim) + if err != nil { + return fmt.Errorf("failed to create defense tx: %w", err) + } + } else { + return fmt.Errorf("either attack or defense flag must be set") + } + + rct, err := txMgr.Send(context.Background(), tx) + if err != nil { + return fmt.Errorf("failed to send tx: %w", err) + } + fmt.Printf("Sent tx with status: %v, hash: %s\n", rct.Status, rct.TxHash.String()) + + return nil +} + +func moveFlags() []cli.Flag { + cliFlags := []cli.Flag{ + flags.L1EthRpcFlag, + GameAddressFlag, + AttackFlag, + DefendFlag, + ParentIndexFlag, + ClaimFlag, + } + cliFlags = append(cliFlags, txmgr.CLIFlagsWithDefaults(flags.EnvVarPrefix, txmgr.DefaultChallengerFlagValues)...) + cliFlags = append(cliFlags, oplog.CLIFlags(flags.EnvVarPrefix)...) + return cliFlags +} + +var MoveCommand = &cli.Command{ + Name: "move", + Usage: "Creates and sends a move transaction to the dispute game", + Description: "Creates and sends a move transaction to the dispute game", + Action: Move, + Flags: moveFlags(), + Hidden: true, +} diff --git a/op-challenger/cmd/resolve.go b/op-challenger/cmd/resolve.go new file mode 100644 index 000000000000..5cbddffcbed3 --- /dev/null +++ b/op-challenger/cmd/resolve.go @@ -0,0 +1,52 @@ +package main + +import ( + "context" + "fmt" + + "github.com/ethereum-optimism/optimism/op-challenger/flags" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/urfave/cli/v2" +) + +func Resolve(ctx *cli.Context) error { + contract, txMgr, err := NewContractWithTxMgr[*contracts.FaultDisputeGameContract](ctx, GameAddressFlag.Name, contracts.NewFaultDisputeGameContract) + if err != nil { + return fmt.Errorf("failed to create dispute game bindings: %w", err) + } + + tx, err := contract.ResolveTx() + if err != nil { + return fmt.Errorf("failed to create resolve tx: %w", err) + } + + rct, err := txMgr.Send(context.Background(), tx) + if err != nil { + return fmt.Errorf("failed to send tx: %w", err) + } + + fmt.Printf("Sent resolve tx with status: %v, hash: %s\n", rct.Status, rct.TxHash.String()) + + return nil +} + +func resolveFlags() []cli.Flag { + cliFlags := []cli.Flag{ + flags.L1EthRpcFlag, + GameAddressFlag, + } + cliFlags = append(cliFlags, txmgr.CLIFlagsWithDefaults(flags.EnvVarPrefix, txmgr.DefaultChallengerFlagValues)...) + cliFlags = append(cliFlags, oplog.CLIFlags(flags.EnvVarPrefix)...) + return cliFlags +} + +var ResolveCommand = &cli.Command{ + Name: "resolve", + Usage: "Resolves the specified dispute game if possible", + Description: "Resolves the specified dispute game if possible", + Action: Resolve, + Flags: resolveFlags(), + Hidden: true, +} diff --git a/op-challenger/cmd/utils.go b/op-challenger/cmd/utils.go new file mode 100644 index 000000000000..e15a8bbd260d --- /dev/null +++ b/op-challenger/cmd/utils.go @@ -0,0 +1,76 @@ +package main + +import ( + "fmt" + + "github.com/ethereum-optimism/optimism/op-challenger/flags" + opservice "github.com/ethereum-optimism/optimism/op-service" + "github.com/ethereum-optimism/optimism/op-service/dial" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum-optimism/optimism/op-service/txmgr/metrics" + "github.com/ethereum/go-ethereum/common" + "github.com/urfave/cli/v2" +) + +type ContractCreator[T any] func(common.Address, *batching.MultiCaller) (T, error) + +// NewContractWithTxMgr creates a new contract and a transaction manager. +func NewContractWithTxMgr[T any](ctx *cli.Context, flagName string, creator ContractCreator[T]) (T, txmgr.TxManager, error) { + var contract T + caller, txMgr, err := newClientsFromCLI(ctx) + if err != nil { + return contract, nil, err + } + + created, err := newContractFromCLI(ctx, flagName, caller, creator) + if err != nil { + return contract, nil, err + } + + return created, txMgr, nil +} + +// newContractFromCLI creates a new contract from the CLI context. +func newContractFromCLI[T any](ctx *cli.Context, flagName string, caller *batching.MultiCaller, creator ContractCreator[T]) (T, error) { + var contract T + gameAddr, err := opservice.ParseAddress(ctx.String(flagName)) + if err != nil { + return contract, err + } + + created, err := creator(gameAddr, caller) + if err != nil { + return contract, fmt.Errorf("failed to create dispute game bindings: %w", err) + } + + return created, nil +} + +// newClientsFromCLI creates a new caller and transaction manager from the CLI context. +func newClientsFromCLI(ctx *cli.Context) (*batching.MultiCaller, txmgr.TxManager, error) { + logger, err := setupLogging(ctx) + if err != nil { + return nil, nil, err + } + + rpcUrl := ctx.String(flags.L1EthRpcFlag.Name) + if rpcUrl == "" { + return nil, nil, fmt.Errorf("missing %v", flags.L1EthRpcFlag.Name) + } + + l1Client, err := dial.DialEthClientWithTimeout(ctx.Context, dial.DefaultDialTimeout, logger, rpcUrl) + if err != nil { + return nil, nil, fmt.Errorf("failed to dial L1: %w", err) + } + defer l1Client.Close() + + caller := batching.NewMultiCaller(l1Client.Client(), batching.DefaultBatchSize) + txMgrConfig := txmgr.ReadCLIConfig(ctx) + txMgr, err := txmgr.NewSimpleTxManager("challenger", logger, &metrics.NoopTxMetrics{}, txMgrConfig) + if err != nil { + return nil, nil, fmt.Errorf("failed to create the transaction manager: %w", err) + } + + return caller, txMgr, nil +} diff --git a/op-challenger/config/config.go b/op-challenger/config/config.go index eb20295ce59e..d13c716b803f 100644 --- a/op-challenger/config/config.go +++ b/op-challenger/config/config.go @@ -24,6 +24,7 @@ var ( ErrMissingCannonServer = errors.New("missing cannon server") ErrMissingCannonAbsolutePreState = errors.New("missing cannon absolute pre-state") ErrMissingL1EthRPC = errors.New("missing l1 eth rpc url") + ErrMissingL1Beacon = errors.New("missing l1 beacon url") ErrMissingGameFactoryAddress = errors.New("missing game factory address") ErrMissingCannonSnapshotFreq = errors.New("missing cannon snapshot freq") ErrMissingCannonInfoFreq = errors.New("missing cannon info freq") @@ -38,23 +39,12 @@ var ( type TraceType string const ( - TraceTypeAlphabet TraceType = "alphabet" - TraceTypeCannon TraceType = "cannon" - - // Mainnet games - CannonFaultGameID = 0 - - // Devnet games - AlphabetFaultGameID = 255 + TraceTypeAlphabet TraceType = "alphabet" + TraceTypeCannon TraceType = "cannon" + TraceTypePermissioned TraceType = "permissioned" ) -var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon} - -// GameIdToString maps game IDs to their string representation. -var GameIdToString = map[uint8]string{ - CannonFaultGameID: "Cannon", - AlphabetFaultGameID: "Alphabet", -} +var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon, TraceTypePermissioned} func (t TraceType) String() string { return string(t) @@ -89,22 +79,29 @@ const ( DefaultCannonInfoFreq = uint(10_000_000) // DefaultGameWindow is the default maximum time duration in the past // that the challenger will look for games to progress. - // The default value is 11 days, which is a 4 day resolution buffer - // plus the 7 day game finalization window. - DefaultGameWindow = time.Duration(11 * 24 * time.Hour) + // The default value is 15 days, which is an 8 day resolution buffer + // and bond claiming buffer plus the 7 day game finalization window. + DefaultGameWindow = time.Duration(15 * 24 * time.Hour) + DefaultMaxPendingTx = 10 ) // Config is a well typed config that is parsed from the CLI params. // This also contains config options for auxiliary services. // It is used to initialize the challenger. type Config struct { - L1EthRpc string // L1 RPC Url - GameFactoryAddress common.Address // Address of the dispute game factory - GameAllowlist []common.Address // Allowlist of fault game addresses - GameWindow time.Duration // Maximum time duration to look for games to progress - Datadir string // Data Directory - MaxConcurrency uint // Maximum number of threads to use when progressing games - PollInterval time.Duration // Polling interval for latest-block subscription when using an HTTP RPC provider + L1EthRpc string // L1 RPC Url + L1Beacon string // L1 Beacon API Url + GameFactoryAddress common.Address // Address of the dispute game factory + GameAllowlist []common.Address // Allowlist of fault game addresses + GameWindow time.Duration // Maximum time duration to look for games to progress + Datadir string // Data Directory + MaxConcurrency uint // Maximum number of threads to use when progressing games + PollInterval time.Duration // Polling interval for latest-block subscription when using an HTTP RPC provider + AllowInvalidPrestate bool // Whether to allow responding to games where the prestate does not match + + AdditionalBondClaimants []common.Address // List of addresses to claim bonds for in addition to the tx manager sender + + SelectiveClaimResolution bool // Whether to only resolve claims for the claimants in AdditionalBondClaimants union [TxSender.From()] TraceTypes []TraceType // Type of traces supported @@ -122,6 +119,8 @@ type Config struct { CannonSnapshotFreq uint // Frequency of snapshots to create when executing cannon (in VM instructions) CannonInfoFreq uint // Frequency of cannon progress log messages (in VM instructions) + MaxPendingTx uint64 // Maximum number of pending transactions (0 == no limit) + TxMgrConfig txmgr.CLIConfig MetricsConfig opmetrics.CLIConfig PprofConfig oppprof.CLIConfig @@ -130,17 +129,21 @@ type Config struct { func NewConfig( gameFactoryAddress common.Address, l1EthRpc string, + l1BeaconApi string, datadir string, supportedTraceTypes ...TraceType, ) Config { return Config{ L1EthRpc: l1EthRpc, + L1Beacon: l1BeaconApi, GameFactoryAddress: gameFactoryAddress, MaxConcurrency: uint(runtime.NumCPU()), PollInterval: DefaultPollInterval, TraceTypes: supportedTraceTypes, + MaxPendingTx: DefaultMaxPendingTx, + TxMgrConfig: txmgr.NewCLIConfig(l1EthRpc, txmgr.DefaultChallengerFlagValues), MetricsConfig: opmetrics.DefaultCLIConfig(), PprofConfig: oppprof.DefaultCLIConfig(), @@ -161,6 +164,9 @@ func (c Config) Check() error { if c.L1EthRpc == "" { return ErrMissingL1EthRPC } + if c.L1Beacon == "" { + return ErrMissingL1Beacon + } if c.RollupRpc == "" { return ErrMissingRollupRpc } @@ -176,7 +182,7 @@ func (c Config) Check() error { if c.MaxConcurrency == 0 { return ErrMaxConcurrencyZero } - if c.TraceTypeEnabled(TraceTypeCannon) { + if c.TraceTypeEnabled(TraceTypeCannon) || c.TraceTypeEnabled(TraceTypePermissioned) { if c.CannonBin == "" { return ErrMissingCannonBin } diff --git a/op-challenger/config/config_test.go b/op-challenger/config/config_test.go index 20f4ba526e70..01210557c60d 100644 --- a/op-challenger/config/config_test.go +++ b/op-challenger/config/config_test.go @@ -1,6 +1,7 @@ package config import ( + "fmt" "runtime" "testing" @@ -12,6 +13,7 @@ import ( var ( validL1EthRpc = "http://localhost:8545" + validL1BeaconUrl = "http://localhost:9000" validGameFactoryAddress = common.Address{0x23} validCannonBin = "./bin/cannon" validCannonOpProgramBin = "./bin/op-program" @@ -22,9 +24,11 @@ var ( validRollupRpc = "http://localhost:8555" ) +var cannonTraceTypes = []TraceType{TraceTypeCannon, TraceTypePermissioned} + func validConfig(traceType TraceType) Config { - cfg := NewConfig(validGameFactoryAddress, validL1EthRpc, validDatadir, traceType) - if traceType == TraceTypeCannon { + cfg := NewConfig(validGameFactoryAddress, validL1EthRpc, validL1BeaconUrl, validDatadir, traceType) + if traceType == TraceTypeCannon || traceType == TraceTypePermissioned { cfg.CannonBin = validCannonBin cfg.CannonServer = validCannonOpProgramBin cfg.CannonAbsolutePreState = validCannonAbsolutPreState @@ -60,34 +64,112 @@ func TestL1EthRpcRequired(t *testing.T) { require.ErrorIs(t, config.Check(), ErrMissingL1EthRPC) } +func TestL1BeaconRequired(t *testing.T) { + config := validConfig(TraceTypeCannon) + config.L1Beacon = "" + require.ErrorIs(t, config.Check(), ErrMissingL1Beacon) +} + func TestGameFactoryAddressRequired(t *testing.T) { config := validConfig(TraceTypeCannon) config.GameFactoryAddress = common.Address{} require.ErrorIs(t, config.Check(), ErrMissingGameFactoryAddress) } -func TestGameAllowlistNotRequired(t *testing.T) { +func TestSelectiveClaimResolutionNotRequired(t *testing.T) { config := validConfig(TraceTypeCannon) - config.GameAllowlist = []common.Address{} + require.Equal(t, false, config.SelectiveClaimResolution) require.NoError(t, config.Check()) } -func TestCannonBinRequired(t *testing.T) { +func TestGameAllowlistNotRequired(t *testing.T) { config := validConfig(TraceTypeCannon) - config.CannonBin = "" - require.ErrorIs(t, config.Check(), ErrMissingCannonBin) + config.GameAllowlist = []common.Address{} + require.NoError(t, config.Check()) } -func TestCannonServerRequired(t *testing.T) { - config := validConfig(TraceTypeCannon) - config.CannonServer = "" - require.ErrorIs(t, config.Check(), ErrMissingCannonServer) -} +func TestCannonRequiredArgs(t *testing.T) { + for _, traceType := range cannonTraceTypes { + traceType := traceType -func TestCannonAbsolutePreStateRequired(t *testing.T) { - config := validConfig(TraceTypeCannon) - config.CannonAbsolutePreState = "" - require.ErrorIs(t, config.Check(), ErrMissingCannonAbsolutePreState) + t.Run(fmt.Sprintf("TestCannonBinRequired-%v", traceType), func(t *testing.T) { + config := validConfig(traceType) + config.CannonBin = "" + require.ErrorIs(t, config.Check(), ErrMissingCannonBin) + }) + + t.Run(fmt.Sprintf("TestCannonServerRequired-%v", traceType), func(t *testing.T) { + config := validConfig(traceType) + config.CannonServer = "" + require.ErrorIs(t, config.Check(), ErrMissingCannonServer) + }) + + t.Run(fmt.Sprintf("TestCannonAbsolutePreStateRequired-%v", traceType), func(t *testing.T) { + config := validConfig(traceType) + config.CannonAbsolutePreState = "" + require.ErrorIs(t, config.Check(), ErrMissingCannonAbsolutePreState) + }) + + t.Run(fmt.Sprintf("TestCannonL2Required-%v", traceType), func(t *testing.T) { + config := validConfig(traceType) + config.CannonL2 = "" + require.ErrorIs(t, config.Check(), ErrMissingCannonL2) + }) + + t.Run(fmt.Sprintf("TestCannonSnapshotFreq-%v", traceType), func(t *testing.T) { + t.Run("MustNotBeZero", func(t *testing.T) { + cfg := validConfig(traceType) + cfg.CannonSnapshotFreq = 0 + require.ErrorIs(t, cfg.Check(), ErrMissingCannonSnapshotFreq) + }) + }) + + t.Run(fmt.Sprintf("TestCannonInfoFreq-%v", traceType), func(t *testing.T) { + t.Run("MustNotBeZero", func(t *testing.T) { + cfg := validConfig(traceType) + cfg.CannonInfoFreq = 0 + require.ErrorIs(t, cfg.Check(), ErrMissingCannonInfoFreq) + }) + }) + + t.Run(fmt.Sprintf("TestCannonNetworkOrRollupConfigRequired-%v", traceType), func(t *testing.T) { + cfg := validConfig(traceType) + cfg.CannonNetwork = "" + cfg.CannonRollupConfigPath = "" + cfg.CannonL2GenesisPath = "genesis.json" + require.ErrorIs(t, cfg.Check(), ErrMissingCannonRollupConfig) + }) + + t.Run(fmt.Sprintf("TestCannonNetworkOrL2GenesisRequired-%v", traceType), func(t *testing.T) { + cfg := validConfig(traceType) + cfg.CannonNetwork = "" + cfg.CannonRollupConfigPath = "foo.json" + cfg.CannonL2GenesisPath = "" + require.ErrorIs(t, cfg.Check(), ErrMissingCannonL2Genesis) + }) + + t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndRollup-%v", traceType), func(t *testing.T) { + cfg := validConfig(traceType) + cfg.CannonNetwork = validCannonNetwork + cfg.CannonRollupConfigPath = "foo.json" + cfg.CannonL2GenesisPath = "" + require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndRollupConfig) + }) + + t.Run(fmt.Sprintf("TestMustNotSpecifyNetworkAndL2Genesis-%v", traceType), func(t *testing.T) { + cfg := validConfig(traceType) + cfg.CannonNetwork = validCannonNetwork + cfg.CannonRollupConfigPath = "" + cfg.CannonL2GenesisPath = "foo.json" + require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndL2Genesis) + }) + + t.Run(fmt.Sprintf("TestNetworkMustBeValid-%v", traceType), func(t *testing.T) { + cfg := validConfig(traceType) + cfg.CannonNetwork = "unknown" + require.ErrorIs(t, cfg.Check(), ErrCannonNetworkUnknown) + }) + } } func TestDatadirRequired(t *testing.T) { @@ -116,76 +198,15 @@ func TestHttpPollInterval(t *testing.T) { }) } -func TestRollupRpcRequired_Cannon(t *testing.T) { - config := validConfig(TraceTypeCannon) - config.RollupRpc = "" - require.ErrorIs(t, config.Check(), ErrMissingRollupRpc) -} - -func TestRollupRpcRequired_Alphabet(t *testing.T) { - config := validConfig(TraceTypeAlphabet) - config.RollupRpc = "" - require.ErrorIs(t, config.Check(), ErrMissingRollupRpc) -} - -func TestCannonL2Required(t *testing.T) { - config := validConfig(TraceTypeCannon) - config.CannonL2 = "" - require.ErrorIs(t, config.Check(), ErrMissingCannonL2) -} - -func TestCannonSnapshotFreq(t *testing.T) { - t.Run("MustNotBeZero", func(t *testing.T) { - cfg := validConfig(TraceTypeCannon) - cfg.CannonSnapshotFreq = 0 - require.ErrorIs(t, cfg.Check(), ErrMissingCannonSnapshotFreq) - }) -} - -func TestCannonInfoFreq(t *testing.T) { - t.Run("MustNotBeZero", func(t *testing.T) { - cfg := validConfig(TraceTypeCannon) - cfg.CannonInfoFreq = 0 - require.ErrorIs(t, cfg.Check(), ErrMissingCannonInfoFreq) - }) -} - -func TestCannonNetworkOrRollupConfigRequired(t *testing.T) { - cfg := validConfig(TraceTypeCannon) - cfg.CannonNetwork = "" - cfg.CannonRollupConfigPath = "" - cfg.CannonL2GenesisPath = "genesis.json" - require.ErrorIs(t, cfg.Check(), ErrMissingCannonRollupConfig) -} - -func TestCannonNetworkOrL2GenesisRequired(t *testing.T) { - cfg := validConfig(TraceTypeCannon) - cfg.CannonNetwork = "" - cfg.CannonRollupConfigPath = "foo.json" - cfg.CannonL2GenesisPath = "" - require.ErrorIs(t, cfg.Check(), ErrMissingCannonL2Genesis) -} - -func TestMustNotSpecifyNetworkAndRollup(t *testing.T) { - cfg := validConfig(TraceTypeCannon) - cfg.CannonNetwork = validCannonNetwork - cfg.CannonRollupConfigPath = "foo.json" - cfg.CannonL2GenesisPath = "" - require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndRollupConfig) -} - -func TestMustNotSpecifyNetworkAndL2Genesis(t *testing.T) { - cfg := validConfig(TraceTypeCannon) - cfg.CannonNetwork = validCannonNetwork - cfg.CannonRollupConfigPath = "" - cfg.CannonL2GenesisPath = "foo.json" - require.ErrorIs(t, cfg.Check(), ErrCannonNetworkAndL2Genesis) -} - -func TestNetworkMustBeValid(t *testing.T) { - cfg := validConfig(TraceTypeCannon) - cfg.CannonNetwork = "unknown" - require.ErrorIs(t, cfg.Check(), ErrCannonNetworkUnknown) +func TestRollupRpcRequired(t *testing.T) { + for _, traceType := range TraceTypes { + traceType := traceType + t.Run(traceType.String(), func(t *testing.T) { + config := validConfig(traceType) + config.RollupRpc = "" + require.ErrorIs(t, config.Check(), ErrMissingRollupRpc) + }) + } } func TestRequireConfigForMultipleTraceTypes(t *testing.T) { diff --git a/op-challenger/flags/flags.go b/op-challenger/flags/flags.go index 0c06f6892b70..718cd5c00b20 100644 --- a/op-challenger/flags/flags.go +++ b/op-challenger/flags/flags.go @@ -19,12 +19,10 @@ import ( "github.com/ethereum-optimism/optimism/op-service/txmgr" ) -const ( - envVarPrefix = "OP_CHALLENGER" -) +const EnvVarPrefix = "OP_CHALLENGER" func prefixEnvVars(name string) []string { - return opservice.PrefixEnvVar(envVarPrefix, name) + return opservice.PrefixEnvVar(EnvVarPrefix, name) } var ( @@ -34,6 +32,16 @@ var ( Usage: "HTTP provider URL for L1.", EnvVars: prefixEnvVars("L1_ETH_RPC"), } + L1BeaconFlag = &cli.StringFlag{ + Name: "l1-beacon", + Usage: "Address of L1 Beacon API endpoint to use", + EnvVars: prefixEnvVars("L1_BEACON"), + } + RollupRpcFlag = &cli.StringFlag{ + Name: "rollup-rpc", + Usage: "HTTP provider URL for the rollup node", + EnvVars: prefixEnvVars("ROLLUP_RPC"), + } FactoryAddressFlag = &cli.StringFlag{ Name: "game-factory-address", Usage: "Address of the fault game factory contract.", @@ -63,16 +71,22 @@ var ( EnvVars: prefixEnvVars("MAX_CONCURRENCY"), Value: uint(runtime.NumCPU()), } + MaxPendingTransactionsFlag = &cli.Uint64Flag{ + Name: "max-pending-tx", + Usage: "The maximum number of pending transactions. 0 for no limit.", + Value: config.DefaultMaxPendingTx, + EnvVars: prefixEnvVars("MAX_PENDING_TX"), + } HTTPPollInterval = &cli.DurationFlag{ Name: "http-poll-interval", Usage: "Polling interval for latest-block subscription when using an HTTP RPC provider.", EnvVars: prefixEnvVars("HTTP_POLL_INTERVAL"), Value: config.DefaultPollInterval, } - RollupRpcFlag = &cli.StringFlag{ - Name: "rollup-rpc", - Usage: "HTTP provider URL for the rollup node", - EnvVars: prefixEnvVars("ROLLUP_RPC"), + AdditionalBondClaimants = &cli.StringSliceFlag{ + Name: "additional-bond-claimants", + Usage: "List of addresses to claim bonds for, in addition to the configured transaction sender", + EnvVars: prefixEnvVars("ADDITIONAL_BOND_CLAIMANTS"), } CannonNetworkFlag = &cli.StringFlag{ Name: "cannon-network", @@ -125,11 +139,23 @@ var ( Value: config.DefaultCannonInfoFreq, } GameWindowFlag = &cli.DurationFlag{ - Name: "game-window", - Usage: "The time window which the challenger will look for games to progress.", + Name: "game-window", + Usage: "The time window which the challenger will look for games to progress and claim bonds. " + + "This should include a buffer for the challenger to claim bonds for games outside the maximum game duration.", EnvVars: prefixEnvVars("GAME_WINDOW"), Value: config.DefaultGameWindow, } + SelectiveClaimResolutionFlag = &cli.BoolFlag{ + Name: "selective-claim-resolution", + Usage: "Only resolve claims for the configured claimants", + EnvVars: prefixEnvVars("SELECTIVE_CLAIM_RESOLUTION"), + } + UnsafeAllowInvalidPrestate = &cli.BoolFlag{ + Name: "unsafe-allow-invalid-prestate", + Usage: "Allow responding to games where the absolute prestate is configured incorrectly. THIS IS UNSAFE!", + EnvVars: prefixEnvVars("UNSAFE_ALLOW_INVALID_PRESTATE"), + Hidden: true, // Hidden as this is an unsafe flag added only for testing purposes + } ) // requiredFlags are checked by [CheckRequired] @@ -137,14 +163,17 @@ var requiredFlags = []cli.Flag{ L1EthRpcFlag, FactoryAddressFlag, DatadirFlag, + RollupRpcFlag, + L1BeaconFlag, } // optionalFlags is a list of unchecked cli flags var optionalFlags = []cli.Flag{ TraceTypeFlag, MaxConcurrencyFlag, + MaxPendingTransactionsFlag, HTTPPollInterval, - RollupRpcFlag, + AdditionalBondClaimants, GameAllowlistFlag, CannonNetworkFlag, CannonRollupConfigFlag, @@ -156,13 +185,15 @@ var optionalFlags = []cli.Flag{ CannonSnapshotFreqFlag, CannonInfoFreqFlag, GameWindowFlag, + SelectiveClaimResolutionFlag, + UnsafeAllowInvalidPrestate, } func init() { - optionalFlags = append(optionalFlags, oplog.CLIFlags(envVarPrefix)...) - optionalFlags = append(optionalFlags, txmgr.CLIFlagsWithDefaults(envVarPrefix, txmgr.DefaultChallengerFlagValues)...) - optionalFlags = append(optionalFlags, opmetrics.CLIFlags(envVarPrefix)...) - optionalFlags = append(optionalFlags, oppprof.CLIFlags(envVarPrefix)...) + optionalFlags = append(optionalFlags, oplog.CLIFlags(EnvVarPrefix)...) + optionalFlags = append(optionalFlags, txmgr.CLIFlagsWithDefaults(EnvVarPrefix, txmgr.DefaultChallengerFlagValues)...) + optionalFlags = append(optionalFlags, opmetrics.CLIFlags(EnvVarPrefix)...) + optionalFlags = append(optionalFlags, oppprof.CLIFlags(EnvVarPrefix)...) Flags = append(requiredFlags, optionalFlags...) } @@ -204,17 +235,11 @@ func CheckRequired(ctx *cli.Context, traceTypes []config.TraceType) error { } for _, traceType := range traceTypes { switch traceType { - case config.TraceTypeCannon: + case config.TraceTypeCannon, config.TraceTypePermissioned: if err := CheckCannonFlags(ctx); err != nil { return err } - if !ctx.IsSet(RollupRpcFlag.Name) { - return fmt.Errorf("flag %s is required", RollupRpcFlag.Name) - } case config.TraceTypeAlphabet: - if !ctx.IsSet(RollupRpcFlag.Name) { - return fmt.Errorf("flag %s is required", RollupRpcFlag.Name) - } default: return fmt.Errorf("invalid trace type. must be one of %v", config.TraceTypes) } @@ -268,28 +293,43 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) { if maxConcurrency == 0 { return nil, fmt.Errorf("%v must not be 0", MaxConcurrencyFlag.Name) } + var claimants []common.Address + if ctx.IsSet(AdditionalBondClaimants.Name) { + for _, addrStr := range ctx.StringSlice(AdditionalBondClaimants.Name) { + claimant, err := opservice.ParseAddress(addrStr) + if err != nil { + return nil, fmt.Errorf("invalid additional claimant: %w", err) + } + claimants = append(claimants, claimant) + } + } return &config.Config{ // Required Flags - L1EthRpc: ctx.String(L1EthRpcFlag.Name), - TraceTypes: traceTypes, - GameFactoryAddress: gameFactoryAddress, - GameAllowlist: allowedGames, - GameWindow: ctx.Duration(GameWindowFlag.Name), - MaxConcurrency: maxConcurrency, - PollInterval: ctx.Duration(HTTPPollInterval.Name), - RollupRpc: ctx.String(RollupRpcFlag.Name), - CannonNetwork: ctx.String(CannonNetworkFlag.Name), - CannonRollupConfigPath: ctx.String(CannonRollupConfigFlag.Name), - CannonL2GenesisPath: ctx.String(CannonL2GenesisFlag.Name), - CannonBin: ctx.String(CannonBinFlag.Name), - CannonServer: ctx.String(CannonServerFlag.Name), - CannonAbsolutePreState: ctx.String(CannonPreStateFlag.Name), - Datadir: ctx.String(DatadirFlag.Name), - CannonL2: ctx.String(CannonL2Flag.Name), - CannonSnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name), - CannonInfoFreq: ctx.Uint(CannonInfoFreqFlag.Name), - TxMgrConfig: txMgrConfig, - MetricsConfig: metricsConfig, - PprofConfig: pprofConfig, + L1EthRpc: ctx.String(L1EthRpcFlag.Name), + L1Beacon: ctx.String(L1BeaconFlag.Name), + TraceTypes: traceTypes, + GameFactoryAddress: gameFactoryAddress, + GameAllowlist: allowedGames, + GameWindow: ctx.Duration(GameWindowFlag.Name), + MaxConcurrency: maxConcurrency, + MaxPendingTx: ctx.Uint64(MaxPendingTransactionsFlag.Name), + PollInterval: ctx.Duration(HTTPPollInterval.Name), + AdditionalBondClaimants: claimants, + RollupRpc: ctx.String(RollupRpcFlag.Name), + CannonNetwork: ctx.String(CannonNetworkFlag.Name), + CannonRollupConfigPath: ctx.String(CannonRollupConfigFlag.Name), + CannonL2GenesisPath: ctx.String(CannonL2GenesisFlag.Name), + CannonBin: ctx.String(CannonBinFlag.Name), + CannonServer: ctx.String(CannonServerFlag.Name), + CannonAbsolutePreState: ctx.String(CannonPreStateFlag.Name), + Datadir: ctx.String(DatadirFlag.Name), + CannonL2: ctx.String(CannonL2Flag.Name), + CannonSnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name), + CannonInfoFreq: ctx.Uint(CannonInfoFreqFlag.Name), + TxMgrConfig: txMgrConfig, + MetricsConfig: metricsConfig, + PprofConfig: pprofConfig, + SelectiveClaimResolution: ctx.Bool(SelectiveClaimResolutionFlag.Name), + AllowInvalidPrestate: ctx.Bool(UnsafeAllowInvalidPrestate.Name), }, nil } diff --git a/op-challenger/game/fault/agent.go b/op-challenger/game/fault/agent.go index 755ccd7d8d1e..f67ef57336ce 100644 --- a/op-challenger/game/fault/agent.go +++ b/op-challenger/game/fault/agent.go @@ -4,12 +4,14 @@ import ( "context" "errors" "fmt" + "slices" "sync" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/solver" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-challenger/metrics" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) @@ -18,14 +20,14 @@ import ( // For full op-challenger this means executing the transaction on chain. type Responder interface { CallResolve(ctx context.Context) (gameTypes.GameStatus, error) - Resolve(ctx context.Context) error + Resolve() error CallResolveClaim(ctx context.Context, claimIdx uint64) error - ResolveClaim(ctx context.Context, claimIdx uint64) error + ResolveClaim(claimIdx uint64) error PerformAction(ctx context.Context, action types.Action) error } type ClaimLoader interface { - GetAllClaims(ctx context.Context) ([]types.Claim, error) + GetAllClaims(ctx context.Context, block rpcblock.Block) ([]types.Claim, error) } type Agent struct { @@ -33,16 +35,29 @@ type Agent struct { solver *solver.GameSolver loader ClaimLoader responder Responder + selective bool + claimants []common.Address maxDepth types.Depth log log.Logger } -func NewAgent(m metrics.Metricer, loader ClaimLoader, maxDepth types.Depth, trace types.TraceAccessor, responder Responder, log log.Logger) *Agent { +func NewAgent( + m metrics.Metricer, + loader ClaimLoader, + maxDepth types.Depth, + trace types.TraceAccessor, + responder Responder, + log log.Logger, + selective bool, + claimants []common.Address, +) *Agent { return &Agent{ metrics: m, solver: solver.NewGameSolver(maxDepth, trace), loader: loader, responder: responder, + selective: selective, + claimants: claimants, maxDepth: maxDepth, log: log, } @@ -53,39 +68,56 @@ func (a *Agent) Act(ctx context.Context) error { if a.tryResolve(ctx) { return nil } + game, err := a.newGameFromContracts(ctx) if err != nil { return fmt.Errorf("create game from contracts: %w", err) } - // Calculate the actions to take actions, err := a.solver.CalculateNextActions(ctx, game) if err != nil { - log.Error("Failed to calculate all required moves", "err", err) + a.log.Error("Failed to calculate all required moves", "err", err) } - // Perform the actions + var wg sync.WaitGroup + wg.Add(len(actions)) for _, action := range actions { - log := a.log.New("action", action.Type, "is_attack", action.IsAttack, "parent", action.ParentIdx) - if action.Type == types.ActionTypeStep { - log = log.New("prestate", common.Bytes2Hex(action.PreState), "proof", common.Bytes2Hex(action.ProofData)) - } else { - log = log.New("value", action.Value) - } + go a.performAction(ctx, &wg, action) + } + wg.Wait() + return nil +} - switch action.Type { - case types.ActionTypeMove: - a.metrics.RecordGameMove() - case types.ActionTypeStep: - a.metrics.RecordGameStep() - } - log.Info("Performing action") - err := a.responder.PerformAction(ctx, action) - if err != nil { - log.Error("Action failed", "err", err) +func (a *Agent) performAction(ctx context.Context, wg *sync.WaitGroup, action types.Action) { + defer wg.Done() + actionLog := a.log.New("action", action.Type, "is_attack", action.IsAttack, "parent", action.ParentIdx) + if action.Type == types.ActionTypeStep { + containsOracleData := action.OracleData != nil + isLocal := containsOracleData && action.OracleData.IsLocal + actionLog = actionLog.New( + "prestate", common.Bytes2Hex(action.PreState), + "proof", common.Bytes2Hex(action.ProofData), + "containsOracleData", containsOracleData, + "isLocalPreimage", isLocal, + ) + if action.OracleData != nil { + actionLog = actionLog.New("oracleKey", common.Bytes2Hex(action.OracleData.OracleKey)) } + } else { + actionLog = actionLog.New("value", action.Value) + } + + switch action.Type { + case types.ActionTypeMove: + a.metrics.RecordGameMove() + case types.ActionTypeStep: + a.metrics.RecordGameStep() + } + actionLog.Info("Performing action") + err := a.responder.PerformAction(ctx, action) + if err != nil { + actionLog.Error("Action failed", "err", err) } - return nil } // tryResolve resolves the game if it is in a winning state @@ -100,7 +132,7 @@ func (a *Agent) tryResolve(ctx context.Context) bool { return false } a.log.Info("Resolving game") - if err := a.responder.Resolve(ctx); err != nil { + if err := a.responder.Resolve(); err != nil { a.log.Error("Failed to resolve the game", "err", err) } return true @@ -109,7 +141,7 @@ func (a *Agent) tryResolve(ctx context.Context) bool { var errNoResolvableClaims = errors.New("no resolvable claims") func (a *Agent) tryResolveClaims(ctx context.Context) error { - claims, err := a.loader.GetAllClaims(ctx) + claims, err := a.loader.GetAllClaims(ctx, rpcblock.Latest) if err != nil { return fmt.Errorf("failed to fetch claims: %w", err) } @@ -119,6 +151,15 @@ func (a *Agent) tryResolveClaims(ctx context.Context) error { var resolvableClaims []int64 for _, claim := range claims { + if a.selective { + a.log.Trace("Selective claim resolution, checking if claim is incentivized", "claimIdx", claim.ContractIndex) + isUncounteredClaim := slices.Contains(a.claimants, claim.Claimant) && claim.CounteredBy == common.Address{} + ourCounter := slices.Contains(a.claimants, claim.CounteredBy) + if !isUncounteredClaim && !ourCounter { + a.log.Debug("Skipping claim to check resolution", "claimIdx", claim.ContractIndex) + continue + } + } a.log.Trace("Checking if claim is resolvable", "claimIdx", claim.ContractIndex) if err := a.responder.CallResolveClaim(ctx, uint64(claim.ContractIndex)); err == nil { a.log.Info("Resolving claim", "claimIdx", claim.ContractIndex) @@ -136,7 +177,7 @@ func (a *Agent) tryResolveClaims(ctx context.Context) error { claimIdx := claimIdx go func() { defer wg.Done() - err := a.responder.ResolveClaim(ctx, uint64(claimIdx)) + err := a.responder.ResolveClaim(uint64(claimIdx)) if err != nil { a.log.Error("Failed to resolve claim", "err", err) } @@ -162,7 +203,7 @@ func (a *Agent) resolveClaims(ctx context.Context) error { // newGameFromContracts initializes a new game state from the state in the contract func (a *Agent) newGameFromContracts(ctx context.Context) (types.Game, error) { - claims, err := a.loader.GetAllClaims(ctx) + claims, err := a.loader.GetAllClaims(ctx, rpcblock.Latest) if err != nil { return nil, fmt.Errorf("failed to fetch claims: %w", err) } diff --git a/op-challenger/game/fault/agent_test.go b/op-challenger/game/fault/agent_test.go index 47bcacbcba93..c1c3d22636b2 100644 --- a/op-challenger/game/fault/agent_test.go +++ b/op-challenger/game/fault/agent_test.go @@ -4,11 +4,14 @@ import ( "context" "errors" "math/big" + "sync" "testing" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/test" @@ -52,6 +55,80 @@ func TestDoNotMakeMovesWhenGameIsResolvable(t *testing.T) { } } +func createClaimsWithClaimants(t *testing.T, d types.Depth) []types.Claim { + claimBuilder := test.NewClaimBuilder(t, d, alphabet.NewTraceProvider(big.NewInt(0), d)) + rootClaim := claimBuilder.CreateRootClaim() + claim1 := rootClaim + claim1.Claimant = common.BigToAddress(big.NewInt(1)) + claim2 := claimBuilder.AttackClaim(claim1) + claim2.Claimant = common.BigToAddress(big.NewInt(2)) + claim3 := claimBuilder.AttackClaim(claim2) + claim3.Claimant = common.BigToAddress(big.NewInt(3)) + return []types.Claim{claim1, claim2, claim3} +} + +func TestAgent_SelectiveClaimResolution(t *testing.T) { + ctx := context.Background() + + tests := []struct { + name string + callResolveStatus gameTypes.GameStatus + selective bool + claimants []common.Address + claims []types.Claim + expectedResolveCount int + }{ + { + name: "NonSelectiveEmptyClaimants", + callResolveStatus: gameTypes.GameStatusDefenderWon, + selective: false, + claimants: []common.Address{}, + claims: createClaimsWithClaimants(t, types.Depth(4)), + expectedResolveCount: 3, + }, + { + name: "NonSelectiveWithClaimants", + callResolveStatus: gameTypes.GameStatusDefenderWon, + selective: false, + claimants: []common.Address{common.BigToAddress(big.NewInt(1))}, + claims: createClaimsWithClaimants(t, types.Depth(4)), + expectedResolveCount: 3, + }, + { + name: "SelectiveEmptyClaimants", + callResolveStatus: gameTypes.GameStatusDefenderWon, + selective: true, + claimants: []common.Address{}, + claims: createClaimsWithClaimants(t, types.Depth(4)), + }, + { + name: "SelectiveWithClaimants", + callResolveStatus: gameTypes.GameStatusDefenderWon, + selective: true, + claimants: []common.Address{common.BigToAddress(big.NewInt(1))}, + claims: createClaimsWithClaimants(t, types.Depth(4)), + expectedResolveCount: 1, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + agent, claimLoader, responder := setupTestAgent(t) + agent.selective = test.selective + agent.claimants = test.claimants + claimLoader.maxLoads = 1 + claimLoader.claims = test.claims + responder.callResolveStatus = test.callResolveStatus + + require.NoError(t, agent.Act(ctx)) + + require.Equal(t, test.expectedResolveCount, responder.callResolveClaimCount, "should check if game is resolvable") + require.Equal(t, test.expectedResolveCount, responder.resolveClaimCount, "should check if game is resolvable") + }) + } +} + func TestLoadClaimsWhenGameNotResolvable(t *testing.T) { // Checks that if the game isn't resolvable, that the agent continues on to start checking claims agent, claimLoader, responder := setupTestAgent(t) @@ -61,7 +138,7 @@ func TestLoadClaimsWhenGameNotResolvable(t *testing.T) { claimBuilder := test.NewClaimBuilder(t, depth, alphabet.NewTraceProvider(big.NewInt(0), depth)) claimLoader.claims = []types.Claim{ - claimBuilder.CreateRootClaim(true), + claimBuilder.CreateRootClaim(), } require.NoError(t, agent.Act(context.Background())) @@ -72,26 +149,31 @@ func TestLoadClaimsWhenGameNotResolvable(t *testing.T) { } func setupTestAgent(t *testing.T) (*Agent, *stubClaimLoader, *stubResponder) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) claimLoader := &stubClaimLoader{} depth := types.Depth(4) provider := alphabet.NewTraceProvider(big.NewInt(0), depth) responder := &stubResponder{} - agent := NewAgent(metrics.NoopMetrics, claimLoader, depth, trace.NewSimpleTraceAccessor(provider), responder, logger) + agent := NewAgent(metrics.NoopMetrics, claimLoader, depth, trace.NewSimpleTraceAccessor(provider), responder, logger, false, []common.Address{}) return agent, claimLoader, responder } type stubClaimLoader struct { callCount int + maxLoads int claims []types.Claim } -func (s *stubClaimLoader) GetAllClaims(ctx context.Context) ([]types.Claim, error) { +func (s *stubClaimLoader) GetAllClaims(_ context.Context, _ rpcblock.Block) ([]types.Claim, error) { s.callCount++ + if s.callCount > s.maxLoads && s.maxLoads != 0 { + return []types.Claim{}, nil + } return s.claims, nil } type stubResponder struct { + l sync.Mutex callResolveCount int callResolveStatus gameTypes.GameStatus callResolveErr error @@ -105,21 +187,29 @@ type stubResponder struct { } func (s *stubResponder) CallResolve(ctx context.Context) (gameTypes.GameStatus, error) { + s.l.Lock() + defer s.l.Unlock() s.callResolveCount++ return s.callResolveStatus, s.callResolveErr } -func (s *stubResponder) Resolve(ctx context.Context) error { +func (s *stubResponder) Resolve() error { + s.l.Lock() + defer s.l.Unlock() s.resolveCount++ return s.resolveErr } func (s *stubResponder) CallResolveClaim(ctx context.Context, clainIdx uint64) error { + s.l.Lock() + defer s.l.Unlock() s.callResolveClaimCount++ return s.callResolveClaimErr } -func (s *stubResponder) ResolveClaim(ctx context.Context, clainIdx uint64) error { +func (s *stubResponder) ResolveClaim(clainIdx uint64) error { + s.l.Lock() + defer s.l.Unlock() s.resolveClaimCount++ return nil } diff --git a/op-challenger/game/fault/claims/claimer.go b/op-challenger/game/fault/claims/claimer.go new file mode 100644 index 000000000000..7e8fbd037ccf --- /dev/null +++ b/op-challenger/game/fault/claims/claimer.go @@ -0,0 +1,87 @@ +package claims + +import ( + "context" + "errors" + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" +) + +type BondClaimMetrics interface { + RecordBondClaimed(amount uint64) +} + +type BondContract interface { + GetCredit(ctx context.Context, receipient common.Address) (*big.Int, types.GameStatus, error) + ClaimCredit(receipient common.Address) (txmgr.TxCandidate, error) +} + +type BondContractCreator func(game types.GameMetadata) (BondContract, error) + +type Claimer struct { + logger log.Logger + metrics BondClaimMetrics + contractCreator BondContractCreator + txSender types.TxSender + claimants []common.Address +} + +var _ BondClaimer = (*Claimer)(nil) + +func NewBondClaimer(l log.Logger, m BondClaimMetrics, contractCreator BondContractCreator, txSender types.TxSender, claimants ...common.Address) *Claimer { + return &Claimer{ + logger: l, + metrics: m, + contractCreator: contractCreator, + txSender: txSender, + claimants: claimants, + } +} + +func (c *Claimer) ClaimBonds(ctx context.Context, games []types.GameMetadata) (err error) { + for _, game := range games { + for _, claimant := range c.claimants { + err = errors.Join(err, c.claimBond(ctx, game, claimant)) + } + } + return err +} + +func (c *Claimer) claimBond(ctx context.Context, game types.GameMetadata, addr common.Address) error { + c.logger.Debug("Attempting to claim bonds for", "game", game.Proxy, "addr", addr) + + contract, err := c.contractCreator(game) + if err != nil { + return fmt.Errorf("failed to create bond contract bindings: %w", err) + } + credit, status, err := contract.GetCredit(ctx, addr) + if err != nil { + return fmt.Errorf("failed to get credit: %w", err) + } + + if status == types.GameStatusInProgress { + c.logger.Debug("Not claiming credit from in progress game", "game", game.Proxy, "addr", addr, "status", status) + return nil + } + if credit.Cmp(big.NewInt(0)) == 0 { + c.logger.Debug("No credit to claim", "game", game.Proxy, "addr", addr) + return nil + } + + candidate, err := contract.ClaimCredit(addr) + if err != nil { + return fmt.Errorf("failed to create credit claim tx: %w", err) + } + + if _, err = c.txSender.SendAndWait("claim credit", candidate); err != nil { + return fmt.Errorf("failed to claim credit: %w", err) + } + + c.metrics.RecordBondClaimed(credit.Uint64()) + return nil +} diff --git a/op-challenger/game/fault/claims/claimer_test.go b/op-challenger/game/fault/claims/claimer_test.go new file mode 100644 index 000000000000..8d157d16c9a3 --- /dev/null +++ b/op-challenger/game/fault/claims/claimer_test.go @@ -0,0 +1,157 @@ +package claims + +import ( + "context" + "errors" + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +var ( + mockTxMgrSendError = errors.New("mock tx mgr send error") +) + +func TestClaimer_ClaimBonds(t *testing.T) { + t.Run("MultipleBondClaimsSucceed", func(t *testing.T) { + gameAddr := common.HexToAddress("0x1234") + c, m, contract, txSender := newTestClaimer(t) + contract.credit[txSender.From()] = 1 + err := c.ClaimBonds(context.Background(), []types.GameMetadata{{Proxy: gameAddr}, {Proxy: gameAddr}, {Proxy: gameAddr}}) + require.NoError(t, err) + require.Equal(t, 3, txSender.sends) + require.Equal(t, 3, m.RecordBondClaimedCalls) + }) + + t.Run("BondClaimSucceeds", func(t *testing.T) { + gameAddr := common.HexToAddress("0x1234") + c, m, contract, txSender := newTestClaimer(t) + contract.credit[txSender.From()] = 1 + err := c.ClaimBonds(context.Background(), []types.GameMetadata{{Proxy: gameAddr}}) + require.NoError(t, err) + require.Equal(t, 1, txSender.sends) + require.Equal(t, 1, m.RecordBondClaimedCalls) + }) + + t.Run("BondClaimSucceedsForMultipleAddresses", func(t *testing.T) { + claimant1 := common.Address{0xaa} + claimant2 := common.Address{0xbb} + claimant3 := common.Address{0xcc} + gameAddr := common.HexToAddress("0x1234") + c, m, contract, txSender := newTestClaimer(t, claimant1, claimant2, claimant3) + contract.credit[claimant1] = 1 + contract.credit[claimant2] = 2 + contract.credit[claimant3] = 0 + err := c.ClaimBonds(context.Background(), []types.GameMetadata{{Proxy: gameAddr}}) + require.NoError(t, err) + require.Equal(t, 2, txSender.sends) + require.Equal(t, 2, m.RecordBondClaimedCalls) + }) + + t.Run("BondClaimSkippedForInProgressGame", func(t *testing.T) { + gameAddr := common.HexToAddress("0x1234") + c, m, contract, txSender := newTestClaimer(t) + contract.credit[txSender.From()] = 1 + contract.status = types.GameStatusInProgress + err := c.ClaimBonds(context.Background(), []types.GameMetadata{{Proxy: gameAddr}}) + require.NoError(t, err) + require.Equal(t, 0, txSender.sends) + require.Equal(t, 0, m.RecordBondClaimedCalls) + }) + + t.Run("BondClaimFails", func(t *testing.T) { + gameAddr := common.HexToAddress("0x1234") + c, m, contract, txSender := newTestClaimer(t) + txSender.sendFails = true + contract.credit[txSender.From()] = 1 + err := c.ClaimBonds(context.Background(), []types.GameMetadata{{Proxy: gameAddr}}) + require.ErrorIs(t, err, mockTxMgrSendError) + require.Equal(t, 1, txSender.sends) + require.Equal(t, 0, m.RecordBondClaimedCalls) + }) + + t.Run("ZeroCreditReturnsNil", func(t *testing.T) { + gameAddr := common.HexToAddress("0x1234") + c, m, contract, txSender := newTestClaimer(t) + contract.credit[txSender.From()] = 0 + err := c.ClaimBonds(context.Background(), []types.GameMetadata{{Proxy: gameAddr}}) + require.NoError(t, err) + require.Equal(t, 0, txSender.sends) + require.Equal(t, 0, m.RecordBondClaimedCalls) + }) + + t.Run("MultipleBondClaimFails", func(t *testing.T) { + gameAddr := common.HexToAddress("0x1234") + c, m, contract, txSender := newTestClaimer(t) + contract.credit[txSender.From()] = 1 + txSender.sendFails = true + err := c.ClaimBonds(context.Background(), []types.GameMetadata{{Proxy: gameAddr}, {Proxy: gameAddr}, {Proxy: gameAddr}}) + require.ErrorIs(t, err, mockTxMgrSendError) + require.Equal(t, 3, txSender.sends) + require.Equal(t, 0, m.RecordBondClaimedCalls) + }) +} + +func newTestClaimer(t *testing.T, claimants ...common.Address) (*Claimer, *mockClaimMetrics, *stubBondContract, *mockTxSender) { + logger := testlog.Logger(t, log.LvlDebug) + m := &mockClaimMetrics{} + txSender := &mockTxSender{} + bondContract := &stubBondContract{status: types.GameStatusChallengerWon, credit: make(map[common.Address]int64)} + contractCreator := func(game types.GameMetadata) (BondContract, error) { + return bondContract, nil + } + if len(claimants) == 0 { + claimants = []common.Address{txSender.From()} + } + c := NewBondClaimer(logger, m, contractCreator, txSender, claimants...) + return c, m, bondContract, txSender +} + +type mockClaimMetrics struct { + RecordBondClaimedCalls int +} + +func (m *mockClaimMetrics) RecordBondClaimed(amount uint64) { + m.RecordBondClaimedCalls++ +} + +type mockTxSender struct { + sends int + sendFails bool + statusFail bool +} + +func (s *mockTxSender) From() common.Address { + return common.HexToAddress("0x33333") +} + +func (s *mockTxSender) SendAndWait(_ string, _ ...txmgr.TxCandidate) ([]*ethtypes.Receipt, error) { + s.sends++ + if s.sendFails { + return nil, mockTxMgrSendError + } + if s.statusFail { + return []*ethtypes.Receipt{{Status: ethtypes.ReceiptStatusFailed}}, nil + } + return []*ethtypes.Receipt{{Status: ethtypes.ReceiptStatusSuccessful}}, nil +} + +type stubBondContract struct { + credit map[common.Address]int64 + status types.GameStatus +} + +func (s *stubBondContract) GetCredit(_ context.Context, addr common.Address) (*big.Int, types.GameStatus, error) { + return big.NewInt(s.credit[addr]), s.status, nil +} + +func (s *stubBondContract) ClaimCredit(_ common.Address) (txmgr.TxCandidate, error) { + return txmgr.TxCandidate{}, nil +} diff --git a/op-challenger/game/fault/claims/scheduler.go b/op-challenger/game/fault/claims/scheduler.go new file mode 100644 index 000000000000..17dbee301209 --- /dev/null +++ b/op-challenger/game/fault/claims/scheduler.go @@ -0,0 +1,77 @@ +package claims + +import ( + "context" + "sync" + + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum/go-ethereum/log" +) + +type BondClaimer interface { + ClaimBonds(ctx context.Context, games []types.GameMetadata) error +} + +type BondClaimScheduler struct { + log log.Logger + metrics BondClaimSchedulerMetrics + ch chan schedulerMessage + claimer BondClaimer + cancel func() + wg sync.WaitGroup +} + +type BondClaimSchedulerMetrics interface { + RecordBondClaimFailed() +} + +type schedulerMessage struct { + blockNumber uint64 + games []types.GameMetadata +} + +func NewBondClaimScheduler(logger log.Logger, metrics BondClaimSchedulerMetrics, claimer BondClaimer) *BondClaimScheduler { + return &BondClaimScheduler{ + log: logger, + metrics: metrics, + ch: make(chan schedulerMessage, 1), + claimer: claimer, + } +} + +func (s *BondClaimScheduler) Start(ctx context.Context) { + ctx, cancel := context.WithCancel(ctx) + s.cancel = cancel + s.wg.Add(1) + go s.run(ctx) +} + +func (s *BondClaimScheduler) Close() error { + s.cancel() + s.wg.Wait() + return nil +} + +func (s *BondClaimScheduler) run(ctx context.Context) { + defer s.wg.Done() + for { + select { + case <-ctx.Done(): + return + case msg := <-s.ch: + if err := s.claimer.ClaimBonds(ctx, msg.games); err != nil { + s.metrics.RecordBondClaimFailed() + s.log.Error("Failed to claim bonds", "blockNumber", msg.blockNumber, "err", err) + } + } + } +} + +func (s *BondClaimScheduler) Schedule(blockNumber uint64, games []types.GameMetadata) error { + select { + case s.ch <- schedulerMessage{blockNumber, games}: + default: + s.log.Trace("Skipping game bond claim while claiming in progress") + } + return nil +} diff --git a/op-challenger/game/fault/claims/scheduler_test.go b/op-challenger/game/fault/claims/scheduler_test.go new file mode 100644 index 000000000000..724189cb3f34 --- /dev/null +++ b/op-challenger/game/fault/claims/scheduler_test.go @@ -0,0 +1,99 @@ +package claims + +import ( + "context" + "errors" + "sync/atomic" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +var mockClaimError = errors.New("mock claim error") + +func TestBondClaimScheduler_Schedule(t *testing.T) { + tests := []struct { + name string + claimErr error + games []types.GameMetadata + expectedMetricCalls int + expectedClaimCalls int + }{ + { + name: "SingleGame_Succeeds", + games: []types.GameMetadata{{}}, + expectedMetricCalls: 0, + expectedClaimCalls: 1, + }, + { + name: "SingleGame_Fails", + claimErr: mockClaimError, + games: []types.GameMetadata{{}}, + expectedMetricCalls: 1, + expectedClaimCalls: 1, + }, + { + name: "MultipleGames_Succeed", + games: []types.GameMetadata{{}, {}, {}}, + expectedMetricCalls: 0, + expectedClaimCalls: 1, + }, + { + name: "MultipleGames_Fails", + claimErr: mockClaimError, + games: []types.GameMetadata{{}, {}, {}}, + expectedMetricCalls: 1, + expectedClaimCalls: 1, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + ctx := context.Background() + scheduler, metrics, claimer := setupTestBondClaimScheduler(t) + claimer.claimErr = test.claimErr + scheduler.Start(ctx) + defer scheduler.Close() + + err := scheduler.Schedule(1, test.games) + require.NoError(t, err) + require.Eventually(t, func() bool { + return int(claimer.claimCalls.Load()) == test.expectedClaimCalls + }, 10*time.Second, 10*time.Millisecond) + require.Eventually(t, func() bool { + return int(metrics.failedCalls.Load()) == test.expectedMetricCalls + }, 10*time.Second, 10*time.Millisecond) + }) + } +} + +func setupTestBondClaimScheduler(t *testing.T) (*BondClaimScheduler, *stubMetrics, *stubClaimer) { + logger := testlog.Logger(t, log.LvlInfo) + metrics := &stubMetrics{} + claimer := &stubClaimer{} + scheduler := NewBondClaimScheduler(logger, metrics, claimer) + return scheduler, metrics, claimer +} + +type stubMetrics struct { + failedCalls atomic.Int64 +} + +func (s *stubMetrics) RecordBondClaimFailed() { + s.failedCalls.Add(1) +} + +type stubClaimer struct { + claimCalls atomic.Int64 + claimErr error +} + +func (s *stubClaimer) ClaimBonds(ctx context.Context, games []types.GameMetadata) error { + s.claimCalls.Add(1) + return s.claimErr +} diff --git a/op-challenger/game/fault/contracts/faultdisputegame.go b/op-challenger/game/fault/contracts/faultdisputegame.go index 1eeecb04d7c9..d7d3557bc093 100644 --- a/op-challenger/game/fault/contracts/faultdisputegame.go +++ b/op-challenger/game/fault/contracts/faultdisputegame.go @@ -3,36 +3,42 @@ package contracts import ( "context" "fmt" + "math" "math/big" "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/common" ) var ( - methodGameDuration = "gameDuration" - methodMaxGameDepth = "maxGameDepth" - methodAbsolutePrestate = "absolutePrestate" - methodStatus = "status" - methodClaimCount = "claimDataLen" - methodClaim = "claimData" - methodL1Head = "l1Head" - methodResolve = "resolve" - methodResolveClaim = "resolveClaim" - methodAttack = "attack" - methodDefend = "defend" - methodStep = "step" - methodAddLocalData = "addLocalData" - methodVM = "vm" - methodGenesisBlockNumber = "genesisBlockNumber" - methodGenesisOutputRoot = "genesisOutputRoot" - methodSplitDepth = "splitDepth" - methodL2BlockNumber = "l2BlockNumber" - methodRequiredBond = "getRequiredBond" + methodGameDuration = "gameDuration" + methodMaxGameDepth = "maxGameDepth" + methodAbsolutePrestate = "absolutePrestate" + methodStatus = "status" + methodRootClaim = "rootClaim" + methodClaimCount = "claimDataLen" + methodClaim = "claimData" + methodL1Head = "l1Head" + methodResolve = "resolve" + methodResolveClaim = "resolveClaim" + methodAttack = "attack" + methodDefend = "defend" + methodStep = "step" + methodAddLocalData = "addLocalData" + methodVM = "vm" + methodStartingBlockNumber = "startingBlockNumber" + methodStartingRootHash = "startingRootHash" + methodSplitDepth = "splitDepth" + methodL2BlockNumber = "l2BlockNumber" + methodRequiredBond = "getRequiredBond" + methodClaimCredit = "claimCredit" + methodCredit = "credit" + methodWETH = "weth" ) type FaultDisputeGameContract struct { @@ -57,12 +63,28 @@ func NewFaultDisputeGameContract(addr common.Address, caller *batching.MultiCall }, nil } +// GetBalance returns the total amount of ETH controlled by this contract. +// Note that the ETH is actually held by the DelayedWETH contract which may be shared by multiple games. +// Returns the balance and the address of the contract that actually holds the balance. +func (f *FaultDisputeGameContract) GetBalance(ctx context.Context, block rpcblock.Block) (*big.Int, common.Address, error) { + result, err := f.multiCaller.SingleCall(ctx, block, f.contract.Call(methodWETH)) + if err != nil { + return nil, common.Address{}, fmt.Errorf("failed to load weth address: %w", err) + } + wethAddr := result.GetAddress(0) + result, err = f.multiCaller.SingleCall(ctx, block, batching.NewBalanceCall(wethAddr)) + if err != nil { + return nil, common.Address{}, fmt.Errorf("failed to retrieve game balance: %w", err) + } + return result.GetBigInt(0), wethAddr, nil +} + // GetBlockRange returns the block numbers of the absolute pre-state block (typically genesis or the bedrock activation block) // and the post-state block (that the proposed output root is for). -func (c *FaultDisputeGameContract) GetBlockRange(ctx context.Context) (prestateBlock uint64, poststateBlock uint64, retErr error) { - results, err := c.multiCaller.Call(ctx, batching.BlockLatest, - c.contract.Call(methodGenesisBlockNumber), - c.contract.Call(methodL2BlockNumber)) +func (f *FaultDisputeGameContract) GetBlockRange(ctx context.Context) (prestateBlock uint64, poststateBlock uint64, retErr error) { + results, err := f.multiCaller.Call(ctx, rpcblock.Latest, + f.contract.Call(methodStartingBlockNumber), + f.contract.Call(methodL2BlockNumber)) if err != nil { retErr = fmt.Errorf("failed to retrieve game block range: %w", err) return @@ -76,24 +98,88 @@ func (c *FaultDisputeGameContract) GetBlockRange(ctx context.Context) (prestateB return } -func (c *FaultDisputeGameContract) GetGenesisOutputRoot(ctx context.Context) (common.Hash, error) { - genesisOutputRoot, err := c.multiCaller.SingleCall(ctx, batching.BlockLatest, c.contract.Call(methodGenesisOutputRoot)) +// GetGameMetadata returns the game's L1 head, L2 block number, root claim, status, and game duration. +func (f *FaultDisputeGameContract) GetGameMetadata(ctx context.Context, block rpcblock.Block) (common.Hash, uint64, common.Hash, gameTypes.GameStatus, uint64, error) { + results, err := f.multiCaller.Call(ctx, block, + f.contract.Call(methodL1Head), + f.contract.Call(methodL2BlockNumber), + f.contract.Call(methodRootClaim), + f.contract.Call(methodStatus), + f.contract.Call(methodGameDuration)) + if err != nil { + return common.Hash{}, 0, common.Hash{}, 0, 0, fmt.Errorf("failed to retrieve game metadata: %w", err) + } + if len(results) != 5 { + return common.Hash{}, 0, common.Hash{}, 0, 0, fmt.Errorf("expected 3 results but got %v", len(results)) + } + l1Head := results[0].GetHash(0) + l2BlockNumber := results[1].GetBigInt(0).Uint64() + rootClaim := results[2].GetHash(0) + status, err := gameTypes.GameStatusFromUint8(results[3].GetUint8(0)) + if err != nil { + return common.Hash{}, 0, common.Hash{}, 0, 0, fmt.Errorf("failed to convert game status: %w", err) + } + duration := results[4].GetUint64(0) + return l1Head, l2BlockNumber, rootClaim, status, duration, nil +} + +func (f *FaultDisputeGameContract) GetStartingRootHash(ctx context.Context) (common.Hash, error) { + startingRootHash, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodStartingRootHash)) if err != nil { return common.Hash{}, fmt.Errorf("failed to retrieve genesis output root: %w", err) } - return genesisOutputRoot.GetHash(0), nil + return startingRootHash.GetHash(0), nil } -func (c *FaultDisputeGameContract) GetSplitDepth(ctx context.Context) (types.Depth, error) { - splitDepth, err := c.multiCaller.SingleCall(ctx, batching.BlockLatest, c.contract.Call(methodSplitDepth)) +func (f *FaultDisputeGameContract) GetSplitDepth(ctx context.Context) (types.Depth, error) { + splitDepth, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodSplitDepth)) if err != nil { return 0, fmt.Errorf("failed to retrieve split depth: %w", err) } return types.Depth(splitDepth.GetBigInt(0).Uint64()), nil } -func (c *FaultDisputeGameContract) GetRequiredBond(ctx context.Context, position types.Position) (*big.Int, error) { - bond, err := c.multiCaller.SingleCall(ctx, batching.BlockLatest, c.contract.Call(methodRequiredBond, position.ToGIndex())) +func (f *FaultDisputeGameContract) GetCredit(ctx context.Context, recipient common.Address) (*big.Int, gameTypes.GameStatus, error) { + results, err := f.multiCaller.Call(ctx, rpcblock.Latest, + f.contract.Call(methodCredit, recipient), + f.contract.Call(methodStatus)) + if err != nil { + return nil, gameTypes.GameStatusInProgress, err + } + if len(results) != 2 { + return nil, gameTypes.GameStatusInProgress, fmt.Errorf("expected 2 results but got %v", len(results)) + } + credit := results[0].GetBigInt(0) + status, err := gameTypes.GameStatusFromUint8(results[1].GetUint8(0)) + if err != nil { + return nil, gameTypes.GameStatusInProgress, fmt.Errorf("invalid game status %v: %w", status, err) + } + return credit, status, nil +} + +func (f *FaultDisputeGameContract) GetCredits(ctx context.Context, block rpcblock.Block, recipients ...common.Address) ([]*big.Int, error) { + calls := make([]batching.Call, 0, len(recipients)) + for _, recipient := range recipients { + calls = append(calls, f.contract.Call(methodCredit, recipient)) + } + results, err := f.multiCaller.Call(ctx, block, calls...) + if err != nil { + return nil, fmt.Errorf("failed to retrieve credit: %w", err) + } + credits := make([]*big.Int, 0, len(recipients)) + for _, result := range results { + credits = append(credits, result.GetBigInt(0)) + } + return credits, nil +} + +func (f *FaultDisputeGameContract) ClaimCredit(recipient common.Address) (txmgr.TxCandidate, error) { + call := f.contract.Call(methodClaimCredit, recipient) + return call.ToTxCandidate() +} + +func (f *FaultDisputeGameContract) GetRequiredBond(ctx context.Context, position types.Position) (*big.Int, error) { + bond, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodRequiredBond, position.ToGIndex())) if err != nil { return nil, fmt.Errorf("failed to retrieve required bond: %w", err) } @@ -134,7 +220,7 @@ func (f *FaultDisputeGameContract) GetOracle(ctx context.Context) (*PreimageOrac } func (f *FaultDisputeGameContract) GetGameDuration(ctx context.Context) (uint64, error) { - result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodGameDuration)) + result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodGameDuration)) if err != nil { return 0, fmt.Errorf("failed to fetch game duration: %w", err) } @@ -142,7 +228,7 @@ func (f *FaultDisputeGameContract) GetGameDuration(ctx context.Context) (uint64, } func (f *FaultDisputeGameContract) GetMaxGameDepth(ctx context.Context) (types.Depth, error) { - result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodMaxGameDepth)) + result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodMaxGameDepth)) if err != nil { return 0, fmt.Errorf("failed to fetch max game depth: %w", err) } @@ -150,7 +236,7 @@ func (f *FaultDisputeGameContract) GetMaxGameDepth(ctx context.Context) (types.D } func (f *FaultDisputeGameContract) GetAbsolutePrestateHash(ctx context.Context) (common.Hash, error) { - result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodAbsolutePrestate)) + result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodAbsolutePrestate)) if err != nil { return common.Hash{}, fmt.Errorf("failed to fetch absolute prestate hash: %w", err) } @@ -158,7 +244,7 @@ func (f *FaultDisputeGameContract) GetAbsolutePrestateHash(ctx context.Context) } func (f *FaultDisputeGameContract) GetL1Head(ctx context.Context) (common.Hash, error) { - result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodL1Head)) + result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodL1Head)) if err != nil { return common.Hash{}, fmt.Errorf("failed to fetch L1 head: %w", err) } @@ -166,7 +252,7 @@ func (f *FaultDisputeGameContract) GetL1Head(ctx context.Context) (common.Hash, } func (f *FaultDisputeGameContract) GetStatus(ctx context.Context) (gameTypes.GameStatus, error) { - result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodStatus)) + result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodStatus)) if err != nil { return 0, fmt.Errorf("failed to fetch status: %w", err) } @@ -174,7 +260,7 @@ func (f *FaultDisputeGameContract) GetStatus(ctx context.Context) (gameTypes.Gam } func (f *FaultDisputeGameContract) GetClaimCount(ctx context.Context) (uint64, error) { - result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodClaimCount)) + result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodClaimCount)) if err != nil { return 0, fmt.Errorf("failed to fetch claim count: %w", err) } @@ -182,15 +268,15 @@ func (f *FaultDisputeGameContract) GetClaimCount(ctx context.Context) (uint64, e } func (f *FaultDisputeGameContract) GetClaim(ctx context.Context, idx uint64) (types.Claim, error) { - result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodClaim, new(big.Int).SetUint64(idx))) + result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodClaim, new(big.Int).SetUint64(idx))) if err != nil { return types.Claim{}, fmt.Errorf("failed to fetch claim %v: %w", idx, err) } return f.decodeClaim(result, int(idx)), nil } -func (f *FaultDisputeGameContract) GetAllClaims(ctx context.Context) ([]types.Claim, error) { - results, err := batching.ReadArray(ctx, f.multiCaller, batching.BlockLatest, f.contract.Call(methodClaimCount), func(i *big.Int) *batching.ContractCall { +func (f *FaultDisputeGameContract) GetAllClaims(ctx context.Context, block rpcblock.Block) ([]types.Claim, error) { + results, err := batching.ReadArray(ctx, f.multiCaller, block, f.contract.Call(methodClaimCount), func(i *big.Int) *batching.ContractCall { return f.contract.Call(methodClaim, i) }) if err != nil { @@ -205,7 +291,7 @@ func (f *FaultDisputeGameContract) GetAllClaims(ctx context.Context) ([]types.Cl } func (f *FaultDisputeGameContract) vm(ctx context.Context) (*VMContract, error) { - result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodVM)) + result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodVM)) if err != nil { return nil, fmt.Errorf("failed to fetch VM addr: %w", err) } @@ -230,7 +316,7 @@ func (f *FaultDisputeGameContract) StepTx(claimIdx uint64, isAttack bool, stateD func (f *FaultDisputeGameContract) CallResolveClaim(ctx context.Context, claimIdx uint64) error { call := f.resolveClaimCall(claimIdx) - _, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, call) + _, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, call) if err != nil { return fmt.Errorf("failed to call resolve claim: %w", err) } @@ -248,7 +334,7 @@ func (f *FaultDisputeGameContract) resolveClaimCall(claimIdx uint64) *batching.C func (f *FaultDisputeGameContract) CallResolve(ctx context.Context) (gameTypes.GameStatus, error) { call := f.resolveCall() - result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, call) + result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, call) if err != nil { return gameTypes.GameStatusInProgress, fmt.Errorf("failed to call resolve: %w", err) } @@ -264,6 +350,21 @@ func (f *FaultDisputeGameContract) resolveCall() *batching.ContractCall { return f.contract.Call(methodResolve) } +// decodeClock decodes a uint128 into a Clock duration and timestamp. +func decodeClock(clock *big.Int) *types.Clock { + maxUint64 := new(big.Int).Add(new(big.Int).SetUint64(math.MaxUint64), big.NewInt(1)) + remainder := new(big.Int) + quotient, _ := new(big.Int).QuoRem(clock, maxUint64, remainder) + return types.NewClock(quotient.Uint64(), remainder.Uint64()) +} + +// packClock packs the Clock duration and timestamp into a uint128. +func packClock(c *types.Clock) *big.Int { + duration := new(big.Int).SetUint64(c.Duration) + encoded := new(big.Int).Lsh(duration, 64) + return new(big.Int).Or(encoded, new(big.Int).SetUint64(c.Timestamp)) +} + func (f *FaultDisputeGameContract) decodeClaim(result *batching.CallResult, contractIndex int) types.Claim { parentIndex := result.GetUint32(0) counteredBy := result.GetAddress(1) @@ -280,7 +381,7 @@ func (f *FaultDisputeGameContract) decodeClaim(result *batching.CallResult, cont }, CounteredBy: counteredBy, Claimant: claimant, - Clock: clock.Uint64(), + Clock: decodeClock(clock), ContractIndex: contractIndex, ParentContractIndex: int(parentIndex), } diff --git a/op-challenger/game/fault/contracts/faultdisputegame_test.go b/op-challenger/game/fault/contracts/faultdisputegame_test.go index 99f9665be70f..0206ec7c7a2f 100644 --- a/op-challenger/game/fault/contracts/faultdisputegame_test.go +++ b/op-challenger/game/fault/contracts/faultdisputegame_test.go @@ -10,6 +10,7 @@ import ( faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" batchingTest "github.com/ethereum-optimism/optimism/op-service/sources/batching/test" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" @@ -93,7 +94,7 @@ func TestSimpleGetters(t *testing.T) { test := test t.Run(test.methodAlias, func(t *testing.T) { stubRpc, game := setupFaultDisputeGameTest(t) - stubRpc.SetResponse(fdgAddr, test.method, batching.BlockLatest, nil, []interface{}{test.result}) + stubRpc.SetResponse(fdgAddr, test.method, rpcblock.Latest, nil, []interface{}{test.result}) status, err := test.call(game) require.NoError(t, err) expected := test.expected @@ -105,10 +106,48 @@ func TestSimpleGetters(t *testing.T) { } } +func TestClock_EncodingDecoding(t *testing.T) { + t.Run("DurationAndTimestamp", func(t *testing.T) { + by := common.Hex2Bytes("00000000000000050000000000000002") + encoded := new(big.Int).SetBytes(by) + clock := decodeClock(encoded) + require.Equal(t, uint64(5), clock.Duration) + require.Equal(t, uint64(2), clock.Timestamp) + require.Equal(t, encoded, packClock(clock)) + }) + + t.Run("ZeroDuration", func(t *testing.T) { + by := common.Hex2Bytes("00000000000000000000000000000002") + encoded := new(big.Int).SetBytes(by) + clock := decodeClock(encoded) + require.Equal(t, uint64(0), clock.Duration) + require.Equal(t, uint64(2), clock.Timestamp) + require.Equal(t, encoded, packClock(clock)) + }) + + t.Run("ZeroTimestamp", func(t *testing.T) { + by := common.Hex2Bytes("00000000000000050000000000000000") + encoded := new(big.Int).SetBytes(by) + clock := decodeClock(encoded) + require.Equal(t, uint64(5), clock.Duration) + require.Equal(t, uint64(0), clock.Timestamp) + require.Equal(t, encoded, packClock(clock)) + }) + + t.Run("ZeroClock", func(t *testing.T) { + by := common.Hex2Bytes("00000000000000000000000000000000") + encoded := new(big.Int).SetBytes(by) + clock := decodeClock(encoded) + require.Equal(t, uint64(0), clock.Duration) + require.Equal(t, uint64(0), clock.Timestamp) + require.Equal(t, encoded.Uint64(), packClock(clock).Uint64()) + }) +} + func TestGetOracleAddr(t *testing.T) { stubRpc, game := setupFaultDisputeGameTest(t) - stubRpc.SetResponse(fdgAddr, methodVM, batching.BlockLatest, nil, []interface{}{vmAddr}) - stubRpc.SetResponse(vmAddr, methodOracle, batching.BlockLatest, nil, []interface{}{oracleAddr}) + stubRpc.SetResponse(fdgAddr, methodVM, rpcblock.Latest, nil, []interface{}{vmAddr}) + stubRpc.SetResponse(vmAddr, methodOracle, rpcblock.Latest, nil, []interface{}{oracleAddr}) actual, err := game.GetOracle(context.Background()) require.NoError(t, err) @@ -125,7 +164,7 @@ func TestGetClaim(t *testing.T) { value := common.Hash{0xab} position := big.NewInt(2) clock := big.NewInt(1234) - stubRpc.SetResponse(fdgAddr, methodClaim, batching.BlockLatest, []interface{}{idx}, []interface{}{parentIndex, counteredBy, claimant, bond, value, position, clock}) + stubRpc.SetResponse(fdgAddr, methodClaim, rpcblock.Latest, []interface{}{idx}, []interface{}{parentIndex, counteredBy, claimant, bond, value, position, clock}) status, err := game.GetClaim(context.Background(), idx.Uint64()) require.NoError(t, err) require.Equal(t, faultTypes.Claim{ @@ -136,7 +175,7 @@ func TestGetClaim(t *testing.T) { }, CounteredBy: counteredBy, Claimant: claimant, - Clock: 1234, + Clock: decodeClock(big.NewInt(1234)), ContractIndex: int(idx.Uint64()), ParentContractIndex: 1, }, status) @@ -152,7 +191,7 @@ func TestGetAllClaims(t *testing.T) { }, CounteredBy: common.Address{0x01}, Claimant: common.Address{0x02}, - Clock: 1234, + Clock: decodeClock(big.NewInt(1234)), ContractIndex: 0, ParentContractIndex: math.MaxUint32, } @@ -164,7 +203,7 @@ func TestGetAllClaims(t *testing.T) { }, CounteredBy: common.Address{0x02}, Claimant: common.Address{0x01}, - Clock: 4455, + Clock: decodeClock(big.NewInt(4455)), ContractIndex: 1, ParentContractIndex: 0, } @@ -175,30 +214,45 @@ func TestGetAllClaims(t *testing.T) { Bond: big.NewInt(5), }, Claimant: common.Address{0x02}, - Clock: 7777, + Clock: decodeClock(big.NewInt(7777)), ContractIndex: 2, ParentContractIndex: 1, } expectedClaims := []faultTypes.Claim{claim0, claim1, claim2} - stubRpc.SetResponse(fdgAddr, methodClaimCount, batching.BlockLatest, nil, []interface{}{big.NewInt(int64(len(expectedClaims)))}) + block := rpcblock.ByNumber(42) + stubRpc.SetResponse(fdgAddr, methodClaimCount, block, nil, []interface{}{big.NewInt(int64(len(expectedClaims)))}) for _, claim := range expectedClaims { - expectGetClaim(stubRpc, claim) + expectGetClaim(stubRpc, block, claim) } - claims, err := game.GetAllClaims(context.Background()) + claims, err := game.GetAllClaims(context.Background(), block) require.NoError(t, err) require.Equal(t, expectedClaims, claims) } +func TestGetBalance(t *testing.T) { + wethAddr := common.Address{0x11, 0x55, 0x66} + balance := big.NewInt(9995877) + block := rpcblock.ByNumber(424) + stubRpc, game := setupFaultDisputeGameTest(t) + stubRpc.SetResponse(fdgAddr, methodWETH, block, nil, []interface{}{wethAddr}) + stubRpc.AddExpectedCall(batchingTest.NewGetBalanceCall(wethAddr, block, balance)) + + actualBalance, actualAddr, err := game.GetBalance(context.Background(), block) + require.NoError(t, err) + require.Equal(t, wethAddr, actualAddr) + require.Truef(t, balance.Cmp(actualBalance) == 0, "Expected balance %v but was %v", balance, actualBalance) +} + func TestCallResolveClaim(t *testing.T) { stubRpc, game := setupFaultDisputeGameTest(t) - stubRpc.SetResponse(fdgAddr, methodResolveClaim, batching.BlockLatest, []interface{}{big.NewInt(123)}, nil) + stubRpc.SetResponse(fdgAddr, methodResolveClaim, rpcblock.Latest, []interface{}{big.NewInt(123)}, nil) err := game.CallResolveClaim(context.Background(), 123) require.NoError(t, err) } func TestResolveClaimTxTest(t *testing.T) { stubRpc, game := setupFaultDisputeGameTest(t) - stubRpc.SetResponse(fdgAddr, methodResolveClaim, batching.BlockLatest, []interface{}{big.NewInt(123)}, nil) + stubRpc.SetResponse(fdgAddr, methodResolveClaim, rpcblock.Latest, []interface{}{big.NewInt(123)}, nil) tx, err := game.ResolveClaimTx(123) require.NoError(t, err) stubRpc.VerifyTxCandidate(tx) @@ -206,7 +260,7 @@ func TestResolveClaimTxTest(t *testing.T) { func TestResolveTx(t *testing.T) { stubRpc, game := setupFaultDisputeGameTest(t) - stubRpc.SetResponse(fdgAddr, methodResolve, batching.BlockLatest, nil, nil) + stubRpc.SetResponse(fdgAddr, methodResolve, rpcblock.Latest, nil, nil) tx, err := game.ResolveTx() require.NoError(t, err) stubRpc.VerifyTxCandidate(tx) @@ -215,7 +269,7 @@ func TestResolveTx(t *testing.T) { func TestAttackTx(t *testing.T) { stubRpc, game := setupFaultDisputeGameTest(t) value := common.Hash{0xaa} - stubRpc.SetResponse(fdgAddr, methodAttack, batching.BlockLatest, []interface{}{big.NewInt(111), value}, nil) + stubRpc.SetResponse(fdgAddr, methodAttack, rpcblock.Latest, []interface{}{big.NewInt(111), value}, nil) tx, err := game.AttackTx(111, value) require.NoError(t, err) stubRpc.VerifyTxCandidate(tx) @@ -224,7 +278,7 @@ func TestAttackTx(t *testing.T) { func TestDefendTx(t *testing.T) { stubRpc, game := setupFaultDisputeGameTest(t) value := common.Hash{0xaa} - stubRpc.SetResponse(fdgAddr, methodDefend, batching.BlockLatest, []interface{}{big.NewInt(111), value}, nil) + stubRpc.SetResponse(fdgAddr, methodDefend, rpcblock.Latest, []interface{}{big.NewInt(111), value}, nil) tx, err := game.DefendTx(111, value) require.NoError(t, err) stubRpc.VerifyTxCandidate(tx) @@ -234,17 +288,17 @@ func TestStepTx(t *testing.T) { stubRpc, game := setupFaultDisputeGameTest(t) stateData := []byte{1, 2, 3} proofData := []byte{4, 5, 6, 7, 8, 9} - stubRpc.SetResponse(fdgAddr, methodStep, batching.BlockLatest, []interface{}{big.NewInt(111), true, stateData, proofData}, nil) + stubRpc.SetResponse(fdgAddr, methodStep, rpcblock.Latest, []interface{}{big.NewInt(111), true, stateData, proofData}, nil) tx, err := game.StepTx(111, true, stateData, proofData) require.NoError(t, err) stubRpc.VerifyTxCandidate(tx) } -func expectGetClaim(stubRpc *batchingTest.AbiBasedRpc, claim faultTypes.Claim) { +func expectGetClaim(stubRpc *batchingTest.AbiBasedRpc, block rpcblock.Block, claim faultTypes.Claim) { stubRpc.SetResponse( fdgAddr, methodClaim, - batching.BlockLatest, + block, []interface{}{big.NewInt(int64(claim.ContractIndex))}, []interface{}{ uint32(claim.ParentContractIndex), @@ -253,7 +307,7 @@ func expectGetClaim(stubRpc *batchingTest.AbiBasedRpc, claim faultTypes.Claim) { claim.Bond, claim.Value, claim.Position.ToGIndex(), - big.NewInt(int64(claim.Clock)), + packClock(claim.Clock), }) } @@ -261,8 +315,8 @@ func TestGetBlockRange(t *testing.T) { stubRpc, contract := setupFaultDisputeGameTest(t) expectedStart := uint64(65) expectedEnd := uint64(102) - stubRpc.SetResponse(fdgAddr, methodGenesisBlockNumber, batching.BlockLatest, nil, []interface{}{new(big.Int).SetUint64(expectedStart)}) - stubRpc.SetResponse(fdgAddr, methodL2BlockNumber, batching.BlockLatest, nil, []interface{}{new(big.Int).SetUint64(expectedEnd)}) + stubRpc.SetResponse(fdgAddr, methodStartingBlockNumber, rpcblock.Latest, nil, []interface{}{new(big.Int).SetUint64(expectedStart)}) + stubRpc.SetResponse(fdgAddr, methodL2BlockNumber, rpcblock.Latest, nil, []interface{}{new(big.Int).SetUint64(expectedEnd)}) start, end, err := contract.GetBlockRange(context.Background()) require.NoError(t, err) require.Equal(t, expectedStart, start) @@ -272,32 +326,49 @@ func TestGetBlockRange(t *testing.T) { func TestGetSplitDepth(t *testing.T) { stubRpc, contract := setupFaultDisputeGameTest(t) expectedSplitDepth := faultTypes.Depth(15) - stubRpc.SetResponse(fdgAddr, methodSplitDepth, batching.BlockLatest, nil, []interface{}{new(big.Int).SetUint64(uint64(expectedSplitDepth))}) + stubRpc.SetResponse(fdgAddr, methodSplitDepth, rpcblock.Latest, nil, []interface{}{new(big.Int).SetUint64(uint64(expectedSplitDepth))}) splitDepth, err := contract.GetSplitDepth(context.Background()) require.NoError(t, err) require.Equal(t, expectedSplitDepth, splitDepth) } -func TestGetGenesisOutputRoot(t *testing.T) { +func TestGetGameMetadata(t *testing.T) { + stubRpc, contract := setupFaultDisputeGameTest(t) + expectedL1Head := common.Hash{0x0a, 0x0b} + expectedL2BlockNumber := uint64(123) + expectedGameDuration := uint64(456) + expectedRootClaim := common.Hash{0x01, 0x02} + expectedStatus := types.GameStatusChallengerWon + block := rpcblock.ByNumber(889) + stubRpc.SetResponse(fdgAddr, methodL1Head, block, nil, []interface{}{expectedL1Head}) + stubRpc.SetResponse(fdgAddr, methodL2BlockNumber, block, nil, []interface{}{new(big.Int).SetUint64(expectedL2BlockNumber)}) + stubRpc.SetResponse(fdgAddr, methodRootClaim, block, nil, []interface{}{expectedRootClaim}) + stubRpc.SetResponse(fdgAddr, methodStatus, block, nil, []interface{}{expectedStatus}) + stubRpc.SetResponse(fdgAddr, methodGameDuration, block, nil, []interface{}{expectedGameDuration}) + l1Head, l2BlockNumber, rootClaim, status, duration, err := contract.GetGameMetadata(context.Background(), block) + require.NoError(t, err) + require.Equal(t, expectedL1Head, l1Head) + require.Equal(t, expectedL2BlockNumber, l2BlockNumber) + require.Equal(t, expectedRootClaim, rootClaim) + require.Equal(t, expectedStatus, status) + require.Equal(t, expectedGameDuration, duration) +} + +func TestGetStartingRootHash(t *testing.T) { stubRpc, contract := setupFaultDisputeGameTest(t) expectedOutputRoot := common.HexToHash("0x1234") - stubRpc.SetResponse(fdgAddr, methodGenesisOutputRoot, batching.BlockLatest, nil, []interface{}{expectedOutputRoot}) - genesisOutputRoot, err := contract.GetGenesisOutputRoot(context.Background()) + stubRpc.SetResponse(fdgAddr, methodStartingRootHash, rpcblock.Latest, nil, []interface{}{expectedOutputRoot}) + startingOutputRoot, err := contract.GetStartingRootHash(context.Background()) require.NoError(t, err) - require.Equal(t, expectedOutputRoot, genesisOutputRoot) + require.Equal(t, expectedOutputRoot, startingOutputRoot) } func TestFaultDisputeGame_UpdateOracleTx(t *testing.T) { t.Run("Local", func(t *testing.T) { stubRpc, game := setupFaultDisputeGameTest(t) - data := &faultTypes.PreimageOracleData{ - IsLocal: true, - OracleKey: common.Hash{0xbc}.Bytes(), - OracleData: []byte{1, 2, 3, 4, 5, 6, 7}, - OracleOffset: 16, - } + data := faultTypes.NewPreimageOracleData(common.Hash{0x01, 0xbc}.Bytes(), []byte{1, 2, 3, 4, 5, 6, 7}, 16) claimIdx := uint64(6) - stubRpc.SetResponse(fdgAddr, methodAddLocalData, batching.BlockLatest, []interface{}{ + stubRpc.SetResponse(fdgAddr, methodAddLocalData, rpcblock.Latest, []interface{}{ data.GetIdent(), new(big.Int).SetUint64(claimIdx), new(big.Int).SetUint64(uint64(data.OracleOffset)), @@ -309,16 +380,11 @@ func TestFaultDisputeGame_UpdateOracleTx(t *testing.T) { t.Run("Global", func(t *testing.T) { stubRpc, game := setupFaultDisputeGameTest(t) - data := &faultTypes.PreimageOracleData{ - IsLocal: false, - OracleKey: common.Hash{0xbc}.Bytes(), - OracleData: []byte{1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15}, - OracleOffset: 16, - } + data := faultTypes.NewPreimageOracleData(common.Hash{0x02, 0xbc}.Bytes(), []byte{1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15}, 16) claimIdx := uint64(6) - stubRpc.SetResponse(fdgAddr, methodVM, batching.BlockLatest, nil, []interface{}{vmAddr}) - stubRpc.SetResponse(vmAddr, methodOracle, batching.BlockLatest, nil, []interface{}{oracleAddr}) - stubRpc.SetResponse(oracleAddr, methodLoadKeccak256PreimagePart, batching.BlockLatest, []interface{}{ + stubRpc.SetResponse(fdgAddr, methodVM, rpcblock.Latest, nil, []interface{}{vmAddr}) + stubRpc.SetResponse(vmAddr, methodOracle, rpcblock.Latest, nil, []interface{}{oracleAddr}) + stubRpc.SetResponse(oracleAddr, methodLoadKeccak256PreimagePart, rpcblock.Latest, []interface{}{ new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize(), }, nil) @@ -328,6 +394,40 @@ func TestFaultDisputeGame_UpdateOracleTx(t *testing.T) { }) } +func TestFaultDisputeGame_GetCredit(t *testing.T) { + stubRpc, game := setupFaultDisputeGameTest(t) + addr := common.Address{0x01} + expectedCredit := big.NewInt(4284) + expectedStatus := types.GameStatusChallengerWon + stubRpc.SetResponse(fdgAddr, methodCredit, rpcblock.Latest, []interface{}{addr}, []interface{}{expectedCredit}) + stubRpc.SetResponse(fdgAddr, methodStatus, rpcblock.Latest, nil, []interface{}{expectedStatus}) + + actualCredit, actualStatus, err := game.GetCredit(context.Background(), addr) + require.NoError(t, err) + require.Equal(t, expectedCredit, actualCredit) + require.Equal(t, expectedStatus, actualStatus) +} + +func TestFaultDisputeGame_GetCredits(t *testing.T) { + stubRpc, game := setupFaultDisputeGameTest(t) + + block := rpcblock.ByNumber(482) + + addrs := []common.Address{{0x01}, {0x02}, {0x03}} + expected := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(0)} + + for i, addr := range addrs { + stubRpc.SetResponse(fdgAddr, methodCredit, block, []interface{}{addr}, []interface{}{expected[i]}) + } + + actual, err := game.GetCredits(context.Background(), block, addrs...) + require.NoError(t, err) + require.Equal(t, len(expected), len(actual)) + for i := range expected { + require.Zerof(t, expected[i].Cmp(actual[i]), "expected: %v actual: %v", expected[i], actual[i]) + } +} + func setupFaultDisputeGameTest(t *testing.T) (*batchingTest.AbiBasedRpc, *FaultDisputeGameContract) { fdgAbi, err := bindings.FaultDisputeGameMetaData.GetAbi() require.NoError(t, err) diff --git a/op-challenger/game/fault/contracts/gamefactory.go b/op-challenger/game/fault/contracts/gamefactory.go index 843ffd438428..346a0eea7390 100644 --- a/op-challenger/game/fault/contracts/gamefactory.go +++ b/op-challenger/game/fault/contracts/gamefactory.go @@ -8,6 +8,8 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/common" ) @@ -15,6 +17,8 @@ const ( methodGameCount = "gameCount" methodGameAtIndex = "gameAtIndex" methodGameImpls = "gameImpls" + methodCreateGame = "create" + methodGames = "games" ) type DisputeGameFactoryContract struct { @@ -33,8 +37,16 @@ func NewDisputeGameFactoryContract(addr common.Address, caller *batching.MultiCa }, nil } +func (f *DisputeGameFactoryContract) GetGameFromParameters(ctx context.Context, traceType uint32, outputRoot common.Hash, l2BlockNum uint64) (common.Address, error) { + result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodGames, traceType, outputRoot, common.BigToHash(big.NewInt(int64(l2BlockNum))).Bytes())) + if err != nil { + return common.Address{}, fmt.Errorf("failed to fetch game from parameters: %w", err) + } + return result.GetAddress(0), nil +} + func (f *DisputeGameFactoryContract) GetGameCount(ctx context.Context, blockHash common.Hash) (uint64, error) { - result, err := f.multiCaller.SingleCall(ctx, batching.BlockByHash(blockHash), f.contract.Call(methodGameCount)) + result, err := f.multiCaller.SingleCall(ctx, rpcblock.ByHash(blockHash), f.contract.Call(methodGameCount)) if err != nil { return 0, fmt.Errorf("failed to load game count: %w", err) } @@ -42,33 +54,76 @@ func (f *DisputeGameFactoryContract) GetGameCount(ctx context.Context, blockHash } func (f *DisputeGameFactoryContract) GetGame(ctx context.Context, idx uint64, blockHash common.Hash) (types.GameMetadata, error) { - result, err := f.multiCaller.SingleCall(ctx, batching.BlockByHash(blockHash), f.contract.Call(methodGameAtIndex, new(big.Int).SetUint64(idx))) + result, err := f.multiCaller.SingleCall(ctx, rpcblock.ByHash(blockHash), f.contract.Call(methodGameAtIndex, new(big.Int).SetUint64(idx))) if err != nil { return types.GameMetadata{}, fmt.Errorf("failed to load game %v: %w", idx, err) } return f.decodeGame(result), nil } -func (f *DisputeGameFactoryContract) GetGameImpl(ctx context.Context, gameType uint8) (common.Address, error) { - result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodGameImpls, gameType)) +func (f *DisputeGameFactoryContract) GetGameImpl(ctx context.Context, gameType uint32) (common.Address, error) { + result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodGameImpls, gameType)) if err != nil { return common.Address{}, fmt.Errorf("failed to load game impl for type %v: %w", gameType, err) } return result.GetAddress(0), nil } +func (f *DisputeGameFactoryContract) GetGamesAtOrAfter(ctx context.Context, blockHash common.Hash, earliestTimestamp uint64) ([]types.GameMetadata, error) { + count, err := f.GetGameCount(ctx, blockHash) + if err != nil { + return nil, err + } + batchSize := uint64(f.multiCaller.BatchSize()) + rangeEnd := count + + var games []types.GameMetadata + for { + if rangeEnd == uint64(0) { + // rangeEnd is exclusive so if its 0 we've reached the end. + return games, nil + } + rangeStart := uint64(0) + if rangeEnd > batchSize { + rangeStart = rangeEnd - batchSize + } + calls := make([]batching.Call, 0, rangeEnd-rangeStart) + for i := rangeEnd - 1; ; i-- { + calls = append(calls, f.contract.Call(methodGameAtIndex, new(big.Int).SetUint64(i))) + // Break once we've added the last call to avoid underflow when rangeStart == 0 + if i == rangeStart { + break + } + } + + results, err := f.multiCaller.Call(ctx, rpcblock.ByHash(blockHash), calls...) + if err != nil { + return nil, fmt.Errorf("failed to fetch games: %w", err) + } + + for _, result := range results { + game := f.decodeGame(result) + if game.Timestamp < earliestTimestamp { + return games, nil + } + games = append(games, game) + } + rangeEnd = rangeStart + } +} + func (f *DisputeGameFactoryContract) GetAllGames(ctx context.Context, blockHash common.Hash) ([]types.GameMetadata, error) { count, err := f.GetGameCount(ctx, blockHash) if err != nil { return nil, err } - calls := make([]*batching.ContractCall, count) + calls := make([]batching.Call, count) for i := uint64(0); i < count; i++ { calls[i] = f.contract.Call(methodGameAtIndex, new(big.Int).SetUint64(i)) } - results, err := f.multiCaller.Call(ctx, batching.BlockByHash(blockHash), calls...) + results, err := f.multiCaller.Call(ctx, rpcblock.ByHash(blockHash), calls...) if err != nil { return nil, fmt.Errorf("failed to fetch games: %w", err) } @@ -80,8 +135,13 @@ func (f *DisputeGameFactoryContract) GetAllGames(ctx context.Context, blockHash return games, nil } +func (f *DisputeGameFactoryContract) CreateTx(traceType uint32, outputRoot common.Hash, l2BlockNum uint64) (txmgr.TxCandidate, error) { + call := f.contract.Call(methodCreateGame, traceType, outputRoot, common.BigToHash(big.NewInt(int64(l2BlockNum))).Bytes()) + return call.ToTxCandidate() +} + func (f *DisputeGameFactoryContract) decodeGame(result *batching.CallResult) types.GameMetadata { - gameType := result.GetUint8(0) + gameType := result.GetUint32(0) timestamp := result.GetUint64(1) proxy := result.GetAddress(2) return types.GameMetadata{ diff --git a/op-challenger/game/fault/contracts/gamefactory_test.go b/op-challenger/game/fault/contracts/gamefactory_test.go index 69a8df55f47e..f7f98760eebb 100644 --- a/op-challenger/game/fault/contracts/gamefactory_test.go +++ b/op-challenger/game/fault/contracts/gamefactory_test.go @@ -2,12 +2,15 @@ package contracts import ( "context" + "fmt" "math/big" + "slices" "testing" "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" batchingTest "github.com/ethereum-optimism/optimism/op-service/sources/batching/test" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" @@ -15,6 +18,7 @@ import ( var ( factoryAddr = common.HexToAddress("0x24112842371dFC380576ebb09Ae16Cb6B6caD7CB") + batchSize = 5 ) func TestDisputeGameFactorySimpleGetters(t *testing.T) { @@ -39,7 +43,7 @@ func TestDisputeGameFactorySimpleGetters(t *testing.T) { test := test t.Run(test.method, func(t *testing.T) { stubRpc, factory := setupDisputeGameFactoryTest(t) - stubRpc.SetResponse(factoryAddr, test.method, batching.BlockByHash(blockHash), nil, []interface{}{test.result}) + stubRpc.SetResponse(factoryAddr, test.method, rpcblock.ByHash(blockHash), nil, []interface{}{test.result}) status, err := test.call(factory) require.NoError(t, err) expected := test.expected @@ -98,7 +102,7 @@ func TestGetAllGames(t *testing.T) { } expectedGames := []types.GameMetadata{game0, game1, game2} - stubRpc.SetResponse(factoryAddr, methodGameCount, batching.BlockByHash(blockHash), nil, []interface{}{big.NewInt(int64(len(expectedGames)))}) + stubRpc.SetResponse(factoryAddr, methodGameCount, rpcblock.ByHash(blockHash), nil, []interface{}{big.NewInt(int64(len(expectedGames)))}) for idx, expected := range expectedGames { expectGetGame(stubRpc, idx, blockHash, expected) } @@ -107,14 +111,82 @@ func TestGetAllGames(t *testing.T) { require.Equal(t, expectedGames, actualGames) } +func TestGetAllGamesAtOrAfter(t *testing.T) { + tests := []struct { + gameCount int + earliestGameIdx int + }{ + {gameCount: batchSize * 4, earliestGameIdx: batchSize + 3}, + {gameCount: 0, earliestGameIdx: 0}, + {gameCount: batchSize * 2, earliestGameIdx: batchSize}, + {gameCount: batchSize * 2, earliestGameIdx: batchSize + 1}, + {gameCount: batchSize * 2, earliestGameIdx: batchSize - 1}, + {gameCount: batchSize * 2, earliestGameIdx: batchSize * 2}, + {gameCount: batchSize * 2, earliestGameIdx: batchSize*2 + 1}, + {gameCount: batchSize - 2, earliestGameIdx: batchSize - 3}, + } + for _, test := range tests { + test := test + t.Run(fmt.Sprintf("Count_%v_Start_%v", test.gameCount, test.earliestGameIdx), func(t *testing.T) { + blockHash := common.Hash{0xbb, 0xce} + stubRpc, factory := setupDisputeGameFactoryTest(t) + var allGames []types.GameMetadata + for i := 0; i < test.gameCount; i++ { + allGames = append(allGames, types.GameMetadata{ + GameType: uint32(i), + Timestamp: uint64(i), + Proxy: common.Address{byte(i)}, + }) + } + + stubRpc.SetResponse(factoryAddr, methodGameCount, rpcblock.ByHash(blockHash), nil, []interface{}{big.NewInt(int64(len(allGames)))}) + for idx, expected := range allGames { + expectGetGame(stubRpc, idx, blockHash, expected) + } + // Set an earliest timestamp that's in the middle of a batch + earliestTimestamp := uint64(test.earliestGameIdx) + actualGames, err := factory.GetGamesAtOrAfter(context.Background(), blockHash, earliestTimestamp) + require.NoError(t, err) + // Games come back in descending timestamp order + var expectedGames []types.GameMetadata + if test.earliestGameIdx < len(allGames) { + expectedGames = slices.Clone(allGames[test.earliestGameIdx:]) + } + slices.Reverse(expectedGames) + require.Equal(t, len(expectedGames), len(actualGames)) + if len(expectedGames) != 0 { + // Don't assert equal for empty arrays, we accept nil or empty array + require.Equal(t, expectedGames, actualGames) + } + }) + } +} + +func TestGetGameFromParameters(t *testing.T) { + stubRpc, factory := setupDisputeGameFactoryTest(t) + traceType := uint32(123) + outputRoot := common.Hash{0x01} + l2BlockNum := common.BigToHash(big.NewInt(456)).Bytes() + stubRpc.SetResponse( + factoryAddr, + methodGames, + rpcblock.Latest, + []interface{}{traceType, outputRoot, l2BlockNum}, + []interface{}{common.Address{0xaa}, uint64(1)}, + ) + addr, err := factory.GetGameFromParameters(context.Background(), traceType, outputRoot, uint64(456)) + require.NoError(t, err) + require.Equal(t, common.Address{0xaa}, addr) +} + func TestGetGameImpl(t *testing.T) { stubRpc, factory := setupDisputeGameFactoryTest(t) - gameType := uint8(3) + gameType := uint32(3) gameImplAddr := common.Address{0xaa} stubRpc.SetResponse( factoryAddr, - "gameImpls", - batching.BlockLatest, + methodGameImpls, + rpcblock.Latest, []interface{}{gameType}, []interface{}{gameImplAddr}) actual, err := factory.GetGameImpl(context.Background(), gameType) @@ -126,7 +198,7 @@ func expectGetGame(stubRpc *batchingTest.AbiBasedRpc, idx int, blockHash common. stubRpc.SetResponse( factoryAddr, methodGameAtIndex, - batching.BlockByHash(blockHash), + rpcblock.ByHash(blockHash), []interface{}{big.NewInt(int64(idx))}, []interface{}{ game.GameType, @@ -135,12 +207,23 @@ func expectGetGame(stubRpc *batchingTest.AbiBasedRpc, idx int, blockHash common. }) } +func TestCreateTx(t *testing.T) { + stubRpc, factory := setupDisputeGameFactoryTest(t) + traceType := uint32(123) + outputRoot := common.Hash{0x01} + l2BlockNum := common.BigToHash(big.NewInt(456)).Bytes() + stubRpc.SetResponse(factoryAddr, methodCreateGame, rpcblock.Latest, []interface{}{traceType, outputRoot, l2BlockNum}, nil) + tx, err := factory.CreateTx(traceType, outputRoot, uint64(456)) + require.NoError(t, err) + stubRpc.VerifyTxCandidate(tx) +} + func setupDisputeGameFactoryTest(t *testing.T) (*batchingTest.AbiBasedRpc, *DisputeGameFactoryContract) { fdgAbi, err := bindings.DisputeGameFactoryMetaData.GetAbi() require.NoError(t, err) stubRpc := batchingTest.NewAbiBasedRpc(t, factoryAddr, fdgAbi) - caller := batching.NewMultiCaller(stubRpc, 100) + caller := batching.NewMultiCaller(stubRpc, batchSize) factory, err := NewDisputeGameFactoryContract(factoryAddr, caller) require.NoError(t, err) return stubRpc, factory diff --git a/op-challenger/game/fault/contracts/oracle.go b/op-challenger/game/fault/contracts/oracle.go index be45a655bc58..4524034cffe9 100644 --- a/op-challenger/game/fault/contracts/oracle.go +++ b/op-challenger/game/fault/contracts/oracle.go @@ -7,30 +7,45 @@ import ( "fmt" "math" "math/big" + "sync/atomic" "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" - "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/matrix" + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/merkle" keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" + preimage "github.com/ethereum-optimism/optimism/op-preimage" "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/common" ) const ( - methodInitLPP = "initLPP" - methodAddLeavesLPP = "addLeavesLPP" - methodSqueezeLPP = "squeezeLPP" - methodLoadKeccak256PreimagePart = "loadKeccak256PreimagePart" - methodProposalCount = "proposalCount" - methodProposals = "proposals" - methodProposalMetadata = "proposalMetadata" - methodProposalBlocksLen = "proposalBlocksLen" - methodProposalBlocks = "proposalBlocks" + methodInitLPP = "initLPP" + methodAddLeavesLPP = "addLeavesLPP" + methodSqueezeLPP = "squeezeLPP" + methodLoadKeccak256PreimagePart = "loadKeccak256PreimagePart" + methodLoadSha256PreimagePart = "loadSha256PreimagePart" + methodLoadBlobPreimagePart = "loadBlobPreimagePart" + methodLoadPrecompilePreimagePart = "loadPrecompilePreimagePart" + methodProposalCount = "proposalCount" + methodProposals = "proposals" + methodProposalMetadata = "proposalMetadata" + methodProposalBlocksLen = "proposalBlocksLen" + methodProposalBlocks = "proposalBlocks" + methodPreimagePartOk = "preimagePartOk" + methodMinProposalSize = "minProposalSize" + methodChallengeFirstLPP = "challengeFirstLPP" + methodChallengeLPP = "challengeLPP" + methodChallengePeriod = "challengePeriod" + methodGetTreeRootLPP = "getTreeRootLPP" + methodMinBondSizeLPP = "MIN_BOND_SIZE" ) var ( ErrInvalidAddLeavesCall = errors.New("tx is not a valid addLeaves call") + ErrInvalidPreimageKey = errors.New("invalid preimage key") + ErrUnsupportedKeyType = errors.New("unsupported preimage key type") ) // PreimageOracleContract is a binding that works with contracts implementing the IPreimageOracle interface @@ -38,35 +53,24 @@ type PreimageOracleContract struct { addr common.Address multiCaller *batching.MultiCaller contract *batching.BoundContract + + // challengePeriod caches the challenge period from the contract once it has been loaded. + // 0 indicates the period has not been loaded yet. + challengePeriod atomic.Uint64 + // minBondSizeLPP caches the minimum bond size for large preimages from the contract once it has been loaded. + // 0 indicates the value has not been loaded yet. + minBondSizeLPP atomic.Uint64 } // toPreimageOracleLeaf converts a Leaf to the contract [bindings.PreimageOracleLeaf] type. func toPreimageOracleLeaf(l keccakTypes.Leaf) bindings.PreimageOracleLeaf { return bindings.PreimageOracleLeaf{ Input: l.Input[:], - Index: l.Index, + Index: new(big.Int).SetUint64(l.Index), StateCommitment: l.StateCommitment, } } -// MerkleProof is a place holder for the actual type we use for merkle proofs -// TODO(client-pod#481): Move this somewhere better and add useful functionality -type MerkleProof [][]byte - -// toSized converts a [][]byte to a [][32]byte -func (p MerkleProof) toSized() [][32]byte { - var sized [][32]byte - for _, proof := range p { - // SAFETY: if the proof is less than 32 bytes, it will be padded with 0s - if len(proof) < 32 { - proof = append(proof, make([]byte, 32-len(proof))...) - } - // SAFETY: the proof is 32 or more bytes here, so it will be truncated to 32 bytes - sized = append(sized, [32]byte(proof[:32])) - } - return sized -} - func NewPreimageOracleContract(addr common.Address, caller *batching.MultiCaller) (*PreimageOracleContract, error) { oracleAbi, err := bindings.PreimageOracleMetaData.GetAbi() if err != nil { @@ -85,8 +89,34 @@ func (c *PreimageOracleContract) Addr() common.Address { } func (c *PreimageOracleContract) AddGlobalDataTx(data *types.PreimageOracleData) (txmgr.TxCandidate, error) { - call := c.contract.Call(methodLoadKeccak256PreimagePart, new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize()) - return call.ToTxCandidate() + if len(data.OracleKey) == 0 { + return txmgr.TxCandidate{}, ErrInvalidPreimageKey + } + keyType := preimage.KeyType(data.OracleKey[0]) + switch keyType { + case preimage.Keccak256KeyType: + call := c.contract.Call(methodLoadKeccak256PreimagePart, new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize()) + return call.ToTxCandidate() + case preimage.Sha256KeyType: + call := c.contract.Call(methodLoadSha256PreimagePart, new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize()) + return call.ToTxCandidate() + case preimage.BlobKeyType: + call := c.contract.Call(methodLoadBlobPreimagePart, + new(big.Int).SetUint64(data.BlobFieldIndex), + new(big.Int).SetBytes(data.GetPreimageWithoutSize()), + data.BlobCommitment, + data.BlobProof, + new(big.Int).SetUint64(uint64(data.OracleOffset))) + return call.ToTxCandidate() + case preimage.PrecompileKeyType: + call := c.contract.Call(methodLoadPrecompilePreimagePart, + new(big.Int).SetUint64(uint64(data.OracleOffset)), + data.GetPrecompileAddress(), + data.GetPrecompileInput()) + return call.ToTxCandidate() + default: + return txmgr.TxCandidate{}, fmt.Errorf("%w: %v", ErrUnsupportedKeyType, keyType) + } } func (c *PreimageOracleContract) InitLargePreimage(uuid *big.Int, partOffset uint32, claimedSize uint32) (txmgr.TxCandidate, error) { @@ -99,41 +129,75 @@ func (c *PreimageOracleContract) AddLeaves(uuid *big.Int, startingBlockIndex *bi return call.ToTxCandidate() } +// MinLargePreimageSize returns the minimum size of a large preimage. +func (c *PreimageOracleContract) MinLargePreimageSize(ctx context.Context) (uint64, error) { + result, err := c.multiCaller.SingleCall(ctx, rpcblock.Latest, c.contract.Call(methodMinProposalSize)) + if err != nil { + return 0, fmt.Errorf("failed to fetch min lpp size bytes: %w", err) + } + return result.GetBigInt(0).Uint64(), nil +} + +// ChallengePeriod returns the challenge period for large preimages. +func (c *PreimageOracleContract) ChallengePeriod(ctx context.Context) (uint64, error) { + if period := c.challengePeriod.Load(); period != 0 { + return period, nil + } + result, err := c.multiCaller.SingleCall(ctx, rpcblock.Latest, c.contract.Call(methodChallengePeriod)) + if err != nil { + return 0, fmt.Errorf("failed to fetch challenge period: %w", err) + } + period := result.GetBigInt(0).Uint64() + c.challengePeriod.Store(period) + return period, nil +} + +func (c *PreimageOracleContract) CallSqueeze( + ctx context.Context, + claimant common.Address, + uuid *big.Int, + prestateMatrix keccakTypes.StateSnapshot, + preState keccakTypes.Leaf, + preStateProof merkle.Proof, + postState keccakTypes.Leaf, + postStateProof merkle.Proof, +) error { + call := c.contract.Call(methodSqueezeLPP, claimant, uuid, abiEncodeSnapshot(prestateMatrix), toPreimageOracleLeaf(preState), preStateProof, toPreimageOracleLeaf(postState), postStateProof) + _, err := c.multiCaller.SingleCall(ctx, rpcblock.Latest, call) + if err != nil { + return fmt.Errorf("failed to call squeeze: %w", err) + } + return nil +} + func (c *PreimageOracleContract) Squeeze( claimant common.Address, uuid *big.Int, - stateMatrix *matrix.StateMatrix, + prestateMatrix keccakTypes.StateSnapshot, preState keccakTypes.Leaf, - preStateProof MerkleProof, + preStateProof merkle.Proof, postState keccakTypes.Leaf, - postStateProof MerkleProof, + postStateProof merkle.Proof, ) (txmgr.TxCandidate, error) { call := c.contract.Call( methodSqueezeLPP, claimant, uuid, - abiEncodeStateMatrix(stateMatrix), + abiEncodeSnapshot(prestateMatrix), toPreimageOracleLeaf(preState), - preStateProof.toSized(), + preStateProof, toPreimageOracleLeaf(postState), - postStateProof.toSized(), + postStateProof, ) return call.ToTxCandidate() } -// abiEncodeStateMatrix encodes the state matrix for the contract ABI -func abiEncodeStateMatrix(stateMatrix *matrix.StateMatrix) bindings.LibKeccakStateMatrix { - packedState := stateMatrix.PackState() - stateSlice := new([25]uint64) - // SAFETY: a maximum of 25 * 8 bytes will be read from packedState and written to stateSlice - for i := 0; i < min(len(packedState), 25*8); i += 8 { - stateSlice[i/8] = new(big.Int).SetBytes(packedState[i : i+8]).Uint64() - } - return bindings.LibKeccakStateMatrix{State: *stateSlice} +func abiEncodeSnapshot(packedState keccakTypes.StateSnapshot) bindings.LibKeccakStateMatrix { + return bindings.LibKeccakStateMatrix{State: packedState} } func (c *PreimageOracleContract) GetActivePreimages(ctx context.Context, blockHash common.Hash) ([]keccakTypes.LargePreimageMetaData, error) { - block := batching.BlockByHash(blockHash) + block := rpcblock.ByHash(blockHash) results, err := batching.ReadArray(ctx, c.multiCaller, block, c.contract.Call(methodProposalCount), func(i *big.Int) *batching.ContractCall { return c.contract.Call(methodProposals, i) }) @@ -149,8 +213,8 @@ func (c *PreimageOracleContract) GetActivePreimages(ctx context.Context, blockHa return c.GetProposalMetadata(ctx, block, idents...) } -func (c *PreimageOracleContract) GetProposalMetadata(ctx context.Context, block batching.Block, idents ...keccakTypes.LargePreimageIdent) ([]keccakTypes.LargePreimageMetaData, error) { - var calls []*batching.ContractCall +func (c *PreimageOracleContract) GetProposalMetadata(ctx context.Context, block rpcblock.Block, idents ...keccakTypes.LargePreimageIdent) ([]keccakTypes.LargePreimageMetaData, error) { + var calls []batching.Call for _, ident := range idents { calls = append(calls, c.contract.Call(methodProposalMetadata, ident.Claimant, ident.UUID)) } @@ -174,7 +238,16 @@ func (c *PreimageOracleContract) GetProposalMetadata(ctx context.Context, block return proposals, nil } -func (c *PreimageOracleContract) GetInputDataBlocks(ctx context.Context, block batching.Block, ident keccakTypes.LargePreimageIdent) ([]uint64, error) { +func (c *PreimageOracleContract) GetProposalTreeRoot(ctx context.Context, block rpcblock.Block, ident keccakTypes.LargePreimageIdent) (common.Hash, error) { + call := c.contract.Call(methodGetTreeRootLPP, ident.Claimant, ident.UUID) + result, err := c.multiCaller.SingleCall(ctx, block, call) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to get tree root: %w", err) + } + return result.GetHash(0), nil +} + +func (c *PreimageOracleContract) GetInputDataBlocks(ctx context.Context, block rpcblock.Block, ident keccakTypes.LargePreimageIdent) ([]uint64, error) { results, err := batching.ReadArray(ctx, c.multiCaller, block, c.contract.Call(methodProposalBlocksLen, ident.Claimant, ident.UUID), func(i *big.Int) *batching.ContractCall { @@ -221,6 +294,51 @@ func (c *PreimageOracleContract) DecodeInputData(data []byte) (*big.Int, keccakT }, nil } +func (c *PreimageOracleContract) GlobalDataExists(ctx context.Context, data *types.PreimageOracleData) (bool, error) { + call := c.contract.Call(methodPreimagePartOk, common.Hash(data.OracleKey), new(big.Int).SetUint64(uint64(data.OracleOffset))) + results, err := c.multiCaller.SingleCall(ctx, rpcblock.Latest, call) + if err != nil { + return false, fmt.Errorf("failed to get preimagePartOk: %w", err) + } + return results.GetBool(0), nil +} + +func (c *PreimageOracleContract) ChallengeTx(ident keccakTypes.LargePreimageIdent, challenge keccakTypes.Challenge) (txmgr.TxCandidate, error) { + var call *batching.ContractCall + if challenge.Prestate == (keccakTypes.Leaf{}) { + call = c.contract.Call( + methodChallengeFirstLPP, + ident.Claimant, + ident.UUID, + toPreimageOracleLeaf(challenge.Poststate), + challenge.PoststateProof) + } else { + call = c.contract.Call( + methodChallengeLPP, + ident.Claimant, + ident.UUID, + abiEncodeSnapshot(challenge.StateMatrix), + toPreimageOracleLeaf(challenge.Prestate), + challenge.PrestateProof, + toPreimageOracleLeaf(challenge.Poststate), + challenge.PoststateProof) + } + return call.ToTxCandidate() +} + +func (c *PreimageOracleContract) GetMinBondLPP(ctx context.Context) (*big.Int, error) { + if bondSize := c.minBondSizeLPP.Load(); bondSize != 0 { + return big.NewInt(int64(bondSize)), nil + } + result, err := c.multiCaller.SingleCall(ctx, rpcblock.Latest, c.contract.Call(methodMinBondSizeLPP)) + if err != nil { + return nil, fmt.Errorf("failed to fetch min bond size for LPPs: %w", err) + } + period := result.GetBigInt(0) + c.minBondSizeLPP.Store(period.Uint64()) + return period, nil +} + func (c *PreimageOracleContract) decodePreimageIdent(result *batching.CallResult) keccakTypes.LargePreimageIdent { return keccakTypes.LargePreimageIdent{ Claimant: result.GetAddress(0), diff --git a/op-challenger/game/fault/contracts/oracle_test.go b/op-challenger/game/fault/contracts/oracle_test.go index e12a1e6047a4..0a65b239aef4 100644 --- a/op-challenger/game/fault/contracts/oracle_test.go +++ b/op-challenger/game/fault/contracts/oracle_test.go @@ -5,34 +5,157 @@ import ( "fmt" "math" "math/big" + "math/rand" "testing" "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" - "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/matrix" + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/merkle" keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" + preimage "github.com/ethereum-optimism/optimism/op-preimage" "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" batchingTest "github.com/ethereum-optimism/optimism/op-service/sources/batching/test" + "github.com/ethereum-optimism/optimism/op-service/testutils" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ) -func TestPreimageOracleContract_LoadKeccak256(t *testing.T) { +func TestPreimageOracleContract_AddGlobalDataTx(t *testing.T) { + t.Run("UnknownType", func(t *testing.T) { + _, oracle := setupPreimageOracleTest(t) + data := types.NewPreimageOracleData(common.Hash{0xcc}.Bytes(), make([]byte, 20), uint32(545)) + _, err := oracle.AddGlobalDataTx(data) + require.ErrorIs(t, err, ErrUnsupportedKeyType) + }) + + t.Run("Keccak256", func(t *testing.T) { + stubRpc, oracle := setupPreimageOracleTest(t) + data := types.NewPreimageOracleData(common.Hash{byte(preimage.Keccak256KeyType), 0xcc}.Bytes(), make([]byte, 20), uint32(545)) + stubRpc.SetResponse(oracleAddr, methodLoadKeccak256PreimagePart, rpcblock.Latest, []interface{}{ + new(big.Int).SetUint64(uint64(data.OracleOffset)), + data.GetPreimageWithoutSize(), + }, nil) + + tx, err := oracle.AddGlobalDataTx(data) + require.NoError(t, err) + stubRpc.VerifyTxCandidate(tx) + }) + + t.Run("Sha256", func(t *testing.T) { + stubRpc, oracle := setupPreimageOracleTest(t) + data := types.NewPreimageOracleData(common.Hash{byte(preimage.Sha256KeyType), 0xcc}.Bytes(), make([]byte, 20), uint32(545)) + stubRpc.SetResponse(oracleAddr, methodLoadSha256PreimagePart, rpcblock.Latest, []interface{}{ + new(big.Int).SetUint64(uint64(data.OracleOffset)), + data.GetPreimageWithoutSize(), + }, nil) + + tx, err := oracle.AddGlobalDataTx(data) + require.NoError(t, err) + stubRpc.VerifyTxCandidate(tx) + }) + + t.Run("Blob", func(t *testing.T) { + stubRpc, oracle := setupPreimageOracleTest(t) + fieldData := testutils.RandomData(rand.New(rand.NewSource(23)), 32) + data := types.NewPreimageOracleData(common.Hash{byte(preimage.BlobKeyType), 0xcc}.Bytes(), fieldData, uint32(545)) + stubRpc.SetResponse(oracleAddr, methodLoadBlobPreimagePart, rpcblock.Latest, []interface{}{ + new(big.Int).SetUint64(data.BlobFieldIndex), + new(big.Int).SetBytes(data.GetPreimageWithoutSize()), + data.BlobCommitment, + data.BlobProof, + new(big.Int).SetUint64(uint64(data.OracleOffset)), + }, nil) + + tx, err := oracle.AddGlobalDataTx(data) + require.NoError(t, err) + stubRpc.VerifyTxCandidate(tx) + }) + + t.Run("Precompile", func(t *testing.T) { + stubRpc, oracle := setupPreimageOracleTest(t) + input := testutils.RandomData(rand.New(rand.NewSource(23)), 200) + data := types.NewPreimageOracleData(common.Hash{byte(preimage.PrecompileKeyType), 0xcc}.Bytes(), input, uint32(545)) + stubRpc.SetResponse(oracleAddr, methodLoadPrecompilePreimagePart, rpcblock.Latest, []interface{}{ + new(big.Int).SetUint64(uint64(data.OracleOffset)), + data.GetPrecompileAddress(), + data.GetPrecompileInput(), + }, nil) + + tx, err := oracle.AddGlobalDataTx(data) + require.NoError(t, err) + stubRpc.VerifyTxCandidate(tx) + }) +} + +func TestPreimageOracleContract_ChallengePeriod(t *testing.T) { stubRpc, oracle := setupPreimageOracleTest(t) + stubRpc.SetResponse(oracleAddr, methodChallengePeriod, rpcblock.Latest, + []interface{}{}, + []interface{}{big.NewInt(123)}, + ) + challengePeriod, err := oracle.ChallengePeriod(context.Background()) + require.NoError(t, err) + require.Equal(t, uint64(123), challengePeriod) - data := &types.PreimageOracleData{ - OracleKey: common.Hash{0xcc}.Bytes(), - OracleData: make([]byte, 20), - OracleOffset: 545, - } - stubRpc.SetResponse(oracleAddr, methodLoadKeccak256PreimagePart, batching.BlockLatest, []interface{}{ - new(big.Int).SetUint64(uint64(data.OracleOffset)), - data.GetPreimageWithoutSize(), - }, nil) + // Should cache responses + stubRpc.ClearResponses() + challengePeriod, err = oracle.ChallengePeriod(context.Background()) + require.NoError(t, err) + require.Equal(t, uint64(123), challengePeriod) +} - tx, err := oracle.AddGlobalDataTx(data) +func TestPreimageOracleContract_MinLargePreimageSize(t *testing.T) { + stubRpc, oracle := setupPreimageOracleTest(t) + stubRpc.SetResponse(oracleAddr, methodMinProposalSize, rpcblock.Latest, + []interface{}{}, + []interface{}{big.NewInt(123)}, + ) + minProposalSize, err := oracle.MinLargePreimageSize(context.Background()) require.NoError(t, err) - stubRpc.VerifyTxCandidate(tx) + require.Equal(t, uint64(123), minProposalSize) +} + +func TestPreimageOracleContract_MinBondSizeLPP(t *testing.T) { + stubRpc, oracle := setupPreimageOracleTest(t) + stubRpc.SetResponse(oracleAddr, methodMinBondSizeLPP, rpcblock.Latest, + []interface{}{}, + []interface{}{big.NewInt(123)}, + ) + minBond, err := oracle.GetMinBondLPP(context.Background()) + require.NoError(t, err) + require.Equal(t, big.NewInt(123), minBond) + + // Should cache responses + stubRpc.ClearResponses() + minBond, err = oracle.GetMinBondLPP(context.Background()) + require.NoError(t, err) + require.Equal(t, big.NewInt(123), minBond) +} + +func TestPreimageOracleContract_PreimageDataExists(t *testing.T) { + t.Run("exists", func(t *testing.T) { + stubRpc, oracle := setupPreimageOracleTest(t) + data := types.NewPreimageOracleData(common.Hash{0xcc}.Bytes(), make([]byte, 20), 545) + stubRpc.SetResponse(oracleAddr, methodPreimagePartOk, rpcblock.Latest, + []interface{}{common.Hash(data.OracleKey), new(big.Int).SetUint64(uint64(data.OracleOffset))}, + []interface{}{true}, + ) + exists, err := oracle.GlobalDataExists(context.Background(), data) + require.NoError(t, err) + require.True(t, exists) + }) + t.Run("does not exist", func(t *testing.T) { + stubRpc, oracle := setupPreimageOracleTest(t) + data := types.NewPreimageOracleData(common.Hash{0xcc}.Bytes(), make([]byte, 20), 545) + stubRpc.SetResponse(oracleAddr, methodPreimagePartOk, rpcblock.Latest, + []interface{}{common.Hash(data.OracleKey), new(big.Int).SetUint64(uint64(data.OracleOffset))}, + []interface{}{false}, + ) + exists, err := oracle.GlobalDataExists(context.Background(), data) + require.NoError(t, err) + require.False(t, exists) + }) } func TestPreimageOracleContract_InitLargePreimage(t *testing.T) { @@ -41,7 +164,7 @@ func TestPreimageOracleContract_InitLargePreimage(t *testing.T) { uuid := big.NewInt(123) partOffset := uint32(1) claimedSize := uint32(2) - stubRpc.SetResponse(oracleAddr, methodInitLPP, batching.BlockLatest, []interface{}{ + stubRpc.SetResponse(oracleAddr, methodInitLPP, rpcblock.Latest, []interface{}{ uuid, partOffset, claimedSize, @@ -60,7 +183,7 @@ func TestPreimageOracleContract_AddLeaves(t *testing.T) { input := []byte{0x12} commitments := []common.Hash{{0x34}} finalize := true - stubRpc.SetResponse(oracleAddr, methodAddLeavesLPP, batching.BlockLatest, []interface{}{ + stubRpc.SetResponse(oracleAddr, methodAddLeavesLPP, rpcblock.Latest, []interface{}{ uuid, startingBlockIndex, input, @@ -78,37 +201,37 @@ func TestPreimageOracleContract_Squeeze(t *testing.T) { claimant := common.Address{0x12} uuid := big.NewInt(123) - stateMatrix := matrix.NewStateMatrix() + preStateMatrix := keccakTypes.StateSnapshot{0, 1, 2, 3, 4} preState := keccakTypes.Leaf{ Input: [keccakTypes.BlockSize]byte{0x12}, - Index: big.NewInt(123), + Index: 123, StateCommitment: common.Hash{0x34}, } - preStateProof := MerkleProof{{0x34}} + preStateProof := merkle.Proof{{0x34}} postState := keccakTypes.Leaf{ Input: [keccakTypes.BlockSize]byte{0x34}, - Index: big.NewInt(456), + Index: 456, StateCommitment: common.Hash{0x56}, } - postStateProof := MerkleProof{{0x56}} - stubRpc.SetResponse(oracleAddr, methodSqueezeLPP, batching.BlockLatest, []interface{}{ + postStateProof := merkle.Proof{{0x56}} + stubRpc.SetResponse(oracleAddr, methodSqueezeLPP, rpcblock.Latest, []interface{}{ claimant, uuid, - abiEncodeStateMatrix(stateMatrix), + abiEncodeSnapshot(preStateMatrix), toPreimageOracleLeaf(preState), - preStateProof.toSized(), + preStateProof, toPreimageOracleLeaf(postState), - postStateProof.toSized(), + postStateProof, }, nil) - tx, err := oracle.Squeeze(claimant, uuid, stateMatrix, preState, preStateProof, postState, postStateProof) + tx, err := oracle.Squeeze(claimant, uuid, preStateMatrix, preState, preStateProof, postState, postStateProof) require.NoError(t, err) stubRpc.VerifyTxCandidate(tx) } func TestGetActivePreimages(t *testing.T) { blockHash := common.Hash{0xaa} - _, oracle, proposals := setupPreimageOracleTestWithProposals(t, batching.BlockByHash(blockHash)) + _, oracle, proposals := setupPreimageOracleTestWithProposals(t, rpcblock.ByHash(blockHash)) preimages, err := oracle.GetActivePreimages(context.Background(), blockHash) require.NoError(t, err) require.Equal(t, proposals, preimages) @@ -116,7 +239,7 @@ func TestGetActivePreimages(t *testing.T) { func TestGetProposalMetadata(t *testing.T) { blockHash := common.Hash{0xaa} - block := batching.BlockByHash(blockHash) + block := rpcblock.ByHash(blockHash) stubRpc, oracle, proposals := setupPreimageOracleTestWithProposals(t, block) preimages, err := oracle.GetProposalMetadata( context.Background(), @@ -137,12 +260,25 @@ func TestGetProposalMetadata(t *testing.T) { block, []interface{}{ident.Claimant, ident.UUID}, []interface{}{meta}) - preimages, err = oracle.GetProposalMetadata(context.Background(), batching.BlockByHash(blockHash), ident) + preimages, err = oracle.GetProposalMetadata(context.Background(), rpcblock.ByHash(blockHash), ident) require.NoError(t, err) require.Equal(t, []keccakTypes.LargePreimageMetaData{{LargePreimageIdent: ident}}, preimages) } -func setupPreimageOracleTestWithProposals(t *testing.T, block batching.Block) (*batchingTest.AbiBasedRpc, *PreimageOracleContract, []keccakTypes.LargePreimageMetaData) { +func TestGetProposalTreeRoot(t *testing.T) { + blockHash := common.Hash{0xaa} + expectedRoot := common.Hash{0xbb} + ident := keccakTypes.LargePreimageIdent{Claimant: common.Address{0x12}, UUID: big.NewInt(123)} + stubRpc, oracle := setupPreimageOracleTest(t) + stubRpc.SetResponse(oracleAddr, methodGetTreeRootLPP, rpcblock.ByHash(blockHash), + []interface{}{ident.Claimant, ident.UUID}, + []interface{}{expectedRoot}) + actualRoot, err := oracle.GetProposalTreeRoot(context.Background(), rpcblock.ByHash(blockHash), ident) + require.NoError(t, err) + require.Equal(t, expectedRoot, actualRoot) +} + +func setupPreimageOracleTestWithProposals(t *testing.T, block rpcblock.Block) (*batchingTest.AbiBasedRpc, *PreimageOracleContract, []keccakTypes.LargePreimageMetaData) { stubRpc, oracle := setupPreimageOracleTest(t) stubRpc.SetResponse( oracleAddr, @@ -216,7 +352,6 @@ func setupPreimageOracleTestWithProposals(t *testing.T, block batching.Block) (* } return stubRpc, oracle, proposals - } func setupPreimageOracleTest(t *testing.T) (*batchingTest.AbiBasedRpc, *PreimageOracleContract) { @@ -293,7 +428,7 @@ func TestMetadata_Countered(t *testing.T) { func TestGetInputDataBlocks(t *testing.T) { stubRpc, oracle := setupPreimageOracleTest(t) - block := batching.BlockByHash(common.Hash{0xaa}) + block := rpcblock.ByHash(common.Hash{0xaa}) preimage := keccakTypes.LargePreimageIdent{ Claimant: common.Address{0xbb}, @@ -438,6 +573,84 @@ func TestDecodeInputData(t *testing.T) { } } +func TestChallenge_First(t *testing.T) { + stubRpc, oracle := setupPreimageOracleTest(t) + + ident := keccakTypes.LargePreimageIdent{ + Claimant: common.Address{0xab}, + UUID: big.NewInt(4829), + } + challenge := keccakTypes.Challenge{ + StateMatrix: keccakTypes.StateSnapshot{1, 2, 3, 4, 5}, + Prestate: keccakTypes.Leaf{}, + Poststate: keccakTypes.Leaf{ + Input: [136]byte{5, 4, 3, 2, 1}, + Index: 0, + StateCommitment: common.Hash{0xbb}, + }, + PoststateProof: merkle.Proof{common.Hash{0x01}, common.Hash{0x02}}, + } + stubRpc.SetResponse(oracleAddr, methodChallengeFirstLPP, rpcblock.Latest, + []interface{}{ + ident.Claimant, ident.UUID, + bindings.PreimageOracleLeaf{ + Input: challenge.Poststate.Input[:], + Index: new(big.Int).SetUint64(challenge.Poststate.Index), + StateCommitment: challenge.Poststate.StateCommitment, + }, + challenge.PoststateProof, + }, + nil) + tx, err := oracle.ChallengeTx(ident, challenge) + require.NoError(t, err) + stubRpc.VerifyTxCandidate(tx) +} + +func TestChallenge_NotFirst(t *testing.T) { + stubRpc, oracle := setupPreimageOracleTest(t) + + ident := keccakTypes.LargePreimageIdent{ + Claimant: common.Address{0xab}, + UUID: big.NewInt(4829), + } + challenge := keccakTypes.Challenge{ + StateMatrix: keccakTypes.StateSnapshot{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, + Prestate: keccakTypes.Leaf{ + Input: [136]byte{9, 8, 7, 6, 5}, + Index: 3, + StateCommitment: common.Hash{0xcc}, + }, + PrestateProof: merkle.Proof{common.Hash{0x01}, common.Hash{0x02}}, + Poststate: keccakTypes.Leaf{ + Input: [136]byte{5, 4, 3, 2, 1}, + Index: 4, + StateCommitment: common.Hash{0xbb}, + }, + PoststateProof: merkle.Proof{common.Hash{0x03}, common.Hash{0x04}}, + } + stubRpc.SetResponse(oracleAddr, methodChallengeLPP, rpcblock.Latest, + []interface{}{ + ident.Claimant, ident.UUID, + bindings.LibKeccakStateMatrix{State: challenge.StateMatrix}, + bindings.PreimageOracleLeaf{ + Input: challenge.Prestate.Input[:], + Index: new(big.Int).SetUint64(challenge.Prestate.Index), + StateCommitment: challenge.Prestate.StateCommitment, + }, + challenge.PrestateProof, + bindings.PreimageOracleLeaf{ + Input: challenge.Poststate.Input[:], + Index: new(big.Int).SetUint64(challenge.Poststate.Index), + StateCommitment: challenge.Poststate.StateCommitment, + }, + challenge.PoststateProof, + }, + nil) + tx, err := oracle.ChallengeTx(ident, challenge) + require.NoError(t, err) + stubRpc.VerifyTxCandidate(tx) +} + func toAddLeavesTxData(t *testing.T, oracle *PreimageOracleContract, uuid *big.Int, inputData keccakTypes.InputData) []byte { tx, err := oracle.AddLeaves(uuid, big.NewInt(1), inputData.Input, inputData.Commitments, inputData.Finalize) require.NoError(t, err) diff --git a/op-challenger/game/fault/contracts/vm.go b/op-challenger/game/fault/contracts/vm.go index bdc23cd4f974..2fb354d89bd8 100644 --- a/op-challenger/game/fault/contracts/vm.go +++ b/op-challenger/game/fault/contracts/vm.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum/go-ethereum/common" ) @@ -32,7 +33,7 @@ func NewVMContract(addr common.Address, caller *batching.MultiCaller) (*VMContra } func (c *VMContract) Oracle(ctx context.Context) (*PreimageOracleContract, error) { - results, err := c.multiCaller.SingleCall(ctx, batching.BlockLatest, c.contract.Call(methodOracle)) + results, err := c.multiCaller.SingleCall(ctx, rpcblock.Latest, c.contract.Call(methodOracle)) if err != nil { return nil, fmt.Errorf("failed to load oracle address: %w", err) } diff --git a/op-challenger/game/fault/contracts/vm_test.go b/op-challenger/game/fault/contracts/vm_test.go index a329e90df2ce..13758ccd6500 100644 --- a/op-challenger/game/fault/contracts/vm_test.go +++ b/op-challenger/game/fault/contracts/vm_test.go @@ -6,8 +6,11 @@ import ( "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + preimage "github.com/ethereum-optimism/optimism/op-preimage" "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" batchingTest "github.com/ethereum-optimism/optimism/op-service/sources/batching/test" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ) @@ -19,13 +22,11 @@ func TestVMContract_Oracle(t *testing.T) { vmContract, err := NewVMContract(vmAddr, batching.NewMultiCaller(stubRpc, batching.DefaultBatchSize)) require.NoError(t, err) - stubRpc.SetResponse(vmAddr, methodOracle, batching.BlockLatest, nil, []interface{}{oracleAddr}) + stubRpc.SetResponse(vmAddr, methodOracle, rpcblock.Latest, nil, []interface{}{oracleAddr}) oracleContract, err := vmContract.Oracle(context.Background()) require.NoError(t, err) - tx, err := oracleContract.AddGlobalDataTx(&types.PreimageOracleData{ - OracleData: make([]byte, 20), - }) + tx, err := oracleContract.AddGlobalDataTx(types.NewPreimageOracleData(common.Hash{byte(preimage.Keccak256KeyType)}.Bytes(), make([]byte, 20), 0)) require.NoError(t, err) // This test doesn't care about all the tx details, we just want to confirm the contract binding is using the // correct address diff --git a/op-challenger/game/fault/player.go b/op-challenger/game/fault/player.go index 2a2361cae987..bba42d8bc89d 100644 --- a/op-challenger/game/fault/player.go +++ b/op-challenger/game/fault/player.go @@ -2,16 +2,19 @@ package fault import ( "context" + "errors" "fmt" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/claims" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/preimages" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/responder" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-challenger/metrics" - "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/common" + gethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" ) @@ -22,36 +25,53 @@ type GameInfo interface { GetClaimCount(context.Context) (uint64, error) } +type SyncValidator interface { + ValidateNodeSynced(ctx context.Context, gameL1Head eth.BlockID) error +} + +type L1HeaderSource interface { + HeaderByHash(context.Context, common.Hash) (*gethTypes.Header, error) +} + type GamePlayer struct { act actor loader GameInfo logger log.Logger + syncValidator SyncValidator prestateValidators []Validator status gameTypes.GameStatus + gameL1Head eth.BlockID } type GameContract interface { preimages.PreimageGameContract responder.GameContract + claims.BondContract GameInfo ClaimLoader GetStatus(ctx context.Context) (gameTypes.GameStatus, error) GetMaxGameDepth(ctx context.Context) (types.Depth, error) GetOracle(ctx context.Context) (*contracts.PreimageOracleContract, error) + GetL1Head(ctx context.Context) (common.Hash, error) } type resourceCreator func(ctx context.Context, logger log.Logger, gameDepth types.Depth, dir string) (types.TraceAccessor, error) func NewGamePlayer( ctx context.Context, + cl types.ClockReader, logger log.Logger, m metrics.Metricer, dir string, addr common.Address, - txMgr txmgr.TxManager, + txSender gameTypes.TxSender, loader GameContract, + syncValidator SyncValidator, validators []Validator, creator resourceCreator, + l1HeaderSource L1HeaderSource, + selective bool, + claimants []common.Address, ) (*GamePlayer, error) { logger = logger.New("game", addr) @@ -88,21 +108,38 @@ func NewGamePlayer( if err != nil { return nil, fmt.Errorf("failed to load oracle: %w", err) } - direct := preimages.NewDirectPreimageUploader(logger, txMgr, loader) - large := preimages.NewLargePreimageUploader(logger, txMgr, oracle) - uploader := preimages.NewSplitPreimageUploader(direct, large) - responder, err := responder.NewFaultResponder(logger, txMgr, loader, uploader) + l1HeadHash, err := loader.GetL1Head(ctx) + if err != nil { + return nil, fmt.Errorf("failed to load game L1 head: %w", err) + } + l1Header, err := l1HeaderSource.HeaderByHash(ctx, l1HeadHash) + if err != nil { + return nil, fmt.Errorf("failed to load L1 header %v: %w", l1HeadHash, err) + } + l1Head := eth.HeaderBlockID(l1Header) + + minLargePreimageSize, err := oracle.MinLargePreimageSize(ctx) + if err != nil { + return nil, fmt.Errorf("failed to load min large preimage size: %w", err) + } + direct := preimages.NewDirectPreimageUploader(logger, txSender, loader) + large := preimages.NewLargePreimageUploader(logger, cl, txSender, oracle) + uploader := preimages.NewSplitPreimageUploader(direct, large, minLargePreimageSize) + responder, err := responder.NewFaultResponder(logger, txSender, loader, uploader, oracle) if err != nil { return nil, fmt.Errorf("failed to create the responder: %w", err) } - agent := NewAgent(m, loader, gameDepth, accessor, responder, logger) + agent := NewAgent(m, loader, gameDepth, accessor, responder, logger, selective, claimants) return &GamePlayer{ - act: agent.Act, - loader: loader, - logger: logger, - status: status, + act: agent.Act, + loader: loader, + logger: logger, + status: status, + gameL1Head: l1Head, + syncValidator: syncValidator, + prestateValidators: validators, }, nil } @@ -125,13 +162,20 @@ func (g *GamePlayer) ProgressGame(ctx context.Context) gameTypes.GameStatus { g.logger.Trace("Skipping completed game") return g.status } + if err := g.syncValidator.ValidateNodeSynced(ctx, g.gameL1Head); errors.Is(err, ErrNotInSync) { + g.logger.Warn("Local node not sufficiently up to date", "err", err) + return g.status + } else if err != nil { + g.logger.Error("Could not check local node was in sync", "err", err) + return g.status + } g.logger.Trace("Checking if actions are required") if err := g.act(ctx); err != nil { g.logger.Error("Error when acting on game", "err", err) } status, err := g.loader.GetStatus(ctx) if err != nil { - g.logger.Warn("Unable to retrieve game status", "err", err) + g.logger.Error("Unable to retrieve game status", "err", err) return gameTypes.GameStatusInProgress } g.logGameStatus(ctx, status) diff --git a/op-challenger/game/fault/player_test.go b/op-challenger/game/fault/player_test.go index b5fb2d97fd37..0c662ac63883 100644 --- a/op-challenger/game/fault/player_test.go +++ b/op-challenger/game/fault/player_test.go @@ -7,30 +7,33 @@ import ( "testing" "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" ) -var ( - mockValidatorError = fmt.Errorf("mock validator error") -) +var mockValidatorError = fmt.Errorf("mock validator error") func TestProgressGame_LogErrorFromAct(t *testing.T) { - handler, game, actor := setupProgressGameTest(t) + handler, game, actor, _ := setupProgressGameTest(t) actor.actErr = errors.New("boom") status := game.ProgressGame(context.Background()) require.Equal(t, types.GameStatusInProgress, status) require.Equal(t, 1, actor.callCount, "should perform next actions") - errLog := handler.FindLog(log.LvlError, "Error when acting on game") + levelFilter := testlog.NewLevelFilter(log.LevelError) + msgFilter := testlog.NewMessageFilter("Error when acting on game") + errLog := handler.FindLog(levelFilter, msgFilter) require.NotNil(t, errLog, "should log error") - require.Equal(t, actor.actErr, errLog.GetContextValue("err")) + require.Equal(t, actor.actErr, errLog.AttrValue("err")) // Should still log game status - msg := handler.FindLog(log.LvlInfo, "Game info") + levelFilter = testlog.NewLevelFilter(log.LevelInfo) + msgFilter = testlog.NewMessageFilter("Game info") + msg := handler.FindLog(levelFilter, msgFilter) require.NotNil(t, msg) - require.Equal(t, uint64(1), msg.GetContextValue("claims")) + require.Equal(t, uint64(1), msg.AttrValue("claims")) } func TestProgressGame_LogGameStatus(t *testing.T) { @@ -58,15 +61,17 @@ func TestProgressGame_LogGameStatus(t *testing.T) { for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { - handler, game, gameState := setupProgressGameTest(t) + handler, game, gameState, _ := setupProgressGameTest(t) gameState.status = test.status status := game.ProgressGame(context.Background()) require.Equal(t, 1, gameState.callCount, "should perform next actions") require.Equal(t, test.status, status) - errLog := handler.FindLog(log.LvlInfo, test.logMsg) + levelFilter := testlog.NewLevelFilter(log.LevelInfo) + msgFilter := testlog.NewMessageFilter(test.logMsg) + errLog := handler.FindLog(levelFilter, msgFilter) require.NotNil(t, errLog, "should log game result") - require.Equal(t, test.status, errLog.GetContextValue("status")) + require.Equal(t, test.status, errLog.AttrValue("status")) }) } } @@ -74,7 +79,7 @@ func TestProgressGame_LogGameStatus(t *testing.T) { func TestDoNotActOnCompleteGame(t *testing.T) { for _, status := range []types.GameStatus{types.GameStatusChallengerWon, types.GameStatusDefenderWon} { t.Run(status.String(), func(t *testing.T) { - _, game, gameState := setupProgressGameTest(t) + _, game, gameState, _ := setupProgressGameTest(t) gameState.status = status fetched := game.ProgressGame(context.Background()) @@ -89,6 +94,17 @@ func TestDoNotActOnCompleteGame(t *testing.T) { } } +func TestValidateLocalNodeSync(t *testing.T) { + _, game, gameState, syncValidator := setupProgressGameTest(t) + + game.ProgressGame(context.Background()) + require.Equal(t, 1, gameState.callCount, "acts when in sync") + + syncValidator.result = errors.New("boom") + game.ProgressGame(context.Background()) + require.Equal(t, 1, gameState.callCount, "does not act when not in sync") +} + func TestValidatePrestate(t *testing.T) { tests := []struct { name string @@ -138,26 +154,36 @@ type mockValidator struct { err bool } -func (m *mockValidator) Validate(ctx context.Context) error { +func (m *mockValidator) Validate(_ context.Context) error { if m.err { return mockValidatorError } return nil } -func setupProgressGameTest(t *testing.T) (*testlog.CapturingHandler, *GamePlayer, *stubGameState) { - logger := testlog.Logger(t, log.LvlDebug) - handler := &testlog.CapturingHandler{ - Delegate: logger.GetHandler(), - } - logger.SetHandler(handler) +func setupProgressGameTest(t *testing.T) (*testlog.CapturingHandler, *GamePlayer, *stubGameState, *stubSyncValidator) { + logger, logs := testlog.CaptureLogger(t, log.LevelDebug) gameState := &stubGameState{claimCount: 1} + syncValidator := &stubSyncValidator{} game := &GamePlayer{ - act: gameState.Act, - loader: gameState, - logger: logger, + act: gameState.Act, + loader: gameState, + logger: logger, + syncValidator: syncValidator, + gameL1Head: eth.BlockID{ + Hash: common.Hash{0x1a}, + Number: 32, + }, } - return handler, game, gameState + return logs, game, gameState, syncValidator +} + +type stubSyncValidator struct { + result error +} + +func (s *stubSyncValidator) ValidateNodeSynced(_ context.Context, _ eth.BlockID) error { + return s.result } type stubGameState struct { diff --git a/op-challenger/game/fault/preimages/direct.go b/op-challenger/game/fault/preimages/direct.go index 2bd777bc0198..24c1f51e25fd 100644 --- a/op-challenger/game/fault/preimages/direct.go +++ b/op-challenger/game/fault/preimages/direct.go @@ -5,8 +5,8 @@ import ( "fmt" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-service/txmgr" - ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" ) @@ -21,40 +21,25 @@ type PreimageGameContract interface { type DirectPreimageUploader struct { log log.Logger - txMgr txmgr.TxManager + txSender gameTypes.TxSender contract PreimageGameContract } -func NewDirectPreimageUploader(logger log.Logger, txMgr txmgr.TxManager, contract PreimageGameContract) *DirectPreimageUploader { - return &DirectPreimageUploader{logger, txMgr, contract} +func NewDirectPreimageUploader(logger log.Logger, txSender gameTypes.TxSender, contract PreimageGameContract) *DirectPreimageUploader { + return &DirectPreimageUploader{logger, txSender, contract} } func (d *DirectPreimageUploader) UploadPreimage(ctx context.Context, claimIdx uint64, data *types.PreimageOracleData) error { if data == nil { return ErrNilPreimageData } - d.log.Info("Updating oracle data", "key", data.OracleKey) + d.log.Info("Updating oracle data", "key", fmt.Sprintf("%x", data.OracleKey)) candidate, err := d.contract.UpdateOracleTx(ctx, claimIdx, data) if err != nil { return fmt.Errorf("failed to create pre-image oracle tx: %w", err) } - if err := d.sendTxAndWait(ctx, candidate); err != nil { + if _, err := d.txSender.SendAndWait("populate pre-image oracle", candidate); err != nil { return fmt.Errorf("failed to populate pre-image oracle: %w", err) } return nil } - -// sendTxAndWait sends a transaction through the [txmgr] and waits for a receipt. -// This sets the tx GasLimit to 0, performing gas estimation online through the [txmgr]. -func (d *DirectPreimageUploader) sendTxAndWait(ctx context.Context, candidate txmgr.TxCandidate) error { - receipt, err := d.txMgr.Send(ctx, candidate) - if err != nil { - return err - } - if receipt.Status == ethtypes.ReceiptStatusFailed { - d.log.Error("DirectPreimageUploader tx successfully published but reverted", "tx_hash", receipt.TxHash) - } else { - d.log.Debug("DirectPreimageUploader tx successfully published", "tx_hash", receipt.TxHash) - } - return nil -} diff --git a/op-challenger/game/fault/preimages/direct_test.go b/op-challenger/game/fault/preimages/direct_test.go index d7d7da9a8e35..473334237fc7 100644 --- a/op-challenger/game/fault/preimages/direct_test.go +++ b/op-challenger/game/fault/preimages/direct_test.go @@ -53,34 +53,9 @@ func TestDirectPreimageUploader_UploadPreimage(t *testing.T) { }) } -func TestDirectPreimageUploader_SendTxAndWait(t *testing.T) { - t.Run("SendFails", func(t *testing.T) { - oracle, txMgr, _ := newTestDirectPreimageUploader(t) - txMgr.sendFails = true - err := oracle.sendTxAndWait(context.Background(), txmgr.TxCandidate{}) - require.ErrorIs(t, err, mockTxMgrSendError) - require.Equal(t, 1, txMgr.sends) - }) - - t.Run("ReceiptStatusFailed", func(t *testing.T) { - oracle, txMgr, _ := newTestDirectPreimageUploader(t) - txMgr.statusFail = true - err := oracle.sendTxAndWait(context.Background(), txmgr.TxCandidate{}) - require.NoError(t, err) - require.Equal(t, 1, txMgr.sends) - }) - - t.Run("Success", func(t *testing.T) { - oracle, txMgr, _ := newTestDirectPreimageUploader(t) - err := oracle.sendTxAndWait(context.Background(), txmgr.TxCandidate{}) - require.NoError(t, err) - require.Equal(t, 1, txMgr.sends) - }) -} - -func newTestDirectPreimageUploader(t *testing.T) (*DirectPreimageUploader, *mockTxMgr, *mockPreimageGameContract) { - logger := testlog.Logger(t, log.LvlError) - txMgr := &mockTxMgr{} +func newTestDirectPreimageUploader(t *testing.T) (*DirectPreimageUploader, *mockTxSender, *mockPreimageGameContract) { + logger := testlog.Logger(t, log.LevelError) + txMgr := &mockTxSender{} contract := &mockPreimageGameContract{} return NewDirectPreimageUploader(logger, txMgr, contract), txMgr, contract } @@ -98,23 +73,23 @@ func (s *mockPreimageGameContract) UpdateOracleTx(_ context.Context, _ uint64, _ return txmgr.TxCandidate{}, nil } -type mockTxMgr struct { +type mockTxSender struct { sends int sendFails bool statusFail bool } -func (s *mockTxMgr) Send(_ context.Context, _ txmgr.TxCandidate) (*ethtypes.Receipt, error) { +func (s *mockTxSender) From() common.Address { + return common.Address{} +} + +func (s *mockTxSender) SendAndWait(_ string, _ ...txmgr.TxCandidate) ([]*ethtypes.Receipt, error) { s.sends++ if s.sendFails { return nil, mockTxMgrSendError } if s.statusFail { - return ðtypes.Receipt{Status: ethtypes.ReceiptStatusFailed}, nil + return []*ethtypes.Receipt{{Status: ethtypes.ReceiptStatusFailed}}, nil } - return ðtypes.Receipt{Status: ethtypes.ReceiptStatusSuccessful}, nil + return []*ethtypes.Receipt{{Status: ethtypes.ReceiptStatusSuccessful}}, nil } - -func (s *mockTxMgr) BlockNumber(_ context.Context) (uint64, error) { return 0, nil } -func (s *mockTxMgr) From() common.Address { return common.Address{} } -func (s *mockTxMgr) Close() {} diff --git a/op-challenger/game/fault/preimages/large.go b/op-challenger/game/fault/preimages/large.go index 4e0bce1b5a5f..47fa47e804f7 100644 --- a/op-challenger/game/fault/preimages/large.go +++ b/op-challenger/game/fault/preimages/large.go @@ -12,17 +12,20 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/matrix" keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" - "github.com/ethereum-optimism/optimism/op-service/sources/batching" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum-optimism/optimism/op-service/txmgr" - ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" ) -var errNotSupported = errors.New("not supported") - var _ PreimageUploader = (*LargePreimageUploader)(nil) +// ErrChallengePeriodNotOver is returned when the challenge period is not over. +var ErrChallengePeriodNotOver = errors.New("challenge period not over") + // MaxBlocksPerChunk is the maximum number of keccak blocks per chunk. const MaxBlocksPerChunk = 300 @@ -37,32 +40,34 @@ const MaxChunkSize = MaxBlocksPerChunk * keccakTypes.BlockSize type LargePreimageUploader struct { log log.Logger - txMgr txmgr.TxManager + clock types.ClockReader + txSender gameTypes.TxSender contract PreimageOracleContract } -func NewLargePreimageUploader(logger log.Logger, txMgr txmgr.TxManager, contract PreimageOracleContract) *LargePreimageUploader { - return &LargePreimageUploader{logger, txMgr, contract} +func NewLargePreimageUploader(logger log.Logger, cl types.ClockReader, txSender gameTypes.TxSender, contract PreimageOracleContract) *LargePreimageUploader { + return &LargePreimageUploader{logger, cl, txSender, contract} } func (p *LargePreimageUploader) UploadPreimage(ctx context.Context, parent uint64, data *types.PreimageOracleData) error { - calls, err := p.splitCalls(data) + p.log.Debug("Upload large preimage", "key", hexutil.Bytes(data.OracleKey)) + stateMatrix, calls, err := p.splitCalls(data) if err != nil { return fmt.Errorf("failed to split preimage into chunks for data with oracle offset %d: %w", data.OracleOffset, err) } - uuid := p.newUUID(data) + uuid := NewUUID(p.txSender.From(), data) // Fetch the current metadata for this preimage data, if it exists. - ident := keccakTypes.LargePreimageIdent{Claimant: p.txMgr.From(), UUID: uuid} - metadata, err := p.contract.GetProposalMetadata(ctx, batching.BlockLatest, ident) + ident := keccakTypes.LargePreimageIdent{Claimant: p.txSender.From(), UUID: uuid} + metadata, err := p.contract.GetProposalMetadata(ctx, rpcblock.Latest, ident) if err != nil { return fmt.Errorf("failed to get pre-image oracle metadata: %w", err) } // The proposal is not initialized if the queried metadata has a claimed size of 0. if len(metadata) == 1 && metadata[0].ClaimedSize == 0 { - err = p.initLargePreimage(ctx, uuid, data.OracleOffset, uint32(len(data.OracleData))) + err = p.initLargePreimage(uuid, data.OracleOffset, uint32(len(data.GetPreimageWithoutSize()))) if err != nil { return fmt.Errorf("failed to initialize large preimage with uuid: %s: %w", uuid, err) } @@ -78,56 +83,94 @@ func (p *LargePreimageUploader) UploadPreimage(ctx context.Context, parent uint6 } } - err = p.addLargePreimageData(ctx, uuid, calls) + err = p.addLargePreimageData(uuid, calls) if err != nil { return fmt.Errorf("failed to add leaves to large preimage with uuid: %s: %w", uuid, err) } - // todo(proofs#467): track the challenge period starting once the full preimage is posted. - // todo(proofs#467): once the challenge period is over, call `squeezeLPP` on the preimage oracle contract. - - return errNotSupported + return p.Squeeze(ctx, uuid, stateMatrix) } -// newUUID generates a new unique identifier for the preimage by hashing the +// NewUUID generates a new unique identifier for the preimage by hashing the // concatenated preimage data, preimage offset, and sender address. -func (p *LargePreimageUploader) newUUID(data *types.PreimageOracleData) *big.Int { - sender := p.txMgr.From() +func NewUUID(sender common.Address, data *types.PreimageOracleData) *big.Int { offset := make([]byte, 4) binary.LittleEndian.PutUint32(offset, data.OracleOffset) - concatenated := append(data.OracleData, offset...) + concatenated := append(data.GetPreimageWithoutSize(), offset...) concatenated = append(concatenated, sender.Bytes()...) hash := crypto.Keccak256Hash(concatenated) return hash.Big() } // splitChunks splits the preimage data into chunks of size [MaxChunkSize] (except the last chunk). -func (p *LargePreimageUploader) splitCalls(data *types.PreimageOracleData) ([]keccakTypes.InputData, error) { +// It also returns the state matrix and the data for the squeeze call if possible. +func (p *LargePreimageUploader) splitCalls(data *types.PreimageOracleData) (*matrix.StateMatrix, []keccakTypes.InputData, error) { // Split the preimage data into chunks of size [MaxChunkSize] (except the last chunk). stateMatrix := matrix.NewStateMatrix() var calls []keccakTypes.InputData - in := bytes.NewReader(data.OracleData) + in := bytes.NewReader(data.GetPreimageWithoutSize()) for { call, err := stateMatrix.AbsorbUpTo(in, MaxChunkSize) if errors.Is(err, io.EOF) { calls = append(calls, call) break } else if err != nil { - return nil, fmt.Errorf("failed to absorb data: %w", err) + return nil, nil, fmt.Errorf("failed to absorb data: %w", err) } calls = append(calls, call) } - return calls, nil + return stateMatrix, calls, nil +} + +func (p *LargePreimageUploader) Squeeze(ctx context.Context, uuid *big.Int, stateMatrix *matrix.StateMatrix) error { + prestateMatrix := stateMatrix.PrestateMatrix() + prestate, prestateProof := stateMatrix.PrestateWithProof() + poststate, poststateProof := stateMatrix.PoststateWithProof() + challengePeriod, err := p.contract.ChallengePeriod(ctx) + if err != nil { + return fmt.Errorf("failed to get challenge period: %w", err) + } + currentTimestamp := p.clock.Now().Unix() + ident := keccakTypes.LargePreimageIdent{Claimant: p.txSender.From(), UUID: uuid} + metadata, err := p.contract.GetProposalMetadata(ctx, rpcblock.Latest, ident) + if err != nil { + return fmt.Errorf("failed to get pre-image oracle metadata: %w", err) + } + if len(metadata) == 0 || metadata[0].ClaimedSize == 0 { + return fmt.Errorf("no metadata found for pre-image oracle with uuid: %s", uuid) + } + if uint64(currentTimestamp) < metadata[0].Timestamp+challengePeriod { + return ErrChallengePeriodNotOver + } + if err := p.contract.CallSqueeze(ctx, p.txSender.From(), uuid, prestateMatrix, prestate, prestateProof, poststate, poststateProof); err != nil { + p.log.Warn("Expected a successful squeeze call", "metadataTimestamp", metadata[0].Timestamp, "currentTimestamp", currentTimestamp, "err", err) + return fmt.Errorf("failed to call squeeze: %w", err) + } + p.log.Info("Squeezing large preimage", "uuid", uuid) + tx, err := p.contract.Squeeze(p.txSender.From(), uuid, prestateMatrix, prestate, prestateProof, poststate, poststateProof) + if err != nil { + return fmt.Errorf("failed to create pre-image oracle tx: %w", err) + } + if _, err := p.txSender.SendAndWait("squeeze large preimage", tx); err != nil { + return fmt.Errorf("failed to populate pre-image oracle: %w", err) + } + return nil } // initLargePreimage initializes the large preimage proposal. // This method *must* be called before adding any leaves. -func (p *LargePreimageUploader) initLargePreimage(ctx context.Context, uuid *big.Int, partOffset uint32, claimedSize uint32) error { +func (p *LargePreimageUploader) initLargePreimage(uuid *big.Int, partOffset uint32, claimedSize uint32) error { + p.log.Info("Init large preimage upload", "uuid", uuid, "partOffset", partOffset, "size", claimedSize) candidate, err := p.contract.InitLargePreimage(uuid, partOffset, claimedSize) if err != nil { return fmt.Errorf("failed to create pre-image oracle tx: %w", err) } - if err := p.sendTxAndWait(ctx, candidate); err != nil { + bond, err := p.contract.GetMinBondLPP(context.Background()) + if err != nil { + return fmt.Errorf("failed to get min bond for large preimage proposal: %w", err) + } + candidate.Value = bond + if _, err := p.txSender.SendAndWait("init large preimage", candidate); err != nil { return fmt.Errorf("failed to populate pre-image oracle: %w", err) } return nil @@ -136,9 +179,8 @@ func (p *LargePreimageUploader) initLargePreimage(ctx context.Context, uuid *big // addLargePreimageData adds data to the large preimage proposal. // This method **must** be called after calling [initLargePreimage]. // SAFETY: submits transactions in a [Queue] for latency while preserving submission order. -func (p *LargePreimageUploader) addLargePreimageData(ctx context.Context, uuid *big.Int, chunks []keccakTypes.InputData) error { - queue := txmgr.NewQueue[int](ctx, p.txMgr, 10) - receiptChs := make([]chan txmgr.TxReceipt[int], len(chunks)) +func (p *LargePreimageUploader) addLargePreimageData(uuid *big.Int, chunks []keccakTypes.InputData) error { + txs := make([]txmgr.TxCandidate, len(chunks)) blocksProcessed := int64(0) for i, chunk := range chunks { tx, err := p.contract.AddLeaves(uuid, big.NewInt(blocksProcessed), chunk.Input, chunk.Commitments, chunk.Finalize) @@ -146,34 +188,9 @@ func (p *LargePreimageUploader) addLargePreimageData(ctx context.Context, uuid * return fmt.Errorf("failed to create pre-image oracle tx: %w", err) } blocksProcessed += int64(len(chunk.Input) / keccakTypes.BlockSize) - receiptChs[i] = make(chan txmgr.TxReceipt[int], 1) - queue.Send(i, tx, receiptChs[i]) - } - for _, receiptCh := range receiptChs { - receipt := <-receiptCh - if receipt.Err != nil { - return receipt.Err - } - if receipt.Receipt.Status == ethtypes.ReceiptStatusFailed { - p.log.Error("LargePreimageUploader add leafs tx successfully published but reverted", "tx_hash", receipt.Receipt.TxHash) - } else { - p.log.Debug("LargePreimageUploader add leafs tx successfully published", "tx_hash", receipt.Receipt.TxHash) - } + txs[i] = tx } - return nil -} - -// sendTxAndWait sends a transaction through the [txmgr] and waits for a receipt. -// This sets the tx GasLimit to 0, performing gas estimation online through the [txmgr]. -func (p *LargePreimageUploader) sendTxAndWait(ctx context.Context, candidate txmgr.TxCandidate) error { - receipt, err := p.txMgr.Send(ctx, candidate) - if err != nil { - return err - } - if receipt.Status == ethtypes.ReceiptStatusFailed { - p.log.Error("LargePreimageUploader tx successfully published but reverted", "tx_hash", receipt.TxHash) - } else { - p.log.Debug("LargePreimageUploader tx successfully published", "tx_hash", receipt.TxHash) - } - return nil + p.log.Info("Adding large preimage leaves", "uuid", uuid, "blocksProcessed", blocksProcessed, "txs", len(txs)) + _, err := p.txSender.SendAndWait("add leaf to large preimage", txs...) + return err } diff --git a/op-challenger/game/fault/preimages/large_test.go b/op-challenger/game/fault/preimages/large_test.go index 198149d0ff04..1913e5a6a47d 100644 --- a/op-challenger/game/fault/preimages/large_test.go +++ b/op-challenger/game/fault/preimages/large_test.go @@ -1,24 +1,36 @@ package preimages import ( + "bytes" "context" + "encoding/binary" "errors" + "io" "math/big" "testing" + "time" - "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/matrix" + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/merkle" keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" - "github.com/ethereum-optimism/optimism/op-service/sources/batching" + preimage "github.com/ethereum-optimism/optimism/op-preimage" + "github.com/ethereum-optimism/optimism/op-service/clock" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" ) -var mockAddLeavesError = errors.New("mock add leaves error") +var ( + mockChallengePeriod = uint64(10000000) + mockAddLeavesError = errors.New("mock add leaves error") + mockSqueezeError = errors.New("mock squeeze error") + mockSqueezeCallError = errors.New("mock squeeze call error") +) func TestLargePreimageUploader_NewUUID(t *testing.T) { tests := []struct { @@ -28,128 +40,131 @@ func TestLargePreimageUploader_NewUUID(t *testing.T) { }{ { name: "EmptyOracleData", - data: &types.PreimageOracleData{}, - expectedUUID: new(big.Int).SetBytes(common.Hex2Bytes("827b659bbda2a0bdecce2c91b8b68462545758f3eba2dbefef18e0daf84f5ccd")), + data: makePreimageData([]byte{}, 0), + expectedUUID: new(big.Int).SetBytes(common.FromHex("827b659bbda2a0bdecce2c91b8b68462545758f3eba2dbefef18e0daf84f5ccd")), }, { - name: "OracleDataAndOffset_Control", - data: &types.PreimageOracleData{ - OracleData: []byte{1, 2, 3}, - OracleOffset: 0x010203, - }, - expectedUUID: new(big.Int).SetBytes(common.Hex2Bytes("641e230bcf3ade8c71b7e591d210184cdb190e853f61ba59a1411c3b7aca9890")), + name: "OracleDataAndOffset_Control", + data: makePreimageData([]byte{1, 2, 3}, 0x010203), + expectedUUID: new(big.Int).SetBytes(common.FromHex("641e230bcf3ade8c71b7e591d210184cdb190e853f61ba59a1411c3b7aca9890")), }, { - name: "OracleDataAndOffset_DifferentOffset", - data: &types.PreimageOracleData{ - OracleData: []byte{1, 2, 3}, - OracleOffset: 0x010204, - }, - expectedUUID: new(big.Int).SetBytes(common.Hex2Bytes("aec56de44401325420e5793f72b777e3e547778de7d8344004b31be086a3136d")), + name: "OracleDataAndOffset_DifferentOffset", + data: makePreimageData([]byte{1, 2, 3}, 0x010204), + expectedUUID: new(big.Int).SetBytes(common.FromHex("aec56de44401325420e5793f72b777e3e547778de7d8344004b31be086a3136d")), }, { - name: "OracleDataAndOffset_DifferentData", - data: &types.PreimageOracleData{ - OracleData: []byte{1, 2, 3, 4}, - OracleOffset: 0x010203, - }, - expectedUUID: new(big.Int).SetBytes(common.Hex2Bytes("ca38aa17d56805cf26376a050c2c7b15b6be4e709bc422a1c679fe21aa6aa8c7")), + name: "OracleDataAndOffset_DifferentData", + data: makePreimageData([]byte{1, 2, 3, 4}, 0x010203), + expectedUUID: new(big.Int).SetBytes(common.FromHex("ca38aa17d56805cf26376a050c2c7b15b6be4e709bc422a1c679fe21aa6aa8c7")), }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - oracle, _, _ := newTestLargePreimageUploader(t) - uuid := oracle.newUUID(test.data) + oracle, _, _, _ := newTestLargePreimageUploader(t) + uuid := NewUUID(oracle.txSender.From(), test.data) require.Equal(t, test.expectedUUID, uuid) }) } } -func TestLargePreimageUploader_UploadPreimage(t *testing.T) { +func TestLargePreimageUploader_UploadPreimage_EdgeCases(t *testing.T) { t.Run("InitFails", func(t *testing.T) { - oracle, _, contract := newTestLargePreimageUploader(t) + oracle, _, _, contract := newTestLargePreimageUploader(t) contract.initFails = true data := mockPreimageOracleData() - err := oracle.UploadPreimage(context.Background(), 0, &data) + err := oracle.UploadPreimage(context.Background(), 0, data) require.ErrorIs(t, err, mockInitLPPError) require.Equal(t, 1, contract.initCalls) }) t.Run("AddLeavesFails", func(t *testing.T) { - oracle, _, contract := newTestLargePreimageUploader(t) + oracle, _, _, contract := newTestLargePreimageUploader(t) contract.addFails = true data := mockPreimageOracleData() - err := oracle.UploadPreimage(context.Background(), 0, &data) + err := oracle.UploadPreimage(context.Background(), 0, data) require.ErrorIs(t, err, mockAddLeavesError) require.Equal(t, 1, contract.addCalls) }) + t.Run("NoBytesProcessed", func(t *testing.T) { + oracle, _, _, contract := newTestLargePreimageUploader(t) + data := mockPreimageOracleData() + contract.claimedSize = uint32(len(data.GetPreimageWithoutSize())) + err := oracle.UploadPreimage(context.Background(), 0, data) + require.NoError(t, err) + require.Equal(t, 1, contract.initCalls) + require.Equal(t, 6, contract.addCalls) + require.Equal(t, data.GetPreimageWithoutSize(), contract.addData) + }) + t.Run("AlreadyInitialized", func(t *testing.T) { - oracle, _, contract := newTestLargePreimageUploader(t) + oracle, _, _, contract := newTestLargePreimageUploader(t) data := mockPreimageOracleData() contract.initialized = true - contract.claimedSize = uint32(len(data.OracleData)) - err := oracle.UploadPreimage(context.Background(), 0, &data) + contract.claimedSize = uint32(len(data.GetPreimageWithoutSize())) + err := oracle.UploadPreimage(context.Background(), 0, data) + require.NoError(t, err) require.Equal(t, 0, contract.initCalls) require.Equal(t, 6, contract.addCalls) - // TODO(client-pod#467): fix this to not error. See LargePreimageUploader.UploadPreimage. - require.ErrorIs(t, err, errNotSupported) }) - t.Run("NoBytesProcessed", func(t *testing.T) { - oracle, _, contract := newTestLargePreimageUploader(t) + t.Run("ChallengePeriodNotElapsed", func(t *testing.T) { + oracle, cl, _, contract := newTestLargePreimageUploader(t) data := mockPreimageOracleData() - err := oracle.UploadPreimage(context.Background(), 0, &data) - require.Equal(t, 1, contract.initCalls) - require.Equal(t, 6, contract.addCalls) - require.Equal(t, data.OracleData, contract.addData) - // TODO(client-pod#467): fix this to not error. See LargePreimageUploader.UploadPreimage. - require.ErrorIs(t, err, errNotSupported) + contract.bytesProcessed = 5*MaxChunkSize + 1 + contract.claimedSize = uint32(len(data.GetPreimageWithoutSize())) + contract.timestamp = uint64(cl.Now().Unix()) + err := oracle.UploadPreimage(context.Background(), 0, data) + require.ErrorIs(t, err, ErrChallengePeriodNotOver) + require.Equal(t, 0, contract.squeezeCalls) + // Squeeze should be called once the challenge period has elapsed. + cl.AdvanceTime(time.Duration(mockChallengePeriod) * time.Second) + err = oracle.UploadPreimage(context.Background(), 0, data) + require.NoError(t, err) + require.Equal(t, 1, contract.squeezeCalls) }) - t.Run("PartialBytesProcessed", func(t *testing.T) { - oracle, _, contract := newTestLargePreimageUploader(t) + t.Run("SqueezeCallFails", func(t *testing.T) { + oracle, _, _, contract := newTestLargePreimageUploader(t) data := mockPreimageOracleData() - contract.bytesProcessed = 3 * MaxChunkSize - contract.claimedSize = uint32(len(data.OracleData)) - err := oracle.UploadPreimage(context.Background(), 0, &data) - require.Equal(t, 0, contract.initCalls) - require.Equal(t, 3, contract.addCalls) - require.Equal(t, data.OracleData[contract.bytesProcessed:], contract.addData) - // TODO(client-pod#467): fix this to not error. See LargePreimageUploader.UploadPreimage. - require.ErrorIs(t, err, errNotSupported) + contract.bytesProcessed = 5*MaxChunkSize + 1 + contract.timestamp = 123 + contract.claimedSize = uint32(len(data.GetPreimageWithoutSize())) + contract.squeezeCallFails = true + err := oracle.UploadPreimage(context.Background(), 0, data) + require.ErrorIs(t, err, mockSqueezeCallError) + require.Equal(t, 0, contract.squeezeCalls) }) - t.Run("LastLeafNotProcessed", func(t *testing.T) { - oracle, _, contract := newTestLargePreimageUploader(t) + t.Run("SqueezeFails", func(t *testing.T) { + oracle, _, _, contract := newTestLargePreimageUploader(t) data := mockPreimageOracleData() - contract.bytesProcessed = 5 * MaxChunkSize - contract.claimedSize = uint32(len(data.OracleData)) - err := oracle.UploadPreimage(context.Background(), 0, &data) - require.Equal(t, 0, contract.initCalls) - require.Equal(t, 1, contract.addCalls) - require.Equal(t, data.OracleData[contract.bytesProcessed:], contract.addData) - // TODO(client-pod#467): fix this to not error. See LargePreimageUploader.UploadPreimage. - require.ErrorIs(t, err, errNotSupported) + contract.bytesProcessed = 5*MaxChunkSize + 1 + contract.timestamp = 123 + contract.claimedSize = uint32(len(data.GetPreimageWithoutSize())) + contract.squeezeFails = true + err := oracle.UploadPreimage(context.Background(), 0, data) + require.ErrorIs(t, err, mockSqueezeError) + require.Equal(t, 1, contract.squeezeCalls) }) t.Run("AllBytesProcessed", func(t *testing.T) { - oracle, _, contract := newTestLargePreimageUploader(t) + oracle, _, _, contract := newTestLargePreimageUploader(t) data := mockPreimageOracleData() contract.bytesProcessed = 5*MaxChunkSize + 1 contract.timestamp = 123 - contract.claimedSize = uint32(len(data.OracleData)) - err := oracle.UploadPreimage(context.Background(), 0, &data) + contract.claimedSize = uint32(len(data.GetPreimageWithoutSize())) + err := oracle.UploadPreimage(context.Background(), 0, data) + require.NoError(t, err) require.Equal(t, 0, contract.initCalls) require.Equal(t, 0, contract.addCalls) require.Empty(t, contract.addData) - // TODO(client-pod#467): fix this to not error. See LargePreimageUploader.UploadPreimage. - require.ErrorIs(t, err, errNotSupported) }) } -func mockPreimageOracleData() types.PreimageOracleData { +func mockPreimageOracleData() *types.PreimageOracleData { fullLeaf := make([]byte, keccakTypes.BlockSize) for i := 0; i < keccakTypes.BlockSize; i++ { fullLeaf[i] = byte(i) @@ -160,30 +175,108 @@ func mockPreimageOracleData() types.PreimageOracleData { } // Add a single byte to the end to make sure the last leaf is not processed. oracleData = append(oracleData, byte(1)) - return types.PreimageOracleData{ - OracleData: oracleData, + return makePreimageData(oracleData, 0) +} + +func makePreimageData(pre []byte, offset uint32) *types.PreimageOracleData { + key := preimage.Keccak256Key(crypto.Keccak256Hash(pre)).PreimageKey() + // add the length prefix + preimage := make([]byte, 0, 8+len(pre)) + preimage = binary.BigEndian.AppendUint64(preimage, uint64(len(pre))) + preimage = append(preimage, pre...) + return types.NewPreimageOracleData(key[:], preimage, offset) +} + +func TestLargePreimageUploader_UploadPreimage_Succeeds(t *testing.T) { + fullLeaf := new([keccakTypes.BlockSize]byte) + for i := 0; i < keccakTypes.BlockSize; i++ { + fullLeaf[i] = byte(i) + } + chunk := make([]byte, 0, MaxChunkSize) + for i := 0; i < MaxBlocksPerChunk; i++ { + chunk = append(chunk, fullLeaf[:]...) + } + tests := []struct { + name string + input []byte + addCalls int + prestateLeaf keccakTypes.Leaf + poststateLeaf keccakTypes.Leaf + }{ + { + name: "FullLeaf", + input: fullLeaf[:], + addCalls: 1, + }, + { + name: "MultipleLeaves", + input: append(fullLeaf[:], append(fullLeaf[:], fullLeaf[:]...)...), + addCalls: 1, + }, + { + name: "MultipleLeavesUnaligned", + input: append(fullLeaf[:], append(fullLeaf[:], byte(9))...), + addCalls: 1, + }, + { + name: "MultipleChunks", + input: append(chunk, append(fullLeaf[:], fullLeaf[:]...)...), + addCalls: 2, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + oracle, _, _, contract := newTestLargePreimageUploader(t) + data := makePreimageData(test.input, 0) + err := oracle.UploadPreimage(context.Background(), 0, data) + require.NoError(t, err) + require.Equal(t, test.addCalls, contract.addCalls) + // There must always be at least one init and squeeze call + // for successful large preimage upload calls. + require.Equal(t, 1, contract.initCalls) + require.Equal(t, 1, contract.squeezeCalls) + + // Use the StateMatrix to determine the expected leaves so it includes padding correctly. + // We rely on the unit tests for StateMatrix to confirm that it does the right thing. + s := matrix.NewStateMatrix() + _, err = s.AbsorbUpTo(bytes.NewReader(test.input), keccakTypes.BlockSize*10000) + require.ErrorIs(t, err, io.EOF) + prestate, _ := s.PrestateWithProof() + poststate, _ := s.PoststateWithProof() + require.Equal(t, prestate, contract.squeezePrestate) + require.Equal(t, poststate, contract.squeezePoststate) + }) } } -func newTestLargePreimageUploader(t *testing.T) (*LargePreimageUploader, *mockTxMgr, *mockPreimageOracleContract) { - logger := testlog.Logger(t, log.LvlError) - txMgr := &mockTxMgr{} +func newTestLargePreimageUploader(t *testing.T) (*LargePreimageUploader, *clock.AdvancingClock, *mockTxSender, *mockPreimageOracleContract) { + logger := testlog.Logger(t, log.LevelError) + cl := clock.NewAdvancingClock(time.Second) + cl.Start() + txSender := &mockTxSender{} contract := &mockPreimageOracleContract{ addData: make([]byte, 0), } - return NewLargePreimageUploader(logger, txMgr, contract), txMgr, contract + return NewLargePreimageUploader(logger, cl, txSender, contract), cl, txSender, contract } type mockPreimageOracleContract struct { - initCalls int - initFails bool - initialized bool - claimedSize uint32 - bytesProcessed int - timestamp uint64 - addCalls int - addFails bool - addData []byte + initCalls int + initFails bool + initialized bool + claimedSize uint32 + bytesProcessed int + timestamp uint64 + addCalls int + addFails bool + addData []byte + squeezeCalls int + squeezeFails bool + squeezeCallFails bool + squeezeCallClaimSize uint32 + squeezePrestate keccakTypes.Leaf + squeezePoststate keccakTypes.Leaf } func (s *mockPreimageOracleContract) InitLargePreimage(_ *big.Int, _ uint32, _ uint32) (txmgr.TxCandidate, error) { @@ -203,10 +296,33 @@ func (s *mockPreimageOracleContract) AddLeaves(_ *big.Int, _ *big.Int, input []b return txmgr.TxCandidate{}, nil } -func (s *mockPreimageOracleContract) Squeeze(_ common.Address, _ *big.Int, _ *matrix.StateMatrix, _ keccakTypes.Leaf, _ contracts.MerkleProof, _ keccakTypes.Leaf, _ contracts.MerkleProof) (txmgr.TxCandidate, error) { +func (s *mockPreimageOracleContract) Squeeze(_ common.Address, _ *big.Int, _ keccakTypes.StateSnapshot, prestate keccakTypes.Leaf, _ merkle.Proof, poststate keccakTypes.Leaf, _ merkle.Proof) (txmgr.TxCandidate, error) { + s.squeezeCalls++ + s.squeezePrestate = prestate + s.squeezePoststate = poststate + if s.squeezeFails { + return txmgr.TxCandidate{}, mockSqueezeError + } return txmgr.TxCandidate{}, nil } -func (s *mockPreimageOracleContract) GetProposalMetadata(_ context.Context, _ batching.Block, idents ...keccakTypes.LargePreimageIdent) ([]keccakTypes.LargePreimageMetaData, error) { + +func (s *mockPreimageOracleContract) ChallengePeriod(_ context.Context) (uint64, error) { + return mockChallengePeriod, nil +} + +func (s *mockPreimageOracleContract) GetProposalMetadata(_ context.Context, _ rpcblock.Block, idents ...keccakTypes.LargePreimageIdent) ([]keccakTypes.LargePreimageMetaData, error) { + if s.squeezeCallClaimSize > 0 { + metadata := make([]keccakTypes.LargePreimageMetaData, 0) + for _, ident := range idents { + metadata = append(metadata, keccakTypes.LargePreimageMetaData{ + LargePreimageIdent: ident, + ClaimedSize: s.squeezeCallClaimSize, + BytesProcessed: uint32(s.bytesProcessed), + Timestamp: s.timestamp, + }) + } + return metadata, nil + } if s.initialized || s.bytesProcessed > 0 { metadata := make([]keccakTypes.LargePreimageMetaData, 0) for _, ident := range idents { @@ -219,5 +335,17 @@ func (s *mockPreimageOracleContract) GetProposalMetadata(_ context.Context, _ ba } return metadata, nil } + s.squeezeCallClaimSize = 1 return []keccakTypes.LargePreimageMetaData{{LargePreimageIdent: idents[0]}}, nil } + +func (s *mockPreimageOracleContract) GetMinBondLPP(_ context.Context) (*big.Int, error) { + return big.NewInt(0), nil +} + +func (s *mockPreimageOracleContract) CallSqueeze(_ context.Context, _ common.Address, _ *big.Int, _ keccakTypes.StateSnapshot, _ keccakTypes.Leaf, _ merkle.Proof, _ keccakTypes.Leaf, _ merkle.Proof) error { + if s.squeezeCallFails { + return mockSqueezeCallError + } + return nil +} diff --git a/op-challenger/game/fault/preimages/split.go b/op-challenger/game/fault/preimages/split.go index d219facc048a..84541c7feb6e 100644 --- a/op-challenger/game/fault/preimages/split.go +++ b/op-challenger/game/fault/preimages/split.go @@ -8,31 +8,26 @@ import ( var _ PreimageUploader = (*SplitPreimageUploader)(nil) -// PREIMAGE_SIZE_THRESHOLD is the size threshold for determining whether a preimage -// should be uploaded directly or through the large preimage uploader. -// TODO(client-pod#467): determine the correct size threshold to toggle between -// -// the direct and large preimage uploaders. -const PREIMAGE_SIZE_THRESHOLD = 136 * 128 - // SplitPreimageUploader routes preimage uploads to the appropriate uploader // based on the size of the preimage. type SplitPreimageUploader struct { - directUploader PreimageUploader - largeUploader PreimageUploader + largePreimageSizeThreshold uint64 + directUploader PreimageUploader + largeUploader PreimageUploader } -func NewSplitPreimageUploader(directUploader PreimageUploader, largeUploader PreimageUploader) *SplitPreimageUploader { - return &SplitPreimageUploader{directUploader, largeUploader} +func NewSplitPreimageUploader(directUploader PreimageUploader, largeUploader PreimageUploader, minLargePreimageSize uint64) *SplitPreimageUploader { + return &SplitPreimageUploader{minLargePreimageSize, directUploader, largeUploader} } func (s *SplitPreimageUploader) UploadPreimage(ctx context.Context, parent uint64, data *types.PreimageOracleData) error { if data == nil { return ErrNilPreimageData } - if len(data.OracleData) > PREIMAGE_SIZE_THRESHOLD { - return s.largeUploader.UploadPreimage(ctx, parent, data) - } else { + // Always route local preimage uploads to the direct uploader. + if data.IsLocal || uint64(len(data.GetPreimageWithoutSize())) < s.largePreimageSizeThreshold { return s.directUploader.UploadPreimage(ctx, parent, data) + } else { + return s.largeUploader.UploadPreimage(ctx, parent, data) } } diff --git a/op-challenger/game/fault/preimages/split_test.go b/op-challenger/game/fault/preimages/split_test.go index 83286ab0f767..fbecdc06467c 100644 --- a/op-challenger/game/fault/preimages/split_test.go +++ b/op-challenger/game/fault/preimages/split_test.go @@ -8,25 +8,43 @@ import ( "github.com/stretchr/testify/require" ) +var mockLargePreimageSizeThreshold = uint64(100) + func TestSplitPreimageUploader_UploadPreimage(t *testing.T) { t.Run("DirectUploadSucceeds", func(t *testing.T) { - oracle, direct, large := newTestSplitPreimageUploader(t) - err := oracle.UploadPreimage(context.Background(), 0, &types.PreimageOracleData{}) + oracle, direct, large := newTestSplitPreimageUploader(t, mockLargePreimageSizeThreshold) + err := oracle.UploadPreimage(context.Background(), 0, makePreimageData(nil, 0)) + require.NoError(t, err) + require.Equal(t, 1, direct.updates) + require.Equal(t, 0, large.updates) + }) + + t.Run("LocalDataUploadSucceeds", func(t *testing.T) { + oracle, direct, large := newTestSplitPreimageUploader(t, mockLargePreimageSizeThreshold) + err := oracle.UploadPreimage(context.Background(), 0, &types.PreimageOracleData{IsLocal: true}) + require.NoError(t, err) + require.Equal(t, 1, direct.updates) + require.Equal(t, 0, large.updates) + }) + + t.Run("MaxSizeDirectUploadSucceeds", func(t *testing.T) { + oracle, direct, large := newTestSplitPreimageUploader(t, mockLargePreimageSizeThreshold) + err := oracle.UploadPreimage(context.Background(), 0, makePreimageData(make([]byte, mockLargePreimageSizeThreshold-1), 0)) require.NoError(t, err) require.Equal(t, 1, direct.updates) require.Equal(t, 0, large.updates) }) t.Run("LargeUploadSucceeds", func(t *testing.T) { - oracle, direct, large := newTestSplitPreimageUploader(t) - err := oracle.UploadPreimage(context.Background(), 0, &types.PreimageOracleData{OracleData: make([]byte, PREIMAGE_SIZE_THRESHOLD+1)}) + oracle, direct, large := newTestSplitPreimageUploader(t, mockLargePreimageSizeThreshold) + err := oracle.UploadPreimage(context.Background(), 0, makePreimageData(make([]byte, mockLargePreimageSizeThreshold), 0)) require.NoError(t, err) require.Equal(t, 1, large.updates) require.Equal(t, 0, direct.updates) }) t.Run("NilPreimageOracleData", func(t *testing.T) { - oracle, _, _ := newTestSplitPreimageUploader(t) + oracle, _, _ := newTestSplitPreimageUploader(t, mockLargePreimageSizeThreshold) err := oracle.UploadPreimage(context.Background(), 0, nil) require.ErrorIs(t, err, ErrNilPreimageData) }) @@ -45,8 +63,8 @@ func (s *mockPreimageUploader) UploadPreimage(ctx context.Context, parent uint64 return nil } -func newTestSplitPreimageUploader(t *testing.T) (*SplitPreimageUploader, *mockPreimageUploader, *mockPreimageUploader) { +func newTestSplitPreimageUploader(t *testing.T, threshold uint64) (*SplitPreimageUploader, *mockPreimageUploader, *mockPreimageUploader) { direct := &mockPreimageUploader{} large := &mockPreimageUploader{} - return NewSplitPreimageUploader(direct, large), direct, large + return NewSplitPreimageUploader(direct, large, threshold), direct, large } diff --git a/op-challenger/game/fault/preimages/types.go b/op-challenger/game/fault/preimages/types.go index 339ce164d64e..45665d5fc94e 100644 --- a/op-challenger/game/fault/preimages/types.go +++ b/op-challenger/game/fault/preimages/types.go @@ -5,11 +5,10 @@ import ( "fmt" "math/big" - "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" - "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/matrix" + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/merkle" keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" - "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/common" ) @@ -26,6 +25,9 @@ type PreimageUploader interface { type PreimageOracleContract interface { InitLargePreimage(uuid *big.Int, partOffset uint32, claimedSize uint32) (txmgr.TxCandidate, error) AddLeaves(uuid *big.Int, startingBlockIndex *big.Int, input []byte, commitments []common.Hash, finalize bool) (txmgr.TxCandidate, error) - Squeeze(claimant common.Address, uuid *big.Int, stateMatrix *matrix.StateMatrix, preState keccakTypes.Leaf, preStateProof contracts.MerkleProof, postState keccakTypes.Leaf, postStateProof contracts.MerkleProof) (txmgr.TxCandidate, error) - GetProposalMetadata(ctx context.Context, block batching.Block, idents ...keccakTypes.LargePreimageIdent) ([]keccakTypes.LargePreimageMetaData, error) + Squeeze(claimant common.Address, uuid *big.Int, prestateMatrix keccakTypes.StateSnapshot, preState keccakTypes.Leaf, preStateProof merkle.Proof, postState keccakTypes.Leaf, postStateProof merkle.Proof) (txmgr.TxCandidate, error) + CallSqueeze(ctx context.Context, claimant common.Address, uuid *big.Int, prestateMatrix keccakTypes.StateSnapshot, preState keccakTypes.Leaf, preStateProof merkle.Proof, postState keccakTypes.Leaf, postStateProof merkle.Proof) error + GetProposalMetadata(ctx context.Context, block rpcblock.Block, idents ...keccakTypes.LargePreimageIdent) ([]keccakTypes.LargePreimageMetaData, error) + ChallengePeriod(ctx context.Context) (uint64, error) + GetMinBondLPP(ctx context.Context) (*big.Int, error) } diff --git a/op-challenger/game/fault/register.go b/op-challenger/game/fault/register.go index 345c901dc2db..936cb7145af2 100644 --- a/op-challenger/game/fault/register.go +++ b/op-challenger/game/fault/register.go @@ -5,7 +5,9 @@ import ( "fmt" "github.com/ethereum-optimism/optimism/op-challenger/config" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/claims" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/outputs" faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" @@ -13,37 +15,48 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/scheduler" "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum-optimism/optimism/op-challenger/metrics" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/sources/batching" - "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" ) -var ( - cannonGameType = uint8(0) - alphabetGameType = uint8(255) -) - type CloseFunc func() type Registry interface { - RegisterGameType(gameType uint8, creator scheduler.PlayerCreator, oracle keccakTypes.LargePreimageOracle) + RegisterGameType(gameType uint32, creator scheduler.PlayerCreator) + RegisterBondContract(gameType uint32, creator claims.BondContractCreator) +} + +type OracleRegistry interface { + RegisterOracle(oracle keccakTypes.LargePreimageOracle) +} + +type RollupClient interface { + outputs.OutputRollupClient + SyncStatusProvider } func RegisterGameTypes( - registry Registry, ctx context.Context, + cl faultTypes.ClockReader, logger log.Logger, m metrics.Metricer, cfg *config.Config, - rollupClient outputs.OutputRollupClient, - txMgr txmgr.TxManager, + registry Registry, + oracles OracleRegistry, + rollupClient RollupClient, + txSender types.TxSender, gameFactory *contracts.DisputeGameFactoryContract, caller *batching.MultiCaller, + l1HeaderSource L1HeaderSource, + selective bool, + claimants []common.Address, ) (CloseFunc, error) { var closer CloseFunc var l2Client *ethclient.Client - if cfg.TraceTypeEnabled(config.TraceTypeCannon) { + if cfg.TraceTypeEnabled(config.TraceTypeCannon) || cfg.TraceTypeEnabled(config.TraceTypePermissioned) { l2, err := ethclient.DialContext(ctx, cfg.CannonL2) if err != nil { return nil, fmt.Errorf("dial l2 client %v: %w", cfg.CannonL2, err) @@ -51,13 +64,20 @@ func RegisterGameTypes( l2Client = l2 closer = l2Client.Close } + syncValidator := newSyncStatusValidator(rollupClient) + if cfg.TraceTypeEnabled(config.TraceTypeCannon) { - if err := registerCannon(registry, ctx, logger, m, cfg, rollupClient, txMgr, gameFactory, caller, l2Client); err != nil { + if err := registerCannon(faultTypes.CannonGameType, registry, oracles, ctx, cl, logger, m, cfg, syncValidator, rollupClient, txSender, gameFactory, caller, l2Client, l1HeaderSource, selective, claimants); err != nil { return nil, fmt.Errorf("failed to register cannon game type: %w", err) } } + if cfg.TraceTypeEnabled(config.TraceTypePermissioned) { + if err := registerCannon(faultTypes.PermissionedGameType, registry, oracles, ctx, cl, logger, m, cfg, syncValidator, rollupClient, txSender, gameFactory, caller, l2Client, l1HeaderSource, selective, claimants); err != nil { + return nil, fmt.Errorf("failed to register permissioned cannon game type: %w", err) + } + } if cfg.TraceTypeEnabled(config.TraceTypeAlphabet) { - if err := registerAlphabet(registry, ctx, logger, m, rollupClient, txMgr, gameFactory, caller); err != nil { + if err := registerAlphabet(registry, oracles, ctx, cl, logger, m, syncValidator, rollupClient, txSender, gameFactory, caller, l1HeaderSource, selective, claimants); err != nil { return nil, fmt.Errorf("failed to register alphabet game type: %w", err) } } @@ -66,104 +86,159 @@ func RegisterGameTypes( func registerAlphabet( registry Registry, + oracles OracleRegistry, ctx context.Context, + cl faultTypes.ClockReader, logger log.Logger, m metrics.Metricer, - rollupClient outputs.OutputRollupClient, - txMgr txmgr.TxManager, + syncValidator SyncValidator, + rollupClient RollupClient, + txSender types.TxSender, gameFactory *contracts.DisputeGameFactoryContract, caller *batching.MultiCaller, + l1HeaderSource L1HeaderSource, + selective bool, + claimants []common.Address, ) error { playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) { contract, err := contracts.NewFaultDisputeGameContract(game.Proxy, caller) if err != nil { return nil, err } + oracle, err := contract.GetOracle(ctx) + if err != nil { + return nil, fmt.Errorf("failed to load oracle for game %v: %w", game.Proxy, err) + } + oracles.RegisterOracle(oracle) prestateBlock, poststateBlock, err := contract.GetBlockRange(ctx) if err != nil { return nil, err } - prestateProvider := outputs.NewPrestateProvider(ctx, logger, rollupClient, prestateBlock) splitDepth, err := contract.GetSplitDepth(ctx) if err != nil { return nil, err } + l1Head, err := loadL1Head(contract, ctx, l1HeaderSource) + if err != nil { + return nil, err + } + prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock) creator := func(ctx context.Context, logger log.Logger, gameDepth faultTypes.Depth, dir string) (faultTypes.TraceAccessor, error) { - accessor, err := outputs.NewOutputAlphabetTraceAccessor(logger, m, prestateProvider, rollupClient, splitDepth, prestateBlock, poststateBlock) + accessor, err := outputs.NewOutputAlphabetTraceAccessor(logger, m, prestateProvider, rollupClient, l1Head, splitDepth, prestateBlock, poststateBlock) if err != nil { return nil, err } return accessor, nil } - prestateValidator := NewPrestateValidator(contract.GetAbsolutePrestateHash, prestateProvider) - genesisValidator := NewPrestateValidator(contract.GetGenesisOutputRoot, prestateProvider) - return NewGamePlayer(ctx, logger, m, dir, game.Proxy, txMgr, contract, []Validator{prestateValidator, genesisValidator}, creator) + prestateValidator := NewPrestateValidator("alphabet", contract.GetAbsolutePrestateHash, alphabet.PrestateProvider) + startingValidator := NewPrestateValidator("output root", contract.GetStartingRootHash, prestateProvider) + return NewGamePlayer(ctx, cl, logger, m, dir, game.Proxy, txSender, contract, syncValidator, []Validator{prestateValidator, startingValidator}, creator, l1HeaderSource, selective, claimants) } - oracle, err := createOracle(ctx, gameFactory, caller) + err := registerOracle(ctx, oracles, gameFactory, caller, faultTypes.AlphabetGameType) if err != nil { return err } - registry.RegisterGameType(alphabetGameType, playerCreator, oracle) + registry.RegisterGameType(faultTypes.AlphabetGameType, playerCreator) + + contractCreator := func(game types.GameMetadata) (claims.BondContract, error) { + return contracts.NewFaultDisputeGameContract(game.Proxy, caller) + } + registry.RegisterBondContract(faultTypes.AlphabetGameType, contractCreator) return nil } -func createOracle(ctx context.Context, gameFactory *contracts.DisputeGameFactoryContract, caller *batching.MultiCaller) (*contracts.PreimageOracleContract, error) { - implAddr, err := gameFactory.GetGameImpl(ctx, alphabetGameType) +func registerOracle(ctx context.Context, oracles OracleRegistry, gameFactory *contracts.DisputeGameFactoryContract, caller *batching.MultiCaller, gameType uint32) error { + implAddr, err := gameFactory.GetGameImpl(ctx, gameType) if err != nil { - return nil, fmt.Errorf("failed to load alphabet game implementation: %w", err) + return fmt.Errorf("failed to load implementation for game type %v: %w", gameType, err) } contract, err := contracts.NewFaultDisputeGameContract(implAddr, caller) if err != nil { - return nil, err + return err } oracle, err := contract.GetOracle(ctx) if err != nil { - return nil, fmt.Errorf("failed to load oracle address: %w", err) + return fmt.Errorf("failed to load oracle address: %w", err) } - return oracle, nil + oracles.RegisterOracle(oracle) + return nil } func registerCannon( + gameType uint32, registry Registry, + oracles OracleRegistry, ctx context.Context, + cl faultTypes.ClockReader, logger log.Logger, m metrics.Metricer, cfg *config.Config, + syncValidator SyncValidator, rollupClient outputs.OutputRollupClient, - txMgr txmgr.TxManager, + txSender types.TxSender, gameFactory *contracts.DisputeGameFactoryContract, caller *batching.MultiCaller, l2Client cannon.L2HeaderSource, + l1HeaderSource L1HeaderSource, + selective bool, + claimants []common.Address, ) error { + cannonPrestateProvider := cannon.NewPrestateProvider(cfg.CannonAbsolutePreState) playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) { contract, err := contracts.NewFaultDisputeGameContract(game.Proxy, caller) if err != nil { return nil, err } + oracle, err := contract.GetOracle(ctx) + if err != nil { + return nil, fmt.Errorf("failed to load oracle for game %v: %w", game.Proxy, err) + } + oracles.RegisterOracle(oracle) prestateBlock, poststateBlock, err := contract.GetBlockRange(ctx) if err != nil { return nil, err } - prestateProvider := outputs.NewPrestateProvider(ctx, logger, rollupClient, prestateBlock) + splitDepth, err := contract.GetSplitDepth(ctx) + if err != nil { + return nil, fmt.Errorf("failed to load split depth: %w", err) + } + l1HeadID, err := loadL1Head(contract, ctx, l1HeaderSource) + if err != nil { + return nil, err + } + prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock) creator := func(ctx context.Context, logger log.Logger, gameDepth faultTypes.Depth, dir string) (faultTypes.TraceAccessor, error) { - splitDepth, err := contract.GetSplitDepth(ctx) - if err != nil { - return nil, fmt.Errorf("failed to load split depth: %w", err) - } - accessor, err := outputs.NewOutputCannonTraceAccessor(logger, m, cfg, l2Client, contract, prestateProvider, rollupClient, dir, splitDepth, prestateBlock, poststateBlock) + accessor, err := outputs.NewOutputCannonTraceAccessor(logger, m, cfg, l2Client, prestateProvider, rollupClient, dir, l1HeadID, splitDepth, prestateBlock, poststateBlock) if err != nil { return nil, err } return accessor, nil } - prestateValidator := NewPrestateValidator(contract.GetAbsolutePrestateHash, prestateProvider) - genesisValidator := NewPrestateValidator(contract.GetGenesisOutputRoot, prestateProvider) - return NewGamePlayer(ctx, logger, m, dir, game.Proxy, txMgr, contract, []Validator{prestateValidator, genesisValidator}, creator) + prestateValidator := NewPrestateValidator("cannon", contract.GetAbsolutePrestateHash, cannonPrestateProvider) + startingValidator := NewPrestateValidator("output root", contract.GetStartingRootHash, prestateProvider) + return NewGamePlayer(ctx, cl, logger, m, dir, game.Proxy, txSender, contract, syncValidator, []Validator{prestateValidator, startingValidator}, creator, l1HeaderSource, selective, claimants) } - oracle, err := createOracle(ctx, gameFactory, caller) + err := registerOracle(ctx, oracles, gameFactory, caller, gameType) if err != nil { return err } - registry.RegisterGameType(cannonGameType, playerCreator, oracle) + registry.RegisterGameType(gameType, playerCreator) + + contractCreator := func(game types.GameMetadata) (claims.BondContract, error) { + return contracts.NewFaultDisputeGameContract(game.Proxy, caller) + } + registry.RegisterBondContract(gameType, contractCreator) return nil } + +func loadL1Head(contract *contracts.FaultDisputeGameContract, ctx context.Context, l1HeaderSource L1HeaderSource) (eth.BlockID, error) { + l1Head, err := contract.GetL1Head(ctx) + if err != nil { + return eth.BlockID{}, fmt.Errorf("failed to load L1 head: %w", err) + } + l1Header, err := l1HeaderSource.HeaderByHash(ctx, l1Head) + if err != nil { + return eth.BlockID{}, fmt.Errorf("failed to load L1 header: %w", err) + } + return eth.HeaderBlockID(l1Header), nil +} diff --git a/op-challenger/game/fault/responder/responder.go b/op-challenger/game/fault/responder/responder.go index 84215524ee1f..fbeddc5b622c 100644 --- a/op-challenger/game/fault/responder/responder.go +++ b/op-challenger/game/fault/responder/responder.go @@ -2,6 +2,7 @@ package responder import ( "context" + "errors" "fmt" "math/big" @@ -11,7 +12,6 @@ import ( "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" ) @@ -26,22 +26,27 @@ type GameContract interface { GetRequiredBond(ctx context.Context, position types.Position) (*big.Int, error) } +type Oracle interface { + GlobalDataExists(ctx context.Context, data *types.PreimageOracleData) (bool, error) +} + // FaultResponder implements the [Responder] interface to send onchain transactions. type FaultResponder struct { - log log.Logger - - txMgr txmgr.TxManager + log log.Logger + sender gameTypes.TxSender contract GameContract uploader preimages.PreimageUploader + oracle Oracle } // NewFaultResponder returns a new [FaultResponder]. -func NewFaultResponder(logger log.Logger, txMgr txmgr.TxManager, contract GameContract, uploader preimages.PreimageUploader) (*FaultResponder, error) { +func NewFaultResponder(logger log.Logger, sender gameTypes.TxSender, contract GameContract, uploader preimages.PreimageUploader, oracle Oracle) (*FaultResponder, error) { return &FaultResponder{ log: logger, - txMgr: txMgr, + sender: sender, contract: contract, uploader: uploader, + oracle: oracle, }, nil } @@ -52,13 +57,13 @@ func (r *FaultResponder) CallResolve(ctx context.Context) (gameTypes.GameStatus, } // Resolve executes a resolve transaction to resolve a fault dispute game. -func (r *FaultResponder) Resolve(ctx context.Context) error { +func (r *FaultResponder) Resolve() error { candidate, err := r.contract.ResolveTx() if err != nil { return err } - return r.sendTxAndWait(ctx, candidate) + return r.sendTxAndWait("resolve game", candidate) } // CallResolveClaim determines if the resolveClaim function on the fault dispute game contract @@ -68,19 +73,33 @@ func (r *FaultResponder) CallResolveClaim(ctx context.Context, claimIdx uint64) } // ResolveClaim executes a resolveClaim transaction to resolve a fault dispute game. -func (r *FaultResponder) ResolveClaim(ctx context.Context, claimIdx uint64) error { +func (r *FaultResponder) ResolveClaim(claimIdx uint64) error { candidate, err := r.contract.ResolveClaimTx(claimIdx) if err != nil { return err } - return r.sendTxAndWait(ctx, candidate) + return r.sendTxAndWait("resolve claim", candidate) } func (r *FaultResponder) PerformAction(ctx context.Context, action types.Action) error { if action.OracleData != nil { - err := r.uploader.UploadPreimage(ctx, uint64(action.ParentIdx), action.OracleData) - if err != nil { - return fmt.Errorf("failed to upload preimage: %w", err) + var preimageExists bool + var err error + if !action.OracleData.IsLocal { + preimageExists, err = r.oracle.GlobalDataExists(ctx, action.OracleData) + if err != nil { + return fmt.Errorf("failed to check if preimage exists: %w", err) + } + } + // Always upload local preimages + if !preimageExists { + err := r.uploader.UploadPreimage(ctx, uint64(action.ParentIdx), action.OracleData) + if errors.Is(err, preimages.ErrChallengePeriodNotOver) { + r.log.Debug("Large Preimage Squeeze failed, challenge period not over") + return nil + } else if err != nil { + return fmt.Errorf("failed to upload preimage: %w", err) + } } } var candidate txmgr.TxCandidate @@ -107,20 +126,12 @@ func (r *FaultResponder) PerformAction(ctx context.Context, action types.Action) if err != nil { return err } - return r.sendTxAndWait(ctx, candidate) + return r.sendTxAndWait("perform action", candidate) } // sendTxAndWait sends a transaction through the [txmgr] and waits for a receipt. // This sets the tx GasLimit to 0, performing gas estimation online through the [txmgr]. -func (r *FaultResponder) sendTxAndWait(ctx context.Context, candidate txmgr.TxCandidate) error { - receipt, err := r.txMgr.Send(ctx, candidate) - if err != nil { - return err - } - if receipt.Status == ethtypes.ReceiptStatusFailed { - r.log.Error("Responder tx successfully published but reverted", "tx_hash", receipt.TxHash) - } else { - r.log.Debug("Responder tx successfully published", "tx_hash", receipt.TxHash) - } - return nil +func (r *FaultResponder) sendTxAndWait(purpose string, candidate txmgr.TxCandidate) error { + _, err := r.sender.SendAndWait(purpose, candidate) + return err } diff --git a/op-challenger/game/fault/responder/responder_test.go b/op-challenger/game/fault/responder/responder_test.go index 6f62e2bdc71a..a2be0bab9ad3 100644 --- a/op-challenger/game/fault/responder/responder_test.go +++ b/op-challenger/game/fault/responder/responder_test.go @@ -22,12 +22,13 @@ var ( mockPreimageUploadErr = errors.New("mock preimage upload error") mockSendError = errors.New("mock send error") mockCallError = errors.New("mock call error") + mockOracleExistsError = errors.New("mock oracle exists error") ) // TestCallResolve tests the [Responder.CallResolve]. func TestCallResolve(t *testing.T) { t.Run("SendFails", func(t *testing.T) { - responder, _, contract, _ := newTestFaultResponder(t) + responder, _, contract, _, _ := newTestFaultResponder(t) contract.callFails = true status, err := responder.CallResolve(context.Background()) require.ErrorIs(t, err, mockCallError) @@ -36,7 +37,7 @@ func TestCallResolve(t *testing.T) { }) t.Run("Success", func(t *testing.T) { - responder, _, contract, _ := newTestFaultResponder(t) + responder, _, contract, _, _ := newTestFaultResponder(t) status, err := responder.CallResolve(context.Background()) require.NoError(t, err) require.Equal(t, gameTypes.GameStatusInProgress, status) @@ -47,16 +48,16 @@ func TestCallResolve(t *testing.T) { // TestResolve tests the [Responder.Resolve] method. func TestResolve(t *testing.T) { t.Run("SendFails", func(t *testing.T) { - responder, mockTxMgr, _, _ := newTestFaultResponder(t) + responder, mockTxMgr, _, _, _ := newTestFaultResponder(t) mockTxMgr.sendFails = true - err := responder.Resolve(context.Background()) + err := responder.Resolve() require.ErrorIs(t, err, mockSendError) require.Equal(t, 0, mockTxMgr.sends) }) t.Run("Success", func(t *testing.T) { - responder, mockTxMgr, _, _ := newTestFaultResponder(t) - err := responder.Resolve(context.Background()) + responder, mockTxMgr, _, _, _ := newTestFaultResponder(t) + err := responder.Resolve() require.NoError(t, err) require.Equal(t, 1, mockTxMgr.sends) }) @@ -64,7 +65,7 @@ func TestResolve(t *testing.T) { func TestCallResolveClaim(t *testing.T) { t.Run("SendFails", func(t *testing.T) { - responder, _, contract, _ := newTestFaultResponder(t) + responder, _, contract, _, _ := newTestFaultResponder(t) contract.callFails = true err := responder.CallResolveClaim(context.Background(), 0) require.ErrorIs(t, err, mockCallError) @@ -72,7 +73,7 @@ func TestCallResolveClaim(t *testing.T) { }) t.Run("Success", func(t *testing.T) { - responder, _, contract, _ := newTestFaultResponder(t) + responder, _, contract, _, _ := newTestFaultResponder(t) err := responder.CallResolveClaim(context.Background(), 0) require.NoError(t, err) require.Equal(t, 1, contract.calls) @@ -81,16 +82,16 @@ func TestCallResolveClaim(t *testing.T) { func TestResolveClaim(t *testing.T) { t.Run("SendFails", func(t *testing.T) { - responder, mockTxMgr, _, _ := newTestFaultResponder(t) + responder, mockTxMgr, _, _, _ := newTestFaultResponder(t) mockTxMgr.sendFails = true - err := responder.ResolveClaim(context.Background(), 0) + err := responder.ResolveClaim(0) require.ErrorIs(t, err, mockSendError) require.Equal(t, 0, mockTxMgr.sends) }) t.Run("Success", func(t *testing.T) { - responder, mockTxMgr, _, _ := newTestFaultResponder(t) - err := responder.ResolveClaim(context.Background(), 0) + responder, mockTxMgr, _, _, _ := newTestFaultResponder(t) + err := responder.ResolveClaim(0) require.NoError(t, err) require.Equal(t, 1, mockTxMgr.sends) }) @@ -99,7 +100,7 @@ func TestResolveClaim(t *testing.T) { // TestRespond tests the [Responder.Respond] method. func TestPerformAction(t *testing.T) { t.Run("send fails", func(t *testing.T) { - responder, mockTxMgr, _, _ := newTestFaultResponder(t) + responder, mockTxMgr, _, _, _ := newTestFaultResponder(t) mockTxMgr.sendFails = true err := responder.PerformAction(context.Background(), types.Action{ Type: types.ActionTypeMove, @@ -112,7 +113,7 @@ func TestPerformAction(t *testing.T) { }) t.Run("sends response", func(t *testing.T) { - responder, mockTxMgr, _, _ := newTestFaultResponder(t) + responder, mockTxMgr, _, _, _ := newTestFaultResponder(t) err := responder.PerformAction(context.Background(), types.Action{ Type: types.ActionTypeMove, ParentIdx: 123, @@ -124,7 +125,7 @@ func TestPerformAction(t *testing.T) { }) t.Run("attack", func(t *testing.T) { - responder, mockTxMgr, contract, _ := newTestFaultResponder(t) + responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t) action := types.Action{ Type: types.ActionTypeMove, ParentIdx: 123, @@ -140,7 +141,7 @@ func TestPerformAction(t *testing.T) { }) t.Run("defend", func(t *testing.T) { - responder, mockTxMgr, contract, _ := newTestFaultResponder(t) + responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t) action := types.Action{ Type: types.ActionTypeMove, ParentIdx: 123, @@ -156,7 +157,7 @@ func TestPerformAction(t *testing.T) { }) t.Run("step", func(t *testing.T) { - responder, mockTxMgr, contract, _ := newTestFaultResponder(t) + responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t) action := types.Action{ Type: types.ActionTypeStep, ParentIdx: 123, @@ -172,8 +173,8 @@ func TestPerformAction(t *testing.T) { require.Equal(t, ([]byte)("step"), mockTxMgr.sent[0].TxData) }) - t.Run("stepWithOracleData", func(t *testing.T) { - responder, mockTxMgr, contract, uploader := newTestFaultResponder(t) + t.Run("stepWithLocalOracleData", func(t *testing.T) { + responder, mockTxMgr, contract, uploader, oracle := newTestFaultResponder(t) action := types.Action{ Type: types.ActionTypeStep, ParentIdx: 123, @@ -191,10 +192,33 @@ func TestPerformAction(t *testing.T) { require.Nil(t, contract.updateOracleArgs) // mock uploader returns nil require.Equal(t, ([]byte)("step"), mockTxMgr.sent[0].TxData) require.Equal(t, 1, uploader.updates) + require.Equal(t, 0, oracle.existCalls) + }) + + t.Run("stepWithGlobalOracleData", func(t *testing.T) { + responder, mockTxMgr, contract, uploader, oracle := newTestFaultResponder(t) + action := types.Action{ + Type: types.ActionTypeStep, + ParentIdx: 123, + IsAttack: true, + PreState: []byte{1, 2, 3}, + ProofData: []byte{4, 5, 6}, + OracleData: &types.PreimageOracleData{ + IsLocal: false, + }, + } + err := responder.PerformAction(context.Background(), action) + require.NoError(t, err) + + require.Len(t, mockTxMgr.sent, 1) + require.Nil(t, contract.updateOracleArgs) // mock uploader returns nil + require.Equal(t, ([]byte)("step"), mockTxMgr.sent[0].TxData) + require.Equal(t, 1, uploader.updates) + require.Equal(t, 1, oracle.existCalls) }) t.Run("stepWithOracleDataAndUploadFails", func(t *testing.T) { - responder, mockTxMgr, contract, uploader := newTestFaultResponder(t) + responder, mockTxMgr, contract, uploader, _ := newTestFaultResponder(t) uploader.uploadFails = true action := types.Action{ Type: types.ActionTypeStep, @@ -212,16 +236,59 @@ func TestPerformAction(t *testing.T) { require.Nil(t, contract.updateOracleArgs) // mock uploader returns nil require.Equal(t, 1, uploader.updates) }) + + t.Run("stepWithOracleDataAndGlobalPreimageAlreadyExists", func(t *testing.T) { + responder, mockTxMgr, contract, uploader, oracle := newTestFaultResponder(t) + oracle.existsResult = true + action := types.Action{ + Type: types.ActionTypeStep, + ParentIdx: 123, + IsAttack: true, + PreState: []byte{1, 2, 3}, + ProofData: []byte{4, 5, 6}, + OracleData: &types.PreimageOracleData{ + IsLocal: false, + }, + } + err := responder.PerformAction(context.Background(), action) + require.Nil(t, err) + require.Len(t, mockTxMgr.sent, 1) + require.Nil(t, contract.updateOracleArgs) // mock uploader returns nil + require.Equal(t, 0, uploader.updates) + require.Equal(t, 1, oracle.existCalls) + }) + + t.Run("stepWithOracleDataAndGlobalPreimageExistsFails", func(t *testing.T) { + responder, mockTxMgr, contract, uploader, oracle := newTestFaultResponder(t) + oracle.existsFails = true + action := types.Action{ + Type: types.ActionTypeStep, + ParentIdx: 123, + IsAttack: true, + PreState: []byte{1, 2, 3}, + ProofData: []byte{4, 5, 6}, + OracleData: &types.PreimageOracleData{ + IsLocal: false, + }, + } + err := responder.PerformAction(context.Background(), action) + require.ErrorIs(t, err, mockOracleExistsError) + require.Len(t, mockTxMgr.sent, 0) + require.Nil(t, contract.updateOracleArgs) // mock uploader returns nil + require.Equal(t, 0, uploader.updates) + require.Equal(t, 1, oracle.existCalls) + }) } -func newTestFaultResponder(t *testing.T) (*FaultResponder, *mockTxManager, *mockContract, *mockPreimageUploader) { - log := testlog.Logger(t, log.LvlError) +func newTestFaultResponder(t *testing.T) (*FaultResponder, *mockTxManager, *mockContract, *mockPreimageUploader, *mockOracle) { + log := testlog.Logger(t, log.LevelError) mockTxMgr := &mockTxManager{} contract := &mockContract{} uploader := &mockPreimageUploader{} - responder, err := NewFaultResponder(log, mockTxMgr, contract, uploader) + oracle := &mockOracle{} + responder, err := NewFaultResponder(log, mockTxMgr, contract, uploader, oracle) require.NoError(t, err) - return responder, mockTxMgr, contract, uploader + return responder, mockTxMgr, contract, uploader, oracle } type mockPreimageUploader struct { @@ -237,6 +304,20 @@ func (m *mockPreimageUploader) UploadPreimage(ctx context.Context, parent uint64 return nil } +type mockOracle struct { + existCalls int + existsResult bool + existsFails bool +} + +func (m *mockOracle) GlobalDataExists(ctx context.Context, data *types.PreimageOracleData) (bool, error) { + m.existCalls++ + if m.existsFails { + return false, mockOracleExistsError + } + return m.existsResult, nil +} + type mockTxManager struct { from common.Address sends int @@ -244,17 +325,21 @@ type mockTxManager struct { sendFails bool } -func (m *mockTxManager) Send(_ context.Context, candidate txmgr.TxCandidate) (*ethtypes.Receipt, error) { - if m.sendFails { - return nil, mockSendError +func (m *mockTxManager) SendAndWait(_ string, txs ...txmgr.TxCandidate) ([]*ethtypes.Receipt, error) { + rcpts := make([]*ethtypes.Receipt, 0, len(txs)) + for _, tx := range txs { + if m.sendFails { + return nil, mockSendError + } + m.sends++ + m.sent = append(m.sent, tx) + rcpts = append(rcpts, ethtypes.NewReceipt( + []byte{}, + false, + 0, + )) } - m.sends++ - m.sent = append(m.sent, candidate) - return ethtypes.NewReceipt( - []byte{}, - false, - 0, - ), nil + return rcpts, nil } func (m *mockTxManager) BlockNumber(_ context.Context) (uint64, error) { @@ -326,3 +411,11 @@ func (m *mockContract) UpdateOracleTx(_ context.Context, claimIdx uint64, data * func (m *mockContract) GetRequiredBond(_ context.Context, position types.Position) (*big.Int, error) { return big.NewInt(5), nil } + +func (m *mockContract) GetCredit(_ context.Context, _ common.Address) (*big.Int, error) { + return big.NewInt(5), nil +} + +func (m *mockContract) ClaimCredit(_ common.Address) (txmgr.TxCandidate, error) { + return txmgr.TxCandidate{TxData: ([]byte)("claimCredit")}, nil +} diff --git a/op-challenger/game/fault/solver/actors.go b/op-challenger/game/fault/solver/actors.go new file mode 100644 index 000000000000..309569ea6213 --- /dev/null +++ b/op-challenger/game/fault/solver/actors.go @@ -0,0 +1,136 @@ +package solver + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/test" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum/go-ethereum/common" +) + +type actor interface { + Apply(t *testing.T, game types.Game, correctTrace types.TraceProvider) (types.Game, bool) +} + +type actorFn func(t *testing.T, game types.Game, correctTrace types.TraceProvider) (types.Game, bool) + +func (a actorFn) Apply(t *testing.T, game types.Game, correctTrace types.TraceProvider) (types.Game, bool) { + return a(t, game, correctTrace) +} + +type builderFn func(builder *test.GameBuilder) bool + +func (a builderFn) Apply(t *testing.T, game types.Game, correctTrace types.TraceProvider) (types.Game, bool) { + builder := test.NewGameBuilderFromGame(t, correctTrace, game) + done := a(builder) + return builder.Game, done +} + +func combineActors(actors ...actor) actor { + return actorFn(func(t *testing.T, game types.Game, correctTrace types.TraceProvider) (types.Game, bool) { + done := true + for _, actor := range actors { + newGame, actorDone := actor.Apply(t, game, correctTrace) + game = newGame + done = done && actorDone + } + return game, done + }) +} + +var doNothingActor builderFn = func(builder *test.GameBuilder) bool { + return true +} + +var correctAttackLastClaim = respondLastClaim(func(seq *test.GameBuilderSeq) { + seq.Attack() +}) + +var correctDefendLastClaim = respondLastClaim(func(seq *test.GameBuilderSeq) { + if seq.IsRoot() { + // Must attack the root + seq.Attack() + } else { + seq.Defend() + } +}) + +var incorrectAttackLastClaim = respondLastClaim(func(seq *test.GameBuilderSeq) { + seq.Attack(test.WithValue(common.Hash{0xaa})) +}) + +var incorrectDefendLastClaim = respondLastClaim(func(seq *test.GameBuilderSeq) { + if seq.IsRoot() { + // Must attack the root + seq.Attack(test.WithValue(common.Hash{0xdd})) + } else { + seq.Defend(test.WithValue(common.Hash{0xdd})) + } +}) + +var attackEverythingCorrect = respondAllClaims(func(seq *test.GameBuilderSeq) { + seq.Attack() +}) + +var defendEverythingCorrect = respondAllClaims(func(seq *test.GameBuilderSeq) { + if seq.IsRoot() { + // Must attack root + seq.Attack() + } else { + seq.Defend() + } +}) + +var attackEverythingIncorrect = respondAllClaims(func(seq *test.GameBuilderSeq) { + seq.Attack(test.WithValue(common.Hash{0xaa})) +}) + +var defendEverythingIncorrect = respondAllClaims(func(seq *test.GameBuilderSeq) { + if seq.IsRoot() { + // Must attack root + seq.Attack(test.WithValue(common.Hash{0xbb})) + } else { + seq.Defend(test.WithValue(common.Hash{0xbb})) + } +}) + +var exhaustive = respondAllClaims(func(seq *test.GameBuilderSeq) { + seq.Attack() + seq.Attack(test.WithValue(common.Hash{0xaa})) + if !seq.IsRoot() { + seq.Defend() + seq.Defend(test.WithValue(common.Hash{0xdd})) + } +}) + +func respondLastClaim(respond func(seq *test.GameBuilderSeq)) builderFn { + return func(builder *test.GameBuilder) bool { + seq := seqFromLastClaim(builder) + if seq.IsMaxDepth() { + // Can't counter the leaf claim + return true + } + respond(seq) + return false + } +} + +func respondAllClaims(respond func(seq *test.GameBuilderSeq)) builderFn { + return func(builder *test.GameBuilder) bool { + startingCount := len(builder.Game.Claims()) + for _, claim := range builder.Game.Claims() { + if claim.Depth() == builder.Game.MaxDepth() { + continue + } + respond(builder.SeqFrom(claim)) + } + finalCount := len(builder.Game.Claims()) + return finalCount == startingCount + } +} + +func seqFromLastClaim(builder *test.GameBuilder) *test.GameBuilderSeq { + claims := builder.Game.Claims() + claim := claims[len(claims)-1] + return builder.SeqFrom(claim) +} diff --git a/op-challenger/game/fault/solver/game_rules_test.go b/op-challenger/game/fault/solver/game_rules_test.go new file mode 100644 index 000000000000..44eb998ef3c6 --- /dev/null +++ b/op-challenger/game/fault/solver/game_rules_test.go @@ -0,0 +1,91 @@ +package solver + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/resolution" + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/transform" + disputeTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func verifyGameRules(t *testing.T, game types.Game, rootClaimCorrect bool) { + actualResult, claimTree, resolvedGame := gameResult(game) + + verifyExpectedGameResult(t, rootClaimCorrect, actualResult) + + verifyNoChallengerClaimsWereSuccessfullyCountered(t, resolvedGame) + verifyChallengerAlwaysWinsParentBond(t, resolvedGame) + verifyChallengerNeverCountersAClaimTwice(t, claimTree) +} + +// verifyExpectedGameResult verifies that valid output roots are successfully defended and invalid roots are challenged +// Rationale: Ensures the game always and only allows valid output roots to be finalized. +func verifyExpectedGameResult(t *testing.T, rootClaimCorrect bool, actualResult gameTypes.GameStatus) { + expectedResult := gameTypes.GameStatusChallengerWon + if rootClaimCorrect { + expectedResult = gameTypes.GameStatusDefenderWon + } + require.Equalf(t, expectedResult, actualResult, "Game should resolve correctly expected %v but was %v", expectedResult, actualResult) +} + +// verifyNoChallengerClaimsWereSuccessfullyCountered verifies the challenger didn't lose any of its bonds +// Note that this also forbids the challenger losing a bond to itself since it shouldn't challenge its own claims +// Rationale: If honest actors lose their bond, it indicates that incentive compatibility is broken because honest actors +// lose money. +func verifyNoChallengerClaimsWereSuccessfullyCountered(t *testing.T, resolvedGame types.Game) { + for _, claim := range resolvedGame.Claims() { + if claim.Claimant != challengerAddr { + continue + } + if claim.CounteredBy != (common.Address{}) { + t.Fatalf("Challenger posted claim %v but it was countered by someone else:\n%v", claim.ContractIndex, printClaim(claim, resolvedGame)) + } + } +} + +// verifyChallengerAlwaysWinsParentBond verifies that the challenger is always allocated the bond of any parent claim it +// counters. +// Rationale: If an honest action does not win the bond for countering a claim, incentive compatibility is broken because +// honest actors are not being paid to perform their job (or the challenger is posting unnecessary claims) +func verifyChallengerAlwaysWinsParentBond(t *testing.T, resolvedGame types.Game) { + for _, claim := range resolvedGame.Claims() { + if claim.Claimant != challengerAddr { + continue + } + parent, err := resolvedGame.GetParent(claim) + require.NoErrorf(t, err, "Failed to get parent of claim %v", claim.ContractIndex) + require.Equal(t, challengerAddr, parent.CounteredBy, + "Expected claim %v to have challenger as its claimant because of counter claim %v", parent.ContractIndex, claim.ContractIndex) + } +} + +// verifyChallengerNeverCountersAClaimTwice verifies that the challenger never posts more than one counter to a claim +// Rationale: The parent claim bond is only intended to cover costs of a single counter claim so incentive compatibility +// is broken if the challenger needs to post multiple claims. Or if the claim wasn't required, the challenger is just +// wasting money posting unnecessary claims. +func verifyChallengerNeverCountersAClaimTwice(t *testing.T, tree *disputeTypes.BidirectionalTree) { + for _, claim := range tree.Claims { + challengerCounterCount := 0 + for _, child := range claim.Children { + if child.Claim.Claimant != challengerAddr { + continue + } + challengerCounterCount++ + } + require.LessOrEqualf(t, challengerCounterCount, 1, "Found multiple honest counters to claim %v", claim.Claim.ContractIndex) + } +} + +func gameResult(game types.Game) (gameTypes.GameStatus, *disputeTypes.BidirectionalTree, types.Game) { + tree := transform.CreateBidirectionalTree(game.Claims()) + result := resolution.Resolve(tree) + resolvedClaims := make([]types.Claim, 0, len(tree.Claims)) + for _, claim := range tree.Claims { + resolvedClaims = append(resolvedClaims, *claim.Claim) + } + return result, tree, types.NewGameState(resolvedClaims, game.MaxDepth()) +} diff --git a/op-challenger/game/fault/solver/game_solver.go b/op-challenger/game/fault/solver/game_solver.go index 3d5103d4c56b..7c10d005c2e3 100644 --- a/op-challenger/game/fault/solver/game_solver.go +++ b/op-challenger/game/fault/solver/game_solver.go @@ -2,7 +2,6 @@ package solver import ( "context" - "errors" "fmt" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" @@ -28,42 +27,43 @@ func (s *GameSolver) CalculateNextActions(ctx context.Context, game types.Game) if err != nil { return nil, fmt.Errorf("failed to determine if root claim is correct: %w", err) } - var errs []error var actions []types.Action + agreedClaims := newHonestClaimTracker() + if agreeWithRootClaim { + agreedClaims.AddHonestClaim(types.Claim{}, game.Claims()[0]) + } for _, claim := range game.Claims() { var action *types.Action - var err error if claim.Depth() == game.MaxDepth() { - action, err = s.calculateStep(ctx, game, agreeWithRootClaim, claim) + action, err = s.calculateStep(ctx, game, claim, agreedClaims) } else { - action, err = s.calculateMove(ctx, game, agreeWithRootClaim, claim) + action, err = s.calculateMove(ctx, game, claim, agreedClaims) } if err != nil { - errs = append(errs, err) - continue + // Unable to continue iterating claims safely because we may not have tracked the required honest moves + // for this claim which affects the response to later claims. + // Any actions we've already identified are still safe to apply. + return actions, fmt.Errorf("failed to determine response to claim %v: %w", claim.ContractIndex, err) } if action == nil { continue } actions = append(actions, *action) } - return actions, errors.Join(errs...) + return actions, nil } -func (s *GameSolver) calculateStep(ctx context.Context, game types.Game, agreeWithRootClaim bool, claim types.Claim) (*types.Action, error) { +func (s *GameSolver) calculateStep(ctx context.Context, game types.Game, claim types.Claim, agreedClaims *honestClaimTracker) (*types.Action, error) { if claim.CounteredBy != (common.Address{}) { return nil, nil } - if game.AgreeWithClaimLevel(claim, agreeWithRootClaim) { - return nil, nil - } - step, err := s.claimSolver.AttemptStep(ctx, game, claim) - if errors.Is(err, ErrStepIgnoreInvalidPath) { - return nil, nil - } + step, err := s.claimSolver.AttemptStep(ctx, game, claim, agreedClaims) if err != nil { return nil, err } + if step == nil { + return nil, nil + } return &types.Action{ Type: types.ActionTypeStep, ParentIdx: step.LeafClaim.ContractIndex, @@ -75,15 +75,16 @@ func (s *GameSolver) calculateStep(ctx context.Context, game types.Game, agreeWi }, nil } -func (s *GameSolver) calculateMove(ctx context.Context, game types.Game, agreeWithRootClaim bool, claim types.Claim) (*types.Action, error) { - if game.AgreeWithClaimLevel(claim, agreeWithRootClaim) { - return nil, nil - } - move, err := s.claimSolver.NextMove(ctx, claim, game) +func (s *GameSolver) calculateMove(ctx context.Context, game types.Game, claim types.Claim, honestClaims *honestClaimTracker) (*types.Action, error) { + move, err := s.claimSolver.NextMove(ctx, claim, game, honestClaims) if err != nil { return nil, fmt.Errorf("failed to calculate next move for claim index %v: %w", claim.ContractIndex, err) } - if move == nil || game.IsDuplicate(*move) { + if move == nil { + return nil, nil + } + honestClaims.AddHonestClaim(claim, *move) + if game.IsDuplicate(*move) { return nil, nil } return &types.Action{ diff --git a/op-challenger/game/fault/solver/game_solver_test.go b/op-challenger/game/fault/solver/game_solver_test.go index cd7965bd6557..49a808c685db 100644 --- a/op-challenger/game/fault/solver/game_solver_test.go +++ b/op-challenger/game/fault/solver/game_solver_test.go @@ -3,6 +3,7 @@ package solver import ( "context" "encoding/hex" + "fmt" "math/big" "testing" @@ -14,7 +15,7 @@ import ( ) func TestCalculateNextActions(t *testing.T) { - maxDepth := types.Depth(4) + maxDepth := types.Depth(6) startingL2BlockNumber := big.NewInt(0) claimBuilder := faulttest.NewAlphabetClaimBuilder(t, startingL2BlockNumber, maxDepth) @@ -40,30 +41,32 @@ func TestCalculateNextActions(t *testing.T) { name: "DoNotPerformDuplicateMoves", setupGame: func(builder *faulttest.GameBuilder) { // Expected move has already been made. - builder.Seq().AttackCorrect() + builder.Seq().Attack() }, }, { name: "RespondToAllClaimsAtDisagreeingLevel", setupGame: func(builder *faulttest.GameBuilder) { - honestClaim := builder.Seq().AttackCorrect() - honestClaim.AttackCorrect().ExpectDefend() - honestClaim.DefendCorrect().ExpectDefend() - honestClaim.Attack(common.Hash{0xaa}).ExpectAttack() - honestClaim.Attack(common.Hash{0xbb}).ExpectAttack() - honestClaim.Defend(common.Hash{0xcc}).ExpectAttack() - honestClaim.Defend(common.Hash{0xdd}).ExpectAttack() + honestClaim := builder.Seq().Attack() + honestClaim.Attack().ExpectDefend() + honestClaim.Defend().ExpectDefend() + honestClaim.Attack(faulttest.WithValue(common.Hash{0xaa})).ExpectAttack() + honestClaim.Attack(faulttest.WithValue(common.Hash{0xbb})).ExpectAttack() + honestClaim.Defend(faulttest.WithValue(common.Hash{0xcc})).ExpectAttack() + honestClaim.Defend(faulttest.WithValue(common.Hash{0xdd})).ExpectAttack() }, }, { name: "StepAtMaxDepth", setupGame: func(builder *faulttest.GameBuilder) { lastHonestClaim := builder.Seq(). - AttackCorrect(). - AttackCorrect(). - DefendCorrect() - lastHonestClaim.AttackCorrect().ExpectStepDefend() - lastHonestClaim.Attack(common.Hash{0xdd}).ExpectStepAttack() + Attack(). + Attack(). + Defend(). + Defend(). + Defend() + lastHonestClaim.Attack().ExpectStepDefend() + lastHonestClaim.Attack(faulttest.WithValue(common.Hash{0xdd})).ExpectStepAttack() }, }, { @@ -74,14 +77,99 @@ func TestCalculateNextActions(t *testing.T) { // Dishonest actor counters their own claims to set up a situation with an invalid prestate // The honest actor should ignore path created by the dishonest actor, only supporting its own attack on the root claim - honestMove := builder.Seq().AttackCorrect() // This expected action is the winning move. - dishonestMove := honestMove.Attack(maliciousStateHash) + honestMove := builder.Seq().Attack() // This expected action is the winning move. + dishonestMove := honestMove.Attack(faulttest.WithValue(maliciousStateHash)) // The expected action by the honest actor dishonestMove.ExpectAttack() // The honest actor will ignore this poisoned path dishonestMove. - Defend(maliciousStateHash). - Attack(maliciousStateHash) + Defend(faulttest.WithValue(maliciousStateHash)). + Attack(faulttest.WithValue(maliciousStateHash)) + }, + }, + { + name: "Freeloader-ValidClaimAtInvalidAttackPosition", + setupGame: func(builder *faulttest.GameBuilder) { + builder.Seq(). + Attack(). // Honest response to invalid root + Defend().ExpectDefend(). // Defender agrees at this point, we should defend + Attack().ExpectDefend() // Freeloader attacks instead of defends + }, + }, + { + name: "Freeloader-InvalidClaimAtInvalidAttackPosition", + setupGame: func(builder *faulttest.GameBuilder) { + builder.Seq(). + Attack(). // Honest response to invalid root + Defend().ExpectDefend(). // Defender agrees at this point, we should defend + Attack(faulttest.WithValue(common.Hash{0xbb})).ExpectAttack() // Freeloader attacks with wrong claim instead of defends + }, + }, + { + name: "Freeloader-InvalidClaimAtValidDefensePosition", + setupGame: func(builder *faulttest.GameBuilder) { + builder.Seq(). + Attack(). // Honest response to invalid root + Defend().ExpectDefend(). // Defender agrees at this point, we should defend + Defend(faulttest.WithValue(common.Hash{0xbb})).ExpectAttack() // Freeloader defends with wrong claim, we should attack + }, + }, + { + name: "Freeloader-InvalidClaimAtValidAttackPosition", + setupGame: func(builder *faulttest.GameBuilder) { + builder.Seq(). + Attack(). // Honest response to invalid root + Defend(faulttest.WithValue(common.Hash{0xaa})).ExpectAttack(). // Defender disagrees at this point, we should attack + Attack(faulttest.WithValue(common.Hash{0xbb})).ExpectAttack() // Freeloader attacks with wrong claim instead of defends + }, + }, + { + name: "Freeloader-InvalidClaimAtInvalidDefensePosition", + setupGame: func(builder *faulttest.GameBuilder) { + builder.Seq(). + Attack(). // Honest response to invalid root + Defend(faulttest.WithValue(common.Hash{0xaa})).ExpectAttack(). // Defender disagrees at this point, we should attack + Defend(faulttest.WithValue(common.Hash{0xbb})) // Freeloader defends with wrong claim but we must not respond to avoid poisoning + }, + }, + { + name: "Freeloader-ValidClaimAtInvalidAttackPosition-RespondingToDishonestButCorrectAttack", + setupGame: func(builder *faulttest.GameBuilder) { + builder.Seq(). + Attack(). // Honest response to invalid root + Attack().ExpectDefend(). // Defender attacks with correct value, we should defend + Attack().ExpectDefend() // Freeloader attacks with wrong claim, we should defend + }, + }, + { + name: "Freeloader-DoNotCounterOwnClaim", + setupGame: func(builder *faulttest.GameBuilder) { + builder.Seq(). + Attack(). // Honest response to invalid root + Attack().ExpectDefend(). // Defender attacks with correct value, we should defend + Attack(). // Freeloader attacks instead, we should defend + Defend() // We do defend and we shouldn't counter our own claim + }, + }, + { + name: "Freeloader-ContinueDefendingAgainstFreeloader", + setupGame: func(builder *faulttest.GameBuilder) { + builder.Seq(). // invalid root + Attack(). // Honest response to invalid root + Attack().ExpectDefend(). // Defender attacks with correct value, we should defend + Attack(). // Freeloader attacks instead, we should defend + Defend(). // We do defend + Attack(faulttest.WithValue(common.Hash{0xaa})). // freeloader attacks our defense, we should attack + ExpectAttack() + }, + }, + { + name: "Freeloader-FreeloaderCountersRootClaim", + setupGame: func(builder *faulttest.GameBuilder) { + builder.Seq(). + ExpectAttack(). // Honest response to invalid root + Attack(faulttest.WithValue(common.Hash{0xaa})). // freeloader + ExpectAttack() // Honest response to freeloader }, }, } @@ -89,29 +177,161 @@ func TestCalculateNextActions(t *testing.T) { for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { - builder := claimBuilder.GameBuilder(test.rootClaimCorrect) + builder := claimBuilder.GameBuilder(faulttest.WithInvalidValue(!test.rootClaimCorrect)) test.setupGame(builder) game := builder.Game - for i, claim := range game.Claims() { - t.Logf("Claim %v: Pos: %v TraceIdx: %v ParentIdx: %v, CounteredBy: %v, Value: %v", - i, claim.Position.ToGIndex(), claim.Position.TraceIndex(maxDepth), claim.ParentContractIndex, claim.CounteredBy, claim.Value) - } solver := NewGameSolver(maxDepth, trace.NewSimpleTraceAccessor(claimBuilder.CorrectTraceProvider())) - actions, err := solver.CalculateNextActions(context.Background(), game) - require.NoError(t, err) - for i, action := range actions { - t.Logf("Move %v: Type: %v, ParentIdx: %v, Attack: %v, Value: %v, PreState: %v, ProofData: %v", - i, action.Type, action.ParentIdx, action.IsAttack, action.Value, hex.EncodeToString(action.PreState), hex.EncodeToString(action.ProofData)) - // Check that every move the solver returns meets the generic validation rules - require.NoError(t, checkRules(game, action), "Attempting to perform invalid action") - } + postState, actions := runStep(t, solver, game, claimBuilder.CorrectTraceProvider()) for i, action := range builder.ExpectedActions { t.Logf("Expect %v: Type: %v, ParentIdx: %v, Attack: %v, Value: %v, PreState: %v, ProofData: %v", i, action.Type, action.ParentIdx, action.IsAttack, action.Value, hex.EncodeToString(action.PreState), hex.EncodeToString(action.ProofData)) require.Containsf(t, actions, action, "Expected claim %v missing", i) } require.Len(t, actions, len(builder.ExpectedActions), "Incorrect number of actions") + + verifyGameRules(t, postState, test.rootClaimCorrect) }) } } + +func runStep(t *testing.T, solver *GameSolver, game types.Game, correctTraceProvider types.TraceProvider) (types.Game, []types.Action) { + actions, err := solver.CalculateNextActions(context.Background(), game) + require.NoError(t, err) + + postState := applyActions(game, challengerAddr, actions) + + for i, action := range actions { + t.Logf("Move %v: Type: %v, ParentIdx: %v, Attack: %v, Value: %v, PreState: %v, ProofData: %v", + i, action.Type, action.ParentIdx, action.IsAttack, action.Value, hex.EncodeToString(action.PreState), hex.EncodeToString(action.ProofData)) + // Check that every move the solver returns meets the generic validation rules + require.NoError(t, checkRules(game, action, correctTraceProvider), "Attempting to perform invalid action") + } + return postState, actions +} + +func TestMultipleRounds(t *testing.T) { + t.Parallel() + tests := []struct { + name string + actor actor + }{ + { + name: "SingleRoot", + actor: doNothingActor, + }, + { + name: "LinearAttackCorrect", + actor: correctAttackLastClaim, + }, + { + name: "LinearDefendCorrect", + actor: correctDefendLastClaim, + }, + { + name: "LinearAttackIncorrect", + actor: incorrectAttackLastClaim, + }, + { + name: "LinearDefendInorrect", + actor: incorrectDefendLastClaim, + }, + { + name: "LinearDefendIncorrectDefendCorrect", + actor: combineActors(incorrectDefendLastClaim, correctDefendLastClaim), + }, + { + name: "LinearAttackIncorrectDefendCorrect", + actor: combineActors(incorrectAttackLastClaim, correctDefendLastClaim), + }, + { + name: "LinearDefendIncorrectDefendIncorrect", + actor: combineActors(incorrectDefendLastClaim, incorrectDefendLastClaim), + }, + { + name: "LinearAttackIncorrectDefendIncorrect", + actor: combineActors(incorrectAttackLastClaim, incorrectDefendLastClaim), + }, + { + name: "AttackEverythingCorrect", + actor: attackEverythingCorrect, + }, + { + name: "DefendEverythingCorrect", + actor: defendEverythingCorrect, + }, + { + name: "AttackEverythingIncorrect", + actor: attackEverythingIncorrect, + }, + { + name: "DefendEverythingIncorrect", + actor: defendEverythingIncorrect, + }, + { + name: "Exhaustive", + actor: exhaustive, + }, + } + for _, test := range tests { + test := test + for _, rootClaimCorrect := range []bool{true, false} { + rootClaimCorrect := rootClaimCorrect + t.Run(fmt.Sprintf("%v-%v", test.name, rootClaimCorrect), func(t *testing.T) { + t.Parallel() + + maxDepth := types.Depth(6) + startingL2BlockNumber := big.NewInt(50) + claimBuilder := faulttest.NewAlphabetClaimBuilder(t, startingL2BlockNumber, maxDepth) + builder := claimBuilder.GameBuilder(faulttest.WithInvalidValue(!rootClaimCorrect)) + game := builder.Game + + correctTrace := claimBuilder.CorrectTraceProvider() + solver := NewGameSolver(maxDepth, trace.NewSimpleTraceAccessor(correctTrace)) + + roundNum := 0 + done := false + for !done { + t.Logf("------ ROUND %v ------", roundNum) + game, _ = runStep(t, solver, game, correctTrace) + verifyGameRules(t, game, rootClaimCorrect) + + game, done = test.actor.Apply(t, game, correctTrace) + roundNum++ + } + }) + } + } +} + +func applyActions(game types.Game, claimant common.Address, actions []types.Action) types.Game { + claims := game.Claims() + for _, action := range actions { + switch action.Type { + case types.ActionTypeMove: + newPosition := action.ParentPosition.Attack() + if !action.IsAttack { + newPosition = action.ParentPosition.Defend() + } + claim := types.Claim{ + ClaimData: types.ClaimData{ + Value: action.Value, + Bond: big.NewInt(0), + Position: newPosition, + }, + Claimant: claimant, + Clock: nil, + ContractIndex: len(claims), + ParentContractIndex: action.ParentIdx, + } + claims = append(claims, claim) + case types.ActionTypeStep: + counteredClaim := claims[action.ParentIdx] + counteredClaim.CounteredBy = claimant + claims[action.ParentIdx] = counteredClaim + default: + panic(fmt.Errorf("unknown move type: %v", action.Type)) + } + } + return types.NewGameState(claims, game.MaxDepth()) +} diff --git a/op-challenger/game/fault/solver/honest_claims.go b/op-challenger/game/fault/solver/honest_claims.go new file mode 100644 index 000000000000..e340815a64b1 --- /dev/null +++ b/op-challenger/game/fault/solver/honest_claims.go @@ -0,0 +1,36 @@ +package solver + +import "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + +type honestClaimTracker struct { + // agreed tracks the existing claims in the game that the honest actor would make + // The claims may not yet have been made so are tracked by ClaimID not ContractIndex + agreed map[types.ClaimID]bool + + // counters tracks the counter claim for a claim by contract index. + // The counter claim may not yet be part of the game state (ie it may be a move the honest actor is planning to make) + counters map[types.ClaimID]types.Claim +} + +func newHonestClaimTracker() *honestClaimTracker { + return &honestClaimTracker{ + agreed: make(map[types.ClaimID]bool), + counters: make(map[types.ClaimID]types.Claim), + } +} + +func (a *honestClaimTracker) AddHonestClaim(parent types.Claim, claim types.Claim) { + a.agreed[claim.ID()] = true + if parent != (types.Claim{}) { + a.counters[parent.ID()] = claim + } +} + +func (a *honestClaimTracker) IsHonest(claim types.Claim) bool { + return a.agreed[claim.ID()] +} + +func (a *honestClaimTracker) HonestCounter(parent types.Claim) (types.Claim, bool) { + counter, ok := a.counters[parent.ID()] + return counter, ok +} diff --git a/op-challenger/game/fault/solver/honest_claims_test.go b/op-challenger/game/fault/solver/honest_claims_test.go new file mode 100644 index 000000000000..7b06e2635659 --- /dev/null +++ b/op-challenger/game/fault/solver/honest_claims_test.go @@ -0,0 +1,38 @@ +package solver + +import ( + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/test" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/stretchr/testify/require" +) + +func TestHonestClaimTracker_RootClaim(t *testing.T) { + tracker := newHonestClaimTracker() + builder := test.NewAlphabetClaimBuilder(t, big.NewInt(3), 4) + + claim := builder.Seq().Get() + require.False(t, tracker.IsHonest(claim)) + + tracker.AddHonestClaim(types.Claim{}, claim) + require.True(t, tracker.IsHonest(claim)) +} + +func TestHonestClaimTracker_ChildClaim(t *testing.T) { + tracker := newHonestClaimTracker() + builder := test.NewAlphabetClaimBuilder(t, big.NewInt(3), 4) + + seq := builder.Seq().Attack().Defend() + parent := seq.Get() + child := seq.Attack().Get() + require.Zero(t, child.ContractIndex, "should work for claims that are not in the game state yet") + + tracker.AddHonestClaim(parent, child) + require.False(t, tracker.IsHonest(parent)) + require.True(t, tracker.IsHonest(child)) + counter, ok := tracker.HonestCounter(parent) + require.True(t, ok) + require.Equal(t, child, counter) +} diff --git a/op-challenger/game/fault/solver/rules.go b/op-challenger/game/fault/solver/rules.go index 888da89a318d..5a77ca5869a5 100644 --- a/op-challenger/game/fault/solver/rules.go +++ b/op-challenger/game/fault/solver/rules.go @@ -1,38 +1,60 @@ package solver import ( + "bytes" + "context" "errors" "fmt" + "math/big" + "slices" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" ) -type actionRule func(game types.Game, action types.Action) error +var challengerAddr = common.Address(bytes.Repeat([]byte{0xaa}, 20)) + +type actionRule func(game types.Game, action types.Action, correctTrace types.TraceProvider) error var rules = []actionRule{ parentMustExist, onlyStepAtMaxDepth, onlyMoveBeforeMaxDepth, doNotDuplicateExistingMoves, + doNotStepAlreadyCounteredClaims, doNotDefendRootClaim, + avoidPoisonedPrestate, + detectPoisonedStepPrestate, + detectFailedStep, + doNotCounterSelf, +} + +func printClaim(claim types.Claim, game types.Game) string { + return fmt.Sprintf("Claim %v: Pos: %v TraceIdx: %v Depth: %v IndexAtDepth: %v ParentIdx: %v Value: %v Claimant: %v CounteredBy: %v", + claim.ContractIndex, claim.Position.ToGIndex(), claim.Position.TraceIndex(game.MaxDepth()), claim.Position.Depth(), claim.Position.IndexAtDepth(), claim.ParentContractIndex, claim.Value, claim.Claimant, claim.CounteredBy) } -func checkRules(game types.Game, action types.Action) error { +func checkRules(game types.Game, action types.Action, correctTrace types.TraceProvider) error { var errs []error for _, rule := range rules { - errs = append(errs, rule(game, action)) + errs = append(errs, rule(game, action, correctTrace)) } return errors.Join(errs...) } -func parentMustExist(game types.Game, action types.Action) error { +// parentMustExist checks that every action performed has a valid parent claim +// Rationale: The action would be rejected by the contracts +func parentMustExist(game types.Game, action types.Action, _ types.TraceProvider) error { if len(game.Claims()) <= action.ParentIdx || action.ParentIdx < 0 { return fmt.Errorf("parent claim %v does not exist in game with %v claims", action.ParentIdx, len(game.Claims())) } return nil } -func onlyStepAtMaxDepth(game types.Game, action types.Action) error { +// onlyStepAtMaxDepth verifies that step actions are only performed against leaf claims +// Rationale: The action would be rejected by the contracts +func onlyStepAtMaxDepth(game types.Game, action types.Action, _ types.TraceProvider) error { if action.Type == types.ActionTypeStep { return nil } @@ -44,7 +66,9 @@ func onlyStepAtMaxDepth(game types.Game, action types.Action) error { return nil } -func onlyMoveBeforeMaxDepth(game types.Game, action types.Action) error { +// onlyMoveBeforeMaxDepth verifies that move actions are not performed against leaf claims +// Rationale: The action would be rejected by the contracts +func onlyMoveBeforeMaxDepth(game types.Game, action types.Action, _ types.TraceProvider) error { if action.Type == types.ActionTypeMove { return nil } @@ -56,7 +80,9 @@ func onlyMoveBeforeMaxDepth(game types.Game, action types.Action) error { return nil } -func doNotDuplicateExistingMoves(game types.Game, action types.Action) error { +// doNotDuplicateExistingMoves verifies that the challenger doesn't attempt to post a duplicate claim +// Rationale: The action would be rejected by the contracts +func doNotDuplicateExistingMoves(game types.Game, action types.Action, _ types.TraceProvider) error { newClaimData := types.ClaimData{ Value: action.Value, Position: resultingPosition(game, action), @@ -67,13 +93,180 @@ func doNotDuplicateExistingMoves(game types.Game, action types.Action) error { return nil } -func doNotDefendRootClaim(game types.Game, action types.Action) error { +// doNotStepAlreadyCounteredClaims checks the challenger does not attempt to call step on already countered claims +// Rationale: The step call is redundant and a waste of gas +func doNotStepAlreadyCounteredClaims(game types.Game, action types.Action, _ types.TraceProvider) error { + claim := game.Claims()[action.ParentIdx] + if claim.CounteredBy != (common.Address{}) { + return fmt.Errorf("attempting to step already countered claim: %v", claim.ContractIndex) + } + return nil +} + +// doNotDefendRootClaim checks the challenger doesn't attempt to defend the root claim +// Rationale: The action would be rejected by the contracts +func doNotDefendRootClaim(game types.Game, action types.Action, _ types.TraceProvider) error { if game.Claims()[action.ParentIdx].IsRootPosition() && !action.IsAttack { return fmt.Errorf("defending the root claim at idx %v", action.ParentIdx) } return nil } +// doNotCounterSelf checks the challenger doesn't counter its own claims +// Rationale: The challenger should not disagree with itself +func doNotCounterSelf(game types.Game, action types.Action, _ types.TraceProvider) error { + claim := game.Claims()[action.ParentIdx] + if claim.Claimant == challengerAddr { + return fmt.Errorf("countering own claim at idx %v", action.ParentIdx) + } + return nil +} + +// avoidPoisonedPrestate checks the challenger does not perform a move that results in a claim where the ancestor +// with the largest trace index less than the new claim's trace index is invalid. +// Rationale: If such a claim were posted, an attacker could attack with invalid values down to max depth and setup a +// step call which uses the invalid claim as the pre-state. The challenger could not call step because it does not have +// the preimage of the invalid state. If the attacker should call step, they could provide a carefully crafted state +// that allows it to successfully step against the challenger's claim. +func avoidPoisonedPrestate(game types.Game, action types.Action, correctTrace types.TraceProvider) error { + if action.Type == types.ActionTypeStep { + return nil + } + ancestors := "" + movePosition := resultingPosition(game, action) + honestTraceIndex := movePosition.TraceIndex(game.MaxDepth()) + // Walk back up the claims and find the claim with highest trace index < honestTraceIndex + claim := game.Claims()[action.ParentIdx] + var preStateClaim types.Claim + for { + ancestors += printClaim(claim, game) + "\n" + claimTraceIdx := claim.TraceIndex(game.MaxDepth()) + if claimTraceIdx.Cmp(honestTraceIndex) < 0 { // Check it's left of the honest claim + if preStateClaim == (types.Claim{}) || claimTraceIdx.Cmp(preStateClaim.TraceIndex(game.MaxDepth())) > 0 { + preStateClaim = claim + } + } + if claim.IsRoot() { + break + } + parent, err := game.GetParent(claim) + if err != nil { + return fmt.Errorf("no parent of claim %v: %w", claim.ContractIndex, err) + } + claim = parent + } + if preStateClaim == (types.Claim{}) { + // No claim to the left of the honest claim, so can't have been poisoned + return nil + } + correctValue, err := correctTrace.Get(context.Background(), preStateClaim.Position) + if err != nil { + return fmt.Errorf("failed to get correct trace at position %v: %w", preStateClaim.Position, err) + } + if correctValue != preStateClaim.Value { + err = fmt.Errorf("prestate poisoned claim %v has invalid prestate and is left of honest claim countering %v at trace index %v", preStateClaim.ContractIndex, action.ParentIdx, honestTraceIndex) + return err + } + return nil +} + +// detectFailedStep checks that step actions will succeed. +// Rationale: The action would be rejected by the contracts +// +// INVARIANT: If a step is an attack, the poststate is valid if the step produces +// +// the same poststate hash as the parent claim's value. +// If a step is a defense: +// 1. If the parent claim and the found post state agree with each other +// (depth diff % 2 == 0), the step is valid if it produces the same +// state hash as the post state's claim. +// 2. If the parent claim and the found post state disagree with each other +// (depth diff % 2 != 0), the parent cannot be countered unless the step +// produces the same state hash as `postState.claim`. +func detectFailedStep(game types.Game, action types.Action, correctTrace types.TraceProvider) error { + if action.Type != types.ActionTypeStep { + // An invalid post state is not an issue if we are moving, only if the honest challenger has to call step. + return nil + } + position := resultingPosition(game, action) + if position.Depth() != game.MaxDepth() { + // Not at max depth yet + return nil + } + honestTraceIndex := position.TraceIndex(game.MaxDepth()) + poststateIndex := honestTraceIndex + if !action.IsAttack { + poststateIndex = new(big.Int).Add(honestTraceIndex, big.NewInt(1)) + } + // Walk back up the claims and find the claim required post state index + claim := game.Claims()[action.ParentIdx] + poststateClaim, ok := game.AncestorWithTraceIndex(claim, poststateIndex) + if !ok { + return fmt.Errorf("did not find required poststate at %v to counter claim %v", poststateIndex, action.ParentIdx) + } + correctValue, err := correctTrace.Get(context.Background(), poststateClaim.Position) + if err != nil { + return fmt.Errorf("failed to get correct trace at position %v: %w", poststateClaim.Position, err) + } + validStep := correctValue == poststateClaim.Value + parentPostAgree := (claim.Depth()-poststateClaim.Depth())%2 == 0 + if parentPostAgree == validStep { + return fmt.Errorf("failed step against claim at %v using poststate from claim %v post state is correct? %v parentPostAgree? %v", + action.ParentIdx, poststateClaim.ContractIndex, validStep, parentPostAgree) + } + return nil +} + +// detectPoisonedStepPrestate checks that: +// 1. step actions performed by the challenger always have a valid prestate +// 2. move actions that create a claim a max depth would have a valid prestate if they are attacked +// 3. the actual prestate provided matches the prestate claim's commitment +// Rationale: A step against an invalid prestate will fail because the preimage of the prestate claim is unknown +// and claims at max depth with an invalid prestate could be stepped against because the prestate is invalid so a VM +// step will not result in the correct post-state. +func detectPoisonedStepPrestate(game types.Game, action types.Action, correctTrace types.TraceProvider) error { + position := resultingPosition(game, action) + if position.Depth() != game.MaxDepth() { + // Not at max depth yet + return nil + } + honestTraceIndex := position.TraceIndex(game.MaxDepth()) + prestateIndex := honestTraceIndex + // If we're performing a move to post a leaf claim, assume the attacker will try to attack it from their + // poisoned prestate + if action.IsAttack || action.Type == types.ActionTypeMove { + prestateIndex = new(big.Int).Sub(prestateIndex, big.NewInt(1)) + } + if prestateIndex.Cmp(big.NewInt(0)) < 0 { + // Absolute prestate is not poisoned + return nil + } + // Walk back up the claims and find the claim with highest trace index < honestTraceIndex + claim := game.Claims()[action.ParentIdx] + preStateClaim, ok := game.AncestorWithTraceIndex(claim, prestateIndex) + if !ok { + return fmt.Errorf("performing step against claim %v with no prestate available at %v", claim.ContractIndex, prestateIndex) + } + correctValue, err := correctTrace.Get(context.Background(), preStateClaim.Position) + if err != nil { + return fmt.Errorf("failed to get correct trace at position %v: %w", preStateClaim.Position, err) + } + if correctValue != preStateClaim.Value { + if action.Type == types.ActionTypeStep { + return fmt.Errorf("stepping from poisoned prestate at claim %v when countering %v", preStateClaim.ContractIndex, action.ParentIdx) + } else { + return fmt.Errorf("posting leaf claim with poisoned prestate from claim %v when countering %v", preStateClaim.ContractIndex, action.ParentIdx) + } + } + if action.Type == types.ActionTypeStep { + prestateHash := crypto.Keccak256Hash(action.PreState) + if !slices.Equal(prestateHash[1:], preStateClaim.Value[1:]) { + return fmt.Errorf("prestate hash %v does not match expected prestate claim %v from claim %v", prestateHash, preStateClaim.Value, preStateClaim.ContractIndex) + } + } + return nil +} + func resultingPosition(game types.Game, action types.Action) types.Position { parentPos := game.Claims()[action.ParentIdx].Position if action.Type == types.ActionTypeStep { diff --git a/op-challenger/game/fault/solver/solver.go b/op-challenger/game/fault/solver/solver.go index e622c946b8bc..4292754c23e4 100644 --- a/op-challenger/game/fault/solver/solver.go +++ b/op-challenger/game/fault/solver/solver.go @@ -10,9 +10,7 @@ import ( ) var ( - ErrStepNonLeafNode = errors.New("cannot step on non-leaf claims") - ErrStepAgreedClaim = errors.New("cannot step on claims we agree with") - ErrStepIgnoreInvalidPath = errors.New("cannot step on claims that dispute invalid paths") + ErrStepNonLeafNode = errors.New("cannot step on non-leaf claims") ) // claimSolver uses a [TraceProvider] to determine the moves to make in a dispute game. @@ -29,34 +27,54 @@ func newClaimSolver(gameDepth types.Depth, trace types.TraceAccessor) *claimSolv } } +func (s *claimSolver) shouldCounter(game types.Game, claim types.Claim, honestClaims *honestClaimTracker) (bool, error) { + // Do not counter honest claims + if honestClaims.IsHonest(claim) { + return false, nil + } + + if claim.IsRoot() { + // Always counter the root claim if it is not honest + return true, nil + } + + parent, err := game.GetParent(claim) + if err != nil { + return false, fmt.Errorf("no parent for claim %v: %w", claim.ContractIndex, err) + } + + // Counter all claims that are countering an honest claim + if honestClaims.IsHonest(parent) { + return true, nil + } + + counter, hasCounter := honestClaims.HonestCounter(parent) + // Do not respond to any claim countering a claim the honest actor ignored + if !hasCounter { + return false, nil + } + + // Do not counter sibling to an honest claim that are right of the honest claim. + honestIdx := counter.TraceIndex(game.MaxDepth()) + claimIdx := claim.TraceIndex(game.MaxDepth()) + return claimIdx.Cmp(honestIdx) <= 0, nil +} + // NextMove returns the next move to make given the current state of the game. -func (s *claimSolver) NextMove(ctx context.Context, claim types.Claim, game types.Game) (*types.Claim, error) { +func (s *claimSolver) NextMove(ctx context.Context, claim types.Claim, game types.Game, honestClaims *honestClaimTracker) (*types.Claim, error) { if claim.Depth() == s.gameDepth { return nil, types.ErrGameDepthReached } - // Before challenging this claim, first check that the move wasn't warranted. - // If the parent claim is on a dishonest path, then we would have moved against it anyways. So we don't move. - // Avoiding dishonest paths ensures that there's always a valid claim available to support ours during step. - if !claim.IsRoot() { - parent, err := game.GetParent(claim) - if err != nil { - return nil, err - } - agreeWithParent, err := s.agreeWithClaimPath(ctx, game, parent) - if err != nil { - return nil, err - } - if !agreeWithParent { - return nil, nil - } - } - - agree, err := s.agreeWithClaim(ctx, game, claim) - if err != nil { - return nil, err + if counter, err := s.shouldCounter(game, claim, honestClaims); err != nil { + return nil, fmt.Errorf("failed to determine if claim should be countered: %w", err) + } else if !counter { + return nil, nil } - if agree { + + if agree, err := s.agreeWithClaim(ctx, game, claim); err != nil { + return nil, err + } else if agree { return s.defend(ctx, game, claim) } else { return s.attack(ctx, game, claim) @@ -71,30 +89,23 @@ type StepData struct { OracleData *types.PreimageOracleData } -// AttemptStep determines what step should occur for a given leaf claim. +// AttemptStep determines what step, if any, should occur for a given leaf claim. // An error will be returned if the claim is not at the max depth. -// Returns ErrStepIgnoreInvalidPath if the claim disputes an invalid path -func (s *claimSolver) AttemptStep(ctx context.Context, game types.Game, claim types.Claim) (StepData, error) { +// Returns nil, nil if no step should be performed. +func (s *claimSolver) AttemptStep(ctx context.Context, game types.Game, claim types.Claim, honestClaims *honestClaimTracker) (*StepData, error) { if claim.Depth() != s.gameDepth { - return StepData{}, ErrStepNonLeafNode + return nil, ErrStepNonLeafNode } - // Step only on claims that dispute a valid path - parent, err := game.GetParent(claim) - if err != nil { - return StepData{}, err - } - parentValid, err := s.agreeWithClaimPath(ctx, game, parent) - if err != nil { - return StepData{}, err - } - if !parentValid { - return StepData{}, ErrStepIgnoreInvalidPath + if counter, err := s.shouldCounter(game, claim, honestClaims); err != nil { + return nil, fmt.Errorf("failed to determine if claim should be countered: %w", err) + } else if !counter { + return nil, nil } claimCorrect, err := s.agreeWithClaim(ctx, game, claim) if err != nil { - return StepData{}, err + return nil, err } var position types.Position @@ -109,10 +120,10 @@ func (s *claimSolver) AttemptStep(ctx context.Context, game types.Game, claim ty preState, proofData, oracleData, err := s.trace.GetStepData(ctx, game, claim, position) if err != nil { - return StepData{}, err + return nil, err } - return StepData{ + return &StepData{ LeafClaim: claim, IsAttack: !claimCorrect, PreState: preState, @@ -155,29 +166,3 @@ func (s *claimSolver) agreeWithClaim(ctx context.Context, game types.Game, claim ourValue, err := s.trace.Get(ctx, game, claim, claim.Position) return bytes.Equal(ourValue[:], claim.Value[:]), err } - -// agreeWithClaimPath returns true if the every other claim in the path to root is correct according to the internal [TraceProvider]. -func (s *claimSolver) agreeWithClaimPath(ctx context.Context, game types.Game, claim types.Claim) (bool, error) { - agree, err := s.agreeWithClaim(ctx, game, claim) - if err != nil { - return false, err - } - if !agree { - return false, nil - } - if claim.IsRoot() { - return true, nil - } - parent, err := game.GetParent(claim) - if err != nil { - return false, fmt.Errorf("failed to get parent of claim %v: %w", claim.ContractIndex, err) - } - if parent.IsRoot() { - return true, nil - } - grandParent, err := game.GetParent(parent) - if err != nil { - return false, err - } - return s.agreeWithClaimPath(ctx, game, grandParent) -} diff --git a/op-challenger/game/fault/solver/solver_test.go b/op-challenger/game/fault/solver/solver_test.go index 60a22d5595df..96755b843634 100644 --- a/op-challenger/game/fault/solver/solver_test.go +++ b/op-challenger/game/fault/solver/solver_test.go @@ -27,6 +27,7 @@ func TestAttemptStep(t *testing.T) { name string agreeWithOutputRoot bool expectedErr error + expectNoStep bool expectAttack bool expectPreState []byte expectProofData []byte @@ -41,9 +42,9 @@ func TestAttemptStep(t *testing.T) { expectedOracleData: claimBuilder.CorrectOracleData(common.Big0), setupGame: func(builder *faulttest.GameBuilder) { builder.Seq(). - Attack(common.Hash{0xaa}). - AttackCorrect(). - Attack(common.Hash{0xbb}) + Attack(faulttest.WithValue(common.Hash{0xaa})). + Attack(). + Attack(faulttest.WithValue(common.Hash{0xbb})) }, }, { @@ -54,9 +55,9 @@ func TestAttemptStep(t *testing.T) { expectedOracleData: claimBuilder.CorrectOracleData(big.NewInt(1)), setupGame: func(builder *faulttest.GameBuilder) { builder.Seq(). - Attack(common.Hash{0xaa}). - AttackCorrect(). - AttackCorrect() + Attack(faulttest.WithValue(common.Hash{0xaa})). + Attack(). + Attack() }, }, { @@ -67,9 +68,9 @@ func TestAttemptStep(t *testing.T) { expectedOracleData: claimBuilder.CorrectOracleData(big.NewInt(4)), setupGame: func(builder *faulttest.GameBuilder) { builder.Seq(). - AttackCorrect(). - DefendCorrect(). - Attack(common.Hash{0xaa}) + Attack(). + Defend(). + Attack(faulttest.WithValue(common.Hash{0xaa})) }, }, { @@ -80,9 +81,9 @@ func TestAttemptStep(t *testing.T) { expectedOracleData: claimBuilder.CorrectOracleData(big.NewInt(5)), setupGame: func(builder *faulttest.GameBuilder) { builder.Seq(). - AttackCorrect(). - DefendCorrect(). - AttackCorrect() + Attack(). + Defend(). + Attack() }, }, { @@ -93,9 +94,9 @@ func TestAttemptStep(t *testing.T) { expectedOracleData: claimBuilder.CorrectOracleData(lastLeafTraceIndex), setupGame: func(builder *faulttest.GameBuilder) { builder.Seq(). - AttackCorrect(). - DefendCorrect(). - Defend(common.Hash{0xaa}) + Attack(). + Defend(). + Defend(faulttest.WithValue(common.Hash{0xaa})) }, }, { @@ -106,15 +107,15 @@ func TestAttemptStep(t *testing.T) { expectedOracleData: claimBuilder.CorrectOracleData(lastLeafTraceIndexPlusOne), setupGame: func(builder *faulttest.GameBuilder) { builder.Seq(). - AttackCorrect(). - DefendCorrect(). - DefendCorrect() + Attack(). + Defend(). + Defend() }, }, { name: "CannotStepNonLeaf", setupGame: func(builder *faulttest.GameBuilder) { - builder.Seq().AttackCorrect().AttackCorrect() + builder.Seq().Attack().Attack() }, expectedErr: ErrStepNonLeafNode, agreeWithOutputRoot: true, @@ -123,22 +124,22 @@ func TestAttemptStep(t *testing.T) { name: "CannotStepAgreedNode", setupGame: func(builder *faulttest.GameBuilder) { builder.Seq(). - AttackCorrect(). - Attack(common.Hash{0xaa}). - AttackCorrect() + Attack(). + Attack(faulttest.WithValue(common.Hash{0xaa})). + Attack() }, - expectedErr: ErrStepIgnoreInvalidPath, + expectNoStep: true, agreeWithOutputRoot: true, }, { name: "CannotStepInvalidPath", setupGame: func(builder *faulttest.GameBuilder) { builder.Seq(). - Attack(common.Hash{0xaa}). - Attack(common.Hash{0xbb}). - Attack(common.Hash{0xcc}) + Attack(faulttest.WithValue(common.Hash{0xaa})). + Attack(faulttest.WithValue(common.Hash{0xbb})). + Attack(faulttest.WithValue(common.Hash{0xcc})) }, - expectedErr: ErrStepIgnoreInvalidPath, + expectNoStep: true, agreeWithOutputRoot: true, }, { @@ -149,11 +150,11 @@ func TestAttemptStep(t *testing.T) { expectedOracleData: claimBuilder.CorrectOracleData(big.NewInt(4)), setupGame: func(builder *faulttest.GameBuilder) { builder.Seq(). - AttackCorrect(). - DefendCorrect(). - DefendCorrect() + Attack(). + Defend(). + Defend() }, - expectedErr: ErrStepIgnoreInvalidPath, + expectNoStep: true, agreeWithOutputRoot: true, }, } @@ -161,26 +162,35 @@ func TestAttemptStep(t *testing.T) { for _, tableTest := range tests { tableTest := tableTest t.Run(tableTest.name, func(t *testing.T) { - builder := claimBuilder.GameBuilder(!tableTest.agreeWithOutputRoot) + builder := claimBuilder.GameBuilder(faulttest.WithInvalidValue(tableTest.agreeWithOutputRoot)) tableTest.setupGame(builder) alphabetSolver := newClaimSolver(maxDepth, trace.NewSimpleTraceAccessor(claimBuilder.CorrectTraceProvider())) game := builder.Game claims := game.Claims() lastClaim := claims[len(claims)-1] - step, err := alphabetSolver.AttemptStep(ctx, game, lastClaim) - if tableTest.expectedErr == nil { - require.NoError(t, err) + agreedClaims := newHonestClaimTracker() + if tableTest.agreeWithOutputRoot { + agreedClaims.AddHonestClaim(types.Claim{}, claims[0]) + } + if (lastClaim.Depth()%2 == 0) == tableTest.agreeWithOutputRoot { + parentClaim := claims[lastClaim.ParentContractIndex] + grandParentClaim := claims[parentClaim.ParentContractIndex] + agreedClaims.AddHonestClaim(grandParentClaim, parentClaim) + } + step, err := alphabetSolver.AttemptStep(ctx, game, lastClaim, agreedClaims) + require.ErrorIs(t, err, tableTest.expectedErr) + if !tableTest.expectNoStep && tableTest.expectedErr == nil { + require.NotNil(t, step) require.Equal(t, lastClaim, step.LeafClaim) require.Equal(t, tableTest.expectAttack, step.IsAttack) require.Equal(t, tableTest.expectPreState, step.PreState) require.Equal(t, tableTest.expectProofData, step.ProofData) require.Equal(t, tableTest.expectedOracleData.IsLocal, step.OracleData.IsLocal) require.Equal(t, tableTest.expectedOracleData.OracleKey, step.OracleData.OracleKey) - require.Equal(t, tableTest.expectedOracleData.OracleData, step.OracleData.OracleData) + require.Equal(t, tableTest.expectedOracleData.GetPreimageWithSize(), step.OracleData.GetPreimageWithSize()) require.Equal(t, tableTest.expectedOracleData.OracleOffset, step.OracleData.OracleOffset) } else { - require.ErrorIs(t, err, tableTest.expectedErr) - require.Equal(t, StepData{}, step) + require.Nil(t, step) } }) } diff --git a/op-challenger/game/fault/sync.go b/op-challenger/game/fault/sync.go new file mode 100644 index 000000000000..ec0a8104080f --- /dev/null +++ b/op-challenger/game/fault/sync.go @@ -0,0 +1,36 @@ +package fault + +import ( + "context" + "errors" + "fmt" + + "github.com/ethereum-optimism/optimism/op-service/eth" +) + +var ErrNotInSync = errors.New("local node too far behind") + +type SyncStatusProvider interface { + SyncStatus(context.Context) (*eth.SyncStatus, error) +} + +type syncStatusValidator struct { + statusProvider SyncStatusProvider +} + +func newSyncStatusValidator(statusProvider SyncStatusProvider) *syncStatusValidator { + return &syncStatusValidator{ + statusProvider: statusProvider, + } +} + +func (s *syncStatusValidator) ValidateNodeSynced(ctx context.Context, gameL1Head eth.BlockID) error { + syncStatus, err := s.statusProvider.SyncStatus(ctx) + if err != nil { + return fmt.Errorf("failed to retrieve local node sync status: %w", err) + } + if syncStatus.CurrentL1.Number <= gameL1Head.Number { + return fmt.Errorf("%w require L1 block above %v but at %v", ErrNotInSync, gameL1Head.Number, syncStatus.CurrentL1.Number) + } + return nil +} diff --git a/op-challenger/game/fault/sync_test.go b/op-challenger/game/fault/sync_test.go new file mode 100644 index 000000000000..9099f52aeb81 --- /dev/null +++ b/op-challenger/game/fault/sync_test.go @@ -0,0 +1,83 @@ +package fault + +import ( + "context" + "errors" + "testing" + + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/stretchr/testify/require" +) + +func TestSyncStatusProvider(t *testing.T) { + requestErr := errors.New("boom") + tests := []struct { + name string + gameL1Head eth.BlockID + syncStatus *eth.SyncStatus + statusReqErr error + expected error + }{ + { + name: "ErrorFetchingStatus", + gameL1Head: eth.BlockID{Number: 100}, + syncStatus: nil, + statusReqErr: requestErr, + expected: requestErr, + }, + { + name: "CurrentL1BelowGameL1Head", + gameL1Head: eth.BlockID{Number: 100}, + syncStatus: ð.SyncStatus{ + CurrentL1: eth.L1BlockRef{ + Number: 99, + }, + }, + statusReqErr: nil, + expected: ErrNotInSync, + }, + { + name: "CurrentL1EqualToGameL1Head", + gameL1Head: eth.BlockID{Number: 100}, + syncStatus: ð.SyncStatus{ + CurrentL1: eth.L1BlockRef{ + Number: 100, + }, + }, + statusReqErr: nil, + expected: ErrNotInSync, + }, + { + name: "CurrentL1AboveGameL1Head", + gameL1Head: eth.BlockID{Number: 100}, + syncStatus: ð.SyncStatus{ + CurrentL1: eth.L1BlockRef{ + Number: 101, + }, + }, + statusReqErr: nil, + expected: nil, + }, + } + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + provider := &stubSyncStatusProvider{ + status: test.syncStatus, + err: test.statusReqErr, + } + validator := newSyncStatusValidator(provider) + err := validator.ValidateNodeSynced(context.Background(), test.gameL1Head) + require.ErrorIs(t, err, test.expected) + }) + } +} + +type stubSyncStatusProvider struct { + status *eth.SyncStatus + err error +} + +func (s *stubSyncStatusProvider) SyncStatus(_ context.Context) (*eth.SyncStatus, error) { + return s.status, s.err +} diff --git a/op-challenger/game/fault/test/claim_builder.go b/op-challenger/game/fault/test/claim_builder.go index 3a8cb6300740..36bfd1b4d8fc 100644 --- a/op-challenger/game/fault/test/claim_builder.go +++ b/op-challenger/game/fault/test/claim_builder.go @@ -10,6 +10,57 @@ import ( "github.com/stretchr/testify/require" ) +var DefaultClaimant = common.Address{0xba, 0xdb, 0xad, 0xba, 0xdb, 0xad} + +type claimCfg struct { + value common.Hash + invalidValue bool + claimant common.Address + parentIdx int +} + +func newClaimCfg(opts ...ClaimOpt) *claimCfg { + cfg := &claimCfg{} + for _, opt := range opts { + opt.Apply(cfg) + } + return cfg +} + +type ClaimOpt interface { + Apply(cfg *claimCfg) +} + +type claimOptFn func(cfg *claimCfg) + +func (c claimOptFn) Apply(cfg *claimCfg) { + c(cfg) +} + +func WithValue(value common.Hash) ClaimOpt { + return claimOptFn(func(cfg *claimCfg) { + cfg.value = value + }) +} + +func WithInvalidValue(invalid bool) ClaimOpt { + return claimOptFn(func(cfg *claimCfg) { + cfg.invalidValue = invalid + }) +} + +func WithClaimant(claimant common.Address) ClaimOpt { + return claimOptFn(func(cfg *claimCfg) { + cfg.claimant = claimant + }) +} + +func WithParent(claim types.Claim) ClaimOpt { + return claimOptFn(func(cfg *claimCfg) { + cfg.parentIdx = claim.ContractIndex + }) +} + // ClaimBuilder is a test utility to enable creating claims in a wide range of situations type ClaimBuilder struct { require *require.Assertions @@ -65,75 +116,44 @@ func (c *ClaimBuilder) incorrectClaim(pos types.Position) common.Hash { return common.BigToHash(pos.TraceIndex(c.maxDepth)) } -func (c *ClaimBuilder) claim(pos types.Position, correct bool) common.Hash { - if correct { - return c.CorrectClaimAtPosition(pos) - } else { - return c.incorrectClaim(pos) - } -} - -func (c *ClaimBuilder) CreateRootClaim(correct bool) types.Claim { - value := c.claim(types.NewPositionFromGIndex(big.NewInt(1)), correct) +func (c *ClaimBuilder) claim(pos types.Position, opts ...ClaimOpt) types.Claim { + cfg := newClaimCfg(opts...) claim := types.Claim{ ClaimData: types.ClaimData{ - Value: value, - Position: types.NewPosition(0, common.Big0), + Position: pos, }, + Claimant: DefaultClaimant, + } + if cfg.claimant != (common.Address{}) { + claim.Claimant = cfg.claimant + } + if cfg.value != (common.Hash{}) { + claim.Value = cfg.value + } else if cfg.invalidValue { + claim.Value = c.incorrectClaim(pos) + } else { + claim.Value = c.CorrectClaimAtPosition(pos) } + claim.ParentContractIndex = cfg.parentIdx return claim } -func (c *ClaimBuilder) CreateLeafClaim(traceIndex *big.Int, correct bool) types.Claim { - pos := types.NewPosition(c.maxDepth, traceIndex) - return types.Claim{ - ClaimData: types.ClaimData{ - Value: c.claim(pos, correct), - Position: pos, - }, - } +func (c *ClaimBuilder) CreateRootClaim(opts ...ClaimOpt) types.Claim { + pos := types.NewPositionFromGIndex(big.NewInt(1)) + return c.claim(pos, opts...) } -func (c *ClaimBuilder) AttackClaim(claim types.Claim, correct bool) types.Claim { - pos := claim.Position.Attack() - return types.Claim{ - ClaimData: types.ClaimData{ - Value: c.claim(pos, correct), - Position: pos, - }, - ParentContractIndex: claim.ContractIndex, - } +func (c *ClaimBuilder) CreateLeafClaim(traceIndex *big.Int, opts ...ClaimOpt) types.Claim { + pos := types.NewPosition(c.maxDepth, traceIndex) + return c.claim(pos, opts...) } -func (c *ClaimBuilder) AttackClaimWithValue(claim types.Claim, value common.Hash) types.Claim { +func (c *ClaimBuilder) AttackClaim(claim types.Claim, opts ...ClaimOpt) types.Claim { pos := claim.Position.Attack() - return types.Claim{ - ClaimData: types.ClaimData{ - Value: value, - Position: pos, - }, - ParentContractIndex: claim.ContractIndex, - } + return c.claim(pos, append([]ClaimOpt{WithParent(claim)}, opts...)...) } -func (c *ClaimBuilder) DefendClaim(claim types.Claim, correct bool) types.Claim { +func (c *ClaimBuilder) DefendClaim(claim types.Claim, opts ...ClaimOpt) types.Claim { pos := claim.Position.Defend() - return types.Claim{ - ClaimData: types.ClaimData{ - Value: c.claim(pos, correct), - Position: pos, - }, - ParentContractIndex: claim.ContractIndex, - } -} - -func (c *ClaimBuilder) DefendClaimWithValue(claim types.Claim, value common.Hash) types.Claim { - pos := claim.Position.Defend() - return types.Claim{ - ClaimData: types.ClaimData{ - Value: value, - Position: pos, - }, - ParentContractIndex: claim.ContractIndex, - } + return c.claim(pos, append([]ClaimOpt{WithParent(claim)}, opts...)...) } diff --git a/op-challenger/game/fault/test/game_builder.go b/op-challenger/game/fault/test/game_builder.go index f939f651aac3..331d59c60be0 100644 --- a/op-challenger/game/fault/test/game_builder.go +++ b/op-challenger/game/fault/test/game_builder.go @@ -2,6 +2,7 @@ package test import ( "math/big" + "testing" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum/go-ethereum/common" @@ -13,10 +14,18 @@ type GameBuilder struct { ExpectedActions []types.Action } -func (c *ClaimBuilder) GameBuilder(rootCorrect bool) *GameBuilder { +func NewGameBuilderFromGame(t *testing.T, provider types.TraceProvider, game types.Game) *GameBuilder { + claimBuilder := NewClaimBuilder(t, game.MaxDepth(), provider) + return &GameBuilder{ + builder: claimBuilder, + Game: types.NewGameState(game.Claims(), game.MaxDepth()), + } +} + +func (c *ClaimBuilder) GameBuilder(rootOpts ...ClaimOpt) *GameBuilder { return &GameBuilder{ builder: c, - Game: types.NewGameState([]types.Claim{c.CreateRootClaim(rootCorrect)}, c.maxDepth), + Game: types.NewGameState([]types.Claim{c.CreateRootClaim(rootOpts...)}, c.maxDepth), } } @@ -38,16 +47,28 @@ func (g *GameBuilder) SeqFrom(claim types.Claim) *GameBuilderSeq { } } +func (g *GameBuilderSeq) IsMaxDepth() bool { + return g.lastClaim.Depth() == g.gameBuilder.Game.MaxDepth() +} + +func (g *GameBuilderSeq) IsRoot() bool { + return g.lastClaim.IsRoot() +} + // addClaimToGame replaces the game being built with a new instance that has claim as the latest claim. // The ContractIndex in claim is updated with its position in the game's claim array. +// Does nothing if the claim already exists func (s *GameBuilderSeq) addClaimToGame(claim *types.Claim) { + if s.gameBuilder.Game.IsDuplicate(*claim) { + return + } claim.ContractIndex = len(s.gameBuilder.Game.Claims()) claims := append(s.gameBuilder.Game.Claims(), *claim) s.gameBuilder.Game = types.NewGameState(claims, s.builder.maxDepth) } -func (s *GameBuilderSeq) AttackCorrect() *GameBuilderSeq { - claim := s.builder.AttackClaim(s.lastClaim, true) +func (s *GameBuilderSeq) Attack(opts ...ClaimOpt) *GameBuilderSeq { + claim := s.builder.AttackClaim(s.lastClaim, opts...) s.addClaimToGame(&claim) return &GameBuilderSeq{ gameBuilder: s.gameBuilder, @@ -56,8 +77,8 @@ func (s *GameBuilderSeq) AttackCorrect() *GameBuilderSeq { } } -func (s *GameBuilderSeq) Attack(value common.Hash) *GameBuilderSeq { - claim := s.builder.AttackClaimWithValue(s.lastClaim, value) +func (s *GameBuilderSeq) Defend(opts ...ClaimOpt) *GameBuilderSeq { + claim := s.builder.DefendClaim(s.lastClaim, opts...) s.addClaimToGame(&claim) return &GameBuilderSeq{ gameBuilder: s.gameBuilder, @@ -66,24 +87,15 @@ func (s *GameBuilderSeq) Attack(value common.Hash) *GameBuilderSeq { } } -func (s *GameBuilderSeq) DefendCorrect() *GameBuilderSeq { - claim := s.builder.DefendClaim(s.lastClaim, true) - s.addClaimToGame(&claim) - return &GameBuilderSeq{ - gameBuilder: s.gameBuilder, - builder: s.builder, - lastClaim: claim, - } -} - -func (s *GameBuilderSeq) Defend(value common.Hash) *GameBuilderSeq { - claim := s.builder.DefendClaimWithValue(s.lastClaim, value) - s.addClaimToGame(&claim) - return &GameBuilderSeq{ - gameBuilder: s.gameBuilder, - builder: s.builder, - lastClaim: claim, +func (s *GameBuilderSeq) Step(opts ...ClaimOpt) { + cfg := newClaimCfg(opts...) + claimant := DefaultClaimant + if cfg.claimant != (common.Address{}) { + claimant = cfg.claimant } + claims := s.gameBuilder.Game.Claims() + claims[len(claims)-1].CounteredBy = claimant + s.gameBuilder.Game = types.NewGameState(claims, s.builder.maxDepth) } func (s *GameBuilderSeq) ExpectAttack() *GameBuilderSeq { diff --git a/op-challenger/game/fault/test/seq_builder.go b/op-challenger/game/fault/test/seq_builder.go index 1a02b9b52dbe..4863604b6ed9 100644 --- a/op-challenger/game/fault/test/seq_builder.go +++ b/op-challenger/game/fault/test/seq_builder.go @@ -12,24 +12,24 @@ type SequenceBuilder struct { // Seq starts building a claim by following a sequence of attack and defend moves from the root // The returned SequenceBuilder can be used to add additional moves. e.g: // claim := Seq(true).Attack(false).Attack(true).Defend(true).Get() -func (c *ClaimBuilder) Seq(rootCorrect bool) *SequenceBuilder { - claim := c.CreateRootClaim(rootCorrect) +func (c *ClaimBuilder) Seq(rootOpts ...ClaimOpt) *SequenceBuilder { + claim := c.CreateRootClaim(rootOpts...) return &SequenceBuilder{ builder: c, lastClaim: claim, } } -func (s *SequenceBuilder) Attack(correct bool) *SequenceBuilder { - claim := s.builder.AttackClaim(s.lastClaim, correct) +func (s *SequenceBuilder) Attack(opts ...ClaimOpt) *SequenceBuilder { + claim := s.builder.AttackClaim(s.lastClaim, opts...) return &SequenceBuilder{ builder: s.builder, lastClaim: claim, } } -func (s *SequenceBuilder) Defend(correct bool) *SequenceBuilder { - claim := s.builder.DefendClaim(s.lastClaim, correct) +func (s *SequenceBuilder) Defend(opts ...ClaimOpt) *SequenceBuilder { + claim := s.builder.DefendClaim(s.lastClaim, opts...) return &SequenceBuilder{ builder: s.builder, lastClaim: claim, diff --git a/op-challenger/game/fault/trace/alphabet/prestate.go b/op-challenger/game/fault/trace/alphabet/prestate.go index 61f5fd98bd08..0820b689122e 100644 --- a/op-challenger/game/fault/trace/alphabet/prestate.go +++ b/op-challenger/game/fault/trace/alphabet/prestate.go @@ -10,16 +10,19 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) -var absolutePrestate = common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000060") +var absolutePrestate = common.FromHex("0000000000000000000000000000000000000000000000000000000000000060") var absolutePrestateInt = new(big.Int).SetBytes(absolutePrestate) -var _ types.PrestateProvider = (*AlphabetPrestateProvider)(nil) +var _ types.PrestateProvider = (*alphabetPrestateProvider)(nil) -// AlphabetPrestateProvider is a stateless [PrestateProvider] that +// PrestateProvider provides the alphabet VM prestate +var PrestateProvider = &alphabetPrestateProvider{} + +// alphabetPrestateProvider is a stateless [PrestateProvider] that // uses a pre-determined, fixed pre-state hash. -type AlphabetPrestateProvider struct{} +type alphabetPrestateProvider struct{} -func (ap *AlphabetPrestateProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) { +func (ap *alphabetPrestateProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) { hash := common.BytesToHash(crypto.Keccak256(absolutePrestate)) hash[0] = mipsevm.VMStatusUnfinished return hash, nil diff --git a/op-challenger/game/fault/trace/alphabet/prestate_test.go b/op-challenger/game/fault/trace/alphabet/prestate_test.go index bbad0389a129..bac7f46d2299 100644 --- a/op-challenger/game/fault/trace/alphabet/prestate_test.go +++ b/op-challenger/game/fault/trace/alphabet/prestate_test.go @@ -9,7 +9,7 @@ import ( ) func TestAlphabetPrestateProvider_AbsolutePreStateCommitment_Succeeds(t *testing.T) { - provider := AlphabetPrestateProvider{} + provider := alphabetPrestateProvider{} hash, err := provider.AbsolutePreStateCommitment(context.Background()) require.NoError(t, err) expected := common.HexToHash("0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98") diff --git a/op-challenger/game/fault/trace/alphabet/provider.go b/op-challenger/game/fault/trace/alphabet/provider.go index 373fcb0adc2f..6cae7154ed76 100644 --- a/op-challenger/game/fault/trace/alphabet/provider.go +++ b/op-challenger/game/fault/trace/alphabet/provider.go @@ -28,7 +28,7 @@ var _ types.TraceProvider = (*AlphabetTraceProvider)(nil) // AlphabetTraceProvider is a [TraceProvider] that monotonically increments // the starting l2 block number as the claim value. type AlphabetTraceProvider struct { - AlphabetPrestateProvider + alphabetPrestateProvider startingBlockNumber *big.Int depth types.Depth maxLen uint64 diff --git a/op-challenger/game/fault/trace/cannon/executor.go b/op-challenger/game/fault/trace/cannon/executor.go index eeb24dd73eab..e2aaf7693cfc 100644 --- a/op-challenger/game/fault/trace/cannon/executor.go +++ b/op-challenger/game/fault/trace/cannon/executor.go @@ -33,6 +33,7 @@ type Executor struct { logger log.Logger metrics CannonMetricer l1 string + l1Beacon string l2 string inputs LocalGameInputs cannon string @@ -52,6 +53,7 @@ func NewExecutor(logger log.Logger, m CannonMetricer, cfg *config.Config, inputs logger: logger, metrics: m, l1: cfg.L1EthRpc, + l1Beacon: cfg.L1Beacon, l2: cfg.CannonL2, inputs: inputs, cannon: cfg.CannonBin, @@ -67,14 +69,23 @@ func NewExecutor(logger log.Logger, m CannonMetricer, cfg *config.Config, inputs } } +// GenerateProof executes cannon to generate a proof at the specified trace index. +// The proof is stored at the specified directory. func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) error { + return e.generateProof(ctx, dir, i, i) +} + +// generateProofOrUntilPreimageRead executes cannon to generate a proof at the specified trace index, +// or until a non-local preimage read is encountered if untilPreimageRead is true. +// The proof is stored at the specified directory. +func (e *Executor) generateProof(ctx context.Context, dir string, begin uint64, end uint64, extraCannonArgs ...string) error { snapshotDir := filepath.Join(dir, snapsDir) - start, err := e.selectSnapshot(e.logger, snapshotDir, e.absolutePreState, i) + start, err := e.selectSnapshot(e.logger, snapshotDir, e.absolutePreState, begin) if err != nil { return fmt.Errorf("find starting snapshot: %w", err) } proofDir := filepath.Join(dir, proofsDir) - dataDir := filepath.Join(dir, preimagesDir) + dataDir := preimageDir(dir) lastGeneratedState := filepath.Join(dir, finalState) args := []string{ "run", @@ -82,18 +93,20 @@ func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) erro "--output", lastGeneratedState, "--meta", "", "--info-at", "%" + strconv.FormatUint(uint64(e.infoFreq), 10), - "--proof-at", "=" + strconv.FormatUint(i, 10), + "--proof-at", "=" + strconv.FormatUint(end, 10), "--proof-fmt", filepath.Join(proofDir, "%d.json.gz"), "--snapshot-at", "%" + strconv.FormatUint(uint64(e.snapshotFreq), 10), "--snapshot-fmt", filepath.Join(snapshotDir, "%d.json.gz"), } - if i < math.MaxUint64 { - args = append(args, "--stop-at", "="+strconv.FormatUint(i+1, 10)) + if end < math.MaxUint64 { + args = append(args, "--stop-at", "="+strconv.FormatUint(end+1, 10)) } + args = append(args, extraCannonArgs...) args = append(args, "--", e.server, "--server", "--l1", e.l1, + "--l1.beacon", e.l1Beacon, "--l2", e.l2, "--datadir", dataDir, "--l1.head", e.inputs.L1Head.Hex(), @@ -121,19 +134,23 @@ func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) erro if err := os.MkdirAll(proofDir, 0755); err != nil { return fmt.Errorf("could not create proofs directory %v: %w", proofDir, err) } - e.logger.Info("Generating trace", "proof", i, "cmd", e.cannon, "args", strings.Join(args, ", ")) + e.logger.Info("Generating trace", "proof", end, "cmd", e.cannon, "args", strings.Join(args, ", ")) execStart := time.Now() - err = e.cmdExecutor(ctx, e.logger.New("proof", i), e.cannon, args...) + err = e.cmdExecutor(ctx, e.logger.New("proof", end), e.cannon, args...) e.metrics.RecordCannonExecutionTime(time.Since(execStart).Seconds()) return err } +func preimageDir(dir string) string { + return filepath.Join(dir, preimagesDir) +} + func runCmd(ctx context.Context, l log.Logger, binary string, args ...string) error { cmd := exec.CommandContext(ctx, binary, args...) - stdOut := oplog.NewWriter(l, log.LvlInfo) + stdOut := oplog.NewWriter(l, log.LevelInfo) defer stdOut.Close() // Keep stdErr at info level because cannon uses stderr for progress messages - stdErr := oplog.NewWriter(l, log.LvlInfo) + stdErr := oplog.NewWriter(l, log.LevelInfo) defer stdErr.Close() cmd.Stdout = stdOut cmd.Stderr = stdErr diff --git a/op-challenger/game/fault/trace/cannon/executor_test.go b/op-challenger/game/fault/trace/cannon/executor_test.go index 0e67aa9bcaf4..9ac7db834bd7 100644 --- a/op-challenger/game/fault/trace/cannon/executor_test.go +++ b/op-challenger/game/fault/trace/cannon/executor_test.go @@ -24,7 +24,7 @@ func TestGenerateProof(t *testing.T) { input := "starting.json" tempDir := t.TempDir() dir := filepath.Join(tempDir, "gameDir") - cfg := config.NewConfig(common.Address{0xbb}, "http://localhost:8888", tempDir, config.TraceTypeCannon) + cfg := config.NewConfig(common.Address{0xbb}, "http://localhost:8888", "http://localhost:9000", tempDir, config.TraceTypeCannon) cfg.CannonAbsolutePreState = "pre.json" cfg.CannonBin = "./bin/cannon" cfg.CannonServer = "./bin/op-program" @@ -41,7 +41,7 @@ func TestGenerateProof(t *testing.T) { } captureExec := func(t *testing.T, cfg config.Config, proofAt uint64) (string, string, map[string]string) { m := &cannonDurationMetrics{} - executor := NewExecutor(testlog.Logger(t, log.LvlInfo), m, &cfg, inputs) + executor := NewExecutor(testlog.Logger(t, log.LevelInfo), m, &cfg, inputs) executor.selectSnapshot = func(logger log.Logger, dir string, absolutePreState string, i uint64) (string, error) { return input, nil } @@ -91,6 +91,7 @@ func TestGenerateProof(t *testing.T) { // Then everything else pairs off correctly again require.Equal(t, "--server", args[cfg.CannonServer]) require.Equal(t, cfg.L1EthRpc, args["--l1"]) + require.Equal(t, cfg.L1Beacon, args["--l1.beacon"]) require.Equal(t, cfg.CannonL2, args["--l2"]) require.Equal(t, filepath.Join(dir, preimagesDir), args["--datadir"]) require.Equal(t, filepath.Join(dir, proofsDir, "%d.json.gz"), args["--proof-fmt"]) @@ -135,15 +136,16 @@ func TestRunCmdLogsOutput(t *testing.T) { } ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - logger := testlog.Logger(t, log.LvlInfo) - logs := testlog.Capture(logger) + logger, logs := testlog.CaptureLogger(t, log.LevelInfo) err := runCmd(ctx, logger, bin, "Hello World") require.NoError(t, err) - require.NotNil(t, logs.FindLog(log.LvlInfo, "Hello World")) + levelFilter := testlog.NewLevelFilter(log.LevelInfo) + msgFilter := testlog.NewMessageFilter("Hello World") + require.NotNil(t, logs.FindLog(levelFilter, msgFilter)) } func TestFindStartingSnapshot(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) withSnapshots := func(t *testing.T, files ...string) string { dir := t.TempDir() diff --git a/op-challenger/game/fault/trace/cannon/local.go b/op-challenger/game/fault/trace/cannon/local.go index 90c8d575beea..7f44886fd387 100644 --- a/op-challenger/game/fault/trace/cannon/local.go +++ b/op-challenger/game/fault/trace/cannon/local.go @@ -36,15 +36,15 @@ func FetchLocalInputs(ctx context.Context, caller GameInputsSource, l2Client L2H if err != nil { return LocalGameInputs{}, fmt.Errorf("fetch proposals: %w", err) } - return FetchLocalInputsFromProposals(ctx, caller, l2Client, agreedOutput, claimedOutput) -} - -func FetchLocalInputsFromProposals(ctx context.Context, caller L1HeadSource, l2Client L2HeaderSource, agreedOutput contracts.Proposal, claimedOutput contracts.Proposal) (LocalGameInputs, error) { l1Head, err := caller.GetL1Head(ctx) if err != nil { return LocalGameInputs{}, fmt.Errorf("fetch L1 head: %w", err) } + return FetchLocalInputsFromProposals(ctx, l1Head, l2Client, agreedOutput, claimedOutput) +} + +func FetchLocalInputsFromProposals(ctx context.Context, l1Head common.Hash, l2Client L2HeaderSource, agreedOutput contracts.Proposal, claimedOutput contracts.Proposal) (LocalGameInputs, error) { agreedHeader, err := l2Client.HeaderByNumber(ctx, agreedOutput.L2BlockNumber) if err != nil { return LocalGameInputs{}, fmt.Errorf("fetch L2 block header %v: %w", agreedOutput.L2BlockNumber, err) diff --git a/op-challenger/game/fault/trace/cannon/local_test.go b/op-challenger/game/fault/trace/cannon/local_test.go index d0e542f536b2..4248b4dc6226 100644 --- a/op-challenger/game/fault/trace/cannon/local_test.go +++ b/op-challenger/game/fault/trace/cannon/local_test.go @@ -52,9 +52,7 @@ func TestFetchLocalInputsFromProposals(t *testing.T) { L2BlockNumber: big.NewInt(3333), OutputRoot: common.Hash{0xee}, } - contract := &mockGameInputsSource{ - l1Head: common.Hash{0xcc}, - } + l1Head := common.Hash{0xcc} l2Client := &mockL2DataSource{ chainID: big.NewInt(88422), header: ethtypes.Header{ @@ -62,10 +60,10 @@ func TestFetchLocalInputsFromProposals(t *testing.T) { }, } - inputs, err := FetchLocalInputsFromProposals(ctx, contract, l2Client, agreed, claimed) + inputs, err := FetchLocalInputsFromProposals(ctx, l1Head, l2Client, agreed, claimed) require.NoError(t, err) - require.Equal(t, contract.l1Head, inputs.L1Head) + require.Equal(t, l1Head, inputs.L1Head) require.Equal(t, l2Client.header.Hash(), inputs.L2Head) require.EqualValues(t, agreed.OutputRoot, inputs.L2OutputRoot) require.EqualValues(t, claimed.OutputRoot, inputs.L2Claim) diff --git a/op-challenger/game/fault/trace/cannon/preimage.go b/op-challenger/game/fault/trace/cannon/preimage.go new file mode 100644 index 000000000000..60bb6ec6fad2 --- /dev/null +++ b/op-challenger/game/fault/trace/cannon/preimage.go @@ -0,0 +1,120 @@ +package cannon + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + preimage "github.com/ethereum-optimism/optimism/op-preimage" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/kzg4844" + "github.com/ethereum/go-ethereum/params" +) + +const ( + fieldElemKeyLength = 80 + commitmentLength = 48 + lengthPrefixSize = 8 +) + +var ( + ErrInvalidScalarValue = errors.New("invalid scalar value") + ErrInvalidBlobKeyPreimage = errors.New("invalid blob key preimage") +) + +type preimageSource func(key common.Hash) ([]byte, error) + +type preimageLoader struct { + getPreimage preimageSource +} + +func newPreimageLoader(getPreimage preimageSource) *preimageLoader { + return &preimageLoader{ + getPreimage: getPreimage, + } +} + +func (l *preimageLoader) LoadPreimage(proof *proofData) (*types.PreimageOracleData, error) { + if len(proof.OracleKey) == 0 { + return nil, nil + } + switch preimage.KeyType(proof.OracleKey[0]) { + case preimage.BlobKeyType: + return l.loadBlobPreimage(proof) + case preimage.PrecompileKeyType: + return l.loadPrecompilePreimage(proof) + default: + return types.NewPreimageOracleData(proof.OracleKey, proof.OracleValue, proof.OracleOffset), nil + } +} + +func (l *preimageLoader) loadBlobPreimage(proof *proofData) (*types.PreimageOracleData, error) { + // The key for a blob field element is a keccak hash of commitment++fieldElementIndex. + // First retrieve the preimage of the key as a keccak hash so we have the commitment and required field element + inputsKey := preimage.Keccak256Key(proof.OracleKey).PreimageKey() + inputs, err := l.getPreimage(inputsKey) + if err != nil { + return nil, fmt.Errorf("failed to get key preimage: %w", err) + } + if len(inputs) != fieldElemKeyLength { + return nil, fmt.Errorf("%w, expected length %v but was %v", ErrInvalidBlobKeyPreimage, fieldElemKeyLength, len(inputs)) + } + commitment := inputs[:commitmentLength] + requiredFieldElement := binary.BigEndian.Uint64(inputs[72:]) + + // Now, reconstruct the full blob by loading the 4096 field elements. + blob := eth.Blob{} + fieldElemKey := make([]byte, fieldElemKeyLength) + copy(fieldElemKey[:commitmentLength], commitment) + for i := 0; i < params.BlobTxFieldElementsPerBlob; i++ { + binary.BigEndian.PutUint64(fieldElemKey[72:], uint64(i)) + key := preimage.BlobKey(crypto.Keccak256(fieldElemKey)).PreimageKey() + fieldElement, err := l.getPreimage(key) + if err != nil { + return nil, fmt.Errorf("failed to load field element %v with key %v: %w", i, common.Hash(key), err) + } + copy(blob[i<<5:(i+1)<<5], fieldElement[:]) + } + + // Sanity check the blob data matches the commitment + blobCommitment, err := blob.ComputeKZGCommitment() + if err != nil || !bytes.Equal(blobCommitment[:], commitment[:]) { + return nil, fmt.Errorf("invalid blob commitment: %w", err) + } + // Compute the KZG proof for the required field element + var point kzg4844.Point + new(big.Int).SetUint64(requiredFieldElement).FillBytes(point[:]) + kzgProof, claim, err := kzg4844.ComputeProof(kzg4844.Blob(blob), point) + if err != nil { + return nil, fmt.Errorf("failed to compute kzg proof: %w", err) + } + err = kzg4844.VerifyProof(kzg4844.Commitment(commitment), point, claim, kzgProof) + if err != nil { + return nil, fmt.Errorf("failed to verify proof: %w", err) + } + + claimWithLength := lengthPrefixed(claim[:]) + return types.NewPreimageOracleBlobData(proof.OracleKey, claimWithLength, proof.OracleOffset, requiredFieldElement, commitment, kzgProof[:]), nil +} + +func (l *preimageLoader) loadPrecompilePreimage(proof *proofData) (*types.PreimageOracleData, error) { + inputKey := preimage.Keccak256Key(proof.OracleKey).PreimageKey() + input, err := l.getPreimage(inputKey) + if err != nil { + return nil, fmt.Errorf("failed to get key preimage: %w", err) + } + inputWithLength := lengthPrefixed(input) + return types.NewPreimageOracleData(proof.OracleKey, inputWithLength, proof.OracleOffset), nil +} + +func lengthPrefixed(data []byte) []byte { + dataWithLength := make([]byte, len(data)+lengthPrefixSize) + binary.BigEndian.PutUint64(dataWithLength[:lengthPrefixSize], uint64(len(data))) + copy(dataWithLength[lengthPrefixSize:], data) + return dataWithLength +} diff --git a/op-challenger/game/fault/trace/cannon/preimage_test.go b/op-challenger/game/fault/trace/cannon/preimage_test.go new file mode 100644 index 000000000000..94fbbc35bc88 --- /dev/null +++ b/op-challenger/game/fault/trace/cannon/preimage_test.go @@ -0,0 +1,214 @@ +package cannon + +import ( + "crypto/sha256" + "encoding/binary" + "fmt" + "math/big" + "testing" + + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + gokzg4844 "github.com/crate-crypto/go-kzg-4844" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + preimage "github.com/ethereum-optimism/optimism/op-preimage" + "github.com/ethereum-optimism/optimism/op-program/host/kvstore" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/kzg4844" + "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/require" +) + +func TestPreimageLoader_NoPreimage(t *testing.T) { + loader := newPreimageLoader(kvstore.NewMemKV().Get) + actual, err := loader.LoadPreimage(&proofData{}) + require.NoError(t, err) + require.Nil(t, actual) +} + +func TestPreimageLoader_LocalPreimage(t *testing.T) { + loader := newPreimageLoader(kvstore.NewMemKV().Get) + proof := &proofData{ + OracleKey: common.Hash{byte(preimage.LocalKeyType), 0xaa, 0xbb}.Bytes(), + OracleValue: nil, + OracleOffset: 4, + } + actual, err := loader.LoadPreimage(proof) + require.NoError(t, err) + expected := types.NewPreimageOracleData(proof.OracleKey, nil, proof.OracleOffset) + require.Equal(t, expected, actual) + require.True(t, actual.IsLocal) +} + +func TestPreimageLoader_SimpleTypes(t *testing.T) { + tests := []preimage.KeyType{ + preimage.Keccak256KeyType, + preimage.Sha256KeyType, + } + for _, keyType := range tests { + keyType := keyType + t.Run(fmt.Sprintf("type-%v", keyType), func(t *testing.T) { + loader := newPreimageLoader(kvstore.NewMemKV().Get) + proof := &proofData{ + OracleKey: common.Hash{byte(keyType), 0xaa, 0xbb}.Bytes(), + OracleValue: []byte{1, 2, 3, 4, 5, 6}, + OracleOffset: 3, + } + actual, err := loader.LoadPreimage(proof) + require.NoError(t, err) + expected := types.NewPreimageOracleData(proof.OracleKey, proof.OracleValue, proof.OracleOffset) + require.Equal(t, expected, actual) + }) + } +} + +func TestPreimageLoader_BlobPreimage(t *testing.T) { + blob := testBlob() + commitment, err := kzg4844.BlobToCommitment(kzg4844.Blob(blob)) + require.NoError(t, err) + + fieldIndex := uint64(24) + elementData := blob[fieldIndex<<5 : (fieldIndex+1)<<5] + var point kzg4844.Point + new(big.Int).SetUint64(fieldIndex).FillBytes(point[:]) + kzgProof, claim, err := kzg4844.ComputeProof(kzg4844.Blob(blob), point) + require.NoError(t, err) + elementDataWithLengthPrefix := make([]byte, len(elementData)+lengthPrefixSize) + binary.BigEndian.PutUint64(elementDataWithLengthPrefix[:lengthPrefixSize], uint64(len(elementData))) + copy(elementDataWithLengthPrefix[lengthPrefixSize:], elementData) + + keyBuf := make([]byte, 80) + copy(keyBuf[:48], commitment[:]) + binary.BigEndian.PutUint64(keyBuf[72:], fieldIndex) + key := preimage.BlobKey(crypto.Keccak256Hash(keyBuf)).PreimageKey() + + proof := &proofData{ + OracleKey: key[:], + OracleValue: elementDataWithLengthPrefix, + OracleOffset: 4, + } + + t.Run("NoKeyPreimage", func(t *testing.T) { + kv := kvstore.NewMemKV() + loader := newPreimageLoader(kv.Get) + proof := &proofData{ + OracleKey: common.Hash{byte(preimage.BlobKeyType), 0xaf}.Bytes(), + OracleValue: proof.OracleValue, + OracleOffset: proof.OracleOffset, + } + _, err := loader.LoadPreimage(proof) + require.ErrorIs(t, err, kvstore.ErrNotFound) + }) + + t.Run("InvalidKeyPreimage", func(t *testing.T) { + kv := kvstore.NewMemKV() + loader := newPreimageLoader(kv.Get) + proof := &proofData{ + OracleKey: common.Hash{byte(preimage.BlobKeyType), 0xad}.Bytes(), + OracleValue: proof.OracleValue, + OracleOffset: proof.OracleOffset, + } + require.NoError(t, kv.Put(preimage.Keccak256Key(proof.OracleKey).PreimageKey(), []byte{1, 2})) + _, err := loader.LoadPreimage(proof) + require.ErrorIs(t, err, ErrInvalidBlobKeyPreimage) + }) + + t.Run("MissingBlobs", func(t *testing.T) { + kv := kvstore.NewMemKV() + loader := newPreimageLoader(kv.Get) + proof := &proofData{ + OracleKey: common.Hash{byte(preimage.BlobKeyType), 0xae}.Bytes(), + OracleValue: proof.OracleValue, + OracleOffset: proof.OracleOffset, + } + require.NoError(t, kv.Put(preimage.Keccak256Key(proof.OracleKey).PreimageKey(), keyBuf)) + _, err := loader.LoadPreimage(proof) + require.ErrorIs(t, err, kvstore.ErrNotFound) + }) + + t.Run("Valid", func(t *testing.T) { + kv := kvstore.NewMemKV() + loader := newPreimageLoader(kv.Get) + storeBlob(t, kv, gokzg4844.KZGCommitment(commitment), blob) + actual, err := loader.LoadPreimage(proof) + require.NoError(t, err) + + claimWithLength := make([]byte, len(claim)+lengthPrefixSize) + binary.BigEndian.PutUint64(claimWithLength[:lengthPrefixSize], uint64(len(claim))) + copy(claimWithLength[lengthPrefixSize:], claim[:]) + + expected := types.NewPreimageOracleBlobData(proof.OracleKey, claimWithLength, proof.OracleOffset, fieldIndex, commitment[:], kzgProof[:]) + require.Equal(t, expected, actual) + require.False(t, actual.IsLocal) + + // Check the KZG proof is valid + var actualPoint kzg4844.Point + new(big.Int).SetUint64(actual.BlobFieldIndex).FillBytes(actualPoint[:]) + actualClaim := kzg4844.Claim(actual.GetPreimageWithoutSize()) + actualCommitment := kzg4844.Commitment(actual.BlobCommitment) + actualProof := kzg4844.Proof(actual.BlobProof) + err = kzg4844.VerifyProof(actualCommitment, actualPoint, actualClaim, actualProof) + require.NoError(t, err) + }) +} + +func TestPreimageLoader_PrecompilePreimage(t *testing.T) { + input := []byte("test input") + key := preimage.PrecompileKey(crypto.Keccak256Hash(input)).PreimageKey() + proof := &proofData{ + OracleKey: key[:], + } + + t.Run("NoInputPreimage", func(t *testing.T) { + kv := kvstore.NewMemKV() + loader := newPreimageLoader(kv.Get) + _, err := loader.LoadPreimage(proof) + require.ErrorIs(t, err, kvstore.ErrNotFound) + }) + t.Run("Valid", func(t *testing.T) { + kv := kvstore.NewMemKV() + loader := newPreimageLoader(kv.Get) + require.NoError(t, kv.Put(preimage.Keccak256Key(proof.OracleKey).PreimageKey(), input)) + actual, err := loader.LoadPreimage(proof) + require.NoError(t, err) + inputWithLength := lengthPrefixed(input) + expected := types.NewPreimageOracleData(proof.OracleKey, inputWithLength, proof.OracleOffset) + require.Equal(t, expected, actual) + }) +} + +// Returns a serialized random field element in big-endian +func fieldElement(val uint64) [32]byte { + r := fr.NewElement(val) + return gokzg4844.SerializeScalar(r) +} + +func testBlob() gokzg4844.Blob { + var blob gokzg4844.Blob + bytesPerBlob := gokzg4844.ScalarsPerBlob * gokzg4844.SerializedScalarSize + for i := 0; i < bytesPerBlob; i += gokzg4844.SerializedScalarSize { + fieldElementBytes := fieldElement(uint64(i)) + copy(blob[i:i+gokzg4844.SerializedScalarSize], fieldElementBytes[:]) + } + return blob +} + +func storeBlob(t *testing.T, kv kvstore.KV, commitment gokzg4844.KZGCommitment, blob gokzg4844.Blob) { + // Pre-store versioned hash preimage (commitment) + key := preimage.Sha256Key(sha256.Sum256(commitment[:])) + err := kv.Put(key.PreimageKey(), commitment[:]) + require.NoError(t, err, "Failed to store versioned hash preimage in kvstore") + + // Pre-store blob field elements + blobKeyBuf := make([]byte, 80) + copy(blobKeyBuf[:48], commitment[:]) + for i := 0; i < params.BlobTxFieldElementsPerBlob; i++ { + binary.BigEndian.PutUint64(blobKeyBuf[72:], uint64(i)) + feKey := crypto.Keccak256Hash(blobKeyBuf) + err := kv.Put(preimage.Keccak256Key(feKey).PreimageKey(), blobKeyBuf) + require.NoError(t, err) + + err = kv.Put(preimage.BlobKey(feKey).PreimageKey(), blob[i<<5:(i+1)<<5]) + require.NoError(t, err, "Failed to store field element preimage in kvstore") + } +} diff --git a/op-challenger/game/fault/trace/cannon/prestate.go b/op-challenger/game/fault/trace/cannon/prestate.go index ae6237ca4c72..67d7c55389c2 100644 --- a/op-challenger/game/fault/trace/cannon/prestate.go +++ b/op-challenger/game/fault/trace/cannon/prestate.go @@ -14,10 +14,12 @@ var _ types.PrestateProvider = (*CannonPrestateProvider)(nil) type CannonPrestateProvider struct { prestate string + + prestateCommitment common.Hash } func NewPrestateProvider(prestate string) *CannonPrestateProvider { - return &CannonPrestateProvider{prestate} + return &CannonPrestateProvider{prestate: prestate} } func (p *CannonPrestateProvider) absolutePreState() ([]byte, error) { @@ -29,6 +31,9 @@ func (p *CannonPrestateProvider) absolutePreState() ([]byte, error) { } func (p *CannonPrestateProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) { + if p.prestateCommitment != (common.Hash{}) { + return p.prestateCommitment, nil + } state, err := p.absolutePreState() if err != nil { return common.Hash{}, fmt.Errorf("cannot load absolute pre-state: %w", err) @@ -37,5 +42,6 @@ func (p *CannonPrestateProvider) AbsolutePreStateCommitment(_ context.Context) ( if err != nil { return common.Hash{}, fmt.Errorf("cannot hash absolute pre-state: %w", err) } + p.prestateCommitment = hash return hash, nil } diff --git a/op-challenger/game/fault/trace/cannon/prestate_test.go b/op-challenger/game/fault/trace/cannon/prestate_test.go index 14b49cf4744d..1f14ebac118e 100644 --- a/op-challenger/game/fault/trace/cannon/prestate_test.go +++ b/op-challenger/game/fault/trace/cannon/prestate_test.go @@ -58,6 +58,21 @@ func TestAbsolutePreStateCommitment(t *testing.T) { require.NoError(t, err) require.Equal(t, expected, actual) }) + + t.Run("CacheAbsolutePreState", func(t *testing.T) { + setupPreState(t, dataDir, "state.json") + provider := newCannonPrestateProvider(dataDir, prestate) + first, err := provider.AbsolutePreStateCommitment(context.Background()) + require.NoError(t, err) + + // Remove the prestate from disk + require.NoError(t, os.Remove(provider.prestate)) + + // Value should still be available from cache + cached, err := provider.AbsolutePreStateCommitment(context.Background()) + require.NoError(t, err) + require.Equal(t, first, cached) + }) } func setupPreState(t *testing.T, dataDir string, filename string) { diff --git a/op-challenger/game/fault/trace/cannon/provider.go b/op-challenger/game/fault/trace/cannon/provider.go index 936e29424ace..bd71ce2a4db5 100644 --- a/op-challenger/game/fault/trace/cannon/provider.go +++ b/op-challenger/game/fault/trace/cannon/provider.go @@ -5,11 +5,16 @@ import ( "encoding/json" "errors" "fmt" + "io" + "math" "os" "path/filepath" + "strconv" "github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + preimage "github.com/ethereum-optimism/optimism/op-preimage" + "github.com/ethereum-optimism/optimism/op-program/host/kvstore" "github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -42,26 +47,26 @@ type ProofGenerator interface { } type CannonTraceProvider struct { - logger log.Logger - dir string - prestate string - generator ProofGenerator - gameDepth types.Depth - localContext common.Hash + logger log.Logger + dir string + prestate string + generator ProofGenerator + gameDepth types.Depth + preimageLoader *preimageLoader // lastStep stores the last step in the actual trace if known. 0 indicates unknown. // Cached as an optimisation to avoid repeatedly attempting to execute beyond the end of the trace. lastStep uint64 } -func NewTraceProvider(logger log.Logger, m CannonMetricer, cfg *config.Config, localContext common.Hash, localInputs LocalGameInputs, dir string, gameDepth types.Depth) *CannonTraceProvider { +func NewTraceProvider(logger log.Logger, m CannonMetricer, cfg *config.Config, localInputs LocalGameInputs, dir string, gameDepth types.Depth) *CannonTraceProvider { return &CannonTraceProvider{ - logger: logger, - dir: dir, - prestate: cfg.CannonAbsolutePreState, - generator: NewExecutor(logger, m, cfg, localInputs), - gameDepth: gameDepth, - localContext: localContext, + logger: logger, + dir: dir, + prestate: cfg.CannonAbsolutePreState, + generator: NewExecutor(logger, m, cfg, localInputs), + gameDepth: gameDepth, + preimageLoader: newPreimageLoader(kvstore.NewDiskKV(preimageDir(dir)).Get), } } @@ -103,9 +108,9 @@ func (p *CannonTraceProvider) GetStepData(ctx context.Context, pos types.Positio if data == nil { return nil, nil, nil, errors.New("proof missing proof data") } - var oracleData *types.PreimageOracleData - if len(proof.OracleKey) > 0 { - oracleData = types.NewPreimageOracleData(proof.OracleKey, proof.OracleValue, proof.OracleOffset) + oracleData, err := p.preimageLoader.LoadPreimage(proof) + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to load preimage: %w", err) } return value, data, oracleData, nil } @@ -156,9 +161,9 @@ func (p *CannonTraceProvider) loadProof(ctx context.Context, i uint64) (*proofDa file, err = ioutil.OpenDecompressed(path) if errors.Is(err, os.ErrNotExist) { // Expected proof wasn't generated, check if we reached the end of execution - state, err := parseState(filepath.Join(p.dir, finalState)) + state, err := p.finalState() if err != nil { - return nil, fmt.Errorf("cannot read final state: %w", err) + return nil, err } if state.Exited && state.Step <= i { p.logger.Warn("Requested proof was after the program exited", "proof", i, "last", state.Step) @@ -201,6 +206,14 @@ func (p *CannonTraceProvider) loadProof(ctx context.Context, i uint64) (*proofDa return &proof, nil } +func (c *CannonTraceProvider) finalState() (*mipsevm.State, error) { + state, err := parseState(filepath.Join(c.dir, finalState)) + if err != nil { + return nil, fmt.Errorf("cannot read final state: %w", err) + } + return state, nil +} + type diskStateCacheObj struct { Step uint64 `json:"step"` } @@ -232,3 +245,69 @@ func writeLastStep(dir string, proof *proofData, step uint64) error { } return nil } + +// CannonTraceProviderForTest is a CannonTraceProvider that can find the step referencing the preimage read +// Only to be used for testing +type CannonTraceProviderForTest struct { + *CannonTraceProvider +} + +type preimageOpts []string + +type PreimageOpt func() preimageOpts + +func PreimageLoad(key preimage.Key, offset uint32) PreimageOpt { + return func() preimageOpts { + return []string{"--stop-at-preimage", fmt.Sprintf("%v@%v", common.Hash(key.PreimageKey()).Hex(), offset)} + } +} + +func FirstPreimageLoadOfType(preimageType string) PreimageOpt { + return func() preimageOpts { + return []string{"--stop-at-preimage-type", preimageType} + } +} + +func FirstKeccakPreimageLoad() PreimageOpt { + return FirstPreimageLoadOfType("keccak") +} + +func FirstPrecompilePreimageLoad() PreimageOpt { + return FirstPreimageLoadOfType("precompile") +} + +func PreimageLargerThan(size int) PreimageOpt { + return func() preimageOpts { + return []string{"--stop-at-preimage-larger-than", strconv.Itoa(size)} + } +} + +func NewTraceProviderForTest(logger log.Logger, m CannonMetricer, cfg *config.Config, localInputs LocalGameInputs, dir string, gameDepth types.Depth) *CannonTraceProviderForTest { + p := &CannonTraceProvider{ + logger: logger, + dir: dir, + prestate: cfg.CannonAbsolutePreState, + generator: NewExecutor(logger, m, cfg, localInputs), + gameDepth: gameDepth, + preimageLoader: newPreimageLoader(kvstore.NewDiskKV(preimageDir(dir)).Get), + } + return &CannonTraceProviderForTest{p} +} + +func (p *CannonTraceProviderForTest) FindStep(ctx context.Context, start uint64, preimage PreimageOpt) (uint64, error) { + // Run cannon to find the step that meets the preimage conditions + if err := p.generator.(*Executor).generateProof(ctx, p.dir, start, math.MaxUint64, preimage()...); err != nil { + return 0, fmt.Errorf("generate cannon trace (until preimage read): %w", err) + } + // Load the step from the state cannon finished with + state, err := p.finalState() + if err != nil { + return 0, fmt.Errorf("failed to load final state: %w", err) + } + // Check we didn't get to the end of the trace without finding the preimage read we were looking for + if state.Exited { + return 0, fmt.Errorf("preimage read not found: %w", io.EOF) + } + // The state is the post-state so the step we want to execute to read the preimage is step - 1. + return state.Step - 1, nil +} diff --git a/op-challenger/game/fault/trace/cannon/provider_test.go b/op-challenger/game/fault/trace/cannon/provider_test.go index f6903e29a96a..a98b59adf6e8 100644 --- a/op-challenger/game/fault/trace/cannon/provider_test.go +++ b/op-challenger/game/fault/trace/cannon/provider_test.go @@ -84,9 +84,9 @@ func TestGetStepData(t *testing.T) { provider, generator := setupWithTestData(t, dataDir, prestate) value, proof, data, err := provider.GetStepData(context.Background(), PositionFromTraceIndex(provider, new(big.Int))) require.NoError(t, err) - expected := common.Hex2Bytes("b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f400000000000000000000000000000000000000000000000000000000000000000000000000") + expected := common.FromHex("b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f400000000000000000000000000000000000000000000000000000000000000000000000000") require.Equal(t, expected, value) - expectedProof := common.Hex2Bytes("08028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004") + expectedProof := common.FromHex("08028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004") require.Equal(t, expectedProof, proof) // TODO: Need to add some oracle data require.Nil(t, data) @@ -207,9 +207,9 @@ func TestGetStepData(t *testing.T) { provider, generator := setupWithTestData(t, dataDir, prestate) value, proof, data, err := provider.GetStepData(context.Background(), PositionFromTraceIndex(provider, big.NewInt(2))) require.NoError(t, err) - expected := common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc") + expected := common.FromHex("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc") require.Equal(t, expected, value) - expectedProof := common.Hex2Bytes("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd") + expectedProof := common.FromHex("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd") require.Equal(t, expectedProof, proof) require.Empty(t, generator.generated) require.Nil(t, data) @@ -235,7 +235,7 @@ func setupTestData(t *testing.T) (string, string) { func setupWithTestData(t *testing.T, dataDir string, prestate string) (*CannonTraceProvider, *stubGenerator) { generator := &stubGenerator{} return &CannonTraceProvider{ - logger: testlog.Logger(t, log.LvlInfo), + logger: testlog.Logger(t, log.LevelInfo), dir: dataDir, generator: generator, prestate: filepath.Join(dataDir, prestate), diff --git a/op-challenger/game/fault/trace/outputs/output_alphabet.go b/op-challenger/game/fault/trace/outputs/output_alphabet.go index 51361e868d33..22b0fc762f83 100644 --- a/op-challenger/game/fault/trace/outputs/output_alphabet.go +++ b/op-challenger/game/fault/trace/outputs/output_alphabet.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/split" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/metrics" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) @@ -18,11 +19,12 @@ func NewOutputAlphabetTraceAccessor( m metrics.Metricer, prestateProvider types.PrestateProvider, rollupClient OutputRollupClient, + l1Head eth.BlockID, splitDepth types.Depth, prestateBlock uint64, poststateBlock uint64, ) (*trace.Accessor, error) { - outputProvider := NewTraceProviderFromInputs(logger, prestateProvider, rollupClient, splitDepth, prestateBlock, poststateBlock) + outputProvider := NewTraceProvider(logger, prestateProvider, rollupClient, l1Head, splitDepth, prestateBlock, poststateBlock) alphabetCreator := func(ctx context.Context, localContext common.Hash, depth types.Depth, agreed contracts.Proposal, claimed contracts.Proposal) (types.TraceProvider, error) { provider := alphabet.NewTraceProvider(agreed.L2BlockNumber, depth) return provider, nil diff --git a/op-challenger/game/fault/trace/outputs/output_cannon.go b/op-challenger/game/fault/trace/outputs/output_cannon.go index f2a10de62cf1..03c2bfb902e5 100644 --- a/op-challenger/game/fault/trace/outputs/output_cannon.go +++ b/op-challenger/game/fault/trace/outputs/output_cannon.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/split" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/metrics" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) @@ -21,23 +22,23 @@ func NewOutputCannonTraceAccessor( m metrics.Metricer, cfg *config.Config, l2Client cannon.L2HeaderSource, - contract cannon.L1HeadSource, prestateProvider types.PrestateProvider, rollupClient OutputRollupClient, dir string, + l1Head eth.BlockID, splitDepth types.Depth, prestateBlock uint64, poststateBlock uint64, ) (*trace.Accessor, error) { - outputProvider := NewTraceProviderFromInputs(logger, prestateProvider, rollupClient, splitDepth, prestateBlock, poststateBlock) + outputProvider := NewTraceProvider(logger, prestateProvider, rollupClient, l1Head, splitDepth, prestateBlock, poststateBlock) cannonCreator := func(ctx context.Context, localContext common.Hash, depth types.Depth, agreed contracts.Proposal, claimed contracts.Proposal) (types.TraceProvider, error) { logger := logger.New("pre", agreed.OutputRoot, "post", claimed.OutputRoot, "localContext", localContext) subdir := filepath.Join(dir, localContext.Hex()) - localInputs, err := cannon.FetchLocalInputsFromProposals(ctx, contract, l2Client, agreed, claimed) + localInputs, err := cannon.FetchLocalInputsFromProposals(ctx, l1Head.Hash, l2Client, agreed, claimed) if err != nil { return nil, fmt.Errorf("failed to fetch cannon local inputs: %w", err) } - provider := cannon.NewTraceProvider(logger, m, cfg, localContext, localInputs, subdir, depth) + provider := cannon.NewTraceProvider(logger, m, cfg, localInputs, subdir, depth) return provider, nil } diff --git a/op-challenger/game/fault/trace/outputs/prestate.go b/op-challenger/game/fault/trace/outputs/prestate.go index 7ac2af757714..086cba796087 100644 --- a/op-challenger/game/fault/trace/outputs/prestate.go +++ b/op-challenger/game/fault/trace/outputs/prestate.go @@ -5,9 +5,7 @@ import ( "fmt" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" ) var _ types.PrestateProvider = (*OutputPrestateProvider)(nil) @@ -17,7 +15,7 @@ type OutputPrestateProvider struct { rollupClient OutputRollupClient } -func NewPrestateProvider(ctx context.Context, logger log.Logger, rollupClient OutputRollupClient, prestateBlock uint64) *OutputPrestateProvider { +func NewPrestateProvider(rollupClient OutputRollupClient, prestateBlock uint64) *OutputPrestateProvider { return &OutputPrestateProvider{ prestateBlock: prestateBlock, rollupClient: rollupClient, diff --git a/op-challenger/game/fault/trace/outputs/prestate_test.go b/op-challenger/game/fault/trace/outputs/prestate_test.go index 8884cb5c0bfe..0b497ee5e872 100644 --- a/op-challenger/game/fault/trace/outputs/prestate_test.go +++ b/op-challenger/game/fault/trace/outputs/prestate_test.go @@ -9,7 +9,7 @@ import ( ) func newOutputPrestateProvider(t *testing.T, prestateBlock uint64) (*OutputPrestateProvider, *stubRollupClient) { - rollupClient := stubRollupClient{ + rollupClient := &stubRollupClient{ outputs: map[uint64]*eth.OutputResponse{ prestateBlock: { OutputRoot: eth.Bytes32(prestateOutputRoot), @@ -23,9 +23,9 @@ func newOutputPrestateProvider(t *testing.T, prestateBlock uint64) (*OutputPrest }, } return &OutputPrestateProvider{ - rollupClient: &rollupClient, + rollupClient: rollupClient, prestateBlock: prestateBlock, - }, &rollupClient + }, rollupClient } func TestAbsolutePreStateCommitment(t *testing.T) { diff --git a/op-challenger/game/fault/trace/outputs/provider.go b/op-challenger/game/fault/trace/outputs/provider.go index 2f9723fc75ec..d2da7fd45a52 100644 --- a/op-challenger/game/fault/trace/outputs/provider.go +++ b/op-challenger/game/fault/trace/outputs/provider.go @@ -6,9 +6,7 @@ import ( "fmt" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" - "github.com/ethereum-optimism/optimism/op-service/dial" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) @@ -22,6 +20,7 @@ var _ types.TraceProvider = (*OutputTraceProvider)(nil) type OutputRollupClient interface { OutputAtBlock(ctx context.Context, blockNum uint64) (*eth.OutputResponse, error) + SafeHeadAtL1Block(ctx context.Context, l1BlockNum uint64) (*eth.SafeHeadResponse, error) } // OutputTraceProvider is a [types.TraceProvider] implementation that uses @@ -29,37 +28,33 @@ type OutputRollupClient interface { type OutputTraceProvider struct { types.PrestateProvider logger log.Logger - rollupClient OutputRollupClient + rollupProvider OutputRollupClient prestateBlock uint64 poststateBlock uint64 + l1Head eth.BlockID gameDepth types.Depth } -func NewTraceProvider(ctx context.Context, logger log.Logger, rollupRpc string, gameDepth types.Depth, prestateBlock, poststateBlock uint64) (*OutputTraceProvider, error) { - rollupClient, err := dial.DialRollupClientWithTimeout(ctx, dial.DefaultDialTimeout, logger, rollupRpc) - if err != nil { - return nil, err - } - prestateProvider := NewPrestateProvider(ctx, logger, rollupClient, prestateBlock) - return NewTraceProviderFromInputs(logger, prestateProvider, rollupClient, gameDepth, prestateBlock, poststateBlock), nil -} - -func NewTraceProviderFromInputs(logger log.Logger, prestateProvider types.PrestateProvider, rollupClient OutputRollupClient, gameDepth types.Depth, prestateBlock, poststateBlock uint64) *OutputTraceProvider { +func NewTraceProvider(logger log.Logger, prestateProvider types.PrestateProvider, rollupProvider OutputRollupClient, l1Head eth.BlockID, gameDepth types.Depth, prestateBlock, poststateBlock uint64) *OutputTraceProvider { return &OutputTraceProvider{ PrestateProvider: prestateProvider, logger: logger, - rollupClient: rollupClient, + rollupProvider: rollupProvider, prestateBlock: prestateBlock, poststateBlock: poststateBlock, + l1Head: l1Head, gameDepth: gameDepth, } } -func (o *OutputTraceProvider) BlockNumber(pos types.Position) (uint64, error) { +// ClaimedBlockNumber returns the block number for a position restricted only by the claimed L2 block number. +// The returned block number may be after the safe head reached by processing batch data up to the game's L1 head +func (o *OutputTraceProvider) ClaimedBlockNumber(pos types.Position) (uint64, error) { traceIndex := pos.TraceIndex(o.gameDepth) if !traceIndex.IsUint64() { return 0, fmt.Errorf("%w: %v", ErrIndexTooBig, traceIndex) } + outputBlock := traceIndex.Uint64() + o.prestateBlock + 1 if outputBlock > o.poststateBlock { outputBlock = o.poststateBlock @@ -67,8 +62,27 @@ func (o *OutputTraceProvider) BlockNumber(pos types.Position) (uint64, error) { return outputBlock, nil } +// HonestBlockNumber returns the block number for a position in the game restricted to the minimum of the claimed L2 +// block number or the safe head reached by processing batch data up to the game's L1 head. +// This is used when posting honest output roots to ensure that only roots supported by L1 data are posted +func (o *OutputTraceProvider) HonestBlockNumber(ctx context.Context, pos types.Position) (uint64, error) { + outputBlock, err := o.ClaimedBlockNumber(pos) + if err != nil { + return 0, err + } + resp, err := o.rollupProvider.SafeHeadAtL1Block(ctx, o.l1Head.Number) + if err != nil { + return 0, fmt.Errorf("failed to get safe head at L1 block %v: %w", o.l1Head, err) + } + maxSafeHead := resp.SafeHead.Number + if outputBlock > maxSafeHead { + outputBlock = maxSafeHead + } + return outputBlock, nil +} + func (o *OutputTraceProvider) Get(ctx context.Context, pos types.Position) (common.Hash, error) { - outputBlock, err := o.BlockNumber(pos) + outputBlock, err := o.HonestBlockNumber(ctx, pos) if err != nil { return common.Hash{}, err } @@ -81,9 +95,9 @@ func (o *OutputTraceProvider) GetStepData(_ context.Context, _ types.Position) ( } func (o *OutputTraceProvider) outputAtBlock(ctx context.Context, block uint64) (common.Hash, error) { - output, err := o.rollupClient.OutputAtBlock(ctx, block) + output, err := o.rollupProvider.OutputAtBlock(ctx, block) if err != nil { - return common.Hash{}, fmt.Errorf("failed to fetch output at block %v: %w", o.prestateBlock, err) + return common.Hash{}, fmt.Errorf("failed to fetch output at block %v: %w", block, err) } return common.Hash(output.OutputRoot), nil } diff --git a/op-challenger/game/fault/trace/outputs/provider_test.go b/op-challenger/game/fault/trace/outputs/provider_test.go index 67a8cd8c9d25..c4e154ff17c3 100644 --- a/op-challenger/game/fault/trace/outputs/provider_test.go +++ b/op-challenger/game/fault/trace/outputs/provider_test.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "math" "math/big" "testing" @@ -62,26 +63,74 @@ func TestGet(t *testing.T) { }) } -func TestGetBlockNumber(t *testing.T) { +func TestHonestBlockNumber(t *testing.T) { tests := []struct { - name string - pos types.Position - expected uint64 + name string + pos types.Position + expected uint64 + maxSafeHead uint64 }{ - {"FirstBlockAfterPrestate", types.NewPosition(gameDepth, big.NewInt(0)), prestateBlock + 1}, - {"PostStateBlock", types.NewPositionFromGIndex(big.NewInt(228)), poststateBlock}, - {"AfterPostStateBlock", types.NewPositionFromGIndex(big.NewInt(229)), poststateBlock}, - {"Root", types.NewPositionFromGIndex(big.NewInt(1)), poststateBlock}, - {"MiddleNode1", types.NewPosition(gameDepth-1, big.NewInt(2)), 106}, - {"MiddleNode2", types.NewPosition(gameDepth-1, big.NewInt(3)), 108}, - {"Leaf1", types.NewPosition(gameDepth, big.NewInt(1)), prestateBlock + 2}, - {"Leaf2", types.NewPosition(gameDepth, big.NewInt(2)), prestateBlock + 3}, + {"FirstBlockAfterPrestate", types.NewPosition(gameDepth, big.NewInt(0)), prestateBlock + 1, math.MaxUint64}, + {"PostStateBlock", types.NewPositionFromGIndex(big.NewInt(228)), poststateBlock, math.MaxUint64}, + {"AfterPostStateBlock", types.NewPositionFromGIndex(big.NewInt(229)), poststateBlock, math.MaxUint64}, + {"Root", types.NewPositionFromGIndex(big.NewInt(1)), poststateBlock, math.MaxUint64}, + {"MiddleNode1", types.NewPosition(gameDepth-1, big.NewInt(2)), 106, math.MaxUint64}, + {"MiddleNode2", types.NewPosition(gameDepth-1, big.NewInt(3)), 108, math.MaxUint64}, + {"Leaf1", types.NewPosition(gameDepth, big.NewInt(1)), prestateBlock + 2, math.MaxUint64}, + {"Leaf2", types.NewPosition(gameDepth, big.NewInt(2)), prestateBlock + 3, math.MaxUint64}, + + {"RestrictedHead-UnderLimit", types.NewPosition(gameDepth, big.NewInt(48)), prestateBlock + 49, prestateBlock + 50}, + {"RestrictedHead-EqualLimit", types.NewPosition(gameDepth, big.NewInt(49)), prestateBlock + 50, prestateBlock + 50}, + {"RestrictedHead-OverLimit", types.NewPosition(gameDepth, big.NewInt(50)), prestateBlock + 50, prestateBlock + 50}, + {"RestrictedHead-PastPostState", types.NewPosition(gameDepth, big.NewInt(1000)), prestateBlock + 50, prestateBlock + 50}, + } + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + provider, stubRollupClient := setupWithTestData(t, prestateBlock, poststateBlock) + stubRollupClient.maxSafeHead = test.maxSafeHead + actual, err := provider.HonestBlockNumber(context.Background(), test.pos) + require.NoError(t, err) + require.Equal(t, test.expected, actual) + }) + } + + t.Run("ErrorsTraceIndexOutOfBounds", func(t *testing.T) { + deepGame := types.Depth(164) + provider, _ := setupWithTestData(t, prestateBlock, poststateBlock, deepGame) + pos := types.NewPosition(0, big.NewInt(0)) + _, err := provider.HonestBlockNumber(context.Background(), pos) + require.ErrorIs(t, err, ErrIndexTooBig) + }) +} + +func TestClaimedBlockNumber(t *testing.T) { + tests := []struct { + name string + pos types.Position + expected uint64 + maxSafeHead uint64 + }{ + {"FirstBlockAfterPrestate", types.NewPosition(gameDepth, big.NewInt(0)), prestateBlock + 1, math.MaxUint64}, + {"PostStateBlock", types.NewPositionFromGIndex(big.NewInt(228)), poststateBlock, math.MaxUint64}, + {"AfterPostStateBlock", types.NewPositionFromGIndex(big.NewInt(229)), poststateBlock, math.MaxUint64}, + {"Root", types.NewPositionFromGIndex(big.NewInt(1)), poststateBlock, math.MaxUint64}, + {"MiddleNode1", types.NewPosition(gameDepth-1, big.NewInt(2)), 106, math.MaxUint64}, + {"MiddleNode2", types.NewPosition(gameDepth-1, big.NewInt(3)), 108, math.MaxUint64}, + {"Leaf1", types.NewPosition(gameDepth, big.NewInt(1)), prestateBlock + 2, math.MaxUint64}, + {"Leaf2", types.NewPosition(gameDepth, big.NewInt(2)), prestateBlock + 3, math.MaxUint64}, + + {"RestrictedHead-UnderLimit", types.NewPosition(gameDepth, big.NewInt(48)), prestateBlock + 49, prestateBlock + 50}, + {"RestrictedHead-EqualLimit", types.NewPosition(gameDepth, big.NewInt(49)), prestateBlock + 50, prestateBlock + 50}, + {"RestrictedHead-OverLimit", types.NewPosition(gameDepth, big.NewInt(50)), prestateBlock + 51, prestateBlock + 50}, + {"RestrictedHead-PastPostState", types.NewPosition(gameDepth, big.NewInt(300)), poststateBlock, prestateBlock + 50}, } for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { - provider, _ := setupWithTestData(t, prestateBlock, poststateBlock) - actual, err := provider.BlockNumber(test.pos) + provider, stubRollupClient := setupWithTestData(t, prestateBlock, poststateBlock) + stubRollupClient.maxSafeHead = test.maxSafeHead + actual, err := provider.ClaimedBlockNumber(test.pos) require.NoError(t, err) require.Equal(t, test.expected, actual) }) @@ -91,7 +140,7 @@ func TestGetBlockNumber(t *testing.T) { deepGame := types.Depth(164) provider, _ := setupWithTestData(t, prestateBlock, poststateBlock, deepGame) pos := types.NewPosition(0, big.NewInt(0)) - _, err := provider.BlockNumber(pos) + _, err := provider.ClaimedBlockNumber(pos) require.ErrorIs(t, err, ErrIndexTooBig) }) } @@ -103,7 +152,7 @@ func TestGetStepData(t *testing.T) { } func setupWithTestData(t *testing.T, prestateBlock, poststateBlock uint64, customGameDepth ...types.Depth) (*OutputTraceProvider, *stubRollupClient) { - rollupClient := stubRollupClient{ + rollupClient := &stubRollupClient{ outputs: map[uint64]*eth.OutputResponse{ prestateBlock: { OutputRoot: eth.Bytes32(prestateOutputRoot), @@ -115,23 +164,25 @@ func setupWithTestData(t *testing.T, prestateBlock, poststateBlock uint64, custo OutputRoot: eth.Bytes32(poststateOutputRoot), }, }, + maxSafeHead: math.MaxUint64, } inputGameDepth := gameDepth if len(customGameDepth) > 0 { inputGameDepth = customGameDepth[0] } return &OutputTraceProvider{ - logger: testlog.Logger(t, log.LvlInfo), - rollupClient: &rollupClient, + logger: testlog.Logger(t, log.LevelInfo), + rollupProvider: rollupClient, prestateBlock: prestateBlock, poststateBlock: poststateBlock, gameDepth: inputGameDepth, - }, &rollupClient + }, rollupClient } type stubRollupClient struct { errorsOnPrestateFetch bool outputs map[uint64]*eth.OutputResponse + maxSafeHead uint64 } func (s *stubRollupClient) OutputAtBlock(_ context.Context, blockNum uint64) (*eth.OutputResponse, error) { @@ -141,3 +192,12 @@ func (s *stubRollupClient) OutputAtBlock(_ context.Context, blockNum uint64) (*e } return output, nil } + +func (s *stubRollupClient) SafeHeadAtL1Block(_ context.Context, l1BlockNum uint64) (*eth.SafeHeadResponse, error) { + return ð.SafeHeadResponse{ + SafeHead: eth.BlockID{ + Number: s.maxSafeHead, + Hash: common.Hash{0x11}, + }, + }, nil +} diff --git a/op-challenger/game/fault/trace/outputs/split_adapter.go b/op-challenger/game/fault/trace/outputs/split_adapter.go index b87af2200993..2d77ec9e627a 100644 --- a/op-challenger/game/fault/trace/outputs/split_adapter.go +++ b/op-challenger/game/fault/trace/outputs/split_adapter.go @@ -16,42 +16,49 @@ type ProposalTraceProviderCreator func(ctx context.Context, localContext common. func OutputRootSplitAdapter(topProvider *OutputTraceProvider, creator ProposalTraceProviderCreator) split.ProviderCreator { return func(ctx context.Context, depth types.Depth, pre types.Claim, post types.Claim) (types.TraceProvider, error) { - localContext := createLocalContext(pre, post) - usePrestateBlock := pre == (types.Claim{}) - var agreed contracts.Proposal - if usePrestateBlock { - prestateRoot, err := topProvider.AbsolutePreStateCommitment(ctx) - if err != nil { - return nil, fmt.Errorf("failed to retrieve absolute prestate output root: %w", err) - } - agreed = contracts.Proposal{ - L2BlockNumber: new(big.Int).SetUint64(topProvider.prestateBlock), - OutputRoot: prestateRoot, - } - } else { - preBlockNum, err := topProvider.BlockNumber(pre.Position) - if err != nil { - return nil, fmt.Errorf("unable to calculate pre-claim block number: %w", err) - } - agreed = contracts.Proposal{ - L2BlockNumber: new(big.Int).SetUint64(preBlockNum), - OutputRoot: pre.Value, - } + localContext := CreateLocalContext(pre, post) + agreed, disputed, err := FetchProposals(ctx, topProvider, pre, post) + if err != nil { + return nil, err } - postBlockNum, err := topProvider.BlockNumber(post.Position) + return creator(ctx, localContext, depth, agreed, disputed) + } +} + +func FetchProposals(ctx context.Context, topProvider *OutputTraceProvider, pre types.Claim, post types.Claim) (contracts.Proposal, contracts.Proposal, error) { + usePrestateBlock := pre == (types.Claim{}) + var agreed contracts.Proposal + if usePrestateBlock { + prestateRoot, err := topProvider.AbsolutePreStateCommitment(ctx) if err != nil { - return nil, fmt.Errorf("unable to calculate post-claim block number: %w", err) + return contracts.Proposal{}, contracts.Proposal{}, fmt.Errorf("failed to retrieve absolute prestate output root: %w", err) } - claimed := contracts.Proposal{ - L2BlockNumber: new(big.Int).SetUint64(postBlockNum), - OutputRoot: post.Value, + agreed = contracts.Proposal{ + L2BlockNumber: new(big.Int).SetUint64(topProvider.prestateBlock), + OutputRoot: prestateRoot, } - - return creator(ctx, localContext, depth, agreed, claimed) + } else { + preBlockNum, err := topProvider.HonestBlockNumber(ctx, pre.Position) + if err != nil { + return contracts.Proposal{}, contracts.Proposal{}, fmt.Errorf("unable to calculate pre-claim block number: %w", err) + } + agreed = contracts.Proposal{ + L2BlockNumber: new(big.Int).SetUint64(preBlockNum), + OutputRoot: pre.Value, + } + } + postBlockNum, err := topProvider.ClaimedBlockNumber(post.Position) + if err != nil { + return contracts.Proposal{}, contracts.Proposal{}, fmt.Errorf("unable to calculate post-claim block number: %w", err) + } + claimed := contracts.Proposal{ + L2BlockNumber: new(big.Int).SetUint64(postBlockNum), + OutputRoot: post.Value, } + return agreed, claimed, nil } -func createLocalContext(pre types.Claim, post types.Claim) common.Hash { +func CreateLocalContext(pre types.Claim, post types.Claim) common.Hash { return crypto.Keccak256Hash(localContextPreimage(pre, post)) } diff --git a/op-challenger/game/fault/trace/outputs/split_adapter_test.go b/op-challenger/game/fault/trace/outputs/split_adapter_test.go index fe03035a5067..8eabc520def7 100644 --- a/op-challenger/game/fault/trace/outputs/split_adapter_test.go +++ b/op-challenger/game/fault/trace/outputs/split_adapter_test.go @@ -84,7 +84,7 @@ func TestOutputRootSplitAdapter(t *testing.T) { _, err := adapter(context.Background(), 5, preClaim, postClaim) require.ErrorIs(t, err, creatorError) - require.Equal(t, createLocalContext(preClaim, postClaim), creator.localContext) + require.Equal(t, CreateLocalContext(preClaim, postClaim), creator.localContext) require.Equal(t, expectedAgreed, creator.agreed) require.Equal(t, expectedClaimed, creator.claimed) }) @@ -115,7 +115,7 @@ func TestOutputRootSplitAdapter_FromAbsolutePrestate(t *testing.T) { _, err := adapter(context.Background(), 5, types.Claim{}, postClaim) require.ErrorIs(t, err, creatorError) - require.Equal(t, createLocalContext(types.Claim{}, postClaim), creator.localContext) + require.Equal(t, CreateLocalContext(types.Claim{}, postClaim), creator.localContext) require.Equal(t, expectedAgreed, creator.agreed) require.Equal(t, expectedClaimed, creator.claimed) } @@ -124,17 +124,22 @@ func setupAdapterTest(t *testing.T, topDepth types.Depth) (split.ProviderCreator prestateBlock := uint64(20) poststateBlock := uint64(40) creator := &capturingCreator{} + l1Head := eth.BlockID{ + Hash: common.Hash{0x11, 0x11}, + Number: 11, + } rollupClient := &stubRollupClient{ outputs: map[uint64]*eth.OutputResponse{ prestateBlock: { OutputRoot: eth.Bytes32(prestateOutputRoot), }, }, + maxSafeHead: math.MaxUint64, } prestateProvider := &stubPrestateProvider{ absolutePrestate: prestateOutputRoot, } - topProvider := NewTraceProviderFromInputs(testlog.Logger(t, log.LvlInfo), prestateProvider, rollupClient, topDepth, prestateBlock, poststateBlock) + topProvider := NewTraceProvider(testlog.Logger(t, log.LevelInfo), prestateProvider, rollupClient, l1Head, topDepth, prestateBlock, poststateBlock) adapter := OutputRootSplitAdapter(topProvider, creator.Create) return adapter, creator } @@ -167,15 +172,15 @@ func TestCreateLocalContext(t *testing.T) { prePosition: types.NewPositionFromGIndex(big.NewInt(2)), postValue: common.HexToHash("cc00000000000000000000000000000000000000000000000000000000000000"), postPosition: types.NewPositionFromGIndex(big.NewInt(3)), - expected: common.Hex2Bytes("abcdef0123456789abcdef0123456789abcdef0123456789abcdef01234567890000000000000000000000000000000000000000000000000000000000000002cc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"), + expected: common.FromHex("abcdef0123456789abcdef0123456789abcdef0123456789abcdef01234567890000000000000000000000000000000000000000000000000000000000000002cc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"), }, { name: "LargePositions", preValue: common.HexToHash("abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"), - prePosition: types.NewPositionFromGIndex(new(big.Int).SetBytes(common.Hex2Bytes("cbcdef0123456789abcdef0123456789abcdef0123456789abcdef012345678c"))), + prePosition: types.NewPositionFromGIndex(new(big.Int).SetBytes(common.FromHex("cbcdef0123456789abcdef0123456789abcdef0123456789abcdef012345678c"))), postValue: common.HexToHash("dd00000000000000000000000000000000000000000000000000000000000000"), postPosition: types.NewPositionFromGIndex(new(big.Int).SetUint64(math.MaxUint64)), - expected: common.Hex2Bytes("abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789cbcdef0123456789abcdef0123456789abcdef0123456789abcdef012345678cdd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff"), + expected: common.FromHex("abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789cbcdef0123456789abcdef0123456789abcdef0123456789abcdef012345678cdd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff"), }, { name: "AbsolutePreState", @@ -183,7 +188,7 @@ func TestCreateLocalContext(t *testing.T) { prePosition: types.Position{}, postValue: common.HexToHash("cc00000000000000000000000000000000000000000000000000000000000000"), postPosition: types.NewPositionFromGIndex(big.NewInt(3)), - expected: common.Hex2Bytes("cc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"), + expected: common.FromHex("cc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"), }, } @@ -204,7 +209,7 @@ func TestCreateLocalContext(t *testing.T) { } actualPreimage := localContextPreimage(pre, post) require.Equal(t, test.expected, actualPreimage) - localContext := createLocalContext(pre, post) + localContext := CreateLocalContext(pre, post) require.Equal(t, crypto.Keccak256Hash(test.expected), localContext) }) } diff --git a/op-challenger/game/fault/trace/split/split_test.go b/op-challenger/game/fault/trace/split/split_test.go index 577939e6b414..fb47932455d0 100644 --- a/op-challenger/game/fault/trace/split/split_test.go +++ b/op-challenger/game/fault/trace/split/split_test.go @@ -147,12 +147,12 @@ func TestBottomProviderAttackingTopLeaf(t *testing.T) { // If the ref is the leaf of the top claim, ensure we respect whether the test is setup // to attack or defend the top leaf claim. if ref.Depth() != splitDepth || !pos.RightOf(ref.Position) { - gameBuilder.SeqFrom(ref).AttackCorrect() + gameBuilder.SeqFrom(ref).Attack() attackRef := latestClaim(gameBuilder) testDescendantClaims(attackRef, attackRef.Position) } if ref.Depth() != splitDepth || pos.RightOf(ref.Position) { - gameBuilder.SeqFrom(ref).DefendCorrect() + gameBuilder.SeqFrom(ref).Defend() defendRef := latestClaim(gameBuilder) testDescendantClaims(defendRef, defendRef.Position) } @@ -164,10 +164,10 @@ func TestBottomProviderAttackingTopLeaf(t *testing.T) { func attackTopLeafGIndex8(_ *testing.T, gameBuilder *test.GameBuilder) (ref types.Claim, pos types.Position, expectPre types.Claim, expectPost types.Claim) { // Generate claims down to the top provider's leaf - seq := gameBuilder.Seq() // gindex 1, trace 7 - seq = seq.AttackCorrect() // gindex 2, trace 3 - seq = seq.AttackCorrect() // gindex 4, trace 1 - seq.AttackCorrect() // gindex 8, trace 0 + seq := gameBuilder.Seq() // gindex 1, trace 7 + seq = seq.Attack() // gindex 2, trace 3 + seq = seq.Attack() // gindex 4, trace 1 + seq.Attack() // gindex 8, trace 0 expectPost = latestClaim(gameBuilder) // No pre-claim as the first output root is being challenged. @@ -180,11 +180,11 @@ func attackTopLeafGIndex8(_ *testing.T, gameBuilder *test.GameBuilder) (ref type func defendTopLeafGIndex8(_ *testing.T, gameBuilder *test.GameBuilder) (ref types.Claim, pos types.Position, expectPre types.Claim, expectPost types.Claim) { // Generate claims down to the top provider's leaf - seq := gameBuilder.Seq() // gindex 1, trace 7 - seq = seq.AttackCorrect() // gindex 2, trace 3 - seq = seq.AttackCorrect() // gindex 4, trace 1 + seq := gameBuilder.Seq() // gindex 1, trace 7 + seq = seq.Attack() // gindex 2, trace 3 + seq = seq.Attack() // gindex 4, trace 1 expectPost = latestClaim(gameBuilder) - seq.AttackCorrect() // gindex 8, trace 0 + seq.Attack() // gindex 8, trace 0 expectPre = latestClaim(gameBuilder) ref = latestClaim(gameBuilder) @@ -193,11 +193,11 @@ func defendTopLeafGIndex8(_ *testing.T, gameBuilder *test.GameBuilder) (ref type } func attackTopLeafGIndex10(_ *testing.T, gameBuilder *test.GameBuilder) (ref types.Claim, pos types.Position, expectPre types.Claim, expectPost types.Claim) { - seq := gameBuilder.Seq() // gindex 1, trace 7 - seq = seq.AttackCorrect() // gindex 2, trace 3 - seq = seq.AttackCorrect() // gindex 4, trace 1 + seq := gameBuilder.Seq() // gindex 1, trace 7 + seq = seq.Attack() // gindex 2, trace 3 + seq = seq.Attack() // gindex 4, trace 1 expectPre = latestClaim(gameBuilder) - seq.DefendCorrect() // gindex 10, trace 2 + seq.Defend() // gindex 10, trace 2 expectPost = latestClaim(gameBuilder) ref = latestClaim(gameBuilder) @@ -206,11 +206,11 @@ func attackTopLeafGIndex10(_ *testing.T, gameBuilder *test.GameBuilder) (ref typ } func defendTopLeafGIndex10(_ *testing.T, gameBuilder *test.GameBuilder) (ref types.Claim, pos types.Position, expectPre types.Claim, expectPost types.Claim) { - seq := gameBuilder.Seq() // gindex 1, trace 7 - seq = seq.AttackCorrect() // gindex 2, trace 3 + seq := gameBuilder.Seq() // gindex 1, trace 7 + seq = seq.Attack() // gindex 2, trace 3 expectPost = latestClaim(gameBuilder) - seq = seq.AttackCorrect() // gindex 4, trace 1 - seq.DefendCorrect() // gindex 10, trace 2 + seq = seq.Attack() // gindex 4, trace 1 + seq.Defend() // gindex 10, trace 2 expectPre = latestClaim(gameBuilder) ref = latestClaim(gameBuilder) @@ -219,11 +219,11 @@ func defendTopLeafGIndex10(_ *testing.T, gameBuilder *test.GameBuilder) (ref typ } func attackTopLeafGIndex12(_ *testing.T, gameBuilder *test.GameBuilder) (ref types.Claim, pos types.Position, expectPre types.Claim, expectPost types.Claim) { - seq := gameBuilder.Seq() // gindex 1, trace 7 - seq = seq.AttackCorrect() // gindex 2, trace 3 + seq := gameBuilder.Seq() // gindex 1, trace 7 + seq = seq.Attack() // gindex 2, trace 3 expectPre = latestClaim(gameBuilder) - seq = seq.DefendCorrect() // gindex 6, trace 5 - seq.AttackCorrect() // gindex 12, trace 4 + seq = seq.Defend() // gindex 6, trace 5 + seq.Attack() // gindex 12, trace 4 expectPost = latestClaim(gameBuilder) ref = latestClaim(gameBuilder) @@ -232,11 +232,11 @@ func attackTopLeafGIndex12(_ *testing.T, gameBuilder *test.GameBuilder) (ref typ } func defendTopLeafGIndex12(_ *testing.T, gameBuilder *test.GameBuilder) (ref types.Claim, pos types.Position, expectPre types.Claim, expectPost types.Claim) { - seq := gameBuilder.Seq() // gindex 1, trace 7 - seq = seq.AttackCorrect() // gindex 2, trace 3 - seq = seq.DefendCorrect() // gindex 6, trace 5 + seq := gameBuilder.Seq() // gindex 1, trace 7 + seq = seq.Attack() // gindex 2, trace 3 + seq = seq.Defend() // gindex 6, trace 5 expectPost = latestClaim(gameBuilder) - seq.AttackCorrect() // gindex 12, trace 4 + seq.Attack() // gindex 12, trace 4 expectPre = latestClaim(gameBuilder) ref = latestClaim(gameBuilder) @@ -245,11 +245,11 @@ func defendTopLeafGIndex12(_ *testing.T, gameBuilder *test.GameBuilder) (ref typ } func attackTopLeafGIndex14(_ *testing.T, gameBuilder *test.GameBuilder) (ref types.Claim, pos types.Position, expectPre types.Claim, expectPost types.Claim) { - seq := gameBuilder.Seq() // gindex 1, trace 7 - seq = seq.AttackCorrect() // gindex 2, trace 3 - seq = seq.DefendCorrect() // gindex 6, trace 5 + seq := gameBuilder.Seq() // gindex 1, trace 7 + seq = seq.Attack() // gindex 2, trace 3 + seq = seq.Defend() // gindex 6, trace 5 expectPre = latestClaim(gameBuilder) - seq.DefendCorrect() // gindex 14, trace 6 + seq.Defend() // gindex 14, trace 6 expectPost = latestClaim(gameBuilder) ref = latestClaim(gameBuilder) @@ -260,9 +260,9 @@ func attackTopLeafGIndex14(_ *testing.T, gameBuilder *test.GameBuilder) (ref typ func defendTopLeafGIndex14(_ *testing.T, gameBuilder *test.GameBuilder) (ref types.Claim, pos types.Position, expectPre types.Claim, expectPost types.Claim) { seq := gameBuilder.Seq() // gindex 1, trace 7 expectPost = latestClaim(gameBuilder) - seq = seq.AttackCorrect() // gindex 2, trace 3 - seq = seq.DefendCorrect() // gindex 6, trace 5 - seq.DefendCorrect() // gindex 14, trace 6 + seq = seq.Attack() // gindex 2, trace 3 + seq = seq.Defend() // gindex 6, trace 5 + seq.Defend() // gindex 14, trace 6 expectPre = latestClaim(gameBuilder) ref = latestClaim(gameBuilder) @@ -277,7 +277,7 @@ func latestClaim(gameBuilder *test.GameBuilder) types.Claim { func createClaimsToDepth(gameBuilder *test.GameBuilder, depth int) { seq := gameBuilder.Seq() for i := 0; i < depth; i++ { - seq = seq.AttackCorrect() + seq = seq.Attack() } } @@ -314,7 +314,7 @@ func setupAlphabetSplitSelector(t *testing.T) (*alphabet.AlphabetTraceProvider, selector := NewSplitProviderSelector(top, splitDepth, bottomCreator) claimBuilder := test.NewAlphabetClaimBuilder(t, big.NewInt(0), gameDepth) - gameBuilder := claimBuilder.GameBuilder(true) + gameBuilder := claimBuilder.GameBuilder() return top, selector, gameBuilder } diff --git a/op-challenger/game/fault/types/game.go b/op-challenger/game/fault/types/game.go index 1fe2d67e55be..20bd6e2bff00 100644 --- a/op-challenger/game/fault/types/game.go +++ b/op-challenger/game/fault/types/game.go @@ -3,9 +3,6 @@ package types import ( "errors" "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" ) var ( @@ -33,16 +30,10 @@ type Game interface { AgreeWithClaimLevel(claim Claim, agreeWithRootClaim bool) bool MaxDepth() Depth -} - -type claimID common.Hash -func computeClaimID(claim Claim) claimID { - return claimID(crypto.Keccak256Hash( - claim.Position.ToGIndex().Bytes(), - claim.Value.Bytes(), - big.NewInt(int64(claim.ParentContractIndex)).Bytes(), - )) + // AncestorWithTraceIndex finds the ancestor of claim with trace index idx if present. + // Returns the claim and true if the ancestor is found, or Claim{}, false if not. + AncestorWithTraceIndex(claim Claim, idx *big.Int) (Claim, bool) } // gameState is a struct that represents the state of a dispute game. @@ -50,16 +41,16 @@ func computeClaimID(claim Claim) claimID { type gameState struct { // claims is the list of claims in the same order as the contract claims []Claim - claimIDs map[claimID]bool + claimIDs map[ClaimID]bool depth Depth } // NewGameState returns a new game state. // The provided [Claim] is used as the root node. func NewGameState(claims []Claim, depth Depth) *gameState { - claimIDs := make(map[claimID]bool) + claimIDs := make(map[ClaimID]bool) for _, claim := range claims { - claimIDs[computeClaimID(claim)] = true + claimIDs[claim.ID()] = true } return &gameState{ claims: claims, @@ -81,7 +72,7 @@ func (g *gameState) AgreeWithClaimLevel(claim Claim, agreeWithRootClaim bool) bo } func (g *gameState) IsDuplicate(claim Claim) bool { - return g.claimIDs[computeClaimID(claim)] + return g.claimIDs[claim.ID()] } func (g *gameState) Claims() []Claim { @@ -119,3 +110,19 @@ func (g *gameState) getParent(claim Claim) *Claim { parent := g.claims[claim.ParentContractIndex] return &parent } + +func (g *gameState) AncestorWithTraceIndex(claim Claim, idx *big.Int) (Claim, bool) { + for { + if claim.Position.TraceIndex(g.depth).Cmp(idx) == 0 { + return claim, true + } + if claim.IsRoot() { + return Claim{}, false + } + next := g.getParent(claim) + if next == nil { + return Claim{}, false + } + claim = *next + } +} diff --git a/op-challenger/game/fault/types/game_test.go b/op-challenger/game/fault/types/game_test.go index 4d16dc0b0562..cad4b5c856bd 100644 --- a/op-challenger/game/fault/types/game_test.go +++ b/op-challenger/game/fault/types/game_test.go @@ -131,6 +131,92 @@ func TestGame_DefendsParent(t *testing.T) { } } +func TestAncestorWithTraceIndex(t *testing.T) { + depth := Depth(4) + claims := []Claim{ + { + ClaimData: ClaimData{ + Position: NewPositionFromGIndex(big.NewInt(0)), + }, + ContractIndex: 0, + ParentContractIndex: 0, + }, + } + addClaimAtPos := func(parent Claim, pos Position) Claim { + claim := Claim{ + ClaimData: ClaimData{ + Position: pos, + }, + ParentContractIndex: parent.ContractIndex, + ContractIndex: len(claims), + } + claims = append(claims, claim) + return claim + } + attack := func(claim Claim) Claim { + return addClaimAtPos(claim, claim.Position.Attack()) + } + defend := func(claim Claim) Claim { + return addClaimAtPos(claim, claim.Position.Defend()) + } + // Create a variety of paths to leaf nodes + attack(attack(attack(attack(claims[0])))) + defend(defend(defend(defend(claims[0])))) + defend(attack(defend(attack(claims[0])))) + attack(defend(attack(defend(claims[0])))) + attack(attack(defend(defend(claims[0])))) + defend(defend(attack(attack(claims[0])))) + + game := NewGameState(claims, depth) + // Every claim should be able to find the root's trace index + for _, claim := range claims { + actual, ok := game.AncestorWithTraceIndex(claim, claims[0].TraceIndex(depth)) + require.True(t, ok) + require.Equal(t, claims[0], actual) + } + + // Leaf claims should be able to find the trace index before and after + for _, claim := range game.Claims() { + if claim.Depth() != depth { + // Only leaf nodes are guaranteed to have the pre and post states available + continue + } + claimIdx := claim.TraceIndex(depth) + + actual, ok := game.AncestorWithTraceIndex(claim, claimIdx) + require.True(t, ok) + require.Equal(t, claim, actual, "Should get leaf claim for its own trace index") + + // The right most claim doesn't have + if claim.IndexAtDepth().Cmp(big.NewInt(30)) < 0 { + idx := new(big.Int).Add(claimIdx, big.NewInt(1)) + actual, ok = game.AncestorWithTraceIndex(claim, idx) + require.Truef(t, ok, "Should find claim with next trace index for claim %v index at depth %v", claim.ContractIndex, claim.IndexAtDepth()) + require.Equalf(t, idx, actual.TraceIndex(depth), "Should find claim with next trace index for claim %v index at depth %v", claim.ContractIndex, claim.IndexAtDepth()) + } + + if claimIdx.Cmp(big.NewInt(0)) == 0 { + continue + } + idx := new(big.Int).Sub(claimIdx, big.NewInt(1)) + actual, ok = game.AncestorWithTraceIndex(claim, idx) + require.True(t, ok) + require.Equal(t, idx, actual.TraceIndex(depth), "Should find claim with previous trace index") + } + + actual, ok := game.AncestorWithTraceIndex(claims[0], big.NewInt(0)) + require.False(t, ok) + require.Equal(t, Claim{}, actual) + + actual, ok = game.AncestorWithTraceIndex(claims[1], big.NewInt(1)) + require.False(t, ok) + require.Equal(t, Claim{}, actual) + + actual, ok = game.AncestorWithTraceIndex(claims[3], big.NewInt(1)) + require.True(t, ok) + require.Equal(t, claims[3], actual) +} + func buildGameWithClaim(claimGIndex *big.Int, parentGIndex *big.Int) *gameState { parentClaim := Claim{ ClaimData: ClaimData{ diff --git a/op-challenger/game/fault/types/types.go b/op-challenger/game/fault/types/types.go index 613b08f38da6..2e3d2c42f391 100644 --- a/op-challenger/game/fault/types/types.go +++ b/op-challenger/game/fault/types/types.go @@ -4,25 +4,39 @@ import ( "context" "errors" "math/big" + "time" + preimage "github.com/ethereum-optimism/optimism/op-preimage" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" ) var ( ErrGameDepthReached = errors.New("game depth reached") +) - // NoLocalContext is the LocalContext value used when the cannon trace provider is used alone instead of as part - // of a split game. - NoLocalContext = common.Hash{} +const ( + CannonGameType uint32 = 0 + PermissionedGameType uint32 = 1 + AlphabetGameType uint32 = 255 ) +type ClockReader interface { + Now() time.Time +} + // PreimageOracleData encapsulates the preimage oracle data // to load into the onchain oracle. type PreimageOracleData struct { IsLocal bool OracleKey []byte - OracleData []byte + oracleData []byte OracleOffset uint32 + + // 4844 blob data + BlobFieldIndex uint64 + BlobCommitment []byte + BlobProof []byte } // GetIdent returns the ident for the preimage oracle data. @@ -32,19 +46,44 @@ func (p *PreimageOracleData) GetIdent() *big.Int { // GetPreimageWithoutSize returns the preimage for the preimage oracle data. func (p *PreimageOracleData) GetPreimageWithoutSize() []byte { - return p.OracleData[8:] + return p.oracleData[8:] +} + +// GetPreimageWithSize returns the preimage with its length prefix. +func (p *PreimageOracleData) GetPreimageWithSize() []byte { + return p.oracleData +} + +func (p *PreimageOracleData) GetPrecompileAddress() common.Address { + return common.BytesToAddress(p.oracleData[8:28]) +} + +func (p *PreimageOracleData) GetPrecompileInput() []byte { + return p.oracleData[28:] } // NewPreimageOracleData creates a new [PreimageOracleData] instance. func NewPreimageOracleData(key []byte, data []byte, offset uint32) *PreimageOracleData { return &PreimageOracleData{ - IsLocal: len(key) > 0 && key[0] == byte(1), + IsLocal: len(key) > 0 && key[0] == byte(preimage.LocalKeyType), OracleKey: key, - OracleData: data, + oracleData: data, OracleOffset: offset, } } +func NewPreimageOracleBlobData(key []byte, data []byte, offset uint32, fieldIndex uint64, commitment []byte, proof []byte) *PreimageOracleData { + return &PreimageOracleData{ + IsLocal: false, + OracleKey: key, + oracleData: data, + OracleOffset: offset, + BlobFieldIndex: fieldIndex, + BlobCommitment: commitment, + BlobProof: proof, + } +} + // StepCallData encapsulates the data needed to perform a step. type StepCallData struct { ClaimIndex uint64 @@ -100,6 +139,8 @@ func (c *ClaimData) ValueBytes() [32]byte { return responseArr } +type ClaimID common.Hash + // Claim extends ClaimData with information about the relationship between two claims. // It uses ClaimData to break cyclicity without using pointers. // If the position of the game is Depth 0, IndexAtDepth 0 it is the root claim @@ -112,14 +153,54 @@ type Claim struct { // to be changed/removed to avoid invalid/stale contract state. CounteredBy common.Address Claimant common.Address - Clock uint64 + Clock *Clock // Location of the claim & it's parent inside the contract. Does not exist // for claims that have not made it to the contract. ContractIndex int ParentContractIndex int } +func (c Claim) ID() ClaimID { + return ClaimID(crypto.Keccak256Hash( + c.Position.ToGIndex().Bytes(), + c.Value.Bytes(), + big.NewInt(int64(c.ParentContractIndex)).Bytes(), + )) +} + // IsRoot returns true if this claim is the root claim. func (c *Claim) IsRoot() bool { return c.Position.IsRootPosition() } + +// ChessTime returns the amount of time accumulated in the chess clock. +// Does not assume the claim is countered and uses the specified time +// to calculate the time since the claim was posted. +func (c *Claim) ChessTime(now time.Time) time.Duration { + timeSince := int64(0) + if now.Unix() > int64(c.Clock.Timestamp) { + timeSince = now.Unix() - int64(c.Clock.Timestamp) + } + return time.Duration(c.Clock.Duration) + time.Duration(timeSince) +} + +// Clock is a packed uint128 with the upper 64 bits being the +// duration and the lower 64 bits being the timestamp. +// ┌────────────┬────────────────┐ +// │ Bits │ Value │ +// ├────────────┼────────────────┤ +// │ [0, 64) │ Duration │ +// │ [64, 128) │ Timestamp │ +// └────────────┴────────────────┘ +type Clock struct { + Duration uint64 + Timestamp uint64 +} + +// NewClock creates a new Clock instance. +func NewClock(duration uint64, timestamp uint64) *Clock { + return &Clock{ + Duration: duration, + Timestamp: timestamp, + } +} diff --git a/op-challenger/game/fault/types/types_test.go b/op-challenger/game/fault/types/types_test.go index 378a684f97d0..8ea40ab67790 100644 --- a/op-challenger/game/fault/types/types_test.go +++ b/op-challenger/game/fault/types/types_test.go @@ -3,16 +3,73 @@ package types import ( "math/big" "testing" + "time" "github.com/stretchr/testify/require" ) +func TestClaim_RemainingDuration(t *testing.T) { + tests := []struct { + name string + duration uint64 + timestamp uint64 + now int64 + expected uint64 + }{ + { + name: "AllZeros", + duration: 0, + timestamp: 0, + now: 0, + expected: 0, + }, + { + name: "ZeroTimestamp", + duration: 5, + timestamp: 0, + now: 0, + expected: 5, + }, + { + name: "ZeroTimestampWithNow", + duration: 5, + timestamp: 0, + now: 10, + expected: 15, + }, + { + name: "ZeroNow", + duration: 5, + timestamp: 10, + now: 0, + expected: 5, + }, + { + name: "ValidTimeSinze", + duration: 20, + timestamp: 10, + now: 15, + expected: 25, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + claim := &Claim{ + Clock: NewClock(test.duration, test.timestamp), + } + require.Equal(t, time.Duration(test.expected), claim.ChessTime(time.Unix(test.now, 0))) + }) + } +} + func TestNewPreimageOracleData(t *testing.T) { t.Run("LocalData", func(t *testing.T) { data := NewPreimageOracleData([]byte{1, 2, 3}, []byte{4, 5, 6}, 7) require.True(t, data.IsLocal) require.Equal(t, []byte{1, 2, 3}, data.OracleKey) - require.Equal(t, []byte{4, 5, 6}, data.OracleData) + require.Equal(t, []byte{4, 5, 6}, data.GetPreimageWithSize()) require.Equal(t, uint32(7), data.OracleOffset) }) @@ -20,7 +77,7 @@ func TestNewPreimageOracleData(t *testing.T) { data := NewPreimageOracleData([]byte{0, 2, 3}, []byte{4, 5, 6}, 7) require.False(t, data.IsLocal) require.Equal(t, []byte{0, 2, 3}, data.OracleKey) - require.Equal(t, []byte{4, 5, 6}, data.OracleData) + require.Equal(t, []byte{4, 5, 6}, data.GetPreimageWithSize()) require.Equal(t, uint32(7), data.OracleOffset) }) } diff --git a/op-challenger/game/fault/validator.go b/op-challenger/game/fault/validator.go index e59648065cc2..93d9d3dca461 100644 --- a/op-challenger/game/fault/validator.go +++ b/op-challenger/game/fault/validator.go @@ -5,6 +5,7 @@ import ( "context" "fmt" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" @@ -19,14 +20,16 @@ type Validator interface { var _ Validator = (*PrestateValidator)(nil) type PrestateValidator struct { - load PrestateLoader - provider types.PrestateProvider + valueName string + load PrestateLoader + provider types.PrestateProvider } -func NewPrestateValidator(loader PrestateLoader, provider types.PrestateProvider) *PrestateValidator { +func NewPrestateValidator(valueName string, contractProvider PrestateLoader, localProvider types.PrestateProvider) *PrestateValidator { return &PrestateValidator{ - load: loader, - provider: provider, + valueName: valueName, + load: contractProvider, + provider: localProvider, } } @@ -40,7 +43,8 @@ func (v *PrestateValidator) Validate(ctx context.Context) error { return fmt.Errorf("failed to fetch provider's prestate hash: %w", err) } if !bytes.Equal(prestateCommitment[:], prestateHash[:]) { - return fmt.Errorf("provider's absolute prestate does not match contract's absolute prestate: Provider: %s | Contract: %s", prestateCommitment.Hex(), prestateHash.Hex()) + return fmt.Errorf("%v %w: Provider: %s | Contract: %s", + v.valueName, gameTypes.ErrInvalidPrestate, prestateCommitment.Hex(), prestateHash.Hex()) } return nil } diff --git a/op-challenger/game/fault/validator_test.go b/op-challenger/game/fault/validator_test.go index 3cc16bf02994..6782e2651b46 100644 --- a/op-challenger/game/fault/validator_test.go +++ b/op-challenger/game/fault/validator_test.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" @@ -54,7 +55,7 @@ func TestValidate(t *testing.T) { provider: newMockPrestateProvider(false, prestate), } err := player.Validate(context.Background()) - require.Error(t, err) + require.ErrorIs(t, err, gameTypes.ErrInvalidPrestate) }) } @@ -72,7 +73,7 @@ func newMockPrestateProvider(prestateErrors bool, prestate []byte) *mockPrestate } } -func (m *mockPrestateProvider) AbsolutePreStateCommitment(ctx context.Context) (common.Hash, error) { +func (m *mockPrestateProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) { if m.prestateErrors { return common.Hash{}, mockProviderError } diff --git a/op-challenger/game/keccak/challenger.go b/op-challenger/game/keccak/challenger.go new file mode 100644 index 000000000000..362c432e3150 --- /dev/null +++ b/op-challenger/game/keccak/challenger.go @@ -0,0 +1,91 @@ +package keccak + +import ( + "context" + "errors" + "fmt" + "sync" + + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/matrix" + keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" +) + +type Oracle interface { + VerifierPreimageOracle + ChallengeTx(ident keccakTypes.LargePreimageIdent, challenge keccakTypes.Challenge) (txmgr.TxCandidate, error) +} + +type ChallengeMetrics interface { + RecordPreimageChallenged() + RecordPreimageChallengeFailed() +} + +type Verifier interface { + CreateChallenge(ctx context.Context, blockHash common.Hash, oracle VerifierPreimageOracle, preimage keccakTypes.LargePreimageMetaData) (keccakTypes.Challenge, error) +} + +type Sender interface { + SendAndWait(txPurpose string, txs ...txmgr.TxCandidate) ([]*types.Receipt, error) +} + +type PreimageChallenger struct { + log log.Logger + metrics ChallengeMetrics + verifier Verifier + sender Sender +} + +func NewPreimageChallenger(logger log.Logger, metrics ChallengeMetrics, verifier Verifier, sender Sender) *PreimageChallenger { + return &PreimageChallenger{ + log: logger, + metrics: metrics, + verifier: verifier, + sender: sender, + } +} + +func (c *PreimageChallenger) Challenge(ctx context.Context, blockHash common.Hash, oracle Oracle, preimages []keccakTypes.LargePreimageMetaData) error { + var txLock sync.Mutex + var wg sync.WaitGroup + var txs []txmgr.TxCandidate + for _, preimage := range preimages { + preimage := preimage + wg.Add(1) + go func() { + defer wg.Done() + logger := c.log.New("oracle", oracle.Addr(), "claimant", preimage.Claimant, "uuid", preimage.UUID) + challenge, err := c.verifier.CreateChallenge(ctx, blockHash, oracle, preimage) + if errors.Is(err, matrix.ErrValid) { + logger.Debug("Preimage is valid") + return + } else if err != nil { + logger.Error("Failed to verify large preimage", "err", err) + return + } + logger.Info("Challenging preimage", "block", challenge.Poststate.Index) + tx, err := oracle.ChallengeTx(preimage.LargePreimageIdent, challenge) + if err != nil { + logger.Error("Failed to create challenge transaction", "err", err) + return + } + txLock.Lock() + defer txLock.Unlock() + txs = append(txs, tx) + }() + } + wg.Wait() + c.log.Debug("Created preimage challenge transactions", "count", len(txs)) + if len(txs) > 0 { + _, err := c.sender.SendAndWait("challenge preimages", txs...) + if err != nil { + c.metrics.RecordPreimageChallengeFailed() + return fmt.Errorf("failed to send challenge txs: %w", err) + } + c.metrics.RecordPreimageChallenged() + } + return nil +} diff --git a/op-challenger/game/keccak/challenger_test.go b/op-challenger/game/keccak/challenger_test.go new file mode 100644 index 000000000000..0c9c0424034a --- /dev/null +++ b/op-challenger/game/keccak/challenger_test.go @@ -0,0 +1,175 @@ +package keccak + +import ( + "context" + "errors" + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/matrix" + keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func TestChallenge(t *testing.T) { + preimages := []keccakTypes.LargePreimageMetaData{ + { + LargePreimageIdent: keccakTypes.LargePreimageIdent{ + Claimant: common.Address{0xff, 0x00}, + UUID: big.NewInt(0), + }, + }, + { + LargePreimageIdent: keccakTypes.LargePreimageIdent{ + Claimant: common.Address{0xff, 0x01}, + UUID: big.NewInt(1), + }, + }, + { + LargePreimageIdent: keccakTypes.LargePreimageIdent{ + Claimant: common.Address{0xff, 0x02}, + UUID: big.NewInt(2), + }, + }, + } + + logger := testlog.Logger(t, log.LevelInfo) + + t.Run("SendChallenges", func(t *testing.T) { + verifier, sender, oracle, challenger := setupChallengerTest(logger) + verifier.challenges[preimages[1].LargePreimageIdent] = keccakTypes.Challenge{StateMatrix: keccakTypes.StateSnapshot{0x01}} + verifier.challenges[preimages[2].LargePreimageIdent] = keccakTypes.Challenge{StateMatrix: keccakTypes.StateSnapshot{0x02}} + err := challenger.Challenge(context.Background(), common.Hash{0xaa}, oracle, preimages) + require.NoError(t, err) + + // Should send the two challenges before returning + require.Len(t, sender.sent, 1, "Should send a single batch of transactions") + for ident, challenge := range verifier.challenges { + tx, err := oracle.ChallengeTx(ident, challenge) + require.NoError(t, err) + require.Contains(t, sender.sent[0], tx) + } + }) + + t.Run("ReturnErrorWhenSendingFails", func(t *testing.T) { + verifier, sender, oracle, challenger := setupChallengerTest(logger) + verifier.challenges[preimages[1].LargePreimageIdent] = keccakTypes.Challenge{StateMatrix: keccakTypes.StateSnapshot{0x01}} + sender.err = errors.New("boom") + err := challenger.Challenge(context.Background(), common.Hash{0xaa}, oracle, preimages) + require.ErrorIs(t, err, sender.err) + }) + + t.Run("LogErrorWhenCreateTxFails", func(t *testing.T) { + logger, logs := testlog.CaptureLogger(t, log.LevelInfo) + + verifier, _, oracle, challenger := setupChallengerTest(logger) + verifier.challenges[preimages[1].LargePreimageIdent] = keccakTypes.Challenge{StateMatrix: keccakTypes.StateSnapshot{0x01}} + oracle.err = errors.New("boom") + err := challenger.Challenge(context.Background(), common.Hash{0xaa}, oracle, preimages) + require.NoError(t, err) + + levelFilter := testlog.NewLevelFilter(log.LevelError) + msgFilter := testlog.NewMessageFilter("Failed to create challenge transaction") + errLog := logs.FindLog(levelFilter, msgFilter) + require.ErrorIs(t, errLog.AttrValue("err").(error), oracle.err) + }) + + t.Run("LogErrorWhenVerifierFails", func(t *testing.T) { + logger, logs := testlog.CaptureLogger(t, log.LevelInfo) + + verifier, _, oracle, challenger := setupChallengerTest(logger) + verifier.challenges[preimages[1].LargePreimageIdent] = keccakTypes.Challenge{StateMatrix: keccakTypes.StateSnapshot{0x01}} + verifier.err = errors.New("boom") + err := challenger.Challenge(context.Background(), common.Hash{0xaa}, oracle, preimages) + require.NoError(t, err) + + levelFilter := testlog.NewLevelFilter(log.LevelError) + msgFilter := testlog.NewMessageFilter("Failed to verify large preimage") + errLog := logs.FindLog(levelFilter, msgFilter) + require.ErrorIs(t, errLog.AttrValue("err").(error), verifier.err) + }) + + t.Run("DoNotLogErrValid", func(t *testing.T) { + logger, logs := testlog.CaptureLogger(t, log.LevelInfo) + + _, _, oracle, challenger := setupChallengerTest(logger) + // All preimages are valid + err := challenger.Challenge(context.Background(), common.Hash{0xaa}, oracle, preimages) + require.NoError(t, err) + + levelFilter := testlog.NewLevelFilter(log.LevelError) + msgFilter := testlog.NewMessageFilter("Failed to verify large preimage") + errLog := logs.FindLog(levelFilter, msgFilter) + require.Nil(t, errLog) + + levelFilter = testlog.NewLevelFilter(log.LevelDebug) + msgFilter = testlog.NewMessageFilter("Preimage is valid") + dbgLog := logs.FindLog(levelFilter, msgFilter) + require.NotNil(t, dbgLog) + }) +} + +func setupChallengerTest(logger log.Logger) (*stubVerifier, *stubSender, *stubChallengerOracle, *PreimageChallenger) { + verifier := &stubVerifier{ + challenges: make(map[keccakTypes.LargePreimageIdent]keccakTypes.Challenge), + } + sender := &stubSender{} + oracle := &stubChallengerOracle{} + metrics := &mockChallengeMetrics{} + challenger := NewPreimageChallenger(logger, metrics, verifier, sender) + return verifier, sender, oracle, challenger +} + +type mockChallengeMetrics struct{} + +func (m *mockChallengeMetrics) RecordPreimageChallenged() {} +func (m *mockChallengeMetrics) RecordPreimageChallengeFailed() {} + +type stubVerifier struct { + challenges map[keccakTypes.LargePreimageIdent]keccakTypes.Challenge + err error +} + +func (s *stubVerifier) CreateChallenge(_ context.Context, _ common.Hash, _ VerifierPreimageOracle, preimage keccakTypes.LargePreimageMetaData) (keccakTypes.Challenge, error) { + if s.err != nil { + return keccakTypes.Challenge{}, s.err + } + challenge, ok := s.challenges[preimage.LargePreimageIdent] + if !ok { + return keccakTypes.Challenge{}, matrix.ErrValid + } + return challenge, nil +} + +type stubSender struct { + err error + sent [][]txmgr.TxCandidate +} + +func (s *stubSender) SendAndWait(_ string, txs ...txmgr.TxCandidate) ([]*types.Receipt, error) { + if s.err != nil { + return nil, s.err + } + s.sent = append(s.sent, txs) + return nil, nil +} + +type stubChallengerOracle struct { + stubOracle + err error +} + +func (s *stubChallengerOracle) ChallengeTx(ident keccakTypes.LargePreimageIdent, challenge keccakTypes.Challenge) (txmgr.TxCandidate, error) { + if s.err != nil { + return txmgr.TxCandidate{}, s.err + } + return txmgr.TxCandidate{ + To: &ident.Claimant, + TxData: append(ident.UUID.Bytes(), challenge.StateMatrix.Pack()...), + }, nil +} diff --git a/op-challenger/game/keccak/fetcher/fetcher.go b/op-challenger/game/keccak/fetcher/fetcher.go index 4158061463f0..755f96b164f3 100644 --- a/op-challenger/game/keccak/fetcher/fetcher.go +++ b/op-challenger/game/keccak/fetcher/fetcher.go @@ -8,7 +8,7 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" - "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" @@ -26,7 +26,7 @@ type L1Source interface { type Oracle interface { Addr() common.Address - GetInputDataBlocks(ctx context.Context, block batching.Block, ident keccakTypes.LargePreimageIdent) ([]uint64, error) + GetInputDataBlocks(ctx context.Context, block rpcblock.Block, ident keccakTypes.LargePreimageIdent) ([]uint64, error) DecodeInputData(data []byte) (*big.Int, keccakTypes.InputData, error) } @@ -36,7 +36,7 @@ type InputFetcher struct { } func (f *InputFetcher) FetchInputs(ctx context.Context, blockHash common.Hash, oracle Oracle, ident keccakTypes.LargePreimageIdent) ([]keccakTypes.InputData, error) { - blockNums, err := oracle.GetInputDataBlocks(ctx, batching.BlockByHash(blockHash), ident) + blockNums, err := oracle.GetInputDataBlocks(ctx, rpcblock.ByHash(blockHash), ident) if err != nil { return nil, fmt.Errorf("failed to retrieve leaf block nums: %w", err) } diff --git a/op-challenger/game/keccak/fetcher/fetcher_test.go b/op-challenger/game/keccak/fetcher/fetcher_test.go index 6d79cf9f7afd..c236712c8466 100644 --- a/op-challenger/game/keccak/fetcher/fetcher_test.go +++ b/op-challenger/game/keccak/fetcher/fetcher_test.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" - "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -174,7 +174,7 @@ func setupFetcherTest(t *testing.T) (*InputFetcher, *stubOracle, *stubL1Source) txs: make(map[uint64]types.Transactions), rcptStatus: make(map[common.Hash]uint64), } - fetcher := NewPreimageFetcher(testlog.Logger(t, log.LvlTrace), l1Source) + fetcher := NewPreimageFetcher(testlog.Logger(t, log.LevelTrace), l1Source) return fetcher, oracle, l1Source } @@ -188,7 +188,7 @@ func (o *stubOracle) Addr() common.Address { return oracleAddr } -func (o *stubOracle) GetInputDataBlocks(_ context.Context, _ batching.Block, _ keccakTypes.LargePreimageIdent) ([]uint64, error) { +func (o *stubOracle) GetInputDataBlocks(_ context.Context, _ rpcblock.Block, _ keccakTypes.LargePreimageIdent) ([]uint64, error) { return o.leafBlocks, nil } diff --git a/op-challenger/game/keccak/matrix/immediateeof_test.go b/op-challenger/game/keccak/matrix/immediateeof_test.go new file mode 100644 index 000000000000..27d0410d8cae --- /dev/null +++ b/op-challenger/game/keccak/matrix/immediateeof_test.go @@ -0,0 +1,66 @@ +package matrix + +import ( + "errors" + "fmt" + "io" + "math/rand" + "testing" + + "github.com/ethereum-optimism/optimism/op-service/testutils" + "github.com/stretchr/testify/require" +) + +type sameCallEOFReader struct { + idx int + data []byte +} + +// newSameCallEOFReader returns an io.Reader that returns io.EOF in the same call that returns the final byte of data. +// This is valid as per io.Reader: +// An instance of this general case is that a Reader returning +// a non-zero number of bytes at the end of the input stream may +// return either err == EOF or err == nil. The next Read should +// return 0, EOF. +func newSameCallEOFReader(data []byte) *sameCallEOFReader { + return &sameCallEOFReader{data: data} +} + +func (i *sameCallEOFReader) Read(out []byte) (int, error) { + end := min(len(i.data), i.idx+len(out)) + n := copy(out, i.data[i.idx:end]) + i.idx += n + if i.idx >= len(i.data) { + return n, io.EOF + } + return n, nil +} + +func TestImmediateEofReader(t *testing.T) { + rng := rand.New(rand.NewSource(223)) + data := testutils.RandomData(rng, 100) + + batchSizes := []int{1, 2, 3, 5, 10, 33, 99, 100, 101} + for _, size := range batchSizes { + size := size + t.Run(fmt.Sprintf("Size-%v", size), func(t *testing.T) { + + reader := &sameCallEOFReader{data: data} + out := make([]byte, size) + actual := make([]byte, 0, len(data)) + for { + n, err := reader.Read(out) + actual = append(actual, out[:n]...) + if errors.Is(err, io.EOF) { + break + } else { + require.NoError(t, err) + } + } + require.Equal(t, data, actual) + n, err := reader.Read(out) + require.Zero(t, n) + require.ErrorIs(t, err, io.EOF) + }) + } +} diff --git a/op-challenger/game/keccak/matrix/matrix.go b/op-challenger/game/keccak/matrix/matrix.go index fd118023c107..8227045dab7d 100644 --- a/op-challenger/game/keccak/matrix/matrix.go +++ b/op-challenger/game/keccak/matrix/matrix.go @@ -2,44 +2,137 @@ package matrix import ( "errors" + "fmt" "io" - "math/big" + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/merkle" "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" ) // StateMatrix implements a stateful keccak sponge with the ability to create state commitments after each permutation type StateMatrix struct { s *state + //prestateMatrix is the state matrix snapshot after processing prestateLeaf but before processing poststateLeaf + prestateMatrix types.StateSnapshot + // prestateLeaf is the last prestate leaf. + // Used to retrieve the prestate to squeeze. + prestateLeaf types.Leaf + // poststateLeaf is the last poststate leaf. + // Used to retrieve the poststate to squeeze. + poststateLeaf types.Leaf + // merkleTree is the internal [merkle.BinaryMerkleTree] used to generate proofs + merkleTree *merkle.BinaryMerkleTree } var ( - ErrInvalidMaxLen = errors.New("invalid max length to absorb") - uint256Size = 32 + ErrInvalidMaxLen = errors.New("invalid max length to absorb") + ErrIncorrectCommitmentCount = errors.New("incorrect number of commitments for input length") + ErrValid = errors.New("state commitments are valid") ) +// Challenge creates a [types.Challenge] to invalidate the provided preimage data if possible. +// [ErrValid] is returned if the provided inputs are valid and no challenge can be created. +func Challenge(data io.Reader, commitments []common.Hash) (types.Challenge, error) { + s := NewStateMatrix() + lastValidState := s.StateSnapshot() + var lastValidLeaf types.Leaf + var firstInvalidLeaf types.Leaf + for i := 0; ; i++ { + if i >= len(commitments) { + // There should have been more commitments. + // The contracts should prevent this so it can't be challenged, return an error + return types.Challenge{}, ErrIncorrectCommitmentCount + } + claimedCommitment := commitments[i] + _, err := s.absorbNextLeafInput(data, func() common.Hash { return claimedCommitment }) + isEOF := errors.Is(err, io.EOF) + if err != nil && !isEOF { + return types.Challenge{}, fmt.Errorf("failed to verify inputs: %w", err) + } + validCommitment := s.StateCommitment() + + if firstInvalidLeaf == (types.Leaf{}) { + if validCommitment != claimedCommitment { + lastValidLeaf = s.prestateLeaf + firstInvalidLeaf = s.poststateLeaf + } else { + lastValidState = s.StateSnapshot() + } + } + if isEOF { + if i < len(commitments)-1 { + // We got too many commitments + // The contracts should prevent this so it can't be challenged, return an error + return types.Challenge{}, ErrIncorrectCommitmentCount + } + break + } + } + if firstInvalidLeaf != (types.Leaf{}) { + var prestateProof merkle.Proof + if lastValidLeaf != (types.Leaf{}) { + prestateProof = s.merkleTree.ProofAtIndex(lastValidLeaf.Index) + } + poststateProof := s.merkleTree.ProofAtIndex(firstInvalidLeaf.Index) + return types.Challenge{ + StateMatrix: lastValidState, + Prestate: lastValidLeaf, + PrestateProof: prestateProof, + Poststate: firstInvalidLeaf, + PoststateProof: poststateProof, + }, nil + } + return types.Challenge{}, ErrValid +} + // NewStateMatrix creates a new state matrix initialized with the initial, zero keccak block. func NewStateMatrix() *StateMatrix { - return &StateMatrix{s: newLegacyKeccak256()} + return &StateMatrix{ + s: newLegacyKeccak256(), + merkleTree: merkle.NewBinaryMerkleTree(), + } } // StateCommitment returns the state commitment for the current state matrix. // Additional data may be absorbed after calling this method. func (d *StateMatrix) StateCommitment() common.Hash { - buf := d.PackState() - return crypto.Keccak256Hash(buf) + return crypto.Keccak256Hash(d.StateSnapshot().Pack()) +} + +func (d *StateMatrix) StateSnapshot() types.StateSnapshot { + var snap types.StateSnapshot + copy(snap[:], d.s.a[:]) + return snap } -// PackState packs the state in to the solidity ABI encoding required for the state matrix -func (d *StateMatrix) PackState() []byte { - buf := make([]byte, 0, len(d.s.a)*uint256Size) - for _, v := range d.s.a { - buf = append(buf, math.U256Bytes(new(big.Int).SetUint64(v))...) +// newLeafWithPadding creates a new [Leaf] from inputs, padding the input to the [BlockSize]. +func (d *StateMatrix) newLeafWithPadding(input []byte, index uint64, commitment common.Hash, final bool) types.Leaf { + var paddedInput [types.BlockSize]byte + copy(paddedInput[:], input) + + if final { + pad(input, &paddedInput, d.s.dsbyte) + } + return types.Leaf{ + Input: paddedInput, + Index: index, + StateCommitment: commitment, } - return buf +} + +func pad(input []byte, paddedInput *[types.BlockSize]byte, dsbyte byte) { + // Pad with this instance's domain-separator bits. We know that there's + // at least one more byte of space in paddedInput because, if it were full, + // this wouldn't be the last block and the padding would be in the next block. + // dsbyte also contains the first one bit for the padding. See the comment in the state struct. + paddedInput[len(input)] = dsbyte + // The remaining bytes are already zeros since paddedInput is a new array. + // This adds the final one bit for the padding. Because of the way that + // bits are numbered from the LSB upwards, the final bit is the MSB of + // the last byte. + paddedInput[types.BlockSize-1] ^= 0x80 } func (d *StateMatrix) AbsorbUpTo(in io.Reader, maxLen int) (types.InputData, error) { @@ -49,7 +142,7 @@ func (d *StateMatrix) AbsorbUpTo(in io.Reader, maxLen int) (types.InputData, err input := make([]byte, 0, maxLen) commitments := make([]common.Hash, 0, maxLen/types.BlockSize) for len(input)+types.BlockSize <= maxLen { - readData, err := d.absorbNextLeafInput(in) + readData, err := d.absorbNextLeafInput(in, d.StateCommitment) if errors.Is(err, io.EOF) { input = append(input, readData...) commitments = append(commitments, d.StateCommitment()) @@ -72,15 +165,32 @@ func (d *StateMatrix) AbsorbUpTo(in io.Reader, maxLen int) (types.InputData, err }, nil } +func (d *StateMatrix) PrestateMatrix() types.StateSnapshot { + return d.prestateMatrix +} + +// PrestateWithProof returns the prestate leaf with its merkle proof. +func (d *StateMatrix) PrestateWithProof() (types.Leaf, merkle.Proof) { + proof := d.merkleTree.ProofAtIndex(d.prestateLeaf.Index) + return d.prestateLeaf, proof +} + +// PoststateWithProof returns the poststate leaf with its merkle proof. +func (d *StateMatrix) PoststateWithProof() (types.Leaf, merkle.Proof) { + proof := d.merkleTree.ProofAtIndex(d.poststateLeaf.Index) + return d.poststateLeaf, proof +} + // absorbNextLeafInput reads up to [BlockSize] bytes from in and absorbs them into the state matrix. // If EOF is reached while reading, the state matrix is finalized and [io.EOF] is returned. -func (d *StateMatrix) absorbNextLeafInput(in io.Reader) ([]byte, error) { +func (d *StateMatrix) absorbNextLeafInput(in io.Reader, stateCommitment func() common.Hash) ([]byte, error) { data := make([]byte, types.BlockSize) read := 0 final := false for read < types.BlockSize { n, err := in.Read(data[read:]) if errors.Is(err, io.EOF) { + read += n final = true break } else if err != nil { @@ -89,7 +199,22 @@ func (d *StateMatrix) absorbNextLeafInput(in io.Reader) ([]byte, error) { read += n } input := data[:read] + // Don't add the padding if we read a full block of input data, even if we reached EOF. + // Just absorb the full block and return so the caller can capture the state commitment after the block + // The next call will read no data from the Reader (already at EOF) and so add the final padding as an + // additional block. We can then return EOF to indicate there are no further blocks. + final = final && len(input) < types.BlockSize + d.prestateMatrix = d.StateSnapshot() d.absorbLeafInput(input, final) + commitment := stateCommitment() + if d.poststateLeaf == (types.Leaf{}) { + d.prestateLeaf = types.Leaf{} + d.poststateLeaf = d.newLeafWithPadding(input, 0, commitment, final) + } else { + d.prestateLeaf = d.poststateLeaf + d.poststateLeaf = d.newLeafWithPadding(input, d.prestateLeaf.Index+1, commitment, final) + } + d.merkleTree.AddLeaf(d.poststateLeaf.Hash()) if final { return input, io.EOF } diff --git a/op-challenger/game/keccak/matrix/matrix_test.go b/op-challenger/game/keccak/matrix/matrix_test.go index 0f8508dfaa04..7be4631a0c99 100644 --- a/op-challenger/game/keccak/matrix/matrix_test.go +++ b/op-challenger/game/keccak/matrix/matrix_test.go @@ -10,6 +10,7 @@ import ( "math/rand" "testing" + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/merkle" "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" "github.com/ethereum-optimism/optimism/op-service/testutils" "github.com/ethereum/go-ethereum/common" @@ -42,46 +43,67 @@ func TestStateCommitment(t *testing.T) { t.Run("", func(t *testing.T) { state := NewStateMatrix() copy(state.s.a[:], test.matrix) - expected := crypto.Keccak256Hash(common.Hex2Bytes(test.expectedPacked)) + expected := crypto.Keccak256Hash(common.FromHex(test.expectedPacked)) actual := state.StateCommitment() - require.Equal(t, test.expectedPacked, common.Bytes2Hex(state.PackState())) + require.Equal(t, test.expectedPacked, common.Bytes2Hex(state.StateSnapshot().Pack())) require.Equal(t, expected, actual) }) } } type testData struct { - Input []byte `json:"input"` - Commitments []common.Hash `json:"commitments"` + Input []byte `json:"input"` + Commitments []common.Hash `json:"commitments"` + PrestateLeaf []byte `json:"prestateLeaf"` + PoststateLeaf []byte `json:"poststateLeaf"` } -func TestReferenceCommitments(t *testing.T) { +func TestAbsorbNextLeaf_ReferenceCommitments(t *testing.T) { var tests []testData require.NoError(t, json.Unmarshal(refTests, &tests)) for i, test := range tests { test := test - t.Run(fmt.Sprintf("Ref-%v", i), func(t *testing.T) { + t.Run(fmt.Sprintf("Ref-%v-%v", i, len(test.Input)), func(t *testing.T) { + prevLeaf := types.Leaf{} s := NewStateMatrix() commitments := []common.Hash{s.StateCommitment()} - for i := 0; i < len(test.Input); i += types.BlockSize { - end := min(i+types.BlockSize, len(test.Input)) - s.absorbLeafInput(test.Input[i:end], end == len(test.Input)) - commitments = append(commitments, s.StateCommitment()) - } - if len(test.Input) == 0 { - s.absorbLeafInput(nil, true) + in := bytes.NewReader(test.Input) + for { + readData, err := s.absorbNextLeafInput(in, s.StateCommitment) + isEOF := errors.Is(err, io.EOF) + if !isEOF { + // Shouldn't get any error except EOF + require.NoError(t, err) + } + prestate, _ := s.PrestateWithProof() + poststate, _ := s.PoststateWithProof() + require.Equal(t, prevLeaf, prestate, "Prestate should be the previous post state") + require.Equal(t, poststate.Input[:len(readData)], readData, "Post state should have returned input data") + prevLeaf = poststate commitments = append(commitments, s.StateCommitment()) + if isEOF { + break + } } actual := s.Hash() expected := crypto.Keccak256Hash(test.Input) require.Equal(t, expected, actual) require.Equal(t, test.Commitments, commitments) + + prestate, _ := s.PrestateWithProof() + var expectedPre [types.BlockSize]byte + copy(expectedPre[:], test.PrestateLeaf) + require.Equal(t, expectedPre, prestate.Input, "Final prestate") + poststate, _ := s.PoststateWithProof() + var expectedPost [types.BlockSize]byte + copy(expectedPost[:], test.PoststateLeaf) + require.Equal(t, expectedPost, poststate.Input, "Final poststate") }) } } -func TestReferenceCommitmentsFromReader(t *testing.T) { +func TestAbsorbUpTo_ReferenceCommitments(t *testing.T) { var tests []testData require.NoError(t, json.Unmarshal(refTests, &tests)) @@ -92,14 +114,14 @@ func TestReferenceCommitmentsFromReader(t *testing.T) { commitments := []common.Hash{s.StateCommitment()} in := bytes.NewReader(test.Input) for { - _, err := s.absorbNextLeafInput(in) + input, err := s.AbsorbUpTo(in, types.BlockSize*3) if errors.Is(err, io.EOF) { - commitments = append(commitments, s.StateCommitment()) + commitments = append(commitments, input.Commitments...) break } // Shouldn't get any error except EOF require.NoError(t, err) - commitments = append(commitments, s.StateCommitment()) + commitments = append(commitments, input.Commitments...) } actual := s.Hash() expected := crypto.Keccak256Hash(test.Input) @@ -109,7 +131,7 @@ func TestReferenceCommitmentsFromReader(t *testing.T) { } } -func TestAbsorbUpTo_ReferenceCommitments(t *testing.T) { +func TestAbsorbUpTo_ReferenceCommitments_SameCallEOF(t *testing.T) { var tests []testData require.NoError(t, json.Unmarshal(refTests, &tests)) @@ -118,7 +140,7 @@ func TestAbsorbUpTo_ReferenceCommitments(t *testing.T) { t.Run(fmt.Sprintf("Ref-%v", i), func(t *testing.T) { s := NewStateMatrix() commitments := []common.Hash{s.StateCommitment()} - in := bytes.NewReader(test.Input) + in := newSameCallEOFReader(test.Input) for { input, err := s.AbsorbUpTo(in, types.BlockSize*3) if errors.Is(err, io.EOF) { @@ -165,7 +187,7 @@ func TestAbsorbUpTo_InvalidLengths(t *testing.T) { } } -func TestMatrix_AbsorbNextLeaf(t *testing.T) { +func TestMatrix_absorbNextLeaf(t *testing.T) { fullLeaf := make([]byte, types.BlockSize) for i := 0; i < types.BlockSize; i++ { fullLeaf[i] = byte(i) @@ -208,7 +230,7 @@ func TestMatrix_AbsorbNextLeaf(t *testing.T) { state := NewStateMatrix() in := bytes.NewReader(test.input) for i, leaf := range test.leafInputs { - buf, err := state.absorbNextLeafInput(in) + buf, err := state.absorbNextLeafInput(in, state.StateCommitment) if errors.Is(err, io.EOF) { require.Equal(t, test.errs[i], err) break @@ -220,6 +242,186 @@ func TestMatrix_AbsorbNextLeaf(t *testing.T) { } } +func TestVerifyPreimage_ReferenceCommitments(t *testing.T) { + var tests []testData + require.NoError(t, json.Unmarshal(refTests, &tests)) + + for i, test := range tests { + test := test + t.Run(fmt.Sprintf("Ref-%v", i), func(t *testing.T) { + // Exclude the empty state commitment + challenge, err := Challenge(bytes.NewReader(test.Input), test.Commitments[1:]) + require.ErrorIs(t, err, ErrValid) + require.Equal(t, types.Challenge{}, challenge) + }) + } +} + +func TestVerifyPreimage_ReferenceCommitments_SameCallEOF(t *testing.T) { + var tests []testData + require.NoError(t, json.Unmarshal(refTests, &tests)) + + for i, test := range tests { + test := test + t.Run(fmt.Sprintf("Ref-%v", i), func(t *testing.T) { + // Exclude the empty state commitment + challenge, err := Challenge(newSameCallEOFReader(test.Input), test.Commitments[1:]) + require.ErrorIs(t, err, ErrValid) + require.Equal(t, types.Challenge{}, challenge) + }) + } +} + +func TestVerifyPreimage(t *testing.T) { + preimage := testutils.RandomData(rand.New(rand.NewSource(2323)), 1024) + validCommitments := func() []common.Hash { + valid, err := NewStateMatrix().AbsorbUpTo(bytes.NewReader(preimage), 1000*types.BlockSize) + require.ErrorIs(t, err, io.EOF, "Should read all preimage data") + return valid.Commitments + } + leafData := func(idx int) (out [types.BlockSize]byte) { + end := min((idx+1)*types.BlockSize, len(preimage)) + input := preimage[idx*types.BlockSize : end] + copy(out[:], input) + if len(input) < types.BlockSize { + pad(input, &out, newLegacyKeccak256().dsbyte) + } + return + } + // merkleTree creates the final merkle tree after including all leaves. + merkleTree := func(commitments []common.Hash) *merkle.BinaryMerkleTree { + m := merkle.NewBinaryMerkleTree() + for i, commitment := range commitments { + leaf := types.Leaf{ + Input: leafData(i), + Index: uint64(i), + StateCommitment: commitment, + } + m.AddLeaf(leaf.Hash()) + } + return m + } + + challengeLeaf := func(commitments []common.Hash, invalidIdx int) types.Challenge { + invalidLeafStart := invalidIdx * types.BlockSize + s := NewStateMatrix() + _, err := s.AbsorbUpTo(bytes.NewReader(preimage), invalidLeafStart) + require.NoError(t, err) + + fullMerkle := merkleTree(commitments) + prestateLeaf := leafData(invalidIdx - 1) + poststateLeaf := leafData(invalidIdx) + return types.Challenge{ + StateMatrix: s.StateSnapshot(), + Prestate: types.Leaf{ + Input: prestateLeaf, + Index: uint64(invalidIdx - 1), + StateCommitment: commitments[invalidIdx-1], + }, + PrestateProof: fullMerkle.ProofAtIndex(uint64(invalidIdx - 1)), + + Poststate: types.Leaf{ + Input: poststateLeaf, + Index: uint64(invalidIdx), + StateCommitment: commitments[invalidIdx], + }, + PoststateProof: fullMerkle.ProofAtIndex(uint64(invalidIdx)), + } + } + + type testInputs struct { + name string + commitments func() []common.Hash + expected types.Challenge + expectedErr error + } + + poststateLeaf := leafData(0) + tests := []testInputs{ + { + name: "Valid", + commitments: validCommitments, + expectedErr: ErrValid, + }, + func() testInputs { + incorrectFirstCommitment := validCommitments() + incorrectFirstCommitment[0] = common.Hash{0xaa} + return testInputs{ + name: "IncorrectFirstLeaf", + commitments: func() []common.Hash { + return incorrectFirstCommitment + }, + expected: types.Challenge{ + StateMatrix: NewStateMatrix().StateSnapshot(), + Prestate: types.Leaf{}, + Poststate: types.Leaf{ + Input: poststateLeaf, + Index: 0, + StateCommitment: common.Hash{0xaa}, + }, + PoststateProof: merkleTree(incorrectFirstCommitment).ProofAtIndex(0), + }, + } + }(), + } + + for i := 1; i < len(preimage)/types.BlockSize; i++ { + commitments := validCommitments() + commitments[i] = common.Hash{0xaa} + tests = append(tests, testInputs{ + name: fmt.Sprintf("Incorrect-%v", i), + commitments: func() []common.Hash { + return commitments + }, + expected: challengeLeaf(commitments, i), + }) + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + challenge, err := Challenge(bytes.NewReader(preimage), test.commitments()) + require.ErrorIs(t, err, test.expectedErr) + require.Equal(t, test.expected.StateMatrix, challenge.StateMatrix, "Correct state matrix") + require.Equal(t, test.expected.Prestate, challenge.Prestate, "Correct prestate") + if test.expected.Prestate != (types.Leaf{}) { + require.Equal(t, test.expected.Prestate.StateCommitment, crypto.Keccak256Hash(challenge.StateMatrix.Pack()), "Prestate matches leaf commitment") + } + require.Equal(t, test.expected.PrestateProof, challenge.PrestateProof, "Correct prestate proof") + require.Equal(t, test.expected.Poststate, challenge.Poststate, "Correct poststate") + require.Equal(t, test.expected.PoststateProof, challenge.PoststateProof, "Correct poststate proof") + require.Equal(t, test.expected, challenge, "Challenge correct overall") + }) + } +} + +func TestVerifyPreimage_DataMultipleOfBlockSize(t *testing.T) { + preimage := testutils.RandomData(rand.New(rand.NewSource(2323)), 5*types.BlockSize) + valid, err := NewStateMatrix().AbsorbUpTo(bytes.NewReader(preimage), 1000*types.BlockSize) + require.ErrorIs(t, err, io.EOF, "Should read all preimage data") + + _, err = Challenge(bytes.NewReader(preimage), valid.Commitments) + require.ErrorIs(t, err, ErrValid) +} + +func TestVerifyPreimage_TooManyCommitments(t *testing.T) { + data := []byte{1} + valid, err := NewStateMatrix().AbsorbUpTo(bytes.NewReader(data[:]), 10*types.BlockSize) + require.ErrorIs(t, err, io.EOF) + commitments := append(valid.Commitments, common.Hash{0xaa}) + _, err = Challenge(bytes.NewReader(data), commitments) + require.ErrorIs(t, err, ErrIncorrectCommitmentCount) +} + +func TestVerifyPreimage_TooFewCommitments(t *testing.T) { + data := [types.BlockSize * 3]byte{} + valid, err := NewStateMatrix().AbsorbUpTo(bytes.NewReader(data[:]), 10*types.BlockSize) + require.ErrorIs(t, err, io.EOF) + commitments := valid.Commitments[:len(valid.Commitments)-1] + _, err = Challenge(bytes.NewReader(data[:]), commitments) + require.ErrorIs(t, err, ErrIncorrectCommitmentCount) +} + func FuzzKeccak(f *testing.F) { f.Fuzz(func(t *testing.T, number, time uint64, data []byte) { s := NewStateMatrix() diff --git a/op-challenger/game/keccak/matrix/testdata/commitments.json b/op-challenger/game/keccak/matrix/testdata/commitments.json index c5c6b9fa2a6f..c94b29261495 100644 --- a/op-challenger/game/keccak/matrix/testdata/commitments.json +++ b/op-challenger/game/keccak/matrix/testdata/commitments.json @@ -4,14 +4,18 @@ "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x87d8548924b20b95fe1ed923236c44d2f98b8dc7a3c8c378e4193cc2745b1e8d" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "kYbKyRm02RR58P+t8WPE/UNL4zmr4XIe3qfMfFwRZVWlpzgDSmAXGNhqCGJZivDoNDRM1zrLaPAk5Ol8dAyi3shQgLHaBur7TLczzwxS9b8rU7WKPhTMsK+zblk3ps19yKixxPMjzMA5L70JOy0ng7/ZoJJhMuHC7TD1SYL5LEABAAAAAAAAgA==" }, { "input": null, "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xb87c3be3d5bf2230e08186014204ab2d4e5eb457ec9e95fd4a703f9f97b8c49a" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "d2w7VVWNxlrhpX8iaT9gU3dqU/LStT7JDOxkPmKDpdExTm23fLcfou2UP+1koHU2XOlRU3gyde/InQA2axIOqmaWn7oU+Zyt8yChgn0fbY6icCcf3ILIKneVRxQQYef6lX7gloDl65pA85pQYZxSfAOIfqrMsAkWoebxmJsoTLSsCHSGrdlE8Cy9hzyNjx2MwnjwTc/GIrX+cpbEfnRXHTQSYrwHjILe57MaJ5EuVA==", @@ -19,14 +23,18 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x74df6384655843a30a8064467ece134524f68d18ca2e2290e0cd6f1c159d901b", "0xb0729c23d40d7d05656a9c0af18caf4234b2d51f7b11f8ad091fb6c6c5f41788" - ] + ], + "prestateLeaf": "d2w7VVWNxlrhpX8iaT9gU3dqU/LStT7JDOxkPmKDpdExTm23fLcfou2UP+1koHU2XOlRU3gyde/InQA2axIOqmaWn7oU+Zyt8yChgn0fbY6icCcf3ILIKneVRxQQYef6lX7gloDl65pA85pQYZxSfAOIfqrMsAkWoebxmJsoTLSsCHSGrdlE8A==", + "poststateLeaf": "LL2HPI2PHYzCePBNz8Yitf5ylsR+dFcdNBJivAeMgt7nsxonkS5UAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "QbjuDum/N3hGQLgqXL+MCiPEUrt4bF+xejAngdRK3D8IOKnZfk6TaiGMdsG8vg==", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xafaa5d998cf20052dea34066e466691f3a59af8a6143b7ff5626f87cb76f820b" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "QbjuDum/N3hGQLgqXL+MCiPEUrt4bF+xejAngdRK3D8IOKnZfk6TaiGMdsG8vgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "PaMoGKkQH3/NFs0YYsAG2u80tRrxq+flLSff0yCFhe5akRB8t03nLlhPgofL80CDBxC0Yc5hGj7bxMVgg4mfjLQ8tKjfxYK99F+IO9cq5cqxHS/QMSQ97KgyNUVb89PB2JwdDuqbCe+RnioFR1MpKyroSJpfmFPt+icQ/OZs6bVKqCw2TnALoheU/9r8MMDWW9NdHzf72ZZJC8UPa86dhESNMnL5VYv27wZibh8FaNw5oAFmEg2C8NBn2RsIkn9yEBD7M1YVA/7QDJghK7iVYhy5x7Hhd+VFikbBmgbWJKG1TQuNc5T1+iYS90GOvOHBwFbJB4/C4b5gUAaJcc7Y4V3/nUPhVMGHj+PA5emMS3J/9Qt43RzJa0/fn0LtCH4mvx73Ll6a91iINQ==", @@ -35,14 +43,18 @@ "0xccd955f751642425fd9b3bf7785da8c9f6e9d55027d1048ade2b9f0a3071860b", "0xf77a4c6e252daf3f67bbe40f3275aa854418b0e0afb389bfc4425899898b1953", "0xf3402153d5503ec0a32cff2b3590764fb284d15f77a6688a6f5d0fc579c7f64a" - ] + ], + "prestateLeaf": "F5T/2vwwwNZb010fN/vZlkkLxQ9rzp2ERI0ycvlVi/bvBmJuHwVo3DmgAWYSDYLw0GfZGwiSf3IQEPszVhUD/tAMmCEruJViHLnHseF35UWKRsGaBtYkobVNC41zlPX6JhL3QY684cHAVskHj8LhvmBQBolxztjhXf+dQ+FUwYeP48Dl6YxLcg==", + "poststateLeaf": "f/ULeN0cyWtP359C7Qh+Jr8e9y5emvdYiDUBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "vKG+6yYjKSdPcwd7e0iBfiwk7dek86+aVEoSgpkf9IdxiukoQFjZsx4XiOHcwv4=", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xc59f075e03c34088cfe44693f1260a94c0ebb6075b07c00875d0c2c072a87708" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "vKG+6yYjKSdPcwd7e0iBfiwk7dek86+aVEoSgpkf9IdxiukoQFjZsx4XiOHcwv4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "8qf1VUYedwv+s6Swd3mfEOvga7Hq/DGOXlV/zZucPT1IdXnG119li9Q+ELxWLSMXD4T4TKoeQnyOXr0t7sNLguKzca1Ra5+iZKCWsDQD77wGJgjh+rVw93NupUjHOtRYyixRVBHe/NrsQIy248NZc5B7fc7XcND3wFDk6gsqiXWmoSdu7ak6n23IruOGlZ5K1ZhlXh5ax1Z3YDfdJQSFbeGcQg0RVg==", @@ -50,7 +62,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x73aa7c55e21e7d1da31e759983a2d81d88ad9306b45e1448c8cc7fbbd8f48e57", "0x640dd808bb3264f28233d889b062c26fe80cf4477946dc0162cfb3033aa92cee" - ] + ], + "prestateLeaf": "8qf1VUYedwv+s6Swd3mfEOvga7Hq/DGOXlV/zZucPT1IdXnG119li9Q+ELxWLSMXD4T4TKoeQnyOXr0t7sNLguKzca1Ra5+iZKCWsDQD77wGJgjh+rVw93NupUjHOtRYyixRVBHe/NrsQIy248NZc5B7fc7XcND3wFDk6gsqiXWmoSdu7ak6nw==", + "poststateLeaf": "bciu44aVnkrVmGVeHlrHVndgN90lBIVt4ZxCDRFWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "3MZjvdJnTVg343pKZjz1OVl1yY8e+Tg8tKM4lPZHys+s0w4R8f6n1Iz7k00DCF3GLQDk96PaNBlGoLZBYjp5EXqXwj/o2q0gYz9wZXxDP0Lkkqo24PRExtAtIPUmVMKOtjpsQ9hnZtAap9fI1CYcokU0ub+HwsB6aZcekWEJHCbfiQKt2eojkVRs/6TGWfyhSo1CB5jZh42btX9NcPY0+NvfcVk+pM34GGgrH//bMDx952t6MxwgN3CevaJMybeZAKzikCvAZU/xj9mPD1WY5tW+YKN1/YoRRba6mSDKkAcYv3PZXk/mfLISvXD1wlIJVjCwffN0d7nhXzha7tXpdkkx4r9/TdwaXMkWFuEBN1Xd0yPRWTELFos=", @@ -59,7 +73,9 @@ "0xf483f22d3ab0f7ed87d97b62150f67e41ea771c0c3cdb6187d041756d3e93aaf", "0x86a10716ffd3208dc77e6ccc5b7a614c9e0543db2058dec6e3878605237a63d2", "0x9ae0878d45796e55b8b866a1c91672b921aee33964af6351f8221c996058e03b" - ] + ], + "prestateLeaf": "VGz/pMZZ/KFKjUIHmNmHjZu1f01w9jT4299xWT6kzfgYaCsf/9swPH3na3ozHCA3cJ69okzJt5kArOKQK8BlT/GP2Y8PVZjm1b5go3X9ihFFtrqZIMqQBxi/c9leT+Z8shK9cPXCUglWMLB983R3ueFfOFru1el2STHiv39N3BpcyRYW4QE3VQ==", + "poststateLeaf": "3dMj0VkxCxaLAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "3EMdZkAwjohNpPLE/zR6nAXNkEk4DP0eNuXjKgQ0hDtQ2mdnsbCCwJ3Lih8qsVTyGRNc/xfZHc/ChlntAvTunU92p0JJvP7TMnyAZUPmmqGWtvk1vne2KbDXV0sD/sfhMG5cW8vHt8XGq7S/2GsljPjUjZyHV2Gg0s0G/r4W/FPrMw/GNNKKP9GQXfSDnqoUYRdJEtnz8rWi1w==", @@ -67,7 +83,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x5ef96af187147cc0ab594b8989269a10417a1aaa8dc382cf82ca5febba03d2da", "0xef1e1ebbd234ac51de0fc268f182b1b5b9d27f98d5052d59aed0fa8e0bcb6b5a" - ] + ], + "prestateLeaf": "3EMdZkAwjohNpPLE/zR6nAXNkEk4DP0eNuXjKgQ0hDtQ2mdnsbCCwJ3Lih8qsVTyGRNc/xfZHc/ChlntAvTunU92p0JJvP7TMnyAZUPmmqGWtvk1vne2KbDXV0sD/sfhMG5cW8vHt8XGq7S/2GsljPjUjZyHV2Gg0s0G/r4W/FPrMw/GNNKKPw==", + "poststateLeaf": "0ZBd9IOeqhRhF0kS2fPytaLXAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "JU9To00l+wzr7e2q+IGxvyanpdY8nI/LPGy9YJye2BlWkUPvDyXBSWwKzNML9rgCtNwvfMp49Yv0dkEjuOsijZaOi1OVB+uTFrw2NHaoK6t94riJLLyGFo3ObYsTFxXVYqdRUv3y8dqOyrJ2bA9rXmnExDFvLSkqE7grxQ6rW3MuiMGaLsjObw7L+yOey2P5K8GSnjgnvSl1PSFdTvcW0XwNiUmxF9mj/CLl0VLj0+tcp7PTOL+rGda+ERID35cNSxAqiy37r1RD0Aku5e3A9KlRW6XY8HtitjgbUgkyncd/+i49XLMOy6Z7+VRHW5ySOMQzBM4aZF0494wo8+hnYkyOQF4uzQdqp1nE5fAmpwG6ZBS1Il2d1IulXjjdcY+wTCBzWQZoRnxxYbU=", @@ -76,7 +94,9 @@ "0xc2244d44050cd1bf8c48ef1fd151118e24d0f4d055c6f8e2d9380393ecf536db", "0x4217f2d70fe289c61f167410b02f0e21cea079e677abc7211e3419acfbfbb68f", "0xbd91622393a0ce9bff67d7746746e9510fc00f9333d76461c17cdfa3dbfeca1f" - ] + ], + "prestateLeaf": "Dsv7I57LY/krwZKeOCe9KXU9IV1O9xbRfA2JSbEX2aP8IuXRUuPT61yns9M4v6sZ1r4REgPflw1LECqLLfuvVEPQCS7l7cD0qVFbpdjwe2K2OBtSCTKdx3/6Lj1csw7Lpnv5VEdbnJI4xDMEzhpkXTj3jCjz6GdiTI5AXi7NB2qnWcTl8CanAQ==", + "poststateLeaf": "umQUtSJdndSLpV443XGPsEwgc1kGaEZ8cWG1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "U+4ryEt1iB943t/XSZVdzLlwakB+Y+hPoG9iSrjOiyfL08ir1RT5PgquCmGzHi6wz6h+F5NnmByCJym79jxR9kfWm2I1B03pT0YwqfX6Z3t2RRDbG68VVK9vffAb+8tyReLczU+rF+PjF4KPhBeKIjHJ/D1QapCnCpq5wwVMOGixw7qr+SNPamMjg/KbVCNI9oaxDlyoXJy1cG3WlsU2OXRpUX0Ny/58kR70fXyjLIEADP7VRgz2M5k74W4PWd5XzssOnajYJ32tgAMLdje3NGyupp5c10LZjO3F2tks7POoMmzdNPrlkgXnfmwPsj7e8+Dq14LHVPOVWIMw9dpx+T+empmJNCLXNdkQni0ONijwtKc5iARcIe4NB6l0q0YiEw3w3MjK8E5BKG1j5w5CIx1MIfuUc/4yp842Geiv08u/4yhBIPgEUtdGqdQc1J3hDZfWgs/434158ANQG8kbE9Fcr0/phrlh5+fIkW1tVKrtwrmNG/YCE35gVLKd6pJ+MBG1WIN30f1yiNfde9HU20fjcV8Zw90ir1GYr1PNchXGG/FuvDrLkd6m2IbDNzsQuijBCRxefsjcJsnhuZgs3WkSCaRr6q9ka0o1yUQKigfYLR/ern3rF4G+dOlV3zh6Vm832UPqRP5J/VNYjVqajjx4MALzQ7OkIDGr8T/Hb2cKxMFWc5xoEf7yZgAGC2N5jyQUSw==", @@ -86,7 +106,9 @@ "0xab029840421422083410d3ea591cc1d6d7f987e11fd1fb41673e4886cc7f9ec0", "0xec87dfbf5373bbf99dde1e23353bedfa596df7887141406cc75a7788c75b1725", "0x26d05dcd547e9c12fd9372c7a72a756d43eab9b1b184f573e87200e516f5199b" - ] + ], + "prestateLeaf": "8LSnOYgEXCHuDQepdKtGIhMN8NzIyvBOQShtY+cOQiMdTCH7lHP+MqfONhnor9PLv+MoQSD4BFLXRqnUHNSd4Q2X1oLP+N+NefADUBvJGxPRXK9P6Ya5YefnyJFtbVSq7cK5jRv2AhN+YFSyneqSfjARtViDd9H9cojX3XvR1NtH43FfGcPdIg==", + "poststateLeaf": "r1GYr1PNchXGG/FuvDrLkd6m2IbDNzsQuijBCRxefsjcJsnhuZgs3WkSCaRr6q9ka0o1yUQKigfYLR/ern3rF4G+dOlV3zh6Vm832UPqRP5J/VNYjVqajjx4MALzQ7OkIDGr8T/Hb2cKxMFWc5xoEf7yZgAGC2N5jyQUSwEAAAAAAAAAAAAAgA==" }, { "input": "ivixMAmdy1yLuqm6Z95ZCzFzPgJJwLbWxMLLECdqYwqyjscxsa55NlLoGIA6wdMUNjEYHifxsmhXRhfvu9vPS3nXJ0oLzvnwLtHp8nZJHfGfcVttccT3c5ODPLaxYArShpMIbeBOu7Cp5BrYt3WnjoWkdpvlD0SJex8VP4mz/XJ0bTt2/xyJg8GSQbyxQn+GzCnpUKDPPK9L8s+Fh/1tCYdzbX+YzCeW9+8vXkoVTQ9QrrPBxgU=", @@ -94,7 +116,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x89271427bd0052876b950a60146c74fa471497eaa803e2c24c4a358c768019a0", "0x41235a392b38e63d2cad93c5a5cd4f9cd4caecfbd9ef0459dc4a17c2893f37a4" - ] + ], + "prestateLeaf": "ivixMAmdy1yLuqm6Z95ZCzFzPgJJwLbWxMLLECdqYwqyjscxsa55NlLoGIA6wdMUNjEYHifxsmhXRhfvu9vPS3nXJ0oLzvnwLtHp8nZJHfGfcVttccT3c5ODPLaxYArShpMIbeBOu7Cp5BrYt3WnjoWkdpvlD0SJex8VP4mz/XJ0bTt2/xyJgw==", + "poststateLeaf": "wZJBvLFCf4bMKelQoM88r0vyz4WH/W0Jh3Ntf5jMJ5b37y9eShVND1Cus8HGBQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "Ck5zoYOAXqv3Uh/+JT/v86YSU9pO47Tg0RttlXad8wZnXyOVT6XqyFT+LpDufiRtYLWctKgbSOYGm/kH3UNbLDRdCItm6aCom/0HJ++ZvhUu8dX1FG1S4P+Jr/kNuokvOgHFTlQhrp5sIzD9jOqPSemxWmXhjbRbU5LuSz53AHxg/OshWA1CokEDDfH+2DrEBVDnqXHXBXKL3McudqosDj/jU1NW50GVlX4ZGjyZLYF5jxVfIDz4vFzW6uThNoTyJ+6jMWl1m93FSylA8bFtq3sxz9yMYnKFESv7YvsQND5EpwnoGfWK9ff1OHLv3XSY7AQv5igZpOkA2rBOdJFT0KH+kj9SKxPH/SnZgIjlNVbCALMgt81ZTtBS1CioTPIx2eAKKiEjn8ESVA1O5oTP7fxF1xvtj/gM1M0dOhY+u4c7jnWmcIDCVyXhBqgTkrhPqJ8eKXdTF/p5cmjs34gjF8TFIL7+", @@ -103,7 +127,9 @@ "0xbc47fa6d888b9725f9d5c4d7b586161e7fc0fac8049df9b36d39dac2f5a6c738", "0xfa87ab1b88d828bca2748721f15f86f725edf0d3f578e172a013cb2e8d6fec00", "0x13921647e516ba9af4a595fb8141525a79c78c1f00fb7837a07682871efe1289" - ] + ], + "prestateLeaf": "QQMN8f7YOsQFUOepcdcFcovcxy52qiwOP+NTU1bnQZWVfhkaPJktgXmPFV8gPPi8XNbq5OE2hPIn7qMxaXWb3cVLKUDxsW2rezHP3IxicoURK/ti+xA0PkSnCegZ9Yr19/U4cu/ddJjsBC/mKBmk6QDasE50kVPQof6SP1IrE8f9KdmAiOU1Vg==", + "poststateLeaf": "wgCzILfNWU7QUtQoqEzyMdngCiohI5/BElQNTuaEz+38Rdcb7Y/4DNTNHToWPruHO451pnCAwlcl4QaoE5K4T6ifHil3Uxf6eXJo7N+IIxfExSC+/gEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "6HjAPGpmaPGPLCx9xAj1Vhl8nKdgpXryqReIbBsNyxDJuqaJW5D0Te4+UWi2yYdbAy6fQPmq73XVG+N3sVHNt7vbKXNrVvSpoCS4m+p0PsFNztulo15r/gxcNeCaI9IKf+m8D0TSNFYYfOhF4k1aZS+74bWrcgYuOmeqv6XgdWR7mL9UjK6+AZryeUyEChjqydX8JGK8soYWOWNrTzV2u6GizHeOCFed8cZ4mXhdEjzlAcKjKxEO24f8qih37sI+6V6WokMW6+E/LZqQ/VxaUqMfTjQVoJ/RRsS79jBAoJ1yi5/oCu+3kHE3leNMMN7aJ+8nnDxuG+jW7ckYdNcjCFoSQLibTGxIbUPixXY4ZCDenuELGETWRy2wFuZllZBD+sRyLtcHPGREFO98GIgfNGBN3u+iCgY6jw2LRWUCkeLtzwWvx7WU4tTWDm3NYqhCQFuo1pH4ttX/ah/RnD+nt8tmdgwKcLeV+pOvNO/MAyBKNi9qbtmMexH8nXyC1immp0u3eVfhJ2DjWGAto43k904V7KJuUDnrlYkikK0sGX/w/qVUfPJFhjaFvF2bSDGAvywCQ53sO8ZgCTWUn66kkDgEpudtLQ==", @@ -113,7 +139,9 @@ "0xaea0c1b37e1e2705800f5b90a14284a9bc7eca441368b493516961b3a98e1a13", "0x341f062f82ad17beb00c8a01a18b17783cf2987fbf3174f768ca42a5a19069e4", "0xc6f3092dbe89d9406fc98aeb99de16f69c9045dcda1f9f72f81537c0e26ab71a" - ] + ], + "prestateLeaf": "3p7hCxhE1kctsBbmZZWQQ/rEci7XBzxkRBTvfBiIHzRgTd7vogoGOo8Ni0VlApHi7c8Fr8e1lOLU1g5tzWKoQkBbqNaR+LbV/2of0Zw/p7fLZnYMCnC3lfqTrzTvzAMgSjYvam7ZjHsR/J18gtYppqdLt3lX4Sdg41hgLaON5PdOFeyiblA56w==", + "poststateLeaf": "lYkikK0sGX/w/qVUfPJFhjaFvF2bSDGAvywCQ53sO8ZgCTWUn66kkDgEpudtLQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "+CYzcP/9LE+EdqOG+9a5RTQG00FP7wvzuwEsw/yuTYI+xxGehPkz9n5YKlJ3BrjkX3jQv2jKM98fMEvSkiJ2+u1sB66qmILE0m/4SDeSRXVphqrP758vExOEsL7NHEgBVd7IvslUFU7gSMZ0+ee1ee0CD8i51lBcpP7rQK3kheu+6RuNTQK+8SJ+bpWgzYqpXisZGIXDefKhANcQWDs+dg4xo/y9FyluuECVtzSGQxwDCLmZDfvKXLozcl+f8wMbRE2MXNMwVYefP6uy0/GgEXIDkwPH4o9dv65JBnlTyUDBEIdB/fbEJRneWTOxOl+SyRz8FLNCkygP953Efo0fcXpKjbIrzuROgxyI+3Amm0Hsj5Zl34RErO1p33m8NBnMK6jBHeXcWp/40tZTmF1j2TE8xyzt76cC9ancmkoipvVCUmyp3S1XWUQZWVrSCdY7QPLXcG81AsdoCwlOe7ZpL5h/b8AZ3wr6ccu3qjYtmfsRLkwA+oUTsNJ6Xr/cRUKhumCdDU0+CLuo6UuNTq4DNPVJNUF4XtFjMh/UsR4GfOts7SBtXjOQgIJf6YAl0S3Cl1bhR9g2hvZyuXxK8kTfwg==", @@ -123,7 +151,9 @@ "0x38c6d5cbf76e73a3fb3f8c056e936dccf9e8b2fe6379cebd58a5bd3358e0da52", "0xe0d2db8687a4e0f0e475fc73a6b4d01b4c2798588940c476313111c3e2eab19d", "0xeec6ab48f1d2149b86dfa43a21ebce258f2dee0f29cc3b133cf94f8eda6f2cb7" - ] + ], + "prestateLeaf": "7I+WZd+ERKztad95vDQZzCuowR3l3Fqf+NLWU5hdY9kxPMcs7e+nAvWp3JpKIqb1QlJsqd0tV1lEGVla0gnWO0Dy13BvNQLHaAsJTnu2aS+Yf2/AGd8K+nHLt6o2LZn7ES5MAPqFE7DSel6/3EVCobpgnQ1NPgi7qOlLjU6uAzT1STVBeF7RYw==", + "poststateLeaf": "Mh/UsR4GfOts7SBtXjOQgIJf6YAl0S3Cl1bhR9g2hvZyuXxK8kTfwgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "V+Je3MC72y9Nj/ndRQ22pHbmfIk3L04GyLRx1y8NdQ8MW/VDtk4DFoJytmVgYMhgk14XRGrdjnRV6qZjElRbxhYkKOCVPMlHfFSLRuJywuMrbZD/ED4enQkcwGBbc0y4xD7SGMxmAN/xe3s115EKb7CmMd1OJKgFXtWCxjqZw3+cTMckBaTamyAhF2wZOFqLCiwACHeaSNuxEfr4tnKt0/WORdepDMBFHQQ2PyyRV6rSpX/wC9n9hTipbADlW+UCoiM0ohC9s+4D89xUWElcl+e0EsomsKduFctgqrExO9O5qkY8buHJZWViNKvpoTaRBfeYCaiGh/rHOBzyC5wfp5gloXw7vOkWV1pB", @@ -131,7 +161,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x1f98ad3e4862403d0ab27479c5949c3e68f715806316dad1139287ae00e9e936", "0xe25797a6a442516c9fe6adff1104f7238df721e74f26494958ac5d0cfcbdad54" - ] + ], + "prestateLeaf": "V+Je3MC72y9Nj/ndRQ22pHbmfIk3L04GyLRx1y8NdQ8MW/VDtk4DFoJytmVgYMhgk14XRGrdjnRV6qZjElRbxhYkKOCVPMlHfFSLRuJywuMrbZD/ED4enQkcwGBbc0y4xD7SGMxmAN/xe3s115EKb7CmMd1OJKgFXtWCxjqZw3+cTMckBaTamw==", + "poststateLeaf": "ICEXbBk4WosKLAAId5pI27ER+vi2cq3T9Y5F16kMwEUdBDY/LJFXqtKlf/AL2f2FOKlsAOVb5QKiIzSiEL2z7gPz3FRYSVyX57QSyiawp24Vy2CqsTE707mqRjxu4cllZWI0q+mhNpEF95gJqIaH+sc4HPILnB+nmCWhfDu86RZXWkEBAAAAgA==" }, { "input": "RyWgwd+Qr5ZO+DBrEHeoHOYKkGSv27AC8AUv7u2tGD8nb4x63hVOAvXbiJNrHqz/hiKCN0PS04CHDVDuugALETTnNJbBzxsXxFQut7x1sQgTrfMI9ZYusMnUgKZU8qgNk0b1QYWEbTOvaCLpMQ9oeyjJbMqIv8X9eqZx8vwKreJvKEa7WWJIxCaLqhMme2Lyq7So2I9YGpAgo5QRbxHSAARLIdtUA66lE37l1Fx+JNlwcl4GD30X1sU9GUdZOtzSHyowWzjz0actn3rjVSmGaOuS3Ah2/gvjQYWC7i3M81anjhdV/2ZCY94AYpr9Lqs+kMxE+nAoBNmJfBoJTZBJrIPqigbSouhH0ijV/5TbuMwfAUQfxSI5ZXQMwdxGwuBImixeglEtxvaYqyM9OJz8n3RHlO8rbSIR8yxShm2SAMn3ry/GoRH5xlxUbLdWN/Q965PJUv0KDi8Vovdj+5ic1XCyLUvWV84ptZyiel+UZdb/CS9YHoPkbcp/GWQIvAUWpNg493eNfwbuZqI=", @@ -140,7 +172,9 @@ "0x9306fc1d963a177e83f4294d9eb3925accaed510895a1e3f574891cf55129601", "0xe2c0e7a580553e21a6a6871769ab80e27077320bc12104b8292fe3e42f753b75", "0x4927ece860e24003c45d18f0baec468dfd68e61eaef117b9568e2bada6743903" - ] + ], + "prestateLeaf": "JouqEyZ7YvKrtKjYj1gakCCjlBFvEdIABEsh21QDrqUTfuXUXH4k2XByXgYPfRfWxT0ZR1k63NIfKjBbOPPRpy2feuNVKYZo65LcCHb+C+NBhYLuLczzVqeOF1X/ZkJj3gBimv0uqz6QzET6cCgE2Yl8GglNkEmsg+qKBtKi6EfSKNX/lNu4zA==", + "poststateLeaf": "HwFEH8UiOWV0DMHcRsLgSJosXoJRLcb2mKsjPTic/J90R5TvK20iEfMsUoZtkgDJ968vxqER+cZcVGy3Vjf0PeuTyVL9Cg4vFaL3Y/uYnNVwsi1L1lfOKbWconpflGXW/wkvWB6D5G3KfxlkCLwFFqTYOPd3jX8G7maiAQAAAAAAAAAAAAAAgA==" }, { "input": "7uyV3gHKCTWno05X0NsqCo+ecSbBndWk2chOcOj9/OEdE2e8xZA9D2PwsHc0Pa/kD7Kz44HRg9tZ2x12S9+8tyrX1Xt3qSVa/rgq9tCp2pK47d/ErS2uMN+7z6Q5YjoCb8opZhOVJYMQ1ydyjfKHklPbkWwe5fxZ8kyX7v1om9RgetMEJC6N++NZA8EiTg==", @@ -148,7 +182,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x6aa1207bbebcbdb562d89afcb3cc5eedd746af84a099ee5782d39c02a444c866", "0xbebbf678447f96212658092d091eb3460ab4f40fd714c02f2526dc79e0853f74" - ] + ], + "prestateLeaf": "7uyV3gHKCTWno05X0NsqCo+ecSbBndWk2chOcOj9/OEdE2e8xZA9D2PwsHc0Pa/kD7Kz44HRg9tZ2x12S9+8tyrX1Xt3qSVa/rgq9tCp2pK47d/ErS2uMN+7z6Q5YjoCb8opZhOVJYMQ1ydyjfKHklPbkWwe5fxZ8kyX7v1om9RgetMEJC6N+w==", + "poststateLeaf": "41kDwSJOAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "TOjxDmmIhy7Mlq4a4V11/CFNbv8NeLrJ7cCi9m2fT537JagWJiMdobTVLNuN71dEO8ER074q5m93RkHwt7oJ73+iTUWGiYgfU5yo6hAIK8kV+Z/lL2p7SGza+xJkbTnrR5lfeNyhynrWGL+TqR54y5ZustFTvDEVWCTk87RjXYUHzseDkYE3JP8AHxKQzZgc3GCTsDjmrtzd1SkKb0s9uF15CfGJqAx+wryGlfkeWrAhf72hp5YGH8Umo5onUBWPvWQyRzHUFKv6LX92kGsJ5t9l9iSuYK6rSmMeTYM3LNM2V2S+vGreS+kzLWa1yJlaiQqN0mEJwdvSzTxbBwt6C4y76+hGmY3Puq7fzN5esJEdsXQh1JBjxG3bGZ2JsJHUF9xaxLN5XVRnMNwykHCW/AV4GYNVlB5tJvwY6bKORgvcf5pZN3iw5QZUVlc8a7KEoyA7e1PxSQiulTp1Jx5tD8WJkSFr8Yh3Ce5Pm6H+48LY4AZV2cWIbsq1FJAPMMxcmejnGxN1sG27SLP/HS/7YOJfclRTPy+ZR7DGcwBwj/TKWpWW/OTlMVv2mPrJVUvTD7qQ53PXdJM1FYQRMolHHFEK4ggJO7n12eyDqKR+aHZYLED8Izt8hUrpzAOTstFX3iov0wEr5N38ldQ2stYA7d/X", @@ -158,7 +194,9 @@ "0x07c48b7c309b8cff89cd1c96f7596ebd1218f588aac8238f5f81704780e4ad93", "0x43673747aca7a3e7428f4ed0702b099e4cb6b3a07b9d876cfe26c93827c7c48a", "0xf9cd4a3c8e8110e3d72dd2196cddfb4e7f7c0cb487743ab4b0d7c27e9dbb203a" - ] + ], + "prestateLeaf": "HbF0IdSQY8Rt2xmdibCR1BfcWsSzeV1UZzDcMpBwlvwFeBmDVZQebSb8GOmyjkYL3H+aWTd4sOUGVFZXPGuyhKMgO3tT8UkIrpU6dScebQ/FiZEha/GIdwnuT5uh/uPC2OAGVdnFiG7KtRSQDzDMXJno5xsTdbBtu0iz/x0v+2DiX3JUUz8vmQ==", + "poststateLeaf": "R7DGcwBwj/TKWpWW/OTlMVv2mPrJVUvTD7qQ53PXdJM1FYQRMolHHFEK4ggJO7n12eyDqKR+aHZYLED8Izt8hUrpzAOTstFX3iov0wEr5N38ldQ2stYA7d/XAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "AvTCu82tHn4vqAeJvRF0D0ZzROQvXqApfQS8wMMPGYeMKMoxv1ylmcZVy8449joQXyI/MCvRBw9ifmRPvvQrz6hAEFrrc9vnVeOGZ3JO4kqqwtXCsBk0uWdX54fTJwKltF79gR2FUWv6jdub+vIPPc/2GNV24VwrYCLJKM3ngc/V6MjklLR2SUufmcU13Nz1GZrNegoEwXzq3SjSX7Jy+UBMaD3OIqwB6TP83BHVlgDGSmyROUcFtXs/P7xakgS4ehCQImklzuDO9DRdMOHM8QVG+7Ru5liTcdnLHGZmuw9w15xzukp3lcBz9r0YE4JpNp88jHSRWy9je1YLiQZqCzsezJTZayTV+PDg7yhzknV7I9ilh9F2Km715Uq8mfqLoSu3P8jhFV6TpfxdbTsf//GiOj2vn50p1OTpw4szVojg3zKFM8LBIsnBlZlhjehSik5/UgXkXidGxftAIgs8QpK1ZM9+Egq77myavndGABvf4Jdj4evZPxg/7lbfF5M5NMRta3z2EL7F", @@ -167,7 +205,9 @@ "0x7ecf008045f77c20bef4585b6fd642c26fe09f2f56a5acb504cfd4bce2e3fadc", "0x253fb668c2363e1f74df922439adbe18e4825be8bf1f900b13c63fdee66855c5", "0x9280e4e10b784a59a620a6e7f6486dc9191529cb19ecb76a909cd99797f269c4" - ] + ], + "prestateLeaf": "S5+ZxTXc3PUZms16CgTBfOrdKNJfsnL5QExoPc4irAHpM/zcEdWWAMZKbJE5RwW1ez8/vFqSBLh6EJAiaSXO4M70NF0w4czxBUb7tG7mWJNx2cscZma7D3DXnHO6SneVwHP2vRgTgmk2nzyMdJFbL2N7VguJBmoLOx7MlNlrJNX48ODvKHOSdQ==", + "poststateLeaf": "eyPYpYfRdipu9eVKvJn6i6Ertz/I4RVek6X8XW07H//xojo9r5+dKdTk6cOLM1aI4N8yhTPCwSLJwZWZYY3oUopOf1IF5F4nRsX7QCILPEKStWTPfhIKu+5smr53RgAb3+CXY+Hr2T8YP+5W3xeTOTTEbWt89hC+xQEAAAAAAAAAAAAAAAAAgA==" }, { "input": "KxErXRtL1JhC7Tl36SnTA6yN1kPJ+FHWHd9Qw3EL1nx7/WjXd3adHalOH+IoiUE8avgcjU0OswihibvyaphqgjYW4aFleB50E4ezd6d6mh5uWbXJM1NXdmUH8BBwCmLoJokM8lv16OJSqavrVRUEcY8Ldl09pmg83KO4wRxjhVe20DUWBnTXztMNlx4HaAcKN7Y67KZQ3m9Oos+CdAL75Wytioo0WVYhef2zg2ZdreOePOACaK+6alFL81Iki/C8Uja2v+YjX8YUs0AsfOpWOZL/Fn8p7BizAwYj", @@ -175,7 +215,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x8a396ea38a21ce7e46777864c464f655b0774045c084d8aa04d5f62ce1ceea4d", "0xf72e61753fd7f471e01d8ad73e725b8251d981ff03161a9b21c195b59bb9e05d" - ] + ], + "prestateLeaf": "KxErXRtL1JhC7Tl36SnTA6yN1kPJ+FHWHd9Qw3EL1nx7/WjXd3adHalOH+IoiUE8avgcjU0OswihibvyaphqgjYW4aFleB50E4ezd6d6mh5uWbXJM1NXdmUH8BBwCmLoJokM8lv16OJSqavrVRUEcY8Ldl09pmg83KO4wRxjhVe20DUWBnTXzg==", + "poststateLeaf": "0w2XHgdoBwo3tjrsplDeb06iz4J0AvvlbK2KijRZViF5/bODZl2t45484AJor7pqUUvzUiSL8LxSNra/5iNfxhSzQCx86lY5kv8WfynsGLMDBiMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "XCg8YCiTI2f46kIaq7zPtH6/qXjsCjjTqJ9T8OIRWrxk7S44HcXD/V72OryGTkghwWJEaZGE3h8iSOeimpclxuVoHl2lgucVrja/U9cqgJryH3pMiikQnrIxRiWLdVfrkYK9F98iNxwd3cbZMYd6MfH620ISHBek84dz4+Ae+aeyLlUd/CKwHZ1CZYOymLaRvlkviy7vhqq9Fyrf1FYXg+bp/gLUxup9cNsX1Q1/OVbieyhOFd39rXJ6ACxWfGZCMPJ+Wuse7ngKebZ2he+G96hX2dUWGSOYxsiozqoP9kg=", @@ -183,7 +225,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x3840877367d901f1bf14f3d589aed7e83948595e0222868a08b59873cb9230df", "0x4ea862d23c02f1a6cc17dbf5ecf1822fa357304128fb6d2edb82a640b0a3ee09" - ] + ], + "prestateLeaf": "XCg8YCiTI2f46kIaq7zPtH6/qXjsCjjTqJ9T8OIRWrxk7S44HcXD/V72OryGTkghwWJEaZGE3h8iSOeimpclxuVoHl2lgucVrja/U9cqgJryH3pMiikQnrIxRiWLdVfrkYK9F98iNxwd3cbZMYd6MfH620ISHBek84dz4+Ae+aeyLlUd/CKwHQ==", + "poststateLeaf": "nUJlg7KYtpG+WS+LLu+Gqr0XKt/UVheD5un+AtTG6n1w2xfVDX85VuJ7KE4V3f2tcnoALFZ8ZkIw8n5a6x7ueAp5tnaF74b3qFfZ1RYZI5jGyKjOqg/2SAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "3tCzFeEQ/cLtfrIrf3xDuG3HIlg3bn9sOR4FFzYSjPqma9CORBkKrq1myqUT5/WFkFRB+6zj/17Kbl/T0M6BWTgQZktrDpup+xCiU2m7ZKqvYImjW1X638odReqVo6XdrC6NyFn9YE/ssHioUKX5FMs3X4+TLi9UmW3brrNfrkw+lum704sAPctDtMwh/LVPapDfhqZlG+f6yTrmp3D6oBLqwcrAMNjIJ5LRJHsI31XG9/Pcd99qCPyg/xzcObVq9XyDg5vX22dSDe204eesHUyfsc1z7Et6MQY99MW83Lp1CGKJc7EgDgj3", @@ -191,7 +235,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x2b345b6138b0af72126dacf2bb933135ec22d9927e66905753ed4dd7673fbcc7", "0x14b3d8fae959461ff1a0682c7e82d63477b4a1bdd83fd7425ae51bd1df4b3188" - ] + ], + "prestateLeaf": "3tCzFeEQ/cLtfrIrf3xDuG3HIlg3bn9sOR4FFzYSjPqma9CORBkKrq1myqUT5/WFkFRB+6zj/17Kbl/T0M6BWTgQZktrDpup+xCiU2m7ZKqvYImjW1X638odReqVo6XdrC6NyFn9YE/ssHioUKX5FMs3X4+TLi9UmW3brrNfrkw+lum704sAPQ==", + "poststateLeaf": "y0O0zCH8tU9qkN+GpmUb5/rJOuancPqgEurBysAw2MgnktEkewjfVcb389x332oI/KD/HNw5tWr1fIODm9fbZ1IN7bTh56wdTJ+xzXPsS3oxBj30xbzcunUIYolzsSAOCPcBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "bfAo9s0t5LyD6E/FL3YItSp7iHRxZsByDcTBKVGLTTYZUOEWd5PDCX0J5GgN82XcwfW8zko0e/ejkOrDk0fvVefhLAD8pcG17MbtQ4wnZ8yKUSAZjA5LMA1gz8MpSMsDWt77ZNb2HXGeHNL8BWu7WhuGzm8d2GpSNCm0b7IpY6mBi1m8LNByXyxkHauXXkNgK4qM/gMHWwsPsW7V344EtcM5YjhT6rfboO1zuAF2udqcZblSuHEQmq8psLJj0mj7t2EPY+p1yxmax8zkfG5qlJUNY+jOTiACzMGGFBOh373aC1MrrVd+Et0BX6IC+k46gZT/jIs2MBMeKl/0NGG0urvHvayTLJXYJEKzplvyDaR7PrUSdxprJIQHfrZe9LnOlZe4PIw1LHo2vrbJ+9TJPR3izoeeUPeIIQjSSG28NzJ5Iar+86ZdSTEI/LnXEaAYSvQ7X28ShxZuHThkWxi9q8pdEv9BWXc=", @@ -200,7 +246,9 @@ "0x70ca6cbbd65222ea5e90b0c595d1cf55b423e1503dd07edaffc5a4a8babf3004", "0x9e04f3082de4ecf1669b7cb0b458a8cafe452a424b395808cc2262236b71b729", "0x115b8dba0fc4524995038e8e06953799cefd0119c75b306020ec53f884480e8b" - ] + ], + "prestateLeaf": "LGQdq5deQ2Arioz+AwdbCw+xbtXfjgS1wzliOFPqt9ug7XO4AXa52pxluVK4cRCarymwsmPSaPu3YQ9j6nXLGZrHzOR8bmqUlQ1j6M5OIALMwYYUE6HfvdoLUyutV34S3QFfogL6TjqBlP+MizYwEx4qX/Q0YbS6u8e9rJMsldgkQrOmW/INpA==", + "poststateLeaf": "ez61EncaaySEB362XvS5zpWXuDyMNSx6Nr62yfvUyT0d4s6HnlD3iCEI0khtvDcyeSGq/vOmXUkxCPy51xGgGEr0O19vEocWbh04ZFsYvavKXRL/QVl3AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "Fn/bjMz27Pmo0ojZ1PbO1pulKlSVEA3NkoaIXezePMDDWhuLfbwngufLxwoyPb3cDAg8JZWXaE0O+liog7xV0p99KYUVOf2bmXcc/Yx1P40ikNkJT2zhhUoqaPBgBAsfSvw0eGBNmTer5Io/sjCdAaY46UnAVG0m303QSc7seGgY52p3Q+p0fblbjieR0iDmtStbnmeRMoc1CybVEWrkUM8mhnoHGzP8fe5i5BIOhGdOEhFEfNr/E128wwTjRYP80nAPZO2vx3sSIrYBl1uAAxglTZd1qqY8ds3LRAT7ioZSImxJgoGwQhaZ2g8zGBFRQlXu", @@ -208,14 +256,18 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x5bb3fd28f16cf712e71ef328668bddb7304a23900d57281146e3d11379f787a1", "0xfa09386208b45515b49b97f859070db73d59b4d5a701ac3925c9ffc65c5648a5" - ] + ], + "prestateLeaf": "Fn/bjMz27Pmo0ojZ1PbO1pulKlSVEA3NkoaIXezePMDDWhuLfbwngufLxwoyPb3cDAg8JZWXaE0O+liog7xV0p99KYUVOf2bmXcc/Yx1P40ikNkJT2zhhUoqaPBgBAsfSvw0eGBNmTer5Io/sjCdAaY46UnAVG0m303QSc7seGgY52p3Q+p0fQ==", + "poststateLeaf": "uVuOJ5HSIOa1K1ueZ5EyhzULJtURauRQzyaGegcbM/x97mLkEg6EZ04SEUR82v8TXbzDBONFg/zScA9k7a/HexIitgGXW4ADGCVNl3Wqpjx2zctEBPuKhlIibEmCgbBCFpnaDzMYEVFCVe4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "aKNFw0pM0XmPQULBOYhXDEpG7xyGpTPpLKWdfAqcx/TsA8M5fxeCyWV01nQK", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xd587c1123b4ff0fa464810067afb76c630d2f55e699e10c87c0a0ef9b8066fb7" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "aKNFw0pM0XmPQULBOYhXDEpG7xyGpTPpLKWdfAqcx/TsA8M5fxeCyWV01nQKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "1AjkmC7TXNJh/LirlVsFxMYFLR0QNB4Wiwi16JAepiRK42RpxBrbhNPOIJFX16r+vK31OWgJwxlCQamOACegcfgDYj6dRhQolfOFs8rccy7bYLsvUA8wgg1LBs4iQ6GJgZHkpaOq83zxZSqiZ+wNyhBH7ZRayhkti1XAbO3zZxJaG/RHfP3JKs6m/VOA7A47/unOIwaZjIsJZPLJABJ+wAhAXNQLQlgL+Tt9JWPr4mWW3d+K5iMNG4R7VJC8Y9MPVWX1P1/h64bToqRj4ELOp8nxsbDmEEnPmXpm", @@ -223,28 +275,36 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x7c5a831165523b98e237daa7ec4f137fd85b4dd3e667bc49064cc31965129850", "0x61fd8ed7abeb89608f8e48309f153b8885b4b4e4bea4c3b7e2c318b977737092" - ] + ], + "prestateLeaf": "1AjkmC7TXNJh/LirlVsFxMYFLR0QNB4Wiwi16JAepiRK42RpxBrbhNPOIJFX16r+vK31OWgJwxlCQamOACegcfgDYj6dRhQolfOFs8rccy7bYLsvUA8wgg1LBs4iQ6GJgZHkpaOq83zxZSqiZ+wNyhBH7ZRayhkti1XAbO3zZxJaG/RHfP3JKg==", + "poststateLeaf": "zqb9U4DsDjv+6c4jBpmMiwlk8skAEn7ACEBc1AtCWAv5O30lY+viZZbd34rmIw0bhHtUkLxj0w9VZfU/X+HrhtOipGPgQs6nyfGxsOYQSc+ZemYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "7GzH5TVEhQ==", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x1a1f489ba334d4068d05ea8347fd83a14a73082101f8d2daba09553485e73c60" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "7GzH5TVEhQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "x9xGIRFaMdQq0l4MEJbBDSzCSTZLsd/0UkOSiHtALhd75Gi/c7ObBdk=", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x1811020a0424b78b1697b9cfaf67ea339be0988c5bfa859725bfbb0aec7ed76a" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "x9xGIRFaMdQq0l4MEJbBDSzCSTZLsd/0UkOSiHtALhd75Gi/c7ObBdkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "O3mF1GL0vHkl1aZEKundwta4m+07cngnlLAtOOlhZA2n9NVQHvffMRc7kgg1zs9nUWNPUcj+O994cRWgMC1k", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xdf980f53d2c8527c8438791243c129bd2aadb23872502fa0e4447e1b0b2202c3" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "O3mF1GL0vHkl1aZEKundwta4m+07cngnlLAtOOlhZA2n9NVQHvffMRc7kgg1zs9nUWNPUcj+O994cRWgMC1kAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "h0RMltv7EyhwfqVLrCEDhVvTJ1tNmbM+C0InbnQY+Kk5eUWfMUMHvUqR/Qgmg9aLlmoFROkcUpfH4AcMm0eFlxnav5yoWlJJmkLKR0CWUAT1jhsxkLOVqpNPWKRvl1IZSpgPW2Czp9SlYP7Z7yfrIovxoNM3qjNWiiXQIqmxl9rKXcXNY/jo0jla8avWXD7lIF7HbE0IWxNTqSwGc111TQUMrzRyonNz2uwW+2YzC4hrwJzkUfAe98pc7qWDv5iJyOU6iPhymXr1Rgead3DRgE6gpdOrVwWqLpUFajhk8LVKH0muEVsQqkSL3/RkuxyYJ1SdbZG0FD70wiGSTBlY", @@ -252,14 +312,18 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xfa1bafcf85ada822d18184fbc939be33cd6bea9203d763a6baba6daa13e925c0", "0x175913e44136b3a8b1eeb4ecd8544a12d5d79b98885c2453c7823a958245953c" - ] + ], + "prestateLeaf": "h0RMltv7EyhwfqVLrCEDhVvTJ1tNmbM+C0InbnQY+Kk5eUWfMUMHvUqR/Qgmg9aLlmoFROkcUpfH4AcMm0eFlxnav5yoWlJJmkLKR0CWUAT1jhsxkLOVqpNPWKRvl1IZSpgPW2Czp9SlYP7Z7yfrIovxoNM3qjNWiiXQIqmxl9rKXcXNY/jo0g==", + "poststateLeaf": "OVrxq9ZcPuUgXsdsTQhbE1OpLAZzXXVNBQyvNHKic3Pa7Bb7ZjMLiGvAnORR8B73ylzupYO/mInI5TqI+HKZevVGB5p3cNGATqCl06tXBaoulQVqOGTwtUofSa4RWxCqRIvf9GS7HJgnVJ1tkbQUPvTCIZJMGVgBAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "Gy9pBTkfOeD0fUr8zbC58w5zP6YqVJZGv52nGLRXSlBlWeJLI35GmP219qhBhPZipJID71G+Hmjea/IB/N4poRzxS+9Ky/7wQNWMOadc/d+VVADXPu71Cy9IV3w=", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x85baa18bcb8dac402216a7c99c6bb508bfc96caabdfc83c7bccc0898a0389910" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "Gy9pBTkfOeD0fUr8zbC58w5zP6YqVJZGv52nGLRXSlBlWeJLI35GmP219qhBhPZipJID71G+Hmjea/IB/N4poRzxS+9Ky/7wQNWMOadc/d+VVADXPu71Cy9IV3wBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "JstIxj+GOiDJaEtSsZLg0MDSvXRLEFo3DhAkyInR0UA/i+s4R4YYvGUw0TCGsWsGepVPFYbTK+iivctM8ayPPEQGsFCVbKj78kG2QiOswmFy57L/8HhNatetUY9cwMDXwUY+z/7pEsh7GjfL9Sb60HKJ6a+imgyxiUbYdbx06mLfwRy8O4xn0ZoUZKacGvR6XXfnKkBx6EZnQ4X/CmRJGEMyDtm9f+386hlnYVyrZKgGh0C8NiLh++Op1jSYUJzCDkSet1ZFVXo1pAEzSCR3cueBzR1M6GM=", @@ -267,14 +331,18 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xe3d55fc5170899ae0ca36a90920c6ca338608f4a5dcd8d93e44e234f36917d68", "0x159eaff490f4841410fe8eded5148778aa5ecbd0fb1bd908f992a85b36e9a613" - ] + ], + "prestateLeaf": "JstIxj+GOiDJaEtSsZLg0MDSvXRLEFo3DhAkyInR0UA/i+s4R4YYvGUw0TCGsWsGepVPFYbTK+iivctM8ayPPEQGsFCVbKj78kG2QiOswmFy57L/8HhNatetUY9cwMDXwUY+z/7pEsh7GjfL9Sb60HKJ6a+imgyxiUbYdbx06mLfwRy8O4xn0Q==", + "poststateLeaf": "mhRkppwa9Hpdd+cqQHHoRmdDhf8KZEkYQzIO2b1/7fzqGWdhXKtkqAaHQLw2IuH746nWNJhQnMIORJ63VkVVejWkATNIJHdy54HNHUzoYwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "/tWP3uV4e9CVYkPJL8Z4kw==", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xf38cdf1a78988c925677b1078d433a759ca4500334818977f2a480532921d78d" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "/tWP3uV4e9CVYkPJL8Z4kwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "bQHlLQQAa9z8oay/nSDVQJURbG/WJkpRBmzYuxfSn7gtd2BWzMxBYegXsaZ4HtpSOIYfRJQX6q2dASJI+naNH3BcUgbcn63G1XeyaZdEptndY0d2JqnWQjMEsurhZE+xJYhdv3PISfZxeSbxCiL1xE3vPfqbJ8zz//E1C+DSnHMfOc91tf09bBBgrqsfUyarZkYoT91m8mTZhEHfXE6Go0lEe4xuKugeArM3XIvcaen/q0i2Om3mh6dddYaOVtpy1tuevw==", @@ -282,14 +350,18 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xddcb88fe5a9d0df55e4c94569523b05b58eb515ca6114674f61e9721c8357f7e", "0x4781cefa8e8bdb384f677c4a87ffd201f31980eea5ed4c321b5770bd6d5bb9b0" - ] + ], + "prestateLeaf": "bQHlLQQAa9z8oay/nSDVQJURbG/WJkpRBmzYuxfSn7gtd2BWzMxBYegXsaZ4HtpSOIYfRJQX6q2dASJI+naNH3BcUgbcn63G1XeyaZdEptndY0d2JqnWQjMEsurhZE+xJYhdv3PISfZxeSbxCiL1xE3vPfqbJ8zz//E1C+DSnHMfOc91tf09bA==", + "poststateLeaf": "EGCuqx9TJqtmRihP3WbyZNmEQd9cToajSUR7jG4q6B4Cszdci9xp6f+rSLY6beaHp111ho5W2nLW256/AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "evoB", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x38859b60e7bc24fc4fb617ce269ca5eb01359eaf45a40b0b50f9248cf0904a32" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "evoBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "tC4HUMrXZ3p1UM4PpGTSYOjLWuLb9BUCGwbTU317sa/az2/NlC7+96kJyL+NVS7+b010XdHKFtS5RcuANAgyqSEwSvV3pTA0wmUymaERp2yEVlwfWwLz7/COl10+rLOft//Q48PVuYxqswRCpbWC570Jfz6RPAX9CZtbIe7+9Jzxfp4hIPlqC4dBuiGoIAuRu7U3jssEYLjtjlWTn5Kip9VYyYyzhMshcYQwOsvm6nIGe2aD9DtqICEaPCAu3mUEIKZ3B1BlyiEkMk3RoTI0n00PxgzKnSZ/MgdyjKoAhV8OyN/8PJJvNB3Jhqiblb+pVhP/DYilY5eFJ3Oy3YpPZcknzX9GwirQP+jWr4N7spt0c8Wzssi0cHXOxLkcy5MuHMrvkcI5lih5HQyzo3Z9rSS5apDdidANjar368I4f9HwPquq9+WRA90qf9dhFp6KlZotH4LzrHyIbPSshpIhgwg1bnVq15PICPT29MSH2I/LrS+RWnNS3A==", @@ -298,7 +370,9 @@ "0xbc688ec6014c19982e8950edc434aab78dda6c284b8bf6685c1ba6199c65005f", "0x837c62188c9acc191b9860e11d5607ebf25715bb4ed725b62eb0051bf7842420", "0xd4cb178f83a9174a2f984aab73b0d599f288cb7c8df9ea7643194f63456c0a1c" - ] + ], + "prestateLeaf": "h0G6IaggC5G7tTeOywRguO2OVZOfkqKn1VjJjLOEyyFxhDA6y+bqcgZ7ZoP0O2ogIRo8IC7eZQQgpncHUGXKISQyTdGhMjSfTQ/GDMqdJn8yB3KMqgCFXw7I3/w8km80HcmGqJuVv6lWE/8NiKVjl4Unc7Ldik9lySfNf0bCKtA/6Navg3uymw==", + "poststateLeaf": "dHPFs7LItHB1zsS5HMuTLhzK75HCOZYoeR0Ms6N2fa0kuWqQ3YnQDY2q9+vCOH/R8D6rqvflkQPdKn/XYRaeipWaLR+C86x8iGz0rIaSIYMINW51ateTyAj09vTEh9iPy60vkVpzUtwBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "EC+6W9qOHpBbkZ4bddtI5XLTkI+RqMvwGV30CdmjcFck/tJGV+6slQu/zD7YqL/hSHCZiqV+uzfN7qohYLSv6SRgnRDcnvcOT5Cjpg8asRH8ZRjBxahqXnVIlY9nOIYoyu+HqMUFm6TJNorPTtiIpUMW1waBYDOFhEBEtAAdS9U80jrf3WmhVBOCVURwQSveLHzZNdZxIHzyOFmZEkijELI/m3Ob/isfh5udJMk0yRTXq6jO+bATgzPegfRjaxSIA8l527VNR/MEuopKB6Cfza9TgWdTn04hk3koxI8BvExOxBI5a2SUm6ZKbI63QgbaTkif+NDIS5GZkIrGPaO4Dyk2gxFAzPWnoBVmAr3TO4BnXdelxSb80ROee74zVVOqQbEAE+caMjXOHCXQZY25grC9ufY4iqMNQRKAiUg=", @@ -307,7 +381,9 @@ "0xbe64214360727aaf82768e2c8c6eea5f5fbca0f0a6a8a5d4bbeb2aaa999cd9b5", "0xdcc702820b8512ab42e85ecbed1c1ad91bda6f27dc3d5c62c01c5e2cf6b55f58", "0x4bc0af92dea76212482183a6822c450d3dd2babf0451f14fe107b4a4bb962a50" - ] + ], + "prestateLeaf": "E4JVRHBBK94sfNk11nEgfPI4WZkSSKMQsj+bc5v+Kx+Hm50kyTTJFNerqM75sBODM96B9GNrFIgDyXnbtU1H8wS6ikoHoJ/Nr1OBZ1OfTiGTeSjEjwG8TE7EEjlrZJSbpkpsjrdCBtpOSJ/40MhLkZmQisY9o7gPKTaDEUDM9aegFWYCvdM7gA==", + "poststateLeaf": "Z13XpcUm/NETnnu+M1VTqkGxABPnGjI1zhwl0GWNuYKwvbn2OIqjDUESgIlIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "ZeDJP67Sw5nYOdhdEIfRUVZL1fFstyMtPOsqF5UYQzOBhgH8dpwpjuvcN6/O1uhtGhFWwbljx/jcazFF2BWfBWf3eC0LWHRMPUiiD6OLrV6k+zrS2yWxqGkulIDOndPUaVeFKZWNSAEi19zmckdy5ItruOIDgo/fBDsH9Nvz/2Wk8j2HkuE+EE+nR9Y9M4fnH79BZk0iTqaDCjwO6bxcfX7yWOHJiWcK6Dl+9fP/Ol24E73andCsbzjcqRs3", @@ -315,7 +391,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x1bfaf14d73c3d16d6277777e30253e43da7ae876a245749379bc2870f8f9fc35", "0xfcfc506a0bca1c16ff13fcf14c7f4f1efd72cfd3d74aa17e61ddcbcfe56258a9" - ] + ], + "prestateLeaf": "ZeDJP67Sw5nYOdhdEIfRUVZL1fFstyMtPOsqF5UYQzOBhgH8dpwpjuvcN6/O1uhtGhFWwbljx/jcazFF2BWfBWf3eC0LWHRMPUiiD6OLrV6k+zrS2yWxqGkulIDOndPUaVeFKZWNSAEi19zmckdy5ItruOIDgo/fBDsH9Nvz/2Wk8j2HkuE+EA==", + "poststateLeaf": "T6dH1j0zh+cfv0FmTSJOpoMKPA7pvFx9fvJY4cmJZwroOX718/86XbgTvdqd0KxvONypGzcBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "+2Sm8j0qq7iqM0k3evWER+e28ZIHbQYaXV79/6cPAkBd1pcuCsA2rsFHJ4YE60RtUviaiDKZmn+yrEd23ZET2De0Ws+eYO/V+D/qldWvL8LI87BSuy62adDjq6bO6e5sEKsopovHiJDYq1LALR+EqOftQPvAT4/xC8yoFEC/rV/k81QmGJ4cpmG0zYOJpIeAZJ+D85AFCDv1M/yj0tVVdhYmcQCobbvUMy7EblzJZs5ZFnuJ78D/6LH50Ldy4H37AJH3pptsV80D0vvPQU5zdVfUA4swUYSQqRw9KGrtjGQgCCHHLrSQzFcMbpvtDsZFb56ix/JWGLKLVVGbA1btq80RH90EFG5IcXo7VyIqGnDQIPJW8hQk1vAluokZ9dciBhkVrsvg5mg4f4clZ7TN0G/uXBzkF9mzjRo4qvGHyIRYqL94kWMZHT8EkeQ27tcXf49hBkBA9ftF66MzMrOiiPaESYhCCyOFHI6iIy7587FfDDUGE0wkNbafxkvZtgJ7e1s20Dtu3d0aDUH1szIrWIvrfRpe7mbP6/+/9EXMwOK23lC+MCm/ykuK3Px8l5jHIEvj/0ZMlIn5OWjTAEY4G1c=", @@ -325,7 +403,9 @@ "0x6c2d4ce7ac4605c324e7a23628a3846b98d28af41db84680d8a598670dee9928", "0x40bce7b1abce938dc4f8b76c8dca3dd2740096a8e1f511bca4c6ade3fe730220", "0x8181226e378240f61866948ba6984e16009879643db599225dc170b05b584bec" - ] + ], + "prestateLeaf": "0CDyVvIUJNbwJbqJGfXXIgYZFa7L4OZoOH+HJWe0zdBv7lwc5BfZs40aOKrxh8iEWKi/eJFjGR0/BJHkNu7XF3+PYQZAQPX7ReujMzKzooj2hEmIQgsjhRyOoiMu+fOxXww1BhNMJDW2n8ZL2bYCe3tbNtA7bt3dGg1B9bMyK1iL630aXu5mzw==", + "poststateLeaf": "6/+/9EXMwOK23lC+MCm/ykuK3Px8l5jHIEvj/0ZMlIn5OWjTAEY4G1cBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "L+x6UWa4Rgm5LHUcwpki2J9NtnTVoIGMbYopms9v/U0bicETMtSC15rxm0KvOSkekklULQLz5CrvoFl8ikQKV8tTnedD5UWWjtP40Qs0MCDUJVzbdNZKzQaPY40vO4bMt7A4wv+1tRtM+eH1RkEhvil/lpZd9diiMxFkjKt3EFZ9uxD3r0KGtFmdwPCXec12tcT42t2yucXEPVFJu3zhggp76H7FPeO8GjAHN/paoNq3wNsIIHfmPXyWaQrq7I+cMd5J5eDRKoct4ZjALXXGT1+5QLIGWctzxq3jMCz7vP6XUlRqUOntEtkliCK/7e0S1ELzlG0=", @@ -333,7 +413,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x8587343e3e6c2059a0335c44fc19a11bf63cb0790e3eb8e57173ef54bfd363b2", "0xf38b109226bec4ec6685d4253e00c26c72aabb581b2376ecf07a475b559733c3" - ] + ], + "prestateLeaf": "L+x6UWa4Rgm5LHUcwpki2J9NtnTVoIGMbYopms9v/U0bicETMtSC15rxm0KvOSkekklULQLz5CrvoFl8ikQKV8tTnedD5UWWjtP40Qs0MCDUJVzbdNZKzQaPY40vO4bMt7A4wv+1tRtM+eH1RkEhvil/lpZd9diiMxFkjKt3EFZ9uxD3r0KGtA==", + "poststateLeaf": "WZ3A8Jd5zXa1xPja3bK5xcQ9UUm7fOGCCnvofsU947waMAc3+lqg2rfA2wggd+Y9fJZpCursj5wx3knl4NEqhy3hmMAtdcZPX7lAsgZZy3PGreMwLPu8/pdSVGpQ6e0S2SWIIr/t7RLUQvOUbQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "SBpvZe6U4DpWPmgdDCMRTdWN3kLWrzjM6uKzA2/08baRIUhYguRJeP12DgO6O7XYMyzJMPffzpoqtbEBcdneMLjP+V/qt+sA36RDAyPusmMgx1tX6kA22+ddJyF4AxQEyh3gEjiMFBj+RAu27qiP22hdBlQDbkzwfMjkf7MqWJ/JqrBZXkkUIn9eCEKci7llGB44Vd0In7nssZ5XnMIq/wWV8NlUABr5IQEMstGWVN1ujOTl9ATinpFGqaKSmcXsEiOkDRuBJ3IAyPzbjPv2jDwfon63IIWa3gWTKkhXN03n/Wkx7YaoLiI1/NNU3i+4sJp8j0YWTJJUcuMYRkN6H+o/3bIS+TB//GO4vj66MPHWK+bpGZgv7dslUpowS7c9+DRIF2peKR6SV0zhMzdfjghPafu32/e/FsD5kbs6YY/5oRuFHqYgCobjJxyrEdMdVoE1/ug4OnC/TywE8krvpmCNrlNvH+YJ5I9/BIFOsg9PObjX5gxnJb4Ziu/+2B3phg5K7IGen+yTp61qwmZZxQMCWr4cc4/x1/c1uDcA15UIBO44ezvtfevdt4VQJCVMcbkSbZOIEBirKgY1a24uFFfy7IKLa2EDFWSyZxLwwBPbI4OM4UqltlNs2UN2soTAK15ODQ==", @@ -343,7 +425,9 @@ "0x422817ae854712d4b23180f01303cbe6eb53d13152059619433a38999cdc32aa", "0xdc0935a99ce5cbe914c53d7a83d7cd735ad3b8d8bc4b833ad411cc815f3dec98", "0xe46d6fcd0fd03eb50aa8d43420f3234a15387cbac907c9fbdde1a914a01e624c" - ] + ], + "prestateLeaf": "1ivm6RmYL+3bJVKaMEu3Pfg0SBdqXikekldM4TM3X44IT2n7t9v3vxbA+ZG7OmGP+aEbhR6mIAqG4yccqxHTHVaBNf7oODpwv08sBPJK76Zgja5Tbx/mCeSPfwSBTrIPTzm41+YMZyW+GYrv/tgd6YYOSuyBnp/sk6etasJmWcUDAlq+HHOP8Q==", + "poststateLeaf": "1/c1uDcA15UIBO44ezvtfevdt4VQJCVMcbkSbZOIEBirKgY1a24uFFfy7IKLa2EDFWSyZxLwwBPbI4OM4UqltlNs2UN2soTAK15ODQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "2QJIWbRUBBG2N/NWq/0sBTi+1xV17LSEombqPr1d1B/e+PRV7KV7a4ztE6rAwCfaFXzb8O/muDh3Wkcs29q+0FSkdVrJEUWH77XEvrjg3j/thC4ARnE/Usy7b/+MDdJl+0p/7uuF+bUbYsF6NgJT4WHqDSiGBs5ZGiwPe8gBiDX2HEyLQDQDEAtcAVbLI8on23epD9/cCS91UygxKYrx1CZyfRYLYEKZ9LyH0ltmll0AqGRvQHuCHq/obtlnW+wfw9Pg+E/0dzMX/B0ESCIKBTgLFLCTupSvV4rwYxo7yHYcAvIKD67HECyncSqp6yVSbsxavmNzlWgo4sfjOhWmPGUsQSb5gmw+5gccDOWmTouTVQ7tOkP8A4n3UpUM04qDQtgbhSWSuxtJ9bb0wPtavJVb1fsZ7N/zb0URAG3M5Kye7ZtDYDwhgEjS4+MBb3DbBilViAuIM6D7fHXpdkSi67TOMmoCz0JWaaNPuWuHxVixPckB2uE8M6cXSNkUVyHsWi1+VVJqHq+bLTSSt76F+EBAICDCtGpmoAxcYWZIXU8xfDG4osgoAyROyR5z18m6Me4Llcw=", @@ -353,7 +437,9 @@ "0x90f85be195450bb1744d71057b67c90c1b75bb59d8cf4c3bdea1e757f28f7655", "0xa284918096cb63f386d38a9493583da530c7937ed570c5f6bfc952c99ac76959", "0x6597135748dd127cc5f095c2da3b7a28a78aa67b4e1fc218ec090defc1201fc0" - ] + ], + "prestateLeaf": "k1UO7TpD/AOJ91KVDNOKg0LYG4UlkrsbSfW29MD7WryVW9X7Gezf829FEQBtzOSsnu2bQ2A8IYBI0uPjAW9w2wYpVYgLiDOg+3x16XZEouu0zjJqAs9CVmmjT7lrh8VYsT3JAdrhPDOnF0jZFFch7FotflVSah6vmy00kre+hfhAQCAgwrRqZg==", + "poststateLeaf": "oAxcYWZIXU8xfDG4osgoAyROyR5z18m6Me4LlcwBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "Nn2tikbbV4mNX+t5FfPtWH+fYknuGvo/rC2dAmatoA6PAOCuRlWM5ogABBwX+LAXjJeNX5AL/L6TRcz4UGNLsyo/1V4ZNQe5+NPQxeh/2470e5z3QsvL27C+ZM7kOHXOXjcNEA7+0ikU9bDXxOIRxjni7KmEW7SGA8XItKI8HV0QlDaW5b9irY/nNVJz5kXHlR1scXVTQrLAjT37kWlvuZd8Ue/5bknPdH3Ix5Gvk9zGpthAmwBpmVAXCF3BWiZtLCJE+aP9tSiWCn+ezb83mmHTktLrar+xWZYXSf82cIIzgkPnPiWL0xz59QV+PoXfh/74/ICRCSyzGiMkDD+eDGdsiu7Qox9KFkLSvxUQ5hKLZwcZIldTMGL0XOdGxRNjx6BQIvzCZ6ns2d3V+pBjm9QUiJiwCasxzExWOU/2sVMPXCaQx0BWZ9W8Su/VIsZsLtYIsNyFs65/OXMsH/3o5/F5zKg1fyxWfyFki2WmBP2LJpelqFrWoKe0UPMYCsVTuGkgOQtJPFA5f/4VKNdaYXguvCoC0DDx1cn0qcuaKGvqW2MsuCCteT8tBBy1x9KLivPmSxMJrgvHAi7rQYOhovkPdB7/", @@ -363,21 +449,27 @@ "0xf5b1c844495f0396f5418e9eb4e487d26f70f0e464c83670e8efba62f2af843e", "0x6555bc7af8c1790ace374c7ae84e169d4acde81319606c6ac37fa846014e2ace", "0xc2e9d0bc1c81d6860da30267bf89552a542ece90ed5aac3cc6da5bd1ee114aa1" - ] + ], + "prestateLeaf": "i2cHGSJXUzBi9FznRsUTY8egUCL8wmep7Nnd1fqQY5vUFIiYsAmrMcxMVjlP9rFTD1wmkMdAVmfVvErv1SLGbC7WCLDchbOufzlzLB/96OfxecyoNX8sVn8hZItlpgT9iyaXpaha1qCntFDzGArFU7hpIDkLSTxQOX/+FSjXWmF4LrwqAtAw8Q==", + "poststateLeaf": "1cn0qcuaKGvqW2MsuCCteT8tBBy1x9KLivPmSxMJrgvHAi7rQYOhovkPdB7/AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "sKUc0bS3vxziYuLSVP+8vjktAy0msieRxuSg0iLcAUuY03cmnnGtdmwOKwfuF2sHLGMDos8IwPbULHApG/i49Y3JAF4iRBWmppjET9h2cKwXgF83mrzd7Zd1bh7f/nz70AGPgfwuRVCYPRruYO36Lbynwg==", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x932653825685e7a4719f711e5de643e9325e3e584f4b1f4f173a1d8914f087ef" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "sKUc0bS3vxziYuLSVP+8vjktAy0msieRxuSg0iLcAUuY03cmnnGtdmwOKwfuF2sHLGMDos8IwPbULHApG/i49Y3JAF4iRBWmppjET9h2cKwXgF83mrzd7Zd1bh7f/nz70AGPgfwuRVCYPRruYO36LbynwgEAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "iCvCPAopIESMi+Hl25arOaBs3JhDP9dQJg==", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x2a05292281cbe8bb141e10a2199e10229ea3b1c049f9c3837090109a6c2c2ecc" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "iCvCPAopIESMi+Hl25arOaBs3JhDP9dQJgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "0Q32kVEATjV2f/Cc0dbx3q+SNfict2QIVg8omyeC1HVF5Q203mKtvn8AH+QrgdMblbSwlGNS9QzCnqG1nnL3RER16Nb8DP8e9r+iLNtBeOFehZTn1KN/1ijJPHZNvJrvDwM5dwh9EMX1ctTG8Byoc3UG/+gZR+gmEQLxO0nQcsgHPzt6+ycmnOxjSEXOzCPltEAzAL9hkcz6fq6+m6TxC88wYP9/bW9QaZ7b0zX1i8Uw+mV5PXl8wnBdOPjRvVAQORtgrMP8VTQJO22AuUwSkz5x3amjKwSzzck1OZhpkrCaUDfRCHkMbntJTG00XNTJYzW2nJEU1Fxt6H1106wqX7MfYmWGhyQFHbz/nyu8Ry72f/4k6AuM+mtv75ST3UzpuQsG3OAYiejOiNM8dBoNP7jlU71SX+CmyGEPUP8OZ+hzY3JGIV7R/gYKIlf/EUCh4Ia12ulV1wQYy4WXCimRZeb93WsDmwaQRPzLwPDWqVmaiabpIgu6YkxTnmKs9fjKiCfVk3qn+P0ozfesw2wC2ZzlwfEu1/wqaaI/D/g0B3w5XkdcCj0jcynsocZxcRKD5K0xHtsk1fW6WBaJahzdCbze52YfGEd6pjdqIkC1pWBNCBOzzHxdAdy2uLkO06VLUXrfqi7NhGFx/A//0mAwrYBvZg==", @@ -387,14 +479,18 @@ "0x022de869c20a4d79405b04d2e0a220a3221bd4a6b4c4193470167a01e38255d4", "0x7c6e00e7a3f0b65becc63b04d3666ce3223bc97cb3cdd9b5a541bebc2d6bcf39", "0x5d9ccd2eecf274c471a3402b8f702ba8da1f9658c33c218ee6415ddbdb6b0fac" - ] + ], + "prestateLeaf": "9n/+JOgLjPprb++Uk91M6bkLBtzgGInozojTPHQaDT+45VO9Ul/gpshhD1D/Dmfoc2NyRiFe0f4GCiJX/xFAoeCGtdrpVdcEGMuFlwopkWXm/d1rA5sGkET8y8Dw1qlZmomm6SILumJMU55irPX4yogn1ZN6p/j9KM33rMNsAtmc5cHxLtf8Kg==", + "poststateLeaf": "aaI/D/g0B3w5XkdcCj0jcynsocZxcRKD5K0xHtsk1fW6WBaJahzdCbze52YfGEd6pjdqIkC1pWBNCBOzzHxdAdy2uLkO06VLUXrfqi7NhGFx/A//0mAwrYBvZgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "NIvaQ23RKSRtOnN9vQ/eEvXlDlYOTTy9STSkj6bTYU9dIQEZy8rHsgD+UkPF8anrPL0ZUdMQ5S7mAa0VB4/vDfB8Kl9H5j3jISJWQEY8HaCuc9JsS1PyLxROveE=", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xf4fd54da2d9deebfb13c263519bc96a75981aec25cfb546c9de7705284ae6c07" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "NIvaQ23RKSRtOnN9vQ/eEvXlDlYOTTy9STSkj6bTYU9dIQEZy8rHsgD+UkPF8anrPL0ZUdMQ5S7mAa0VB4/vDfB8Kl9H5j3jISJWQEY8HaCuc9JsS1PyLxROveEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "WJq3C6/ENKsK+af/2LODE86sRiOi2eX+Mkro7gDG2NdmasXjRH0RpFhKyL73WFEeGYbAaO5f4E/zHCrXGfYZyyarF0LZHNBq8TkvrsojRRhVmGbnn4axeDtUdJq+Hd2eQAem4mgKo6UnuY8aqizBlyJ58mR6KFSOG093KapJ55umKtTD1yvwroBss+KQfT2ZKYfEKDPK1e+iASvyeaYcR5lACt1pUMbnoDjmgg776vW0lITGXIijVQ8U7KWwrKi5k0qgxcpJgEAB5IHQUf4z/hWlLWCpvYlKmVNDKQVVTkrXEXArYXorV/SkjMijQrfZT1AO1e9Z4WDXVJ2l5g9KQVfOpuveOMiFV3/wuvRXVf70bAS+NdJKjq1ybTnauagyZcmMDdkgwZNikg==", @@ -403,7 +499,9 @@ "0x9410877f4fdd218916c30132d71ad536abd51dd03b167c8883f42f0859db47f8", "0x526b5b02a339336494f78a1640c5ba2c7d7c4c6c710866660dee1fbd740fa3da", "0x696dd9436f075634f1169564bb051a3f285ddabaa3e849ac8b8793644311c0cc" - ] + ], + "prestateLeaf": "gGyz4pB9PZkph8QoM8rV76IBK/J5phxHmUAK3WlQxuegOOaCDvvq9bSUhMZciKNVDxTspbCsqLmTSqDFykmAQAHkgdBR/jP+FaUtYKm9iUqZU0MpBVVOStcRcCtheitX9KSMyKNCt9lPUA7V71nhYNdUnaXmD0pBV86m6944yIVXf/C69FdV/g==", + "poststateLeaf": "9GwEvjXSSo6tcm052rmoMmXJjA3ZIMGTYpIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "ZWavHk6IjAS6FtSg9Qg0/c66sfYSTd8ER1pOY+RfR4csyVA8hTFGr6qhOijQjiOzhgUyhZ5Fh8qz0bHMVcxradAbUTZWgb42FrrLUxQptkt8dXZL/Q6phalrTgbWQ5+96ibUGN35fp7PGywHBjlfua4R6/PMBh+hB/8e+Yw63JIZEo2cCYkDp8vMVsIAXkcXD2N8EnIogwhabH3m4XzTvg==", @@ -411,7 +509,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x69f77a980ff49e17ec1d6f7b5a139c639ee8992e0eb984828230ef8c053ceae3", "0x9cd3406f0032d6c07706ebf760890230207d0450a82a711a4d0d927f58dae176" - ] + ], + "prestateLeaf": "ZWavHk6IjAS6FtSg9Qg0/c66sfYSTd8ER1pOY+RfR4csyVA8hTFGr6qhOijQjiOzhgUyhZ5Fh8qz0bHMVcxradAbUTZWgb42FrrLUxQptkt8dXZL/Q6phalrTgbWQ5+96ibUGN35fp7PGywHBjlfua4R6/PMBh+hB/8e+Yw63JIZEo2cCYkDpw==", + "poststateLeaf": "y8xWwgBeRxcPY3wSciiDCFpsfebhfNO+AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "9B9WjYRHM8VA/jKZMRck7bmaKpBidrMIUDcXfze1p7pTFpDN2z4ypMC/qtKkHTVCKFxR9Nb3OkatpLc7L3Zb3mGxgRnL9Z3oviZBQcOwAlgbrnEDnMStOStYHz+FoFWIcvBTblRBdviyQP/eD548mirFH2ldUm/0OVk1ESw336R2lZjz+f2puqfz2eRG9az/4C0qY2FYH2KMzrsdM18sGfOZjf9ptIS47Q8BccZJm/QshiofxA+lGzjI16iJPdAEKEKn+rZ2mcgU+DqOoZBXLqM09+5xW9oIMnAHrN8JLC2xC8cIExVAjFvPK7ePTMIn8mC958AvxYS9H6fmocZqPqbJp1FH/8H0NzNcZvyIFYMNHD4jfX3Y1b6Q6FAY/gIpmZ91PyeOmoNHiRPgGiCvsBULJPLMdSr1iCgeVWwZ/ZmCiaKopqElo9q1BAPaLLBzLm0Ev/1CjQlp4tXvKcLtgcvmU6/7N7xQ4qE7tLEc1q62XUjXBgPorL+HyK52mKN9Ezuuey0rmrtx8qClcggg1LL+yAk2Vw25F4uwRHc9/jbv468ejPRGc/vOgU7hpqi8q5aYtsKcP4DB7k9+DbwViyVHOuYO+BKXYw0SAKF0cptWjYXzSCYNabym/jOMpiJpAF4OzH9acQGVFOV+fIEEwLp/GIPvy3/QAYsoKrnkVq/2dznCLVdLMYZuFdfWd55T", @@ -421,7 +521,9 @@ "0x622ef2b8079f03d64180a9a075edb64a30a6749de2ca75ea95f7aea3b73036b4", "0x28ad78f57bf70f4a719bf2425675f92b0a455058db0ea2d80758ec35232f67c8", "0x0481c175877e232f0950033b43560e873846692d8680038ca0fe78edd4f99300" - ] + ], + "prestateLeaf": "DRw+I3192NW+kOhQGP4CKZmfdT8njpqDR4kT4Bogr7AVCyTyzHUq9YgoHlVsGf2ZgomiqKahJaPatQQD2iywcy5tBL/9Qo0JaeLV7ynC7YHL5lOv+ze8UOKhO7SxHNautl1I1wYD6Ky/h8iudpijfRM7rnstK5q7cfKgpXIIINSy/sgJNlcNuQ==", + "poststateLeaf": "F4uwRHc9/jbv468ejPRGc/vOgU7hpqi8q5aYtsKcP4DB7k9+DbwViyVHOuYO+BKXYw0SAKF0cptWjYXzSCYNabym/jOMpiJpAF4OzH9acQGVFOV+fIEEwLp/GIPvy3/QAYsoKrnkVq/2dznCLVdLMYZuFdfWd55TAQAAAAAAAAAAAAAAAAAAgA==" }, { "input": "owc1BQ5UPycfsH2vPF8uvab49MBYxShWUNX2a3eL/IhA1Z+4OVXjj2pHNa6ojDeNmMh3hF6Y9g2lfENfNWYlLjFyB5FtVcQH87J/qQNHFW6l/WyUxD63YanQRZBs+t6MhyYHOSjfFdh/cGfXRgq57jeeQFlaVQez00hKrWKP3j5HPd0xe8ujwj684kT4aJs8024CHmzFG8YaR0N12SEjYZ80GifHAu8Yr16pfTezBBtlvrnwScH53fpJpRhECOrNZYM4anrxniTWCr2In03wvwGoPiYyQBWIrdQqwSL77qd7/xr90Lgx1GN3aSrr5T4Os4eI7c3lUz3dBm5u2fSWCORB3iRWTYeRLL7+CxX0aVv3FCYP2ILFpBw+ARsNPF3ixCXGPMup8sDUWata79q06TSKNJkJB1kYtrLq7yDr8shi4RGVxeDE9XvrXCKyAvPndIVWyqGzBU6RihuN+AZXtIlodwXnxBOT2m61YYO7w0Md61Dau5BeTAdqcxjTEfI+YCbSztCVsDGPRg==", @@ -430,14 +532,18 @@ "0xcbdf37a7133ed5a200a3fad2902cd9bc1c4dec85d29cc1a83867217940d0d114", "0xfed99f21455221b33517e24fcd4c26288a62348960c6da111ac49e9059aa2b1d", "0xb8c1db5a6337825b6233ce1435766d364a7f2f6b2dab42ea06b24a9af485a916" - ] + ], + "prestateLeaf": "PrziRPhomzzTbgIebMUbxhpHQ3XZISNhnzQaJ8cC7xivXql9N7MEG2W+ufBJwfnd+kmlGEQI6s1lgzhqevGeJNYKvYifTfC/Aag+JjJAFYit1CrBIvvup3v/Gv3QuDHUY3dpKuvlPg6zh4jtzeVTPd0Gbm7Z9JYI5EHeJFZNh5Esvv4LFfRpWw==", + "poststateLeaf": "9xQmD9iCxaQcPgEbDTxd4sQlxjzLqfLA1FmrWu/atOk0ijSZCQdZGLay6u8g6/LIYuERlcXgxPV761wisgLz53SFVsqhswVOkYobjfgGV7SJaHcF58QTk9putWGDu8NDHetQ2ruQXkwHanMY0xHyPmAm0s7QlbAxj0YBAAAAAAAAAAAAAAAAgA==" }, { "input": "YmDfFJIJu992WScmzsVyne6MajcLV+PAuHQjjeqJffVgEfJQF5F63v7SVo2qm3F70XGO6LGinr8bUrXd/PKZp75uTG3THIudOg==", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x759c2672c3bad10c418cbecf4d7562dba49569dfea68ffcb444d7660591e2d7d" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "YmDfFJIJu992WScmzsVyne6MajcLV+PAuHQjjeqJffVgEfJQF5F63v7SVo2qm3F70XGO6LGinr8bUrXd/PKZp75uTG3THIudOgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "TlqhRie7Nhwexw1cmkr0hATHvGmCOnB8i9ftoZMSzbAS/165lmc0rlMZ447NSXcz3NIe11btVQziiaCWa9v4EOJsrrN6b+TPcHao380s+qpWskkRjkxb8iFLIpgiOnty6/uENcyPjlVG3Ll+MT+ICas+Xua9cQweWhn2NrOWU5Q5rvRJu/YiUAzuyE1m3WCNR+VayoqtOYCot7ehD3QBUyHx/zPXSgLiYoFNxdEfmm46AEeXjpZoCYvLm2CBALOt", @@ -445,7 +551,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x28c1a0012cbe44f3fb5ed2feccbd1fa7aae1f76234c1a8dc19ef694bad386c55", "0xcde2358bf74c4718abbb00ab46ee37162b743cb879145dd598861253bdbd607b" - ] + ], + "prestateLeaf": "TlqhRie7Nhwexw1cmkr0hATHvGmCOnB8i9ftoZMSzbAS/165lmc0rlMZ447NSXcz3NIe11btVQziiaCWa9v4EOJsrrN6b+TPcHao380s+qpWskkRjkxb8iFLIpgiOnty6/uENcyPjlVG3Ll+MT+ICas+Xua9cQweWhn2NrOWU5Q5rvRJu/YiUA==", + "poststateLeaf": "DO7ITWbdYI1H5VrKiq05gKi3t6EPdAFTIfH/M9dKAuJigU3F0R+abjoAR5eOlmgJi8ubYIEAs60BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "gKWk0Np+a/dx780AIKKk56s351Mse9BugFfE0VVhqhSwR4NSyqoHio77lhavHgnRAcMLLJXhjTAIZ4lg+0+L0iN2z4jTg+SfcDe5rBLN5E16a8c+0+ezxQ/L6MWOlfp4sHHIcBo/HGF0YRiTcx42pBF+pW3BNSobeB3EXPWuKDloNXpOXj0sgNcV2KtBGfEnjcnySaTEqeHtEWDy2o/h5MTc3on1DPcLKihAQLvQ9GLphQ8Vt2kl4qEsyuta6YczVzQUHKy86ft90ksQwq7EAWsK1jyDCbtlgjoTV21ZxW+7ZN4IJPEcSEZ1wZqbvIffvm2S9GyuxTQB+WVI4pfaBuLRs7cTn14F4aZQdoynjIdi1tQnFynhgt6i51GaKbNQaQTennUT6OHHR27psec9grrM4g9rP4iQpwhN3NA0TUkKWewZnF1HLdT8sHjIgcl/m/juYV8qSM8pg10zQ4igltSy28ercGVATyR8I2Ec9TyWJl0k/9Nb4Nbubm1/ihXcKj2M7vrz3qCX0FCZ0rtkV6TJEkH1zzHeNvMHJHs6", @@ -455,7 +563,9 @@ "0x7824bccd36d6084e91e3602f58d6c1326872ffb714e9eb277b6744a9827ee4f0", "0x1e2bfc61a776eda7628befbc415539254225bb9393d147911a85f3b4f3ac8a97", "0xe7cdcbf0dad6b72f51f1fee83827cb0bca75da17ff1178abd13ec30c28d67512" - ] + ], + "prestateLeaf": "YtbUJxcp4YLeoudRmimzUGkE3p51E+jhx0du6bHnPYK6zOIPaz+IkKcITdzQNE1JClnsGZxdRy3U/LB4yIHJf5v47mFfKkjPKYNdM0OIoJbUstvHq3BlQE8kfCNhHPU8liZdJP/TW+DW7m5tf4oV3Co9jO76896gl9BQmdK7ZFekyRJB9c8x3g==", + "poststateLeaf": "NvMHJHs6AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "XUhVEs9TzsmGyDuTIzwiSfzBvUfuFL1az6WNUYUwrx1x+5eAlN4vNxu53vMsPyzxsNs5bdR51KrDOC4cMB+ruK+ScuqtroI4AH3HIZT4mJeDOZnQHQXwumlybeeumFxL4MWq8YlFe15lUeRbVLlOXPuvWb7D2K2eGout3LFWEJ2jhfyQKgBiE8bUxTRX0MbJwoyR3LOOraDdtJWnomR5rdDqKwvtSjzBRmkHErNfVngifWgxz21H/JpM/FcEuHVWyoVUON2vMO7VY49DtNzX3mnVODXaIfiuxUx9tNt/qKiru5ds51w/7Mi/4MAx/VQQljOBzukf6fSo3IQR/VIr/oNZD8jS+/rTU9wxcbu6f0GstkKbJ3FmZm2/sRh/tmW3M+aMdHewQWUkH3n/z7CWJmh9Eb+1h6oCQ55we2ZsaxK0DFa+7YB6WpCVPg7AJe4iE7caMvDByi+w3VmbfLQknySPxShXdqCaIQPc53sFLrnHNSQWIium8o7KKU2DB4mPHO3atulp1MwoleLYD8FApfV4Qawoe0/22EGcWrlKFV7X3bS44jzNv/A2PiUUgE/Z34ND+Ofw5z9J4l9Ndc39vG0D/r+nGaL7zaeJ7MV7pQE+xZc6P5K4R1+Q+s+eVh16vsscYybG", @@ -465,7 +575,9 @@ "0x7e524169ad08838f7119b4bd41062fdbbd856fe06ab23be337cbbfa7617c3312", "0x353f3fc5a7ae59224bcc68262145bb94fb94f9ebed52f9c9dbc5439fab5b1fcc", "0xc407900eb6a3f77e774a60251244f5e9fae95765de26f48869a834bbe7c5f847" - ] + ], + "prestateLeaf": "rLZCmydxZmZtv7EYf7ZltzPmjHR3sEFlJB95/8+wliZofRG/tYeqAkOecHtmbGsStAxWvu2AelqQlT4OwCXuIhO3GjLwwcovsN1Zm3y0JJ8kj8UoV3agmiED3Od7BS65xzUkFiIrpvKOyilNgweJjxzt2rbpadTMKJXi2A/BQKX1eEGsKHtP9g==", + "poststateLeaf": "2EGcWrlKFV7X3bS44jzNv/A2PiUUgE/Z34ND+Ofw5z9J4l9Ndc39vG0D/r+nGaL7zaeJ7MV7pQE+xZc6P5K4R1+Q+s+eVh16vsscYybGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "OkvbSQAYhLTM/S40CwkShoqc/doQKJuRniWw25qw0ATH9AGBMrIH4GQmBhBJ21JF+DXKHbaX0hiDUo5sRiyPhUNLC3WiHB58XzKUr2R3TCFy1G8f1ufiJSl0tiVEuPUo7EHVB9J8WXz/O97Icsakb5jrzYiLSdsy0Pc82A/tfTZBPuhC4HZ5jhqVetBiRoW8HdS6/dLSioR7XyXUP18KEn9+GC+/QvLpl/bvVRnnvmXpXM/h68d0+cfI5yVvvKZccaAHZcwmkLSC6Sm39Lh3TTM5ETt9Y2nB1kVD2K+02E7Q6pvC61Sm9sVGRSTylcCCLO1HnCQyN50U0HpJwNkC0svtIOfQCnN25I6Mice/rD0sWPkxaEGTJjnYVLY+14+yEhsSRfJPAacUfkmV4QFhFd1bD+PWmRWe3y2C97zwFp2P6i9WANfG/WV1HxXibjJSasmkdb32mHDBa/XFR+A5uDMdprOoJDKS", @@ -474,7 +586,9 @@ "0x6a9c620efe67cd187c9f5885cc2c58d9b359246302be95baf2364c508398d59d", "0xc9f347ba036d7973cd36ee090a73da7a99331f913b962292912b5c64bed6711a", "0x961ed6a2ceb428015ef02f857d420a6e858daee2ba77a7bd025d9ca785ea4725" - ] + ], + "prestateLeaf": "GpV60GJGhbwd1Lr90tKKhHtfJdQ/XwoSf34YL79C8umX9u9VGee+Zelcz+Hrx3T5x8jnJW+8plxxoAdlzCaQtILpKbf0uHdNMzkRO31jacHWRUPYr7TYTtDqm8LrVKb2xUZFJPKVwIIs7UecJDI3nRTQeknA2QLSy+0g59AKc3bkjoyJx7+sPQ==", + "poststateLeaf": "LFj5MWhBkyY52FS2PtePshIbEkXyTwGnFH5JleEBYRXdWw/j1pkVnt8tgve88Badj+ovVgDXxv1ldR8V4m4yUmrJpHW99phwwWv1xUfgObgzHaazqCQykgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "Dni8xdY2FY53gk916B/zgDq3IuWYwhZ2NCTGNBSp7F4a/peabO3eHNz3/j/lD3a4nG8CIZ5/NeS52OhCAo4ie7iS2SkEt0hLmoXOXHg6WRM7BEFFymqBjnr3R7gj26Uht93NNYK9+UuaW1kW4+s4ZvmyVHPPZ9I4hSIaSjg2r3l3/ZVnCgD640AxwtJL/kGZSjjlU5Snhmkn+X911AofeDbyZB4K70P+9fbGKYsKJCVF7VMP/EBmLNlTryt12Us3k7ddtMF1NJzk8xDamkYrmJZNjf3ol3kYr9qdbd5JkBdOObnc9b5m898vqXQWCmS6LcThuy5+QM0y8lDBEScuQag/xKboULbjwcYBur0Ci5ua+d0H4/xlDmNMI+ruuB+B+G14+P+xPPjK2Iu9b93K38K+yZvTPh21tdvj/4njdAMp2w3C0S4tM/XNQVHZLFwuDR6mMzMUj1M9u2rZNU607qL32thrYE/gDavvDUJ1EcKTtHefUbxPYTBwZ5STNTGImenbSCu3wWdNieRmtujsLXSr6vYgqHtF6K8cyqOaOQwb6D1J/ilxZhD0cNWqQEJOnKjIcw3MhjQjSz13Zqy4Kz4BgfZYiVqfsoMW3sW7233jtPR5tmMe3G2kDppZbMmrlak8ooiKstiYKwMR4XvKKQVJyhjj5M9LheuzBvH8fol9wihZWOBdvz5s3RvqDWQkikwMDHxSrRRkwVO7weEK", @@ -484,7 +598,9 @@ "0xe3e0db33b1016c4a1e2cd90fa3cdd7268a70a17cfa801b8112bf9da81e9dff6e", "0x31b580ad3e4eab83a0cefe3b5f580325e02cc9698dfd892c1f89dc881103edb3", "0x619db25a967f481df1824cba2a713b7f0e256f74be84aa09b1a80fdc51c20aa6" - ] + ], + "prestateLeaf": "mvndB+P8ZQ5jTCPq7rgfgfhtePj/sTz4ytiLvW/dyt/Cvsmb0z4dtbXb4/+J43QDKdsNwtEuLTP1zUFR2SxcLg0epjMzFI9TPbtq2TVOtO6i99rYa2BP4A2r7w1CdRHCk7R3n1G8T2EwcGeUkzUxiJnp20grt8FnTYnkZrbo7C10q+r2IKh7RQ==", + "poststateLeaf": "6K8cyqOaOQwb6D1J/ilxZhD0cNWqQEJOnKjIcw3MhjQjSz13Zqy4Kz4BgfZYiVqfsoMW3sW7233jtPR5tmMe3G2kDppZbMmrlak8ooiKstiYKwMR4XvKKQVJyhjj5M9LheuzBvH8fol9wihZWOBdvz5s3RvqDWQkikwMDHxSrRRkwVO7weEKgQ==" }, { "input": "548ML89LjxGqzaKfXD2+DzRe/n4KnhoXHQQxl245B4A6Jd1kIisZ7ZtlgMFIsrRI4SHYo56gPUeNQKKZS1tnkbhwz4Be7FJgaNhy8qmaR1lrPMmGNG3yK0OZbDoZPWWKEnGYwb0wXIXKykd2OeD+V1FEVIb1varcqD6e31UxjH2sKNfbfb2LJj/OC2L5Lg91Qs6L188Wb63WNt+B8c7ArvbgwKwMLVfFcBwwKJjez6MsuiY7nADjs6i/PhTXrkQQKTF5WWzbHpOtCpBAGEF+TjPD0V3V3eAkz7tcvl1PaAcF63i7f5whXYhhpng/QWrxSKjYBFp1E1fcTATM9+O49z7f6AebERcv34sspmYXZE+Hs6HLE0oMnYHOPUOf91qT29khKLbW2DIYZgd8TR/xnL8u6aLZY3dED9cKpUNtJxX2aLN+2gX+O5rZ5MC8816oBTtBmT7eph2HVrPdJODSGtmQ+QU55DORHur9tss1uf+cy3mKtwY+Y7xDmTsA", @@ -493,7 +609,9 @@ "0xfe5251befacdee21746ad860d05e7b49c23a954a731a7ae61f1a02e6408e66ba", "0x45bcd5f51777f3ab924800b6671cd928b96287806ba19fbf9f90d1aa8f50774a", "0x5d4d865d850c9cea52df84142bc0ee4599e586103df653530d5204e265061ca4" - ] + ], + "prestateLeaf": "P84LYvkuD3VCzovXzxZvrdY234HxzsCu9uDArAwtV8VwHDAomN7Poyy6JjucAOOzqL8+FNeuRBApMXlZbNsek60KkEAYQX5OM8PRXdXd4CTPu1y+XU9oBwXreLt/nCFdiGGmeD9BavFIqNgEWnUTV9xMBMz347j3Pt/oB5sRFy/fiyymZhdkTw==", + "poststateLeaf": "h7OhyxNKDJ2Bzj1Dn/dak9vZISi21tgyGGYHfE0f8Zy/Lumi2WN3RA/XCqVDbScV9mizftoF/jua2eTAvPNeqAU7QZk+3qYdh1az3STg0hrZkPkFOeQzkR7q/bbLNbn/nMt5ircGPmO8Q5k7AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "ugu7GzhFq70GgrGQSZEFItW0+khpzmPODUEXabcK2KJPgynWcsBBeW0vNfySTjgOiz6pPaoAvoOf/PokycT6t5fd1A8qHbV+yowAzHElFEJXHjUntFCxI9PNJcJo8758kELCR8R9YKBXZVjmF+M87WWg6/g+d9dpj5AL32dU7kQmLkPu5kaxL7hJRTOlzBJQrMNz7G/BWPJJ0GNbFhvrc2YZIL/LGPCt4OZEHFjG90RRXa9w+cWjZHS/QHAGufVSswFDt52O8/XB0KbI2MWpltbOz2+lCg+M6h19Fx0f47i90BlLymMVi5CZRJ5DhlPkuG3KVo0rUrGEcuizcx7HifIbf45PHOdT8HYvxKedmXCq5MsLd1Ohh9WjzCwaCuql9kc1jBW5OzoFWKnaDGlaCyJqeI1lQBz8FqBHYQi5w8DH/m1ZV7T9StMH1qndmcyNJyMlxhGmGU8QmYBR7hnDTnJpeNkRK6l8LEwcjfen1JXhWy78M98bqZxZiArQBmYImtO1YG7LHhftULixizOxezWO9xaSPZBXh5a7pQ==", @@ -503,7 +621,9 @@ "0xd76c62cf7bfb075bde0ca1f3559e20ea16ff017bf9d8c56dd6a7b5d25b0d4c96", "0x6e8fb71d0bea05ea7d8426b3169b2ad5c59d13679139ea6cf80c27db4def900c", "0xff0fda4e3f43d1c1cdcc59bde8114efff8959d1aec78910020892f6786a11f3d" - ] + ], + "prestateLeaf": "quTLC3dToYfVo8wsGgrqpfZHNYwVuTs6BVip2gxpWgsianiNZUAc/BagR2EIucPAx/5tWVe0/UrTB9ap3ZnMjScjJcYRphlPEJmAUe4Zw05yaXjZESupfCxMHI33p9SV4Vsu/DPfG6mcWYgK0AZmCJrTtWBuyx4X7VC4sYszsXs1jvcWkj2QVw==", + "poststateLeaf": "h5a7pQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "iO4gx/gywUBIM+L59hSKkEPKdj5hVnhQGPcTRscZ10xBbdpZW6xIvZtsCGxmFXa85MP9X37X7ysMtUvspHBYeU8sVGl0GbGb3oxD1Eb9JBGDs1BGPnkDqWeikVfMEaE3HeqrDaxHhGOOLLCT2kM+mWKhAM1NlO4CD/1YuITSyfPlygI0bP5NuhjRe46vVaJpxa0dbByZNvX9dWqk6TQ7hb6ui5eOhtjeN0nw5rxyHPZXn2JTBZGfD0WRI3vDi+97DxziWq/Hl7xJUql1fYiq1X6BYevrMcO16ORcJUY9Q9LtLw+aq38xbQCrtYZv9PqjHjMLG38Lj5pqFi+PiacaDEsWYHk8JmC6VWMkVGP42uWncKlI4vBO+S/7G5VVuJociI8Bmu0Io0Tr7S/NaERIqC9y4SSN7UPzqtpHhQexlfYdnl41UsBzTrDwhdoHyDHuDNnRRB7vTIRnV1ejNX3F72XyrhB2q5fWza2ex+Iz9op7ldop7x3jJjl5PVSmPP0a5QhOW6k+TWtDrujqFaqk9Vuz9Qq27bj51nLNzbMzM57kupnIKNrHr3Hr/W8FdqXmU8UWCI5cX3lBxg/ywNVpvE5JV3C/vfXcfS5vFm4zJS5Gbg==", @@ -513,7 +633,9 @@ "0x956bddcb7caf1472e24289ec253118a9a946cfec3faa43d9cdfb3583c6428c02", "0x256986bdf9066db60f75792c65aa192e846df14a3478a7881238b66b458a81be", "0x9db4b75e27b3bb292bdd450030a1b43d0f6be658fe6d59c711f534d97afa964d" - ] + ], + "prestateLeaf": "p3CpSOLwTvkv+xuVVbiaHIiPAZrtCKNE6+0vzWhESKgvcuEkje1D86raR4UHsZX2HZ5eNVLAc06w8IXaB8gx7gzZ0UQe70yEZ1dXozV9xe9l8q4QdquX1s2tnsfiM/aKe5XaKe8d4yY5eT1Upjz9GuUITlupPk1rQ67o6hWqpPVbs/UKtu24+Q==", + "poststateLeaf": "1nLNzbMzM57kupnIKNrHr3Hr/W8FdqXmU8UWCI5cX3lBxg/ywNVpvE5JV3C/vfXcfS5vFm4zJS5GbgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "VLPu7ILgq9sB+QMzMPf+iYHuoTT2uKjjcs3QJwJGZOlTXBqUZClVaii3BV/rI/iDshbTrWefG4rD5CaLBqcdYTM4JXt1DnnK2S1C77rFTkM6dkN+q2juKQJNDIxGDxcgztKPzmksK47yLnCwxEDbA9E5mKDjnBwCcnfsqbKjg6o2/9LJu1xlj0q0urR3TMCBl+/FaIJmiQ==", @@ -521,14 +643,18 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xbf4fd89b077bf39077318ff9f2eb126cb04c2b3ef6f9f3f1bfb2204e367f731e", "0xb669198808b22cc2e730d88fee059c96b9d13057b509b4b26cb625a04e75432e" - ] + ], + "prestateLeaf": "VLPu7ILgq9sB+QMzMPf+iYHuoTT2uKjjcs3QJwJGZOlTXBqUZClVaii3BV/rI/iDshbTrWefG4rD5CaLBqcdYTM4JXt1DnnK2S1C77rFTkM6dkN+q2juKQJNDIxGDxcgztKPzmksK47yLnCwxEDbA9E5mKDjnBwCcnfsqbKjg6o2/9LJu1xljw==", + "poststateLeaf": "SrS6tHdMwIGX78VogmaJAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "iaA3KhRXBhnFjkR2szfpxFslTINxAiauR6ZS41N7Tyfnk5iczJHJmjmPvWLUVbsoFWwbBvGkVPPJSyYV8z6Ll+CzQJmR", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xe2a777a8bffe0bbba1ad4d89515f6eaa9440c7d843b5543ce53cf15cdd7dc4ef" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "iaA3KhRXBhnFjkR2szfpxFslTINxAiauR6ZS41N7Tyfnk5iczJHJmjmPvWLUVbsoFWwbBvGkVPPJSyYV8z6Ll+CzQJmRAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "X/hVerdH6C8Evfr1bjZ7xBxsFQN1t/PSrXv64Au/vEZMz68f9T7p9OopxElulNEjA/UlijpVs0H81HF29eAyyfqvKojBH6dhCjhMij2DErMGLenHXanHzN6u2LKVv1o1+tCusG7Rw6bzbTsq0Ee95bOfvzfO27/kpJtBFN+5rhm01rez85tb1bEmkgx6Uf18hKF4WES4zUmdE1MEhcClMJEfQy6ZR8NA3x1qRYhUq9r3xmhN1+vFC+YDX0hdTWuCJg==", @@ -536,7 +662,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xead8ca105740b9ddb7988299eb5f06b4dcae604c5b0d08a2cdc8695be973f1f9", "0x053b8f8c5638392c64f158efd55ccb268671ff1cadfa6b919f23f4c58722ddbe" - ] + ], + "prestateLeaf": "X/hVerdH6C8Evfr1bjZ7xBxsFQN1t/PSrXv64Au/vEZMz68f9T7p9OopxElulNEjA/UlijpVs0H81HF29eAyyfqvKojBH6dhCjhMij2DErMGLenHXanHzN6u2LKVv1o1+tCusG7Rw6bzbTsq0Ee95bOfvzfO27/kpJtBFN+5rhm01rez85tb1Q==", + "poststateLeaf": "sSaSDHpR/XyEoXhYRLjNSZ0TUwSFwKUwkR9DLplHw0DfHWpFiFSr2vfGaE3X68UL5gNfSF1Na4ImAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "CeiQEBsTzUss2uuNs6R4kez3liQg+cPLxmbI4+TE19MAHKQ78tPctAoZ3otdXalXdNWwpX1JnWlFGINd+p0g99Vbk718CS349DY5mBwMh11sOmiSRMG5TGE7d9XqSIK+5X8II7vMrcikfvhImOj1+qcVpMYMAiCceIfbnqAeS55Av+SZSDYWUnrVVZ/UBJcHeMqLmFGsJnyulwQIAvPbKPO+qY0IV8LOY8tA6NXF0aIWaSY9izGrb3pvEGOO36uaDzoYEJ6QbN9BCKUq18LtmfjqrEWfl4exdt/twKzFRWcf5MsKUkaBQyFS7mU8Lp49hs9eELETw7Tv67y+QmsWquDOoFNbGRzsclXtkoNTGJOASap3eNKvuLb3DHd5vUidqU0+6/P18dyGjJ+0JWqO", @@ -545,7 +673,9 @@ "0x8cda77b99eb425ea9850550203a6525ecfefce976537ec8841cd5094ea3f5ae9", "0xf7cbceee65f235eec33ca84440f300aecc1c83e265086d562c226065939f1b0f", "0xf3db4825d2244a11f679202c1b476faa6467b60faeaf220b760c90799c4fc041" - ] + ], + "prestateLeaf": "etVVn9QElwd4youYUawmfK6XBAgC89so876pjQhXws5jy0Do1cXRohZpJj2LMatvem8QY47fq5oPOhgQnpBs30EIpSrXwu2Z+OqsRZ+Xh7F23+3ArMVFZx/kywpSRoFDIVLuZTwunj2Gz14QsRPDtO/rvL5Caxaq4M6gU1sZHOxyVe2Sg1MYkw==", + "poststateLeaf": "gEmqd3jSr7i29wx3eb1InalNPuvz9fHchoyftCVqjgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "T43pAryJO7P0xU/AXcqoGcNUCxUvdZ+t+IhKI6wU821towh4/f3ykzeiOyIf4PpQ252B5CjHQzkTf4i6Tvayioo+ZwvFl7Cbt42y3apjZQExrwpCsb/NFfmw328/us91lMipJmcHox7JPPQKibW8KFa6IhseC1msQ7h8V1c1LPnr+TE4NrsfTcI+rB5mSS4YG8F+Kpi+S5OR2C8qx4NbZ7IWIpIZIxKFV28xTtl5LH837MZqYWQigiZexEpvRC4Cua6WTstsNUihbjjElElZPdZhFFLwvpG5uDUEnyt6fm+mJZkLDJG52stPIOIi0YVhkXLVln784zUUXJGWDQGg+ub+vEh2zJ+BYYsUeHUjtnfclH/s66XWtOkTMCs+rt0Kw8lJ4SX8MFDb0yjRt4HhmhyVNfU1VOxkm/Z7ad36ycQ8UOJp+qrqPr5Rk4y7RqJzKj/Fro8mJu2lanKbeYLIPsSgLwrl2rPhbUal7rHstS0UzWLxqPE9EmKikDJ6OJmSQpfF5GOuhRGoWM8NVwwt612f9xEMirXrzUzbNPgBoUibr596HzTr/m4H86gu/wVTNK7v0xMEk//6yOIKy4P3CzROI5jSHTECoNN+8Zw2rHuxctHl/rYic+4qaP2EYNKXF0EV5cJdIqvgApxbz2abAdC+Rqw5ZNYQ+O5JDy4/y7O6WB0vgsx5XXdhM8S+0gTq", @@ -555,7 +685,9 @@ "0x325134ff3a1fb7cbea02c70bf9fe234aeffb339e6c72f355f307c3f2464e9154", "0xc11dd00fa0ecb786e18159660c847a90fcdfe098738e2b15996b2ccbf7960b06", "0x8a645af9f6900d64a16558ad878421f6557221476f78b44ae7b03e3d2e0304dd" - ] + ], + "prestateLeaf": "3JR/7Oul1rTpEzArPq7dCsPJSeEl/DBQ29Mo0beB4ZoclTX1NVTsZJv2e2nd+snEPFDiafqq6j6+UZOMu0aicyo/xa6PJibtpWpym3mCyD7EoC8K5dqz4W1Gpe6x7LUtFM1i8ajxPRJiopAyejiZkkKXxeRjroURqFjPDVcMLetdn/cRDIq16w==", + "poststateLeaf": "zUzbNPgBoUibr596HzTr/m4H86gu/wVTNK7v0xMEk//6yOIKy4P3CzROI5jSHTECoNN+8Zw2rHuxctHl/rYic+4qaP2EYNKXF0EV5cJdIqvgApxbz2abAdC+Rqw5ZNYQ+O5JDy4/y7O6WB0vgsx5XXdhM8S+0gTqAQAAAAAAAAAAAAAAAAAAgA==" }, { "input": "E8ftDm2vrPzfRJ12Iqh62rOORhMZ1BZOGxer0msLFmHUFVOorUGWfbvJHZFHVP1oRGbqlHdr05MpakpXoi+ZNSubKu/zPEAvi0veKZAm/bDzpR7rvTIaIs23pSnq35DfjT/0Xw7ksNsVlu6ZfsS0FPm26RcuOPBiYO9V8/Gq6aAvhSwDmuV33ntGNRwuCm3CZOuA72AwMJtl1LKWVsk+IV8VfVXwitp7SvDDT5e0m970/UnG/o9M9RjSRZbTWLeZfcuYH4iEi0GvvZhywJA5LIn9qg8ixhrrxbO4sl1Sto+BY4BfA4M9/bDyONN+osuVlnh5R9ovFdSqyH+nqAve6lWntoap4B1Dfgu306E7gHT1q2+9HCGrQs9puzi02qSgNCfj+RQHsdGBRgzrruXUjKx+PZV74+Wh3IwPCCwTvQvYkU/Weu8QZoP/bYpgdBJ1AVtiVI1/RTOg", @@ -564,7 +696,9 @@ "0x27a30ccd006cc8547173c85181c75f532dd71c50fb6c7e57f1da58b0555b0546", "0x540375311f1657dd7140d32f2e60d54e53b335ae54539ba511fda8d8c57b74eb", "0xeb893e6229e028b2c510d874435c751039360b203368fa4c75114cfaf39b3c8a" - ] + ], + "prestateLeaf": "e0Y1HC4KbcJk64DvYDAwm2XUspZWyT4hXxV9VfCK2ntK8MNPl7Sb3vT9Scb+j0z1GNJFltNYt5l9y5gfiISLQa+9mHLAkDksif2qDyLGGuvFs7iyXVK2j4FjgF8Dgz39sPI4036iy5WWeHlH2i8V1KrIf6eoC97qVae2hqngHUN+C7fToTuAdA==", + "poststateLeaf": "9atvvRwhq0LPabs4tNqkoDQn4/kUB7HRgUYM667l1Iysfj2Ve+PlodyMDwgsE70L2JFP1nrvEGaD/22KYHQSdQFbYlSNf0UzoAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "aCjoLgKIwqWlW8lhM5bxPyX5Qlipms9rSCj8uLfm6YkYbudeyCaevudHxjcCFWDzmNN4+j/6iNI2dbkQpmrulFvviU5Vn2WlmQSU5D0PvjysOviISM8Tz4PUrdvNxUfIfczgIyFhAG7hKUhi56PtZ9qkYw/I6paRhex8sVqmuei89vswG9SbLkVYU7iOOU/GgeNCfZSM", @@ -572,7 +706,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xe9a9ed50c10f5da4e10231ad4122859ad7a4849aac33887fd6929feebb34239f", "0xccddec19638af750e06720249e99c099c6ea622134ec8a20503013e10d2fb163" - ] + ], + "prestateLeaf": "aCjoLgKIwqWlW8lhM5bxPyX5Qlipms9rSCj8uLfm6YkYbudeyCaevudHxjcCFWDzmNN4+j/6iNI2dbkQpmrulFvviU5Vn2WlmQSU5D0PvjysOviISM8Tz4PUrdvNxUfIfczgIyFhAG7hKUhi56PtZ9qkYw/I6paRhex8sVqmuei89vswG9SbLg==", + "poststateLeaf": "RVhTuI45T8aB40J9lIwBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "2EWBx+PqSowDuumM8eRw5jMnkK54s+tRd5qlGO6RlsR099f8Nz2regoK81zbOwFnDaLJuWMpSi0lQayfwydkZvMz5Nili00eh1d16VxCuvM4OugCz2QxaikZ3SMHiNcVStO4asCZbN2dcZpihuZSNyVScd4VvLEoPk6EZnWaEeAVV14xjfoPgT2iwwVzmrGk8sqjQJGKeYBpcbkpKa4BQqUsonxMCmTngb9p5hU9fkg4uKhVnTOV+R/1QDvhnpxbIQkSn7/oDGqQZ6H4VbR8oB7kMswhED5dQBFmF/VXvVpdwcF5fj0LMF20QIWzs8cn9o2YTS7AZJtOvFBWxBXjzhsXYDFpRI+uiOdP5lgIGDq5L03HvXa591o71hzPfmjyR8Y=", @@ -581,7 +717,9 @@ "0x7261444591a7e2089579fd29293a60dd750951cdb884ba12c741a159b8682d4f", "0x7a9ea07151ca7ca8cea49e9831f91986136303705ed5589d03a9b3101e569b99", "0x5e8282b46e4352cb1e56e9f5a0a08ddacb112cc8e85192ed906ab67445235202" - ] + ], + "prestateLeaf": "PaLDBXOasaTyyqNAkYp5gGlxuSkprgFCpSyifEwKZOeBv2nmFT1+SDi4qFWdM5X5H/VAO+GenFshCRKfv+gMapBnofhVtHygHuQyzCEQPl1AEWYX9Ve9Wl3BwXl+PQswXbRAhbOzxyf2jZhNLsBkm068UFbEFePOGxdgMWlEj66I50/mWAgYOg==", + "poststateLeaf": "uS9Nx712ufdaO9Ycz35o8kfGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "wAA1Mt5xqAbr0sTMUomvimo+WbCHDEiS+pWu+eQGgnXxDWmOmuVqwaA5N4fMefoy2e1ROvyuStbgImQ7TRSaVOJQjT7wgEjoh8K5//MlSbuNFQZnWsAltKhlibYqDV3dl+gUdz3ya0wj2Rv+bp5CgQ1DdBcct+uPD1AeLHWzE+iHDpcTUpyvZ7RFw5ZFcM0zVLObx1UDl1eTmQCWqJDNjunwTmd+msSNX7B4ot6XgR1ox5sBQyqCSLbZ+VeN3fuHzX659WQbXaYGpBE8/xBE9iYBhRMm9jYGY8ycDQVNh/5WYzvB5BX/biu0yv0M9bW/cUd7FzYZGhgVuYznR4Qi+G+HkQ7dncKk5e5PqsduTi3iA6UEOO9Oqpg5jH1MkUoi5d4yrxcdjdAuQdM/J+UQbkQ7CgH+IW3R0wZivS8UepXi7rLazScJKHL/+nZgtI/IRFl6GGvPOYUXmCmWRwzMiON1KXqzon3mKSaIb35O+uJwreK9UjkijgJJuZlRXeubMQD3I+9hSQSGrY3Zm0sVtmR2a8nboqiS0hCn9zwq+NfBnzGr2Tn9lG302auqr3hZ3ESfSYpcrcyD+yu+dRhHwIIHYLbl+Uydkc0+/llyEmEOg1QsJuHac7HPeXEX94hDhKLVey/ZVYLOe+xYPhuLilzQwqt9AorjFGtsogEWmSaO3sfjj+pOiYg=", @@ -591,7 +729,9 @@ "0xd9e75a98f4ae520b38436ca9bf464d6f26768bad4afedcb9f7af183eccce01e3", "0x1a7e9bdb037a90170457843bfa64b4e1442f83c1b383bd1f31878599d8d6250c", "0xae40f2bf7d42e665ab60a5ca75ffa1515014aefd3c13f1161cc432e5b6ebad27" - ] + ], + "prestateLeaf": "4gOlBDjvTqqYOYx9TJFKIuXeMq8XHY3QLkHTPyflEG5EOwoB/iFt0dMGYr0vFHqV4u6y2s0nCShy//p2YLSPyERZehhrzzmFF5gplkcMzIjjdSl6s6J95ikmiG9+TvricK3ivVI5Io4CSbmZUV3rmzEA9yPvYUkEhq2N2ZtLFbZkdmvJ26Kokg==", + "poststateLeaf": "0hCn9zwq+NfBnzGr2Tn9lG302auqr3hZ3ESfSYpcrcyD+yu+dRhHwIIHYLbl+Uydkc0+/llyEmEOg1QsJuHac7HPeXEX94hDhKLVey/ZVYLOe+xYPhuLilzQwqt9AorjFGtsogEWmSaO3sfjj+pOiYgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "Qvy7rQFYakrZWqUKvpTKDtWYg24HYfPSRdE+KrTXeNPq5K1J/7VvR38m6DuUtaVhVcn/d6QRQRRS5RTIDLrUQ1crIWaQ8XmMqNaFKZlBytIGvLpdDWuJ2XydRkPYYChqnH+nSpvJNfAYYKK4K4UY1JNXPjiAOP0jXvWi3oOwEz3brl84/dFPG3IO3dVHJtSzYF63YZ7UXlpJV2MP9q84GwbKirkZthc5IFv7BzOX2AXNIXNDEVkMz1oyytJGK2mlRKLNljapNmo4eAbzHKC4bF4T4ah2O8wpPiUXoWlrQex7wuAnBYGdLS6l3e8mE+Gsd0mEW7vFYKotLAepsHwbPwJ7ESGmDBxbMzicKswWKWyexEL6LpwqcFAcc6Gmiho2D1BOOqpKaApZnWowBk8HFdA2EPjaXycGIxhyftQtMV019XX6hzz93Xt4d4PS0fWfj/ViuFopU/JO3cimvzHqo7tgP8LkiHUlNDF3xnzzn8OpVtvkB7rKAx0tMRWtG+TzvBKKElyr16cYQUX+wd2/u6QBIIx45Vz5z/GzHRXP3nCuFwxNQKhXr0v6KcnGW2QfQRX2LN4PPSk5znTS8Q2R9SgBu4Kjq5sKON5zym8LW8fKOH0Nmheb1Q==", @@ -601,7 +741,9 @@ "0x945dfe1b90dad1ac86ddf5b8f27d8a8faaa6ba396113167510fb60cd088ede07", "0xf52616b7f35617b69013c8a9485507bda0753fef7eac1b1bff8d93574de672fb", "0x72ecc86dd75d9c5c7b1f964dd4a664a8a258a34d0b11f2d97dabaa5d4bb8ad55" - ] + ], + "prestateLeaf": "nsRC+i6cKnBQHHOhpooaNg9QTjqqSmgKWZ1qMAZPBxXQNhD42l8nBiMYcn7ULTFdNfV1+oc8/d17eHeD0tH1n4/1YrhaKVPyTt3Ipr8x6qO7YD/C5Ih1JTQxd8Z885/DqVbb5Ae6ygMdLTEVrRvk87wSihJcq9enGEFF/sHdv7ukASCMeOVc+Q==", + "poststateLeaf": "z/GzHRXP3nCuFwxNQKhXr0v6KcnGW2QfQRX2LN4PPSk5znTS8Q2R9SgBu4Kjq5sKON5zym8LW8fKOH0Nmheb1QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "8DTi9g8t1UVGL22HRPz6nazHrn1f/hKJghZqGDvIVodeI6eld/nUqc4EUOgcn6QAMP1ukAqK+vezIt+T6mNTSxiAf/3wTkmduX3FskhRJ8Iler8Ux1TaZhGMk4WPFbc85DUxrndqKlMsDUgSg9lPcl6KwZ6TVFKT5dIsDXSL+82geDhAyPWs3QKYcnbyJDjoN84NXjxYX/CkZOuvLi4Gf7f3VwtHM18YR6zB07hzIucsKxW2yRaMOQe4cfd0QwODs8qhxJdackMRIpDLFzVdvuglBNdrYjmIwYJtGMK5VFOJYUN3BwC3BlmZ5o9BUzDHZguVtUI2Be2fIH4HtQNnHnxZbNAZGEwoZEfc7IlAOIWu6Gy9ihCaey2Ny+xAAgC866WybS51v9QEKzfG02En0G0qxvTQI6yS16NjKFfAP06LgshjC5sZBSg35YGvlCIe/sNlLivxtJjZwx1btzp2xv/cCOOsYx7OycOQl9w9uqYdFnU1W93VErvuBDgR6+jYpyHUvguDt2SZWA3G4pf+tpS3ng2JsOjjvOVs8buGYKZeUHnfz6p9IfvFpBYu7xY4XOIY3ECTr10Kp0sOGRlBxecJ3FJwIEG8B4+dqLNO5I4AY3KjMsiWd2IPzAUN/iyOIw==", @@ -611,7 +753,9 @@ "0x598fae2025414a8902bc1d75b443d7d00745e0723a1668b0d321b4d8cd22c4e4", "0xadc78b18886ac722fd3fba10b4e2570e25eac9c438cfce45b7dbfb439b6681b9", "0xaf0b22baaec8e6e9491ab8186ff1f262f1bf51394d61d3c1d1cef3f84796e78d" - ] + ], + "prestateLeaf": "ruhsvYoQmnstjcvsQAIAvOulsm0udb/UBCs3xtNhJ9BtKsb00COsktejYyhXwD9Oi4LIYwubGQUoN+WBr5QiHv7DZS4r8bSY2cMdW7c6dsb/3AjjrGMezsnDkJfcPbqmHRZ1NVvd1RK77gQ4Eevo2Kch1L4Lg7dkmVgNxuKX/raUt54NibDo4w==", + "poststateLeaf": "vOVs8buGYKZeUHnfz6p9IfvFpBYu7xY4XOIY3ECTr10Kp0sOGRlBxecJ3FJwIEG8B4+dqLNO5I4AY3KjMsiWd2IPzAUN/iyOIwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "hgb6TGeZKH9EF6P843QwlJxc7JJQpBM9n5w64QSXa3VCFyrYQp3Ep/xSbgXRdIaVQVOu/yzHE1siHjhYZNCR5o1go61dlkWOULFrmfIhsFnFKbllrm8KInzHlenysEhxAMFrDr5+vfZizD0Tt/8JIMkzGy9zUfEjgRSr67dE4Do9HMznfMkgnnfO69/wlZsePVbKR/KoS8keVY/oqaDsCt6EXppCIOdX3s+uel4pWhuNEM15IxCZO3LnOTVRI+lHga7deq0xLZjDHshQVGJhX2BQn7Dey6ZBItRdF8RMNxtKaFnsV+fII5NJ/IrAl6rEPkkoyLShZX8B65Gami0QkBLHQaD1OOopE6fJjUCJCni9Ew3avacWGcA5W+Gvprv3a+budPDTTlvctGY/MWF1B2bCnCv+1lXusDfvN8Yi0a56CGabuIsk0BKlClHCcmxyxmrlswbQZ/ZRjoPHW0W2pOta7p9odDJg79cvJYEgNKn+JW99vKtb3PDXb/gsdVD/OQ+pR4RKUZNBw9YKzyFCnY/lX5jlNSb+RFyyLCBVSm3GvDIm5RTVSnQ5G0fkBZDSmLjCCIU2C3qMQoWHlx79IQfG8+BGNamo9txUgPSZDcq05RRVHLXLNg==", @@ -621,7 +765,9 @@ "0x9eff473185e3c9d53c21e858e1660b72696628953521d6755e77ca29cb3740a0", "0xd937a37fe13016d30a8722a08c3271f875a625186bca9949fda3234c96288317", "0xb1b8222b6a4010a9f5c0773954556ddab87e7f144ef784144e84b793219ef7ec" - ] + ], + "prestateLeaf": "vRMN2r2nFhnAOVvhr6a792vm7nTw005b3LRmPzFhdQdmwpwr/tZV7rA37zfGItGueghmm7iLJNASpQpRwnJscsZq5bMG0Gf2UY6Dx1tFtqTrWu6faHQyYO/XLyWBIDSp/iVvfbyrW9zw12/4LHVQ/zkPqUeESlGTQcPWCs8hQp2P5V+Y5TUm/g==", + "poststateLeaf": "RFyyLCBVSm3GvDIm5RTVSnQ5G0fkBZDSmLjCCIU2C3qMQoWHlx79IQfG8+BGNamo9txUgPSZDcq05RRVHLXLNgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "qa3vm4/HuDuyj8khkZxhXKZvFhhxiGOW47bfybP4mndme0Aek0OdIq6kExKRWSbRN/ZarQ7685YsovxpEq44G1IERrGbVHAcJjiwarh/+8NVYNACr2wb19TRdEGFPRDlLmV2/qurj0h0uZ7IMp0wEhAbY6sXHdaOWO/NZlt0BZIoYWtkJ9ihNWASQgqCBOMoFiVag6wNyeamX6rnw4NgAIZ0KhhP8ahHZo5Tw0UVFvD+HKErSlgUmJHJBpgwFKtHSs8ViTCYFyXGjdGuWRn+LUNHNbcSehCaV0QVy0pXczeYpU/inUvku1NanAZVQV7C8G/yAvBr+tWWrSqSgw==", @@ -629,7 +775,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x667dd12200a0c28ab5d704010fbf9c93efe8f431ba264112d8e505cc9ad494af", "0xc7f3a3e75dfa75b48ddf293608c2f6fb6697cd51a2dbd4ba3e8d987c86f50426" - ] + ], + "prestateLeaf": "qa3vm4/HuDuyj8khkZxhXKZvFhhxiGOW47bfybP4mndme0Aek0OdIq6kExKRWSbRN/ZarQ7685YsovxpEq44G1IERrGbVHAcJjiwarh/+8NVYNACr2wb19TRdEGFPRDlLmV2/qurj0h0uZ7IMp0wEhAbY6sXHdaOWO/NZlt0BZIoYWtkJ9ihNQ==", + "poststateLeaf": "YBJCCoIE4ygWJVqDrA3J5qZfqufDg2AAhnQqGE/xqEdmjlPDRRUW8P4coStKWBSYkckGmDAUq0dKzxWJMJgXJcaN0a5ZGf4tQ0c1txJ6EJpXRBXLSldzN5ilT+KdS+S7U1qcBlVBXsLwb/IC8Gv61ZatKpKDAQAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "GJNvpfWnfXEBn+maEIEAP1HR6sP0guRY4m902PH+sf4XrP1cUCcbxAgMQZKbhZXkvPf5q0J2Gn++UAwvVto3ORTlv0qGT366PYAkBZsw2BXFVC6CVCFqsm2iarYI1f2aoUM/wbQlzW7eBrhvPvxNLgt4rnhX2RS85mEqocaA2Ud6qBwPAlvkUsSGQjB0zlylLd3OO7IA3LeLzsdF3xldlgcrEd6WjKr2yZyNxFJnaDn0fTI=", @@ -637,7 +785,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xea78fd5eba89918cf126ce1268f142622b39d1e9c1fd9d60771e8db8468f9e83", "0x15e000fd4ec88a4d5617d54fc6c4649ffc00c517559b2634b3eb0d9e877ddaf8" - ] + ], + "prestateLeaf": "GJNvpfWnfXEBn+maEIEAP1HR6sP0guRY4m902PH+sf4XrP1cUCcbxAgMQZKbhZXkvPf5q0J2Gn++UAwvVto3ORTlv0qGT366PYAkBZsw2BXFVC6CVCFqsm2iarYI1f2aoUM/wbQlzW7eBrhvPvxNLgt4rnhX2RS85mEqocaA2Ud6qBwPAlvkUg==", + "poststateLeaf": "xIZCMHTOXKUt3c47sgDct4vOx0XfGV2WBysR3paMqvbJnI3EUmdoOfR9MgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "AKxthvJXDO1M+B5i5mYyidmHRAP7jB/1bRMCGz0GmTC0gMq9Dbq91Rdmf8ldoYZXMx9VrzrVCchNVeIaJVGIhMgs5UUwPjtKBjItuhSkctd9k1NYFQBgJc2mPMb7H+d/VmyoiegxKdi5Vh4VTr83N+EKyZDdwb8JKRB7D1wMM7r55No7k2fMANLFOT+VSPzg70WPpaY5HEd1uR5IQ9OnXNjdZBv7wKmk1q9AUIpqgrSK+r2V9d49qaPXyX+XzkNqsWLV3a6dxJ9QG1JqD25RLsUUS0i12TZh0jpdkeHP7FP4R7LPUEODXVroI5+bYNSlRVe7OwNrDk+htHkHKODS0+FBVfulr6qYqoAUBEa0XL/veJdMgjGDh+HTD0x46E7PtjzTwmBMS1H7Vh5ErVaQtDx7iLY9N7moJqI1heBDheMiEDil98Xhmqj3IUncZ1uJfWDqrESS8hwah6WJrP7elcBWaqVI4DFhy8KMtUkeXqd6iV7nycVjbtD02+T/uEFT0V9qzd4zWA+wrvGxitlsrIwcMw==", @@ -646,7 +796,9 @@ "0xb8cd587689045570423cd43026a2f2739adb54b24b56e7f85bd9fe851c454d26", "0x7f1a5e9247f9c215ec0c2a34cd80e1931b96eed90dded0707e4c2772d6a2b2be", "0xd40445f4d71545e4bed22b752ca2110e6c9bb3da8af4abfd31554332f2f2658e" - ] + ], + "prestateLeaf": "0sU5P5VI/ODvRY+lpjkcR3W5HkhD06dc2N1kG/vAqaTWr0BQimqCtIr6vZX13j2po9fJf5fOQ2qxYtXdrp3En1AbUmoPblEuxRRLSLXZNmHSOl2R4c/sU/hHss9QQ4NdWugjn5tg1KVFV7s7A2sOT6G0eQco4NLT4UFV+6WvqpiqgBQERrRcvw==", + "poststateLeaf": "73iXTIIxg4fh0w9MeOhOz7Y808JgTEtR+1YeRK1WkLQ8e4i2PTe5qCaiNYXgQ4XjIhA4pffF4Zqo9yFJ3GdbiX1g6qxEkvIcGoeliaz+3pXAVmqlSOAxYcvCjLVJHl6neole58nFY27Q9Nvk/7hBU9Ffas3eM1gPsK7xsYrZbKyMHDMBAAAAgA==" }, { "input": "d900eUWWrZtBabto65ygKjqnV/jGt+IfbH8GS+AxWdgUIpGGArTHTIUzmZhsMtssGWDMWdsugOjLbD1yhls8RJwRAF8soTs3rhSmphVFOn6KPIc4lyDpPBckmxItmGlk5uP9+JbcyPY4F5I05UAkmtnuoyYMvPyurSCsCPdhwALOXckHdEDSGjaRqY+rugGthFbFICxQXL89u27AhOO7uAtsfle430nfUawwhrr7Kvzfo6UYSQur5TkZGaZS29jvhfY+yR3H+c2U5k2oUfOOLK1QEBNT1WcQ6gywypQwRCQLbV5D73/OBatPjOiKx5KAHU3AdHzt8/0+Ej7G6p+fVeWnoasKALs1dX7I3MUuPPGqZRYrySJLPotrEyFj0ZrNZkzzPhO40Wy+J3mFj7INUvfQSfSFOWa6b+YRrxOJ4tI8fpnzciM1y/Rx64mYOCOQxnBP50Yn4is5RLseJYzSCKTl8yBqyHydCvEqOoBGqcJvtkQmNFTctVfNK4oAXIRxeAYkvRA69Q/xSnBFtKZY+Zid0BlrKeUuT3YJSU+agpGJC0Imiy8ufl6/k1m9B+oKng==", @@ -656,7 +808,9 @@ "0x2ec375aedfc478bef69a5f4d9d74359cdfe51ca01698b179212b5b7a538fbe12", "0xd99eaaa52afb616a2959621233062e8c1ba07fea58f34d00beab630442df1c89", "0xc24b6beb031f922de9b4c4a48ce28bd3b32982126d4104bfd0dabfaf48dfb56c" - ] + ], + "prestateLeaf": "qmUWK8kiSz6LaxMhY9GazWZM8z4TuNFsvid5hY+yDVL30En0hTlmum/mEa8TieLSPH6Z83IjNcv0ceuJmDgjkMZwT+dGJ+IrOUS7HiWM0gik5fMgash8nQrxKjqARqnCb7ZEJjRU3LVXzSuKAFyEcXgGJL0QOvUP8UpwRbSmWPmYndAZaynlLg==", + "poststateLeaf": "T3YJSU+agpGJC0Imiy8ufl6/k1m9B+oKngEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "96g+NaYbWNY8fhK355lnCK0TarKbCBPF/3c0Kp/cF9H1/CncnguutxlZHcJbAiN0IeW10CXmDQSK7gnlIF57tv2fvdaviKJ19s9dlIHjVbWckLcm3kwkfaXZEffsPHFototrK+04ODDNiO+ONvKPANCsi10R11D2RlLJ6JavAVxFUliiLnfVgN8OPHkoG1o5z+LQcYtqoQI+iBCFXoqPq/2ielSTbHn2XbAi9rlZEFRKovLqGB5TOvjZTd0M1yMvEgd9BJjJJ/4=", @@ -664,7 +818,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x8e4daa5e0393a3e6afe66e2d9ccf0684a559f41c5d113d0adf9a27d46fc7c44b", "0x557b27463478dbaeed224211344a3d1800a9aee66c3587ea633c214388014a2a" - ] + ], + "prestateLeaf": "96g+NaYbWNY8fhK355lnCK0TarKbCBPF/3c0Kp/cF9H1/CncnguutxlZHcJbAiN0IeW10CXmDQSK7gnlIF57tv2fvdaviKJ19s9dlIHjVbWckLcm3kwkfaXZEffsPHFototrK+04ODDNiO+ONvKPANCsi10R11D2RlLJ6JavAVxFUliiLnfVgA==", + "poststateLeaf": "3w48eSgbWjnP4tBxi2qhAj6IEIVeio+r/aJ6VJNsefZdsCL2uVkQVEqi8uoYHlM6+NlN3QzXIy8SB30EmMkn/gEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "naVpEVoOzteWfeK9u0WSh79jh1i+pl3BlBXzrAiSCnl+gO+IAGE4FszQN4aVfZGdBodkAQlLNsBmG7Or725IFhcHJ+E82JlLRg9kpMKHtTl5UHvqPZ/hVv2XCZfj9le0df5lz0e2Lsp0XGEReYz42q4fkjxWOLa3rFwkVQgaePf2tgwIwrPd48iweP0hwbOcgFfWVrn5g0Ui53uwKa8KCjmKeuGsSJKGR1TxTAb98mFs5SVzUPE7ajmErHfe1A4JVqSD98D/9IG/OnRYzPidCZytI8WhBwfA3235dO2Q9k11Pg42QO6wfbsdRF8dJ8jCc1zJNQ==", @@ -672,7 +828,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xa74f9004e2958c050a01134b23c268d4c10871ce1f5910d6f67a5224fdaaa077", "0x925b929b966d69070e5b9dd4571730f52833440c82d21b032759d39c6b2a380d" - ] + ], + "prestateLeaf": "naVpEVoOzteWfeK9u0WSh79jh1i+pl3BlBXzrAiSCnl+gO+IAGE4FszQN4aVfZGdBodkAQlLNsBmG7Or725IFhcHJ+E82JlLRg9kpMKHtTl5UHvqPZ/hVv2XCZfj9le0df5lz0e2Lsp0XGEReYz42q4fkjxWOLa3rFwkVQgaePf2tgwIwrPd4w==", + "poststateLeaf": "yLB4/SHBs5yAV9ZWufmDRSLne7AprwoKOYp64axIkoZHVPFMBv3yYWzlJXNQ8TtqOYSsd97UDglWpIP3wP/0gb86dFjM+J0JnK0jxaEHB8Dfbfl07ZD2TXU+DjZA7rB9ux1EXx0nyMJzXMk1AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "b9X5EOqu99dYeLiCgE7ihEmhbhQoo7AQHkRuQ6Js9yGGxvYQDGhVMuo+g2ay56ViV0lmEMsW/15x6o5RMVHeX7ScDfuu22aGhKPo5AGnKj44OaLeUogqLsNp7q40CMTBZH1bkXgHiOGvs+GU7ZAPEuWwKwvKXkbnMSAnD8ybu1eQiAdTGDXglqUI4e7qhDuapIBaVPuUYMnmBc3580o9f3mYP4NCQwcJGafH9B4ToPppHYdjcT6dcTYOp01eMoiKzTsE6nDEIa/atPusKgajDk82L53RuEQBMRmAPGisPISbEog8l8kN+gRfmv/RnRNGUcbUhRUWSKsAo1EtpZOhh4U1aBj1WUAQ/SfnPh9cBUqrqvR4DvJawwxheHuaKi2rzT1esbQhuxT+W+iUdo6pRXJGXiTAvEyippY366NaHUZDR9vN03iU/ryJYkKp3KYyOGZ3AZV0py20gwh8kQXfoc5gVpH24BOrv6MT", @@ -681,7 +839,9 @@ "0x43937b0f787a47a32041578337614b4c322750e68a582e8f0ebb39a09551a876", "0x934d1b6297160f8a3b5975d2be38e7789a593e4074f0f8c536aa3644dc0bfea3", "0xc9b69ea06a2fce42e1ece4b565badc6ce0a7dc9937d13373c57e2bdd19c7b921" - ] + ], + "prestateLeaf": "pQjh7uqEO5qkgFpU+5RgyeYFzfnzSj1/eZg/g0JDBwkZp8f0HhOg+mkdh2NxPp1xNg6nTV4yiIrNOwTqcMQhr9q0+6wqBqMOTzYvndG4RAExGYA8aKw8hJsSiDyXyQ36BF+a/9GdE0ZRxtSFFRZIqwCjUS2lk6GHhTVoGPVZQBD9J+c+H1wFSg==", + "poststateLeaf": "q6r0eA7yWsMMYXh7miotq809XrG0IbsU/lvolHaOqUVyRl4kwLxMoqaWN+ujWh1GQ0fbzdN4lP68iWJCqdymMjhmdwGVdKcttIMIfJEF36HOYFaR9uATq7+jEwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "wCn84Ysh1rI+gqpuVqxHuCSePXQZxFjuSX9VWfGVoSh0PUy0geNnEObkVqE2U48nLt92YPJSgmKFw/JQ7l0XS1teRVBmVWQ1oXtxxp38FDdEZUHui7GKI22m55tbLmDOA3TaX/UgjemQWS3vtEJPO1c4B0GZhepYJvYNIyi83Fjgn26tRFT43Bg4qY4X2vrpMt8kGtLeuoQDFZV2KH4hmEyWlkii3loaclTqwctZTO9Wor6543ynogCm71Sedw80lE13+wOPTbi/Q2Rj0xgGPeim8d+YQ+io8z0gEuL0wh3xBFugxMqe7PjHELq5sHzGkWaHKTmBBUrstI30eacUT67xwwyvWcMY8QoBRoql8IpwQY3i", @@ -690,7 +850,9 @@ "0x77ed1b9215130e26e30bb32940f10803564d21eaf3c34813a88b3620f52925ff", "0x6a3c76ccc0da597941e5336c78c7e74359d0172c76f4ed01eb4c17687758a873", "0x9395db5326d485ca6b249b9d2cae2d71abb6b5a06c5bcf337d886bee66abf4df" - ] + ], + "prestateLeaf": "GDipjhfa+uky3yQa0t66hAMVlXYofiGYTJaWSKLeWhpyVOrBy1lM71aivrnjfKeiAKbvVJ53DzSUTXf7A49NuL9DZGPTGAY96Kbx35hD6KjzPSAS4vTCHfEEW6DEyp7s+McQurmwfMaRZocpOYEFSuy0jfR5pxRPrvHDDK9ZwxjxCgFGiqXwig==", + "poststateLeaf": "cEGN4gEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "6ig8b6H7sUxHcjRDPImXIbLVndahV896pfdMqOe391tOFBOOiZFn6Kzfm/qFrwab3NQvNNc2xcVI3XxA0qDKyRK2WnzkZ7XR1Hrz5Tctr7h5rUy1COhwV/76kNICQ5TktETPDI5EXt0j7II/C2zxDSJHvTU7/IGuhG5rSQ5H5b+Xnb9z2I4mpqy+Gye8KOihYFMl5atGDyGReKO3lUe6Au7wE1/n/YaMCbLcc/0E6pxsqOqkgiIKoKhlVHPPfMXwtg81a0fY0sYz5fmoxJmGExLmTRz61eGb2SYsvBtx", @@ -698,7 +860,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x969ac4305a9133683ee676aaf8df9c9d0d6ff69d9f84f93ded06ae5ebb63af27", "0x69408a441399bb046f0422718652ac8c2a61649041458ec5ed52f4f50bc2af5e" - ] + ], + "prestateLeaf": "6ig8b6H7sUxHcjRDPImXIbLVndahV896pfdMqOe391tOFBOOiZFn6Kzfm/qFrwab3NQvNNc2xcVI3XxA0qDKyRK2WnzkZ7XR1Hrz5Tctr7h5rUy1COhwV/76kNICQ5TktETPDI5EXt0j7II/C2zxDSJHvTU7/IGuhG5rSQ5H5b+Xnb9z2I4mpg==", + "poststateLeaf": "rL4bJ7wo6KFgUyXlq0YPIZF4o7eVR7oC7vATX+f9howJstxz/QTqnGyo6qSCIgqgqGVUc898xfC2DzVrR9jSxjPl+ajEmYYTEuZNHPrV4ZvZJiy8G3EBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "s+gSK/z1Yq6vS7gHZ46TwA4nI4PEEfp3bFQ49VMpa8gBa8sVQJbUvo6yVTk6zuLfkj6tXqYtUyN8jQfH3E6dEy92OlrXqH5u44bYWljAawyOiEV87fUAe5Cun3moBFNpt++w+6l0r4WulyHSi+WIroNSXdSIas8wKBHb5JNwi+6x/4Zg9aZQ0A0ZweBLp3+LHX3SpYSvEzni8xxsSC+rhAl4CQhlMUIrZ1wMorsdgCOthcbNXrKtfpa875ZY0cacjXutXimuzbudNOes+6f2y+8=", @@ -706,7 +870,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x66145485300432cafb0f5c1387c5cf90e275dcd905c24348107bedc231ba690f", "0x7388d16dff1dedd7e404403daaeed4df3a9bdb3baa81c586662624f13dfa56bb" - ] + ], + "prestateLeaf": "s+gSK/z1Yq6vS7gHZ46TwA4nI4PEEfp3bFQ49VMpa8gBa8sVQJbUvo6yVTk6zuLfkj6tXqYtUyN8jQfH3E6dEy92OlrXqH5u44bYWljAawyOiEV87fUAe5Cun3moBFNpt++w+6l0r4WulyHSi+WIroNSXdSIas8wKBHb5JNwi+6x/4Zg9aZQ0A==", + "poststateLeaf": "DRnB4Eunf4sdfdKlhK8TOeLzHGxIL6uECXgJCGUxQitnXAyiux2AI62Fxs1esq1+lrzvlljRxpyNe61eKa7Nu50056z7p/bL7wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "mM4wTpKyOkZgpKod6R3xAcVeU0tiiklnVLM+vGmInIc0MnLiDjuNBTlIhm+6zZW5xYgVk5aOWWXb1MQjFcDEKfZLkn9SUVFjy01ISZlM9dppiUMFjSDjnzbEgKPE3lBuOJ+wfy/S+T7NNOxGboy+4HJbasw9CeK0orJTGpa8CAD97ZF8tVmhLvLQHfPQB8Be8ighEFl9lh5wFLbIzaiBHQdYSKSZRJUL3Rl/T1Bt7KLCLevgfszkxs/JWxA5woclF3ugsFZOg76RCeUVp0c=", @@ -714,7 +880,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x32f7beadef18e590ffe82aa5e8d36005de9bcb0e7e78a0c68381eacc4947e9bc", "0x75f2eebd6c67f78c7a6804b8c4d7637d12be4f35f505b4359e89e7bec6e52ec4" - ] + ], + "prestateLeaf": "mM4wTpKyOkZgpKod6R3xAcVeU0tiiklnVLM+vGmInIc0MnLiDjuNBTlIhm+6zZW5xYgVk5aOWWXb1MQjFcDEKfZLkn9SUVFjy01ISZlM9dppiUMFjSDjnzbEgKPE3lBuOJ+wfy/S+T7NNOxGboy+4HJbasw9CeK0orJTGpa8CAD97ZF8tVmhLg==", + "poststateLeaf": "8tAd89AHwF7yKCEQWX2WHnAUtsjNqIEdB1hIpJlElQvdGX9PUG3sosIt6+B+zOTGz8lbEDnChyUXe6CwVk6DvpEJ5RWnRwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "fXxLDLxHCvA4pJ5lr6+oXvZGW1UrxF0hDPn3pSkL7R7PHWCoW3AZ0N0t7kqIniKqjULZZ/ARy5fj4sXQhRWwJFRVSFs+hYmW3OXAUrrX2OIUAsPjj1q/Ooak5BzMFZ0INZgH5Nc2dGJTdnkatSf5yB3OWpTbx8zEhemmEBbQZIn2RpOC1S7kw9+bSl+hhT40Pn0H6bzrowytyMJZonr4d9Z7pPw/cEG0oxP0bflw380hAtB7aW3LX8qf/OpYRr4Ihwfj2eu0+ZkRLzHhZ2tqfqw1q7fVbryfpFij2edKyzKlzV1DLAplTUGNVdrV1NyVgWvny0MUAiSJJWPeRZXKqehiP4+myA1nDKuXYYgWlJLmPCJSoWjGEkDxltZGByDaLNkFC+eW25XQ2OMbdfzC2N3u60c7/cr2CPbiHzAhVZg/Wl8s5cDJMwTA8b38W3yks3QJGDCtgahuK5jUlWPRn88Ew3rz3NQ2l2fC4X3ZCteKYQFUDDX8IE/WeVeAmcH6yvoOEUM=", @@ -723,28 +891,36 @@ "0xa363a494c41749fa34acbfe0db3a4123732d2ee07bb972035424a4fbb757a992", "0xb4ba5242df70b066f1fdea7bd089ed021a3ddbf6a8cd7a755aec642983c7946c", "0xe1582c446cf455e06911c8bc76c3201fd3fd37c14241919f6aaab0e50d0393b1" - ] + ], + "prestateLeaf": "35tKX6GFPjQ+fQfpvOujDK3Iwlmievh31nuk/D9wQbSjE/Rt+XDfzSEC0Htpbctfyp/86lhGvgiHB+PZ67T5mREvMeFna2p+rDWrt9VuvJ+kWKPZ50rLMqXNXUMsCmVNQY1V2tXU3JWBa+fLQxQCJIklY95Flcqp6GI/j6bIDWcMq5dhiBaUkg==", + "poststateLeaf": "5jwiUqFoxhJA8ZbWRgcg2izZBQvnltuV0NjjG3X8wtjd7utHO/3K9gj24h8wIVWYP1pfLOXAyTMEwPG9/Ft8pLN0CRgwrYGobiuY1JVj0Z/PBMN689zUNpdnwuF92QrXimEBVAw1/CBP1nlXgJnB+sr6DhFDAQAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "BC+MRlxbvGUWnKSyfDm/ivblXLU9B8lijzAPSyuyDdTkYBZ/FSK4+2SMFmtm8KTghrh5OEvpwDz+NYX+y9wcxWFGBxy4zmC5QAmAZO78bJ0wSMdodhKgjE7JcPsUPgMuMGpvAa3TOQ==", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x6b0b2b4094f608f73c61f68be51329aff2fb0a5179de2b9b9467bfe9c3cdbe83" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "BC+MRlxbvGUWnKSyfDm/ivblXLU9B8lijzAPSyuyDdTkYBZ/FSK4+2SMFmtm8KTghrh5OEvpwDz+NYX+y9wcxWFGBxy4zmC5QAmAZO78bJ0wSMdodhKgjE7JcPsUPgMuMGpvAa3TOQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "3L2fS5vNMdKj6LqS47x4oHrNhIIxLe9WYJ8inef4jgT/WXKUwlXH3SH1x9WDtYYD2A==", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x202223f2c589349b4674f6a6e32bf2ade3d3134b59a5c7c663117ecc87fa1455" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "3L2fS5vNMdKj6LqS47x4oHrNhIIxLe9WYJ8inef4jgT/WXKUwlXH3SH1x9WDtYYD2AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "+1FoFm7ydb3xXIdbfSHG7FduytLO9fpgdX43FT+x7FtCbosJEV75Q81gxdLJ8JMMS3/Cxyk0dnEE7f/kI8tiaCdpoFMbXVSPETE+VhpYh3tqUsPx3XvxPp3UnsTT6QwXSWshkw==", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x6c7492b6bf953a71885ecd61168a95fc2e6d73ee46df0bf5ef3a366a34c364d3" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "+1FoFm7ydb3xXIdbfSHG7FduytLO9fpgdX43FT+x7FtCbosJEV75Q81gxdLJ8JMMS3/Cxyk0dnEE7f/kI8tiaCdpoFMbXVSPETE+VhpYh3tqUsPx3XvxPp3UnsTT6QwXSWshkwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "3NaoqHhyoYC9jYZUqLHxpGgV4QbDipeCZ8KMnYabEON2SusALPKdC6RsHpTor+9WiZGPVCzoIVL7uDeHQJqY1VQEYtpFjOhrrFzKQbTdgk1cVDGBR0lq6ePoElwQk8dbnXLuKtFoxm1dwXWXP1GTPup292cFh1z48m/uVunD53XXUmegojcj/z0XyOdUaPMQ/bK69bFNcwtoD3ZlfGukiNllk7jy59i3dK2KhabV2AaQjGJV6GZZmUku3reZ7E8nw536tqEUb0FcOCtXTjCyhFT5KyBzuDUR4w5MbNWj04L5TnRgZheADM3xb1XdBUrHYJNNCpDUKCUnYrHZrc4KEgCi+q/KppcvbvcBOAE8hoceshGtczZDXEdeycCZ", @@ -753,7 +929,9 @@ "0x01cbae12168f2f42f20bc0e26d21447f6e272d77ebea52b645f594b57fb2b6f7", "0x0392329f9ca01abab9d2b1cade00e7f99d0fcae8cee9f22c77b7adf1b4681432", "0x16938f33e76b533c425af0f345683dbc3f3d06abcef46ed196da3012aba4ff7e" - ] + ], + "prestateLeaf": "PRfI51Ro8xD9srr1sU1zC2gPdmV8a6SI2WWTuPLn2Ld0rYqFptXYBpCMYlXoZlmZSS7et5nsTyfDnfq2oRRvQVw4K1dOMLKEVPkrIHO4NRHjDkxs1aPTgvlOdGBmF4AMzfFvVd0FSsdgk00KkNQoJSdisdmtzgoSAKL6r8qmly9u9wE4ATyGhw==", + "poststateLeaf": "HrIRrXM2Q1xHXsnAmQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "bos9QTnn1rzgaPL0vtnPW9Jr1bj31IF1UGb7alBiDWiyNMWfXo+vlXuCdCKkVIn1kpB0ETLS05ZThUpi0rwMB85JRI9jYIiaZtqHECqmODDmi8HgMxNH8Tf3M9WEc2E4sN47vB6LJa7sZOgIfviCHla7LIUI6PCFNXMz6yg/eUNtQbA11qplkdP1LmRTOrw3Ry309S9eWmqkaVfDjzG94kpvM5yHl73JMdXVp/v0vCxFuuIM2EIVnaHbGbK2ggqwaHFIHXdSN2VQ/2O5TbG7gxEdxy/LWjV8RuttAbF1SAxEE5bXGiz6p1bkpLwcIzMTcdLSMjwwBgd2/1auF8Vm3NnAO+Rqnw==", @@ -761,7 +939,9 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x91d6e1afd0a075888cc2d5b5e693bdda3803325e39fbd6336ce9bc005c2d96e8", "0x948020ab27061f5f45c46affe3be5203860745491d71540e2b860330c0dd57ec" - ] + ], + "prestateLeaf": "bos9QTnn1rzgaPL0vtnPW9Jr1bj31IF1UGb7alBiDWiyNMWfXo+vlXuCdCKkVIn1kpB0ETLS05ZThUpi0rwMB85JRI9jYIiaZtqHECqmODDmi8HgMxNH8Tf3M9WEc2E4sN47vB6LJa7sZOgIfviCHla7LIUI6PCFNXMz6yg/eUNtQbA11qplkQ==", + "poststateLeaf": "0/UuZFM6vDdHLfT1L15aaqRpV8OPMb3iSm8znIeXvckx1dWn+/S8LEW64gzYQhWdodsZsraCCrBocUgdd1I3ZVD/Y7lNsbuDER3HL8taNXxG620BsXVIDEQTltcaLPqnVuSkvBwjMxNx0tIyPDAGB3b/Vq4XxWbc2cA75GqfAQAAAAAAAAAAgA==" }, { "input": "6SaxxD+YGI1vnZPnjyTUukGwlnv+6mi+kr0tPJNb+byqdsnp3EmNiZotRPcjKv0mSrN2QlaSgVvtpd1QeM61kh/HHzPqeyY+yl5q8oNTlh75uxskT6MdhHH0348dNg+jR2PkDEXArgnB+l036KgkH42p7RC8eX9fSvXEWnA/9y/khnGRJcfxPqXhFOSlGtFPbI/b4Ia1wmPRwUN80iNxypnlEWgyfClqvaftdOiWDlKOnzzBR3G0ZB1j7/AzKS0Z70K2nVOKtO7oYjMb17Puu3zVIpka2uh6iwLwa58wZlX4Wt2BG+r98k263zW90XyrYt00m6E8diC3B+t/7j0rt9gV6rlBbY6F/c8cIRENxBqWXcc3iemFBr/LYLI=", @@ -770,7 +950,9 @@ "0xec846a6c4315bc6e764fb641a2afe9f15d5eb1861714c76af033da30c15b04b2", "0x6fb5d7ce201d34f801ad591867e189294147d20f911077e1952d0b071bd3fa31", "0x0128bf2377b1952f0146ff7ae00ece8c7d6688cbc6c7cf2418a43bedc1fe5b38" - ] + ], + "prestateLeaf": "peEU5KUa0U9sj9vghrXCY9HBQ3zSI3HKmeURaDJ8KWq9p+106JYOUo6fPMFHcbRkHWPv8DMpLRnvQradU4q07uhiMxvXs+67fNUimRra6HqLAvBrnzBmVfha3YEb6v3yTbrfNb3RfKti3TSboTx2ILcH63/uPSu32BXquUFtjoX9zxwhEQ3EGg==", + "poststateLeaf": "ll3HN4nphQa/y2CyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "7HvyePr04PVkmE4UxQQoYO5qwGyrIYsGY0wmtlMaQ7p6ahwsCXxYL+1Rc7a9lz/oRaRmmhHt5DW6RFtBukhXe2ISy1ftItb82fmikh+Byu1fvJlVfkLfl5dzhoeXv8UHEroxoDNZnhOnt9/saECxkKX9Hp3y9wERFy3uXJzu68I+6tLcK7yRb6ZPAFlJgc8NFfYwu0SaXbV6HUPt50c0EqXs2B4vrxNdiJ5JPDm8a/bw6TB03dEZ7En2cbAYpTyrFjOTws2NdjWqkW1WH+RrSCSNiNSsbEEC6RIEfEss45JL28Ny9YjAnjwl31jpIkH1eY7SO5zuvKsxloZ8NeBTJeaiPu6MfO9WjO1HMi9usfe5IbjNT/Gsc+mcBFszP/6NHcyQYhR4qPNfOf5xp9wNjVYGOTSu5iQUPDfDgEEbTA6BiWIGnLIVT3xkWRcUGVoKM4cct7RHAie38r4/RMhQzfyEQ+Hjz1bZi/+DrXfUFyS6Cvn8G1eHcPXRUHZ+dLy2GzICgTLkTPbbTk8SgvepgdFIJPwGJgkSCYEvpWStEon41UiOP4ojQX4OFGwFrZ/wCdCGAKMB0Wa24Mww9n3ulrdRa95weEg=", @@ -780,7 +962,9 @@ "0x0cec7fa9e32761ef269f706014f5ca47b83388f58abf405cb3d4b58616b561a0", "0x34751c222f5447e5ce41d6f871bf218a1e7e270ddf360d0a200f1bf523d36e5f", "0xa6cada596a1452764f92fc089941d8205a08c8ce544d084eef7f65ce9c208b3e" - ] + ], + "prestateLeaf": "uSG4zU/xrHPpnARbMz/+jR3MkGIUeKjzXzn+cafcDY1WBjk0ruYkFDw3w4BBG0wOgYliBpyyFU98ZFkXFBlaCjOHHLe0RwInt/K+P0TIUM38hEPh489W2Yv/g6131Bckugr5/BtXh3D10VB2fnS8thsyAoEy5Ez2205PEoL3qYHRSCT8BiYJEg==", + "poststateLeaf": "CYEvpWStEon41UiOP4ojQX4OFGwFrZ/wCdCGAKMB0Wa24Mww9n3ulrdRa95weEgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "ul0dLBs/YmNE/uyOROGboezkmoislGftlZIN22FEHY+3nJzijZvf5hUnIeUjR34oGMXa8SIfAmPVhcM5MT3XIR6ZsZSs1Xg2Q4gsIz+lIdlke9uLi01KCa5+2ut8Um+3u9co+h9X/vM4Iwwmz43xaOVUlb6zn+4rBq3gAbFrxq3OrpYJJpfnxMnXp5qdYqQjH1vUYdYlrQKYYZKQHw8TVKHZZ2z/EV0XyqrUTzO6TRFRGNxcYtV8/OX5ErC3PF0FCoOat2iX3wgsptUNB3DhK9LuFu9G6/RJDOhfw/Ehps79yLjFYAwSyKi+OL874MkGgUsTiUTElF/EFAAfuB53aJHYPdEQi2Z6Zw74Ezzvh3oKQtp/Q/dShwyJ1/uZj2xdnfqwTWdI66ZcNNVT+PWTtLANTpFiJtgiy7f4f7xqWh0tcDqDFxwbQrzrdh+U3Mm7EZjQjACGLkCB1VNUn14JFuDnxfOnpqRQgdrzdFWmzsX/JFl4i8uCN4aYNCe1f38wMVb2d+1DqIzL20fIuMc7CjX/u+hojwRQZSTwDCLo9xMjB5sEFYu/NI8QyUNvx18pXkkLWIvvL8BYFkhB/lpzc9NMY6HCM5kV3Odk0u8FIHRm9B+Slj3gf//H5DbbU30pu3tJ9FAv9HkDs1U=", @@ -790,14 +974,18 @@ "0x2879dc29eb40af28eb88ed17c047548bedbf6dcab331ba8b6c050fe6803892a1", "0x85ad14cf814e5cf867611f6222ceb3f2c82dba3f6b1af34ecd236a1d8d9959ef", "0x60e4344aa77bf92735092f446229eb16a0e91ccf7351c9a9e8b207632861a936" - ] + ], + "prestateLeaf": "CkLaf0P3UocMidf7mY9sXZ36sE1nSOumXDTVU/j1k7SwDU6RYibYIsu3+H+8alodLXA6gxccG0K863YflNzJuxGY0IwAhi5AgdVTVJ9eCRbg58Xzp6akUIHa83RVps7F/yRZeIvLgjeGmDQntX9/MDFW9nftQ6iMy9tHyLjHOwo1/7voaI8EUA==", + "poststateLeaf": "ZSTwDCLo9xMjB5sEFYu/NI8QyUNvx18pXkkLWIvvL8BYFkhB/lpzc9NMY6HCM5kV3Odk0u8FIHRm9B+Slj3gf//H5DbbU30pu3tJ9FAv9HkDs1UBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "5AOpWwV0q9zthtbxpvpnf/utrQl1riNtoHTJPRm2uWgO6XaJlJQNKMXa", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0x5f19fac317da21422bb1f587b1dff8f3df060092fdbfdd227271e3bb3fc182fb" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "5AOpWwV0q9zthtbxpvpnf/utrQl1riNtoHTJPRm2uWgO6XaJlJQNKMXaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "svQ4eiNJWQvSsDd6UeZ9Vtc4B7u8MwMnxWdNmlP6LtqRbUIflXt3qcub8ceF9a37f10jXztRn/ey1pexOjfxxtCbyXKLjNGVLw0VdpgBK6D0cnPJsLuJEqZz7dgObU2Q4lY9rATN9ENjIu+QRW5s6kNiaaZwO7FC4xp6u9s0fnQBb9J46ORA5vBIclmqArka0tHUlGCVh4wm888oSMyKCpfGbyjRJotodRi+2JC6UVcAemTUqmO9ckw6pGZzupdgpD6HCsAHhATZIufyS4Uu+gzEzbCJjUz4aS0DvxItfw3LrNJnwv2pwqvstnxcx4N1loLN6N10yZ2qftCdhiv/Ci/DMf3wqn8ZhNOt9fXwMWF0EmhJznNMG+Hyej8g4/nuTMzwx/WcwATTsx0JJicXPDXphVOIYEw9lJlWnQ==", @@ -806,7 +994,9 @@ "0x52311ccdc69e2b3309a674bf5475cd132d2c32ed815028115cafd0f497ea6eb8", "0x5108714c345510560c7e8ad860626f648555dde85c5ff3c1bb9dac1b4b440481", "0x09c7f822bffa5ef1ac75cad13f6b2741bbe5e5ce34a347d16bf7e1b48b8c7687" - ] + ], + "prestateLeaf": "8EhyWaoCuRrS0dSUYJWHjCbzzyhIzIoKl8ZvKNEmi2h1GL7YkLpRVwB6ZNSqY71yTDqkZnO6l2CkPocKwAeEBNki5/JLhS76DMTNsImNTPhpLQO/Ei1/Dcus0mfC/anCq+y2fFzHg3WWgs3o3XTJnap+0J2GK/8KL8Mx/fCqfxmE06319fAxYQ==", + "poststateLeaf": "dBJoSc5zTBvh8no/IOP57kzM8Mf1nMAE07MdCSYnFzw16YVTiGBMPZSZVp0BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "XTleBrkuE5hWTQJFJRFhD12lyVTeV9AXaG/EaSuKhyAjK1EWJGArTmr/+vXyPgm7Wnc3TVRD32GpQIl3o/6bg9nHQ119M2lXyw6mAyypwl5IhmzIns1D3nhgrZJ+9Nz68SRWJ84oLv0Mm33ZHLAoCYmpGqFL4IIWPg96Ds5UHzF8bbEF2SAiYV3LLmGs1sblREH8+yYCCRSwgW9m65lYsDDvM7+QqauLXaOxWEQJcW8zA9G+U402rkB4q26uXxUkUcEsXGWW6d6qyE2uG8C54BWb2eYaaYVC+rWFdIUwJaXJvD7jJhFIj36NsjxZdX2Wckt6j3s2EmNiQwQNJgPqyHd/1cLANrekOoGKWOVm7P/LNpDEoxHntBvh7MVnEorJ", @@ -815,14 +1005,18 @@ "0xc34e8c6768cdd7c7cce28f8547e33f113191da57e3691db60e1ee55800fe96b0", "0x0ac6cedb22f964162bf1a543d006b8d232af6a3f44076cbe30772f9f28c27a95", "0x0809ac2786ade5f79fa427a0377b89ec99ac109ff230ec81bb4d609bcf7fd954" - ] + ], + "prestateLeaf": "XcsuYazWxuVEQfz7JgIJFLCBb2brmViwMO8zv5Cpq4tdo7FYRAlxbzMD0b5TjTauQHirbq5fFSRRwSxcZZbp3qrITa4bwLngFZvZ5hpphUL6tYV0hTAlpcm8PuMmEUiPfo2yPFl1fZZyS3qPezYSY2JDBA0mA+rId3/VwsA2t6Q6gYpY5Wbs/w==", + "poststateLeaf": "yzaQxKMR57Qb4ezFZxKKyQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "eCmovNYrO+YV73aWboXDY/ToIZIp6UfGwIarwJunhPk8EVjTQb3x5K8BPPMG5KRLbTh12+Pu31HC2xXyg7F+SmHbXmt+Uog9FXvnrI9emRAk", "commitments": [ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xd517103b16c5e12cca833ae2cc160e3d11c59c20aa380cfa5284aa10bdf4709a" - ] + ], + "prestateLeaf": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "poststateLeaf": "eCmovNYrO+YV73aWboXDY/ToIZIp6UfGwIarwJunhPk8EVjTQb3x5K8BPPMG5KRLbTh12+Pu31HC2xXyg7F+SmHbXmt+Uog9FXvnrI9emRAkAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "uY3e1GKA8n27JPlxrOmwzav0R8hB2C1oQbUTsZVf17ImDpTqC2e0aeBUOvA+xfyOEUiVoAhF8zd2EfZdt1PG9U+3kOYhLyNKzmjvzosHvIHRw6W8NXqrd0RsmW4i1OLAzJyxbwHvH5G55VVdE1WTmWh/uWC/ww1JDMuUd9n+QddNQng8Q9lxAzhZ8PQMefc9a7fe/XBinzIBtnd2A6kkGa0zd7uoEbElMcrwqBEkDhteq1ykSOE/WDk4xcazJZqt4eMIj6asb5YTLr5EZQXtS1StsS6KiMZmiowo6rBtHCkpwGHN5Vx3whCG1BPw1l3ZRsYq09YM++DF7krB/rf/VxZGvS1T1UUX5v64dSj9PfR2Hm46qnB3eiA+5vwYAA0m7n+Rb6tSKVgpG/FnMXR29PH86EDxNWSzVIa9yFFhRReIW/BHlV7saXrb3A6Ff8UxQxcpcgMMdYDttUeQ7g==", @@ -831,7 +1025,9 @@ "0xcdd63146e8f5f65947495f8051b4696f73b6dcf5965519736f223e4cafb50b4e", "0x7633254742d3f1fb964adde4a6b281aacbe57b38ccfd3032a0fb8d8ccf1352ed", "0x8a08eb0d9beec9bd41f5244566b9d8c524e89a9b22dc0f33504fbbe3dd5eed20" - ] + ], + "prestateLeaf": "OFnw9Ax59z1rt979cGKfMgG2d3YDqSQZrTN3u6gRsSUxyvCoESQOG16rXKRI4T9YOTjFxrMlmq3h4wiPpqxvlhMuvkRlBe1LVK2xLoqIxmaKjCjqsG0cKSnAYc3lXHfCEIbUE/DWXdlGxirT1gz74MXuSsH+t/9XFka9LVPVRRfm/rh1KP099A==", + "poststateLeaf": "dh5uOqpwd3ogPub8GAANJu5/kW+rUilYKRvxZzF0dvTx/OhA8TVks1SGvchRYUUXiFvwR5Ve7Gl629wOhX/FMUMXKXIDDHWA7bVHkO4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "l55l8M4SnsMkcXMGROaphUDY4YUoIyj1d4c/9n3Oym78zfdrkHlgmId6gEeOwUsh0VJ3ja8OH42qiHP10gmKlkXLaWdmJBXQTrT/ygJt7FLJzpqmsSC082JcGT8EHbktfLmRtyKa7mNZjgVsZvxEOcR/fCnF23QnW3qB9gy7Z9odXlqrOka01yBXgPIvcWutRK1M6pq/BRZ9WrXg6uatCZcgE7VhSvAqVq7IWWoA9bKzPlDcWqrwKmIgmGY6gA8J83LbX9Pw4lyvj7AO9rJg4hvuRbbWDeMva2DjzBZsw/66T+CQ5htuevS35DWEVBsEcnPjBdEtWS5dqOiNl72levHJIbfM3RQ/pmhhPd87CmEX9AUeRZ1RFmHB6k7I+ZPZF5IO0+y9Vug67oXUSBmo1onZLKRdbiEuClHf9mbh4Ms=", @@ -840,7 +1036,9 @@ "0xf9df249199350922bdb3d0d66ad8348746df540c87f092b006ae68637b8af765", "0x5d6cbc50af5573059040f81bb9855d2685660e5caa57b88126a9ef7beccb8e26", "0x40d0dc4e0214f314b8114d49e6b3ba842433c341390d7a63ad9be12ad76697ce" - ] + ], + "prestateLeaf": "IFeA8i9xa61ErUzqmr8FFn1ateDq5q0JlyATtWFK8CpWrshZagD1srM+UNxaqvAqYiCYZjqADwnzcttf0/DiXK+PsA72smDiG+5FttYN4y9rYOPMFmzD/rpP4JDmG2569LfkNYRUGwRyc+MF0S1ZLl2o6I2XvaV68ckht8zdFD+maGE93zsKYQ==", + "poststateLeaf": "F/QFHkWdURZhwepOyPmT2ReSDtPsvVboOu6F1EgZqNaJ2SykXW4hLgpR3/Zm4eDLAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" }, { "input": "pisVHfcf8JErfu8ZBb1hDtca67kfmzBHQU4ls3/oeZ7EN0mGnmHN/wUvrHqNyS+32HnH5duO/MiyN5kGH1IqY8IVLEjXF84WfbZsupoXyuDvvkYjPEwVlVAer0vCRkugw9Z8X2DctMcRq9Tc3xLTEPel2+jLCceyzbJvvUNjFqh4CWT1zqpqQCgRYfzo1+hDV554ifwMhbrWCrAam+CvGzmvNZ8+AJ6VIdbTPiSCOywS+/UIzz0=", @@ -848,6 +1046,48 @@ "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", "0xcd4659f1f12afa5949b88198029fc204f63a18d6d4b00c4f8c216019cda7653c", "0x55b83209b05d78020837a302f30f74151e1c871be2ae0f43d6e3d239a05a6416" - ] + ], + "prestateLeaf": "pisVHfcf8JErfu8ZBb1hDtca67kfmzBHQU4ls3/oeZ7EN0mGnmHN/wUvrHqNyS+32HnH5duO/MiyN5kGH1IqY8IVLEjXF84WfbZsupoXyuDvvkYjPEwVlVAer0vCRkugw9Z8X2DctMcRq9Tc3xLTEPel2+jLCceyzbJvvUNjFqh4CWT1zqpqQA==", + "poststateLeaf": "KBFh/OjX6ENXnniJ/AyFutYKsBqb4K8bOa81nz4AnpUh1tM+JII7LBL79QjPPQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" + }, + { + "input": "O8NUg0KaDo18ybTKajXM/sgqEYS37+lewPhGV/2sMAX6bu6pD+hu97cVqUkoazqhtXPFvnwPFy/jQjR+LFOXFZvvjCRgFRQvzzKOb8DJ0fqCRLgr9kiHN9LpqHXVhyHhhlRkem0+AIzvEmyqbgj5pbDQsr0gtBBZYN/IwUYeggMVEhM/rDKEiLf1Z5E/xs1a5ukkKJwXBVAioEmG81qwOBn9FqHWIrclhCUpqZRfRIZPp8ZXl64RTSIXhGibMujQipVQuXUsAOd4QE4HjirdI9SfzsLMesYimfC/eedEkhjL0z9+sjhgp5wJY84LBiNI6ZwrzNGke/zdySctbfKbgj2q6ECX3jy6lbeiNThEdLfO1t+IHM7rijOlNw/r8Up3YgH5ExUuuAOUJ5B8OuPXyMfnl484FISrdt0XGpNJpS66b1XHmf7p3TmFLlnO7/23uN57KiNdpe0RaB8R+Y5IzmcWrzR67wcbjbBTbjbAD6w1QIWVx6iUVSfciQIgw7WdYK1C6PXxUMEflpAnV0POZSMu++sbYrxJhlGArYgVbSH4i93eENLOJytOfnKXYzirqsHyCjHa55FqYBqC4ogkXXHBIzE90x9n2bNpc2IHYXIUfDcrkZSQFBnyze2uRsYx8dBXi+Pd2pLSFc3l0WnUCRXc4LCMFKEKWy/6fPHAUTy569sNCQd1E19Fx96UAQOsLRAtiHKp9XwCQYFhnPY2j61MYnsnV1Eh+cBc4J8ofY4mK4r7OBY9ze9+qrP95CCxyDJUIHDzDySR05MlXTJwwmA1a2X4r45shLLgZEF6EWsLwSvibme0tjvzczsfIwNGAmvg2gx4Uajr6kBelBRAobURalVBBx0SLghEjf1pXftmDkmRJipoV7tUVNK4tYEm5VVAZ95AA98=", + "commitments": [ + "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", + "0xbedfbe751c8d3913a76bb030bdcad312ce8c70aeabfaefcf491dafe740946ca5", + "0x74393cbd5f8764be54385a8c7f9442358ae2580f33aebc2597ffa42949172a34", + "0xc881ce64585de627f538376cae9513ca5f4efaa2ab255ce3fa5b15e890223982", + "0xa6ad654807a4f8de3b78d7fa389dc3bd31bbbb5bef24e8e8174f75c6f9ac5c6d", + "0xf6785ff09114b843cccff1e119100ca5ec235725ef2763573e1f3063bf48b886", + "0x20642552f0e7ef28ff28252b3839f0fa323f46792bd103baa9778684f737cda3" + ], + "prestateLeaf": "rUxieydXUSH5wFzgnyh9jiYrivs4Fj3N736qs/3kILHIMlQgcPMPJJHTkyVdMnDCYDVrZfivjmyEsuBkQXoRawvBK+JuZ7S2O/NzOx8jA0YCa+DaDHhRqOvqQF6UFEChtRFqVUEHHRIuCESN/Wld+2YOSZEmKmhXu1RU0ri1gSblVUBn3kAD3w==", + "poststateLeaf": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA==" + }, + { + "input": "O8NUg0KaDo18ybTKajXM/sgqEYS37+lewPhGV/2sMAX6bu6pD+hu97cVqUkoazqhtXPFvnwPFy/jQjR+LFOXFZvvjCRgFRQvzzKOb8DJ0fqCRLgr9kiHN9LpqHXVhyHhhlRkem0+AIzvEmyqbgj5pbDQsr0gtBBZYN/IwUYeggMVEhM/rDKEiLf1Z5E/xs1a5ukkKJwXBVAioEmG81qwOBn9FqHWIrclhCUpqZRfRIZPp8ZXl64RTSIXhGibMujQipVQuXUsAOd4QE4HjirdI9SfzsLMesYimfC/eedEkhjL0z9+sjhgp5wJY84LBiNI6ZwrzNGke/zdySctbfKbgj2q6ECX3jy6lbeiNThEdLfO1t+IHM7rijOlNw/r8Up3YgH5ExUuuAOUJ5B8OuPXyMfnl484FISrdt0XGpNJpS66b1XHmf7p3TmFLlnO7/23uN57KiNdpe0RaB8R+Y5IzmcWrzR67wcbjbBTbjbAD6w1QIWVx6iUVSfciQIgw7WdYK1C6PXxUMEflpAnV0POZSMu++sbYrxJhlGArYgVbSH4i93eENLOJytOfnKXYzirqsHyCjHa55FqYBqC4ogkXXHBIzE90x9n2bNpc2IHYXIUfDcrkZSQFBnyze2uRsYx8dBXi+Pd2pLSFc3l0WnUCRXc4LCMFKEKWy/6fPHAUTy569sNCQd1E19Fx96UAQOsLRAtiHKp9XwCQYFhnPY2j61MYnsnV1Eh+cBc4J8ofY4mK4r7OBY9ze9+qrP95CCxyDJUIHDzDySR05MlXTJwwmA1a2X4r45shLLgZEF6EWsLwSvibme0tjvzczsfIwNGAmvg2gx4Uajr6kBelBRAobURalVBBx0SLghEjf1pXftmDkmRJipoV7tUVNK4tYEm5VVAZ95AAw==", + "commitments": [ + "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", + "0xbedfbe751c8d3913a76bb030bdcad312ce8c70aeabfaefcf491dafe740946ca5", + "0x74393cbd5f8764be54385a8c7f9442358ae2580f33aebc2597ffa42949172a34", + "0xc881ce64585de627f538376cae9513ca5f4efaa2ab255ce3fa5b15e890223982", + "0xa6ad654807a4f8de3b78d7fa389dc3bd31bbbb5bef24e8e8174f75c6f9ac5c6d", + "0x71ca4f0903770f2035f3650a40ac8b23d00aaffd7b155a8be5bd02ff1c944181" + ], + "prestateLeaf": "hlGArYgVbSH4i93eENLOJytOfnKXYzirqsHyCjHa55FqYBqC4ogkXXHBIzE90x9n2bNpc2IHYXIUfDcrkZSQFBnyze2uRsYx8dBXi+Pd2pLSFc3l0WnUCRXc4LCMFKEKWy/6fPHAUTy569sNCQd1E19Fx96UAQOsLRAtiHKp9XwCQYFhnPY2jw==", + "poststateLeaf": "rUxieydXUSH5wFzgnyh9jiYrivs4Fj3N736qs/3kILHIMlQgcPMPJJHTkyVdMnDCYDVrZfivjmyEsuBkQXoRawvBK+JuZ7S2O/NzOx8jA0YCa+DaDHhRqOvqQF6UFEChtRFqVUEHHRIuCESN/Wld+2YOSZEmKmhXu1RU0ri1gSblVUBn3kADgQ==" + }, + { + "input": "O8NUg0KaDo18ybTKajXM/sgqEYS37+lewPhGV/2sMAX6bu6pD+hu97cVqUkoazqhtXPFvnwPFy/jQjR+LFOXFZvvjCRgFRQvzzKOb8DJ0fqCRLgr9kiHN9LpqHXVhyHhhlRkem0+AIzvEmyqbgj5pbDQsr0gtBBZYN/IwUYeggMVEhM/rDKEiLf1Z5E/xs1a5ukkKJwXBVAioEmG81qwOBn9FqHWIrclhCUpqZRfRIZPp8ZXl64RTSIXhGibMujQipVQuXUsAOd4QE4HjirdI9SfzsLMesYimfC/eedEkhjL0z9+sjhgp5wJY84LBiNI6ZwrzNGke/zdySctbfKbgj2q6ECX3jy6lbeiNThEdLfO1t+IHM7rijOlNw/r8Up3YgH5ExUuuAOUJ5B8OuPXyMfnl484FISrdt0XGpNJpS66b1XHmf7p3TmFLlnO7/23uN57KiNdpe0RaB8R+Y5IzmcWrzR67wcbjbBTbjbAD6w1QIWVx6iUVSfciQIgw7WdYK1C6PXxUMEflpAnV0POZSMu++sbYrxJhlGArYgVbSH4i93eENLOJytOfnKXYzirqsHyCjHa55FqYBqC4ogkXXHBIzE90x9n2bNpc2IHYXIUfDcrkZSQFBnyze2uRsYx8dBXi+Pd2pLSFc3l0WnUCRXc4LCMFKEKWy/6fPHAUTy569sNCQd1E19Fx96UAQOsLRAtiHKp9XwCQYFhnPY2j61MYnsnV1Eh+cBc4J8ofY4mK4r7OBY9ze9+qrP95CCxyDJUIHDzDySR05MlXTJwwmA1a2X4r45shLLgZEF6EWsLwSvibme0tjvzczsfIwNGAmvg2gx4Uajr6kBelBRAobURalVBBx0SLghEjf1pXftmDkmRJipoV7tUVNK4tYEm5VVAZ95A", + "commitments": [ + "0xee0a1a26c607ab52c6308165995365f7951a185fccca4b76c847b8860d9fea7a", + "0xbedfbe751c8d3913a76bb030bdcad312ce8c70aeabfaefcf491dafe740946ca5", + "0x74393cbd5f8764be54385a8c7f9442358ae2580f33aebc2597ffa42949172a34", + "0xc881ce64585de627f538376cae9513ca5f4efaa2ab255ce3fa5b15e890223982", + "0xa6ad654807a4f8de3b78d7fa389dc3bd31bbbb5bef24e8e8174f75c6f9ac5c6d", + "0x8c3c5310bc148f9c71d9c0a8771479fb87c6fd9d9595ba60ded7b8eba1d6a483" + ], + "prestateLeaf": "hlGArYgVbSH4i93eENLOJytOfnKXYzirqsHyCjHa55FqYBqC4ogkXXHBIzE90x9n2bNpc2IHYXIUfDcrkZSQFBnyze2uRsYx8dBXi+Pd2pLSFc3l0WnUCRXc4LCMFKEKWy/6fPHAUTy569sNCQd1E19Fx96UAQOsLRAtiHKp9XwCQYFhnPY2jw==", + "poststateLeaf": "rUxieydXUSH5wFzgnyh9jiYrivs4Fj3N736qs/3kILHIMlQgcPMPJJHTkyVdMnDCYDVrZfivjmyEsuBkQXoRawvBK+JuZ7S2O/NzOx8jA0YCa+DaDHhRqOvqQF6UFEChtRFqVUEHHRIuCESN/Wld+2YOSZEmKmhXu1RU0ri1gSblVUBn3kABgA==" } ] diff --git a/op-challenger/game/keccak/merkle/testdata/proofs.json b/op-challenger/game/keccak/merkle/testdata/proofs.json new file mode 100644 index 000000000000..cf319a4aab25 --- /dev/null +++ b/op-challenger/game/keccak/merkle/testdata/proofs.json @@ -0,0 +1,177 @@ +[ + { + "name": "NoLeaves", + "rootHash": "0x2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f", + "leafCount": 0, + "index": 0, + "proofs": [] + }, + { + "name": "SingleLeaf", + "rootHash": "0x8285ae2d9ccfc8021051c1ea3dfa5ba8219605d0e28c941f1bc174822eda1154", + "leafCount": 1, + "index": 0, + "proofs": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", + "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", + "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", + "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", + "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", + "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", + "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", + "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", + "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", + "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", + "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", + "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", + "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", + "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", + "0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2" + ] + }, + { + "name": "TwoLeaves", + "rootHash": "0x2f27513ae8b07634c3ac408e55e7b4b6d0dc400e3fa9b2165607d61a84625608", + "leafCount": 2, + "index": 1, + "proofs": [ + "0xff00000000000000000000000000000000000000000000000000000000000000", + "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", + "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", + "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", + "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", + "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", + "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", + "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", + "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", + "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", + "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", + "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", + "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", + "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", + "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", + "0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2" + ] + }, + { + "name": "SingleLeaf", + "rootHash": "0x8285ae2d9ccfc8021051c1ea3dfa5ba8219605d0e28c941f1bc174822eda1154", + "leafCount": 1, + "index": 1, + "proofs": [ + "0xff00000000000000000000000000000000000000000000000000000000000000", + "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", + "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", + "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", + "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", + "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", + "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", + "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", + "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", + "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", + "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", + "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", + "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", + "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", + "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", + "0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2" + ] + }, + { + "name": "PartialTree", + "rootHash": "0x72cdab4557ab96d1246b76e49b1d1a582662ebfceafe2f9c2922304d4fb9db33", + "leafCount": 20, + "index": 10, + "proofs": [ + "0xff0b000000000000000000000000000000000000000000000000000000000000", + "0xa68dfd9074d20ce110c771102e62f17a85ae562a56149e112dd4fecb6cbd8f52", + "0x892339d3cfe686a15b728211f6a3e4f21cf4ee128b152664c90f231f5a9f8333", + "0xd8ca500dee0f1f7334075ebef1e979652b70355c56e09b74d50c87e31e675ddb", + "0x0c9a9c89e79e068154f6c2b9b827cd4f3972e035542ebb68d68b9120e757626c", + "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", + "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", + "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", + "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", + "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", + "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", + "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", + "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", + "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", + "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", + "0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2" + ] + }, + { + "name": "PartialTree", + "rootHash": "0x72cdab4557ab96d1246b76e49b1d1a582662ebfceafe2f9c2922304d4fb9db33", + "leafCount": 20, + "index": 11, + "proofs": [ + "0xff0a000000000000000000000000000000000000000000000000000000000000", + "0xa68dfd9074d20ce110c771102e62f17a85ae562a56149e112dd4fecb6cbd8f52", + "0x892339d3cfe686a15b728211f6a3e4f21cf4ee128b152664c90f231f5a9f8333", + "0xd8ca500dee0f1f7334075ebef1e979652b70355c56e09b74d50c87e31e675ddb", + "0x0c9a9c89e79e068154f6c2b9b827cd4f3972e035542ebb68d68b9120e757626c", + "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", + "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", + "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", + "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", + "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", + "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", + "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", + "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", + "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", + "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", + "0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2" + ] + }, + { + "name": "PartialTree", + "rootHash": "0x9c089c06e4f93c68d74fdfef9255cb75f78b053dabb43749d20e21aa8330092c", + "leafCount": 65535, + "index": 65533, + "proofs": [ + "0xfffc000000000000000000000000000000000000000000000000000000000000", + "0xf52ca96368ae7189a9a33f0efefd1b0a2a2c208c8dca11a2b1066fe99a6582c5", + "0x6a9b869f709b2d34940a0bbe9eea3d502f1e918a4490eb890f1727d6843c055d", + "0x02f7a2dbcc9b3d6780f7f72aafd200af423ba438d45c535d2d4e333e43ce98fc", + "0x84952e81b8cba49f78e4ee1ef684936b09c1b851ecbe03382afecc04fb98b305", + "0x2f9e97e47493214948c70a6b818145a7e9cd84f7ceab384b179559730d7efbac", + "0x3414ae9dd358c60fae6b4010fc90af715bcc5d0fdd55cefd5370277de456c4b8", + "0x04c3b7e470a22c856003970d95b7015f284a0a09c8bc18e1da02078ded445d58", + "0x417e698fd035c879670c381d7bb0815ce67fb854625e502984ae8e2436ede0a9", + "0x042abe5eb9668a197d5389e4b225c474a7646950279cbd6d326db073ea120266", + "0x34f6ea610e918f37226300a42b22f702f3dd7bd7ae17e9dcb6e7374906b83aef", + "0x1c050824157972417b2931f6018ed24e3fe7fedf7c5a502eb26710501d5379d2", + "0x529067b7c2a065d285b931d19fd85ad35eb0abf89c1ed40ca836ace2c7ddad9e", + "0xfd4d4328beb216713b978c561d4acde2ffe400c60d4b6abe21940c0cff2bf0bc", + "0x9b4a92fefca8b04570c15e329cbc6c953dbe30e06607d985882f35fb8cfd986a", + "0x6ec52bd9024705f2c1bd913c43550f5c2b3fbba19dee077b4da6aa6cd90d1c3f" + ] + }, + { + "name": "FullTree", + "rootHash": "0x9c089c06e4f93c68d74fdfef9255cb75f78b053dabb43749d20e21aa8330092c", + "leafCount": 65535, + "index": 65534, + "proofs": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x65cf5d60111a84456933bd43218230c6235995be88b274e196e8ffcb88927db6", + "0x6a9b869f709b2d34940a0bbe9eea3d502f1e918a4490eb890f1727d6843c055d", + "0x02f7a2dbcc9b3d6780f7f72aafd200af423ba438d45c535d2d4e333e43ce98fc", + "0x84952e81b8cba49f78e4ee1ef684936b09c1b851ecbe03382afecc04fb98b305", + "0x2f9e97e47493214948c70a6b818145a7e9cd84f7ceab384b179559730d7efbac", + "0x3414ae9dd358c60fae6b4010fc90af715bcc5d0fdd55cefd5370277de456c4b8", + "0x04c3b7e470a22c856003970d95b7015f284a0a09c8bc18e1da02078ded445d58", + "0x417e698fd035c879670c381d7bb0815ce67fb854625e502984ae8e2436ede0a9", + "0x042abe5eb9668a197d5389e4b225c474a7646950279cbd6d326db073ea120266", + "0x34f6ea610e918f37226300a42b22f702f3dd7bd7ae17e9dcb6e7374906b83aef", + "0x1c050824157972417b2931f6018ed24e3fe7fedf7c5a502eb26710501d5379d2", + "0x529067b7c2a065d285b931d19fd85ad35eb0abf89c1ed40ca836ace2c7ddad9e", + "0xfd4d4328beb216713b978c561d4acde2ffe400c60d4b6abe21940c0cff2bf0bc", + "0x9b4a92fefca8b04570c15e329cbc6c953dbe30e06607d985882f35fb8cfd986a", + "0x6ec52bd9024705f2c1bd913c43550f5c2b3fbba19dee077b4da6aa6cd90d1c3f" + ] + } +] diff --git a/op-challenger/game/keccak/merkle/tree.go b/op-challenger/game/keccak/merkle/tree.go new file mode 100644 index 000000000000..16a6c02218b0 --- /dev/null +++ b/op-challenger/game/keccak/merkle/tree.go @@ -0,0 +1,154 @@ +package merkle + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +// BinaryMerkleTreeDepth is the depth of the merkle tree. +const BinaryMerkleTreeDepth = 16 + +// Proof is a list of [common.Hash]s that prove the merkle inclusion of a leaf. +// These are the sibling hashes of the leaf's path from the root to the leaf. +type Proof [BinaryMerkleTreeDepth]common.Hash + +var ( + // MaxLeafCount is the maximum number of leaves in the merkle tree. + MaxLeafCount = 1<= uint64(MaxLeafCount) { + panic("proof index out of bounds") + } + + levelNode := m.walkDownToLeafCount(index + 1) + for height := 0; height < BinaryMerkleTreeDepth; height++ { + if levelNode.Parent.IsLeftChild(levelNode) { + if levelNode.Parent.Right == nil { + proof[height] = common.Hash{} + } else { + proof[height] = levelNode.Parent.Right.Label + } + } else { + if levelNode.Parent.Left == nil { + proof[height] = common.Hash{} + } else { + proof[height] = levelNode.Parent.Left.Label + } + } + levelNode = levelNode.Parent + } + + return proof +} diff --git a/op-challenger/game/keccak/merkle/tree_test.go b/op-challenger/game/keccak/merkle/tree_test.go new file mode 100644 index 000000000000..3fa5f83ddce2 --- /dev/null +++ b/op-challenger/game/keccak/merkle/tree_test.go @@ -0,0 +1,78 @@ +package merkle + +import ( + _ "embed" + "encoding/json" + "fmt" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +//go:embed testdata/proofs.json +var refTests []byte + +type testData struct { + Name string `json:"name"` + LeafCount uint64 `json:"leafCount"` + RootHash common.Hash `json:"rootHash"` + Index uint64 `json:"index"` + Proofs Proof `json:"proofs"` +} + +func TestBinaryMerkleTree_AddLeaf(t *testing.T) { + var tests []testData + require.NoError(t, json.Unmarshal(refTests, &tests)) + + for i, test := range tests { + test := test + t.Run(fmt.Sprintf("%s-LeafCount-%v-Ref-%v", test.Name, test.LeafCount, i), func(t *testing.T) { + tree := NewBinaryMerkleTree() + expectedLeafHash := zeroHashes[BinaryMerkleTreeDepth-1] + for i := 0; i < int(test.LeafCount); i++ { + expectedLeafHash = leafHash(i) + tree.AddLeaf(expectedLeafHash) + } + leaf := tree.walkDownToLeafCount(tree.LeafCount) + require.Equal(t, expectedLeafHash, leaf.Label) + }) + } +} + +func TestBinaryMerkleTree_RootHash(t *testing.T) { + var tests []testData + require.NoError(t, json.Unmarshal(refTests, &tests)) + + for i, test := range tests { + test := test + t.Run(fmt.Sprintf("%s-LeafCount-%v-Ref-%v", test.Name, test.LeafCount, i), func(t *testing.T) { + tree := NewBinaryMerkleTree() + for i := 0; i < int(test.LeafCount); i++ { + tree.AddLeaf(leafHash(i)) + } + require.Equal(t, test.RootHash, tree.RootHash()) + }) + } +} + +func TestBinaryMerkleTree_ProofAtIndex(t *testing.T) { + var tests []testData + require.NoError(t, json.Unmarshal(refTests, &tests)) + + for i, test := range tests { + test := test + t.Run(fmt.Sprintf("%s-Index-%v-Ref-%v", test.Name, test.LeafCount, i), func(t *testing.T) { + tree := NewBinaryMerkleTree() + for i := 0; i < int(test.LeafCount); i++ { + tree.AddLeaf(leafHash(i)) + } + proof := tree.ProofAtIndex(test.Index) + require.Equal(t, test.Proofs, proof) + }) + } +} + +func leafHash(idx int) common.Hash { + return common.Hash{0xff, byte(idx)} +} diff --git a/op-challenger/game/keccak/scheduler.go b/op-challenger/game/keccak/scheduler.go index fb9c87707615..e9d8cb583be4 100644 --- a/op-challenger/game/keccak/scheduler.go +++ b/op-challenger/game/keccak/scheduler.go @@ -2,32 +2,46 @@ package keccak import ( "context" + "errors" + "fmt" "sync" + "time" + faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) -type Verifier interface { - Verify(ctx context.Context, blockHash common.Hash, oracle keccakTypes.LargePreimageOracle, preimage keccakTypes.LargePreimageMetaData) error +type Challenger interface { + Challenge(ctx context.Context, blockHash common.Hash, oracle Oracle, preimages []keccakTypes.LargePreimageMetaData) error +} + +type OracleSource interface { + Oracles() []keccakTypes.LargePreimageOracle } type LargePreimageScheduler struct { - log log.Logger - ch chan common.Hash - oracles []keccakTypes.LargePreimageOracle - verifier Verifier - cancel func() - wg sync.WaitGroup + log log.Logger + cl faultTypes.ClockReader + ch chan common.Hash + oracles OracleSource + challenger Challenger + cancel func() + wg sync.WaitGroup } -func NewLargePreimageScheduler(logger log.Logger, oracles []keccakTypes.LargePreimageOracle, verifier Verifier) *LargePreimageScheduler { +func NewLargePreimageScheduler( + logger log.Logger, + cl faultTypes.ClockReader, + oracleSource OracleSource, + challenger Challenger) *LargePreimageScheduler { return &LargePreimageScheduler{ - log: logger, - ch: make(chan common.Hash, 1), - oracles: oracles, - verifier: verifier, + log: logger, + cl: cl, + ch: make(chan common.Hash, 1), + oracles: oracleSource, + challenger: challenger, } } @@ -52,7 +66,7 @@ func (s *LargePreimageScheduler) run(ctx context.Context) { return case blockHash := <-s.ch: if err := s.verifyPreimages(ctx, blockHash); err != nil { - s.log.Error("Failed to verify large preimages", "err", err) + s.log.Error("Failed to verify large preimages", "blockHash", blockHash, "err", err) } } } @@ -62,28 +76,33 @@ func (s *LargePreimageScheduler) Schedule(blockHash common.Hash, _ uint64) error select { case s.ch <- blockHash: default: - // Already busy processing, skip this update + s.log.Trace("Skipping preimage check while already processing") } return nil } func (s *LargePreimageScheduler) verifyPreimages(ctx context.Context, blockHash common.Hash) error { - for _, oracle := range s.oracles { - if err := s.verifyOraclePreimages(ctx, oracle, blockHash); err != nil { - s.log.Error("Failed to verify preimages in oracle %v: %w", oracle.Addr(), err) - } + var err error + for _, oracle := range s.oracles.Oracles() { + err = errors.Join(err, s.verifyOraclePreimages(ctx, oracle, blockHash)) } - return nil + return err } func (s *LargePreimageScheduler) verifyOraclePreimages(ctx context.Context, oracle keccakTypes.LargePreimageOracle, blockHash common.Hash) error { preimages, err := oracle.GetActivePreimages(ctx, blockHash) + if err != nil { + return err + } + period, err := oracle.ChallengePeriod(ctx) + if err != nil { + return fmt.Errorf("failed to load challenge period: %w", err) + } + toVerify := make([]keccakTypes.LargePreimageMetaData, 0, len(preimages)) for _, preimage := range preimages { - if preimage.ShouldVerify() { - if err := s.verifier.Verify(ctx, blockHash, oracle, preimage); err != nil { - s.log.Error("Failed to verify large preimage", "oracle", oracle.Addr(), "claimant", preimage.Claimant, "uuid", preimage.UUID, "err", err) - } + if preimage.ShouldVerify(s.cl.Now(), time.Duration(period)*time.Second) { + toVerify = append(toVerify, preimage) } } - return err + return s.challenger.Challenge(ctx, blockHash, oracle, toVerify) } diff --git a/op-challenger/game/keccak/scheduler_test.go b/op-challenger/game/keccak/scheduler_test.go index f6743a68e2ca..067fc5d93065 100644 --- a/op-challenger/game/keccak/scheduler_test.go +++ b/op-challenger/game/keccak/scheduler_test.go @@ -2,22 +2,28 @@ package keccak import ( "context" + "errors" "math/big" "sync" "testing" "time" keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" - "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/clock" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" ) +var stubChallengePeriod = uint64(3600) + func TestScheduleNextCheck(t *testing.T) { ctx := context.Background() - logger := testlog.Logger(t, log.LvlInfo) + currentTimestamp := uint64(1240) + logger := testlog.Logger(t, log.LevelInfo) preimage1 := keccakTypes.LargePreimageMetaData{ // Incomplete so won't be verified LargePreimageIdent: keccakTypes.LargePreimageIdent{ Claimant: common.Address{0xab}, @@ -29,7 +35,7 @@ func TestScheduleNextCheck(t *testing.T) { Claimant: common.Address{0xab}, UUID: big.NewInt(222), }, - Timestamp: 1234, + Timestamp: currentTimestamp - 10, Countered: true, } preimage3 := keccakTypes.LargePreimageMetaData{ @@ -37,13 +43,14 @@ func TestScheduleNextCheck(t *testing.T) { Claimant: common.Address{0xdd}, UUID: big.NewInt(333), }, - Timestamp: 1234, + Timestamp: currentTimestamp - 10, } oracle := &stubOracle{ images: []keccakTypes.LargePreimageMetaData{preimage1, preimage2, preimage3}, } - verifier := &stubVerifier{} - scheduler := NewLargePreimageScheduler(logger, []keccakTypes.LargePreimageOracle{oracle}, verifier) + cl := clock.NewDeterministicClock(time.Unix(int64(currentTimestamp), 0)) + challenger := &stubChallenger{} + scheduler := NewLargePreimageScheduler(logger, cl, OracleSourceArray{oracle}, challenger) scheduler.Start(ctx) defer scheduler.Close() err := scheduler.Schedule(common.Hash{0xaa}, 3) @@ -52,8 +59,8 @@ func TestScheduleNextCheck(t *testing.T) { return oracle.GetPreimagesCount() == 1 }, 10*time.Second, 10*time.Millisecond) require.Eventually(t, func() bool { - verified := verifier.Verified() - t.Logf("Verified preimages: %v", verified) + verified := challenger.Checked() + t.Logf("Checked preimages: %v", verified) return len(verified) == 1 && verified[0] == preimage3 }, 10*time.Second, 10*time.Millisecond, "Did not verify preimage") } @@ -63,9 +70,14 @@ type stubOracle struct { addr common.Address getPreimagesCount int images []keccakTypes.LargePreimageMetaData + treeRoots map[keccakTypes.LargePreimageIdent]common.Hash +} + +func (s *stubOracle) ChallengePeriod(_ context.Context) (uint64, error) { + return stubChallengePeriod, nil } -func (s *stubOracle) GetInputDataBlocks(_ context.Context, _ batching.Block, _ keccakTypes.LargePreimageIdent) ([]uint64, error) { +func (s *stubOracle) GetInputDataBlocks(_ context.Context, _ rpcblock.Block, _ keccakTypes.LargePreimageIdent) ([]uint64, error) { panic("not supported") } @@ -90,22 +102,40 @@ func (s *stubOracle) GetPreimagesCount() int { return s.getPreimagesCount } -type stubVerifier struct { - m sync.Mutex - verified []keccakTypes.LargePreimageMetaData +func (s *stubOracle) ChallengeTx(_ keccakTypes.LargePreimageIdent, _ keccakTypes.Challenge) (txmgr.TxCandidate, error) { + panic("not supported") +} + +func (s *stubOracle) GetProposalTreeRoot(_ context.Context, _ rpcblock.Block, ident keccakTypes.LargePreimageIdent) (common.Hash, error) { + root, ok := s.treeRoots[ident] + if ok { + return root, nil + } + return common.Hash{}, errors.New("unknown tree root") +} + +type stubChallenger struct { + m sync.Mutex + checked []keccakTypes.LargePreimageMetaData } -func (s *stubVerifier) Verify(_ context.Context, _ common.Hash, _ keccakTypes.LargePreimageOracle, image keccakTypes.LargePreimageMetaData) error { +func (s *stubChallenger) Challenge(_ context.Context, _ common.Hash, _ Oracle, preimages []keccakTypes.LargePreimageMetaData) error { s.m.Lock() defer s.m.Unlock() - s.verified = append(s.verified, image) + s.checked = append(s.checked, preimages...) return nil } -func (s *stubVerifier) Verified() []keccakTypes.LargePreimageMetaData { +func (s *stubChallenger) Checked() []keccakTypes.LargePreimageMetaData { s.m.Lock() defer s.m.Unlock() - v := make([]keccakTypes.LargePreimageMetaData, len(s.verified)) - copy(v, s.verified) + v := make([]keccakTypes.LargePreimageMetaData, len(s.checked)) + copy(v, s.checked) return v } + +type OracleSourceArray []keccakTypes.LargePreimageOracle + +func (o OracleSourceArray) Oracles() []keccakTypes.LargePreimageOracle { + return o +} diff --git a/op-challenger/game/keccak/types/types.go b/op-challenger/game/keccak/types/types.go index e0007975e4e3..9c423a7a10ca 100644 --- a/op-challenger/game/keccak/types/types.go +++ b/op-challenger/game/keccak/types/types.go @@ -3,9 +3,14 @@ package types import ( "context" "math/big" + "time" - "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/merkle" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/crypto" ) // BlockSize is the size in bytes required for leaf data. @@ -16,11 +21,21 @@ type Leaf struct { // Input is the data absorbed for the block, exactly 136 bytes Input [BlockSize]byte // Index of the block in the absorption process - Index *big.Int + Index uint64 // StateCommitment is the hash of the internal state after absorbing the input. StateCommitment common.Hash } +// Hash returns the hash of the leaf data. That is the +// bytewise concatenation of the input, index, and state commitment. +func (l Leaf) Hash() common.Hash { + concatted := make([]byte, 0, 136+32+32) + concatted = append(concatted, l.Input[:]...) + concatted = append(concatted, math.U256Bytes(new(big.Int).SetUint64(l.Index))...) + concatted = append(concatted, l.StateCommitment.Bytes()...) + return crypto.Keccak256Hash(concatted) +} + // InputData is a contiguous segment of preimage data. type InputData struct { // Input is the preimage data. @@ -51,15 +66,42 @@ type LargePreimageMetaData struct { Countered bool } -// ShouldVerify returns true if the preimage upload is complete and has not yet been countered. -// Note that the challenge period for the preimage may have expired but the image not yet been finalized. -func (m LargePreimageMetaData) ShouldVerify() bool { - return m.Timestamp > 0 && !m.Countered +// ShouldVerify returns true if the preimage upload is complete, has not yet been countered, and the +// challenge period has not yet elapsed. +func (m LargePreimageMetaData) ShouldVerify(now time.Time, ignoreAfter time.Duration) bool { + return m.Timestamp > 0 && !m.Countered && m.Timestamp+uint64(ignoreAfter.Seconds()) > uint64(now.Unix()) +} + +type StateSnapshot [25]uint64 + +// Pack packs the state in to the solidity ABI encoding required for the state matrix +func (s StateSnapshot) Pack() []byte { + buf := make([]byte, 0, len(s)*32) + for _, v := range s { + buf = append(buf, math.U256Bytes(new(big.Int).SetUint64(v))...) + } + return buf +} + +type Challenge struct { + // StateMatrix is the packed state matrix preimage of the StateCommitment in Prestate + StateMatrix StateSnapshot + + // Prestate is the valid leaf immediately prior to the first invalid leaf + Prestate Leaf + PrestateProof merkle.Proof + + // Poststate is the first invalid leaf in the preimage. The challenge claims that this leaf is invalid. + Poststate Leaf + PoststateProof merkle.Proof } type LargePreimageOracle interface { Addr() common.Address GetActivePreimages(ctx context.Context, blockHash common.Hash) ([]LargePreimageMetaData, error) - GetInputDataBlocks(ctx context.Context, block batching.Block, ident LargePreimageIdent) ([]uint64, error) + GetInputDataBlocks(ctx context.Context, block rpcblock.Block, ident LargePreimageIdent) ([]uint64, error) + GetProposalTreeRoot(ctx context.Context, block rpcblock.Block, ident LargePreimageIdent) (common.Hash, error) DecodeInputData(data []byte) (*big.Int, InputData, error) + ChallengeTx(ident LargePreimageIdent, challenge Challenge) (txmgr.TxCandidate, error) + ChallengePeriod(ctx context.Context) (uint64, error) } diff --git a/op-challenger/game/keccak/types/types_test.go b/op-challenger/game/keccak/types/types_test.go new file mode 100644 index 000000000000..b8a34021c2f7 --- /dev/null +++ b/op-challenger/game/keccak/types/types_test.go @@ -0,0 +1,64 @@ +package types + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestShouldVerify(t *testing.T) { + tests := []struct { + name string + timestamp uint64 + countered bool + now int64 + expected bool + }{ + { + name: "IgnoreNotFinalizedAndNotCountered", + timestamp: 0, + countered: false, + now: 100, + expected: false, + }, + { + name: "VerifyFinalizedAndNotCountered", + timestamp: 50, + countered: false, + now: 100, + expected: true, + }, + { + name: "IgnoreFinalizedAndCountered", + timestamp: 50, + countered: true, + now: 100, + expected: false, + }, + { + name: "IgnoreNotFinalizedAndCountered", + timestamp: 0, + countered: true, + now: 100, + expected: false, + }, + { + name: "IgnoreFinalizedBeforeTimeWindowAndNotCountered", + timestamp: 50, + countered: false, + now: 50 + int64((2 * time.Hour).Seconds()), + expected: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + metadata := LargePreimageMetaData{ + Timestamp: test.timestamp, + Countered: test.countered, + } + require.Equal(t, test.expected, metadata.ShouldVerify(time.Unix(test.now, 0), 1*time.Hour)) + }) + } +} diff --git a/op-challenger/game/keccak/verifier.go b/op-challenger/game/keccak/verifier.go index 9f7600ee923e..026462b127e0 100644 --- a/op-challenger/game/keccak/verifier.go +++ b/op-challenger/game/keccak/verifier.go @@ -1,15 +1,28 @@ package keccak import ( + "bytes" "context" + "errors" "fmt" + "io" "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/fetcher" + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/matrix" keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" + lru "github.com/hashicorp/golang-lru/v2" ) +const validPreimageCacheSize = 500 + +type VerifierPreimageOracle interface { + fetcher.Oracle + GetProposalTreeRoot(ctx context.Context, block rpcblock.Block, ident keccakTypes.LargePreimageIdent) (common.Hash, error) +} + type Fetcher interface { FetchInputs(ctx context.Context, blockHash common.Hash, oracle fetcher.Oracle, ident keccakTypes.LargePreimageIdent) ([]keccakTypes.InputData, error) } @@ -17,19 +30,52 @@ type Fetcher interface { type PreimageVerifier struct { log log.Logger fetcher Fetcher + + // knownValid caches the merkle tree roots that have been confirmed as valid. + // Invalid roots are not cached as those preimages will be ignored once the challenge is processed. + knownValid *lru.Cache[common.Hash, bool] } func NewPreimageVerifier(logger log.Logger, fetcher Fetcher) *PreimageVerifier { + // Can't error because size is hard coded + cache, _ := lru.New[common.Hash, bool](validPreimageCacheSize) return &PreimageVerifier{ - log: logger, - fetcher: fetcher, + log: logger, + fetcher: fetcher, + knownValid: cache, } } -func (v *PreimageVerifier) Verify(ctx context.Context, blockHash common.Hash, oracle keccakTypes.LargePreimageOracle, preimage keccakTypes.LargePreimageMetaData) error { - _, err := v.fetcher.FetchInputs(ctx, blockHash, oracle, preimage.LargePreimageIdent) +func (v *PreimageVerifier) CreateChallenge(ctx context.Context, blockHash common.Hash, oracle VerifierPreimageOracle, preimage keccakTypes.LargePreimageMetaData) (keccakTypes.Challenge, error) { + root, err := oracle.GetProposalTreeRoot(ctx, rpcblock.ByHash(blockHash), preimage.LargePreimageIdent) if err != nil { - return fmt.Errorf("failed to fetch leaves: %w", err) + return keccakTypes.Challenge{}, fmt.Errorf("failed to get proposal merkle root: %w", err) + } + if valid, ok := v.knownValid.Get(root); ok && valid { + // We've already determined that the keccak transition is valid. + // Note that the merkle tree may have been validated by a different proposal but since the tree root + // commits to all the input data and the resulting keccak state matrix, any other proposal with the same + // root must also have the same inputs and correctly applied keccak. + // It is possible that this proposal can't be squeezed because the claimed data length doesn't match the + // actual length but the contracts enforce that and it can't be challenged on that basis. + return keccakTypes.Challenge{}, matrix.ErrValid + } + inputs, err := v.fetcher.FetchInputs(ctx, blockHash, oracle, preimage.LargePreimageIdent) + if err != nil { + return keccakTypes.Challenge{}, fmt.Errorf("failed to fetch leaves: %w", err) + } + readers := make([]io.Reader, 0, len(inputs)) + var commitments []common.Hash + for _, input := range inputs { + readers = append(readers, bytes.NewReader(input.Input)) + commitments = append(commitments, input.Commitments...) + } + challenge, err := matrix.Challenge(io.MultiReader(readers...), commitments) + if errors.Is(err, matrix.ErrValid) { + v.knownValid.Add(root, true) + return keccakTypes.Challenge{}, err + } else if err != nil { + return keccakTypes.Challenge{}, fmt.Errorf("failed to create challenge: %w", err) } - return nil + return challenge, nil } diff --git a/op-challenger/game/keccak/verifier_test.go b/op-challenger/game/keccak/verifier_test.go new file mode 100644 index 000000000000..fdf7bf062df7 --- /dev/null +++ b/op-challenger/game/keccak/verifier_test.go @@ -0,0 +1,164 @@ +package keccak + +import ( + "bytes" + "context" + "errors" + "io" + "math/big" + "math/rand" + "sync/atomic" + "testing" + + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/fetcher" + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/matrix" + keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/testutils" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func TestVerify(t *testing.T) { + logger := testlog.Logger(t, log.LevelInfo) + tests := []struct { + name string + inputs func() []keccakTypes.InputData + expectedErr error + }{ + { + name: "Valid-SingleInput", + inputs: func() []keccakTypes.InputData { return validInputs(t, 1) }, + expectedErr: matrix.ErrValid, + }, + { + name: "Valid-MultipleInputs", + inputs: func() []keccakTypes.InputData { return validInputs(t, 3) }, + expectedErr: matrix.ErrValid, + }, + { + name: "Invalid-FirstCommitment", + inputs: func() []keccakTypes.InputData { + inputs := validInputs(t, 1) + inputs[0].Commitments[0] = common.Hash{0xaa} + return inputs + }, + expectedErr: nil, + }, + { + name: "Invalid-MiddleCommitment", + inputs: func() []keccakTypes.InputData { + inputs := validInputs(t, 1) + inputs[0].Commitments[1] = common.Hash{0xaa} + return inputs + }, + expectedErr: nil, + }, + { + name: "Invalid-LastCommitment", + inputs: func() []keccakTypes.InputData { + inputs := validInputs(t, 3) + inputs[2].Commitments[len(inputs[2].Commitments)-1] = common.Hash{0xaa} + return inputs + }, + expectedErr: nil, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + fetcher := &stubFetcher{ + inputs: test.inputs(), + } + verifier := NewPreimageVerifier(logger, fetcher) + preimage := keccakTypes.LargePreimageMetaData{} + oracle := &stubOracle{ + treeRoots: map[keccakTypes.LargePreimageIdent]common.Hash{ + preimage.LargePreimageIdent: {0xde}, + }, + } + challenge, err := verifier.CreateChallenge(context.Background(), common.Hash{0xff}, oracle, preimage) + require.ErrorIs(t, err, test.expectedErr) + if err == nil { + // Leave checking the validity of the challenge to the StateMatrix tests + // Just confirm that we got a non-zero challenge + require.NotEqual(t, keccakTypes.Challenge{}, challenge) + } else { + require.Equal(t, keccakTypes.Challenge{}, challenge) + } + }) + } +} + +func TestCacheValidRoots(t *testing.T) { + logger := testlog.Logger(t, log.LvlInfo) + fetcher := &stubFetcher{ + inputs: validInputs(t, 1), + } + verifier := NewPreimageVerifier(logger, fetcher) + preimage1 := keccakTypes.LargePreimageMetaData{ + LargePreimageIdent: keccakTypes.LargePreimageIdent{ + Claimant: common.Address{0x12}, + UUID: big.NewInt(1), + }, + } + preimage2 := keccakTypes.LargePreimageMetaData{ + LargePreimageIdent: keccakTypes.LargePreimageIdent{ + Claimant: common.Address{0x23}, + UUID: big.NewInt(2), + }, + } + oracle := &stubOracle{ + treeRoots: map[keccakTypes.LargePreimageIdent]common.Hash{ + preimage1.LargePreimageIdent: {0xde}, + preimage2.LargePreimageIdent: {0xde}, + }, + } + challenge, err := verifier.CreateChallenge(context.Background(), common.Hash{0xff}, oracle, preimage1) + require.ErrorIs(t, err, matrix.ErrValid) + require.Equal(t, keccakTypes.Challenge{}, challenge, "Should be valid") + require.EqualValues(t, 1, fetcher.fetchCount.Load(), "Should fetch data and validate") + + // Should cache the validity + challenge, err = verifier.CreateChallenge(context.Background(), common.Hash{0xee}, oracle, preimage1) + require.ErrorIs(t, err, matrix.ErrValid) + require.Equal(t, keccakTypes.Challenge{}, challenge, "Should be valid") + require.EqualValues(t, 1, fetcher.fetchCount.Load(), "Should use cached validity") + + // Should cache the validity across different challenges + challenge, err = verifier.CreateChallenge(context.Background(), common.Hash{0xee}, oracle, preimage2) + require.ErrorIs(t, err, matrix.ErrValid) + require.Equal(t, keccakTypes.Challenge{}, challenge, "Should be valid") + require.EqualValues(t, 1, fetcher.fetchCount.Load(), "Should use cached validity") +} + +func validInputs(t *testing.T, inputCount int) []keccakTypes.InputData { + chunkSize := 2 * keccakTypes.BlockSize + data := testutils.RandomData(rand.New(rand.NewSource(4444)), inputCount*chunkSize) + var calls []keccakTypes.InputData + in := bytes.NewReader(data) + s := matrix.NewStateMatrix() + for { + call, err := s.AbsorbUpTo(in, chunkSize) + if !errors.Is(err, io.EOF) { + require.NoError(t, err) + } + calls = append(calls, call) + if errors.Is(err, io.EOF) { + break + } + } + return calls +} + +type stubFetcher struct { + inputs []keccakTypes.InputData + fetchCount atomic.Int64 +} + +func (s *stubFetcher) FetchInputs(_ context.Context, _ common.Hash, _ fetcher.Oracle, _ keccakTypes.LargePreimageIdent) ([]keccakTypes.InputData, error) { + s.fetchCount.Add(1) + return s.inputs, nil +} diff --git a/op-challenger/game/loader/game_loader.go b/op-challenger/game/loader/game_loader.go deleted file mode 100644 index f0daddc213ad..000000000000 --- a/op-challenger/game/loader/game_loader.go +++ /dev/null @@ -1,49 +0,0 @@ -package loader - -import ( - "context" - "fmt" - - "github.com/ethereum-optimism/optimism/op-challenger/game/types" - "github.com/ethereum/go-ethereum/common" -) - -// MinimalDisputeGameFactoryCaller is a minimal interface around [bindings.DisputeGameFactoryCaller]. -// This needs to be updated if the [bindings.DisputeGameFactoryCaller] interface changes. -type MinimalDisputeGameFactoryCaller interface { - GetGameCount(ctx context.Context, blockHash common.Hash) (uint64, error) - GetGame(ctx context.Context, idx uint64, blockHash common.Hash) (types.GameMetadata, error) -} - -type GameLoader struct { - caller MinimalDisputeGameFactoryCaller -} - -// NewGameLoader creates a new services that can be used to fetch on chain dispute games. -func NewGameLoader(caller MinimalDisputeGameFactoryCaller) *GameLoader { - return &GameLoader{ - caller: caller, - } -} - -// FetchAllGamesAtBlock fetches all dispute games from the factory at a given block number. -func (l *GameLoader) FetchAllGamesAtBlock(ctx context.Context, earliestTimestamp uint64, blockHash common.Hash) ([]types.GameMetadata, error) { - gameCount, err := l.caller.GetGameCount(ctx, blockHash) - if err != nil { - return nil, fmt.Errorf("failed to fetch game count: %w", err) - } - - games := make([]types.GameMetadata, 0, gameCount) - for i := gameCount; i > 0; i-- { - game, err := l.caller.GetGame(ctx, i-1, blockHash) - if err != nil { - return nil, fmt.Errorf("failed to fetch game at index %d: %w", i-1, err) - } - if game.Timestamp < earliestTimestamp { - break - } - games = append(games, game) - } - - return games, nil -} diff --git a/op-challenger/game/loader/game_loader_test.go b/op-challenger/game/loader/game_loader_test.go deleted file mode 100644 index b460d0f83fb7..000000000000 --- a/op-challenger/game/loader/game_loader_test.go +++ /dev/null @@ -1,159 +0,0 @@ -package loader - -import ( - "context" - "errors" - "math/big" - "testing" - - "github.com/ethereum-optimism/optimism/op-challenger/game/types" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" -) - -var ( - gameCountErr = errors.New("game count error") - gameIndexErr = errors.New("game index error") -) - -// TestGameLoader_FetchAllGames tests that the game loader correctly fetches all games. -func TestGameLoader_FetchAllGames(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - caller *mockMinimalDisputeGameFactoryCaller - earliest uint64 - blockHash common.Hash - expectedErr error - expectedLen int - }{ - { - name: "success", - caller: newMockMinimalDisputeGameFactoryCaller(10, false, false), - blockHash: common.Hash{0x01}, - expectedLen: 10, - }, - { - name: "expired game ignored", - caller: newMockMinimalDisputeGameFactoryCaller(10, false, false), - earliest: 500, - blockHash: common.Hash{0x01}, - expectedLen: 5, - }, - { - name: "game count error", - caller: newMockMinimalDisputeGameFactoryCaller(10, true, false), - blockHash: common.Hash{0x01}, - expectedErr: gameCountErr, - }, - { - name: "game index error", - caller: newMockMinimalDisputeGameFactoryCaller(10, false, true), - blockHash: common.Hash{0x01}, - expectedErr: gameIndexErr, - }, - { - name: "no games", - caller: newMockMinimalDisputeGameFactoryCaller(0, false, false), - blockHash: common.Hash{0x01}, - }, - } - - for _, test := range tests { - test := test - - t.Run(test.name, func(t *testing.T) { - t.Parallel() - - loader := NewGameLoader(test.caller) - games, err := loader.FetchAllGamesAtBlock(context.Background(), test.earliest, test.blockHash) - require.ErrorIs(t, err, test.expectedErr) - require.Len(t, games, test.expectedLen) - expectedGames := test.caller.games - expectedGames = expectedGames[len(expectedGames)-test.expectedLen:] - if test.expectedErr != nil { - expectedGames = make([]types.GameMetadata, 0) - } - require.ElementsMatch(t, expectedGames, translateGames(games)) - }) - } -} - -func generateMockGames(count uint64) []types.GameMetadata { - games := make([]types.GameMetadata, count) - - for i := uint64(0); i < count; i++ { - games[i] = types.GameMetadata{ - Proxy: common.BigToAddress(big.NewInt(int64(i))), - Timestamp: i * 100, - } - } - - return games -} - -func translateGames(games []types.GameMetadata) []types.GameMetadata { - translated := make([]types.GameMetadata, len(games)) - - for i, game := range games { - translated[i] = translateFaultDisputeGame(game) - } - - return translated -} - -func translateFaultDisputeGame(game types.GameMetadata) types.GameMetadata { - return types.GameMetadata{ - Proxy: game.Proxy, - Timestamp: game.Timestamp, - } -} - -func generateMockGameErrors(count uint64, injectErrors bool) []bool { - errors := make([]bool, count) - - if injectErrors { - for i := uint64(0); i < count; i++ { - errors[i] = true - } - } - - return errors -} - -type mockMinimalDisputeGameFactoryCaller struct { - gameCountErr bool - indexErrors []bool - gameCount uint64 - games []types.GameMetadata -} - -func newMockMinimalDisputeGameFactoryCaller(count uint64, gameCountErr bool, indexErrors bool) *mockMinimalDisputeGameFactoryCaller { - return &mockMinimalDisputeGameFactoryCaller{ - indexErrors: generateMockGameErrors(count, indexErrors), - gameCountErr: gameCountErr, - gameCount: count, - games: generateMockGames(count), - } -} - -func (m *mockMinimalDisputeGameFactoryCaller) GetGameCount(_ context.Context, _ common.Hash) (uint64, error) { - if m.gameCountErr { - return 0, gameCountErr - } - - return m.gameCount, nil -} - -func (m *mockMinimalDisputeGameFactoryCaller) GetGame(_ context.Context, index uint64, _ common.Hash) (types.GameMetadata, error) { - if m.indexErrors[index] { - return struct { - GameType uint8 - Timestamp uint64 - Proxy common.Address - }{}, gameIndexErr - } - - return m.games[index], nil -} diff --git a/op-challenger/game/monitor.go b/op-challenger/game/monitor.go index 916063910573..fe263a661692 100644 --- a/op-challenger/game/monitor.go +++ b/op-challenger/game/monitor.go @@ -23,7 +23,12 @@ type blockNumberFetcher func(ctx context.Context) (uint64, error) // gameSource loads information about the games available to play type gameSource interface { - FetchAllGamesAtBlock(ctx context.Context, earliest uint64, blockHash common.Hash) ([]types.GameMetadata, error) + GetGamesAtOrAfter(ctx context.Context, blockHash common.Hash, earliestTimestamp uint64) ([]types.GameMetadata, error) +} + +type RWClock interface { + SetTime(uint64) + Now() time.Time } type gameScheduler interface { @@ -34,13 +39,18 @@ type preimageScheduler interface { Schedule(blockHash common.Hash, blockNumber uint64) error } +type claimer interface { + Schedule(blockNumber uint64, games []types.GameMetadata) error +} + type gameMonitor struct { logger log.Logger - clock clock.Clock + clock RWClock source gameSource scheduler gameScheduler preimages preimageScheduler gameWindow time.Duration + claimer claimer fetchBlockNumber blockNumberFetcher allowedGames []common.Address l1HeadsSub ethereum.Subscription @@ -62,11 +72,12 @@ func (s *headSource) SubscribeNewHead(ctx context.Context, ch chan<- *ethTypes.H func newGameMonitor( logger log.Logger, - cl clock.Clock, + cl RWClock, source gameSource, scheduler gameScheduler, preimages preimageScheduler, gameWindow time.Duration, + claimer claimer, fetchBlockNumber blockNumberFetcher, allowedGames []common.Address, l1Source MinimalSubscriber, @@ -78,6 +89,7 @@ func newGameMonitor( preimages: preimages, source: source, gameWindow: gameWindow, + claimer: claimer, fetchBlockNumber: fetchBlockNumber, allowedGames: allowedGames, l1Source: &headSource{inner: l1Source}, @@ -96,20 +108,9 @@ func (m *gameMonitor) allowedGame(game common.Address) bool { return false } -func (m *gameMonitor) minGameTimestamp() uint64 { - if m.gameWindow.Seconds() == 0 { - return 0 - } - // time: "To compute t-d for a duration d, use t.Add(-d)." - // https://pkg.go.dev/time#Time.Sub - if m.clock.Now().Unix() > int64(m.gameWindow.Seconds()) { - return uint64(m.clock.Now().Add(-m.gameWindow).Unix()) - } - return 0 -} - func (m *gameMonitor) progressGames(ctx context.Context, blockHash common.Hash, blockNumber uint64) error { - games, err := m.source.FetchAllGamesAtBlock(ctx, m.minGameTimestamp(), blockHash) + minGameTimestamp := clock.MinCheckedTimestamp(m.clock, m.gameWindow) + games, err := m.source.GetGamesAtOrAfter(ctx, blockHash, minGameTimestamp) if err != nil { return fmt.Errorf("failed to load games: %w", err) } @@ -121,6 +122,9 @@ func (m *gameMonitor) progressGames(ctx context.Context, blockHash common.Hash, } gamesToPlay = append(gamesToPlay, game) } + if err := m.claimer.Schedule(blockNumber, gamesToPlay); err != nil { + return fmt.Errorf("failed to schedule bond claims: %w", err) + } if err := m.scheduler.Schedule(gamesToPlay, blockNumber); errors.Is(err, scheduler.ErrBusy) { m.logger.Info("Scheduler still busy with previous update") } else if err != nil { @@ -130,6 +134,7 @@ func (m *gameMonitor) progressGames(ctx context.Context, blockHash common.Hash, } func (m *gameMonitor) onNewL1Head(ctx context.Context, sig eth.L1BlockRef) { + m.clock.SetTime(sig.Time) if err := m.progressGames(ctx, sig.Hash, sig.Number); err != nil { m.logger.Error("Failed to progress games", "err", err) } diff --git a/op-challenger/game/monitor_test.go b/op-challenger/game/monitor_test.go index ba42a58a6c42..e4fe24e5b799 100644 --- a/op-challenger/game/monitor_test.go +++ b/op-challenger/game/monitor_test.go @@ -20,39 +20,13 @@ import ( "github.com/ethereum-optimism/optimism/op-service/clock" ) -func TestMonitorMinGameTimestamp(t *testing.T) { - t.Parallel() - - t.Run("zero game window returns zero", func(t *testing.T) { - monitor, _, _, _, _ := setupMonitorTest(t, []common.Address{}) - monitor.gameWindow = time.Duration(0) - require.Equal(t, monitor.minGameTimestamp(), uint64(0)) - }) - - t.Run("non-zero game window with zero clock", func(t *testing.T) { - monitor, _, _, _, _ := setupMonitorTest(t, []common.Address{}) - monitor.gameWindow = time.Minute - monitor.clock = clock.NewDeterministicClock(time.Unix(0, 0)) - require.Equal(t, monitor.minGameTimestamp(), uint64(0)) - }) - - t.Run("minimum computed correctly", func(t *testing.T) { - monitor, _, _, _, _ := setupMonitorTest(t, []common.Address{}) - monitor.gameWindow = time.Minute - frozen := time.Unix(int64(time.Hour.Seconds()), 0) - monitor.clock = clock.NewDeterministicClock(frozen) - expected := uint64(frozen.Add(-time.Minute).Unix()) - require.Equal(t, monitor.minGameTimestamp(), expected) - }) -} - // TestMonitorGames tests that the monitor can handle a new head event // and resubscribe to new heads if the subscription errors. func TestMonitorGames(t *testing.T) { t.Run("Schedules games", func(t *testing.T) { addr1 := common.Address{0xaa} addr2 := common.Address{0xbb} - monitor, source, sched, mockHeadSource, preimages := setupMonitorTest(t, []common.Address{}) + monitor, source, sched, mockHeadSource, preimages, _ := setupMonitorTest(t, []common.Address{}) source.games = []types.GameMetadata{newFDG(addr1, 9999), newFDG(addr2, 9999)} ctx, cancel := context.WithCancel(context.Background()) @@ -97,7 +71,7 @@ func TestMonitorGames(t *testing.T) { t.Run("Resubscribes on error", func(t *testing.T) { addr1 := common.Address{0xaa} addr2 := common.Address{0xbb} - monitor, source, sched, mockHeadSource, preimages := setupMonitorTest(t, []common.Address{}) + monitor, source, sched, mockHeadSource, preimages, _ := setupMonitorTest(t, []common.Address{}) source.games = []types.GameMetadata{newFDG(addr1, 9999), newFDG(addr2, 9999)} ctx, cancel := context.WithCancel(context.Background()) @@ -144,7 +118,7 @@ func TestMonitorGames(t *testing.T) { } func TestMonitorCreateAndProgressGameAgents(t *testing.T) { - monitor, source, sched, _, _ := setupMonitorTest(t, []common.Address{}) + monitor, source, sched, _, _, _ := setupMonitorTest(t, []common.Address{}) addr1 := common.Address{0xaa} addr2 := common.Address{0xbb} @@ -159,13 +133,14 @@ func TestMonitorCreateAndProgressGameAgents(t *testing.T) { func TestMonitorOnlyScheduleSpecifiedGame(t *testing.T) { addr1 := common.Address{0xaa} addr2 := common.Address{0xbb} - monitor, source, sched, _, _ := setupMonitorTest(t, []common.Address{addr2}) + monitor, source, sched, _, _, stubClaimer := setupMonitorTest(t, []common.Address{addr2}) source.games = []types.GameMetadata{newFDG(addr1, 9999), newFDG(addr2, 9999)} require.NoError(t, monitor.progressGames(context.Background(), common.Hash{0x01}, 0)) require.Len(t, sched.Scheduled(), 1) require.Equal(t, []common.Address{addr2}, sched.Scheduled()[0]) + require.Equal(t, 1, stubClaimer.scheduledGames) } func newFDG(proxy common.Address, timestamp uint64) types.GameMetadata { @@ -178,8 +153,8 @@ func newFDG(proxy common.Address, timestamp uint64) types.GameMetadata { func setupMonitorTest( t *testing.T, allowedGames []common.Address, -) (*gameMonitor, *stubGameSource, *stubScheduler, *mockNewHeadSource, *stubPreimageScheduler) { - logger := testlog.Logger(t, log.LvlDebug) +) (*gameMonitor, *stubGameSource, *stubScheduler, *mockNewHeadSource, *stubPreimageScheduler, *mockScheduler) { + logger := testlog.Logger(t, log.LevelDebug) source := &stubGameSource{} i := uint64(1) fetchBlockNum := func(ctx context.Context) (uint64, error) { @@ -189,18 +164,20 @@ func setupMonitorTest( sched := &stubScheduler{} preimages := &stubPreimageScheduler{} mockHeadSource := &mockNewHeadSource{} + stubClaimer := &mockScheduler{} monitor := newGameMonitor( logger, - clock.SystemClock, + clock.NewSimpleClock(), source, sched, preimages, time.Duration(0), + stubClaimer, fetchBlockNum, allowedGames, mockHeadSource, ) - return monitor, source, sched, mockHeadSource, preimages + return monitor, source, sched, mockHeadSource, preimages, stubClaimer } type mockNewHeadSource struct { @@ -242,6 +219,16 @@ func (m *mockNewHeadSource) EthSubscribe( return m.sub, nil } +type mockScheduler struct { + scheduleErr error + scheduledGames int +} + +func (m *mockScheduler) Schedule(_ uint64, games []types.GameMetadata) error { + m.scheduledGames += len(games) + return m.scheduleErr +} + type mockSubscription struct { errChan chan error headers chan<- *ethtypes.Header @@ -254,14 +241,18 @@ func (m *mockSubscription) Err() <-chan error { } type stubGameSource struct { - games []types.GameMetadata + fetchErr error + games []types.GameMetadata } -func (s *stubGameSource) FetchAllGamesAtBlock( +func (s *stubGameSource) GetGamesAtOrAfter( _ context.Context, - _ uint64, _ common.Hash, + _ uint64, ) ([]types.GameMetadata, error) { + if s.fetchErr != nil { + return nil, s.fetchErr + } return s.games, nil } diff --git a/op-challenger/game/registry/oracles.go b/op-challenger/game/registry/oracles.go new file mode 100644 index 000000000000..9ee107990280 --- /dev/null +++ b/op-challenger/game/registry/oracles.go @@ -0,0 +1,32 @@ +package registry + +import ( + "sync" + + keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" + "github.com/ethereum/go-ethereum/common" + "golang.org/x/exp/maps" +) + +type OracleRegistry struct { + l sync.Mutex + oracles map[common.Address]keccakTypes.LargePreimageOracle +} + +func NewOracleRegistry() *OracleRegistry { + return &OracleRegistry{ + oracles: make(map[common.Address]keccakTypes.LargePreimageOracle), + } +} + +func (r *OracleRegistry) RegisterOracle(oracle keccakTypes.LargePreimageOracle) { + r.l.Lock() + defer r.l.Unlock() + r.oracles[oracle.Addr()] = oracle +} + +func (r *OracleRegistry) Oracles() []keccakTypes.LargePreimageOracle { + r.l.Lock() + defer r.l.Unlock() + return maps.Values(r.oracles) +} diff --git a/op-challenger/game/registry/oracles_test.go b/op-challenger/game/registry/oracles_test.go new file mode 100644 index 000000000000..8e14fa4f5137 --- /dev/null +++ b/op-challenger/game/registry/oracles_test.go @@ -0,0 +1,56 @@ +package registry + +import ( + "context" + "math/big" + "testing" + + keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestDeduplicateOracles(t *testing.T) { + registry := NewOracleRegistry() + oracleA := stubPreimageOracle{0xaa} + oracleB := stubPreimageOracle{0xbb} + registry.RegisterOracle(oracleA) + registry.RegisterOracle(oracleB) + registry.RegisterOracle(oracleB) + oracles := registry.Oracles() + require.Len(t, oracles, 2) + require.Contains(t, oracles, oracleA) + require.Contains(t, oracles, oracleB) +} + +type stubPreimageOracle common.Address + +func (s stubPreimageOracle) ChallengePeriod(_ context.Context) (uint64, error) { + panic("not supported") +} + +func (s stubPreimageOracle) GetProposalTreeRoot(_ context.Context, _ rpcblock.Block, _ keccakTypes.LargePreimageIdent) (common.Hash, error) { + panic("not supported") +} + +func (s stubPreimageOracle) ChallengeTx(_ keccakTypes.LargePreimageIdent, _ keccakTypes.Challenge) (txmgr.TxCandidate, error) { + panic("not supported") +} + +func (s stubPreimageOracle) GetInputDataBlocks(_ context.Context, _ rpcblock.Block, _ keccakTypes.LargePreimageIdent) ([]uint64, error) { + panic("not supported") +} + +func (s stubPreimageOracle) DecodeInputData(_ []byte) (*big.Int, keccakTypes.InputData, error) { + panic("not supported") +} + +func (s stubPreimageOracle) Addr() common.Address { + return common.Address(s) +} + +func (s stubPreimageOracle) GetActivePreimages(_ context.Context, _ common.Hash) ([]keccakTypes.LargePreimageMetaData, error) { + return nil, nil +} diff --git a/op-challenger/game/registry/registry.go b/op-challenger/game/registry/registry.go index 6198f70e860c..d6713a918ddc 100644 --- a/op-challenger/game/registry/registry.go +++ b/op-challenger/game/registry/registry.go @@ -4,41 +4,39 @@ import ( "errors" "fmt" - keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/claims" "github.com/ethereum-optimism/optimism/op-challenger/game/scheduler" "github.com/ethereum-optimism/optimism/op-challenger/game/types" - "github.com/ethereum/go-ethereum/common" - "golang.org/x/exp/maps" ) -var ( - ErrUnsupportedGameType = errors.New("unsupported game type") -) +var ErrUnsupportedGameType = errors.New("unsupported game type") type GameTypeRegistry struct { - types map[uint8]scheduler.PlayerCreator - oracles map[common.Address]keccakTypes.LargePreimageOracle + types map[uint32]scheduler.PlayerCreator + bondCreators map[uint32]claims.BondContractCreator } func NewGameTypeRegistry() *GameTypeRegistry { return &GameTypeRegistry{ - types: make(map[uint8]scheduler.PlayerCreator), - oracles: make(map[common.Address]keccakTypes.LargePreimageOracle), + types: make(map[uint32]scheduler.PlayerCreator), + bondCreators: make(map[uint32]claims.BondContractCreator), } } // RegisterGameType registers a scheduler.PlayerCreator to use for a specific game type. // Panics if the same game type is registered multiple times, since this indicates a significant programmer error. -func (r *GameTypeRegistry) RegisterGameType(gameType uint8, creator scheduler.PlayerCreator, oracle keccakTypes.LargePreimageOracle) { +func (r *GameTypeRegistry) RegisterGameType(gameType uint32, creator scheduler.PlayerCreator) { if _, ok := r.types[gameType]; ok { panic(fmt.Errorf("duplicate creator registered for game type: %v", gameType)) } r.types[gameType] = creator - if oracle != nil { - // It's ok to have two game types use the same oracle contract. - // We add them to a map deliberately to deduplicate them. - r.oracles[oracle.Addr()] = oracle +} + +func (r *GameTypeRegistry) RegisterBondContract(gameType uint32, creator claims.BondContractCreator) { + if _, ok := r.bondCreators[gameType]; ok { + panic(fmt.Errorf("duplicate bond contract registered for game type: %v", gameType)) } + r.bondCreators[gameType] = creator } // CreatePlayer creates a new game player for the given game, using the specified directory for persisting data. @@ -50,6 +48,10 @@ func (r *GameTypeRegistry) CreatePlayer(game types.GameMetadata, dir string) (sc return creator(game, dir) } -func (r *GameTypeRegistry) Oracles() []keccakTypes.LargePreimageOracle { - return maps.Values(r.oracles) +func (r *GameTypeRegistry) CreateBondContract(game types.GameMetadata) (claims.BondContract, error) { + creator, ok := r.bondCreators[game.GameType] + if !ok { + return nil, fmt.Errorf("%w: %v", ErrUnsupportedGameType, game.GameType) + } + return creator(game) } diff --git a/op-challenger/game/registry/registry_test.go b/op-challenger/game/registry/registry_test.go index dc06baac2e46..0c6fbd9870c0 100644 --- a/op-challenger/game/registry/registry_test.go +++ b/op-challenger/game/registry/registry_test.go @@ -5,11 +5,11 @@ import ( "math/big" "testing" - keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/claims" "github.com/ethereum-optimism/optimism/op-challenger/game/scheduler" "github.com/ethereum-optimism/optimism/op-challenger/game/scheduler/test" "github.com/ethereum-optimism/optimism/op-challenger/game/types" - "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ) @@ -27,7 +27,7 @@ func TestKnownGameType(t *testing.T) { creator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) { return expectedPlayer, nil } - registry.RegisterGameType(0, creator, nil) + registry.RegisterGameType(0, creator) player, err := registry.CreatePlayer(types.GameMetadata{GameType: 0}, "") require.NoError(t, err) require.Same(t, expectedPlayer, player) @@ -38,42 +38,47 @@ func TestPanicsOnDuplicateGameType(t *testing.T) { creator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) { return nil, nil } - registry.RegisterGameType(0, creator, nil) + registry.RegisterGameType(0, creator) require.Panics(t, func() { - registry.RegisterGameType(0, creator, nil) + registry.RegisterGameType(0, creator) }) } -func TestDeduplicateOracles(t *testing.T) { - registry := NewGameTypeRegistry() - creator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) { - return nil, nil - } - oracleA := stubPreimageOracle{0xaa} - oracleB := stubPreimageOracle{0xbb} - registry.RegisterGameType(0, creator, oracleA) - registry.RegisterGameType(1, creator, oracleB) - registry.RegisterGameType(2, creator, oracleB) - oracles := registry.Oracles() - require.Len(t, oracles, 2) - require.Contains(t, oracles, oracleA) - require.Contains(t, oracles, oracleB) +func TestBondContracts(t *testing.T) { + t.Run("UnknownGameType", func(t *testing.T) { + registry := NewGameTypeRegistry() + contract, err := registry.CreateBondContract(types.GameMetadata{GameType: 0}) + require.ErrorIs(t, err, ErrUnsupportedGameType) + require.Nil(t, contract) + }) + t.Run("KnownGameType", func(t *testing.T) { + registry := NewGameTypeRegistry() + expected := &stubBondContract{} + registry.RegisterBondContract(0, func(game types.GameMetadata) (claims.BondContract, error) { + return expected, nil + }) + creator, err := registry.CreateBondContract(types.GameMetadata{GameType: 0}) + require.NoError(t, err) + require.Same(t, expected, creator) + }) + t.Run("PanicsOnDuplicate", func(t *testing.T) { + registry := NewGameTypeRegistry() + creator := func(game types.GameMetadata) (claims.BondContract, error) { + return nil, nil + } + registry.RegisterBondContract(0, creator) + require.Panics(t, func() { + registry.RegisterBondContract(0, creator) + }) + }) } -type stubPreimageOracle common.Address +type stubBondContract struct{} -func (s stubPreimageOracle) GetInputDataBlocks(_ context.Context, _ batching.Block, _ keccakTypes.LargePreimageIdent) ([]uint64, error) { +func (s *stubBondContract) GetCredit(ctx context.Context, receipient common.Address) (*big.Int, types.GameStatus, error) { panic("not supported") } -func (s stubPreimageOracle) DecodeInputData(_ []byte) (*big.Int, keccakTypes.InputData, error) { +func (s *stubBondContract) ClaimCredit(receipient common.Address) (txmgr.TxCandidate, error) { panic("not supported") } - -func (s stubPreimageOracle) Addr() common.Address { - return common.Address(s) -} - -func (s stubPreimageOracle) GetActivePreimages(_ context.Context, _ common.Hash) ([]keccakTypes.LargePreimageMetaData, error) { - return nil, nil -} diff --git a/op-challenger/game/scheduler/coordinator.go b/op-challenger/game/scheduler/coordinator.go index f5245aea52e9..63a2dd74f2fe 100644 --- a/op-challenger/game/scheduler/coordinator.go +++ b/op-challenger/game/scheduler/coordinator.go @@ -46,6 +46,8 @@ type coordinator struct { states map[common.Address]*gameState disk DiskManager + allowInvalidPrestate bool + // lastScheduledBlockNum is the highest block number that the coordinator has seen and scheduled jobs. lastScheduledBlockNum uint64 } @@ -133,7 +135,10 @@ func (c *coordinator) createJob(ctx context.Context, game types.GameMetadata, bl return nil, fmt.Errorf("failed to create game player: %w", err) } if err := player.ValidatePrestate(ctx); err != nil { - return nil, fmt.Errorf("failed to validate prestate: %w", err) + if !c.allowInvalidPrestate || !errors.Is(err, types.ErrInvalidPrestate) { + return nil, fmt.Errorf("failed to validate prestate: %w", err) + } + c.logger.Error("Invalid prestate", "game", game.Proxy, "err", err) } state.player = player state.status = player.Status() @@ -186,14 +191,15 @@ func (c *coordinator) deleteResolvedGameFiles() { } } -func newCoordinator(logger log.Logger, m CoordinatorMetricer, jobQueue chan<- job, resultQueue <-chan job, createPlayer PlayerCreator, disk DiskManager) *coordinator { +func newCoordinator(logger log.Logger, m CoordinatorMetricer, jobQueue chan<- job, resultQueue <-chan job, createPlayer PlayerCreator, disk DiskManager, allowInvalidPrestate bool) *coordinator { return &coordinator{ - logger: logger, - m: m, - jobQueue: jobQueue, - resultQueue: resultQueue, - createPlayer: createPlayer, - disk: disk, - states: make(map[common.Address]*gameState), + logger: logger, + m: m, + jobQueue: jobQueue, + resultQueue: resultQueue, + createPlayer: createPlayer, + disk: disk, + states: make(map[common.Address]*gameState), + allowInvalidPrestate: allowInvalidPrestate, } } diff --git a/op-challenger/game/scheduler/coordinator_test.go b/op-challenger/game/scheduler/coordinator_test.go index 7f2abaedf8c3..5686b1dae9a4 100644 --- a/op-challenger/game/scheduler/coordinator_test.go +++ b/op-challenger/game/scheduler/coordinator_test.go @@ -15,7 +15,7 @@ import ( ) func TestScheduleNewGames(t *testing.T) { - c, workQueue, _, games, disk := setupCoordinatorTest(t, 10) + c, workQueue, _, games, disk, _ := setupCoordinatorTest(t, 10) gameAddr1 := common.Address{0xaa} gameAddr2 := common.Address{0xbb} gameAddr3 := common.Address{0xcc} @@ -36,7 +36,7 @@ func TestScheduleNewGames(t *testing.T) { } func TestSkipSchedulingInflightGames(t *testing.T) { - c, workQueue, _, _, _ := setupCoordinatorTest(t, 10) + c, workQueue, _, _, _, _ := setupCoordinatorTest(t, 10) gameAddr1 := common.Address{0xaa} ctx := context.Background() @@ -51,7 +51,7 @@ func TestSkipSchedulingInflightGames(t *testing.T) { func TestExitWhenContextDoneWhileSchedulingJob(t *testing.T) { // No space in buffer to schedule a job - c, workQueue, _, _, _ := setupCoordinatorTest(t, 0) + c, workQueue, _, _, _, _ := setupCoordinatorTest(t, 0) gameAddr1 := common.Address{0xaa} ctx, cancel := context.WithCancel(context.Background()) cancel() // Context is cancelled @@ -63,8 +63,8 @@ func TestExitWhenContextDoneWhileSchedulingJob(t *testing.T) { } func TestSchedule_PrestateValidationErrors(t *testing.T) { - c, _, _, games, _ := setupCoordinatorTest(t, 10) - games.PrestateErr = fmt.Errorf("prestate error") + c, _, _, games, _, _ := setupCoordinatorTest(t, 10) + games.PrestateErr = types.ErrInvalidPrestate gameAddr1 := common.Address{0xaa} ctx := context.Background() @@ -72,8 +72,34 @@ func TestSchedule_PrestateValidationErrors(t *testing.T) { require.Error(t, err) } +func TestSchedule_SkipPrestateValidationErrors(t *testing.T) { + c, _, _, games, _, logs := setupCoordinatorTest(t, 10) + c.allowInvalidPrestate = true + games.PrestateErr = types.ErrInvalidPrestate + gameAddr1 := common.Address{0xaa} + ctx := context.Background() + + err := c.schedule(ctx, asGames(gameAddr1), 0) + require.NoError(t, err) + errLog := logs.FindLog(testlog.NewLevelFilter(log.LevelError), testlog.NewMessageFilter("Invalid prestate")) + require.NotNil(t, errLog) + require.Equal(t, errLog.AttrValue("game"), gameAddr1) + require.Equal(t, errLog.AttrValue("err"), games.PrestateErr) +} + +func TestSchedule_PrestateValidationFailure(t *testing.T) { + c, _, _, games, _, _ := setupCoordinatorTest(t, 10) + c.allowInvalidPrestate = true + games.PrestateErr = fmt.Errorf("failed to fetch prestate") + gameAddr1 := common.Address{0xaa} + ctx := context.Background() + + err := c.schedule(ctx, asGames(gameAddr1), 0) + require.ErrorIs(t, err, games.PrestateErr) +} + func TestScheduleGameAgainAfterCompletion(t *testing.T) { - c, workQueue, _, _, _ := setupCoordinatorTest(t, 10) + c, workQueue, _, _, _, _ := setupCoordinatorTest(t, 10) gameAddr1 := common.Address{0xaa} ctx := context.Background() @@ -94,13 +120,13 @@ func TestScheduleGameAgainAfterCompletion(t *testing.T) { } func TestResultForUnknownGame(t *testing.T) { - c, _, _, _, _ := setupCoordinatorTest(t, 10) + c, _, _, _, _, _ := setupCoordinatorTest(t, 10) err := c.processResult(job{addr: common.Address{0xaa}}) require.ErrorIs(t, err, errUnknownGame) } func TestProcessResultsWhileJobQueueFull(t *testing.T) { - c, workQueue, resultQueue, games, disk := setupCoordinatorTest(t, 0) + c, workQueue, resultQueue, games, disk, _ := setupCoordinatorTest(t, 0) gameAddr1 := common.Address{0xaa} gameAddr2 := common.Address{0xbb} gameAddr3 := common.Address{0xcc} @@ -142,7 +168,7 @@ loop: } func TestDeleteDataForResolvedGames(t *testing.T) { - c, workQueue, _, _, disk := setupCoordinatorTest(t, 10) + c, workQueue, _, _, disk, _ := setupCoordinatorTest(t, 10) gameAddr1 := common.Address{0xaa} gameAddr2 := common.Address{0xbb} gameAddr3 := common.Address{0xcc} @@ -182,7 +208,7 @@ func TestDeleteDataForResolvedGames(t *testing.T) { } func TestSchedule_RecordActedL1Block(t *testing.T) { - c, workQueue, _, _, _ := setupCoordinatorTest(t, 10) + c, workQueue, _, _, _, _ := setupCoordinatorTest(t, 10) gameAddr3 := common.Address{0xcc} ctx := context.Background() @@ -203,7 +229,7 @@ func TestSchedule_RecordActedL1Block(t *testing.T) { } func TestSchedule_RecordActedL1BlockMultipleGames(t *testing.T) { - c, workQueue, _, _, _ := setupCoordinatorTest(t, 10) + c, workQueue, _, _, _, _ := setupCoordinatorTest(t, 10) gameAddr1 := common.Address{0xaa} gameAddr2 := common.Address{0xbb} gameAddr3 := common.Address{0xcc} @@ -247,7 +273,7 @@ func TestSchedule_RecordActedL1BlockMultipleGames(t *testing.T) { } func TestSchedule_RecordActedL1BlockNewGame(t *testing.T) { - c, workQueue, _, _, _ := setupCoordinatorTest(t, 10) + c, workQueue, _, _, _, _ := setupCoordinatorTest(t, 10) gameAddr1 := common.Address{0xaa} gameAddr2 := common.Address{0xbb} gameAddr3 := common.Address{0xcc} @@ -276,7 +302,7 @@ func TestSchedule_RecordActedL1BlockNewGame(t *testing.T) { } func TestDoNotDeleteDataForGameThatFailedToCreatePlayer(t *testing.T) { - c, workQueue, _, games, disk := setupCoordinatorTest(t, 10) + c, workQueue, _, games, disk, _ := setupCoordinatorTest(t, 10) gameAddr1 := common.Address{0xaa} gameAddr2 := common.Address{0xbb} ctx := context.Background() @@ -307,7 +333,7 @@ func TestDoNotDeleteDataForGameThatFailedToCreatePlayer(t *testing.T) { } func TestDropOldGameStates(t *testing.T) { - c, workQueue, _, _, _ := setupCoordinatorTest(t, 10) + c, workQueue, _, _, _, _ := setupCoordinatorTest(t, 10) gameAddr1 := common.Address{0xaa} gameAddr2 := common.Address{0xbb} gameAddr3 := common.Address{0xcc} @@ -331,8 +357,8 @@ func TestDropOldGameStates(t *testing.T) { require.Contains(t, c.states, gameAddr4, "should create state for game 4") } -func setupCoordinatorTest(t *testing.T, bufferSize int) (*coordinator, <-chan job, chan job, *createdGames, *stubDiskManager) { - logger := testlog.Logger(t, log.LvlInfo) +func setupCoordinatorTest(t *testing.T, bufferSize int) (*coordinator, <-chan job, chan job, *createdGames, *stubDiskManager, *testlog.CapturingHandler) { + logger, logs := testlog.CaptureLogger(t, log.LevelInfo) workQueue := make(chan job, bufferSize) resultQueue := make(chan job, bufferSize) games := &createdGames{ @@ -340,8 +366,8 @@ func setupCoordinatorTest(t *testing.T, bufferSize int) (*coordinator, <-chan jo created: make(map[common.Address]*test.StubGamePlayer), } disk := &stubDiskManager{gameDirExists: make(map[common.Address]bool)} - c := newCoordinator(logger, &stubSchedulerMetrics{}, workQueue, resultQueue, games.CreateGame, disk) - return c, workQueue, resultQueue, games, disk + c := newCoordinator(logger, &stubSchedulerMetrics{}, workQueue, resultQueue, games.CreateGame, disk, false) + return c, workQueue, resultQueue, games, disk, logs } type createdGames struct { diff --git a/op-challenger/game/scheduler/scheduler.go b/op-challenger/game/scheduler/scheduler.go index 07b0f5b95a16..b0e0e1ebbe52 100644 --- a/op-challenger/game/scheduler/scheduler.go +++ b/op-challenger/game/scheduler/scheduler.go @@ -39,7 +39,7 @@ type Scheduler struct { cancel func() } -func NewScheduler(logger log.Logger, m SchedulerMetricer, disk DiskManager, maxConcurrency uint, createPlayer PlayerCreator) *Scheduler { +func NewScheduler(logger log.Logger, m SchedulerMetricer, disk DiskManager, maxConcurrency uint, createPlayer PlayerCreator, allowInvalidPrestate bool) *Scheduler { // Size job and results queues to be fairly small so backpressure is applied early // but with enough capacity to keep the workers busy jobQueue := make(chan job, maxConcurrency*2) @@ -52,7 +52,7 @@ func NewScheduler(logger log.Logger, m SchedulerMetricer, disk DiskManager, maxC return &Scheduler{ logger: logger, m: m, - coordinator: newCoordinator(logger, m, jobQueue, resultQueue, createPlayer, disk), + coordinator: newCoordinator(logger, m, jobQueue, resultQueue, createPlayer, disk, allowInvalidPrestate), maxConcurrency: maxConcurrency, scheduleQueue: scheduleQueue, jobQueue: jobQueue, diff --git a/op-challenger/game/scheduler/scheduler_test.go b/op-challenger/game/scheduler/scheduler_test.go index bd87e41f4b1e..7d02ac9023ee 100644 --- a/op-challenger/game/scheduler/scheduler_test.go +++ b/op-challenger/game/scheduler/scheduler_test.go @@ -14,14 +14,14 @@ import ( ) func TestSchedulerProcessesGames(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) ctx := context.Background() createPlayer := func(g types.GameMetadata, dir string) (GamePlayer, error) { return &test.StubGamePlayer{}, nil } removeExceptCalls := make(chan []common.Address) disk := &trackingDiskManager{removeExceptCalls: removeExceptCalls} - s := NewScheduler(logger, metrics.NoopMetrics, disk, 2, createPlayer) + s := NewScheduler(logger, metrics.NoopMetrics, disk, 2, createPlayer, false) s.Start(ctx) gameAddr1 := common.Address{0xaa} @@ -43,13 +43,13 @@ func TestSchedulerProcessesGames(t *testing.T) { } func TestReturnBusyWhenScheduleQueueFull(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) createPlayer := func(game types.GameMetadata, dir string) (GamePlayer, error) { return &test.StubGamePlayer{}, nil } removeExceptCalls := make(chan []common.Address) disk := &trackingDiskManager{removeExceptCalls: removeExceptCalls} - s := NewScheduler(logger, metrics.NoopMetrics, disk, 2, createPlayer) + s := NewScheduler(logger, metrics.NoopMetrics, disk, 2, createPlayer, false) // Scheduler not started - first call fills the queue require.NoError(t, s.Schedule(asGames(common.Address{0xaa}), 0)) diff --git a/op-challenger/game/service.go b/op-challenger/game/service.go index 901724d01580..34d51261b733 100644 --- a/op-challenger/game/service.go +++ b/op-challenger/game/service.go @@ -9,14 +9,16 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/keccak" "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/fetcher" + "github.com/ethereum-optimism/optimism/op-challenger/sender" "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/game/fault" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/claims" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" - "github.com/ethereum-optimism/optimism/op-challenger/game/loader" "github.com/ethereum-optimism/optimism/op-challenger/game/registry" "github.com/ethereum-optimism/optimism/op-challenger/game/scheduler" "github.com/ethereum-optimism/optimism/op-challenger/metrics" @@ -41,12 +43,17 @@ type Service struct { preimages *keccak.LargePreimageScheduler - txMgr *txmgr.SimpleTxManager + txMgr *txmgr.SimpleTxManager + txSender *sender.TxSender - loader *loader.GameLoader + cl *clock.SimpleClock + + claimants []common.Address + claimer *claims.BondClaimScheduler factoryContract *contracts.DisputeGameFactoryContract registry *registry.GameTypeRegistry + oracles *registry.OracleRegistry rollupClient *sources.RollupClient l1Client *ethclient.Client @@ -63,6 +70,7 @@ type Service struct { // NewService creates a new Service. func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Service, error) { s := &Service{ + cl: clock.NewSimpleClock(), logger: logger, metrics: metrics.NewMetrics(), } @@ -76,9 +84,10 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Se } func (s *Service) initFromConfig(ctx context.Context, cfg *config.Config) error { - if err := s.initTxManager(cfg); err != nil { + if err := s.initTxManager(ctx, cfg); err != nil { return fmt.Errorf("failed to init tx manager: %w", err) } + s.initClaimants(cfg) if err := s.initL1Client(ctx, cfg); err != nil { return fmt.Errorf("failed to init l1 client: %w", err) } @@ -97,12 +106,12 @@ func (s *Service) initFromConfig(ctx context.Context, cfg *config.Config) error if err := s.initFactoryContract(cfg); err != nil { return fmt.Errorf("failed to create factory contract bindings: %w", err) } - if err := s.initGameLoader(); err != nil { - return fmt.Errorf("failed to init game loader: %w", err) - } if err := s.registerGameTypes(ctx, cfg); err != nil { return fmt.Errorf("failed to register game types: %w", err) } + if err := s.initBondClaims(); err != nil { + return fmt.Errorf("failed to init bond claiming: %w", err) + } if err := s.initScheduler(cfg); err != nil { return fmt.Errorf("failed to init scheduler: %w", err) } @@ -117,12 +126,18 @@ func (s *Service) initFromConfig(ctx context.Context, cfg *config.Config) error return nil } -func (s *Service) initTxManager(cfg *config.Config) error { +func (s *Service) initClaimants(cfg *config.Config) { + claimants := []common.Address{s.txSender.From()} + s.claimants = append(claimants, cfg.AdditionalBondClaimants...) +} + +func (s *Service) initTxManager(ctx context.Context, cfg *config.Config) error { txMgr, err := txmgr.NewSimpleTxManager("challenger", s.logger, s.metrics, cfg.TxMgrConfig) if err != nil { return fmt.Errorf("failed to create the transaction manager: %w", err) } s.txMgr = txMgr + s.txSender = sender.NewTxSender(ctx, s.logger, txMgr, cfg.MaxPendingTx) return nil } @@ -176,7 +191,7 @@ func (s *Service) initMetricsServer(cfg *opmetrics.CLIConfig) error { } s.logger.Info("started metrics server", "addr", metricsSrv.Addr()) s.metricsSrv = metricsSrv - s.balanceMetricer = s.metrics.StartBalanceMetrics(s.logger, s.l1Client, s.txMgr.From()) + s.balanceMetricer = s.metrics.StartBalanceMetrics(s.logger, s.l1Client, s.txSender.From()) return nil } @@ -190,8 +205,9 @@ func (s *Service) initFactoryContract(cfg *config.Config) error { return nil } -func (s *Service) initGameLoader() error { - s.loader = loader.NewGameLoader(s.factoryContract) +func (s *Service) initBondClaims() error { + claimer := claims.NewBondClaimer(s.logger, s.metrics, s.registry.CreateBondContract, s.txSender, s.claimants...) + s.claimer = claims.NewBondClaimScheduler(s.logger, s.metrics, claimer) return nil } @@ -209,37 +225,41 @@ func (s *Service) initRollupClient(ctx context.Context, cfg *config.Config) erro func (s *Service) registerGameTypes(ctx context.Context, cfg *config.Config) error { gameTypeRegistry := registry.NewGameTypeRegistry() + oracles := registry.NewOracleRegistry() caller := batching.NewMultiCaller(s.l1Client.Client(), batching.DefaultBatchSize) - closer, err := fault.RegisterGameTypes(gameTypeRegistry, ctx, s.logger, s.metrics, cfg, s.rollupClient, s.txMgr, s.factoryContract, caller) + closer, err := fault.RegisterGameTypes(ctx, s.cl, s.logger, s.metrics, cfg, gameTypeRegistry, oracles, s.rollupClient, s.txSender, s.factoryContract, caller, s.l1Client, cfg.SelectiveClaimResolution, s.claimants) if err != nil { return err } s.faultGamesCloser = closer s.registry = gameTypeRegistry + s.oracles = oracles return nil } func (s *Service) initScheduler(cfg *config.Config) error { disk := newDiskManager(cfg.Datadir) - s.sched = scheduler.NewScheduler(s.logger, s.metrics, disk, cfg.MaxConcurrency, s.registry.CreatePlayer) + s.sched = scheduler.NewScheduler(s.logger, s.metrics, disk, cfg.MaxConcurrency, s.registry.CreatePlayer, cfg.AllowInvalidPrestate) return nil } func (s *Service) initLargePreimages() error { fetcher := fetcher.NewPreimageFetcher(s.logger, s.l1Client) verifier := keccak.NewPreimageVerifier(s.logger, fetcher) - s.preimages = keccak.NewLargePreimageScheduler(s.logger, s.registry.Oracles(), verifier) + challenger := keccak.NewPreimageChallenger(s.logger, s.metrics, verifier, s.txSender) + s.preimages = keccak.NewLargePreimageScheduler(s.logger, s.cl, s.oracles, challenger) return nil } func (s *Service) initMonitor(cfg *config.Config) { - cl := clock.SystemClock - s.monitor = newGameMonitor(s.logger, cl, s.loader, s.sched, s.preimages, cfg.GameWindow, s.l1Client.BlockNumber, cfg.GameAllowlist, s.pollClient) + s.monitor = newGameMonitor(s.logger, s.cl, s.factoryContract, s.sched, s.preimages, cfg.GameWindow, s.claimer, s.l1Client.BlockNumber, cfg.GameAllowlist, s.pollClient) } func (s *Service) Start(ctx context.Context) error { s.logger.Info("starting scheduler") s.sched.Start(ctx) + s.claimer.Start(ctx) + s.preimages.Start(ctx) s.logger.Info("starting monitoring") s.monitor.StartMonitoring() s.logger.Info("challenger game service start completed") diff --git a/op-challenger/game/types/types.go b/op-challenger/game/types/types.go index d69c757b27b3..5e831e73f9ca 100644 --- a/op-challenger/game/types/types.go +++ b/op-challenger/game/types/types.go @@ -1,11 +1,16 @@ package types import ( + "errors" "fmt" + "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" ) +var ErrInvalidPrestate = errors.New("absolute prestate does not match") + type GameStatus uint8 const ( @@ -37,7 +42,12 @@ func GameStatusFromUint8(i uint8) (GameStatus, error) { } type GameMetadata struct { - GameType uint8 + GameType uint32 Timestamp uint64 Proxy common.Address } + +type TxSender interface { + From() common.Address + SendAndWait(txPurpose string, txs ...txmgr.TxCandidate) ([]*ethtypes.Receipt, error) +} diff --git a/op-challenger/metrics/metrics.go b/op-challenger/metrics/metrics.go index fbdfa035e752..9383a45fedc2 100644 --- a/op-challenger/metrics/metrics.go +++ b/op-challenger/metrics/metrics.go @@ -34,6 +34,12 @@ type Metricer interface { RecordGameMove() RecordCannonExecutionTime(t float64) + RecordPreimageChallenged() + RecordPreimageChallengeFailed() + + RecordBondClaimFailed() + RecordBondClaimed(amount uint64) + RecordGamesStatus(inProgress, defenderWon, challengerWon int) RecordGameUpdateScheduled() @@ -62,6 +68,12 @@ type Metrics struct { executors prometheus.GaugeVec + bondClaimFailures prometheus.Counter + bondsClaimed prometheus.Counter + + preimageChallenged prometheus.Counter + preimageChallengeFailed prometheus.Counter + highestActedL1Block prometheus.Gauge moves prometheus.Counter @@ -129,6 +141,26 @@ func NewMetrics() *Metrics { []float64{1.0, 10.0}, prometheus.ExponentialBuckets(30.0, 2.0, 14)...), }), + bondClaimFailures: factory.NewCounter(prometheus.CounterOpts{ + Namespace: Namespace, + Name: "claim_failures", + Help: "Number of bond claims that failed", + }), + bondsClaimed: factory.NewCounter(prometheus.CounterOpts{ + Namespace: Namespace, + Name: "bonds", + Help: "Number of bonds claimed by the challenge agent", + }), + preimageChallenged: factory.NewCounter(prometheus.CounterOpts{ + Namespace: Namespace, + Name: "preimage_challenged", + Help: "Number of preimages challenged by the challenger", + }), + preimageChallengeFailed: factory.NewCounter(prometheus.CounterOpts{ + Namespace: Namespace, + Name: "preimage_challenge_failed", + Help: "Number of preimage challenges that failed", + }), trackedGames: *factory.NewGaugeVec(prometheus.GaugeOpts{ Namespace: Namespace, Name: "tracked_games", @@ -185,6 +217,22 @@ func (m *Metrics) RecordGameStep() { m.steps.Add(1) } +func (m *Metrics) RecordPreimageChallenged() { + m.preimageChallenged.Add(1) +} + +func (m *Metrics) RecordPreimageChallengeFailed() { + m.preimageChallengeFailed.Add(1) +} + +func (m *Metrics) RecordBondClaimFailed() { + m.bondClaimFailures.Add(1) +} + +func (m *Metrics) RecordBondClaimed(amount uint64) { + m.bondsClaimed.Add(float64(amount)) +} + func (m *Metrics) RecordCannonExecutionTime(t float64) { m.cannonExecutionTime.Observe(t) } diff --git a/op-challenger/metrics/noop.go b/op-challenger/metrics/noop.go index 23558263cddd..e14620ef320d 100644 --- a/op-challenger/metrics/noop.go +++ b/op-challenger/metrics/noop.go @@ -28,6 +28,12 @@ func (*NoopMetricsImpl) RecordGameStep() {} func (*NoopMetricsImpl) RecordActedL1Block(_ uint64) {} +func (*NoopMetricsImpl) RecordPreimageChallenged() {} +func (*NoopMetricsImpl) RecordPreimageChallengeFailed() {} + +func (*NoopMetricsImpl) RecordBondClaimFailed() {} +func (*NoopMetricsImpl) RecordBondClaimed(uint64) {} + func (*NoopMetricsImpl) RecordCannonExecutionTime(t float64) {} func (*NoopMetricsImpl) RecordGamesStatus(inProgress, defenderWon, challengerWon int) {} diff --git a/op-challenger/scripts/create_game.sh b/op-challenger/scripts/create_game.sh deleted file mode 100755 index 99063d8612d8..000000000000 --- a/op-challenger/scripts/create_game.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SOURCE_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) -CHALLENGER_DIR="${SOURCE_DIR%/*}" - -# ./create_game.sh -RPC=${1:?Must specify RPC address} -FACTORY_ADDR=${2:?Must specify factory address} -ROOT_CLAIM=${3:?Must specify claimed output root} -L2_BLOCK_NUM=${4:?Must specify L2 block number of claimed output root} -SIGNER_ARGS=("${@:5}") - -# Default to Cannon Fault game type -GAME_TYPE=${GAME_TYPE:-0} - -# Fault dispute game extra data is calculated as follows. -# abi.encode(uint256(l2_block_number), uint256(l1 checkpoint)) -EXTRA_DATA=$(cast abi-encode "f(uint256)" "${L2_BLOCK_NUM}" ) - -echo "Initializing the game" -FAULT_GAME_DATA=$(cast send --rpc-url "${RPC}" "${SIGNER_ARGS[@]}" "${FACTORY_ADDR}" "create(uint8,bytes32,bytes) returns(address)" "${GAME_TYPE}" "${ROOT_CLAIM}" "${EXTRA_DATA}" --json) - -# Extract the address of the newly created game from the receipt logs. -FAULT_GAME_ADDRESS=$(echo "${FAULT_GAME_DATA}" | jq -r '.logs[0].topics[1]' | cast parse-bytes32-address) -echo "Fault game address: ${FAULT_GAME_ADDRESS}" -echo "${FAULT_GAME_ADDRESS}" > "$CHALLENGER_DIR"/.fault-game-address diff --git a/op-challenger/scripts/list_claims.sh b/op-challenger/scripts/list_claims.sh deleted file mode 100755 index 1766f5977f27..000000000000 --- a/op-challenger/scripts/list_claims.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -RPC=${1:?Must specify RPC address} -GAME_ADDR=${2:?Must specify fault dispute game address} - -COUNT=$(cast call --rpc-url "${RPC}" "${GAME_ADDR}" 'claimDataLen() returns(uint256)') -echo "Claim count: ${COUNT}" -((COUNT=COUNT-1)) -for i in $(seq 0 "${COUNT}") -do - CLAIM=$(cast call --rpc-url "${RPC}" "${GAME_ADDR}" 'claimData(uint256) returns(uint32 parentIndex, address counteredBy, address claimant, uint128 bond, bytes32 claim, uint128 position, uint128 clock)' "${i}") - SAVEIFS=$IFS # Save current IFS (Internal Field Separator) - IFS=$'\n' # Change IFS to newline char - # shellcheck disable=SC2206 - CLAIM=($CLAIM) # split the string into an array by the same name - IFS=$SAVEIFS # Restore original IFS - - echo "${i} Parent: ${CLAIM[0]} Countered By: ${CLAIM[1]} Claimant: ${CLAIM[2]} Bond: ${CLAIM[3]} Claim: ${CLAIM[4]} Position: ${CLAIM[5]} Clock ${CLAIM[6]}" -done diff --git a/op-challenger/scripts/list_games.sh b/op-challenger/scripts/list_games.sh deleted file mode 100755 index ed95bca67fa9..000000000000 --- a/op-challenger/scripts/list_games.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -RPC=${1:?Must specify RPC address} -FACTORY_ADDR=${2:?Must specify dispute game factory address} - -COUNT=$(cast call --rpc-url "${RPC}" "${FACTORY_ADDR}" 'gameCount() returns(uint256)') -echo "Game count: ${COUNT}" -if [[ "${COUNT}" == "0" ]] -then - exit -fi -((COUNT=COUNT-1)) -for i in $(seq 0 "${COUNT}") -do - GAME=$(cast call --rpc-url "${RPC}" "${FACTORY_ADDR}" 'gameAtIndex(uint256) returns(uint8, uint64, address)' "${i}") - SAVEIFS=$IFS # Save current IFS (Internal Field Separator) - IFS=$'\n' # Change IFS to newline char - # shellcheck disable=SC2206 - GAME=($GAME) # split the string into an array by the same name - IFS=$SAVEIFS # Restore original IFS - - GAME_ADDR="${GAME[2]}" - CLAIMS=$(cast call --rpc-url "${RPC}" "${GAME_ADDR}" "claimDataLen() returns(uint256)") - STATUS=$(cast call --rpc-url "${RPC}" "${GAME_ADDR}" "status() returns(uint8)" | cast to-dec) - if [[ "${STATUS}" == "0" ]] - then - STATUS="In Progress" - elif [[ "${STATUS}" == "1" ]] - then - STATUS="Challenger Wins" - elif [[ "${STATUS}" == "2" ]] - then - STATUS="Defender Wins" - fi - echo "${i} Game: ${GAME_ADDR} Type: ${GAME[0]} Created: ${GAME[1]} Claims: ${CLAIMS} Status: ${STATUS}" -done diff --git a/op-challenger/scripts/move.sh b/op-challenger/scripts/move.sh deleted file mode 100755 index de374bcb7a16..000000000000 --- a/op-challenger/scripts/move.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -set -euo pipefail - -RPC=${1:?Must specify RPC URL} -GAME_ADDR=${2:?Must specify game address} -ACTION=${3:?Must specify attack or defend} -PARENT_INDEX=${4:?Must specify parent index. Use latest to counter the latest claim added to the game.} -CLAIM=${5:?Must specify claim hash} -SIGNER_ARGS=("${@:6}") - - -if [[ "${ACTION}" != "attack" && "${ACTION}" != "defend" ]] -then - echo "Action must be either attack or defend" - exit 1 -fi - -if [[ "${PARENT_INDEX}" == "latest" ]] -then - # Fetch the index of the most recent claim made. - PARENT_INDEX=$(cast call --rpc-url "${RPC}" "${GAME_ADDR}" 'claimDataLen() returns(uint256)') - ((PARENT_INDEX=PARENT_INDEX-1)) -fi - -# Perform the move. -cast send --rpc-url "${RPC}" "${SIGNER_ARGS[@]}" "${GAME_ADDR}" "$ACTION(uint256,bytes32)" "${PARENT_INDEX}" "${CLAIM}" diff --git a/op-challenger/scripts/resolve.sh b/op-challenger/scripts/resolve.sh deleted file mode 100755 index 60df8767d708..000000000000 --- a/op-challenger/scripts/resolve.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -set -euo pipefail - -RPC=${1:?Must specify RPC URL} -GAME_ADDR=${2:?Must specify game address} -SIGNER_ARGS=("${@:3}") - -# Perform the move. -# shellcheck disable=SC2086 -RESULT_DATA=$(cast send --rpc-url "${RPC}" "${SIGNER_ARGS[@]}" "${GAME_ADDR}" "resolve()" --json) -RESULT=$(echo "${RESULT_DATA}" | jq -r '.logs[0].topics[1]' | cast to-dec) - -if [[ "${RESULT}" == "0" ]] -then - RESULT="In Progress" -elif [[ "${RESULT}" == "1" ]] -then - RESULT="Challenger Wins" -elif [[ "${RESULT}" == "2" ]] -then - RESULT="Defender Wins" -fi - -echo "Result: $RESULT" diff --git a/op-challenger/sender/sender.go b/op-challenger/sender/sender.go new file mode 100644 index 000000000000..01f77c6b9780 --- /dev/null +++ b/op-challenger/sender/sender.go @@ -0,0 +1,56 @@ +package sender + +import ( + "context" + "errors" + + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" +) + +type TxSender struct { + log log.Logger + + txMgr txmgr.TxManager + queue *txmgr.Queue[int] +} + +func NewTxSender(ctx context.Context, logger log.Logger, txMgr txmgr.TxManager, maxPending uint64) *TxSender { + queue := txmgr.NewQueue[int](ctx, txMgr, maxPending) + return &TxSender{ + log: logger, + txMgr: txMgr, + queue: queue, + } +} + +func (s *TxSender) From() common.Address { + return s.txMgr.From() +} + +func (s *TxSender) SendAndWait(txPurpose string, txs ...txmgr.TxCandidate) ([]*types.Receipt, error) { + receiptsCh := make(chan txmgr.TxReceipt[int], len(txs)) + for i, tx := range txs { + s.queue.Send(i, tx, receiptsCh) + } + receipts := make([]*types.Receipt, len(txs)) + completed := 0 + var errs []error + for completed < len(txs) { + rcpt := <-receiptsCh + receipts[rcpt.ID] = rcpt.Receipt + completed++ + if rcpt.Err != nil { + errs = append(errs, rcpt.Err) + } else if rcpt.Receipt != nil { + if rcpt.Receipt.Status != types.ReceiptStatusSuccessful { + s.log.Error("Transaction published but reverted", "tx_hash", rcpt.Receipt.TxHash, "purpose", txPurpose) + } else { + s.log.Debug("Transaction successfully published", "tx_hash", rcpt.Receipt.TxHash, "purpose", txPurpose) + } + } + } + return receipts, errors.Join(errs...) +} diff --git a/op-challenger/sender/sender_test.go b/op-challenger/sender/sender_test.go new file mode 100644 index 000000000000..16dacf6173af --- /dev/null +++ b/op-challenger/sender/sender_test.go @@ -0,0 +1,145 @@ +package sender + +import ( + "context" + "fmt" + "sync" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" +) + +func TestSendAndWait(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + txMgr := &stubTxMgr{sending: make(map[byte]chan *types.Receipt)} + sender := NewTxSender(ctx, testlog.Logger(t, log.LevelInfo), txMgr, 5) + + tx := func(i byte) txmgr.TxCandidate { + return txmgr.TxCandidate{TxData: []byte{i}} + } + + sendAsync := func(txs ...txmgr.TxCandidate) chan []*types.Receipt { + ch := make(chan []*types.Receipt, 1) + go func() { + rcpts, err := sender.SendAndWait("testing", txs...) + require.NoError(t, err) + ch <- rcpts + close(ch) + }() + return ch + } + + wait := func(ch chan []*types.Receipt) []*types.Receipt { + select { + case rcpts := <-ch: + return rcpts + case <-ctx.Done(): + require.FailNow(t, "Timeout waiting for receipt") + return nil + } + } + + batch1 := sendAsync(tx(1), tx(2), tx(3)) + batch2 := sendAsync(tx(4), tx(5)) + require.Eventually(t, func() bool { + return txMgr.sentCount() == 5 + }, 10*time.Second, 1*time.Millisecond, "Wait for first transactions to send") + + require.Len(t, batch1, 0, "Should not have completed batch1") + require.Len(t, batch2, 0, "Should not have completed batch2") + + // Send a third batch after the first set have started sending to avoid races + batch3 := sendAsync(tx(6)) + require.Len(t, batch3, 0, "Should not have completed batch3") + + // Sends the 6th tx after one of the previous ones completes + txMgr.txSuccess(tx(5)) + require.Eventually(t, func() bool { + return txMgr.sentCount() == 6 + }, 10*time.Second, 1*time.Millisecond, "Wait for final transaction to send") + require.Len(t, batch1, 0, "Should not have completed batch1") + require.Len(t, batch2, 0, "Should not have completed batch2") + require.Len(t, batch3, 0, "Should not have completed batch3") + + // Batches complete as soon as they are sent + txMgr.txSuccess(tx(6)) + require.Len(t, wait(batch3), 1, "Batch3 should complete") + require.Len(t, batch1, 0, "Should not have completed batch1") + require.Len(t, batch2, 0, "Should not have completed batch2") + + txMgr.txSuccess(tx(2)) + txMgr.txSuccess(tx(3)) + require.Len(t, batch1, 0, "Should not have completed batch1") + require.Len(t, batch2, 0, "Should not have completed batch2") + + txMgr.txSuccess(tx(1)) + require.Len(t, wait(batch1), 3, "Batch1 should complete") + require.Len(t, batch2, 0, "Should not have completed batch2") + + txMgr.txSuccess(tx(4)) + require.Len(t, wait(batch2), 2, "Batch2 should complete") +} + +type stubTxMgr struct { + m sync.Mutex + sending map[byte]chan *types.Receipt +} + +func (s *stubTxMgr) IsClosed() bool { + return false +} + +func (s *stubTxMgr) Send(ctx context.Context, candidate txmgr.TxCandidate) (*types.Receipt, error) { + ch := s.recordTx(candidate) + return <-ch, nil +} + +func (s *stubTxMgr) recordTx(candidate txmgr.TxCandidate) chan *types.Receipt { + s.m.Lock() + defer s.m.Unlock() + id := candidate.TxData[0] + if _, ok := s.sending[id]; ok { + // Shouldn't happen if tests are well written, but double check... + panic("Sending duplicate transaction") + } + ch := make(chan *types.Receipt, 1) + s.sending[id] = ch + return ch +} + +func (s *stubTxMgr) txSuccess(candidate txmgr.TxCandidate) { + s.m.Lock() + defer s.m.Unlock() + ch, ok := s.sending[candidate.TxData[0]] + if !ok { + // Shouldn't happen if tests are well written, but double check... + panic(fmt.Sprintf("Completing unknown transaction: %v Known: %v", candidate.TxData[0], maps.Keys(s.sending))) + } + ch <- &types.Receipt{Status: types.ReceiptStatusSuccessful} + close(ch) +} + +func (s *stubTxMgr) sentCount() int { + s.m.Lock() + defer s.m.Unlock() + return len(s.sending) +} + +func (s *stubTxMgr) From() common.Address { + panic("unsupported") +} + +func (s *stubTxMgr) BlockNumber(_ context.Context) (uint64, error) { + panic("unsupported") +} + +func (s *stubTxMgr) Close() { +} diff --git a/op-conductor/README.md b/op-conductor/README.md index 06bfdb75e68a..8cb3afcfe34a 100644 --- a/op-conductor/README.md +++ b/op-conductor/README.md @@ -27,4 +27,12 @@ On a high level, op-conductor serves the following functions: 3. monitor sequencer (op-node) health 4. control loop => control sequencer (op-node) status (start / stop) based on different scenarios +### Conductor State Transition + +![conductor state transition](./assets/op-conductor-state-transition.svg) + +Helpful tips: +To better understand the graph, focus on one node at a time, understand what can be transitioned to this current state and how it can transition to other states. +This way you could understand how we handle the state transitions. + This is initial version of README, more details will be added later. diff --git a/op-conductor/assets/op-conductor-state-transition.svg b/op-conductor/assets/op-conductor-state-transition.svg new file mode 100644 index 000000000000..b9e0544524e1 --- /dev/null +++ b/op-conductor/assets/op-conductor-state-transition.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/op-conductor/cmd/main.go b/op-conductor/cmd/main.go index e7b49d9eb29d..508ffe220df0 100644 --- a/op-conductor/cmd/main.go +++ b/op-conductor/cmd/main.go @@ -44,7 +44,7 @@ func main() { func OpConductorMain(ctx *cli.Context, closeApp context.CancelCauseFunc) (cliapp.Lifecycle, error) { logCfg := oplog.ReadCLIConfig(ctx) log := oplog.NewLogger(oplog.AppOut(ctx), logCfg) - oplog.SetGlobalLogHandler(log.GetHandler()) + oplog.SetGlobalLogHandler(log.Handler()) opservice.ValidateEnvVars(flags.EnvVarPrefix, flags.Flags, log) cfg, err := conductor.NewConfig(ctx, log) diff --git a/op-conductor/conductor/config.go b/op-conductor/conductor/config.go index 8e69957c4f7f..ad65a0e34cc3 100644 --- a/op-conductor/conductor/config.go +++ b/op-conductor/conductor/config.go @@ -101,7 +101,7 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*Config, error) { return nil, errors.Wrap(err, "missing required flags") } - rollupCfg, err := opnode.NewRollupConfig(log, ctx) + rollupCfg, err := opnode.NewRollupConfigFromCLI(log, ctx) if err != nil { return nil, errors.Wrap(err, "failed to load rollup config") } @@ -109,15 +109,17 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*Config, error) { return &Config{ ConsensusAddr: ctx.String(flags.ConsensusAddr.Name), ConsensusPort: ctx.Int(flags.ConsensusPort.Name), + RaftBootstrap: ctx.Bool(flags.RaftBootstrap.Name), RaftServerID: ctx.String(flags.RaftServerID.Name), RaftStorageDir: ctx.String(flags.RaftStorageDir.Name), NodeRPC: ctx.String(flags.NodeRPC.Name), ExecutionRPC: ctx.String(flags.ExecutionRPC.Name), Paused: ctx.Bool(flags.Paused.Name), HealthCheck: HealthCheckConfig{ - Interval: ctx.Uint64(flags.HealthCheckInterval.Name), - SafeInterval: ctx.Uint64(flags.HealthCheckSafeInterval.Name), - MinPeerCount: ctx.Uint64(flags.HealthCheckMinPeerCount.Name), + Interval: ctx.Uint64(flags.HealthCheckInterval.Name), + UnsafeInterval: ctx.Uint64(flags.HealthCheckUnsafeInterval.Name), + SafeInterval: ctx.Uint64(flags.HealthCheckSafeInterval.Name), + MinPeerCount: ctx.Uint64(flags.HealthCheckMinPeerCount.Name), }, RollupCfg: *rollupCfg, RPCEnableProxy: ctx.Bool(flags.RPCEnableProxy.Name), @@ -133,6 +135,9 @@ type HealthCheckConfig struct { // Interval is the interval (in seconds) to check the health of the sequencer. Interval uint64 + // UnsafeInterval is the interval allowed between unsafe head and now in seconds. + UnsafeInterval uint64 + // SafeInterval is the interval between safe head progression measured in seconds. SafeInterval uint64 diff --git a/op-conductor/conductor/service.go b/op-conductor/conductor/service.go index a4f4f5e1c2cb..4775d8a48836 100644 --- a/op-conductor/conductor/service.go +++ b/op-conductor/conductor/service.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "math/rand" + "strings" "sync" "sync/atomic" "time" @@ -19,6 +20,7 @@ import ( "github.com/ethereum-optimism/optimism/op-conductor/health" conductorrpc "github.com/ethereum-optimism/optimism/op-conductor/rpc" opp2p "github.com/ethereum-optimism/optimism/op-node/p2p" + "github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum-optimism/optimism/op-service/cliapp" opclient "github.com/ethereum-optimism/optimism/op-service/client" "github.com/ethereum-optimism/optimism/op-service/dial" @@ -28,9 +30,10 @@ import ( ) var ( - ErrResumeTimeout = errors.New("timeout to resume conductor") - ErrPauseTimeout = errors.New("timeout to pause conductor") - ErrUnsafeHeadMismarch = errors.New("unsafe head mismatch") + ErrResumeTimeout = errors.New("timeout to resume conductor") + ErrPauseTimeout = errors.New("timeout to pause conductor") + ErrUnsafeHeadMismarch = errors.New("unsafe head mismatch") + ErrUnableToRetrieveUnsafeHeadFromConsensus = errors.New("unable to retrieve unsafe head from consensus") ) // New creates a new OpConductor instance. @@ -65,7 +68,7 @@ func NewOpConductor( cons: cons, hmon: hmon, } - oc.actionFn = oc.action + oc.loopActionFn = oc.loopAction // explicitly set all atomic.Bool values oc.leader.Store(false) // upon start, it should not be the leader unless specified otherwise by raft bootstrap, in that case, it'll receive a leadership update from consensus. @@ -87,6 +90,7 @@ func NewOpConductor( } return nil, err } + oc.prevState = NewState(oc.leader.Load(), oc.healthy.Load(), oc.seqActive.Load()) return oc, nil } @@ -131,13 +135,7 @@ func (c *OpConductor) initSequencerControl(ctx context.Context) error { node := sources.NewRollupClient(nc) c.ctrl = client.NewSequencerControl(exec, node) - active, err := c.ctrl.SequencerActive(ctx) - if err != nil { - return errors.Wrap(err, "failed to get sequencer active status") - } - c.seqActive.Store(active) - - return nil + return c.updateSequencerActiveStatus() } func (c *OpConductor) initConsensus(ctx context.Context) error { @@ -175,6 +173,7 @@ func (c *OpConductor) initHealthMonitor(ctx context.Context) error { c.hmon = health.NewSequencerHealthMonitor( c.log, c.cfg.HealthCheck.Interval, + c.cfg.HealthCheck.UnsafeInterval, c.cfg.HealthCheck.SafeInterval, c.cfg.HealthCheck.MinPeerCount, &c.cfg.RollupCfg, @@ -220,6 +219,12 @@ func (oc *OpConductor) initRPCServer(ctx context.Context) error { Namespace: conductorrpc.NodeRPCNamespace, Service: nodeProxy, }) + + nodeAdminProxy := conductorrpc.NewNodeAdminProxyBackend(oc.log, oc, nodeClient) + server.AddAPI(rpc.API{ + Namespace: conductorrpc.NodeAdminRPCNamespace, + Service: nodeAdminProxy, + }) } oc.rpcServer = server @@ -245,12 +250,14 @@ type OpConductor struct { hmon health.HealthMonitor leader atomic.Bool - healthy atomic.Bool seqActive atomic.Bool + healthy atomic.Bool + hcerr error // error from health check + prevState *state - healthUpdateCh <-chan bool + healthUpdateCh <-chan error leaderUpdateCh <-chan bool - actionFn func() // actionFn defines the action to be executed to bring the sequencer to the desired state. + loopActionFn func() // loopActionFn defines the logic to be executed inside control loop. wg sync.WaitGroup pauseCh chan struct{} @@ -266,6 +273,23 @@ type OpConductor struct { rpcServer *oprpc.Server } +type state struct { + leader, healthy, active bool +} + +// NewState creates a new state instance. +func NewState(leader, healthy, active bool) *state { + return &state{ + leader: leader, + healthy: healthy, + active: active, + } +} + +func (s *state) Equal(other *state) bool { + return s.leader == other.leader && s.healthy == other.healthy && s.active == other.active +} + var _ cliapp.Lifecycle = (*OpConductor)(nil) // Start implements cliapp.Lifecycle. @@ -349,6 +373,11 @@ func (oc *OpConductor) Pause(ctx context.Context) error { // Resume resumes the control loop of OpConductor. func (oc *OpConductor) Resume(ctx context.Context) error { + err := oc.updateSequencerActiveStatus() + if err != nil { + return errors.Wrap(err, "cannot resume because failed to get sequencer active status") + } + select { case oc.resumeCh <- struct{}{}: <-oc.resumeDoneCh @@ -376,7 +405,7 @@ func (oc *OpConductor) Leader(_ context.Context) bool { } // LeaderWithID returns the current leader's server ID and address. -func (oc *OpConductor) LeaderWithID(_ context.Context) (string, string) { +func (oc *OpConductor) LeaderWithID(_ context.Context) *consensus.ServerInfo { return oc.cons.LeaderWithID() } @@ -405,7 +434,7 @@ func (oc *OpConductor) TransferLeaderToServer(_ context.Context, id string, addr return oc.cons.TransferLeaderTo(id, addr) } -// CommitUnsafePayload commits a unsafe payload (lastest head) to the cluster FSM. +// CommitUnsafePayload commits a unsafe payload (latest head) to the cluster FSM. func (oc *OpConductor) CommitUnsafePayload(_ context.Context, payload *eth.ExecutionPayloadEnvelope) error { return oc.cons.CommitUnsafePayload(payload) } @@ -415,34 +444,50 @@ func (oc *OpConductor) SequencerHealthy(_ context.Context) bool { return oc.healthy.Load() } +// ClusterMembership returns current cluster's membership information. +func (oc *OpConductor) ClusterMembership(_ context.Context) ([]*consensus.ServerInfo, error) { + return oc.cons.ClusterMembership() +} + +// LatestUnsafePayload returns the latest unsafe payload envelope from FSM. +func (oc *OpConductor) LatestUnsafePayload(_ context.Context) *eth.ExecutionPayloadEnvelope { + return oc.cons.LatestUnsafePayload() +} + func (oc *OpConductor) loop() { defer oc.wg.Done() for { select { - // We process status update (health, leadership) first regardless of the paused state. - // This way we could properly bring the sequencer to the desired state when resumed. - case healthy := <-oc.healthUpdateCh: - oc.handleHealthUpdate(healthy) - case leader := <-oc.leaderUpdateCh: - oc.handleLeaderUpdate(leader) - case <-oc.pauseCh: - oc.paused.Store(true) - oc.pauseDoneCh <- struct{}{} - case <-oc.resumeCh: - oc.paused.Store(false) - oc.resumeDoneCh <- struct{}{} - // queue an action to make sure sequencer is in the desired state after resume. - oc.queueAction() case <-oc.shutdownCtx.Done(): return - // Handle control action last, so that when executing the action, we have the latest status and bring the sequencer to the desired state. - case <-oc.actionCh: - oc.actionFn() + default: + oc.loopActionFn() } } } +func (oc *OpConductor) loopAction() { + select { + case healthy := <-oc.healthUpdateCh: + oc.handleHealthUpdate(healthy) + case leader := <-oc.leaderUpdateCh: + oc.handleLeaderUpdate(leader) + case <-oc.pauseCh: + oc.paused.Store(true) + oc.pauseDoneCh <- struct{}{} + case <-oc.resumeCh: + oc.paused.Store(false) + oc.resumeDoneCh <- struct{}{} + // queue an action to make sure sequencer is in the desired state after resume. + oc.queueAction() + case <-oc.shutdownCtx.Done(): + return + case <-oc.actionCh: + oc.action() + } +} + func (oc *OpConductor) queueAction() { select { case oc.actionCh <- struct{}{}: @@ -461,15 +506,22 @@ func (oc *OpConductor) handleLeaderUpdate(leader bool) { } // handleHealthUpdate handles health update from health monitor. -func (oc *OpConductor) handleHealthUpdate(healthy bool) { +func (oc *OpConductor) handleHealthUpdate(hcerr error) { + oc.log.Debug("received health update", "server", oc.cons.ServerID(), "error", hcerr) + healthy := hcerr == nil if !healthy { - oc.log.Error("Sequencer is unhealthy", "server", oc.cons.ServerID()) + oc.log.Error("Sequencer is unhealthy", "server", oc.cons.ServerID(), "err", hcerr) + // always queue an action if it's unhealthy, it could be an no-op in the handler. + oc.queueAction() } if healthy != oc.healthy.Load() { - oc.healthy.Store(healthy) + // queue an action if health status changed. oc.queueAction() } + + oc.healthy.Store(healthy) + oc.hcerr = hcerr } // action tries to bring the sequencer to the desired state, a retry will be queued if any action failed. @@ -479,8 +531,11 @@ func (oc *OpConductor) action() { } var err error + status := NewState(oc.leader.Load(), oc.healthy.Load(), oc.seqActive.Load()) + oc.log.Debug("entering action with status", "status", status) + // exhaust all cases below for completeness, 3 state, 8 cases. - switch status := struct{ leader, healthy, active bool }{oc.leader.Load(), oc.healthy.Load(), oc.seqActive.Load()}; { + switch { case !status.leader && !status.healthy && !status.active: // if follower is not healthy and not sequencing, just log an error oc.log.Error("server (follower) is not healthy", "server", oc.cons.ServerID()) @@ -493,9 +548,35 @@ func (oc *OpConductor) action() { // stop sequencer, this happens when current server steps down as leader. err = oc.stopSequencer() case status.leader && !status.healthy && !status.active: - // transfer leadership to another node + // There are 2 scenarios we need to handle: + // 1. current node is follower, active sequencer became unhealthy and started the leadership transfer process. + // however if leadership transfer took longer than the time for health monitor to treat the node as unhealthy, + // then basically the entire network is stalled and we need to start sequencing in this case. + if !oc.prevState.leader && !oc.prevState.active { + _, _, cerr := oc.compareUnsafeHead(oc.shutdownCtx) + if cerr == nil && !errors.Is(oc.hcerr, health.ErrSequencerConnectionDown) { + // if unsafe in consensus is the same as unsafe in op-node, then it is scenario #1 and we should start sequencer. + err = oc.startSequencer() + break + } + } + + // 2. for other cases, we should try to transfer leader to another node. + // for example, if follower became a leader and unhealthy at the same time (just unhealthy itself), then we should transfer leadership. err = oc.transferLeader() case status.leader && !status.healthy && status.active: + // There are two scenarios we need to handle here: + // 1. we're transitioned from case status.leader && !status.healthy && !status.active, see description above + // then we should continue to sequence blocks and try to bring ourselves back to healthy state. + // note: we need to also make sure that the health error is not due to ErrSequencerConnectionDown + // because in this case, we should stop sequencing and transfer leadership to other nodes. + if oc.prevState.leader && !oc.prevState.healthy && !oc.prevState.active && !errors.Is(oc.hcerr, health.ErrSequencerConnectionDown) { + err = errors.New("waiting for sequencing to become healthy by itself") + break + } + + // 2. we're here becasuse an healthy leader became unhealthy itself + // then we should try to stop sequencing locally and transfer leadership. var result *multierror.Error // Try to stop sequencer first, but since sequencer is not healthy, we may not be able to stop it. // In this case, it's fine to continue to try to transfer leadership to another server. This is safe because @@ -520,17 +601,25 @@ func (oc *OpConductor) action() { // normal leader, do nothing } + oc.log.Debug("exiting action with status and error", "status", status, "err", err) if err != nil { oc.log.Error("failed to execute step, queueing another one to retry", "err", err) // randomly sleep for 0-200ms to avoid excessive retry time.Sleep(time.Duration(rand.Intn(200)) * time.Millisecond) oc.queueAction() + return + } + + if !status.Equal(oc.prevState) { + oc.log.Info("state changed", "prev_state", oc.prevState, "new_state", status) + oc.prevState = status } } // transferLeader tries to transfer leadership to another server. func (oc *OpConductor) transferLeader() error { // TransferLeader here will do round robin to try to transfer leadership to the next healthy node. + oc.log.Info("transferring leadership", "server", oc.cons.ServerID()) err := oc.cons.TransferLeader() if err == nil { oc.leader.Store(false) @@ -551,28 +640,62 @@ func (oc *OpConductor) transferLeader() error { func (oc *OpConductor) stopSequencer() error { oc.log.Info("stopping sequencer", "server", oc.cons.ServerID(), "leader", oc.leader.Load(), "healthy", oc.healthy.Load(), "active", oc.seqActive.Load()) - if _, err := oc.ctrl.StopSequencer(context.Background()); err != nil { - return errors.Wrap(err, "failed to stop sequencer") + _, err := oc.ctrl.StopSequencer(context.Background()) + if err != nil { + if strings.Contains(err.Error(), driver.ErrSequencerAlreadyStopped.Error()) { + oc.log.Warn("sequencer already stopped.", "err", err) + } else { + return errors.Wrap(err, "failed to stop sequencer") + } } + oc.seqActive.Store(false) return nil } func (oc *OpConductor) startSequencer() error { - oc.log.Info("starting sequencer", "server", oc.cons.ServerID(), "leader", oc.leader.Load(), "healthy", oc.healthy.Load(), "active", oc.seqActive.Load()) + ctx := context.Background() // When starting sequencer, we need to make sure that the current node has the latest unsafe head from the consensus protocol // If not, then we wait for the unsafe head to catch up or gossip it to op-node manually from op-conductor. + unsafeInCons, unsafeInNode, err := oc.compareUnsafeHead(ctx) + // if there's a mismatch, try to post the unsafe head to op-node + if err != nil { + if errors.Is(err, ErrUnsafeHeadMismarch) && uint64(unsafeInCons.ExecutionPayload.BlockNumber)-unsafeInNode.NumberU64() == 1 { + // tries to post the unsafe head to op-node when head is only 1 block behind (most likely due to gossip delay) + if innerErr := oc.ctrl.PostUnsafePayload(ctx, unsafeInCons); innerErr != nil { + oc.log.Error("failed to post unsafe head payload envelope to op-node", "err", innerErr) + } + } + return err + } + + oc.log.Info("starting sequencer", "server", oc.cons.ServerID(), "leader", oc.leader.Load(), "healthy", oc.healthy.Load(), "active", oc.seqActive.Load()) + if err = oc.ctrl.StartSequencer(ctx, unsafeInCons.ExecutionPayload.BlockHash); err != nil { + // cannot directly compare using Errors.Is because the error is returned from an JSON RPC server which lost its type. + if !strings.Contains(err.Error(), driver.ErrSequencerAlreadyStarted.Error()) { + return fmt.Errorf("failed to start sequencer: %w", err) + } else { + oc.log.Warn("sequencer already started.", "err", err) + } + } + + oc.seqActive.Store(true) + return nil +} + +func (oc *OpConductor) compareUnsafeHead(ctx context.Context) (*eth.ExecutionPayloadEnvelope, eth.BlockInfo, error) { unsafeInCons := oc.cons.LatestUnsafePayload() if unsafeInCons == nil { - return errors.New("failed to get latest unsafe block from consensus") + return nil, nil, ErrUnableToRetrieveUnsafeHeadFromConsensus } - unsafeInNode, err := oc.ctrl.LatestUnsafeBlock(context.Background()) + + unsafeInNode, err := oc.ctrl.LatestUnsafeBlock(ctx) if err != nil { - return errors.Wrap(err, "failed to get latest unsafe block from EL during startSequencer phase") + return unsafeInCons, nil, errors.Wrap(err, "failed to get latest unsafe block from EL during compareUnsafeHead phase") } - //if unsafeInCons.BlockHash != unsafeInNode.Hash() { + oc.log.Debug("comparing unsafe head", "consensus", unsafeInCons.ExecutionPayload.BlockNumber, "node", unsafeInNode.NumberU64()) if unsafeInCons.ExecutionPayload.BlockHash != unsafeInNode.Hash() { oc.log.Warn( "latest unsafe block in consensus is not the same as the one in op-node", @@ -582,19 +705,18 @@ func (oc *OpConductor) startSequencer() error { "node_block_num", unsafeInNode.NumberU64(), ) - if uint64(unsafeInCons.ExecutionPayload.BlockNumber)-unsafeInNode.NumberU64() == 1 { - // tries to post the unsafe head to op-node when head is only 1 block behind (most likely due to gossip delay) - if err = oc.ctrl.PostUnsafePayload(context.Background(), unsafeInCons); err != nil { - oc.log.Error("failed to post unsafe head payload envelope to op-node", "err", err) - } - } - return ErrUnsafeHeadMismarch // return error to allow retry + return unsafeInCons, unsafeInNode, ErrUnsafeHeadMismarch } - if err := oc.ctrl.StartSequencer(context.Background(), unsafeInCons.ExecutionPayload.BlockHash); err != nil { - return errors.Wrap(err, "failed to start sequencer") - } + return unsafeInCons, unsafeInNode, nil +} - oc.seqActive.Store(true) +func (oc *OpConductor) updateSequencerActiveStatus() error { + active, err := oc.ctrl.SequencerActive(oc.shutdownCtx) + if err != nil { + return errors.Wrap(err, "failed to get sequencer active status") + } + oc.log.Info("sequencer active status updated", "active", active) + oc.seqActive.Store(active) return nil } diff --git a/op-conductor/conductor/service_test.go b/op-conductor/conductor/service_test.go index 3659ee949de6..9f61ed90ba18 100644 --- a/op-conductor/conductor/service_test.go +++ b/op-conductor/conductor/service_test.go @@ -17,6 +17,7 @@ import ( clientmocks "github.com/ethereum-optimism/optimism/op-conductor/client/mocks" consensusmocks "github.com/ethereum-optimism/optimism/op-conductor/consensus/mocks" + "github.com/ethereum-optimism/optimism/op-conductor/health" healthmocks "github.com/ethereum-optimism/optimism/op-conductor/health/mocks" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" @@ -36,9 +37,10 @@ func mockConfig(t *testing.T) Config { ExecutionRPC: "http://geth:8545", Paused: false, HealthCheck: HealthCheckConfig{ - Interval: 1, - SafeInterval: 5, - MinPeerCount: 1, + Interval: 1, + UnsafeInterval: 3, + SafeInterval: 5, + MinPeerCount: 1, }, RollupCfg: rollup.Config{ Genesis: rollup.Genesis{ @@ -64,6 +66,7 @@ func mockConfig(t *testing.T) Config { ChannelTimeout: 300, L1ChainID: big.NewInt(1), L2ChainID: big.NewInt(2), + RegolithTime: &now, CanyonTime: &now, BatchInboxAddress: [20]byte{1, 2}, DepositContractAddress: [20]byte{2, 3}, @@ -77,12 +80,12 @@ func mockConfig(t *testing.T) Config { type OpConductorTestSuite struct { suite.Suite - conductor *OpConductor - - healthUpdateCh chan bool + conductor *OpConductor + healthUpdateCh chan error leaderUpdateCh chan bool ctx context.Context + err error log log.Logger cfg Config version string @@ -90,13 +93,14 @@ type OpConductorTestSuite struct { cons *consensusmocks.Consensus hmon *healthmocks.HealthMonitor - next chan struct{} - wg sync.WaitGroup + syncEnabled bool // syncEnabled controls whether synchronization is enabled for test actions. + next chan struct{} // next is used to signal when the next action in the test can proceed. + wg sync.WaitGroup // wg ensures that test actions are completed before moving on. } func (s *OpConductorTestSuite) SetupSuite() { s.ctx = context.Background() - s.log = testlog.Logger(s.T(), log.LvlDebug) + s.log = testlog.Logger(s.T(), log.LevelDebug) s.cfg = mockConfig(s.T()) s.version = "v0.0.1" s.next = make(chan struct{}, 1) @@ -113,50 +117,75 @@ func (s *OpConductorTestSuite) SetupTest() { s.NoError(err) s.conductor = conductor - s.healthUpdateCh = make(chan bool) + s.healthUpdateCh = make(chan error, 1) s.hmon.EXPECT().Start().Return(nil) s.conductor.healthUpdateCh = s.healthUpdateCh - s.leaderUpdateCh = make(chan bool) + s.leaderUpdateCh = make(chan bool, 1) s.conductor.leaderUpdateCh = s.leaderUpdateCh - err = s.conductor.Start(s.ctx) - s.NoError(err) - s.False(s.conductor.Stopped()) + s.err = errors.New("error") + s.syncEnabled = false // default to no sync, turn it on by calling s.enableSynchronization() } func (s *OpConductorTestSuite) TearDownTest() { s.hmon.EXPECT().Stop().Return(nil) s.cons.EXPECT().Shutdown().Return(nil) + if s.syncEnabled { + s.wg.Add(1) + s.next <- struct{}{} + } s.NoError(s.conductor.Stop(s.ctx)) s.True(s.conductor.Stopped()) } +func (s *OpConductorTestSuite) startConductor() { + err := s.conductor.Start(s.ctx) + s.NoError(err) + s.False(s.conductor.Stopped()) +} + // enableSynchronization wraps conductor actionFn with extra synchronization logic // so that we could control the execution of actionFn and observe the internal state transition in between. func (s *OpConductorTestSuite) enableSynchronization() { - s.conductor.actionFn = func() { + s.syncEnabled = true + s.conductor.loopActionFn = func() { <-s.next - s.conductor.action() + s.conductor.loopAction() s.wg.Done() } + s.startConductor() +} + +func (s *OpConductorTestSuite) disableSynchronization() { + s.syncEnabled = false + s.startConductor() } func (s *OpConductorTestSuite) execute(fn func()) { s.wg.Add(1) - s.next <- struct{}{} if fn != nil { fn() } + s.next <- struct{}{} s.wg.Wait() } -func (s *OpConductorTestSuite) updateStatusAndExecuteAction(ch chan bool, status bool) { +func updateStatusAndExecuteAction[T any](s *OpConductorTestSuite, ch chan T, status T) { fn := func() { ch <- status } - s.execute(fn) + s.execute(fn) // this executes status update + s.executeAction() +} + +func (s *OpConductorTestSuite) updateLeaderStatusAndExecuteAction(status bool) { + updateStatusAndExecuteAction[bool](s, s.leaderUpdateCh, status) +} + +func (s *OpConductorTestSuite) updateHealthStatusAndExecuteAction(status error) { + updateStatusAndExecuteAction[error](s, s.healthUpdateCh, status) } func (s *OpConductorTestSuite) executeAction() { @@ -165,15 +194,19 @@ func (s *OpConductorTestSuite) executeAction() { // Scenario 1: pause -> resume -> stop func (s *OpConductorTestSuite) TestControlLoop1() { + s.disableSynchronization() + // Pause err := s.conductor.Pause(s.ctx) s.NoError(err) s.True(s.conductor.Paused()) // Send health update, make sure it can still be consumed. - s.healthUpdateCh <- true + s.healthUpdateCh <- nil + s.healthUpdateCh <- nil // Resume + s.ctrl.EXPECT().SequencerActive(mock.Anything).Return(false, nil) err = s.conductor.Resume(s.ctx) s.NoError(err) s.False(s.conductor.Paused()) @@ -188,6 +221,8 @@ func (s *OpConductorTestSuite) TestControlLoop1() { // Scenario 2: pause -> pause -> resume -> resume func (s *OpConductorTestSuite) TestControlLoop2() { + s.disableSynchronization() + // Pause err := s.conductor.Pause(s.ctx) s.NoError(err) @@ -199,6 +234,7 @@ func (s *OpConductorTestSuite) TestControlLoop2() { s.True(s.conductor.Paused()) // Resume + s.ctrl.EXPECT().SequencerActive(mock.Anything).Return(false, nil) err = s.conductor.Resume(s.ctx) s.NoError(err) s.False(s.conductor.Paused()) @@ -218,6 +254,8 @@ func (s *OpConductorTestSuite) TestControlLoop2() { // Scenario 3: pause -> stop func (s *OpConductorTestSuite) TestControlLoop3() { + s.disableSynchronization() + // Pause err := s.conductor.Pause(s.ctx) s.NoError(err) @@ -231,7 +269,8 @@ func (s *OpConductorTestSuite) TestControlLoop3() { s.True(s.conductor.Stopped()) } -// In this test, we have a follower that is not healthy and not sequencing, it becomes leader through election and we expect it to transfer leadership to another node. +// In this test, we have a follower that is not healthy and not sequencing, it becomes leader through election. +// But since it does not have the same unsafe head as in consensus. We expect it to transfer leadership to another node. // [follower, not healthy, not sequencing] -- become leader --> [leader, not healthy, not sequencing] -- transfer leadership --> [follower, not healthy, not sequencing] func (s *OpConductorTestSuite) TestScenario1() { s.enableSynchronization() @@ -240,17 +279,42 @@ func (s *OpConductorTestSuite) TestScenario1() { s.conductor.leader.Store(false) s.conductor.healthy.Store(false) s.conductor.seqActive.Store(false) + s.conductor.hcerr = health.ErrSequencerNotHealthy + s.conductor.prevState = &state{ + leader: false, + healthy: false, + active: false, + } + // unsafe in consensus is different than unsafe in node. + mockPayload := ð.ExecutionPayloadEnvelope{ + ExecutionPayload: ð.ExecutionPayload{ + BlockNumber: 2, + BlockHash: [32]byte{4, 5, 6}, + }, + } + mockBlockInfo := &testutils.MockBlockInfo{ + InfoNum: 1, + InfoHash: [32]byte{1, 2, 3}, + } s.cons.EXPECT().TransferLeader().Return(nil) + s.cons.EXPECT().LatestUnsafePayload().Return(mockPayload).Times(1) + s.ctrl.EXPECT().LatestUnsafeBlock(mock.Anything).Return(mockBlockInfo, nil).Times(1) // become leader - s.updateStatusAndExecuteAction(s.leaderUpdateCh, true) + s.updateLeaderStatusAndExecuteAction(true) // expect to transfer leadership, go back to [follower, not healthy, not sequencing] s.False(s.conductor.leader.Load()) s.False(s.conductor.healthy.Load()) s.False(s.conductor.seqActive.Load()) - s.cons.AssertCalled(s.T(), "TransferLeader") + s.Equal(health.ErrSequencerNotHealthy, s.conductor.hcerr) + s.Equal(&state{ + leader: true, + healthy: false, + active: false, + }, s.conductor.prevState) + s.cons.AssertNumberOfCalls(s.T(), "TransferLeader", 1) } // In this test, we have a follower that is not healthy and not sequencing. it becomes healthy and we expect it to stay as follower and not start sequencing. @@ -264,7 +328,7 @@ func (s *OpConductorTestSuite) TestScenario2() { s.conductor.seqActive.Store(false) // become healthy - s.updateStatusAndExecuteAction(s.healthUpdateCh, true) + s.updateHealthStatusAndExecuteAction(nil) // expect to stay as follower, go to [follower, healthy, not sequencing] s.False(s.conductor.leader.Load()) @@ -299,7 +363,7 @@ func (s *OpConductorTestSuite) TestScenario3() { s.False(s.conductor.seqActive.Load()) // become leader - s.updateStatusAndExecuteAction(s.leaderUpdateCh, true) + s.updateLeaderStatusAndExecuteAction(true) // [leader, healthy, sequencing] s.True(s.conductor.leader.Load()) @@ -332,7 +396,7 @@ func (s *OpConductorTestSuite) TestScenario4() { s.ctrl.EXPECT().LatestUnsafeBlock(mock.Anything).Return(mockBlockInfo, nil).Times(1) s.ctrl.EXPECT().PostUnsafePayload(mock.Anything, mock.Anything).Return(nil).Times(1) - s.updateStatusAndExecuteAction(s.leaderUpdateCh, true) + s.updateLeaderStatusAndExecuteAction(true) // [leader, healthy, not sequencing] s.True(s.conductor.leader.Load()) @@ -373,7 +437,7 @@ func (s *OpConductorTestSuite) TestScenario5() { s.conductor.seqActive.Store(false) // become unhealthy - s.updateStatusAndExecuteAction(s.healthUpdateCh, false) + s.updateHealthStatusAndExecuteAction(health.ErrSequencerNotHealthy) // expect to stay as follower, go to [follower, not healthy, not sequencing] s.False(s.conductor.leader.Load()) @@ -394,7 +458,7 @@ func (s *OpConductorTestSuite) TestScenario6() { s.ctrl.EXPECT().StopSequencer(mock.Anything).Return(common.Hash{}, nil).Times(1) // step down as leader - s.updateStatusAndExecuteAction(s.leaderUpdateCh, false) + s.updateLeaderStatusAndExecuteAction(false) // expect to stay as follower, go to [follower, healthy, not sequencing] s.False(s.conductor.leader.Load()) @@ -418,7 +482,7 @@ func (s *OpConductorTestSuite) TestScenario7() { s.ctrl.EXPECT().StopSequencer(mock.Anything).Return(common.Hash{}, nil).Times(1) // become unhealthy - s.updateStatusAndExecuteAction(s.healthUpdateCh, false) + s.updateHealthStatusAndExecuteAction(health.ErrSequencerNotHealthy) // expect to step down as leader and stop sequencing s.False(s.conductor.leader.Load()) @@ -437,34 +501,50 @@ func (s *OpConductorTestSuite) TestScenario7() { // 5. [follower, unhealthy, not sequencing] func (s *OpConductorTestSuite) TestFailureAndRetry1() { s.enableSynchronization() - err := errors.New("failure") // set initial state s.conductor.leader.Store(true) s.conductor.healthy.Store(true) s.conductor.seqActive.Store(true) + s.conductor.prevState = &state{ + leader: true, + healthy: true, + active: true, + } // step 1 & 2: become unhealthy, stop sequencing failed, transfer leadership failed - s.cons.EXPECT().TransferLeader().Return(err).Times(1) - s.ctrl.EXPECT().StopSequencer(mock.Anything).Return(common.Hash{}, err).Times(1) + s.cons.EXPECT().TransferLeader().Return(s.err).Times(1) + s.ctrl.EXPECT().StopSequencer(mock.Anything).Return(common.Hash{}, s.err).Times(1) - s.updateStatusAndExecuteAction(s.healthUpdateCh, false) + s.updateHealthStatusAndExecuteAction(health.ErrSequencerNotHealthy) s.True(s.conductor.leader.Load()) s.False(s.conductor.healthy.Load()) s.True(s.conductor.seqActive.Load()) + s.Equal(health.ErrSequencerNotHealthy, s.conductor.hcerr) + s.Equal(&state{ + leader: true, + healthy: true, + active: true, + }, s.conductor.prevState) s.ctrl.AssertNumberOfCalls(s.T(), "StopSequencer", 1) s.cons.AssertNumberOfCalls(s.T(), "TransferLeader", 1) // step 3: [leader, unhealthy, sequencing] -- stop sequencing succeeded, transfer leadership failed, retry s.ctrl.EXPECT().StopSequencer(mock.Anything).Return(common.Hash{}, nil).Times(1) - s.cons.EXPECT().TransferLeader().Return(err).Times(1) + s.cons.EXPECT().TransferLeader().Return(s.err).Times(1) s.executeAction() s.True(s.conductor.leader.Load()) s.False(s.conductor.healthy.Load()) s.False(s.conductor.seqActive.Load()) + s.Equal(health.ErrSequencerNotHealthy, s.conductor.hcerr) + s.Equal(&state{ + leader: true, + healthy: true, + active: true, + }, s.conductor.prevState) s.ctrl.AssertNumberOfCalls(s.T(), "StopSequencer", 2) s.cons.AssertNumberOfCalls(s.T(), "TransferLeader", 2) @@ -477,6 +557,12 @@ func (s *OpConductorTestSuite) TestFailureAndRetry1() { s.False(s.conductor.leader.Load()) s.False(s.conductor.healthy.Load()) s.False(s.conductor.seqActive.Load()) + s.Equal(health.ErrSequencerNotHealthy, s.conductor.hcerr) + s.Equal(&state{ + leader: true, + healthy: false, + active: false, + }, s.conductor.prevState) s.ctrl.AssertNumberOfCalls(s.T(), "StopSequencer", 2) s.cons.AssertNumberOfCalls(s.T(), "TransferLeader", 3) } @@ -489,22 +575,32 @@ func (s *OpConductorTestSuite) TestFailureAndRetry1() { // 4. [follower, unhealthy, not sequencing] func (s *OpConductorTestSuite) TestFailureAndRetry2() { s.enableSynchronization() - err := errors.New("failure") // set initial state s.conductor.leader.Store(true) s.conductor.healthy.Store(true) s.conductor.seqActive.Store(true) + s.conductor.prevState = &state{ + leader: true, + healthy: true, + active: true, + } // step 1 & 2: become unhealthy, stop sequencing failed, transfer leadership succeeded, retry s.cons.EXPECT().TransferLeader().Return(nil).Times(1) - s.ctrl.EXPECT().StopSequencer(mock.Anything).Return(common.Hash{}, err).Times(1) + s.ctrl.EXPECT().StopSequencer(mock.Anything).Return(common.Hash{}, s.err).Times(1) - s.updateStatusAndExecuteAction(s.healthUpdateCh, false) + s.updateHealthStatusAndExecuteAction(health.ErrSequencerNotHealthy) s.False(s.conductor.leader.Load()) s.False(s.conductor.healthy.Load()) s.True(s.conductor.seqActive.Load()) + s.Equal(health.ErrSequencerNotHealthy, s.conductor.hcerr) + s.Equal(&state{ + leader: true, + healthy: true, + active: true, + }, s.conductor.prevState) s.ctrl.AssertNumberOfCalls(s.T(), "StopSequencer", 1) s.cons.AssertNumberOfCalls(s.T(), "TransferLeader", 1) @@ -516,10 +612,109 @@ func (s *OpConductorTestSuite) TestFailureAndRetry2() { s.False(s.conductor.leader.Load()) s.False(s.conductor.healthy.Load()) s.False(s.conductor.seqActive.Load()) + s.Equal(&state{ + leader: false, + healthy: false, + active: true, + }, s.conductor.prevState) s.ctrl.AssertNumberOfCalls(s.T(), "StopSequencer", 2) s.cons.AssertNumberOfCalls(s.T(), "TransferLeader", 1) } +// In this test, we have a follower that is unhealthy (due to active sequencer not producing blocks) +// Then leadership transfer happened, and the follower became leader. We expect it to start sequencing and catch up eventually. +// 1. [follower, healthy, not sequencing] -- become unhealthy --> +// 2. [follower, unhealthy, not sequencing] -- gained leadership --> +// 3. [leader, unhealthy, not sequencing] -- start sequencing --> +// 4. [leader, unhealthy, sequencing] -> become healthy again --> +// 5. [leader, healthy, sequencing] +func (s *OpConductorTestSuite) TestFailureAndRetry3() { + s.enableSynchronization() + + // set initial state, healthy follower + s.conductor.leader.Store(false) + s.conductor.healthy.Store(true) + s.conductor.seqActive.Store(false) + s.conductor.prevState = &state{ + leader: false, + healthy: true, + active: false, + } + + s.log.Info("1. become unhealthy") + s.updateHealthStatusAndExecuteAction(health.ErrSequencerNotHealthy) + + s.False(s.conductor.leader.Load()) + s.False(s.conductor.healthy.Load()) + s.False(s.conductor.seqActive.Load()) + s.Equal(&state{ + leader: false, + healthy: false, + active: false, + }, s.conductor.prevState) + + s.log.Info("2 & 3. gained leadership, start sequencing") + mockPayload := ð.ExecutionPayloadEnvelope{ + ExecutionPayload: ð.ExecutionPayload{ + BlockNumber: 1, + BlockHash: [32]byte{1, 2, 3}, + }, + } + mockBlockInfo := &testutils.MockBlockInfo{ + InfoNum: 1, + InfoHash: [32]byte{1, 2, 3}, + } + s.cons.EXPECT().LatestUnsafePayload().Return(mockPayload).Times(2) + s.ctrl.EXPECT().LatestUnsafeBlock(mock.Anything).Return(mockBlockInfo, nil).Times(2) + s.ctrl.EXPECT().StartSequencer(mock.Anything, mockBlockInfo.InfoHash).Return(nil).Times(1) + + s.updateLeaderStatusAndExecuteAction(true) + + s.True(s.conductor.leader.Load()) + s.False(s.conductor.healthy.Load()) + s.True(s.conductor.seqActive.Load()) + s.Equal(&state{ + leader: true, + healthy: false, + active: false, + }, s.conductor.prevState) + s.cons.AssertNumberOfCalls(s.T(), "LatestUnsafePayload", 2) + s.ctrl.AssertNumberOfCalls(s.T(), "LatestUnsafeBlock", 2) + s.ctrl.AssertNumberOfCalls(s.T(), "StartSequencer", 1) + + s.log.Info("4. stay unhealthy for a bit while catching up") + s.updateHealthStatusAndExecuteAction(health.ErrSequencerNotHealthy) + + s.True(s.conductor.leader.Load()) + s.False(s.conductor.healthy.Load()) + s.True(s.conductor.seqActive.Load()) + s.Equal(&state{ + leader: true, + healthy: false, + active: false, + }, s.conductor.prevState) + + s.log.Info("5. become healthy again") + s.updateHealthStatusAndExecuteAction(nil) + + // need to use eventually here because starting from step 4, the loop is gonna queue an action and retry until it became healthy again. + // use eventually here avoids the situation where health update is consumed after the action is executed. + s.Eventually(func() bool { + res := s.conductor.leader.Load() == true && + s.conductor.healthy.Load() == true && + s.conductor.seqActive.Load() == true && + s.conductor.prevState.Equal(&state{ + leader: true, + healthy: true, + active: true, + }) + if !res { + s.executeAction() + } + return res + }, 2*time.Second, 100*time.Millisecond) +} + func (s *OpConductorTestSuite) TestHandleInitError() { // This will cause an error in the init function, which should cause the conductor to stop successfully without issues. _, err := New(s.ctx, &s.cfg, s.log, s.version) @@ -528,6 +723,6 @@ func (s *OpConductorTestSuite) TestHandleInitError() { s.False(ok) } -func TestHealthMonitor(t *testing.T) { +func TestControlLoop(t *testing.T) { suite.Run(t, new(OpConductorTestSuite)) } diff --git a/op-conductor/consensus/iface.go b/op-conductor/consensus/iface.go index bfba969bbe08..7134eef5a273 100644 --- a/op-conductor/consensus/iface.go +++ b/op-conductor/consensus/iface.go @@ -4,13 +4,41 @@ import ( "github.com/ethereum-optimism/optimism/op-service/eth" ) +// ServerSuffrage determines whether a Server in a Configuration gets a vote. +type ServerSuffrage int + +const ( + // Voter is a server whose vote is counted in elections. + Voter ServerSuffrage = iota + // Nonvoter is a server that receives log entries but is not considered for + // elections or commitment purposes. + Nonvoter +) + +func (s ServerSuffrage) String() string { + switch s { + case Voter: + return "Voter" + case Nonvoter: + return "Nonvoter" + } + return "ServerSuffrage" +} + +// ServerInfo defines the server information. +type ServerInfo struct { + ID string `json:"id"` + Addr string `json:"addr"` + Suffrage ServerSuffrage `json:"suffrage"` +} + // Consensus defines the consensus interface for leadership election. // //go:generate mockery --name Consensus --output mocks/ --with-expecter=true type Consensus interface { - // AddVoter adds a voting member into the cluster, voter is elegible to become leader. + // AddVoter adds a voting member into the cluster, voter is eligible to become leader. AddVoter(id, addr string) error - // AddNonVoter adds a non-voting member into the cluster, non-voter is not elegible to become leader. + // AddNonVoter adds a non-voting member into the cluster, non-voter is not eligible to become leader. AddNonVoter(id, addr string) error // DemoteVoter demotes a voting member into a non-voting member, if leader is being demoted, it will cause a new leader election. DemoteVoter(id string) error @@ -21,13 +49,15 @@ type Consensus interface { // Leader returns if it is the leader of the cluster. Leader() bool // LeaderWithID returns the leader's server ID and address. - LeaderWithID() (string, string) + LeaderWithID() *ServerInfo // ServerID returns the server ID of the consensus. ServerID() string // TransferLeader triggers leadership transfer to another member in the cluster. TransferLeader() error // TransferLeaderTo triggers leadership transfer to a specific member in the cluster. TransferLeaderTo(id, addr string) error + // ClusterMembership returns the current cluster membership configuration. + ClusterMembership() ([]*ServerInfo, error) // CommitPayload commits latest unsafe payload to the FSM. CommitUnsafePayload(payload *eth.ExecutionPayloadEnvelope) error diff --git a/op-conductor/consensus/mocks/Consensus.go b/op-conductor/consensus/mocks/Consensus.go index 7c2221792628..e85ad0410013 100644 --- a/op-conductor/consensus/mocks/Consensus.go +++ b/op-conductor/consensus/mocks/Consensus.go @@ -3,7 +3,9 @@ package mocks import ( + consensus "github.com/ethereum-optimism/optimism/op-conductor/consensus" eth "github.com/ethereum-optimism/optimism/op-service/eth" + mock "github.com/stretchr/testify/mock" ) @@ -114,6 +116,63 @@ func (_c *Consensus_AddVoter_Call) RunAndReturn(run func(string, string) error) return _c } +// ClusterMembership provides a mock function with given fields: +func (_m *Consensus) ClusterMembership() ([]*consensus.ServerInfo, error) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for ClusterMembership") + } + + var r0 []*consensus.ServerInfo + var r1 error + if rf, ok := ret.Get(0).(func() ([]*consensus.ServerInfo, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() []*consensus.ServerInfo); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*consensus.ServerInfo) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Consensus_ClusterMembership_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClusterMembership' +type Consensus_ClusterMembership_Call struct { + *mock.Call +} + +// ClusterMembership is a helper method to define mock.On call +func (_e *Consensus_Expecter) ClusterMembership() *Consensus_ClusterMembership_Call { + return &Consensus_ClusterMembership_Call{Call: _e.mock.On("ClusterMembership")} +} + +func (_c *Consensus_ClusterMembership_Call) Run(run func()) *Consensus_ClusterMembership_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Consensus_ClusterMembership_Call) Return(_a0 []*consensus.ServerInfo, _a1 error) *Consensus_ClusterMembership_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *Consensus_ClusterMembership_Call) RunAndReturn(run func() ([]*consensus.ServerInfo, error)) *Consensus_ClusterMembership_Call { + _c.Call.Return(run) + return _c +} + // CommitUnsafePayload provides a mock function with given fields: payload func (_m *Consensus) CommitUnsafePayload(payload *eth.ExecutionPayloadEnvelope) error { ret := _m.Called(payload) @@ -346,31 +405,23 @@ func (_c *Consensus_LeaderCh_Call) RunAndReturn(run func() <-chan bool) *Consens } // LeaderWithID provides a mock function with given fields: -func (_m *Consensus) LeaderWithID() (string, string) { +func (_m *Consensus) LeaderWithID() *consensus.ServerInfo { ret := _m.Called() if len(ret) == 0 { panic("no return value specified for LeaderWithID") } - var r0 string - var r1 string - if rf, ok := ret.Get(0).(func() (string, string)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() string); ok { + var r0 *consensus.ServerInfo + if rf, ok := ret.Get(0).(func() *consensus.ServerInfo); ok { r0 = rf() } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func() string); ok { - r1 = rf() - } else { - r1 = ret.Get(1).(string) + if ret.Get(0) != nil { + r0 = ret.Get(0).(*consensus.ServerInfo) + } } - return r0, r1 + return r0 } // Consensus_LeaderWithID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LeaderWithID' @@ -390,12 +441,12 @@ func (_c *Consensus_LeaderWithID_Call) Run(run func()) *Consensus_LeaderWithID_C return _c } -func (_c *Consensus_LeaderWithID_Call) Return(_a0 string, _a1 string) *Consensus_LeaderWithID_Call { - _c.Call.Return(_a0, _a1) +func (_c *Consensus_LeaderWithID_Call) Return(_a0 *consensus.ServerInfo) *Consensus_LeaderWithID_Call { + _c.Call.Return(_a0) return _c } -func (_c *Consensus_LeaderWithID_Call) RunAndReturn(run func() (string, string)) *Consensus_LeaderWithID_Call { +func (_c *Consensus_LeaderWithID_Call) RunAndReturn(run func() *consensus.ServerInfo) *Consensus_LeaderWithID_Call { _c.Call.Return(run) return _c } diff --git a/op-conductor/consensus/raft.go b/op-conductor/consensus/raft.go index 9d3c832a1647..37d9ac69d70a 100644 --- a/op-conductor/consensus/raft.go +++ b/op-conductor/consensus/raft.go @@ -83,7 +83,7 @@ func NewRaftConsensus(log log.Logger, serverID, serverAddr, storageDir string, b return nil, errors.Wrap(err, "failed to create raft") } - // If boostrap = true, start raft in bootstrap mode, this will allow the current node to elect itself as leader when there's no other participants + // If bootstrap = true, start raft in bootstrap mode, this will allow the current node to elect itself as leader when there's no other participants // and allow other nodes to join the cluster. if bootstrap { cfg := raft.Configuration{ @@ -145,9 +145,13 @@ func (rc *RaftConsensus) Leader() bool { } // LeaderWithID implements Consensus, it returns the leader's server ID and address. -func (rc *RaftConsensus) LeaderWithID() (string, string) { +func (rc *RaftConsensus) LeaderWithID() *ServerInfo { addr, id := rc.r.LeaderWithID() - return string(id), string(addr) + return &ServerInfo{ + ID: string(id), + Addr: string(addr), + Suffrage: Voter, // leader will always be Voter + } } // LeaderCh implements Consensus, it returns a channel that will be notified when leadership status changes (true = leader, false = follower). @@ -221,3 +225,21 @@ func (rc *RaftConsensus) LatestUnsafePayload() *eth.ExecutionPayloadEnvelope { payload := rc.unsafeTracker.UnsafeHead() return payload } + +// ClusterMembership implements Consensus, it returns the current cluster membership configuration. +func (rc *RaftConsensus) ClusterMembership() ([]*ServerInfo, error) { + var future raft.ConfigurationFuture + if future = rc.r.GetConfiguration(); future.Error() != nil { + return nil, future.Error() + } + + var servers []*ServerInfo + for _, srv := range future.Configuration().Servers { + servers = append(servers, &ServerInfo{ + ID: string(srv.ID), + Addr: string(srv.Address), + Suffrage: ServerSuffrage(srv.Suffrage), + }) + } + return servers, nil +} diff --git a/op-conductor/consensus/raft_test.go b/op-conductor/consensus/raft_test.go index d5a4b66d2072..775e0a77847f 100644 --- a/op-conductor/consensus/raft_test.go +++ b/op-conductor/consensus/raft_test.go @@ -17,7 +17,7 @@ import ( ) func TestCommitAndRead(t *testing.T) { - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) serverID := "SequencerA" serverAddr := "127.0.0.1:0" bootstrap := true diff --git a/op-conductor/flags/flags.go b/op-conductor/flags/flags.go index fff6e34cb31a..c16de5c645db 100644 --- a/op-conductor/flags/flags.go +++ b/op-conductor/flags/flags.go @@ -28,6 +28,12 @@ var ( EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "CONSENSUS_PORT"), Value: 50050, } + RaftBootstrap = &cli.BoolFlag{ + Name: "raft.bootstrap", + Usage: "If this node should bootstrap a new raft cluster", + EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "RAFT_BOOTSTRAP"), + Value: false, + } RaftServerID = &cli.StringFlag{ Name: "raft.server.id", Usage: "Unique ID for this server used by raft consensus", @@ -53,6 +59,11 @@ var ( Usage: "Interval between health checks", EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "HEALTHCHECK_INTERVAL"), } + HealthCheckUnsafeInterval = &cli.Uint64Flag{ + Name: "healthcheck.unsafe-interval", + Usage: "Interval allowed between unsafe head and now measured in seconds", + EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "HEALTHCHECK_UNSAFE_INTERVAL"), + } HealthCheckSafeInterval = &cli.Uint64Flag{ Name: "healthcheck.safe-interval", Usage: "Interval between safe head progression measured in seconds", @@ -85,6 +96,7 @@ var requiredFlags = []cli.Flag{ NodeRPC, ExecutionRPC, HealthCheckInterval, + HealthCheckUnsafeInterval, HealthCheckSafeInterval, HealthCheckMinPeerCount, } @@ -92,6 +104,7 @@ var requiredFlags = []cli.Flag{ var optionalFlags = []cli.Flag{ Paused, RPCEnableProxy, + RaftBootstrap, } func init() { @@ -99,7 +112,7 @@ func init() { optionalFlags = append(optionalFlags, oplog.CLIFlags(EnvVarPrefix)...) optionalFlags = append(optionalFlags, opmetrics.CLIFlags(EnvVarPrefix)...) optionalFlags = append(optionalFlags, oppprof.CLIFlags(EnvVarPrefix)...) - optionalFlags = append(optionalFlags, opflags.CLIFlags(EnvVarPrefix)...) + optionalFlags = append(optionalFlags, opflags.CLIFlags(EnvVarPrefix, "")...) Flags = append(requiredFlags, optionalFlags...) } diff --git a/op-conductor/health/mocks/HealthMonitor.go b/op-conductor/health/mocks/HealthMonitor.go index 4da01e90176c..de85b716f739 100644 --- a/op-conductor/health/mocks/HealthMonitor.go +++ b/op-conductor/health/mocks/HealthMonitor.go @@ -108,19 +108,19 @@ func (_c *HealthMonitor_Stop_Call) RunAndReturn(run func() error) *HealthMonitor } // Subscribe provides a mock function with given fields: -func (_m *HealthMonitor) Subscribe() <-chan bool { +func (_m *HealthMonitor) Subscribe() <-chan error { ret := _m.Called() if len(ret) == 0 { panic("no return value specified for Subscribe") } - var r0 <-chan bool - if rf, ok := ret.Get(0).(func() <-chan bool); ok { + var r0 <-chan error + if rf, ok := ret.Get(0).(func() <-chan error); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(<-chan bool) + r0 = ret.Get(0).(<-chan error) } } @@ -144,12 +144,12 @@ func (_c *HealthMonitor_Subscribe_Call) Run(run func()) *HealthMonitor_Subscribe return _c } -func (_c *HealthMonitor_Subscribe_Call) Return(_a0 <-chan bool) *HealthMonitor_Subscribe_Call { +func (_c *HealthMonitor_Subscribe_Call) Return(_a0 <-chan error) *HealthMonitor_Subscribe_Call { _c.Call.Return(_a0) return _c } -func (_c *HealthMonitor_Subscribe_Call) RunAndReturn(run func() <-chan bool) *HealthMonitor_Subscribe_Call { +func (_c *HealthMonitor_Subscribe_Call) RunAndReturn(run func() <-chan error) *HealthMonitor_Subscribe_Call { _c.Call.Return(run) return _c } diff --git a/op-conductor/health/monitor.go b/op-conductor/health/monitor.go index 2bbae66238b5..7a541e7b3876 100644 --- a/op-conductor/health/monitor.go +++ b/op-conductor/health/monitor.go @@ -2,6 +2,7 @@ package health import ( "context" + "errors" "sync" "time" @@ -12,12 +13,17 @@ import ( "github.com/ethereum-optimism/optimism/op-service/dial" ) +var ( + ErrSequencerNotHealthy = errors.New("sequencer is not healthy") + ErrSequencerConnectionDown = errors.New("cannot connect to sequencer rpc endpoints") +) + // HealthMonitor defines the interface for monitoring the health of the sequencer. // //go:generate mockery --name HealthMonitor --output mocks/ --with-expecter=true type HealthMonitor interface { // Subscribe returns a channel that will be notified for every health check. - Subscribe() <-chan bool + Subscribe() <-chan error // Start starts the health check. Start() error // Stop stops the health check. @@ -28,15 +34,17 @@ type HealthMonitor interface { // interval is the interval between health checks measured in seconds. // safeInterval is the interval between safe head progress measured in seconds. // minPeerCount is the minimum number of peers required for the sequencer to be healthy. -func NewSequencerHealthMonitor(log log.Logger, interval, safeInterval, minPeerCount uint64, rollupCfg *rollup.Config, node dial.RollupClientInterface, p2p p2p.API) HealthMonitor { +func NewSequencerHealthMonitor(log log.Logger, interval, unsafeInterval, safeInterval, minPeerCount uint64, rollupCfg *rollup.Config, node dial.RollupClientInterface, p2p p2p.API) HealthMonitor { return &SequencerHealthMonitor{ log: log, done: make(chan struct{}), interval: interval, - healthUpdateCh: make(chan bool), + healthUpdateCh: make(chan error), rollupCfg: rollupCfg, + unsafeInterval: unsafeInterval, safeInterval: safeInterval, minPeerCount: minPeerCount, + timeProviderFn: currentTimeProvicer, node: node, p2p: p2p, } @@ -48,11 +56,16 @@ type SequencerHealthMonitor struct { done chan struct{} wg sync.WaitGroup - rollupCfg *rollup.Config - safeInterval uint64 - minPeerCount uint64 - interval uint64 - healthUpdateCh chan bool + rollupCfg *rollup.Config + unsafeInterval uint64 + safeInterval uint64 + minPeerCount uint64 + interval uint64 + healthUpdateCh chan error + lastSeenUnsafeNum uint64 + lastSeenUnsafeTime uint64 + + timeProviderFn func() uint64 node dial.RollupClientInterface p2p p2p.API @@ -81,7 +94,7 @@ func (hm *SequencerHealthMonitor) Stop() error { } // Subscribe implements HealthMonitor. -func (hm *SequencerHealthMonitor) Subscribe() <-chan bool { +func (hm *SequencerHealthMonitor) Subscribe() <-chan error { return hm.healthUpdateCh } @@ -104,37 +117,82 @@ func (hm *SequencerHealthMonitor) loop() { // healthCheck checks the health of the sequencer by 3 criteria: // 1. unsafe head is progressing per block time -// 2. safe head is progressing every configured batch submission interval -// 3. peer count is above the configured minimum -func (hm *SequencerHealthMonitor) healthCheck() bool { +// 2. unsafe head is not too far behind now (measured by unsafeInterval) +// 3. safe head is progressing every configured batch submission interval +// 4. peer count is above the configured minimum +func (hm *SequencerHealthMonitor) healthCheck() error { ctx := context.Background() status, err := hm.node.SyncStatus(ctx) if err != nil { hm.log.Error("health monitor failed to get sync status", "err", err) - return false + return ErrSequencerConnectionDown + } + + now := hm.timeProviderFn() + + var timeDiff, blockDiff, expectedBlocks uint64 + if hm.lastSeenUnsafeNum != 0 { + timeDiff = now - hm.lastSeenUnsafeTime + blockDiff = status.UnsafeL2.Number - hm.lastSeenUnsafeNum + // how many blocks do we expect to see, minus 1 to account for edge case with respect to time. + // for example, if diff = 2.001s and block time = 2s, expecting to see 1 block could potentially cause sequencer to be considered unhealthy. + expectedBlocks = timeDiff / hm.rollupCfg.BlockTime + if expectedBlocks > 0 { + expectedBlocks-- + } + } + if status.UnsafeL2.Number > hm.lastSeenUnsafeNum { + hm.lastSeenUnsafeNum = status.UnsafeL2.Number + hm.lastSeenUnsafeTime = now + } + + if timeDiff > hm.rollupCfg.BlockTime && expectedBlocks > blockDiff { + hm.log.Error( + "unsafe head is not progressing as expected", + "now", now, + "unsafe_head_num", status.UnsafeL2.Number, + "last_seen_unsafe_num", hm.lastSeenUnsafeNum, + "last_seen_unsafe_time", hm.lastSeenUnsafeTime, + "unsafe_interval", hm.unsafeInterval, + ) + return ErrSequencerNotHealthy } - now := uint64(time.Now().Unix()) - // allow at most one block drift for unsafe head - if now-status.UnsafeL2.Time > hm.interval+hm.rollupCfg.BlockTime { - hm.log.Error("unsafe head is not progressing", "lastSeenUnsafeBlock", status.UnsafeL2) - return false + if now-status.UnsafeL2.Time > hm.unsafeInterval { + hm.log.Error( + "unsafe head is not progressing as expected", + "now", now, + "unsafe_head_num", status.UnsafeL2.Number, + "unsafe_head_time", status.UnsafeL2.Time, + "unsafe_interval", hm.unsafeInterval, + ) + return ErrSequencerNotHealthy } if now-status.SafeL2.Time > hm.safeInterval { - hm.log.Error("safe head is not progressing", "safe_head_time", status.SafeL2.Time, "now", now) - return false + hm.log.Error( + "safe head is not progressing as expected", + "now", now, + "safe_head_num", status.SafeL2.Number, + "safe_head_time", status.SafeL2.Time, + "safe_interval", hm.safeInterval, + ) + return ErrSequencerNotHealthy } stats, err := hm.p2p.PeerStats(ctx) if err != nil { hm.log.Error("health monitor failed to get peer stats", "err", err) - return false + return ErrSequencerConnectionDown } if uint64(stats.Connected) < hm.minPeerCount { hm.log.Error("peer count is below minimum", "connected", stats.Connected, "minPeerCount", hm.minPeerCount) - return false + return ErrSequencerNotHealthy } - return true + return nil +} + +func currentTimeProvicer() uint64 { + return uint64(time.Now().Unix()) } diff --git a/op-conductor/health/monitor_test.go b/op-conductor/health/monitor_test.go index 8cb96aab3c5c..0384e5b4b0b5 100644 --- a/op-conductor/health/monitor_test.go +++ b/op-conductor/health/monitor_test.go @@ -27,125 +27,191 @@ type HealthMonitorTestSuite struct { suite.Suite log log.Logger - rc *testutils.MockRollupClient - pc *p2pMocks.API interval uint64 - safeInterval uint64 minPeerCount uint64 rollupCfg *rollup.Config - monitor HealthMonitor } func (s *HealthMonitorTestSuite) SetupSuite() { - s.log = testlog.Logger(s.T(), log.LvlInfo) - s.rc = &testutils.MockRollupClient{} - s.pc = &p2pMocks.API{} + s.log = testlog.Logger(s.T(), log.LevelDebug) s.interval = 1 - s.safeInterval = 5 s.minPeerCount = minPeerCount s.rollupCfg = &rollup.Config{ BlockTime: blockTime, } } -func (s *HealthMonitorTestSuite) SetupTest() { - s.monitor = NewSequencerHealthMonitor(s.log, s.interval, s.safeInterval, s.minPeerCount, s.rollupCfg, s.rc, s.pc) - err := s.monitor.Start() - s.NoError(err) -} - -func (s *HealthMonitorTestSuite) TearDownTest() { - err := s.monitor.Stop() +func (s *HealthMonitorTestSuite) SetupMonitor( + now, unsafeInterval, safeInterval uint64, + mockRollupClient *testutils.MockRollupClient, + mockP2P *p2pMocks.API, +) *SequencerHealthMonitor { + tp := &timeProvider{now: now} + if mockP2P == nil { + mockP2P = &p2pMocks.API{} + ps1 := &p2p.PeerStats{ + Connected: healthyPeerCount, + } + mockP2P.EXPECT().PeerStats(context.Background()).Return(ps1, nil) + } + monitor := &SequencerHealthMonitor{ + log: s.log, + done: make(chan struct{}), + interval: s.interval, + healthUpdateCh: make(chan error), + rollupCfg: s.rollupCfg, + unsafeInterval: unsafeInterval, + safeInterval: safeInterval, + minPeerCount: s.minPeerCount, + timeProviderFn: tp.Now, + node: mockRollupClient, + p2p: mockP2P, + } + err := monitor.Start() s.NoError(err) + return monitor } func (s *HealthMonitorTestSuite) TestUnhealthyLowPeerCount() { + s.T().Parallel() now := uint64(time.Now().Unix()) - ss1 := ð.SyncStatus{ - UnsafeL2: eth.L2BlockRef{ - Time: now - 1, - }, - SafeL2: eth.L2BlockRef{ - Time: now - 2, - }, - } - s.rc.ExpectSyncStatus(ss1, nil) + rc := &testutils.MockRollupClient{} + ss1 := mockSyncStatus(now-1, 1, now-3, 0) + rc.ExpectSyncStatus(ss1, nil) + rc.ExpectSyncStatus(ss1, nil) + + pc := &p2pMocks.API{} ps1 := &p2p.PeerStats{ Connected: unhealthyPeerCount, } - s.pc.EXPECT().PeerStats(context.Background()).Return(ps1, nil).Times(1) + pc.EXPECT().PeerStats(context.Background()).Return(ps1, nil).Times(1) + + monitor := s.SetupMonitor(now, 60, 60, rc, pc) - healthUpdateCh := s.monitor.Subscribe() + healthUpdateCh := monitor.Subscribe() healthy := <-healthUpdateCh - s.False(healthy) + s.NotNil(healthy) + + s.NoError(monitor.Stop()) } func (s *HealthMonitorTestSuite) TestUnhealthyUnsafeHeadNotProgressing() { - ps1 := &p2p.PeerStats{ - Connected: healthyPeerCount, - } - s.pc.EXPECT().PeerStats(context.Background()).Return(ps1, nil).Times(3) - + s.T().Parallel() now := uint64(time.Now().Unix()) - ss1 := ð.SyncStatus{ - UnsafeL2: eth.L2BlockRef{ - Time: now - 1, - }, - SafeL2: eth.L2BlockRef{ - Time: now - 2, - }, + + rc := &testutils.MockRollupClient{} + ss1 := mockSyncStatus(now, 5, now-8, 1) + for i := 0; i < 6; i++ { + rc.ExpectSyncStatus(ss1, nil) } - s.rc.ExpectSyncStatus(ss1, nil) - s.rc.ExpectSyncStatus(ss1, nil) - s.rc.ExpectSyncStatus(ss1, nil) - healthUpdateCh := s.monitor.Subscribe() - for i := 0; i < 3; i++ { + monitor := s.SetupMonitor(now, 60, 60, rc, nil) + healthUpdateCh := monitor.Subscribe() + + for i := 0; i < 5; i++ { healthy := <-healthUpdateCh - if i < 2 { - s.True(healthy) + if i < 4 { + s.Nil(healthy) + s.Equal(now, monitor.lastSeenUnsafeTime) + s.Equal(uint64(5), monitor.lastSeenUnsafeNum) } else { - s.False(healthy) + s.NotNil(healthy) } } + + s.NoError(monitor.Stop()) } func (s *HealthMonitorTestSuite) TestUnhealthySafeHeadNotProgressing() { - ps1 := &p2p.PeerStats{ - Connected: healthyPeerCount, - } - s.pc.EXPECT().PeerStats(context.Background()).Return(ps1, nil).Times(6) - + s.T().Parallel() now := uint64(time.Now().Unix()) - syncStatusGenerator := func(unsafeTime uint64) *eth.SyncStatus { - return ð.SyncStatus{ - UnsafeL2: eth.L2BlockRef{ - Time: unsafeTime, - }, - SafeL2: eth.L2BlockRef{ - Time: now, - }, - } - } - s.rc.ExpectSyncStatus(syncStatusGenerator(now), nil) - s.rc.ExpectSyncStatus(syncStatusGenerator(now), nil) - s.rc.ExpectSyncStatus(syncStatusGenerator(now+2), nil) - s.rc.ExpectSyncStatus(syncStatusGenerator(now+2), nil) - s.rc.ExpectSyncStatus(syncStatusGenerator(now+4), nil) - s.rc.ExpectSyncStatus(syncStatusGenerator(now+4), nil) - - healthUpdateCh := s.monitor.Subscribe() - for i := 0; i < 6; i++ { + + rc := &testutils.MockRollupClient{} + rc.ExpectSyncStatus(mockSyncStatus(now, 1, now, 1), nil) + rc.ExpectSyncStatus(mockSyncStatus(now, 1, now, 1), nil) + rc.ExpectSyncStatus(mockSyncStatus(now+2, 2, now, 1), nil) + rc.ExpectSyncStatus(mockSyncStatus(now+2, 2, now, 1), nil) + rc.ExpectSyncStatus(mockSyncStatus(now+4, 3, now, 1), nil) + rc.ExpectSyncStatus(mockSyncStatus(now+4, 3, now, 1), nil) + + monitor := s.SetupMonitor(now, 60, 3, rc, nil) + healthUpdateCh := monitor.Subscribe() + + for i := 0; i < 5; i++ { healthy := <-healthUpdateCh - if i < 5 { - s.True(healthy) + if i < 4 { + s.Nil(healthy) } else { - s.False(healthy) + s.NotNil(healthy) } } + + s.NoError(monitor.Stop()) +} + +func (s *HealthMonitorTestSuite) TestHealthyWithUnsafeLag() { + s.T().Parallel() + now := uint64(time.Now().Unix()) + + rc := &testutils.MockRollupClient{} + // although unsafe has lag of 20 seconds, it's within the configured unsafe interval + // and it is advancing every block time, so it should be considered safe. + rc.ExpectSyncStatus(mockSyncStatus(now-10, 1, now, 1), nil) + rc.ExpectSyncStatus(mockSyncStatus(now-10, 1, now, 1), nil) + rc.ExpectSyncStatus(mockSyncStatus(now-8, 2, now, 1), nil) + rc.ExpectSyncStatus(mockSyncStatus(now-8, 2, now, 1), nil) + + monitor := s.SetupMonitor(now, 60, 60, rc, nil) + healthUpdateCh := monitor.Subscribe() + + // confirm initial state + s.Zero(monitor.lastSeenUnsafeNum) + s.Zero(monitor.lastSeenUnsafeTime) + + // confirm state after first check + healthy := <-healthUpdateCh + s.Nil(healthy) + lastSeenUnsafeTime := monitor.lastSeenUnsafeTime + s.NotZero(monitor.lastSeenUnsafeTime) + s.Equal(uint64(1), monitor.lastSeenUnsafeNum) + + healthy = <-healthUpdateCh + s.Nil(healthy) + s.Equal(lastSeenUnsafeTime, monitor.lastSeenUnsafeTime) + s.Equal(uint64(1), monitor.lastSeenUnsafeNum) + + healthy = <-healthUpdateCh + s.Nil(healthy) + s.Equal(lastSeenUnsafeTime+2, monitor.lastSeenUnsafeTime) + s.Equal(uint64(2), monitor.lastSeenUnsafeNum) + + s.NoError(monitor.Stop()) +} + +func mockSyncStatus(unsafeTime, unsafeNum, safeTime, safeNum uint64) *eth.SyncStatus { + return ð.SyncStatus{ + UnsafeL2: eth.L2BlockRef{ + Time: unsafeTime, + Number: unsafeNum, + }, + SafeL2: eth.L2BlockRef{ + Time: safeTime, + Number: safeNum, + }, + } } func TestHealthMonitor(t *testing.T) { suite.Run(t, new(HealthMonitorTestSuite)) } + +type timeProvider struct { + now uint64 +} + +func (tp *timeProvider) Now() uint64 { + now := tp.now + tp.now++ + return now +} diff --git a/op-conductor/rpc/api.go b/op-conductor/rpc/api.go index 6e04939fbfb8..4d85d6fe17fd 100644 --- a/op-conductor/rpc/api.go +++ b/op-conductor/rpc/api.go @@ -3,20 +3,15 @@ package rpc import ( "context" "errors" - "math/big" + "github.com/ethereum/go-ethereum/rpc" + + "github.com/ethereum-optimism/optimism/op-conductor/consensus" + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum/go-ethereum/core/types" ) -var ( - ErrNotLeader = errors.New("refusing to proxy request to non-leader sequencer") -) - -type ServerInfo struct { - ID string `json:"id"` - Addr string `json:"addr"` -} +var ErrNotLeader = errors.New("refusing to proxy request to non-leader sequencer") // API defines the interface for the op-conductor API. type API interface { @@ -31,7 +26,7 @@ type API interface { // Leader returns true if the server is the leader. Leader(ctx context.Context) (bool, error) // LeaderWithID returns the current leader's server info. - LeaderWithID(ctx context.Context) (*ServerInfo, error) + LeaderWithID(ctx context.Context) (*consensus.ServerInfo, error) // AddServerAsVoter adds a server as a voter to the cluster. AddServerAsVoter(ctx context.Context, id string, addr string) error // AddServerAsNonvoter adds a server as a non-voter to the cluster. non-voter will not participate in leader election. @@ -42,24 +37,32 @@ type API interface { TransferLeader(ctx context.Context) error // TransferLeaderToServer transfers leadership to a specific server. TransferLeaderToServer(ctx context.Context, id string, addr string) error + // ClusterMembership returns the current cluster membership configuration. + ClusterMembership(ctx context.Context) ([]*consensus.ServerInfo, error) // APIs called by op-node // Active returns true if op-conductor is active. Active(ctx context.Context) (bool, error) - // CommitUnsafePayload commits a unsafe payload (lastest head) to the consensus layer. + // CommitUnsafePayload commits a unsafe payload (latest head) to the consensus layer. CommitUnsafePayload(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) error } // ExecutionProxyAPI defines the methods proxied to the execution rpc backend // This should include all methods that are called by op-batcher or op-proposer type ExecutionProxyAPI interface { - BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) + GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) } // NodeProxyAPI defines the methods proxied to the node rpc backend // This should include all methods that are called by op-batcher or op-proposer type NodeProxyAPI interface { OutputAtBlock(ctx context.Context, blockNum uint64) (*eth.OutputResponse, error) - SequencerActive(ctx context.Context) (bool, error) SyncStatus(ctx context.Context) (*eth.SyncStatus, error) + RollupConfig(ctx context.Context) (*rollup.Config, error) +} + +// NodeProxyAPI defines the methods proxied to the node rpc backend +// This should include all methods that are called by op-batcher or op-proposer +type NodeAdminProxyAPI interface { + SequencerActive(ctx context.Context) (bool, error) } diff --git a/op-conductor/rpc/backend.go b/op-conductor/rpc/backend.go index a320d540e69b..64c2635da9c6 100644 --- a/op-conductor/rpc/backend.go +++ b/op-conductor/rpc/backend.go @@ -5,6 +5,7 @@ import ( "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-conductor/consensus" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -16,13 +17,14 @@ type conductor interface { SequencerHealthy(ctx context.Context) bool Leader(ctx context.Context) bool - LeaderWithID(ctx context.Context) (string, string) + LeaderWithID(ctx context.Context) *consensus.ServerInfo AddServerAsVoter(ctx context.Context, id string, addr string) error AddServerAsNonvoter(ctx context.Context, id string, addr string) error RemoveServer(ctx context.Context, id string) error TransferLeader(ctx context.Context) error TransferLeaderToServer(ctx context.Context, id string, addr string) error CommitUnsafePayload(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) error + ClusterMembership(ctx context.Context) ([]*consensus.ServerInfo, error) } // APIBackend is the backend implementation of the API. @@ -69,12 +71,8 @@ func (api *APIBackend) Leader(ctx context.Context) (bool, error) { } // LeaderWithID implements API, returns the leader's server ID and address (not necessarily the current conductor). -func (api *APIBackend) LeaderWithID(ctx context.Context) (*ServerInfo, error) { - id, addr := api.con.LeaderWithID(ctx) - return &ServerInfo{ - ID: id, - Addr: addr, - }, nil +func (api *APIBackend) LeaderWithID(ctx context.Context) (*consensus.ServerInfo, error) { + return api.con.LeaderWithID(ctx), nil } // Pause implements API. @@ -92,12 +90,14 @@ func (api *APIBackend) Resume(ctx context.Context) error { return api.con.Resume(ctx) } -// TransferLeader implements API. +// TransferLeader implements API. With Raft implementation, a successful call does not mean that leadership transfer is complete +// It just means that leadership transfer is in progress (current leader has initiated a new leader election round and stepped down as leader) func (api *APIBackend) TransferLeader(ctx context.Context) error { return api.con.TransferLeader(ctx) } -// TransferLeaderToServer implements API. +// TransferLeaderToServer implements API. With Raft implementation, a successful call does not mean that leadership transfer is complete +// It just means that leadership transfer is in progress (current leader has initiated a new leader election round and stepped down as leader) func (api *APIBackend) TransferLeaderToServer(ctx context.Context, id string, addr string) error { return api.con.TransferLeaderToServer(ctx, id, addr) } @@ -106,3 +106,8 @@ func (api *APIBackend) TransferLeaderToServer(ctx context.Context, id string, ad func (api *APIBackend) SequencerHealthy(ctx context.Context) (bool, error) { return api.con.SequencerHealthy(ctx), nil } + +// ClusterMembership implements API. +func (api *APIBackend) ClusterMembership(ctx context.Context) ([]*consensus.ServerInfo, error) { + return api.con.ClusterMembership(ctx) +} diff --git a/op-conductor/rpc/client.go b/op-conductor/rpc/client.go index 2193fe46452c..6a20b02a4215 100644 --- a/op-conductor/rpc/client.go +++ b/op-conductor/rpc/client.go @@ -5,6 +5,7 @@ import ( "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum-optimism/optimism/op-conductor/consensus" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -61,8 +62,8 @@ func (c *APIClient) Leader(ctx context.Context) (bool, error) { } // LeaderWithID implements API. -func (c *APIClient) LeaderWithID(ctx context.Context) (*ServerInfo, error) { - var info *ServerInfo +func (c *APIClient) LeaderWithID(ctx context.Context) (*consensus.ServerInfo, error) { + var info *consensus.ServerInfo err := c.c.CallContext(ctx, &info, prefixRPC("leaderWithID")) return info, err } @@ -98,3 +99,10 @@ func (c *APIClient) SequencerHealthy(ctx context.Context) (bool, error) { err := c.c.CallContext(ctx, &healthy, prefixRPC("sequencerHealthy")) return healthy, err } + +// ClusterMembership implements API. +func (c *APIClient) ClusterMembership(ctx context.Context) ([]*consensus.ServerInfo, error) { + var info []*consensus.ServerInfo + err := c.c.CallContext(ctx, &info, prefixRPC("clusterMembership")) + return info, err +} diff --git a/op-conductor/rpc/execution_proxy.go b/op-conductor/rpc/execution_proxy.go index cfa7327e567e..fc3b6662a493 100644 --- a/op-conductor/rpc/execution_proxy.go +++ b/op-conductor/rpc/execution_proxy.go @@ -2,11 +2,10 @@ package rpc import ( "context" - "math/big" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" ) var ExecutionRPCNamespace = "eth" @@ -28,13 +27,14 @@ func NewExecutionProxyBackend(log log.Logger, con conductor, client *ethclient.C } } -func (api *ExecutionProxyBackend) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { - block, err := api.client.BlockByNumber(ctx, number) +func (api *ExecutionProxyBackend) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { + var result map[string]interface{} + err := api.client.Client().Call(&result, "eth_getBlockByNumber", number, fullTx) if err != nil { return nil, err } if !api.con.Leader(ctx) { return nil, ErrNotLeader } - return block, nil + return result, nil } diff --git a/op-conductor/rpc/node_admin_proxy.go b/op-conductor/rpc/node_admin_proxy.go new file mode 100644 index 000000000000..a2365d4c611a --- /dev/null +++ b/op-conductor/rpc/node_admin_proxy.go @@ -0,0 +1,40 @@ +package rpc + +import ( + "context" + + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-service/sources" +) + +var NodeAdminRPCNamespace = "admin" + +// NodeAdminProxyAPI implements a node admin rpc proxy with a leadership check to make sure only leader returns the result. +type NodeAdminProxyBackend struct { + log log.Logger + con conductor + client *sources.RollupClient +} + +var _ NodeAdminProxyAPI = (*NodeAdminProxyBackend)(nil) + +// NewNodeAdminProxyBackend creates a new NodeAdminProxyBackend instance. +func NewNodeAdminProxyBackend(log log.Logger, con conductor, client *sources.RollupClient) NodeAdminProxyAPI { + return &NodeAdminProxyBackend{ + log: log, + con: con, + client: client, + } +} + +func (api *NodeAdminProxyBackend) SequencerActive(ctx context.Context) (bool, error) { + active, err := api.client.SequencerActive(ctx) + if err != nil { + return false, err + } + if !api.con.Leader(ctx) { + return false, ErrNotLeader + } + return active, err +} diff --git a/op-conductor/rpc/node_proxy.go b/op-conductor/rpc/node_proxy.go index 64aa9907d286..786167812b11 100644 --- a/op-conductor/rpc/node_proxy.go +++ b/op-conductor/rpc/node_proxy.go @@ -3,9 +3,11 @@ package rpc import ( "context" + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/sources" - "github.com/ethereum/go-ethereum/log" ) var NodeRPCNamespace = "optimism" @@ -49,13 +51,13 @@ func (api *NodeProxyBackend) OutputAtBlock(ctx context.Context, blockNum uint64) return output, nil } -func (api *NodeProxyBackend) SequencerActive(ctx context.Context) (bool, error) { - active, err := api.client.SequencerActive(ctx) +func (api *NodeProxyBackend) RollupConfig(ctx context.Context) (*rollup.Config, error) { + config, err := api.client.RollupConfig(ctx) if err != nil { - return false, err + return nil, err } if !api.con.Leader(ctx) { - return false, ErrNotLeader + return nil, ErrNotLeader } - return active, err + return config, nil } diff --git a/op-conductor/run_test_100times.sh b/op-conductor/run_test_100times.sh new file mode 100755 index 000000000000..5d7500c44e20 --- /dev/null +++ b/op-conductor/run_test_100times.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +for i in {1..100}; do + echo "=======================" + echo "Running iteration $i" + if ! gotestsum -- -run 'TestControlLoop' ./... --count=1 --timeout=5s -race; then + echo "Test failed" + exit 1 + fi +done diff --git a/op-dispute-mon/.gitignore b/op-dispute-mon/.gitignore new file mode 100644 index 000000000000..ba077a4031ad --- /dev/null +++ b/op-dispute-mon/.gitignore @@ -0,0 +1 @@ +bin diff --git a/op-dispute-mon/Dockerfile b/op-dispute-mon/Dockerfile new file mode 100644 index 000000000000..a2b8fe627b27 --- /dev/null +++ b/op-dispute-mon/Dockerfile @@ -0,0 +1,9 @@ +ARG OP_STACK_GO_BUILDER=us-docker.pkg.dev/oplabs-tools-artifacts/images/op-stack-go:latest +FROM $OP_STACK_GO_BUILDER as builder +# See "make golang-docker" and /ops/docker/op-stack-go + +FROM alpine:3.18 + +COPY --from=builder /usr/local/bin/op-dispute-mon /usr/local/bin/op-dispute-mon + +CMD ["op-dispute-mon"] diff --git a/op-dispute-mon/Dockerfile.dockerignore b/op-dispute-mon/Dockerfile.dockerignore new file mode 100644 index 000000000000..4f26140750a0 --- /dev/null +++ b/op-dispute-mon/Dockerfile.dockerignore @@ -0,0 +1,2 @@ +# ignore everything but the dockerfile, the op-stack-go base image performs the build +* diff --git a/op-dispute-mon/Makefile b/op-dispute-mon/Makefile new file mode 100644 index 000000000000..e7b8edfa0d41 --- /dev/null +++ b/op-dispute-mon/Makefile @@ -0,0 +1,20 @@ +GITCOMMIT ?= $(shell git rev-parse HEAD) +GITDATE ?= $(shell git show -s --format='%ct') +VERSION := v0.0.0 + +LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT) +LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) +LDFLAGSSTRING +=-X main.Version=$(VERSION) +LDFLAGS := -ldflags "$(LDFLAGSSTRING)" + +op-dispute-mon: + env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/op-dispute-mon ./cmd +.PHONY: op-dispute-mon + +clean: + rm bin/op-dispute-mon +.PHONY: clean + +test: + go test -v ./... +.PHONY: test diff --git a/op-dispute-mon/README.md b/op-dispute-mon/README.md new file mode 100644 index 000000000000..0a2a847a29e0 --- /dev/null +++ b/op-dispute-mon/README.md @@ -0,0 +1,20 @@ +# op-dispute-mon + +The `op-dispute-mon` is an off-chain service to monitor dispute games. + +## Quickstart + +Clone this repo. Then run: + +```shell +make op-dispute-mon +``` + +This will build the `op-dispute-mon` binary which can be run with +`./op-dispute-mon/bin/op-dispute-mon`. + +## Usage + +`op-dispute-mon` is configurable via command line flags and environment variables. The help menu +shows the available config options and can be accessed by running `./op-dispute-mon --help`. + diff --git a/op-dispute-mon/cmd/main.go b/op-dispute-mon/cmd/main.go new file mode 100644 index 000000000000..4b2c1f46bd17 --- /dev/null +++ b/op-dispute-mon/cmd/main.go @@ -0,0 +1,69 @@ +package main + +import ( + "context" + "os" + + "github.com/urfave/cli/v2" + + "github.com/ethereum/go-ethereum/log" + + monitor "github.com/ethereum-optimism/optimism/op-dispute-mon" + "github.com/ethereum-optimism/optimism/op-dispute-mon/config" + "github.com/ethereum-optimism/optimism/op-dispute-mon/flags" + "github.com/ethereum-optimism/optimism/op-dispute-mon/version" + opservice "github.com/ethereum-optimism/optimism/op-service" + "github.com/ethereum-optimism/optimism/op-service/cliapp" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/optimism/op-service/opio" +) + +var ( + GitCommit = "" + GitDate = "" +) + +// VersionWithMeta holds the textual version string including the metadata. +var VersionWithMeta = opservice.FormatVersion(version.Version, GitCommit, GitDate, version.Meta) + +func main() { + args := os.Args + ctx := opio.WithInterruptBlocker(context.Background()) + if err := run(ctx, args, monitor.Main); err != nil { + log.Crit("Application failed", "err", err) + } +} + +type ConfiguredLifecycle func(ctx context.Context, log log.Logger, config *config.Config) (cliapp.Lifecycle, error) + +func run(ctx context.Context, args []string, action ConfiguredLifecycle) error { + oplog.SetupDefaults() + + app := cli.NewApp() + app.Version = VersionWithMeta + app.Flags = cliapp.ProtectFlags(flags.Flags) + app.Name = "op-dispute-mon" + app.Usage = "Monitor dispute games" + app.Description = "Monitors output proposals and dispute games." + app.Action = cliapp.LifecycleCmd(func(ctx *cli.Context, close context.CancelCauseFunc) (cliapp.Lifecycle, error) { + logger, err := setupLogging(ctx) + if err != nil { + return nil, err + } + logger.Info("Starting op-dispute-mon", "version", VersionWithMeta) + + cfg, err := flags.NewConfigFromCLI(ctx) + if err != nil { + return nil, err + } + return action(ctx.Context, logger, cfg) + }) + return app.RunContext(ctx, args) +} + +func setupLogging(ctx *cli.Context) (log.Logger, error) { + logCfg := oplog.ReadCLIConfig(ctx) + logger := oplog.NewLogger(oplog.AppOut(ctx), logCfg) + oplog.SetGlobalLogHandler(logger.Handler()) + return logger, nil +} diff --git a/op-dispute-mon/config/config.go b/op-dispute-mon/config/config.go new file mode 100644 index 000000000000..5dc0f62408af --- /dev/null +++ b/op-dispute-mon/config/config.go @@ -0,0 +1,74 @@ +package config + +import ( + "errors" + "fmt" + "time" + + opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" + "github.com/ethereum-optimism/optimism/op-service/oppprof" + + "github.com/ethereum/go-ethereum/common" +) + +var ( + ErrMissingL1EthRPC = errors.New("missing l1 eth rpc url") + ErrMissingGameFactoryAddress = errors.New("missing game factory address") + ErrMissingRollupRpc = errors.New("missing rollup rpc url") +) + +const ( + // DefaultGameWindow is the default maximum time duration in the past + // to look for games to monitor. The default value is 11 days, which + // is a 4 day resolution buffer plus the 7 day game finalization window. + DefaultGameWindow = time.Duration(11 * 24 * time.Hour) + // DefaultMonitorInterval is the default interval at which the dispute + // monitor will check for new games to monitor. + DefaultMonitorInterval = time.Second * 30 +) + +// Config is a well typed config that is parsed from the CLI params. +// It also contains config options for auxiliary services. +type Config struct { + L1EthRpc string // L1 RPC Url + GameFactoryAddress common.Address // Address of the dispute game factory + RollupRpc string // The rollup node RPC URL. + + MonitorInterval time.Duration // Frequency to check for new games to monitor. + GameWindow time.Duration // Maximum window to look for games to monitor. + + MetricsConfig opmetrics.CLIConfig + PprofConfig oppprof.CLIConfig +} + +func NewConfig(gameFactoryAddress common.Address, l1EthRpc string) Config { + return Config{ + L1EthRpc: l1EthRpc, + GameFactoryAddress: gameFactoryAddress, + + MonitorInterval: DefaultMonitorInterval, + GameWindow: DefaultGameWindow, + + MetricsConfig: opmetrics.DefaultCLIConfig(), + PprofConfig: oppprof.DefaultCLIConfig(), + } +} + +func (c Config) Check() error { + if c.L1EthRpc == "" { + return ErrMissingL1EthRPC + } + if c.RollupRpc == "" { + return ErrMissingRollupRpc + } + if c.GameFactoryAddress == (common.Address{}) { + return ErrMissingGameFactoryAddress + } + if err := c.MetricsConfig.Check(); err != nil { + return fmt.Errorf("metrics config: %w", err) + } + if err := c.PprofConfig.Check(); err != nil { + return fmt.Errorf("pprof config: %w", err) + } + return nil +} diff --git a/op-dispute-mon/config/config_test.go b/op-dispute-mon/config/config_test.go new file mode 100644 index 000000000000..d2d2ffbbdc6b --- /dev/null +++ b/op-dispute-mon/config/config_test.go @@ -0,0 +1,43 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/common" +) + +var ( + validL1EthRpc = "http://localhost:8545" + validGameFactoryAddress = common.Address{0x23} + validRollupRpc = "http://localhost:8555" +) + +func validConfig() Config { + cfg := NewConfig(validGameFactoryAddress, validL1EthRpc) + cfg.RollupRpc = validRollupRpc + return cfg +} + +func TestValidConfigIsValid(t *testing.T) { + require.NoError(t, validConfig().Check()) +} + +func TestL1EthRpcRequired(t *testing.T) { + config := validConfig() + config.L1EthRpc = "" + require.ErrorIs(t, config.Check(), ErrMissingL1EthRPC) +} + +func TestGameFactoryAddressRequired(t *testing.T) { + config := validConfig() + config.GameFactoryAddress = common.Address{} + require.ErrorIs(t, config.Check(), ErrMissingGameFactoryAddress) +} + +func TestRollupRpcRequired(t *testing.T) { + config := validConfig() + config.RollupRpc = "" + require.ErrorIs(t, config.Check(), ErrMissingRollupRpc) +} diff --git a/op-dispute-mon/flags/flags.go b/op-dispute-mon/flags/flags.go new file mode 100644 index 000000000000..e314c7acd1f4 --- /dev/null +++ b/op-dispute-mon/flags/flags.go @@ -0,0 +1,113 @@ +package flags + +import ( + "fmt" + + "github.com/urfave/cli/v2" + + "github.com/ethereum-optimism/optimism/op-dispute-mon/config" + opservice "github.com/ethereum-optimism/optimism/op-service" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" + "github.com/ethereum-optimism/optimism/op-service/oppprof" +) + +const ( + envVarPrefix = "OP_DISPUTE_MON" +) + +func prefixEnvVars(name string) []string { + return opservice.PrefixEnvVar(envVarPrefix, name) +} + +var ( + // Required Flags + L1EthRpcFlag = &cli.StringFlag{ + Name: "l1-eth-rpc", + Usage: "HTTP provider URL for L1.", + EnvVars: prefixEnvVars("L1_ETH_RPC"), + } + FactoryAddressFlag = &cli.StringFlag{ + Name: "game-factory-address", + Usage: "Address of the fault game factory contract.", + EnvVars: prefixEnvVars("GAME_FACTORY_ADDRESS"), + } + // Optional Flags + RollupRpcFlag = &cli.StringFlag{ + Name: "rollup-rpc", + Usage: "HTTP provider URL for the rollup node", + EnvVars: prefixEnvVars("ROLLUP_RPC"), + } + MonitorIntervalFlag = &cli.DurationFlag{ + Name: "monitor-interval", + Usage: "The interval at which the dispute monitor will check for new games to monitor.", + EnvVars: prefixEnvVars("MONITOR_INTERVAL"), + Value: config.DefaultMonitorInterval, + } + GameWindowFlag = &cli.DurationFlag{ + Name: "game-window", + Usage: "The time window which the monitor will consider games to report on. " + + "This should include a bond claim buffer for games outside the maximum game duration.", + EnvVars: prefixEnvVars("GAME_WINDOW"), + Value: config.DefaultGameWindow, + } +) + +// requiredFlags are checked by [CheckRequired] +var requiredFlags = []cli.Flag{ + L1EthRpcFlag, + FactoryAddressFlag, +} + +// optionalFlags is a list of unchecked cli flags +var optionalFlags = []cli.Flag{ + RollupRpcFlag, + MonitorIntervalFlag, + GameWindowFlag, +} + +func init() { + optionalFlags = append(optionalFlags, oplog.CLIFlags(envVarPrefix)...) + optionalFlags = append(optionalFlags, opmetrics.CLIFlags(envVarPrefix)...) + optionalFlags = append(optionalFlags, oppprof.CLIFlags(envVarPrefix)...) + + Flags = append(requiredFlags, optionalFlags...) +} + +// Flags contains the list of configuration options available to the binary. +var Flags []cli.Flag + +func CheckRequired(ctx *cli.Context) error { + for _, f := range requiredFlags { + if !ctx.IsSet(f.Names()[0]) { + return fmt.Errorf("flag %s is required", f.Names()[0]) + } + } + return nil +} + +// NewConfigFromCLI parses the Config from the provided flags or environment variables. +func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) { + if err := CheckRequired(ctx); err != nil { + return nil, err + } + gameFactoryAddress, err := opservice.ParseAddress(ctx.String(FactoryAddressFlag.Name)) + if err != nil { + return nil, err + } + + metricsConfig := opmetrics.ReadCLIConfig(ctx) + pprofConfig := oppprof.ReadCLIConfig(ctx) + + return &config.Config{ + L1EthRpc: ctx.String(L1EthRpcFlag.Name), + GameFactoryAddress: gameFactoryAddress, + + RollupRpc: ctx.String(RollupRpcFlag.Name), + MonitorInterval: ctx.Duration(MonitorIntervalFlag.Name), + GameWindow: ctx.Duration(GameWindowFlag.Name), + + MetricsConfig: metricsConfig, + PprofConfig: pprofConfig, + }, nil +} diff --git a/op-dispute-mon/flags/flags_test.go b/op-dispute-mon/flags/flags_test.go new file mode 100644 index 000000000000..31881e0eab86 --- /dev/null +++ b/op-dispute-mon/flags/flags_test.go @@ -0,0 +1,82 @@ +package flags + +import ( + "fmt" + "reflect" + "strings" + "testing" + + opservice "github.com/ethereum-optimism/optimism/op-service" + + "github.com/stretchr/testify/require" + "github.com/urfave/cli/v2" +) + +// TestUniqueFlags asserts that all flag names are unique, to avoid accidental conflicts between the many flags. +func TestUniqueFlags(t *testing.T) { + seenCLI := make(map[string]struct{}) + for _, flag := range Flags { + for _, name := range flag.Names() { + if _, ok := seenCLI[name]; ok { + t.Errorf("duplicate flag %s", name) + continue + } + seenCLI[name] = struct{}{} + } + } +} + +// TestUniqueEnvVars asserts that all flag env vars are unique, to avoid accidental conflicts between the many flags. +func TestUniqueEnvVars(t *testing.T) { + seenCLI := make(map[string]struct{}) + for _, flag := range Flags { + envVar := envVarForFlag(flag) + if _, ok := seenCLI[envVar]; envVar != "" && ok { + t.Errorf("duplicate flag env var %s", envVar) + continue + } + seenCLI[envVar] = struct{}{} + } +} + +func TestCorrectEnvVarPrefix(t *testing.T) { + for _, flag := range Flags { + envVar := envVarForFlag(flag) + if envVar == "" { + t.Errorf("Failed to find EnvVar for flag %v", flag.Names()[0]) + } + if !strings.HasPrefix(envVar, fmt.Sprintf("%s_", envVarPrefix)) { + t.Errorf("Flag %v env var (%v) does not start with %s_", flag.Names()[0], envVar, envVarPrefix) + } + if strings.Contains(envVar, "__") { + t.Errorf("Flag %v env var (%v) has duplicate underscores", flag.Names()[0], envVar) + } + } +} + +func envVarForFlag(flag cli.Flag) string { + values := reflect.ValueOf(flag) + envVarValue := values.Elem().FieldByName("EnvVars") + if envVarValue == (reflect.Value{}) || envVarValue.Len() == 0 { + return "" + } + return envVarValue.Index(0).String() +} + +func TestEnvVarFormat(t *testing.T) { + for _, flag := range Flags { + flag := flag + flagName := flag.Names()[0] + + t.Run(flagName, func(t *testing.T) { + envFlagGetter, ok := flag.(interface { + GetEnvVars() []string + }) + envFlags := envFlagGetter.GetEnvVars() + require.True(t, ok, "must be able to cast the flag to an EnvVar interface") + require.Equal(t, 1, len(envFlags), "flags should have exactly one env var") + expectedEnvVar := opservice.FlagNameToEnvVarName(flagName, envVarPrefix) + require.Equal(t, expectedEnvVar, envFlags[0]) + }) + } +} diff --git a/op-dispute-mon/metrics/metrics.go b/op-dispute-mon/metrics/metrics.go new file mode 100644 index 000000000000..0491df5933bb --- /dev/null +++ b/op-dispute-mon/metrics/metrics.go @@ -0,0 +1,249 @@ +package metrics + +import ( + "fmt" + "io" + "math/big" + + "github.com/ethereum-optimism/optimism/op-service/sources/caching" + "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/ethereum-optimism/optimism/op-service/httputil" + opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" +) + +const Namespace = "op_dispute_mon" + +type GameAgreementStatus uint8 + +const ( + // In progress + AgreeChallengerAhead GameAgreementStatus = iota + DisagreeChallengerAhead + AgreeDefenderAhead + DisagreeDefenderAhead + + // Completed + AgreeDefenderWins + DisagreeDefenderWins + AgreeChallengerWins + DisagreeChallengerWins +) + +type Metricer interface { + RecordInfo(version string) + RecordUp() + + RecordClaimResolutionDelayMax(delay float64) + + RecordOutputFetchTime(timestamp float64) + + RecordGameAgreement(status GameAgreementStatus, count int) + + RecordBondCollateral(addr common.Address, required *big.Int, available *big.Int) + + caching.Metrics +} + +// Metrics implementation must implement RegistryMetricer to allow the metrics server to work. +var _ opmetrics.RegistryMetricer = (*Metrics)(nil) + +type Metrics struct { + ns string + registry *prometheus.Registry + factory opmetrics.Factory + + *opmetrics.CacheMetrics + + info prometheus.GaugeVec + up prometheus.Gauge + + lastOutputFetch prometheus.Gauge + + claimResolutionDelayMax prometheus.Gauge + + gamesAgreement prometheus.GaugeVec + + requiredCollateral prometheus.GaugeVec + availableCollateral prometheus.GaugeVec +} + +func (m *Metrics) Registry() *prometheus.Registry { + return m.registry +} + +var _ Metricer = (*Metrics)(nil) + +func NewMetrics() *Metrics { + registry := opmetrics.NewRegistry() + factory := opmetrics.With(registry) + + return &Metrics{ + ns: Namespace, + registry: registry, + factory: factory, + + CacheMetrics: opmetrics.NewCacheMetrics(factory, Namespace, "provider_cache", "Provider cache"), + + info: *factory.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: Namespace, + Name: "info", + Help: "Pseudo-metric tracking version and config info", + }, []string{ + "version", + }), + up: factory.NewGauge(prometheus.GaugeOpts{ + Namespace: Namespace, + Name: "up", + Help: "1 if the op-challenger has finished starting up", + }), + lastOutputFetch: factory.NewGauge(prometheus.GaugeOpts{ + Namespace: Namespace, + Name: "last_output_fetch", + Help: "Timestamp of the last output fetch", + }), + claimResolutionDelayMax: factory.NewGauge(prometheus.GaugeOpts{ + Namespace: Namespace, + Name: "claim_resolution_delay_max", + Help: "Maximum claim resolution delay in seconds", + }), + gamesAgreement: *factory.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: Namespace, + Name: "games_agreement", + Help: "Number of games broken down by whether the result agrees with the reference node", + }, []string{ + "status", + "completion", + "result_correctness", + "root_agreement", + }), + requiredCollateral: *factory.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: Namespace, + Name: "bond_collateral_required", + Help: "Required collateral (ETH) to cover outstanding bonds and credits", + }, []string{ + // Address of the DelayedWETH contract in use. This is a limited set as only permissioned actors can deploy + // additional DelayedWETH contracts to be used by dispute games + "delayedWETH", + "balance", + }), + availableCollateral: *factory.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: Namespace, + Name: "bond_collateral_available", + Help: "Available collateral (ETH) to cover outstanding bonds and credits", + }, []string{ + // Address of the DelayedWETH contract in use. This is a limited set as only permissioned actors can deploy + // additional DelayedWETH contracts to be used by dispute games + "delayedWETH", + "balance", + }), + } +} + +func (m *Metrics) Start(host string, port int) (*httputil.HTTPServer, error) { + return opmetrics.StartServer(m.registry, host, port) +} + +func (m *Metrics) StartBalanceMetrics( + l log.Logger, + client *ethclient.Client, + account common.Address, +) io.Closer { + return opmetrics.LaunchBalanceMetrics(l, m.registry, m.ns, client, account) +} + +// RecordInfo sets a pseudo-metric that contains versioning and +// config info for the op-proposer. +func (m *Metrics) RecordInfo(version string) { + m.info.WithLabelValues(version).Set(1) +} + +// RecordUp sets the up metric to 1. +func (m *Metrics) RecordUp() { + prometheus.MustRegister() + m.up.Set(1) +} + +func (m *Metrics) RecordClaimResolutionDelayMax(delay float64) { + m.claimResolutionDelayMax.Set(delay) +} + +func (m *Metrics) Document() []opmetrics.DocumentedMetric { + return m.factory.Document() +} + +func (m *Metrics) RecordOutputFetchTime(timestamp float64) { + m.lastOutputFetch.Set(timestamp) +} + +func (m *Metrics) RecordGameAgreement(status GameAgreementStatus, count int) { + m.gamesAgreement.WithLabelValues(labelValuesFor(status)...).Set(float64(count)) +} + +func (m *Metrics) RecordBondCollateral(addr common.Address, required *big.Int, available *big.Int) { + balance := "sufficient" + if required.Cmp(available) > 0 { + balance = "insufficient" + } + m.requiredCollateral.WithLabelValues(addr.Hex(), balance).Set(weiToEther(required)) + m.availableCollateral.WithLabelValues(addr.Hex(), balance).Set(weiToEther(available)) +} + +const ( + inProgress = true + correct = true + agree = true +) + +func labelValuesFor(status GameAgreementStatus) []string { + asStrings := func(status string, inProgress bool, correct bool, agree bool) []string { + inProgressStr := "in_progress" + if !inProgress { + inProgressStr = "complete" + } + correctStr := "correct" + if !correct { + correctStr = "incorrect" + } + agreeStr := "agree" + if !agree { + agreeStr = "disagree" + } + return []string{status, inProgressStr, correctStr, agreeStr} + } + switch status { + case AgreeChallengerAhead: + return asStrings("agree_challenger_ahead", inProgress, !correct, agree) + case DisagreeChallengerAhead: + return asStrings("disagree_challenger_ahead", inProgress, correct, !agree) + case AgreeDefenderAhead: + return asStrings("agree_defender_ahead", inProgress, correct, agree) + case DisagreeDefenderAhead: + return asStrings("disagree_defender_ahead", inProgress, !correct, !agree) + + // Completed + case AgreeDefenderWins: + return asStrings("agree_defender_wins", !inProgress, correct, agree) + case DisagreeDefenderWins: + return asStrings("disagree_defender_wins", !inProgress, !correct, !agree) + case AgreeChallengerWins: + return asStrings("agree_challenger_wins", !inProgress, !correct, agree) + case DisagreeChallengerWins: + return asStrings("disagree_challenger_wins", !inProgress, correct, !agree) + default: + panic(fmt.Errorf("unknown game agreement status: %v", status)) + } +} + +// 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 +} diff --git a/op-dispute-mon/metrics/noop.go b/op-dispute-mon/metrics/noop.go new file mode 100644 index 000000000000..9a3625610140 --- /dev/null +++ b/op-dispute-mon/metrics/noop.go @@ -0,0 +1,25 @@ +package metrics + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" +) + +type NoopMetricsImpl struct{} + +var NoopMetrics Metricer = new(NoopMetricsImpl) + +func (*NoopMetricsImpl) RecordInfo(version string) {} +func (*NoopMetricsImpl) RecordUp() {} + +func (*NoopMetricsImpl) CacheAdd(_ string, _ int, _ bool) {} +func (*NoopMetricsImpl) CacheGet(_ string, _ bool) {} + +func (*NoopMetricsImpl) RecordClaimResolutionDelayMax(delay float64) {} + +func (*NoopMetricsImpl) RecordOutputFetchTime(timestamp float64) {} + +func (*NoopMetricsImpl) RecordGameAgreement(status GameAgreementStatus, count int) {} + +func (i *NoopMetricsImpl) RecordBondCollateral(_ common.Address, _ *big.Int, _ *big.Int) {} diff --git a/op-dispute-mon/mon/bonds/collateral.go b/op-dispute-mon/mon/bonds/collateral.go new file mode 100644 index 000000000000..67d15cbe1f10 --- /dev/null +++ b/op-dispute-mon/mon/bonds/collateral.go @@ -0,0 +1,43 @@ +package bonds + +import ( + "context" + "fmt" + "math/big" + + faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum/go-ethereum/common" + "golang.org/x/exp/maps" +) + +type BondContract interface { + GetCredits(ctx context.Context, block rpcblock.Block, recipients ...common.Address) ([]*big.Int, error) +} + +// CalculateRequiredCollateral determines the minimum balance required for a fault dispute game contract in order +// to pay the outstanding bonds and credits. +// It returns the sum of unpaid bonds from claims, plus the sum of allocated but unclaimed credits. +func CalculateRequiredCollateral(ctx context.Context, contract BondContract, blockHash common.Hash, claims []faultTypes.Claim) (*big.Int, error) { + unpaidBonds := big.NewInt(0) + recipients := make(map[common.Address]bool) + for _, claim := range claims { + if monTypes.ResolvedBondAmount.Cmp(claim.Bond) != 0 { + unpaidBonds = new(big.Int).Add(unpaidBonds, claim.Bond) + } + recipients[claim.Claimant] = true + if claim.CounteredBy != (common.Address{}) { + recipients[claim.CounteredBy] = true + } + } + + credits, err := contract.GetCredits(ctx, rpcblock.ByHash(blockHash), maps.Keys(recipients)...) + if err != nil { + return nil, fmt.Errorf("failed to load credits: %w", err) + } + for _, credit := range credits { + unpaidBonds = new(big.Int).Add(unpaidBonds, credit) + } + return unpaidBonds, nil +} diff --git a/op-dispute-mon/mon/bonds/collateral_test.go b/op-dispute-mon/mon/bonds/collateral_test.go new file mode 100644 index 000000000000..7445a6076315 --- /dev/null +++ b/op-dispute-mon/mon/bonds/collateral_test.go @@ -0,0 +1,64 @@ +package bonds + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestCalculateRequiredCollateral(t *testing.T) { + claims := []types.Claim{ + { + ClaimData: types.ClaimData{ + Bond: monTypes.ResolvedBondAmount, + }, + Claimant: common.Address{0x01}, + CounteredBy: common.Address{0x02}, + }, + { + ClaimData: types.ClaimData{ + Bond: big.NewInt(5), + }, + Claimant: common.Address{0x03}, + CounteredBy: common.Address{}, + }, + { + ClaimData: types.ClaimData{ + Bond: big.NewInt(7), + }, + Claimant: common.Address{0x03}, + CounteredBy: common.Address{}, + }, + } + contract := &stubBondContract{ + credits: map[common.Address]*big.Int{ + {0x01}: big.NewInt(3), + {0x03}: big.NewInt(8), + }, + } + collateral, err := CalculateRequiredCollateral(context.Background(), contract, common.Hash{0xab}, claims) + require.NoError(t, err) + require.Equal(t, collateral.Int64(), int64(5+7+3+8)) +} + +type stubBondContract struct { + credits map[common.Address]*big.Int +} + +func (s *stubBondContract) GetCredits(_ context.Context, _ rpcblock.Block, recipients ...common.Address) ([]*big.Int, error) { + results := make([]*big.Int, len(recipients)) + for i, recipient := range recipients { + credit, ok := s.credits[recipient] + if !ok { + credit = big.NewInt(0) + } + results[i] = credit + } + return results, nil +} diff --git a/op-dispute-mon/mon/bonds/monitor.go b/op-dispute-mon/mon/bonds/monitor.go new file mode 100644 index 000000000000..a84d8a4f62ee --- /dev/null +++ b/op-dispute-mon/mon/bonds/monitor.go @@ -0,0 +1,33 @@ +package bonds + +import ( + "math/big" + + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/transform" + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" +) + +type BondMetrics interface { + RecordBondCollateral(addr common.Address, required *big.Int, available *big.Int) +} + +type Bonds struct { + logger log.Logger + metrics BondMetrics +} + +func NewBonds(logger log.Logger, metrics BondMetrics) *Bonds { + return &Bonds{ + logger: logger, + metrics: metrics, + } +} + +func (b *Bonds) CheckBonds(games []*types.EnrichedGameData) { + data := transform.CalculateRequiredCollateral(games) + for addr, collateral := range data { + b.metrics.RecordBondCollateral(addr, collateral.Required, collateral.Actual) + } +} diff --git a/op-dispute-mon/mon/bonds/monitor_test.go b/op-dispute-mon/mon/bonds/monitor_test.go new file mode 100644 index 000000000000..1cf5f65a7cff --- /dev/null +++ b/op-dispute-mon/mon/bonds/monitor_test.go @@ -0,0 +1,59 @@ +package bonds + +import ( + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/transform" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func TestCheckBonds(t *testing.T) { + weth1 := common.Address{0x1a} + weth1Balance := big.NewInt(4200) + weth2 := common.Address{0x2b} + weth2Balance := big.NewInt(6000) + game1 := &monTypes.EnrichedGameData{ + Credits: map[common.Address]*big.Int{ + common.Address{0x01}: big.NewInt(2), + }, + WETHContract: weth1, + ETHCollateral: weth1Balance, + } + game2 := &monTypes.EnrichedGameData{ + Credits: map[common.Address]*big.Int{ + common.Address{0x01}: big.NewInt(46), + }, + WETHContract: weth2, + ETHCollateral: weth2Balance, + } + + logger := testlog.Logger(t, log.LvlInfo) + metrics := &stubBondMetrics{recorded: make(map[common.Address]transform.Collateral)} + bonds := NewBonds(logger, metrics) + + bonds.CheckBonds([]*monTypes.EnrichedGameData{game1, game2}) + + require.Len(t, metrics.recorded, 2) + require.Contains(t, metrics.recorded, weth1) + require.Contains(t, metrics.recorded, weth2) + require.Equal(t, metrics.recorded[weth1].Required.Uint64(), uint64(2)) + require.Equal(t, metrics.recorded[weth1].Actual.Uint64(), weth1Balance.Uint64()) + require.Equal(t, metrics.recorded[weth2].Required.Uint64(), uint64(46)) + require.Equal(t, metrics.recorded[weth2].Actual.Uint64(), weth2Balance.Uint64()) +} + +type stubBondMetrics struct { + recorded map[common.Address]transform.Collateral +} + +func (s *stubBondMetrics) RecordBondCollateral(addr common.Address, required *big.Int, available *big.Int) { + s.recorded[addr] = transform.Collateral{ + Required: required, + Actual: available, + } +} diff --git a/op-dispute-mon/mon/extract/balance_enricher.go b/op-dispute-mon/mon/extract/balance_enricher.go new file mode 100644 index 000000000000..42cc5b8ccafe --- /dev/null +++ b/op-dispute-mon/mon/extract/balance_enricher.go @@ -0,0 +1,33 @@ +package extract + +import ( + "context" + "fmt" + "math/big" + + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum/go-ethereum/common" +) + +var _ Enricher = (*BalanceEnricher)(nil) + +type BalanceCaller interface { + GetBalance(context.Context, rpcblock.Block) (*big.Int, common.Address, error) +} + +type BalanceEnricher struct{} + +func NewBalanceEnricher() *BalanceEnricher { + return &BalanceEnricher{} +} + +func (b *BalanceEnricher) Enrich(ctx context.Context, block rpcblock.Block, caller GameCaller, game *monTypes.EnrichedGameData) error { + balance, holdingAddr, err := caller.GetBalance(ctx, block) + if err != nil { + return fmt.Errorf("failed to fetch balance: %w", err) + } + game.ETHCollateral = balance + game.WETHContract = holdingAddr + return nil +} diff --git a/op-dispute-mon/mon/extract/balance_enricher_test.go b/op-dispute-mon/mon/extract/balance_enricher_test.go new file mode 100644 index 000000000000..28ce644d5f2f --- /dev/null +++ b/op-dispute-mon/mon/extract/balance_enricher_test.go @@ -0,0 +1,33 @@ +package extract + +import ( + "context" + "errors" + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestBalanceEnricher(t *testing.T) { + t.Run("GetBalanceError", func(t *testing.T) { + enricher := NewBalanceEnricher() + caller := &mockGameCaller{balanceErr: errors.New("nope")} + game := &types.EnrichedGameData{} + err := enricher.Enrich(context.Background(), rpcblock.Latest, caller, game) + require.ErrorIs(t, err, caller.balanceErr) + }) + + t.Run("GetBalanceSuccess", func(t *testing.T) { + enricher := NewBalanceEnricher() + caller := &mockGameCaller{balance: big.NewInt(84242), balanceAddr: common.Address{0xdd}} + game := &types.EnrichedGameData{} + err := enricher.Enrich(context.Background(), rpcblock.Latest, caller, game) + require.NoError(t, err) + require.Equal(t, game.WETHContract, caller.balanceAddr) + require.Equal(t, game.ETHCollateral, caller.balance) + }) +} diff --git a/op-dispute-mon/mon/extract/bond_enricher.go b/op-dispute-mon/mon/extract/bond_enricher.go new file mode 100644 index 000000000000..ec3659f92859 --- /dev/null +++ b/op-dispute-mon/mon/extract/bond_enricher.go @@ -0,0 +1,51 @@ +package extract + +import ( + "context" + "errors" + "fmt" + "math/big" + + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum/go-ethereum/common" + "golang.org/x/exp/maps" +) + +var _ Enricher = (*BondEnricher)(nil) + +var ErrIncorrectCreditCount = errors.New("incorrect credit count") + +type BondCaller interface { + GetCredits(context.Context, rpcblock.Block, ...common.Address) ([]*big.Int, error) +} + +type BondEnricher struct{} + +func NewBondEnricher() *BondEnricher { + return &BondEnricher{} +} + +func (b *BondEnricher) Enrich(ctx context.Context, block rpcblock.Block, caller GameCaller, game *monTypes.EnrichedGameData) error { + recipients := make(map[common.Address]bool) + for _, claim := range game.Claims { + recipients[claim.Claimant] = true + if claim.CounteredBy != (common.Address{}) { + recipients[claim.CounteredBy] = true + } + } + + recipientAddrs := maps.Keys(recipients) + credits, err := caller.GetCredits(ctx, block, recipientAddrs...) + if err != nil { + return err + } + if len(credits) != len(recipientAddrs) { + return fmt.Errorf("%w, requested %v values but got %v", ErrIncorrectCreditCount, len(recipientAddrs), len(credits)) + } + game.Credits = make(map[common.Address]*big.Int) + for i, credit := range credits { + game.Credits[recipientAddrs[i]] = credit + } + return nil +} diff --git a/op-dispute-mon/mon/extract/bond_enricher_test.go b/op-dispute-mon/mon/extract/bond_enricher_test.go new file mode 100644 index 000000000000..29daecb8bade --- /dev/null +++ b/op-dispute-mon/mon/extract/bond_enricher_test.go @@ -0,0 +1,87 @@ +package extract + +import ( + "context" + "errors" + "math/big" + "testing" + + faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestBondEnricher(t *testing.T) { + makeGame := func() *monTypes.EnrichedGameData { + return &monTypes.EnrichedGameData{ + Claims: []faultTypes.Claim{ + { + ClaimData: faultTypes.ClaimData{ + Bond: monTypes.ResolvedBondAmount, + }, + Claimant: common.Address{0x01}, + CounteredBy: common.Address{0x02}, + }, + { + ClaimData: faultTypes.ClaimData{ + Bond: big.NewInt(5), + }, + Claimant: common.Address{0x03}, + CounteredBy: common.Address{}, + }, + { + ClaimData: faultTypes.ClaimData{ + Bond: big.NewInt(7), + }, + Claimant: common.Address{0x03}, + CounteredBy: common.Address{}, + }, + }, + } + } + + t.Run("GetCreditsFails", func(t *testing.T) { + enricher := NewBondEnricher() + caller := &mockGameCaller{creditsErr: errors.New("nope")} + game := makeGame() + err := enricher.Enrich(context.Background(), rpcblock.Latest, caller, game) + require.ErrorIs(t, err, caller.creditsErr) + }) + + t.Run("GetCreditsWrongNumberOfResults", func(t *testing.T) { + enricher := NewBondEnricher() + caller := &mockGameCaller{extraCredit: []*big.Int{big.NewInt(4)}} + game := makeGame() + err := enricher.Enrich(context.Background(), rpcblock.Latest, caller, game) + require.ErrorIs(t, err, ErrIncorrectCreditCount) + }) + + t.Run("GetCreditsSuccess", func(t *testing.T) { + game := makeGame() + expectedRecipients := []common.Address{ + game.Claims[0].Claimant, + game.Claims[0].CounteredBy, + game.Claims[1].Claimant, + // Claim 1 CounteredBy is unset + // Claim 2 Claimant is same as claim 1 Claimant + // Claim 2 CounteredBy is unset + } + enricher := NewBondEnricher() + expectedCredits := map[common.Address]*big.Int{ + expectedRecipients[0]: big.NewInt(10), + expectedRecipients[1]: big.NewInt(20), + expectedRecipients[2]: big.NewInt(30), + } + caller := &mockGameCaller{credits: expectedCredits} + err := enricher.Enrich(context.Background(), rpcblock.Latest, caller, game) + require.NoError(t, err) + + require.Equal(t, len(expectedRecipients), len(caller.requestedCredits)) + for _, recipient := range expectedRecipients { + require.Contains(t, caller.requestedCredits, recipient) + } + require.Equal(t, expectedCredits, game.Credits) + }) +} diff --git a/op-dispute-mon/mon/extract/caller.go b/op-dispute-mon/mon/extract/caller.go new file mode 100644 index 000000000000..caa92ae90902 --- /dev/null +++ b/op-dispute-mon/mon/extract/caller.go @@ -0,0 +1,53 @@ +package extract + +import ( + "context" + "fmt" + + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" + faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/caching" +) + +const metricsLabel = "game_caller_creator" + +type GameCaller interface { + GetGameMetadata(context.Context, rpcblock.Block) (common.Hash, uint64, common.Hash, types.GameStatus, uint64, error) + GetAllClaims(context.Context, rpcblock.Block) ([]faultTypes.Claim, error) + BondCaller + BalanceCaller +} + +type GameCallerCreator struct { + cache *caching.LRUCache[common.Address, *contracts.FaultDisputeGameContract] + caller *batching.MultiCaller +} + +func NewGameCallerCreator(m caching.Metrics, caller *batching.MultiCaller) *GameCallerCreator { + return &GameCallerCreator{ + caller: caller, + cache: caching.NewLRUCache[common.Address, *contracts.FaultDisputeGameContract](m, metricsLabel, 100), + } +} + +func (g *GameCallerCreator) CreateContract(game types.GameMetadata) (GameCaller, error) { + if fdg, ok := g.cache.Get(game.Proxy); ok { + return fdg, nil + } + switch game.GameType { + case faultTypes.CannonGameType, faultTypes.AlphabetGameType: + fdg, err := contracts.NewFaultDisputeGameContract(game.Proxy, g.caller) + if err != nil { + return nil, fmt.Errorf("failed to create FaultDisputeGameContract: %w", err) + } + g.cache.Add(game.Proxy, fdg) + return fdg, nil + default: + return nil, fmt.Errorf("unsupported game type: %d", game.GameType) + } +} diff --git a/op-dispute-mon/mon/extract/caller_test.go b/op-dispute-mon/mon/extract/caller_test.go new file mode 100644 index 000000000000..ffd0ba924bc3 --- /dev/null +++ b/op-dispute-mon/mon/extract/caller_test.go @@ -0,0 +1,81 @@ +package extract + +import ( + "fmt" + "testing" + + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" + batchingTest "github.com/ethereum-optimism/optimism/op-service/sources/batching/test" + "github.com/stretchr/testify/require" +) + +var ( + fdgAddr = common.HexToAddress("0x24112842371dFC380576ebb09Ae16Cb6B6caD7CB") +) + +func TestMetadataCreator_CreateContract(t *testing.T) { + tests := []struct { + name string + game types.GameMetadata + expectedErr error + }{ + { + name: "validCannonGameType", + game: types.GameMetadata{GameType: faultTypes.CannonGameType, Proxy: fdgAddr}, + }, + { + name: "validAlphabetGameType", + game: types.GameMetadata{GameType: faultTypes.AlphabetGameType, Proxy: fdgAddr}, + }, + { + name: "InvalidGameType", + game: types.GameMetadata{GameType: 2, Proxy: fdgAddr}, + expectedErr: fmt.Errorf("unsupported game type: 2"), + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + caller, metrics := setupMetadataLoaderTest(t) + creator := NewGameCallerCreator(metrics, caller) + _, err := creator.CreateContract(test.game) + require.Equal(t, test.expectedErr, err) + if test.expectedErr == nil { + require.Equal(t, 1, metrics.cacheAddCalls) + require.Equal(t, 1, metrics.cacheGetCalls) + } + _, err = creator.CreateContract(test.game) + require.Equal(t, test.expectedErr, err) + if test.expectedErr == nil { + require.Equal(t, 1, metrics.cacheAddCalls) + require.Equal(t, 2, metrics.cacheGetCalls) + } + }) + } +} + +func setupMetadataLoaderTest(t *testing.T) (*batching.MultiCaller, *mockCacheMetrics) { + fdgAbi, err := bindings.FaultDisputeGameMetaData.GetAbi() + require.NoError(t, err) + stubRpc := batchingTest.NewAbiBasedRpc(t, fdgAddr, fdgAbi) + caller := batching.NewMultiCaller(stubRpc, batching.DefaultBatchSize) + return caller, &mockCacheMetrics{} +} + +type mockCacheMetrics struct { + cacheAddCalls int + cacheGetCalls int +} + +func (m *mockCacheMetrics) CacheAdd(_ string, _ int, _ bool) { + m.cacheAddCalls++ +} +func (m *mockCacheMetrics) CacheGet(_ string, _ bool) { + m.cacheGetCalls++ +} diff --git a/op-dispute-mon/mon/extract/extractor.go b/op-dispute-mon/mon/extract/extractor.go new file mode 100644 index 000000000000..fa211a32a1eb --- /dev/null +++ b/op-dispute-mon/mon/extract/extractor.go @@ -0,0 +1,89 @@ +package extract + +import ( + "context" + "fmt" + + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" +) + +type CreateGameCaller func(game gameTypes.GameMetadata) (GameCaller, error) +type FactoryGameFetcher func(ctx context.Context, blockHash common.Hash, earliestTimestamp uint64) ([]gameTypes.GameMetadata, error) + +type Enricher interface { + Enrich(ctx context.Context, block rpcblock.Block, caller GameCaller, game *monTypes.EnrichedGameData) error +} + +type Extractor struct { + logger log.Logger + createContract CreateGameCaller + fetchGames FactoryGameFetcher + enrichers []Enricher +} + +func NewExtractor(logger log.Logger, creator CreateGameCaller, fetchGames FactoryGameFetcher, enrichers ...Enricher) *Extractor { + return &Extractor{ + logger: logger, + createContract: creator, + fetchGames: fetchGames, + enrichers: enrichers, + } +} + +func (e *Extractor) Extract(ctx context.Context, blockHash common.Hash, minTimestamp uint64) ([]*monTypes.EnrichedGameData, error) { + games, err := e.fetchGames(ctx, blockHash, minTimestamp) + if err != nil { + return nil, fmt.Errorf("failed to load games: %w", err) + } + return e.enrichGames(ctx, blockHash, games), nil +} + +func (e *Extractor) enrichGames(ctx context.Context, blockHash common.Hash, games []gameTypes.GameMetadata) []*monTypes.EnrichedGameData { + var enrichedGames []*monTypes.EnrichedGameData + for _, game := range games { + caller, err := e.createContract(game) + if err != nil { + e.logger.Error("Failed to create game caller", "err", err) + continue + } + l1Head, l2BlockNum, rootClaim, status, duration, err := caller.GetGameMetadata(ctx, rpcblock.ByHash(blockHash)) + if err != nil { + e.logger.Error("Failed to fetch game metadata", "err", err) + continue + } + claims, err := caller.GetAllClaims(ctx, rpcblock.ByHash(blockHash)) + if err != nil { + e.logger.Error("Failed to fetch game claims", "err", err) + continue + } + enrichedGame := &monTypes.EnrichedGameData{ + GameMetadata: game, + L1Head: l1Head, + L2BlockNumber: l2BlockNum, + RootClaim: rootClaim, + Status: status, + Duration: duration, + Claims: claims, + } + if err := e.applyEnrichers(ctx, blockHash, caller, enrichedGame); err != nil { + e.logger.Error("Failed to enrich game", "err", err) + continue + } + enrichedGames = append(enrichedGames, enrichedGame) + } + return enrichedGames +} + +func (e *Extractor) applyEnrichers(ctx context.Context, blockHash common.Hash, caller GameCaller, game *monTypes.EnrichedGameData) error { + for _, enricher := range e.enrichers { + if err := enricher.Enrich(ctx, rpcblock.ByHash(blockHash), caller, game); err != nil { + return err + } + } + return nil +} diff --git a/op-dispute-mon/mon/extract/extractor_test.go b/op-dispute-mon/mon/extract/extractor_test.go new file mode 100644 index 000000000000..83264baa4b9e --- /dev/null +++ b/op-dispute-mon/mon/extract/extractor_test.go @@ -0,0 +1,242 @@ +package extract + +import ( + "context" + "errors" + "math/big" + "testing" + + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/stretchr/testify/require" + + faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" +) + +var mockRootClaim = common.HexToHash("0x1234") + +func TestExtractor_Extract(t *testing.T) { + t.Run("FetchGamesError", func(t *testing.T) { + extractor, _, games, _ := setupExtractorTest(t) + games.err = errors.New("boom") + _, err := extractor.Extract(context.Background(), common.Hash{}, 0) + require.ErrorIs(t, err, games.err) + require.Equal(t, 1, games.calls) + }) + + t.Run("CreateGameErrorLog", func(t *testing.T) { + extractor, creator, games, logs := setupExtractorTest(t) + games.games = []gameTypes.GameMetadata{{}} + creator.err = errors.New("boom") + enriched, err := extractor.Extract(context.Background(), common.Hash{}, 0) + require.NoError(t, err) + require.Len(t, enriched, 0) + require.Equal(t, 1, games.calls) + require.Equal(t, 1, creator.calls) + require.Equal(t, 0, creator.caller.metadataCalls) + require.Equal(t, 0, creator.caller.claimsCalls) + verifyLogs(t, logs, 1, 0, 0, 0) + }) + + t.Run("MetadataFetchErrorLog", func(t *testing.T) { + extractor, creator, games, logs := setupExtractorTest(t) + games.games = []gameTypes.GameMetadata{{}} + creator.caller.metadataErr = errors.New("boom") + enriched, err := extractor.Extract(context.Background(), common.Hash{}, 0) + require.NoError(t, err) + require.Len(t, enriched, 0) + require.Equal(t, 1, games.calls) + require.Equal(t, 1, creator.calls) + require.Equal(t, 1, creator.caller.metadataCalls) + require.Equal(t, 0, creator.caller.claimsCalls) + verifyLogs(t, logs, 0, 1, 0, 0) + }) + + t.Run("ClaimsFetchErrorLog", func(t *testing.T) { + extractor, creator, games, logs := setupExtractorTest(t) + games.games = []gameTypes.GameMetadata{{}} + creator.caller.claimsErr = errors.New("boom") + enriched, err := extractor.Extract(context.Background(), common.Hash{}, 0) + require.NoError(t, err) + require.Len(t, enriched, 0) + require.Equal(t, 1, games.calls) + require.Equal(t, 1, creator.calls) + require.Equal(t, 1, creator.caller.metadataCalls) + require.Equal(t, 1, creator.caller.claimsCalls) + verifyLogs(t, logs, 0, 0, 1, 0) + }) + + t.Run("Success", func(t *testing.T) { + extractor, creator, games, _ := setupExtractorTest(t) + games.games = []gameTypes.GameMetadata{{}} + enriched, err := extractor.Extract(context.Background(), common.Hash{}, 0) + require.NoError(t, err) + require.Len(t, enriched, 1) + require.Equal(t, 1, games.calls) + require.Equal(t, 1, creator.calls) + require.Equal(t, 1, creator.caller.metadataCalls) + require.Equal(t, 1, creator.caller.claimsCalls) + }) + + t.Run("EnricherFails", func(t *testing.T) { + enricher := &mockEnricher{err: errors.New("whoops")} + extractor, _, games, logs := setupExtractorTest(t, enricher) + games.games = []gameTypes.GameMetadata{{}} + enriched, err := extractor.Extract(context.Background(), common.Hash{}, 0) + require.NoError(t, err) + l := logs.FindLogs(testlog.NewMessageFilter("Failed to enrich game")) + require.Len(t, l, 1, "Should have logged error") + require.Len(t, enriched, 0, "Should not return games that failed to enrich") + }) + + t.Run("EnricherSuccess", func(t *testing.T) { + enricher := &mockEnricher{} + extractor, _, games, _ := setupExtractorTest(t, enricher) + games.games = []gameTypes.GameMetadata{{}} + enriched, err := extractor.Extract(context.Background(), common.Hash{}, 0) + require.NoError(t, err) + require.Len(t, enriched, 1) + require.Equal(t, 1, enricher.calls) + }) + + t.Run("MultipleEnrichersMultipleGames", func(t *testing.T) { + enricher1 := &mockEnricher{} + enricher2 := &mockEnricher{} + extractor, _, games, _ := setupExtractorTest(t, enricher1, enricher2) + games.games = []gameTypes.GameMetadata{{}, {}} + enriched, err := extractor.Extract(context.Background(), common.Hash{}, 0) + require.NoError(t, err) + require.Len(t, enriched, 2) + require.Equal(t, 2, enricher1.calls) + require.Equal(t, 2, enricher2.calls) + }) +} + +func verifyLogs(t *testing.T, logs *testlog.CapturingHandler, createErr int, metadataErr int, claimsErr int, durationErr int) { + errorLevelFilter := testlog.NewLevelFilter(log.LevelError) + createMessageFilter := testlog.NewMessageFilter("Failed to create game caller") + l := logs.FindLogs(errorLevelFilter, createMessageFilter) + require.Len(t, l, createErr) + fetchMessageFilter := testlog.NewMessageFilter("Failed to fetch game metadata") + l = logs.FindLogs(errorLevelFilter, fetchMessageFilter) + require.Len(t, l, metadataErr) + claimsMessageFilter := testlog.NewMessageFilter("Failed to fetch game claims") + l = logs.FindLogs(errorLevelFilter, claimsMessageFilter) + require.Len(t, l, claimsErr) + durationMessageFilter := testlog.NewMessageFilter("Failed to fetch game duration") + l = logs.FindLogs(errorLevelFilter, durationMessageFilter) + require.Len(t, l, durationErr) +} + +func setupExtractorTest(t *testing.T, enrichers ...Enricher) (*Extractor, *mockGameCallerCreator, *mockGameFetcher, *testlog.CapturingHandler) { + logger, capturedLogs := testlog.CaptureLogger(t, log.LvlDebug) + games := &mockGameFetcher{} + caller := &mockGameCaller{rootClaim: mockRootClaim} + creator := &mockGameCallerCreator{caller: caller} + extractor := NewExtractor( + logger, + creator.CreateGameCaller, + games.FetchGames, + enrichers..., + ) + return extractor, creator, games, capturedLogs +} + +type mockGameFetcher struct { + calls int + err error + games []gameTypes.GameMetadata +} + +func (m *mockGameFetcher) FetchGames(_ context.Context, _ common.Hash, _ uint64) ([]gameTypes.GameMetadata, error) { + m.calls++ + if m.err != nil { + return nil, m.err + } + return m.games, nil +} + +type mockGameCallerCreator struct { + calls int + err error + caller *mockGameCaller +} + +func (m *mockGameCallerCreator) CreateGameCaller(_ gameTypes.GameMetadata) (GameCaller, error) { + m.calls++ + if m.err != nil { + return nil, m.err + } + return m.caller, nil +} + +type mockGameCaller struct { + metadataCalls int + metadataErr error + claimsCalls int + claimsErr error + rootClaim common.Hash + claims []faultTypes.Claim + requestedCredits []common.Address + creditsErr error + credits map[common.Address]*big.Int + extraCredit []*big.Int + balanceErr error + balance *big.Int + balanceAddr common.Address +} + +func (m *mockGameCaller) GetGameMetadata(_ context.Context, _ rpcblock.Block) (common.Hash, uint64, common.Hash, types.GameStatus, uint64, error) { + m.metadataCalls++ + if m.metadataErr != nil { + return common.Hash{}, 0, common.Hash{}, 0, 0, m.metadataErr + } + return common.Hash{0xaa}, 0, mockRootClaim, 0, 0, nil +} + +func (m *mockGameCaller) GetAllClaims(_ context.Context, _ rpcblock.Block) ([]faultTypes.Claim, error) { + m.claimsCalls++ + if m.claimsErr != nil { + return nil, m.claimsErr + } + return m.claims, nil +} + +func (m *mockGameCaller) GetCredits(_ context.Context, _ rpcblock.Block, recipients ...common.Address) ([]*big.Int, error) { + m.requestedCredits = recipients + if m.creditsErr != nil { + return nil, m.creditsErr + } + response := make([]*big.Int, 0, len(recipients)) + for _, recipient := range recipients { + credit, ok := m.credits[recipient] + if !ok { + credit = big.NewInt(0) + } + response = append(response, credit) + } + response = append(response, m.extraCredit...) + return response, nil +} + +func (m *mockGameCaller) GetBalance(_ context.Context, _ rpcblock.Block) (*big.Int, common.Address, error) { + if m.balanceErr != nil { + return nil, common.Address{}, m.balanceErr + } + return m.balance, m.balanceAddr, nil +} + +type mockEnricher struct { + err error + calls int +} + +func (m *mockEnricher) Enrich(_ context.Context, _ rpcblock.Block, _ GameCaller, _ *monTypes.EnrichedGameData) error { + m.calls++ + return m.err +} diff --git a/op-dispute-mon/mon/extract/head_enricher.go b/op-dispute-mon/mon/extract/head_enricher.go new file mode 100644 index 000000000000..943e648f771d --- /dev/null +++ b/op-dispute-mon/mon/extract/head_enricher.go @@ -0,0 +1,34 @@ +package extract + +import ( + "context" + "fmt" + + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +var _ Enricher = (*L1HeadBlockNumEnricher)(nil) + +type BlockFetcher interface { + HeaderByHash(ctx context.Context, block common.Hash) (*types.Header, error) +} + +type L1HeadBlockNumEnricher struct { + client BlockFetcher +} + +func NewL1HeadBlockNumEnricher(client BlockFetcher) *L1HeadBlockNumEnricher { + return &L1HeadBlockNumEnricher{client: client} +} + +func (e *L1HeadBlockNumEnricher) Enrich(ctx context.Context, _ rpcblock.Block, _ GameCaller, game *monTypes.EnrichedGameData) error { + header, err := e.client.HeaderByHash(ctx, game.L1Head) + if err != nil { + return fmt.Errorf("failed to retrieve header for L1 head block %v: %w", game.L1Head, err) + } + game.L1HeadNum = header.Number.Uint64() + return nil +} diff --git a/op-dispute-mon/mon/extract/head_enricher_test.go b/op-dispute-mon/mon/extract/head_enricher_test.go new file mode 100644 index 000000000000..c0cb03b86b7a --- /dev/null +++ b/op-dispute-mon/mon/extract/head_enricher_test.go @@ -0,0 +1,49 @@ +package extract + +import ( + "context" + "errors" + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum/go-ethereum/common" + gethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" +) + +func TestL1HeadEnricher(t *testing.T) { + t.Run("HeaderError", func(t *testing.T) { + client := &stubBlockFetcher{err: errors.New("boom")} + enricher := NewL1HeadBlockNumEnricher(client) + caller := &mockGameCaller{} + game := &types.EnrichedGameData{} + err := enricher.Enrich(context.Background(), rpcblock.Latest, caller, game) + require.ErrorIs(t, err, client.err) + }) + + t.Run("GetBalanceSuccess", func(t *testing.T) { + client := &stubBlockFetcher{num: 5000} + enricher := NewL1HeadBlockNumEnricher(client) + caller := &mockGameCaller{} + game := &types.EnrichedGameData{} + err := enricher.Enrich(context.Background(), rpcblock.Latest, caller, game) + require.NoError(t, err) + require.Equal(t, client.num, game.L1HeadNum) + }) +} + +type stubBlockFetcher struct { + num uint64 + err error +} + +func (s *stubBlockFetcher) HeaderByHash(_ context.Context, _ common.Hash) (*gethTypes.Header, error) { + if s.err != nil { + return nil, s.err + } + return &gethTypes.Header{ + Number: new(big.Int).SetUint64(s.num), + }, nil +} diff --git a/op-dispute-mon/mon/forecast.go b/op-dispute-mon/mon/forecast.go new file mode 100644 index 000000000000..b82a27a0129d --- /dev/null +++ b/op-dispute-mon/mon/forecast.go @@ -0,0 +1,138 @@ +package mon + +import ( + "context" + "errors" + "fmt" + + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-dispute-mon/metrics" + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/resolution" + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/transform" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum/go-ethereum/log" +) + +var ( + ErrRootAgreement = errors.New("failed to check root agreement") +) + +type OutputValidator interface { + CheckRootAgreement(ctx context.Context, l1HeadNum uint64, l2BlockNum uint64, root common.Hash) (bool, common.Hash, error) +} + +type ForecastMetrics interface { + RecordClaimResolutionDelayMax(delay float64) + RecordGameAgreement(status metrics.GameAgreementStatus, count int) +} + +type forecast struct { + logger log.Logger + metrics ForecastMetrics + validator OutputValidator +} + +func newForecast(logger log.Logger, metrics ForecastMetrics, validator OutputValidator) *forecast { + return &forecast{ + logger: logger, + metrics: metrics, + validator: validator, + } +} + +func (f *forecast) Forecast(ctx context.Context, games []*monTypes.EnrichedGameData) { + batch := monTypes.ForecastBatch{} + for _, game := range games { + if err := f.forecastGame(ctx, game, &batch); err != nil { + f.logger.Error("Failed to forecast game", "err", err) + } + } + f.recordBatch(batch) +} + +func (f *forecast) recordBatch(batch monTypes.ForecastBatch) { + f.metrics.RecordGameAgreement(metrics.AgreeDefenderWins, batch.AgreeDefenderWins) + f.metrics.RecordGameAgreement(metrics.DisagreeDefenderWins, batch.DisagreeDefenderWins) + f.metrics.RecordGameAgreement(metrics.AgreeChallengerWins, batch.AgreeChallengerWins) + f.metrics.RecordGameAgreement(metrics.DisagreeChallengerWins, batch.DisagreeChallengerWins) + + f.metrics.RecordGameAgreement(metrics.AgreeChallengerAhead, batch.AgreeChallengerAhead) + f.metrics.RecordGameAgreement(metrics.DisagreeChallengerAhead, batch.DisagreeChallengerAhead) + f.metrics.RecordGameAgreement(metrics.AgreeDefenderAhead, batch.AgreeDefenderAhead) + f.metrics.RecordGameAgreement(metrics.DisagreeDefenderAhead, batch.DisagreeDefenderAhead) +} + +func (f *forecast) forecastGame(ctx context.Context, game *monTypes.EnrichedGameData, metrics *monTypes.ForecastBatch) error { + // Check the root agreement. + agreement, expected, err := f.validator.CheckRootAgreement(ctx, game.L1HeadNum, game.L2BlockNumber, game.RootClaim) + if err != nil { + return fmt.Errorf("%w: %w", ErrRootAgreement, err) + } + + expectedResult := types.GameStatusDefenderWon + if !agreement { + expectedResult = types.GameStatusChallengerWon + } + + if game.Status != types.GameStatusInProgress { + if game.Status != expectedResult { + f.logger.Error("Unexpected game result", + "game", game.Proxy, "blockNum", game.L2BlockNumber, + "expectedResult", expectedResult, "actualResult", game.Status, + "rootClaim", game.RootClaim, "correctClaim", expected) + } + switch game.Status { + case types.GameStatusDefenderWon: + if agreement { + metrics.AgreeDefenderWins++ + } else { + metrics.DisagreeDefenderWins++ + } + case types.GameStatusChallengerWon: + if agreement { + metrics.AgreeChallengerWins++ + } else { + metrics.DisagreeChallengerWins++ + } + } + return nil + } + + // Create the bidirectional tree of claims. + tree := transform.CreateBidirectionalTree(game.Claims) + + // Compute the resolution status of the game. + forecastStatus := resolution.Resolve(tree) + + if agreement { + // If we agree with the output root proposal, the Defender should win, defending that claim. + if forecastStatus == types.GameStatusChallengerWon { + metrics.AgreeChallengerAhead++ + f.logger.Warn("Forecasting unexpected game result", "status", forecastStatus, + "game", game.Proxy, "blockNum", game.L2BlockNumber, + "rootClaim", game.RootClaim, "expected", expected) + } else { + metrics.AgreeDefenderAhead++ + f.logger.Debug("Forecasting expected game result", "status", forecastStatus, + "game", game.Proxy, "blockNum", game.L2BlockNumber, + "rootClaim", game.RootClaim, "expected", expected) + } + } else { + // If we disagree with the output root proposal, the Challenger should win, challenging that claim. + if forecastStatus == types.GameStatusDefenderWon { + metrics.DisagreeDefenderAhead++ + f.logger.Warn("Forecasting unexpected game result", "status", forecastStatus, + "game", game.Proxy, "blockNum", game.L2BlockNumber, + "rootClaim", game.RootClaim, "expected", expected) + } else { + metrics.DisagreeChallengerAhead++ + f.logger.Debug("Forecasting expected game result", "status", forecastStatus, + "game", game.Proxy, "blockNum", game.L2BlockNumber, + "rootClaim", game.RootClaim, "expected", expected) + } + } + + return nil +} diff --git a/op-dispute-mon/mon/forecast_test.go b/op-dispute-mon/mon/forecast_test.go new file mode 100644 index 000000000000..16a97f0fee1a --- /dev/null +++ b/op-dispute-mon/mon/forecast_test.go @@ -0,0 +1,332 @@ +package mon + +import ( + "context" + "errors" + "fmt" + "math" + "math/big" + "testing" + + faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum-optimism/optimism/op-dispute-mon/metrics" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +var ( + failedForecastLog = "Failed to forecast game" + lostGameLog = "Unexpected game result" + unexpectedResultLog = "Forecasting unexpected game result" + expectedResultLog = "Forecasting expected game result" +) + +func TestForecast_Forecast_BasicTests(t *testing.T) { + t.Parallel() + + t.Run("NoGames", func(t *testing.T) { + forecast, _, rollup, logs := setupForecastTest(t) + forecast.Forecast(context.Background(), []*monTypes.EnrichedGameData{}) + require.Equal(t, 0, rollup.calls) + levelFilter := testlog.NewLevelFilter(log.LevelError) + messageFilter := testlog.NewMessageFilter(failedForecastLog) + require.Nil(t, logs.FindLog(levelFilter, messageFilter)) + }) + + t.Run("RollupFetchFails", func(t *testing.T) { + forecast, _, rollup, logs := setupForecastTest(t) + rollup.err = errors.New("boom") + forecast.Forecast(context.Background(), []*monTypes.EnrichedGameData{{}}) + require.Equal(t, 1, rollup.calls) + levelFilter := testlog.NewLevelFilter(log.LevelError) + messageFilter := testlog.NewMessageFilter(failedForecastLog) + l := logs.FindLog(levelFilter, messageFilter) + require.NotNil(t, l) + err := l.AttrValue("err") + expectedErr := fmt.Errorf("%w: %w", ErrRootAgreement, rollup.err) + require.Equal(t, expectedErr, err) + }) + + t.Run("ChallengerWonGame_Agree", func(t *testing.T) { + forecast, m, _, logs := setupForecastTest(t) + expectedGame := monTypes.EnrichedGameData{Status: types.GameStatusChallengerWon, RootClaim: mockRootClaim} + forecast.Forecast(context.Background(), []*monTypes.EnrichedGameData{&expectedGame}) + l := logs.FindLog(testlog.NewLevelFilter(log.LevelError), testlog.NewMessageFilter(lostGameLog)) + require.NotNil(t, l) + require.Equal(t, expectedGame.Proxy, l.AttrValue("game")) + require.Equal(t, types.GameStatusDefenderWon, l.AttrValue("expectedResult")) + require.Equal(t, types.GameStatusChallengerWon, l.AttrValue("actualResult")) + + expectedMetrics := zeroGameAgreement() + expectedMetrics[metrics.AgreeChallengerWins] = 1 + require.Equal(t, expectedMetrics, m.gameAgreement) + }) + + t.Run("ChallengerWonGame_Disagree", func(t *testing.T) { + forecast, m, _, logs := setupForecastTest(t) + expectedGame := monTypes.EnrichedGameData{Status: types.GameStatusChallengerWon, RootClaim: common.Hash{0xbb}} + forecast.Forecast(context.Background(), []*monTypes.EnrichedGameData{&expectedGame}) + l := logs.FindLog(testlog.NewLevelFilter(log.LevelError), testlog.NewMessageFilter(lostGameLog)) + require.Nil(t, l) + + expectedMetrics := zeroGameAgreement() + expectedMetrics[metrics.DisagreeChallengerWins] = 1 + require.Equal(t, expectedMetrics, m.gameAgreement) + }) + + t.Run("DefenderWonGame_Agree", func(t *testing.T) { + forecast, m, _, logs := setupForecastTest(t) + expectedGame := monTypes.EnrichedGameData{Status: types.GameStatusDefenderWon, RootClaim: mockRootClaim} + forecast.Forecast(context.Background(), []*monTypes.EnrichedGameData{&expectedGame}) + l := logs.FindLog(testlog.NewLevelFilter(log.LevelError), testlog.NewMessageFilter(lostGameLog)) + require.Nil(t, l) + + expectedMetrics := zeroGameAgreement() + expectedMetrics[metrics.AgreeDefenderWins] = 1 + require.Equal(t, expectedMetrics, m.gameAgreement) + }) + + t.Run("DefenderWonGame_Disagree", func(t *testing.T) { + forecast, m, _, logs := setupForecastTest(t) + expectedGame := monTypes.EnrichedGameData{Status: types.GameStatusDefenderWon, RootClaim: common.Hash{0xbb}} + forecast.Forecast(context.Background(), []*monTypes.EnrichedGameData{&expectedGame}) + l := logs.FindLog(testlog.NewLevelFilter(log.LevelError), testlog.NewMessageFilter(lostGameLog)) + require.NotNil(t, l) + require.Equal(t, expectedGame.Proxy, l.AttrValue("game")) + require.Equal(t, types.GameStatusChallengerWon, l.AttrValue("expectedResult")) + require.Equal(t, types.GameStatusDefenderWon, l.AttrValue("actualResult")) + + expectedMetrics := zeroGameAgreement() + expectedMetrics[metrics.DisagreeDefenderWins] = 1 + require.Equal(t, expectedMetrics, m.gameAgreement) + }) + + t.Run("SingleGame", func(t *testing.T) { + forecast, _, rollup, logs := setupForecastTest(t) + forecast.Forecast(context.Background(), []*monTypes.EnrichedGameData{{}}) + require.Equal(t, 1, rollup.calls) + require.Nil(t, logs.FindLog(testlog.NewLevelFilter(log.LevelError), testlog.NewMessageFilter(failedForecastLog))) + }) + + t.Run("MultipleGames", func(t *testing.T) { + forecast, _, rollup, logs := setupForecastTest(t) + forecast.Forecast(context.Background(), []*monTypes.EnrichedGameData{{}, {}, {}}) + require.Equal(t, 3, rollup.calls) + require.Nil(t, logs.FindLog(testlog.NewLevelFilter(log.LevelError), testlog.NewMessageFilter(failedForecastLog))) + }) +} + +func TestForecast_Forecast_EndLogs(t *testing.T) { + t.Parallel() + + t.Run("AgreeDefenderWins", func(t *testing.T) { + forecast, _, rollup, logs := setupForecastTest(t) + games := []*monTypes.EnrichedGameData{{ + Status: types.GameStatusInProgress, + RootClaim: mockRootClaim, + Claims: createDeepClaimList()[:1], + }} + forecast.Forecast(context.Background(), games) + require.Equal(t, 1, rollup.calls) + levelFilter := testlog.NewLevelFilter(log.LevelError) + messageFilter := testlog.NewMessageFilter(failedForecastLog) + require.Nil(t, logs.FindLog(levelFilter, messageFilter)) + levelFilter = testlog.NewLevelFilter(log.LevelDebug) + messageFilter = testlog.NewMessageFilter(expectedResultLog) + l := logs.FindLog(levelFilter, messageFilter) + require.NotNil(t, l) + require.Equal(t, mockRootClaim, l.AttrValue("rootClaim")) + require.Equal(t, mockRootClaim, l.AttrValue("expected")) + require.Equal(t, types.GameStatusDefenderWon, l.AttrValue("status")) + }) + + t.Run("AgreeChallengerWins", func(t *testing.T) { + forecast, _, rollup, logs := setupForecastTest(t) + games := []*monTypes.EnrichedGameData{{ + Status: types.GameStatusInProgress, + RootClaim: mockRootClaim, + Claims: createDeepClaimList()[:2], + }} + forecast.Forecast(context.Background(), games) + require.Equal(t, 1, rollup.calls) + levelFilter := testlog.NewLevelFilter(log.LevelError) + messageFilter := testlog.NewMessageFilter(failedForecastLog) + require.Nil(t, logs.FindLog(levelFilter, messageFilter)) + levelFilter = testlog.NewLevelFilter(log.LevelWarn) + messageFilter = testlog.NewMessageFilter(unexpectedResultLog) + l := logs.FindLog(levelFilter, messageFilter) + require.NotNil(t, l) + require.Equal(t, mockRootClaim, l.AttrValue("rootClaim")) + require.Equal(t, mockRootClaim, l.AttrValue("expected")) + require.Equal(t, types.GameStatusChallengerWon, l.AttrValue("status")) + }) + + t.Run("DisagreeChallengerWins", func(t *testing.T) { + forecast, _, rollup, logs := setupForecastTest(t) + forecast.Forecast(context.Background(), []*monTypes.EnrichedGameData{{ + Status: types.GameStatusInProgress, + Claims: createDeepClaimList()[:2], + }}) + require.Equal(t, 1, rollup.calls) + levelFilter := testlog.NewLevelFilter(log.LevelError) + messageFilter := testlog.NewMessageFilter(failedForecastLog) + require.Nil(t, logs.FindLog(levelFilter, messageFilter)) + levelFilter = testlog.NewLevelFilter(log.LevelDebug) + messageFilter = testlog.NewMessageFilter(expectedResultLog) + l := logs.FindLog(levelFilter, messageFilter) + require.NotNil(t, l) + require.Equal(t, common.Hash{}, l.AttrValue("rootClaim")) + require.Equal(t, mockRootClaim, l.AttrValue("expected")) + require.Equal(t, types.GameStatusChallengerWon, l.AttrValue("status")) + }) + + t.Run("DisagreeDefenderWins", func(t *testing.T) { + forecast, _, rollup, logs := setupForecastTest(t) + forecast.Forecast(context.Background(), []*monTypes.EnrichedGameData{{ + Status: types.GameStatusInProgress, + Claims: createDeepClaimList()[:1], + }}) + require.Equal(t, 1, rollup.calls) + levelFilter := testlog.NewLevelFilter(log.LevelError) + messageFilter := testlog.NewMessageFilter(failedForecastLog) + require.Nil(t, logs.FindLog(levelFilter, messageFilter)) + levelFilter = testlog.NewLevelFilter(log.LevelWarn) + messageFilter = testlog.NewMessageFilter(unexpectedResultLog) + l := logs.FindLog(levelFilter, messageFilter) + require.NotNil(t, l) + require.Equal(t, common.Hash{}, l.AttrValue("rootClaim")) + require.Equal(t, mockRootClaim, l.AttrValue("expected")) + require.Equal(t, types.GameStatusDefenderWon, l.AttrValue("status")) + }) +} + +func TestForecast_Forecast_MultipleGames(t *testing.T) { + forecast, _, rollup, logs := setupForecastTest(t) + gameStatus := []types.GameStatus{ + types.GameStatusChallengerWon, + types.GameStatusInProgress, + types.GameStatusInProgress, + types.GameStatusDefenderWon, + types.GameStatusInProgress, + types.GameStatusInProgress, + types.GameStatusDefenderWon, + types.GameStatusChallengerWon, + types.GameStatusChallengerWon, + } + claims := [][]faultTypes.Claim{ + createDeepClaimList()[:1], + createDeepClaimList()[:2], + createDeepClaimList()[:2], + createDeepClaimList()[:1], + createDeepClaimList()[:1], + createDeepClaimList()[:1], + createDeepClaimList()[:1], + createDeepClaimList()[:1], + createDeepClaimList()[:1], + } + rootClaims := []common.Hash{ + {}, + {}, + mockRootClaim, + {}, + {}, + mockRootClaim, + {}, + {}, + {}, + } + games := make([]*monTypes.EnrichedGameData, 9) + for i := range games { + games[i] = &monTypes.EnrichedGameData{ + Status: gameStatus[i], + Claims: claims[i], + RootClaim: rootClaims[i], + } + } + forecast.Forecast(context.Background(), games) + require.Equal(t, len(games), rollup.calls) + levelFilter := testlog.NewLevelFilter(log.LevelError) + messageFilter := testlog.NewMessageFilter(failedForecastLog) + require.Nil(t, logs.FindLog(levelFilter, messageFilter)) +} + +func setupForecastTest(t *testing.T) (*forecast, *mockForecastMetrics, *stubOutputValidator, *testlog.CapturingHandler) { + logger, capturedLogs := testlog.CaptureLogger(t, log.LvlDebug) + validator := &stubOutputValidator{} + metrics := &mockForecastMetrics{ + gameAgreement: zeroGameAgreement(), + } + return newForecast(logger, metrics, validator), metrics, validator, capturedLogs +} + +func zeroGameAgreement() map[metrics.GameAgreementStatus]int { + return map[metrics.GameAgreementStatus]int{ + metrics.AgreeChallengerAhead: 0, + metrics.DisagreeChallengerAhead: 0, + metrics.AgreeDefenderAhead: 0, + metrics.DisagreeDefenderAhead: 0, + metrics.AgreeDefenderWins: 0, + metrics.DisagreeDefenderWins: 0, + metrics.AgreeChallengerWins: 0, + metrics.DisagreeChallengerWins: 0, + } +} + +type mockForecastMetrics struct { + gameAgreement map[metrics.GameAgreementStatus]int + claimResolutionDelayMax float64 +} + +func (m *mockForecastMetrics) RecordGameAgreement(status metrics.GameAgreementStatus, count int) { + m.gameAgreement[status] = count +} + +func (m *mockForecastMetrics) RecordClaimResolutionDelayMax(delay float64) { + m.claimResolutionDelayMax = delay +} + +func createDeepClaimList() []faultTypes.Claim { + return []faultTypes.Claim{ + { + ClaimData: faultTypes.ClaimData{ + Position: faultTypes.NewPosition(0, big.NewInt(0)), + }, + ContractIndex: 0, + ParentContractIndex: math.MaxInt64, + Claimant: common.HexToAddress("0x111111"), + }, + { + ClaimData: faultTypes.ClaimData{ + Position: faultTypes.NewPosition(1, big.NewInt(0)), + }, + ContractIndex: 1, + ParentContractIndex: 0, + Claimant: common.HexToAddress("0x222222"), + }, + { + ClaimData: faultTypes.ClaimData{ + Position: faultTypes.NewPosition(2, big.NewInt(0)), + }, + ContractIndex: 2, + ParentContractIndex: 1, + Claimant: common.HexToAddress("0x111111"), + }, + } +} + +type stubOutputValidator struct { + calls int + err error +} + +func (s *stubOutputValidator) CheckRootAgreement(_ context.Context, _ uint64, _ uint64, rootClaim common.Hash) (bool, common.Hash, error) { + s.calls++ + if s.err != nil { + return false, common.Hash{}, s.err + } + return rootClaim == mockRootClaim, mockRootClaim, nil +} diff --git a/op-dispute-mon/mon/monitor.go b/op-dispute-mon/mon/monitor.go new file mode 100644 index 000000000000..5e8fe55df2df --- /dev/null +++ b/op-dispute-mon/mon/monitor.go @@ -0,0 +1,128 @@ +package mon + +import ( + "context" + "fmt" + "math/big" + "time" + + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/clock" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" +) + +type Forecast func(ctx context.Context, games []*types.EnrichedGameData) +type Bonds func(games []*types.EnrichedGameData) +type BlockHashFetcher func(ctx context.Context, number *big.Int) (common.Hash, error) +type BlockNumberFetcher func(ctx context.Context) (uint64, error) +type Extract func(ctx context.Context, blockHash common.Hash, minTimestamp uint64) ([]*types.EnrichedGameData, error) +type RecordClaimResolutionDelayMax func([]*types.EnrichedGameData) + +type gameMonitor struct { + logger log.Logger + clock clock.Clock + + done chan struct{} + ctx context.Context + cancel context.CancelFunc + + gameWindow time.Duration + monitorInterval time.Duration + + delays RecordClaimResolutionDelayMax + forecast Forecast + bonds Bonds + extract Extract + fetchBlockHash BlockHashFetcher + fetchBlockNumber BlockNumberFetcher +} + +func newGameMonitor( + ctx context.Context, + logger log.Logger, + cl clock.Clock, + monitorInterval time.Duration, + gameWindow time.Duration, + delays RecordClaimResolutionDelayMax, + forecast Forecast, + bonds Bonds, + extract Extract, + fetchBlockNumber BlockNumberFetcher, + fetchBlockHash BlockHashFetcher, +) *gameMonitor { + return &gameMonitor{ + logger: logger, + clock: cl, + ctx: ctx, + done: make(chan struct{}), + monitorInterval: monitorInterval, + gameWindow: gameWindow, + delays: delays, + forecast: forecast, + bonds: bonds, + extract: extract, + fetchBlockNumber: fetchBlockNumber, + fetchBlockHash: fetchBlockHash, + } +} + +func (m *gameMonitor) monitorGames() error { + blockNumber, err := m.fetchBlockNumber(m.ctx) + if err != nil { + return fmt.Errorf("failed to fetch block number: %w", err) + } + m.logger.Debug("Fetched block number", "blockNumber", blockNumber) + blockHash, err := m.fetchBlockHash(context.Background(), new(big.Int).SetUint64(blockNumber)) + if err != nil { + return fmt.Errorf("failed to fetch block hash: %w", err) + } + minGameTimestamp := clock.MinCheckedTimestamp(m.clock, m.gameWindow) + enrichedGames, err := m.extract(m.ctx, blockHash, minGameTimestamp) + if err != nil { + return fmt.Errorf("failed to load games: %w", err) + } + m.delays(enrichedGames) + m.forecast(m.ctx, enrichedGames) + m.bonds(enrichedGames) + return nil +} + +func (m *gameMonitor) loop() { + ticker := m.clock.NewTicker(m.monitorInterval) + defer ticker.Stop() + for { + select { + case <-ticker.Ch(): + if err := m.monitorGames(); err != nil { + m.logger.Error("Failed to monitor games", "err", err) + } + case <-m.done: + m.logger.Info("Stopping game monitor") + return + } + } +} + +func (m *gameMonitor) StartMonitoring() { + // Setup the cancellation only if it's not already set. + // This prevents overwriting the context and cancel function + // if, for example, this function is called multiple times. + if m.cancel == nil { + ctx, cancel := context.WithCancel(m.ctx) + m.ctx = ctx + m.cancel = cancel + } + m.logger.Info("Starting game monitor") + go m.loop() +} + +func (m *gameMonitor) StopMonitoring() { + m.logger.Info("Stopping game monitor") + if m.cancel != nil { + m.cancel() + m.cancel = nil + } + close(m.done) +} diff --git a/op-dispute-mon/mon/monitor_test.go b/op-dispute-mon/mon/monitor_test.go new file mode 100644 index 000000000000..6127d145fbef --- /dev/null +++ b/op-dispute-mon/mon/monitor_test.go @@ -0,0 +1,181 @@ +package mon + +import ( + "context" + "errors" + "math/big" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/clock" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +var ( + mockErr = errors.New("mock error") +) + +func TestMonitor_MonitorGames(t *testing.T) { + t.Parallel() + + t.Run("FailedFetchBlocknumber", func(t *testing.T) { + monitor, _, _, _, _ := setupMonitorTest(t) + boom := errors.New("boom") + monitor.fetchBlockNumber = func(ctx context.Context) (uint64, error) { + return 0, boom + } + err := monitor.monitorGames() + require.ErrorIs(t, err, boom) + }) + + t.Run("FailedFetchBlockHash", func(t *testing.T) { + monitor, _, _, _, _ := setupMonitorTest(t) + boom := errors.New("boom") + monitor.fetchBlockHash = func(ctx context.Context, number *big.Int) (common.Hash, error) { + return common.Hash{}, boom + } + err := monitor.monitorGames() + require.ErrorIs(t, err, boom) + }) + + t.Run("MonitorsWithNoGames", func(t *testing.T) { + monitor, factory, forecast, delays, bonds := setupMonitorTest(t) + factory.games = []*monTypes.EnrichedGameData{} + err := monitor.monitorGames() + require.NoError(t, err) + require.Equal(t, 1, forecast.calls) + require.Equal(t, 1, delays.calls) + require.Equal(t, 1, bonds.calls) + }) + + t.Run("MonitorsMultipleGames", func(t *testing.T) { + monitor, factory, forecast, delays, bonds := setupMonitorTest(t) + factory.games = []*monTypes.EnrichedGameData{{}, {}, {}} + err := monitor.monitorGames() + require.NoError(t, err) + require.Equal(t, 1, forecast.calls) + require.Equal(t, 1, delays.calls) + require.Equal(t, 1, bonds.calls) + }) +} + +func TestMonitor_StartMonitoring(t *testing.T) { + t.Run("MonitorsGames", func(t *testing.T) { + addr1 := common.Address{0xaa} + addr2 := common.Address{0xbb} + monitor, factory, forecaster, _, _ := setupMonitorTest(t) + factory.games = []*monTypes.EnrichedGameData{newEnrichedGameData(addr1, 9999), newEnrichedGameData(addr2, 9999)} + factory.maxSuccess = len(factory.games) // Only allow two successful fetches + + monitor.StartMonitoring() + require.Eventually(t, func() bool { + return forecaster.calls >= 2 + }, time.Second, 50*time.Millisecond) + monitor.StopMonitoring() + require.Equal(t, len(factory.games), forecaster.calls) // Each game's status is recorded twice + }) + + t.Run("FailsToFetchGames", func(t *testing.T) { + monitor, factory, forecaster, _, _ := setupMonitorTest(t) + factory.fetchErr = errors.New("boom") + + monitor.StartMonitoring() + require.Eventually(t, func() bool { + return factory.calls > 0 + }, time.Second, 50*time.Millisecond) + monitor.StopMonitoring() + require.Equal(t, 0, forecaster.calls) + }) +} + +func newEnrichedGameData(proxy common.Address, timestamp uint64) *monTypes.EnrichedGameData { + return &monTypes.EnrichedGameData{ + GameMetadata: types.GameMetadata{ + Proxy: proxy, + Timestamp: timestamp, + }, + Status: types.GameStatusInProgress, + } +} + +func setupMonitorTest(t *testing.T) (*gameMonitor, *mockExtractor, *mockForecast, *mockDelayCalculator, *mockBonds) { + logger := testlog.Logger(t, log.LvlDebug) + fetchBlockNum := func(ctx context.Context) (uint64, error) { + return 1, nil + } + fetchBlockHash := func(ctx context.Context, number *big.Int) (common.Hash, error) { + return common.Hash{}, nil + } + monitorInterval := 100 * time.Millisecond + cl := clock.NewAdvancingClock(10 * time.Millisecond) + cl.Start() + extractor := &mockExtractor{} + forecast := &mockForecast{} + bonds := &mockBonds{} + delays := &mockDelayCalculator{} + monitor := newGameMonitor( + context.Background(), + logger, + cl, + monitorInterval, + 10*time.Second, + delays.RecordClaimResolutionDelayMax, + forecast.Forecast, + bonds.CheckBonds, + extractor.Extract, + fetchBlockNum, + fetchBlockHash, + ) + return monitor, extractor, forecast, delays, bonds +} + +type mockDelayCalculator struct { + calls int +} + +func (m *mockDelayCalculator) RecordClaimResolutionDelayMax(games []*monTypes.EnrichedGameData) { + m.calls++ +} + +type mockForecast struct { + calls int +} + +func (m *mockForecast) Forecast(ctx context.Context, games []*monTypes.EnrichedGameData) { + m.calls++ +} + +type mockBonds struct { + calls int +} + +func (m *mockBonds) CheckBonds(_ []*monTypes.EnrichedGameData) { + m.calls++ +} + +type mockExtractor struct { + fetchErr error + calls int + maxSuccess int + games []*monTypes.EnrichedGameData +} + +func (m *mockExtractor) Extract( + _ context.Context, + _ common.Hash, + _ uint64, +) ([]*monTypes.EnrichedGameData, error) { + m.calls++ + if m.fetchErr != nil { + return nil, m.fetchErr + } + if m.calls > m.maxSuccess && m.maxSuccess != 0 { + return nil, mockErr + } + return m.games, nil +} diff --git a/op-dispute-mon/mon/resolution/delay.go b/op-dispute-mon/mon/resolution/delay.go new file mode 100644 index 000000000000..5067f3aa7f95 --- /dev/null +++ b/op-dispute-mon/mon/resolution/delay.go @@ -0,0 +1,52 @@ +package resolution + +import ( + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/clock" +) + +type DelayMetrics interface { + RecordClaimResolutionDelayMax(delay float64) +} + +type DelayCalculator struct { + metrics DelayMetrics + clock clock.Clock +} + +func NewDelayCalculator(metrics DelayMetrics, clock clock.Clock) *DelayCalculator { + return &DelayCalculator{ + metrics: metrics, + clock: clock, + } +} + +func (d *DelayCalculator) RecordClaimResolutionDelayMax(games []*monTypes.EnrichedGameData) { + var maxDelay uint64 = 0 + for _, game := range games { + maxDelay = max(d.getMaxResolutionDelay(game), maxDelay) + } + d.metrics.RecordClaimResolutionDelayMax(float64(maxDelay)) +} + +func (d *DelayCalculator) getMaxResolutionDelay(game *monTypes.EnrichedGameData) uint64 { + var maxDelay uint64 = 0 + for _, claim := range game.Claims { + maxDelay = max(d.getOverflowTime(game.Duration, &claim), maxDelay) + } + return maxDelay +} + +func (d *DelayCalculator) getOverflowTime(maxGameDuration uint64, claim *types.Claim) uint64 { + // If the bond amount is the max uint128 value, the claim is resolved. + if monTypes.ResolvedBondAmount.Cmp(claim.ClaimData.Bond) == 0 { + return 0 + } + maxChessTime := maxGameDuration / 2 + accumulatedTime := uint64(claim.ChessTime(d.clock.Now())) + if accumulatedTime < maxChessTime { + return 0 + } + return accumulatedTime - maxChessTime +} diff --git a/op-dispute-mon/mon/resolution/delay_test.go b/op-dispute-mon/mon/resolution/delay_test.go new file mode 100644 index 000000000000..355a846e7c9d --- /dev/null +++ b/op-dispute-mon/mon/resolution/delay_test.go @@ -0,0 +1,181 @@ +package resolution + +import ( + "math/big" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum-optimism/optimism/op-service/clock" + "github.com/stretchr/testify/require" +) + +var ( + maxGameDuration = uint64(960) + frozen = time.Unix(int64(time.Hour.Seconds()), 0) +) + +func TestDelayCalculator_getOverflowTime(t *testing.T) { + t.Run("NoClock", func(t *testing.T) { + d, metrics, _ := setupDelayCalculatorTest(t) + claim := &types.Claim{ + ClaimData: types.ClaimData{ + Bond: monTypes.ResolvedBondAmount, + }, + } + delay := d.getOverflowTime(maxGameDuration, claim) + require.Equal(t, uint64(0), delay) + require.Equal(t, 0, metrics.calls) + }) + + t.Run("RemainingTime", func(t *testing.T) { + d, metrics, cl := setupDelayCalculatorTest(t) + duration := uint64(3 * 60) + timestamp := uint64(cl.Now().Add(-time.Minute).Unix()) + claim := &types.Claim{ + ClaimData: types.ClaimData{ + Bond: big.NewInt(5), + }, + Clock: types.NewClock(duration, timestamp), + } + delay := d.getOverflowTime(maxGameDuration, claim) + require.Equal(t, uint64(0), delay) + require.Equal(t, 0, metrics.calls) + }) + + t.Run("OverflowTime", func(t *testing.T) { + d, metrics, cl := setupDelayCalculatorTest(t) + duration := maxGameDuration / 2 + timestamp := uint64(cl.Now().Add(4 * -time.Minute).Unix()) + claim := &types.Claim{ + ClaimData: types.ClaimData{ + Bond: big.NewInt(5), + }, + Clock: types.NewClock(duration, timestamp), + } + delay := d.getOverflowTime(maxGameDuration, claim) + require.Equal(t, uint64(240), delay) + require.Equal(t, 0, metrics.calls) + }) +} + +func TestDelayCalculator_getMaxResolutionDelay(t *testing.T) { + tests := []struct { + name string + claims []types.Claim + want uint64 + }{ + {"NoClaims", []types.Claim{}, 0}, + {"SingleClaim", createClaimList()[:1], 180}, + {"MultipleClaims", createClaimList()[:2], 300}, + {"ClaimsWithMaxUint128", createClaimList(), 300}, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + d, metrics, _ := setupDelayCalculatorTest(t) + game := &monTypes.EnrichedGameData{ + Claims: test.claims, + Duration: maxGameDuration, + } + got := d.getMaxResolutionDelay(game) + require.Equal(t, 0, metrics.calls) + require.Equal(t, test.want, got) + }) + } +} + +func TestDelayCalculator_RecordClaimResolutionDelayMax(t *testing.T) { + tests := []struct { + name string + games []*monTypes.EnrichedGameData + want float64 + }{ + {"NoGames", createGameWithClaimsList()[:0], 0}, + {"SingleGame", createGameWithClaimsList()[:1], 180}, + {"MultipleGames", createGameWithClaimsList()[:2], 300}, + {"ClaimsWithMaxUint128", createGameWithClaimsList(), 300}, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + d, metrics, _ := setupDelayCalculatorTest(t) + d.RecordClaimResolutionDelayMax(test.games) + require.Equal(t, 1, metrics.calls) + require.Equal(t, test.want, metrics.maxDelay) + }) + } +} + +func setupDelayCalculatorTest(t *testing.T) (*DelayCalculator, *mockDelayMetrics, *clock.DeterministicClock) { + metrics := &mockDelayMetrics{} + cl := clock.NewDeterministicClock(frozen) + return NewDelayCalculator(metrics, cl), metrics, cl +} + +func createGameWithClaimsList() []*monTypes.EnrichedGameData { + return []*monTypes.EnrichedGameData{ + { + Claims: createClaimList()[:1], + Duration: maxGameDuration, + }, + { + Claims: createClaimList()[:2], + Duration: maxGameDuration, + }, + { + Claims: createClaimList(), + Duration: maxGameDuration, + }, + } +} + +func createClaimList() []types.Claim { + newClock := func(multiplier int) *types.Clock { + duration := maxGameDuration / 2 + timestamp := uint64(frozen.Add(-time.Minute * time.Duration(multiplier)).Unix()) + return types.NewClock(duration, timestamp) + } + return []types.Claim{ + { + ClaimData: types.ClaimData{ + Bond: big.NewInt(5), + }, + Clock: newClock(3), + }, + { + ClaimData: types.ClaimData{ + Bond: big.NewInt(10), + }, + Clock: newClock(5), + }, + { + ClaimData: types.ClaimData{ + Bond: big.NewInt(100), + }, + Clock: newClock(2), + }, + { + // This claim should be skipped because it's resolved. + ClaimData: types.ClaimData{ + Bond: monTypes.ResolvedBondAmount, + }, + Clock: newClock(10), + }, + } +} + +type mockDelayMetrics struct { + calls int + maxDelay float64 +} + +func (m *mockDelayMetrics) RecordClaimResolutionDelayMax(delay float64) { + m.calls++ + if delay > m.maxDelay { + m.maxDelay = delay + } +} diff --git a/op-dispute-mon/mon/resolution/resolver.go b/op-dispute-mon/mon/resolution/resolver.go new file mode 100644 index 000000000000..a27ebaadac63 --- /dev/null +++ b/op-dispute-mon/mon/resolution/resolver.go @@ -0,0 +1,36 @@ +package resolution + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" +) + +// Resolve iterates backwards over the bidirectional tree, iteratively +// checking the leftmost counter of each claim, and updating the claim's counter +// claimant. Once the root claim is reached, the resolution game status is returned. +func Resolve(tree *monTypes.BidirectionalTree) gameTypes.GameStatus { + for i := len(tree.Claims) - 1; i >= 0; i-- { + claim := tree.Claims[i] + counterClaimant := claim.Claim.CounteredBy + var leftmostCounter *big.Int + for _, child := range claim.Children { + if child.Claim.CounteredBy != (common.Address{}) { + continue // Ignore countered claims + } + if leftmostCounter == nil || child.Claim.Position.IndexAtDepth().Cmp(leftmostCounter) < 0 { + counterClaimant = child.Claim.Claimant + leftmostCounter = child.Claim.Position.IndexAtDepth() + } + } + claim.Claim.CounteredBy = counterClaimant + } + if (len(tree.Claims) == 0 || tree.Claims[0].Claim.CounteredBy == common.Address{}) { + return gameTypes.GameStatusDefenderWon + } else { + return gameTypes.GameStatusChallengerWon + } +} diff --git a/op-dispute-mon/mon/resolution/resolver_test.go b/op-dispute-mon/mon/resolution/resolver_test.go new file mode 100644 index 000000000000..d949b2285ce5 --- /dev/null +++ b/op-dispute-mon/mon/resolution/resolver_test.go @@ -0,0 +1,169 @@ +package resolution + +import ( + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/test" + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/transform" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" +) + +func TestResolver_Resolve(t *testing.T) { + t.Run("NoClaims", func(t *testing.T) { + tree := transform.CreateBidirectionalTree([]faultTypes.Claim{}) + status := Resolve(tree) + require.Equal(t, gameTypes.GameStatusDefenderWon, status) + }) + + t.Run("SingleRootClaim", func(t *testing.T) { + builder := test.NewAlphabetClaimBuilder(t, big.NewInt(10), 4).GameBuilder() + tree := transform.CreateBidirectionalTree(builder.Game.Claims()) + tree.Claims[0].Claim.CounteredBy = common.Address{} + status := Resolve(tree) + require.Equal(t, gameTypes.GameStatusDefenderWon, status) + }) + + t.Run("ManyClaims_ChallengerWon", func(t *testing.T) { + builder := test.NewAlphabetClaimBuilder(t, big.NewInt(10), 5).GameBuilder() + builder.Seq(). // Defender winning + Attack(). // Challenger winning + Attack(). // Defender winning + Defend(). // Challenger winning + Defend(). // Defender winning + Attack() // Challenger winning + tree := transform.CreateBidirectionalTree(builder.Game.Claims()) + status := Resolve(tree) + require.Equal(t, gameTypes.GameStatusChallengerWon, status) + }) + + t.Run("ManyClaims_DefenderWon", func(t *testing.T) { + builder := test.NewAlphabetClaimBuilder(t, big.NewInt(10), 5).GameBuilder() + builder.Seq(). // Defender winning + Attack(). // Challenger winning + Attack(). // Defender winning + Defend(). // Challenger winning + Defend() // Defender winning + tree := transform.CreateBidirectionalTree(builder.Game.Claims()) + status := Resolve(tree) + require.Equal(t, gameTypes.GameStatusDefenderWon, status) + }) + + t.Run("MultipleBranches_ChallengerWon", func(t *testing.T) { + builder := test.NewAlphabetClaimBuilder(t, big.NewInt(10), 5).GameBuilder() + forkPoint := builder.Seq(). // Defender winning + Attack(). // Challenger winning + Attack() // Defender winning + forkPoint. + Defend(). // Challenger winning + Defend(). // Defender winning + Attack() // Challenger winning + forkPoint.Defend(test.WithValue(common.Hash{0xbb})). // Challenger winning + Defend(). // Defender winning + Attack(). // Challenger winning + Step() // Defender winning + forkPoint.Defend(test.WithValue(common.Hash{0xcc})). // Challenger winning + Defend() // Defender winning + tree := transform.CreateBidirectionalTree(builder.Game.Claims()) + status := Resolve(tree) + // First fork has an uncountered claim with challenger winning so that invalidates the parent and wins the game + require.Equal(t, gameTypes.GameStatusChallengerWon, status) + }) + + t.Run("MultipleBranches_DefenderWon", func(t *testing.T) { + builder := test.NewAlphabetClaimBuilder(t, big.NewInt(10), 5).GameBuilder() + forkPoint := builder.Seq(). // Defender winning + Attack(). // Challenger winning + Attack() // Defender winning + forkPoint. + Defend(). // Challenger winning + Defend() // Defender winning + forkPoint.Defend(test.WithValue(common.Hash{0xbb})). // Challenger winning + Defend(). // Defender winning + Attack(). // Challenger winning + Step() // Defender winning + forkPoint.Defend(test.WithValue(common.Hash{0xcc})). // Challenger winning + Defend() // Defender winning + + tree := transform.CreateBidirectionalTree(builder.Game.Claims()) + status := Resolve(tree) + // Defender won all forks + require.Equal(t, gameTypes.GameStatusDefenderWon, status) + }) + + t.Run("UseLeftMostUncounteredClaim", func(t *testing.T) { + builder := test.NewAlphabetClaimBuilder(t, big.NewInt(10), 5).GameBuilder() + expectedRootCounteredBy := common.Address{0xaa} + forkPoint := builder.Seq(). // Defender winning + Attack(test.WithClaimant(expectedRootCounteredBy)). // Challenger winning + Attack() // Defender winning + + // Left most child of forkPoint, but has been countered + forkPoint. + Attack(test.WithValue(common.Hash{0xaa}), test.WithClaimant(common.Address{0xbb})). + Defend() + + // Uncountered child, but not leftmost + forkPoint. + Defend(test.WithValue(common.Hash{0xbb}), test.WithClaimant(common.Address{0xcc})). // Challenger winning + Defend(). // Defender winning + Defend() // Challenger winning + + // Left most child that is ultimately uncountered and should be used as CounteredBy + expectedCounteredBy := common.Address{0xdd} + forkPoint. + Attack(test.WithClaimant(expectedCounteredBy)). + Defend(). + Defend() + + // Uncountered child, + forkPoint. + Defend(test.WithClaimant(common.Address{0xee})). // Challenger winning + Defend(). // Defender winning + Defend() // Challenger winning + tree := transform.CreateBidirectionalTree(builder.Game.Claims()) + status := Resolve(tree) + // Defender won all forks + require.Equal(t, gameTypes.GameStatusChallengerWon, status) + forkPointClaim := tree.Claims[2].Claim + require.Equal(t, expectedCounteredBy, forkPointClaim.CounteredBy) + require.Equal(t, expectedRootCounteredBy, tree.Claims[0].Claim.CounteredBy) + }) + + t.Run("SteppedClaimed_ChallengerWon", func(t *testing.T) { + builder := test.NewAlphabetClaimBuilder(t, big.NewInt(10), 4).GameBuilder() + builder.Seq(). // Defender winning + Attack(). // Challenger winning + Attack(). // Defender winning + Defend(). // Challenger winning + Defend(). // Defender winning + Step() // Challenger winning + claims := builder.Game.Claims() + // Successful step so mark as countered + claims[len(claims)-1].CounteredBy = common.Address{0xaa} + tree := transform.CreateBidirectionalTree(claims) + status := Resolve(tree) + require.Equal(t, gameTypes.GameStatusChallengerWon, status) + }) + + t.Run("SteppedClaimed_DefenderWon", func(t *testing.T) { + builder := test.NewAlphabetClaimBuilder(t, big.NewInt(10), 5).GameBuilder() + builder.Seq(). // Defender winning + Attack(). // Challenger winning + Attack(). // Defender winning + Defend(). // Challenger winning + Defend(). // Defender winning + Attack(). // Challenger winning + Step() // Defender winning + claims := builder.Game.Claims() + // Successful step so mark as countered + claims[len(claims)-1].CounteredBy = common.Address{0xaa} + tree := transform.CreateBidirectionalTree(claims) + status := Resolve(tree) + require.Equal(t, gameTypes.GameStatusDefenderWon, status) + }) +} diff --git a/op-dispute-mon/mon/service.go b/op-dispute-mon/mon/service.go new file mode 100644 index 000000000000..593917781e35 --- /dev/null +++ b/op-dispute-mon/mon/service.go @@ -0,0 +1,248 @@ +package mon + +import ( + "context" + "errors" + "fmt" + "math/big" + "sync/atomic" + + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/bonds" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-dispute-mon/config" + "github.com/ethereum-optimism/optimism/op-dispute-mon/metrics" + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/extract" + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/resolution" + "github.com/ethereum-optimism/optimism/op-dispute-mon/version" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" + "github.com/ethereum-optimism/optimism/op-service/clock" + "github.com/ethereum-optimism/optimism/op-service/dial" + "github.com/ethereum-optimism/optimism/op-service/httputil" + opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" + "github.com/ethereum-optimism/optimism/op-service/oppprof" + "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" +) + +type Service struct { + logger log.Logger + metrics metrics.Metricer + monitor *gameMonitor + + factoryContract *contracts.DisputeGameFactoryContract + + cl clock.Clock + + delays *resolution.DelayCalculator + extractor *extract.Extractor + forecast *forecast + bonds *bonds.Bonds + game *extract.GameCallerCreator + rollupClient *sources.RollupClient + validator *outputValidator + + l1Client *ethclient.Client + + pprofService *oppprof.Service + metricsSrv *httputil.HTTPServer + + stopped atomic.Bool +} + +// NewService creates a new Service. +func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Service, error) { + s := &Service{ + cl: clock.SystemClock, + logger: logger, + metrics: metrics.NewMetrics(), + } + + if err := s.initFromConfig(ctx, cfg); err != nil { + return nil, errors.Join(fmt.Errorf("failed to init service: %w", err), s.Stop(ctx)) + } + + return s, nil +} + +func (s *Service) initFromConfig(ctx context.Context, cfg *config.Config) error { + if err := s.initL1Client(ctx, cfg); err != nil { + return fmt.Errorf("failed to init l1 client: %w", err) + } + if err := s.initPProf(&cfg.PprofConfig); err != nil { + return fmt.Errorf("failed to init profiling: %w", err) + } + if err := s.initMetricsServer(&cfg.MetricsConfig); err != nil { + return fmt.Errorf("failed to init metrics server: %w", err) + } + if err := s.initFactoryContract(cfg); err != nil { + return fmt.Errorf("failed to create factory contract bindings: %w", err) + } + if err := s.initOutputRollupClient(ctx, cfg); err != nil { + return fmt.Errorf("failed to init rollup client: %w", err) + } + + s.initOutputValidator() // Must be called before initForecast + s.initGameCallerCreator() // Must be called before initForecast + + s.initDelayCalculator() + s.initExtractor() + + s.initForecast(cfg) + s.initBonds() + + s.initMonitor(ctx, cfg) // Monitor must be initialized last + + s.metrics.RecordInfo(version.SimpleWithMeta) + s.metrics.RecordUp() + + return nil +} + +func (s *Service) initOutputValidator() { + s.validator = newOutputValidator(s.logger, s.metrics, s.rollupClient) +} + +func (s *Service) initGameCallerCreator() { + s.game = extract.NewGameCallerCreator(s.metrics, batching.NewMultiCaller(s.l1Client.Client(), batching.DefaultBatchSize)) +} + +func (s *Service) initDelayCalculator() { + s.delays = resolution.NewDelayCalculator(s.metrics, s.cl) +} + +func (s *Service) initExtractor() { + s.extractor = extract.NewExtractor(s.logger, s.game.CreateContract, s.factoryContract.GetGamesAtOrAfter, + extract.NewBondEnricher(), + extract.NewBalanceEnricher(), + extract.NewL1HeadBlockNumEnricher(s.l1Client), + ) +} + +func (s *Service) initForecast(cfg *config.Config) { + s.forecast = newForecast(s.logger, s.metrics, s.validator) +} + +func (s *Service) initBonds() { + s.bonds = bonds.NewBonds(s.logger, s.metrics) +} + +func (s *Service) initOutputRollupClient(ctx context.Context, cfg *config.Config) error { + outputRollupClient, err := dial.DialRollupClientWithTimeout(ctx, dial.DefaultDialTimeout, s.logger, cfg.RollupRpc) + if err != nil { + return fmt.Errorf("failed to dial rollup client: %w", err) + } + s.rollupClient = outputRollupClient + return nil +} + +func (s *Service) initL1Client(ctx context.Context, cfg *config.Config) error { + l1Client, err := dial.DialEthClientWithTimeout(ctx, dial.DefaultDialTimeout, s.logger, cfg.L1EthRpc) + if err != nil { + return fmt.Errorf("failed to dial L1: %w", err) + } + s.l1Client = l1Client + return nil +} + +func (s *Service) initPProf(cfg *oppprof.CLIConfig) error { + s.pprofService = oppprof.New( + cfg.ListenEnabled, + cfg.ListenAddr, + cfg.ListenPort, + cfg.ProfileType, + cfg.ProfileDir, + cfg.ProfileFilename, + ) + + if err := s.pprofService.Start(); err != nil { + return fmt.Errorf("failed to start pprof service: %w", err) + } + + return nil +} + +func (s *Service) initMetricsServer(cfg *opmetrics.CLIConfig) error { + if !cfg.Enabled { + return nil + } + s.logger.Debug("starting metrics server", "addr", cfg.ListenAddr, "port", cfg.ListenPort) + m, ok := s.metrics.(opmetrics.RegistryMetricer) + if !ok { + return fmt.Errorf("metrics were enabled, but metricer %T does not expose registry for metrics-server", s.metrics) + } + metricsSrv, err := opmetrics.StartServer(m.Registry(), cfg.ListenAddr, cfg.ListenPort) + if err != nil { + return fmt.Errorf("failed to start metrics server: %w", err) + } + s.logger.Info("started metrics server", "addr", metricsSrv.Addr()) + s.metricsSrv = metricsSrv + return nil +} + +func (s *Service) initFactoryContract(cfg *config.Config) error { + factoryContract, err := contracts.NewDisputeGameFactoryContract(cfg.GameFactoryAddress, + batching.NewMultiCaller(s.l1Client.Client(), batching.DefaultBatchSize)) + if err != nil { + return fmt.Errorf("failed to bind the fault dispute game factory contract: %w", err) + } + s.factoryContract = factoryContract + return nil +} + +func (s *Service) initMonitor(ctx context.Context, cfg *config.Config) { + blockHashFetcher := func(ctx context.Context, blockNumber *big.Int) (common.Hash, error) { + block, err := s.l1Client.BlockByNumber(ctx, blockNumber) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to fetch block by number: %w", err) + } + return block.Hash(), nil + } + s.monitor = newGameMonitor( + ctx, + s.logger, + s.cl, + cfg.MonitorInterval, + cfg.GameWindow, + s.delays.RecordClaimResolutionDelayMax, + s.forecast.Forecast, + s.bonds.CheckBonds, + s.extractor.Extract, + s.l1Client.BlockNumber, + blockHashFetcher, + ) +} + +func (s *Service) Start(ctx context.Context) error { + s.logger.Info("Starting scheduler") + s.logger.Info("Starting monitoring") + s.monitor.StartMonitoring() + s.logger.Info("Dispute monitor game service start completed") + return nil +} + +func (s *Service) Stopped() bool { + return s.stopped.Load() +} + +func (s *Service) Stop(ctx context.Context) error { + s.logger.Info("Stopping dispute mon service") + + var result error + if s.pprofService != nil { + if err := s.pprofService.Stop(ctx); err != nil { + result = errors.Join(result, fmt.Errorf("failed to close pprof server: %w", err)) + } + } + if s.metricsSrv != nil { + if err := s.metricsSrv.Stop(ctx); err != nil { + result = errors.Join(result, fmt.Errorf("failed to close metrics server: %w", err)) + } + } + s.stopped.Store(true) + s.logger.Info("stopped dispute mon service", "err", result) + return result +} diff --git a/op-dispute-mon/mon/transform/collateral.go b/op-dispute-mon/mon/transform/collateral.go new file mode 100644 index 000000000000..14263f2641f8 --- /dev/null +++ b/op-dispute-mon/mon/transform/collateral.go @@ -0,0 +1,50 @@ +package transform + +import ( + "math/big" + + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum/go-ethereum/common" +) + +type Collateral struct { + // Required is the amount of collateral required to pay out bonds. + Required *big.Int + + // Actual is the amount of collateral actually head by the DelayedWETH contract + Actual *big.Int +} + +// CalculateRequiredCollateral determines the minimum balance required for each DelayedWETH contract used by a set +// of dispute games. +// Returns a map of DelayedWETH contract address to collateral data (required and actual amounts) +func CalculateRequiredCollateral(games []*monTypes.EnrichedGameData) map[common.Address]Collateral { + result := make(map[common.Address]Collateral) + for _, game := range games { + collateral, ok := result[game.WETHContract] + if !ok { + collateral = Collateral{ + Required: big.NewInt(0), + Actual: game.ETHCollateral, + } + } + gameRequired := requiredCollateralForGame(game) + collateral.Required = new(big.Int).Add(collateral.Required, gameRequired) + result[game.WETHContract] = collateral + } + return result +} + +func requiredCollateralForGame(game *monTypes.EnrichedGameData) *big.Int { + required := big.NewInt(0) + for _, claim := range game.Claims { + if monTypes.ResolvedBondAmount.Cmp(claim.Bond) != 0 { + required = new(big.Int).Add(required, claim.Bond) + } + } + + for _, unclaimedCredit := range game.Credits { + required = new(big.Int).Add(required, unclaimedCredit) + } + return required +} diff --git a/op-dispute-mon/mon/transform/collateral_test.go b/op-dispute-mon/mon/transform/collateral_test.go new file mode 100644 index 000000000000..96dc64967765 --- /dev/null +++ b/op-dispute-mon/mon/transform/collateral_test.go @@ -0,0 +1,104 @@ +package transform + +import ( + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestCalculateRequiredCollateral(t *testing.T) { + weth1 := common.Address{0x1a} + weth1Balance := big.NewInt(4200) + weth2 := common.Address{0x2b} + weth2Balance := big.NewInt(6000) + game1 := &monTypes.EnrichedGameData{ + Claims: []types.Claim{ + { + ClaimData: types.ClaimData{ + Bond: monTypes.ResolvedBondAmount, + }, + Claimant: common.Address{0x01}, + CounteredBy: common.Address{0x02}, + }, + { + ClaimData: types.ClaimData{ + Bond: big.NewInt(5), + }, + Claimant: common.Address{0x03}, + CounteredBy: common.Address{}, + }, + { + ClaimData: types.ClaimData{ + Bond: big.NewInt(7), + }, + Claimant: common.Address{0x03}, + CounteredBy: common.Address{}, + }, + }, + Credits: map[common.Address]*big.Int{ + common.Address{0x01}: big.NewInt(2), + common.Address{0x04}: big.NewInt(3), + }, + WETHContract: weth1, + ETHCollateral: weth1Balance, + } + game2 := &monTypes.EnrichedGameData{ + Claims: []types.Claim{ + { + ClaimData: types.ClaimData{ + Bond: monTypes.ResolvedBondAmount, + }, + Claimant: common.Address{0x01}, + CounteredBy: common.Address{0x02}, + }, + { + ClaimData: types.ClaimData{ + Bond: big.NewInt(6), + }, + Claimant: common.Address{0x03}, + CounteredBy: common.Address{}, + }, + { + ClaimData: types.ClaimData{ + Bond: big.NewInt(9), + }, + Claimant: common.Address{0x03}, + CounteredBy: common.Address{}, + }, + }, + Credits: map[common.Address]*big.Int{ + common.Address{0x01}: big.NewInt(4), + common.Address{0x04}: big.NewInt(1), + }, + WETHContract: weth1, + ETHCollateral: weth1Balance, + } + game3 := &monTypes.EnrichedGameData{ + Claims: []types.Claim{ + { + ClaimData: types.ClaimData{ + Bond: big.NewInt(23), + }, + Claimant: common.Address{0x03}, + CounteredBy: common.Address{}, + }, + }, + Credits: map[common.Address]*big.Int{ + common.Address{0x01}: big.NewInt(46), + }, + WETHContract: weth2, + ETHCollateral: weth2Balance, + } + actual := CalculateRequiredCollateral([]*monTypes.EnrichedGameData{game1, game2, game3}) + require.Len(t, actual, 2) + require.Contains(t, actual, weth1) + require.Contains(t, actual, weth2) + require.Equal(t, actual[weth1].Required.Uint64(), uint64(5+7+2+3+6+9+4+1)) + require.Equal(t, actual[weth1].Actual.Uint64(), weth1Balance.Uint64()) + require.Equal(t, actual[weth2].Required.Uint64(), uint64(23+46)) + require.Equal(t, actual[weth2].Actual.Uint64(), weth2Balance.Uint64()) +} diff --git a/op-dispute-mon/mon/transform/tree.go b/op-dispute-mon/mon/transform/tree.go new file mode 100644 index 000000000000..e9bcff71c50a --- /dev/null +++ b/op-dispute-mon/mon/transform/tree.go @@ -0,0 +1,28 @@ +package transform + +import ( + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" +) + +// CreateBidirectionalTree walks backwards through the list of claims and creates a bidirectional +// tree of claims. The root claim must be at index 0. The tree is returned as a flat array so it +// can be easily traversed following the resolution process. +func CreateBidirectionalTree(claims []types.Claim) *monTypes.BidirectionalTree { + claimMap := make(map[int]*monTypes.BidirectionalClaim) + res := make([]*monTypes.BidirectionalClaim, 0, len(claims)) + for _, claim := range claims { + claim := claim + bidirectionalClaim := &monTypes.BidirectionalClaim{ + Claim: &claim, + } + claimMap[claim.ContractIndex] = bidirectionalClaim + if !claim.IsRoot() { + // SAFETY: the parent must exist in the list prior to the current claim. + parent := claimMap[claim.ParentContractIndex] + parent.Children = append(parent.Children, bidirectionalClaim) + } + res = append(res, bidirectionalClaim) + } + return &monTypes.BidirectionalTree{Claims: res} +} diff --git a/op-dispute-mon/mon/transform/tree_test.go b/op-dispute-mon/mon/transform/tree_test.go new file mode 100644 index 000000000000..dba36ec25608 --- /dev/null +++ b/op-dispute-mon/mon/transform/tree_test.go @@ -0,0 +1,80 @@ +package transform + +import ( + "math" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" +) + +func TestResolver_CreateBidirectionalTree(t *testing.T) { + t.Run("SingleClaim", func(t *testing.T) { + claims := createDeepClaimList()[:1] + claims[0].CounteredBy = common.Address{} + tree := CreateBidirectionalTree(claims) + require.Len(t, tree.Claims, 1) + require.Equal(t, claims[0], *tree.Claims[0].Claim) + require.Empty(t, tree.Claims[0].Children) + }) + + t.Run("MultipleClaims", func(t *testing.T) { + claims := createDeepClaimList()[:2] + claims[1].CounteredBy = common.Address{} + tree := CreateBidirectionalTree(claims) + require.Len(t, tree.Claims, 2) + require.Equal(t, claims[0], *tree.Claims[0].Claim) + require.Len(t, tree.Claims[0].Children, 1) + require.Equal(t, claims[1], *tree.Claims[0].Children[0].Claim) + require.Equal(t, claims[1], *tree.Claims[1].Claim) + require.Empty(t, tree.Claims[1].Children) + }) + + t.Run("MultipleClaimsAndChildren", func(t *testing.T) { + claims := createDeepClaimList() + tree := CreateBidirectionalTree(claims) + require.Len(t, tree.Claims, 3) + require.Equal(t, claims[0], *tree.Claims[0].Claim) + require.Len(t, tree.Claims[0].Children, 1) + require.Equal(t, tree.Claims[0].Children[0], tree.Claims[1]) + require.Equal(t, claims[1], *tree.Claims[1].Claim) + require.Len(t, tree.Claims[1].Children, 1) + require.Equal(t, tree.Claims[1].Children[0], tree.Claims[2]) + require.Equal(t, claims[2], *tree.Claims[2].Claim) + require.Empty(t, tree.Claims[2].Children) + }) +} + +func createDeepClaimList() []types.Claim { + return []types.Claim{ + { + ClaimData: types.ClaimData{ + Position: types.NewPosition(0, big.NewInt(0)), + }, + ContractIndex: 0, + CounteredBy: common.HexToAddress("0x222222"), + ParentContractIndex: math.MaxInt64, + Claimant: common.HexToAddress("0x111111"), + }, + { + ClaimData: types.ClaimData{ + Position: types.NewPosition(1, big.NewInt(0)), + }, + CounteredBy: common.HexToAddress("0x111111"), + ContractIndex: 1, + ParentContractIndex: 0, + Claimant: common.HexToAddress("0x222222"), + }, + { + ClaimData: types.ClaimData{ + Position: types.NewPosition(2, big.NewInt(0)), + }, + ContractIndex: 2, + ParentContractIndex: 1, + Claimant: common.HexToAddress("0x111111"), + }, + } +} diff --git a/op-dispute-mon/mon/types/types.go b/op-dispute-mon/mon/types/types.go new file mode 100644 index 000000000000..c7232cc8f18b --- /dev/null +++ b/op-dispute-mon/mon/types/types.go @@ -0,0 +1,57 @@ +package types + +import ( + "math/big" + + faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum-optimism/optimism/op-challenger/game/types" + "github.com/ethereum/go-ethereum/common" +) + +// ResolvedBondAmount is the uint128 value where a bond is considered claimed. +var ResolvedBondAmount = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 128), big.NewInt(1)) + +type EnrichedGameData struct { + types.GameMetadata + L1Head common.Hash + L1HeadNum uint64 + L2BlockNumber uint64 + RootClaim common.Hash + Status types.GameStatus + Duration uint64 + Claims []faultTypes.Claim + + // Credits records the paid out bonds for the game, keyed by recipient. + Credits map[common.Address]*big.Int + + // WETHContract is the address of the DelayedWETH contract used by this game + // The contract is potentially shared by multiple games. + WETHContract common.Address + + // ETHCollateral is the ETH balance of the (potentially shared) WETHContract + // This ETH balance will be used to pay out any bonds required by the games that use the same DelayedWETH contract. + ETHCollateral *big.Int +} + +// BidirectionalTree is a tree of claims represented as a flat list of claims. +// This keeps the tree structure identical to how claims are stored in the contract. +type BidirectionalTree struct { + Claims []*BidirectionalClaim +} + +type BidirectionalClaim struct { + Claim *faultTypes.Claim + Children []*BidirectionalClaim +} + +type ForecastBatch struct { + AgreeDefenderAhead int + DisagreeDefenderAhead int + AgreeChallengerAhead int + DisagreeChallengerAhead int + + AgreeDefenderWins int + DisagreeDefenderWins int + AgreeChallengerWins int + DisagreeChallengerWins int +} diff --git a/op-dispute-mon/mon/types/types_test.go b/op-dispute-mon/mon/types/types_test.go new file mode 100644 index 000000000000..1958be239954 --- /dev/null +++ b/op-dispute-mon/mon/types/types_test.go @@ -0,0 +1,11 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestMaxValue(t *testing.T) { + require.Equal(t, ResolvedBondAmount.String(), "340282366920938463463374607431768211455") +} diff --git a/op-dispute-mon/mon/validator.go b/op-dispute-mon/mon/validator.go new file mode 100644 index 000000000000..32e1e879db5d --- /dev/null +++ b/op-dispute-mon/mon/validator.go @@ -0,0 +1,67 @@ +package mon + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-service/eth" +) + +type OutputRollupClient interface { + OutputAtBlock(ctx context.Context, blockNum uint64) (*eth.OutputResponse, error) + SafeHeadAtL1Block(ctx context.Context, blockNum uint64) (*eth.SafeHeadResponse, error) +} + +type OutputMetrics interface { + RecordOutputFetchTime(float64) +} + +type outputValidator struct { + log log.Logger + metrics OutputMetrics + client OutputRollupClient +} + +func newOutputValidator(logger log.Logger, metrics OutputMetrics, client OutputRollupClient) *outputValidator { + return &outputValidator{ + log: logger, + metrics: metrics, + client: client, + } +} + +// CheckRootAgreement validates the specified root claim against the output at the given block number. +func (o *outputValidator) CheckRootAgreement(ctx context.Context, l1HeadNum uint64, l2BlockNum uint64, rootClaim common.Hash) (bool, common.Hash, error) { + output, err := o.client.OutputAtBlock(ctx, l2BlockNum) + if err != nil { + // string match as the error comes from the remote server so we can't use Errors.Is sadly. + if strings.Contains(err.Error(), "not found") { + // Output root doesn't exist, so we must disagree with it. + return false, common.Hash{}, nil + } + return false, common.Hash{}, fmt.Errorf("failed to get output at block: %w", err) + } + o.metrics.RecordOutputFetchTime(float64(time.Now().Unix())) + expected := common.Hash(output.OutputRoot) + rootMatches := rootClaim == expected + if !rootMatches { + return false, expected, nil + } + + // If the root matches, also check that l2 block is safe at the L1 head + safeHead, err := o.client.SafeHeadAtL1Block(ctx, l1HeadNum) + if err != nil { + o.log.Warn("Unable to verify proposed block was safe", "l1HeadNum", l1HeadNum, "l2BlockNum", l2BlockNum, "err", err) + // If safe head data isn't available, assume the output root was safe + // Avoids making the dispute mon dependent on safe head db being available + // + return true, expected, nil + } + isSafe := safeHead.SafeHead.Number >= l2BlockNum + return isSafe, expected, nil +} diff --git a/op-dispute-mon/mon/validator_test.go b/op-dispute-mon/mon/validator_test.go new file mode 100644 index 000000000000..5b395bee98f9 --- /dev/null +++ b/op-dispute-mon/mon/validator_test.go @@ -0,0 +1,139 @@ +package mon + +import ( + "context" + "errors" + "testing" + + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +var ( + mockRootClaim = common.HexToHash("0x10") +) + +func TestDetector_CheckRootAgreement(t *testing.T) { + t.Parallel() + + t.Run("OutputFetchFails", func(t *testing.T) { + validator, rollup, metrics := setupOutputValidatorTest(t) + rollup.outputErr = errors.New("boom") + agree, fetched, err := validator.CheckRootAgreement(context.Background(), 100, 0, mockRootClaim) + require.ErrorIs(t, err, rollup.outputErr) + require.Equal(t, common.Hash{}, fetched) + require.False(t, agree) + require.Zero(t, metrics.fetchTime) + }) + + t.Run("OutputMismatch_Safe", func(t *testing.T) { + validator, _, metrics := setupOutputValidatorTest(t) + agree, fetched, err := validator.CheckRootAgreement(context.Background(), 100, 0, common.Hash{}) + require.NoError(t, err) + require.Equal(t, mockRootClaim, fetched) + require.False(t, agree) + require.NotZero(t, metrics.fetchTime) + }) + + t.Run("OutputMatches_Safe", func(t *testing.T) { + validator, _, metrics := setupOutputValidatorTest(t) + agree, fetched, err := validator.CheckRootAgreement(context.Background(), 200, 0, mockRootClaim) + require.NoError(t, err) + require.Equal(t, mockRootClaim, fetched) + require.True(t, agree) + require.NotZero(t, metrics.fetchTime) + }) + + t.Run("OutputMismatch_NotSafe", func(t *testing.T) { + validator, client, metrics := setupOutputValidatorTest(t) + client.safeHeadNum = 99 + agree, fetched, err := validator.CheckRootAgreement(context.Background(), 100, 0, common.Hash{}) + require.NoError(t, err) + require.Equal(t, mockRootClaim, fetched) + require.False(t, agree) + require.NotZero(t, metrics.fetchTime) + }) + + t.Run("OutputMatches_SafeHeadError", func(t *testing.T) { + validator, client, metrics := setupOutputValidatorTest(t) + client.safeHeadErr = errors.New("boom") + agree, fetched, err := validator.CheckRootAgreement(context.Background(), 200, 0, mockRootClaim) + require.NoError(t, err) + require.Equal(t, mockRootClaim, fetched) + require.True(t, agree) // Assume safe if we can't retrieve the safe head so monitoring isn't dependent on safe head db + require.NotZero(t, metrics.fetchTime) + }) + + t.Run("OutputMismatch_SafeHeadError", func(t *testing.T) { + validator, client, metrics := setupOutputValidatorTest(t) + client.safeHeadErr = errors.New("boom") + agree, fetched, err := validator.CheckRootAgreement(context.Background(), 100, 0, common.Hash{}) + require.NoError(t, err) + require.Equal(t, mockRootClaim, fetched) + require.False(t, agree) // Not agreed because the root doesn't match + require.NotZero(t, metrics.fetchTime) + }) + + t.Run("OutputMatches_NotSafe", func(t *testing.T) { + validator, client, metrics := setupOutputValidatorTest(t) + client.safeHeadNum = 99 + agree, fetched, err := validator.CheckRootAgreement(context.Background(), 200, 100, mockRootClaim) + require.NoError(t, err) + require.Equal(t, mockRootClaim, fetched) + require.False(t, agree) + require.NotZero(t, metrics.fetchTime) + }) + + t.Run("OutputNotFound", func(t *testing.T) { + validator, rollup, metrics := setupOutputValidatorTest(t) + // This crazy error is what we actually get back from the API + rollup.outputErr = errors.New("failed to get L2 block ref with sync status: failed to determine L2BlockRef of height 42984924, could not get payload: not found") + agree, fetched, err := validator.CheckRootAgreement(context.Background(), 100, 42984924, mockRootClaim) + require.NoError(t, err) + require.Equal(t, common.Hash{}, fetched) + require.False(t, agree) + require.Zero(t, metrics.fetchTime) + }) +} + +func setupOutputValidatorTest(t *testing.T) (*outputValidator, *stubRollupClient, *stubOutputMetrics) { + logger := testlog.Logger(t, log.LvlInfo) + client := &stubRollupClient{safeHeadNum: 99999999999} + metrics := &stubOutputMetrics{} + validator := newOutputValidator(logger, metrics, client) + return validator, client, metrics +} + +type stubOutputMetrics struct { + fetchTime float64 +} + +func (s *stubOutputMetrics) RecordOutputFetchTime(fetchTime float64) { + s.fetchTime = fetchTime +} + +type stubRollupClient struct { + blockNum uint64 + outputErr error + safeHeadErr error + safeHeadNum uint64 +} + +func (s *stubRollupClient) OutputAtBlock(ctx context.Context, blockNum uint64) (*eth.OutputResponse, error) { + s.blockNum = blockNum + return ð.OutputResponse{OutputRoot: eth.Bytes32(mockRootClaim)}, s.outputErr +} + +func (s *stubRollupClient) SafeHeadAtL1Block(_ context.Context, _ uint64) (*eth.SafeHeadResponse, error) { + if s.safeHeadErr != nil { + return nil, s.safeHeadErr + } + return ð.SafeHeadResponse{ + SafeHead: eth.BlockID{ + Number: s.safeHeadNum, + }, + }, nil +} diff --git a/op-dispute-mon/monitor.go b/op-dispute-mon/monitor.go new file mode 100644 index 000000000000..42e82b3d7c77 --- /dev/null +++ b/op-dispute-mon/monitor.go @@ -0,0 +1,18 @@ +package monitor + +import ( + "context" + + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-dispute-mon/config" + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon" + "github.com/ethereum-optimism/optimism/op-service/cliapp" +) + +func Main(ctx context.Context, logger log.Logger, cfg *config.Config) (cliapp.Lifecycle, error) { + if err := cfg.Check(); err != nil { + return nil, err + } + return mon.NewService(ctx, logger, cfg) +} diff --git a/op-dispute-mon/monitor_test.go b/op-dispute-mon/monitor_test.go new file mode 100644 index 000000000000..6a8896d114e0 --- /dev/null +++ b/op-dispute-mon/monitor_test.go @@ -0,0 +1,18 @@ +package monitor + +import ( + "context" + "testing" + + "github.com/ethereum-optimism/optimism/op-dispute-mon/config" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func TestMainShouldReturnErrorWhenConfigInvalid(t *testing.T) { + cfg := &config.Config{} + app, err := Main(context.Background(), testlog.Logger(t, log.LvlInfo), cfg) + require.ErrorIs(t, err, cfg.Check()) + require.Nil(t, app) +} diff --git a/op-dispute-mon/version/version.go b/op-dispute-mon/version/version.go new file mode 100644 index 000000000000..834fc089b19e --- /dev/null +++ b/op-dispute-mon/version/version.go @@ -0,0 +1,14 @@ +package version + +var ( + Version = "v0.1.0" + Meta = "dev" +) + +var SimpleWithMeta = func() string { + v := Version + if Meta != "" { + v += "-" + Meta + } + return v +}() diff --git a/op-e2e/Makefile b/op-e2e/Makefile index 1f880be22503..5d1876dfb120 100644 --- a/op-e2e/Makefile +++ b/op-e2e/Makefile @@ -1,8 +1,8 @@ # Generally, JUNIT_FILE is set in CI but may be specified to an arbitrary file location to emulate CI locally ifdef JUNIT_FILE - go_test = OP_TESTLOG_DISABLE_COLOR=true OP_E2E_DISABLE_PARALLEL=false gotestsum --format=standard-verbose --junitfile=$(JUNIT_FILE) -- + go_test = OP_TESTLOG_DISABLE_COLOR=true OP_E2E_DISABLE_PARALLEL=false gotestsum --format=standard-verbose --junitfile=$(JUNIT_FILE) -- -failfast # Note: -parallel must be set to match the number of cores in the resource class - go_test_flags = -timeout=20m -parallel=8 + go_test_flags = -timeout=60m -parallel=8 else go_test = go test go_test_flags = -v @@ -16,13 +16,25 @@ test-external-%: pre-test $(go_test) $(go_test_flags) --externalL2 ./external_$*/ test-ws: pre-test - $(go_test) $(go_test_flags) ./... + $(go_test) $(go_test_flags) . ./e2eutils/... .PHONY: test-ws +test-actions: pre-test + $(go_test) $(go_test_flags) ./actions +.PHONY: test-actions + test-http: pre-test - OP_E2E_USE_HTTP=true $(go_test) $(go_test_flags) ./... + OP_E2E_USE_HTTP=true $(go_test) $(go_test_flags) . ./e2eutils/... .PHONY: test-http +test-cannon: pre-test + OP_E2E_CANNON_ENABLED=true $(go_test) $(go_test_flags) ./faultproofs +.PHONY: test-cannon + +test-fault-proofs: pre-test + $(go_test) $(go_test_flags) ./faultproofs +.PHONY: test-faultproofs + cannon-prestate: make -C .. cannon-prestate .PHONY: cannon-prestate diff --git a/op-e2e/README.md b/op-e2e/README.md index c64024f1be5d..28fdb06dad1b 100644 --- a/op-e2e/README.md +++ b/op-e2e/README.md @@ -19,3 +19,16 @@ runtime, but others cannot be changed or else it will result in broken tests. Any changes to `devnetL1.json` should result in rebuilding the `.devnet` artifacts before the new values will be present in the `op-e2e` tests. + +## Running tests +Consult the [Makefile](./Makefile) in this directory. Run, e.g.: + +```bash +make test-http +``` + +### Troubleshooting +If you encounter errors: +* ensure you have the latest version of foundry installed: `pnpm update:foundry` +* try deleting the `packages/contracts-bedrock/forge-artifacts` directory +* if the above step doesn't fix the error, try `pnpm clean` diff --git a/op-e2e/actions/action.go b/op-e2e/actions/action.go index 53b710a44e21..551ab58d9632 100644 --- a/op-e2e/actions/action.go +++ b/op-e2e/actions/action.go @@ -2,26 +2,12 @@ package actions import ( "context" - "os" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ) -var enableParallelTesting bool = true - -func init() { - if os.Getenv("OP_E2E_DISABLE_PARALLEL") == "true" { - enableParallelTesting = false - } -} - -func parallel(t e2eutils.TestingBase) { - t.Helper() - if enableParallelTesting { - t.Parallel() - } -} - // Testing is an interface to Go-like testing, // extended with a context getter for the test runner to shut down individual actions without interrupting the test, // and a signaling function for when an invalid action is hit. @@ -69,7 +55,8 @@ type StatefulTesting interface { // NewDefaultTesting returns a new testing obj, and enables parallel test execution. // Returns an interface, we're likely changing the behavior here as we build more action tests. func NewDefaultTesting(tb e2eutils.TestingBase) StatefulTesting { - parallel(tb) + op_e2e.InitParallel(tb) + return &defaultTesting{ TestingBase: tb, ctx: context.Background(), diff --git a/op-e2e/actions/blocktime_test.go b/op-e2e/actions/blocktime_test.go index cb2e4b05a6b1..90a38be9a337 100644 --- a/op-e2e/actions/blocktime_test.go +++ b/op-e2e/actions/blocktime_test.go @@ -51,7 +51,7 @@ func BatchInLastPossibleBlocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp.DeployConfig.L2BlockTime = 2 sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) sd, _, miner, sequencer, sequencerEngine, _, _, batcher := setupReorgTestActors(t, dp, sd, log) @@ -163,7 +163,7 @@ func LargeL1Gaps(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp.DeployConfig.MaxSequencerDrift = 32 applyDeltaTimeOffset(dp, deltaTimeOffset) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) sd, _, miner, sequencer, sequencerEngine, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) diff --git a/op-e2e/actions/dencun_fork_test.go b/op-e2e/actions/dencun_fork_test.go index 262f6499b3e4..5e0f1706cb31 100644 --- a/op-e2e/actions/dencun_fork_test.go +++ b/op-e2e/actions/dencun_fork_test.go @@ -22,7 +22,7 @@ func TestDencunL1ForkAfterGenesis(gt *testing.T) { offset := hexutil.Uint64(24) dp.DeployConfig.L1CancunTimeOffset = &offset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) l1Head := miner.l1Chain.CurrentBlock() @@ -65,7 +65,7 @@ func TestDencunL1ForkAtGenesis(gt *testing.T) { offset := hexutil.Uint64(0) dp.DeployConfig.L1CancunTimeOffset = &offset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) l1Head := miner.l1Chain.CurrentBlock() @@ -130,7 +130,7 @@ func TestDencunL2ForkAfterGenesis(gt *testing.T) { dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) _, _, _, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) // start op-nodes @@ -167,7 +167,7 @@ func TestDencunL2ForkAtGenesis(gt *testing.T) { dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) _, _, _, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) // start op-nodes @@ -209,7 +209,7 @@ func TestDencunBlobTxRPC(gt *testing.T) { dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) engine := newEngine(t, sd, log) cl := engine.EthClient() tx := aliceSimpleBlobTx(t, dp) @@ -228,7 +228,7 @@ func TestDencunBlobTxInTxPool(gt *testing.T) { dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) engine := newEngine(t, sd, log) tx := aliceSimpleBlobTx(t, dp) errs := engine.eth.TxPool().Add([]*types.Transaction{tx}, true, true) @@ -246,7 +246,7 @@ func TestDencunBlobTxInclusion(gt *testing.T) { dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) _, engine, sequencer := setupSequencerTest(t, sd, log) sequencer.ActL2PipelineFull(t) diff --git a/op-e2e/actions/ecotone_fork_test.go b/op-e2e/actions/ecotone_fork_test.go index 1bdc27a689e7..4cadbdafce08 100644 --- a/op-e2e/actions/ecotone_fork_test.go +++ b/op-e2e/actions/ecotone_fork_test.go @@ -5,7 +5,6 @@ import ( "math/big" "testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/common" @@ -24,15 +23,20 @@ import ( ) var ( - l1BlockCodeHash = common.FromHex("0xc88a313aa75dc4fbf0b6850d9f9ae41e04243b7008cf3eadb29256d4a71c1dfd") - gasPriceOracleCodeHash = common.FromHex("0x8b71360ea773b4cfaf1ae6d2bd15464a4e1e2e360f786e475f63aeaed8da0ae5") + l1BlockCodeHash = common.HexToHash("0xc88a313aa75dc4fbf0b6850d9f9ae41e04243b7008cf3eadb29256d4a71c1dfd") + gasPriceOracleCodeHash = common.HexToHash("0x8b71360ea773b4cfaf1ae6d2bd15464a4e1e2e360f786e475f63aeaed8da0ae5") ) -func verifyCodeHashMatches(t *testing.T, client *ethclient.Client, address common.Address, expectedCodeHash []byte) { +// verifyCodeHashMatches checks that the has of the code at the given address matches the expected code-hash. +// It also sanity-checks that the code is not empty: we should never deploy empty contract codes. +// Returns the contract code +func verifyCodeHashMatches(t Testing, client *ethclient.Client, address common.Address, expectedCodeHash common.Hash) []byte { code, err := client.CodeAt(context.Background(), address, nil) require.NoError(t, err) + require.NotEmpty(t, code) codeHash := crypto.Keccak256Hash(code) - require.Equal(t, expectedCodeHash, codeHash.Bytes()) + require.Equal(t, expectedCodeHash, codeHash) + return code } func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { @@ -51,15 +55,16 @@ func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { require.NoError(t, dp.DeployConfig.Check(), "must have valid config") sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) _, _, miner, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) + ethCl := engine.EthClient() // start op-nodes sequencer.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t) // Get gas price from oracle - gasPriceOracle, err := bindings.NewGasPriceOracleCaller(predeploys.GasPriceOracleAddr, engine.EthClient()) + gasPriceOracle, err := bindings.NewGasPriceOracleCaller(predeploys.GasPriceOracleAddr, ethCl) require.NoError(t, err) scalar, err := gasPriceOracle.Scalar(nil) @@ -68,16 +73,16 @@ func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { require.True(t, scalar.Cmp(new(big.Int).SetUint64(dp.DeployConfig.GasPriceOracleScalar)) == 0, "must match deploy config") // Get current implementations addresses (by slot) for L1Block + GasPriceOracle - initialGasPriceOracleAddress, err := engine.EthClient().StorageAt(context.Background(), predeploys.GasPriceOracleAddr, genesis.ImplementationSlot, nil) + initialGasPriceOracleAddress, err := ethCl.StorageAt(context.Background(), predeploys.GasPriceOracleAddr, genesis.ImplementationSlot, nil) require.NoError(t, err) - initialL1BlockAddress, err := engine.EthClient().StorageAt(context.Background(), predeploys.L1BlockAddr, genesis.ImplementationSlot, nil) + initialL1BlockAddress, err := ethCl.StorageAt(context.Background(), predeploys.L1BlockAddr, genesis.ImplementationSlot, nil) require.NoError(t, err) // Build to the ecotone block sequencer.ActBuildL2ToEcotone(t) // get latest block - latestBlock, err := engine.EthClient().BlockByNumber(context.Background(), nil) + latestBlock, err := ethCl.BlockByNumber(context.Background(), nil) require.NoError(t, err) require.Equal(t, sequencer.L2Unsafe().Number, latestBlock.Number().Uint64()) @@ -94,35 +99,37 @@ func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { // All transactions are successful for i := 1; i < 7; i++ { txn := transactions[i] - receipt, err := engine.EthClient().TransactionReceipt(context.Background(), txn.Hash()) + receipt, err := ethCl.TransactionReceipt(context.Background(), txn.Hash()) require.NoError(t, err) require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) + require.NotEmpty(t, txn.Data(), "upgrade tx must provide input data") } expectedL1BlockAddress := crypto.CreateAddress(derive.L1BlockDeployerAddress, 0) expectedGasPriceOracleAddress := crypto.CreateAddress(derive.GasPriceOracleDeployerAddress, 0) // Gas Price Oracle Proxy is updated - updatedGasPriceOracleAddress, err := engine.EthClient().StorageAt(context.Background(), predeploys.GasPriceOracleAddr, genesis.ImplementationSlot, latestBlock.Number()) + updatedGasPriceOracleAddress, err := ethCl.StorageAt(context.Background(), predeploys.GasPriceOracleAddr, genesis.ImplementationSlot, latestBlock.Number()) require.NoError(t, err) - assert.Equal(t, expectedGasPriceOracleAddress, common.BytesToAddress(updatedGasPriceOracleAddress)) - assert.NotEqualf(t, initialGasPriceOracleAddress, updatedGasPriceOracleAddress, "Gas Price Oracle Proxy address should have changed") - verifyCodeHashMatches(gt, engine.EthClient(), expectedGasPriceOracleAddress, gasPriceOracleCodeHash) + require.Equal(t, expectedGasPriceOracleAddress, common.BytesToAddress(updatedGasPriceOracleAddress)) + require.NotEqualf(t, initialGasPriceOracleAddress, updatedGasPriceOracleAddress, "Gas Price Oracle Proxy address should have changed") + verifyCodeHashMatches(t, ethCl, expectedGasPriceOracleAddress, gasPriceOracleCodeHash) // L1Block Proxy is updated - updatedL1BlockAddress, err := engine.EthClient().StorageAt(context.Background(), predeploys.L1BlockAddr, genesis.ImplementationSlot, latestBlock.Number()) + updatedL1BlockAddress, err := ethCl.StorageAt(context.Background(), predeploys.L1BlockAddr, genesis.ImplementationSlot, latestBlock.Number()) require.NoError(t, err) - assert.Equal(t, expectedL1BlockAddress, common.BytesToAddress(updatedL1BlockAddress)) - assert.NotEqualf(t, initialL1BlockAddress, updatedL1BlockAddress, "L1Block Proxy address should have changed") - verifyCodeHashMatches(gt, engine.EthClient(), expectedL1BlockAddress, l1BlockCodeHash) + require.Equal(t, expectedL1BlockAddress, common.BytesToAddress(updatedL1BlockAddress)) + require.NotEqualf(t, initialL1BlockAddress, updatedL1BlockAddress, "L1Block Proxy address should have changed") + verifyCodeHashMatches(t, ethCl, expectedL1BlockAddress, l1BlockCodeHash) _, err = gasPriceOracle.Scalar(nil) require.ErrorContains(t, err, "scalar() is deprecated") cost, err := gasPriceOracle.GetL1Fee(nil, []byte{0, 1, 2, 3, 4}) require.NoError(t, err) - // Pre-ecotone the GPO getL1Fee contract erroneously returned the pre-regolith L1 fee. - // Thus we do not assert the exact value here. + // The L1 info tx does not get included until after the Ecotone upgrade. + // The scalars are thus empty during activation, and only deposits are included, so the L1 fee is unused. + require.True(t, cost.IsUint64()) require.Equal(t, cost.Uint64(), uint64(0), "expecting zero scalars within activation block") // Check that Ecotone was activated @@ -132,15 +139,47 @@ func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { // 4788 contract is deployed expected4788Address := crypto.CreateAddress(derive.EIP4788From, 0) - code, err := engine.EthClient().CodeAt(context.Background(), expected4788Address, latestBlock.Number()) - require.NoError(t, err) - require.Equal(t, code, predeploys.EIP4788ContractCode) + require.Equal(t, predeploys.EIP4788ContractAddr, expected4788Address) + code := verifyCodeHashMatches(t, ethCl, predeploys.EIP4788ContractAddr, predeploys.EIP4788ContractCodeHash) + require.Equal(t, predeploys.EIP4788ContractCode, code) + // Test that the beacon-block-root has been set + checkBeaconBlockRoot := func(timestamp uint64, expectedHash common.Hash, expectedTime uint64, msg string) { + historyBufferLength := uint64(8191) + rootIdx := common.BigToHash(new(big.Int).SetUint64((timestamp % historyBufferLength) + historyBufferLength)) + timeIdx := common.BigToHash(new(big.Int).SetUint64(timestamp % historyBufferLength)) + + rootValue, err := ethCl.StorageAt(context.Background(), predeploys.EIP4788ContractAddr, rootIdx, nil) + require.NoError(t, err) + require.Equal(t, expectedHash, common.BytesToHash(rootValue), msg) + + timeValue, err := ethCl.StorageAt(context.Background(), predeploys.EIP4788ContractAddr, timeIdx, nil) + require.NoError(t, err) + timeBig := new(big.Int).SetBytes(timeValue) + require.True(t, timeBig.IsUint64()) + require.Equal(t, expectedTime, timeBig.Uint64(), msg) + } + // The header will always have the beacon-block-root, at the very start. + require.NotNil(t, latestBlock.BeaconRoot()) + require.Equal(t, *latestBlock.BeaconRoot(), common.Hash{}, + "L1 genesis block has zeroed parent-beacon-block-root, since it has no parent block, and that propagates into L2") + // The first block is an exception in upgrade-networks, + // since the beacon-block root contract isn't there at Ecotone activation, + // and the beacon-block-root insertion is processed at the start of the block before deposit txs. + // If the contract was permissionlessly deployed before, the contract storage will be updated however. + checkBeaconBlockRoot(latestBlock.Time(), common.Hash{}, 0, "ecotone activation block has no data yet (since contract wasn't there)") // Build empty L2 block, to pass ecotone activation sequencer.ActL2StartBlock(t) sequencer.ActL2EndBlock(t) - // assert again, now that we are past activation + // Test the L2 block after activation: it should have data in the contract storage now + latestBlock, err = ethCl.BlockByNumber(context.Background(), nil) + require.NoError(t, err) + require.NotNil(t, latestBlock.BeaconRoot()) + firstBeaconBlockRoot := *latestBlock.BeaconRoot() + checkBeaconBlockRoot(latestBlock.Time(), *latestBlock.BeaconRoot(), latestBlock.Time(), "post-activation") + + // require.again, now that we are past activation _, err = gasPriceOracle.Scalar(nil) require.ErrorContains(t, err, "scalar() is deprecated") @@ -151,14 +190,16 @@ func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { cost, err = gasPriceOracle.GetL1Fee(nil, []byte{0, 1, 2, 3, 4}) require.NoError(t, err) + // The GPO getL1Fee contract returns the L1 fee with approximate signature overhead pre-included, + // like the pre-regolith L1 fee. We do the full fee check below. Just sanity check it is not zero anymore first. require.Greater(t, cost.Uint64(), uint64(0), "expecting non-zero scalars after activation block") // Get L1Block info - l1Block, err := bindings.NewL1BlockCaller(predeploys.L1BlockAddr, engine.EthClient()) + l1Block, err := bindings.NewL1BlockCaller(predeploys.L1BlockAddr, ethCl) require.NoError(t, err) l1BlockInfo, err := l1Block.Timestamp(nil) require.NoError(t, err) - assert.Greater(t, l1BlockInfo, uint64(0)) + require.Greater(t, l1BlockInfo, uint64(0)) l1OriginBlock, err := miner.EthClient().BlockByHash(context.Background(), sequencer.L2Unsafe().L1Origin.Hash) require.NoError(t, err) @@ -174,6 +215,18 @@ func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { expectedL1Fee = expectedL1Fee.Mul(expectedL1Fee, new(big.Int).SetUint64(uint64(basefeeScalar))) expectedL1Fee = expectedL1Fee.Div(expectedL1Fee, big.NewInt(16e6)) require.Equal(t, expectedL1Fee, cost, "expecting cost based on regular base fee scalar alone") + + // build forward, incorporate new L1 data + miner.ActEmptyBlock(t) + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) + + // Contract storage should be updated now, different than before + latestBlock, err = ethCl.BlockByNumber(context.Background(), nil) + require.NoError(t, err) + require.NotNil(t, latestBlock.BeaconRoot()) + require.NotEqual(t, firstBeaconBlockRoot, *latestBlock.BeaconRoot()) + checkBeaconBlockRoot(latestBlock.Time(), *latestBlock.BeaconRoot(), latestBlock.Time(), "updates on new L1 data") } // TestEcotoneBeforeL1 tests that the L2 Ecotone fork can activate before L1 Dencun does @@ -189,7 +242,7 @@ func TestEcotoneBeforeL1(gt *testing.T) { dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) _, _, _, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) // start op-nodes diff --git a/op-e2e/actions/eip4844_test.go b/op-e2e/actions/eip4844_test.go new file mode 100644 index 000000000000..ddab21d48b47 --- /dev/null +++ b/op-e2e/actions/eip4844_test.go @@ -0,0 +1,185 @@ +package actions + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "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/log" + + batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/testlog" +) + +func setupEIP4844Test(t Testing, log log.Logger) (*e2eutils.SetupData, *e2eutils.DeployParams, *L1Miner, *L2Sequencer, *L2Engine, *L2Verifier, *L2Engine) { + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + genesisActivation := hexutil.Uint64(0) + dp.DeployConfig.L1CancunTimeOffset = &genesisActivation + dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisActivation + dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisActivation + dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisActivation + + sd := e2eutils.Setup(t, dp, defaultAlloc) + miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) + miner.ActL1SetFeeRecipient(common.Address{'A'}) + sequencer.ActL2PipelineFull(t) + verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + return sd, dp, miner, sequencer, seqEngine, verifier, verifEngine +} + +func setupBatcher(t Testing, log log.Logger, sd *e2eutils.SetupData, dp *e2eutils.DeployParams, miner *L1Miner, + sequencer *L2Sequencer, engine *L2Engine, daType batcherFlags.DataAvailabilityType, +) *L2Batcher { + return NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, + DataAvailabilityType: daType, + }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) +} + +func TestEIP4844DataAvailability(gt *testing.T) { + t := NewDefaultTesting(gt) + + log := testlog.Logger(t, log.LevelDebug) + sd, dp, miner, sequencer, seqEngine, verifier, _ := setupEIP4844Test(t, log) + + batcher := setupBatcher(t, log, sd, dp, miner, sequencer, seqEngine, batcherFlags.BlobsType) + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + // build empty L1 block + miner.ActEmptyBlock(t) + // finalize it, so the L1 geth blob pool doesn't log errors about missing finality + miner.ActL1SafeNext(t) + miner.ActL1FinalizeNext(t) + + // Create L2 blocks, and reference the L1 head as origin + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) + + // submit all new L2 blocks + batcher.ActSubmitAll(t) + batchTx := batcher.LastSubmitted + require.Equal(t, uint8(types.BlobTxType), batchTx.Type(), "batch tx must be blob-tx") + + // new L1 block with L2 batch + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTxByHash(batchTx.Hash())(t) + miner.ActL1EndBlock(t) + + // verifier picks up the L2 chain that was submitted + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + require.Equal(t, verifier.L2Safe(), sequencer.L2Unsafe(), "verifier syncs from sequencer via L1") + require.NotEqual(t, sequencer.L2Safe(), sequencer.L2Unsafe(), "sequencer has not processed L1 yet") +} + +func TestEIP4844MultiBlobs(gt *testing.T) { + t := NewDefaultTesting(gt) + + log := testlog.Logger(t, log.LevelDebug) + sd, dp, miner, sequencer, seqEngine, verifier, _ := setupEIP4844Test(t, log) + + batcher := setupBatcher(t, log, sd, dp, miner, sequencer, seqEngine, batcherFlags.BlobsType) + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + // build empty L1 block + miner.ActEmptyBlock(t) + // finalize it, so the L1 geth blob pool doesn't log errors about missing finality + miner.ActL1SafeNext(t) + miner.ActL1FinalizeNext(t) + + // Create L2 blocks, and reference the L1 head as origin + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) + + // submit all new L2 blocks + batcher.ActSubmitAllMultiBlobs(t, 6) + batchTx := batcher.LastSubmitted + require.Equal(t, uint8(types.BlobTxType), batchTx.Type(), "batch tx must be blob-tx") + require.Len(t, batchTx.BlobTxSidecar().Blobs, 6) + + // new L1 block with L2 batch + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTxByHash(batchTx.Hash())(t) + miner.ActL1EndBlock(t) + + // verifier picks up the L2 chain that was submitted + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + require.Equal(t, verifier.L2Safe(), sequencer.L2Unsafe(), "verifier syncs from sequencer via L1") + require.NotEqual(t, sequencer.L2Safe(), sequencer.L2Unsafe(), "sequencer has not processed L1 yet") +} + +func TestEIP4844DataAvailabilitySwitch(gt *testing.T) { + t := NewDefaultTesting(gt) + + log := testlog.Logger(t, log.LevelDebug) + sd, dp, miner, sequencer, seqEngine, verifier, _ := setupEIP4844Test(t, log) + + oldBatcher := setupBatcher(t, log, sd, dp, miner, sequencer, seqEngine, batcherFlags.CalldataType) + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + // build empty L1 block + miner.ActEmptyBlock(t) + // finalize it, so the L1 geth blob pool doesn't log errors about missing finality + miner.ActL1SafeNext(t) + miner.ActL1FinalizeNext(t) + + // Create L2 blocks, and reference the L1 head as origin + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) + + // submit all new L2 blocks, with legacy calldata DA + oldBatcher.ActSubmitAll(t) + batchTx := oldBatcher.LastSubmitted + require.Equal(t, uint8(types.DynamicFeeTxType), batchTx.Type(), "batch tx must be eip1559 tx") + + // new L1 block with L2 batch + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTxByHash(batchTx.Hash())(t) + miner.ActL1EndBlock(t) + + // verifier picks up the L2 chain that was submitted + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + require.Equal(t, verifier.L2Safe(), sequencer.L2Unsafe(), "verifier syncs from sequencer via L1") + require.NotEqual(t, sequencer.L2Safe(), sequencer.L2Unsafe(), "sequencer has not processed L1 yet") + + newBatcher := setupBatcher(t, log, sd, dp, miner, sequencer, seqEngine, batcherFlags.BlobsType) + + // build empty L1 block + miner.ActEmptyBlock(t) + + // Create L2 blocks, and reference the L1 head as origin + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) + + // submit all new L2 blocks, now with Blobs DA! + newBatcher.ActSubmitAll(t) + batchTx = newBatcher.LastSubmitted + + // new L1 block with L2 batch + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTxByHash(batchTx.Hash())(t) + miner.ActL1EndBlock(t) + + require.Equal(t, uint8(types.BlobTxType), batchTx.Type(), "batch tx must be blob-tx") + + // verifier picks up the L2 chain that was submitted + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + require.Equal(t, verifier.L2Safe(), sequencer.L2Unsafe(), "verifier syncs from sequencer via L1") + require.NotEqual(t, sequencer.L2Safe(), sequencer.L2Unsafe(), "sequencer has not processed L1 yet") +} diff --git a/op-e2e/actions/garbage_channel_out.go b/op-e2e/actions/garbage_channel_out.go index b2888d28b470..41a290570ea9 100644 --- a/op-e2e/actions/garbage_channel_out.go +++ b/op-e2e/actions/garbage_channel_out.go @@ -207,10 +207,10 @@ func (co *GarbageChannelOut) OutputFrame(w *bytes.Buffer, maxSize uint64) (uint1 // Fixed overhead: 32 + 8 + 2 + 4 + 1 = 47 bytes. // Add one extra byte for the version byte (for the entire L1 tx though) maxDataSize := maxSize - 47 - 1 - if maxDataSize > uint64(co.buf.Len()) { + if maxDataSize >= uint64(co.buf.Len()) { maxDataSize = uint64(co.buf.Len()) // If we are closed & will not spill past the current frame - // mark it is the final frame of the channel. + // mark it as the final frame of the channel. if co.closed { f.IsLast = true } diff --git a/op-e2e/actions/l1_miner.go b/op-e2e/actions/l1_miner.go index 56f508d095d2..adbaee77da90 100644 --- a/op-e2e/actions/l1_miner.go +++ b/op-e2e/actions/l1_miner.go @@ -3,20 +3,29 @@ package actions import ( "math/big" + "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/misc/eip1559" + "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "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/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/trie" - "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-service/eth" ) // L1Miner wraps a L1Replica with instrumented block building ability. type L1Miner struct { L1Replica + blobStore *e2eutils.BlobsStore + // L1 block building preferences prefCoinbase common.Address @@ -29,6 +38,8 @@ type L1Miner struct { l1Receipts []*types.Receipt // collect receipts of ongoing building l1Building bool l1TxFailed []*types.Transaction // log of failed transactions which could not be included + // sidecars that come with the transactions + l1BuildingBlobSidecars []*types.BlobTxSidecar } // NewL1Miner creates a new L1Replica that can also build blocks. @@ -36,9 +47,14 @@ func NewL1Miner(t Testing, log log.Logger, genesis *core.Genesis) *L1Miner { rep := NewL1Replica(t, log, genesis) return &L1Miner{ L1Replica: *rep, + blobStore: e2eutils.NewBlobStore(), } } +func (s *L1Miner) BlobStore() derive.L1BlobsFetcher { + return s.blobStore +} + // 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 { @@ -77,10 +93,9 @@ func (s *L1Miner) ActL1StartBlock(timeDelta uint64) Action { header.WithdrawalsHash = &types.EmptyWithdrawalsHash } if s.l1Cfg.Config.IsCancun(header.Number, header.Time) { - var root common.Hash - var zero uint64 - header.BlobGasUsed = &zero - header.ExcessBlobGas = &zero + header.BlobGasUsed = new(uint64) + header.ExcessBlobGas = new(uint64) + root := crypto.Keccak256Hash([]byte("fake-beacon-block-root"), header.Number.Bytes()) header.ParentBeaconRoot = &root } @@ -90,6 +105,7 @@ func (s *L1Miner) ActL1StartBlock(timeDelta uint64) Action { s.l1Receipts = make([]*types.Receipt, 0) s.l1Transactions = make([]*types.Transaction, 0) s.pendingIndices = make(map[common.Address]uint64) + s.l1BuildingBlobSidecars = make([]*types.BlobTxSidecar, 0) s.l1GasPool = new(core.GasPool).AddGas(header.GasLimit) } @@ -111,6 +127,22 @@ func (s *L1Miner) ActL1IncludeTx(from common.Address) Action { } } +// ActL1IncludeTxByHash tries to include a tx by tx-hash. +func (s *L1Miner) ActL1IncludeTxByHash(txHash common.Hash) Action { + return func(t Testing) { + if !s.l1Building { + t.InvalidAction("no tx inclusion when not building l1 block") + return + } + tx := s.eth.TxPool().Get(txHash) + require.NotNil(t, tx, "cannot find tx %s", txHash) + s.IncludeTx(t, tx) + from, err := s.l1Signer.Sender(tx) + require.NoError(t, err) + s.pendingIndices[from] = s.pendingIndices[from] + 1 // won't retry the tx + } +} + func (s *L1Miner) IncludeTx(t Testing, tx *types.Transaction) { from, err := s.l1Signer.Sender(tx) require.NoError(t, err) @@ -124,13 +156,21 @@ func (s *L1Miner) IncludeTx(t Testing, tx *types.Transaction) { } s.l1BuildingState.SetTxContext(tx.Hash(), len(s.l1Transactions)) 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()) + s.l1GasPool, s.l1BuildingState, s.l1BuildingHeader, tx.WithoutBlobTxSidecar(), &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): %v", len(s.l1Transactions), err) } s.l1Receipts = append(s.l1Receipts, receipt) - s.l1Transactions = append(s.l1Transactions, tx) + s.l1Transactions = append(s.l1Transactions, tx.WithoutBlobTxSidecar()) + if tx.Type() == types.BlobTxType { + require.True(t, s.l1Cfg.Config.IsCancun(s.l1BuildingHeader.Number, s.l1BuildingHeader.Time), "L1 must be cancun to process blob tx") + sidecar := tx.BlobTxSidecar() + if sidecar != nil { + s.l1BuildingBlobSidecars = append(s.l1BuildingBlobSidecars, sidecar) + } + *s.l1BuildingHeader.BlobGasUsed += receipt.BlobGasUsed + } } func (s *L1Miner) ActL1SetFeeRecipient(coinbase common.Address) { @@ -154,6 +194,19 @@ func (s *L1Miner) ActL1EndBlock(t Testing) { if s.l1Cfg.Config.IsShanghai(s.l1BuildingHeader.Number, s.l1BuildingHeader.Time) { block = block.WithWithdrawals(make([]*types.Withdrawal, 0)) } + if s.l1Cfg.Config.IsCancun(s.l1BuildingHeader.Number, s.l1BuildingHeader.Time) { + parent := s.l1Chain.GetHeaderByHash(s.l1BuildingHeader.ParentHash) + var ( + parentExcessBlobGas uint64 + parentBlobGasUsed uint64 + ) + if parent.ExcessBlobGas != nil { + parentExcessBlobGas = *parent.ExcessBlobGas + parentBlobGasUsed = *parent.BlobGasUsed + } + excessBlobGas := eip4844.CalcExcessBlobGas(parentExcessBlobGas, parentBlobGasUsed) + s.l1BuildingHeader.ExcessBlobGas = &excessBlobGas + } // Write state changes to db root, err := s.l1BuildingState.Commit(s.l1BuildingHeader.Number.Uint64(), s.l1Cfg.Config.IsEIP158(s.l1BuildingHeader.Number)) @@ -163,7 +216,13 @@ func (s *L1Miner) ActL1EndBlock(t Testing) { if err := s.l1BuildingState.Database().TrieDB().Commit(root, false); err != nil { t.Fatalf("l1 trie write error: %v", err) } - + // now that the blob txs are in a canonical block, flush them to the blob store + for _, sidecar := range s.l1BuildingBlobSidecars { + for i, h := range sidecar.BlobHashes() { + blob := (*eth.Blob)(&sidecar.Blobs[i]) + s.blobStore.StoreBlob(block.Hash(), h, blob) + } + } _, err = s.l1Chain.InsertChain(types.Blocks{block}) if err != nil { t.Fatalf("failed to insert block into l1 chain") diff --git a/op-e2e/actions/l1_miner_test.go b/op-e2e/actions/l1_miner_test.go index b149cfd778c3..10e4c0c5498c 100644 --- a/op-e2e/actions/l1_miner_test.go +++ b/op-e2e/actions/l1_miner_test.go @@ -17,7 +17,7 @@ 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) + log := testlog.Logger(t, log.LevelDebug) miner := NewL1Miner(t, log, sd.L1Cfg) t.Cleanup(func() { _ = miner.Close() diff --git a/op-e2e/actions/l1_replica_test.go b/op-e2e/actions/l1_replica_test.go index fa12159f7ea6..7e9b65cfac86 100644 --- a/op-e2e/actions/l1_replica_test.go +++ b/op-e2e/actions/l1_replica_test.go @@ -34,7 +34,7 @@ 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) + log := testlog.Logger(t, log.LevelDebug) replica := NewL1Replica(t, log, sd.L1Cfg) t.Cleanup(func() { _ = replica.Close() @@ -56,7 +56,7 @@ 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) + log := testlog.Logger(t, log.LevelDebug) genesisBlock := sd.L1Cfg.ToBlock() consensus := beacon.New(ethash.NewFaker()) db := rawdb.NewMemoryDatabase() diff --git a/op-e2e/actions/l2_batcher.go b/op-e2e/actions/l2_batcher.go index 66e3b9ea2182..908eb9b4f6b3 100644 --- a/op-e2e/actions/l2_batcher.go +++ b/op-e2e/actions/l2_batcher.go @@ -8,18 +8,26 @@ import ( "io" "math/big" + "github.com/holiman/uint256" + "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" - "github.com/stretchr/testify/require" + "github.com/ethereum-optimism/optimism/op-batcher/batcher" "github.com/ethereum-optimism/optimism/op-batcher/compressor" + batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + plasma "github.com/ethereum-optimism/optimism/op-plasma" "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/txmgr" ) type SyncStatusAPI interface { @@ -36,6 +44,10 @@ type L1TxAPI interface { SendTransaction(ctx context.Context, tx *types.Transaction) error } +type PlasmaInputSetter interface { + SetInput(ctx context.Context, img []byte) (plasma.Keccak256Commitment, error) +} + type BatcherCfg struct { // Limit the size of txs MinL1TxSize uint64 @@ -47,6 +59,30 @@ type BatcherCfg struct { ForceSubmitSingularBatch bool ForceSubmitSpanBatch bool + UsePlasma bool + + DataAvailabilityType batcherFlags.DataAvailabilityType + PlasmaDA PlasmaInputSetter +} + +func DefaultBatcherCfg(dp *e2eutils.DeployParams) *BatcherCfg { + return &BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, + DataAvailabilityType: batcherFlags.CalldataType, + } +} + +func PlasmaBatcherCfg(dp *e2eutils.DeployParams, plasmaDa PlasmaInputSetter) *BatcherCfg { + return &BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, + DataAvailabilityType: batcherFlags.CalldataType, + PlasmaDA: plasmaDa, + UsePlasma: true, + } } type L2BlockRefs interface { @@ -76,6 +112,8 @@ type L2Batcher struct { l2SubmittedBlock eth.L2BlockRef l2BatcherCfg *BatcherCfg batcherAddr common.Address + + LastSubmitted *types.Transaction } func NewL2Batcher(log log.Logger, rollupCfg *rollup.Config, batcherCfg *BatcherCfg, api SyncStatusAPI, l1 L1TxAPI, l2 BlocksAPI, engCl L2BlockRefs) *L2Batcher { @@ -152,8 +190,7 @@ func (s *L2Batcher) Buffer(t Testing) error { ch, err = NewGarbageChannelOut(s.l2BatcherCfg.GarbageCfg) } else { c, e := compressor.NewRatioCompressor(compressor.Config{ - TargetFrameSize: s.l2BatcherCfg.MaxL1TxSize, - TargetNumFrames: 1, + TargetOutputSize: batcher.MaxDataSize(1, s.l2BatcherCfg.MaxL1TxSize), ApproxComprRatio: 1, }) require.NoError(t, e, "failed to create compressor") @@ -212,6 +249,13 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing, txOpts ...func(tx *types.Dynamic t.Fatalf("failed to output channel data to frame: %v", err) } + payload := data.Bytes() + if s.l2BatcherCfg.UsePlasma { + comm, err := s.l2BatcherCfg.PlasmaDA.SetInput(t.Ctx(), payload) + require.NoError(t, err, "failed to set input for plasma") + payload = comm.TxData() + } + nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.batcherAddr) require.NoError(t, err, "need batcher nonce") @@ -220,26 +264,137 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing, txOpts ...func(tx *types.Dynamic require.NoError(t, err, "need l1 pending header for gas price estimation") gasFeeCap := new(big.Int).Add(gasTipCap, new(big.Int).Mul(pendingHeader.BaseFee, big.NewInt(2))) - rawTx := &types.DynamicFeeTx{ - ChainID: s.rollupCfg.L1ChainID, - Nonce: nonce, - To: &s.rollupCfg.BatchInboxAddress, - GasTipCap: gasTipCap, - GasFeeCap: gasFeeCap, - Data: data.Bytes(), + var txData types.TxData + if s.l2BatcherCfg.DataAvailabilityType == batcherFlags.CalldataType { + rawTx := &types.DynamicFeeTx{ + ChainID: s.rollupCfg.L1ChainID, + Nonce: nonce, + To: &s.rollupCfg.BatchInboxAddress, + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + Data: payload, + } + for _, opt := range txOpts { + opt(rawTx) + } + + gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false) + require.NoError(t, err, "need to compute intrinsic gas") + rawTx.Gas = gas + txData = rawTx + } else if s.l2BatcherCfg.DataAvailabilityType == batcherFlags.BlobsType { + var b eth.Blob + require.NoError(t, b.FromData(payload), "must turn data into blob") + sidecar, blobHashes, err := txmgr.MakeSidecar([]*eth.Blob{&b}) + require.NoError(t, err) + require.NotNil(t, pendingHeader.ExcessBlobGas, "need L1 header with 4844 properties") + blobBaseFee := eip4844.CalcBlobFee(*pendingHeader.ExcessBlobGas) + blobFeeCap := new(uint256.Int).Mul(uint256.NewInt(2), uint256.MustFromBig(blobBaseFee)) + if blobFeeCap.Lt(uint256.NewInt(params.GWei)) { // ensure we meet 1 gwei geth tx-pool minimum + blobFeeCap = uint256.NewInt(params.GWei) + } + txData = &types.BlobTx{ + To: s.rollupCfg.BatchInboxAddress, + Data: nil, + Gas: params.TxGas, // intrinsic gas only + BlobHashes: blobHashes, + Sidecar: sidecar, + ChainID: uint256.MustFromBig(s.rollupCfg.L1ChainID), + GasTipCap: uint256.MustFromBig(gasTipCap), + GasFeeCap: uint256.MustFromBig(gasFeeCap), + BlobFeeCap: blobFeeCap, + Value: uint256.NewInt(0), + Nonce: nonce, + } + } else { + t.Fatalf("unrecognized DA type: %q", string(s.l2BatcherCfg.DataAvailabilityType)) } - for _, opt := range txOpts { - opt(rawTx) + + tx, err := types.SignNewTx(s.l2BatcherCfg.BatcherKey, s.l1Signer, txData) + require.NoError(t, err, "need to sign tx") + + err = s.l1.SendTransaction(t.Ctx(), tx) + require.NoError(t, err, "need to send tx") + s.LastSubmitted = tx +} + +func (s *L2Batcher) ActL2BatchSubmitMultiBlob(t Testing, numBlobs int) { + if s.l2BatcherCfg.DataAvailabilityType != batcherFlags.BlobsType { + t.InvalidAction("ActL2BatchSubmitMultiBlob only available for Blobs DA type") + return + } else if numBlobs > 6 || numBlobs < 1 { + t.InvalidAction("invalid number of blobs %d, must be within [1,6]", numBlobs) } - gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false) - require.NoError(t, err, "need to compute intrinsic gas") - rawTx.Gas = gas - tx, err := types.SignNewTx(s.l2BatcherCfg.BatcherKey, s.l1Signer, rawTx) + // Don't run this action if there's no data to submit + if s.l2ChannelOut == nil { + t.InvalidAction("need to buffer data first, cannot batch submit with empty buffer") + return + } + + // Collect the output frames into blobs + blobs := make([]*eth.Blob, numBlobs) + for i := 0; i < numBlobs; i++ { + data := new(bytes.Buffer) + data.WriteByte(derive.DerivationVersion0) + // write only a few bytes to all but the last blob + l := uint64(derive.FrameV0OverHeadSize + 4) // 4 bytes content + if i == numBlobs-1 { + // write remaining channel to last frame + // subtract one, to account for the version byte + l = s.l2BatcherCfg.MaxL1TxSize - 1 + } + if _, err := s.l2ChannelOut.OutputFrame(data, l); err == io.EOF { + s.l2Submitting = false + if i < numBlobs-1 { + t.Fatalf("failed to fill up %d blobs, only filled %d", numBlobs, i+1) + } + s.l2ChannelOut = nil + } else if err != nil { + s.l2Submitting = false + t.Fatalf("failed to output channel data to frame: %v", err) + } + + blobs[i] = new(eth.Blob) + require.NoError(t, blobs[i].FromData(data.Bytes()), "must turn data into blob") + } + + nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.batcherAddr) + require.NoError(t, err, "need batcher nonce") + + gasTipCap := big.NewInt(2 * params.GWei) + pendingHeader, err := s.l1.HeaderByNumber(t.Ctx(), big.NewInt(-1)) + require.NoError(t, err, "need l1 pending header for gas price estimation") + gasFeeCap := new(big.Int).Add(gasTipCap, new(big.Int).Mul(pendingHeader.BaseFee, big.NewInt(2))) + + sidecar, blobHashes, err := txmgr.MakeSidecar(blobs) + require.NoError(t, err) + require.NotNil(t, pendingHeader.ExcessBlobGas, "need L1 header with 4844 properties") + blobBaseFee := eip4844.CalcBlobFee(*pendingHeader.ExcessBlobGas) + blobFeeCap := new(uint256.Int).Mul(uint256.NewInt(2), uint256.MustFromBig(blobBaseFee)) + if blobFeeCap.Lt(uint256.NewInt(params.GWei)) { // ensure we meet 1 gwei geth tx-pool minimum + blobFeeCap = uint256.NewInt(params.GWei) + } + txData := &types.BlobTx{ + To: s.rollupCfg.BatchInboxAddress, + Data: nil, + Gas: params.TxGas, // intrinsic gas only + BlobHashes: blobHashes, + Sidecar: sidecar, + ChainID: uint256.MustFromBig(s.rollupCfg.L1ChainID), + GasTipCap: uint256.MustFromBig(gasTipCap), + GasFeeCap: uint256.MustFromBig(gasFeeCap), + BlobFeeCap: blobFeeCap, + Value: uint256.NewInt(0), + Nonce: nonce, + } + + tx, err := types.SignNewTx(s.l2BatcherCfg.BatcherKey, s.l1Signer, txData) require.NoError(t, err, "need to sign tx") err = s.l1.SendTransaction(t.Ctx(), tx) require.NoError(t, err, "need to send tx") + s.LastSubmitted = tx } // ActL2BatchSubmitGarbage constructs a malformed channel frame and submits it to the @@ -338,3 +493,9 @@ func (s *L2Batcher) ActSubmitAll(t Testing) { s.ActL2ChannelClose(t) s.ActL2BatchSubmit(t) } + +func (s *L2Batcher) ActSubmitAllMultiBlobs(t Testing, numBlobs int) { + s.ActBufferAll(t) + s.ActL2ChannelClose(t) + s.ActL2BatchSubmitMultiBlob(t, numBlobs) +} diff --git a/op-e2e/actions/l2_batcher_test.go b/op-e2e/actions/l2_batcher_test.go index e3bb484a655d..82dd4bccacec 100644 --- a/op-e2e/actions/l2_batcher_test.go +++ b/op-e2e/actions/l2_batcher_test.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/require" + batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" @@ -82,16 +83,13 @@ func NormalBatcher(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp := e2eutils.MakeDeployParams(t, p) applyDeltaTimeOffset(dp, deltaTimeOffset) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) // Alice makes a L2 tx cl := seqEngine.EthClient() @@ -154,7 +152,7 @@ func L2Finalization(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) applyDeltaTimeOffset(dp, deltaTimeOffset) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) miner, engine, sequencer := setupSequencerTest(t, sd, log) sequencer.ActL2PipelineFull(t) @@ -186,11 +184,8 @@ func L2Finalization(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { require.Equal(t, uint64(1), sequencer.SyncStatus().FinalizedL1.Number) require.Equal(t, uint64(0), sequencer.SyncStatus().FinalizedL2.Number, "L2 block has to be included on L1 before it can be finalized") - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) heightToSubmit := sequencer.SyncStatus().UnsafeL2.Number @@ -261,7 +256,7 @@ func L2FinalizationWithSparseL1(gt *testing.T, deltaTimeOffset *hexutil.Uint64) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) applyDeltaTimeOffset(dp, deltaTimeOffset) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) miner, engine, sequencer := setupSequencerTest(t, sd, log) sequencer.ActL2PipelineFull(t) @@ -273,11 +268,8 @@ func L2FinalizationWithSparseL1(gt *testing.T, deltaTimeOffset *hexutil.Uint64) startStatus := sequencer.SyncStatus() require.Less(t, startStatus.SafeL2.Number, startStatus.UnsafeL2.Number, "sequencer has unsafe L2 block") - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) batcher.ActSubmitAll(t) // include in L1 @@ -322,16 +314,12 @@ func GarbageBatch(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { applyDeltaTimeOffset(dp, deltaTimeOffset) for _, garbageKind := range GarbageKinds { sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) miner, engine, sequencer := setupSequencerTest(t, sd, log) - _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) - batcherCfg := &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - } + batcherCfg := DefaultBatcherCfg(dp) if garbageKind == MALFORM_RLP || garbageKind == INVALID_COMPRESSION { // If the garbage kind is `INVALID_COMPRESSION` or `MALFORM_RLP`, use the `actions` packages @@ -406,16 +394,13 @@ func ExtendedTimeWithoutL1Batches(gt *testing.T, deltaTimeOffset *hexutil.Uint64 dp := e2eutils.MakeDeployParams(t, p) applyDeltaTimeOffset(dp, deltaTimeOffset) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) miner, engine, sequencer := setupSequencerTest(t, sd, log) - _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t) @@ -465,15 +450,16 @@ func BigL2Txs(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp := e2eutils.MakeDeployParams(t, p) applyDeltaTimeOffset(dp, deltaTimeOffset) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) miner, engine, sequencer := setupSequencerTest(t, sd, log) - _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 40_000, // try a small batch size, to force the data to be split between more frames - BatcherKey: dp.Secrets.Batcher, + MinL1TxSize: 0, + MaxL1TxSize: 40_000, // try a small batch size, to force the data to be split between more frames + BatcherKey: dp.Secrets.Batcher, + DataAvailabilityType: batcherFlags.CalldataType, }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) diff --git a/op-e2e/actions/l2_engine.go b/op-e2e/actions/l2_engine.go index b8647c382c4e..910f487fb7c0 100644 --- a/op-e2e/actions/l2_engine.go +++ b/op-e2e/actions/l2_engine.go @@ -142,6 +142,10 @@ func (s *L2Engine) AddPeers(peers ...*enode.Node) { } } +func (s *L2Engine) PeerCount() int { + return s.node.Server().PeerCount() +} + func (s *L2Engine) EthClient() *ethclient.Client { cl := s.node.Attach() return ethclient.NewClient(cl) @@ -170,13 +174,13 @@ func (e *L2Engine) EngineClient(t Testing, cfg *rollup.Config) *sources.EngineCl return l2Cl } -// ActL2RPCFail makes the next L2 RPC request fail -func (e *L2Engine) ActL2RPCFail(t Testing) { +// ActL2RPCFail makes the next L2 RPC request fail with given error +func (e *L2Engine) ActL2RPCFail(t Testing, err error) { 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") + e.failL2RPC = err } // ActL2IncludeTx includes the next transaction from the given address in the block that is being built diff --git a/op-e2e/actions/l2_engine_test.go b/op-e2e/actions/l2_engine_test.go index c497f7f5a34c..36e146c282a6 100644 --- a/op-e2e/actions/l2_engine_test.go +++ b/op-e2e/actions/l2_engine_test.go @@ -1,6 +1,7 @@ package actions import ( + "errors" "math/big" "testing" @@ -30,7 +31,7 @@ func TestL2EngineAPI(gt *testing.T) { jwtPath := e2eutils.WriteDefaultJWT(t) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) genesisBlock := sd.L2Cfg.ToBlock() consensus := beacon.New(ethash.NewFaker()) db := rawdb.NewMemoryDatabase() @@ -94,7 +95,7 @@ func TestL2EngineAPIBlockBuilding(gt *testing.T) { jwtPath := e2eutils.WriteDefaultJWT(t) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) genesisBlock := sd.L2Cfg.ToBlock() db := rawdb.NewMemoryDatabase() tdb := trie.NewDatabase(db, &trie.Config{HashDB: hashdb.Defaults}) @@ -154,7 +155,7 @@ func TestL2EngineAPIBlockBuilding(gt *testing.T) { engine.ActL2IncludeTx(dp.Addresses.Alice)(t) } - envelope, err := l2Cl.GetPayload(t.Ctx(), *fcRes.PayloadID) + envelope, err := l2Cl.GetPayload(t.Ctx(), eth.PayloadInfo{ID: *fcRes.PayloadID, Timestamp: uint64(nextBlockTime)}) payload := envelope.ExecutionPayload require.NoError(t, err) require.Equal(t, parent.Hash(), payload.ParentHash, "block builds on parent block") @@ -189,15 +190,16 @@ func TestL2EngineAPIFail(gt *testing.T) { jwtPath := e2eutils.WriteDefaultJWT(t) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) engine := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) // mock an RPC failure - engine.ActL2RPCFail(t) + mockErr := errors.New("mock L2 RPC error") + engine.ActL2RPCFail(t, mockErr) // 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") + require.ErrorIs(t, err, mockErr) 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_proposer.go b/op-e2e/actions/l2_proposer.go index 7705b5f4985a..660bc71b4b20 100644 --- a/op-e2e/actions/l2_proposer.go +++ b/op-e2e/actions/l2_proposer.go @@ -18,9 +18,11 @@ import ( "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-proposer/metrics" "github.com/ethereum-optimism/optimism/op-proposer/proposer" "github.com/ethereum-optimism/optimism/op-service/dial" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/txmgr" ) @@ -29,20 +31,22 @@ type ProposerCfg struct { OutputOracleAddr *common.Address DisputeGameFactoryAddr *common.Address ProposalInterval time.Duration - DisputeGameType uint8 + DisputeGameType uint32 ProposerKey *ecdsa.PrivateKey AllowNonFinalized bool } type L2Proposer struct { - log log.Logger - l1 *ethclient.Client - driver *proposer.L2OutputSubmitter - contract *bindings.L2OutputOracleCaller - address common.Address - privKey *ecdsa.PrivateKey - contractAddr common.Address - lastTx common.Hash + log log.Logger + l1 *ethclient.Client + driver *proposer.L2OutputSubmitter + l2OutputOracle *bindings.L2OutputOracleCaller + l2OutputOracleAddr *common.Address + disputeGameFactory *bindings.DisputeGameFactoryCaller + disputeGameFactoryAddr *common.Address + address common.Address + privKey *ecdsa.PrivateKey + lastTx common.Hash } type fakeTxMgr struct { @@ -64,6 +68,10 @@ func (f fakeTxMgr) Send(_ context.Context, _ txmgr.TxCandidate) (*types.Receipt, func (f fakeTxMgr) Close() { } +func (f fakeTxMgr) IsClosed() bool { + return false +} + func NewL2Proposer(t Testing, log log.Logger, cfg *ProposerCfg, l1 *ethclient.Client, rollupCl *sources.RollupClient) *L2Proposer { proposerConfig := proposer.ProposerConfig{ PollInterval: time.Second, @@ -85,28 +93,34 @@ func NewL2Proposer(t Testing, log log.Logger, cfg *ProposerCfg, l1 *ethclient.Cl RollupProvider: rollupProvider, } - if cfg.OutputOracleAddr == nil { - panic("L2OutputOracle address must be set in op-e2e test harness. The DisputeGameFactory is not yet supported as a proposal destination.") - } - dr, err := proposer.NewL2OutputSubmitter(driverSetup) require.NoError(t, err) - contract, err := bindings.NewL2OutputOracleCaller(*cfg.OutputOracleAddr, l1) - require.NoError(t, err) address := crypto.PubkeyToAddress(cfg.ProposerKey.PublicKey) - proposer, err := contract.PROPOSER(&bind.CallOpts{}) - require.NoError(t, err) - require.Equal(t, proposer, address, "PROPOSER must be the proposer's address") + + var l2OutputOracle *bindings.L2OutputOracleCaller + var disputeGameFactory *bindings.DisputeGameFactoryCaller + if e2eutils.UseFPAC() { + disputeGameFactory, err = bindings.NewDisputeGameFactoryCaller(*cfg.DisputeGameFactoryAddr, l1) + require.NoError(t, err) + } else { + l2OutputOracle, err := bindings.NewL2OutputOracleCaller(*cfg.OutputOracleAddr, l1) + require.NoError(t, err) + proposer, err := l2OutputOracle.PROPOSER(&bind.CallOpts{}) + require.NoError(t, err) + require.Equal(t, proposer, address, "PROPOSER must be the proposer's address") + } return &L2Proposer{ - log: log, - l1: l1, - driver: dr, - contract: contract, - address: address, - privKey: cfg.ProposerKey, - contractAddr: *cfg.OutputOracleAddr, + log: log, + l1: l1, + driver: dr, + l2OutputOracle: l2OutputOracle, + l2OutputOracleAddr: cfg.OutputOracleAddr, + disputeGameFactory: disputeGameFactory, + disputeGameFactoryAddr: cfg.DisputeGameFactoryAddr, + address: address, + privKey: cfg.ProposerKey, } } @@ -122,9 +136,16 @@ func (p *L2Proposer) sendTx(t Testing, data []byte) { nonce, err := p.l1.NonceAt(t.Ctx(), p.address, nil) require.NoError(t, err) + var addr common.Address + if e2eutils.UseFPAC() { + addr = *p.disputeGameFactoryAddr + } else { + addr = *p.l2OutputOracleAddr + } + gasLimit, err := estimateGasPending(t.Ctx(), p.l1, ethereum.CallMsg{ From: p.address, - To: &p.contractAddr, + To: &addr, GasFeeCap: gasFeeCap, GasTipCap: gasTipCap, Data: data, @@ -133,7 +154,7 @@ func (p *L2Proposer) sendTx(t Testing, data []byte) { rawTx := &types.DynamicFeeTx{ Nonce: nonce, - To: &p.contractAddr, + To: &addr, Data: data, GasFeeCap: gasFeeCap, GasTipCap: gasTipCap, @@ -145,7 +166,6 @@ func (p *L2Proposer) sendTx(t Testing, data []byte) { require.NoError(t, err, "need to sign tx") err = p.l1.SendTransaction(t.Ctx(), tx) - log.Info("Proposer sent tx", "hash", tx.Hash(), "to", p.contractAddr) require.NoError(t, err, "need to send tx") p.lastTx = tx.Hash() @@ -184,21 +204,56 @@ func toCallArg(msg ethereum.CallMsg) interface{} { return arg } +func (p *L2Proposer) fetchNextOutput(t Testing) (*eth.OutputResponse, bool, error) { + if e2eutils.UseFPAC() { + blockNumber, err := p.driver.FetchCurrentBlockNumber(t.Ctx()) + if err != nil { + return nil, false, err + } + + output, _, err := p.driver.FetchOutput(t.Ctx(), blockNumber) + if err != nil { + return nil, false, err + } + + encodedBlockNumber := make([]byte, 32) + copy(encodedBlockNumber[32-len(blockNumber.Bytes()):], blockNumber.Bytes()) + game, err := p.disputeGameFactory.Games(&bind.CallOpts{}, p.driver.Cfg.DisputeGameType, output.OutputRoot, encodedBlockNumber) + if err != nil { + return nil, false, err + } + if game.Timestamp != 0 { + return nil, false, nil + } + + return output, true, nil + } else { + return p.driver.FetchNextOutputInfo(t.Ctx()) + } +} + func (p *L2Proposer) CanPropose(t Testing) bool { - _, shouldPropose, err := p.driver.FetchNextOutputInfo(t.Ctx()) + _, shouldPropose, err := p.fetchNextOutput(t) require.NoError(t, err) return shouldPropose } func (p *L2Proposer) ActMakeProposalTx(t Testing) { - output, shouldPropose, err := p.driver.FetchNextOutputInfo(t.Ctx()) + output, shouldPropose, err := p.fetchNextOutput(t) + require.NoError(t, err) + if !shouldPropose { return } - require.NoError(t, err) - txData, err := p.driver.ProposeL2OutputTxData(output) - require.NoError(t, err) + var txData []byte + if e2eutils.UseFPAC() { + txData, _, err = p.driver.ProposeL2OutputDGFTxData(output) + require.NoError(t, err) + } else { + txData, err = p.driver.ProposeL2OutputTxData(output) + require.NoError(t, err) + } // Note: Use L1 instead of the output submitter's transaction manager because // this is non-blocking while the txmgr is blocking & deadlocks the tests diff --git a/op-e2e/actions/l2_proposer_test.go b/op-e2e/actions/l2_proposer_test.go index 1c346f020680..5143b58e7c5f 100644 --- a/op-e2e/actions/l2_proposer_test.go +++ b/op-e2e/actions/l2_proposer_test.go @@ -1,15 +1,19 @@ package actions import ( + "math/big" "testing" + "time" "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/types" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-bindings/bindingspreview" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" @@ -44,21 +48,29 @@ func RunProposerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) rollupSeqCl := sequencer.RollupClient() - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) - proposer := NewL2Proposer(t, log, &ProposerCfg{ - OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy, - ProposerKey: dp.Secrets.Proposer, - AllowNonFinalized: false, - }, miner.EthClient(), sequencer.RollupClient()) + var proposer *L2Proposer + if e2eutils.UseFPAC() { + proposer = NewL2Proposer(t, log, &ProposerCfg{ + DisputeGameFactoryAddr: &sd.DeploymentsL1.DisputeGameFactoryProxy, + ProposalInterval: 6 * time.Second, + DisputeGameType: 0, + ProposerKey: dp.Secrets.Proposer, + AllowNonFinalized: true, + }, miner.EthClient(), rollupSeqCl) + } else { + proposer = NewL2Proposer(t, log, &ProposerCfg{ + OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy, + ProposerKey: dp.Secrets.Proposer, + AllowNonFinalized: false, + }, miner.EthClient(), rollupSeqCl) + } // L1 block miner.ActEmptyBlock(t) @@ -97,17 +109,41 @@ func RunProposerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { } // check that L1 stored the expected output root - outputOracleContract, err := bindings.NewL2OutputOracle(sd.DeploymentsL1.L2OutputOracleProxy, miner.EthClient()) - require.NoError(t, err) - blockNumber, err := outputOracleContract.LatestBlockNumber(&bind.CallOpts{}) - require.NoError(t, err) - require.Greater(t, int64(blockNumber.Uint64()), int64(0), "latest block number must be greater than 0") - block, err := seqEngine.EthClient().BlockByNumber(t.Ctx(), blockNumber) - require.NoError(t, err) - outputOnL1, err := outputOracleContract.GetL2OutputAfter(&bind.CallOpts{}, blockNumber) - require.NoError(t, err) - require.Less(t, block.Time(), outputOnL1.Timestamp.Uint64(), "output is registered with L1 timestamp of proposal tx, past L2 block") - outputComputed, err := sequencer.RollupClient().OutputAtBlock(t.Ctx(), blockNumber.Uint64()) - require.NoError(t, err) - require.Equal(t, eth.Bytes32(outputOnL1.OutputRoot), outputComputed.OutputRoot, "output roots must match") + if e2eutils.UseFPAC() { + optimismPortal2Contract, err := bindingspreview.NewOptimismPortal2(sd.DeploymentsL1.OptimismPortalProxy, miner.EthClient()) + require.NoError(t, err) + respectedGameType, err := optimismPortal2Contract.RespectedGameType(&bind.CallOpts{}) + require.NoError(t, err) + disputeGameFactoryContract, err := bindings.NewDisputeGameFactory(sd.DeploymentsL1.DisputeGameFactoryProxy, miner.EthClient()) + require.NoError(t, err) + gameCount, err := disputeGameFactoryContract.GameCount(&bind.CallOpts{}) + require.NoError(t, err) + require.Greater(t, gameCount.Uint64(), uint64(0), "game count must be greater than 0") + latestGames, err := disputeGameFactoryContract.FindLatestGames(&bind.CallOpts{}, respectedGameType, new(big.Int).Sub(gameCount, common.Big1), common.Big1) + require.NoError(t, err) + require.Greater(t, len(latestGames), 0, "latest games must be greater than 0") + latestGame := latestGames[0] + gameBlockNumber := new(big.Int) + gameBlockNumber.SetBytes(latestGame.ExtraData[0:32]) + block, err := seqEngine.EthClient().BlockByNumber(t.Ctx(), gameBlockNumber) + require.NoError(t, err) + require.Less(t, block.Time(), latestGame.Timestamp, "output is registered with L1 timestamp of proposal tx, past L2 block") + outputComputed, err := sequencer.RollupClient().OutputAtBlock(t.Ctx(), gameBlockNumber.Uint64()) + require.NoError(t, err) + require.Equal(t, eth.Bytes32(latestGame.RootClaim), outputComputed.OutputRoot, "output roots must match") + } else { + outputOracleContract, err := bindings.NewL2OutputOracle(sd.DeploymentsL1.L2OutputOracleProxy, miner.EthClient()) + require.NoError(t, err) + blockNumber, err := outputOracleContract.LatestBlockNumber(&bind.CallOpts{}) + require.NoError(t, err) + require.Greater(t, int64(blockNumber.Uint64()), int64(0), "latest block number must be greater than 0") + block, err := seqEngine.EthClient().BlockByNumber(t.Ctx(), blockNumber) + require.NoError(t, err) + outputOnL1, err := outputOracleContract.GetL2OutputAfter(&bind.CallOpts{}, blockNumber) + require.NoError(t, err) + require.Less(t, block.Time(), outputOnL1.Timestamp.Uint64(), "output is registered with L1 timestamp of proposal tx, past L2 block") + outputComputed, err := sequencer.RollupClient().OutputAtBlock(t.Ctx(), blockNumber.Uint64()) + require.NoError(t, err) + require.Equal(t, eth.Bytes32(outputOnL1.OutputRoot), outputComputed.OutputRoot, "output roots must match") + } } diff --git a/op-e2e/actions/l2_sequencer.go b/op-e2e/actions/l2_sequencer.go index f479a46ce337..c1c93cf74dec 100644 --- a/op-e2e/actions/l2_sequencer.go +++ b/op-e2e/actions/l2_sequencer.go @@ -4,6 +4,7 @@ import ( "context" "errors" + "github.com/ethereum-optimism/optimism/op-node/node/safedb" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" @@ -30,18 +31,6 @@ func (m *MockL1OriginSelector) FindL1Origin(ctx context.Context, l2Head eth.L2Bl return m.actual.FindL1Origin(ctx, l2Head) } -// emptyL1BlobsFetcher is a no-op blobs provider. The actions test batcher currently only supports using calldata. -type emptyL1BlobsFetcher struct { - t Testing -} - -var _ derive.L1BlobsFetcher = &emptyL1BlobsFetcher{} - -func (e *emptyL1BlobsFetcher) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) { - e.t.Fatal("actions test do not support blobs") - return nil, nil -} - // 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 { @@ -54,9 +43,9 @@ type L2Sequencer struct { mockL1OriginSelector *MockL1OriginSelector } -func NewL2Sequencer(t Testing, log log.Logger, l1 derive.L1Fetcher, eng L2API, cfg *rollup.Config, seqConfDepth uint64) *L2Sequencer { - mockBlobFetcher := &emptyL1BlobsFetcher{t: t} - ver := NewL2Verifier(t, log, l1, mockBlobFetcher, eng, cfg, &sync.Config{}) +func NewL2Sequencer(t Testing, log log.Logger, l1 derive.L1Fetcher, blobSrc derive.L1BlobsFetcher, + plasmaSrc derive.PlasmaInputFetcher, eng L2API, cfg *rollup.Config, seqConfDepth uint64) *L2Sequencer { + ver := NewL2Verifier(t, log, l1, blobSrc, plasmaSrc, eng, cfg, &sync.Config{}, safedb.Disabled) attrBuilder := derive.NewFetchingAttributesBuilder(cfg, l1, eng) seqConfDepthL1 := driver.NewConfDepth(seqConfDepth, ver.l1State.L1Head, l1) l1OriginSelector := &MockL1OriginSelector{ diff --git a/op-e2e/actions/l2_sequencer_test.go b/op-e2e/actions/l2_sequencer_test.go index 2bfd8d6cb0dc..1bcf4c4d0cff 100644 --- a/op-e2e/actions/l2_sequencer_test.go +++ b/op-e2e/actions/l2_sequencer_test.go @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + plasma "github.com/ethereum-optimism/optimism/op-plasma" "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/testlog" ) @@ -47,7 +48,7 @@ func setupSequencerTest(t Testing, sd *e2eutils.SetupData, log log.Logger) (*L1M l2Cl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) require.NoError(t, err) - sequencer := NewL2Sequencer(t, log, l1F, l2Cl, sd.RollupCfg, 0) + sequencer := NewL2Sequencer(t, log, l1F, miner.BlobStore(), plasma.Disabled, l2Cl, sd.RollupCfg, 0) return miner, engine, sequencer } @@ -61,7 +62,7 @@ func TestL2Sequencer_SequencerDrift(gt *testing.T) { } dp := e2eutils.MakeDeployParams(t, p) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) miner, engine, sequencer := setupSequencerTest(t, sd, log) miner.ActL1SetFeeRecipient(common.Address{'A'}) @@ -129,7 +130,7 @@ func TestL2Sequencer_SequencerOnlyReorg(gt *testing.T) { t := NewDefaultTesting(gt) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) miner, _, sequencer := setupSequencerTest(t, sd, log) // Sequencer at first only recognizes the genesis as safe. diff --git a/op-e2e/actions/l2_verifier.go b/op-e2e/actions/l2_verifier.go index 3e8095ae182a..5cd743329f96 100644 --- a/op-e2e/actions/l2_verifier.go +++ b/op-e2e/actions/l2_verifier.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/eigenda" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/testutils" @@ -58,10 +59,15 @@ type L2API interface { OutputV0AtBlock(ctx context.Context, blockHash common.Hash) (*eth.OutputV0, error) } -func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, blobsSrc derive.L1BlobsFetcher, eng L2API, cfg *rollup.Config, syncCfg *sync.Config) *L2Verifier { +type safeDB interface { + derive.SafeHeadListener + node.SafeDBReader +} + +func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, blobsSrc derive.L1BlobsFetcher, plasmaSrc derive.PlasmaInputFetcher, eng L2API, cfg *rollup.Config, syncCfg *sync.Config, safeHeadListener safeDB, daCfg *eigenda.Config) *L2Verifier { metrics := &testutils.TestDerivationMetrics{} engine := derive.NewEngineController(eng, log, metrics, cfg, syncCfg.SyncMode) - pipeline := derive.NewDerivationPipeline(log, cfg, l1, blobsSrc, eng, engine, metrics, syncCfg) + pipeline := derive.NewDerivationPipeline(log, cfg, l1, blobsSrc, plasmaSrc, eng, engine, metrics, syncCfg, safeHeadListener, daCfg) pipeline.Reset() rollupNode := &L2Verifier{ @@ -84,7 +90,7 @@ func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, blobsSrc deri apis := []rpc.API{ { Namespace: "optimism", - Service: node.NewNodeAPI(cfg, eng, backend, log, m), + Service: node.NewNodeAPI(cfg, eng, backend, safeHeadListener, log, m), Public: true, Authenticated: false, }, @@ -150,6 +156,10 @@ func (s *L2Verifier) L2Unsafe() eth.L2BlockRef { return s.engine.UnsafeL2Head() } +func (s *L2Verifier) L2BackupUnsafe() eth.L2BlockRef { + return s.engine.BackupUnsafeL2Head() +} + func (s *L2Verifier) SyncStatus() *eth.SyncStatus { return ð.SyncStatus{ CurrentL1: s.derivation.Origin(), diff --git a/op-e2e/actions/l2_verifier_test.go b/op-e2e/actions/l2_verifier_test.go index 4150c984f695..6fe70a3e6fb4 100644 --- a/op-e2e/actions/l2_verifier_test.go +++ b/op-e2e/actions/l2_verifier_test.go @@ -3,6 +3,8 @@ package actions import ( "testing" + "github.com/ethereum-optimism/optimism/op-node/node/safedb" + plasma "github.com/ethereum-optimism/optimism/op-plasma" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" @@ -13,19 +15,40 @@ import ( "github.com/ethereum-optimism/optimism/op-service/testlog" ) -func setupVerifier(t Testing, sd *e2eutils.SetupData, log log.Logger, l1F derive.L1Fetcher, syncCfg *sync.Config) (*L2Engine, *L2Verifier) { +type verifierCfg struct { + safeHeadListener safeDB +} + +type VerifierOpt func(opts *verifierCfg) + +func WithSafeHeadListener(l safeDB) VerifierOpt { + return func(opts *verifierCfg) { + opts.safeHeadListener = l + } +} + +func defaultVerifierCfg() *verifierCfg { + return &verifierCfg{ + safeHeadListener: safedb.Disabled, + } +} + +func setupVerifier(t Testing, sd *e2eutils.SetupData, log log.Logger, l1F derive.L1Fetcher, blobSrc derive.L1BlobsFetcher, syncCfg *sync.Config, opts ...VerifierOpt) (*L2Engine, *L2Verifier) { + cfg := defaultVerifierCfg() + for _, opt := range opts { + opt(cfg) + } jwtPath := e2eutils.WriteDefaultJWT(t) engine := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, EngineWithP2P()) engCl := engine.EngineClient(t, sd.RollupCfg) - mockBlobFetcher := &emptyL1BlobsFetcher{t: t} - verifier := NewL2Verifier(t, log, l1F, mockBlobFetcher, engCl, sd.RollupCfg, syncCfg) + verifier := NewL2Verifier(t, log, l1F, blobSrc, plasma.Disabled, engCl, sd.RollupCfg, syncCfg, cfg.safeHeadListener) return engine, verifier } func setupVerifierOnlyTest(t Testing, sd *e2eutils.SetupData, log log.Logger) (*L1Miner, *L2Engine, *L2Verifier) { miner := NewL1Miner(t, log, sd.L1Cfg) l1Cl := miner.L1Client(t, sd.RollupCfg) - engine, verifier := setupVerifier(t, sd, log, l1Cl, &sync.Config{}) + engine, verifier := setupVerifier(t, sd, log, l1Cl, miner.BlobStore(), &sync.Config{}) return miner, engine, verifier } @@ -39,7 +62,7 @@ func TestL2Verifier_SequenceWindow(gt *testing.T) { } dp := e2eutils.MakeDeployParams(t, p) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) miner, engine, verifier := setupVerifierOnlyTest(t, sd, log) miner.ActL1SetFeeRecipient(common.Address{'A'}) diff --git a/op-e2e/actions/plasma_test.go b/op-e2e/actions/plasma_test.go new file mode 100644 index 000000000000..f8bc24188a52 --- /dev/null +++ b/op-e2e/actions/plasma_test.go @@ -0,0 +1,624 @@ +package actions + +import ( + "math/big" + "math/rand" + "testing" + + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/node/safedb" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + plasma "github.com/ethereum-optimism/optimism/op-plasma" + "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "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/log" + "github.com/stretchr/testify/require" +) + +// Devnet allocs should have plasma mode enabled for these tests to pass + +// L2PlasmaDA is a test harness for manipulating plasma DA state. +type L2PlasmaDA struct { + log log.Logger + storage *plasma.DAErrFaker + daMgr *plasma.DA + plasmaCfg plasma.Config + contract *bindings.DataAvailabilityChallenge + batcher *L2Batcher + sequencer *L2Sequencer + engine *L2Engine + engCl *sources.EngineClient + sd *e2eutils.SetupData + dp *e2eutils.DeployParams + miner *L1Miner + alice *CrossLayerUser + lastComm []byte + lastCommBn uint64 +} + +type PlasmaParam func(p *e2eutils.TestParams) + +func NewL2PlasmaDA(t Testing, params ...PlasmaParam) *L2PlasmaDA { + p := &e2eutils.TestParams{ + MaxSequencerDrift: 40, + SequencerWindowSize: 120, + ChannelTimeout: 120, + L1BlockTime: 12, + UsePlasma: true, + } + for _, apply := range params { + apply(p) + } + log := testlog.Logger(t, log.LvlDebug) + + dp := e2eutils.MakeDeployParams(t, p) + sd := e2eutils.Setup(t, dp, defaultAlloc) + + require.True(t, sd.RollupCfg.UsePlasma) + + miner := NewL1Miner(t, log, sd.L1Cfg) + l1Client := miner.EthClient() + + jwtPath := e2eutils.WriteDefaultJWT(t) + engine := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + engCl := engine.EngineClient(t, sd.RollupCfg) + + storage := &plasma.DAErrFaker{Client: plasma.NewMockDAClient(log)} + + l1F, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false, sources.RPCKindBasic)) + require.NoError(t, err) + + plasmaCfg, err := sd.RollupCfg.PlasmaConfig() + require.NoError(t, err) + + daMgr := plasma.NewPlasmaDAWithStorage(log, plasmaCfg, storage, &plasma.NoopMetrics{}) + + sequencer := NewL2Sequencer(t, log, l1F, nil, daMgr, engCl, sd.RollupCfg, 0) + miner.ActL1SetFeeRecipient(common.Address{'A'}) + sequencer.ActL2PipelineFull(t) + + batcher := NewL2Batcher(log, sd.RollupCfg, PlasmaBatcherCfg(dp, storage), sequencer.RollupClient(), l1Client, engine.EthClient(), engCl) + + addresses := e2eutils.CollectAddresses(sd, dp) + cl := engine.EthClient() + l2UserEnv := &BasicUserEnv[*L2Bindings]{ + EthCl: cl, + Signer: types.LatestSigner(sd.L2Cfg.Config), + AddressCorpora: addresses, + Bindings: NewL2Bindings(t, cl, engine.GethClient()), + } + alice := NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) + alice.L2.SetUserEnv(l2UserEnv) + + contract, err := bindings.NewDataAvailabilityChallenge(sd.RollupCfg.DAChallengeAddress, l1Client) + require.NoError(t, err) + + challengeWindow, err := contract.ChallengeWindow(nil) + require.NoError(t, err) + require.Equal(t, plasmaCfg.ChallengeWindow, challengeWindow.Uint64()) + + resolveWindow, err := contract.ResolveWindow(nil) + require.NoError(t, err) + require.Equal(t, plasmaCfg.ResolveWindow, resolveWindow.Uint64()) + + return &L2PlasmaDA{ + log: log, + storage: storage, + daMgr: daMgr, + plasmaCfg: plasmaCfg, + contract: contract, + batcher: batcher, + sequencer: sequencer, + engine: engine, + engCl: engCl, + sd: sd, + dp: dp, + miner: miner, + alice: alice, + } +} + +func (a *L2PlasmaDA) StorageClient() *plasma.DAErrFaker { + return a.storage +} + +func (a *L2PlasmaDA) NewVerifier(t Testing) *L2Verifier { + jwtPath := e2eutils.WriteDefaultJWT(t) + engine := NewL2Engine(t, a.log, a.sd.L2Cfg, a.sd.RollupCfg.Genesis.L1, jwtPath) + engCl := engine.EngineClient(t, a.sd.RollupCfg) + l1F, err := sources.NewL1Client(a.miner.RPCClient(), a.log, nil, sources.L1ClientDefaultConfig(a.sd.RollupCfg, false, sources.RPCKindBasic)) + require.NoError(t, err) + + daMgr := plasma.NewPlasmaDAWithStorage(a.log, a.plasmaCfg, a.storage, &plasma.NoopMetrics{}) + + verifier := NewL2Verifier(t, a.log, l1F, nil, daMgr, engCl, a.sd.RollupCfg, &sync.Config{}, safedb.Disabled) + + return verifier +} + +func (a *L2PlasmaDA) ActSequencerIncludeTx(t Testing) { + a.alice.L2.ActResetTxOpts(t) + a.alice.L2.ActSetTxToAddr(&a.dp.Addresses.Bob)(t) + a.alice.L2.ActMakeTx(t) + + a.sequencer.ActL2PipelineFull(t) + + a.sequencer.ActL2StartBlock(t) + a.engine.ActL2IncludeTx(a.alice.Address())(t) + a.sequencer.ActL2EndBlock(t) +} + +func (a *L2PlasmaDA) ActNewL2Tx(t Testing) { + a.ActSequencerIncludeTx(t) + + a.batcher.ActL2BatchBuffer(t) + a.batcher.ActL2ChannelClose(t) + a.batcher.ActL2BatchSubmit(t, func(tx *types.DynamicFeeTx) { + // skip txdata version byte + a.lastComm = tx.Data[1:] + }) + + a.miner.ActL1StartBlock(12)(t) + a.miner.ActL1IncludeTx(a.dp.Addresses.Batcher)(t) + a.miner.ActL1EndBlock(t) + + a.lastCommBn = a.miner.l1Chain.CurrentBlock().Number.Uint64() +} + +func (a *L2PlasmaDA) ActDeleteLastInput(t Testing) { + require.NoError(t, a.storage.Client.DeleteData(a.lastComm)) +} + +func (a *L2PlasmaDA) ActChallengeLastInput(t Testing) { + a.ActChallengeInput(t, a.lastComm, a.lastCommBn) + + a.log.Info("challenged last input", "block", a.lastCommBn) +} + +func (a *L2PlasmaDA) ActChallengeInput(t Testing, comm []byte, bn uint64) { + bondValue, err := a.contract.BondSize(&bind.CallOpts{}) + require.NoError(t, err) + + txOpts, err := bind.NewKeyedTransactorWithChainID(a.dp.Secrets.Alice, a.sd.L1Cfg.Config.ChainID) + require.NoError(t, err) + + txOpts.Value = bondValue + _, err = a.contract.Deposit(txOpts) + require.NoError(t, err) + + a.miner.ActL1StartBlock(12)(t) + a.miner.ActL1IncludeTx(a.alice.Address())(t) + a.miner.ActL1EndBlock(t) + + txOpts, err = bind.NewKeyedTransactorWithChainID(a.dp.Secrets.Alice, a.sd.L1Cfg.Config.ChainID) + require.NoError(t, err) + + _, err = a.contract.Challenge(txOpts, big.NewInt(int64(bn)), comm) + require.NoError(t, err) + + a.miner.ActL1StartBlock(12)(t) + a.miner.ActL1IncludeTx(a.alice.Address())(t) + a.miner.ActL1EndBlock(t) +} + +func (a *L2PlasmaDA) ActExpireLastInput(t Testing) { + reorgWindow := a.plasmaCfg.ResolveWindow + a.plasmaCfg.ChallengeWindow + for a.miner.l1Chain.CurrentBlock().Number.Uint64() <= a.lastCommBn+reorgWindow { + a.miner.ActL1StartBlock(12)(t) + a.miner.ActL1EndBlock(t) + } +} + +func (a *L2PlasmaDA) ActResolveInput(t Testing, comm []byte, input []byte, bn uint64) { + txOpts, err := bind.NewKeyedTransactorWithChainID(a.dp.Secrets.Alice, a.sd.L1Cfg.Config.ChainID) + require.NoError(t, err) + + _, err = a.contract.Resolve(txOpts, big.NewInt(int64(bn)), comm, input) + require.NoError(t, err) + + a.miner.ActL1StartBlock(12)(t) + a.miner.ActL1IncludeTx(a.alice.Address())(t) + a.miner.ActL1EndBlock(t) +} + +func (a *L2PlasmaDA) ActResolveLastChallenge(t Testing) { + // remove derivation byte prefix + input, err := a.storage.GetInput(t.Ctx(), a.lastComm[1:]) + require.NoError(t, err) + + a.ActResolveInput(t, a.lastComm, input, a.lastCommBn) +} + +func (a *L2PlasmaDA) ActL1Blocks(t Testing, n uint64) { + for i := uint64(0); i < n; i++ { + a.miner.ActL1StartBlock(12)(t) + a.miner.ActL1EndBlock(t) + } +} + +func (a *L2PlasmaDA) GetLastTxBlock(t Testing) *types.Block { + rcpt, err := a.engine.EthClient().TransactionReceipt(t.Ctx(), a.alice.L2.lastTxHash) + require.NoError(t, err) + blk, err := a.engine.EthClient().BlockByHash(t.Ctx(), rcpt.BlockHash) + require.NoError(t, err) + return blk +} + +func (a *L2PlasmaDA) ActL1Finalized(t Testing) { + latest := a.miner.l1Chain.CurrentBlock().Number.Uint64() + a.miner.ActL1Safe(t, latest) + a.miner.ActL1Finalize(t, latest) + a.sequencer.ActL1FinalizedSignal(t) +} + +// Commitment is challenged but never resolved, chain reorgs when challenge window expires. +func TestPlasma_ChallengeExpired(gt *testing.T) { + if !e2eutils.UsePlasma() { + gt.Skip("Plasma is not enabled") + } + + t := NewDefaultTesting(gt) + harness := NewL2PlasmaDA(t) + + // generate enough initial l1 blocks to have a finalized head. + harness.ActL1Blocks(t, 5) + + // Include a new l2 transaction, submitting an input commitment to the l1. + harness.ActNewL2Tx(t) + + // Challenge the input commitment on the l1 challenge contract. + harness.ActChallengeLastInput(t) + + blk := harness.GetLastTxBlock(t) + + // catch up the sequencer derivation pipeline with the new l1 blocks. + harness.sequencer.ActL2PipelineFull(t) + + // create enough l1 blocks to expire the resolve window. + harness.ActExpireLastInput(t) + + // catch up the sequencer derivation pipeline with the new l1 blocks. + harness.sequencer.ActL2PipelineFull(t) + + // the L1 finalized signal should trigger plasma to finalize the engine queue. + harness.ActL1Finalized(t) + + // move one more block for engine controller to update. + harness.ActL1Blocks(t, 1) + harness.sequencer.ActL2PipelineFull(t) + + // get new block with same number to compare + newBlk, err := harness.engine.EthClient().BlockByNumber(t.Ctx(), blk.Number()) + require.NoError(t, err) + + // reorg happened even though data was available + require.NotEqual(t, blk.Hash(), newBlk.Hash()) + + // now delete the data from the storage service so it is not available at all + // to the verifier derivation pipeline. + harness.ActDeleteLastInput(t) + + syncStatus := harness.sequencer.SyncStatus() + + // verifier is able to sync with expired missing data + verifier := harness.NewVerifier(t) + verifier.ActL2PipelineFull(t) + verifier.ActL1FinalizedSignal(t) + + verifSyncStatus := verifier.SyncStatus() + + require.Equal(t, syncStatus.FinalizedL2, verifSyncStatus.FinalizedL2) +} + +// Commitment is challenged after sequencer derived the chain but data disappears. A verifier +// derivation pipeline stalls until the challenge is resolved and then resumes with data from the contract. +func TestPlasma_ChallengeResolved(gt *testing.T) { + if !e2eutils.UsePlasma() { + gt.Skip("Plasma is not enabled") + } + + t := NewDefaultTesting(gt) + harness := NewL2PlasmaDA(t) + + // include a new l2 transaction, submitting an input commitment to the l1. + harness.ActNewL2Tx(t) + + // generate 3 l1 blocks. + harness.ActL1Blocks(t, 3) + + // challenge the input commitment for that l2 transaction on the l1 challenge contract. + harness.ActChallengeLastInput(t) + + // catch up sequencer derivation pipeline. + // this syncs the latest event within the AltDA manager. + harness.sequencer.ActL2PipelineFull(t) + + // resolve the challenge on the l1 challenge contract. + harness.ActResolveLastChallenge(t) + + // catch up the sequencer derivation pipeline with the new l1 blocks. + // this syncs the resolved status and input data within the AltDA manager. + harness.sequencer.ActL2PipelineFull(t) + + // finalize l1 + harness.ActL1Finalized(t) + + // delete the data from the storage service so it is not available at all + // to the verifier derivation pipeline. + harness.ActDeleteLastInput(t) + + syncStatus := harness.sequencer.SyncStatus() + + // new verifier is able to sync and resolve the input from calldata + verifier := harness.NewVerifier(t) + verifier.ActL2PipelineFull(t) + verifier.ActL1FinalizedSignal(t) + + verifSyncStatus := verifier.SyncStatus() + + require.Equal(t, syncStatus.SafeL2, verifSyncStatus.SafeL2) +} + +// DA storage service goes offline while sequencer keeps making blocks. When storage comes back online, it should be able to catch up. +func TestPlasma_StorageError(gt *testing.T) { + if !e2eutils.UsePlasma() { + gt.Skip("Plasma is not enabled") + } + + t := NewDefaultTesting(gt) + harness := NewL2PlasmaDA(t) + + // include a new l2 transaction, submitting an input commitment to the l1. + harness.ActNewL2Tx(t) + + txBlk := harness.GetLastTxBlock(t) + + // mock a storage client error when trying to get the pre-image. + // this simulates the storage service going offline for example. + harness.storage.ActGetPreImageFail() + + // try to derive the l2 chain from the submitted inputs commitments. + // the storage call will fail the first time then succeed. + harness.sequencer.ActL2PipelineFull(t) + + // sequencer derivation was able to sync to latest l1 origin + syncStatus := harness.sequencer.SyncStatus() + require.Equal(t, uint64(1), syncStatus.SafeL2.Number) + require.Equal(t, txBlk.Hash(), syncStatus.SafeL2.Hash) +} + +// L1 chain reorgs a resolved challenge so it expires instead causing +// the l2 chain to reorg as well. +func TestPlasma_ChallengeReorg(gt *testing.T) { + if !e2eutils.UsePlasma() { + gt.Skip("Plasma is not enabled") + } + + t := NewDefaultTesting(gt) + harness := NewL2PlasmaDA(t) + + // New L2 tx added to a batch and committed to L1 + harness.ActNewL2Tx(t) + + // add a buffer of L1 blocks + harness.ActL1Blocks(t, 3) + + // challenge the input commitment + harness.ActChallengeLastInput(t) + + // keep track of the block where the L2 tx was included + blk := harness.GetLastTxBlock(t) + + // progress derivation pipeline + harness.sequencer.ActL2PipelineFull(t) + + // resolve the challenge so pipeline can progress + harness.ActResolveLastChallenge(t) + + // derivation marks the challenge as resolve, chain is not impacted + harness.sequencer.ActL2PipelineFull(t) + + // Rewind the L1, essentially reorging the challenge resolution + harness.miner.ActL1RewindToParent(t) + + // Now the L1 chain advances without the challenge resolution + // so the challenge is expired. + harness.ActExpireLastInput(t) + + // derivation pipeline reorgs the commitment out of the chain + harness.sequencer.ActL2PipelineFull(t) + + newBlk, err := harness.engine.EthClient().BlockByNumber(t.Ctx(), blk.Number()) + require.NoError(t, err) + + // confirm the reorg did happen + require.NotEqual(t, blk.Hash(), newBlk.Hash()) +} + +// Sequencer stalls as data is not available, batcher keeps posting, untracked commitments are +// challenged and resolved, then sequencer resumes and catches up. +func TestPlasma_SequencerStalledMultiChallenges(gt *testing.T) { + if !e2eutils.UsePlasma() { + gt.Skip("Plasma is not enabled") + } + + t := NewDefaultTesting(gt) + a := NewL2PlasmaDA(t) + + // generate some initial L1 blocks. + a.ActL1Blocks(t, 5) + a.sequencer.ActL1HeadSignal(t) + + // create a new tx on l2 and commit it to l1 + a.ActNewL2Tx(t) + + // keep track of the related commitment + comm1 := a.lastComm + input1, err := a.storage.GetInput(t.Ctx(), comm1[1:]) + bn1 := a.lastCommBn + require.NoError(t, err) + + // delete it from the DA provider so the pipeline cannot verify it + a.ActDeleteLastInput(t) + + // build more empty l2 unsafe blocks as the l1 origin progresses + a.ActL1Blocks(t, 10) + a.sequencer.ActBuildToL1HeadUnsafe(t) + + // build another L2 block without advancing derivation + a.alice.L2.ActResetTxOpts(t) + a.alice.L2.ActSetTxToAddr(&a.dp.Addresses.Bob)(t) + a.alice.L2.ActMakeTx(t) + + a.sequencer.ActL2StartBlock(t) + a.engine.ActL2IncludeTx(a.alice.Address())(t) + a.sequencer.ActL2EndBlock(t) + + a.batcher.ActL2BatchBuffer(t) + a.batcher.ActL2ChannelClose(t) + a.batcher.ActL2BatchSubmit(t, func(tx *types.DynamicFeeTx) { + a.lastComm = tx.Data[1:] + }) + + // include it in L1 + a.miner.ActL1StartBlock(120)(t) + a.miner.ActL1IncludeTx(a.dp.Addresses.Batcher)(t) + a.miner.ActL1EndBlock(t) + + a.sequencer.ActL1HeadSignal(t) + + unsafe := a.sequencer.L2Unsafe() + unsafeBlk, err := a.engine.EthClient().BlockByHash(t.Ctx(), unsafe.Hash) + require.NoError(t, err) + + // advance the pipeline until it errors out as it is still stuck + // on deriving the first commitment + for i := 0; i < 3; i++ { + a.sequencer.ActL2PipelineStep(t) + } + + // keep track of the second commitment + comm2 := a.lastComm + _, err = a.storage.GetInput(t.Ctx(), comm2[1:]) + require.NoError(t, err) + a.lastCommBn = a.miner.l1Chain.CurrentBlock().Number.Uint64() + + // ensure the second commitment is distinct from the first + require.NotEqual(t, comm1, comm2) + + // challenge the last commitment while the pipeline is stuck on the first + a.ActChallengeLastInput(t) + + // resolve the latest commitment before the first one is event challenged. + a.ActResolveLastChallenge(t) + + // now we delete it to force the pipeline to resolve the second commitment + // from the challenge data. + a.ActDeleteLastInput(t) + + // finally challenge the first commitment + a.ActChallengeInput(t, comm1, bn1) + + // resolve it immediately so we can resume derivation + a.ActResolveInput(t, comm1, input1, bn1) + + // pipeline can go on + a.sequencer.ActL2PipelineFull(t) + + // verify that the chain did not reorg out + safeBlk, err := a.engine.EthClient().BlockByNumber(t.Ctx(), unsafeBlk.Number()) + require.NoError(t, err) + require.Equal(t, unsafeBlk.Hash(), safeBlk.Hash()) +} + +// Verify that finalization happens based on plasma DA windows. +// based on l2_batcher_test.go L2Finalization +func TestPlasma_Finalization(gt *testing.T) { + if !e2eutils.UsePlasma() { + gt.Skip("Plasma is not enabled") + } + t := NewDefaultTesting(gt) + a := NewL2PlasmaDA(t) + + // build L1 block #1 + a.ActL1Blocks(t, 1) + a.miner.ActL1SafeNext(t) + + // Fill with l2 blocks up to the L1 head + a.sequencer.ActL1HeadSignal(t) + a.sequencer.ActBuildToL1Head(t) + + a.sequencer.ActL2PipelineFull(t) + a.sequencer.ActL1SafeSignal(t) + require.Equal(t, uint64(1), a.sequencer.SyncStatus().SafeL1.Number) + + // add L1 block #2 + a.ActL1Blocks(t, 1) + a.miner.ActL1SafeNext(t) + a.miner.ActL1FinalizeNext(t) + a.sequencer.ActL1HeadSignal(t) + a.sequencer.ActBuildToL1Head(t) + + // Catch up derivation + a.sequencer.ActL2PipelineFull(t) + a.sequencer.ActL1FinalizedSignal(t) + a.sequencer.ActL1SafeSignal(t) + + // commit all the l2 blocks to L1 + a.batcher.ActSubmitAll(t) + a.miner.ActL1StartBlock(12)(t) + a.miner.ActL1IncludeTx(a.dp.Addresses.Batcher)(t) + a.miner.ActL1EndBlock(t) + + // verify + a.sequencer.ActL2PipelineFull(t) + + // fill with more unsafe L2 blocks + a.sequencer.ActL1HeadSignal(t) + a.sequencer.ActBuildToL1Head(t) + + // submit those blocks too, block #4 + a.batcher.ActSubmitAll(t) + a.miner.ActL1StartBlock(12)(t) + a.miner.ActL1IncludeTx(a.dp.Addresses.Batcher)(t) + a.miner.ActL1EndBlock(t) + + // add some more L1 blocks #5, #6 + a.miner.ActEmptyBlock(t) + a.miner.ActEmptyBlock(t) + + // and more unsafe L2 blocks + a.sequencer.ActL1HeadSignal(t) + a.sequencer.ActBuildToL1Head(t) + + // move safe/finalize markers: finalize the L1 chain block with the first batch, but not the second + a.miner.ActL1SafeNext(t) // #2 -> #3 + a.miner.ActL1SafeNext(t) // #3 -> #4 + a.miner.ActL1FinalizeNext(t) // #1 -> #2 + a.miner.ActL1FinalizeNext(t) // #2 -> #3 + + // L1 safe and finalized as expected + a.sequencer.ActL2PipelineFull(t) + a.sequencer.ActL1FinalizedSignal(t) + a.sequencer.ActL1SafeSignal(t) + a.sequencer.ActL1HeadSignal(t) + require.Equal(t, uint64(6), a.sequencer.SyncStatus().HeadL1.Number) + require.Equal(t, uint64(4), a.sequencer.SyncStatus().SafeL1.Number) + require.Equal(t, uint64(3), a.sequencer.SyncStatus().FinalizedL1.Number) + // l2 cannot finalize yet as the challenge window is not passed + require.Equal(t, uint64(0), a.sequencer.SyncStatus().FinalizedL2.Number) + + // expire the challenge window so these blocks can no longer be challenged + a.ActL1Blocks(t, a.plasmaCfg.ChallengeWindow) + + // advance derivation and finalize plasma via the L1 signal + a.sequencer.ActL2PipelineFull(t) + a.ActL1Finalized(t) + + // given 12s l1 time and 1s l2 time, l2 should be 12 * 3 = 36 blocks finalized + require.Equal(t, uint64(36), a.sequencer.SyncStatus().FinalizedL2.Number) +} diff --git a/op-e2e/actions/reorg_test.go b/op-e2e/actions/reorg_test.go index 25804e59f0fc..1b4edbaf9cfe 100644 --- a/op-e2e/actions/reorg_test.go +++ b/op-e2e/actions/reorg_test.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + plasma "github.com/ethereum-optimism/optimism/op-plasma" "github.com/ethereum-optimism/optimism/op-service/client" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/sources" @@ -27,7 +28,7 @@ func setupReorgTest(t Testing, config *e2eutils.TestParams, deltaTimeOffset *hex dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) return setupReorgTestActors(t, dp, sd, log) } @@ -36,13 +37,10 @@ func setupReorgTestActors(t Testing, dp *e2eutils.DeployParams, sd *e2eutils.Set miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner.ActL1SetFeeRecipient(common.Address{'A'}) sequencer.ActL2PipelineFull(t) - verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) return sd, dp, miner, sequencer, seqEngine, verifier, verifEngine, batcher } @@ -384,7 +382,7 @@ func DeepReorg(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { } // Set up alice - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) addresses := e2eutils.CollectAddresses(sd, dp) l2UserEnv := &BasicUserEnv[*L2Bindings]{ EthCl: l2Client, @@ -609,7 +607,7 @@ func RestartOpGeth(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) jwtPath := e2eutils.WriteDefaultJWT(t) // L1 miner := NewL1Miner(t, log, sd.L1Cfg) @@ -620,13 +618,10 @@ func RestartOpGeth(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { engRpc := &rpcWrapper{seqEng.RPCClient()} l2Cl, err := sources.NewEngineClient(engRpc, log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) require.NoError(t, err) - sequencer := NewL2Sequencer(t, log, l1F, l2Cl, sd.RollupCfg, 0) + sequencer := NewL2Sequencer(t, log, l1F, miner.BlobStore(), plasma.Disabled, l2Cl, sd.RollupCfg, 0) - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) // start sequencer.ActL2PipelineFull(t) @@ -700,7 +695,7 @@ func ConflictingL2Blocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) sd, _, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) @@ -711,12 +706,9 @@ func ConflictingL2Blocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { require.NoError(t, err) l1F, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false, sources.RPCKindStandard)) require.NoError(t, err) - altSequencer := NewL2Sequencer(t, log, l1F, altSeqEngCl, sd.RollupCfg, 0) - altBatcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, altSequencer.RollupClient(), miner.EthClient(), altSeqEng.EthClient(), altSeqEng.EngineClient(t, sd.RollupCfg)) + altSequencer := NewL2Sequencer(t, log, l1F, miner.BlobStore(), plasma.Disabled, altSeqEngCl, sd.RollupCfg, 0) + altBatcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + altSequencer.RollupClient(), miner.EthClient(), altSeqEng.EthClient(), altSeqEng.EngineClient(t, sd.RollupCfg)) // And set up user Alice, using the alternative sequencer endpoint l2Cl := altSeqEng.EthClient() @@ -815,7 +807,7 @@ func SyncAfterReorg(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { } sd, dp, miner, sequencer, seqEngine, verifier, _, batcher := setupReorgTest(t, &testingParams, deltaTimeOffset) l2Client := seqEngine.EthClient() - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) addresses := e2eutils.CollectAddresses(sd, dp) l2UserEnv := &BasicUserEnv[*L2Bindings]{ EthCl: l2Client, diff --git a/op-e2e/actions/safedb_test.go b/op-e2e/actions/safedb_test.go new file mode 100644 index 000000000000..9fd570fa79f5 --- /dev/null +++ b/op-e2e/actions/safedb_test.go @@ -0,0 +1,140 @@ +package actions + +import ( + "context" + "testing" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/node/safedb" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func TestRecordSafeHeadUpdates(gt *testing.T) { + t := NewDefaultTesting(gt) + sd, miner, sequencer, verifier, verifierEng, batcher := setupSafeDBTest(t, defaultRollupTestParams) + verifEngClient := verifierEng.EngineClient(t, sd.RollupCfg) + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + // build empty L1 block + miner.ActEmptyBlock(t) + + // Create L2 blocks, and reference the L1 head as origin + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) + + // submit all new L2 blocks + batcher.ActSubmitAll(t) + + // new L1 block with L2 batch + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) + batchTx := miner.l1Transactions[0] + miner.ActL1EndBlock(t) + + // verifier picks up the L2 chain that was submitted + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + require.Equal(t, verifier.L2Safe(), sequencer.L2Unsafe(), "verifier syncs from sequencer via L1") + require.NotEqual(t, sequencer.L2Safe(), sequencer.L2Unsafe(), "sequencer has not processed L1 yet") + + // Verify the safe head is recorded + l1Head := miner.l1Chain.CurrentBlock() + firstSafeHeadUpdateL1Block := l1Head.Number.Uint64() + response, err := verifier.RollupClient().SafeHeadAtL1Block(context.Background(), firstSafeHeadUpdateL1Block) + require.NoError(t, err) + require.Equal(t, eth.HeaderBlockID(l1Head), response.L1Block) + require.Equal(t, verifier.L2Unsafe().ID(), response.SafeHead) + + // Should get the same result for anything after that L1 block too + response, err = verifier.RollupClient().SafeHeadAtL1Block(context.Background(), firstSafeHeadUpdateL1Block+1) + require.NoError(t, err) + require.Equal(t, eth.HeaderBlockID(l1Head), response.L1Block) + require.Equal(t, verifier.L2Unsafe().ID(), response.SafeHead) + + // Only genesis is safe at this point + response, err = verifier.RollupClient().SafeHeadAtL1Block(context.Background(), firstSafeHeadUpdateL1Block-1) + require.NoError(t, err) + require.Equal(t, eth.HeaderBlockID(miner.l1Chain.Genesis().Header()), response.L1Block) + require.Equal(t, sd.RollupCfg.Genesis.L2, response.SafeHead) + + // orphan the L1 block that included the batch tx, and build a new different L1 block + miner.ActL1RewindToParent(t) + miner.ActL1SetFeeRecipient(common.Address{'B'}) + miner.ActEmptyBlock(t) + miner.ActEmptyBlock(t) // needs to be a longer chain for reorg to be applied. + + // sync verifier again. The L1 reorg excluded the batch, so now the previous L2 chain should be unsafe again. + // However, the L2 chain can still be canonical later, since it did not reference the reorged L1 block + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + require.Equal(t, verifier.L2Safe(), sequencer.L2Safe(), "verifier rewinds safe when L1 reorgs out batch") + ref, err := verifEngClient.L2BlockRefByLabel(t.Ctx(), eth.Safe) + require.NoError(t, err) + require.Equal(t, verifier.L2Safe(), ref, "verifier engine matches rollup client") + + // The safe head has been reorged so the record should have been deleted, leaving us back with just genesis safe + response, err = verifier.RollupClient().SafeHeadAtL1Block(context.Background(), firstSafeHeadUpdateL1Block) + require.NoError(t, err) + require.Equal(t, eth.HeaderBlockID(miner.l1Chain.Genesis().Header()), response.L1Block) + require.Equal(t, sd.RollupCfg.Genesis.L2, response.SafeHead) + + // Now replay the batch tx in a new L1 block + miner.ActL1StartBlock(12)(t) + miner.ActL1SetFeeRecipient(common.Address{'C'}) + // note: the geth tx pool reorgLoop is too slow (responds to chain head events, but async), + // and there's no way to manually trigger runReorg, so we re-insert it ourselves. + require.NoError(t, miner.eth.TxPool().Add([]*types.Transaction{batchTx}, true, true)[0]) + // need to re-insert previously included tx into the block + miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) + miner.ActL1EndBlock(t) + + // sync the verifier again: now it should be safe again + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + require.Equal(t, verifier.L2Safe(), sequencer.L2Unsafe(), "verifier syncs from sequencer via replayed batch on L1") + ref, err = verifEngClient.L2BlockRefByLabel(t.Ctx(), eth.Safe) + require.NoError(t, err) + require.Equal(t, verifier.L2Safe(), ref, "verifier engine matches rollup client") + + // Verify the safe head is recorded again + l1Head = miner.l1Chain.CurrentBlock() + firstSafeHeadUpdateL1Block = l1Head.Number.Uint64() + response, err = verifier.RollupClient().SafeHeadAtL1Block(context.Background(), firstSafeHeadUpdateL1Block) + require.NoError(t, err) + require.Equal(t, eth.HeaderBlockID(l1Head), response.L1Block) + require.Equal(t, verifier.L2Unsafe().ID(), response.SafeHead) +} + +func setupSafeDBTest(t Testing, config *e2eutils.TestParams) (*e2eutils.SetupData, *L1Miner, *L2Sequencer, *L2Verifier, *L2Engine, *L2Batcher) { + dp := e2eutils.MakeDeployParams(t, config) + + sd := e2eutils.Setup(t, dp, defaultAlloc) + logger := testlog.Logger(t, log.LevelDebug) + + return setupSafeDBTestActors(t, dp, sd, logger) +} + +func setupSafeDBTestActors(t Testing, dp *e2eutils.DeployParams, sd *e2eutils.SetupData, log log.Logger) (*e2eutils.SetupData, *L1Miner, *L2Sequencer, *L2Verifier, *L2Engine, *L2Batcher) { + dir := t.TempDir() + db, err := safedb.NewSafeDB(log, dir) + require.NoError(t, err) + t.Cleanup(func() { + _ = db.Close() + }) + miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) + miner.ActL1SetFeeRecipient(common.Address{'A'}) + sequencer.ActL2PipelineFull(t) + verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}, WithSafeHeadListener(db)) + rollupSeqCl := sequencer.RollupClient() + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + return sd, miner, sequencer, verifier, verifEngine, batcher +} diff --git a/op-e2e/actions/span_batch_test.go b/op-e2e/actions/span_batch_test.go index 07bdd91ee3b9..ce3a48fd2386 100644 --- a/op-e2e/actions/span_batch_test.go +++ b/op-e2e/actions/span_batch_test.go @@ -8,9 +8,8 @@ import ( "math/rand" "testing" - "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" - "github.com/ethereum-optimism/optimism/op-node/rollup/sync" - "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" @@ -20,7 +19,11 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" - "github.com/stretchr/testify/require" + + batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/testlog" ) // TestDropSpanBatchBeforeHardfork tests behavior of op-node before Delta hardfork. @@ -37,9 +40,9 @@ func TestDropSpanBatchBeforeHardfork(gt *testing.T) { // do not activate Delta hardfork for verifier dp.DeployConfig.L2GenesisDeltaTimeOffset = nil sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() // Force batcher to submit SpanBatches to L1. @@ -48,6 +51,7 @@ func TestDropSpanBatchBeforeHardfork(gt *testing.T) { MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, ForceSubmitSpanBatch: true, + DataAvailabilityType: batcherFlags.CalldataType, }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) // Alice makes a L2 tx @@ -127,9 +131,9 @@ func TestHardforkMiddleOfSpanBatch(gt *testing.T) { deltaOffset := hexutil.Uint64(6) dp.DeployConfig.L2GenesisDeltaTimeOffset = &deltaOffset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) minerCl := miner.EthClient() rollupSeqCl := sequencer.RollupClient() @@ -139,6 +143,7 @@ func TestHardforkMiddleOfSpanBatch(gt *testing.T) { MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, ForceSubmitSpanBatch: true, + DataAvailabilityType: batcherFlags.CalldataType, }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) // Alice makes a L2 tx @@ -234,9 +239,9 @@ func TestAcceptSingularBatchAfterHardfork(gt *testing.T) { // activate Delta hardfork for verifier. dp.DeployConfig.L2GenesisDeltaTimeOffset = &minTs sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() // Force batcher to submit SingularBatches to L1. @@ -245,6 +250,7 @@ func TestAcceptSingularBatchAfterHardfork(gt *testing.T) { MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, ForceSubmitSingularBatch: true, + DataAvailabilityType: batcherFlags.CalldataType, }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) // Alice makes a L2 tx @@ -319,9 +325,9 @@ func TestMixOfBatchesAfterHardfork(gt *testing.T) { // Activate Delta hardfork for verifier. dp.DeployConfig.L2GenesisDeltaTimeOffset = &minTs sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() seqEngCl := seqEngine.EthClient() @@ -361,6 +367,7 @@ func TestMixOfBatchesAfterHardfork(gt *testing.T) { BatcherKey: dp.Secrets.Batcher, ForceSubmitSpanBatch: i%2 == 0, // Submit SpanBatch for odd numbered batches ForceSubmitSingularBatch: i%2 == 1, // Submit SingularBatch for even numbered batches + DataAvailabilityType: batcherFlags.CalldataType, } batcher := NewL2Batcher(log, sd.RollupCfg, &batcherCfg, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) // Submit all new blocks @@ -408,16 +415,13 @@ func TestSpanBatchEmptyChain(gt *testing.T) { // Activate Delta hardfork dp.DeployConfig.L2GenesisDeltaTimeOffset = &minTs sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t) @@ -474,16 +478,13 @@ func TestSpanBatchLowThroughputChain(gt *testing.T) { // Activate Delta hardfork dp.DeployConfig.L2GenesisDeltaTimeOffset = &minTs sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) cl := seqEngine.EthClient() const numTestUsers = 5 @@ -574,7 +575,7 @@ func TestSpanBatchLowThroughputChain(gt *testing.T) { func TestBatchEquivalence(gt *testing.T) { t := NewDefaultTesting(gt) - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) p := &e2eutils.TestParams{ MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) @@ -604,10 +605,10 @@ func TestBatchEquivalence(gt *testing.T) { seqEngCl := seqEngine.EthClient() // Setup Delta activated spanVerifier - _, spanVerifier := setupVerifier(t, sdDeltaActivated, log, miner.L1Client(t, sdDeltaActivated.RollupCfg), &sync.Config{}) + _, spanVerifier := setupVerifier(t, sdDeltaActivated, log, miner.L1Client(t, sdDeltaActivated.RollupCfg), miner.BlobStore(), &sync.Config{}) // Setup Delta deactivated spanVerifier - _, singularVerifier := setupVerifier(t, sdDeltaDeactivated, log, miner.L1Client(t, sdDeltaDeactivated.RollupCfg), &sync.Config{}) + _, singularVerifier := setupVerifier(t, sdDeltaDeactivated, log, miner.L1Client(t, sdDeltaDeactivated.RollupCfg), miner.BlobStore(), &sync.Config{}) // Setup SpanBatcher spanBatcher := NewL2Batcher(log, sdDeltaActivated.RollupCfg, &BatcherCfg{ @@ -615,6 +616,7 @@ func TestBatchEquivalence(gt *testing.T) { MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, ForceSubmitSpanBatch: true, + DataAvailabilityType: batcherFlags.CalldataType, }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sdDeltaActivated.RollupCfg)) // Setup SingularBatcher @@ -623,6 +625,7 @@ func TestBatchEquivalence(gt *testing.T) { MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, ForceSubmitSingularBatch: true, + DataAvailabilityType: batcherFlags.CalldataType, }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sdDeltaDeactivated.RollupCfg)) const numTestUsers = 5 diff --git a/op-e2e/actions/sync_test.go b/op-e2e/actions/sync_test.go index efecb376ca51..9dd1ee838413 100644 --- a/op-e2e/actions/sync_test.go +++ b/op-e2e/actions/sync_test.go @@ -16,6 +16,8 @@ import ( "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testutils" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/beacon/engine" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" @@ -54,7 +56,7 @@ func DerivationWithFlakyL1RPC(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlError) // mute all the temporary derivation errors that we forcefully create + log := testlog.Logger(t, log.LevelError) // mute all the temporary derivation errors that we forcefully create _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) rng := rand.New(rand.NewSource(1234)) @@ -94,7 +96,7 @@ func FinalizeWhileSyncing(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlError) // mute all the temporary derivation errors that we forcefully create + log := testlog.Logger(t, log.LevelError) // mute all the temporary derivation errors that we forcefully create _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) sequencer.ActL2PipelineFull(t) @@ -138,7 +140,7 @@ func TestUnsafeSync(gt *testing.T) { t := NewDefaultTesting(gt) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) sd, _, _, sequencer, seqEng, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) @@ -162,24 +164,562 @@ func TestUnsafeSync(gt *testing.T) { } } +func TestBackupUnsafe(gt *testing.T) { + t := NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + minTs := hexutil.Uint64(0) + // Activate Delta hardfork + dp.DeployConfig.L2GenesisDeltaTimeOffset = &minTs + dp.DeployConfig.L2BlockTime = 2 + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlInfo) + _, dp, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + l2Cl := seqEng.EthClient() + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) + + rng := rand.New(rand.NewSource(1234)) + signer := types.LatestSigner(sd.L2Cfg.Config) + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + // Create block A1 ~ A5 + for i := 0; i < 5; i++ { + // Build a L2 block + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) + + // Notify new L2 block to verifier by unsafe gossip + seqHead, err := seqEngCl.PayloadByLabel(t.Ctx(), eth.Unsafe) + require.NoError(t, err) + verifier.ActL2UnsafeGossipReceive(seqHead)(t) + } + + seqHead, err := seqEngCl.PayloadByLabel(t.Ctx(), eth.Unsafe) + require.NoError(t, err) + // eventually correct hash for A5 + targetUnsafeHeadHash := seqHead.ExecutionPayload.BlockHash + + // only advance unsafe head to A5 + require.Equal(t, sequencer.L2Unsafe().Number, uint64(5)) + require.Equal(t, sequencer.L2Safe().Number, uint64(0)) + + // Handle unsafe payload + verifier.ActL2PipelineFull(t) + // only advance unsafe head to A5 + require.Equal(t, verifier.L2Unsafe().Number, uint64(5)) + require.Equal(t, verifier.L2Safe().Number, uint64(0)) + + c, e := compressor.NewRatioCompressor(compressor.Config{ + TargetOutputSize: 128_000, + ApproxComprRatio: 1, + }) + require.NoError(t, e) + spanBatchBuilder := derive.NewSpanBatchBuilder(sd.RollupCfg.Genesis.L2Time, sd.RollupCfg.L2ChainID) + // Create new span batch channel + channelOut, err := derive.NewChannelOut(derive.SpanBatchType, c, spanBatchBuilder) + require.NoError(t, err) + + for i := uint64(1); i <= sequencer.L2Unsafe().Number; i++ { + block, err := l2Cl.BlockByNumber(t.Ctx(), new(big.Int).SetUint64(i)) + require.NoError(t, err) + if i == 2 { + // Make block B2 as an valid block different with unsafe block + // Alice makes a L2 tx + n, err := l2Cl.PendingNonceAt(t.Ctx(), dp.Addresses.Alice) + require.NoError(t, err) + validTx := 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), + }) + block = block.WithBody([]*types.Transaction{block.Transactions()[0], validTx}, []*types.Header{}) + } + if i == 3 { + // Make block B3 as an invalid block + invalidTx := testutils.RandomTx(rng, big.NewInt(100), signer) + block = block.WithBody([]*types.Transaction{block.Transactions()[0], invalidTx}, []*types.Header{}) + } + // Add A1, B2, B3, B4, B5 into the channel + _, err = channelOut.AddBlock(sd.RollupCfg, block) + require.NoError(t, err) + } + + // Submit span batch(A1, B2, invalid B3, B4, B5) + batcher.l2ChannelOut = channelOut + batcher.ActL2ChannelClose(t) + batcher.ActL2BatchSubmit(t) + + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + + // let sequencer process invalid span batch + sequencer.ActL1HeadSignal(t) + // before stepping, make sure backupUnsafe is empty + require.Equal(t, eth.L2BlockRef{}, sequencer.L2BackupUnsafe()) + // pendingSafe must not be advanced as well + require.Equal(t, sequencer.L2PendingSafe().Number, uint64(0)) + // Preheat engine queue and consume A1 from batch + for i := 0; i < 4; i++ { + sequencer.ActL2PipelineStep(t) + } + // A1 is valid original block so pendingSafe is advanced + require.Equal(t, sequencer.L2PendingSafe().Number, uint64(1)) + require.Equal(t, sequencer.L2Unsafe().Number, uint64(5)) + // backupUnsafe is still empty + require.Equal(t, eth.L2BlockRef{}, sequencer.L2BackupUnsafe()) + + // Process B2 + sequencer.ActL2PipelineStep(t) + sequencer.ActL2PipelineStep(t) + // B2 is valid different block, triggering unsafe chain reorg + require.Equal(t, sequencer.L2Unsafe().Number, uint64(2)) + // B2 is valid different block, triggering unsafe block backup + require.Equal(t, targetUnsafeHeadHash, sequencer.L2BackupUnsafe().Hash) + // B2 is valid different block, so pendingSafe is advanced + require.Equal(t, sequencer.L2PendingSafe().Number, uint64(2)) + // try to process invalid leftovers: B3, B4, B5 + sequencer.ActL2PipelineFull(t) + // backupUnsafe is used because A3 is invalid. Check backupUnsafe is emptied after used + require.Equal(t, eth.L2BlockRef{}, sequencer.L2BackupUnsafe()) + + // check pendingSafe is reset + require.Equal(t, sequencer.L2PendingSafe().Number, uint64(0)) + // check backupUnsafe is applied + require.Equal(t, sequencer.L2Unsafe().Hash, targetUnsafeHeadHash) + require.Equal(t, sequencer.L2Unsafe().Number, uint64(5)) + // safe head cannot be advanced because batch contained invalid blocks + require.Equal(t, sequencer.L2Safe().Number, uint64(0)) + + // let verifier process invalid span batch + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + + // safe head cannot be advanced, while unsafe head not changed + require.Equal(t, verifier.L2Unsafe().Number, uint64(5)) + require.Equal(t, verifier.L2Safe().Number, uint64(0)) + require.Equal(t, verifier.L2Unsafe().Hash, targetUnsafeHeadHash) + + // Build and submit a span batch with A1 ~ A5 + batcher.ActSubmitAll(t) + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + + // let sequencer process valid span batch + sequencer.ActL1HeadSignal(t) + sequencer.ActL2PipelineFull(t) + + // safe/unsafe head must be advanced + require.Equal(t, sequencer.L2Unsafe().Number, uint64(5)) + require.Equal(t, sequencer.L2Safe().Number, uint64(5)) + require.Equal(t, sequencer.L2Safe().Hash, targetUnsafeHeadHash) + // check backupUnsafe is emptied after consolidation + require.Equal(t, eth.L2BlockRef{}, sequencer.L2BackupUnsafe()) + + // let verifier process valid span batch + verifier.ActL1HeadSignal(t) + verifier.ActL2PipelineFull(t) + + // safe and unsafe head must be advanced + require.Equal(t, verifier.L2Unsafe().Number, uint64(5)) + require.Equal(t, verifier.L2Safe().Number, uint64(5)) + require.Equal(t, verifier.L2Safe().Hash, targetUnsafeHeadHash) + // check backupUnsafe is emptied after consolidation + require.Equal(t, eth.L2BlockRef{}, verifier.L2BackupUnsafe()) +} + +func TestBackupUnsafeReorgForkChoiceInputError(gt *testing.T) { + t := NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + minTs := hexutil.Uint64(0) + // Activate Delta hardfork + dp.DeployConfig.L2GenesisDeltaTimeOffset = &minTs + dp.DeployConfig.L2BlockTime = 2 + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlInfo) + _, dp, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + l2Cl := seqEng.EthClient() + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) + + rng := rand.New(rand.NewSource(1234)) + signer := types.LatestSigner(sd.L2Cfg.Config) + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + // Create block A1 ~ A5 + for i := 0; i < 5; i++ { + // Build a L2 block + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) + + // Notify new L2 block to verifier by unsafe gossip + seqHead, err := seqEngCl.PayloadByLabel(t.Ctx(), eth.Unsafe) + require.NoError(t, err) + verifier.ActL2UnsafeGossipReceive(seqHead)(t) + } + + seqHead, err := seqEngCl.PayloadByLabel(t.Ctx(), eth.Unsafe) + require.NoError(t, err) + // eventually correct hash for A5 + targetUnsafeHeadHash := seqHead.ExecutionPayload.BlockHash + + // only advance unsafe head to A5 + require.Equal(t, sequencer.L2Unsafe().Number, uint64(5)) + require.Equal(t, sequencer.L2Safe().Number, uint64(0)) + + // Handle unsafe payload + verifier.ActL2PipelineFull(t) + // only advance unsafe head to A5 + require.Equal(t, verifier.L2Unsafe().Number, uint64(5)) + require.Equal(t, verifier.L2Safe().Number, uint64(0)) + + c, e := compressor.NewRatioCompressor(compressor.Config{ + TargetOutputSize: 128_000, + ApproxComprRatio: 1, + }) + require.NoError(t, e) + spanBatchBuilder := derive.NewSpanBatchBuilder(sd.RollupCfg.Genesis.L2Time, sd.RollupCfg.L2ChainID) + // Create new span batch channel + channelOut, err := derive.NewChannelOut(derive.SpanBatchType, c, spanBatchBuilder) + require.NoError(t, err) + + for i := uint64(1); i <= sequencer.L2Unsafe().Number; i++ { + block, err := l2Cl.BlockByNumber(t.Ctx(), new(big.Int).SetUint64(i)) + require.NoError(t, err) + if i == 2 { + // Make block B2 as an valid block different with unsafe block + // Alice makes a L2 tx + n, err := l2Cl.PendingNonceAt(t.Ctx(), dp.Addresses.Alice) + require.NoError(t, err) + validTx := 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), + }) + block = block.WithBody([]*types.Transaction{block.Transactions()[0], validTx}, []*types.Header{}) + } + if i == 3 { + // Make block B3 as an invalid block + invalidTx := testutils.RandomTx(rng, big.NewInt(100), signer) + block = block.WithBody([]*types.Transaction{block.Transactions()[0], invalidTx}, []*types.Header{}) + } + // Add A1, B2, B3, B4, B5 into the channel + _, err = channelOut.AddBlock(sd.RollupCfg, block) + require.NoError(t, err) + } + + // Submit span batch(A1, B2, invalid B3, B4, B5) + batcher.l2ChannelOut = channelOut + batcher.ActL2ChannelClose(t) + batcher.ActL2BatchSubmit(t) + + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + + // let sequencer process invalid span batch + sequencer.ActL1HeadSignal(t) + // before stepping, make sure backupUnsafe is empty + require.Equal(t, eth.L2BlockRef{}, sequencer.L2BackupUnsafe()) + // pendingSafe must not be advanced as well + require.Equal(t, sequencer.L2PendingSafe().Number, uint64(0)) + // Preheat engine queue and consume A1 from batch + for i := 0; i < 4; i++ { + sequencer.ActL2PipelineStep(t) + } + // A1 is valid original block so pendingSafe is advanced + require.Equal(t, sequencer.L2PendingSafe().Number, uint64(1)) + require.Equal(t, sequencer.L2Unsafe().Number, uint64(5)) + // backupUnsafe is still empty + require.Equal(t, eth.L2BlockRef{}, sequencer.L2BackupUnsafe()) + + // Process B2 + sequencer.ActL2PipelineStep(t) + sequencer.ActL2PipelineStep(t) + // B2 is valid different block, triggering unsafe chain reorg + require.Equal(t, sequencer.L2Unsafe().Number, uint64(2)) + // B2 is valid different block, triggering unsafe block backup + require.Equal(t, targetUnsafeHeadHash, sequencer.L2BackupUnsafe().Hash) + // B2 is valid different block, so pendingSafe is advanced + require.Equal(t, sequencer.L2PendingSafe().Number, uint64(2)) + + // B3 is invalid block + // NextAttributes is called + sequencer.ActL2PipelineStep(t) + // forceNextSafeAttributes is called + sequencer.ActL2PipelineStep(t) + // mock forkChoiceUpdate error while restoring previous unsafe chain using backupUnsafe. + seqEng.ActL2RPCFail(t, eth.InputError{Inner: errors.New("mock L2 RPC error"), Code: eth.InvalidForkchoiceState}) + + // TryBackupUnsafeReorg is called + sequencer.ActL2PipelineStep(t) + + // try to process invalid leftovers: B4, B5 + sequencer.ActL2PipelineFull(t) + + // backupUnsafe is not used because forkChoiceUpdate returned an error. + // Check backupUnsafe is emptied. + require.Equal(t, eth.L2BlockRef{}, sequencer.L2BackupUnsafe()) + + // check pendingSafe is reset + require.Equal(t, sequencer.L2PendingSafe().Number, uint64(0)) + // unsafe head is not restored due to forkchoiceUpdate error in TryBackupUnsafeReorg + require.Equal(t, sequencer.L2Unsafe().Number, uint64(2)) + // safe head cannot be advanced because batch contained invalid blocks + require.Equal(t, sequencer.L2Safe().Number, uint64(0)) +} + +func TestBackupUnsafeReorgForkChoiceNotInputError(gt *testing.T) { + t := NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + minTs := hexutil.Uint64(0) + // Activate Delta hardfork + dp.DeployConfig.L2GenesisDeltaTimeOffset = &minTs + dp.DeployConfig.L2BlockTime = 2 + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlInfo) + _, dp, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + l2Cl := seqEng.EthClient() + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) + + rng := rand.New(rand.NewSource(1234)) + signer := types.LatestSigner(sd.L2Cfg.Config) + + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + // Create block A1 ~ A5 + for i := 0; i < 5; i++ { + // Build a L2 block + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) + + // Notify new L2 block to verifier by unsafe gossip + seqHead, err := seqEngCl.PayloadByLabel(t.Ctx(), eth.Unsafe) + require.NoError(t, err) + verifier.ActL2UnsafeGossipReceive(seqHead)(t) + } + + seqHead, err := seqEngCl.PayloadByLabel(t.Ctx(), eth.Unsafe) + require.NoError(t, err) + // eventually correct hash for A5 + targetUnsafeHeadHash := seqHead.ExecutionPayload.BlockHash + + // only advance unsafe head to A5 + require.Equal(t, sequencer.L2Unsafe().Number, uint64(5)) + require.Equal(t, sequencer.L2Safe().Number, uint64(0)) + + // Handle unsafe payload + verifier.ActL2PipelineFull(t) + // only advance unsafe head to A5 + require.Equal(t, verifier.L2Unsafe().Number, uint64(5)) + require.Equal(t, verifier.L2Safe().Number, uint64(0)) + + c, e := compressor.NewRatioCompressor(compressor.Config{ + TargetOutputSize: 128_000, + ApproxComprRatio: 1, + }) + require.NoError(t, e) + spanBatchBuilder := derive.NewSpanBatchBuilder(sd.RollupCfg.Genesis.L2Time, sd.RollupCfg.L2ChainID) + // Create new span batch channel + channelOut, err := derive.NewChannelOut(derive.SpanBatchType, c, spanBatchBuilder) + require.NoError(t, err) + + for i := uint64(1); i <= sequencer.L2Unsafe().Number; i++ { + block, err := l2Cl.BlockByNumber(t.Ctx(), new(big.Int).SetUint64(i)) + require.NoError(t, err) + if i == 2 { + // Make block B2 as an valid block different with unsafe block + // Alice makes a L2 tx + n, err := l2Cl.PendingNonceAt(t.Ctx(), dp.Addresses.Alice) + require.NoError(t, err) + validTx := 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), + }) + block = block.WithBody([]*types.Transaction{block.Transactions()[0], validTx}, []*types.Header{}) + } + if i == 3 { + // Make block B3 as an invalid block + invalidTx := testutils.RandomTx(rng, big.NewInt(100), signer) + block = block.WithBody([]*types.Transaction{block.Transactions()[0], invalidTx}, []*types.Header{}) + } + // Add A1, B2, B3, B4, B5 into the channel + _, err = channelOut.AddBlock(sd.RollupCfg, block) + require.NoError(t, err) + } + + // Submit span batch(A1, B2, invalid B3, B4, B5) + batcher.l2ChannelOut = channelOut + batcher.ActL2ChannelClose(t) + batcher.ActL2BatchSubmit(t) + + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + + // let sequencer process invalid span batch + sequencer.ActL1HeadSignal(t) + // before stepping, make sure backupUnsafe is empty + require.Equal(t, eth.L2BlockRef{}, sequencer.L2BackupUnsafe()) + // pendingSafe must not be advanced as well + require.Equal(t, sequencer.L2PendingSafe().Number, uint64(0)) + // Preheat engine queue and consume A1 from batch + for i := 0; i < 4; i++ { + sequencer.ActL2PipelineStep(t) + } + // A1 is valid original block so pendingSafe is advanced + require.Equal(t, sequencer.L2PendingSafe().Number, uint64(1)) + require.Equal(t, sequencer.L2Unsafe().Number, uint64(5)) + // backupUnsafe is still empty + require.Equal(t, eth.L2BlockRef{}, sequencer.L2BackupUnsafe()) + + // Process B2 + sequencer.ActL2PipelineStep(t) + sequencer.ActL2PipelineStep(t) + // B2 is valid different block, triggering unsafe chain reorg + require.Equal(t, sequencer.L2Unsafe().Number, uint64(2)) + // B2 is valid different block, triggering unsafe block backup + require.Equal(t, targetUnsafeHeadHash, sequencer.L2BackupUnsafe().Hash) + // B2 is valid different block, so pendingSafe is advanced + require.Equal(t, sequencer.L2PendingSafe().Number, uint64(2)) + + // B3 is invalid block + // NextAttributes is called + sequencer.ActL2PipelineStep(t) + // forceNextSafeAttributes is called + sequencer.ActL2PipelineStep(t) + + serverErrCnt := 2 + for i := 0; i < serverErrCnt; i++ { + // mock forkChoiceUpdate failure while restoring previous unsafe chain using backupUnsafe. + seqEng.ActL2RPCFail(t, engine.GenericServerError) + // TryBackupUnsafeReorg is called - forkChoiceUpdate returns GenericServerError so retry + sequencer.ActL2PipelineStep(t) + // backupUnsafeHead not emptied yet + require.Equal(t, targetUnsafeHeadHash, sequencer.L2BackupUnsafe().Hash) + } + // now forkchoice succeeds + // try to process invalid leftovers: B4, B5 + sequencer.ActL2PipelineFull(t) + + // backupUnsafe is used because forkChoiceUpdate eventually succeeded. + // Check backupUnsafe is emptied. + require.Equal(t, eth.L2BlockRef{}, sequencer.L2BackupUnsafe()) + + // check pendingSafe is reset + require.Equal(t, sequencer.L2PendingSafe().Number, uint64(0)) + // check backupUnsafe is applied + require.Equal(t, sequencer.L2Unsafe().Hash, targetUnsafeHeadHash) + require.Equal(t, sequencer.L2Unsafe().Number, uint64(5)) + // safe head cannot be advanced because batch contained invalid blocks + require.Equal(t, sequencer.L2Safe().Number, uint64(0)) +} + // TestELSync tests that a verifier will have the EL import the full chain from the sequencer // when passed a single unsafe block. op-geth can either snap sync or full sync here. func TestELSync(gt *testing.T) { t := NewDefaultTesting(gt) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) miner, seqEng, sequencer := setupSequencerTest(t, sd, log) // Enable engine P2P sync - verEng, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{SyncMode: sync.ELSync}) + verEng, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{SyncMode: sync.ELSync}) + + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) + + sequencer.ActL2PipelineFull(t) + + // Build 10 L1 blocks on the sequencer + for i := 0; i < 10; i++ { + // Build a L2 block + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) + } - seqEng.AddPeers(verEng.Enode()) + // Wait longer to peer. This tests flakes or takes a long time when the op-geth instances are not able to peer. verEng.AddPeers(seqEng.Enode()) - seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + // Insert it on the verifier + seqHead, err := seqEngCl.PayloadByLabel(t.Ctx(), eth.Unsafe) + require.NoError(t, err) + seqStart, err := seqEngCl.PayloadByNumber(t.Ctx(), 1) + require.NoError(t, err) + verifier.ActL2InsertUnsafePayload(seqHead)(t) + + require.Eventually(t, + func() bool { + return seqEng.PeerCount() > 0 && verEng.PeerCount() > 0 + }, + 120*time.Second, 1500*time.Millisecond, + "Sequencer & Verifier must peer with each other for snap sync to work", + ) + + // Expect snap sync to download & execute the entire chain + // Verify this by checking that the verifier has the correct value for block 1 + require.Eventually(t, + func() bool { + block, err := verifier.eng.L2BlockRefByNumber(t.Ctx(), 1) + if err != nil { + return false + } + return seqStart.ExecutionPayload.BlockHash == block.Hash + }, + 60*time.Second, 1500*time.Millisecond, + "verifier did not snap sync", + ) +} + +// TestELSyncTransitionstoCL tests that a verifier which starts with EL sync can switch back to a proper CL sync. +// It takes a sequencer & verifier through the following: +// 1. Build 10 unsafe blocks on the sequencer +// 2. Snap sync those blocks to the verifier +// 3. Build & insert 1 unsafe block from the sequencer to the verifier to end snap sync +// 4. Batch submit everything +// 5. Build 10 more unsafe blocks on the sequencer +// 6. Gossip in the highest block to the verifier. **Expect that it does not snap sync** +// 7. Then gossip the rest of the blocks to the verifier. Once this is complete it should pick up all of the unsafe blocks. +// Prior to this PR, the test would fail at this point. +// 8. Create 1 more block & batch submit everything & assert that the verifier picked up those blocks +func TestELSyncTransitionstoCL(gt *testing.T) { + t := NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + sd := e2eutils.Setup(t, dp, defaultAlloc) + logger := testlog.Logger(t, log.LevelInfo) + + captureLog, captureLogHandler := testlog.CaptureLogger(t, log.LevelInfo) + + miner, seqEng, sequencer := setupSequencerTest(t, sd, logger) + batcher := NewL2Batcher(logger, sd.RollupCfg, DefaultBatcherCfg(dp), sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) + // Enable engine P2P sync + verEng, verifier := setupVerifier(t, sd, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{SyncMode: sync.ELSync}) + + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), logger, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) require.NoError(t, err) + miner.ActEmptyBlock(t) sequencer.ActL2PipelineFull(t) // Build 10 L1 blocks on the sequencer @@ -189,6 +729,9 @@ func TestELSync(gt *testing.T) { sequencer.ActL2EndBlock(t) } + // Wait longer to peer. This tests flakes or takes a long time when the op-geth instances are not able to peer. + verEng.AddPeers(seqEng.Enode()) + // Insert it on the verifier seqHead, err := seqEngCl.PayloadByLabel(t.Ctx(), eth.Unsafe) require.NoError(t, err) @@ -196,6 +739,14 @@ func TestELSync(gt *testing.T) { require.NoError(t, err) verifier.ActL2InsertUnsafePayload(seqHead)(t) + require.Eventually(t, + func() bool { + return seqEng.PeerCount() > 0 && verEng.PeerCount() > 0 + }, + 120*time.Second, 1500*time.Millisecond, + "Sequencer & Verifier must peer with each other for snap sync to work", + ) + // Expect snap sync to download & execute the entire chain // Verify this by checking that the verifier has the correct value for block 1 require.Eventually(t, @@ -207,7 +758,95 @@ func TestELSync(gt *testing.T) { return seqStart.ExecutionPayload.BlockHash == block.Hash }, 60*time.Second, 1500*time.Millisecond, + "verifier did not snap sync", ) + // Despite downloading the blocks, it has not finished finalizing + _, err = verifier.eng.L2BlockRefByLabel(t.Ctx(), "safe") + require.ErrorIs(t, err, ethereum.NotFound) + + // Insert a block on the verifier to end snap sync + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) + seqHead, err = seqEngCl.PayloadByLabel(t.Ctx(), eth.Unsafe) + require.NoError(t, err) + verifier.ActL2InsertUnsafePayload(seqHead)(t) + + // Check that safe + finalized are there + id, err := verifier.eng.L2BlockRefByLabel(t.Ctx(), eth.Safe) + require.Equal(t, uint64(11), id.Number) + require.NoError(t, err) + id, err = verifier.eng.L2BlockRefByLabel(t.Ctx(), eth.Finalized) + require.Equal(t, uint64(11), id.Number) + require.NoError(t, err) + + // Batch submit everything + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) + batcher.ActSubmitAll(t) + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + // Verify that the batch submitted blocks are there now + id, err = sequencer.eng.L2BlockRefByLabel(t.Ctx(), eth.Safe) + require.NoError(t, err) + require.Equal(t, uint64(12), id.Number) + id, err = verifier.eng.L2BlockRefByLabel(t.Ctx(), eth.Safe) + require.NoError(t, err) + require.Equal(t, uint64(12), id.Number) + + // Build another 10 L1 blocks on the sequencer + for i := 0; i < 10; i++ { + // Build a L2 block + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) + } + + // Now pass payloads to the derivation pipeline + // This is a little hacky that we have to manually switch between InsertBlock + // and UnsafeGossipReceive in the tests + seqHead, err = seqEngCl.PayloadByLabel(t.Ctx(), eth.Unsafe) + require.NoError(t, err) + verifier.ActL2UnsafeGossipReceive(seqHead)(t) + verifier.ActL2PipelineFull(t) + // Verify that the derivation pipeline did not request a sync to the new head. This is the core of the test, but a little fragile. + record := captureLogHandler.FindLog(testlog.NewMessageFilter("Forkchoice requested sync to new head"), testlog.NewAttributesFilter("number", "22")) + require.Nil(t, record, "The verifier should not request to sync to block number 22 because it is in CL mode, not EL mode at this point.") + + for i := 13; i < 23; i++ { + seqHead, err = seqEngCl.PayloadByNumber(t.Ctx(), uint64(i)) + require.NoError(t, err) + verifier.ActL2UnsafeGossipReceive(seqHead)(t) + } + verifier.ActL2PipelineFull(t) + + // Verify that the unsafe blocks are there now + // This was failing prior to PR 9661 because op-node would attempt to immediately insert blocks into the EL inside the engine queue. op-geth + // would not be able to fetch the second range of blocks & it would wipe out the unsafe payloads queue because op-node thought that it had a + // higher unsafe block but op-geth did not. + id, err = verifier.eng.L2BlockRefByLabel(t.Ctx(), eth.Unsafe) + require.NoError(t, err) + require.Equal(t, uint64(22), id.Number) + + // Create 1 more block & batch submit everything + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) + batcher.ActSubmitAll(t) + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) + + // Verify that the batch submitted blocks are there now + id, err = sequencer.eng.L2BlockRefByLabel(t.Ctx(), eth.Safe) + require.NoError(t, err) + require.Equal(t, uint64(23), id.Number) + id, err = verifier.eng.L2BlockRefByLabel(t.Ctx(), eth.Safe) + require.NoError(t, err) + require.Equal(t, uint64(23), id.Number) } func TestInvalidPayloadInSpanBatch(gt *testing.T) { @@ -218,7 +857,7 @@ func TestInvalidPayloadInSpanBatch(gt *testing.T) { dp.DeployConfig.L2GenesisDeltaTimeOffset = &minTs dp.DeployConfig.L2BlockTime = 2 sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) _, _, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) l2Cl := seqEng.EthClient() rng := rand.New(rand.NewSource(1234)) @@ -228,8 +867,7 @@ func TestInvalidPayloadInSpanBatch(gt *testing.T) { verifier.ActL2PipelineFull(t) c, e := compressor.NewRatioCompressor(compressor.Config{ - TargetFrameSize: 128_000, - TargetNumFrames: 1, + TargetOutputSize: 128_000, ApproxComprRatio: 1, }) require.NoError(t, e) @@ -277,8 +915,7 @@ func TestInvalidPayloadInSpanBatch(gt *testing.T) { // Create new span batch channel c, e = compressor.NewRatioCompressor(compressor.Config{ - TargetFrameSize: 128_000, - TargetNumFrames: 1, + TargetOutputSize: 128_000, ApproxComprRatio: 1, }) require.NoError(t, e) @@ -341,7 +978,7 @@ func TestSpanBatchAtomicity_Consolidation(gt *testing.T) { dp.DeployConfig.L2GenesisDeltaTimeOffset = &minTs dp.DeployConfig.L2BlockTime = 2 sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) _, _, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) require.NoError(t, err) @@ -400,7 +1037,7 @@ func TestSpanBatchAtomicity_ForceAdvance(gt *testing.T) { dp.DeployConfig.L2GenesisDeltaTimeOffset = &minTs dp.DeployConfig.L2BlockTime = 2 sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) targetHeadNumber := uint64(6) // L1 block time / L2 block time diff --git a/op-e2e/actions/system_config_test.go b/op-e2e/actions/system_config_test.go index f796c9ea6cc2..c9f32d1ea9f0 100644 --- a/op-e2e/actions/system_config_test.go +++ b/op-e2e/actions/system_config_test.go @@ -55,26 +55,22 @@ func BatcherKeyRotation(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp.DeployConfig.L2BlockTime = 2 dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) miner.ActL1SetFeeRecipient(common.Address{'A'}) sequencer.ActL2PipelineFull(t) - _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() // the default batcher - batcherA := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + batcherA := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) // a batcher with a new key - batcherB := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Bob, - }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + altCfg := *DefaultBatcherCfg(dp) + altCfg.BatcherKey = dp.Secrets.Bob + batcherB := NewL2Batcher(log, sd.RollupCfg, &altCfg, + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t) @@ -233,13 +229,10 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) alice := NewBasicUser[any](log, dp.Secrets.Alice, rand.New(rand.NewSource(1234))) alice.SetUserEnv(&BasicUserEnv[any]{ @@ -363,13 +356,10 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) miner.ActEmptyBlock(t) @@ -412,7 +402,7 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) miner.ActL1EndBlock(t) - _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), &sync.Config{}) + _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) verifier.ActL2PipelineFull(t) require.Equal(t, sequencer.L2Unsafe(), verifier.L2Safe(), "verifier stays in sync, even with gaslimit changes") diff --git a/op-e2e/actions/user.go b/op-e2e/actions/user.go index 5e5780fb1f97..726f53ad472c 100644 --- a/op-e2e/actions/user.go +++ b/op-e2e/actions/user.go @@ -6,6 +6,7 @@ import ( "fmt" "math/big" "math/rand" + "time" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -18,17 +19,22 @@ import ( "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-bindings/bindingspreview" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" + "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" + e2e "github.com/ethereum-optimism/optimism/op-e2e" "github.com/ethereum-optimism/optimism/op-e2e/config" + "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" ) type L1Bindings struct { // contract bindings - OptimismPortal *bindings.OptimismPortal - - L2OutputOracle *bindings.L2OutputOracle + OptimismPortal *bindings.OptimismPortal + L2OutputOracle *bindings.L2OutputOracle + OptimismPortal2 *bindingspreview.OptimismPortal2 + DisputeGameFactory *bindings.DisputeGameFactory } func NewL1Bindings(t Testing, l1Cl *ethclient.Client) *L1Bindings { @@ -38,9 +44,17 @@ func NewL1Bindings(t Testing, l1Cl *ethclient.Client) *L1Bindings { l2OutputOracle, err := bindings.NewL2OutputOracle(config.L1Deployments.L2OutputOracleProxy, l1Cl) require.NoError(t, err) + optimismPortal2, err := bindingspreview.NewOptimismPortal2(config.L1Deployments.OptimismPortalProxy, l1Cl) + require.NoError(t, err) + + disputeGameFactory, err := bindings.NewDisputeGameFactory(config.L1Deployments.DisputeGameFactoryProxy, l1Cl) + require.NoError(t, err) + return &L1Bindings{ - OptimismPortal: optimismPortal, - L2OutputOracle: l2OutputOracle, + OptimismPortal: optimismPortal, + L2OutputOracle: l2OutputOracle, + OptimismPortal2: optimismPortal2, + DisputeGameFactory: disputeGameFactory, } } @@ -392,39 +406,89 @@ func (s *CrossLayerUser) Address() common.Address { return s.L1.address } -// ActCompleteWithdrawal creates a L1 proveWithdrawal tx for latest withdrawal. -// The tx hash is remembered as the last L1 tx, to check as L1 actor. -func (s *CrossLayerUser) ActProveWithdrawal(t Testing) { - s.L1.lastTxHash = s.ProveWithdrawal(t, s.lastL2WithdrawalTxHash) -} - -// ProveWithdrawal creates a L1 proveWithdrawal tx for the given L2 withdrawal tx, returning the tx hash. -func (s *CrossLayerUser) ProveWithdrawal(t Testing, l2TxHash common.Hash) common.Hash { - // Figure out when our withdrawal was included - receipt := s.L2.CheckReceipt(t, true, l2TxHash) +func (s *CrossLayerUser) getLatestWithdrawalParams(t Testing) (*withdrawals.ProvenWithdrawalParameters, error) { + receipt := s.L2.CheckReceipt(t, true, s.lastL2WithdrawalTxHash) l2WithdrawalBlock, err := s.L2.env.EthCl.BlockByNumber(t.Ctx(), receipt.BlockNumber) require.NoError(t, err) - // Figure out what the Output oracle on L1 has seen so far - l2OutputBlockNr, err := s.L1.env.Bindings.L2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) - require.NoError(t, err) - l2OutputBlock, err := s.L2.env.EthCl.BlockByNumber(t.Ctx(), l2OutputBlockNr) - require.NoError(t, err) - l2OutputIndex, err := s.L1.env.Bindings.L2OutputOracle.GetL2OutputIndexAfter(&bind.CallOpts{}, l2OutputBlockNr) - require.NoError(t, err) + var l2OutputBlockNr *big.Int + var l2OutputBlock *types.Block + if e2eutils.UseFPAC() { + latestGame, err := withdrawals.FindLatestGame(t.Ctx(), &s.L1.env.Bindings.DisputeGameFactory.DisputeGameFactoryCaller, &s.L1.env.Bindings.OptimismPortal2.OptimismPortal2Caller) + require.NoError(t, err) + l2OutputBlockNr = new(big.Int).SetBytes(latestGame.ExtraData[0:32]) + l2OutputBlock, err = s.L2.env.EthCl.BlockByNumber(t.Ctx(), l2OutputBlockNr) + require.NoError(t, err) + } else { + l2OutputBlockNr, err = s.L1.env.Bindings.L2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) + require.NoError(t, err) + l2OutputBlock, err = s.L2.env.EthCl.BlockByNumber(t.Ctx(), l2OutputBlockNr) + require.NoError(t, err) + } - // Check if the L2 output is even old enough to include the withdrawal if l2OutputBlock.NumberU64() < l2WithdrawalBlock.NumberU64() { - t.InvalidAction("the latest L2 output is %d and is not past L2 block %d that includes the withdrawal yet, no withdrawal can be proved yet", l2OutputBlock.NumberU64(), l2WithdrawalBlock.NumberU64()) - return common.Hash{} + return nil, fmt.Errorf("the latest L2 output is %d and is not past L2 block %d that includes the withdrawal yet, no withdrawal can be proved yet", l2OutputBlock.NumberU64(), l2WithdrawalBlock.NumberU64()) + } + + if !e2eutils.UseFPAC() { + finalizationPeriod, err := s.L1.env.Bindings.L2OutputOracle.FINALIZATIONPERIODSECONDS(&bind.CallOpts{}) + require.NoError(t, err) + l1Head, err := s.L1.env.EthCl.HeaderByNumber(t.Ctx(), nil) + require.NoError(t, err) + + if l2OutputBlock.Time()+finalizationPeriod.Uint64() >= l1Head.Time { + return nil, fmt.Errorf("L2 output block %d (time %d) is not past finalization period %d from L2 block %d (time %d) at head %d (time %d)", l2OutputBlock.NumberU64(), l2OutputBlock.Time(), finalizationPeriod.Uint64(), l2WithdrawalBlock.NumberU64(), l2WithdrawalBlock.Time(), l1Head.Number.Uint64(), l1Head.Time) + } } - // We generate a proof for the latest L2 output, which shouldn't require archive-node data if it's recent enough. header, err := s.L2.env.EthCl.HeaderByNumber(t.Ctx(), l2OutputBlockNr) require.NoError(t, err) - params, err := withdrawals.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header, &s.L1.env.Bindings.L2OutputOracle.L2OutputOracleCaller) + params, err := e2e.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header, &s.L1.env.Bindings.L2OutputOracle.L2OutputOracleCaller, &s.L1.env.Bindings.DisputeGameFactory.DisputeGameFactoryCaller, &s.L1.env.Bindings.OptimismPortal2.OptimismPortal2Caller) require.NoError(t, err) + return ¶ms, nil +} + +func (s *CrossLayerUser) getDisputeGame(t Testing, params withdrawals.ProvenWithdrawalParameters) (*bindings.FaultDisputeGame, error) { + wd := crossdomain.Withdrawal{ + Nonce: params.Nonce, + Sender: ¶ms.Sender, + Target: ¶ms.Target, + Value: params.Value, + GasLimit: params.GasLimit, + Data: params.Data, + } + + portal2, err := bindingspreview.NewOptimismPortal2(config.L1Deployments.OptimismPortalProxy, s.L1.env.EthCl) + require.Nil(t, err) + + wdHash, err := wd.Hash() + require.Nil(t, err) + + game, err := portal2.ProvenWithdrawals(&bind.CallOpts{}, wdHash) + require.Nil(t, err) + require.NotNil(t, game, "withdrawal should be proven") + + proxy, err := bindings.NewFaultDisputeGame(game.DisputeGameProxy, s.L1.env.EthCl) + require.Nil(t, err) + + return proxy, nil +} + +// ActCompleteWithdrawal creates a L1 proveWithdrawal tx for latest withdrawal. +// The tx hash is remembered as the last L1 tx, to check as L1 actor. +func (s *CrossLayerUser) ActProveWithdrawal(t Testing) { + s.L1.lastTxHash = s.ProveWithdrawal(t, s.lastL2WithdrawalTxHash) +} + +// ProveWithdrawal creates a L1 proveWithdrawal tx for the given L2 withdrawal tx, returning the tx hash. +func (s *CrossLayerUser) ProveWithdrawal(t Testing, l2TxHash common.Hash) common.Hash { + params, err := s.getLatestWithdrawalParams(t) + if err != nil { + t.InvalidAction("cannot prove withdrawal: %v", err) + return common.Hash{} + } + // Create the prove tx tx, err := s.L1.env.Bindings.OptimismPortal.ProveWithdrawalTransaction( &s.L1.txOpts, @@ -436,7 +500,7 @@ func (s *CrossLayerUser) ProveWithdrawal(t Testing, l2TxHash common.Hash) common GasLimit: params.GasLimit, Data: params.Data, }, - l2OutputIndex, + params.L2OutputIndex, params.OutputRootProof, params.WithdrawalProof, ) @@ -458,44 +522,12 @@ func (s *CrossLayerUser) ActCompleteWithdrawal(t Testing) { // CompleteWithdrawal creates a L1 withdrawal finalization tx for the given L2 withdrawal tx, returning the tx hash. // It's an invalid action to attempt to complete a withdrawal that has not passed the L1 finalization period yet func (s *CrossLayerUser) CompleteWithdrawal(t Testing, l2TxHash common.Hash) common.Hash { - finalizationPeriod, err := s.L1.env.Bindings.L2OutputOracle.FINALIZATIONPERIODSECONDS(&bind.CallOpts{}) - require.NoError(t, err) - - // Figure out when our withdrawal was included - receipt := s.L2.CheckReceipt(t, true, l2TxHash) - l2WithdrawalBlock, err := s.L2.env.EthCl.BlockByNumber(t.Ctx(), receipt.BlockNumber) - require.NoError(t, err) - - // Figure out what the Output oracle on L1 has seen so far - l2OutputBlockNr, err := s.L1.env.Bindings.L2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) - require.NoError(t, err) - l2OutputBlock, err := s.L2.env.EthCl.BlockByNumber(t.Ctx(), l2OutputBlockNr) - require.NoError(t, err) - - // Check if the L2 output is even old enough to include the withdrawal - if l2OutputBlock.NumberU64() < l2WithdrawalBlock.NumberU64() { - t.InvalidAction("the latest L2 output is %d and is not past L2 block %d that includes the withdrawal yet, no withdrawal can be completed yet", l2OutputBlock.NumberU64(), l2WithdrawalBlock.NumberU64()) - return common.Hash{} - } - - l1Head, err := s.L1.env.EthCl.HeaderByNumber(t.Ctx(), nil) - require.NoError(t, err) - - // Check if the withdrawal may be completed yet - if l2OutputBlock.Time()+finalizationPeriod.Uint64() >= l1Head.Time { - t.InvalidAction("withdrawal tx %s was included in L2 block %d (time %d) but L1 only knows of L2 proposal %d (time %d) at head %d (time %d) which has not reached output confirmation yet (period is %d)", - l2TxHash, l2WithdrawalBlock.NumberU64(), l2WithdrawalBlock.Time(), l2OutputBlock.NumberU64(), l2OutputBlock.Time(), l1Head.Number.Uint64(), l1Head.Time, finalizationPeriod.Uint64()) + params, err := s.getLatestWithdrawalParams(t) + if err != nil { + t.InvalidAction("cannot complete withdrawal: %v", err) return common.Hash{} } - // We generate a proof for the latest L2 output, which shouldn't require archive-node data if it's recent enough. - // Note that for the `FinalizeWithdrawalTransaction` function, this proof isn't needed. We simply use some of the - // params for the `WithdrawalTransaction` type generated in the bindings. - header, err := s.L2.env.EthCl.HeaderByNumber(t.Ctx(), l2OutputBlockNr) - require.NoError(t, err) - params, err := withdrawals.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header, &s.L1.env.Bindings.L2OutputOracle.L2OutputOracleCaller) - require.NoError(t, err) - // Create the withdrawal tx tx, err := s.L1.env.Bindings.OptimismPortal.FinalizeWithdrawalTransaction( &s.L1.txOpts, @@ -515,3 +547,57 @@ func (s *CrossLayerUser) CompleteWithdrawal(t Testing, l2TxHash common.Hash) com require.NoError(t, err, "must send finalize tx") return tx.Hash() } + +// ActResolveClaim creates a L1 resolveClaim tx for the latest withdrawal. +func (s *CrossLayerUser) ActResolveClaim(t Testing) { + s.L1.lastTxHash = s.ResolveClaim(t, s.lastL2WithdrawalTxHash) +} + +// ResolveClaim creates a L1 resolveClaim tx for the given L2 withdrawal tx, returning the tx hash. +func (s *CrossLayerUser) ResolveClaim(t Testing, l2TxHash common.Hash) common.Hash { + params, err := s.getLatestWithdrawalParams(t) + if err != nil { + t.InvalidAction("cannot resolve claim: %v", err) + return common.Hash{} + } + + game, err := s.getDisputeGame(t, *params) + require.NoError(t, err) + + expiry, err := game.GameDuration(&bind.CallOpts{}) + require.Nil(t, err) + + time.Sleep(time.Duration(expiry) * time.Second) + resolveClaimTx, err := game.ResolveClaim(&s.L1.txOpts, common.Big0) + require.Nil(t, err) + + err = s.L1.env.EthCl.SendTransaction(t.Ctx(), resolveClaimTx) + require.Nil(t, err) + return resolveClaimTx.Hash() +} + +// ActResolve creates a L1 resolve tx for the latest withdrawal. +// Resolve is different than resolving a claim, the root claim must be resolved first and then +// the game itself can be resolved. +func (s *CrossLayerUser) ActResolve(t Testing) { + s.L1.lastTxHash = s.Resolve(t, s.lastL2WithdrawalTxHash) +} + +// Resolve creates a L1 resolve tx for the given L2 withdrawal tx, returning the tx hash. +func (s *CrossLayerUser) Resolve(t Testing, l2TxHash common.Hash) common.Hash { + params, err := s.getLatestWithdrawalParams(t) + if err != nil { + t.InvalidAction("cannot resolve game: %v", err) + return common.Hash{} + } + + game, err := s.getDisputeGame(t, *params) + require.NoError(t, err) + + resolveTx, err := game.Resolve(&s.L1.txOpts) + require.Nil(t, err) + + err = s.L1.env.EthCl.SendTransaction(t.Ctx(), resolveTx) + require.Nil(t, err) + return resolveTx.Hash() +} diff --git a/op-e2e/actions/user_test.go b/op-e2e/actions/user_test.go index bed5466baa28..b6f3f370ee27 100644 --- a/op-e2e/actions/user_test.go +++ b/op-e2e/actions/user_test.go @@ -4,6 +4,7 @@ import ( "fmt" "math/rand" "testing" + "time" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" @@ -123,22 +124,31 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) { } sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) require.Equal(t, dp.Secrets.Addresses().Batcher, dp.DeployConfig.BatchSenderAddress) require.Equal(t, dp.Secrets.Addresses().Proposer, dp.DeployConfig.L2OutputOracleProposer) miner, seqEngine, seq := setupSequencerTest(t, sd, log) - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ - MinL1TxSize: 0, - MaxL1TxSize: 128_000, - BatcherKey: dp.Secrets.Batcher, - }, seq.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) - proposer := NewL2Proposer(t, log, &ProposerCfg{ - OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy, - ProposerKey: dp.Secrets.Proposer, - AllowNonFinalized: true, - }, miner.EthClient(), seq.RollupClient()) + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + seq.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + + var proposer *L2Proposer + if e2eutils.UseFPAC() { + proposer = NewL2Proposer(t, log, &ProposerCfg{ + DisputeGameFactoryAddr: &sd.DeploymentsL1.DisputeGameFactoryProxy, + ProposalInterval: 6 * time.Second, + DisputeGameType: 0, + ProposerKey: dp.Secrets.Proposer, + AllowNonFinalized: true, + }, miner.EthClient(), seq.RollupClient()) + } else { + proposer = NewL2Proposer(t, log, &ProposerCfg{ + OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy, + ProposerKey: dp.Secrets.Proposer, + AllowNonFinalized: true, + }, miner.EthClient(), seq.RollupClient()) + } // need to start derivation before we can make L2 blocks seq.ActL2PipelineFull(t) @@ -269,6 +279,25 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) { miner.ActL1StartBlock(13)(t) miner.ActL1EndBlock(t) + // If using FPAC we need to resolve the game + if e2eutils.UseFPAC() { + // Resolve the root claim + alice.ActResolveClaim(t) + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(alice.Address())(t) + miner.ActL1EndBlock(t) + // Resolve the game + alice.L1.ActCheckReceiptStatusOfLastTx(true)(t) + alice.ActResolve(t) + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(alice.Address())(t) + miner.ActL1EndBlock(t) + // Create an empty block to pass the air-gap window + alice.L1.ActCheckReceiptStatusOfLastTx(true)(t) + miner.ActL1StartBlock(13)(t) + miner.ActL1EndBlock(t) + } + // make the L1 finalize withdrawal tx alice.ActCompleteWithdrawal(t) // include completed withdrawal in new L1 block diff --git a/op-e2e/bridge_test.go b/op-e2e/bridge_test.go index 8f617985233f..57ad2997cf1f 100644 --- a/op-e2e/bridge_test.go +++ b/op-e2e/bridge_test.go @@ -32,7 +32,7 @@ func TestERC20BridgeDeposits(t *testing.T) { require.Nil(t, err, "Error starting up system") defer sys.Close() - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) l1Client := sys.Clients["l1"] diff --git a/op-e2e/config/init.go b/op-e2e/config/init.go index 6f60d1a5d81f..4d7a0a7f432c 100644 --- a/op-e2e/config/init.go +++ b/op-e2e/config/init.go @@ -10,6 +10,8 @@ import ( "testing" "time" + "golang.org/x/exp/slog" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/log" @@ -20,10 +22,21 @@ import ( oplog "github.com/ethereum-optimism/optimism/op-service/log" ) +// legacy geth log levels - the geth command line --verbosity flag wasn't +// migrated to use slog's numerical levels. +const ( + LegacyLevelCrit = iota + LegacyLevelError + LegacyLevelWarn + LegacyLevelInfo + LegacyLevelDebug + LegacyLevelTrace +) + var ( // All of the following variables are set in the init function // and read from JSON files on disk that are generated by the - // foundry deploy script. The are globally exported to be used + // foundry deploy script. These are globally exported to be used // in end to end tests. // L1Allocs represents the L1 genesis block state. @@ -39,7 +52,7 @@ var ( // ExternalL2TestParms is additional metadata for executing external L2 // tests. ExternalL2TestParms external.TestParms - // EthNodeVerbosity is the level of verbosity to output + // EthNodeVerbosity is the (legacy geth) level of verbosity to output EthNodeVerbosity int ) @@ -63,26 +76,29 @@ func init() { flag.StringVar(&l1DeploymentsPath, "l1-deployments", defaultL1DeploymentsPath, "") flag.StringVar(&deployConfigPath, "deploy-config", defaultDeployConfigPath, "") flag.StringVar(&externalL2, "externalL2", "", "Enable tests with external L2") - flag.IntVar(&EthNodeVerbosity, "ethLogVerbosity", int(log.LvlInfo), "The level of verbosity to use for the eth node logs") + flag.IntVar(&EthNodeVerbosity, "ethLogVerbosity", LegacyLevelInfo, "The (legacy geth) level of verbosity to use for the eth node logs") testing.Init() // Register test flags before parsing flag.Parse() // Setup global logger - lvl := log.Lvl(EthNodeVerbosity) - if lvl < log.LvlCrit { - log.Root().SetHandler(log.DiscardHandler()) - } else if lvl > log.LvlTrace { // clip to trace level - lvl = log.LvlTrace + lvl := log.FromLegacyLevel(EthNodeVerbosity) + var handler slog.Handler + if lvl > log.LevelCrit { + handler = log.DiscardHandler() + } else { + if lvl < log.LevelTrace { // clip to trace level + lvl = log.LevelTrace + } + // We cannot attach a testlog logger, + // because the global logger is shared between different independent parallel tests. + // Tests that write to a testlogger of another finished test fail. + handler = oplog.NewLogHandler(os.Stdout, oplog.CLIConfig{ + Level: lvl, + Color: false, // some CI logs do not handle colors well + Format: oplog.FormatTerminal, + }) } - // We cannot attach a testlog logger, - // because the global logger is shared between different independent parallel tests. - // Tests that write to a testlogger of another finished test fail. - h := oplog.NewLogHandler(os.Stdout, oplog.CLIConfig{ - Level: lvl, - Color: false, // some CI logs do not handle colors well - Format: oplog.FormatTerminal, - }) - oplog.SetGlobalLogHandler(h) + oplog.SetGlobalLogHandler(handler) if err := allExist(l1AllocsPath, l1DeploymentsPath, deployConfigPath); err != nil { return diff --git a/op-e2e/e2eutils/batcher/batcher.go b/op-e2e/e2eutils/batcher/batcher.go new file mode 100644 index 000000000000..8f3e273dfbeb --- /dev/null +++ b/op-e2e/e2eutils/batcher/batcher.go @@ -0,0 +1,56 @@ +package batcher + +import ( + "context" + "crypto/ecdsa" + "math/big" + "math/rand" + "testing" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-service/testutils" + gethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/require" +) + +type Helper struct { + t *testing.T + privKey *ecdsa.PrivateKey + rollupCfg *rollup.Config + l1Client *ethclient.Client +} + +func NewHelper(t *testing.T, privKey *ecdsa.PrivateKey, rollupCfg *rollup.Config, l1Client *ethclient.Client) *Helper { + return &Helper{ + t: t, + privKey: privKey, + rollupCfg: rollupCfg, + l1Client: l1Client, + } +} + +func (h *Helper) SendLargeInvalidBatch(ctx context.Context) { + nonce, err := h.l1Client.PendingNonceAt(ctx, crypto.PubkeyToAddress(h.privKey.PublicKey)) + require.NoError(h.t, err, "Should get next batcher nonce") + + maxTxDataSize := 131072 // As per the Ethereum spec. + data := testutils.RandomData(rand.New(rand.NewSource(9849248)), maxTxDataSize-200) + tx := gethTypes.MustSignNewTx(h.privKey, h.rollupCfg.L1Signer(), &gethTypes.DynamicFeeTx{ + ChainID: h.rollupCfg.L1ChainID, + Nonce: nonce, + GasTipCap: big.NewInt(1 * params.GWei), + GasFeeCap: big.NewInt(10 * params.GWei), + Gas: 5_000_000, + To: &h.rollupCfg.BatchInboxAddress, + Value: big.NewInt(0), + Data: data, + }) + err = h.l1Client.SendTransaction(ctx, tx) + require.NoError(h.t, err, "Should send large batch transaction") + _, err = wait.ForReceiptOK(ctx, h.l1Client, tx.Hash()) + require.NoError(h.t, err, "Tx should be ok") +} diff --git a/op-e2e/e2eutils/blobs.go b/op-e2e/e2eutils/blobs.go new file mode 100644 index 000000000000..730aae1d94c5 --- /dev/null +++ b/op-e2e/e2eutils/blobs.go @@ -0,0 +1,49 @@ +package e2eutils + +import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-service/eth" +) + +// BlobsStore is a simple in-memory store of blobs, for testing purposes +type BlobsStore struct { + // blockhash -> blob versioned hash -> blob + blobs map[common.Hash]map[common.Hash]*eth.Blob +} + +func NewBlobStore() *BlobsStore { + return &BlobsStore{blobs: make(map[common.Hash]map[common.Hash]*eth.Blob)} +} + +func (store *BlobsStore) StoreBlob(blockHash common.Hash, versionedHash common.Hash, blob *eth.Blob) { + m, ok := store.blobs[blockHash] + if !ok { + m = make(map[common.Hash]*eth.Blob) + store.blobs[blockHash] = m + } + m[versionedHash] = blob +} + +func (store *BlobsStore) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) { + out := make([]*eth.Blob, 0, len(hashes)) + m, ok := store.blobs[ref.Hash] + if !ok { + return nil, fmt.Errorf("no blobs known with given time: %w", ethereum.NotFound) + } + for _, h := range hashes { + b, ok := m[h.Hash] + if !ok { + return nil, fmt.Errorf("blob %d %s is not in store: %w", h.Index, h.Hash, ethereum.NotFound) + } + out = append(out, b) + } + return out, nil +} + +var _ derive.L1BlobsFetcher = (*BlobsStore)(nil) diff --git a/op-e2e/e2eutils/challenger/helper.go b/op-e2e/e2eutils/challenger/helper.go index 60a1483ee58a..a662aff560fb 100644 --- a/op-e2e/e2eutils/challenger/helper.go +++ b/op-e2e/e2eutils/challenger/helper.go @@ -27,6 +27,11 @@ import ( "github.com/ethereum-optimism/optimism/op-service/testlog" ) +type EndpointProvider interface { + NodeEndpoint(name string) string + L1BeaconEndpoint() string +} + type Helper struct { log log.Logger t *testing.T @@ -61,6 +66,25 @@ func WithPollInterval(pollInterval time.Duration) Option { } } +// findMonorepoRoot finds the relative path to the monorepo root +// Different tests might be nested in subdirectories of the op-e2e dir. +func findMonorepoRoot(t *testing.T) string { + path := "./" + // Only search up 5 directories + // Avoids infinite recursion if the root isn't found for some reason + for i := 0; i < 5; i++ { + _, err := os.Stat(path + "op-e2e") + if errors.Is(err, os.ErrNotExist) { + path = path + "../" + continue + } + require.NoErrorf(t, err, "Failed to stat %v even though it existed", path) + return path + } + t.Fatalf("Could not find monorepo root, trying up to %v", path) + return "" +} + func applyCannonConfig( c *config.Config, t *testing.T, @@ -70,9 +94,10 @@ func applyCannonConfig( ) { require := require.New(t) c.CannonL2 = l2Endpoint - c.CannonBin = "../../cannon/bin/cannon" - c.CannonServer = "../../op-program/bin/op-program" - c.CannonAbsolutePreState = "../../op-program/bin/prestate.json" + root := findMonorepoRoot(t) + c.CannonBin = root + "cannon/bin/cannon" + c.CannonServer = root + "op-program/bin/op-program" + c.CannonAbsolutePreState = root + "op-program/bin/prestate.json" c.CannonSnapshotFreq = 10_000_000 genesisBytes, err := json.Marshal(l2Genesis) @@ -109,10 +134,10 @@ func WithAlphabet(rollupEndpoint string) Option { } } -func NewChallenger(t *testing.T, ctx context.Context, l1Endpoint string, name string, options ...Option) *Helper { - log := testlog.Logger(t, log.LvlDebug).New("role", name) - log.Info("Creating challenger", "l1", l1Endpoint) - cfg := NewChallengerConfig(t, l1Endpoint, options...) +func NewChallenger(t *testing.T, ctx context.Context, sys EndpointProvider, name string, options ...Option) *Helper { + log := testlog.Logger(t, log.LevelDebug).New("role", name) + log.Info("Creating challenger") + cfg := NewChallengerConfig(t, sys, options...) chl, err := challenger.Main(ctx, log, cfg) require.NoError(t, err, "must init challenger") require.NoError(t, chl.Start(ctx), "must start challenger") @@ -126,9 +151,14 @@ func NewChallenger(t *testing.T, ctx context.Context, l1Endpoint string, name st } } -func NewChallengerConfig(t *testing.T, l1Endpoint string, options ...Option) *config.Config { +func NewChallengerConfig(t *testing.T, sys EndpointProvider, options ...Option) *config.Config { // Use the NewConfig method to ensure we pick up any defaults that are set. - cfg := config.NewConfig(common.Address{}, l1Endpoint, t.TempDir()) + l1Endpoint := sys.NodeEndpoint("l1") + l1Beacon := sys.L1BeaconEndpoint() + cfg := config.NewConfig(common.Address{}, l1Endpoint, l1Beacon, t.TempDir()) + // The devnet can't set the absolute prestate output root because the contracts are deployed in L1 genesis + // before the L2 genesis is known. + cfg.AllowInvalidPrestate = true cfg.TxMgrConfig.NumConfirmations = 1 cfg.TxMgrConfig.ReceiptQueryInterval = 1 * time.Second if cfg.MaxConcurrency > 4 { diff --git a/op-e2e/e2eutils/disputegame/alphabet_helper.go b/op-e2e/e2eutils/disputegame/alphabet_helper.go index 723ae6d3c67d..228dc52f4ba2 100644 --- a/op-e2e/e2eutils/disputegame/alphabet_helper.go +++ b/op-e2e/e2eutils/disputegame/alphabet_helper.go @@ -13,14 +13,14 @@ type AlphabetGameHelper struct { FaultGameHelper } -func (g *AlphabetGameHelper) StartChallenger(ctx context.Context, l1Endpoint string, name string, options ...challenger.Option) *challenger.Helper { +func (g *AlphabetGameHelper) StartChallenger(ctx context.Context, sys challenger.EndpointProvider, name string, options ...challenger.Option) *challenger.Helper { opts := []challenger.Option{ challenger.WithFactoryAddress(g.factoryAddr), challenger.WithGameAddress(g.addr), challenger.WithAlphabet(g.system.RollupEndpoint("sequencer")), } opts = append(opts, options...) - c := challenger.NewChallenger(g.t, ctx, l1Endpoint, name, opts...) + c := challenger.NewChallenger(g.t, ctx, sys, name, opts...) g.t.Cleanup(func() { _ = c.Close() }) diff --git a/op-e2e/e2eutils/disputegame/claim_helper.go b/op-e2e/e2eutils/disputegame/claim_helper.go index 2e349f29ae15..eff88db4240a 100644 --- a/op-e2e/e2eutils/disputegame/claim_helper.go +++ b/op-e2e/e2eutils/disputegame/claim_helper.go @@ -67,7 +67,12 @@ func (c *ClaimHelper) Depth() types.Depth { // WaitForCounterClaim waits for the claim to be countered by another claim being posted. // It returns a helper for the claim that countered this one. func (c *ClaimHelper) WaitForCounterClaim(ctx context.Context, ignoreClaims ...*ClaimHelper) *ClaimHelper { - counterIdx, counterClaim := c.game.waitForClaim(ctx, fmt.Sprintf("failed to find claim with parent idx %v", c.index), func(claimIdx int64, claim ContractClaim) bool { + timeout := defaultTimeout + if c.IsOutputRootLeaf(ctx) { + // This is the first claim we need to run cannon on, so give it more time + timeout = timeout * 2 + } + counterIdx, counterClaim := c.game.waitForClaim(ctx, timeout, fmt.Sprintf("failed to find claim with parent idx %v", c.index), func(claimIdx int64, claim ContractClaim) bool { return int64(claim.ParentIndex) == c.index && !containsClaim(claimIdx, ignoreClaims) }) return newClaimHelper(c.game, counterIdx, counterClaim) @@ -93,13 +98,13 @@ func (c *ClaimHelper) RequireCorrectOutputRoot(ctx context.Context) { c.require.Equalf(expected, c.claim, "Should have correct output root in claim %v and position %v", c.index, c.position) } -func (c *ClaimHelper) Attack(ctx context.Context, value common.Hash) *ClaimHelper { - c.game.Attack(ctx, c.index, value) +func (c *ClaimHelper) Attack(ctx context.Context, value common.Hash, opts ...MoveOpt) *ClaimHelper { + c.game.Attack(ctx, c.index, value, opts...) return c.WaitForCounterClaim(ctx) } -func (c *ClaimHelper) Defend(ctx context.Context, value common.Hash) *ClaimHelper { - c.game.Defend(ctx, c.index, value) +func (c *ClaimHelper) Defend(ctx context.Context, value common.Hash, opts ...MoveOpt) *ClaimHelper { + c.game.Defend(ctx, c.index, value, opts...) return c.WaitForCounterClaim(ctx) } diff --git a/op-e2e/e2eutils/disputegame/dishonest_helper.go b/op-e2e/e2eutils/disputegame/dishonest_helper.go index 09de3461ca6b..1b5798a06f50 100644 --- a/op-e2e/e2eutils/disputegame/dishonest_helper.go +++ b/op-e2e/e2eutils/disputegame/dishonest_helper.go @@ -9,57 +9,14 @@ import ( "github.com/ethereum/go-ethereum/common" ) -type dishonestClaim struct { - ParentIndex int64 - IsAttack bool - Valid bool -} - type DishonestHelper struct { *OutputGameHelper *OutputHonestHelper - claims map[dishonestClaim]bool defender bool } func newDishonestHelper(g *OutputGameHelper, correctTrace *OutputHonestHelper, defender bool) *DishonestHelper { - return &DishonestHelper{g, correctTrace, make(map[dishonestClaim]bool), defender} -} - -func (t *DishonestHelper) Attack(ctx context.Context, claimIndex int64) { - c := dishonestClaim{claimIndex, true, false} - if t.claims[c] { - return - } - t.claims[c] = true - t.OutputGameHelper.Attack(ctx, claimIndex, common.Hash{byte(claimIndex)}) -} - -func (t *DishonestHelper) Defend(ctx context.Context, claimIndex int64) { - c := dishonestClaim{claimIndex, false, false} - if t.claims[c] { - return - } - t.claims[c] = true - t.OutputGameHelper.Defend(ctx, claimIndex, common.Hash{byte(claimIndex)}) -} - -func (t *DishonestHelper) AttackCorrect(ctx context.Context, claimIndex int64) { - c := dishonestClaim{claimIndex, true, true} - if t.claims[c] { - return - } - t.claims[c] = true - t.OutputHonestHelper.Attack(ctx, claimIndex) -} - -func (t *DishonestHelper) DefendCorrect(ctx context.Context, claimIndex int64) { - c := dishonestClaim{claimIndex, false, true} - if t.claims[c] { - return - } - t.claims[c] = true - t.OutputHonestHelper.Defend(ctx, claimIndex) + return &DishonestHelper{g, correctTrace, defender} } // ExhaustDishonestClaims makes all possible significant moves (mod honest challenger's) in a game. @@ -85,14 +42,14 @@ func (d *DishonestHelper) ExhaustDishonestClaims(ctx context.Context, rootClaim d.OutputGameHelper.t.Logf("Dishonest moves against claimIndex %d", claimIndex) agreeWithLevel := d.defender == (pos.Depth()%2 == 0) if !agreeWithLevel { - d.AttackCorrect(ctx, claimIndex) + d.OutputHonestHelper.Attack(ctx, claimIndex, WithIgnoreDuplicates()) if claimIndex != 0 && pos.Depth() != splitDepth+1 { - d.DefendCorrect(ctx, claimIndex) + d.OutputHonestHelper.Defend(ctx, claimIndex, WithIgnoreDuplicates()) } } - d.Attack(ctx, claimIndex) + d.OutputGameHelper.Attack(ctx, claimIndex, common.Hash{byte(claimIndex)}, WithIgnoreDuplicates()) if claimIndex != 0 && pos.Depth() != splitDepth+1 { - d.Defend(ctx, claimIndex) + d.OutputGameHelper.Defend(ctx, claimIndex, common.Hash{byte(claimIndex)}, WithIgnoreDuplicates()) } } diff --git a/op-e2e/e2eutils/disputegame/helper.go b/op-e2e/e2eutils/disputegame/helper.go index 2f9acd9f3947..291baa09374a 100644 --- a/op-e2e/e2eutils/disputegame/helper.go +++ b/op-e2e/e2eutils/disputegame/helper.go @@ -14,11 +14,12 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/outputs" faultTypes "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame/preimage" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" - "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/l2oo" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -31,9 +32,9 @@ import ( ) const ( - cannonGameType uint8 = 0 - alphabetGameType uint8 = 255 - alphabetGameDepth = 4 + cannonGameType uint32 = 0 + alphabetGameType uint32 = 255 + alphabetGameDepth = 4 ) type Status uint8 @@ -57,7 +58,33 @@ func (s Status) String() string { } } +type gameCfg struct { + allowFuture bool + allowUnsafe bool +} +type GameOpt interface { + Apply(cfg *gameCfg) +} +type gameOptFn func(c *gameCfg) + +func (g gameOptFn) Apply(cfg *gameCfg) { + g(cfg) +} + +func WithUnsafeProposal() GameOpt { + return gameOptFn(func(c *gameCfg) { + c.allowUnsafe = true + }) +} + +func WithFutureProposal() GameOpt { + return gameOptFn(func(c *gameCfg) { + c.allowFuture = true + }) +} + type DisputeSystem interface { + L1BeaconEndpoint() string NodeEndpoint(name string) string NodeClient(name string) *ethclient.Client RollupEndpoint(name string) string @@ -66,6 +93,8 @@ type DisputeSystem interface { L1Deployments() *genesis.L1Deployments RollupCfg() *rollup.Config L2Genesis() *core.Genesis + + AdvanceTime(time.Duration) } type FactoryHelper struct { @@ -76,7 +105,6 @@ type FactoryHelper struct { opts *bind.TransactOpts factoryAddr common.Address factory *bindings.DisputeGameFactory - l2ooHelper *l2oo.L2OOHelper } func NewFactoryHelper(t *testing.T, ctx context.Context, system DisputeSystem) *FactoryHelper { @@ -100,22 +128,46 @@ func NewFactoryHelper(t *testing.T, ctx context.Context, system DisputeSystem) * opts: opts, factory: factory, factoryAddr: factoryAddr, - l2ooHelper: l2oo.NewL2OOHelperReadOnly(t, l1Deployments, client), } } -func (h *FactoryHelper) StartOutputCannonGameWithCorrectRoot(ctx context.Context, l2Node string, l2BlockNumber uint64) *OutputCannonGameHelper { - h.waitForBlockToBeSafe(l2Node, l2BlockNumber) +func (h *FactoryHelper) PreimageHelper(ctx context.Context) *preimage.Helper { + opts := &bind.CallOpts{Context: ctx} + gameAddr, err := h.factory.GameImpls(opts, cannonGameType) + h.require.NoError(err) + game, err := bindings.NewFaultDisputeGameCaller(gameAddr, h.client) + h.require.NoError(err) + vmAddr, err := game.Vm(opts) + h.require.NoError(err) + vm, err := bindings.NewMIPSCaller(vmAddr, h.client) + h.require.NoError(err) + oracleAddr, err := vm.Oracle(opts) + h.require.NoError(err) + return preimage.NewHelper(h.t, h.opts, h.client, oracleAddr) +} + +func newGameCfg(opts ...GameOpt) *gameCfg { + cfg := &gameCfg{} + for _, opt := range opts { + opt.Apply(cfg) + } + return cfg +} + +func (h *FactoryHelper) StartOutputCannonGameWithCorrectRoot(ctx context.Context, l2Node string, l2BlockNumber uint64, opts ...GameOpt) *OutputCannonGameHelper { + cfg := newGameCfg(opts...) + h.waitForBlock(l2Node, l2BlockNumber, cfg) output, err := h.system.RollupClient(l2Node).OutputAtBlock(ctx, l2BlockNumber) h.require.NoErrorf(err, "Failed to get output at block %v", l2BlockNumber) - return h.StartOutputCannonGame(ctx, l2Node, l2BlockNumber, common.Hash(output.OutputRoot)) + return h.StartOutputCannonGame(ctx, l2Node, l2BlockNumber, common.Hash(output.OutputRoot), opts...) } -func (h *FactoryHelper) StartOutputCannonGame(ctx context.Context, l2Node string, l2BlockNumber uint64, rootClaim common.Hash) *OutputCannonGameHelper { - logger := testlog.Logger(h.t, log.LvlInfo).New("role", "OutputCannonGameHelper") +func (h *FactoryHelper) StartOutputCannonGame(ctx context.Context, l2Node string, l2BlockNumber uint64, rootClaim common.Hash, opts ...GameOpt) *OutputCannonGameHelper { + cfg := newGameCfg(opts...) + logger := testlog.Logger(h.t, log.LevelInfo).New("role", "OutputCannonGameHelper") rollupClient := h.system.RollupClient(l2Node) - extraData := h.createBisectionGameExtraData(l2Node, l2BlockNumber) + extraData := h.createBisectionGameExtraData(l2Node, l2BlockNumber, cfg) ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) defer cancel() @@ -126,20 +178,23 @@ func (h *FactoryHelper) StartOutputCannonGame(ctx context.Context, l2Node string h.require.NoError(err, "create fault dispute game") rcpt, err := wait.ForReceiptOK(ctx, h.client, tx.Hash()) h.require.NoError(err, "wait for create fault dispute game receipt to be OK") - h.require.Len(rcpt.Logs, 1, "should have emitted a single DisputeGameCreated event") - createdEvent, err := h.factory.ParseDisputeGameCreated(*rcpt.Logs[0]) + h.require.Len(rcpt.Logs, 2, "should have emitted a single DisputeGameCreated event") + createdEvent, err := h.factory.ParseDisputeGameCreated(*rcpt.Logs[1]) h.require.NoError(err) game, err := bindings.NewFaultDisputeGame(createdEvent.DisputeProxy, h.client) h.require.NoError(err) - prestateBlock, err := game.GenesisBlockNumber(&bind.CallOpts{Context: ctx}) - h.require.NoError(err, "Failed to load genesis block number") - poststateBlock, err := game.L2BlockNumber(&bind.CallOpts{Context: ctx}) + callOpts := &bind.CallOpts{Context: ctx} + prestateBlock, err := game.StartingBlockNumber(callOpts) + h.require.NoError(err, "Failed to load starting block number") + poststateBlock, err := game.L2BlockNumber(callOpts) h.require.NoError(err, "Failed to load l2 block number") - splitDepth, err := game.SplitDepth(&bind.CallOpts{Context: ctx}) + splitDepth, err := game.SplitDepth(callOpts) h.require.NoError(err, "Failed to load split depth") - prestateProvider := outputs.NewPrestateProvider(ctx, logger, rollupClient, prestateBlock.Uint64()) - provider := outputs.NewTraceProviderFromInputs(logger, prestateProvider, rollupClient, faultTypes.Depth(splitDepth.Uint64()), prestateBlock.Uint64(), poststateBlock.Uint64()) + l1Head := h.getL1Head(ctx, game) + + prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock.Uint64()) + provider := outputs.NewTraceProvider(logger, prestateProvider, rollupClient, l1Head, faultTypes.Depth(splitDepth.Uint64()), prestateBlock.Uint64(), poststateBlock.Uint64()) return &OutputCannonGameHelper{ OutputGameHelper: OutputGameHelper{ @@ -156,18 +211,29 @@ func (h *FactoryHelper) StartOutputCannonGame(ctx context.Context, l2Node string } } -func (h *FactoryHelper) StartOutputAlphabetGameWithCorrectRoot(ctx context.Context, l2Node string, l2BlockNumber uint64) *OutputAlphabetGameHelper { - h.waitForBlockToBeSafe(l2Node, l2BlockNumber) +func (h *FactoryHelper) getL1Head(ctx context.Context, game *bindings.FaultDisputeGame) eth.BlockID { + l1HeadHash, err := game.L1Head(&bind.CallOpts{Context: ctx}) + h.require.NoError(err, "Failed to load L1 head") + l1Header, err := h.client.HeaderByHash(ctx, l1HeadHash) + h.require.NoError(err, "Failed to load L1 header") + l1Head := eth.HeaderBlockID(l1Header) + return l1Head +} + +func (h *FactoryHelper) StartOutputAlphabetGameWithCorrectRoot(ctx context.Context, l2Node string, l2BlockNumber uint64, opts ...GameOpt) *OutputAlphabetGameHelper { + cfg := newGameCfg(opts...) + h.waitForBlock(l2Node, l2BlockNumber, cfg) output, err := h.system.RollupClient(l2Node).OutputAtBlock(ctx, l2BlockNumber) h.require.NoErrorf(err, "Failed to get output at block %v", l2BlockNumber) return h.StartOutputAlphabetGame(ctx, l2Node, l2BlockNumber, common.Hash(output.OutputRoot)) } -func (h *FactoryHelper) StartOutputAlphabetGame(ctx context.Context, l2Node string, l2BlockNumber uint64, rootClaim common.Hash) *OutputAlphabetGameHelper { - logger := testlog.Logger(h.t, log.LvlInfo).New("role", "OutputAlphabetGameHelper") +func (h *FactoryHelper) StartOutputAlphabetGame(ctx context.Context, l2Node string, l2BlockNumber uint64, rootClaim common.Hash, opts ...GameOpt) *OutputAlphabetGameHelper { + cfg := newGameCfg(opts...) + logger := testlog.Logger(h.t, log.LevelInfo).New("role", "OutputAlphabetGameHelper") rollupClient := h.system.RollupClient(l2Node) - extraData := h.createBisectionGameExtraData(l2Node, l2BlockNumber) + extraData := h.createBisectionGameExtraData(l2Node, l2BlockNumber, cfg) ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) defer cancel() @@ -178,20 +244,23 @@ func (h *FactoryHelper) StartOutputAlphabetGame(ctx context.Context, l2Node stri h.require.NoError(err, "create output bisection game") rcpt, err := wait.ForReceiptOK(ctx, h.client, tx.Hash()) h.require.NoError(err, "wait for create output bisection game receipt to be OK") - h.require.Len(rcpt.Logs, 1, "should have emitted a single DisputeGameCreated event") - createdEvent, err := h.factory.ParseDisputeGameCreated(*rcpt.Logs[0]) + h.require.Len(rcpt.Logs, 2, "should have emitted a single DisputeGameCreated event") + createdEvent, err := h.factory.ParseDisputeGameCreated(*rcpt.Logs[1]) h.require.NoError(err) game, err := bindings.NewFaultDisputeGame(createdEvent.DisputeProxy, h.client) h.require.NoError(err) - prestateBlock, err := game.GenesisBlockNumber(&bind.CallOpts{Context: ctx}) - h.require.NoError(err, "Failed to load genesis block number") - poststateBlock, err := game.L2BlockNumber(&bind.CallOpts{Context: ctx}) + callOpts := &bind.CallOpts{Context: ctx} + prestateBlock, err := game.StartingBlockNumber(callOpts) + h.require.NoError(err, "Failed to load starting block number") + poststateBlock, err := game.L2BlockNumber(callOpts) h.require.NoError(err, "Failed to load l2 block number") - splitDepth, err := game.SplitDepth(&bind.CallOpts{Context: ctx}) + splitDepth, err := game.SplitDepth(callOpts) h.require.NoError(err, "Failed to load split depth") - prestateProvider := outputs.NewPrestateProvider(ctx, logger, rollupClient, prestateBlock.Uint64()) - provider := outputs.NewTraceProviderFromInputs(logger, prestateProvider, rollupClient, faultTypes.Depth(splitDepth.Uint64()), prestateBlock.Uint64(), poststateBlock.Uint64()) + l1Head := h.getL1Head(ctx, game) + prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock.Uint64()) + + provider := outputs.NewTraceProvider(logger, prestateProvider, rollupClient, l1Head, faultTypes.Depth(splitDepth.Uint64()), prestateBlock.Uint64(), poststateBlock.Uint64()) return &OutputAlphabetGameHelper{ OutputGameHelper: OutputGameHelper{ @@ -208,18 +277,28 @@ func (h *FactoryHelper) StartOutputAlphabetGame(ctx context.Context, l2Node stri } } -func (h *FactoryHelper) createBisectionGameExtraData(l2Node string, l2BlockNumber uint64) []byte { - h.waitForBlockToBeSafe(l2Node, l2BlockNumber) +func (h *FactoryHelper) createBisectionGameExtraData(l2Node string, l2BlockNumber uint64, cfg *gameCfg) []byte { + h.waitForBlock(l2Node, l2BlockNumber, cfg) h.t.Logf("Creating game with l2 block number: %v", l2BlockNumber) extraData := make([]byte, 32) binary.BigEndian.PutUint64(extraData[24:], l2BlockNumber) return extraData } -func (h *FactoryHelper) waitForBlockToBeSafe(l2Node string, l2BlockNumber uint64) { +func (h *FactoryHelper) waitForBlock(l2Node string, l2BlockNumber uint64, cfg *gameCfg) { + if cfg.allowFuture { + // Proposing a block that doesn't exist yet, so don't perform any checks + return + } + l2Client := h.system.NodeClient(l2Node) - _, err := geth.WaitForBlockToBeSafe(new(big.Int).SetUint64(l2BlockNumber), l2Client, 1*time.Minute) - h.require.NoErrorf(err, "Block number %v did not become safe", l2BlockNumber) + if cfg.allowUnsafe { + _, err := geth.WaitForBlock(new(big.Int).SetUint64(l2BlockNumber), l2Client, 1*time.Minute) + h.require.NoErrorf(err, "Block number %v did not become unsafe", l2BlockNumber) + } else { + _, err := geth.WaitForBlockToBeSafe(new(big.Int).SetUint64(l2BlockNumber), l2Client, 1*time.Minute) + h.require.NoErrorf(err, "Block number %v did not become safe", l2BlockNumber) + } } func (h *FactoryHelper) StartChallenger(ctx context.Context, name string, options ...challenger.Option) *challenger.Helper { @@ -227,7 +306,7 @@ func (h *FactoryHelper) StartChallenger(ctx context.Context, name string, option challenger.WithFactoryAddress(h.factoryAddr), } opts = append(opts, options...) - c := challenger.NewChallenger(h.t, ctx, h.system.NodeEndpoint("l1"), name, opts...) + c := challenger.NewChallenger(h.t, ctx, h.system, name, opts...) h.t.Cleanup(func() { _ = c.Close() }) diff --git a/op-e2e/e2eutils/disputegame/output_alphabet_helper.go b/op-e2e/e2eutils/disputegame/output_alphabet_helper.go index 871c4e69349d..da99c40a8136 100644 --- a/op-e2e/e2eutils/disputegame/output_alphabet_helper.go +++ b/op-e2e/e2eutils/disputegame/output_alphabet_helper.go @@ -28,7 +28,7 @@ func (g *OutputAlphabetGameHelper) StartChallenger( challenger.WithGameAddress(g.addr), } opts = append(opts, options...) - c := challenger.NewChallenger(g.t, ctx, g.system.NodeEndpoint("l1"), name, opts...) + c := challenger.NewChallenger(g.t, ctx, g.system, name, opts...) g.t.Cleanup(func() { _ = c.Close() }) @@ -36,16 +36,17 @@ func (g *OutputAlphabetGameHelper) StartChallenger( } func (g *OutputAlphabetGameHelper) CreateHonestActor(ctx context.Context, l2Node string) *OutputHonestHelper { - logger := testlog.Logger(g.t, log.LvlInfo).New("role", "HonestHelper", "game", g.addr) + logger := testlog.Logger(g.t, log.LevelInfo).New("role", "HonestHelper", "game", g.addr) caller := batching.NewMultiCaller(g.system.NodeClient("l1").Client(), batching.DefaultBatchSize) contract, err := contracts.NewFaultDisputeGameContract(g.addr, caller) g.require.NoError(err, "Failed to create game contact") prestateBlock, poststateBlock, err := contract.GetBlockRange(ctx) g.require.NoError(err, "Get block range") splitDepth := g.SplitDepth(ctx) + l1Head := g.getL1Head(ctx) rollupClient := g.system.RollupClient(l2Node) - prestateProvider := outputs.NewPrestateProvider(ctx, logger, rollupClient, prestateBlock) - correctTrace, err := outputs.NewOutputAlphabetTraceAccessor(logger, metrics.NoopMetrics, prestateProvider, rollupClient, splitDepth, prestateBlock, poststateBlock) + prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock) + correctTrace, err := outputs.NewOutputAlphabetTraceAccessor(logger, metrics.NoopMetrics, prestateProvider, rollupClient, l1Head, splitDepth, prestateBlock, poststateBlock) g.require.NoError(err, "Create trace accessor") return &OutputHonestHelper{ t: g.t, diff --git a/op-e2e/e2eutils/disputegame/output_cannon_helper.go b/op-e2e/e2eutils/disputegame/output_cannon_helper.go index 7060872f4dd8..6d5d73f9e491 100644 --- a/op-e2e/e2eutils/disputegame/output_cannon_helper.go +++ b/op-e2e/e2eutils/disputegame/output_cannon_helper.go @@ -2,14 +2,30 @@ package disputegame import ( "context" + "crypto/ecdsa" + "errors" + "io" + "math/big" "path/filepath" + "time" + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/outputs" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/split" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + preimage "github.com/ethereum-optimism/optimism/op-preimage" "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) @@ -31,7 +47,7 @@ func (g *OutputCannonGameHelper) StartChallenger( challenger.WithGameAddress(g.addr), } opts = append(opts, options...) - c := challenger.NewChallenger(g.t, ctx, g.system.NodeEndpoint("l1"), name, opts...) + c := challenger.NewChallenger(g.t, ctx, g.system, name, opts...) g.t.Cleanup(func() { _ = c.Close() }) @@ -39,15 +55,11 @@ func (g *OutputCannonGameHelper) StartChallenger( } func (g *OutputCannonGameHelper) CreateHonestActor(ctx context.Context, l2Node string, options ...challenger.Option) *OutputHonestHelper { - opts := []challenger.Option{ - challenger.WithCannon(g.t, g.system.RollupCfg(), g.system.L2Genesis(), g.system.RollupEndpoint(l2Node), g.system.NodeEndpoint(l2Node)), - challenger.WithFactoryAddress(g.factoryAddr), - challenger.WithGameAddress(g.addr), - } + opts := g.defaultChallengerOptions(l2Node) opts = append(opts, options...) - cfg := challenger.NewChallengerConfig(g.t, g.system.NodeEndpoint("l1"), opts...) + cfg := challenger.NewChallengerConfig(g.t, g.system, opts...) - logger := testlog.Logger(g.t, log.LvlInfo).New("role", "HonestHelper", "game", g.addr) + logger := testlog.Logger(g.t, log.LevelInfo).New("role", "HonestHelper", "game", g.addr) l2Client := g.system.NodeClient(l2Node) caller := batching.NewMultiCaller(g.system.NodeClient("l1").Client(), batching.DefaultBatchSize) contract, err := contracts.NewFaultDisputeGameContract(g.addr, caller) @@ -58,9 +70,10 @@ func (g *OutputCannonGameHelper) CreateHonestActor(ctx context.Context, l2Node s dir := filepath.Join(cfg.Datadir, "honest") splitDepth := g.SplitDepth(ctx) rollupClient := g.system.RollupClient(l2Node) - prestateProvider := outputs.NewPrestateProvider(ctx, logger, rollupClient, prestateBlock) + prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock) + l1Head := g.getL1Head(ctx) accessor, err := outputs.NewOutputCannonTraceAccessor( - logger, metrics.NoopMetrics, cfg, l2Client, contract, prestateProvider, rollupClient, dir, splitDepth, prestateBlock, poststateBlock) + logger, metrics.NoopMetrics, cfg, l2Client, prestateProvider, rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock) g.require.NoError(err, "Failed to create output cannon trace accessor") return &OutputHonestHelper{ t: g.t, @@ -70,3 +83,254 @@ func (g *OutputCannonGameHelper) CreateHonestActor(ctx context.Context, l2Node s correctTrace: accessor, } } + +type PreimageLoadCheck func(types.TraceProvider, uint64) error + +func (g *OutputCannonGameHelper) CreateStepLargePreimageLoadCheck(ctx context.Context, sender common.Address) PreimageLoadCheck { + return func(provider types.TraceProvider, targetTraceIndex uint64) error { + // Fetch the challenge period + challengePeriod := g.ChallengePeriod(ctx) + + // Get the preimage data + execDepth := g.ExecDepth(ctx) + _, _, preimageData, err := provider.GetStepData(ctx, types.NewPosition(execDepth, big.NewInt(int64(targetTraceIndex)))) + g.require.NoError(err) + + // Wait until the challenge period has started by checking until the challenge + // period start time is not zero by calling the ChallengePeriodStartTime method + g.WaitForChallengePeriodStart(ctx, sender, preimageData) + + challengePeriodStart := g.ChallengePeriodStartTime(ctx, sender, preimageData) + challengePeriodEnd := challengePeriodStart + challengePeriod + + // Time travel past the challenge period. + g.system.AdvanceTime(time.Duration(challengePeriod) * time.Second) + g.require.NoError(wait.ForBlockWithTimestamp(ctx, g.system.NodeClient("l1"), challengePeriodEnd)) + + // Assert that the preimage was indeed loaded by an honest challenger + g.waitForPreimageInOracle(ctx, preimageData) + return nil + } +} + +func (g *OutputCannonGameHelper) CreateStepPreimageLoadCheck(ctx context.Context) PreimageLoadCheck { + return func(provider types.TraceProvider, targetTraceIndex uint64) error { + execDepth := g.ExecDepth(ctx) + _, _, preimageData, err := provider.GetStepData(ctx, types.NewPosition(execDepth, big.NewInt(int64(targetTraceIndex)))) + g.require.NoError(err) + g.waitForPreimageInOracle(ctx, preimageData) + return nil + } +} + +// ChallengeToPreimageLoad challenges the supplied execution root claim by inducing a step that requires a preimage to be loaded +// It does this by: +// 1. Identifying the first state transition that loads a global preimage +// 2. Descending the execution game tree to reach the step that loads the preimage +// 3. Asserting that the preimage was indeed loaded by an honest challenger (assuming the preimage is not preloaded) +// This expects an odd execution game depth in order for the honest challenger to step on our leaf claim +func (g *OutputCannonGameHelper) ChallengeToPreimageLoad(ctx context.Context, outputRootClaim *ClaimHelper, challengerKey *ecdsa.PrivateKey, preimage cannon.PreimageOpt, preimageCheck PreimageLoadCheck, preloadPreimage bool) { + // Identifying the first state transition that loads a global preimage + provider, _ := g.createCannonTraceProvider(ctx, "sequencer", outputRootClaim, challenger.WithPrivKey(challengerKey)) + targetTraceIndex, err := provider.FindStep(ctx, 0, preimage) + g.require.NoError(err) + + splitDepth := g.SplitDepth(ctx) + execDepth := g.ExecDepth(ctx) + g.require.NotEqual(outputRootClaim.position.TraceIndex(execDepth).Uint64(), targetTraceIndex, "cannot move to defend a terminal trace index") + g.require.EqualValues(splitDepth+1, outputRootClaim.Depth(), "supplied claim must be the root of an execution game") + g.require.EqualValues(execDepth%2, 1, "execution game depth must be odd") // since we're challenging the execution root claim + + if preloadPreimage { + _, _, preimageData, err := provider.GetStepData(ctx, types.NewPosition(execDepth, big.NewInt(int64(targetTraceIndex)))) + g.require.NoError(err) + g.uploadPreimage(ctx, preimageData, challengerKey) + g.waitForPreimageInOracle(ctx, preimageData) + } + + // Descending the execution game tree to reach the step that loads the preimage + bisectTraceIndex := func(claim *ClaimHelper) *ClaimHelper { + execClaimPosition, err := claim.position.RelativeToAncestorAtDepth(splitDepth + 1) + g.require.NoError(err) + + claimTraceIndex := execClaimPosition.TraceIndex(execDepth).Uint64() + g.t.Logf("Bisecting: Into targetTraceIndex %v: claimIndex=%v at depth=%v. claimPosition=%v execClaimPosition=%v claimTraceIndex=%v", + targetTraceIndex, claim.index, claim.Depth(), claim.position, execClaimPosition, claimTraceIndex) + + // We always want to position ourselves such that the challenger generates proofs for the targetTraceIndex as prestate + if execClaimPosition.Depth() == execDepth-1 { + if execClaimPosition.TraceIndex(execDepth).Uint64() == targetTraceIndex { + newPosition := execClaimPosition.Attack() + correct, err := provider.Get(ctx, newPosition) + g.require.NoError(err) + g.t.Logf("Bisecting: Attack correctly for step at newPosition=%v execIndexAtDepth=%v", newPosition, newPosition.TraceIndex(execDepth)) + return claim.Attack(ctx, correct) + } else if execClaimPosition.TraceIndex(execDepth).Uint64() > targetTraceIndex { + g.t.Logf("Bisecting: Attack incorrectly for step") + return claim.Attack(ctx, common.Hash{0xdd}) + } else if execClaimPosition.TraceIndex(execDepth).Uint64()+1 == targetTraceIndex { + g.t.Logf("Bisecting: Defend incorrectly for step") + return claim.Defend(ctx, common.Hash{0xcc}) + } else { + newPosition := execClaimPosition.Defend() + correct, err := provider.Get(ctx, newPosition) + g.require.NoError(err) + g.t.Logf("Bisecting: Defend correctly for step at newPosition=%v execIndexAtDepth=%v", newPosition, newPosition.TraceIndex(execDepth)) + return claim.Defend(ctx, correct) + } + } + + // Attack or Defend depending on whether the claim we're responding to is to the left or right of the trace index + // Induce the honest challenger to attack or defend depending on whether our new position will be to the left or right of the trace index + if execClaimPosition.TraceIndex(execDepth).Uint64() < targetTraceIndex && claim.Depth() != splitDepth+1 { + newPosition := execClaimPosition.Defend() + if newPosition.TraceIndex(execDepth).Uint64() < targetTraceIndex { + g.t.Logf("Bisecting: Defend correct. newPosition=%v execIndexAtDepth=%v", newPosition, newPosition.TraceIndex(execDepth)) + correct, err := provider.Get(ctx, newPosition) + g.require.NoError(err) + return claim.Defend(ctx, correct) + } else { + g.t.Logf("Bisecting: Defend incorrect. newPosition=%v execIndexAtDepth=%v", newPosition, newPosition.TraceIndex(execDepth)) + return claim.Defend(ctx, common.Hash{0xaa}) + } + } else { + newPosition := execClaimPosition.Attack() + if newPosition.TraceIndex(execDepth).Uint64() < targetTraceIndex { + g.t.Logf("Bisecting: Attack correct. newPosition=%v execIndexAtDepth=%v", newPosition, newPosition.TraceIndex(execDepth)) + correct, err := provider.Get(ctx, newPosition) + g.require.NoError(err) + return claim.Attack(ctx, correct) + } else { + g.t.Logf("Bisecting: Attack incorrect. newPosition=%v execIndexAtDepth=%v", newPosition, newPosition.TraceIndex(execDepth)) + return claim.Attack(ctx, common.Hash{0xbb}) + } + } + } + + g.LogGameData(ctx) + // Initial bisect to put us on defense + mover := bisectTraceIndex(outputRootClaim) + leafClaim := g.DefendClaim(ctx, mover, bisectTraceIndex, WithoutWaitingForStep()) + + // Validate that the preimage was loaded correctly + g.require.NoError(preimageCheck(provider, targetTraceIndex)) + + // Now the preimage is available wait for the step call to succeed. + leafClaim.WaitForCountered(ctx) + g.LogGameData(ctx) +} + +func (g *OutputCannonGameHelper) VerifyPreimage(ctx context.Context, outputRootClaim *ClaimHelper, preimageKey preimage.Key) { + execDepth := g.ExecDepth(ctx) + + // Identifying the first state transition that loads a global preimage + provider, localContext := g.createCannonTraceProvider(ctx, "sequencer", outputRootClaim, challenger.WithPrivKey(deployer.TestKey)) + start := uint64(0) + found := false + for offset := uint32(0); ; offset += 4 { + preimageOpt := cannon.PreimageLoad(preimageKey, offset) + g.t.Logf("Searching for step with key %x and offset %v", preimageKey.PreimageKey(), offset) + targetTraceIndex, err := provider.FindStep(ctx, start, preimageOpt) + if errors.Is(err, io.EOF) { + // Did not find any more reads + g.require.True(found, "Should have found at least one preimage read") + g.t.Logf("Searching for step with key %x and offset %v did not find another read", preimageKey.PreimageKey(), offset) + return + } + g.require.NoError(err, "Failed to find step that loads requested preimage") + start = targetTraceIndex + found = true + + g.t.Logf("Target trace index: %v", targetTraceIndex) + pos := types.NewPosition(execDepth, new(big.Int).SetUint64(targetTraceIndex)) + g.require.Equal(targetTraceIndex, pos.TraceIndex(execDepth).Uint64()) + + prestate, proof, oracleData, err := provider.GetStepData(ctx, pos) + g.require.NoError(err, "Failed to get step data") + g.require.NotNil(oracleData, "Should have had required preimage oracle data") + g.require.Equal(common.Hash(preimageKey.PreimageKey()).Bytes(), oracleData.OracleKey, "Must have correct preimage key") + + tx, err := g.game.AddLocalData(g.opts, + oracleData.GetIdent(), + big.NewInt(outputRootClaim.index), + new(big.Int).SetUint64(uint64(oracleData.OracleOffset))) + g.require.NoError(err) + _, err = wait.ForReceiptOK(ctx, g.client, tx.Hash()) + g.require.NoError(err) + + expectedPostState, err := provider.Get(ctx, pos) + g.require.NoError(err, "Failed to get expected post state") + + callOpts := &bind.CallOpts{Context: ctx} + vmAddr, err := g.game.Vm(callOpts) + g.require.NoError(err, "Failed to get VM address") + + abi, err := bindings.MIPSMetaData.GetAbi() + g.require.NoError(err, "Failed to load MIPS ABI") + caller := batching.NewMultiCaller(g.client.Client(), batching.DefaultBatchSize) + result, err := caller.SingleCall(ctx, rpcblock.Latest, &batching.ContractCall{ + Abi: abi, + Addr: vmAddr, + Method: "step", + Args: []interface{}{ + prestate, proof, localContext, + }, + From: g.addr, + }) + g.require.NoError(err, "Failed to call step") + actualPostState := result.GetBytes32(0) + g.require.Equal(expectedPostState, common.Hash(actualPostState)) + } +} + +func (g *OutputCannonGameHelper) createCannonTraceProvider(ctx context.Context, l2Node string, outputRootClaim *ClaimHelper, options ...challenger.Option) (*cannon.CannonTraceProviderForTest, common.Hash) { + splitDepth := g.SplitDepth(ctx) + g.require.EqualValues(outputRootClaim.Depth(), splitDepth+1, "outputRootClaim must be the root of an execution game") + + logger := testlog.Logger(g.t, log.LevelInfo).New("role", "CannonTraceProvider", "game", g.addr) + opt := g.defaultChallengerOptions(l2Node) + opt = append(opt, options...) + cfg := challenger.NewChallengerConfig(g.t, g.system, opt...) + + caller := batching.NewMultiCaller(g.system.NodeClient("l1").Client(), batching.DefaultBatchSize) + l2Client := g.system.NodeClient(l2Node) + contract, err := contracts.NewFaultDisputeGameContract(g.addr, caller) + g.require.NoError(err, "Failed to create game contact") + + prestateBlock, poststateBlock, err := contract.GetBlockRange(ctx) + g.require.NoError(err, "Failed to load block range") + rollupClient := g.system.RollupClient(l2Node) + prestateProvider := outputs.NewPrestateProvider(rollupClient, prestateBlock) + l1Head := g.getL1Head(ctx) + outputProvider := outputs.NewTraceProvider(logger, prestateProvider, rollupClient, l1Head, splitDepth, prestateBlock, poststateBlock) + + var localContext common.Hash + selector := split.NewSplitProviderSelector(outputProvider, splitDepth, func(ctx context.Context, depth types.Depth, pre types.Claim, post types.Claim) (types.TraceProvider, error) { + agreed, disputed, err := outputs.FetchProposals(ctx, outputProvider, pre, post) + g.require.NoError(err) + g.t.Logf("Using trace between blocks %v and %v\n", agreed.L2BlockNumber, disputed.L2BlockNumber) + localInputs, err := cannon.FetchLocalInputsFromProposals(ctx, l1Head.Hash, l2Client, agreed, disputed) + g.require.NoError(err, "Failed to fetch local inputs") + localContext = outputs.CreateLocalContext(pre, post) + dir := filepath.Join(cfg.Datadir, "cannon-trace") + subdir := filepath.Join(dir, localContext.Hex()) + return cannon.NewTraceProviderForTest(logger, metrics.NoopMetrics, cfg, localInputs, subdir, g.MaxDepth(ctx)-splitDepth-1), nil + }) + + claims, err := contract.GetAllClaims(ctx, rpcblock.Latest) + g.require.NoError(err) + game := types.NewGameState(claims, g.MaxDepth(ctx)) + + provider, err := selector(ctx, game, game.Claims()[outputRootClaim.parentIndex], outputRootClaim.position) + g.require.NoError(err) + translatingProvider := provider.(*trace.TranslatingProvider) + return translatingProvider.Original().(*cannon.CannonTraceProviderForTest), localContext +} + +func (g *OutputCannonGameHelper) defaultChallengerOptions(l2Node string) []challenger.Option { + return []challenger.Option{ + challenger.WithCannon(g.t, g.system.RollupCfg(), g.system.L2Genesis(), g.system.RollupEndpoint(l2Node), g.system.NodeEndpoint(l2Node)), + challenger.WithFactoryAddress(g.factoryAddr), + challenger.WithGameAddress(g.addr), + } +} diff --git a/op-e2e/e2eutils/disputegame/output_game_helper.go b/op-e2e/e2eutils/disputegame/output_game_helper.go index 3f257d9cd8ba..42ee42c8f3fc 100644 --- a/op-e2e/e2eutils/disputegame/output_game_helper.go +++ b/op-e2e/e2eutils/disputegame/output_game_helper.go @@ -2,15 +2,23 @@ package disputegame import ( "context" + "crypto/ecdsa" "fmt" "math/big" "testing" "time" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/preimages" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/outputs" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + preimage "github.com/ethereum-optimism/optimism/op-preimage" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" gethtypes "github.com/ethereum/go-ethereum/core/types" @@ -32,6 +40,33 @@ type OutputGameHelper struct { system DisputeSystem } +type moveCfg struct { + opts *bind.TransactOpts + ignoreDupes bool +} + +type MoveOpt interface { + Apply(cfg *moveCfg) +} + +type moveOptFn func(c *moveCfg) + +func (f moveOptFn) Apply(c *moveCfg) { + f(c) +} + +func WithTransactOpts(opts *bind.TransactOpts) MoveOpt { + return moveOptFn(func(c *moveCfg) { + c.opts = opts + }) +} + +func WithIgnoreDuplicates() MoveOpt { + return moveOptFn(func(c *moveCfg) { + c.ignoreDupes = true + }) +} + func (g *OutputGameHelper) Addr() common.Address { return g.addr } @@ -42,22 +77,30 @@ func (g *OutputGameHelper) SplitDepth(ctx context.Context) types.Depth { return types.Depth(splitDepth.Uint64()) } +func (g *OutputGameHelper) ExecDepth(ctx context.Context) types.Depth { + return g.MaxDepth(ctx) - g.SplitDepth(ctx) - 1 +} + func (g *OutputGameHelper) L2BlockNum(ctx context.Context) uint64 { blockNum, err := g.game.L2BlockNumber(&bind.CallOpts{Context: ctx}) g.require.NoError(err, "failed to load l2 block number") return blockNum.Uint64() } -func (g *OutputGameHelper) GenesisBlockNum(ctx context.Context) uint64 { - blockNum, err := g.game.GenesisBlockNumber(&bind.CallOpts{Context: ctx}) - g.require.NoError(err, "failed to load genesis block number") +func (g *OutputGameHelper) StartingBlockNum(ctx context.Context) uint64 { + blockNum, err := g.game.StartingBlockNumber(&bind.CallOpts{Context: ctx}) + g.require.NoError(err, "failed to load starting block number") return blockNum.Uint64() } -// DisputeLastBlock posts claims from both the honest and dishonest actor to progress the output root part of the game +func (g *OutputGameHelper) DisputeLastBlock(ctx context.Context) *ClaimHelper { + return g.DisputeBlock(ctx, g.L2BlockNum(ctx)) +} + +// DisputeBlock posts claims from both the honest and dishonest actor to progress the output root part of the game // through to the split depth and the claims are setup such that the last block in the game range is the block // to execute cannon on. ie the first block the honest and dishonest actors disagree about is the l2 block of the game. -func (g *OutputGameHelper) DisputeLastBlock(ctx context.Context) *ClaimHelper { +func (g *OutputGameHelper) DisputeBlock(ctx context.Context, disputeBlockNum uint64) *ClaimHelper { dishonestValue := g.GetClaimValue(ctx, 0) correctRootClaim := g.correctOutputRoot(ctx, types.NewPositionFromGIndex(big.NewInt(1))) rootIsValid := dishonestValue == correctRootClaim @@ -66,10 +109,9 @@ func (g *OutputGameHelper) DisputeLastBlock(ctx context.Context) *ClaimHelper { // Otherwise, the honest challenger will defend our counter and ruin everything. dishonestValue = common.Hash{0xff, 0xff, 0xff} } - disputeBlockNum := g.L2BlockNum(ctx) pos := types.NewPositionFromGIndex(big.NewInt(1)) getClaimValue := func(parentClaim *ClaimHelper, claimPos types.Position) common.Hash { - claimBlockNum, err := g.correctOutputProvider.BlockNumber(claimPos) + claimBlockNum, err := g.correctOutputProvider.ClaimedBlockNumber(claimPos) g.require.NoError(err, "failed to calculate claim block number") if claimBlockNum < disputeBlockNum { // Use the correct output root for all claims prior to the dispute block number @@ -87,7 +129,7 @@ func (g *OutputGameHelper) DisputeLastBlock(ctx context.Context) *ClaimHelper { claim := g.RootClaim(ctx) for !claim.IsOutputRootLeaf(ctx) { - parentClaimBlockNum, err := g.correctOutputProvider.BlockNumber(pos) + parentClaimBlockNum, err := g.correctOutputProvider.ClaimedBlockNumber(pos) g.require.NoError(err, "failed to calculate parent claim block number") if parentClaimBlockNum >= disputeBlockNum { pos = pos.Attack() @@ -124,6 +166,50 @@ func (g *OutputGameHelper) GameDuration(ctx context.Context) time.Duration { return time.Duration(duration) * time.Second } +func (g *OutputGameHelper) WaitForNoAvailableCredit(ctx context.Context, addr common.Address) { + timedCtx, cancel := context.WithTimeout(ctx, defaultTimeout) + defer cancel() + err := wait.For(timedCtx, time.Second, func() (bool, error) { + bal, err := g.game.Credit(&bind.CallOpts{Context: timedCtx}, addr) + if err != nil { + return false, err + } + g.t.Log("Waiting for zero available credit", "current", bal, "addr", addr) + return bal.Cmp(big.NewInt(0)) == 0, nil + }) + if err != nil { + g.LogGameData(ctx) + g.require.NoError(err, "Failed to wait for zero available credit") + } +} + +func (g *OutputGameHelper) AvailableCredit(ctx context.Context, addr common.Address) *big.Int { + credit, err := g.game.Credit(&bind.CallOpts{Context: ctx}, addr) + g.require.NoErrorf(err, "Failed to fetch available credit for %v", addr) + return credit +} + +func (g *OutputGameHelper) CreditUnlockDuration(ctx context.Context) time.Duration { + weth, err := g.game.Weth(&bind.CallOpts{Context: ctx}) + g.require.NoError(err, "Failed to get WETH contract") + contract, err := bindings.NewDelayedWETH(weth, g.client) + g.require.NoError(err) + period, err := contract.Delay(&bind.CallOpts{Context: ctx}) + g.require.NoError(err, "Failed to get WETH unlock period") + float, _ := period.Float64() + return time.Duration(float) * time.Second +} + +func (g *OutputGameHelper) WethBalance(ctx context.Context, addr common.Address) *big.Int { + weth, err := g.game.Weth(&bind.CallOpts{Context: ctx}) + g.require.NoError(err, "Failed to get WETH contract") + contract, err := bindings.NewDelayedWETH(weth, g.client) + g.require.NoError(err) + balance, err := contract.BalanceOf(&bind.CallOpts{Context: ctx}, addr) + g.require.NoError(err, "Failed to get WETH balance") + return balance +} + // WaitForClaimCount waits until there are at least count claims in the game. // This does not check that the number of claims is exactly the specified count to avoid intermittent failures // where a challenger posts an additional claim before this method sees the number of claims it was waiting for. @@ -160,8 +246,8 @@ func (g *OutputGameHelper) MaxDepth(ctx context.Context) types.Depth { return types.Depth(depth.Uint64()) } -func (g *OutputGameHelper) waitForClaim(ctx context.Context, errorMsg string, predicate func(claimIdx int64, claim ContractClaim) bool) (int64, ContractClaim) { - timedCtx, cancel := context.WithTimeout(ctx, defaultTimeout) +func (g *OutputGameHelper) waitForClaim(ctx context.Context, timeout time.Duration, errorMsg string, predicate func(claimIdx int64, claim ContractClaim) bool) (int64, ContractClaim) { + timedCtx, cancel := context.WithTimeout(ctx, timeout) defer cancel() var matchedClaim ContractClaim var matchClaimIdx int64 @@ -243,6 +329,7 @@ func (g *OutputGameHelper) getClaim(ctx context.Context, claimIdx int64) Contrac func (g *OutputGameHelper) WaitForClaimAtDepth(ctx context.Context, depth types.Depth) { g.waitForClaim( ctx, + defaultTimeout, fmt.Sprintf("Could not find claim depth %v", depth), func(_ int64, claim ContractClaim) bool { pos := types.NewPositionFromGIndex(claim.Position) @@ -254,6 +341,7 @@ func (g *OutputGameHelper) WaitForClaimAtMaxDepth(ctx context.Context, countered maxDepth := g.MaxDepth(ctx) g.waitForClaim( ctx, + defaultTimeout, fmt.Sprintf("Could not find claim depth %v with countered=%v", maxDepth, countered), func(_ int64, claim ContractClaim) bool { pos := types.NewPositionFromGIndex(claim.Position) @@ -348,11 +436,28 @@ type Mover func(parent *ClaimHelper) *ClaimHelper // Stepper is a function that attempts to perform a step against the claim at parentClaimIdx type Stepper func(parentClaimIdx int64) +type defendClaimCfg struct { + skipWaitingForStep bool +} + +type DefendClaimOpt func(cfg *defendClaimCfg) + +func WithoutWaitingForStep() DefendClaimOpt { + return func(cfg *defendClaimCfg) { + cfg.skipWaitingForStep = true + } +} + // DefendClaim uses the supplied Mover to perform moves in an attempt to defend the supplied claim. // It is assumed that the specified claim is invalid and that an honest op-challenger is already running. // When the game has reached the maximum depth it waits for the honest challenger to counter the leaf claim with step. -func (g *OutputGameHelper) DefendClaim(ctx context.Context, claim *ClaimHelper, performMove Mover) { +// Returns the final leaf claim +func (g *OutputGameHelper) DefendClaim(ctx context.Context, claim *ClaimHelper, performMove Mover, opts ...DefendClaimOpt) *ClaimHelper { g.t.Logf("Defending claim %v at depth %v", claim.index, claim.Depth()) + cfg := &defendClaimCfg{} + for _, opt := range opts { + opt(cfg) + } for !claim.IsMaxDepth(ctx) { g.LogGameData(ctx) // Wait for the challenger to counter @@ -363,7 +468,10 @@ func (g *OutputGameHelper) DefendClaim(ctx context.Context, claim *ClaimHelper, claim = performMove(claim) } - claim.WaitForCountered(ctx) + if !cfg.skipWaitingForStep { + claim.WaitForCountered(ctx) + } + return claim } // ChallengeClaim uses the supplied functions to perform moves and steps in an attempt to challenge the supplied claim. @@ -414,28 +522,86 @@ func (g *OutputGameHelper) waitForNewClaim(ctx context.Context, checkPoint int64 return newClaimLen, err } -func (g *OutputGameHelper) Attack(ctx context.Context, claimIdx int64, claim common.Hash) { +func (g *OutputGameHelper) moveCfg(opts ...MoveOpt) *moveCfg { + cfg := &moveCfg{ + opts: g.opts, + } + for _, opt := range opts { + opt.Apply(cfg) + } + return cfg +} + +func (g *OutputGameHelper) Attack(ctx context.Context, claimIdx int64, claim common.Hash, opts ...MoveOpt) { g.t.Logf("Attacking claim %v with value %v", claimIdx, claim) - tx, err := g.game.Attack(g.opts, big.NewInt(claimIdx), claim) + cfg := g.moveCfg(opts...) + + claimData, err := g.game.ClaimData(&bind.CallOpts{Context: ctx}, big.NewInt(claimIdx)) + g.require.NoError(err, "Failed to get claim data") + pos := types.NewPositionFromGIndex(claimData.Position) + attackPos := pos.Attack() + transactOpts := g.makeBondedTransactOpts(ctx, pos.Attack().ToGIndex(), cfg.opts) + + err = g.sendMove(ctx, func() (*gethtypes.Transaction, error) { + return g.game.Attack(transactOpts, big.NewInt(claimIdx), claim) + }) if err != nil { - g.require.NoErrorf(err, "Attack transaction did not send. Game state: \n%v", g.gameData(ctx)) + if cfg.ignoreDupes && g.hasClaim(ctx, claimIdx, attackPos, claim) { + return + } + g.require.NoErrorf(err, "Defend transaction failed. Game state: \n%v", g.gameData(ctx)) } - _, err = wait.ForReceiptOK(ctx, g.client, tx.Hash()) +} + +func (g *OutputGameHelper) Defend(ctx context.Context, claimIdx int64, claim common.Hash, opts ...MoveOpt) { + g.t.Logf("Defending claim %v with value %v", claimIdx, claim) + cfg := g.moveCfg(opts...) + + claimData, err := g.game.ClaimData(&bind.CallOpts{Context: ctx}, big.NewInt(claimIdx)) + g.require.NoError(err, "Failed to get claim data") + pos := types.NewPositionFromGIndex(claimData.Position) + defendPos := pos.Defend() + transactOpts := g.makeBondedTransactOpts(ctx, defendPos.ToGIndex(), cfg.opts) + + err = g.sendMove(ctx, func() (*gethtypes.Transaction, error) { + return g.game.Defend(transactOpts, big.NewInt(claimIdx), claim) + }) if err != nil { - g.require.NoErrorf(err, "Attack transaction was not OK. Game state: \n%v", g.gameData(ctx)) + if cfg.ignoreDupes && g.hasClaim(ctx, claimIdx, defendPos, claim) { + return + } + g.require.NoErrorf(err, "Defend transaction failed. Game state: \n%v", g.gameData(ctx)) } } -func (g *OutputGameHelper) Defend(ctx context.Context, claimIdx int64, claim common.Hash) { - g.t.Logf("Defending claim %v with value %v", claimIdx, claim) - tx, err := g.game.Defend(g.opts, big.NewInt(claimIdx), claim) +func (g *OutputGameHelper) hasClaim(ctx context.Context, parentIdx int64, pos types.Position, value common.Hash) bool { + claims := g.getAllClaims(ctx) + for _, claim := range claims { + if int64(claim.ParentIndex) == parentIdx && claim.Position.Cmp(pos.ToGIndex()) == 0 && claim.Claim == value { + return true + } + } + return false +} + +func (g *OutputGameHelper) sendMove(ctx context.Context, send func() (*gethtypes.Transaction, error)) error { + tx, err := send() if err != nil { - g.require.NoErrorf(err, "Defend transaction did not send. Game state: \n%v", g.gameData(ctx)) + return fmt.Errorf("transaction did not send: %w", err) } _, err = wait.ForReceiptOK(ctx, g.client, tx.Hash()) if err != nil { - g.require.NoErrorf(err, "Defend transaction was not OK. Game state: \n%v", g.gameData(ctx)) + return fmt.Errorf("transaction was not ok: %w", err) } + return nil +} + +func (g *OutputGameHelper) makeBondedTransactOpts(ctx context.Context, pos *big.Int, opts *bind.TransactOpts) *bind.TransactOpts { + bopts := *opts + bond, err := g.game.GetRequiredBond(&bind.CallOpts{Context: ctx}, pos) + g.require.NoError(err, "Failed to get required bond") + bopts.Value = bond + return &bopts } type ErrWithData interface { @@ -459,6 +625,89 @@ func (g *OutputGameHelper) ResolveClaim(ctx context.Context, claimIdx int64) { g.require.NoError(err, "ResolveClaim transaction was not OK") } +// ChallengePeriod returns the challenge period fetched from the PreimageOracle contract. +// The returned uint64 value is the number of seconds for the challenge period. +func (g *OutputGameHelper) ChallengePeriod(ctx context.Context) uint64 { + oracle := g.oracle(ctx) + period, err := oracle.ChallengePeriod(ctx) + g.require.NoError(err, "Failed to get challenge period") + return period +} + +// WaitForChallengePeriodStart waits for the challenge period to start for a given large preimage claim. +func (g *OutputGameHelper) WaitForChallengePeriodStart(ctx context.Context, sender common.Address, data *types.PreimageOracleData) { + timedCtx, cancel := context.WithTimeout(ctx, defaultTimeout) + defer cancel() + err := wait.For(timedCtx, time.Second, func() (bool, error) { + ctx, cancel := context.WithTimeout(timedCtx, 30*time.Second) + defer cancel() + timestamp := g.ChallengePeriodStartTime(ctx, sender, data) + g.t.Log("Waiting for challenge period start", "timestamp", timestamp, "key", data.OracleKey, "game", g.addr) + return timestamp > 0, nil + }) + if err != nil { + g.LogGameData(ctx) + g.require.NoErrorf(err, "Failed to get challenge start period for preimage data %v", data) + } +} + +// ChallengePeriodStartTime returns the start time of the challenge period for a given large preimage claim. +// If the returned start time is 0, the challenge period has not started. +func (g *OutputGameHelper) ChallengePeriodStartTime(ctx context.Context, sender common.Address, data *types.PreimageOracleData) uint64 { + oracle := g.oracle(ctx) + uuid := preimages.NewUUID(sender, data) + metadata, err := oracle.GetProposalMetadata(ctx, rpcblock.Latest, keccakTypes.LargePreimageIdent{ + Claimant: sender, + UUID: uuid, + }) + g.require.NoError(err, "Failed to get proposal metadata") + if len(metadata) == 0 { + return 0 + } + return metadata[0].Timestamp +} + +func (g *OutputGameHelper) waitForPreimageInOracle(ctx context.Context, data *types.PreimageOracleData) { + timedCtx, cancel := context.WithTimeout(ctx, defaultTimeout) + defer cancel() + oracle := g.oracle(ctx) + err := wait.For(timedCtx, time.Second, func() (bool, error) { + g.t.Logf("Waiting for preimage (%v) to be present in oracle", common.Bytes2Hex(data.OracleKey)) + return oracle.GlobalDataExists(ctx, data) + }) + g.require.NoErrorf(err, "Did not find preimage (%v) in oracle", common.Bytes2Hex(data.OracleKey)) +} + +func (g *OutputGameHelper) uploadPreimage(ctx context.Context, data *types.PreimageOracleData, privateKey *ecdsa.PrivateKey) { + oracle := g.oracle(ctx) + boundOracle, err := bindings.NewPreimageOracle(oracle.Addr(), g.client) + g.require.NoError(err) + var tx *gethtypes.Transaction + switch data.OracleKey[0] { + case byte(preimage.PrecompileKeyType): + tx, err = boundOracle.LoadPrecompilePreimagePart( + g.opts, + new(big.Int).SetUint64(uint64(data.OracleOffset)), + data.GetPrecompileAddress(), + data.GetPrecompileInput(), + ) + default: + tx, err = boundOracle.LoadKeccak256PreimagePart(g.opts, new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize()) + } + g.require.NoError(err, "Failed to load preimage part") + _, err = wait.ForReceiptOK(ctx, g.client, tx.Hash()) + g.require.NoError(err) +} + +func (g *OutputGameHelper) oracle(ctx context.Context) *contracts.PreimageOracleContract { + caller := batching.NewMultiCaller(g.system.NodeClient("l1").Client(), batching.DefaultBatchSize) + contract, err := contracts.NewFaultDisputeGameContract(g.addr, caller) + g.require.NoError(err, "Failed to create game contract") + oracle, err := contract.GetOracle(ctx) + g.require.NoError(err, "Failed to create oracle contract") + return oracle +} + func (g *OutputGameHelper) gameData(ctx context.Context) string { opts := &bind.CallOpts{Context: ctx} maxDepth := g.MaxDepth(ctx) @@ -473,14 +722,14 @@ func (g *OutputGameHelper) gameData(ctx context.Context) string { pos := types.NewPositionFromGIndex(claim.Position) extra := "" if pos.Depth() <= splitDepth { - blockNum, err := g.correctOutputProvider.BlockNumber(pos) + blockNum, err := g.correctOutputProvider.ClaimedBlockNumber(pos) if err != nil { } else { extra = fmt.Sprintf("Block num: %v", blockNum) } } - info = info + fmt.Sprintf("%v - Position: %v, Depth: %v, IndexAtDepth: %v Trace Index: %v, Value: %v, Countered By: %v, ParentIndex: %v %v\n", - i, claim.Position.Int64(), pos.Depth(), pos.IndexAtDepth(), pos.TraceIndex(maxDepth), common.Hash(claim.Claim).Hex(), claim.CounteredBy, claim.ParentIndex, extra) + info = info + fmt.Sprintf("%v - Position: %v, Depth: %v, IndexAtDepth: %v Trace Index: %v, ClaimHash: %v, Countered By: %v, ParentIndex: %v Claimant: %v Bond: %v %v\n", + i, claim.Position.Int64(), pos.Depth(), pos.IndexAtDepth(), pos.TraceIndex(maxDepth), common.Hash(claim.Claim).Hex(), claim.CounteredBy, claim.ParentIndex, claim.Claimant, claim.Bond, extra) } l2BlockNum := g.L2BlockNum(ctx) status, err := g.game.Status(opts) @@ -492,3 +741,19 @@ func (g *OutputGameHelper) gameData(ctx context.Context) string { func (g *OutputGameHelper) LogGameData(ctx context.Context) { g.t.Log(g.gameData(ctx)) } + +func (g *OutputGameHelper) Credit(ctx context.Context, addr common.Address) *big.Int { + opts := &bind.CallOpts{Context: ctx} + amt, err := g.game.Credit(opts, addr) + g.require.NoError(err) + return amt +} + +func (g *OutputGameHelper) getL1Head(ctx context.Context) eth.BlockID { + l1HeadHash, err := g.game.L1Head(&bind.CallOpts{Context: ctx}) + g.require.NoError(err, "Failed to load L1 head") + l1Header, err := g.client.HeaderByHash(ctx, l1HeadHash) + g.require.NoError(err, "Failed to load L1 header") + l1Head := eth.HeaderBlockID(l1Header) + return l1Head +} diff --git a/op-e2e/e2eutils/disputegame/output_honest_helper.go b/op-e2e/e2eutils/disputegame/output_honest_helper.go index 6615cf3646c8..9258dfd797e4 100644 --- a/op-e2e/e2eutils/disputegame/output_honest_helper.go +++ b/op-e2e/e2eutils/disputegame/output_honest_helper.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/stretchr/testify/require" ) @@ -18,17 +19,28 @@ type OutputHonestHelper struct { correctTrace types.TraceAccessor } -func (h *OutputHonestHelper) AttackClaim(ctx context.Context, claim *ClaimHelper) *ClaimHelper { - h.Attack(ctx, claim.index) +func (h *OutputHonestHelper) CounterClaim(ctx context.Context, claim *ClaimHelper, opts ...MoveOpt) *ClaimHelper { + game, target := h.loadState(ctx, claim.index) + value, err := h.correctTrace.Get(ctx, game, target, target.Position) + h.require.NoErrorf(err, "Failed to determine correct claim at position %v with g index %v", target.Position, target.Position.ToGIndex()) + if value == claim.claim { + return h.DefendClaim(ctx, claim, opts...) + } else { + return h.AttackClaim(ctx, claim, opts...) + } +} + +func (h *OutputHonestHelper) AttackClaim(ctx context.Context, claim *ClaimHelper, opts ...MoveOpt) *ClaimHelper { + h.Attack(ctx, claim.index, opts...) return claim.WaitForCounterClaim(ctx) } -func (h *OutputHonestHelper) DefendClaim(ctx context.Context, claim *ClaimHelper) *ClaimHelper { - h.Defend(ctx, claim.index) +func (h *OutputHonestHelper) DefendClaim(ctx context.Context, claim *ClaimHelper, opts ...MoveOpt) *ClaimHelper { + h.Defend(ctx, claim.index, opts...) return claim.WaitForCounterClaim(ctx) } -func (h *OutputHonestHelper) Attack(ctx context.Context, claimIdx int64) { +func (h *OutputHonestHelper) Attack(ctx context.Context, claimIdx int64, opts ...MoveOpt) { // Ensure the claim exists h.game.WaitForClaimCount(ctx, claimIdx+1) @@ -41,11 +53,11 @@ func (h *OutputHonestHelper) Attack(ctx context.Context, claimIdx int64) { value, err := h.correctTrace.Get(ctx, game, claim, attackPos) h.require.NoErrorf(err, "Get correct claim at position %v with g index %v", attackPos, attackPos.ToGIndex()) h.t.Log("Performing attack") - h.game.Attack(ctx, claimIdx, value) + h.game.Attack(ctx, claimIdx, value, opts...) h.t.Log("Attack complete") } -func (h *OutputHonestHelper) Defend(ctx context.Context, claimIdx int64) { +func (h *OutputHonestHelper) Defend(ctx context.Context, claimIdx int64, opts ...MoveOpt) { // Ensure the claim exists h.game.WaitForClaimCount(ctx, claimIdx+1) @@ -55,7 +67,7 @@ func (h *OutputHonestHelper) Defend(ctx context.Context, claimIdx int64) { defendPos := claim.Position.Defend() value, err := h.correctTrace.Get(ctx, game, claim, defendPos) h.game.require.NoErrorf(err, "Get correct claim at position %v with g index %v", defendPos, defendPos.ToGIndex()) - h.game.Defend(ctx, claimIdx, value) + h.game.Defend(ctx, claimIdx, value, opts...) } func (h *OutputHonestHelper) StepClaimFails(ctx context.Context, claim *ClaimHelper, isAttack bool) { @@ -81,7 +93,7 @@ func (h *OutputHonestHelper) StepFails(ctx context.Context, claimIdx int64, isAt } func (h *OutputHonestHelper) loadState(ctx context.Context, claimIdx int64) (types.Game, types.Claim) { - claims, err := h.contract.GetAllClaims(ctx) + claims, err := h.contract.GetAllClaims(ctx, rpcblock.Latest) h.require.NoError(err, "Failed to load claims from game") game := types.NewGameState(claims, h.game.MaxDepth(ctx)) diff --git a/op-e2e/e2eutils/disputegame/preimage/preimage_helper.go b/op-e2e/e2eutils/disputegame/preimage/preimage_helper.go new file mode 100644 index 000000000000..f124add19d63 --- /dev/null +++ b/op-e2e/e2eutils/disputegame/preimage/preimage_helper.go @@ -0,0 +1,139 @@ +package preimage + +import ( + "bytes" + "context" + "errors" + "io" + "math/big" + "math/rand" + "sync/atomic" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/preimages" + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/matrix" + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum-optimism/optimism/op-service/testutils" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +const MinPreimageSize = 10000 + +type Helper struct { + t *testing.T + require *require.Assertions + client *ethclient.Client + opts *bind.TransactOpts + oracleBindings *bindings.PreimageOracle + oracle *contracts.PreimageOracleContract + uuidProvider atomic.Int64 +} + +func NewHelper(t *testing.T, opts *bind.TransactOpts, client *ethclient.Client, addr common.Address) *Helper { + require := require.New(t) + oracleBindings, err := bindings.NewPreimageOracle(addr, client) + require.NoError(err) + + oracle, err := contracts.NewPreimageOracleContract(addr, batching.NewMultiCaller(client.Client(), batching.DefaultBatchSize)) + require.NoError(err) + return &Helper{ + t: t, + require: require, + client: client, + opts: opts, + oracleBindings: oracleBindings, + oracle: oracle, + } +} + +type InputModifier func(startBlock uint64, input *types.InputData) + +func WithReplacedCommitment(idx uint64, value common.Hash) InputModifier { + return func(startBlock uint64, input *types.InputData) { + if startBlock > idx { + return + } + if startBlock+uint64(len(input.Commitments)) < idx { + return + } + input.Commitments[idx-startBlock] = value + } +} + +func WithLastCommitment(value common.Hash) InputModifier { + return func(startBlock uint64, input *types.InputData) { + if input.Finalize { + input.Commitments[len(input.Commitments)-1] = value + } + } +} + +// UploadLargePreimage inits the preimage upload and uploads the leaves, starting the challenge period. +// Squeeze is not called by this method as the challenge period has not yet elapsed. +func (h *Helper) UploadLargePreimage(ctx context.Context, dataSize int, modifiers ...InputModifier) types.LargePreimageIdent { + data := testutils.RandomData(rand.New(rand.NewSource(1234)), dataSize) + s := matrix.NewStateMatrix() + uuid := big.NewInt(h.uuidProvider.Add(1)) + bondValue, err := h.oracleBindings.MINBONDSIZE(&bind.CallOpts{}) + h.require.NoError(err) + h.opts.Value = bondValue + tx, err := h.oracleBindings.InitLPP(h.opts, uuid, 32, uint32(len(data))) + h.require.NoError(err) + _, err = wait.ForReceiptOK(ctx, h.client, tx.Hash()) + h.require.NoError(err) + h.opts.Value = big.NewInt(0) + + startBlock := big.NewInt(0) + totalBlocks := len(data) / types.BlockSize + in := bytes.NewReader(data) + for { + inputData, err := s.AbsorbUpTo(in, preimages.MaxChunkSize) + if !errors.Is(err, io.EOF) { + h.require.NoError(err) + } + for _, modifier := range modifiers { + modifier(startBlock.Uint64(), &inputData) + } + commitments := make([][32]byte, len(inputData.Commitments)) + for i, commitment := range inputData.Commitments { + commitments[i] = commitment + } + h.t.Logf("Uploading %v parts of preimage %v starting at block %v of about %v Finalize: %v", len(commitments), uuid.Uint64(), startBlock.Uint64(), totalBlocks, inputData.Finalize) + tx, err := h.oracleBindings.AddLeavesLPP(h.opts, uuid, startBlock, inputData.Input, commitments, inputData.Finalize) + h.require.NoError(err) + _, err = wait.ForReceiptOK(ctx, h.client, tx.Hash()) + h.require.NoError(err) + startBlock = new(big.Int).Add(startBlock, big.NewInt(int64(len(inputData.Commitments)))) + if inputData.Finalize { + break + } + } + + return types.LargePreimageIdent{ + Claimant: h.opts.From, + UUID: uuid, + } +} + +func (h *Helper) WaitForChallenged(ctx context.Context, ident types.LargePreimageIdent) { + timedCtx, cancel := context.WithTimeout(ctx, 30*time.Second) + defer cancel() + err := wait.For(timedCtx, time.Second, func() (bool, error) { + metadata, err := h.oracle.GetProposalMetadata(ctx, rpcblock.Latest, ident) + if err != nil { + return false, err + } + h.require.Len(metadata, 1) + return metadata[0].Countered, nil + }) + h.require.NoError(err, "Preimage was not challenged") +} diff --git a/op-e2e/e2eutils/fakebeacon/blobs.go b/op-e2e/e2eutils/fakebeacon/blobs.go index 7f3c950685a1..1f77e3d5a3f8 100644 --- a/op-e2e/e2eutils/fakebeacon/blobs.go +++ b/op-e2e/e2eutils/fakebeacon/blobs.go @@ -113,7 +113,7 @@ func (f *FakeBeacon) Start(addr string) error { return } sidecars[i] = ð.APIBlobSidecar{ - Index: eth.Uint64String(i), + Index: eth.Uint64String(ix), KZGCommitment: eth.Bytes48(bundle.Commitments[ix]), KZGProof: eth.Bytes48(bundle.Proofs[ix]), SignedBlockHeader: eth.SignedBeaconBlockHeader{ diff --git a/op-e2e/e2eutils/geth/find.go b/op-e2e/e2eutils/geth/find.go new file mode 100644 index 000000000000..6d86659a4c1d --- /dev/null +++ b/op-e2e/e2eutils/geth/find.go @@ -0,0 +1,50 @@ +package geth + +import ( + "context" + "errors" + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" +) + +var ErrNotFound = errors.New("not found") + +// FindBlock finds the first block for which the predicate [pred] matches +// and returns it. It starts at [from] and iterates until [to], inclusively, +// using the provided [client]. It supports both search directions, forwards +// and backwards. +func FindBlock(client *ethclient.Client, + from, to int, timeout time.Duration, + pred func(*types.Block) (bool, error), +) (*types.Block, error) { + dir := 1 + if from > to { + dir = -1 + } + + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + for n := from; ; n += dir { + b, err := client.BlockByNumber(ctx, big.NewInt(int64(n))) + if err != nil { + return nil, fmt.Errorf("fetching block[%d]: %w", n, err) + } + ok, err := pred(b) + if err != nil { + return nil, fmt.Errorf("predicate error[%d]: %w", n, err) + } else if ok { + return b, nil + } + + // include n in range + if n == to { + break + } + } + + return nil, ErrNotFound +} diff --git a/op-e2e/e2eutils/l2oo/helper.go b/op-e2e/e2eutils/l2oo/helper.go deleted file mode 100644 index 47676e7c6fb6..000000000000 --- a/op-e2e/e2eutils/l2oo/helper.go +++ /dev/null @@ -1,130 +0,0 @@ -package l2oo - -import ( - "context" - "crypto/ecdsa" - "math/big" - "testing" - "time" - - "github.com/ethereum-optimism/optimism/op-bindings/bindings" - "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" - "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" - "github.com/ethereum-optimism/optimism/op-node/rollup" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/stretchr/testify/require" -) - -type L2OOHelper struct { - t *testing.T - require *require.Assertions - client *ethclient.Client - l2oo *bindings.L2OutputOracle - - // Nil when read-only - transactOpts *bind.TransactOpts - rollupCfg *rollup.Config -} - -func NewL2OOHelperReadOnly(t *testing.T, deployments *genesis.L1Deployments, client *ethclient.Client) *L2OOHelper { - require := require.New(t) - l2oo, err := bindings.NewL2OutputOracle(deployments.L2OutputOracleProxy, client) - require.NoError(err, "Error creating l2oo bindings") - - return &L2OOHelper{ - t: t, - require: require, - client: client, - l2oo: l2oo, - } -} - -func NewL2OOHelper(t *testing.T, deployments *genesis.L1Deployments, client *ethclient.Client, proposerKey *ecdsa.PrivateKey, rollupCfg *rollup.Config) *L2OOHelper { - h := NewL2OOHelperReadOnly(t, deployments, client) - - chainID, err := client.ChainID(context.Background()) - h.require.NoError(err, "Failed to get chain ID") - transactOpts, err := bind.NewKeyedTransactorWithChainID(proposerKey, chainID) - h.require.NoError(err) - h.transactOpts = transactOpts - h.rollupCfg = rollupCfg - return h -} - -// WaitForProposals waits until there are at least the specified number of proposals in the output oracle -// Returns the index of the latest output proposal -func (h *L2OOHelper) WaitForProposals(ctx context.Context, req int64) uint64 { - ctx, cancel := context.WithTimeout(ctx, 2*time.Minute) - defer cancel() - opts := &bind.CallOpts{Context: ctx} - latestOutputIndex, err := wait.AndGet( - ctx, - time.Second, - func() (*big.Int, error) { - index, err := h.l2oo.LatestOutputIndex(opts) - if err != nil { - h.t.Logf("Could not get latest output index: %v", err.Error()) - return nil, nil - } - h.t.Logf("Latest output index: %v", index) - return index, nil - }, - func(index *big.Int) bool { - return index != nil && index.Cmp(big.NewInt(req-1)) >= 0 - }) - h.require.NoErrorf(err, "Did not get %v output roots", req) - return latestOutputIndex.Uint64() -} - -func (h *L2OOHelper) GetL2Output(ctx context.Context, idx uint64) bindings.TypesOutputProposal { - output, err := h.l2oo.GetL2Output(&bind.CallOpts{Context: ctx}, new(big.Int).SetUint64(idx)) - h.require.NoErrorf(err, "Failed to get output root at index: %v", idx) - return output -} - -func (h *L2OOHelper) GetL2OutputAfter(ctx context.Context, l2BlockNum uint64) bindings.TypesOutputProposal { - opts := &bind.CallOpts{Context: ctx} - outputIdx, err := h.l2oo.GetL2OutputIndexAfter(opts, new(big.Int).SetUint64(l2BlockNum)) - h.require.NoError(err, "Fetch challenged output index") - output, err := h.l2oo.GetL2Output(opts, outputIdx) - h.require.NoError(err, "Fetch challenged output") - return output -} - -func (h *L2OOHelper) GetL2OutputBefore(ctx context.Context, l2BlockNum uint64) bindings.TypesOutputProposal { - opts := &bind.CallOpts{Context: ctx} - latestBlockNum, err := h.l2oo.LatestBlockNumber(opts) - h.require.NoError(err, "Failed to get latest output root block number") - var outputIdx *big.Int - if latestBlockNum.Uint64() < l2BlockNum { - outputIdx, err = h.l2oo.LatestOutputIndex(opts) - h.require.NoError(err, "Failed to get latest output index") - } else { - outputIdx, err = h.l2oo.GetL2OutputIndexAfter(opts, new(big.Int).SetUint64(l2BlockNum)) - h.require.NoErrorf(err, "Failed to get output index after block %v", l2BlockNum) - h.require.NotZerof(outputIdx.Uint64(), "No l2 output before block %v", l2BlockNum) - outputIdx = new(big.Int).Sub(outputIdx, common.Big1) - } - return h.GetL2Output(ctx, outputIdx.Uint64()) -} - -func (h *L2OOHelper) PublishNextOutput(ctx context.Context, outputRoot common.Hash) { - h.require.NotNil(h.transactOpts, "Can't publish outputs from a read only L2OOHelper") - nextBlockNum, err := h.l2oo.NextBlockNumber(&bind.CallOpts{Context: ctx}) - h.require.NoError(err, "Should get next block number") - - genesis := h.rollupCfg.Genesis - targetTimestamp := genesis.L2Time + ((nextBlockNum.Uint64() - genesis.L2.Number) * h.rollupCfg.BlockTime) - timedCtx, cancel := context.WithTimeout(ctx, 30*time.Second) - defer cancel() - h.require.NoErrorf( - wait.ForBlockWithTimestamp(timedCtx, h.client, targetTimestamp), - "Wait for L1 block with timestamp >= %v", targetTimestamp) - - tx, err := h.l2oo.ProposeL2Output(h.transactOpts, outputRoot, nextBlockNum, [32]byte{}, common.Big0) - h.require.NoErrorf(err, "Failed to propose output root for l2 block number %v", nextBlockNum) - _, err = wait.ForReceiptOK(ctx, h.client, tx.Hash()) - h.require.NoErrorf(err, "Proposal for l2 block %v failed", nextBlockNum) -} diff --git a/op-e2e/e2eutils/setup.go b/op-e2e/e2eutils/setup.go index 3370a1076bf5..a417060a7399 100644 --- a/op-e2e/e2eutils/setup.go +++ b/op-e2e/e2eutils/setup.go @@ -44,6 +44,7 @@ type TestParams struct { SequencerWindowSize uint64 ChannelTimeout uint64 L1BlockTime uint64 + UsePlasma bool } func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams { @@ -57,6 +58,7 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams { deployConfig.SequencerWindowSize = tp.SequencerWindowSize deployConfig.ChannelTimeout = tp.ChannelTimeout deployConfig.L1BlockTime = tp.L1BlockTime + deployConfig.UsePlasma = tp.UsePlasma ApplyDeployConfigForks(deployConfig) require.NoError(t, deployConfig.Check()) @@ -103,9 +105,9 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) * require.NoError(t, deployConf.Check()) l1Deployments := config.L1Deployments.Copy() - require.NoError(t, l1Deployments.Check()) + require.NoError(t, l1Deployments.Check(deployConf)) - l1Genesis, err := genesis.BuildL1DeveloperGenesis(deployConf, config.L1Allocs, l1Deployments, true) + l1Genesis, err := genesis.BuildL1DeveloperGenesis(deployConf, config.L1Allocs, l1Deployments) require.NoError(t, err, "failed to create l1 genesis") if alloc.PrefundTestUsers { for _, addr := range deployParams.Addresses.All() { @@ -161,6 +163,10 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) * EcotoneTime: deployConf.EcotoneTime(uint64(deployConf.L1GenesisBlockTimestamp)), FjordTime: deployConf.FjordTime(uint64(deployConf.L1GenesisBlockTimestamp)), InteropTime: deployConf.InteropTime(uint64(deployConf.L1GenesisBlockTimestamp)), + DAChallengeAddress: l1Deployments.DataAvailabilityChallengeProxy, + DAChallengeWindow: deployConf.DAChallengeWindow, + DAResolveWindow: deployConf.DAResolveWindow, + UsePlasma: deployConf.UsePlasma, } require.NoError(t, rollupCfg.Check()) @@ -204,3 +210,11 @@ func ApplyDeployConfigForks(deployConfig *genesis.DeployConfig) { deployConfig.L2GenesisCanyonTimeOffset = new(hexutil.Uint64) deployConfig.L2GenesisRegolithTimeOffset = new(hexutil.Uint64) } + +func UseFPAC() bool { + return os.Getenv("OP_E2E_USE_FPAC") == "true" +} + +func UsePlasma() bool { + return os.Getenv("OP_E2E_USE_PLASMA") == "true" +} diff --git a/op-e2e/e2eutils/transactions/gas.go b/op-e2e/e2eutils/transactions/gas.go index 4ce5e84e0f87..84e13aec25a5 100644 --- a/op-e2e/e2eutils/transactions/gas.go +++ b/op-e2e/e2eutils/transactions/gas.go @@ -17,14 +17,15 @@ type TxBuilder func(opts *bind.TransactOpts) (*types.Transaction, error) // NoSend=false and GasLimit including the requested padding. func PadGasEstimate(opts *bind.TransactOpts, paddingFactor float64, builder TxBuilder) (*types.Transaction, error) { // Take a copy of the opts to avoid mutating the original - o := *opts + oCopy := *opts + o := &oCopy o.NoSend = true - tx, err := builder(&o) + tx, err := builder(o) if err != nil { return nil, fmt.Errorf("failed to estimate gas: %w", err) } gas := float64(tx.Gas()) * paddingFactor o.GasLimit = uint64(gas) o.NoSend = false - return builder(&o) + return builder(o) } diff --git a/op-e2e/e2eutils/wait/blocks.go b/op-e2e/e2eutils/wait/blocks.go index 9656fc80e77b..9617c71a69b3 100644 --- a/op-e2e/e2eutils/wait/blocks.go +++ b/op-e2e/e2eutils/wait/blocks.go @@ -84,11 +84,22 @@ func ForUnsafeBlock(ctx context.Context, rollupCl *sources.RollupClient, n uint6 return err } -func ForNextSafeBlock(ctx context.Context, client BlockCaller) error { +func ForSafeBlock(ctx context.Context, rollupClient *sources.RollupClient, n uint64) error { + ctx, cancel := context.WithTimeout(ctx, 60*time.Second) + defer cancel() + _, err := AndGet(ctx, time.Second, func() (*eth.SyncStatus, error) { + return rollupClient.SyncStatus(ctx) + }, func(syncStatus *eth.SyncStatus) bool { + return syncStatus.SafeL2.Number >= n + }) + return err +} + +func ForNextSafeBlock(ctx context.Context, client BlockCaller) (*types.Block, error) { safeBlockNumber := big.NewInt(rpc.SafeBlockNumber.Int64()) current, err := client.BlockByNumber(ctx, safeBlockNumber) if err != nil { - return err + return nil, err } // Long timeout so we don't have to care what the block time is. If the test passes this will complete early anyway. @@ -97,14 +108,14 @@ func ForNextSafeBlock(ctx context.Context, client BlockCaller) error { for { select { case <-ctx.Done(): - return ctx.Err() + return nil, ctx.Err() default: next, err := client.BlockByNumber(ctx, safeBlockNumber) if err != nil { - return err + return nil, err } if next.NumberU64() > current.NumberU64() { - return nil + return next, nil } time.Sleep(500 * time.Millisecond) } diff --git a/op-e2e/e2eutils/wait/withdrawals.go b/op-e2e/e2eutils/wait/withdrawals.go index 2774ab12b57c..35c8f3005111 100644 --- a/op-e2e/e2eutils/wait/withdrawals.go +++ b/op-e2e/e2eutils/wait/withdrawals.go @@ -7,6 +7,9 @@ import ( "time" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-bindings/bindingspreview" + "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" + "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/ethclient" @@ -16,6 +19,8 @@ import ( // This function polls and can block for a very long time if used on mainnet. // This returns the block number to use for proof generation. func ForOutputRootPublished(ctx context.Context, client *ethclient.Client, l2OutputOracleAddr common.Address, l2BlockNumber *big.Int) (uint64, error) { + ctx, cancel := context.WithTimeout(ctx, 2*time.Minute) + defer cancel() l2BlockNumber = new(big.Int).Set(l2BlockNumber) // Don't clobber caller owned l2BlockNumber opts := &bind.CallOpts{Context: ctx} @@ -69,3 +74,58 @@ func ForFinalizationPeriod(ctx context.Context, client *ethclient.Client, l1Prov return header.Time > targetTimestamp.Uint64(), nil }) } + +// ForGamePublished waits until a game is published on L1 for the given l2BlockNumber. +func ForGamePublished(ctx context.Context, client *ethclient.Client, optimismPortalAddr common.Address, disputeGameFactoryAddr common.Address, l2BlockNumber *big.Int) (uint64, error) { + ctx, cancel := context.WithTimeout(ctx, 2*time.Minute) + defer cancel() + l2BlockNumber = new(big.Int).Set(l2BlockNumber) // Don't clobber caller owned l2BlockNumber + + optimismPortal2Contract, err := bindingspreview.NewOptimismPortal2Caller(optimismPortalAddr, client) + if err != nil { + return 0, err + } + + disputeGameFactoryContract, err := bindings.NewDisputeGameFactoryCaller(disputeGameFactoryAddr, client) + if err != nil { + return 0, err + } + + getL2BlockFromLatestGame := func() (*big.Int, error) { + latestGame, err := withdrawals.FindLatestGame(ctx, disputeGameFactoryContract, optimismPortal2Contract) + if err != nil { + return big.NewInt(-1), nil + } + + gameBlockNumber := new(big.Int).SetBytes(latestGame.ExtraData[0:32]) + return gameBlockNumber, nil + } + outputBlockNum, err := AndGet(ctx, time.Second, getL2BlockFromLatestGame, func(latest *big.Int) bool { + return latest.Cmp(l2BlockNumber) >= 0 + }) + if err != nil { + return 0, err + } + return outputBlockNum.Uint64(), nil +} + +// ForWithdrawalCheck waits until the withdrawal check in the portal succeeds. +func ForWithdrawalCheck(ctx context.Context, client *ethclient.Client, withdrawal crossdomain.Withdrawal, optimismPortalAddr common.Address) error { + ctx, cancel := context.WithTimeout(ctx, 2*time.Minute) + defer cancel() + opts := &bind.CallOpts{Context: ctx} + portal, err := bindingspreview.NewOptimismPortal2Caller(optimismPortalAddr, client) + if err != nil { + return fmt.Errorf("create portal caller: %w", err) + } + + return For(ctx, time.Second, func() (bool, error) { + wdHash, err := withdrawal.Hash() + if err != nil { + return false, fmt.Errorf("hash withdrawal: %w", err) + } + + err = portal.CheckWithdrawal(opts, wdHash) + return err == nil, nil + }) +} diff --git a/op-e2e/eip4844_test.go b/op-e2e/eip4844_test.go index 673946abd89a..5b5cc1d5308e 100644 --- a/op-e2e/eip4844_test.go +++ b/op-e2e/eip4844_test.go @@ -3,6 +3,7 @@ package op_e2e import ( "context" "math/big" + "math/rand" "testing" "time" @@ -11,22 +12,44 @@ import ( "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/log" "github.com/ethereum/go-ethereum/rpc" batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" + gethutils "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/testutils" ) // TestSystem4844E2E runs the SystemE2E test with 4844 enabled on L1, // and active on the rollup in the op-batcher and verifier. func TestSystem4844E2E(t *testing.T) { + t.Run("single-blob", func(t *testing.T) { testSystem4844E2E(t, false) }) + t.Run("multi-blob", func(t *testing.T) { testSystem4844E2E(t, true) }) +} + +func testSystem4844E2E(t *testing.T, multiBlob bool) { InitParallel(t) cfg := DefaultSystemConfig(t) cfg.DataAvailabilityType = batcherFlags.BlobsType + const maxBlobs = 6 + var maxL1TxSize int + if multiBlob { + cfg.BatcherTargetNumFrames = 6 + cfg.BatcherUseMaxTxSizeForBlobs = true + // leads to 6 blobs for an L2 block with a user tx with 400 random bytes + // while all other L2 blocks take 1 blob (deposit tx) + maxL1TxSize = derive.FrameV0OverHeadSize + 100 + cfg.BatcherMaxL1TxSizeBytes = uint64(maxL1TxSize) + } genesisActivation := hexutil.Uint64(0) cfg.DeployConfig.L1CancunTimeOffset = &genesisActivation @@ -37,7 +60,7 @@ func TestSystem4844E2E(t *testing.T) { require.Nil(t, err, "Error starting up system") defer sys.Close() - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) l1Client := sys.Clients["l1"] @@ -66,7 +89,7 @@ func TestSystem4844E2E(t *testing.T) { // Confirm balance ctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) defer cancel() - endBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) + endBalance, err := wait.ForBalanceChange(ctx, l2Verif, fromAddr, startBalance) require.NoError(t, err) diff := new(big.Int).Sub(endBalance, startBalance) @@ -77,6 +100,10 @@ func TestSystem4844E2E(t *testing.T) { opts.Value = big.NewInt(1_000_000_000) opts.Nonce = 1 // Already have deposit opts.ToAddr = &common.Address{0xff, 0xff} + // put some random data in the tx to make it fill up 6 blobs (multi-blob case) + opts.Data = testutils.RandomData(rand.New(rand.NewSource(420)), 400) + opts.Gas, err = core.IntrinsicGas(opts.Data, nil, false, true, true, false) + require.NoError(t, err) opts.VerifyOnClients(l2Verif) }) @@ -108,11 +135,61 @@ func TestSystem4844E2E(t *testing.T) { // wait for chain to be marked as "safe" (i.e. confirm batch-submission works) stat, err := rollupClient.SyncStatus(context.Background()) require.NoError(t, err) - return stat.SafeL2.Number > 0 + return stat.SafeL2.Number >= receipt.BlockNumber.Uint64() }, time.Second*20, time.Second, "expected L2 to be batch-submitted and labeled as safe") // check that the L2 tx is still canonical seqBlock, err = l2Seq.BlockByNumber(context.Background(), receipt.BlockNumber) require.NoError(t, err) require.Equal(t, seqBlock.Hash(), receipt.BlockHash, "receipt block must match canonical block at tx inclusion height") + + // find L1 block that contained the blob(s) batch tx + tip, err := l1Client.HeaderByNumber(context.Background(), nil) + require.NoError(t, err) + var blobTx *types.Transaction + blobBlock, err := gethutils.FindBlock(l1Client, int(tip.Number.Int64()), 0, 5*time.Second, + func(b *types.Block) (bool, error) { + for _, tx := range b.Transactions() { + if tx.Type() != types.BlobTxType { + continue + } + // expect to find at least one tx with multiple blobs in multi-blob case + if !multiBlob || len(tx.BlobHashes()) > 1 { + blobTx = tx + return true, nil + } + } + return false, nil + }) + require.NoError(t, err) + + numBlobs := len(blobTx.BlobHashes()) + if !multiBlob { + require.NotZero(t, numBlobs, "single-blob: expected to find L1 blob tx") + } else { + require.Equal(t, maxBlobs, numBlobs, "multi-blob: expected to find L1 blob tx with 6 blobs") + // blob tx should have filled up all but last blob + bcl := sys.L1BeaconHTTPClient() + hashes := toIndexedBlobHashes(blobTx.BlobHashes()...) + sidecars, err := bcl.BeaconBlobSideCars(context.Background(), false, sys.L1Slot(blobBlock.Time()), hashes) + require.NoError(t, err) + require.Len(t, sidecars.Data, maxBlobs) + for i := 0; i < maxBlobs-1; i++ { + data, err := sidecars.Data[i].Blob.ToData() + require.NoError(t, err) + require.Len(t, data, maxL1TxSize) + } + // last blob should only be partially filled + data, err := sidecars.Data[maxBlobs-1].Blob.ToData() + require.NoError(t, err) + require.Less(t, len(data), maxL1TxSize) + } +} + +func toIndexedBlobHashes(hs ...common.Hash) []eth.IndexedBlobHash { + hashes := make([]eth.IndexedBlobHash, 0, len(hs)) + for i, hash := range hs { + hashes = append(hashes, eth.IndexedBlobHash{Index: uint64(i), Hash: hash}) + } + return hashes } diff --git a/op-e2e/external_geth/main_test.go b/op-e2e/external_geth/main_test.go index b1f09b580672..85f4218f90b1 100644 --- a/op-e2e/external_geth/main_test.go +++ b/op-e2e/external_geth/main_test.go @@ -33,7 +33,7 @@ func TestShim(t *testing.T) { require.NoError(t, err) require.FileExists(t, "op-geth") - config.EthNodeVerbosity = 4 + config.EthNodeVerbosity = config.LegacyLevelDebug ec := (&e2e.ExternalRunner{ Name: "TestShim", diff --git a/op-e2e/faultproofs/challenge_preimage_test.go b/op-e2e/faultproofs/challenge_preimage_test.go new file mode 100644 index 000000000000..f071580b51ae --- /dev/null +++ b/op-e2e/faultproofs/challenge_preimage_test.go @@ -0,0 +1,68 @@ +package faultproofs + +import ( + "context" + "testing" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame/preimage" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestChallengeLargePreimages_ChallengeFirst(t *testing.T) { + op_e2e.InitParallel(t) + ctx := context.Background() + sys, _ := startFaultDisputeSystem(t) + t.Cleanup(sys.Close) + + disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys) + disputeGameFactory.StartChallenger(ctx, "Challenger", + challenger.WithAlphabet(sys.RollupEndpoint("sequencer")), + challenger.WithPrivKey(sys.Cfg.Secrets.Alice)) + preimageHelper := disputeGameFactory.PreimageHelper(ctx) + ident := preimageHelper.UploadLargePreimage(ctx, preimage.MinPreimageSize, + preimage.WithReplacedCommitment(0, common.Hash{0xaa})) + + require.NotEqual(t, ident.Claimant, common.Address{}) + + preimageHelper.WaitForChallenged(ctx, ident) +} + +func TestChallengeLargePreimages_ChallengeMiddle(t *testing.T) { + op_e2e.InitParallel(t) + ctx := context.Background() + sys, _ := startFaultDisputeSystem(t) + t.Cleanup(sys.Close) + disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys) + disputeGameFactory.StartChallenger(ctx, "Challenger", + challenger.WithAlphabet(sys.RollupEndpoint("sequencer")), + challenger.WithPrivKey(sys.Cfg.Secrets.Mallory)) + preimageHelper := disputeGameFactory.PreimageHelper(ctx) + ident := preimageHelper.UploadLargePreimage(ctx, preimage.MinPreimageSize, + preimage.WithReplacedCommitment(10, common.Hash{0xaa})) + + require.NotEqual(t, ident.Claimant, common.Address{}) + + preimageHelper.WaitForChallenged(ctx, ident) +} + +func TestChallengeLargePreimages_ChallengeLast(t *testing.T) { + op_e2e.InitParallel(t) + ctx := context.Background() + sys, _ := startFaultDisputeSystem(t) + t.Cleanup(sys.Close) + disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys) + disputeGameFactory.StartChallenger(ctx, "Challenger", + challenger.WithAlphabet(sys.RollupEndpoint("sequencer")), + challenger.WithPrivKey(sys.Cfg.Secrets.Mallory)) + preimageHelper := disputeGameFactory.PreimageHelper(ctx) + ident := preimageHelper.UploadLargePreimage(ctx, preimage.MinPreimageSize, + preimage.WithLastCommitment(common.Hash{0xaa})) + + require.NotEqual(t, ident.Claimant, common.Address{}) + + preimageHelper.WaitForChallenged(ctx, ident) +} diff --git a/op-e2e/faultproofs/multi_test.go b/op-e2e/faultproofs/multi_test.go index f1316a7dd504..0db4167cf492 100644 --- a/op-e2e/faultproofs/multi_test.go +++ b/op-e2e/faultproofs/multi_test.go @@ -11,7 +11,7 @@ import ( ) func TestMultipleGameTypes(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(0)) + op_e2e.InitParallel(t, op_e2e.UsesCannon) ctx := context.Background() sys, _ := startFaultDisputeSystem(t) diff --git a/op-e2e/faultproofs/output_alphabet_test.go b/op-e2e/faultproofs/output_alphabet_test.go index e7abf06e3d64..e87049b9c2e9 100644 --- a/op-e2e/faultproofs/output_alphabet_test.go +++ b/op-e2e/faultproofs/output_alphabet_test.go @@ -2,19 +2,22 @@ package faultproofs import ( "context" + "math/big" "testing" "time" + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer" op_e2e "github.com/ethereum-optimism/optimism/op-e2e" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ) func TestOutputAlphabetGame_ChallengerWins(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UseExecutor(1)) + op_e2e.InitParallel(t) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) t.Cleanup(sys.Close) @@ -70,8 +73,69 @@ func TestOutputAlphabetGame_ChallengerWins(t *testing.T) { game.LogGameData(ctx) } +func TestOutputAlphabetGame_ReclaimBond(t *testing.T) { + op_e2e.InitParallel(t) + ctx := context.Background() + sys, l1Client := startFaultDisputeSystem(t) + t.Cleanup(sys.Close) + + disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys) + game := disputeGameFactory.StartOutputAlphabetGame(ctx, "sequencer", 3, common.Hash{0xff}) + game.LogGameData(ctx) + + // The dispute game should have a zero balance + balance := game.WethBalance(ctx, game.Addr()) + require.Zero(t, balance.Uint64()) + + alice := sys.Cfg.Secrets.Addresses().Alice + + // Grab the root claim + claim := game.RootClaim(ctx) + opts := challenger.WithPrivKey(sys.Cfg.Secrets.Alice) + game.StartChallenger(ctx, "sequencer", "Challenger", opts) + game.LogGameData(ctx) + + // Perform a few moves + claim = claim.WaitForCounterClaim(ctx) + game.LogGameData(ctx) + claim = claim.Attack(ctx, common.Hash{}) + claim = claim.WaitForCounterClaim(ctx) + game.LogGameData(ctx) + claim = claim.Attack(ctx, common.Hash{}) + game.LogGameData(ctx) + _ = claim.WaitForCounterClaim(ctx) + + // Expect posted claims so the game balance is non-zero + balance = game.WethBalance(ctx, game.Addr()) + require.Truef(t, balance.Cmp(big.NewInt(0)) > 0, "Expected game balance to be above zero") + + sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx)) + require.NoError(t, wait.ForNextBlock(ctx, l1Client)) + game.WaitForGameStatus(ctx, disputegame.StatusChallengerWins) + game.LogGameData(ctx) + + // Expect Alice's credit to be non-zero + // But it can't be claimed right now since there is a delay on the weth unlock + require.Truef(t, game.AvailableCredit(ctx, alice).Cmp(big.NewInt(0)) > 0, "Expected alice credit to be above zero") + + // The actor should have no credit available because all its bonds were paid to Alice. + actorCredit := game.AvailableCredit(ctx, deployer.TestAddress) + require.True(t, actorCredit.Cmp(big.NewInt(0)) == 0, "Expected alice available credit to be zero") + + // Advance the time past the weth unlock delay + sys.TimeTravelClock.AdvanceTime(game.CreditUnlockDuration(ctx)) + require.NoError(t, wait.ForNextBlock(ctx, l1Client)) + + // Wait for alice to have no available credit + // aka, wait for the challenger to claim its credit + game.WaitForNoAvailableCredit(ctx, alice) + + // The dispute game delayed weth balance should be zero since it's all claimed + require.True(t, game.WethBalance(ctx, game.Addr()).Cmp(big.NewInt(0)) == 0) +} + func TestOutputAlphabetGame_ValidOutputRoot(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UseExecutor(1)) + op_e2e.InitParallel(t) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) t.Cleanup(sys.Close) @@ -102,7 +166,7 @@ func TestOutputAlphabetGame_ValidOutputRoot(t *testing.T) { } func TestChallengerCompleteExhaustiveDisputeGame(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UseExecutor(1)) + op_e2e.InitParallel(t) testCase := func(t *testing.T, isRootCorrect bool) { ctx := context.Background() @@ -159,11 +223,74 @@ func TestChallengerCompleteExhaustiveDisputeGame(t *testing.T) { } t.Run("RootCorrect", func(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UseExecutor(1)) + op_e2e.InitParallel(t) testCase(t, true) }) t.Run("RootIncorrect", func(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UseExecutor(1)) + op_e2e.InitParallel(t) testCase(t, false) }) } + +func TestOutputAlphabetGame_FreeloaderEarnsNothing(t *testing.T) { + op_e2e.InitParallel(t) + ctx := context.Background() + sys, l1Client := startFaultDisputeSystem(t) + t.Cleanup(sys.Close) + + freeloaderOpts, err := bind.NewKeyedTransactorWithChainID(sys.Cfg.Secrets.Mallory, sys.Cfg.L1ChainIDBig()) + require.Nil(t, err) + + disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys) + game := disputeGameFactory.StartOutputAlphabetGameWithCorrectRoot(ctx, "sequencer", 2) + correctTrace := game.CreateHonestActor(ctx, "sequencer") + game.LogGameData(ctx) + claim := game.DisputeLastBlock(ctx) + // Invalid root claim of the alphabet game + claim = claim.Attack(ctx, common.Hash{0x01}) + + // Chronology of claims: + // dishonest root claim: + // - honest counter + // - dishonest + // - freeloader + // - honest + // - freeloader + // The freeloader must be positioned leftmost (gindex positioning) or at the same position as honest claims. + + // honest counter + claim = correctTrace.AttackClaim(ctx, claim) + + var freeloaders []*disputegame.ClaimHelper + + // dishonest + dishonest := correctTrace.AttackClaim(ctx, claim) + + freeloaders = append(freeloaders, correctTrace.AttackClaim(ctx, dishonest, disputegame.WithTransactOpts(freeloaderOpts))) + freeloaders = append(freeloaders, dishonest.Attack(ctx, common.Hash{0x02}, disputegame.WithTransactOpts(freeloaderOpts))) + freeloaders = append(freeloaders, dishonest.Defend(ctx, common.Hash{0x03}, disputegame.WithTransactOpts(freeloaderOpts))) + + // Ensure freeloaders respond before the honest challenger + game.StartChallenger(ctx, "sequencer", "Challenger", challenger.WithPrivKey(sys.Cfg.Secrets.Alice)) + dishonest.WaitForCounterClaim(ctx, freeloaders...) + + // Freeloaders after the honest challenger + freeloaders = append(freeloaders, dishonest.Attack(ctx, common.Hash{0x04}, disputegame.WithTransactOpts(freeloaderOpts))) + freeloaders = append(freeloaders, dishonest.Defend(ctx, common.Hash{0x05}, disputegame.WithTransactOpts(freeloaderOpts))) + + for _, freeloader := range freeloaders { + if freeloader.IsMaxDepth(ctx) { + freeloader.WaitForCountered(ctx) + } else { + freeloader.WaitForCounterClaim(ctx) + } + } + + game.LogGameData(ctx) + sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx)) + require.NoError(t, wait.ForNextBlock(ctx, l1Client)) + game.WaitForGameStatus(ctx, disputegame.StatusDefenderWins) + + amt := game.Credit(ctx, freeloaderOpts.From) + require.True(t, amt.BitLen() == 0, "freeloaders should not be rewarded") +} diff --git a/op-e2e/faultproofs/output_cannon_test.go b/op-e2e/faultproofs/output_cannon_test.go index be16c921f966..6aed7c041e34 100644 --- a/op-e2e/faultproofs/output_cannon_test.go +++ b/op-e2e/faultproofs/output_cannon_test.go @@ -3,21 +3,23 @@ package faultproofs import ( "context" "fmt" + "math/big" "testing" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" op_e2e "github.com/ethereum-optimism/optimism/op-e2e" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame/preimage" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/require" ) -const outputCannonTestExecutor = 0 - func TestOutputCannonGame(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(outputCannonTestExecutor)) + op_e2e.InitParallel(t, op_e2e.UsesCannon) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) t.Cleanup(sys.Close) @@ -73,7 +75,7 @@ func TestOutputCannonGame(t *testing.T) { func TestOutputCannon_ChallengeAllZeroClaim(t *testing.T) { // The dishonest actor always posts claims with all zeros. - op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(outputCannonTestExecutor)) + op_e2e.InitParallel(t, op_e2e.UsesCannon) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) t.Cleanup(sys.Close) @@ -101,7 +103,7 @@ func TestOutputCannon_ChallengeAllZeroClaim(t *testing.T) { } func TestOutputCannon_PublishCannonRootClaim(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(outputCannonTestExecutor)) + op_e2e.InitParallel(t, op_e2e.UsesCannon) tests := []struct { disputeL2BlockNumber uint64 }{ @@ -111,7 +113,8 @@ func TestOutputCannon_PublishCannonRootClaim(t *testing.T) { for _, test := range tests { test := test t.Run(fmt.Sprintf("Dispute_%v", test.disputeL2BlockNumber), func(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(outputCannonTestExecutor)) + op_e2e.InitParallel(t, op_e2e.UsesCannon) + ctx := context.Background() sys, _ := startFaultDisputeSystem(t) @@ -129,9 +132,7 @@ func TestOutputCannon_PublishCannonRootClaim(t *testing.T) { } func TestOutputCannonDisputeGame(t *testing.T) { - executor := uint64(1) // Different executor to the other tests to help balance things better - op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(executor)) - + op_e2e.InitParallel(t, op_e2e.UsesCannon) tests := []struct { name string defendClaimDepth types.Depth @@ -143,7 +144,7 @@ func TestOutputCannonDisputeGame(t *testing.T) { for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UseExecutor(executor)) + op_e2e.InitParallel(t, op_e2e.UsesCannon) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) @@ -180,8 +181,7 @@ func TestOutputCannonDisputeGame(t *testing.T) { } func TestOutputCannonDefendStep(t *testing.T) { - executor := uint64(1) // Different executor to the other tests to help balance things better - op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(executor)) + op_e2e.InitParallel(t, op_e2e.UsesCannon) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) @@ -216,9 +216,139 @@ func TestOutputCannonDefendStep(t *testing.T) { require.EqualValues(t, disputegame.StatusChallengerWins, game.Status(ctx)) } +func TestOutputCannonStepWithLargePreimage(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + + ctx := context.Background() + sys, _ := startFaultDisputeSystem(t, withBatcherStopped()) + t.Cleanup(sys.Close) + + // Manually send a tx from the correct batcher key to the batcher input with very large (invalid) data + // This forces op-program to load a large preimage. + sys.BatcherHelper().SendLargeInvalidBatch(ctx) + + require.NoError(t, sys.BatchSubmitter.Start(ctx)) + + safeHead, err := wait.ForNextSafeBlock(ctx, sys.NodeClient("sequencer")) + require.NoError(t, err, "Batcher should resume submitting valid batches") + + l2BlockNumber := safeHead.NumberU64() + disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys) + // Dispute any block - it will have to read the L1 batches to see if the block is reached + game := disputeGameFactory.StartOutputCannonGame(ctx, "sequencer", l2BlockNumber, common.Hash{0x01, 0xaa}) + require.NotNil(t, game) + outputRootClaim := game.DisputeBlock(ctx, l2BlockNumber) + game.LogGameData(ctx) + + game.StartChallenger(ctx, "sequencer", "Challenger", challenger.WithPrivKey(sys.Cfg.Secrets.Alice)) + + // Wait for the honest challenger to dispute the outputRootClaim. + // This creates a root of an execution game that we challenge by + // coercing a step at a preimage trace index. + outputRootClaim = outputRootClaim.WaitForCounterClaim(ctx) + + game.LogGameData(ctx) + // Now the honest challenger is positioned as the defender of the + // execution game. We then move to challenge it to induce a large preimage load. + sender := sys.Cfg.Secrets.Addresses().Alice + preimageLoadCheck := game.CreateStepLargePreimageLoadCheck(ctx, sender) + game.ChallengeToPreimageLoad(ctx, outputRootClaim, sys.Cfg.Secrets.Alice, cannon.PreimageLargerThan(preimage.MinPreimageSize), preimageLoadCheck, false) + // The above method already verified the image was uploaded and step called successfully + // So we don't waste time resolving the game - that's tested elsewhere. +} + +func TestOutputCannonStepWithPreimage(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + testPreimageStep := func(t *testing.T, preimageType cannon.PreimageOpt, preloadPreimage bool) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + + ctx := context.Background() + sys, _ := startFaultDisputeSystem(t, withBlobBatches()) + t.Cleanup(sys.Close) + + disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys) + game := disputeGameFactory.StartOutputCannonGame(ctx, "sequencer", 1, common.Hash{0x01, 0xaa}) + require.NotNil(t, game) + outputRootClaim := game.DisputeLastBlock(ctx) + game.LogGameData(ctx) + + game.StartChallenger(ctx, "sequencer", "Challenger", challenger.WithPrivKey(sys.Cfg.Secrets.Alice)) + + // Wait for the honest challenger to dispute the outputRootClaim. This creates a root of an execution game that we challenge by coercing + // a step at a preimage trace index. + outputRootClaim = outputRootClaim.WaitForCounterClaim(ctx) + + // Now the honest challenger is positioned as the defender of the execution game + // We then move to challenge it to induce a preimage load + preimageLoadCheck := game.CreateStepPreimageLoadCheck(ctx) + game.ChallengeToPreimageLoad(ctx, outputRootClaim, sys.Cfg.Secrets.Alice, preimageType, preimageLoadCheck, preloadPreimage) + // The above method already verified the image was uploaded and step called successfully + // So we don't waste time resolving the game - that's tested elsewhere. + } + + preimageConditions := []string{"keccak", "sha256", "blob"} + for _, preimageType := range preimageConditions { + preimageType := preimageType + t.Run("non-existing preimage-"+preimageType, func(t *testing.T) { + testPreimageStep(t, cannon.FirstPreimageLoadOfType(preimageType), false) + }) + } + // Only test pre-existing images with one type to save runtime + t.Run("preimage already exists", func(t *testing.T) { + testPreimageStep(t, cannon.FirstKeccakPreimageLoad(), true) + }) +} + +func TestOutputCannonStepWithKZGPointEvaluation(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + + testPreimageStep := func(t *testing.T, preloadPreimage bool) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + + ctx := context.Background() + sys, _ := startFaultDisputeSystem(t, withEcotone()) + t.Cleanup(sys.Close) + + // NOTE: Flake prevention + // Ensure that the L1 origin including the point eval tx isn't on the genesis epoch. + safeBlock, err := sys.Clients["sequencer"].BlockByNumber(ctx, big.NewInt(int64(rpc.SafeBlockNumber))) + require.NoError(t, err) + require.NoError(t, wait.ForSafeBlock(ctx, sys.RollupClient("sequencer"), safeBlock.NumberU64()+3)) + + receipt := sendKZGPointEvaluationTx(t, sys, "sequencer", sys.Cfg.Secrets.Alice) + precompileBlock := receipt.BlockNumber + t.Logf("KZG Point Evaluation block number: %d", precompileBlock) + + disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys) + game := disputeGameFactory.StartOutputCannonGame(ctx, "sequencer", precompileBlock.Uint64(), common.Hash{0x01, 0xaa}) + require.NotNil(t, game) + outputRootClaim := game.DisputeLastBlock(ctx) + game.LogGameData(ctx) + + game.StartChallenger(ctx, "sequencer", "Challenger", challenger.WithPrivKey(sys.Cfg.Secrets.Alice)) + + // Wait for the honest challenger to dispute the outputRootClaim. This creates a root of an execution game that we challenge by coercing + // a step at a preimage trace index. + outputRootClaim = outputRootClaim.WaitForCounterClaim(ctx) + + // Now the honest challenger is positioned as the defender of the execution game + // We then move to challenge it to induce a preimage load + preimageLoadCheck := game.CreateStepPreimageLoadCheck(ctx) + game.ChallengeToPreimageLoad(ctx, outputRootClaim, sys.Cfg.Secrets.Alice, cannon.FirstPrecompilePreimageLoad(), preimageLoadCheck, preloadPreimage) + // The above method already verified the image was uploaded and step called successfully + // So we don't waste time resolving the game - that's tested elsewhere. + } + + t.Run("non-existing preimage", func(t *testing.T) { + testPreimageStep(t, false) + }) + t.Run("preimage already exists", func(t *testing.T) { + testPreimageStep(t, true) + }) +} + func TestOutputCannonProposedOutputRootValid(t *testing.T) { - executor := uint64(1) // Different executor to the other tests to help balance things better - op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(executor)) + op_e2e.InitParallel(t, op_e2e.UsesCannon) // honestStepsFail attempts to perform both an attack and defend step using the correct trace. honestStepsFail := func(ctx context.Context, game *disputegame.OutputCannonGameHelper, correctTrace *disputegame.OutputHonestHelper, parentClaimIdx int64) { // Attack step should fail @@ -273,7 +403,7 @@ func TestOutputCannonProposedOutputRootValid(t *testing.T) { for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UseExecutor(executor)) + op_e2e.InitParallel(t, op_e2e.UsesCannon) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) @@ -307,7 +437,7 @@ func TestOutputCannonProposedOutputRootValid(t *testing.T) { } func TestOutputCannonPoisonedPostState(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(outputCannonTestExecutor)) + op_e2e.InitParallel(t, op_e2e.UsesCannon) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) @@ -371,7 +501,7 @@ func TestOutputCannonPoisonedPostState(t *testing.T) { } func TestDisputeOutputRootBeyondProposedBlock_ValidOutputRoot(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(outputCannonTestExecutor)) + op_e2e.InitParallel(t, op_e2e.UsesCannon) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) @@ -421,7 +551,7 @@ func TestDisputeOutputRootBeyondProposedBlock_ValidOutputRoot(t *testing.T) { } func TestDisputeOutputRootBeyondProposedBlock_InvalidOutputRoot(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(outputCannonTestExecutor)) + op_e2e.InitParallel(t, op_e2e.UsesCannon) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) @@ -472,7 +602,7 @@ func TestDisputeOutputRootBeyondProposedBlock_InvalidOutputRoot(t *testing.T) { } func TestDisputeOutputRoot_ChangeClaimedOutputRoot(t *testing.T) { - op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(outputCannonTestExecutor)) + op_e2e.InitParallel(t, op_e2e.UsesCannon) ctx := context.Background() sys, l1Client := startFaultDisputeSystem(t) @@ -530,3 +660,127 @@ func TestDisputeOutputRoot_ChangeClaimedOutputRoot(t *testing.T) { game.WaitForGameStatus(ctx, disputegame.StatusChallengerWins) game.LogGameData(ctx) } + +func TestInvalidateUnsafeProposal(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + ctx := context.Background() + + tests := []struct { + name string + strategy func(correctTrace *disputegame.OutputHonestHelper, parent *disputegame.ClaimHelper) *disputegame.ClaimHelper + }{ + { + name: "Attack", + strategy: func(correctTrace *disputegame.OutputHonestHelper, parent *disputegame.ClaimHelper) *disputegame.ClaimHelper { + return correctTrace.AttackClaim(ctx, parent) + }, + }, + { + name: "Defend", + strategy: func(correctTrace *disputegame.OutputHonestHelper, parent *disputegame.ClaimHelper) *disputegame.ClaimHelper { + return correctTrace.DefendClaim(ctx, parent) + }, + }, + { + name: "Counter", + strategy: func(correctTrace *disputegame.OutputHonestHelper, parent *disputegame.ClaimHelper) *disputegame.ClaimHelper { + return correctTrace.CounterClaim(ctx, parent) + }, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + sys, l1Client := startFaultDisputeSystem(t, withSequencerWindowSize(100000), withBatcherStopped()) + t.Cleanup(sys.Close) + + blockNum := uint64(1) + disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys) + // Root claim is _dishonest_ because the required data is not available on L1 + game := disputeGameFactory.StartOutputCannonGameWithCorrectRoot(ctx, "sequencer", blockNum, disputegame.WithUnsafeProposal()) + + correctTrace := game.CreateHonestActor(ctx, "sequencer", challenger.WithPrivKey(sys.Cfg.Secrets.Alice)) + + // Start the honest challenger + game.StartChallenger(ctx, "sequencer", "Challenger", challenger.WithPrivKey(sys.Cfg.Secrets.Bob)) + + game.DefendClaim(ctx, game.RootClaim(ctx), func(parent *disputegame.ClaimHelper) *disputegame.ClaimHelper { + if parent.IsBottomGameRoot(ctx) { + return correctTrace.AttackClaim(ctx, parent) + } + return test.strategy(correctTrace, parent) + }) + + // Time travel past when the game will be resolvable. + sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx)) + require.NoError(t, wait.ForNextBlock(ctx, l1Client)) + + game.WaitForGameStatus(ctx, disputegame.StatusChallengerWins) + game.LogGameData(ctx) + }) + } +} + +func TestInvalidateProposalForFutureBlock(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + ctx := context.Background() + + tests := []struct { + name string + strategy func(correctTrace *disputegame.OutputHonestHelper, parent *disputegame.ClaimHelper) *disputegame.ClaimHelper + }{ + { + name: "Attack", + strategy: func(correctTrace *disputegame.OutputHonestHelper, parent *disputegame.ClaimHelper) *disputegame.ClaimHelper { + return correctTrace.AttackClaim(ctx, parent) + }, + }, + { + name: "Defend", + strategy: func(correctTrace *disputegame.OutputHonestHelper, parent *disputegame.ClaimHelper) *disputegame.ClaimHelper { + return correctTrace.DefendClaim(ctx, parent) + }, + }, + { + name: "Counter", + strategy: func(correctTrace *disputegame.OutputHonestHelper, parent *disputegame.ClaimHelper) *disputegame.ClaimHelper { + return correctTrace.CounterClaim(ctx, parent) + }, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + sys, l1Client := startFaultDisputeSystem(t, withSequencerWindowSize(100000)) + t.Cleanup(sys.Close) + + farFutureBlockNum := uint64(10_000_000) + disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys) + // Root claim is _dishonest_ because the required data is not available on L1 + game := disputeGameFactory.StartOutputCannonGame(ctx, "sequencer", farFutureBlockNum, common.Hash{0xaa}, disputegame.WithFutureProposal()) + + correctTrace := game.CreateHonestActor(ctx, "sequencer", challenger.WithPrivKey(sys.Cfg.Secrets.Alice)) + + // Start the honest challenger + game.StartChallenger(ctx, "sequencer", "Honest", challenger.WithPrivKey(sys.Cfg.Secrets.Bob)) + + game.DefendClaim(ctx, game.RootClaim(ctx), func(parent *disputegame.ClaimHelper) *disputegame.ClaimHelper { + if parent.IsBottomGameRoot(ctx) { + return correctTrace.AttackClaim(ctx, parent) + } + return test.strategy(correctTrace, parent) + }) + + // Time travel past when the game will be resolvable. + sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx)) + require.NoError(t, wait.ForNextBlock(ctx, l1Client)) + + game.WaitForGameStatus(ctx, disputegame.StatusChallengerWins) + game.LogGameData(ctx) + }) + } +} diff --git a/op-e2e/faultproofs/precompile_test.go b/op-e2e/faultproofs/precompile_test.go new file mode 100644 index 000000000000..388fc6aeba52 --- /dev/null +++ b/op-e2e/faultproofs/precompile_test.go @@ -0,0 +1,170 @@ +package faultproofs + +import ( + "context" + "encoding/json" + "fmt" + "math" + "path/filepath" + "testing" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/op-challenger/config" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon" + "github.com/ethereum-optimism/optimism/op-challenger/metrics" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/require" +) + +func TestPrecompiles(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + // precompile test vectors copied from go-ethereum + tests := []struct { + name string + address common.Address + input []byte + }{ + { + name: "ecrecover", + address: common.BytesToAddress([]byte{0x01}), + input: common.FromHex("18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549"), + }, + { + name: "sha256", + address: common.BytesToAddress([]byte{0x02}), + input: common.FromHex("68656c6c6f20776f726c64"), + }, + { + name: "ripemd160", + address: common.BytesToAddress([]byte{0x03}), + input: common.FromHex("68656c6c6f20776f726c64"), + }, + { + name: "bn256Pairing", + address: common.BytesToAddress([]byte{0x08}), + input: common.FromHex("1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"), + }, + { + name: "blake2F", + address: common.BytesToAddress([]byte{0x09}), + input: common.FromHex("0000000048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001"), + }, + { + name: "kzgPointEvaluation", + address: common.BytesToAddress([]byte{0x0a}), + input: common.FromHex("01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a"), + }, + } + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + ctx := context.Background() + cfg := op_e2e.DefaultSystemConfig(t) + // We don't need a verifier - just the sequencer is enough + delete(cfg.Nodes, "verifier") + // Use a small sequencer window size to avoid test timeout while waiting for empty blocks + // But not too small to ensure that our claim and subsequent state change is published + cfg.DeployConfig.SequencerWindowSize = 16 + minTs := hexutil.Uint64(0) + cfg.DeployConfig.L2GenesisDeltaTimeOffset = &minTs + cfg.DeployConfig.L2GenesisEcotoneTimeOffset = &minTs + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + defer sys.Close() + + log := testlog.Logger(t, log.LevelInfo) + 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"] + rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint()) + require.Nil(t, err) + rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient)) + + aliceKey := cfg.Secrets.Alice + + t.Log("Capture current L2 head as agreed starting point") + latestBlock, err := l2Seq.BlockByNumber(ctx, nil) + require.NoError(t, err) + agreedL2Output, err := rollupClient.OutputAtBlock(ctx, latestBlock.NumberU64()) + require.NoError(t, err, "could not retrieve l2 agreed block") + l2Head := agreedL2Output.BlockRef.Hash + l2OutputRoot := agreedL2Output.OutputRoot + + receipt := op_e2e.SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *op_e2e.TxOpts) { + opts.Gas = 1_000_000 + opts.ToAddr = &test.address + opts.Nonce = 0 + opts.Data = test.input + }) + + t.Log("Determine L2 claim") + l2ClaimBlockNumber := receipt.BlockNumber + l2Output, err := rollupClient.OutputAtBlock(ctx, l2ClaimBlockNumber.Uint64()) + require.NoError(t, err, "could not get expected output") + l2Claim := l2Output.OutputRoot + + t.Log("Determine L1 head that includes all batches required for L2 claim block") + require.NoError(t, wait.ForSafeBlock(ctx, rollupClient, l2ClaimBlockNumber.Uint64())) + l1HeadBlock, err := l1Client.BlockByNumber(ctx, nil) + require.NoError(t, err, "get l1 head block") + l1Head := l1HeadBlock.Hash() + + inputs := cannon.LocalGameInputs{ + L1Head: l1Head, + L2Head: l2Head, + L2Claim: common.Hash(l2Claim), + L2OutputRoot: common.Hash(l2OutputRoot), + L2BlockNumber: l2ClaimBlockNumber, + } + runCannon(t, ctx, sys, inputs, "sequencer") + }) + } +} + +func runCannon(t *testing.T, ctx context.Context, sys *op_e2e.System, inputs cannon.LocalGameInputs, l2Node string) { + l1Endpoint := sys.NodeEndpoint("l1") + l1Beacon := sys.L1BeaconEndpoint() + cannonOpts := challenger.WithCannon(t, sys.RollupCfg(), sys.L2Genesis(), sys.RollupEndpoint(l2Node), sys.NodeEndpoint(l2Node)) + dir := t.TempDir() + proofsDir := filepath.Join(dir, "cannon-proofs") + cfg := config.NewConfig(common.Address{}, l1Endpoint, l1Beacon, dir) + cannonOpts(&cfg) + + logger := testlog.Logger(t, log.LevelInfo).New("role", "cannon") + executor := cannon.NewExecutor(logger, metrics.NoopMetrics, &cfg, inputs) + + t.Log("Running cannon") + err := executor.GenerateProof(ctx, proofsDir, math.MaxUint) + require.NoError(t, err, "failed to generate proof") + + state, err := parseState(filepath.Join(proofsDir, "final.json.gz")) + require.NoError(t, err, "failed to parse state") + t.Logf("Completed in %d steps", state.Step) +} + +func parseState(path string) (*mipsevm.State, error) { + file, err := ioutil.OpenDecompressed(path) + if err != nil { + return nil, fmt.Errorf("cannot open state file (%v): %w", path, err) + } + defer file.Close() + var state mipsevm.State + err = json.NewDecoder(file).Decode(&state) + if err != nil { + return nil, fmt.Errorf("invalid mipsevm state (%v): %w", path, err) + } + return &state, nil +} diff --git a/op-e2e/faultproofs/preimages_test.go b/op-e2e/faultproofs/preimages_test.go new file mode 100644 index 000000000000..fd6032b83fa1 --- /dev/null +++ b/op-e2e/faultproofs/preimages_test.go @@ -0,0 +1,53 @@ +package faultproofs + +import ( + "context" + "fmt" + "testing" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" + preimage "github.com/ethereum-optimism/optimism/op-preimage" + "github.com/ethereum-optimism/optimism/op-program/client" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestLocalPreimages(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + tests := []struct { + key preimage.Key + }{ + {key: client.L1HeadLocalIndex}, + {key: client.L2OutputRootLocalIndex}, + {key: client.L2ClaimLocalIndex}, + {key: client.L2ClaimBlockNumberLocalIndex}, + // We don't check client.L2ChainIDLocalIndex because e2e tests use a custom chain configuration + // which requires using a custom chain ID indicator so op-program will load the full rollup config and + // genesis from the preimage oracle + } + for _, test := range tests { + test := test + t.Run(fmt.Sprintf("preimage-%v", test.key), func(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + + ctx := context.Background() + sys, _ := startFaultDisputeSystem(t) + t.Cleanup(sys.Close) + + disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys) + game := disputeGameFactory.StartOutputCannonGame(ctx, "sequencer", 3, common.Hash{0x01, 0xaa}) + require.NotNil(t, game) + claim := game.DisputeLastBlock(ctx) + + // Create the root of the cannon trace. + claim = claim.Attack(ctx, common.Hash{0x01}) + + game.LogGameData(ctx) + + game.VerifyPreimage(ctx, claim, test.key) + + game.LogGameData(ctx) + }) + } +} diff --git a/op-e2e/faultproofs/util.go b/op-e2e/faultproofs/util.go index a86aa4f52ca2..804c8f307a02 100644 --- a/op-e2e/faultproofs/util.go +++ b/op-e2e/faultproofs/util.go @@ -1,16 +1,59 @@ package faultproofs import ( + "crypto/ecdsa" "testing" + batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "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/ethclient" "github.com/stretchr/testify/require" ) -func startFaultDisputeSystem(t *testing.T) (*op_e2e.System, *ethclient.Client) { +type faultDisputeConfigOpts func(cfg *op_e2e.SystemConfig) + +func withBatcherStopped() faultDisputeConfigOpts { + return func(cfg *op_e2e.SystemConfig) { + cfg.DisableBatcher = true + } +} + +func withBlobBatches() faultDisputeConfigOpts { + return func(cfg *op_e2e.SystemConfig) { + cfg.DataAvailabilityType = batcherFlags.BlobsType + + genesisActivation := hexutil.Uint64(0) + cfg.DeployConfig.L1CancunTimeOffset = &genesisActivation + cfg.DeployConfig.L2GenesisDeltaTimeOffset = &genesisActivation + cfg.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisActivation + } +} + +func withEcotone() faultDisputeConfigOpts { + return func(cfg *op_e2e.SystemConfig) { + genesisActivation := hexutil.Uint64(0) + cfg.DeployConfig.L1CancunTimeOffset = &genesisActivation + cfg.DeployConfig.L2GenesisDeltaTimeOffset = &genesisActivation + cfg.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisActivation + } +} + +func withSequencerWindowSize(size uint64) faultDisputeConfigOpts { + return func(cfg *op_e2e.SystemConfig) { + cfg.DeployConfig.SequencerWindowSize = size + } +} + +func startFaultDisputeSystem(t *testing.T, opts ...faultDisputeConfigOpts) (*op_e2e.System, *ethclient.Client) { cfg := op_e2e.DefaultSystemConfig(t) delete(cfg.Nodes, "verifier") + for _, opt := range opts { + opt(&cfg) + } + cfg.Nodes["sequencer"].SafeDBPath = t.TempDir() cfg.DeployConfig.SequencerWindowSize = 4 cfg.DeployConfig.FinalizationPeriodSeconds = 2 cfg.SupportL1TimeTravel = true @@ -20,3 +63,12 @@ func startFaultDisputeSystem(t *testing.T) (*op_e2e.System, *ethclient.Client) { require.Nil(t, err, "Error starting up system") return sys, sys.Clients["l1"] } + +func sendKZGPointEvaluationTx(t *testing.T, sys *op_e2e.System, l2Node string, privateKey *ecdsa.PrivateKey) *types.Receipt { + return op_e2e.SendL2Tx(t, sys.Cfg, sys.Clients[l2Node], privateKey, func(opts *op_e2e.TxOpts) { + precompile := common.BytesToAddress([]byte{0x0a}) + opts.Gas = 100_000 + opts.ToAddr = &precompile + opts.Data = common.FromHex("01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a") + }) +} diff --git a/op-e2e/helper.go b/op-e2e/helper.go index 3c8d411b1292..e9e53deac8b1 100644 --- a/op-e2e/helper.go +++ b/op-e2e/helper.go @@ -1,55 +1,79 @@ package op_e2e import ( + "crypto/md5" "os" "strconv" - "testing" + "strings" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ) var enableParallelTesting bool = os.Getenv("OP_E2E_DISABLE_PARALLEL") != "true" -type testopts struct { - executor uint64 -} - -func InitParallel(t *testing.T, args ...func(t *testing.T, opts *testopts)) { +func InitParallel(t e2eutils.TestingBase, args ...func(t e2eutils.TestingBase)) { t.Helper() if enableParallelTesting { t.Parallel() } - - opts := &testopts{} for _, arg := range args { - arg(t, opts) + arg(t) } - checkExecutor(t, opts.executor) + autoAllocateExecutor(t) +} + +// isSubTest determines if the test is a sub-test or top level test. +// It does this by checking if the test name contains / +// This is not a particularly great way check, but appears to be the only option currently. +func isSubTest(t e2eutils.TestingBase) bool { + return strings.Contains(t.Name(), "/") } -func UsesCannon(t *testing.T, opts *testopts) { +func autoAllocateExecutor(t e2eutils.TestingBase) { + if isSubTest(t) { + // Always run subtests, they only start on the same executor as their parent. + return + } + info := getExecutorInfo(t) + tName := t.Name() + tHash := md5.Sum([]byte(tName)) + executor := uint64(tHash[0]) % info.total + checkExecutor(t, info, executor) +} + +func UsesCannon(t e2eutils.TestingBase) { if os.Getenv("OP_E2E_CANNON_ENABLED") == "false" { t.Skip("Skipping cannon test") } } -// UseExecutor allows manually splitting tests between circleci executors -// -// Tests default to run on the first executor but can be moved to the second with: -// InitParallel(t, UseExecutor(1)) -// Any tests assigned to an executor greater than the number available automatically use the last executor. -// Executor indexes start from 0 -func UseExecutor(assignedIdx uint64) func(t *testing.T, opts *testopts) { - return func(t *testing.T, opts *testopts) { - opts.executor = assignedIdx +func SkipOnFPAC(t e2eutils.TestingBase) { + if e2eutils.UseFPAC() { + t.Skip("Skipping test for FPAC") + } +} + +func SkipOnNotFPAC(t e2eutils.TestingBase) { + if !e2eutils.UseFPAC() { + t.Skip("Skipping test for non-FPAC") } } -func checkExecutor(t *testing.T, assignedIdx uint64) { +type executorInfo struct { + total uint64 + idx uint64 + splitInUse bool +} + +func getExecutorInfo(t e2eutils.TestingBase) executorInfo { + var info executorInfo envTotal := os.Getenv("CIRCLE_NODE_TOTAL") envIdx := os.Getenv("CIRCLE_NODE_INDEX") if envTotal == "" || envIdx == "" { // Not using test splitting, so ignore assigned executor - t.Logf("Running test. Test splitting not in use.") - return + t.Logf("Test splitting not in use.") + info.total = 1 + return info } total, err := strconv.ParseUint(envTotal, 10, 0) if err != nil { @@ -59,13 +83,26 @@ func checkExecutor(t *testing.T, assignedIdx uint64) { if err != nil { t.Fatalf("Could not parse CIRCLE_NODE_INDEX env var %v: %v", envIdx, err) } - if assignedIdx >= total && idx == total-1 { - t.Logf("Running test. Current executor (%v) is the last executor and assigned executor (%v) >= total executors (%v).", idx, assignedIdx, total) + + info.total = total + info.idx = idx + info.splitInUse = true + return info +} + +func checkExecutor(t e2eutils.TestingBase, info executorInfo, assignedIdx uint64) { + if !info.splitInUse { + t.Logf("Test splitting not in use.") + return + } + + if assignedIdx >= info.total && info.idx == info.total-1 { + t.Logf("Running test. Current executor (%v) is the last executor and assigned executor (%v) >= total executors (%v).", info.idx, assignedIdx, info.total) return } - if idx == assignedIdx { - t.Logf("Running test. Assigned executor (%v) matches current executor (%v) of total (%v)", assignedIdx, idx, total) + if info.idx == assignedIdx { + t.Logf("Running test. Assigned executor (%v) matches current executor (%v) of total (%v)", assignedIdx, info.idx, info.total) return } - t.Skipf("Skipping test. Assigned executor %v, current executor %v of total %v", assignedIdx, idx, total) + t.Skipf("Skipping test. Assigned executor %v, current executor %v of total %v", assignedIdx, info.idx, info.total) } diff --git a/op-e2e/l1_beacon_client_test.go b/op-e2e/l1_beacon_client_test.go index bf40f40bb765..09cdd4c592d2 100644 --- a/op-e2e/l1_beacon_client_test.go +++ b/op-e2e/l1_beacon_client_test.go @@ -13,7 +13,9 @@ import ( ) func TestGetVersion(t *testing.T) { - l := testlog.Logger(t, log.LvlInfo) + InitParallel(t) + + l := testlog.Logger(t, log.LevelInfo) beaconApi := fakebeacon.NewBeacon(l, t.TempDir(), uint64(0), uint64(0)) t.Cleanup(func() { @@ -21,7 +23,8 @@ func TestGetVersion(t *testing.T) { }) require.NoError(t, beaconApi.Start("127.0.0.1:0")) - cl := sources.NewL1BeaconClient(client.NewBasicHTTPClient(beaconApi.BeaconAddr(), l)) + beaconCfg := sources.L1BeaconClientConfig{FetchAllSidecars: false} + cl := sources.NewL1BeaconClient(sources.NewBeaconHTTPClient(client.NewBasicHTTPClient(beaconApi.BeaconAddr(), l)), beaconCfg) version, err := cl.GetVersion(context.Background()) require.NoError(t, err) diff --git a/op-e2e/op_geth.go b/op-e2e/op_geth.go index ab95986b4e93..c14f62b55d6b 100644 --- a/op-e2e/op_geth.go +++ b/op-e2e/op_geth.go @@ -52,9 +52,9 @@ type OpGeth struct { } func NewOpGeth(t *testing.T, ctx context.Context, cfg *SystemConfig) (*OpGeth, error) { - logger := testlog.Logger(t, log.LvlCrit) + logger := testlog.Logger(t, log.LevelCrit) - l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig, config.L1Allocs, config.L1Deployments, true) + l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig, config.L1Allocs, config.L1Deployments) require.Nil(t, err) l1Block := l1Genesis.ToBlock() @@ -158,7 +158,7 @@ func (d *OpGeth) AddL2Block(ctx context.Context, txs ...*types.Transaction) (*et return nil, err } - envelope, err := d.l2Engine.GetPayload(ctx, *res.PayloadID) + envelope, err := d.l2Engine.GetPayload(ctx, eth.PayloadInfo{ID: *res.PayloadID, Timestamp: uint64(attrs.Timestamp)}) payload := envelope.ExecutionPayload if err != nil { diff --git a/op-e2e/op_geth_test.go b/op-e2e/op_geth_test.go index b117c257681a..717ac285d946 100644 --- a/op-e2e/op_geth_test.go +++ b/op-e2e/op_geth_test.go @@ -199,7 +199,7 @@ func TestGethOnlyPendingBlockIsLatest(t *testing.T) { time.Sleep(time.Second * 4) // conservatively wait 4 seconds, CI might lag during block building. // retrieve the block - envelope, err := opGeth.l2Engine.GetPayload(ctx, *res.PayloadID) + envelope, err := opGeth.l2Engine.GetPayload(ctx, eth.PayloadInfo{ID: *res.PayloadID, Timestamp: uint64(attrs.Timestamp)}) require.NoError(t, err) payload := envelope.ExecutionPayload @@ -226,9 +226,11 @@ func TestGethOnlyPendingBlockIsLatest(t *testing.T) { } func TestPreregolith(t *testing.T) { + t.Skip("peptide crashes when going through the deposit txs is only one error. Many more to go through") InitParallel(t) - futureTimestamp := hexutil.Uint64(4) + + futureTimestamp := hexutil.Uint64(4) tests := []struct { name string regolithTime *hexutil.Uint64 @@ -412,7 +414,6 @@ func TestPreregolith(t *testing.T) { } func TestRegolith(t *testing.T) { - InitParallel(t) tests := []struct { name string regolithTime hexutil.Uint64 @@ -735,7 +736,6 @@ func TestRegolith(t *testing.T) { } func TestPreCanyon(t *testing.T) { - InitParallel(t) futureTimestamp := hexutil.Uint64(4) tests := []struct { @@ -802,8 +802,6 @@ func TestPreCanyon(t *testing.T) { } func TestCanyon(t *testing.T) { - InitParallel(t) - tests := []struct { name string canyonTime hexutil.Uint64 @@ -878,7 +876,6 @@ func TestCanyon(t *testing.T) { } func TestPreEcotone(t *testing.T) { - InitParallel(t) futureTimestamp := hexutil.Uint64(4) tests := []struct { @@ -947,8 +944,6 @@ func TestPreEcotone(t *testing.T) { } func TestEcotone(t *testing.T) { - InitParallel(t) - tests := []struct { name string ecotoneTime hexutil.Uint64 diff --git a/op-e2e/sequencer_failover_setup.go b/op-e2e/sequencer_failover_setup.go index 6a9a3d1ca338..fbc3e1a9e7e8 100644 --- a/op-e2e/sequencer_failover_setup.go +++ b/op-e2e/sequencer_failover_setup.go @@ -15,7 +15,6 @@ import ( "github.com/stretchr/testify/require" bss "github.com/ethereum-optimism/optimism/op-batcher/batcher" - "github.com/ethereum-optimism/optimism/op-batcher/compressor" batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" con "github.com/ethereum-optimism/optimism/op-conductor/conductor" conrpc "github.com/ethereum-optimism/optimism/op-conductor/rpc" @@ -32,10 +31,10 @@ import ( ) const ( - sequencer1Name = "sequencer1" - sequencer2Name = "sequencer2" - sequencer3Name = "sequencer3" - verifierName = "verifier" + Sequencer1Name = "sequencer1" + Sequencer2Name = "sequencer2" + Sequencer3Name = "sequencer3" + VerifierName = "verifier" localhost = "127.0.0.1" ) @@ -52,15 +51,21 @@ func (c *conductor) ConsensusEndpoint() string { } func (c *conductor) RPCEndpoint() string { - return fmt.Sprintf("%s:%d", localhost, c.rpcPort) + return fmt.Sprintf("http://%s:%d", localhost, c.rpcPort) } func setupSequencerFailoverTest(t *testing.T) (*System, map[string]*conductor) { InitParallel(t) ctx := context.Background() + conductorRpcPorts := map[string]int{ + Sequencer1Name: findAvailablePort(t), + Sequencer2Name: findAvailablePort(t), + Sequencer3Name: findAvailablePort(t), + } + // 3 sequencers, 1 verifier, 1 active sequencer. - cfg := sequencerFailoverSystemConfig(t) + cfg := sequencerFailoverSystemConfig(t, conductorRpcPorts) sys, err := cfg.Start(t) require.NoError(t, err) @@ -70,45 +75,56 @@ func setupSequencerFailoverTest(t *testing.T) (*System, map[string]*conductor) { // initialize all conductors in paused mode conductorCfgs := []struct { name string + port int bootstrap bool }{ - {sequencer1Name, true}, // one in bootstrap mode so that we can form a cluster. - {sequencer2Name, false}, - {sequencer3Name, false}, + {Sequencer1Name, conductorRpcPorts[Sequencer1Name], true}, // one in bootstrap mode so that we can form a cluster. + {Sequencer2Name, conductorRpcPorts[Sequencer2Name], false}, + {Sequencer3Name, conductorRpcPorts[Sequencer3Name], false}, } for _, cfg := range conductorCfgs { cfg := cfg nodePRC := sys.RollupNodes[cfg.name].HTTPEndpoint() engineRPC := sys.EthInstances[cfg.name].HTTPEndpoint() - conductors[cfg.name] = setupConductor(t, cfg.name, t.TempDir(), nodePRC, engineRPC, cfg.bootstrap, *sys.RollupConfig) + conductors[cfg.name] = setupConductor(t, cfg.name, t.TempDir(), nodePRC, engineRPC, cfg.port, cfg.bootstrap, *sys.RollupConfig) } - // 1 batcher that listens to all 3 sequencers, in started mode. - setupBatcher(t, sys, conductors) - // form a cluster - c1 := conductors[sequencer1Name] - c2 := conductors[sequencer2Name] - c3 := conductors[sequencer3Name] + c1 := conductors[Sequencer1Name] + c2 := conductors[Sequencer2Name] + c3 := conductors[Sequencer3Name] - require.NoError(t, waitForLeadershipChange(t, c1, true)) - require.NoError(t, c1.client.AddServerAsVoter(ctx, sequencer2Name, c2.ConsensusEndpoint())) - require.NoError(t, c1.client.AddServerAsVoter(ctx, sequencer3Name, c3.ConsensusEndpoint())) + require.NoError(t, waitForLeadership(t, c1)) + require.NoError(t, c1.client.AddServerAsVoter(ctx, Sequencer2Name, c2.ConsensusEndpoint())) + require.NoError(t, c1.client.AddServerAsVoter(ctx, Sequencer3Name, c3.ConsensusEndpoint())) require.True(t, leader(t, ctx, c1)) require.False(t, leader(t, ctx, c2)) require.False(t, leader(t, ctx, c3)) + // start sequencing on leader + lid, _ := findLeader(t, conductors) + unsafeHead, err := sys.Clients[lid].BlockByNumber(ctx, nil) + require.NoError(t, err) + require.Equal(t, uint64(0), unsafeHead.NumberU64()) + require.NoError(t, sys.RollupClient(lid).StartSequencer(ctx, unsafeHead.Hash())) + + // 1 batcher that listens to all 3 sequencers, in started mode. + setupBatcher(t, sys, conductors) + // weirdly, batcher does not submit a batch until unsafe block 9. // It became normal after that and submits a batch every L1 block (2s) per configuration. // Since our health monitor checks on safe head progression, wait for batcher to become normal before proceeding. - require.NoError(t, wait.ForNextSafeBlock(ctx, sys.Clients[sequencer1Name])) - require.NoError(t, wait.ForNextSafeBlock(ctx, sys.Clients[sequencer1Name])) - require.NoError(t, wait.ForNextSafeBlock(ctx, sys.Clients[sequencer1Name])) + _, err = wait.ForNextSafeBlock(ctx, sys.Clients[Sequencer1Name]) + require.NoError(t, err) + _, err = wait.ForNextSafeBlock(ctx, sys.Clients[Sequencer1Name]) + require.NoError(t, err) // make sure conductor reports all sequencers as healthy, this means they're syncing correctly. - require.True(t, healthy(t, ctx, c1)) - require.True(t, healthy(t, ctx, c2)) - require.True(t, healthy(t, ctx, c3)) + require.Eventually(t, func() bool { + return healthy(t, ctx, c1) && + healthy(t, ctx, c2) && + healthy(t, ctx, c3) + }, 30*time.Second, 500*time.Millisecond, "Expected sequencers to become healthy") // unpause all conductors require.NoError(t, c1.client.Resume(ctx)) @@ -120,9 +136,9 @@ func setupSequencerFailoverTest(t *testing.T) (*System, map[string]*conductor) { require.True(t, conductorActive(t, ctx, c2)) require.True(t, conductorActive(t, ctx, c3)) - require.True(t, sequencerActive(t, ctx, sys.RollupClient(sequencer1Name))) - require.False(t, sequencerActive(t, ctx, sys.RollupClient(sequencer2Name))) - require.False(t, sequencerActive(t, ctx, sys.RollupClient(sequencer3Name))) + require.True(t, sequencerActive(t, ctx, sys.RollupClient(Sequencer1Name))) + require.False(t, sequencerActive(t, ctx, sys.RollupClient(Sequencer2Name))) + require.False(t, sequencerActive(t, ctx, sys.RollupClient(Sequencer3Name))) require.True(t, healthy(t, ctx, c1)) require.True(t, healthy(t, ctx, c2)) @@ -134,13 +150,13 @@ func setupSequencerFailoverTest(t *testing.T) (*System, map[string]*conductor) { func setupConductor( t *testing.T, serverID, dir, nodeRPC, engineRPC string, + rpcPort int, bootstrap bool, rollupCfg rollup.Config, ) *conductor { // it's unfortunate that it is not possible to pass 0 as consensus port and get back the actual assigned port from raft implementation. // So we find an available port and pass it in to avoid test flakiness (avoid port already in use error). consensusPort := findAvailablePort(t) - rpcPort := findAvailablePort(t) cfg := con.Config{ ConsensusAddr: localhost, ConsensusPort: consensusPort, @@ -152,13 +168,17 @@ func setupConductor( Paused: true, HealthCheck: con.HealthCheckConfig{ Interval: 1, // per test setup, l2 block time is 1s. - SafeInterval: 4, // per test setup (l1 block time = 2s, max channel duration = 1, 2s buffer) MinPeerCount: 2, // per test setup, each sequencer has 2 peers + // CI is unstable in terms of the delay between now and the head time + // so we set the unsafe interval to 30s to avoid flakiness. + // This is fine because there's a progression check within health monitor to check progression. + UnsafeInterval: 30, + SafeInterval: 30, }, RollupCfg: rollupCfg, RPCEnableProxy: true, LogConfig: oplog.CLIConfig{ - Level: log.LvlInfo, + Level: log.LevelInfo, Color: false, }, RPC: oprpc.CLIConfig{ @@ -168,7 +188,7 @@ func setupConductor( } ctx := context.Background() - service, err := con.New(ctx, &cfg, testlog.Logger(t, log.LvlInfo), "0.0.1") + service, err := con.New(ctx, &cfg, testlog.Logger(t, log.LevelInfo), "0.0.1") require.NoError(t, err) err = service.Start(ctx) require.NoError(t, err) @@ -186,25 +206,18 @@ func setupConductor( } func setupBatcher(t *testing.T, sys *System, conductors map[string]*conductor) { - var batchType uint = derive.SingularBatchType - if sys.Cfg.DeployConfig.L2GenesisDeltaTimeOffset != nil && *sys.Cfg.DeployConfig.L2GenesisDeltaTimeOffset == hexutil.Uint64(0) { - batchType = derive.SpanBatchType - } - batcherMaxL1TxSizeBytes := sys.Cfg.BatcherMaxL1TxSizeBytes - if batcherMaxL1TxSizeBytes == 0 { - batcherMaxL1TxSizeBytes = 240_000 - } - // enable active sequencer follow mode. + // in sequencer HA, all batcher / proposer requests will be proxied by conductor so that we can make sure + // that requests are always handled by leader. l2EthRpc := strings.Join([]string{ - conductors[sequencer1Name].RPCEndpoint(), - conductors[sequencer2Name].RPCEndpoint(), - conductors[sequencer3Name].RPCEndpoint(), + conductors[Sequencer1Name].RPCEndpoint(), + conductors[Sequencer2Name].RPCEndpoint(), + conductors[Sequencer3Name].RPCEndpoint(), }, ",") rollupRpc := strings.Join([]string{ - conductors[sequencer1Name].RPCEndpoint(), - conductors[sequencer2Name].RPCEndpoint(), - conductors[sequencer3Name].RPCEndpoint(), + conductors[Sequencer1Name].RPCEndpoint(), + conductors[Sequencer2Name].RPCEndpoint(), + conductors[Sequencer3Name].RPCEndpoint(), }, ",") batcherCLIConfig := &bss.CLIConfig{ L1EthRpc: sys.EthInstances["l1"].WSEndpoint(), @@ -212,21 +225,18 @@ func setupBatcher(t *testing.T, sys *System, conductors map[string]*conductor) { RollupRpc: rollupRpc, MaxPendingTransactions: 0, MaxChannelDuration: 1, - MaxL1TxSize: batcherMaxL1TxSizeBytes, - CompressorConfig: compressor.CLIConfig{ - TargetL1TxSizeBytes: sys.Cfg.BatcherTargetL1TxSizeBytes, - TargetNumFrames: 1, - ApproxComprRatio: 0.4, - }, - SubSafetyMargin: 0, - PollInterval: 50 * time.Millisecond, - TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), sys.Cfg.Secrets.Batcher), + MaxL1TxSize: 120_000, + TargetNumFrames: 1, + ApproxComprRatio: 0.4, + SubSafetyMargin: 4, + PollInterval: 1 * time.Second, + TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), sys.Cfg.Secrets.Batcher), LogConfig: oplog.CLIConfig{ - Level: log.LvlInfo, + Level: log.LevelDebug, Format: oplog.FormatText, }, Stopped: false, - BatchType: batchType, + BatchType: derive.SpanBatchType, DataAvailabilityType: batcherFlags.CalldataType, ActiveSequencerCheckDuration: 0, } @@ -238,34 +248,38 @@ func setupBatcher(t *testing.T, sys *System, conductors map[string]*conductor) { sys.BatchSubmitter = batcher } -func sequencerFailoverSystemConfig(t *testing.T) SystemConfig { +func sequencerFailoverSystemConfig(t *testing.T, ports map[string]int) SystemConfig { cfg := DefaultSystemConfig(t) delete(cfg.Nodes, "sequencer") - cfg.Nodes[sequencer1Name] = sequencerCfg(true) - cfg.Nodes[sequencer2Name] = sequencerCfg(false) - cfg.Nodes[sequencer3Name] = sequencerCfg(false) + cfg.Nodes[Sequencer1Name] = sequencerCfg(ports[Sequencer1Name]) + cfg.Nodes[Sequencer2Name] = sequencerCfg(ports[Sequencer2Name]) + cfg.Nodes[Sequencer3Name] = sequencerCfg(ports[Sequencer3Name]) delete(cfg.Loggers, "sequencer") - cfg.Loggers[sequencer1Name] = testlog.Logger(t, log.LvlInfo).New("role", sequencer1Name) - cfg.Loggers[sequencer2Name] = testlog.Logger(t, log.LvlInfo).New("role", sequencer2Name) - cfg.Loggers[sequencer3Name] = testlog.Logger(t, log.LvlInfo).New("role", sequencer3Name) + cfg.Loggers[Sequencer1Name] = testlog.Logger(t, log.LevelInfo).New("role", Sequencer1Name) + cfg.Loggers[Sequencer2Name] = testlog.Logger(t, log.LevelInfo).New("role", Sequencer2Name) + cfg.Loggers[Sequencer3Name] = testlog.Logger(t, log.LevelInfo).New("role", Sequencer3Name) cfg.P2PTopology = map[string][]string{ - sequencer1Name: {sequencer2Name, sequencer3Name}, - sequencer2Name: {sequencer3Name, verifierName}, - sequencer3Name: {verifierName, sequencer1Name}, - verifierName: {sequencer1Name, sequencer2Name}, + Sequencer1Name: {Sequencer2Name, Sequencer3Name}, + Sequencer2Name: {Sequencer3Name, VerifierName}, + Sequencer3Name: {VerifierName, Sequencer1Name}, + VerifierName: {Sequencer1Name, Sequencer2Name}, } + offset := hexutil.Uint64(0) + cfg.DeployConfig.L2GenesisDeltaTimeOffset = &offset + cfg.DeployConfig.L2GenesisEcotoneTimeOffset = &offset return cfg } -func sequencerCfg(sequencerEnabled bool) *rollupNode.Config { +func sequencerCfg(rpcPort int) *rollupNode.Config { return &rollupNode.Config{ Driver: driver.Config{ VerifierConfDepth: 0, SequencerConfDepth: 0, - SequencerEnabled: sequencerEnabled, + SequencerEnabled: true, + SequencerStopped: true, }, // Submitter PrivKey is set in system start for rollup nodes where sequencer = true RPC: rollupNode.RPCConfig{ @@ -277,27 +291,62 @@ func sequencerCfg(sequencerEnabled bool) *rollupNode.Config { RuntimeConfigReloadInterval: time.Minute * 10, ConfigPersistence: &rollupNode.DisabledConfigPersistence{}, Sync: sync.Config{SyncMode: sync.CLSync}, + ConductorEnabled: true, + ConductorRpc: fmt.Sprintf("http://%s:%d", localhost, rpcPort), + ConductorRpcTimeout: 1 * time.Second, } } -func waitForLeadershipChange(t *testing.T, c *conductor, leader bool) error { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) +func waitForLeadership(t *testing.T, c *conductor) error { + condition := func() (bool, error) { + isLeader, err := c.client.Leader(context.Background()) + if err != nil { + return false, err + } + return isLeader, nil + } + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - for { - select { - case <-ctx.Done(): - return ctx.Err() - default: - isLeader, err := c.client.Leader(ctx) - if err != nil { - return err - } - if isLeader == leader { - return nil - } - time.Sleep(500 * time.Millisecond) + return wait.For(ctx, 1*time.Second, condition) +} + +func waitForLeadershipChange(t *testing.T, prev *conductor, prevID string, conductors map[string]*conductor, sys *System) string { + condition := func() (bool, error) { + isLeader, err := prev.client.Leader(context.Background()) + if err != nil { + return false, err } + return !isLeader, nil } + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + err := wait.For(ctx, 1*time.Second, condition) + require.NoError(t, err) + + ensureOnlyOneLeader(t, sys, conductors) + newLeader, err := prev.client.LeaderWithID(ctx) + require.NoError(t, err) + require.NotEmpty(t, newLeader.ID) + require.NotEqual(t, prevID, newLeader.ID, "Expected a new leader") + require.NoError(t, waitForSequencerStatusChange(t, sys.RollupClient(newLeader.ID), true)) + + return newLeader.ID +} + +func waitForSequencerStatusChange(t *testing.T, rollupClient *sources.RollupClient, active bool) error { + condition := func() (bool, error) { + isActive, err := rollupClient.SequencerActive(context.Background()) + if err != nil { + return false, err + } + return isActive == active, nil + } + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + return wait.For(ctx, 1*time.Second, condition) } func leader(t *testing.T, ctx context.Context, con *conductor) bool { @@ -332,7 +381,8 @@ func findAvailablePort(t *testing.T) int { case <-ctx.Done(): t.Error("Failed to find available port") default: - port := rand.Intn(65535-1024) + 1024 // Random port in the range 1024-65535 + // private / ephemeral ports are in the range 49152-65535 + port := rand.Intn(65535-49152) + 49152 addr := fmt.Sprintf("127.0.0.1:%d", port) l, err := net.Listen("tcp", addr) if err == nil { @@ -342,3 +392,47 @@ func findAvailablePort(t *testing.T) int { } } } + +func findLeader(t *testing.T, conductors map[string]*conductor) (string, *conductor) { + for id, con := range conductors { + if leader(t, context.Background(), con) { + return id, con + } + } + return "", nil +} + +func findFollower(t *testing.T, conductors map[string]*conductor) (string, *conductor) { + for id, con := range conductors { + if !leader(t, context.Background(), con) { + return id, con + } + } + return "", nil +} + +func ensureOnlyOneLeader(t *testing.T, sys *System, conductors map[string]*conductor) { + condition := func() (bool, error) { + leaders := 0 + ctx := context.Background() + for name, con := range conductors { + leader, err := con.client.Leader(ctx) + if err != nil { + continue + } + active, err := sys.RollupClient(name).SequencerActive(ctx) + if err != nil { + continue + } + + if leader && active { + leaders++ + } + } + return leaders == 1, nil + } + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + require.NoError(t, wait.For(ctx, 1*time.Second, condition)) +} diff --git a/op-e2e/sequencer_failover_test.go b/op-e2e/sequencer_failover_test.go index 348aea6671ea..a07266e533dc 100644 --- a/op-e2e/sequencer_failover_test.go +++ b/op-e2e/sequencer_failover_test.go @@ -1,15 +1,18 @@ package op_e2e import ( + "context" + "sort" "testing" "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/optimism/op-conductor/consensus" ) // [Category: Initial Setup] // In this test, we test that we can successfully setup a working cluster. func TestSequencerFailover_SetupCluster(t *testing.T) { - t.Skip("temporarily disable due to flakiness for now") sys, conductors := setupSequencerFailoverTest(t) defer sys.Close() @@ -18,3 +21,146 @@ func TestSequencerFailover_SetupCluster(t *testing.T) { require.NotNil(t, con, "Expected conductor to be non-nil") } } + +// [Category: conductor rpc] +// In this test, we test all rpcs exposed by conductor. +func TestSequencerFailover_ConductorRPC(t *testing.T) { + ctx := context.Background() + sys, conductors := setupSequencerFailoverTest(t) + defer sys.Close() + + // SequencerHealthy, Leader, AddServerAsVoter are used in setup already. + + // Test ClusterMembership + t.Log("Testing ClusterMembership") + c1 := conductors[Sequencer1Name] + c2 := conductors[Sequencer2Name] + c3 := conductors[Sequencer3Name] + membership, err := c1.client.ClusterMembership(ctx) + require.NoError(t, err) + require.Equal(t, 3, len(membership), "Expected 3 members in cluster") + ids := make([]string, 0) + for _, member := range membership { + ids = append(ids, member.ID) + require.Equal(t, consensus.Voter, member.Suffrage, "Expected all members to be voters") + } + sort.Strings(ids) + require.Equal(t, []string{Sequencer1Name, Sequencer2Name, Sequencer3Name}, ids, "Expected all sequencers to be in cluster") + + // Test Active & Pause & Resume + t.Log("Testing Active & Pause & Resume") + active, err := c1.client.Active(ctx) + require.NoError(t, err) + require.True(t, active, "Expected conductor to be active") + + err = c1.client.Pause(ctx) + require.NoError(t, err) + active, err = c1.client.Active(ctx) + require.NoError(t, err) + require.False(t, active, "Expected conductor to be paused") + + err = c1.client.Resume(ctx) + require.NoError(t, err) + active, err = c1.client.Active(ctx) + require.NoError(t, err) + require.True(t, active, "Expected conductor to be active") + + t.Log("Testing LeaderWithID") + leader1, err := c1.client.LeaderWithID(ctx) + require.NoError(t, err) + leader2, err := c2.client.LeaderWithID(ctx) + require.NoError(t, err) + leader3, err := c3.client.LeaderWithID(ctx) + require.NoError(t, err) + require.Equal(t, leader1.ID, leader2.ID, "Expected leader ID to be the same") + require.Equal(t, leader1.ID, leader3.ID, "Expected leader ID to be the same") + + t.Log("Testing TransferLeader") + lid, leader := findLeader(t, conductors) + err = leader.client.TransferLeader(ctx) + require.NoError(t, err, "Expected leader to transfer leadership to another node") + _ = waitForLeadershipChange(t, leader, lid, conductors, sys) + + // old leader now became follower, we're trying to transfer leadership directly back to it. + t.Log("Testing TransferLeaderToServer") + fid, follower := lid, leader + lid, leader = findLeader(t, conductors) + err = leader.client.TransferLeaderToServer(ctx, fid, follower.ConsensusEndpoint()) + require.NoError(t, err, "Expected leader to transfer leadership to follower") + newID := waitForLeadershipChange(t, leader, lid, conductors, sys) + require.Equal(t, fid, newID, "Expected leader to transfer to %s", fid) + + leader = follower + + // Test AddServerAsNonvoter, do not start a new sequencer just for this purpose, use Sequencer3's rpc to start conductor. + // This is fine as this mainly tests conductor's ability to add itself into the raft consensus cluster as a nonvoter. + t.Log("Testing AddServerAsNonvoter") + nonvoter := setupConductor( + t, VerifierName, t.TempDir(), + sys.RollupEndpoint(Sequencer3Name), + sys.NodeEndpoint(Sequencer3Name), + findAvailablePort(t), + false, + *sys.RollupConfig, + ) + + err = leader.client.AddServerAsNonvoter(ctx, VerifierName, nonvoter.ConsensusEndpoint()) + require.NoError(t, err, "Expected leader to add non-voter") + membership, err = leader.client.ClusterMembership(ctx) + require.NoError(t, err) + require.Equal(t, 4, len(membership), "Expected 4 members in cluster") + require.Equal(t, consensus.Nonvoter, membership[3].Suffrage, "Expected last member to be non-voter") + + t.Log("Testing RemoveServer, call remove on follower, expected to fail") + lid, leader = findLeader(t, conductors) + fid, follower = findFollower(t, conductors) + err = follower.client.RemoveServer(ctx, lid) + require.ErrorContains(t, err, "node is not the leader", "Expected follower to fail to remove leader") + membership, err = c1.client.ClusterMembership(ctx) + require.NoError(t, err) + require.Equal(t, 4, len(membership), "Expected 4 members in cluster") + + t.Log("Testing RemoveServer, call remove on leader, expect non-voter to be removed") + err = leader.client.RemoveServer(ctx, VerifierName) + require.NoError(t, err, "Expected leader to remove non-voter") + membership, err = c1.client.ClusterMembership(ctx) + require.NoError(t, err) + require.Equal(t, 3, len(membership), "Expected 2 members in cluster after removal") + require.NotContains(t, membership, VerifierName, "Expected follower to be removed from cluster") + + t.Log("Testing RemoveServer, call remove on leader, expect voter to be removed") + err = leader.client.RemoveServer(ctx, fid) + require.NoError(t, err, "Expected leader to remove follower") + membership, err = c1.client.ClusterMembership(ctx) + require.NoError(t, err) + require.Equal(t, 2, len(membership), "Expected 2 members in cluster after removal") + require.NotContains(t, membership, fid, "Expected follower to be removed from cluster") +} + +// [Category: Sequencer Failover] +// Test that the sequencer can successfully failover to a new sequencer once the active sequencer goes down. +func TestSequencerFailover_ActiveSequencerDown(t *testing.T) { + sys, conductors := setupSequencerFailoverTest(t) + defer sys.Close() + + ctx := context.Background() + leaderId, leader := findLeader(t, conductors) + err := sys.RollupNodes[leaderId].Stop(ctx) // Stop the current leader sequencer + require.NoError(t, err) + + // The leadership change should occur with no errors + newID := waitForLeadershipChange(t, leader, leaderId, conductors, sys) + require.NotEqual(t, leaderId, newID, "Expected leader to change") + + // Confirm the new leader is different from the old leader + newLeaderId, _ := findLeader(t, conductors) + require.NotEqual(t, leaderId, newLeaderId, "Expected leader to change") + + // Check that the sequencer is healthy + require.True(t, healthy(t, ctx, conductors[newLeaderId])) + + // Check if the new leader is sequencing + active, err := sys.RollupClient(newLeaderId).SequencerActive(ctx) + require.NoError(t, err) + require.True(t, active, "Expected new leader to be sequencing") +} diff --git a/op-e2e/setup.go b/op-e2e/setup.go index ff23d69fb244..d6de10fcb78d 100644 --- a/op-e2e/setup.go +++ b/op-e2e/setup.go @@ -16,6 +16,7 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/batcher" ds "github.com/ipfs/go-datastore" dsSync "github.com/ipfs/go-datastore/sync" ic "github.com/libp2p/go-libp2p/core/crypto" @@ -38,7 +39,6 @@ import ( "github.com/ethereum/go-ethereum/rpc" bss "github.com/ethereum-optimism/optimism/op-batcher/batcher" - "github.com/ethereum-optimism/optimism/op-batcher/compressor" batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" @@ -57,6 +57,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup/sync" l2os "github.com/ethereum-optimism/optimism/op-proposer/proposer" "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/ethereum-optimism/optimism/op-service/client" "github.com/ethereum-optimism/optimism/op-service/clock" "github.com/ethereum-optimism/optimism/op-service/dial" "github.com/ethereum-optimism/optimism/op-service/eth" @@ -66,9 +67,7 @@ import ( "github.com/ethereum-optimism/optimism/op-service/txmgr" ) -var ( - testingJWTSecret = [32]byte{123} -) +var testingJWTSecret = [32]byte{123} func newTxMgrConfig(l1Addr string, privKey *ecdsa.PrivateKey) txmgr.CLIConfig { return txmgr.CLIConfig{ @@ -94,7 +93,7 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { e2eutils.ApplyDeployConfigForks(deployConfig) require.NoError(t, deployConfig.Check(), "Deploy config is invalid, do you need to run make devnet-allocs?") l1Deployments := config.L1Deployments.Copy() - require.NoError(t, l1Deployments.Check()) + require.NoError(t, l1Deployments.Check(deployConfig)) require.Equal(t, secrets.Addresses().Batcher, deployConfig.BatchSenderAddress) require.Equal(t, secrets.Addresses().SequencerP2P, deployConfig.P2PSequencerAddress) @@ -146,17 +145,18 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { }, }, 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"), + "verifier": testlog.Logger(t, log.LevelInfo).New("role", "verifier"), + "sequencer": testlog.Logger(t, log.LevelInfo).New("role", "sequencer"), + "batcher": testlog.Logger(t, log.LevelInfo).New("role", "batcher"), + "proposer": testlog.Logger(t, log.LevelCrit).New("role", "proposer"), }, - GethOptions: map[string][]geth.GethOption{}, - P2PTopology: nil, // no P2P connectivity by default - NonFinalizedProposals: false, - ExternalL2Shim: config.ExternalL2Shim, - BatcherTargetL1TxSizeBytes: 100_000, - DataAvailabilityType: batcherFlags.CalldataType, + GethOptions: map[string][]geth.GethOption{}, + P2PTopology: nil, // no P2P connectivity by default + NonFinalizedProposals: false, + ExternalL2Shim: config.ExternalL2Shim, + DataAvailabilityType: batcherFlags.CalldataType, + MaxPendingTransactions: 1, + BatcherTargetNumFrames: 1, } } @@ -212,14 +212,23 @@ type SystemConfig struct { // Configure data-availability type that is used by the batcher. DataAvailabilityType batcherFlags.DataAvailabilityType - // Target L1 tx size for the batcher transactions - BatcherTargetL1TxSizeBytes uint64 - // Max L1 tx size for the batcher transactions BatcherMaxL1TxSizeBytes uint64 + // Target number of frames to create per channel. Can be used to create + // multi-blob transactions. + // Default is 1 if unset. + BatcherTargetNumFrames int + + // whether to actually use BatcherMaxL1TxSizeBytes for blobs, insteaf of max blob size + BatcherUseMaxTxSizeForBlobs bool + // SupportL1TimeTravel determines if the L1 node supports quickly skipping forward in time SupportL1TimeTravel bool + + // MaxPendingTransactions determines how many transactions the batcher will try to send + // concurrently. 0 means unlimited. + MaxPendingTransactions uint64 } type GethInstance struct { @@ -299,6 +308,23 @@ type System struct { rollupClients map[string]*sources.RollupClient } +// AdvanceTime advances the system clock by the given duration. +// If the [System.TimeTravelClock] is nil, this is a no-op. +func (sys *System) AdvanceTime(d time.Duration) { + if sys.TimeTravelClock != nil { + sys.TimeTravelClock.AdvanceTime(d) + } +} + +func (sys *System) L1BeaconEndpoint() string { + return sys.L1BeaconAPIAddr +} + +func (sys *System) L1BeaconHTTPClient() *sources.BeaconHTTPClient { + logger := testlog.Logger(sys.t, log.LevelInfo).New("component", "beaconClient") + return sources.NewBeaconHTTPClient(client.NewBasicHTTPClient(sys.L1BeaconEndpoint(), logger)) +} + func (sys *System) NodeEndpoint(name string) string { return selectEndpoint(sys.EthInstances[name]) } @@ -316,7 +342,7 @@ func (sys *System) RollupClient(name string) *sources.RollupClient { if ok { return client } - logger := testlog.Logger(sys.t, log.LvlInfo).New("rollupClient", name) + logger := testlog.Logger(sys.t, log.LevelInfo).New("rollupClient", name) endpoint := sys.RollupEndpoint(name) client, err := dial.DialRollupClientWithTimeout(context.Background(), 30*time.Second, logger, endpoint) require.NoErrorf(sys.t, err, "Failed to dial rollup client %v", name) @@ -336,6 +362,11 @@ func (sys *System) L2Genesis() *core.Genesis { return sys.L2GenesisCfg } +func (sys *System) L1Slot(l1Timestamp uint64) uint64 { + return (l1Timestamp - uint64(sys.Cfg.DeployConfig.L1GenesisBlockTimestamp)) / + sys.Cfg.DeployConfig.L1BlockTime +} + func (sys *System) Close() { if !sys.closed.CompareAndSwap(false, true) { // Already closed. @@ -436,7 +467,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste return nil, err } - l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig, config.L1Allocs, config.L1Deployments, true) + l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig, config.L1Allocs, config.L1Deployments) if err != nil { return nil, err } @@ -518,7 +549,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste sys.RollupConfig = &defaultConfig // Create a fake Beacon node to hold on to blobs created by the L1 miner, and to serve them to L2 - bcn := fakebeacon.NewBeacon(testlog.Logger(t, log.LvlInfo).New("role", "l1_cl"), + bcn := fakebeacon.NewBeacon(testlog.Logger(t, log.LevelInfo).New("role", "l1_cl"), path.Join(cfg.BlobsPath, "l1_cl"), l1Genesis.Timestamp, cfg.DeployConfig.L1BlockTime) t.Cleanup(func() { _ = bcn.Close() @@ -664,8 +695,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste } // Don't log state snapshots in test output - snapLog := log.New() - snapLog.SetHandler(log.DiscardHandler()) + snapLog := log.NewLogger(log.DiscardHandler()) // Rollup nodes @@ -755,17 +785,35 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste } // L2Output Submitter - proposerCLIConfig := &l2os.CLIConfig{ - L1EthRpc: sys.EthInstances["l1"].WSEndpoint(), - RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(), - L2OOAddress: config.L1Deployments.L2OutputOracleProxy.Hex(), - PollInterval: 50 * time.Millisecond, - TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), cfg.Secrets.Proposer), - AllowNonFinalized: cfg.NonFinalizedProposals, - LogConfig: oplog.CLIConfig{ - Level: log.LvlInfo, - Format: oplog.FormatText, - }, + var proposerCLIConfig *l2os.CLIConfig + if e2eutils.UseFPAC() { + proposerCLIConfig = &l2os.CLIConfig{ + L1EthRpc: sys.EthInstances["l1"].WSEndpoint(), + RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(), + DGFAddress: config.L1Deployments.DisputeGameFactoryProxy.Hex(), + ProposalInterval: 6 * time.Second, + DisputeGameType: 0, + PollInterval: 50 * time.Millisecond, + TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), cfg.Secrets.Proposer), + AllowNonFinalized: cfg.NonFinalizedProposals, + LogConfig: oplog.CLIConfig{ + Level: log.LvlInfo, + Format: oplog.FormatText, + }, + } + } else { + proposerCLIConfig = &l2os.CLIConfig{ + L1EthRpc: sys.EthInstances["l1"].WSEndpoint(), + RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(), + L2OOAddress: config.L1Deployments.L2OutputOracleProxy.Hex(), + PollInterval: 50 * time.Millisecond, + TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), cfg.Secrets.Proposer), + AllowNonFinalized: cfg.NonFinalizedProposals, + LogConfig: oplog.CLIConfig{ + Level: log.LvlInfo, + Format: oplog.FormatText, + }, + } } proposer, err := l2os.ProposerServiceFromCLIConfig(context.Background(), "0.0.1", proposerCLIConfig, sys.Cfg.Loggers["proposer"]) if err != nil { @@ -780,27 +828,30 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste if cfg.DeployConfig.L2GenesisDeltaTimeOffset != nil && *cfg.DeployConfig.L2GenesisDeltaTimeOffset == hexutil.Uint64(0) { batchType = derive.SpanBatchType } + // batcher defaults if unset batcherMaxL1TxSizeBytes := cfg.BatcherMaxL1TxSizeBytes if batcherMaxL1TxSizeBytes == 0 { - batcherMaxL1TxSizeBytes = 240_000 + batcherMaxL1TxSizeBytes = 120_000 + } + batcherTargetNumFrames := cfg.BatcherTargetNumFrames + if batcherTargetNumFrames == 0 { + batcherTargetNumFrames = 1 } batcherCLIConfig := &bss.CLIConfig{ - L1EthRpc: sys.EthInstances["l1"].WSEndpoint(), - L2EthRpc: sys.EthInstances["sequencer"].WSEndpoint(), - RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(), - MaxPendingTransactions: 0, - MaxChannelDuration: 1, - MaxL1TxSize: batcherMaxL1TxSizeBytes, - CompressorConfig: compressor.CLIConfig{ - TargetL1TxSizeBytes: cfg.BatcherTargetL1TxSizeBytes, - TargetNumFrames: 1, - ApproxComprRatio: 0.4, - }, - SubSafetyMargin: 4, - PollInterval: 50 * time.Millisecond, - TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), cfg.Secrets.Batcher), + L1EthRpc: sys.EthInstances["l1"].WSEndpoint(), + L2EthRpc: sys.EthInstances["sequencer"].WSEndpoint(), + RollupRpc: sys.RollupNodes["sequencer"].HTTPEndpoint(), + MaxPendingTransactions: cfg.MaxPendingTransactions, + MaxChannelDuration: 1, + MaxL1TxSize: batcherMaxL1TxSizeBytes, + TestUseMaxTxSizeForBlobs: cfg.BatcherUseMaxTxSizeForBlobs, + TargetNumFrames: int(batcherTargetNumFrames), + ApproxComprRatio: 0.4, + SubSafetyMargin: 4, + PollInterval: 50 * time.Millisecond, + TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), cfg.Secrets.Batcher), LogConfig: oplog.CLIConfig{ - Level: log.LvlInfo, + Level: log.LevelInfo, Format: oplog.FormatText, }, Stopped: sys.Cfg.DisableBatcher, // Batch submitter may be enabled later @@ -865,6 +916,10 @@ func (sys *System) newMockNetPeer() (host.Host, error) { return sys.Mocknet.AddPeerWithPeerstore(p, eps) } +func (sys *System) BatcherHelper() *batcher.Helper { + return batcher.NewHelper(sys.t, sys.Cfg.Secrets.Batcher, sys.RollupConfig, sys.NodeClient("l1")) +} + func UseHTTP() bool { return os.Getenv("OP_E2E_USE_HTTP") == "true" } diff --git a/op-e2e/system_fpp_test.go b/op-e2e/system_fpp_test.go index e517d2b5cab6..1997250ceee5 100644 --- a/op-e2e/system_fpp_test.go +++ b/op-e2e/system_fpp_test.go @@ -104,7 +104,7 @@ func testVerifyL2OutputRootEmptyBlock(t *testing.T, detached bool, spanBatchActi require.Nil(t, err, "Error starting up system") defer sys.Close() - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) l1Client := sys.Clients["l1"] @@ -203,7 +203,7 @@ func testVerifyL2OutputRoot(t *testing.T, detached bool, spanBatchActivated bool require.Nil(t, err, "Error starting up system") defer sys.Close() - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) l1Client := sys.Clients["l1"] @@ -296,7 +296,7 @@ func testFaultProofProgramScenario(t *testing.T, ctx context.Context, sys *Syste // Check the FPP confirms the expected output t.Log("Running fault proof in fetching mode") - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) err := opp.FaultProofProgram(ctx, log, fppConfig) require.NoError(t, err) diff --git a/op-e2e/system_test.go b/op-e2e/system_test.go index 904ba26ac1bb..8e2de77a0854 100644 --- a/op-e2e/system_test.go +++ b/op-e2e/system_test.go @@ -10,6 +10,7 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -90,7 +91,7 @@ func TestMain(m *testing.M) { } func TestL2OutputSubmitter(t *testing.T) { - InitParallel(t) + InitParallel(t, SkipOnFPAC) cfg := DefaultSystemConfig(t) cfg.NonFinalizedProposals = true // speed up the time till we see output proposals @@ -142,7 +143,7 @@ func TestL2OutputSubmitter(t *testing.T) { // // NOTE: This assertion will change once the L2 output format is // finalized. - ctx, cancel := context.WithTimeout(context.Background(), time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() l2Output, err := rollupClient.OutputAtBlock(ctx, l2ooBlockNumber.Uint64()) require.Nil(t, err) @@ -158,6 +159,66 @@ func TestL2OutputSubmitter(t *testing.T) { } } +func TestL2OutputSubmitterFPAC(t *testing.T) { + InitParallel(t, SkipOnNotFPAC) + + cfg := DefaultSystemConfig(t) + cfg.NonFinalizedProposals = true // speed up the time till we see output proposals + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + defer sys.Close() + + l1Client := sys.Clients["l1"] + + rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["sequencer"].HTTPEndpoint()) + require.Nil(t, err) + rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient)) + + disputeGameFactory, err := bindings.NewDisputeGameFactoryCaller(cfg.L1Deployments.DisputeGameFactoryProxy, l1Client) + require.Nil(t, err) + + initialGameCount, err := disputeGameFactory.GameCount(&bind.CallOpts{}) + require.Nil(t, err) + + l2Verif := sys.Clients["verifier"] + _, err = geth.WaitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) + require.Nil(t, err) + + timeoutCh := time.After(15 * time.Second) + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + for { + latestGameCount, err := disputeGameFactory.GameCount(&bind.CallOpts{}) + require.Nil(t, err) + + if latestGameCount.Cmp(initialGameCount) > 0 { + committedL2Output, err := disputeGameFactory.GameAtIndex(&bind.CallOpts{}, new(big.Int).Sub(latestGameCount, common.Big1)) + require.Nil(t, err) + proxy, err := bindings.NewFaultDisputeGameCaller(committedL2Output.Proxy, l1Client) + require.Nil(t, err) + committedOutputRoot, err := proxy.RootClaim(&bind.CallOpts{}) + require.Nil(t, err) + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + extradata, err := proxy.ExtraData(&bind.CallOpts{}) + require.Nil(t, err) + gameBlockNumber := new(big.Int).SetBytes(extradata[0:32]) + l2Output, err := rollupClient.OutputAtBlock(ctx, gameBlockNumber.Uint64()) + require.Nil(t, err) + require.Equal(t, l2Output.OutputRoot[:], committedOutputRoot[:]) + break + } + + select { + case <-timeoutCh: + t.Fatalf("State root oracle not updated") + case <-ticker.C: + } + } +} + func TestSystemE2EDencunAtGenesis(t *testing.T) { InitParallel(t) @@ -176,10 +237,13 @@ func TestSystemE2EDencunAtGenesis(t *testing.T) { // TestSystemE2EDencunAtGenesis tests if L2 finalizes when blobs are present on L1 func TestSystemE2EDencunAtGenesisWithBlobs(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + InitParallel(t) cfg := DefaultSystemConfig(t) - //cancun is on from genesis: + // cancun is on from genesis: genesisActivation := hexutil.Uint64(0) cfg.DeployConfig.L1CancunTimeOffset = &genesisActivation // i.e. turn cancun on at genesis time + 0 @@ -199,7 +263,7 @@ func TestSystemE2EDencunAtGenesisWithBlobs(t *testing.T) { err = l1Client.SendTransaction(sendCtx, tx) require.NoError(t, err, "Sending L1 empty blob tx") // Wait for transaction on L1 - blockContainsBlob, err := geth.WaitForTransaction(tx.Hash(), l1Client, 30*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + blockContainsBlob, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash()) require.Nil(t, err, "Waiting for blob tx on L1") // end sending blob-containing txns on l1 l2Client := sys.Clients["sequencer"] @@ -225,7 +289,7 @@ func TestSystemE2E(t *testing.T) { } func runE2ESystemTest(t *testing.T, sys *System) { - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) l1Client := sys.Clients["l1"] @@ -308,7 +372,7 @@ func TestConfirmationDepth(t *testing.T) { require.Nil(t, err, "Error starting up system") defer sys.Close() - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) l1Client := sys.Clients["l1"] @@ -320,7 +384,7 @@ func TestConfirmationDepth(t *testing.T) { <-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) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() l1Head, err := l1Client.BlockByNumber(ctx, nil) require.NoError(t, err) @@ -366,14 +430,14 @@ func TestPendingGasLimit(t *testing.T) { require.Nil(t, err, "Error starting up system") defer sys.Close() - log := testlog.Logger(t, log.LvlInfo) + log := testlog.Logger(t, log.LevelInfo) log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) l2Verif := sys.Clients["verifier"] l2Seq := sys.Clients["sequencer"] checkGasLimit := func(client *ethclient.Client, number *big.Int, expected uint64) *types.Header { - ctx, cancel := context.WithTimeout(context.Background(), time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) header, err := client.HeaderByNumber(ctx, number) cancel() require.NoError(t, err) @@ -453,7 +517,7 @@ func TestMissingBatchE2E(t *testing.T) { require.Nil(t, err, "Waiting for block on verifier") // Assert that the transaction is not found on the verifier - ctx, cancel := context.WithTimeout(context.Background(), time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() _, err = l2Verif.TransactionReceipt(ctx, receipt.TxHash) require.Equal(t, ethereum.NotFound, err, "Found transaction in verifier when it should not have been included") @@ -463,7 +527,7 @@ func TestMissingBatchE2E(t *testing.T) { require.Nil(t, err, "timeout waiting for L2 reorg on sequencer safe head") // Assert that the reconciliation process did an L2 reorg on the sequencer to remove the invalid block - ctx2, cancel := context.WithTimeout(context.Background(), time.Second) + ctx2, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() block, err := l2Seq.BlockByNumber(ctx2, receipt.BlockNumber) if err != nil { @@ -475,7 +539,7 @@ func TestMissingBatchE2E(t *testing.T) { func L1InfoFromState(ctx context.Context, contract *bindings.L1Block, l2Number *big.Int, ecotone bool) (*derive.L1BlockInfo, error) { var err error - var out = &derive.L1BlockInfo{} + out := &derive.L1BlockInfo{} opts := bind.CallOpts{ BlockNumber: l2Number, Context: ctx, @@ -624,14 +688,19 @@ func TestSystemMockP2P(t *testing.T) { // Verify that everything that was received was published require.GreaterOrEqual(t, len(published), len(received)) - require.ElementsMatch(t, received, published[:len(received)]) + require.Subset(t, published, received) // Verify that the tx was received via p2p require.Contains(t, received, receiptSeq.BlockHash) } func TestSystemP2PAltSync(t *testing.T) { + t.Skip("fails with: the method eth_sendRawTransaction does not exist/is not available") + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + InitParallel(t) cfg := DefaultSystemConfig(t) @@ -655,8 +724,8 @@ func TestSystemP2PAltSync(t *testing.T) { }, L1EpochPollInterval: time.Second * 4, } - cfg.Loggers["alice"] = testlog.Logger(t, log.LvlInfo).New("role", "alice") - cfg.Loggers["bob"] = testlog.Logger(t, log.LvlInfo).New("role", "bob") + cfg.Loggers["alice"] = testlog.Logger(t, log.LevelInfo).New("role", "alice") + cfg.Loggers["bob"] = testlog.Logger(t, log.LevelInfo).New("role", "bob") // connect the nodes cfg.P2PTopology = map[string][]string{ @@ -699,9 +768,8 @@ func TestSystemP2PAltSync(t *testing.T) { time.Sleep(time.Second * 10) // set up our syncer node, connect it to alice/bob - cfg.Loggers["syncer"] = testlog.Logger(t, log.LvlInfo).New("role", "syncer") - snapLog := log.New() - snapLog.SetHandler(log.DiscardHandler()) + cfg.Loggers["syncer"] = testlog.Logger(t, log.LevelInfo).New("role", "syncer") + snapLog := log.NewLogger(log.DiscardHandler()) // Create a peer, and hook up alice and bob h, err := sys.newMockNetPeer() @@ -739,10 +807,13 @@ func TestSystemP2PAltSync(t *testing.T) { configureL2(syncNodeCfg, syncerL2Engine, cfg.JWTSecret) - syncerNode, err := rollupNode.New(context.Background(), syncNodeCfg, cfg.Loggers["syncer"], snapLog, "", metrics.NewMetrics("")) + syncerNode, err := rollupNode.New(ctx, syncNodeCfg, cfg.Loggers["syncer"], snapLog, "", metrics.NewMetrics("")) require.NoError(t, err) - err = syncerNode.Start(context.Background()) + err = syncerNode.Start(ctx) require.NoError(t, err) + defer func() { + require.NoError(t, syncerNode.Stop(ctx)) + }() // connect alice and bob to our new syncer node _, err = sys.Mocknet.ConnectPeers(sys.RollupNodes["alice"].P2P().Host().ID(), syncerNode.P2P().Host().ID()) @@ -754,7 +825,7 @@ func TestSystemP2PAltSync(t *testing.T) { l2Verif := ethclient.NewClient(rpc) // It may take a while to sync, but eventually we should see the sequenced data show up - receiptVerif, err := geth.WaitForTransaction(receiptSeq.TxHash, l2Verif, 100*time.Duration(sys.RollupConfig.BlockTime)*time.Second) + receiptVerif, err := wait.ForReceiptOK(ctx, l2Verif, receiptSeq.TxHash) require.Nil(t, err, "Waiting for L2 tx on verifier") require.Equal(t, receiptSeq, receiptVerif) @@ -764,7 +835,7 @@ func TestSystemP2PAltSync(t *testing.T) { // Verify that everything that was received was published require.GreaterOrEqual(t, len(published), len(syncedPayloads)) - require.ElementsMatch(t, syncedPayloads, published[:len(syncedPayloads)]) + require.Subset(t, published, syncedPayloads) } // TestSystemDenseTopology sets up a dense p2p topology with 3 verifier nodes and 1 sequencer node. @@ -795,8 +866,8 @@ func TestSystemDenseTopology(t *testing.T) { }, L1EpochPollInterval: time.Second * 4, } - cfg.Loggers["verifier2"] = testlog.Logger(t, log.LvlInfo).New("role", "verifier") - cfg.Loggers["verifier3"] = testlog.Logger(t, log.LvlInfo).New("role", "verifier") + cfg.Loggers["verifier2"] = testlog.Logger(t, log.LevelInfo).New("role", "verifier") + cfg.Loggers["verifier3"] = testlog.Logger(t, log.LevelInfo).New("role", "verifier") // connect the nodes cfg.P2PTopology = map[string][]string{ @@ -974,7 +1045,6 @@ func TestL1InfoContract(t *testing.T) { checkInfoList("On sequencer with state", l1InfosFromSequencerState) checkInfoList("On verifier with tx", l1InfosFromVerifierTransactions) checkInfoList("On verifier with state", l1InfosFromVerifierState) - } // calcGasFees determines the actual cost of the transaction given a specific base fee @@ -1015,7 +1085,7 @@ func TestWithdrawals(t *testing.T) { require.Nil(t, err) // Start L2 balance - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() startBalanceBeforeDeposit, err := l2Verif.BalanceAt(ctx, fromAddr, nil) require.Nil(t, err) @@ -1028,7 +1098,7 @@ func TestWithdrawals(t *testing.T) { }) // Confirm L2 balance - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) defer cancel() endBalanceAfterDeposit, err := wait.ForBalanceChange(ctx, l2Verif, fromAddr, startBalanceBeforeDeposit) require.Nil(t, err) @@ -1038,7 +1108,7 @@ func TestWithdrawals(t *testing.T) { require.Equal(t, mintAmount, diff, "Did not get expected balance change after mint") // Start L2 balance for withdrawal - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) defer cancel() startBalanceBeforeWithdrawal, err := l2Seq.BalanceAt(ctx, fromAddr, nil) require.Nil(t, err) @@ -1050,12 +1120,12 @@ func TestWithdrawals(t *testing.T) { }) // Verify L2 balance after withdrawal - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) defer cancel() header, err := l2Verif.HeaderByNumber(ctx, receipt.BlockNumber) require.Nil(t, err) - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) defer cancel() endBalanceAfterWithdrawal, err := wait.ForBalanceChange(ctx, l2Seq, fromAddr, startBalanceBeforeWithdrawal) require.Nil(t, err) @@ -1068,15 +1138,15 @@ func TestWithdrawals(t *testing.T) { require.Equal(t, withdrawAmount, diff) // Take start balance on L1 - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) defer cancel() startBalanceBeforeFinalize, err := l1Client.BalanceAt(ctx, fromAddr, nil) require.Nil(t, err) - proveReceipt, finalizeReceipt := ProveAndFinalizeWithdrawal(t, cfg, sys, "verifier", ethPrivKey, receipt) + proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := ProveAndFinalizeWithdrawal(t, cfg, sys, "verifier", ethPrivKey, receipt) // Verify balance after withdrawal - ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) defer cancel() endBalanceAfterFinalize, err := wait.ForBalanceChange(ctx, l1Client, fromAddr, startBalanceBeforeFinalize) require.Nil(t, err) @@ -1088,6 +1158,12 @@ func TestWithdrawals(t *testing.T) { proveFee := new(big.Int).Mul(new(big.Int).SetUint64(proveReceipt.GasUsed), proveReceipt.EffectiveGasPrice) finalizeFee := new(big.Int).Mul(new(big.Int).SetUint64(finalizeReceipt.GasUsed), finalizeReceipt.EffectiveGasPrice) fees = new(big.Int).Add(proveFee, finalizeFee) + if e2eutils.UseFPAC() { + resolveClaimFee := new(big.Int).Mul(new(big.Int).SetUint64(resolveClaimReceipt.GasUsed), resolveClaimReceipt.EffectiveGasPrice) + resolveFee := new(big.Int).Mul(new(big.Int).SetUint64(resolveReceipt.GasUsed), resolveReceipt.EffectiveGasPrice) + fees = new(big.Int).Add(fees, resolveClaimFee) + fees = new(big.Int).Add(fees, resolveFee) + } withdrawAmount = withdrawAmount.Sub(withdrawAmount, fees) require.Equal(t, withdrawAmount, diff) } @@ -1110,10 +1186,12 @@ func (sga *stateGetterAdapter) GetState(addr common.Address, key common.Hash) co // TestFees checks that L1/L2 fees are handled. func TestFees(t *testing.T) { + t.Skip("fails with: the method eth_call does not exist/is not available") InitParallel(t) t.Run("pre-regolith", func(t *testing.T) { + InitParallel(t) cfg := DefaultSystemConfig(t) cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) @@ -1124,6 +1202,7 @@ func TestFees(t *testing.T) { testFees(t, cfg) }) t.Run("regolith", func(t *testing.T) { + InitParallel(t) cfg := DefaultSystemConfig(t) cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) @@ -1134,6 +1213,7 @@ func TestFees(t *testing.T) { testFees(t, cfg) }) t.Run("ecotone", func(t *testing.T) { + InitParallel(t) cfg := DefaultSystemConfig(t) cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) @@ -1146,7 +1226,6 @@ func TestFees(t *testing.T) { } func testFees(t *testing.T, cfg SystemConfig) { - sys, err := cfg.Start(t) require.Nil(t, err, "Error starting up system") defer sys.Close() @@ -1319,11 +1398,11 @@ func StopStartBatcher(t *testing.T, deltaTimeOffset *hexutil.Uint64) { cfg := DefaultSystemConfig(t) cfg.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") + require.NoError(t, err, "Error starting up system") defer sys.Close() rollupRPCClient, err := rpc.DialContext(context.Background(), sys.RollupNodes["verifier"].HTTPEndpoint()) - require.Nil(t, err) + require.NoError(t, err) rollupClient := sources.NewRollupClient(client.NewBaseRPCClient(rollupRPCClient)) l2Seq := sys.Clients["sequencer"] @@ -1331,7 +1410,7 @@ func StopStartBatcher(t *testing.T, deltaTimeOffset *hexutil.Uint64) { // retrieve the initial sync status seqStatus, err := rollupClient.SyncStatus(context.Background()) - require.Nil(t, err) + require.NoError(t, err) nonce := uint64(0) sendTx := func() *types.Receipt { @@ -1350,24 +1429,24 @@ func StopStartBatcher(t *testing.T, deltaTimeOffset *hexutil.Uint64) { // wait until the block the tx was first included in shows up in the safe chain on the verifier safeBlockInclusionDuration := time.Duration(6*cfg.DeployConfig.L1BlockTime) * time.Second _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, safeBlockInclusionDuration) - require.Nil(t, err, "Waiting for block on verifier") + require.NoError(t, err, "Waiting for block on verifier") require.NoError(t, wait.ForProcessingFullBatch(context.Background(), rollupClient)) // ensure the safe chain advances newSeqStatus, err := rollupClient.SyncStatus(context.Background()) - require.Nil(t, err) + require.NoError(t, err) require.Greater(t, newSeqStatus.SafeL2.Number, seqStatus.SafeL2.Number, "Safe chain did not advance") // stop the batch submission err = sys.BatchSubmitter.Driver().StopBatchSubmitting(context.Background()) - require.Nil(t, err) + require.NoError(t, err) // wait for any old safe blocks being submitted / derived time.Sleep(safeBlockInclusionDuration) // get the initial sync status seqStatus, err = rollupClient.SyncStatus(context.Background()) - require.Nil(t, err) + require.NoError(t, err) // send another tx sendTx() @@ -1375,12 +1454,12 @@ func StopStartBatcher(t *testing.T, deltaTimeOffset *hexutil.Uint64) { // ensure that the safe chain does not advance while the batcher is stopped newSeqStatus, err = rollupClient.SyncStatus(context.Background()) - require.Nil(t, err) + require.NoError(t, err) require.Equal(t, newSeqStatus.SafeL2.Number, seqStatus.SafeL2.Number, "Safe chain advanced while batcher was stopped") // start the batch submission err = sys.BatchSubmitter.Driver().StartBatchSubmitting() - require.Nil(t, err) + require.NoError(t, err) time.Sleep(safeBlockInclusionDuration) // send a third tx @@ -1388,12 +1467,12 @@ func StopStartBatcher(t *testing.T, deltaTimeOffset *hexutil.Uint64) { // wait until the block the tx was first included in shows up in the safe chain on the verifier _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, safeBlockInclusionDuration) - require.Nil(t, err, "Waiting for block on verifier") + require.NoError(t, err, "Waiting for block on verifier") require.NoError(t, wait.ForProcessingFullBatch(context.Background(), rollupClient)) // ensure that the safe chain advances after restarting the batcher newSeqStatus, err = rollupClient.SyncStatus(context.Background()) - require.Nil(t, err) + require.NoError(t, err) require.Greater(t, newSeqStatus.SafeL2.Number, seqStatus.SafeL2.Number, "Safe chain did not advance after batcher was restarted") } @@ -1401,26 +1480,28 @@ func TestBatcherMultiTx(t *testing.T) { InitParallel(t) cfg := DefaultSystemConfig(t) - cfg.BatcherTargetL1TxSizeBytes = 2 // ensures that batcher txs are as small as possible + cfg.MaxPendingTransactions = 0 // no limit on parallel txs + // ensures that batcher txs are as small as possible + cfg.BatcherMaxL1TxSizeBytes = derive.FrameV0OverHeadSize + 1 /*version bytes*/ + 1 cfg.DisableBatcher = true sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") + require.NoError(t, err, "Error starting up system") defer sys.Close() l1Client := sys.Clients["l1"] l2Seq := sys.Clients["sequencer"] _, err = geth.WaitForBlock(big.NewInt(10), l2Seq, time.Duration(cfg.DeployConfig.L2BlockTime*15)*time.Second) - require.Nil(t, err, "Waiting for L2 blocks") + require.NoError(t, err, "Waiting for L2 blocks") - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() l1Number, err := l1Client.BlockNumber(ctx) - require.Nil(t, err) + require.NoError(t, err) // start batch submission err = sys.BatchSubmitter.Driver().StartBatchSubmitting() - require.Nil(t, err) + require.NoError(t, err) totalTxCount := 0 // wait for up to 10 L1 blocks, usually only 3 is required, but it's @@ -1428,7 +1509,7 @@ func TestBatcherMultiTx(t *testing.T) { // so we wait additional blocks. for i := int64(0); i < 10; i++ { block, err := geth.WaitForBlock(big.NewInt(int64(l1Number)+i), l1Client, time.Duration(cfg.DeployConfig.L1BlockTime*5)*time.Second) - require.Nil(t, err, "Waiting for l1 blocks") + require.NoError(t, err, "Waiting for l1 blocks") totalTxCount += len(block.Transactions()) if totalTxCount >= 10 { @@ -1440,7 +1521,7 @@ func TestBatcherMultiTx(t *testing.T) { } func latestBlock(t *testing.T, client *ethclient.Client) uint64 { - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() blockAfter, err := client.BlockNumber(ctx) require.Nil(t, err, "Error getting latest block") @@ -1636,7 +1717,7 @@ func TestRequiredProtocolVersionChangeAndHalt(t *testing.T) { // Checking if the engine is down is not trivial in op-e2e. // In op-geth we have halting tests covering the Engine API, in op-e2e we instead check if the API stops. _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) _, err := sys.Clients["verifier"].ChainID(ctx) cancel() if err != nil && !errors.Is(err, ctx.Err()) { // waiting for client to stop responding to chainID requests diff --git a/op-e2e/system_tob_test.go b/op-e2e/system_tob_test.go index ede811e114ff..991eb6057f9b 100644 --- a/op-e2e/system_tob_test.go +++ b/op-e2e/system_tob_test.go @@ -11,11 +11,14 @@ import ( "time" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-bindings/bindingspreview" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" + "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" - "github.com/ethereum-optimism/optimism/op-node/withdrawals" "github.com/ethereum-optimism/optimism/op-service/testutils/fuzzerutils" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi" @@ -33,7 +36,12 @@ import ( // TestGasPriceOracleFeeUpdates checks that the gas price oracle cannot be locked by mis-configuring parameters. func TestGasPriceOracleFeeUpdates(t *testing.T) { + t.Skip("fails with: the method eth_call does not exist/is not available") + + ctx, ctxCancel := context.WithCancel(context.Background()) + defer ctxCancel() + InitParallel(t) // Define our values to set in the GasPriceOracle (we set them high to see if it can lock L2 or stop bindings // from updating the prices once again. @@ -67,14 +75,13 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) { txTimeoutDuration := 10 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second // Update the gas config, wait for it to show up on L2, & verify that it was set as intended - opts.Context, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) + opts.Context, cancel = context.WithTimeout(ctx, txTimeoutDuration) tx, err := sysconfig.SetGasConfig(opts, overheadValue, scalarValue) cancel() require.Nil(t, err, "sending overhead update tx") - receipt, err := geth.WaitForTransaction(tx.Hash(), l1Client, txTimeoutDuration) - require.Nil(t, err, "waiting for sysconfig set gas config update tx") - require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed") + receipt, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash()) + require.Nil(t, err, "Waiting for sysconfig set gas config update tx") _, err = geth.WaitForL1OriginOnL2(sys.RollupConfig, receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration) require.NoError(t, err, "waiting for L2 block to include the sysconfig update") @@ -99,9 +106,8 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) { cancel() require.Nil(t, err, "sending overhead update tx") - receipt, err = geth.WaitForTransaction(tx.Hash(), l1Client, txTimeoutDuration) - require.Nil(t, err, "waiting for sysconfig set gas config update tx") - require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed") + receipt, err = wait.ForReceiptOK(ctx, l1Client, tx.Hash()) + require.Nil(t, err, "Waiting for sysconfig set gas config update tx") _, err = geth.WaitForL1OriginOnL2(sys.RollupConfig, receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration) require.NoError(t, err, "waiting for L2 block to include the sysconfig update") @@ -397,10 +403,14 @@ func TestMixedWithdrawalValidity(t *testing.T) { for i := 0; i <= 8; i++ { i := i // avoid loop var capture t.Run(fmt.Sprintf("withdrawal test#%d", i+1), func(t *testing.T) { + ctx, bgCancel := context.WithCancel(context.Background()) + defer bgCancel() + InitParallel(t) // Create our system configuration, funding all accounts we created for L1/L2, and start it cfg := DefaultSystemConfig(t) + cfg.Nodes["sequencer"].SafeDBPath = t.TempDir() cfg.DeployConfig.L2BlockTime = 2 require.LessOrEqual(t, cfg.DeployConfig.FinalizationPeriodSeconds, uint64(6)) require.Equal(t, cfg.DeployConfig.FundDevAccounts, true) @@ -445,6 +455,12 @@ func TestMixedWithdrawalValidity(t *testing.T) { require.NoError(t, err) require.Equal(t, cfg.DeployConfig.FinalizationPeriodSeconds, finalizationPeriod.Uint64()) + disputeGameFactory, err := bindings.NewDisputeGameFactoryCaller(cfg.L1Deployments.DisputeGameFactoryProxy, l1Client) + require.NoError(t, err) + + optimismPortal2, err := bindingspreview.NewOptimismPortal2Caller(cfg.L1Deployments.OptimismPortalProxy, l1Client) + require.NoError(t, err) + // Create a struct used to track our transactors and their transactions sent. type TestAccountState struct { Account *TestAccount @@ -473,15 +489,15 @@ func TestMixedWithdrawalValidity(t *testing.T) { require.NoError(t, err) // Obtain the transactor's starting balance on L1. - ctx, cancel := context.WithTimeout(context.Background(), txTimeoutDuration) - transactor.ExpectedL1Balance, err = l1Client.BalanceAt(ctx, transactor.Account.L1Opts.From, nil) - cancel() + txCtx, txCancel := context.WithTimeout(context.Background(), txTimeoutDuration) + transactor.ExpectedL1Balance, err = l1Client.BalanceAt(txCtx, transactor.Account.L1Opts.From, nil) + txCancel() require.NoError(t, err) // Obtain the transactor's starting balance on L2. - ctx, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) - transactor.ExpectedL2Balance, err = l2Verif.BalanceAt(ctx, transactor.Account.L2Opts.From, nil) - cancel() + txCtx, txCancel = context.WithTimeout(context.Background(), txTimeoutDuration) + transactor.ExpectedL2Balance, err = l2Verif.BalanceAt(txCtx, transactor.Account.L2Opts.From, nil) + txCancel() require.NoError(t, err) // Bind to the L2-L1 message passer @@ -508,23 +524,20 @@ func TestMixedWithdrawalValidity(t *testing.T) { require.Nil(t, err, "sending initiate withdraw tx") t.Logf("Waiting for tx %s to be in sequencer", tx.Hash().Hex()) - receiptSeq, err := geth.WaitForTransaction(tx.Hash(), l2Seq, txTimeoutDuration) + receiptSeq, err := wait.ForReceiptOK(ctx, l2Seq, tx.Hash()) require.Nil(t, err, "withdrawal initiated on L2 sequencer") - require.Equal(t, receiptSeq.Status, types.ReceiptStatusSuccessful, "transaction failed") verifierTip, err := l2Verif.BlockByNumber(context.Background(), nil) require.Nil(t, err) t.Logf("Waiting for tx %s to be in verifier. Verifier tip is %s:%d. Included in sequencer in block %s:%d", tx.Hash().Hex(), verifierTip.Hash().Hex(), verifierTip.NumberU64(), receiptSeq.BlockHash.Hex(), receiptSeq.BlockNumber) - // Wait for the transaction to appear in L2 verifier - receipt, err := geth.WaitForTransaction(tx.Hash(), l2Verif, txTimeoutDuration) + receipt, err := wait.ForReceiptOK(ctx, l2Verif, tx.Hash()) require.Nilf(t, err, "withdrawal tx %s not found in verifier. included in block %s:%d", tx.Hash().Hex(), receiptSeq.BlockHash.Hex(), receiptSeq.BlockNumber) - require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful, "transaction failed") // Obtain the header for the block containing the transaction (used to calculate gas fees) - ctx, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) - header, err := l2Verif.HeaderByNumber(ctx, receipt.BlockNumber) - cancel() + txCtx, txCancel = context.WithTimeout(context.Background(), txTimeoutDuration) + header, err := l2Verif.HeaderByNumber(txCtx, receipt.BlockNumber) + txCancel() require.Nil(t, err) // Calculate gas fees for the withdrawal in L2 to later adjust our balance. @@ -537,35 +550,38 @@ func TestMixedWithdrawalValidity(t *testing.T) { transactor.ExpectedL2Nonce = transactor.ExpectedL2Nonce + 1 // Wait for the finalization period, then we can finalize this withdrawal. - ctx, cancel = context.WithTimeout(context.Background(), 40*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) require.NotEqual(t, cfg.L1Deployments.L2OutputOracleProxy, common.Address{}) - blockNumber, err := wait.ForOutputRootPublished(ctx, l1Client, cfg.L1Deployments.L2OutputOracleProxy, receipt.BlockNumber) - cancel() + var blockNumber uint64 + if e2eutils.UseFPAC() { + blockNumber, err = wait.ForGamePublished(ctx, l1Client, cfg.L1Deployments.OptimismPortalProxy, cfg.L1Deployments.DisputeGameFactoryProxy, receipt.BlockNumber) + } else { + blockNumber, err = wait.ForOutputRootPublished(ctx, l1Client, cfg.L1Deployments.L2OutputOracleProxy, receipt.BlockNumber) + } require.Nil(t, err) - ctx, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) header, err = l2Verif.HeaderByNumber(ctx, new(big.Int).SetUint64(blockNumber)) - cancel() require.Nil(t, err) rpcClient, err := rpc.Dial(sys.EthInstances["verifier"].WSEndpoint()) require.Nil(t, err) proofCl := gethclient.New(rpcClient) receiptCl := ethclient.NewClient(rpcClient) + blockCl := ethclient.NewClient(rpcClient) // Now create the withdrawal - params, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, tx.Hash(), header, l2OutputOracle) + params, err := ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, blockCl, tx.Hash(), header, l2OutputOracle, disputeGameFactory, optimismPortal2) require.Nil(t, err) // Obtain our withdrawal parameters - withdrawalTransaction := &bindings.TypesWithdrawalTransaction{ + withdrawal := crossdomain.Withdrawal{ Nonce: params.Nonce, - Sender: params.Sender, - Target: params.Target, + Sender: ¶ms.Sender, + Target: ¶ms.Target, Value: params.Value, GasLimit: params.GasLimit, Data: params.Data, } + withdrawalTransaction := withdrawal.WithdrawalTransaction() l2OutputIndexParam := params.L2OutputIndex outputRootProofParam := params.OutputRootProof withdrawalProofParam := params.WithdrawalProof @@ -628,7 +644,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { // Prove withdrawal. This checks the proof so we only finalize if this succeeds tx, err = depositContract.ProveWithdrawalTransaction( transactor.Account.L1Opts, - *withdrawalTransaction, + withdrawalTransaction, l2OutputIndexParam, outputRootProofParam, withdrawalProofParam, @@ -642,15 +658,19 @@ func TestMixedWithdrawalValidity(t *testing.T) { } else { require.NoError(t, err) - receipt, err = geth.WaitForTransaction(tx.Hash(), l1Client, txTimeoutDuration) - require.Nil(t, err, "finalize withdrawal") - require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status) + if e2eutils.UseFPAC() { + // Start a challenger to resolve claims and games once the clock expires + factoryHelper := disputegame.NewFactoryHelper(t, ctx, sys) + factoryHelper.StartChallenger(ctx, "Challenger", + challenger.WithCannon(t, sys.RollupConfig, sys.L2GenesisCfg, sys.RollupEndpoint("sequencer"), sys.NodeEndpoint("sequencer")), + challenger.WithPrivKey(sys.Cfg.Secrets.Mallory)) + } + receipt, err = wait.ForReceiptOK(ctx, l1Client, tx.Hash()) + require.NoError(t, err, "finalize withdrawal") // Verify balance after withdrawal - ctx, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) header, err = l1Client.HeaderByNumber(ctx, receipt.BlockNumber) - cancel() - require.Nil(t, err) + require.NoError(t, err) // Ensure that withdrawal - gas fees are added to the L1 balance // Fun fact, the fee is greater than the withdrawal amount @@ -660,20 +680,24 @@ func TestMixedWithdrawalValidity(t *testing.T) { transactor.ExpectedL1Nonce++ // Ensure that our withdrawal was proved successfully - proveReceipt, err := geth.WaitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) - require.Nil(t, err, "prove withdrawal") - require.Equal(t, types.ReceiptStatusSuccessful, proveReceipt.Status) + _, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash()) + require.NoError(t, err, "prove withdrawal") // Wait for finalization and then create the Finalized Withdrawal Transaction - ctx, cancel = context.WithTimeout(context.Background(), 45*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) - defer cancel() - err = wait.ForFinalizationPeriod(ctx, l1Client, header.Number, cfg.L1Deployments.L2OutputOracleProxy) - require.Nil(t, err) + ctx, withdrawalCancel := context.WithTimeout(context.Background(), 60*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + defer withdrawalCancel() + if e2eutils.UseFPAC() { + err = wait.ForWithdrawalCheck(ctx, l1Client, withdrawal, cfg.L1Deployments.OptimismPortalProxy) + require.NoError(t, err) + } else { + err = wait.ForFinalizationPeriod(ctx, l1Client, header.Number, cfg.L1Deployments.L2OutputOracleProxy) + require.NoError(t, err) + } // Finalize withdrawal _, err = depositContract.FinalizeWithdrawalTransaction( transactor.Account.L1Opts, - *withdrawalTransaction, + withdrawalTransaction, ) require.NoError(t, err) } @@ -681,39 +705,27 @@ func TestMixedWithdrawalValidity(t *testing.T) { // At the end, assert our account balance/nonce states. // Obtain the L2 sequencer account balance - ctx, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) endL1Balance, err := l1Client.BalanceAt(ctx, transactor.Account.L1Opts.From, nil) - cancel() require.NoError(t, err) // Obtain the L1 account nonce - ctx, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) endL1Nonce, err := l1Client.NonceAt(ctx, transactor.Account.L1Opts.From, nil) - cancel() require.NoError(t, err) // Obtain the L2 sequencer account balance - ctx, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) endL2SeqBalance, err := l2Seq.BalanceAt(ctx, transactor.Account.L1Opts.From, nil) - cancel() require.NoError(t, err) // Obtain the L2 sequencer account nonce - ctx, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) endL2SeqNonce, err := l2Seq.NonceAt(ctx, transactor.Account.L1Opts.From, nil) - cancel() require.NoError(t, err) // Obtain the L2 verifier account balance - ctx, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) endL2VerifBalance, err := l2Verif.BalanceAt(ctx, transactor.Account.L1Opts.From, nil) - cancel() require.NoError(t, err) // Obtain the L2 verifier account nonce - ctx, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) endL2VerifNonce, err := l2Verif.NonceAt(ctx, transactor.Account.L1Opts.From, nil) - cancel() require.NoError(t, err) // TODO: Check L1 balance as well here. We avoided this due to time constraints as it seems L1 fees diff --git a/op-e2e/tx_helper.go b/op-e2e/tx_helper.go index 2dab1787292a..2c930801ad1a 100644 --- a/op-e2e/tx_helper.go +++ b/op-e2e/tx_helper.go @@ -7,8 +7,9 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-bindings/bindings" - "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -40,18 +41,17 @@ func SendDepositTx(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, l require.Nil(t, err, "with deposit tx") // Wait for transaction on L1 - l1Receipt, err := geth.WaitForTransaction(tx.Hash(), l1Client, 10*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + l1Receipt, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash()) require.Nil(t, err, "Waiting for deposit tx on L1") // Wait for transaction to be included on L2 reconstructedDep, err := derive.UnmarshalDepositLogEvent(l1Receipt.Logs[0]) require.NoError(t, err, "Could not reconstruct L2 Deposit") tx = types.NewTx(reconstructedDep) - // Use a long wait because the l2Client may not be configured to receive gossip from the sequencer - // so has to wait for the batcher to submit and then import those blocks from L1. - l2Receipt, err := geth.WaitForTransaction(tx.Hash(), l2Client, 60*time.Second) - require.NoError(t, err) - require.Equal(t, l2Opts.ExpectedStatus, l2Receipt.Status, "l2 transaction status") + l2Receipt, err := wait.ForReceipt(ctx, l2Client, tx.Hash(), l2Opts.ExpectedStatus) + require.NoError(t, err, "Waiting for deposit tx on L2") return l2Receipt } @@ -92,19 +92,20 @@ func SendL2Tx(t *testing.T, cfg SystemConfig, l2Client *ethclient.Client, privKe GasTipCap: opts.GasTipCap, GasFeeCap: opts.GasFeeCap, Gas: opts.Gas, + Data: opts.Data, }) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() err := l2Client.SendTransaction(ctx, tx) require.NoError(t, err, "Sending L2 tx") - receipt, err := geth.WaitForTransaction(tx.Hash(), l2Client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) + receipt, err := wait.ForReceiptOK(ctx, l2Client, tx.Hash()) require.NoError(t, err, "Waiting for L2 tx") require.Equal(t, opts.ExpectedStatus, receipt.Status, "TX should have expected status") for i, client := range opts.VerifyClients { t.Logf("Waiting for tx %v on verification client %d", tx.Hash(), i) - receiptVerif, err := geth.WaitForTransaction(tx.Hash(), client, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) + receiptVerif, err := wait.ForReceiptOK(ctx, client, tx.Hash()) require.NoErrorf(t, err, "Waiting for L2 tx on verification client %d", i) require.Equalf(t, receipt, receiptVerif, "Receipts should be the same on sequencer and verification client %d", i) } diff --git a/op-e2e/withdrawal_helper.go b/op-e2e/withdrawal_helper.go index 67822d4e7353..f0457d105db0 100644 --- a/op-e2e/withdrawal_helper.go +++ b/op-e2e/withdrawal_helper.go @@ -8,8 +8,11 @@ import ( "time" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-bindings/bindingspreview" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" + "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" "github.com/ethereum-optimism/optimism/op-e2e/config" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-node/withdrawals" @@ -82,10 +85,10 @@ func defaultWithdrawalTxOpts() *WithdrawalTxOpts { } } -func ProveAndFinalizeWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2NodeName string, ethPrivKey *ecdsa.PrivateKey, l2WithdrawalReceipt *types.Receipt) (*types.Receipt, *types.Receipt) { +func ProveAndFinalizeWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2NodeName string, ethPrivKey *ecdsa.PrivateKey, l2WithdrawalReceipt *types.Receipt) (*types.Receipt, *types.Receipt, *types.Receipt, *types.Receipt) { params, proveReceipt := ProveWithdrawal(t, cfg, clients, l2NodeName, ethPrivKey, l2WithdrawalReceipt) - finalizeReceipt := FinalizeWithdrawal(t, cfg, clients.NodeClient("l1"), ethPrivKey, proveReceipt, params) - return proveReceipt, finalizeReceipt + finalizeReceipt, resolveClaimReceipt, resolveReceipt := FinalizeWithdrawal(t, cfg, clients.NodeClient("l1"), ethPrivKey, proveReceipt, params) + return proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt } func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2NodeName string, ethPrivKey *ecdsa.PrivateKey, l2WithdrawalReceipt *types.Receipt) (withdrawals.ProvenWithdrawalParameters, *types.Receipt) { @@ -94,10 +97,18 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2N defer cancel() l1Client := clients.NodeClient("l1") - blockNumber, err := wait.ForOutputRootPublished(ctx, l1Client, config.L1Deployments.L2OutputOracleProxy, l2WithdrawalReceipt.BlockNumber) - require.Nil(t, err) + var blockNumber uint64 + var err error + if e2eutils.UseFPAC() { + blockNumber, err = wait.ForGamePublished(ctx, l1Client, config.L1Deployments.OptimismPortalProxy, config.L1Deployments.DisputeGameFactoryProxy, l2WithdrawalReceipt.BlockNumber) + require.Nil(t, err) + } else { + blockNumber, err = wait.ForOutputRootPublished(ctx, l1Client, config.L1Deployments.L2OutputOracleProxy, l2WithdrawalReceipt.BlockNumber) + require.Nil(t, err) + } receiptCl := clients.NodeClient(l2NodeName) + blockCl := clients.NodeClient(l2NodeName) proofCl := gethclient.New(receiptCl.Client()) ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) @@ -106,11 +117,16 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2N header, err := receiptCl.HeaderByNumber(ctx, new(big.Int).SetUint64(blockNumber)) require.Nil(t, err) - // Now create withdrawal oracle, err := bindings.NewL2OutputOracleCaller(config.L1Deployments.L2OutputOracleProxy, l1Client) require.Nil(t, err) - params, err := withdrawals.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, l2WithdrawalReceipt.TxHash, header, oracle) + factory, err := bindings.NewDisputeGameFactoryCaller(config.L1Deployments.DisputeGameFactoryProxy, l1Client) + require.Nil(t, err) + + portal2, err := bindingspreview.NewOptimismPortal2Caller(config.L1Deployments.OptimismPortalProxy, l1Client) + require.Nil(t, err) + + params, err := ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, blockCl, l2WithdrawalReceipt.TxHash, header, oracle, factory, portal2) require.Nil(t, err) portal, err := bindings.NewOptimismPortal(config.L1Deployments.OptimismPortalProxy, l1Client) @@ -143,35 +159,84 @@ func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2N return params, proveReceipt } -func FinalizeWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, privKey *ecdsa.PrivateKey, withdrawalProofReceipt *types.Receipt, params withdrawals.ProvenWithdrawalParameters) *types.Receipt { +func ProveWithdrawalParameters(ctx context.Context, proofCl withdrawals.ProofClient, l2ReceiptCl withdrawals.ReceiptClient, l2BlockCl withdrawals.BlockClient, txHash common.Hash, header *types.Header, l2OutputOracleContract *bindings.L2OutputOracleCaller, disputeGameFactoryContract *bindings.DisputeGameFactoryCaller, optimismPortal2Contract *bindingspreview.OptimismPortal2Caller) (withdrawals.ProvenWithdrawalParameters, error) { + if e2eutils.UseFPAC() { + return withdrawals.ProveWithdrawalParametersFPAC(ctx, proofCl, l2ReceiptCl, l2BlockCl, txHash, disputeGameFactoryContract, optimismPortal2Contract) + } else { + return withdrawals.ProveWithdrawalParameters(ctx, proofCl, l2ReceiptCl, l2BlockCl, txHash, header, l2OutputOracleContract) + } +} + +func FinalizeWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, privKey *ecdsa.PrivateKey, withdrawalProofReceipt *types.Receipt, params withdrawals.ProvenWithdrawalParameters) (*types.Receipt, *types.Receipt, *types.Receipt) { // Wait for finalization and then create the Finalized Withdrawal Transaction ctx, cancel := context.WithTimeout(context.Background(), 30*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) defer cancel() - err := wait.ForFinalizationPeriod(ctx, l1Client, withdrawalProofReceipt.BlockNumber, config.L1Deployments.L2OutputOracleProxy) - require.Nil(t, err) + wd := crossdomain.Withdrawal{ + Nonce: params.Nonce, + Sender: ¶ms.Sender, + Target: ¶ms.Target, + Value: params.Value, + GasLimit: params.GasLimit, + Data: params.Data, + } opts, err := bind.NewKeyedTransactorWithChainID(privKey, cfg.L1ChainIDBig()) require.Nil(t, err) + + var resolveClaimReceipt *types.Receipt + var resolveReceipt *types.Receipt + if e2eutils.UseFPAC() { + portal2, err := bindingspreview.NewOptimismPortal2(config.L1Deployments.OptimismPortalProxy, l1Client) + require.Nil(t, err) + + wdHash, err := wd.Hash() + require.Nil(t, err) + + game, err := portal2.ProvenWithdrawals(&bind.CallOpts{}, wdHash) + require.Nil(t, err) + require.NotNil(t, game, "withdrawal should be proven") + + proxy, err := bindings.NewFaultDisputeGame(game.DisputeGameProxy, l1Client) + require.Nil(t, err) + + expiry, err := proxy.GameDuration(&bind.CallOpts{}) + require.Nil(t, err) + + time.Sleep(time.Duration(expiry) * time.Second) + resolveClaimTx, err := proxy.ResolveClaim(opts, common.Big0) + require.Nil(t, err) + + resolveClaimReceipt, err = wait.ForReceiptOK(ctx, l1Client, resolveClaimTx.Hash()) + require.Nil(t, err, "resolve claim") + require.Equal(t, types.ReceiptStatusSuccessful, resolveClaimReceipt.Status) + + resolveTx, err := proxy.Resolve(opts) + require.Nil(t, err) + + resolveReceipt, err = wait.ForReceiptOK(ctx, l1Client, resolveTx.Hash()) + require.Nil(t, err, "resolve") + require.Equal(t, types.ReceiptStatusSuccessful, resolveReceipt.Status) + } + + if e2eutils.UseFPAC() { + err := wait.ForWithdrawalCheck(ctx, l1Client, wd, config.L1Deployments.OptimismPortalProxy) + require.Nil(t, err) + } else { + err := wait.ForFinalizationPeriod(ctx, l1Client, withdrawalProofReceipt.BlockNumber, config.L1Deployments.L2OutputOracleProxy) + require.Nil(t, err) + } + portal, err := bindings.NewOptimismPortal(config.L1Deployments.OptimismPortalProxy, l1Client) require.Nil(t, err) + // Finalize withdrawal - tx, err := portal.FinalizeWithdrawalTransaction( - opts, - bindings.TypesWithdrawalTransaction{ - Nonce: params.Nonce, - Sender: params.Sender, - Target: params.Target, - Value: params.Value, - GasLimit: params.GasLimit, - Data: params.Data, - }, - ) + tx, err := portal.FinalizeWithdrawalTransaction(opts, wd.WithdrawalTransaction()) require.Nil(t, err) // Ensure that our withdrawal was finalized successfully - finalizeReceipt, err := geth.WaitForTransaction(tx.Hash(), l1Client, 3*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + finalizeReceipt, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash()) require.Nil(t, err, "finalize withdrawal") require.Equal(t, types.ReceiptStatusSuccessful, finalizeReceipt.Status) - return finalizeReceipt + return finalizeReceipt, resolveClaimReceipt, resolveReceipt } diff --git a/op-heartbeat/service.go b/op-heartbeat/service.go index 801d61feedd2..55305fde591a 100644 --- a/op-heartbeat/service.go +++ b/op-heartbeat/service.go @@ -39,7 +39,7 @@ func Main(version string) func(ctx *cli.Context) error { } l := oplog.NewLogger(oplog.AppOut(cliCtx), cfg.Log) - oplog.SetGlobalLogHandler(l.GetHandler()) + oplog.SetGlobalLogHandler(l.Handler()) l.Info("starting heartbeat monitor", "version", version) srv, err := Start(cliCtx.Context, l, cfg, version) diff --git a/op-node/README.md b/op-node/README.md index 1a7cc05adcfb..fa190535a452 100644 --- a/op-node/README.md +++ b/op-node/README.md @@ -1,6 +1,6 @@ # op-node -This is the reference implementation of the [rollup-node spec](../specs/rollup-node.md). +This is the reference implementation of the [rollup-node spec](https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/rollup-node.md). ## Compiling diff --git a/op-node/chaincfg/chains_test.go b/op-node/chaincfg/chains_test.go index ff549bb6fb50..b7b401b5094a 100644 --- a/op-node/chaincfg/chains_test.go +++ b/op-node/chaincfg/chains_test.go @@ -20,10 +20,11 @@ import ( // This test ensures no op-node config-loading behavior changes before // the superchain-registry is no longer deemed experimental. func TestGetRollupConfig(t *testing.T) { - var configsByName = map[string]rollup.Config{ - "goerli": goerliCfg, - "mainnet": mainnetCfg, - "sepolia": sepoliaCfg, + configsByName := map[string]rollup.Config{ + "goerli": goerliCfg, + "mainnet": mainnetCfg, + "sepolia": sepoliaCfg, + "oplabs-devnet-0-sepolia-dev-0": sepoliaDev0Cfg, } for name, expectedCfg := range configsByName { @@ -63,6 +64,8 @@ var mainnetCfg = rollup.Config{ L1SystemConfigAddress: common.HexToAddress("0x229047fed2591dbec1eF1118d64F7aF3dB9EB290"), RegolithTime: u64Ptr(0), CanyonTime: u64Ptr(1704992401), + DeltaTime: u64Ptr(1708560000), + EcotoneTime: u64Ptr(1710374401), ProtocolVersionsAddress: common.HexToAddress("0x8062AbC286f5e7D9428a0Ccb9AbD71e50d93b935"), } @@ -96,6 +99,7 @@ var goerliCfg = rollup.Config{ RegolithTime: u64Ptr(1679079600), CanyonTime: u64Ptr(1699981200), DeltaTime: u64Ptr(1703116800), + EcotoneTime: u64Ptr(1707238800), ProtocolVersionsAddress: common.HexToAddress("0x0C24F5098774aA366827D667494e9F889f7cFc08"), } @@ -129,9 +133,44 @@ var sepoliaCfg = rollup.Config{ RegolithTime: u64Ptr(0), CanyonTime: u64Ptr(1699981200), DeltaTime: u64Ptr(1703203200), + EcotoneTime: u64Ptr(1708534800), ProtocolVersionsAddress: common.HexToAddress("0x79ADD5713B383DAa0a138d3C4780C7A1804a8090"), } +var sepoliaDev0Cfg = rollup.Config{ + Genesis: rollup.Genesis{ + L1: eth.BlockID{ + Hash: common.HexToHash("0x5639be97000fec7131a880b19b664cae43f975c773f628a08a9bb658c2a68df0"), + Number: 5173577, + }, + L2: eth.BlockID{ + Hash: common.HexToHash("0x027ae1f4f9a441f9c8a01828f3b6d05803a0f524c07e09263264a38b755f804b"), + Number: 0, + }, + L2Time: 1706484048, + SystemConfig: eth.SystemConfig{ + BatcherAddr: common.HexToAddress("0x19cc7073150d9f5888f09e0e9016d2a39667df14"), + Overhead: eth.Bytes32(common.HexToHash("0x00000000000000000000000000000000000000000000000000000000000000bc")), + Scalar: eth.Bytes32(common.HexToHash("0x00000000000000000000000000000000000000000000000000000000000a6fe0")), + GasLimit: 30000000, + }, + }, + BlockTime: 2, + MaxSequencerDrift: 600, + SeqWindowSize: 3600, + ChannelTimeout: 300, + L1ChainID: big.NewInt(11155111), + L2ChainID: big.NewInt(11155421), + BatchInboxAddress: common.HexToAddress("0xff00000000000000000000000000000011155421"), + DepositContractAddress: common.HexToAddress("0x76114bd29dFcC7a9892240D317E6c7C2A281Ffc6"), + L1SystemConfigAddress: common.HexToAddress("0xa6b72407e2dc9EBF84b839B69A24C88929cf20F7"), + RegolithTime: u64Ptr(0), + CanyonTime: u64Ptr(0), + DeltaTime: u64Ptr(0), + EcotoneTime: u64Ptr(1706634000), + ProtocolVersionsAddress: common.HexToAddress("0x252CbE9517F731C618961D890D534183822dcC8d"), +} + func u64Ptr(v uint64) *uint64 { return &v } diff --git a/op-node/cmd/genesis/cmd.go b/op-node/cmd/genesis/cmd.go index 716d71a9f1d1..360f7ecb59dc 100644 --- a/op-node/cmd/genesis/cmd.go +++ b/op-node/cmd/genesis/cmd.go @@ -7,7 +7,6 @@ import ( "fmt" "math/big" "os" - "path/filepath" "github.com/urfave/cli/v2" @@ -18,8 +17,8 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum-optimism/optimism/op-bindings/hardhat" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" ) var ( @@ -36,13 +35,10 @@ var ( Usage: "Path to deploy config file", Required: true, } - deploymentDirFlag = &cli.PathFlag{ - Name: "deployment-dir", - Usage: "Path to network deployment directory. Cannot be used with --l1-deployments", - } l1DeploymentsFlag = &cli.PathFlag{ - Name: "l1-deployments", - Usage: "Path to L1 deployments JSON file. Cannot be used with --deployment-dir", + Name: "l1-deployments", + Usage: "Path to L1 deployments JSON file as in superchain-registry", + Required: true, } outfileL2Flag = &cli.PathFlag{ Name: "outfile.l2", @@ -73,7 +69,6 @@ var ( l1RPCFlag, l1StartingBlockFlag, deployConfigFlag, - deploymentDirFlag, l1DeploymentsFlag, outfileL2Flag, outfileRollupFlag, @@ -121,12 +116,12 @@ var Subcommands = cli.Commands{ } } - l1Genesis, err := genesis.BuildL1DeveloperGenesis(config, dump, deployments, true) + l1Genesis, err := genesis.BuildL1DeveloperGenesis(config, dump, deployments) if err != nil { return err } - return writeJSONFile(ctx.String("outfile.l1"), l1Genesis) + return jsonutil.WriteJSON(ctx.String("outfile.l1"), l1Genesis, 0o666) }, }, { @@ -146,16 +141,7 @@ var Subcommands = cli.Commands{ return err } - deployDir := ctx.Path("deployment-dir") l1Deployments := ctx.Path("l1-deployments") - - if deployDir != "" && l1Deployments != "" { - return errors.New("cannot specify both --deployment-dir and --l1-deployments") - } - if deployDir == "" && l1Deployments == "" { - return errors.New("must specify either --deployment-dir or --l1-deployments") - } - l1StartBlockPath := ctx.Path("l1-starting-block") l1RPC := ctx.String("l1-rpc") @@ -166,27 +152,11 @@ var Subcommands = cli.Commands{ return errors.New("cannot specify both --l1-starting-block and --l1-rpc") } - if deployDir != "" { - log.Info("Deployment directory", "path", deployDir) - depPath, network := filepath.Split(deployDir) - hh, err := hardhat.New(network, nil, []string{depPath}) - if err != nil { - return err - } - - // Read the appropriate deployment addresses from disk - if err := config.GetDeployedAddresses(hh); err != nil { - return err - } - } - - if l1Deployments != "" { - deployments, err := genesis.NewL1Deployments(l1Deployments) - if err != nil { - return fmt.Errorf("cannot read L1 deployments at %s: %w", l1Deployments, err) - } - config.SetDeployments(deployments) + deployments, err := genesis.NewL1Deployments(l1Deployments) + if err != nil { + return fmt.Errorf("cannot read L1 deployments at %s: %w", l1Deployments, err) } + config.SetDeployments(deployments) var l1StartBlock *types.Block if l1StartBlockPath != "" { @@ -249,28 +219,14 @@ var Subcommands = cli.Commands{ return fmt.Errorf("generated rollup config does not pass validation: %w", err) } - if err := writeJSONFile(ctx.String("outfile.l2"), l2Genesis); err != nil { + if err := jsonutil.WriteJSON(ctx.String("outfile.l2"), l2Genesis, 0o666); err != nil { return err } - return writeJSONFile(ctx.String("outfile.rollup"), rollupConfig) + return jsonutil.WriteJSON(ctx.String("outfile.rollup"), rollupConfig, 0o666) }, }, } -// writeJSONFile will write a JSON file to disk at the given path -// containing the JSON serialized input value. -func writeJSONFile(outfile string, input any) error { - f, err := os.OpenFile(outfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o644) - if err != nil { - return err - } - defer f.Close() - - enc := json.NewEncoder(f) - enc.SetIndent("", " ") - return enc.Encode(input) -} - // rpcBlock represents the JSON serialization of a block from an Ethereum RPC. type rpcBlock struct { Hash common.Hash `json:"hash"` diff --git a/op-node/cmd/main.go b/op-node/cmd/main.go index 40bfb76f6a1b..f0e0122ac95f 100644 --- a/op-node/cmd/main.go +++ b/op-node/cmd/main.go @@ -74,7 +74,7 @@ func main() { func RollupNodeMain(ctx *cli.Context, closeApp context.CancelCauseFunc) (cliapp.Lifecycle, error) { logCfg := oplog.ReadCLIConfig(ctx) log := oplog.NewLogger(oplog.AppOut(ctx), logCfg) - oplog.SetGlobalLogHandler(log.GetHandler()) + oplog.SetGlobalLogHandler(log.Handler()) opservice.ValidateEnvVars(flags.EnvVarPrefix, flags.Flags, log) opservice.WarnOnDeprecatedFlags(ctx, flags.DeprecatedFlags, log) m := metrics.NewMetrics("default") diff --git a/op-node/cmd/networks/cmd.go b/op-node/cmd/networks/cmd.go index 90f5f7fd083f..aa30681a97fb 100644 --- a/op-node/cmd/networks/cmd.go +++ b/op-node/cmd/networks/cmd.go @@ -18,7 +18,7 @@ var Subcommands = []*cli.Command{ Name: "dump-rollup-config", Usage: "Dumps network configs", Flags: []cli.Flag{ - opflags.CLINetworkFlag(flags.EnvVarPrefix), + opflags.CLINetworkFlag(flags.EnvVarPrefix, ""), }, Action: func(ctx *cli.Context) error { logCfg := oplog.ReadCLIConfig(ctx) @@ -29,7 +29,7 @@ var Subcommands = []*cli.Command{ return errors.New("must specify a network name") } - rCfg, err := opnode.NewRollupConfig(logger, ctx) + rCfg, err := opnode.NewRollupConfigFromCLI(logger, ctx) if err != nil { return err } diff --git a/op-node/cmd/stateviz/assets/index.html b/op-node/cmd/stateviz/assets/index.html deleted file mode 100644 index 73388f3f077f..000000000000 --- a/op-node/cmd/stateviz/assets/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - -
-
-
-
- - - - - - - - - diff --git a/op-node/cmd/stateviz/assets/main.js b/op-node/cmd/stateviz/assets/main.js deleted file mode 100644 index d713cd4797e5..000000000000 --- a/op-node/cmd/stateviz/assets/main.js +++ /dev/null @@ -1,125 +0,0 @@ -function prettyHex(hash) { - return `${hash.slice(0, 8)}..${hash.slice(56)}`; -} - -// return a light-ish hue -function colorCode(hash) { - const code = parseInt(hash.slice(60), 16); - const h = code % 361; - const s = code % 101; - let l = code % 101; - // yeah this is biased but it's good enough - if (l < 30) { - l += 30; - } - return `hsl(${h}, ${s}%, ${l}%)`; -} - -async function fetchLogs() { - const response = await fetch("/logs"); - return await response.json(); -} - -function tooltipFormat(v) { - var out = "" - out += `
` - out += `hash: ${v["hash"]}
` - out += `num: ${v["number"]}
` - out += `parent: ${v["parentHash"]}
` - out += `time: ${v["timestamp"]}
` - if(v.hasOwnProperty("l1origin")) { - out += `L1 hash: ${v["l1origin"]["hash"]}
` - out += `L1 num: ${v["l1origin"]["number"]}
` - out += `seq: ${v["sequenceNumber"]}
` - } - out += `
` - return out -} - -async function pageTable() { - const logs = await fetchLogs(); - if (logs.length === 0) { - return - } - - const dataEl = $(`
`); - $("#logs").append(dataEl); - - let numCols = 0 - if (logs.length !== 0) { - numCols = logs[0].length - } - const paginationEl = $(``) - $("#logs").append(paginationEl) - paginationEl.pagination({ - dataSource: logs, - pageSize: 40, - showGoInput: true, - showGoButton: true, - callback: (data, pagination) => { - let tables = [] - for (var i = 0; i < numCols; i++) { - // TODO: Fix grid overflow with more than 2 rollup drivers - let html = '
'; - html += ` - - - - - - - - - - - - `; - html += ""; - - // TODO: it'll also be useful to indicate which rollup driver updated its state for the given timestamp - for (const record of data) { - const e = record[i]; - if (e === undefined) { - // this column has reached its end - break - } - // outer stringify in title attribute escapes the content and adds the quotes for the html to be valid - // inner stringify in - - // TODO: click to copy full hash - html += ` - - - - - - - `; - } - html += ""; - html += "
${data[0][i].engine_addr}
TimestampL1HeadL1CurrentL2HeadL2SafeL2FinalizedHead
- ${e.t} - - ${prettyHex(e.l1Head.hash)} - - ${prettyHex(e.l1Current.hash)} - - ${prettyHex(e.l2Head.hash)} - - ${prettyHex(e.l2Safe.hash)} - - ${prettyHex(e.l2FinalizedHead.hash)} -
"; - tables.push(html); - } - - const html = tables.join("\n"); - dataEl.html(html); - $('[data-toggle="tooltip"]').tooltip(); - } - }) -} - -(async () => { - pageTable() -})() diff --git a/op-node/cmd/stateviz/main.go b/op-node/cmd/stateviz/main.go deleted file mode 100644 index 8479984361bd..000000000000 --- a/op-node/cmd/stateviz/main.go +++ /dev/null @@ -1,244 +0,0 @@ -package main - -import ( - "bufio" - "compress/gzip" - "embed" - "encoding/json" - "errors" - "flag" - "fmt" - "io" - "io/fs" - "net" - "net/http" - "os" - "strconv" - "strings" - "sync" - "time" - - "github.com/ethereum-optimism/optimism/op-service/eth" - ophttp "github.com/ethereum-optimism/optimism/op-service/httputil" - "github.com/ethereum/go-ethereum/log" -) - -var ( - snapshot = flag.String("snapshot", "", "path to snapshot log") - listenAddr = flag.String("addr", "", "listen address of webserver") - refresh = flag.Duration("refresh", 10*time.Second, "snapshot refresh rate") -) - -var ( - entries map[string][]SnapshotState - entriesMutex sync.Mutex - - assetFS fs.FS -) - -type SnapshotState struct { - Timestamp string `json:"t"` - EngineAddr string `json:"engine_addr"` - Event string `json:"event"` // event name - L1Head eth.L1BlockRef `json:"l1Head"` // what we see as head on L1 - L1Current eth.L1BlockRef `json:"l1Current"` // l1 block that the derivation is currently using - L2Head eth.L2BlockRef `json:"l2Head"` // l2 block that was last optimistically accepted (unsafe head) - L2Safe eth.L2BlockRef `json:"l2Safe"` // l2 block that was last derived - L2FinalizedHead eth.BlockID `json:"l2FinalizedHead"` // l2 block that is irreversible -} - -func (e *SnapshotState) UnmarshalJSON(data []byte) error { - t := struct { - Timestamp string `json:"t"` - EngineAddr string `json:"engine_addr"` - Event string `json:"event"` - L1Head json.RawMessage `json:"l1Head"` - L1Current json.RawMessage `json:"l1Current"` - L2Head json.RawMessage `json:"l2Head"` - L2Safe json.RawMessage `json:"l2Safe"` - L2FinalizedHead json.RawMessage `json:"l2FinalizedHead"` - }{} - if err := json.Unmarshal(data, &t); err != nil { - return err - } - e.Timestamp = t.Timestamp - e.EngineAddr = t.EngineAddr - e.Event = t.Event - - unquote := func(d json.RawMessage) []byte { - s, _ := strconv.Unquote(string(d)) - return []byte(s) - } - - if err := json.Unmarshal(unquote(t.L1Head), &e.L1Head); err != nil { - return err - } - if err := json.Unmarshal(unquote(t.L1Current), &e.L1Current); err != nil { - return err - } - if err := json.Unmarshal(unquote(t.L2Head), &e.L2Head); err != nil { - return err - } - if err := json.Unmarshal(unquote(t.L2Safe), &e.L2Safe); err != nil { - return err - } - if err := json.Unmarshal(unquote(t.L2FinalizedHead), &e.L2FinalizedHead); err != nil { - return err - } - return nil -} - -//go:embed assets -var embeddedAssets embed.FS - -func main() { - flag.Parse() - - log.Root().SetHandler( - log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stdout, log.TerminalFormat(true))), - ) - - if *snapshot == "" { - log.Crit("missing required -snapshot flag") - } - - sub, err := fs.Sub(embeddedAssets, "assets") - if err != nil { - log.Crit("Failed to open asset directory", "message", err) - } - assetFS = sub - - go func() { - ticker := time.NewTicker(*refresh) - defer ticker.Stop() - for range ticker.C { - // TODO: incremental load - log.Info("loading snapshot...") - if err := loadSnapshot(); err != nil { - log.Error("failed to load snapshot", "err", err) - } - } - }() - - runServer() -} - -func loadSnapshot() error { - file, err := os.Open(*snapshot) - if err != nil { - return fmt.Errorf("%w: failed to open snapshot file", err) - } - defer file.Close() - - tempEntries := make(map[string][]SnapshotState) - scanner := bufio.NewScanner(file) - for scanner.Scan() { - var entry SnapshotState - if err := json.Unmarshal([]byte(scanner.Text()), &entry); err != nil { - return fmt.Errorf("%w: failed to decode snapshot log", err) - } - - tempEntries[entry.EngineAddr] = append(tempEntries[entry.EngineAddr], entry) - } - if err := scanner.Err(); err != nil { - return fmt.Errorf("%w: failed to scan snapshot file", err) - } - - entriesMutex.Lock() - entries = tempEntries - entriesMutex.Unlock() - - return nil -} - -func runServer() { - l, err := net.Listen("tcp", *listenAddr) - if err != nil { - log.Crit("Failed to listen on address", "message", err) - } - - mux := http.NewServeMux() - mux.Handle("/", http.FileServer(http.FS(assetFS))) - mux.HandleFunc("/logs", makeGzipHandler(logsHandler)) - - log.Info("running webserver...") - httpServer := ophttp.NewHttpServer(mux) - if err := httpServer.Serve(l); err != nil && !errors.Is(err, http.ErrServerClosed) { - log.Crit("http server failed", "message", err) - } -} - -type gzipResponseWriter struct { - io.Writer - http.ResponseWriter -} - -func (w gzipResponseWriter) Write(b []byte) (int, error) { - return w.Writer.Write(b) -} - -func makeGzipHandler(fn http.HandlerFunc) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { - fn(w, r) - return - } - w.Header().Set("Content-Encoding", "gzip") - gz := gzip.NewWriter(w) - defer gz.Close() - gzr := gzipResponseWriter{Writer: gz, ResponseWriter: w} - fn(gzr, r) - } -} - -func logsHandler(w http.ResponseWriter, r *http.Request) { - var output [][]SnapshotState - - entriesMutex.Lock() - // shallow copy so we can update the SnapshotState slice head - entriesCopy := make(map[string][]SnapshotState) - for k, v := range entries { - entriesCopy[k] = v - } - entriesMutex.Unlock() - - // sort log entries and zip em up - // Each record/row contains SnapshotStates for each rollup driver - // Note that we assume each SnapshotState slice is sorted by the timestamp - for { - var min *SnapshotState - var minKey string - for k, v := range entriesCopy { - if len(v) == 0 { - continue - } - if min == nil || v[0].Timestamp < min.Timestamp { - min = &v[0] - minKey = k - } - } - - if min == nil { - break - } - - entriesCopy[minKey] = entriesCopy[minKey][1:] - - rec := make([]SnapshotState, 0, len(entriesCopy)) - rec = append(rec, *min) - for k, v := range entriesCopy { - if k != minKey && len(v) != 0 { - newEntry := v[0] - newEntry.Timestamp = min.Timestamp - rec = append(rec, newEntry) - } - } - output = append(output, rec) - } - - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Cache-Control", "public, max-age=100000") - if err := json.NewEncoder(w).Encode(output); err != nil { - log.Warn("failed to encode logs", "message", err) - } -} diff --git a/op-node/flags/flags.go b/op-node/flags/flags.go index 3dd910538913..24ca78b45c00 100644 --- a/op-node/flags/flags.go +++ b/op-node/flags/flags.go @@ -7,6 +7,7 @@ import ( "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + plasma "github.com/ethereum-optimism/optimism/op-plasma" openum "github.com/ethereum-optimism/optimism/op-service/enum" opflags "github.com/ethereum-optimism/optimism/op-service/flags" oplog "github.com/ethereum-optimism/optimism/op-service/log" @@ -18,6 +19,21 @@ import ( const EnvVarPrefix = "OP_NODE" +const ( + RollupCategory = "1. ROLLUP" + L1RPCCategory = "2. L1 RPC" + SequencerCategory = "3. SEQUENCER" + OperationsCategory = "4. LOGGING, METRICS, DEBUGGING, AND API" + P2PCategory = "5. PEER-TO-PEER" + PlasmaCategory = "6. PLASMA (EXPERIMENTAL)" + MiscCategory = "7. MISC" +) + +func init() { + cli.HelpFlag.(*cli.BoolFlag).Category = MiscCategory + cli.VersionFlag.(*cli.BoolFlag).Category = MiscCategory +} + func prefixEnvVars(name string) []string { return []string{EnvVarPrefix + "_" + name} } @@ -25,15 +41,17 @@ func prefixEnvVars(name string) []string { var ( /* Required Flags */ L1NodeAddr = &cli.StringFlag{ - Name: "l1", - Usage: "Address of L1 User JSON-RPC endpoint to use (eth namespace required)", - Value: "http://127.0.0.1:8545", - EnvVars: prefixEnvVars("L1_ETH_RPC"), + Name: "l1", + Usage: "Address of L1 User JSON-RPC endpoint to use (eth namespace required)", + Value: "http://127.0.0.1:8545", + EnvVars: prefixEnvVars("L1_ETH_RPC"), + Category: RollupCategory, } L2EngineAddr = &cli.StringFlag{ - Name: "l2", - Usage: "Address of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required)", - EnvVars: prefixEnvVars("L2_ENGINE_RPC"), + Name: "l2", + Usage: "Address of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required)", + EnvVars: prefixEnvVars("L2_ENGINE_RPC"), + Category: RollupCategory, } L2EngineJWTSecret = &cli.StringFlag{ Name: "l2.jwt-secret", @@ -41,13 +59,29 @@ var ( EnvVars: prefixEnvVars("L2_ENGINE_AUTH"), Value: "", Destination: new(string), + Category: RollupCategory, } - /* Optional Flags */ BeaconAddr = &cli.StringFlag{ Name: "l1.beacon", Usage: "Address of L1 Beacon-node HTTP endpoint to use.", Required: false, EnvVars: prefixEnvVars("L1_BEACON"), + Category: RollupCategory, + } + /* Optional Flags */ + BeaconHeader = &cli.StringFlag{ + Name: "l1.beacon-header", + Usage: "Optional HTTP header to add to all requests to the L1 Beacon endpoint. Format: 'X-Key: Value'", + Required: false, + EnvVars: prefixEnvVars("L1_BEACON_HEADER"), + Category: L1RPCCategory, + } + BeaconArchiverAddr = &cli.StringFlag{ + Name: "l1.beacon-archiver", + Usage: "Address of L1 Beacon-node compatible HTTP endpoint to use. This is used to fetch blobs that the --l1.beacon does not have (i.e expired blobs).", + Required: false, + EnvVars: prefixEnvVars("L1_BEACON_ARCHIVER"), + Category: L1RPCCategory, } BeaconCheckIgnore = &cli.BoolFlag{ Name: "l1.beacon.ignore", @@ -55,43 +89,57 @@ var ( Required: false, Value: false, EnvVars: prefixEnvVars("L1_BEACON_IGNORE"), + Category: L1RPCCategory, + } + BeaconFetchAllSidecars = &cli.BoolFlag{ + Name: "l1.beacon.fetch-all-sidecars", + Usage: "If true, all sidecars are fetched and filtered locally. Workaround for buggy Beacon nodes.", + Required: false, + Value: false, + EnvVars: prefixEnvVars("L1_BEACON_FETCH_ALL_SIDECARS"), + Category: L1RPCCategory, } SyncModeFlag = &cli.GenericFlag{ Name: "syncmode", - Usage: fmt.Sprintf("IN DEVELOPMENT: Options are: %s", openum.EnumString(sync.ModeStrings)), + Usage: fmt.Sprintf("Blockchain sync mode (options: %s)", openum.EnumString(sync.ModeStrings)), EnvVars: prefixEnvVars("SYNCMODE"), Value: func() *sync.Mode { out := sync.CLSync return &out }(), - Hidden: true, + Category: RollupCategory, } RPCListenAddr = &cli.StringFlag{ - Name: "rpc.addr", - Usage: "RPC listening address", - EnvVars: prefixEnvVars("RPC_ADDR"), - Value: "127.0.0.1", + Name: "rpc.addr", + Usage: "RPC listening address", + EnvVars: prefixEnvVars("RPC_ADDR"), + Value: "127.0.0.1", + Category: OperationsCategory, } RPCListenPort = &cli.IntFlag{ - Name: "rpc.port", - Usage: "RPC listening port", - EnvVars: prefixEnvVars("RPC_PORT"), - Value: 9545, // Note: op-service/rpc/cli.go uses 8545 as the default. + Name: "rpc.port", + Usage: "RPC listening port", + EnvVars: prefixEnvVars("RPC_PORT"), + Value: 9545, // Note: op-service/rpc/cli.go uses 8545 as the default. + Category: OperationsCategory, } RPCEnableAdmin = &cli.BoolFlag{ - Name: "rpc.enable-admin", - Usage: "Enable the admin API (experimental)", - EnvVars: prefixEnvVars("RPC_ENABLE_ADMIN"), + Name: "rpc.enable-admin", + Usage: "Enable the admin API (experimental)", + EnvVars: prefixEnvVars("RPC_ENABLE_ADMIN"), + Category: OperationsCategory, } RPCAdminPersistence = &cli.StringFlag{ - Name: "rpc.admin-state", - Usage: "File path used to persist state changes made via the admin API so they persist across restarts. Disabled if not set.", - EnvVars: prefixEnvVars("RPC_ADMIN_STATE"), + Name: "rpc.admin-state", + Usage: "File path used to persist state changes made via the admin API so they persist across restarts. Disabled if not set.", + EnvVars: prefixEnvVars("RPC_ADMIN_STATE"), + Category: OperationsCategory, } L1TrustRPC = &cli.BoolFlag{ - Name: "l1.trustrpc", - Usage: "Trust the L1 RPC, sync faster at risk of malicious/buggy RPC providing bad or inconsistent L1 data", - EnvVars: prefixEnvVars("L1_TRUST_RPC"), + Name: "l1.trustrpc", + Usage: "Trust the L1 RPC, sync faster at risk of malicious/buggy RPC providing bad or inconsistent L1 data", + EnvVars: prefixEnvVars("L1_TRUST_RPC"), + Category: L1RPCCategory, } L1RPCProviderKind = &cli.GenericFlag{ Name: "l1.rpckind", @@ -102,124 +150,152 @@ var ( out := sources.RPCKindStandard return &out }(), + Category: L1RPCCategory, } L1RethDBPath = &cli.StringFlag{ - Name: "l1.rethdb", - Usage: "The L1 RethDB path, used to fetch receipts for L1 blocks. Only applicable when using the `reth_db` RPC kind with `l1.rpckind`.", - EnvVars: prefixEnvVars("L1_RETHDB"), - Hidden: true, + Name: "l1.rethdb", + Usage: "The L1 RethDB path, used to fetch receipts for L1 blocks. Only applicable when using the `reth_db` RPC kind with `l1.rpckind`.", + EnvVars: prefixEnvVars("L1_RETHDB"), + Hidden: true, + Category: L1RPCCategory, } L1RPCMaxConcurrency = &cli.IntFlag{ - Name: "l1.max-concurrency", - Usage: "Maximum number of concurrent RPC requests to make to the L1 RPC provider.", - EnvVars: prefixEnvVars("L1_MAX_CONCURRENCY"), - Value: 10, + Name: "l1.max-concurrency", + Usage: "Maximum number of concurrent RPC requests to make to the L1 RPC provider.", + EnvVars: prefixEnvVars("L1_MAX_CONCURRENCY"), + Value: 10, + Category: L1RPCCategory, } L1RPCRateLimit = &cli.Float64Flag{ - Name: "l1.rpc-rate-limit", - Usage: "Optional self-imposed global rate-limit on L1 RPC requests, specified in requests / second. Disabled if set to 0.", - EnvVars: prefixEnvVars("L1_RPC_RATE_LIMIT"), - Value: 0, + Name: "l1.rpc-rate-limit", + Usage: "Optional self-imposed global rate-limit on L1 RPC requests, specified in requests / second. Disabled if set to 0.", + EnvVars: prefixEnvVars("L1_RPC_RATE_LIMIT"), + Value: 0, + Category: L1RPCCategory, } L1RPCMaxBatchSize = &cli.IntFlag{ - Name: "l1.rpc-max-batch-size", - Usage: "Maximum number of RPC requests to bundle, e.g. during L1 blocks receipt fetching. The L1 RPC rate limit counts this as N items, but allows it to burst at once.", - EnvVars: prefixEnvVars("L1_RPC_MAX_BATCH_SIZE"), - Value: 20, + Name: "l1.rpc-max-batch-size", + Usage: "Maximum number of RPC requests to bundle, e.g. during L1 blocks receipt fetching. The L1 RPC rate limit counts this as N items, but allows it to burst at once.", + EnvVars: prefixEnvVars("L1_RPC_MAX_BATCH_SIZE"), + Value: 20, + Category: L1RPCCategory, } L1HTTPPollInterval = &cli.DurationFlag{ - Name: "l1.http-poll-interval", - Usage: "Polling interval for latest-block subscription when using an HTTP RPC provider. Ignored for other types of RPC endpoints.", - EnvVars: prefixEnvVars("L1_HTTP_POLL_INTERVAL"), - Value: time.Second * 12, + Name: "l1.http-poll-interval", + Usage: "Polling interval for latest-block subscription when using an HTTP RPC provider. Ignored for other types of RPC endpoints.", + EnvVars: prefixEnvVars("L1_HTTP_POLL_INTERVAL"), + Value: time.Second * 12, + Category: L1RPCCategory, } VerifierL1Confs = &cli.Uint64Flag{ - Name: "verifier.l1-confs", - Usage: "Number of L1 blocks to keep distance from the L1 head before deriving L2 data from. Reorgs are supported, but may be slow to perform.", - EnvVars: prefixEnvVars("VERIFIER_L1_CONFS"), - Value: 0, + Name: "verifier.l1-confs", + Usage: "Number of L1 blocks to keep distance from the L1 head before deriving L2 data from. Reorgs are supported, but may be slow to perform.", + EnvVars: prefixEnvVars("VERIFIER_L1_CONFS"), + Value: 0, + Category: L1RPCCategory, } SequencerEnabledFlag = &cli.BoolFlag{ - Name: "sequencer.enabled", - Usage: "Enable sequencing of new L2 blocks. A separate batch submitter has to be deployed to publish the data for verifiers.", - EnvVars: prefixEnvVars("SEQUENCER_ENABLED"), + Name: "sequencer.enabled", + Usage: "Enable sequencing of new L2 blocks. A separate batch submitter has to be deployed to publish the data for verifiers.", + EnvVars: prefixEnvVars("SEQUENCER_ENABLED"), + Category: SequencerCategory, } SequencerStoppedFlag = &cli.BoolFlag{ - Name: "sequencer.stopped", - Usage: "Initialize the sequencer in a stopped state. The sequencer can be started using the admin_startSequencer RPC", - EnvVars: prefixEnvVars("SEQUENCER_STOPPED"), + Name: "sequencer.stopped", + Usage: "Initialize the sequencer in a stopped state. The sequencer can be started using the admin_startSequencer RPC", + EnvVars: prefixEnvVars("SEQUENCER_STOPPED"), + Category: SequencerCategory, } SequencerMaxSafeLagFlag = &cli.Uint64Flag{ - Name: "sequencer.max-safe-lag", - Usage: "Maximum number of L2 blocks for restricting the distance between L2 safe and unsafe. Disabled if 0.", - EnvVars: prefixEnvVars("SEQUENCER_MAX_SAFE_LAG"), - Value: 0, + Name: "sequencer.max-safe-lag", + Usage: "Maximum number of L2 blocks for restricting the distance between L2 safe and unsafe. Disabled if 0.", + EnvVars: prefixEnvVars("SEQUENCER_MAX_SAFE_LAG"), + Value: 0, + Category: SequencerCategory, } SequencerL1Confs = &cli.Uint64Flag{ - Name: "sequencer.l1-confs", - Usage: "Number of L1 blocks to keep distance from the L1 head as a sequencer for picking an L1 origin.", - EnvVars: prefixEnvVars("SEQUENCER_L1_CONFS"), - Value: 4, + Name: "sequencer.l1-confs", + Usage: "Number of L1 blocks to keep distance from the L1 head as a sequencer for picking an L1 origin.", + EnvVars: prefixEnvVars("SEQUENCER_L1_CONFS"), + Value: 4, + Category: SequencerCategory, } L1EpochPollIntervalFlag = &cli.DurationFlag{ - Name: "l1.epoch-poll-interval", - Usage: "Poll interval for retrieving new L1 epoch updates such as safe and finalized block changes. Disabled if 0 or negative.", - EnvVars: prefixEnvVars("L1_EPOCH_POLL_INTERVAL"), - Value: time.Second * 12 * 32, + Name: "l1.epoch-poll-interval", + Usage: "Poll interval for retrieving new L1 epoch updates such as safe and finalized block changes. Disabled if 0 or negative.", + EnvVars: prefixEnvVars("L1_EPOCH_POLL_INTERVAL"), + Value: time.Second * 12 * 32, + Category: L1RPCCategory, } RuntimeConfigReloadIntervalFlag = &cli.DurationFlag{ - Name: "l1.runtime-config-reload-interval", - Usage: "Poll interval for reloading the runtime config, useful when config events are not being picked up. Disabled if 0 or negative.", - EnvVars: prefixEnvVars("L1_RUNTIME_CONFIG_RELOAD_INTERVAL"), - Value: time.Minute * 10, + Name: "l1.runtime-config-reload-interval", + Usage: "Poll interval for reloading the runtime config, useful when config events are not being picked up. Disabled if 0 or negative.", + EnvVars: prefixEnvVars("L1_RUNTIME_CONFIG_RELOAD_INTERVAL"), + Value: time.Minute * 10, + Category: L1RPCCategory, } MetricsEnabledFlag = &cli.BoolFlag{ - Name: "metrics.enabled", - Usage: "Enable the metrics server", - EnvVars: prefixEnvVars("METRICS_ENABLED"), + Name: "metrics.enabled", + Usage: "Enable the metrics server", + EnvVars: prefixEnvVars("METRICS_ENABLED"), + Category: OperationsCategory, } MetricsAddrFlag = &cli.StringFlag{ - Name: "metrics.addr", - Usage: "Metrics listening address", - Value: "0.0.0.0", // TODO(CLI-4159): Switch to 127.0.0.1 - EnvVars: prefixEnvVars("METRICS_ADDR"), + Name: "metrics.addr", + Usage: "Metrics listening address", + Value: "0.0.0.0", // TODO(CLI-4159): Switch to 127.0.0.1 + EnvVars: prefixEnvVars("METRICS_ADDR"), + Category: OperationsCategory, } MetricsPortFlag = &cli.IntFlag{ - Name: "metrics.port", - Usage: "Metrics listening port", - Value: 7300, - EnvVars: prefixEnvVars("METRICS_PORT"), + Name: "metrics.port", + Usage: "Metrics listening port", + Value: 7300, + EnvVars: prefixEnvVars("METRICS_PORT"), + Category: OperationsCategory, } SnapshotLog = &cli.StringFlag{ - Name: "snapshotlog.file", - Usage: "Path to the snapshot log file", - EnvVars: prefixEnvVars("SNAPSHOT_LOG"), + Name: "snapshotlog.file", + Usage: "Path to the snapshot log file", + EnvVars: prefixEnvVars("SNAPSHOT_LOG"), + Category: OperationsCategory, } HeartbeatEnabledFlag = &cli.BoolFlag{ - Name: "heartbeat.enabled", - Usage: "Enables or disables heartbeating", - EnvVars: prefixEnvVars("HEARTBEAT_ENABLED"), + Name: "heartbeat.enabled", + Usage: "Enables or disables heartbeating", + EnvVars: prefixEnvVars("HEARTBEAT_ENABLED"), + Category: OperationsCategory, } HeartbeatMonikerFlag = &cli.StringFlag{ - Name: "heartbeat.moniker", - Usage: "Sets a moniker for this node", - EnvVars: prefixEnvVars("HEARTBEAT_MONIKER"), + Name: "heartbeat.moniker", + Usage: "Sets a moniker for this node", + EnvVars: prefixEnvVars("HEARTBEAT_MONIKER"), + Category: OperationsCategory, } HeartbeatURLFlag = &cli.StringFlag{ - Name: "heartbeat.url", - Usage: "Sets the URL to heartbeat to", - EnvVars: prefixEnvVars("HEARTBEAT_URL"), - Value: "https://heartbeat.optimism.io", + Name: "heartbeat.url", + Usage: "Sets the URL to heartbeat to", + EnvVars: prefixEnvVars("HEARTBEAT_URL"), + Value: "https://heartbeat.optimism.io", + Category: OperationsCategory, } RollupHalt = &cli.StringFlag{ - Name: "rollup.halt", - Usage: "Opt-in option to halt on incompatible protocol version requirements of the given level (major/minor/patch/none), as signaled onchain in L1", - EnvVars: prefixEnvVars("ROLLUP_HALT"), + Name: "rollup.halt", + Usage: "Opt-in option to halt on incompatible protocol version requirements of the given level (major/minor/patch/none), as signaled onchain in L1", + EnvVars: prefixEnvVars("ROLLUP_HALT"), + Category: RollupCategory, } RollupLoadProtocolVersions = &cli.BoolFlag{ - Name: "rollup.load-protocol-versions", - Usage: "Load protocol versions from the superchain L1 ProtocolVersions contract (if available), and report in logs and metrics", - EnvVars: prefixEnvVars("ROLLUP_LOAD_PROTOCOL_VERSIONS"), + Name: "rollup.load-protocol-versions", + Usage: "Load protocol versions from the superchain L1 ProtocolVersions contract (if available), and report in logs and metrics", + EnvVars: prefixEnvVars("ROLLUP_LOAD_PROTOCOL_VERSIONS"), + Category: RollupCategory, + } + SafeDBPath = &cli.StringFlag{ + Name: "safedb.path", + Usage: "File path used to persist safe head update data. Disabled if not set.", + EnvVars: prefixEnvVars("SAFEDB_PATH"), + Category: OperationsCategory, } /* Deprecated Flags */ L2EngineSyncEnabled = &cli.BoolFlag{ @@ -257,22 +333,37 @@ var ( Hidden: true, } ConductorEnabledFlag = &cli.BoolFlag{ - Name: "conductor.enabled", - Usage: "Enable the conductor service", - EnvVars: prefixEnvVars("CONDUCTOR_ENABLED"), - Value: false, + Name: "conductor.enabled", + Usage: "Enable the conductor service", + EnvVars: prefixEnvVars("CONDUCTOR_ENABLED"), + Value: false, + Category: SequencerCategory, } ConductorRpcFlag = &cli.StringFlag{ - Name: "conductor.rpc", - Usage: "Conductor service rpc endpoint", - EnvVars: prefixEnvVars("CONDUCTOR_RPC"), - Value: "http://127.0.0.1:8547", + Name: "conductor.rpc", + Usage: "Conductor service rpc endpoint", + EnvVars: prefixEnvVars("CONDUCTOR_RPC"), + Value: "http://127.0.0.1:8547", + Category: SequencerCategory, } ConductorRpcTimeoutFlag = &cli.DurationFlag{ - Name: "conductor.rpc-timeout", - Usage: "Conductor service rpc timeout", - EnvVars: prefixEnvVars("CONDUCTOR_RPC_TIMEOUT"), - Value: time.Second * 1, + Name: "conductor.rpc-timeout", + Usage: "Conductor service rpc timeout", + EnvVars: prefixEnvVars("CONDUCTOR_RPC_TIMEOUT"), + Value: time.Second * 1, + Category: SequencerCategory, + } + DARPC = &cli.StringFlag{ + Name: "da-rpc", + Usage: "Data Availability RPC", + Value: "http://da:26658", + EnvVars: prefixEnvVars("DA_RPC"), + } + PrefixDerivationEnabledFlag = &cli.BoolFlag{ + Name: "da-prefix-derivation-enabled", + Usage: "Enable prefix derivation", + Value: false, + EnvVars: prefixEnvVars("DA_PREFIX_DERIVATION_ENABLED"), } ) @@ -280,11 +371,15 @@ var requiredFlags = []cli.Flag{ L1NodeAddr, L2EngineAddr, L2EngineJWTSecret, + DARPC, } var optionalFlags = []cli.Flag{ BeaconAddr, + BeaconHeader, + BeaconArchiverAddr, BeaconCheckIgnore, + BeaconFetchAllSidecars, SyncModeFlag, RPCListenAddr, RPCListenPort, @@ -316,6 +411,8 @@ var optionalFlags = []cli.Flag{ ConductorEnabledFlag, ConductorRpcFlag, ConductorRpcTimeoutFlag, + SafeDBPath, + PrefixDerivationEnabledFlag, } var DeprecatedFlags = []cli.Flag{ @@ -333,10 +430,11 @@ var Flags []cli.Flag func init() { DeprecatedFlags = append(DeprecatedFlags, deprecatedP2PFlags(EnvVarPrefix)...) optionalFlags = append(optionalFlags, P2PFlags(EnvVarPrefix)...) - optionalFlags = append(optionalFlags, oplog.CLIFlags(EnvVarPrefix)...) - optionalFlags = append(optionalFlags, oppprof.CLIFlags(EnvVarPrefix)...) + optionalFlags = append(optionalFlags, oplog.CLIFlagsWithCategory(EnvVarPrefix, OperationsCategory)...) + optionalFlags = append(optionalFlags, oppprof.CLIFlagsWithCategory(EnvVarPrefix, OperationsCategory)...) optionalFlags = append(optionalFlags, DeprecatedFlags...) - optionalFlags = append(optionalFlags, opflags.CLIFlags(EnvVarPrefix)...) + optionalFlags = append(optionalFlags, opflags.CLIFlags(EnvVarPrefix, RollupCategory)...) + optionalFlags = append(optionalFlags, plasma.CLIFlags(EnvVarPrefix, PlasmaCategory)...) Flags = append(requiredFlags, optionalFlags...) } diff --git a/op-node/flags/p2p_flags.go b/op-node/flags/p2p_flags.go index ca9851da98f2..419d0bd4f0f4 100644 --- a/op-node/flags/p2p_flags.go +++ b/op-node/flags/p2p_flags.go @@ -53,6 +53,7 @@ var ( GossipMeshDlazyName = "p2p.gossip.mesh.dlazy" GossipFloodPublishName = "p2p.gossip.mesh.floodpublish" SyncReqRespName = "p2p.sync.req-resp" + P2PPingName = "p2p.ping" ) func deprecatedP2PFlags(envPrefix string) []cli.Flag { @@ -62,6 +63,7 @@ func deprecatedP2PFlags(envPrefix string) []cli.Flag { Usage: fmt.Sprintf("Deprecated: Use %v instead", ScoringName), Required: false, Hidden: true, + Category: P2PCategory, }, &cli.StringFlag{ Name: PeerScoreBandsName, @@ -69,12 +71,14 @@ func deprecatedP2PFlags(envPrefix string) []cli.Flag { Required: false, Value: "", Hidden: true, + Category: P2PCategory, }, &cli.StringFlag{ Name: TopicScoringName, Usage: fmt.Sprintf("Deprecated: Use %v instead", ScoringName), Required: false, Hidden: true, + Category: P2PCategory, }, } } @@ -88,12 +92,14 @@ func P2PFlags(envPrefix string) []cli.Flag { Usage: "Completely disable the P2P stack", Required: false, EnvVars: p2pEnv(envPrefix, "DISABLE"), + Category: P2PCategory, }, &cli.BoolFlag{ Name: NoDiscoveryName, Usage: "Disable Discv5 (node discovery)", Required: false, EnvVars: p2pEnv(envPrefix, "NO_DISCOVERY"), + Category: P2PCategory, }, &cli.StringFlag{ Name: ScoringName, @@ -101,6 +107,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: "light", EnvVars: p2pEnv(envPrefix, "PEER_SCORING"), + Category: P2PCategory, }, &cli.BoolFlag{ // Banning Flag - whether or not we want to act on the scoring @@ -109,6 +116,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Value: true, Required: false, EnvVars: p2pEnv(envPrefix, "PEER_BANNING"), + Category: P2PCategory, }, &cli.Float64Flag{ Name: BanningThresholdName, @@ -116,6 +124,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: -100, EnvVars: p2pEnv(envPrefix, "PEER_BANNING_THRESHOLD"), + Category: P2PCategory, }, &cli.DurationFlag{ Name: BanningDurationName, @@ -123,6 +132,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: 1 * time.Hour, EnvVars: p2pEnv(envPrefix, "PEER_BANNING_DURATION"), + Category: P2PCategory, }, &cli.StringFlag{ Name: P2PPrivPathName, @@ -132,6 +142,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Value: "opnode_p2p_priv.txt", EnvVars: p2pEnv(envPrefix, "PRIV_PATH"), TakesFile: true, + Category: P2PCategory, }, &cli.StringFlag{ // sometimes it may be ok to not persist the peer priv key as file, and instead pass it directly. @@ -141,6 +152,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Hidden: true, Value: "", EnvVars: p2pEnv(envPrefix, "PRIV_RAW"), + Category: P2PCategory, }, &cli.StringFlag{ Name: ListenIPName, @@ -148,6 +160,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: "0.0.0.0", EnvVars: p2pEnv(envPrefix, "LISTEN_IP"), + Category: P2PCategory, }, &cli.UintFlag{ Name: ListenTCPPortName, @@ -155,6 +168,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: 9222, EnvVars: p2pEnv(envPrefix, "LISTEN_TCP_PORT"), + Category: P2PCategory, }, &cli.UintFlag{ Name: ListenUDPPortName, @@ -162,6 +176,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: 0, // can simply match the TCP libp2p port EnvVars: p2pEnv(envPrefix, "LISTEN_UDP_PORT"), + Category: P2PCategory, }, &cli.StringFlag{ Name: AdvertiseIPName, @@ -169,8 +184,9 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, // Ignored by default, nodes can discover their own external IP in the happy case, // by communicating with bootnodes. Fixed IP is recommended for faster bootstrap though. - Value: "", - EnvVars: p2pEnv(envPrefix, "ADVERTISE_IP"), + Value: "", + EnvVars: p2pEnv(envPrefix, "ADVERTISE_IP"), + Category: P2PCategory, }, &cli.UintFlag{ Name: AdvertiseTCPPortName, @@ -178,6 +194,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: 0, EnvVars: p2pEnv(envPrefix, "ADVERTISE_TCP"), + Category: P2PCategory, }, &cli.UintFlag{ Name: AdvertiseUDPPortName, @@ -185,6 +202,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: 0, EnvVars: p2pEnv(envPrefix, "ADVERTISE_UDP"), + Category: P2PCategory, }, &cli.StringFlag{ Name: BootnodesName, @@ -192,6 +210,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: "", EnvVars: p2pEnv(envPrefix, "BOOTNODES"), + Category: P2PCategory, }, &cli.StringFlag{ Name: StaticPeersName, @@ -200,12 +219,14 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: "", EnvVars: p2pEnv(envPrefix, "STATIC"), + Category: P2PCategory, }, &cli.StringFlag{ Name: NetRestrictName, Usage: "Comma-separated list of CIDR masks. P2P will only try to connect on these networks", Required: false, EnvVars: p2pEnv(envPrefix, "NETRESTRICT"), + Category: P2PCategory, }, &cli.StringFlag{ Name: HostMuxName, @@ -214,6 +235,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: "yamux,mplex", EnvVars: p2pEnv(envPrefix, "MUX"), + Category: P2PCategory, }, &cli.StringFlag{ Name: HostSecurityName, @@ -222,6 +244,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: "noise", EnvVars: p2pEnv(envPrefix, "SECURITY"), + Category: P2PCategory, }, &cli.UintFlag{ Name: PeersLoName, @@ -229,6 +252,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: 20, EnvVars: p2pEnv(envPrefix, "PEERS_LO"), + Category: P2PCategory, }, &cli.UintFlag{ Name: PeersHiName, @@ -236,6 +260,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: 30, EnvVars: p2pEnv(envPrefix, "PEERS_HI"), + Category: P2PCategory, }, &cli.DurationFlag{ Name: PeersGraceName, @@ -243,12 +268,14 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: 30 * time.Second, EnvVars: p2pEnv(envPrefix, "PEERS_GRACE"), + Category: P2PCategory, }, &cli.BoolFlag{ Name: NATName, Usage: "Enable NAT traversal with PMP/UPNP devices to learn external IP.", Required: false, EnvVars: p2pEnv(envPrefix, "NAT"), + Category: P2PCategory, }, &cli.StringFlag{ Name: UserAgentName, @@ -257,6 +284,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: "optimism", EnvVars: p2pEnv(envPrefix, "AGENT"), + Category: P2PCategory, }, &cli.DurationFlag{ Name: TimeoutNegotiationName, @@ -265,6 +293,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: 10 * time.Second, EnvVars: p2pEnv(envPrefix, "TIMEOUT_NEGOTIATION"), + Category: P2PCategory, }, &cli.DurationFlag{ Name: TimeoutAcceptName, @@ -273,6 +302,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: 10 * time.Second, EnvVars: p2pEnv(envPrefix, "TIMEOUT_ACCEPT"), + Category: P2PCategory, }, &cli.DurationFlag{ Name: TimeoutDialName, @@ -281,6 +311,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: 10 * time.Second, EnvVars: p2pEnv(envPrefix, "TIMEOUT_DIAL"), + Category: P2PCategory, }, &cli.StringFlag{ Name: PeerstorePathName, @@ -291,6 +322,7 @@ func P2PFlags(envPrefix string) []cli.Flag { TakesFile: true, Value: "opnode_peerstore_db", EnvVars: p2pEnv(envPrefix, "PEERSTORE_PATH"), + Category: P2PCategory, }, &cli.StringFlag{ Name: DiscoveryPathName, @@ -299,6 +331,7 @@ func P2PFlags(envPrefix string) []cli.Flag { TakesFile: true, Value: "opnode_discovery_db", EnvVars: p2pEnv(envPrefix, "DISCOVERY_PATH"), + Category: P2PCategory, }, &cli.StringFlag{ Name: SequencerP2PKeyName, @@ -306,6 +339,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Value: "", EnvVars: p2pEnv(envPrefix, "SEQUENCER_KEY"), + Category: P2PCategory, }, &cli.UintFlag{ Name: GossipMeshDName, @@ -314,6 +348,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Hidden: true, Value: p2p.DefaultMeshD, EnvVars: p2pEnv(envPrefix, "GOSSIP_MESH_D"), + Category: P2PCategory, }, &cli.UintFlag{ Name: GossipMeshDloName, @@ -322,6 +357,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Hidden: true, Value: p2p.DefaultMeshDlo, EnvVars: p2pEnv(envPrefix, "GOSSIP_MESH_DLO"), + Category: P2PCategory, }, &cli.UintFlag{ Name: GossipMeshDhiName, @@ -330,6 +366,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Hidden: true, Value: p2p.DefaultMeshDhi, EnvVars: p2pEnv(envPrefix, "GOSSIP_MESH_DHI"), + Category: P2PCategory, }, &cli.UintFlag{ Name: GossipMeshDlazyName, @@ -338,6 +375,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Hidden: true, Value: p2p.DefaultMeshDlazy, EnvVars: p2pEnv(envPrefix, "GOSSIP_MESH_DLAZY"), + Category: P2PCategory, }, &cli.BoolFlag{ Name: GossipFloodPublishName, @@ -345,6 +383,7 @@ func P2PFlags(envPrefix string) []cli.Flag { Required: false, Hidden: true, EnvVars: p2pEnv(envPrefix, "GOSSIP_FLOOD_PUBLISH"), + Category: P2PCategory, }, &cli.BoolFlag{ Name: SyncReqRespName, @@ -352,6 +391,15 @@ func P2PFlags(envPrefix string) []cli.Flag { Value: true, Required: false, EnvVars: p2pEnv(envPrefix, "SYNC_REQ_RESP"), + Category: P2PCategory, + }, + &cli.BoolFlag{ + Name: P2PPingName, + Usage: "Enables P2P ping-pong background service", + Value: true, // on by default + Hidden: true, // hidden, only here to disable in case of bugs. + Required: false, + EnvVars: p2pEnv(envPrefix, "PING"), }, } } diff --git a/op-node/metrics/metrics.go b/op-node/metrics/metrics.go index 999f1b3edae4..e44020f7894b 100644 --- a/op-node/metrics/metrics.go +++ b/op-node/metrics/metrics.go @@ -10,6 +10,8 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum-optimism/optimism/op-node/p2p/store" + plasma "github.com/ethereum-optimism/optimism/op-plasma" + ophttp "github.com/ethereum-optimism/optimism/op-service/httputil" "github.com/ethereum-optimism/optimism/op-service/metrics" @@ -122,6 +124,8 @@ type Metrics struct { TransactionsSequencedTotal prometheus.Counter + PlasmaMetrics plasma.Metricer + // Channel Bank Metrics headChannelOpenedEvent *metrics.Event channelTimedOutEvent *metrics.Event @@ -384,6 +388,8 @@ func NewMetrics(procName string) *Metrics { "required", }), + PlasmaMetrics: plasma.MakeMetrics(ns, factory), + registry: registry, factory: factory, } diff --git a/op-node/node/api.go b/op-node/node/api.go index 3a4ba07e33be..d6252c84540e 100644 --- a/op-node/node/api.go +++ b/op-node/node/api.go @@ -2,8 +2,10 @@ package node import ( "context" + "errors" "fmt" + "github.com/ethereum-optimism/optimism/op-node/node/safedb" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" @@ -33,6 +35,10 @@ type driverClient interface { OnUnsafeL2Payload(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) error } +type SafeDBReader interface { + SafeHeadAtL1(ctx context.Context, l1BlockNum uint64) (l1 eth.BlockID, l2 eth.BlockID, err error) +} + type adminAPI struct { *rpc.CommonAdminAPI dr driverClient @@ -89,15 +95,17 @@ type nodeAPI struct { config *rollup.Config client l2EthClient dr driverClient + safeDB SafeDBReader log log.Logger m metrics.RPCMetricer } -func NewNodeAPI(config *rollup.Config, l2Client l2EthClient, dr driverClient, log log.Logger, m metrics.RPCMetricer) *nodeAPI { +func NewNodeAPI(config *rollup.Config, l2Client l2EthClient, dr driverClient, safeDB SafeDBReader, log log.Logger, m metrics.RPCMetricer) *nodeAPI { return &nodeAPI{ config: config, client: l2Client, dr: dr, + safeDB: safeDB, log: log, m: m, } @@ -126,6 +134,21 @@ func (n *nodeAPI) OutputAtBlock(ctx context.Context, number hexutil.Uint64) (*et }, nil } +func (n *nodeAPI) SafeHeadAtL1Block(ctx context.Context, number hexutil.Uint64) (*eth.SafeHeadResponse, error) { + recordDur := n.m.RecordRPCServerRequest("optimism_safeHeadAtL1Block") + defer recordDur() + l1Block, safeHead, err := n.safeDB.SafeHeadAtL1(ctx, uint64(number)) + if errors.Is(err, safedb.ErrNotFound) { + return nil, err + } else if err != nil { + return nil, fmt.Errorf("failed to get safe head at l1 block %s: %w", number, err) + } + return ð.SafeHeadResponse{ + L1Block: l1Block, + SafeHead: safeHead, + }, nil +} + func (n *nodeAPI) SyncStatus(ctx context.Context) (*eth.SyncStatus, error) { recordDur := n.m.RecordRPCServerRequest("optimism_syncStatus") defer recordDur() diff --git a/op-node/node/client.go b/op-node/node/client.go index 1f1f3b206525..b6a7edbbad65 100644 --- a/op-node/node/client.go +++ b/op-node/node/client.go @@ -4,6 +4,8 @@ import ( "context" "errors" "fmt" + "net/http" + "strings" "time" "github.com/ethereum-optimism/optimism/op-node/rollup" @@ -30,9 +32,10 @@ type L1EndpointSetup interface { } type L1BeaconEndpointSetup interface { - Setup(ctx context.Context, log log.Logger) (cl client.HTTP, err error) + Setup(ctx context.Context, log log.Logger) (cl sources.BeaconClient, fb []sources.BlobSideCarsFetcher, err error) // ShouldIgnoreBeaconCheck returns true if the Beacon-node version check should not halt startup. ShouldIgnoreBeaconCheck() bool + ShouldFetchAllSidecars() bool Check() error } @@ -175,14 +178,31 @@ func (cfg *PreparedL1Endpoint) Check() error { } type L1BeaconEndpointConfig struct { - BeaconAddr string // Address of L1 User Beacon-API endpoint to use (beacon namespace required) - BeaconCheckIgnore bool // When false, halt startup if the beacon version endpoint fails + BeaconAddr string // Address of L1 User Beacon-API endpoint to use (beacon namespace required) + BeaconHeader string // Optional HTTP header for all requests to L1 Beacon + BeaconArchiverAddr string // Address of L1 User Beacon-API Archive endpoint to use for expired blobs (beacon namespace required) + BeaconCheckIgnore bool // When false, halt startup if the beacon version endpoint fails + BeaconFetchAllSidecars bool // Whether to fetch all blob sidecars and filter locally } var _ L1BeaconEndpointSetup = (*L1BeaconEndpointConfig)(nil) -func (cfg *L1BeaconEndpointConfig) Setup(ctx context.Context, log log.Logger) (cl client.HTTP, err error) { - return client.NewBasicHTTPClient(cfg.BeaconAddr, log), nil +func (cfg *L1BeaconEndpointConfig) Setup(ctx context.Context, log log.Logger) (cl sources.BeaconClient, fb []sources.BlobSideCarsFetcher, err error) { + var opts []client.BasicHTTPClientOption + if cfg.BeaconHeader != "" { + hdr, err := parseHTTPHeader(cfg.BeaconHeader) + if err != nil { + return nil, nil, fmt.Errorf("parsing beacon header: %w", err) + } + opts = append(opts, client.WithHeader(hdr)) + } + + a := client.NewBasicHTTPClient(cfg.BeaconAddr, log, opts...) + if cfg.BeaconArchiverAddr != "" { + b := client.NewBasicHTTPClient(cfg.BeaconArchiverAddr, log) + fb = append(fb, sources.NewBeaconHTTPClient(b)) + } + return sources.NewBeaconHTTPClient(a), fb, nil } func (cfg *L1BeaconEndpointConfig) Check() error { @@ -195,3 +215,17 @@ func (cfg *L1BeaconEndpointConfig) Check() error { func (cfg *L1BeaconEndpointConfig) ShouldIgnoreBeaconCheck() bool { return cfg.BeaconCheckIgnore } + +func (cfg *L1BeaconEndpointConfig) ShouldFetchAllSidecars() bool { + return cfg.BeaconFetchAllSidecars +} + +func parseHTTPHeader(headerStr string) (http.Header, error) { + h := make(http.Header, 1) + s := strings.SplitN(headerStr, ": ", 2) + if len(s) != 2 { + return nil, errors.New("invalid header format") + } + h.Add(s[0], s[1]) + return h, nil +} diff --git a/op-node/node/client_test.go b/op-node/node/client_test.go new file mode 100644 index 000000000000..a5ab75fc5630 --- /dev/null +++ b/op-node/node/client_test.go @@ -0,0 +1,62 @@ +package node + +import ( + "net/http" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseHTTPHeader(t *testing.T) { + for _, test := range []struct { + desc string + str string + expHdr http.Header + expErr bool + }{ + { + desc: "err-empty", + expErr: true, + }, + { + desc: "err-no-colon", + str: "Key", + expErr: true, + }, + { + desc: "err-only-key", + str: "Key:", + expErr: true, + }, + { + desc: "err-no-space", + str: "Key:value", + expErr: true, + }, + { + desc: "valid", + str: "Key: value", + expHdr: http.Header{"Key": []string{"value"}}, + }, + { + desc: "valid-small", + str: "key: value", + expHdr: http.Header{"Key": []string{"value"}}, + }, + { + desc: "valid-spaces-colons", + str: "X-Key: a long value with spaces: and: colons", + expHdr: http.Header{"X-Key": []string{"a long value with spaces: and: colons"}}, + }, + } { + t.Run(test.desc, func(t *testing.T) { + h, err := parseHTTPHeader(test.str) + if test.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, test.expHdr, h) + } + }) + } +} diff --git a/op-node/node/config.go b/op-node/node/config.go index 626bcad1ce7a..bae29f0ec8ab 100644 --- a/op-node/node/config.go +++ b/op-node/node/config.go @@ -12,6 +12,8 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + plasma "github.com/ethereum-optimism/optimism/op-plasma" + "github.com/ethereum-optimism/optimism/op-service/eigenda" "github.com/ethereum-optimism/optimism/op-service/oppprof" "github.com/ethereum/go-ethereum/log" ) @@ -43,12 +45,18 @@ type Config struct { ConfigPersistence ConfigPersistence + // Path to store safe head database. Disabled when set to empty string + SafeDBPath string + // RuntimeConfigReloadInterval defines the interval between runtime config reloads. // Disabled if <= 0. // Runtime config changes should be picked up from log-events, // but if log-events are not coming in (e.g. not syncing blocks) then the reload ensures the config stays accurate. RuntimeConfigReloadInterval time.Duration + DA eigenda.Config + PrefixDerivationEnabled bool + // Optional Tracer Tracer Heartbeat HeartbeatConfig @@ -69,6 +77,9 @@ type Config struct { ConductorEnabled bool ConductorRpc string ConductorRpcTimeout time.Duration + + // Plasma DA config + Plasma plasma.CLIConfig } type RPCConfig struct { @@ -164,5 +175,8 @@ func (cfg *Config) Check() error { return fmt.Errorf("sequencer must be enabled when conductor is enabled") } } + if err := cfg.Plasma.Check(); err != nil { + return fmt.Errorf("plasma config error: %w", err) + } return nil } diff --git a/op-node/node/node.go b/op-node/node/node.go index 8fcf42c5c341..d1a3608b6200 100644 --- a/op-node/node/node.go +++ b/op-node/node/node.go @@ -4,9 +4,13 @@ import ( "context" "errors" "fmt" + "io" "sync/atomic" "time" + "github.com/ethereum-optimism/optimism/op-node/node/safedb" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + plasma "github.com/ethereum-optimism/optimism/op-plasma" "github.com/ethereum-optimism/optimism/op-service/httputil" "github.com/hashicorp/go-multierror" @@ -30,9 +34,13 @@ import ( "github.com/ethereum-optimism/optimism/op-service/sources" ) -var ( - ErrAlreadyClosed = errors.New("node is already closed") -) +var ErrAlreadyClosed = errors.New("node is already closed") + +type closableSafeDB interface { + derive.SafeHeadListener + SafeDBReader + io.Closer +} type OpNode struct { log log.Logger @@ -52,6 +60,8 @@ type OpNode struct { tracer Tracer // tracer to get events for testing/debugging runCfg *RuntimeConfig // runtime configurables + safeDB closableSafeDB + rollupHalt string // when to halt the rollup, disabled if empty pprofService *oppprof.Service @@ -131,7 +141,7 @@ func (n *OpNode) init(ctx context.Context, cfg *Config, snapshotLog log.Logger) return fmt.Errorf("failed to init the P2P stack: %w", err) } // Only expose the server at the end, ensuring all RPC backend components are initialized. - if err := n.initRPCServer(ctx, cfg); err != nil { + if err := n.initRPCServer(cfg); err != nil { return fmt.Errorf("failed to init the RPC server: %w", err) } if err := n.initMetricsServer(cfg); err != nil { @@ -143,6 +153,7 @@ func (n *OpNode) init(ctx context.Context, cfg *Config, snapshotLog log.Logger) if err := n.initPProf(cfg); err != nil { return fmt.Errorf("failed to init profiling: %w", err) } + return nil } @@ -304,11 +315,14 @@ func (n *OpNode) initL1BeaconAPI(ctx context.Context, cfg *Config) error { // We always initialize a client. We will get an error on requests if the client does not work. // This way the op-node can continue non-L1 functionality when the user chooses to ignore the Beacon API requirement. - httpClient, err := cfg.Beacon.Setup(ctx, n.log) + beaconClient, fallbacks, err := cfg.Beacon.Setup(ctx, n.log) if err != nil { return fmt.Errorf("failed to setup L1 Beacon API client: %w", err) } - n.beacon = sources.NewL1BeaconClient(httpClient) + beaconCfg := sources.L1BeaconClientConfig{ + FetchAllSidecars: cfg.Beacon.ShouldFetchAllSidecars(), + } + n.beacon = sources.NewL1BeaconClient(beaconClient, beaconCfg, fallbacks...) // Retry retrieval of the Beacon API version, to be more robust on startup against Beacon API connection issues. beaconVersion, missingEndpoint, err := retry.Do2[string, bool](ctx, 5, retry.Exponential(), func() (string, bool, error) { @@ -372,13 +386,29 @@ func (n *OpNode) initL2(ctx context.Context, cfg *Config, snapshotLog log.Logger if cfg.ConductorEnabled { sequencerConductor = NewConductorClient(cfg, n.log, n.metrics) } - n.l2Driver = driver.NewDriver(&cfg.Driver, &cfg.Rollup, n.l2Source, n.l1Source, n.beacon, n, n, n.log, snapshotLog, n.metrics, cfg.ConfigPersistence, &cfg.Sync, sequencerConductor) + // if plasma is not explicitly activated in the node CLI, the config + any error will be ignored. + rpCfg, err := cfg.Rollup.PlasmaConfig() + if cfg.Plasma.Enabled && err != nil { + return fmt.Errorf("failed to get plasma config: %w", err) + } + plasmaDA := plasma.NewPlasmaDA(n.log, cfg.Plasma, rpCfg, n.metrics.PlasmaMetrics) + if cfg.SafeDBPath != "" { + n.log.Info("Safe head database enabled", "path", cfg.SafeDBPath) + safeDB, err := safedb.NewSafeDB(n.log, cfg.SafeDBPath) + if err != nil { + return fmt.Errorf("failed to create safe head database at %v: %w", cfg.SafeDBPath, err) + } + n.safeDB = safeDB + } else { + n.safeDB = safedb.Disabled + } + n.l2Driver = driver.NewDriver(&cfg.Driver, &cfg.Rollup, n.l2Source, n.l1Source, n.beacon, n, n, n.log, snapshotLog, n.metrics, cfg.ConfigPersistence, n.safeDB, &cfg.Sync, sequencerConductor, plasmaDA, &cfg.DA, cfg.PrefixDerivationEnabled) return nil } -func (n *OpNode) initRPCServer(ctx context.Context, cfg *Config) error { - server, err := newRPCServer(ctx, &cfg.RPC, &cfg.Rollup, n.l2Source.L2Client, n.l2Driver, n.log, n.appVersion, n.metrics) +func (n *OpNode) initRPCServer(cfg *Config) error { + server, err := newRPCServer(&cfg.RPC, &cfg.Rollup, n.l2Source.L2Client, n.l2Driver, n.safeDB, n.log, n.appVersion, n.metrics) if err != nil { return err } @@ -641,6 +671,12 @@ func (n *OpNode) Stop(ctx context.Context) error { } } + if n.safeDB != nil { + if err := n.safeDB.Close(); err != nil { + result = multierror.Append(result, fmt.Errorf("failed to close safe head db: %w", err)) + } + } + // Wait for the runtime config loader to be done using the data sources before closing them if n.runtimeConfigReloaderDone != nil { <-n.runtimeConfigReloaderDone diff --git a/op-node/node/safedb/disabled.go b/op-node/node/safedb/disabled.go new file mode 100644 index 000000000000..09ff5cf2433a --- /dev/null +++ b/op-node/node/safedb/disabled.go @@ -0,0 +1,36 @@ +package safedb + +import ( + "context" + "errors" + + "github.com/ethereum-optimism/optimism/op-service/eth" +) + +type DisabledDB struct{} + +var ( + Disabled = &DisabledDB{} + ErrNotEnabled = errors.New("safe head database not enabled") +) + +func (d *DisabledDB) Enabled() bool { + return false +} + +func (d *DisabledDB) SafeHeadUpdated(_ eth.L2BlockRef, _ eth.BlockID) error { + return nil +} + +func (d *DisabledDB) SafeHeadAtL1(_ context.Context, _ uint64) (l1 eth.BlockID, safeHead eth.BlockID, err error) { + err = ErrNotEnabled + return +} + +func (d *DisabledDB) SafeHeadReset(_ eth.L2BlockRef) error { + return nil +} + +func (d *DisabledDB) Close() error { + return nil +} diff --git a/op-node/node/safedb/safedb.go b/op-node/node/safedb/safedb.go new file mode 100644 index 000000000000..6b45411b7981 --- /dev/null +++ b/op-node/node/safedb/safedb.go @@ -0,0 +1,196 @@ +package safedb + +import ( + "context" + "encoding/binary" + "errors" + "fmt" + "math" + "slices" + "sync" + + "github.com/cockroachdb/pebble" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum/go-ethereum/log" +) + +var ( + ErrNotFound = errors.New("not found") + ErrInvalidEntry = errors.New("invalid db entry") +) + +const ( + // Keys are prefixed with a constant byte to allow us to differentiate different "columns" within the data + keyPrefixSafeByL1BlockNum byte = 0 +) + +var ( + safeByL1BlockNumKey = uint64Key{prefix: keyPrefixSafeByL1BlockNum} +) + +type uint64Key struct { + prefix byte +} + +func (c uint64Key) Of(num uint64) []byte { + key := make([]byte, 0, 9) + key = append(key, c.prefix) + key = binary.BigEndian.AppendUint64(key, num) + return key +} +func (c uint64Key) Max() []byte { + return c.Of(math.MaxUint64) +} + +func (c uint64Key) IterRange() *pebble.IterOptions { + return &pebble.IterOptions{ + LowerBound: c.Of(0), + UpperBound: c.Max(), + } +} + +type SafeDB struct { + // m ensures all read iterators are closed before closing the database by preventing concurrent read and write + // operations (with close considered a write operation). + m sync.RWMutex + log log.Logger + db *pebble.DB + + writeOpts *pebble.WriteOptions + + closed bool +} + +func safeByL1BlockNumValue(l1 eth.BlockID, l2 eth.BlockID) []byte { + val := make([]byte, 0, 72) + val = append(val, l1.Hash.Bytes()...) + val = append(val, l2.Hash.Bytes()...) + val = binary.BigEndian.AppendUint64(val, l2.Number) + return val +} + +func decodeSafeByL1BlockNum(key []byte, val []byte) (l1 eth.BlockID, l2 eth.BlockID, err error) { + if len(key) != 9 || len(val) != 72 || key[0] != keyPrefixSafeByL1BlockNum { + err = ErrInvalidEntry + return + } + copy(l1.Hash[:], val[:32]) + l1.Number = binary.BigEndian.Uint64(key[1:]) + copy(l2.Hash[:], val[32:64]) + l2.Number = binary.BigEndian.Uint64(val[64:]) + return +} + +func NewSafeDB(logger log.Logger, path string) (*SafeDB, error) { + db, err := pebble.Open(path, &pebble.Options{}) + if err != nil { + return nil, err + } + return &SafeDB{ + log: logger, + db: db, + writeOpts: &pebble.WriteOptions{Sync: true}, + }, nil +} + +func (d *SafeDB) Enabled() bool { + return true +} + +func (d *SafeDB) SafeHeadUpdated(safeHead eth.L2BlockRef, l1Head eth.BlockID) error { + d.m.Lock() + defer d.m.Unlock() + d.log.Info("Record safe head", "l2", safeHead.ID(), "l1", l1Head) + batch := d.db.NewBatch() + defer batch.Close() + if err := batch.Set(safeByL1BlockNumKey.Of(l1Head.Number), safeByL1BlockNumValue(l1Head, safeHead.ID()), d.writeOpts); err != nil { + return fmt.Errorf("failed to record safe head update: %w", err) + } + if err := batch.Commit(d.writeOpts); err != nil { + return fmt.Errorf("failed to commit safe head update: %w", err) + } + return nil +} + +func (d *SafeDB) SafeHeadReset(safeHead eth.L2BlockRef) error { + d.m.Lock() + defer d.m.Unlock() + iter, err := d.db.NewIter(safeByL1BlockNumKey.IterRange()) + if err != nil { + return fmt.Errorf("reset failed to create iterator: %w", err) + } + defer iter.Close() + if valid := iter.SeekGE(safeByL1BlockNumKey.Of(safeHead.L1Origin.Number)); !valid { + // Reached end of column without finding any entries to delete + return nil + } + for { + val, err := iter.ValueAndErr() + if err != nil { + return fmt.Errorf("reset failed to read entry: %w", err) + } + l1Block, l2Block, err := decodeSafeByL1BlockNum(iter.Key(), val) + if err != nil { + return fmt.Errorf("reset encountered invalid entry: %w", err) + } + if l2Block.Number >= safeHead.Number { + // Keep a copy of this key - it may be modified when calling Prev() + l1HeadKey := slices.Clone(iter.Key()) + hasPrevEntry := iter.Prev() + // Found the first entry that made the new safe head safe. + batch := d.db.NewBatch() + if err := batch.DeleteRange(l1HeadKey, safeByL1BlockNumKey.Max(), d.writeOpts); err != nil { + return fmt.Errorf("reset failed to delete entries after %v: %w", l1HeadKey, err) + } + + // If we reset to a safe head before the first entry, we don't know if the new safe head actually became + // safe in that L1 block or if it was just before our records start, so don't record it as safe at the + // specified L1 block. + if hasPrevEntry { + if err := batch.Set(l1HeadKey, safeByL1BlockNumValue(l1Block, safeHead.ID()), d.writeOpts); err != nil { + return fmt.Errorf("reset failed to record safe head update: %w", err) + } + } + if err := batch.Commit(d.writeOpts); err != nil { + return fmt.Errorf("reset failed to commit batch: %w", err) + } + return nil + } + if valid := iter.Next(); !valid { + // Reached end of column + return nil + } + } +} + +func (d *SafeDB) SafeHeadAtL1(ctx context.Context, l1BlockNum uint64) (l1Block eth.BlockID, safeHead eth.BlockID, err error) { + d.m.RLock() + defer d.m.RUnlock() + iter, err := d.db.NewIterWithContext(ctx, safeByL1BlockNumKey.IterRange()) + if err != nil { + return + } + defer iter.Close() + if valid := iter.SeekLT(safeByL1BlockNumKey.Of(l1BlockNum + 1)); !valid { + err = ErrNotFound + return + } + // Found an entry at or before the requested L1 block + val, err := iter.ValueAndErr() + if err != nil { + return + } + l1Block, safeHead, err = decodeSafeByL1BlockNum(iter.Key(), val) + return +} + +func (d *SafeDB) Close() error { + d.m.Lock() + defer d.m.Unlock() + if d.closed { + // Already closed + return nil + } + d.closed = true + return d.db.Close() +} diff --git a/op-node/node/safedb/safedb_test.go b/op-node/node/safedb/safedb_test.go new file mode 100644 index 000000000000..03fae503c0f3 --- /dev/null +++ b/op-node/node/safedb/safedb_test.go @@ -0,0 +1,369 @@ +package safedb + +import ( + "context" + "math" + "slices" + "testing" + + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func TestStoreSafeHeads(t *testing.T) { + logger := testlog.Logger(t, log.LvlInfo) + dir := t.TempDir() + db, err := NewSafeDB(logger, dir) + require.NoError(t, err) + defer db.Close() + l2a := eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xaa}, + Number: 20, + } + l2b := eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xbb}, + Number: 25, + } + l1a := eth.BlockID{ + Hash: common.Hash{0x01, 0xaa}, + Number: 100, + } + l1b := eth.BlockID{ + Hash: common.Hash{0x01, 0xbb}, + Number: 150, + } + require.NoError(t, db.SafeHeadUpdated(l2a, l1a)) + require.NoError(t, db.SafeHeadUpdated(l2b, l1b)) + + verifySafeHeads := func(db *SafeDB) { + _, _, err = db.SafeHeadAtL1(context.Background(), l1a.Number-1) + require.ErrorIs(t, err, ErrNotFound) + + actualL1, actualL2, err := db.SafeHeadAtL1(context.Background(), l1a.Number) + require.NoError(t, err) + require.Equal(t, l1a, actualL1) + require.Equal(t, l2a.ID(), actualL2) + + actualL1, actualL2, err = db.SafeHeadAtL1(context.Background(), l1a.Number+1) + require.NoError(t, err) + require.Equal(t, l1a, actualL1) + require.Equal(t, l2a.ID(), actualL2) + + actualL1, actualL2, err = db.SafeHeadAtL1(context.Background(), l1b.Number) + require.NoError(t, err) + require.Equal(t, l1b, actualL1) + require.Equal(t, l2b.ID(), actualL2) + + actualL1, actualL2, err = db.SafeHeadAtL1(context.Background(), l1b.Number+1) + require.NoError(t, err) + require.Equal(t, l1b, actualL1) + require.Equal(t, l2b.ID(), actualL2) + } + // Verify loading the safe heads with the already open DB + verifySafeHeads(db) + + // Close the DB and open a new instance + require.NoError(t, db.Close()) + newDB, err := NewSafeDB(logger, dir) + require.NoError(t, err) + // Verify the data is reloaded correctly + verifySafeHeads(newDB) +} + +func TestSafeHeadAtL1_EmptyDatabase(t *testing.T) { + logger := testlog.Logger(t, log.LvlInfo) + dir := t.TempDir() + db, err := NewSafeDB(logger, dir) + require.NoError(t, err) + defer db.Close() + _, _, err = db.SafeHeadAtL1(context.Background(), 100) + require.ErrorIs(t, err, ErrNotFound) +} + +func TestTruncateOnSafeHeadReset(t *testing.T) { + logger := testlog.Logger(t, log.LvlInfo) + dir := t.TempDir() + db, err := NewSafeDB(logger, dir) + require.NoError(t, err) + defer db.Close() + + l2a := eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xaa}, + Number: 20, + L1Origin: eth.BlockID{ + Number: 60, + }, + } + l2b := eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xbb}, + Number: 22, + L1Origin: eth.BlockID{ + Number: 90, + }, + } + l2c := eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xcc}, + Number: 25, + L1Origin: eth.BlockID{ + Number: 110, + }, + } + l2d := eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xcc}, + Number: 30, + L1Origin: eth.BlockID{ + Number: 120, + }, + } + l1a := eth.BlockID{ + Hash: common.Hash{0x01, 0xaa}, + Number: 100, + } + l1b := eth.BlockID{ + Hash: common.Hash{0x01, 0xbb}, + Number: 150, + } + l1c := eth.BlockID{ + Hash: common.Hash{0x01, 0xcc}, + Number: 160, + } + + // Add some entries + require.NoError(t, db.SafeHeadUpdated(l2a, l1a)) + require.NoError(t, db.SafeHeadUpdated(l2c, l1b)) + require.NoError(t, db.SafeHeadUpdated(l2d, l1c)) + + // Then reset to between the two existing entries + require.NoError(t, db.SafeHeadReset(l2b)) + + // Only the reset safe head is now safe at the previous L1 block number + actualL1, actualL2, err := db.SafeHeadAtL1(context.Background(), l1b.Number) + require.NoError(t, err) + require.Equal(t, l1b, actualL1) + require.Equal(t, l2b.ID(), actualL2) + + actualL1, actualL2, err = db.SafeHeadAtL1(context.Background(), l1c.Number) + require.NoError(t, err) + require.Equal(t, l1b, actualL1) + require.Equal(t, l2b.ID(), actualL2) + + // l2a is still safe from its original update + actualL1, actualL2, err = db.SafeHeadAtL1(context.Background(), l1a.Number) + require.NoError(t, err) + require.Equal(t, l1a, actualL1) + require.Equal(t, l2a.ID(), actualL2) +} + +func TestTruncateOnSafeHeadReset_BeforeFirstEntry(t *testing.T) { + logger := testlog.Logger(t, log.LvlInfo) + dir := t.TempDir() + db, err := NewSafeDB(logger, dir) + require.NoError(t, err) + defer db.Close() + + l2b := eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xbb}, + Number: 22, + L1Origin: eth.BlockID{ + Number: 90, + }, + } + l2c := eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xcc}, + Number: 25, + L1Origin: eth.BlockID{ + Number: 110, + }, + } + l2d := eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xcc}, + Number: 30, + L1Origin: eth.BlockID{ + Number: 120, + }, + } + l1a := eth.BlockID{ + Hash: common.Hash{0x01, 0xaa}, + Number: 100, + } + l1b := eth.BlockID{ + Hash: common.Hash{0x01, 0xbb}, + Number: 150, + } + l1c := eth.BlockID{ + Hash: common.Hash{0x01, 0xcc}, + Number: 160, + } + + // Add some entries + require.NoError(t, db.SafeHeadUpdated(l2c, l1b)) + require.NoError(t, db.SafeHeadUpdated(l2d, l1c)) + + // Then reset to between the two existing entries + require.NoError(t, db.SafeHeadReset(l2b)) + + // All entries got removed + _, _, err = db.SafeHeadAtL1(context.Background(), l1a.Number) + require.ErrorIs(t, err, ErrNotFound) + _, _, err = db.SafeHeadAtL1(context.Background(), l1b.Number) + require.ErrorIs(t, err, ErrNotFound) + _, _, err = db.SafeHeadAtL1(context.Background(), l1c.Number) + require.ErrorIs(t, err, ErrNotFound) +} + +func TestTruncateOnSafeHeadReset_AfterLastEntry(t *testing.T) { + logger := testlog.Logger(t, log.LvlInfo) + dir := t.TempDir() + db, err := NewSafeDB(logger, dir) + require.NoError(t, err) + defer db.Close() + + l2a := eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xaa}, + Number: 20, + L1Origin: eth.BlockID{ + Number: 60, + }, + } + l2b := eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xbb}, + Number: 22, + L1Origin: eth.BlockID{ + Number: 90, + }, + } + l2c := eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xcc}, + Number: 25, + L1Origin: eth.BlockID{ + Number: 110, + }, + } + l1a := eth.BlockID{ + Hash: common.Hash{0x01, 0xaa}, + Number: 100, + } + l1b := eth.BlockID{ + Hash: common.Hash{0x01, 0xbb}, + Number: 150, + } + l1c := eth.BlockID{ + Hash: common.Hash{0x01, 0xcc}, + Number: 160, + } + + // Add some entries + require.NoError(t, db.SafeHeadUpdated(l2a, l1a)) + require.NoError(t, db.SafeHeadUpdated(l2b, l1b)) + require.NoError(t, db.SafeHeadUpdated(l2c, l1c)) + + verifySafeHeads := func() { + // Everything is still safe + actualL1, actualL2, err := db.SafeHeadAtL1(context.Background(), l1a.Number) + require.NoError(t, err) + require.Equal(t, l1a, actualL1) + require.Equal(t, l2a.ID(), actualL2) + + // Everything is still safe + actualL1, actualL2, err = db.SafeHeadAtL1(context.Background(), l1b.Number) + require.NoError(t, err) + require.Equal(t, l1b, actualL1) + require.Equal(t, l2b.ID(), actualL2) + + // Everything is still safe + actualL1, actualL2, err = db.SafeHeadAtL1(context.Background(), l1c.Number) + require.NoError(t, err) + require.Equal(t, l1c, actualL1) + require.Equal(t, l2c.ID(), actualL2) + } + verifySafeHeads() + + // Then reset to an L2 block after all entries with an origin after all L1 entries + require.NoError(t, db.SafeHeadReset(eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xdd}, + Number: 30, + L1Origin: eth.BlockID{ + Number: l1c.Number + 1, + }, + })) + verifySafeHeads() + + // Then reset to an L2 block after all entries with an origin before some L1 entries + require.NoError(t, db.SafeHeadReset(eth.L2BlockRef{ + Hash: common.Hash{0x02, 0xdd}, + Number: 30, + L1Origin: eth.BlockID{ + Number: l1b.Number - 1, + }, + })) + verifySafeHeads() +} + +func TestKeysFollowNaturalByteOrdering(t *testing.T) { + vals := []uint64{0, 1, math.MaxUint32 - 1, math.MaxUint32, math.MaxUint32 + 1, math.MaxUint64 - 1, math.MaxUint64} + for i := 1; i < len(vals); i++ { + prev := safeByL1BlockNumKey.Of(vals[i-1]) + cur := safeByL1BlockNumKey.Of(vals[i]) + require.True(t, slices.Compare(prev, cur) < 0, "Expected %v key %x to be less than %v key %x", vals[i-1], prev, vals[i], cur) + } +} + +func TestDecodeSafeByL1BlockNum(t *testing.T) { + l1 := eth.BlockID{ + Hash: common.Hash{0x01}, + Number: 84298, + } + l2 := eth.BlockID{ + Hash: common.Hash{0x02}, + Number: 3224, + } + validKey := safeByL1BlockNumKey.Of(l1.Number) + validValue := safeByL1BlockNumValue(l1, l2) + + t.Run("Roundtrip", func(t *testing.T) { + actualL1, actualL2, err := decodeSafeByL1BlockNum(validKey, validValue) + require.NoError(t, err) + require.Equal(t, l1, actualL1) + require.Equal(t, l2, actualL2) + }) + + t.Run("ErrorOnEmptyKey", func(t *testing.T) { + _, _, err := decodeSafeByL1BlockNum([]byte{}, validValue) + require.ErrorIs(t, err, ErrInvalidEntry) + }) + + t.Run("ErrorOnTooShortKey", func(t *testing.T) { + _, _, err := decodeSafeByL1BlockNum([]byte{1, 2, 3, 4}, validValue) + require.ErrorIs(t, err, ErrInvalidEntry) + }) + + t.Run("ErrorOnTooLongKey", func(t *testing.T) { + _, _, err := decodeSafeByL1BlockNum(append(validKey, 2), validValue) + require.ErrorIs(t, err, ErrInvalidEntry) + }) + + t.Run("ErrorOnWrongKeyPrefix", func(t *testing.T) { + invalidKey := slices.Clone(validKey) + invalidKey[0] = 49 + _, _, err := decodeSafeByL1BlockNum(invalidKey, validValue) + require.ErrorIs(t, err, ErrInvalidEntry) + }) + + t.Run("ErrorOnEmptyValue", func(t *testing.T) { + _, _, err := decodeSafeByL1BlockNum(validKey, []byte{}) + require.ErrorIs(t, err, ErrInvalidEntry) + }) + + t.Run("ErrorOnTooShortValue", func(t *testing.T) { + _, _, err := decodeSafeByL1BlockNum(validKey, []byte{1, 2, 3, 4}) + require.ErrorIs(t, err, ErrInvalidEntry) + }) + + t.Run("ErrorOnTooLongValue", func(t *testing.T) { + _, _, err := decodeSafeByL1BlockNum(validKey, append(validKey, 2)) + require.ErrorIs(t, err, ErrInvalidEntry) + }) +} diff --git a/op-node/node/server.go b/op-node/node/server.go index ce94a1497f24..e1b1531b0142 100644 --- a/op-node/node/server.go +++ b/op-node/node/server.go @@ -27,8 +27,8 @@ type rpcServer struct { sources.L2Client } -func newRPCServer(ctx context.Context, rpcCfg *RPCConfig, rollupCfg *rollup.Config, l2Client l2EthClient, dr driverClient, log log.Logger, appVersion string, m metrics.Metricer) (*rpcServer, error) { - api := NewNodeAPI(rollupCfg, l2Client, dr, log.New("rpc", "node"), m) +func newRPCServer(rpcCfg *RPCConfig, rollupCfg *rollup.Config, l2Client l2EthClient, dr driverClient, safedb SafeDBReader, log log.Logger, appVersion string, m metrics.Metricer) (*rpcServer, error) { + api := NewNodeAPI(rollupCfg, l2Client, dr, safedb, 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 062aa22cdfe6..587befd6de80 100644 --- a/op-node/node/server_test.go +++ b/op-node/node/server_test.go @@ -7,6 +7,7 @@ import ( "testing" "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/log" "github.com/stretchr/testify/assert" @@ -23,7 +24,7 @@ import ( ) func TestOutputAtBlock(t *testing.T) { - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) // Test data for Merkle Patricia Trie: proof the eth2 deposit contract account contents (mainnet). headerTestData := ` @@ -97,10 +98,11 @@ func TestOutputAtBlock(t *testing.T) { l2Client.ExpectOutputV0AtBlock(common.HexToHash("0x8512bee03061475e4b069171f7b406097184f16b22c3f5c97c0abfc49591c524"), output, nil) drClient := &mockDriverClient{} + safeReader := &mockSafeDBReader{} status := randomSyncStatus(rand.New(rand.NewSource(123))) drClient.ExpectBlockRefWithStatus(0xdcdc89, ref, status, nil) - server, err := newRPCServer(context.Background(), rpcCfg, rollupCfg, l2Client, drClient, log, "0.0", metrics.NoopMetrics) + server, err := newRPCServer(rpcCfg, rollupCfg, l2Client, drClient, safeReader, log, "0.0", metrics.NoopMetrics) require.NoError(t, err) require.NoError(t, server.Start()) defer func() { @@ -121,12 +123,14 @@ func TestOutputAtBlock(t *testing.T) { require.Equal(t, *status, *out.Status) l2Client.Mock.AssertExpectations(t) drClient.Mock.AssertExpectations(t) + safeReader.Mock.AssertExpectations(t) } func TestVersion(t *testing.T) { - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) l2Client := &testutils.MockL2Client{} drClient := &mockDriverClient{} + safeReader := &mockSafeDBReader{} rpcCfg := &RPCConfig{ ListenAddr: "localhost", ListenPort: 0, @@ -134,7 +138,7 @@ func TestVersion(t *testing.T) { rollupCfg := &rollup.Config{ // ignore other rollup config info in this test } - server, err := newRPCServer(context.Background(), rpcCfg, rollupCfg, l2Client, drClient, log, "0.0", metrics.NoopMetrics) + server, err := newRPCServer(rpcCfg, rollupCfg, l2Client, drClient, safeReader, log, "0.0", metrics.NoopMetrics) assert.NoError(t, err) assert.NoError(t, server.Start()) defer func() { @@ -165,9 +169,10 @@ func randomSyncStatus(rng *rand.Rand) *eth.SyncStatus { } func TestSyncStatus(t *testing.T) { - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) l2Client := &testutils.MockL2Client{} drClient := &mockDriverClient{} + safeReader := &mockSafeDBReader{} rng := rand.New(rand.NewSource(1234)) status := randomSyncStatus(rng) drClient.On("SyncStatus").Return(status) @@ -179,7 +184,7 @@ func TestSyncStatus(t *testing.T) { rollupCfg := &rollup.Config{ // ignore other rollup config info in this test } - server, err := newRPCServer(context.Background(), rpcCfg, rollupCfg, l2Client, drClient, log, "0.0", metrics.NoopMetrics) + server, err := newRPCServer(rpcCfg, rollupCfg, l2Client, drClient, safeReader, log, "0.0", metrics.NoopMetrics) assert.NoError(t, err) assert.NoError(t, server.Start()) defer func() { @@ -195,6 +200,52 @@ func TestSyncStatus(t *testing.T) { assert.Equal(t, status, out) } +func TestSafeHeadAtL1Block(t *testing.T) { + log := testlog.Logger(t, log.LevelError) + l2Client := &testutils.MockL2Client{} + drClient := &mockDriverClient{} + safeReader := &mockSafeDBReader{} + l1BlockNum := uint64(5223) + expectedL1 := eth.BlockID{ + Hash: common.Hash{0xdd}, + Number: l1BlockNum - 2, + } + expectedSafeHead := eth.BlockID{ + Hash: common.Hash{0xee}, + Number: 223, + } + expected := ð.SafeHeadResponse{ + L1Block: expectedL1, + SafeHead: expectedSafeHead, + } + safeReader.ExpectSafeHeadAtL1(l1BlockNum, expectedL1, expectedSafeHead, nil) + + rpcCfg := &RPCConfig{ + ListenAddr: "localhost", + ListenPort: 0, + } + rollupCfg := &rollup.Config{ + // ignore other rollup config info in this test + } + server, err := newRPCServer(rpcCfg, rollupCfg, l2Client, drClient, safeReader, log, "0.0", metrics.NoopMetrics) + require.NoError(t, err) + require.NoError(t, server.Start()) + defer func() { + require.NoError(t, server.Stop(context.Background())) + }() + + client, err := rpcclient.NewRPC(context.Background(), log, "http://"+server.Addr().String(), rpcclient.WithDialBackoff(3)) + require.NoError(t, err) + + var out *eth.SafeHeadResponse + err = client.CallContext(context.Background(), &out, "optimism_safeHeadAtL1Block", hexutil.Uint64(l1BlockNum).String()) + require.NoError(t, err) + require.Equal(t, expected, out) + l2Client.Mock.AssertExpectations(t) + drClient.Mock.AssertExpectations(t) + safeReader.Mock.AssertExpectations(t) +} + type mockDriverClient struct { mock.Mock } @@ -231,3 +282,16 @@ func (c *mockDriverClient) SequencerActive(ctx context.Context) (bool, error) { func (c *mockDriverClient) OnUnsafeL2Payload(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) error { return c.Mock.MethodCalled("OnUnsafeL2Payload").Get(0).(error) } + +type mockSafeDBReader struct { + mock.Mock +} + +func (m *mockSafeDBReader) SafeHeadAtL1(ctx context.Context, l1BlockNum uint64) (l1Hash eth.BlockID, l2Hash eth.BlockID, err error) { + r := m.Mock.MethodCalled("SafeHeadAtL1", l1BlockNum) + return r[0].(eth.BlockID), r[1].(eth.BlockID), *r[2].(*error) +} + +func (m *mockSafeDBReader) ExpectSafeHeadAtL1(l1BlockNum uint64, l1 eth.BlockID, safeHead eth.BlockID, err error) { + m.Mock.On("SafeHeadAtL1", l1BlockNum).Return(l1, safeHead, &err) +} diff --git a/op-node/p2p/app_scores.go b/op-node/p2p/app_scores.go index 06693868c3e2..be0fe7a7e95f 100644 --- a/op-node/p2p/app_scores.go +++ b/op-node/p2p/app_scores.go @@ -111,6 +111,7 @@ func (s *peerApplicationScorer) start() { go func() { defer s.done.Done() ticker := s.clock.NewTicker(s.params.DecayInterval) + defer ticker.Stop() for { select { case <-s.ctx.Done(): diff --git a/op-node/p2p/app_scores_test.go b/op-node/p2p/app_scores_test.go index 720b0c4babf5..337d8244c5ae 100644 --- a/op-node/p2p/app_scores_test.go +++ b/op-node/p2p/app_scores_test.go @@ -63,7 +63,7 @@ func (a *appScoreTestData) WaitForNextScoreBookUpdate(t *testing.T) stubScoreBoo func setupPeerApplicationScorerTest(t *testing.T, params *ApplicationScoreParams) (*appScoreTestData, *peerApplicationScorer) { data := &appScoreTestData{ ctx: context.Background(), - logger: testlog.Logger(t, log.LvlInfo), + logger: testlog.Logger(t, log.LevelInfo), clock: clock.NewDeterministicClock(time.UnixMilli(1000)), peers: []peer.ID{}, scorebook: &stubScoreBook{ diff --git a/op-node/p2p/cli/load_config.go b/op-node/p2p/cli/load_config.go index 41ae628b8b28..98e205e97213 100644 --- a/op-node/p2p/cli/load_config.go +++ b/op-node/p2p/cli/load_config.go @@ -65,6 +65,7 @@ func NewConfig(ctx *cli.Context, rollupCfg *rollup.Config) (*p2p.Config, error) } conf.EnableReqRespSync = ctx.Bool(flags.SyncReqRespName) + conf.EnablePingService = ctx.Bool(flags.P2PPingName) return conf, nil } diff --git a/op-node/p2p/config.go b/op-node/p2p/config.go index 1ad5c3c872a0..326f7e66077e 100644 --- a/op-node/p2p/config.go +++ b/op-node/p2p/config.go @@ -26,9 +26,18 @@ import ( ) var DefaultBootnodes = []*enode.Node{ - enode.MustParse("enode://869d07b5932f17e8490990f75a3f94195e9504ddb6b85f7189e5a9c0a8fff8b00aecf6f3ac450ecba6cdabdb5858788a94bde2b613e0f2d82e9b395355f76d1a@34.65.67.101:0?discport=30305"), - enode.MustParse("enode://2d4e7e9d48f4dd4efe9342706dd1b0024681bd4c3300d021f86fc75eab7865d4e0cbec6fbc883f011cfd6a57423e7e2f6e104baad2b744c3cafaec6bc7dc92c1@34.65.43.171:0?discport=30305"), - enode.MustParse("enode://9d7a3efefe442351217e73b3a593bcb8efffb55b4807699972145324eab5e6b382152f8d24f6301baebbfb5ecd4127bd3faab2842c04cd432bdf50ba092f6645@34.65.109.126:0?discport=30305"), + // OP Labs + enode.MustParse("enode://869d07b5932f17e8490990f75a3f94195e9504ddb6b85f7189e5a9c0a8fff8b00aecf6f3ac450ecba6cdabdb5858788a94bde2b613e0f2d82e9b395355f76d1a@34.65.67.101:30305"), + enode.MustParse("enode://2d4e7e9d48f4dd4efe9342706dd1b0024681bd4c3300d021f86fc75eab7865d4e0cbec6fbc883f011cfd6a57423e7e2f6e104baad2b744c3cafaec6bc7dc92c1@34.65.43.171:30305"), + enode.MustParse("enode://9d7a3efefe442351217e73b3a593bcb8efffb55b4807699972145324eab5e6b382152f8d24f6301baebbfb5ecd4127bd3faab2842c04cd432bdf50ba092f6645@34.65.109.126:30305"), + // Base + enode.MustParse("enr:-J24QNz9lbrKbN4iSmmjtnr7SjUMk4zB7f1krHZcTZx-JRKZd0kA2gjufUROD6T3sOWDVDnFJRvqBBo62zuF-hYCohOGAYiOoEyEgmlkgnY0gmlwhAPniryHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQKNVFlCxh_B-716tTs-h1vMzZkSs1FTu_OYTNjgufplG4N0Y3CCJAaDdWRwgiQG"), + enode.MustParse("enr:-J24QH-f1wt99sfpHy4c0QJM-NfmsIfmlLAMMcgZCUEgKG_BBYFc6FwYgaMJMQN5dsRBJApIok0jFn-9CS842lGpLmqGAYiOoDRAgmlkgnY0gmlwhLhIgb2Hb3BzdGFja4OFQgCJc2VjcDI1NmsxoQJ9FTIv8B9myn1MWaC_2lJ-sMoeCDkusCsk4BYHjjCq04N0Y3CCJAaDdWRwgiQG"), + enode.MustParse("enr:-J24QDXyyxvQYsd0yfsN0cRr1lZ1N11zGTplMNlW4xNEc7LkPXh0NAJ9iSOVdRO95GPYAIc6xmyoCCG6_0JxdL3a0zaGAYiOoAjFgmlkgnY0gmlwhAPckbGHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQJwoS7tzwxqXSyFL7g0JM-KWVbgvjfB8JA__T7yY_cYboN0Y3CCJAaDdWRwgiQG"), + enode.MustParse("enr:-J24QHmGyBwUZXIcsGYMaUqGGSl4CFdx9Tozu-vQCn5bHIQbR7On7dZbU61vYvfrJr30t0iahSqhc64J46MnUO2JvQaGAYiOoCKKgmlkgnY0gmlwhAPnCzSHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQINc4fSijfbNIiGhcgvwjsjxVFJHUstK9L1T8OTKUjgloN0Y3CCJAaDdWRwgiQG"), + enode.MustParse("enr:-J24QG3ypT4xSu0gjb5PABCmVxZqBjVw9ca7pvsI8jl4KATYAnxBmfkaIuEqy9sKvDHKuNCsy57WwK9wTt2aQgcaDDyGAYiOoGAXgmlkgnY0gmlwhDbGmZaHb3BzdGFja4OFQgCJc2VjcDI1NmsxoQIeAK_--tcLEiu7HvoUlbV52MspE0uCocsx1f_rYvRenIN0Y3CCJAaDdWRwgiQG"), + // Conduit + enode.MustParse("enode://9d7a3efefe442351217e73b3a593bcb8efffb55b4807699972145324eab5e6b382152f8d24f6301baebbfb5ecd4127bd3faab2842c04cd432bdf50ba092f6645@34.65.109.126:30305"), } type HostMetrics interface { @@ -118,6 +127,8 @@ type Config struct { Store ds.Batching EnableReqRespSync bool + + EnablePingService bool } func DefaultConnManager(conf *Config) (connmgr.ConnManager, error) { diff --git a/op-node/p2p/gating/expiry.go b/op-node/p2p/gating/expiry.go index 73522f79acbc..e6f1662b3597 100644 --- a/op-node/p2p/gating/expiry.go +++ b/op-node/p2p/gating/expiry.go @@ -45,6 +45,19 @@ func AddBanExpiry(gater BlockingConnectionGater, store ExpiryStore, log log.Logg } } +func (g *ExpiryConnectionGater) UnblockPeer(p peer.ID) error { + if err := g.BlockingConnectionGater.UnblockPeer(p); err != nil { + log.Warn("failed to unblock peer from underlying gater", "method", "UnblockPeer", "peer_id", p, "err", err) + return err + } + if err := g.store.SetPeerBanExpiration(p, time.Time{}); err != nil { + log.Warn("failed to unblock peer from expiry gater", "method", "UnblockPeer", "peer_id", p, "err", err) + return err + } + g.m.RecordPeerUnban() + return nil +} + func (g *ExpiryConnectionGater) peerBanExpiryCheck(p peer.ID) (allow bool) { // if the peer is blocked, check if it's time to unblock expiry, err := g.store.GetPeerBanExpiration(p) @@ -52,7 +65,7 @@ func (g *ExpiryConnectionGater) peerBanExpiryCheck(p peer.ID) (allow bool) { return true // peer is allowed if it has not been banned } if err != nil { - g.log.Warn("failed to load peer-ban expiry time", "peer_id", p, "err", err) + g.log.Warn("failed to load peer-ban expiry time", "method", "peerBanExpiryCheck", "peer_id", p, "err", err) return false } if g.clock.Now().Before(expiry) { @@ -60,7 +73,7 @@ func (g *ExpiryConnectionGater) peerBanExpiryCheck(p peer.ID) (allow bool) { } g.log.Info("peer-ban expired, unbanning peer", "peer_id", p, "expiry", expiry) if err := g.store.SetPeerBanExpiration(p, time.Time{}); err != nil { - g.log.Warn("failed to unban peer", "peer_id", p, "err", err) + g.log.Warn("failed to unban peer", "method", "peerBanExpiryCheck", "peer_id", p, "err", err) return false // if we ignored the error, then the inner connection-gater would drop them } g.m.RecordPeerUnban() @@ -70,7 +83,7 @@ func (g *ExpiryConnectionGater) peerBanExpiryCheck(p peer.ID) (allow bool) { func (g *ExpiryConnectionGater) addrBanExpiryCheck(ma multiaddr.Multiaddr) (allow bool) { ip, err := manet.ToIP(ma) if err != nil { - g.log.Error("tried to check multi-addr with bad IP", "addr", ma) + g.log.Error("tried to check multi-addr with bad IP", "method", "addrBanExpiryCheck", "addr", ma) return false } // if just the IP is blocked, check if it's time to unblock @@ -79,15 +92,15 @@ func (g *ExpiryConnectionGater) addrBanExpiryCheck(ma multiaddr.Multiaddr) (allo return true // IP is allowed if it has not been banned } if err != nil { - g.log.Warn("failed to load IP-ban expiry time", "ip", ip, "err", err) + g.log.Warn("failed to load IP-ban expiry time", "method", "addrBanExpiryCheck", "ip", ip, "err", err) return false } if g.clock.Now().Before(expiry) { return false } - g.log.Info("IP-ban expired, unbanning IP", "ip", ip, "expiry", expiry) + g.log.Info("IP-ban expired, unbanning IP", "method", "addrBanExpiryCheck", "ip", ip, "expiry", expiry) if err := g.store.SetIPBanExpiration(ip, time.Time{}); err != nil { - g.log.Warn("failed to unban IP", "ip", ip, "err", err) + g.log.Warn("failed to unban IP", "method", "addrBanExpiryCheck", "ip", ip, "err", err) return false // if we ignored the error, then the inner connection-gater would drop them } g.m.RecordIPUnban() @@ -98,21 +111,39 @@ func (g *ExpiryConnectionGater) InterceptPeerDial(p peer.ID) (allow bool) { if !g.BlockingConnectionGater.InterceptPeerDial(p) { return false } - return g.peerBanExpiryCheck(p) + peerBan := g.peerBanExpiryCheck(p) + if !peerBan { + log.Warn("peer is temporarily banned", "method", "InterceptPeerDial", "peer_id", p) + } + return peerBan } func (g *ExpiryConnectionGater) InterceptAddrDial(id peer.ID, ma multiaddr.Multiaddr) (allow bool) { if !g.BlockingConnectionGater.InterceptAddrDial(id, ma) { return false } - return g.peerBanExpiryCheck(id) && g.addrBanExpiryCheck(ma) + peerBan := g.peerBanExpiryCheck(id) + if !peerBan { + log.Warn("peer id is temporarily banned", "method", "InterceptAddrDial", "peer_id", id, "multi_addr", ma) + return false + } + addrBan := g.addrBanExpiryCheck(ma) + if !addrBan { + log.Warn("peer address is temporarily banned", "method", "InterceptAddrDial", "peer_id", id, "multi_addr", ma) + return false + } + return true } func (g *ExpiryConnectionGater) InterceptAccept(mas network.ConnMultiaddrs) (allow bool) { if !g.BlockingConnectionGater.InterceptAccept(mas) { return false } - return g.addrBanExpiryCheck(mas.RemoteMultiaddr()) + addrBan := g.addrBanExpiryCheck(mas.RemoteMultiaddr()) + if !addrBan { + log.Warn("peer address is temporarily banned", "method", "InterceptAccept", "multi_addr", mas.RemoteMultiaddr()) + } + return addrBan } func (g *ExpiryConnectionGater) InterceptSecured(direction network.Direction, id peer.ID, mas network.ConnMultiaddrs) (allow bool) { @@ -125,5 +156,9 @@ func (g *ExpiryConnectionGater) InterceptSecured(direction network.Direction, id } // InterceptSecured is called after InterceptAccept, we already checked the addrs. // This leaves just the peer-ID expiry to check on inbound connections. - return g.peerBanExpiryCheck(id) + peerBan := g.peerBanExpiryCheck(id) + if !peerBan { + log.Warn("peer id is temporarily banned", "method", "InterceptSecured", "peer_id", id, "multi_addr", mas.RemoteMultiaddr()) + } + return peerBan } diff --git a/op-node/p2p/gating/expiry_test.go b/op-node/p2p/gating/expiry_test.go index b64085fe64fc..453e1d3fe2cb 100644 --- a/op-node/p2p/gating/expiry_test.go +++ b/op-node/p2p/gating/expiry_test.go @@ -20,7 +20,7 @@ import ( func expiryTestSetup(t *testing.T) (*clock.DeterministicClock, *mocks.ExpiryStore, *mocks.BlockingConnectionGater, *ExpiryConnectionGater) { mockGater := mocks.NewBlockingConnectionGater(t) - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) cl := clock.NewDeterministicClock(time.Now()) mockExpiryStore := mocks.NewExpiryStore(t) gater := AddBanExpiry(mockGater, mockExpiryStore, log, cl, metrics.NoopMetrics) diff --git a/op-node/p2p/gating/scoring.go b/op-node/p2p/gating/scoring.go index 0e23e3fce655..8b0d305d2bb8 100644 --- a/op-node/p2p/gating/scoring.go +++ b/op-node/p2p/gating/scoring.go @@ -1,6 +1,7 @@ package gating import ( + "github.com/ethereum/go-ethereum/log" "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" "github.com/multiformats/go-multiaddr" @@ -22,22 +23,43 @@ func AddScoring(gater BlockingConnectionGater, scores Scores, minScore float64) return &ScoringConnectionGater{BlockingConnectionGater: gater, scores: scores, minScore: minScore} } -func (g *ScoringConnectionGater) checkScore(p peer.ID) (allow bool) { +func (g *ScoringConnectionGater) checkScore(p peer.ID) (allow bool, score float64) { score, err := g.scores.GetPeerScore(p) if err != nil { - return false + return false, score } - return score >= g.minScore + return score >= g.minScore, score } func (g *ScoringConnectionGater) InterceptPeerDial(p peer.ID) (allow bool) { - return g.BlockingConnectionGater.InterceptPeerDial(p) && g.checkScore(p) + if !g.BlockingConnectionGater.InterceptPeerDial(p) { + return false + } + check, score := g.checkScore(p) + if !check { + log.Warn("peer has failed checkScore", "peer_id", p, "score", score, "min_score", g.minScore) + } + return check } func (g *ScoringConnectionGater) InterceptAddrDial(id peer.ID, ma multiaddr.Multiaddr) (allow bool) { - return g.BlockingConnectionGater.InterceptAddrDial(id, ma) && g.checkScore(id) + if !g.BlockingConnectionGater.InterceptAddrDial(id, ma) { + return false + } + check, score := g.checkScore(id) + if !check { + log.Warn("peer has failed checkScore", "peer_id", id, "score", score, "min_score", g.minScore) + } + return check } func (g *ScoringConnectionGater) InterceptSecured(dir network.Direction, id peer.ID, mas network.ConnMultiaddrs) (allow bool) { - return g.BlockingConnectionGater.InterceptSecured(dir, id, mas) && g.checkScore(id) + if !g.BlockingConnectionGater.InterceptSecured(dir, id, mas) { + return false + } + check, score := g.checkScore(id) + if !check { + log.Warn("peer has failed checkScore", "peer_id", id, "score", score, "min_score", g.minScore) + } + return check } diff --git a/op-node/p2p/gossip_test.go b/op-node/p2p/gossip_test.go index 0bfc6bc33fbe..0833f270e40b 100644 --- a/op-node/p2p/gossip_test.go +++ b/op-node/p2p/gossip_test.go @@ -31,7 +31,7 @@ import ( ) func TestGuardGossipValidator(t *testing.T) { - logger := testlog.Logger(t, log.LvlCrit) + logger := testlog.Logger(t, log.LevelCrit) val := guardGossipValidator(logger, func(ctx context.Context, id peer.ID, message *pubsub.Message) pubsub.ValidationResult { if id == "mallory" { panic("mallory was here") @@ -57,7 +57,7 @@ func TestCombinePeers(t *testing.T) { } func TestVerifyBlockSignature(t *testing.T) { - logger := testlog.Logger(t, log.LvlCrit) + logger := testlog.Logger(t, log.LevelCrit) cfg := &rollup.Config{ L2ChainID: big.NewInt(100), } @@ -153,8 +153,8 @@ func TestBlockValidator(t *testing.T) { // Params Set 2: Call the validation function peerID := peer.ID("foo") - v2Validator := BuildBlocksValidator(testlog.Logger(t, log.LvlCrit), cfg, runCfg, eth.BlockV2) - v3Validator := BuildBlocksValidator(testlog.Logger(t, log.LvlCrit), cfg, runCfg, eth.BlockV3) + v2Validator := BuildBlocksValidator(testlog.Logger(t, log.LevelCrit), cfg, runCfg, eth.BlockV2) + v3Validator := BuildBlocksValidator(testlog.Logger(t, log.LevelCrit), cfg, runCfg, eth.BlockV3) zero, one := uint64(0), uint64(1) beaconHash := common.HexToHash("0x1234") diff --git a/op-node/p2p/host.go b/op-node/p2p/host.go index 6011617f5c78..584a42d0fe75 100644 --- a/op-node/p2p/host.go +++ b/op-node/p2p/host.go @@ -21,6 +21,7 @@ import ( "github.com/libp2p/go-libp2p/core/sec/insecure" basichost "github.com/libp2p/go-libp2p/p2p/host/basic" "github.com/libp2p/go-libp2p/p2p/muxer/yamux" + "github.com/libp2p/go-libp2p/p2p/protocol/ping" "github.com/libp2p/go-libp2p/p2p/security/noise" tls "github.com/libp2p/go-libp2p/p2p/security/tls" "github.com/libp2p/go-libp2p/p2p/transport/tcp" @@ -52,6 +53,8 @@ type extraHost struct { staticPeers []*peer.AddrInfo + pinging *PingService + quitC chan struct{} } @@ -65,6 +68,9 @@ func (e *extraHost) ConnectionManager() connmgr.ConnManager { func (e *extraHost) Close() error { close(e.quitC) + if e.pinging != nil { + e.pinging.Close() + } return e.Host.Close() } @@ -249,6 +255,14 @@ func (conf *Config) Host(log log.Logger, reporter metrics.Reporter, metrics Host staticPeers: staticPeers, quitC: make(chan struct{}), } + + if conf.EnablePingService { + out.pinging = NewPingService(log, + func(ctx context.Context, peerID peer.ID) <-chan ping.Result { + return ping.Ping(ctx, h, peerID) + }, h.Network().Peers, clock.SystemClock) + } + out.initStaticPeers() if len(conf.StaticPeers) > 0 { go out.monitorStaticPeers() diff --git a/op-node/p2p/host_test.go b/op-node/p2p/host_test.go index 25351eb24dc5..a71372a08967 100644 --- a/op-node/p2p/host_test.go +++ b/op-node/p2p/host_test.go @@ -61,10 +61,10 @@ func TestingConfig(t *testing.T) *Config { func TestP2PSimple(t *testing.T) { confA := TestingConfig(t) confB := TestingConfig(t) - hostA, err := confA.Host(testlog.Logger(t, log.LvlError).New("host", "A"), nil, metrics.NoopMetrics) + hostA, err := confA.Host(testlog.Logger(t, log.LevelError).New("host", "A"), nil, metrics.NoopMetrics) require.NoError(t, err, "failed to launch host A") defer hostA.Close() - hostB, err := confB.Host(testlog.Logger(t, log.LvlError).New("host", "B"), nil, metrics.NoopMetrics) + hostB, err := confB.Host(testlog.Logger(t, log.LevelError).New("host", "B"), nil, metrics.NoopMetrics) require.NoError(t, err, "failed to launch host B") defer hostB.Close() err = hostA.Connect(context.Background(), peer.AddrInfo{ID: hostB.ID(), Addrs: hostB.Addrs()}) @@ -119,7 +119,7 @@ func TestP2PFull(t *testing.T) { runCfgA := &testutils.MockRuntimeConfig{P2PSeqAddress: common.Address{0x42}} runCfgB := &testutils.MockRuntimeConfig{P2PSeqAddress: common.Address{0x42}} - logA := testlog.Logger(t, log.LvlError).New("host", "A") + logA := testlog.Logger(t, log.LevelError).New("host", "A") nodeA, err := NewNodeP2P(context.Background(), &rollup.Config{}, logA, &confA, &mockGossipIn{}, nil, runCfgA, metrics.NoopMetrics, false) require.NoError(t, err) defer nodeA.Close() @@ -148,7 +148,7 @@ func TestP2PFull(t *testing.T) { require.NoError(t, err) confB.StaticPeers = append(confB.StaticPeers, altAddrB) - logB := testlog.Logger(t, log.LvlError).New("host", "B") + logB := testlog.Logger(t, log.LevelError).New("host", "B") nodeB, err := NewNodeP2P(context.Background(), &rollup.Config{}, logB, &confB, &mockGossipIn{}, nil, runCfgB, metrics.NoopMetrics, false) require.NoError(t, err) @@ -159,7 +159,7 @@ func TestP2PFull(t *testing.T) { require.False(t, nodeB.IsStatic(hostB.ID()), "node B must not be static peer of node B itself") select { - case <-time.After(time.Second): + case <-time.After(30 * time.Second): t.Fatal("failed to connect new host") case c := <-conns: require.Equal(t, hostB.ID(), c.RemotePeer()) @@ -181,6 +181,17 @@ func TestP2PFull(t *testing.T) { require.Equal(t, []peer.ID{hostB.ID()}, blockedPeers) require.NoError(t, p2pClientA.UnblockPeer(ctx, hostB.ID())) + require.Error(t, p2pClientA.BlockAddr(ctx, nil)) + require.Error(t, p2pClientA.UnblockAddr(ctx, nil)) + require.Error(t, p2pClientA.BlockSubnet(ctx, nil)) + require.Error(t, p2pClientA.UnblockSubnet(ctx, nil)) + require.Error(t, p2pClientA.BlockPeer(ctx, "")) + require.Error(t, p2pClientA.UnblockPeer(ctx, "")) + require.Error(t, p2pClientA.ProtectPeer(ctx, "")) + require.Error(t, p2pClientA.UnprotectPeer(ctx, "")) + require.Error(t, p2pClientA.ConnectPeer(ctx, "")) + require.Error(t, p2pClientA.DisconnectPeer(ctx, "")) + require.NoError(t, p2pClientA.BlockAddr(ctx, net.IP{123, 123, 123, 123})) blockedIPs, err := p2pClientA.ListBlockedAddrs(ctx) require.NoError(t, err) @@ -208,11 +219,16 @@ func TestP2PFull(t *testing.T) { require.Equal(t, uint(1), stats.Connected) // disconnect + hostBId := hostB.ID().String() + peerDump, err = p2pClientA.Peers(ctx, false) + require.Nil(t, err) + data = peerDump.Peers[hostBId] + require.NotNil(t, data) require.NoError(t, p2pClientA.DisconnectPeer(ctx, hostB.ID())) peerDump, err = p2pClientA.Peers(ctx, false) require.Nil(t, err) - data = peerDump.Peers[hostB.ID().String()] - require.Equal(t, data.Connectedness, network.NotConnected) + data = peerDump.Peers[hostBId] + require.Nil(t, data) // reconnect addrsB, err := peer.AddrInfoToP2pAddrs(&peer.AddrInfo{ID: hostB.ID(), Addrs: hostB.Addrs()}) @@ -224,6 +240,8 @@ func TestP2PFull(t *testing.T) { } func TestDiscovery(t *testing.T) { + t.Skipf("skipping flaky test") + pA, _, err := crypto.GenerateSecp256k1Key(rand.Reader) require.NoError(t, err, "failed to generate new p2p priv key") pB, _, err := crypto.GenerateSecp256k1Key(rand.Reader) @@ -231,9 +249,9 @@ func TestDiscovery(t *testing.T) { pC, _, err := crypto.GenerateSecp256k1Key(rand.Reader) require.NoError(t, err, "failed to generate new p2p priv key") - logA := testlog.Logger(t, log.LvlError).New("host", "A") - logB := testlog.Logger(t, log.LvlError).New("host", "B") - logC := testlog.Logger(t, log.LvlError).New("host", "C") + logA := testlog.Logger(t, log.LevelError).New("host", "A") + logB := testlog.Logger(t, log.LevelError).New("host", "B") + logC := testlog.Logger(t, log.LevelError).New("host", "C") discDBA, err := enode.OpenDB("") // "" = memory db require.NoError(t, err) diff --git a/op-node/p2p/monitor/peer_monitor_test.go b/op-node/p2p/monitor/peer_monitor_test.go index 6e18ac43f9c4..815e0531497c 100644 --- a/op-node/p2p/monitor/peer_monitor_test.go +++ b/op-node/p2p/monitor/peer_monitor_test.go @@ -18,7 +18,7 @@ import ( const testBanDuration = 2 * time.Hour func peerMonitorSetup(t *testing.T) (*PeerMonitor, *clock2.DeterministicClock, *mocks.PeerManager) { - l := testlog.Logger(t, log.LvlInfo) + l := testlog.Logger(t, log.LevelInfo) clock := clock2.NewDeterministicClock(time.UnixMilli(10000)) manager := mocks.NewPeerManager(t) monitor := NewPeerMonitor(context.Background(), l, clock, manager, -100, testBanDuration) diff --git a/op-node/p2p/peer_scorer_test.go b/op-node/p2p/peer_scorer_test.go index 9750c8cc57ff..d0bc6fe73e6f 100644 --- a/op-node/p2p/peer_scorer_test.go +++ b/op-node/p2p/peer_scorer_test.go @@ -30,7 +30,7 @@ type PeerScorerTestSuite struct { func (testSuite *PeerScorerTestSuite) SetupTest() { testSuite.mockStore = &p2pMocks.Peerstore{} testSuite.mockMetricer = &p2pMocks.ScoreMetrics{} - testSuite.logger = testlog.Logger(testSuite.T(), log.LvlError) + testSuite.logger = testlog.Logger(testSuite.T(), log.LevelError) } // TestPeerScorer runs the PeerScorerTestSuite. diff --git a/op-node/p2p/peer_scores_test.go b/op-node/p2p/peer_scores_test.go index 4590b3466dc5..f7f8da6d5d27 100644 --- a/op-node/p2p/peer_scores_test.go +++ b/op-node/p2p/peer_scores_test.go @@ -46,7 +46,7 @@ type PeerScoresTestSuite struct { func (testSuite *PeerScoresTestSuite) SetupTest() { testSuite.mockStore = &p2pMocks.Peerstore{} testSuite.mockMetricer = &p2pMocks.ScoreMetrics{} - testSuite.logger = testlog.Logger(testSuite.T(), log.LvlError) + testSuite.logger = testlog.Logger(testSuite.T(), log.LevelError) } // TestPeerScores runs the PeerScoresTestSuite. @@ -71,7 +71,7 @@ func (c *customPeerstoreNetwork) Close() error { // getNetHosts generates a slice of hosts using the [libp2p/go-libp2p] library. func getNetHosts(testSuite *PeerScoresTestSuite, ctx context.Context, n int) []host.Host { var out []host.Host - log := testlog.Logger(testSuite.T(), log.LvlError) + log := testlog.Logger(testSuite.T(), log.LevelError) for i := 0; i < n; i++ { swarm := tswarm.GenSwarm(testSuite.T()) eps, err := store.NewExtendedPeerstore(ctx, log, clock.SystemClock, swarm.Peerstore(), sync.MutexWrap(ds.NewMapDatastore()), 1*time.Hour) @@ -99,7 +99,7 @@ func (d *discriminatingAppScorer) ApplicationScore(id peer.ID) float64 { func newGossipSubs(testSuite *PeerScoresTestSuite, ctx context.Context, hosts []host.Host) []*pubsub.PubSub { var psubs []*pubsub.PubSub - logger := testlog.Logger(testSuite.T(), log.LvlCrit) + logger := testlog.Logger(testSuite.T(), log.LevelCrit) // For each host, create a default gossipsub router. for _, h := range hosts { diff --git a/op-node/p2p/pings.go b/op-node/p2p/pings.go new file mode 100644 index 000000000000..bae2630959f2 --- /dev/null +++ b/op-node/p2p/pings.go @@ -0,0 +1,134 @@ +package p2p + +import ( + "context" + "sync" + "time" + + "github.com/libp2p/go-libp2p/core/peer" + "github.com/libp2p/go-libp2p/p2p/protocol/ping" + "golang.org/x/time/rate" + + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-service/clock" +) + +const ( + pingRound = 3 * time.Minute + pingsPerSecond rate.Limit = 1 + pingsBurst = 10 +) + +type PingFn func(ctx context.Context, peerID peer.ID) <-chan ping.Result + +type PeersFn func() []peer.ID + +type PingService struct { + ping PingFn + peers PeersFn + + clock clock.Clock + + log log.Logger + + ctx context.Context + cancel context.CancelFunc + + trace func(work string) + + // to signal service completion + wg sync.WaitGroup +} + +func NewPingService(log log.Logger, ping PingFn, peers PeersFn, clock clock.Clock) *PingService { + ctx, cancel := context.WithCancel(context.Background()) + srv := &PingService{ + ping: ping, + peers: peers, + log: log, + clock: clock, + ctx: ctx, + cancel: cancel, + } + srv.wg.Add(1) + go srv.pingPeersBackground() + return srv +} + +func (p *PingService) Close() { + p.cancel() + p.wg.Wait() +} + +func (e *PingService) pingPeersBackground() { + defer e.wg.Done() + + tick := e.clock.NewTicker(pingRound) + defer tick.Stop() + + if e.trace != nil { + e.trace("started") + } + + for { + select { + case <-tick.Ch(): + e.pingPeers() + case <-e.ctx.Done(): + return + } + } +} + +func (e *PingService) pingPeers() { + if e.trace != nil { + e.trace("pingPeers start") + } + ctx, cancel := context.WithTimeout(e.ctx, pingRound) + defer cancel() + + // Wait group to wait for all pings to complete + var wg sync.WaitGroup + // Rate-limiter to help schedule the ping + // work without overwhelming ourselves. + rl := rate.NewLimiter(pingsPerSecond, pingsBurst) + + // iterate through the connected peers + for i, peerID := range e.peers() { + if e.ctx.Err() != nil { // stop if the service is closing or timing out + return + } + if ctx.Err() != nil { + e.log.Warn("failed to ping all peers", "pinged", i, "err", ctx.Err()) + return + } + if err := rl.Wait(ctx); err != nil { + // host may be getting closed, causing a parent ctx to close. + return + } + wg.Add(1) + go func(peerID peer.ID) { + e.pingPeer(ctx, peerID) + wg.Done() + }(peerID) + } + wg.Wait() + if e.trace != nil { + e.trace("pingPeers end") + } +} + +func (e *PingService) pingPeer(ctx context.Context, peerID peer.ID) { + results := e.ping(ctx, peerID) + // the results channel will be closed by the ping.Ping function upon context close / completion + res, ok := <-results + if !ok { + // timed out or completed before Pong + e.log.Warn("failed to ping peer, context cancelled", "peerID", peerID, "err", ctx.Err()) + } else if res.Error != nil { + e.log.Warn("failed to ping peer, communication error", "peerID", peerID, "err", res.Error) + } else { + e.log.Debug("ping-pong", "peerID", peerID, "rtt", res.RTT) + } +} diff --git a/op-node/p2p/pings_test.go b/op-node/p2p/pings_test.go new file mode 100644 index 000000000000..5db685dd7a18 --- /dev/null +++ b/op-node/p2p/pings_test.go @@ -0,0 +1,84 @@ +package p2p + +import ( + "context" + "errors" + "testing" + "time" + + "github.com/stretchr/testify/require" + "golang.org/x/exp/slog" + + "github.com/libp2p/go-libp2p/core/peer" + "github.com/libp2p/go-libp2p/p2p/protocol/ping" + + "github.com/ethereum-optimism/optimism/op-service/clock" + "github.com/ethereum-optimism/optimism/op-service/testlog" +) + +func TestPingService(t *testing.T) { + peers := []peer.ID{"a", "b", "c"} + log, captLog := testlog.CaptureLogger(t, slog.LevelDebug) + + pingCount := 0 + pingFn := PingFn(func(ctx context.Context, peerID peer.ID) <-chan ping.Result { + out := make(chan ping.Result, 1) + switch pingCount % 3 { + case 0: + // success + out <- ping.Result{ + RTT: time.Millisecond * 10, + Error: nil, + } + case 1: + // fake timeout + case 2: + // error + out <- ping.Result{ + RTT: 0, + Error: errors.New("fake error"), + } + } + close(out) + pingCount += 1 + return out + }) + + fakeClock := clock.NewDeterministicClock(time.Now()) + peersFn := PeersFn(func() []peer.ID { + return peers + }) + + srv := NewPingService(log, pingFn, peersFn, fakeClock) + + trace := make(chan string) + srv.trace = func(work string) { + trace <- work + } + + // wait for ping service to get online + require.Equal(t, "started", <-trace) + fakeClock.AdvanceTime(pingRound) + // wait for first round to start and complete + require.Equal(t, "pingPeers start", <-trace) + require.Equal(t, "pingPeers end", <-trace) + // see if client has hit all 3 cases we simulated on the server-side + require.Equal(t, 3, pingCount, "pinged 3 peers") + require.NotNil(t, captLog.FindLog(testlog.NewMessageContainsFilter("ping-pong")), "case 0") + require.NotNil(t, captLog.FindLog(testlog.NewMessageContainsFilter("failed to ping peer, context cancelled")), "case 1") + require.NotNil(t, captLog.FindLog(testlog.NewMessageContainsFilter("failed to ping peer, communication error")), "case 2") + captLog.Clear() + + // advance clock again to proceed to second round, and wait for the round to start and complete + fakeClock.AdvanceTime(pingRound) + require.Equal(t, "pingPeers start", <-trace) + require.Equal(t, "pingPeers end", <-trace) + // see if client has hit all 3 cases we simulated on the server-side + require.Equal(t, 6, pingCount, "pinged 3 peers again") + require.NotNil(t, captLog.FindLog(testlog.NewMessageContainsFilter("ping-pong")), "case 0") + require.NotNil(t, captLog.FindLog(testlog.NewMessageContainsFilter("failed to ping peer, context cancelled")), "case 1") + require.NotNil(t, captLog.FindLog(testlog.NewMessageContainsFilter("failed to ping peer, communication error")), "case 2") + captLog.Clear() + + srv.Close() +} diff --git a/op-node/p2p/rpc_server.go b/op-node/p2p/rpc_server.go index 8e122a7862c8..1a9c7fcb8f2b 100644 --- a/op-node/p2p/rpc_server.go +++ b/op-node/p2p/rpc_server.go @@ -36,6 +36,7 @@ var ( ErrDisabledDiscovery = errors.New("discovery disabled") ErrNoConnectionManager = errors.New("no connection manager") ErrNoConnectionGater = errors.New("no connection gater") + ErrInvalidRequest = errors.New("invalid request") ) type Node interface { @@ -244,23 +245,31 @@ func (s *APIBackend) DiscoveryTable(_ context.Context) ([]*enode.Node, error) { } } -func (s *APIBackend) BlockPeer(_ context.Context, p peer.ID) error { +func (s *APIBackend) BlockPeer(_ context.Context, id peer.ID) error { recordDur := s.m.RecordRPCServerRequest("opp2p_blockPeer") + if err := id.Validate(); err != nil { + log.Warn("invalid peer ID", "method", "BlockPeer", "peer", id, "err", err) + return ErrInvalidRequest + } defer recordDur() if gater := s.node.ConnectionGater(); gater == nil { return ErrNoConnectionGater } else { - return gater.BlockPeer(p) + return gater.BlockPeer(id) } } -func (s *APIBackend) UnblockPeer(_ context.Context, p peer.ID) error { +func (s *APIBackend) UnblockPeer(_ context.Context, id peer.ID) error { recordDur := s.m.RecordRPCServerRequest("opp2p_unblockPeer") + if err := id.Validate(); err != nil { + log.Warn("invalid peer ID", "method", "UnblockPeer", "peer", id, "err", err) + return ErrInvalidRequest + } defer recordDur() if gater := s.node.ConnectionGater(); gater == nil { return ErrNoConnectionGater } else { - return gater.UnblockPeer(p) + return gater.UnblockPeer(id) } } @@ -278,6 +287,10 @@ func (s *APIBackend) ListBlockedPeers(_ context.Context) ([]peer.ID, error) { // Note: active connections to the IP address are not automatically closed. func (s *APIBackend) BlockAddr(_ context.Context, ip net.IP) error { recordDur := s.m.RecordRPCServerRequest("opp2p_blockAddr") + if ip == nil { + log.Warn("invalid IP", "method", "BlockAddr") + return ErrInvalidRequest + } defer recordDur() if gater := s.node.ConnectionGater(); gater == nil { return ErrNoConnectionGater @@ -288,6 +301,10 @@ func (s *APIBackend) BlockAddr(_ context.Context, ip net.IP) error { func (s *APIBackend) UnblockAddr(_ context.Context, ip net.IP) error { recordDur := s.m.RecordRPCServerRequest("opp2p_unblockAddr") + if ip == nil { + log.Warn("invalid IP", "method", "UnblockAddr") + return ErrInvalidRequest + } defer recordDur() if gater := s.node.ConnectionGater(); gater == nil { return ErrNoConnectionGater @@ -310,6 +327,10 @@ func (s *APIBackend) ListBlockedAddrs(_ context.Context) ([]net.IP, error) { // Note: active connections to the IP subnet are not automatically closed. func (s *APIBackend) BlockSubnet(_ context.Context, ipnet *net.IPNet) error { recordDur := s.m.RecordRPCServerRequest("opp2p_blockSubnet") + if ipnet == nil { + log.Warn("invalid IPNet", "method", "BlockSubnet") + return ErrInvalidRequest + } defer recordDur() if gater := s.node.ConnectionGater(); gater == nil { return ErrNoConnectionGater @@ -320,6 +341,10 @@ func (s *APIBackend) BlockSubnet(_ context.Context, ipnet *net.IPNet) error { func (s *APIBackend) UnblockSubnet(_ context.Context, ipnet *net.IPNet) error { recordDur := s.m.RecordRPCServerRequest("opp2p_unblockSubnet") + if ipnet == nil { + log.Warn("invalid IPNet", "method", "UnblockSubnet") + return ErrInvalidRequest + } defer recordDur() if gater := s.node.ConnectionGater(); gater == nil { return ErrNoConnectionGater @@ -338,24 +363,32 @@ func (s *APIBackend) ListBlockedSubnets(_ context.Context) ([]*net.IPNet, error) } } -func (s *APIBackend) ProtectPeer(_ context.Context, p peer.ID) error { +func (s *APIBackend) ProtectPeer(_ context.Context, id peer.ID) error { recordDur := s.m.RecordRPCServerRequest("opp2p_protectPeer") + if err := id.Validate(); err != nil { + log.Warn("invalid peer ID", "method", "ProtectPeer", "peer", id, "err", err) + return ErrInvalidRequest + } defer recordDur() if manager := s.node.ConnectionManager(); manager == nil { return ErrNoConnectionManager } else { - manager.Protect(p, "api-protected") + manager.Protect(id, "api-protected") return nil } } -func (s *APIBackend) UnprotectPeer(_ context.Context, p peer.ID) error { +func (s *APIBackend) UnprotectPeer(_ context.Context, id peer.ID) error { recordDur := s.m.RecordRPCServerRequest("opp2p_unprotectPeer") + if err := id.Validate(); err != nil { + log.Warn("invalid peer ID", "method", "UnprotectPeer", "peer", id, "err", err) + return ErrInvalidRequest + } defer recordDur() if manager := s.node.ConnectionManager(); manager == nil { return ErrNoConnectionManager } else { - manager.Unprotect(p, "api-protected") + manager.Unprotect(id, "api-protected") return nil } } @@ -377,6 +410,21 @@ func (s *APIBackend) ConnectPeer(ctx context.Context, addr string) error { func (s *APIBackend) DisconnectPeer(_ context.Context, id peer.ID) error { recordDur := s.m.RecordRPCServerRequest("opp2p_disconnectPeer") + if err := id.Validate(); err != nil { + log.Warn("invalid peer ID", "method", "DisconnectPeer", "peer", id, "err", err) + return ErrInvalidRequest + } defer recordDur() - return s.node.Host().Network().ClosePeer(id) + err := s.node.Host().Network().ClosePeer(id) + if err != nil { + return err + } + ps := s.node.Host().Peerstore() + ps.RemovePeer(id) + ps.ClearAddrs(id) + err = s.node.ConnectionGater().UnblockPeer(id) + if err != nil { + return fmt.Errorf("closed peer but failed to unblock: %w", err) + } + return nil } diff --git a/op-node/p2p/store/gc_test.go b/op-node/p2p/store/gc_test.go index 68d8023b1bd5..650b5bb3cb4b 100644 --- a/op-node/p2p/store/gc_test.go +++ b/op-node/p2p/store/gc_test.go @@ -20,7 +20,7 @@ func TestScheduleGcPeriodically(t *testing.T) { // Wait for the gc background process to complete after cancelling the context bgTasks.Wait() }() - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) clock := clock.NewDeterministicClock(time.UnixMilli(5000)) called := make(chan struct{}, 10) diff --git a/op-node/p2p/store/ip_ban_book_test.go b/op-node/p2p/store/ip_ban_book_test.go index 34bf37618258..24d3574e0c93 100644 --- a/op-node/p2p/store/ip_ban_book_test.go +++ b/op-node/p2p/store/ip_ban_book_test.go @@ -35,7 +35,7 @@ func TestRoundTripIPBan(t *testing.T) { func createMemoryIPBanBook(t *testing.T) *ipBanBook { store := sync.MutexWrap(ds.NewMapDatastore()) - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) c := clock.NewDeterministicClock(time.UnixMilli(100)) book, err := newIPBanBook(context.Background(), logger, c, store) require.NoError(t, err) diff --git a/op-node/p2p/store/peer_ban_book_test.go b/op-node/p2p/store/peer_ban_book_test.go index a9d0ce6c28b2..580dea3a3e8e 100644 --- a/op-node/p2p/store/peer_ban_book_test.go +++ b/op-node/p2p/store/peer_ban_book_test.go @@ -33,7 +33,7 @@ func TestRoundTripPeerBan(t *testing.T) { func createMemoryPeerBanBook(t *testing.T) *peerBanBook { store := sync.MutexWrap(ds.NewMapDatastore()) - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) c := clock.NewDeterministicClock(time.UnixMilli(100)) book, err := newPeerBanBook(context.Background(), logger, c, store) require.NoError(t, err) diff --git a/op-node/p2p/store/scorebook_test.go b/op-node/p2p/store/scorebook_test.go index 2ff398df9edf..29fa7a2fe303 100644 --- a/op-node/p2p/store/scorebook_test.go +++ b/op-node/p2p/store/scorebook_test.go @@ -165,7 +165,7 @@ func TestCloseCompletes(t *testing.T) { func TestPrune(t *testing.T) { ctx, cancelFunc := context.WithCancel(context.Background()) defer cancelFunc() - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) store := sync.MutexWrap(ds.NewMapDatastore()) clock := clock.NewDeterministicClock(time.UnixMilli(1000)) book, err := newScoreBook(ctx, logger, clock, store, 24*time.Hour) @@ -220,7 +220,7 @@ func TestPrune(t *testing.T) { func TestPruneMultipleBatches(t *testing.T) { ctx, cancelFunc := context.WithCancel(context.Background()) defer cancelFunc() - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) clock := clock.NewDeterministicClock(time.UnixMilli(1000)) book, err := newScoreBook(ctx, logger, clock, sync.MutexWrap(ds.NewMapDatastore()), 24*time.Hour) require.NoError(t, err) @@ -250,7 +250,7 @@ func TestPruneMultipleBatches(t *testing.T) { func TestIgnoreOutdatedScores(t *testing.T) { ctx, cancelFunc := context.WithCancel(context.Background()) defer cancelFunc() - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) clock := clock.NewDeterministicClock(time.UnixMilli(1000)) retentionPeriod := 24 * time.Hour book, err := newScoreBook(ctx, logger, clock, sync.MutexWrap(ds.NewMapDatastore()), retentionPeriod) @@ -289,7 +289,7 @@ func createMemoryStore(t *testing.T) ExtendedPeerstore { func createPeerstoreWithBacking(t *testing.T, store *sync.MutexDatastore) ExtendedPeerstore { ps, err := pstoreds.NewPeerstore(context.Background(), store, pstoreds.DefaultOpts()) require.NoError(t, err, "Failed to create peerstore") - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) c := clock.NewDeterministicClock(time.UnixMilli(100)) eps, err := NewExtendedPeerstore(context.Background(), logger, c, ps, store, 24*time.Hour) require.NoError(t, err) diff --git a/op-node/p2p/sync_test.go b/op-node/p2p/sync_test.go index 4e40f76256fd..0c43778ce8f0 100644 --- a/op-node/p2p/sync_test.go +++ b/op-node/p2p/sync_test.go @@ -124,7 +124,7 @@ func setupSyncTestData(length uint64) (*rollup.Config, *syncTestData) { func TestSinglePeerSync(t *testing.T) { t.Parallel() // Takes a while, but can run in parallel - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) cfg, payloads := setupSyncTestData(25) @@ -191,7 +191,7 @@ func TestSinglePeerSync(t *testing.T) { func TestMultiPeerSync(t *testing.T) { t.Parallel() // Takes a while, but can run in parallel - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) cfg, payloads := setupSyncTestData(100) @@ -329,7 +329,7 @@ func TestMultiPeerSync(t *testing.T) { func TestNetworkNotifyAddPeerAndRemovePeer(t *testing.T) { t.Parallel() - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) cfg, _ := setupSyncTestData(25) diff --git a/op-node/rollup/derive/attributes_queue_test.go b/op-node/rollup/derive/attributes_queue_test.go index 702ff1296942..c9f23080d4fc 100644 --- a/op-node/rollup/derive/attributes_queue_test.go +++ b/op-node/rollup/derive/attributes_queue_test.go @@ -79,7 +79,7 @@ func TestAttributesQueue(t *testing.T) { } attrBuilder := NewFetchingAttributesBuilder(cfg, l1Fetcher, l2Fetcher) - aq := NewAttributesQueue(testlog.Logger(t, log.LvlError), cfg, attrBuilder, nil) + aq := NewAttributesQueue(testlog.Logger(t, log.LevelError), cfg, attrBuilder, nil) actual, err := aq.createNextAttributes(context.Background(), &batch, safeHead) diff --git a/op-node/rollup/derive/batch_queue.go b/op-node/rollup/derive/batch_queue.go index 22cb1bafc547..4ac92bf04b8b 100644 --- a/op-node/rollup/derive/batch_queue.go +++ b/op-node/rollup/derive/batch_queue.go @@ -117,11 +117,7 @@ func (bq *BatchQueue) NextBatch(ctx context.Context, parent eth.L2BlockRef) (*Si for i, l1Block := range bq.l1Blocks { if parent.L1Origin.Number == l1Block.Number { bq.l1Blocks = bq.l1Blocks[i:] - if len(bq.l1Blocks) > 0 { - bq.log.Debug("Advancing internal L1 blocks", "next_epoch", bq.l1Blocks[0].ID(), "next_epoch_time", bq.l1Blocks[0].Time) - } else { - bq.log.Debug("Advancing internal L1 blocks. No L1 blocks left") - } + bq.log.Debug("Advancing internal L1 blocks", "next_epoch", bq.l1Blocks[0].ID(), "next_epoch_time", bq.l1Blocks[0].Time) break } } diff --git a/op-node/rollup/derive/batch_queue_test.go b/op-node/rollup/derive/batch_queue_test.go index 9598d78efc4a..f82a7520842a 100644 --- a/op-node/rollup/derive/batch_queue_test.go +++ b/op-node/rollup/derive/batch_queue_test.go @@ -167,7 +167,7 @@ func TestBatchQueue(t *testing.T) { // when the safehead's origin is ahead of the pipeline's origin (as is after a reset). // This issue was fixed in https://github.com/ethereum-optimism/optimism/pull/3694 func BatchQueueNewOrigin(t *testing.T, batchType int) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) l1 := L1Chain([]uint64{10, 15, 20, 25}) safeHead := eth.L2BlockRef{ Hash: mockHash(10, 2), @@ -227,7 +227,7 @@ func BatchQueueNewOrigin(t *testing.T, batchType int) { // BatchQueueEager adds a bunch of contiguous batches and asserts that // enough calls to `NextBatch` return all of those batches. func BatchQueueEager(t *testing.T, batchType int) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) l1 := L1Chain([]uint64{10, 20, 30}) chainId := big.NewInt(1234) safeHead := eth.L2BlockRef{ @@ -305,7 +305,7 @@ func BatchQueueEager(t *testing.T, batchType int) { // BatchQueueInvalidInternalAdvance asserts that we do not miss an epoch when generating batches. // This is a regression test for CLI-3378. func BatchQueueInvalidInternalAdvance(t *testing.T, batchType int) { - log := testlog.Logger(t, log.LvlTrace) + log := testlog.Logger(t, log.LevelTrace) l1 := L1Chain([]uint64{10, 15, 20, 25, 30}) chainId := big.NewInt(1234) safeHead := eth.L2BlockRef{ @@ -424,7 +424,7 @@ func BatchQueueInvalidInternalAdvance(t *testing.T, batchType int) { } func BatchQueueMissing(t *testing.T, batchType int) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) l1 := L1Chain([]uint64{10, 15, 20, 25}) chainId := big.NewInt(1234) safeHead := eth.L2BlockRef{ @@ -541,7 +541,7 @@ func BatchQueueMissing(t *testing.T, batchType int) { // BatchQueueAdvancedEpoch tests that batch queue derives consecutive valid batches with advancing epochs. // Batch queue's l1blocks list should be updated along epochs. func BatchQueueAdvancedEpoch(t *testing.T, batchType int) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) l1 := L1Chain([]uint64{0, 6, 12, 18, 24}) // L1 block time: 6s chainId := big.NewInt(1234) safeHead := eth.L2BlockRef{ @@ -628,7 +628,7 @@ func BatchQueueAdvancedEpoch(t *testing.T, batchType int) { // BatchQueueShuffle tests batch queue can reorder shuffled valid batches func BatchQueueShuffle(t *testing.T, batchType int) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) l1 := L1Chain([]uint64{0, 6, 12, 18, 24}) // L1 block time: 6s chainId := big.NewInt(1234) safeHead := eth.L2BlockRef{ @@ -726,7 +726,7 @@ func BatchQueueShuffle(t *testing.T, batchType int) { } func TestBatchQueueOverlappingSpanBatch(t *testing.T) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) l1 := L1Chain([]uint64{10, 20, 30}) chainId := big.NewInt(1234) safeHead := eth.L2BlockRef{ @@ -831,7 +831,7 @@ func TestBatchQueueOverlappingSpanBatch(t *testing.T) { } func TestBatchQueueComplex(t *testing.T) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) l1 := L1Chain([]uint64{0, 6, 12, 18, 24}) // L1 block time: 6s chainId := big.NewInt(1234) safeHead := eth.L2BlockRef{ @@ -949,7 +949,7 @@ func TestBatchQueueComplex(t *testing.T) { } func TestBatchQueueResetSpan(t *testing.T) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) chainId := big.NewInt(1234) l1 := L1Chain([]uint64{0, 4, 8}) safeHead := eth.L2BlockRef{ diff --git a/op-node/rollup/derive/batches_test.go b/op-node/rollup/derive/batches_test.go index 67ba1ccaed99..2cef6c4c6c0b 100644 --- a/op-node/rollup/derive/batches_test.go +++ b/op-node/rollup/derive/batches_test.go @@ -1,12 +1,10 @@ package derive import ( - "bytes" "context" "errors" "math/big" "math/rand" - "strings" "testing" "github.com/stretchr/testify/require" @@ -31,16 +29,6 @@ type ValidBatchTestCase struct { DeltaTime *uint64 } -type TestLogHandler struct { - handler log.Handler - logs *bytes.Buffer -} - -func (th *TestLogHandler) Log(r *log.Record) error { - th.logs.WriteString(r.Msg + "\n") - return th.handler.Log(r) -} - func TestValidBatch(t *testing.T) { defaultConf := rollup.Config{ Genesis: rollup.Genesis{ @@ -1498,12 +1486,7 @@ func TestValidBatch(t *testing.T) { } // Log level can be increased for debugging purposes - logger := testlog.Logger(t, log.LvlError) - - // Create a test log handler to check expected logs - var logBuf bytes.Buffer - handler := TestLogHandler{handler: logger.GetHandler(), logs: &logBuf} - logger.SetHandler(&handler) + logger, logs := testlog.CaptureLogger(t, log.LevelDebug) l2Client := testutils.MockL2Client{} var nilErr error @@ -1538,19 +1521,21 @@ func TestValidBatch(t *testing.T) { } validity := CheckBatch(ctx, &rcfg, logger, testCase.L1Blocks, testCase.L2SafeHead, &testCase.Batch, &l2Client) require.Equal(t, testCase.Expected, validity, "batch check must return expected validity level") - if testCase.ExpectedLog != "" { + if expLog := testCase.ExpectedLog; expLog != "" { // Check if ExpectedLog is contained in the log buffer - if !strings.Contains(logBuf.String(), testCase.ExpectedLog) { - t.Errorf("Expected log message was not found in the buffer: %s", testCase.ExpectedLog) + containsFilter := testlog.NewMessageContainsFilter(expLog) + if l := logs.FindLog(containsFilter); l == nil { + t.Errorf("Expected log message was not logged: %q", expLog) } } - if testCase.NotExpectedLog != "" { + if notExpLog := testCase.NotExpectedLog; notExpLog != "" { // Check if NotExpectedLog is contained in the log buffer - if strings.Contains(logBuf.String(), testCase.NotExpectedLog) { - t.Errorf("Not expected log message was found in the buffer: %s", testCase.NotExpectedLog) + containsFilter := testlog.NewMessageContainsFilter(notExpLog) + if l := logs.FindLog(containsFilter); l != nil { + t.Errorf("Unexpected log message containing %q was logged: %q", notExpLog, l.Message) } } - logBuf.Reset() + logs.Clear() } // Run singular batch test cases diff --git a/op-node/rollup/derive/blob_data_source.go b/op-node/rollup/derive/blob_data_source.go index 7780b6065063..ab8a3dbb022e 100644 --- a/op-node/rollup/derive/blob_data_source.go +++ b/op-node/rollup/derive/blob_data_source.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-service/eigenda" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -23,24 +24,28 @@ type blobOrCalldata struct { // BlobDataSource fetches blobs or calldata as appropriate and transforms them into usable rollup // data. type BlobDataSource struct { - data []blobOrCalldata - ref eth.L1BlockRef - batcherAddr common.Address - dsCfg DataSourceConfig - fetcher L1TransactionFetcher - blobsFetcher L1BlobsFetcher - log log.Logger + data []blobOrCalldata + ref eth.L1BlockRef + batcherAddr common.Address + dsCfg DataSourceConfig + fetcher L1TransactionFetcher + blobsFetcher L1BlobsFetcher + log log.Logger + daClient eigenda.IEigenDA + prefixDerivationEnabled bool } // NewBlobDataSource creates a new blob data source. -func NewBlobDataSource(ctx context.Context, log log.Logger, dsCfg DataSourceConfig, fetcher L1TransactionFetcher, blobsFetcher L1BlobsFetcher, ref eth.L1BlockRef, batcherAddr common.Address) DataIter { +func NewBlobDataSource(ctx context.Context, log log.Logger, dsCfg DataSourceConfig, fetcher L1TransactionFetcher, blobsFetcher L1BlobsFetcher, ref eth.L1BlockRef, batcherAddr common.Address, daClient eigenda.IEigenDA, prefixDerivationEnabled bool) DataIter { return &BlobDataSource{ - ref: ref, - dsCfg: dsCfg, - fetcher: fetcher, - log: log.New("origin", ref), - batcherAddr: batcherAddr, - blobsFetcher: blobsFetcher, + ref: ref, + dsCfg: dsCfg, + fetcher: fetcher, + log: log.New("origin", ref), + batcherAddr: batcherAddr, + blobsFetcher: blobsFetcher, + daClient: daClient, + prefixDerivationEnabled: prefixDerivationEnabled, } } @@ -86,7 +91,7 @@ func (ds *BlobDataSource) open(ctx context.Context) ([]blobOrCalldata, error) { return nil, NewTemporaryError(fmt.Errorf("failed to open blob data source: %w", err)) } - data, hashes := dataAndHashesFromTxs(txs, &ds.dsCfg, ds.batcherAddr) + data, hashes := dataAndHashesFromTxs(txs, &ds.dsCfg, ds.batcherAddr, ds.daClient, ds.prefixDerivationEnabled) if len(hashes) == 0 { // there are no blobs to fetch so we can return immediately @@ -115,11 +120,12 @@ func (ds *BlobDataSource) open(ctx context.Context) ([]blobOrCalldata, error) { // dataAndHashesFromTxs extracts calldata and datahashes from the input transactions and returns them. It // creates a placeholder blobOrCalldata element for each returned blob hash that must be populated // by fillBlobPointers after blob bodies are retrieved. -func dataAndHashesFromTxs(txs types.Transactions, config *DataSourceConfig, batcherAddr common.Address) ([]blobOrCalldata, []eth.IndexedBlobHash) { +func dataAndHashesFromTxs(txs types.Transactions, config *DataSourceConfig, batcherAddr common.Address, daClient eigenda.IEigenDA, prefixDerivationEnabled bool) ([]blobOrCalldata, []eth.IndexedBlobHash) { data := []blobOrCalldata{} var hashes []eth.IndexedBlobHash blobIndex := 0 // index of each blob in the block's blob sidecar for _, tx := range txs { + logger := log.New("tx", tx.Hash()) // skip any non-batcher transactions if !isValidBatchTx(tx, config.l1Signer, config.batchInboxAddress, batcherAddr) { blobIndex += len(tx.BlobHashes()) @@ -127,8 +133,12 @@ func dataAndHashesFromTxs(txs types.Transactions, config *DataSourceConfig, batc } // handle non-blob batcher transactions by extracting their calldata if tx.Type() != types.BlobTxType { - calldata := eth.Data(tx.Data()) - data = append(data, blobOrCalldata{nil, &calldata}) + calldata := DataFromEVMTransactions(*config, batcherAddr, types.Transactions{tx}, logger, daClient, prefixDerivationEnabled) + if len(calldata) == 0 { + log.Warn("eigenda: skipping empty calldata") + continue + } + data = append(data, blobOrCalldata{nil, &calldata[0]}) continue } // handle blob batcher transactions by extracting their blob hashes, ignoring any calldata. diff --git a/op-node/rollup/derive/blob_data_source_test.go b/op-node/rollup/derive/blob_data_source_test.go index aa9ef82cb991..3dada928337b 100644 --- a/op-node/rollup/derive/blob_data_source_test.go +++ b/op-node/rollup/derive/blob_data_source_test.go @@ -42,7 +42,7 @@ func TestDataAndHashesFromTxs(t *testing.T) { } calldataTx, _ := types.SignNewTx(privateKey, signer, txData) txs := types.Transactions{calldataTx} - data, blobHashes := dataAndHashesFromTxs(txs, &config, batcherAddr) + data, blobHashes := dataAndHashesFromTxs(txs, &config, batcherAddr, nil, false) require.Equal(t, 1, len(data)) require.Equal(t, 0, len(blobHashes)) @@ -57,14 +57,14 @@ func TestDataAndHashesFromTxs(t *testing.T) { } blobTx, _ := types.SignNewTx(privateKey, signer, blobTxData) txs = types.Transactions{blobTx} - data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr) + data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, nil, false) require.Equal(t, 1, len(data)) require.Equal(t, 1, len(blobHashes)) require.Nil(t, data[0].calldata) // try again with both the blob & calldata transactions and make sure both are picked up txs = types.Transactions{blobTx, calldataTx} - data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr) + data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, nil, false) require.Equal(t, 2, len(data)) require.Equal(t, 1, len(blobHashes)) require.NotNil(t, data[1].calldata) @@ -72,7 +72,7 @@ func TestDataAndHashesFromTxs(t *testing.T) { // make sure blob tx to the batch inbox is ignored if not signed by the batcher blobTx, _ = types.SignNewTx(testutils.RandomKey(), signer, blobTxData) txs = types.Transactions{blobTx} - data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr) + data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, nil, false) require.Equal(t, 0, len(data)) require.Equal(t, 0, len(blobHashes)) @@ -81,7 +81,7 @@ func TestDataAndHashesFromTxs(t *testing.T) { blobTxData.To = testutils.RandomAddress(rng) blobTx, _ = types.SignNewTx(privateKey, signer, blobTxData) txs = types.Transactions{blobTx} - data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr) + data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, nil, false) require.Equal(t, 0, len(data)) require.Equal(t, 0, len(blobHashes)) } diff --git a/op-node/rollup/derive/calldata_source.go b/op-node/rollup/derive/calldata_source.go index 0a5d7915770d..525cef64fa68 100644 --- a/op-node/rollup/derive/calldata_source.go +++ b/op-node/rollup/derive/calldata_source.go @@ -2,6 +2,8 @@ package derive import ( "context" + "encoding/base64" + "encoding/json" "errors" "fmt" "io" @@ -10,8 +12,11 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "google.golang.org/protobuf/proto" + "github.com/ethereum-optimism/optimism/op-service/eigenda" "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/proto/gen/op_service/v1" ) // CalldataSource is a fault tolerant approach to fetching data. @@ -27,26 +32,31 @@ type CalldataSource struct { fetcher L1TransactionFetcher log log.Logger - batcherAddr common.Address + batcherAddr common.Address + daClient eigenda.IEigenDA + prefixDerivationEnabled bool } // NewCalldataSource creates a new calldata source. It suppresses errors in fetching the L1 block if they occur. // If there is an error, it will attempt to fetch the result on the next call to `Next`. -func NewCalldataSource(ctx context.Context, log log.Logger, dsCfg DataSourceConfig, fetcher L1TransactionFetcher, ref eth.L1BlockRef, batcherAddr common.Address) DataIter { +func NewCalldataSource(ctx context.Context, log log.Logger, dsCfg DataSourceConfig, fetcher L1TransactionFetcher, ref eth.L1BlockRef, batcherAddr common.Address, daClient eigenda.IEigenDA, prefixDerivationEnabled bool) DataIter { _, txs, err := fetcher.InfoAndTxsByHash(ctx, ref.Hash) if err != nil { return &CalldataSource{ - open: false, - ref: ref, - dsCfg: dsCfg, - fetcher: fetcher, - log: log, - batcherAddr: batcherAddr, + open: false, + ref: ref, + dsCfg: dsCfg, + fetcher: fetcher, + log: log, + batcherAddr: batcherAddr, + daClient: daClient, + prefixDerivationEnabled: prefixDerivationEnabled, + } + } else { + return &CalldataSource{ + open: true, + data: DataFromEVMTransactions(dsCfg, batcherAddr, txs, log.New("origin", ref), daClient, prefixDerivationEnabled), } - } - return &CalldataSource{ - open: true, - data: DataFromEVMTransactions(dsCfg, batcherAddr, txs, log.New("origin", ref)), } } @@ -57,7 +67,7 @@ func (ds *CalldataSource) Next(ctx context.Context) (eth.Data, error) { if !ds.open { if _, txs, err := ds.fetcher.InfoAndTxsByHash(ctx, ds.ref.Hash); err == nil { ds.open = true - ds.data = DataFromEVMTransactions(ds.dsCfg, ds.batcherAddr, txs, ds.log) + ds.data = DataFromEVMTransactions(ds.dsCfg, ds.batcherAddr, txs, ds.log, ds.daClient, ds.prefixDerivationEnabled) } else if errors.Is(err, ethereum.NotFound) { return nil, NewResetError(fmt.Errorf("failed to open calldata source: %w", err)) } else { @@ -76,11 +86,71 @@ func (ds *CalldataSource) Next(ctx context.Context) (eth.Data, error) { // DataFromEVMTransactions filters all of the transactions and returns the calldata from transactions // that are sent to the batch inbox address from the batch sender address. // This will return an empty array if no valid transactions are found. -func DataFromEVMTransactions(dsCfg DataSourceConfig, batcherAddr common.Address, txs types.Transactions, log log.Logger) []eth.Data { +func DataFromEVMTransactions(dsCfg DataSourceConfig, batcherAddr common.Address, txs types.Transactions, log log.Logger, daClient eigenda.IEigenDA, prefixDerivationEnabled bool) []eth.Data { out := []eth.Data{} - for _, tx := range txs { + for j, tx := range txs { if isValidBatchTx(tx, dsCfg.l1Signer, dsCfg.batchInboxAddress, batcherAddr) { - out = append(out, tx.Data()) + data := tx.Data() + + if prefixDerivationEnabled { + log.Info("Prefix derivation enabled, checking derivation version") + switch len(data) { + case 0: + out = append(out, data) + // skip next tx + continue + default: + switch data[0] { + case eigenda.DerivationVersionEigenda: + log.Info("EigenDA derivation version detected") + // skip the first byte and unwrap the data with protobuf + data = data[1:] + default: + log.Info("No EigenDA derivation version detected, falling back to calldata") + out = append(out, data) + log.Info("Successfully read data from calldata (not EigenDA)") + // skip next tx + continue + } + } + } + + calldataFrame := &op_service.CalldataFrame{} + err := proto.Unmarshal(data, calldataFrame) + if err != nil { + log.Warn("unable to decode calldata frame", "index", j, "err", err) + return nil + } + + switch calldataFrame.Value.(type) { + case *op_service.CalldataFrame_FrameRef: + frameRef := calldataFrame.GetFrameRef() + if len(frameRef.QuorumIds) == 0 { + log.Warn("decoded frame ref contains no quorum IDs", "index", j, "err", err) + return nil + } + + log.Info("requesting data from EigenDA", "quorum id", frameRef.QuorumIds[0], "confirmation block number", frameRef.ReferenceBlockNumber) + data, err := daClient.RetrieveBlob(context.Background(), frameRef.BatchHeaderHash, frameRef.BlobIndex) + if err != nil { + retrieveReqJSON, _ := json.Marshal(struct { + BatchHeaderHash string + BlobIndex uint32 + }{ + BatchHeaderHash: base64.StdEncoding.EncodeToString(frameRef.BatchHeaderHash), + BlobIndex: frameRef.BlobIndex, + }) + log.Warn("could not retrieve data from EigenDA", "request", string(retrieveReqJSON), "err", err) + return nil + } + log.Info("Successfully retrieved data from EigenDA", "quorum id", frameRef.QuorumIds[0], "confirmation block number", frameRef.ReferenceBlockNumber) + data = data[:frameRef.BlobLength] + out = append(out, data) + case *op_service.CalldataFrame_Frame: + log.Info("Successfully read data from calldata (not EigenDA)") + frame := calldataFrame.GetFrame() + out = append(out, frame) + } } } return out diff --git a/op-node/rollup/derive/calldata_source_test.go b/op-node/rollup/derive/calldata_source_test.go index 213052b36e16..e6eb4a2b547e 100644 --- a/op-node/rollup/derive/calldata_source_test.go +++ b/op-node/rollup/derive/calldata_source_test.go @@ -1,11 +1,14 @@ package derive import ( + "context" "crypto/ecdsa" + "fmt" "math/big" "math/rand" "testing" + "github.com/Layr-Labs/eigenda/api/grpc/disperser" "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/common" @@ -15,6 +18,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-service/eigenda" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testutils" @@ -49,6 +53,34 @@ type calldataTest struct { txs []testTx } +var _ eigenda.IEigenDA = &EigenDAClientMock{} + +type EigenDAClientMock struct { + Responses [][]byte + ResponseIndex int +} + +func (c *EigenDAClientMock) RetrieveBlob(ctx context.Context, BatchHeaderHash []byte, BlobIndex uint32) ([]byte, error) { + if c.ResponseIndex < len(c.Responses) { + res := c.Responses[c.ResponseIndex] + c.ResponseIndex += 1 + return res, nil + } else { + return nil, fmt.Errorf("Ran out of stub responses") + } +} + +func (c *EigenDAClientMock) DisperseBlob(ctx context.Context, txData []byte) (*disperser.BlobInfo, error) { + return nil, fmt.Errorf("not implemented") +} + +func NewEigenDAClientMock(responses [][]byte) eigenda.IEigenDA { + return &EigenDAClientMock{ + Responses: responses, + ResponseIndex: 0, + } +} + // TestDataFromEVMTransactions creates some transactions from a specified template and asserts // that DataFromEVMTransactions properly filters and returns the data from the authorized transactions // inside the transaction set. @@ -59,6 +91,11 @@ func TestDataFromEVMTransactions(t *testing.T) { L1ChainID: big.NewInt(100), BatchInboxAddress: crypto.PubkeyToAddress(inboxPriv.PublicKey), } + + daClient := NewEigenDAClientMock([][]byte{ + []byte{0x00, 0x01, 0x02}, + }) + batcherAddr := crypto.PubkeyToAddress(batcherPriv.PublicKey) altInbox := testutils.RandomAddress(rand.New(rand.NewSource(1234))) @@ -121,7 +158,7 @@ func TestDataFromEVMTransactions(t *testing.T) { } } - out := DataFromEVMTransactions(DataSourceConfig{cfg.L1Signer(), cfg.BatchInboxAddress}, batcherAddr, txs, testlog.Logger(t, log.LvlCrit)) + out := DataFromEVMTransactions(DataSourceConfig{cfg.L1Signer(), cfg.BatchInboxAddress, false}, batcherAddr, txs, testlog.Logger(t, log.LevelCrit), daClient, false) require.ElementsMatch(t, expectedData, out) } diff --git a/op-node/rollup/derive/channel_bank_test.go b/op-node/rollup/derive/channel_bank_test.go index 495ce4426bb8..a4485834ece6 100644 --- a/op-node/rollup/derive/channel_bank_test.go +++ b/op-node/rollup/derive/channel_bank_test.go @@ -102,7 +102,7 @@ func TestChannelBankSimple(t *testing.T) { cfg := &rollup.Config{ChannelTimeout: 10} - cb := NewChannelBank(testlog.Logger(t, log.LvlCrit), cfg, input, nil, metrics.NoopMetrics) + cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, nil, metrics.NoopMetrics) // Load the first frame out, err := cb.NextData(context.Background()) @@ -146,7 +146,7 @@ func TestChannelBankInterleavedPreCanyon(t *testing.T) { cfg := &rollup.Config{ChannelTimeout: 10, CanyonTime: nil} - cb := NewChannelBank(testlog.Logger(t, log.LvlCrit), cfg, input, nil, metrics.NoopMetrics) + cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, nil, metrics.NoopMetrics) // Load a:0 out, err := cb.NextData(context.Background()) @@ -211,7 +211,7 @@ func TestChannelBankInterleaved(t *testing.T) { ct := uint64(0) cfg := &rollup.Config{ChannelTimeout: 10, CanyonTime: &ct} - cb := NewChannelBank(testlog.Logger(t, log.LvlCrit), cfg, input, nil, metrics.NoopMetrics) + cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, nil, metrics.NoopMetrics) // Load a:0 out, err := cb.NextData(context.Background()) @@ -271,7 +271,7 @@ func TestChannelBankDuplicates(t *testing.T) { cfg := &rollup.Config{ChannelTimeout: 10} - cb := NewChannelBank(testlog.Logger(t, log.LvlCrit), cfg, input, nil, metrics.NoopMetrics) + cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, nil, metrics.NoopMetrics) // Load the first frame out, err := cb.NextData(context.Background()) diff --git a/op-node/rollup/derive/channel_out.go b/op-node/rollup/derive/channel_out.go index ab94986fb8f3..52fd2fb36da0 100644 --- a/op-node/rollup/derive/channel_out.go +++ b/op-node/rollup/derive/channel_out.go @@ -22,7 +22,7 @@ var ErrChannelOutAlreadyClosed = errors.New("channel-out already closed") // This is the fixed overhead frame size, calculated as specified // in the [Frame Format] specs: 16 + 2 + 4 + 1 = 23 bytes. // -// [Frame Format]: https://github.com/ethereum-optimism/optimism/blob/develop/specs/derivation.md#frame-format +// [Frame Format]: https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/derivation.md#frame-format const FrameV0OverHeadSize = 23 var CompressorFullErr = errors.New("compressor is full") @@ -224,6 +224,10 @@ func (co *SingularChannelOut) OutputFrame(w *bytes.Buffer, maxSize uint64) (uint // BlockToSingularBatch transforms a block into a batch object that can easily be RLP encoded. func BlockToSingularBatch(rollupCfg *rollup.Config, block *types.Block) (*SingularBatch, *L1BlockInfo, error) { + if len(block.Transactions()) == 0 { + return nil, nil, fmt.Errorf("block %v has no transactions", block.Hash()) + } + opaqueTxs := make([]hexutil.Bytes, 0, len(block.Transactions())) for i, tx := range block.Transactions() { if tx.Type() == types.DepositTxType { @@ -235,9 +239,7 @@ func BlockToSingularBatch(rollupCfg *rollup.Config, block *types.Block) (*Singul } opaqueTxs = append(opaqueTxs, otx) } - if len(block.Transactions()) == 0 { - return nil, nil, fmt.Errorf("block %v has no transactions", block.Hash()) - } + l1InfoTx := block.Transactions()[0] if l1InfoTx.Type() != types.DepositTxType { return nil, nil, ErrNotDepositTx @@ -320,10 +322,10 @@ func createEmptyFrame(id ChannelID, frame uint64, readyBytes int, closed bool, m // Copy data from the local buffer into the frame data buffer maxDataSize := maxSize - FrameV0OverHeadSize - if maxDataSize > uint64(readyBytes) { + if maxDataSize >= uint64(readyBytes) { maxDataSize = uint64(readyBytes) // If we are closed & will not spill past the current frame - // mark it is the final frame of the channel. + // mark it as the final frame of the channel. if closed { f.IsLast = true } diff --git a/op-node/rollup/derive/channel_out_test.go b/op-node/rollup/derive/channel_out_test.go index a46a7a333397..7e6bc04cb06c 100644 --- a/op-node/rollup/derive/channel_out_test.go +++ b/op-node/rollup/derive/channel_out_test.go @@ -2,7 +2,9 @@ package derive import ( "bytes" + "io" "math/big" + "math/rand" "testing" "github.com/ethereum/go-ethereum/common" @@ -68,6 +70,27 @@ func TestOutputFrameSmallMaxSize(t *testing.T) { } } +func TestOutputFrameNoEmptyLastFrame(t *testing.T) { + cout, err := NewChannelOut(SingularBatchType, &nonCompressor{}, nil) + require.NoError(t, err) + + rng := rand.New(rand.NewSource(0x543331)) + chainID := big.NewInt(rng.Int63n(1000)) + txCount := 1 + singularBatch := RandomSingularBatch(rng, txCount, chainID) + + written, err := cout.AddSingularBatch(singularBatch, 0) + require.NoError(t, err) + + require.NoError(t, cout.Close()) + + var buf bytes.Buffer + // Output a frame which needs exactly `written` bytes. This frame is expected to be the last frame. + _, err = cout.OutputFrame(&buf, written+FrameV0OverHeadSize) + require.ErrorIs(t, err, io.EOF) + +} + // TestRLPByteLimit ensures that stream encoder is properly limiting the length. // It will decode the input if `len(input) <= inputLimit`. func TestRLPByteLimit(t *testing.T) { diff --git a/op-node/rollup/derive/data_source.go b/op-node/rollup/derive/data_source.go index 9881b813d7cd..a117b0591879 100644 --- a/op-node/rollup/derive/data_source.go +++ b/op-node/rollup/derive/data_source.go @@ -9,6 +9,8 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-node/rollup" + plasma "github.com/ethereum-optimism/optimism/op-plasma" + "github.com/ethereum-optimism/optimism/op-service/eigenda" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -25,40 +27,85 @@ type L1BlobsFetcher interface { GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) } +type PlasmaInputFetcher interface { + // GetInput fetches the input for the given commitment at the given block number from the DA storage service. + GetInput(ctx context.Context, l1 plasma.L1Fetcher, c plasma.Keccak256Commitment, blockId eth.BlockID) (eth.Data, error) + // AdvanceL1Origin advances the L1 origin to the given block number, syncing the DA challenge events. + AdvanceL1Origin(ctx context.Context, l1 plasma.L1Fetcher, blockId eth.BlockID) error + // Reset the challenge origin in case of L1 reorg + Reset(ctx context.Context, base eth.L1BlockRef, baseCfg eth.SystemConfig) error + // Notify L1 finalized head so plasma finality is always behind L1 + Finalize(ref eth.L1BlockRef) + // Set the engine finalization signal callback + OnFinalizedHeadSignal(f plasma.HeadSignalFn) +} + // DataSourceFactory reads raw transactions from a given block & then filters for // batch submitter transactions. // This is not a stage in the pipeline, but a wrapper for another stage in the pipeline type DataSourceFactory struct { - log log.Logger - dsCfg DataSourceConfig - fetcher L1TransactionFetcher - blobsFetcher L1BlobsFetcher - ecotoneTime *uint64 + log log.Logger + dsCfg DataSourceConfig + fetcher L1Fetcher + blobsFetcher L1BlobsFetcher + plasmaFetcher PlasmaInputFetcher + ecotoneTime *uint64 + daClient eigenda.IEigenDA + prefixDerivationEnabled bool } -func NewDataSourceFactory(log log.Logger, cfg *rollup.Config, fetcher L1TransactionFetcher, blobsFetcher L1BlobsFetcher) *DataSourceFactory { +func NewDataSourceFactory(log log.Logger, cfg *rollup.Config, fetcher L1Fetcher, blobsFetcher L1BlobsFetcher, plasmaFetcher PlasmaInputFetcher, daCfg *eigenda.Config, prefixDerivationEnabled bool) *DataSourceFactory { config := DataSourceConfig{ l1Signer: cfg.L1Signer(), batchInboxAddress: cfg.BatchInboxAddress, + plasmaEnabled: cfg.UsePlasma, + } + + var daClient eigenda.IEigenDA + if daCfg != nil { + daClient = &eigenda.EigenDA{ + Log: log, + Config: *daCfg, + } + } + + return &DataSourceFactory{ + log: log, + dsCfg: config, + fetcher: fetcher, + blobsFetcher: blobsFetcher, + plasmaFetcher: plasmaFetcher, + ecotoneTime: cfg.EcotoneTime, + daClient: daClient, + prefixDerivationEnabled: prefixDerivationEnabled, } - return &DataSourceFactory{log: log, dsCfg: config, fetcher: fetcher, blobsFetcher: blobsFetcher, ecotoneTime: cfg.EcotoneTime} } // OpenData returns the appropriate data source for the L1 block `ref`. func (ds *DataSourceFactory) OpenData(ctx context.Context, ref eth.L1BlockRef, batcherAddr common.Address) (DataIter, error) { + // Creates a data iterator from blob or calldata source so we can forward it to the plasma source + // if enabled as it still requires an L1 data source for fetching input commmitments. + var src DataIter if ds.ecotoneTime != nil && ref.Time >= *ds.ecotoneTime { if ds.blobsFetcher == nil { return nil, fmt.Errorf("ecotone upgrade active but beacon endpoint not configured") } - return NewBlobDataSource(ctx, ds.log, ds.dsCfg, ds.fetcher, ds.blobsFetcher, ref, batcherAddr), nil + src = NewBlobDataSource(ctx, ds.log, ds.dsCfg, ds.fetcher, ds.blobsFetcher, ref, batcherAddr, ds.daClient, ds.prefixDerivationEnabled) + } else { + src = NewCalldataSource(ctx, ds.log, ds.dsCfg, ds.fetcher, ref, batcherAddr, ds.daClient, ds.prefixDerivationEnabled) + } + if ds.dsCfg.plasmaEnabled { + // plasma([calldata | blobdata](l1Ref)) -> data + return NewPlasmaDataSource(ds.log, src, ds.fetcher, ds.plasmaFetcher, ref.ID()), nil } - return NewCalldataSource(ctx, ds.log, ds.dsCfg, ds.fetcher, ref, batcherAddr), nil + return src, nil } // DataSourceConfig regroups the mandatory rollup.Config fields needed for DataFromEVMTransactions. type DataSourceConfig struct { l1Signer types.Signer batchInboxAddress common.Address + plasmaEnabled bool } // isValidBatchTx returns true if: diff --git a/op-node/rollup/derive/ecotone_upgrade_transactions.go b/op-node/rollup/derive/ecotone_upgrade_transactions.go index 2c62ffd38598..7b0d885025af 100644 --- a/op-node/rollup/derive/ecotone_upgrade_transactions.go +++ b/op-node/rollup/derive/ecotone_upgrade_transactions.go @@ -34,7 +34,7 @@ var ( enableEcotoneInput = crypto.Keccak256([]byte("setEcotone()"))[:4] EIP4788From = common.HexToAddress("0x0B799C86a49DEeb90402691F1041aa3AF2d3C875") - eip4788CreationData = common.Hex2Bytes("0x60618060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500") + eip4788CreationData = common.FromHex("0x60618060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500") UpgradeToFuncBytes4 = crypto.Keccak256([]byte(UpgradeToFuncSignature))[:4] l1BlockDeploymentBytecode = common.FromHex("0x608060405234801561001057600080fd5b5061053e806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80638381f58a11610097578063c598591811610066578063c598591814610229578063e591b28214610249578063e81b2c6d14610289578063f82061401461029257600080fd5b80638381f58a146101e35780638b239f73146101f75780639e8c496614610200578063b80777ea1461020957600080fd5b806354fd4d50116100d357806354fd4d50146101335780635cf249691461017c57806364ca23ef1461018557806368d5dca6146101b257600080fd5b8063015d8eb9146100fa57806309bd5a601461010f578063440a5e201461012b575b600080fd5b61010d61010836600461044c565b61029b565b005b61011860025481565b6040519081526020015b60405180910390f35b61010d6103da565b61016f6040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b60405161012291906104be565b61011860015481565b6003546101999067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610122565b6003546101ce9068010000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610122565b6000546101999067ffffffffffffffff1681565b61011860055481565b61011860065481565b6000546101999068010000000000000000900467ffffffffffffffff1681565b6003546101ce906c01000000000000000000000000900463ffffffff1681565b61026473deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610122565b61011860045481565b61011860075481565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4c31426c6f636b3a206f6e6c7920746865206465706f7369746f72206163636f60448201527f756e742063616e20736574204c3120626c6f636b2076616c7565730000000000606482015260840160405180910390fd5b6000805467ffffffffffffffff98891668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116998916999099179890981790975560019490945560029290925560038054919094167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009190911617909255600491909155600555600655565b3373deaddeaddeaddeaddeaddeaddeaddeaddead00011461040357633cc50b456000526004601cfd5b60043560801c60035560143560801c600055602435600155604435600755606435600255608435600455565b803567ffffffffffffffff8116811461044757600080fd5b919050565b600080600080600080600080610100898b03121561046957600080fd5b6104728961042f565b975061048060208a0161042f565b9650604089013595506060890135945061049c60808a0161042f565b979a969950949793969560a0850135955060c08501359460e001359350915050565b600060208083528351808285015260005b818110156104eb578581018301518582016040015282016104cf565b818111156104fd576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201604001939250505056fea164736f6c634300080f000a") @@ -42,7 +42,7 @@ var ( ) func EcotoneNetworkUpgradeTransactions() ([]hexutil.Bytes, error) { - upgradeTxns := make([]hexutil.Bytes, 0, 5) + upgradeTxns := make([]hexutil.Bytes, 0, 6) deployL1BlockTransaction, err := types.NewTx(&types.DepositTx{ SourceHash: deployL1BlockSource.SourceHash(), diff --git a/op-node/rollup/derive/ecotone_upgrade_transactions_test.go b/op-node/rollup/derive/ecotone_upgrade_transactions_test.go index ef8894aecccd..13f8f237bed2 100644 --- a/op-node/rollup/derive/ecotone_upgrade_transactions_test.go +++ b/op-node/rollup/derive/ecotone_upgrade_transactions_test.go @@ -110,9 +110,11 @@ func TestEcotoneNetworkTransactions(t *testing.T) { require.Nil(t, beaconRoots.To()) require.Equal(t, uint64(250_000), beaconRoots.Gas()) require.Equal(t, eip4788CreationData, beaconRoots.Data()) + require.NotEmpty(t, beaconRoots.Data()) } func TestEip4788Params(t *testing.T) { require.Equal(t, EIP4788From, common.HexToAddress("0x0B799C86a49DEeb90402691F1041aa3AF2d3C875")) - require.Equal(t, eip4788CreationData, common.Hex2Bytes("0x60618060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500")) + require.Equal(t, eip4788CreationData, common.FromHex("0x60618060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500")) + require.NotEmpty(t, eip4788CreationData) } diff --git a/op-node/rollup/derive/engine_consolidate_test.go b/op-node/rollup/derive/engine_consolidate_test.go index 43e4c07ac428..f67c331d36f7 100644 --- a/op-node/rollup/derive/engine_consolidate_test.go +++ b/op-node/rollup/derive/engine_consolidate_test.go @@ -195,7 +195,7 @@ func TestAttributesMatch(t *testing.T) { } for _, test := range tests { - err := AttributesMatchBlock(rollupCfg, test.args.attrs, test.args.parentHash, test.args.envelope, testlog.Logger(t, log.LvlInfo)) + err := AttributesMatchBlock(rollupCfg, test.args.attrs, test.args.parentHash, test.args.envelope, testlog.Logger(t, log.LevelInfo)) if test.shouldMatch { require.NoError(t, err) } else { @@ -366,7 +366,7 @@ func TestGetMissingTxnHashes(t *testing.T) { for _, test := range tests { missingSafeHashes, missingUnsafeHashes, err := getMissingTxnHashes( - testlog.Logger(t, log.LvlError), + testlog.Logger(t, log.LevelError), test.safeTransactions, test.unsafeTransactions, ) diff --git a/op-node/rollup/derive/engine_controller.go b/op-node/rollup/derive/engine_controller.go index 8ffb1f872b85..d9103fcd5cbc 100644 --- a/op-node/rollup/derive/engine_controller.go +++ b/op-node/rollup/derive/engine_controller.go @@ -38,7 +38,7 @@ var _ EngineControl = (*EngineController)(nil) var _ LocalEngineControl = (*EngineController)(nil) type ExecEngine interface { - GetPayload(ctx context.Context, payloadId eth.PayloadID) (*eth.ExecutionPayloadEnvelope, error) + GetPayload(ctx context.Context, payloadInfo eth.PayloadInfo) (*eth.ExecutionPayloadEnvelope, error) ForkchoiceUpdate(ctx context.Context, state *eth.ForkchoiceState, attr *eth.PayloadAttributes) (*eth.ForkchoiceUpdatedResult, error) NewPayload(ctx context.Context, payload *eth.ExecutionPayload, parentBeaconBlockRoot *common.Hash) (*eth.PayloadStatusV1, error) L2BlockRefByLabel(ctx context.Context, label eth.BlockLabel) (eth.L2BlockRef, error) @@ -55,15 +55,22 @@ type EngineController struct { clock clock.Clock // Block Head State - unsafeHead eth.L2BlockRef - pendingSafeHead eth.L2BlockRef // L2 block processed from the middle of a span batch, but not marked as the safe block yet. - safeHead eth.L2BlockRef - finalizedHead eth.L2BlockRef - needFCUCall bool + unsafeHead eth.L2BlockRef + pendingSafeHead eth.L2BlockRef // L2 block processed from the middle of a span batch, but not marked as the safe block yet. + safeHead eth.L2BlockRef + finalizedHead eth.L2BlockRef + backupUnsafeHead eth.L2BlockRef + needFCUCall bool + // Track when the rollup node changes the forkchoice to restore previous + // known unsafe chain. e.g. Unsafe Reorg caused by Invalid span batch. + // This update does not retry except engine returns non-input error + // because engine may forgot backupUnsafeHead or backupUnsafeHead is not part + // of the chain. + needFCUCallForBackupUnsafeReorg bool // Building State buildingOnto eth.L2BlockRef - buildingID eth.PayloadID + buildingInfo eth.PayloadInfo buildingSafe bool safeAttrs *AttributesWithParent } @@ -103,8 +110,12 @@ func (e *EngineController) Finalized() eth.L2BlockRef { return e.finalizedHead } +func (e *EngineController) BackupUnsafeL2Head() eth.L2BlockRef { + return e.backupUnsafeHead +} + func (e *EngineController) BuildingPayload() (eth.L2BlockRef, eth.PayloadID, bool) { - return e.buildingOnto, e.buildingID, e.buildingSafe + return e.buildingOnto, e.buildingInfo.ID, e.buildingSafe } func (e *EngineController) IsEngineSyncing() bool { @@ -140,14 +151,21 @@ func (e *EngineController) SetUnsafeHead(r eth.L2BlockRef) { e.needFCUCall = true } +// SetBackupUnsafeL2Head implements LocalEngineControl. +func (e *EngineController) SetBackupUnsafeL2Head(r eth.L2BlockRef, triggerReorg bool) { + e.metrics.RecordL2Ref("l2_backup_unsafe", r) + e.backupUnsafeHead = r + e.needFCUCallForBackupUnsafeReorg = triggerReorg +} + // Engine Methods func (e *EngineController) StartPayload(ctx context.Context, parent eth.L2BlockRef, attrs *AttributesWithParent, updateSafe bool) (errType BlockInsertionErrType, err error) { if e.IsEngineSyncing() { return BlockInsertTemporaryErr, fmt.Errorf("engine is in progess of p2p sync") } - if e.buildingID != (eth.PayloadID{}) { - e.log.Warn("did not finish previous block building, starting new building now", "prev_onto", e.buildingOnto, "prev_payload_id", e.buildingID, "new_onto", parent) + if e.buildingInfo != (eth.PayloadInfo{}) { + e.log.Warn("did not finish previous block building, starting new building now", "prev_onto", e.buildingOnto, "prev_payload_id", e.buildingInfo.ID, "new_onto", parent) // TODO(8841): maybe worth it to force-cancel the old payload ID here. } fc := eth.ForkchoiceState{ @@ -161,7 +179,7 @@ func (e *EngineController) StartPayload(ctx context.Context, parent eth.L2BlockR return errTyp, err } - e.buildingID = id + e.buildingInfo = eth.PayloadInfo{ID: id, Timestamp: uint64(attrs.attributes.Timestamp)} e.buildingSafe = updateSafe e.buildingOnto = parent if updateSafe { @@ -172,10 +190,16 @@ func (e *EngineController) StartPayload(ctx context.Context, parent eth.L2BlockR } func (e *EngineController) ConfirmPayload(ctx context.Context, agossip async.AsyncGossiper, sequencerConductor conductor.SequencerConductor) (out *eth.ExecutionPayloadEnvelope, errTyp BlockInsertionErrType, err error) { - if e.buildingID == (eth.PayloadID{}) { + // don't create a BlockInsertPrestateErr if we have a cached gossip payload + if e.buildingInfo == (eth.PayloadInfo{}) && agossip.Get() == nil { return nil, BlockInsertPrestateErr, fmt.Errorf("cannot complete payload building: not currently building a payload") } - if e.buildingOnto.Hash != e.unsafeHead.Hash { // E.g. when safe-attributes consolidation fails, it will drop the existing work. + if p := agossip.Get(); p != nil && e.buildingOnto == (eth.L2BlockRef{}) { + e.log.Warn("Found reusable payload from async gossiper, and no block was being built. Reusing payload.", + "hash", p.ExecutionPayload.BlockHash, + "number", uint64(p.ExecutionPayload.BlockNumber), + "parent", p.ExecutionPayload.ParentHash) + } else if e.buildingOnto.Hash != e.unsafeHead.Hash { // E.g. when safe-attributes consolidation fails, it will drop the existing work. e.log.Warn("engine is building block that reorgs previous unsafe head", "onto", e.buildingOnto, "unsafe", e.unsafeHead) } fc := eth.ForkchoiceState{ @@ -185,15 +209,18 @@ func (e *EngineController) ConfirmPayload(ctx context.Context, agossip async.Asy } // Update the safe head if the payload is built with the last attributes in the batch. updateSafe := e.buildingSafe && e.safeAttrs != nil && e.safeAttrs.isLastInSpan - envelope, errTyp, err := confirmPayload(ctx, e.log, e.engine, fc, e.buildingID, updateSafe, agossip, sequencerConductor) + envelope, errTyp, err := confirmPayload(ctx, e.log, e.engine, fc, e.buildingInfo, updateSafe, agossip, sequencerConductor) if err != nil { - return nil, errTyp, fmt.Errorf("failed to complete building on top of L2 chain %s, id: %s, error (%d): %w", e.buildingOnto, e.buildingID, errTyp, err) + return nil, errTyp, fmt.Errorf("failed to complete building on top of L2 chain %s, id: %s, error (%d): %w", e.buildingOnto, e.buildingInfo.ID, errTyp, err) } ref, err := PayloadToBlockRef(e.rollupCfg, envelope.ExecutionPayload) if err != nil { return nil, BlockInsertPayloadErr, NewResetError(fmt.Errorf("failed to decode L2 block ref from payload: %w", err)) } - + // Backup unsafeHead when new block is not built on original unsafe head. + if e.unsafeHead.Number >= ref.Number { + e.SetBackupUnsafeL2Head(e.unsafeHead, false) + } e.unsafeHead = ref e.metrics.RecordL2Ref("l2_unsafe", ref) @@ -203,6 +230,8 @@ func (e *EngineController) ConfirmPayload(ctx context.Context, agossip async.Asy if updateSafe { e.safeHead = ref e.metrics.RecordL2Ref("l2_safe", ref) + // Remove backupUnsafeHead because this backup will be never used after consolidation. + e.SetBackupUnsafeL2Head(eth.L2BlockRef{}, false) } } @@ -211,14 +240,14 @@ func (e *EngineController) ConfirmPayload(ctx context.Context, agossip async.Asy } func (e *EngineController) CancelPayload(ctx context.Context, force bool) error { - if e.buildingID == (eth.PayloadID{}) { // only cancel if there is something to cancel. + if e.buildingInfo == (eth.PayloadInfo{}) { // only cancel if there is something to cancel. return nil } // the building job gets wrapped up as soon as the payload is retrieved, there's no explicit cancel in the Engine API - e.log.Error("cancelling old block sealing job", "payload", e.buildingID) - _, err := e.engine.GetPayload(ctx, e.buildingID) + e.log.Error("cancelling old block sealing job", "payload", e.buildingInfo.ID) + _, err := e.engine.GetPayload(ctx, e.buildingInfo) if err != nil { - e.log.Error("failed to cancel block building job", "payload", e.buildingID, "err", err) + e.log.Error("failed to cancel block building job", "payload", e.buildingInfo.ID, "err", err) if !force { return err } @@ -228,7 +257,7 @@ func (e *EngineController) CancelPayload(ctx context.Context, force bool) error } func (e *EngineController) resetBuildingState() { - e.buildingID = eth.PayloadID{} + e.buildingInfo = eth.PayloadInfo{} e.buildingOnto = eth.L2BlockRef{} e.buildingSafe = false e.safeAttrs = nil @@ -269,7 +298,7 @@ func (e *EngineController) TryUpdateEngine(ctx context.Context) error { return errNoFCUNeeded } if e.IsEngineSyncing() { - e.log.Warn("Attempting to update forkchoice state while engine is P2P syncing") + e.log.Warn("Attempting to update forkchoice state while EL syncing") } fc := eth.ForkchoiceState{ HeadBlockHash: e.unsafeHead.Hash, @@ -298,7 +327,8 @@ func (e *EngineController) InsertUnsafePayload(ctx context.Context, envelope *et // Check if there is a finalized head once when doing EL sync. If so, transition to CL sync if e.syncStatus == syncStatusWillStartEL { b, err := e.engine.L2BlockRefByLabel(ctx, eth.Finalized) - if errors.Is(err, ethereum.NotFound) { + isTransitionBlock := e.rollupCfg.Genesis.L2.Number != 0 && b.Hash == e.rollupCfg.Genesis.L2.Hash + if errors.Is(err, ethereum.NotFound) || isTransitionBlock { e.syncStatus = syncStatusStartedEL e.log.Info("Starting EL sync") e.elStart = e.clock.Now() @@ -356,13 +386,81 @@ func (e *EngineController) InsertUnsafePayload(ctx context.Context, envelope *et e.needFCUCall = false if e.syncStatus == syncStatusFinishedELButNotFinalized { - e.log.Info("Finished EL sync", "sync_duration", e.clock.Since(e.elStart)) + e.log.Info("Finished EL sync", "sync_duration", e.clock.Since(e.elStart), "finalized_block", ref.ID().String()) e.syncStatus = syncStatusFinishedEL } return nil } +// shouldTryBackupUnsafeReorg checks reorging(restoring) unsafe head to backupUnsafeHead is needed. +// Returns boolean which decides to trigger FCU. +func (e *EngineController) shouldTryBackupUnsafeReorg() bool { + if !e.needFCUCallForBackupUnsafeReorg { + return false + } + // This method must be never called when EL sync. If EL sync is in progress, early return. + if e.IsEngineSyncing() { + e.log.Warn("Attempting to unsafe reorg using backupUnsafe while EL syncing") + return false + } + if e.BackupUnsafeL2Head() == (eth.L2BlockRef{}) { // sanity check backupUnsafeHead is there + e.log.Warn("Attempting to unsafe reorg using backupUnsafe even though it is empty") + e.SetBackupUnsafeL2Head(eth.L2BlockRef{}, false) + return false + } + return true +} + +// TryBackupUnsafeReorg attempts to reorg(restore) unsafe head to backupUnsafeHead. +// If succeeds, update current forkchoice state to the rollup node. +func (e *EngineController) TryBackupUnsafeReorg(ctx context.Context) (bool, error) { + if !e.shouldTryBackupUnsafeReorg() { + // Do not need to perform FCU. + return false, nil + } + // Only try FCU once because execution engine may forgot backupUnsafeHead + // or backupUnsafeHead is not part of the chain. + // Exception: Retry when forkChoiceUpdate returns non-input error. + e.needFCUCallForBackupUnsafeReorg = false + // Reorg unsafe chain. Safe/Finalized chain will not be updated. + e.log.Warn("trying to restore unsafe head", "backupUnsafe", e.backupUnsafeHead.ID(), "unsafe", e.unsafeHead.ID()) + fc := eth.ForkchoiceState{ + HeadBlockHash: e.backupUnsafeHead.Hash, + SafeBlockHash: e.safeHead.Hash, + FinalizedBlockHash: e.finalizedHead.Hash, + } + fcRes, err := e.engine.ForkchoiceUpdate(ctx, &fc, nil) + if err != nil { + var inputErr eth.InputError + if errors.As(err, &inputErr) { + e.SetBackupUnsafeL2Head(eth.L2BlockRef{}, false) + switch inputErr.Code { + case eth.InvalidForkchoiceState: + return true, NewResetError(fmt.Errorf("forkchoice update was inconsistent with engine, need reset to resolve: %w", inputErr.Unwrap())) + default: + return true, NewTemporaryError(fmt.Errorf("unexpected error code in forkchoice-updated response: %w", err)) + } + } else { + // Retry when forkChoiceUpdate returns non-input error. + // Do not reset backupUnsafeHead because it will be used again. + e.needFCUCallForBackupUnsafeReorg = true + return true, NewTemporaryError(fmt.Errorf("failed to sync forkchoice with engine: %w", err)) + } + } + if fcRes.PayloadStatus.Status == eth.ExecutionValid { + // Execution engine accepted the reorg. + e.log.Info("successfully reorged unsafe head using backupUnsafe", "unsafe", e.backupUnsafeHead.ID()) + e.SetUnsafeHead(e.BackupUnsafeL2Head()) + e.SetBackupUnsafeL2Head(eth.L2BlockRef{}, false) + return true, nil + } + e.SetBackupUnsafeL2Head(eth.L2BlockRef{}, false) + // Execution engine could not reorg back to previous unsafe head. + return true, NewTemporaryError(fmt.Errorf("cannot restore unsafe chain using backupUnsafe: err: %w", + eth.ForkchoiceUpdateErr(fcRes.PayloadStatus))) +} + // ResetBuildingState implements LocalEngineControl. func (e *EngineController) ResetBuildingState() { e.resetBuildingState() diff --git a/op-node/rollup/derive/engine_queue.go b/op-node/rollup/derive/engine_queue.go index 206cdd3a7d1c..4dd4bebec49a 100644 --- a/op-node/rollup/derive/engine_queue.go +++ b/op-node/rollup/derive/engine_queue.go @@ -82,14 +82,36 @@ type LocalEngineControl interface { ResetBuildingState() IsEngineSyncing() bool TryUpdateEngine(ctx context.Context) error + TryBackupUnsafeReorg(ctx context.Context) (bool, error) InsertUnsafePayload(ctx context.Context, payload *eth.ExecutionPayloadEnvelope, ref eth.L2BlockRef) error PendingSafeL2Head() eth.L2BlockRef + BackupUnsafeL2Head() eth.L2BlockRef SetUnsafeHead(eth.L2BlockRef) SetSafeHead(eth.L2BlockRef) SetFinalizedHead(eth.L2BlockRef) SetPendingSafeL2Head(eth.L2BlockRef) + SetBackupUnsafeL2Head(block eth.L2BlockRef, triggerReorg bool) +} + +// SafeHeadListener is called when the safe head is updated. +// The safe head may advance by more than one block in a single update +// The l1Block specified is the first L1 block that includes sufficient information to derive the new safe head +type SafeHeadListener interface { + + // Enabled reports if this safe head listener is actively using the posted data. This allows the engine queue to + // optionally skip making calls that may be expensive to prepare. + // Callbacks may still be made if Enabled returns false but are not guaranteed. + Enabled() bool + + // SafeHeadUpdated indicates that the safe head has been updated in response to processing batch data + // The l1Block specified is the first L1 block containing all required batch data to derive newSafeHead + SafeHeadUpdated(newSafeHead eth.L2BlockRef, l1Block eth.BlockID) error + + // SafeHeadReset indicates that the derivation pipeline reset back to the specified safe head + // The L1 block that made the new safe head safe is unknown. + SafeHeadReset(resetSafeHead eth.L2BlockRef) error } // Max memory used for buffering unsafe payloads @@ -114,6 +136,21 @@ const finalityLookback = 4*32 + 1 // We do not want to do this too often, since it requires fetching a L1 block by number, so no cache data. const finalityDelay = 64 +// calcFinalityLookback calculates the default finality lookback based on DA challenge window if plasma +// mode is activated or L1 finality lookback. +func calcFinalityLookback(cfg *rollup.Config) uint64 { + // in plasma mode the longest finality lookback is a commitment is challenged on the last block of + // the challenge window in which case it will be both challenge + resolve window. + if cfg.UsePlasma { + lkb := cfg.DAChallengeWindow + cfg.DAResolveWindow + 1 + // in the case only if the plasma windows are longer than the default finality lookback + if lkb > finalityLookback { + return lkb + } + } + return finalityLookback +} + type FinalityData struct { // The last L2 block that was fully derived and inserted into the L2 engine while processing this L1 block. L2Block eth.L2BlockRef @@ -153,21 +190,25 @@ type EngineQueue struct { l1Fetcher L1Fetcher syncCfg *sync.Config + + safeHeadNotifs SafeHeadListener // notified when safe head is updated + lastNotifiedSafeHead eth.L2BlockRef } // NewEngineQueue creates a new EngineQueue, which should be Reset(origin) before use. -func NewEngineQueue(log log.Logger, cfg *rollup.Config, l2Source L2Source, engine LocalEngineControl, metrics Metrics, prev NextAttributesProvider, l1Fetcher L1Fetcher, syncCfg *sync.Config) *EngineQueue { +func NewEngineQueue(log log.Logger, cfg *rollup.Config, l2Source L2Source, engine LocalEngineControl, metrics Metrics, prev NextAttributesProvider, l1Fetcher L1Fetcher, syncCfg *sync.Config, safeHeadNotifs SafeHeadListener) *EngineQueue { return &EngineQueue{ log: log, cfg: cfg, ec: engine, engine: l2Source, metrics: metrics, - finalityData: make([]FinalityData, 0, finalityLookback), - unsafePayloads: NewPayloadsQueue(maxUnsafePayloadsMemory, payloadMemSize), + finalityData: make([]FinalityData, 0, calcFinalityLookback(cfg)), + unsafePayloads: NewPayloadsQueue(log, maxUnsafePayloadsMemory, payloadMemSize), prev: prev, l1Fetcher: l1Fetcher, syncCfg: syncCfg, + safeHeadNotifs: safeHeadNotifs, } } @@ -196,8 +237,9 @@ func (eq *EngineQueue) AddUnsafePayload(envelope *eth.ExecutionPayloadEnvelope) } func (eq *EngineQueue) Finalize(l1Origin eth.L1BlockRef) { + prevFinalizedL1 := eq.finalizedL1 if l1Origin.Number < eq.finalizedL1.Number { - eq.log.Error("ignoring old L1 finalized block signal! Is the L1 provider corrupted?", "prev_finalized_l1", eq.finalizedL1, "signaled_finalized_l1", l1Origin) + eq.log.Error("ignoring old L1 finalized block signal! Is the L1 provider corrupted?", "prev_finalized_l1", prevFinalizedL1, "signaled_finalized_l1", l1Origin) return } @@ -216,7 +258,7 @@ func (eq *EngineQueue) Finalize(l1Origin eth.L1BlockRef) { } } - eq.log.Info("received L1 finality signal, but missing data for immediate L2 finalization", "prev_finalized_l1", eq.finalizedL1, "signaled_finalized_l1", l1Origin) + eq.log.Info("received L1 finality signal, but missing data for immediate L2 finalization", "prev_finalized_l1", prevFinalizedL1, "signaled_finalized_l1", l1Origin) } // FinalizedL1 identifies the L1 chain (incl.) that included and/or produced all the finalized L2 blocks. @@ -238,12 +280,22 @@ func (eq *EngineQueue) LowestQueuedUnsafeBlock() eth.L2BlockRef { return ref } +func (eq *EngineQueue) BackupUnsafeL2Head() eth.L2BlockRef { + return eq.ec.BackupUnsafeL2Head() +} + // Determine if the engine is syncing to the target block func (eq *EngineQueue) isEngineSyncing() bool { return eq.ec.IsEngineSyncing() } func (eq *EngineQueue) Step(ctx context.Context) error { + // If we don't need to call FCU to restore unsafeHead using backupUnsafe, keep going b/c + // this was a no-op(except correcting invalid state when backupUnsafe is empty but TryBackupUnsafeReorg called). + if fcuCalled, err := eq.ec.TryBackupUnsafeReorg(ctx); fcuCalled { + // If we needed to perform a network call, then we should yield even if we did not encounter an error. + return err + } // If we don't need to call FCU, keep going b/c this was a no-op. If we needed to // perform a network call, then we should yield even if we did not encounter an error. if err := eq.ec.TryUpdateEngine(ctx); !errors.Is(err, errNoFCUNeeded) { @@ -271,7 +323,10 @@ func (eq *EngineQueue) Step(ctx context.Context) error { return err } eq.origin = newOrigin - eq.postProcessSafeL2() // make sure we track the last L2 safe head for every new L1 block + // make sure we track the last L2 safe head for every new L1 block + if err := eq.postProcessSafeL2(); err != nil { + return err + } // try to finalize the L2 blocks we have synced so far (no-op if L1 finality is behind) if err := eq.tryFinalizePastL2Blocks(ctx); err != nil { return err @@ -379,10 +434,13 @@ func (eq *EngineQueue) tryFinalizeL2() { // postProcessSafeL2 buffers the L1 block the safe head was fully derived from, // to finalize it once the L1 block, or later, finalizes. -func (eq *EngineQueue) postProcessSafeL2() { +func (eq *EngineQueue) postProcessSafeL2() error { + if err := eq.notifyNewSafeHead(eq.ec.SafeL2Head()); err != nil { + return err + } // prune finality data if necessary - if len(eq.finalityData) >= finalityLookback { - eq.finalityData = append(eq.finalityData[:0], eq.finalityData[1:finalityLookback]...) + if uint64(len(eq.finalityData)) >= calcFinalityLookback(eq.cfg) { + eq.finalityData = append(eq.finalityData[:0], eq.finalityData[1:calcFinalityLookback(eq.cfg)]...) } // remember the last L2 block that we fully derived from the given finality data if len(eq.finalityData) == 0 || eq.finalityData[len(eq.finalityData)-1].L1Block.Number < eq.origin.Number { @@ -401,6 +459,23 @@ func (eq *EngineQueue) postProcessSafeL2() { eq.log.Debug("updated finality-data", "last_l1", last.L1Block, "last_l2", last.L2Block) } } + return nil +} + +// notifyNewSafeHead calls the safe head listener with the current safe head and l1 origin information. +func (eq *EngineQueue) notifyNewSafeHead(safeHead eth.L2BlockRef) error { + if eq.lastNotifiedSafeHead == safeHead { + // No change, no need to notify + return nil + } + if err := eq.safeHeadNotifs.SafeHeadUpdated(safeHead, eq.origin.ID()); err != nil { + // At this point our state is in a potentially inconsistent state as we've updated the safe head + // in the execution client but failed to post process it. Reset the pipeline so the safe head rolls back + // a little (it always rolls back at least 1 block) and then it will retry storing the entry + return NewResetError(fmt.Errorf("safe head notifications failed: %w", err)) + } + eq.lastNotifiedSafeHead = safeHead + return nil } func (eq *EngineQueue) logSyncProgress(reason string) { @@ -410,6 +485,7 @@ func (eq *EngineQueue) logSyncProgress(reason string) { "l2_safe", eq.ec.SafeL2Head(), "l2_pending_safe", eq.ec.PendingSafeL2Head(), "l2_unsafe", eq.ec.UnsafeL2Head(), + "l2_backup_unsafe", eq.ec.BackupUnsafeL2Head(), "l2_time", eq.ec.UnsafeL2Head().Time, "l1_derived", eq.origin, ) @@ -431,7 +507,7 @@ func (eq *EngineQueue) tryNextUnsafePayload(ctx context.Context) error { } // Ensure that the unsafe payload builds upon the current unsafe head - if eq.syncCfg.SyncMode != sync.ELSync && first.ParentHash != eq.ec.UnsafeL2Head().Hash { + if first.ParentHash != eq.ec.UnsafeL2Head().Hash { if uint64(first.BlockNumber) == eq.ec.UnsafeL2Head().Number+1 { eq.log.Info("skipping unsafe payload, since it does not build onto the existing unsafe chain", "safe", eq.ec.SafeL2Head().ID(), "unsafe", first.ID(), "payload", first.ID()) eq.unsafePayloads.Pop() @@ -520,7 +596,9 @@ func (eq *EngineQueue) consolidateNextSafeAttributes(ctx context.Context) error eq.ec.SetPendingSafeL2Head(ref) if eq.safeAttributes.isLastInSpan { eq.ec.SetSafeHead(ref) - eq.postProcessSafeL2() + if err := eq.postProcessSafeL2(); err != nil { + return err + } } // unsafe head stays the same, we did not reorg the chain. eq.safeAttributes = nil @@ -572,8 +650,11 @@ func (eq *EngineQueue) forceNextSafeAttributes(ctx context.Context) error { // suppress the error b/c we want to retry with the next batch from the batch queue // If there is no valid batch the node will eventually force a deposit only block. If // the deposit only block fails, this will return the critical error above. - return nil + // Try to restore to previous known unsafe chain. + eq.ec.SetBackupUnsafeL2Head(eq.ec.BackupUnsafeL2Head(), true) + + return nil default: return NewCriticalError(fmt.Errorf("unknown InsertHeadBlock error type %d: %w", errType, err)) } @@ -581,7 +662,9 @@ func (eq *EngineQueue) forceNextSafeAttributes(ctx context.Context) error { eq.safeAttributes = nil eq.logSyncProgress("processed safe block derived from L1") if lastInSpan { - eq.postProcessSafeL2() + if err := eq.postProcessSafeL2(); err != nil { + return err + } } return nil @@ -649,6 +732,7 @@ func (eq *EngineQueue) Reset(ctx context.Context, _ eth.L1BlockRef, _ eth.System eq.ec.SetSafeHead(safe) eq.ec.SetPendingSafeL2Head(safe) eq.ec.SetFinalizedHead(finalized) + eq.ec.SetBackupUnsafeL2Head(eth.L2BlockRef{}, false) eq.safeAttributes = nil eq.ec.ResetBuildingState() eq.finalityData = eq.finalityData[:0] @@ -656,6 +740,24 @@ func (eq *EngineQueue) Reset(ctx context.Context, _ eth.L1BlockRef, _ eth.System // note: we do not clear the unsafe payloads queue; if the payloads are not applicable anymore the parent hash checks will clear out the old payloads. eq.origin = pipelineOrigin eq.sysCfg = l1Cfg + eq.lastNotifiedSafeHead = safe + if err := eq.safeHeadNotifs.SafeHeadReset(safe); err != nil { + return err + } + if eq.safeHeadNotifs.Enabled() && safe.Number == eq.cfg.Genesis.L2.Number && safe.Hash == eq.cfg.Genesis.L2.Hash { + // The rollup genesis block is always safe by definition. So if the pipeline resets this far back we know + // we will process all safe head updates and can record genesis as always safe from L1 genesis. + // Note that it is not safe to use cfg.Genesis.L1 here as it is the block immediately before the L2 genesis + // but the contracts may have been deployed earlier than that, allowing creating a dispute game + // with a L1 head prior to cfg.Genesis.L1 + l1Genesis, err := eq.l1Fetcher.L1BlockRefByNumber(ctx, 0) + if err != nil { + return fmt.Errorf("failed to retrieve L1 genesis: %w", err) + } + if err := eq.safeHeadNotifs.SafeHeadUpdated(safe, l1Genesis.ID()); err != nil { + return err + } + } eq.logSyncProgress("reset derivation work") return io.EOF } diff --git a/op-node/rollup/derive/engine_queue_test.go b/op-node/rollup/derive/engine_queue_test.go index 0a0090cded5e..190e86140efb 100644 --- a/op-node/rollup/derive/engine_queue_test.go +++ b/op-node/rollup/derive/engine_queue_test.go @@ -8,6 +8,7 @@ import ( "math/rand" "testing" + "github.com/ethereum-optimism/optimism/op-node/node/safedb" "github.com/holiman/uint256" "github.com/stretchr/testify/require" @@ -44,7 +45,7 @@ func (f *fakeAttributesQueue) NextAttributes(_ context.Context, safeHead eth.L2B var _ NextAttributesProvider = (*fakeAttributesQueue)(nil) func TestEngineQueue_Finalize(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) rng := rand.New(rand.NewSource(1234)) @@ -251,7 +252,7 @@ func TestEngineQueue_Finalize(t *testing.T) { prev := &fakeAttributesQueue{} ec := NewEngineController(eng, logger, metrics, &rollup.Config{}, sync.CLSync) - eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}) + eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}, safedb.Disabled) require.ErrorIs(t, eq.Reset(context.Background(), eth.L1BlockRef{}, eth.SystemConfig{}), io.EOF) require.Equal(t, refB1, ec.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") @@ -262,13 +263,13 @@ func TestEngineQueue_Finalize(t *testing.T) { eq.origin = refD prev.origin = refD eq.ec.SetSafeHead(refC1) - eq.postProcessSafeL2() + require.NoError(t, eq.postProcessSafeL2()) // now say D0 was included in E and became the new safe head eq.origin = refE prev.origin = refE eq.ec.SetSafeHead(refD0) - eq.postProcessSafeL2() + require.NoError(t, eq.postProcessSafeL2()) // let's finalize D (current L1), from which we fully derived C1 (it was safe head), but not D0 (included in E) eq.Finalize(refD) @@ -280,7 +281,7 @@ func TestEngineQueue_Finalize(t *testing.T) { } func TestEngineQueue_ResetWhenUnsafeOriginNotCanonical(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) rng := rand.New(rand.NewSource(1234)) @@ -487,7 +488,7 @@ func TestEngineQueue_ResetWhenUnsafeOriginNotCanonical(t *testing.T) { prev := &fakeAttributesQueue{origin: refE} ec := NewEngineController(eng, logger, metrics, &rollup.Config{}, sync.CLSync) - eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}) + eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}, safedb.Disabled) require.ErrorIs(t, eq.Reset(context.Background(), eth.L1BlockRef{}, eth.SystemConfig{}), io.EOF) require.Equal(t, refB1, ec.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") @@ -520,7 +521,7 @@ func TestEngineQueue_ResetWhenUnsafeOriginNotCanonical(t *testing.T) { } func TestVerifyNewL1Origin(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) rng := rand.New(rand.NewSource(1234)) @@ -817,7 +818,7 @@ func TestVerifyNewL1Origin(t *testing.T) { prev := &fakeAttributesQueue{origin: refE} ec := NewEngineController(eng, logger, metrics, &rollup.Config{}, sync.CLSync) - eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}) + eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}, safedb.Disabled) require.ErrorIs(t, eq.Reset(context.Background(), eth.L1BlockRef{}, eth.SystemConfig{}), io.EOF) require.Equal(t, refB1, ec.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") @@ -851,7 +852,7 @@ func TestVerifyNewL1Origin(t *testing.T) { } func TestBlockBuildingRace(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) eng := &testutils.MockEngine{} rng := rand.New(rand.NewSource(1234)) @@ -914,7 +915,7 @@ func TestBlockBuildingRace(t *testing.T) { prev := &fakeAttributesQueue{origin: refA, attrs: attrs, islastInSpan: true} ec := NewEngineController(eng, logger, metrics, &rollup.Config{}, sync.CLSync) - eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}) + eq := NewEngineQueue(logger, cfg, eng, ec, metrics, prev, l1F, &sync.Config{}, safedb.Disabled) require.ErrorIs(t, eq.Reset(context.Background(), eth.L1BlockRef{}, eth.SystemConfig{}), io.EOF) id := eth.PayloadID{0xff} @@ -975,7 +976,7 @@ func TestBlockBuildingRace(t *testing.T) { GasUsed: 0, Timestamp: eth.Uint64Quantity(refA1.Time), ExtraData: nil, - BaseFeePerGas: *uint256.NewInt(7), + BaseFeePerGas: eth.Uint256Quantity(*uint256.NewInt(7)), BlockHash: refA1.Hash, Transactions: []eth.Data{ a1InfoTx, @@ -1016,7 +1017,7 @@ func TestBlockBuildingRace(t *testing.T) { } func TestResetLoop(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) eng := &testutils.MockEngine{} l1F := &testutils.MockL1Source{} @@ -1086,7 +1087,7 @@ func TestResetLoop(t *testing.T) { prev := &fakeAttributesQueue{origin: refA, attrs: attrs, islastInSpan: true} ec := NewEngineController(eng, logger, metrics.NoopMetrics, &rollup.Config{}, sync.CLSync) - eq := NewEngineQueue(logger, cfg, eng, ec, metrics.NoopMetrics, prev, l1F, &sync.Config{}) + eq := NewEngineQueue(logger, cfg, eng, ec, metrics.NoopMetrics, prev, l1F, &sync.Config{}, safedb.Disabled) eq.ec.SetUnsafeHead(refA2) eq.ec.SetSafeHead(refA1) eq.ec.SetFinalizedHead(refA0) @@ -1124,7 +1125,7 @@ func TestResetLoop(t *testing.T) { } func TestEngineQueue_StepPopOlderUnsafe(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LevelInfo) eng := &testutils.MockEngine{} l1F := &testutils.MockL1Source{} @@ -1184,7 +1185,7 @@ func TestEngineQueue_StepPopOlderUnsafe(t *testing.T) { GasUsed: 0, Timestamp: eth.Uint64Quantity(refA1.Time), ExtraData: nil, - BaseFeePerGas: *uint256.NewInt(7), + BaseFeePerGas: eth.Uint256Quantity(*uint256.NewInt(7)), BlockHash: refA1.Hash, Transactions: []eth.Data{}, }} @@ -1192,7 +1193,7 @@ func TestEngineQueue_StepPopOlderUnsafe(t *testing.T) { prev := &fakeAttributesQueue{origin: refA} ec := NewEngineController(eng, logger, metrics.NoopMetrics, &rollup.Config{}, sync.CLSync) - eq := NewEngineQueue(logger, cfg, eng, ec, metrics.NoopMetrics, prev, l1F, &sync.Config{}) + eq := NewEngineQueue(logger, cfg, eng, ec, metrics.NoopMetrics, prev, l1F, &sync.Config{}, safedb.Disabled) eq.ec.SetUnsafeHead(refA2) eq.ec.SetSafeHead(refA0) eq.ec.SetFinalizedHead(refA0) @@ -1217,3 +1218,99 @@ func TestEngineQueue_StepPopOlderUnsafe(t *testing.T) { l1F.AssertExpectations(t) eng.AssertExpectations(t) } + +func TestPlasmaFinalityData(t *testing.T) { + logger := testlog.Logger(t, log.LevelInfo) + eng := &testutils.MockEngine{} + l1F := &testutils.MockL1Source{} + + rng := rand.New(rand.NewSource(1234)) + + refA := testutils.RandomBlockRef(rng) + refA0 := eth.L2BlockRef{ + Hash: testutils.RandomHash(rng), + Number: 0, + ParentHash: common.Hash{}, + Time: refA.Time, + L1Origin: refA.ID(), + SequenceNumber: 0, + } + + prev := &fakeAttributesQueue{origin: refA} + + cfg := &rollup.Config{ + Genesis: rollup.Genesis{ + L1: refA.ID(), + L2: refA0.ID(), + L2Time: refA0.Time, + SystemConfig: eth.SystemConfig{ + BatcherAddr: common.Address{42}, + Overhead: [32]byte{123}, + Scalar: [32]byte{42}, + GasLimit: 20_000_000, + }, + }, + BlockTime: 1, + SeqWindowSize: 2, + UsePlasma: false, + DAChallengeWindow: 90, + DAResolveWindow: 90, + } + // shoud return l1 finality if plasma is not enabled + require.Equal(t, uint64(finalityLookback), calcFinalityLookback(cfg)) + + cfg.UsePlasma = true + expFinalityLookback := 181 + require.Equal(t, uint64(expFinalityLookback), calcFinalityLookback(cfg)) + + refA1 := eth.L2BlockRef{ + Hash: testutils.RandomHash(rng), + Number: refA0.Number + 1, + ParentHash: refA0.Hash, + Time: refA0.Time + cfg.BlockTime, + L1Origin: refA.ID(), + SequenceNumber: 1, + } + + ec := NewEngineController(eng, logger, metrics.NoopMetrics, &rollup.Config{}, sync.CLSync) + + eq := NewEngineQueue(logger, cfg, eng, ec, metrics.NoopMetrics, prev, l1F, &sync.Config{}, safedb.Disabled) + require.Equal(t, expFinalityLookback, cap(eq.finalityData)) + + l1parent := refA + l2parent := refA1 + + ec.SetSafeHead(l2parent) + require.NoError(t, eq.postProcessSafeL2()) + + // advance over 200 l1 origins each time incrementing new l2 safe heads + // and post processing. + for i := uint64(0); i < 200; i++ { + require.NoError(t, eq.postProcessSafeL2()) + + l1parent = eth.L1BlockRef{ + Hash: testutils.RandomHash(rng), + Number: l1parent.Number + 1, + ParentHash: l1parent.Hash, + Time: l1parent.Time + 12, + } + eq.origin = l1parent + + for j := uint64(0); i < cfg.SeqWindowSize; i++ { + l2parent = eth.L2BlockRef{ + Hash: testutils.RandomHash(rng), + Number: l2parent.Number + 1, + ParentHash: l2parent.Hash, + Time: l2parent.Time + cfg.BlockTime, + L1Origin: l1parent.ID(), + SequenceNumber: j, + } + ec.SetSafeHead(l2parent) + require.NoError(t, eq.postProcessSafeL2()) + } + } + + // finality data does not go over challenge + resolve windows + 1 capacity + // (prunes down to 180 then adds the extra 1 each time) + require.Equal(t, expFinalityLookback, len(eq.finalityData)) +} diff --git a/op-node/rollup/derive/engine_update.go b/op-node/rollup/derive/engine_update.go index 5408ef495ec3..b23a27004004 100644 --- a/op-node/rollup/derive/engine_update.go +++ b/op-node/rollup/derive/engine_update.go @@ -124,7 +124,7 @@ func confirmPayload( log log.Logger, eng ExecEngine, fc eth.ForkchoiceState, - id eth.PayloadID, + payloadInfo eth.PayloadInfo, updateSafe bool, agossip async.AsyncGossiper, sequencerConductor conductor.SequencerConductor, @@ -140,7 +140,7 @@ func confirmPayload( "parent", envelope.ExecutionPayload.ParentHash, "txs", len(envelope.ExecutionPayload.Transactions)) } else { - envelope, err = eng.GetPayload(ctx, id) + envelope, err = eng.GetPayload(ctx, payloadInfo) } 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. diff --git a/op-node/rollup/derive/l1_retrieval_test.go b/op-node/rollup/derive/l1_retrieval_test.go index 33538ad9296a..8851957b43a1 100644 --- a/op-node/rollup/derive/l1_retrieval_test.go +++ b/op-node/rollup/derive/l1_retrieval_test.go @@ -92,7 +92,7 @@ func TestL1RetrievalReset(t *testing.T) { dataSrc.ExpectOpenData(a, &fakeDataIter{}, l1Cfg.BatcherAddr) defer dataSrc.AssertExpectations(t) - l1r := NewL1Retrieval(testlog.Logger(t, log.LvlError), dataSrc, nil) + l1r := NewL1Retrieval(testlog.Logger(t, log.LevelError), dataSrc, nil) // We assert that it opens up the correct data on a reset _ = l1r.Reset(context.Background(), a, l1Cfg) @@ -149,7 +149,7 @@ func TestL1RetrievalNextData(t *testing.T) { dataSrc := &MockDataSource{} dataSrc.ExpectOpenData(test.prevBlock, &fakeDataIter{data: test.datas, errs: test.datasErrs}, test.sysCfg.BatcherAddr) - ret := NewL1Retrieval(testlog.Logger(t, log.LvlCrit), dataSrc, l1t) + ret := NewL1Retrieval(testlog.Logger(t, log.LevelCrit), dataSrc, l1t) // If prevErr != nil we forced an error while getting data from the previous stage if test.openErr != nil { diff --git a/op-node/rollup/derive/l1_traversal_test.go b/op-node/rollup/derive/l1_traversal_test.go index 544b10e58cf8..1826562c789a 100644 --- a/op-node/rollup/derive/l1_traversal_test.go +++ b/op-node/rollup/derive/l1_traversal_test.go @@ -36,7 +36,7 @@ func TestL1TraversalNext(t *testing.T) { Genesis: rollup.Genesis{SystemConfig: l1Cfg}, L1SystemConfigAddress: sysCfgAddr, } - tr := NewL1Traversal(testlog.Logger(t, log.LvlError), cfg, nil) + tr := NewL1Traversal(testlog.Logger(t, log.LevelError), cfg, nil) _ = tr.Reset(context.Background(), a, l1Cfg) @@ -132,7 +132,7 @@ func TestL1TraversalAdvance(t *testing.T) { Genesis: rollup.Genesis{SystemConfig: test.initialL1Cfg}, L1SystemConfigAddress: sysCfgAddr, } - tr := NewL1Traversal(testlog.Logger(t, log.LvlError), cfg, src) + tr := NewL1Traversal(testlog.Logger(t, log.LevelError), cfg, src) // Load up the initial state with a reset _ = tr.Reset(context.Background(), test.startBlock, test.initialL1Cfg) diff --git a/op-node/rollup/derive/params.go b/op-node/rollup/derive/params.go index bba78cc2dfee..35ac8667e83c 100644 --- a/op-node/rollup/derive/params.go +++ b/op-node/rollup/derive/params.go @@ -4,6 +4,8 @@ import ( "encoding/hex" "errors" "fmt" + + plasma "github.com/ethereum-optimism/optimism/op-plasma" ) // count the tagging info as 200 in terms of buffer size. @@ -19,6 +21,9 @@ func frameSize(frame Frame) uint64 { const DerivationVersion0 = 0 +// DerivationVersion1 is reserved for batcher transactions containing plasma commitments. +const DerivationVersion1 = plasma.TxDataVersion1 + // MaxSpanBatchSize is the maximum amount of bytes that will be needed // to decode every span batch field. This value cannot be larger than // MaxRLPBytesPerChannel because single batch cannot be larger than channel size. diff --git a/op-node/rollup/derive/payloads_queue.go b/op-node/rollup/derive/payloads_queue.go index 2ae59e4a262b..2ac554fb6d43 100644 --- a/op-node/rollup/derive/payloads_queue.go +++ b/op-node/rollup/derive/payloads_queue.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -81,15 +82,17 @@ type PayloadsQueue struct { MaxSize uint64 blockHashes map[common.Hash]struct{} SizeFn func(p *eth.ExecutionPayloadEnvelope) uint64 + log log.Logger } -func NewPayloadsQueue(maxSize uint64, sizeFn func(p *eth.ExecutionPayloadEnvelope) uint64) *PayloadsQueue { +func NewPayloadsQueue(log log.Logger, maxSize uint64, sizeFn func(p *eth.ExecutionPayloadEnvelope) uint64) *PayloadsQueue { return &PayloadsQueue{ pq: nil, currentSize: 0, MaxSize: maxSize, blockHashes: make(map[common.Hash]struct{}), SizeFn: sizeFn, + log: log, } } @@ -125,7 +128,8 @@ func (upq *PayloadsQueue) Push(e *eth.ExecutionPayloadEnvelope) error { }) upq.currentSize += size for upq.currentSize > upq.MaxSize { - upq.Pop() + env := upq.Pop() + upq.log.Info("Dropping payload from payload queue because the payload queue is too large", "id", env.ExecutionPayload.ID()) } upq.blockHashes[e.ExecutionPayload.BlockHash] = struct{}{} return nil diff --git a/op-node/rollup/derive/payloads_queue_test.go b/op-node/rollup/derive/payloads_queue_test.go index 1ba93279ece0..c5accbdeab11 100644 --- a/op-node/rollup/derive/payloads_queue_test.go +++ b/op-node/rollup/derive/payloads_queue_test.go @@ -5,9 +5,11 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/testlog" ) func TestPayloadsByNumber(t *testing.T) { @@ -81,7 +83,7 @@ func envelope(payload *eth.ExecutionPayload) *eth.ExecutionPayloadEnvelope { } func TestPayloadsQueue(t *testing.T) { - pq := NewPayloadsQueue(payloadMemFixedCost*3, payloadMemSize) + pq := NewPayloadsQueue(testlog.Logger(t, log.LvlInfo), payloadMemFixedCost*3, payloadMemSize) require.Equal(t, 0, pq.Len()) require.Nil(t, pq.Peek()) require.Nil(t, pq.Pop()) diff --git a/op-node/rollup/derive/pipeline.go b/op-node/rollup/derive/pipeline.go index 295b93757e8c..90c5c7998390 100644 --- a/op-node/rollup/derive/pipeline.go +++ b/op-node/rollup/derive/pipeline.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/eigenda" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -53,6 +54,7 @@ type DerivationPipeline struct { log log.Logger rollupCfg *rollup.Config l1Fetcher L1Fetcher + plasma PlasmaInputFetcher // Index of the stage that is currently being reset. // >= len(stages) if no additional resetting is required @@ -68,11 +70,11 @@ type DerivationPipeline struct { // NewDerivationPipeline creates a derivation pipeline, which should be reset before use. -func NewDerivationPipeline(log log.Logger, rollupCfg *rollup.Config, l1Fetcher L1Fetcher, l1Blobs L1BlobsFetcher, l2Source L2Source, engine LocalEngineControl, metrics Metrics, syncCfg *sync.Config) *DerivationPipeline { +func NewDerivationPipeline(log log.Logger, rollupCfg *rollup.Config, l1Fetcher L1Fetcher, l1Blobs L1BlobsFetcher, plasma PlasmaInputFetcher, l2Source L2Source, engine LocalEngineControl, metrics Metrics, syncCfg *sync.Config, safeHeadListener SafeHeadListener, daCfg *eigenda.Config, prefixDerivationEnabled bool) *DerivationPipeline { // Pull stages l1Traversal := NewL1Traversal(log, rollupCfg, l1Fetcher) - dataSrc := NewDataSourceFactory(log, rollupCfg, l1Fetcher, l1Blobs) // auxiliary stage for L1Retrieval + dataSrc := NewDataSourceFactory(log, rollupCfg, l1Fetcher, l1Blobs, plasma, daCfg, prefixDerivationEnabled) // auxiliary stage for L1Retrieval l1Src := NewL1Retrieval(log, dataSrc, l1Traversal) frameQueue := NewFrameQueue(log, l1Src) bank := NewChannelBank(log, rollupCfg, frameQueue, l1Fetcher, metrics) @@ -82,17 +84,23 @@ func NewDerivationPipeline(log log.Logger, rollupCfg *rollup.Config, l1Fetcher L attributesQueue := NewAttributesQueue(log, rollupCfg, attrBuilder, batchQueue) // Step stages - eng := NewEngineQueue(log, rollupCfg, l2Source, engine, metrics, attributesQueue, l1Fetcher, syncCfg) + eng := NewEngineQueue(log, rollupCfg, l2Source, engine, metrics, attributesQueue, l1Fetcher, syncCfg, safeHeadListener) + + // Plasma takes control of the engine finalization signal only when usePlasma is enabled. + plasma.OnFinalizedHeadSignal(func(ref eth.L1BlockRef) { + eng.Finalize(ref) + }) // 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 := []ResettableStage{eng, l1Traversal, l1Src, frameQueue, bank, chInReader, batchQueue, attributesQueue} + stages := []ResettableStage{eng, l1Traversal, l1Src, plasma, frameQueue, bank, chInReader, batchQueue, attributesQueue} return &DerivationPipeline{ log: log, rollupCfg: rollupCfg, l1Fetcher: l1Fetcher, + plasma: plasma, resetting: 0, stages: stages, eng: eng, @@ -118,7 +126,13 @@ func (dp *DerivationPipeline) Origin() eth.L1BlockRef { } func (dp *DerivationPipeline) Finalize(l1Origin eth.L1BlockRef) { - dp.eng.Finalize(l1Origin) + // In plasma mode, the finalization signal is proxied through the plasma manager. + // Finality signal will come from the DA contract or L1 finality whichever is last. + if dp.rollupCfg.UsePlasma { + dp.plasma.Finalize(l1Origin) + } else { + dp.eng.Finalize(l1Origin) + } } // FinalizedL1 is the L1 finalization of the inner-most stage of the derivation pipeline, @@ -139,7 +153,7 @@ func (dp *DerivationPipeline) LowestQueuedUnsafeBlock() eth.L2BlockRef { } // Step tries to progress the buffer. -// An EOF is returned if there pipeline is blocked by waiting for new L1 data. +// An EOF is returned if the pipeline is blocked by waiting for new L1 data. // If ctx errors no error is returned, but the step may exit early in a state that can still be continued. // Any other error is critical and the derivation pipeline should be reset. // An error is expected when the underlying source closes. diff --git a/op-node/rollup/derive/plasma_data_source.go b/op-node/rollup/derive/plasma_data_source.go new file mode 100644 index 000000000000..e6b9ad7dbfe1 --- /dev/null +++ b/op-node/rollup/derive/plasma_data_source.go @@ -0,0 +1,102 @@ +package derive + +import ( + "context" + "errors" + "fmt" + + plasma "github.com/ethereum-optimism/optimism/op-plasma" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum/go-ethereum/log" +) + +// PlasmaDataSource is a data source that fetches inputs from a plasma DA provider given +// their onchain commitments. Same as CalldataSource it will keep attempting to fetch. +type PlasmaDataSource struct { + log log.Logger + src DataIter + fetcher PlasmaInputFetcher + l1 L1Fetcher + id eth.BlockID + // keep track of a pending commitment so we can keep trying to fetch the input. + comm plasma.Keccak256Commitment +} + +func NewPlasmaDataSource(log log.Logger, src DataIter, l1 L1Fetcher, fetcher PlasmaInputFetcher, id eth.BlockID) *PlasmaDataSource { + return &PlasmaDataSource{ + log: log, + src: src, + fetcher: fetcher, + l1: l1, + id: id, + } +} + +func (s *PlasmaDataSource) Next(ctx context.Context) (eth.Data, error) { + // Process origin syncs the challenge contract events and updates the local challenge states + // before we can proceed to fetch the input data. This function can be called multiple times + // for the same origin and noop if the origin was already processed. It is also called if + // there is not commitment in the current origin. + if err := s.fetcher.AdvanceL1Origin(ctx, s.l1, s.id); err != nil { + if errors.Is(err, plasma.ErrReorgRequired) { + return nil, NewResetError(fmt.Errorf("new expired challenge")) + } + return nil, NewTemporaryError(fmt.Errorf("failed to advance plasma L1 origin: %w", err)) + } + + if s.comm == nil { + // the l1 source returns the input commitment for the batch. + data, err := s.src.Next(ctx) + if err != nil { + return nil, err + } + + if len(data) == 0 { + return nil, NotEnoughData + } + // If the tx data type is not plasma, we forward it downstream to let the next + // steps validate and potentially parse it as L1 DA inputs. + if data[0] != plasma.TxDataVersion1 { + return data, nil + } + + // validate batcher inbox data is a commitment. + comm, err := plasma.DecodeKeccak256(data[1:]) + if err != nil { + s.log.Warn("invalid commitment", "commitment", data, "err", err) + return s.Next(ctx) + } + s.comm = comm + } + // use the commitment to fetch the input from the plasma DA provider. + data, err := s.fetcher.GetInput(ctx, s.l1, s.comm, s.id) + // GetInput may call for a reorg if the pipeline is stalled and the plasma DA manager + // continued syncing origins detached from the pipeline origin. + if errors.Is(err, plasma.ErrReorgRequired) { + // challenge for a new previously derived commitment expired. + return nil, NewResetError(err) + } else if errors.Is(err, plasma.ErrExpiredChallenge) { + // this commitment was challenged and the challenge expired. + s.log.Warn("challenge expired, skipping batch", "comm", s.comm) + s.comm = nil + // skip the input + return s.Next(ctx) + } else if errors.Is(err, plasma.ErrMissingPastWindow) { + return nil, NewCriticalError(fmt.Errorf("data for comm %x not available: %w", s.comm, err)) + } else if errors.Is(err, plasma.ErrPendingChallenge) { + // continue stepping without slowing down. + return nil, NotEnoughData + } else if err != nil { + // return temporary error so we can keep retrying. + return nil, NewTemporaryError(fmt.Errorf("failed to fetch input data with comm %x from da service: %w", s.comm, err)) + } + // inputs are limited to a max size to ensure they can be challenged in the DA contract. + if len(data) > plasma.MaxInputSize { + s.log.Warn("input data exceeds max size", "size", len(data), "max", plasma.MaxInputSize) + s.comm = nil + return s.Next(ctx) + } + // reset the commitment so we can fetch the next one from the source at the next iteration. + s.comm = nil + return data, nil +} diff --git a/op-node/rollup/derive/plasma_data_source_test.go b/op-node/rollup/derive/plasma_data_source_test.go new file mode 100644 index 000000000000..fa15aa400151 --- /dev/null +++ b/op-node/rollup/derive/plasma_data_source_test.go @@ -0,0 +1,523 @@ +package derive + +import ( + "context" + "io" + "math/big" + "math/rand" + "testing" + + "github.com/ethereum-optimism/optimism/op-node/rollup" + plasma "github.com/ethereum-optimism/optimism/op-plasma" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/testutils" + "github.com/ethereum/go-ethereum" + "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/log" + "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +type MockFinalitySignal struct { + mock.Mock +} + +func (m *MockFinalitySignal) OnFinalized(blockRef eth.L1BlockRef) { + m.MethodCalled("OnFinalized", blockRef) +} + +func (m *MockFinalitySignal) ExpectFinalized(blockRef eth.L1BlockRef) { + m.On("OnFinalized", blockRef).Once() +} + +// TestPlasmaDataSource verifies that commitments are correctly read from l1 and then +// forwarded to the Plasma DA to return the correct inputs in the iterator. +// First it generates some L1 refs containing a random number of commitments, challenges +// the first 4 commitments then generates enough blocks to expire the challenge. +// Then it simulates rederiving while verifying it does skip the expired input until the next +// challenge expires. +func TestPlasmaDataSource(t *testing.T) { + logger := testlog.Logger(t, log.LevelDebug) + ctx := context.Background() + + rng := rand.New(rand.NewSource(1234)) + + l1F := &testutils.MockL1Source{} + + storage := plasma.NewMockDAClient(logger) + + pcfg := plasma.Config{ + ChallengeWindow: 90, ResolveWindow: 90, + } + metrics := &plasma.NoopMetrics{} + + daState := plasma.NewState(logger, metrics) + + da := plasma.NewPlasmaDAWithState(logger, pcfg, storage, metrics, daState) + + finalitySignal := &MockFinalitySignal{} + da.OnFinalizedHeadSignal(finalitySignal.OnFinalized) + + // Create rollup genesis and config + l1Time := uint64(2) + refA := testutils.RandomBlockRef(rng) + refA.Number = 1 + l1Refs := []eth.L1BlockRef{refA} + refA0 := eth.L2BlockRef{ + Hash: testutils.RandomHash(rng), + Number: 0, + ParentHash: common.Hash{}, + Time: refA.Time, + L1Origin: refA.ID(), + SequenceNumber: 0, + } + batcherPriv := testutils.RandomKey() + batcherAddr := crypto.PubkeyToAddress(batcherPriv.PublicKey) + batcherInbox := common.Address{42} + cfg := &rollup.Config{ + Genesis: rollup.Genesis{ + L1: refA.ID(), + L2: refA0.ID(), + L2Time: refA0.Time, + }, + BlockTime: 1, + SeqWindowSize: 20, + BatchInboxAddress: batcherInbox, + UsePlasma: true, + } + // keep track of random input data to validate against + var inputs [][]byte + var comms []plasma.Keccak256Commitment + + signer := cfg.L1Signer() + + factory := NewDataSourceFactory(logger, cfg, l1F, nil, da, nil, false) + + nc := 0 + firstChallengeExpirationBlock := uint64(95) + + for i := uint64(0); i <= pcfg.ChallengeWindow+pcfg.ResolveWindow; i++ { + parent := l1Refs[len(l1Refs)-1] + // create a new mock l1 ref + ref := eth.L1BlockRef{ + Hash: testutils.RandomHash(rng), + Number: parent.Number + 1, + ParentHash: parent.Hash, + Time: parent.Time + l1Time, + } + l1Refs = append(l1Refs, ref) + logger.Info("new l1 block", "ref", ref) + // called for each l1 block to sync challenges + l1F.ExpectFetchReceipts(ref.Hash, nil, types.Receipts{}, nil) + + // pick a random number of commitments to include in the l1 block + c := rng.Intn(4) + var txs []*types.Transaction + + for j := 0; j < c; j++ { + // mock input commitments in l1 transactions + input := testutils.RandomData(rng, 2000) + comm, _ := storage.SetInput(ctx, input) + inputs = append(inputs, input) + comms = append(comms, comm) + + tx, err := types.SignNewTx(batcherPriv, signer, &types.DynamicFeeTx{ + ChainID: signer.ChainID(), + Nonce: 0, + GasTipCap: big.NewInt(2 * params.GWei), + GasFeeCap: big.NewInt(30 * params.GWei), + Gas: 100_000, + To: &batcherInbox, + Value: big.NewInt(int64(0)), + Data: comm.TxData(), + }) + require.NoError(t, err) + + txs = append(txs, tx) + + } + logger.Info("included commitments", "count", c) + l1F.ExpectInfoAndTxsByHash(ref.Hash, testutils.RandomBlockInfo(rng), txs, nil) + // called once per derivation + l1F.ExpectInfoAndTxsByHash(ref.Hash, testutils.RandomBlockInfo(rng), txs, nil) + + if ref.Number == 2 { + l1F.ExpectL1BlockRefByNumber(ref.Number, ref, nil) + finalitySignal.ExpectFinalized(ref) + } + + // challenge the first 4 commitments as soon as we have collected them all + if len(comms) >= 4 && nc < 7 { + // skip a block between each challenge transaction + if nc%2 == 0 { + daState.SetActiveChallenge(comms[nc/2].Encode(), ref.Number, pcfg.ResolveWindow) + logger.Info("setting active challenge", "comm", comms[nc/2]) + } + nc++ + } + + // create a new data source for each block + src, err := factory.OpenData(ctx, ref, batcherAddr) + require.NoError(t, err) + + // first challenge expires + if i == firstChallengeExpirationBlock { + _, err := src.Next(ctx) + require.ErrorIs(t, err, ErrReset) + break + } + + for j := 0; j < c; j++ { + data, err := src.Next(ctx) + // check that each commitment is resolved + require.NoError(t, err) + require.Equal(t, hexutil.Bytes(inputs[len(inputs)-(c-j)]), data) + } + // returns EOF once done + _, err = src.Next(ctx) + require.ErrorIs(t, err, io.EOF) + } + + logger.Info("pipeline reset ..................................") + + // start at 1 since first input should be skipped + nc = 1 + secondChallengeExpirationBlock := 98 + + for i := 1; i <= len(l1Refs)+2; i++ { + + var ref eth.L1BlockRef + // first we run through all the existing l1 blocks + if i < len(l1Refs) { + ref = l1Refs[i] + logger.Info("re deriving block", "ref", ref, "i", i) + + if i == len(l1Refs)-1 { + l1F.ExpectFetchReceipts(ref.Hash, nil, types.Receipts{}, nil) + } + // once past the l1 head, continue generating new l1 refs + } else { + parent := l1Refs[len(l1Refs)-1] + // create a new mock l1 ref + ref = eth.L1BlockRef{ + Hash: testutils.RandomHash(rng), + Number: parent.Number + 1, + ParentHash: parent.Hash, + Time: parent.Time + l1Time, + } + l1Refs = append(l1Refs, ref) + logger.Info("new l1 block", "ref", ref) + // called for each l1 block to sync challenges + l1F.ExpectFetchReceipts(ref.Hash, nil, types.Receipts{}, nil) + + // pick a random number of commitments to include in the l1 block + c := rng.Intn(4) + var txs []*types.Transaction + + for j := 0; j < c; j++ { + // mock input commitments in l1 transactions + input := testutils.RandomData(rng, 2000) + comm, _ := storage.SetInput(ctx, input) + inputs = append(inputs, input) + comms = append(comms, comm) + + tx, err := types.SignNewTx(batcherPriv, signer, &types.DynamicFeeTx{ + ChainID: signer.ChainID(), + Nonce: 0, + GasTipCap: big.NewInt(2 * params.GWei), + GasFeeCap: big.NewInt(30 * params.GWei), + Gas: 100_000, + To: &batcherInbox, + Value: big.NewInt(int64(0)), + Data: comm.TxData(), + }) + require.NoError(t, err) + + txs = append(txs, tx) + + } + logger.Info("included commitments", "count", c) + l1F.ExpectInfoAndTxsByHash(ref.Hash, testutils.RandomBlockInfo(rng), txs, nil) + } + + // create a new data source for each block + src, err := factory.OpenData(ctx, ref, batcherAddr) + require.NoError(t, err) + + // next challenge expires + if i == secondChallengeExpirationBlock { + _, err := src.Next(ctx) + require.ErrorIs(t, err, ErrReset) + break + } + + for data, err := src.Next(ctx); err != io.EOF; data, err = src.Next(ctx) { + logger.Info("yielding data") + // check that each commitment is resolved + require.NoError(t, err) + require.Equal(t, hexutil.Bytes(inputs[nc]), data) + + nc++ + } + + } + + // trigger l1 finalization signal + da.Finalize(l1Refs[len(l1Refs)-32]) + + finalitySignal.AssertExpectations(t) + l1F.AssertExpectations(t) +} + +// This tests makes sure the pipeline returns a temporary error if data is not found. +func TestPlasmaDataSourceStall(t *testing.T) { + logger := testlog.Logger(t, log.LevelDebug) + ctx := context.Background() + + rng := rand.New(rand.NewSource(1234)) + + l1F := &testutils.MockL1Source{} + + storage := plasma.NewMockDAClient(logger) + + pcfg := plasma.Config{ + ChallengeWindow: 90, ResolveWindow: 90, + } + + metrics := &plasma.NoopMetrics{} + + daState := plasma.NewState(logger, metrics) + + da := plasma.NewPlasmaDAWithState(logger, pcfg, storage, metrics, daState) + + finalitySignal := &MockFinalitySignal{} + da.OnFinalizedHeadSignal(finalitySignal.OnFinalized) + + // Create rollup genesis and config + l1Time := uint64(2) + refA := testutils.RandomBlockRef(rng) + refA.Number = 1 + l1Refs := []eth.L1BlockRef{refA} + refA0 := eth.L2BlockRef{ + Hash: testutils.RandomHash(rng), + Number: 0, + ParentHash: common.Hash{}, + Time: refA.Time, + L1Origin: refA.ID(), + SequenceNumber: 0, + } + batcherPriv := testutils.RandomKey() + batcherAddr := crypto.PubkeyToAddress(batcherPriv.PublicKey) + batcherInbox := common.Address{42} + cfg := &rollup.Config{ + Genesis: rollup.Genesis{ + L1: refA.ID(), + L2: refA0.ID(), + L2Time: refA0.Time, + }, + BlockTime: 1, + SeqWindowSize: 20, + BatchInboxAddress: batcherInbox, + UsePlasma: true, + } + + signer := cfg.L1Signer() + + factory := NewDataSourceFactory(logger, cfg, l1F, nil, da, nil, false) + + parent := l1Refs[0] + // create a new mock l1 ref + ref := eth.L1BlockRef{ + Hash: testutils.RandomHash(rng), + Number: parent.Number + 1, + ParentHash: parent.Hash, + Time: parent.Time + l1Time, + } + l1F.ExpectFetchReceipts(ref.Hash, nil, types.Receipts{}, nil) + // mock input commitments in l1 transactions + input := testutils.RandomData(rng, 2000) + comm, _ := storage.SetInput(ctx, input) + + tx, err := types.SignNewTx(batcherPriv, signer, &types.DynamicFeeTx{ + ChainID: signer.ChainID(), + Nonce: 0, + GasTipCap: big.NewInt(2 * params.GWei), + GasFeeCap: big.NewInt(30 * params.GWei), + Gas: 100_000, + To: &batcherInbox, + Value: big.NewInt(int64(0)), + Data: comm.TxData(), + }) + require.NoError(t, err) + + txs := []*types.Transaction{tx} + + l1F.ExpectInfoAndTxsByHash(ref.Hash, testutils.RandomBlockInfo(rng), txs, nil) + + // delete the input from the DA provider so it returns not found + require.NoError(t, storage.DeleteData(comm.Encode())) + + // next block is fetched to look ahead challenges but is not yet available + l1F.ExpectL1BlockRefByNumber(ref.Number+1, eth.L1BlockRef{}, ethereum.NotFound) + + src, err := factory.OpenData(ctx, ref, batcherAddr) + require.NoError(t, err) + + // data is not found so we return a temporary error + _, err = src.Next(ctx) + require.ErrorIs(t, err, ErrTemporary) + + // next block is available with no challenge events + nextRef := eth.L1BlockRef{ + Number: ref.Number + 1, + Hash: testutils.RandomHash(rng), + } + l1F.ExpectL1BlockRefByNumber(nextRef.Number, nextRef, nil) + l1F.ExpectFetchReceipts(nextRef.Hash, nil, types.Receipts{}, nil) + + // not enough data + _, err = src.Next(ctx) + require.ErrorIs(t, err, NotEnoughData) + + // now challenge is resolved + daState.SetResolvedChallenge(comm.Encode(), input, ref.Number+2) + + // derivation can resume + data, err := src.Next(ctx) + require.NoError(t, err) + require.Equal(t, hexutil.Bytes(input), data) + + l1F.AssertExpectations(t) +} + +// TestPlasmaDataSourceInvalidData tests that the pipeline skips invalid data and continues +// this includes invalid commitments and oversized inputs. +func TestPlasmaDataSourceInvalidData(t *testing.T) { + logger := testlog.Logger(t, log.LevelDebug) + ctx := context.Background() + + rng := rand.New(rand.NewSource(1234)) + + l1F := &testutils.MockL1Source{} + + storage := plasma.NewMockDAClient(logger) + + pcfg := plasma.Config{ + ChallengeWindow: 90, ResolveWindow: 90, + } + + da := plasma.NewPlasmaDAWithStorage(logger, pcfg, storage, &plasma.NoopMetrics{}) + + // Create rollup genesis and config + l1Time := uint64(2) + refA := testutils.RandomBlockRef(rng) + refA.Number = 1 + l1Refs := []eth.L1BlockRef{refA} + refA0 := eth.L2BlockRef{ + Hash: testutils.RandomHash(rng), + Number: 0, + ParentHash: common.Hash{}, + Time: refA.Time, + L1Origin: refA.ID(), + SequenceNumber: 0, + } + batcherPriv := testutils.RandomKey() + batcherAddr := crypto.PubkeyToAddress(batcherPriv.PublicKey) + batcherInbox := common.Address{42} + cfg := &rollup.Config{ + Genesis: rollup.Genesis{ + L1: refA.ID(), + L2: refA0.ID(), + L2Time: refA0.Time, + }, + BlockTime: 1, + SeqWindowSize: 20, + BatchInboxAddress: batcherInbox, + UsePlasma: true, + } + + signer := cfg.L1Signer() + + factory := NewDataSourceFactory(logger, cfg, l1F, nil, da, nil, false) + + parent := l1Refs[0] + // create a new mock l1 ref + ref := eth.L1BlockRef{ + Hash: testutils.RandomHash(rng), + Number: parent.Number + 1, + ParentHash: parent.Hash, + Time: parent.Time + l1Time, + } + l1F.ExpectFetchReceipts(ref.Hash, nil, types.Receipts{}, nil) + // mock input commitments in l1 transactions with an oversized input + input := testutils.RandomData(rng, plasma.MaxInputSize+1) + comm, _ := storage.SetInput(ctx, input) + + tx1, err := types.SignNewTx(batcherPriv, signer, &types.DynamicFeeTx{ + ChainID: signer.ChainID(), + Nonce: 0, + GasTipCap: big.NewInt(2 * params.GWei), + GasFeeCap: big.NewInt(30 * params.GWei), + Gas: 100_000, + To: &batcherInbox, + Value: big.NewInt(int64(0)), + Data: comm.TxData(), + }) + require.NoError(t, err) + + // valid data + input2 := testutils.RandomData(rng, 2000) + comm2, _ := storage.SetInput(ctx, input2) + tx2, err := types.SignNewTx(batcherPriv, signer, &types.DynamicFeeTx{ + ChainID: signer.ChainID(), + Nonce: 0, + GasTipCap: big.NewInt(2 * params.GWei), + GasFeeCap: big.NewInt(30 * params.GWei), + Gas: 100_000, + To: &batcherInbox, + Value: big.NewInt(int64(0)), + Data: comm2.TxData(), + }) + require.NoError(t, err) + + // regular input instead of commitment + input3 := testutils.RandomData(rng, 32) + tx3, err := types.SignNewTx(batcherPriv, signer, &types.DynamicFeeTx{ + ChainID: signer.ChainID(), + Nonce: 0, + GasTipCap: big.NewInt(2 * params.GWei), + GasFeeCap: big.NewInt(30 * params.GWei), + Gas: 100_000, + To: &batcherInbox, + Value: big.NewInt(int64(0)), + Data: input3, + }) + require.NoError(t, err) + + txs := []*types.Transaction{tx1, tx2, tx3} + + l1F.ExpectInfoAndTxsByHash(ref.Hash, testutils.RandomBlockInfo(rng), txs, nil) + + src, err := factory.OpenData(ctx, ref, batcherAddr) + require.NoError(t, err) + + // oversized input is skipped and returns input2 directly + data, err := src.Next(ctx) + require.NoError(t, err) + require.Equal(t, hexutil.Bytes(input2), data) + + // regular input is passed through + data, err = src.Next(ctx) + require.NoError(t, err) + require.Equal(t, hexutil.Bytes(input3), data) + + _, err = src.Next(ctx) + require.ErrorIs(t, err, io.EOF) + + l1F.AssertExpectations(t) +} diff --git a/op-node/rollup/driver/driver.go b/op-node/rollup/driver/driver.go index f9eaf9a66d15..1b0a57cf7b23 100644 --- a/op-node/rollup/driver/driver.go +++ b/op-node/rollup/driver/driver.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup/conductor" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/eigenda" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -114,14 +115,32 @@ type SequencerStateListener interface { } // 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, l1Blobs derive.L1BlobsFetcher, altSync AltSync, network Network, log log.Logger, snapshotLog log.Logger, metrics Metrics, sequencerStateListener SequencerStateListener, syncCfg *sync.Config, sequencerConductor conductor.SequencerConductor) *Driver { +func NewDriver( + driverCfg *Config, + cfg *rollup.Config, + l2 L2Chain, + l1 L1Chain, + l1Blobs derive.L1BlobsFetcher, + altSync AltSync, + network Network, + log log.Logger, + snapshotLog log.Logger, + metrics Metrics, + sequencerStateListener SequencerStateListener, + safeHeadListener derive.SafeHeadListener, + syncCfg *sync.Config, + sequencerConductor conductor.SequencerConductor, + plasma derive.PlasmaInputFetcher, + daCfg *eigenda.Config, + prefixDerivationEnabled bool, +) *Driver { l1 = NewMeteredL1Fetcher(l1, metrics) l1State := NewL1State(log, metrics) sequencerConfDepth := NewConfDepth(driverCfg.SequencerConfDepth, l1State.L1Head, l1) findL1Origin := NewL1OriginSelector(log, cfg, sequencerConfDepth) verifConfDepth := NewConfDepth(driverCfg.VerifierConfDepth, l1State.L1Head, l1) engine := derive.NewEngineController(l2, log, metrics, cfg, syncCfg.SyncMode) - derivationPipeline := derive.NewDerivationPipeline(log, cfg, verifConfDepth, l1Blobs, l2, engine, metrics, syncCfg) + derivationPipeline := derive.NewDerivationPipeline(log, cfg, verifConfDepth, l1Blobs, plasma, l2, engine, metrics, syncCfg, safeHeadListener, daCfg, prefixDerivationEnabled) attrBuilder := derive.NewFetchingAttributesBuilder(cfg, l1, l2) meteredEngine := NewMeteredEngine(cfg, engine, metrics, log) // Only use the metered engine in the sequencer b/c it records sequencing metrics. sequencer := NewSequencer(log, cfg, meteredEngine, attrBuilder, findL1Origin, metrics) diff --git a/op-node/rollup/driver/origin_selector_test.go b/op-node/rollup/driver/origin_selector_test.go index a4728d04d5db..1ddfb8840ee8 100644 --- a/op-node/rollup/driver/origin_selector_test.go +++ b/op-node/rollup/driver/origin_selector_test.go @@ -21,7 +21,7 @@ import ( // is no conf depth to stop the origin selection so block `b` should // be the next L1 origin func TestOriginSelectorAdvances(t *testing.T) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) cfg := &rollup.Config{ MaxSequencerDrift: 500, BlockTime: 2, @@ -62,7 +62,7 @@ func TestOriginSelectorAdvances(t *testing.T) { // but it should select block `a` because the L2 block time must be ahead // of the the timestamp of it's L1 origin. func TestOriginSelectorRespectsOriginTiming(t *testing.T) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) cfg := &rollup.Config{ MaxSequencerDrift: 500, BlockTime: 2, @@ -102,7 +102,7 @@ func TestOriginSelectorRespectsOriginTiming(t *testing.T) { // as the origin, however block `b` is the L1 Head & the sequencer // needs to wait until that block is confirmed enough before advancing. func TestOriginSelectorRespectsConfDepth(t *testing.T) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) cfg := &rollup.Config{ MaxSequencerDrift: 500, BlockTime: 2, @@ -145,7 +145,7 @@ func TestOriginSelectorRespectsConfDepth(t *testing.T) { // This is because 29 (next L2 time) > 20 (origin) + 8 (seq drift) => invalid block. // We maintain confirmation distance, even though we would shift to the next origin if we could. func TestOriginSelectorStrictConfDepth(t *testing.T) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) cfg := &rollup.Config{ MaxSequencerDrift: 8, BlockTime: 2, @@ -183,7 +183,7 @@ func TestOriginSelectorStrictConfDepth(t *testing.T) { // drift, the origin should remain on block `a` because the next origin's // time is greater than the next L2 time. func TestOriginSelectorSeqDriftRespectsNextOriginTime(t *testing.T) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) cfg := &rollup.Config{ MaxSequencerDrift: 8, BlockTime: 2, @@ -225,7 +225,7 @@ func TestOriginSelectorSeqDriftRespectsNextOriginTime(t *testing.T) { // Due to a conf depth of 2, block `b` is not immediately visible, // and the origin selection should fail until it is visible, by waiting for block `c`. func TestOriginSelectorHandlesLateL1Blocks(t *testing.T) { - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) cfg := &rollup.Config{ MaxSequencerDrift: 8, BlockTime: 2, diff --git a/op-node/rollup/driver/sequencer_test.go b/op-node/rollup/driver/sequencer_test.go index fa3dfed3d73a..6edf0960f08a 100644 --- a/op-node/rollup/driver/sequencer_test.go +++ b/op-node/rollup/driver/sequencer_test.go @@ -171,7 +171,7 @@ func TestSequencerChaosMonkey(t *testing.T) { l1Time := uint64(100000) // mute errors. We expect a lot of the mocked errors to cause error-logs. We check chain health at the end of the test. - log := testlog.Logger(t, log.LvlCrit) + log := testlog.Logger(t, log.LevelCrit) cfg := &rollup.Config{ Genesis: rollup.Genesis{ diff --git a/op-node/rollup/driver/state.go b/op-node/rollup/driver/state.go index 59c7f2a4ae48..c206204e03a0 100644 --- a/op-node/rollup/driver/state.go +++ b/op-node/rollup/driver/state.go @@ -22,6 +22,11 @@ import ( "github.com/ethereum-optimism/optimism/op-service/retry" ) +var ( + ErrSequencerAlreadyStarted = errors.New("sequencer already running") + ErrSequencerAlreadyStopped = errors.New("sequencer not running") +) + // Deprecated: use eth.SyncStatus instead. type SyncStatus = eth.SyncStatus @@ -343,7 +348,7 @@ func (s *Driver) eventLoop() { if err := s.engineController.InsertUnsafePayload(s.driverCtx, envelope, ref); err != nil { s.log.Warn("Failed to insert unsafe payload for EL sync", "id", envelope.ExecutionPayload.ID(), "err", err) } - s.logSyncProgress("unsafe payload from sequencer") + s.logSyncProgress("unsafe payload from sequencer while in EL sync") } case newL1Head := <-s.l1HeadSig: s.l1State.HandleNewL1HeadBlock(newL1Head) @@ -412,7 +417,7 @@ func (s *Driver) eventLoop() { case resp := <-s.startSequencer: unsafeHead := s.engineController.UnsafeL2Head().Hash if !s.driverConfig.SequencerStopped { - resp.err <- errors.New("sequencer already running") + resp.err <- ErrSequencerAlreadyStarted } else if !bytes.Equal(unsafeHead[:], resp.hash[:]) { resp.err <- fmt.Errorf("block hash does not match: head %s, received %s", unsafeHead.String(), resp.hash.String()) } else { @@ -427,7 +432,7 @@ func (s *Driver) eventLoop() { } case respCh := <-s.stopSequencer: if s.driverConfig.SequencerStopped { - respCh <- hashAndError{err: errors.New("sequencer not running")} + respCh <- hashAndError{err: ErrSequencerAlreadyStopped} } else { if err := s.sequencerNotifs.SequencerStopped(); err != nil { respCh <- hashAndError{err: fmt.Errorf("sequencer start notification: %w", err)} diff --git a/op-node/rollup/superchain.go b/op-node/rollup/superchain.go index 703eff774e32..9c8ff2b8cb4a 100644 --- a/op-node/rollup/superchain.go +++ b/op-node/rollup/superchain.go @@ -12,20 +12,22 @@ import ( "github.com/ethereum-optimism/superchain-registry/superchain" ) -var OPStackSupport = params.ProtocolVersionV0{Build: [8]byte{}, Major: 5, Minor: 0, Patch: 0, PreRelease: 1}.Encode() +var OPStackSupport = params.ProtocolVersionV0{Build: [8]byte{}, Major: 6, Minor: 0, Patch: 0, PreRelease: 0}.Encode() const ( - opMainnet = 10 - opGoerli = 420 - opSepolia = 11155420 + opMainnet = 10 + opGoerli = 420 + opSepolia = 11155420 + + labsGoerliDevnet = 997 + labsGoerliChaosnet = 888 + labsSepoliaDevnet0 = 11155421 + baseGoerli = 84531 baseMainnet = 8453 - pgnMainnet = 424 - pgnSepolia = 58008 - zoraGoerli = 999 - zoraMainnet = 7777777 - labsDevnet = 997 - chaosnet = 888 + + pgnMainnet = 424 + pgnSepolia = 58008 ) // LoadOPStackRollupConfig loads the rollup configuration of the requested chain ID from the superchain-registry. @@ -53,10 +55,8 @@ func LoadOPStackRollupConfig(chainID uint64) (*Config, error) { return nil, fmt.Errorf("unable to retrieve genesis SystemConfig of chain %d", chainID) } - var depositContractAddress common.Address - if addrs, ok := superchain.Addresses[chainID]; ok { - depositContractAddress = common.Address(addrs.OptimismPortalProxy) - } else { + addrs, ok := superchain.Addresses[chainID] + if !ok { return nil, fmt.Errorf("unable to retrieve deposit contract address") } @@ -68,9 +68,9 @@ func LoadOPStackRollupConfig(chainID uint64) (*Config, error) { regolithTime = 1683219600 case opGoerli: regolithTime = 1679079600 - case labsDevnet: + case labsGoerliDevnet: regolithTime = 1677984480 - case chaosnet: + case labsGoerliChaosnet: regolithTime = 1692156862 } @@ -98,18 +98,18 @@ func LoadOPStackRollupConfig(chainID uint64) (*Config, error) { L1ChainID: new(big.Int).SetUint64(superChain.Config.L1.ChainID), L2ChainID: new(big.Int).SetUint64(chConfig.ChainID), RegolithTime: ®olithTime, - CanyonTime: superChain.Config.CanyonTime, - DeltaTime: superChain.Config.DeltaTime, - EcotoneTime: superChain.Config.EcotoneTime, - FjordTime: superChain.Config.FjordTime, + CanyonTime: chConfig.CanyonTime, + DeltaTime: chConfig.DeltaTime, + EcotoneTime: chConfig.EcotoneTime, + FjordTime: chConfig.FjordTime, BatchInboxAddress: common.Address(chConfig.BatchInboxAddr), - DepositContractAddress: depositContractAddress, - L1SystemConfigAddress: common.Address(chConfig.SystemConfigAddr), + DepositContractAddress: common.Address(addrs.OptimismPortalProxy), + L1SystemConfigAddress: common.Address(addrs.SystemConfigProxy), } if superChain.Config.ProtocolVersionsAddr != nil { // Set optional protocol versions address cfg.ProtocolVersionsAddress = common.Address(*superChain.Config.ProtocolVersionsAddr) } - if chainID == labsDevnet || chainID == chaosnet { + if chainID == labsGoerliDevnet || chainID == labsGoerliChaosnet { cfg.ChannelTimeout = 120 cfg.MaxSequencerDrift = 1200 } diff --git a/op-node/rollup/sync/start.go b/op-node/rollup/sync/start.go index aed0befd04b0..34d650cec749 100644 --- a/op-node/rollup/sync/start.go +++ b/op-node/rollup/sync/start.go @@ -176,7 +176,7 @@ func FindL2Heads(ctx context.Context, cfg *rollup.Config, l1 L1Chain, l2 L2Chain if result.Unsafe == (eth.L2BlockRef{}) { result.Unsafe = n // Check we are not reorging L2 incredibly deep - if n.L1Origin.Number+(MaxReorgSeqWindows*cfg.SeqWindowSize) < prevUnsafe.L1Origin.Number { + if n.L1Origin.Number+(MaxReorgSeqWindows*cfg.SyncLookback()) < prevUnsafe.L1Origin.Number { // If the reorg depth is too large, something is fishy. // This can legitimately happen if L1 goes down for a while. But in that case, // restarting the L2 node with a bigger configured MaxReorgDepth is an acceptable @@ -195,13 +195,13 @@ func FindL2Heads(ctx context.Context, cfg *rollup.Config, l1 L1Chain, l2 L2Chain highestL2WithCanonicalL1Origin = n } } else { - // L1 origin not ahead of L1 head nor canonical, discard previous candidate and keep looking. + // L1 origin neither ahead of L1 head nor canonical, discard previous candidate and keep looking. result.Unsafe = eth.L2BlockRef{} highestL2WithCanonicalL1Origin = eth.L2BlockRef{} } // If the L2 block is at least as old as the previous safe head, and we have seen at least a full sequence window worth of L1 blocks to confirm - if n.Number <= result.Safe.Number && n.L1Origin.Number+cfg.SeqWindowSize < highestL2WithCanonicalL1Origin.L1Origin.Number && n.SequenceNumber == 0 { + if n.Number <= result.Safe.Number && n.L1Origin.Number+cfg.SyncLookback() < highestL2WithCanonicalL1Origin.L1Origin.Number && n.SequenceNumber == 0 { ready = true } diff --git a/op-node/rollup/sync/start_test.go b/op-node/rollup/sync/start_test.go index 1881b7b61e45..0c202543c5de 100644 --- a/op-node/rollup/sync/start_test.go +++ b/op-node/rollup/sync/start_test.go @@ -23,7 +23,7 @@ var _ L2Chain = (*testutils.FakeChainSource)(nil) // - Both heads are at the tip of their respective chains func (c *syncStartTestCase) generateFakeL2(t *testing.T) (*testutils.FakeChainSource, rollup.Genesis) { t.Helper() - log := testlog.Logger(t, log.LvlError) + log := testlog.Logger(t, log.LevelError) chain := testutils.NewFakeChainSource([]string{c.L1, c.NewL1}, []string{c.L2}, int(c.GenesisL1Num), log) chain.SetL2Head(len(c.L2) - 1) genesis := testutils.FakeGenesis(c.GenesisL1, c.GenesisL2, int(c.GenesisL1Num)) @@ -74,8 +74,7 @@ func (c *syncStartTestCase) Run(t *testing.T) { Genesis: genesis, SeqWindowSize: c.SeqWindowSize, } - lgr := log.New() - lgr.SetHandler(log.DiscardHandler()) + lgr := log.NewLogger(log.DiscardHandler()) result, err := FindL2Heads(context.Background(), cfg, chain, chain, lgr, &Config{}) if c.ExpectedErr != nil { require.ErrorIs(t, err, c.ExpectedErr, "expected error") @@ -108,6 +107,23 @@ func TestFindSyncStart(t *testing.T) { SafeL2Head: 'A', ExpectedErr: nil, }, + { + Name: "already synced with safe head after genesis", + GenesisL1Num: 0, + L1: "abcdefghijkj", + L2: "ABCDEFGHIJKJ", + NewL1: "abcdefghijkj", + PreFinalizedL2: 'B', + PreSafeL2: 'D', + GenesisL1: 'a', + GenesisL2: 'A', + UnsafeL2Head: 'J', + SeqWindowSize: 2, + // Important this steps back at least one safe block so the safedb is sent the latest safe head + // again - we may be resetting because the safedb failed to write the previous entry + SafeL2Head: 'C', + ExpectedErr: nil, + }, { Name: "small reorg long chain", GenesisL1Num: 0, diff --git a/op-node/rollup/types.go b/op-node/rollup/types.go index 3bbe1c768fe6..1ad45272e8aa 100644 --- a/op-node/rollup/types.go +++ b/op-node/rollup/types.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + plasma "github.com/ethereum-optimism/optimism/op-plasma" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -108,8 +109,19 @@ type Config struct { // L1 address that declares the protocol versions, optional (Beta feature) ProtocolVersionsAddress common.Address `json:"protocol_versions_address,omitempty"` - // L1 block timestamp to start reading blobs as batch data-source. Optional. - BlobsEnabledL1Timestamp *uint64 `json:"blobs_data,omitempty"` + // L1 DataAvailabilityChallenge contract proxy address + DAChallengeAddress common.Address `json:"da_challenge_address,omitempty"` + + // DA challenge window value set on the DAC contract. Used in plasma mode + // to compute when a commitment can no longer be challenged. + DAChallengeWindow uint64 `json:"da_challenge_window"` + + // DA resolve window value set on the DAC contract. Used in plasma mode + // to compute when a challenge expires and trigger a reorg if needed. + DAResolveWindow uint64 `json:"da_resolve_window"` + + // UsePlasma is activated when the chain is in plasma mode. + UsePlasma bool `json:"use_plasma"` } // ValidateL1Config checks L1 config variables for errors. @@ -277,6 +289,37 @@ func (cfg *Config) Check() error { if cfg.L2ChainID.Sign() < 1 { return ErrL2ChainIDNotPositive } + + if err := checkFork(cfg.RegolithTime, cfg.CanyonTime, "regolith", "canyon"); err != nil { + return err + } + if err := checkFork(cfg.CanyonTime, cfg.DeltaTime, "canyon", "delta"); err != nil { + return err + } + if err := checkFork(cfg.DeltaTime, cfg.EcotoneTime, "delta", "ecotone"); err != nil { + return err + } + if err := checkFork(cfg.EcotoneTime, cfg.FjordTime, "ecotone", "fjord"); err != nil { + return err + } + + return nil +} + +// checkFork checks that fork A is before or at the same time as fork B +func checkFork(a, b *uint64, aName, bName string) error { + if a == nil && b == nil { + return nil + } + if a == nil && b != nil { + return fmt.Errorf("fork %s set (to %d), but prior fork %s missing", bName, *b, aName) + } + if a != nil && b == nil { + return nil + } + if *a > *b { + return fmt.Errorf("fork %s set to %d, but prior fork %s has higher offset %d", bName, *b, aName, *a) + } return nil } @@ -322,6 +365,75 @@ func (c *Config) IsInterop(timestamp uint64) bool { return c.InteropTime != nil && timestamp >= *c.InteropTime } +// ForkchoiceUpdatedVersion returns the EngineAPIMethod suitable for the chain hard fork version. +func (c *Config) ForkchoiceUpdatedVersion(attr *eth.PayloadAttributes) eth.EngineAPIMethod { + if attr == nil { + // Don't begin payload build process. + return eth.FCUV3 + } + ts := uint64(attr.Timestamp) + if c.IsEcotone(ts) { + // Cancun + return eth.FCUV3 + } else if c.IsCanyon(ts) { + // Shanghai + return eth.FCUV2 + } else { + // According to Ethereum engine API spec, we can use fcuV2 here, + // but upstream Geth v1.13.11 does not accept V2 before Shanghai. + return eth.FCUV1 + } +} + +// NewPayloadVersion returns the EngineAPIMethod suitable for the chain hard fork version. +func (c *Config) NewPayloadVersion(timestamp uint64) eth.EngineAPIMethod { + if c.IsEcotone(timestamp) { + // Cancun + return eth.NewPayloadV3 + } else { + return eth.NewPayloadV2 + } +} + +// GetPayloadVersion returns the EngineAPIMethod suitable for the chain hard fork version. +func (c *Config) GetPayloadVersion(timestamp uint64) eth.EngineAPIMethod { + if c.IsEcotone(timestamp) { + // Cancun + return eth.GetPayloadV3 + } else { + return eth.GetPayloadV2 + } +} + +// PlasmaConfig validates and returns the plasma config from the rollup config. +func (c *Config) PlasmaConfig() (plasma.Config, error) { + if c.DAChallengeAddress == (common.Address{}) { + return plasma.Config{}, fmt.Errorf("missing DAChallengeAddress") + } + if c.DAChallengeWindow == uint64(0) { + return plasma.Config{}, fmt.Errorf("missing DAChallengeWindow") + } + if c.DAResolveWindow == uint64(0) { + return plasma.Config{}, fmt.Errorf("missing DAResolveWindow") + } + return plasma.Config{ + DAChallengeContractAddress: c.DAChallengeAddress, + ChallengeWindow: c.DAChallengeWindow, + ResolveWindow: c.DAResolveWindow, + }, nil +} + +// SyncLookback computes the number of blocks to walk back in order to find the correct L1 origin. +// In plasma mode longest possible window is challenge + resolve windows. +func (c *Config) SyncLookback() uint64 { + if c.UsePlasma { + if win := (c.DAChallengeWindow + c.DAResolveWindow); win > c.SeqWindowSize { + return win + } + } + return c.SeqWindowSize +} + // Description outputs a banner describing the important parts of rollup configuration in a human-readable form. // Optionally provide a mapping of L2 chain IDs to network names to label the L2 chain with if not unknown. // The config should be config.Check()-ed before creating a description. diff --git a/op-node/rollup/types_test.go b/op-node/rollup/types_test.go index d87365cb516d..17343430f262 100644 --- a/op-node/rollup/types_test.go +++ b/op-node/rollup/types_test.go @@ -408,6 +408,54 @@ func TestConfig_Check(t *testing.T) { assert.Same(t, err, test.expectedErr) }) } + + forkTests := []struct { + name string + modifier func(cfg *Config) + expectedErr error + }{ + { + name: "PriorForkMissing", + modifier: func(cfg *Config) { + ecotoneTime := uint64(1) + cfg.EcotoneTime = &ecotoneTime + }, + expectedErr: fmt.Errorf("fork ecotone set (to 1), but prior fork delta missing"), + }, + { + name: "PriorForkHasHigherOffset", + modifier: func(cfg *Config) { + regolithTime := uint64(2) + canyonTime := uint64(1) + cfg.RegolithTime = ®olithTime + cfg.CanyonTime = &canyonTime + }, + expectedErr: fmt.Errorf("fork canyon set to 1, but prior fork regolith has higher offset 2"), + }, + { + name: "PriorForkOK", + modifier: func(cfg *Config) { + regolithTime := uint64(1) + canyonTime := uint64(2) + deltaTime := uint64(3) + ecotoneTime := uint64(4) + cfg.RegolithTime = ®olithTime + cfg.CanyonTime = &canyonTime + cfg.DeltaTime = &deltaTime + cfg.EcotoneTime = &ecotoneTime + }, + expectedErr: nil, + }, + } + + for _, test := range forkTests { + t.Run(test.name, func(t *testing.T) { + cfg := randConfig() + test.modifier(cfg) + err := cfg.Check() + assert.Equal(t, err, test.expectedErr) + }) + } } func TestTimestampForBlock(t *testing.T) { @@ -460,3 +508,118 @@ func TestTimestampForBlock(t *testing.T) { } } + +func TestForkchoiceUpdatedVersion(t *testing.T) { + config := randConfig() + tests := []struct { + name string + canyonTime uint64 + ecotoneTime uint64 + attrs *eth.PayloadAttributes + expectedMethod eth.EngineAPIMethod + }{ + { + name: "NoAttrs", + canyonTime: 10, + ecotoneTime: 20, + attrs: nil, + expectedMethod: eth.FCUV3, + }, + { + name: "BeforeCanyon", + canyonTime: 10, + ecotoneTime: 20, + attrs: ð.PayloadAttributes{Timestamp: 5}, + expectedMethod: eth.FCUV1, + }, + { + name: "Canyon", + canyonTime: 10, + ecotoneTime: 20, + attrs: ð.PayloadAttributes{Timestamp: 15}, + expectedMethod: eth.FCUV2, + }, + { + name: "Ecotone", + canyonTime: 10, + ecotoneTime: 20, + attrs: ð.PayloadAttributes{Timestamp: 25}, + expectedMethod: eth.FCUV3, + }, + } + + for _, test := range tests { + test := test + t.Run(fmt.Sprintf("TestForkchoiceUpdatedVersion_%s", test.name), func(t *testing.T) { + config.CanyonTime = &test.canyonTime + config.EcotoneTime = &test.ecotoneTime + assert.Equal(t, config.ForkchoiceUpdatedVersion(test.attrs), test.expectedMethod) + }) + } +} + +func TestNewPayloadVersion(t *testing.T) { + config := randConfig() + canyonTime := uint64(0) + config.CanyonTime = &canyonTime + tests := []struct { + name string + ecotoneTime uint64 + payloadTime uint64 + expectedMethod eth.EngineAPIMethod + }{ + { + name: "BeforeEcotone", + ecotoneTime: 10, + payloadTime: 5, + expectedMethod: eth.NewPayloadV2, + }, + { + name: "Ecotone", + ecotoneTime: 10, + payloadTime: 15, + expectedMethod: eth.NewPayloadV3, + }, + } + + for _, test := range tests { + test := test + t.Run(fmt.Sprintf("TestNewPayloadVersion_%s", test.name), func(t *testing.T) { + config.EcotoneTime = &test.ecotoneTime + assert.Equal(t, config.NewPayloadVersion(test.payloadTime), test.expectedMethod) + }) + } +} + +func TestGetPayloadVersion(t *testing.T) { + config := randConfig() + canyonTime := uint64(0) + config.CanyonTime = &canyonTime + tests := []struct { + name string + ecotoneTime uint64 + payloadTime uint64 + expectedMethod eth.EngineAPIMethod + }{ + { + name: "BeforeEcotone", + ecotoneTime: 10, + payloadTime: 5, + expectedMethod: eth.GetPayloadV2, + }, + { + name: "Ecotone", + ecotoneTime: 10, + payloadTime: 15, + expectedMethod: eth.GetPayloadV3, + }, + } + + for _, test := range tests { + test := test + t.Run(fmt.Sprintf("TestGetPayloadVersion_%s", test.name), func(t *testing.T) { + config.EcotoneTime = &test.ecotoneTime + assert.Equal(t, config.GetPayloadVersion(test.payloadTime), test.expectedMethod) + }) + } +} diff --git a/op-node/service.go b/op-node/service.go index f172847c1220..b4216ae6892f 100644 --- a/op-node/service.go +++ b/op-node/service.go @@ -10,12 +10,15 @@ import ( "strings" "github.com/ethereum-optimism/optimism/op-node/chaincfg" + plasma "github.com/ethereum-optimism/optimism/op-plasma" + "github.com/ethereum-optimism/optimism/op-service/eigenda" "github.com/ethereum-optimism/optimism/op-service/oppprof" "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/urfave/cli/v2" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" - "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-node/flags" "github.com/ethereum-optimism/optimism/op-node/node" @@ -32,7 +35,7 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { return nil, err } - rollupConfig, err := NewRollupConfig(log, ctx) + rollupConfig, err := NewRollupConfigFromCLI(log, ctx) if err != nil { return nil, err } @@ -73,6 +76,11 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { haltOption = "" } + daCfg, err := NewEigenDAConfig(ctx) + if err != nil { + return nil, fmt.Errorf("failed to load da config: %w", err) + } + cfg := &node.Config{ L1: l1Endpoint, L2: l2Endpoint, @@ -100,6 +108,7 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { URL: ctx.String(flags.HeartbeatURLFlag.Name), }, ConfigPersistence: configPersistence, + SafeDBPath: ctx.String(flags.SafeDBPath.Name), Sync: *syncConfig, RollupHalt: haltOption, RethDBPath: ctx.String(flags.L1RethDBPath.Name), @@ -107,6 +116,11 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { ConductorEnabled: ctx.Bool(flags.ConductorEnabledFlag.Name), ConductorRpc: ctx.String(flags.ConductorRpcFlag.Name), ConductorRpcTimeout: ctx.Duration(flags.ConductorRpcTimeoutFlag.Name), + + Plasma: plasma.ReadCLIConfig(ctx), + + DA: daCfg, + PrefixDerivationEnabled: ctx.Bool(flags.PrefixDerivationEnabledFlag.Name), } if err := cfg.LoadPersisted(log); err != nil { @@ -126,8 +140,11 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { func NewBeaconEndpointConfig(ctx *cli.Context) node.L1BeaconEndpointSetup { return &node.L1BeaconEndpointConfig{ - BeaconAddr: ctx.String(flags.BeaconAddr.Name), - BeaconCheckIgnore: ctx.Bool(flags.BeaconCheckIgnore.Name), + BeaconAddr: ctx.String(flags.BeaconAddr.Name), + BeaconHeader: ctx.String(flags.BeaconHeader.Name), + BeaconArchiverAddr: ctx.String(flags.BeaconArchiverAddr.Name), + BeaconCheckIgnore: ctx.Bool(flags.BeaconCheckIgnore.Name), + BeaconFetchAllSidecars: ctx.Bool(flags.BeaconFetchAllSidecars.Name), } } @@ -191,12 +208,21 @@ func NewDriverConfig(ctx *cli.Context) *driver.Config { } } -func NewRollupConfig(log log.Logger, ctx *cli.Context) (*rollup.Config, error) { +func NewRollupConfigFromCLI(log log.Logger, ctx *cli.Context) (*rollup.Config, error) { network := ctx.String(opflags.NetworkFlagName) rollupConfigPath := ctx.String(opflags.RollupConfigFlagName) if ctx.Bool(flags.BetaExtraNetworks.Name) { log.Warn("The beta.extra-networks flag is deprecated and can be omitted safely.") } + rollupConfig, err := NewRollupConfig(log, network, rollupConfigPath) + if err != nil { + return nil, err + } + applyOverrides(ctx, rollupConfig) + return rollupConfig, nil +} + +func NewRollupConfig(log log.Logger, network string, rollupConfigPath string) (*rollup.Config, error) { if network != "" { if rollupConfigPath != "" { log.Error(`Cannot configure network and rollup-config at the same time. @@ -208,7 +234,6 @@ Conflicting configuration is deprecated, and will stop the op-node from starting if err != nil { return nil, err } - applyOverrides(ctx, rollupConfig) return rollupConfig, nil } @@ -222,7 +247,6 @@ Conflicting configuration is deprecated, and will stop the op-node from starting if err := json.NewDecoder(file).Decode(&rollupConfig); err != nil { return nil, fmt.Errorf("failed to decode rollup config: %w", err) } - applyOverrides(ctx, &rollupConfig) return &rollupConfig, nil } @@ -235,22 +259,24 @@ func applyOverrides(ctx *cli.Context, rollupConfig *rollup.Config) { delta := ctx.Uint64(opflags.DeltaOverrideFlagName) rollupConfig.DeltaTime = &delta } + if ctx.IsSet(opflags.EcotoneOverrideFlagName) { + ecotone := ctx.Uint64(opflags.EcotoneOverrideFlagName) + rollupConfig.EcotoneTime = &ecotone + } } func NewSnapshotLogger(ctx *cli.Context) (log.Logger, error) { snapshotFile := ctx.String(flags.SnapshotLog.Name) - handler := log.DiscardHandler() - if snapshotFile != "" { - var err error - handler, err = log.FileHandler(snapshotFile, log.JSONFormat()) - if err != nil { - return nil, err - } - handler = log.SyncHandler(handler) + if snapshotFile == "" { + return log.NewLogger(log.DiscardHandler()), nil + } + + sf, err := os.OpenFile(snapshotFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) + if err != nil { + return nil, err } - logger := log.New() - logger.SetHandler(handler) - return logger, nil + handler := log.JSONHandler(sf) + return log.NewLogger(handler), nil } func NewSyncConfig(ctx *cli.Context, log log.Logger) (*sync.Config, error) { @@ -273,3 +299,11 @@ func NewSyncConfig(ctx *cli.Context, log log.Logger) (*sync.Config, error) { return cfg, nil } + +func NewEigenDAConfig(ctx *cli.Context) (eigenda.Config, error) { + rpc := ctx.String(flags.DARPC.Name) + return eigenda.Config{ + RPC: rpc, + // Can leave everything else unfilled for the node + }, nil +} diff --git a/op-node/withdrawals/utils.go b/op-node/withdrawals/utils.go index 52e59ca42142..057b56a29945 100644 --- a/op-node/withdrawals/utils.go +++ b/op-node/withdrawals/utils.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/ethclient/gethclient" "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-bindings/bindingspreview" "github.com/ethereum-optimism/optimism/op-bindings/predeploys" ) @@ -28,6 +29,10 @@ type ReceiptClient interface { TransactionReceipt(context.Context, common.Hash) (*types.Receipt, error) } +type BlockClient interface { + BlockByNumber(context.Context, *big.Int) (*types.Block, error) +} + // ProvenWithdrawalParameters is the set of parameters to pass to the ProveWithdrawalTransaction // and FinalizeWithdrawalTransaction functions type ProvenWithdrawalParameters struct { @@ -42,10 +47,32 @@ type ProvenWithdrawalParameters struct { WithdrawalProof [][]byte // List of trie nodes to prove L2 storage } -// ProveWithdrawalParameters queries L1 & L2 to generate all withdrawal parameters and proof necessary to prove a withdrawal on L1. +// ProveWithdrawalParameters calls ProveWithdrawalParametersForBlock with the most recent L2 output after the given header. +func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2ReceiptCl ReceiptClient, l2BlockCl BlockClient, txHash common.Hash, header *types.Header, l2OutputOracleContract *bindings.L2OutputOracleCaller) (ProvenWithdrawalParameters, error) { + l2OutputIndex, err := l2OutputOracleContract.GetL2OutputIndexAfter(&bind.CallOpts{}, header.Number) + if err != nil { + return ProvenWithdrawalParameters{}, fmt.Errorf("failed to get l2OutputIndex: %w", err) + } + l2BlockNumber := header.Number + return ProveWithdrawalParametersForBlock(ctx, proofCl, l2ReceiptCl, l2BlockCl, txHash, l2BlockNumber, l2OutputIndex) +} + +// ProveWithdrawalParametersFPAC calls ProveWithdrawalParametersForBlock with the most recent L2 output after the latest game. +func ProveWithdrawalParametersFPAC(ctx context.Context, proofCl ProofClient, l2ReceiptCl ReceiptClient, l2BlockCl BlockClient, txHash common.Hash, disputeGameFactoryContract *bindings.DisputeGameFactoryCaller, optimismPortal2Contract *bindingspreview.OptimismPortal2Caller) (ProvenWithdrawalParameters, error) { + latestGame, err := FindLatestGame(ctx, disputeGameFactoryContract, optimismPortal2Contract) + if err != nil { + return ProvenWithdrawalParameters{}, fmt.Errorf("failed to find latest game: %w", err) + } + + l2BlockNumber := new(big.Int).SetBytes(latestGame.ExtraData[0:32]) + l2OutputIndex := latestGame.Index + return ProveWithdrawalParametersForBlock(ctx, proofCl, l2ReceiptCl, l2BlockCl, txHash, l2BlockNumber, l2OutputIndex) +} + +// ProveWithdrawalParametersForBlock queries L1 & L2 to generate all withdrawal parameters and proof necessary to prove a withdrawal on L1. // The header provided is very important. It should be a block (timestamp) for which there is a submitted output in the L2 Output Oracle // contract. If not, the withdrawal will fail as it the storage proof cannot be verified if there is no submitted state root. -func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2ReceiptCl ReceiptClient, txHash common.Hash, header *types.Header, l2OutputOracleContract *bindings.L2OutputOracleCaller) (ProvenWithdrawalParameters, error) { +func ProveWithdrawalParametersForBlock(ctx context.Context, proofCl ProofClient, l2ReceiptCl ReceiptClient, l2BlockCl BlockClient, txHash common.Hash, l2BlockNumber, l2OutputIndex *big.Int) (ProvenWithdrawalParameters, error) { // Transaction receipt receipt, err := l2ReceiptCl.TransactionReceipt(ctx, txHash) if err != nil { @@ -65,18 +92,14 @@ func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2Recei return ProvenWithdrawalParameters{}, err } slot := StorageSlotOfWithdrawalHash(withdrawalHash) - p, err := proofCl.GetProof(ctx, predeploys.L2ToL1MessagePasserAddr, []string{slot.String()}, header.Number) - if err != nil { - return ProvenWithdrawalParameters{}, err - } - // Fetch the L2OutputIndex from the L2 Output Oracle caller (on L1) - l2OutputIndex, err := l2OutputOracleContract.GetL2OutputIndexAfter(&bind.CallOpts{}, header.Number) + // Fetch the block from the L2 node + l2Block, err := l2BlockCl.BlockByNumber(ctx, l2BlockNumber) if err != nil { - return ProvenWithdrawalParameters{}, fmt.Errorf("failed to get l2OutputIndex: %w", err) + return ProvenWithdrawalParameters{}, fmt.Errorf("failed to get l2Block: %w", err) } - // TODO: Could skip this step, but it's nice to double check it - err = VerifyProof(header.Root, p) + + p, err := proofCl.GetProof(ctx, predeploys.L2ToL1MessagePasserAddr, []string{slot.String()}, l2Block.Number()) if err != nil { return ProvenWithdrawalParameters{}, err } @@ -84,6 +107,11 @@ func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2Recei return ProvenWithdrawalParameters{}, errors.New("invalid amount of storage proofs") } + err = VerifyProof(l2Block.Root(), p) + if err != nil { + return ProvenWithdrawalParameters{}, err + } + // Encode it as expected by the contract trieNodes := make([][]byte, len(p.StorageProof[0].Proof)) for i, s := range p.StorageProof[0].Proof { @@ -100,14 +128,42 @@ func ProveWithdrawalParameters(ctx context.Context, proofCl ProofClient, l2Recei Data: ev.Data, OutputRootProof: bindings.TypesOutputRootProof{ Version: [32]byte{}, // Empty for version 1 - StateRoot: header.Root, + StateRoot: l2Block.Root(), MessagePasserStorageRoot: p.StorageHash, - LatestBlockhash: header.Hash(), + LatestBlockhash: l2Block.Hash(), }, WithdrawalProof: trieNodes, }, nil } +// FindLatestGame finds the latest game in the DisputeGameFactory contract. +func FindLatestGame(ctx context.Context, disputeGameFactoryContract *bindings.DisputeGameFactoryCaller, optimismPortal2Contract *bindingspreview.OptimismPortal2Caller) (*bindings.IDisputeGameFactoryGameSearchResult, error) { + respectedGameType, err := optimismPortal2Contract.RespectedGameType(&bind.CallOpts{}) + if err != nil { + return nil, fmt.Errorf("failed to get respected game type: %w", err) + } + + gameCount, err := disputeGameFactoryContract.GameCount(&bind.CallOpts{}) + if err != nil { + return nil, fmt.Errorf("failed to get game count: %w", err) + } + if gameCount.Cmp(common.Big0) == 0 { + return nil, errors.New("no games") + } + + searchStart := new(big.Int).Sub(gameCount, common.Big1) + latestGames, err := disputeGameFactoryContract.FindLatestGames(&bind.CallOpts{}, respectedGameType, searchStart, common.Big1) + if err != nil { + return nil, fmt.Errorf("failed to get latest games: %w", err) + } + if len(latestGames) == 0 { + return nil, errors.New("no latest games") + } + + latestGame := latestGames[0] + return &latestGame, nil +} + // Standard ABI types copied from golang ABI tests var ( Uint256Type, _ = abi.NewType("uint256", "", nil) diff --git a/op-plasma/cli.go b/op-plasma/cli.go new file mode 100644 index 000000000000..92164bd5041d --- /dev/null +++ b/op-plasma/cli.go @@ -0,0 +1,73 @@ +package plasma + +import ( + "fmt" + "net/url" + + "github.com/urfave/cli/v2" +) + +const ( + EnabledFlagName = "plasma.enabled" + DaServerAddressFlagName = "plasma.da-server" + VerifyOnReadFlagName = "plasma.verify-on-read" +) + +func plasmaEnv(envprefix, v string) []string { + return []string{envprefix + "_PLASMA_" + v} +} + +func CLIFlags(envPrefix string, category string) []cli.Flag { + return []cli.Flag{ + &cli.BoolFlag{ + Name: EnabledFlagName, + Usage: "Enable plasma mode", + Value: false, + EnvVars: plasmaEnv(envPrefix, "ENABLED"), + Category: category, + }, + &cli.StringFlag{ + Name: DaServerAddressFlagName, + Usage: "HTTP address of a DA Server", + EnvVars: plasmaEnv(envPrefix, "DA_SERVER"), + Category: category, + }, + &cli.BoolFlag{ + Name: VerifyOnReadFlagName, + Usage: "Verify input data matches the commitments from the DA storage service", + Value: true, + EnvVars: plasmaEnv(envPrefix, "VERIFY_ON_READ"), + Category: category, + }, + } +} + +type CLIConfig struct { + Enabled bool + DAServerURL string + VerifyOnRead bool +} + +func (c CLIConfig) Check() error { + if c.Enabled { + if c.DAServerURL == "" { + return fmt.Errorf("DA server URL is required when plasma da is enabled") + } + if _, err := url.Parse(c.DAServerURL); err != nil { + return fmt.Errorf("DA server URL is invalid: %w", err) + } + } + return nil +} + +func (c CLIConfig) NewDAClient() *DAClient { + return &DAClient{url: c.DAServerURL, verify: c.VerifyOnRead} +} + +func ReadCLIConfig(c *cli.Context) CLIConfig { + return CLIConfig{ + Enabled: c.Bool(EnabledFlagName), + DAServerURL: c.String(DaServerAddressFlagName), + VerifyOnRead: c.Bool(VerifyOnReadFlagName), + } +} diff --git a/op-plasma/commitment.go b/op-plasma/commitment.go new file mode 100644 index 000000000000..6f45bd4f8429 --- /dev/null +++ b/op-plasma/commitment.go @@ -0,0 +1,61 @@ +package plasma + +import ( + "bytes" + "errors" + + "github.com/ethereum/go-ethereum/crypto" +) + +// ErrInvalidCommitment is returned when the commitment cannot be parsed into a known commitment type. +var ErrInvalidCommitment = errors.New("invalid commitment") + +// ErrCommitmentMismatch is returned when the commitment does not match the given input. +var ErrCommitmentMismatch = errors.New("commitment mismatch") + +// CommitmentType is the commitment type prefix. +type CommitmentType byte + +// KeccakCommitmentType is the default commitment type for the DA storage. +const Keccak256CommitmentType CommitmentType = 0 + +// Keccak256Commitment is the default commitment type for op-plasma. +type Keccak256Commitment []byte + +// Encode adds a commitment type prefix self describing the commitment. +func (c Keccak256Commitment) Encode() []byte { + return append([]byte{byte(Keccak256CommitmentType)}, c...) +} + +// TxData adds an extra version byte to signal it's a commitment. +func (c Keccak256Commitment) TxData() []byte { + return append([]byte{TxDataVersion1}, c.Encode()...) +} + +// Verify checks if the commitment matches the given input. +func (c Keccak256Commitment) Verify(input []byte) error { + if !bytes.Equal(c, crypto.Keccak256(input)) { + return ErrCommitmentMismatch + } + return nil +} + +// Keccak256 creates a new commitment from the given input. +func Keccak256(input []byte) Keccak256Commitment { + return Keccak256Commitment(crypto.Keccak256(input)) +} + +// DecodeKeccak256 validates and casts the commitment into a Keccak256Commitment. +func DecodeKeccak256(commitment []byte) (Keccak256Commitment, error) { + if len(commitment) == 0 { + return nil, ErrInvalidCommitment + } + if commitment[0] != byte(Keccak256CommitmentType) { + return nil, ErrInvalidCommitment + } + c := commitment[1:] + if len(c) != 32 { + return nil, ErrInvalidCommitment + } + return c, nil +} diff --git a/op-plasma/daclient.go b/op-plasma/daclient.go new file mode 100644 index 000000000000..e1c03509f69a --- /dev/null +++ b/op-plasma/daclient.go @@ -0,0 +1,83 @@ +package plasma + +import ( + "bytes" + "context" + "errors" + "fmt" + "io" + "net/http" +) + +// ErrNotFound is returned when the server could not find the input. +var ErrNotFound = errors.New("not found") + +// ErrInvalidInput is returned when the input is not valid for posting to the DA storage. +var ErrInvalidInput = errors.New("invalid input") + +// DAClient is an HTTP client to communicate with a DA storage service. +// It creates commitments and retrieves input data + verifies if needed. +// Currently only supports Keccak256 commitments but may be extended eventually. +type DAClient struct { + url string + // VerifyOnRead sets the client to verify the commitment on read. + // SHOULD enable if the storage service is not trusted. + verify bool +} + +func NewDAClient(url string, verify bool) *DAClient { + return &DAClient{url, verify} +} + +// GetInput returns the input data for the given encoded commitment bytes. +func (c *DAClient) GetInput(ctx context.Context, comm Keccak256Commitment) ([]byte, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/get/0x%x", c.url, comm.Encode()), nil) + if err != nil { + return nil, fmt.Errorf("failed to create HTTP request: %w", err) + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + if resp.StatusCode == http.StatusNotFound { + return nil, ErrNotFound + } + defer resp.Body.Close() + input, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + if c.verify { + if err := comm.Verify(input); err != nil { + return nil, err + } + + } + return input, nil +} + +// SetInput sets the input data and returns the keccak256 hash commitment. +func (c *DAClient) SetInput(ctx context.Context, img []byte) (Keccak256Commitment, error) { + if len(img) == 0 { + return nil, ErrInvalidInput + } + comm := Keccak256(img) + // encode with commitment type prefix + key := comm.Encode() + body := bytes.NewReader(img) + url := fmt.Sprintf("%s/put/0x%x", c.url, key) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, body) + if err != nil { + return nil, fmt.Errorf("failed to create HTTP request: %w", err) + } + req.Header.Set("Content-Type", "application/octet-stream") + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("failed to store preimage: %v", resp.StatusCode) + } + return comm, nil +} diff --git a/op-plasma/daclient_test.go b/op-plasma/daclient_test.go new file mode 100644 index 000000000000..f605cda761ad --- /dev/null +++ b/op-plasma/daclient_test.go @@ -0,0 +1,115 @@ +package plasma + +import ( + "context" + "io" + "math/rand" + "net/http" + "net/http/httptest" + "testing" + + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/ethdb/memorydb" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func TestDAClient(t *testing.T) { + store := memorydb.New() + logger := testlog.Logger(t, log.LevelDebug) + + ctx := context.Background() + + mux := http.NewServeMux() + mux.Handle("/get/", http.StripPrefix("/get/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + logger.Debug("GET", "url", r.URL) + + comm, err := hexutil.Decode(r.URL.String()) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + input, err := store.Get(comm) + if err != nil { + w.WriteHeader(http.StatusNotFound) + return + } + if _, err := w.Write(input); err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + }))) + mux.Handle("/put/", http.StripPrefix("/put/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + logger.Debug("PUT", "url", r.URL) + + input, err := io.ReadAll(r.Body) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + comm, err := hexutil.Decode(r.URL.String()) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + if err := store.Put(comm, input); err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + if _, err := w.Write(comm); err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + }))) + + tsrv := httptest.NewServer(mux) + + cfg := CLIConfig{ + Enabled: true, + DAServerURL: tsrv.URL, + VerifyOnRead: true, + } + require.NoError(t, cfg.Check()) + + client := cfg.NewDAClient() + + rng := rand.New(rand.NewSource(1234)) + + input := RandomData(rng, 2000) + + comm, err := client.SetInput(ctx, input) + require.NoError(t, err) + + require.Equal(t, comm, Keccak256(input)) + + stored, err := client.GetInput(ctx, comm) + require.NoError(t, err) + + require.Equal(t, input, stored) + + // set a bad commitment in the store + require.NoError(t, store.Put(comm.Encode(), []byte("bad data"))) + + _, err = client.GetInput(ctx, comm) + require.ErrorIs(t, err, ErrCommitmentMismatch) + + // test not found error + comm = Keccak256(RandomData(rng, 32)) + _, err = client.GetInput(ctx, comm) + require.ErrorIs(t, err, ErrNotFound) + + // test storing bad data + _, err = client.SetInput(ctx, []byte{}) + require.ErrorIs(t, err, ErrInvalidInput) + + // server not responsive + tsrv.Close() + _, err = client.SetInput(ctx, input) + require.Error(t, err) + + _, err = client.GetInput(ctx, Keccak256(input)) + require.Error(t, err) +} diff --git a/op-plasma/damgr.go b/op-plasma/damgr.go new file mode 100644 index 000000000000..3ecc2af7a7a6 --- /dev/null +++ b/op-plasma/damgr.go @@ -0,0 +1,425 @@ +package plasma + +import ( + "context" + "errors" + "fmt" + "io" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum-optimism/optimism/op-service/eth" +) + +// ErrPendingChallenge is returned when data is not available but can still be challenged/resolved +// so derivation should halt temporarily. +var ErrPendingChallenge = errors.New("not found, pending challenge") + +// ErrExpiredChallenge is returned when a challenge was not resolved and derivation should skip this input. +var ErrExpiredChallenge = errors.New("challenge expired") + +// ErrMissingPastWindow is returned when the input data is MIA and cannot be challenged. +// This is a protocol fatal error. +var ErrMissingPastWindow = errors.New("data missing past window") + +// ErrInvalidChallenge is returned when a challenge event does is decoded but does not +// relate to the actual chain commitments. +var ErrInvalidChallenge = errors.New("invalid challenge") + +// L1Fetcher is the required interface for syncing the DA challenge contract state. +type L1Fetcher interface { + InfoAndTxsByHash(ctx context.Context, hash common.Hash) (eth.BlockInfo, types.Transactions, error) + FetchReceipts(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Receipts, error) + L1BlockRefByNumber(context.Context, uint64) (eth.L1BlockRef, error) +} + +// DAStorage interface for calling the DA storage server. +type DAStorage interface { + GetInput(ctx context.Context, key Keccak256Commitment) ([]byte, error) + SetInput(ctx context.Context, img []byte) (Keccak256Commitment, error) +} + +// HeadSignalFn is the callback function to accept head-signals without a context. +type HeadSignalFn func(eth.L1BlockRef) + +// Config is the relevant subset of rollup config for plasma DA. +type Config struct { + // Required for filtering contract events + DAChallengeContractAddress common.Address + // The number of l1 blocks after the input is committed during which one can challenge. + ChallengeWindow uint64 + // The number of l1 blocks after a commitment is challenged during which one can resolve. + ResolveWindow uint64 +} + +type DA struct { + log log.Logger + cfg Config + metrics Metricer + + storage DAStorage + + // the DA state keeps track of all the commitments and their challenge status. + state *State + + // the latest l1 block we synced challenge contract events from + origin eth.BlockID + // the latest recorded finalized head as per the challenge contract + finalizedHead eth.L1BlockRef + // the latest recorded finalized head as per the l1 finalization signal + l1FinalizedHead eth.L1BlockRef + // flag the reset function we are resetting because of an expired challenge + resetting bool + + finalizedHeadSignalFunc HeadSignalFn +} + +// NewPlasmaDA creates a new PlasmaDA instance with the given log and CLIConfig. +func NewPlasmaDA(log log.Logger, cli CLIConfig, cfg Config, metrics Metricer) *DA { + return NewPlasmaDAWithStorage(log, cfg, cli.NewDAClient(), metrics) +} + +// NewPlasmaDAWithStorage creates a new PlasmaDA instance with the given log and DAStorage interface. +func NewPlasmaDAWithStorage(log log.Logger, cfg Config, storage DAStorage, metrics Metricer) *DA { + return &DA{ + log: log, + cfg: cfg, + storage: storage, + metrics: metrics, + state: NewState(log, metrics), + } +} + +// NewPlasmaWithState creates a plasma storage from initial state used for testing in isolation. +// We pass the L1Fetcher to each method so it is kept in sync with the conf depth of the pipeline. +func NewPlasmaDAWithState(log log.Logger, cfg Config, storage DAStorage, metrics Metricer, state *State) *DA { + return &DA{ + log: log, + cfg: cfg, + storage: storage, + metrics: metrics, + state: state, + } +} + +// OnFinalizedHeadSignal sets the callback function to be called when the finalized head is updated. +// This will signal to the engine queue that will set the proper L2 block as finalized. +func (d *DA) OnFinalizedHeadSignal(f HeadSignalFn) { + d.finalizedHeadSignalFunc = f +} + +// Finalize takes the L1 finality signal, compares the plasma finalized block and forwards the finality +// signal to the engine queue based on whichever is most behind. +func (d *DA) Finalize(l1Finalized eth.L1BlockRef) { + ref := d.finalizedHead + d.log.Info("received l1 finalized signal, forwarding to engine queue", "l1", l1Finalized, "plasma", ref) + // if the l1 finalized head is behind it is the finalized head + if l1Finalized.Number < d.finalizedHead.Number { + ref = l1Finalized + } + // prune finalized state + d.state.Prune(ref.Number) + + if d.finalizedHeadSignalFunc == nil { + d.log.Warn("finalized head signal function not set") + return + } + + // signal the engine queue + d.finalizedHeadSignalFunc(ref) +} + +// LookAhead increments the challenges origin and process the new block if it exists. +// It is used when the derivation pipeline stalls due to missing data and we need to continue +// syncing challenge events until the challenge is resolved or expires. +func (d *DA) LookAhead(ctx context.Context, l1 L1Fetcher) error { + blkRef, err := l1.L1BlockRefByNumber(ctx, d.origin.Number+1) + // temporary error, will do a backoff + if err != nil { + return err + } + return d.AdvanceL1Origin(ctx, l1, blkRef.ID()) +} + +// Reset the challenge event derivation origin in case of L1 reorg +func (d *DA) Reset(ctx context.Context, base eth.L1BlockRef, baseCfg eth.SystemConfig) error { + // resetting due to expired challenge, do not clear state. + // If the DA source returns ErrReset, the pipeline is forced to reset by the rollup driver. + // In that case the Reset function will be called immediately, BEFORE the pipeline can + // call any further stage to step. Thus the state will NOT be cleared if the reset originates + // from this stage of the pipeline. + if d.resetting { + d.resetting = false + } else { + // resetting due to L1 reorg, clear state + d.origin = base.ID() + d.state.Reset() + } + return io.EOF +} + +// GetInput returns the input data for the given commitment bytes. blockNumber is required to lookup +// the challenge status in the DataAvailabilityChallenge L1 contract. +func (d *DA) GetInput(ctx context.Context, l1 L1Fetcher, comm Keccak256Commitment, blockId eth.BlockID) (eth.Data, error) { + // If the challenge head is ahead in the case of a pipeline reset or stall, we might have synced a + // challenge event for this commitment. Otherwise we mark the commitment as part of the canonical + // chain so potential future challenge events can be selected. + ch := d.state.GetOrTrackChallenge(comm.Encode(), blockId.Number, d.cfg.ChallengeWindow) + + // Fetch the input from the DA storage. + data, err := d.storage.GetInput(ctx, comm) + + // data is not found in storage but may be available if the challenge was resolved. + notFound := errors.Is(ErrNotFound, err) + + if err != nil && !notFound { + d.log.Error("failed to get preimage", "err", err) + // the storage client request failed for some other reason + // in which case derivation pipeline should be retried + return nil, err + } + + switch ch.challengeStatus { + case ChallengeActive: + if d.isExpired(ch.expiresAt) { + // this challenge has expired, this input must be skipped + return nil, ErrExpiredChallenge + } else if notFound { + // data is missing and a challenge is active, we must wait for the challenge to resolve + // hence we continue syncing new origins to sync the new challenge events. + if err := d.LookAhead(ctx, l1); err != nil { + return nil, err + } + return nil, ErrPendingChallenge + } + case ChallengeExpired: + // challenge was marked as expired, skip + return nil, ErrExpiredChallenge + case ChallengeResolved: + // challenge was resolved, data is available in storage, return directly + if !notFound { + return data, nil + } + // data not found in storage, return from challenge resolved input + resolvedInput, err := d.state.GetResolvedInput(comm.Encode()) + if err != nil { + return nil, err + } + return resolvedInput, nil + default: + if notFound { + if d.isExpired(ch.expiresAt) { + // we're past the challenge window and the data is not available + return nil, ErrMissingPastWindow + } else { + // continue syncing challenges hoping it eventually is challenged and resolved + if err := d.LookAhead(ctx, l1); err != nil { + return nil, err + } + return nil, ErrPendingChallenge + } + } + } + + return data, nil +} + +// isExpired returns whether the given expiration block number is lower or equal to the current head +func (d *DA) isExpired(bn uint64) bool { + return d.origin.Number >= bn +} + +// AdvanceL1Origin syncs any challenge events included in the l1 block, expires any active challenges +// after the new resolveWindow, computes and signals the new finalized head and sets the l1 block +// as the new head for tracking challenges. If forwards an error if any new challenge have expired to +// trigger a derivation reset. +func (d *DA) AdvanceL1Origin(ctx context.Context, l1 L1Fetcher, block eth.BlockID) error { + // do not repeat for the same origin + if block.Number <= d.origin.Number { + return nil + } + // sync challenges for the given block ID + if err := d.LoadChallengeEvents(ctx, l1, block); err != nil { + return err + } + // advance challenge window, computing the finalized head + bn, err := d.state.ExpireChallenges(block.Number) + if err != nil { + // warn the reset function not to clear the state + d.resetting = true + return err + } + + // finalized head signal is called only when the finalized head number increases + // and the l1 finalized head ahead of the DA finalized head. + if bn > d.finalizedHead.Number { + ref, err := l1.L1BlockRefByNumber(ctx, bn) + if err != nil { + return err + } + d.metrics.RecordChallengesHead("finalized", bn) + + // keep track of finalized had so it can be picked up by the + // l1 finalization signal + d.finalizedHead = ref + } + d.origin = block + d.metrics.RecordChallengesHead("latest", d.origin.Number) + + d.log.Info("processed plasma l1 origin", "origin", block, "next-finalized", bn, "finalized", d.finalizedHead.Number, "l1-finalize", d.l1FinalizedHead.Number) + return nil +} + +// LoadChallengeEvents fetches the l1 block receipts and updates the challenge status +func (d *DA) LoadChallengeEvents(ctx context.Context, l1 L1Fetcher, block eth.BlockID) error { + // filter any challenge event logs in the block + logs, err := d.fetchChallengeLogs(ctx, l1, block) + if err != nil { + return err + } + + for _, log := range logs { + i := log.TxIndex + status, comm, err := d.decodeChallengeStatus(log) + if err != nil { + d.log.Error("failed to decode challenge event", "block", block.Number, "tx", i, "log", log.Index, "err", err) + continue + } + switch status { + case ChallengeResolved: + // cached with input resolution call so not expensive + _, txs, err := l1.InfoAndTxsByHash(ctx, block.Hash) + if err != nil { + d.log.Error("failed to fetch l1 block", "block", block.Number, "err", err) + continue + } + // avoid panic in black swan case of faulty rpc + if uint(len(txs)) <= i { + d.log.Error("tx/receipt mismatch in InfoAndTxsByHash") + continue + } + // select the transaction corresponding to the receipt + tx := txs[i] + // txs and receipts must be in the same order + if tx.Hash() != log.TxHash { + d.log.Error("tx hash mismatch", "block", block.Number, "txIdx", i, "log", log.Index, "txHash", tx.Hash(), "receiptTxHash", log.TxHash) + continue + } + // Decode the input from resolver tx calldata + input, err := DecodeResolvedInput(tx.Data()) + if err != nil { + d.log.Error("failed to decode resolved input", "block", block.Number, "txIdx", i, "err", err) + continue + } + if err := comm.Verify(input); err != nil { + d.log.Error("failed to verify commitment", "block", block.Number, "txIdx", i, "err", err) + continue + } + d.log.Debug("challenge resolved", "block", block, "txIdx", i) + d.state.SetResolvedChallenge(comm.Encode(), input, log.BlockNumber) + case ChallengeActive: + d.log.Info("detected new active challenge", "block", block) + d.state.SetActiveChallenge(comm.Encode(), log.BlockNumber, d.cfg.ResolveWindow) + default: + d.log.Warn("skipping unknown challenge status", "block", block.Number, "tx", i, "log", log.Index, "status", status) + } + } + return nil +} + +// fetchChallengeLogs returns logs for challenge events if any for the given block +func (d *DA) fetchChallengeLogs(ctx context.Context, l1 L1Fetcher, block eth.BlockID) ([]*types.Log, error) { //cached with deposits events call so not expensive + var logs []*types.Log + _, receipts, err := l1.FetchReceipts(ctx, block.Hash) + if err != nil { + return nil, err + } + d.log.Info("loading challenges", "epoch", block.Number, "numReceipts", len(receipts)) + for _, rec := range receipts { + // skip error logs + if rec.Status != types.ReceiptStatusSuccessful { + continue + } + for _, log := range rec.Logs { + if log.Address == d.cfg.DAChallengeContractAddress && len(log.Topics) > 0 && log.Topics[0] == ChallengeStatusEventABIHash { + logs = append(logs, log) + } + } + } + + return logs, nil +} + +// decodeChallengeStatus decodes and validates a challenge event from a transaction log, returning the associated commitment bytes. +func (d *DA) decodeChallengeStatus(log *types.Log) (ChallengeStatus, Keccak256Commitment, error) { + event, err := DecodeChallengeStatusEvent(log) + if err != nil { + return 0, nil, err + } + comm, err := DecodeKeccak256(event.ChallengedCommitment) + if err != nil { + return 0, nil, err + } + d.log.Debug("decoded challenge status event", "log", log, "event", event, "comm", fmt.Sprintf("%x", comm.Encode())) + + bn := event.ChallengedBlockNumber.Uint64() + // IsTracking just validates whether the commitment was challenged for the correct block number + // if it has been loaded from the batcher inbox before. Spam commitments will be tracked but + // ignored and evicted unless derivation encounters the commitment. + if !d.state.IsTracking(comm.Encode(), bn) { + return 0, nil, fmt.Errorf("%w: %x at block %d", ErrInvalidChallenge, comm.Encode(), bn) + } + return ChallengeStatus(event.Status), comm, nil +} + +var ( + ChallengeStatusEventName = "ChallengeStatusChanged" + ChallengeStatusEventABI = "ChallengeStatusChanged(uint256,bytes,uint8)" + ChallengeStatusEventABIHash = crypto.Keccak256Hash([]byte(ChallengeStatusEventABI)) +) + +// DecodeChallengeStatusEvent decodes the challenge status event from the log data and the indexed challenged +// hash and block number from the topics. +func DecodeChallengeStatusEvent(log *types.Log) (*bindings.DataAvailabilityChallengeChallengeStatusChanged, error) { + // abi lazy loaded, cached after decoded once + dacAbi, err := bindings.DataAvailabilityChallengeMetaData.GetAbi() + if err != nil { + return nil, err + } + var event bindings.DataAvailabilityChallengeChallengeStatusChanged + err = dacAbi.UnpackIntoInterface(&event, ChallengeStatusEventName, log.Data) + if err != nil { + return nil, err + } + var indexed abi.Arguments + for _, arg := range dacAbi.Events[ChallengeStatusEventName].Inputs { + if arg.Indexed { + indexed = append(indexed, arg) + } + } + if err := abi.ParseTopics(&event, indexed, log.Topics[1:]); err != nil { + return nil, err + } + return &event, nil +} + +// DecodeResolvedInput decodes the preimage bytes from the tx input data. +func DecodeResolvedInput(data []byte) ([]byte, error) { + dacAbi, _ := bindings.DataAvailabilityChallengeMetaData.GetAbi() + + args := make(map[string]interface{}) + err := dacAbi.Methods["resolve"].Inputs.UnpackIntoMap(args, data[4:]) + if err != nil { + return nil, err + } + rd, ok := args["resolveData"].([]byte) + if !ok || len(rd) == 0 { + return nil, fmt.Errorf("invalid resolve data") + } + return rd, nil +} diff --git a/op-plasma/damgr_test.go b/op-plasma/damgr_test.go new file mode 100644 index 000000000000..5a37badc19ca --- /dev/null +++ b/op-plasma/damgr_test.go @@ -0,0 +1,366 @@ +package plasma + +import ( + "context" + "math/big" + "math/rand" + "testing" + + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func RandomData(rng *rand.Rand, size int) []byte { + out := make([]byte, size) + rng.Read(out) + return out +} + +// TestDAChallengeState is a simple test with small values to verify the finalized head logic +func TestDAChallengeState(t *testing.T) { + logger := testlog.Logger(t, log.LvlDebug) + + rng := rand.New(rand.NewSource(1234)) + state := NewState(logger, &NoopMetrics{}) + + i := uint64(1) + + challengeWindow := uint64(6) + resolveWindow := uint64(6) + + // track commitments in the first 10 blocks + for ; i < 10; i++ { + // this is akin to stepping the derivation pipeline through a range a blocks each with a commitment + state.SetInputCommitment(RandomData(rng, 32), i, challengeWindow) + } + + // blocks are finalized after the challenge window expires + bn, err := state.ExpireChallenges(10) + require.NoError(t, err) + // finalized head = 10 - 6 = 4 + require.Equal(t, uint64(4), bn) + + // track the next commitment and mark it as challenged + c := RandomData(rng, 32) + // add input commitment at block i = 10 + state.SetInputCommitment(c, 10, challengeWindow) + // i+4 is the block at which it was challenged + state.SetActiveChallenge(c, 14, resolveWindow) + + for j := i + 1; j < 18; j++ { + // continue walking the pipeline through some more blocks with commitments + state.SetInputCommitment(RandomData(rng, 32), j, challengeWindow) + } + + // finalized l1 origin should not extend past the resolve window + bn, err = state.ExpireChallenges(18) + require.NoError(t, err) + // finalized is active_challenge_block - 1 = 10 - 1 and cannot move until the challenge expires + require.Equal(t, uint64(9), bn) + + // walk past the resolve window + for j := uint64(18); j < 22; j++ { + state.SetInputCommitment(RandomData(rng, 32), j, challengeWindow) + } + + // no more active challenges, the finalized head can catch up to the challenge window + bn, err = state.ExpireChallenges(22) + require.ErrorIs(t, err, ErrReorgRequired) + // finalized head is now 22 - 6 = 16 + require.Equal(t, uint64(16), bn) + + // cleanup state we don't need anymore + state.Prune(22) + // now if we expire the challenges again, it won't request a reorg again + bn, err = state.ExpireChallenges(22) + require.NoError(t, err) + // finalized head hasn't moved + require.Equal(t, uint64(16), bn) + + // add one more commitment and challenge it + c = RandomData(rng, 32) + state.SetInputCommitment(c, 22, challengeWindow) + // challenge 3 blocks after + state.SetActiveChallenge(c, 25, resolveWindow) + + // exceed the challenge window with more commitments + for j := uint64(23); j < 30; j++ { + state.SetInputCommitment(RandomData(rng, 32), j, challengeWindow) + } + + // finalized head should not extend past the resolve window + bn, err = state.ExpireChallenges(30) + require.NoError(t, err) + // finalized head is stuck waiting for resolve window + require.Equal(t, uint64(21), bn) + + input := RandomData(rng, 100) + // resolve the challenge + state.SetResolvedChallenge(c, input, 30) + + // finalized head catches up + bn, err = state.ExpireChallenges(31) + require.NoError(t, err) + // finalized head is now 31 - 6 = 25 + require.Equal(t, uint64(25), bn) + + // the resolved input is also stored + storedInput, err := state.GetResolvedInput(c) + require.NoError(t, err) + require.Equal(t, input, storedInput) +} + +// TestExpireChallenges expires challenges and prunes the state for longer windows +// with commitments every 6 blocks. +func TestExpireChallenges(t *testing.T) { + logger := testlog.Logger(t, log.LvlDebug) + + rng := rand.New(rand.NewSource(1234)) + state := NewState(logger, &NoopMetrics{}) + + comms := make(map[uint64][]byte) + + i := uint64(3713854) + + var finalized uint64 + + challengeWindow := uint64(90) + resolveWindow := uint64(90) + + // increment new commitments every 6 blocks + for ; i < 3713948; i += 6 { + comm := RandomData(rng, 32) + comms[i] = comm + logger.Info("set commitment", "block", i) + cm := state.GetOrTrackChallenge(comm, i, challengeWindow) + require.NotNil(t, cm) + + bn, err := state.ExpireChallenges(i) + logger.Info("expire challenges", "finalized head", bn, "err", err) + + // only update finalized head if it has moved + if bn > finalized { + finalized = bn + // prune unused state + state.Prune(bn) + } + } + + // activate a couple of subsequent challenges + state.SetActiveChallenge(comms[3713926], 3713948, resolveWindow) + + state.SetActiveChallenge(comms[3713932], 3713950, resolveWindow) + + // continue incrementing commitments + for ; i < 3714038; i += 6 { + comm := RandomData(rng, 32) + comms[i] = comm + logger.Info("set commitment", "block", i) + cm := state.GetOrTrackChallenge(comm, i, challengeWindow) + require.NotNil(t, cm) + + bn, err := state.ExpireChallenges(i) + logger.Info("expire challenges", "expired", bn, "err", err) + + if bn > finalized { + finalized = bn + state.Prune(bn) + } + + } + + // finalized head does not move as it expires previously seen blocks + bn, err := state.ExpireChallenges(3714034) + require.NoError(t, err) + require.Equal(t, uint64(3713920), bn) + + bn, err = state.ExpireChallenges(3714035) + require.NoError(t, err) + require.Equal(t, uint64(3713920), bn) + + bn, err = state.ExpireChallenges(3714036) + require.NoError(t, err) + require.Equal(t, uint64(3713920), bn) + + bn, err = state.ExpireChallenges(3714037) + require.NoError(t, err) + require.Equal(t, uint64(3713920), bn) + + // lastly we get to the resolve window and trigger a reorg + _, err = state.ExpireChallenges(3714038) + require.ErrorIs(t, err, ErrReorgRequired) + + // this is simulating a pipeline reset where it walks back challenge + resolve window + for i := uint64(3713854); i < 3714044; i += 6 { + cm := state.GetOrTrackChallenge(comms[i], i, challengeWindow) + require.NotNil(t, cm) + + // check that the challenge status was updated to expired + if i == 3713926 { + require.Equal(t, ChallengeExpired, cm.challengeStatus) + } + } + + bn, err = state.ExpireChallenges(3714038) + require.NoError(t, err) + + // finalized at last + require.Equal(t, uint64(3713926), bn) +} + +func TestDAChallengeDetached(t *testing.T) { + logger := testlog.Logger(t, log.LvlDebug) + + rng := rand.New(rand.NewSource(1234)) + state := NewState(logger, &NoopMetrics{}) + + challengeWindow := uint64(6) + resolveWindow := uint64(6) + + c1 := RandomData(rng, 32) + c2 := RandomData(rng, 32) + + // c1 at bn1 is missing, pipeline stalls + state.GetOrTrackChallenge(c1, 1, challengeWindow) + + // c2 at bn2 is challenged at bn3 + require.True(t, state.IsTracking(c2, 2)) + state.SetActiveChallenge(c2, 3, resolveWindow) + + // c1 is finally challenged at bn5 + state.SetActiveChallenge(c1, 5, resolveWindow) + + // c2 expires but should not trigger a reset because we don't know if it's valid yet + bn, err := state.ExpireChallenges(10) + require.NoError(t, err) + require.Equal(t, uint64(0), bn) + + // c1 expires finally + bn, err = state.ExpireChallenges(11) + require.ErrorIs(t, err, ErrReorgRequired) + require.Equal(t, uint64(1), bn) + + // pruning finalized block is safe + state.Prune(bn) + + // pipeline discovers c2 + comm := state.GetOrTrackChallenge(c2, 2, challengeWindow) + // it is already marked as expired so it will be skipped without needing a reorg + require.Equal(t, ChallengeExpired, comm.challengeStatus) + + // later when we get to finalizing block 10 + margin, the pending challenge is safely pruned + state.Prune(210) + require.Equal(t, 0, len(state.expiredComms)) +} + +// cannot import from testutils at this time because of import cycle +type mockL1Fetcher struct { + mock.Mock +} + +func (m *mockL1Fetcher) InfoAndTxsByHash(ctx context.Context, hash common.Hash) (eth.BlockInfo, types.Transactions, error) { + out := m.Mock.Called(hash) + return out.Get(0).(eth.BlockInfo), out.Get(1).(types.Transactions), out.Error(2) +} + +func (m *mockL1Fetcher) ExpectInfoAndTxsByHash(hash common.Hash, info eth.BlockInfo, transactions types.Transactions, err error) { + m.Mock.On("InfoAndTxsByHash", hash).Once().Return(info, transactions, err) +} + +func (m *mockL1Fetcher) FetchReceipts(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Receipts, error) { + out := m.Mock.Called(blockHash) + return *out.Get(0).(*eth.BlockInfo), out.Get(1).(types.Receipts), out.Error(2) +} + +func (m *mockL1Fetcher) ExpectFetchReceipts(hash common.Hash, info eth.BlockInfo, receipts types.Receipts, err error) { + m.Mock.On("FetchReceipts", hash).Once().Return(&info, receipts, err) +} + +func (m *mockL1Fetcher) L1BlockRefByNumber(ctx context.Context, num uint64) (eth.L1BlockRef, error) { + out := m.Mock.Called(num) + return out.Get(0).(eth.L1BlockRef), out.Error(1) +} + +func (m *mockL1Fetcher) ExpectL1BlockRefByNumber(num uint64, ref eth.L1BlockRef, err error) { + m.Mock.On("L1BlockRefByNumber", num).Once().Return(ref, err) +} + +func TestFilterInvalidBlockNumber(t *testing.T) { + logger := testlog.Logger(t, log.LevelDebug) + ctx := context.Background() + + l1F := &mockL1Fetcher{} + + storage := NewMockDAClient(logger) + + daddr := common.HexToAddress("0x978e3286eb805934215a88694d80b09aded68d90") + pcfg := Config{ + ChallengeWindow: 90, ResolveWindow: 90, DAChallengeContractAddress: daddr, + } + + bn := uint64(19) + bhash := common.HexToHash("0xd438144ffab918b1349e7cd06889c26800c26d8edc34d64f750e3e097166a09c") + + state := NewState(logger, &NoopMetrics{}) + + da := NewPlasmaDAWithState(logger, pcfg, storage, &NoopMetrics{}, state) + + receipts := types.Receipts{&types.Receipt{ + Type: 2, + Status: 1, + Logs: []*types.Log{ + { + BlockNumber: bn, + Address: daddr, + Topics: []common.Hash{ + common.HexToHash("0xa448afda7ea1e3a7a10fcab0c29fe9a9dd85791503bf0171f281521551c7ec05"), + }, + }, + { + BlockNumber: bn, + Address: daddr, + Topics: []common.Hash{ + common.HexToHash("0xc5d8c630ba2fdacb1db24c4599df78c7fb8cf97b5aecde34939597f6697bb1ad"), + common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000000e"), + }, + Data: common.FromHex("0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002100eed82c1026bdd0f23461dd6ca515ef677624e63e6fc0ff91e3672af8eddf579d00000000000000000000000000000000000000000000000000000000000000"), + }, + }, + BlockNumber: big.NewInt(int64(bn)), + }} + id := eth.BlockID{ + Number: bn, + Hash: bhash, + } + l1F.ExpectFetchReceipts(bhash, nil, receipts, nil) + + // we get 1 log successfully filtered as valid status updated contract event + logs, err := da.fetchChallengeLogs(ctx, l1F, id) + require.NoError(t, err) + require.Equal(t, len(logs), 1) + + // commitment is tracked but not canonical + status, comm, err := da.decodeChallengeStatus(logs[0]) + require.NoError(t, err) + + c, has := state.commsByKey[string(comm.Encode())] + require.True(t, has) + require.False(t, c.canonical) + + require.Equal(t, ChallengeActive, status) + // once tracked, set as active based on decoded status + state.SetActiveChallenge(comm.Encode(), bn, pcfg.ResolveWindow) + + // once we request it during derivation it becomes canonical + tracked := state.GetOrTrackChallenge(comm.Encode(), 14, pcfg.ChallengeWindow) + require.True(t, tracked.canonical) + + require.Equal(t, ChallengeActive, tracked.challengeStatus) + require.Equal(t, uint64(14), tracked.blockNumber) + require.Equal(t, bn+pcfg.ResolveWindow, tracked.expiresAt) +} diff --git a/op-plasma/damock.go b/op-plasma/damock.go new file mode 100644 index 000000000000..f21e80df25e0 --- /dev/null +++ b/op-plasma/damock.go @@ -0,0 +1,99 @@ +package plasma + +import ( + "context" + "errors" + "io" + + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/ethdb/memorydb" + "github.com/ethereum/go-ethereum/log" +) + +// MockDAClient mocks a DA storage provider to avoid running an HTTP DA server +// in unit tests. +type MockDAClient struct { + store ethdb.KeyValueStore + log log.Logger +} + +func NewMockDAClient(log log.Logger) *MockDAClient { + return &MockDAClient{ + store: memorydb.New(), + log: log, + } +} + +func (c *MockDAClient) GetInput(ctx context.Context, key Keccak256Commitment) ([]byte, error) { + bytes, err := c.store.Get(key.Encode()) + if err != nil { + return nil, ErrNotFound + } + return bytes, nil +} + +func (c *MockDAClient) SetInput(ctx context.Context, data []byte) (Keccak256Commitment, error) { + key := Keccak256(data) + return key, c.store.Put(key.Encode(), data) +} + +func (c *MockDAClient) DeleteData(key []byte) error { + return c.store.Delete(key) +} + +type DAErrFaker struct { + Client *MockDAClient + + getInputErr error + setInputErr error +} + +func (f *DAErrFaker) GetInput(ctx context.Context, key Keccak256Commitment) ([]byte, error) { + if err := f.getInputErr; err != nil { + f.getInputErr = nil + return nil, err + } + return f.Client.GetInput(ctx, key) +} + +func (f *DAErrFaker) SetInput(ctx context.Context, data []byte) (Keccak256Commitment, error) { + if err := f.setInputErr; err != nil { + f.setInputErr = nil + return nil, err + } + return f.Client.SetInput(ctx, data) +} + +func (f *DAErrFaker) ActGetPreImageFail() { + f.getInputErr = errors.New("get input failed") +} + +func (f *DAErrFaker) ActSetPreImageFail() { + f.setInputErr = errors.New("set input failed") +} + +var Disabled = &PlasmaDisabled{} + +var ErrNotEnabled = errors.New("plasma not enabled") + +// PlasmaDisabled is a noop plasma DA implementation for stubbing. +type PlasmaDisabled struct{} + +func (d *PlasmaDisabled) GetInput(ctx context.Context, l1 L1Fetcher, commitment Keccak256Commitment, blockId eth.BlockID) (eth.Data, error) { + return nil, ErrNotEnabled +} + +func (d *PlasmaDisabled) Reset(ctx context.Context, base eth.L1BlockRef, baseCfg eth.SystemConfig) error { + return io.EOF +} + +func (d *PlasmaDisabled) Finalize(ref eth.L1BlockRef) { +} + +func (d *PlasmaDisabled) OnFinalizedHeadSignal(f HeadSignalFn) { +} + +func (d *PlasmaDisabled) AdvanceL1Origin(ctx context.Context, l1 L1Fetcher, blockId eth.BlockID) error { + return ErrNotEnabled +} diff --git a/op-plasma/dastate.go b/op-plasma/dastate.go new file mode 100644 index 000000000000..c6fee4800af9 --- /dev/null +++ b/op-plasma/dastate.go @@ -0,0 +1,228 @@ +package plasma + +import ( + "container/heap" + "errors" + "fmt" + + "github.com/ethereum/go-ethereum/log" +) + +// ErrReorgRequired is returned when a commitment was derived but for which the challenge expired. +// This requires a reorg to rederive without the input even if the input was previously available. +var ErrReorgRequired = errors.New("reorg required") + +type ChallengeStatus uint8 + +const ( + ChallengeUninitialized ChallengeStatus = iota + ChallengeActive + ChallengeResolved + ChallengeExpired +) + +// Commitment keeps track of the onchain state of an input commitment. +type Commitment struct { + key []byte // the encoded commitment + input []byte // the input itself if it was resolved onchain + expiresAt uint64 // represents the block number after which the commitment can no longer be challenged or if challenged no longer be resolved. + blockNumber uint64 // block where the commitment is included as calldata to the batcher inbox + challengeStatus ChallengeStatus // latest known challenge status + canonical bool // whether the commitment was derived as part of the canonical chain if canonical it will be in comms queue if not in the pendingComms queue. +} + +// CommQueue is a priority queue of commitments ordered by block number. +type CommQueue []*Commitment + +var _ heap.Interface = (*CommQueue)(nil) + +func (c CommQueue) Len() int { return len(c) } + +// we want the first item in the queue to have the lowest block number +func (c CommQueue) Less(i, j int) bool { + return c[i].blockNumber < c[j].blockNumber +} + +func (c CommQueue) Swap(i, j int) { + c[i], c[j] = c[j], c[i] +} + +func (c *CommQueue) Push(x any) { + *c = append(*c, x.(*Commitment)) +} + +func (c *CommQueue) Pop() any { + old := *c + n := len(old) + item := old[n-1] + old[n-1] = nil // avoid memory leak + *c = old[0 : n-1] + return item +} + +// State tracks the commitment and their challenges in order of l1 inclusion. +type State struct { + activeComms CommQueue + expiredComms CommQueue + commsByKey map[string]*Commitment + log log.Logger + metrics Metricer + finalized uint64 +} + +func NewState(log log.Logger, m Metricer) *State { + return &State{ + activeComms: make(CommQueue, 0), + expiredComms: make(CommQueue, 0), + commsByKey: make(map[string]*Commitment), + log: log, + metrics: m, + } +} + +// IsTracking returns whether we currently have a commitment for the given key. +// if the block number is mismatched we return false to ignore the challenge. +func (s *State) IsTracking(key []byte, bn uint64) bool { + if c, ok := s.commsByKey[string(key)]; ok { + return c.blockNumber == bn + } + // track the commitment knowing we may be in detached head and not have seen + // the commitment in the inbox yet. + s.TrackDetachedCommitment(key, bn) + return true +} + +// TrackDetachedCommitment is used for indexing challenges for commitments that have not yet +// been derived due to the derivation pipeline being stalled pending a commitment to be challenged. +// Memory usage is bound to L1 block space during the DA windows, so it is hard and expensive to spam. +// Note that the challenge status and expiration is updated separately after it is tracked. +func (s *State) TrackDetachedCommitment(key []byte, bn uint64) { + c := &Commitment{ + key: key, + expiresAt: bn, + blockNumber: bn, + canonical: false, + } + s.log.Debug("tracking detached commitment", "blockNumber", c.blockNumber, "commitment", fmt.Sprintf("%x", key)) + heap.Push(&s.activeComms, c) + s.commsByKey[string(key)] = c +} + +// SetActiveChallenge switches the state of a given commitment to active challenge. Noop if +// the commitment is not tracked as we don't want to track challenges for invalid commitments. +func (s *State) SetActiveChallenge(key []byte, challengedAt uint64, resolveWindow uint64) { + if c, ok := s.commsByKey[string(key)]; ok { + c.expiresAt = challengedAt + resolveWindow + c.challengeStatus = ChallengeActive + s.metrics.RecordActiveChallenge(c.blockNumber, challengedAt, key) + } +} + +// SetResolvedChallenge switches the state of a given commitment to resolved. Noop if +// the commitment is not tracked as we don't want to track challenges for invalid commitments. +// The input posted onchain is stored in the state for later retrieval. +func (s *State) SetResolvedChallenge(key []byte, input []byte, resolvedAt uint64) { + if c, ok := s.commsByKey[string(key)]; ok { + c.challengeStatus = ChallengeResolved + c.expiresAt = resolvedAt + c.input = input + s.metrics.RecordResolvedChallenge(key) + } +} + +// SetInputCommitment initializes a new commitment and adds it to the state. +// This is called when we see a commitment during derivation so we can refer to it later in +// challenges. +func (s *State) SetInputCommitment(key []byte, committedAt uint64, challengeWindow uint64) *Commitment { + c := &Commitment{ + key: key, + expiresAt: committedAt + challengeWindow, + blockNumber: committedAt, + canonical: true, + } + s.log.Debug("append commitment", "expiresAt", c.expiresAt, "blockNumber", c.blockNumber) + heap.Push(&s.activeComms, c) + s.commsByKey[string(key)] = c + + return c +} + +// GetOrTrackChallenge returns the commitment for the given key if it is already tracked, or +// initializes a new commitment and adds it to the state. +func (s *State) GetOrTrackChallenge(key []byte, bn uint64, challengeWindow uint64) *Commitment { + if c, ok := s.commsByKey[string(key)]; ok { + // commitments previously introduced by challenge events are marked as canonical + c.canonical = true + return c + } + return s.SetInputCommitment(key, bn, challengeWindow) +} + +// GetResolvedInput returns the input bytes if the commitment was resolved onchain. +func (s *State) GetResolvedInput(key []byte) ([]byte, error) { + if c, ok := s.commsByKey[string(key)]; ok { + return c.input, nil + } + return nil, errors.New("commitment not found") +} + +// ExpireChallenges walks back from the oldest commitment to find the latest l1 origin +// for which input data can no longer be challenged. It also marks any active challenges +// as expired based on the new latest l1 origin. If any active challenges are expired +// it returns an error to signal that a derivation pipeline reset is required. +func (s *State) ExpireChallenges(bn uint64) (uint64, error) { + var err error + for s.activeComms.Len() > 0 && s.activeComms[0].expiresAt <= bn && s.activeComms[0].blockNumber > s.finalized { + // move from the active to the expired queue + c := heap.Pop(&s.activeComms).(*Commitment) + heap.Push(&s.expiredComms, c) + + if c.canonical { + // advance finalized head only if the commitment was derived as part of the canonical chain + s.finalized = c.blockNumber + } + + // active mark as expired so it is skipped in the derivation pipeline + if c.challengeStatus == ChallengeActive { + c.challengeStatus = ChallengeExpired + + // only reorg if canonical. If the pipeline is behind, it will just + // get skipped once it catches up. If it is spam, it will be pruned + // with no effect. + if c.canonical { + err = ErrReorgRequired + s.metrics.RecordExpiredChallenge(c.key) + } + } + } + + return s.finalized, err +} + +// safely prune in case reset is deeper than the finalized l1 +const commPruneMargin = 200 + +// Prune removes commitments once they can no longer be challenged or resolved. +// the finalized head block number is passed so we can safely remove any commitments +// with finalized block numbers. +func (s *State) Prune(bn uint64) { + if bn > commPruneMargin { + bn -= commPruneMargin + } else { + bn = 0 + } + for s.expiredComms.Len() > 0 && s.expiredComms[0].blockNumber < bn { + c := heap.Pop(&s.expiredComms).(*Commitment) + s.log.Debug("prune commitment", "expiresAt", c.expiresAt, "blockNumber", c.blockNumber) + delete(s.commsByKey, string(c.key)) + } +} + +// In case of L1 reorg, state should be cleared so we can sync all the challenge events +// from scratch. +func (s *State) Reset() { + s.activeComms = s.activeComms[:0] + s.expiredComms = s.expiredComms[:0] + s.finalized = 0 + clear(s.commsByKey) +} diff --git a/op-plasma/metrics.go b/op-plasma/metrics.go new file mode 100644 index 000000000000..9843e91f3863 --- /dev/null +++ b/op-plasma/metrics.go @@ -0,0 +1,73 @@ +package plasma + +import ( + "github.com/ethereum-optimism/optimism/op-service/metrics" + "github.com/prometheus/client_golang/prometheus" +) + +type Metricer interface { + RecordActiveChallenge(commBlock uint64, startBlock uint64, hash []byte) + RecordResolvedChallenge(hash []byte) + RecordExpiredChallenge(hash []byte) + RecordChallengesHead(name string, num uint64) + RecordStorageError() +} + +type Metrics struct { + ChallengesStatus *prometheus.GaugeVec + ChallengesHead *prometheus.GaugeVec + + StorageErrors *metrics.Event +} + +var _ Metricer = (*Metrics)(nil) + +func MakeMetrics(ns string, factory metrics.Factory) *Metrics { + return &Metrics{ + ChallengesStatus: factory.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: ns, + Name: "challenges_status", + Help: "Gauge representing the status of challenges synced", + }, []string{"status"}), + ChallengesHead: factory.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: ns, + Name: "challenges_head", + Help: "Gauge representing the l1 heads of challenges synced", + }, []string{"type"}), + StorageErrors: metrics.NewEvent(factory, ns, "", "storage_errors", "errors when fetching or uploading to storage service"), + } +} + +func (m *Metrics) RecordChallenge(status string) { + m.ChallengesStatus.WithLabelValues(status).Inc() +} + +// RecordActiveChallenge records when a commitment is challenged including the block where the commitment +// is included, the block where the commitment was challenged and the commitment hash. +func (m *Metrics) RecordActiveChallenge(commBlock uint64, startBlock uint64, hash []byte) { + m.RecordChallenge("active") +} + +func (m *Metrics) RecordResolvedChallenge(hash []byte) { + m.RecordChallenge("resolved") +} + +func (m *Metrics) RecordExpiredChallenge(hash []byte) { + m.RecordChallenge("expired") +} + +func (m *Metrics) RecordStorageError() { + m.StorageErrors.Record() +} + +func (m *Metrics) RecordChallengesHead(name string, num uint64) { + m.ChallengesHead.WithLabelValues(name).Set(float64(num)) +} + +type NoopMetrics struct{} + +func (m *NoopMetrics) RecordActiveChallenge(commBlock uint64, startBlock uint64, hash []byte) {} +func (m *NoopMetrics) RecordResolvedChallenge(hash []byte) {} +func (m *NoopMetrics) RecordExpiredChallenge(hash []byte) {} +func (m *NoopMetrics) RecordChallengesHead(name string, num uint64) {} +func (m *NoopMetrics) RecordStorageError() {} diff --git a/op-plasma/params.go b/op-plasma/params.go new file mode 100644 index 000000000000..e176c207919a --- /dev/null +++ b/op-plasma/params.go @@ -0,0 +1,11 @@ +package plasma + +// Max input size ensures the canonical chain cannot include input batches too large to +// challenge in the Data Availability Challenge contract. Value in number of bytes. +// This value can only be changed in a hard fork. +const MaxInputSize = 130672 + +// TxDataVersion1 is the version number for batcher transactions containing +// plasma commitments. It should not collide with DerivationVersion which is still +// used downstream when parsing the frames. +const TxDataVersion1 = 1 diff --git a/op-preimage/iface.go b/op-preimage/iface.go index 8ccb7b84a599..c1835c0797d0 100644 --- a/op-preimage/iface.go +++ b/op-preimage/iface.go @@ -34,6 +34,14 @@ const ( LocalKeyType KeyType = 1 // Keccak256KeyType is for keccak256 pre-images, for any global shared pre-images. Keccak256KeyType KeyType = 2 + // GlobalGenericKeyType is a reserved key type for generic global data. + GlobalGenericKeyType KeyType = 3 + // Sha256KeyType is for sha256 pre-images, for any global shared pre-images. + Sha256KeyType KeyType = 4 + // BlobKeyType is for blob point pre-images. + BlobKeyType KeyType = 5 + // PrecompileKeyType is for precompile result pre-images. + PrecompileKeyType KeyType = 6 ) // LocalIndexKey is a key local to the program, indexing a special program input. @@ -62,6 +70,57 @@ func (k Keccak256Key) TerminalString() string { return "0x" + hex.EncodeToString(k[:]) } +// Sha256Key wraps a sha256 hash to use it as a typed pre-image key.hash +type Sha256Key [32]byte + +func (k Sha256Key) PreimageKey() (out [32]byte) { + out = k + out[0] = byte(Sha256KeyType) + return +} + +func (k Sha256Key) String() string { + return "0x" + hex.EncodeToString(k[:]) +} + +func (k Sha256Key) TerminalString() string { + return "0x" + hex.EncodeToString(k[:]) +} + +// BlobKey is the hash of a blob commitment and `z` value to use as a preimage key for `y`. +type BlobKey [32]byte + +func (k BlobKey) PreimageKey() (out [32]byte) { + out = k + out[0] = byte(BlobKeyType) + return +} + +func (k BlobKey) String() string { + return "0x" + hex.EncodeToString(k[:]) +} + +func (k BlobKey) TerminalString() string { + return "0x" + hex.EncodeToString(k[:]) +} + +// PrecompileKey is the hash of precompile address and its input data +type PrecompileKey [32]byte + +func (k PrecompileKey) PreimageKey() (out [32]byte) { + out = k + out[0] = byte(PrecompileKeyType) + return +} + +func (k PrecompileKey) String() string { + return "0x" + hex.EncodeToString(k[:]) +} + +func (k PrecompileKey) TerminalString() string { + return "0x" + hex.EncodeToString(k[:]) +} + // Hint is an interface to enable any program type to function as a hint, // when passed to the Hinter interface, returning a string representation // of what data the host should prepare pre-images for. diff --git a/op-preimage/iface_test.go b/op-preimage/iface_test.go new file mode 100644 index 000000000000..b7eb05c98a93 --- /dev/null +++ b/op-preimage/iface_test.go @@ -0,0 +1,80 @@ +package preimage + +import ( + "encoding/binary" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestPreimageKeyTypes(t *testing.T) { + t.Run("LocalIndexKey", func(t *testing.T) { + actual := LocalIndexKey(0xFFFFFFFF) + + // PreimageKey encoding + expected := [32]byte{} + expected[0] = byte(LocalKeyType) + binary.BigEndian.PutUint64(expected[24:], 0xFFFFFFFF) + require.Equal(t, expected, actual.PreimageKey()) + }) + + t.Run("Keccak256Key", func(t *testing.T) { + fauxHash := [32]byte{} + fauxHash[31] = 0xFF + actual := Keccak256Key(fauxHash) + + // PreimageKey encoding + expected := [32]byte{} + expected[0] = byte(Keccak256KeyType) + expected[31] = 0xFF + require.Equal(t, expected, actual.PreimageKey()) + + // String encoding + require.Equal(t, "0x00000000000000000000000000000000000000000000000000000000000000ff", actual.String()) + }) + + t.Run("Sha256Key", func(t *testing.T) { + fauxHash := [32]byte{} + fauxHash[31] = 0xFF + actual := Sha256Key(fauxHash) + + // PreimageKey encoding + expected := [32]byte{} + expected[0] = byte(Sha256KeyType) + expected[31] = 0xFF + require.Equal(t, expected, actual.PreimageKey()) + + // String encoding + require.Equal(t, "0x00000000000000000000000000000000000000000000000000000000000000ff", actual.String()) + }) + + t.Run("BlobKey", func(t *testing.T) { + fauxHash := [32]byte{} + fauxHash[31] = 0xFF + actual := BlobKey(fauxHash) + + // PreimageKey encoding + expected := [32]byte{} + expected[0] = byte(BlobKeyType) + expected[31] = 0xFF + require.Equal(t, expected, actual.PreimageKey()) + + // String encoding + require.Equal(t, "0x00000000000000000000000000000000000000000000000000000000000000ff", actual.String()) + }) + + t.Run("KZGPointEvaluationKey", func(t *testing.T) { + fauxHash := [32]byte{} + fauxHash[31] = 0xFF + actual := PrecompileKey(fauxHash) + + // PreimageKey encoding + expected := [32]byte{} + expected[0] = byte(PrecompileKeyType) + expected[31] = 0xFF + require.Equal(t, expected, actual.PreimageKey()) + + // String encoding + require.Equal(t, "0x00000000000000000000000000000000000000000000000000000000000000ff", actual.String()) + }) +} diff --git a/op-preimage/verifier.go b/op-preimage/verifier.go index c780b58edf43..6623d02abe13 100644 --- a/op-preimage/verifier.go +++ b/op-preimage/verifier.go @@ -1,6 +1,7 @@ package preimage import ( + "crypto/sha256" "errors" "fmt" "slices" @@ -28,6 +29,18 @@ func WithVerification(source PreimageGetter) PreimageGetter { return nil, fmt.Errorf("%w for key %v, hash: %v data: %x", ErrIncorrectData, key, hash, data) } return data, nil + case Sha256KeyType: + hash := sha256.Sum256(data) + if !slices.Equal(hash[1:], key[1:]) { + return nil, fmt.Errorf("%w for key %v, hash: %v data: %x", ErrIncorrectData, key, hash, data) + } + return data, nil + case BlobKeyType: + // Can't verify an individual field element without having a kzg proof + return data, nil + case PrecompileKeyType: + // Can't verify precompile result without knowing the input preimage + return data, nil default: return nil, fmt.Errorf("%w: %v", ErrUnsupportedKeyType, key[0]) } diff --git a/op-preimage/verifier_test.go b/op-preimage/verifier_test.go index f0c801efe481..fb2c722c875c 100644 --- a/op-preimage/verifier_test.go +++ b/op-preimage/verifier_test.go @@ -1,7 +1,10 @@ package preimage import ( + "crypto/sha256" "errors" + "fmt" + "reflect" "testing" "github.com/stretchr/testify/require" @@ -10,16 +13,20 @@ import ( func TestWithVerification(t *testing.T) { validData := []byte{1, 2, 3, 4, 5, 6} keccak256Key := Keccak256Key(Keccak256(validData)) + sha256Key := Sha256Key(sha256.Sum256(validData)) anError := errors.New("boom") - tests := []struct { + validKeys := []Key{keccak256Key, sha256Key} + + type testData struct { name string key Key data []byte err error expectedErr error expectedData []byte - }{ + } + tests := []testData{ { name: "LocalKey NoVerification", key: LocalIndexKey(1), @@ -27,29 +34,16 @@ func TestWithVerification(t *testing.T) { expectedData: []byte{4, 3, 5, 7, 3}, }, { - name: "Keccak256 Valid", - key: keccak256Key, - data: validData, - expectedData: validData, - }, - { - name: "Keccak256 Error", - key: keccak256Key, - data: validData, - err: anError, - expectedErr: anError, - }, - { - name: "Keccak256 InvalidData", - key: keccak256Key, - data: []byte{6, 7, 8}, - expectedErr: ErrIncorrectData, + name: "BlobKey NoVerification", + key: BlobKey([32]byte{1, 2, 3, 4}), + data: []byte{4, 3, 5, 7, 3}, + expectedData: []byte{4, 3, 5, 7, 3}, }, { - name: "EmptyData", - key: keccak256Key, - data: []byte{}, - expectedErr: ErrIncorrectData, + name: "KZGPointEvaluationKey NoVerification", + key: PrecompileKey([32]byte{1, 2, 3, 4}), + data: []byte{4, 3, 5, 7, 3}, + expectedData: []byte{4, 3, 5, 7, 3}, }, { name: "UnknownKey", @@ -59,6 +53,36 @@ func TestWithVerification(t *testing.T) { }, } + for _, key := range validKeys { + name := reflect.TypeOf(key).Name() + tests = append(tests, + testData{ + name: fmt.Sprintf("%v-Valid", name), + key: key, + data: validData, + expectedData: validData, + }, + testData{ + name: fmt.Sprintf("%v-Error", name), + key: key, + data: validData, + err: anError, + expectedErr: anError, + }, + testData{ + name: fmt.Sprintf("%v-InvalidData", name), + key: key, + data: []byte{6, 7, 8}, + expectedErr: ErrIncorrectData, + }, + testData{ + name: fmt.Sprintf("%v-EmptyData", name), + key: key, + data: []byte{}, + expectedErr: ErrIncorrectData, + }) + } + for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { diff --git a/op-program/Makefile b/op-program/Makefile index bda07489a8d7..25a8ec3f9005 100644 --- a/op-program/Makefile +++ b/op-program/Makefile @@ -38,21 +38,36 @@ clean: test: go test -v ./... -verify-goerli: op-program-host op-program-client - env GO111MODULE=on go run ./verify/cmd/goerli.go --l1 $$L1URL --l2 $$L2URL +verify-sepolia: op-program-host op-program-client + env GO111MODULE=on go run ./verify/sepolia/cmd/sepolia.go --l1 $$SEPOLIA_L1URL --l1.beacon $$SEPOLIA_BEACON_URL --l2 $$SEPOLIA_L2URL --datadir /tmp/test-sepolia -capture-goerli-verify: op-program-host op-program-client - rm -rf "$(COMPAT_DIR)/goerli" "$(COMPAT_DIR)/goerli.tar.bz" - env GO111MODULE=on go run ./verify/cmd/goerli.go --l1 $$L1URL --l2 $$L2URL --datadir "$(COMPAT_DIR)/goerli" - tar jcf "$(COMPAT_DIR)/goerli.tar.bz" -C "$(COMPAT_DIR)" goerli +capture-mainnet-genesis: op-program-host op-program-client + rm -rf "$(COMPAT_DIR)/mainnet-genesis" "$(COMPAT_DIR)/mainnet-genesis.tar.bz" + env GO111MODULE=on go run ./verify/mainnet/cmd/mainnet.go --l1 $$MAINNET_L1URL --l1.beacon $$MAINNET_BEACON_URL --l2 $$MAINNET_L2URL --datadir "$(COMPAT_DIR)/mainnet-genesis" --l1.head "0x4903424f6cc2cfba7c2bf8c8f48ca46721c963fa64b411cfee3697b781e3e5f1" --l2.start "105235063" --l2.end "105235064" + tar jcf "$(COMPAT_DIR)/mainnet-genesis.tar.bz" -C "$(COMPAT_DIR)" mainnet-genesis -capture-chain-test-data: capture-goerli-verify +capture-sepolia-delta: op-program-host op-program-client + rm -rf "$(COMPAT_DIR)/sepolia-delta" "$(COMPAT_DIR)/sepolia-delta.tar.bz" + env GO111MODULE=on go run ./verify/sepolia/cmd/sepolia.go --l1 $$SEPOLIA_L1URL --l1.beacon $$SEPOLIA_BEACON_URL --l2 $$SEPOLIA_L2URL --datadir "$(COMPAT_DIR)/sepolia-delta" --l1.head "0x935428728bcfcfeb2e5ba9175fd2890e52831dae221aa4d5dcffed8320edc001" --l2.start "8728200" --l2.end "8728320" + tar jcf "$(COMPAT_DIR)/sepolia-delta.tar.bz" -C "$(COMPAT_DIR)" sepolia-delta -run-goerli-verify: op-program-host op-program-client - mkdir -p "$(COMPAT_DIR)" - curl -L -o "$(COMPAT_DIR)/goerli.tar.bz" https://github.com/ethereum-optimism/chain-test-data/releases/download/2023-10-11/goerli.tar.bz - tar jxf "$(COMPAT_DIR)/goerli.tar.bz" -C "$(COMPAT_DIR)" - ./bin/op-program `cat "$(COMPAT_DIR)/goerli/args.txt"` +capture-sepolia-ecotone: op-program-host op-program-client + rm -rf "$(COMPAT_DIR)/sepolia-ecotone" "$(COMPAT_DIR)/sepolia-ecotone.tar.bz" + env GO111MODULE=on go run ./verify/sepolia/cmd/sepolia.go --l1 $$SEPOLIA_L1URL --l1.beacon $$SEPOLIA_BEACON_URL --l2 $$SEPOLIA_L2URL --datadir "$(COMPAT_DIR)/sepolia-ecotone" --l1.head "0x5d491a8c1e728a4e70720c09fefdaa083681a9421cd365af85220cf8bd4448a3" --l2.start "9205715" --l2.end "9205815" + tar jcf "$(COMPAT_DIR)/sepolia-ecotone.tar.bz" -C "$(COMPAT_DIR)" sepolia-ecotone + +capture-chain-test-data: capture-mainnet-genesis capture-sepolia-delta capture-sepolia-ecotone + +verify-sepolia-delta: op-program-host op-program-client + ./scripts/run-compat.sh "sepolia-delta" + +verify-mainnet-genesis: op-program-host op-program-client + ./scripts/run-compat.sh "mainnet-genesis" + +verify-sepolia-ecotone: op-program-host op-program-client + ./scripts/run-compat.sh "sepolia-ecotone" + +verify-compat: verify-sepolia-delta verify-sepolia-ecotone verify-mainnet-genesis .PHONY: \ op-program \ @@ -61,7 +76,12 @@ run-goerli-verify: op-program-host op-program-client op-program-client-mips \ clean \ test \ - verify-goerli \ capture-goerli-verify \ + verify-sepolia \ + capture-mainnet-genesis \ + capture-sepolia-delta \ + capture-sepolia-ecotone \ capture-chain-test-data \ - run-goerli-verify + run-goerli-verify \ + run-sepolia-verify \ + run-compat diff --git a/op-program/client/boot.go b/op-program/client/boot.go index e0b2de0d71e3..35d6edcb8ad3 100644 --- a/op-program/client/boot.go +++ b/op-program/client/boot.go @@ -22,6 +22,7 @@ const ( // These local keys are only used for custom chains L2ChainConfigLocalIndex RollupConfigLocalIndex + DaConfigIndex ) // CustomChainIDIndicator is used to detect when the program should load custom chain configuration diff --git a/op-program/client/cmd/main.go b/op-program/client/cmd/main.go index 822c48556b6e..d075083e5aa1 100644 --- a/op-program/client/cmd/main.go +++ b/op-program/client/cmd/main.go @@ -13,10 +13,10 @@ func main() { // Default to a machine parsable but relatively human friendly log format. // Don't do anything fancy to detect if color output is supported. logger := oplog.NewLogger(os.Stdout, oplog.CLIConfig{ - Level: log.LvlInfo, + Level: log.LevelInfo, Format: oplog.FormatLogFmt, Color: false, }) - oplog.SetGlobalLogHandler(logger.GetHandler()) + oplog.SetGlobalLogHandler(logger.Handler()) client.Main(logger) } diff --git a/op-program/client/driver/driver.go b/op-program/client/driver/driver.go index 2f98dfb7adb2..aa3449f8f286 100644 --- a/op-program/client/driver/driver.go +++ b/op-program/client/driver/driver.go @@ -7,16 +7,17 @@ import ( "io" "github.com/ethereum-optimism/optimism/op-node/metrics" + "github.com/ethereum-optimism/optimism/op-node/node/safedb" "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/sync" + plasma "github.com/ethereum-optimism/optimism/op-plasma" + "github.com/ethereum-optimism/optimism/op-service/eigenda" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/log" ) -var ( - ErrClaimNotValid = errors.New("invalid claim") -) +var ErrClaimNotValid = errors.New("invalid claim") type Derivation interface { Step(ctx context.Context) error @@ -39,9 +40,9 @@ type Driver struct { targetBlockNum uint64 } -func NewDriver(logger log.Logger, cfg *rollup.Config, l1Source derive.L1Fetcher, l2Source L2Source, targetBlockNum uint64) *Driver { +func NewDriver(logger log.Logger, cfg *rollup.Config, l1Source derive.L1Fetcher, l1BlobsSource derive.L1BlobsFetcher, l2Source L2Source, targetBlockNum uint64, daCfg *eigenda.Config, prefixDerivationEnabled bool) *Driver { engine := derive.NewEngineController(l2Source, logger, metrics.NoopMetrics, cfg, sync.CLSync) - pipeline := derive.NewDerivationPipeline(logger, cfg, l1Source, nil, l2Source, engine, metrics.NoopMetrics, &sync.Config{}) + pipeline := derive.NewDerivationPipeline(logger, cfg, l1Source, l1BlobsSource, plasma.Disabled, l2Source, engine, metrics.NoopMetrics, &sync.Config{}, safedb.Disabled, daCfg, prefixDerivationEnabled) pipeline.Reset() return &Driver{ logger: logger, @@ -84,11 +85,12 @@ func (d *Driver) SafeHead() eth.L2BlockRef { } func (d *Driver) ValidateClaim(l2ClaimBlockNum uint64, claimedOutputRoot eth.Bytes32) error { - outputRoot, err := d.l2OutputRoot(l2ClaimBlockNum) + l2Head := d.SafeHead() + outputRoot, err := d.l2OutputRoot(min(l2ClaimBlockNum, l2Head.Number)) if err != nil { return fmt.Errorf("calculate L2 output root: %w", err) } - d.logger.Info("Validating claim", "head", d.SafeHead(), "output", outputRoot, "claim", claimedOutputRoot) + d.logger.Info("Validating claim", "head", l2Head, "output", outputRoot, "claim", claimedOutputRoot) if claimedOutputRoot != outputRoot { return fmt.Errorf("%w: claim: %v actual: %v", ErrClaimNotValid, claimedOutputRoot, outputRoot) } diff --git a/op-program/client/driver/driver_test.go b/op-program/client/driver/driver_test.go index 0f38735b7bc4..03cda64101ff 100644 --- a/op-program/client/driver/driver_test.go +++ b/op-program/client/driver/driver_test.go @@ -80,6 +80,19 @@ func TestValidateClaim(t *testing.T) { require.NoError(t, err) }) + t.Run("Valid-PriorToSafeHead", func(t *testing.T) { + driver := createDriverWithNextBlock(t, io.EOF, 10) + expected := eth.Bytes32{0x11} + requestedOutputRoot := uint64(0) + driver.l2OutputRoot = func(blockNum uint64) (eth.Bytes32, error) { + requestedOutputRoot = blockNum + return expected, nil + } + err := driver.ValidateClaim(uint64(20), expected) + require.NoError(t, err) + require.Equal(t, uint64(10), requestedOutputRoot) + }) + t.Run("Invalid", func(t *testing.T) { driver := createDriver(t, io.EOF) driver.l2OutputRoot = func(_ uint64) (eth.Bytes32, error) { @@ -89,6 +102,19 @@ func TestValidateClaim(t *testing.T) { require.ErrorIs(t, err, ErrClaimNotValid) }) + t.Run("Invalid-PriorToSafeHead", func(t *testing.T) { + driver := createDriverWithNextBlock(t, io.EOF, 10) + expected := eth.Bytes32{0x11} + requestedOutputRoot := uint64(0) + driver.l2OutputRoot = func(blockNum uint64) (eth.Bytes32, error) { + requestedOutputRoot = blockNum + return expected, nil + } + err := driver.ValidateClaim(uint64(20), eth.Bytes32{0x55}) + require.ErrorIs(t, err, ErrClaimNotValid) + require.Equal(t, uint64(10), requestedOutputRoot) + }) + t.Run("Error", func(t *testing.T) { driver := createDriver(t, io.EOF) expectedErr := errors.New("boom") @@ -107,7 +133,7 @@ func createDriver(t *testing.T, derivationResult error) *Driver { func createDriverWithNextBlock(t *testing.T, derivationResult error, nextBlockNum uint64) *Driver { derivation := &stubDerivation{nextErr: derivationResult, nextBlockNum: nextBlockNum} return &Driver{ - logger: testlog.Logger(t, log.LvlDebug), + logger: testlog.Logger(t, log.LevelDebug), pipeline: derivation, engine: derivation, targetBlockNum: 1_000_000, diff --git a/op-program/client/l1/blob_fetcher.go b/op-program/client/l1/blob_fetcher.go new file mode 100644 index 000000000000..b41082e4d4d8 --- /dev/null +++ b/op-program/client/l1/blob_fetcher.go @@ -0,0 +1,36 @@ +package l1 + +import ( + "context" + "errors" + + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum/go-ethereum/log" +) + +var InvalidHashesLengthError = errors.New("invalid hashes length") + +type BlobFetcher struct { + logger log.Logger + oracle Oracle +} + +var _ = (*derive.L1BlobsFetcher)(nil) + +func NewBlobFetcher(logger log.Logger, oracle Oracle) *BlobFetcher { + return &BlobFetcher{ + logger: logger, + oracle: oracle, + } +} + +// GetBlobs fetches blobs that were confirmed in the given L1 block with the given indexed blob hashes. +func (b *BlobFetcher) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) { + blobs := make([]*eth.Blob, len(hashes)) + for i := 0; i < len(hashes); i++ { + b.logger.Info("Fetching blob", "l1_ref", ref.Hash, "blob_versioned_hash", hashes[i].Hash, "index", hashes[i].Index) + blobs[i] = b.oracle.GetBlob(ref, hashes[i]) + } + return blobs, nil +} diff --git a/op-program/client/l1/cache.go b/op-program/client/l1/cache.go index bb484cc50d8b..5541779f9755 100644 --- a/op-program/client/l1/cache.go +++ b/op-program/client/l1/cache.go @@ -1,10 +1,13 @@ package l1 import ( + "encoding/binary" + "github.com/hashicorp/golang-lru/v2/simplelru" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -18,17 +21,28 @@ type CachingOracle struct { blocks *simplelru.LRU[common.Hash, eth.BlockInfo] txs *simplelru.LRU[common.Hash, types.Transactions] rcpts *simplelru.LRU[common.Hash, types.Receipts] + blobs *simplelru.LRU[common.Hash, *eth.Blob] + pcmps *simplelru.LRU[common.Hash, precompileResult] +} + +type precompileResult struct { + result []byte + ok bool } func NewCachingOracle(oracle Oracle) *CachingOracle { blockLRU, _ := simplelru.NewLRU[common.Hash, eth.BlockInfo](cacheSize, nil) txsLRU, _ := simplelru.NewLRU[common.Hash, types.Transactions](cacheSize, nil) rcptsLRU, _ := simplelru.NewLRU[common.Hash, types.Receipts](cacheSize, nil) + blobsLRU, _ := simplelru.NewLRU[common.Hash, *eth.Blob](cacheSize, nil) + pcmps, _ := simplelru.NewLRU[common.Hash, precompileResult](cacheSize, nil) return &CachingOracle{ oracle: oracle, blocks: blockLRU, txs: txsLRU, rcpts: rcptsLRU, + blobs: blobsLRU, + pcmps: pcmps, } } @@ -63,3 +77,30 @@ func (o *CachingOracle) ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInf o.rcpts.Add(blockHash, rcpts) return block, rcpts } + +func (o *CachingOracle) GetBlob(ref eth.L1BlockRef, blobHash eth.IndexedBlobHash) *eth.Blob { + // Create a 32 byte hash key by hashing `blobHash.Hash ++ ref.Time ++ blobHash.Index` + hashBuf := make([]byte, 48) + copy(hashBuf[0:32], blobHash.Hash[:]) + binary.BigEndian.PutUint64(hashBuf[32:], ref.Time) + binary.BigEndian.PutUint64(hashBuf[40:], blobHash.Index) + cacheKey := crypto.Keccak256Hash(hashBuf) + + blob, ok := o.blobs.Get(cacheKey) + if ok { + return blob + } + blob = o.oracle.GetBlob(ref, blobHash) + o.blobs.Add(cacheKey, blob) + return blob +} + +func (o *CachingOracle) Precompile(address common.Address, input []byte) ([]byte, bool) { + cacheKey := crypto.Keccak256Hash(append(address.Bytes(), input...)) + if val, ok := o.pcmps.Get(cacheKey); ok { + return val.result, val.ok + } + res, ok := o.oracle.Precompile(address, input) + o.pcmps.Add(cacheKey, precompileResult{res, ok}) + return res, ok +} diff --git a/op-program/client/l1/cache_test.go b/op-program/client/l1/cache_test.go index c3b702bd9f78..1c6da3ddeeab 100644 --- a/op-program/client/l1/cache_test.go +++ b/op-program/client/l1/cache_test.go @@ -7,6 +7,8 @@ import ( "github.com/ethereum-optimism/optimism/op-program/client/l1/test" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testutils" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" ) @@ -71,3 +73,44 @@ func TestCachingOracle_ReceiptsByBlockHash(t *testing.T) { require.Equal(t, eth.BlockToInfo(block), actualBlock) require.EqualValues(t, rcpts, actualRcpts) } + +func TestCachingOracle_GetBlobs(t *testing.T) { + stub := test.NewStubOracle(t) + oracle := NewCachingOracle(stub) + + l1BlockRef := eth.L1BlockRef{Time: 0} + indexedBlobHash := eth.IndexedBlobHash{Hash: [32]byte{0xFA, 0xCA, 0xDE}, Index: 0} + blob := eth.Blob{0xFF} + + // Initial call retrieves from the stub + stub.Blobs[l1BlockRef] = make(map[eth.IndexedBlobHash]*eth.Blob) + stub.Blobs[l1BlockRef][indexedBlobHash] = &blob + actualBlob := oracle.GetBlob(l1BlockRef, indexedBlobHash) + require.Equal(t, &blob, actualBlob) + + // Later calls should retrieve from cache + delete(stub.Blobs[l1BlockRef], indexedBlobHash) + actualBlob = oracle.GetBlob(l1BlockRef, indexedBlobHash) + require.Equal(t, &blob, actualBlob) +} + +func TestCachingOracle_Precompile(t *testing.T) { + stub := test.NewStubOracle(t) + oracle := NewCachingOracle(stub) + + input := []byte{0x01, 0x02, 0x03, 0x04} + output := []byte{0x0a, 0x0b, 0x0c, 0x0d} + addr := common.Address{0x1} + + // Initial call retrieves from the stub + stub.PcmpResults[crypto.Keccak256Hash(append(addr.Bytes(), input...))] = output + actualResult, actualStatus := oracle.Precompile(addr, input) + require.True(t, actualStatus) + require.EqualValues(t, output, actualResult) + + // Later calls should retrieve from cache + delete(stub.PcmpResults, crypto.Keccak256Hash(append(addr.Bytes(), input...))) + actualResult, actualStatus = oracle.Precompile(addr, input) + require.True(t, actualStatus) + require.EqualValues(t, output, actualResult) +} diff --git a/op-program/client/l1/client_test.go b/op-program/client/l1/client_test.go index 8333b4a70590..4e03f92baa94 100644 --- a/op-program/client/l1/client_test.go +++ b/op-program/client/l1/client_test.go @@ -164,7 +164,7 @@ func TestL1BlockRefByNumber(t *testing.T) { func newClient(t *testing.T) (*OracleL1Client, *test.StubOracle) { stub := test.NewStubOracle(t) stub.Blocks[head.Hash()] = head - client := NewOracleL1Client(testlog.Logger(t, log.LvlDebug), stub, head.Hash()) + client := NewOracleL1Client(testlog.Logger(t, log.LevelDebug), stub, head.Hash()) return client, stub } diff --git a/op-program/client/l1/hints.go b/op-program/client/l1/hints.go index 1383f6a295f4..0a1ceabaa956 100644 --- a/op-program/client/l1/hints.go +++ b/op-program/client/l1/hints.go @@ -2,6 +2,7 @@ package l1 import ( "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" preimage "github.com/ethereum-optimism/optimism/op-preimage" ) @@ -10,6 +11,8 @@ const ( HintL1BlockHeader = "l1-block-header" HintL1Transactions = "l1-transactions" HintL1Receipts = "l1-receipts" + HintL1Blob = "l1-blob" + HintL1Precompile = "l1-precompile" ) type BlockHeaderHint common.Hash @@ -35,3 +38,19 @@ var _ preimage.Hint = ReceiptsHint{} func (l ReceiptsHint) Hint() string { return HintL1Receipts + " " + (common.Hash)(l).String() } + +type BlobHint []byte + +var _ preimage.Hint = BlobHint{} + +func (l BlobHint) Hint() string { + return HintL1Blob + " " + hexutil.Encode(l) +} + +type PrecompileHint []byte + +var _ preimage.Hint = PrecompileHint{} + +func (l PrecompileHint) Hint() string { + return HintL1Precompile + " " + hexutil.Encode(l) +} diff --git a/op-program/client/l1/oracle.go b/op-program/client/l1/oracle.go index 736606116555..7bec829c8b6c 100644 --- a/op-program/client/l1/oracle.go +++ b/op-program/client/l1/oracle.go @@ -1,10 +1,13 @@ package l1 import ( + "encoding/binary" "fmt" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" preimage "github.com/ethereum-optimism/optimism/op-preimage" @@ -21,6 +24,12 @@ type Oracle interface { // ReceiptsByBlockHash retrieves the receipts from the block with the given hash. ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Receipts) + + // GetBlob retrieves the blob with the given hash. + GetBlob(ref eth.L1BlockRef, blobHash eth.IndexedBlobHash) *eth.Blob + + // Precompile retrieves the result and success indicator of a precompile call for the given input. + Precompile(precompileAddress common.Address, input []byte) ([]byte, bool) } // PreimageOracle implements Oracle using by interfacing with the pure preimage.Oracle @@ -86,3 +95,37 @@ func (p *PreimageOracle) ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockIn return info, receipts } + +func (p *PreimageOracle) GetBlob(ref eth.L1BlockRef, blobHash eth.IndexedBlobHash) *eth.Blob { + // Send a hint for the blob commitment & blob field elements. + blobReqMeta := make([]byte, 16) + binary.BigEndian.PutUint64(blobReqMeta[0:8], blobHash.Index) + binary.BigEndian.PutUint64(blobReqMeta[8:16], ref.Time) + p.hint.Hint(BlobHint(append(blobHash.Hash[:], blobReqMeta...))) + + commitment := p.oracle.Get(preimage.Sha256Key(blobHash.Hash)) + + // Reconstruct the full blob from the 4096 field elements. + blob := eth.Blob{} + fieldElemKey := make([]byte, 80) + copy(fieldElemKey[:48], commitment) + for i := 0; i < params.BlobTxFieldElementsPerBlob; i++ { + binary.BigEndian.PutUint64(fieldElemKey[72:], uint64(i)) + fieldElement := p.oracle.Get(preimage.BlobKey(crypto.Keccak256(fieldElemKey))) + + copy(blob[i<<5:(i+1)<<5], fieldElement[:]) + } + + return &blob +} + +func (p *PreimageOracle) Precompile(address common.Address, input []byte) ([]byte, bool) { + hintBytes := append(address.Bytes(), input...) + p.hint.Hint(PrecompileHint(hintBytes)) + key := preimage.PrecompileKey(crypto.Keccak256Hash(hintBytes)) + result := p.oracle.Get(key) + if len(result) == 0 { // must contain at least the status code + panic(fmt.Errorf("unexpected precompile oracle behavior, got result: %x", result)) + } + return result[1:], result[0] == 1 +} diff --git a/op-program/client/l1/test/stub_oracle.go b/op-program/client/l1/test/stub_oracle.go index 5033e06d74b1..6c154b04ef5a 100644 --- a/op-program/client/l1/test/stub_oracle.go +++ b/op-program/client/l1/test/stub_oracle.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" ) type StubOracle struct { @@ -19,16 +20,25 @@ type StubOracle struct { // Rcpts maps Block hash to receipts Rcpts map[common.Hash]types.Receipts + + // Blobs maps indexed blob hash to l1 block ref to blob + Blobs map[eth.L1BlockRef]map[eth.IndexedBlobHash]*eth.Blob + + // PcmpResults maps hashed input to the results of precompile calls + PcmpResults map[common.Hash][]byte } func NewStubOracle(t *testing.T) *StubOracle { return &StubOracle{ - t: t, - Blocks: make(map[common.Hash]eth.BlockInfo), - Txs: make(map[common.Hash]types.Transactions), - Rcpts: make(map[common.Hash]types.Receipts), + t: t, + Blocks: make(map[common.Hash]eth.BlockInfo), + Txs: make(map[common.Hash]types.Transactions), + Rcpts: make(map[common.Hash]types.Receipts), + Blobs: make(map[eth.L1BlockRef]map[eth.IndexedBlobHash]*eth.Blob), + PcmpResults: make(map[common.Hash][]byte), } } + func (o StubOracle) HeaderByBlockHash(blockHash common.Hash) eth.BlockInfo { info, ok := o.Blocks[blockHash] if !ok { @@ -52,3 +62,23 @@ func (o StubOracle) ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInfo, t } return o.HeaderByBlockHash(blockHash), rcpts } + +func (o StubOracle) GetBlob(ref eth.L1BlockRef, blobHash eth.IndexedBlobHash) *eth.Blob { + blobMap, ok := o.Blobs[ref] + if !ok { + o.t.Fatalf("unknown blob ref %s", ref) + } + blob, ok := blobMap[blobHash] + if !ok { + o.t.Fatalf("unknown blob hash %s %d", blobHash.Hash, blobHash.Index) + } + return blob +} + +func (o StubOracle) Precompile(addr common.Address, input []byte) ([]byte, bool) { + result, ok := o.PcmpResults[crypto.Keccak256Hash(append(addr.Bytes(), input...))] + if !ok { + o.t.Fatalf("unknown kzg point evaluation %x", input) + } + return result, true +} diff --git a/op-program/client/l2/engine.go b/op-program/client/l2/engine.go index 260561bccee3..b3040187138c 100644 --- a/op-program/client/l2/engine.go +++ b/op-program/client/l2/engine.go @@ -15,9 +15,7 @@ import ( "github.com/ethereum/go-ethereum/log" ) -var ( - ErrNotFound = errors.New("not found") -) +var ErrNotFound = errors.New("not found") type OracleEngine struct { api *engineapi.L2EngineAPI @@ -43,15 +41,24 @@ func (o *OracleEngine) L2OutputRoot(l2ClaimBlockNum uint64) (eth.Bytes32, error) if err != nil { return eth.Bytes32{}, fmt.Errorf("failed to open L2 state db at block %s: %w", outBlock.Hash(), err) } - withdrawalsTrie, err := stateDB.Database().OpenStorageTrie(outBlock.Root, predeploys.L2ToL1MessagePasserAddr, stateDB.GetStorageRoot(predeploys.L2ToL1MessagePasserAddr)) + withdrawalsTrie, err := stateDB.OpenStorageTrie(predeploys.L2ToL1MessagePasserAddr) if err != nil { return eth.Bytes32{}, fmt.Errorf("withdrawals trie unavailable at block %v: %w", outBlock.Hash(), err) } return rollup.ComputeL2OutputRootV0(eth.HeaderBlockInfo(outBlock), withdrawalsTrie.Hash()) } -func (o *OracleEngine) GetPayload(ctx context.Context, payloadId eth.PayloadID) (*eth.ExecutionPayloadEnvelope, error) { - res, err := o.api.GetPayloadV3(ctx, payloadId) +func (o *OracleEngine) GetPayload(ctx context.Context, payloadInfo eth.PayloadInfo) (*eth.ExecutionPayloadEnvelope, error) { + var res *eth.ExecutionPayloadEnvelope + var err error + switch method := o.rollupCfg.GetPayloadVersion(payloadInfo.Timestamp); method { + case eth.GetPayloadV3: + res, err = o.api.GetPayloadV3(ctx, payloadInfo.ID) + case eth.GetPayloadV2: + res, err = o.api.GetPayloadV2(ctx, payloadInfo.ID) + default: + return nil, fmt.Errorf("unsupported GetPayload version: %s", method) + } if err != nil { return nil, err } @@ -59,14 +66,26 @@ func (o *OracleEngine) GetPayload(ctx context.Context, payloadId eth.PayloadID) } func (o *OracleEngine) ForkchoiceUpdate(ctx context.Context, state *eth.ForkchoiceState, attr *eth.PayloadAttributes) (*eth.ForkchoiceUpdatedResult, error) { - return o.api.ForkchoiceUpdatedV3(ctx, state, attr) + switch method := o.rollupCfg.ForkchoiceUpdatedVersion(attr); method { + case eth.FCUV3: + return o.api.ForkchoiceUpdatedV3(ctx, state, attr) + case eth.FCUV2: + return o.api.ForkchoiceUpdatedV2(ctx, state, attr) + case eth.FCUV1: + return o.api.ForkchoiceUpdatedV1(ctx, state, attr) + default: + return nil, fmt.Errorf("unsupported ForkchoiceUpdated version: %s", method) + } } func (o *OracleEngine) NewPayload(ctx context.Context, payload *eth.ExecutionPayload, parentBeaconBlockRoot *common.Hash) (*eth.PayloadStatusV1, error) { - if o.rollupCfg.IsEcotone(uint64(payload.Timestamp)) { + switch method := o.rollupCfg.NewPayloadVersion(uint64(payload.Timestamp)); method { + case eth.NewPayloadV3: return o.api.NewPayloadV3(ctx, payload, []common.Hash{}, parentBeaconBlockRoot) - } else { + case eth.NewPayloadV2: return o.api.NewPayloadV2(ctx, payload) + default: + return nil, fmt.Errorf("unsupported NewPayload version: %s", method) } } @@ -75,14 +94,7 @@ func (o *OracleEngine) PayloadByHash(ctx context.Context, hash common.Hash) (*et if block == nil { return nil, ErrNotFound } - payload, err := eth.BlockAsPayload(block, o.rollupCfg.CanyonTime) - if err != nil { - return nil, err - } - return ð.ExecutionPayloadEnvelope{ - ParentBeaconBlockRoot: block.BeaconRoot(), - ExecutionPayload: payload, - }, nil + return eth.BlockAsPayloadEnv(block, o.rollupCfg.CanyonTime) } func (o *OracleEngine) PayloadByNumber(ctx context.Context, n uint64) (*eth.ExecutionPayloadEnvelope, error) { diff --git a/op-program/client/l2/engine_backend.go b/op-program/client/l2/engine_backend.go index ca7a495753cf..3880056e3376 100644 --- a/op-program/client/l2/engine_backend.go +++ b/op-program/client/l2/engine_backend.go @@ -40,7 +40,7 @@ type OracleBackedL2Chain struct { var _ engineapi.EngineBackend = (*OracleBackedL2Chain)(nil) -func NewOracleBackedL2Chain(logger log.Logger, oracle Oracle, chainCfg *params.ChainConfig, l2OutputRoot common.Hash) (*OracleBackedL2Chain, error) { +func NewOracleBackedL2Chain(logger log.Logger, oracle Oracle, precompileOracle engineapi.PrecompileOracle, chainCfg *params.ChainConfig, l2OutputRoot common.Hash) (*OracleBackedL2Chain, error) { output := oracle.OutputByRoot(l2OutputRoot) outputV0, ok := output.(*eth.OutputV0) if !ok { @@ -66,6 +66,9 @@ func NewOracleBackedL2Chain(logger log.Logger, oracle Oracle, chainCfg *params.C oracleHead: head.Header(), blocks: make(map[common.Hash]*types.Block), db: NewOracleBackedDB(oracle), + vmCfg: vm.Config{ + OptimismPrecompileOverrides: engineapi.CreatePrecompileOverrides(precompileOracle), + }, }, nil } diff --git a/op-program/client/l2/engine_backend_test.go b/op-program/client/l2/engine_backend_test.go index 861e68068625..0801d8738038 100644 --- a/op-program/client/l2/engine_backend_test.go +++ b/op-program/client/l2/engine_backend_test.go @@ -28,6 +28,18 @@ var fundedKey, _ = crypto.GenerateKey() var fundedAddress = crypto.PubkeyToAddress(fundedKey.PublicKey) var targetAddress = common.HexToAddress("0x001122334455") +var ( + kzgInputData = common.FromHex("01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a") + ecRecoverInputData = common.FromHex("18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549") + bn256PairingInputData = common.FromHex("1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa") +) + +var ( + ecRecoverReturnValue = []byte{0x1, 0x2} + bn256PairingReturnValue = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} + blobPrecompileReturnValue = common.FromHex("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001") +) + func TestInitialState(t *testing.T) { blocks, chain := setupOracleBackedChain(t, 5) head := blocks[5] @@ -186,6 +198,56 @@ func TestGetHeaderByNumber(t *testing.T) { }) } +func TestPrecompileOracle(t *testing.T) { + tests := []struct { + name string + input []byte + target common.Address + result []byte + }{ + { + name: "EcRecover", + input: ecRecoverInputData, + target: common.BytesToAddress([]byte{0x1}), + result: ecRecoverReturnValue, + }, + { + name: "Bn256Pairing", + input: bn256PairingInputData, + target: common.BytesToAddress([]byte{0x8}), + result: bn256PairingReturnValue, + }, + { + name: "KZGPointEvaluation", + input: kzgInputData, + target: common.BytesToAddress([]byte{0xa}), + result: blobPrecompileReturnValue, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + blockCount := 3 + headBlockNumber := 3 + logger := testlog.Logger(t, log.LevelDebug) + chainCfg, blocks, oracle := setupOracle(t, blockCount, headBlockNumber, true) + head := blocks[headBlockNumber].Hash() + stubOutput := eth.OutputV0{BlockHash: head} + precompileOracle := new(l2test.StubPrecompileOracle) + precompileOracle.Results = map[common.Hash]l2test.PrecompileResult{ + crypto.Keccak256Hash(append(test.target.Bytes(), test.input...)): {Result: test.result, Ok: true}, + } + chain, err := NewOracleBackedL2Chain(logger, oracle, precompileOracle, chainCfg, common.Hash(eth.OutputRoot(&stubOutput))) + require.NoError(t, err) + + newBlock := createBlock(t, chain, WithInput(test.input), WithTargetAddress(test.target)) + require.NoError(t, chain.InsertBlockWithoutSetHead(newBlock)) + require.Equal(t, 1, precompileOracle.Calls) + }) + } +} + func assertBlockDataAvailable(t *testing.T, chain *OracleBackedL2Chain, block *types.Block, blockNumber uint64) { require.Equal(t, block, chain.GetBlockByHash(block.Hash()), "get block %v by hash", blockNumber) require.Equal(t, block.Header(), chain.GetHeaderByHash(block.Hash()), "get header %v by hash", blockNumber) @@ -199,16 +261,17 @@ func setupOracleBackedChain(t *testing.T, blockCount int) ([]*types.Block, *Orac } func setupOracleBackedChainWithLowerHead(t *testing.T, blockCount int, headBlockNumber int) ([]*types.Block, *OracleBackedL2Chain) { - logger := testlog.Logger(t, log.LvlDebug) - chainCfg, blocks, oracle := setupOracle(t, blockCount, headBlockNumber) + logger := testlog.Logger(t, log.LevelDebug) + chainCfg, blocks, oracle := setupOracle(t, blockCount, headBlockNumber, false) head := blocks[headBlockNumber].Hash() stubOutput := eth.OutputV0{BlockHash: head} - chain, err := NewOracleBackedL2Chain(logger, oracle, chainCfg, common.Hash(eth.OutputRoot(&stubOutput))) + precompileOracle := new(l2test.StubPrecompileOracle) + chain, err := NewOracleBackedL2Chain(logger, oracle, precompileOracle, chainCfg, common.Hash(eth.OutputRoot(&stubOutput))) require.NoError(t, err) return blocks, chain } -func setupOracle(t *testing.T, blockCount int, headBlockNumber int) (*params.ChainConfig, []*types.Block, *l2test.StubBlockOracle) { +func setupOracle(t *testing.T, blockCount int, headBlockNumber int, enableEcotone bool) (*params.ChainConfig, []*types.Block, *l2test.StubBlockOracle) { deployConfig := &genesis.DeployConfig{ L1ChainID: 900, L2ChainID: 901, @@ -219,6 +282,13 @@ func setupOracle(t *testing.T, blockCount int, headBlockNumber int) (*params.Cha // This is slightly weird for a chain starting post-merge but it happens so need to make sure it works L2GenesisBlockDifficulty: (*hexutil.Big)(big.NewInt(100)), } + if enableEcotone { + ts := hexutil.Uint64(0) + deployConfig.L2GenesisRegolithTimeOffset = &ts + deployConfig.L2GenesisCanyonTimeOffset = &ts + deployConfig.L2GenesisDeltaTimeOffset = &ts + deployConfig.L2GenesisEcotoneTimeOffset = &ts + } l1Genesis, err := genesis.NewL1Genesis(deployConfig) require.NoError(t, err) l2Genesis, err := genesis.NewL2Genesis(deployConfig, l1Genesis.ToBlock()) @@ -246,7 +316,33 @@ func setupOracle(t *testing.T, blockCount int, headBlockNumber int) (*params.Cha return chainCfg, blocks, oracle } -func createBlock(t *testing.T, chain *OracleBackedL2Chain) *types.Block { +type blockCreateConfig struct { + input []byte + target *common.Address +} + +type blockCreateOption func(*blockCreateConfig) + +func WithInput(input []byte) blockCreateOption { + return func(opts *blockCreateConfig) { + opts.input = input + } +} + +func WithTargetAddress(target common.Address) blockCreateOption { + return func(opts *blockCreateConfig) { + opts.target = &target + } +} + +func createBlock(t *testing.T, chain *OracleBackedL2Chain, opts ...blockCreateOption) *types.Block { + cfg := blockCreateConfig{} + for _, o := range opts { + o(&cfg) + } + if cfg.target == nil { + cfg.target = &targetAddress + } parent := chain.GetBlockByHash(chain.CurrentHeader().Hash()) parentDB, err := chain.StateAt(parent.Root()) require.NoError(t, err) @@ -257,10 +353,11 @@ func createBlock(t *testing.T, chain *OracleBackedL2Chain) *types.Block { rawTx := &types.DynamicFeeTx{ ChainID: config.ChainID, Nonce: nonce, - To: &targetAddress, + To: cfg.target, GasTipCap: big.NewInt(0), GasFeeCap: parent.BaseFee(), - Gas: 21_000, + Gas: 2_000_000, + Data: cfg.input, Value: big.NewInt(1), } tx := types.MustSignNewTx(fundedKey, types.NewLondonSigner(config.ChainID), rawTx) diff --git a/op-program/client/l2/engineapi/block_processor.go b/op-program/client/l2/engineapi/block_processor.go index ef15e66fd2dd..d81212db206c 100644 --- a/op-program/client/l2/engineapi/block_processor.go +++ b/op-program/client/l2/engineapi/block_processor.go @@ -39,21 +39,21 @@ type BlockProcessor struct { dataProvider BlockDataProvider } -func NewBlockProcessorFromPayloadAttributes(provider BlockDataProvider, parent common.Hash, params *eth.PayloadAttributes) (*BlockProcessor, error) { +func NewBlockProcessorFromPayloadAttributes(provider BlockDataProvider, parent common.Hash, attrs *eth.PayloadAttributes) (*BlockProcessor, error) { header := &types.Header{ ParentHash: parent, - Coinbase: params.SuggestedFeeRecipient, + Coinbase: attrs.SuggestedFeeRecipient, Difficulty: common.Big0, - GasLimit: uint64(*params.GasLimit), - Time: uint64(params.Timestamp), + GasLimit: uint64(*attrs.GasLimit), + Time: uint64(attrs.Timestamp), Extra: nil, - MixDigest: common.Hash(params.PrevRandao), + MixDigest: common.Hash(attrs.PrevRandao), Nonce: types.EncodeNonce(0), - ParentBeaconRoot: params.ParentBeaconBlockRoot, + ParentBeaconRoot: attrs.ParentBeaconBlockRoot, } // Ecotone - if params.ParentBeaconBlockRoot != nil { + if attrs.ParentBeaconBlockRoot != nil { zero := uint64(0) header.BlobGasUsed = &zero header.ExcessBlobGas = &zero @@ -80,6 +80,18 @@ func NewBlockProcessorFromHeader(provider BlockDataProvider, h *types.Header) (* header.BaseFee = eip1559.CalcBaseFee(provider.Config(), parentHeader, header.Time) header.GasUsed = 0 gasPool := new(core.GasPool).AddGas(header.GasLimit) + if h.ParentBeaconRoot != nil { + // Unfortunately this is not part of any Geth environment setup, + // we just have to apply it, like how the Geth block-builder worker does. + context := core.NewEVMBlockContext(header, provider, nil, provider.Config(), statedb) + // NOTE: Unlikely to be needed for the beacon block root, but we setup any precompile overrides anyways for forwards-compatibility + var precompileOverrides vm.PrecompileOverrides + if vmConfig := provider.GetVMConfig(); vmConfig != nil && vmConfig.OptimismPrecompileOverrides != nil { + precompileOverrides = vmConfig.OptimismPrecompileOverrides + } + vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, provider.Config(), vm.Config{OptimismPrecompileOverrides: precompileOverrides}) + core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, vmenv, statedb) + } return &BlockProcessor{ header: header, state: statedb, diff --git a/op-program/client/l2/engineapi/l2_engine_api.go b/op-program/client/l2/engineapi/l2_engine_api.go index 184494a84b8f..dbcd1b7c13e0 100644 --- a/op-program/client/l2/engineapi/l2_engine_api.go +++ b/op-program/client/l2/engineapi/l2_engine_api.go @@ -19,6 +19,7 @@ import ( "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/holiman/uint256" ) type EngineBackend interface { @@ -79,20 +80,20 @@ var ( ) // computePayloadId computes a pseudo-random payloadid, based on the parameters. -func computePayloadId(headBlockHash common.Hash, params *eth.PayloadAttributes) engine.PayloadID { +func computePayloadId(headBlockHash common.Hash, attrs *eth.PayloadAttributes) engine.PayloadID { // Hash hasher := sha256.New() hasher.Write(headBlockHash[:]) - _ = binary.Write(hasher, binary.BigEndian, params.Timestamp) - hasher.Write(params.PrevRandao[:]) - hasher.Write(params.SuggestedFeeRecipient[:]) - _ = binary.Write(hasher, binary.BigEndian, params.NoTxPool) - _ = binary.Write(hasher, binary.BigEndian, uint64(len(params.Transactions))) - for _, tx := range params.Transactions { + _ = binary.Write(hasher, binary.BigEndian, attrs.Timestamp) + hasher.Write(attrs.PrevRandao[:]) + hasher.Write(attrs.SuggestedFeeRecipient[:]) + _ = binary.Write(hasher, binary.BigEndian, attrs.NoTxPool) + _ = binary.Write(hasher, binary.BigEndian, uint64(len(attrs.Transactions))) + for _, tx := range attrs.Transactions { _ = binary.Write(hasher, binary.BigEndian, uint64(len(tx))) // length-prefix to avoid collisions hasher.Write(tx) } - _ = binary.Write(hasher, binary.BigEndian, *params.GasLimit) + _ = binary.Write(hasher, binary.BigEndian, *attrs.GasLimit) var out engine.PayloadID copy(out[:], hasher.Sum(nil)[:8]) return out @@ -113,9 +114,7 @@ func (ea *L2EngineAPI) PendingIndices(from common.Address) uint64 { return ea.pendingIndices[from] } -var ( - ErrNotBuildingBlock = errors.New("not currently building a block, cannot include tx from queue") -) +var ErrNotBuildingBlock = errors.New("not currently building a block, cannot include tx from queue") func (ea *L2EngineAPI) IncludeTx(tx *types.Transaction, from common.Address) error { if ea.blockProcessor == nil { @@ -141,22 +140,22 @@ func (ea *L2EngineAPI) IncludeTx(tx *types.Transaction, from common.Address) err return nil } -func (ea *L2EngineAPI) startBlock(parent common.Hash, params *eth.PayloadAttributes) error { +func (ea *L2EngineAPI) startBlock(parent common.Hash, attrs *eth.PayloadAttributes) error { if ea.blockProcessor != nil { ea.log.Warn("started building new block without ending previous block", "previous", ea.blockProcessor.header, "prev_payload_id", ea.payloadID) } - processor, err := NewBlockProcessorFromPayloadAttributes(ea.backend, parent, params) + processor, err := NewBlockProcessorFromPayloadAttributes(ea.backend, parent, attrs) if err != nil { return err } ea.blockProcessor = processor ea.pendingIndices = make(map[common.Address]uint64) - ea.l2ForceEmpty = params.NoTxPool - ea.payloadID = computePayloadId(parent, params) + ea.l2ForceEmpty = attrs.NoTxPool + ea.payloadID = computePayloadId(parent, attrs) // pre-process the deposits - for i, otx := range params.Transactions { + for i, otx := range attrs.Transactions { var tx types.Transaction if err := tx.UnmarshalBinary(otx); err != nil { return fmt.Errorf("transaction %d is not valid: %w", i, err) @@ -305,7 +304,7 @@ func (ea *L2EngineAPI) NewPayloadV3(ctx context.Context, params *eth.ExecutionPa return ea.newPayload(ctx, params, versionedHashes, beaconRoot) } -func (ea *L2EngineAPI) getPayload(ctx context.Context, payloadId eth.PayloadID) (*eth.ExecutionPayloadEnvelope, error) { +func (ea *L2EngineAPI) getPayload(_ context.Context, payloadId eth.PayloadID) (*eth.ExecutionPayloadEnvelope, 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) @@ -317,15 +316,10 @@ func (ea *L2EngineAPI) getPayload(ctx context.Context, payloadId eth.PayloadID) return nil, engine.UnknownPayload } - payload, err := eth.BlockAsPayload(bl, ea.config().CanyonTime) - if err != nil { - return nil, err - } - - return ð.ExecutionPayloadEnvelope{ExecutionPayload: payload, ParentBeaconBlockRoot: bl.BeaconRoot()}, nil + return eth.BlockAsPayloadEnv(bl, ea.config().CanyonTime) } -func (ea *L2EngineAPI) forkchoiceUpdated(ctx context.Context, state *eth.ForkchoiceState, attr *eth.PayloadAttributes) (*eth.ForkchoiceUpdatedResult, error) { +func (ea *L2EngineAPI) forkchoiceUpdated(_ 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") @@ -350,7 +344,7 @@ func (ea *L2EngineAPI) forkchoiceUpdated(ctx context.Context, state *eth.Forkcho return STATUS_SYNCING, nil } - ea.log.Info("Forkchoice requested sync to new head", "number", header.Number, "hash", header.Hash()) + ea.log.Info("Forkchoice requested sync to new head", "number", header.Number(), "hash", header.Hash()) if err := ea.downloader.BeaconSync(downloader.SnapSync, header.Header(), nil); err != nil { return STATUS_SYNCING, err } @@ -444,7 +438,7 @@ func toGethWithdrawals(payload *eth.ExecutionPayload) []*types.Withdrawal { return result } -func (ea *L2EngineAPI) newPayload(ctx context.Context, payload *eth.ExecutionPayload, hashes []common.Hash, root *common.Hash) (*eth.PayloadStatusV1, error) { +func (ea *L2EngineAPI) newPayload(_ context.Context, payload *eth.ExecutionPayload, hashes []common.Hash, root *common.Hash) (*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 { @@ -462,14 +456,13 @@ func (ea *L2EngineAPI) newPayload(ctx context.Context, payload *eth.ExecutionPay GasUsed: uint64(payload.GasUsed), Timestamp: uint64(payload.Timestamp), ExtraData: payload.ExtraData, - BaseFeePerGas: payload.BaseFeePerGas.ToBig(), + BaseFeePerGas: (*uint256.Int)(&payload.BaseFeePerGas).ToBig(), BlockHash: payload.BlockHash, Transactions: txs, Withdrawals: toGethWithdrawals(payload), ExcessBlobGas: (*uint64)(payload.ExcessBlobGas), BlobGasUsed: (*uint64)(payload.BlobGasUsed), }, hashes, root) - if err != nil { log.Debug("Invalid NewPayload params", "params", payload, "error", err) return ð.PayloadStatusV1{Status: eth.ExecutionInvalidBlockHash}, nil diff --git a/op-program/client/l2/engineapi/precompiles.go b/op-program/client/l2/engineapi/precompiles.go new file mode 100644 index 000000000000..5ef77663d5bb --- /dev/null +++ b/op-program/client/l2/engineapi/precompiles.go @@ -0,0 +1,222 @@ +// This file contains code of the upstream go-ethereum kzgPointEvaluation implementation. +// Modifications have been made, primarily to substitute kzgPointEvaluation, ecrecover, and runBn256Pairing +// functions to interact with the preimage oracle. +// +// Original copyright disclaimer, applicable only to this file: +// ------------------------------------------------------------------- +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package engineapi + +import ( + "bytes" + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/kzg4844" + "github.com/ethereum/go-ethereum/params" + + "github.com/ethereum-optimism/optimism/op-service/eth" +) + +var ( + ecrecoverPrecompileAddress = common.BytesToAddress([]byte{0x1}) + bn256PairingPrecompileAddress = common.BytesToAddress([]byte{0x8}) + kzgPointEvaluationPrecompileAddress = common.BytesToAddress([]byte{0xa}) +) + +// PrecompileOracle defines the high-level API used to retrieve the result of a precompile call +// The caller is expected to validate the input to the precompile call +type PrecompileOracle interface { + Precompile(address common.Address, input []byte) ([]byte, bool) +} + +func CreatePrecompileOverrides(precompileOracle PrecompileOracle) vm.PrecompileOverrides { + return func(rules params.Rules, orig vm.PrecompiledContract, address common.Address) (vm.PrecompiledContract, bool) { + // NOTE: Ignoring chain rules for now. We assume that precompile behavior won't change for the foreseeable future + switch address { + case ecrecoverPrecompileAddress: + return &ecrecoverOracle{Orig: orig, Oracle: precompileOracle}, true + case bn256PairingPrecompileAddress: + return &bn256PairingOracle{Orig: orig, Oracle: precompileOracle}, true + case kzgPointEvaluationPrecompileAddress: + return &kzgPointEvaluationOracle{Orig: orig, Oracle: precompileOracle}, true + default: + return nil, false + } + } +} + +type ecrecoverOracle struct { + Orig vm.PrecompiledContract + Oracle PrecompileOracle +} + +func (c *ecrecoverOracle) RequiredGas(input []byte) uint64 { + return c.Orig.RequiredGas(input) +} + +func (c *ecrecoverOracle) Run(input []byte) ([]byte, error) { + // Modification note: the L1 precompile behavior may change, but not in incompatible ways. + // We want to enforce the subset that represents the EVM behavior activated in L2. + // Below is a copy of the Cancun behavior. L1 might expand on that at a later point. + + const ecRecoverInputLength = 128 + + input = common.RightPadBytes(input, ecRecoverInputLength) + // "input" is (hash, v, r, s), each 32 bytes + // but for ecrecover we want (r, s, v) + + r := new(big.Int).SetBytes(input[64:96]) + s := new(big.Int).SetBytes(input[96:128]) + v := input[63] - 27 + + // tighter sig s values input homestead only apply to tx sigs + if !allZero(input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) { + return nil, nil + } + // We must make sure not to modify the 'input', so placing the 'v' along with + // the signature needs to be done on a new allocation + sig := make([]byte, 65) + copy(sig, input[64:128]) + sig[64] = v + // v needs to be at the end for libsecp256k1 + + // Modification note: below replaces the crypto.Ecrecover call + result, ok := c.Oracle.Precompile(ecrecoverPrecompileAddress, input) + if !ok { + return nil, errors.New("invalid ecrecover input") + } + return result, nil +} + +func allZero(b []byte) bool { + for _, byte := range b { + if byte != 0 { + return false + } + } + return true +} + +type bn256PairingOracle struct { + Orig vm.PrecompiledContract + Oracle PrecompileOracle +} + +func (b *bn256PairingOracle) RequiredGas(input []byte) uint64 { + return b.Orig.RequiredGas(input) +} + +var ( + // true32Byte is returned if the bn256 pairing check succeeds. + true32Byte = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} + + // false32Byte is returned if the bn256 pairing check fails. + false32Byte = make([]byte, 32) + + // errBadPairingInput is returned if the bn256 pairing input is invalid. + errBadPairingInput = errors.New("bad elliptic curve pairing size") +) + +func (b *bn256PairingOracle) Run(input []byte) ([]byte, error) { + // Handle some corner cases cheaply + if len(input)%192 > 0 { + return nil, errBadPairingInput + } + // Modification note: below replaces point verification and pairing checks + // Assumes both L2 and the L1 oracle have an identical range of valid points + result, ok := b.Oracle.Precompile(bn256PairingPrecompileAddress, input) + if !ok { + return nil, errors.New("invalid bn256Pairing check") + } + if !bytes.Equal(result, true32Byte) && !bytes.Equal(result, false32Byte) { + panic("unexpected result from bn256Pairing check") + } + return result, nil +} + +// kzgPointEvaluationOracle implements the EIP-4844 point evaluation precompile, +// using the preimage-oracle to perform the evaluation. +type kzgPointEvaluationOracle struct { + Orig vm.PrecompiledContract + Oracle PrecompileOracle +} + +// RequiredGas estimates the gas required for running the point evaluation precompile. +func (b *kzgPointEvaluationOracle) RequiredGas(input []byte) uint64 { + return b.Orig.RequiredGas(input) +} + +const ( + blobVerifyInputLength = 192 // Max input length for the point evaluation precompile. + blobPrecompileReturnValue = "000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001" +) + +var ( + errBlobVerifyInvalidInputLength = errors.New("invalid input length") + errBlobVerifyMismatchedVersion = errors.New("mismatched versioned hash") + errBlobVerifyKZGProof = errors.New("error verifying kzg proof") +) + +// Run executes the point evaluation precompile. +func (b *kzgPointEvaluationOracle) Run(input []byte) ([]byte, error) { + // Modification note: the L1 precompile behavior may change, but not in incompatible ways. + // We want to enforce the subset that represents the EVM behavior activated in L2. + // Below is a copy of the Cancun behavior. L1 might expand on that at a later point. + + if len(input) != blobVerifyInputLength { + return nil, errBlobVerifyInvalidInputLength + } + // versioned hash: first 32 bytes + var versionedHash common.Hash + copy(versionedHash[:], input[:]) + + var ( + point kzg4844.Point + claim kzg4844.Claim + ) + // Evaluation point: next 32 bytes + copy(point[:], input[32:]) + // Expected output: next 32 bytes + copy(claim[:], input[64:]) + + // input kzg point: next 48 bytes + var commitment kzg4844.Commitment + copy(commitment[:], input[96:]) + if eth.KZGToVersionedHash(commitment) != versionedHash { + return nil, errBlobVerifyMismatchedVersion + } + + // Proof: next 48 bytes + var proof kzg4844.Proof + copy(proof[:], input[144:]) + + // Modification note: below replaces the kzg4844.VerifyProof call + result, ok := b.Oracle.Precompile(kzgPointEvaluationPrecompileAddress, input) + if !ok { + return nil, fmt.Errorf("%w: invalid KZG point evaluation", errBlobVerifyKZGProof) + } + if !bytes.Equal(result, common.FromHex(blobPrecompileReturnValue)) { + panic("unexpected result from KZG point evaluation check") + } + return result, nil +} diff --git a/op-program/client/l2/engineapi/test/l2_engine_api_tests.go b/op-program/client/l2/engineapi/test/l2_engine_api_tests.go index c8a0fb706283..1d8a9ff61ff7 100644 --- a/op-program/client/l2/engineapi/test/l2_engine_api_tests.go +++ b/op-program/client/l2/engineapi/test/l2_engine_api_tests.go @@ -317,7 +317,7 @@ type testHelper struct { } func newTestHelper(t *testing.T, createBackend func(t *testing.T) engineapi.EngineBackend) *testHelper { - logger := testlog.Logger(t, log.LvlDebug) + logger := testlog.Logger(t, log.LevelDebug) ctx := context.Background() backend := createBackend(t) api := engineapi.NewL2EngineAPI(logger, backend, nil) diff --git a/op-program/client/l2/test/stub_oracle.go b/op-program/client/l2/test/stub_oracle.go index c681bc8d76f7..95610b6119ad 100644 --- a/op-program/client/l2/test/stub_oracle.go +++ b/op-program/client/l2/test/stub_oracle.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" ) @@ -122,3 +123,23 @@ func (o *StubStateOracle) CodeByHash(hash common.Hash) []byte { } return data } + +type StubPrecompileOracle struct { + t *testing.T + Results map[common.Hash]PrecompileResult + Calls int +} + +type PrecompileResult struct { + Result []byte + Ok bool +} + +func (o *StubPrecompileOracle) Precompile(address common.Address, input []byte) ([]byte, bool) { + result, ok := o.Results[crypto.Keccak256Hash(append(address.Bytes(), input...))] + if !ok { + o.t.Fatalf("no value for point evaluation %v", input) + } + o.Calls++ + return result.Result, result.Ok +} diff --git a/op-program/client/program.go b/op-program/client/program.go index b43950bfb871..991e975429bb 100644 --- a/op-program/client/program.go +++ b/op-program/client/program.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum-optimism/optimism/op-program/client/l1" "github.com/ethereum-optimism/optimism/op-program/client/l2" oppio "github.com/ethereum-optimism/optimism/op-program/io" + "github.com/ethereum-optimism/optimism/op-service/eigenda" "github.com/ethereum-optimism/optimism/op-service/eth" ) @@ -40,38 +41,39 @@ func Main(logger log.Logger) { // RunProgram executes the Program, while attached to an IO based pre-image oracle, to be served by a host. func RunProgram(logger log.Logger, preimageOracle io.ReadWriter, preimageHinter io.ReadWriter) error { - pClient := preimage.NewOracleClient(preimageOracle) - hClient := preimage.NewHintWriter(preimageHinter) - l1PreimageOracle := l1.NewCachingOracle(l1.NewPreimageOracle(pClient, hClient)) - l2PreimageOracle := l2.NewCachingOracle(l2.NewPreimageOracle(pClient, hClient)) + // hClient := preimage.NewHintWriter(preimageHinter) + // l1PreimageOracle := l1.NewCachingOracle(l1.NewPreimageOracle(pClient, hClient)) + // l2PreimageOracle := l2.NewCachingOracle(l2.NewPreimageOracle(pClient, hClient)) bootInfo := NewBootstrapClient(pClient).BootInfo() logger.Info("Program Bootstrapped", "bootInfo", bootInfo) - return runDerivation( - logger, - bootInfo.RollupConfig, - bootInfo.L2ChainConfig, - bootInfo.L1Head, - bootInfo.L2OutputRoot, - bootInfo.L2Claim, - bootInfo.L2ClaimBlockNumber, - l1PreimageOracle, - l2PreimageOracle, - ) + return nil + // return runDerivation( + // logger, + // bootInfo.RollupConfig, + // bootInfo.L2ChainConfig, + // bootInfo.L1Head, + // bootInfo.L2OutputRoot, + // bootInfo.L2Claim, + // bootInfo.L2ClaimBlockNumber, + // l1PreimageOracle, + // l2PreimageOracle, + // ) } // runDerivation executes the L2 state transition, given a minimal interface to retrieve data. -func runDerivation(logger log.Logger, cfg *rollup.Config, l2Cfg *params.ChainConfig, l1Head common.Hash, l2OutputRoot common.Hash, l2Claim common.Hash, l2ClaimBlockNum uint64, l1Oracle l1.Oracle, l2Oracle l2.Oracle) error { +func runDerivation(logger log.Logger, cfg *rollup.Config, daCfg *eigenda.Config, prefixDerivationEnabled bool, l2Cfg *params.ChainConfig, l1Head common.Hash, l2OutputRoot common.Hash, l2Claim common.Hash, l2ClaimBlockNum uint64, l1Oracle l1.Oracle, l2Oracle l2.Oracle) error { l1Source := l1.NewOracleL1Client(logger, l1Oracle, l1Head) - engineBackend, err := l2.NewOracleBackedL2Chain(logger, l2Oracle, l2Cfg, l2OutputRoot) + l1BlobsSource := l1.NewBlobFetcher(logger, l1Oracle) + engineBackend, err := l2.NewOracleBackedL2Chain(logger, l2Oracle, l1Oracle /* kzg oracle */, l2Cfg, l2OutputRoot) if err != nil { return fmt.Errorf("failed to create oracle-backed L2 chain: %w", err) } l2Source := l2.NewOracleEngine(cfg, logger, engineBackend) logger.Info("Starting derivation") - d := cldr.NewDriver(logger, cfg, l1Source, l2Source, l2ClaimBlockNum) + d := cldr.NewDriver(logger, cfg, l1Source, l1BlobsSource, l2Source, l2ClaimBlockNum, daCfg, prefixDerivationEnabled) for { if err = d.Step(context.Background()); errors.Is(err, io.EOF) { break diff --git a/op-program/host/cmd/main.go b/op-program/host/cmd/main.go index 19d0f188730b..75dc1383983e 100644 --- a/op-program/host/cmd/main.go +++ b/op-program/host/cmd/main.go @@ -64,6 +64,6 @@ func run(args []string, action ConfigAction) error { func setupLogging(ctx *cli.Context) (log.Logger, error) { logCfg := oplog.ReadCLIConfig(ctx) logger := oplog.NewLogger(oplog.AppOut(ctx), logCfg) - oplog.SetGlobalLogHandler(logger.GetHandler()) + oplog.SetGlobalLogHandler(logger.Handler()) return logger, nil } diff --git a/op-program/host/cmd/main_test.go b/op-program/host/cmd/main_test.go index 38cf29e6a4b6..928158c7cd01 100644 --- a/op-program/host/cmd/main_test.go +++ b/op-program/host/cmd/main_test.go @@ -9,7 +9,9 @@ import ( "github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-program/chainconfig" "github.com/ethereum-optimism/optimism/op-program/host/config" + oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/log" @@ -48,7 +50,12 @@ func TestLogFormat(t *testing.T) { verifyArgsInvalid(t, `unrecognized log-format: "foo"`, addRequiredArgs("--log.format=foo")) }) - for _, lvl := range []string{"json", "json-pretty", "terminal", "text", "logfmt"} { + for _, lvl := range []string{ + oplog.FormatJSON.String(), + oplog.FormatTerminal.String(), + oplog.FormatText.String(), + oplog.FormatLogFmt.String(), + } { lvl := lvl t.Run("AcceptValid_"+lvl, func(t *testing.T) { logger, _, err := runWithArgs(addRequiredArgs("--log.format", lvl)) diff --git a/op-program/host/config/config.go b/op-program/host/config/config.go index 117cdeadc9fd..25f1a75724c9 100644 --- a/op-program/host/config/config.go +++ b/op-program/host/config/config.go @@ -35,17 +35,17 @@ var ( type Config struct { Rollup *rollup.Config // DataDir is the directory to read/write pre-image data from/to. - //If not set, an in-memory key-value store is used and fetching data must be enabled + // If not set, an in-memory key-value store is used and fetching data must be enabled DataDir string - // L1Head is the block has of the L1 chain head block - L1Head common.Hash - L1URL string - L1TrustRPC bool - L1RPCKind sources.RPCProviderKind + // L1Head is the block hash of the L1 chain head block + L1Head common.Hash + L1URL string + L1BeaconURL string + L1TrustRPC bool + L1RPCKind sources.RPCProviderKind // L2Head is the l2 block hash contained in the L2 Output referenced by the L2OutputRoot - // TODO(inphi): This can be made optional with hardcoded rollup configs and output oracle addresses by searching the oracle for the l2 output root L2Head common.Hash // L2OutputRoot is the agreed L2 output root to start derivation from L2OutputRoot common.Hash @@ -104,6 +104,7 @@ func (c *Config) Check() error { } func (c *Config) FetchingEnabled() bool { + // TODO: Include Beacon URL once cancun is active on all chains we fault prove. return c.L1URL != "" && c.L2URL != "" } @@ -136,7 +137,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) { if err := flags.CheckRequired(ctx); err != nil { return nil, err } - rollupCfg, err := opnode.NewRollupConfig(log, ctx) + rollupCfg, err := opnode.NewRollupConfigFromCLI(log, ctx) if err != nil { return nil, err } @@ -193,6 +194,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) { L2ClaimBlockNumber: l2ClaimBlockNum, L1Head: l1Head, L1URL: ctx.String(flags.L1NodeAddr.Name), + L1BeaconURL: ctx.String(flags.L1BeaconAddr.Name), L1TrustRPC: ctx.Bool(flags.L1TrustRPC.Name), L1RPCKind: sources.RPCProviderKind(ctx.String(flags.L1RPCProviderKind.Name)), ExecCmd: ctx.String(flags.Exec.Name), diff --git a/op-program/host/flags/flags.go b/op-program/host/flags/flags.go index a4340be84cff..3356bbfda8a9 100644 --- a/op-program/host/flags/flags.go +++ b/op-program/host/flags/flags.go @@ -75,6 +75,11 @@ var ( Usage: "Address of L1 JSON-RPC endpoint to use (eth namespace required)", EnvVars: prefixEnvVars("L1_RPC"), } + L1BeaconAddr = &cli.StringFlag{ + Name: "l1.beacon", + Usage: "Address of L1 Beacon API endpoint to use", + EnvVars: prefixEnvVars("L1_BEACON_API"), + } L1TrustRPC = &cli.BoolFlag{ Name: "l1.trustrpc", Usage: "Trust the L1 RPC, sync faster at risk of malicious/buggy RPC providing bad or inconsistent L1 data", @@ -112,6 +117,7 @@ var requiredFlags = []cli.Flag{ L2Claim, L2BlockNumber, } + var programFlags = []cli.Flag{ RollupConfig, Network, @@ -119,6 +125,7 @@ var programFlags = []cli.Flag{ L2NodeAddr, L2GenesisPath, L1NodeAddr, + L1BeaconAddr, L1TrustRPC, L1RPCProviderKind, Exec, diff --git a/op-program/host/host.go b/op-program/host/host.go index f96015a5e825..2933d0be59b0 100644 --- a/op-program/host/host.go +++ b/op-program/host/host.go @@ -201,12 +201,14 @@ func makePrefetcher(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg * if err != nil { return nil, fmt.Errorf("failed to create L1 client: %w", err) } + l1Beacon := sources.NewBeaconHTTPClient(client.NewBasicHTTPClient(cfg.L1BeaconURL, logger)) + l1BlobFetcher := sources.NewL1BeaconClient(l1Beacon, sources.L1BeaconClientConfig{FetchAllSidecars: false}) l2Cl, err := NewL2Client(l2RPC, logger, nil, &L2ClientConfig{L2ClientConfig: l2ClCfg, L2Head: cfg.L2Head}) if err != nil { return nil, fmt.Errorf("failed to create L2 client: %w", err) } l2DebugCl := &L2Source{L2Client: l2Cl, DebugClient: sources.NewDebugClient(l2RPC.CallContext)} - return prefetcher.NewPrefetcher(logger, l1Cl, l2DebugCl, kv), nil + return prefetcher.NewPrefetcher(logger, l1Cl, l1BlobFetcher, l2DebugCl, kv), nil } func routeHints(logger log.Logger, hHostRW io.ReadWriter, hinter preimage.HintHandler) chan error { diff --git a/op-program/host/host_test.go b/op-program/host/host_test.go index b3fd3d83396e..c46ebe781190 100644 --- a/op-program/host/host_test.go +++ b/op-program/host/host_test.go @@ -35,7 +35,7 @@ func TestServerMode(t *testing.T) { hintServer, hintClient, err := io.CreateBidirectionalChannel() require.NoError(t, err) defer hintClient.Close() - logger := testlog.Logger(t, log.LvlTrace) + logger := testlog.Logger(t, log.LevelTrace) result := make(chan error) go func() { result <- PreimageServer(context.Background(), logger, cfg, preimageServer, hintServer) diff --git a/op-program/host/kvstore/mem.go b/op-program/host/kvstore/mem.go index 6071db4e1512..9af540e235fa 100644 --- a/op-program/host/kvstore/mem.go +++ b/op-program/host/kvstore/mem.go @@ -1,6 +1,7 @@ package kvstore import ( + "slices" "sync" "github.com/ethereum/go-ethereum/common" @@ -23,7 +24,7 @@ func NewMemKV() *MemKV { func (m *MemKV) Put(k common.Hash, v []byte) error { m.Lock() defer m.Unlock() - m.m[k] = v + m.m[k] = slices.Clone(v) return nil } @@ -34,5 +35,5 @@ func (m *MemKV) Get(k common.Hash) ([]byte, error) { if !ok { return nil, ErrNotFound } - return v, nil + return slices.Clone(v), nil } diff --git a/op-program/host/l2_client.go b/op-program/host/l2_client.go index 162cfe6d3154..e71cbd28d684 100644 --- a/op-program/host/l2_client.go +++ b/op-program/host/l2_client.go @@ -40,10 +40,12 @@ func (s *L2Client) OutputByRoot(ctx context.Context, l2OutputRoot common.Hash) ( if err != nil { return nil, err } - if eth.OutputRoot(output) != eth.Bytes32(l2OutputRoot) { + actualOutputRoot := eth.OutputRoot(output) + if actualOutputRoot != eth.Bytes32(l2OutputRoot) { // For fault proofs, we only reference outputs at the l2 head at boot time // The caller shouldn't be requesting outputs at any other block - return nil, fmt.Errorf("unknown output root") + // If they are, there is no chance of recovery and we should panic to avoid retrying forever + panic(fmt.Errorf("output root %v from specified L2 block %v does not match requested output root %v", actualOutputRoot, s.l2Head, l2OutputRoot)) } return output, nil } diff --git a/op-program/host/prefetcher/prefetcher.go b/op-program/host/prefetcher/prefetcher.go index 3a5d81663e6d..babca2b2c859 100644 --- a/op-program/host/prefetcher/prefetcher.go +++ b/op-program/host/prefetcher/prefetcher.go @@ -2,8 +2,10 @@ package prefetcher import ( "context" + "encoding/binary" "errors" "fmt" + "slices" "strings" preimage "github.com/ethereum-optimism/optimism/op-preimage" @@ -15,16 +17,34 @@ import ( "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/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" ) +var ( + precompileSuccess = [1]byte{1} + precompileFailure = [1]byte{0} +) + +var acceleratedPrecompiles = []common.Address{ + common.BytesToAddress([]byte{0x1}), // ecrecover + common.BytesToAddress([]byte{0x8}), // bn256Pairing + common.BytesToAddress([]byte{0x0a}), // KZG Point Evaluation +} + type L1Source interface { InfoByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, error) InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error) FetchReceipts(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Receipts, error) } +type L1BlobSource interface { + GetBlobSidecars(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.BlobSidecar, error) + GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) +} + type L2Source interface { InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error) NodeByHash(ctx context.Context, hash common.Hash) ([]byte, error) @@ -33,19 +53,21 @@ type L2Source interface { } type Prefetcher struct { - logger log.Logger - l1Fetcher L1Source - l2Fetcher L2Source - lastHint string - kvStore kvstore.KV + logger log.Logger + l1Fetcher L1Source + l1BlobFetcher L1BlobSource + l2Fetcher L2Source + lastHint string + kvStore kvstore.KV } -func NewPrefetcher(logger log.Logger, l1Fetcher L1Source, l2Fetcher L2Source, kvStore kvstore.KV) *Prefetcher { +func NewPrefetcher(logger log.Logger, l1Fetcher L1Source, l1BlobFetcher L1BlobSource, l2Fetcher L2Source, kvStore kvstore.KV) *Prefetcher { return &Prefetcher{ - logger: logger, - l1Fetcher: NewRetryingL1Source(logger, l1Fetcher), - l2Fetcher: NewRetryingL2Source(logger, l2Fetcher), - kvStore: kvStore, + logger: logger, + l1Fetcher: NewRetryingL1Source(logger, l1Fetcher), + l1BlobFetcher: NewRetryingL1BlobSource(logger, l1BlobFetcher), + l2Fetcher: NewRetryingL2Source(logger, l2Fetcher), + kvStore: kvStore, } } @@ -75,13 +97,17 @@ func (p *Prefetcher) GetPreimage(ctx context.Context, key common.Hash) ([]byte, } func (p *Prefetcher) prefetch(ctx context.Context, hint string) error { - hintType, hash, err := parseHint(hint) + hintType, hintBytes, err := parseHint(hint) if err != nil { return err } - p.logger.Debug("Prefetching", "type", hintType, "hash", hash) + p.logger.Debug("Prefetching", "type", hintType, "bytes", hexutil.Bytes(hintBytes)) switch hintType { case l1.HintL1BlockHeader: + if len(hintBytes) != 32 { + return fmt.Errorf("invalid L1 block hint: %x", hint) + } + hash := common.Hash(hintBytes) header, err := p.l1Fetcher.InfoByHash(ctx, hash) if err != nil { return fmt.Errorf("failed to fetch L1 block %s header: %w", hash, err) @@ -92,18 +118,98 @@ func (p *Prefetcher) prefetch(ctx context.Context, hint string) error { } return p.kvStore.Put(preimage.Keccak256Key(hash).PreimageKey(), data) case l1.HintL1Transactions: + if len(hintBytes) != 32 { + return fmt.Errorf("invalid L1 transactions hint: %x", hint) + } + hash := common.Hash(hintBytes) _, txs, err := p.l1Fetcher.InfoAndTxsByHash(ctx, hash) if err != nil { return fmt.Errorf("failed to fetch L1 block %s txs: %w", hash, err) } return p.storeTransactions(txs) case l1.HintL1Receipts: + if len(hintBytes) != 32 { + return fmt.Errorf("invalid L1 receipts hint: %x", hint) + } + hash := common.Hash(hintBytes) _, receipts, err := p.l1Fetcher.FetchReceipts(ctx, hash) if err != nil { return fmt.Errorf("failed to fetch L1 block %s receipts: %w", hash, err) } return p.storeReceipts(receipts) + case l1.HintL1Blob: + if len(hintBytes) != 48 { + return fmt.Errorf("invalid blob hint: %x", hint) + } + + blobVersionHash := common.Hash(hintBytes[:32]) + blobHashIndex := binary.BigEndian.Uint64(hintBytes[32:40]) + refTimestamp := binary.BigEndian.Uint64(hintBytes[40:48]) + + // Fetch the blob sidecar for the indexed blob hash passed in the hint. + indexedBlobHash := eth.IndexedBlobHash{ + Hash: blobVersionHash, + Index: blobHashIndex, + } + // We pass an `eth.L1BlockRef`, but `GetBlobSidecars` only uses the timestamp, which we received in the hint. + sidecars, err := p.l1BlobFetcher.GetBlobSidecars(ctx, eth.L1BlockRef{Time: refTimestamp}, []eth.IndexedBlobHash{indexedBlobHash}) + if err != nil || len(sidecars) != 1 { + return fmt.Errorf("failed to fetch blob sidecars for %s %d: %w", blobVersionHash, blobHashIndex, err) + } + sidecar := sidecars[0] + + // Put the preimage for the versioned hash into the kv store + if err = p.kvStore.Put(preimage.Sha256Key(blobVersionHash).PreimageKey(), sidecar.KZGCommitment[:]); err != nil { + return err + } + + // Put all of the blob's field elements into the kv store. There should be 4096. The preimage oracle key for + // each field element is the keccak256 hash of `abi.encodePacked(sidecar.KZGCommitment, uint256(i))` + blobKey := make([]byte, 80) + copy(blobKey[:48], sidecar.KZGCommitment[:]) + for i := 0; i < params.BlobTxFieldElementsPerBlob; i++ { + binary.BigEndian.PutUint64(blobKey[72:], uint64(i)) + blobKeyHash := crypto.Keccak256Hash(blobKey) + if err := p.kvStore.Put(preimage.Keccak256Key(blobKeyHash).PreimageKey(), blobKey); err != nil { + return err + } + if err = p.kvStore.Put(preimage.BlobKey(blobKeyHash).PreimageKey(), sidecar.Blob[i<<5:(i+1)<<5]); err != nil { + return err + } + } + return nil + case l1.HintL1Precompile: + if len(hintBytes) < 20 { + return fmt.Errorf("invalid precompile hint: %x", hint) + } + precompileAddress := common.BytesToAddress(hintBytes[:20]) + // For extra safety, avoid accelerating unexpected precompiles + if !slices.Contains(acceleratedPrecompiles, precompileAddress) { + return fmt.Errorf("unsupported precompile address: %s", precompileAddress) + } + // NOTE: We use the precompiled contracts from Cancun because it's the only set that contains the addresses of all accelerated precompiles + // We assume the precompile Run function behavior does not change across EVM upgrades. + // As such, we must not rely on upgrade-specific behavior such as precompile.RequiredGas. + precompile := getPrecompiledContract(precompileAddress) + + // KZG Point Evaluation precompile also verifies its input + result, err := precompile.Run(hintBytes[20:]) + if err == nil { + result = append(precompileSuccess[:], result...) + } else { + result = append(precompileFailure[:], result...) + } + inputHash := crypto.Keccak256Hash(hintBytes) + // Put the input preimage so it can be loaded later + if err := p.kvStore.Put(preimage.Keccak256Key(inputHash).PreimageKey(), hintBytes); err != nil { + return err + } + return p.kvStore.Put(preimage.PrecompileKey(inputHash).PreimageKey(), result) case l2.HintL2BlockHeader, l2.HintL2Transactions: + if len(hintBytes) != 32 { + return fmt.Errorf("invalid L2 header/tx hint: %x", hint) + } + hash := common.Hash(hintBytes) header, txs, err := p.l2Fetcher.InfoAndTxsByHash(ctx, hash) if err != nil { return fmt.Errorf("failed to fetch L2 block %s: %w", hash, err) @@ -118,18 +224,30 @@ func (p *Prefetcher) prefetch(ctx context.Context, hint string) error { } return p.storeTransactions(txs) case l2.HintL2StateNode: + if len(hintBytes) != 32 { + return fmt.Errorf("invalid L2 state node hint: %x", hint) + } + hash := common.Hash(hintBytes) node, err := p.l2Fetcher.NodeByHash(ctx, hash) if err != nil { return fmt.Errorf("failed to fetch L2 state node %s: %w", hash, err) } return p.kvStore.Put(preimage.Keccak256Key(hash).PreimageKey(), node) case l2.HintL2Code: + if len(hintBytes) != 32 { + return fmt.Errorf("invalid L2 code hint: %x", hint) + } + hash := common.Hash(hintBytes) code, err := p.l2Fetcher.CodeByHash(ctx, hash) if err != nil { return fmt.Errorf("failed to fetch L2 contract code %s: %w", hash, err) } return p.kvStore.Put(preimage.Keccak256Key(hash).PreimageKey(), code) case l2.HintL2Output: + if len(hintBytes) != 32 { + return fmt.Errorf("invalid L2 output hint: %x", hint) + } + hash := common.Hash(hintBytes) output, err := p.l2Fetcher.OutputByRoot(ctx, hash) if err != nil { return fmt.Errorf("failed to fetch L2 output root %s: %w", hash, err) @@ -167,14 +285,19 @@ func (p *Prefetcher) storeTrieNodes(values []hexutil.Bytes) error { } // parseHint parses a hint string in wire protocol. Returns the hint type, requested hash and error (if any). -func parseHint(hint string) (string, common.Hash, error) { - hintType, hashStr, found := strings.Cut(hint, " ") +func parseHint(hint string) (string, []byte, error) { + hintType, bytesStr, found := strings.Cut(hint, " ") if !found { - return "", common.Hash{}, fmt.Errorf("unsupported hint: %s", hint) + return "", nil, fmt.Errorf("unsupported hint: %s", hint) } - hash := common.HexToHash(hashStr) - if hash == (common.Hash{}) { - return "", common.Hash{}, fmt.Errorf("invalid hash: %s", hashStr) + + hintBytes, err := hexutil.Decode(bytesStr) + if err != nil { + return "", make([]byte, 0), fmt.Errorf("invalid bytes: %s", bytesStr) } - return hintType, hash, nil + return hintType, hintBytes, nil +} + +func getPrecompiledContract(address common.Address) vm.PrecompiledContract { + return vm.PrecompiledContractsCancun[address] } diff --git a/op-program/host/prefetcher/prefetcher_test.go b/op-program/host/prefetcher/prefetcher_test.go index 802638437da2..6ffb9bd5af8a 100644 --- a/op-program/host/prefetcher/prefetcher_test.go +++ b/op-program/host/prefetcher/prefetcher_test.go @@ -2,13 +2,18 @@ package prefetcher import ( "context" + "crypto/sha256" + "encoding/binary" "math/rand" "testing" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + gokzg4844 "github.com/crate-crypto/go-kzg-4844" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/stretchr/testify/require" @@ -24,14 +29,14 @@ import ( func TestNoHint(t *testing.T) { t.Run("NotFound", func(t *testing.T) { - prefetcher, _, _, _ := createPrefetcher(t) + prefetcher, _, _, _, _ := createPrefetcher(t) res, err := prefetcher.GetPreimage(context.Background(), common.Hash{0xab}) require.ErrorIs(t, err, kvstore.ErrNotFound) require.Nil(t, res) }) t.Run("Exists", func(t *testing.T) { - prefetcher, _, _, kv := createPrefetcher(t) + prefetcher, _, _, _, kv := createPrefetcher(t) data := []byte{1, 2, 3} hash := crypto.Keccak256Hash(data) require.NoError(t, kv.Put(hash, data)) @@ -51,7 +56,7 @@ func TestFetchL1BlockHeader(t *testing.T) { require.NoError(t, err) t.Run("AlreadyKnown", func(t *testing.T) { - prefetcher, _, _, kv := createPrefetcher(t) + prefetcher, _, _, _, kv := createPrefetcher(t) storeBlock(t, kv, block, rcpts) oracle := l1.NewPreimageOracle(asOracleFn(t, prefetcher), asHinter(t, prefetcher)) @@ -60,7 +65,7 @@ func TestFetchL1BlockHeader(t *testing.T) { }) t.Run("Unknown", func(t *testing.T) { - prefetcher, l1Cl, _, _ := createPrefetcher(t) + prefetcher, l1Cl, _, _, _ := createPrefetcher(t) l1Cl.ExpectInfoByHash(hash, eth.HeaderBlockInfo(block.Header()), nil) defer l1Cl.AssertExpectations(t) @@ -77,7 +82,7 @@ func TestFetchL1Transactions(t *testing.T) { hash := block.Hash() t.Run("AlreadyKnown", func(t *testing.T) { - prefetcher, _, _, kv := createPrefetcher(t) + prefetcher, _, _, _, kv := createPrefetcher(t) storeBlock(t, kv, block, rcpts) @@ -89,7 +94,7 @@ func TestFetchL1Transactions(t *testing.T) { }) t.Run("Unknown", func(t *testing.T) { - prefetcher, l1Cl, _, _ := createPrefetcher(t) + prefetcher, l1Cl, _, _, _ := createPrefetcher(t) l1Cl.ExpectInfoByHash(hash, eth.BlockToInfo(block), nil) l1Cl.ExpectInfoAndTxsByHash(hash, eth.BlockToInfo(block), block.Transactions(), nil) defer l1Cl.AssertExpectations(t) @@ -107,7 +112,7 @@ func TestFetchL1Receipts(t *testing.T) { hash := block.Hash() t.Run("AlreadyKnown", func(t *testing.T) { - prefetcher, _, _, kv := createPrefetcher(t) + prefetcher, _, _, _, kv := createPrefetcher(t) storeBlock(t, kv, block, receipts) // Check the data is available (note the oracle does not know about the block, only the kvstore does) @@ -118,7 +123,7 @@ func TestFetchL1Receipts(t *testing.T) { }) t.Run("Unknown", func(t *testing.T) { - prefetcher, l1Cl, _, _ := createPrefetcher(t) + prefetcher, l1Cl, _, _, _ := createPrefetcher(t) l1Cl.ExpectInfoByHash(hash, eth.BlockToInfo(block), nil) l1Cl.ExpectInfoAndTxsByHash(hash, eth.BlockToInfo(block), block.Transactions(), nil) l1Cl.ExpectFetchReceipts(hash, eth.BlockToInfo(block), receipts, nil) @@ -133,7 +138,7 @@ func TestFetchL1Receipts(t *testing.T) { // Blocks may have identical RLP receipts for different transactions. // Check that the node already existing is handled t.Run("CommonTrieNodes", func(t *testing.T) { - prefetcher, l1Cl, _, kv := createPrefetcher(t) + prefetcher, l1Cl, _, _, kv := createPrefetcher(t) l1Cl.ExpectInfoByHash(hash, eth.BlockToInfo(block), nil) l1Cl.ExpectInfoAndTxsByHash(hash, eth.BlockToInfo(block), block.Transactions(), nil) l1Cl.ExpectFetchReceipts(hash, eth.BlockToInfo(block), receipts, nil) @@ -153,13 +158,172 @@ func TestFetchL1Receipts(t *testing.T) { }) } +// Globally initialize a kzgCtx for blob tests. +var kzgCtx, _ = gokzg4844.NewContext4096Secure() + +// Returns a serialized random field element in big-endian +func GetRandFieldElement(seed int64) [32]byte { + var r fr.Element + _, _ = r.SetRandom() + return gokzg4844.SerializeScalar(r) +} + +func GetRandBlob(seed int64) gokzg4844.Blob { + var blob gokzg4844.Blob + bytesPerBlob := gokzg4844.ScalarsPerBlob * gokzg4844.SerializedScalarSize + for i := 0; i < bytesPerBlob; i += gokzg4844.SerializedScalarSize { + fieldElementBytes := GetRandFieldElement(seed + int64(i)) + copy(blob[i:i+gokzg4844.SerializedScalarSize], fieldElementBytes[:]) + } + return blob +} + +func TestFetchL1Blob(t *testing.T) { + blob := GetRandBlob(0xf00f00) + commitment, err := kzgCtx.BlobToKZGCommitment(blob, 0) + require.NoError(t, err) + versionedHash := sha256.Sum256(commitment[:]) + versionedHash[0] = params.BlobTxHashVersion + blobHash := eth.IndexedBlobHash{Hash: versionedHash, Index: 0xFACADE} + l1Ref := eth.L1BlockRef{Time: 0} + + t.Run("AlreadyKnown", func(t *testing.T) { + prefetcher, _, blobFetcher, _, kv := createPrefetcher(t) + storeBlob(t, kv, (eth.Bytes48)(commitment), (*eth.Blob)(&blob)) + + oracle := l1.NewPreimageOracle(asOracleFn(t, prefetcher), asHinter(t, prefetcher)) + defer blobFetcher.AssertExpectations(t) + + blobs := oracle.GetBlob(l1Ref, blobHash) + require.EqualValues(t, blobs[:], blob[:]) + }) + + t.Run("Unknown", func(t *testing.T) { + prefetcher, _, blobFetcher, _, _ := createPrefetcher(t) + + oracle := l1.NewPreimageOracle(asOracleFn(t, prefetcher), asHinter(t, prefetcher)) + blobFetcher.ExpectOnGetBlobSidecars( + context.Background(), + l1Ref, + []eth.IndexedBlobHash{blobHash}, + (eth.Bytes48)(commitment), + []*eth.Blob{(*eth.Blob)(&blob)}, + nil, + ) + defer blobFetcher.AssertExpectations(t) + + blobs := oracle.GetBlob(l1Ref, blobHash) + require.EqualValues(t, blobs[:], blob[:]) + + // Check that the preimages of field element keys are also stored + // This makes it possible for the challenger to extract the commitment and required field from the + // oracle key rather than needing the hint data. + + fieldElemKey := make([]byte, 80) + copy(fieldElemKey[:48], commitment[:]) + for i := 0; i < params.BlobTxFieldElementsPerBlob; i++ { + binary.BigEndian.PutUint64(fieldElemKey[72:], uint64(i)) + key := preimage.Keccak256Key(crypto.Keccak256(fieldElemKey)).PreimageKey() + actual, err := prefetcher.kvStore.Get(key) + require.NoError(t, err) + require.Equal(t, fieldElemKey, actual) + } + }) +} + +func TestFetchPrecompileResult(t *testing.T) { + ecRecoverInput := common.FromHex("18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549") + kzgPointEvalInput := common.FromHex("01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a") + + failure := []byte{0} + success := []byte{1} + + tests := []struct { + name string + addr common.Address + input []byte + result []byte + }{ + { + name: "EcRecover-Valid", + addr: common.BytesToAddress([]byte{0x1}), + input: ecRecoverInput, + result: append(success, common.FromHex("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b")...), + }, + { + name: "Bn256Pairing-Valid", + addr: common.BytesToAddress([]byte{0x8}), + input: []byte{}, // empty is valid + result: append(success, common.FromHex("0000000000000000000000000000000000000000000000000000000000000001")...), + }, + { + name: "Bn256Pairing-Invalid", + addr: common.BytesToAddress([]byte{0x8}), + input: []byte{0x1}, + result: failure, + }, + { + name: "KzgPointEvaluation-Valid", + addr: common.BytesToAddress([]byte{0xa}), + input: kzgPointEvalInput, + result: append(success, common.FromHex("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001")...), + }, + { + name: "KzgPointEvaluation-Invalid", + addr: common.BytesToAddress([]byte{0xa}), + input: []byte{0x0}, + result: failure, + }, + } + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + prefetcher, _, _, _, _ := createPrefetcher(t) + oracle := l1.NewPreimageOracle(asOracleFn(t, prefetcher), asHinter(t, prefetcher)) + + result, ok := oracle.Precompile(test.addr, test.input) + require.Equal(t, test.result[0] == 1, ok) + require.EqualValues(t, test.result[1:], result) + + key := crypto.Keccak256Hash(append(test.addr.Bytes(), test.input...)) + val, err := prefetcher.kvStore.Get(preimage.Keccak256Key(key).PreimageKey()) + require.NoError(t, err) + require.NotEmpty(t, val) + + val, err = prefetcher.kvStore.Get(preimage.PrecompileKey(key).PreimageKey()) + require.NoError(t, err) + require.EqualValues(t, test.result, val) + }) + } + + t.Run("Already Known", func(t *testing.T) { + input := []byte("test input") + addr := common.BytesToAddress([]byte{0x1}) + result := []byte{0x1} + prefetcher, _, _, _, kv := createPrefetcher(t) + err := kv.Put(preimage.PrecompileKey(crypto.Keccak256Hash(append(addr.Bytes(), input...))).PreimageKey(), append([]byte{1}, result...)) + require.NoError(t, err) + + oracle := l1.NewPreimageOracle(asOracleFn(t, prefetcher), asHinter(t, prefetcher)) + actualResult, status := oracle.Precompile(addr, input) + require.EqualValues(t, actualResult, result) + require.True(t, status) + }) +} + +func TestRestrictedPrecompileContracts(t *testing.T) { + for _, addr := range acceleratedPrecompiles { + require.NotNil(t, getPrecompiledContract(addr)) + } +} + func TestFetchL2Block(t *testing.T) { rng := rand.New(rand.NewSource(123)) block, rcpts := testutils.RandomBlock(rng, 10) hash := block.Hash() t.Run("AlreadyKnown", func(t *testing.T) { - prefetcher, _, _, kv := createPrefetcher(t) + prefetcher, _, _, _, kv := createPrefetcher(t) storeBlock(t, kv, block, rcpts) oracle := l2.NewPreimageOracle(asOracleFn(t, prefetcher), asHinter(t, prefetcher)) @@ -169,7 +333,7 @@ func TestFetchL2Block(t *testing.T) { }) t.Run("Unknown", func(t *testing.T) { - prefetcher, _, l2Cl, _ := createPrefetcher(t) + prefetcher, _, _, l2Cl, _ := createPrefetcher(t) l2Cl.ExpectInfoAndTxsByHash(hash, eth.BlockToInfo(block), block.Transactions(), nil) defer l2Cl.MockL2Client.AssertExpectations(t) @@ -186,7 +350,7 @@ func TestFetchL2Transactions(t *testing.T) { hash := block.Hash() t.Run("AlreadyKnown", func(t *testing.T) { - prefetcher, _, _, kv := createPrefetcher(t) + prefetcher, _, _, _, kv := createPrefetcher(t) storeBlock(t, kv, block, rcpts) oracle := l2.NewPreimageOracle(asOracleFn(t, prefetcher), asHinter(t, prefetcher)) @@ -195,7 +359,7 @@ func TestFetchL2Transactions(t *testing.T) { }) t.Run("Unknown", func(t *testing.T) { - prefetcher, _, l2Cl, _ := createPrefetcher(t) + prefetcher, _, _, l2Cl, _ := createPrefetcher(t) l2Cl.ExpectInfoAndTxsByHash(hash, eth.BlockToInfo(block), block.Transactions(), nil) defer l2Cl.MockL2Client.AssertExpectations(t) @@ -212,7 +376,7 @@ func TestFetchL2Node(t *testing.T) { key := preimage.Keccak256Key(hash).PreimageKey() t.Run("AlreadyKnown", func(t *testing.T) { - prefetcher, _, _, kv := createPrefetcher(t) + prefetcher, _, _, _, kv := createPrefetcher(t) require.NoError(t, kv.Put(key, node)) oracle := l2.NewPreimageOracle(asOracleFn(t, prefetcher), asHinter(t, prefetcher)) @@ -221,7 +385,7 @@ func TestFetchL2Node(t *testing.T) { }) t.Run("Unknown", func(t *testing.T) { - prefetcher, _, l2Cl, _ := createPrefetcher(t) + prefetcher, _, _, l2Cl, _ := createPrefetcher(t) l2Cl.ExpectNodeByHash(hash, node, nil) defer l2Cl.MockDebugClient.AssertExpectations(t) @@ -238,7 +402,7 @@ func TestFetchL2Code(t *testing.T) { key := preimage.Keccak256Key(hash).PreimageKey() t.Run("AlreadyKnown", func(t *testing.T) { - prefetcher, _, _, kv := createPrefetcher(t) + prefetcher, _, _, _, kv := createPrefetcher(t) require.NoError(t, kv.Put(key, code)) oracle := l2.NewPreimageOracle(asOracleFn(t, prefetcher), asHinter(t, prefetcher)) @@ -247,7 +411,7 @@ func TestFetchL2Code(t *testing.T) { }) t.Run("Unknown", func(t *testing.T) { - prefetcher, _, l2Cl, _ := createPrefetcher(t) + prefetcher, _, _, l2Cl, _ := createPrefetcher(t) l2Cl.ExpectCodeByHash(hash, code, nil) defer l2Cl.MockDebugClient.AssertExpectations(t) @@ -258,7 +422,7 @@ func TestFetchL2Code(t *testing.T) { } func TestBadHints(t *testing.T) { - prefetcher, _, _, kv := createPrefetcher(t) + prefetcher, _, _, _, kv := createPrefetcher(t) hash := common.Hash{0xad} t.Run("NoSpace", func(t *testing.T) { @@ -277,7 +441,7 @@ func TestBadHints(t *testing.T) { // But it will fail to prefetch when the pre-image isn't available pre, err := prefetcher.GetPreimage(context.Background(), hash) - require.ErrorContains(t, err, "invalid hash") + require.ErrorContains(t, err, "invalid bytes") require.Nil(t, pre) }) @@ -311,10 +475,10 @@ func TestRetryWhenNotAvailableAfterPrefetching(t *testing.T) { node := testutils.RandomData(rng, 30) hash := crypto.Keccak256Hash(node) - _, l1Source, l2Cl, kv := createPrefetcher(t) + _, l1Source, l1BlobSource, l2Cl, kv := createPrefetcher(t) putsToIgnore := 2 kv = &unreliableKvStore{KV: kv, putsToIgnore: putsToIgnore} - prefetcher := NewPrefetcher(testlog.Logger(t, log.LvlInfo), l1Source, l2Cl, kv) + prefetcher := NewPrefetcher(testlog.Logger(t, log.LevelInfo), l1Source, l1BlobSource, l2Cl, kv) // Expect one call for each ignored put, plus one more request for when the put succeeds for i := 0; i < putsToIgnore+1; i++ { @@ -355,18 +519,19 @@ func (m *l2Client) ExpectOutputByRoot(root common.Hash, output eth.Output, err e m.Mock.On("OutputByRoot", root).Once().Return(output, &err) } -func createPrefetcher(t *testing.T) (*Prefetcher, *testutils.MockL1Source, *l2Client, kvstore.KV) { - logger := testlog.Logger(t, log.LvlDebug) +func createPrefetcher(t *testing.T) (*Prefetcher, *testutils.MockL1Source, *testutils.MockBlobsFetcher, *l2Client, kvstore.KV) { + logger := testlog.Logger(t, log.LevelDebug) kv := kvstore.NewMemKV() l1Source := new(testutils.MockL1Source) + l1BlobSource := new(testutils.MockBlobsFetcher) l2Source := &l2Client{ MockL2Client: new(testutils.MockL2Client), MockDebugClient: new(testutils.MockDebugClient), } - prefetcher := NewPrefetcher(logger, l1Source, l2Source, kv) - return prefetcher, l1Source, l2Source, kv + prefetcher := NewPrefetcher(logger, l1Source, l1BlobSource, l2Source, kv) + return prefetcher, l1Source, l1BlobSource, l2Source, kv } func storeBlock(t *testing.T, kv kvstore.KV, block *types.Block, receipts types.Receipts) { @@ -392,6 +557,23 @@ func storeBlock(t *testing.T, kv kvstore.KV, block *types.Block, receipts types. require.NoError(t, kv.Put(preimage.Keccak256Key(block.Hash()).PreimageKey(), headerRlp)) } +func storeBlob(t *testing.T, kv kvstore.KV, commitment eth.Bytes48, blob *eth.Blob) { + // Pre-store versioned hash preimage (commitment) + err := kv.Put(preimage.Sha256Key(sha256.Sum256(commitment[:])).PreimageKey(), commitment[:]) + require.NoError(t, err, "Failed to store versioned hash preimage in kvstore") + + // Pre-store blob field elements + blobKeyBuf := make([]byte, 80) + copy(blobKeyBuf[:48], commitment[:]) + for i := 0; i < params.BlobTxFieldElementsPerBlob; i++ { + binary.BigEndian.PutUint64(blobKeyBuf[72:], uint64(i)) + feKey := crypto.Keccak256Hash(blobKeyBuf) + + err = kv.Put(preimage.BlobKey(feKey).PreimageKey(), blob[i<<5:(i+1)<<5]) + require.NoError(t, err, "Failed to store field element preimage in kvstore") + } +} + func asOracleFn(t *testing.T, prefetcher *Prefetcher) preimage.OracleFn { return func(key preimage.Key) []byte { pre, err := prefetcher.GetPreimage(context.Background(), key.PreimageKey()) diff --git a/op-program/host/prefetcher/retry.go b/op-program/host/prefetcher/retry.go index 601c2820de5b..da9a588d8c3a 100644 --- a/op-program/host/prefetcher/retry.go +++ b/op-program/host/prefetcher/retry.go @@ -59,6 +59,42 @@ func (s *RetryingL1Source) FetchReceipts(ctx context.Context, blockHash common.H var _ L1Source = (*RetryingL1Source)(nil) +type RetryingL1BlobSource struct { + logger log.Logger + source L1BlobSource + strategy retry.Strategy +} + +func NewRetryingL1BlobSource(logger log.Logger, source L1BlobSource) *RetryingL1BlobSource { + return &RetryingL1BlobSource{ + logger: logger, + source: source, + strategy: retry.Exponential(), + } +} + +func (s *RetryingL1BlobSource) GetBlobSidecars(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.BlobSidecar, error) { + return retry.Do(ctx, maxAttempts, s.strategy, func() ([]*eth.BlobSidecar, error) { + sidecars, err := s.source.GetBlobSidecars(ctx, ref, hashes) + if err != nil { + s.logger.Warn("Failed to retrieve blob sidecars", "ref", ref, "err", err) + } + return sidecars, err + }) +} + +func (s *RetryingL1BlobSource) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) { + return retry.Do(ctx, maxAttempts, s.strategy, func() ([]*eth.Blob, error) { + blobs, err := s.source.GetBlobs(ctx, ref, hashes) + if err != nil { + s.logger.Warn("Failed to retrieve blobs", "ref", ref, "err", err) + } + return blobs, err + }) +} + +var _ L1BlobSource = (*RetryingL1BlobSource)(nil) + type RetryingL2Source struct { logger log.Logger source L2Source diff --git a/op-program/host/prefetcher/retry_test.go b/op-program/host/prefetcher/retry_test.go index c6d46d027a48..205b3ce84d0e 100644 --- a/op-program/host/prefetcher/retry_test.go +++ b/op-program/host/prefetcher/retry_test.go @@ -2,6 +2,7 @@ package prefetcher import ( "context" + "crypto/sha256" "errors" "testing" @@ -11,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/retry" @@ -103,7 +105,7 @@ func TestRetryingL1Source(t *testing.T) { } func createL1Source(t *testing.T) (*RetryingL1Source, *testutils.MockL1Source) { - logger := testlog.Logger(t, log.LvlDebug) + logger := testlog.Logger(t, log.LevelDebug) mock := &testutils.MockL1Source{} source := NewRetryingL1Source(logger, mock) // Avoid sleeping in tests by using a fixed retry strategy with no delay @@ -111,6 +113,117 @@ func createL1Source(t *testing.T) (*RetryingL1Source, *testutils.MockL1Source) { return source, mock } +func TestRetryingL1BlobSource(t *testing.T) { + ctx := context.Background() + blob := GetRandBlob(0xFACADE) + commitment, err := kzgCtx.BlobToKZGCommitment(blob, 0) + require.NoError(t, err) + versionedHash := sha256.Sum256(commitment[:]) + versionedHash[0] = params.BlobTxHashVersion + blobHash := eth.IndexedBlobHash{Hash: versionedHash, Index: 0xFACADE} + l1BlockRef := eth.L1BlockRef{Time: 0} + + t.Run("GetBlobs Success", func(t *testing.T) { + source, mock := createL1BlobSource(t) + defer mock.AssertExpectations(t) + mock.ExpectOnGetBlobs( + ctx, + l1BlockRef, + []eth.IndexedBlobHash{blobHash}, + []*eth.Blob{(*eth.Blob)(&blob)}, + nil, + ) + + result, err := source.GetBlobs(ctx, l1BlockRef, []eth.IndexedBlobHash{blobHash}) + require.NoError(t, err) + require.Equal(t, len(result), 1) + require.Equal(t, blob[:], result[0][:]) + }) + + t.Run("GetBlobs Error", func(t *testing.T) { + source, mock := createL1BlobSource(t) + defer mock.AssertExpectations(t) + expectedErr := errors.New("boom") + mock.ExpectOnGetBlobs( + ctx, + l1BlockRef, + []eth.IndexedBlobHash{blobHash}, + nil, + expectedErr, + ) + mock.ExpectOnGetBlobs( + ctx, + l1BlockRef, + []eth.IndexedBlobHash{blobHash}, + []*eth.Blob{(*eth.Blob)(&blob)}, + nil, + ) + + result, err := source.GetBlobs(ctx, l1BlockRef, []eth.IndexedBlobHash{blobHash}) + require.NoError(t, err) + require.Equal(t, len(result), 1) + require.Equal(t, blob[:], result[0][:]) + }) + + t.Run("GetBlobSidecars Success", func(t *testing.T) { + source, mock := createL1BlobSource(t) + defer mock.AssertExpectations(t) + mock.ExpectOnGetBlobSidecars( + ctx, + l1BlockRef, + []eth.IndexedBlobHash{blobHash}, + (eth.Bytes48)(commitment), + []*eth.Blob{(*eth.Blob)(&blob)}, + nil, + ) + + result, err := source.GetBlobSidecars(ctx, l1BlockRef, []eth.IndexedBlobHash{blobHash}) + require.NoError(t, err) + require.Equal(t, len(result), 1) + require.Equal(t, blob[:], result[0].Blob[:]) + require.Equal(t, blobHash.Index, uint64(result[0].Index)) + require.Equal(t, (eth.Bytes48)(commitment), result[0].KZGCommitment) + }) + + t.Run("GetBlobSidecars Error", func(t *testing.T) { + source, mock := createL1BlobSource(t) + defer mock.AssertExpectations(t) + expectedErr := errors.New("boom") + mock.ExpectOnGetBlobSidecars( + ctx, + l1BlockRef, + []eth.IndexedBlobHash{blobHash}, + (eth.Bytes48)(commitment), + []*eth.Blob{(*eth.Blob)(&blob)}, + expectedErr, + ) + mock.ExpectOnGetBlobSidecars( + ctx, + l1BlockRef, + []eth.IndexedBlobHash{blobHash}, + (eth.Bytes48)(commitment), + []*eth.Blob{(*eth.Blob)(&blob)}, + nil, + ) + + result, err := source.GetBlobSidecars(ctx, l1BlockRef, []eth.IndexedBlobHash{blobHash}) + require.NoError(t, err) + require.Equal(t, len(result), 1) + require.Equal(t, blob[:], result[0].Blob[:]) + require.Equal(t, blobHash.Index, uint64(result[0].Index)) + require.Equal(t, (eth.Bytes48)(commitment), result[0].KZGCommitment) + }) +} + +func createL1BlobSource(t *testing.T) (*RetryingL1BlobSource, *testutils.MockBlobsFetcher) { + logger := testlog.Logger(t, log.LvlDebug) + mock := &testutils.MockBlobsFetcher{} + source := NewRetryingL1BlobSource(logger, mock) + // Avoid sleeping in tests by using a fixed retry strategy with no delay + source.strategy = retry.Fixed(0) + return source, mock +} + func TestRetryingL2Source(t *testing.T) { ctx := context.Background() hash := common.Hash{0xab} @@ -216,7 +329,7 @@ func TestRetryingL2Source(t *testing.T) { } func createL2Source(t *testing.T) (*RetryingL2Source, *MockL2Source) { - logger := testlog.Logger(t, log.LvlDebug) + logger := testlog.Logger(t, log.LevelDebug) mock := &MockL2Source{} source := NewRetryingL2Source(logger, mock) // Avoid sleeping in tests by using a fixed retry strategy with no delay diff --git a/op-program/scripts/run-compat.sh b/op-program/scripts/run-compat.sh new file mode 100755 index 000000000000..c01fb7d1af00 --- /dev/null +++ b/op-program/scripts/run-compat.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -euo pipefail + +SCRIPTS_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +COMPAT_DIR="${SCRIPTS_DIR}/../temp/compat" + +TESTNAME="${1?Must specify compat file to run}" +BASEURL="${2:-https://github.com/ethereum-optimism/chain-test-data/releases/download/2024-03-14.3}" + +URL="${BASEURL}/${TESTNAME}.tar.bz" + +mkdir -p "${COMPAT_DIR}" +curl --etag-save "${COMPAT_DIR}/${TESTNAME}-etag.txt" --etag-compare "${COMPAT_DIR}/${TESTNAME}-etag.txt" -L --fail -o "${COMPAT_DIR}/${TESTNAME}.tar.bz" "${URL}" +tar jxf "${COMPAT_DIR}/${TESTNAME}.tar.bz" -C "${COMPAT_DIR}" +# shellcheck disable=SC2046 +"${SCRIPTS_DIR}/../bin/op-program" $(cat "${COMPAT_DIR}/${TESTNAME}/args.txt") diff --git a/op-program/verify/cmd/goerli.go b/op-program/verify/cmd/goerli.go deleted file mode 100644 index ade973a72322..000000000000 --- a/op-program/verify/cmd/goerli.go +++ /dev/null @@ -1,175 +0,0 @@ -package main - -import ( - "context" - "flag" - "fmt" - "math/big" - "os" - "path/filepath" - "strings" - - "github.com/ethereum-optimism/optimism/op-bindings/bindings" - "github.com/ethereum-optimism/optimism/op-node/rollup" - "github.com/ethereum-optimism/optimism/op-program/chainconfig" - "github.com/ethereum-optimism/optimism/op-program/host" - config "github.com/ethereum-optimism/optimism/op-program/host/config" - oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum-optimism/optimism/op-service/sources" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rpc" -) - -func main() { - var l1RpcUrl string - var l1RpcKind string - var l2RpcUrl string - var dataDir string - flag.StringVar(&l1RpcUrl, "l1", "", "L1 RPC URL to use") - flag.StringVar(&l1RpcKind, "l1-rpckind", "alchemy", "L1 RPC kind") - flag.StringVar(&l2RpcUrl, "l2", "", "L2 RPC URL to use") - flag.StringVar(&dataDir, "datadir", "", - "Directory to use for storing pre-images. If not set a temporary directory will be used.") - flag.Parse() - - if l1RpcUrl == "" || l2RpcUrl == "" { - _, _ = fmt.Fprintln(os.Stderr, "Must specify --l1 and --l2 RPC URLs") - os.Exit(2) - } - - goerliOutputAddress := common.HexToAddress("0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0") - err := Run(l1RpcUrl, l1RpcKind, l2RpcUrl, goerliOutputAddress, dataDir) - if err != nil { - _, _ = fmt.Fprintf(os.Stderr, "Failed: %v\n", err.Error()) - os.Exit(1) - } -} - -func Run(l1RpcUrl string, l1RpcKind string, l2RpcUrl string, l2OracleAddr common.Address, dataDir string) error { - ctx := context.Background() - l1RpcClient, err := rpc.Dial(l1RpcUrl) - if err != nil { - return fmt.Errorf("dial L1 client: %w", err) - } - l1Client := ethclient.NewClient(l1RpcClient) - - l2RpcClient, err := rpc.Dial(l2RpcUrl) - if err != nil { - return fmt.Errorf("dial L2 client: %w", err) - } - l2Client := ethclient.NewClient(l2RpcClient) - - outputOracle, err := bindings.NewL2OutputOracle(l2OracleAddr, l1Client) - if err != nil { - return fmt.Errorf("create output oracle bindings: %w", err) - } - - // Find L1 finalized block. Can't be re-orged. - l1BlockNum := big.NewInt(int64(rpc.FinalizedBlockNumber)) - l1HeadBlock, err := l1Client.BlockByNumber(ctx, l1BlockNum) - if err != nil { - return fmt.Errorf("find L1 head: %w", err) - } - fmt.Printf("Found l1 head block number: %v hash: %v\n", l1HeadBlock.NumberU64(), l1HeadBlock.Hash()) - - l1CallOpts := &bind.CallOpts{Context: ctx, BlockNumber: l1BlockNum} - - // Find the latest output root published in this finalized block - latestOutputIndex, err := outputOracle.LatestOutputIndex(l1CallOpts) - if err != nil { - return fmt.Errorf("fetch latest output index: %w", err) - } - output, err := outputOracle.GetL2Output(l1CallOpts, latestOutputIndex) - if err != nil { - return fmt.Errorf("fetch l2 output %v: %w", latestOutputIndex, err) - } - - // Use the previous output as the agreed starting point - agreedOutput, err := outputOracle.GetL2Output(l1CallOpts, new(big.Int).Sub(latestOutputIndex, common.Big1)) - if err != nil { - return fmt.Errorf("fetch l2 output before %v: %w", latestOutputIndex, err) - } - l2BlockAtOutput, err := l2Client.BlockByNumber(ctx, agreedOutput.L2BlockNumber) - if err != nil { - return fmt.Errorf("retrieve agreed block: %w", err) - } - - l2Head := l2BlockAtOutput.Hash() - l2BlockNumber := output.L2BlockNumber - l2Claim := common.Hash(output.OutputRoot) - l1Head := l1HeadBlock.Hash() - - if dataDir == "" { - dataDir, err = os.MkdirTemp("", "oracledata") - if err != nil { - return fmt.Errorf("create temp dir: %w", err) - } - defer func() { - err := os.RemoveAll(dataDir) - if err != nil { - fmt.Println("Failed to remove temp dir:" + err.Error()) - } - }() - } else { - if err := os.MkdirAll(dataDir, 0755); err != nil { - fmt.Printf("Could not create data directory %v: %v", dataDir, err) - os.Exit(1) - } - } - fmt.Printf("Using dir: %s\n", dataDir) - args := []string{ - "--log.level", "DEBUG", - "--network", "goerli", - "--exec", "./bin/op-program-client", - "--datadir", dataDir, - "--l1.head", l1Head.Hex(), - "--l2.head", l2Head.Hex(), - "--l2.outputroot", common.Bytes2Hex(agreedOutput.OutputRoot[:]), - "--l2.claim", l2Claim.Hex(), - "--l2.blocknumber", l2BlockNumber.String(), - } - argsStr := strings.Join(args, " ") - // args.txt is used by run-goerli-verify job for offline verification in CI - if err := os.WriteFile(filepath.Join(dataDir, "args.txt"), []byte(argsStr), 0644); err != nil { - fmt.Printf("Could not write args: %v", err) - os.Exit(1) - } - fmt.Printf("Configuration: %s\n", argsStr) - - logger := oplog.DefaultCLIConfig() - logger.Level = log.LvlDebug - rollupCfg, err := rollup.LoadOPStackRollupConfig(chainconfig.OPGoerliChainConfig.ChainID.Uint64()) - if err != nil { - return fmt.Errorf("failed to load rollup config: %w", err) - } - offlineCfg := config.Config{ - Rollup: rollupCfg, - DataDir: dataDir, - L2ChainConfig: chainconfig.OPGoerliChainConfig, - L2Head: l2Head, - L2OutputRoot: agreedOutput.OutputRoot, - L2Claim: l2Claim, - L2ClaimBlockNumber: l2BlockNumber.Uint64(), - L1Head: l1Head, - } - onlineCfg := offlineCfg - onlineCfg.L1URL = l1RpcUrl - onlineCfg.L2URL = l2RpcUrl - onlineCfg.L1RPCKind = sources.RPCProviderKind(l1RpcKind) - - fmt.Println("Running in online mode") - err = host.Main(oplog.NewLogger(os.Stderr, logger), &onlineCfg) - if err != nil { - return fmt.Errorf("online mode failed: %w", err) - } - - fmt.Println("Running in offline mode") - err = host.Main(oplog.NewLogger(os.Stderr, logger), &offlineCfg) - if err != nil { - return fmt.Errorf("offline mode failed: %w", err) - } - return nil -} diff --git a/op-program/verify/mainnet/cmd/mainnet.go b/op-program/verify/mainnet/cmd/mainnet.go new file mode 100644 index 000000000000..bcd4d5df030d --- /dev/null +++ b/op-program/verify/mainnet/cmd/mainnet.go @@ -0,0 +1,67 @@ +package main + +import ( + "context" + "flag" + "fmt" + "os" + + "github.com/ethereum-optimism/optimism/op-program/chainconfig" + "github.com/ethereum-optimism/optimism/op-program/verify" + "github.com/ethereum/go-ethereum/common" +) + +func main() { + var l1RpcUrl string + var l1RpcKind string + var l1BeaconUrl string + var l2RpcUrl string + var dataDir string + var l1HashStr string + var l2Start uint64 + var l2End uint64 + flag.StringVar(&l1RpcUrl, "l1", "", "L1 RPC URL to use") + flag.StringVar(&l1BeaconUrl, "l1.beacon", "", "L1 Beacon URL to use") + flag.StringVar(&l1RpcKind, "l1-rpckind", "", "L1 RPC kind") + flag.StringVar(&l2RpcUrl, "l2", "", "L2 RPC URL to use") + flag.StringVar(&dataDir, "datadir", "", + "Directory to use for storing pre-images. If not set a temporary directory will be used.") + flag.StringVar(&l1HashStr, "l1.head", "", "Hash of L1 block to use") + flag.Uint64Var(&l2Start, "l2.start", 0, "Block number of agreed L2 block") + flag.Uint64Var(&l2End, "l2.end", 0, "Block number of claimed L2 block") + flag.Parse() + + if l1RpcUrl == "" { + _, _ = fmt.Fprintln(os.Stderr, "Must specify --l1 RPC URL") + os.Exit(2) + } + if l1BeaconUrl == "" { + _, _ = fmt.Fprintln(os.Stderr, "Must specify --l1.beacon URL") + os.Exit(2) + } + if l2RpcUrl == "" { + _, _ = fmt.Fprintln(os.Stderr, "Must specify --l2 RPC URL") + os.Exit(2) + } + + runner, err := verify.NewRunner(l1RpcUrl, l1RpcKind, l1BeaconUrl, l2RpcUrl, dataDir, "op-mainnet", chainconfig.OPMainnetChainConfig) + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "Failed to create runner: %v\n", err.Error()) + os.Exit(1) + } + + if l1HashStr == "" && l2Start == 0 && l2End == 0 { + err = runner.RunToFinalized(context.Background()) + } else { + l1Hash := common.HexToHash(l1HashStr) + if l1Hash == (common.Hash{}) { + _, _ = fmt.Fprintf(os.Stderr, "Invalid --l1.head: %v\n", l1HashStr) + os.Exit(2) + } + err = runner.RunBetweenBlocks(context.Background(), l1Hash, l2Start, l2End) + } + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "Failed: %v\n", err.Error()) + os.Exit(1) + } +} diff --git a/op-program/verify/sepolia/cmd/sepolia.go b/op-program/verify/sepolia/cmd/sepolia.go new file mode 100644 index 000000000000..50c38d4a70ec --- /dev/null +++ b/op-program/verify/sepolia/cmd/sepolia.go @@ -0,0 +1,67 @@ +package main + +import ( + "context" + "flag" + "fmt" + "os" + + "github.com/ethereum-optimism/optimism/op-program/chainconfig" + "github.com/ethereum-optimism/optimism/op-program/verify" + "github.com/ethereum/go-ethereum/common" +) + +func main() { + var l1RpcUrl string + var l1RpcKind string + var l1BeaconUrl string + var l2RpcUrl string + var dataDir string + var l1HashStr string + var l2Start uint64 + var l2End uint64 + flag.StringVar(&l1RpcUrl, "l1", "", "L1 RPC URL to use") + flag.StringVar(&l1BeaconUrl, "l1.beacon", "", "L1 Beacon URL to use") + flag.StringVar(&l1RpcKind, "l1-rpckind", "", "L1 RPC kind") + flag.StringVar(&l2RpcUrl, "l2", "", "L2 RPC URL to use") + flag.StringVar(&dataDir, "datadir", "", + "Directory to use for storing pre-images. If not set a temporary directory will be used.") + flag.StringVar(&l1HashStr, "l1.head", "", "Hash of L1 block to use") + flag.Uint64Var(&l2Start, "l2.start", 0, "Block number of agreed L2 block") + flag.Uint64Var(&l2End, "l2.end", 0, "Block number of claimed L2 block") + flag.Parse() + + if l1RpcUrl == "" { + _, _ = fmt.Fprintln(os.Stderr, "Must specify --l1 RPC URL") + os.Exit(2) + } + if l1BeaconUrl == "" { + _, _ = fmt.Fprintln(os.Stderr, "Must specify --l1.beacon URL") + os.Exit(2) + } + if l2RpcUrl == "" { + _, _ = fmt.Fprintln(os.Stderr, "Must specify --l2 RPC URL") + os.Exit(2) + } + + runner, err := verify.NewRunner(l1RpcUrl, l1RpcKind, l1BeaconUrl, l2RpcUrl, dataDir, "sepolia", chainconfig.OPSepoliaChainConfig) + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "Failed to create runner: %v\n", err.Error()) + os.Exit(1) + } + + if l1HashStr == "" && l2Start == 0 && l2End == 0 { + err = runner.RunToFinalized(context.Background()) + } else { + l1Hash := common.HexToHash(l1HashStr) + if l1Hash == (common.Hash{}) { + _, _ = fmt.Fprintf(os.Stderr, "Invalid --l1.head: %v\n", l1HashStr) + os.Exit(2) + } + err = runner.RunBetweenBlocks(context.Background(), l1Hash, l2Start, l2End) + } + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "Failed: %v\n", err.Error()) + os.Exit(1) + } +} diff --git a/op-program/verify/verify.go b/op-program/verify/verify.go new file mode 100644 index 000000000000..43150cfbc2b4 --- /dev/null +++ b/op-program/verify/verify.go @@ -0,0 +1,244 @@ +package verify + +import ( + "context" + "fmt" + "math/big" + "os" + "path/filepath" + "strconv" + "strings" + "time" + + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-program/host" + "github.com/ethereum-optimism/optimism/op-program/host/config" + "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/dial" + "github.com/ethereum-optimism/optimism/op-service/eth" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/optimism/op-service/retry" + "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" +) + +type Runner struct { + l1RpcUrl string + l1RpcKind string + l1BeaconUrl string + l2RpcUrl string + dataDir string + network string + chainCfg *params.ChainConfig + l2Client *sources.L2Client + logCfg oplog.CLIConfig + setupLog log.Logger + rollupCfg *rollup.Config +} + +func NewRunner(l1RpcUrl string, l1RpcKind string, l1BeaconUrl string, l2RpcUrl string, dataDir string, network string, chainCfg *params.ChainConfig) (*Runner, error) { + ctx := context.Background() + logCfg := oplog.DefaultCLIConfig() + logCfg.Level = log.LevelDebug + + setupLog := oplog.NewLogger(os.Stderr, logCfg) + + l2RawRpc, err := dial.DialRPCClientWithTimeout(ctx, dial.DefaultDialTimeout, setupLog, l2RpcUrl) + if err != nil { + return nil, fmt.Errorf("dial L2 client: %w", err) + } + + rollupCfg, err := rollup.LoadOPStackRollupConfig(chainCfg.ChainID.Uint64()) + if err != nil { + return nil, fmt.Errorf("failed to load rollup config: %w", err) + } + + l2ClientCfg := sources.L2ClientDefaultConfig(rollupCfg, false) + l2RPC := client.NewBaseRPCClient(l2RawRpc) + l2Client, err := sources.NewL2Client(l2RPC, setupLog, nil, l2ClientCfg) + if err != nil { + return nil, fmt.Errorf("failed to create L2 client: %w", err) + } + + return &Runner{ + l1RpcUrl: l1RpcUrl, + l1RpcKind: l1RpcKind, + l1BeaconUrl: l1BeaconUrl, + l2RpcUrl: l2RpcUrl, + dataDir: dataDir, + network: network, + chainCfg: chainCfg, + logCfg: logCfg, + setupLog: setupLog, + l2Client: l2Client, + rollupCfg: rollupCfg, + }, nil +} + +func (r *Runner) RunBetweenBlocks(ctx context.Context, l1Head common.Hash, startBlockNum uint64, endBlockNumber uint64) error { + if startBlockNum >= endBlockNumber { + return fmt.Errorf("start block number %v must be less than end block number %v", startBlockNum, endBlockNumber) + } + + l2Client, err := r.createL2Client(ctx) + if err != nil { + return err + } + defer l2Client.Close() + + agreedBlockInfo, agreedOutputRoot, err := outputAtBlockNum(ctx, l2Client, startBlockNum) + if err != nil { + return fmt.Errorf("failed to find starting block info: %w", err) + } + claimedBlockInfo, claimedOutputRoot, err := outputAtBlockNum(ctx, l2Client, endBlockNumber) + if err != nil { + return fmt.Errorf("failed to find ending block info: %w", err) + } + + return r.run(l1Head, agreedBlockInfo, agreedOutputRoot, claimedOutputRoot, claimedBlockInfo) +} + +func (r *Runner) createL2Client(ctx context.Context) (*sources.L2Client, error) { + l2RawRpc, err := dial.DialRPCClientWithTimeout(ctx, dial.DefaultDialTimeout, r.setupLog, r.l2RpcUrl) + if err != nil { + return nil, fmt.Errorf("dial L2 client: %w", err) + } + l2ClientCfg := sources.L2ClientDefaultConfig(r.rollupCfg, false) + l2RPC := client.NewBaseRPCClient(l2RawRpc) + l2Client, err := sources.NewL2Client(l2RPC, r.setupLog, nil, l2ClientCfg) + if err != nil { + return nil, fmt.Errorf("failed to create L2 client: %w", err) + } + return l2Client, nil +} + +func (r *Runner) RunToFinalized(ctx context.Context) error { + l1Client, err := dial.DialEthClientWithTimeout(ctx, dial.DefaultDialTimeout, r.setupLog, r.l1RpcUrl) + if err != nil { + return fmt.Errorf("failed to dial L1 client: %w", err) + } + + l2Client, err := r.createL2Client(ctx) + if err != nil { + return err + } + defer l2Client.Close() + + l2Finalized, err := retryOp(ctx, func() (eth.BlockInfo, error) { + return l2Client.InfoByLabel(ctx, eth.Finalized) + }) + if err != nil { + return fmt.Errorf("failed to retrieve finalized L2 block: %w", err) + } + + // Retrieve finalized L1 block after finalized L2 block to ensure it is + l1Head, err := retryOp(ctx, func() (*types.Header, error) { + return l1Client.HeaderByNumber(ctx, big.NewInt(rpc.FinalizedBlockNumber.Int64())) + }) + if err != nil { + return fmt.Errorf("failed to retrieve finalized L1 block: %w", err) + } + + // Process the 100 blocks leading up to finalized + startBlockNum := uint64(0) + if l2Finalized.NumberU64() > 100 { + startBlockNum = l2Finalized.NumberU64() - 100 + } + agreedBlockInfo, agreedOutputRoot, err := outputAtBlockNum(ctx, l2Client, startBlockNum) + if err != nil { + return fmt.Errorf("failed to find starting block info: %w", err) + } + claimedBlockInfo, claimedOutputRoot, err := outputAtBlockNum(ctx, l2Client, l2Finalized.NumberU64()) + if err != nil { + return fmt.Errorf("failed to find ending block info: %w", err) + } + + return r.run(l1Head.Hash(), agreedBlockInfo, agreedOutputRoot, claimedOutputRoot, claimedBlockInfo) +} + +func (r *Runner) run(l1Head common.Hash, agreedBlockInfo eth.BlockInfo, agreedOutputRoot common.Hash, claimedOutputRoot common.Hash, claimedBlockInfo eth.BlockInfo) error { + var err error + if r.dataDir == "" { + r.dataDir, err = os.MkdirTemp("", "oracledata") + if err != nil { + return fmt.Errorf("create temp dir: %w", err) + } + defer func() { + err := os.RemoveAll(r.dataDir) + if err != nil { + fmt.Println("Failed to remove temp dir:" + err.Error()) + } + }() + } else { + if err := os.MkdirAll(r.dataDir, 0755); err != nil { + fmt.Printf("Could not create data directory %v: %v", r.dataDir, err) + os.Exit(1) + } + } + fmt.Printf("Using dir: %s\n", r.dataDir) + args := []string{ + "--log.level", "DEBUG", + "--network", r.network, + "--exec", "./bin/op-program-client", + "--datadir", r.dataDir, + "--l1.head", l1Head.Hex(), + "--l2.head", agreedBlockInfo.Hash().Hex(), + "--l2.outputroot", agreedOutputRoot.Hex(), + "--l2.claim", claimedOutputRoot.Hex(), + "--l2.blocknumber", strconv.FormatUint(claimedBlockInfo.NumberU64(), 10), + } + argsStr := strings.Join(args, " ") + // args.txt is used by the verify job for offline verification in CI + if err := os.WriteFile(filepath.Join(r.dataDir, "args.txt"), []byte(argsStr), 0644); err != nil { + fmt.Printf("Could not write args: %v", err) + os.Exit(1) + } + fmt.Printf("Configuration: %s\n", argsStr) + + offlineCfg := config.NewConfig( + r.rollupCfg, r.chainCfg, l1Head, agreedBlockInfo.Hash(), agreedOutputRoot, claimedOutputRoot, claimedBlockInfo.NumberU64()) + offlineCfg.DataDir = r.dataDir + onlineCfg := *offlineCfg + onlineCfg.L1URL = r.l1RpcUrl + onlineCfg.L1BeaconURL = r.l1BeaconUrl + onlineCfg.L2URL = r.l2RpcUrl + if r.l1RpcKind != "" { + onlineCfg.L1RPCKind = sources.RPCProviderKind(r.l1RpcKind) + } + + fmt.Println("Running in online mode") + err = host.Main(oplog.NewLogger(os.Stderr, r.logCfg), &onlineCfg) + if err != nil { + return fmt.Errorf("online mode failed: %w", err) + } + + fmt.Println("Running in offline mode") + err = host.Main(oplog.NewLogger(os.Stderr, r.logCfg), offlineCfg) + if err != nil { + return fmt.Errorf("offline mode failed: %w", err) + } + return nil +} + +func outputAtBlockNum(ctx context.Context, l2Client *sources.L2Client, blockNum uint64) (eth.BlockInfo, common.Hash, error) { + startBlockInfo, err := l2Client.InfoByNumber(ctx, blockNum) + if err != nil { + return nil, common.Hash{}, fmt.Errorf("failed to retrieve info for block %v: %w", startBlockInfo, err) + } + + output, err := retryOp(ctx, func() (*eth.OutputV0, error) { + return l2Client.OutputV0AtBlock(ctx, startBlockInfo.Hash()) + }) + if err != nil { + return nil, common.Hash{}, fmt.Errorf("failed to retrieve agreed output root for block %v: %w", startBlockInfo.Hash(), err) + } + return startBlockInfo, common.Hash(eth.OutputRoot(output)), nil +} + +func retryOp[T any](ctx context.Context, op func() (T, error)) (T, error) { + return retry.Do(ctx, 10, retry.Fixed(time.Second*2), op) +} diff --git a/op-proposer/flags/flags.go b/op-proposer/flags/flags.go index 2ca34179d02c..fa95551236dc 100644 --- a/op-proposer/flags/flags.go +++ b/op-proposer/flags/flags.go @@ -51,27 +51,24 @@ var ( EnvVars: prefixEnvVars("ALLOW_NON_FINALIZED"), } DisputeGameFactoryAddressFlag = &cli.StringFlag{ - Name: "dgf-address", + Name: "game-factory-address", Usage: "Address of the DisputeGameFactory contract", - EnvVars: prefixEnvVars("DGF_ADDRESS"), - Hidden: true, + EnvVars: prefixEnvVars("GAME_FACTORY_ADDRESS"), } ProposalIntervalFlag = &cli.DurationFlag{ Name: "proposal-interval", - Usage: "Interval between submitting L2 output proposals when the DGFAddress is set", + Usage: "Interval between submitting L2 output proposals when the dispute game factory address is set", EnvVars: prefixEnvVars("PROPOSAL_INTERVAL"), - Hidden: true, } DisputeGameTypeFlag = &cli.UintFlag{ - Name: "dg-type", + Name: "game-type", Usage: "Dispute game type to create via the configured DisputeGameFactory", Value: 0, - EnvVars: prefixEnvVars("DG_TYPE"), - Hidden: true, + EnvVars: prefixEnvVars("GAME_TYPE"), } ActiveSequencerCheckDurationFlag = &cli.DurationFlag{ Name: "active-sequencer-check-duration", - Usage: "The duration between checks to determine the active sequencer endpoint. ", + Usage: "The duration between checks to determine the active sequencer endpoint.", Value: 2 * time.Minute, EnvVars: prefixEnvVars("ACTIVE_SEQUENCER_CHECK_DURATION"), } diff --git a/op-proposer/proposer/abi_test.go b/op-proposer/proposer/abi_test.go index 009ca272fb06..7ff576c365e3 100644 --- a/op-proposer/proposer/abi_test.go +++ b/op-proposer/proposer/abi_test.go @@ -103,13 +103,13 @@ func TestManualABIPacking(t *testing.T) { output = testutils.RandomOutputResponse(rng) - txData, err = proposeL2OutputDGFTxData(dgfAbi, uint8(0), output) + txData, err = proposeL2OutputDGFTxData(dgfAbi, uint32(0), output) require.NoError(t, err) opts.GasLimit = 100_000 dgfTx, err := dgf.Create( opts, - uint8(0), + uint32(0), output.OutputRoot, math.U256Bytes(new(big.Int).SetUint64(output.BlockRef.Number)), ) diff --git a/op-proposer/proposer/config.go b/op-proposer/proposer/config.go index 8f3770e6e288..dcd0693549bb 100644 --- a/op-proposer/proposer/config.go +++ b/op-proposer/proposer/config.go @@ -54,7 +54,7 @@ type CLIConfig struct { ProposalInterval time.Duration // DisputeGameType is the type of dispute game to create when submitting an output proposal. - DisputeGameType uint8 + DisputeGameType uint32 // ActiveSequencerCheckDuration is the duration between checks to determine the active sequencer endpoint. ActiveSequencerCheckDuration time.Duration @@ -104,7 +104,7 @@ func NewConfig(ctx *cli.Context) *CLIConfig { PprofConfig: oppprof.ReadCLIConfig(ctx), DGFAddress: ctx.String(flags.DisputeGameFactoryAddressFlag.Name), ProposalInterval: ctx.Duration(flags.ProposalIntervalFlag.Name), - DisputeGameType: uint8(ctx.Uint(flags.DisputeGameTypeFlag.Name)), + DisputeGameType: uint32(ctx.Uint(flags.DisputeGameTypeFlag.Name)), ActiveSequencerCheckDuration: ctx.Duration(flags.ActiveSequencerCheckDurationFlag.Name), } } diff --git a/op-proposer/proposer/driver.go b/op-proposer/proposer/driver.go index 8cbe203970ef..68fee69a1ba2 100644 --- a/op-proposer/proposer/driver.go +++ b/op-proposer/proposer/driver.go @@ -238,7 +238,7 @@ func (l *L2OutputSubmitter) FetchNextOutputInfo(ctx context.Context) (*eth.Outpu return nil, false, nil } - return l.fetchOutput(ctx, nextCheckpointBlock) + return l.FetchOutput(ctx, nextCheckpointBlock) } // FetchCurrentBlockNumber gets the current block number from the [L2OutputSubmitter]'s [RollupClient]. If the `AllowNonFinalized` configuration @@ -267,7 +267,7 @@ func (l *L2OutputSubmitter) FetchCurrentBlockNumber(ctx context.Context) (*big.I return currentBlockNumber, nil } -func (l *L2OutputSubmitter) fetchOutput(ctx context.Context, block *big.Int) (*eth.OutputResponse, bool, error) { +func (l *L2OutputSubmitter) FetchOutput(ctx context.Context, block *big.Int) (*eth.OutputResponse, bool, error) { ctx, cancel := context.WithTimeout(ctx, l.Cfg.NetworkTimeout) defer cancel() @@ -330,7 +330,7 @@ func (l *L2OutputSubmitter) ProposeL2OutputDGFTxData(output *eth.OutputResponse) } // proposeL2OutputDGFTxData creates the transaction data for the DisputeGameFactory's `create` function -func proposeL2OutputDGFTxData(abi *abi.ABI, gameType uint8, output *eth.OutputResponse) ([]byte, error) { +func proposeL2OutputDGFTxData(abi *abi.ABI, gameType uint32, output *eth.OutputResponse) ([]byte, error) { return abi.Pack("create", gameType, output.OutputRoot, math.U256Bytes(new(big.Int).SetUint64(output.BlockRef.Number))) } @@ -451,7 +451,7 @@ func (l *L2OutputSubmitter) loopDGF(ctx context.Context) { break } - output, shouldPropose, err := l.fetchOutput(ctx, blockNumber) + output, shouldPropose, err := l.FetchOutput(ctx, blockNumber) if err != nil || !shouldPropose { break } diff --git a/op-proposer/proposer/l2_output_submitter.go b/op-proposer/proposer/l2_output_submitter.go index e435e47d0b0d..a98e96e63031 100644 --- a/op-proposer/proposer/l2_output_submitter.go +++ b/op-proposer/proposer/l2_output_submitter.go @@ -25,7 +25,7 @@ func Main(version string) cliapp.LifecycleAction { } l := oplog.NewLogger(oplog.AppOut(cliCtx), cfg.LogConfig) - oplog.SetGlobalLogHandler(l.GetHandler()) + oplog.SetGlobalLogHandler(l.Handler()) opservice.ValidateEnvVars(flags.EnvVarPrefix, flags.Flags, l) l.Info("Initializing L2Output Submitter") diff --git a/op-proposer/proposer/service.go b/op-proposer/proposer/service.go index cadefdf32935..0336c2d6bb4f 100644 --- a/op-proposer/proposer/service.go +++ b/op-proposer/proposer/service.go @@ -19,6 +19,7 @@ import ( "github.com/ethereum-optimism/optimism/op-service/oppprof" oprpc "github.com/ethereum-optimism/optimism/op-service/rpc" "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" @@ -36,7 +37,7 @@ type ProposerConfig struct { L2OutputOracleAddr *common.Address DisputeGameFactoryAddr *common.Address - DisputeGameType uint8 + DisputeGameType uint32 // AllowNonFinalized enables the proposal of safe, but non-finalized L2 blocks. // The L1 block-hash embedded in the proposal TX is checked and should ensure the proposal diff --git a/op-service/Makefile b/op-service/Makefile index d458b3c15aa5..5f1dde5d9b3e 100644 --- a/op-service/Makefile +++ b/op-service/Makefile @@ -1,9 +1,20 @@ +PROTOS := ./proto/src +PROTO_GEN := ./proto/gen + test: go test -v ./... generate-mocks: go generate ./... +.PHONY: \ + test \ + lint \ + generate-mocks \ + fuzz \ + clean \ + protoc + fuzz: go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzExecutionPayloadUnmarshal ./eth go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzExecutionPayloadMarshalUnmarshalV1 ./eth @@ -13,7 +24,14 @@ fuzz: go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzEncodeDecodeBlob ./eth go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzDetectNonBijectivity ./eth -.PHONY: \ - test \ - generate-mocks \ - fuzz +clean: + find $(PROTO_GEN) -name "*.pb.go" -type f | xargs rm -rf + mkdir -p $(PROTO_GEN) + +protoc: clean + protoc -I $(PROTOS) \ + --go_out=$(PROTO_GEN) \ + --go_opt=paths=source_relative \ + --go-grpc_out=$(PROTO_GEN) \ + --go-grpc_opt=paths=source_relative \ + $$(find $(PROTOS) -name '*.proto') diff --git a/op-service/client/http.go b/op-service/client/http.go index 055e4b0f3c78..7b5cc680eac8 100644 --- a/op-service/client/http.go +++ b/op-service/client/http.go @@ -23,16 +23,40 @@ type HTTP interface { type BasicHTTPClient struct { endpoint string - log log.Logger - client *http.Client + header http.Header // optional header to use in every request + + log log.Logger + client *http.Client } -func NewBasicHTTPClient(endpoint string, log log.Logger) *BasicHTTPClient { - return &BasicHTTPClient{ +func NewBasicHTTPClient(endpoint string, log log.Logger, opts ...BasicHTTPClientOption) *BasicHTTPClient { + c := &BasicHTTPClient{ endpoint: endpoint, log: log, client: &http.Client{Timeout: DefaultTimeoutSeconds * time.Second}, } + + for _, opt := range opts { + opt.Apply(c) + } + + return c +} + +type BasicHTTPClientOption interface { + Apply(c *BasicHTTPClient) +} + +type BasicHTTPClientOptionFn func(*BasicHTTPClient) + +func (fn BasicHTTPClientOptionFn) Apply(c *BasicHTTPClient) { + fn(c) +} + +func WithHeader(h http.Header) BasicHTTPClientOption { + return BasicHTTPClientOptionFn(func(c *BasicHTTPClient) { + c.header = h + }) } var ErrNoEndpoint = errors.New("no endpoint is configured") @@ -54,10 +78,16 @@ func (cl *BasicHTTPClient) Get(ctx context.Context, p string, query url.Values, if err != nil { return nil, fmt.Errorf("%w: failed to construct request", err) } - for k, values := range headers { - for _, v := range values { - req.Header.Add(k, v) + addHTTPHeaders(req.Header, cl.header, headers) + return cl.client.Do(req) +} + +func addHTTPHeaders(header http.Header, hs ...http.Header) { + for _, h := range hs { + for key, values := range h { + for _, value := range values { + header.Add(key, value) + } } } - return cl.client.Do(req) } diff --git a/op-service/client/http_test.go b/op-service/client/http_test.go new file mode 100644 index 000000000000..60fd9fd9873f --- /dev/null +++ b/op-service/client/http_test.go @@ -0,0 +1,100 @@ +package client + +import ( + "context" + "net/http" + "net/http/httptest" + "net/url" + "testing" + + "golang.org/x/exp/slog" + + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/stretchr/testify/require" +) + +func TestBasicHTTPClient(t *testing.T) { + called := make(chan *http.Request, 1) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + called <- r + })) + defer ts.Close() + + // generate deep clones + mkhdr := func() http.Header { + return http.Header{ + "Foo": []string{"bar", "baz"}, + "Superchain": []string{"op"}, + } + } + opt := WithHeader(mkhdr()) + c := NewBasicHTTPClient(ts.URL, testlog.Logger(t, slog.LevelInfo), opt) + + const ep = "/api/version" + query := url.Values{ + "key": []string{"123"}, + } + getheader := http.Header{ + "Fruits": []string{"apple"}, + "Superchain": []string{"base"}, + } + resp, err := c.Get(context.Background(), ep, query, getheader) + require.NoError(t, err) + defer resp.Body.Close() + + require.Equal(t, http.StatusOK, resp.StatusCode) + req := <-called + require.Equal(t, ep, req.URL.Path) + require.Equal(t, query, req.URL.Query()) + require.ElementsMatch(t, req.Header.Values("Foo"), mkhdr()["Foo"]) + require.ElementsMatch(t, req.Header.Values("Fruits"), getheader["Fruits"]) + require.ElementsMatch(t, req.Header.Values("Superchain"), []string{"op", "base"}) +} + +func TestAddHTTPHeaders(t *testing.T) { + for _, test := range []struct { + desc string + expheader http.Header + headers []http.Header + }{ + { + desc: "all-empty", + expheader: http.Header{}, + headers: nil, + }, + { + desc: "1-header-and-nils", + expheader: http.Header{"Foo": []string{"bar"}}, + headers: []http.Header{ + nil, + {"Foo": []string{"bar"}}, + nil, + }, + }, + { + desc: "2-headers", + expheader: http.Header{ + "Foo": []string{"bar", "baz"}, + "Super": []string{"chain"}, + "Fruit": []string{"apple"}, + }, + headers: []http.Header{ + { + "Foo": []string{"bar"}, + "Super": []string{"chain"}, + }, + { + "Foo": []string{"baz"}, + "Fruit": []string{"apple"}, + }, + }, + }, + } { + t.Run(test.desc, func(t *testing.T) { + h := make(http.Header) + addHTTPHeaders(h, test.headers...) + require.Equal(t, test.expheader, h) + }) + } +} diff --git a/op-service/client/polling_test.go b/op-service/client/polling_test.go index a0210d911a48..721cd326ca49 100644 --- a/op-service/client/polling_test.go +++ b/op-service/client/polling_test.go @@ -73,8 +73,7 @@ func (m *MockRPC) popResult() { } func TestPollingClientSubscribeUnsubscribe(t *testing.T) { - lgr := log.New() - lgr.SetHandler(log.DiscardHandler()) + lgr := log.NewLogger(log.DiscardHandler()) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -134,8 +133,7 @@ func TestPollingClientSubscribeUnsubscribe(t *testing.T) { } func TestPollingClientErrorRecovery(t *testing.T) { - lgr := log.New() - lgr.SetHandler(log.DiscardHandler()) + lgr := log.NewLogger(log.DiscardHandler()) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -165,8 +163,7 @@ func TestPollingClientErrorRecovery(t *testing.T) { } func TestPollingClientClose(t *testing.T) { - lgr := log.New() - lgr.SetHandler(log.DiscardHandler()) + lgr := log.NewLogger(log.DiscardHandler()) ctx, cancel := context.WithCancel(context.Background()) defer cancel() diff --git a/op-service/clock/advancing.go b/op-service/clock/advancing.go index c57bf23a7901..a441c0b8982c 100644 --- a/op-service/clock/advancing.go +++ b/op-service/clock/advancing.go @@ -55,6 +55,7 @@ func (c *AdvancingClock) Stop() { // Already stopped return } + c.ticker.Stop() c.quit <- nil } diff --git a/op-service/clock/simple.go b/op-service/clock/simple.go new file mode 100644 index 000000000000..1f685d180372 --- /dev/null +++ b/op-service/clock/simple.go @@ -0,0 +1,22 @@ +package clock + +import ( + "sync/atomic" + "time" +) + +type SimpleClock struct { + unix atomic.Uint64 +} + +func NewSimpleClock() *SimpleClock { + return &SimpleClock{} +} + +func (c *SimpleClock) SetTime(u uint64) { + c.unix.Store(u) +} + +func (c *SimpleClock) Now() time.Time { + return time.Unix(int64(c.unix.Load()), 0) +} diff --git a/op-service/clock/simple_test.go b/op-service/clock/simple_test.go new file mode 100644 index 000000000000..3760f1033ceb --- /dev/null +++ b/op-service/clock/simple_test.go @@ -0,0 +1,52 @@ +package clock + +import ( + "sync/atomic" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestSimpleClock_Now(t *testing.T) { + c := NewSimpleClock() + require.Equal(t, time.Unix(0, 0), c.Now()) + expectedTime := uint64(time.Now().Unix()) + c.unix = atomic.Uint64{} + c.unix.Store(expectedTime) + require.Equal(t, time.Unix(int64(expectedTime), 0), c.Now()) +} + +func TestSimpleClock_SetTime(t *testing.T) { + tests := []struct { + name string + expectedTime int64 + }{ + { + name: "SetZeroTime", + expectedTime: 0, + }, + { + name: "SetZeroUnixTime", + expectedTime: time.Unix(0, 0).Unix(), + }, + + { + name: "SetCurrentTime", + expectedTime: time.Now().Unix(), + }, + { + name: "SetFutureTime", + expectedTime: time.Now().Add(time.Hour).Unix(), + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + c := NewSimpleClock() + c.SetTime(uint64(test.expectedTime)) + require.Equal(t, time.Unix(test.expectedTime, 0), c.Now()) + }) + } +} diff --git a/op-service/clock/util.go b/op-service/clock/util.go new file mode 100644 index 000000000000..dc564c652fff --- /dev/null +++ b/op-service/clock/util.go @@ -0,0 +1,25 @@ +package clock + +import ( + "time" +) + +type RWClock interface { + Now() time.Time +} + +// MinCheckedTimestamp returns the minimum checked unix timestamp. +// If the duration is 0, the returned minimum timestamp is 0. +// Otherwise, the minimum timestamp is the current unix time minus the duration. +// The subtraction operation is checked and returns 0 on underflow. +func MinCheckedTimestamp(clock RWClock, duration time.Duration) uint64 { + if duration.Seconds() == 0 { + return 0 + } + // To compute t-d for a duration d, use t.Add(-d). + // See https://pkg.go.dev/time#Time.Sub + if clock.Now().Unix() > int64(duration.Seconds()) { + return uint64(clock.Now().Add(-duration).Unix()) + } + return 0 +} diff --git a/op-service/clock/util_test.go b/op-service/clock/util_test.go new file mode 100644 index 000000000000..b2c5e3f50259 --- /dev/null +++ b/op-service/clock/util_test.go @@ -0,0 +1,64 @@ +package clock + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestMinCheckedTimestamp(t *testing.T) { + tests := []struct { + name string + now time.Time + duration time.Duration + want uint64 + }{ + { + name: "ZeroDurationZeroClock", + now: time.Unix(0, 0), + duration: 0, + want: 0, + }, + { + name: "ZeroDurationPositiveClock", + now: time.Unix(1, 0), + duration: 0, + want: 0, + }, + { + name: "UnderflowZeroClock", + now: time.Unix(0, 0), + duration: time.Second, + want: 0, + }, + { + name: "UnderflowPositiveClock", + now: time.Unix(1, 0), + duration: time.Second * 2, + want: 0, + }, + { + name: "CorrectArithmetic", + now: time.Unix(100, 0), + duration: time.Second * 10, + want: 90, + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + clock := &mockClock{now: test.now} + require.Equal(t, test.want, MinCheckedTimestamp(clock, test.duration)) + }) + } +} + +type mockClock struct { + now time.Time +} + +func (m *mockClock) Now() time.Time { + return m.now +} diff --git a/op-service/dial/active_l2_provider_test.go b/op-service/dial/active_l2_provider_test.go index 5790c3dbd71c..e9b532cc10bd 100644 --- a/op-service/dial/active_l2_provider_test.go +++ b/op-service/dial/active_l2_provider_test.go @@ -67,7 +67,7 @@ func (et *endpointProviderTest) newActiveL2RollupProvider(checkDuration time.Dur rollupUrls, checkDuration, 1*time.Minute, - testlog.Logger(et.t, log.LvlDebug), + testlog.Logger(et.t, log.LevelDebug), mockRollupDialer, ) } @@ -116,7 +116,7 @@ func (et *endpointProviderTest) newActiveL2EndpointProvider(checkDuration time.D rollupUrls, checkDuration, 1*time.Minute, - testlog.Logger(et.t, log.LvlDebug), + testlog.Logger(et.t, log.LevelDebug), mockEthDialer, mockRollupDialer, ) diff --git a/op-service/eigenda/cli.go b/op-service/eigenda/cli.go new file mode 100644 index 000000000000..ed8c1672e767 --- /dev/null +++ b/op-service/eigenda/cli.go @@ -0,0 +1,69 @@ +package eigenda + +import ( + "errors" + "time" + + opservice "github.com/ethereum-optimism/optimism/op-service" + "github.com/urfave/cli/v2" +) + +const ( + RPCFlagName = "da-rpc" + StatusQueryRetryIntervalFlagName = "da-status-query-retry-interval" + StatusQueryTimeoutFlagName = "da-status-query-timeout" +) + +type CLIConfig struct { + RPC string + StatusQueryRetryInterval time.Duration + StatusQueryTimeout time.Duration +} + +// NewConfig parses the Config from the provided flags or environment variables. +func ReadCLIConfig(ctx *cli.Context) CLIConfig { + return CLIConfig{ + /* Required Flags */ + RPC: ctx.String(RPCFlagName), + StatusQueryRetryInterval: ctx.Duration(StatusQueryRetryIntervalFlagName), + StatusQueryTimeout: ctx.Duration(StatusQueryTimeoutFlagName), + } +} + +func (m CLIConfig) Check() error { + if m.RPC == "" { + return errors.New("must provide a DA RPC url") + } + if m.StatusQueryTimeout == 0 { + return errors.New("DA status query timeout must be greater than 0") + } + if m.StatusQueryRetryInterval == 0 { + return errors.New("DA status query retry interval must be greater than 0") + } + return nil +} + +func CLIFlags(envPrefix string) []cli.Flag { + prefixEnvVars := func(name string) []string { + return opservice.PrefixEnvVar(envPrefix, name) + } + return []cli.Flag{ + &cli.StringFlag{ + Name: RPCFlagName, + Usage: "RPC endpoint of the EigenDA disperser", + EnvVars: prefixEnvVars("DA_RPC"), + }, + &cli.DurationFlag{ + Name: StatusQueryTimeoutFlagName, + Usage: "Timeout for aborting an EigenDA blob dispersal if the disperser does not report that the blob has been confirmed dispersed.", + Value: 1 * time.Minute, + EnvVars: prefixEnvVars("DA_STATUS_QUERY_TIMEOUT"), + }, + &cli.DurationFlag{ + Name: StatusQueryRetryIntervalFlagName, + Usage: "Wait time between retries of EigenDA blob status queries (made while waiting for a blob to be confirmed by)", + Value: 5 * time.Second, + EnvVars: prefixEnvVars("DA_STATUS_QUERY_INTERVAL"), + }, + } +} diff --git a/op-service/eigenda/config.go b/op-service/eigenda/config.go new file mode 100644 index 000000000000..b18598103c58 --- /dev/null +++ b/op-service/eigenda/config.go @@ -0,0 +1,40 @@ +package eigenda + +import ( + "fmt" + "math" + "time" + + "github.com/urfave/cli/v2" +) + +type Config struct { + // TODO(eigenlayer): Update quorum ID command-line parameters to support passing + // and arbitrary number of quorum IDs. + + // DaRpc is the HTTP provider URL for the Data Availability node. + RPC string + + // The total amount of time that the batcher will spend waiting for EigenDA to confirm a blob + StatusQueryTimeout time.Duration + + // The amount of time to wait between status queries of a newly dispersed blob + StatusQueryRetryInterval time.Duration +} + +// We add this because the urfave/cli library doesn't support uint32 specifically +func Uint32(ctx *cli.Context, flagName string) uint32 { + daQuorumIDLong := ctx.Uint64(flagName) + daQuorumID, success := SafeConvertUInt64ToUInt32(daQuorumIDLong) + if !success { + panic(fmt.Errorf("%s must be in the uint32 range", flagName)) + } + return daQuorumID +} + +func SafeConvertUInt64ToUInt32(val uint64) (uint32, bool) { + if val <= math.MaxUint32 { + return uint32(val), true + } + return 0, false +} diff --git a/op-service/eigenda/da.go b/op-service/eigenda/da.go new file mode 100644 index 000000000000..d613f043823d --- /dev/null +++ b/op-service/eigenda/da.go @@ -0,0 +1,118 @@ +package eigenda + +import ( + "context" + "crypto/tls" + "encoding/base64" + "encoding/hex" + "fmt" + "time" + + "github.com/Layr-Labs/eigenda/api/grpc/disperser" + "github.com/Layr-Labs/eigenda/encoding/utils/codec" + "github.com/ethereum/go-ethereum/log" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +type IEigenDA interface { + RetrieveBlob(ctx context.Context, BatchHeaderHash []byte, BlobIndex uint32) ([]byte, error) + DisperseBlob(ctx context.Context, txData []byte) (*disperser.BlobInfo, error) +} + +type EigenDA struct { + Config + + Log log.Logger +} + +func (m *EigenDA) RetrieveBlob(ctx context.Context, BatchHeaderHash []byte, BlobIndex uint32) ([]byte, error) { + config := &tls.Config{} + credential := credentials.NewTLS(config) + dialOptions := []grpc.DialOption{grpc.WithTransportCredentials(credential)} + conn, err := grpc.Dial(m.RPC, dialOptions...) + if err != nil { + return nil, err + } + daClient := disperser.NewDisperserClient(conn) + + reply, err := daClient.RetrieveBlob(ctx, &disperser.RetrieveBlobRequest{ + BatchHeaderHash: BatchHeaderHash, + BlobIndex: BlobIndex, + }) + if err != nil { + return nil, err + } + + // decode modulo bn254 + decodedData := codec.RemoveEmptyByteFromPaddedBytes(reply.Data) + + return decodedData, nil +} + +func (m *EigenDA) DisperseBlob(ctx context.Context, txData []byte) (*disperser.BlobInfo, error) { + m.Log.Info("Attempting to disperse blob to EigenDA") + config := &tls.Config{} + credential := credentials.NewTLS(config) + dialOptions := []grpc.DialOption{grpc.WithTransportCredentials(credential)} + conn, err := grpc.Dial(m.RPC, dialOptions...) + if err != nil { + return nil, err + } + daClient := disperser.NewDisperserClient(conn) + + // encode modulo bn254 + encodedTxData := codec.ConvertByPaddingEmptyByte(txData) + + disperseReq := &disperser.DisperseBlobRequest{ + Data: encodedTxData, + } + disperseRes, err := daClient.DisperseBlob(ctx, disperseReq) + + if err != nil || disperseRes == nil { + m.Log.Error("Unable to disperse blob to EigenDA, aborting", "err", err) + return nil, err + } + + if disperseRes.Result == disperser.BlobStatus_UNKNOWN || + disperseRes.Result == disperser.BlobStatus_FAILED { + m.Log.Error("Unable to disperse blob to EigenDA, aborting", "err", err) + return nil, fmt.Errorf("reply status is %d", disperseRes.Result) + } + + base64RequestID := base64.StdEncoding.EncodeToString(disperseRes.RequestId) + + m.Log.Info("Blob disepersed to EigenDA, now waiting for confirmation", "requestID", base64RequestID) + + var statusRes *disperser.BlobStatusReply + timeoutTime := time.Now().Add(m.StatusQueryTimeout) + // Wait before first status check + time.Sleep(m.StatusQueryRetryInterval) + for time.Now().Before(timeoutTime) { + statusRes, err = daClient.GetBlobStatus(ctx, &disperser.BlobStatusRequest{ + RequestId: disperseRes.RequestId, + }) + if err != nil { + m.Log.Warn("Unable to retrieve blob dispersal status, will retry", "requestID", base64RequestID, "err", err) + } else if statusRes.Status == disperser.BlobStatus_CONFIRMED || statusRes.Status == disperser.BlobStatus_FINALIZED { + // TODO(eigenlayer): As long as fault proofs are disabled, we can move on once a blob is confirmed + // but not yet finalized, without further logic. Once fault proofs are enabled, we will need to update + // the proposer to wait until the blob associated with an L2 block has been finalized, i.e. the EigenDA + // contracts on Ethereum have confirmed the full availability of the blob on EigenDA. + batchHeaderHashHex := fmt.Sprintf("0x%s", hex.EncodeToString(statusRes.Info.BlobVerificationProof.BatchMetadata.BatchHeaderHash)) + m.Log.Info("Successfully dispersed blob to EigenDA", "requestID", base64RequestID, "batchHeaderHash", batchHeaderHashHex) + return statusRes.Info, nil + } else if statusRes.Status == disperser.BlobStatus_UNKNOWN || + statusRes.Status == disperser.BlobStatus_FAILED { + m.Log.Error("EigenDA blob dispersal failed in processing", "requestID", base64RequestID, "err", err) + return nil, fmt.Errorf("eigenDA blob dispersal failed in processing with reply status %d", statusRes.Status) + } else { + m.Log.Warn("Still waiting for confirmation from EigenDA", "requestID", base64RequestID) + } + + // Wait before first status check + time.Sleep(m.StatusQueryRetryInterval) + } + + return nil, fmt.Errorf("timed out getting EigenDA status for dispersed blob key: %s", base64RequestID) +} diff --git a/op-service/eigenda/derivation.go b/op-service/eigenda/derivation.go new file mode 100644 index 000000000000..3b020899b179 --- /dev/null +++ b/op-service/eigenda/derivation.go @@ -0,0 +1,5 @@ +package eigenda + +// Useful to dinstiguish between plain calldata and alt-da blob refs +// Support seamless migration of existing rollups using ETH DA +const DerivationVersionEigenda = 0xed diff --git a/op-service/eth/blob_test.go b/op-service/eth/blob_test.go index 4334bbd935e4..83e21ed88b4e 100644 --- a/op-service/eth/blob_test.go +++ b/op-service/eth/blob_test.go @@ -44,6 +44,7 @@ func TestSmallBlobEncoding(t *testing.T) { require.Equal(t, data, decoded) // only 10 bytes of data + data = Data(make([]byte, 10)) data[9] = 0xFF err = b.FromData(data) require.NoError(t, err) @@ -157,8 +158,6 @@ func FuzzDetectNonBijectivity(f *testing.F) { }) } -// TODO(optimism#8872): Create more test vectors to implement one-way tests confirming that -// specific inputs yield desired outputs. func TestDecodeTestVectors(t *testing.T) { cases := []struct { input, output string @@ -185,6 +184,21 @@ func TestDecodeTestVectors(t *testing.T) { input: "\x00\x00\x01\xFB\xFD", err: ErrBlobInvalidLength, }, + { + // encode len=10 + input: "\x00\x00\x00\x00\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff", + output: "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff", + }, + { + // decode what should be 27 0xFF bytes + input: "\x00\x00\x00\x00\x1b\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", + output: "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", + }, + { + // decode what should be 32 0xFF bytes + input: "\x3f\x00\x00\x00\x20\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x30\xff\xff\xff\xff", + output: "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", + }, } var b Blob @@ -202,6 +216,53 @@ func TestDecodeTestVectors(t *testing.T) { } } +func TestEncodeTestVectors(t *testing.T) { + cases := []struct { + input, output string + err error + }{ + { + // empty (all zeros) blob should decode as empty string + input: "", + output: "", + }, + { + // max input data + input: string(make([]byte, MaxBlobDataSize)), + output: "\x00\x00\x01\xfb\xfc", + }, + { + // input data too big + input: string(make([]byte, MaxBlobDataSize+1)), + output: "", + err: ErrBlobInputTooLarge, + }, + { + // 27 bytes each with high order bits set (should cleanly fit in the first FE along with the version+length) + input: "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", + output: "\x00\x00\x00\x00\x1b\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", + }, + { + // 28 bytes each with high order bits set, requires high bits spilling into byte 0 and last byte + input: "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", + output: "\x3f\x00\x00\x00\x1c\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x30", + }, + } + + var b, testBlob Blob + for _, c := range cases { + err := b.FromData(Data(c.input)) + if c.err != nil { + require.ErrorIs(t, err, c.err) + } else { + require.NoError(t, err) + testBlob.Clear() + copy(testBlob[:], []byte(c.output)) + require.Equal(t, testBlob, b) + } + } +} + func TestExtraneousData(t *testing.T) { var b Blob // make sure 0 length blob with non-zero bits in upper byte are detected & rejected diff --git a/op-service/eth/blobs_api.go b/op-service/eth/blobs_api.go index b4fc9d011f85..3dbff1745bc2 100644 --- a/op-service/eth/blobs_api.go +++ b/op-service/eth/blobs_api.go @@ -1,7 +1,6 @@ package eth type BlobSidecar struct { - Slot Uint64String `json:"slot"` Blob Blob `json:"blob"` Index Uint64String `json:"index"` KZGCommitment Bytes48 `json:"kzg_commitment"` @@ -20,7 +19,6 @@ type APIBlobSidecar struct { func (sc *APIBlobSidecar) BlobSidecar() *BlobSidecar { return &BlobSidecar{ - Slot: sc.SignedBlockHeader.Message.Slot, Blob: sc.Blob, Index: sc.Index, KZGCommitment: sc.KZGCommitment, diff --git a/op-service/eth/output.go b/op-service/eth/output.go index 8cadaeb26c1e..516829d93df9 100644 --- a/op-service/eth/output.go +++ b/op-service/eth/output.go @@ -16,6 +16,11 @@ type OutputResponse struct { Status *SyncStatus `json:"syncStatus"` } +type SafeHeadResponse struct { + L1Block BlockID `json:"l1Block"` + SafeHead BlockID `json:"safeHead"` +} + var ( ErrInvalidOutput = errors.New("invalid output") ErrInvalidOutputVersion = errors.New("invalid output version") diff --git a/op-service/eth/ssz_test.go b/op-service/eth/ssz_test.go index 23c90266b49b..fdaded1c19e6 100644 --- a/op-service/eth/ssz_test.go +++ b/op-service/eth/ssz_test.go @@ -67,7 +67,7 @@ func FuzzExecutionPayloadMarshalUnmarshalV1(f *testing.F) { extraData = extraData[:32] } payload.ExtraData = extraData - payload.BaseFeePerGas.SetBytes(data[:32]) + (*uint256.Int)(&payload.BaseFeePerGas).SetBytes(data[:32]) payload.BlockHash = *(*common.Hash)(data[:32]) payload.Transactions = make([]Data, txs) for i := 0; i < int(txs); i++ { @@ -124,7 +124,7 @@ func FuzzExecutionPayloadMarshalUnmarshalV2(f *testing.F) { extraData = extraData[:32] } payload.ExtraData = extraData - payload.BaseFeePerGas.SetBytes(data[:32]) + (*uint256.Int)(&payload.BaseFeePerGas).SetBytes(data[:32]) payload.BlockHash = *(*common.Hash)(data[:32]) payload.Transactions = make([]Data, txs) for i := 0; i < int(txs); i++ { @@ -196,7 +196,7 @@ func FuzzExecutionPayloadMarshalUnmarshalV3(f *testing.F) { extraData = extraData[:32] } payload.ExtraData = extraData - payload.BaseFeePerGas.SetBytes(data[:32]) + (*uint256.Int)(&payload.BaseFeePerGas).SetBytes(data[:32]) payload.BlockHash = *(*common.Hash)(data[:32]) payload.Transactions = make([]Data, txs) for i := 0; i < int(txs); i++ { @@ -319,7 +319,6 @@ func TestOPB04(t *testing.T) { require.Error(t, err) require.Equal(t, ErrExtraDataTooLarge, err) } - } func createPayloadWithWithdrawals(w *types.Withdrawals) *ExecutionPayload { @@ -334,11 +333,11 @@ func createPayloadWithWithdrawals(w *types.Withdrawals) *ExecutionPayload { GasLimit: Uint64Quantity(333), GasUsed: Uint64Quantity(444), Timestamp: Uint64Quantity(555), - ExtraData: common.Hex2Bytes("6666"), - BaseFeePerGas: *uint256.NewInt(777), + ExtraData: common.FromHex("6666"), + BaseFeePerGas: Uint256Quantity(*uint256.NewInt(777)), BlockHash: common.HexToHash("0x888"), Withdrawals: w, - Transactions: []Data{common.Hex2Bytes("9999")}, + Transactions: []Data{common.FromHex("9999")}, } } diff --git a/op-service/eth/types.go b/op-service/eth/types.go index bb7e4c6cdd14..58d16c3cdd22 100644 --- a/op-service/eth/types.go +++ b/op-service/eth/types.go @@ -148,11 +148,17 @@ func (b BytesMax32) String() string { return hexutil.Encode(b) } -type Uint256Quantity = uint256.Int +type Uint256Quantity = hexutil.U256 type Data = hexutil.Bytes -type PayloadID = engine.PayloadID +type ( + PayloadID = engine.PayloadID + PayloadInfo struct { + ID PayloadID + Timestamp uint64 + } +) type ExecutionPayloadEnvelope struct { ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot,omitempty"` @@ -230,7 +236,7 @@ func (envelope *ExecutionPayloadEnvelope) CheckBlockHash() (actual common.Hash, Extra: payload.ExtraData, MixDigest: common.Hash(payload.PrevRandao), Nonce: types.BlockNonce{}, // zeroed, proof-of-work legacy - BaseFee: payload.BaseFeePerGas.ToBig(), + BaseFee: (*uint256.Int)(&payload.BaseFeePerGas).ToBig(), ParentBeaconRoot: envelope.ParentBeaconBlockRoot, } @@ -269,7 +275,7 @@ func BlockAsPayload(bl *types.Block, canyonForkTime *uint64) (*ExecutionPayload, GasUsed: Uint64Quantity(bl.GasUsed()), Timestamp: Uint64Quantity(bl.Time()), ExtraData: bl.Extra(), - BaseFeePerGas: *baseFee, + BaseFeePerGas: Uint256Quantity(*baseFee), BlockHash: bl.Hash(), Transactions: opaqueTxs, ExcessBlobGas: (*Uint64Quantity)(bl.ExcessBlobGas()), @@ -283,6 +289,17 @@ func BlockAsPayload(bl *types.Block, canyonForkTime *uint64) (*ExecutionPayload, return payload, nil } +func BlockAsPayloadEnv(bl *types.Block, canyonForkTime *uint64) (*ExecutionPayloadEnvelope, error) { + payload, err := BlockAsPayload(bl, canyonForkTime) + if err != nil { + return nil, err + } + return &ExecutionPayloadEnvelope{ + ExecutionPayload: payload, + ParentBeaconBlockRoot: bl.BeaconRoot(), + }, nil +} + type PayloadAttributes struct { // value for the timestamp field of the new payload Timestamp Uint64Quantity `json:"timestamp"` @@ -292,14 +309,17 @@ type PayloadAttributes struct { SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient"` // Withdrawals to include into the block -- should be nil or empty depending on Shanghai enablement Withdrawals *types.Withdrawals `json:"withdrawals,omitempty"` + // parentBeaconBlockRoot optional extension in Dencun + ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot,omitempty"` + + // Optimism additions + // Transactions to force into the block (always at the start of the transactions list). Transactions []Data `json:"transactions,omitempty"` // NoTxPool to disable adding any transactions from the transaction-pool. NoTxPool bool `json:"noTxPool,omitempty"` // GasLimit override GasLimit *Uint64Quantity `json:"gasLimit,omitempty"` - // parentBeaconBlockRoot optional extension in Dencun - ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot,omitempty"` } type ExecutePayloadStatus string @@ -454,3 +474,17 @@ func (v *Uint64String) UnmarshalText(b []byte) error { *v = Uint64String(n) return nil } + +type EngineAPIMethod string + +const ( + FCUV1 EngineAPIMethod = "engine_forkchoiceUpdatedV1" + FCUV2 EngineAPIMethod = "engine_forkchoiceUpdatedV2" + FCUV3 EngineAPIMethod = "engine_forkchoiceUpdatedV3" + + NewPayloadV2 EngineAPIMethod = "engine_newPayloadV2" + NewPayloadV3 EngineAPIMethod = "engine_newPayloadV3" + + GetPayloadV2 EngineAPIMethod = "engine_getPayloadV2" + GetPayloadV3 EngineAPIMethod = "engine_getPayloadV3" +) diff --git a/op-service/flags/flags.go b/op-service/flags/flags.go index ae0ce39a2b4d..31ca3eb5bc6b 100644 --- a/op-service/flags/flags.go +++ b/op-service/flags/flags.go @@ -11,44 +11,56 @@ import ( ) const ( - RollupConfigFlagName = "rollup.config" - NetworkFlagName = "network" - CanyonOverrideFlagName = "override.canyon" - DeltaOverrideFlagName = "override.delta" + RollupConfigFlagName = "rollup.config" + NetworkFlagName = "network" + CanyonOverrideFlagName = "override.canyon" + DeltaOverrideFlagName = "override.delta" + EcotoneOverrideFlagName = "override.ecotone" ) -func CLIFlags(envPrefix string) []cli.Flag { +func CLIFlags(envPrefix string, category string) []cli.Flag { return []cli.Flag{ &cli.Uint64Flag{ - Name: CanyonOverrideFlagName, - Usage: "Manually specify the Canyon fork timestamp, overriding the bundled setting", - EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_CANYON"), - Hidden: false, + Name: CanyonOverrideFlagName, + Usage: "Manually specify the Canyon fork timestamp, overriding the bundled setting", + EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_CANYON"), + Hidden: false, + Category: category, }, &cli.Uint64Flag{ - Name: DeltaOverrideFlagName, - Usage: "Manually specify the Delta fork timestamp, overriding the bundled setting", - EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_DELTA"), - Hidden: false, + Name: DeltaOverrideFlagName, + Usage: "Manually specify the Delta fork timestamp, overriding the bundled setting", + EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_DELTA"), + Hidden: false, + Category: category, }, - CLINetworkFlag(envPrefix), - CLIRollupConfigFlag(envPrefix), + &cli.Uint64Flag{ + Name: EcotoneOverrideFlagName, + Usage: "Manually specify the Ecotone fork timestamp, overriding the bundled setting", + EnvVars: opservice.PrefixEnvVar(envPrefix, "OVERRIDE_ECOTONE"), + Hidden: false, + Category: category, + }, + CLINetworkFlag(envPrefix, category), + CLIRollupConfigFlag(envPrefix, category), } } -func CLINetworkFlag(envPrefix string) cli.Flag { +func CLINetworkFlag(envPrefix string, category string) cli.Flag { return &cli.StringFlag{ - Name: NetworkFlagName, - Usage: fmt.Sprintf("Predefined network selection. Available networks: %s", strings.Join(chaincfg.AvailableNetworks(), ", ")), - EnvVars: opservice.PrefixEnvVar(envPrefix, "NETWORK"), + Name: NetworkFlagName, + Usage: fmt.Sprintf("Predefined network selection. Available networks: %s", strings.Join(chaincfg.AvailableNetworks(), ", ")), + EnvVars: opservice.PrefixEnvVar(envPrefix, "NETWORK"), + Category: category, } } -func CLIRollupConfigFlag(envPrefix string) cli.Flag { +func CLIRollupConfigFlag(envPrefix string, category string) cli.Flag { return &cli.StringFlag{ - Name: RollupConfigFlagName, - Usage: "Rollup chain parameters", - EnvVars: opservice.PrefixEnvVar(envPrefix, "ROLLUP_CONFIG"), + Name: RollupConfigFlagName, + Usage: "Rollup chain parameters", + EnvVars: opservice.PrefixEnvVar(envPrefix, "ROLLUP_CONFIG"), + Category: category, } } diff --git a/cannon/cmd/json.go b/op-service/jsonutil/json.go similarity index 85% rename from cannon/cmd/json.go rename to op-service/jsonutil/json.go index 615bacedc860..a7918d6d4a62 100644 --- a/cannon/cmd/json.go +++ b/op-service/jsonutil/json.go @@ -1,4 +1,4 @@ -package cmd +package jsonutil import ( "encoding/json" @@ -10,7 +10,7 @@ import ( "github.com/ethereum-optimism/optimism/op-service/ioutil" ) -func loadJSON[X any](inputPath string) (*X, error) { +func LoadJSON[X any](inputPath string) (*X, error) { if inputPath == "" { return nil, errors.New("no path specified") } @@ -27,14 +27,14 @@ func loadJSON[X any](inputPath string) (*X, error) { return &state, nil } -func writeJSON[X any](outputPath string, value X) error { +func WriteJSON[X any](outputPath string, value X, perm os.FileMode) error { if outputPath == "" { return nil } var out io.Writer finish := func() error { return nil } if outputPath != "-" { - f, err := ioutil.NewAtomicWriterCompressed(outputPath, 0755) + f, err := ioutil.NewAtomicWriterCompressed(outputPath, perm) if err != nil { return fmt.Errorf("failed to open output file: %w", err) } @@ -48,6 +48,7 @@ func writeJSON[X any](outputPath string, value X) error { out = os.Stdout } enc := json.NewEncoder(out) + enc.SetIndent("", " ") if err := enc.Encode(value); err != nil { return fmt.Errorf("failed to encode to JSON: %w", err) } diff --git a/cannon/cmd/json_test.go b/op-service/jsonutil/json_test.go similarity index 86% rename from cannon/cmd/json_test.go rename to op-service/jsonutil/json_test.go index 63d4636b7d9a..16eb91992f87 100644 --- a/cannon/cmd/json_test.go +++ b/op-service/jsonutil/json_test.go @@ -1,4 +1,4 @@ -package cmd +package jsonutil import ( "encoding/json" @@ -13,7 +13,7 @@ func TestRoundTripJSON(t *testing.T) { dir := t.TempDir() file := filepath.Join(dir, "test.json") data := &jsonTestData{A: "yay", B: 3} - err := writeJSON(file, data) + err := WriteJSON(file, data, 0o755) require.NoError(t, err) // Confirm the file is uncompressed @@ -23,7 +23,7 @@ func TestRoundTripJSON(t *testing.T) { require.NoError(t, err) var result *jsonTestData - result, err = loadJSON[jsonTestData](file) + result, err = LoadJSON[jsonTestData](file) require.NoError(t, err) require.EqualValues(t, data, result) } @@ -32,7 +32,7 @@ func TestRoundTripJSONWithGzip(t *testing.T) { dir := t.TempDir() file := filepath.Join(dir, "test.json.gz") data := &jsonTestData{A: "yay", B: 3} - err := writeJSON(file, data) + err := WriteJSON(file, data, 0o755) require.NoError(t, err) // Confirm the file isn't raw JSON @@ -42,7 +42,7 @@ func TestRoundTripJSONWithGzip(t *testing.T) { require.Error(t, err, "should not be able to decode without decompressing") var result *jsonTestData - result, err = loadJSON[jsonTestData](file) + result, err = LoadJSON[jsonTestData](file) require.NoError(t, err) require.EqualValues(t, data, result) } diff --git a/op-service/jsonutil/write.go b/op-service/jsonutil/write.go deleted file mode 100644 index 8b0a295f9713..000000000000 --- a/op-service/jsonutil/write.go +++ /dev/null @@ -1,18 +0,0 @@ -package jsonutil - -import ( - "encoding/json" - "os" -) - -func WriteJSON(outfile string, input interface{}) error { - f, err := os.OpenFile(outfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o666) - if err != nil { - return err - } - defer f.Close() - - enc := json.NewEncoder(f) - enc.SetIndent("", " ") - return enc.Encode(input) -} diff --git a/op-service/log/cli.go b/op-service/log/cli.go index 983f7228dbfc..966f7ad7d8c7 100644 --- a/op-service/log/cli.go +++ b/op-service/log/cli.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/urfave/cli/v2" + "golang.org/x/exp/slog" "golang.org/x/term" "github.com/ethereum/go-ethereum/log" @@ -21,95 +22,127 @@ const ( ColorFlagName = "log.color" ) -// CLIFlags creates flag definitions for the logging utils. +func CLIFlags(envPrefix string) []cli.Flag { + return CLIFlagsWithCategory(envPrefix, "") +} + +// CLIFlagsWithCategory creates flag definitions for the logging utils. // Warning: flags are not safe to reuse due to an upstream urfave default-value mutation bug in GenericFlag. // Use cliapp.ProtectFlags(flags) to create a copy before passing it into an App if the app runs more than once. -func CLIFlags(envPrefix string) []cli.Flag { +func CLIFlagsWithCategory(envPrefix string, category string) []cli.Flag { return []cli.Flag{ &cli.GenericFlag{ - Name: LevelFlagName, - Usage: "The lowest log level that will be output", - Value: NewLvlFlagValue(log.LvlInfo), - EnvVars: opservice.PrefixEnvVar(envPrefix, "LOG_LEVEL"), + Name: LevelFlagName, + Usage: "The lowest log level that will be output", + Value: NewLevelFlagValue(log.LevelInfo), + EnvVars: opservice.PrefixEnvVar(envPrefix, "LOG_LEVEL"), + Category: category, }, &cli.GenericFlag{ - Name: FormatFlagName, - Usage: "Format the log output. Supported formats: 'text', 'terminal', 'logfmt', 'json', 'json-pretty',", - Value: NewFormatFlagValue(FormatText), - EnvVars: opservice.PrefixEnvVar(envPrefix, "LOG_FORMAT"), + Name: FormatFlagName, + Usage: "Format the log output. Supported formats: 'text', 'terminal', 'logfmt', 'json', 'json-pretty',", + Value: NewFormatFlagValue(FormatText), + EnvVars: opservice.PrefixEnvVar(envPrefix, "LOG_FORMAT"), + Category: category, }, &cli.BoolFlag{ - Name: ColorFlagName, - Usage: "Color the log output if in terminal mode", - EnvVars: opservice.PrefixEnvVar(envPrefix, "LOG_COLOR"), + Name: ColorFlagName, + Usage: "Color the log output if in terminal mode", + EnvVars: opservice.PrefixEnvVar(envPrefix, "LOG_COLOR"), + Category: category, }, } } -// LvlFlagValue is a value type for cli.GenericFlag to parse and validate log-level values. +// LevelFlagValue is a value type for cli.GenericFlag to parse and validate log-level values. // Log level: trace, debug, info, warn, error, crit. Capitals are accepted too. -type LvlFlagValue log.Lvl +type LevelFlagValue slog.Level -func NewLvlFlagValue(lvl log.Lvl) *LvlFlagValue { - return (*LvlFlagValue)(&lvl) +func NewLevelFlagValue(lvl slog.Level) *LevelFlagValue { + return (*LevelFlagValue)(&lvl) } -func (fv *LvlFlagValue) Set(value string) error { +func (fv *LevelFlagValue) Set(value string) error { value = strings.ToLower(value) // ignore case - lvl, err := log.LvlFromString(value) + lvl, err := LevelFromString(value) if err != nil { return err } - *fv = LvlFlagValue(lvl) + *fv = LevelFlagValue(lvl) return nil } -func (fv LvlFlagValue) String() string { - return log.Lvl(fv).String() +func (fv LevelFlagValue) String() string { + return slog.Level(fv).String() } -func (fv LvlFlagValue) LogLvl() log.Lvl { - return log.Lvl(fv) +func (fv LevelFlagValue) Level() slog.Level { + return slog.Level(fv).Level() } -func (fv *LvlFlagValue) Clone() any { +func (fv *LevelFlagValue) Clone() any { cpy := *fv return &cpy } -var _ cliapp.CloneableGeneric = (*LvlFlagValue)(nil) +// LevelFromString returns the appropriate Level from a string name. +// Useful for parsing command line args and configuration files. +// It also converts strings to lowercase. +// If the string is unknown, LevelDebug is returned as a default, together with +// a non-nil error. +func LevelFromString(lvlString string) (slog.Level, error) { + lvlString = strings.ToLower(lvlString) // ignore case + switch lvlString { + case "trace", "trce": + return log.LevelTrace, nil + case "debug", "dbug": + return log.LevelDebug, nil + case "info": + return log.LevelInfo, nil + case "warn": + return log.LevelWarn, nil + case "error", "eror": + return log.LevelError, nil + case "crit": + return log.LevelCrit, nil + default: + return log.LevelDebug, fmt.Errorf("unknown level: %v", lvlString) + } +} + +var _ cliapp.CloneableGeneric = (*LevelFlagValue)(nil) // FormatType defines a type of log format. -// Supported formats: 'text', 'terminal', 'logfmt', 'json', 'json-pretty' +// Supported formats: 'text', 'terminal', 'logfmt', 'json' type FormatType string const ( - FormatText FormatType = "text" - FormatTerminal FormatType = "terminal" - FormatLogFmt FormatType = "logfmt" - FormatJSON FormatType = "json" - FormatJSONPretty FormatType = "json-pretty" + FormatText FormatType = "text" + FormatTerminal FormatType = "terminal" + FormatLogFmt FormatType = "logfmt" + FormatJSON FormatType = "json" ) -// Formatter turns a format type and color into a structured Format object -func (ft FormatType) Formatter(color bool) log.Format { +// FormatHandler returns the correct slog handler factory for the provided format. +func FormatHandler(ft FormatType, color bool) func(io.Writer) slog.Handler { + termColorHandler := func(w io.Writer) slog.Handler { + return log.NewTerminalHandler(w, color) + } switch ft { case FormatJSON: - return log.JSONFormat() - case FormatJSONPretty: - return log.JSONFormatEx(true, true) + return log.JSONHandler case FormatText: if term.IsTerminal(int(os.Stdout.Fd())) { - return log.TerminalFormat(color) + return termColorHandler } else { - return log.LogfmtFormat() + return log.LogfmtHandler } case FormatTerminal: - return log.TerminalFormat(color) + return termColorHandler case FormatLogFmt: - return log.LogfmtFormat() + return log.LogfmtHandler default: - panic(fmt.Errorf("failed to create `log.Format` for format-type=%q and color=%v", ft, color)) + panic(fmt.Errorf("failed to create slog.Handler factory for format-type=%q and color=%v", ft, color)) } } @@ -126,7 +159,7 @@ func NewFormatFlagValue(fmtType FormatType) *FormatFlagValue { func (fv *FormatFlagValue) Set(value string) error { switch FormatType(value) { - case FormatText, FormatTerminal, FormatLogFmt, FormatJSON, FormatJSONPretty: + case FormatText, FormatTerminal, FormatLogFmt, FormatJSON: *fv = FormatFlagValue(value) return nil default: @@ -150,7 +183,7 @@ func (fv *FormatFlagValue) Clone() any { var _ cliapp.CloneableGeneric = (*FormatFlagValue)(nil) type CLIConfig struct { - Level log.Lvl + Level slog.Level Color bool Format FormatType } @@ -165,20 +198,16 @@ func AppOut(ctx *cli.Context) io.Writer { } // NewLogHandler creates a new configured handler, compatible as LvlSetter for log-level changes during runtime. -func NewLogHandler(wr io.Writer, cfg CLIConfig) log.Handler { - handler := log.StreamHandler(wr, cfg.Format.Formatter(cfg.Color)) - handler = log.SyncHandler(handler) - handler = NewDynamicLogHandler(cfg.Level, handler) - return handler +func NewLogHandler(wr io.Writer, cfg CLIConfig) slog.Handler { + handler := FormatHandler(cfg.Format, cfg.Color)(wr) + return NewDynamicLogHandler(cfg.Level, handler) } // NewLogger creates a new configured logger. // The log handler of the logger is a LvlSetter, i.e. the log level can be changed as needed. func NewLogger(wr io.Writer, cfg CLIConfig) log.Logger { - handler := NewLogHandler(wr, cfg) - logger := log.New() - logger.SetHandler(handler) - return logger + h := NewLogHandler(wr, cfg) + return log.NewLogger(h) } // SetGlobalLogHandler sets the log handles as the handler of the global default logger. @@ -186,15 +215,15 @@ func NewLogger(wr io.Writer, cfg CLIConfig) log.Logger { // as it does makes it difficult to distinguish different services in the same process, e.g. during tests. // Geth and other components may use the global logger however, // and it is thus recommended to set the global log handler to catch these logs. -func SetGlobalLogHandler(h log.Handler) { - log.Root().SetHandler(h) +func SetGlobalLogHandler(h slog.Handler) { + log.SetDefault(log.NewLogger(h)) } // DefaultCLIConfig creates a default log configuration. // Color defaults to true if terminal is detected. func DefaultCLIConfig() CLIConfig { return CLIConfig{ - Level: log.LvlInfo, + Level: log.LevelInfo, Format: FormatText, Color: term.IsTerminal(int(os.Stdout.Fd())), } @@ -202,7 +231,7 @@ func DefaultCLIConfig() CLIConfig { func ReadCLIConfig(ctx *cli.Context) CLIConfig { cfg := DefaultCLIConfig() - cfg.Level = ctx.Generic(LevelFlagName).(*LvlFlagValue).LogLvl() + cfg.Level = ctx.Generic(LevelFlagName).(*LevelFlagValue).Level() cfg.Format = ctx.Generic(FormatFlagName).(*FormatFlagValue).FormatType() if ctx.IsSet(ColorFlagName) { cfg.Color = ctx.Bool(ColorFlagName) diff --git a/op-service/log/defaults.go b/op-service/log/defaults.go index a57408be81db..d7997e8040a3 100644 --- a/op-service/log/defaults.go +++ b/op-service/log/defaults.go @@ -7,10 +7,5 @@ import ( ) func SetupDefaults() { - log.Root().SetHandler( - log.LvlFilterHandler( - log.LvlInfo, - log.StreamHandler(os.Stdout, log.LogfmtFormat()), - ), - ) + SetGlobalLogHandler(log.LogfmtHandlerWithLevel(os.Stdout, log.LevelInfo)) } diff --git a/op-service/log/dynamic.go b/op-service/log/dynamic.go index 901279aba094..72f23f505bbc 100644 --- a/op-service/log/dynamic.go +++ b/op-service/log/dynamic.go @@ -1,31 +1,53 @@ package log -import "github.com/ethereum/go-ethereum/log" +import ( + "context" + + "golang.org/x/exp/slog" +) type LvlSetter interface { - SetLogLevel(lvl log.Lvl) + SetLogLevel(lvl slog.Level) } // DynamicLogHandler allow runtime-configuration of the log handler. type DynamicLogHandler struct { - log.Handler // embedded, to expose any extra methods the underlying handler might provide - maxLvl log.Lvl + h slog.Handler + minLvl *slog.Level // shared with derived dynamic handlers } -func NewDynamicLogHandler(lvl log.Lvl, h log.Handler) *DynamicLogHandler { +func NewDynamicLogHandler(lvl slog.Level, h slog.Handler) *DynamicLogHandler { return &DynamicLogHandler{ - Handler: h, - maxLvl: lvl, + h: h, + minLvl: &lvl, } } -func (d *DynamicLogHandler) SetLogLevel(lvl log.Lvl) { - d.maxLvl = lvl +func (d *DynamicLogHandler) SetLogLevel(lvl slog.Level) { + *d.minLvl = lvl } -func (d *DynamicLogHandler) Log(r *log.Record) error { - if r.Lvl > d.maxLvl { // lower log level values are more critical +func (d *DynamicLogHandler) Handle(ctx context.Context, r slog.Record) error { + if r.Level < *d.minLvl { // higher log level values are more critical return nil } - return d.Handler.Log(r) // process the log + return d.h.Handle(ctx, r) // process the log +} + +func (d *DynamicLogHandler) Enabled(ctx context.Context, lvl slog.Level) bool { + return (lvl >= *d.minLvl) && d.h.Enabled(ctx, lvl) +} + +func (d *DynamicLogHandler) WithAttrs(attrs []slog.Attr) slog.Handler { + return &DynamicLogHandler{ + h: d.h.WithAttrs(attrs), + minLvl: d.minLvl, + } +} + +func (d *DynamicLogHandler) WithGroup(name string) slog.Handler { + return &DynamicLogHandler{ + h: d.h.WithGroup(name), + minLvl: d.minLvl, + } } diff --git a/op-service/log/dynamic_test.go b/op-service/log/dynamic_test.go index 45fd3def95df..3a992710b4d8 100644 --- a/op-service/log/dynamic_test.go +++ b/op-service/log/dynamic_test.go @@ -1,44 +1,84 @@ package log import ( + "context" "testing" "github.com/stretchr/testify/require" + "golang.org/x/exp/slog" "github.com/ethereum/go-ethereum/log" ) func TestDynamicLogHandler_SetLogLevel(t *testing.T) { - var records []*log.Record - h := log.FuncHandler(func(r *log.Record) error { - records = append(records, r) - return nil - }) - d := NewDynamicLogHandler(log.LvlInfo, h) - logger := log.New() - logger.SetHandler(d) + h := new(testRecorder) + d := NewDynamicLogHandler(log.LevelInfo, h) + logger := log.NewLogger(d) logger.Info("hello world") // y logger.Error("error!") // y logger.Debug("debugging") // n // increase log level - logger.GetHandler().(LvlSetter).SetLogLevel(log.LvlDebug) + d.SetLogLevel(log.LevelDebug) logger.Info("hello again") // y logger.Debug("can see debug now") // y logger.Trace("but no trace") // n // and decrease log level - logger.GetHandler().(LvlSetter).SetLogLevel(log.LvlWarn) + d.SetLogLevel(log.LevelWarn) logger.Warn("visible warning") // y logger.Info("info should be hidden now") // n logger.Error("another error") // y - require.Len(t, records, 2+2+2) - require.Equal(t, records[0].Msg, "hello world") - require.Equal(t, records[1].Msg, "error!") - require.Equal(t, records[2].Msg, "hello again") - require.Equal(t, records[3].Msg, "can see debug now") - require.Equal(t, records[4].Msg, "visible warning") - require.Equal(t, records[5].Msg, "another error") + require.Len(t, h.records, 2+2+2) + require.Equal(t, h.records[0].Message, "hello world") + require.Equal(t, h.records[1].Message, "error!") + require.Equal(t, h.records[2].Message, "hello again") + require.Equal(t, h.records[3].Message, "can see debug now") + require.Equal(t, h.records[4].Message, "visible warning") + require.Equal(t, h.records[5].Message, "another error") } + +func TestDynamicLogHandler_WithAttrs(t *testing.T) { + h := new(testRecorder) + d := NewDynamicLogHandler(log.LevelInfo, h) + logger := log.NewLogger(d) + logwith := logger.With("a", 1) // derived logger + + // increase log level + d.SetLogLevel(log.LevelDebug) + + logwith.Info("info0") // y + logwith.Debug("debug0") // y + logwith.Trace("trace0") // n + + // and decrease log level + d.SetLogLevel(log.LevelWarn) + + logwith.Info("info1") // n + logwith.Warn("warn1") // y + logwith.Error("error1") // y + + require.Len(t, h.records, 2+2) + require.Equal(t, h.records[0].Message, "info0") + require.Equal(t, h.records[1].Message, "debug0") + require.Equal(t, h.records[2].Message, "warn1") + require.Equal(t, h.records[3].Message, "error1") +} + +type testRecorder struct { + records []slog.Record +} + +func (r testRecorder) Enabled(context.Context, slog.Level) bool { + return true +} + +func (r *testRecorder) Handle(_ context.Context, rec slog.Record) error { + r.records = append(r.records, rec) + return nil +} + +func (r *testRecorder) WithAttrs([]slog.Attr) slog.Handler { return r } +func (r *testRecorder) WithGroup(string) slog.Handler { return r } diff --git a/op-service/log/writer.go b/op-service/log/writer.go index 77c787249142..0a1731383068 100644 --- a/op-service/log/writer.go +++ b/op-service/log/writer.go @@ -3,29 +3,31 @@ package log import ( "sync" + "golang.org/x/exp/slog" + "github.com/ethereum/go-ethereum/log" ) type Writer struct { - log func(str string, ctx ...interface{}) + log func(str string, ctx ...any) lock sync.Mutex pending []byte } -func NewWriter(l log.Logger, lvl log.Lvl) *Writer { - var logMethod func(str string, ctx ...interface{}) +func NewWriter(l log.Logger, lvl slog.Level) *Writer { + var logMethod func(str string, ctx ...any) switch lvl { - case log.LvlTrace: + case log.LevelTrace: logMethod = l.Trace - case log.LvlDebug: + case log.LevelDebug: logMethod = l.Debug - case log.LvlInfo: + case log.LevelInfo: logMethod = l.Info - case log.LvlWarn: + case log.LevelWarn: logMethod = l.Warn - case log.LvlError: + case log.LevelError: logMethod = l.Error - case log.LvlCrit: + case log.LevelCrit: logMethod = l.Crit default: // Cast lvl to int to avoid trying to convert it to a string which will fail for unknown types diff --git a/op-service/log/writer_test.go b/op-service/log/writer_test.go index 4a4c000bd5b3..2e9cf14b3a75 100644 --- a/op-service/log/writer_test.go +++ b/op-service/log/writer_test.go @@ -1,81 +1,98 @@ -package log +package log_test import ( "io" "testing" - "github.com/ethereum-optimism/optimism/op-service/testlog" - "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" + "golang.org/x/exp/slog" + + "github.com/ethereum/go-ethereum/log" + + . "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/optimism/op-service/testlog" ) var _ io.Writer = (*Writer)(nil) func TestLogWriter(t *testing.T) { - setup := func(t *testing.T, lvl log.Lvl) (*Writer, *testlog.CapturingHandler) { - logger := testlog.Logger(t, lvl) - logs := testlog.Capture(logger) + setup := func(t *testing.T, lvl slog.Level) (*Writer, *testlog.CapturingHandler) { + logger, logs := testlog.CaptureLogger(t, lvl) writer := NewWriter(logger, lvl) return writer, logs } t.Run("LogSingleLine", func(t *testing.T) { - writer, logs := setup(t, log.LvlInfo) + writer, logs := setup(t, log.LevelInfo) line := []byte("Test line\n") count, err := writer.Write(line) require.NoError(t, err) require.Equal(t, len(line), count) - require.NotNil(t, logs.FindLog(log.LvlInfo, "Test line")) + levelFilter := testlog.NewLevelFilter(log.LevelInfo) + msgFilter := testlog.NewMessageFilter("Test line") + require.NotNil(t, logs.FindLog(levelFilter, msgFilter)) }) t.Run("LogMultipleLines", func(t *testing.T) { - writer, logs := setup(t, log.LvlInfo) + writer, logs := setup(t, log.LevelInfo) line := []byte("Line 1\nLine 2\n") count, err := writer.Write(line) require.NoError(t, err) require.Equal(t, len(line), count) - require.NotNil(t, logs.FindLog(log.LvlInfo, "Line 1")) - require.NotNil(t, logs.FindLog(log.LvlInfo, "Line 2")) + levelFilter := testlog.NewLevelFilter(log.LevelInfo) + lineOneFilter := testlog.NewMessageFilter("Line 1") + lineTwoFilter := testlog.NewMessageFilter("Line 2") + require.NotNil(t, logs.FindLog(levelFilter, lineOneFilter)) + require.NotNil(t, logs.FindLog(levelFilter, lineTwoFilter)) }) t.Run("LogLineAcrossMultipleCalls", func(t *testing.T) { - writer, logs := setup(t, log.LvlInfo) + writer, logs := setup(t, log.LevelInfo) line := []byte("First line\nSplit ") count, err := writer.Write(line) require.NoError(t, err) require.Equal(t, len(line), count) - require.NotNil(t, logs.FindLog(log.LvlInfo, "First line")) + levelFilter := testlog.NewLevelFilter(log.LevelInfo) + msgFilter := testlog.NewMessageFilter("First line") + require.NotNil(t, logs.FindLog(levelFilter, msgFilter)) line = []byte("Line\nLast Line\n") count, err = writer.Write(line) require.NoError(t, err) require.Equal(t, len(line), count) - require.NotNil(t, logs.FindLog(log.LvlInfo, "Split Line")) - require.NotNil(t, logs.FindLog(log.LvlInfo, "Last Line")) + levelFilter = testlog.NewLevelFilter(log.LevelInfo) + splitLineFilter := testlog.NewMessageFilter("Split Line") + lastLineFilter := testlog.NewMessageFilter("Last Line") + require.NotNil(t, logs.FindLog(levelFilter, splitLineFilter)) + require.NotNil(t, logs.FindLog(levelFilter, lastLineFilter)) }) - // Can't test LvlCrit or it will call os.Exit - for _, lvl := range []log.Lvl{log.LvlTrace, log.LvlDebug, log.LvlInfo, log.LvlWarn, log.LvlError} { + // Can't test LevelCrit or it will call os.Exit + for _, lvl := range []slog.Level{log.LevelTrace, log.LevelDebug, log.LevelInfo, log.LevelWarn, log.LevelError} { lvl := lvl - t.Run("LogLvl_"+lvl.String(), func(t *testing.T) { + t.Run("LogLevel_"+lvl.String(), func(t *testing.T) { writer, logs := setup(t, lvl) line := []byte("Log line\n") count, err := writer.Write(line) require.NoError(t, err) require.Equal(t, len(line), count) - require.NotNil(t, logs.FindLog(lvl, "Log line")) + levelFilter := testlog.NewLevelFilter(lvl) + msgFilter := testlog.NewMessageFilter("Log line") + require.NotNil(t, logs.FindLog(levelFilter, msgFilter)) }) } t.Run("UseErrorForUnknownLevels", func(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) - logs := testlog.Capture(logger) + logger, logs := testlog.CaptureLogger(t, log.LevelInfo) writer := NewWriter(logger, 60027) line := []byte("Log line\n") count, err := writer.Write(line) require.NoError(t, err) require.Equal(t, len(line), count) - require.NotNil(t, logs.FindLog(log.LvlError, "Unknown log level. Using Error")) - require.NotNil(t, logs.FindLog(log.LvlError, "Log line")) + levelFilter := testlog.NewLevelFilter(log.LevelError) + unknownFilter := testlog.NewMessageFilter("Unknown log level. Using Error") + logLineFilter := testlog.NewMessageFilter("Log line") + require.NotNil(t, logs.FindLog(levelFilter, unknownFilter)) + require.NotNil(t, logs.FindLog(levelFilter, logLineFilter)) }) } diff --git a/op-service/oppprof/cli.go b/op-service/oppprof/cli.go index 6613be19c68a..710cbeaaf764 100644 --- a/op-service/oppprof/cli.go +++ b/op-service/oppprof/cli.go @@ -61,29 +61,37 @@ func DefaultCLIConfig() CLIConfig { } func CLIFlags(envPrefix string) []cli.Flag { + return CLIFlagsWithCategory(envPrefix, "") +} + +func CLIFlagsWithCategory(envPrefix string, category string) []cli.Flag { return []cli.Flag{ &cli.BoolFlag{ - Name: EnabledFlagName, - Usage: "Enable the pprof server", - EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_ENABLED"), + Name: EnabledFlagName, + Usage: "Enable the pprof server", + EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_ENABLED"), + Category: category, }, &cli.StringFlag{ - Name: ListenAddrFlagName, - Usage: "pprof listening address", - Value: defaultListenAddr, // TODO(CLI-4159): Switch to 127.0.0.1 - EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_ADDR"), + Name: ListenAddrFlagName, + Usage: "pprof listening address", + Value: defaultListenAddr, // TODO(CLI-4159): Switch to 127.0.0.1 + EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_ADDR"), + Category: category, }, &cli.IntFlag{ - Name: PortFlagName, - Usage: "pprof listening port", - Value: defaultListenPort, - EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_PORT"), + Name: PortFlagName, + Usage: "pprof listening port", + Value: defaultListenPort, + EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_PORT"), + Category: category, }, &cli.GenericFlag{ - Name: ProfilePathFlagName, - Usage: "pprof file path. If it is a directory, the path is {dir}/{profileType}.prof", - Value: new(flags.PathFlag), - EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_PATH"), + Name: ProfilePathFlagName, + Usage: "pprof file path. If it is a directory, the path is {dir}/{profileType}.prof", + Value: new(flags.PathFlag), + EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_PATH"), + Category: category, }, &cli.GenericFlag{ Name: ProfileTypeFlagName, @@ -92,7 +100,8 @@ func CLIFlags(envPrefix string) []cli.Flag { defaultProfType := profileType("") return &defaultProfType }(), - EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_TYPE"), + EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_TYPE"), + Category: category, }, } } diff --git a/op-service/proto/gen/op_service/v1/calldata.pb.go b/op-service/proto/gen/op_service/v1/calldata.pb.go new file mode 100644 index 000000000000..ca3044cef1da --- /dev/null +++ b/op-service/proto/gen/op_service/v1/calldata.pb.go @@ -0,0 +1,296 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v4.24.3 +// source: op_service/v1/calldata.proto + +package op_service + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// CalldataFrame wraps the frame data or the eigenda blob reference to the frame data +type CalldataFrame struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Value: + // + // *CalldataFrame_Frame + // *CalldataFrame_FrameRef + Value isCalldataFrame_Value `protobuf_oneof:"value"` +} + +func (x *CalldataFrame) Reset() { + *x = CalldataFrame{} + if protoimpl.UnsafeEnabled { + mi := &file_op_service_v1_calldata_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CalldataFrame) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CalldataFrame) ProtoMessage() {} + +func (x *CalldataFrame) ProtoReflect() protoreflect.Message { + mi := &file_op_service_v1_calldata_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CalldataFrame.ProtoReflect.Descriptor instead. +func (*CalldataFrame) Descriptor() ([]byte, []int) { + return file_op_service_v1_calldata_proto_rawDescGZIP(), []int{0} +} + +func (m *CalldataFrame) GetValue() isCalldataFrame_Value { + if m != nil { + return m.Value + } + return nil +} + +func (x *CalldataFrame) GetFrame() []byte { + if x, ok := x.GetValue().(*CalldataFrame_Frame); ok { + return x.Frame + } + return nil +} + +func (x *CalldataFrame) GetFrameRef() *FrameRef { + if x, ok := x.GetValue().(*CalldataFrame_FrameRef); ok { + return x.FrameRef + } + return nil +} + +type isCalldataFrame_Value interface { + isCalldataFrame_Value() +} + +type CalldataFrame_Frame struct { + Frame []byte `protobuf:"bytes,1,opt,name=frame,proto3,oneof"` +} + +type CalldataFrame_FrameRef struct { + FrameRef *FrameRef `protobuf:"bytes,2,opt,name=frame_ref,json=frameRef,proto3,oneof"` +} + +func (*CalldataFrame_Frame) isCalldataFrame_Value() {} + +func (*CalldataFrame_FrameRef) isCalldataFrame_Value() {} + +// This is a copy of BlobRequest here: https://github.com/Layr-Labs/eigenda/blob/main/api/proto/retriever/retriever.proto#L10 +type FrameRef struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BatchHeaderHash []byte `protobuf:"bytes,1,opt,name=batch_header_hash,json=batchHeaderHash,proto3" json:"batch_header_hash,omitempty"` + BlobIndex uint32 `protobuf:"varint,2,opt,name=blob_index,json=blobIndex,proto3" json:"blob_index,omitempty"` + ReferenceBlockNumber uint32 `protobuf:"varint,3,opt,name=reference_block_number,json=referenceBlockNumber,proto3" json:"reference_block_number,omitempty"` + QuorumIds []uint32 `protobuf:"varint,4,rep,packed,name=quorum_ids,json=quorumIds,proto3" json:"quorum_ids,omitempty"` + BlobLength uint32 `protobuf:"varint,5,opt,name=blob_length,json=blobLength,proto3" json:"blob_length,omitempty"` +} + +func (x *FrameRef) Reset() { + *x = FrameRef{} + if protoimpl.UnsafeEnabled { + mi := &file_op_service_v1_calldata_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FrameRef) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FrameRef) ProtoMessage() {} + +func (x *FrameRef) ProtoReflect() protoreflect.Message { + mi := &file_op_service_v1_calldata_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FrameRef.ProtoReflect.Descriptor instead. +func (*FrameRef) Descriptor() ([]byte, []int) { + return file_op_service_v1_calldata_proto_rawDescGZIP(), []int{1} +} + +func (x *FrameRef) GetBatchHeaderHash() []byte { + if x != nil { + return x.BatchHeaderHash + } + return nil +} + +func (x *FrameRef) GetBlobIndex() uint32 { + if x != nil { + return x.BlobIndex + } + return 0 +} + +func (x *FrameRef) GetReferenceBlockNumber() uint32 { + if x != nil { + return x.ReferenceBlockNumber + } + return 0 +} + +func (x *FrameRef) GetQuorumIds() []uint32 { + if x != nil { + return x.QuorumIds + } + return nil +} + +func (x *FrameRef) GetBlobLength() uint32 { + if x != nil { + return x.BlobLength + } + return 0 +} + +var File_op_service_v1_calldata_proto protoreflect.FileDescriptor + +var file_op_service_v1_calldata_proto_rawDesc = []byte{ + 0x0a, 0x1c, 0x6f, 0x70, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x76, 0x31, 0x2f, + 0x63, 0x61, 0x6c, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, + 0x6f, 0x70, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x22, 0x68, 0x0a, + 0x0d, 0x43, 0x61, 0x6c, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x16, + 0x0a, 0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, + 0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, + 0x72, 0x65, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6f, 0x70, 0x5f, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, + 0x65, 0x66, 0x48, 0x00, 0x52, 0x08, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x66, 0x42, 0x07, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xcb, 0x01, 0x0a, 0x08, 0x46, 0x72, 0x61, 0x6d, + 0x65, 0x52, 0x65, 0x66, 0x12, 0x2a, 0x0a, 0x11, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x68, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x61, 0x73, 0x68, + 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x62, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, + 0x34, 0x0a, 0x16, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x14, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x71, 0x75, 0x6f, 0x72, 0x75, 0x6d, 0x5f, + 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x09, 0x71, 0x75, 0x6f, 0x72, 0x75, + 0x6d, 0x49, 0x64, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x6c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x62, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2d, 0x6f, 0x70, 0x74, + 0x69, 0x6d, 0x69, 0x73, 0x6d, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x73, 0x6d, 0x2f, 0x6f, + 0x70, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_op_service_v1_calldata_proto_rawDescOnce sync.Once + file_op_service_v1_calldata_proto_rawDescData = file_op_service_v1_calldata_proto_rawDesc +) + +func file_op_service_v1_calldata_proto_rawDescGZIP() []byte { + file_op_service_v1_calldata_proto_rawDescOnce.Do(func() { + file_op_service_v1_calldata_proto_rawDescData = protoimpl.X.CompressGZIP(file_op_service_v1_calldata_proto_rawDescData) + }) + return file_op_service_v1_calldata_proto_rawDescData +} + +var file_op_service_v1_calldata_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_op_service_v1_calldata_proto_goTypes = []interface{}{ + (*CalldataFrame)(nil), // 0: op_service.v1.CalldataFrame + (*FrameRef)(nil), // 1: op_service.v1.FrameRef +} +var file_op_service_v1_calldata_proto_depIdxs = []int32{ + 1, // 0: op_service.v1.CalldataFrame.frame_ref:type_name -> op_service.v1.FrameRef + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_op_service_v1_calldata_proto_init() } +func file_op_service_v1_calldata_proto_init() { + if File_op_service_v1_calldata_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_op_service_v1_calldata_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CalldataFrame); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_op_service_v1_calldata_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FrameRef); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_op_service_v1_calldata_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*CalldataFrame_Frame)(nil), + (*CalldataFrame_FrameRef)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_op_service_v1_calldata_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_op_service_v1_calldata_proto_goTypes, + DependencyIndexes: file_op_service_v1_calldata_proto_depIdxs, + MessageInfos: file_op_service_v1_calldata_proto_msgTypes, + }.Build() + File_op_service_v1_calldata_proto = out.File + file_op_service_v1_calldata_proto_rawDesc = nil + file_op_service_v1_calldata_proto_goTypes = nil + file_op_service_v1_calldata_proto_depIdxs = nil +} diff --git a/op-service/proto/src/op_service/v1/calldata.proto b/op-service/proto/src/op_service/v1/calldata.proto new file mode 100644 index 000000000000..d092c0fec929 --- /dev/null +++ b/op-service/proto/src/op_service/v1/calldata.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +option go_package = "github.com/ethereum-optimism/optimism/op_service"; + +package op_service.v1; + +// CalldataFrame wraps the frame data or the eigenda blob reference to the frame data +message CalldataFrame { + oneof value { + bytes frame = 1; + FrameRef frame_ref = 2; + } +} + +// This is a copy of BlobRequest here: https://github.com/Layr-Labs/eigenda/blob/main/api/proto/retriever/retriever.proto#L10 +message FrameRef { + bytes batch_header_hash = 1; + uint32 blob_index = 2; + uint32 reference_block_number = 3; + repeated uint32 quorum_ids = 4; + uint32 blob_length = 5; +} diff --git a/op-service/rethdb-reader/Cargo.lock b/op-service/rethdb-reader/Cargo.lock index 3f103fe045bf..9ad3a5ed6639 100644 --- a/op-service/rethdb-reader/Cargo.lock +++ b/op-service/rethdb-reader/Cargo.lock @@ -41,9 +41,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher 0.4.4", @@ -66,9 +66,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "8b79b82693f705137f8fb9b37871d99e4f9a7df12b917eed79c3d3954830a60b" dependencies = [ "cfg-if", "once_cell", @@ -91,20 +91,56 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "alloy-chains" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe92bd1fb0c96e938f9f2284618028e5f4dc3d719cac32631ed51e1b86a06895" +dependencies = [ + "alloy-rlp", + "arbitrary", + "num_enum", + "proptest", + "serde", + "strum", +] + +[[package]] +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=76c70fb#76c70fb9d44ace661bbf33408c2527e3874c964e" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "thiserror", +] + +[[package]] +name = "alloy-genesis" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=76c70fb#76c70fb9d44ace661bbf33408c2527e3874c964e" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types", + "serde", +] + [[package]] name = "alloy-primitives" -version = "0.5.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5def4b5e1bb8fe7ea37eeac1063246d4ef26f56cbdccf864a5a6bdcb80e91f4" +checksum = "ef197eb250c64962003cb08b90b17f0882c192f4a6f2f544809d424fd7cb0e7d" dependencies = [ "alloy-rlp", "bytes", "cfg-if", "const-hex", "derive_more", - "getrandom 0.2.10", + "getrandom 0.2.12", "hex-literal", "itoa", + "k256", + "keccak-asm", "proptest", "rand 0.8.5", "ruint", @@ -114,50 +150,87 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc0fac0fc16baf1f63f78b47c3d24718f3619b0714076f6a02957d808d52cbef" +checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" dependencies = [ "alloy-rlp-derive", "arrayvec", "bytes", - "smol_str", ] [[package]] name = "alloy-rlp-derive" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0391754c09fab4eae3404d19d0d297aa1c670c1775ab51d8a5312afeca23157" +checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", +] + +[[package]] +name = "alloy-rpc-engine-types" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=76c70fb#76c70fb9d44ace661bbf33408c2527e3874c964e" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types", + "jsonrpsee-types", + "serde", + "thiserror", +] + +[[package]] +name = "alloy-rpc-trace-types" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=76c70fb#76c70fb9d44ace661bbf33408c2527e3874c964e" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-rpc-types" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=76c70fb#76c70fb9d44ace661bbf33408c2527e3874c964e" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "itertools 0.12.1", + "jsonrpsee-types", + "serde", + "serde_json", + "thiserror", ] [[package]] name = "alloy-sol-macro" -version = "0.5.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0acd5b8d2699b095a57a0ecea6a6a2045b8e5ed6f2607bfa3382961d2889e82" +checksum = "82e92100dee7fd1e44abbe0ef6607f18758cf0ad4e483f4c65ff5c8d85428a6d" dependencies = [ "const-hex", "dunce", "heck", - "indexmap 2.0.2", + "indexmap 2.2.3", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-types" -version = "0.5.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d483e9c6db659cdb24fc736684ef68b743705fbdb0677c6404815361871b92" +checksum = "3e7c6a8c492b1d6a4f92a8fc6a13cf39473978dd7d459d7221969ce5a73d97cd" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -165,6 +238,22 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-trie" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b9e1498416f7e7f09af8061970e14936846b6271e153aa5ba539a22a7eb414d" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "derive_more", + "hashbrown 0.14.3", + "nybbles", + "serde", + "smallvec", + "tracing", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -180,26 +269,80 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "aquamarine" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df752953c49ce90719c7bf1fc587bc8227aed04732ea0c0f85e5397d7fdbd1a1" +checksum = "21cc1548309245035eb18aa7f0967da6bc65587005170c56e6ef2788a4cf3f4e" dependencies = [ "include_dir", "itertools 0.10.5", "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", ] +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + [[package]] name = "ark-ff" version = "0.3.0" @@ -332,43 +475,24 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", -] - -[[package]] -name = "atomic-polyfill" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" -dependencies = [ - "critical-section", -] - -[[package]] -name = "atomic-polyfill" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" -dependencies = [ - "critical-section", + "syn 2.0.52", ] [[package]] name = "attohttpc" -version = "0.16.3" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb8867f378f33f78a811a8eb9bf108ad99430d7aad43315dd9319c827ef6247" +checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2" dependencies = [ "http", "log", "url", - "wildmatch", ] [[package]] @@ -383,14 +507,13 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", ] [[package]] @@ -422,9 +545,9 @@ checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -452,52 +575,29 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.66.1" +version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cexpr", "clang-sys", + "itertools 0.12.1", "lazy_static", "lazycell", - "log", - "peeking_take_while", - "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", - "syn 2.0.38", - "which", -] - -[[package]] -name = "bindgen" -version = "0.68.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078" -dependencies = [ - "bitflags 2.4.1", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] name = "binout" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "288c7b1c00556959bb7dc822d8adad4a30edd0d3a1fcc6839515792b8f300e5f" +checksum = "b60b1af88a588fca5fe424ae7d735bc52814f80ff57614f57043cc4e2024f2ea" [[package]] name = "bit-set" @@ -522,18 +622,18 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" dependencies = [ "serde", ] [[package]] name = "bitm" -version = "0.2.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7becd9fb525c1c507eb025ec37129a0d9320aee17c841085a48101f4f18c0d27" +checksum = "31b9ea263f0faf826a1c9de0e8bf8f32f5986c05f5e3abcf6bcde74616009586" dependencies = [ "dyn_size_of", ] @@ -581,149 +681,11 @@ dependencies = [ "zeroize", ] -[[package]] -name = "boa_ast" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73498e9b2f0aa7db74977afa4d594657611e90587abf0dd564c0b55b4a130163" -dependencies = [ - "bitflags 2.4.1", - "boa_interner", - "boa_macros", - "indexmap 2.0.2", - "num-bigint", - "rustc-hash", -] - -[[package]] -name = "boa_engine" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16377479d5d6d33896e7acdd1cc698d04a8f72004025bbbddf47558cd29146a6" -dependencies = [ - "bitflags 2.4.1", - "boa_ast", - "boa_gc", - "boa_icu_provider", - "boa_interner", - "boa_macros", - "boa_parser", - "boa_profiler", - "chrono", - "dashmap", - "fast-float", - "icu_normalizer", - "indexmap 2.0.2", - "itertools 0.11.0", - "num-bigint", - "num-integer", - "num-traits", - "num_enum 0.6.1", - "once_cell", - "pollster", - "rand 0.8.5", - "regress", - "rustc-hash", - "ryu-js", - "serde", - "serde_json", - "sptr", - "static_assertions", - "tap", - "thin-vec", - "thiserror", -] - -[[package]] -name = "boa_gc" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c97b44beaef9d4452342d117d94607fdfa8d474280f1ba0fd97853834e3a49b2" -dependencies = [ - "boa_macros", - "boa_profiler", - "thin-vec", -] - -[[package]] -name = "boa_icu_provider" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30e52e34e451dd0bfc2c654a9a43ed34b0073dbd4ae3394b40313edda8627aa" -dependencies = [ - "icu_collections", - "icu_normalizer", - "icu_properties", - "icu_provider", - "icu_provider_adapters", - "icu_provider_blob", - "once_cell", -] - -[[package]] -name = "boa_interner" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e5afa991908cfbe79bd3109b824e473a1dc5f74f31fab91bb44c9e245daa77" -dependencies = [ - "boa_gc", - "boa_macros", - "hashbrown 0.14.2", - "indexmap 2.0.2", - "once_cell", - "phf", - "rustc-hash", - "static_assertions", -] - -[[package]] -name = "boa_macros" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "005fa0c5bd20805466dda55eb34cd709bb31a2592bb26927b47714eeed6914d8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", - "synstructure", -] - -[[package]] -name = "boa_parser" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e09afb035377a9044443b598187a7d34cd13164617182a4d7c348522ee3f052" -dependencies = [ - "bitflags 2.4.1", - "boa_ast", - "boa_icu_provider", - "boa_interner", - "boa_macros", - "boa_profiler", - "fast-float", - "icu_locid", - "icu_properties", - "icu_provider", - "icu_provider_macros", - "num-bigint", - "num-traits", - "once_cell", - "regress", - "rustc-hash", - "tinystr", -] - -[[package]] -name = "boa_profiler" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3190f92dfe48224adc92881c620f08ccf37ff62b91a094bb357fe53bd5e84647" - [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" [[package]] name = "byte-slice-cast" @@ -748,11 +710,10 @@ dependencies = [ [[package]] name = "c-kzg" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32700dc7904064bb64e857d38a1766607372928e2466ee5f02a869829b3297d7" +checksum = "94a4bc5367b6284358d2a6a6a1dc2d92ec4b86034561c3b9d3341909752fd848" dependencies = [ - "bindgen 0.66.1", "blst", "cc", "glob", @@ -788,9 +749,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ "android-tzdata", "iana-time-zone", @@ -798,7 +759,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets", + "windows-targets 0.52.4", ] [[package]] @@ -822,9 +783,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" dependencies = [ "glob", "libc", @@ -832,41 +793,82 @@ dependencies = [ ] [[package]] -name = "cobs" -version = "0.2.3" +name = "clap" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.0", +] + +[[package]] +name = "clap_derive" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.52", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "codecs-derive" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ "convert_case 0.6.0", "parity-scale-codec", "proc-macro2", "quote", "serde", - "syn 2.0.38", + "syn 2.0.52", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "const-hex" -version = "1.9.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c37be52ef5e3b394db27a2341010685ad5103c72ac15ce2e9420a7e8f93f342c" +checksum = "efbd12d49ab0eaf8193ba9175e45f56bbc2e4b27d57b8cfe62aa47942a46b9a9" dependencies = [ "cfg-if", "cpufeatures", "hex", + "proptest", "serde", ] [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "convert_case" @@ -885,15 +887,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -909,58 +911,43 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" - -[[package]] -name = "critical-section" -version = "1.1.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crunchy" @@ -970,9 +957,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", "rand_core 0.6.4", @@ -1033,9 +1020,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" dependencies = [ "cfg-if", "cpufeatures", @@ -1050,13 +1037,13 @@ dependencies = [ [[package]] name = "curve25519-dalek-derive" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -1071,12 +1058,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ - "darling_core 0.20.3", - "darling_macro 0.20.3", + "darling_core 0.20.8", + "darling_macro 0.20.8", ] [[package]] @@ -1095,16 +1082,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -1120,13 +1107,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ - "darling_core 0.20.3", + "darling_core 0.20.8", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -1136,7 +1123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.2", + "hashbrown 0.14.3", "lock_api", "once_cell", "parking_lot_core 0.9.9", @@ -1144,9 +1131,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "delay_map" @@ -1170,9 +1157,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", "serde", @@ -1264,7 +1251,7 @@ dependencies = [ "hex", "hkdf", "lazy_static", - "lru 0.12.0", + "lru", "more-asserts", "parking_lot 0.11.2", "rand 0.8.5", @@ -1278,17 +1265,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "displaydoc" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - [[package]] name = "dns-lookup" version = "1.0.8" @@ -1309,15 +1285,15 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "dyn_size_of" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8adcce29eef18ae1369bbd268fd56bf98144e80281315e9d4a82e34df001c7" +checksum = "33d4f78a40b1ec35bf8cafdaaf607ba2f773c366b0b3bda48937cacd7a8d5134" [[package]] name = "ecdsa" -version = "0.16.8" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", "digest 0.10.7", @@ -1339,15 +1315,16 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", "rand_core 0.6.4", "serde", "sha2", + "subtle", "zeroize", ] @@ -1365,15 +1342,15 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "elliptic-curve" -version = "0.13.6" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", @@ -1388,12 +1365,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "embedded-io" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" - [[package]] name = "endian-type" version = "0.1.2" @@ -1442,18 +1413,18 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] name = "enumn" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" +checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -1464,30 +1435,24 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "eyre" -version = "0.6.8" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", ] -[[package]] -name = "fast-float" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95765f67b4b18863968b4a1bd5bb576f732b29a4a28c7cd84c09fa3e2875f33c" - [[package]] name = "fastrand" version = "2.0.1" @@ -1517,9 +1482,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.1" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" +checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" [[package]] name = "fixed-hash" @@ -1541,9 +1506,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -1556,9 +1521,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1571,9 +1536,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1581,15 +1546,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1598,38 +1563,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -1667,9 +1632,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -1688,9 +1653,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" @@ -1721,22 +1686,13 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.0.2", + "indexmap 2.2.3", "slab", "tokio", "tokio-util", "tracing", ] -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -1745,18 +1701,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash", -] - -[[package]] -name = "hashbrown" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ "ahash", "allocator-api2", @@ -1769,21 +1716,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.2", -] - -[[package]] -name = "heapless" -version = "0.7.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" -dependencies = [ - "atomic-polyfill 0.1.11", - "hash32", - "rustc_version 0.4.0", - "serde", - "spin 0.9.8", - "stable_deref_trait", + "hashbrown 0.14.3", ] [[package]] @@ -1794,9 +1727,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "379dada1584ad501b383485dd706b8afb7a70fcbc7f4da7d780638a5a6124a60" [[package]] name = "hex" @@ -1815,9 +1748,9 @@ checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" [[package]] name = "hkdf" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ "hmac", ] @@ -1831,20 +1764,11 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "home" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" -dependencies = [ - "windows-sys", -] - [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -1853,9 +1777,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -1876,9 +1800,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -1891,7 +1815,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.6", "tokio", "tower-service", "tracing", @@ -1914,9 +1838,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1935,122 +1859,6 @@ dependencies = [ "cc", ] -[[package]] -name = "icu_collections" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8302d8dfd6044d3ddb3f807a5ef3d7bbca9a574959c6d6e4dc39aa7012d0d5" -dependencies = [ - "displaydoc", - "serde", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3003f85dccfc0e238ff567693248c59153a46f4e6125ba4020b973cef4d1d335" -dependencies = [ - "displaydoc", - "litemap", - "serde", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "652869735c9fb9f5a64ba180ee16f2c848390469c116deef517ecc53f4343598" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_properties", - "icu_provider", - "serde", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_properties" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce0e1aa26851f16c9e04412a5911c86b7f8768dac8f8d4c5f1c568a7e5d7a434" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_provider", - "serde", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_provider" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc312a7b6148f7dfe098047ae2494d12d4034f48ade58d4f353000db376e305" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "postcard", - "serde", - "stable_deref_trait", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_adapters" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ae1e2bd0c41728b77e7c46e9afdec5e2127d1eedacc684724667d50c126bd3" -dependencies = [ - "icu_locid", - "icu_provider", - "serde", - "tinystr", - "yoke", - "zerovec", -] - -[[package]] -name = "icu_provider_blob" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd364c9a01f791a4bc04a74cf2a1d01d9f6926a40fd5ae1c28004e1e70d8338b" -dependencies = [ - "icu_provider", - "postcard", - "serde", - "writeable", - "yoke", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b728b9421e93eff1d9f8681101b78fa745e0748c95c655c83f337044a7e10" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -2070,19 +1878,21 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", ] [[package]] -name = "igd" -version = "0.12.0" -source = "git+https://github.com/stevefan1999-personal/rust-igd?rev=c2d1f83eb1612a462962453cb0703bc93258b173#c2d1f83eb1612a462962453cb0703bc93258b173" +name = "igd-next" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064d90fec10d541084e7b39ead8875a5a80d9114a2b18791565253bae25f49e4" dependencies = [ + "async-trait", "attohttpc", "bytes", "futures", @@ -2153,12 +1963,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" dependencies = [ "equivalent", - "hashbrown 0.14.2", + "hashbrown 0.14.3", "serde", ] @@ -2198,33 +2008,33 @@ dependencies = [ [[package]] name = "itertools" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" dependencies = [ "wasm-bindgen", ] @@ -2245,9 +2055,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ "cfg-if", "ecdsa", @@ -2259,20 +2069,30 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] +[[package]] +name = "keccak-asm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb8515fff80ed850aea4a1595f2e519c003e2a00a82fe168ebf5269196caf444" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] @@ -2283,18 +2103,37 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libffi" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2" +dependencies = [ + "libc", + "libffi-sys", +] + +[[package]] +name = "libffi-sys" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c" +dependencies = [ + "cc", +] [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -2320,15 +2159,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" - -[[package]] -name = "litemap" -version = "0.7.1" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2647d5b7134127971a6de0d533c49de2159167e7f259c427195f87168a1" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -2348,27 +2181,18 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "lru" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a83fb7698b3643a0e34f9ae6f2e8f0178c0fd42f8b59d493aa271ff3a5bf21" -dependencies = [ - "hashbrown 0.14.2", -] - -[[package]] -name = "lru" -version = "0.12.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efa59af2ddfad1854ae27d75009d538d0998b4b2fd47083e743ac1a10e46c60" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown 0.14.2", + "hashbrown 0.14.3", ] [[package]] name = "lz4_flex" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea9b256699eda7b0387ffbc776dd625e28bde3918446381781245b7a50349d8" +checksum = "912b45c753ff5f7f5208307e8ace7d2a2e30d024e26d3509f3dce546c044ce15" [[package]] name = "matchers" @@ -2387,9 +2211,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" @@ -2400,15 +2224,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - [[package]] name = "metrics" version = "0.21.1" @@ -2422,13 +2237,13 @@ dependencies = [ [[package]] name = "metrics-macros" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddece26afd34c31585c74a4db0630c376df271c285d682d1e55012197830b6df" +checksum = "38b4faf00617defe497754acde3024865bc143d44a86799b24e191ecff91354f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -2439,22 +2254,22 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2536,33 +2351,37 @@ dependencies = [ "autocfg", "num-integer", "num-traits", - "serde", ] [[package]] name = "num-complex" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" dependencies = [ "autocfg", "num-integer", @@ -2583,9 +2402,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", "libm", @@ -2603,73 +2422,52 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" -dependencies = [ - "num_enum_derive 0.6.1", -] - -[[package]] -name = "num_enum" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb" -dependencies = [ - "num_enum_derive 0.7.0", -] - -[[package]] -name = "num_enum_derive" -version = "0.6.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.38", + "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] -name = "num_threads" -version = "0.1.6" +name = "nybbles" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "95f06be0417d97f81fe4e5c86d7d01b392655a9cac9c19a848aa033e18937b23" dependencies = [ - "libc", + "alloy-rlp", + "const-hex", + "proptest", + "serde", + "smallvec", ] [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -dependencies = [ - "atomic-polyfill 1.0.3", - "critical-section", -] +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" @@ -2695,9 +2493,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.5" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" dependencies = [ "arrayvec", "bitvec", @@ -2710,11 +2508,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.5" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", "syn 1.0.109", @@ -2765,7 +2563,7 @@ dependencies = [ "libc", "redox_syscall 0.4.1", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -2774,23 +2572,17 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.5" +version = "2.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +checksum = "219c0dcc30b6a27553f9cc242972b67f75b60eb0db71f0b5462f38b058c41546" dependencies = [ "memchr", "thiserror", @@ -2799,9 +2591,9 @@ dependencies = [ [[package]] name = "ph" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88c6e62e083483e2812a9d2a6eff6b97871302ef4166b5182c6da30624b7e991" +checksum = "86b7b74d575d7c11fb653fae69688be5206cafc1ead33c01ce61ac7f36eae45b" dependencies = [ "binout", "bitm", @@ -2810,66 +2602,24 @@ dependencies = [ "wyhash", ] -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared", - "rand 0.8.5", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -2896,21 +2646,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "platforms" -version = "3.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" - -[[package]] -name = "pollster" -version = "0.3.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" +checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" [[package]] name = "polyval" @@ -2926,21 +2670,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b559898e0b4931ed2d3b959ab0c2da4d99cc644c4b0b1a35b4d344027f474023" - -[[package]] -name = "postcard" -version = "1.0.8" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" -dependencies = [ - "cobs", - "embedded-io", - "heapless", - "serde", -] +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" [[package]] name = "powerfmt" @@ -2954,16 +2686,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "prettyplease" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" -dependencies = [ - "proc-macro2", - "syn 2.0.38", -] - [[package]] name = "primitive-types" version = "0.12.2" @@ -2977,12 +2699,20 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "once_cell", - "toml_edit", + "toml_edit 0.20.7", +] + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", ] [[package]] @@ -3011,28 +2741,28 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.4.1", + "bitflags 2.4.2", "lazy_static", "num-traits", "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.7.5", + "regex-syntax 0.8.2", "rusty-fork", "tempfile", "unarray", @@ -3067,9 +2797,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -3149,7 +2879,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.12", ] [[package]] @@ -3172,9 +2902,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" dependencies = [ "either", "rayon-core", @@ -3182,9 +2912,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -3199,15 +2929,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -3219,13 +2940,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", + "regex-automata 0.4.5", "regex-syntax 0.8.2", ] @@ -3240,9 +2961,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -3255,36 +2976,20 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" -[[package]] -name = "regex-syntax" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" - [[package]] name = "regex-syntax" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" -[[package]] -name = "regress" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a9ecfa0cb04d0b04dddb99b8ccf4f66bc8dfd23df694b398570bd8ae3a50fb" -dependencies = [ - "hashbrown 0.13.2", - "memchr", -] - [[package]] name = "reth-blockchain-tree" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ "aquamarine", "linked_hash_set", - "lru 0.11.1", + "lru", "metrics", "parking_lot 0.12.1", "reth-db", @@ -3293,25 +2998,27 @@ dependencies = [ "reth-primitives", "reth-provider", "reth-stages", + "reth-trie", "tokio", "tracing", ] [[package]] name = "reth-codecs" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ + "alloy-primitives", "bytes", "codecs-derive", - "revm-primitives", ] [[package]] name = "reth-consensus-common" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ + "alloy-chains", "cfg-if", "reth-interfaces", "reth-primitives", @@ -3320,24 +3027,19 @@ dependencies = [ [[package]] name = "reth-db" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ "bytes", "derive_more", "eyre", - "futures", - "heapless", - "itertools 0.11.0", "metrics", "modular-bitfield", + "once_cell", "page_size", "parity-scale-codec", "parking_lot 0.12.1", "paste", - "postcard", - "rand 0.8.5", - "rayon", "reth-codecs", "reth-interfaces", "reth-libmdbx", @@ -3345,16 +3047,16 @@ dependencies = [ "reth-nippy-jar", "reth-primitives", "reth-tracing", + "rustc-hash", "serde", + "strum", "thiserror", - "tokio-stream", - "vergen", ] [[package]] name = "reth-discv4" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ "alloy-rlp", "discv5", @@ -3375,10 +3077,10 @@ dependencies = [ [[package]] name = "reth-ecies" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ - "aes 0.8.3", + "aes 0.8.4", "alloy-rlp", "block-padding", "byteorder", @@ -3406,12 +3108,13 @@ dependencies = [ [[package]] name = "reth-eth-wire" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ + "alloy-chains", "alloy-rlp", - "async-trait", "bytes", + "derive_more", "futures", "metrics", "pin-project", @@ -3429,59 +3132,68 @@ dependencies = [ "tracing", ] +[[package]] +name = "reth-ethereum-forks" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" +dependencies = [ + "alloy-chains", + "alloy-primitives", + "alloy-rlp", + "crc", + "serde", + "thiserror", +] + [[package]] name = "reth-interfaces" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ - "async-trait", "auto_impl", "futures", - "modular-bitfield", - "parking_lot 0.12.1", - "rand 0.8.5", - "reth-codecs", "reth-eth-wire", "reth-network-api", "reth-nippy-jar", "reth-primitives", "reth-rpc-types", - "revm-primitives", "thiserror", "tokio", - "tokio-stream", "tracing", ] [[package]] name = "reth-libmdbx" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "byteorder", + "dashmap", "derive_more", - "indexmap 2.0.2", + "indexmap 2.2.3", "libc", + "libffi", "parking_lot 0.12.1", "reth-mdbx-sys", "thiserror", + "tracing", ] [[package]] name = "reth-mdbx-sys" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ - "bindgen 0.68.1", + "bindgen", "cc", "libc", ] [[package]] name = "reth-metrics" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ "futures", "metrics", @@ -3492,20 +3204,20 @@ dependencies = [ [[package]] name = "reth-metrics-derive" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ "once_cell", "proc-macro2", "quote", "regex", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] name = "reth-net-common" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ "pin-project", "reth-primitives", @@ -3514,10 +3226,10 @@ dependencies = [ [[package]] name = "reth-net-nat" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ - "igd", + "igd-next", "pin-project-lite", "public-ip", "serde_with", @@ -3528,9 +3240,10 @@ dependencies = [ [[package]] name = "reth-network-api" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ + "alloy-chains", "async-trait", "reth-discv4", "reth-eth-wire", @@ -3543,8 +3256,8 @@ dependencies = [ [[package]] name = "reth-nippy-jar" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ "anyhow", "bincode", @@ -3560,49 +3273,66 @@ dependencies = [ "zstd", ] +[[package]] +name = "reth-node-api" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" +dependencies = [ + "reth-primitives", + "reth-rpc-types", + "revm", + "revm-primitives", + "serde", + "thiserror", +] + [[package]] name = "reth-primitives" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ + "alloy-chains", + "alloy-eips", + "alloy-genesis", "alloy-primitives", "alloy-rlp", + "alloy-trie", "byteorder", "bytes", "c-kzg", - "crc", + "cfg-if", "derive_more", - "itertools 0.11.0", + "itertools 0.12.1", "modular-bitfield", - "num_enum 0.7.0", + "num_enum", + "nybbles", "once_cell", "rayon", "reth-codecs", + "reth-ethereum-forks", "reth-rpc-types", "revm", "revm-primitives", "secp256k1 0.27.0", "serde", "serde_json", - "serde_with", "sha2", "strum", "sucds 0.6.0", "tempfile", "thiserror", "tracing", - "url", "zstd", ] [[package]] name = "reth-provider" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ "auto_impl", "dashmap", - "itertools 0.11.0", + "itertools 0.12.1", "metrics", "parking_lot 0.12.1", "pin-project", @@ -3611,9 +3341,11 @@ dependencies = [ "reth-interfaces", "reth-metrics", "reth-nippy-jar", + "reth-node-api", "reth-primitives", "reth-trie", "revm", + "strum", "tokio", "tokio-stream", "tracing", @@ -3621,44 +3353,31 @@ dependencies = [ [[package]] name = "reth-revm" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ "reth-consensus-common", "reth-interfaces", + "reth-node-api", "reth-primitives", "reth-provider", - "reth-revm-inspectors", "revm", + "revm-inspectors", "tracing", ] -[[package]] -name = "reth-revm-inspectors" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" -dependencies = [ - "alloy-primitives", - "alloy-sol-types", - "boa_engine", - "boa_gc", - "reth-rpc-types", - "revm", - "serde", - "serde_json", - "thiserror", - "tokio", -] - [[package]] name = "reth-rpc-types" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ "alloy-primitives", "alloy-rlp", + "alloy-rpc-engine-types", + "alloy-rpc-trace-types", + "alloy-rpc-types", "bytes", - "itertools 0.11.0", + "itertools 0.12.1", "jsonrpsee-types", "secp256k1 0.27.0", "serde", @@ -3670,14 +3389,13 @@ dependencies = [ [[package]] name = "reth-stages" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ "aquamarine", - "async-trait", "auto_impl", "futures-util", - "itertools 0.11.0", + "itertools 0.12.1", "metrics", "num-traits", "pin-project", @@ -3700,8 +3418,8 @@ dependencies = [ [[package]] name = "reth-tokio-util" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ "tokio", "tokio-stream", @@ -3709,29 +3427,33 @@ dependencies = [ [[package]] name = "reth-tracing" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ + "clap", + "eyre", "rolling-file", "tracing", "tracing-appender", "tracing-journald", + "tracing-logfmt", "tracing-subscriber", ] [[package]] name = "reth-trie" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth.git?rev=b58bfe6#b58bfe6e37f8e8e017c6c5d43c5a9fca9af7e819" +version = "0.1.0-alpha.21" +source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" dependencies = [ + "alloy-chains", "alloy-rlp", "auto_impl", "derive_more", "reth-db", "reth-interfaces", "reth-primitives", + "revm", "thiserror", - "tokio", "tracing", ] @@ -3753,26 +3475,47 @@ dependencies = [ [[package]] name = "revm" -version = "3.5.0" -source = "git+https://github.com/bluealloy/revm?branch=reth_freeze#b00ebab8b3477f87e3d876a11b8f18d00a8f4103" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d35316fc02d99e42831356c71e882f5d385c77b78f64a44ae82f2f9a4b8b72f" +dependencies = [ + "auto_impl", + "cfg-if", + "revm-interpreter", + "revm-precompile", + "serde", + "serde_json", +] + +[[package]] +name = "revm-inspectors" +version = "0.1.0" +source = "git+https://github.com/paradigmxyz/evm-inspectors?rev=75a187b#75a187ba967a29b30af2e5e848073c755068da06" dependencies = [ - "auto_impl", - "revm-interpreter", - "revm-precompile", + "alloy-primitives", + "alloy-rpc-trace-types", + "alloy-rpc-types", + "alloy-sol-types", + "anstyle", + "colorchoice", + "revm", ] [[package]] name = "revm-interpreter" -version = "1.3.0" -source = "git+https://github.com/bluealloy/revm?branch=reth_freeze#b00ebab8b3477f87e3d876a11b8f18d00a8f4103" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fa10c2dc1e8f4934bdc763a2c09371bcec29e50c22e55e3eb325ee0cba09064" dependencies = [ "revm-primitives", + "serde", ] [[package]] name = "revm-precompile" -version = "2.2.0" -source = "git+https://github.com/bluealloy/revm?branch=reth_freeze#b00ebab8b3477f87e3d876a11b8f18d00a8f4103" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db828d49d329560a70809d9d1fa0c74695edb49f50c5332db3eb24483076deac" dependencies = [ "aurora-engine-modexp", "c-kzg", @@ -3780,25 +3523,26 @@ dependencies = [ "once_cell", "revm-primitives", "ripemd", - "secp256k1 0.28.0", + "secp256k1 0.28.2", "sha2", "substrate-bn", ] [[package]] name = "revm-primitives" -version = "1.3.0" -source = "git+https://github.com/bluealloy/revm?branch=reth_freeze#b00ebab8b3477f87e3d876a11b8f18d00a8f4103" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fecd125aad58e135e2ca5771ed6e4e7b1f05fa3a64e0dfb9cc643b7a800a8435" dependencies = [ "alloy-primitives", - "alloy-rlp", "auto_impl", - "bitflags 2.4.1", + "bitflags 2.4.2", "bitvec", "c-kzg", + "cfg-if", "derive_more", "enumn", - "hashbrown 0.14.2", + "hashbrown 0.14.3", "hex", "once_cell", "serde", @@ -3844,9 +3588,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608a5726529f2f0ef81b8fde9873c4bb829d6b5b5ca6be4d97345ddf0749c825" +checksum = "49b1d9521f889713d1221270fdd63370feca7e5c71a18745343402fa86e4f04f" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", @@ -3868,9 +3612,9 @@ dependencies = [ [[package]] name = "ruint-macro" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e666a5496a0b2186dbcd0ff6106e29e093c15591bde62c20d3842007c6978a09" +checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" [[package]] name = "rustc-demangle" @@ -3905,20 +3649,20 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.20", + "semver 1.0.22", ] [[package]] name = "rustix" -version = "0.38.20" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -3941,15 +3685,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "ryu-js" -version = "0.2.2" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6518fc26bced4d53678a22d6e423e9d8716377def84545fe328236e3af070e7f" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "scopeguard" @@ -3984,11 +3722,11 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.28.0" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ - "secp256k1-sys 0.9.0", + "secp256k1-sys 0.9.2", ] [[package]] @@ -4002,9 +3740,9 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09e67c467c38fd24bd5499dc9a18183b31575c12ee549197e3e20d57aa4fe3b7" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" dependencies = [ "cc", ] @@ -4020,9 +3758,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "semver-parser" @@ -4035,39 +3773,40 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.190" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.12" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ + "indexmap 2.2.3", "itoa", "ryu", "serde", @@ -4075,16 +3814,17 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.4.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" +checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" dependencies = [ "base64", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.0.2", + "indexmap 2.2.3", "serde", + "serde_derive", "serde_json", "serde_with_macros", "time", @@ -4092,14 +3832,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.4.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" +checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d" dependencies = [ - "darling 0.20.3", + "darling 0.20.8", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -4123,6 +3863,16 @@ dependencies = [ "keccak", ] +[[package]] +name = "sha3-asm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bac61da6b35ad76b195eb4771210f947734321a8d81d7738e1580d953bc7a15e" +dependencies = [ + "cc", + "cfg-if", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -4149,20 +3899,14 @@ dependencies = [ [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", "rand_core 0.6.4", ] -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - [[package]] name = "slab" version = "0.4.9" @@ -4174,24 +3918,18 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" - -[[package]] -name = "smol_str" -version = "0.2.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" dependencies = [ "serde", ] [[package]] name = "snap" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "socket2" @@ -4205,12 +3943,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -4219,37 +3957,16 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", ] -[[package]] -name = "sptr" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "static_assertions" version = "1.1.0" @@ -4268,26 +3985,32 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strsim" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" + [[package]] name = "strum" -version = "0.25.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.25.3" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" dependencies = [ "heck", "proc-macro2", "quote", "rustversion", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -4341,9 +4064,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", @@ -4352,26 +4075,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.5.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e349ed2ca56eff703d7c3ea013771bcbab9ad2ad39dddf863fc51d820329dc41" +checksum = "e656cbcef8a77543b5accbd76f60f9e0bc4be364b0aba4263a6f313f8a355511" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.38", -] - -[[package]] -name = "synstructure" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", - "unicode-xid", + "syn 2.0.52", ] [[package]] @@ -4382,48 +4093,41 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", "rustix", - "windows-sys", + "windows-sys 0.52.0", ] -[[package]] -name = "thin-vec" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8" - [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -4440,14 +4144,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", "itoa", - "libc", - "num_threads", + "num-conv", "powerfmt", "serde", "time-core", @@ -4462,10 +4165,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] @@ -4478,17 +4182,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "tinystr" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8faa444297615a4e020acb64146b0603c9c395c03a97c17fd9028816d3b4d63e" -dependencies = [ - "displaydoc", - "serde", - "zerovec", -] - [[package]] name = "tinyvec" version = "1.6.0" @@ -4506,9 +4199,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.33.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", @@ -4518,20 +4211,20 @@ dependencies = [ "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2 0.5.6", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -4569,11 +4262,22 @@ checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" [[package]] name = "toml_edit" -version = "0.19.15" +version = "0.20.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +dependencies = [ + "indexmap 2.2.3", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -4598,11 +4302,12 @@ dependencies = [ [[package]] name = "tracing-appender" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", + "thiserror", "time", "tracing-subscriber", ] @@ -4615,7 +4320,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] @@ -4653,31 +4358,56 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ "log", "once_cell", "tracing-core", ] +[[package]] +name = "tracing-logfmt" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84bab42e40ace4e4ff19c92023ee1dbc1510db60976828fbbdc6994852c7d065" +dependencies = [ + "time", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", "once_cell", "regex", + "serde", + "serde_json", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", + "tracing-serde", ] [[package]] @@ -4727,9 +4457,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" @@ -4763,9 +4493,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -4775,24 +4505,18 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode-xid" -version = "0.2.4" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "universal-hash" @@ -4806,26 +4530,20 @@ dependencies = [ [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 0.4.0", + "idna 0.5.0", "percent-encoding", ] [[package]] -name = "utf16_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52df8b7fb78e7910d776fccf2e42ceaf3604d55e8e7eb2dbd183cb1441d8a692" - -[[package]] -name = "utf8_iter" -version = "1.0.3" +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a8922555b9500e3d865caed19330172cd67cbf82203f1a3311d8c305cc9f33" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "valuable" @@ -4833,17 +4551,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" -[[package]] -name = "vergen" -version = "8.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e7dc29b3c54a2ea67ef4f953d5ec0c4085035c0ae2d325be1c0d2144bd9f16" -dependencies = [ - "anyhow", - "rustversion", - "time", -] - [[package]] name = "version_check" version = "0.9.4" @@ -4882,9 +4589,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4892,24 +4599,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4917,40 +4624,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.52", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "wildmatch" -version = "1.1.0" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f44b95f62d34113cf558c93511ac93027e03e9c29a60dd0fd70e6e025c7270a" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] name = "winapi" @@ -4976,11 +4665,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.4", ] [[package]] @@ -4989,7 +4678,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", ] [[package]] @@ -4998,13 +4696,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -5013,63 +4726,93 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + [[package]] name = "winnow" -version = "0.5.17" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0af0c3d13faebf8dda0b5256fa7096a2d5ccb662f7b9f54a40fe201077ab1c2" - [[package]] name = "wyhash" version = "0.5.0" @@ -5103,76 +4846,31 @@ dependencies = [ "xml-rs", ] -[[package]] -name = "yoke" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e38c508604d6bbbd292dadb3c02559aa7fff6b654a078a36217cad871636e4" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5e19fb6ed40002bab5403ffa37e53e0e56f914a4450c8765f533018db1db35f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", - "synstructure", -] - [[package]] name = "zerocopy" -version = "0.7.31" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "zerofrom" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655b0814c5c0b19ade497851070c640773304939a6c0fd5f5fb43da0696d05b7" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.3" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a647510471d372f2e6c2e6b7219e44d8c574d24fdc11c610a61455782f18c3" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", - "synstructure", + "syn 2.0.52", ] [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" dependencies = [ "zeroize_derive", ] @@ -5185,30 +4883,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", -] - -[[package]] -name = "zerovec" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "591691014119b87047ead4dcf3e6adfbf73cb7c38ab6980d4f18a32138f35d46" -dependencies = [ - "serde", - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a4a1638a1934450809c2266a70362bfc96cd90550c073f5b8a55014d1010157" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", + "syn 2.0.52", ] [[package]] diff --git a/op-service/rethdb-reader/Cargo.toml b/op-service/rethdb-reader/Cargo.toml index e613e9447a1e..16bbc7325b7f 100644 --- a/op-service/rethdb-reader/Cargo.toml +++ b/op-service/rethdb-reader/Cargo.toml @@ -10,17 +10,17 @@ crate-type = ["cdylib"] [dependencies] # reth -reth-primitives = { git = "https://github.com/paradigmxyz/reth.git", rev = "b58bfe6" } -reth-provider = { git = "https://github.com/paradigmxyz/reth.git", rev = "b58bfe6" } -reth-db = { git = "https://github.com/paradigmxyz/reth.git", rev = "b58bfe6" } -reth-rpc-types = { git = "https://github.com/paradigmxyz/reth.git", rev = "b58bfe6" } -reth-blockchain-tree = { git = "https://github.com/paradigmxyz/reth.git", rev = "b58bfe6" } +reth-primitives = { git = "https://github.com/paradigmxyz/reth.git", rev = "e0c220e" } +reth-provider = { git = "https://github.com/paradigmxyz/reth.git", rev = "e0c220e" } +reth-db = { git = "https://github.com/paradigmxyz/reth.git", rev = "e0c220e" } +reth-rpc-types = { git = "https://github.com/paradigmxyz/reth.git", rev = "e0c220e" } +reth-blockchain-tree = { git = "https://github.com/paradigmxyz/reth.git", rev = "e0c220e" } # misc -serde = "1.0.190" -serde_json = "1.0.107" -anyhow = "1.0.75" +serde = "1.0.197" +serde_json = "1.0.114" +anyhow = "1.0.80" [dev-dependencies] -reth-revm = { git = "https://github.com/paradigmxyz/reth.git", rev = "b58bfe6" } -alloy-rlp = "0.3.3" +reth-revm = { git = "https://github.com/paradigmxyz/reth.git", rev = "e0c220e" } +alloy-rlp = "0.3.4" diff --git a/op-service/rethdb-reader/src/receipts.rs b/op-service/rethdb-reader/src/receipts.rs index 3ecddda7fd96..3e10900ef6e5 100644 --- a/op-service/rethdb-reader/src/receipts.rs +++ b/op-service/rethdb-reader/src/receipts.rs @@ -3,7 +3,7 @@ use anyhow::{anyhow, Result}; use reth_blockchain_tree::noop::NoopBlockchainTree; -use reth_db::open_db_read_only; +use reth_db::{mdbx::DatabaseArguments, open_db_read_only}; use reth_primitives::{ BlockHashOrNumber, Receipt, TransactionKind, TransactionMeta, TransactionSigned, MAINNET, U128, U256, U64, @@ -66,7 +66,8 @@ pub(crate) unsafe fn read_receipts_inner( } .to_str()?; - let db = open_db_read_only(Path::new(db_path_str), None).map_err(|e| anyhow!(e))?; + let db = open_db_read_only(Path::new(db_path_str), DatabaseArguments::default()) + .map_err(|e| anyhow!(e))?; let factory = ProviderFactory::new(db, MAINNET.clone()); // Create a read-only BlockChainProvider @@ -159,6 +160,9 @@ fn build_transaction_receipt_with_block_receipts( // EIP-4844 fields blob_gas_price: None, blob_gas_used: None, + + // Other: + other: Default::default(), }; match tx.transaction.kind() { @@ -199,7 +203,7 @@ fn build_transaction_receipt_with_block_receipts( mod test { use super::*; use alloy_rlp::Decodable; - use reth_db::database::Database; + use reth_db::{database::Database, mdbx::DatabaseArguments}; use reth_primitives::{ address, b256, bloom, hex, Address, Block, Bytes, ReceiptWithBloom, Receipts, SealedBlockWithSenders, U8, @@ -235,11 +239,12 @@ mod test { #[inline] fn open_receipts_testdata_db() -> Result<()> { if File::open("testdata/db").is_ok() { - return Ok(()) + return Ok(()); } // Open a RW handle to the MDBX database - let db = reth_db::init_db(Path::new("testdata/db"), None).map_err(|e| anyhow!(e))?; + let db = reth_db::init_db(Path::new("testdata/db"), DatabaseArguments::default()) + .map_err(|e| anyhow!(e))?; let pr = DatabaseProvider::new_rw(db.tx_mut()?, MAINNET.clone()); // Grab the dummy block and receipts @@ -260,13 +265,15 @@ mod test { .ok_or(anyhow!("Failed to recover signers"))?; // Commit the bundle state to the database - pr.append_blocks_with_bundle_state( + pr.append_blocks_with_state( vec![SealedBlockWithSenders { block: block.seal_slow(), senders }], BundleStateWithReceipts::new( BundleState::default(), Receipts::from_block_receipt(receipts), block_number, ), + Default::default(), + Default::default(), None, )?; pr.commit()?; diff --git a/op-service/rpc/api.go b/op-service/rpc/api.go index 6ed8229d92dd..1bea71ad5799 100644 --- a/op-service/rpc/api.go +++ b/op-service/rpc/api.go @@ -33,13 +33,12 @@ func (n *CommonAdminAPI) SetLogLevel(ctx context.Context, lvlStr string) error { recordDur := n.M.RecordRPCServerRequest("admin_setLogLevel") defer recordDur() - h := n.log.GetHandler() - - lvl, err := log.LvlFromString(lvlStr) + lvl, err := oplog.LevelFromString(lvlStr) if err != nil { return err } + h := n.log.Handler() // We set the log level, and do not wrap the handler with an additional filter handler, // as the underlying handler would otherwise also still filter with the previous log level. lvlSetter, ok := h.(oplog.LvlSetter) diff --git a/op-service/rpc/server.go b/op-service/rpc/server.go index b569e5929428..a715c0de699b 100644 --- a/op-service/rpc/server.go +++ b/op-service/rpc/server.go @@ -204,6 +204,8 @@ func (b *Server) Start() error { // verify that the server comes up tick := time.NewTimer(10 * time.Millisecond) + defer tick.Stop() + select { case err := <-errCh: return fmt.Errorf("http server failed: %w", err) diff --git a/op-service/signer/client.go b/op-service/signer/client.go index e5baa33568f8..9822a1a7409f 100644 --- a/op-service/signer/client.go +++ b/op-service/signer/client.go @@ -93,17 +93,23 @@ func (s *SignerClient) pingVersion() (string, error) { } func (s *SignerClient) SignTransaction(ctx context.Context, chainId *big.Int, from common.Address, tx *types.Transaction) (*types.Transaction, error) { - args := NewTransactionArgsFromTransaction(chainId, from, tx) + sidecar := tx.BlobTxSidecar() + args := NewTransactionArgsFromTransaction(chainId, &from, tx.WithoutBlobTxSidecar()) var result hexutil.Bytes if err := s.client.CallContext(ctx, &result, "eth_signTransaction", args); err != nil { return nil, fmt.Errorf("eth_signTransaction failed: %w", err) } - signed := &types.Transaction{} + var signed types.Transaction if err := signed.UnmarshalBinary(result); err != nil { return nil, err } + if sidecar != nil { + if err := signed.SetBlobTxSidecar(sidecar); err != nil { + return nil, fmt.Errorf("failed to attach sidecar to signed blob tx: %w", err) + } + } - return signed, nil + return &signed, nil } diff --git a/op-service/signer/transaction_args.go b/op-service/signer/transaction_args.go index ea9fcd486231..bd7fec62adf9 100644 --- a/op-service/signer/transaction_args.go +++ b/op-service/signer/transaction_args.go @@ -1,8 +1,13 @@ package signer import ( + "bytes" + "errors" + "fmt" "math/big" + "github.com/holiman/uint256" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" @@ -10,6 +15,8 @@ import ( // TransactionArgs represents the arguments to construct a new transaction // or a message call. +// Geth has an internal version of this, but this is not exported, and only supported in v1.13.11 and forward. +// This signing API format is based on the legacy personal-account signing RPC of ethereum. type TransactionArgs struct { From *common.Address `json:"from"` To *common.Address `json:"to"` @@ -28,16 +35,20 @@ type TransactionArgs struct { AccessList *types.AccessList `json:"accessList,omitempty"` ChainID *hexutil.Big `json:"chainId,omitempty"` + + // Custom extension for EIP-4844 support + BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` + BlobFeeCap *hexutil.Big `json:"maxFeePerBlobGas,omitempty"` } -// NewTransactionArgsFromTransaction creates a TransactionArgs struct from an EIP-1559 transaction -func NewTransactionArgsFromTransaction(chainId *big.Int, from common.Address, tx *types.Transaction) *TransactionArgs { +// NewTransactionArgsFromTransaction creates a TransactionArgs struct from an EIP-1559 or EIP-4844 transaction +func NewTransactionArgsFromTransaction(chainId *big.Int, from *common.Address, tx *types.Transaction) *TransactionArgs { data := hexutil.Bytes(tx.Data()) nonce := hexutil.Uint64(tx.Nonce()) gas := hexutil.Uint64(tx.Gas()) accesses := tx.AccessList() args := &TransactionArgs{ - From: &from, + From: from, Input: &data, Nonce: &nonce, Value: (*hexutil.Big)(tx.Value()), @@ -47,6 +58,8 @@ func NewTransactionArgsFromTransaction(chainId *big.Int, from common.Address, tx MaxFeePerGas: (*hexutil.Big)(tx.GasFeeCap()), MaxPriorityFeePerGas: (*hexutil.Big)(tx.GasTipCap()), AccessList: &accesses, + BlobVersionedHashes: tx.BlobHashes(), + BlobFeeCap: (*hexutil.Big)(tx.BlobGasFeeCap()), } return args } @@ -62,23 +75,106 @@ func (args *TransactionArgs) data() []byte { return nil } -// ToTransaction converts the arguments to a transaction. -func (args *TransactionArgs) ToTransaction() *types.Transaction { +func (args *TransactionArgs) Check() error { + if args.Gas == nil { + return errors.New("gas not specified") + } + if args.GasPrice != nil { + return errors.New("only accepts maxFeePerGas/maxPriorityFeePerGas params") + } + if args.MaxFeePerGas == nil || args.MaxPriorityFeePerGas == nil { + return errors.New("missing maxFeePerGas or maxPriorityFeePerGas") + } + // Both EIP-1559 fee parameters are now set; sanity check them. + if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 { + return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas) + } + if args.Nonce == nil { + return errors.New("nonce not specified") + } + if args.Data != nil && args.Input != nil && !bytes.Equal(*args.Data, *args.Input) { + return errors.New(`both "data" and "input" are set and not equal. Please use "input" to pass transaction call data`) + } + if args.To == nil && len(args.data()) == 0 { + return errors.New("contract creation without any data provided") + } + if args.ChainID == nil { + return errors.New("chain id not specified") + } + if args.Value == nil { + args.Value = new(hexutil.Big) + } + if args.AccessList == nil { + args.AccessList = &types.AccessList{} + } + if args.BlobVersionedHashes != nil { + if len(args.BlobVersionedHashes) == 0 { + return errors.New("non-null blob versioned hashes should not be empty") + } + if args.BlobFeeCap == nil { + return errors.New("when including blobs a blob-fee-cap is required") + } + } else { + if args.BlobFeeCap != nil { + return errors.New("unexpected blob-fee-cap, transaction does not include blobs") + } + } + return nil +} + +// ToTransactionData converts the arguments to transaction content-data. Warning: this excludes blob data. +func (args *TransactionArgs) ToTransactionData() (types.TxData, error) { var data types.TxData al := types.AccessList{} if args.AccessList != nil { al = *args.AccessList } - data = &types.DynamicFeeTx{ - To: args.To, - ChainID: (*big.Int)(args.ChainID), - Nonce: uint64(*args.Nonce), - Gas: uint64(*args.Gas), - GasFeeCap: (*big.Int)(args.MaxFeePerGas), - GasTipCap: (*big.Int)(args.MaxPriorityFeePerGas), - Value: (*big.Int)(args.Value), - Data: args.data(), - AccessList: al, - } - return types.NewTx(data) + if len(args.BlobVersionedHashes) > 0 { + chainID, overflow := uint256.FromBig((*big.Int)(args.ChainID)) + if overflow { + return nil, fmt.Errorf("chainID %s too large for blob tx", args.ChainID) + } + maxFeePerGas, overflow := uint256.FromBig((*big.Int)(args.MaxFeePerGas)) + if overflow { + return nil, fmt.Errorf("maxFeePerGas %s too large for blob tx", args.MaxFeePerGas) + } + maxPriorityFeePerGas, overflow := uint256.FromBig((*big.Int)(args.MaxPriorityFeePerGas)) + if overflow { + return nil, fmt.Errorf("maxPriorityFeePerGas %s too large for blob tx", args.MaxPriorityFeePerGas) + } + value, overflow := uint256.FromBig((*big.Int)(args.Value)) + if overflow { + return nil, fmt.Errorf("value %s too large for blob tx", args.Value) + } + blobFeeCap, overflow := uint256.FromBig((*big.Int)(args.BlobFeeCap)) + if overflow { + return nil, fmt.Errorf("blobFeeCap %s too large for blob tx", args.BlobFeeCap) + } + data = &types.BlobTx{ + ChainID: chainID, + Nonce: uint64(*args.Nonce), + GasTipCap: maxPriorityFeePerGas, + GasFeeCap: maxFeePerGas, + Gas: uint64(*args.Gas), + To: *args.To, + Value: value, + Data: args.data(), + AccessList: al, + BlobFeeCap: blobFeeCap, + BlobHashes: args.BlobVersionedHashes, + } + } else { + data = &types.DynamicFeeTx{ + ChainID: (*big.Int)(args.ChainID), + Nonce: uint64(*args.Nonce), + GasTipCap: (*big.Int)(args.MaxPriorityFeePerGas), + GasFeeCap: (*big.Int)(args.MaxFeePerGas), + Gas: uint64(*args.Gas), + To: args.To, + Value: (*big.Int)(args.Value), + Data: args.data(), + AccessList: al, + } + } + return data, nil } diff --git a/op-service/sources/batching/arrays.go b/op-service/sources/batching/arrays.go index c11e5269f2cb..b946014215c1 100644 --- a/op-service/sources/batching/arrays.go +++ b/op-service/sources/batching/arrays.go @@ -4,19 +4,21 @@ import ( "context" "fmt" "math/big" + + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" ) // ReadArray uses batch calls to load all entries from an array. // countCall is used to retrieve the current array length, then getCall is used to create calls for each element // which are sent in a batch call. // The returned *CallResult slice, contains a result for each entry in the array, in the same order as in the contract. -func ReadArray(ctx context.Context, caller *MultiCaller, block Block, countCall *ContractCall, getCall func(i *big.Int) *ContractCall) ([]*CallResult, error) { +func ReadArray(ctx context.Context, caller *MultiCaller, block rpcblock.Block, countCall *ContractCall, getCall func(i *big.Int) *ContractCall) ([]*CallResult, error) { result, err := caller.SingleCall(ctx, block, countCall) if err != nil { return nil, fmt.Errorf("failed to load array length: %w", err) } count := result.GetBigInt(0).Uint64() - calls := make([]*ContractCall, count) + calls := make([]Call, count) for i := uint64(0); i < count; i++ { calls[i] = getCall(new(big.Int).SetUint64(i)) } diff --git a/op-service/sources/batching/balance_call.go b/op-service/sources/batching/balance_call.go new file mode 100644 index 000000000000..a91bca04a30b --- /dev/null +++ b/op-service/sources/batching/balance_call.go @@ -0,0 +1,40 @@ +package batching + +import ( + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rpc" +) + +type BalanceCall struct { + addr common.Address +} + +var _ Call = (*BalanceCall)(nil) + +func NewBalanceCall(addr common.Address) *BalanceCall { + return &BalanceCall{addr} +} + +func (b *BalanceCall) ToBatchElemCreator() (BatchElementCreator, error) { + return func(block rpcblock.Block) (any, rpc.BatchElem) { + out := new(hexutil.Big) + return out, rpc.BatchElem{ + Method: "eth_getBalance", + Args: []interface{}{b.addr, block.ArgValue()}, + Result: &out, + } + }, nil +} + +func (b *BalanceCall) HandleResult(result interface{}) (*CallResult, error) { + val, ok := result.(*hexutil.Big) + if !ok { + return nil, fmt.Errorf("response %v was not a *big.Int", result) + } + return &CallResult{out: []interface{}{(*big.Int)(val)}}, nil +} diff --git a/op-service/sources/batching/balance_call_test.go b/op-service/sources/batching/balance_call_test.go new file mode 100644 index 000000000000..5541360ae966 --- /dev/null +++ b/op-service/sources/batching/balance_call_test.go @@ -0,0 +1,25 @@ +package batching + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/test" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestGetBalance(t *testing.T) { + addr := common.Address{0xab, 0xcd} + expectedBalance := big.NewInt(248924) + + stub := test.NewRpcStub(t) + stub.AddExpectedCall(test.NewGetBalanceCall(addr, rpcblock.Latest, expectedBalance)) + + caller := NewMultiCaller(stub, DefaultBatchSize) + result, err := caller.SingleCall(context.Background(), rpcblock.Latest, NewBalanceCall(addr)) + require.NoError(t, err) + require.Equal(t, expectedBalance, result.GetBigInt(0)) +} diff --git a/op-service/sources/batching/bound.go b/op-service/sources/batching/bound.go index e78817219c28..a6b7e3385f8d 100644 --- a/op-service/sources/batching/bound.go +++ b/op-service/sources/batching/bound.go @@ -25,6 +25,10 @@ func NewBoundContract(abi *abi.ABI, addr common.Address) *BoundContract { } } +func (b *BoundContract) Addr() common.Address { + return b.addr +} + func (b *BoundContract) Call(method string, args ...interface{}) *ContractCall { return NewContractCall(b.abi, b.addr, method, args...) } diff --git a/op-service/sources/batching/call.go b/op-service/sources/batching/call.go index 4dbfb6160685..d84932fac6ee 100644 --- a/op-service/sources/batching/call.go +++ b/op-service/sources/batching/call.go @@ -1,85 +1,19 @@ package batching import ( - "fmt" "math/big" - "github.com/ethereum-optimism/optimism/op-service/txmgr" - "github.com/ethereum/go-ethereum" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rpc" ) -type ContractCall struct { - Abi *abi.ABI - Addr common.Address - Method string - Args []interface{} -} - -func NewContractCall(abi *abi.ABI, addr common.Address, method string, args ...interface{}) *ContractCall { - return &ContractCall{ - Abi: abi, - Addr: addr, - Method: method, - Args: args, - } -} - -func (c *ContractCall) Pack() ([]byte, error) { - return c.Abi.Pack(c.Method, c.Args...) -} - -func (c *ContractCall) ToCallArgs() (interface{}, error) { - data, err := c.Pack() - if err != nil { - return nil, fmt.Errorf("failed to pack arguments: %w", err) - } - msg := ethereum.CallMsg{ - To: &c.Addr, - Data: data, - } - return toCallArg(msg), nil -} - -func (c *ContractCall) Unpack(hex hexutil.Bytes) (*CallResult, error) { - out, err := c.Abi.Unpack(c.Method, hex) - if err != nil { - return nil, fmt.Errorf("failed to unpack data: %w", err) - } - return &CallResult{out: out}, nil -} - -func toCallArg(msg ethereum.CallMsg) interface{} { - arg := map[string]interface{}{ - "from": msg.From, - "to": msg.To, - } - if len(msg.Data) > 0 { - arg["input"] = hexutil.Bytes(msg.Data) - } - if msg.Value != nil { - arg["value"] = (*hexutil.Big)(msg.Value) - } - if msg.Gas != 0 { - arg["gas"] = hexutil.Uint64(msg.Gas) - } - if msg.GasPrice != nil { - arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice) - } - return arg -} +type BatchElementCreator func(block rpcblock.Block) (any, rpc.BatchElem) -func (c *ContractCall) ToTxCandidate() (txmgr.TxCandidate, error) { - data, err := c.Pack() - if err != nil { - return txmgr.TxCandidate{}, fmt.Errorf("failed to pack arguments: %w", err) - } - return txmgr.TxCandidate{ - TxData: data, - To: &c.Addr, - }, nil +type Call interface { + ToBatchElemCreator() (BatchElementCreator, error) + HandleResult(interface{}) (*CallResult, error) } type CallResult struct { diff --git a/op-service/sources/batching/call_test.go b/op-service/sources/batching/call_test.go index f3c6c8649e23..10b785127763 100644 --- a/op-service/sources/batching/call_test.go +++ b/op-service/sources/batching/call_test.go @@ -4,102 +4,10 @@ import ( "math/big" "testing" - "github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/require" ) -func TestContractCall_ToCallArgs(t *testing.T) { - addr := common.Address{0xbd} - testAbi, err := bindings.ERC20MetaData.GetAbi() - require.NoError(t, err) - call := NewContractCall(testAbi, addr, "approve", common.Address{0xcc}, big.NewInt(1234444)) - args, err := call.ToCallArgs() - require.NoError(t, err) - argMap, ok := args.(map[string]interface{}) - require.True(t, ok) - require.Equal(t, argMap["from"], common.Address{}) - require.Equal(t, argMap["to"], &addr) - expectedData, err := call.Pack() - require.NoError(t, err) - require.Equal(t, argMap["input"], hexutil.Bytes(expectedData)) - - require.NotContains(t, argMap, "value") - require.NotContains(t, argMap, "gas") - require.NotContains(t, argMap, "gasPrice") -} - -func TestContractCall_ToTxCandidate(t *testing.T) { - addr := common.Address{0xbd} - testAbi, err := bindings.ERC20MetaData.GetAbi() - require.NoError(t, err) - call := NewContractCall(testAbi, addr, "approve", common.Address{0xcc}, big.NewInt(1234444)) - candidate, err := call.ToTxCandidate() - require.NoError(t, err) - require.Equal(t, candidate.To, &addr) - expectedData, err := call.Pack() - require.NoError(t, err) - require.Equal(t, candidate.TxData, expectedData) - - require.Nil(t, candidate.Value) - require.Zero(t, candidate.GasLimit) -} - -func TestContractCall_Pack(t *testing.T) { - addr := common.Address{0xbd} - testAbi, err := bindings.ERC20MetaData.GetAbi() - require.NoError(t, err) - sender := common.Address{0xcc} - amount := big.NewInt(1234444) - call := NewContractCall(testAbi, addr, "approve", sender, amount) - actual, err := call.Pack() - require.NoError(t, err) - - expected, err := testAbi.Pack("approve", sender, amount) - require.NoError(t, err) - require.Equal(t, actual, expected) -} - -func TestContractCall_PackInvalid(t *testing.T) { - addr := common.Address{0xbd} - testAbi, err := bindings.ERC20MetaData.GetAbi() - require.NoError(t, err) - // Second arg should be a *big.Int so packing should fail - call := NewContractCall(testAbi, addr, "approve", common.Address{0xcc}, uint32(123)) - _, err = call.Pack() - require.Error(t, err) -} - -func TestContractCall_Unpack(t *testing.T) { - addr := common.Address{0xbd} - testAbi, err := bindings.ERC20MetaData.GetAbi() - require.NoError(t, err) - call := NewContractCall(testAbi, addr, "balanceOf", common.Address{0xcc}) - outputs := testAbi.Methods["balanceOf"].Outputs - expected := big.NewInt(1234) - packed, err := outputs.Pack(expected) - require.NoError(t, err) - - unpacked, err := call.Unpack(packed) - require.NoError(t, err) - require.Equal(t, unpacked.GetBigInt(0), expected) -} - -func TestContractCall_UnpackInvalid(t *testing.T) { - addr := common.Address{0xbd} - testAbi, err := bindings.ERC20MetaData.GetAbi() - require.NoError(t, err) - call := NewContractCall(testAbi, addr, "balanceOf", common.Address{0xcc}) - - // Input data is the wrong format and won't unpack successfully - inputPacked, err := call.Pack() - require.NoError(t, err) - - _, err = call.Unpack(inputPacked) - require.Error(t, err) -} - func TestCallResult_GetValues(t *testing.T) { tests := []struct { name string diff --git a/op-service/sources/batching/contract_call.go b/op-service/sources/batching/contract_call.go new file mode 100644 index 000000000000..87b265e84717 --- /dev/null +++ b/op-service/sources/batching/contract_call.go @@ -0,0 +1,95 @@ +package batching + +import ( + "fmt" + + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rpc" +) + +type ContractCall struct { + Abi *abi.ABI + Addr common.Address + Method string + Args []interface{} + From common.Address +} + +func NewContractCall(abi *abi.ABI, addr common.Address, method string, args ...interface{}) *ContractCall { + return &ContractCall{ + Abi: abi, + Addr: addr, + Method: method, + Args: args, + } +} + +func (c *ContractCall) Pack() ([]byte, error) { + return c.Abi.Pack(c.Method, c.Args...) +} + +func (c *ContractCall) CallMethod() string { + return "eth_call" +} + +func (c *ContractCall) ToBatchElemCreator() (BatchElementCreator, error) { + args, err := c.ToCallArgs() + if err != nil { + return nil, err + } + f := func(block rpcblock.Block) (any, rpc.BatchElem) { + out := new(hexutil.Bytes) + return out, rpc.BatchElem{ + Method: "eth_call", + Args: []interface{}{args, block.ArgValue()}, + Result: &out, + } + } + return f, nil +} + +func (c *ContractCall) ToCallArgs() (interface{}, error) { + data, err := c.Pack() + if err != nil { + return nil, fmt.Errorf("failed to pack arguments: %w", err) + } + + arg := map[string]interface{}{ + "from": c.From, + "to": &c.Addr, + "input": hexutil.Bytes(data), + } + return arg, nil +} + +func (c *ContractCall) CreateResult() interface{} { + return new(hexutil.Bytes) +} + +func (c *ContractCall) HandleResult(result interface{}) (*CallResult, error) { + out, err := c.Unpack(*result.(*hexutil.Bytes)) + return out, err +} + +func (c *ContractCall) Unpack(hex hexutil.Bytes) (*CallResult, error) { + out, err := c.Abi.Unpack(c.Method, hex) + if err != nil { + return nil, fmt.Errorf("failed to unpack data: %w", err) + } + return &CallResult{out: out}, nil +} + +func (c *ContractCall) ToTxCandidate() (txmgr.TxCandidate, error) { + data, err := c.Pack() + if err != nil { + return txmgr.TxCandidate{}, fmt.Errorf("failed to pack arguments: %w", err) + } + return txmgr.TxCandidate{ + TxData: data, + To: &c.Addr, + }, nil +} diff --git a/op-service/sources/batching/contract_call_test.go b/op-service/sources/batching/contract_call_test.go new file mode 100644 index 000000000000..854161c5cbda --- /dev/null +++ b/op-service/sources/batching/contract_call_test.go @@ -0,0 +1,102 @@ +package batching + +import ( + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-bindings/bindings" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/require" +) + +func TestContractCall_ToCallArgs(t *testing.T) { + addr := common.Address{0xbd} + testAbi, err := bindings.ERC20MetaData.GetAbi() + require.NoError(t, err) + call := NewContractCall(testAbi, addr, "approve", common.Address{0xcc}, big.NewInt(1234444)) + call.From = common.Address{0xab} + args, err := call.ToCallArgs() + require.NoError(t, err) + argMap, ok := args.(map[string]interface{}) + require.True(t, ok) + require.Equal(t, argMap["from"], call.From) + require.Equal(t, argMap["to"], &addr) + expectedData, err := call.Pack() + require.NoError(t, err) + require.Equal(t, argMap["input"], hexutil.Bytes(expectedData)) + + require.NotContains(t, argMap, "value") + require.NotContains(t, argMap, "gas") + require.NotContains(t, argMap, "gasPrice") +} + +func TestContractCall_ToTxCandidate(t *testing.T) { + addr := common.Address{0xbd} + testAbi, err := bindings.ERC20MetaData.GetAbi() + require.NoError(t, err) + call := NewContractCall(testAbi, addr, "approve", common.Address{0xcc}, big.NewInt(1234444)) + candidate, err := call.ToTxCandidate() + require.NoError(t, err) + require.Equal(t, candidate.To, &addr) + expectedData, err := call.Pack() + require.NoError(t, err) + require.Equal(t, candidate.TxData, expectedData) + + require.Nil(t, candidate.Value) + require.Zero(t, candidate.GasLimit) +} + +func TestContractCall_Pack(t *testing.T) { + addr := common.Address{0xbd} + testAbi, err := bindings.ERC20MetaData.GetAbi() + require.NoError(t, err) + sender := common.Address{0xcc} + amount := big.NewInt(1234444) + call := NewContractCall(testAbi, addr, "approve", sender, amount) + actual, err := call.Pack() + require.NoError(t, err) + + expected, err := testAbi.Pack("approve", sender, amount) + require.NoError(t, err) + require.Equal(t, actual, expected) +} + +func TestContractCall_PackInvalid(t *testing.T) { + addr := common.Address{0xbd} + testAbi, err := bindings.ERC20MetaData.GetAbi() + require.NoError(t, err) + // Second arg should be a *big.Int so packing should fail + call := NewContractCall(testAbi, addr, "approve", common.Address{0xcc}, uint32(123)) + _, err = call.Pack() + require.Error(t, err) +} + +func TestContractCall_Unpack(t *testing.T) { + addr := common.Address{0xbd} + testAbi, err := bindings.ERC20MetaData.GetAbi() + require.NoError(t, err) + call := NewContractCall(testAbi, addr, "balanceOf", common.Address{0xcc}) + outputs := testAbi.Methods["balanceOf"].Outputs + expected := big.NewInt(1234) + packed, err := outputs.Pack(expected) + require.NoError(t, err) + + unpacked, err := call.Unpack(packed) + require.NoError(t, err) + require.Equal(t, unpacked.GetBigInt(0), expected) +} + +func TestContractCall_UnpackInvalid(t *testing.T) { + addr := common.Address{0xbd} + testAbi, err := bindings.ERC20MetaData.GetAbi() + require.NoError(t, err) + call := NewContractCall(testAbi, addr, "balanceOf", common.Address{0xcc}) + + // Input data is the wrong format and won't unpack successfully + inputPacked, err := call.Pack() + require.NoError(t, err) + + _, err = call.Unpack(inputPacked) + require.Error(t, err) +} diff --git a/op-service/sources/batching/multicall.go b/op-service/sources/batching/multicall.go index 79322da1f9b7..2a02ce774f73 100644 --- a/op-service/sources/batching/multicall.go +++ b/op-service/sources/batching/multicall.go @@ -5,8 +5,7 @@ import ( "fmt" "io" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" "github.com/ethereum/go-ethereum/rpc" ) @@ -29,7 +28,11 @@ func NewMultiCaller(rpc EthRpc, batchSize int) *MultiCaller { } } -func (m *MultiCaller) SingleCall(ctx context.Context, block Block, call *ContractCall) (*CallResult, error) { +func (m *MultiCaller) BatchSize() int { + return m.batchSize +} + +func (m *MultiCaller) SingleCall(ctx context.Context, block rpcblock.Block, call Call) (*CallResult, error) { results, err := m.Call(ctx, block, call) if err != nil { return nil, err @@ -37,24 +40,19 @@ func (m *MultiCaller) SingleCall(ctx context.Context, block Block, call *Contrac return results[0], nil } -func (m *MultiCaller) Call(ctx context.Context, block Block, calls ...*ContractCall) ([]*CallResult, error) { - keys := make([]interface{}, len(calls)) +func (m *MultiCaller) Call(ctx context.Context, block rpcblock.Block, calls ...Call) ([]*CallResult, error) { + keys := make([]BatchElementCreator, len(calls)) for i := 0; i < len(calls); i++ { - args, err := calls[i].ToCallArgs() + creator, err := calls[i].ToBatchElemCreator() if err != nil { return nil, err } - keys[i] = args + keys[i] = creator } - fetcher := NewIterativeBatchCall[interface{}, *hexutil.Bytes]( + fetcher := NewIterativeBatchCall[BatchElementCreator, any]( keys, - func(args interface{}) (*hexutil.Bytes, rpc.BatchElem) { - out := new(hexutil.Bytes) - return out, rpc.BatchElem{ - Method: "eth_call", - Args: []interface{}{args, block.value}, - Result: &out, - } + func(key BatchElementCreator) (any, rpc.BatchElem) { + return key(block) }, m.rpc.BatchCallContext, m.rpc.CallContext, @@ -63,7 +61,7 @@ func (m *MultiCaller) Call(ctx context.Context, block Block, calls ...*ContractC if err := fetcher.Fetch(ctx); err == io.EOF { break } else if err != nil { - return nil, fmt.Errorf("failed to fetch claims: %w", err) + return nil, fmt.Errorf("failed to fetch batch: %w", err) } } results, err := fetcher.Result() @@ -74,7 +72,7 @@ func (m *MultiCaller) Call(ctx context.Context, block Block, calls ...*ContractC callResults := make([]*CallResult, len(results)) for i, result := range results { call := calls[i] - out, err := call.Unpack(*result) + out, err := call.HandleResult(result) if err != nil { return nil, fmt.Errorf("failed to unpack result: %w", err) } @@ -82,30 +80,3 @@ func (m *MultiCaller) Call(ctx context.Context, block Block, calls ...*ContractC } return callResults, nil } - -// Block represents the block ref value in RPC calls. -// It can be either a label (e.g. latest), a block number or block hash. -type Block struct { - value any -} - -func (b Block) ArgValue() any { - return b.value -} - -var ( - BlockPending = Block{"pending"} - BlockLatest = Block{"latest"} - BlockSafe = Block{"safe"} - BlockFinalized = Block{"finalized"} -) - -// BlockByNumber references a canonical block by number. -func BlockByNumber(blockNum uint64) Block { - return Block{rpc.BlockNumber(blockNum)} -} - -// BlockByHash references a block by hash. Canonical or non-canonical blocks may be referenced. -func BlockByHash(hash common.Hash) Block { - return Block{rpc.BlockNumberOrHashWithHash(hash, false)} -} diff --git a/op-service/sources/batching/rpcblock/blocks.go b/op-service/sources/batching/rpcblock/blocks.go new file mode 100644 index 000000000000..caf8bf94c78f --- /dev/null +++ b/op-service/sources/batching/rpcblock/blocks.go @@ -0,0 +1,33 @@ +package rpcblock + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rpc" +) + +// Block represents the block ref value in RPC calls. +// It can be either a label (e.g. latest), a block number or block hash. +type Block struct { + value any +} + +func (b Block) ArgValue() any { + return b.value +} + +var ( + Pending = Block{"pending"} + Latest = Block{"latest"} + Safe = Block{"safe"} + Finalized = Block{"finalized"} +) + +// ByNumber references a canonical block by number. +func ByNumber(blockNum uint64) Block { + return Block{rpc.BlockNumber(blockNum)} +} + +// ByHash references a block by hash. Canonical or non-canonical blocks may be referenced. +func ByHash(hash common.Hash) Block { + return Block{rpc.BlockNumberOrHashWithHash(hash, false)} +} diff --git a/op-service/sources/batching/test/abi_stub.go b/op-service/sources/batching/test/abi_stub.go new file mode 100644 index 000000000000..f4a70b907a96 --- /dev/null +++ b/op-service/sources/batching/test/abi_stub.go @@ -0,0 +1,138 @@ +package test + +import ( + "encoding/json" + "errors" + "fmt" + "testing" + + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/exp/slices" +) + +type expectedCall struct { + abiMethod abi.Method + to common.Address + block rpcblock.Block + args []interface{} + packedArgs []byte + outputs []interface{} +} + +func (c *expectedCall) Matches(rpcMethod string, args ...interface{}) error { + if rpcMethod != "eth_call" { + return fmt.Errorf("expected rpcMethod eth_call but was %v", rpcMethod) + } + if len(args) != 2 { + return fmt.Errorf("expected arg count 2 but was %v", len(args)) + } + callOpts, ok := args[0].(map[string]any) + if !ok { + return fmt.Errorf("arg 0 is not a map[string]any") + } + actualBlockRef := args[1] + to, ok := callOpts["to"].(*common.Address) + if !ok { + return errors.New("to is not an address") + } + if to == nil { + return errors.New("to is nil") + } + if *to != c.to { + return fmt.Errorf("expected to %v but was %v", c.to, *to) + } + data, ok := callOpts["input"].(hexutil.Bytes) + if !ok { + return errors.New("input is not hexutil.Bytes") + } + if len(data) < 4 { + return fmt.Errorf("expected input to have at least 4 bytes but was %v", len(data)) + } + if !slices.Equal(c.abiMethod.ID, data[:4]) { + return fmt.Errorf("expected abi method ID %x but was %x", c.abiMethod.ID, data[:4]) + } + if !slices.Equal(c.packedArgs, data[4:]) { + return fmt.Errorf("expected args %x but was %x", c.packedArgs, data[4:]) + } + if !assert.ObjectsAreEqualValues(c.block.ArgValue(), actualBlockRef) { + return fmt.Errorf("expected block ref %v but was %v", c.block.ArgValue(), actualBlockRef) + } + return nil +} + +func (c *expectedCall) Execute(t *testing.T, out interface{}) { + output, err := c.abiMethod.Outputs.Pack(c.outputs...) + require.NoErrorf(t, err, "Invalid outputs for method %v: %v", c.abiMethod.Name, c.outputs) + + // I admit I do not understand Go reflection. + // So leverage json.Unmarshal to set the out value correctly. + j, err := json.Marshal(hexutil.Bytes(output)) + require.NoError(t, err) + require.NoError(t, json.Unmarshal(j, out)) +} + +func (c *expectedCall) String() string { + return fmt.Sprintf("{to: %v, block: %v, args: %v, outputs: %v}", c.to, c.block, c.args, c.outputs) +} + +type AbiBasedRpc struct { + RpcStub + abis map[common.Address]*abi.ABI +} + +func NewAbiBasedRpc(t *testing.T, to common.Address, contractAbi *abi.ABI) *AbiBasedRpc { + abis := make(map[common.Address]*abi.ABI) + abis[to] = contractAbi + return &AbiBasedRpc{ + RpcStub: RpcStub{ + t: t, + }, + abis: abis, + } +} + +func (l *AbiBasedRpc) AddContract(to common.Address, contractAbi *abi.ABI) { + l.abis[to] = contractAbi +} + +func (l *AbiBasedRpc) abi(to common.Address) *abi.ABI { + abi, ok := l.abis[to] + require.Truef(l.t, ok, "Missing ABI for %v", to) + return abi +} + +func (l *AbiBasedRpc) SetResponse(to common.Address, method string, block rpcblock.Block, expected []interface{}, output []interface{}) { + if expected == nil { + expected = []interface{}{} + } + if output == nil { + output = []interface{}{} + } + abiMethod, ok := l.abi(to).Methods[method] + require.Truef(l.t, ok, "No method: %v", method) + packedArgs, err := abiMethod.Inputs.Pack(expected...) + require.NoErrorf(l.t, err, "Invalid expected arguments for method %v: %v", method, expected) + l.AddExpectedCall(&expectedCall{ + abiMethod: abiMethod, + to: to, + block: block, + args: expected, + packedArgs: packedArgs, + outputs: output, + }) +} + +func (l *AbiBasedRpc) VerifyTxCandidate(candidate txmgr.TxCandidate) { + require.NotNil(l.t, candidate.To) + l.findExpectedCall("eth_call", map[string]any{ + "to": candidate.To, + "input": hexutil.Bytes(candidate.TxData), + "value": candidate.Value, + }, rpcblock.Latest.ArgValue()) +} diff --git a/op-service/sources/batching/test/generic_stub.go b/op-service/sources/batching/test/generic_stub.go new file mode 100644 index 000000000000..9e78656ad48f --- /dev/null +++ b/op-service/sources/batching/test/generic_stub.go @@ -0,0 +1,104 @@ +package test + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "math/big" + "testing" + + "github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type ExpectedRpcCall interface { + fmt.Stringer + Matches(rpcMethod string, args ...interface{}) error + Execute(t *testing.T, out interface{}) +} + +type RpcStub struct { + t *testing.T + expectedCalls []ExpectedRpcCall +} + +func NewRpcStub(t *testing.T) *RpcStub { + return &RpcStub{t: t} +} + +func (r *RpcStub) ClearResponses() { + r.expectedCalls = nil +} + +func (r *RpcStub) AddExpectedCall(call ExpectedRpcCall) { + r.expectedCalls = append(r.expectedCalls, call) +} + +func (r *RpcStub) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { + var errs []error + for _, elem := range b { + elem.Error = r.CallContext(ctx, elem.Result, elem.Method, elem.Args...) + errs = append(errs, elem.Error) + } + return errors.Join(errs...) +} + +func (r *RpcStub) CallContext(_ context.Context, out interface{}, method string, args ...interface{}) error { + call := r.findExpectedCall(method, args...) + call.Execute(r.t, out) + return nil +} + +func (r *RpcStub) findExpectedCall(rpcMethod string, args ...interface{}) ExpectedRpcCall { + var matchResults string + for _, call := range r.expectedCalls { + if err := call.Matches(rpcMethod, args...); err == nil { + return call + } else { + matchResults += fmt.Sprintf("%v: %v", call, err) + } + } + require.Failf(r.t, "No matching expected calls.", matchResults) + return nil +} + +type GenericExpectedCall struct { + method string + args []interface{} + result interface{} +} + +func NewGetBalanceCall(addr common.Address, block rpcblock.Block, balance *big.Int) ExpectedRpcCall { + return &GenericExpectedCall{ + method: "eth_getBalance", + args: []interface{}{addr, block.ArgValue()}, + result: (*hexutil.Big)(balance), + } +} + +func (c *GenericExpectedCall) Matches(rpcMethod string, args ...interface{}) error { + if rpcMethod != c.method { + return fmt.Errorf("expected method %v but was %v", c.method, rpcMethod) + } + if !assert.ObjectsAreEqualValues(c.args, args) { + return fmt.Errorf("expected args %v but was %v", c.args, args) + } + return nil +} + +func (c *GenericExpectedCall) Execute(t *testing.T, out interface{}) { + // I admit I do not understand Go reflection. + // So leverage json.Unmarshal to set the out value correctly. + j, err := json.Marshal(c.result) + require.NoError(t, err) + require.NoError(t, json.Unmarshal(j, out)) +} + +func (c *GenericExpectedCall) String() string { + return fmt.Sprintf("%v(%v)->%v", c.method, c.args, c.result) +} diff --git a/op-service/sources/batching/test/stubs.go b/op-service/sources/batching/test/stubs.go deleted file mode 100644 index e24b2ec541f4..000000000000 --- a/op-service/sources/batching/test/stubs.go +++ /dev/null @@ -1,143 +0,0 @@ -package test - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "testing" - - "github.com/ethereum-optimism/optimism/op-service/sources/batching" - "github.com/ethereum-optimism/optimism/op-service/txmgr" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/rpc" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/exp/slices" -) - -type expectedCall struct { - to common.Address - block batching.Block - args []interface{} - packedArgs []byte - outputs []interface{} -} - -func (e *expectedCall) String() string { - return fmt.Sprintf("{to: %v, block: %v, args: %v, outputs: %v}", e.to, e.block, e.args, e.outputs) -} - -type AbiBasedRpc struct { - t *testing.T - abis map[common.Address]*abi.ABI - - expectedCalls map[string][]*expectedCall -} - -func NewAbiBasedRpc(t *testing.T, to common.Address, contractAbi *abi.ABI) *AbiBasedRpc { - abis := make(map[common.Address]*abi.ABI) - abis[to] = contractAbi - return &AbiBasedRpc{ - t: t, - abis: abis, - expectedCalls: make(map[string][]*expectedCall), - } -} - -func (l *AbiBasedRpc) AddContract(to common.Address, contractAbi *abi.ABI) { - l.abis[to] = contractAbi -} - -func (l *AbiBasedRpc) abi(to common.Address) *abi.ABI { - abi, ok := l.abis[to] - require.Truef(l.t, ok, "Missing ABI for %v", to) - return abi -} - -func (l *AbiBasedRpc) SetResponse(to common.Address, method string, block batching.Block, expected []interface{}, output []interface{}) { - if expected == nil { - expected = []interface{}{} - } - if output == nil { - output = []interface{}{} - } - abiMethod, ok := l.abi(to).Methods[method] - require.Truef(l.t, ok, "No method: %v", method) - packedArgs, err := abiMethod.Inputs.Pack(expected...) - require.NoErrorf(l.t, err, "Invalid expected arguments for method %v: %v", method, expected) - l.expectedCalls[method] = append(l.expectedCalls[method], &expectedCall{ - to: to, - block: block, - args: expected, - packedArgs: packedArgs, - outputs: output, - }) -} - -func (l *AbiBasedRpc) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { - var errs []error - for _, elem := range b { - elem.Error = l.CallContext(ctx, elem.Result, elem.Method, elem.Args...) - errs = append(errs, elem.Error) - } - return errors.Join(errs...) -} - -func (l *AbiBasedRpc) VerifyTxCandidate(candidate txmgr.TxCandidate) { - require.NotNil(l.t, candidate.To) - l.findExpectedCall(*candidate.To, candidate.TxData, batching.BlockLatest.ArgValue()) -} - -func (l *AbiBasedRpc) CallContext(_ context.Context, out interface{}, method string, args ...interface{}) error { - require.Equal(l.t, "eth_call", method) - require.Len(l.t, args, 2) - actualBlockRef := args[1] - callOpts, ok := args[0].(map[string]any) - require.True(l.t, ok) - to, ok := callOpts["to"].(*common.Address) - require.True(l.t, ok) - require.NotNil(l.t, to) - data, ok := callOpts["input"].(hexutil.Bytes) - require.True(l.t, ok) - - call, abiMethod := l.findExpectedCall(*to, data, actualBlockRef) - - output, err := abiMethod.Outputs.Pack(call.outputs...) - require.NoErrorf(l.t, err, "Invalid outputs for method %v: %v", abiMethod.Name, call.outputs) - - // I admit I do not understand Go reflection. - // So leverage json.Unmarshal to set the out value correctly. - j, err := json.Marshal(hexutil.Bytes(output)) - require.NoError(l.t, err) - require.NoError(l.t, json.Unmarshal(j, out)) - return nil -} - -func (l *AbiBasedRpc) findExpectedCall(to common.Address, data []byte, actualBlockRef interface{}) (*expectedCall, *abi.Method) { - - abiMethod, err := l.abi(to).MethodById(data[0:4]) - require.NoError(l.t, err) - - argData := data[4:] - args, err := abiMethod.Inputs.Unpack(argData) - require.NoError(l.t, err) - require.Len(l.t, args, len(abiMethod.Inputs)) - - expectedCalls, ok := l.expectedCalls[abiMethod.Name] - require.Truef(l.t, ok, "Unexpected call to %v", abiMethod.Name) - var call *expectedCall - for _, candidate := range expectedCalls { - if to == candidate.to && - slices.Equal(candidate.packedArgs, argData) && - assert.ObjectsAreEqualValues(candidate.block.ArgValue(), actualBlockRef) { - call = candidate - break - } - } - require.NotNilf(l.t, call, "No expected calls to %v at block %v with to: %v, arguments: %v\nExpected calls: %v", - to, abiMethod.Name, actualBlockRef, args, expectedCalls) - return call, abiMethod -} diff --git a/op-service/sources/engine_client.go b/op-service/sources/engine_client.go index e80280a317b8..183356f03c53 100644 --- a/op-service/sources/engine_client.go +++ b/op-service/sources/engine_client.go @@ -31,6 +31,7 @@ func EngineClientDefaultConfig(config *rollup.Config) *EngineClientConfig { // EngineClient extends L2Client with engine API bindings. type EngineClient struct { *L2Client + *EngineAPIClient } func NewEngineClient(client client.RPC, log log.Logger, metrics caching.Metrics, config *EngineClientConfig) (*EngineClient, error) { @@ -39,11 +40,39 @@ func NewEngineClient(client client.RPC, log log.Logger, metrics caching.Metrics, return nil, err } + engineAPIClient := NewEngineAPIClient(client, log, config.RollupCfg) + return &EngineClient{ - L2Client: l2Client, + L2Client: l2Client, + EngineAPIClient: engineAPIClient, }, nil } +// EngineAPIClient is an RPC client for the Engine API functions. +type EngineAPIClient struct { + RPC client.RPC + log log.Logger + evp EngineVersionProvider +} + +type EngineVersionProvider interface { + ForkchoiceUpdatedVersion(attr *eth.PayloadAttributes) eth.EngineAPIMethod + NewPayloadVersion(timestamp uint64) eth.EngineAPIMethod + GetPayloadVersion(timestamp uint64) eth.EngineAPIMethod +} + +func NewEngineAPIClient(rpc client.RPC, l log.Logger, evp EngineVersionProvider) *EngineAPIClient { + return &EngineAPIClient{ + RPC: rpc, + log: l, + evp: evp, + } +} + +// EngineVersionProvider returns the underlying engine version provider used for +// resolving the correct Engine API versions. +func (s *EngineAPIClient) EngineVersionProvider() EngineVersionProvider { return s.evp } + // ForkchoiceUpdate updates the forkchoice on the execution client. If attributes is not nil, the engine client will also begin building a block // based on attributes after the new head block and return the payload ID. // @@ -51,14 +80,15 @@ func NewEngineClient(client client.RPC, log log.Logger, metrics caching.Metrics, // 1. Processing error: ForkchoiceUpdatedResult.PayloadStatusV1.ValidationError or other non-success PayloadStatusV1, // 2. `error` as eth.InputError: the forkchoice state or attributes are not valid. // 3. Other types of `error`: temporary RPC errors, like timeouts. -func (s *EngineClient) ForkchoiceUpdate(ctx context.Context, fc *eth.ForkchoiceState, attributes *eth.PayloadAttributes) (*eth.ForkchoiceUpdatedResult, error) { +func (s *EngineAPIClient) ForkchoiceUpdate(ctx context.Context, fc *eth.ForkchoiceState, attributes *eth.PayloadAttributes) (*eth.ForkchoiceUpdatedResult, error) { llog := s.log.New("state", fc) // local logger tlog := llog.New("attr", attributes) // trace logger tlog.Trace("Sharing forkchoice-updated signal") fcCtx, cancel := context.WithTimeout(ctx, time.Second*5) defer cancel() var result eth.ForkchoiceUpdatedResult - err := s.client.CallContext(fcCtx, &result, "engine_forkchoiceUpdatedV3", fc, attributes) + method := s.evp.ForkchoiceUpdatedVersion(attributes) + err := s.RPC.CallContext(fcCtx, &result, string(method), fc, attributes) if err == nil { tlog.Trace("Shared forkchoice-updated signal") if attributes != nil { // block building is optional, we only get a payload ID if we are building a block @@ -86,7 +116,7 @@ func (s *EngineClient) ForkchoiceUpdate(ctx context.Context, fc *eth.ForkchoiceS // NewPayload executes a full block on the execution engine. // This returns a PayloadStatusV1 which encodes any validation/processing error, // and this type of error is kept separate from the returned `error` used for RPC errors, like timeouts. -func (s *EngineClient) NewPayload(ctx context.Context, payload *eth.ExecutionPayload, parentBeaconBlockRoot *common.Hash) (*eth.PayloadStatusV1, error) { +func (s *EngineAPIClient) NewPayload(ctx context.Context, payload *eth.ExecutionPayload, parentBeaconBlockRoot *common.Hash) (*eth.PayloadStatusV1, error) { e := s.log.New("block_hash", payload.BlockHash) e.Trace("sending payload for execution") @@ -95,10 +125,13 @@ func (s *EngineClient) NewPayload(ctx context.Context, payload *eth.ExecutionPay var result eth.PayloadStatusV1 var err error - if s.rollupCfg.IsEcotone(uint64(payload.Timestamp)) { - err = s.client.CallContext(execCtx, &result, "engine_newPayloadV3", payload, []common.Hash{}, parentBeaconBlockRoot) - } else { - err = s.client.CallContext(execCtx, &result, "engine_newPayloadV2", payload) + switch method := s.evp.NewPayloadVersion(uint64(payload.Timestamp)); method { + case eth.NewPayloadV3: + err = s.RPC.CallContext(execCtx, &result, string(method), payload, []common.Hash{}, parentBeaconBlockRoot) + case eth.NewPayloadV2: + err = s.RPC.CallContext(execCtx, &result, string(method), payload) + default: + return nil, fmt.Errorf("unsupported NewPayload version: %s", method) } e.Trace("Received payload execution result", "status", result.Status, "latestValidHash", result.LatestValidHash, "message", result.ValidationError) @@ -113,13 +146,14 @@ func (s *EngineClient) NewPayload(ctx context.Context, payload *eth.ExecutionPay // There may be two types of error: // 1. `error` as eth.InputError: the payload ID may be unknown // 2. Other types of `error`: temporary RPC errors, like timeouts. -func (s *EngineClient) GetPayload(ctx context.Context, payloadId eth.PayloadID) (*eth.ExecutionPayloadEnvelope, error) { - e := s.log.New("payload_id", payloadId) +func (s *EngineAPIClient) GetPayload(ctx context.Context, payloadInfo eth.PayloadInfo) (*eth.ExecutionPayloadEnvelope, error) { + e := s.log.New("payload_id", payloadInfo.ID) e.Trace("getting payload") var result eth.ExecutionPayloadEnvelope - err := s.client.CallContext(ctx, &result, "engine_getPayloadV3", payloadId) + method := s.evp.GetPayloadVersion(payloadInfo.Timestamp) + err := s.RPC.CallContext(ctx, &result, string(method), payloadInfo.ID) if err != nil { - e.Warn("Failed to get payload", "payload_id", payloadId, "err", err) + e.Warn("Failed to get payload", "payload_id", payloadInfo.ID, "err", err) if rpcErr, ok := err.(rpc.Error); ok { code := eth.ErrorCode(rpcErr.ErrorCode()) switch code { @@ -138,9 +172,9 @@ func (s *EngineClient) GetPayload(ctx context.Context, payloadId eth.PayloadID) return &result, nil } -func (s *EngineClient) SignalSuperchainV1(ctx context.Context, recommended, required params.ProtocolVersion) (params.ProtocolVersion, error) { +func (s *EngineAPIClient) SignalSuperchainV1(ctx context.Context, recommended, required params.ProtocolVersion) (params.ProtocolVersion, error) { var result params.ProtocolVersion - err := s.client.CallContext(ctx, &result, "engine_signalSuperchainV1", &catalyst.SuperchainSignal{ + err := s.RPC.CallContext(ctx, &result, "engine_signalSuperchainV1", &catalyst.SuperchainSignal{ Recommended: recommended, Required: required, }) diff --git a/op-service/sources/eth_client.go b/op-service/sources/eth_client.go index 254fa6c5416a..8f73b13b6110 100644 --- a/op-service/sources/eth_client.go +++ b/op-service/sources/eth_client.go @@ -187,7 +187,7 @@ func (n numberID) CheckID(id eth.BlockID) error { } func (s *EthClient) headerCall(ctx context.Context, method string, id rpcBlockID) (eth.BlockInfo, error) { - var header *rpcHeader + var header *RPCHeader err := s.client.CallContext(ctx, &header, method, id.Arg(), false) // headers are just blocks without txs if err != nil { return nil, err @@ -207,7 +207,7 @@ func (s *EthClient) headerCall(ctx context.Context, method string, id rpcBlockID } func (s *EthClient) blockCall(ctx context.Context, method string, id rpcBlockID) (eth.BlockInfo, types.Transactions, error) { - var block *rpcBlock + var block *RPCBlock err := s.client.CallContext(ctx, &block, method, id.Arg(), true) if err != nil { return nil, nil, err @@ -228,7 +228,7 @@ func (s *EthClient) blockCall(ctx context.Context, method string, id rpcBlockID) } func (s *EthClient) payloadCall(ctx context.Context, method string, id rpcBlockID) (*eth.ExecutionPayloadEnvelope, error) { - var block *rpcBlock + var block *RPCBlock err := s.client.CallContext(ctx, &block, method, id.Arg(), true) if err != nil { return nil, err @@ -317,16 +317,11 @@ func (s *EthClient) FetchReceipts(ctx context.Context, blockHash common.Hash) (e return nil, nil, fmt.Errorf("querying block: %w", err) } - txHashes, block := eth.TransactionsToHashes(txs), eth.ToBlockID(info) - receipts, err := s.recProvider.FetchReceipts(ctx, block, txHashes) + txHashes, _ := eth.TransactionsToHashes(txs), eth.ToBlockID(info) + receipts, err := s.recProvider.FetchReceipts(ctx, info, txHashes) if err != nil { return nil, nil, err } - - if err := validateReceipts(block, info.ReceiptHash(), txHashes, receipts); err != nil { - return info, nil, fmt.Errorf("invalid receipts: %w", err) - } - return info, receipts, nil } diff --git a/op-service/sources/eth_client_test.go b/op-service/sources/eth_client_test.go index 6bc554660447..fe2d9839f009 100644 --- a/op-service/sources/eth_client_test.go +++ b/op-service/sources/eth_client_test.go @@ -62,7 +62,7 @@ func randHash() (out common.Hash) { return out } -func randHeader() (*types.Header, *rpcHeader) { +func randHeader() (*types.Header, *RPCHeader) { hdr := &types.Header{ ParentHash: randHash(), UncleHash: randHash(), @@ -81,7 +81,7 @@ func randHeader() (*types.Header, *rpcHeader) { Nonce: types.BlockNonce{}, BaseFee: big.NewInt(100), } - rhdr := &rpcHeader{ + rhdr := &RPCHeader{ ParentHash: hdr.ParentHash, UncleHash: hdr.UncleHash, Coinbase: hdr.Coinbase, @@ -108,9 +108,9 @@ func TestEthClient_InfoByHash(t *testing.T) { _, rhdr := randHeader() expectedInfo, _ := rhdr.Info(true, false) ctx := context.Background() - m.On("CallContext", ctx, new(*rpcHeader), + m.On("CallContext", ctx, new(*RPCHeader), "eth_getBlockByHash", []any{rhdr.Hash, false}).Run(func(args mock.Arguments) { - *args[1].(**rpcHeader) = rhdr + *args[1].(**RPCHeader) = rhdr }).Return([]error{nil}) s, err := NewEthClient(m, nil, nil, testEthClientConfig) require.NoError(t, err) @@ -131,9 +131,9 @@ func TestEthClient_InfoByNumber(t *testing.T) { expectedInfo, _ := rhdr.Info(true, false) n := rhdr.Number ctx := context.Background() - m.On("CallContext", ctx, new(*rpcHeader), + m.On("CallContext", ctx, new(*RPCHeader), "eth_getBlockByNumber", []any{n.String(), false}).Run(func(args mock.Arguments) { - *args[1].(**rpcHeader) = rhdr + *args[1].(**RPCHeader) = rhdr }).Return([]error{nil}) s, err := NewL1Client(m, nil, nil, L1ClientDefaultConfig(&rollup.Config{SeqWindowSize: 10}, true, RPCKindStandard)) require.NoError(t, err) @@ -150,9 +150,9 @@ func TestEthClient_WrongInfoByNumber(t *testing.T) { rhdr2.Number += 1 n := rhdr.Number ctx := context.Background() - m.On("CallContext", ctx, new(*rpcHeader), + m.On("CallContext", ctx, new(*RPCHeader), "eth_getBlockByNumber", []any{n.String(), false}).Run(func(args mock.Arguments) { - *args[1].(**rpcHeader) = &rhdr2 + *args[1].(**RPCHeader) = &rhdr2 }).Return([]error{nil}) s, err := NewL1Client(m, nil, nil, L1ClientDefaultConfig(&rollup.Config{SeqWindowSize: 10}, true, RPCKindStandard)) require.NoError(t, err) @@ -169,9 +169,9 @@ func TestEthClient_WrongInfoByHash(t *testing.T) { rhdr2.Hash = rhdr2.computeBlockHash() k := rhdr.Hash ctx := context.Background() - m.On("CallContext", ctx, new(*rpcHeader), + m.On("CallContext", ctx, new(*RPCHeader), "eth_getBlockByHash", []any{k, false}).Run(func(args mock.Arguments) { - *args[1].(**rpcHeader) = &rhdr2 + *args[1].(**RPCHeader) = &rhdr2 }).Return([]error{nil}) s, err := NewL1Client(m, nil, nil, L1ClientDefaultConfig(&rollup.Config{SeqWindowSize: 10}, true, RPCKindStandard)) require.NoError(t, err) @@ -180,95 +180,49 @@ func TestEthClient_WrongInfoByHash(t *testing.T) { m.Mock.AssertExpectations(t) } -type validateReceiptsTest struct { - desc string - trustRPC bool - mutReceipts func(types.Receipts) types.Receipts - expError string -} - -func TestEthClient_validateReceipts(t *testing.T) { - mutBloom := func(rs types.Receipts) types.Receipts { - rs[2].Bloom[0] = 1 - return rs - } - mutTruncate := func(rs types.Receipts) types.Receipts { - return rs[:len(rs)-1] - } - - for _, tt := range []validateReceiptsTest{ - { - desc: "valid", - }, - { - desc: "invalid-mut-bloom", - mutReceipts: mutBloom, - expError: "invalid receipts: failed to fetch list of receipts: expected receipt root", - }, - { - desc: "invalid-truncated", - mutReceipts: mutTruncate, - expError: "invalid receipts: got 3 receipts but expected 4", - }, - } { - t.Run("no-trust-"+tt.desc, func(t *testing.T) { - testEthClient_validateReceipts(t, tt) - }) - // trusting the rpc should still lead to failed validation - tt.trustRPC = true - t.Run("trust-"+tt.desc, func(t *testing.T) { - testEthClient_validateReceipts(t, tt) - }) +func newEthClientWithCaches(metrics caching.Metrics, cacheSize int) *EthClient { + return &EthClient{ + transactionsCache: caching.NewLRUCache[common.Hash, types.Transactions](metrics, "txs", cacheSize), + headersCache: caching.NewLRUCache[common.Hash, eth.BlockInfo](metrics, "headers", cacheSize), + payloadsCache: caching.NewLRUCache[common.Hash, *eth.ExecutionPayloadEnvelope](metrics, "payloads", cacheSize), } } -func testEthClient_validateReceipts(t *testing.T, test validateReceiptsTest) { +// TestReceiptValidation tests that the receipt validation is performed by the underlying RPCReceiptsFetcher +func TestReceiptValidation(t *testing.T) { require := require.New(t) mrpc := new(mockRPC) - mrp := new(mockReceiptsProvider) - const numTxs = 4 - block, receipts := randomRpcBlockAndReceipts(rand.New(rand.NewSource(420)), numTxs) - txHashes := receiptTxHashes(receipts) + rp := NewRPCReceiptsFetcher(mrpc, nil, RPCReceiptsConfig{}) + const numTxs = 1 + block, _ := randomRpcBlockAndReceipts(rand.New(rand.NewSource(420)), numTxs) + //txHashes := receiptTxHashes(receipts) ctx := context.Background() - if mut := test.mutReceipts; mut != nil { - receipts = mut(receipts) - } - - mrpc.On("CallContext", ctx, mock.AnythingOfType("**sources.rpcBlock"), - "eth_getBlockByHash", []any{block.Hash, true}). + mrpc.On("CallContext", + ctx, + mock.Anything, + "eth_getTransactionReceipt", + mock.Anything). Run(func(args mock.Arguments) { - *(args[1].(**rpcBlock)) = block }). - Return([]error{nil}).Once() - - mrp.On("FetchReceipts", ctx, block.BlockID(), txHashes). - Return(types.Receipts(receipts), error(nil)).Once() + Return([]error{nil}) + + // when the block is requested, the block is returned + mrpc.On("CallContext", + ctx, + mock.Anything, + "eth_getBlockByHash", + mock.Anything). + Run(func(args mock.Arguments) { + *(args[1].(**RPCBlock)) = block + }). + Return([]error{nil}) ethcl := newEthClientWithCaches(nil, numTxs) ethcl.client = mrpc - ethcl.recProvider = mrp - ethcl.trustRPC = test.trustRPC - - info, recs, err := ethcl.FetchReceipts(ctx, block.Hash) - if test.expError != "" { - require.ErrorContains(err, test.expError) - } else { - require.NoError(err) - expInfo, _, err := block.Info(true, false) - require.NoError(err) - require.Equal(expInfo, info) - require.Equal(types.Receipts(receipts), recs) - } - - mrpc.AssertExpectations(t) - mrp.AssertExpectations(t) -} + ethcl.recProvider = rp + ethcl.trustRPC = true -func newEthClientWithCaches(metrics caching.Metrics, cacheSize int) *EthClient { - return &EthClient{ - transactionsCache: caching.NewLRUCache[common.Hash, types.Transactions](metrics, "txs", cacheSize), - headersCache: caching.NewLRUCache[common.Hash, eth.BlockInfo](metrics, "headers", cacheSize), - payloadsCache: caching.NewLRUCache[common.Hash, *eth.ExecutionPayloadEnvelope](metrics, "payloads", cacheSize), - } + _, _, err := ethcl.FetchReceipts(ctx, block.Hash) + require.ErrorContains(err, "unexpected nil block number") } diff --git a/op-service/sources/l1_beacon_client.go b/op-service/sources/l1_beacon_client.go index 1ad7537583d6..7a6aea703a13 100644 --- a/op-service/sources/l1_beacon_client.go +++ b/op-service/sources/l1_beacon_client.go @@ -3,12 +3,12 @@ package sources import ( "context" "encoding/json" + "errors" "fmt" "io" "net/http" "net/url" "path" - "slices" "strconv" "sync" @@ -20,29 +20,57 @@ import ( const ( versionMethod = "eth/v1/node/version" - genesisMethod = "eth/v1/beacon/genesis" specMethod = "eth/v1/config/spec" + genesisMethod = "eth/v1/beacon/genesis" sidecarsMethodPrefix = "eth/v1/beacon/blob_sidecars/" ) +type L1BeaconClientConfig struct { + FetchAllSidecars bool +} + +// L1BeaconClient is a high level golang client for the Beacon API. type L1BeaconClient struct { - cl client.HTTP + cl BeaconClient + pool *ClientPool[BlobSideCarsFetcher] + cfg L1BeaconClientConfig initLock sync.Mutex timeToSlotFn TimeToSlotFn } -// NewL1BeaconClient returns a client for making requests to an L1 consensus layer node. -func NewL1BeaconClient(cl client.HTTP) *L1BeaconClient { - return &L1BeaconClient{cl: cl} +// BeaconClient is a thin wrapper over the Beacon APIs. +// +//go:generate mockery --name BeaconClient --with-expecter=true +type BeaconClient interface { + NodeVersion(ctx context.Context) (string, error) + ConfigSpec(ctx context.Context) (eth.APIConfigResponse, error) + BeaconGenesis(ctx context.Context) (eth.APIGenesisResponse, error) + BeaconBlobSideCars(ctx context.Context, fetchAllSidecars bool, slot uint64, hashes []eth.IndexedBlobHash) (eth.APIGetBlobSidecarsResponse, error) +} + +// BlobSideCarsFetcher is a thin wrapper over the Beacon APIs. +// +//go:generate mockery --name BlobSideCarsFetcher --with-expecter=true +type BlobSideCarsFetcher interface { + BeaconBlobSideCars(ctx context.Context, fetchAllSidecars bool, slot uint64, hashes []eth.IndexedBlobHash) (eth.APIGetBlobSidecarsResponse, error) +} + +// BeaconHTTPClient implements BeaconClient. It provides golang types over the basic Beacon API. +type BeaconHTTPClient struct { + cl client.HTTP +} + +func NewBeaconHTTPClient(cl client.HTTP) *BeaconHTTPClient { + return &BeaconHTTPClient{cl} } -func (cl *L1BeaconClient) apiReq(ctx context.Context, dest any, reqPath string, reqQuery url.Values) error { +func (cl *BeaconHTTPClient) apiReq(ctx context.Context, dest any, reqPath string, reqQuery url.Values) error { headers := http.Header{} headers.Add("Accept", "application/json") resp, err := cl.cl.Get(ctx, reqPath, reqQuery, headers) if err != nil { - return fmt.Errorf("%w: http Get failed", err) + return fmt.Errorf("http Get failed: %w", err) } if resp.StatusCode != http.StatusOK { errMsg, _ := io.ReadAll(resp.Body) @@ -54,11 +82,89 @@ func (cl *L1BeaconClient) apiReq(ctx context.Context, dest any, reqPath string, return err } if err := resp.Body.Close(); err != nil { - return fmt.Errorf("%w: failed to close response body", err) + return fmt.Errorf("failed to close response body: %w", err) } return nil } +func (cl *BeaconHTTPClient) NodeVersion(ctx context.Context) (string, error) { + var resp eth.APIVersionResponse + if err := cl.apiReq(ctx, &resp, versionMethod, nil); err != nil { + return "", err + } + return resp.Data.Version, nil +} + +func (cl *BeaconHTTPClient) ConfigSpec(ctx context.Context) (eth.APIConfigResponse, error) { + var configResp eth.APIConfigResponse + if err := cl.apiReq(ctx, &configResp, specMethod, nil); err != nil { + return eth.APIConfigResponse{}, err + } + return configResp, nil +} + +func (cl *BeaconHTTPClient) BeaconGenesis(ctx context.Context) (eth.APIGenesisResponse, error) { + var genesisResp eth.APIGenesisResponse + if err := cl.apiReq(ctx, &genesisResp, genesisMethod, nil); err != nil { + return eth.APIGenesisResponse{}, err + } + return genesisResp, nil +} + +func (cl *BeaconHTTPClient) BeaconBlobSideCars(ctx context.Context, fetchAllSidecars bool, slot uint64, hashes []eth.IndexedBlobHash) (eth.APIGetBlobSidecarsResponse, error) { + reqPath := path.Join(sidecarsMethodPrefix, strconv.FormatUint(slot, 10)) + var reqQuery url.Values + if !fetchAllSidecars { + reqQuery = url.Values{} + for i := range hashes { + reqQuery.Add("indices", strconv.FormatUint(hashes[i].Index, 10)) + } + } + var resp eth.APIGetBlobSidecarsResponse + if err := cl.apiReq(ctx, &resp, reqPath, reqQuery); err != nil { + return eth.APIGetBlobSidecarsResponse{}, err + } + return resp, nil +} + +type ClientPool[T any] struct { + clients []T + index int +} + +func NewClientPool[T any](clients ...T) *ClientPool[T] { + return &ClientPool[T]{ + clients: clients, + index: 0, + } +} + +func (p *ClientPool[T]) Len() int { + return len(p.clients) +} + +func (p *ClientPool[T]) Get() T { + return p.clients[p.index] +} + +func (p *ClientPool[T]) MoveToNext() { + p.index += 1 + if p.index == len(p.clients) { + p.index = 0 + } +} + +// NewL1BeaconClient returns a client for making requests to an L1 consensus layer node. +// Fallbacks are optional clients that will be used for fetching blobs. L1BeaconClient will rotate between +// the `cl` and the fallbacks whenever a client runs into an error while fetching blobs. +func NewL1BeaconClient(cl BeaconClient, cfg L1BeaconClientConfig, fallbacks ...BlobSideCarsFetcher) *L1BeaconClient { + cs := append([]BlobSideCarsFetcher{cl}, fallbacks...) + return &L1BeaconClient{ + cl: cl, + pool: NewClientPool[BlobSideCarsFetcher](cs...), + cfg: cfg} +} + type TimeToSlotFn func(timestamp uint64) (uint64, error) // GetTimeToSlotFn returns a function that converts a timestamp to a slot number. @@ -69,20 +175,20 @@ func (cl *L1BeaconClient) GetTimeToSlotFn(ctx context.Context) (TimeToSlotFn, er return cl.timeToSlotFn, nil } - var genesisResp eth.APIGenesisResponse - if err := cl.apiReq(ctx, &genesisResp, genesisMethod, nil); err != nil { + genesis, err := cl.cl.BeaconGenesis(ctx) + if err != nil { return nil, err } - var configResp eth.APIConfigResponse - if err := cl.apiReq(ctx, &configResp, specMethod, nil); err != nil { + config, err := cl.cl.ConfigSpec(ctx) + if err != nil { return nil, err } - genesisTime := uint64(genesisResp.Data.GenesisTime) - secondsPerSlot := uint64(configResp.Data.SecondsPerSlot) + genesisTime := uint64(genesis.Data.GenesisTime) + secondsPerSlot := uint64(config.Data.SecondsPerSlot) if secondsPerSlot == 0 { - return nil, fmt.Errorf("got bad value for seconds per slot: %v", configResp.Data.SecondsPerSlot) + return nil, fmt.Errorf("got bad value for seconds per slot: %v", config.Data.SecondsPerSlot) } cl.timeToSlotFn = func(timestamp uint64) (uint64, error) { if timestamp < genesisTime { @@ -93,37 +199,60 @@ func (cl *L1BeaconClient) GetTimeToSlotFn(ctx context.Context) (TimeToSlotFn, er return cl.timeToSlotFn, nil } -// GetBlobSidecars fetches blob sidecars that were confirmed in the specified L1 block with the -// given indexed hashes. Order of the returned sidecars is not guaranteed, and blob data is not -// checked for validity. +func (cl *L1BeaconClient) fetchSidecars(ctx context.Context, slot uint64, hashes []eth.IndexedBlobHash) (eth.APIGetBlobSidecarsResponse, error) { + var errs []error + for i := 0; i < cl.pool.Len(); i++ { + f := cl.pool.Get() + resp, err := f.BeaconBlobSideCars(ctx, cl.cfg.FetchAllSidecars, slot, hashes) + if err != nil { + cl.pool.MoveToNext() + errs = append(errs, err) + } else { + return resp, nil + } + } + return eth.APIGetBlobSidecarsResponse{}, errors.Join(errs...) +} + +// GetBlobSidecars fetches blob sidecars that were confirmed in the specified +// L1 block with the given indexed hashes. +// Order of the returned sidecars is guaranteed to be that of the hashes. +// Blob data is not checked for validity. func (cl *L1BeaconClient) GetBlobSidecars(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.BlobSidecar, error) { if len(hashes) == 0 { return []*eth.BlobSidecar{}, nil } slotFn, err := cl.GetTimeToSlotFn(ctx) if err != nil { - return nil, fmt.Errorf("%w: failed to get time to slot function", err) + return nil, fmt.Errorf("failed to get time to slot function: %w", err) } slot, err := slotFn(ref.Time) if err != nil { - return nil, fmt.Errorf("%w: error in converting ref.Time to slot", err) + return nil, fmt.Errorf("error in converting ref.Time to slot: %w", err) } - reqPath := path.Join(sidecarsMethodPrefix, strconv.FormatUint(slot, 10)) - reqQuery := url.Values{} - for i := range hashes { - reqQuery.Add("indices", strconv.FormatUint(hashes[i].Index, 10)) + resp, err := cl.fetchSidecars(ctx, slot, hashes) + if err != nil { + return nil, fmt.Errorf("failed to fetch blob sidecars for slot %v block %v: %w", slot, ref, err) } - var resp eth.APIGetBlobSidecarsResponse - if err := cl.apiReq(ctx, &resp, reqPath, reqQuery); err != nil { - return nil, fmt.Errorf("%w: failed to fetch blob sidecars for slot %v block %v", err, slot, ref) + + apiscs := make([]*eth.APIBlobSidecar, 0, len(hashes)) + // filter and order by hashes + for _, h := range hashes { + for _, apisc := range resp.Data { + if h.Index == uint64(apisc.Index) { + apiscs = append(apiscs, apisc) + break + } + } } - if len(hashes) != len(resp.Data) { - return nil, fmt.Errorf("expected %v sidecars but got %v", len(hashes), len(resp.Data)) + + if len(hashes) != len(apiscs) { + return nil, fmt.Errorf("expected %v sidecars but got %v", len(hashes), len(apiscs)) } bscs := make([]*eth.BlobSidecar, 0, len(hashes)) - for _, apisc := range resp.Data { + for _, apisc := range apiscs { bscs = append(bscs, apisc.BlobSidecar()) } @@ -137,24 +266,22 @@ func (cl *L1BeaconClient) GetBlobSidecars(ctx context.Context, ref eth.L1BlockRe func (cl *L1BeaconClient) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) { blobSidecars, err := cl.GetBlobSidecars(ctx, ref, hashes) if err != nil { - return nil, fmt.Errorf("%w: failed to get blob sidecars for L1BlockRef %s", err, ref) + return nil, fmt.Errorf("failed to get blob sidecars for L1BlockRef %s: %w", ref, err) } return blobsFromSidecars(blobSidecars, hashes) } func blobsFromSidecars(blobSidecars []*eth.BlobSidecar, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) { + if len(blobSidecars) != len(hashes) { + return nil, fmt.Errorf("number of hashes and blobSidecars mismatch, %d != %d", len(hashes), len(blobSidecars)) + } + out := make([]*eth.Blob, len(hashes)) for i, ih := range hashes { - // The beacon node api makes no guarantees on order of the returned blob sidecars, so - // search for the sidecar that matches the current indexed hash to ensure blobs are - // returned in the same order. - scIndex := slices.IndexFunc( - blobSidecars, - func(sc *eth.BlobSidecar) bool { return uint64(sc.Index) == ih.Index }) - if scIndex == -1 { - return nil, fmt.Errorf("no blob in response matches desired index: %v", ih.Index) + sidecar := blobSidecars[i] + if sidx := uint64(sidecar.Index); sidx != ih.Index { + return nil, fmt.Errorf("expected sidecars to be ordered by hashes, but got %d != %d", sidx, ih.Index) } - sidecar := blobSidecars[scIndex] // make sure the blob's kzg commitment hashes to the expected value hash := eth.KZGToVersionedHash(kzg4844.Commitment(sidecar.KZGCommitment)) @@ -164,7 +291,7 @@ func blobsFromSidecars(blobSidecars []*eth.BlobSidecar, hashes []eth.IndexedBlob // confirm blob data is valid by verifying its proof against the commitment if err := eth.VerifyBlobProof(&sidecar.Blob, kzg4844.Commitment(sidecar.KZGCommitment), kzg4844.Proof(sidecar.KZGProof)); err != nil { - return nil, fmt.Errorf("%w: blob at index %d failed verification", err, i) + return nil, fmt.Errorf("blob at index %d failed verification: %w", i, err) } out[i] = &sidecar.Blob } @@ -173,9 +300,5 @@ func blobsFromSidecars(blobSidecars []*eth.BlobSidecar, hashes []eth.IndexedBlob // GetVersion fetches the version of the Beacon-node. func (cl *L1BeaconClient) GetVersion(ctx context.Context) (string, error) { - var resp eth.APIVersionResponse - if err := cl.apiReq(ctx, &resp, versionMethod, nil); err != nil { - return "", err - } - return resp.Data.Version, nil + return cl.cl.NodeVersion(ctx) } diff --git a/op-service/sources/l1_beacon_client_test.go b/op-service/sources/l1_beacon_client_test.go index bbb9c17420e7..defee7d8cbf3 100644 --- a/op-service/sources/l1_beacon_client_test.go +++ b/op-service/sources/l1_beacon_client_test.go @@ -1,9 +1,12 @@ package sources import ( + "context" + "errors" "testing" "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/sources/mocks" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/stretchr/testify/require" ) @@ -41,9 +44,18 @@ func TestBlobsFromSidecars(t *testing.T) { hashes := []eth.IndexedBlobHash{index0, index1, index2} - // put the sidecars in scrambled order of expectation to confirm function appropriately - // reorders the output to match that of the blob hashes + // put the sidecars in scrambled order to confirm error sidecars := []*eth.BlobSidecar{sidecar2, sidecar0, sidecar1} + _, err := blobsFromSidecars(sidecars, hashes) + require.Error(t, err) + + // too few sidecars should error + sidecars = []*eth.BlobSidecar{sidecar0, sidecar1} + _, err = blobsFromSidecars(sidecars, hashes) + require.Error(t, err) + + // correct order should work + sidecars = []*eth.BlobSidecar{sidecar0, sidecar1, sidecar2} blobs, err := blobsFromSidecars(sidecars, hashes) require.NoError(t, err) // confirm order by checking first blob byte against expected index @@ -79,3 +91,100 @@ func TestBlobsFromSidecars_EmptySidecarList(t *testing.T) { require.NoError(t, err) require.Empty(t, blobs, "blobs should be empty when no sidecars are provided") } + +func toAPISideCars(sidecars []*eth.BlobSidecar) []*eth.APIBlobSidecar { + var out []*eth.APIBlobSidecar + for _, s := range sidecars { + out = append(out, ð.APIBlobSidecar{ + Index: s.Index, + Blob: s.Blob, + KZGCommitment: s.KZGCommitment, + KZGProof: s.KZGProof, + SignedBlockHeader: eth.SignedBeaconBlockHeader{}, + }) + } + return out +} + +func TestBeaconClientNoErrorPrimary(t *testing.T) { + indices := []uint64{5, 7, 2} + index0, sidecar0 := makeTestBlobSidecar(indices[0]) + index1, sidecar1 := makeTestBlobSidecar(indices[1]) + index2, sidecar2 := makeTestBlobSidecar(indices[2]) + + hashes := []eth.IndexedBlobHash{index0, index1, index2} + sidecars := []*eth.BlobSidecar{sidecar0, sidecar1, sidecar2} + apiSidecars := toAPISideCars(sidecars) + + ctx := context.Background() + p := mocks.NewBeaconClient(t) + f := mocks.NewBlobSideCarsFetcher(t) + c := NewL1BeaconClient(p, L1BeaconClientConfig{}, f) + p.EXPECT().BeaconGenesis(ctx).Return(eth.APIGenesisResponse{Data: eth.ReducedGenesisData{GenesisTime: 10}}, nil) + p.EXPECT().ConfigSpec(ctx).Return(eth.APIConfigResponse{Data: eth.ReducedConfigData{SecondsPerSlot: 2}}, nil) + // Timestamp 12 = Slot 1 + p.EXPECT().BeaconBlobSideCars(ctx, false, uint64(1), hashes).Return(eth.APIGetBlobSidecarsResponse{Data: apiSidecars}, nil) + + resp, err := c.GetBlobSidecars(ctx, eth.L1BlockRef{Time: 12}, hashes) + require.Equal(t, sidecars, resp) + require.NoError(t, err) +} + +func TestBeaconClientFallback(t *testing.T) { + indices := []uint64{5, 7, 2} + index0, sidecar0 := makeTestBlobSidecar(indices[0]) + index1, sidecar1 := makeTestBlobSidecar(indices[1]) + index2, sidecar2 := makeTestBlobSidecar(indices[2]) + + hashes := []eth.IndexedBlobHash{index0, index1, index2} + sidecars := []*eth.BlobSidecar{sidecar0, sidecar1, sidecar2} + apiSidecars := toAPISideCars(sidecars) + + ctx := context.Background() + p := mocks.NewBeaconClient(t) + f := mocks.NewBlobSideCarsFetcher(t) + c := NewL1BeaconClient(p, L1BeaconClientConfig{}, f) + p.EXPECT().BeaconGenesis(ctx).Return(eth.APIGenesisResponse{Data: eth.ReducedGenesisData{GenesisTime: 10}}, nil) + p.EXPECT().ConfigSpec(ctx).Return(eth.APIConfigResponse{Data: eth.ReducedConfigData{SecondsPerSlot: 2}}, nil) + // Timestamp 12 = Slot 1 + p.EXPECT().BeaconBlobSideCars(ctx, false, uint64(1), hashes).Return(eth.APIGetBlobSidecarsResponse{}, errors.New("404 not found")) + f.EXPECT().BeaconBlobSideCars(ctx, false, uint64(1), hashes).Return(eth.APIGetBlobSidecarsResponse{Data: apiSidecars}, nil) + + resp, err := c.GetBlobSidecars(ctx, eth.L1BlockRef{Time: 12}, hashes) + require.Equal(t, sidecars, resp) + require.NoError(t, err) + + // Second set of calls. This time rotate back to the primary + indices = []uint64{3, 9, 11} + index0, sidecar0 = makeTestBlobSidecar(indices[0]) + index1, sidecar1 = makeTestBlobSidecar(indices[1]) + index2, sidecar2 = makeTestBlobSidecar(indices[2]) + + hashes = []eth.IndexedBlobHash{index0, index1, index2} + sidecars = []*eth.BlobSidecar{sidecar0, sidecar1, sidecar2} + apiSidecars = toAPISideCars(sidecars) + + // Timestamp 14 = Slot 2 + f.EXPECT().BeaconBlobSideCars(ctx, false, uint64(2), hashes).Return(eth.APIGetBlobSidecarsResponse{}, errors.New("404 not found")) + p.EXPECT().BeaconBlobSideCars(ctx, false, uint64(2), hashes).Return(eth.APIGetBlobSidecarsResponse{Data: apiSidecars}, nil) + + resp, err = c.GetBlobSidecars(ctx, eth.L1BlockRef{Time: 14}, hashes) + require.Equal(t, sidecars, resp) + require.NoError(t, err) + +} + +func TestClientPoolSingle(t *testing.T) { + p := NewClientPool[int](1) + for i := 0; i < 10; i++ { + require.Equal(t, 1, p.Get()) + p.MoveToNext() + } +} +func TestClientPoolSeveral(t *testing.T) { + p := NewClientPool[int](0, 1, 2, 3) + for i := 0; i < 25; i++ { + require.Equal(t, i%4, p.Get()) + p.MoveToNext() + } +} diff --git a/op-service/sources/mocks/BeaconClient.go b/op-service/sources/mocks/BeaconClient.go new file mode 100644 index 000000000000..b862b39db64c --- /dev/null +++ b/op-service/sources/mocks/BeaconClient.go @@ -0,0 +1,249 @@ +// Code generated by mockery v2.28.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + + eth "github.com/ethereum-optimism/optimism/op-service/eth" + mock "github.com/stretchr/testify/mock" +) + +// BeaconClient is an autogenerated mock type for the BeaconClient type +type BeaconClient struct { + mock.Mock +} + +type BeaconClient_Expecter struct { + mock *mock.Mock +} + +func (_m *BeaconClient) EXPECT() *BeaconClient_Expecter { + return &BeaconClient_Expecter{mock: &_m.Mock} +} + +// BeaconBlobSideCars provides a mock function with given fields: ctx, fetchAllSidecars, slot, hashes +func (_m *BeaconClient) BeaconBlobSideCars(ctx context.Context, fetchAllSidecars bool, slot uint64, hashes []eth.IndexedBlobHash) (eth.APIGetBlobSidecarsResponse, error) { + ret := _m.Called(ctx, fetchAllSidecars, slot, hashes) + + var r0 eth.APIGetBlobSidecarsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, bool, uint64, []eth.IndexedBlobHash) (eth.APIGetBlobSidecarsResponse, error)); ok { + return rf(ctx, fetchAllSidecars, slot, hashes) + } + if rf, ok := ret.Get(0).(func(context.Context, bool, uint64, []eth.IndexedBlobHash) eth.APIGetBlobSidecarsResponse); ok { + r0 = rf(ctx, fetchAllSidecars, slot, hashes) + } else { + r0 = ret.Get(0).(eth.APIGetBlobSidecarsResponse) + } + + if rf, ok := ret.Get(1).(func(context.Context, bool, uint64, []eth.IndexedBlobHash) error); ok { + r1 = rf(ctx, fetchAllSidecars, slot, hashes) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BeaconClient_BeaconBlobSideCars_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BeaconBlobSideCars' +type BeaconClient_BeaconBlobSideCars_Call struct { + *mock.Call +} + +// BeaconBlobSideCars is a helper method to define mock.On call +// - ctx context.Context +// - fetchAllSidecars bool +// - slot uint64 +// - hashes []eth.IndexedBlobHash +func (_e *BeaconClient_Expecter) BeaconBlobSideCars(ctx interface{}, fetchAllSidecars interface{}, slot interface{}, hashes interface{}) *BeaconClient_BeaconBlobSideCars_Call { + return &BeaconClient_BeaconBlobSideCars_Call{Call: _e.mock.On("BeaconBlobSideCars", ctx, fetchAllSidecars, slot, hashes)} +} + +func (_c *BeaconClient_BeaconBlobSideCars_Call) Run(run func(ctx context.Context, fetchAllSidecars bool, slot uint64, hashes []eth.IndexedBlobHash)) *BeaconClient_BeaconBlobSideCars_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(bool), args[2].(uint64), args[3].([]eth.IndexedBlobHash)) + }) + return _c +} + +func (_c *BeaconClient_BeaconBlobSideCars_Call) Return(_a0 eth.APIGetBlobSidecarsResponse, _a1 error) *BeaconClient_BeaconBlobSideCars_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *BeaconClient_BeaconBlobSideCars_Call) RunAndReturn(run func(context.Context, bool, uint64, []eth.IndexedBlobHash) (eth.APIGetBlobSidecarsResponse, error)) *BeaconClient_BeaconBlobSideCars_Call { + _c.Call.Return(run) + return _c +} + +// BeaconGenesis provides a mock function with given fields: ctx +func (_m *BeaconClient) BeaconGenesis(ctx context.Context) (eth.APIGenesisResponse, error) { + ret := _m.Called(ctx) + + var r0 eth.APIGenesisResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (eth.APIGenesisResponse, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) eth.APIGenesisResponse); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(eth.APIGenesisResponse) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BeaconClient_BeaconGenesis_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BeaconGenesis' +type BeaconClient_BeaconGenesis_Call struct { + *mock.Call +} + +// BeaconGenesis is a helper method to define mock.On call +// - ctx context.Context +func (_e *BeaconClient_Expecter) BeaconGenesis(ctx interface{}) *BeaconClient_BeaconGenesis_Call { + return &BeaconClient_BeaconGenesis_Call{Call: _e.mock.On("BeaconGenesis", ctx)} +} + +func (_c *BeaconClient_BeaconGenesis_Call) Run(run func(ctx context.Context)) *BeaconClient_BeaconGenesis_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *BeaconClient_BeaconGenesis_Call) Return(_a0 eth.APIGenesisResponse, _a1 error) *BeaconClient_BeaconGenesis_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *BeaconClient_BeaconGenesis_Call) RunAndReturn(run func(context.Context) (eth.APIGenesisResponse, error)) *BeaconClient_BeaconGenesis_Call { + _c.Call.Return(run) + return _c +} + +// ConfigSpec provides a mock function with given fields: ctx +func (_m *BeaconClient) ConfigSpec(ctx context.Context) (eth.APIConfigResponse, error) { + ret := _m.Called(ctx) + + var r0 eth.APIConfigResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (eth.APIConfigResponse, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) eth.APIConfigResponse); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(eth.APIConfigResponse) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BeaconClient_ConfigSpec_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConfigSpec' +type BeaconClient_ConfigSpec_Call struct { + *mock.Call +} + +// ConfigSpec is a helper method to define mock.On call +// - ctx context.Context +func (_e *BeaconClient_Expecter) ConfigSpec(ctx interface{}) *BeaconClient_ConfigSpec_Call { + return &BeaconClient_ConfigSpec_Call{Call: _e.mock.On("ConfigSpec", ctx)} +} + +func (_c *BeaconClient_ConfigSpec_Call) Run(run func(ctx context.Context)) *BeaconClient_ConfigSpec_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *BeaconClient_ConfigSpec_Call) Return(_a0 eth.APIConfigResponse, _a1 error) *BeaconClient_ConfigSpec_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *BeaconClient_ConfigSpec_Call) RunAndReturn(run func(context.Context) (eth.APIConfigResponse, error)) *BeaconClient_ConfigSpec_Call { + _c.Call.Return(run) + return _c +} + +// NodeVersion provides a mock function with given fields: ctx +func (_m *BeaconClient) NodeVersion(ctx context.Context) (string, error) { + ret := _m.Called(ctx) + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (string, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) string); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BeaconClient_NodeVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NodeVersion' +type BeaconClient_NodeVersion_Call struct { + *mock.Call +} + +// NodeVersion is a helper method to define mock.On call +// - ctx context.Context +func (_e *BeaconClient_Expecter) NodeVersion(ctx interface{}) *BeaconClient_NodeVersion_Call { + return &BeaconClient_NodeVersion_Call{Call: _e.mock.On("NodeVersion", ctx)} +} + +func (_c *BeaconClient_NodeVersion_Call) Run(run func(ctx context.Context)) *BeaconClient_NodeVersion_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *BeaconClient_NodeVersion_Call) Return(_a0 string, _a1 error) *BeaconClient_NodeVersion_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *BeaconClient_NodeVersion_Call) RunAndReturn(run func(context.Context) (string, error)) *BeaconClient_NodeVersion_Call { + _c.Call.Return(run) + return _c +} + +type mockConstructorTestingTNewBeaconClient interface { + mock.TestingT + Cleanup(func()) +} + +// NewBeaconClient creates a new instance of BeaconClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewBeaconClient(t mockConstructorTestingTNewBeaconClient) *BeaconClient { + mock := &BeaconClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/op-service/sources/mocks/BlobSideCarsFetcher.go b/op-service/sources/mocks/BlobSideCarsFetcher.go new file mode 100644 index 000000000000..5dc530d9317a --- /dev/null +++ b/op-service/sources/mocks/BlobSideCarsFetcher.go @@ -0,0 +1,93 @@ +// Code generated by mockery v2.28.1. DO NOT EDIT. + +package mocks + +import ( + context "context" + + eth "github.com/ethereum-optimism/optimism/op-service/eth" + mock "github.com/stretchr/testify/mock" +) + +// BlobSideCarsFetcher is an autogenerated mock type for the BlobSideCarsFetcher type +type BlobSideCarsFetcher struct { + mock.Mock +} + +type BlobSideCarsFetcher_Expecter struct { + mock *mock.Mock +} + +func (_m *BlobSideCarsFetcher) EXPECT() *BlobSideCarsFetcher_Expecter { + return &BlobSideCarsFetcher_Expecter{mock: &_m.Mock} +} + +// BeaconBlobSideCars provides a mock function with given fields: ctx, fetchAllSidecars, slot, hashes +func (_m *BlobSideCarsFetcher) BeaconBlobSideCars(ctx context.Context, fetchAllSidecars bool, slot uint64, hashes []eth.IndexedBlobHash) (eth.APIGetBlobSidecarsResponse, error) { + ret := _m.Called(ctx, fetchAllSidecars, slot, hashes) + + var r0 eth.APIGetBlobSidecarsResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, bool, uint64, []eth.IndexedBlobHash) (eth.APIGetBlobSidecarsResponse, error)); ok { + return rf(ctx, fetchAllSidecars, slot, hashes) + } + if rf, ok := ret.Get(0).(func(context.Context, bool, uint64, []eth.IndexedBlobHash) eth.APIGetBlobSidecarsResponse); ok { + r0 = rf(ctx, fetchAllSidecars, slot, hashes) + } else { + r0 = ret.Get(0).(eth.APIGetBlobSidecarsResponse) + } + + if rf, ok := ret.Get(1).(func(context.Context, bool, uint64, []eth.IndexedBlobHash) error); ok { + r1 = rf(ctx, fetchAllSidecars, slot, hashes) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BlobSideCarsFetcher_BeaconBlobSideCars_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BeaconBlobSideCars' +type BlobSideCarsFetcher_BeaconBlobSideCars_Call struct { + *mock.Call +} + +// BeaconBlobSideCars is a helper method to define mock.On call +// - ctx context.Context +// - fetchAllSidecars bool +// - slot uint64 +// - hashes []eth.IndexedBlobHash +func (_e *BlobSideCarsFetcher_Expecter) BeaconBlobSideCars(ctx interface{}, fetchAllSidecars interface{}, slot interface{}, hashes interface{}) *BlobSideCarsFetcher_BeaconBlobSideCars_Call { + return &BlobSideCarsFetcher_BeaconBlobSideCars_Call{Call: _e.mock.On("BeaconBlobSideCars", ctx, fetchAllSidecars, slot, hashes)} +} + +func (_c *BlobSideCarsFetcher_BeaconBlobSideCars_Call) Run(run func(ctx context.Context, fetchAllSidecars bool, slot uint64, hashes []eth.IndexedBlobHash)) *BlobSideCarsFetcher_BeaconBlobSideCars_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(bool), args[2].(uint64), args[3].([]eth.IndexedBlobHash)) + }) + return _c +} + +func (_c *BlobSideCarsFetcher_BeaconBlobSideCars_Call) Return(_a0 eth.APIGetBlobSidecarsResponse, _a1 error) *BlobSideCarsFetcher_BeaconBlobSideCars_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *BlobSideCarsFetcher_BeaconBlobSideCars_Call) RunAndReturn(run func(context.Context, bool, uint64, []eth.IndexedBlobHash) (eth.APIGetBlobSidecarsResponse, error)) *BlobSideCarsFetcher_BeaconBlobSideCars_Call { + _c.Call.Return(run) + return _c +} + +type mockConstructorTestingTNewBlobSideCarsFetcher interface { + mock.TestingT + Cleanup(func()) +} + +// NewBlobSideCarsFetcher creates a new instance of BlobSideCarsFetcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +func NewBlobSideCarsFetcher(t mockConstructorTestingTNewBlobSideCarsFetcher) *BlobSideCarsFetcher { + mock := &BlobSideCarsFetcher{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/op-service/sources/receipts.go b/op-service/sources/receipts.go index a7a2b67131ee..79929e4f7318 100644 --- a/op-service/sources/receipts.go +++ b/op-service/sources/receipts.go @@ -14,7 +14,7 @@ type ReceiptsProvider interface { // 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. - FetchReceipts(ctx context.Context, block eth.BlockID, txHashes []common.Hash) (types.Receipts, error) + FetchReceipts(ctx context.Context, blockInfo eth.BlockInfo, txHashes []common.Hash) (types.Receipts, error) } // validateReceipts validates that the receipt contents are valid. diff --git a/op-service/sources/receipts_basic.go b/op-service/sources/receipts_basic.go index 85d5cea679ba..ec63c0565bf2 100644 --- a/op-service/sources/receipts_basic.go +++ b/op-service/sources/receipts_basic.go @@ -31,7 +31,10 @@ func NewBasicRPCReceiptsFetcher(client rpcClient, maxBatchSize int) *BasicRPCRec } } -func (f *BasicRPCReceiptsFetcher) FetchReceipts(ctx context.Context, block eth.BlockID, txHashes []common.Hash) (types.Receipts, error) { +// FetchReceipts fetches receipts for the given block and transaction hashes +// it does not validate receipts, and expects the caller to do so +func (f *BasicRPCReceiptsFetcher) FetchReceipts(ctx context.Context, blockInfo eth.BlockInfo, txHashes []common.Hash) (types.Receipts, error) { + block := eth.ToBlockID(blockInfo) call := f.getOrCreateBatchCall(block.Hash, txHashes) // Fetch all receipts diff --git a/op-service/sources/receipts_basic_test.go b/op-service/sources/receipts_basic_test.go index 3af93c875efa..3a0bbdf2219d 100644 --- a/op-service/sources/receipts_basic_test.go +++ b/op-service/sources/receipts_basic_test.go @@ -35,7 +35,6 @@ func TestBasicRPCReceiptsFetcher_Reuse(t *testing.T) { require := require.New(t) batchSize, txCount := 2, uint64(4) block, receipts := randomRpcBlockAndReceipts(rand.New(rand.NewSource(123)), txCount) - blockid := block.BlockID() txHashes := make([]common.Hash, 0, len(receipts)) recMap := make(map[common.Hash]*types.Receipt, len(receipts)) for _, rec := range receipts { @@ -75,8 +74,10 @@ func TestBasicRPCReceiptsFetcher_Reuse(t *testing.T) { return err } + bInfo, _, _ := block.Info(true, true) + // 1st fetching should result in errors - recs, err := rp.FetchReceipts(ctx, blockid, txHashes) + recs, err := rp.FetchReceipts(ctx, bInfo, txHashes) require.Error(err) require.Nil(recs) require.EqualValues(2, numCalls.Load()) @@ -84,7 +85,7 @@ func TestBasicRPCReceiptsFetcher_Reuse(t *testing.T) { // prepare 2nd fetching - all should succeed now response[txHashes[2]] = true response[txHashes[3]] = true - recs, err = rp.FetchReceipts(ctx, blockid, txHashes) + recs, err = rp.FetchReceipts(ctx, bInfo, txHashes) require.NoError(err) require.NotNil(recs) for i, rec := range recs { @@ -130,7 +131,7 @@ func TestBasicRPCReceiptsFetcher_Concurrency(t *testing.T) { require.Less(finalNumCalls, numFetchers, "Some IterativeBatchCalls should have been shared.") } -func runConcurrentFetchingTest(t *testing.T, rp ReceiptsProvider, numFetchers int, receipts types.Receipts, block *rpcBlock) { +func runConcurrentFetchingTest(t *testing.T, rp ReceiptsProvider, numFetchers int, receipts types.Receipts, block *RPCBlock) { require := require.New(t) txHashes := receiptTxHashes(receipts) @@ -141,12 +142,13 @@ func runConcurrentFetchingTest(t *testing.T, rp ReceiptsProvider, numFetchers in } fetchResults := make(chan fetchResult, numFetchers) barrier := make(chan struct{}) + bInfo, _, _ := block.Info(true, true) ctx, done := context.WithTimeout(context.Background(), 10*time.Second) defer done() for i := 0; i < numFetchers; i++ { go func() { <-barrier - recs, err := rp.FetchReceipts(ctx, block.BlockID(), txHashes) + recs, err := rp.FetchReceipts(ctx, bInfo, txHashes) fetchResults <- fetchResult{rs: recs, err: err} }() } diff --git a/op-service/sources/receipts_caching.go b/op-service/sources/receipts_caching.go index bc02e39e8728..4631e4e78b23 100644 --- a/op-service/sources/receipts_caching.go +++ b/op-service/sources/receipts_caching.go @@ -51,7 +51,10 @@ func (p *CachingReceiptsProvider) deleteFetchingLock(blockHash common.Hash) { delete(p.fetching, blockHash) } -func (p *CachingReceiptsProvider) FetchReceipts(ctx context.Context, block eth.BlockID, txHashes []common.Hash) (types.Receipts, error) { +// FetchReceipts fetches receipts for the given block and transaction hashes +// it expects that the inner FetchReceipts implementation handles validation +func (p *CachingReceiptsProvider) FetchReceipts(ctx context.Context, blockInfo eth.BlockInfo, txHashes []common.Hash) (types.Receipts, error) { + block := eth.ToBlockID(blockInfo) if r, ok := p.cache.Get(block.Hash); ok { return r, nil } @@ -67,10 +70,11 @@ func (p *CachingReceiptsProvider) FetchReceipts(ctx context.Context, block eth.B return r, nil } - r, err := p.inner.FetchReceipts(ctx, block, txHashes) + r, err := p.inner.FetchReceipts(ctx, blockInfo, txHashes) if err != nil { return nil, err } + p.cache.Add(block.Hash, r) // result now in cache, can delete fetching lock p.deleteFetchingLock(block.Hash) diff --git a/op-service/sources/receipts_caching_test.go b/op-service/sources/receipts_caching_test.go index a4eacf518fda..e7891b9e34fd 100644 --- a/op-service/sources/receipts_caching_test.go +++ b/op-service/sources/receipts_caching_test.go @@ -17,7 +17,8 @@ type mockReceiptsProvider struct { mock.Mock } -func (m *mockReceiptsProvider) FetchReceipts(ctx context.Context, block eth.BlockID, txHashes []common.Hash) (types.Receipts, error) { +func (m *mockReceiptsProvider) FetchReceipts(ctx context.Context, blockInfo eth.BlockInfo, txHashes []common.Hash) (types.Receipts, error) { + block := eth.ToBlockID(blockInfo) args := m.Called(ctx, block, txHashes) return args.Get(0).(types.Receipts), args.Error(1) } @@ -35,8 +36,9 @@ func TestCachingReceiptsProvider_Caching(t *testing.T) { Return(types.Receipts(receipts), error(nil)). Once() // receipts should be cached after first fetch + bInfo, _, _ := block.Info(true, true) for i := 0; i < 4; i++ { - gotRecs, err := rp.FetchReceipts(ctx, blockid, txHashes) + gotRecs, err := rp.FetchReceipts(ctx, bInfo, txHashes) require.NoError(t, err) for i, gotRec := range gotRecs { requireEqualReceipt(t, receipts[i], gotRec) diff --git a/op-service/sources/receipts_rcp.go b/op-service/sources/receipts_rpc.go similarity index 98% rename from op-service/sources/receipts_rcp.go rename to op-service/sources/receipts_rpc.go index bf6398b5a8f2..ecf2c8582210 100644 --- a/op-service/sources/receipts_rcp.go +++ b/op-service/sources/receipts_rpc.go @@ -70,11 +70,12 @@ func NewRPCReceiptsFetcher(client rpcClient, log log.Logger, config RPCReceiptsC } } -func (f *RPCReceiptsFetcher) FetchReceipts(ctx context.Context, block eth.BlockID, txHashes []common.Hash) (result types.Receipts, err error) { +func (f *RPCReceiptsFetcher) FetchReceipts(ctx context.Context, blockInfo eth.BlockInfo, txHashes []common.Hash) (result types.Receipts, err error) { m := f.PickReceiptsMethod(len(txHashes)) + block := eth.ToBlockID(blockInfo) switch m { case EthGetTransactionReceiptBatch: - result, err = f.basic.FetchReceipts(ctx, block, txHashes) + result, err = f.basic.FetchReceipts(ctx, blockInfo, txHashes) case AlchemyGetTransactionReceipts: var tmp receiptsWrapper err = f.client.CallContext(ctx, &tmp, "alchemy_getTransactionReceipts", blockHashParameter{BlockHash: block.Hash}) @@ -104,6 +105,10 @@ func (f *RPCReceiptsFetcher) FetchReceipts(ctx context.Context, block eth.BlockI return nil, err } + if err = validateReceipts(block, blockInfo.ReceiptHash(), txHashes, result); err != nil { + return nil, err + } + return } diff --git a/op-service/sources/receipts_test.go b/op-service/sources/receipts_test.go index 8fe32d6402bb..088a3d9b22cb 100644 --- a/op-service/sources/receipts_test.go +++ b/op-service/sources/receipts_test.go @@ -27,9 +27,9 @@ type ethBackend struct { *mock.Mock } -func (b *ethBackend) GetBlockByHash(id common.Hash, fullTxs bool) (*rpcBlock, error) { +func (b *ethBackend) GetBlockByHash(id common.Hash, fullTxs bool) (*RPCBlock, error) { out := b.Mock.MethodCalled("eth_getBlockByHash", id, fullTxs) - return out[0].(*rpcBlock), nil + return out[0].(*RPCBlock), nil } func (b *ethBackend) GetTransactionReceipt(txHash common.Hash) (*types.Receipt, error) { @@ -98,7 +98,7 @@ type ReceiptsTestCase struct { name string providerKind RPCProviderKind staticMethod bool - setup func(t *testing.T) (*rpcBlock, []ReceiptsRequest) + setup func(t *testing.T) (*RPCBlock, []ReceiptsRequest) } func (tc *ReceiptsTestCase) Run(t *testing.T) { @@ -163,7 +163,7 @@ func (tc *ReceiptsTestCase) Run(t *testing.T) { if tc.staticMethod { // if static, instantly reset, for fast clock-independent testing testCfg.MethodResetDuration = 0 } - logger := testlog.Logger(t, log.LvlError) + logger := testlog.Logger(t, log.LevelError) ethCl, err := NewEthClient(client.NewBaseRPCClient(cl), logger, nil, testCfg) require.NoError(t, err) defer ethCl.Close() @@ -185,10 +185,10 @@ func (tc *ReceiptsTestCase) Run(t *testing.T) { m.AssertExpectations(t) } -func randomRpcBlockAndReceipts(rng *rand.Rand, txCount uint64) (*rpcBlock, []*types.Receipt) { +func randomRpcBlockAndReceipts(rng *rand.Rand, txCount uint64) (*RPCBlock, []*types.Receipt) { block, receipts := testutils.RandomBlock(rng, txCount) - return &rpcBlock{ - rpcHeader: rpcHeader{ + return &RPCBlock{ + RPCHeader: RPCHeader{ ParentHash: block.ParentHash(), UncleHash: block.UncleHash(), Coinbase: block.Coinbase(), @@ -214,8 +214,8 @@ func randomRpcBlockAndReceipts(rng *rand.Rand, txCount uint64) (*rpcBlock, []*ty func TestEthClient_FetchReceipts(t *testing.T) { // Helper to quickly define the test case requests scenario: // each method fails to fetch the receipts, except the last - fallbackCase := func(txCount uint64, methods ...ReceiptsFetchingMethod) func(t *testing.T) (*rpcBlock, []ReceiptsRequest) { - return func(t *testing.T) (*rpcBlock, []ReceiptsRequest) { + fallbackCase := func(txCount uint64, methods ...ReceiptsFetchingMethod) func(t *testing.T) (*RPCBlock, []ReceiptsRequest) { + return func(t *testing.T) (*RPCBlock, []ReceiptsRequest) { block, receipts := randomRpcBlockAndReceipts(rand.New(rand.NewSource(123)), txCount) // zero out the data we don't want to verify for _, r := range receipts { @@ -356,7 +356,7 @@ func TestVerifyReceipts(t *testing.T) { Type: 2, Status: 0, CumulativeGasUsed: 0x3035b, - Bloom: types.BytesToBloom(common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")), + Bloom: types.BytesToBloom(common.FromHex("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")), Logs: nil, TxHash: txHashes[0], GasUsed: 0x3035b, @@ -369,7 +369,7 @@ func TestVerifyReceipts(t *testing.T) { Type: 2, Status: 1, CumulativeGasUsed: 0xa9ae4, - Bloom: types.BytesToBloom(common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")), + Bloom: types.BytesToBloom(common.FromHex("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")), Logs: nil, TxHash: txHashes[1], GasUsed: 0x79789, @@ -382,7 +382,7 @@ func TestVerifyReceipts(t *testing.T) { Type: 0, Status: 1, CumulativeGasUsed: 0x101f09, - Bloom: types.BytesToBloom(common.Hex2Bytes("00000000000000000000000000000200000400000000000000000000000000800000000000040000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000800000000000000000000000000000000000000000000000000000400000000000000020000000000000000000000000002000000000000000000000000000000000000000000")), + Bloom: types.BytesToBloom(common.FromHex("00000000000000000000000000000200000400000000000000000000000000800000000000040000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000800000000000000000000000000000000000000000000000000000400000000000000020000000000000000000000000002000000000000000000000000000000000000000000")), Logs: []*types.Log{ { Address: common.HexToAddress("0x759c5e44a9e4be8b7e9bd25a790ceb662c924c45"), @@ -391,7 +391,7 @@ func TestVerifyReceipts(t *testing.T) { common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000426a80"), common.HexToHash("0x000000000000000000000000a6275ee214f80a532c3abee0a4cbbc2d1dc22a72"), }, - Data: common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000000005dc"), + Data: common.FromHex("00000000000000000000000000000000000000000000000000000000000005dc"), BlockNumber: block.Number, TxHash: txHashes[2], TxIndex: 2, @@ -411,7 +411,7 @@ func TestVerifyReceipts(t *testing.T) { Type: 0, Status: 1, CumulativeGasUsed: 0x1227ab, - Bloom: types.BytesToBloom(common.Hex2Bytes("00000000000000000000000000000200000400000000000000000000000000800000000000040000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000800000000000000000000000000000000000000000000000000000400000000000000020000000000000000000000000002000000000000000000000000000000000000000000")), + Bloom: types.BytesToBloom(common.FromHex("00000000000000000000000000000200000400000000000000000000000000800000000000040000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000800000000000000000000000000000000000000000000000000000400000000000000020000000000000000000000000002000000000000000000000000000000000000000000")), Logs: []*types.Log{ { Address: common.HexToAddress("0x759c5e44a9e4be8b7e9bd25a790ceb662c924c45"), @@ -420,7 +420,7 @@ func TestVerifyReceipts(t *testing.T) { common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000426a80"), common.HexToHash("0x000000000000000000000000a6275ee214f80a532c3abee0a4cbbc2d1dc22a72"), }, - Data: common.Hex2Bytes("00000000000000000000000000000000000000000000000000000000000005dc"), + Data: common.FromHex("00000000000000000000000000000000000000000000000000000000000005dc"), BlockNumber: block.Number, TxHash: txHashes[3], TxIndex: 3, diff --git a/op-service/sources/reth_db.go b/op-service/sources/reth_db.go index 0bec214367b5..aba2d8f25bff 100644 --- a/op-service/sources/reth_db.go +++ b/op-service/sources/reth_db.go @@ -77,14 +77,17 @@ type RethDBReceiptsFetcher struct { // into NewRethDBReceiptsFetcher. } +var _ ReceiptsProvider = (*RethDBReceiptsFetcher)(nil) + func NewRethDBReceiptsFetcher(dbPath string) *RethDBReceiptsFetcher { return &RethDBReceiptsFetcher{ dbPath: dbPath, } } -func (f *RethDBReceiptsFetcher) FetchReceipts(ctx context.Context, block eth.BlockID, txHashes []common.Hash) (types.Receipts, error) { - return FetchRethReceipts(f.dbPath, &block.Hash) +func (f *RethDBReceiptsFetcher) FetchReceipts(ctx context.Context, block eth.BlockInfo, txHashes []common.Hash) (types.Receipts, error) { + hash := block.Hash() + return FetchRethReceipts(f.dbPath, &hash) } func NewCachingRethDBReceiptsFetcher(dbPath string, m caching.Metrics, cacheSize int) *CachingReceiptsProvider { diff --git a/op-service/sources/reth_db_test.go b/op-service/sources/reth_db_test.go index e1942344620a..c98cf07a6153 100644 --- a/op-service/sources/reth_db_test.go +++ b/op-service/sources/reth_db_test.go @@ -30,11 +30,11 @@ func TestRethDBReceiptsLoad(t *testing.T) { require.Equal(t, receipt.Type, uint8(2)) require.Equal(t, receipt.Status, uint64(1)) require.Equal(t, receipt.CumulativeGasUsed, uint64(115_316)) - require.Equal(t, receipt.Bloom, types.BytesToBloom(common.Hex2Bytes("00200000000000000000000080001000000000000000000000000000000000000000000000000000000000000000100002000100080000000000000000000000000000000000000000000008000000200000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000400000000000001000000000000000100000000080000004000000000000000000000000000000000000002000000000000000000000000000000000000000006000000000000000000000000000000000000001000000000000000000000200000000000000100000000020000000000000000000000000000000010"))) + require.Equal(t, receipt.Bloom, types.BytesToBloom(common.FromHex("00200000000000000000000080001000000000000000000000000000000000000000000000000000000000000000100002000100080000000000000000000000000000000000000000000008000000200000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000400000000000001000000000000000100000000080000004000000000000000000000000000000000000002000000000000000000000000000000000000000006000000000000000000000000000000000000001000000000000000000000200000000000000100000000020000000000000000000000000000000010"))) require.Equal(t, receipt.Logs[0].Address, common.HexToAddress("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")) require.Equal(t, receipt.Logs[0].Topics[0], common.HexToHash("ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef")) require.Equal(t, receipt.Logs[0].Topics[1], common.HexToHash("00000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40")) - require.Equal(t, receipt.Logs[0].Data, common.Hex2Bytes("00000000000000000000000000000000000000000000000008a30cd230000000")) + require.Equal(t, receipt.Logs[0].Data, common.FromHex("00000000000000000000000000000000000000000000000008a30cd230000000")) require.Equal(t, receipt.TxHash, common.HexToHash("0x88b2d153a4e893ba91ac235325c44b1aa0c802fcb42657701e1a73e1c675f7ca")) require.Equal(t, receipt.BlockHash, blockHash) diff --git a/op-service/sources/rollupclient.go b/op-service/sources/rollupclient.go index cc45dddb9168..96cd166732a9 100644 --- a/op-service/sources/rollupclient.go +++ b/op-service/sources/rollupclient.go @@ -3,9 +3,10 @@ package sources import ( "context" + "golang.org/x/exp/slog" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/client" @@ -26,6 +27,12 @@ func (r *RollupClient) OutputAtBlock(ctx context.Context, blockNum uint64) (*eth return output, err } +func (r *RollupClient) SafeHeadAtL1Block(ctx context.Context, blockNum uint64) (*eth.SafeHeadResponse, error) { + var output *eth.SafeHeadResponse + err := r.rpc.CallContext(ctx, &output, "optimism_safeHeadAtL1Block", hexutil.Uint64(blockNum)) + return output, err +} + func (r *RollupClient) SyncStatus(ctx context.Context) (*eth.SyncStatus, error) { var output *eth.SyncStatus err := r.rpc.CallContext(ctx, &output, "optimism_syncStatus") @@ -64,7 +71,7 @@ func (r *RollupClient) PostUnsafePayload(ctx context.Context, payload *eth.Execu return r.rpc.CallContext(ctx, nil, "admin_postUnsafePayload", payload) } -func (r *RollupClient) SetLogLevel(ctx context.Context, lvl log.Lvl) error { +func (r *RollupClient) SetLogLevel(ctx context.Context, lvl slog.Level) error { return r.rpc.CallContext(ctx, nil, "admin_setLogLevel", lvl.String()) } diff --git a/op-service/sources/types.go b/op-service/sources/types.go index d9cffa60d758..afb994bd7cc3 100644 --- a/op-service/sources/types.go +++ b/op-service/sources/types.go @@ -98,7 +98,7 @@ func (h headerInfo) HeaderRLP() ([]byte, error) { return rlp.EncodeToBytes(h.Header) } -type rpcHeader struct { +type RPCHeader struct { ParentHash common.Hash `json:"parentHash"` UncleHash common.Hash `json:"sha3Uncles"` Coinbase common.Address `json:"miner"` @@ -136,7 +136,7 @@ type rpcHeader struct { // checkPostMerge checks that the block header meets all criteria to be a valid ExecutionPayloadHeader, // see EIP-3675 (block header changes) and EIP-4399 (mixHash usage for prev-randao) -func (hdr *rpcHeader) checkPostMerge() error { +func (hdr *RPCHeader) checkPostMerge() error { // TODO: the genesis block has a non-zero difficulty number value. // Either this block needs to change, or we special case it. This is not valid w.r.t. EIP-3675. if hdr.Number != 0 && (*big.Int)(&hdr.Difficulty).Cmp(common.Big0) != 0 { @@ -157,12 +157,12 @@ func (hdr *rpcHeader) checkPostMerge() error { return nil } -func (hdr *rpcHeader) computeBlockHash() common.Hash { +func (hdr *RPCHeader) computeBlockHash() common.Hash { gethHeader := hdr.createGethHeader() return gethHeader.Hash() } -func (hdr *rpcHeader) createGethHeader() *types.Header { +func (hdr *RPCHeader) createGethHeader() *types.Header { return &types.Header{ ParentHash: hdr.ParentHash, UncleHash: hdr.UncleHash, @@ -188,7 +188,7 @@ func (hdr *rpcHeader) createGethHeader() *types.Header { } } -func (hdr *rpcHeader) Info(trustCache bool, mustBePostMerge bool) (eth.BlockInfo, error) { +func (hdr *RPCHeader) Info(trustCache bool, mustBePostMerge bool) (eth.BlockInfo, error) { if mustBePostMerge { if err := hdr.checkPostMerge(); err != nil { return nil, err @@ -202,20 +202,20 @@ func (hdr *rpcHeader) Info(trustCache bool, mustBePostMerge bool) (eth.BlockInfo return &headerInfo{hdr.Hash, hdr.createGethHeader()}, nil } -func (hdr *rpcHeader) BlockID() eth.BlockID { +func (hdr *RPCHeader) BlockID() eth.BlockID { return eth.BlockID{ Hash: hdr.Hash, Number: uint64(hdr.Number), } } -type rpcBlock struct { - rpcHeader +type RPCBlock struct { + RPCHeader Transactions []*types.Transaction `json:"transactions"` Withdrawals *types.Withdrawals `json:"withdrawals,omitempty"` } -func (block *rpcBlock) verify() error { +func (block *RPCBlock) verify() error { if computed := block.computeBlockHash(); computed != block.Hash { return fmt.Errorf("failed to verify block hash: computed %s but RPC said %s", computed, block.Hash) } @@ -247,7 +247,7 @@ func (block *rpcBlock) verify() error { return nil } -func (block *rpcBlock) Info(trustCache bool, mustBePostMerge bool) (eth.BlockInfo, types.Transactions, error) { +func (block *RPCBlock) Info(trustCache bool, mustBePostMerge bool) (eth.BlockInfo, types.Transactions, error) { if mustBePostMerge { if err := block.checkPostMerge(); err != nil { return nil, nil, err @@ -260,7 +260,7 @@ func (block *rpcBlock) Info(trustCache bool, mustBePostMerge bool) (eth.BlockInf } // verify the header data - info, err := block.rpcHeader.Info(trustCache, mustBePostMerge) + info, err := block.RPCHeader.Info(trustCache, mustBePostMerge) if err != nil { return nil, nil, fmt.Errorf("failed to verify block from RPC: %w", err) } @@ -268,7 +268,7 @@ func (block *rpcBlock) Info(trustCache bool, mustBePostMerge bool) (eth.BlockInf return info, block.Transactions, nil } -func (block *rpcBlock) ExecutionPayloadEnvelope(trustCache bool) (*eth.ExecutionPayloadEnvelope, error) { +func (block *RPCBlock) ExecutionPayloadEnvelope(trustCache bool) (*eth.ExecutionPayloadEnvelope, error) { if err := block.checkPostMerge(); err != nil { return nil, err } @@ -303,10 +303,12 @@ func (block *rpcBlock) ExecutionPayloadEnvelope(trustCache bool) (*eth.Execution GasUsed: block.GasUsed, Timestamp: block.Time, ExtraData: eth.BytesMax32(block.Extra), - BaseFeePerGas: baseFee, + BaseFeePerGas: eth.Uint256Quantity(baseFee), BlockHash: block.Hash, Transactions: opaqueTxs, Withdrawals: block.Withdrawals, + BlobGasUsed: block.BlobGasUsed, + ExcessBlobGas: block.ExcessBlobGas, } return ð.ExecutionPayloadEnvelope{ diff --git a/op-service/sources/types_test.go b/op-service/sources/types_test.go index 881809391e1b..6d6bad5565bf 100644 --- a/op-service/sources/types_test.go +++ b/op-service/sources/types_test.go @@ -3,9 +3,14 @@ package sources import ( "embed" "encoding/json" + "math/big" "strings" "testing" + "github.com/ethereum-optimism/optimism/op-service/eth" + "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" ) @@ -37,7 +42,7 @@ func TestBlockHeaderJSON(t *testing.T) { var metadata testMetadata readJsonTestdata(t, "testdata/data/headers/"+entry.Name(), &metadata) t.Run(metadata.Name, func(t *testing.T) { - var header rpcHeader + var header RPCHeader readJsonTestdata(t, "testdata/data/headers/"+strings.Replace(entry.Name(), "_metadata.json", "_data.json", 1), &header) h := header.computeBlockHash() @@ -62,7 +67,7 @@ func TestBlockJSON(t *testing.T) { var metadata testMetadata readJsonTestdata(t, "testdata/data/blocks/"+entry.Name(), &metadata) t.Run(metadata.Name, func(t *testing.T) { - var block rpcBlock + var block RPCBlock readJsonTestdata(t, "testdata/data/blocks/"+strings.Replace(entry.Name(), "_metadata.json", "_data.json", 1), &block) err := block.verify() @@ -75,3 +80,69 @@ func TestBlockJSON(t *testing.T) { }) } } + +func TestBlockToExecutionPayloadIncludesEcotoneProperties(t *testing.T) { + zero := uint64(0) + + hdr := &types.Header{ + ParentHash: randHash(), + UncleHash: types.EmptyUncleHash, + Coinbase: common.Address{}, + Root: randHash(), + TxHash: types.EmptyTxsHash, + ReceiptHash: randHash(), + Bloom: types.Bloom{}, + Difficulty: big.NewInt(0), + Number: big.NewInt(1234), + GasLimit: 0, + GasUsed: 0, + Time: 123456, + Extra: make([]byte, 0), + MixDigest: randHash(), + Nonce: types.BlockNonce{}, + BaseFee: big.NewInt(100), + WithdrawalsHash: &types.EmptyWithdrawalsHash, + ExcessBlobGas: &zero, + BlobGasUsed: &zero, + ParentBeaconRoot: &common.Hash{}, + } + rhdr := RPCHeader{ + ParentBeaconRoot: hdr.ParentBeaconRoot, + ParentHash: hdr.ParentHash, + WithdrawalsRoot: hdr.WithdrawalsHash, + UncleHash: hdr.UncleHash, + Coinbase: hdr.Coinbase, + Root: hdr.Root, + TxHash: hdr.TxHash, + ReceiptHash: hdr.ReceiptHash, + Bloom: eth.Bytes256(hdr.Bloom), + Difficulty: *(*hexutil.Big)(hdr.Difficulty), + Number: hexutil.Uint64(hdr.Number.Uint64()), + GasLimit: hexutil.Uint64(hdr.GasLimit), + GasUsed: hexutil.Uint64(hdr.GasUsed), + Time: hexutil.Uint64(hdr.Time), + Extra: hdr.Extra, + MixDigest: hdr.MixDigest, + Nonce: hdr.Nonce, + BaseFee: (*hexutil.Big)(hdr.BaseFee), + Hash: hdr.Hash(), + BlobGasUsed: (*hexutil.Uint64)(hdr.BlobGasUsed), + ExcessBlobGas: (*hexutil.Uint64)(hdr.ExcessBlobGas), + } + + block := RPCBlock{ + RPCHeader: rhdr, + Transactions: types.Transactions{}, + Withdrawals: &types.Withdrawals{}, + } + + envelope, err := block.ExecutionPayloadEnvelope(false) + require.NoError(t, err) + + require.NotNil(t, envelope.ParentBeaconBlockRoot) + require.Equal(t, *envelope.ParentBeaconBlockRoot, *hdr.ParentBeaconRoot) + require.NotNil(t, envelope.ExecutionPayload.ExcessBlobGas) + require.Equal(t, *envelope.ExecutionPayload.ExcessBlobGas, *rhdr.ExcessBlobGas) + require.NotNil(t, envelope.ExecutionPayload.BlobGasUsed) + require.Equal(t, *envelope.ExecutionPayload.BlobGasUsed, *rhdr.BlobGasUsed) +} diff --git a/op-service/testlog/capturing.go b/op-service/testlog/capturing.go index 5b87e30f445b..6e1edb09b504 100644 --- a/op-service/testlog/capturing.go +++ b/op-service/testlog/capturing.go @@ -1,56 +1,155 @@ package testlog import ( + "context" + "strings" + + "golang.org/x/exp/slog" + "github.com/ethereum/go-ethereum/log" ) // CapturingHandler provides a log handler that captures all log records and optionally forwards them to a delegate. // Note that it is not thread safe. type CapturingHandler struct { - Delegate log.Handler - Logs []*log.Record + handler slog.Handler + Logs *[]*slog.Record // shared among derived CapturingHandlers } -func Capture(l log.Logger) *CapturingHandler { - handler := &CapturingHandler{ - Delegate: l.GetHandler(), - } - l.SetHandler(handler) - return handler +func CaptureLogger(t Testing, level slog.Level) (_ log.Logger, ch *CapturingHandler) { + return LoggerWithHandlerMod(t, level, func(h slog.Handler) slog.Handler { + ch = &CapturingHandler{handler: h, Logs: new([]*slog.Record)} + return ch + }), ch +} + +func (c *CapturingHandler) Enabled(context.Context, slog.Level) bool { + // We want to capture all logs, even if the underlying handler only logs + // above a certain level. + return true } -func (c *CapturingHandler) Log(r *log.Record) error { - c.Logs = append(c.Logs, r) - if c.Delegate != nil { - return c.Delegate.Log(r) +func (c *CapturingHandler) Handle(ctx context.Context, r slog.Record) error { + *c.Logs = append(*c.Logs, &r) + if c.handler != nil && c.handler.Enabled(ctx, r.Level) { + return c.handler.Handle(ctx, r) } return nil } +func (c *CapturingHandler) WithAttrs(attrs []slog.Attr) slog.Handler { + // Note: additional attributes won't be visible for captured logs + return &CapturingHandler{ + handler: c.handler.WithAttrs(attrs), + Logs: c.Logs, + } +} + +func (c *CapturingHandler) WithGroup(name string) slog.Handler { + return &CapturingHandler{ + handler: c.handler.WithGroup(name), + Logs: c.Logs, + } +} + func (c *CapturingHandler) Clear() { - c.Logs = nil + *c.Logs = (*c.Logs)[:0] // reuse slice +} + +func NewLevelFilter(level slog.Level) LogFilter { + return func(r *slog.Record) bool { + return r.Level == level + } } -func (c *CapturingHandler) FindLog(lvl log.Lvl, msg string) *HelperRecord { - for _, record := range c.Logs { - if record.Lvl == lvl && record.Msg == msg { +func NewAttributesFilter(key, value string) LogFilter { + return func(r *slog.Record) bool { + found := false + r.Attrs(func(a slog.Attr) bool { + if a.Key == key && a.Value.String() == value { + found = true + return false + } + return true // try next + }) + return found + } +} + +func NewAttributesContainsFilter(key, value string) LogFilter { + return func(r *slog.Record) bool { + found := false + r.Attrs(func(a slog.Attr) bool { + if a.Key == key && strings.Contains(a.Value.String(), value) { + found = true + return false + } + return true // try next + }) + return found + } +} + +func NewMessageFilter(message string) LogFilter { + return func(r *slog.Record) bool { + return r.Message == message + } +} + +func NewMessageContainsFilter(message string) LogFilter { + return func(r *slog.Record) bool { + return strings.Contains(r.Message, message) + } +} + +type LogFilter func(*slog.Record) bool + +func (c *CapturingHandler) FindLog(filters ...LogFilter) *HelperRecord { + for _, record := range *c.Logs { + match := true + for _, filter := range filters { + if !filter(record) { + match = false + break + } + } + if match { return &HelperRecord{record} } } return nil } +func (c *CapturingHandler) FindLogs(filters ...LogFilter) []*HelperRecord { + var logs []*HelperRecord + for _, record := range *c.Logs { + match := true + for _, filter := range filters { + if !filter(record) { + match = false + break + } + } + if match { + logs = append(logs, &HelperRecord{record}) + } + } + return logs +} + type HelperRecord struct { - *log.Record + *slog.Record } -func (h *HelperRecord) GetContextValue(name string) any { - for i := 0; i < len(h.Ctx); i += 2 { - if h.Ctx[i] == name { - return h.Ctx[i+1] +func (h HelperRecord) AttrValue(name string) (v any) { + h.Attrs(func(a slog.Attr) bool { + if a.Key == name { + v = a.Value.Any() + return false } - } - return nil + return true // try next + }) + return } -var _ log.Handler = (*CapturingHandler)(nil) +var _ slog.Handler = (*CapturingHandler)(nil) diff --git a/op-service/testlog/capturing_test.go b/op-service/testlog/capturing_test.go new file mode 100644 index 000000000000..46f6fd175e08 --- /dev/null +++ b/op-service/testlog/capturing_test.go @@ -0,0 +1,60 @@ +package testlog_test + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func TestCaptureLogger(t *testing.T) { + lgr, logs := testlog.CaptureLogger(t, log.LevelInfo) + msg := "foo bar" + lgr.Info(msg, "a", 1) + msgFilter := testlog.NewMessageFilter(msg) + rec := logs.FindLog(msgFilter) + require.Equal(t, msg, rec.Message) + require.EqualValues(t, 1, rec.AttrValue("a")) + + lgr.Debug("bug") + containsFilter := testlog.NewMessageContainsFilter("bug") + l := logs.FindLog(containsFilter) + require.NotNil(t, l, "should capture all logs, not only above level") + + msgClear := "clear" + lgr.Error(msgClear) + levelFilter := testlog.NewLevelFilter(log.LevelError) + msgFilter = testlog.NewMessageFilter(msgClear) + require.NotNil(t, logs.FindLog(levelFilter, msgFilter)) + logs.Clear() + containsFilter = testlog.NewMessageContainsFilter(msgClear) + l = logs.FindLog(containsFilter) + require.Nil(t, l) + + lgrb := lgr.New("b", 2) + msgOp := "optimistic" + lgrb.Info(msgOp, "c", 3) + containsFilter = testlog.NewMessageContainsFilter(msgOp) + recOp := logs.FindLog(containsFilter) + require.NotNil(t, recOp, "should still capture logs from derived logger") + require.EqualValues(t, 3, recOp.AttrValue("c")) + // Note: "b" attributes won't be visible on captured record +} + +func TestCaptureLoggerAttributesFilter(t *testing.T) { + lgr, logs := testlog.CaptureLogger(t, log.LevelInfo) + msg := "foo bar" + lgr.Info(msg, "a", "test") + lgr.Info(msg, "a", "test 2") + lgr.Info(msg, "a", "random") + msgFilter := testlog.NewMessageFilter(msg) + attrFilter := testlog.NewAttributesFilter("a", "random") + + rec := logs.FindLog(msgFilter, attrFilter) + require.Equal(t, msg, rec.Message) + require.EqualValues(t, "random", rec.AttrValue("a")) + + recs := logs.FindLogs(msgFilter, attrFilter) + require.Len(t, recs, 1) +} diff --git a/op-service/testlog/testlog.go b/op-service/testlog/testlog.go index d3e3c8b04447..0ff544225599 100644 --- a/op-service/testlog/testlog.go +++ b/op-service/testlog/testlog.go @@ -18,12 +18,17 @@ package testlog import ( + "bufio" + "bytes" + "context" "os" "runtime" "strconv" "strings" "sync" + "golang.org/x/exp/slog" + "github.com/ethereum/go-ethereum/log" ) @@ -42,52 +47,32 @@ type Testing interface { Helper() } -// Handler returns a log handler which logs to the unit test log of t. -func Handler(t Testing, level log.Lvl, format log.Format) log.Handler { - return log.LvlFilterHandler(level, &handler{t, format}) -} - -type handler struct { - t Testing - fmt log.Format -} - -func (h *handler) Log(r *log.Record) error { - h.t.Logf("%s", h.fmt.Format(r)) - return nil -} - // logger implements log.Logger such that all output goes to the unit test log via // t.Logf(). All methods in between logger.Trace, logger.Debug, etc. are marked as test // 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 - l log.Logger - mu *sync.Mutex - h *bufHandler + t Testing + l log.Logger + mu *sync.Mutex + buf *bytes.Buffer } -type bufHandler struct { - buf []*log.Record - fmt log.Format +// Logger returns a logger which logs to the unit test log of t. +func Logger(t Testing, level slog.Level) log.Logger { + return LoggerWithHandlerMod(t, level, func(h slog.Handler) slog.Handler { return h }) } -func (h *bufHandler) Log(r *log.Record) error { - h.buf = append(h.buf, r) - return nil +func LoggerWithHandlerMod(t Testing, level slog.Level, handlerMod func(slog.Handler) slog.Handler) log.Logger { + l := &logger{t: t, mu: new(sync.Mutex), buf: new(bytes.Buffer)} + var handler slog.Handler = log.NewTerminalHandlerWithLevel(l.buf, level, useColorInTestLog) + handler = handlerMod(handler) + l.l = log.NewLogger(handler) + return l } -// Logger returns a logger which logs to the unit test log of t. -func Logger(t Testing, level log.Lvl) log.Logger { - l := &logger{ - t: t, - l: log.New(), - mu: new(sync.Mutex), - h: &bufHandler{fmt: log.TerminalFormat(useColorInTestLog)}, - } - l.l.SetHandler(log.LvlFilterHandler(level, l.h)) - return l +func (l *logger) Handler() slog.Handler { + return l.l.Handler() } func (l *logger) Trace(msg string, ctx ...any) { @@ -138,16 +123,28 @@ func (l *logger) Crit(msg string, ctx ...any) { l.flush() } +func (l *logger) Log(level slog.Level, msg string, ctx ...any) { + l.t.Helper() + l.mu.Lock() + defer l.mu.Unlock() + l.l.Log(level, msg, ctx...) + l.flush() +} + +func (l *logger) Write(level slog.Level, msg string, ctx ...any) { + l.Log(level, msg, ctx...) +} + func (l *logger) New(ctx ...any) log.Logger { - return &logger{l.t, l.l.New(ctx...), l.mu, l.h} + return &logger{l.t, l.l.New(ctx...), l.mu, l.buf} } -func (l *logger) GetHandler() log.Handler { - return l.l.GetHandler() +func (l *logger) With(ctx ...any) log.Logger { + return l.New(ctx...) } -func (l *logger) SetHandler(h log.Handler) { - l.l.SetHandler(h) +func (l *logger) Enabled(ctx context.Context, level slog.Level) bool { + return l.l.Enabled(ctx, level) } // flush writes all buffered messages and clears the buffer. @@ -160,10 +157,12 @@ func (l *logger) flush() { if decorationLen <= padLength { padding = padLength - decorationLen } - for _, r := range l.h.buf { - l.t.Logf("%*s%s", padding, "", l.h.fmt.Format(r)) + + scanner := bufio.NewScanner(l.buf) + for scanner.Scan() { + l.t.Logf("%*s%s", padding, "", scanner.Text()) } - l.h.buf = nil + l.buf.Reset() } // The Go testing lib uses the runtime package to get info about the calling site, and then decorates the line. diff --git a/op-service/testutils/mock_blobs_fetcher.go b/op-service/testutils/mock_blobs_fetcher.go new file mode 100644 index 000000000000..df09f5f46a23 --- /dev/null +++ b/op-service/testutils/mock_blobs_fetcher.go @@ -0,0 +1,34 @@ +package testutils + +import ( + "context" + + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/stretchr/testify/mock" +) + +type MockBlobsFetcher struct { + mock.Mock +} + +func (cl *MockBlobsFetcher) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) { + out := cl.Mock.MethodCalled("GetBlobs", ref, hashes) + return out.Get(0).([]*eth.Blob), out.Error(1) +} + +func (cl *MockBlobsFetcher) ExpectOnGetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash, blobs []*eth.Blob, err error) { + cl.Mock.On("GetBlobs", ref, hashes).Once().Return(blobs, err) +} + +func (cl *MockBlobsFetcher) GetBlobSidecars(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.BlobSidecar, error) { + out := cl.Mock.MethodCalled("GetBlobSidecars", ref, hashes) + return out.Get(0).([]*eth.BlobSidecar), out.Error(1) +} + +func (cl *MockBlobsFetcher) ExpectOnGetBlobSidecars(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash, commitment eth.Bytes48, blobs []*eth.Blob, err error) { + cl.Mock.On("GetBlobSidecars", ref, hashes).Once().Return([]*eth.BlobSidecar{{ + Blob: *blobs[0], + Index: eth.Uint64String(hashes[0].Index), + KZGCommitment: commitment, + }}, err) +} diff --git a/op-service/testutils/mock_engine.go b/op-service/testutils/mock_engine.go index b6bfa5d98f5b..99dadf534ec4 100644 --- a/op-service/testutils/mock_engine.go +++ b/op-service/testutils/mock_engine.go @@ -12,8 +12,8 @@ type MockEngine struct { MockL2Client } -func (m *MockEngine) GetPayload(ctx context.Context, payloadId eth.PayloadID) (*eth.ExecutionPayloadEnvelope, error) { - out := m.Mock.Called(payloadId) +func (m *MockEngine) GetPayload(ctx context.Context, payloadInfo eth.PayloadInfo) (*eth.ExecutionPayloadEnvelope, error) { + out := m.Mock.Called(payloadInfo.ID) return out.Get(0).(*eth.ExecutionPayloadEnvelope), out.Error(1) } diff --git a/op-service/testutils/random.go b/op-service/testutils/random.go index 092b881bacd4..f13fb2fc658d 100644 --- a/op-service/testutils/random.go +++ b/op-service/testutils/random.go @@ -106,7 +106,7 @@ func NextRandomL2Ref(rng *rand.Rand, l2BlockTime uint64, parent eth.L2BlockRef, // Output is deterministic when the supplied rng generates the same random sequence. func InsecureRandomKey(rng *rand.Rand) *ecdsa.PrivateKey { idx := rng.Intn(len(randomEcdsaKeys)) - key, err := crypto.ToECDSA(common.Hex2Bytes(randomEcdsaKeys[idx])) + key, err := crypto.ToECDSA(common.FromHex(randomEcdsaKeys[idx])) if err != nil { // Should never happen because the list of keys is hard coded and known to be valid. panic(fmt.Errorf("invalid pre-generated ecdsa key at index %v: %w", idx, err)) diff --git a/op-service/txmgr/cli.go b/op-service/txmgr/cli.go index e3d0ff2ec39f..4d1069e522fa 100644 --- a/op-service/txmgr/cli.go +++ b/op-service/txmgr/cli.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "math" "math/big" "time" @@ -58,6 +59,8 @@ type DefaultFlagValues struct { SafeAbortNonceTooLowCount uint64 FeeLimitMultiplier uint64 FeeLimitThresholdGwei float64 + MinTipCapGwei float64 + MinBaseFeeGwei float64 ResubmissionTimeout time.Duration NetworkTimeout time.Duration TxSendTimeout time.Duration @@ -71,6 +74,8 @@ var ( SafeAbortNonceTooLowCount: uint64(3), FeeLimitMultiplier: uint64(5), FeeLimitThresholdGwei: 100.0, + MinTipCapGwei: 1.0, + MinBaseFeeGwei: 1.0, ResubmissionTimeout: 48 * time.Second, NetworkTimeout: 10 * time.Second, TxSendTimeout: 0 * time.Second, @@ -82,6 +87,8 @@ var ( SafeAbortNonceTooLowCount: uint64(3), FeeLimitMultiplier: uint64(5), FeeLimitThresholdGwei: 100.0, + MinTipCapGwei: 1.0, + MinBaseFeeGwei: 1.0, ResubmissionTimeout: 24 * time.Second, NetworkTimeout: 10 * time.Second, TxSendTimeout: 2 * time.Minute, @@ -138,16 +145,18 @@ func CLIFlagsWithDefaults(envPrefix string, defaults DefaultFlagValues) []cli.Fl Value: defaults.FeeLimitThresholdGwei, EnvVars: prefixEnvVars("TXMGR_FEE_LIMIT_THRESHOLD"), }, - &cli.Float64Flag{ - Name: MinBaseFeeFlagName, - Usage: "Enforces a minimum base fee (in GWei) to assume when determining tx fees. Off by default.", - EnvVars: prefixEnvVars("TXMGR_MIN_BASEFEE"), - }, &cli.Float64Flag{ Name: MinTipCapFlagName, - Usage: "Enforces a minimum tip cap (in GWei) to use when determining tx fees. Off by default.", + Usage: "Enforces a minimum tip cap (in GWei) to use when determining tx fees. 1 GWei by default.", + Value: defaults.MinTipCapGwei, EnvVars: prefixEnvVars("TXMGR_MIN_TIP_CAP"), }, + &cli.Float64Flag{ + Name: MinBaseFeeFlagName, + Usage: "Enforces a minimum base fee (in GWei) to assume when determining tx fees. 1 GWei by default.", + Value: defaults.MinBaseFeeGwei, + EnvVars: prefixEnvVars("TXMGR_MIN_BASEFEE"), + }, &cli.DurationFlag{ Name: ResubmissionTimeoutFlagName, Usage: "Duration we will wait before resubmitting a transaction to L1", @@ -209,6 +218,8 @@ func NewCLIConfig(l1RPCURL string, defaults DefaultFlagValues) CLIConfig { SafeAbortNonceTooLowCount: defaults.SafeAbortNonceTooLowCount, FeeLimitMultiplier: defaults.FeeLimitMultiplier, FeeLimitThresholdGwei: defaults.FeeLimitThresholdGwei, + MinTipCapGwei: defaults.MinTipCapGwei, + MinBaseFeeGwei: defaults.MinBaseFeeGwei, ResubmissionTimeout: defaults.ResubmissionTimeout, NetworkTimeout: defaults.NetworkTimeout, TxSendTimeout: defaults.TxSendTimeout, @@ -399,6 +410,13 @@ type Config struct { From common.Address } +func SafeConvertUInt64ToUInt32(val uint64) (uint32, bool) { + if val <= math.MaxUint32 { + return uint32(val), true + } + return 0, false +} + func (m Config) Check() error { if m.Backend == nil { return errors.New("must provide the Backend") diff --git a/op-service/txmgr/mocks/TxManager.go b/op-service/txmgr/mocks/TxManager.go index 330e4bccdfc5..a5c6f584537e 100644 --- a/op-service/txmgr/mocks/TxManager.go +++ b/op-service/txmgr/mocks/TxManager.go @@ -64,6 +64,20 @@ func (_m *TxManager) From() common.Address { return r0 } +// IsClosed provides a mock function with given fields: +func (_m *TxManager) IsClosed() bool { + ret := _m.Called() + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + // Send provides a mock function with given fields: ctx, candidate func (_m *TxManager) Send(ctx context.Context, candidate txmgr.TxCandidate) (*types.Receipt, error) { ret := _m.Called(ctx, candidate) diff --git a/op-service/txmgr/price_bump_test.go b/op-service/txmgr/price_bump_test.go index ca74b4a620b9..37d55be4fba0 100644 --- a/op-service/txmgr/price_bump_test.go +++ b/op-service/txmgr/price_bump_test.go @@ -24,7 +24,7 @@ type priceBumpTest struct { func (tc *priceBumpTest) run(t *testing.T) { prevFC := calcGasFeeCap(big.NewInt(tc.prevBaseFee), big.NewInt(tc.prevGasTip)) - lgr := testlog.Logger(t, log.LvlCrit) + lgr := testlog.Logger(t, log.LevelCrit) tip, fc := updateFees(big.NewInt(tc.prevGasTip), prevFC, big.NewInt(tc.newGasTip), big.NewInt(tc.newBaseFee), tc.isBlobTx, lgr) diff --git a/op-service/txmgr/queue.go b/op-service/txmgr/queue.go index d71398ae4b4b..cf83b00d5f8a 100644 --- a/op-service/txmgr/queue.go +++ b/op-service/txmgr/queue.go @@ -29,7 +29,7 @@ type Queue[T any] struct { // NewQueue creates a new transaction sending Queue, with the following parameters: // - ctx: runtime context of the queue. If canceled, all ongoing send processes are canceled. -// - txMgt: transaction managre to use for transaction sending +// - txMgr: transaction manager to use for transaction sending // - maxPending: max number of pending txs at once (0 == no limit) func NewQueue[T any](ctx context.Context, txMgr TxManager, maxPending uint64) *Queue[T] { if maxPending > math.MaxInt { diff --git a/op-service/txmgr/queue_test.go b/op-service/txmgr/queue_test.go index db953fc5173a..e0b65d32fd09 100644 --- a/op-service/txmgr/queue_test.go +++ b/op-service/txmgr/queue_test.go @@ -158,7 +158,7 @@ func TestQueue_Send(t *testing.T) { {}, }, nonces: []uint64{0, 1}, - total: 3 * time.Second, + total: 1 * time.Second, }, } for _, test := range testCases { @@ -176,7 +176,7 @@ func TestQueue_Send(t *testing.T) { name: "TEST", cfg: conf, backend: backend, - l: testlog.Logger(t, log.LvlCrit), + l: testlog.Logger(t, log.LevelCrit), metr: &metrics.NoopTxMetrics{}, } diff --git a/op-service/txmgr/send_state.go b/op-service/txmgr/send_state.go index e1878c64f9dd..7ccc52b2e151 100644 --- a/op-service/txmgr/send_state.go +++ b/op-service/txmgr/send_state.go @@ -1,7 +1,7 @@ package txmgr import ( - "strings" + "errors" "sync" "time" @@ -9,6 +9,17 @@ import ( "github.com/ethereum/go-ethereum/core" ) +var ( + // Returned by CriticalError when there is an incompatible tx type already in the mempool. + // geth defines this error as txpool.ErrAlreadyReserved in v1.13.14 so we can remove this + // declaration once op-geth is updated to this version. + ErrAlreadyReserved = errors.New("address already reserved") + + // Returned by CriticalError when the system is unable to get the tx into the mempool in the + // alloted time + ErrMempoolDeadlineExpired = errors.New("failed to get tx into the mempool") +) + // SendState tracks information about the publication state of a given txn. In // this context, a txn may correspond to multiple different txn hashes due to // varying gas prices, though we treat them all as the same logical txn. This @@ -27,6 +38,9 @@ type SendState struct { successFullPublishCount uint64 // nil error => tx made it to the mempool safeAbortNonceTooLowCount uint64 // nonce too low error + // Whether any attempt to send the tx resulted in ErrAlreadyReserved + alreadyReserved bool + // Miscellaneous tracking bumpCount int // number of times we have bumped the gas price } @@ -60,8 +74,10 @@ func (s *SendState) ProcessSendError(err error) { switch { case err == nil: s.successFullPublishCount++ - case strings.Contains(err.Error(), core.ErrNonceTooLow.Error()): + case errStringMatch(err, core.ErrNonceTooLow): s.nonceTooLowCount++ + case errStringMatch(err, ErrAlreadyReserved): + s.alreadyReserved = true } } @@ -93,27 +109,29 @@ func (s *SendState) TxNotMined(txHash common.Hash) { } } -// ShouldAbortImmediately returns true if the txmgr should give up on trying a -// given txn with the target nonce. -// This occurs when the set of errors recorded indicates that no further progress can be made -// on this transaction. -func (s *SendState) ShouldAbortImmediately() bool { +// CriticalError returns a non-nil error if the txmgr should give up on trying a given txn with the +// target nonce. This occurs when the set of errors recorded indicates that no further progress +// can be made on this transaction, or if there is an incompatible tx type currently in the +// mempool. +func (s *SendState) CriticalError() error { s.mu.RLock() defer s.mu.RUnlock() - // Never abort if our latest sample reports having at least one mined txn. - if len(s.minedTxs) > 0 { - return false - } - - // If we have exceeded the nonce too low count, abort - if s.nonceTooLowCount >= s.safeAbortNonceTooLowCount || - // If we have not published a transaction in the allotted time, abort - (s.successFullPublishCount == 0 && s.now().After(s.txInMempoolDeadline)) { - return true + switch { + case len(s.minedTxs) > 0: + // Never abort if our latest sample reports having at least one mined txn. + return nil + case s.nonceTooLowCount >= s.safeAbortNonceTooLowCount: + // we have exceeded the nonce too low count + return core.ErrNonceTooLow + case s.successFullPublishCount == 0 && s.now().After(s.txInMempoolDeadline): + // unable to get the tx into the mempool in the alloted time + return ErrMempoolDeadlineExpired + case s.alreadyReserved: + // incompatible tx type in mempool + return ErrAlreadyReserved } - - return false + return nil } // IsWaitingForConfirmation returns true if we have at least one confirmation on diff --git a/op-service/txmgr/send_state_test.go b/op-service/txmgr/send_state_test.go index 53ca3ee48c28..20bfe155ed97 100644 --- a/op-service/txmgr/send_state_test.go +++ b/op-service/txmgr/send_state_test.go @@ -1,4 +1,4 @@ -package txmgr_test +package txmgr import ( "errors" @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" ) @@ -18,15 +17,15 @@ var ( const testSafeAbortNonceTooLowCount = 3 -func newSendState() *txmgr.SendState { +func newSendState() *SendState { return newSendStateWithTimeout(time.Hour, time.Now) } -func newSendStateWithTimeout(t time.Duration, now func() time.Time) *txmgr.SendState { - return txmgr.NewSendStateWithNow(testSafeAbortNonceTooLowCount, t, now) +func newSendStateWithTimeout(t time.Duration, now func() time.Time) *SendState { + return NewSendStateWithNow(testSafeAbortNonceTooLowCount, t, now) } -func processNSendErrors(sendState *txmgr.SendState, err error, n int) { +func processNSendErrors(sendState *SendState, err error, n int) { for i := 0; i < n; i++ { sendState.ProcessSendError(err) } @@ -36,7 +35,7 @@ func processNSendErrors(sendState *txmgr.SendState, err error, n int) { // trigger an abort even after the safe abort interval has elapsed. func TestSendStateNoAbortAfterInit(t *testing.T) { sendState := newSendState() - require.False(t, sendState.ShouldAbortImmediately()) + require.Nil(t, sendState.CriticalError()) require.False(t, sendState.IsWaitingForConfirmation()) } @@ -46,7 +45,7 @@ func TestSendStateNoAbortAfterProcessNilError(t *testing.T) { sendState := newSendState() processNSendErrors(sendState, nil, testSafeAbortNonceTooLowCount) - require.False(t, sendState.ShouldAbortImmediately()) + require.Nil(t, sendState.CriticalError()) } // TestSendStateNoAbortAfterProcessOtherError asserts that non-nil errors other @@ -56,7 +55,7 @@ func TestSendStateNoAbortAfterProcessOtherError(t *testing.T) { otherError := errors.New("other error") processNSendErrors(sendState, otherError, testSafeAbortNonceTooLowCount) - require.False(t, sendState.ShouldAbortImmediately()) + require.Nil(t, sendState.CriticalError()) } // TestSendStateAbortSafelyAfterNonceTooLowButNoTxMined asserts that we will @@ -65,11 +64,11 @@ func TestSendStateAbortSafelyAfterNonceTooLowButNoTxMined(t *testing.T) { sendState := newSendState() sendState.ProcessSendError(core.ErrNonceTooLow) - require.False(t, sendState.ShouldAbortImmediately()) + require.Nil(t, sendState.CriticalError()) sendState.ProcessSendError(core.ErrNonceTooLow) - require.False(t, sendState.ShouldAbortImmediately()) + require.Nil(t, sendState.CriticalError()) sendState.ProcessSendError(core.ErrNonceTooLow) - require.True(t, sendState.ShouldAbortImmediately()) + require.ErrorIs(t, sendState.CriticalError(), core.ErrNonceTooLow) } // TestSendStateMiningTxCancelsAbort asserts that a tx getting mined after @@ -80,9 +79,9 @@ func TestSendStateMiningTxCancelsAbort(t *testing.T) { sendState.ProcessSendError(core.ErrNonceTooLow) sendState.ProcessSendError(core.ErrNonceTooLow) sendState.TxMined(testHash) - require.False(t, sendState.ShouldAbortImmediately()) + require.Nil(t, sendState.CriticalError()) sendState.ProcessSendError(core.ErrNonceTooLow) - require.False(t, sendState.ShouldAbortImmediately()) + require.Nil(t, sendState.CriticalError()) } // TestSendStateReorgingTxResetsAbort asserts that unmining a tx does not @@ -96,7 +95,7 @@ func TestSendStateReorgingTxResetsAbort(t *testing.T) { sendState.TxMined(testHash) sendState.TxNotMined(testHash) sendState.ProcessSendError(core.ErrNonceTooLow) - require.False(t, sendState.ShouldAbortImmediately()) + require.Nil(t, sendState.CriticalError()) } // TestSendStateNoAbortEvenIfNonceTooLowAfterTxMined asserts that we will not @@ -112,7 +111,7 @@ func TestSendStateNoAbortEvenIfNonceTooLowAfterTxMined(t *testing.T) { processNSendErrors( sendState, core.ErrNonceTooLow, testSafeAbortNonceTooLowCount, ) - require.False(t, sendState.ShouldAbortImmediately()) + require.Nil(t, sendState.CriticalError()) } // TestSendStateSafeAbortIfNonceTooLowPersistsAfterUnmine asserts that we will @@ -125,9 +124,9 @@ func TestSendStateSafeAbortIfNonceTooLowPersistsAfterUnmine(t *testing.T) { sendState.TxNotMined(testHash) sendState.ProcessSendError(core.ErrNonceTooLow) sendState.ProcessSendError(core.ErrNonceTooLow) - require.False(t, sendState.ShouldAbortImmediately()) + require.Nil(t, sendState.CriticalError()) sendState.ProcessSendError(core.ErrNonceTooLow) - require.True(t, sendState.ShouldAbortImmediately()) + require.ErrorIs(t, sendState.CriticalError(), core.ErrNonceTooLow) } // TestSendStateSafeAbortWhileCallingNotMinedOnUnminedTx asserts that we will @@ -140,7 +139,7 @@ func TestSendStateSafeAbortWhileCallingNotMinedOnUnminedTx(t *testing.T) { sendState, core.ErrNonceTooLow, testSafeAbortNonceTooLowCount, ) sendState.TxNotMined(testHash) - require.True(t, sendState.ShouldAbortImmediately()) + require.ErrorIs(t, sendState.CriticalError(), core.ErrNonceTooLow) } // TestSendStateIsWaitingForConfirmationAfterTxMined asserts that we are waiting @@ -179,7 +178,7 @@ func stepClock(step time.Duration) func() time.Time { // when no successful transactions have been recorded func TestSendStateTimeoutAbort(t *testing.T) { sendState := newSendStateWithTimeout(10*time.Millisecond, stepClock(20*time.Millisecond)) - require.True(t, sendState.ShouldAbortImmediately(), "Should abort after timing out") + require.ErrorIs(t, sendState.CriticalError(), ErrMempoolDeadlineExpired, "Should abort after timing out") } // TestSendStateNoTimeoutAbortIfPublishedTx ensure that this will not abort if there is @@ -187,5 +186,5 @@ func TestSendStateTimeoutAbort(t *testing.T) { func TestSendStateNoTimeoutAbortIfPublishedTx(t *testing.T) { sendState := newSendStateWithTimeout(10*time.Millisecond, stepClock(20*time.Millisecond)) sendState.ProcessSendError(nil) - require.False(t, sendState.ShouldAbortImmediately(), "Should not abort if published transaction successfully") + require.Nil(t, sendState.CriticalError(), "Should not abort if published transaction successfully") } diff --git a/op-service/txmgr/txmgr.go b/op-service/txmgr/txmgr.go index 195ab14b9041..f2aa7d8f54ad 100644 --- a/op-service/txmgr/txmgr.go +++ b/op-service/txmgr/txmgr.go @@ -22,6 +22,7 @@ import ( "github.com/holiman/uint256" "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/retry" "github.com/ethereum-optimism/optimism/op-service/txmgr/metrics" ) @@ -59,6 +60,10 @@ type TxManager interface { // may be included on L1 even if the context is cancelled. // // NOTE: Send can be called concurrently, the nonce will be managed internally. + // + // Callers using both Blob and non-Blob transactions should check to see if the returned error + // is ErrAlreadyReserved, which indicates an incompatible transaction may be stuck in the + // mempool and is in need of replacement or cancellation. Send(ctx context.Context, candidate TxCandidate) (*types.Receipt, error) // From returns the sending address associated with the instance of the transaction manager. @@ -70,6 +75,7 @@ type TxManager interface { // Close the underlying connection Close() + IsClosed() bool } // ETHBackend is the set of methods that the transaction manager uses to resubmit gas & determine @@ -170,7 +176,7 @@ func (m *SimpleTxManager) txLogger(tx *types.Transaction, logGas bool) log.Logge } if len(tx.BlobHashes()) != 0 { // log the number of blobs a tx has only if it's a blob tx - fields = append(fields, "blobs", len(tx.BlobHashes())) + fields = append(fields, "blobs", len(tx.BlobHashes()), "blobFeeCap", tx.BlobGasFeeCap()) } return m.l.New(fields...) } @@ -223,6 +229,7 @@ func (m *SimpleTxManager) send(ctx context.Context, candidate TxCandidate) (*typ ctx, cancel = context.WithTimeout(ctx, m.cfg.TxSendTimeout) defer cancel() } + tx, err := retry.Do(ctx, 30, retry.Fixed(2*time.Second), func() (*types.Transaction, error) { if m.closed.Load() { return nil, ErrClosed @@ -245,6 +252,7 @@ func (m *SimpleTxManager) send(ctx context.Context, candidate TxCandidate) (*typ // NOTE: If the [TxCandidate.GasLimit] is non-zero, it will be used as the transaction's gas. // NOTE: Otherwise, the [SimpleTxManager] will query the specified backend for an estimate. func (m *SimpleTxManager) craftTx(ctx context.Context, candidate TxCandidate) (*types.Transaction, error) { + m.l.Debug("crafting Transaction", "blobs", len(candidate.Blobs), "calldata_size", len(candidate.TxData)) gasTipCap, baseFee, blobBaseFee, err := m.suggestGasPriceCaps(ctx) if err != nil { m.metr.RPCError() @@ -277,7 +285,7 @@ func (m *SimpleTxManager) craftTx(ctx context.Context, candidate TxCandidate) (* if candidate.To == nil { return nil, errors.New("blob txs cannot deploy contracts") } - if sidecar, blobHashes, err = makeSidecar(candidate.Blobs); err != nil { + if sidecar, blobHashes, err = MakeSidecar(candidate.Blobs); err != nil { return nil, fmt.Errorf("failed to make sidecar: %w", err) } } @@ -314,9 +322,9 @@ func (m *SimpleTxManager) craftTx(ctx context.Context, candidate TxCandidate) (* } -// makeSidecar builds & returns the BlobTxSidecar and corresponding blob hashes from the raw blob +// MakeSidecar builds & returns the BlobTxSidecar and corresponding blob hashes from the raw blob // data. -func makeSidecar(blobs []*eth.Blob) (*types.BlobTxSidecar, []common.Hash, error) { +func MakeSidecar(blobs []*eth.Blob) (*types.BlobTxSidecar, []common.Hash, error) { sidecar := &types.BlobTxSidecar{} blobHashes := []common.Hash{} for i, blob := range blobs { @@ -420,17 +428,16 @@ func (m *SimpleTxManager) sendTx(ctx context.Context, tx *types.Transaction) (*t defer ticker.Stop() for { + if err := sendState.CriticalError(); err != nil { + m.txLogger(tx, false).Warn("Aborting transaction submission", "err", err) + return nil, fmt.Errorf("aborted tx send due to critical error: %w", err) + } select { case <-ticker.C: // Don't resubmit a transaction if it has been mined, but we are waiting for the conf depth. if sendState.IsWaitingForConfirmation() { continue } - // If we see lots of unrecoverable errors (and no pending transactions) abort sending the transaction. - if sendState.ShouldAbortImmediately() { - m.txLogger(tx, false).Warn("Aborting transaction submission") - return nil, errors.New("aborted transaction sending") - } // if the tx manager closed while we were waiting for the tx, give up if m.closed.Load() { m.txLogger(tx, false).Warn("TxManager closed, aborting transaction submission") @@ -489,14 +496,19 @@ func (m *SimpleTxManager) publishTx(ctx context.Context, tx *types.Transaction, if err == nil { m.metr.TxPublished("") - log.Info("Transaction successfully published") + l.Info("Transaction successfully published") return tx, true } switch { + case errStringMatch(err, ErrAlreadyReserved): + // this can happen if, say, a blob transaction is stuck in the mempool and we try to + // send a non-blob transaction (and vice-versa). + l.Warn("txpool contains pending tx of incompatible type", "err", err) + m.metr.TxPublished("pending_tx_of_incompatible_type") case errStringMatch(err, core.ErrNonceTooLow): l.Warn("nonce too low", "err", err) - m.metr.TxPublished("nonce_to_low") + m.metr.TxPublished("nonce_too_low") case errStringMatch(err, context.Canceled): m.metr.RPCError() l.Warn("transaction send cancelled", "err", err) @@ -650,7 +662,10 @@ func (m *SimpleTxManager) increaseGasPrice(ctx context.Context, tx *types.Transa return nil, err } if tx.Gas() != gas { - m.l.Info("re-estimated gas differs", "tx", tx.Hash(), "oldgas", tx.Gas(), "newgas", gas, + // non-determinism in gas limit estimation happens regularly due to underlying state + // changes across calls, and is even more common now that geth uses an in-exact estimation + // approach as of v1.13.6. + m.l.Debug("re-estimated gas differs", "tx", tx.Hash(), "oldgas", tx.Gas(), "newgas", gas, "gasFeeCap", bumpedFee, "gasTipCap", bumpedTip) } @@ -743,23 +758,29 @@ func (m *SimpleTxManager) suggestGasPriceCaps(ctx context.Context) (*big.Int, *b return tip, baseFee, blobFee, nil } -func (m *SimpleTxManager) checkLimits(tip, baseFee, bumpedTip, bumpedFee *big.Int) error { - // If below threshold, don't apply multiplier limit - if thr := m.cfg.FeeLimitThreshold; thr != nil && thr.Cmp(bumpedFee) == 1 { - return nil +// checkLimits checks that the tip and baseFee have not increased by more than the configured multipliers +// if FeeLimitThreshold is specified in config, any increase which stays under the threshold are allowed +func (m *SimpleTxManager) checkLimits(tip, baseFee, bumpedTip, bumpedFee *big.Int) (errs error) { + threshold := m.cfg.FeeLimitThreshold + limit := big.NewInt(int64(m.cfg.FeeLimitMultiplier)) + maxTip := new(big.Int).Mul(tip, limit) + maxFee := calcGasFeeCap(new(big.Int).Mul(baseFee, limit), maxTip) + + // generic check function to check tip and fee, and build up an error + check := func(v, max *big.Int, name string) { + // if threshold is specified and the value is under the threshold, no need to check the max + if threshold != nil && threshold.Cmp(v) > 0 { + return + } + // if the value is over the max, add an error message + if v.Cmp(max) > 0 { + errs = errors.Join(errs, fmt.Errorf("bumped %s cap %v is over %dx multiple of the suggested value", name, v, limit)) + } } + check(bumpedTip, maxTip, "tip") + check(bumpedFee, maxFee, "fee") - // Make sure increase is at most [FeeLimitMultiplier] the suggested values - feeLimitMult := big.NewInt(int64(m.cfg.FeeLimitMultiplier)) - maxTip := new(big.Int).Mul(tip, feeLimitMult) - if bumpedTip.Cmp(maxTip) > 0 { - return fmt.Errorf("bumped tip cap %v is over %dx multiple of the suggested value", bumpedTip, m.cfg.FeeLimitMultiplier) - } - maxFee := calcGasFeeCap(new(big.Int).Mul(baseFee, feeLimitMult), maxTip) - if bumpedFee.Cmp(maxFee) > 0 { - return fmt.Errorf("bumped fee cap %v is over %dx multiple of the suggested value", bumpedFee, m.cfg.FeeLimitMultiplier) - } - return nil + return errs } func (m *SimpleTxManager) checkBlobFeeLimits(blobBaseFee, bumpedBlobFee *big.Int) error { @@ -777,6 +798,11 @@ func (m *SimpleTxManager) checkBlobFeeLimits(blobBaseFee, bumpedBlobFee *big.Int return nil } +// IsClosed returns true if the tx manager is closed. +func (m *SimpleTxManager) IsClosed() bool { + return m.closed.Load() +} + // calcThresholdValue returns ceil(x * priceBumpPercent / 100) for non-blob txs, or // ceil(x * blobPriceBumpPercent / 100) for blob txs. // It guarantees that x is increased by at least 1 diff --git a/op-service/txmgr/txmgr_test.go b/op-service/txmgr/txmgr_test.go index b316acc4fc32..e404ea9de761 100644 --- a/op-service/txmgr/txmgr_test.go +++ b/op-service/txmgr/txmgr_test.go @@ -2,6 +2,7 @@ package txmgr import ( "context" + "crypto/rand" "errors" "fmt" "math/big" @@ -60,7 +61,7 @@ func newTestHarnessWithConfig(t *testing.T, cfg Config) *testHarness { name: "TEST", cfg: cfg, backend: cfg.Backend, - l: testlog.Logger(t, log.LvlCrit), + l: testlog.Logger(t, log.LevelCrit), metr: &metrics.NoopTxMetrics{}, } @@ -391,6 +392,23 @@ func TestTxMgrNeverConfirmCancel(t *testing.T) { require.Nil(t, receipt) } +// TestAlreadyReserved tests that AlreadyReserved error results in immediate abort of transaction +// sending. +func TestAlreadyReserved(t *testing.T) { + conf := configWithNumConfs(1) + h := newTestHarnessWithConfig(t, conf) + + sendTx := func(ctx context.Context, tx *types.Transaction) error { + return ErrAlreadyReserved + } + h.backend.setTxSender(sendTx) + + _, err := h.mgr.Send(context.Background(), TxCandidate{ + To: &common.Address{}, + }) + require.ErrorIs(t, err, ErrAlreadyReserved) +} + // TestTxMgrConfirmsAtMaxGasPrice asserts that Send properly returns the max gas // price receipt if none of the lower gas price txs were mined. func TestTxMgrConfirmsAtHigherGasPrice(t *testing.T) { @@ -827,7 +845,7 @@ func TestWaitMinedMultipleConfs(t *testing.T) { func TestManagerErrsOnZeroCLIConfs(t *testing.T) { t.Parallel() - _, err := NewSimpleTxManager("TEST", testlog.Logger(t, log.LvlCrit), &metrics.NoopTxMetrics{}, CLIConfig{}) + _, err := NewSimpleTxManager("TEST", testlog.Logger(t, log.LevelCrit), &metrics.NoopTxMetrics{}, CLIConfig{}) require.Error(t, err) } @@ -836,7 +854,7 @@ func TestManagerErrsOnZeroCLIConfs(t *testing.T) { func TestManagerErrsOnZeroConfs(t *testing.T) { t.Parallel() - _, err := NewSimpleTxManagerFromConfig("TEST", testlog.Logger(t, log.LvlCrit), &metrics.NoopTxMetrics{}, Config{}) + _, err := NewSimpleTxManagerFromConfig("TEST", testlog.Logger(t, log.LevelCrit), &metrics.NoopTxMetrics{}, Config{}) require.Error(t, err) } @@ -939,7 +957,7 @@ func TestWaitMinedReturnsReceiptAfterFailure(t *testing.T) { }, name: "TEST", backend: &borkedBackend, - l: testlog.Logger(t, log.LvlCrit), + l: testlog.Logger(t, log.LevelCrit), metr: &metrics.NoopTxMetrics{}, } @@ -956,7 +974,7 @@ func TestWaitMinedReturnsReceiptAfterFailure(t *testing.T) { require.Equal(t, receipt.TxHash, txHash) } -func doGasPriceIncrease(t *testing.T, txTipCap, txFeeCap, newTip, newBaseFee int64) (*types.Transaction, *types.Transaction) { +func doGasPriceIncrease(t *testing.T, txTipCap, txFeeCap, newTip, newBaseFee int64) (*types.Transaction, *types.Transaction, error) { borkedBackend := failingBackend{ gasTip: big.NewInt(newTip), baseFee: big.NewInt(newBaseFee), @@ -977,7 +995,7 @@ func doGasPriceIncrease(t *testing.T, txTipCap, txFeeCap, newTip, newBaseFee int }, name: "TEST", backend: &borkedBackend, - l: testlog.Logger(t, log.LvlCrit), + l: testlog.Logger(t, log.LevelCrit), metr: &metrics.NoopTxMetrics{}, } @@ -986,8 +1004,7 @@ func doGasPriceIncrease(t *testing.T, txTipCap, txFeeCap, newTip, newBaseFee int GasFeeCap: big.NewInt(txFeeCap), }) newTx, err := mgr.increaseGasPrice(context.Background(), tx) - require.NoError(t, err) - return tx, newTx + return tx, newTx, err } func TestIncreaseGasPrice(t *testing.T) { @@ -1000,58 +1017,89 @@ func TestIncreaseGasPrice(t *testing.T) { { name: "bump at least 1", run: func(t *testing.T) { - tx, newTx := doGasPriceIncrease(t, 1, 3, 1, 1) + tx, newTx, err := doGasPriceIncrease(t, 1, 3, 1, 1) require.True(t, newTx.GasFeeCap().Cmp(tx.GasFeeCap()) > 0, "new tx fee cap must be larger") require.True(t, newTx.GasTipCap().Cmp(tx.GasTipCap()) > 0, "new tx tip must be larger") + require.NoError(t, err) }, }, { name: "enforces min bump", run: func(t *testing.T) { - tx, newTx := doGasPriceIncrease(t, 100, 1000, 101, 460) + tx, newTx, err := doGasPriceIncrease(t, 100, 1000, 101, 460) require.True(t, newTx.GasFeeCap().Cmp(tx.GasFeeCap()) > 0, "new tx fee cap must be larger") require.True(t, newTx.GasTipCap().Cmp(tx.GasTipCap()) > 0, "new tx tip must be larger") + require.NoError(t, err) }, }, { name: "enforces min bump on only tip increase", run: func(t *testing.T) { - tx, newTx := doGasPriceIncrease(t, 100, 1000, 101, 440) + tx, newTx, err := doGasPriceIncrease(t, 100, 1000, 101, 440) require.True(t, newTx.GasFeeCap().Cmp(tx.GasFeeCap()) > 0, "new tx fee cap must be larger") require.True(t, newTx.GasTipCap().Cmp(tx.GasTipCap()) > 0, "new tx tip must be larger") + require.NoError(t, err) }, }, { name: "enforces min bump on only base fee increase", run: func(t *testing.T) { - tx, newTx := doGasPriceIncrease(t, 100, 1000, 99, 460) + tx, newTx, err := doGasPriceIncrease(t, 100, 1000, 99, 460) require.True(t, newTx.GasFeeCap().Cmp(tx.GasFeeCap()) > 0, "new tx fee cap must be larger") require.True(t, newTx.GasTipCap().Cmp(tx.GasTipCap()) > 0, "new tx tip must be larger") + require.NoError(t, err) }, }, { name: "uses L1 values when larger", run: func(t *testing.T) { - _, newTx := doGasPriceIncrease(t, 10, 100, 50, 200) + _, newTx, err := doGasPriceIncrease(t, 10, 100, 50, 200) require.True(t, newTx.GasFeeCap().Cmp(big.NewInt(450)) == 0, "new tx fee cap must be equal L1") require.True(t, newTx.GasTipCap().Cmp(big.NewInt(50)) == 0, "new tx tip must be equal L1") + require.NoError(t, err) }, }, { name: "uses L1 tip when larger and threshold FC", run: func(t *testing.T) { - _, newTx := doGasPriceIncrease(t, 100, 2200, 120, 1050) + _, newTx, err := doGasPriceIncrease(t, 100, 2200, 120, 1050) require.True(t, newTx.GasTipCap().Cmp(big.NewInt(120)) == 0, "new tx tip must be equal L1") require.True(t, newTx.GasFeeCap().Cmp(big.NewInt(2420)) == 0, "new tx fee cap must be equal to the threshold value") + require.NoError(t, err) + }, + }, + { + name: "bumped fee above multiplier limit", + run: func(t *testing.T) { + _, _, err := doGasPriceIncrease(t, 1, 9999, 1, 1) + require.ErrorContains(t, err, "fee cap") + require.NotContains(t, err.Error(), "tip cap") + }, + }, + { + name: "bumped tip above multiplier limit", + run: func(t *testing.T) { + _, _, err := doGasPriceIncrease(t, 9999, 0, 0, 9999) + require.ErrorContains(t, err, "tip cap") + require.NotContains(t, err.Error(), "fee cap") + }, + }, + { + name: "bumped fee and tip above multiplier limit", + run: func(t *testing.T) { + _, _, err := doGasPriceIncrease(t, 9999, 9999, 1, 1) + require.ErrorContains(t, err, "tip cap") + require.ErrorContains(t, err, "fee cap") }, }, { name: "uses L1 FC when larger and threshold tip", run: func(t *testing.T) { - _, newTx := doGasPriceIncrease(t, 100, 2200, 100, 2000) + _, newTx, err := doGasPriceIncrease(t, 100, 2200, 100, 2000) require.True(t, newTx.GasTipCap().Cmp(big.NewInt(110)) == 0, "new tx tip must be equal the threshold value") t.Log("Vals:", newTx.GasFeeCap()) require.True(t, newTx.GasFeeCap().Cmp(big.NewInt(4110)) == 0, "new tx fee cap must be equal L1") + require.NoError(t, err) }, }, } @@ -1118,7 +1166,7 @@ func testIncreaseGasPriceLimit(t *testing.T, lt gasPriceLimitTest) { }, name: "TEST", backend: &borkedBackend, - l: testlog.Logger(t, log.LvlCrit), + l: testlog.Logger(t, log.LevelCrit), metr: &metrics.NoopTxMetrics{}, } lastGoodTx := types.NewTx(&types.DynamicFeeTx{ @@ -1403,3 +1451,24 @@ func TestCloseWaitingForConfirmation(t *testing.T) { require.True(t, h.mgr.closed.Load()) require.NoError(t, err) } + +func TestMakeSidecar(t *testing.T) { + var blob eth.Blob + _, err := rand.Read(blob[:]) + require.NoError(t, err) + // get the field-elements into a valid range + for i := 0; i < 4096; i++ { + blob[32*i] &= 0b0011_1111 + } + sidecar, hashes, err := MakeSidecar([]*eth.Blob{&blob}) + require.NoError(t, err) + require.Equal(t, len(hashes), 1) + require.Equal(t, len(sidecar.Blobs), len(hashes)) + require.Equal(t, len(sidecar.Proofs), len(hashes)) + require.Equal(t, len(sidecar.Commitments), len(hashes)) + + for i, commit := range sidecar.Commitments { + require.NoError(t, eth.VerifyBlobProof((*eth.Blob)(&sidecar.Blobs[i]), commit, sidecar.Proofs[i]), "proof must be valid") + require.Equal(t, hashes[i], eth.KZGToVersionedHash(commit)) + } +} diff --git a/op-ufm/Makefile b/op-ufm/Makefile index 517de9ec80ab..7dbd96f11dcf 100644 --- a/op-ufm/Makefile +++ b/op-ufm/Makefile @@ -25,3 +25,12 @@ tls: kubectl get secrets op-ufm-client-tls -o yaml | yq '.data."tls.crt"' | base64 --decode > tls/tls.crt kubectl get secrets op-ufm-client-tls -o yaml | yq '.data."ca.crt"' | base64 --decode > tls/ca.crt .PHONY: tls + +mod-tidy: + # Below GOPRIVATE line allows mod-tidy to be run immediately after + # releasing new versions. This bypasses the Go modules proxy, which + # can take a while to index new versions. + # + # See https://proxy.golang.org/ for more info. + export GOPRIVATE="github.com/ethereum-optimism" && go mod tidy +.PHONY: mod-tidy diff --git a/op-ufm/cmd/ufm/main.go b/op-ufm/cmd/ufm/main.go index ca2cac4d2c39..f4f753a40c85 100644 --- a/op-ufm/cmd/ufm/main.go +++ b/op-ufm/cmd/ufm/main.go @@ -8,10 +8,13 @@ import ( "os/signal" "syscall" - "github.com/ethereum-optimism/optimism/op-ufm/pkg/config" - "github.com/ethereum-optimism/optimism/op-ufm/pkg/service" + "golang.org/x/exp/slog" "github.com/ethereum/go-ethereum/log" + + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/optimism/op-ufm/pkg/config" + "github.com/ethereum-optimism/optimism/op-ufm/pkg/service" ) var ( @@ -21,12 +24,8 @@ var ( ) func main() { - log.Root().SetHandler( - log.LvlFilterHandler( - log.LvlInfo, - log.StreamHandler(os.Stdout, log.JSONFormat()), - ), - ) + oplog.SetGlobalLogHandler(slog.NewJSONHandler( + os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})) log.Info("initializing", "version", GitVersion, @@ -60,20 +59,16 @@ func initConfig(cfgFile string) *config.Config { } // update log level from config - logLevel, err := log.LvlFromString(cfg.LogLevel) + logLevel, err := oplog.LevelFromString(cfg.LogLevel) if err != nil { - logLevel = log.LvlInfo + logLevel = log.LevelInfo if cfg.LogLevel != "" { log.Warn("invalid server.log_level", "log_level", cfg.LogLevel) } } - log.Root().SetHandler( - log.LvlFilterHandler( - logLevel, - log.StreamHandler(os.Stdout, log.JSONFormat()), - ), - ) + oplog.SetGlobalLogHandler(slog.NewJSONHandler( + os.Stdout, &slog.HandlerOptions{Level: logLevel})) // readable parsed config jsonCfg, _ := json.MarshalIndent(cfg, "", " ") diff --git a/op-ufm/go.mod b/op-ufm/go.mod index a911d50aa744..e00d1ad4d24a 100644 --- a/op-ufm/go.mod +++ b/op-ufm/go.mod @@ -2,17 +2,18 @@ module github.com/ethereum-optimism/optimism/op-ufm go 1.21 -toolchain go1.21.3 +toolchain go1.21.6 require ( cloud.google.com/go/kms v1.12.1 github.com/BurntSushi/toml v1.3.2 - github.com/ethereum-optimism/optimism v1.2.0 - github.com/ethereum/go-ethereum v1.13.5 + github.com/ethereum-optimism/optimism v1.6.2-0.20240222202618-f707883038d5 + github.com/ethereum/go-ethereum v1.13.8 github.com/gorilla/mux v1.8.0 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.17.0 + github.com/prometheus/client_golang v1.19.0 github.com/rs/cors v1.9.0 + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa ) require ( @@ -23,47 +24,48 @@ require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.7.0 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cockroachdb/errors v1.9.1 // indirect + github.com/cockroachdb/errors v1.11.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect - github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect - github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cockroachdb/pebble v0.0.0-20231018212520-f6cde3fc2fa4 // indirect + github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/deckarep/golang-set/v2 v2.1.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240306093353-c557df8e6f41 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-stack/stack v1.8.1 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/s2a-go v0.1.4 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect - github.com/holiman/uint256 v1.2.3 // indirect - github.com/klauspost/compress v1.16.7 // indirect + github.com/holiman/uint256 v1.2.4 // indirect + github.com/klauspost/compress v1.17.2 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/rivo/uniseg v0.4.3 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect @@ -72,25 +74,30 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect - github.com/urfave/cli/v2 v2.25.7 // indirect + github.com/urfave/cli/v2 v2.27.1 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/oauth2 v0.10.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/oauth2 v0.16.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.13.0 // indirect + golang.org/x/tools v0.16.1 // indirect google.golang.org/api v0.132.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect google.golang.org/grpc v1.56.3 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) + +replace github.com/ethereum/go-ethereum v1.13.8 => github.com/ethereum-optimism/op-geth v1.101308.2-rc.2 + +replace github.com/ethereum-optimism/optimism => ../. diff --git a/op-ufm/go.sum b/op-ufm/go.sum index 95dc0ef62b5e..a40bd9ece1ed 100644 --- a/op-ufm/go.sum +++ b/op-ufm/go.sum @@ -10,36 +10,28 @@ cloud.google.com/go/iam v1.1.0 h1:67gSqaPukx7O8WLLHMa0PNs3EBGd2eE4d+psbO/CO94= cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk= cloud.google.com/go/kms v1.12.1 h1:xZmZuwy2cwzsocmKDOPu4BL7umg8QXagQx6fKVmf45U= cloud.google.com/go/kms v1.12.1/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM= -github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= -github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= -github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= 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/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= -github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/btcsuite/btcd v0.23.3 h1:4KH/JKy9WiCd+iUS9Mu0Zp7Dnj17TGdKrg9xc/FGj24= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo= github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= -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/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= @@ -54,31 +46,26 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= -github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= -github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/errors v1.11.1 h1:xSEW75zKaKCWzR3OfxXUxgrk/NtT4G1MiOv5lWZazG8= +github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= -github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= -github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= -github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/pebble v0.0.0-20231018212520-f6cde3fc2fa4 h1:PuHFhOUMnD62r80dN+Ik5qco2drekgsUSVdcHsvllec= +github.com/cockroachdb/pebble v0.0.0-20231018212520-f6cde3fc2fa4/go.mod h1:sEHm5NOXxyiAoKWhoFxT8xMgd/f3RA6qUqQ1BXKrh2E= +github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30= +github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= -github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -91,65 +78,41 @@ github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5il github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= 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/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/ethereum-optimism/optimism v1.2.0 h1:wlVqKHj6+HCMrXRskLM7b45zcdqSHCsVk0Kmg+ViCS8= -github.com/ethereum-optimism/optimism v1.2.0/go.mod h1:y1J1a0BkbJ5MTImx1Ayk2syTXZEoFucRAsBpdzbn0Qk= +github.com/ethereum-optimism/op-geth v1.101308.2-rc.2 h1:Tjm2n7/actyINbRIbqeDS+SyWAcIl+pRfOHODwW7lpQ= +github.com/ethereum-optimism/op-geth v1.101308.2-rc.2/go.mod h1:RPqVhnX00rJNys/YRDK4Wl4PvS6dgFrLqhsopIZOhEw= +github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240306093353-c557df8e6f41 h1:WKJvsRyW/YNgyT0P2x5U530ITOY8Dv9TrZnbliqSXd8= +github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240306093353-c557df8e6f41/go.mod h1:7xh2awFQqsiZxFrHKTgEd+InVfDRrkKVUIuK8SAFHp0= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.13.5 h1:U6TCRciCqZRe4FPXmy1sMGxTfuk8P7u2UoinF3VbaFk= -github.com/ethereum/go-ethereum v1.13.5/go.mod h1:yMTu38GSuyxaYzQMViqNmQ1s3cE84abZexQmTgenWk0= -github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ= github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= -github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= -github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= -github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -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/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= -github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -176,7 +139,6 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= 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= @@ -184,105 +146,57 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/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.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.1/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/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/go-bexpr v0.1.11 h1:6DqdA/KBjurGby9yTY0bmkathya0lfwF2SeuubCI7dY= github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U+N8T+6Kz1AE= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= -github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= -github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= -github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= -github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= -github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= -github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= -github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= -github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= -github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= -github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= @@ -290,22 +204,12 @@ github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8oh github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= -github.com/modern-go/concurrent v0.0.0-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/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -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/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 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= @@ -315,70 +219,51 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.28.0 h1:i2rg/p9n/UqIDAMFUJ6qIUUMcsqOuUHgbpbu235Vr1c= -github.com/onsi/gomega v1.28.0/go.mod h1:A1H2JE76sI14WIP57LMKj7FVfCHx3g3BcZVjJG8bjX8= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= +github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= -github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 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 v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -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/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= @@ -389,175 +274,121 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= -github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= -github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= -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/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= +github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= -github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= -github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= -github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/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-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -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-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= 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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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-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-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-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/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-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-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-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20181205085412-a5c9d58dba9a/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-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-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/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.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= 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= @@ -569,19 +400,16 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 h1:Au6te5hbKUV8pIYWHqOUZ1pva5qK/rwbIhoXEUB9Lu8= google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y= google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU= google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= -google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -589,7 +417,6 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= @@ -604,19 +431,12 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD 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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= -gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -627,9 +447,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/op-wheel/cheat/cheat.go b/op-wheel/cheat/cheat.go index debffacc1182..1bf4c4bad97d 100644 --- a/op-wheel/cheat/cheat.go +++ b/op-wheel/cheat/cheat.go @@ -21,13 +21,13 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" ) -var HundredETH = big.NewInt(0).Mul(big.NewInt(100), big.NewInt(1000000000000000000)) +var HundredETH = big.NewInt(0).Mul(big.NewInt(100), big.NewInt(params.Ether)) type Cheater struct { // The database of the chain with the head block that we patch the state-root of, once the state is updated. @@ -78,12 +78,6 @@ func (ch *Cheater) Close() error { return ch.DB.Close() } -func openStorageTrie(s *state.StateDB, addr common.Address) (state.Trie, error) { - stateRoot := s.IntermediateRoot(true) - storageRoot := s.GetStorageRoot(addr) - return s.Database().OpenStorageTrie(stateRoot, addr, storageRoot) -} - type HeadFn func(header *types.Header, headState *state.StateDB) error // RunAndClose runs the given function on the head-state, and then persists any changes (if not ReadOnly), @@ -198,7 +192,7 @@ func StorageGet(address common.Address, key common.Hash, w io.Writer) HeadFn { // to another account (maybe even in a different database!). func StorageReadAll(address common.Address, w io.Writer) HeadFn { return func(_ *types.Header, headState *state.StateDB) error { - storage, err := openStorageTrie(headState, address) + storage, err := headState.OpenStorageTrie(address) if err != nil { return fmt.Errorf("failed to open storage trie of addr %s: %w", address, err) } @@ -235,14 +229,14 @@ func dbValueToHash(enc []byte) common.Hash { // Each difference is expressed with 1 character + or - to indicate the change from a to b, followed by key = value. func StorageDiff(out io.Writer, addressA, addressB common.Address) HeadFn { return func(_ *types.Header, headState *state.StateDB) error { - aStorage, err := openStorageTrie(headState, addressA) + aStorage, err := headState.OpenStorageTrie(addressA) if err != nil { return fmt.Errorf("failed to open storage trie of addr A %s: %w", addressA, err) } if aStorage == nil { return fmt.Errorf("no storage trie in state for account A %s", addressA) } - bStorage, err := openStorageTrie(headState, addressB) + bStorage, err := headState.OpenStorageTrie(addressB) if err != nil { return fmt.Errorf("failed to open storage trie of addr B %s: %w", addressB, err) } @@ -339,58 +333,6 @@ func StoragePatch(patch io.Reader, address common.Address) HeadFn { } } -type OvmOwnersConfig struct { - Network string `json:"network"` - Owner common.Address `json:"owner"` - Sequencer common.Address `json:"sequencer"` - Proposer common.Address `json:"proposer"` -} - -func OvmOwners(conf *OvmOwnersConfig) HeadFn { - return func(_ *types.Header, headState *state.StateDB) error { - var addressManager common.Address // Lib_AddressManager - var l1SBProxy common.Address // Proxy__OVM_L1StandardBridge - var l1XDMProxy common.Address // Proxy__OVM_L1CrossDomainMessenger - var l1ERC721BridgeProxy common.Address - switch conf.Network { - case "mainnet": - addressManager = common.HexToAddress("0xdE1FCfB0851916CA5101820A69b13a4E276bd81F") - l1SBProxy = common.HexToAddress("0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1") - l1XDMProxy = common.HexToAddress("0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1") - l1ERC721BridgeProxy = common.HexToAddress("0x5a7749f83b81B301cAb5f48EB8516B986DAef23D") - case "goerli": - addressManager = common.HexToAddress("0xa6f73589243a6A7a9023b1Fa0651b1d89c177111") - l1SBProxy = common.HexToAddress("0x636Af16bf2f682dD3109e60102b8E1A089FedAa8") - l1XDMProxy = common.HexToAddress("0x5086d1eEF304eb5284A0f6720f79403b4e9bE294") - l1ERC721BridgeProxy = common.HexToAddress("0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9") - default: - return fmt.Errorf("unknown network: %q", conf.Network) - } - // See Proxy.sol OWNER_KEY: https://eips.ethereum.org/EIPS/eip-1967#admin-address - ownerSlot := common.HexToHash("0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103") - - // Address manager owner - // Ownable, first storage slot - headState.SetState(addressManager, common.Hash{}, eth.AddressAsLeftPaddedHash(conf.Owner)) - // L1SB proxy owner - headState.SetState(l1SBProxy, ownerSlot, eth.AddressAsLeftPaddedHash(conf.Owner)) - // L1XDM owner - // 0x33 = 51. L1CrossDomainMessenger is L1CrossDomainMessenger (0) Lib_AddressResolver (1) OwnableUpgradeable (1, but covered by gap) + ContextUpgradeable (special gap of 50) and then _owner - headState.SetState(l1XDMProxy, common.Hash{31: 0x33}, eth.AddressAsLeftPaddedHash(conf.Owner)) - // L1 ERC721 bridge owner - headState.SetState(l1ERC721BridgeProxy, ownerSlot, eth.AddressAsLeftPaddedHash(conf.Owner)) - // Legacy sequencer/proposer addresses - // See AddressManager.sol "addresses" mapping(bytes32 => address), at slot position 1 - addressesSlot := common.BigToHash(big.NewInt(1)) - headState.SetState(addressManager, crypto.Keccak256Hash(crypto.Keccak256([]byte("OVM_Sequencer")), addressesSlot.Bytes()), eth.AddressAsLeftPaddedHash(conf.Sequencer)) - headState.SetState(addressManager, crypto.Keccak256Hash(crypto.Keccak256([]byte("OVM_Proposer")), addressesSlot.Bytes()), eth.AddressAsLeftPaddedHash(conf.Proposer)) - // Fund sequencer and proposer with 100 ETH - headState.SetBalance(conf.Sequencer, HundredETH) - headState.SetBalance(conf.Proposer, HundredETH) - return nil - } -} - func SetBalance(addr common.Address, amount *big.Int) HeadFn { return func(_ *types.Header, headState *state.StateDB) error { headState.SetBalance(addr, amount) diff --git a/op-wheel/cmd/main.go b/op-wheel/cmd/main.go index 29c726cddb21..03d29c72c055 100644 --- a/op-wheel/cmd/main.go +++ b/op-wheel/cmd/main.go @@ -27,12 +27,8 @@ func main() { app.Description = "Optimism Wheel is a CLI tool to direct the engine one way or the other with DB cheats and Engine API routines." app.Flags = []cli.Flag{wheel.GlobalGethLogLvlFlag} app.Before = func(c *cli.Context) error { - log.Root().SetHandler( - log.LvlFilterHandler( - c.Generic(wheel.GlobalGethLogLvlFlag.Name).(*oplog.LvlFlagValue).LogLvl(), - log.StreamHandler(os.Stdout, log.TerminalFormat(true)), - ), - ) + lvl := c.Generic(wheel.GlobalGethLogLvlFlag.Name).(*oplog.LevelFlagValue).Level() + oplog.SetGlobalLogHandler(log.NewTerminalHandlerWithLevel(os.Stdout, lvl, true)) return nil } app.Action = cli.ActionFunc(func(c *cli.Context) error { diff --git a/op-wheel/commands.go b/op-wheel/commands.go index b356c8711dab..908e62275879 100644 --- a/op-wheel/commands.go +++ b/op-wheel/commands.go @@ -18,12 +18,16 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum-optimism/optimism/op-node/rollup" opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/client" oplog "github.com/ethereum-optimism/optimism/op-service/log" opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" + "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-wheel/cheat" "github.com/ethereum-optimism/optimism/op-wheel/engine" ) @@ -39,7 +43,7 @@ var ( Name: "geth-log-level", Usage: "Set the global geth logging level", EnvVars: prefixEnvVars("GETH_LOG_LEVEL"), - Value: oplog.NewLvlFlagValue(log.LvlError), + Value: oplog.NewLevelFlagValue(log.LevelError), } DataDirFlag = &cli.StringFlag{ Name: "data-dir", @@ -50,8 +54,9 @@ var ( } EngineEndpoint = &cli.StringFlag{ Name: "engine", - Usage: "Engine API RPC endpoint, can be HTTP/WS/IPC", + Usage: "Authenticated Engine API RPC endpoint, can be HTTP/WS/IPC", Required: true, + Value: "http://localhost:8551/", EnvVars: prefixEnvVars("ENGINE"), } EngineJWTPath = &cli.StringFlag{ @@ -61,6 +66,23 @@ var ( TakesFile: true, EnvVars: prefixEnvVars("ENGINE_JWT_SECRET"), } + EngineOpenEndpoint = &cli.StringFlag{ + Name: "engine.open", + Usage: "Open Engine API RPC endpoint, can be HTTP/WS/IPC", + Value: "http://localhost:8545/", + EnvVars: prefixEnvVars("ENGINE_OPEN"), + } + EngineVersion = &cli.IntFlag{ + Name: "engine.version", + Usage: "Engine API version to use for Engine calls (1, 2, or 3)", + EnvVars: prefixEnvVars("ENGINE_VERSION"), + Action: func(ctx *cli.Context, ev int) error { + if ev < 1 || ev > 3 { + return fmt.Errorf("invalid Engine API version: %d", ev) + } + return nil + }, + } FeeRecipientFlag = &cli.GenericFlag{ Name: "fee-recipient", Usage: "fee-recipient of the block building", @@ -92,6 +114,12 @@ var ( } ) +func withEngineFlags(flags ...cli.Flag) []cli.Flag { + return append(append(flags, + EngineEndpoint, EngineJWTPath, EngineOpenEndpoint, EngineVersion), + oplog.CLIFlags(envVarPrefix)...) +} + func ParseBuildingArgs(ctx *cli.Context) *engine.BlockBuildingSettings { return &engine.BlockBuildingSettings{ BlockTime: ctx.Uint64(BlockTimeFlag.Name), @@ -124,19 +152,84 @@ func CheatRawDBAction(readOnly bool, fn func(ctx *cli.Context, db ethdb.Database } } -func EngineAction(fn func(ctx *cli.Context, client client.RPC) error) cli.ActionFunc { +func EngineAction(fn func(ctx *cli.Context, client *sources.EngineAPIClient, lgr log.Logger) error) cli.ActionFunc { return func(ctx *cli.Context) error { - jwtData, err := os.ReadFile(ctx.String(EngineJWTPath.Name)) + lgr := initLogger(ctx) + rpc, err := initEngineRPC(ctx, lgr) if err != nil { - return fmt.Errorf("failed to read jwt: %w", err) + return fmt.Errorf("failed to dial Engine API endpoint %q: %w", + ctx.String(EngineEndpoint.Name), err) } - secret := common.HexToHash(strings.TrimSpace(string(jwtData))) - endpoint := ctx.String(EngineEndpoint.Name) - client, err := engine.DialClient(context.Background(), endpoint, secret) + evp, err := initVersionProvider(ctx, lgr) if err != nil { - return fmt.Errorf("failed to dial Engine API endpoint %q: %w", endpoint, err) + return fmt.Errorf("failed to init Engine version provider: %w", err) } - return fn(ctx, client) + client := sources.NewEngineAPIClient(rpc, lgr, evp) + return fn(ctx, client, lgr) + } +} + +func initLogger(ctx *cli.Context) log.Logger { + logCfg := oplog.ReadCLIConfig(ctx) + lgr := oplog.NewLogger(oplog.AppOut(ctx), logCfg) + oplog.SetGlobalLogHandler(lgr.Handler()) + return lgr +} + +func initEngineRPC(ctx *cli.Context, lgr log.Logger) (client.RPC, error) { + jwtData, err := os.ReadFile(ctx.String(EngineJWTPath.Name)) + if err != nil { + return nil, fmt.Errorf("failed to read jwt: %w", err) + } + secret := common.HexToHash(strings.TrimSpace(string(jwtData))) + endpoint := ctx.String(EngineEndpoint.Name) + return client.NewRPC(ctx.Context, lgr, endpoint, + client.WithGethRPCOptions(rpc.WithHTTPAuth(node.NewJWTAuth(secret)))) +} + +func initVersionProvider(ctx *cli.Context, lgr log.Logger) (sources.EngineVersionProvider, error) { + // static configuration takes precedent, if set + if ctx.IsSet(EngineVersion.Name) { + ev := ctx.Int(EngineVersion.Name) + return engine.StaticVersionProvider(ev), nil + } + + // otherwise get config from EL + rpc, err := initOpenEngineRPC(ctx, lgr) + if err != nil { + return nil, err + } + + cfg, err := engine.GetChainConfig(ctx.Context, rpc) + if err != nil { + return nil, err + } + return rollupFromGethConfig(cfg), nil +} + +func initOpenEngineRPC(ctx *cli.Context, lgr log.Logger) (client.RPC, error) { + openEP := ctx.String(EngineOpenEndpoint.Name) + rpc, err := client.NewRPC(ctx.Context, lgr, openEP) + if err != nil { + return nil, fmt.Errorf("failed to dial open Engine endpoint %q: %w", openEP, err) + } + return rpc, nil +} + +// rollupFromGethConfig returns a very incomplete rollup config with only the +// L2ChainID and (most) fork activation timestamps set. +// +// Because Delta was a pure CL fork, its time isn't set either. +// +// This incomplete [rollup.Config] can be used as a [sources.EngineVersionProvider]. +func rollupFromGethConfig(cfg *params.ChainConfig) *rollup.Config { + return &rollup.Config{ + L2ChainID: cfg.ChainID, + + RegolithTime: cfg.RegolithTime, + CanyonTime: cfg.CanyonTime, + EcotoneTime: cfg.EcotoneTime, + InteropTime: cfg.InteropTime, } } @@ -316,30 +409,6 @@ var ( return ch.RunAndClose(cheat.SetNonce(addrFlagValue("address", ctx), bigFlagValue("balance", ctx).Uint64())) }), } - CheatOvmOwnersCmd = &cli.Command{ - Name: "ovm-owners", - Flags: []cli.Flag{ - DataDirFlag, - &cli.StringFlag{ - Name: "config", - Usage: "Path to JSON config of OVM address replacements to apply.", - Required: true, - EnvVars: prefixEnvVars("OVM_OWNERS"), - Value: "ovm-owners.json", - }, - }, - Action: CheatAction(false, func(ctx *cli.Context, ch *cheat.Cheater) error { - confData, err := os.ReadFile(ctx.String("config")) - if err != nil { - return fmt.Errorf("failed to read OVM owners JSON config file: %w", err) - } - var conf cheat.OvmOwnersConfig - if err := json.Unmarshal(confData, &conf); err != nil { - return err - } - return ch.RunAndClose(cheat.OvmOwners(&conf)) - }), - } CheatPrintHeadBlock = &cli.Command{ Name: "head-block", Usage: "dump head block as JSON", @@ -374,41 +443,35 @@ var ( EngineBlockCmd = &cli.Command{ Name: "block", Usage: "build the next block using the Engine API", - Flags: []cli.Flag{ - EngineEndpoint, EngineJWTPath, + Flags: withEngineFlags( FeeRecipientFlag, RandaoFlag, BlockTimeFlag, BuildingTime, AllowGaps, - }, + ), // TODO: maybe support transaction and tx pool engine flags, since we use op-geth? // TODO: reorg flag // TODO: finalize/safe flag - Action: EngineAction(func(ctx *cli.Context, client client.RPC) error { + Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, _ log.Logger) error { settings := ParseBuildingArgs(ctx) - status, err := engine.Status(context.Background(), client) + status, err := engine.Status(context.Background(), client.RPC) if err != nil { return err } - payload, err := engine.BuildBlock(context.Background(), client, status, settings) + payloadEnv, err := engine.BuildBlock(context.Background(), client, status, settings) if err != nil { return err } - _, err = io.WriteString(ctx.App.Writer, payload.BlockHash.String()) - return err + fmt.Fprintln(ctx.App.Writer, payloadEnv.ExecutionPayload.BlockHash) + return nil }), } EngineAutoCmd = &cli.Command{ Name: "auto", Usage: "Run a proof-of-nothing chain with fixed block time.", Description: "The block time can be changed. The execution engine must be synced to a post-Merge state first.", - Flags: append(append([]cli.Flag{ - EngineEndpoint, EngineJWTPath, - FeeRecipientFlag, RandaoFlag, BlockTimeFlag, BuildingTime, AllowGaps, - }, oplog.CLIFlags(envVarPrefix)...), opmetrics.CLIFlags(envVarPrefix)...), - Action: EngineAction(func(ctx *cli.Context, client client.RPC) error { - logCfg := oplog.ReadCLIConfig(ctx) - l := oplog.NewLogger(oplog.AppOut(ctx), logCfg) - oplog.SetGlobalLogHandler(l.GetHandler()) - + Flags: append(withEngineFlags( + FeeRecipientFlag, RandaoFlag, BlockTimeFlag, BuildingTime, AllowGaps), + opmetrics.CLIFlags(envVarPrefix)...), + Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, l log.Logger) error { settings := ParseBuildingArgs(ctx) // TODO: finalize/safe flag @@ -435,9 +498,9 @@ var ( } EngineStatusCmd = &cli.Command{ Name: "status", - Flags: []cli.Flag{EngineEndpoint, EngineJWTPath}, - Action: EngineAction(func(ctx *cli.Context, client client.RPC) error { - stat, err := engine.Status(context.Background(), client) + Flags: withEngineFlags(), + Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, _ log.Logger) error { + stat, err := engine.Status(context.Background(), client.RPC) if err != nil { return err } @@ -448,16 +511,15 @@ var ( } EngineCopyCmd = &cli.Command{ Name: "copy", - Flags: []cli.Flag{ - EngineEndpoint, EngineJWTPath, + Flags: withEngineFlags( &cli.StringFlag{ Name: "source", Usage: "Unauthenticated regular eth JSON RPC to pull block data from, can be HTTP/WS/IPC.", Required: true, - EnvVars: prefixEnvVars("ENGINE"), + EnvVars: prefixEnvVars("SOURCE"), }, - }, - Action: EngineAction(func(ctx *cli.Context, dest client.RPC) error { + ), + Action: EngineAction(func(ctx *cli.Context, dest *sources.EngineAPIClient, _ log.Logger) error { rpcClient, err := rpc.DialOptions(context.Background(), ctx.String("source")) if err != nil { return fmt.Errorf("failed to dial engine source endpoint: %w", err) @@ -467,11 +529,37 @@ var ( }), } + EngineCopyPayloadCmd = &cli.Command{ + Name: "copy-payload", + Description: "Take the block by number from source and insert it to the engine with NewPayload. No other calls are made.", + Flags: withEngineFlags( + &cli.StringFlag{ + Name: "source", + Usage: "Unauthenticated regular eth JSON RPC to pull block data from, can be HTTP/WS/IPC.", + Required: true, + EnvVars: prefixEnvVars("SOURCE"), + }, + &cli.Uint64Flag{ + Name: "number", + Usage: "Block number to copy from the source", + Required: true, + EnvVars: prefixEnvVars("NUMBER"), + }, + ), + Action: EngineAction(func(ctx *cli.Context, dest *sources.EngineAPIClient, _ log.Logger) error { + rpcClient, err := rpc.DialOptions(context.Background(), ctx.String("source")) + if err != nil { + return fmt.Errorf("failed to dial engine source endpoint: %w", err) + } + source := client.NewBaseRPCClient(rpcClient) + return engine.CopyPayload(context.Background(), ctx.Uint64("number"), source, dest) + }), + } + EngineSetForkchoiceCmd = &cli.Command{ Name: "set-forkchoice", Description: "Set forkchoice, specify unsafe, safe and finalized blocks by number", - Flags: []cli.Flag{ - EngineEndpoint, EngineJWTPath, + Flags: withEngineFlags( &cli.Uint64Flag{ Name: "unsafe", Usage: "Block number of block to set as latest block", @@ -490,26 +578,81 @@ var ( Required: true, EnvVars: prefixEnvVars("FINALIZED"), }, - }, - Action: EngineAction(func(ctx *cli.Context, client client.RPC) error { + ), + Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, _ log.Logger) error { return engine.SetForkchoice(ctx.Context, client, ctx.Uint64("finalized"), ctx.Uint64("safe"), ctx.Uint64("unsafe")) }), } + EngineSetForkchoiceHashCmd = &cli.Command{ + Name: "set-forkchoice-by-hash", + Description: "Set forkchoice, specify unsafe, safe and finalized blocks by hash", + Flags: withEngineFlags( + &cli.StringFlag{ + Name: "unsafe", + Usage: "Block hash of block to set as latest block", + Required: true, + EnvVars: prefixEnvVars("UNSAFE"), + }, + &cli.StringFlag{ + Name: "safe", + Usage: "Block hash of block to set as safe block", + Required: true, + EnvVars: prefixEnvVars("SAFE"), + }, + &cli.StringFlag{ + Name: "finalized", + Usage: "Block hash of block to set as finalized block", + Required: true, + EnvVars: prefixEnvVars("FINALIZED"), + }, + ), + Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, _ log.Logger) error { + finalized := common.HexToHash(ctx.String("finalized")) + safe := common.HexToHash(ctx.String("safe")) + unsafe := common.HexToHash(ctx.String("unsafe")) + return engine.SetForkchoiceByHash(ctx.Context, client, finalized, safe, unsafe) + }), + } + + EngineRewindCmd = &cli.Command{ + Name: "rewind", + Description: "Rewind chain by number (destructive!)", + Flags: withEngineFlags( + &cli.Uint64Flag{ + Name: "to", + Usage: "Block number to rewind chain to", + Required: true, + EnvVars: prefixEnvVars("REWIND_TO"), + }, + &cli.BoolFlag{ + Name: "set-head", + Usage: "Whether to also call debug_setHead when rewinding", + EnvVars: prefixEnvVars("REWIND_SET_HEAD"), + }, + ), + Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, lgr log.Logger) error { + open, err := initOpenEngineRPC(ctx, lgr) + if err != nil { + return fmt.Errorf("failed to dial open RPC endpoint: %w", err) + } + return engine.Rewind(ctx.Context, lgr, client, open, ctx.Uint64("to"), ctx.Bool("set-head")) + }), + } + EngineJSONCmd = &cli.Command{ Name: "json", Description: "read json values from remaining args, or STDIN, and use them as RPC params to call the engine RPC method (first arg)", - Flags: []cli.Flag{ - EngineEndpoint, EngineJWTPath, + Flags: withEngineFlags( &cli.BoolFlag{ Name: "stdin", Usage: "Read params from stdin instead", Required: false, EnvVars: prefixEnvVars("STDIN"), }, - }, + ), ArgsUsage: " [params...]", - Action: EngineAction(func(ctx *cli.Context, client client.RPC) error { + Action: EngineAction(func(ctx *cli.Context, client *sources.EngineAPIClient, _ log.Logger) error { if ctx.NArg() == 0 { return fmt.Errorf("expected at least 1 argument: RPC method name") } @@ -520,7 +663,7 @@ var ( } else { args = ctx.Args().Tail() } - return engine.RawJSONInteraction(ctx.Context, client, ctx.Args().Get(0), args, r, ctx.App.Writer) + return engine.RawJSONInteraction(ctx.Context, client.RPC, ctx.Args().Get(0), args, r, ctx.App.Writer) }), } ) @@ -535,7 +678,6 @@ var CheatCmd = &cli.Command{ CheatSetBalanceCmd, CheatSetCodeCmd, CheatSetNonceCmd, - CheatOvmOwnersCmd, CheatPrintHeadBlock, CheatPrintHeadHeader, }, @@ -543,14 +685,17 @@ var CheatCmd = &cli.Command{ var EngineCmd = &cli.Command{ Name: "engine", - Usage: "Engine API commands to build/reorg/finalize blocks.", + Usage: "Engine API commands to build/reorg/rewind/finalize/copy blocks.", Description: "Each sub-command dials the engine API endpoint (with provided JWT secret) and then runs the action", Subcommands: []*cli.Command{ EngineBlockCmd, EngineAutoCmd, EngineStatusCmd, EngineCopyCmd, + EngineCopyPayloadCmd, EngineSetForkchoiceCmd, + EngineSetForkchoiceHashCmd, + EngineRewindCmd, EngineJSONCmd, }, } diff --git a/op-wheel/engine/engine.go b/op-wheel/engine/engine.go index 52fce956727b..c715d659afb8 100644 --- a/op-wheel/engine/engine.go +++ b/op-wheel/engine/engine.go @@ -10,48 +10,27 @@ import ( "strings" "time" - "github.com/ethereum/go-ethereum/beacon/engine" "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/log" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/params" + "github.com/holiman/uint256" "github.com/ethereum-optimism/optimism/op-service/client" "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/sources" ) -type PayloadAttributesV2 struct { - Timestamp uint64 `json:"timestamp"` - Random common.Hash `json:"prevRandao"` - SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` -} - -func (p PayloadAttributesV2) MarshalJSON() ([]byte, error) { - type PayloadAttributes struct { - Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` - Random common.Hash `json:"prevRandao" gencodec:"required"` - SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"` - Withdrawals []*types.Withdrawal `json:"withdrawals"` - } - var enc PayloadAttributes - enc.Timestamp = hexutil.Uint64(p.Timestamp) - enc.Random = p.Random - enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient - enc.Withdrawals = make([]*types.Withdrawal, 0) - return json.Marshal(&enc) -} - -func DialClient(ctx context.Context, endpoint string, jwtSecret [32]byte) (client.RPC, error) { - auth := node.NewJWTAuth(jwtSecret) +const ( + methodEthGetBlockByNumber = "eth_getBlockByNumber" + methodDebugChainConfig = "debug_chainConfig" + methodDebugSetHead = "debug_setHead" +) - rpcClient, err := rpc.DialOptions(ctx, endpoint, rpc.WithHTTPAuth(auth)) - if err != nil { - return nil, fmt.Errorf("failed to dial engine endpoint: %w", err) - } - return client.NewBaseRPCClient(rpcClient), nil +func GetChainConfig(ctx context.Context, open client.RPC) (cfg *params.ChainConfig, err error) { + err = open.CallContext(ctx, &cfg, methodDebugChainConfig) + return } type RPCBlock struct { @@ -77,49 +56,67 @@ func getHeader(ctx context.Context, client client.RPC, method string, tag string return header, nil } -func headSafeFinalized(ctx context.Context, client client.RPC) (head *types.Block, safe, finalized *types.Header, err error) { - head, err = getBlock(ctx, client, "eth_getBlockByNumber", "latest") +func headSafeFinalized(ctx context.Context, client client.RPC) (head, safe, finalized *types.Header, err error) { + head, err = getHeader(ctx, client, methodEthGetBlockByNumber, "latest") + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to get latest: %w", err) + } + safe, fin, err := safeFinalized(ctx, client) + return head, safe, fin, err +} + +func headBlockSafeFinalized(ctx context.Context, client client.RPC) (head *types.Block, safe, finalized *types.Header, err error) { + head, err = getBlock(ctx, client, methodEthGetBlockByNumber, "latest") if err != nil { - return nil, nil, nil, fmt.Errorf("failed to get block: %w", err) + return nil, nil, nil, fmt.Errorf("failed to get latest: %w", err) } - safe, err = getHeader(ctx, client, "eth_getBlockByNumber", "safe") + safe, fin, err := safeFinalized(ctx, client) + return head, safe, fin, err +} + +func safeFinalized(ctx context.Context, client client.RPC) (safe, finalized *types.Header, err error) { + safe, err = getHeader(ctx, client, methodEthGetBlockByNumber, "safe") if err != nil { - return head, nil, nil, fmt.Errorf("failed to get safe block: %w", err) + return nil, nil, fmt.Errorf("failed to get safe: %w", err) } - finalized, err = getHeader(ctx, client, "eth_getBlockByNumber", "finalized") + finalized, err = getHeader(ctx, client, methodEthGetBlockByNumber, "finalized") if err != nil { - return head, safe, nil, fmt.Errorf("failed to get finalized block: %w", err) + return safe, nil, fmt.Errorf("failed to get finalized: %w", err) } - return head, safe, finalized, nil + return safe, finalized, nil } -func insertBlock(ctx context.Context, client client.RPC, payload *engine.ExecutableData) error { - var payloadResult *engine.PayloadStatusV1 - if err := client.CallContext(ctx, &payloadResult, "engine_newPayloadV2", payload); err != nil { - return fmt.Errorf("failed to insert block %d: %w", payload.Number, err) +func insertBlock(ctx context.Context, client *sources.EngineAPIClient, payloadEnv *eth.ExecutionPayloadEnvelope) error { + payload := payloadEnv.ExecutionPayload + payloadResult, err := client.NewPayload(ctx, payload, payloadEnv.ParentBeaconBlockRoot) + if err != nil { + return fmt.Errorf("failed to insert block %d: %w", payload.BlockNumber, err) } - if payloadResult.Status != string(eth.ExecutionValid) { + if payloadResult.Status != eth.ExecutionValid { return fmt.Errorf("block insertion was not valid: %v", payloadResult.ValidationError) } return nil } -func updateForkchoice(ctx context.Context, client client.RPC, head, safe, finalized common.Hash) error { - var post engine.ForkChoiceResponse - if err := client.CallContext(ctx, &post, "engine_forkchoiceUpdatedV2", - engine.ForkchoiceStateV1{ - HeadBlockHash: head, - SafeBlockHash: safe, - FinalizedBlockHash: finalized, - }, nil); err != nil { - return fmt.Errorf("failed to set forkchoice with new block %s: %w", head, err) +func updateForkchoice(ctx context.Context, client *sources.EngineAPIClient, head, safe, finalized common.Hash) error { + res, err := client.ForkchoiceUpdate(ctx, ð.ForkchoiceState{ + HeadBlockHash: head, + SafeBlockHash: safe, + FinalizedBlockHash: finalized, + }, nil) + if err != nil { + return fmt.Errorf("failed to update forkchoice with new head %s: %w", head, err) } - if post.PayloadStatus.Status != string(eth.ExecutionValid) { - return fmt.Errorf("post-block forkchoice update was not valid: %v", post.PayloadStatus.ValidationError) + if res.PayloadStatus.Status != eth.ExecutionValid { + return fmt.Errorf("forkchoice update was not valid: %v", res.PayloadStatus.ValidationError) } return nil } +func debugSetHead(ctx context.Context, open client.RPC, head uint64) error { + return open.CallContext(ctx, nil, methodDebugSetHead, hexutil.Uint64(head)) +} + type BlockBuildingSettings struct { BlockTime uint64 // skip a block; timestamps will still increase in multiples of BlockTime like L1, but there may be gaps. @@ -129,7 +126,7 @@ type BlockBuildingSettings struct { BuildTime time.Duration } -func BuildBlock(ctx context.Context, client client.RPC, status *StatusData, settings *BlockBuildingSettings) (*engine.ExecutableData, error) { +func BuildBlock(ctx context.Context, client *sources.EngineAPIClient, status *StatusData, settings *BlockBuildingSettings) (*eth.ExecutionPayloadEnvelope, error) { timestamp := status.Head.Time + settings.BlockTime if settings.AllowGaps { now := uint64(time.Now().Unix()) @@ -137,20 +134,17 @@ func BuildBlock(ctx context.Context, client client.RPC, status *StatusData, sett timestamp = now - ((now - timestamp) % settings.BlockTime) } } - var pre engine.ForkChoiceResponse - if err := client.CallContext(ctx, &pre, "engine_forkchoiceUpdatedV2", - engine.ForkchoiceStateV1{ + attrs := newPayloadAttributes(client.EngineVersionProvider(), timestamp, settings.Random, settings.FeeRecipient) + pre, err := client.ForkchoiceUpdate(ctx, + ð.ForkchoiceState{ HeadBlockHash: status.Head.Hash, SafeBlockHash: status.Safe.Hash, FinalizedBlockHash: status.Finalized.Hash, - }, PayloadAttributesV2{ - Timestamp: timestamp, - Random: settings.Random, - SuggestedFeeRecipient: settings.FeeRecipient, - }); err != nil { + }, attrs) + if err != nil { return nil, fmt.Errorf("failed to set forkchoice when building new block: %w", err) } - if pre.PayloadStatus.Status != string(eth.ExecutionValid) { + if pre.PayloadStatus.Status != eth.ExecutionValid { return nil, fmt.Errorf("pre-block forkchoice update was not valid: %v", pre.PayloadStatus.ValidationError) } @@ -161,26 +155,45 @@ func BuildBlock(ctx context.Context, client client.RPC, status *StatusData, sett case <-time.After(settings.BuildTime): } - var payload *engine.ExecutionPayloadEnvelope - if err := client.CallContext(ctx, &payload, "engine_getPayloadV2", pre.PayloadID); err != nil { + payload, err := client.GetPayload(ctx, eth.PayloadInfo{ID: *pre.PayloadID, Timestamp: timestamp}) + if err != nil { return nil, fmt.Errorf("failed to get payload %v, %d time after instructing engine to build it: %w", pre.PayloadID, settings.BuildTime, err) } - if err := insertBlock(ctx, client, payload.ExecutionPayload); err != nil { + if err := insertBlock(ctx, client, payload); err != nil { return nil, err } if err := updateForkchoice(ctx, client, payload.ExecutionPayload.BlockHash, status.Safe.Hash, status.Finalized.Hash); err != nil { return nil, err } - return payload.ExecutionPayload, nil + return payload, nil +} + +func newPayloadAttributes(evp sources.EngineVersionProvider, timestamp uint64, prevRandao common.Hash, feeRecipient common.Address) *eth.PayloadAttributes { + pa := ð.PayloadAttributes{ + Timestamp: hexutil.Uint64(timestamp), + PrevRandao: eth.Bytes32(prevRandao), + SuggestedFeeRecipient: feeRecipient, + } + + ver := evp.ForkchoiceUpdatedVersion(pa) + if ver == eth.FCUV2 || ver == eth.FCUV3 { + withdrawals := make(types.Withdrawals, 0) + pa.Withdrawals = &withdrawals + } + if ver == eth.FCUV3 { + pa.ParentBeaconBlockRoot = new(common.Hash) + } + + return pa } -func Auto(ctx context.Context, metrics Metricer, client client.RPC, log log.Logger, shutdown <-chan struct{}, settings *BlockBuildingSettings) error { +func Auto(ctx context.Context, metrics Metricer, client *sources.EngineAPIClient, log log.Logger, shutdown <-chan struct{}, settings *BlockBuildingSettings) error { ticker := time.NewTicker(time.Millisecond * 100) defer ticker.Stop() - var lastPayload *engine.ExecutableData + var lastPayload *eth.ExecutionPayload var buildErr error for { select { @@ -194,7 +207,7 @@ func Auto(ctx context.Context, metrics Metricer, client client.RPC, log log.Logg blockTime := time.Duration(settings.BlockTime) * time.Second lastTime := uint64(0) if lastPayload != nil { - lastTime = lastPayload.Timestamp + lastTime = uint64(lastPayload.Timestamp) } buildTriggerTime := time.Unix(int64(lastTime), 0).Add(blockTime - settings.BuildTime) @@ -206,7 +219,7 @@ func Auto(ctx context.Context, metrics Metricer, client client.RPC, log log.Logg buildTime = 10 * time.Millisecond } buildErr = nil - status, err := Status(ctx, client) + status, err := Status(ctx, client.RPC) if err != nil { log.Error("failed to get pre-block engine status", "err", err) metrics.RecordBlockFail() @@ -220,7 +233,7 @@ func Auto(ctx context.Context, metrics Metricer, client client.RPC, log log.Logg // There are no gap slots, so we just go back 32 blocks. if status.Head.Number%32 == 0 { if status.Safe.Number+32 <= status.Head.Number { - safe, err := getHeader(ctx, client, "eth_getBlockByNumber", hexutil.Uint64(status.Head.Number-32).String()) + safe, err := getHeader(ctx, client.RPC, methodEthGetBlockByNumber, hexutil.Uint64(status.Head.Number-32).String()) if err != nil { buildErr = err log.Error("failed to find block for new safe block progress", "err", err) @@ -229,7 +242,7 @@ func Auto(ctx context.Context, metrics Metricer, client client.RPC, log log.Logg status.Safe = eth.L1BlockRef{Hash: safe.Hash(), Number: safe.Number.Uint64(), Time: safe.Time, ParentHash: safe.ParentHash} } if status.Finalized.Number+32 <= status.Safe.Number { - finalized, err := getHeader(ctx, client, "eth_getBlockByNumber", hexutil.Uint64(status.Safe.Number-32).String()) + finalized, err := getHeader(ctx, client.RPC, methodEthGetBlockByNumber, hexutil.Uint64(status.Safe.Number-32).String()) if err != nil { buildErr = err log.Error("failed to find block for new finalized block progress", "err", err) @@ -239,7 +252,7 @@ func Auto(ctx context.Context, metrics Metricer, client client.RPC, log log.Logg } } - payload, err := BuildBlock(ctx, client, status, &BlockBuildingSettings{ + payloadEnv, err := BuildBlock(ctx, client, status, &BlockBuildingSettings{ BlockTime: settings.BlockTime, AllowGaps: settings.AllowGaps, Random: settings.Random, @@ -251,12 +264,16 @@ func Auto(ctx context.Context, metrics Metricer, client client.RPC, log log.Logg log.Error("failed to produce block", "err", err) metrics.RecordBlockFail() } else { + payload := payloadEnv.ExecutionPayload lastPayload = payload - log.Info("created block", "hash", payload.BlockHash, "number", payload.Number, + log.Info("created block", "hash", payload.BlockHash, "number", payload.BlockNumber, "timestamp", payload.Timestamp, "txs", len(payload.Transactions), "gas", payload.GasUsed, "basefee", payload.BaseFeePerGas) - basefee, _ := new(big.Float).SetInt(payload.BaseFeePerGas).Float64() - metrics.RecordBlockStats(payload.BlockHash, payload.Number, payload.Timestamp, uint64(len(payload.Transactions)), payload.GasUsed, basefee) + basefee := (*uint256.Int)(&payload.BaseFeePerGas).Float64() + metrics.RecordBlockStats( + payload.BlockHash, uint64(payload.BlockNumber), uint64(payload.Timestamp), + uint64(len(payload.Transactions)), + uint64(payload.GasUsed), basefee) } } } @@ -274,7 +291,7 @@ type StatusData struct { } func Status(ctx context.Context, client client.RPC) (*StatusData, error) { - head, safe, finalized, err := headSafeFinalized(ctx, client) + head, safe, finalized, err := headBlockSafeFinalized(ctx, client) if err != nil { return nil, err } @@ -291,44 +308,73 @@ func Status(ctx context.Context, client client.RPC) (*StatusData, error) { // Copy takes the forkchoice state of copyFrom, and applies it to copyTo, and inserts the head-block. // The destination engine should then start syncing to this new chain if it has peers to do so. -func Copy(ctx context.Context, copyFrom client.RPC, copyTo client.RPC) error { - copyHead, copySafe, copyFinalized, err := headSafeFinalized(ctx, copyFrom) +func Copy(ctx context.Context, copyFrom client.RPC, copyTo *sources.EngineAPIClient) error { + copyHead, copySafe, copyFinalized, err := headBlockSafeFinalized(ctx, copyFrom) + if err != nil { + return err + } + payloadEnv, err := blockAsPayloadEnv(copyHead, copyTo.EngineVersionProvider()) if err != nil { return err } - payloadEnv := engine.BlockToExecutableData(copyHead, nil, nil) + if err := updateForkchoice(ctx, copyTo, copyHead.ParentHash(), copySafe.Hash(), copyFinalized.Hash()); err != nil { return err } - payload := payloadEnv.ExecutionPayload - if err := insertBlock(ctx, copyTo, payload); err != nil { + if err := insertBlock(ctx, copyTo, payloadEnv); err != nil { return err } - if err := updateForkchoice(ctx, copyTo, payload.BlockHash, copySafe.Hash(), copyFinalized.Hash()); err != nil { + if err := updateForkchoice(ctx, copyTo, + payloadEnv.ExecutionPayload.BlockHash, copySafe.Hash(), copyFinalized.Hash()); err != nil { return err } return nil } -func SetForkchoice(ctx context.Context, client client.RPC, finalizedNum, safeNum, unsafeNum uint64) error { +// CopyPaylod takes the execution payload at number & applies it via NewPayload to copyTo +func CopyPayload(ctx context.Context, number uint64, copyFrom client.RPC, copyTo *sources.EngineAPIClient) error { + copyHead, err := getBlock(ctx, copyFrom, methodEthGetBlockByNumber, hexutil.EncodeUint64(number)) + if err != nil { + return err + } + payloadEnv, err := blockAsPayloadEnv(copyHead, copyTo.EngineVersionProvider()) + if err != nil { + return err + } + if err := insertBlock(ctx, copyTo, payloadEnv); err != nil { + return err + } + return nil +} + +func blockAsPayloadEnv(block *types.Block, evp sources.EngineVersionProvider) (*eth.ExecutionPayloadEnvelope, error) { + var canyon *uint64 + // hack: if we're calling at least FCUV2, get empty withdrawals by setting Canyon before the block time + if v := evp.ForkchoiceUpdatedVersion(ð.PayloadAttributes{Timestamp: hexutil.Uint64(block.Time())}); v != eth.FCUV1 { + canyon = new(uint64) + } + return eth.BlockAsPayloadEnv(block, canyon) +} + +func SetForkchoice(ctx context.Context, client *sources.EngineAPIClient, finalizedNum, safeNum, unsafeNum uint64) error { if unsafeNum < safeNum { return fmt.Errorf("cannot set unsafe (%d) < safe (%d)", unsafeNum, safeNum) } if safeNum < finalizedNum { return fmt.Errorf("cannot set safe (%d) < finalized (%d)", safeNum, finalizedNum) } - head, err := getHeader(ctx, client, "eth_getBlockByNumber", "latest") + head, err := getHeader(ctx, client.RPC, methodEthGetBlockByNumber, "latest") if err != nil { return fmt.Errorf("failed to get latest block: %w", err) } if unsafeNum > head.Number.Uint64() { return fmt.Errorf("cannot set unsafe (%d) > latest (%d)", unsafeNum, head.Number.Uint64()) } - finalizedHeader, err := getHeader(ctx, client, "eth_getBlockByNumber", hexutil.Uint64(finalizedNum).String()) + finalizedHeader, err := getHeader(ctx, client.RPC, methodEthGetBlockByNumber, hexutil.Uint64(finalizedNum).String()) if err != nil { return fmt.Errorf("failed to get block %d to mark finalized: %w", finalizedNum, err) } - safeHeader, err := getHeader(ctx, client, "eth_getBlockByNumber", hexutil.Uint64(safeNum).String()) + safeHeader, err := getHeader(ctx, client.RPC, methodEthGetBlockByNumber, hexutil.Uint64(safeNum).String()) if err != nil { return fmt.Errorf("failed to get block %d to mark safe: %w", safeNum, err) } @@ -338,6 +384,50 @@ func SetForkchoice(ctx context.Context, client client.RPC, finalizedNum, safeNum return nil } +func SetForkchoiceByHash(ctx context.Context, client *sources.EngineAPIClient, finalized, safe, unsafe common.Hash) error { + if err := updateForkchoice(ctx, client, unsafe, safe, finalized); err != nil { + return fmt.Errorf("failed to update forkchoice: %w", err) + } + return nil +} + +func Rewind(ctx context.Context, lgr log.Logger, client *sources.EngineAPIClient, open client.RPC, to uint64, setHead bool) error { + unsafe, err := getHeader(ctx, open, methodEthGetBlockByNumber, hexutil.Uint64(to).String()) + if err != nil { + return fmt.Errorf("failed to get header %d: %w", to, err) + } + toUnsafe := eth.HeaderBlockID(unsafe) + + latest, safe, finalized, err := headSafeFinalized(ctx, open) + if err != nil { + return fmt.Errorf("failed to get current heads: %w", err) + } + + // when rewinding, don't increase unsafe/finalized tags + toSafe, toFinalized := toUnsafe, toUnsafe + if safe.Number.Uint64() < to { + toSafe = eth.HeaderBlockID(safe) + } + if finalized.Number.Uint64() < to { + toFinalized = eth.HeaderBlockID(finalized) + } + + lgr.Info("Rewinding chain", + "setHead", setHead, + "latest", eth.HeaderBlockID(latest), + "unsafe", toUnsafe, + "safe", toSafe, + "finalized", toFinalized, + ) + if setHead { + lgr.Debug("Calling "+methodDebugSetHead, "head", to) + if err := debugSetHead(ctx, open, to); err != nil { + return fmt.Errorf("failed to setHead %d: %w", to, err) + } + } + return SetForkchoiceByHash(ctx, client, toFinalized.Hash, toSafe.Hash, toUnsafe.Hash) +} + func RawJSONInteraction(ctx context.Context, client client.RPC, method string, args []string, input io.Reader, output io.Writer) error { var params []any if input != nil { diff --git a/op-wheel/engine/version_provider.go b/op-wheel/engine/version_provider.go new file mode 100644 index 000000000000..d3aaa377e1c4 --- /dev/null +++ b/op-wheel/engine/version_provider.go @@ -0,0 +1,44 @@ +package engine + +import ( + "strconv" + + "github.com/ethereum-optimism/optimism/op-service/eth" +) + +type StaticVersionProvider int + +func (v StaticVersionProvider) ForkchoiceUpdatedVersion(*eth.PayloadAttributes) eth.EngineAPIMethod { + switch int(v) { + case 1: + return eth.FCUV1 + case 2: + return eth.FCUV2 + case 3: + return eth.FCUV3 + default: + panic("invalid Engine API version: " + strconv.Itoa(int(v))) + } +} + +func (v StaticVersionProvider) NewPayloadVersion(uint64) eth.EngineAPIMethod { + switch int(v) { + case 1, 2: + return eth.NewPayloadV2 + case 3: + return eth.NewPayloadV3 + default: + panic("invalid Engine API version: " + strconv.Itoa(int(v))) + } +} + +func (v StaticVersionProvider) GetPayloadVersion(uint64) eth.EngineAPIMethod { + switch int(v) { + case 1, 2: + return eth.GetPayloadV2 + case 3: + return eth.GetPayloadV3 + default: + panic("invalid Engine API version: " + strconv.Itoa(int(v))) + } +} diff --git a/ops-bedrock/Dockerfile.l1 b/ops-bedrock/Dockerfile.l1 index e0b8f7ecd493..1cf2c0229903 100644 --- a/ops-bedrock/Dockerfile.l1 +++ b/ops-bedrock/Dockerfile.l1 @@ -1,4 +1,4 @@ -FROM ethereum/client-go:v1.13.10 +FROM ethereum/client-go:v1.13.14 RUN apk add --no-cache jq bash diff --git a/ops-bedrock/Dockerfile.stateviz b/ops-bedrock/Dockerfile.stateviz deleted file mode 100644 index 87905c2f5fac..000000000000 --- a/ops-bedrock/Dockerfile.stateviz +++ /dev/null @@ -1,22 +0,0 @@ -FROM golang:1.20.4-alpine3.16 as builder - -RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash - -COPY ./go.mod /app/go.mod -COPY ./go.sum /app/go.sum - -COPY ./op-bindings /app/op-bindings -COPY ./op-service /app/op-service - -WORKDIR /app/op-node -RUN go mod download -x - -COPY ./op-node /app/op-node - -RUN go build -o ./bin/stateviz ./cmd/stateviz - -FROM alpine:3.19 - -COPY --from=builder /app/op-node/bin/stateviz /usr/local/bin - -CMD ["stateviz"] diff --git a/ops-bedrock/docker-compose.yml b/ops-bedrock/docker-compose.yml index 12216ab510ff..2f41407a226e 100644 --- a/ops-bedrock/docker-compose.yml +++ b/ops-bedrock/docker-compose.yml @@ -80,7 +80,7 @@ services: --p2p.listen.ip=0.0.0.0 --p2p.listen.tcp=9003 --p2p.listen.udp=9003 - --p2p.scoring.peers=light + --p2p.scoring=light --p2p.ban.peers=true --snapshotlog.file=/op_log/snapshot.log --p2p.priv.path=/config/p2p-node-key.txt @@ -89,6 +89,7 @@ services: --metrics.port=7300 --pprof.enabled --rpc.enable-admin + --da-rpc=host.docker.internal:32003 ports: - "7545:8545" - "9003:9003" @@ -125,6 +126,9 @@ services: OP_PROPOSER_MNEMONIC: test test test test test test test test test test test junk OP_PROPOSER_L2_OUTPUT_HD_PATH: "m/44'/60'/0'/0/1" OP_PROPOSER_L2OO_ADDRESS: "${L2OO_ADDRESS}" + OP_PROPOSER_GAME_FACTORY_ADDRESS: "${DGF_ADDRESS}" + OP_PROPOSER_GAME_TYPE: "${DG_TYPE}" + OP_PROPOSER_PROPOSAL_INTERVAL: "${PROPOSAL_INTERVAL}" OP_PROPOSER_PPROF_ENABLED: "true" OP_PROPOSER_METRICS_ENABLED: "true" OP_PROPOSER_ALLOW_NON_FINALIZED: "true" @@ -160,6 +164,42 @@ services: OP_BATCHER_METRICS_ENABLED: "true" OP_BATCHER_RPC_ENABLE_ADMIN: "true" OP_BATCHER_BATCH_TYPE: 0 + OP_BATCHER_DA_RPC: host.docker.internal:32003 + OP_BATCHER_DA_STATUS_QUERY_INTERVAL: "5s" + OP_BATCHER_DA_STATUS_QUERY_TIMEOUT: "30s" + + op-challenger: + depends_on: + - op_stack_go_builder + - l1 + - l2 + - op-node + build: + context: ../ + dockerfile: ./op-challenger/Dockerfile + args: + OP_STACK_GO_BUILDER: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-stack-go:devnet + image: us-docker.pkg.dev/oplabs-tools-artifacts/images/op-challenger:devnet + environment: + OP_CHALLENGER_L1_ETH_RPC: http://l1:8545 + # Note: this will need to be updated to point to a L1 consensus node when there is one in the devnet + OP_CHALLENGER_L1_BEACON: "unset" + OP_CHALLENGER_ROLLUP_RPC: http://op-node:8545 + OP_CHALLENGER_TRACE_TYPE: cannon + OP_CHALLENGER_GAME_FACTORY_ADDRESS: ${DGF_ADDRESS} + # The devnet can't set the absolute prestate output root because the contracts are deployed in L1 genesis + # before the L2 genesis is known. + OP_CHALLENGER_UNSAFE_ALLOW_INVALID_PRESTATE: "true" + OP_CHALLENGER_DATADIR: temp/challenger-data + OP_CHALLENGER_CANNON_ROLLUP_CONFIG: ./.devnet/rollup.json + OP_CHALLENGER_CANNON_L2_GENESIS: ./.devnet/genesis-l2.json + OP_CHALLENGER_CANNON_BIN: ./cannon/bin/cannon + OP_CHALLENGER_CANNON_SERVER: ./op-program/bin/op-program + OP_CHALLENGER_CANNON_PRESTATE: ./op-program/bin/prestate.json + OP_CHALLENGER_CANNON_L2: http://l2:8545 + OP_CHALLENGER_MNEMONIC: test test test test test test test test test test test junk + OP_CHALLENGER_HD_PATH: "m/44'/60'/0'/0/4" + OP_CHALLENGER_NUM_CONFIRMATIONS: 1 artifact-server: depends_on: @@ -171,17 +211,3 @@ services: - "${PWD}/../.devnet/:/usr/share/nginx/html/:ro" security_opt: - "no-new-privileges:true" - -# stateviz: -# build: -# context: ../ -# dockerfile: ./ops-bedrock/Dockerfile.stateviz -# command: -# - stateviz -# - -addr=0.0.0.0:8080 -# - -snapshot=/op_log/snapshot.log -# - -refresh=10s -# ports: -# - "9090:8080" -# volumes: -# - op_log:/op_log:ro diff --git a/ops/check-changed/main.py b/ops/check-changed/main.py index fb3a9a458abf..8ce1a7bce9db 100644 --- a/ops/check-changed/main.py +++ b/ops/check-changed/main.py @@ -12,14 +12,16 @@ r'^\.github/\.*', r'^package\.json', r'ops/check-changed/.*', - r'^go\.mod', - r'^go\.sum', - r'ops/check-changed/.*' ] with open("../../nx.json") as file: nx_json_data = json.load(file) REBUILD_ALL_PATTERNS += nx_json_data["implicitDependencies"].keys() +GO_PATTERNS = [ + r'^go\.mod', + r'^go\.sum', +] + WHITELISTED_BRANCHES = { 'master', 'develop' @@ -55,8 +57,10 @@ def main(): - patterns = sys.argv[1].split(',') - patterns = patterns + REBUILD_ALL_PATTERNS + patterns = sys.argv[1].split(',') + REBUILD_ALL_PATTERNS + no_go_deps = os.getenv('CHECK_CHANGED_NO_GO_DEPS') + if no_go_deps is None: + patterns = patterns + GO_PATTERNS fp = os.path.realpath(__file__) monorepo_path = os.path.realpath(os.path.join(fp, '..', '..')) @@ -71,6 +75,15 @@ def main(): pr_urls = os.getenv('CIRCLE_PULL_REQUESTS', None) pr_urls = pr_urls.split(',') if pr_urls else [] + + # If we successfully extracted a PR number and did not find PRs from CIRCLE_PULL_REQUESTS, + # we are on a merge queue branch and can reconstruct the original PR URL from the PR number. + pr_number = extract_pr_number(current_branch) + if not pr_urls and pr_number is not None: + log.info('No PR URLs found but extracted branch number, constructing PR URL') + base_url = "https://github.com/ethereum-optimism/optimism/pull/" + pr_urls = [base_url + pr_number] + if len(pr_urls) == 0: log.info('Not a PR build, triggering build') exit_build() @@ -122,6 +135,15 @@ def match_path(path, patterns): return True return False +def extract_pr_number(branch_name): + # Merge queue branches are named: gh-readonly-queue/{base_branch}/pr-{number}-{sha} + match = re.search(r'/pr-(\d+)-', branch_name) + if match: + pr_number = match.group(1) + log.info('Extracted PR number: %s', pr_number) + return pr_number + else: + return None def exit_build(): sys.exit(0) diff --git a/ops/docker/ci-builder/Dockerfile b/ops/docker/ci-builder/Dockerfile index ba4ac375179b..5ef307482018 100644 --- a/ops/docker/ci-builder/Dockerfile +++ b/ops/docker/ci-builder/Dockerfile @@ -10,7 +10,7 @@ SHELL ["/bin/bash", "-c"] ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ - apt-get install -y curl build-essential git clang lld curl jq + apt-get install -y build-essential git clang lld curl jq RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup.sh && \ chmod +x ./rustup.sh && \ @@ -28,15 +28,18 @@ COPY ./versions.json ./versions.json COPY ./ops/scripts/install-foundry.sh ./install-foundry.sh RUN curl -L https://foundry.paradigm.xyz | bash -RUN source $HOME/.profile && ./install-foundry.sh +RUN source $HOME/.profile && \ + ./install-foundry.sh && \ + cargo install svm-rs RUN strip /root/.foundry/bin/forge && \ strip /root/.foundry/bin/cast && \ - strip /root/.foundry/bin/anvil + strip /root/.foundry/bin/anvil && \ + strip /root/.cargo/bin/svm FROM --platform=linux/amd64 debian:bullseye-slim as go-build -RUN apt-get update && apt-get install -y curl ca-certificates jq +RUN apt-get update && apt-get install -y curl ca-certificates jq binutils ENV GO_VERSION=1.21.1 @@ -56,16 +59,20 @@ RUN go install gotest.tools/gotestsum@latest RUN go install github.com/vektra/mockery/v2@v2.28.1 RUN go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2 -FROM --platform=linux/amd64 debian:bullseye-slim +# Strip binaries to reduce size +RUN strip /go/bin/gotestsum && \ + strip /go/bin/mockery && \ + strip /go/bin/golangci-lint && \ + strip /go/bin/abigen && \ + strip /go/bin/geth + +FROM --platform=linux/amd64 debian:bullseye-slim as base-builder ENV GOPATH=/go ENV PATH=/usr/local/go/bin:$GOPATH/bin:$PATH ENV PATH=/root/.cargo/bin:$PATH ENV DEBIAN_FRONTEND=noninteractive -# Create rust directories for copying the installation into -RUN mkdir /root/.cargo && mkdir /root/.cargo/bin && mkdir /root/.rustup - # copy the go installation, but not the module cache (cache will get stale, and would add a lot of weight) COPY --from=go-build /usr/local/go /usr/local/go @@ -76,14 +83,11 @@ COPY --from=go-build /go/bin/golangci-lint /go/bin/golangci-lint COPY --from=go-build /go/bin/abigen /usr/local/bin/abigen COPY --from=go-build /go/bin/geth /usr/local/bin/geth -# copy the rust installation, alongside the installed toolchains -COPY --from=rust-build /root/.cargo/bin /root/.cargo/bin -COPY --from=rust-build /root/.rustup /root/.rustup - # copy tools COPY --from=rust-build /root/.foundry/bin/forge /usr/local/bin/forge COPY --from=rust-build /root/.foundry/bin/cast /usr/local/bin/cast COPY --from=rust-build /root/.foundry/bin/anvil /usr/local/bin/anvil +COPY --from=rust-build /root/.cargo/bin/svm /usr/local/bin/svm COPY .nvmrc .nvmrc COPY ./versions.json ./versions.json @@ -92,7 +96,7 @@ ENV NODE_MAJOR=20 RUN /bin/sh -c set -eux; \ apt-get update; \ - apt-get install -y --no-install-recommends bash curl openssh-client git build-essential pkg-config libssl-dev clang lld libclang-dev ca-certificates jq gnupg binutils-mips-linux-gnu python3 python3-pip; \ + apt-get install -y --no-install-recommends bash curl openssh-client git build-essential ca-certificates jq gnupg binutils-mips-linux-gnu python3 python3-pip; \ mkdir -p /etc/apt/keyrings; \ curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \ echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list; \ @@ -103,7 +107,7 @@ RUN /bin/sh -c set -eux; \ apt-get install -y nodejs docker-ce-cli; \ ln -s /usr/local/go/bin/gofmt /usr/local/bin/gofmt; \ npm i -g depcheck; \ - pip install slither-analyzer==$(jq -r .slither < versions.json) capstone pyelftools; \ + pip install capstone pyelftools; \ curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | bash; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ rm -rf /var/lib/apt/lists/*; \ @@ -138,3 +142,16 @@ ENV SHELL=/bin/bash ENV BASH=/bin/bash ENTRYPOINT ["/bin/bash", "-c"] + +FROM base-builder as rust-builder + +# Install clang & lld +RUN apt-get update && apt-get install -y clang lld + +# Copy the rust installation, alongside the installed toolchains +COPY --from=rust-build /root/.cargo /root/.cargo +COPY --from=rust-build /root/.rustup /root/.rustup + +# copy the rust installation, alongside the installed toolchains +COPY --from=rust-build /root/.cargo/bin /root/.cargo/bin +COPY --from=rust-build /root/.rustup /root/.rustup diff --git a/ops/docker/op-stack-go/Dockerfile b/ops/docker/op-stack-go/Dockerfile index 8b431ddf513e..ee3cbc95e383 100644 --- a/ops/docker/op-stack-go/Dockerfile +++ b/ops/docker/op-stack-go/Dockerfile @@ -31,6 +31,7 @@ ARG OP_WHEEL_VERSION=v0.0.0 ARG OP_NODE_VERSION=v0.0.0 ARG OP_CHALLENGER_VERSION=v0.0.0 +ARG OP_DISPUTE_MON_VERSION=v0.0.0 ARG OP_BATCHER_VERSION=v0.0.0 ARG OP_PROPOSER_VERSION=v0.0.0 ARG OP_CONDUCTOR_VERSION=v0.0.0 @@ -62,6 +63,8 @@ RUN --mount=type=cache,target=/root/.cache/go-build cd op-node && make op-node GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_NODE_VERSION" RUN --mount=type=cache,target=/root/.cache/go-build cd op-challenger && make op-challenger \ GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_CHALLENGER_VERSION" +RUN --mount=type=cache,target=/root/.cache/go-build cd op-dispute-mon && make op-dispute-mon \ + GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_DISPUTE_MON_VERSION" RUN --mount=type=cache,target=/root/.cache/go-build cd op-batcher && make op-batcher \ GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_BATCHER_VERSION" RUN --mount=type=cache,target=/root/.cache/go-build cd op-proposer && make op-proposer \ @@ -80,8 +83,7 @@ COPY --from=builder /app/op-wheel/bin/op-wheel /usr/local/bin/ COPY --from=builder /app/op-node/bin/op-node /usr/local/bin/ COPY --from=builder /app/op-challenger/bin/op-challenger /usr/local/bin/ +COPY --from=builder /app/op-dispute-mon/bin/op-dispute-mon /usr/local/bin/ COPY --from=builder /app/op-batcher/bin/op-batcher /usr/local/bin/ COPY --from=builder /app/op-proposer/bin/op-proposer /usr/local/bin/ COPY --from=builder /app/op-conductor/bin/op-conductor /usr/local/bin/ - - diff --git a/ops/docker/op-stack-go/Dockerfile.dockerignore b/ops/docker/op-stack-go/Dockerfile.dockerignore index dcefe9d5a907..821978fb7992 100644 --- a/ops/docker/op-stack-go/Dockerfile.dockerignore +++ b/ops/docker/op-stack-go/Dockerfile.dockerignore @@ -8,6 +8,7 @@ !/op-bootnode !/op-chain-ops !/op-challenger +!/op-dispute-mon !/op-conductor !/op-heartbeat !/op-node @@ -16,5 +17,6 @@ !/op-proposer !/op-service !/op-wheel +!/op-plasma !/go.mod !/go.sum diff --git a/ops/scripts/ci-docker-tag-op-stack-release.sh b/ops/scripts/ci-docker-tag-op-stack-release.sh index 9edd98f2cae8..62cf4b319dbd 100755 --- a/ops/scripts/ci-docker-tag-op-stack-release.sh +++ b/ops/scripts/ci-docker-tag-op-stack-release.sh @@ -6,7 +6,7 @@ DOCKER_REPO=$1 GIT_TAG=$2 GIT_SHA=$3 -IMAGE_NAME=$(echo "$GIT_TAG" | grep -Eow '^(ci-builder|chain-mon|proxyd|indexer|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)' || true) +IMAGE_NAME=$(echo "$GIT_TAG" | grep -Eow '^(ci-builder(-rust)?|chain-mon|proxyd|indexer|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)' || true) if [ -z "$IMAGE_NAME" ]; then echo "image name could not be parsed from git tag '$GIT_TAG'" exit 1 diff --git a/ops/scripts/geth-version-checker.sh b/ops/scripts/geth-version-checker.sh index 9ad909f71bce..98d94e664136 100755 --- a/ops/scripts/geth-version-checker.sh +++ b/ops/scripts/geth-version-checker.sh @@ -7,7 +7,7 @@ MONOREPO_DIR=$(cd "$SCRIPTS_DIR/../../" && pwd) GETH_VERSION="v$(geth version | grep '^Version:' | awk '{print $2}')" # Read the version from the versions file -EXPECTED_GETH_VERSION=$(jq -r .geth < $MONOREPO_DIR/versions.json) +EXPECTED_GETH_VERSION=$(jq -r .geth < "$MONOREPO_DIR"/versions.json) # Check if EXPECTED_GETH_VERSION contains a '-'. If not, append '-stable'. if [[ $EXPECTED_GETH_VERSION != *-* ]]; then diff --git a/ops/scripts/install-foundry.sh b/ops/scripts/install-foundry.sh index cd3f8ac9f9c4..5f1fc577e3b0 100755 --- a/ops/scripts/install-foundry.sh +++ b/ops/scripts/install-foundry.sh @@ -6,7 +6,7 @@ SCRIPTS_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) MONOREPO_DIR=$(cd "$SCRIPTS_DIR/../../" && pwd) # Grab the foundry commit hash. -SHA=$(jq -r .foundry < $MONOREPO_DIR/versions.json) +SHA=$(jq -r .foundry < "$MONOREPO_DIR"/versions.json) # Check if there is a nightly tag corresponding to the commit hash TAG="nightly-$SHA" diff --git a/ops/tag-service/README.md b/ops/tag-service/README.md new file mode 100644 index 000000000000..b1fdc89f47b8 --- /dev/null +++ b/ops/tag-service/README.md @@ -0,0 +1,21 @@ +# Tag Service +Tag Service is a Github action which builds new tags and applies them to services in the monorepo. +It accepts: +* Service name +* Bump Amount [major, minor, patch] +* Prerelease and Finalize-Prerelease (to add/remove `rc` versions) + +It can be triggered from the Github Actions panel in the monorepo + +# Tag Tool +Tag Tool is a minimal rewrite of the Tag Service to let operators prepare and commit tags from commandline +It accepts: +* Service name +* Bump Amount [major, minor, patch, prerelease, finalize-prerelease] + +Tag Tool is meant to be run locally, and *does not* perform any write operations. Instead, it prints the git commands to console for the operator to use. + +Additionally, a special service name "op-stack" is available, which will bump versions for `op-node`, `op-batcher` and `op-proposer` from the highest semver amongst them. + +To run Tag Tool locally, the only dependency is `pip install semver` + diff --git a/ops/tag-service/tag-service.py b/ops/tag-service/tag-service.py index 37d875e6abbc..b88a03ad1292 100755 --- a/ops/tag-service/tag-service.py +++ b/ops/tag-service/tag-service.py @@ -11,16 +11,20 @@ # Minimum version numbers for packages migrating from legacy versioning. MIN_VERSIONS = { 'ci-builder': '0.6.0', + 'ci-builder-rust': '0.1.0', 'chain-mon': '0.2.2', 'indexer': '0.5.0', 'op-node': '0.10.14', 'op-batcher': '0.10.14', 'op-challenger': '0.0.4', + 'op-program': '0.0.0', + 'op-dispute-mon': '0.0.0', 'op-proposer': '0.10.14', 'op-ufm': '0.1.0', 'proxyd': '3.16.0', 'op-heartbeat': '0.1.0', 'ufm-metamask': '0.1.0', + 'op-contracts': '1.0.0', } VALID_BUMPS = ('major', 'minor', 'patch', 'prerelease', 'finalize-prerelease') diff --git a/ops/tag-service/tag-tool.py b/ops/tag-service/tag-tool.py new file mode 100644 index 000000000000..ddab04e00a4f --- /dev/null +++ b/ops/tag-service/tag-tool.py @@ -0,0 +1,94 @@ +import argparse +import subprocess +import re +import semver + +SERVICES = [ + 'ci-builder', + 'ci-builder-rust', + 'chain-mon', + 'indexer', + 'op-node', + 'op-batcher', + 'op-challenger', + 'op-dispute-mon', + 'op-proposer', + 'op-ufm', + 'proxyd', + 'op-heartbeat', + 'ufm-metamask', + 'op-contracts', + 'test', + 'op-stack', # special case for tagging op-node, op-batcher, and op-proposer together +] +VERSION_PATTERN = '^{service}/v\\d+\\.\\d+\\.\\d+(-rc\\.\\d+)?$' +GIT_TAG_COMMAND = 'git tag -a {tag} -m "{message}"' +GIT_PUSH_COMMAND = 'git push origin {tag}' + +def new_tag(service, version, bump): + if bump == 'major': + bumped = version.bump_major() + elif bump == 'minor': + bumped = version.bump_minor() + elif bump == 'patch': + bumped = version.bump_patch() + elif bump == 'prerelease': + bumped = version.bump_prerelease() + elif bump == 'finalize-prerelease': + bumped = version.finalize_version() + else: + raise Exception('Invalid bump type: {}'.format(bump)) + return f'{service}/v{bumped}' + +def latest_version(service): + # Get the list of tags from the git repository. + tags = subprocess.run(['git', 'tag', '--list', f'{service}/v*'], capture_output=True, check=True) \ + .stdout.decode('utf-8').splitlines() + # Filter out tags that don't match the service name, and tags for prerelease versions. + svc_versions = sorted([t.replace(f'{service}/v', '') for t in tags]) + if len(svc_versions) == 0: + raise Exception(f'No tags found for service: {service}') + return svc_versions[-1] + +def latest_among_services(services): + latest = '0.0.0' + for service in services: + candidate = latest_version(service) + if semver.compare(candidate, latest) > 0: + latest = candidate + return latest + +def main(): + parser = argparse.ArgumentParser(description='Create a new git tag for a service') + parser.add_argument('--service', type=str, help='The name of the Service') + parser.add_argument('--bump', type=str, help='The type of bump to apply to the version number') + parser.add_argument('--message', type=str, help='Message to include in git tag', default='[tag-tool-release]') + args = parser.parse_args() + + service = args.service + + if service == 'op-stack': + latest = latest_among_services(['op-node', 'op-batcher', 'op-proposer']) + else: + latest = latest_version(service) + + bumped = new_tag(service, semver.VersionInfo.parse(latest), args.bump) + + print(f'latest tag: {latest}') + print(f'new tag: {bumped}') + print('run the following commands to create the new tag:\n') + # special case for tagging op-node, op-batcher, and op-proposer together. All three would share the same semver + if args.service == 'op-stack': + print(GIT_TAG_COMMAND.format(tag=bumped.replace('op-stack', 'op-node'), message=args.message)) + print(GIT_PUSH_COMMAND.format(tag=bumped.replace('op-stack', 'op-node'))) + print(GIT_TAG_COMMAND.format(tag=bumped.replace('op-stack', 'op-batcher'), message=args.message)) + print(GIT_PUSH_COMMAND.format(tag=bumped.replace('op-stack', 'op-batcher'))) + print(GIT_TAG_COMMAND.format(tag=bumped.replace('op-stack', 'op-proposer'), message=args.message)) + print(GIT_PUSH_COMMAND.format(tag=bumped.replace('op-stack', 'op-proposer'))) + else: + print(GIT_TAG_COMMAND.format(tag=bumped, message=args.message)) + print(GIT_PUSH_COMMAND.format(tag=bumped)) + +if __name__ == "__main__": + main() + diff --git a/package.json b/package.json index a1ad30061851..f3cf78bca9d2 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "lint:ts:check": "npx nx run-many --target=lint:ts:check", "lint:check": "npx nx run-many --target=lint:check", "lint:fix": "npx nx run-many --target=lint:fix", + "lint:shellcheck": "find . -type f -name '*.sh' -not -path '*/node_modules/*' -not -path './packages/contracts-bedrock/lib/*' -not -path './packages/contracts-bedrock/kout*/*' -not -path './.husky/_/husky.sh' -exec sh -c 'echo \"Checking $1\"; shellcheck \"$1\"' _ {} \\;", "preinstall": "npx only-allow pnpm", "ready": "pnpm lint && pnpm test", "prepare": "husky install", @@ -30,6 +31,9 @@ "release:version": "changeset version && pnpm install --lockfile-only", "install:foundry": "curl -L https://foundry.paradigm.xyz | bash && pnpm update:foundry", "update:foundry": "bash ./ops/scripts/install-foundry.sh", + "check:foundry": "bash ./packages/contracts-bedrock/scripts/checks/check-foundry-install.sh", + "install:kontrol": "curl -L https://kframework.org/install | bash && pnpm update:kontrol", + "update:kontrol": "kup install kontrol --version v$(jq -r .kontrol < versions.json)", "install:abigen": "go install github.com/ethereum/go-ethereum/cmd/abigen@$(jq -r .abigen < versions.json)", "print:abigen": "abigen --version | sed -e 's/[^0-9]/ /g' -e 's/^ *//g' -e 's/ *$//g' -e 's/ /./g' -e 's/^/v/'", "check:abigen": "[[ $(pnpm -s print:abigen) = $(cat versions.json | jq -r '.abigen') ]] && echo '✓ abigen versions match' || (echo '✗ abigen version mismatch. Run `pnpm upgrade:abigen` to upgrade.' && exit 1)", @@ -40,14 +44,14 @@ "upgrade:slither": "jq '.slither = $v' --arg v $(pnpm -s print:slither) <<<$(cat versions.json) > versions.json" }, "devDependencies": { - "@babel/eslint-parser": "^7.23.3", + "@babel/eslint-parser": "^7.23.10", "@changesets/changelog-github": "^0.4.8", "@types/chai": "^4.3.11", "@types/chai-as-promised": "^7.1.8", "@types/mocha": "^10.0.6", - "@types/node": "^20.11.5", - "@typescript-eslint/eslint-plugin": "^6.19.1", - "@typescript-eslint/parser": "^6.19.1", + "@types/node": "^20.11.17", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", "chai": "^4.3.10", "depcheck": "^1.4.7", "doctoc": "^2.2.0", @@ -55,17 +59,17 @@ "eslint-config-prettier": "^9.1.0", "eslint-config-standard": "^16.0.3", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsdoc": "^35.1.2", + "eslint-plugin-jsdoc": "^48.0.6", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prefer-arrow": "^1.2.3", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-promise": "^5.1.0", "eslint-plugin-react": "^7.24.0", "eslint-plugin-unicorn": "^50.0.1", - "husky": "^8.0.3", + "husky": "^9.0.10", "lint-staged": "15.2.0", "mocha": "^10.2.0", - "nx": "17.2.8", + "nx": "18.1.2", "nyc": "^15.1.0", "prettier": "^2.8.0", "rimraf": "^5.0.5", diff --git a/packages/chain-mon/.env.example b/packages/chain-mon/.env.example index 68354e4b4313..0e10b0aaf530 100644 --- a/packages/chain-mon/.env.example +++ b/packages/chain-mon/.env.example @@ -63,6 +63,20 @@ FAULT_DETECTOR__L2_RPC_PROVIDER= # --bedrock Whether or not the service is running against a Bedrock chain (env: FAULT_DETECTOR__BEDROCK) BEDROCK=true +############################################################################### +# ↓ initialized-upgraded-mon ↓ # +############################################################################### + +# RPC pointing to network to monitor +INITIALIZED_UPGRADED_MON__RPC= + +# The block number to start monitoring from +# Defaults to the first bedrock block if unset. +INITIALIZED_UPGRADED_MON__START_BLOCK_NUMBER= + +# JSON array in the format [{ "label": , "address":
}, ... ] +INITIALIZED_UPGRADED_MON__CONTRACTS= + # Optional Params # --startbatchindex Batch index to start checking from. For bedrock chains, this is the L2 height to start from (env: FAULT_DETECTOR__START_BATCH_INDEX) diff --git a/packages/chain-mon/CHANGELOG.md b/packages/chain-mon/CHANGELOG.md index 0a9ca342a32a..fd80a56235f0 100644 --- a/packages/chain-mon/CHANGELOG.md +++ b/packages/chain-mon/CHANGELOG.md @@ -1,5 +1,32 @@ # @eth-optimism/drippie-mon +## 0.6.2 + +### Patch Changes + +- Updated dependencies [[`3ccd12fe5c8c4c5a6acbf370d474ffa8db816562`](https://github.com/ethereum-optimism/optimism/commit/3ccd12fe5c8c4c5a6acbf370d474ffa8db816562)]: + - @eth-optimism/sdk@3.2.2 + +## 0.6.1 + +### Patch Changes + +- Updated dependencies [[`a1329f21f33ecafe409990964d3af7bf05a8a756`](https://github.com/ethereum-optimism/optimism/commit/a1329f21f33ecafe409990964d3af7bf05a8a756)]: + - @eth-optimism/sdk@3.2.1 + +## 0.6.0 + +### Minor Changes + +- [#9334](https://github.com/ethereum-optimism/optimism/pull/9334) [`1ed50c44a5c4fb7244ede3b4c45ea7bbf144c1e5`](https://github.com/ethereum-optimism/optimism/commit/1ed50c44a5c4fb7244ede3b4c45ea7bbf144c1e5) Thanks [@smartcontracts](https://github.com/smartcontracts)! - Updates wd-mon inside chain-mon to support FPAC. + +### Patch Changes + +- Updated dependencies [[`1ed50c44a5c4fb7244ede3b4c45ea7bbf144c1e5`](https://github.com/ethereum-optimism/optimism/commit/1ed50c44a5c4fb7244ede3b4c45ea7bbf144c1e5), [`d99d425a4f73fba19ffcf180deb0ef48ff3b9a6a`](https://github.com/ethereum-optimism/optimism/commit/d99d425a4f73fba19ffcf180deb0ef48ff3b9a6a), [`79effc52e8b82d15b5eda43acf540ac6c5f8d5d7`](https://github.com/ethereum-optimism/optimism/commit/79effc52e8b82d15b5eda43acf540ac6c5f8d5d7), [`73a748575e7c3d67c293814a12bf41eee216163c`](https://github.com/ethereum-optimism/optimism/commit/73a748575e7c3d67c293814a12bf41eee216163c), [`44a2d9cec5f3b309b723b3e4dd8d29b5b70f1cc8`](https://github.com/ethereum-optimism/optimism/commit/44a2d9cec5f3b309b723b3e4dd8d29b5b70f1cc8)]: + - @eth-optimism/common-ts@0.8.8 + - @eth-optimism/sdk@3.2.0 + - @eth-optimism/contracts-bedrock@0.17.1 + ## 0.5.7 ### Patch Changes diff --git a/packages/chain-mon/package.json b/packages/chain-mon/package.json index f183602d76a0..540aaf3f7916 100644 --- a/packages/chain-mon/package.json +++ b/packages/chain-mon/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@eth-optimism/chain-mon", - "version": "0.5.7", + "version": "0.6.2", "description": "[Optimism] Chain monitoring services", "main": "dist/index", "types": "dist/index", @@ -16,6 +16,7 @@ "dev:replica-mon": "tsx watch ./src/replica-mon/service.ts", "dev:wallet-mon": "tsx watch ./src/wallet-mon/service.ts", "dev:wd-mon": "tsx watch ./src/wd-mon/service.ts", + "dev:initialized-upgraded-mon": "tsx watch ./src/initialized-upgraded-mon/service.ts", "start:balance-mon": "tsx ./src/balance-mon/service.ts", "start:drippie-mon": "tsx ./src/drippie-mon/service.ts", "start:fault-mon": "tsx ./src/fault-mon/service.ts", @@ -23,11 +24,11 @@ "start:replica-mon": "tsx ./src/replica-mon/service.ts", "start:wallet-mon": "tsx ./src/wallet-mon/service.ts", "start:wd-mon": "tsx ./src/wd-mon/service.ts", + "start:initialized-upgraded-mon": "tsx ./src/initialized-upgraded-mon/service.ts", "test": "hardhat test", "test:coverage": "nyc hardhat test && nyc merge .nyc_output coverage.json", "build": "tsc -p ./tsconfig.json", "clean": "rimraf dist/ ./tsconfig.tsbuildinfo", - "preinstall": "npx only-allow pnpm", "lint": "pnpm lint:fix && pnpm lint:check", "pre-commit": "lint-staged", "lint:fix": "pnpm lint:check --fix", @@ -54,15 +55,15 @@ "@types/dateformat": "^5.0.0", "chai-as-promised": "^7.1.1", "dateformat": "^4.5.1", - "dotenv": "^16.3.1", + "dotenv": "^16.4.5", "ethers": "^5.7.2" }, "devDependencies": { "@ethersproject/abstract-provider": "^5.7.0", "@nomiclabs/hardhat-ethers": "^2.2.3", "@nomiclabs/hardhat-waffle": "^2.0.6", - "hardhat": "^2.19.4", + "hardhat": "^2.20.1", "ts-node": "^10.9.2", "tsx": "^4.7.0" } -} +} \ No newline at end of file diff --git a/packages/chain-mon/src/index.ts b/packages/chain-mon/src/index.ts index 8e4d4163c0a1..9091eca096d6 100644 --- a/packages/chain-mon/src/index.ts +++ b/packages/chain-mon/src/index.ts @@ -4,3 +4,4 @@ export * from './fault-mon/index' export * from './multisig-mon/service' export * from './wd-mon/service' export * from './wallet-mon/service' +export * from './initialized-upgraded-mon/service' diff --git a/packages/chain-mon/src/initialized-upgraded-mon/service.ts b/packages/chain-mon/src/initialized-upgraded-mon/service.ts new file mode 100644 index 000000000000..5fe302063dd7 --- /dev/null +++ b/packages/chain-mon/src/initialized-upgraded-mon/service.ts @@ -0,0 +1,238 @@ +import { + BaseServiceV2, + StandardOptions, + Gauge, + Counter, + validators, + waitForProvider, +} from '@eth-optimism/common-ts' +import { getChainId, compareAddrs } from '@eth-optimism/core-utils' +import { Provider, TransactionResponse } from '@ethersproject/abstract-provider' +import mainnetConfig from '@eth-optimism/contracts-bedrock/deploy-config/mainnet.json' +import sepoliaConfig from '@eth-optimism/contracts-bedrock/deploy-config/sepolia.json' +import goerliConfig from '@eth-optimism/contracts-bedrock/deploy-config/goerli.json' + +import { version } from '../../package.json' + +const networks = { + 1: { + name: 'mainnet', + l1StartingBlockTag: mainnetConfig.l1StartingBlockTag, + }, + 10: { + name: 'op-mainnet', + l1StartingBlockTag: null, + }, + 11155111: { + name: 'sepolia', + l1StartingBlockTag: sepoliaConfig.l1StartingBlockTag, + }, + 11155420: { + name: 'op-sepolia', + l1StartingBlockTag: null, + }, + 5: { + name: 'goerli', + l1StartingBlockTag: goerliConfig.l1StartingBlockTag, + }, + 420: { + name: 'op-goerli', + l1StartingBlockTag: null, + }, +} + +// keccak256("Initialized(uint8)") = 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 +const topic_initialized = + '0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498' + +// keccak256("Upgraded(address)") = 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b +const topic_upgraded = + '0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b' + +type InitializedUpgradedMonOptions = { + rpc: Provider + startBlockNumber: number + contracts: string +} + +type InitializedUpgradedMonMetrics = { + initializedCalls: Counter + upgradedCalls: Counter + unexpectedRpcErrors: Counter +} + +type InitializedUpgradedMonState = { + chainId: number + highestUncheckedBlockNumber: number + contracts: Array<{ label: string; address: string }> +} + +export class InitializedUpgradedMonService extends BaseServiceV2< + InitializedUpgradedMonOptions, + InitializedUpgradedMonMetrics, + InitializedUpgradedMonState +> { + constructor( + options?: Partial + ) { + super({ + version, + name: 'initialized-upgraded-mon', + loop: true, + options: { + loopIntervalMs: 1000, + ...options, + }, + optionsSpec: { + rpc: { + validator: validators.provider, + desc: 'Provider for network to monitor balances on', + }, + startBlockNumber: { + validator: validators.num, + default: -1, + desc: 'L1 block number to start checking from', + public: true, + }, + contracts: { + validator: validators.str, + desc: 'JSON array of [{ label, address }] to monitor contracts for', + public: true, + }, + }, + metricsSpec: { + initializedCalls: { + type: Gauge, + desc: 'Successful transactions to tracked contracts emitting initialized event', + labels: ['label', 'address'], + }, + upgradedCalls: { + type: Gauge, + desc: 'Successful transactions to tracked contracts emitting upgraded event', + labels: ['label', 'address'], + }, + unexpectedRpcErrors: { + type: Counter, + desc: 'Number of unexpected RPC errors', + labels: ['section', 'name'], + }, + }, + }) + } + + protected async init(): Promise { + // Connect to L1. + await waitForProvider(this.options.rpc, { + logger: this.logger, + name: 'L1', + }) + + this.state.chainId = await getChainId(this.options.rpc) + + const l1StartingBlockTag = networks[this.state.chainId].l1StartingBlockTag + + if (this.options.startBlockNumber === -1) { + const block_number = + l1StartingBlockTag != null + ? (await this.options.rpc.getBlock(l1StartingBlockTag)).number + : 0 + this.state.highestUncheckedBlockNumber = block_number + } else { + this.state.highestUncheckedBlockNumber = this.options.startBlockNumber + } + + try { + this.state.contracts = JSON.parse(this.options.contracts) + } catch (e) { + throw new Error( + 'unable to start service because provided options is not valid json' + ) + } + } + + protected async main(): Promise { + if ( + (await this.options.rpc.getBlockNumber()) < + this.state.highestUncheckedBlockNumber + ) { + this.logger.info('Waiting for new blocks') + return + } + + const block = await this.options.rpc.getBlock( + this.state.highestUncheckedBlockNumber + ) + this.logger.info('Checking block', { + number: block.number, + }) + + const transactions: TransactionResponse[] = [] + for (const txHash of block.transactions) { + const t = await this.options.rpc.getTransaction(txHash) + transactions.push(t) + } + + for (const transaction of transactions) { + for (const contract of this.state.contracts) { + const to = + transaction.to != null ? transaction.to : transaction['creates'] + if (compareAddrs(contract.address, to)) { + try { + const transactionReceipt = await transaction.wait() + for (const log of transactionReceipt.logs) { + if (log.topics.includes(topic_initialized)) { + this.metrics.initializedCalls.inc({ + label: contract.label, + address: contract.address, + }) + this.logger.info('initialized event', { + label: contract.label, + address: contract.address, + }) + } else if (log.topics.includes(topic_upgraded)) { + this.metrics.upgradedCalls.inc({ + label: contract.label, + address: contract.address, + }) + this.logger.info('upgraded event', { + label: contract.label, + address: contract.address, + }) + } + } + } catch (err) { + // If error is due to transaction failing, ignore transaction + if ( + err.message.length >= 18 && + err.message.slice(0, 18) === 'transaction failed' + ) { + break + } + // Otherwise, we have an unexpected RPC error + this.logger.info(`got unexpected RPC error`, { + section: 'creations', + name: 'NULL', + err, + }) + + this.metrics.unexpectedRpcErrors.inc({ + section: 'creations', + name: 'NULL', + }) + + return + } + } + } + } + this.logger.info('Checked block', { + number: this.state.highestUncheckedBlockNumber, + }) + this.state.highestUncheckedBlockNumber++ + } +} + +if (require.main === module) { + const service = new InitializedUpgradedMonService() + service.run() +} diff --git a/packages/chain-mon/src/wallet-mon/service.ts b/packages/chain-mon/src/wallet-mon/service.ts index 745b32f00302..819f18333dc1 100644 --- a/packages/chain-mon/src/wallet-mon/service.ts +++ b/packages/chain-mon/src/wallet-mon/service.ts @@ -10,8 +10,6 @@ import { getChainId, compareAddrs } from '@eth-optimism/core-utils' import { Provider, TransactionResponse } from '@ethersproject/abstract-provider' import mainnetConfig from '@eth-optimism/contracts-bedrock/deploy-config/mainnet.json' import goerliConfig from '@eth-optimism/contracts-bedrock/deploy-config/goerli.json' -import l2OutputOracleArtifactsMainnet from '@eth-optimism/contracts-bedrock/deployments/mainnet/L2OutputOracleProxy.json' -import l2OutputOracleArtifactsGoerli from '@eth-optimism/contracts-bedrock/deployments/goerli/L2OutputOracleProxy.json' import { version } from '../../package.json' @@ -23,7 +21,7 @@ const networks = { { label: 'Proposer', wallet: mainnetConfig.l2OutputOracleProposer, - target: l2OutputOracleArtifactsMainnet.address, + target: '0xdfe97868233d1aa22e815a266982f2cf17685a27', }, { label: 'Batcher', @@ -39,7 +37,7 @@ const networks = { { label: 'Proposer', wallet: goerliConfig.l2OutputOracleProposer, - target: l2OutputOracleArtifactsGoerli.address, + target: '0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0', }, { label: 'Batcher', diff --git a/packages/chain-mon/src/wd-mon/constants.ts b/packages/chain-mon/src/wd-mon/constants.ts new file mode 100644 index 000000000000..0021c0de2606 --- /dev/null +++ b/packages/chain-mon/src/wd-mon/constants.ts @@ -0,0 +1,21 @@ +import { L2ChainID } from '@eth-optimism/sdk' + +// TODO: Consider moving to `@eth-optimism/constants` and generating from superchain registry. +// @see https://github.com/ethereum-optimism/optimism/pull/9041 + +/** + * Mapping of L2ChainIDs to the L1 block numbers where the wd-mon service should start looking for + * withdrawals by default. L1 block numbers here are based on the block number in which the + * OptimismPortal proxy contract was deployed to L1. + */ +export const DEFAULT_STARTING_BLOCK_NUMBERS: { + [ChainID in L2ChainID]?: number +} = { + [L2ChainID.OPTIMISM]: 17365802 as const, + [L2ChainID.OPTIMISM_GOERLI]: 8299684 as const, + [L2ChainID.OPTIMISM_SEPOLIA]: 4071248 as const, + [L2ChainID.BASE_MAINNET]: 17482143 as const, + [L2ChainID.BASE_GOERLI]: 8411116 as const, + [L2ChainID.BASE_SEPOLIA]: 4370901 as const, + [L2ChainID.ZORA_MAINNET]: 17473938 as const, +} diff --git a/packages/chain-mon/src/wd-mon/helpers.ts b/packages/chain-mon/src/wd-mon/helpers.ts deleted file mode 100644 index ed00acde5aff..000000000000 --- a/packages/chain-mon/src/wd-mon/helpers.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Provider } from '@ethersproject/abstract-provider' -import { Logger } from '@eth-optimism/common-ts' - -/** - * Finds - * - * @param - * @param - * @param - * @returns - */ -export const getLastFinalizedBlock = async ( - l1RpcProvider: Provider, - faultProofWindow: number, - logger: Logger -): Promise => { - let guessWindowStartBlock - try { - const l1Block = await l1RpcProvider.getBlock('latest') - - // The time corresponding to the start of the FPW, based on the current block. - const windowStartTime = l1Block.timestamp - faultProofWindow - - // Use the FPW to find the block number that is the start of the FPW. - guessWindowStartBlock = l1Block.number - faultProofWindow / 12 - - let block = await l1RpcProvider.getBlock(guessWindowStartBlock) - while (block.timestamp > windowStartTime) { - guessWindowStartBlock-- - block = await l1RpcProvider.getBlock(guessWindowStartBlock) - } - return block.number - } catch (err) { - logger.fatal('error when calling querying for block', { - errors: err, - }) - throw new Error( - `unable to find block number ${guessWindowStartBlock || 'latest'}` - ) - } -} diff --git a/packages/chain-mon/src/wd-mon/service.ts b/packages/chain-mon/src/wd-mon/service.ts index 62f4066fe8e9..86e56e12562a 100644 --- a/packages/chain-mon/src/wd-mon/service.ts +++ b/packages/chain-mon/src/wd-mon/service.ts @@ -6,30 +6,35 @@ import { validators, waitForProvider, } from '@eth-optimism/common-ts' -import { CrossChainMessenger } from '@eth-optimism/sdk' +import { getOEContract, DEFAULT_L2_CONTRACT_ADDRESSES } from '@eth-optimism/sdk' import { getChainId, sleep } from '@eth-optimism/core-utils' import { Provider } from '@ethersproject/abstract-provider' -import { Event } from 'ethers' +import { ethers } from 'ethers' import dateformat from 'dateformat' import { version } from '../../package.json' -import { getLastFinalizedBlock as getLastFinalizedBlock } from './helpers' +import { DEFAULT_STARTING_BLOCK_NUMBERS } from './constants' type Options = { l1RpcProvider: Provider l2RpcProvider: Provider + optimismPortalAddress: string + l2ToL1MessagePasserAddress: string startBlockNumber: number + eventBlockRange: number sleepTimeMs: number } type Metrics = { + highestBlockNumber: Gauge withdrawalsValidated: Gauge isDetectingForgeries: Gauge nodeConnectionFailures: Gauge } type State = { - messenger: CrossChainMessenger + portal: ethers.Contract + messenger: ethers.Contract highestUncheckedBlockNumber: number faultProofWindow: number forgeryDetected: boolean @@ -54,12 +59,30 @@ export class WithdrawalMonitor extends BaseServiceV2 { validator: validators.provider, desc: 'Provider for interacting with L2', }, + optimismPortalAddress: { + validator: validators.address, + default: null, + desc: 'Address of the OptimismPortal proxy contract on L1', + public: true, + }, + l2ToL1MessagePasserAddress: { + validator: validators.address, + default: DEFAULT_L2_CONTRACT_ADDRESSES.BedrockMessagePasser as string, + desc: 'Address of the L2ToL1MessagePasser contract on L2', + public: true, + }, startBlockNumber: { validator: validators.num, default: -1, desc: 'L1 block number to start checking from', public: true, }, + eventBlockRange: { + validator: validators.num, + default: 2000, + desc: 'Number of blocks to query for events over per loop', + public: true, + }, sleepTimeMs: { validator: validators.num, default: 15000, @@ -68,6 +91,11 @@ export class WithdrawalMonitor extends BaseServiceV2 { }, }, metricsSpec: { + highestBlockNumber: { + type: Gauge, + desc: 'Highest block number (checked and known)', + labels: ['type'], + }, withdrawalsValidated: { type: Gauge, desc: 'Latest L1 Block (checked and known)', @@ -99,38 +127,41 @@ export class WithdrawalMonitor extends BaseServiceV2 { name: 'L2', }) - this.state.messenger = new CrossChainMessenger({ - l1SignerOrProvider: this.options.l1RpcProvider, - l2SignerOrProvider: this.options.l2RpcProvider, - l1ChainId: await getChainId(this.options.l1RpcProvider), - l2ChainId: await getChainId(this.options.l2RpcProvider), - bedrock: true, - }) + // Need L2 chain ID to resolve contract addresses. + const l2ChainId = await getChainId(this.options.l2RpcProvider) - // Not detected by default. - this.state.forgeryDetected = false + // Create the OptimismPortal contract instance. If the optimismPortal option is not provided + // then the SDK will attempt to resolve the address automatically based on the L2 chain ID. If + // the SDK isn't aware of the L2 chain ID then it will throw an error that makes it clear the + // user needs to provide this value explicitly. + this.state.portal = getOEContract('OptimismPortal', l2ChainId, { + signerOrProvider: this.options.l1RpcProvider, + address: this.options.optimismPortalAddress, + }) - this.state.faultProofWindow = - await this.state.messenger.getChallengePeriodSeconds() - this.logger.info( - `fault proof window is ${this.state.faultProofWindow} seconds` - ) + // Create the L2ToL1MessagePasser contract instance. If the l2ToL1MessagePasser option is not + // provided then we'll use the default address which typically should be correct. It's very + // unlikely that any user would change this address so this should work in 99% of cases. If we + // really wanted to be extra safe we could do some sanity checks to make sure the contract has + // the interface we need but doesn't seem important for now. + this.state.messenger = getOEContract('L2ToL1MessagePasser', l2ChainId, { + signerOrProvider: this.options.l2RpcProvider, + address: this.options.l2ToL1MessagePasserAddress, + }) - // Set the start block number. + // Previous versions of wd-mon would try to pick the starting block number automatically but + // this had the possibility of missing certain withdrawals if the service was restarted at the + // wrong time. Given the added complexity of finding a starting point automatically after FPAC, + // it's much easier to simply start a fixed block number than trying to do something fancy. Use + // the default configured in this service or use zero if no default is defined. + this.state.highestUncheckedBlockNumber = this.options.startBlockNumber if (this.options.startBlockNumber === -1) { - // We default to starting from the last finalized block. - this.state.highestUncheckedBlockNumber = await getLastFinalizedBlock( - this.options.l1RpcProvider, - this.state.faultProofWindow, - this.logger - ) - } else { - this.state.highestUncheckedBlockNumber = this.options.startBlockNumber + this.state.highestUncheckedBlockNumber = + DEFAULT_STARTING_BLOCK_NUMBERS[l2ChainId] || 0 } - this.logger.info(`starting L1 block height`, { - startBlockNumber: this.state.highestUncheckedBlockNumber, - }) + // Default state is that forgeries have not been detected. + this.state.forgeryDetected = false } // K8s healthcheck @@ -143,94 +174,131 @@ export class WithdrawalMonitor extends BaseServiceV2 { } async main(): Promise { - // Get current block number + // Get the latest L1 block number. let latestL1BlockNumber: number try { latestL1BlockNumber = await this.options.l1RpcProvider.getBlockNumber() } catch (err) { + // Log the issue so we can debug it. this.logger.error(`got error when connecting to node`, { error: err, node: 'l1', section: 'getBlockNumber', }) + + // Increment the metric so we can detect the issue. this.metrics.nodeConnectionFailures.inc({ layer: 'l1', section: 'getBlockNumber', }) - await sleep(this.options.sleepTimeMs) - return + + // Sleep for a little to give intermittent errors a chance to recover. + return sleep(this.options.sleepTimeMs) } - // See if we have a new unchecked block + // Update highest block number metrics so we can keep track of how the service is doing. + this.metrics.highestBlockNumber.set({ type: 'known' }, latestL1BlockNumber) + this.metrics.highestBlockNumber.set( + { type: 'checked' }, + this.state.highestUncheckedBlockNumber + ) + + // Check if the RPC provider is behind us for some reason. Can happen occasionally, + // particularly if connected to an RPC provider that load balances over multiple nodes that + // might not be perfectly in sync. if (latestL1BlockNumber <= this.state.highestUncheckedBlockNumber) { - // The RPC provider is behind us, wait a bit - await sleep(this.options.sleepTimeMs) - return + // Sleep for a little to give the RPC a chance to catch up. + return sleep(this.options.sleepTimeMs) } + // Generally better to use a relatively small block range because it means this service can be + // used alongside many different types of L1 nodes. For instance, Geth will typically only + // support a block range of 2000 blocks out of the box. + const toBlockNumber = Math.min( + this.state.highestUncheckedBlockNumber + this.options.eventBlockRange, + latestL1BlockNumber + ) + + // Useful to log this stuff just in case we get stuck or something. this.logger.info(`checking recent blocks`, { fromBlockNumber: this.state.highestUncheckedBlockNumber, - toBlockNumber: latestL1BlockNumber, + toBlockNumber, }) - // Perform the check - let proofEvents: Event[] + // Query for WithdrawalProven events within the specified block range. + let events: ethers.Event[] try { - // The query includes events in the blockNumbers given as the last two arguments - proofEvents = - await this.state.messenger.contracts.l1.OptimismPortal.queryFilter( - this.state.messenger.contracts.l1.OptimismPortal.filters.WithdrawalProven(), - this.state.highestUncheckedBlockNumber, - latestL1BlockNumber - ) + events = await this.state.portal.queryFilter( + this.state.portal.filters.WithdrawalProven(), + this.state.highestUncheckedBlockNumber, + toBlockNumber + ) } catch (err) { + // Log the issue so we can debug it. this.logger.error(`got error when connecting to node`, { error: err, node: 'l1', section: 'querying for WithdrawalProven events', }) + + // Increment the metric so we can detect the issue. this.metrics.nodeConnectionFailures.inc({ layer: 'l1', section: 'querying for WithdrawalProven events', }) - // connection error, wait then restart - await sleep(this.options.sleepTimeMs) - return + + // Sleep for a little to give intermittent errors a chance to recover. + return sleep(this.options.sleepTimeMs) } - for (const proofEvent of proofEvents) { - const exists = - await this.state.messenger.contracts.l2.BedrockMessagePasser.sentMessages( - proofEvent.args.withdrawalHash - ) - const block = await proofEvent.getBlock() - const now = new Date(block.timestamp * 1000) - const dateString = dateformat( - now, - 'mmmm dS, yyyy, h:MM:ss TT', - true // use UTC time - ) - const provenAt = `${dateString} UTC` + // Go over all the events and check if the withdrawal hash actually exists on L2. + for (const event of events) { + // Could consider using multicall here but this is efficient enough for now. + const hash = event.args.withdrawalHash + const exists = await this.state.messenger.sentMessages(hash) + + // Hopefully the withdrawal exists! if (exists) { - this.metrics.withdrawalsValidated.inc() + // Unlike below we don't grab the timestamp here because it adds an unnecessary request. this.logger.info(`valid withdrawal`, { - withdrawalHash: proofEvent.args.withdrawalHash, - provenAt, + withdrawalHash: event.args.withdrawalHash, }) + + // Bump the withdrawals metric so we can keep track. + this.metrics.withdrawalsValidated.inc() } else { + // Grab and format the timestamp so it's clear how much time is left. + const block = await event.getBlock() + const ts = `${dateformat( + new Date(block.timestamp * 1000), + 'mmmm dS, yyyy, h:MM:ss TT', + true + )} UTC` + + // Uh oh! this.logger.error(`withdrawalHash not seen on L2`, { - withdrawalHash: proofEvent.args.withdrawalHash, - provenAt, + withdrawalHash: event.args.withdrawalHash, + provenAt: ts, }) + + // Change to forgery state. this.state.forgeryDetected = true this.metrics.isDetectingForgeries.set(1) - return + + // Return early so that we never increment the highest unchecked block number and therefore + // will continue to loop on this forgery indefinitely. We probably want to change this + // behavior at some point so that we keep scanning for additional forgeries since the + // existence of one forgery likely implies the existence of many others. + return sleep(this.options.sleepTimeMs) } } - this.state.highestUncheckedBlockNumber = latestL1BlockNumber + 1 + // Increment the highest unchecked block number for the next loop. + this.state.highestUncheckedBlockNumber = toBlockNumber - // If we got through the above without throwing an error, we should be fine to reset. + // If we got through the above without throwing an error, we should be fine to reset. Only case + // where this is relevant is if something is detected as a forgery accidentally and the error + // doesn't happen again on the next loop. this.state.forgeryDetected = false this.metrics.isDetectingForgeries.set(0) } diff --git a/packages/common-ts/CHANGELOG.md b/packages/common-ts/CHANGELOG.md index 4b034ba17078..3d2733c11f53 100644 --- a/packages/common-ts/CHANGELOG.md +++ b/packages/common-ts/CHANGELOG.md @@ -1,5 +1,11 @@ # @eth-optimism/common-ts +## 0.8.8 + +### Patch Changes + +- [#9334](https://github.com/ethereum-optimism/optimism/pull/9334) [`1ed50c44a5c4fb7244ede3b4c45ea7bbf144c1e5`](https://github.com/ethereum-optimism/optimism/commit/1ed50c44a5c4fb7244ede3b4c45ea7bbf144c1e5) Thanks [@smartcontracts](https://github.com/smartcontracts)! - Adds a new validator for address types. + ## 0.8.7 ### Patch Changes diff --git a/packages/common-ts/package.json b/packages/common-ts/package.json index c3a473a7155a..4ad287f66bd2 100644 --- a/packages/common-ts/package.json +++ b/packages/common-ts/package.json @@ -1,6 +1,6 @@ { "name": "@eth-optimism/common-ts", - "version": "0.8.7", + "version": "0.8.8", "description": "[Optimism] Advanced typescript tooling used by various services", "main": "dist/index", "types": "dist/index", @@ -12,7 +12,6 @@ "all": "pnpm clean && pnpm build && pnpm test && pnpm lint:fix && pnpm lint", "build": "tsc -p tsconfig.json", "clean": "rimraf dist/ ./tsconfig.tsbuildinfo", - "preinstall": "npx only-allow pnpm", "lint:check": "eslint . --max-warnings=0", "lint:fix": "pnpm lint:check --fix", "lint": "pnpm lint:fix && pnpm lint:check", @@ -35,18 +34,18 @@ }, "dependencies": { "@eth-optimism/core-utils": "workspace:*", - "@sentry/node": "^7.94.1", + "@sentry/node": "^7.99.0", "bcfg": "^0.2.1", "body-parser": "^1.20.2", "commander": "^11.1.0", - "dotenv": "^16.3.1", + "dotenv": "^16.4.5", "envalid": "^8.0.0", "ethers": "^5.7.2", "express": "^4.18.2", "express-prom-bundle": "^7.0.0", "lodash": "^4.17.21", "morgan": "^1.10.0", - "pino": "^8.17.2", + "pino": "^8.19.0", "pino-multi-stream": "^6.0.0", "pino-sentry": "^0.14.0", "prom-client": "^14.2.0" diff --git a/packages/common-ts/src/base-service/validators.ts b/packages/common-ts/src/base-service/validators.ts index a919e700ac52..5eced2306707 100644 --- a/packages/common-ts/src/base-service/validators.ts +++ b/packages/common-ts/src/base-service/validators.ts @@ -49,6 +49,14 @@ const logLevel = makeValidator((input) => { } }) +const address = makeValidator((input) => { + if (!ethers.utils.isHexString(input, 20)) { + throw new Error(`expected input to be an address: ${input}`) + } else { + return input as `0x${string}` + } +}) + export const validators = { str, bool, @@ -63,4 +71,5 @@ export const validators = { jsonRpcProvider, staticJsonRpcProvider, logLevel, + address, } diff --git a/packages/contracts-bedrock/.gas-snapshot b/packages/contracts-bedrock/.gas-snapshot index c943a2fb8384..d3f5f6634f59 100644 --- a/packages/contracts-bedrock/.gas-snapshot +++ b/packages/contracts-bedrock/.gas-snapshot @@ -1,11 +1,11 @@ GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 356552) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2954759) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 549114) +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2954737) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 549159) GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4061135) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 450330) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 450308) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3496057) GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 59803) -GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 92973) -GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 68382) -GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 68991) -GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 155559) \ No newline at end of file +GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 92930) +GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 68360) +GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 69013) +GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 155551) \ No newline at end of file diff --git a/packages/contracts-bedrock/.gitignore b/packages/contracts-bedrock/.gitignore index a92ac864e649..8b673a6cb333 100644 --- a/packages/contracts-bedrock/.gitignore +++ b/packages/contracts-bedrock/.gitignore @@ -13,6 +13,7 @@ coverage.out # Testing State .testdata +kontrol_prove_report.xml # Scripts scripts/go-ffi/go-ffi diff --git a/packages/contracts-bedrock/CHANGELOG.md b/packages/contracts-bedrock/CHANGELOG.md index 52af9bab0fb3..881f44272508 100644 --- a/packages/contracts-bedrock/CHANGELOG.md +++ b/packages/contracts-bedrock/CHANGELOG.md @@ -1,5 +1,11 @@ # @eth-optimism/contracts-bedrock +## 0.17.1 + +### Patch Changes + +- [#9415](https://github.com/ethereum-optimism/optimism/pull/9415) [`79effc52e8b82d15b5eda43acf540ac6c5f8d5d7`](https://github.com/ethereum-optimism/optimism/commit/79effc52e8b82d15b5eda43acf540ac6c5f8d5d7) Thanks [@nitaliano](https://github.com/nitaliano)! - Bumps version so fpac contracts exist for SDK to consume + ## 0.16.2 ### Patch Changes diff --git a/packages/contracts-bedrock/README.md b/packages/contracts-bedrock/README.md index 739feb8423bf..216e84b7af58 100644 --- a/packages/contracts-bedrock/README.md +++ b/packages/contracts-bedrock/README.md @@ -1,58 +1,268 @@ -# Optimism Smart Contracts (Bedrock) +# OP Stack Smart Contracts + +This package contains the L1 and L2 smart contracts for the OP Stack. +Detailed specifications for the contracts contained within this package can be found at [specs.optimism.io](https://specs.optimism.io). +High-level information about these contracts can be found within this README and within the [Optimism Developer Docs](https://docs.optimism.io). + + + +## Table of Contents + +- [Architecture Overview](#architecture-overview) + - [Core L1 Smart Contracts](#core-l1-smart-contracts) + - [Notes for Core L1 Smart Contracts](#notes-for-core-l1-smart-contracts) + - [Core L2 Smart Contracts](#core-l2-smart-contracts) + - [Notes for Core L2 Smart Contracts](#notes-for-core-l2-smart-contracts) + - [Smart Contract Proxies](#smart-contract-proxies) +- [External Usage](#external-usage) + - [Using OP Stack Contracts in Solidity](#using-op-stack-contracts-in-solidity) + - [Using OP Stack Contracts in JavaScript](#using-op-stack-contracts-in-javascript) + - [Deployed Addresses](#deployed-addresses) +- [Contributing](#contributing) + - [Contributing Guide](#contributing-guide) + - [Style Guide](#style-guide) +- [Deployment](#deployment) + - [Configuration](#configuration) + - [Execution](#execution) + - [Deploying a single contract](#deploying-a-single-contract) +- [Testing](#testing) + - [Test Setup](#test-setup) + - [Static Analysis](#static-analysis) + + + +## Architecture Overview + +> **NOTE**: Smart contract names in the architecture diagrams below are links to source code. Click them! + +### Core L1 Smart Contracts + +Below you'll find an architecture diagram describing the core L1 smart contracts for the OP Stack. +Smart contracts that are considered "peripheral" and not core to the operation of the OP Stack system are described separately. + +```mermaid +graph LR + subgraph "External Contracts" + ExternalERC20(External ERC20 Contracts) + ExternalERC721(External ERC721 Contracts) + end + + subgraph "L1 Smart Contracts" + BatchDataEOA(Batch Inbox Address) + L1StandardBridge(L1StandardBridge) + L1ERC721Bridge(L1ERC721Bridge) + L1CrossDomainMessenger(L1CrossDomainMessenger) + L2OutputOracle(L2OutputOracle) + OptimismPortal(OptimismPortal) + SuperchainConfig(SuperchainConfig) + SystemConfig(SystemConfig) + end + + subgraph "User Interactions" + Users(Users) + end + + subgraph "System Interactions" + Batcher(Batcher) + Proposer(Proposer) + Guardian(Guardian) + end + + subgraph "Layer 2 Interactions" + L2Nodes(Layer 2 Nodes) + end + + Batcher -->|publish transaction batches| BatchDataEOA + Proposer -->|propose state outputs| L2OutputOracle + Guardian -->|remove invalid state outputs| L2OutputOracle + + ExternalERC20 <-->|mint/burn/transfer| L1StandardBridge + ExternalERC721 <-->|mint/burn/transfer| L1ERC721Bridge + + L1StandardBridge <-->|send/receive message| L1CrossDomainMessenger + L1ERC721Bridge <-->|send/receive message| L1CrossDomainMessenger + L1CrossDomainMessenger <-->|package/send/receive message| OptimismPortal + L1StandardBridge -.->|query pause state| SuperchainConfig + L1ERC721Bridge -.->|query pause state| SuperchainConfig + L1CrossDomainMessenger -.->|query pause state| SuperchainConfig + OptimismPortal -.->|query pause state| SuperchainConfig + + OptimismPortal -.->|query config| SystemConfig + OptimismPortal -.->|query proposed states| L2OutputOracle + + Users <-->|deposit/withdraw ETH/ERC20| L1StandardBridge + Users <-->|deposit/withdraw ERC721| L1ERC721Bridge + Users -->|prove/execute withdrawal transactions| OptimismPortal + + L2Nodes -.->|fetch transaction batches| BatchDataEOA + L2Nodes -.->|verify output roots| L2OutputOracle + L2Nodes -.->|fetch deposit events| OptimismPortal + + classDef extContracts stroke:#ff9,stroke-width:2px; + classDef l1Contracts stroke:#bbf,stroke-width:2px; + classDef l1EOA stroke:#bbb,stroke-width:2px; + classDef userInt stroke:#f9a,stroke-width:2px; + classDef systemUser stroke:#f9a,stroke-width:2px; + classDef l2Nodes stroke:#333,stroke-width:2px + class ExternalERC20,ExternalERC721 extContracts; + class L1StandardBridge,L1ERC721Bridge,L1CrossDomainMessenger,L2OutputOracle,OptimismPortal,SuperchainConfig,SystemConfig l1Contracts; + class BatchDataEOA l1EOA; + class Users userInt; + class Batcher,Proposer,Guardian systemUser; + class L2Nodes l2Nodes; +``` -[![codecov](https://codecov.io/gh/ethereum-optimism/optimism/branch/develop/graph/badge.svg?token=0VTG7PG7YR&flag=contracts-bedrock-tests)](https://codecov.io/gh/ethereum-optimism/optimism) +#### Notes for Core L1 Smart Contracts + +- The `Batch Data Address` described above (**highlighted in GREY**) is *not* a smart contract and is instead simply an arbitrarily chosen account that is assumed to have no known private key. This account is typically chosen as the account `0xFF0000....` where `` is chain ID of the Layer 2 network for which the data is being posted. For instance, for OP Mainnet, this account is chosen as `0xFF00000000000000000000000000000000000010`. However, this is not a strict requirement and some OP Stack chains may not follow this convention. +- Smart contracts that sit behind `Proxy` contracts are **highlighted in BLUE**. Refer to the [Smart Contract Proxies](#smart-contract-proxies) section below to understand how these proxies are designed. + - The `L1CrossDomainMessenger` contract sits behind the [`ResolvedDelegateProxy`](https://github.com/ethereum-optimism/optimism/tree/develop/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol) contract, a legacy proxy contract type used within older versions of the OP Stack. This proxy type is used exclusively for the `L1CrossDomainMessenger` to maintain backwards compatibility. + - The `L1StandardBridge` contract sits behind the [`L1ChugSplashProxy`](https://github.com/ethereum-optimism/optimism/tree/develop/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol) contract, a legacy proxy contract type used within older versions of the OP Stack. This proxy type is used exclusively for the `L1StandardBridge` contract to maintain backwards compatibility. + +### Core L2 Smart Contracts + +Here you'll find an architecture diagram describing the core OP Stack smart contracts that exist natively on the L2 chain itself. + +```mermaid +graph LR + subgraph "Layer 1 (Ethereum)" + L1SmartContracts(L1 Smart Contracts) + end + + subgraph "L2 Client" + L2Node(L2 Node) + end + + subgraph "L2 System Contracts" + L1Block(L1Block) + GasPriceOracle(GasPriceOracle) + L1FeeVault(L1FeeVault) + BaseFeeVault(BaseFeeVault) + SequencerFeeVault(SequencerFeeVault) + end + + subgraph "L2 Bridge Contracts" + L2CrossDomainMessenger(L2CrossDomainMessenger) + L2ToL1MessagePasser(L2ToL1MessagePasser) + L2StandardBridge(L2StandardBridge) + L2ERC721Bridge(L2ERC721Bridge) + end + + subgraph "Transactions" + DepositTransaction(Deposit Transaction) + UserTransaction(User Transaction) + end + + subgraph "External Contracts" + ExternalERC20(External ERC20 Contracts) + ExternalERC721(External ERC721 Contracts) + end + + subgraph "Remaining L2 Universe" + OtherContracts(Any Contracts and Addresses) + end + + L2Node -.->|derives chain from| L1SmartContracts + L2Node -->|updates| L1Block + L2Node -->|distributes fees to| L1FeeVault + L2Node -->|distributes fees to| BaseFeeVault + L2Node -->|distributes fees to| SequencerFeeVault + L2Node -->|derives from deposits| DepositTransaction + L2Node -->|derives from chain data| UserTransaction + + UserTransaction -->|can trigger| OtherContracts + DepositTransaction -->|maybe triggers| L2CrossDomainMessenger + DepositTransaction -->|can trigger| OtherContracts + + ExternalERC20 <-->|mint/burn/transfer| L2StandardBridge + ExternalERC721 <-->|mint/burn/transfer| L2ERC721Bridge + + L2StandardBridge <-->|sends/receives messages| L2CrossDomainMessenger + L2ERC721Bridge <-->|sends/receives messages| L2CrossDomainMessenger + GasPriceOracle -.->|queries| L1Block + L2CrossDomainMessenger -->|sends messages| L2ToL1MessagePasser + + classDef extContracts stroke:#ff9,stroke-width:2px; + classDef l2Contracts stroke:#bbf,stroke-width:2px; + classDef transactions stroke:#fba,stroke-width:2px; + classDef l2Node stroke:#f9a,stroke-width:2px; + + class ExternalERC20,ExternalERC721 extContracts; + class L2CrossDomainMessenger,L2ToL1MessagePasser,L2StandardBridge,L2ERC721Bridge l2Contracts; + class L1Block,L1FeeVault,BaseFeeVault,SequencerFeeVault,GasPriceOracle l2Contracts; + class UserTransaction,DepositTransaction transactions; + class L2Node l2Node; +``` -This package contains the smart contracts that compose the on-chain component of Optimism's upcoming Bedrock upgrade. -We've tried to maintain 100% backwards compatibility with the existing system while also introducing new useful features. -You can find detailed specifications for the contracts contained within this package [here](../../specs). +#### Notes for Core L2 Smart Contracts -A style guide we follow for writing contracts can be found [here](./STYLE_GUIDE.md). +- Contracts highlighted as "L2 System Contracts" are updated or mutated automatically as part of the chain derivation process. Users typically do not mutate these contracts directly, except in the case of the `FeeVault` contracts where any user may trigger a withdrawal of collected fees to the pre-determined withdrawal address. +- Smart contracts that sit behind `Proxy` contracts are **highlighted in BLUE**. Refer to the [Smart Contract Proxies](#smart-contract-proxies) section below to understand how these proxies are designed. +- User interactions for the "L2 Bridge Contracts" have been omitted from this diagram but largely follow the same user interactions described in the architecture diagram for the [Core L1 Smart Contracts](#core-l1-smart-contracts). -## Contracts Overview +### Smart Contract Proxies -### Contracts deployed to L1 +Most L1 and L2 smart contracts for OP Stack chains today sit behind `Proxy` contracts that themselves are managed by a `ProxyAdmin` contract. +The `ProxyAdmin` contract is controlled by some `owner` address that can be any EOA or smart contract. +Below you'll find a diagram that explains the behavior of the typical proxy contract. -| Name | Proxy Type | Description | -| ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | -| [`L1CrossDomainMessenger`](../../specs/messengers.md) | [`ResolvedDelegateProxy`](./contracts/legacy/ResolvedDelegateProxy.sol) | High-level interface for sending messages to and receiving messages from Optimism | -| [`L1StandardBridge`](../../specs/bridges.md) | [`L1ChugSplashProxy`](./contracts/legacy/L1ChugSplashProxy.sol) | Standardized system for transferring ERC20 tokens to/from Optimism | -| [`L2OutputOracle`](../../specs/proposals.md#l2-output-oracle-smart-contract) | [`Proxy`](./contracts/universal/Proxy.sol) | Stores commitments to the state of Optimism which can be used by contracts on L1 to access L2 state | -| [`OptimismPortal`](../../specs/deposits.md#deposit-contract) | [`Proxy`](./contracts/universal/Proxy.sol) | Low-level message passing interface | -| [`OptimismMintableERC20Factory`](../../specs/predeploys.md#optimismmintableerc20factory) | [`Proxy`](./contracts/universal/Proxy.sol) | Deploys standard `OptimismMintableERC20` tokens that are compatible with either `StandardBridge` | -| [`ProxyAdmin`](../../specs/TODO) | - | Contract that can upgrade L1 contracts | +```mermaid +graph LR + ProxyAdminOwner(Proxy Admin Owner) + ProxyAdmin(ProxyAdmin) -### Contracts deployed to L2 + subgraph "Logical Smart Contract" + Proxy(Proxy) + Implementation(Implementation) + end -| Name | Proxy Type | Description | -| ---------------------------------------------------------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------ | -| [`GasPriceOracle`](../../specs/predeploys.md#ovm_gaspriceoracle) | [`Proxy`](./contracts/universal/Proxy.sol) | Stores L2 gas price configuration values | -| [`L1Block`](../../specs/predeploys.md#l1block) | [`Proxy`](./contracts/universal/Proxy.sol) | Stores L1 block context information (e.g., latest known L1 block hash) | -| [`L2CrossDomainMessenger`](../../specs/predeploys.md#l2crossdomainmessenger) | [`Proxy`](./contracts/universal/Proxy.sol) | High-level interface for sending messages to and receiving messages from L1 | -| [`L2StandardBridge`](../../specs/predeploys.md#l2standardbridge) | [`Proxy`](./contracts/universal/Proxy.sol) | Standardized system for transferring ERC20 tokens to/from L1 | -| [`L2ToL1MessagePasser`](../../specs/predeploys.md#ovm_l2tol1messagepasser) | [`Proxy`](./contracts/universal/Proxy.sol) | Low-level message passing interface | -| [`SequencerFeeVault`](../../specs/predeploys.md#sequencerfeevault) | [`Proxy`](./contracts/universal/Proxy.sol) | Vault for L2 transaction fees | -| [`OptimismMintableERC20Factory`](../../specs/predeploys.md#optimismmintableerc20factory) | [`Proxy`](./contracts/universal/Proxy.sol) | Deploys standard `OptimismMintableERC20` tokens that are compatible with either `StandardBridge` | -| [`L2ProxyAdmin`](../../specs/TODO) | - | Contract that can upgrade L2 contracts when sent a transaction from L1 | + ProxyAdminOwner -->|manages| ProxyAdmin + ProxyAdmin -->|upgrades| Proxy + Proxy -->|delegatecall| Implementation -### Legacy and deprecated contracts + classDef l1Contracts stroke:#bbf,stroke-width:2px; + classDef systemUser stroke:#f9a,stroke-width:2px; + class Proxy l1Contracts; + class ProxyAdminOwner systemUser; +``` -| Name | Location | Proxy Type | Description | -| --------------------------------------------------------------- | -------- | ------------------------------------------ | ------------------------------------------------------------------------------------- | -| [`AddressManager`](./contracts/legacy/AddressManager.sol) | L1 | - | Legacy upgrade mechanism (unused in Bedrock) | -| [`DeployerWhitelist`](./contracts/legacy/DeployerWhitelist.sol) | L2 | [`Proxy`](./contracts/universal/Proxy.sol) | Legacy contract for managing allowed deployers (unused since EVM Equivalence upgrade) | -| [`L1BlockNumber`](./contracts/legacy/L1BlockNumber.sol) | L2 | [`Proxy`](./contracts/universal/Proxy.sol) | Legacy contract for accessing latest known L1 block number, replaced by `L1Block` | +## External Usage -## Installation +### Using OP Stack Contracts in Solidity -We export contract ABIs, contract source code, and contract deployment information for this package via `npm`: +OP Stack smart contracts are published to NPM and can be installed via: -```shell -npm install @eth-optimism/contracts-bedrock +```sh +npm install @eth-optimism/contracts-bedrock. ``` +Refer to the [Optimism Developer Docs](https://docs.optimism.io/builders/dapp-developers/contracts/system-contracts#using-system-contracts-in-solidity) for additional information about how to use this package. + +### Using OP Stack Contracts in JavaScript + +Contract ABIs and addresses are published to NPM in a separate package and can be installed via: + +```sh +npm install @eth-optimism/contracts-ts +``` + +Refer to the [Optimism Developer Docs](https://docs.optimism.io/builders/dapp-developers/contracts/system-contracts#using-system-contracts-in-javascript) for additional information about how to use this package. + +### Deployed Addresses + +See the [Optimism Developer Docs](https://docs.optimism.io/chain/addresses) for the deployed addresses of these smart contracts for OP Mainnet and OP Sepolia. + ## Contributing -For all information about working on and contributing to Optimism's smart contracts, please see [CONTRIBUTING.md](./CONTRIBUTING.md) +### Contributing Guide + +Contributions to the OP Stack are always welcome. +Please refer to the [CONTRIBUTING.md](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/CONTRIBUTING.md) for more information about how to contribute to the OP Stack smart contracts. + +### Style Guide + +OP Stack smart contracts should be written according to the [STYLE_GUIDE.md](./STYLE_GUIDE.md) found within this repository. +Maintaining a consistent code style makes code easier to review and maintain, ultimately making the development process safer. ## Deployment @@ -85,6 +295,8 @@ Run the deployment with state diffs by executing: `forge script -vvv scripts/Dep All of the functions for deploying a single contract are `public` meaning that the `--sig` argument to `forge script` can be used to target the deployment of a single contract. +## Testing + ### Test Setup The Solidity unit tests use the same codepaths to set up state that are used in production. The same L1 deploy script is used to deploy the L1 contracts for the in memory tests @@ -97,15 +309,17 @@ since some contracts are deployed using `CREATE`. Run `pnpm clean` and rerun the ### Static Analysis -`contracts-bedrock` uses [slither](https://github.com/crytic/slither) as its primary static analysis tool. When opening a pr that includes changes to `contracts-bedrock`, you should -verify that slither did not detect any new issues by running `pnpm slither:check`. +`contracts-bedrock` uses [slither](https://github.com/crytic/slither) as its primary static analysis tool. +Slither will be run against PRs as part of CI, and new findings will be reported as a comment on the PR. +CI will fail if there are any new findings of medium or higher severity, as configured in the repo's Settings > Code Security and Analysis > Code Scanning > Protection rules setting. + +There are two corresponding jobs in CI: one calls "Slither Analysis" and one called "Code scanning results / Slither". +The former will always pass if Slither runs successfully, and the latter will fail if there are any new findings of medium or higher severity. + +Existing findings can be found in the repo's Security tab > [Code Scanning](https://github.com/ethereum-optimism/optimism/security/code-scanning) section. +You can view findings for a specific PR using the `pr:{number}` filter, such [`pr:9405`](https://github.com/ethereum-optimism/optimism/security/code-scanning?query=is:open+pr:9405). -If there are new issues, you should triage them. -Run `pnpm slither:triage` to step through findings. -You should _carefully_ walk through these findings, specifying which to triage/ignore (default is to keep all, outputting them into `slither-report.json`). -Findings can be triaged into `slither.db.json` or kept in the `slither-report.json`. -You should triage issues with extreme _care_ and security sign-off. +For each finding, either fix it locally and push a new commit, or dismiss it through the PR comment's UI. -After issues are triaged, or an updated slither report is generated, make sure to check in your changes to git. -Once checked in, the changes can be verified by running `pnpm slither:check`. -This will fail if there are issues missing from the `slither-report.json` that are _not_ triaged into `slither.db.json`. +Note that you can run slither locally by running `slither .`, but because it does not contain the triaged results from GitHub, it will be noisy. +Instead, you should run `slither ./path/to/contract.sol` to run it against a specific file. diff --git a/packages/contracts-bedrock/STYLE_GUIDE.md b/packages/contracts-bedrock/STYLE_GUIDE.md index 32c5e09872f7..181521368c58 100644 --- a/packages/contracts-bedrock/STYLE_GUIDE.md +++ b/packages/contracts-bedrock/STYLE_GUIDE.md @@ -115,9 +115,14 @@ All test contracts and functions should be organized and named according to the These guidelines are also encoded in a script which can be run with: ``` -tsx scripts/forge-test-names.ts +tsx scripts/checks/check-test-names.ts ``` +#### Expect Revert with Low Level Calls + +There is a non-intuitive behavior in foundry tests, which is documented [here](https://book.getfoundry.sh/cheatcodes/expect-revert?highlight=expectrevert#expectrevert). +When testing for a revert on a low-level call, please use the `revertsAsExpected` pattern suggested there. + _Note: This is a work in progress, not all test files are compliant with these guidelines._ #### Organizing Principles diff --git a/packages/contracts-bedrock/deploy-config/devnetL1-template.json b/packages/contracts-bedrock/deploy-config/devnetL1-template.json index 69b7fbb5591f..b04cb3ba5289 100644 --- a/packages/contracts-bedrock/deploy-config/devnetL1-template.json +++ b/packages/contracts-bedrock/deploy-config/devnetL1-template.json @@ -24,9 +24,9 @@ "baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", "l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", "sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", - "baseFeeVaultWithdrawalNetwork": "remote", - "l1FeeVaultWithdrawalNetwork": "remote", - "sequencerFeeVaultWithdrawalNetwork": "remote", + "baseFeeVaultWithdrawalNetwork": 0, + "l1FeeVaultWithdrawalNetwork": 0, + "sequencerFeeVaultWithdrawalNetwork": 0, "proxyAdminOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", "finalSystemOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", "superchainConfigGuardian": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", @@ -42,7 +42,7 @@ "eip1559Denominator": 50, "eip1559DenominatorCanyon": 250, "eip1559Elasticity": 6, - "l1GenesisBlockTimestamp": "0x64c811bf", + "l1GenesisBlockTimestamp": "0x654140d3", "l2GenesisRegolithTimeOffset": "0x0", "l2GenesisDeltaTimeOffset": null, "l2GenesisCanyonTimeOffset": "0x0", @@ -50,11 +50,21 @@ "requiredProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", "faultGameAbsolutePrestate": "0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98", - "faultGameMaxDepth": 44, - "faultGameMaxDuration": 1200, + "faultGameMaxDepth": 50, + "faultGameMaxDuration": 2400, "faultGameGenesisBlock": 0, - "faultGameGenesisOutputRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "faultGameGenesisOutputRoot": "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF", "faultGameSplitDepth": 14, - "preimageOracleMinProposalSize": 1800000, - "preimageOracleChallengePeriod": 86400 + "faultGameWithdrawalDelay": 604800, + "preimageOracleMinProposalSize": 10000, + "preimageOracleChallengePeriod": 120, + "proofMaturityDelaySeconds": 12, + "disputeGameFinalityDelaySeconds": 6, + "respectedGameType": 0, + "useFaultProofs": false, + "usePlasma": false, + "daChallengeWindow": 160, + "daResolveWindow": 160, + "daBondSize": 1000000, + "daResolverRefundPercentage": 0 } diff --git a/packages/contracts-bedrock/deploy-config/eigenda-poc-preprod.json b/packages/contracts-bedrock/deploy-config/eigenda-poc-preprod.json new file mode 100644 index 000000000000..64e828d9b39f --- /dev/null +++ b/packages/contracts-bedrock/deploy-config/eigenda-poc-preprod.json @@ -0,0 +1,61 @@ +{ + "finalSystemOwner": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", + "superchainConfigGuardian": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", + + "l1StartingBlockTag": "0xd3a60981c854f00a1aece8f94f0c69a3f6e74c490adbefa2ff227e0edb179401", + + "l1ChainID": 11155111, + "l2ChainID": 42069, + "l2BlockTime": 2, + "l1BlockTime": 12, + + "maxSequencerDrift": 600, + "sequencerWindowSize": 3600, + "channelTimeout": 300, + + "p2pSequencerAddress": "0xC509B3dD03B0E3f680706A2352Bd0cdc4Aa0a4e8", + "batchInboxAddress": "0xff00000000000000000000000000000000042069", + "batchSenderAddress": "0x234e10CcDd714F2260dD61503d9FdE8fAf67960b", + + "l2OutputOracleSubmissionInterval": 120, + "l2OutputOracleStartingBlockNumber": 0, + "l2OutputOracleStartingTimestamp": 1701901152, + + "l2OutputOracleProposer": "0x0b30D3F823aEFD81C7cE5a446eeb23c372D64f41", + "l2OutputOracleChallenger": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", + + "finalizationPeriodSeconds": 12, + + "proxyAdminOwner": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", + "baseFeeVaultRecipient": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", + "l1FeeVaultRecipient": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", + "sequencerFeeVaultRecipient": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", + + "baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", + "l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", + "sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", + "baseFeeVaultWithdrawalNetwork": 0, + "l1FeeVaultWithdrawalNetwork": 0, + "sequencerFeeVaultWithdrawalNetwork": 0, + + "gasPriceOracleOverhead": 2100, + "gasPriceOracleScalar": 1000000, + + "enableGovernance": true, + "governanceTokenSymbol": "OP", + "governanceTokenName": "Optimism", + "governanceTokenOwner": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", + + "l2GenesisBlockGasLimit": "0x1c9c380", + "l2GenesisBlockBaseFeePerGas": "0x3b9aca00", + "l2GenesisRegolithTimeOffset": "0x0", + + "eip1559Denominator": 50, + "eip1559DenominatorCanyon": 250, + "eip1559Elasticity": 10, + + "systemConfigStartBlock": 0, + + "requiredProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", + "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000" +} diff --git a/packages/contracts-bedrock/deploy-config/goerli.json b/packages/contracts-bedrock/deploy-config/goerli.json index be204af92914..2084f742c403 100644 --- a/packages/contracts-bedrock/deploy-config/goerli.json +++ b/packages/contracts-bedrock/deploy-config/goerli.json @@ -41,5 +41,19 @@ "eip1559Elasticity": 10, "systemConfigStartBlock": 8300214, "requiredProtocolVersion": "0x0000000000000000000000000000000000000003000000010000000000000000", - "recommendedProtocolVersion": "0x0000000000000000000000000000000000000003000000010000000000000000" + "recommendedProtocolVersion": "0x0000000000000000000000000000000000000003000000010000000000000000", + "fundDevAccounts": false, + "faultGameAbsolutePrestate": "0x03e1255457128b9afd9acf93239c1d477bdff88624901f9ca8fe0783b756dbe0", + "faultGameMaxDepth": 73, + "faultGameMaxDuration": 604800, + "faultGameGenesisBlock": 4061224, + "faultGameGenesisOutputRoot": "0xd08055c58b2c5149565c636b44fad2c25b5ccddef1385a2cb721529d7480b242", + "faultGameSplitDepth": 32, + "faultGameWithdrawalDelay": 604800, + "preimageOracleMinProposalSize": 1800000, + "preimageOracleChallengePeriod": 86400, + "proofMaturityDelaySeconds": 604800, + "disputeGameFinalityDelaySeconds": 302400, + "respectedGameType": 0, + "useFaultProofs": true } diff --git a/packages/contracts-bedrock/deploy-config/hardhat.json b/packages/contracts-bedrock/deploy-config/hardhat.json index 4cd278509aa8..aa9cc17b9448 100644 --- a/packages/contracts-bedrock/deploy-config/hardhat.json +++ b/packages/contracts-bedrock/deploy-config/hardhat.json @@ -42,5 +42,24 @@ "l2GenesisRegolithTimeOffset": "0x0", "systemConfigStartBlock": 0, "requiredProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", - "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000" + "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", + "faultGameAbsolutePrestate": "0x0000000000000000000000000000000000000000000000000000000000000000", + "faultGameMaxDepth": 8, + "faultGameMaxDuration": 2400, + "faultGameGenesisBlock": 0, + "faultGameGenesisOutputRoot": "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF", + "faultGameSplitDepth": 4, + "faultGameWithdrawalDelay": 604800, + "preimageOracleMinProposalSize": 10000, + "preimageOracleChallengePeriod": 120, + "proofMaturityDelaySeconds": 12, + "disputeGameFinalityDelaySeconds": 6, + "respectedGameType": 0, + "useFaultProofs": false, + "fundDevAccounts": false, + "usePlasma": false, + "daChallengeWindow": 100, + "daResolveWindow": 100, + "daBondSize": 1000, + "daResolverRefundPercentage": 50 } diff --git a/packages/contracts-bedrock/deploy-config/sepolia-devnet-0.json b/packages/contracts-bedrock/deploy-config/sepolia-devnet-0.json new file mode 100644 index 000000000000..7110b3ed3bbf --- /dev/null +++ b/packages/contracts-bedrock/deploy-config/sepolia-devnet-0.json @@ -0,0 +1,87 @@ +{ + "l1StartingBlockTag": "0x5639be97000fec7131a880b19b664cae43f975c773f628a08a9bb658c2a68df0", + "l1ChainID": 11155111, + "l2ChainID": 11155421, + "l2BlockTime": 2, + "finalizationPeriodSeconds": 12, + "maxSequencerDrift": 600, + "sequencerWindowSize": 3600, + "channelTimeout": 300, + "p2pSequencerAddress": "0xa95b83e39aa78b00f12fe431865b563793d97af5", + "batchInboxAddress": "0xff00000000000000000000000000000011155421", + "batchSenderAddress": "0x19cc7073150d9f5888f09e0e9016d2a39667df14", + "l2OutputOracleSubmissionInterval": 120, + "l2OutputOracleStartingTimestamp": 1706484048, + "l2OutputOracleStartingBlockNumber": 0, + "l2OutputOracleProposer": "0x95014c45078354ff839f14192228108eac82e00a", + "l2OutputOracleChallenger": "0x8c20c40180751d93e939dddee3517ae0d1ebead2", + "cliqueSignerAddress": "0x0000000000000000000000000000000000000000", + "l1UseClique": false, + "l1BlockTime": 12, + "l1GenesisBlockTimestamp": "0x0", + "l1GenesisBlockNonce": "0x0", + "l1GenesisBlockGasLimit": "0x0", + "l1GenesisBlockDifficulty": null, + "l1GenesisBlockMixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "l1GenesisBlockCoinbase": "0x0000000000000000000000000000000000000000", + "l1GenesisBlockNumber": "0x0", + "l1GenesisBlockGasUsed": "0x0", + "l1GenesisBlockParentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "l1GenesisBlockBaseFeePerGas": null, + "l2GenesisBlockNonce": "0x0", + "l2GenesisBlockGasLimit": "0x1c9c380", + "l2GenesisBlockDifficulty": null, + "l2GenesisBlockMixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "l2GenesisBlockNumber": "0x0", + "l2GenesisBlockGasUsed": "0x0", + "l2GenesisBlockParentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "l2GenesisBlockBaseFeePerGas": "0x3b9aca00", + "l2GenesisRegolithTimeOffset": "0x0", + "l2GenesisCanyonTimeOffset": "0x0", + "l2GenesisDeltaTimeOffset": "0x0", + "l2GenesisBlockExtraData": null, + "proxyAdminOwner": "0x8c20c40180751d93e939dddee3517ae0d1ebead2", + "finalSystemOwner": "0x8c20c40180751d93e939dddee3517ae0d1ebead2", + "superchainConfigGuardian": "0x8c20c40180751d93e939dddee3517ae0d1ebead2", + "baseFeeVaultRecipient": "0x8c20c40180751d93e939dddee3517ae0d1ebead2", + "l1FeeVaultRecipient": "0x8c20c40180751d93e939dddee3517ae0d1ebead2", + "sequencerFeeVaultRecipient": "0x8c20c40180751d93e939dddee3517ae0d1ebead2", + "baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", + "l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", + "sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", + "baseFeeVaultWithdrawalNetwork": 1, + "l1FeeVaultWithdrawalNetwork": 1, + "sequencerFeeVaultWithdrawalNetwork": 1, + "l1StandardBridgeProxy": "0x0000000000000000000000000000000000000000", + "l1CrossDomainMessengerProxy": "0x0000000000000000000000000000000000000000", + "l1ERC721BridgeProxy": "0x0000000000000000000000000000000000000000", + "systemConfigProxy": "0x0000000000000000000000000000000000000000", + "optimismPortalProxy": "0x0000000000000000000000000000000000000000", + "gasPriceOracleOverhead": 188, + "gasPriceOracleScalar": 684000, + "enableGovernance": true, + "governanceTokenSymbol": "OP", + "governanceTokenName": "Optimism", + "governanceTokenOwner": "0x8c20c40180751d93e939dddee3517ae0d1ebead2", + "deploymentWaitConfirmations": 0, + "eip1559Elasticity": 6, + "eip1559Denominator": 250, + "eip1559DenominatorCanyon": 250, + "systemConfigStartBlock": 4071248, + "faultGameAbsolutePrestate": "0x031e3b504740d0b1264e8cf72b6dde0d497184cfb3f98e451c6be8b33bd3f808", + "faultGameMaxDepth": 73, + "faultGameMaxDuration": 604800, + "faultGameGenesisBlock": 0, + "faultGameGenesisOutputRoot": "0x91bd00ecd596a86c9f4e12c0646578e77022881c87c06ec6aa31e656d2730688", + "faultGameSplitDepth": 30, + "faultGameWithdrawalDelay": 604800, + "preimageOracleMinProposalSize": 126000, + "preimageOracleChallengePeriod": 86400, + "proofMaturityDelaySeconds": 604800, + "disputeGameFinalityDelaySeconds": 302400, + "respectedGameType": 0, + "useFaultProofs": true, + "fundDevAccounts": false, + "requiredProtocolVersion": "0x0000000000000000000000000000000000000005000000000000000000000000", + "recommendedProtocolVersion": "0x0000000000000000000000000000000000000005000000000000000000000000" +} diff --git a/packages/contracts-bedrock/deploy-config/sepolia.json b/packages/contracts-bedrock/deploy-config/sepolia.json index c46a9725035f..50ca9de37ce2 100644 --- a/packages/contracts-bedrock/deploy-config/sepolia.json +++ b/packages/contracts-bedrock/deploy-config/sepolia.json @@ -42,12 +42,18 @@ "systemConfigStartBlock": 4071248, "requiredProtocolVersion": "0x0000000000000000000000000000000000000004000000000000000000000001", "recommendedProtocolVersion": "0x0000000000000000000000000000000000000004000000000000000000000001", - "faultGameAbsolutePrestate": "0x037bbcc23684afbb7f608024369242c5cdea261a4f63981387efb7cd81763536", + "fundDevAccounts": false, + "faultGameAbsolutePrestate": "0x031e3b504740d0b1264e8cf72b6dde0d497184cfb3f98e451c6be8b33bd3f808", "faultGameMaxDepth": 73, - "faultGameMaxDuration": 86400, - "faultGameGenesisBlock": 0, - "faultGameGenesisOutputRoot": "0x6a2fb9128c8bc82eed49ee590fba3e975bd67fede20535d0d20b3000ea6d99b1", - "faultGameSplitDepth": 32, - "preimageOracleMinProposalSize": 1800000, - "preimageOracleChallengePeriod": 86400 + "faultGameMaxDuration": 604800, + "faultGameGenesisBlock": 9496192, + "faultGameGenesisOutputRoot": "0x63b1cda487c072b020a57c1203f7c2921754005cadbd54bed7f558111b8278d8", + "faultGameSplitDepth": 30, + "faultGameWithdrawalDelay": 604800, + "preimageOracleMinProposalSize": 126000, + "preimageOracleChallengePeriod": 86400, + "proofMaturityDelaySeconds": 604800, + "disputeGameFinalityDelaySeconds": 302400, + "respectedGameType": 0, + "useFaultProofs": true } diff --git a/packages/contracts-bedrock/deployments/.gitinclude b/packages/contracts-bedrock/deployments/.gitinclude new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/contracts-bedrock/deployments/4202/.chainId b/packages/contracts-bedrock/deployments/4202/.chainId new file mode 100644 index 000000000000..edfd6052cc76 --- /dev/null +++ b/packages/contracts-bedrock/deployments/4202/.chainId @@ -0,0 +1 @@ +4202 \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/.chainId b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/.chainId similarity index 100% rename from packages/contracts-bedrock/deployments/goerli/.chainId rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/.chainId diff --git a/packages/contracts-bedrock/deployments/sepolia/AddressManager.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/AddressManager.json similarity index 82% rename from packages/contracts-bedrock/deployments/sepolia/AddressManager.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/AddressManager.json index 0204a3620d88..6279703e7b90 100644 --- a/packages/contracts-bedrock/deployments/sepolia/AddressManager.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/AddressManager.json @@ -115,7 +115,7 @@ "type": "function" } ], - "address": "0x9bFE9c5609311DF1c011c47642253B78a4f33F4B", + "address": "0x6cabEB4a6C417fA09916681CF11d4173dAC990a6", "args": [], "bytecode": "0x608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6105ef8061007e6000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80639b2ea4bd116100505780639b2ea4bd146100b9578063bf40fac1146100cc578063f2fde38b146100df57600080fd5b8063715018a61461006c5780638da5cb5b14610076575b600080fd5b6100746100f2565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100746100c73660046104fa565b610106565b6100906100da366004610548565b6101d9565b6100746100ed366004610585565b610215565b6100fa6102d1565b6101046000610352565b565b61010e6102d1565b6000610119836103c7565b60008181526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff8681167fffffffffffffffffffffffff00000000000000000000000000000000000000008316179092559151929350169061017c9085906105a7565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b6000600160006101e8846103c7565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1692915050565b61021d6102d1565b73ffffffffffffffffffffffffffffffffffffffff81166102c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102ce81610352565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610104576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102bc565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816040516020016103da91906105a7565b604051602081830303815290604052805190602001209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261043757600080fd5b813567ffffffffffffffff80821115610452576104526103f7565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610498576104986103f7565b816040528381528660208588010111156104b157600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b919050565b6000806040838503121561050d57600080fd5b823567ffffffffffffffff81111561052457600080fd5b61053085828601610426565b92505061053f602084016104d1565b90509250929050565b60006020828403121561055a57600080fd5b813567ffffffffffffffff81111561057157600080fd5b61057d84828501610426565b949350505050565b60006020828403121561059757600080fd5b6105a0826104d1565b9392505050565b6000825160005b818110156105c857602081860181015185830152016105ae565b818111156105d7576000828501525b50919091019291505056fea164736f6c634300080f000a", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c80639b2ea4bd116100505780639b2ea4bd146100b9578063bf40fac1146100cc578063f2fde38b146100df57600080fd5b8063715018a61461006c5780638da5cb5b14610076575b600080fd5b6100746100f2565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100746100c73660046104fa565b610106565b6100906100da366004610548565b6101d9565b6100746100ed366004610585565b610215565b6100fa6102d1565b6101046000610352565b565b61010e6102d1565b6000610119836103c7565b60008181526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff8681167fffffffffffffffffffffffff00000000000000000000000000000000000000008316179092559151929350169061017c9085906105a7565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b6000600160006101e8846103c7565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1692915050565b61021d6102d1565b73ffffffffffffffffffffffffffffffffffffffff81166102c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102ce81610352565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610104576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102bc565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816040516020016103da91906105a7565b604051602081830303815290604052805190602001209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261043757600080fd5b813567ffffffffffffffff80821115610452576104526103f7565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610498576104986103f7565b816040528381528660208588010111156104b157600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b919050565b6000806040838503121561050d57600080fd5b823567ffffffffffffffff81111561052457600080fd5b61053085828601610426565b92505061053f602084016104d1565b90509250929050565b60006020828403121561055a57600080fd5b813567ffffffffffffffff81111561057157600080fd5b61057d84828501610426565b949350505050565b60006020828403121561059757600080fd5b6105a0826104d1565b9392505050565b6000825160005b818110156105c857602081860181015185830152016105ae565b818111156105d7576000828501525b50919091019291505056fea164736f6c634300080f000a", @@ -157,45 +157,45 @@ } } }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newAddress\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"oldAddress\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AddressSet\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setAddress\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getAddress(string)\":{\"params\":{\"_name\":\"Name to retrieve an address for.\"},\"returns\":{\"_0\":\"Address associated with the given name.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAddress(string,address)\":{\"params\":{\"_address\":\"Address to associate with the name.\",\"_name\":\"String name to associate an address with.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getAddress(string)\":{\"notice\":\"Retrieves the address associated with a given name.\"},\"setAddress(string,address)\":{\"notice\":\"Changes the address associated with a particular name.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/legacy/AddressManager.sol\":\"AddressManager\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"src/legacy/AddressManager.sol\":{\"keccak256\":\"0x1fcb990df6473f7fa360d5924d62d39ce2ca97d45668e3901e5405cfbe598b19\",\"urls\":[\"bzz-raw://9d08358b60dea54dbc32e988a1bb7ea909488063eaae3c5ae28a322f125c9b34\",\"dweb:/ipfs/QmZPQwdjLh9gaamNAoTUmWwwbRKj3yHovBYfnTPnfuKvUt\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 4, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newAddress\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"oldAddress\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AddressSet\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setAddress\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getAddress(string)\":{\"params\":{\"_name\":\"Name to retrieve an address for.\"},\"returns\":{\"_0\":\"Address associated with the given name.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAddress(string,address)\":{\"params\":{\"_address\":\"Address to associate with the name.\",\"_name\":\"String name to associate an address with.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getAddress(string)\":{\"notice\":\"Retrieves the address associated with a given name.\"},\"setAddress(string,address)\":{\"notice\":\"Changes the address associated with a particular name.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/legacy/AddressManager.sol\":\"AddressManager\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"src/legacy/AddressManager.sol\":{\"keccak256\":\"0x1fcb990df6473f7fa360d5924d62d39ce2ca97d45668e3901e5405cfbe598b19\",\"urls\":[\"bzz-raw://9d08358b60dea54dbc32e988a1bb7ea909488063eaae3c5ae28a322f125c9b34\",\"dweb:/ipfs/QmZPQwdjLh9gaamNAoTUmWwwbRKj3yHovBYfnTPnfuKvUt\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 1, "receipt": { - "transactionHash": "0xe6d395de5325c383fda316d820c8086e2fba23f26d3ae72a20778a7ca0edccdb", + "transactionHash": "0xe9bcbc0399d83c6ed65bdd7983f5abab62d877117884f486e89669333b57715f", "transactionIndex": "0x2", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "from": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", "to": null, - "cumulativeGasUsed": "0x223cf5", + "cumulativeGasUsed": "0xafc0b", "gasUsed": "0x62d28", - "contractAddress": "0x9bFE9c5609311DF1c011c47642253B78a4f33F4B", + "contractAddress": "0x6cabEB4a6C417fA09916681CF11d4173dAC990a6", "logs": [ { - "address": "0x9bFE9c5609311DF1c011c47642253B78a4f33F4B", + "address": "0x6cabEB4a6C417fA09916681CF11d4173dAC990a6", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000018394b52d3cb931dfa76f63251919d051953413d" + "0x00000000000000000000000055351d70ac0602ed7a41d77735dc6ae1b7cbac68" ], "data": "0x", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "transactionHash": "0xe6d395de5325c383fda316d820c8086e2fba23f26d3ae72a20778a7ca0edccdb", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0xe9bcbc0399d83c6ed65bdd7983f5abab62d877117884f486e89669333b57715f", "transactionIndex": "0x2", - "logIndex": "0x2", + "logIndex": "0x5", "removed": false } ], "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000200000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000001000000000004000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000040000000000000000008000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "logsBloom": "0x00000000000000020000000000000000000000000000000000840000000000000000000000000000000000000000000000000000800000000800000000000000000000000000000000000000000000000001001000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", "type": "0x2", - "effectiveGasPrice": "0xbec78df7" + "effectiveGasPrice": "0xb2d05e0a" }, "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [ { - "astId": 31896, + "astId": 47128, "contract": "src/legacy/AddressManager.sol:AddressManager", "label": "_owner", "offset": 0, @@ -203,7 +203,7 @@ "type": "t_address" }, { - "astId": 62378, + "astId": 87125, "contract": "src/legacy/AddressManager.sol:AddressManager", "label": "addresses", "offset": 0, @@ -231,7 +231,7 @@ } } }, - "transactionHash": "0xe6d395de5325c383fda316d820c8086e2fba23f26d3ae72a20778a7ca0edccdb", + "transactionHash": "0xe9bcbc0399d83c6ed65bdd7983f5abab62d877117884f486e89669333b57715f", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/eigenda-poc-preprod/DisputeGameFactoryProxy.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/DisputeGameFactoryProxy.json new file mode 100644 index 000000000000..8cf35efc9cd6 --- /dev/null +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/DisputeGameFactoryProxy.json @@ -0,0 +1,256 @@ +{ + "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" + } + ], + "address": "0x52BD87296C5f3cE3012C42E01ABAf5E388340907", + "args": [ + "0x1814DBa2CC02DC44408ec2E05a680bC3dD24Cf4B" + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "admin()": { + "returns": { + "_0": "Owner address." + } + }, + "changeAdmin(address)": { + "params": { + "_admin": "New owner of the proxy contract." + } + }, + "constructor": { + "params": { + "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." + } + }, + "implementation()": { + "returns": { + "_0": "Implementation address." + } + }, + "upgradeTo(address)": { + "params": { + "_implementation": "Address of the implementation contract." + } + }, + "upgradeToAndCall(address,bytes)": { + "params": { + "_data": "Calldata to delegatecall the new implementation with.", + "_implementation": "Address of the implementation contract." + } + } + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new owner of the contract", + "previousAdmin": "The previous owner of the contract" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The address of the implementation contract" + } + } + }, + "title": "Proxy" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 1, + "receipt": { + "transactionHash": "0x44e60718901be5d49e53e5d035276cc57204dae82ae7a04d2e299eeaf8742d8d", + "transactionIndex": "0x13", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "from": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", + "to": null, + "cumulativeGasUsed": "0x889a23", + "gasUsed": "0x80250", + "contractAddress": "0x52BD87296C5f3cE3012C42E01ABAf5E388340907", + "logs": [ + { + "address": "0x52BD87296C5f3cE3012C42E01ABAf5E388340907", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001814dba2cc02dc44408ec2e05a680bc3dd24cf4b", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0x44e60718901be5d49e53e5d035276cc57204dae82ae7a04d2e299eeaf8742d8d", + "transactionIndex": "0x13", + "logIndex": "0x22", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000400200000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xb2d05e0a" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0x44e60718901be5d49e53e5d035276cc57204dae82ae7a04d2e299eeaf8742d8d", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "admin()": { + "notice": "Gets the owner of the proxy contract." + }, + "changeAdmin(address)": { + "notice": "Changes the owner of the proxy contract. Only callable by the owner." + }, + "constructor": { + "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." + }, + "upgradeTo(address)": { + "notice": "Set the implementation contract address. The code at the given address will execute when this contract is called." + }, + "upgradeToAndCall(address,bytes)": { + "notice": "Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades." + } + }, + "events": { + "AdminChanged(address,address)": { + "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." + }, + "Upgraded(address)": { + "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." + } + }, + "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." + } +} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/sepolia/L1CrossDomainMessenger.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1CrossDomainMessenger.json similarity index 83% rename from packages/contracts-bedrock/deployments/sepolia/L1CrossDomainMessenger.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1CrossDomainMessenger.json index fc0457fe3334..2d636f870467 100644 --- a/packages/contracts-bedrock/deployments/sepolia/L1CrossDomainMessenger.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1CrossDomainMessenger.json @@ -451,12 +451,12 @@ "type": "function" } ], - "address": "0xC3c7E6f4ad6a593a9731a39FA883eC1999d7D873", + "address": "0x86E1151998eE8FE475EB1e3E0bf5F0C6734a2AD8", "args": [ - "0x16Fc5058F25648194471939df75CF27A2fdC48BC" + "0x1f1cd3b548FC4Df6b6dBeA9F983D3B7357Aa6d7a" ], - "bytecode": "0x60c06040523480156200001157600080fd5b506040516200223d3803806200223d833981016040819052620000349162000269565b7342000000000000000000000000000000000000076080526001600160a01b03811660a0526200006560006200006c565b506200029b565b600054600160a81b900460ff16158080156200009557506000546001600160a01b90910460ff16105b80620000cc5750620000b230620001d560201b620014771760201c565b158015620000cc5750600054600160a01b900460ff166001145b620001355760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b179055801562000163576000805460ff60a81b1916600160a81b1790555b60fb80546001600160a01b0319166001600160a01b03841617905562000188620001e4565b8015620001d1576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054600160a81b900460ff16620002535760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200012c565b60cc80546001600160a01b03191661dead179055565b6000602082840312156200027c57600080fd5b81516001600160a01b03811681146200029457600080fd5b9392505050565b60805160a051611f4b620002f2600039600081816101d401528181610350015281816114d00152818161167d015281816116de01526117aa0152600081816103b2015281816104f101526116a70152611f4b6000f3fe6080604052600436106101755760003560e01c80636425666b116100cb578063a4e7f8bd1161007f578063c4d66de811610059578063c4d66de814610454578063d764ad0b14610474578063ecc704281461048757600080fd5b8063a4e7f8bd146103d4578063b1b1b20914610404578063b28ade251461043457600080fd5b806383a74074116100b057806383a74074146103895780638cbeeef21461029a5780639fce812c146103a057600080fd5b80636425666b146103415780636e296e451461037457600080fd5b80633dbb202b1161012d57806354fd4d501161010757806354fd4d50146102b05780635644cfdf146103065780635c975abb1461031c57600080fd5b80633dbb202b1461025d5780633f827a5a146102725780634c1d6a691461029a57600080fd5b80630ff754ea1161015e5780630ff754ea146101c25780632828d7e81461021b57806335e80ab31461023057600080fd5b8063028f85f71461017a5780630c568498146101ad575b600080fd5b34801561018657600080fd5b5061018f601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b5061018f603f81565b3480156101ce57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a4565b34801561022757600080fd5b5061018f604081565b34801561023c57600080fd5b5060fb546101f69073ffffffffffffffffffffffffffffffffffffffff1681565b61027061026b3660046119f5565b6104ec565b005b34801561027e57600080fd5b50610287600181565b60405161ffff90911681526020016101a4565b3480156102a657600080fd5b5061018f619c4081565b3480156102bc57600080fd5b506102f96040518060400160405280600581526020017f322e312e3100000000000000000000000000000000000000000000000000000081525081565b6040516101a49190611ac7565b34801561031257600080fd5b5061018f61138881565b34801561032857600080fd5b50610331610750565b60405190151581526020016101a4565b34801561034d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101f6565b34801561038057600080fd5b506101f66107e9565b34801561039557600080fd5b5061018f62030d4081565b3480156103ac57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b3480156103e057600080fd5b506103316103ef366004611ae1565b60ce6020526000908152604090205460ff1681565b34801561041057600080fd5b5061033161041f366004611ae1565b60cb6020526000908152604090205460ff1681565b34801561044057600080fd5b5061018f61044f366004611afa565b6108d5565b34801561046057600080fd5b5061027061046f366004611b4e565b610943565b610270610482366004611b6b565b610b81565b34801561049357600080fd5b506104de60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a4565b6106257f000000000000000000000000000000000000000000000000000000000000000061051b8585856108d5565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061058760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105a39796959493929190611c3a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611493565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856106aa60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516106bc959493929190611c99565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156107c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e49190611ce7565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016108b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6108f1604063ffffffff8816611d38565b6108fb9190611d68565b610906601088611d38565b6109139062030d40611db6565b61091d9190611db6565b6109279190611db6565b6109319190611db6565b61093b9190611db6565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff161580801561098e575060005460017401000000000000000000000000000000000000000090910460ff16105b806109c05750303b1580156109c0575060005474010000000000000000000000000000000000000000900460ff166001145b610a4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016108af565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610ad257600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055610b1a611548565b8015610b7d57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610b89610750565b15610bf0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016108af565b60f087901c60028110610cab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016108af565b8061ffff16600003610da0576000610cfc878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f9250611621915050565b600081815260cb602052604090205490915060ff1615610d9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016108af565b505b6000610de6898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164092505050565b9050610df0611663565b15610e2857853414610e0457610e04611de2565b600081815260ce602052604090205460ff1615610e2357610e23611de2565b610f7a565b3415610edc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016108af565b600081815260ce602052604090205460ff16610f7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016108af565b610f8387611787565b15611036576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016108af565b600081815260cb602052604090205460ff16156110d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016108af565b6110f6856110e7611388619c40611db6565b67ffffffffffffffff166117fe565b158061111c575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561123557600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161122e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b505061146e565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006112c688619c405a6112899190611e11565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061181c92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561135d57600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a261146a565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c42908490611510908890839089906000908990600401611e28565b6000604051808303818588803b15801561152957600080fd5b505af115801561153d573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff166115f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016108af565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b600061162f85858585611836565b805190602001209050949350505050565b60006116508787878787876118cf565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156107e457507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa158015611747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176b9190611e80565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff82163014806117f857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b60608484848460405160240161184f9493929190611e9d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b60608686868686866040516024016118ec96959493929190611ee7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461199057600080fd5b50565b60008083601f8401126119a557600080fd5b50813567ffffffffffffffff8111156119bd57600080fd5b6020830191508360208285010111156119d557600080fd5b9250929050565b803563ffffffff811681146119f057600080fd5b919050565b60008060008060608587031215611a0b57600080fd5b8435611a168161196e565b9350602085013567ffffffffffffffff811115611a3257600080fd5b611a3e87828801611993565b9094509250611a519050604086016119dc565b905092959194509250565b6000815180845260005b81811015611a8257602081850181015186830182015201611a66565b81811115611a94576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611ada6020830184611a5c565b9392505050565b600060208284031215611af357600080fd5b5035919050565b600080600060408486031215611b0f57600080fd5b833567ffffffffffffffff811115611b2657600080fd5b611b3286828701611993565b9094509250611b459050602085016119dc565b90509250925092565b600060208284031215611b6057600080fd5b8135611ada8161196e565b600080600080600080600060c0888a031215611b8657600080fd5b873596506020880135611b988161196e565b95506040880135611ba88161196e565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611bd257600080fd5b611bde8a828b01611993565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611c8c60c083018486611bf1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611cc9608083018688611bf1565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611cf957600080fd5b81518015158114611ada57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611d5f57611d5f611d09565b02949350505050565b600067ffffffffffffffff80841680611daa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611dd957611dd9611d09565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611e2357611e23611d09565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611e7560a0830184611a5c565b979650505050505050565b600060208284031215611e9257600080fd5b8151611ada8161196e565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611ed66080830185611a5c565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611f3260c0830184611a5c565b9897505050505050505056fea164736f6c634300080f000a", - "deployedBytecode": "0x6080604052600436106101755760003560e01c80636425666b116100cb578063a4e7f8bd1161007f578063c4d66de811610059578063c4d66de814610454578063d764ad0b14610474578063ecc704281461048757600080fd5b8063a4e7f8bd146103d4578063b1b1b20914610404578063b28ade251461043457600080fd5b806383a74074116100b057806383a74074146103895780638cbeeef21461029a5780639fce812c146103a057600080fd5b80636425666b146103415780636e296e451461037457600080fd5b80633dbb202b1161012d57806354fd4d501161010757806354fd4d50146102b05780635644cfdf146103065780635c975abb1461031c57600080fd5b80633dbb202b1461025d5780633f827a5a146102725780634c1d6a691461029a57600080fd5b80630ff754ea1161015e5780630ff754ea146101c25780632828d7e81461021b57806335e80ab31461023057600080fd5b8063028f85f71461017a5780630c568498146101ad575b600080fd5b34801561018657600080fd5b5061018f601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b5061018f603f81565b3480156101ce57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a4565b34801561022757600080fd5b5061018f604081565b34801561023c57600080fd5b5060fb546101f69073ffffffffffffffffffffffffffffffffffffffff1681565b61027061026b3660046119f5565b6104ec565b005b34801561027e57600080fd5b50610287600181565b60405161ffff90911681526020016101a4565b3480156102a657600080fd5b5061018f619c4081565b3480156102bc57600080fd5b506102f96040518060400160405280600581526020017f322e312e3100000000000000000000000000000000000000000000000000000081525081565b6040516101a49190611ac7565b34801561031257600080fd5b5061018f61138881565b34801561032857600080fd5b50610331610750565b60405190151581526020016101a4565b34801561034d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101f6565b34801561038057600080fd5b506101f66107e9565b34801561039557600080fd5b5061018f62030d4081565b3480156103ac57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b3480156103e057600080fd5b506103316103ef366004611ae1565b60ce6020526000908152604090205460ff1681565b34801561041057600080fd5b5061033161041f366004611ae1565b60cb6020526000908152604090205460ff1681565b34801561044057600080fd5b5061018f61044f366004611afa565b6108d5565b34801561046057600080fd5b5061027061046f366004611b4e565b610943565b610270610482366004611b6b565b610b81565b34801561049357600080fd5b506104de60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a4565b6106257f000000000000000000000000000000000000000000000000000000000000000061051b8585856108d5565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061058760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105a39796959493929190611c3a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611493565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856106aa60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516106bc959493929190611c99565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156107c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e49190611ce7565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016108b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6108f1604063ffffffff8816611d38565b6108fb9190611d68565b610906601088611d38565b6109139062030d40611db6565b61091d9190611db6565b6109279190611db6565b6109319190611db6565b61093b9190611db6565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff161580801561098e575060005460017401000000000000000000000000000000000000000090910460ff16105b806109c05750303b1580156109c0575060005474010000000000000000000000000000000000000000900460ff166001145b610a4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016108af565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610ad257600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055610b1a611548565b8015610b7d57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610b89610750565b15610bf0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016108af565b60f087901c60028110610cab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016108af565b8061ffff16600003610da0576000610cfc878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f9250611621915050565b600081815260cb602052604090205490915060ff1615610d9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016108af565b505b6000610de6898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164092505050565b9050610df0611663565b15610e2857853414610e0457610e04611de2565b600081815260ce602052604090205460ff1615610e2357610e23611de2565b610f7a565b3415610edc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016108af565b600081815260ce602052604090205460ff16610f7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016108af565b610f8387611787565b15611036576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016108af565b600081815260cb602052604090205460ff16156110d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016108af565b6110f6856110e7611388619c40611db6565b67ffffffffffffffff166117fe565b158061111c575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561123557600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161122e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b505061146e565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006112c688619c405a6112899190611e11565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061181c92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561135d57600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a261146a565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c42908490611510908890839089906000908990600401611e28565b6000604051808303818588803b15801561152957600080fd5b505af115801561153d573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff166115f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016108af565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b600061162f85858585611836565b805190602001209050949350505050565b60006116508787878787876118cf565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156107e457507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa158015611747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176b9190611e80565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff82163014806117f857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b60608484848460405160240161184f9493929190611e9d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b60608686868686866040516024016118ec96959493929190611ee7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461199057600080fd5b50565b60008083601f8401126119a557600080fd5b50813567ffffffffffffffff8111156119bd57600080fd5b6020830191508360208285010111156119d557600080fd5b9250929050565b803563ffffffff811681146119f057600080fd5b919050565b60008060008060608587031215611a0b57600080fd5b8435611a168161196e565b9350602085013567ffffffffffffffff811115611a3257600080fd5b611a3e87828801611993565b9094509250611a519050604086016119dc565b905092959194509250565b6000815180845260005b81811015611a8257602081850181015186830182015201611a66565b81811115611a94576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611ada6020830184611a5c565b9392505050565b600060208284031215611af357600080fd5b5035919050565b600080600060408486031215611b0f57600080fd5b833567ffffffffffffffff811115611b2657600080fd5b611b3286828701611993565b9094509250611b459050602085016119dc565b90509250925092565b600060208284031215611b6057600080fd5b8135611ada8161196e565b600080600080600080600060c0888a031215611b8657600080fd5b873596506020880135611b988161196e565b95506040880135611ba88161196e565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611bd257600080fd5b611bde8a828b01611993565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611c8c60c083018486611bf1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611cc9608083018688611bf1565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611cf957600080fd5b81518015158114611ada57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611d5f57611d5f611d09565b02949350505050565b600067ffffffffffffffff80841680611daa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611dd957611dd9611d09565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611e2357611e23611d09565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611e7560a0830184611a5c565b979650505050505050565b600060208284031215611e9257600080fd5b8151611ada8161196e565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611ed66080830185611a5c565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611f3260c0830184611a5c565b9897505050505050505056fea164736f6c634300080f000a", + "bytecode": "0x60c06040523480156200001157600080fd5b506040516200223d3803806200223d833981016040819052620000349162000269565b7342000000000000000000000000000000000000076080526001600160a01b03811660a0526200006560006200006c565b506200029b565b600054600160a81b900460ff16158080156200009557506000546001600160a01b90910460ff16105b80620000cc5750620000b230620001d560201b620014771760201c565b158015620000cc5750600054600160a01b900460ff166001145b620001355760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b179055801562000163576000805460ff60a81b1916600160a81b1790555b60fb80546001600160a01b0319166001600160a01b03841617905562000188620001e4565b8015620001d1576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054600160a81b900460ff16620002535760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200012c565b60cc80546001600160a01b03191661dead179055565b6000602082840312156200027c57600080fd5b81516001600160a01b03811681146200029457600080fd5b9392505050565b60805160a051611f4b620002f2600039600081816101d401528181610350015281816114d00152818161167d015281816116de01526117aa0152600081816103b2015281816104f101526116a70152611f4b6000f3fe6080604052600436106101755760003560e01c80636425666b116100cb578063a4e7f8bd1161007f578063c4d66de811610059578063c4d66de814610454578063d764ad0b14610474578063ecc704281461048757600080fd5b8063a4e7f8bd146103d4578063b1b1b20914610404578063b28ade251461043457600080fd5b806383a74074116100b057806383a74074146103895780638cbeeef21461029a5780639fce812c146103a057600080fd5b80636425666b146103415780636e296e451461037457600080fd5b80633dbb202b1161012d57806354fd4d501161010757806354fd4d50146102b05780635644cfdf146103065780635c975abb1461031c57600080fd5b80633dbb202b1461025d5780633f827a5a146102725780634c1d6a691461029a57600080fd5b80630ff754ea1161015e5780630ff754ea146101c25780632828d7e81461021b57806335e80ab31461023057600080fd5b8063028f85f71461017a5780630c568498146101ad575b600080fd5b34801561018657600080fd5b5061018f601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b5061018f603f81565b3480156101ce57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a4565b34801561022757600080fd5b5061018f604081565b34801561023c57600080fd5b5060fb546101f69073ffffffffffffffffffffffffffffffffffffffff1681565b61027061026b3660046119f5565b6104ec565b005b34801561027e57600080fd5b50610287600181565b60405161ffff90911681526020016101a4565b3480156102a657600080fd5b5061018f619c4081565b3480156102bc57600080fd5b506102f96040518060400160405280600581526020017f322e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516101a49190611ac7565b34801561031257600080fd5b5061018f61138881565b34801561032857600080fd5b50610331610750565b60405190151581526020016101a4565b34801561034d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101f6565b34801561038057600080fd5b506101f66107e9565b34801561039557600080fd5b5061018f62030d4081565b3480156103ac57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b3480156103e057600080fd5b506103316103ef366004611ae1565b60ce6020526000908152604090205460ff1681565b34801561041057600080fd5b5061033161041f366004611ae1565b60cb6020526000908152604090205460ff1681565b34801561044057600080fd5b5061018f61044f366004611afa565b6108d5565b34801561046057600080fd5b5061027061046f366004611b4e565b610943565b610270610482366004611b6b565b610b81565b34801561049357600080fd5b506104de60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a4565b6106257f000000000000000000000000000000000000000000000000000000000000000061051b8585856108d5565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061058760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105a39796959493929190611c3a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611493565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856106aa60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516106bc959493929190611c99565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156107c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e49190611ce7565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016108b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6108f1604063ffffffff8816611d38565b6108fb9190611d68565b610906601088611d38565b6109139062030d40611db6565b61091d9190611db6565b6109279190611db6565b6109319190611db6565b61093b9190611db6565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff161580801561098e575060005460017401000000000000000000000000000000000000000090910460ff16105b806109c05750303b1580156109c0575060005474010000000000000000000000000000000000000000900460ff166001145b610a4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016108af565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610ad257600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055610b1a611548565b8015610b7d57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610b89610750565b15610bf0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016108af565b60f087901c60028110610cab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016108af565b8061ffff16600003610da0576000610cfc878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f9250611621915050565b600081815260cb602052604090205490915060ff1615610d9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016108af565b505b6000610de6898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164092505050565b9050610df0611663565b15610e2857853414610e0457610e04611de2565b600081815260ce602052604090205460ff1615610e2357610e23611de2565b610f7a565b3415610edc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016108af565b600081815260ce602052604090205460ff16610f7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016108af565b610f8387611787565b15611036576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016108af565b600081815260cb602052604090205460ff16156110d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016108af565b6110f6856110e7611388619c40611db6565b67ffffffffffffffff166117fe565b158061111c575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561123557600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161122e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b505061146e565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006112c688619c405a6112899190611e11565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061181c92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561135d57600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a261146a565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c42908490611510908890839089906000908990600401611e28565b6000604051808303818588803b15801561152957600080fd5b505af115801561153d573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff166115f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016108af565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b600061162f85858585611836565b805190602001209050949350505050565b60006116508787878787876118cf565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156107e457507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa158015611747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176b9190611e80565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff82163014806117f857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b60608484848460405160240161184f9493929190611e9d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b60608686868686866040516024016118ec96959493929190611ee7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461199057600080fd5b50565b60008083601f8401126119a557600080fd5b50813567ffffffffffffffff8111156119bd57600080fd5b6020830191508360208285010111156119d557600080fd5b9250929050565b803563ffffffff811681146119f057600080fd5b919050565b60008060008060608587031215611a0b57600080fd5b8435611a168161196e565b9350602085013567ffffffffffffffff811115611a3257600080fd5b611a3e87828801611993565b9094509250611a519050604086016119dc565b905092959194509250565b6000815180845260005b81811015611a8257602081850181015186830182015201611a66565b81811115611a94576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611ada6020830184611a5c565b9392505050565b600060208284031215611af357600080fd5b5035919050565b600080600060408486031215611b0f57600080fd5b833567ffffffffffffffff811115611b2657600080fd5b611b3286828701611993565b9094509250611b459050602085016119dc565b90509250925092565b600060208284031215611b6057600080fd5b8135611ada8161196e565b600080600080600080600060c0888a031215611b8657600080fd5b873596506020880135611b988161196e565b95506040880135611ba88161196e565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611bd257600080fd5b611bde8a828b01611993565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611c8c60c083018486611bf1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611cc9608083018688611bf1565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611cf957600080fd5b81518015158114611ada57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611d5f57611d5f611d09565b02949350505050565b600067ffffffffffffffff80841680611daa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611dd957611dd9611d09565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611e2357611e23611d09565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611e7560a0830184611a5c565b979650505050505050565b600060208284031215611e9257600080fd5b8151611ada8161196e565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611ed66080830185611a5c565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611f3260c0830184611a5c565b9897505050505050505056fea164736f6c634300080f000a", + "deployedBytecode": "0x6080604052600436106101755760003560e01c80636425666b116100cb578063a4e7f8bd1161007f578063c4d66de811610059578063c4d66de814610454578063d764ad0b14610474578063ecc704281461048757600080fd5b8063a4e7f8bd146103d4578063b1b1b20914610404578063b28ade251461043457600080fd5b806383a74074116100b057806383a74074146103895780638cbeeef21461029a5780639fce812c146103a057600080fd5b80636425666b146103415780636e296e451461037457600080fd5b80633dbb202b1161012d57806354fd4d501161010757806354fd4d50146102b05780635644cfdf146103065780635c975abb1461031c57600080fd5b80633dbb202b1461025d5780633f827a5a146102725780634c1d6a691461029a57600080fd5b80630ff754ea1161015e5780630ff754ea146101c25780632828d7e81461021b57806335e80ab31461023057600080fd5b8063028f85f71461017a5780630c568498146101ad575b600080fd5b34801561018657600080fd5b5061018f601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b5061018f603f81565b3480156101ce57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a4565b34801561022757600080fd5b5061018f604081565b34801561023c57600080fd5b5060fb546101f69073ffffffffffffffffffffffffffffffffffffffff1681565b61027061026b3660046119f5565b6104ec565b005b34801561027e57600080fd5b50610287600181565b60405161ffff90911681526020016101a4565b3480156102a657600080fd5b5061018f619c4081565b3480156102bc57600080fd5b506102f96040518060400160405280600581526020017f322e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516101a49190611ac7565b34801561031257600080fd5b5061018f61138881565b34801561032857600080fd5b50610331610750565b60405190151581526020016101a4565b34801561034d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101f6565b34801561038057600080fd5b506101f66107e9565b34801561039557600080fd5b5061018f62030d4081565b3480156103ac57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b3480156103e057600080fd5b506103316103ef366004611ae1565b60ce6020526000908152604090205460ff1681565b34801561041057600080fd5b5061033161041f366004611ae1565b60cb6020526000908152604090205460ff1681565b34801561044057600080fd5b5061018f61044f366004611afa565b6108d5565b34801561046057600080fd5b5061027061046f366004611b4e565b610943565b610270610482366004611b6b565b610b81565b34801561049357600080fd5b506104de60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a4565b6106257f000000000000000000000000000000000000000000000000000000000000000061051b8585856108d5565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061058760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105a39796959493929190611c3a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611493565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856106aa60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516106bc959493929190611c99565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156107c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e49190611ce7565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016108b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6108f1604063ffffffff8816611d38565b6108fb9190611d68565b610906601088611d38565b6109139062030d40611db6565b61091d9190611db6565b6109279190611db6565b6109319190611db6565b61093b9190611db6565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff161580801561098e575060005460017401000000000000000000000000000000000000000090910460ff16105b806109c05750303b1580156109c0575060005474010000000000000000000000000000000000000000900460ff166001145b610a4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016108af565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610ad257600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055610b1a611548565b8015610b7d57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610b89610750565b15610bf0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016108af565b60f087901c60028110610cab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016108af565b8061ffff16600003610da0576000610cfc878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f9250611621915050565b600081815260cb602052604090205490915060ff1615610d9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016108af565b505b6000610de6898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164092505050565b9050610df0611663565b15610e2857853414610e0457610e04611de2565b600081815260ce602052604090205460ff1615610e2357610e23611de2565b610f7a565b3415610edc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016108af565b600081815260ce602052604090205460ff16610f7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016108af565b610f8387611787565b15611036576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016108af565b600081815260cb602052604090205460ff16156110d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016108af565b6110f6856110e7611388619c40611db6565b67ffffffffffffffff166117fe565b158061111c575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561123557600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161122e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b505061146e565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006112c688619c405a6112899190611e11565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061181c92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561135d57600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a261146a565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c42908490611510908890839089906000908990600401611e28565b6000604051808303818588803b15801561152957600080fd5b505af115801561153d573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff166115f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016108af565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b600061162f85858585611836565b805190602001209050949350505050565b60006116508787878787876118cf565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156107e457507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa158015611747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176b9190611e80565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff82163014806117f857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b60608484848460405160240161184f9493929190611e9d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b60608686868686866040516024016118ec96959493929190611ee7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461199057600080fd5b50565b60008083601f8401126119a557600080fd5b50813567ffffffffffffffff8111156119bd57600080fd5b6020830191508360208285010111156119d557600080fd5b9250929050565b803563ffffffff811681146119f057600080fd5b919050565b60008060008060608587031215611a0b57600080fd5b8435611a168161196e565b9350602085013567ffffffffffffffff811115611a3257600080fd5b611a3e87828801611993565b9094509250611a519050604086016119dc565b905092959194509250565b6000815180845260005b81811015611a8257602081850181015186830182015201611a66565b81811115611a94576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611ada6020830184611a5c565b9392505050565b600060208284031215611af357600080fd5b5035919050565b600080600060408486031215611b0f57600080fd5b833567ffffffffffffffff811115611b2657600080fd5b611b3286828701611993565b9094509250611b459050602085016119dc565b90509250925092565b600060208284031215611b6057600080fd5b8135611ada8161196e565b600080600080600080600060c0888a031215611b8657600080fd5b873596506020880135611b988161196e565b95506040880135611ba88161196e565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611bd257600080fd5b611bde8a828b01611993565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611c8c60c083018486611bf1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611cc9608083018688611bf1565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611cf957600080fd5b81518015158114611ada57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611d5f57611d5f611d09565b02949350505050565b600067ffffffffffffffff80841680611daa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611dd957611dd9611d09565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611e2357611e23611d09565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611e7560a0830184611a5c565b979650505050505050565b600060208284031215611e9257600080fd5b8151611ada8161196e565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611ed66080830185611a5c565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611f3260c0830184611a5c565b9897505050505050505056fea164736f6c634300080f000a", "devdoc": { "version": 1, "kind": "dev", @@ -514,43 +514,14 @@ } } }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"_portal\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"FailedRelayedMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"RelayedMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"messageNonce\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"SentMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"SentMessageExtension1\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSAGE_VERSION\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_CALLDATA_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_MESSENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"PORTAL\",\"outputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_CALL_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_CONSTANT_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_GAS_CHECK_BUFFER\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_RESERVED_GAS\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"baseGas\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"failedMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"_superchainConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messageNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"portal\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"relayMessage\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"sendMessage\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"successfulMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"superchainConfig\",\"outputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"xDomainMessageSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"baseGas(bytes,uint32)\":{\"params\":{\"_message\":\"Message to compute the amount of required gas for.\",\"_minGasLimit\":\"Minimum desired gas limit when message goes to target.\"},\"returns\":{\"_0\":\"Amount of gas required to guarantee message receipt.\"}},\"constructor\":{\"params\":{\"_portal\":\"Address of the OptimismPortal contract on this network.\"}},\"initialize(address)\":{\"params\":{\"_superchainConfig\":\"Address of the SuperchainConfig contract on this network.\"}},\"messageNonce()\":{\"returns\":{\"_0\":\"Nonce of the next message to be sent, with added message version.\"}},\"paused()\":{\"returns\":{\"_0\":\"Whether or not the contract is paused.\"}},\"relayMessage(uint256,address,address,uint256,uint256,bytes)\":{\"params\":{\"_message\":\"Message to send to the target.\",\"_minGasLimit\":\"Minimum amount of gas that the message can be executed with.\",\"_nonce\":\"Nonce of the message being relayed.\",\"_sender\":\"Address of the user who sent the message.\",\"_target\":\"Address that the message is targeted at.\",\"_value\":\"ETH value to send with the message.\"}},\"sendMessage(address,bytes,uint32)\":{\"params\":{\"_message\":\"Message to trigger the target address with.\",\"_minGasLimit\":\"Minimum gas limit that the message can be executed with.\",\"_target\":\"Target contract or wallet address.\"}},\"xDomainMessageSender()\":{\"returns\":{\"_0\":\"Address of the sender of the currently executing message on the other chain.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSAGE_VERSION()\":{\"notice\":\"Current message version identifier.\"},\"MIN_GAS_CALLDATA_OVERHEAD()\":{\"notice\":\"Extra gas added to base gas for each byte of calldata in a message.\"},\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR()\":{\"notice\":\"Denominator for dynamic overhead added to the base gas for a message.\"},\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR()\":{\"notice\":\"Numerator for dynamic overhead added to the base gas for a message.\"},\"OTHER_MESSENGER()\":{\"notice\":\"Address of the paired CrossDomainMessenger contract on the other chain.\"},\"PORTAL()\":{\"notice\":\"Address of the OptimismPortal. This will be removed in the future, use `portal` instead.\"},\"RELAY_CALL_OVERHEAD()\":{\"notice\":\"Gas reserved for performing the external call in `relayMessage`.\"},\"RELAY_CONSTANT_OVERHEAD()\":{\"notice\":\"Constant overhead added to the base gas for a message.\"},\"RELAY_GAS_CHECK_BUFFER()\":{\"notice\":\"Gas reserved for the execution between the `hasMinGas` check and the external call in `relayMessage`.\"},\"RELAY_RESERVED_GAS()\":{\"notice\":\"Gas reserved for finalizing the execution of `relayMessage` after the safe call.\"},\"baseGas(bytes,uint32)\":{\"notice\":\"Computes the amount of gas required to guarantee that a given message will be received on the other chain without running out of gas. Guaranteeing that a message will not run out of gas is important because this ensures that a message can always be replayed on the other chain if it fails to execute completely.\"},\"constructor\":{\"notice\":\"Constructs the L1CrossDomainMessenger contract.\"},\"failedMessages(bytes32)\":{\"notice\":\"Mapping of message hashes to a boolean if and only if the message has failed to be executed at least once. A message will not be present in this mapping if it successfully executed on the first attempt.\"},\"initialize(address)\":{\"notice\":\"Initializes the contract.\"},\"messageNonce()\":{\"notice\":\"Retrieves the next message nonce. Message version will be added to the upper two bytes of the message nonce. Message version allows us to treat messages as having different structures.\"},\"paused()\":{\"notice\":\"This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op.\"},\"portal()\":{\"notice\":\"Getter for the OptimismPortal address.\"},\"relayMessage(uint256,address,address,uint256,uint256,bytes)\":{\"notice\":\"Relays a message that was sent by the other CrossDomainMessenger contract. Can only be executed via cross-chain call from the other messenger OR if the message was already received once and is currently being replayed.\"},\"sendMessage(address,bytes,uint32)\":{\"notice\":\"Sends a message to some target address on the other chain. Note that if the call always reverts, then the message will be unrelayable, and any ETH sent will be permanently locked. The same will occur if the target on the other chain is considered unsafe (see the _isUnsafeTarget() function).\"},\"successfulMessages(bytes32)\":{\"notice\":\"Mapping of message hashes to boolean receipt values. Note that a message will only be present in this mapping if it has successfully been relayed on this chain, and can therefore not be relayed again.\"},\"superchainConfig()\":{\"notice\":\"Address of the SuperchainConfig contract.\"},\"version()\":{\"notice\":\"Semantic version.\"},\"xDomainMessageSender()\":{\"notice\":\"Retrieves the address of the contract or wallet that initiated the currently executing message on the other chain. Will throw an error if there is no message currently being executed. Allows the recipient of a call to see who triggered it.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1CrossDomainMessenger.sol\":\"L1CrossDomainMessenger\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1CrossDomainMessenger.sol\":{\"keccak256\":\"0x9df7a928c47b13e5762d37319b4b3632e2e19b4c8dba10209f7db53e6d9a05a2\",\"urls\":[\"bzz-raw://fd3d7c6503dc4572750dde44decce8e3b772e156456e33da6c8d560ddbc8b37d\",\"dweb:/ipfs/Qmes7MhyEdRweVzdEPWSYcScDbyKHpg2qxYK6dvsy4R2uU\"],\"license\":\"MIT\"},\"src/L1/L2OutputOracle.sol\":{\"keccak256\":\"0xecd3b0cd61ec0d1246ea19cc5095508b84ad0d586988f781b4de9233b3c2821d\",\"urls\":[\"bzz-raw://b4d5e6a842dd999ff09c6db97c8a5e44aaa5f84652a6eb1aa3c170094e9c9591\",\"dweb:/ipfs/QmfUaT1pX9rQBZm48zdwzaSQ7miW8Ek7kBwys1UhMFSYJR\"],\"license\":\"MIT\"},\"src/L1/OptimismPortal.sol\":{\"keccak256\":\"0xf128f38f10196f54f108f9ab1036db85b0e7b631b1c728b21a410c747963c193\",\"urls\":[\"bzz-raw://149a852fdf45ad58a6df9fa8503dbc8a8bdd40fe730010c83d1f57d698c15cb1\",\"dweb:/ipfs/QmYEhvArJ3Tud1kfyx2LwyAg9RMLb9hp8r3VLnFjR19Pyy\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0x4a03e4a42900cecb4e923b92a7a10edb367347260bf38a937ce31826f1644330\",\"urls\":[\"bzz-raw://29dbfb9f323dfb9c4ce23c27a876dd7caddda6a3a5d483429cda433021d9f145\",\"dweb:/ipfs/QmZff2htQcExkwLdoGZ6e81zCFeGZV8oXgn4BhpW8Sccq7\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x3dd454d7ec9e2a90a6daf4b0c2f9ba371eae564b6e535aa88884e50de7df340a\",\"urls\":[\"bzz-raw://710bcccf6a1071171c45c2594e896ef5a26080a00dd3586e9ce80148a731d55b\",\"dweb:/ipfs/QmRSSYggh5woP8Xd9SHhuNt6tF7hMaSUMMk8W5zWk34NeL\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x5c6346060b3e8d3bf4289b20fd869a66fbad8f69dc0b095845f990066b6c4d2b\",\"urls\":[\"bzz-raw://161277a9935cc567d76096a9a3ffc54632fda2020e02b4c5dc5541bfad3d166f\",\"dweb:/ipfs/QmXiDP2A4MPsN9VDNf9YbqbQQTU2J5tffWbJHg45f9LJyN\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Bytes.sol\":{\"keccak256\":\"0x827f47d123b0fdf3b08816d5b33831811704dbf4e554e53f2269354f6bba8859\",\"urls\":[\"bzz-raw://3137ac7204d30a245a8b0d67aa6da5286f1bd8c90379daab561f84963b6db782\",\"dweb:/ipfs/QmWRhisw3axJK833gUScs23ETh2MLFbVzzqzYVMKSDN3S9\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x75408c79fd51bd6f53ab1ad1719ec09264d1e6965cd5604c8346fbee76039fc3\",\"urls\":[\"bzz-raw://100be0dc2c772b569820b3c0828fac21fb241773c586eb8e789b4ddbca89f4f8\",\"dweb:/ipfs/QmW8NrsSeu1kYkga5cdjuzQ853dZZKFY22ZaycoHwiStbw\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x7ce27a05552aa69afa6b2ab6684dfe99f27366cf8ef2046baeb1fb62fff0022f\",\"urls\":[\"bzz-raw://a6a24f3ed56681720707a5ab0372fd67fcb1a4f6fb072c7140cda28bdb70f269\",\"dweb:/ipfs/QmW9uTpUULV4xmP7A7MoBDeDhVfQgmJG5qVUFGtXxWpWWK\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPReader.sol\":{\"keccak256\":\"0x9ba74a3b0a11693e622380807d213d5d1250d974e18b2cd768da9cbe719a6778\",\"urls\":[\"bzz-raw://0808d721ed9e05707526ee134faa051d707a95ee6b8bd6e0b1972275da8e5723\",\"dweb:/ipfs/QmcTTPu9xgckfWdbFUAcr2RAgk3J6vzyR4FpV798TjFMeN\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/libraries/trie/MerkleTrie.sol\":{\"keccak256\":\"0xf8ba770ee6666e73ae43184c700e9c704b2c4ace71f9e3c2227ddc11a8148b4c\",\"urls\":[\"bzz-raw://4702ccee1fe44aea3ee01d59e6152eb755da083f786f00947fec4437c064fe74\",\"dweb:/ipfs/QmQjFj5J7hrEM1dxJjFszzW2Cs7g7eMhYNBXonF2DXBstE\"],\"license\":\"MIT\"},\"src/libraries/trie/SecureMerkleTrie.sol\":{\"keccak256\":\"0xeaff8315cfd21197bc6bc859c2decf5d4f4838c9c357c502cdf2b1eac863d288\",\"urls\":[\"bzz-raw://79dcdcaa560aea51d138da4f5dc553a1808b6de090b2dc1629f18375edbff681\",\"dweb:/ipfs/QmbE4pUPhf5fLKW4W6cEjhQs55gEDvHmbmoBqkW1yz3bnw\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x62e11a169b3fa987af2427bf5117612e2770d4cca51565e6bbfe255ff7ffc4bb\",\"urls\":[\"bzz-raw://c852c8c0571bb22d9f28d577620a71de5ee60eb0c7ab8c68645da9a7295d24a0\",\"dweb:/ipfs/QmdixJ2dpsz8N8CgZz8z1MkZNVjw6ZkRM6bS7mchPYX6Yi\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"],\"license\":\"Apache-2.0\"}},\"version\":1}", - "numDeployments": 8, - "receipt": { - "transactionHash": "0xc73ca7bd71a8b59260cce45b0b11ce40ae19d7888e1fe79a1897ab17b564ee32", - "transactionIndex": "0xc", - "blockHash": "0xc66ec67b9c6d76b26bf152b19705f229c5f0164a669badef3c1d282d30fd6871", - "blockNumber": "0x49d1f8", - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "cumulativeGasUsed": "0x2132f2", - "gasUsed": "0x1bf2d5", - "contractAddress": "0xC3c7E6f4ad6a593a9731a39FA883eC1999d7D873", - "logs": [ - { - "address": "0xC3c7E6f4ad6a593a9731a39FA883eC1999d7D873", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "blockHash": "0xc66ec67b9c6d76b26bf152b19705f229c5f0164a669badef3c1d282d30fd6871", - "blockNumber": "0x49d1f8", - "transactionHash": "0xc73ca7bd71a8b59260cce45b0b11ce40ae19d7888e1fe79a1897ab17b564ee32", - "transactionIndex": "0xc", - "logIndex": "0x2", - "removed": false - } - ], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "type": "0x2", - "effectiveGasPrice": "0xb7974470" - }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"_portal\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"FailedRelayedMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"RelayedMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"messageNonce\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"SentMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"SentMessageExtension1\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSAGE_VERSION\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_CALLDATA_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_MESSENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"PORTAL\",\"outputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_CALL_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_CONSTANT_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_GAS_CHECK_BUFFER\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_RESERVED_GAS\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"baseGas\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"failedMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"_superchainConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messageNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"portal\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"relayMessage\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"sendMessage\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"successfulMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"superchainConfig\",\"outputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"xDomainMessageSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"baseGas(bytes,uint32)\":{\"params\":{\"_message\":\"Message to compute the amount of required gas for.\",\"_minGasLimit\":\"Minimum desired gas limit when message goes to target.\"},\"returns\":{\"_0\":\"Amount of gas required to guarantee message receipt.\"}},\"constructor\":{\"params\":{\"_portal\":\"Address of the OptimismPortal contract on this network.\"}},\"initialize(address)\":{\"params\":{\"_superchainConfig\":\"Address of the SuperchainConfig contract on this network.\"}},\"messageNonce()\":{\"returns\":{\"_0\":\"Nonce of the next message to be sent, with added message version.\"}},\"paused()\":{\"returns\":{\"_0\":\"Whether or not the contract is paused.\"}},\"relayMessage(uint256,address,address,uint256,uint256,bytes)\":{\"params\":{\"_message\":\"Message to send to the target.\",\"_minGasLimit\":\"Minimum amount of gas that the message can be executed with.\",\"_nonce\":\"Nonce of the message being relayed.\",\"_sender\":\"Address of the user who sent the message.\",\"_target\":\"Address that the message is targeted at.\",\"_value\":\"ETH value to send with the message.\"}},\"sendMessage(address,bytes,uint32)\":{\"params\":{\"_message\":\"Message to trigger the target address with.\",\"_minGasLimit\":\"Minimum gas limit that the message can be executed with.\",\"_target\":\"Target contract or wallet address.\"}},\"xDomainMessageSender()\":{\"returns\":{\"_0\":\"Address of the sender of the currently executing message on the other chain.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSAGE_VERSION()\":{\"notice\":\"Current message version identifier.\"},\"MIN_GAS_CALLDATA_OVERHEAD()\":{\"notice\":\"Extra gas added to base gas for each byte of calldata in a message.\"},\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR()\":{\"notice\":\"Denominator for dynamic overhead added to the base gas for a message.\"},\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR()\":{\"notice\":\"Numerator for dynamic overhead added to the base gas for a message.\"},\"OTHER_MESSENGER()\":{\"notice\":\"Address of the paired CrossDomainMessenger contract on the other chain.\"},\"PORTAL()\":{\"notice\":\"Address of the OptimismPortal. This will be removed in the future, use `portal` instead.\"},\"RELAY_CALL_OVERHEAD()\":{\"notice\":\"Gas reserved for performing the external call in `relayMessage`.\"},\"RELAY_CONSTANT_OVERHEAD()\":{\"notice\":\"Constant overhead added to the base gas for a message.\"},\"RELAY_GAS_CHECK_BUFFER()\":{\"notice\":\"Gas reserved for the execution between the `hasMinGas` check and the external call in `relayMessage`.\"},\"RELAY_RESERVED_GAS()\":{\"notice\":\"Gas reserved for finalizing the execution of `relayMessage` after the safe call.\"},\"baseGas(bytes,uint32)\":{\"notice\":\"Computes the amount of gas required to guarantee that a given message will be received on the other chain without running out of gas. Guaranteeing that a message will not run out of gas is important because this ensures that a message can always be replayed on the other chain if it fails to execute completely.\"},\"constructor\":{\"notice\":\"Constructs the L1CrossDomainMessenger contract.\"},\"failedMessages(bytes32)\":{\"notice\":\"Mapping of message hashes to a boolean if and only if the message has failed to be executed at least once. A message will not be present in this mapping if it successfully executed on the first attempt.\"},\"initialize(address)\":{\"notice\":\"Initializes the contract.\"},\"messageNonce()\":{\"notice\":\"Retrieves the next message nonce. Message version will be added to the upper two bytes of the message nonce. Message version allows us to treat messages as having different structures.\"},\"paused()\":{\"notice\":\"This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op.\"},\"portal()\":{\"notice\":\"Getter for the OptimismPortal address.\"},\"relayMessage(uint256,address,address,uint256,uint256,bytes)\":{\"notice\":\"Relays a message that was sent by the other CrossDomainMessenger contract. Can only be executed via cross-chain call from the other messenger OR if the message was already received once and is currently being replayed.\"},\"sendMessage(address,bytes,uint32)\":{\"notice\":\"Sends a message to some target address on the other chain. Note that if the call always reverts, then the message will be unrelayable, and any ETH sent will be permanently locked. The same will occur if the target on the other chain is considered unsafe (see the _isUnsafeTarget() function).\"},\"successfulMessages(bytes32)\":{\"notice\":\"Mapping of message hashes to boolean receipt values. Note that a message will only be present in this mapping if it has successfully been relayed on this chain, and can therefore not be relayed again.\"},\"superchainConfig()\":{\"notice\":\"Address of the other SuperchainConfig contract.\"},\"version()\":{\"notice\":\"Semantic version.\"},\"xDomainMessageSender()\":{\"notice\":\"Retrieves the address of the contract or wallet that initiated the currently executing message on the other chain. Will throw an error if there is no message currently being executed. Allows the recipient of a call to see who triggered it.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1CrossDomainMessenger.sol\":\"L1CrossDomainMessenger\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1CrossDomainMessenger.sol\":{\"keccak256\":\"0xa4624575365f9e6cc32cc7305f414b2799649e2aa8bcee76557685441e4d5709\",\"urls\":[\"bzz-raw://2552e5e25af29f2708cc73cadd9b465e535317d5fac7504fd730f1635c008a92\",\"dweb:/ipfs/QmZHrPr7o8qVQHt1QcLY9gKRo7n4WTTz9g6iXwJfmG6Uvz\"],\"license\":\"MIT\"},\"src/L1/L2OutputOracle.sol\":{\"keccak256\":\"0xecd3b0cd61ec0d1246ea19cc5095508b84ad0d586988f781b4de9233b3c2821d\",\"urls\":[\"bzz-raw://b4d5e6a842dd999ff09c6db97c8a5e44aaa5f84652a6eb1aa3c170094e9c9591\",\"dweb:/ipfs/QmfUaT1pX9rQBZm48zdwzaSQ7miW8Ek7kBwys1UhMFSYJR\"],\"license\":\"MIT\"},\"src/L1/OptimismPortal.sol\":{\"keccak256\":\"0x62c4745158651d87705e20b3bbe5aecc09790a2a08a84b65cf5961a746716363\",\"urls\":[\"bzz-raw://47ec233411fcad292daaa5463c2c86352718c0e0ff8d1f27a87d4781382f91f5\",\"dweb:/ipfs/QmfKW1SDvoBcFeYRXYwnBsXKP5npC4PXNXpQz2wVn1Xx7S\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x9d6e33ea5d12b78fd3cb024ed5863c8c14cb55977cbab56fd9ce5c309918afc6\",\"urls\":[\"bzz-raw://d8545d6255ed4428b168a3547d6935043e5b680344d650fd090293ba36b59897\",\"dweb:/ipfs/QmPLVma7kqTTgbAHtxog2MGD7S2Wr8nd42MhBcfJ5yyF4W\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x5c6346060b3e8d3bf4289b20fd869a66fbad8f69dc0b095845f990066b6c4d2b\",\"urls\":[\"bzz-raw://161277a9935cc567d76096a9a3ffc54632fda2020e02b4c5dc5541bfad3d166f\",\"dweb:/ipfs/QmXiDP2A4MPsN9VDNf9YbqbQQTU2J5tffWbJHg45f9LJyN\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Bytes.sol\":{\"keccak256\":\"0x827f47d123b0fdf3b08816d5b33831811704dbf4e554e53f2269354f6bba8859\",\"urls\":[\"bzz-raw://3137ac7204d30a245a8b0d67aa6da5286f1bd8c90379daab561f84963b6db782\",\"dweb:/ipfs/QmWRhisw3axJK833gUScs23ETh2MLFbVzzqzYVMKSDN3S9\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x75408c79fd51bd6f53ab1ad1719ec09264d1e6965cd5604c8346fbee76039fc3\",\"urls\":[\"bzz-raw://100be0dc2c772b569820b3c0828fac21fb241773c586eb8e789b4ddbca89f4f8\",\"dweb:/ipfs/QmW8NrsSeu1kYkga5cdjuzQ853dZZKFY22ZaycoHwiStbw\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPReader.sol\":{\"keccak256\":\"0x9ba74a3b0a11693e622380807d213d5d1250d974e18b2cd768da9cbe719a6778\",\"urls\":[\"bzz-raw://0808d721ed9e05707526ee134faa051d707a95ee6b8bd6e0b1972275da8e5723\",\"dweb:/ipfs/QmcTTPu9xgckfWdbFUAcr2RAgk3J6vzyR4FpV798TjFMeN\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/libraries/trie/MerkleTrie.sol\":{\"keccak256\":\"0xf8ba770ee6666e73ae43184c700e9c704b2c4ace71f9e3c2227ddc11a8148b4c\",\"urls\":[\"bzz-raw://4702ccee1fe44aea3ee01d59e6152eb755da083f786f00947fec4437c064fe74\",\"dweb:/ipfs/QmQjFj5J7hrEM1dxJjFszzW2Cs7g7eMhYNBXonF2DXBstE\"],\"license\":\"MIT\"},\"src/libraries/trie/SecureMerkleTrie.sol\":{\"keccak256\":\"0xeaff8315cfd21197bc6bc859c2decf5d4f4838c9c357c502cdf2b1eac863d288\",\"urls\":[\"bzz-raw://79dcdcaa560aea51d138da4f5dc553a1808b6de090b2dc1629f18375edbff681\",\"dweb:/ipfs/QmbE4pUPhf5fLKW4W6cEjhQs55gEDvHmbmoBqkW1yz3bnw\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x62e11a169b3fa987af2427bf5117612e2770d4cca51565e6bbfe255ff7ffc4bb\",\"urls\":[\"bzz-raw://c852c8c0571bb22d9f28d577620a71de5ee60eb0c7ab8c68645da9a7295d24a0\",\"dweb:/ipfs/QmdixJ2dpsz8N8CgZz8z1MkZNVjw6ZkRM6bS7mchPYX6Yi\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"],\"license\":\"Apache-2.0\"}},\"version\":1}", + "numDeployments": 1, + "receipt": "", "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [ { - "astId": 89394, + "astId": 93594, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "spacer_0_0_20", "offset": 0, @@ -574,7 +545,7 @@ "type": "t_bool" }, { - "astId": 89401, + "astId": 93601, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "spacer_1_0_1600", "offset": 0, @@ -582,7 +553,7 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 89404, + "astId": 93604, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "spacer_51_0_20", "offset": 0, @@ -590,7 +561,7 @@ "type": "t_address" }, { - "astId": 89409, + "astId": 93609, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "spacer_52_0_1568", "offset": 0, @@ -598,7 +569,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 89412, + "astId": 93612, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "spacer_101_0_1", "offset": 0, @@ -606,7 +577,7 @@ "type": "t_bool" }, { - "astId": 89417, + "astId": 93617, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "spacer_102_0_1568", "offset": 0, @@ -614,7 +585,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 89420, + "astId": 93620, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "spacer_151_0_32", "offset": 0, @@ -622,7 +593,7 @@ "type": "t_uint256" }, { - "astId": 89425, + "astId": 93625, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "spacer_152_0_1568", "offset": 0, @@ -630,7 +601,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 89430, + "astId": 93630, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "spacer_201_0_32", "offset": 0, @@ -638,7 +609,7 @@ "type": "t_mapping(t_bytes32,t_bool)" }, { - "astId": 89435, + "astId": 93635, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "spacer_202_0_32", "offset": 0, @@ -646,7 +617,7 @@ "type": "t_mapping(t_bytes32,t_bool)" }, { - "astId": 89483, + "astId": 93683, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "successfulMessages", "offset": 0, @@ -654,7 +625,7 @@ "type": "t_mapping(t_bytes32,t_bool)" }, { - "astId": 89486, + "astId": 93686, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "xDomainMsgSender", "offset": 0, @@ -662,7 +633,7 @@ "type": "t_address" }, { - "astId": 89489, + "astId": 93689, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "msgNonce", "offset": 0, @@ -670,7 +641,7 @@ "type": "t_uint240" }, { - "astId": 89494, + "astId": 93694, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "failedMessages", "offset": 0, @@ -678,7 +649,7 @@ "type": "t_mapping(t_bytes32,t_bool)" }, { - "astId": 89499, + "astId": 93699, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "__gap", "offset": 0, @@ -686,12 +657,12 @@ "type": "t_array(t_uint256)44_storage" }, { - "astId": 72191, + "astId": 74735, "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", "label": "superchainConfig", "offset": 0, "slot": "251", - "type": "t_contract(SuperchainConfig)75085" + "type": "t_contract(SuperchainConfig)77526" } ], "types": { @@ -728,7 +699,7 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_contract(SuperchainConfig)75085": { + "t_contract(SuperchainConfig)77526": { "encoding": "inplace", "label": "contract SuperchainConfig", "numberOfBytes": "20" @@ -757,7 +728,7 @@ } } }, - "transactionHash": "0xc73ca7bd71a8b59260cce45b0b11ce40ae19d7888e1fe79a1897ab17b564ee32", + "transactionHash": "0x3c10f93bb05f674af954e0748cc53f0be68c6f27265c58613dc2b82b705bb3e7", "userdoc": { "version": 1, "kind": "user", @@ -823,7 +794,7 @@ "notice": "Mapping of message hashes to boolean receipt values. Note that a message will only be present in this mapping if it has successfully been relayed on this chain, and can therefore not be relayed again." }, "superchainConfig()": { - "notice": "Address of the SuperchainConfig contract." + "notice": "Address of the other SuperchainConfig contract." }, "version()": { "notice": "Semantic version." diff --git a/packages/contracts-bedrock/deployments/sepolia/L1CrossDomainMessengerProxy.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1CrossDomainMessengerProxy.json similarity index 72% rename from packages/contracts-bedrock/deployments/sepolia/L1CrossDomainMessengerProxy.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1CrossDomainMessengerProxy.json index 88097abff1ce..0b1ab5f6220c 100644 --- a/packages/contracts-bedrock/deployments/sepolia/L1CrossDomainMessengerProxy.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1CrossDomainMessengerProxy.json @@ -21,11 +21,8 @@ "type": "fallback" } ], - "address": "0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef", - "args": [ - "0x9bFE9c5609311DF1c011c47642253B78a4f33F4B", - "OVM_L1CrossDomainMessenger" - ], + "address": "0x534571C20b87500CC86ae505da23eD357C6aFc2D", + "args": "[\"0x6cabEB4a6C417fA09916681CF11d4173dAC990a6\",\"\\OVM_L1CrossDomainMessenger\\\"]", "bytecode": "0x608060405234801561001057600080fd5b506040516105f03803806105f083398101604081905261002f91610088565b30600090815260016020908152604080832080546001600160a01b0319166001600160a01b03871617905590829052902061006a8282610203565b5050506102c2565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561009b57600080fd5b82516001600160a01b03811681146100b257600080fd5b602084810151919350906001600160401b03808211156100d157600080fd5b818601915086601f8301126100e557600080fd5b8151818111156100f7576100f7610072565b604051601f8201601f19908116603f0116810190838211818310171561011f5761011f610072565b81604052828152898684870101111561013757600080fd5b600093505b82841015610159578484018601518185018701529285019261013c565b8284111561016a5760008684830101525b8096505050505050509250929050565b600181811c9082168061018e57607f821691505b6020821081036101ae57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156101fe57600081815260208120601f850160051c810160208610156101db5750805b601f850160051c820191505b818110156101fa578281556001016101e7565b5050505b505050565b81516001600160401b0381111561021c5761021c610072565b6102308161022a845461017a565b846101b4565b602080601f831160018114610265576000841561024d5750858301515b600019600386901b1c1916600185901b1785556101fa565b600085815260208120601f198616915b8281101561029457888601518255948401946001909101908401610275565b50858210156102b25787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61031f806102d16000396000f3fe608060408181523060009081526001602090815282822054908290529181207fbf40fac1000000000000000000000000000000000000000000000000000000009093529173ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac19061006d9060846101e2565b602060405180830381865afa15801561008a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ae91906102c5565b905073ffffffffffffffffffffffffffffffffffffffff8116610157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f5265736f6c76656444656c656761746550726f78793a2074617267657420616460448201527f6472657373206d75737420626520696e697469616c697a656400000000000000606482015260840160405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff16600036604051610182929190610302565b600060405180830381855af49150503d80600081146101bd576040519150601f19603f3d011682016040523d82523d6000602084013e6101c2565b606091505b5090925090508115156001036101da57805160208201f35b805160208201fd5b600060208083526000845481600182811c91508083168061020457607f831692505b858310810361023a577f4e487b710000000000000000000000000000000000000000000000000000000085526022600452602485fd5b878601838152602001818015610257576001811461028b576102b6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616825284151560051b820196506102b6565b60008b81526020902060005b868110156102b057815484820152908501908901610297565b83019750505b50949998505050505050505050565b6000602082840312156102d757600080fd5b815173ffffffffffffffffffffffffffffffffffffffff811681146102fb57600080fd5b9392505050565b818382376000910190815291905056fea164736f6c634300080f000a", "deployedBytecode": "0x608060408181523060009081526001602090815282822054908290529181207fbf40fac1000000000000000000000000000000000000000000000000000000009093529173ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac19061006d9060846101e2565b602060405180830381865afa15801561008a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ae91906102c5565b905073ffffffffffffffffffffffffffffffffffffffff8116610157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f5265736f6c76656444656c656761746550726f78793a2074617267657420616460448201527f6472657373206d75737420626520696e697469616c697a656400000000000000606482015260840160405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff16600036604051610182929190610302565b600060405180830381855af49150503d80600081146101bd576040519150601f19603f3d011682016040523d82523d6000602084013e6101c2565b606091505b5090925090508115156001036101da57805160208201f35b805160208201fd5b600060208083526000845481600182811c91508083168061020457607f831692505b858310810361023a577f4e487b710000000000000000000000000000000000000000000000000000000085526022600452602485fd5b878601838152602001818015610257576001811461028b576102b6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616825284151560051b820196506102b6565b60008b81526020902060005b868110156102b057815484820152908501908901610297565b83019750505b50949998505050505050505050565b6000602082840312156102d757600080fd5b815173ffffffffffffffffffffffffffffffffffffffff811681146102fb57600080fd5b9392505050565b818382376000910190815291905056fea164736f6c634300080f000a", "devdoc": { @@ -40,29 +37,29 @@ } } }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract AddressManager\",\"name\":\"_addressManager\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_implementationName\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_addressManager\":\"Address of the AddressManager.\",\"_implementationName\":\"implementationName of the contract to proxy to.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/legacy/ResolvedDelegateProxy.sol\":\"ResolvedDelegateProxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"src/legacy/AddressManager.sol\":{\"keccak256\":\"0x1fcb990df6473f7fa360d5924d62d39ce2ca97d45668e3901e5405cfbe598b19\",\"urls\":[\"bzz-raw://9d08358b60dea54dbc32e988a1bb7ea909488063eaae3c5ae28a322f125c9b34\",\"dweb:/ipfs/QmZPQwdjLh9gaamNAoTUmWwwbRKj3yHovBYfnTPnfuKvUt\"],\"license\":\"MIT\"},\"src/legacy/ResolvedDelegateProxy.sol\":{\"keccak256\":\"0xe4ac1ddcf33df096f54db4e02d0b128704facdbd918645888d2d0431e4bb11fb\",\"urls\":[\"bzz-raw://61eeaea537ab98eb27b65afaf3665dc16338bd81f48f01b8477c6176328b3033\",\"dweb:/ipfs/QmSGYe6ZB8BrC7u28NTGeAtpqs9CcfkneuCngEUS1tyujS\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 4, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract AddressManager\",\"name\":\"_addressManager\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_implementationName\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_addressManager\":\"Address of the AddressManager.\",\"_implementationName\":\"implementationName of the contract to proxy to.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/legacy/ResolvedDelegateProxy.sol\":\"ResolvedDelegateProxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"src/legacy/AddressManager.sol\":{\"keccak256\":\"0x1fcb990df6473f7fa360d5924d62d39ce2ca97d45668e3901e5405cfbe598b19\",\"urls\":[\"bzz-raw://9d08358b60dea54dbc32e988a1bb7ea909488063eaae3c5ae28a322f125c9b34\",\"dweb:/ipfs/QmZPQwdjLh9gaamNAoTUmWwwbRKj3yHovBYfnTPnfuKvUt\"],\"license\":\"MIT\"},\"src/legacy/ResolvedDelegateProxy.sol\":{\"keccak256\":\"0x33425509c2982627f1e88977d76637096322954c474217bd4d03a3244814f332\",\"urls\":[\"bzz-raw://2cb3702c3c280ebf65e636b2d2fd8533aebae69014304014353afee129415c53\",\"dweb:/ipfs/QmYpcVwF8hzwCcPqv535oENbars988N21MVvvDw9eQNaSf\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 1, "receipt": { - "transactionHash": "0xf6dcfce79f0b87a325b4f42d397a4a02c0143e1a2aafd931eed9190f13336808", - "transactionIndex": "0x9", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", + "transactionHash": "0x3af1c1270996cb801de0f15a6f1c0ccb86923bd54f4099f4c36fc640a043be3b", + "transactionIndex": "0x10", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "from": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", "to": null, - "cumulativeGasUsed": "0x5f2b88", + "cumulativeGasUsed": "0x709333", "gasUsed": "0x44e5e", - "contractAddress": "0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef", + "contractAddress": "0x534571C20b87500CC86ae505da23eD357C6aFc2D", "logs": [], "status": "0x1", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "type": "0x2", - "effectiveGasPrice": "0xbec78df7" + "effectiveGasPrice": "0xb2d05e0a" }, "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [ { - "astId": 63316, + "astId": 88060, "contract": "src/legacy/ResolvedDelegateProxy.sol:ResolvedDelegateProxy", "label": "implementationName", "offset": 0, @@ -70,12 +67,12 @@ "type": "t_mapping(t_address,t_string_storage)" }, { - "astId": 63322, + "astId": 88066, "contract": "src/legacy/ResolvedDelegateProxy.sol:ResolvedDelegateProxy", "label": "addressManager", "offset": 0, "slot": "1", - "type": "t_mapping(t_address,t_contract(AddressManager)62454)" + "type": "t_mapping(t_address,t_contract(AddressManager)87201)" } ], "types": { @@ -84,17 +81,17 @@ "label": "address", "numberOfBytes": "20" }, - "t_contract(AddressManager)62454": { + "t_contract(AddressManager)87201": { "encoding": "inplace", "label": "contract AddressManager", "numberOfBytes": "20" }, - "t_mapping(t_address,t_contract(AddressManager)62454)": { + "t_mapping(t_address,t_contract(AddressManager)87201)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => contract AddressManager)", "numberOfBytes": "32", - "value": "t_contract(AddressManager)62454" + "value": "t_contract(AddressManager)87201" }, "t_mapping(t_address,t_string_storage)": { "encoding": "mapping", @@ -110,7 +107,7 @@ } } }, - "transactionHash": "0xf6dcfce79f0b87a325b4f42d397a4a02c0143e1a2aafd931eed9190f13336808", + "transactionHash": "0x3af1c1270996cb801de0f15a6f1c0ccb86923bd54f4099f4c36fc640a043be3b", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1ERC721Bridge.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1ERC721Bridge.json new file mode 100644 index 000000000000..0776c3b5c376 --- /dev/null +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1ERC721Bridge.json @@ -0,0 +1,482 @@ +{ + "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": [], + "name": "MESSENGER", + "outputs": [ + { + "internalType": "contract CrossDomainMessenger", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "OTHER_BRIDGE", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "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": [], + "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" + } + ], + "address": "0x4479610daE39D807a8d5B84101a1B14fe51786D2", + "args": [ + "0x534571C20b87500CC86ae505da23eD357C6aFc2D", + "0x4200000000000000000000000000000000000014" + ], + "bytecode": "0x60c060405234801561001057600080fd5b5060405161119138038061119183398101604081905261002f91610145565b81816001600160a01b0382166100a15760405162461bcd60e51b815260206004820152602c60248201527f4552433732314272696467653a206d657373656e6765722063616e6e6f74206260448201526b65206164647265737328302960a01b60648201526084015b60405180910390fd5b6001600160a01b03811661010f5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314272696467653a206f74686572206272696467652063616e6e6f60448201526e74206265206164647265737328302960881b6064820152608401610098565b6001600160a01b039182166080521660a052506101789050565b80516001600160a01b038116811461014057600080fd5b919050565b6000806040838503121561015857600080fd5b61016183610129565b915061016f60208401610129565b90509250929050565b60805160a051610fc46101cd600039600081816101ae0152818161020c0152818161031e0152610aa501526000818160bf015281816101d5015281816102f4015281816103550152610a760152610fc46000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063761f449311610076578063927ede2d1161005b578063927ede2d146101d0578063aa557452146101f7578063c89701a21461020a57600080fd5b8063761f4493146101965780637f46ddb2146101a957600080fd5b80633687011a146100a85780633cb747bf146100bd57806354fd4d50146101095780635d93a3fc14610152575b600080fd5b6100bb6100b6366004610c17565b610230565b005b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e352e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610d05565b610186610160366004610d1f565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b6040519015158152602001610100565b6100bb6101a4366004610d60565b6102dc565b6100df7f000000000000000000000000000000000000000000000000000000000000000081565b6100df7f000000000000000000000000000000000000000000000000000000000000000081565b6100bb610205366004610df8565b61075d565b7f00000000000000000000000000000000000000000000000000000000000000006100df565b333b156102c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102d48686333388888888610819565b505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103fa57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e29190610e6f565b73ffffffffffffffffffffffffffffffffffffffff16145b610486576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f74686572206272696467650060648201526084016102bb565b3073ffffffffffffffffffffffffffffffffffffffff88160361052b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c660000000000000000000000000000000000000000000060648201526084016102bb565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146105fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c31204272696467650000000000000060648201526084016102bb565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156106ba57600080fd5b505af11580156106ce573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac8787878760405161074c9493929190610ed5565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610800576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f7420626520616464726573732830290000000000000000000000000000000060648201526084016102bb565b6108108787338888888888610819565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff87166108bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f74206265206164647265737328302900000000000000000000000000000060648201526084016102bb565b600063761f449360e01b888a89898988886040516024016108e39796959493929190610f15565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b50506040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169250633dbb202b9150610ad1907f00000000000000000000000000000000000000000000000000000000000000009085908990600401610f72565b600060405180830381600087803b158015610aeb57600080fd5b505af1158015610aff573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610b7d9493929190610ed5565b60405180910390a4505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610bb257600080fd5b50565b803563ffffffff81168114610bc957600080fd5b919050565b60008083601f840112610be057600080fd5b50813567ffffffffffffffff811115610bf857600080fd5b602083019150836020828501011115610c1057600080fd5b9250929050565b60008060008060008060a08789031215610c3057600080fd5b8635610c3b81610b90565b95506020870135610c4b81610b90565b945060408701359350610c6060608801610bb5565b9250608087013567ffffffffffffffff811115610c7c57600080fd5b610c8889828a01610bce565b979a9699509497509295939492505050565b6000815180845260005b81811015610cc057602081850181015186830182015201610ca4565b81811115610cd2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610d186020830184610c9a565b9392505050565b600080600060608486031215610d3457600080fd5b8335610d3f81610b90565b92506020840135610d4f81610b90565b929592945050506040919091013590565b600080600080600080600060c0888a031215610d7b57600080fd5b8735610d8681610b90565b96506020880135610d9681610b90565b95506040880135610da681610b90565b94506060880135610db681610b90565b93506080880135925060a088013567ffffffffffffffff811115610dd957600080fd5b610de58a828b01610bce565b989b979a50959850939692959293505050565b600080600080600080600060c0888a031215610e1357600080fd5b8735610e1e81610b90565b96506020880135610e2e81610b90565b95506040880135610e3e81610b90565b945060608801359350610e5360808901610bb5565b925060a088013567ffffffffffffffff811115610dd957600080fd5b600060208284031215610e8157600080fd5b8151610d1881610b90565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000610f0b606083018486610e8c565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a0830152610f6560c083018486610e8c565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000610fa16060830185610c9a565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100a35760003560e01c8063761f449311610076578063927ede2d1161005b578063927ede2d146101d0578063aa557452146101f7578063c89701a21461020a57600080fd5b8063761f4493146101965780637f46ddb2146101a957600080fd5b80633687011a146100a85780633cb747bf146100bd57806354fd4d50146101095780635d93a3fc14610152575b600080fd5b6100bb6100b6366004610c17565b610230565b005b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e352e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610d05565b610186610160366004610d1f565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b6040519015158152602001610100565b6100bb6101a4366004610d60565b6102dc565b6100df7f000000000000000000000000000000000000000000000000000000000000000081565b6100df7f000000000000000000000000000000000000000000000000000000000000000081565b6100bb610205366004610df8565b61075d565b7f00000000000000000000000000000000000000000000000000000000000000006100df565b333b156102c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102d48686333388888888610819565b505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103fa57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e29190610e6f565b73ffffffffffffffffffffffffffffffffffffffff16145b610486576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f74686572206272696467650060648201526084016102bb565b3073ffffffffffffffffffffffffffffffffffffffff88160361052b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c660000000000000000000000000000000000000000000060648201526084016102bb565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146105fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c31204272696467650000000000000060648201526084016102bb565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156106ba57600080fd5b505af11580156106ce573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac8787878760405161074c9493929190610ed5565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610800576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f7420626520616464726573732830290000000000000000000000000000000060648201526084016102bb565b6108108787338888888888610819565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff87166108bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f74206265206164647265737328302900000000000000000000000000000060648201526084016102bb565b600063761f449360e01b888a89898988886040516024016108e39796959493929190610f15565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610a2357600080fd5b505af1158015610a37573d6000803e3d6000fd5b50506040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169250633dbb202b9150610ad1907f00000000000000000000000000000000000000000000000000000000000000009085908990600401610f72565b600060405180830381600087803b158015610aeb57600080fd5b505af1158015610aff573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610b7d9493929190610ed5565b60405180910390a4505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610bb257600080fd5b50565b803563ffffffff81168114610bc957600080fd5b919050565b60008083601f840112610be057600080fd5b50813567ffffffffffffffff811115610bf857600080fd5b602083019150836020828501011115610c1057600080fd5b9250929050565b60008060008060008060a08789031215610c3057600080fd5b8635610c3b81610b90565b95506020870135610c4b81610b90565b945060408701359350610c6060608801610bb5565b9250608087013567ffffffffffffffff811115610c7c57600080fd5b610c8889828a01610bce565b979a9699509497509295939492505050565b6000815180845260005b81811015610cc057602081850181015186830182015201610ca4565b81811115610cd2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610d186020830184610c9a565b9392505050565b600080600060608486031215610d3457600080fd5b8335610d3f81610b90565b92506020840135610d4f81610b90565b929592945050506040919091013590565b600080600080600080600060c0888a031215610d7b57600080fd5b8735610d8681610b90565b96506020880135610d9681610b90565b95506040880135610da681610b90565b94506060880135610db681610b90565b93506080880135925060a088013567ffffffffffffffff811115610dd957600080fd5b610de58a828b01610bce565b989b979a50959850939692959293505050565b600080600080600080600060c0888a031215610e1357600080fd5b8735610e1e81610b90565b96506020880135610e2e81610b90565b95506040880135610e3e81610b90565b945060608801359350610e5360808901610bb5565b925060a088013567ffffffffffffffff811115610dd957600080fd5b600060208284031215610e8157600080fd5b8151610d1881610b90565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201526000610f0b606083018486610e8c565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a0830152610f6560c083018486610e8c565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000610fa16060830185610c9a565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "bridgeERC721(address,address,uint256,uint32,bytes)": { + "params": { + "_extraData": "Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.", + "_localToken": "Address of the ERC721 on this domain.", + "_minGasLimit": "Minimum gas limit for the bridge message on the other domain.", + "_remoteToken": "Address of the ERC721 on the remote domain.", + "_tokenId": "Token ID to bridge." + } + }, + "bridgeERC721To(address,address,address,uint256,uint32,bytes)": { + "params": { + "_extraData": "Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.", + "_localToken": "Address of the ERC721 on this domain.", + "_minGasLimit": "Minimum gas limit for the bridge message on the other domain.", + "_remoteToken": "Address of the ERC721 on the remote domain.", + "_to": "Address to receive the token on the other domain.", + "_tokenId": "Token ID to bridge." + } + }, + "constructor": { + "params": { + "_messenger": "Address of the CrossDomainMessenger on this network.", + "_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." + } + }, + "messenger()": { + "returns": { + "_0": "Messenger contract on this domain." + } + }, + "otherBridge()": { + "returns": { + "_0": "Address of the bridge on the other network." + } + } + }, + "title": "L1ERC721Bridge" + }, + "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\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC721BridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC721BridgeInitiated\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC721\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC721To\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeBridgeERC721\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bridgeERC721(address,address,uint256,uint32,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.\",\"_localToken\":\"Address of the ERC721 on this domain.\",\"_minGasLimit\":\"Minimum gas limit for the bridge message on the other domain.\",\"_remoteToken\":\"Address of the ERC721 on the remote domain.\",\"_tokenId\":\"Token ID to bridge.\"}},\"bridgeERC721To(address,address,address,uint256,uint32,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.\",\"_localToken\":\"Address of the ERC721 on this domain.\",\"_minGasLimit\":\"Minimum gas limit for the bridge message on the other domain.\",\"_remoteToken\":\"Address of the ERC721 on the remote domain.\",\"_to\":\"Address to receive the token on the other domain.\",\"_tokenId\":\"Token ID to bridge.\"}},\"constructor\":{\"params\":{\"_messenger\":\"Address of the CrossDomainMessenger on this network.\",\"_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.\"}},\"messenger()\":{\"returns\":{\"_0\":\"Messenger contract on this domain.\"}},\"otherBridge()\":{\"returns\":{\"_0\":\"Address of the bridge on the other network.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSENGER()\":{\"notice\":\"Messenger contract on this domain. This will be removed in the future, use `messenger` instead.\"},\"OTHER_BRIDGE()\":{\"notice\":\"Address of the bridge on the other network. This will be removed in the future, use `otherBridge` instead.\"},\"bridgeERC721(address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to the caller's account on the other chain. Note that this function can only be called by EOAs. Smart contract wallets should use the `bridgeERC721To` function after ensuring that the recipient address on the remote chain exists. Also note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2.\"},\"bridgeERC721To(address,address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to some recipient's account on the other chain. Note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2.\"},\"constructor\":{\"notice\":\"Constructs the L1ERC721Bridge contract.\"},\"deposits(address,address,uint256)\":{\"notice\":\"Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token by ID was deposited for a given L2 token.\"},\"finalizeBridgeERC721(address,address,address,address,uint256,bytes)\":{\"notice\":\"Completes an ERC721 bridge from the other domain and sends the ERC721 token to the recipient on this domain.\"},\"messenger()\":{\"notice\":\"Legacy getter for messenger contract.\"},\"otherBridge()\":{\"notice\":\"Legacy getter for other bridge address.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1ERC721Bridge.sol\":\"L1ERC721Bridge\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"keccak256\":\"0xed6a749c5373af398105ce6ee3ac4763aa450ea7285d268c85d9eeca809cdb1f\",\"urls\":[\"bzz-raw://20a97f891d06f0fe91560ea1a142aaa26fdd22bed1b51606b7d48f670deeb50f\",\"dweb:/ipfs/QmTbCtZKChpaX5H2iRiTDMcSz29GSLCpTCDgJpcMR4wg8x\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"urls\":[\"bzz-raw://26fef835622b46a5ba08b3ef6b46a22e94b5f285d0f0fb66b703bd30217d2c34\",\"dweb:/ipfs/QmZ548qdwfL1qF7aXz3xh1GCdTiST81kGGuKRqVUfYmPZR\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1ERC721Bridge.sol\":{\"keccak256\":\"0x4f848e29a1d9e8616abac21da54885b1eae10fa4287eb7121ec726dff6bf38e8\",\"urls\":[\"bzz-raw://2d24ef5edee24341c7d292b9dcf15209fb1d8f3e0b948ebee1aa7f2d2af6fc4c\",\"dweb:/ipfs/QmYU3eisGWBKHHnwesSC9rc5z39fpns7jfVDD2nkaLRUuR\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L2/L2ERC721Bridge.sol\":{\"keccak256\":\"0xbea27f7fc900e4bde4e890ce7e419894e96e49a7bdca3dc7c8e7f9b420a4b4a0\",\"urls\":[\"bzz-raw://25c12f05cb8e1d9f70ad25b8e39c0df79fa43f675db8235d2ae0d2a6ac7273ae\",\"dweb:/ipfs/Qmcqh7yFcpvdBmHmYhL4iv1uiqtSetixtiPy1BsbHmwVHw\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x75408c79fd51bd6f53ab1ad1719ec09264d1e6965cd5604c8346fbee76039fc3\",\"urls\":[\"bzz-raw://100be0dc2c772b569820b3c0828fac21fb241773c586eb8e789b4ddbca89f4f8\",\"dweb:/ipfs/QmW8NrsSeu1kYkga5cdjuzQ853dZZKFY22ZaycoHwiStbw\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x62e11a169b3fa987af2427bf5117612e2770d4cca51565e6bbfe255ff7ffc4bb\",\"urls\":[\"bzz-raw://c852c8c0571bb22d9f28d577620a71de5ee60eb0c7ab8c68645da9a7295d24a0\",\"dweb:/ipfs/QmdixJ2dpsz8N8CgZz8z1MkZNVjw6ZkRM6bS7mchPYX6Yi\"],\"license\":\"MIT\"},\"src/universal/ERC721Bridge.sol\":{\"keccak256\":\"0x17b0f1bebb710c78486d0eb0bd55f9cf90cdad1bc70a312ef3e8091075a6e05e\",\"urls\":[\"bzz-raw://75880ae5f873337a973b6f53fa342d9ef1dcac14066d2bb76116a9e11679be9c\",\"dweb:/ipfs/QmX52UPmYmFNQG1tmE8U4CNSf3RQ2ge63SFjqgkGcpGjgq\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC721.sol\":{\"keccak256\":\"0xb3a65b067e67a9e1fa0493401c8d247970377c6725eba4e7b02ce8099c4f4f52\",\"urls\":[\"bzz-raw://86bb6864027560ade2f4ced6a6e34213cbff8002977dc365377e5a0b473cf17b\",\"dweb:/ipfs/QmQvjtodTK27as1g1PzsYk9NyJJ3X6a6251o1vrBwx7DPT\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 1, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 94153, + "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", + "label": "__gap", + "offset": 0, + "slot": "0", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 74908, + "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", + "label": "deposits", + "offset": 0, + "slot": "49", + "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568", + "base": "t_uint256" + }, + "t_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" + } + } + }, + "transactionHash": "0x938ee02118b5e5bdb99ab74085ca0d4d7bf127e2ce602b877cd70fba724ffefb", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "MESSENGER()": { + "notice": "Messenger contract on this domain. This will be removed in the future, use `messenger` instead." + }, + "OTHER_BRIDGE()": { + "notice": "Address of the bridge on the other network. This will be removed in the future, use `otherBridge` instead." + }, + "bridgeERC721(address,address,uint256,uint32,bytes)": { + "notice": "Initiates a bridge of an NFT to the caller's account on the other chain. Note that this function can only be called by EOAs. Smart contract wallets should use the `bridgeERC721To` function after ensuring that the recipient address on the remote chain exists. Also note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2." + }, + "bridgeERC721To(address,address,address,uint256,uint32,bytes)": { + "notice": "Initiates a bridge of an NFT to some recipient's account on the other chain. Note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2." + }, + "constructor": { + "notice": "Constructs the L1ERC721Bridge contract." + }, + "deposits(address,address,uint256)": { + "notice": "Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token by ID was deposited for a given L2 token." + }, + "finalizeBridgeERC721(address,address,address,address,uint256,bytes)": { + "notice": "Completes an ERC721 bridge from the other domain and sends the ERC721 token to the recipient on this domain." + }, + "messenger()": { + "notice": "Legacy getter for messenger contract." + }, + "otherBridge()": { + "notice": "Legacy getter for other bridge address." + }, + "version()": { + "notice": "Semantic version." + } + }, + "events": { + "ERC721BridgeFinalized(address,address,address,address,uint256,bytes)": { + "notice": "Emitted when an ERC721 bridge from the other network is finalized." + }, + "ERC721BridgeInitiated(address,address,address,address,uint256,bytes)": { + "notice": "Emitted when an ERC721 bridge to the other network is initiated." + } + }, + "notice": "The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract acts as an escrow for ERC721 tokens deposited into L2." + } +} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/ProtocolVersionsProxy.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1ERC721BridgeProxy.json similarity index 78% rename from packages/contracts-bedrock/deployments/goerli/ProtocolVersionsProxy.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1ERC721BridgeProxy.json index f5624f846eb1..2a46a46c641a 100644 --- a/packages/contracts-bedrock/deployments/goerli/ProtocolVersionsProxy.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1ERC721BridgeProxy.json @@ -128,9 +128,9 @@ "type": "receive" } ], - "address": "0x0C24F5098774aA366827D667494e9F889f7cFc08", + "address": "0x0A704BFf69d6c73c8bCd385209A621380258a650", "args": [ - "0x0a08E04c73f22C65D6dBFF20f87171240df6E519" + "0x1814DBa2CC02DC44408ec2E05a680bC3dD24Cf4B" ], "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", @@ -185,44 +185,44 @@ }, "title": "Proxy" }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xcbdb44713cb15af4c542ef51f2be9e32da0bb4ffc72a03953b38870955023fc3\",\"urls\":[\"bzz-raw://0d7663f5fac06c6344f68aa531d7e9a4e0ba9d2d3a6a3ad8d5bbec4b9b9ca202\",\"dweb:/ipfs/QmbMAZcVwf7syjhKyj3LjwsNMVZiQUPaV5D1zEr4r57v6H\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xc56de5e39cd44eaeb93f0f8705dd07f4a89f66d5c186522532cf899a104cdbca\",\"urls\":[\"bzz-raw://cd1b595148fa62a798343a23e3330e79fef7d747f039d664482044be9ec0ccf3\",\"dweb:/ipfs/QmeAft6H9wbc9zZZ3prtRaBGGzcPy9yExKAhZHjp1iZ8UF\"],\"license\":\"MIT\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", "numDeployments": 1, "receipt": { - "transactionHash": "0x697aec3f4cd721a0094428e0f01051d8c355e66e3a81ad4b037f1cd4e888317b", - "transactionIndex": "0x3", - "blockHash": "0x7b58250d6876d9f305908605607e2c4ef8866244d7c2a6d59fabb927f7aa92de", - "blockNumber": "0x948895", - "from": "0x0a08E04c73f22C65D6dBFF20f87171240df6E519", + "transactionHash": "0x7fa3250bf208387c1f70c55f1e845f66f97dac43daafe33826c9c89e9bd30b27", + "transactionIndex": "0x12", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "from": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", "to": null, - "cumulativeGasUsed": "0xfee48", + "cumulativeGasUsed": "0x8097d3", "gasUsed": "0x80250", - "contractAddress": "0x0C24F5098774aA366827D667494e9F889f7cFc08", + "contractAddress": "0x0A704BFf69d6c73c8bCd385209A621380258a650", "logs": [ { - "address": "0x0C24F5098774aA366827D667494e9F889f7cFc08", + "address": "0x0A704BFf69d6c73c8bCd385209A621380258a650", "topics": [ "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a08e04c73f22c65d6dbff20f87171240df6e519", - "blockHash": "0x7b58250d6876d9f305908605607e2c4ef8866244d7c2a6d59fabb927f7aa92de", - "blockNumber": "0x948895", - "transactionHash": "0x697aec3f4cd721a0094428e0f01051d8c355e66e3a81ad4b037f1cd4e888317b", - "transactionIndex": "0x3", - "logIndex": "0x5", + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001814dba2cc02dc44408ec2e05a680bc3dd24cf4b", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0x7fa3250bf208387c1f70c55f1e845f66f97dac43daafe33826c9c89e9bd30b27", + "transactionIndex": "0x12", + "logIndex": "0x21", "removed": false } ], "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000008000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000002000000000000000000000040000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "type": "0x2", - "effectiveGasPrice": "0xb2d05e0c" + "effectiveGasPrice": "0xb2d05e0a" }, "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [], "types": {} }, - "transactionHash": "0x697aec3f4cd721a0094428e0f01051d8c355e66e3a81ad4b037f1cd4e888317b", + "transactionHash": "0x7fa3250bf208387c1f70c55f1e845f66f97dac43daafe33826c9c89e9bd30b27", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1StandardBridge.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1StandardBridge.json new file mode 100644 index 000000000000..2d3b5c44726e --- /dev/null +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1StandardBridge.json @@ -0,0 +1,1076 @@ +{ + "abi": [ + { + "inputs": [ + { + "internalType": "address payable", + "name": "_messenger", + "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": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ERC20BridgeFinalized", + "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": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ERC20BridgeInitiated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ERC20DepositInitiated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ERC20WithdrawalFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ETHBridgeFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ETHBridgeInitiated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ETHDepositInitiated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ETHWithdrawalFinalized", + "type": "event" + }, + { + "inputs": [], + "name": "MESSENGER", + "outputs": [ + { + "internalType": "contract CrossDomainMessenger", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "OTHER_BRIDGE", + "outputs": [ + { + "internalType": "contract StandardBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_localToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_remoteToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "bridgeERC20", + "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": "_amount", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "bridgeERC20To", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "bridgeETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "bridgeETHTo", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2Token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "depositERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "depositERC20To", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "depositETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "depositETHTo", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "deposits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "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": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "finalizeBridgeERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "finalizeBridgeETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "finalizeERC20Withdrawal", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "finalizeETHWithdrawal", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "l2TokenBridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "messenger", + "outputs": [ + { + "internalType": "contract CrossDomainMessenger", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "otherBridge", + "outputs": [ + { + "internalType": "contract StandardBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "address": "0xf8c8da6f7f78B78414fB8b0ddc0389B578B51037", + "args": [ + "0x534571C20b87500CC86ae505da23eD357C6aFc2D" + ], + "bytecode": "0x60c06040523480156200001157600080fd5b506040516200296b3803806200296b83398101604081905262000034916200005e565b6001600160a01b031660805273420000000000000000000000000000000000001060a05262000090565b6000602082840312156200007157600080fd5b81516001600160a01b03811681146200008957600080fd5b9392505050565b60805160a05161285a6200011160003960008181610360015281816104170152818161051d015281816109fe0152818161130201526119b401526000818161026e0152818161044d015281816104f301528181610554015281816109d401528181610a3501528181610cc2015281816112c50152611978015261285a6000f3fe6080604052600436106101485760003560e01c8063838b2520116100c05780639a2ac6d511610074578063b1a1a88211610059578063b1a1a882146104a2578063c89701a214610408578063e11013dd146104b557600080fd5b80639a2ac6d51461046f578063a9f9e6751461048257600080fd5b80638f601f66116100a55780638f601f66146103c257806391c49bf814610408578063927ede2d1461043b57600080fd5b8063838b25201461038257806387087623146103a257600080fd5b80633cb747bf1161011757806354fd4d50116100fc57806354fd4d50146102d857806358a997f61461032e5780637f46ddb21461034e57600080fd5b80633cb747bf1461025f578063540abf73146102b857600080fd5b80630166a07a1461020657806309fc8843146102265780631532ec34146102395780631635f5fd1461024c57600080fd5b3661020157333b156101e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101ff333362030d40604051806020016040528060008152506104c8565b005b600080fd5b34801561021257600080fd5b506101ff6102213660046122be565b6104db565b6101ff61023436600461236f565b6108d1565b6101ff6102473660046123c2565b6109a8565b6101ff61025a3660046123c2565b6109bc565b34801561026b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102c457600080fd5b506101ff6102d3366004612435565b610e91565b3480156102e457600080fd5b506103216040518060400160405280600581526020017f312e352e3000000000000000000000000000000000000000000000000000000081525081565b6040516102af9190612522565b34801561033a57600080fd5b506101ff610349366004612535565b610ed6565b34801561035a57600080fd5b5061028e7f000000000000000000000000000000000000000000000000000000000000000081565b34801561038e57600080fd5b506101ff61039d366004612435565b610faa565b3480156103ae57600080fd5b506101ff6103bd366004612535565b610fef565b3480156103ce57600080fd5b506103fa6103dd3660046125b8565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102af565b34801561041457600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061028e565b34801561044757600080fd5b5061028e7f000000000000000000000000000000000000000000000000000000000000000081565b6101ff61047d3660046125f1565b6110c3565b34801561048e57600080fd5b506101ff61049d3660046122be565b611105565b6101ff6104b036600461236f565b611114565b6101ff6104c33660046125f1565b6111e5565b6104d58484348585611228565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156105f957507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e19190612654565b73ffffffffffffffffffffffffffffffffffffffff16145b6106ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101d8565b6106b48761140c565b15610802576106c3878761146e565b610775576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101d8565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156107e557600080fd5b505af11580156107f9573d6000803e3d6000fd5b50505050610884565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a16835292905220546108409084906126a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c168352939052919091209190915561088490858561158e565b6108c8878787878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061166292505050565b50505050505050565b333b15610960576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101d8565b6109a33333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061122892505050565b505050565b6109b585858585856109bc565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015610ada57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac29190612654565b73ffffffffffffffffffffffffffffffffffffffff16145b610b8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101d8565b823414610c1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101d8565b3073ffffffffffffffffffffffffffffffffffffffff851603610cc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101d8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610d9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101d8565b610ddd85858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506116f092505050565b6000610dfa855a8660405180602001604052806000815250611763565b905080610e89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101d8565b505050505050565b6108c887873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061177d92505050565b333b15610f65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101d8565b610e8986863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ac492505050565b6108c887873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ac492505050565b333b1561107e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101d8565b610e8986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061177d92505050565b6104d533858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104c892505050565b6108c8878787878787876104db565b333b156111a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101d8565b6109a333338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104c892505050565b6104d53385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061122892505050565b8234146112b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101d8565b6112c385858584611ad3565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b847f0000000000000000000000000000000000000000000000000000000000000000631635f5fd60e01b8989898860405160240161134094939291906126b7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526113d392918890600401612700565b6000604051808303818588803b1580156113ec57600080fd5b505af1158015611400573d6000803e3d6000fd5b50505050505050505050565b6000611438827f1d1d8b6300000000000000000000000000000000000000000000000000000000611b46565b806114685750611468827fec4fc8e300000000000000000000000000000000000000000000000000000000611b46565b92915050565b600061149a837f1d1d8b6300000000000000000000000000000000000000000000000000000000611b46565b15611543578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150e9190612654565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611468565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ea573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109a39084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611b69565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b38686866040516116da93929190612745565b60405180910390a4610e89868686868686611c75565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e631848460405161174f929190612783565b60405180910390a36104d584848484611cfd565b600080600080845160208601878a8af19695505050505050565b6117868761140c565b156118d457611795878761146e565b611847576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101d8565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b1580156118b757600080fd5b505af11580156118cb573d6000803e3d6000fd5b50505050611968565b6118f673ffffffffffffffffffffffffffffffffffffffff8816863086611d6a565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461193490849061279c565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611976878787878786611dc8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b7f0000000000000000000000000000000000000000000000000000000000000000630166a07a60e01b898b8a8a8a896040516024016119f6969594939291906127b4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611a8992918790600401612700565b600060405180830381600087803b158015611aa357600080fd5b505af1158015611ab7573d6000803e3d6000fd5b5050505050505050505050565b6108c88787878787878761177d565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611b32929190612783565b60405180910390a36104d584848484611e56565b6000611b5183611eb5565b8015611b625750611b628383611f19565b9392505050565b6000611bcb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611fe89092919063ffffffff16565b8051909150156109a35780806020019051810190611be9919061280f565b6109a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101d8565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd868686604051611ced93929190612745565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051611d5c929190612783565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526104d59085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016115e0565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d0396868686604051611e4093929190612745565b60405180910390a4610e89868686868686611fff565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051611d5c929190612783565b6000611ee1827f01ffc9a700000000000000000000000000000000000000000000000000000000611f19565b80156114685750611f12827fffffffff00000000000000000000000000000000000000000000000000000000611f19565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015611fd1575060208210155b8015611fdd5750600081115b979650505050505050565b6060611ff78484600085612077565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf868686604051611ced93929190612745565b606082471015612109576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101d8565b73ffffffffffffffffffffffffffffffffffffffff85163b612187576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101d8565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516121b09190612831565b60006040518083038185875af1925050503d80600081146121ed576040519150601f19603f3d011682016040523d82523d6000602084013e6121f2565b606091505b5091509150611fdd8282866060831561220c575081611b62565b82511561221c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101d89190612522565b73ffffffffffffffffffffffffffffffffffffffff8116811461227257600080fd5b50565b60008083601f84011261228757600080fd5b50813567ffffffffffffffff81111561229f57600080fd5b6020830191508360208285010111156122b757600080fd5b9250929050565b600080600080600080600060c0888a0312156122d957600080fd5b87356122e481612250565b965060208801356122f481612250565b9550604088013561230481612250565b9450606088013561231481612250565b93506080880135925060a088013567ffffffffffffffff81111561233757600080fd5b6123438a828b01612275565b989b979a50959850939692959293505050565b803563ffffffff8116811461236a57600080fd5b919050565b60008060006040848603121561238457600080fd5b61238d84612356565b9250602084013567ffffffffffffffff8111156123a957600080fd5b6123b586828701612275565b9497909650939450505050565b6000806000806000608086880312156123da57600080fd5b85356123e581612250565b945060208601356123f581612250565b935060408601359250606086013567ffffffffffffffff81111561241857600080fd5b61242488828901612275565b969995985093965092949392505050565b600080600080600080600060c0888a03121561245057600080fd5b873561245b81612250565b9650602088013561246b81612250565b9550604088013561247b81612250565b94506060880135935061249060808901612356565b925060a088013567ffffffffffffffff81111561233757600080fd5b60005b838110156124c75781810151838201526020016124af565b838111156104d55750506000910152565b600081518084526124f08160208601602086016124ac565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611b6260208301846124d8565b60008060008060008060a0878903121561254e57600080fd5b863561255981612250565b9550602087013561256981612250565b94506040870135935061257e60608801612356565b9250608087013567ffffffffffffffff81111561259a57600080fd5b6125a689828a01612275565b979a9699509497509295939492505050565b600080604083850312156125cb57600080fd5b82356125d681612250565b915060208301356125e681612250565b809150509250929050565b6000806000806060858703121561260757600080fd5b843561261281612250565b935061262060208601612356565b9250604085013567ffffffffffffffff81111561263c57600080fd5b61264887828801612275565b95989497509550505050565b60006020828403121561266657600080fd5b8151611b6281612250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156126b2576126b2612671565b500390565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526126f660808301846124d8565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061272f60608301856124d8565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061277a60608301846124d8565b95945050505050565b828152604060208201526000611ff760408301846124d8565b600082198211156127af576127af612671565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a083015261280360c08301846124d8565b98975050505050505050565b60006020828403121561282157600080fd5b81518015158114611b6257600080fd5b600082516128438184602087016124ac565b919091019291505056fea164736f6c634300080f000a", + "deployedBytecode": "0x6080604052600436106101485760003560e01c8063838b2520116100c05780639a2ac6d511610074578063b1a1a88211610059578063b1a1a882146104a2578063c89701a214610408578063e11013dd146104b557600080fd5b80639a2ac6d51461046f578063a9f9e6751461048257600080fd5b80638f601f66116100a55780638f601f66146103c257806391c49bf814610408578063927ede2d1461043b57600080fd5b8063838b25201461038257806387087623146103a257600080fd5b80633cb747bf1161011757806354fd4d50116100fc57806354fd4d50146102d857806358a997f61461032e5780637f46ddb21461034e57600080fd5b80633cb747bf1461025f578063540abf73146102b857600080fd5b80630166a07a1461020657806309fc8843146102265780631532ec34146102395780631635f5fd1461024c57600080fd5b3661020157333b156101e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101ff333362030d40604051806020016040528060008152506104c8565b005b600080fd5b34801561021257600080fd5b506101ff6102213660046122be565b6104db565b6101ff61023436600461236f565b6108d1565b6101ff6102473660046123c2565b6109a8565b6101ff61025a3660046123c2565b6109bc565b34801561026b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102c457600080fd5b506101ff6102d3366004612435565b610e91565b3480156102e457600080fd5b506103216040518060400160405280600581526020017f312e352e3000000000000000000000000000000000000000000000000000000081525081565b6040516102af9190612522565b34801561033a57600080fd5b506101ff610349366004612535565b610ed6565b34801561035a57600080fd5b5061028e7f000000000000000000000000000000000000000000000000000000000000000081565b34801561038e57600080fd5b506101ff61039d366004612435565b610faa565b3480156103ae57600080fd5b506101ff6103bd366004612535565b610fef565b3480156103ce57600080fd5b506103fa6103dd3660046125b8565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102af565b34801561041457600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061028e565b34801561044757600080fd5b5061028e7f000000000000000000000000000000000000000000000000000000000000000081565b6101ff61047d3660046125f1565b6110c3565b34801561048e57600080fd5b506101ff61049d3660046122be565b611105565b6101ff6104b036600461236f565b611114565b6101ff6104c33660046125f1565b6111e5565b6104d58484348585611228565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156105f957507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e19190612654565b73ffffffffffffffffffffffffffffffffffffffff16145b6106ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101d8565b6106b48761140c565b15610802576106c3878761146e565b610775576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101d8565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156107e557600080fd5b505af11580156107f9573d6000803e3d6000fd5b50505050610884565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a16835292905220546108409084906126a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c168352939052919091209190915561088490858561158e565b6108c8878787878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061166292505050565b50505050505050565b333b15610960576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101d8565b6109a33333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061122892505050565b505050565b6109b585858585856109bc565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015610ada57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac29190612654565b73ffffffffffffffffffffffffffffffffffffffff16145b610b8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101d8565b823414610c1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101d8565b3073ffffffffffffffffffffffffffffffffffffffff851603610cc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101d8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610d9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101d8565b610ddd85858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506116f092505050565b6000610dfa855a8660405180602001604052806000815250611763565b905080610e89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101d8565b505050505050565b6108c887873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061177d92505050565b333b15610f65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101d8565b610e8986863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ac492505050565b6108c887873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ac492505050565b333b1561107e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101d8565b610e8986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061177d92505050565b6104d533858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104c892505050565b6108c8878787878787876104db565b333b156111a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101d8565b6109a333338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104c892505050565b6104d53385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061122892505050565b8234146112b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101d8565b6112c385858584611ad3565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b847f0000000000000000000000000000000000000000000000000000000000000000631635f5fd60e01b8989898860405160240161134094939291906126b7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526113d392918890600401612700565b6000604051808303818588803b1580156113ec57600080fd5b505af1158015611400573d6000803e3d6000fd5b50505050505050505050565b6000611438827f1d1d8b6300000000000000000000000000000000000000000000000000000000611b46565b806114685750611468827fec4fc8e300000000000000000000000000000000000000000000000000000000611b46565b92915050565b600061149a837f1d1d8b6300000000000000000000000000000000000000000000000000000000611b46565b15611543578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150e9190612654565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611468565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114ea573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109a39084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611b69565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b38686866040516116da93929190612745565b60405180910390a4610e89868686868686611c75565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e631848460405161174f929190612783565b60405180910390a36104d584848484611cfd565b600080600080845160208601878a8af19695505050505050565b6117868761140c565b156118d457611795878761146e565b611847576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101d8565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b1580156118b757600080fd5b505af11580156118cb573d6000803e3d6000fd5b50505050611968565b6118f673ffffffffffffffffffffffffffffffffffffffff8816863086611d6a565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461193490849061279c565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611976878787878786611dc8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b7f0000000000000000000000000000000000000000000000000000000000000000630166a07a60e01b898b8a8a8a896040516024016119f6969594939291906127b4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611a8992918790600401612700565b600060405180830381600087803b158015611aa357600080fd5b505af1158015611ab7573d6000803e3d6000fd5b5050505050505050505050565b6108c88787878787878761177d565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611b32929190612783565b60405180910390a36104d584848484611e56565b6000611b5183611eb5565b8015611b625750611b628383611f19565b9392505050565b6000611bcb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611fe89092919063ffffffff16565b8051909150156109a35780806020019051810190611be9919061280f565b6109a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101d8565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd868686604051611ced93929190612745565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051611d5c929190612783565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526104d59085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016115e0565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d0396868686604051611e4093929190612745565b60405180910390a4610e89868686868686611fff565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051611d5c929190612783565b6000611ee1827f01ffc9a700000000000000000000000000000000000000000000000000000000611f19565b80156114685750611f12827fffffffff00000000000000000000000000000000000000000000000000000000611f19565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015611fd1575060208210155b8015611fdd5750600081115b979650505050505050565b6060611ff78484600085612077565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf868686604051611ced93929190612745565b606082471015612109576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101d8565b73ffffffffffffffffffffffffffffffffffffffff85163b612187576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101d8565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516121b09190612831565b60006040518083038185875af1925050503d80600081146121ed576040519150601f19603f3d011682016040523d82523d6000602084013e6121f2565b606091505b5091509150611fdd8282866060831561220c575081611b62565b82511561221c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101d89190612522565b73ffffffffffffffffffffffffffffffffffffffff8116811461227257600080fd5b50565b60008083601f84011261228757600080fd5b50813567ffffffffffffffff81111561229f57600080fd5b6020830191508360208285010111156122b757600080fd5b9250929050565b600080600080600080600060c0888a0312156122d957600080fd5b87356122e481612250565b965060208801356122f481612250565b9550604088013561230481612250565b9450606088013561231481612250565b93506080880135925060a088013567ffffffffffffffff81111561233757600080fd5b6123438a828b01612275565b989b979a50959850939692959293505050565b803563ffffffff8116811461236a57600080fd5b919050565b60008060006040848603121561238457600080fd5b61238d84612356565b9250602084013567ffffffffffffffff8111156123a957600080fd5b6123b586828701612275565b9497909650939450505050565b6000806000806000608086880312156123da57600080fd5b85356123e581612250565b945060208601356123f581612250565b935060408601359250606086013567ffffffffffffffff81111561241857600080fd5b61242488828901612275565b969995985093965092949392505050565b600080600080600080600060c0888a03121561245057600080fd5b873561245b81612250565b9650602088013561246b81612250565b9550604088013561247b81612250565b94506060880135935061249060808901612356565b925060a088013567ffffffffffffffff81111561233757600080fd5b60005b838110156124c75781810151838201526020016124af565b838111156104d55750506000910152565b600081518084526124f08160208601602086016124ac565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611b6260208301846124d8565b60008060008060008060a0878903121561254e57600080fd5b863561255981612250565b9550602087013561256981612250565b94506040870135935061257e60608801612356565b9250608087013567ffffffffffffffff81111561259a57600080fd5b6125a689828a01612275565b979a9699509497509295939492505050565b600080604083850312156125cb57600080fd5b82356125d681612250565b915060208301356125e681612250565b809150509250929050565b6000806000806060858703121561260757600080fd5b843561261281612250565b935061262060208601612356565b9250604085013567ffffffffffffffff81111561263c57600080fd5b61264887828801612275565b95989497509550505050565b60006020828403121561266657600080fd5b8151611b6281612250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156126b2576126b2612671565b500390565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526126f660808301846124d8565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061272f60608301856124d8565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061277a60608301846124d8565b95945050505050565b828152604060208201526000611ff760408301846124d8565b600082198211156127af576127af612671565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a083015261280360c08301846124d8565b98975050505050505050565b60006020828403121561282157600080fd5b81518015158114611b6257600080fd5b600082516128438184602087016124ac565b919091019291505056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "bridgeERC20(address,address,uint256,uint32,bytes)": { + "params": { + "_amount": "Amount of local tokens to deposit.", + "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", + "_localToken": "Address of the ERC20 on this chain.", + "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", + "_remoteToken": "Address of the corresponding token on the remote chain." + } + }, + "bridgeERC20To(address,address,address,uint256,uint32,bytes)": { + "params": { + "_amount": "Amount of local tokens to deposit.", + "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", + "_localToken": "Address of the ERC20 on this chain.", + "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", + "_remoteToken": "Address of the corresponding token on the remote chain.", + "_to": "Address of the receiver." + } + }, + "bridgeETH(uint32,bytes)": { + "params": { + "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", + "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with." + } + }, + "bridgeETHTo(address,uint32,bytes)": { + "params": { + "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", + "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", + "_to": "Address of the receiver." + } + }, + "constructor": { + "params": { + "_messenger": "Address of the L1CrossDomainMessenger." + } + }, + "depositERC20(address,address,uint256,uint32,bytes)": { + "params": { + "_amount": "Amount of the ERC20 to deposit.", + "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", + "_l1Token": "Address of the L1 token being deposited.", + "_l2Token": "Address of the corresponding token on L2.", + "_minGasLimit": "Minimum gas limit for the deposit message on L2." + } + }, + "depositERC20To(address,address,address,uint256,uint32,bytes)": { + "params": { + "_amount": "Amount of the ERC20 to deposit.", + "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", + "_l1Token": "Address of the L1 token being deposited.", + "_l2Token": "Address of the corresponding token on L2.", + "_minGasLimit": "Minimum gas limit for the deposit message on L2.", + "_to": "Address of the recipient on L2." + } + }, + "depositETH(uint32,bytes)": { + "params": { + "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", + "_minGasLimit": "Minimum gas limit for the deposit message on L2." + } + }, + "depositETHTo(address,uint32,bytes)": { + "params": { + "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", + "_minGasLimit": "Minimum gas limit for the deposit message on L2.", + "_to": "Address of the recipient on L2." + } + }, + "finalizeBridgeERC20(address,address,address,address,uint256,bytes)": { + "params": { + "_amount": "Amount of the ERC20 being bridged.", + "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", + "_from": "Address of the sender.", + "_localToken": "Address of the ERC20 on this chain.", + "_remoteToken": "Address of the corresponding token on the remote chain.", + "_to": "Address of the receiver." + } + }, + "finalizeBridgeETH(address,address,uint256,bytes)": { + "params": { + "_amount": "Amount of ETH being bridged.", + "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", + "_from": "Address of the sender.", + "_to": "Address of the receiver." + } + }, + "finalizeERC20Withdrawal(address,address,address,address,uint256,bytes)": { + "params": { + "_amount": "Amount of the ERC20 to withdraw.", + "_extraData": "Optional data forwarded from L2.", + "_from": "Address of the withdrawer on L2.", + "_l1Token": "Address of the token on L1.", + "_l2Token": "Address of the corresponding token on L2.", + "_to": "Address of the recipient on L1." + } + }, + "finalizeETHWithdrawal(address,address,uint256,bytes)": { + "params": { + "_amount": "Amount of ETH to withdraw.", + "_extraData": "Optional data forwarded from L2.", + "_from": "Address of the withdrawer on L2.", + "_to": "Address of the recipient on L1." + } + }, + "l2TokenBridge()": { + "returns": { + "_0": "Address of the corresponding L2 bridge contract." + } + }, + "messenger()": { + "returns": { + "_0": "Messenger contract on this domain." + } + }, + "otherBridge()": { + "returns": { + "_0": "The bridge contract on the other network." + } + } + }, + "events": { + "ERC20DepositInitiated(address,address,address,address,uint256,bytes)": { + "params": { + "amount": "Amount of the ERC20 deposited.", + "extraData": "Extra data attached to the deposit.", + "from": "Address of the depositor.", + "l1Token": "Address of the token on L1.", + "l2Token": "Address of the corresponding token on L2.", + "to": "Address of the recipient on L2." + } + }, + "ERC20WithdrawalFinalized(address,address,address,address,uint256,bytes)": { + "params": { + "amount": "Amount of the ERC20 withdrawn.", + "extraData": "Extra data attached to the withdrawal.", + "from": "Address of the withdrawer.", + "l1Token": "Address of the token on L1.", + "l2Token": "Address of the corresponding token on L2.", + "to": "Address of the recipient on L1." + } + }, + "ETHDepositInitiated(address,address,uint256,bytes)": { + "params": { + "amount": "Amount of ETH deposited.", + "extraData": "Extra data attached to the deposit.", + "from": "Address of the depositor.", + "to": "Address of the recipient on L2." + } + }, + "ETHWithdrawalFinalized(address,address,uint256,bytes)": { + "params": { + "amount": "Amount of ETH withdrawn.", + "extraData": "Extra data attached to the withdrawal.", + "from": "Address of the withdrawer.", + "to": "Address of the recipient on L1." + } + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_messenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20BridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20BridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20DepositInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20WithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHBridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHBridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHDepositInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHWithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"contract StandardBridge\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC20To\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"bridgeETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"bridgeETHTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"depositERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"depositERC20To\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositETHTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeBridgeERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"finalizeBridgeETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeERC20Withdrawal\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"finalizeETHWithdrawal\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2TokenBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"contract StandardBridge\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bridgeERC20(address,address,uint256,uint32,bytes)\":{\"params\":{\"_amount\":\"Amount of local tokens to deposit.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\"}},\"bridgeERC20To(address,address,address,uint256,uint32,bytes)\":{\"params\":{\"_amount\":\"Amount of local tokens to deposit.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\",\"_to\":\"Address of the receiver.\"}},\"bridgeETH(uint32,bytes)\":{\"params\":{\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\"}},\"bridgeETHTo(address,uint32,bytes)\":{\"params\":{\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_to\":\"Address of the receiver.\"}},\"constructor\":{\"params\":{\"_messenger\":\"Address of the L1CrossDomainMessenger.\"}},\"depositERC20(address,address,uint256,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ERC20 tokens into the sender's account on L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to deposit.\",\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_l1Token\":\"Address of the L1 token being deposited.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\"}},\"depositERC20To(address,address,address,uint256,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ERC20 tokens into a target account on L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to deposit.\",\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_l1Token\":\"Address of the L1 token being deposited.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\",\"_to\":\"Address of the recipient on L2.\"}},\"depositETH(uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ETH into the sender's account on L2.\",\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\"}},\"depositETHTo(address,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ETH into a target account on L2. Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will be locked in the L2StandardBridge. ETH may be recoverable if the call can be successfully replayed by increasing the amount of gas supplied to the call. If the call will fail for any amount of gas, then the ETH will be locked permanently.\",\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\",\"_to\":\"Address of the recipient on L2.\"}},\"finalizeBridgeERC20(address,address,address,address,uint256,bytes)\":{\"params\":{\"_amount\":\"Amount of the ERC20 being bridged.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_from\":\"Address of the sender.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\",\"_to\":\"Address of the receiver.\"}},\"finalizeBridgeETH(address,address,uint256,bytes)\":{\"params\":{\"_amount\":\"Amount of ETH being bridged.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_from\":\"Address of the sender.\",\"_to\":\"Address of the receiver.\"}},\"finalizeERC20Withdrawal(address,address,address,address,uint256,bytes)\":{\"custom:legacy\":\"@notice Finalizes a withdrawal of ERC20 tokens from L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to withdraw.\",\"_extraData\":\"Optional data forwarded from L2.\",\"_from\":\"Address of the withdrawer on L2.\",\"_l1Token\":\"Address of the token on L1.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_to\":\"Address of the recipient on L1.\"}},\"finalizeETHWithdrawal(address,address,uint256,bytes)\":{\"custom:legacy\":\"@notice Finalizes a withdrawal of ETH from L2.\",\"params\":{\"_amount\":\"Amount of ETH to withdraw.\",\"_extraData\":\"Optional data forwarded from L2.\",\"_from\":\"Address of the withdrawer on L2.\",\"_to\":\"Address of the recipient on L1.\"}},\"l2TokenBridge()\":{\"custom:legacy\":\"@notice Retrieves the access of the corresponding L2 bridge contract.\",\"returns\":{\"_0\":\"Address of the corresponding L2 bridge contract.\"}},\"messenger()\":{\"returns\":{\"_0\":\"Messenger contract on this domain.\"}},\"otherBridge()\":{\"returns\":{\"_0\":\"The bridge contract on the other network.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSENGER()\":{\"notice\":\"Messenger contract on this domain.\"},\"OTHER_BRIDGE()\":{\"notice\":\"Corresponding bridge on the other domain.\"},\"bridgeERC20(address,address,uint256,uint32,bytes)\":{\"notice\":\"Sends ERC20 tokens to the sender's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain.\"},\"bridgeERC20To(address,address,address,uint256,uint32,bytes)\":{\"notice\":\"Sends ERC20 tokens to a receiver's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain.\"},\"bridgeETH(uint32,bytes)\":{\"notice\":\"Sends ETH to the sender's address on the other chain.\"},\"bridgeETHTo(address,uint32,bytes)\":{\"notice\":\"Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a smart contract and the call fails, the ETH will be temporarily locked in the StandardBridge on the other chain until the call is replayed. If the call cannot be replayed with any amount of gas (call always reverts), then the ETH will be permanently locked in the StandardBridge on the other chain. ETH will also be locked if the receiver is the other bridge, because finalizeBridgeETH will revert in that case.\"},\"constructor\":{\"notice\":\"Constructs the L1StandardBridge contract.\"},\"deposits(address,address)\":{\"notice\":\"Mapping that stores deposits for a given pair of local and remote tokens.\"},\"finalizeBridgeERC20(address,address,address,address,uint256,bytes)\":{\"notice\":\"Finalizes an ERC20 bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain.\"},\"finalizeBridgeETH(address,address,uint256,bytes)\":{\"notice\":\"Finalizes an ETH bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain.\"},\"messenger()\":{\"notice\":\"Getter for messenger contract.\"},\"otherBridge()\":{\"notice\":\"Getter for the other bridge.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1StandardBridge.sol\":\"L1StandardBridge\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"urls\":[\"bzz-raw://b2717fd2bdac99daa960a6de500754ea1b932093c946388c381da48658234b95\",\"dweb:/ipfs/QmP6QVMn6UeA3ByahyJbYQr5M6coHKBKsf3ySZSfbyA8R7\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x032807210d1d7d218963d7355d62e021a84bf1b3339f4f50be2f63b53cccaf29\",\"urls\":[\"bzz-raw://11756f42121f6541a35a8339ea899ee7514cfaa2e6d740625fcc844419296aa6\",\"dweb:/ipfs/QmekMuk6BY4DAjzeXr4MSbKdgoqqsZnA8JPtuyWc6CwXHf\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1StandardBridge.sol\":{\"keccak256\":\"0x2816b3b16075346f3eb6855d88e6569f198d0d992db07b16f8b9cb324973abff\",\"urls\":[\"bzz-raw://d072bd091adb5dd2d7e640f8c9d2e2c0103e4f2c555f5654ea230dd816907fa5\",\"dweb:/ipfs/QmbwYRt1FkgYNEphKJcedCPRaPsFbRmgrYAchd5DDu3UWY\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x75408c79fd51bd6f53ab1ad1719ec09264d1e6965cd5604c8346fbee76039fc3\",\"urls\":[\"bzz-raw://100be0dc2c772b569820b3c0828fac21fb241773c586eb8e789b4ddbca89f4f8\",\"dweb:/ipfs/QmW8NrsSeu1kYkga5cdjuzQ853dZZKFY22ZaycoHwiStbw\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x62e11a169b3fa987af2427bf5117612e2770d4cca51565e6bbfe255ff7ffc4bb\",\"urls\":[\"bzz-raw://c852c8c0571bb22d9f28d577620a71de5ee60eb0c7ab8c68645da9a7295d24a0\",\"dweb:/ipfs/QmdixJ2dpsz8N8CgZz8z1MkZNVjw6ZkRM6bS7mchPYX6Yi\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x6f8133b39efcbcbd5088f195dfacf1bedc3146508429c3865443909af735a04c\",\"urls\":[\"bzz-raw://adc36971e2e120458769f050428d9d2b0504516660345020c2521ee46e6d8abf\",\"dweb:/ipfs/QmPbFusQkZgGKpU8Fv5JoqL4oVeJtM3yqnhRGLY9eZT5zZ\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x18721f41a831ec39d47002e73ecc2aa3e6624f8d1ab7b9f25b53348e8b0765df\",\"urls\":[\"bzz-raw://2162fa7529a77b199a07f37fca26c778542f6c8805f0365f1ceef90c5cd3a3a7\",\"dweb:/ipfs/QmaMmHJS52Bp95AGnrjh1zV7fLLqV3uAbFzkVLziMnPJYa\"],\"license\":\"MIT\"},\"src/universal/StandardBridge.sol\":{\"keccak256\":\"0xc646978d2c459360d35ac83b489aa9a42b2b8aeed8bd167c842459043bc3143f\",\"urls\":[\"bzz-raw://badcbcfa3d41a0f117145577a5750fda368b75b7fd8583f3e516bb9df342a297\",\"dweb:/ipfs/QmcmyA5kwm1vbVgYVrNtVBUYouSXok4ktL5NdtRxNaG8JE\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 1, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 96163, + "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", + "label": "spacer_0_0_20", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 96166, + "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", + "label": "spacer_1_0_20", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 96173, + "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", + "label": "deposits", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 96178, + "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", + "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", + "base": "t_uint256" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + }, + "transactionHash": "0x0793128a066476c9b3a986d79e632da13525a69829a9737aa07c22a8017c1b1a", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "MESSENGER()": { + "notice": "Messenger contract on this domain." + }, + "OTHER_BRIDGE()": { + "notice": "Corresponding bridge on the other domain." + }, + "bridgeERC20(address,address,uint256,uint32,bytes)": { + "notice": "Sends ERC20 tokens to the sender's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain." + }, + "bridgeERC20To(address,address,address,uint256,uint32,bytes)": { + "notice": "Sends ERC20 tokens to a receiver's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain." + }, + "bridgeETH(uint32,bytes)": { + "notice": "Sends ETH to the sender's address on the other chain." + }, + "bridgeETHTo(address,uint32,bytes)": { + "notice": "Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a smart contract and the call fails, the ETH will be temporarily locked in the StandardBridge on the other chain until the call is replayed. If the call cannot be replayed with any amount of gas (call always reverts), then the ETH will be permanently locked in the StandardBridge on the other chain. ETH will also be locked if the receiver is the other bridge, because finalizeBridgeETH will revert in that case." + }, + "constructor": { + "notice": "Constructs the L1StandardBridge contract." + }, + "deposits(address,address)": { + "notice": "Mapping that stores deposits for a given pair of local and remote tokens." + }, + "finalizeBridgeERC20(address,address,address,address,uint256,bytes)": { + "notice": "Finalizes an ERC20 bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain." + }, + "finalizeBridgeETH(address,address,uint256,bytes)": { + "notice": "Finalizes an ETH bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain." + }, + "messenger()": { + "notice": "Getter for messenger contract." + }, + "otherBridge()": { + "notice": "Getter for the other bridge." + }, + "version()": { + "notice": "Semantic version." + } + }, + "events": { + "ERC20BridgeFinalized(address,address,address,address,uint256,bytes)": { + "notice": "Emitted when an ERC20 bridge is finalized on this chain." + }, + "ERC20BridgeInitiated(address,address,address,address,uint256,bytes)": { + "notice": "Emitted when an ERC20 bridge is initiated to the other chain." + }, + "ETHBridgeFinalized(address,address,uint256,bytes)": { + "notice": "Emitted when an ETH bridge is finalized on this chain." + }, + "ETHBridgeInitiated(address,address,uint256,bytes)": { + "notice": "Emitted when an ETH bridge is initiated to the other chain." + } + }, + "notice": "The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and L2. In the case that an ERC20 token is native to L1, it will be escrowed within this contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was stored within this contract. After Bedrock, ETH is instead stored inside the OptimismPortal contract. NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples of some token types that may not be properly supported by this contract include, but are not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists." + } +} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/sepolia/L1StandardBridgeProxy.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1StandardBridgeProxy.json similarity index 80% rename from packages/contracts-bedrock/deployments/sepolia/L1StandardBridgeProxy.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1StandardBridgeProxy.json index a1911106523e..126996e9225e 100644 --- a/packages/contracts-bedrock/deployments/sepolia/L1StandardBridgeProxy.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L1StandardBridgeProxy.json @@ -90,9 +90,9 @@ "type": "receive" } ], - "address": "0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1", + "address": "0x8ed848d60d988B27C0B9C9F86171083302F66EFb", "args": [ - "0x189aBAAaa82DfC015A588A7dbaD6F13b1D3485Bc" + "0x1814DBa2CC02DC44408ec2E05a680bC3dD24Cf4B" ], "bytecode": "0x608060405234801561001057600080fd5b50604051610a44380380610a4483398101604081905261002f9161005d565b610057817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b5061008d565b60006020828403121561006f57600080fd5b81516001600160a01b038116811461008657600080fd5b9392505050565b6109a88061009c6000396000f3fe60806040526004361061005e5760003560e01c8063893d20e811610043578063893d20e8146100b55780639b0b0fda146100f3578063aaf10f42146101135761006d565b806313af4035146100755780636c5d4ad0146100955761006d565b3661006d5761006b610128565b005b61006b610128565b34801561008157600080fd5b5061006b6100903660046107a2565b6103cb565b3480156100a157600080fd5b5061006b6100b036600461080e565b61045c565b3480156100c157600080fd5b506100ca610611565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ff57600080fd5b5061006b61010e3660046108dd565b6106a8565b34801561011f57600080fd5b506100ca610716565b60006101527fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb7947262000000000000000000000000000000000000000000000000000000001790529051919250600091829173ffffffffffffffffffffffffffffffffffffffff8516916101d4919061093a565b600060405180830381855afa9150503d806000811461020f576040519150601f19603f3d011682016040523d82523d6000602084013e610214565b606091505b5091509150818015610227575080516020145b156102d9576000818060200190518101906102429190610946565b905080156102d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c314368756753706c61736850726f78793a2073797374656d2069732063757260448201527f72656e746c79206265696e67207570677261646564000000000000000000000060648201526084015b60405180910390fd5b505b60006103037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166103a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4c314368756753706c61736850726f78793a20696d706c656d656e746174696f60448201527f6e206973206e6f7420736574207965740000000000000000000000000000000060648201526084016102ce565b3660008037600080366000845af43d6000803e806103c5573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610424575033155b1561045457610451817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b50565b610451610128565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104b5575033155b156104545760006104e47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050803f82516020840120036104f8575050565b60405160009061052e907f600d380380600d6000396000f30000000000000000000000000000000000000090859060200161095f565b604051602081830303815290604052905060008151602083016000f084516020860120909150813f146105e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4c314368756753706c61736850726f78793a20636f646520776173206e6f742060448201527f636f72726563746c79206465706c6f796564000000000000000000000000000060648201526084016102ce565b61060b817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b50505050565b600061063b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610672575033155b1561069d57507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6106a5610128565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610701575033155b1561070a579055565b610712610128565b5050565b60006107407fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610777575033155b1561069d57507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000602082840312156107b457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146107d857600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561082057600080fd5b813567ffffffffffffffff8082111561083857600080fd5b818401915084601f83011261084c57600080fd5b81358181111561085e5761085e6107df565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108a4576108a46107df565b816040528281528760208487010111156108bd57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600080604083850312156108f057600080fd5b50508035926020909101359150565b6000815160005b818110156109205760208185018101518683015201610906565b8181111561092f576000828601525b509290920192915050565b60006107d882846108ff565b60006020828403121561095857600080fd5b5051919050565b7fffffffffffffffffffffffffff00000000000000000000000000000000000000831681526000610993600d8301846108ff565b94935050505056fea164736f6c634300080f000a", "deployedBytecode": "0x60806040526004361061005e5760003560e01c8063893d20e811610043578063893d20e8146100b55780639b0b0fda146100f3578063aaf10f42146101135761006d565b806313af4035146100755780636c5d4ad0146100955761006d565b3661006d5761006b610128565b005b61006b610128565b34801561008157600080fd5b5061006b6100903660046107a2565b6103cb565b3480156100a157600080fd5b5061006b6100b036600461080e565b61045c565b3480156100c157600080fd5b506100ca610611565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ff57600080fd5b5061006b61010e3660046108dd565b6106a8565b34801561011f57600080fd5b506100ca610716565b60006101527fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb7947262000000000000000000000000000000000000000000000000000000001790529051919250600091829173ffffffffffffffffffffffffffffffffffffffff8516916101d4919061093a565b600060405180830381855afa9150503d806000811461020f576040519150601f19603f3d011682016040523d82523d6000602084013e610214565b606091505b5091509150818015610227575080516020145b156102d9576000818060200190518101906102429190610946565b905080156102d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c314368756753706c61736850726f78793a2073797374656d2069732063757260448201527f72656e746c79206265696e67207570677261646564000000000000000000000060648201526084015b60405180910390fd5b505b60006103037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166103a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4c314368756753706c61736850726f78793a20696d706c656d656e746174696f60448201527f6e206973206e6f7420736574207965740000000000000000000000000000000060648201526084016102ce565b3660008037600080366000845af43d6000803e806103c5573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610424575033155b1561045457610451817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b50565b610451610128565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104b5575033155b156104545760006104e47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050803f82516020840120036104f8575050565b60405160009061052e907f600d380380600d6000396000f30000000000000000000000000000000000000090859060200161095f565b604051602081830303815290604052905060008151602083016000f084516020860120909150813f146105e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4c314368756753706c61736850726f78793a20636f646520776173206e6f742060448201527f636f72726563746c79206465706c6f796564000000000000000000000000000060648201526084016102ce565b61060b817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b50505050565b600061063b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610672575033155b1561069d57507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6106a5610128565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610701575033155b1561070a579055565b610712610128565b5050565b60006107407fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610777575033155b1561069d57507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000602082840312156107b457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146107d857600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561082057600080fd5b813567ffffffffffffffff8082111561083857600080fd5b818401915084601f83011261084c57600080fd5b81358181111561085e5761085e6107df565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108a4576108a46107df565b816040528281528760208487010111156108bd57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600080604083850312156108f057600080fd5b50508035926020909101359150565b6000815160005b818110156109205760208185018101518683015201610906565b8181111561092f576000828601525b509290920192915050565b60006107d882846108ff565b60006020828403121561095857600080fd5b5051919050565b7fffffffffffffffffffffffffff00000000000000000000000000000000000000831681526000610993600d8301846108ff565b94935050505056fea164736f6c634300080f000a", @@ -133,30 +133,30 @@ } } }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"getImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"getOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_code\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setCode\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setOwner\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_value\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setStorage\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_owner\":\"Address of the initial contract owner.\"}},\"getImplementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"getOwner()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"setCode(bytes)\":{\"params\":{\"_code\":\"New contract code to run inside this contract.\"}},\"setOwner(address)\":{\"params\":{\"_owner\":\"New owner of the proxy contract.\"}},\"setStorage(bytes32,bytes32)\":{\"params\":{\"_key\":\"Storage key to modify.\",\"_value\":\"New value for the storage key.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getImplementation()\":{\"notice\":\"Queries the implementation address. Can only be called by the owner OR by making an eth_call and setting the \\\"from\\\" address to address(0).\"},\"getOwner()\":{\"notice\":\"Queries the owner of the proxy contract. Can only be called by the owner OR by making an eth_call and setting the \\\"from\\\" address to address(0).\"},\"setCode(bytes)\":{\"notice\":\"Sets the code that should be running behind this proxy. Note: This scheme is a bit different from the standard proxy scheme where one would typically deploy the code separately and then set the implementation address. We're doing it this way because it gives us a lot more freedom on the client side. Can only be triggered by the contract owner.\"},\"setOwner(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"setStorage(bytes32,bytes32)\":{\"notice\":\"Modifies some storage slot within the proxy contract. Gives us a lot of power to perform upgrades in a more transparent way. Only callable by the owner.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/legacy/L1ChugSplashProxy.sol\":\"L1ChugSplashProxy\"},\"libraries\":{}},\"sources\":{\"src/legacy/L1ChugSplashProxy.sol\":{\"keccak256\":\"0x102ea9c1eac2bbc071e38fdcc8d92deda3e7f32dc72d57fa3fe315cef354a5fe\",\"urls\":[\"bzz-raw://42efc6f277dd5f9ed874dbc6e214d481a26cc71751d505a75b44d86ecf8e4815\",\"dweb:/ipfs/QmUZLYii4uBr5JrWz8NTaaYkX56VvygKSqziKqGHuzM2Wr\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 4, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"getImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"getOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_code\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setCode\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setOwner\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_value\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setStorage\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_owner\":\"Address of the initial contract owner.\"}},\"getImplementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"getOwner()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"setCode(bytes)\":{\"params\":{\"_code\":\"New contract code to run inside this contract.\"}},\"setOwner(address)\":{\"params\":{\"_owner\":\"New owner of the proxy contract.\"}},\"setStorage(bytes32,bytes32)\":{\"params\":{\"_key\":\"Storage key to modify.\",\"_value\":\"New value for the storage key.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getImplementation()\":{\"notice\":\"Queries the implementation address. Can only be called by the owner OR by making an eth_call and setting the \\\"from\\\" address to address(0).\"},\"getOwner()\":{\"notice\":\"Queries the owner of the proxy contract. Can only be called by the owner OR by making an eth_call and setting the \\\"from\\\" address to address(0).\"},\"setCode(bytes)\":{\"notice\":\"Sets the code that should be running behind this proxy. Note: This scheme is a bit different from the standard proxy scheme where one would typically deploy the code separately and then set the implementation address. We're doing it this way because it gives us a lot more freedom on the client side. Can only be triggered by the contract owner.\"},\"setOwner(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"setStorage(bytes32,bytes32)\":{\"notice\":\"Modifies some storage slot within the proxy contract. Gives us a lot of power to perform upgrades in a more transparent way. Only callable by the owner.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/legacy/L1ChugSplashProxy.sol\":\"L1ChugSplashProxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/legacy/L1ChugSplashProxy.sol\":{\"keccak256\":\"0xdde5626645fa217ad3a37805c4c3012e4251de01df868aae73b986f5d03cdb23\",\"urls\":[\"bzz-raw://a99fd0ec440c17c826465001dc88c5185dd41dc72396254fdd3cdfcc84aeae8c\",\"dweb:/ipfs/QmStHuecN89zBL8FH9SUK1TtkyYwfzMY2KkQaFJLHZLuyA\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 1, "receipt": { - "transactionHash": "0x736c5d873360bd726f70311303b34d4beb022b23bd87b2684723d14067e6e143", - "transactionIndex": "0x8", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", + "transactionHash": "0xd399ab960cc38029c91d96b9ff4f802e253fcfed6c29a72ab34c5c502c052760", + "transactionIndex": "0xf", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "from": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", "to": null, - "cumulativeGasUsed": "0x5add2a", + "cumulativeGasUsed": "0x6c44d5", "gasUsed": "0x94b82", - "contractAddress": "0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1", + "contractAddress": "0x8ed848d60d988B27C0B9C9F86171083302F66EFb", "logs": [], "status": "0x1", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "type": "0x2", - "effectiveGasPrice": "0xbec78df7" + "effectiveGasPrice": "0xb2d05e0a" }, "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [], "types": {} }, - "transactionHash": "0x736c5d873360bd726f70311303b34d4beb022b23bd87b2684723d14067e6e143", + "transactionHash": "0xd399ab960cc38029c91d96b9ff4f802e253fcfed6c29a72ab34c5c502c052760", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/sepolia/L2OutputOracle.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L2OutputOracle.json similarity index 98% rename from packages/contracts-bedrock/deployments/sepolia/L2OutputOracle.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/L2OutputOracle.json index f0a0145cd4a7..2d6ed5c3fe5e 100644 --- a/packages/contracts-bedrock/deployments/sepolia/L2OutputOracle.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L2OutputOracle.json @@ -495,14 +495,14 @@ "type": "function" } ], - "address": "0x83aEb8B156cD90E64C702781C84A681DADb1DDe2", + "address": "0x358A08dB2dfA0D4f70f00aD000106586AfB9AF77", "args": [ "120", "2", "0", "0", - "0x49277EE36A024120Ee218127354c4a3591dc90A9", - "0xfd1D2e729aE8eEe2E146c033bf4400fE75284301", + "0x0b30D3F823aEFD81C7cE5a446eeb23c372D64f41", + "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", "12" ], "bytecode": "0x6101206040523480156200001257600080fd5b506040516200198438038062001984833981016040819052620000359162000347565b60008611620000b15760405162461bcd60e51b815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e203000000000000000000000000060648201526084015b60405180910390fd5b60008711620001295760405162461bcd60e51b815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e20300000000000006064820152608401620000a8565b608087905260a08690526001600160a01b0380841660e052821660c05261010081905262000158858562000165565b50505050505050620003af565b600054610100900460ff1615808015620001865750600054600160ff909116105b80620001b65750620001a3306200031b60201b6200133c1760201c565b158015620001b6575060005460ff166001145b6200021b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000a8565b6000805460ff1916600117905580156200023f576000805461ff0019166101001790555b42821115620002c55760405162461bcd60e51b8152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201526374696d6560e01b608482015260a401620000a8565b60028290556001839055801562000316576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b80516001600160a01b03811681146200034257600080fd5b919050565b600080600080600080600060e0888a0312156200036357600080fd5b875196506020880151955060408801519450606088015193506200038a608089016200032a565b92506200039a60a089016200032a565b915060c0880151905092959891949750929550565b60805160a05160c05160e0516101005161154a6200043a600039600081816104ad0152818161058b01526109c90152600081816104460152818161047c0152610b3901526000818161022e0152818161030501526108630152600081816101a1015281816103a401526110700152600081816101fd0152818161053501526110be015261154a6000f3fe60806040526004361061018a5760003560e01c806393991af3116100d6578063cf8e5cf01161007f578063e1a41bcf11610059578063e1a41bcf14610526578063e4a3011614610559578063f4daa2911461057957600080fd5b8063cf8e5cf0146104d1578063d1de856c146104f1578063dcec33481461051157600080fd5b8063a8e4fb90116100b0578063a8e4fb9014610437578063bffa7f0f1461046a578063ce5db8d61461049e57600080fd5b806393991af3146103955780639aaab648146103c8578063a25ae557146103db57600080fd5b80636abcf563116101385780637f006420116101125780637f0064201461033d578063887862721461035d57806389c44cbb1461037357600080fd5b80636abcf563146102de5780636b4d98dd146102f357806370872aa51461032757600080fd5b8063534db0e211610169578063534db0e21461021f57806354fd4d501461027357806369f16eec146102c957600080fd5b80622134cc1461018f5780634599c788146101d6578063529933df146101eb575b600080fd5b34801561019b57600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b3480156101e257600080fd5b506101c36105ad565b3480156101f757600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b34801561022b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101cd565b34801561027f57600080fd5b506102bc6040518060400160405280600581526020017f312e372e3000000000000000000000000000000000000000000000000000000081525081565b6040516101cd9190611358565b3480156102d557600080fd5b506101c3610620565b3480156102ea57600080fd5b506003546101c3565b3480156102ff57600080fd5b5061024e7f000000000000000000000000000000000000000000000000000000000000000081565b34801561033357600080fd5b506101c360015481565b34801561034957600080fd5b506101c36103583660046113cb565b610632565b34801561036957600080fd5b506101c360025481565b34801561037f57600080fd5b5061039361038e3660046113cb565b61084b565b005b3480156103a157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b6103936103d63660046113e4565b610b21565b3480156103e757600080fd5b506103fb6103f63660046113cb565b610fa0565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101cd565b34801561044357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061024e565b34801561047657600080fd5b5061024e7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104aa57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b3480156104dd57600080fd5b506103fb6104ec3660046113cb565b611034565b3480156104fd57600080fd5b506101c361050c3660046113cb565b61106c565b34801561051d57600080fd5b506101c36110ba565b34801561053257600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b34801561056557600080fd5b50610393610574366004611416565b6110ef565b34801561058557600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b6003546000901561061757600380546105c890600190611467565b815481106105d8576105d861147e565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b60035460009061061b90600190611467565b600061063c6105ad565b8211156106f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6003546107ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a4016106ed565b6003546000905b8082101561084457600060026107c883856114ad565b6107d291906114c5565b905084600382815481106107e8576107e861147e565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16101561083a576108338160016114ad565b925061083e565b8091505b506107b2565b5092915050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610910576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f757470757473000060648201526084016106ed565b60035481106109c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b7f0000000000000000000000000000000000000000000000000000000000000000600382815481106109fb576109fb61147e565b6000918252602090912060016002909202010154610a2b906fffffffffffffffffffffffffffffffff1642611467565b10610ade576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a4016106ed565b6000610ae960035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610c0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b610c146110ba565b8314610cc8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a4016106ed565b42610cd28461106c565b10610d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e20746865206675747572650000000000000000000060648201526084016106ed565b83610dec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f206861736800000000000060648201526084016106ed565b8115610ea85781814014610ea8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a4016106ed565b82610eb260035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e242604051610ee491815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b604080516060810182526000808252602082018190529181019190915260038281548110610fd057610fd061147e565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b6040805160608101825260008082526020820181905291810191909152600361105c83610632565b81548110610fd057610fd061147e565b60007f00000000000000000000000000000000000000000000000000000000000000006001548361109d9190611467565b6110a79190611500565b6002546110b491906114ad565b92915050565b60007f00000000000000000000000000000000000000000000000000000000000000006110e56105ad565b61061b91906114ad565b600054610100900460ff161580801561110f5750600054600160ff909116105b806111295750303b158015611129575060005460ff166001145b6111b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106ed565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561121357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b428211156112ca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b60028290556001839055801561133757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208083528351808285015260005b8181101561138557858101830151858201604001528201611369565b81811115611397576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000602082840312156113dd57600080fd5b5035919050565b600080600080608085870312156113fa57600080fd5b5050823594602084013594506040840135936060013592509050565b6000806040838503121561142957600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561147957611479611438565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156114c0576114c0611438565b500190565b6000826114fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561153857611538611438565b50029056fea164736f6c634300080f000a", @@ -611,13 +611,13 @@ } }, "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_proposer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_challenger\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriodSeconds\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"l2OutputIndex\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"l2BlockNumber\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"l1Timestamp\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"OutputProposed\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prevNextOutputIndex\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"newNextOutputIndex\",\"type\":\"uint256\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OutputsDeleted\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"CHALLENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"FINALIZATION_PERIOD_SECONDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"PROPOSER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"challenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"computeL2Timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"deleteL2Outputs\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"finalizationPeriodSeconds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"struct Types.OutputProposal\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"}]}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getL2OutputAfter\",\"outputs\":[{\"internalType\":\"struct Types.OutputProposal\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"}]}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getL2OutputIndexAfter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_startingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingTimestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2BlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"latestBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"latestOutputIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"nextBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"nextOutputIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1BlockHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"proposeL2Output\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"proposer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"startingBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"startingTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"submissionInterval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"computeL2Timestamp(uint256)\":{\"params\":{\"_l2BlockNumber\":\"The L2 block number of the target block.\"},\"returns\":{\"_0\":\"L2 timestamp of the given block.\"}},\"constructor\":{\"params\":{\"_challenger\":\"The address of the challenger.\",\"_l2BlockTime\":\"The time per L2 block, in seconds.\",\"_proposer\":\"The address of the proposer.\",\"_startingBlockNumber\":\"The number of the first L2 block.\",\"_startingTimestamp\":\"The timestamp of the first L2 block.\",\"_submissionInterval\":\"Interval in blocks at which checkpoints must be submitted.\"}},\"deleteL2Outputs(uint256)\":{\"params\":{\"_l2OutputIndex\":\"Index of the first L2 output to be deleted. All outputs after this output will also be deleted.\"}},\"getL2Output(uint256)\":{\"params\":{\"_l2OutputIndex\":\"Index of the output to return.\"},\"returns\":{\"_0\":\"The output at the given index.\"}},\"getL2OutputAfter(uint256)\":{\"params\":{\"_l2BlockNumber\":\"L2 block number to find a checkpoint for.\"},\"returns\":{\"_0\":\"First checkpoint that commits to the given L2 block number.\"}},\"getL2OutputIndexAfter(uint256)\":{\"params\":{\"_l2BlockNumber\":\"L2 block number to find a checkpoint for.\"},\"returns\":{\"_0\":\"Index of the first checkpoint that commits to the given L2 block number.\"}},\"initialize(uint256,uint256)\":{\"params\":{\"_startingBlockNumber\":\"Block number for the first recoded L2 block.\",\"_startingTimestamp\":\"Timestamp for the first recoded L2 block.\"}},\"latestBlockNumber()\":{\"returns\":{\"_0\":\"Latest submitted L2 block number.\"}},\"latestOutputIndex()\":{\"returns\":{\"_0\":\"The number of outputs that have been proposed.\"}},\"nextBlockNumber()\":{\"returns\":{\"_0\":\"Next L2 block number.\"}},\"nextOutputIndex()\":{\"returns\":{\"_0\":\"The index of the next output to be proposed.\"}},\"proposeL2Output(bytes32,uint256,bytes32,uint256)\":{\"params\":{\"_l1BlockHash\":\"A block hash which must be included in the current chain.\",\"_l1BlockNumber\":\"The block number with the specified block hash.\",\"_l2BlockNumber\":\"The L2 block number that resulted in _outputRoot.\",\"_outputRoot\":\"The L2 output of the checkpoint block.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"CHALLENGER()\":{\"notice\":\"The address of the challenger. Can be updated via upgrade. This will be removed in the future, use `challenger` instead.\"},\"FINALIZATION_PERIOD_SECONDS()\":{\"notice\":\"The minimum time (in seconds) that must elapse before a withdrawal can be finalized.\"},\"L2_BLOCK_TIME()\":{\"notice\":\"The time between L2 blocks in seconds. Once set, this value MUST NOT be modified.\"},\"PROPOSER()\":{\"notice\":\"The address of the proposer. Can be updated via upgrade. This will be removed in the future, use `proposer` instead.\"},\"SUBMISSION_INTERVAL()\":{\"notice\":\"The interval in L2 blocks at which checkpoints must be submitted. Although this is immutable, it can safely be modified by upgrading the implementation contract. Public getter is legacy and will be removed in the future. Use `submissionInterval` instead.\"},\"challenger()\":{\"notice\":\"Getter for the challenger address.\"},\"computeL2Timestamp(uint256)\":{\"notice\":\"Returns the L2 timestamp corresponding to a given L2 block number.\"},\"constructor\":{\"notice\":\"Constructs the L2OutputOracle contract.\"},\"deleteL2Outputs(uint256)\":{\"notice\":\"Deletes all output proposals after and including the proposal that corresponds to the given output index. Only the challenger address can delete outputs.\"},\"finalizationPeriodSeconds()\":{\"notice\":\"Getter for the FINALIZATION_PERIOD_SECONDS.\"},\"getL2Output(uint256)\":{\"notice\":\"Returns an output by index. Needed to return a struct instead of a tuple.\"},\"getL2OutputAfter(uint256)\":{\"notice\":\"Returns the L2 output proposal that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block.\"},\"getL2OutputIndexAfter(uint256)\":{\"notice\":\"Returns the index of the L2 output that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block.\"},\"initialize(uint256,uint256)\":{\"notice\":\"Initializer.\"},\"l2BlockTime()\":{\"notice\":\"Getter for the L2_BLOCK_TIME.\"},\"latestBlockNumber()\":{\"notice\":\"Returns the block number of the latest submitted L2 output proposal. If no proposals been submitted yet then this function will return the starting block number.\"},\"latestOutputIndex()\":{\"notice\":\"Returns the number of outputs that have been proposed. Will revert if no outputs have been proposed yet.\"},\"nextBlockNumber()\":{\"notice\":\"Computes the block number of the next L2 block that needs to be checkpointed.\"},\"nextOutputIndex()\":{\"notice\":\"Returns the index of the next output to be proposed.\"},\"proposeL2Output(bytes32,uint256,bytes32,uint256)\":{\"notice\":\"Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp must be equal to the current value returned by `nextTimestamp()` in order to be accepted. This function may only be called by the Proposer.\"},\"proposer()\":{\"notice\":\"Getter for the PROPOSER address.\"},\"startingBlockNumber()\":{\"notice\":\"The number of the first L2 block recorded in this contract.\"},\"startingTimestamp()\":{\"notice\":\"The timestamp of the first L2 block recorded in this contract.\"},\"submissionInterval()\":{\"notice\":\"Getter for the SUBMISSION_INTERVAL.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L2OutputOracle.sol\":\"L2OutputOracle\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L2OutputOracle.sol\":{\"keccak256\":\"0xecd3b0cd61ec0d1246ea19cc5095508b84ad0d586988f781b4de9233b3c2821d\",\"urls\":[\"bzz-raw://b4d5e6a842dd999ff09c6db97c8a5e44aaa5f84652a6eb1aa3c170094e9c9591\",\"dweb:/ipfs/QmfUaT1pX9rQBZm48zdwzaSQ7miW8Ek7kBwys1UhMFSYJR\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 7, + "numDeployments": 1, "receipt": "", "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [ { - "astId": 45395, + "astId": 47332, "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", "label": "_initialized", "offset": 0, @@ -625,7 +625,7 @@ "type": "t_uint8" }, { - "astId": 45398, + "astId": 47335, "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", "label": "_initializing", "offset": 1, @@ -633,7 +633,7 @@ "type": "t_bool" }, { - "astId": 66319, + "astId": 75566, "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", "label": "startingBlockNumber", "offset": 0, @@ -641,7 +641,7 @@ "type": "t_uint256" }, { - "astId": 66322, + "astId": 75569, "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", "label": "startingTimestamp", "offset": 0, @@ -649,20 +649,20 @@ "type": "t_uint256" }, { - "astId": 66327, + "astId": 75574, "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", "label": "l2Outputs", "offset": 0, "slot": "3", - "type": "t_array(t_struct(OutputProposal)79366_storage)dyn_storage" + "type": "t_array(t_struct(OutputProposal)89577_storage)dyn_storage" } ], "types": { - "t_array(t_struct(OutputProposal)79366_storage)dyn_storage": { + "t_array(t_struct(OutputProposal)89577_storage)dyn_storage": { "encoding": "dynamic_array", "label": "struct Types.OutputProposal[]", "numberOfBytes": "32", - "base": "t_struct(OutputProposal)79366_storage" + "base": "t_struct(OutputProposal)89577_storage" }, "t_bool": { "encoding": "inplace", @@ -674,13 +674,13 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_struct(OutputProposal)79366_storage": { + "t_struct(OutputProposal)89577_storage": { "encoding": "inplace", "label": "struct Types.OutputProposal", "numberOfBytes": "64", "members": [ { - "astId": 79361, + "astId": 89572, "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", "label": "outputRoot", "offset": 0, @@ -688,7 +688,7 @@ "type": "t_bytes32" }, { - "astId": 79363, + "astId": 89574, "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", "label": "timestamp", "offset": 0, @@ -696,7 +696,7 @@ "type": "t_uint128" }, { - "astId": 79365, + "astId": 89576, "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", "label": "l2BlockNumber", "offset": 16, @@ -722,7 +722,7 @@ } } }, - "transactionHash": "0xc84d1047795fb6f848826d234fe9020e568f552eeabc65593cd6826f876baf96", + "transactionHash": "0xddb1a9f5889ce8313f9d90810a0caa7ccd866ca1293b4c4b08a651e3e4544908", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L2OutputOracleProxy.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L2OutputOracleProxy.json new file mode 100644 index 000000000000..046cde19fb47 --- /dev/null +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/L2OutputOracleProxy.json @@ -0,0 +1,256 @@ +{ + "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" + } + ], + "address": "0x568128D8EF08D30cEf0Ad50273701EC5B3c43Ebc", + "args": [ + "0x1814DBa2CC02DC44408ec2E05a680bC3dD24Cf4B" + ], + "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "admin()": { + "returns": { + "_0": "Owner address." + } + }, + "changeAdmin(address)": { + "params": { + "_admin": "New owner of the proxy contract." + } + }, + "constructor": { + "params": { + "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." + } + }, + "implementation()": { + "returns": { + "_0": "Implementation address." + } + }, + "upgradeTo(address)": { + "params": { + "_implementation": "Address of the implementation contract." + } + }, + "upgradeToAndCall(address,bytes)": { + "params": { + "_data": "Calldata to delegatecall the new implementation with.", + "_implementation": "Address of the implementation contract." + } + } + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new owner of the contract", + "previousAdmin": "The previous owner of the contract" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The address of the implementation contract" + } + } + }, + "title": "Proxy" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 1, + "receipt": { + "transactionHash": "0x6be59dd7b3cb633a5167e6f077c49963d005469f41150ecdd16faffbbf8892cd", + "transactionIndex": "0xd", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "from": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", + "to": null, + "cumulativeGasUsed": "0x5af703", + "gasUsed": "0x80250", + "contractAddress": "0x568128D8EF08D30cEf0Ad50273701EC5B3c43Ebc", + "logs": [ + { + "address": "0x568128D8EF08D30cEf0Ad50273701EC5B3c43Ebc", + "topics": [ + "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" + ], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001814dba2cc02dc44408ec2e05a680bc3dd24cf4b", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0x6be59dd7b3cb633a5167e6f077c49963d005469f41150ecdd16faffbbf8892cd", + "transactionIndex": "0xd", + "logIndex": "0x1e", + "removed": false + } + ], + "status": "0x1", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "effectiveGasPrice": "0xb2d05e0a" + }, + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [], + "types": {} + }, + "transactionHash": "0x6be59dd7b3cb633a5167e6f077c49963d005469f41150ecdd16faffbbf8892cd", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "admin()": { + "notice": "Gets the owner of the proxy contract." + }, + "changeAdmin(address)": { + "notice": "Changes the owner of the proxy contract. Only callable by the owner." + }, + "constructor": { + "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." + }, + "upgradeTo(address)": { + "notice": "Set the implementation contract address. The code at the given address will execute when this contract is called." + }, + "upgradeToAndCall(address,bytes)": { + "notice": "Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades." + } + }, + "events": { + "AdminChanged(address,address)": { + "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." + }, + "Upgraded(address)": { + "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." + } + }, + "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." + } +} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/sepolia/OptimismMintableERC20Factory.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/OptimismMintableERC20Factory.json similarity index 99% rename from packages/contracts-bedrock/deployments/sepolia/OptimismMintableERC20Factory.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/OptimismMintableERC20Factory.json index ff9fa00d562c..ea953593082c 100644 --- a/packages/contracts-bedrock/deployments/sepolia/OptimismMintableERC20Factory.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/OptimismMintableERC20Factory.json @@ -187,9 +187,9 @@ "type": "function" } ], - "address": "0xD7e63EC8ec03803236bE93642a610641DEe51e62", + "address": "0x26004BFE7155167ca5aCa3Bb818A1365a2bF8C48", "args": [ - "0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1" + "0x8ed848d60d988B27C0B9C9F86171083302F66EFb" ], "bytecode": "0x60a060405234801561001057600080fd5b50604051611f59380380611f5983398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b608051611ec0610099600039600081816101420152818161016d01526102880152611ec06000f3fe60806040523480156200001157600080fd5b50600436106200007b5760003560e01c8063ce5ac90f1162000056578063ce5ac90f1462000129578063e78cea921462000140578063ee9a31a2146200016757600080fd5b806354fd4d501462000080578063896f93d114620000d55780638cf0629c1462000112575b600080fd5b620000bd6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b604051620000cc91906200042e565b60405180910390f35b620000ec620000e636600462000556565b6200018f565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000cc565b620000ec62000123366004620005d3565b620001a6565b620000ec6200013a36600462000556565b620003a1565b7f0000000000000000000000000000000000000000000000000000000000000000620000ec565b620000ec7f000000000000000000000000000000000000000000000000000000000000000081565b60006200019e848484620003a1565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000250576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e206164647265737300606482015260840160405180910390fd5b6000858585856040516020016200026b94939291906200066a565b6040516020818303038152906040528051906020012090506000817f000000000000000000000000000000000000000000000000000000000000000088888888604051620002b990620003b2565b620002c9959493929190620006c4565b8190604051809103906000f5905080158015620002ea573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b60006200019e8484846012620001a6565b61178a806200072a83390190565b6000815180845260005b81811015620003e857602081850181015186830182015201620003ca565b81811115620003fb576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620004436020830184620003c0565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200046f57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112620004b557600080fd5b813567ffffffffffffffff80821115620004d357620004d362000474565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156200051c576200051c62000474565b816040528381528660208588010111156200053657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200056c57600080fd5b62000577846200044a565b9250602084013567ffffffffffffffff808211156200059557600080fd5b620005a387838801620004a3565b93506040860135915080821115620005ba57600080fd5b50620005c986828701620004a3565b9150509250925092565b60008060008060808587031215620005ea57600080fd5b620005f5856200044a565b9350602085013567ffffffffffffffff808211156200061357600080fd5b6200062188838901620004a3565b945060408701359150808211156200063857600080fd5b506200064787828801620004a3565b925050606085013560ff811681146200065f57600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200069b6080830186620003c0565b8281036040840152620006af8186620003c0565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620006ff60a0830186620003c0565b8281036060840152620007138186620003c0565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a", "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200007b5760003560e01c8063ce5ac90f1162000056578063ce5ac90f1462000129578063e78cea921462000140578063ee9a31a2146200016757600080fd5b806354fd4d501462000080578063896f93d114620000d55780638cf0629c1462000112575b600080fd5b620000bd6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b604051620000cc91906200042e565b60405180910390f35b620000ec620000e636600462000556565b6200018f565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000cc565b620000ec62000123366004620005d3565b620001a6565b620000ec6200013a36600462000556565b620003a1565b7f0000000000000000000000000000000000000000000000000000000000000000620000ec565b620000ec7f000000000000000000000000000000000000000000000000000000000000000081565b60006200019e848484620003a1565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000250576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e206164647265737300606482015260840160405180910390fd5b6000858585856040516020016200026b94939291906200066a565b6040516020818303038152906040528051906020012090506000817f000000000000000000000000000000000000000000000000000000000000000088888888604051620002b990620003b2565b620002c9959493929190620006c4565b8190604051809103906000f5905080158015620002ea573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b60006200019e8484846012620001a6565b61178a806200072a83390190565b6000815180845260005b81811015620003e857602081850181015186830182015201620003ca565b81811115620003fb576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620004436020830184620003c0565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200046f57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112620004b557600080fd5b813567ffffffffffffffff80821115620004d357620004d362000474565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156200051c576200051c62000474565b816040528381528660208588010111156200053657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200056c57600080fd5b62000577846200044a565b9250602084013567ffffffffffffffff808211156200059557600080fd5b620005a387838801620004a3565b93506040860135915080821115620005ba57600080fd5b50620005c986828701620004a3565b9150509250925092565b60008060008060808587031215620005ea57600080fd5b620005f5856200044a565b9350602085013567ffffffffffffffff808211156200061357600080fd5b6200062188838901620004a3565b945060408701359150808211156200063857600080fd5b506200064787828801620004a3565b925050606085013560ff811681146200065f57600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200069b6080830186620003c0565b8281036040840152620006af8186620003c0565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620006ff60a0830186620003c0565b8281036060840152620007138186620003c0565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a", @@ -252,14 +252,14 @@ "title": "OptimismMintableERC20Factory" }, "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"deployer\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"OptimismMintableERC20Created\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"StandardL2TokenCreated\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createOptimismMintableERC20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createOptimismMintableERC20WithDecimals\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createStandardL2Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_bridge\":\"Address of the StandardBridge on this chain.\"}},\"createOptimismMintableERC20(address,string,string)\":{\"params\":{\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}},\"createOptimismMintableERC20WithDecimals(address,string,string,uint8)\":{\"params\":{\"_decimals\":\"ERC20 decimals\",\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}},\"createStandardL2Token(address,string,string)\":{\"custom:legacy\":\"@notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the newer createOptimismMintableERC20 function, which has a more intuitive name.\",\"params\":{\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"BRIDGE()\":{\"notice\":\"Address of the StandardBridge on this chain.\"},\"bridge()\":{\"notice\":\"Getter function for the address of the StandardBridge on this chain.Address of the StandardBridge on this chain.\"},\"createOptimismMintableERC20(address,string,string)\":{\"notice\":\"Creates an instance of the OptimismMintableERC20 contract.\"},\"createOptimismMintableERC20WithDecimals(address,string,string,uint8)\":{\"notice\":\"Creates an instance of the OptimismMintableERC20 contract, with specified decimals.\"},\"version()\":{\"notice\":\"The semver MUST be bumped any time that there is a change in the OptimismMintableERC20 token contract since this contract is responsible for deploying OptimismMintableERC20 contracts.Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/OptimismMintableERC20Factory.sol\":\"OptimismMintableERC20Factory\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x6f8133b39efcbcbd5088f195dfacf1bedc3146508429c3865443909af735a04c\",\"urls\":[\"bzz-raw://adc36971e2e120458769f050428d9d2b0504516660345020c2521ee46e6d8abf\",\"dweb:/ipfs/QmPbFusQkZgGKpU8Fv5JoqL4oVeJtM3yqnhRGLY9eZT5zZ\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x18721f41a831ec39d47002e73ecc2aa3e6624f8d1ab7b9f25b53348e8b0765df\",\"urls\":[\"bzz-raw://2162fa7529a77b199a07f37fca26c778542f6c8805f0365f1ceef90c5cd3a3a7\",\"dweb:/ipfs/QmaMmHJS52Bp95AGnrjh1zV7fLLqV3uAbFzkVLziMnPJYa\"],\"license\":\"MIT\"},\"src/universal/OptimismMintableERC20Factory.sol\":{\"keccak256\":\"0xb1246b060ce15bc0921415ade33770583f3e8c6433c340a5d54dea0a2b000d2b\",\"urls\":[\"bzz-raw://173ca63347b9d6cdea43ce47906b55e11a35950f9efe9333c9be4fa069ee6ae8\",\"dweb:/ipfs/QmcUf2CndeHPbSEKzWorPoS2dMG6PKHJEyV8FSiqdwFtn5\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 7, + "numDeployments": 1, "receipt": "", "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [], "types": {} }, - "transactionHash": "0x92a4aca5c8a826e65206dbaad676eae57e4dcd17ff0357aa265f8f56adedb474", + "transactionHash": "0xcec04fd297e9c4547cf7a7522dd30b130d2b987f328ca997e80c72148c177614", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/mainnet/ProtocolVersionsProxy.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/OptimismMintableERC20FactoryProxy.json similarity index 77% rename from packages/contracts-bedrock/deployments/mainnet/ProtocolVersionsProxy.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/OptimismMintableERC20FactoryProxy.json index 571d13eef0f5..e48f0eb97522 100644 --- a/packages/contracts-bedrock/deployments/mainnet/ProtocolVersionsProxy.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/OptimismMintableERC20FactoryProxy.json @@ -128,9 +128,9 @@ "type": "receive" } ], - "address": "0x8062AbC286f5e7D9428a0Ccb9AbD71e50d93b935", + "address": "0x96B8653eCb0A67976BB3874FB5a91ab55413a45C", "args": [ - "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960" + "0x1814DBa2CC02DC44408ec2E05a680bC3dD24Cf4B" ], "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", @@ -185,44 +185,44 @@ }, "title": "Proxy" }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xc56de5e39cd44eaeb93f0f8705dd07f4a89f66d5c186522532cf899a104cdbca\",\"urls\":[\"bzz-raw://cd1b595148fa62a798343a23e3330e79fef7d747f039d664482044be9ec0ccf3\",\"dweb:/ipfs/QmeAft6H9wbc9zZZ3prtRaBGGzcPy9yExKAhZHjp1iZ8UF\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 2, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 1, "receipt": { - "transactionHash": "0x4ab7f052e31b73b021e814069aca71203829101066362541ba8e14113932ea99", - "transactionIndex": "0x9", - "blockHash": "0x0d0787545a87d78f45279d585b9b25c4aeeb8d2110d56f2c5307b80445d45c53", - "blockNumber": "0x1184344", - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", + "transactionHash": "0x5bd70691190cca5c05d079f8ffddb7a256065eda347c9a2a9c34e73fcff091e4", + "transactionIndex": "0x11", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "from": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", "to": null, - "cumulativeGasUsed": "0x2afbc6", + "cumulativeGasUsed": "0x789583", "gasUsed": "0x80250", - "contractAddress": "0x8062AbC286f5e7D9428a0Ccb9AbD71e50d93b935", + "contractAddress": "0x96B8653eCb0A67976BB3874FB5a91ab55413a45C", "logs": [ { - "address": "0x8062AbC286f5e7D9428a0Ccb9AbD71e50d93b935", + "address": "0x96B8653eCb0A67976BB3874FB5a91ab55413a45C", "topics": [ "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000354f3f4ecdca5e0a7ace08d71348cdc1dab48960", - "blockHash": "0x0d0787545a87d78f45279d585b9b25c4aeeb8d2110d56f2c5307b80445d45c53", - "blockNumber": "0x1184344", - "transactionHash": "0x4ab7f052e31b73b021e814069aca71203829101066362541ba8e14113932ea99", - "transactionIndex": "0x9", - "logIndex": "0x31", + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001814dba2cc02dc44408ec2e05a680bc3dd24cf4b", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0x5bd70691190cca5c05d079f8ffddb7a256065eda347c9a2a9c34e73fcff091e4", + "transactionIndex": "0x11", + "logIndex": "0x20", "removed": false } ], "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000040000000000000000000000000000000000000000000000000000000000000000000000000000", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000200000000000000080000000000000000", "type": "0x2", - "effectiveGasPrice": "0x22f2c5d4c" + "effectiveGasPrice": "0xb2d05e0a" }, "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [], "types": {} }, - "transactionHash": "0x4ab7f052e31b73b021e814069aca71203829101066362541ba8e14113932ea99", + "transactionHash": "0x5bd70691190cca5c05d079f8ffddb7a256065eda347c9a2a9c34e73fcff091e4", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/goerli/OptimismPortal.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/OptimismPortal.json similarity index 98% rename from packages/contracts-bedrock/deployments/goerli/OptimismPortal.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/OptimismPortal.json index 1f8263659109..f9e967fc2cc2 100644 --- a/packages/contracts-bedrock/deployments/goerli/OptimismPortal.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/OptimismPortal.json @@ -567,10 +567,10 @@ "type": "receive" } ], - "address": "0x770D4355c9658Cad9fC555cD04E657aBAB9E65B9", + "address": "0xfAA271aEb5ea1D88007cE2bFd08756c3288a7AD3", "args": [ - "0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0", - "0xAe851f927Ee40dE99aaBb7461C00f9622ab91d60" + "0x568128D8EF08D30cEf0Ad50273701EC5B3c43Ebc", + "0x843264FdBAfF9fB1F156892d8055992f57838705" ], "bytecode": "0x60c06040523480156200001157600080fd5b50604051620057313803806200573183398101604081905262000034916200028f565b6001600160a01b03808316608052811660a0526200005360006200005b565b5050620002ce565b600054610100900460ff16158080156200007c5750600054600160ff909116105b80620000ac57506200009930620001c460201b62001be21760201c565b158015620000ac575060005460ff166001145b620001155760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000139576000805461ff0019166101001790555b603280546001600160a01b03191661dead179055603580546001600160a01b03841661010002610100600160a81b031990911617905562000179620001d3565b8015620001c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620002405760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200010c565b60408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b6001600160a01b03811681146200028c57600080fd5b50565b60008060408385031215620002a357600080fd5b8251620002b08162000276565b6020840151909250620002c38162000276565b809150509250929050565b60805160a0516153fe6200033360003960008181610230015281816105b601526121f30152600081816101ab0152818161038a01528181610a6b01528181610c4c01528181611051015281816112f7015281816115690152611fdf01526153fe6000f3fe60806040526004361061016d5760003560e01c80638b4c40b0116100cb578063a35d99df1161007f578063e965084c11610059578063e965084c14610505578063e9e05c4214610591578063f0498750146105a457600080fd5b8063a35d99df1461040b578063c4d66de814610444578063cff0ab961461046457600080fd5b80639b5f694a116100b05780639b5f694a1461037b5780639bf62d82146103ae578063a14238e7146103db57600080fd5b80638b4c40b0146101925780638c3152e91461035b57600080fd5b80634870496f116101225780635c975abb116101075780635c975abb146103115780636dbffb7814610326578063724c184c1461034657600080fd5b80634870496f1461029b57806354fd4d50146102bb57600080fd5b806333d7e2bd1161015357806333d7e2bd1461022157806335e80ab314610254578063452a93201461028657600080fd5b80621c2ff61461019957806318db921b146101f757600080fd5b36610194576101923334620186a06000604051806020016040528060008152506105d8565b005b600080fd5b3480156101a557600080fd5b506101cd7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561020357600080fd5b506035546102119060ff1681565b60405190151581526020016101ee565b34801561022d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101cd565b34801561026057600080fd5b506035546101cd90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561029257600080fd5b506101cd610873565b3480156102a757600080fd5b506101926102b63660046149ef565b61090b565b3480156102c757600080fd5b506103046040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101ee9190614b45565b34801561031d57600080fd5b50610211610f73565b34801561033257600080fd5b50610211610341366004614b58565b611006565b34801561035257600080fd5b506101cd6110dd565b34801561036757600080fd5b50610192610376366004614b71565b6110e7565b34801561038757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101cd565b3480156103ba57600080fd5b506032546101cd9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103e757600080fd5b506102116103f6366004614b58565b60336020526000908152604090205460ff1681565b34801561041757600080fd5b5061042b610426366004614bcb565b6119c4565b60405167ffffffffffffffff90911681526020016101ee565b34801561045057600080fd5b5061019261045f366004614be6565b6119dd565b34801561047057600080fd5b506001546104cc906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101ee565b34801561051157600080fd5b50610563610520366004614b58565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101ee565b61019261059f366004614c11565b6105d8565b3480156105b057600080fd5b506101cd7f000000000000000000000000000000000000000000000000000000000000000081565b8260005a9050831561068f5773ffffffffffffffffffffffffffffffffffffffff87161561068f57604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b61069983516119c4565b67ffffffffffffffff168567ffffffffffffffff16101561073c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c00000000000000000000000000000000000000000000000000000000006064820152608401610686565b6201d4c0835111156107aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c6172676500006044820152606401610686565b333281146107cb575033731111000000000000000000000000000000001111015b600034888888886040516020016107e6959493929190614c8e565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516108569190614b45565b60405180910390a4505061086a8282611bfe565b50505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190614cf3565b905090565b610913610f73565b1561097a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610686565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610a39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610686565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610ac7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aeb9190614d30565b519050610b05610b0036869003860186614d95565b611f2b565b8114610b93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610686565b6000610b9e87611f87565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610cd05750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610ca8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccc9190614d30565b5114155b610d5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610686565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610e259101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610e1b888a614dfb565b8a60400135611fb7565b610eb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610686565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fe2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190614e7f565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018290526000906110d79073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa158015611098573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bc9190614d30565b602001516fffffffffffffffffffffffffffffffff16611fdb565b92915050565b6000610906610873565b6110ef610f73565b15611156576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610686565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead146111ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610686565b600061120a82611f87565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036112f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610686565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa158015611360573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113849190614e9c565b81602001516fffffffffffffffffffffffffffffffff16101561144f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610686565b61146e81602001516fffffffffffffffffffffffffffffffff16611fdb565b611520576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610686565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e99190614d30565b82518151919250146116a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610686565b6116c281602001516fffffffffffffffffffffffffffffffff16611fdb565b611774576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610686565b60008381526033602052604090205460ff1615611813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610686565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a08801516118b59392919061207e565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061191a90841515815260200190565b60405180910390a2801580156119305750326001145b156119bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610686565b5050505050565b60006119d1826010614ee4565b6110d790615208614f14565b600054610100900460ff16158080156119fd5750600054600160ff909116105b80611a175750303b158015611a17575060005460ff166001145b611aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610686565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611b0157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556035805473ffffffffffffffffffffffffffffffffffffffff8416610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909116179055611b7b6120dc565b8015611bde57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611c34907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643614f40565b90506000611c406121bf565b90506000816020015160ff16826000015163ffffffff16611c619190614f86565b90508215611d9857600154600090611c98908390700100000000000000000000000000000000900467ffffffffffffffff16614fee565b90506000836040015160ff1683611caf9190615062565b600154611ccf9084906fffffffffffffffffffffffffffffffff16615062565b611cd99190614f86565b600154909150600090611d2a90611d039084906fffffffffffffffffffffffffffffffff1661511e565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612280565b90506001861115611d5957611d56611d0382876040015160ff1660018a611d519190614f40565b61229f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611dcb908490700100000000000000000000000000000000900467ffffffffffffffff16614f14565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611eae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d697400006064820152608401610686565b600154600090611eda906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615192565b90506000611eec48633b9aca006122f4565b611ef690836151cf565b905060005a611f059088614f40565b905080821115611f2157611f21611f1c8284614f40565b61230b565b5050505050505050565b60008160000151826020015183604001518460600151604051602001611f6a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097611f6a9790969591016151e3565b600080611fc386612339565b9050611fd18186868661236b565b9695505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa158015612048573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206c9190614e9c565b612076908361523a565b421192915050565b600080600061208e86600061239b565b9050806120c4576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff16612173576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610686565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663cc731b026040518163ffffffff1660e01b815260040160c060405180830381865afa15801561225c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190615277565b600061229561228f85856123b9565b836123c9565b90505b9392505050565b6000670de0b6b3a76400006122e06122b78583614f86565b6122c990670de0b6b3a7640000614fee565b6122db85670de0b6b3a7640000615062565b6123d8565b6122ea9086615062565b6122959190614f86565b6000818310156123045781612298565b5090919050565b6000805a90505b825a61231e9083614f40565b10156123345761232d82615316565b9150612312565b505050565b6060818051906020012060405160200161235591815260200190565b6040516020818303038152906040529050919050565b60006123928461237c878686612409565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156123045781612298565b60008183126123045781612298565b6000612298670de0b6b3a7640000836123f086612e87565b6123fa9190615062565b6124049190614f86565b6130cb565b60606000845111612476576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610686565b60006124818461330a565b9050600061248e866133f6565b90506000846040516020016124a591815260200190565b60405160208183030381529060405290506000805b8451811015612dfe5760008582815181106124d7576124d761534e565b602002602001015190508451831115612572576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610686565b8260000361262b57805180516020918201206040516125c09261259a92910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610686565b612782565b8051516020116126e157805180516020918201206040516126559261259a92910190815260200190565b612626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610686565b805184516020808701919091208251919092012014612782576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610686565b61278e6010600161523a565b8160200151510361296a5784518303612902576127c881602001516010815181106127bb576127bb61534e565b6020026020010151613459565b9650600087511161285b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610686565b600186516128699190614f40565b82146128f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610686565b505050505050612298565b60008584815181106129165761291661534e565b602001015160f81c60f81b60f81c9050600082602001518260ff16815181106129415761294161534e565b60200260200101519050612954816135b9565b955061296160018661523a565b94505050612deb565b600281602001515103612d63576000612982826135de565b90506000816000815181106129995761299961534e565b016020015160f81c905060006129b060028361537d565b6129bb90600261539f565b905060006129cc848360ff16613602565b905060006129da8a89613602565b905060006129e88383613638565b905080835114612a7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610686565b60ff851660021480612a8f575060ff85166003145b15612c7e5780825114612b24576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610686565b612b3e87602001516001815181106127bb576127bb61534e565b9c5060008d5111612bd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610686565b60018c51612bdf9190614f40565b8814612c6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610686565b505050505050505050505050612298565b60ff85161580612c91575060ff85166001145b15612cd057612cbd8760200151600181518110612cb057612cb061534e565b60200260200101516135b9565b9950612cc9818a61523a565b9850612d58565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610686565b505050505050612deb565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610686565b5080612df681615316565b9150506124ba565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610686565b6000808213612ef2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610686565b60006060612eff846136ec565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136130fc57506000919050565b680755bf798b4a1bf1e5821261316e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610686565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff8111156133285761332861480f565b60405190808252806020026020018201604052801561336d57816020015b60408051808201909152606080825260208201528152602001906001900390816133465790505b50915060005b818110156133ef5760405180604001604052808583815181106133985761339861534e565b602002602001015181526020016133c78684815181106133ba576133ba61534e565b60200260200101516137c2565b8152508382815181106133dc576133dc61534e565b6020908102919091010152600101613373565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b8381101561344e578060011b82018184015160001a8060041c8253600f811660018301535050600101613420565b509295945050505050565b60606000806000613469856137d5565b919450925090506000816001811115613484576134846153c2565b14613511576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d000000000000006064820152608401610686565b61351b828461523a565b8551146135aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e6465720000000000000000000000006064820152608401610686565b61239285602001518484614242565b606060208260000151106135d5576135d082613459565b6110d7565b6110d7826142d6565b60606110d76135fd83602001516000815181106127bb576127bb61534e565b6133f6565b60608251821061362157506040805160208101909152600081526110d7565b61229883838486516136339190614f40565b6142ec565b600080825184511061364b57825161364e565b83515b90505b80821080156136d5575082828151811061366d5761366d61534e565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106136ac576136ac61534e565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156136e557816001019150613651565b5092915050565b6000808211613757576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610686565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60606110d76137d0836144c4565b6145ad565b600080600080846000015111613893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610686565b6020840151805160001a607f81116138b857600060016000945094509450505061423b565b60b78111613ac65760006138cd608083614f40565b905080876000015111613988576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a401610686565b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082141580613a0157507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613ab3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a401610686565b506001955093506000925061423b915050565b60bf8111613e14576000613adb60b783614f40565b905080876000015111613b96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a401610686565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613c74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a401610686565b600184015160088302610100031c60378111613d38576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a401610686565b613d42818461523a565b895111613df7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a401610686565b613e0283600161523a565b975095506000945061423b9350505050565b60f78111613ef5576000613e2960c083614f40565b905080876000015111613ee4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a401610686565b60019550935084925061423b915050565b6000613f0260f783614f40565b905080876000015111613fbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a401610686565b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361409b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a401610686565b600184015160088302610100031c6037811161415f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a401610686565b614169818461523a565b89511161421e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a401610686565b61422983600161523a565b975095506001945061423b9350505050565b9193909250565b60608167ffffffffffffffff81111561425d5761425d61480f565b6040519080825280601f01601f191660200182016040528015614287576020820181803683370190505b509050811561229857600061429c848661523a565b90506020820160005b848110156142bd5782810151828201526020016142a5565b848111156142cc576000858301525b5050509392505050565b60606110d7826020015160008460000151614242565b60608182601f01101561435b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610686565b8282840110156143c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610686565b81830184511015614434576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610686565b60608215801561445357604051915060008252602082016040526144bb565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561448c578051835260209283019201614474565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6040805180820190915260008082526020820152600082511161458f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610686565b50604080518082019091528151815260209182019181019190915290565b606060008060006145bd856137d5565b9194509250905060018160018111156145d8576145d86153c2565b14614665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d00000000000000006064820152608401610686565b8451614671838561523a565b146146fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e64657200000000000000000000000000006064820152608401610686565b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816147155790505093506000835b8651811015614803576000806147886040518060400160405280858c6000015161476c9190614f40565b8152602001858c60200151614781919061523a565b90526137d5565b5091509150604051806040016040528083836147a4919061523a565b8152602001848b602001516147b9919061523a565b8152508885815181106147ce576147ce61534e565b60209081029190910101526147e460018561523a565b93506147f0818361523a565b6147fa908461523a565b92505050614742565b50845250919392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156148855761488561480f565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff811681146148af57600080fd5b50565b600082601f8301126148c357600080fd5b813567ffffffffffffffff8111156148dd576148dd61480f565b61490e60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161483e565b81815284602083860101111561492357600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561495257600080fd5b60405160c0810167ffffffffffffffff82821081831117156149765761497661480f565b8160405282935084358352602085013591506149918261488d565b816020840152604085013591506149a78261488d565b816040840152606085013560608401526080850135608084015260a08501359150808211156149d557600080fd5b506149e2858286016148b2565b60a0830152505092915050565b600080600080600085870360e0811215614a0857600080fd5b863567ffffffffffffffff80821115614a2057600080fd5b614a2c8a838b01614940565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614a6557600080fd5b60408901955060c0890135925080831115614a7f57600080fd5b828901925089601f840112614a9357600080fd5b8235915080821115614aa457600080fd5b508860208260051b8401011115614aba57600080fd5b959894975092955050506020019190565b60005b83811015614ae6578181015183820152602001614ace565b83811115614af5576000848401525b50505050565b60008151808452614b13816020860160208601614acb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122986020830184614afb565b600060208284031215614b6a57600080fd5b5035919050565b600060208284031215614b8357600080fd5b813567ffffffffffffffff811115614b9a57600080fd5b614ba684828501614940565b949350505050565b803567ffffffffffffffff81168114614bc657600080fd5b919050565b600060208284031215614bdd57600080fd5b61229882614bae565b600060208284031215614bf857600080fd5b81356122988161488d565b80151581146148af57600080fd5b600080600080600060a08688031215614c2957600080fd5b8535614c348161488d565b945060208601359350614c4960408701614bae565b92506060860135614c5981614c03565b9150608086013567ffffffffffffffff811115614c7557600080fd5b614c81888289016148b2565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614ce2816049850160208701614acb565b919091016049019695505050505050565b600060208284031215614d0557600080fd5b81516122988161488d565b80516fffffffffffffffffffffffffffffffff81168114614bc657600080fd5b600060608284031215614d4257600080fd5b6040516060810181811067ffffffffffffffff82111715614d6557614d6561480f565b60405282518152614d7860208401614d10565b6020820152614d8960408401614d10565b60408201529392505050565b600060808284031215614da757600080fd5b6040516080810181811067ffffffffffffffff82111715614dca57614dca61480f565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614e1657614e1661480f565b8360051b6020614e2781830161483e565b868152918501918181019036841115614e3f57600080fd5b865b84811015614e7357803586811115614e595760008081fd5b614e6536828b016148b2565b845250918301918301614e41565b50979650505050505050565b600060208284031215614e9157600080fd5b815161229881614c03565b600060208284031215614eae57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615614f0b57614f0b614eb5565b02949350505050565b600067ffffffffffffffff808316818516808303821115614f3757614f37614eb5565b01949350505050565b600082821015614f5257614f52614eb5565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614f9557614f95614f57565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615614fe957614fe9614eb5565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561502857615028614eb5565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561505c5761505c614eb5565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156150a3576150a3614eb5565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156150de576150de614eb5565b600087129250878205871284841616156150fa576150fa614eb5565b8785058712818416161561511057615110614eb5565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561515857615158614eb5565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561518c5761518c614eb5565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156151ca576151ca614eb5565b500290565b6000826151de576151de614f57565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261522e60c0830184614afb565b98975050505050505050565b6000821982111561524d5761524d614eb5565b500190565b805163ffffffff81168114614bc657600080fd5b805160ff81168114614bc657600080fd5b600060c0828403121561528957600080fd5b60405160c0810181811067ffffffffffffffff821117156152ac576152ac61480f565b6040526152b883615252565b81526152c660208401615266565b60208201526152d760408401615266565b60408201526152e860608401615252565b60608201526152f960808401615252565b608082015261530a60a08401614d10565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361534757615347614eb5565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff83168061539057615390614f57565b8060ff84160691505092915050565b600060ff821660ff8416808210156153b9576153b9614eb5565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", "deployedBytecode": "0x60806040526004361061016d5760003560e01c80638b4c40b0116100cb578063a35d99df1161007f578063e965084c11610059578063e965084c14610505578063e9e05c4214610591578063f0498750146105a457600080fd5b8063a35d99df1461040b578063c4d66de814610444578063cff0ab961461046457600080fd5b80639b5f694a116100b05780639b5f694a1461037b5780639bf62d82146103ae578063a14238e7146103db57600080fd5b80638b4c40b0146101925780638c3152e91461035b57600080fd5b80634870496f116101225780635c975abb116101075780635c975abb146103115780636dbffb7814610326578063724c184c1461034657600080fd5b80634870496f1461029b57806354fd4d50146102bb57600080fd5b806333d7e2bd1161015357806333d7e2bd1461022157806335e80ab314610254578063452a93201461028657600080fd5b80621c2ff61461019957806318db921b146101f757600080fd5b36610194576101923334620186a06000604051806020016040528060008152506105d8565b005b600080fd5b3480156101a557600080fd5b506101cd7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561020357600080fd5b506035546102119060ff1681565b60405190151581526020016101ee565b34801561022d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101cd565b34801561026057600080fd5b506035546101cd90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561029257600080fd5b506101cd610873565b3480156102a757600080fd5b506101926102b63660046149ef565b61090b565b3480156102c757600080fd5b506103046040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101ee9190614b45565b34801561031d57600080fd5b50610211610f73565b34801561033257600080fd5b50610211610341366004614b58565b611006565b34801561035257600080fd5b506101cd6110dd565b34801561036757600080fd5b50610192610376366004614b71565b6110e7565b34801561038757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101cd565b3480156103ba57600080fd5b506032546101cd9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103e757600080fd5b506102116103f6366004614b58565b60336020526000908152604090205460ff1681565b34801561041757600080fd5b5061042b610426366004614bcb565b6119c4565b60405167ffffffffffffffff90911681526020016101ee565b34801561045057600080fd5b5061019261045f366004614be6565b6119dd565b34801561047057600080fd5b506001546104cc906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101ee565b34801561051157600080fd5b50610563610520366004614b58565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101ee565b61019261059f366004614c11565b6105d8565b3480156105b057600080fd5b506101cd7f000000000000000000000000000000000000000000000000000000000000000081565b8260005a9050831561068f5773ffffffffffffffffffffffffffffffffffffffff87161561068f57604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b61069983516119c4565b67ffffffffffffffff168567ffffffffffffffff16101561073c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c00000000000000000000000000000000000000000000000000000000006064820152608401610686565b6201d4c0835111156107aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c6172676500006044820152606401610686565b333281146107cb575033731111000000000000000000000000000000001111015b600034888888886040516020016107e6959493929190614c8e565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516108569190614b45565b60405180910390a4505061086a8282611bfe565b50505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190614cf3565b905090565b610913610f73565b1561097a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610686565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610a39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610686565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610ac7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aeb9190614d30565b519050610b05610b0036869003860186614d95565b611f2b565b8114610b93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610686565b6000610b9e87611f87565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610cd05750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610ca8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ccc9190614d30565b5114155b610d5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610686565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610e259101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610e1b888a614dfb565b8a60400135611fb7565b610eb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610686565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fe2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190614e7f565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018290526000906110d79073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa158015611098573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bc9190614d30565b602001516fffffffffffffffffffffffffffffffff16611fdb565b92915050565b6000610906610873565b6110ef610f73565b15611156576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610686565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead146111ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610686565b600061120a82611f87565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036112f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610686565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa158015611360573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113849190614e9c565b81602001516fffffffffffffffffffffffffffffffff16101561144f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610686565b61146e81602001516fffffffffffffffffffffffffffffffff16611fdb565b611520576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610686565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e99190614d30565b82518151919250146116a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610686565b6116c281602001516fffffffffffffffffffffffffffffffff16611fdb565b611774576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610686565b60008381526033602052604090205460ff1615611813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610686565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a08801516118b59392919061207e565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061191a90841515815260200190565b60405180910390a2801580156119305750326001145b156119bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610686565b5050505050565b60006119d1826010614ee4565b6110d790615208614f14565b600054610100900460ff16158080156119fd5750600054600160ff909116105b80611a175750303b158015611a17575060005460ff166001145b611aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610686565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611b0157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556035805473ffffffffffffffffffffffffffffffffffffffff8416610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909116179055611b7b6120dc565b8015611bde57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611c34907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643614f40565b90506000611c406121bf565b90506000816020015160ff16826000015163ffffffff16611c619190614f86565b90508215611d9857600154600090611c98908390700100000000000000000000000000000000900467ffffffffffffffff16614fee565b90506000836040015160ff1683611caf9190615062565b600154611ccf9084906fffffffffffffffffffffffffffffffff16615062565b611cd99190614f86565b600154909150600090611d2a90611d039084906fffffffffffffffffffffffffffffffff1661511e565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612280565b90506001861115611d5957611d56611d0382876040015160ff1660018a611d519190614f40565b61229f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611dcb908490700100000000000000000000000000000000900467ffffffffffffffff16614f14565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611eae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d697400006064820152608401610686565b600154600090611eda906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615192565b90506000611eec48633b9aca006122f4565b611ef690836151cf565b905060005a611f059088614f40565b905080821115611f2157611f21611f1c8284614f40565b61230b565b5050505050505050565b60008160000151826020015183604001518460600151604051602001611f6a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097611f6a9790969591016151e3565b600080611fc386612339565b9050611fd18186868661236b565b9695505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa158015612048573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206c9190614e9c565b612076908361523a565b421192915050565b600080600061208e86600061239b565b9050806120c4576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff16612173576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610686565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663cc731b026040518163ffffffff1660e01b815260040160c060405180830381865afa15801561225c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190615277565b600061229561228f85856123b9565b836123c9565b90505b9392505050565b6000670de0b6b3a76400006122e06122b78583614f86565b6122c990670de0b6b3a7640000614fee565b6122db85670de0b6b3a7640000615062565b6123d8565b6122ea9086615062565b6122959190614f86565b6000818310156123045781612298565b5090919050565b6000805a90505b825a61231e9083614f40565b10156123345761232d82615316565b9150612312565b505050565b6060818051906020012060405160200161235591815260200190565b6040516020818303038152906040529050919050565b60006123928461237c878686612409565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156123045781612298565b60008183126123045781612298565b6000612298670de0b6b3a7640000836123f086612e87565b6123fa9190615062565b6124049190614f86565b6130cb565b60606000845111612476576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610686565b60006124818461330a565b9050600061248e866133f6565b90506000846040516020016124a591815260200190565b60405160208183030381529060405290506000805b8451811015612dfe5760008582815181106124d7576124d761534e565b602002602001015190508451831115612572576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610686565b8260000361262b57805180516020918201206040516125c09261259a92910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610686565b612782565b8051516020116126e157805180516020918201206040516126559261259a92910190815260200190565b612626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610686565b805184516020808701919091208251919092012014612782576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610686565b61278e6010600161523a565b8160200151510361296a5784518303612902576127c881602001516010815181106127bb576127bb61534e565b6020026020010151613459565b9650600087511161285b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610686565b600186516128699190614f40565b82146128f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610686565b505050505050612298565b60008584815181106129165761291661534e565b602001015160f81c60f81b60f81c9050600082602001518260ff16815181106129415761294161534e565b60200260200101519050612954816135b9565b955061296160018661523a565b94505050612deb565b600281602001515103612d63576000612982826135de565b90506000816000815181106129995761299961534e565b016020015160f81c905060006129b060028361537d565b6129bb90600261539f565b905060006129cc848360ff16613602565b905060006129da8a89613602565b905060006129e88383613638565b905080835114612a7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610686565b60ff851660021480612a8f575060ff85166003145b15612c7e5780825114612b24576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610686565b612b3e87602001516001815181106127bb576127bb61534e565b9c5060008d5111612bd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610686565b60018c51612bdf9190614f40565b8814612c6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610686565b505050505050505050505050612298565b60ff85161580612c91575060ff85166001145b15612cd057612cbd8760200151600181518110612cb057612cb061534e565b60200260200101516135b9565b9950612cc9818a61523a565b9850612d58565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610686565b505050505050612deb565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610686565b5080612df681615316565b9150506124ba565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610686565b6000808213612ef2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610686565b60006060612eff846136ec565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136130fc57506000919050565b680755bf798b4a1bf1e5821261316e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610686565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff8111156133285761332861480f565b60405190808252806020026020018201604052801561336d57816020015b60408051808201909152606080825260208201528152602001906001900390816133465790505b50915060005b818110156133ef5760405180604001604052808583815181106133985761339861534e565b602002602001015181526020016133c78684815181106133ba576133ba61534e565b60200260200101516137c2565b8152508382815181106133dc576133dc61534e565b6020908102919091010152600101613373565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b8381101561344e578060011b82018184015160001a8060041c8253600f811660018301535050600101613420565b509295945050505050565b60606000806000613469856137d5565b919450925090506000816001811115613484576134846153c2565b14613511576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d000000000000006064820152608401610686565b61351b828461523a565b8551146135aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e6465720000000000000000000000006064820152608401610686565b61239285602001518484614242565b606060208260000151106135d5576135d082613459565b6110d7565b6110d7826142d6565b60606110d76135fd83602001516000815181106127bb576127bb61534e565b6133f6565b60608251821061362157506040805160208101909152600081526110d7565b61229883838486516136339190614f40565b6142ec565b600080825184511061364b57825161364e565b83515b90505b80821080156136d5575082828151811061366d5761366d61534e565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106136ac576136ac61534e565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156136e557816001019150613651565b5092915050565b6000808211613757576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610686565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60606110d76137d0836144c4565b6145ad565b600080600080846000015111613893576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610686565b6020840151805160001a607f81116138b857600060016000945094509450505061423b565b60b78111613ac65760006138cd608083614f40565b905080876000015111613988576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a401610686565b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082141580613a0157507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613ab3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a401610686565b506001955093506000925061423b915050565b60bf8111613e14576000613adb60b783614f40565b905080876000015111613b96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a401610686565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613c74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a401610686565b600184015160088302610100031c60378111613d38576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a401610686565b613d42818461523a565b895111613df7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a401610686565b613e0283600161523a565b975095506000945061423b9350505050565b60f78111613ef5576000613e2960c083614f40565b905080876000015111613ee4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a401610686565b60019550935084925061423b915050565b6000613f0260f783614f40565b905080876000015111613fbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a401610686565b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361409b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a401610686565b600184015160088302610100031c6037811161415f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a401610686565b614169818461523a565b89511161421e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a401610686565b61422983600161523a565b975095506001945061423b9350505050565b9193909250565b60608167ffffffffffffffff81111561425d5761425d61480f565b6040519080825280601f01601f191660200182016040528015614287576020820181803683370190505b509050811561229857600061429c848661523a565b90506020820160005b848110156142bd5782810151828201526020016142a5565b848111156142cc576000858301525b5050509392505050565b60606110d7826020015160008460000151614242565b60608182601f01101561435b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610686565b8282840110156143c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610686565b81830184511015614434576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610686565b60608215801561445357604051915060008252602082016040526144bb565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561448c578051835260209283019201614474565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6040805180820190915260008082526020820152600082511161458f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610686565b50604080518082019091528151815260209182019181019190915290565b606060008060006145bd856137d5565b9194509250905060018160018111156145d8576145d86153c2565b14614665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d00000000000000006064820152608401610686565b8451614671838561523a565b146146fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e64657200000000000000000000000000006064820152608401610686565b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816147155790505093506000835b8651811015614803576000806147886040518060400160405280858c6000015161476c9190614f40565b8152602001858c60200151614781919061523a565b90526137d5565b5091509150604051806040016040528083836147a4919061523a565b8152602001848b602001516147b9919061523a565b8152508885815181106147ce576147ce61534e565b60209081029190910101526147e460018561523a565b93506147f0818361523a565b6147fa908461523a565b92505050614742565b50845250919392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156148855761488561480f565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff811681146148af57600080fd5b50565b600082601f8301126148c357600080fd5b813567ffffffffffffffff8111156148dd576148dd61480f565b61490e60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161483e565b81815284602083860101111561492357600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561495257600080fd5b60405160c0810167ffffffffffffffff82821081831117156149765761497661480f565b8160405282935084358352602085013591506149918261488d565b816020840152604085013591506149a78261488d565b816040840152606085013560608401526080850135608084015260a08501359150808211156149d557600080fd5b506149e2858286016148b2565b60a0830152505092915050565b600080600080600085870360e0811215614a0857600080fd5b863567ffffffffffffffff80821115614a2057600080fd5b614a2c8a838b01614940565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614a6557600080fd5b60408901955060c0890135925080831115614a7f57600080fd5b828901925089601f840112614a9357600080fd5b8235915080821115614aa457600080fd5b508860208260051b8401011115614aba57600080fd5b959894975092955050506020019190565b60005b83811015614ae6578181015183820152602001614ace565b83811115614af5576000848401525b50505050565b60008151808452614b13816020860160208601614acb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122986020830184614afb565b600060208284031215614b6a57600080fd5b5035919050565b600060208284031215614b8357600080fd5b813567ffffffffffffffff811115614b9a57600080fd5b614ba684828501614940565b949350505050565b803567ffffffffffffffff81168114614bc657600080fd5b919050565b600060208284031215614bdd57600080fd5b61229882614bae565b600060208284031215614bf857600080fd5b81356122988161488d565b80151581146148af57600080fd5b600080600080600060a08688031215614c2957600080fd5b8535614c348161488d565b945060208601359350614c4960408701614bae565b92506060860135614c5981614c03565b9150608086013567ffffffffffffffff811115614c7557600080fd5b614c81888289016148b2565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614ce2816049850160208701614acb565b919091016049019695505050505050565b600060208284031215614d0557600080fd5b81516122988161488d565b80516fffffffffffffffffffffffffffffffff81168114614bc657600080fd5b600060608284031215614d4257600080fd5b6040516060810181811067ffffffffffffffff82111715614d6557614d6561480f565b60405282518152614d7860208401614d10565b6020820152614d8960408401614d10565b60408201529392505050565b600060808284031215614da757600080fd5b6040516080810181811067ffffffffffffffff82111715614dca57614dca61480f565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614e1657614e1661480f565b8360051b6020614e2781830161483e565b868152918501918181019036841115614e3f57600080fd5b865b84811015614e7357803586811115614e595760008081fd5b614e6536828b016148b2565b845250918301918301614e41565b50979650505050505050565b600060208284031215614e9157600080fd5b815161229881614c03565b600060208284031215614eae57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615614f0b57614f0b614eb5565b02949350505050565b600067ffffffffffffffff808316818516808303821115614f3757614f37614eb5565b01949350505050565b600082821015614f5257614f52614eb5565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614f9557614f95614f57565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615614fe957614fe9614eb5565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561502857615028614eb5565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561505c5761505c614eb5565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156150a3576150a3614eb5565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156150de576150de614eb5565b600087129250878205871284841616156150fa576150fa614eb5565b8785058712818416161561511057615110614eb5565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561515857615158614eb5565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561518c5761518c614eb5565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156151ca576151ca614eb5565b500290565b6000826151de576151de614f57565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261522e60c0830184614afb565b98975050505050505050565b6000821982111561524d5761524d614eb5565b500190565b805163ffffffff81168114614bc657600080fd5b805160ff81168114614bc657600080fd5b600060c0828403121561528957600080fd5b60405160c0810181811067ffffffffffffffff821117156152ac576152ac61480f565b6040526152b883615252565b81526152c660208401615266565b60208201526152d760408401615266565b60408201526152e860608401615252565b60608201526152f960808401615252565b608082015261530a60a08401614d10565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361534757615347614eb5565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff83168061539057615390614f57565b8060ff84160691505092915050565b600060ff821660ff8416808210156153b9576153b9614eb5565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", @@ -665,37 +665,8 @@ } }, "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"contract SystemConfig\",\"name\":\"_systemConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Paused\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"opaqueData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"TransactionDeposited\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Unpaused\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\",\"indexed\":false}],\"type\":\"event\",\"name\":\"WithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"WithdrawalProven\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"GUARDIAN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"SYSTEM_CONFIG\",\"outputs\":[{\"internalType\":\"contract SystemConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositTransaction\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"donateETH\"},{\"inputs\":[{\"internalType\":\"struct Types.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeWithdrawalTransaction\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"guardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"_superchainConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"isOutputFinalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2Oracle\",\"outputs\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_byteCount\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"minimumGasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"params\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"prevBaseFee\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"prevBoughtGas\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"prevBlockNum\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"struct Types.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}]},{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"},{\"internalType\":\"struct Types.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messagePasserStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}]},{\"internalType\":\"bytes[]\",\"name\":\"_withdrawalProof\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"proveWithdrawalTransaction\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"provenWithdrawals\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2OutputIndex\",\"type\":\"uint128\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"spacer_53_0_1\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"superchainConfig\",\"outputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"systemConfig\",\"outputs\":[{\"internalType\":\"contract SystemConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"GUARDIAN()\":{\"custom:legacy\":\"\"},\"constructor\":{\"params\":{\"_l2Oracle\":\"Address of the L2OutputOracle contract.\",\"_systemConfig\":\"Address of the SystemConfig contract.\"}},\"depositTransaction(address,uint256,uint64,bool,bytes)\":{\"params\":{\"_data\":\"Data to trigger the recipient with.\",\"_gasLimit\":\"Amount of L2 gas to purchase by burning gas on L1.\",\"_isCreation\":\"Whether or not the transaction is a contract creation.\",\"_to\":\"Target address on L2.\",\"_value\":\"ETH value to send to the recipient.\"}},\"finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))\":{\"params\":{\"_tx\":\"Withdrawal transaction to finalize.\"}},\"guardian()\":{\"custom:legacy\":\"\"},\"initialize(address)\":{\"params\":{\"_superchainConfig\":\"Address of the SuperchainConfig contract.\"}},\"isOutputFinalized(uint256)\":{\"params\":{\"_l2OutputIndex\":\"Index of the L2 output to check.\"},\"returns\":{\"_0\":\"Whether or not the output is finalized.\"}},\"minimumGasLimit(uint64)\":{\"params\":{\"_byteCount\":\"Number of bytes in the calldata.\"},\"returns\":{\"_0\":\"The minimum gas limit for a deposit.\"}},\"proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])\":{\"params\":{\"_l2OutputIndex\":\"L2 output index to prove against.\",\"_outputRootProof\":\"Inclusion proof of the L2ToL1MessagePasser contract's storage root.\",\"_tx\":\"Withdrawal transaction to finalize.\",\"_withdrawalProof\":\"Inclusion proof of the withdrawal in L2ToL1MessagePasser contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"GUARDIAN()\":{\"notice\":\"Getter function for the address of the guardian. This will be removed in the future, use `SuperchainConfig.guardian()` instead.Address of the guardian.\"},\"L2_ORACLE()\":{\"notice\":\"Address of the L2OutputOracle contract. This will be removed in the future, use `l2Oracle` instead.\"},\"SYSTEM_CONFIG()\":{\"notice\":\"Address of the SystemConfig contract. This will be removed in the future, use `systemConfig` instead.\"},\"constructor\":{\"notice\":\"Constructs the OptimismPortal contract.\"},\"depositTransaction(address,uint256,uint64,bool,bytes)\":{\"notice\":\"Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in deriving deposit transactions. Note that if a deposit is made by a contract, its address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider using the CrossDomainMessenger contracts for a simpler developer experience.\"},\"donateETH()\":{\"notice\":\"Accepts ETH value without triggering a deposit to L2. This function mainly exists for the sake of the migration between the legacy Optimism system and Bedrock.\"},\"finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))\":{\"notice\":\"Finalizes a withdrawal transaction.\"},\"finalizedWithdrawals(bytes32)\":{\"notice\":\"A list of withdrawal hashes which have been successfully finalized.\"},\"guardian()\":{\"notice\":\"Getter function for the address of the guardian. This will be removed in the future, use `SuperchainConfig.guardian()` instead.Address of the guardian.\"},\"initialize(address)\":{\"notice\":\"Initializer.\"},\"isOutputFinalized(uint256)\":{\"notice\":\"Determine if a given output is finalized. Reverts if the call to L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.\"},\"l2Oracle()\":{\"notice\":\"Getter function for the address of the L2OutputOracle on this chain.Address of the L2OutputOracle on this chain.\"},\"l2Sender()\":{\"notice\":\"Address of the L2 account which initiated a withdrawal in this transaction. If the of this variable is the default L2 sender address, then we are NOT inside of a call to finalizeWithdrawalTransaction.\"},\"minimumGasLimit(uint64)\":{\"notice\":\"Computes the minimum gas limit for a deposit. The minimum gas limit linearly increases based on the size of the calldata. This is to prevent users from creating L2 resource usage without paying for it. This function can be used when interacting with the portal to ensure forwards compatibility.\"},\"params()\":{\"notice\":\"EIP-1559 style gas parameters.\"},\"paused()\":{\"notice\":\"Getter for the current paused status.\"},\"proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])\":{\"notice\":\"Proves a withdrawal transaction.\"},\"provenWithdrawals(bytes32)\":{\"notice\":\"A mapping of withdrawal hashes to `ProvenWithdrawal` data.\"},\"spacer_53_0_1()\":{\"notice\":\"Spacer for backwards compatibility.\"},\"superchainConfig()\":{\"notice\":\"The address of the Superchain Config contract.\"},\"systemConfig()\":{\"notice\":\"Getter function for the address of the SystemConfig on this chain.Address of the SystemConfig on this chain.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/OptimismPortal.sol\":\"OptimismPortal\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L2OutputOracle.sol\":{\"keccak256\":\"0xecd3b0cd61ec0d1246ea19cc5095508b84ad0d586988f781b4de9233b3c2821d\",\"urls\":[\"bzz-raw://b4d5e6a842dd999ff09c6db97c8a5e44aaa5f84652a6eb1aa3c170094e9c9591\",\"dweb:/ipfs/QmfUaT1pX9rQBZm48zdwzaSQ7miW8Ek7kBwys1UhMFSYJR\"],\"license\":\"MIT\"},\"src/L1/OptimismPortal.sol\":{\"keccak256\":\"0x62c4745158651d87705e20b3bbe5aecc09790a2a08a84b65cf5961a746716363\",\"urls\":[\"bzz-raw://47ec233411fcad292daaa5463c2c86352718c0e0ff8d1f27a87d4781382f91f5\",\"dweb:/ipfs/QmfKW1SDvoBcFeYRXYwnBsXKP5npC4PXNXpQz2wVn1Xx7S\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x9d6e33ea5d12b78fd3cb024ed5863c8c14cb55977cbab56fd9ce5c309918afc6\",\"urls\":[\"bzz-raw://d8545d6255ed4428b168a3547d6935043e5b680344d650fd090293ba36b59897\",\"dweb:/ipfs/QmPLVma7kqTTgbAHtxog2MGD7S2Wr8nd42MhBcfJ5yyF4W\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x5c6346060b3e8d3bf4289b20fd869a66fbad8f69dc0b095845f990066b6c4d2b\",\"urls\":[\"bzz-raw://161277a9935cc567d76096a9a3ffc54632fda2020e02b4c5dc5541bfad3d166f\",\"dweb:/ipfs/QmXiDP2A4MPsN9VDNf9YbqbQQTU2J5tffWbJHg45f9LJyN\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Bytes.sol\":{\"keccak256\":\"0x827f47d123b0fdf3b08816d5b33831811704dbf4e554e53f2269354f6bba8859\",\"urls\":[\"bzz-raw://3137ac7204d30a245a8b0d67aa6da5286f1bd8c90379daab561f84963b6db782\",\"dweb:/ipfs/QmWRhisw3axJK833gUScs23ETh2MLFbVzzqzYVMKSDN3S9\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPReader.sol\":{\"keccak256\":\"0x9ba74a3b0a11693e622380807d213d5d1250d974e18b2cd768da9cbe719a6778\",\"urls\":[\"bzz-raw://0808d721ed9e05707526ee134faa051d707a95ee6b8bd6e0b1972275da8e5723\",\"dweb:/ipfs/QmcTTPu9xgckfWdbFUAcr2RAgk3J6vzyR4FpV798TjFMeN\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/libraries/trie/MerkleTrie.sol\":{\"keccak256\":\"0xf8ba770ee6666e73ae43184c700e9c704b2c4ace71f9e3c2227ddc11a8148b4c\",\"urls\":[\"bzz-raw://4702ccee1fe44aea3ee01d59e6152eb755da083f786f00947fec4437c064fe74\",\"dweb:/ipfs/QmQjFj5J7hrEM1dxJjFszzW2Cs7g7eMhYNBXonF2DXBstE\"],\"license\":\"MIT\"},\"src/libraries/trie/SecureMerkleTrie.sol\":{\"keccak256\":\"0xeaff8315cfd21197bc6bc859c2decf5d4f4838c9c357c502cdf2b1eac863d288\",\"urls\":[\"bzz-raw://79dcdcaa560aea51d138da4f5dc553a1808b6de090b2dc1629f18375edbff681\",\"dweb:/ipfs/QmbE4pUPhf5fLKW4W6cEjhQs55gEDvHmbmoBqkW1yz3bnw\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"],\"license\":\"Apache-2.0\"}},\"version\":1}", - "numDeployments": 5, - "receipt": { - "transactionHash": "0x0158c5df5e0c7623c39c228b2b3421e386dc80eb3f5d4f0cb6ea1f3a4fa9c0bd", - "transactionIndex": "0x4c", - "blockHash": "0x26b41230d3e96940acaeee8dca1fc446fbdb113d6ec7b07d8dffa3dd302469af", - "blockNumber": "0x9acee7", - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "cumulativeGasUsed": "0x19ad986", - "gasUsed": "0x4874c2", - "contractAddress": "0x770D4355c9658Cad9fC555cD04E657aBAB9E65B9", - "logs": [ - { - "address": "0x770D4355c9658Cad9fC555cD04E657aBAB9E65B9", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "blockHash": "0x26b41230d3e96940acaeee8dca1fc446fbdb113d6ec7b07d8dffa3dd302469af", - "blockNumber": "0x9acee7", - "transactionHash": "0x0158c5df5e0c7623c39c228b2b3421e386dc80eb3f5d4f0cb6ea1f3a4fa9c0bd", - "transactionIndex": "0x4c", - "logIndex": "0x76", - "removed": false - } - ], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000001000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "type": "0x2", - "effectiveGasPrice": "0xb2d05f18" - }, + "numDeployments": 1, + "receipt": "", "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [ @@ -716,15 +687,15 @@ "type": "t_bool" }, { - "astId": 77647, + "astId": 77020, "contract": "src/L1/OptimismPortal.sol:OptimismPortal", "label": "params", "offset": 0, "slot": "1", - "type": "t_struct(ResourceParams)77630_storage" + "type": "t_struct(ResourceParams)77003_storage" }, { - "astId": 77652, + "astId": 77025, "contract": "src/L1/OptimismPortal.sol:OptimismPortal", "label": "__gap", "offset": 0, @@ -732,7 +703,7 @@ "type": "t_array(t_uint256)48_storage" }, { - "astId": 76728, + "astId": 76101, "contract": "src/L1/OptimismPortal.sol:OptimismPortal", "label": "l2Sender", "offset": 0, @@ -740,7 +711,7 @@ "type": "t_address" }, { - "astId": 76733, + "astId": 76106, "contract": "src/L1/OptimismPortal.sol:OptimismPortal", "label": "finalizedWithdrawals", "offset": 0, @@ -748,15 +719,15 @@ "type": "t_mapping(t_bytes32,t_bool)" }, { - "astId": 76739, + "astId": 76112, "contract": "src/L1/OptimismPortal.sol:OptimismPortal", "label": "provenWithdrawals", "offset": 0, "slot": "52", - "type": "t_mapping(t_bytes32,t_struct(ProvenWithdrawal)76709_storage)" + "type": "t_mapping(t_bytes32,t_struct(ProvenWithdrawal)76082_storage)" }, { - "astId": 76742, + "astId": 76115, "contract": "src/L1/OptimismPortal.sol:OptimismPortal", "label": "spacer_53_0_1", "offset": 0, @@ -764,12 +735,12 @@ "type": "t_bool" }, { - "astId": 76746, + "astId": 76119, "contract": "src/L1/OptimismPortal.sol:OptimismPortal", "label": "superchainConfig", "offset": 1, "slot": "53", - "type": "t_contract(SuperchainConfig)78153" + "type": "t_contract(SuperchainConfig)77526" } ], "types": { @@ -794,7 +765,7 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_contract(SuperchainConfig)78153": { + "t_contract(SuperchainConfig)77526": { "encoding": "inplace", "label": "contract SuperchainConfig", "numberOfBytes": "20" @@ -806,20 +777,20 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_bytes32,t_struct(ProvenWithdrawal)76709_storage)": { + "t_mapping(t_bytes32,t_struct(ProvenWithdrawal)76082_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct OptimismPortal.ProvenWithdrawal)", "numberOfBytes": "32", - "value": "t_struct(ProvenWithdrawal)76709_storage" + "value": "t_struct(ProvenWithdrawal)76082_storage" }, - "t_struct(ProvenWithdrawal)76709_storage": { + "t_struct(ProvenWithdrawal)76082_storage": { "encoding": "inplace", "label": "struct OptimismPortal.ProvenWithdrawal", "numberOfBytes": "64", "members": [ { - "astId": 76704, + "astId": 76077, "contract": "src/L1/OptimismPortal.sol:OptimismPortal", "label": "outputRoot", "offset": 0, @@ -827,7 +798,7 @@ "type": "t_bytes32" }, { - "astId": 76706, + "astId": 76079, "contract": "src/L1/OptimismPortal.sol:OptimismPortal", "label": "timestamp", "offset": 0, @@ -835,7 +806,7 @@ "type": "t_uint128" }, { - "astId": 76708, + "astId": 76081, "contract": "src/L1/OptimismPortal.sol:OptimismPortal", "label": "l2OutputIndex", "offset": 16, @@ -844,13 +815,13 @@ } ] }, - "t_struct(ResourceParams)77630_storage": { + "t_struct(ResourceParams)77003_storage": { "encoding": "inplace", "label": "struct ResourceMetering.ResourceParams", "numberOfBytes": "32", "members": [ { - "astId": 77625, + "astId": 76998, "contract": "src/L1/OptimismPortal.sol:OptimismPortal", "label": "prevBaseFee", "offset": 0, @@ -858,7 +829,7 @@ "type": "t_uint128" }, { - "astId": 77627, + "astId": 77000, "contract": "src/L1/OptimismPortal.sol:OptimismPortal", "label": "prevBoughtGas", "offset": 16, @@ -866,7 +837,7 @@ "type": "t_uint64" }, { - "astId": 77629, + "astId": 77002, "contract": "src/L1/OptimismPortal.sol:OptimismPortal", "label": "prevBlockNum", "offset": 24, @@ -897,7 +868,7 @@ } } }, - "transactionHash": "0x0158c5df5e0c7623c39c228b2b3421e386dc80eb3f5d4f0cb6ea1f3a4fa9c0bd", + "transactionHash": "0xae4ecc0094037822129526a5d9987e60511a3a264347bfcced3d4973d919cc37", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/sepolia/L1ERC721BridgeProxy.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/OptimismPortalProxy.json similarity index 53% rename from packages/contracts-bedrock/deployments/sepolia/L1ERC721BridgeProxy.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/OptimismPortalProxy.json index 449f83f9b234..31871ac3efdb 100644 --- a/packages/contracts-bedrock/deployments/sepolia/L1ERC721BridgeProxy.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/OptimismPortalProxy.json @@ -128,12 +128,12 @@ "type": "receive" } ], - "address": "0xd83e03D576d23C9AEab8cC44Fa98d058D2176D1f", + "address": "0x1f1cd3b548FC4Df6b6dBeA9F983D3B7357Aa6d7a", "args": [ - "0x189aBAAaa82DfC015A588A7dbaD6F13b1D3485Bc" + "0x1814DBa2CC02DC44408ec2E05a680bC3dD24Cf4B" ], - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", "devdoc": { "version": 1, "kind": "dev", @@ -185,44 +185,44 @@ }, "title": "Proxy" }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"src/universal/Proxy.sol\":{\"keccak256\":\"0x783aed9ff90b38a9898be5fb18699b3b249f012bc2c33f6537e1ab9f6444478f\",\"urls\":[\"bzz-raw://b119b1b68874f4d92a89cc05a4f0d25da73a959747a81e26739739a52895b844\",\"dweb:/ipfs/QmbKZqMd6CsM7annE7bCXcCi72syJAX3qtuFNPEGMCp13W\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 4, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 1, "receipt": { - "transactionHash": "0x0cc2efb428b8fcd337337e6c04d1af53ffa295345244c448617ab9156a624d69", + "transactionHash": "0x8aaea11800531d34415cda91003165c7b075dbf01dc6a87e208c5bba20c727f1", "transactionIndex": "0xc", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "from": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", "to": null, - "cumulativeGasUsed": "0x6fea85", - "gasUsed": "0x7feb8", - "contractAddress": "0xd83e03D576d23C9AEab8cC44Fa98d058D2176D1f", + "cumulativeGasUsed": "0x52f4b3", + "gasUsed": "0x80250", + "contractAddress": "0x1f1cd3b548FC4Df6b6dBeA9F983D3B7357Aa6d7a", "logs": [ { - "address": "0xd83e03D576d23C9AEab8cC44Fa98d058D2176D1f", + "address": "0x1f1cd3b548FC4Df6b6dBeA9F983D3B7357Aa6d7a", "topics": [ "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000189abaaaa82dfc015a588a7dbad6f13b1d3485bc", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "transactionHash": "0x0cc2efb428b8fcd337337e6c04d1af53ffa295345244c448617ab9156a624d69", + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001814dba2cc02dc44408ec2e05a680bc3dd24cf4b", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0x8aaea11800531d34415cda91003165c7b075dbf01dc6a87e208c5bba20c727f1", "transactionIndex": "0xc", - "logIndex": "0xa", + "logIndex": "0x1d", "removed": false } ], "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000040000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "type": "0x2", - "effectiveGasPrice": "0xbec78df7" + "effectiveGasPrice": "0xb2d05e0a" }, "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [], "types": {} }, - "transactionHash": "0x0cc2efb428b8fcd337337e6c04d1af53ffa295345244c448617ab9156a624d69", + "transactionHash": "0x8aaea11800531d34415cda91003165c7b075dbf01dc6a87e208c5bba20c727f1", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/eigenda-poc-preprod/ProtocolVersions.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/ProtocolVersions.json new file mode 100644 index 000000000000..eddf69277ebf --- /dev/null +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/ProtocolVersions.json @@ -0,0 +1,407 @@ +{ + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "version", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "enum ProtocolVersions.UpdateType", + "name": "updateType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "ConfigUpdate", + "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": "RECOMMENDED_SLOT", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REQUIRED_SLOT", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "ProtocolVersion", + "name": "_required", + "type": "uint256" + }, + { + "internalType": "ProtocolVersion", + "name": "_recommended", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "recommended", + "outputs": [ + { + "internalType": "ProtocolVersion", + "name": "out_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "required", + "outputs": [ + { + "internalType": "ProtocolVersion", + "name": "out_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "ProtocolVersion", + "name": "_recommended", + "type": "uint256" + } + ], + "name": "setRecommended", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "ProtocolVersion", + "name": "_required", + "type": "uint256" + } + ], + "name": "setRequired", + "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" + } + ], + "address": "0xD63D25161BEE26F973FBCa51366E69Ca8103c48d", + "args": [], + "bytecode": "0x60806040523480156200001157600080fd5b506200002261dead60008062000028565b6200051c565b600054610100900460ff1615808015620000495750600054600160ff909116105b8062000079575062000066306200017e60201b6200053f1760201c565b15801562000079575060005460ff166001145b620000e25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000106576000805461ff0019166101001790555b620001106200018d565b6200011b84620001f5565b620001268362000274565b620001318262000324565b801562000178576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b602482015260008051602062000f4f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d9565b620001f362000385565b565b620001ff620003ec565b6001600160a01b038116620002665760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620000d9565b620002718162000448565b50565b620002ba620002a560017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16200049e565b60001b826200049a60201b6200055b1760201c565b600081604051602001620002d091815260200190565b60408051601f19818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051620003189190620004c4565b60405180910390a35050565b62000355620002a560017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6200049e565b6000816040516020016200036b91815260200190565b60408051601f1981840301815291905290506001620002e5565b600054610100900460ff16620003e15760405162461bcd60e51b815260206004820152602b602482015260008051602062000f4f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d9565b620001f33362000448565b6033546001600160a01b03163314620001f35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620000d9565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b9055565b600082821015620004bf57634e487b7160e01b600052601160045260246000fd5b500390565b600060208083528351808285015260005b81811015620004f357858101830151858201604001528201620004d5565b8181111562000506576000604083870101525b50601f01601f1916929092016040019392505050565b610a23806200052c6000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", + "devdoc": { + "version": 1, + "kind": "dev", + "methods": { + "initialize(address,uint256,uint256)": { + "params": { + "_owner": "Initial owner of the contract.", + "_recommended": "Recommended protocol version to operate on thi chain.", + "_required": "Required protocol version to operate on this chain." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "recommended()": { + "returns": { + "out_": "Recommended protocol version to sync to the head of the chain." + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "required()": { + "returns": { + "out_": "Required protocol version to sync to the head of the chain." + } + }, + "setRecommended(uint256)": { + "params": { + "_recommended": "New recommended protocol version." + } + }, + "setRequired(uint256)": { + "params": { + "_required": "New required protocol version." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "events": { + "ConfigUpdate(uint256,uint8,bytes)": { + "params": { + "data": "Encoded update data.", + "updateType": "Type of update.", + "version": "ProtocolVersion version." + } + } + }, + "title": "ProtocolVersions" + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"enum ProtocolVersions.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ConfigUpdate\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RECOMMENDED_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"REQUIRED_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"ProtocolVersion\",\"name\":\"_required\",\"type\":\"uint256\"},{\"internalType\":\"ProtocolVersion\",\"name\":\"_recommended\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"recommended\",\"outputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"out_\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"required\",\"outputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"out_\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"_recommended\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setRecommended\"},{\"inputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"_required\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setRequired\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"initialize(address,uint256,uint256)\":{\"params\":{\"_owner\":\"Initial owner of the contract.\",\"_recommended\":\"Recommended protocol version to operate on thi chain.\",\"_required\":\"Required protocol version to operate on this chain.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"recommended()\":{\"returns\":{\"out_\":\"Recommended protocol version to sync to the head of the chain.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"required()\":{\"returns\":{\"out_\":\"Required protocol version to sync to the head of the chain.\"}},\"setRecommended(uint256)\":{\"params\":{\"_recommended\":\"New recommended protocol version.\"}},\"setRequired(uint256)\":{\"params\":{\"_required\":\"New required protocol version.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"RECOMMENDED_SLOT()\":{\"notice\":\"Storage slot that the recommended protocol version is stored at.\"},\"REQUIRED_SLOT()\":{\"notice\":\"Storage slot that the required protocol version is stored at.\"},\"VERSION()\":{\"notice\":\"Version identifier, used for upgrades.\"},\"constructor\":{\"notice\":\"Constructs the ProtocolVersion contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)` A zero version is considered empty and is ignored by nodes.\"},\"initialize(address,uint256,uint256)\":{\"notice\":\"Initializer.\"},\"recommended()\":{\"notice\":\"High level getter for the recommended protocol version.\"},\"required()\":{\"notice\":\"High level getter for the required protocol version.\"},\"setRecommended(uint256)\":{\"notice\":\"Updates the recommended protocol version. Can only be called by the owner.\"},\"setRequired(uint256)\":{\"notice\":\"Updates the required protocol version. Can only be called by the owner.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/ProtocolVersions.sol\":\"ProtocolVersions\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ProtocolVersions.sol\":{\"keccak256\":\"0x83182a9b71c648f9a5ee7a3b572df4e038857c464379aa9cf45d0a74325acf83\",\"urls\":[\"bzz-raw://69573d2de0bdcdb6f1d34a49072976de0738344372f8364104b2fd35e3dca367\",\"dweb:/ipfs/QmU1UJV14EJtDsa96d7jX4giPgUtPPJB9S2xGddarDjZj2\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 1, + "receipt": "", + "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "storageLayout": { + "storage": [ + { + "astId": 44768, + "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 44771, + "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 46299, + "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 44640, + "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 44760, + "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568", + "base": "t_uint256" + }, + "t_array(t_uint256)50_storage": { + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600", + "base": "t_uint256" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "transactionHash": "0xf8f4c784af07a6a102587e19f3d7534e83874413fa35efdac85eaea14fdcf56b", + "userdoc": { + "version": 1, + "kind": "user", + "methods": { + "RECOMMENDED_SLOT()": { + "notice": "Storage slot that the recommended protocol version is stored at." + }, + "REQUIRED_SLOT()": { + "notice": "Storage slot that the required protocol version is stored at." + }, + "VERSION()": { + "notice": "Version identifier, used for upgrades." + }, + "constructor": { + "notice": "Constructs the ProtocolVersion contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)` A zero version is considered empty and is ignored by nodes." + }, + "initialize(address,uint256,uint256)": { + "notice": "Initializer." + }, + "recommended()": { + "notice": "High level getter for the recommended protocol version." + }, + "required()": { + "notice": "High level getter for the required protocol version." + }, + "setRecommended(uint256)": { + "notice": "Updates the recommended protocol version. Can only be called by the owner." + }, + "setRequired(uint256)": { + "notice": "Updates the required protocol version. Can only be called by the owner." + }, + "version()": { + "notice": "Semantic version." + } + }, + "events": { + "ConfigUpdate(uint256,uint8,bytes)": { + "notice": "Emitted when configuration is updated." + } + }, + "notice": "The ProtocolVersions contract is used to manage superchain protocol version information." + } +} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/sepolia/ProtocolVersionsProxy.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/ProtocolVersionsProxy.json similarity index 78% rename from packages/contracts-bedrock/deployments/sepolia/ProtocolVersionsProxy.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/ProtocolVersionsProxy.json index 740dae175468..c61e7fbbcc79 100644 --- a/packages/contracts-bedrock/deployments/sepolia/ProtocolVersionsProxy.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/ProtocolVersionsProxy.json @@ -128,9 +128,9 @@ "type": "receive" } ], - "address": "0x79ADD5713B383DAa0a138d3C4780C7A1804a8090", + "address": "0x6935D091e231fd08448EF3C6888ad153415661e3", "args": [ - "0x0a08E04c73f22C65D6dBFF20f87171240df6E519" + "0x1814DBa2CC02DC44408ec2E05a680bC3dD24Cf4B" ], "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", @@ -185,44 +185,44 @@ }, "title": "Proxy" }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xc56de5e39cd44eaeb93f0f8705dd07f4a89f66d5c186522532cf899a104cdbca\",\"urls\":[\"bzz-raw://cd1b595148fa62a798343a23e3330e79fef7d747f039d664482044be9ec0ccf3\",\"dweb:/ipfs/QmeAft6H9wbc9zZZ3prtRaBGGzcPy9yExKAhZHjp1iZ8UF\"],\"license\":\"MIT\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", "numDeployments": 1, "receipt": { - "transactionHash": "0xb38d6a449755fc90b9b4a96879c896aa21e156b0363aabec9959d71b554c1060", - "transactionIndex": "0x1", - "blockHash": "0x294120db9ff8f22f5d95b4bcc5dffb23af2cc6f7b02ce2726de0de377f10e03a", - "blockNumber": "0x44bb94", - "from": "0x0a08E04c73f22C65D6dBFF20f87171240df6E519", + "transactionHash": "0xe8ecc054daff5e543e87075031bd90d885ed3d04e97b48d37e19a4772e281e60", + "transactionIndex": "0x9", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "from": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", "to": null, - "cumulativeGasUsed": "0x135be4", + "cumulativeGasUsed": "0x3e1bcc", "gasUsed": "0x80250", - "contractAddress": "0x79ADD5713B383DAa0a138d3C4780C7A1804a8090", + "contractAddress": "0x6935D091e231fd08448EF3C6888ad153415661e3", "logs": [ { - "address": "0x79ADD5713B383DAa0a138d3C4780C7A1804a8090", + "address": "0x6935D091e231fd08448EF3C6888ad153415661e3", "topics": [ "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a08e04c73f22c65d6dbff20f87171240df6e519", - "blockHash": "0x294120db9ff8f22f5d95b4bcc5dffb23af2cc6f7b02ce2726de0de377f10e03a", - "blockNumber": "0x44bb94", - "transactionHash": "0xb38d6a449755fc90b9b4a96879c896aa21e156b0363aabec9959d71b554c1060", - "transactionIndex": "0x1", - "logIndex": "0x4", + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001814dba2cc02dc44408ec2e05a680bc3dd24cf4b", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0xe8ecc054daff5e543e87075031bd90d885ed3d04e97b48d37e19a4772e281e60", + "transactionIndex": "0x9", + "logIndex": "0x10", "removed": false } ], "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000800000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000400000000000004000000000000000000000000000000000000000000000000000000000000000000000000", "type": "0x2", - "effectiveGasPrice": "0xb2d05e10" + "effectiveGasPrice": "0xb2d05e0a" }, "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [], "types": {} }, - "transactionHash": "0xb38d6a449755fc90b9b4a96879c896aa21e156b0363aabec9959d71b554c1060", + "transactionHash": "0xe8ecc054daff5e543e87075031bd90d885ed3d04e97b48d37e19a4772e281e60", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/sepolia/ProxyAdmin.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/ProxyAdmin.json similarity index 86% rename from packages/contracts-bedrock/deployments/sepolia/ProxyAdmin.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/ProxyAdmin.json index 670cdc4a4504..a19a54af1350 100644 --- a/packages/contracts-bedrock/deployments/sepolia/ProxyAdmin.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/ProxyAdmin.json @@ -305,9 +305,9 @@ "type": "function" } ], - "address": "0x189aBAAaa82DfC015A588A7dbaD6F13b1D3485Bc", + "address": "0x1814DBa2CC02DC44408ec2E05a680bC3dD24Cf4B", "args": [ - "0x18394B52d3Cb931dfA76F63251919D051953413d" + "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68" ], "bytecode": "0x60806040523480156200001157600080fd5b5060405162001a5f38038062001a5f8339810160408190526200003491620000a1565b6200003f3362000051565b6200004a8162000051565b50620000d3565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215620000b457600080fd5b81516001600160a01b0381168114620000cc57600080fd5b9392505050565b61197c80620000e36000396000f3fe60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a", "deployedBytecode": "0x60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a", @@ -400,60 +400,60 @@ }, "title": "ProxyAdmin" }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"addressManager\",\"outputs\":[{\"internalType\":\"contract AddressManager\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_newAdmin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeProxyAdmin\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getProxyAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getProxyImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"implementationName\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"isUpgrading\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"proxyType\",\"outputs\":[{\"internalType\":\"enum ProxyAdmin.ProxyType\",\"name\":\"\",\"type\":\"uint8\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setAddress\"},{\"inputs\":[{\"internalType\":\"contract AddressManager\",\"name\":\"_address\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setAddressManager\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setImplementationName\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"enum ProxyAdmin.ProxyType\",\"name\":\"_type\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setProxyType\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_upgrading\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setUpgrading\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgrade\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeAndCall\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"changeProxyAdmin(address,address)\":{\"params\":{\"_newAdmin\":\"Address of the new proxy admin.\",\"_proxy\":\"Address of the proxy to update.\"}},\"constructor\":{\"params\":{\"_owner\":\"Address of the initial owner of this contract.\"}},\"getProxyAdmin(address)\":{\"params\":{\"_proxy\":\"Address of the proxy to get the admin of.\"},\"returns\":{\"_0\":\"Address of the admin of the proxy.\"}},\"getProxyImplementation(address)\":{\"params\":{\"_proxy\":\"Address of the proxy to get the implementation of.\"},\"returns\":{\"_0\":\"Address of the implementation of the proxy.\"}},\"isUpgrading()\":{\"custom:legacy\":\"@notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening.\",\"returns\":{\"_0\":\"Whether or not there is an upgrade going on. May not actually tell you whether an upgrade is going on, since we don't currently plan to use this variable for anything other than a legacy indicator to fix a UX bug in the ChugSplash proxy.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAddress(string,address)\":{\"custom:legacy\":\"@notice Set an address in the address manager. Since only the owner of the AddressManager can directly modify addresses and the ProxyAdmin will own the AddressManager, this gives the owner of the ProxyAdmin the ability to modify addresses directly.\",\"params\":{\"_address\":\"Address to attach to the given name.\",\"_name\":\"Name to set within the AddressManager.\"}},\"setAddressManager(address)\":{\"params\":{\"_address\":\"Address of the AddressManager.\"}},\"setImplementationName(address,string)\":{\"params\":{\"_address\":\"Address of the ResolvedDelegateProxy.\",\"_name\":\"Name of the implementation for the proxy.\"}},\"setProxyType(address,uint8)\":{\"params\":{\"_address\":\"Address of the proxy.\",\"_type\":\"Type of the proxy.\"}},\"setUpgrading(bool)\":{\"custom:legacy\":\"@notice Set the upgrading status for the Chugsplash proxy type.\",\"params\":{\"_upgrading\":\"Whether or not the system is upgrading.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgrade(address,address)\":{\"params\":{\"_implementation\":\"Address of the new implementation address.\",\"_proxy\":\"Address of the proxy to upgrade.\"}},\"upgradeAndCall(address,address,bytes)\":{\"params\":{\"_data\":\"Data to trigger the new implementation with.\",\"_implementation\":\"Address of the new implementation address.\",\"_proxy\":\"Address of the proxy to upgrade.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addressManager()\":{\"notice\":\"The address of the address manager, this is required to manage the ResolvedDelegateProxy type.\"},\"changeProxyAdmin(address,address)\":{\"notice\":\"Updates the admin of the given proxy address.\"},\"getProxyAdmin(address)\":{\"notice\":\"Returns the admin of the given proxy address.\"},\"getProxyImplementation(address)\":{\"notice\":\"Returns the implementation of the given proxy address.\"},\"implementationName(address)\":{\"notice\":\"A reverse mapping of addresses to names held in the AddressManager. This must be manually kept up to date with changes in the AddressManager for this contract to be able to work as an admin for the ResolvedDelegateProxy type.\"},\"proxyType(address)\":{\"notice\":\"A mapping of proxy types, used for backwards compatibility.\"},\"setAddressManager(address)\":{\"notice\":\"Set the address of the AddressManager. This is required to manage legacy ResolvedDelegateProxy type proxy contracts.\"},\"setImplementationName(address,string)\":{\"notice\":\"Sets the implementation name for a given address. Only required for ResolvedDelegateProxy type proxies that have an implementation name.\"},\"setProxyType(address,uint8)\":{\"notice\":\"Sets the proxy type for a given address. Only required for non-standard (legacy) proxy types.\"},\"upgrade(address,address)\":{\"notice\":\"Changes a proxy's implementation contract.\"},\"upgradeAndCall(address,address,bytes)\":{\"notice\":\"Changes a proxy's implementation contract and delegatecalls the new implementation with some given data. Useful for atomic upgrade-and-initialize calls.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/ProxyAdmin.sol\":\"ProxyAdmin\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"src/legacy/AddressManager.sol\":{\"keccak256\":\"0x1fcb990df6473f7fa360d5924d62d39ce2ca97d45668e3901e5405cfbe598b19\",\"urls\":[\"bzz-raw://9d08358b60dea54dbc32e988a1bb7ea909488063eaae3c5ae28a322f125c9b34\",\"dweb:/ipfs/QmZPQwdjLh9gaamNAoTUmWwwbRKj3yHovBYfnTPnfuKvUt\"],\"license\":\"MIT\"},\"src/legacy/L1ChugSplashProxy.sol\":{\"keccak256\":\"0x102ea9c1eac2bbc071e38fdcc8d92deda3e7f32dc72d57fa3fe315cef354a5fe\",\"urls\":[\"bzz-raw://42efc6f277dd5f9ed874dbc6e214d481a26cc71751d505a75b44d86ecf8e4815\",\"dweb:/ipfs/QmUZLYii4uBr5JrWz8NTaaYkX56VvygKSqziKqGHuzM2Wr\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0x783aed9ff90b38a9898be5fb18699b3b249f012bc2c33f6537e1ab9f6444478f\",\"urls\":[\"bzz-raw://b119b1b68874f4d92a89cc05a4f0d25da73a959747a81e26739739a52895b844\",\"dweb:/ipfs/QmbKZqMd6CsM7annE7bCXcCi72syJAX3qtuFNPEGMCp13W\"],\"license\":\"MIT\"},\"src/universal/ProxyAdmin.sol\":{\"keccak256\":\"0xacc43c5531cdb4ab39a66f7cadce5237fe50524d09ec9a247556501832e95b39\",\"urls\":[\"bzz-raw://ddfbac05eb0a63ae377e50e1fdb477558f68eed2bc38ccbd6faae866b0cdebfa\",\"dweb:/ipfs/QmcRkpxA5cGKboA2dFCqBUBLZy1U911arKBnPygcp2xXFi\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 4, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"addressManager\",\"outputs\":[{\"internalType\":\"contract AddressManager\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_newAdmin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeProxyAdmin\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getProxyAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getProxyImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"implementationName\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"isUpgrading\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"proxyType\",\"outputs\":[{\"internalType\":\"enum ProxyAdmin.ProxyType\",\"name\":\"\",\"type\":\"uint8\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setAddress\"},{\"inputs\":[{\"internalType\":\"contract AddressManager\",\"name\":\"_address\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setAddressManager\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setImplementationName\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"enum ProxyAdmin.ProxyType\",\"name\":\"_type\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setProxyType\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_upgrading\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setUpgrading\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgrade\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeAndCall\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"changeProxyAdmin(address,address)\":{\"params\":{\"_newAdmin\":\"Address of the new proxy admin.\",\"_proxy\":\"Address of the proxy to update.\"}},\"constructor\":{\"params\":{\"_owner\":\"Address of the initial owner of this contract.\"}},\"getProxyAdmin(address)\":{\"params\":{\"_proxy\":\"Address of the proxy to get the admin of.\"},\"returns\":{\"_0\":\"Address of the admin of the proxy.\"}},\"getProxyImplementation(address)\":{\"params\":{\"_proxy\":\"Address of the proxy to get the implementation of.\"},\"returns\":{\"_0\":\"Address of the implementation of the proxy.\"}},\"isUpgrading()\":{\"custom:legacy\":\"@notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening.\",\"returns\":{\"_0\":\"Whether or not there is an upgrade going on. May not actually tell you whether an upgrade is going on, since we don't currently plan to use this variable for anything other than a legacy indicator to fix a UX bug in the ChugSplash proxy.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAddress(string,address)\":{\"custom:legacy\":\"@notice Set an address in the address manager. Since only the owner of the AddressManager can directly modify addresses and the ProxyAdmin will own the AddressManager, this gives the owner of the ProxyAdmin the ability to modify addresses directly.\",\"params\":{\"_address\":\"Address to attach to the given name.\",\"_name\":\"Name to set within the AddressManager.\"}},\"setAddressManager(address)\":{\"params\":{\"_address\":\"Address of the AddressManager.\"}},\"setImplementationName(address,string)\":{\"params\":{\"_address\":\"Address of the ResolvedDelegateProxy.\",\"_name\":\"Name of the implementation for the proxy.\"}},\"setProxyType(address,uint8)\":{\"params\":{\"_address\":\"Address of the proxy.\",\"_type\":\"Type of the proxy.\"}},\"setUpgrading(bool)\":{\"custom:legacy\":\"@notice Set the upgrading status for the Chugsplash proxy type.\",\"params\":{\"_upgrading\":\"Whether or not the system is upgrading.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgrade(address,address)\":{\"params\":{\"_implementation\":\"Address of the new implementation address.\",\"_proxy\":\"Address of the proxy to upgrade.\"}},\"upgradeAndCall(address,address,bytes)\":{\"params\":{\"_data\":\"Data to trigger the new implementation with.\",\"_implementation\":\"Address of the new implementation address.\",\"_proxy\":\"Address of the proxy to upgrade.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addressManager()\":{\"notice\":\"The address of the address manager, this is required to manage the ResolvedDelegateProxy type.\"},\"changeProxyAdmin(address,address)\":{\"notice\":\"Updates the admin of the given proxy address.\"},\"getProxyAdmin(address)\":{\"notice\":\"Returns the admin of the given proxy address.\"},\"getProxyImplementation(address)\":{\"notice\":\"Returns the implementation of the given proxy address.\"},\"implementationName(address)\":{\"notice\":\"A reverse mapping of addresses to names held in the AddressManager. This must be manually kept up to date with changes in the AddressManager for this contract to be able to work as an admin for the ResolvedDelegateProxy type.\"},\"proxyType(address)\":{\"notice\":\"A mapping of proxy types, used for backwards compatibility.\"},\"setAddressManager(address)\":{\"notice\":\"Set the address of the AddressManager. This is required to manage legacy ResolvedDelegateProxy type proxy contracts.\"},\"setImplementationName(address,string)\":{\"notice\":\"Sets the implementation name for a given address. Only required for ResolvedDelegateProxy type proxies that have an implementation name.\"},\"setProxyType(address,uint8)\":{\"notice\":\"Sets the proxy type for a given address. Only required for non-standard (legacy) proxy types.\"},\"upgrade(address,address)\":{\"notice\":\"Changes a proxy's implementation contract.\"},\"upgradeAndCall(address,address,bytes)\":{\"notice\":\"Changes a proxy's implementation contract and delegatecalls the new implementation with some given data. Useful for atomic upgrade-and-initialize calls.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/ProxyAdmin.sol\":\"ProxyAdmin\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/legacy/AddressManager.sol\":{\"keccak256\":\"0x1fcb990df6473f7fa360d5924d62d39ce2ca97d45668e3901e5405cfbe598b19\",\"urls\":[\"bzz-raw://9d08358b60dea54dbc32e988a1bb7ea909488063eaae3c5ae28a322f125c9b34\",\"dweb:/ipfs/QmZPQwdjLh9gaamNAoTUmWwwbRKj3yHovBYfnTPnfuKvUt\"],\"license\":\"MIT\"},\"src/legacy/L1ChugSplashProxy.sol\":{\"keccak256\":\"0xdde5626645fa217ad3a37805c4c3012e4251de01df868aae73b986f5d03cdb23\",\"urls\":[\"bzz-raw://a99fd0ec440c17c826465001dc88c5185dd41dc72396254fdd3cdfcc84aeae8c\",\"dweb:/ipfs/QmStHuecN89zBL8FH9SUK1TtkyYwfzMY2KkQaFJLHZLuyA\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"},\"src/universal/ProxyAdmin.sol\":{\"keccak256\":\"0xd15267cf5ed8c24d5a0f2099b8d470178d7ad729db52be16232eb143620b8dcf\",\"urls\":[\"bzz-raw://e9300ee0feb16fcf6c06ee541f2496eac533256bd97f79fe2128527d2f096894\",\"dweb:/ipfs/Qme3Md8pGSnjkG94WFXUdi5UF3a47BTQgKCdGmTKcMgcRa\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 1, "receipt": { - "transactionHash": "0x33d37db3eb5f0dae04a7654e3d6028af3270ca60e9904ff61a5d3b84178d1231", + "transactionHash": "0xc22202a854bff271593001c49a15f6a63e5939a2be1deedb9f54b558295294c7", "transactionIndex": "0x3", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "from": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", "to": null, - "cumulativeGasUsed": "0x38e1ae", + "cumulativeGasUsed": "0x21a0c4", "gasUsed": "0x16a4b9", - "contractAddress": "0x189aBAAaa82DfC015A588A7dbaD6F13b1D3485Bc", + "contractAddress": "0x1814DBa2CC02DC44408ec2E05a680bC3dD24Cf4B", "logs": [ { - "address": "0x189aBAAaa82DfC015A588A7dbaD6F13b1D3485Bc", + "address": "0x1814DBa2CC02DC44408ec2E05a680bC3dD24Cf4B", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000018394b52d3cb931dfa76f63251919d051953413d" + "0x00000000000000000000000055351d70ac0602ed7a41d77735dc6ae1b7cbac68" ], "data": "0x", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "transactionHash": "0x33d37db3eb5f0dae04a7654e3d6028af3270ca60e9904ff61a5d3b84178d1231", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0xc22202a854bff271593001c49a15f6a63e5939a2be1deedb9f54b558295294c7", "transactionIndex": "0x3", - "logIndex": "0x3", + "logIndex": "0x6", "removed": false }, { - "address": "0x189aBAAaa82DfC015A588A7dbaD6F13b1D3485Bc", + "address": "0x1814DBa2CC02DC44408ec2E05a680bC3dD24Cf4B", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x00000000000000000000000018394b52d3cb931dfa76f63251919d051953413d", - "0x00000000000000000000000018394b52d3cb931dfa76f63251919d051953413d" + "0x00000000000000000000000055351d70ac0602ed7a41d77735dc6ae1b7cbac68", + "0x00000000000000000000000055351d70ac0602ed7a41d77735dc6ae1b7cbac68" ], "data": "0x", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "transactionHash": "0x33d37db3eb5f0dae04a7654e3d6028af3270ca60e9904ff61a5d3b84178d1231", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0xc22202a854bff271593001c49a15f6a63e5939a2be1deedb9f54b558295294c7", "transactionIndex": "0x3", - "logIndex": "0x4", + "logIndex": "0x7", "removed": false } ], "status": "0x1", - "logsBloom": "0x00000100000000000000000000000000000000000000000000800000000000000000000000000000000000010000000000000000000000040000000000000000000000000000000000000000000000000001000000008000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "logsBloom": "0x00000000000000020000000000000010000000000000000000840000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001001000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000100000000", "type": "0x2", - "effectiveGasPrice": "0xbec78df7" + "effectiveGasPrice": "0xb2d05e0a" }, "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [ { - "astId": 31896, + "astId": 47128, "contract": "src/universal/ProxyAdmin.sol:ProxyAdmin", "label": "_owner", "offset": 0, @@ -461,15 +461,15 @@ "type": "t_address" }, { - "astId": 70723, + "astId": 95696, "contract": "src/universal/ProxyAdmin.sol:ProxyAdmin", "label": "proxyType", "offset": 0, "slot": "1", - "type": "t_mapping(t_address,t_enum(ProxyType)70717)" + "type": "t_mapping(t_address,t_enum(ProxyType)95690)" }, { - "astId": 70728, + "astId": 95701, "contract": "src/universal/ProxyAdmin.sol:ProxyAdmin", "label": "implementationName", "offset": 0, @@ -477,15 +477,15 @@ "type": "t_mapping(t_address,t_string_storage)" }, { - "astId": 70732, + "astId": 95705, "contract": "src/universal/ProxyAdmin.sol:ProxyAdmin", "label": "addressManager", "offset": 0, "slot": "3", - "type": "t_contract(AddressManager)62454" + "type": "t_contract(AddressManager)87201" }, { - "astId": 70735, + "astId": 95708, "contract": "src/universal/ProxyAdmin.sol:ProxyAdmin", "label": "upgrading", "offset": 20, @@ -504,22 +504,22 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(AddressManager)62454": { + "t_contract(AddressManager)87201": { "encoding": "inplace", "label": "contract AddressManager", "numberOfBytes": "20" }, - "t_enum(ProxyType)70717": { + "t_enum(ProxyType)95690": { "encoding": "inplace", "label": "enum ProxyAdmin.ProxyType", "numberOfBytes": "1" }, - "t_mapping(t_address,t_enum(ProxyType)70717)": { + "t_mapping(t_address,t_enum(ProxyType)95690)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => enum ProxyAdmin.ProxyType)", "numberOfBytes": "32", - "value": "t_enum(ProxyType)70717" + "value": "t_enum(ProxyType)95690" }, "t_mapping(t_address,t_string_storage)": { "encoding": "mapping", @@ -535,7 +535,7 @@ } } }, - "transactionHash": "0x33d37db3eb5f0dae04a7654e3d6028af3270ca60e9904ff61a5d3b84178d1231", + "transactionHash": "0xc22202a854bff271593001c49a15f6a63e5939a2be1deedb9f54b558295294c7", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/goerli/SuperchainConfig.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/SuperchainConfig.json similarity index 89% rename from packages/contracts-bedrock/deployments/goerli/SuperchainConfig.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/SuperchainConfig.json index 1a7d0429a39d..d2920f935388 100644 --- a/packages/contracts-bedrock/deployments/goerli/SuperchainConfig.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/SuperchainConfig.json @@ -155,7 +155,7 @@ "type": "function" } ], - "address": "0xE4268D9E82DfD3cf280170A14829262C513c9459", + "address": "0xD9147100812c75457492CA37b979aD912ee522d1", "args": [], "bytecode": "0x608060405234801561001057600080fd5b5061001b6000610020565b610273565b600054610100900460ff16158080156100405750600054600160ff909116105b8061006b57506100593061014860201b6106221760201c565b15801561006b575060005460ff166001145b6100d25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff1916600117905580156100f5576000805461ff0019166101001790555b6100fe82610157565b8015610144576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b61019861018560017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe696101f9565b60001b826101f560201b61063e1760201c565b6000604080516001600160a01b03841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb910160408051601f19818403018152908290526101ea9161021e565b60405180910390a250565b9055565b60008282101561021957634e487b7160e01b600052601160045260246000fd5b500390565b600060208083528351808285015260005b8181101561024b5785810183015185820160400152820161022f565b8181111561025d576000604083870101525b50601f01601f1916929092016040019392505050565b610901806102826000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80636da663551161005b5780636da663551461012a5780637fbf7b6a1461013d578063c23a451a14610153578063c4d66de81461015b57600080fd5b80633f4ba83a1461008d578063452a93201461009757806354fd4d50146100c95780635c975abb14610112575b600080fd5b61009561016e565b005b61009f610294565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101056040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c09190610768565b61011a6102cd565b60405190151581526020016100c0565b6100956101383660046107b1565b610305565b610145610435565b6040519081526020016100c0565b610145610463565b610095610169366004610880565b61048e565b610176610294565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b76108b6565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b60006102c86102c460017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe696108b6565b5490565b905090565b60006102fd6102c460017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b76108b6565b600114905090565b61030d610294565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6103fb6103f560017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b76108b6565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161042a9190610768565b60405180910390a150565b61046060017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b76108b6565b81565b61046060017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe696108b6565b600054610100900460ff16158080156104ae5750600054600160ff909116105b806104c85750303b1580156104c8575060005460ff166001145b610554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6105bb82610642565b801561061e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61067561067060017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe696108b6565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106f291610768565b60405180910390a250565b6000815180845260005b8181101561072357602081850181015186830182015201610707565b81811115610735576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061077b60208301846106fd565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156107c357600080fd5b813567ffffffffffffffff808211156107db57600080fd5b818401915084601f8301126107ef57600080fd5b81358181111561080157610801610782565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561084757610847610782565b8160405282815287602084870101111561086057600080fd5b826020860160208301376000928101602001929092525095945050505050565b60006020828403121561089257600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461077b57600080fd5b6000828210156108ef577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c80636da663551161005b5780636da663551461012a5780637fbf7b6a1461013d578063c23a451a14610153578063c4d66de81461015b57600080fd5b80633f4ba83a1461008d578063452a93201461009757806354fd4d50146100c95780635c975abb14610112575b600080fd5b61009561016e565b005b61009f610294565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101056040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c09190610768565b61011a6102cd565b60405190151581526020016100c0565b6100956101383660046107b1565b610305565b610145610435565b6040519081526020016100c0565b610145610463565b610095610169366004610880565b61048e565b610176610294565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b76108b6565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b60006102c86102c460017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe696108b6565b5490565b905090565b60006102fd6102c460017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b76108b6565b600114905090565b61030d610294565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6103fb6103f560017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b76108b6565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161042a9190610768565b60405180910390a150565b61046060017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b76108b6565b81565b61046060017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe696108b6565b600054610100900460ff16158080156104ae5750600054600160ff909116105b806104c85750303b1580156104c8575060005460ff166001145b610554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6105bb82610642565b801561061e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61067561067060017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe696108b6565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106f291610768565b60405180910390a250565b6000815180845260005b8181101561072357602081850181015186830182015201610707565b81811115610735576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061077b60208301846106fd565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156107c357600080fd5b813567ffffffffffffffff808211156107db57600080fd5b818401915084601f8301126107ef57600080fd5b81358181111561080157610801610782565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561084757610847610782565b8160405282815287602084870101111561086057600080fd5b826020860160208301376000928101602001929092525095945050505050565b60006020828403121561089257600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461077b57600080fd5b6000828210156108ef577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", @@ -191,55 +191,12 @@ }, "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"enum SuperchainConfig.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ConfigUpdate\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"identifier\",\"type\":\"string\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Paused\",\"anonymous\":false},{\"inputs\":[],\"type\":\"event\",\"name\":\"Unpaused\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"GUARDIAN_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"PAUSED_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"guardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"guardian_\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guardian\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_identifier\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"pause\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"unpause\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"initialize(address)\":{\"params\":{\"_guardian\":\"Address of the guardian, can pause the OptimismPortal.\"}},\"pause(string)\":{\"params\":{\"_identifier\":\"(Optional) A string to identify provenance of the pause transaction.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"GUARDIAN_SLOT()\":{\"notice\":\"The address of the guardian, which can pause withdrawals from the System. It can only be modified by an upgrade.\"},\"PAUSED_SLOT()\":{\"notice\":\"Whether or not the Superchain is paused.\"},\"constructor\":{\"notice\":\"Constructs the SuperchainConfig contract.\"},\"guardian()\":{\"notice\":\"Getter for the guardian address.\"},\"initialize(address)\":{\"notice\":\"Initializer.\"},\"pause(string)\":{\"notice\":\"Pauses withdrawals.\"},\"paused()\":{\"notice\":\"Getter for the current paused status.\"},\"unpause()\":{\"notice\":\"Unpauses withdrawals.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/SuperchainConfig.sol\":\"SuperchainConfig\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x9d6e33ea5d12b78fd3cb024ed5863c8c14cb55977cbab56fd9ce5c309918afc6\",\"urls\":[\"bzz-raw://d8545d6255ed4428b168a3547d6935043e5b680344d650fd090293ba36b59897\",\"dweb:/ipfs/QmPLVma7kqTTgbAHtxog2MGD7S2Wr8nd42MhBcfJ5yyF4W\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", "numDeployments": 1, - "receipt": { - "transactionHash": "0x8303ba7f8a872f0e031c3489978ca94bc1100ca5c7db98fe1700fa4a641be5e5", - "transactionIndex": "0x1e", - "blockHash": "0x619e583c5d1d2aead1a8243ad552f2dbff0a52409c24b7036267a5c7b8e5c6e7", - "blockNumber": "0x9b04b9", - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "cumulativeGasUsed": "0x473df9", - "gasUsed": "0x8fa4b", - "contractAddress": "0xE4268D9E82DfD3cf280170A14829262C513c9459", - "logs": [ - { - "address": "0xE4268D9E82DfD3cf280170A14829262C513c9459", - "topics": [ - "0x7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x619e583c5d1d2aead1a8243ad552f2dbff0a52409c24b7036267a5c7b8e5c6e7", - "blockNumber": "0x9b04b9", - "transactionHash": "0x8303ba7f8a872f0e031c3489978ca94bc1100ca5c7db98fe1700fa4a641be5e5", - "transactionIndex": "0x1e", - "logIndex": "0xd", - "removed": false - }, - { - "address": "0xE4268D9E82DfD3cf280170A14829262C513c9459", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "blockHash": "0x619e583c5d1d2aead1a8243ad552f2dbff0a52409c24b7036267a5c7b8e5c6e7", - "blockNumber": "0x9b04b9", - "transactionHash": "0x8303ba7f8a872f0e031c3489978ca94bc1100ca5c7db98fe1700fa4a641be5e5", - "transactionIndex": "0x1e", - "logIndex": "0xe", - "removed": false - } - ], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000800000000000000000000000040000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000002000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000040000000000000040000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "type": "0x2", - "effectiveGasPrice": "0xb2d05e10" - }, + "receipt": "", "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [ { - "astId": 45395, + "astId": 47332, "contract": "src/L1/SuperchainConfig.sol:SuperchainConfig", "label": "_initialized", "offset": 0, @@ -247,7 +204,7 @@ "type": "t_uint8" }, { - "astId": 45398, + "astId": 47335, "contract": "src/L1/SuperchainConfig.sol:SuperchainConfig", "label": "_initializing", "offset": 1, @@ -268,7 +225,7 @@ } } }, - "transactionHash": "0x8303ba7f8a872f0e031c3489978ca94bc1100ca5c7db98fe1700fa4a641be5e5", + "transactionHash": "0x076008ef12ec5b66f3f3f8cfdbf83956b37331b41cd749e4e8d1f2e3f8abf847", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/sepolia/SuperchainConfigProxy.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/SuperchainConfigProxy.json similarity index 94% rename from packages/contracts-bedrock/deployments/sepolia/SuperchainConfigProxy.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/SuperchainConfigProxy.json index b5a264971124..0530409b7984 100644 --- a/packages/contracts-bedrock/deployments/sepolia/SuperchainConfigProxy.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/SuperchainConfigProxy.json @@ -128,9 +128,9 @@ "type": "receive" } ], - "address": "0xC2Be75506d5724086DEB7245bd260Cc9753911Be", + "address": "0x6C92dFd49b2eA9e709c042B43961d81a42D900c7", "args": [ - "0x189aBAAaa82DfC015A588A7dbaD6F13b1D3485Bc" + "0x1814DBa2CC02DC44408ec2E05a680bC3dD24Cf4B" ], "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", @@ -188,41 +188,41 @@ "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", "numDeployments": 1, "receipt": { - "transactionHash": "0xe6b7f301f0a9fdf14159b4c6e2299b3d7e6f763c8f592a4749c935a5ebc30e0e", - "transactionIndex": "0xa", - "blockHash": "0x3852e8f5c0e20f139502bf0c23697a0fcdf6f816f9a2378e82749de27dca5bae", - "blockNumber": "0x49e12c", - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", + "transactionHash": "0x6dd20bd1e1a5d0aca30fb7de4b375dc82883e79fa95a170048b9f0d67435e5e9", + "transactionIndex": "0x6", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "from": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", "to": null, - "cumulativeGasUsed": "0x13ce59", + "cumulativeGasUsed": "0x2ac678", "gasUsed": "0x80250", - "contractAddress": "0xC2Be75506d5724086DEB7245bd260Cc9753911Be", + "contractAddress": "0x6C92dFd49b2eA9e709c042B43961d81a42D900c7", "logs": [ { - "address": "0xC2Be75506d5724086DEB7245bd260Cc9753911Be", + "address": "0x6C92dFd49b2eA9e709c042B43961d81a42D900c7", "topics": [ "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000189abaaaa82dfc015a588a7dbad6f13b1d3485bc", - "blockHash": "0x3852e8f5c0e20f139502bf0c23697a0fcdf6f816f9a2378e82749de27dca5bae", - "blockNumber": "0x49e12c", - "transactionHash": "0xe6b7f301f0a9fdf14159b4c6e2299b3d7e6f763c8f592a4749c935a5ebc30e0e", - "transactionIndex": "0xa", - "logIndex": "0x4", + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001814dba2cc02dc44408ec2e05a680bc3dd24cf4b", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0x6dd20bd1e1a5d0aca30fb7de4b375dc82883e79fa95a170048b9f0d67435e5e9", + "transactionIndex": "0x6", + "logIndex": "0x9", "removed": false } ], "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000008000000000000000000000000000000000000000", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000001000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000002000000400000000000", "type": "0x2", - "effectiveGasPrice": "0xb985e174" + "effectiveGasPrice": "0xb2d05e0a" }, "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [], "types": {} }, - "transactionHash": "0xe6b7f301f0a9fdf14159b4c6e2299b3d7e6f763c8f592a4749c935a5ebc30e0e", + "transactionHash": "0x6dd20bd1e1a5d0aca30fb7de4b375dc82883e79fa95a170048b9f0d67435e5e9", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/sepolia/SystemConfig.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/SystemConfig.json similarity index 93% rename from packages/contracts-bedrock/deployments/sepolia/SystemConfig.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/SystemConfig.json index a68783822f3a..7d47449332e8 100644 --- a/packages/contracts-bedrock/deployments/sepolia/SystemConfig.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/SystemConfig.json @@ -503,7 +503,7 @@ "type": "function" } ], - "address": "0xce77d580E0bEFbb1561376A722217017651B9dbF", + "address": "0x9686BD1487bb261a5140026E3fD06b36819221f2", "args": [ "0x000000000000000000000000000000000000dEaD", "0", @@ -603,127 +603,127 @@ }, "title": "SystemConfig" }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"},{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"enum SystemConfig.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ConfigUpdate\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"UNSAFE_BLOCK_SIGNER_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"batcherHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"gasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"},{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"minimumGasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"overhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"resourceConfig\",\"outputs\":[{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"scalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setBatcherHash\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setGasConfig\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setGasLimit\"},{\"inputs\":[{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setResourceConfig\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setUnsafeBlockSigner\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"unsafeBlockSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_batcherHash\":\"Initial batcher hash.\",\"_config\":\"Initial resource config.\",\"_gasLimit\":\"Initial gas limit.\",\"_overhead\":\"Initial overhead value.\",\"_owner\":\"Initial owner of the contract.\",\"_scalar\":\"Initial scalar value.\",\"_unsafeBlockSigner\":\"Initial unsafe block signer address.\"}},\"initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128))\":{\"params\":{\"_batcherHash\":\"Initial batcher hash.\",\"_config\":\"Initial ResourceConfig.\",\"_gasLimit\":\"Initial gas limit.\",\"_overhead\":\"Initial overhead value.\",\"_owner\":\"Initial owner of the contract.\",\"_scalar\":\"Initial scalar value.\",\"_unsafeBlockSigner\":\"Initial unsafe block signer address.\"}},\"minimumGasLimit()\":{\"returns\":{\"_0\":\"uint64 Minimum gas limit.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"resourceConfig()\":{\"returns\":{\"_0\":\"ResourceConfig\"}},\"setBatcherHash(bytes32)\":{\"params\":{\"_batcherHash\":\"New batcher hash.\"}},\"setGasConfig(uint256,uint256)\":{\"params\":{\"_overhead\":\"New overhead value.\",\"_scalar\":\"New scalar value.\"}},\"setGasLimit(uint64)\":{\"params\":{\"_gasLimit\":\"New gas limit.\"}},\"setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))\":{\"params\":{\"_config\":\"The new resource config values.\"}},\"setUnsafeBlockSigner(address)\":{\"params\":{\"_unsafeBlockSigner\":\"New unsafe block signer address.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsafeBlockSigner()\":{\"returns\":{\"addr_\":\"Address of the unsafe block signer.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"UNSAFE_BLOCK_SIGNER_SLOT()\":{\"notice\":\"Storage slot that the unsafe block signer is stored at. Storing it at this deterministic storage slot allows for decoupling the storage layout from the way that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value.\"},\"VERSION()\":{\"notice\":\"Version identifier, used for upgrades.\"},\"batcherHash()\":{\"notice\":\"Identifier for the batcher. For version 1 of this configuration, this is represented as an address left-padded with zeros to 32 bytes.\"},\"constructor\":{\"notice\":\"Constructs the SystemConfig contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)`\"},\"gasLimit()\":{\"notice\":\"L2 block gas limit.\"},\"initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128))\":{\"notice\":\"Initializer. The resource config must be set before the require check.\"},\"minimumGasLimit()\":{\"notice\":\"Returns the minimum L2 gas limit that can be safely set for the system to operate. The L2 gas limit must be larger than or equal to the amount of gas that is allocated for deposits per block plus the amount of gas that is allocated for the system transaction. This function is used to determine if changes to parameters are safe.\"},\"overhead()\":{\"notice\":\"Fixed L2 gas overhead. Used as part of the L2 fee calculation.\"},\"resourceConfig()\":{\"notice\":\"A getter for the resource config. Ensures that the struct is returned instead of a tuple.\"},\"scalar()\":{\"notice\":\"Dynamic L2 gas overhead. Used as part of the L2 fee calculation.\"},\"setBatcherHash(bytes32)\":{\"notice\":\"Updates the batcher hash. Can only be called by the owner.\"},\"setGasConfig(uint256,uint256)\":{\"notice\":\"Updates gas config. Can only be called by the owner.\"},\"setGasLimit(uint64)\":{\"notice\":\"Updates the L2 gas limit. Can only be called by the owner.\"},\"setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))\":{\"notice\":\"An external setter for the resource config. In the future, this method may emit an event that the `op-node` picks up for when the resource config is changed.\"},\"setUnsafeBlockSigner(address)\":{\"notice\":\"Updates the unsafe block signer address. Can only be called by the owner.\"},\"unsafeBlockSigner()\":{\"notice\":\"High level getter for the unsafe block signer address. Unsafe blocks can be propagated across the p2p network if they are signed by the key corresponding to this address.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/SystemConfig.sol\":\"SystemConfig\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0x4a03e4a42900cecb4e923b92a7a10edb367347260bf38a937ce31826f1644330\",\"urls\":[\"bzz-raw://29dbfb9f323dfb9c4ce23c27a876dd7caddda6a3a5d483429cda433021d9f145\",\"dweb:/ipfs/QmZff2htQcExkwLdoGZ6e81zCFeGZV8oXgn4BhpW8Sccq7\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x5c6346060b3e8d3bf4289b20fd869a66fbad8f69dc0b095845f990066b6c4d2b\",\"urls\":[\"bzz-raw://161277a9935cc567d76096a9a3ffc54632fda2020e02b4c5dc5541bfad3d166f\",\"dweb:/ipfs/QmXiDP2A4MPsN9VDNf9YbqbQQTU2J5tffWbJHg45f9LJyN\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x7ce27a05552aa69afa6b2ab6684dfe99f27366cf8ef2046baeb1fb62fff0022f\",\"urls\":[\"bzz-raw://a6a24f3ed56681720707a5ab0372fd67fcb1a4f6fb072c7140cda28bdb70f269\",\"dweb:/ipfs/QmW9uTpUULV4xmP7A7MoBDeDhVfQgmJG5qVUFGtXxWpWWK\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 8, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"},{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"enum SystemConfig.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ConfigUpdate\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"UNSAFE_BLOCK_SIGNER_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"batcherHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"gasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"},{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"minimumGasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"overhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"resourceConfig\",\"outputs\":[{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"scalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setBatcherHash\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setGasConfig\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setGasLimit\"},{\"inputs\":[{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setResourceConfig\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setUnsafeBlockSigner\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"unsafeBlockSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_batcherHash\":\"Initial batcher hash.\",\"_config\":\"Initial resource config.\",\"_gasLimit\":\"Initial gas limit.\",\"_overhead\":\"Initial overhead value.\",\"_owner\":\"Initial owner of the contract.\",\"_scalar\":\"Initial scalar value.\",\"_unsafeBlockSigner\":\"Initial unsafe block signer address.\"}},\"initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128))\":{\"params\":{\"_batcherHash\":\"Initial batcher hash.\",\"_config\":\"Initial ResourceConfig.\",\"_gasLimit\":\"Initial gas limit.\",\"_overhead\":\"Initial overhead value.\",\"_owner\":\"Initial owner of the contract.\",\"_scalar\":\"Initial scalar value.\",\"_unsafeBlockSigner\":\"Initial unsafe block signer address.\"}},\"minimumGasLimit()\":{\"returns\":{\"_0\":\"uint64 Minimum gas limit.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"resourceConfig()\":{\"returns\":{\"_0\":\"ResourceConfig\"}},\"setBatcherHash(bytes32)\":{\"params\":{\"_batcherHash\":\"New batcher hash.\"}},\"setGasConfig(uint256,uint256)\":{\"params\":{\"_overhead\":\"New overhead value.\",\"_scalar\":\"New scalar value.\"}},\"setGasLimit(uint64)\":{\"params\":{\"_gasLimit\":\"New gas limit.\"}},\"setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))\":{\"params\":{\"_config\":\"The new resource config values.\"}},\"setUnsafeBlockSigner(address)\":{\"params\":{\"_unsafeBlockSigner\":\"New unsafe block signer address.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsafeBlockSigner()\":{\"returns\":{\"addr_\":\"Address of the unsafe block signer.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"UNSAFE_BLOCK_SIGNER_SLOT()\":{\"notice\":\"Storage slot that the unsafe block signer is stored at. Storing it at this deterministic storage slot allows for decoupling the storage layout from the way that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value.\"},\"VERSION()\":{\"notice\":\"Version identifier, used for upgrades.\"},\"batcherHash()\":{\"notice\":\"Identifier for the batcher. For version 1 of this configuration, this is represented as an address left-padded with zeros to 32 bytes.\"},\"constructor\":{\"notice\":\"Constructs the SystemConfig contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)`\"},\"gasLimit()\":{\"notice\":\"L2 block gas limit.\"},\"initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128))\":{\"notice\":\"Initializer. The resource config must be set before the require check.\"},\"minimumGasLimit()\":{\"notice\":\"Returns the minimum L2 gas limit that can be safely set for the system to operate. The L2 gas limit must be larger than or equal to the amount of gas that is allocated for deposits per block plus the amount of gas that is allocated for the system transaction. This function is used to determine if changes to parameters are safe.\"},\"overhead()\":{\"notice\":\"Fixed L2 gas overhead. Used as part of the L2 fee calculation.\"},\"resourceConfig()\":{\"notice\":\"A getter for the resource config. Ensures that the struct is returned instead of a tuple.\"},\"scalar()\":{\"notice\":\"Dynamic L2 gas overhead. Used as part of the L2 fee calculation.\"},\"setBatcherHash(bytes32)\":{\"notice\":\"Updates the batcher hash. Can only be called by the owner.\"},\"setGasConfig(uint256,uint256)\":{\"notice\":\"Updates gas config. Can only be called by the owner.\"},\"setGasLimit(uint64)\":{\"notice\":\"Updates the L2 gas limit. Can only be called by the owner.\"},\"setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))\":{\"notice\":\"An external setter for the resource config. In the future, this method may emit an event that the `op-node` picks up for when the resource config is changed.\"},\"setUnsafeBlockSigner(address)\":{\"notice\":\"Updates the unsafe block signer address. Can only be called by the owner.\"},\"unsafeBlockSigner()\":{\"notice\":\"High level getter for the unsafe block signer address. Unsafe blocks can be propagated across the p2p network if they are signed by the key corresponding to this address.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/SystemConfig.sol\":\"SystemConfig\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x5c6346060b3e8d3bf4289b20fd869a66fbad8f69dc0b095845f990066b6c4d2b\",\"urls\":[\"bzz-raw://161277a9935cc567d76096a9a3ffc54632fda2020e02b4c5dc5541bfad3d166f\",\"dweb:/ipfs/QmXiDP2A4MPsN9VDNf9YbqbQQTU2J5tffWbJHg45f9LJyN\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 1, "receipt": { - "transactionHash": "0x4cabb0ac950d5b765094f37eaac61f1873919d272f7be2c70b21e9dae2f2b56f", - "transactionIndex": "0x12", - "blockHash": "0x6b36d67b55b6e74f9d3f8cf93380be49442229bd6ca7f6222d2905896042dad5", - "blockNumber": "0x49d203", - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", + "transactionHash": "0x1d65341a66312bfd96886ebd056da8795cf5b6edf526fd9098902790313409ad", + "transactionIndex": "0x19", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "from": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", "to": null, - "cumulativeGasUsed": "0x6cc314", + "cumulativeGasUsed": "0x130508a", "gasUsed": "0x14f3ca", - "contractAddress": "0xce77d580E0bEFbb1561376A722217017651B9dbF", + "contractAddress": "0x9686BD1487bb261a5140026E3fD06b36819221f2", "logs": [ { - "address": "0xce77d580E0bEFbb1561376A722217017651B9dbF", + "address": "0x9686BD1487bb261a5140026E3fD06b36819221f2", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000354f3f4ecdca5e0a7ace08d71348cdc1dab48960" + "0x00000000000000000000000055351d70ac0602ed7a41d77735dc6ae1b7cbac68" ], "data": "0x", - "blockHash": "0x6b36d67b55b6e74f9d3f8cf93380be49442229bd6ca7f6222d2905896042dad5", - "blockNumber": "0x49d203", - "transactionHash": "0x4cabb0ac950d5b765094f37eaac61f1873919d272f7be2c70b21e9dae2f2b56f", - "transactionIndex": "0x12", - "logIndex": "0x4", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0x1d65341a66312bfd96886ebd056da8795cf5b6edf526fd9098902790313409ad", + "transactionIndex": "0x19", + "logIndex": "0x27", "removed": false }, { - "address": "0xce77d580E0bEFbb1561376A722217017651B9dbF", + "address": "0x9686BD1487bb261a5140026E3fD06b36819221f2", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x000000000000000000000000354f3f4ecdca5e0a7ace08d71348cdc1dab48960", + "0x00000000000000000000000055351d70ac0602ed7a41d77735dc6ae1b7cbac68", "0x000000000000000000000000000000000000000000000000000000000000dead" ], "data": "0x", - "blockHash": "0x6b36d67b55b6e74f9d3f8cf93380be49442229bd6ca7f6222d2905896042dad5", - "blockNumber": "0x49d203", - "transactionHash": "0x4cabb0ac950d5b765094f37eaac61f1873919d272f7be2c70b21e9dae2f2b56f", - "transactionIndex": "0x12", - "logIndex": "0x5", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0x1d65341a66312bfd96886ebd056da8795cf5b6edf526fd9098902790313409ad", + "transactionIndex": "0x19", + "logIndex": "0x28", "removed": false }, { - "address": "0xce77d580E0bEFbb1561376A722217017651B9dbF", + "address": "0x9686BD1487bb261a5140026E3fD06b36819221f2", "topics": [ "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x6b36d67b55b6e74f9d3f8cf93380be49442229bd6ca7f6222d2905896042dad5", - "blockNumber": "0x49d203", - "transactionHash": "0x4cabb0ac950d5b765094f37eaac61f1873919d272f7be2c70b21e9dae2f2b56f", - "transactionIndex": "0x12", - "logIndex": "0x6", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0x1d65341a66312bfd96886ebd056da8795cf5b6edf526fd9098902790313409ad", + "transactionIndex": "0x19", + "logIndex": "0x29", "removed": false }, { - "address": "0xce77d580E0bEFbb1561376A722217017651B9dbF", + "address": "0x9686BD1487bb261a5140026E3fD06b36819221f2", "topics": [ "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000001" ], "data": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x6b36d67b55b6e74f9d3f8cf93380be49442229bd6ca7f6222d2905896042dad5", - "blockNumber": "0x49d203", - "transactionHash": "0x4cabb0ac950d5b765094f37eaac61f1873919d272f7be2c70b21e9dae2f2b56f", - "transactionIndex": "0x12", - "logIndex": "0x7", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0x1d65341a66312bfd96886ebd056da8795cf5b6edf526fd9098902790313409ad", + "transactionIndex": "0x19", + "logIndex": "0x2a", "removed": false }, { - "address": "0xce77d580E0bEFbb1561376A722217017651B9dbF", + "address": "0x9686BD1487bb261a5140026E3fD06b36819221f2", "topics": [ "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000002" ], "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000001406f40", - "blockHash": "0x6b36d67b55b6e74f9d3f8cf93380be49442229bd6ca7f6222d2905896042dad5", - "blockNumber": "0x49d203", - "transactionHash": "0x4cabb0ac950d5b765094f37eaac61f1873919d272f7be2c70b21e9dae2f2b56f", - "transactionIndex": "0x12", - "logIndex": "0x8", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0x1d65341a66312bfd96886ebd056da8795cf5b6edf526fd9098902790313409ad", + "transactionIndex": "0x19", + "logIndex": "0x2b", "removed": false }, { - "address": "0xce77d580E0bEFbb1561376A722217017651B9dbF", + "address": "0x9686BD1487bb261a5140026E3fD06b36819221f2", "topics": [ "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000003" ], "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x6b36d67b55b6e74f9d3f8cf93380be49442229bd6ca7f6222d2905896042dad5", - "blockNumber": "0x49d203", - "transactionHash": "0x4cabb0ac950d5b765094f37eaac61f1873919d272f7be2c70b21e9dae2f2b56f", - "transactionIndex": "0x12", - "logIndex": "0x9", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0x1d65341a66312bfd96886ebd056da8795cf5b6edf526fd9098902790313409ad", + "transactionIndex": "0x19", + "logIndex": "0x2c", "removed": false }, { - "address": "0xce77d580E0bEFbb1561376A722217017651B9dbF", + "address": "0x9686BD1487bb261a5140026E3fD06b36819221f2", "topics": [ "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" ], "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "blockHash": "0x6b36d67b55b6e74f9d3f8cf93380be49442229bd6ca7f6222d2905896042dad5", - "blockNumber": "0x49d203", - "transactionHash": "0x4cabb0ac950d5b765094f37eaac61f1873919d272f7be2c70b21e9dae2f2b56f", - "transactionIndex": "0x12", - "logIndex": "0xa", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0x1d65341a66312bfd96886ebd056da8795cf5b6edf526fd9098902790313409ad", + "transactionIndex": "0x19", + "logIndex": "0x2d", "removed": false } ], "status": "0x1", - "logsBloom": "0x04000800000010000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000020008000000000000040000000000000000000000000000000000000001000000040000000000000000000000000000020000000000000000800800000000000000000000000000000000400200000000000000000004060000000020000000000080000000000000000000000000010000000000000100000400000000000000800000000000000000400000000400000000000000000000040000000000000000000000000000000060000000000000000000000000000000000000000000008000000000008000000000", + "logsBloom": "0x04000000000010020000000000000000000000000000000000840000000000000000000000000000000000000000000000000000020008000000000000040000000000000000000008000000000000000001001000040000000000000000000000000000020000000000000000000800000000000000000000000000002000400000000000000000000004040000000000000000000080000000000000000000000000000000000000000100000400000000000000800000000000000000400010000400000000000000000000040000000000000000000000000000000060000000000000000000000000000000000000000000008000000000008000000000", "type": "0x2", - "effectiveGasPrice": "0xb872d82e" + "effectiveGasPrice": "0xb2d05e0a" }, "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { @@ -745,7 +745,7 @@ "type": "t_bool" }, { - "astId": 45196, + "astId": 46299, "contract": "src/L1/SystemConfig.sol:SystemConfig", "label": "__gap", "offset": 0, @@ -769,7 +769,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 75120, + "astId": 77561, "contract": "src/L1/SystemConfig.sol:SystemConfig", "label": "overhead", "offset": 0, @@ -777,7 +777,7 @@ "type": "t_uint256" }, { - "astId": 75123, + "astId": 77564, "contract": "src/L1/SystemConfig.sol:SystemConfig", "label": "scalar", "offset": 0, @@ -785,7 +785,7 @@ "type": "t_uint256" }, { - "astId": 75126, + "astId": 77567, "contract": "src/L1/SystemConfig.sol:SystemConfig", "label": "batcherHash", "offset": 0, @@ -793,7 +793,7 @@ "type": "t_bytes32" }, { - "astId": 75129, + "astId": 77570, "contract": "src/L1/SystemConfig.sol:SystemConfig", "label": "gasLimit", "offset": 0, @@ -801,12 +801,12 @@ "type": "t_uint64" }, { - "astId": 75133, + "astId": 77574, "contract": "src/L1/SystemConfig.sol:SystemConfig", "label": "_resourceConfig", "offset": 0, "slot": "105", - "type": "t_struct(ResourceConfig)74551_storage" + "type": "t_struct(ResourceConfig)77016_storage" } ], "types": { @@ -837,13 +837,13 @@ "label": "bytes32", "numberOfBytes": "32" }, - "t_struct(ResourceConfig)74551_storage": { + "t_struct(ResourceConfig)77016_storage": { "encoding": "inplace", "label": "struct ResourceMetering.ResourceConfig", "numberOfBytes": "32", "members": [ { - "astId": 74540, + "astId": 77005, "contract": "src/L1/SystemConfig.sol:SystemConfig", "label": "maxResourceLimit", "offset": 0, @@ -851,7 +851,7 @@ "type": "t_uint32" }, { - "astId": 74542, + "astId": 77007, "contract": "src/L1/SystemConfig.sol:SystemConfig", "label": "elasticityMultiplier", "offset": 4, @@ -859,7 +859,7 @@ "type": "t_uint8" }, { - "astId": 74544, + "astId": 77009, "contract": "src/L1/SystemConfig.sol:SystemConfig", "label": "baseFeeMaxChangeDenominator", "offset": 5, @@ -867,7 +867,7 @@ "type": "t_uint8" }, { - "astId": 74546, + "astId": 77011, "contract": "src/L1/SystemConfig.sol:SystemConfig", "label": "minimumBaseFee", "offset": 6, @@ -875,7 +875,7 @@ "type": "t_uint32" }, { - "astId": 74548, + "astId": 77013, "contract": "src/L1/SystemConfig.sol:SystemConfig", "label": "systemTxMaxGas", "offset": 10, @@ -883,7 +883,7 @@ "type": "t_uint32" }, { - "astId": 74550, + "astId": 77015, "contract": "src/L1/SystemConfig.sol:SystemConfig", "label": "maximumBaseFee", "offset": 14, @@ -919,7 +919,7 @@ } } }, - "transactionHash": "0x4cabb0ac950d5b765094f37eaac61f1873919d272f7be2c70b21e9dae2f2b56f", + "transactionHash": "0x1d65341a66312bfd96886ebd056da8795cf5b6edf526fd9098902790313409ad", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/sepolia/SystemConfigProxy.json b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/SystemConfigProxy.json similarity index 52% rename from packages/contracts-bedrock/deployments/sepolia/SystemConfigProxy.json rename to packages/contracts-bedrock/deployments/eigenda-poc-preprod/SystemConfigProxy.json index 8016b8fe9dda..e44b2bb4c85d 100644 --- a/packages/contracts-bedrock/deployments/sepolia/SystemConfigProxy.json +++ b/packages/contracts-bedrock/deployments/eigenda-poc-preprod/SystemConfigProxy.json @@ -128,12 +128,12 @@ "type": "receive" } ], - "address": "0x034edD2A225f7f429A63E0f1D2084B9E0A93b538", + "address": "0x843264FdBAfF9fB1F156892d8055992f57838705", "args": [ - "0x189aBAAaa82DfC015A588A7dbaD6F13b1D3485Bc" + "0x1814DBa2CC02DC44408ec2E05a680bC3dD24Cf4B" ], - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "bytecode": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", "devdoc": { "version": 1, "kind": "dev", @@ -185,44 +185,44 @@ }, "title": "Proxy" }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"src/universal/Proxy.sol\":{\"keccak256\":\"0x783aed9ff90b38a9898be5fb18699b3b249f012bc2c33f6537e1ab9f6444478f\",\"urls\":[\"bzz-raw://b119b1b68874f4d92a89cc05a4f0d25da73a959747a81e26739739a52895b844\",\"dweb:/ipfs/QmbKZqMd6CsM7annE7bCXcCi72syJAX3qtuFNPEGMCp13W\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 4, + "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/universal/Proxy.sol\":{\"keccak256\":\"0xa6b50d6843b92a5917a1c0677ab395159616ec6bb0e9746a31eac8423396e706\",\"urls\":[\"bzz-raw://6fe8b988623864daad44bd7354380744169b13aca4b257918ee07b665b18db0b\",\"dweb:/ipfs/QmRPLJ4rEX3MsgBZ9fFKKXQTWVnXH4drwB2arxdV7GWWat\"],\"license\":\"MIT\"}},\"version\":1}", + "numDeployments": 1, "receipt": { - "transactionHash": "0x951deaff679124ded80e96135b9b44c726e2d831eb1ab792e5673225aa778c9a", - "transactionIndex": "0x7", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", + "transactionHash": "0xfcd7e3d3d226cd75b496af3ab5ee562db864d4b0bbf4831337554aa7a6fc242a", + "transactionIndex": "0xe", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "from": "0x55351d70ac0602eD7A41d77735Dc6aE1b7CbAc68", "to": null, - "cumulativeGasUsed": "0x5191a8", - "gasUsed": "0x7feb8", - "contractAddress": "0x034edD2A225f7f429A63E0f1D2084B9E0A93b538", + "cumulativeGasUsed": "0x62f953", + "gasUsed": "0x80250", + "contractAddress": "0x843264FdBAfF9fB1F156892d8055992f57838705", "logs": [ { - "address": "0x034edD2A225f7f429A63E0f1D2084B9E0A93b538", + "address": "0x843264FdBAfF9fB1F156892d8055992f57838705", "topics": [ "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000189abaaaa82dfc015a588a7dbad6f13b1d3485bc", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "transactionHash": "0x951deaff679124ded80e96135b9b44c726e2d831eb1ab792e5673225aa778c9a", - "transactionIndex": "0x7", - "logIndex": "0x7", + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001814dba2cc02dc44408ec2e05a680bc3dd24cf4b", + "blockHash": "0xca1fd85fc40a8348ae1e5d0a30eb6ae33ef1d1c9fd39383ce9564066e97d8979", + "blockNumber": "0x9b2e7b", + "transactionHash": "0xfcd7e3d3d226cd75b496af3ab5ee562db864d4b0bbf4831337554aa7a6fc242a", + "transactionIndex": "0xe", + "logIndex": "0x1f", "removed": false } ], "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000004000000000000000000000000000000000000000000000000", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000040000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000800000000000000000000000000000000000000000000000000000000000000000000000000000", "type": "0x2", - "effectiveGasPrice": "0xbec78df7" + "effectiveGasPrice": "0xb2d05e0a" }, "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "storageLayout": { "storage": [], "types": {} }, - "transactionHash": "0x951deaff679124ded80e96135b9b44c726e2d831eb1ab792e5673225aa778c9a", + "transactionHash": "0xfcd7e3d3d226cd75b496af3ab5ee562db864d4b0bbf4831337554aa7a6fc242a", "userdoc": { "version": 1, "kind": "user", diff --git a/packages/contracts-bedrock/deployments/goerli/AddressManager.json b/packages/contracts-bedrock/deployments/goerli/AddressManager.json deleted file mode 100644 index b8a050ae83e7..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/AddressManager.json +++ /dev/null @@ -1,237 +0,0 @@ -{ - "address": "0xa6f73589243a6A7a9023b1Fa0651b1d89c177111", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "indexed": false, - "internalType": "address", - "name": "_newAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "_oldAddress", - "type": "address" - } - ], - "name": "AddressSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - } - ], - "name": "getAddress", - "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": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "address", - "name": "_address", - "type": "address" - } - ], - "name": "setAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x5048d305a449374d0903384f23c112696557878bf4b1ac52e8e7530898cc03e8", - "receipt": { - "to": null, - "from": "0x3a605B442055DF2898E18cF518feb2e2A6BD0D31", - "contractAddress": "0xa6f73589243a6A7a9023b1Fa0651b1d89c177111", - "transactionIndex": 6, - "gasUsed": "463444", - "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000001000000000000000001000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000200200000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x59b45b1099d0a874e3bbb89d53ec856f7a7ae3a98013b5be0d3ceff8172240b3", - "transactionHash": "0x5048d305a449374d0903384f23c112696557878bf4b1ac52e8e7530898cc03e8", - "logs": [ - { - "transactionIndex": 6, - "blockNumber": 7017076, - "transactionHash": "0x5048d305a449374d0903384f23c112696557878bf4b1ac52e8e7530898cc03e8", - "address": "0xa6f73589243a6A7a9023b1Fa0651b1d89c177111", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000003a605b442055df2898e18cf518feb2e2a6bd0d31" - ], - "data": "0x", - "logIndex": 103, - "blockHash": "0x59b45b1099d0a874e3bbb89d53ec856f7a7ae3a98013b5be0d3ceff8172240b3" - } - ], - "blockNumber": 7017076, - "cumulativeGasUsed": "3261100", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "5f4e2d2e170708499f05344e000df330", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_newAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_oldAddress\",\"type\":\"address\"}],\"name\":\"AddressSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"getAddress\",\"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\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getAddress(string)\":{\"params\":{\"_name\":\"Name to retrieve an address for.\"},\"returns\":{\"_0\":\"Address associated with the given name.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAddress(string,address)\":{\"params\":{\"_address\":\"Address to associate with the name.\",\"_name\":\"String name to associate an address with.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"title\":\"Lib_AddressManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getAddress(string)\":{\"notice\":\"Retrieves the address associated with a given name.\"},\"setAddress(string,address)\":{\"notice\":\"Changes the address associated with a particular name.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/resolver/Lib_AddressManager.sol\":\"Lib_AddressManager\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\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 _setOwner(_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 _setOwner(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 _setOwner(newOwner);\\n }\\n\\n function _setOwner(address newOwner) private {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x6bb804a310218875e89d12c053e94a13a4607cdf7cc2052f3e52bd32a0dc50a1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\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\":\"0x90565a39ae45c80f0468dc96c7b20d0afc3055f344c8203a0c9258239f350b9f\",\"license\":\"MIT\"},\"contracts/libraries/resolver/Lib_AddressManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/* External Imports */\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n/**\\n * @title Lib_AddressManager\\n */\\ncontract Lib_AddressManager is Ownable {\\n /**********\\n * Events *\\n **********/\\n\\n event AddressSet(string indexed _name, address _newAddress, address _oldAddress);\\n\\n /*************\\n * Variables *\\n *************/\\n\\n mapping(bytes32 => address) private addresses;\\n\\n /********************\\n * Public Functions *\\n ********************/\\n\\n /**\\n * Changes the address associated with a particular name.\\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 * Retrieves the address associated with a given name.\\n * @param _name Name to retrieve an address for.\\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 * Internal Functions *\\n **********************/\\n\\n /**\\n * Computes the hash of a name.\\n * @param _name Name to compute a hash for.\\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\",\"keccak256\":\"0xcde9b29429d512c549f7c1b8a033f161fa71c18cda08b241748663854196ae14\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6107028061007e6000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80639b2ea4bd116100505780639b2ea4bd146100b9578063bf40fac1146100cc578063f2fde38b146100df57600080fd5b8063715018a61461006c5780638da5cb5b14610076575b600080fd5b6100746100f2565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100746100c73660046105e4565b610184565b6100906100da366004610632565b6102d0565b6100746100ed36600461066f565b61030c565b60005473ffffffffffffffffffffffffffffffffffffffff163314610178576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b610182600061043c565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610205576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161016f565b6000610210836104b1565b60008181526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff8681167fffffffffffffffffffffffff000000000000000000000000000000000000000083161790925591519293501690610273908590610691565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b6000600160006102df846104b1565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1692915050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461038d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161016f565b73ffffffffffffffffffffffffffffffffffffffff8116610430576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161016f565b6104398161043c565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816040516020016104c49190610691565b604051602081830303815290604052805190602001209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261052157600080fd5b813567ffffffffffffffff8082111561053c5761053c6104e1565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610582576105826104e1565b8160405283815286602085880101111561059b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146105df57600080fd5b919050565b600080604083850312156105f757600080fd5b823567ffffffffffffffff81111561060e57600080fd5b61061a85828601610510565b925050610629602084016105bb565b90509250929050565b60006020828403121561064457600080fd5b813567ffffffffffffffff81111561065b57600080fd5b61066784828501610510565b949350505050565b60006020828403121561068157600080fd5b61068a826105bb565b9392505050565b6000825160005b818110156106b25760208186018101518583015201610698565b818111156106c1576000828501525b50919091019291505056fea2646970667358221220882d6a267e1fbcc015c1726b422a6847e08c6be7e987e8b5ec1f7e85aa5095bb64736f6c63430008090033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c80639b2ea4bd116100505780639b2ea4bd146100b9578063bf40fac1146100cc578063f2fde38b146100df57600080fd5b8063715018a61461006c5780638da5cb5b14610076575b600080fd5b6100746100f2565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100746100c73660046105e4565b610184565b6100906100da366004610632565b6102d0565b6100746100ed36600461066f565b61030c565b60005473ffffffffffffffffffffffffffffffffffffffff163314610178576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b610182600061043c565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610205576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161016f565b6000610210836104b1565b60008181526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff8681167fffffffffffffffffffffffff000000000000000000000000000000000000000083161790925591519293501690610273908590610691565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b6000600160006102df846104b1565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1692915050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461038d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161016f565b73ffffffffffffffffffffffffffffffffffffffff8116610430576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161016f565b6104398161043c565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816040516020016104c49190610691565b604051602081830303815290604052805190602001209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261052157600080fd5b813567ffffffffffffffff8082111561053c5761053c6104e1565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610582576105826104e1565b8160405283815286602085880101111561059b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146105df57600080fd5b919050565b600080604083850312156105f757600080fd5b823567ffffffffffffffff81111561060e57600080fd5b61061a85828601610510565b925050610629602084016105bb565b90509250929050565b60006020828403121561064457600080fd5b813567ffffffffffffffff81111561065b57600080fd5b61066784828501610510565b949350505050565b60006020828403121561068157600080fd5b61068a826105bb565b9392505050565b6000825160005b818110156106b25760208186018101518583015201610698565b818111156106c1576000828501525b50919091019291505056fea2646970667358221220882d6a267e1fbcc015c1726b422a6847e08c6be7e987e8b5ec1f7e85aa5095bb64736f6c63430008090033", - "devdoc": { - "kind": "dev", - "methods": { - "getAddress(string)": { - "params": { - "_name": "Name to retrieve an address for." - }, - "returns": { - "_0": "Address associated with the given name." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "setAddress(string,address)": { - "params": { - "_address": "Address to associate with the name.", - "_name": "String name to associate an address with." - } - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - } - }, - "title": "Lib_AddressManager", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "getAddress(string)": { - "notice": "Retrieves the address associated with a given name." - }, - "setAddress(string,address)": { - "notice": "Changes the address associated with a particular name." - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 393, - "contract": "contracts/libraries/resolver/Lib_AddressManager.sol:Lib_AddressManager", - "label": "_owner", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 7017, - "contract": "contracts/libraries/resolver/Lib_AddressManager.sol:Lib_AddressManager", - "label": "addresses", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_bytes32,t_address)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes32,t_address)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => address)", - "numberOfBytes": "32", - "value": "t_address" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/CheckBalanceHigh.json b/packages/contracts-bedrock/deployments/goerli/CheckBalanceHigh.json deleted file mode 100644 index 2ca0130add0c..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/CheckBalanceHigh.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "address": "0x7eC64a8a591bFf829ff6C8be76074D540ACb813F", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "threshold", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct CheckBalanceHigh.Params", - "name": "params", - "type": "tuple" - } - ], - "name": "_EventToExposeStructInABI__Params", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_params", - "type": "bytes" - } - ], - "name": "check", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x1d1543b42c1a5404d3b1794a399239d1e3f40c10e865d0f2e4a362a349d30a6e", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 76, - "gasUsed": "176628", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x0b10b7612a1de5326e045069eb60151e2fa615ce7d342b13acb14ba165edddb1", - "transactionHash": "0x1d1543b42c1a5404d3b1794a399239d1e3f40c10e865d0f2e4a362a349d30a6e", - "logs": [], - "blockNumber": 8182666, - "cumulativeGasUsed": "10050194", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "2373b7ba869baea4fec58e6e7f7b8988", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"struct CheckBalanceHigh.Params\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"_EventToExposeStructInABI__Params\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_params\",\"type\":\"bytes\"}],\"name\":\"check\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"_EventToExposeStructInABI__Params((address,uint256))\":{\"params\":{\"params\":\"Parameters to encode.\"}}},\"kind\":\"dev\",\"methods\":{\"check(bytes)\":{\"params\":{\"_params\":\"Encoded parameters for the drip check.\"},\"returns\":{\"_0\":\"Whether the drip should be executed.\"}}},\"title\":\"CheckBalanceHigh\",\"version\":1},\"userdoc\":{\"events\":{\"_EventToExposeStructInABI__Params((address,uint256))\":{\"notice\":\"External event used to help client-side tooling encode parameters.\"}},\"kind\":\"user\",\"methods\":{\"check(bytes)\":{\"notice\":\"Checks whether a drip should be executable.\"}},\"notice\":\"DripCheck for checking if an account's balance is above a given threshold.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/dripchecks/CheckBalanceHigh.sol\":\"CheckBalanceHigh\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n /**\\n * @notice Checks whether a drip should be executable.\\n *\\n * @param _params Encoded parameters for the drip check.\\n *\\n * @return Whether the drip should be executed.\\n */\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb52c89360566b2963dfd82cb2cc23f0c3ce4503a69e8563878e8aa80b6c60b3f\",\"license\":\"MIT\"},\"contracts/universal/drippie/dripchecks/CheckBalanceHigh.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.16;\\n\\nimport { IDripCheck } from \\\"../IDripCheck.sol\\\";\\n\\n/**\\n * @title CheckBalanceHigh\\n * @notice DripCheck for checking if an account's balance is above a given threshold.\\n */\\ncontract CheckBalanceHigh is IDripCheck {\\n struct Params {\\n address target;\\n uint256 threshold;\\n }\\n\\n /**\\n * @notice External event used to help client-side tooling encode parameters.\\n *\\n * @param params Parameters to encode.\\n */\\n event _EventToExposeStructInABI__Params(Params params);\\n\\n /**\\n * @inheritdoc IDripCheck\\n */\\n function check(bytes memory _params) external view returns (bool) {\\n Params memory params = abi.decode(_params, (Params));\\n\\n // Check target balance is above threshold.\\n return params.target.balance > params.threshold;\\n }\\n}\\n\",\"keccak256\":\"0xcb27d9e50a7c32406872b8fdc4ca62ee0d27372eb9077657f6d16f3cd3b58c85\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610239806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e3660046100c3565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610192565b6020810151905173ffffffffffffffffffffffffffffffffffffffff1631119392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156100d557600080fd5b813567ffffffffffffffff808211156100ed57600080fd5b818401915084601f83011261010157600080fd5b81358181111561011357610113610094565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561015957610159610094565b8160405282815287602084870101111561017257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000604082840312156101a457600080fd5b6040516040810181811067ffffffffffffffff821117156101c7576101c7610094565b604052825173ffffffffffffffffffffffffffffffffffffffff811681146101ee57600080fd5b8152602092830151928101929092525091905056fea26469706673582212203818d112b628fa60d8cffe88e7198c860e268b9375b8b118dacdbf531c397ef864736f6c63430008100033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e3660046100c3565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610192565b6020810151905173ffffffffffffffffffffffffffffffffffffffff1631119392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156100d557600080fd5b813567ffffffffffffffff808211156100ed57600080fd5b818401915084601f83011261010157600080fd5b81358181111561011357610113610094565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561015957610159610094565b8160405282815287602084870101111561017257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000604082840312156101a457600080fd5b6040516040810181811067ffffffffffffffff821117156101c7576101c7610094565b604052825173ffffffffffffffffffffffffffffffffffffffff811681146101ee57600080fd5b8152602092830151928101929092525091905056fea26469706673582212203818d112b628fa60d8cffe88e7198c860e268b9375b8b118dacdbf531c397ef864736f6c63430008100033", - "devdoc": { - "events": { - "_EventToExposeStructInABI__Params((address,uint256))": { - "params": { - "params": "Parameters to encode." - } - } - }, - "kind": "dev", - "methods": { - "check(bytes)": { - "params": { - "_params": "Encoded parameters for the drip check." - }, - "returns": { - "_0": "Whether the drip should be executed." - } - } - }, - "title": "CheckBalanceHigh", - "version": 1 - }, - "userdoc": { - "events": { - "_EventToExposeStructInABI__Params((address,uint256))": { - "notice": "External event used to help client-side tooling encode parameters." - } - }, - "kind": "user", - "methods": { - "check(bytes)": { - "notice": "Checks whether a drip should be executable." - } - }, - "notice": "DripCheck for checking if an account's balance is above a given threshold.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/CheckBalanceLow.json b/packages/contracts-bedrock/deployments/goerli/CheckBalanceLow.json deleted file mode 100644 index 35655ec4fb04..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/CheckBalanceLow.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "address": "0x381a4eFC2A2C914eA1889722bB4B44Fa6BD5b640", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "threshold", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct CheckBalanceLow.Params", - "name": "params", - "type": "tuple" - } - ], - "name": "_EventToExposeStructInABI__Params", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_params", - "type": "bytes" - } - ], - "name": "check", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x27c46f8d4f3a93eb7388ebd9be8b8c4628a30de6b358f721e810e9c881a279e5", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 67, - "gasUsed": "176640", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4a6c891cb4fae11711c0494dae3ec8e90c64b1ff33e424de9db865098471e10d", - "transactionHash": "0x27c46f8d4f3a93eb7388ebd9be8b8c4628a30de6b358f721e810e9c881a279e5", - "logs": [], - "blockNumber": 8182667, - "cumulativeGasUsed": "14037277", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "2373b7ba869baea4fec58e6e7f7b8988", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"struct CheckBalanceLow.Params\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"_EventToExposeStructInABI__Params\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_params\",\"type\":\"bytes\"}],\"name\":\"check\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"_EventToExposeStructInABI__Params((address,uint256))\":{\"params\":{\"params\":\"Parameters to encode.\"}}},\"kind\":\"dev\",\"methods\":{\"check(bytes)\":{\"params\":{\"_params\":\"Encoded parameters for the drip check.\"},\"returns\":{\"_0\":\"Whether the drip should be executed.\"}}},\"title\":\"CheckBalanceLow\",\"version\":1},\"userdoc\":{\"events\":{\"_EventToExposeStructInABI__Params((address,uint256))\":{\"notice\":\"External event used to help client-side tooling encode parameters.\"}},\"kind\":\"user\",\"methods\":{\"check(bytes)\":{\"notice\":\"Checks whether a drip should be executable.\"}},\"notice\":\"DripCheck for checking if an account's balance is below a given threshold.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/dripchecks/CheckBalanceLow.sol\":\"CheckBalanceLow\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n /**\\n * @notice Checks whether a drip should be executable.\\n *\\n * @param _params Encoded parameters for the drip check.\\n *\\n * @return Whether the drip should be executed.\\n */\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb52c89360566b2963dfd82cb2cc23f0c3ce4503a69e8563878e8aa80b6c60b3f\",\"license\":\"MIT\"},\"contracts/universal/drippie/dripchecks/CheckBalanceLow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.16;\\n\\nimport { IDripCheck } from \\\"../IDripCheck.sol\\\";\\n\\n/**\\n * @title CheckBalanceLow\\n * @notice DripCheck for checking if an account's balance is below a given threshold.\\n */\\ncontract CheckBalanceLow is IDripCheck {\\n struct Params {\\n address target;\\n uint256 threshold;\\n }\\n\\n /**\\n * @notice External event used to help client-side tooling encode parameters.\\n *\\n * @param params Parameters to encode.\\n */\\n event _EventToExposeStructInABI__Params(Params params);\\n\\n /**\\n * @inheritdoc IDripCheck\\n */\\n function check(bytes memory _params) external view returns (bool) {\\n Params memory params = abi.decode(_params, (Params));\\n\\n // Check target ETH balance is below threshold.\\n return params.target.balance < params.threshold;\\n }\\n}\\n\",\"keccak256\":\"0x6a1187a80093770931296d3360b1ecc7d17f69157fe88f628989b257548b564b\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610239806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e3660046100c3565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610192565b6020810151905173ffffffffffffffffffffffffffffffffffffffff1631109392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156100d557600080fd5b813567ffffffffffffffff808211156100ed57600080fd5b818401915084601f83011261010157600080fd5b81358181111561011357610113610094565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561015957610159610094565b8160405282815287602084870101111561017257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000604082840312156101a457600080fd5b6040516040810181811067ffffffffffffffff821117156101c7576101c7610094565b604052825173ffffffffffffffffffffffffffffffffffffffff811681146101ee57600080fd5b8152602092830151928101929092525091905056fea2646970667358221220cc86d01120737597addcccffd841244801dcb64ce402d73b8d8569a52348996464736f6c63430008100033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e3660046100c3565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610192565b6020810151905173ffffffffffffffffffffffffffffffffffffffff1631109392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156100d557600080fd5b813567ffffffffffffffff808211156100ed57600080fd5b818401915084601f83011261010157600080fd5b81358181111561011357610113610094565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561015957610159610094565b8160405282815287602084870101111561017257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000604082840312156101a457600080fd5b6040516040810181811067ffffffffffffffff821117156101c7576101c7610094565b604052825173ffffffffffffffffffffffffffffffffffffffff811681146101ee57600080fd5b8152602092830151928101929092525091905056fea2646970667358221220cc86d01120737597addcccffd841244801dcb64ce402d73b8d8569a52348996464736f6c63430008100033", - "devdoc": { - "events": { - "_EventToExposeStructInABI__Params((address,uint256))": { - "params": { - "params": "Parameters to encode." - } - } - }, - "kind": "dev", - "methods": { - "check(bytes)": { - "params": { - "_params": "Encoded parameters for the drip check." - }, - "returns": { - "_0": "Whether the drip should be executed." - } - } - }, - "title": "CheckBalanceLow", - "version": 1 - }, - "userdoc": { - "events": { - "_EventToExposeStructInABI__Params((address,uint256))": { - "notice": "External event used to help client-side tooling encode parameters." - } - }, - "kind": "user", - "methods": { - "check(bytes)": { - "notice": "Checks whether a drip should be executable." - } - }, - "notice": "DripCheck for checking if an account's balance is below a given threshold.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/CheckGelatoLow.json b/packages/contracts-bedrock/deployments/goerli/CheckGelatoLow.json deleted file mode 100644 index bef8d12d042b..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/CheckGelatoLow.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "address": "0x4f7CFc43f6D262a085F3b946cAC69E7a8E39BBAa", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "treasury", - "type": "address" - }, - { - "internalType": "uint256", - "name": "threshold", - "type": "uint256" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "indexed": false, - "internalType": "struct CheckGelatoLow.Params", - "name": "params", - "type": "tuple" - } - ], - "name": "_EventToExposeStructInABI__Params", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_params", - "type": "bytes" - } - ], - "name": "check", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x6426a895e674bb8849028c089ed41d1b9179d8392adc9ad6d225cd53c53fe49c", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 61, - "gasUsed": "222032", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4b8ed6e59a8559084820c6f9514b9ddec7de519cbf6940131b43f939c63c4307", - "transactionHash": "0x6426a895e674bb8849028c089ed41d1b9179d8392adc9ad6d225cd53c53fe49c", - "logs": [], - "blockNumber": 8182670, - "cumulativeGasUsed": "12472395", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "2373b7ba869baea4fec58e6e7f7b8988", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"treasury\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct CheckGelatoLow.Params\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"_EventToExposeStructInABI__Params\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_params\",\"type\":\"bytes\"}],\"name\":\"check\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"_EventToExposeStructInABI__Params((address,uint256,address))\":{\"params\":{\"params\":\"Parameters to encode.\"}}},\"kind\":\"dev\",\"methods\":{\"check(bytes)\":{\"params\":{\"_params\":\"Encoded parameters for the drip check.\"},\"returns\":{\"_0\":\"Whether the drip should be executed.\"}}},\"title\":\"CheckGelatoLow\",\"version\":1},\"userdoc\":{\"events\":{\"_EventToExposeStructInABI__Params((address,uint256,address))\":{\"notice\":\"External event used to help client-side tooling encode parameters.\"}},\"kind\":\"user\",\"methods\":{\"check(bytes)\":{\"notice\":\"Checks whether a drip should be executable.\"}},\"notice\":\"DripCheck for checking if an account's Gelato ETH balance is below some threshold.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/dripchecks/CheckGelatoLow.sol\":\"CheckGelatoLow\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n /**\\n * @notice Checks whether a drip should be executable.\\n *\\n * @param _params Encoded parameters for the drip check.\\n *\\n * @return Whether the drip should be executed.\\n */\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb52c89360566b2963dfd82cb2cc23f0c3ce4503a69e8563878e8aa80b6c60b3f\",\"license\":\"MIT\"},\"contracts/universal/drippie/dripchecks/CheckGelatoLow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.16;\\n\\nimport { IDripCheck } from \\\"../IDripCheck.sol\\\";\\n\\ninterface IGelatoTreasury {\\n function userTokenBalance(address _user, address _token) external view returns (uint256);\\n}\\n\\n/**\\n * @title CheckGelatoLow\\n * @notice DripCheck for checking if an account's Gelato ETH balance is below some threshold.\\n */\\ncontract CheckGelatoLow is IDripCheck {\\n struct Params {\\n address treasury;\\n uint256 threshold;\\n address recipient;\\n }\\n\\n /**\\n * @notice External event used to help client-side tooling encode parameters.\\n *\\n * @param params Parameters to encode.\\n */\\n event _EventToExposeStructInABI__Params(Params params);\\n\\n /**\\n * @inheritdoc IDripCheck\\n */\\n function check(bytes memory _params) external view returns (bool) {\\n Params memory params = abi.decode(_params, (Params));\\n\\n // Check GelatoTreasury ETH balance is below threshold.\\n return\\n IGelatoTreasury(params.treasury).userTokenBalance(\\n params.recipient,\\n // Gelato represents ETH as 0xeeeee....eeeee\\n 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\\n ) < params.threshold;\\n }\\n}\\n\",\"keccak256\":\"0x1a127a2c8955525cc2e5cd3c6703edc785c662a79222f524df4574cf47ddd864\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061030c806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e366004610160565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610258565b6020810151815160408084015190517fb47064c800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6024820152939450919291169063b47064c890604401602060405180830381865afa158015610105573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061012991906102bd565b109392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561017257600080fd5b813567ffffffffffffffff8082111561018a57600080fd5b818401915084601f83011261019e57600080fd5b8135818111156101b0576101b0610131565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101f6576101f6610131565b8160405282815287602084870101111561020f57600080fd5b826020860160208301376000928101602001929092525095945050505050565b805173ffffffffffffffffffffffffffffffffffffffff8116811461025357600080fd5b919050565b60006060828403121561026a57600080fd5b6040516060810181811067ffffffffffffffff8211171561028d5761028d610131565b6040526102998361022f565b8152602083015160208201526102b16040840161022f565b60408201529392505050565b6000602082840312156102cf57600080fd5b505191905056fea2646970667358221220d5d7b760af134f89109f20dbf88fd89e78bb4b81bed97f9aa45772b3775b388964736f6c63430008100033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e366004610160565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610258565b6020810151815160408084015190517fb47064c800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6024820152939450919291169063b47064c890604401602060405180830381865afa158015610105573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061012991906102bd565b109392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561017257600080fd5b813567ffffffffffffffff8082111561018a57600080fd5b818401915084601f83011261019e57600080fd5b8135818111156101b0576101b0610131565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101f6576101f6610131565b8160405282815287602084870101111561020f57600080fd5b826020860160208301376000928101602001929092525095945050505050565b805173ffffffffffffffffffffffffffffffffffffffff8116811461025357600080fd5b919050565b60006060828403121561026a57600080fd5b6040516060810181811067ffffffffffffffff8211171561028d5761028d610131565b6040526102998361022f565b8152602083015160208201526102b16040840161022f565b60408201529392505050565b6000602082840312156102cf57600080fd5b505191905056fea2646970667358221220d5d7b760af134f89109f20dbf88fd89e78bb4b81bed97f9aa45772b3775b388964736f6c63430008100033", - "devdoc": { - "events": { - "_EventToExposeStructInABI__Params((address,uint256,address))": { - "params": { - "params": "Parameters to encode." - } - } - }, - "kind": "dev", - "methods": { - "check(bytes)": { - "params": { - "_params": "Encoded parameters for the drip check." - }, - "returns": { - "_0": "Whether the drip should be executed." - } - } - }, - "title": "CheckGelatoLow", - "version": 1 - }, - "userdoc": { - "events": { - "_EventToExposeStructInABI__Params((address,uint256,address))": { - "notice": "External event used to help client-side tooling encode parameters." - } - }, - "kind": "user", - "methods": { - "check(bytes)": { - "notice": "Checks whether a drip should be executable." - } - }, - "notice": "DripCheck for checking if an account's Gelato ETH balance is below some threshold.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/CheckTrue.json b/packages/contracts-bedrock/deployments/goerli/CheckTrue.json deleted file mode 100644 index 89a088d39722..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/CheckTrue.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "address": "0x5c741a38cb11424711231777D71689C458eE835D", - "abi": [ - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "check", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - } - ], - "transactionHash": "0xeacb73acd8f3d741e1a4a136e95cec43d21aef36b95611cdaa86c87066bfd087", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 81, - "gasUsed": "139230", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x396e72234d59683880032c4c9e6fd61a46b839b61c644c7bd180e02d565c3b14", - "transactionHash": "0xeacb73acd8f3d741e1a4a136e95cec43d21aef36b95611cdaa86c87066bfd087", - "logs": [], - "blockNumber": 8182671, - "cumulativeGasUsed": "17047212", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "2373b7ba869baea4fec58e6e7f7b8988", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"check\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"check(bytes)\":{\"params\":{\"_params\":\"Encoded parameters for the drip check.\"},\"returns\":{\"_0\":\"Whether the drip should be executed.\"}}},\"title\":\"CheckTrue\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"check(bytes)\":{\"notice\":\"Checks whether a drip should be executable.\"}},\"notice\":\"DripCheck that always returns true.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/dripchecks/CheckTrue.sol\":\"CheckTrue\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n /**\\n * @notice Checks whether a drip should be executable.\\n *\\n * @param _params Encoded parameters for the drip check.\\n *\\n * @return Whether the drip should be executed.\\n */\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb52c89360566b2963dfd82cb2cc23f0c3ce4503a69e8563878e8aa80b6c60b3f\",\"license\":\"MIT\"},\"contracts/universal/drippie/dripchecks/CheckTrue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.16;\\n\\nimport { IDripCheck } from \\\"../IDripCheck.sol\\\";\\n\\n/**\\n * @title CheckTrue\\n * @notice DripCheck that always returns true.\\n */\\ncontract CheckTrue is IDripCheck {\\n /**\\n * @inheritdoc IDripCheck\\n */\\n function check(bytes memory) external pure returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xf2f5474f12983c30ca4fe9d19e7f88e6d2262e4a6f779e86b4a2117498fdbea5\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061018c806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004461003e366004610087565b50600190565b604051901515815260200160405180910390f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561009957600080fd5b813567ffffffffffffffff808211156100b157600080fd5b818401915084601f8301126100c557600080fd5b8135818111156100d7576100d7610058565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561011d5761011d610058565b8160405282815287602084870101111561013657600080fd5b82602086016020830137600092810160200192909252509594505050505056fea26469706673582212200bb899cb0e5f9dce180ebe72a1dfade46ffc5ec3cab398d1f2af09e8b9ce76d164736f6c63430008100033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004461003e366004610087565b50600190565b604051901515815260200160405180910390f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561009957600080fd5b813567ffffffffffffffff808211156100b157600080fd5b818401915084601f8301126100c557600080fd5b8135818111156100d7576100d7610058565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561011d5761011d610058565b8160405282815287602084870101111561013657600080fd5b82602086016020830137600092810160200192909252509594505050505056fea26469706673582212200bb899cb0e5f9dce180ebe72a1dfade46ffc5ec3cab398d1f2af09e8b9ce76d164736f6c63430008100033", - "devdoc": { - "kind": "dev", - "methods": { - "check(bytes)": { - "params": { - "_params": "Encoded parameters for the drip check." - }, - "returns": { - "_0": "Whether the drip should be executed." - } - } - }, - "title": "CheckTrue", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "check(bytes)": { - "notice": "Checks whether a drip should be executable." - } - }, - "notice": "DripCheck that always returns true.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/Drippie.json b/packages/contracts-bedrock/deployments/goerli/Drippie.json deleted file mode 100644 index f4d72fe6deed..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/Drippie.json +++ /dev/null @@ -1,1054 +0,0 @@ -{ - "address": "0x44b3A2a040057eBafC601A78647e805fd58B1f50", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "nameref", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "components": [ - { - "internalType": "bool", - "name": "reentrant", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "interval", - "type": "uint256" - }, - { - "internalType": "contract IDripCheck", - "name": "dripcheck", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkparams", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address payable", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct Drippie.DripAction[]", - "name": "actions", - "type": "tuple[]" - } - ], - "indexed": false, - "internalType": "struct Drippie.DripConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "DripCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "nameref", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "address", - "name": "executor", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - } - ], - "name": "DripExecuted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "nameref", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "enum Drippie.DripStatus", - "name": "status", - "type": "uint8" - } - ], - "name": "DripStatusUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ReceivedETH", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrewERC20", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "WithdrewERC721", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrewETH", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "CALL", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "DELEGATECALL", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "components": [ - { - "internalType": "bool", - "name": "reentrant", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "interval", - "type": "uint256" - }, - { - "internalType": "contract IDripCheck", - "name": "dripcheck", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkparams", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address payable", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct Drippie.DripAction[]", - "name": "actions", - "type": "tuple[]" - } - ], - "internalType": "struct Drippie.DripConfig", - "name": "_config", - "type": "tuple" - } - ], - "name": "create", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - } - ], - "name": "drip", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "drips", - "outputs": [ - { - "internalType": "enum Drippie.DripStatus", - "name": "status", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "bool", - "name": "reentrant", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "interval", - "type": "uint256" - }, - { - "internalType": "contract IDripCheck", - "name": "dripcheck", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkparams", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address payable", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct Drippie.DripAction[]", - "name": "actions", - "type": "tuple[]" - } - ], - "internalType": "struct Drippie.DripConfig", - "name": "config", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "last", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "count", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - } - ], - "name": "executable", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "setOwner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "enum Drippie.DripStatus", - "name": "_status", - "type": "uint8" - } - ], - "name": "status", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC20", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC20", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC721", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "withdrawERC721", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdrawETH", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - } - ], - "name": "withdrawETH", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0x4bd4a6ab9e90105104d13049891298914961a4379c1cd25b636037d7f54e85b2", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 102, - "gasUsed": "2419585", - "logsBloom": "0x00000000000000000001000000000000000000000000000000000000000000000000100000000000000000000000080000000000000000000000000000000004000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000400000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000020000000000000000000000000000000000000000000000", - "blockHash": "0x59e68f7aa73c5c9e2c0c6bcf2eb9fdcc473be33538564b57202ef0fe89bfb61a", - "transactionHash": "0x4bd4a6ab9e90105104d13049891298914961a4379c1cd25b636037d7f54e85b2", - "logs": [ - { - "transactionIndex": 102, - "blockNumber": 8182665, - "transactionHash": "0x4bd4a6ab9e90105104d13049891298914961a4379c1cd25b636037d7f54e85b2", - "address": "0x44b3A2a040057eBafC601A78647e805fd58B1f50", - "topics": [ - "0x8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58" - ], - "data": "0x", - "logIndex": 274, - "blockHash": "0x59e68f7aa73c5c9e2c0c6bcf2eb9fdcc473be33538564b57202ef0fe89bfb61a" - } - ], - "blockNumber": 8182665, - "cumulativeGasUsed": "25052149", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "2373b7ba869baea4fec58e6e7f7b8988", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"nameref\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"reentrant\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"interval\",\"type\":\"uint256\"},{\"internalType\":\"contract IDripCheck\",\"name\":\"dripcheck\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkparams\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address payable\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"struct Drippie.DripAction[]\",\"name\":\"actions\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"struct Drippie.DripConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DripCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"nameref\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"executor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"DripExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"nameref\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"enum Drippie.DripStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"name\":\"DripStatusUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ReceivedETH\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrewERC20\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"WithdrewERC721\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrewETH\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"CALL\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"DELEGATECALL\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"reentrant\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"interval\",\"type\":\"uint256\"},{\"internalType\":\"contract IDripCheck\",\"name\":\"dripcheck\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkparams\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address payable\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"struct Drippie.DripAction[]\",\"name\":\"actions\",\"type\":\"tuple[]\"}],\"internalType\":\"struct Drippie.DripConfig\",\"name\":\"_config\",\"type\":\"tuple\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"drip\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"drips\",\"outputs\":[{\"internalType\":\"enum Drippie.DripStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"reentrant\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"interval\",\"type\":\"uint256\"},{\"internalType\":\"contract IDripCheck\",\"name\":\"dripcheck\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkparams\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address payable\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"struct Drippie.DripAction[]\",\"name\":\"actions\",\"type\":\"tuple[]\"}],\"internalType\":\"struct Drippie.DripConfig\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"last\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"executable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"enum Drippie.DripStatus\",\"name\":\"_status\",\"type\":\"uint8\"}],\"name\":\"status\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"withdrawERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC721\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"withdrawERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"withdrawETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"events\":{\"DripCreated(string,string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))\":{\"params\":{\"config\":\"Config for the created drip.\",\"name\":\"Unindexed name parameter (unhashed).\",\"nameref\":\"Indexed name parameter (hashed).\"}},\"DripExecuted(string,string,address,uint256)\":{\"params\":{\"executor\":\"Address that executed the drip.\",\"name\":\"Unindexed name parameter (unhashed).\",\"nameref\":\"Indexed name parameter (hashed).\",\"timestamp\":\"Time when the drip was executed.\"}},\"DripStatusUpdated(string,string,uint8)\":{\"params\":{\"name\":\"Unindexed name parameter (unhashed).\",\"nameref\":\"Indexed name parameter (hashed).\",\"status\":\"New drip status.\"}}},\"kind\":\"dev\",\"methods\":{\"CALL(address,bytes,uint256)\":{\"params\":{\"_data\":\"Data to send with the call.\",\"_target\":\"Address to call.\",\"_value\":\"ETH value to send with the call.\"},\"returns\":{\"_0\":\"Boolean success value.\",\"_1\":\"Bytes data returned by the call.\"}},\"DELEGATECALL(address,bytes)\":{\"params\":{\"_data\":\"Data to send with the call.\",\"_target\":\"Address to call.\"},\"returns\":{\"_0\":\"Boolean success value.\",\"_1\":\"Bytes data returned by the call.\"}},\"constructor\":{\"params\":{\"_owner\":\"Initial contract owner.\"}},\"create(string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))\":{\"params\":{\"_config\":\"Configuration for the drip.\",\"_name\":\"Name of the drip.\"}},\"drip(string)\":{\"params\":{\"_name\":\"Name of the drip to trigger.\"}},\"executable(string)\":{\"params\":{\"_name\":\"Drip to check.\"},\"returns\":{\"_0\":\"True if the drip is executable, reverts otherwise.\"}},\"status(string,uint8)\":{\"params\":{\"_name\":\"Name of the drip to update.\",\"_status\":\"New drip status.\"}},\"withdrawERC20(address,address)\":{\"params\":{\"_asset\":\"ERC20 token to withdraw.\",\"_to\":\"Address to receive the ERC20 balance.\"}},\"withdrawERC20(address,address,uint256)\":{\"params\":{\"_amount\":\"Amount of ERC20 to withdraw.\",\"_asset\":\"ERC20 token to withdraw.\",\"_to\":\"Address to receive the ERC20 balance.\"}},\"withdrawERC721(address,address,uint256)\":{\"params\":{\"_asset\":\"ERC721 token to withdraw.\",\"_id\":\"Token ID of the ERC721 token to withdraw.\",\"_to\":\"Address to receive the ERC721 token.\"}},\"withdrawETH(address)\":{\"params\":{\"_to\":\"Address to receive the ETH balance.\"}},\"withdrawETH(address,uint256)\":{\"params\":{\"_amount\":\"Amount of ETH to withdraw.\",\"_to\":\"Address to receive the ETH balance.\"}}},\"title\":\"Drippie\",\"version\":1},\"userdoc\":{\"events\":{\"DripCreated(string,string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))\":{\"notice\":\"Emitted when a new drip is created.\"},\"DripExecuted(string,string,address,uint256)\":{\"notice\":\"Emitted when a drip is executed.\"},\"DripStatusUpdated(string,string,uint8)\":{\"notice\":\"Emitted when a drip status is updated.\"},\"ReceivedETH(address,uint256)\":{\"notice\":\"Emitted when ETH is received by this address.\"},\"WithdrewERC20(address,address,address,uint256)\":{\"notice\":\"Emitted when ERC20 tokens are withdrawn from this address.\"},\"WithdrewERC721(address,address,address,uint256)\":{\"notice\":\"Emitted when ERC20 tokens are withdrawn from this address.\"},\"WithdrewETH(address,address,uint256)\":{\"notice\":\"Emitted when ETH is withdrawn from this address.\"}},\"kind\":\"user\",\"methods\":{\"CALL(address,bytes,uint256)\":{\"notice\":\"Sends a CALL to a target address.\"},\"DELEGATECALL(address,bytes)\":{\"notice\":\"Sends a DELEGATECALL to a target address.\"},\"create(string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))\":{\"notice\":\"Creates a new drip with the given name and configuration. Once created, drips cannot be modified in any way (this is a security measure). If you want to update a drip, simply pause (and potentially archive) the existing drip and create a new one.\"},\"drip(string)\":{\"notice\":\"Triggers a drip. This function is deliberately left as a public function because the assumption being made here is that setting the drip to ACTIVE is an affirmative signal that the drip should be executable according to the drip parameters, drip check, and drip interval. Note that drip parameters are read entirely from the state and are not supplied as user input, so there should not be any way for a non-authorized user to influence the behavior of the drip. Note that the drip check is executed only **once** at the beginning of the call to the drip function and will not be executed again between the drip actions within this call.\"},\"drips(string)\":{\"notice\":\"Maps from drip names to drip states.\"},\"executable(string)\":{\"notice\":\"Checks if a given drip is executable.\"},\"status(string,uint8)\":{\"notice\":\"Sets the status for a given drip. The behavior of this function depends on the status that the user is trying to set. A drip can always move between ACTIVE and PAUSED, but it can never move back to NONE and once ARCHIVED, it can never move back to ACTIVE or PAUSED.\"},\"withdrawERC20(address,address)\":{\"notice\":\"Withdraws full ERC20 balance to the recipient.\"},\"withdrawERC20(address,address,uint256)\":{\"notice\":\"Withdraws partial ERC20 balance to the recipient.\"},\"withdrawERC721(address,address,uint256)\":{\"notice\":\"Withdraws ERC721 token to the recipient.\"},\"withdrawETH(address)\":{\"notice\":\"Withdraws full ETH balance to the recipient.\"},\"withdrawETH(address,uint256)\":{\"notice\":\"Withdraws partial ETH balance to the recipient.\"}},\"notice\":\"Drippie is a system for managing automated contract interactions. A specific interaction is called a \\\"drip\\\" and can be executed according to some condition (called a dripcheck) and an execution interval. Drips cannot be executed faster than the execution interval. Drips can trigger arbitrary contract calls where the calling contract is this contract address. Drips can also send ETH value, which makes them ideal for keeping addresses sufficiently funded with ETH. Drippie is designed to be connected with smart contract automation services so that drips can be executed automatically. However, Drippie is specifically designed to be separated from these services so that trust assumptions are better compartmentalized.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/Drippie.sol\":\"Drippie\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x7e91c80b0dd1a14a19cb9e661b99924043adab6d9d893bbfcf3a6a3dc23a6743\",\"license\":\"AGPL-3.0-only\"},\"@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\",\"keccak256\":\"0x43aa1509bb753f053143530705d9c4eee415691d26a4779769bf028a74e6ac69\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xdac91feb466e74905737338d80cac5303eb7aedcbe76eda11c45eaa728451075\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x7e9bcbf8e23cb5f48e4eca605da6b7d96f88b9499e91a92cbf74d82e9e91cdf1\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x6a9e687b2f333bcc8ade530325005cb67ab7f78fd31407d4f2274324e71fc0fb\",\"license\":\"MIT\"},\"contracts/universal/drippie/Drippie.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.16;\\n\\nimport { AssetReceiver } from \\\"../AssetReceiver.sol\\\";\\nimport { IDripCheck } from \\\"./IDripCheck.sol\\\";\\n\\n/**\\n * @title Drippie\\n * @notice Drippie is a system for managing automated contract interactions. A specific interaction\\n * is called a \\\"drip\\\" and can be executed according to some condition (called a dripcheck)\\n * and an execution interval. Drips cannot be executed faster than the execution interval.\\n * Drips can trigger arbitrary contract calls where the calling contract is this contract\\n * address. Drips can also send ETH value, which makes them ideal for keeping addresses\\n * sufficiently funded with ETH. Drippie is designed to be connected with smart contract\\n * automation services so that drips can be executed automatically. However, Drippie is\\n * specifically designed to be separated from these services so that trust assumptions are\\n * better compartmentalized.\\n */\\ncontract Drippie is AssetReceiver {\\n /**\\n * @notice Enum representing different status options for a given drip.\\n *\\n * @custom:value NONE Drip does not exist.\\n * @custom:value PAUSED Drip is paused and cannot be executed until reactivated.\\n * @custom:value ACTIVE Drip is active and can be executed.\\n * @custom:value ARCHIVED Drip is archived and can no longer be executed or reactivated.\\n */\\n enum DripStatus {\\n NONE,\\n PAUSED,\\n ACTIVE,\\n ARCHIVED\\n }\\n\\n /**\\n * @notice Represents a drip action.\\n */\\n struct DripAction {\\n address payable target;\\n bytes data;\\n uint256 value;\\n }\\n\\n /**\\n * @notice Represents the configuration for a given drip.\\n */\\n struct DripConfig {\\n bool reentrant;\\n uint256 interval;\\n IDripCheck dripcheck;\\n bytes checkparams;\\n DripAction[] actions;\\n }\\n\\n /**\\n * @notice Represents the state of an active drip.\\n */\\n struct DripState {\\n DripStatus status;\\n DripConfig config;\\n uint256 last;\\n uint256 count;\\n }\\n\\n /**\\n * @notice Emitted when a new drip is created.\\n *\\n * @param nameref Indexed name parameter (hashed).\\n * @param name Unindexed name parameter (unhashed).\\n * @param config Config for the created drip.\\n */\\n event DripCreated(\\n // Emit name twice because indexed version is hashed.\\n string indexed nameref,\\n string name,\\n DripConfig config\\n );\\n\\n /**\\n * @notice Emitted when a drip status is updated.\\n *\\n * @param nameref Indexed name parameter (hashed).\\n * @param name Unindexed name parameter (unhashed).\\n * @param status New drip status.\\n */\\n event DripStatusUpdated(\\n // Emit name twice because indexed version is hashed.\\n string indexed nameref,\\n string name,\\n DripStatus status\\n );\\n\\n /**\\n * @notice Emitted when a drip is executed.\\n *\\n * @param nameref Indexed name parameter (hashed).\\n * @param name Unindexed name parameter (unhashed).\\n * @param executor Address that executed the drip.\\n * @param timestamp Time when the drip was executed.\\n */\\n event DripExecuted(\\n // Emit name twice because indexed version is hashed.\\n string indexed nameref,\\n string name,\\n address executor,\\n uint256 timestamp\\n );\\n\\n /**\\n * @notice Maps from drip names to drip states.\\n */\\n mapping(string => DripState) public drips;\\n\\n /**\\n * @param _owner Initial contract owner.\\n */\\n constructor(address _owner) AssetReceiver(_owner) {}\\n\\n /**\\n * @notice Creates a new drip with the given name and configuration. Once created, drips cannot\\n * be modified in any way (this is a security measure). If you want to update a drip,\\n * simply pause (and potentially archive) the existing drip and create a new one.\\n *\\n * @param _name Name of the drip.\\n * @param _config Configuration for the drip.\\n */\\n function create(string calldata _name, DripConfig calldata _config) external onlyOwner {\\n // Make sure this drip doesn't already exist. We *must* guarantee that no other function\\n // will ever set the status of a drip back to NONE after it's been created. This is why\\n // archival is a separate status.\\n require(\\n drips[_name].status == DripStatus.NONE,\\n \\\"Drippie: drip with that name already exists\\\"\\n );\\n\\n // Validate the drip interval, only allowing an interval of zero if the drip has explicitly\\n // been marked as reentrant. Prevents client-side bugs making a drip infinitely executable\\n // within the same block (of course, restricted by gas limits).\\n if (_config.reentrant) {\\n require(\\n _config.interval == 0,\\n \\\"Drippie: if allowing reentrant drip, must set interval to zero\\\"\\n );\\n } else {\\n require(\\n _config.interval > 0,\\n \\\"Drippie: interval must be greater than zero if drip is not reentrant\\\"\\n );\\n }\\n\\n // We initialize this way because Solidity won't let us copy arrays into storage yet.\\n DripState storage state = drips[_name];\\n state.status = DripStatus.PAUSED;\\n state.config.reentrant = _config.reentrant;\\n state.config.interval = _config.interval;\\n state.config.dripcheck = _config.dripcheck;\\n state.config.checkparams = _config.checkparams;\\n\\n // Solidity doesn't let us copy arrays into storage, so we push each array one by one.\\n for (uint256 i = 0; i < _config.actions.length; i++) {\\n state.config.actions.push(_config.actions[i]);\\n }\\n\\n // Tell the world!\\n emit DripCreated(_name, _name, _config);\\n }\\n\\n /**\\n * @notice Sets the status for a given drip. The behavior of this function depends on the\\n * status that the user is trying to set. A drip can always move between ACTIVE and\\n * PAUSED, but it can never move back to NONE and once ARCHIVED, it can never move back\\n * to ACTIVE or PAUSED.\\n *\\n * @param _name Name of the drip to update.\\n * @param _status New drip status.\\n */\\n function status(string calldata _name, DripStatus _status) external onlyOwner {\\n // Make sure we can never set drip status back to NONE. A simple security measure to\\n // prevent accidental overwrites if this code is ever updated down the line.\\n require(\\n _status != DripStatus.NONE,\\n \\\"Drippie: drip status can never be set back to NONE after creation\\\"\\n );\\n\\n // Load the drip status once to avoid unnecessary SLOADs.\\n DripStatus curr = drips[_name].status;\\n\\n // Make sure the drip in question actually exists. Not strictly necessary but there doesn't\\n // seem to be any clear reason why you would want to do this, and it may save some gas in\\n // the case of a front-end bug.\\n require(\\n curr != DripStatus.NONE,\\n \\\"Drippie: drip with that name does not exist and cannot be updated\\\"\\n );\\n\\n // Once a drip has been archived, it cannot be un-archived. This is, after all, the entire\\n // point of archiving a drip.\\n require(\\n curr != DripStatus.ARCHIVED,\\n \\\"Drippie: drip with that name has been archived and cannot be updated\\\"\\n );\\n\\n // Although not strictly necessary, we make sure that the status here is actually changing.\\n // This may save the client some gas if there's a front-end bug and the user accidentally\\n // tries to \\\"change\\\" the status to the same value as before.\\n require(\\n curr != _status,\\n \\\"Drippie: cannot set drip status to the same status as its current status\\\"\\n );\\n\\n // If the user is trying to archive this drip, make sure the drip has been paused. We do\\n // not allow users to archive active drips so that the effects of this action are more\\n // abundantly clear.\\n if (_status == DripStatus.ARCHIVED) {\\n require(\\n curr == DripStatus.PAUSED,\\n \\\"Drippie: drip must first be paused before being archived\\\"\\n );\\n }\\n\\n // If we made it here then we can safely update the status.\\n drips[_name].status = _status;\\n emit DripStatusUpdated(_name, _name, _status);\\n }\\n\\n /**\\n * @notice Checks if a given drip is executable.\\n *\\n * @param _name Drip to check.\\n *\\n * @return True if the drip is executable, reverts otherwise.\\n */\\n function executable(string calldata _name) public view returns (bool) {\\n DripState storage state = drips[_name];\\n\\n // Only allow active drips to be executed, an obvious security measure.\\n require(\\n state.status == DripStatus.ACTIVE,\\n \\\"Drippie: selected drip does not exist or is not currently active\\\"\\n );\\n\\n // Don't drip if the drip interval has not yet elapsed since the last time we dripped. This\\n // is a safety measure that prevents a malicious recipient from, e.g., spending all of\\n // their funds and repeatedly requesting new drips. Limits the potential impact of a\\n // compromised recipient to just a single drip interval, after which the drip can be paused\\n // by the owner address.\\n require(\\n state.last + state.config.interval <= block.timestamp,\\n \\\"Drippie: drip interval has not elapsed since last drip\\\"\\n );\\n\\n // Make sure we're allowed to execute this drip.\\n require(\\n state.config.dripcheck.check(state.config.checkparams),\\n \\\"Drippie: dripcheck failed so drip is not yet ready to be triggered\\\"\\n );\\n\\n // Alright, we're good to execute.\\n return true;\\n }\\n\\n /**\\n * @notice Triggers a drip. This function is deliberately left as a public function because the\\n * assumption being made here is that setting the drip to ACTIVE is an affirmative\\n * signal that the drip should be executable according to the drip parameters, drip\\n * check, and drip interval. Note that drip parameters are read entirely from the state\\n * and are not supplied as user input, so there should not be any way for a\\n * non-authorized user to influence the behavior of the drip. Note that the drip check\\n * is executed only **once** at the beginning of the call to the drip function and will\\n * not be executed again between the drip actions within this call.\\n *\\n * @param _name Name of the drip to trigger.\\n */\\n function drip(string calldata _name) external {\\n DripState storage state = drips[_name];\\n\\n // Make sure the drip can be executed. Since executable reverts if the drip is not ready to\\n // be executed, we don't need to do an assertion that the returned value is true.\\n executable(_name);\\n\\n // Update the last execution time for this drip before the call. Note that it's entirely\\n // possible for a drip to be executed multiple times per block or even multiple times\\n // within the same transaction (via re-entrancy) if the drip interval is set to zero. Users\\n // should set a drip interval of 1 if they'd like the drip to be executed only once per\\n // block (since this will then prevent re-entrancy).\\n state.last = block.timestamp;\\n\\n // Update the number of times this drip has been executed. Although this increases the cost\\n // of using Drippie, it slightly simplifies the client-side by not having to worry about\\n // counting drips via events. Useful for monitoring the rate of drip execution.\\n state.count++;\\n\\n // Execute each action in the drip. We allow drips to have multiple actions because there\\n // are scenarios in which a contract must do multiple things atomically. For example, the\\n // contract may need to withdraw ETH from one account and then deposit that ETH into\\n // another account within the same transaction.\\n uint256 len = state.config.actions.length;\\n for (uint256 i = 0; i < len; i++) {\\n // Must be marked as \\\"storage\\\" because copying structs into memory is not yet supported\\n // by Solidity. Won't significantly reduce gas costs but at least makes it easier to\\n // read what the rest of this section is doing.\\n DripAction storage action = state.config.actions[i];\\n\\n // Actually execute the action. We could use ExcessivelySafeCall here but not strictly\\n // necessary (worst case, a drip gets bricked IFF the target is malicious, doubt this\\n // will ever happen in practice). Could save a marginal amount of gas to ignore the\\n // returndata.\\n // slither-disable-next-line calls-loop\\n (bool success, ) = action.target.call{ value: action.value }(action.data);\\n\\n // Generally should not happen, but could if there's a misconfiguration (e.g., passing\\n // the wrong data to the target contract), the recipient is not payable, or\\n // insufficient gas was supplied to this transaction. We revert so the drip can be\\n // fixed and triggered again later. Means we cannot emit an event to alert of the\\n // failure, but can reasonably be detected by off-chain services even without an event.\\n // Note that this forces the drip executor to supply sufficient gas to the call\\n // (assuming there is some sufficient gas limit that exists, otherwise the drip will\\n // not execute).\\n require(\\n success,\\n \\\"Drippie: drip was unsuccessful, please check your configuration for mistakes\\\"\\n );\\n }\\n\\n emit DripExecuted(_name, _name, msg.sender, block.timestamp);\\n }\\n}\\n\",\"keccak256\":\"0x60aac1f170b36ddd9523a48eccae75ad408ecbad6b32bcf5567e7f680ab10c94\",\"license\":\"MIT\"},\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n /**\\n * @notice Checks whether a drip should be executable.\\n *\\n * @param _params Encoded parameters for the drip check.\\n *\\n * @return Whether the drip should be executed.\\n */\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb52c89360566b2963dfd82cb2cc23f0c3ce4503a69e8563878e8aa80b6c60b3f\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162002b3138038062002b3183398101604081905262000034916200008c565b600080546001600160a01b0319166001600160a01b03831690811782556040518392839283929091907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a350505050620000be565b6000602082840312156200009f57600080fd5b81516001600160a01b0381168114620000b757600080fd5b9392505050565b612a6380620000ce6000396000f3fe6080604052600436106100e15760003560e01c80636e2d44ae1161007f5780639bc94d01116100595780639bc94d01146102b0578063e551cdaa146102d0578063edee6239146102f0578063fc3e3eba1461030357600080fd5b80636e2d44ae1461021d5780638da5cb5b1461023e5780639456fbcc1461029057600080fd5b80634782f779116100bb5780634782f779146101845780634d7fba6e146101a457806367148cd2146101dd578063690d8320146101fd57600080fd5b806313af4035146101225780634025feb21461014457806344004cc11461016457600080fd5b3661011d5760405134815233907f4103257eaac983ca79a70d28f90dfc4fa16b619bb0c17ee7cab0d4034c2796249060200160405180910390a2005b600080fd5b34801561012e57600080fd5b5061014261013d366004611af9565b610333565b005b34801561015057600080fd5b5061014261015f366004611b1d565b61040f565b34801561017057600080fd5b5061014261017f366004611b1d565b610587565b34801561019057600080fd5b5061014261019f366004611b5e565b6106fe565b3480156101b057600080fd5b506101c46101bf366004611c2f565b610834565b6040516101d49493929190611d3a565b60405180910390f35b3480156101e957600080fd5b506101426101f8366004611e94565b610a66565b34801561020957600080fd5b50610142610218366004611af9565b610c6f565b61023061022b366004611ef6565b610ce3565b6040516101d4929190611f4f565b34801561024a57600080fd5b5060005461026b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d4565b34801561029c57600080fd5b506101426102ab366004611f6a565b610dc3565b3480156102bc57600080fd5b506101426102cb366004611fa3565b610ec4565b3480156102dc57600080fd5b506101426102eb366004611ffe565b611363565b6102306102fe366004612063565b61177f565b34801561030f57600080fd5b5061032361031e366004611e94565b61185c565b60405190151581526020016101d4565b60005473ffffffffffffffffffffffffffffffffffffffff16331461039f5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104765760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b1580156104ec57600080fd5b505af1158015610500573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f30b478a5e196e55886228aa87ba74a7dfeba655e0a4d7ba275eabfc22aabb7a88460405161057a91815260200190565b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105ee5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb906044016020604051808303816000875af1158015610663573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068791906120c1565b508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f6b00f1c7883f053ba83e907fd1965b22fffe3c4111383e725f04638a566cdbfa8460405161057a91815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107655760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146107bf576040519150601f19603f3d011682016040523d82523d6000602084013e6107c4565b606091505b505090508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f1f12aa8b6d492dd9b98e2b00b0b20830c2a7ded65afac13b60d169a034ae90bc8460405161082791815260200190565b60405180910390a3505050565b805160208183018101805160018083529383019483019490942093905282546040805160a081018252938501805460ff90811615158652600287015494860194909452600386015473ffffffffffffffffffffffffffffffffffffffff169185019190915260048501805493909216949392909160608401916108b6906120de565b80601f01602080910402602001604051908101604052809291908181526020018280546108e2906120de565b801561092f5780601f106109045761010080835404028352916020019161092f565b820191906000526020600020905b81548152906001019060200180831161091257829003601f168201915b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b82821015610a4e576000848152602090819020604080516060810190915260038502909101805473ffffffffffffffffffffffffffffffffffffffff16825260018101805492939192918401916109b3906120de565b80601f01602080910402602001604051908101604052809291908181526020018280546109df906120de565b8015610a2c5780601f10610a0157610100808354040283529160200191610a2c565b820191906000526020600020905b815481529060010190602001808311610a0f57829003601f168201915b505050505081526020016002820154815250508152602001906001019061095d565b50505091525050600682015460079092015490919084565b600060018383604051610a7a929190612131565b90815260200160405180910390209050610a94838361185c565b50426006820155600781018054906000610aad83612170565b9091555050600581015460005b81811015610c13576000836001016004018281548110610adc57610adc6121a8565b6000918252602082206003909102018054600282015460405192945073ffffffffffffffffffffffffffffffffffffffff90911691610b1f9060018601906121d7565b60006040518083038185875af1925050503d8060008114610b5c576040519150601f19603f3d011682016040523d82523d6000602084013e610b61565b606091505b5050905080610bfe5760405162461bcd60e51b815260206004820152604c60248201527f447269707069653a20647269702077617320756e7375636365737366756c2c2060448201527f706c6561736520636865636b20796f757220636f6e66696775726174696f6e2060648201527f666f72206d697374616b65730000000000000000000000000000000000000000608482015260a401610396565b50508080610c0b90612170565b915050610aba565b508383604051610c24929190612131565b60405180910390207fea21435419aad9c54a9d90e2522b6f60bd566401f36fcef661f5f5a28cc0d2c685853342604051610c619493929190612296565b60405180910390a250505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610cd65760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b610ce081476106fe565b50565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610d4e5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b8473ffffffffffffffffffffffffffffffffffffffff168385604051610d7491906122d3565b60006040518083038185875af1925050503d8060008114610db1576040519150601f19603f3d011682016040523d82523d6000602084013e610db6565b606091505b5091509150935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e2a5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610ec0908390839073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610e9c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061017f91906122ef565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610f2b5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6000816003811115610f3f57610f3f611c80565b03610fd85760405162461bcd60e51b815260206004820152604160248201527f447269707069653a2064726970207374617475732063616e206e65766572206260448201527f6520736574206261636b20746f204e4f4e45206166746572206372656174696f60648201527f6e00000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b600060018484604051610fec929190612131565b9081526040519081900360200190205460ff169050600081600381111561101557611015611c80565b036110ae5760405162461bcd60e51b815260206004820152604160248201527f447269707069653a206472697020776974682074686174206e616d6520646f6560448201527f73206e6f7420657869737420616e642063616e6e6f742062652075706461746560648201527f6400000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b60038160038111156110c2576110c2611c80565b0361115c5760405162461bcd60e51b8152602060048201526044602482018190527f447269707069653a206472697020776974682074686174206e616d6520686173908201527f206265656e20617263686976656420616e642063616e6e6f742062652075706460648201527f6174656400000000000000000000000000000000000000000000000000000000608482015260a401610396565b81600381111561116e5761116e611c80565b81600381111561118057611180611c80565b036112195760405162461bcd60e51b815260206004820152604860248201527f447269707069653a2063616e6e6f74207365742064726970207374617475732060448201527f746f207468652073616d6520737461747573206173206974732063757272656e60648201527f7420737461747573000000000000000000000000000000000000000000000000608482015260a401610396565b600382600381111561122d5761122d611c80565b036112b957600181600381111561124657611246611c80565b146112b95760405162461bcd60e51b815260206004820152603860248201527f447269707069653a2064726970206d757374206669727374206265207061757360448201527f6564206265666f7265206265696e6720617263686976656400000000000000006064820152608401610396565b81600185856040516112cc929190612131565b90815260405190819003602001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183600381111561131357611313611c80565b02179055508383604051611328929190612131565b60405180910390207f407cb3ad05e60ec498fb39417c7a4f6b82d5ba80f82fe512a37b02c93181a2a1858585604051610c6193929190612308565b60005473ffffffffffffffffffffffffffffffffffffffff1633146113ca5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6000600184846040516113de929190612131565b9081526040519081900360200190205460ff16600381111561140257611402611c80565b146114755760405162461bcd60e51b815260206004820152602b60248201527f447269707069653a206472697020776974682074686174206e616d6520616c7260448201527f65616479206578697374730000000000000000000000000000000000000000006064820152608401610396565b611482602082018261232b565b15611504576020810135156114ff5760405162461bcd60e51b815260206004820152603e60248201527f447269707069653a20696620616c6c6f77696e67207265656e7472616e74206460448201527f7269702c206d7573742073657420696e74657276616c20746f207a65726f00006064820152608401610396565b6115a5565b60008160200135116115a55760405162461bcd60e51b8152602060048201526044602482018190527f447269707069653a20696e74657276616c206d75737420626520677265617465908201527f72207468616e207a65726f2069662064726970206973206e6f74207265656e7460648201527f72616e7400000000000000000000000000000000000000000000000000000000608482015260a401610396565b6000600184846040516115b9929190612131565b9081526040516020918190038201902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117815591506116009083018361232b565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556020820135600282015561164b6060830160408401611af9565b6003820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905561169f6060830183612348565b60048301916116af9190836123fc565b5060005b6116c060808401846124f9565b905081101561173357600582016116da60808501856124f9565b838181106116ea576116ea6121a8565b90506020028101906116fc9190612561565b81546001810183556000928352602090922090916003020161171e8282612595565b5050808061172b90612170565b9150506116b3565b508383604051611744929190612131565b60405180910390207fe38d8d98e6cc66f6f520d483c6c5a89289681f897799c4c29d767cf57e76d9a6858585604051610c619392919061286a565b6000805460609073ffffffffffffffffffffffffffffffffffffffff1633146117ea5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b8373ffffffffffffffffffffffffffffffffffffffff168360405161180f91906122d3565b600060405180830381855af49150503d806000811461184a576040519150601f19603f3d011682016040523d82523d6000602084013e61184f565b606091505b50915091505b9250929050565b60008060018484604051611871929190612131565b90815260405190819003602001902090506002815460ff16600381111561189a5761189a611c80565b1461190f576040805162461bcd60e51b81526020600482015260248101919091527f447269707069653a2073656c6563746564206472697020646f6573206e6f742060448201527f6578697374206f72206973206e6f742063757272656e746c79206163746976656064820152608401610396565b60028101546006820154429161192491612971565b11156119985760405162461bcd60e51b815260206004820152603660248201527f447269707069653a206472697020696e74657276616c20686173206e6f74206560448201527f6c61707365642073696e6365206c6173742064726970000000000000000000006064820152608401610396565b60038101546040517fc64b3bb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063c64b3bb5906119f29060048086019101612984565b602060405180830381865afa158015611a0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3391906120c1565b611acb5760405162461bcd60e51b815260206004820152604260248201527f447269707069653a2064726970636865636b206661696c656420736f2064726960448201527f70206973206e6f742079657420726561647920746f206265207472696767657260648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b60019150505b92915050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce057600080fd5b600060208284031215611b0b57600080fd5b8135611b1681611ad7565b9392505050565b600080600060608486031215611b3257600080fd5b8335611b3d81611ad7565b92506020840135611b4d81611ad7565b929592945050506040919091013590565b60008060408385031215611b7157600080fd5b8235611b7c81611ad7565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600067ffffffffffffffff80841115611bd457611bd4611b8a565b604051601f8501601f19908116603f01168101908282118183101715611bfc57611bfc611b8a565b81604052809350858152868686011115611c1557600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215611c4157600080fd5b813567ffffffffffffffff811115611c5857600080fd5b8201601f81018413611c6957600080fd5b611c7884823560208401611bb9565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110611ce6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b60005b83811015611d05578181015183820152602001611ced565b50506000910152565b60008151808452611d26816020860160208601611cea565b601f01601f19169290920160200192915050565b611d448186611caf565b600060206080818401528551151560808401528086015160a084015260408087015173ffffffffffffffffffffffffffffffffffffffff80821660c0870152606091508189015160a060e0880152611da0610120880182611d0e565b60808b01518882037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80016101008a0152805180835291925086019086830190600581901b8401880160005b82811015611e3657601f1986830301845284518781511683528a810151898c850152611e198a850182611d0e565b918b0151938b0193909352948a0194938a01939150600101611deb565b50968a019b909b52505050509093019390935250949350505050565b60008083601f840112611e6457600080fd5b50813567ffffffffffffffff811115611e7c57600080fd5b60208301915083602082850101111561185557600080fd5b60008060208385031215611ea757600080fd5b823567ffffffffffffffff811115611ebe57600080fd5b611eca85828601611e52565b90969095509350505050565b600082601f830112611ee757600080fd5b611b1683833560208501611bb9565b600080600060608486031215611f0b57600080fd5b8335611f1681611ad7565b9250602084013567ffffffffffffffff811115611f3257600080fd5b611f3e86828701611ed6565b925050604084013590509250925092565b8215158152604060208201526000611c786040830184611d0e565b60008060408385031215611f7d57600080fd5b8235611f8881611ad7565b91506020830135611f9881611ad7565b809150509250929050565b600080600060408486031215611fb857600080fd5b833567ffffffffffffffff811115611fcf57600080fd5b611fdb86828701611e52565b909450925050602084013560048110611ff357600080fd5b809150509250925092565b60008060006040848603121561201357600080fd5b833567ffffffffffffffff8082111561202b57600080fd5b61203787838801611e52565b9095509350602086013591508082111561205057600080fd5b50840160a08187031215611ff357600080fd5b6000806040838503121561207657600080fd5b823561208181611ad7565b9150602083013567ffffffffffffffff81111561209d57600080fd5b6120a985828601611ed6565b9150509250929050565b8015158114610ce057600080fd5b6000602082840312156120d357600080fd5b8151611b16816120b3565b600181811c908216806120f257607f821691505b60208210810361212b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121a1576121a1612141565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083546121e5816120de565b600182811680156121fd57600181146122305761225f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008416875282151583028701945061225f565b8760005260208060002060005b858110156122565781548a82015290840190820161223d565b50505082870194505b50929695505050505050565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b6060815260006122aa60608301868861226b565b73ffffffffffffffffffffffffffffffffffffffff949094166020830152506040015292915050565b600082516122e5818460208701611cea565b9190910192915050565b60006020828403121561230157600080fd5b5051919050565b60408152600061231c60408301858761226b565b9050611c786020830184611caf565b60006020828403121561233d57600080fd5b8135611b16816120b3565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261237d57600080fd5b83018035915067ffffffffffffffff82111561239857600080fd5b60200191503681900382131561185557600080fd5b601f8211156123f757600081815260208120601f850160051c810160208610156123d45750805b601f850160051c820191505b818110156123f3578281556001016123e0565b5050505b505050565b67ffffffffffffffff83111561241457612414611b8a565b6124288361242283546120de565b836123ad565b6000601f84116001811461247a57600085156124445750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556124f2565b600083815260209020601f19861690835b828110156124ab578685013582556020948501946001909201910161248b565b50868210156124e6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261252e57600080fd5b83018035915067ffffffffffffffff82111561254957600080fd5b6020019150600581901b360382131561185557600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126122e557600080fd5b81356125a081611ad7565b73ffffffffffffffffffffffffffffffffffffffff81167fffffffffffffffffffffffff00000000000000000000000000000000000000008354161782555060018082016020808501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe186360301811261261a57600080fd5b8501803567ffffffffffffffff81111561263357600080fd5b803603838301131561264457600080fd5b6126588161265286546120de565b866123ad565b6000601f8211600181146126ac576000831561267657508382018501355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b178655612723565b600086815260209020601f19841690835b828110156126dc578685018801358255938701939089019087016126bd565b5084821015612719577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c198785880101351681555b50508683881b0186555b50505050505050604082013560028201555050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261276d57600080fd5b830160208101925035905067ffffffffffffffff81111561278d57600080fd5b80360382131561185557600080fd5b81835260006020808501808196508560051b81019150846000805b8881101561285c578385038a5282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18936030181126127f5578283fd5b88016060813561280481611ad7565b73ffffffffffffffffffffffffffffffffffffffff16875261282882890183612738565b828a8a015261283a838a01828461226b565b60409485013599909401989098525050998601999450918501916001016127b7565b509298975050505050505050565b60408152600061287e60408301858761226b565b82810360208401528335612891816120b3565b151581526020848101359082015260408401356128ad81611ad7565b73ffffffffffffffffffffffffffffffffffffffff1660408201526128d56060850185612738565b60a060608401526128ea60a08401828461226b565b91505060808501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe186360301811261292257600080fd5b850160208101903567ffffffffffffffff81111561293f57600080fd5b8060051b360382131561295157600080fd5b838303608085015261296483828461279c565b9998505050505050505050565b80820180821115611ad157611ad1612141565b6000602080835260008454612998816120de565b808487015260406001808416600081146129b957600181146129f157612a1f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550612a1f565b896000528660002060005b85811015612a175781548b82018601529083019088016129fc565b8a0184019650505b50939897505050505050505056fea26469706673582212208d60ccb026b0dcc2e3511887db1b30dfd98f123af2a2a96714cbeca8ed21494464736f6c63430008100033", - "deployedBytecode": "0x6080604052600436106100e15760003560e01c80636e2d44ae1161007f5780639bc94d01116100595780639bc94d01146102b0578063e551cdaa146102d0578063edee6239146102f0578063fc3e3eba1461030357600080fd5b80636e2d44ae1461021d5780638da5cb5b1461023e5780639456fbcc1461029057600080fd5b80634782f779116100bb5780634782f779146101845780634d7fba6e146101a457806367148cd2146101dd578063690d8320146101fd57600080fd5b806313af4035146101225780634025feb21461014457806344004cc11461016457600080fd5b3661011d5760405134815233907f4103257eaac983ca79a70d28f90dfc4fa16b619bb0c17ee7cab0d4034c2796249060200160405180910390a2005b600080fd5b34801561012e57600080fd5b5061014261013d366004611af9565b610333565b005b34801561015057600080fd5b5061014261015f366004611b1d565b61040f565b34801561017057600080fd5b5061014261017f366004611b1d565b610587565b34801561019057600080fd5b5061014261019f366004611b5e565b6106fe565b3480156101b057600080fd5b506101c46101bf366004611c2f565b610834565b6040516101d49493929190611d3a565b60405180910390f35b3480156101e957600080fd5b506101426101f8366004611e94565b610a66565b34801561020957600080fd5b50610142610218366004611af9565b610c6f565b61023061022b366004611ef6565b610ce3565b6040516101d4929190611f4f565b34801561024a57600080fd5b5060005461026b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d4565b34801561029c57600080fd5b506101426102ab366004611f6a565b610dc3565b3480156102bc57600080fd5b506101426102cb366004611fa3565b610ec4565b3480156102dc57600080fd5b506101426102eb366004611ffe565b611363565b6102306102fe366004612063565b61177f565b34801561030f57600080fd5b5061032361031e366004611e94565b61185c565b60405190151581526020016101d4565b60005473ffffffffffffffffffffffffffffffffffffffff16331461039f5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104765760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b1580156104ec57600080fd5b505af1158015610500573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f30b478a5e196e55886228aa87ba74a7dfeba655e0a4d7ba275eabfc22aabb7a88460405161057a91815260200190565b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105ee5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb906044016020604051808303816000875af1158015610663573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068791906120c1565b508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f6b00f1c7883f053ba83e907fd1965b22fffe3c4111383e725f04638a566cdbfa8460405161057a91815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107655760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146107bf576040519150601f19603f3d011682016040523d82523d6000602084013e6107c4565b606091505b505090508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f1f12aa8b6d492dd9b98e2b00b0b20830c2a7ded65afac13b60d169a034ae90bc8460405161082791815260200190565b60405180910390a3505050565b805160208183018101805160018083529383019483019490942093905282546040805160a081018252938501805460ff90811615158652600287015494860194909452600386015473ffffffffffffffffffffffffffffffffffffffff169185019190915260048501805493909216949392909160608401916108b6906120de565b80601f01602080910402602001604051908101604052809291908181526020018280546108e2906120de565b801561092f5780601f106109045761010080835404028352916020019161092f565b820191906000526020600020905b81548152906001019060200180831161091257829003601f168201915b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b82821015610a4e576000848152602090819020604080516060810190915260038502909101805473ffffffffffffffffffffffffffffffffffffffff16825260018101805492939192918401916109b3906120de565b80601f01602080910402602001604051908101604052809291908181526020018280546109df906120de565b8015610a2c5780601f10610a0157610100808354040283529160200191610a2c565b820191906000526020600020905b815481529060010190602001808311610a0f57829003601f168201915b505050505081526020016002820154815250508152602001906001019061095d565b50505091525050600682015460079092015490919084565b600060018383604051610a7a929190612131565b90815260200160405180910390209050610a94838361185c565b50426006820155600781018054906000610aad83612170565b9091555050600581015460005b81811015610c13576000836001016004018281548110610adc57610adc6121a8565b6000918252602082206003909102018054600282015460405192945073ffffffffffffffffffffffffffffffffffffffff90911691610b1f9060018601906121d7565b60006040518083038185875af1925050503d8060008114610b5c576040519150601f19603f3d011682016040523d82523d6000602084013e610b61565b606091505b5050905080610bfe5760405162461bcd60e51b815260206004820152604c60248201527f447269707069653a20647269702077617320756e7375636365737366756c2c2060448201527f706c6561736520636865636b20796f757220636f6e66696775726174696f6e2060648201527f666f72206d697374616b65730000000000000000000000000000000000000000608482015260a401610396565b50508080610c0b90612170565b915050610aba565b508383604051610c24929190612131565b60405180910390207fea21435419aad9c54a9d90e2522b6f60bd566401f36fcef661f5f5a28cc0d2c685853342604051610c619493929190612296565b60405180910390a250505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610cd65760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b610ce081476106fe565b50565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610d4e5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b8473ffffffffffffffffffffffffffffffffffffffff168385604051610d7491906122d3565b60006040518083038185875af1925050503d8060008114610db1576040519150601f19603f3d011682016040523d82523d6000602084013e610db6565b606091505b5091509150935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e2a5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610ec0908390839073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610e9c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061017f91906122ef565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610f2b5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6000816003811115610f3f57610f3f611c80565b03610fd85760405162461bcd60e51b815260206004820152604160248201527f447269707069653a2064726970207374617475732063616e206e65766572206260448201527f6520736574206261636b20746f204e4f4e45206166746572206372656174696f60648201527f6e00000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b600060018484604051610fec929190612131565b9081526040519081900360200190205460ff169050600081600381111561101557611015611c80565b036110ae5760405162461bcd60e51b815260206004820152604160248201527f447269707069653a206472697020776974682074686174206e616d6520646f6560448201527f73206e6f7420657869737420616e642063616e6e6f742062652075706461746560648201527f6400000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b60038160038111156110c2576110c2611c80565b0361115c5760405162461bcd60e51b8152602060048201526044602482018190527f447269707069653a206472697020776974682074686174206e616d6520686173908201527f206265656e20617263686976656420616e642063616e6e6f742062652075706460648201527f6174656400000000000000000000000000000000000000000000000000000000608482015260a401610396565b81600381111561116e5761116e611c80565b81600381111561118057611180611c80565b036112195760405162461bcd60e51b815260206004820152604860248201527f447269707069653a2063616e6e6f74207365742064726970207374617475732060448201527f746f207468652073616d6520737461747573206173206974732063757272656e60648201527f7420737461747573000000000000000000000000000000000000000000000000608482015260a401610396565b600382600381111561122d5761122d611c80565b036112b957600181600381111561124657611246611c80565b146112b95760405162461bcd60e51b815260206004820152603860248201527f447269707069653a2064726970206d757374206669727374206265207061757360448201527f6564206265666f7265206265696e6720617263686976656400000000000000006064820152608401610396565b81600185856040516112cc929190612131565b90815260405190819003602001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183600381111561131357611313611c80565b02179055508383604051611328929190612131565b60405180910390207f407cb3ad05e60ec498fb39417c7a4f6b82d5ba80f82fe512a37b02c93181a2a1858585604051610c6193929190612308565b60005473ffffffffffffffffffffffffffffffffffffffff1633146113ca5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6000600184846040516113de929190612131565b9081526040519081900360200190205460ff16600381111561140257611402611c80565b146114755760405162461bcd60e51b815260206004820152602b60248201527f447269707069653a206472697020776974682074686174206e616d6520616c7260448201527f65616479206578697374730000000000000000000000000000000000000000006064820152608401610396565b611482602082018261232b565b15611504576020810135156114ff5760405162461bcd60e51b815260206004820152603e60248201527f447269707069653a20696620616c6c6f77696e67207265656e7472616e74206460448201527f7269702c206d7573742073657420696e74657276616c20746f207a65726f00006064820152608401610396565b6115a5565b60008160200135116115a55760405162461bcd60e51b8152602060048201526044602482018190527f447269707069653a20696e74657276616c206d75737420626520677265617465908201527f72207468616e207a65726f2069662064726970206973206e6f74207265656e7460648201527f72616e7400000000000000000000000000000000000000000000000000000000608482015260a401610396565b6000600184846040516115b9929190612131565b9081526040516020918190038201902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117815591506116009083018361232b565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556020820135600282015561164b6060830160408401611af9565b6003820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905561169f6060830183612348565b60048301916116af9190836123fc565b5060005b6116c060808401846124f9565b905081101561173357600582016116da60808501856124f9565b838181106116ea576116ea6121a8565b90506020028101906116fc9190612561565b81546001810183556000928352602090922090916003020161171e8282612595565b5050808061172b90612170565b9150506116b3565b508383604051611744929190612131565b60405180910390207fe38d8d98e6cc66f6f520d483c6c5a89289681f897799c4c29d767cf57e76d9a6858585604051610c619392919061286a565b6000805460609073ffffffffffffffffffffffffffffffffffffffff1633146117ea5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b8373ffffffffffffffffffffffffffffffffffffffff168360405161180f91906122d3565b600060405180830381855af49150503d806000811461184a576040519150601f19603f3d011682016040523d82523d6000602084013e61184f565b606091505b50915091505b9250929050565b60008060018484604051611871929190612131565b90815260405190819003602001902090506002815460ff16600381111561189a5761189a611c80565b1461190f576040805162461bcd60e51b81526020600482015260248101919091527f447269707069653a2073656c6563746564206472697020646f6573206e6f742060448201527f6578697374206f72206973206e6f742063757272656e746c79206163746976656064820152608401610396565b60028101546006820154429161192491612971565b11156119985760405162461bcd60e51b815260206004820152603660248201527f447269707069653a206472697020696e74657276616c20686173206e6f74206560448201527f6c61707365642073696e6365206c6173742064726970000000000000000000006064820152608401610396565b60038101546040517fc64b3bb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063c64b3bb5906119f29060048086019101612984565b602060405180830381865afa158015611a0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3391906120c1565b611acb5760405162461bcd60e51b815260206004820152604260248201527f447269707069653a2064726970636865636b206661696c656420736f2064726960448201527f70206973206e6f742079657420726561647920746f206265207472696767657260648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b60019150505b92915050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce057600080fd5b600060208284031215611b0b57600080fd5b8135611b1681611ad7565b9392505050565b600080600060608486031215611b3257600080fd5b8335611b3d81611ad7565b92506020840135611b4d81611ad7565b929592945050506040919091013590565b60008060408385031215611b7157600080fd5b8235611b7c81611ad7565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600067ffffffffffffffff80841115611bd457611bd4611b8a565b604051601f8501601f19908116603f01168101908282118183101715611bfc57611bfc611b8a565b81604052809350858152868686011115611c1557600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215611c4157600080fd5b813567ffffffffffffffff811115611c5857600080fd5b8201601f81018413611c6957600080fd5b611c7884823560208401611bb9565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110611ce6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b60005b83811015611d05578181015183820152602001611ced565b50506000910152565b60008151808452611d26816020860160208601611cea565b601f01601f19169290920160200192915050565b611d448186611caf565b600060206080818401528551151560808401528086015160a084015260408087015173ffffffffffffffffffffffffffffffffffffffff80821660c0870152606091508189015160a060e0880152611da0610120880182611d0e565b60808b01518882037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80016101008a0152805180835291925086019086830190600581901b8401880160005b82811015611e3657601f1986830301845284518781511683528a810151898c850152611e198a850182611d0e565b918b0151938b0193909352948a0194938a01939150600101611deb565b50968a019b909b52505050509093019390935250949350505050565b60008083601f840112611e6457600080fd5b50813567ffffffffffffffff811115611e7c57600080fd5b60208301915083602082850101111561185557600080fd5b60008060208385031215611ea757600080fd5b823567ffffffffffffffff811115611ebe57600080fd5b611eca85828601611e52565b90969095509350505050565b600082601f830112611ee757600080fd5b611b1683833560208501611bb9565b600080600060608486031215611f0b57600080fd5b8335611f1681611ad7565b9250602084013567ffffffffffffffff811115611f3257600080fd5b611f3e86828701611ed6565b925050604084013590509250925092565b8215158152604060208201526000611c786040830184611d0e565b60008060408385031215611f7d57600080fd5b8235611f8881611ad7565b91506020830135611f9881611ad7565b809150509250929050565b600080600060408486031215611fb857600080fd5b833567ffffffffffffffff811115611fcf57600080fd5b611fdb86828701611e52565b909450925050602084013560048110611ff357600080fd5b809150509250925092565b60008060006040848603121561201357600080fd5b833567ffffffffffffffff8082111561202b57600080fd5b61203787838801611e52565b9095509350602086013591508082111561205057600080fd5b50840160a08187031215611ff357600080fd5b6000806040838503121561207657600080fd5b823561208181611ad7565b9150602083013567ffffffffffffffff81111561209d57600080fd5b6120a985828601611ed6565b9150509250929050565b8015158114610ce057600080fd5b6000602082840312156120d357600080fd5b8151611b16816120b3565b600181811c908216806120f257607f821691505b60208210810361212b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121a1576121a1612141565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083546121e5816120de565b600182811680156121fd57600181146122305761225f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008416875282151583028701945061225f565b8760005260208060002060005b858110156122565781548a82015290840190820161223d565b50505082870194505b50929695505050505050565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b6060815260006122aa60608301868861226b565b73ffffffffffffffffffffffffffffffffffffffff949094166020830152506040015292915050565b600082516122e5818460208701611cea565b9190910192915050565b60006020828403121561230157600080fd5b5051919050565b60408152600061231c60408301858761226b565b9050611c786020830184611caf565b60006020828403121561233d57600080fd5b8135611b16816120b3565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261237d57600080fd5b83018035915067ffffffffffffffff82111561239857600080fd5b60200191503681900382131561185557600080fd5b601f8211156123f757600081815260208120601f850160051c810160208610156123d45750805b601f850160051c820191505b818110156123f3578281556001016123e0565b5050505b505050565b67ffffffffffffffff83111561241457612414611b8a565b6124288361242283546120de565b836123ad565b6000601f84116001811461247a57600085156124445750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556124f2565b600083815260209020601f19861690835b828110156124ab578685013582556020948501946001909201910161248b565b50868210156124e6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261252e57600080fd5b83018035915067ffffffffffffffff82111561254957600080fd5b6020019150600581901b360382131561185557600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126122e557600080fd5b81356125a081611ad7565b73ffffffffffffffffffffffffffffffffffffffff81167fffffffffffffffffffffffff00000000000000000000000000000000000000008354161782555060018082016020808501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe186360301811261261a57600080fd5b8501803567ffffffffffffffff81111561263357600080fd5b803603838301131561264457600080fd5b6126588161265286546120de565b866123ad565b6000601f8211600181146126ac576000831561267657508382018501355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b178655612723565b600086815260209020601f19841690835b828110156126dc578685018801358255938701939089019087016126bd565b5084821015612719577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c198785880101351681555b50508683881b0186555b50505050505050604082013560028201555050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261276d57600080fd5b830160208101925035905067ffffffffffffffff81111561278d57600080fd5b80360382131561185557600080fd5b81835260006020808501808196508560051b81019150846000805b8881101561285c578385038a5282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18936030181126127f5578283fd5b88016060813561280481611ad7565b73ffffffffffffffffffffffffffffffffffffffff16875261282882890183612738565b828a8a015261283a838a01828461226b565b60409485013599909401989098525050998601999450918501916001016127b7565b509298975050505050505050565b60408152600061287e60408301858761226b565b82810360208401528335612891816120b3565b151581526020848101359082015260408401356128ad81611ad7565b73ffffffffffffffffffffffffffffffffffffffff1660408201526128d56060850185612738565b60a060608401526128ea60a08401828461226b565b91505060808501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe186360301811261292257600080fd5b850160208101903567ffffffffffffffff81111561293f57600080fd5b8060051b360382131561295157600080fd5b838303608085015261296483828461279c565b9998505050505050505050565b80820180821115611ad157611ad1612141565b6000602080835260008454612998816120de565b808487015260406001808416600081146129b957600181146129f157612a1f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550612a1f565b896000528660002060005b85811015612a175781548b82018601529083019088016129fc565b8a0184019650505b50939897505050505050505056fea26469706673582212208d60ccb026b0dcc2e3511887db1b30dfd98f123af2a2a96714cbeca8ed21494464736f6c63430008100033", - "devdoc": { - "events": { - "DripCreated(string,string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))": { - "params": { - "config": "Config for the created drip.", - "name": "Unindexed name parameter (unhashed).", - "nameref": "Indexed name parameter (hashed)." - } - }, - "DripExecuted(string,string,address,uint256)": { - "params": { - "executor": "Address that executed the drip.", - "name": "Unindexed name parameter (unhashed).", - "nameref": "Indexed name parameter (hashed).", - "timestamp": "Time when the drip was executed." - } - }, - "DripStatusUpdated(string,string,uint8)": { - "params": { - "name": "Unindexed name parameter (unhashed).", - "nameref": "Indexed name parameter (hashed).", - "status": "New drip status." - } - } - }, - "kind": "dev", - "methods": { - "CALL(address,bytes,uint256)": { - "params": { - "_data": "Data to send with the call.", - "_target": "Address to call.", - "_value": "ETH value to send with the call." - }, - "returns": { - "_0": "Boolean success value.", - "_1": "Bytes data returned by the call." - } - }, - "DELEGATECALL(address,bytes)": { - "params": { - "_data": "Data to send with the call.", - "_target": "Address to call." - }, - "returns": { - "_0": "Boolean success value.", - "_1": "Bytes data returned by the call." - } - }, - "constructor": { - "params": { - "_owner": "Initial contract owner." - } - }, - "create(string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))": { - "params": { - "_config": "Configuration for the drip.", - "_name": "Name of the drip." - } - }, - "drip(string)": { - "params": { - "_name": "Name of the drip to trigger." - } - }, - "executable(string)": { - "params": { - "_name": "Drip to check." - }, - "returns": { - "_0": "True if the drip is executable, reverts otherwise." - } - }, - "status(string,uint8)": { - "params": { - "_name": "Name of the drip to update.", - "_status": "New drip status." - } - }, - "withdrawERC20(address,address)": { - "params": { - "_asset": "ERC20 token to withdraw.", - "_to": "Address to receive the ERC20 balance." - } - }, - "withdrawERC20(address,address,uint256)": { - "params": { - "_amount": "Amount of ERC20 to withdraw.", - "_asset": "ERC20 token to withdraw.", - "_to": "Address to receive the ERC20 balance." - } - }, - "withdrawERC721(address,address,uint256)": { - "params": { - "_asset": "ERC721 token to withdraw.", - "_id": "Token ID of the ERC721 token to withdraw.", - "_to": "Address to receive the ERC721 token." - } - }, - "withdrawETH(address)": { - "params": { - "_to": "Address to receive the ETH balance." - } - }, - "withdrawETH(address,uint256)": { - "params": { - "_amount": "Amount of ETH to withdraw.", - "_to": "Address to receive the ETH balance." - } - } - }, - "title": "Drippie", - "version": 1 - }, - "userdoc": { - "events": { - "DripCreated(string,string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))": { - "notice": "Emitted when a new drip is created." - }, - "DripExecuted(string,string,address,uint256)": { - "notice": "Emitted when a drip is executed." - }, - "DripStatusUpdated(string,string,uint8)": { - "notice": "Emitted when a drip status is updated." - }, - "ReceivedETH(address,uint256)": { - "notice": "Emitted when ETH is received by this address." - }, - "WithdrewERC20(address,address,address,uint256)": { - "notice": "Emitted when ERC20 tokens are withdrawn from this address." - }, - "WithdrewERC721(address,address,address,uint256)": { - "notice": "Emitted when ERC20 tokens are withdrawn from this address." - }, - "WithdrewETH(address,address,uint256)": { - "notice": "Emitted when ETH is withdrawn from this address." - } - }, - "kind": "user", - "methods": { - "CALL(address,bytes,uint256)": { - "notice": "Sends a CALL to a target address." - }, - "DELEGATECALL(address,bytes)": { - "notice": "Sends a DELEGATECALL to a target address." - }, - "create(string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))": { - "notice": "Creates a new drip with the given name and configuration. Once created, drips cannot be modified in any way (this is a security measure). If you want to update a drip, simply pause (and potentially archive) the existing drip and create a new one." - }, - "drip(string)": { - "notice": "Triggers a drip. This function is deliberately left as a public function because the assumption being made here is that setting the drip to ACTIVE is an affirmative signal that the drip should be executable according to the drip parameters, drip check, and drip interval. Note that drip parameters are read entirely from the state and are not supplied as user input, so there should not be any way for a non-authorized user to influence the behavior of the drip. Note that the drip check is executed only **once** at the beginning of the call to the drip function and will not be executed again between the drip actions within this call." - }, - "drips(string)": { - "notice": "Maps from drip names to drip states." - }, - "executable(string)": { - "notice": "Checks if a given drip is executable." - }, - "status(string,uint8)": { - "notice": "Sets the status for a given drip. The behavior of this function depends on the status that the user is trying to set. A drip can always move between ACTIVE and PAUSED, but it can never move back to NONE and once ARCHIVED, it can never move back to ACTIVE or PAUSED." - }, - "withdrawERC20(address,address)": { - "notice": "Withdraws full ERC20 balance to the recipient." - }, - "withdrawERC20(address,address,uint256)": { - "notice": "Withdraws partial ERC20 balance to the recipient." - }, - "withdrawERC721(address,address,uint256)": { - "notice": "Withdraws ERC721 token to the recipient." - }, - "withdrawETH(address)": { - "notice": "Withdraws full ETH balance to the recipient." - }, - "withdrawETH(address,uint256)": { - "notice": "Withdraws partial ETH balance to the recipient." - } - }, - "notice": "Drippie is a system for managing automated contract interactions. A specific interaction is called a \"drip\" and can be executed according to some condition (called a dripcheck) and an execution interval. Drips cannot be executed faster than the execution interval. Drips can trigger arbitrary contract calls where the calling contract is this contract address. Drips can also send ETH value, which makes them ideal for keeping addresses sufficiently funded with ETH. Drippie is designed to be connected with smart contract automation services so that drips can be executed automatically. However, Drippie is specifically designed to be separated from these services so that trust assumptions are better compartmentalized.", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 10, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "owner", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 1431, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "drips", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_string_memory_ptr,t_struct(DripState)1394_storage)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_address_payable": { - "encoding": "inplace", - "label": "address payable", - "numberOfBytes": "20" - }, - "t_array(t_struct(DripAction)1369_storage)dyn_storage": { - "base": "t_struct(DripAction)1369_storage", - "encoding": "dynamic_array", - "label": "struct Drippie.DripAction[]", - "numberOfBytes": "32" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes_storage": { - "encoding": "bytes", - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(IDripCheck)1794": { - "encoding": "inplace", - "label": "contract IDripCheck", - "numberOfBytes": "20" - }, - "t_enum(DripStatus)1362": { - "encoding": "inplace", - "label": "enum Drippie.DripStatus", - "numberOfBytes": "1" - }, - "t_mapping(t_string_memory_ptr,t_struct(DripState)1394_storage)": { - "encoding": "mapping", - "key": "t_string_memory_ptr", - "label": "mapping(string => struct Drippie.DripState)", - "numberOfBytes": "32", - "value": "t_struct(DripState)1394_storage" - }, - "t_string_memory_ptr": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_struct(DripAction)1369_storage": { - "encoding": "inplace", - "label": "struct Drippie.DripAction", - "members": [ - { - "astId": 1364, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "target", - "offset": 0, - "slot": "0", - "type": "t_address_payable" - }, - { - "astId": 1366, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "data", - "offset": 0, - "slot": "1", - "type": "t_bytes_storage" - }, - { - "astId": 1368, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "value", - "offset": 0, - "slot": "2", - "type": "t_uint256" - } - ], - "numberOfBytes": "96" - }, - "t_struct(DripConfig)1383_storage": { - "encoding": "inplace", - "label": "struct Drippie.DripConfig", - "members": [ - { - "astId": 1371, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "reentrant", - "offset": 0, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 1373, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "interval", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 1376, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "dripcheck", - "offset": 0, - "slot": "2", - "type": "t_contract(IDripCheck)1794" - }, - { - "astId": 1378, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "checkparams", - "offset": 0, - "slot": "3", - "type": "t_bytes_storage" - }, - { - "astId": 1382, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "actions", - "offset": 0, - "slot": "4", - "type": "t_array(t_struct(DripAction)1369_storage)dyn_storage" - } - ], - "numberOfBytes": "160" - }, - "t_struct(DripState)1394_storage": { - "encoding": "inplace", - "label": "struct Drippie.DripState", - "members": [ - { - "astId": 1386, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "status", - "offset": 0, - "slot": "0", - "type": "t_enum(DripStatus)1362" - }, - { - "astId": 1389, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "config", - "offset": 0, - "slot": "1", - "type": "t_struct(DripConfig)1383_storage" - }, - { - "astId": 1391, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "last", - "offset": 0, - "slot": "6", - "type": "t_uint256" - }, - { - "astId": 1393, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "count", - "offset": 0, - "slot": "7", - "type": "t_uint256" - } - ], - "numberOfBytes": "256" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/L1CrossDomainMessenger.json b/packages/contracts-bedrock/deployments/goerli/L1CrossDomainMessenger.json deleted file mode 100644 index 16322d5ae8ab..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/L1CrossDomainMessenger.json +++ /dev/null @@ -1,851 +0,0 @@ -{ - "abi": [ - { - "inputs": [ - { - "internalType": "contract OptimismPortal", - "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": "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" - }, - { - "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_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": [], - "name": "OTHER_MESSENGER", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PORTAL", - "outputs": [ - { - "internalType": "contract OptimismPortal", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAY_CALL_OVERHEAD", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAY_CONSTANT_OVERHEAD", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAY_GAS_CHECK_BUFFER", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAY_RESERVED_GAS", - "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": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "failedMessages", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract SuperchainConfig", - "name": "_superchainConfig", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "messageNonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "portal", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "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": [ - { - "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": [], - "name": "superchainConfig", - "outputs": [ - { - "internalType": "contract SuperchainConfig", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "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" - } - ], - "address": "0x7C195AFFC48399546A0979aD2C740a022d524BA6", - "args": [ - "0x5b47E1A08Ea6d985D6649300584e6722Ec4B1383" - ], - "bytecode": "0x60c06040523480156200001157600080fd5b506040516200223d3803806200223d833981016040819052620000349162000269565b7342000000000000000000000000000000000000076080526001600160a01b03811660a0526200006560006200006c565b506200029b565b600054600160a81b900460ff16158080156200009557506000546001600160a01b90910460ff16105b80620000cc5750620000b230620001d560201b620014771760201c565b158015620000cc5750600054600160a01b900460ff166001145b620001355760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b179055801562000163576000805460ff60a81b1916600160a81b1790555b60fb80546001600160a01b0319166001600160a01b03841617905562000188620001e4565b8015620001d1576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054600160a81b900460ff16620002535760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200012c565b60cc80546001600160a01b03191661dead179055565b6000602082840312156200027c57600080fd5b81516001600160a01b03811681146200029457600080fd5b9392505050565b60805160a051611f4b620002f2600039600081816101d401528181610350015281816114d00152818161167d015281816116de01526117aa0152600081816103b2015281816104f101526116a70152611f4b6000f3fe6080604052600436106101755760003560e01c80636425666b116100cb578063a4e7f8bd1161007f578063c4d66de811610059578063c4d66de814610454578063d764ad0b14610474578063ecc704281461048757600080fd5b8063a4e7f8bd146103d4578063b1b1b20914610404578063b28ade251461043457600080fd5b806383a74074116100b057806383a74074146103895780638cbeeef21461029a5780639fce812c146103a057600080fd5b80636425666b146103415780636e296e451461037457600080fd5b80633dbb202b1161012d57806354fd4d501161010757806354fd4d50146102b05780635644cfdf146103065780635c975abb1461031c57600080fd5b80633dbb202b1461025d5780633f827a5a146102725780634c1d6a691461029a57600080fd5b80630ff754ea1161015e5780630ff754ea146101c25780632828d7e81461021b57806335e80ab31461023057600080fd5b8063028f85f71461017a5780630c568498146101ad575b600080fd5b34801561018657600080fd5b5061018f601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b5061018f603f81565b3480156101ce57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a4565b34801561022757600080fd5b5061018f604081565b34801561023c57600080fd5b5060fb546101f69073ffffffffffffffffffffffffffffffffffffffff1681565b61027061026b3660046119f5565b6104ec565b005b34801561027e57600080fd5b50610287600181565b60405161ffff90911681526020016101a4565b3480156102a657600080fd5b5061018f619c4081565b3480156102bc57600080fd5b506102f96040518060400160405280600581526020017f322e312e3100000000000000000000000000000000000000000000000000000081525081565b6040516101a49190611ac7565b34801561031257600080fd5b5061018f61138881565b34801561032857600080fd5b50610331610750565b60405190151581526020016101a4565b34801561034d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101f6565b34801561038057600080fd5b506101f66107e9565b34801561039557600080fd5b5061018f62030d4081565b3480156103ac57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b3480156103e057600080fd5b506103316103ef366004611ae1565b60ce6020526000908152604090205460ff1681565b34801561041057600080fd5b5061033161041f366004611ae1565b60cb6020526000908152604090205460ff1681565b34801561044057600080fd5b5061018f61044f366004611afa565b6108d5565b34801561046057600080fd5b5061027061046f366004611b4e565b610943565b610270610482366004611b6b565b610b81565b34801561049357600080fd5b506104de60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a4565b6106257f000000000000000000000000000000000000000000000000000000000000000061051b8585856108d5565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061058760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105a39796959493929190611c3a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611493565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856106aa60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516106bc959493929190611c99565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156107c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e49190611ce7565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016108b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6108f1604063ffffffff8816611d38565b6108fb9190611d68565b610906601088611d38565b6109139062030d40611db6565b61091d9190611db6565b6109279190611db6565b6109319190611db6565b61093b9190611db6565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff161580801561098e575060005460017401000000000000000000000000000000000000000090910460ff16105b806109c05750303b1580156109c0575060005474010000000000000000000000000000000000000000900460ff166001145b610a4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016108af565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610ad257600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055610b1a611548565b8015610b7d57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610b89610750565b15610bf0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016108af565b60f087901c60028110610cab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016108af565b8061ffff16600003610da0576000610cfc878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f9250611621915050565b600081815260cb602052604090205490915060ff1615610d9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016108af565b505b6000610de6898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164092505050565b9050610df0611663565b15610e2857853414610e0457610e04611de2565b600081815260ce602052604090205460ff1615610e2357610e23611de2565b610f7a565b3415610edc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016108af565b600081815260ce602052604090205460ff16610f7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016108af565b610f8387611787565b15611036576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016108af565b600081815260cb602052604090205460ff16156110d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016108af565b6110f6856110e7611388619c40611db6565b67ffffffffffffffff166117fe565b158061111c575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561123557600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161122e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b505061146e565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006112c688619c405a6112899190611e11565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061181c92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561135d57600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a261146a565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c42908490611510908890839089906000908990600401611e28565b6000604051808303818588803b15801561152957600080fd5b505af115801561153d573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff166115f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016108af565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b600061162f85858585611836565b805190602001209050949350505050565b60006116508787878787876118cf565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156107e457507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa158015611747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176b9190611e80565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff82163014806117f857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b60608484848460405160240161184f9493929190611e9d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b60608686868686866040516024016118ec96959493929190611ee7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461199057600080fd5b50565b60008083601f8401126119a557600080fd5b50813567ffffffffffffffff8111156119bd57600080fd5b6020830191508360208285010111156119d557600080fd5b9250929050565b803563ffffffff811681146119f057600080fd5b919050565b60008060008060608587031215611a0b57600080fd5b8435611a168161196e565b9350602085013567ffffffffffffffff811115611a3257600080fd5b611a3e87828801611993565b9094509250611a519050604086016119dc565b905092959194509250565b6000815180845260005b81811015611a8257602081850181015186830182015201611a66565b81811115611a94576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611ada6020830184611a5c565b9392505050565b600060208284031215611af357600080fd5b5035919050565b600080600060408486031215611b0f57600080fd5b833567ffffffffffffffff811115611b2657600080fd5b611b3286828701611993565b9094509250611b459050602085016119dc565b90509250925092565b600060208284031215611b6057600080fd5b8135611ada8161196e565b600080600080600080600060c0888a031215611b8657600080fd5b873596506020880135611b988161196e565b95506040880135611ba88161196e565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611bd257600080fd5b611bde8a828b01611993565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611c8c60c083018486611bf1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611cc9608083018688611bf1565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611cf957600080fd5b81518015158114611ada57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611d5f57611d5f611d09565b02949350505050565b600067ffffffffffffffff80841680611daa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611dd957611dd9611d09565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611e2357611e23611d09565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611e7560a0830184611a5c565b979650505050505050565b600060208284031215611e9257600080fd5b8151611ada8161196e565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611ed66080830185611a5c565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611f3260c0830184611a5c565b9897505050505050505056fea164736f6c634300080f000a", - "deployedBytecode": "0x6080604052600436106101755760003560e01c80636425666b116100cb578063a4e7f8bd1161007f578063c4d66de811610059578063c4d66de814610454578063d764ad0b14610474578063ecc704281461048757600080fd5b8063a4e7f8bd146103d4578063b1b1b20914610404578063b28ade251461043457600080fd5b806383a74074116100b057806383a74074146103895780638cbeeef21461029a5780639fce812c146103a057600080fd5b80636425666b146103415780636e296e451461037457600080fd5b80633dbb202b1161012d57806354fd4d501161010757806354fd4d50146102b05780635644cfdf146103065780635c975abb1461031c57600080fd5b80633dbb202b1461025d5780633f827a5a146102725780634c1d6a691461029a57600080fd5b80630ff754ea1161015e5780630ff754ea146101c25780632828d7e81461021b57806335e80ab31461023057600080fd5b8063028f85f71461017a5780630c568498146101ad575b600080fd5b34801561018657600080fd5b5061018f601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b5061018f603f81565b3480156101ce57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a4565b34801561022757600080fd5b5061018f604081565b34801561023c57600080fd5b5060fb546101f69073ffffffffffffffffffffffffffffffffffffffff1681565b61027061026b3660046119f5565b6104ec565b005b34801561027e57600080fd5b50610287600181565b60405161ffff90911681526020016101a4565b3480156102a657600080fd5b5061018f619c4081565b3480156102bc57600080fd5b506102f96040518060400160405280600581526020017f322e312e3100000000000000000000000000000000000000000000000000000081525081565b6040516101a49190611ac7565b34801561031257600080fd5b5061018f61138881565b34801561032857600080fd5b50610331610750565b60405190151581526020016101a4565b34801561034d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101f6565b34801561038057600080fd5b506101f66107e9565b34801561039557600080fd5b5061018f62030d4081565b3480156103ac57600080fd5b506101f67f000000000000000000000000000000000000000000000000000000000000000081565b3480156103e057600080fd5b506103316103ef366004611ae1565b60ce6020526000908152604090205460ff1681565b34801561041057600080fd5b5061033161041f366004611ae1565b60cb6020526000908152604090205460ff1681565b34801561044057600080fd5b5061018f61044f366004611afa565b6108d5565b34801561046057600080fd5b5061027061046f366004611b4e565b610943565b610270610482366004611b6b565b610b81565b34801561049357600080fd5b506104de60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101a4565b6106257f000000000000000000000000000000000000000000000000000000000000000061051b8585856108d5565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061058760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105a39796959493929190611c3a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611493565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856106aa60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516106bc959493929190611c99565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156107c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e49190611ce7565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016108b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6108f1604063ffffffff8816611d38565b6108fb9190611d68565b610906601088611d38565b6109139062030d40611db6565b61091d9190611db6565b6109279190611db6565b6109319190611db6565b61093b9190611db6565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff161580801561098e575060005460017401000000000000000000000000000000000000000090910460ff16105b806109c05750303b1580156109c0575060005474010000000000000000000000000000000000000000900460ff166001145b610a4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016108af565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610ad257600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055610b1a611548565b8015610b7d57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610b89610750565b15610bf0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016108af565b60f087901c60028110610cab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016108af565b8061ffff16600003610da0576000610cfc878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f9250611621915050565b600081815260cb602052604090205490915060ff1615610d9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016108af565b505b6000610de6898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164092505050565b9050610df0611663565b15610e2857853414610e0457610e04611de2565b600081815260ce602052604090205460ff1615610e2357610e23611de2565b610f7a565b3415610edc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016108af565b600081815260ce602052604090205460ff16610f7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016108af565b610f8387611787565b15611036576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016108af565b600081815260cb602052604090205460ff16156110d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016108af565b6110f6856110e7611388619c40611db6565b67ffffffffffffffff166117fe565b158061111c575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561123557600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161122e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b505061146e565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006112c688619c405a6112899190611e11565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061181c92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561135d57600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a261146a565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161146a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016108af565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e9e05c42908490611510908890839089906000908990600401611e28565b6000604051808303818588803b15801561152957600080fd5b505af115801561153d573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff166115f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016108af565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b600061162f85858585611836565b805190602001209050949350505050565b60006116508787878787876118cf565b8051906020012090509695505050505050565b60003373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156107e457507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bf62d826040518163ffffffff1660e01b8152600401602060405180830381865afa158015611747573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176b9190611e80565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff82163014806117f857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b60608484848460405160240161184f9493929190611e9d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b60608686868686866040516024016118ec96959493929190611ee7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461199057600080fd5b50565b60008083601f8401126119a557600080fd5b50813567ffffffffffffffff8111156119bd57600080fd5b6020830191508360208285010111156119d557600080fd5b9250929050565b803563ffffffff811681146119f057600080fd5b919050565b60008060008060608587031215611a0b57600080fd5b8435611a168161196e565b9350602085013567ffffffffffffffff811115611a3257600080fd5b611a3e87828801611993565b9094509250611a519050604086016119dc565b905092959194509250565b6000815180845260005b81811015611a8257602081850181015186830182015201611a66565b81811115611a94576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611ada6020830184611a5c565b9392505050565b600060208284031215611af357600080fd5b5035919050565b600080600060408486031215611b0f57600080fd5b833567ffffffffffffffff811115611b2657600080fd5b611b3286828701611993565b9094509250611b459050602085016119dc565b90509250925092565b600060208284031215611b6057600080fd5b8135611ada8161196e565b600080600080600080600060c0888a031215611b8657600080fd5b873596506020880135611b988161196e565b95506040880135611ba88161196e565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611bd257600080fd5b611bde8a828b01611993565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611c8c60c083018486611bf1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611cc9608083018688611bf1565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611cf957600080fd5b81518015158114611ada57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611d5f57611d5f611d09565b02949350505050565b600067ffffffffffffffff80841680611daa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611dd957611dd9611d09565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611e2357611e23611d09565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611e7560a0830184611a5c565b979650505050505050565b600060208284031215611e9257600080fd5b8151611ada8161196e565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611ed66080830185611a5c565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611f3260c0830184611a5c565b9897505050505050505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "baseGas(bytes,uint32)": { - "params": { - "_message": "Message to compute the amount of required gas for.", - "_minGasLimit": "Minimum desired gas limit when message goes to target." - }, - "returns": { - "_0": "Amount of gas required to guarantee message receipt." - } - }, - "constructor": { - "params": { - "_portal": "Address of the OptimismPortal contract on this network." - } - }, - "initialize(address)": { - "params": { - "_superchainConfig": "Address of the SuperchainConfig contract on this network." - } - }, - "messageNonce()": { - "returns": { - "_0": "Nonce of the next message to be sent, with added message version." - } - }, - "paused()": { - "returns": { - "_0": "Whether or not the contract is paused." - } - }, - "relayMessage(uint256,address,address,uint256,uint256,bytes)": { - "params": { - "_message": "Message to send to the target.", - "_minGasLimit": "Minimum amount of gas that the message can be executed with.", - "_nonce": "Nonce of the message being relayed.", - "_sender": "Address of the user who sent the message.", - "_target": "Address that the message is targeted at.", - "_value": "ETH value to send with the message." - } - }, - "sendMessage(address,bytes,uint32)": { - "params": { - "_message": "Message to trigger the target address with.", - "_minGasLimit": "Minimum gas limit that the message can be executed with.", - "_target": "Target contract or wallet address." - } - }, - "xDomainMessageSender()": { - "returns": { - "_0": "Address of the sender of the currently executing message on the other chain." - } - } - } - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"_portal\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"FailedRelayedMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"RelayedMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"messageNonce\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"SentMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"SentMessageExtension1\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSAGE_VERSION\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_CALLDATA_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_MESSENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"PORTAL\",\"outputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_CALL_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_CONSTANT_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_GAS_CHECK_BUFFER\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_RESERVED_GAS\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"baseGas\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"failedMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"_superchainConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messageNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"portal\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"relayMessage\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"sendMessage\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"successfulMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"superchainConfig\",\"outputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"xDomainMessageSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"baseGas(bytes,uint32)\":{\"params\":{\"_message\":\"Message to compute the amount of required gas for.\",\"_minGasLimit\":\"Minimum desired gas limit when message goes to target.\"},\"returns\":{\"_0\":\"Amount of gas required to guarantee message receipt.\"}},\"constructor\":{\"params\":{\"_portal\":\"Address of the OptimismPortal contract on this network.\"}},\"initialize(address)\":{\"params\":{\"_superchainConfig\":\"Address of the SuperchainConfig contract on this network.\"}},\"messageNonce()\":{\"returns\":{\"_0\":\"Nonce of the next message to be sent, with added message version.\"}},\"paused()\":{\"returns\":{\"_0\":\"Whether or not the contract is paused.\"}},\"relayMessage(uint256,address,address,uint256,uint256,bytes)\":{\"params\":{\"_message\":\"Message to send to the target.\",\"_minGasLimit\":\"Minimum amount of gas that the message can be executed with.\",\"_nonce\":\"Nonce of the message being relayed.\",\"_sender\":\"Address of the user who sent the message.\",\"_target\":\"Address that the message is targeted at.\",\"_value\":\"ETH value to send with the message.\"}},\"sendMessage(address,bytes,uint32)\":{\"params\":{\"_message\":\"Message to trigger the target address with.\",\"_minGasLimit\":\"Minimum gas limit that the message can be executed with.\",\"_target\":\"Target contract or wallet address.\"}},\"xDomainMessageSender()\":{\"returns\":{\"_0\":\"Address of the sender of the currently executing message on the other chain.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSAGE_VERSION()\":{\"notice\":\"Current message version identifier.\"},\"MIN_GAS_CALLDATA_OVERHEAD()\":{\"notice\":\"Extra gas added to base gas for each byte of calldata in a message.\"},\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR()\":{\"notice\":\"Denominator for dynamic overhead added to the base gas for a message.\"},\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR()\":{\"notice\":\"Numerator for dynamic overhead added to the base gas for a message.\"},\"OTHER_MESSENGER()\":{\"notice\":\"Address of the paired CrossDomainMessenger contract on the other chain.\"},\"PORTAL()\":{\"notice\":\"Address of the OptimismPortal. This will be removed in the future, use `portal` instead.\"},\"RELAY_CALL_OVERHEAD()\":{\"notice\":\"Gas reserved for performing the external call in `relayMessage`.\"},\"RELAY_CONSTANT_OVERHEAD()\":{\"notice\":\"Constant overhead added to the base gas for a message.\"},\"RELAY_GAS_CHECK_BUFFER()\":{\"notice\":\"Gas reserved for the execution between the `hasMinGas` check and the external call in `relayMessage`.\"},\"RELAY_RESERVED_GAS()\":{\"notice\":\"Gas reserved for finalizing the execution of `relayMessage` after the safe call.\"},\"baseGas(bytes,uint32)\":{\"notice\":\"Computes the amount of gas required to guarantee that a given message will be received on the other chain without running out of gas. Guaranteeing that a message will not run out of gas is important because this ensures that a message can always be replayed on the other chain if it fails to execute completely.\"},\"constructor\":{\"notice\":\"Constructs the L1CrossDomainMessenger contract.\"},\"failedMessages(bytes32)\":{\"notice\":\"Mapping of message hashes to a boolean if and only if the message has failed to be executed at least once. A message will not be present in this mapping if it successfully executed on the first attempt.\"},\"initialize(address)\":{\"notice\":\"Initializes the contract.\"},\"messageNonce()\":{\"notice\":\"Retrieves the next message nonce. Message version will be added to the upper two bytes of the message nonce. Message version allows us to treat messages as having different structures.\"},\"paused()\":{\"notice\":\"This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op.\"},\"portal()\":{\"notice\":\"Getter for the OptimismPortal address.\"},\"relayMessage(uint256,address,address,uint256,uint256,bytes)\":{\"notice\":\"Relays a message that was sent by the other CrossDomainMessenger contract. Can only be executed via cross-chain call from the other messenger OR if the message was already received once and is currently being replayed.\"},\"sendMessage(address,bytes,uint32)\":{\"notice\":\"Sends a message to some target address on the other chain. Note that if the call always reverts, then the message will be unrelayable, and any ETH sent will be permanently locked. The same will occur if the target on the other chain is considered unsafe (see the _isUnsafeTarget() function).\"},\"successfulMessages(bytes32)\":{\"notice\":\"Mapping of message hashes to boolean receipt values. Note that a message will only be present in this mapping if it has successfully been relayed on this chain, and can therefore not be relayed again.\"},\"superchainConfig()\":{\"notice\":\"Address of the SuperchainConfig contract.\"},\"version()\":{\"notice\":\"Semantic version.\"},\"xDomainMessageSender()\":{\"notice\":\"Retrieves the address of the contract or wallet that initiated the currently executing message on the other chain. Will throw an error if there is no message currently being executed. Allows the recipient of a call to see who triggered it.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1CrossDomainMessenger.sol\":\"L1CrossDomainMessenger\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1CrossDomainMessenger.sol\":{\"keccak256\":\"0x9df7a928c47b13e5762d37319b4b3632e2e19b4c8dba10209f7db53e6d9a05a2\",\"urls\":[\"bzz-raw://fd3d7c6503dc4572750dde44decce8e3b772e156456e33da6c8d560ddbc8b37d\",\"dweb:/ipfs/Qmes7MhyEdRweVzdEPWSYcScDbyKHpg2qxYK6dvsy4R2uU\"],\"license\":\"MIT\"},\"src/L1/L2OutputOracle.sol\":{\"keccak256\":\"0xecd3b0cd61ec0d1246ea19cc5095508b84ad0d586988f781b4de9233b3c2821d\",\"urls\":[\"bzz-raw://b4d5e6a842dd999ff09c6db97c8a5e44aaa5f84652a6eb1aa3c170094e9c9591\",\"dweb:/ipfs/QmfUaT1pX9rQBZm48zdwzaSQ7miW8Ek7kBwys1UhMFSYJR\"],\"license\":\"MIT\"},\"src/L1/OptimismPortal.sol\":{\"keccak256\":\"0x62c4745158651d87705e20b3bbe5aecc09790a2a08a84b65cf5961a746716363\",\"urls\":[\"bzz-raw://47ec233411fcad292daaa5463c2c86352718c0e0ff8d1f27a87d4781382f91f5\",\"dweb:/ipfs/QmfKW1SDvoBcFeYRXYwnBsXKP5npC4PXNXpQz2wVn1Xx7S\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x9d6e33ea5d12b78fd3cb024ed5863c8c14cb55977cbab56fd9ce5c309918afc6\",\"urls\":[\"bzz-raw://d8545d6255ed4428b168a3547d6935043e5b680344d650fd090293ba36b59897\",\"dweb:/ipfs/QmPLVma7kqTTgbAHtxog2MGD7S2Wr8nd42MhBcfJ5yyF4W\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x5c6346060b3e8d3bf4289b20fd869a66fbad8f69dc0b095845f990066b6c4d2b\",\"urls\":[\"bzz-raw://161277a9935cc567d76096a9a3ffc54632fda2020e02b4c5dc5541bfad3d166f\",\"dweb:/ipfs/QmXiDP2A4MPsN9VDNf9YbqbQQTU2J5tffWbJHg45f9LJyN\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Bytes.sol\":{\"keccak256\":\"0x827f47d123b0fdf3b08816d5b33831811704dbf4e554e53f2269354f6bba8859\",\"urls\":[\"bzz-raw://3137ac7204d30a245a8b0d67aa6da5286f1bd8c90379daab561f84963b6db782\",\"dweb:/ipfs/QmWRhisw3axJK833gUScs23ETh2MLFbVzzqzYVMKSDN3S9\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x75408c79fd51bd6f53ab1ad1719ec09264d1e6965cd5604c8346fbee76039fc3\",\"urls\":[\"bzz-raw://100be0dc2c772b569820b3c0828fac21fb241773c586eb8e789b4ddbca89f4f8\",\"dweb:/ipfs/QmW8NrsSeu1kYkga5cdjuzQ853dZZKFY22ZaycoHwiStbw\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPReader.sol\":{\"keccak256\":\"0x9ba74a3b0a11693e622380807d213d5d1250d974e18b2cd768da9cbe719a6778\",\"urls\":[\"bzz-raw://0808d721ed9e05707526ee134faa051d707a95ee6b8bd6e0b1972275da8e5723\",\"dweb:/ipfs/QmcTTPu9xgckfWdbFUAcr2RAgk3J6vzyR4FpV798TjFMeN\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/libraries/trie/MerkleTrie.sol\":{\"keccak256\":\"0xf8ba770ee6666e73ae43184c700e9c704b2c4ace71f9e3c2227ddc11a8148b4c\",\"urls\":[\"bzz-raw://4702ccee1fe44aea3ee01d59e6152eb755da083f786f00947fec4437c064fe74\",\"dweb:/ipfs/QmQjFj5J7hrEM1dxJjFszzW2Cs7g7eMhYNBXonF2DXBstE\"],\"license\":\"MIT\"},\"src/libraries/trie/SecureMerkleTrie.sol\":{\"keccak256\":\"0xeaff8315cfd21197bc6bc859c2decf5d4f4838c9c357c502cdf2b1eac863d288\",\"urls\":[\"bzz-raw://79dcdcaa560aea51d138da4f5dc553a1808b6de090b2dc1629f18375edbff681\",\"dweb:/ipfs/QmbE4pUPhf5fLKW4W6cEjhQs55gEDvHmbmoBqkW1yz3bnw\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x62e11a169b3fa987af2427bf5117612e2770d4cca51565e6bbfe255ff7ffc4bb\",\"urls\":[\"bzz-raw://c852c8c0571bb22d9f28d577620a71de5ee60eb0c7ab8c68645da9a7295d24a0\",\"dweb:/ipfs/QmdixJ2dpsz8N8CgZz8z1MkZNVjw6ZkRM6bS7mchPYX6Yi\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"],\"license\":\"Apache-2.0\"}},\"version\":1}", - "numDeployments": 5, - "receipt": { - "transactionHash": "0x27e29dc98caa5a420af1246250219417b15d1df5424611fe11342f04ecc5cded", - "transactionIndex": "0xd", - "blockHash": "0x1a26f29e4504908bfc1e3395090b918855c1726180f36c7a5cc7d2ef76532b9d", - "blockNumber": "0x9ace50", - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "cumulativeGasUsed": "0xa1ac7e", - "gasUsed": "0x1bf2c9", - "contractAddress": "0x7C195AFFC48399546A0979aD2C740a022d524BA6", - "logs": [ - { - "address": "0x7C195AFFC48399546A0979aD2C740a022d524BA6", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "blockHash": "0x1a26f29e4504908bfc1e3395090b918855c1726180f36c7a5cc7d2ef76532b9d", - "blockNumber": "0x9ace50", - "transactionHash": "0x27e29dc98caa5a420af1246250219417b15d1df5424611fe11342f04ecc5cded", - "transactionIndex": "0xd", - "logIndex": "0x2f", - "removed": false - } - ], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "type": "0x2", - "effectiveGasPrice": "0xb2d05e0b" - }, - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 94245, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_0_0_20", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 44768, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "_initialized", - "offset": 20, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 44771, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "_initializing", - "offset": 21, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 94252, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_1_0_1600", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 94255, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_51_0_20", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 94260, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_52_0_1568", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 94263, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_101_0_1", - "offset": 0, - "slot": "101", - "type": "t_bool" - }, - { - "astId": 94268, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_102_0_1568", - "offset": 0, - "slot": "102", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 94271, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_151_0_32", - "offset": 0, - "slot": "151", - "type": "t_uint256" - }, - { - "astId": 94276, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_152_0_1568", - "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 94281, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_201_0_32", - "offset": 0, - "slot": "201", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 94286, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_202_0_32", - "offset": 0, - "slot": "202", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 94334, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "successfulMessages", - "offset": 0, - "slot": "203", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 94337, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "xDomainMsgSender", - "offset": 0, - "slot": "204", - "type": "t_address" - }, - { - "astId": 94340, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "msgNonce", - "offset": 0, - "slot": "205", - "type": "t_uint240" - }, - { - "astId": 94345, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "failedMessages", - "offset": 0, - "slot": "206", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 94350, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "__gap", - "offset": 0, - "slot": "207", - "type": "t_array(t_uint256)44_storage" - }, - { - "astId": 75321, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "superchainConfig", - "offset": 0, - "slot": "251", - "type": "t_contract(SuperchainConfig)78153" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)44_storage": { - "encoding": "inplace", - "label": "uint256[44]", - "numberOfBytes": "1408", - "base": "t_uint256" - }, - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_array(t_uint256)50_storage": { - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(SuperchainConfig)78153": { - "encoding": "inplace", - "label": "contract SuperchainConfig", - "numberOfBytes": "20" - }, - "t_mapping(t_bytes32,t_bool)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_uint240": { - "encoding": "inplace", - "label": "uint240", - "numberOfBytes": "30" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x27e29dc98caa5a420af1246250219417b15d1df5424611fe11342f04ecc5cded", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MESSAGE_VERSION()": { - "notice": "Current message version identifier." - }, - "MIN_GAS_CALLDATA_OVERHEAD()": { - "notice": "Extra gas added to base gas for each byte of calldata in a message." - }, - "MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR()": { - "notice": "Denominator for dynamic overhead added to the base gas for a message." - }, - "MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR()": { - "notice": "Numerator for dynamic overhead added to the base gas for a message." - }, - "OTHER_MESSENGER()": { - "notice": "Address of the paired CrossDomainMessenger contract on the other chain." - }, - "PORTAL()": { - "notice": "Address of the OptimismPortal. This will be removed in the future, use `portal` instead." - }, - "RELAY_CALL_OVERHEAD()": { - "notice": "Gas reserved for performing the external call in `relayMessage`." - }, - "RELAY_CONSTANT_OVERHEAD()": { - "notice": "Constant overhead added to the base gas for a message." - }, - "RELAY_GAS_CHECK_BUFFER()": { - "notice": "Gas reserved for the execution between the `hasMinGas` check and the external call in `relayMessage`." - }, - "RELAY_RESERVED_GAS()": { - "notice": "Gas reserved for finalizing the execution of `relayMessage` after the safe call." - }, - "baseGas(bytes,uint32)": { - "notice": "Computes the amount of gas required to guarantee that a given message will be received on the other chain without running out of gas. Guaranteeing that a message will not run out of gas is important because this ensures that a message can always be replayed on the other chain if it fails to execute completely." - }, - "constructor": { - "notice": "Constructs the L1CrossDomainMessenger contract." - }, - "failedMessages(bytes32)": { - "notice": "Mapping of message hashes to a boolean if and only if the message has failed to be executed at least once. A message will not be present in this mapping if it successfully executed on the first attempt." - }, - "initialize(address)": { - "notice": "Initializes the contract." - }, - "messageNonce()": { - "notice": "Retrieves the next message nonce. Message version will be added to the upper two bytes of the message nonce. Message version allows us to treat messages as having different structures." - }, - "paused()": { - "notice": "This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op." - }, - "portal()": { - "notice": "Getter for the OptimismPortal address." - }, - "relayMessage(uint256,address,address,uint256,uint256,bytes)": { - "notice": "Relays a message that was sent by the other CrossDomainMessenger contract. Can only be executed via cross-chain call from the other messenger OR if the message was already received once and is currently being replayed." - }, - "sendMessage(address,bytes,uint32)": { - "notice": "Sends a message to some target address on the other chain. Note that if the call always reverts, then the message will be unrelayable, and any ETH sent will be permanently locked. The same will occur if the target on the other chain is considered unsafe (see the _isUnsafeTarget() function)." - }, - "successfulMessages(bytes32)": { - "notice": "Mapping of message hashes to boolean receipt values. Note that a message will only be present in this mapping if it has successfully been relayed on this chain, and can therefore not be relayed again." - }, - "superchainConfig()": { - "notice": "Address of the SuperchainConfig contract." - }, - "version()": { - "notice": "Semantic version." - }, - "xDomainMessageSender()": { - "notice": "Retrieves the address of the contract or wallet that initiated the currently executing message on the other chain. Will throw an error if there is no message currently being executed. Allows the recipient of a call to see who triggered it." - } - }, - "events": { - "FailedRelayedMessage(bytes32)": { - "notice": "Emitted whenever a message fails to be relayed on this chain." - }, - "RelayedMessage(bytes32)": { - "notice": "Emitted whenever a message is successfully relayed on this chain." - }, - "SentMessage(address,address,bytes,uint256,uint256)": { - "notice": "Emitted whenever a message is sent to the other chain." - }, - "SentMessageExtension1(address,uint256)": { - "notice": "Additional event data to emit, required as of Bedrock. Cannot be merged with the SentMessage event without breaking the ABI of this contract, this is good enough." - } - }, - "notice": "The L1CrossDomainMessenger is a message passing interface between L1 and L2 responsible for sending and receiving data on the L1 side. Users are encouraged to use this interface instead of interacting with lower-level contracts directly." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/L1CrossDomainMessengerProxy.json b/packages/contracts-bedrock/deployments/goerli/L1CrossDomainMessengerProxy.json deleted file mode 100644 index 1ea3f212cbde..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/L1CrossDomainMessengerProxy.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "address": "0x5086d1eEF304eb5284A0f6720f79403b4e9bE294", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_libAddressManager", - "type": "address" - }, - { - "internalType": "string", - "name": "_implementationName", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "stateMutability": "payable", - "type": "fallback" - } - ], - "transactionHash": "0xc547cd677c4bcb87deead498c827b1dfcfd5d14826f58a0f7416a46024a03e85", - "receipt": { - "to": null, - "from": "0x3a605B442055DF2898E18cF518feb2e2A6BD0D31", - "contractAddress": "0x5086d1eEF304eb5284A0f6720f79403b4e9bE294", - "transactionIndex": 13, - "gasUsed": "291461", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x3e18927a7be75d3ac2b6f54f8c40d781756e78327f9cedd8dff5e79dd49403ff", - "transactionHash": "0xc547cd677c4bcb87deead498c827b1dfcfd5d14826f58a0f7416a46024a03e85", - "logs": [], - "blockNumber": 7017129, - "cumulativeGasUsed": "1033610", - "status": 1, - "byzantium": true - }, - "args": [ - "0xa6f73589243a6A7a9023b1Fa0651b1d89c177111", - "OVM_L1CrossDomainMessenger" - ], - "numDeployments": 1, - "solcInputHash": "76c096070f4b72a86045eb6ab63709ed", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_libAddressManager\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_implementationName\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_implementationName\":\"implementationName of the contract to proxy to.\",\"_libAddressManager\":\"Address of the Lib_AddressManager.\"}}},\"title\":\"Lib_ResolvedDelegateProxy\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/resolver/Lib_ResolvedDelegateProxy.sol\":\"Lib_ResolvedDelegateProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\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 _setOwner(_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 _setOwner(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 _setOwner(newOwner);\\n }\\n\\n function _setOwner(address newOwner) private {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x6bb804a310218875e89d12c053e94a13a4607cdf7cc2052f3e52bd32a0dc50a1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\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\":\"0x90565a39ae45c80f0468dc96c7b20d0afc3055f344c8203a0c9258239f350b9f\",\"license\":\"MIT\"},\"contracts/libraries/resolver/Lib_AddressManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/* External Imports */\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n/**\\n * @title Lib_AddressManager\\n */\\ncontract Lib_AddressManager is Ownable {\\n /**********\\n * Events *\\n **********/\\n\\n event AddressSet(string indexed _name, address _newAddress, address _oldAddress);\\n\\n /*************\\n * Variables *\\n *************/\\n\\n mapping(bytes32 => address) private addresses;\\n\\n /********************\\n * Public Functions *\\n ********************/\\n\\n /**\\n * Changes the address associated with a particular name.\\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 * Retrieves the address associated with a given name.\\n * @param _name Name to retrieve an address for.\\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 * Internal Functions *\\n **********************/\\n\\n /**\\n * Computes the hash of a name.\\n * @param _name Name to compute a hash for.\\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\",\"keccak256\":\"0xcde9b29429d512c549f7c1b8a033f161fa71c18cda08b241748663854196ae14\",\"license\":\"MIT\"},\"contracts/libraries/resolver/Lib_ResolvedDelegateProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/* Library Imports */\\nimport { Lib_AddressManager } from \\\"./Lib_AddressManager.sol\\\";\\n\\n/**\\n * @title Lib_ResolvedDelegateProxy\\n */\\ncontract Lib_ResolvedDelegateProxy {\\n /*************\\n * Variables *\\n *************/\\n\\n // Using mappings to store fields to avoid overwriting storage slots in the\\n // implementation contract. For example, instead of storing these fields at\\n // storage slot `0` & `1`, they are stored at `keccak256(key + slot)`.\\n // See: https://solidity.readthedocs.io/en/v0.7.0/internals/layout_in_storage.html\\n // NOTE: Do not use this code in your own contract system.\\n // There is a known flaw in this contract, and we will remove it from the repository\\n // in the near future. Due to the very limited way that we are using it, this flaw is\\n // not an issue in our system.\\n mapping(address => string) private implementationName;\\n mapping(address => Lib_AddressManager) private addressManager;\\n\\n /***************\\n * Constructor *\\n ***************/\\n\\n /**\\n * @param _libAddressManager Address of the Lib_AddressManager.\\n * @param _implementationName implementationName of the contract to proxy to.\\n */\\n constructor(address _libAddressManager, string memory _implementationName) {\\n addressManager[address(this)] = Lib_AddressManager(_libAddressManager);\\n implementationName[address(this)] = _implementationName;\\n }\\n\\n /*********************\\n * Fallback Function *\\n *********************/\\n\\n fallback() external payable {\\n address target = addressManager[address(this)].getAddress(\\n (implementationName[address(this)])\\n );\\n\\n require(target != address(0), \\\"Target address must be initialized.\\\");\\n\\n // slither-disable-next-line controlled-delegatecall\\n (bool success, bytes memory returndata) = target.delegatecall(msg.data);\\n\\n if (success == true) {\\n assembly {\\n return(add(returndata, 0x20), mload(returndata))\\n }\\n } else {\\n assembly {\\n revert(add(returndata, 0x20), mload(returndata))\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x987774d18365ed25f5be61198e8b241728db6f97c6f2496f4a35bf9dbe0bda2b\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506040516105b53803806105b583398101604081905261002f91610125565b30600090815260016020908152604080832080546001600160a01b0319166001600160a01b038716179055828252909120825161006e92840190610076565b505050610252565b82805461008290610217565b90600052602060002090601f0160209004810192826100a457600085556100ea565b82601f106100bd57805160ff19168380011785556100ea565b828001600101855582156100ea579182015b828111156100ea5782518255916020019190600101906100cf565b506100f69291506100fa565b5090565b5b808211156100f657600081556001016100fb565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561013857600080fd5b82516001600160a01b038116811461014f57600080fd5b602084810151919350906001600160401b038082111561016e57600080fd5b818601915086601f83011261018257600080fd5b8151818111156101945761019461010f565b604051601f8201601f19908116603f011681019083821181831017156101bc576101bc61010f565b8160405282815289868487010111156101d457600080fd5b600093505b828410156101f657848401860151818501870152928501926101d9565b828411156102075760008684830101525b8096505050505050509250929050565b600181811c9082168061022b57607f821691505b6020821081141561024c57634e487b7160e01b600052602260045260246000fd5b50919050565b610354806102616000396000f3fe608060408181523060009081526001602090815282822054908290529181207fbf40fac1000000000000000000000000000000000000000000000000000000009093529173ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac19061006d9060846101f2565b60206040518083038186803b15801561008557600080fd5b505afa158015610099573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100bd91906102d1565b905073ffffffffffffffffffffffffffffffffffffffff8116610166576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5461726765742061646472657373206d75737420626520696e697469616c697a60448201527f65642e0000000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1660003660405161019192919061030e565b600060405180830381855af49150503d80600081146101cc576040519150601f19603f3d011682016040523d82523d6000602084013e6101d1565b606091505b509092509050600182151514156101ea57805160208201f35b805160208201fd5b600060208083526000845481600182811c91508083168061021457607f831692505b85831081141561024b577f4e487b710000000000000000000000000000000000000000000000000000000085526022600452602485fd5b8786018381526020018180156102685760018114610297576102c2565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616825287820196506102c2565b60008b81526020902060005b868110156102bc578154848201529085019089016102a3565b83019750505b50949998505050505050505050565b6000602082840312156102e357600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461030757600080fd5b9392505050565b818382376000910190815291905056fea2646970667358221220d66a7dad92a7f7528f41181719174e1d244423b8bb730d2884645c76cfa0944064736f6c63430008090033", - "deployedBytecode": "0x608060408181523060009081526001602090815282822054908290529181207fbf40fac1000000000000000000000000000000000000000000000000000000009093529173ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac19061006d9060846101f2565b60206040518083038186803b15801561008557600080fd5b505afa158015610099573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100bd91906102d1565b905073ffffffffffffffffffffffffffffffffffffffff8116610166576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5461726765742061646472657373206d75737420626520696e697469616c697a60448201527f65642e0000000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff1660003660405161019192919061030e565b600060405180830381855af49150503d80600081146101cc576040519150601f19603f3d011682016040523d82523d6000602084013e6101d1565b606091505b509092509050600182151514156101ea57805160208201f35b805160208201fd5b600060208083526000845481600182811c91508083168061021457607f831692505b85831081141561024b577f4e487b710000000000000000000000000000000000000000000000000000000085526022600452602485fd5b8786018381526020018180156102685760018114610297576102c2565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616825287820196506102c2565b60008b81526020902060005b868110156102bc578154848201529085019089016102a3565b83019750505b50949998505050505050505050565b6000602082840312156102e357600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461030757600080fd5b9392505050565b818382376000910190815291905056fea2646970667358221220d66a7dad92a7f7528f41181719174e1d244423b8bb730d2884645c76cfa0944064736f6c63430008090033", - "devdoc": { - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_implementationName": "implementationName of the contract to proxy to.", - "_libAddressManager": "Address of the Lib_AddressManager." - } - } - }, - "title": "Lib_ResolvedDelegateProxy", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 7129, - "contract": "contracts/libraries/resolver/Lib_ResolvedDelegateProxy.sol:Lib_ResolvedDelegateProxy", - "label": "implementationName", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_address,t_string_storage)" - }, - { - "astId": 7134, - "contract": "contracts/libraries/resolver/Lib_ResolvedDelegateProxy.sol:Lib_ResolvedDelegateProxy", - "label": "addressManager", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_address,t_contract(Lib_AddressManager)7084)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_contract(Lib_AddressManager)7084": { - "encoding": "inplace", - "label": "contract Lib_AddressManager", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_contract(Lib_AddressManager)7084)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => contract Lib_AddressManager)", - "numberOfBytes": "32", - "value": "t_contract(Lib_AddressManager)7084" - }, - "t_mapping(t_address,t_string_storage)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => string)", - "numberOfBytes": "32", - "value": "t_string_storage" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/L1ERC721Bridge.json b/packages/contracts-bedrock/deployments/goerli/L1ERC721Bridge.json deleted file mode 100644 index de86c406ab20..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/L1ERC721Bridge.json +++ /dev/null @@ -1,525 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "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" - }, - { - "inputs": [], - "name": "MESSENGER", - "outputs": [ - { - "internalType": "contract CrossDomainMessenger", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OTHER_BRIDGE", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "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": "contract CrossDomainMessenger", - "name": "_messenger", - "type": "address" - } - ], - "name": "initialize", - "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" - } - ], - "address": "0x806C2d0d2BDDFf9279CB2A8722F9117f0b0aDE73", - "args": [], - "bytecode": "0x60a060405234801561001057600080fd5b50734200000000000000000000000000000000000014610034565b60405180910390fd5b6001600160a01b031660805261004a600061004f565b6101cb565b600054600390610100900460ff16158015610071575060005460ff8083169116105b6100d45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161002b565b6000805461ffff191660ff8316176101001790556100f182610136565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b600054610100900460ff166101a15760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161002b565b600080546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b6080516112116101fb600039600081816101cd0152818161023b015281816103350152610bf101526112116000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637f46ddb211610076578063aa5574521161005b578063aa55745214610213578063c4d66de814610226578063c89701a21461023957600080fd5b80637f46ddb2146101c8578063927ede2d146101ef57600080fd5b806354fd4d50116100a757806354fd4d50146101285780635d93a3fc14610171578063761f4493146101b557600080fd5b80633687011a146100c35780633cb747bf146100d8575b600080fd5b6100d66100d1366004610e47565b61025f565b005b6000546100fe9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101646040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b60405161011f9190610f35565b6101a561017f366004610f4f565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b604051901515815260200161011f565b6100d66101c3366004610f90565b61030b565b6100fe7f000000000000000000000000000000000000000000000000000000000000000081565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff166100fe565b6100d6610221366004611028565b610776565b6100d661023436600461109f565b610832565b7f00000000000000000000000000000000000000000000000000000000000000006100fe565b333b156102f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b610303868633338888888861097c565b505050505050565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff163314801561041357507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103fb91906110bc565b73ffffffffffffffffffffffffffffffffffffffff16145b61049f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f74686572206272696467650060648201526084016102ea565b3073ffffffffffffffffffffffffffffffffffffffff881603610544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c660000000000000000000000000000000000000000000060648201526084016102ea565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff161515600114610613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c31204272696467650000000000000060648201526084016102ea565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156106d357600080fd5b505af11580156106e7573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516107659493929190611122565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610819576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f7420626520616464726573732830290000000000000000000000000000000060648201526084016102ea565b610829878733888888888861097c565b50505050505050565b600054600390610100900460ff16158015610854575060005460ff8083169116105b6108e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016102ea565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905561091a82610cdc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b73ffffffffffffffffffffffffffffffffffffffff8716610a1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f74206265206164647265737328302900000000000000000000000000000060648201526084016102ea565b600063761f449360e01b888a8989898888604051602401610a469796959493929190611162565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610b8657600080fd5b505af1158015610b9a573d6000803e3d6000fd5b50506000546040517f3dbb202b0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169250633dbb202b9150610c1d907f000000000000000000000000000000000000000000000000000000000000000090859089906004016111bf565b600060405180830381600087803b158015610c3757600080fd5b505af1158015610c4b573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610cc99493929190611122565b60405180910390a4505050505050505050565b600054610100900460ff16610d73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ea565b6000805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610de257600080fd5b50565b803563ffffffff81168114610df957600080fd5b919050565b60008083601f840112610e1057600080fd5b50813567ffffffffffffffff811115610e2857600080fd5b602083019150836020828501011115610e4057600080fd5b9250929050565b60008060008060008060a08789031215610e6057600080fd5b8635610e6b81610dc0565b95506020870135610e7b81610dc0565b945060408701359350610e9060608801610de5565b9250608087013567ffffffffffffffff811115610eac57600080fd5b610eb889828a01610dfe565b979a9699509497509295939492505050565b6000815180845260005b81811015610ef057602081850181015186830182015201610ed4565b81811115610f02576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610f486020830184610eca565b9392505050565b600080600060608486031215610f6457600080fd5b8335610f6f81610dc0565b92506020840135610f7f81610dc0565b929592945050506040919091013590565b600080600080600080600060c0888a031215610fab57600080fd5b8735610fb681610dc0565b96506020880135610fc681610dc0565b95506040880135610fd681610dc0565b94506060880135610fe681610dc0565b93506080880135925060a088013567ffffffffffffffff81111561100957600080fd5b6110158a828b01610dfe565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561104357600080fd5b873561104e81610dc0565b9650602088013561105e81610dc0565b9550604088013561106e81610dc0565b94506060880135935061108360808901610de5565b925060a088013567ffffffffffffffff81111561100957600080fd5b6000602082840312156110b157600080fd5b8135610f4881610dc0565b6000602082840312156110ce57600080fd5b8151610f4881610dc0565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006111586060830184866110d9565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a08301526111b260c0830184866110d9565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006111ee6060830185610eca565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100be5760003560e01c80637f46ddb211610076578063aa5574521161005b578063aa55745214610213578063c4d66de814610226578063c89701a21461023957600080fd5b80637f46ddb2146101c8578063927ede2d146101ef57600080fd5b806354fd4d50116100a757806354fd4d50146101285780635d93a3fc14610171578063761f4493146101b557600080fd5b80633687011a146100c35780633cb747bf146100d8575b600080fd5b6100d66100d1366004610e47565b61025f565b005b6000546100fe9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101646040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b60405161011f9190610f35565b6101a561017f366004610f4f565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b604051901515815260200161011f565b6100d66101c3366004610f90565b61030b565b6100fe7f000000000000000000000000000000000000000000000000000000000000000081565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff166100fe565b6100d6610221366004611028565b610776565b6100d661023436600461109f565b610832565b7f00000000000000000000000000000000000000000000000000000000000000006100fe565b333b156102f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b610303868633338888888861097c565b505050505050565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff163314801561041357507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103fb91906110bc565b73ffffffffffffffffffffffffffffffffffffffff16145b61049f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f74686572206272696467650060648201526084016102ea565b3073ffffffffffffffffffffffffffffffffffffffff881603610544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c660000000000000000000000000000000000000000000060648201526084016102ea565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff161515600114610613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c31204272696467650000000000000060648201526084016102ea565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156106d357600080fd5b505af11580156106e7573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516107659493929190611122565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610819576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f7420626520616464726573732830290000000000000000000000000000000060648201526084016102ea565b610829878733888888888861097c565b50505050505050565b600054600390610100900460ff16158015610854575060005460ff8083169116105b6108e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016102ea565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905561091a82610cdc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b73ffffffffffffffffffffffffffffffffffffffff8716610a1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f74206265206164647265737328302900000000000000000000000000000060648201526084016102ea565b600063761f449360e01b888a8989898888604051602401610a469796959493929190611162565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610b8657600080fd5b505af1158015610b9a573d6000803e3d6000fd5b50506000546040517f3dbb202b0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169250633dbb202b9150610c1d907f000000000000000000000000000000000000000000000000000000000000000090859089906004016111bf565b600060405180830381600087803b158015610c3757600080fd5b505af1158015610c4b573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610cc99493929190611122565b60405180910390a4505050505050505050565b600054610100900460ff16610d73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ea565b6000805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610de257600080fd5b50565b803563ffffffff81168114610df957600080fd5b919050565b60008083601f840112610e1057600080fd5b50813567ffffffffffffffff811115610e2857600080fd5b602083019150836020828501011115610e4057600080fd5b9250929050565b60008060008060008060a08789031215610e6057600080fd5b8635610e6b81610dc0565b95506020870135610e7b81610dc0565b945060408701359350610e9060608801610de5565b9250608087013567ffffffffffffffff811115610eac57600080fd5b610eb889828a01610dfe565b979a9699509497509295939492505050565b6000815180845260005b81811015610ef057602081850181015186830182015201610ed4565b81811115610f02576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610f486020830184610eca565b9392505050565b600080600060608486031215610f6457600080fd5b8335610f6f81610dc0565b92506020840135610f7f81610dc0565b929592945050506040919091013590565b600080600080600080600060c0888a031215610fab57600080fd5b8735610fb681610dc0565b96506020880135610fc681610dc0565b95506040880135610fd681610dc0565b94506060880135610fe681610dc0565b93506080880135925060a088013567ffffffffffffffff81111561100957600080fd5b6110158a828b01610dfe565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561104357600080fd5b873561104e81610dc0565b9650602088013561105e81610dc0565b9550604088013561106e81610dc0565b94506060880135935061108360808901610de5565b925060a088013567ffffffffffffffff81111561100957600080fd5b6000602082840312156110b157600080fd5b8135610f4881610dc0565b6000602082840312156110ce57600080fd5b8151610f4881610dc0565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006111586060830184866110d9565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a08301526111b260c0830184866110d9565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006111ee6060830185610eca565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "bridgeERC721(address,address,uint256,uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.", - "_localToken": "Address of the ERC721 on this domain.", - "_minGasLimit": "Minimum gas limit for the bridge message on the other domain.", - "_remoteToken": "Address of the ERC721 on the remote domain.", - "_tokenId": "Token ID to bridge." - } - }, - "bridgeERC721To(address,address,address,uint256,uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.", - "_localToken": "Address of the ERC721 on this domain.", - "_minGasLimit": "Minimum gas limit for the bridge message on the other domain.", - "_remoteToken": "Address of the ERC721 on the remote domain.", - "_to": "Address to receive the token on the other domain.", - "_tokenId": "Token ID to bridge." - } - }, - "finalizeBridgeERC721(address,address,address,address,uint256,bytes)": { - "params": { - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_from": "Address that triggered the bridge on the other domain.", - "_localToken": "Address of the ERC721 token on this domain.", - "_remoteToken": "Address of the ERC721 token on the other domain.", - "_to": "Address to receive the token on this domain.", - "_tokenId": "ID of the token being deposited." - } - }, - "initialize(address)": { - "params": { - "_messenger": "Address of the CrossDomainMessenger on this network." - } - }, - "otherBridge()": { - "returns": { - "_0": "Address of the bridge on the other network." - } - } - }, - "title": "L1ERC721Bridge" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC721BridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC721BridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC721\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC721To\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeBridgeERC721\"},{\"inputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"_messenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bridgeERC721(address,address,uint256,uint32,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.\",\"_localToken\":\"Address of the ERC721 on this domain.\",\"_minGasLimit\":\"Minimum gas limit for the bridge message on the other domain.\",\"_remoteToken\":\"Address of the ERC721 on the remote domain.\",\"_tokenId\":\"Token ID to bridge.\"}},\"bridgeERC721To(address,address,address,uint256,uint32,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.\",\"_localToken\":\"Address of the ERC721 on this domain.\",\"_minGasLimit\":\"Minimum gas limit for the bridge message on the other domain.\",\"_remoteToken\":\"Address of the ERC721 on the remote domain.\",\"_to\":\"Address to receive the token on the other domain.\",\"_tokenId\":\"Token ID to bridge.\"}},\"finalizeBridgeERC721(address,address,address,address,uint256,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_from\":\"Address that triggered the bridge on the other domain.\",\"_localToken\":\"Address of the ERC721 token on this domain.\",\"_remoteToken\":\"Address of the ERC721 token on the other domain.\",\"_to\":\"Address to receive the token on this domain.\",\"_tokenId\":\"ID of the token being deposited.\"}},\"initialize(address)\":{\"params\":{\"_messenger\":\"Address of the CrossDomainMessenger on this network.\"}},\"otherBridge()\":{\"returns\":{\"_0\":\"Address of the bridge on the other network.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSENGER()\":{\"notice\":\"Getter for messenger contract.\"},\"OTHER_BRIDGE()\":{\"notice\":\"Address of the bridge on the other network.\"},\"bridgeERC721(address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to the caller's account on the other chain. Note that this function can only be called by EOAs. Smart contract wallets should use the `bridgeERC721To` function after ensuring that the recipient address on the remote chain exists. Also note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2.\"},\"bridgeERC721To(address,address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to some recipient's account on the other chain. Note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2.\"},\"constructor\":{\"notice\":\"Constructs the contract.\"},\"deposits(address,address,uint256)\":{\"notice\":\"Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token by ID was deposited for a given L2 token.\"},\"finalizeBridgeERC721(address,address,address,address,uint256,bytes)\":{\"notice\":\"Completes an ERC721 bridge from the other domain and sends the ERC721 token to the recipient on this domain.\"},\"initialize(address)\":{\"notice\":\"Initializes the contract.\"},\"messenger()\":{\"notice\":\"Messenger contract on this domain.\"},\"otherBridge()\":{\"notice\":\"Getter for other bridge address.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1ERC721Bridge.sol\":\"L1ERC721Bridge\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"keccak256\":\"0xed6a749c5373af398105ce6ee3ac4763aa450ea7285d268c85d9eeca809cdb1f\",\"urls\":[\"bzz-raw://20a97f891d06f0fe91560ea1a142aaa26fdd22bed1b51606b7d48f670deeb50f\",\"dweb:/ipfs/QmTbCtZKChpaX5H2iRiTDMcSz29GSLCpTCDgJpcMR4wg8x\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"urls\":[\"bzz-raw://26fef835622b46a5ba08b3ef6b46a22e94b5f285d0f0fb66b703bd30217d2c34\",\"dweb:/ipfs/QmZ548qdwfL1qF7aXz3xh1GCdTiST81kGGuKRqVUfYmPZR\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1ERC721Bridge.sol\":{\"keccak256\":\"0xfcbde0f08cd5601aac88a40ee9224f59af9c7f5c404d67f37cbb0abd5f298b1f\",\"urls\":[\"bzz-raw://f1d26441cb269c4e1d45b2739342c016d8ec461dcb99c30da6e649e58d3b376d\",\"dweb:/ipfs/QmU4sYC5ZBGWtgwV2isLp8pXhvNum34d6Fsdsj7UNLEcUw\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L2/L2ERC721Bridge.sol\":{\"keccak256\":\"0xcc0de3ee4e726fe4a0a52a0684fc30454a49190d600c7cbeade798ae020d70f6\",\"urls\":[\"bzz-raw://bfa81e6c23f59237794bce97ad55cca091980c3db50bb295f836ab20cb58e4c8\",\"dweb:/ipfs/QmSpfckbZeoCEAASqxWdFm7t8q6Rqkqwk2jQFSCKEBXEVs\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x5af3a849f68f7c9108858ebac5c769da8f1c0309b5c0cb42eb5cbb15e3fe6058\",\"urls\":[\"bzz-raw://6ffe76429a96d274577be66627eddad5cd05ad36d0cb6b9b3c3f9fa8a609dd7e\",\"dweb:/ipfs/QmVhWnB7Avg684TEQ9BExWqSN1YfLehUTWoqpjymeQEQHm\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x4302ae78bcafde2737d4048bbf8fdb3dd4cd7254c015b91dfa14fdaafd412f4a\",\"urls\":[\"bzz-raw://78d3d1823ad4e1fba15921a0a361b452c85d111e2d53cbbed11a8632782ea8f3\",\"dweb:/ipfs/QmVc2rTRpn7g7WAUxDShSuy6dY5zmtbJ7hHC6sT9PcD3Gj\"],\"license\":\"MIT\"},\"src/universal/ERC721Bridge.sol\":{\"keccak256\":\"0x1aba1c039fa759d7d081e0d60c5d742e8d3147f0eda19af5c17cf291b4f53213\",\"urls\":[\"bzz-raw://a3581c48036bf901da4dd823f4b2fc65870414a116b32ed042d89778a2027e3f\",\"dweb:/ipfs/QmVqTCMR6NroWCQzjc1vkznHp1XbNFSYXNDgrvXUDEuZoA\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC721.sol\":{\"keccak256\":\"0xb3a65b067e67a9e1fa0493401c8d247970377c6725eba4e7b02ce8099c4f4f52\",\"urls\":[\"bzz-raw://86bb6864027560ade2f4ced6a6e34213cbff8002977dc365377e5a0b473cf17b\",\"dweb:/ipfs/QmQvjtodTK27as1g1PzsYk9NyJJ3X6a6251o1vrBwx7DPT\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 4, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 32100, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 32103, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 76028, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "messenger", - "offset": 2, - "slot": "0", - "type": "t_contract(CrossDomainMessenger)76013" - }, - { - "astId": 76036, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)48_storage" - }, - { - "astId": 58984, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "deposits", - "offset": 0, - "slot": "49", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)48_storage": { - "encoding": "inplace", - "label": "uint256[48]", - "numberOfBytes": "1536", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(CrossDomainMessenger)76013": { - "encoding": "inplace", - "label": "contract CrossDomainMessenger", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => mapping(uint256 => bool)))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_bool))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(uint256 => bool))", - "numberOfBytes": "32", - "value": "t_mapping(t_uint256,t_bool)" - }, - "t_mapping(t_uint256,t_bool)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x0ec4e7357fd7c3e3661a350cd839c720467242a7a5a895cb032cb08a52ea7021", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MESSENGER()": { - "notice": "Getter for messenger contract." - }, - "OTHER_BRIDGE()": { - "notice": "Address of the bridge on the other network." - }, - "bridgeERC721(address,address,uint256,uint32,bytes)": { - "notice": "Initiates a bridge of an NFT to the caller's account on the other chain. Note that this function can only be called by EOAs. Smart contract wallets should use the `bridgeERC721To` function after ensuring that the recipient address on the remote chain exists. Also note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2." - }, - "bridgeERC721To(address,address,address,uint256,uint32,bytes)": { - "notice": "Initiates a bridge of an NFT to some recipient's account on the other chain. Note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2." - }, - "constructor": { - "notice": "Constructs the contract." - }, - "deposits(address,address,uint256)": { - "notice": "Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token by ID was deposited for a given L2 token." - }, - "finalizeBridgeERC721(address,address,address,address,uint256,bytes)": { - "notice": "Completes an ERC721 bridge from the other domain and sends the ERC721 token to the recipient on this domain." - }, - "initialize(address)": { - "notice": "Initializes the contract." - }, - "messenger()": { - "notice": "Messenger contract on this domain." - }, - "otherBridge()": { - "notice": "Getter for other bridge address." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "ERC721BridgeFinalized(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC721 bridge from the other network is finalized." - }, - "ERC721BridgeInitiated(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC721 bridge to the other network is initiated." - } - }, - "notice": "The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract acts as an escrow for ERC721 tokens deposited into L2." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/L1ERC721BridgeProxy.json b/packages/contracts-bedrock/deployments/goerli/L1ERC721BridgeProxy.json deleted file mode 100644 index f233a6c393e0..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/L1ERC721BridgeProxy.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "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-bedrock/deployments/goerli/L1StandardBridge.json b/packages/contracts-bedrock/deployments/goerli/L1StandardBridge.json deleted file mode 100644 index cc657993302d..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/L1StandardBridge.json +++ /dev/null @@ -1,1215 +0,0 @@ -{ - "abi": [ - { - "inputs": [ - { - "internalType": "address payable", - "name": "_messenger", - "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": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20BridgeFinalized", - "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": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20BridgeInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l1Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20DepositInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l1Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20WithdrawalFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHBridgeFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHBridgeInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHDepositInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHWithdrawalFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "inputs": [], - "name": "MESSENGER", - "outputs": [ - { - "internalType": "contract CrossDomainMessenger", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OTHER_BRIDGE", - "outputs": [ - { - "internalType": "contract StandardBridge", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_localToken", - "type": "address" - }, - { - "internalType": "address", - "name": "_remoteToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeERC20", - "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": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeERC20To", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeETH", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeETHTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "depositERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "depositERC20To", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "depositETH", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "depositETHTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "deposits", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "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": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeBridgeERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeBridgeETH", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeERC20Withdrawal", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeETHWithdrawal", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract SuperchainConfig", - "name": "_superchainConfig", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l2TokenBridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "messenger", - "outputs": [ - { - "internalType": "contract CrossDomainMessenger", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "otherBridge", - "outputs": [ - { - "internalType": "contract StandardBridge", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "superchainConfig", - "outputs": [ - { - "internalType": "contract SuperchainConfig", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "address": "0xbD6d6147C5f0953f29D31167b4041cc367E892ea", - "args": [ - "0x5086d1eEF304eb5284A0f6720f79403b4e9bE294" - ], - "bytecode": "0x60c06040523480156200001157600080fd5b5060405162002eed38038062002eed8339810160408190526200003491620001be565b6001600160a01b03811660805273420000000000000000000000000000000000001060a0526200006560006200006c565b50620001f0565b600054610100900460ff16158080156200008d5750600054600160ff909116105b80620000bd5750620000aa30620001af60201b6200056f1760201c565b158015620000bd575060005460ff166001145b620001255760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff19166001179055801562000149576000805461ff0019166101001790555b603280546001600160a01b0319166001600160a01b0384161790558015620001ab576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600060208284031215620001d157600080fd5b81516001600160a01b0381168114620001e957600080fd5b9392505050565b60805160a051612c7c62000271600039600081816103e70152818161049e015281816105e001528181610b30015281816117070152611db90152600081816102f6015281816104d4015281816105b60152818161061701528181610b0601528181610b6701528181610e63015281816116ca0152611d7d0152612c7c6000f3fe6080604052600436106101795760003560e01c8063838b2520116100cb5780639a2ac6d51161007f578063c4d66de811610059578063c4d66de81461053c578063c89701a21461048f578063e11013dd1461055c57600080fd5b80639a2ac6d5146104f6578063a9f9e67514610509578063b1a1a8821461052957600080fd5b80638f601f66116100b05780638f601f661461044957806391c49bf81461048f578063927ede2d146104c257600080fd5b8063838b252014610409578063870876231461042957600080fd5b80633cb747bf1161012d57806358a997f61161010757806358a997f6146103905780635c975abb146103b05780637f46ddb2146103d557600080fd5b80633cb747bf146102e7578063540abf731461031a57806354fd4d501461033a57600080fd5b80631532ec341161015e5780631532ec341461026a5780631635f5fd1461027d57806335e80ab31461029057600080fd5b80630166a07a1461023757806309fc88431461025757600080fd5b3661023257333b15610212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b610230333362030d406040518060200160405280600081525061058b565b005b600080fd5b34801561024357600080fd5b506102306102523660046126c3565b61059e565b610230610265366004612774565b610a03565b6102306102783660046127c7565b610ada565b61023061028b3660046127c7565b610aee565b34801561029c57600080fd5b506032546102bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102f357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102bd565b34801561032657600080fd5b5061023061033536600461283a565b611032565b34801561034657600080fd5b506103836040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516102de9190612927565b34801561039c57600080fd5b506102306103ab36600461293a565b611077565b3480156103bc57600080fd5b506103c561114b565b60405190151581526020016102de565b3480156103e157600080fd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561041557600080fd5b5061023061042436600461283a565b6111e4565b34801561043557600080fd5b5061023061044436600461293a565b611229565b34801561045557600080fd5b506104816104643660046129bd565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102de565b34801561049b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102bd565b3480156104ce57600080fd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b6102306105043660046129f6565b6112fd565b34801561051557600080fd5b506102306105243660046126c3565b61133f565b610230610537366004612774565b61134e565b34801561054857600080fd5b50610230610557366004612a59565b61141f565b61023061056a3660046129f6565b6115ea565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b610598848434858561162d565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156106bc57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a49190612a76565b73ffffffffffffffffffffffffffffffffffffffff16145b61076e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b61077661114b565b156107dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b6107e687611811565b15610934576107f58787611873565b6108a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561091757600080fd5b505af115801561092b573d6000803e3d6000fd5b505050506109b6565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610972908490612ac2565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556109b6908585611993565b6109fa878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a6792505050565b50505050505050565b333b15610a92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610ad53333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162d92505050565b505050565b610ae78585858585610aee565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015610c0c57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190612a76565b73ffffffffffffffffffffffffffffffffffffffff16145b610cbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b610cc661114b565b15610d2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b823414610dbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610209565b3073ffffffffffffffffffffffffffffffffffffffff851603610e61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610209565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610f3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610209565b610f7e85858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611af592505050565b6000610f9b855a8660405180602001604052806000815250611b68565b90508061102a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610209565b505050505050565b6109fa87873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8292505050565b333b15611106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b61102a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ec992505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111df9190612ad9565b905090565b6109fa87873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ec992505050565b333b156112b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b61102a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8292505050565b61059833858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058b92505050565b6109fa8787878787878761059e565b333b156113dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610ad533338585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058b92505050565b600054610100900460ff161580801561143f5750600054600160ff909116105b806114595750303b158015611459575060005460ff166001145b6114e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610209565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561154357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156115e657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6105983385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162d92505050565b8234146116bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610209565b6116c885858584611ed8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b847f0000000000000000000000000000000000000000000000000000000000000000631635f5fd60e01b898989886040516024016117459493929190612afb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526117d892918890600401612b44565b6000604051808303818588803b1580156117f157600080fd5b505af1158015611805573d6000803e3d6000fd5b50505050505050505050565b600061183d827f1d1d8b6300000000000000000000000000000000000000000000000000000000611f4b565b8061186d575061186d827fec4fc8e300000000000000000000000000000000000000000000000000000000611f4b565b92915050565b600061189f837f1d1d8b6300000000000000000000000000000000000000000000000000000000611f4b565b15611948578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119139190612a76565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905061186d565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610ad59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611f6e565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611adf93929190612b89565b60405180910390a461102a86868686868661207a565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611b54929190612bc7565b60405180910390a361059884848484612102565b600080600080845160208601878a8af19695505050505050565b611b8b87611811565b15611cd957611b9a8787611873565b611c4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611cbc57600080fd5b505af1158015611cd0573d6000803e3d6000fd5b50505050611d6d565b611cfb73ffffffffffffffffffffffffffffffffffffffff881686308661216f565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611d39908490612be0565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611d7b8787878787866121cd565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b7f0000000000000000000000000000000000000000000000000000000000000000630166a07a60e01b898b8a8a8a89604051602401611dfb96959493929190612bf8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611e8e92918790600401612b44565b600060405180830381600087803b158015611ea857600080fd5b505af1158015611ebc573d6000803e3d6000fd5b5050505050505050505050565b6109fa87878787878787611b82565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611f37929190612bc7565b60405180910390a36105988484848461225b565b6000611f56836122ba565b8015611f675750611f67838361231e565b9392505050565b6000611fd0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123ed9092919063ffffffff16565b805190915015610ad55780806020019051810190611fee9190612ad9565b610ad5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610209565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd8686866040516120f293929190612b89565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051612161929190612bc7565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105989085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016119e5565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161224593929190612b89565b60405180910390a461102a868686868686612404565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051612161929190612bc7565b60006122e6827f01ffc9a70000000000000000000000000000000000000000000000000000000061231e565b801561186d5750612317827fffffffff0000000000000000000000000000000000000000000000000000000061231e565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156123d6575060208210155b80156123e25750600081115b979650505050505050565b60606123fc848460008561247c565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf8686866040516120f293929190612b89565b60608247101561250e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610209565b73ffffffffffffffffffffffffffffffffffffffff85163b61258c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610209565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125b59190612c53565b60006040518083038185875af1925050503d80600081146125f2576040519150601f19603f3d011682016040523d82523d6000602084013e6125f7565b606091505b50915091506123e282828660608315612611575081611f67565b8251156126215782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102099190612927565b73ffffffffffffffffffffffffffffffffffffffff8116811461267757600080fd5b50565b60008083601f84011261268c57600080fd5b50813567ffffffffffffffff8111156126a457600080fd5b6020830191508360208285010111156126bc57600080fd5b9250929050565b600080600080600080600060c0888a0312156126de57600080fd5b87356126e981612655565b965060208801356126f981612655565b9550604088013561270981612655565b9450606088013561271981612655565b93506080880135925060a088013567ffffffffffffffff81111561273c57600080fd5b6127488a828b0161267a565b989b979a50959850939692959293505050565b803563ffffffff8116811461276f57600080fd5b919050565b60008060006040848603121561278957600080fd5b6127928461275b565b9250602084013567ffffffffffffffff8111156127ae57600080fd5b6127ba8682870161267a565b9497909650939450505050565b6000806000806000608086880312156127df57600080fd5b85356127ea81612655565b945060208601356127fa81612655565b935060408601359250606086013567ffffffffffffffff81111561281d57600080fd5b6128298882890161267a565b969995985093965092949392505050565b600080600080600080600060c0888a03121561285557600080fd5b873561286081612655565b9650602088013561287081612655565b9550604088013561288081612655565b9450606088013593506128956080890161275b565b925060a088013567ffffffffffffffff81111561273c57600080fd5b60005b838110156128cc5781810151838201526020016128b4565b838111156105985750506000910152565b600081518084526128f58160208601602086016128b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f6760208301846128dd565b60008060008060008060a0878903121561295357600080fd5b863561295e81612655565b9550602087013561296e81612655565b9450604087013593506129836060880161275b565b9250608087013567ffffffffffffffff81111561299f57600080fd5b6129ab89828a0161267a565b979a9699509497509295939492505050565b600080604083850312156129d057600080fd5b82356129db81612655565b915060208301356129eb81612655565b809150509250929050565b60008060008060608587031215612a0c57600080fd5b8435612a1781612655565b9350612a256020860161275b565b9250604085013567ffffffffffffffff811115612a4157600080fd5b612a4d8782880161267a565b95989497509550505050565b600060208284031215612a6b57600080fd5b8135611f6781612655565b600060208284031215612a8857600080fd5b8151611f6781612655565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612ad457612ad4612a93565b500390565b600060208284031215612aeb57600080fd5b81518015158114611f6757600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612b3a60808301846128dd565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612b7360608301856128dd565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612bbe60608301846128dd565b95945050505050565b8281526040602082015260006123fc60408301846128dd565b60008219821115612bf357612bf3612a93565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612c4760c08301846128dd565b98975050505050505050565b60008251612c658184602087016128b1565b919091019291505056fea164736f6c634300080f000a", - "deployedBytecode": "0x6080604052600436106101795760003560e01c8063838b2520116100cb5780639a2ac6d51161007f578063c4d66de811610059578063c4d66de81461053c578063c89701a21461048f578063e11013dd1461055c57600080fd5b80639a2ac6d5146104f6578063a9f9e67514610509578063b1a1a8821461052957600080fd5b80638f601f66116100b05780638f601f661461044957806391c49bf81461048f578063927ede2d146104c257600080fd5b8063838b252014610409578063870876231461042957600080fd5b80633cb747bf1161012d57806358a997f61161010757806358a997f6146103905780635c975abb146103b05780637f46ddb2146103d557600080fd5b80633cb747bf146102e7578063540abf731461031a57806354fd4d501461033a57600080fd5b80631532ec341161015e5780631532ec341461026a5780631635f5fd1461027d57806335e80ab31461029057600080fd5b80630166a07a1461023757806309fc88431461025757600080fd5b3661023257333b15610212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b610230333362030d406040518060200160405280600081525061058b565b005b600080fd5b34801561024357600080fd5b506102306102523660046126c3565b61059e565b610230610265366004612774565b610a03565b6102306102783660046127c7565b610ada565b61023061028b3660046127c7565b610aee565b34801561029c57600080fd5b506032546102bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102f357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102bd565b34801561032657600080fd5b5061023061033536600461283a565b611032565b34801561034657600080fd5b506103836040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516102de9190612927565b34801561039c57600080fd5b506102306103ab36600461293a565b611077565b3480156103bc57600080fd5b506103c561114b565b60405190151581526020016102de565b3480156103e157600080fd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561041557600080fd5b5061023061042436600461283a565b6111e4565b34801561043557600080fd5b5061023061044436600461293a565b611229565b34801561045557600080fd5b506104816104643660046129bd565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102de565b34801561049b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102bd565b3480156104ce57600080fd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b6102306105043660046129f6565b6112fd565b34801561051557600080fd5b506102306105243660046126c3565b61133f565b610230610537366004612774565b61134e565b34801561054857600080fd5b50610230610557366004612a59565b61141f565b61023061056a3660046129f6565b6115ea565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b610598848434858561162d565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156106bc57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a49190612a76565b73ffffffffffffffffffffffffffffffffffffffff16145b61076e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b61077661114b565b156107dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b6107e687611811565b15610934576107f58787611873565b6108a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561091757600080fd5b505af115801561092b573d6000803e3d6000fd5b505050506109b6565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610972908490612ac2565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556109b6908585611993565b6109fa878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a6792505050565b50505050505050565b333b15610a92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610ad53333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162d92505050565b505050565b610ae78585858585610aee565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015610c0c57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190612a76565b73ffffffffffffffffffffffffffffffffffffffff16145b610cbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b610cc661114b565b15610d2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b823414610dbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610209565b3073ffffffffffffffffffffffffffffffffffffffff851603610e61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610209565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610f3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610209565b610f7e85858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611af592505050565b6000610f9b855a8660405180602001604052806000815250611b68565b90508061102a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610209565b505050505050565b6109fa87873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8292505050565b333b15611106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b61102a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ec992505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111df9190612ad9565b905090565b6109fa87873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ec992505050565b333b156112b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b61102a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8292505050565b61059833858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058b92505050565b6109fa8787878787878761059e565b333b156113dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610ad533338585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058b92505050565b600054610100900460ff161580801561143f5750600054600160ff909116105b806114595750303b158015611459575060005460ff166001145b6114e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610209565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561154357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156115e657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6105983385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162d92505050565b8234146116bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610209565b6116c885858584611ed8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b847f0000000000000000000000000000000000000000000000000000000000000000631635f5fd60e01b898989886040516024016117459493929190612afb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526117d892918890600401612b44565b6000604051808303818588803b1580156117f157600080fd5b505af1158015611805573d6000803e3d6000fd5b50505050505050505050565b600061183d827f1d1d8b6300000000000000000000000000000000000000000000000000000000611f4b565b8061186d575061186d827fec4fc8e300000000000000000000000000000000000000000000000000000000611f4b565b92915050565b600061189f837f1d1d8b6300000000000000000000000000000000000000000000000000000000611f4b565b15611948578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119139190612a76565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905061186d565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610ad59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611f6e565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611adf93929190612b89565b60405180910390a461102a86868686868661207a565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611b54929190612bc7565b60405180910390a361059884848484612102565b600080600080845160208601878a8af19695505050505050565b611b8b87611811565b15611cd957611b9a8787611873565b611c4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611cbc57600080fd5b505af1158015611cd0573d6000803e3d6000fd5b50505050611d6d565b611cfb73ffffffffffffffffffffffffffffffffffffffff881686308661216f565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611d39908490612be0565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611d7b8787878787866121cd565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b7f0000000000000000000000000000000000000000000000000000000000000000630166a07a60e01b898b8a8a8a89604051602401611dfb96959493929190612bf8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611e8e92918790600401612b44565b600060405180830381600087803b158015611ea857600080fd5b505af1158015611ebc573d6000803e3d6000fd5b5050505050505050505050565b6109fa87878787878787611b82565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611f37929190612bc7565b60405180910390a36105988484848461225b565b6000611f56836122ba565b8015611f675750611f67838361231e565b9392505050565b6000611fd0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123ed9092919063ffffffff16565b805190915015610ad55780806020019051810190611fee9190612ad9565b610ad5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610209565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd8686866040516120f293929190612b89565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051612161929190612bc7565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105989085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016119e5565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161224593929190612b89565b60405180910390a461102a868686868686612404565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051612161929190612bc7565b60006122e6827f01ffc9a70000000000000000000000000000000000000000000000000000000061231e565b801561186d5750612317827fffffffff0000000000000000000000000000000000000000000000000000000061231e565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156123d6575060208210155b80156123e25750600081115b979650505050505050565b60606123fc848460008561247c565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf8686866040516120f293929190612b89565b60608247101561250e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610209565b73ffffffffffffffffffffffffffffffffffffffff85163b61258c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610209565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125b59190612c53565b60006040518083038185875af1925050503d80600081146125f2576040519150601f19603f3d011682016040523d82523d6000602084013e6125f7565b606091505b50915091506123e282828660608315612611575081611f67565b8251156126215782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102099190612927565b73ffffffffffffffffffffffffffffffffffffffff8116811461267757600080fd5b50565b60008083601f84011261268c57600080fd5b50813567ffffffffffffffff8111156126a457600080fd5b6020830191508360208285010111156126bc57600080fd5b9250929050565b600080600080600080600060c0888a0312156126de57600080fd5b87356126e981612655565b965060208801356126f981612655565b9550604088013561270981612655565b9450606088013561271981612655565b93506080880135925060a088013567ffffffffffffffff81111561273c57600080fd5b6127488a828b0161267a565b989b979a50959850939692959293505050565b803563ffffffff8116811461276f57600080fd5b919050565b60008060006040848603121561278957600080fd5b6127928461275b565b9250602084013567ffffffffffffffff8111156127ae57600080fd5b6127ba8682870161267a565b9497909650939450505050565b6000806000806000608086880312156127df57600080fd5b85356127ea81612655565b945060208601356127fa81612655565b935060408601359250606086013567ffffffffffffffff81111561281d57600080fd5b6128298882890161267a565b969995985093965092949392505050565b600080600080600080600060c0888a03121561285557600080fd5b873561286081612655565b9650602088013561287081612655565b9550604088013561288081612655565b9450606088013593506128956080890161275b565b925060a088013567ffffffffffffffff81111561273c57600080fd5b60005b838110156128cc5781810151838201526020016128b4565b838111156105985750506000910152565b600081518084526128f58160208601602086016128b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f6760208301846128dd565b60008060008060008060a0878903121561295357600080fd5b863561295e81612655565b9550602087013561296e81612655565b9450604087013593506129836060880161275b565b9250608087013567ffffffffffffffff81111561299f57600080fd5b6129ab89828a0161267a565b979a9699509497509295939492505050565b600080604083850312156129d057600080fd5b82356129db81612655565b915060208301356129eb81612655565b809150509250929050565b60008060008060608587031215612a0c57600080fd5b8435612a1781612655565b9350612a256020860161275b565b9250604085013567ffffffffffffffff811115612a4157600080fd5b612a4d8782880161267a565b95989497509550505050565b600060208284031215612a6b57600080fd5b8135611f6781612655565b600060208284031215612a8857600080fd5b8151611f6781612655565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612ad457612ad4612a93565b500390565b600060208284031215612aeb57600080fd5b81518015158114611f6757600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612b3a60808301846128dd565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612b7360608301856128dd565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612bbe60608301846128dd565b95945050505050565b8281526040602082015260006123fc60408301846128dd565b60008219821115612bf357612bf3612a93565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612c4760c08301846128dd565b98975050505050505050565b60008251612c658184602087016128b1565b919091019291505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "bridgeERC20(address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of local tokens to deposit.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_localToken": "Address of the ERC20 on this chain.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", - "_remoteToken": "Address of the corresponding token on the remote chain." - } - }, - "bridgeERC20To(address,address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of local tokens to deposit.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_localToken": "Address of the ERC20 on this chain.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", - "_remoteToken": "Address of the corresponding token on the remote chain.", - "_to": "Address of the receiver." - } - }, - "bridgeETH(uint32,bytes)": { - "params": { - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with." - } - }, - "bridgeETHTo(address,uint32,bytes)": { - "params": { - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", - "_to": "Address of the receiver." - } - }, - "constructor": { - "params": { - "_messenger": "Address of the L1CrossDomainMessenger." - } - }, - "depositERC20(address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of the ERC20 to deposit.", - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_l1Token": "Address of the L1 token being deposited.", - "_l2Token": "Address of the corresponding token on L2.", - "_minGasLimit": "Minimum gas limit for the deposit message on L2." - } - }, - "depositERC20To(address,address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of the ERC20 to deposit.", - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_l1Token": "Address of the L1 token being deposited.", - "_l2Token": "Address of the corresponding token on L2.", - "_minGasLimit": "Minimum gas limit for the deposit message on L2.", - "_to": "Address of the recipient on L2." - } - }, - "depositETH(uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_minGasLimit": "Minimum gas limit for the deposit message on L2." - } - }, - "depositETHTo(address,uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_minGasLimit": "Minimum gas limit for the deposit message on L2.", - "_to": "Address of the recipient on L2." - } - }, - "finalizeBridgeERC20(address,address,address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of the ERC20 being bridged.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_from": "Address of the sender.", - "_localToken": "Address of the ERC20 on this chain.", - "_remoteToken": "Address of the corresponding token on the remote chain.", - "_to": "Address of the receiver." - } - }, - "finalizeBridgeETH(address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of ETH being bridged.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_from": "Address of the sender.", - "_to": "Address of the receiver." - } - }, - "finalizeERC20Withdrawal(address,address,address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of the ERC20 to withdraw.", - "_extraData": "Optional data forwarded from L2.", - "_from": "Address of the withdrawer on L2.", - "_l1Token": "Address of the token on L1.", - "_l2Token": "Address of the corresponding token on L2.", - "_to": "Address of the recipient on L1." - } - }, - "finalizeETHWithdrawal(address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of ETH to withdraw.", - "_extraData": "Optional data forwarded from L2.", - "_from": "Address of the withdrawer on L2.", - "_to": "Address of the recipient on L1." - } - }, - "initialize(address)": { - "params": { - "_superchainConfig": "Address of the SuperchainConfig contract on this network." - } - }, - "l2TokenBridge()": { - "returns": { - "_0": "Address of the corresponding L2 bridge contract." - } - }, - "messenger()": { - "returns": { - "_0": "Messenger contract on this domain." - } - }, - "otherBridge()": { - "returns": { - "_0": "The bridge contract on the other network." - } - }, - "paused()": { - "returns": { - "_0": "Whether or not the contract is paused." - } - } - }, - "events": { - "ERC20DepositInitiated(address,address,address,address,uint256,bytes)": { - "params": { - "amount": "Amount of the ERC20 deposited.", - "extraData": "Extra data attached to the deposit.", - "from": "Address of the depositor.", - "l1Token": "Address of the token on L1.", - "l2Token": "Address of the corresponding token on L2.", - "to": "Address of the recipient on L2." - } - }, - "ERC20WithdrawalFinalized(address,address,address,address,uint256,bytes)": { - "params": { - "amount": "Amount of the ERC20 withdrawn.", - "extraData": "Extra data attached to the withdrawal.", - "from": "Address of the withdrawer.", - "l1Token": "Address of the token on L1.", - "l2Token": "Address of the corresponding token on L2.", - "to": "Address of the recipient on L1." - } - }, - "ETHDepositInitiated(address,address,uint256,bytes)": { - "params": { - "amount": "Amount of ETH deposited.", - "extraData": "Extra data attached to the deposit.", - "from": "Address of the depositor.", - "to": "Address of the recipient on L2." - } - }, - "ETHWithdrawalFinalized(address,address,uint256,bytes)": { - "params": { - "amount": "Amount of ETH withdrawn.", - "extraData": "Extra data attached to the withdrawal.", - "from": "Address of the withdrawer.", - "to": "Address of the recipient on L1." - } - } - } - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_messenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20BridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20BridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20DepositInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20WithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHBridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHBridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHDepositInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHWithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"contract StandardBridge\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC20To\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"bridgeETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"bridgeETHTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"depositERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"depositERC20To\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositETHTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeBridgeERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"finalizeBridgeETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeERC20Withdrawal\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"finalizeETHWithdrawal\"},{\"inputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"_superchainConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2TokenBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"contract StandardBridge\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"superchainConfig\",\"outputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bridgeERC20(address,address,uint256,uint32,bytes)\":{\"params\":{\"_amount\":\"Amount of local tokens to deposit.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\"}},\"bridgeERC20To(address,address,address,uint256,uint32,bytes)\":{\"params\":{\"_amount\":\"Amount of local tokens to deposit.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\",\"_to\":\"Address of the receiver.\"}},\"bridgeETH(uint32,bytes)\":{\"params\":{\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\"}},\"bridgeETHTo(address,uint32,bytes)\":{\"params\":{\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_to\":\"Address of the receiver.\"}},\"constructor\":{\"params\":{\"_messenger\":\"Address of the L1CrossDomainMessenger.\"}},\"depositERC20(address,address,uint256,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ERC20 tokens into the sender's account on L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to deposit.\",\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_l1Token\":\"Address of the L1 token being deposited.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\"}},\"depositERC20To(address,address,address,uint256,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ERC20 tokens into a target account on L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to deposit.\",\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_l1Token\":\"Address of the L1 token being deposited.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\",\"_to\":\"Address of the recipient on L2.\"}},\"depositETH(uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ETH into the sender's account on L2.\",\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\"}},\"depositETHTo(address,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ETH into a target account on L2. Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will be locked in the L2StandardBridge. ETH may be recoverable if the call can be successfully replayed by increasing the amount of gas supplied to the call. If the call will fail for any amount of gas, then the ETH will be locked permanently.\",\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\",\"_to\":\"Address of the recipient on L2.\"}},\"finalizeBridgeERC20(address,address,address,address,uint256,bytes)\":{\"params\":{\"_amount\":\"Amount of the ERC20 being bridged.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_from\":\"Address of the sender.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\",\"_to\":\"Address of the receiver.\"}},\"finalizeBridgeETH(address,address,uint256,bytes)\":{\"params\":{\"_amount\":\"Amount of ETH being bridged.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_from\":\"Address of the sender.\",\"_to\":\"Address of the receiver.\"}},\"finalizeERC20Withdrawal(address,address,address,address,uint256,bytes)\":{\"custom:legacy\":\"@notice Finalizes a withdrawal of ERC20 tokens from L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to withdraw.\",\"_extraData\":\"Optional data forwarded from L2.\",\"_from\":\"Address of the withdrawer on L2.\",\"_l1Token\":\"Address of the token on L1.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_to\":\"Address of the recipient on L1.\"}},\"finalizeETHWithdrawal(address,address,uint256,bytes)\":{\"custom:legacy\":\"@notice Finalizes a withdrawal of ETH from L2.\",\"params\":{\"_amount\":\"Amount of ETH to withdraw.\",\"_extraData\":\"Optional data forwarded from L2.\",\"_from\":\"Address of the withdrawer on L2.\",\"_to\":\"Address of the recipient on L1.\"}},\"initialize(address)\":{\"params\":{\"_superchainConfig\":\"Address of the SuperchainConfig contract on this network.\"}},\"l2TokenBridge()\":{\"custom:legacy\":\"@notice Retrieves the access of the corresponding L2 bridge contract.\",\"returns\":{\"_0\":\"Address of the corresponding L2 bridge contract.\"}},\"messenger()\":{\"returns\":{\"_0\":\"Messenger contract on this domain.\"}},\"otherBridge()\":{\"returns\":{\"_0\":\"The bridge contract on the other network.\"}},\"paused()\":{\"returns\":{\"_0\":\"Whether or not the contract is paused.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSENGER()\":{\"notice\":\"Messenger contract on this domain.\"},\"OTHER_BRIDGE()\":{\"notice\":\"Corresponding bridge on the other domain.\"},\"bridgeERC20(address,address,uint256,uint32,bytes)\":{\"notice\":\"Sends ERC20 tokens to the sender's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain.\"},\"bridgeERC20To(address,address,address,uint256,uint32,bytes)\":{\"notice\":\"Sends ERC20 tokens to a receiver's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain.\"},\"bridgeETH(uint32,bytes)\":{\"notice\":\"Sends ETH to the sender's address on the other chain.\"},\"bridgeETHTo(address,uint32,bytes)\":{\"notice\":\"Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a smart contract and the call fails, the ETH will be temporarily locked in the StandardBridge on the other chain until the call is replayed. If the call cannot be replayed with any amount of gas (call always reverts), then the ETH will be permanently locked in the StandardBridge on the other chain. ETH will also be locked if the receiver is the other bridge, because finalizeBridgeETH will revert in that case.\"},\"constructor\":{\"notice\":\"Constructs the L1StandardBridge contract.\"},\"deposits(address,address)\":{\"notice\":\"Mapping that stores deposits for a given pair of local and remote tokens.\"},\"finalizeBridgeERC20(address,address,address,address,uint256,bytes)\":{\"notice\":\"Finalizes an ERC20 bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain.\"},\"finalizeBridgeETH(address,address,uint256,bytes)\":{\"notice\":\"Finalizes an ETH bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain.\"},\"initialize(address)\":{\"notice\":\"Initializes the contract.\"},\"messenger()\":{\"notice\":\"Getter for messenger contract.\"},\"otherBridge()\":{\"notice\":\"Getter for the other bridge.\"},\"paused()\":{\"notice\":\"This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op.\"},\"superchainConfig()\":{\"notice\":\"Address of the SuperchainConfig contract.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1StandardBridge.sol\":\"L1StandardBridge\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"urls\":[\"bzz-raw://b2717fd2bdac99daa960a6de500754ea1b932093c946388c381da48658234b95\",\"dweb:/ipfs/QmP6QVMn6UeA3ByahyJbYQr5M6coHKBKsf3ySZSfbyA8R7\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x032807210d1d7d218963d7355d62e021a84bf1b3339f4f50be2f63b53cccaf29\",\"urls\":[\"bzz-raw://11756f42121f6541a35a8339ea899ee7514cfaa2e6d740625fcc844419296aa6\",\"dweb:/ipfs/QmekMuk6BY4DAjzeXr4MSbKdgoqqsZnA8JPtuyWc6CwXHf\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1StandardBridge.sol\":{\"keccak256\":\"0x2564decacc35545e2de52ea7793ceaa561ec4bc86fdd9d56b41c199cd6bca7ef\",\"urls\":[\"bzz-raw://6231b05c0c581b04536ac968ce053a99312d24e35defcd64b4f2cb8540ffe268\",\"dweb:/ipfs/QmRrq2Sguo4CyMyy8KPyXsGe4ULQr8Tm3919eRsvs3yPte\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x9d6e33ea5d12b78fd3cb024ed5863c8c14cb55977cbab56fd9ce5c309918afc6\",\"urls\":[\"bzz-raw://d8545d6255ed4428b168a3547d6935043e5b680344d650fd090293ba36b59897\",\"dweb:/ipfs/QmPLVma7kqTTgbAHtxog2MGD7S2Wr8nd42MhBcfJ5yyF4W\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x75408c79fd51bd6f53ab1ad1719ec09264d1e6965cd5604c8346fbee76039fc3\",\"urls\":[\"bzz-raw://100be0dc2c772b569820b3c0828fac21fb241773c586eb8e789b4ddbca89f4f8\",\"dweb:/ipfs/QmW8NrsSeu1kYkga5cdjuzQ853dZZKFY22ZaycoHwiStbw\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x62e11a169b3fa987af2427bf5117612e2770d4cca51565e6bbfe255ff7ffc4bb\",\"urls\":[\"bzz-raw://c852c8c0571bb22d9f28d577620a71de5ee60eb0c7ab8c68645da9a7295d24a0\",\"dweb:/ipfs/QmdixJ2dpsz8N8CgZz8z1MkZNVjw6ZkRM6bS7mchPYX6Yi\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x6f8133b39efcbcbd5088f195dfacf1bedc3146508429c3865443909af735a04c\",\"urls\":[\"bzz-raw://adc36971e2e120458769f050428d9d2b0504516660345020c2521ee46e6d8abf\",\"dweb:/ipfs/QmPbFusQkZgGKpU8Fv5JoqL4oVeJtM3yqnhRGLY9eZT5zZ\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x18721f41a831ec39d47002e73ecc2aa3e6624f8d1ab7b9f25b53348e8b0765df\",\"urls\":[\"bzz-raw://2162fa7529a77b199a07f37fca26c778542f6c8805f0365f1ceef90c5cd3a3a7\",\"dweb:/ipfs/QmaMmHJS52Bp95AGnrjh1zV7fLLqV3uAbFzkVLziMnPJYa\"],\"license\":\"MIT\"},\"src/universal/StandardBridge.sol\":{\"keccak256\":\"0x84b8925a791503b39861a9bf692e45d149053922b1339abe4d13b633121f0493\",\"urls\":[\"bzz-raw://b71e4723358644d72b35442530abdbdfcb425d807c675ba0bf94c2b95632bff2\",\"dweb:/ipfs/QmaKMD4wkAdiGGBhG49AN62jzD5F5PLWcNKjMasLwyN2WE\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 5, - "receipt": { - "transactionHash": "0x0a3334826c23b5ce213ba7cb0781ae61efbfcdfb96ceff7245cc6322aebca0bf", - "transactionIndex": "0x5", - "blockHash": "0x748f8022ca00bcb03cba62df6bbe8fa5c1605e852a0d9eb0bd368397e7f71d99", - "blockNumber": "0x9ace87", - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "cumulativeGasUsed": "0x2a84e6", - "gasUsed": "0x26a66d", - "contractAddress": "0xbD6d6147C5f0953f29D31167b4041cc367E892ea", - "logs": [ - { - "address": "0xbD6d6147C5f0953f29D31167b4041cc367E892ea", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "blockHash": "0x748f8022ca00bcb03cba62df6bbe8fa5c1605e852a0d9eb0bd368397e7f71d99", - "blockNumber": "0x9ace87", - "transactionHash": "0x0a3334826c23b5ce213ba7cb0781ae61efbfcdfb96ceff7245cc6322aebca0bf", - "transactionIndex": "0x5", - "logIndex": "0x3", - "removed": false - } - ], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000008040000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "type": "0x2", - "effectiveGasPrice": "0xb2d05e0b" - }, - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 47332, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 47335, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 96816, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "spacer_0_2_20", - "offset": 2, - "slot": "0", - "type": "t_address" - }, - { - "astId": 96819, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "spacer_1_0_20", - "offset": 0, - "slot": "1", - "type": "t_address" - }, - { - "astId": 96826, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "deposits", - "offset": 0, - "slot": "2", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" - }, - { - "astId": 96831, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "__gap", - "offset": 0, - "slot": "3", - "type": "t_array(t_uint256)47_storage" - }, - { - "astId": 75748, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "superchainConfig", - "offset": 0, - "slot": "50", - "type": "t_contract(SuperchainConfig)78153" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)47_storage": { - "encoding": "inplace", - "label": "uint256[47]", - "numberOfBytes": "1504", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(SuperchainConfig)78153": { - "encoding": "inplace", - "label": "contract SuperchainConfig", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x0a3334826c23b5ce213ba7cb0781ae61efbfcdfb96ceff7245cc6322aebca0bf", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MESSENGER()": { - "notice": "Messenger contract on this domain." - }, - "OTHER_BRIDGE()": { - "notice": "Corresponding bridge on the other domain." - }, - "bridgeERC20(address,address,uint256,uint32,bytes)": { - "notice": "Sends ERC20 tokens to the sender's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain." - }, - "bridgeERC20To(address,address,address,uint256,uint32,bytes)": { - "notice": "Sends ERC20 tokens to a receiver's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain." - }, - "bridgeETH(uint32,bytes)": { - "notice": "Sends ETH to the sender's address on the other chain." - }, - "bridgeETHTo(address,uint32,bytes)": { - "notice": "Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a smart contract and the call fails, the ETH will be temporarily locked in the StandardBridge on the other chain until the call is replayed. If the call cannot be replayed with any amount of gas (call always reverts), then the ETH will be permanently locked in the StandardBridge on the other chain. ETH will also be locked if the receiver is the other bridge, because finalizeBridgeETH will revert in that case." - }, - "constructor": { - "notice": "Constructs the L1StandardBridge contract." - }, - "deposits(address,address)": { - "notice": "Mapping that stores deposits for a given pair of local and remote tokens." - }, - "finalizeBridgeERC20(address,address,address,address,uint256,bytes)": { - "notice": "Finalizes an ERC20 bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain." - }, - "finalizeBridgeETH(address,address,uint256,bytes)": { - "notice": "Finalizes an ETH bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain." - }, - "initialize(address)": { - "notice": "Initializes the contract." - }, - "messenger()": { - "notice": "Getter for messenger contract." - }, - "otherBridge()": { - "notice": "Getter for the other bridge." - }, - "paused()": { - "notice": "This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op." - }, - "superchainConfig()": { - "notice": "Address of the SuperchainConfig contract." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "ERC20BridgeFinalized(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC20 bridge is finalized on this chain." - }, - "ERC20BridgeInitiated(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC20 bridge is initiated to the other chain." - }, - "ETHBridgeFinalized(address,address,uint256,bytes)": { - "notice": "Emitted when an ETH bridge is finalized on this chain." - }, - "ETHBridgeInitiated(address,address,uint256,bytes)": { - "notice": "Emitted when an ETH bridge is initiated to the other chain." - } - }, - "notice": "The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and L2. In the case that an ERC20 token is native to L1, it will be escrowed within this contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was stored within this contract. After Bedrock, ETH is instead stored inside the OptimismPortal contract. NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples of some token types that may not be properly supported by this contract include, but are not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/L1StandardBridgeProxy.json b/packages/contracts-bedrock/deployments/goerli/L1StandardBridgeProxy.json deleted file mode 100644 index 040726460d21..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/L1StandardBridgeProxy.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "address": "0x636Af16bf2f682dD3109e60102b8E1A089FedAa8", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "getImplementation", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_code", - "type": "bytes" - } - ], - "name": "setCode", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "setOwner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_key", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_value", - "type": "bytes32" - } - ], - "name": "setStorage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xd57130025124776619229f980ae08c3097156ab127c897fa9ef17e29bf757a16", - "receipt": { - "to": null, - "from": "0x3a605B442055DF2898E18cF518feb2e2A6BD0D31", - "contractAddress": "0x636Af16bf2f682dD3109e60102b8E1A089FedAa8", - "transactionIndex": 8, - "gasUsed": "614417", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x85ce123b23be93051e83bc9d6dd2bf7817ee0fd338b936684c821020b8285393", - "transactionHash": "0xd57130025124776619229f980ae08c3097156ab127c897fa9ef17e29bf757a16", - "logs": [], - "blockNumber": 7017137, - "cumulativeGasUsed": "5543459", - "status": 1, - "byzantium": true - }, - "args": [ - "0x3a605B442055DF2898E18cF518feb2e2A6BD0D31" - ], - "numDeployments": 1, - "solcInputHash": "0a41276e1e61949b5de1e4f1cd89fb6c", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"getImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_code\",\"type\":\"bytes\"}],\"name\":\"setCode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_value\",\"type\":\"bytes32\"}],\"name\":\"setStorage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added functions `setCode` and `setStorage` for changing the code or storage of the contract. Nifty! Note for future developers: do NOT make anything in this contract 'public' unless you know what you're doing. Anything public can potentially have a function signature that conflicts with a signature attached to the implementation contract. Public functions SHOULD always have the 'proxyCallIfNotOwner' modifier unless there's some *really* good reason not to have that modifier. And there almost certainly is not a good reason to not have that modifier. Beware!\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_owner\":\"Address of the initial contract owner.\"}},\"getImplementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"getOwner()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"setCode(bytes)\":{\"params\":{\"_code\":\"New contract code to run inside this contract.\"}},\"setOwner(address)\":{\"params\":{\"_owner\":\"New owner of the proxy contract.\"}},\"setStorage(bytes32,bytes32)\":{\"params\":{\"_key\":\"Storage key to modify.\",\"_value\":\"New value for the storage key.\"}}},\"title\":\"L1ChugSplashProxy\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getImplementation()\":{\"notice\":\"Queries the implementation address. Can only be called by the owner OR by making an eth_call and setting the \\\"from\\\" address to address(0).\"},\"getOwner()\":{\"notice\":\"Queries the owner of the proxy contract. Can only be called by the owner OR by making an eth_call and setting the \\\"from\\\" address to address(0).\"},\"setCode(bytes)\":{\"notice\":\"Sets the code that should be running behind this proxy. Note that this scheme is a bit different from the standard proxy scheme where one would typically deploy the code separately and then set the implementation address. We're doing it this way because it gives us a lot more freedom on the client side. Can only be triggered by the contract owner.\"},\"setOwner(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"setStorage(bytes32,bytes32)\":{\"notice\":\"Modifies some storage slot within the proxy contract. Gives us a lot of power to perform upgrades in a more transparent way. Only callable by the owner.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/chugsplash/L1ChugSplashProxy.sol\":\"L1ChugSplashProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/chugsplash/L1ChugSplashProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\nimport { iL1ChugSplashDeployer } from \\\"./interfaces/iL1ChugSplashDeployer.sol\\\";\\n\\n/**\\n * @title L1ChugSplashProxy\\n * @dev 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. Nifty!\\n *\\n * Note for future developers: do NOT make anything in this contract 'public' unless you know what\\n * you're doing. Anything public can potentially have a function signature that conflicts with a\\n * signature attached to the implementation contract. Public functions SHOULD always have the\\n * 'proxyCallIfNotOwner' modifier unless there's some *really* good reason not to have that\\n * modifier. And there almost certainly is not a good reason to not have that modifier. Beware!\\n */\\ncontract L1ChugSplashProxy {\\n /*************\\n * Constants *\\n *************/\\n\\n // \\\"Magic\\\" prefix. When prepended to some arbitrary bytecode and used to create a contract, the\\n // appended bytecode will be deployed as given.\\n bytes13 internal constant DEPLOY_CODE_PREFIX = 0x600D380380600D6000396000f3;\\n\\n // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\\n bytes32 internal constant IMPLEMENTATION_KEY =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n // bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\\n bytes32 internal constant OWNER_KEY =\\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /***************\\n * Constructor *\\n ***************/\\n\\n /**\\n * @param _owner Address of the initial contract owner.\\n */\\n constructor(address _owner) {\\n _setOwner(_owner);\\n }\\n\\n /**********************\\n * Function Modifiers *\\n **********************/\\n\\n /**\\n * Blocks a function from being called when the parent signals that the system should be paused\\n * 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 * Makes a proxy call instead of triggering the given function when the caller is either the\\n * owner or the zero address. Caller can only ever be the zero address if this function is\\n * being called off-chain via eth_call, which is totally fine and can be convenient for\\n * client-side tooling. Avoids situations where the proxy and implementation share a sighash\\n * and the proxy function ends up being called instead of the implementation one.\\n *\\n * Note: msg.sender == address(0) can ONLY be triggered off-chain via eth_call. If there's a\\n * way for someone to send a transaction with msg.sender == address(0) in any real context then\\n * we have much bigger problems. Primary reason to include this additional allowed sender is\\n * because the owner address can be changed dynamically and we do not want clients to have to\\n * keep track of the current owner in order to make an eth_call that doesn't trigger the\\n * 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 * Fallback Function *\\n *********************/\\n\\n // slither-disable-next-line locked-ether\\n fallback() external payable {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n /********************\\n * Public Functions *\\n ********************/\\n\\n /**\\n * Sets the code that should be running behind this proxy. Note that this scheme is a bit\\n * different from the standard proxy scheme where one would typically deploy the code\\n * separately and then set the implementation address. We're doing it this way because it gives\\n * us a lot more freedom on the client side. Can only be triggered by the contract owner.\\n * @param _code New contract code to run inside this contract.\\n */\\n // slither-disable-next-line external-function\\n function setCode(bytes memory _code) public 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 * Modifies some storage slot within the proxy contract. Gives us a lot of power to perform\\n * upgrades in a more transparent way. Only callable by the owner.\\n * @param _key Storage key to modify.\\n * @param _value New value for the storage key.\\n */\\n // slither-disable-next-line external-function\\n function setStorage(bytes32 _key, bytes32 _value) public proxyCallIfNotOwner {\\n assembly {\\n sstore(_key, _value)\\n }\\n }\\n\\n /**\\n * Changes the owner of the proxy contract. Only callable by the owner.\\n * @param _owner New owner of the proxy contract.\\n */\\n // slither-disable-next-line external-function\\n function setOwner(address _owner) public proxyCallIfNotOwner {\\n _setOwner(_owner);\\n }\\n\\n /**\\n * Queries the owner of the proxy contract. Can only be called by the owner OR by making an\\n * eth_call and setting the \\\"from\\\" address to address(0).\\n * @return Owner address.\\n */\\n // slither-disable-next-line external-function\\n function getOwner() public proxyCallIfNotOwner returns (address) {\\n return _getOwner();\\n }\\n\\n /**\\n * 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 * @return Implementation address.\\n */\\n // slither-disable-next-line external-function\\n function getImplementation() public proxyCallIfNotOwner returns (address) {\\n return _getImplementation();\\n }\\n\\n /**********************\\n * Internal Functions *\\n **********************/\\n\\n /**\\n * Sets the implementation address.\\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 * Queries the implementation address.\\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 * Changes the owner of the proxy contract.\\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 * Queries the owner of the proxy contract.\\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 * Gets the code hash for a given account.\\n * @param _account Address of the account to get a code hash for.\\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 /**\\n * 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\",\"keccak256\":\"0xc3cb52dfdc2706992572dd5621ae89ba919fd20539b73488a455d564f16f1b8d\",\"license\":\"MIT\"},\"contracts/chugsplash/interfaces/iL1ChugSplashDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\n/**\\n * @title iL1ChugSplashDeployer\\n */\\ninterface iL1ChugSplashDeployer {\\n function isUpgrading() external view returns (bool);\\n}\\n\",\"keccak256\":\"0x9a496d99f111c1091f0c33d6bfc7802a522baa7235614b0014f35e4bbe280e57\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50604051610a5d380380610a5d83398101604081905261002f9161005d565b610057817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b5061008d565b60006020828403121561006f57600080fd5b81516001600160a01b038116811461008657600080fd5b9392505050565b6109c18061009c6000396000f3fe60806040526004361061005a5760003560e01c8063893d20e811610043578063893d20e8146100a45780639b0b0fda146100e2578063aaf10f42146101025761005a565b806313af4035146100645780636c5d4ad014610084575b610062610117565b005b34801561007057600080fd5b5061006261007f366004610792565b6103ba565b34801561009057600080fd5b5061006261009f3660046107fe565b61044b565b3480156100b057600080fd5b506100b9610601565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ee57600080fd5b506100626100fd3660046108cd565b610698565b34801561010e57600080fd5b506100b9610706565b60006101417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb7947262000000000000000000000000000000000000000000000000000000001790529051919250600091829173ffffffffffffffffffffffffffffffffffffffff8516916101c3919061092a565b600060405180830381855afa9150503d80600081146101fe576040519150601f19603f3d011682016040523d82523d6000602084013e610203565b606091505b5091509150818015610216575080516020145b156102c8576000818060200190518101906102319190610936565b905080156102c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c314368756753706c61736850726f78793a2073797374656d2069732063757260448201527f72656e746c79206265696e67207570677261646564000000000000000000000060648201526084015b60405180910390fd5b505b60006102f27f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610397576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4c314368756753706c61736850726f78793a20696d706c656d656e746174696f60448201527f6e206973206e6f7420736574207965740000000000000000000000000000000060648201526084016102bd565b3660008037600080366000845af43d6000803e806103b4573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610413575033155b1561044357610440817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b50565b610440610117565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104a4575033155b156104435760006104d37f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050803f8251602084012014156104e8575050565b60405160009061051e907f600d380380600d6000396000f30000000000000000000000000000000000000090859060200161094f565b604051602081830303815290604052905060008151602083016000f084516020860120909150813f146105d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f4c314368756753706c61736850726f78793a20636f646520776173206e6f742060448201527f636f72726563746c79206465706c6f7965642e0000000000000000000000000060648201526084016102bd565b6105fb817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b50505050565b600061062b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610662575033155b1561068d57507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b610695610117565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806106f1575033155b156106fa579055565b610702610117565b5050565b60006107307fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610767575033155b1561068d57507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000602082840312156107a457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146107c857600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561081057600080fd5b813567ffffffffffffffff8082111561082857600080fd5b818401915084601f83011261083c57600080fd5b81358181111561084e5761084e6107cf565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610894576108946107cf565b816040528281528760208487010111156108ad57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600080604083850312156108e057600080fd5b50508035926020909101359150565b6000815160005b8181101561091057602081850181015186830152016108f6565b8181111561091f576000828601525b509290920192915050565b60006107c882846108ef565b60006020828403121561094857600080fd5b5051919050565b7fffffffffffffffffffffffffff00000000000000000000000000000000000000831681526000610983600d8301846108ef565b94935050505056fea2646970667358221220aea34fd8cdcf3a9cced029d5f7b1e628f42ad1514501878e0040df2afddb6e7164736f6c63430008090033", - "deployedBytecode": "0x60806040526004361061005a5760003560e01c8063893d20e811610043578063893d20e8146100a45780639b0b0fda146100e2578063aaf10f42146101025761005a565b806313af4035146100645780636c5d4ad014610084575b610062610117565b005b34801561007057600080fd5b5061006261007f366004610792565b6103ba565b34801561009057600080fd5b5061006261009f3660046107fe565b61044b565b3480156100b057600080fd5b506100b9610601565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ee57600080fd5b506100626100fd3660046108cd565b610698565b34801561010e57600080fd5b506100b9610706565b60006101417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb7947262000000000000000000000000000000000000000000000000000000001790529051919250600091829173ffffffffffffffffffffffffffffffffffffffff8516916101c3919061092a565b600060405180830381855afa9150503d80600081146101fe576040519150601f19603f3d011682016040523d82523d6000602084013e610203565b606091505b5091509150818015610216575080516020145b156102c8576000818060200190518101906102319190610936565b905080156102c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c314368756753706c61736850726f78793a2073797374656d2069732063757260448201527f72656e746c79206265696e67207570677261646564000000000000000000000060648201526084015b60405180910390fd5b505b60006102f27f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610397576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4c314368756753706c61736850726f78793a20696d706c656d656e746174696f60448201527f6e206973206e6f7420736574207965740000000000000000000000000000000060648201526084016102bd565b3660008037600080366000845af43d6000803e806103b4573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610413575033155b1561044357610440817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b50565b610440610117565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104a4575033155b156104435760006104d37f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050803f8251602084012014156104e8575050565b60405160009061051e907f600d380380600d6000396000f30000000000000000000000000000000000000090859060200161094f565b604051602081830303815290604052905060008151602083016000f084516020860120909150813f146105d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f4c314368756753706c61736850726f78793a20636f646520776173206e6f742060448201527f636f72726563746c79206465706c6f7965642e0000000000000000000000000060648201526084016102bd565b6105fb817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b50505050565b600061062b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610662575033155b1561068d57507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b610695610117565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806106f1575033155b156106fa579055565b610702610117565b5050565b60006107307fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610767575033155b1561068d57507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000602082840312156107a457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146107c857600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561081057600080fd5b813567ffffffffffffffff8082111561082857600080fd5b818401915084601f83011261083c57600080fd5b81358181111561084e5761084e6107cf565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610894576108946107cf565b816040528281528760208487010111156108ad57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600080604083850312156108e057600080fd5b50508035926020909101359150565b6000815160005b8181101561091057602081850181015186830152016108f6565b8181111561091f576000828601525b509290920192915050565b60006107c882846108ef565b60006020828403121561094857600080fd5b5051919050565b7fffffffffffffffffffffffffff00000000000000000000000000000000000000831681526000610983600d8301846108ef565b94935050505056fea2646970667358221220aea34fd8cdcf3a9cced029d5f7b1e628f42ad1514501878e0040df2afddb6e7164736f6c63430008090033", - "devdoc": { - "details": "Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added functions `setCode` and `setStorage` for changing the code or storage of the contract. Nifty! Note for future developers: do NOT make anything in this contract 'public' unless you know what you're doing. Anything public can potentially have a function signature that conflicts with a signature attached to the implementation contract. Public functions SHOULD always have the 'proxyCallIfNotOwner' modifier unless there's some *really* good reason not to have that modifier. And there almost certainly is not a good reason to not have that modifier. Beware!", - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_owner": "Address of the initial contract owner." - } - }, - "getImplementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "getOwner()": { - "returns": { - "_0": "Owner address." - } - }, - "setCode(bytes)": { - "params": { - "_code": "New contract code to run inside this contract." - } - }, - "setOwner(address)": { - "params": { - "_owner": "New owner of the proxy contract." - } - }, - "setStorage(bytes32,bytes32)": { - "params": { - "_key": "Storage key to modify.", - "_value": "New value for the storage key." - } - } - }, - "title": "L1ChugSplashProxy", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "getImplementation()": { - "notice": "Queries the implementation address. Can only be called by the owner OR by making an eth_call and setting the \"from\" address to address(0)." - }, - "getOwner()": { - "notice": "Queries the owner of the proxy contract. Can only be called by the owner OR by making an eth_call and setting the \"from\" address to address(0)." - }, - "setCode(bytes)": { - "notice": "Sets the code that should be running behind this proxy. Note that this scheme is a bit different from the standard proxy scheme where one would typically deploy the code separately and then set the implementation address. We're doing it this way because it gives us a lot more freedom on the client side. Can only be triggered by the contract owner." - }, - "setOwner(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "setStorage(bytes32,bytes32)": { - "notice": "Modifies some storage slot within the proxy contract. Gives us a lot of power to perform upgrades in a more transparent way. Only callable by the owner." - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/L2OutputOracle.json b/packages/contracts-bedrock/deployments/goerli/L2OutputOracle.json deleted file mode 100644 index ae7d019c5d08..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/L2OutputOracle.json +++ /dev/null @@ -1,817 +0,0 @@ -{ - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_submissionInterval", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_l2BlockTime", - "type": "uint256" - }, - { - "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": "bytes32", - "name": "outputRoot", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "l2OutputIndex", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "l2BlockNumber", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "l1Timestamp", - "type": "uint256" - } - ], - "name": "OutputProposed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "prevNextOutputIndex", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "newNextOutputIndex", - "type": "uint256" - } - ], - "name": "OutputsDeleted", - "type": "event" - }, - { - "inputs": [], - "name": "CHALLENGER", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "FINALIZATION_PERIOD_SECONDS", - "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": "PROPOSER", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SUBMISSION_INTERVAL", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "challenger", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2BlockNumber", - "type": "uint256" - } - ], - "name": "computeL2Timestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2OutputIndex", - "type": "uint256" - } - ], - "name": "deleteL2Outputs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "finalizationPeriodSeconds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2OutputIndex", - "type": "uint256" - } - ], - "name": "getL2Output", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "outputRoot", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "timestamp", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "l2BlockNumber", - "type": "uint128" - } - ], - "internalType": "struct Types.OutputProposal", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2BlockNumber", - "type": "uint256" - } - ], - "name": "getL2OutputAfter", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "outputRoot", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "timestamp", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "l2BlockNumber", - "type": "uint128" - } - ], - "internalType": "struct Types.OutputProposal", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2BlockNumber", - "type": "uint256" - } - ], - "name": "getL2OutputIndexAfter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_startingBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_startingTimestamp", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_proposer", - "type": "address" - }, - { - "internalType": "address", - "name": "_challenger", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l2BlockTime", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestBlockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestOutputIndex", - "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": "nextOutputIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "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": "startingBlockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "startingTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "submissionInterval", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "address": "0xdb515F91fAA93d894586bA45FEe58d511FDAEC32", - "args": [], - "bytecode": "0x60e06040523480156200001157600080fd5b50604051620018ae380380620018ae8339810160408190526200003491620002f3565b60008211620000b05760405162461bcd60e51b815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e203000000000000000000000000060648201526084015b60405180910390fd5b60008311620001285760405162461bcd60e51b815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e20300000000000006064820152608401620000a7565b608083905260a082905260c08190526200014660008080806200014f565b50505062000322565b600054600390610100900460ff1615801562000172575060005460ff8083169116105b620001d75760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000a7565b6000805461ffff191660ff83161761010017905542841115620002715760405162461bcd60e51b8152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201526374696d6560e01b608482015260a401620000a7565b60028490556001859055600580546001600160a01b038581166001600160a01b03199283161790925560048054928516929091169190911790556000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6000806000606084860312156200030957600080fd5b8351925060208401519150604084015190509250925092565b60805160a05160c0516115326200037c600039600081816104b3015281816105710152610beb0152600081816101a1015281816103b9015261127401526000818161021f0152818161053b01526112c201526115326000f3fe60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec334814610517578063e1a41bcf1461052c578063f4daa2911461055f57600080fd5b8063ce5db8d6146104a4578063cf8e5cf0146104d7578063d1de856c146104f757600080fd5b8063a25ae557116100b0578063a25ae557146103f0578063a8e4fb901461044c578063bffa7f0f1461047957600080fd5b806389c44cbb1461038a57806393991af3146103aa5780639aaab648146103dd57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa51461033e5780637f00642014610354578063887862721461037457600080fd5b806369f16eec146102e95780636abcf563146102fe5780636b4d98dd1461031357600080fd5b8063529933df11610169578063529933df1461020d578063534db0e21461024157806354fd4d501461029357600080fd5b80622134cc1461018f578063019e2729146101d65780634599c788146101f8575b600080fd5b34801561019b57600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b3480156101e257600080fd5b506101f66101f136600461131c565b610593565b005b34801561020457600080fd5b506101c36107f2565b34801561021957600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b34801561024d57600080fd5b5060045461026e9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101cd565b34801561029f57600080fd5b506102dc6040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101cd9190611362565b3480156102f557600080fd5b506101c3610865565b34801561030a57600080fd5b506003546101c3565b34801561031f57600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff1661026e565b34801561034a57600080fd5b506101c360015481565b34801561036057600080fd5b506101c361036f3660046113d5565b610877565b34801561038057600080fd5b506101c360025481565b34801561039657600080fd5b506101f66103a53660046113d5565b610a8b565b3480156103b657600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b6101f66103eb3660046113ee565b610d43565b3480156103fc57600080fd5b5061041061040b3660046113d5565b6111a4565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101cd565b34801561045857600080fd5b5060055461026e9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561048557600080fd5b5060055473ffffffffffffffffffffffffffffffffffffffff1661026e565b3480156104b057600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b3480156104e357600080fd5b506104106104f23660046113d5565b611238565b34801561050357600080fd5b506101c36105123660046113d5565b611270565b34801561052357600080fd5b506101c36112be565b34801561053857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b34801561056b57600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b600054600390610100900460ff161580156105b5575060005460ff8083169116105b610646576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff8316176101001790554284111561072e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161063d565b600284905560018590556005805473ffffffffffffffffffffffffffffffffffffffff8581167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556004805492851692909116919091179055600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6003546000901561085c576003805461080d9060019061144f565b8154811061081d5761081d611466565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b6003546000906108609060019061144f565b60006108816107f2565b821115610936576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161063d565b6003546109eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161063d565b6003546000905b80821015610a845760006002610a088385611495565b610a1291906114ad565b90508460038281548110610a2857610a28611466565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610a7a57610a73816001611495565b9250610a7e565b8091505b506109f2565b5092915050565b60045473ffffffffffffffffffffffffffffffffffffffff163314610b32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161063d565b6003548110610be9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161063d565b7f000000000000000000000000000000000000000000000000000000000000000060038281548110610c1d57610c1d611466565b6000918252602090912060016002909202010154610c4d906fffffffffffffffffffffffffffffffff164261144f565b10610d00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161063d565b6000610d0b60035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60055473ffffffffffffffffffffffffffffffffffffffff163314610e10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161063d565b610e186112be565b8314610ecc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161063d565b42610ed684611270565b10610f63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161063d565b83610ff0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161063d565b81156110ac57818140146110ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161063d565b826110b660035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e2426040516110e891815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b6040805160608101825260008082526020820181905291810191909152600382815481106111d4576111d4611466565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b6040805160608101825260008082526020820181905291810191909152600361126083610877565b815481106111d4576111d4611466565b60007f0000000000000000000000000000000000000000000000000000000000000000600154836112a1919061144f565b6112ab91906114e8565b6002546112b89190611495565b92915050565b60007f00000000000000000000000000000000000000000000000000000000000000006112e96107f2565b6108609190611495565b803573ffffffffffffffffffffffffffffffffffffffff8116811461131757600080fd5b919050565b6000806000806080858703121561133257600080fd5b8435935060208501359250611349604086016112f3565b9150611357606086016112f3565b905092959194509250565b600060208083528351808285015260005b8181101561138f57858101830151858201604001528201611373565b818111156113a1576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000602082840312156113e757600080fd5b5035919050565b6000806000806080858703121561140457600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561146157611461611420565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156114a8576114a8611420565b500190565b6000826114e3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561152057611520611420565b50029056fea164736f6c634300080f000a", - "deployedBytecode": "0x60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec334814610517578063e1a41bcf1461052c578063f4daa2911461055f57600080fd5b8063ce5db8d6146104a4578063cf8e5cf0146104d7578063d1de856c146104f757600080fd5b8063a25ae557116100b0578063a25ae557146103f0578063a8e4fb901461044c578063bffa7f0f1461047957600080fd5b806389c44cbb1461038a57806393991af3146103aa5780639aaab648146103dd57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa51461033e5780637f00642014610354578063887862721461037457600080fd5b806369f16eec146102e95780636abcf563146102fe5780636b4d98dd1461031357600080fd5b8063529933df11610169578063529933df1461020d578063534db0e21461024157806354fd4d501461029357600080fd5b80622134cc1461018f578063019e2729146101d65780634599c788146101f8575b600080fd5b34801561019b57600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b3480156101e257600080fd5b506101f66101f136600461131c565b610593565b005b34801561020457600080fd5b506101c36107f2565b34801561021957600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b34801561024d57600080fd5b5060045461026e9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101cd565b34801561029f57600080fd5b506102dc6040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101cd9190611362565b3480156102f557600080fd5b506101c3610865565b34801561030a57600080fd5b506003546101c3565b34801561031f57600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff1661026e565b34801561034a57600080fd5b506101c360015481565b34801561036057600080fd5b506101c361036f3660046113d5565b610877565b34801561038057600080fd5b506101c360025481565b34801561039657600080fd5b506101f66103a53660046113d5565b610a8b565b3480156103b657600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b6101f66103eb3660046113ee565b610d43565b3480156103fc57600080fd5b5061041061040b3660046113d5565b6111a4565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101cd565b34801561045857600080fd5b5060055461026e9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561048557600080fd5b5060055473ffffffffffffffffffffffffffffffffffffffff1661026e565b3480156104b057600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b3480156104e357600080fd5b506104106104f23660046113d5565b611238565b34801561050357600080fd5b506101c36105123660046113d5565b611270565b34801561052357600080fd5b506101c36112be565b34801561053857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b34801561056b57600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b600054600390610100900460ff161580156105b5575060005460ff8083169116105b610646576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff8316176101001790554284111561072e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161063d565b600284905560018590556005805473ffffffffffffffffffffffffffffffffffffffff8581167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556004805492851692909116919091179055600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6003546000901561085c576003805461080d9060019061144f565b8154811061081d5761081d611466565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b6003546000906108609060019061144f565b60006108816107f2565b821115610936576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161063d565b6003546109eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161063d565b6003546000905b80821015610a845760006002610a088385611495565b610a1291906114ad565b90508460038281548110610a2857610a28611466565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610a7a57610a73816001611495565b9250610a7e565b8091505b506109f2565b5092915050565b60045473ffffffffffffffffffffffffffffffffffffffff163314610b32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161063d565b6003548110610be9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161063d565b7f000000000000000000000000000000000000000000000000000000000000000060038281548110610c1d57610c1d611466565b6000918252602090912060016002909202010154610c4d906fffffffffffffffffffffffffffffffff164261144f565b10610d00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161063d565b6000610d0b60035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60055473ffffffffffffffffffffffffffffffffffffffff163314610e10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161063d565b610e186112be565b8314610ecc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161063d565b42610ed684611270565b10610f63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161063d565b83610ff0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161063d565b81156110ac57818140146110ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161063d565b826110b660035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e2426040516110e891815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b6040805160608101825260008082526020820181905291810191909152600382815481106111d4576111d4611466565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b6040805160608101825260008082526020820181905291810191909152600361126083610877565b815481106111d4576111d4611466565b60007f0000000000000000000000000000000000000000000000000000000000000000600154836112a1919061144f565b6112ab91906114e8565b6002546112b89190611495565b92915050565b60007f00000000000000000000000000000000000000000000000000000000000000006112e96107f2565b6108609190611495565b803573ffffffffffffffffffffffffffffffffffffffff8116811461131757600080fd5b919050565b6000806000806080858703121561133257600080fd5b8435935060208501359250611349604086016112f3565b9150611357606086016112f3565b905092959194509250565b600060208083528351808285015260005b8181101561138f57858101830151858201604001528201611373565b818111156113a1576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000602082840312156113e757600080fd5b5035919050565b6000806000806080858703121561140457600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561146157611461611420565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156114a8576114a8611420565b500190565b6000826114e3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561152057611520611420565b50029056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "CHALLENGER()": {}, - "PROPOSER()": {}, - "computeL2Timestamp(uint256)": { - "params": { - "_l2BlockNumber": "The L2 block number of the target block." - }, - "returns": { - "_0": "L2 timestamp of the given block." - } - }, - "constructor": { - "params": { - "_finalizationPeriodSeconds": "The amount of time that must pass for an output proposal", - "_l2BlockTime": "The time per L2 block, in seconds.", - "_submissionInterval": "Interval in blocks at which checkpoints must be submitted." - } - }, - "deleteL2Outputs(uint256)": { - "params": { - "_l2OutputIndex": "Index of the first L2 output to be deleted. All outputs after this output will also be deleted." - } - }, - "getL2Output(uint256)": { - "params": { - "_l2OutputIndex": "Index of the output to return." - }, - "returns": { - "_0": "The output at the given index." - } - }, - "getL2OutputAfter(uint256)": { - "params": { - "_l2BlockNumber": "L2 block number to find a checkpoint for." - }, - "returns": { - "_0": "First checkpoint that commits to the given L2 block number." - } - }, - "getL2OutputIndexAfter(uint256)": { - "params": { - "_l2BlockNumber": "L2 block number to find a checkpoint for." - }, - "returns": { - "_0": "Index of the first checkpoint that commits to the given L2 block number." - } - }, - "initialize(uint256,uint256,address,address)": { - "params": { - "_challenger": "The address of the challenger.", - "_proposer": "The address of the proposer.", - "_startingBlockNumber": "Block number for the first recoded L2 block.", - "_startingTimestamp": "Timestamp for the first recoded L2 block." - } - }, - "latestBlockNumber()": { - "returns": { - "_0": "Latest submitted L2 block number." - } - }, - "latestOutputIndex()": { - "returns": { - "_0": "The number of outputs that have been proposed." - } - }, - "nextBlockNumber()": { - "returns": { - "_0": "Next L2 block number." - } - }, - "nextOutputIndex()": { - "returns": { - "_0": "The index of the next output to be proposed." - } - }, - "proposeL2Output(bytes32,uint256,bytes32,uint256)": { - "params": { - "_l1BlockHash": "A block hash which must be included in the current chain.", - "_l1BlockNumber": "The block number with the specified block hash.", - "_l2BlockNumber": "The L2 block number that resulted in _outputRoot.", - "_outputRoot": "The L2 output of the checkpoint block." - } - } - }, - "events": { - "OutputProposed(bytes32,uint256,uint256,uint256)": { - "params": { - "l1Timestamp": "The L1 timestamp when proposed.", - "l2BlockNumber": "The L2 block number of the output root.", - "l2OutputIndex": "The index of the output in the l2Outputs array.", - "outputRoot": "The output root." - } - }, - "OutputsDeleted(uint256,uint256)": { - "params": { - "newNextOutputIndex": "Next L2 output index after the deletion.", - "prevNextOutputIndex": "Next L2 output index before the deletion." - } - } - } - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriodSeconds\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"l2OutputIndex\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"l2BlockNumber\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"l1Timestamp\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"OutputProposed\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prevNextOutputIndex\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"newNextOutputIndex\",\"type\":\"uint256\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OutputsDeleted\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"CHALLENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"FINALIZATION_PERIOD_SECONDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"PROPOSER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"challenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"computeL2Timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"deleteL2Outputs\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"finalizationPeriodSeconds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"struct Types.OutputProposal\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"}]}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getL2OutputAfter\",\"outputs\":[{\"internalType\":\"struct Types.OutputProposal\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"}]}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getL2OutputIndexAfter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_startingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_proposer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_challenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2BlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"latestBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"latestOutputIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"nextBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"nextOutputIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1BlockHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"proposeL2Output\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"proposer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"startingBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"startingTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"submissionInterval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"CHALLENGER()\":{\"custom:legacy\":\"\"},\"PROPOSER()\":{\"custom:legacy\":\"\"},\"computeL2Timestamp(uint256)\":{\"params\":{\"_l2BlockNumber\":\"The L2 block number of the target block.\"},\"returns\":{\"_0\":\"L2 timestamp of the given block.\"}},\"constructor\":{\"params\":{\"_finalizationPeriodSeconds\":\"The amount of time that must pass for an output proposal\",\"_l2BlockTime\":\"The time per L2 block, in seconds.\",\"_submissionInterval\":\"Interval in blocks at which checkpoints must be submitted.\"}},\"deleteL2Outputs(uint256)\":{\"params\":{\"_l2OutputIndex\":\"Index of the first L2 output to be deleted. All outputs after this output will also be deleted.\"}},\"getL2Output(uint256)\":{\"params\":{\"_l2OutputIndex\":\"Index of the output to return.\"},\"returns\":{\"_0\":\"The output at the given index.\"}},\"getL2OutputAfter(uint256)\":{\"params\":{\"_l2BlockNumber\":\"L2 block number to find a checkpoint for.\"},\"returns\":{\"_0\":\"First checkpoint that commits to the given L2 block number.\"}},\"getL2OutputIndexAfter(uint256)\":{\"params\":{\"_l2BlockNumber\":\"L2 block number to find a checkpoint for.\"},\"returns\":{\"_0\":\"Index of the first checkpoint that commits to the given L2 block number.\"}},\"initialize(uint256,uint256,address,address)\":{\"params\":{\"_challenger\":\"The address of the challenger.\",\"_proposer\":\"The address of the proposer.\",\"_startingBlockNumber\":\"Block number for the first recoded L2 block.\",\"_startingTimestamp\":\"Timestamp for the first recoded L2 block.\"}},\"latestBlockNumber()\":{\"returns\":{\"_0\":\"Latest submitted L2 block number.\"}},\"latestOutputIndex()\":{\"returns\":{\"_0\":\"The number of outputs that have been proposed.\"}},\"nextBlockNumber()\":{\"returns\":{\"_0\":\"Next L2 block number.\"}},\"nextOutputIndex()\":{\"returns\":{\"_0\":\"The index of the next output to be proposed.\"}},\"proposeL2Output(bytes32,uint256,bytes32,uint256)\":{\"params\":{\"_l1BlockHash\":\"A block hash which must be included in the current chain.\",\"_l1BlockNumber\":\"The block number with the specified block hash.\",\"_l2BlockNumber\":\"The L2 block number that resulted in _outputRoot.\",\"_outputRoot\":\"The L2 output of the checkpoint block.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"CHALLENGER()\":{\"notice\":\"Getter for the challenger address. This will be removed in the future, use `challenger` instead.\"},\"L2_BLOCK_TIME()\":{\"notice\":\"The time between L2 blocks in seconds. Once set, this value MUST NOT be modified. Public getter is legacy and will be removed in the future. Use `l2BlockTime` instead.\"},\"PROPOSER()\":{\"notice\":\"Getter for the proposer address. This will be removed in the future, use `proposer` instead.\"},\"SUBMISSION_INTERVAL()\":{\"notice\":\"The interval in L2 blocks at which checkpoints must be submitted. Although this is immutable, it can safely be modified by upgrading the implementation contract. Public getter is legacy and will be removed in the future. Use `submissionInterval` instead.\"},\"challenger()\":{\"notice\":\"The address of the challenger. Can be updated via reinitialize.\"},\"computeL2Timestamp(uint256)\":{\"notice\":\"Returns the L2 timestamp corresponding to a given L2 block number.\"},\"constructor\":{\"notice\":\"Constructs the L2OutputOracle contract.\"},\"deleteL2Outputs(uint256)\":{\"notice\":\"Deletes all output proposals after and including the proposal that corresponds to the given output index. Only the challenger address can delete outputs.\"},\"finalizationPeriodSeconds()\":{\"notice\":\"Getter for the finalization period.\"},\"getL2Output(uint256)\":{\"notice\":\"Returns an output by index. Needed to return a struct instead of a tuple.\"},\"getL2OutputAfter(uint256)\":{\"notice\":\"Returns the L2 output proposal that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block.\"},\"getL2OutputIndexAfter(uint256)\":{\"notice\":\"Returns the index of the L2 output that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block.\"},\"initialize(uint256,uint256,address,address)\":{\"notice\":\"Initializer.\"},\"l2BlockTime()\":{\"notice\":\"Getter for the L2 block time.\"},\"latestBlockNumber()\":{\"notice\":\"Returns the block number of the latest submitted L2 output proposal. If no proposals been submitted yet then this function will return the starting block number.\"},\"latestOutputIndex()\":{\"notice\":\"Returns the number of outputs that have been proposed. Will revert if no outputs have been proposed yet.\"},\"nextBlockNumber()\":{\"notice\":\"Computes the block number of the next L2 block that needs to be checkpointed.\"},\"nextOutputIndex()\":{\"notice\":\"Returns the index of the next output to be proposed.\"},\"proposeL2Output(bytes32,uint256,bytes32,uint256)\":{\"notice\":\"Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp must be equal to the current value returned by `nextTimestamp()` in order to be accepted. This function may only be called by the Proposer.\"},\"proposer()\":{\"notice\":\"The address of the proposer. Can be updated via reinitialize.\"},\"startingBlockNumber()\":{\"notice\":\"The number of the first L2 block recorded in this contract.\"},\"startingTimestamp()\":{\"notice\":\"The timestamp of the first L2 block recorded in this contract.\"},\"submissionInterval()\":{\"notice\":\"Getter for the output proposal submission interval.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L2OutputOracle.sol\":\"L2OutputOracle\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L2OutputOracle.sol\":{\"keccak256\":\"0x60042eb3e619518cab9a8f2480b62871c2d813716e2e60d9a5e0c5f271c58705\",\"urls\":[\"bzz-raw://08538ef2aa99c508b56a8bb9b3c7b93476cba9dbf0b47783141e5e50a02156cc\",\"dweb:/ipfs/QmdvFZ1fUaTkNdmtB66rNAo73RxY7kccsgR6Uqz7psoXGN\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 4, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 32100, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 32103, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 59681, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "startingBlockNumber", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 59684, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "startingTimestamp", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 59689, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "l2Outputs", - "offset": 0, - "slot": "3", - "type": "t_array(t_struct(OutputProposal)71419_storage)dyn_storage" - }, - { - "astId": 59692, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "challenger", - "offset": 0, - "slot": "4", - "type": "t_address" - }, - { - "astId": 59695, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "proposer", - "offset": 0, - "slot": "5", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_struct(OutputProposal)71419_storage)dyn_storage": { - "encoding": "dynamic_array", - "label": "struct Types.OutputProposal[]", - "numberOfBytes": "32", - "base": "t_struct(OutputProposal)71419_storage" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_struct(OutputProposal)71419_storage": { - "encoding": "inplace", - "label": "struct Types.OutputProposal", - "numberOfBytes": "64", - "members": [ - { - "astId": 71414, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "outputRoot", - "offset": 0, - "slot": "0", - "type": "t_bytes32" - }, - { - "astId": 71416, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "timestamp", - "offset": 0, - "slot": "1", - "type": "t_uint128" - }, - { - "astId": 71418, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "l2BlockNumber", - "offset": 16, - "slot": "1", - "type": "t_uint128" - } - ] - }, - "t_uint128": { - "encoding": "inplace", - "label": "uint128", - "numberOfBytes": "16" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x04967474706b357893b9dfdfd8e8ab8d4a2cb3c4e8561d76b5149f4c5e92ad0a", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "CHALLENGER()": { - "notice": "Getter for the challenger address. This will be removed in the future, use `challenger` instead." - }, - "L2_BLOCK_TIME()": { - "notice": "The time between L2 blocks in seconds. Once set, this value MUST NOT be modified. Public getter is legacy and will be removed in the future. Use `l2BlockTime` instead." - }, - "PROPOSER()": { - "notice": "Getter for the proposer address. This will be removed in the future, use `proposer` instead." - }, - "SUBMISSION_INTERVAL()": { - "notice": "The interval in L2 blocks at which checkpoints must be submitted. Although this is immutable, it can safely be modified by upgrading the implementation contract. Public getter is legacy and will be removed in the future. Use `submissionInterval` instead." - }, - "challenger()": { - "notice": "The address of the challenger. Can be updated via reinitialize." - }, - "computeL2Timestamp(uint256)": { - "notice": "Returns the L2 timestamp corresponding to a given L2 block number." - }, - "constructor": { - "notice": "Constructs the L2OutputOracle contract." - }, - "deleteL2Outputs(uint256)": { - "notice": "Deletes all output proposals after and including the proposal that corresponds to the given output index. Only the challenger address can delete outputs." - }, - "finalizationPeriodSeconds()": { - "notice": "Getter for the finalization period." - }, - "getL2Output(uint256)": { - "notice": "Returns an output by index. Needed to return a struct instead of a tuple." - }, - "getL2OutputAfter(uint256)": { - "notice": "Returns the L2 output proposal that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block." - }, - "getL2OutputIndexAfter(uint256)": { - "notice": "Returns the index of the L2 output that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block." - }, - "initialize(uint256,uint256,address,address)": { - "notice": "Initializer." - }, - "l2BlockTime()": { - "notice": "Getter for the L2 block time." - }, - "latestBlockNumber()": { - "notice": "Returns the block number of the latest submitted L2 output proposal. If no proposals been submitted yet then this function will return the starting block number." - }, - "latestOutputIndex()": { - "notice": "Returns the number of outputs that have been proposed. Will revert if no outputs have been proposed yet." - }, - "nextBlockNumber()": { - "notice": "Computes the block number of the next L2 block that needs to be checkpointed." - }, - "nextOutputIndex()": { - "notice": "Returns the index of the next output to be proposed." - }, - "proposeL2Output(bytes32,uint256,bytes32,uint256)": { - "notice": "Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp must be equal to the current value returned by `nextTimestamp()` in order to be accepted. This function may only be called by the Proposer." - }, - "proposer()": { - "notice": "The address of the proposer. Can be updated via reinitialize." - }, - "startingBlockNumber()": { - "notice": "The number of the first L2 block recorded in this contract." - }, - "startingTimestamp()": { - "notice": "The timestamp of the first L2 block recorded in this contract." - }, - "submissionInterval()": { - "notice": "Getter for the output proposal submission interval." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "OutputProposed(bytes32,uint256,uint256,uint256)": { - "notice": "Emitted when an output is proposed." - }, - "OutputsDeleted(uint256,uint256)": { - "notice": "Emitted when outputs are deleted." - } - }, - "notice": "The L2OutputOracle contains an array of L2 state outputs, where each output is a commitment to the state of the L2 chain. Other contracts like the OptimismPortal use these outputs to verify information about the state of L2." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/L2OutputOracleProxy.json b/packages/contracts-bedrock/deployments/goerli/L2OutputOracleProxy.json deleted file mode 100644 index dc44266faa39..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/L2OutputOracleProxy.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "address": "0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0", - "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": "0x20ddfee1cf52769675d3921f016b9ca4f2cc6d6b107dcf6f3ed1b452f985c2db", - "receipt": { - "to": null, - "from": "0x956a5152D0f498dBA0c5966577bb44262F8F7078", - "contractAddress": "0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0", - "transactionIndex": 13, - "gasUsed": "523800", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000010000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000800000000000000000000000000000000000000000000000100000000000000000", - "blockHash": "0xb88a44a833cf2fea693fa468365ef085d8a755757db02a9d0a09e2b507fb00bc", - "transactionHash": "0x20ddfee1cf52769675d3921f016b9ca4f2cc6d6b107dcf6f3ed1b452f985c2db", - "logs": [ - { - "transactionIndex": 13, - "blockNumber": 8299683, - "transactionHash": "0x20ddfee1cf52769675d3921f016b9ca4f2cc6d6b107dcf6f3ed1b452f985c2db", - "address": "0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d3670863c3f4b24d7b107900f0b75d4bbc6e0d", - "logIndex": 22, - "blockHash": "0xb88a44a833cf2fea693fa468365ef085d8a755757db02a9d0a09e2b507fb00bc" - } - ], - "blockNumber": 8299683, - "cumulativeGasUsed": "1695349", - "status": 1, - "byzantium": true - }, - "args": [ - "0x01d3670863c3F4b24D7b107900f0b75d4BbC6e0d" - ], - "numDeployments": 1, - "solcInputHash": "672fbec9734a08fc34112408d6dc7f7b", - "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\":{\"contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0xfa08635f1866139673ac4fe7b07330f752f93800075b895d8fcb8484f4a3f753\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8f2247604d527f560edbb851c43b6c16b37e34972ddb305e16dd73623b8288cd\",\"dweb:/ipfs/QmfM8sLAZrxrnqyRdt1XJ5LyJh4wKbeEqk3VkvxG7BDqFj\"]}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "admin()": { - "returns": { - "_0": "Owner address." - } - }, - "changeAdmin(address)": { - "params": { - "_admin": "New owner of the proxy contract." - } - }, - "constructor": { - "params": { - "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "Address of the implementation contract." - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "Calldata to delegatecall the new implementation with.", - "_implementation": "Address of the implementation contract." - } - } - }, - "events": { - "AdminChanged(address,address)": { - "params": { - "newAdmin": "The new owner of the contract", - "previousAdmin": "The previous owner of the contract" - } - }, - "Upgraded(address)": { - "params": { - "implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "admin()": { - "notice": "Gets the owner of the proxy contract." - }, - "changeAdmin(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "constructor": { - "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." - }, - "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." - } - }, - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." - } - }, - "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/OptimismMintableERC20Factory.json b/packages/contracts-bedrock/deployments/goerli/OptimismMintableERC20Factory.json deleted file mode 100644 index e7d2e45f747e..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/OptimismMintableERC20Factory.json +++ /dev/null @@ -1,356 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "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": "localToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "deployer", - "type": "address" - } - ], - "name": "OptimismMintableERC20Created", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "localToken", - "type": "address" - } - ], - "name": "StandardL2TokenCreated", - "type": "event" - }, - { - "inputs": [], - "name": "BRIDGE", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "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": "createOptimismMintableERC20", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_remoteToken", - "type": "address" - }, - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - }, - { - "internalType": "uint8", - "name": "_decimals", - "type": "uint8" - } - ], - "name": "createOptimismMintableERC20WithDecimals", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_remoteToken", - "type": "address" - }, - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - } - ], - "name": "createStandardL2Token", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_bridge", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "address": "0x373B66bd178cb2716D5A9596B1a42Ed39b87A535", - "args": [], - "bytecode": "0x608060405234801561001057600080fd5b5061001b6000610020565b610118565b600054600390610100900460ff16158015610042575060005460ff8083169116105b6100a95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805461010060ff841661ffff19909216821717610100600160b01b03191661ff0019620100006001600160a01b0387160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6123cf806101276000396000f3fe60806040523480156200001157600080fd5b5060043610620000875760003560e01c8063c4d66de81162000062578063c4d66de81462000135578063ce5ac90f146200014e578063e78cea921462000165578063ee9a31a2146200018c57600080fd5b806354fd4d50146200008c578063896f93d114620000e15780638cf0629c146200011e575b600080fd5b620000c96040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b604051620000d89190620005d1565b60405180910390f35b620000f8620000f2366004620006f9565b620001b1565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620000f86200012f36600462000776565b620001c8565b6200014c620001463660046200080d565b620003c6565b005b620000f86200015f366004620006f9565b62000544565b600054620000f89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000f8565b6000620001c084848462000544565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b6000858585856040516020016200028e94939291906200082b565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688888888604051620002de9062000555565b620002ee95949392919062000885565b8190604051809103906000f59050801580156200030f573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054600390610100900460ff16158015620003e9575060005460ff8083169116105b62000477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200026a565b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000620001c08484846012620001c8565b611ad880620008eb83390190565b6000815180845260005b818110156200058b576020818501810151868301820152016200056d565b818111156200059e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005e6602083018462000563565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061257600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200065857600080fd5b813567ffffffffffffffff8082111562000676576200067662000617565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006bf57620006bf62000617565b81604052838152866020858801011115620006d957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200070f57600080fd5b6200071a84620005ed565b9250602084013567ffffffffffffffff808211156200073857600080fd5b620007468783880162000646565b935060408601359150808211156200075d57600080fd5b506200076c8682870162000646565b9150509250925092565b600080600080608085870312156200078d57600080fd5b6200079885620005ed565b9350602085013567ffffffffffffffff80821115620007b657600080fd5b620007c48883890162000646565b94506040870135915080821115620007db57600080fd5b50620007ea8782880162000646565b925050606085013560ff811681146200080257600080fd5b939692955090935050565b6000602082840312156200082057600080fd5b620005e682620005ed565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200085c608083018662000563565b828103604084015262000870818662000563565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620008c060a083018662000563565b8281036060840152620008d4818662000563565b91505060ff83166080830152969550505050505056fe6101406040523480156200001257600080fd5b5060405162001ad838038062001ad8833981016040819052620000359162000178565b600160026000858560036200004b8382620002b3565b5060046200005a8282620002b3565b50505060809290925260a05260c0526001600160a01b0393841660e0529390921661010052505060ff16610120526200037f565b80516001600160a01b0381168114620000a657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000d357600080fd5b81516001600160401b0380821115620000f057620000f0620000ab565b604051601f8301601f19908116603f011681019082821181831017156200011b576200011b620000ab565b816040528381526020925086838588010111156200013857600080fd5b600091505b838210156200015c57858201830151818301840152908201906200013d565b838211156200016e5760008385830101525b9695505050505050565b600080600080600060a086880312156200019157600080fd5b6200019c866200008e565b9450620001ac602087016200008e565b60408701519094506001600160401b0380821115620001ca57600080fd5b620001d889838a01620000c1565b94506060880151915080821115620001ef57600080fd5b50620001fe88828901620000c1565b925050608086015160ff811681146200021657600080fd5b809150509295509295909350565b600181811c908216806200023957607f821691505b6020821081036200025a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002ae57600081815260208120601f850160051c81016020861015620002895750805b601f850160051c820191505b81811015620002aa5782815560010162000295565b5050505b505050565b81516001600160401b03811115620002cf57620002cf620000ab565b620002e781620002e0845462000224565b8462000260565b602080601f8311600181146200031f5760008415620003065750858301515b600019600386901b1c1916600185901b178555620002aa565b600085815260208120601f198616915b8281101562000350578886015182559484019460019091019084016200032f565b50858210156200036f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161010051610120516116ed620003eb6000396000610244015260008181610317015281816103ac015281816105f101526107cb0152600081816101a9015261033d0152600061075a015260006107310152600061070801526116ed6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610361578063e78cea9214610315578063ee9a31a2146103a757600080fd5b8063ae1f6aaf14610315578063c01e1bd61461033b578063d6c0b2c41461033b57600080fd5b80639dc29fac116100bd5780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb1461030257600080fd5b806370a082311461029e57806395d89b41146102d457600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611329565b6103ce565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104bf565b60405161019b919061139e565b61018f610213366004611418565b610551565b6002545b60405190815260200161019b565b61018f610238366004611442565b610569565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611418565b61058d565b61029461028f366004611418565b6105d9565b005b6101f8610701565b61021c6102ac36600461147e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f86107a4565b6102946102ea366004611418565b6107b3565b61018f6102fd366004611418565b6108ca565b61018f610310366004611418565b61099b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61036f366004611499565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061048757507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104b657507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ce906114cc565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa906114cc565b80156105475780601f1061051c57610100808354040283529160200191610547565b820191906000526020600020905b81548152906001019060200180831161052a57829003601f168201915b5050505050905090565b60003361055f8185856109a9565b5060019392505050565b600033610577858285610b5d565b610582858585610c34565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061055f90829086906105d490879061154e565b6109a9565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106ad8282610ee7565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106f591815260200190565b60405180910390a25050565b606061072c7f0000000000000000000000000000000000000000000000000000000000000000611007565b6107557f0000000000000000000000000000000000000000000000000000000000000000611007565b61077e7f0000000000000000000000000000000000000000000000000000000000000000611007565b60405160200161079093929190611566565b604051602081830303815290604052905090565b6060600480546104ce906114cc565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610878576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161069a565b6108828282611144565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106f591815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561098e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161069a565b61058282868684036109a9565b60003361055f818585610c34565b73ffffffffffffffffffffffffffffffffffffffff8316610a4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610aee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2e5781811015610c21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161069a565b610c2e84848484036109a9565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e7490849061154e565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eda91815260200190565b60405180910390a3610c2e565b73ffffffffffffffffffffffffffffffffffffffff8216610f64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161069a565b8060026000828254610f76919061154e565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610fb090849061154e565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361104a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611074578061105e816115dc565b915061106d9050600a83611643565b915061104e565b60008167ffffffffffffffff81111561108f5761108f611657565b6040519080825280601f01601f1916602001820160405280156110b9576020820181803683370190505b5090505b841561113c576110ce600183611686565b91506110db600a8661169d565b6110e690603061154e565b60f81b8183815181106110fb576110fb6116b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611135600a86611643565b94506110bd565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561129d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112d9908490611686565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b50565b60006020828403121561133b57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461136b57600080fd5b9392505050565b60005b8381101561138d578181015183820152602001611375565b83811115610c2e5750506000910152565b60208152600082518060208401526113bd816040850160208701611372565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461141357600080fd5b919050565b6000806040838503121561142b57600080fd5b611434836113ef565b946020939093013593505050565b60008060006060848603121561145757600080fd5b611460846113ef565b925061146e602085016113ef565b9150604084013590509250925092565b60006020828403121561149057600080fd5b61136b826113ef565b600080604083850312156114ac57600080fd5b6114b5836113ef565b91506114c3602084016113ef565b90509250929050565b600181811c908216806114e057607f821691505b602082108103611519577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115615761156161151f565b500190565b60008451611578818460208901611372565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516115b4816001850160208a01611372565b600192019182015283516115cf816002840160208801611372565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361160d5761160d61151f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165257611652611614565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156116985761169861151f565b500390565b6000826116ac576116ac611614565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a", - "deployedBytecode": "0x60806040523480156200001157600080fd5b5060043610620000875760003560e01c8063c4d66de81162000062578063c4d66de81462000135578063ce5ac90f146200014e578063e78cea921462000165578063ee9a31a2146200018c57600080fd5b806354fd4d50146200008c578063896f93d114620000e15780638cf0629c146200011e575b600080fd5b620000c96040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b604051620000d89190620005d1565b60405180910390f35b620000f8620000f2366004620006f9565b620001b1565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620000f86200012f36600462000776565b620001c8565b6200014c620001463660046200080d565b620003c6565b005b620000f86200015f366004620006f9565b62000544565b600054620000f89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000f8565b6000620001c084848462000544565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b6000858585856040516020016200028e94939291906200082b565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688888888604051620002de9062000555565b620002ee95949392919062000885565b8190604051809103906000f59050801580156200030f573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054600390610100900460ff16158015620003e9575060005460ff8083169116105b62000477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200026a565b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000620001c08484846012620001c8565b611ad880620008eb83390190565b6000815180845260005b818110156200058b576020818501810151868301820152016200056d565b818111156200059e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005e6602083018462000563565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061257600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200065857600080fd5b813567ffffffffffffffff8082111562000676576200067662000617565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006bf57620006bf62000617565b81604052838152866020858801011115620006d957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200070f57600080fd5b6200071a84620005ed565b9250602084013567ffffffffffffffff808211156200073857600080fd5b620007468783880162000646565b935060408601359150808211156200075d57600080fd5b506200076c8682870162000646565b9150509250925092565b600080600080608085870312156200078d57600080fd5b6200079885620005ed565b9350602085013567ffffffffffffffff80821115620007b657600080fd5b620007c48883890162000646565b94506040870135915080821115620007db57600080fd5b50620007ea8782880162000646565b925050606085013560ff811681146200080257600080fd5b939692955090935050565b6000602082840312156200082057600080fd5b620005e682620005ed565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200085c608083018662000563565b828103604084015262000870818662000563565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620008c060a083018662000563565b8281036060840152620008d4818662000563565b91505060ff83166080830152969550505050505056fe6101406040523480156200001257600080fd5b5060405162001ad838038062001ad8833981016040819052620000359162000178565b600160026000858560036200004b8382620002b3565b5060046200005a8282620002b3565b50505060809290925260a05260c0526001600160a01b0393841660e0529390921661010052505060ff16610120526200037f565b80516001600160a01b0381168114620000a657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000d357600080fd5b81516001600160401b0380821115620000f057620000f0620000ab565b604051601f8301601f19908116603f011681019082821181831017156200011b576200011b620000ab565b816040528381526020925086838588010111156200013857600080fd5b600091505b838210156200015c57858201830151818301840152908201906200013d565b838211156200016e5760008385830101525b9695505050505050565b600080600080600060a086880312156200019157600080fd5b6200019c866200008e565b9450620001ac602087016200008e565b60408701519094506001600160401b0380821115620001ca57600080fd5b620001d889838a01620000c1565b94506060880151915080821115620001ef57600080fd5b50620001fe88828901620000c1565b925050608086015160ff811681146200021657600080fd5b809150509295509295909350565b600181811c908216806200023957607f821691505b6020821081036200025a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002ae57600081815260208120601f850160051c81016020861015620002895750805b601f850160051c820191505b81811015620002aa5782815560010162000295565b5050505b505050565b81516001600160401b03811115620002cf57620002cf620000ab565b620002e781620002e0845462000224565b8462000260565b602080601f8311600181146200031f5760008415620003065750858301515b600019600386901b1c1916600185901b178555620002aa565b600085815260208120601f198616915b8281101562000350578886015182559484019460019091019084016200032f565b50858210156200036f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161010051610120516116ed620003eb6000396000610244015260008181610317015281816103ac015281816105f101526107cb0152600081816101a9015261033d0152600061075a015260006107310152600061070801526116ed6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610361578063e78cea9214610315578063ee9a31a2146103a757600080fd5b8063ae1f6aaf14610315578063c01e1bd61461033b578063d6c0b2c41461033b57600080fd5b80639dc29fac116100bd5780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb1461030257600080fd5b806370a082311461029e57806395d89b41146102d457600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611329565b6103ce565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104bf565b60405161019b919061139e565b61018f610213366004611418565b610551565b6002545b60405190815260200161019b565b61018f610238366004611442565b610569565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611418565b61058d565b61029461028f366004611418565b6105d9565b005b6101f8610701565b61021c6102ac36600461147e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f86107a4565b6102946102ea366004611418565b6107b3565b61018f6102fd366004611418565b6108ca565b61018f610310366004611418565b61099b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61036f366004611499565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061048757507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104b657507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ce906114cc565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa906114cc565b80156105475780601f1061051c57610100808354040283529160200191610547565b820191906000526020600020905b81548152906001019060200180831161052a57829003601f168201915b5050505050905090565b60003361055f8185856109a9565b5060019392505050565b600033610577858285610b5d565b610582858585610c34565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061055f90829086906105d490879061154e565b6109a9565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106ad8282610ee7565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106f591815260200190565b60405180910390a25050565b606061072c7f0000000000000000000000000000000000000000000000000000000000000000611007565b6107557f0000000000000000000000000000000000000000000000000000000000000000611007565b61077e7f0000000000000000000000000000000000000000000000000000000000000000611007565b60405160200161079093929190611566565b604051602081830303815290604052905090565b6060600480546104ce906114cc565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610878576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161069a565b6108828282611144565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106f591815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561098e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161069a565b61058282868684036109a9565b60003361055f818585610c34565b73ffffffffffffffffffffffffffffffffffffffff8316610a4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610aee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2e5781811015610c21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161069a565b610c2e84848484036109a9565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e7490849061154e565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eda91815260200190565b60405180910390a3610c2e565b73ffffffffffffffffffffffffffffffffffffffff8216610f64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161069a565b8060026000828254610f76919061154e565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610fb090849061154e565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361104a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611074578061105e816115dc565b915061106d9050600a83611643565b915061104e565b60008167ffffffffffffffff81111561108f5761108f611657565b6040519080825280601f01601f1916602001820160405280156110b9576020820181803683370190505b5090505b841561113c576110ce600183611686565b91506110db600a8661169d565b6110e690603061154e565b60f81b8183815181106110fb576110fb6116b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611135600a86611643565b94506110bd565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561129d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112d9908490611686565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b50565b60006020828403121561133b57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461136b57600080fd5b9392505050565b60005b8381101561138d578181015183820152602001611375565b83811115610c2e5750506000910152565b60208152600082518060208401526113bd816040850160208701611372565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461141357600080fd5b919050565b6000806040838503121561142b57600080fd5b611434836113ef565b946020939093013593505050565b60008060006060848603121561145757600080fd5b611460846113ef565b925061146e602085016113ef565b9150604084013590509250925092565b60006020828403121561149057600080fd5b61136b826113ef565b600080604083850312156114ac57600080fd5b6114b5836113ef565b91506114c3602084016113ef565b90509250929050565b600181811c908216806114e057607f821691505b602082108103611519577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115615761156161151f565b500190565b60008451611578818460208901611372565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516115b4816001850160208a01611372565b600192019182015283516115cf816002840160208801611372565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361160d5761160d61151f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165257611652611614565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156116985761169861151f565b500390565b6000826116ac576116ac611614565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "BRIDGE()": {}, - "createOptimismMintableERC20(address,string,string)": { - "params": { - "_name": "ERC20 name.", - "_remoteToken": "Address of the token on the remote chain.", - "_symbol": "ERC20 symbol." - }, - "returns": { - "_0": "Address of the newly created token." - } - }, - "createOptimismMintableERC20WithDecimals(address,string,string,uint8)": { - "params": { - "_decimals": "ERC20 decimals", - "_name": "ERC20 name.", - "_remoteToken": "Address of the token on the remote chain.", - "_symbol": "ERC20 symbol." - }, - "returns": { - "_0": "Address of the newly created token." - } - }, - "createStandardL2Token(address,string,string)": { - "params": { - "_name": "ERC20 name.", - "_remoteToken": "Address of the token on the remote chain.", - "_symbol": "ERC20 symbol." - }, - "returns": { - "_0": "Address of the newly created token." - } - }, - "initialize(address)": { - "params": { - "_bridge": "Address of the StandardBridge on this chain." - } - } - }, - "events": { - "OptimismMintableERC20Created(address,address,address)": { - "params": { - "deployer": "Address of the account that deployed the token.", - "localToken": "Address of the created token on the local chain.", - "remoteToken": "Address of the corresponding token on the remote chain." - } - }, - "StandardL2TokenCreated(address,address)": { - "params": { - "localToken": "Address of the created token on the local chain.", - "remoteToken": "Address of the token on the remote chain." - } - } - }, - "title": "OptimismMintableERC20Factory" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"deployer\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"OptimismMintableERC20Created\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"StandardL2TokenCreated\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createOptimismMintableERC20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createOptimismMintableERC20WithDecimals\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createStandardL2Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"BRIDGE()\":{\"custom:legacy\":\"\"},\"createOptimismMintableERC20(address,string,string)\":{\"params\":{\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}},\"createOptimismMintableERC20WithDecimals(address,string,string,uint8)\":{\"params\":{\"_decimals\":\"ERC20 decimals\",\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}},\"createStandardL2Token(address,string,string)\":{\"custom:legacy\":\"@notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the newer createOptimismMintableERC20 function, which has a more intuitive name.\",\"params\":{\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}},\"initialize(address)\":{\"params\":{\"_bridge\":\"Address of the StandardBridge on this chain.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"BRIDGE()\":{\"notice\":\"Returns the address of the StandardBridge on this chain. This is a legacy getter, use `bridge` instead.\"},\"bridge()\":{\"notice\":\"Address of the StandardBridge on this chain.\"},\"constructor\":{\"notice\":\"The semver MUST be bumped any time that there is a change in the OptimismMintableERC20 token contract since this contract is responsible for deploying OptimismMintableERC20 contracts.\"},\"createOptimismMintableERC20(address,string,string)\":{\"notice\":\"Creates an instance of the OptimismMintableERC20 contract.\"},\"createOptimismMintableERC20WithDecimals(address,string,string,uint8)\":{\"notice\":\"Creates an instance of the OptimismMintableERC20 contract, with specified decimals.\"},\"initialize(address)\":{\"notice\":\"Initializer.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/OptimismMintableERC20Factory.sol\":\"OptimismMintableERC20Factory\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x6f8133b39efcbcbd5088f195dfacf1bedc3146508429c3865443909af735a04c\",\"urls\":[\"bzz-raw://adc36971e2e120458769f050428d9d2b0504516660345020c2521ee46e6d8abf\",\"dweb:/ipfs/QmPbFusQkZgGKpU8Fv5JoqL4oVeJtM3yqnhRGLY9eZT5zZ\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x39af021e492020fbeb5401371010d4a2fb69debe9596dbbead7bcd7fae248b0b\",\"urls\":[\"bzz-raw://dbeea52e586d2d7de55491a660ca76f75167ba6b43b65d29564864ee9c34a174\",\"dweb:/ipfs/QmS23vFqQxyUXhGuV1nSowZZS93CUkSnsb41uuyRtSeAED\"],\"license\":\"MIT\"},\"src/universal/OptimismMintableERC20Factory.sol\":{\"keccak256\":\"0x60862069899142dc4803d5f5754fd22339980bf74cfc4e2573bb59ff88a99c69\",\"urls\":[\"bzz-raw://8018f9fb11105ab80d4d6fb0bceabf8435d20d0883efa95070ae9e9983e3895c\",\"dweb:/ipfs/Qmf2ghxThySJA1pRvZfj3Q9yJwAZHSxwXAV9GDEqXxEWY9\"],\"license\":\"MIT\"},\"src/universal/Semver.sol\":{\"keccak256\":\"0x9de68ce536aee1aa616b4bf88d7ccc335460e6edd0e7170bdbf94c4fe3d41c60\",\"urls\":[\"bzz-raw://d5909c0b049b03a2bc24816ecf15b0aaf18c04a963174e1eba7624321bef330d\",\"dweb:/ipfs/QmeqdutwZWHqQMXauNR6WY8PrUpfsTiWTQyanbnGM9QqzT\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 5, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 32100, - "contract": "src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 32103, - "contract": "src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 76782, - "contract": "src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory", - "label": "bridge", - "offset": 2, - "slot": "0", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0xd84a03bef7be22fbd6e3f10e95fe63f5a187b2055a3e35f69b3018b28eeb609e", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "BRIDGE()": { - "notice": "Returns the address of the StandardBridge on this chain. This is a legacy getter, use `bridge` instead." - }, - "bridge()": { - "notice": "Address of the StandardBridge on this chain." - }, - "constructor": { - "notice": "The semver MUST be bumped any time that there is a change in the OptimismMintableERC20 token contract since this contract is responsible for deploying OptimismMintableERC20 contracts." - }, - "createOptimismMintableERC20(address,string,string)": { - "notice": "Creates an instance of the OptimismMintableERC20 contract." - }, - "createOptimismMintableERC20WithDecimals(address,string,string,uint8)": { - "notice": "Creates an instance of the OptimismMintableERC20 contract, with specified decimals." - }, - "initialize(address)": { - "notice": "Initializer." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "OptimismMintableERC20Created(address,address,address)": { - "notice": "Emitted whenever a new OptimismMintableERC20 is created." - } - }, - "notice": "OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20 contracts on the network it's deployed to. Simplifies the deployment process for users who may be less familiar with deploying smart contracts. Designed to be backwards compatible with the older StandardL2ERC20Factory contract." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/OptimismMintableERC20FactoryProxy.json b/packages/contracts-bedrock/deployments/goerli/OptimismMintableERC20FactoryProxy.json deleted file mode 100644 index e3d233bd6354..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/OptimismMintableERC20FactoryProxy.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "address": "0x883dcF8B05364083D849D8bD226bC8Cb4c42F9C5", - "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": "0x644dfa60d2e46b047a87d67362580323e8a90cafb9921983a41f3bb02caf8616", - "receipt": { - "to": null, - "from": "0x956a5152D0f498dBA0c5966577bb44262F8F7078", - "contractAddress": "0x883dcF8B05364083D849D8bD226bC8Cb4c42F9C5", - "transactionIndex": 42, - "gasUsed": "523800", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000002000000000000000000000000000000000000800000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xb6ba4f180c713ba5841f814d52de09d6863565d893d932a705283abfb127f3a4", - "transactionHash": "0x644dfa60d2e46b047a87d67362580323e8a90cafb9921983a41f3bb02caf8616", - "logs": [ - { - "transactionIndex": 42, - "blockNumber": 8299686, - "transactionHash": "0x644dfa60d2e46b047a87d67362580323e8a90cafb9921983a41f3bb02caf8616", - "address": "0x883dcF8B05364083D849D8bD226bC8Cb4c42F9C5", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d3670863c3f4b24d7b107900f0b75d4bbc6e0d", - "logIndex": 114, - "blockHash": "0xb6ba4f180c713ba5841f814d52de09d6863565d893d932a705283abfb127f3a4" - } - ], - "blockNumber": 8299686, - "cumulativeGasUsed": "8264141", - "status": 1, - "byzantium": true - }, - "args": [ - "0x01d3670863c3F4b24D7b107900f0b75d4BbC6e0d" - ], - "numDeployments": 1, - "solcInputHash": "672fbec9734a08fc34112408d6dc7f7b", - "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\":{\"contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0xfa08635f1866139673ac4fe7b07330f752f93800075b895d8fcb8484f4a3f753\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8f2247604d527f560edbb851c43b6c16b37e34972ddb305e16dd73623b8288cd\",\"dweb:/ipfs/QmfM8sLAZrxrnqyRdt1XJ5LyJh4wKbeEqk3VkvxG7BDqFj\"]}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "admin()": { - "returns": { - "_0": "Owner address." - } - }, - "changeAdmin(address)": { - "params": { - "_admin": "New owner of the proxy contract." - } - }, - "constructor": { - "params": { - "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "Address of the implementation contract." - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "Calldata to delegatecall the new implementation with.", - "_implementation": "Address of the implementation contract." - } - } - }, - "events": { - "AdminChanged(address,address)": { - "params": { - "newAdmin": "The new owner of the contract", - "previousAdmin": "The previous owner of the contract" - } - }, - "Upgraded(address)": { - "params": { - "implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "admin()": { - "notice": "Gets the owner of the proxy contract." - }, - "changeAdmin(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "constructor": { - "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." - }, - "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." - } - }, - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." - } - }, - "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/OptimismPortalProxy.json b/packages/contracts-bedrock/deployments/goerli/OptimismPortalProxy.json deleted file mode 100644 index 5e2760f63a6d..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/OptimismPortalProxy.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "address": "0x5b47E1A08Ea6d985D6649300584e6722Ec4B1383", - "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": "0xa04905ce7658945cde6348e5e8044cb37a6397c53d5acf0144172beb150cb7a7", - "receipt": { - "to": null, - "from": "0x956a5152D0f498dBA0c5966577bb44262F8F7078", - "contractAddress": "0x5b47E1A08Ea6d985D6649300584e6722Ec4B1383", - "transactionIndex": 22, - "gasUsed": "523800", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000010000000000000000000000000000000000000000000000000", - "blockHash": "0x96b7fbc6e5fafa9f7b84079d192b2120b4e3188c1e0d4d0023bf9a5a6466acd4", - "transactionHash": "0xa04905ce7658945cde6348e5e8044cb37a6397c53d5acf0144172beb150cb7a7", - "logs": [ - { - "transactionIndex": 22, - "blockNumber": 8299684, - "transactionHash": "0xa04905ce7658945cde6348e5e8044cb37a6397c53d5acf0144172beb150cb7a7", - "address": "0x5b47E1A08Ea6d985D6649300584e6722Ec4B1383", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d3670863c3f4b24d7b107900f0b75d4bbc6e0d", - "logIndex": 52, - "blockHash": "0x96b7fbc6e5fafa9f7b84079d192b2120b4e3188c1e0d4d0023bf9a5a6466acd4" - } - ], - "blockNumber": 8299684, - "cumulativeGasUsed": "4365507", - "status": 1, - "byzantium": true - }, - "args": [ - "0x01d3670863c3F4b24D7b107900f0b75d4BbC6e0d" - ], - "numDeployments": 1, - "solcInputHash": "672fbec9734a08fc34112408d6dc7f7b", - "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\":{\"contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0xfa08635f1866139673ac4fe7b07330f752f93800075b895d8fcb8484f4a3f753\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8f2247604d527f560edbb851c43b6c16b37e34972ddb305e16dd73623b8288cd\",\"dweb:/ipfs/QmfM8sLAZrxrnqyRdt1XJ5LyJh4wKbeEqk3VkvxG7BDqFj\"]}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "admin()": { - "returns": { - "_0": "Owner address." - } - }, - "changeAdmin(address)": { - "params": { - "_admin": "New owner of the proxy contract." - } - }, - "constructor": { - "params": { - "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "Address of the implementation contract." - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "Calldata to delegatecall the new implementation with.", - "_implementation": "Address of the implementation contract." - } - } - }, - "events": { - "AdminChanged(address,address)": { - "params": { - "newAdmin": "The new owner of the contract", - "previousAdmin": "The previous owner of the contract" - } - }, - "Upgraded(address)": { - "params": { - "implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "admin()": { - "notice": "Gets the owner of the proxy contract." - }, - "changeAdmin(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "constructor": { - "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." - }, - "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." - } - }, - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." - } - }, - "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/PortalSender.json b/packages/contracts-bedrock/deployments/goerli/PortalSender.json deleted file mode 100644 index 0a18c5368fdc..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/PortalSender.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "address": "0xe7FACd39531ee3C313330E93B4d7a8B8A3c84Aa4", - "abi": [ - { - "inputs": [ - { - "internalType": "contract OptimismPortal", - "name": "_portal", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "PORTAL", - "outputs": [ - { - "internalType": "contract OptimismPortal", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "donate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x2440cbd5dd9690dab099a0e62e4064c02f7cbca54f0bd60933da46c834d18d92", - "receipt": { - "to": null, - "from": "0x956a5152D0f498dBA0c5966577bb44262F8F7078", - "contractAddress": "0xe7FACd39531ee3C313330E93B4d7a8B8A3c84Aa4", - "transactionIndex": 34, - "gasUsed": "118144", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xf5bae9de168a815dde2f1dc82cb3753a0a08a5269029a8135a7b8bf9323f1f2e", - "transactionHash": "0x2440cbd5dd9690dab099a0e62e4064c02f7cbca54f0bd60933da46c834d18d92", - "logs": [], - "blockNumber": 8299695, - "cumulativeGasUsed": "11116294", - "status": 1, - "byzantium": true - }, - "args": [ - "0x5b47E1A08Ea6d985D6649300584e6722Ec4B1383" - ], - "numDeployments": 1, - "solcInputHash": "672fbec9734a08fc34112408d6dc7f7b", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"_portal\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"PORTAL\",\"outputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"donate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_portal\":\"Address of the OptimismPortal contract.\"}}},\"title\":\"PortalSender\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"PORTAL()\":{\"notice\":\"Address of the OptimismPortal contract.\"},\"donate()\":{\"notice\":\"Sends balance of this contract to the OptimismPortal.\"}},\"notice\":\"The PortalSender is a simple intermediate contract that will transfer the balance of the L1StandardBridge to the OptimismPortal during the Bedrock migration.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/deployment/PortalSender.sol\":\"PortalSender\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/L1/L2OutputOracle.sol\":{\"keccak256\":\"0xaa706785b6c6e01b21b47d050a19f83d6afaf8a1db152d0e48463eea55c0c366\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://84f6a9884c4cf7edf499e4182bd9db03876e33df66a0b64307e2c7b997c150b7\",\"dweb:/ipfs/QmR2prJL6HGxPjVjbW5o96C9ekavkarNEy2v11yCGxrdfX\"]},\"contracts/L1/OptimismPortal.sol\":{\"keccak256\":\"0xc9fa6b522c76e6f8de364b4e6f58ebcd073a47b37fb343e444687429bbc2b49e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b3ee3b286e2f5930ee0ec98864c6f51b0d33820678760b668689487a67771f48\",\"dweb:/ipfs/Qmb1KbJXBGzohdyzw5hsMkaEVtPjEEW5BdvDRAUN9Fv7Vy\"]},\"contracts/L1/ResourceMetering.sol\":{\"keccak256\":\"0x23045734df51c2f237d0def7f5e6dda69304bb3cfb554c6c1e934c4c8b07cecc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e6f84a34b842702c3ab4b06da997903046556f3f809716763a351b9f379b7e07\",\"dweb:/ipfs/QmQPyWcbuAMhghZdGSPwSBQdQgZi5hk6Bdg4s7qxaHpcMw\"]},\"contracts/deployment/PortalSender.sol\":{\"keccak256\":\"0xe60d88036d9aa8f8e80a4108ee30ad987564ad996af87a79ba92f6ca35852881\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a4be187cd3d5926592491f722dfa1b1c41a8f4f1abdc8cf3883964f70acb0a44\",\"dweb:/ipfs/QmYsAK4YcRHmPoex2eX2x1r6N76AMk3rdBHHmp6gUT73Fa\"]},\"contracts/libraries/Arithmetic.sol\":{\"keccak256\":\"0xc8858039f87e48e6f18c1af8bc0b03e57cfef564acddfd06e4d91e3db7ac5ed6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2fc79af1e844aa6dc1c68067bfe1d359df8d4e9a3e8881afb3bcfcbf68071714\",\"dweb:/ipfs/QmcNC4k8zmvwj4kZizSenTiWbx2DJQPbwqXXLF4iMbkRVD\"]},\"contracts/libraries/Burn.sol\":{\"keccak256\":\"0x54233b226ba6919dc46d438bc790108d8f855001002a1b9c3c37aed7a83e5f3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4051a4baca357a9191a6c9e3aa1593a17b69dd7915966e23e4cb269e9c1d9ed4\",\"dweb:/ipfs/QmadKjGKvxm53abVHQdsxrXBc8e9jXywu6vvhkAgjsx59J\"]},\"contracts/libraries/Bytes.sol\":{\"keccak256\":\"0x7aca6593fadf438ee9cd090d8fdc8f94a5202a2eb7f764c9a86f207712d87a48\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://aac32157885c5a08bd0bc7dcd5511f66db12bb20d0c263dd7be9f58b91538fc1\",\"dweb:/ipfs/Qmb1iG11Z53yt9wNbGsuTvoydJXFosDDpWwRSADKyqiCjw\"]},\"contracts/libraries/Constants.sol\":{\"keccak256\":\"0x50a2b69a5e9246945ee1588278753feae90285ff7e675369f0cc5b64acea333c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://75153213766bd271cce59d5284a4a0d2f6283e3c6a9dc31b8ce20a3a4c28c066\",\"dweb:/ipfs/QmcbpwMLYuKUPahVYJ3W7sfntQgHk9RTuR2DUzFMrfPMQr\"]},\"contracts/libraries/Encoding.sol\":{\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f18156216c1f9457c2e032a812ad70f2babbc5b89997554ff014d64c483fb2ff\",\"dweb:/ipfs/Qmc5rjMaBFn3jV7XqDrEvRbmatQvJxeVJYA5B5rdcKPkcJ\"]},\"contracts/libraries/Hashing.sol\":{\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6746ed0d26d603568818cc52a29d0209effd69f7e55bd0017a6b91bd6cf319fe\",\"dweb:/ipfs/QmPebCmCELMBRtDDxt5ziEPfRXUh6tfm2qJdwz3iyrDdWN\"]},\"contracts/libraries/SafeCall.sol\":{\"keccak256\":\"0xbb0621c028c18e9d5a54cf1a8136cf2e77f161de48aeb8d911e230f6b280c9ed\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://924ecc629c7642bc19e2f8a390f1b946d22862c8889453da681b5bc1a45d7703\",\"dweb:/ipfs/QmbNknQ8pzssXDXGVjXxzZ8zh1YnNCWtRJVepiM1TnqoqQ\"]},\"contracts/libraries/Types.sol\":{\"keccak256\":\"0x822e7c7ac5d45eac20551ba602d8bff3d22db3538fb32be42c1ab12d7bfca110\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://970823854723de895ca7a24d34269e886a20824c75f706cb41541893b7c78838\",\"dweb:/ipfs/QmSQbEECeTxgUT65pK7Czc4ovAv2FdQ9EHyi5Z8mZgNkXc\"]},\"contracts/libraries/rlp/RLPReader.sol\":{\"keccak256\":\"0x50763c897f0fe84cb067985ec4d7c5721ce9004a69cf0327f96f8982ee8ca412\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://603af847b43933b075f9aac3a7b3cd65041ffe6d732826695458ca9575e1a809\",\"dweb:/ipfs/QmfByFEaCxT9y1VtqoLi5EsXZ9ihkPfj6g5x7pcPoQ7q2K\"]},\"contracts/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://921c44e6a0982b9a4011900fda1bda2c06b7a85894967de98b407a83fe9f90c0\",\"dweb:/ipfs/QmSsHLKDUQ82kpKdqB6VntVGKuPDb4W9VdotsubuqWBzio\"]},\"contracts/libraries/trie/MerkleTrie.sol\":{\"keccak256\":\"0xd27fc945d6dd2821636d840f3766f817823c8e9fbfdb87c2da7c73e4292d2f7f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://497cec37d09ebcdc8d1cccac608a4a0b9b9d83eac6cc7c9e8b73c4c6644e2209\",\"dweb:/ipfs/QmUYMsCcgU6epspvKV9Y6anHyyMb4hd1xVzUZheBY9mfG7\"]},\"contracts/libraries/trie/SecureMerkleTrie.sol\":{\"keccak256\":\"0x61b03a03779cb1f75cea3b88af16fdfd10629029b4b2d6be5238e71af8ef1b5f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1212951af291c0e033a7119b42de5cad6b6bf32da26777da7c2419e76fa8f314\",\"dweb:/ipfs/QmYbnifDmL6UkP9D1X9GaNLR1Q8wYwmDNeYqkJ71bycaE5\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x979b13465de4996a1105850abbf48abe7f71d5e18a8d4af318597ee14c165fdf\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d0881ed7d8371fe1c12b931334e107746fa97d9ecd6aa3c0fca0c0db8581474e\",\"dweb:/ipfs/QmQ9UFwZgWkyFAHrzTtS7m6rghZ8nP9QybEuJ5y9vux5Gv\"]},\"contracts/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"]},\"node_modules/@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]},\"node_modules/@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"]},\"node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"]},\"node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"]}},\"version\":1}", - "bytecode": "0x60a060405234801561001057600080fd5b506040516101b53803806101b583398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b6080516101256100906000396000818160400152609701526101256000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630ff754ea1461003b578063ed88c68e1461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610093610095565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638b4c40b0476040518263ffffffff1660e01b81526004016000604051808303818588803b1580156100fd57600080fd5b505af1158015610111573d6000803e3d6000fd5b505050505056fea164736f6c634300080f000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630ff754ea1461003b578063ed88c68e1461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610093610095565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638b4c40b0476040518263ffffffff1660e01b81526004016000604051808303818588803b1580156100fd57600080fd5b505af1158015610111573d6000803e3d6000fd5b505050505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_portal": "Address of the OptimismPortal contract." - } - } - }, - "title": "PortalSender" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "PORTAL()": { - "notice": "Address of the OptimismPortal contract." - }, - "donate()": { - "notice": "Sends balance of this contract to the OptimismPortal." - } - }, - "notice": "The PortalSender is a simple intermediate contract that will transfer the balance of the L1StandardBridge to the OptimismPortal during the Bedrock migration." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/ProtocolVersions.json b/packages/contracts-bedrock/deployments/goerli/ProtocolVersions.json deleted file mode 100644 index 01adc2635496..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/ProtocolVersions.json +++ /dev/null @@ -1,407 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "version", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "enum ProtocolVersions.UpdateType", - "name": "updateType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "ConfigUpdate", - "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": "RECOMMENDED_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REQUIRED_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "ProtocolVersion", - "name": "_required", - "type": "uint256" - }, - { - "internalType": "ProtocolVersion", - "name": "_recommended", - "type": "uint256" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "recommended", - "outputs": [ - { - "internalType": "ProtocolVersion", - "name": "out_", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "required", - "outputs": [ - { - "internalType": "ProtocolVersion", - "name": "out_", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "ProtocolVersion", - "name": "_recommended", - "type": "uint256" - } - ], - "name": "setRecommended", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "ProtocolVersion", - "name": "_required", - "type": "uint256" - } - ], - "name": "setRequired", - "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" - } - ], - "address": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "args": [], - "bytecode": "0x60806040523480156200001157600080fd5b506200002261dead60008062000028565b620004c9565b600054600390610100900460ff161580156200004b575060005460ff8083169116105b620000b45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805461ffff191660ff831617610100179055620000d26200013a565b620000dd84620001a2565b620000e88362000221565b620000f382620002d1565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b600054610100900460ff16620001965760405162461bcd60e51b815260206004820152602b602482015260008051602062000e9683398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000ab565b620001a062000332565b565b620001ac62000399565b6001600160a01b038116620002135760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620000ab565b6200021e81620003f5565b50565b620002676200025260017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16200044b565b60001b826200044760201b620004f51760201c565b6000816040516020016200027d91815260200190565b60408051601f19818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051620002c5919062000471565b60405180910390a35050565b620003026200025260017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6200044b565b6000816040516020016200031891815260200190565b60408051601f198184030181529190529050600162000292565b600054610100900460ff166200038e5760405162461bcd60e51b815260206004820152602b602482015260008051602062000e9683398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000ab565b620001a033620003f5565b6033546001600160a01b03163314620001a05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620000ab565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b9055565b6000828210156200046c57634e487b7160e01b600052601160045260246000fd5b500390565b600060208083528351808285015260005b81811015620004a05785810183015185820160400152820162000482565b81811115620004b3576000604083870101525b50601f01601f1916929092016040019392505050565b6109bd80620004d96000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e736600461085d565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161010091906108e1565b6100ec61016036600461085d565b61021d565b6100ec61022e565b6100ec61017b366004610924565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103ad565b6100f66103e6565b6100ec6101c6366004610957565b610416565b6100f66104ca565b6100f6600081565b6101e36104f9565b6101ec8161057a565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b81565b6102256104f9565b6101ec81610632565b6102366104f9565b61024060006106ac565b565b600054600390610100900460ff16158015610264575060005460ff8083169116105b6102f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905561032e610723565b61033784610416565b6103408361057a565b61034982610632565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b60006103e16103dd60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b5490565b905090565b60006103e16103dd60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b61041e6104f9565b73ffffffffffffffffffffffffffffffffffffffff81166104c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102ec565b6101ec816106ac565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102ec565b6105ad6105a860017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b829055565b6000816040516020016105c291815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161062691906108e1565b60405180910390a35050565b6106606105a860017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b60008160405160200161067591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060016105f5565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166107ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ec565b610240600054610100900460ff16610854576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ec565b610240336106ac565b60006020828403121561086f57600080fd5b5035919050565b6000815180845260005b8181101561089c57602081850181015186830182015201610880565b818111156108ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006108f46020830184610876565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091f57600080fd5b919050565b60008060006060848603121561093957600080fd5b610942846108fb565b95602085013595506040909401359392505050565b60006020828403121561096957600080fd5b6108f4826108fb565b6000828210156109ab577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e736600461085d565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161010091906108e1565b6100ec61016036600461085d565b61021d565b6100ec61022e565b6100ec61017b366004610924565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103ad565b6100f66103e6565b6100ec6101c6366004610957565b610416565b6100f66104ca565b6100f6600081565b6101e36104f9565b6101ec8161057a565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b81565b6102256104f9565b6101ec81610632565b6102366104f9565b61024060006106ac565b565b600054600390610100900460ff16158015610264575060005460ff8083169116105b6102f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905561032e610723565b61033784610416565b6103408361057a565b61034982610632565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b60006103e16103dd60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b5490565b905090565b60006103e16103dd60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b61041e6104f9565b73ffffffffffffffffffffffffffffffffffffffff81166104c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102ec565b6101ec816106ac565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102ec565b6105ad6105a860017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b829055565b6000816040516020016105c291815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161062691906108e1565b60405180910390a35050565b6106606105a860017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b60008160405160200161067591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060016105f5565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166107ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ec565b610240600054610100900460ff16610854576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ec565b610240336106ac565b60006020828403121561086f57600080fd5b5035919050565b6000815180845260005b8181101561089c57602081850181015186830182015201610880565b818111156108ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006108f46020830184610876565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091f57600080fd5b919050565b60008060006060848603121561093957600080fd5b610942846108fb565b95602085013595506040909401359392505050565b60006020828403121561096957600080fd5b6108f4826108fb565b6000828210156109ab577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "initialize(address,uint256,uint256)": { - "params": { - "_owner": "Initial owner of the contract.", - "_recommended": "Recommended protocol version to operate on thi chain.", - "_required": "Required protocol version to operate on this chain." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "recommended()": { - "returns": { - "out_": "Recommended protocol version to sync to the head of the chain." - } - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "required()": { - "returns": { - "out_": "Required protocol version to sync to the head of the chain." - } - }, - "setRecommended(uint256)": { - "params": { - "_recommended": "New recommended protocol version." - } - }, - "setRequired(uint256)": { - "params": { - "_required": "New required protocol version." - } - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - } - }, - "events": { - "ConfigUpdate(uint256,uint8,bytes)": { - "params": { - "data": "Encoded update data.", - "updateType": "Type of update.", - "version": "ProtocolVersion version." - } - } - }, - "title": "ProtocolVersions" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"enum ProtocolVersions.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ConfigUpdate\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RECOMMENDED_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"REQUIRED_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"ProtocolVersion\",\"name\":\"_required\",\"type\":\"uint256\"},{\"internalType\":\"ProtocolVersion\",\"name\":\"_recommended\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"recommended\",\"outputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"out_\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"required\",\"outputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"out_\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"_recommended\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setRecommended\"},{\"inputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"_required\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setRequired\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"initialize(address,uint256,uint256)\":{\"params\":{\"_owner\":\"Initial owner of the contract.\",\"_recommended\":\"Recommended protocol version to operate on thi chain.\",\"_required\":\"Required protocol version to operate on this chain.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"recommended()\":{\"returns\":{\"out_\":\"Recommended protocol version to sync to the head of the chain.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"required()\":{\"returns\":{\"out_\":\"Required protocol version to sync to the head of the chain.\"}},\"setRecommended(uint256)\":{\"params\":{\"_recommended\":\"New recommended protocol version.\"}},\"setRequired(uint256)\":{\"params\":{\"_required\":\"New required protocol version.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"RECOMMENDED_SLOT()\":{\"notice\":\"Storage slot that the recommended protocol version is stored at.\"},\"REQUIRED_SLOT()\":{\"notice\":\"Storage slot that the required protocol version is stored at.\"},\"VERSION()\":{\"notice\":\"Version identifier, used for upgrades.\"},\"constructor\":{\"notice\":\"Constructs the ProtocolVersion contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)` A zero version is considered empty and is ignored by nodes.\"},\"initialize(address,uint256,uint256)\":{\"notice\":\"Initializer.\"},\"recommended()\":{\"notice\":\"High level getter for the recommended protocol version.\"},\"required()\":{\"notice\":\"High level getter for the required protocol version.\"},\"setRecommended(uint256)\":{\"notice\":\"Updates the recommended protocol version. Can only be called by the owner.\"},\"setRequired(uint256)\":{\"notice\":\"Updates the required protocol version. Can only be called by the owner.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/ProtocolVersions.sol\":\"ProtocolVersions\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ProtocolVersions.sol\":{\"keccak256\":\"0xa283721c36e2ba3ea1c61faebc364a8884bf3a276f80374cc8017d0e23ea1dfc\",\"urls\":[\"bzz-raw://4ee23cbc9772213c637c767747e5fb1db7c3f0f17d6a1ff576b638f25c6799e8\",\"dweb:/ipfs/QmfKZfFC6fyhQdLk2YrjVBL6eRX1d9CTrPHj7fNPUNXmEq\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 3, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 29536, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 29539, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 31067, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 29408, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 29528, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_array(t_uint256)50_storage": { - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x668fd8fa1ddfef9a1e20ad56c48e379721d506fbce8f40c80c733ce43e2150c2", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "RECOMMENDED_SLOT()": { - "notice": "Storage slot that the recommended protocol version is stored at." - }, - "REQUIRED_SLOT()": { - "notice": "Storage slot that the required protocol version is stored at." - }, - "VERSION()": { - "notice": "Version identifier, used for upgrades." - }, - "constructor": { - "notice": "Constructs the ProtocolVersion contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)` A zero version is considered empty and is ignored by nodes." - }, - "initialize(address,uint256,uint256)": { - "notice": "Initializer." - }, - "recommended()": { - "notice": "High level getter for the recommended protocol version." - }, - "required()": { - "notice": "High level getter for the required protocol version." - }, - "setRecommended(uint256)": { - "notice": "Updates the recommended protocol version. Can only be called by the owner." - }, - "setRequired(uint256)": { - "notice": "Updates the required protocol version. Can only be called by the owner." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "ConfigUpdate(uint256,uint8,bytes)": { - "notice": "Emitted when configuration is updated." - } - }, - "notice": "The ProtocolVersions contract is used to manage superchain protocol version information." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/ProxyAdmin.json b/packages/contracts-bedrock/deployments/goerli/ProxyAdmin.json deleted file mode 100644 index 703a55cc1eae..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/ProxyAdmin.json +++ /dev/null @@ -1,576 +0,0 @@ -{ - "address": "0x01d3670863c3F4b24D7b107900f0b75d4BbC6e0d", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "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": "addressManager", - "outputs": [ - { - "internalType": "contract AddressManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_proxy", - "type": "address" - }, - { - "internalType": "address", - "name": "_newAdmin", - "type": "address" - } - ], - "name": "changeProxyAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_proxy", - "type": "address" - } - ], - "name": "getProxyAdmin", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_proxy", - "type": "address" - } - ], - "name": "getProxyImplementation", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "implementationName", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "isUpgrading", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "proxyType", - "outputs": [ - { - "internalType": "enum ProxyAdmin.ProxyType", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "address", - "name": "_address", - "type": "address" - } - ], - "name": "setAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract AddressManager", - "name": "_address", - "type": "address" - } - ], - "name": "setAddressManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_address", - "type": "address" - }, - { - "internalType": "string", - "name": "_name", - "type": "string" - } - ], - "name": "setImplementationName", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_address", - "type": "address" - }, - { - "internalType": "enum ProxyAdmin.ProxyType", - "name": "_type", - "type": "uint8" - } - ], - "name": "setProxyType", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_upgrading", - "type": "bool" - } - ], - "name": "setUpgrading", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_proxy", - "type": "address" - }, - { - "internalType": "address", - "name": "_implementation", - "type": "address" - } - ], - "name": "upgrade", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_proxy", - "type": "address" - }, - { - "internalType": "address", - "name": "_implementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "upgradeAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } - ], - "transactionHash": "0x1945e7f290b6347aef2843fb9aff577e6d7b6ab0280088dd9151db13e4169549", - "receipt": { - "to": null, - "from": "0x956a5152D0f498dBA0c5966577bb44262F8F7078", - "contractAddress": "0x01d3670863c3F4b24D7b107900f0b75d4BbC6e0d", - "transactionIndex": 24, - "gasUsed": "1483537", - "logsBloom": "0x00000000008000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400002000000000000000000000010000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000400", - "blockHash": "0xf4b8cf8bae5715632f5d24fa7465ef6796e00022c4edff51b191313b5cc91866", - "transactionHash": "0x1945e7f290b6347aef2843fb9aff577e6d7b6ab0280088dd9151db13e4169549", - "logs": [ - { - "transactionIndex": 24, - "blockNumber": 8299682, - "transactionHash": "0x1945e7f290b6347aef2843fb9aff577e6d7b6ab0280088dd9151db13e4169549", - "address": "0x01d3670863c3F4b24D7b107900f0b75d4BbC6e0d", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000956a5152d0f498dba0c5966577bb44262f8f7078" - ], - "data": "0x", - "logIndex": 75, - "blockHash": "0xf4b8cf8bae5715632f5d24fa7465ef6796e00022c4edff51b191313b5cc91866" - }, - { - "transactionIndex": 24, - "blockNumber": 8299682, - "transactionHash": "0x1945e7f290b6347aef2843fb9aff577e6d7b6ab0280088dd9151db13e4169549", - "address": "0x01d3670863c3F4b24D7b107900f0b75d4BbC6e0d", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x000000000000000000000000956a5152d0f498dba0c5966577bb44262f8f7078", - "0x000000000000000000000000956a5152d0f498dba0c5966577bb44262f8f7078" - ], - "data": "0x", - "logIndex": 76, - "blockHash": "0xf4b8cf8bae5715632f5d24fa7465ef6796e00022c4edff51b191313b5cc91866" - } - ], - "blockNumber": 8299682, - "cumulativeGasUsed": "5783338", - "status": 1, - "byzantium": true - }, - "args": [ - "0x956a5152D0f498dBA0c5966577bb44262F8F7078" - ], - "numDeployments": 1, - "solcInputHash": "672fbec9734a08fc34112408d6dc7f7b", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"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\":\"addressManager\",\"outputs\":[{\"internalType\":\"contract AddressManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_newAdmin\",\"type\":\"address\"}],\"name\":\"changeProxyAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"getProxyAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"getProxyImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"implementationName\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isUpgrading\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"proxyType\",\"outputs\":[{\"internalType\":\"enum ProxyAdmin.ProxyType\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract AddressManager\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setAddressManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"setImplementationName\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"enum ProxyAdmin.ProxyType\",\"name\":\"_type\",\"type\":\"uint8\"}],\"name\":\"setProxyType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_upgrading\",\"type\":\"bool\"}],\"name\":\"setUpgrading\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"upgrade\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"upgradeAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"changeProxyAdmin(address,address)\":{\"params\":{\"_newAdmin\":\"Address of the new proxy admin.\",\"_proxy\":\"Address of the proxy to update.\"}},\"constructor\":{\"params\":{\"_owner\":\"Address of the initial owner of this contract.\"}},\"getProxyAdmin(address)\":{\"params\":{\"_proxy\":\"Address of the proxy to get the admin of.\"},\"returns\":{\"_0\":\"Address of the admin of the proxy.\"}},\"getProxyImplementation(address)\":{\"params\":{\"_proxy\":\"Address of the proxy to get the implementation of.\"},\"returns\":{\"_0\":\"Address of the implementation of the proxy.\"}},\"isUpgrading()\":{\"custom:legacy\":\"@notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening.\",\"returns\":{\"_0\":\"Whether or not there is an upgrade going on. May not actually tell you whether an upgrade is going on, since we don't currently plan to use this variable for anything other than a legacy indicator to fix a UX bug in the ChugSplash proxy.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAddress(string,address)\":{\"custom:legacy\":\"@notice Set an address in the address manager. Since only the owner of the AddressManager can directly modify addresses and the ProxyAdmin will own the AddressManager, this gives the owner of the ProxyAdmin the ability to modify addresses directly.\",\"params\":{\"_address\":\"Address to attach to the given name.\",\"_name\":\"Name to set within the AddressManager.\"}},\"setAddressManager(address)\":{\"params\":{\"_address\":\"Address of the AddressManager.\"}},\"setImplementationName(address,string)\":{\"params\":{\"_address\":\"Address of the ResolvedDelegateProxy.\",\"_name\":\"Name of the implementation for the proxy.\"}},\"setProxyType(address,uint8)\":{\"params\":{\"_address\":\"Address of the proxy.\",\"_type\":\"Type of the proxy.\"}},\"setUpgrading(bool)\":{\"custom:legacy\":\"@notice Set the upgrading status for the Chugsplash proxy type.\",\"params\":{\"_upgrading\":\"Whether or not the system is upgrading.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgrade(address,address)\":{\"params\":{\"_implementation\":\"Address of the new implementation address.\",\"_proxy\":\"Address of the proxy to upgrade.\"}},\"upgradeAndCall(address,address,bytes)\":{\"params\":{\"_data\":\"Data to trigger the new implementation with.\",\"_implementation\":\"Address of the new implementation address.\",\"_proxy\":\"Address of the proxy to upgrade.\"}}},\"title\":\"ProxyAdmin\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addressManager()\":{\"notice\":\"The address of the address manager, this is required to manage the ResolvedDelegateProxy type.\"},\"changeProxyAdmin(address,address)\":{\"notice\":\"Updates the admin of the given proxy address.\"},\"getProxyAdmin(address)\":{\"notice\":\"Returns the admin of the given proxy address.\"},\"getProxyImplementation(address)\":{\"notice\":\"Returns the implementation of the given proxy address.\"},\"implementationName(address)\":{\"notice\":\"A reverse mapping of addresses to names held in the AddressManager. This must be manually kept up to date with changes in the AddressManager for this contract to be able to work as an admin for the ResolvedDelegateProxy type.\"},\"proxyType(address)\":{\"notice\":\"A mapping of proxy types, used for backwards compatibility.\"},\"setAddressManager(address)\":{\"notice\":\"Set the address of the AddressManager. This is required to manage legacy ResolvedDelegateProxy type proxy contracts.\"},\"setImplementationName(address,string)\":{\"notice\":\"Sets the implementation name for a given address. Only required for ResolvedDelegateProxy type proxies that have an implementation name.\"},\"setProxyType(address,uint8)\":{\"notice\":\"Sets the proxy type for a given address. Only required for non-standard (legacy) proxy types.\"},\"upgrade(address,address)\":{\"notice\":\"Changes a proxy's implementation contract.\"},\"upgradeAndCall(address,address,bytes)\":{\"notice\":\"Changes a proxy's implementation contract and delegatecalls the new implementation with some given data. Useful for atomic upgrade-and-initialize calls.\"}},\"notice\":\"This is an auxiliary contract meant to be assigned as the admin of an ERC1967 Proxy, based on the OpenZeppelin implementation. It has backwards compatibility logic to work with the various types of proxies that have been deployed by Optimism in the past.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/ProxyAdmin.sol\":\"ProxyAdmin\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/legacy/AddressManager.sol\":{\"keccak256\":\"0x7a353d4c92eed32665fd2f0023c55054901293cf7a6e14ca108229d87c047b10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b92ba23601d1951271729a20db931a45639d9376b7c8e2705c23dc360833715a\",\"dweb:/ipfs/QmTKwYLNYYBKZpd31VNBANmguVUwFZifSg7joHSgLZjZCj\"]},\"contracts/legacy/L1ChugSplashProxy.sol\":{\"keccak256\":\"0x6ae7bf6ea9ac0e3511ee4cb15d946589da0dd35098ff762c0b2903d064f24875\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://02028d86c1d38563021d5ead5282271ccdf1c03a24f2eaee056ae2157f0554ee\",\"dweb:/ipfs/QmW9urkBBRTmZ8FjL5Y5zWbdnRhPDruxCCLnpr2CTkozKM\"]},\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0xfa08635f1866139673ac4fe7b07330f752f93800075b895d8fcb8484f4a3f753\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8f2247604d527f560edbb851c43b6c16b37e34972ddb305e16dd73623b8288cd\",\"dweb:/ipfs/QmfM8sLAZrxrnqyRdt1XJ5LyJh4wKbeEqk3VkvxG7BDqFj\"]},\"contracts/universal/ProxyAdmin.sol\":{\"keccak256\":\"0x7326011ac425cc9ab4760c29ca559342d4832633b5019a9a61b9e63067374e2a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7d3541272c48443f0b339998553e44600b7bcb4f949e5c94acb5a3acfce19399\",\"dweb:/ipfs/QmNSd9jxACWg8bZE8EgxmRdXwLUQixVs4oiugrVegapUe4\"]},\"node_modules/@openzeppelin/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162001a5f38038062001a5f8339810160408190526200003491620000a1565b6200003f3362000051565b6200004a8162000051565b50620000d3565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215620000b457600080fd5b81516001600160a01b0381168114620000cc57600080fd5b9392505050565b61197c80620000e36000396000f3fe60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a", - "deployedBytecode": "0x60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "changeProxyAdmin(address,address)": { - "params": { - "_newAdmin": "Address of the new proxy admin.", - "_proxy": "Address of the proxy to update." - } - }, - "constructor": { - "params": { - "_owner": "Address of the initial owner of this contract." - } - }, - "getProxyAdmin(address)": { - "params": { - "_proxy": "Address of the proxy to get the admin of." - }, - "returns": { - "_0": "Address of the admin of the proxy." - } - }, - "getProxyImplementation(address)": { - "params": { - "_proxy": "Address of the proxy to get the implementation of." - }, - "returns": { - "_0": "Address of the implementation of the proxy." - } - }, - "isUpgrading()": { - "returns": { - "_0": "Whether or not there is an upgrade going on. May not actually tell you whether an upgrade is going on, since we don't currently plan to use this variable for anything other than a legacy indicator to fix a UX bug in the ChugSplash proxy." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "setAddress(string,address)": { - "params": { - "_address": "Address to attach to the given name.", - "_name": "Name to set within the AddressManager." - } - }, - "setAddressManager(address)": { - "params": { - "_address": "Address of the AddressManager." - } - }, - "setImplementationName(address,string)": { - "params": { - "_address": "Address of the ResolvedDelegateProxy.", - "_name": "Name of the implementation for the proxy." - } - }, - "setProxyType(address,uint8)": { - "params": { - "_address": "Address of the proxy.", - "_type": "Type of the proxy." - } - }, - "setUpgrading(bool)": { - "params": { - "_upgrading": "Whether or not the system is upgrading." - } - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - }, - "upgrade(address,address)": { - "params": { - "_implementation": "Address of the new implementation address.", - "_proxy": "Address of the proxy to upgrade." - } - }, - "upgradeAndCall(address,address,bytes)": { - "params": { - "_data": "Data to trigger the new implementation with.", - "_implementation": "Address of the new implementation address.", - "_proxy": "Address of the proxy to upgrade." - } - } - }, - "title": "ProxyAdmin" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "addressManager()": { - "notice": "The address of the address manager, this is required to manage the ResolvedDelegateProxy type." - }, - "changeProxyAdmin(address,address)": { - "notice": "Updates the admin of the given proxy address." - }, - "getProxyAdmin(address)": { - "notice": "Returns the admin of the given proxy address." - }, - "getProxyImplementation(address)": { - "notice": "Returns the implementation of the given proxy address." - }, - "implementationName(address)": { - "notice": "A reverse mapping of addresses to names held in the AddressManager. This must be manually kept up to date with changes in the AddressManager for this contract to be able to work as an admin for the ResolvedDelegateProxy type." - }, - "proxyType(address)": { - "notice": "A mapping of proxy types, used for backwards compatibility." - }, - "setAddressManager(address)": { - "notice": "Set the address of the AddressManager. This is required to manage legacy ResolvedDelegateProxy type proxy contracts." - }, - "setImplementationName(address,string)": { - "notice": "Sets the implementation name for a given address. Only required for ResolvedDelegateProxy type proxies that have an implementation name." - }, - "setProxyType(address,uint8)": { - "notice": "Sets the proxy type for a given address. Only required for non-standard (legacy) proxy types." - }, - "upgrade(address,address)": { - "notice": "Changes a proxy's implementation contract." - }, - "upgradeAndCall(address,address,bytes)": { - "notice": "Changes a proxy's implementation contract and delegatecalls the new implementation with some given data. Useful for atomic upgrade-and-initialize calls." - } - }, - "notice": "This is an auxiliary contract meant to be assigned as the admin of an ERC1967 Proxy, based on the OpenZeppelin implementation. It has backwards compatibility logic to work with the various types of proxies that have been deployed by Optimism in the past." - }, - "storageLayout": { - "storage": [ - { - "astId": 40375, - "contract": "contracts/universal/ProxyAdmin.sol:ProxyAdmin", - "label": "_owner", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 38436, - "contract": "contracts/universal/ProxyAdmin.sol:ProxyAdmin", - "label": "proxyType", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_address,t_enum(ProxyType)38430)" - }, - { - "astId": 38441, - "contract": "contracts/universal/ProxyAdmin.sol:ProxyAdmin", - "label": "implementationName", - "offset": 0, - "slot": "2", - "type": "t_mapping(t_address,t_string_storage)" - }, - { - "astId": 38445, - "contract": "contracts/universal/ProxyAdmin.sol:ProxyAdmin", - "label": "addressManager", - "offset": 0, - "slot": "3", - "type": "t_contract(AddressManager)5619" - }, - { - "astId": 38448, - "contract": "contracts/universal/ProxyAdmin.sol:ProxyAdmin", - "label": "upgrading", - "offset": 20, - "slot": "3", - "type": "t_bool" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(AddressManager)5619": { - "encoding": "inplace", - "label": "contract AddressManager", - "numberOfBytes": "20" - }, - "t_enum(ProxyType)38430": { - "encoding": "inplace", - "label": "enum ProxyAdmin.ProxyType", - "numberOfBytes": "1" - }, - "t_mapping(t_address,t_enum(ProxyType)38430)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => enum ProxyAdmin.ProxyType)", - "numberOfBytes": "32", - "value": "t_enum(ProxyType)38430" - }, - "t_mapping(t_address,t_string_storage)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => string)", - "numberOfBytes": "32", - "value": "t_string_storage" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/SystemConfig.json b/packages/contracts-bedrock/deployments/goerli/SystemConfig.json deleted file mode 100644 index 05116a352b91..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/SystemConfig.json +++ /dev/null @@ -1,1197 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "version", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "enum SystemConfig.UpdateType", - "name": "updateType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "ConfigUpdate", - "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": "BATCH_INBOX_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L1_CROSS_DOMAIN_MESSENGER_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L1_ERC_721_BRIDGE_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L1_STANDARD_BRIDGE_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L2_OUTPUT_ORACLE_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMISM_PORTAL_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UNSAFE_BLOCK_SIGNER_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "batchInbox", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "batcherHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasLimit", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_overhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_scalar", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_batcherHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "_gasLimit", - "type": "uint64" - }, - { - "internalType": "address", - "name": "_unsafeBlockSigner", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "maxResourceLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "elasticityMultiplier", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "baseFeeMaxChangeDenominator", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "minimumBaseFee", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "systemTxMaxGas", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "maximumBaseFee", - "type": "uint128" - } - ], - "internalType": "struct ResourceMetering.ResourceConfig", - "name": "_config", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "_startBlock", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_batchInbox", - "type": "address" - }, - { - "components": [ - { - "internalType": "address", - "name": "l1CrossDomainMessenger", - "type": "address" - }, - { - "internalType": "address", - "name": "l1ERC721Bridge", - "type": "address" - }, - { - "internalType": "address", - "name": "l1StandardBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "l2OutputOracle", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismPortal", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismMintableERC20Factory", - "type": "address" - } - ], - "internalType": "struct SystemConfig.Addresses", - "name": "_addresses", - "type": "tuple" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1CrossDomainMessenger", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1ERC721Bridge", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1StandardBridge", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l2OutputOracle", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minimumGasLimit", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "optimismMintableERC20Factory", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "optimismPortal", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "overhead", - "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": [], - "name": "resourceConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "maxResourceLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "elasticityMultiplier", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "baseFeeMaxChangeDenominator", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "minimumBaseFee", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "systemTxMaxGas", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "maximumBaseFee", - "type": "uint128" - } - ], - "internalType": "struct ResourceMetering.ResourceConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "scalar", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_batcherHash", - "type": "bytes32" - } - ], - "name": "setBatcherHash", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_overhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_scalar", - "type": "uint256" - } - ], - "name": "setGasConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_gasLimit", - "type": "uint64" - } - ], - "name": "setGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "maxResourceLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "elasticityMultiplier", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "baseFeeMaxChangeDenominator", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "minimumBaseFee", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "systemTxMaxGas", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "maximumBaseFee", - "type": "uint128" - } - ], - "internalType": "struct ResourceMetering.ResourceConfig", - "name": "_config", - "type": "tuple" - } - ], - "name": "setResourceConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_unsafeBlockSigner", - "type": "address" - } - ], - "name": "setUnsafeBlockSigner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "startBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unsafeBlockSigner", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "address": "0x3b6090d4ba84B94C20a789436B9010F340AaaC70", - "args": [], - "bytecode": "0x60806040523480156200001157600080fd5b506040805160c080820183526001808352602080840182905260028486015260006060808601829052608080870183905260a08088018490528851968701895283875293860183905296850182905284018190529483018590528201849052620000909361dead93909283928392909183919060001990839062000096565b62000ccc565b600054600390610100900460ff16158015620000b9575060005460ff8083169116105b620001225760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805461ffff191660ff831617610100179055620001406200043a565b6200014b8b620004a2565b620001568862000521565b620001628a8a62000573565b6200016d87620005d7565b620001788662000674565b620001be620001a960017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59862000ba9565b60001b84620006dc60201b62000d211760201c565b62000208620001ef60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063762000ba9565b60001b8360000151620006dc60201b62000d211760201c565b620002526200023960017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a862000ba9565b60001b8360200151620006dc60201b62000d211760201c565b6200029c6200028360017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637762000ba9565b60001b8360400151620006dc60201b62000d211760201c565b620002e6620002cd60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a687181662000ba9565b60001b8360600151620006dc60201b62000d211760201c565b620003306200031760017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad62000ba9565b60001b8360800151620006dc60201b62000d211760201c565b6200037a6200036160017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d62000ba9565b60001b8360a00151620006dc60201b62000d211760201c565b6200038584620006e0565b62000390856200070d565b6200039a62000a51565b6001600160401b0316876001600160401b03161015620003ec5760405162461bcd60e51b815260206004820152601f60248201526000805160206200281f833981519152604482015260640162000119565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050505050565b600054610100900460ff16620004965760405162461bcd60e51b815260206004820152602b60248201526000805160206200285f83398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000119565b620004a062000a7e565b565b620004ac62000ae5565b6001600160a01b038116620005135760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000119565b6200051e8162000b41565b50565b60678190556040805160208082018490528251808303909101815290820190915260005b60006000805160206200283f8339815191528360405162000567919062000bc3565b60405180910390a35050565b60658290556066819055604080516020810184905290810182905260009060600160408051601f198184030181529190529050600160006000805160206200283f83398151915283604051620005ca919062000bc3565b60405180910390a3505050565b620005e162000a51565b6001600160401b0316816001600160401b03161015620006335760405162461bcd60e51b815260206004820152601f60248201526000805160206200281f833981519152604482015260640162000119565b606880546001600160401b0319166001600160401b038316908117909155604080516020808201939093528151808203909301835281019052600262000545565b620006ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0882620006dc60201b62000d211760201c565b604080516001600160a01b03831660208201526000910160408051601f198184030181529190529050600362000545565b9055565b8015801590620006f05750606a54155b15620006fb57606a55565b606a546000036200051e5743606a5550565b8060a001516001600160801b0316816060015163ffffffff1611156200079c5760405162461bcd60e51b815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d617820626173650000000000000000000000606482015260840162000119565b6001816040015160ff16116200080d5760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201526e65206c6172676572207468616e203160881b606482015260840162000119565b606854608082015182516001600160401b03909216916200082f919062000c1b565b63ffffffff161115620008745760405162461bcd60e51b815260206004820152601f60248201526000805160206200281f833981519152604482015260640162000119565b6000816020015160ff1611620008e55760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201526e06965722063616e6e6f74206265203608c1b606482015260840162000119565b8051602082015163ffffffff82169160ff909116906200090790829062000c46565b62000913919062000c78565b63ffffffff16146200098e5760405162461bcd60e51b815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d6974000000000000000000606482015260840162000119565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff96871664ffffffffff199095169490941764010000000060ff948516021764ffffffffff60281b191665010000000000939092169290920263ffffffff60301b19161766010000000000009185169190910217600160501b600160f01b0319166a01000000000000000000009390941692909202600160701b600160f01b03191692909217600160701b6001600160801b0390921691909102179055565b60695460009062000a799063ffffffff6a010000000000000000000082048116911662000ca7565b905090565b600054610100900460ff1662000ada5760405162461bcd60e51b815260206004820152602b60248201526000805160206200285f83398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000119565b620004a03362000b41565b6033546001600160a01b03163314620004a05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000119565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052601160045260246000fd5b60008282101562000bbe5762000bbe62000b93565b500390565b600060208083528351808285015260005b8181101562000bf25785810183015185820160400152820162000bd4565b8181111562000c05576000604083870101525b50601f01601f1916929092016040019392505050565b600063ffffffff80831681851680830382111562000c3d5762000c3d62000b93565b01949350505050565b600063ffffffff8084168062000c6c57634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b600063ffffffff8083168185168183048111821515161562000c9e5762000c9e62000b93565b02949350505050565b60006001600160401b0382811684821680830382111562000c3d5762000c3d62000b93565b611b438062000cdc6000396000f3fe608060405234801561001057600080fd5b50600436106102265760003560e01c8063935f029e1161012a578063cc731b02116100bd578063f45e65d81161008c578063f8c68de011610071578063f8c68de014610575578063fd32aa0f1461057d578063ffa1ad741461058557600080fd5b8063f45e65d814610558578063f68016b71461056157600080fd5b8063cc731b0214610400578063dac6e63a14610534578063e81b2c6d1461053c578063f2fde38b1461054557600080fd5b8063bc49ce5f116100f9578063bc49ce5f146103ca578063c4e8ddfa146103d2578063c71973f6146103da578063c9b26f61146103ed57600080fd5b8063935f029e146103945780639b7d7f0a146103a7578063a7119869146103af578063b40a817c146103b757600080fd5b80634add321d116101bd57806354fd4d501161018c57806361d157681161017157806361d1576814610366578063715018a61461036e5780638da5cb5b1461037657600080fd5b806354fd4d50146103155780635d73369c1461035e57600080fd5b80634add321d146102b25780634d9f1559146102d35780634f16540b146102db5780635228a6ac1461030257600080fd5b806318d13918116101f957806318d139181461028457806319f5cea8146102995780631fd19ee1146102a157806348cd4cb1146102a957600080fd5b806306c926571461022b578063078f29cf146102465780630a49cb03146102735780630c18c1621461027b575b600080fd5b61023361058d565b6040519081526020015b60405180910390f35b61024e6105bb565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161023d565b61024e6105f4565b61023360655481565b610297610292366004611677565b610624565b005b610233610638565b61024e610663565b610233606a5481565b6102ba61068d565b60405167ffffffffffffffff909116815260200161023d565b61024e6106b3565b6102337f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b610297610310366004611807565b6106e3565b6103516040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b60405161023d91906119aa565b610233610a79565b610233610aa4565b610297610acf565b60335473ffffffffffffffffffffffffffffffffffffffff1661024e565b6102976103a23660046119bd565b610ae3565b61024e610af9565b61024e610b29565b6102976103c53660046119df565b610b59565b610233610b6a565b61024e610b95565b6102976103e83660046119fa565b610bc5565b6102976103fb366004611a16565b610bd6565b6104c46040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b60405161023d9190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61024e610be7565b61023360675481565b610297610553366004611677565b610c17565b61023360665481565b6068546102ba9067ffffffffffffffff1681565b610233610ccb565b610233610cf6565b610233600081565b6105b860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611a5e565b81565b60006105ef6105eb60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611a5e565b5490565b905090565b60006105ef6105eb60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611a5e565b61062c610d25565b61063581610da6565b50565b6105b860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611a5e565b60006105ef7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b6069546000906105ef9063ffffffff6a0100000000000000000000820481169116611a75565b60006105ef6105eb60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611a5e565b600054600390610100900460ff16158015610705575060005460ff8083169116105b610796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff8316176101001790556107cf610e63565b6107d88b610c17565b6107e188610f02565b6107eb8a8a610f2a565b6107f487610fbb565b6107fd86610da6565b61083061082b60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611a5e565b849055565b61086461085e60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611a5e565b83519055565b61089b61089260017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611a5e565b60208401519055565b6108d26108c960017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611a5e565b60408401519055565b61090961090060017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611a5e565b60608401519055565b61094061093760017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611a5e565b60808401519055565b61097761096e60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611a5e565b60a08401519055565b61098084611099565b610989856110c3565b61099161068d565b67ffffffffffffffff168767ffffffffffffffff161015610a0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640161078d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050505050565b6105b860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611a5e565b6105b860017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611a5e565b610ad7610d25565b610ae16000611537565b565b610aeb610d25565b610af58282610f2a565b5050565b60006105ef6105eb60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611a5e565b60006105ef6105eb60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611a5e565b610b61610d25565b61063581610fbb565b6105b860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611a5e565b60006105ef6105eb60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611a5e565b610bcd610d25565b610635816110c3565b610bde610d25565b61063581610f02565b60006105ef6105eb60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611a5e565b610c1f610d25565b73ffffffffffffffffffffffffffffffffffffffff8116610cc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161078d565b61063581611537565b6105b860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611a5e565b6105b860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611a5e565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ae1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161078d565b610dcf7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610e5791906119aa565b60405180910390a35050565b600054610100900460ff16610efa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161078d565b610ae16115ae565b6067819055604080516020808201849052825180830390910181529082019091526000610e26565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610fae91906119aa565b60405180910390a3505050565b610fc361068d565b67ffffffffffffffff168167ffffffffffffffff161015611040576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640161078d565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610e26565b80158015906110a85750606a54155b156110b257606a55565b606a546000036106355743606a5550565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611173576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d617820626173650000000000000000000000606482015260840161078d565b6001816040015160ff161161120a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e20310000000000000000000000000000000000606482015260840161078d565b6068546080820151825167ffffffffffffffff9092169161122b9190611aa1565b63ffffffff161115611299576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640161078d565b6000816020015160ff1611611330576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f7420626520300000000000000000000000000000000000606482015260840161078d565b8051602082015163ffffffff82169160ff90911690611350908290611ac0565b61135a9190611b0a565b63ffffffff16146113ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d6974000000000000000000606482015260840161078d565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611645576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161078d565b610ae133611537565b803573ffffffffffffffffffffffffffffffffffffffff8116811461167257600080fd5b919050565b60006020828403121561168957600080fd5b6116928261164e565b9392505050565b803567ffffffffffffffff8116811461167257600080fd5b60405160c0810167ffffffffffffffff811182821017156116fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290565b803563ffffffff8116811461167257600080fd5b803560ff8116811461167257600080fd5b600060c0828403121561173857600080fd5b60405160c0810181811067ffffffffffffffff82111715611782577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290508061179183611701565b815261179f60208401611715565b60208201526117b060408401611715565b60408201526117c160608401611701565b60608201526117d260808401611701565b608082015260a08301356fffffffffffffffffffffffffffffffff811681146117fa57600080fd5b60a0919091015292915050565b6000806000806000806000806000808a8c0361028081121561182857600080fd5b6118318c61164e565b9a5060208c0135995060408c0135985060608c0135975061185460808d01611699565b965061186260a08d0161164e565b95506118718d60c08e01611726565b94506101808c013593506118886101a08d0161164e565b925060c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe40820112156118ba57600080fd5b506118c36116b1565b6118d06101c08d0161164e565b81526118df6101e08d0161164e565b60208201526118f16102008d0161164e565b60408201526119036102208d0161164e565b60608201526119156102408d0161164e565b60808201526119276102608d0161164e565b60a0820152809150509295989b9194979a5092959850565b6000815180845260005b8181101561196557602081850181015186830182015201611949565b81811115611977576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611692602083018461193f565b600080604083850312156119d057600080fd5b50508035926020909101359150565b6000602082840312156119f157600080fd5b61169282611699565b600060c08284031215611a0c57600080fd5b6116928383611726565b600060208284031215611a2857600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611a7057611a70611a2f565b500390565b600067ffffffffffffffff808316818516808303821115611a9857611a98611a2f565b01949350505050565b600063ffffffff808316818516808303821115611a9857611a98611a2f565b600063ffffffff80841680611afe577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff80831681851681830481118215151615611b2d57611b2d611a2f565b0294935050505056fea164736f6c634300080f000a53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77001d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102265760003560e01c8063935f029e1161012a578063cc731b02116100bd578063f45e65d81161008c578063f8c68de011610071578063f8c68de014610575578063fd32aa0f1461057d578063ffa1ad741461058557600080fd5b8063f45e65d814610558578063f68016b71461056157600080fd5b8063cc731b0214610400578063dac6e63a14610534578063e81b2c6d1461053c578063f2fde38b1461054557600080fd5b8063bc49ce5f116100f9578063bc49ce5f146103ca578063c4e8ddfa146103d2578063c71973f6146103da578063c9b26f61146103ed57600080fd5b8063935f029e146103945780639b7d7f0a146103a7578063a7119869146103af578063b40a817c146103b757600080fd5b80634add321d116101bd57806354fd4d501161018c57806361d157681161017157806361d1576814610366578063715018a61461036e5780638da5cb5b1461037657600080fd5b806354fd4d50146103155780635d73369c1461035e57600080fd5b80634add321d146102b25780634d9f1559146102d35780634f16540b146102db5780635228a6ac1461030257600080fd5b806318d13918116101f957806318d139181461028457806319f5cea8146102995780631fd19ee1146102a157806348cd4cb1146102a957600080fd5b806306c926571461022b578063078f29cf146102465780630a49cb03146102735780630c18c1621461027b575b600080fd5b61023361058d565b6040519081526020015b60405180910390f35b61024e6105bb565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161023d565b61024e6105f4565b61023360655481565b610297610292366004611677565b610624565b005b610233610638565b61024e610663565b610233606a5481565b6102ba61068d565b60405167ffffffffffffffff909116815260200161023d565b61024e6106b3565b6102337f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b610297610310366004611807565b6106e3565b6103516040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b60405161023d91906119aa565b610233610a79565b610233610aa4565b610297610acf565b60335473ffffffffffffffffffffffffffffffffffffffff1661024e565b6102976103a23660046119bd565b610ae3565b61024e610af9565b61024e610b29565b6102976103c53660046119df565b610b59565b610233610b6a565b61024e610b95565b6102976103e83660046119fa565b610bc5565b6102976103fb366004611a16565b610bd6565b6104c46040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b60405161023d9190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61024e610be7565b61023360675481565b610297610553366004611677565b610c17565b61023360665481565b6068546102ba9067ffffffffffffffff1681565b610233610ccb565b610233610cf6565b610233600081565b6105b860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611a5e565b81565b60006105ef6105eb60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611a5e565b5490565b905090565b60006105ef6105eb60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611a5e565b61062c610d25565b61063581610da6565b50565b6105b860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611a5e565b60006105ef7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b6069546000906105ef9063ffffffff6a0100000000000000000000820481169116611a75565b60006105ef6105eb60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611a5e565b600054600390610100900460ff16158015610705575060005460ff8083169116105b610796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff8316176101001790556107cf610e63565b6107d88b610c17565b6107e188610f02565b6107eb8a8a610f2a565b6107f487610fbb565b6107fd86610da6565b61083061082b60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611a5e565b849055565b61086461085e60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611a5e565b83519055565b61089b61089260017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611a5e565b60208401519055565b6108d26108c960017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611a5e565b60408401519055565b61090961090060017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611a5e565b60608401519055565b61094061093760017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611a5e565b60808401519055565b61097761096e60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611a5e565b60a08401519055565b61098084611099565b610989856110c3565b61099161068d565b67ffffffffffffffff168767ffffffffffffffff161015610a0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640161078d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050505050565b6105b860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611a5e565b6105b860017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611a5e565b610ad7610d25565b610ae16000611537565b565b610aeb610d25565b610af58282610f2a565b5050565b60006105ef6105eb60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611a5e565b60006105ef6105eb60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611a5e565b610b61610d25565b61063581610fbb565b6105b860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611a5e565b60006105ef6105eb60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611a5e565b610bcd610d25565b610635816110c3565b610bde610d25565b61063581610f02565b60006105ef6105eb60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611a5e565b610c1f610d25565b73ffffffffffffffffffffffffffffffffffffffff8116610cc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161078d565b61063581611537565b6105b860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611a5e565b6105b860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611a5e565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ae1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161078d565b610dcf7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610e5791906119aa565b60405180910390a35050565b600054610100900460ff16610efa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161078d565b610ae16115ae565b6067819055604080516020808201849052825180830390910181529082019091526000610e26565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610fae91906119aa565b60405180910390a3505050565b610fc361068d565b67ffffffffffffffff168167ffffffffffffffff161015611040576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640161078d565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610e26565b80158015906110a85750606a54155b156110b257606a55565b606a546000036106355743606a5550565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611173576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d617820626173650000000000000000000000606482015260840161078d565b6001816040015160ff161161120a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e20310000000000000000000000000000000000606482015260840161078d565b6068546080820151825167ffffffffffffffff9092169161122b9190611aa1565b63ffffffff161115611299576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640161078d565b6000816020015160ff1611611330576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f7420626520300000000000000000000000000000000000606482015260840161078d565b8051602082015163ffffffff82169160ff90911690611350908290611ac0565b61135a9190611b0a565b63ffffffff16146113ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d6974000000000000000000606482015260840161078d565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611645576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161078d565b610ae133611537565b803573ffffffffffffffffffffffffffffffffffffffff8116811461167257600080fd5b919050565b60006020828403121561168957600080fd5b6116928261164e565b9392505050565b803567ffffffffffffffff8116811461167257600080fd5b60405160c0810167ffffffffffffffff811182821017156116fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290565b803563ffffffff8116811461167257600080fd5b803560ff8116811461167257600080fd5b600060c0828403121561173857600080fd5b60405160c0810181811067ffffffffffffffff82111715611782577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290508061179183611701565b815261179f60208401611715565b60208201526117b060408401611715565b60408201526117c160608401611701565b60608201526117d260808401611701565b608082015260a08301356fffffffffffffffffffffffffffffffff811681146117fa57600080fd5b60a0919091015292915050565b6000806000806000806000806000808a8c0361028081121561182857600080fd5b6118318c61164e565b9a5060208c0135995060408c0135985060608c0135975061185460808d01611699565b965061186260a08d0161164e565b95506118718d60c08e01611726565b94506101808c013593506118886101a08d0161164e565b925060c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe40820112156118ba57600080fd5b506118c36116b1565b6118d06101c08d0161164e565b81526118df6101e08d0161164e565b60208201526118f16102008d0161164e565b60408201526119036102208d0161164e565b60608201526119156102408d0161164e565b60808201526119276102608d0161164e565b60a0820152809150509295989b9194979a5092959850565b6000815180845260005b8181101561196557602081850181015186830182015201611949565b81811115611977576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611692602083018461193f565b600080604083850312156119d057600080fd5b50508035926020909101359150565b6000602082840312156119f157600080fd5b61169282611699565b600060c08284031215611a0c57600080fd5b6116928383611726565b600060208284031215611a2857600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611a7057611a70611a2f565b500390565b600067ffffffffffffffff808316818516808303821115611a9857611a98611a2f565b01949350505050565b600063ffffffff808316818516808303821115611a9857611a98611a2f565b600063ffffffff80841680611afe577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff80831681851681830481118215151615611b2d57611b2d611a2f565b0294935050505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128),uint256,address,(address,address,address,address,address,address))": { - "params": { - "_addresses": "Set of L1 contract addresses. These should be the proxies.", - "_batchInbox": "Batch inbox address. An identifier for the op-node to find canonical data.", - "_batcherHash": "Initial batcher hash.", - "_config": "Initial ResourceConfig.", - "_gasLimit": "Initial gas limit.", - "_overhead": "Initial overhead value.", - "_owner": "Initial owner of the contract.", - "_scalar": "Initial scalar value.", - "_startBlock": "Starting block for the op-node to search for logs from. Contracts that were deployed before this field existed need to have this field set manually via an override. Newly deployed contracts should set this value to uint256(0).", - "_unsafeBlockSigner": "Initial unsafe block signer address." - } - }, - "minimumGasLimit()": { - "returns": { - "_0": "uint64 Minimum gas limit." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "resourceConfig()": { - "returns": { - "_0": "ResourceConfig" - } - }, - "setBatcherHash(bytes32)": { - "params": { - "_batcherHash": "New batcher hash." - } - }, - "setGasConfig(uint256,uint256)": { - "params": { - "_overhead": "New overhead value.", - "_scalar": "New scalar value." - } - }, - "setGasLimit(uint64)": { - "params": { - "_gasLimit": "New gas limit." - } - }, - "setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))": { - "params": { - "_config": "The new resource config values." - } - }, - "setUnsafeBlockSigner(address)": { - "params": { - "_unsafeBlockSigner": "New unsafe block signer address." - } - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - }, - "unsafeBlockSigner()": { - "returns": { - "addr_": "Address of the unsafe block signer." - } - } - }, - "events": { - "ConfigUpdate(uint256,uint8,bytes)": { - "params": { - "data": "Encoded update data.", - "updateType": "Type of update.", - "version": "SystemConfig version." - } - } - }, - "title": "SystemConfig" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"enum SystemConfig.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ConfigUpdate\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"BATCH_INBOX_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L1_CROSS_DOMAIN_MESSENGER_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L1_ERC_721_BRIDGE_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L1_STANDARD_BRIDGE_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L2_OUTPUT_ORACLE_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OPTIMISM_PORTAL_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"UNSAFE_BLOCK_SIGNER_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"batchInbox\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"batcherHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"gasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"},{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]},{\"internalType\":\"uint256\",\"name\":\"_startBlock\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_batchInbox\",\"type\":\"address\"},{\"internalType\":\"struct SystemConfig.Addresses\",\"name\":\"_addresses\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"address\",\"name\":\"l1CrossDomainMessenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1ERC721Bridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1StandardBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l2OutputOracle\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"optimismPortal\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"optimismMintableERC20Factory\",\"type\":\"address\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l1CrossDomainMessenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l1ERC721Bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l1StandardBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2OutputOracle\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"minimumGasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"optimismMintableERC20Factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"optimismPortal\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"overhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"resourceConfig\",\"outputs\":[{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"scalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setBatcherHash\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setGasConfig\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setGasLimit\"},{\"inputs\":[{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setResourceConfig\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setUnsafeBlockSigner\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"startBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"unsafeBlockSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128),uint256,address,(address,address,address,address,address,address))\":{\"params\":{\"_addresses\":\"Set of L1 contract addresses. These should be the proxies.\",\"_batchInbox\":\"Batch inbox address. An identifier for the op-node to find canonical data.\",\"_batcherHash\":\"Initial batcher hash.\",\"_config\":\"Initial ResourceConfig.\",\"_gasLimit\":\"Initial gas limit.\",\"_overhead\":\"Initial overhead value.\",\"_owner\":\"Initial owner of the contract.\",\"_scalar\":\"Initial scalar value.\",\"_startBlock\":\"Starting block for the op-node to search for logs from. Contracts that were deployed before this field existed need to have this field set manually via an override. Newly deployed contracts should set this value to uint256(0).\",\"_unsafeBlockSigner\":\"Initial unsafe block signer address.\"}},\"minimumGasLimit()\":{\"returns\":{\"_0\":\"uint64 Minimum gas limit.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"resourceConfig()\":{\"returns\":{\"_0\":\"ResourceConfig\"}},\"setBatcherHash(bytes32)\":{\"params\":{\"_batcherHash\":\"New batcher hash.\"}},\"setGasConfig(uint256,uint256)\":{\"params\":{\"_overhead\":\"New overhead value.\",\"_scalar\":\"New scalar value.\"}},\"setGasLimit(uint64)\":{\"params\":{\"_gasLimit\":\"New gas limit.\"}},\"setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))\":{\"params\":{\"_config\":\"The new resource config values.\"}},\"setUnsafeBlockSigner(address)\":{\"params\":{\"_unsafeBlockSigner\":\"New unsafe block signer address.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsafeBlockSigner()\":{\"returns\":{\"addr_\":\"Address of the unsafe block signer.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"BATCH_INBOX_SLOT()\":{\"notice\":\"Storage slot that the batch inbox address is stored at.\"},\"L1_CROSS_DOMAIN_MESSENGER_SLOT()\":{\"notice\":\"Storage slot that the L1CrossDomainMessenger address is stored at.\"},\"L1_ERC_721_BRIDGE_SLOT()\":{\"notice\":\"Storage slot that the L1ERC721Bridge address is stored at.\"},\"L1_STANDARD_BRIDGE_SLOT()\":{\"notice\":\"Storage slot that the L1StandardBridge address is stored at.\"},\"L2_OUTPUT_ORACLE_SLOT()\":{\"notice\":\"Storage slot that the L2OutputOracle address is stored at.\"},\"OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT()\":{\"notice\":\"Storage slot that the OptimismMintableERC20Factory address is stored at.\"},\"OPTIMISM_PORTAL_SLOT()\":{\"notice\":\"Storage slot that the OptimismPortal address is stored at.\"},\"UNSAFE_BLOCK_SIGNER_SLOT()\":{\"notice\":\"Storage slot that the unsafe block signer is stored at. Storing it at this deterministic storage slot allows for decoupling the storage layout from the way that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value.\"},\"VERSION()\":{\"notice\":\"Version identifier, used for upgrades.\"},\"batchInbox()\":{\"notice\":\"Getter for the BatchInbox address.\"},\"batcherHash()\":{\"notice\":\"Identifier for the batcher. For version 1 of this configuration, this is represented as an address left-padded with zeros to 32 bytes.\"},\"constructor\":{\"notice\":\"Constructs the SystemConfig contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)`\"},\"gasLimit()\":{\"notice\":\"L2 block gas limit.\"},\"initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128),uint256,address,(address,address,address,address,address,address))\":{\"notice\":\"Initializer. The resource config must be set before the require check.\"},\"l1CrossDomainMessenger()\":{\"notice\":\"Getter for the L1CrossDomainMessenger address.\"},\"l1ERC721Bridge()\":{\"notice\":\"Getter for the L1ERC721Bridge address.\"},\"l1StandardBridge()\":{\"notice\":\"Getter for the L1StandardBridge address.\"},\"l2OutputOracle()\":{\"notice\":\"Getter for the L2OutputOracle address.\"},\"minimumGasLimit()\":{\"notice\":\"Returns the minimum L2 gas limit that can be safely set for the system to operate. The L2 gas limit must be larger than or equal to the amount of gas that is allocated for deposits per block plus the amount of gas that is allocated for the system transaction. This function is used to determine if changes to parameters are safe.\"},\"optimismMintableERC20Factory()\":{\"notice\":\"Getter for the OptimismMintableERC20Factory address.\"},\"optimismPortal()\":{\"notice\":\"Getter for the OptimismPortal address.\"},\"overhead()\":{\"notice\":\"Fixed L2 gas overhead. Used as part of the L2 fee calculation.\"},\"resourceConfig()\":{\"notice\":\"A getter for the resource config. Ensures that the struct is returned instead of a tuple.\"},\"scalar()\":{\"notice\":\"Dynamic L2 gas overhead. Used as part of the L2 fee calculation.\"},\"setBatcherHash(bytes32)\":{\"notice\":\"Updates the batcher hash. Can only be called by the owner.\"},\"setGasConfig(uint256,uint256)\":{\"notice\":\"Updates gas config. Can only be called by the owner.\"},\"setGasLimit(uint64)\":{\"notice\":\"Updates the L2 gas limit. Can only be called by the owner.\"},\"setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))\":{\"notice\":\"An external setter for the resource config. In the future, this method may emit an event that the `op-node` picks up for when the resource config is changed.\"},\"setUnsafeBlockSigner(address)\":{\"notice\":\"Updates the unsafe block signer address. Can only be called by the owner.\"},\"startBlock()\":{\"notice\":\"The block at which the op-node can start searching for logs from.\"},\"unsafeBlockSigner()\":{\"notice\":\"High level getter for the unsafe block signer address. Unsafe blocks can be propagated across the p2p network if they are signed by the key corresponding to this address.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/SystemConfig.sol\":\"SystemConfig\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x4bbbc7868e948c44f29285a69383e93251a0c330a67929fb72def01cec060d4e\",\"urls\":[\"bzz-raw://1e7ea2f8b3d49bee9c753f107ede6eda93b2cc0e34d0643fa14ebbb26c19e71b\",\"dweb:/ipfs/QmRP81F8FRVXVZs6u2f2poEPDnbFZhNwNYxHgCVEhGpEmB\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 6, - "receipt": { - "transactionHash": "0x4bfbbbc994d0ebd60a667d5f00818c6e5ce02148713734796ddc2918070d59ed", - "transactionIndex": "0x3", - "blockHash": "0x28d3a10e81b2ea28788ad35a3dcb922b92a2d9b634d551eb1d0eb9a5be84371c", - "blockNumber": "0x95b3e3", - "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "cumulativeGasUsed": "0x2288bb", - "gasUsed": "0x1ae55a", - "contractAddress": "0x3b6090d4ba84B94C20a789436B9010F340AaaC70", - "logs": [ - { - "address": "0x3b6090d4ba84B94C20a789436B9010F340AaaC70", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c" - ], - "data": "0x", - "blockHash": "0x28d3a10e81b2ea28788ad35a3dcb922b92a2d9b634d551eb1d0eb9a5be84371c", - "blockNumber": "0x95b3e3", - "transactionHash": "0x4bfbbbc994d0ebd60a667d5f00818c6e5ce02148713734796ddc2918070d59ed", - "transactionIndex": "0x3", - "logIndex": "0x0", - "removed": false - }, - { - "address": "0x3b6090d4ba84B94C20a789436B9010F340AaaC70", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "0x000000000000000000000000000000000000000000000000000000000000dead" - ], - "data": "0x", - "blockHash": "0x28d3a10e81b2ea28788ad35a3dcb922b92a2d9b634d551eb1d0eb9a5be84371c", - "blockNumber": "0x95b3e3", - "transactionHash": "0x4bfbbbc994d0ebd60a667d5f00818c6e5ce02148713734796ddc2918070d59ed", - "transactionIndex": "0x3", - "logIndex": "0x1", - "removed": false - }, - { - "address": "0x3b6090d4ba84B94C20a789436B9010F340AaaC70", - "topics": [ - "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x28d3a10e81b2ea28788ad35a3dcb922b92a2d9b634d551eb1d0eb9a5be84371c", - "blockNumber": "0x95b3e3", - "transactionHash": "0x4bfbbbc994d0ebd60a667d5f00818c6e5ce02148713734796ddc2918070d59ed", - "transactionIndex": "0x3", - "logIndex": "0x2", - "removed": false - }, - { - "address": "0x3b6090d4ba84B94C20a789436B9010F340AaaC70", - "topics": [ - "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x28d3a10e81b2ea28788ad35a3dcb922b92a2d9b634d551eb1d0eb9a5be84371c", - "blockNumber": "0x95b3e3", - "transactionHash": "0x4bfbbbc994d0ebd60a667d5f00818c6e5ce02148713734796ddc2918070d59ed", - "transactionIndex": "0x3", - "logIndex": "0x3", - "removed": false - }, - { - "address": "0x3b6090d4ba84B94C20a789436B9010F340AaaC70", - "topics": [ - "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000002" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001", - "blockHash": "0x28d3a10e81b2ea28788ad35a3dcb922b92a2d9b634d551eb1d0eb9a5be84371c", - "blockNumber": "0x95b3e3", - "transactionHash": "0x4bfbbbc994d0ebd60a667d5f00818c6e5ce02148713734796ddc2918070d59ed", - "transactionIndex": "0x3", - "logIndex": "0x4", - "removed": false - }, - { - "address": "0x3b6090d4ba84B94C20a789436B9010F340AaaC70", - "topics": [ - "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000003" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x28d3a10e81b2ea28788ad35a3dcb922b92a2d9b634d551eb1d0eb9a5be84371c", - "blockNumber": "0x95b3e3", - "transactionHash": "0x4bfbbbc994d0ebd60a667d5f00818c6e5ce02148713734796ddc2918070d59ed", - "transactionIndex": "0x3", - "logIndex": "0x5", - "removed": false - }, - { - "address": "0x3b6090d4ba84B94C20a789436B9010F340AaaC70", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000003", - "blockHash": "0x28d3a10e81b2ea28788ad35a3dcb922b92a2d9b634d551eb1d0eb9a5be84371c", - "blockNumber": "0x95b3e3", - "transactionHash": "0x4bfbbbc994d0ebd60a667d5f00818c6e5ce02148713734796ddc2918070d59ed", - "transactionIndex": "0x3", - "logIndex": "0x6", - "removed": false - } - ], - "status": "0x1", - "logsBloom": "0x04000000000010000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000020008000000000000040000000000000000000000100000000000000001000000040000000000000000000000000000020000000000000000000800000000000000002000000000000000400000000000000000000004040000000000000000001080000000000000000000000000000001000000000100000400000000000000800000000000000000400000000400000000000000000000040000000000000000000000000000000060000000000000000008000000000000000080000000008000000000008000000000", - "type": "0x2", - "effectiveGasPrice": "0xb2d05e07" - }, - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 29536, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 29539, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 31067, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 29408, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 29528, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 61640, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "overhead", - "offset": 0, - "slot": "101", - "type": "t_uint256" - }, - { - "astId": 61643, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "scalar", - "offset": 0, - "slot": "102", - "type": "t_uint256" - }, - { - "astId": 61646, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "batcherHash", - "offset": 0, - "slot": "103", - "type": "t_bytes32" - }, - { - "astId": 61649, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "gasLimit", - "offset": 0, - "slot": "104", - "type": "t_uint64" - }, - { - "astId": 61653, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "_resourceConfig", - "offset": 0, - "slot": "105", - "type": "t_struct(ResourceConfig)61178_storage" - }, - { - "astId": 61666, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "startBlock", - "offset": 0, - "slot": "106", - "type": "t_uint256" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_array(t_uint256)50_storage": { - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_struct(ResourceConfig)61178_storage": { - "encoding": "inplace", - "label": "struct ResourceMetering.ResourceConfig", - "numberOfBytes": "32", - "members": [ - { - "astId": 61167, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "maxResourceLimit", - "offset": 0, - "slot": "0", - "type": "t_uint32" - }, - { - "astId": 61169, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "elasticityMultiplier", - "offset": 4, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 61171, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "baseFeeMaxChangeDenominator", - "offset": 5, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 61173, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "minimumBaseFee", - "offset": 6, - "slot": "0", - "type": "t_uint32" - }, - { - "astId": 61175, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "systemTxMaxGas", - "offset": 10, - "slot": "0", - "type": "t_uint32" - }, - { - "astId": 61177, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "maximumBaseFee", - "offset": 14, - "slot": "0", - "type": "t_uint128" - } - ] - }, - "t_uint128": { - "encoding": "inplace", - "label": "uint128", - "numberOfBytes": "16" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint32": { - "encoding": "inplace", - "label": "uint32", - "numberOfBytes": "4" - }, - "t_uint64": { - "encoding": "inplace", - "label": "uint64", - "numberOfBytes": "8" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x4bfbbbc994d0ebd60a667d5f00818c6e5ce02148713734796ddc2918070d59ed", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "BATCH_INBOX_SLOT()": { - "notice": "Storage slot that the batch inbox address is stored at." - }, - "L1_CROSS_DOMAIN_MESSENGER_SLOT()": { - "notice": "Storage slot that the L1CrossDomainMessenger address is stored at." - }, - "L1_ERC_721_BRIDGE_SLOT()": { - "notice": "Storage slot that the L1ERC721Bridge address is stored at." - }, - "L1_STANDARD_BRIDGE_SLOT()": { - "notice": "Storage slot that the L1StandardBridge address is stored at." - }, - "L2_OUTPUT_ORACLE_SLOT()": { - "notice": "Storage slot that the L2OutputOracle address is stored at." - }, - "OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT()": { - "notice": "Storage slot that the OptimismMintableERC20Factory address is stored at." - }, - "OPTIMISM_PORTAL_SLOT()": { - "notice": "Storage slot that the OptimismPortal address is stored at." - }, - "UNSAFE_BLOCK_SIGNER_SLOT()": { - "notice": "Storage slot that the unsafe block signer is stored at. Storing it at this deterministic storage slot allows for decoupling the storage layout from the way that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value." - }, - "VERSION()": { - "notice": "Version identifier, used for upgrades." - }, - "batchInbox()": { - "notice": "Getter for the BatchInbox address." - }, - "batcherHash()": { - "notice": "Identifier for the batcher. For version 1 of this configuration, this is represented as an address left-padded with zeros to 32 bytes." - }, - "constructor": { - "notice": "Constructs the SystemConfig contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)`" - }, - "gasLimit()": { - "notice": "L2 block gas limit." - }, - "initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128),uint256,address,(address,address,address,address,address,address))": { - "notice": "Initializer. The resource config must be set before the require check." - }, - "l1CrossDomainMessenger()": { - "notice": "Getter for the L1CrossDomainMessenger address." - }, - "l1ERC721Bridge()": { - "notice": "Getter for the L1ERC721Bridge address." - }, - "l1StandardBridge()": { - "notice": "Getter for the L1StandardBridge address." - }, - "l2OutputOracle()": { - "notice": "Getter for the L2OutputOracle address." - }, - "minimumGasLimit()": { - "notice": "Returns the minimum L2 gas limit that can be safely set for the system to operate. The L2 gas limit must be larger than or equal to the amount of gas that is allocated for deposits per block plus the amount of gas that is allocated for the system transaction. This function is used to determine if changes to parameters are safe." - }, - "optimismMintableERC20Factory()": { - "notice": "Getter for the OptimismMintableERC20Factory address." - }, - "optimismPortal()": { - "notice": "Getter for the OptimismPortal address." - }, - "overhead()": { - "notice": "Fixed L2 gas overhead. Used as part of the L2 fee calculation." - }, - "resourceConfig()": { - "notice": "A getter for the resource config. Ensures that the struct is returned instead of a tuple." - }, - "scalar()": { - "notice": "Dynamic L2 gas overhead. Used as part of the L2 fee calculation." - }, - "setBatcherHash(bytes32)": { - "notice": "Updates the batcher hash. Can only be called by the owner." - }, - "setGasConfig(uint256,uint256)": { - "notice": "Updates gas config. Can only be called by the owner." - }, - "setGasLimit(uint64)": { - "notice": "Updates the L2 gas limit. Can only be called by the owner." - }, - "setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))": { - "notice": "An external setter for the resource config. In the future, this method may emit an event that the `op-node` picks up for when the resource config is changed." - }, - "setUnsafeBlockSigner(address)": { - "notice": "Updates the unsafe block signer address. Can only be called by the owner." - }, - "startBlock()": { - "notice": "The block at which the op-node can start searching for logs from." - }, - "unsafeBlockSigner()": { - "notice": "High level getter for the unsafe block signer address. Unsafe blocks can be propagated across the p2p network if they are signed by the key corresponding to this address." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "ConfigUpdate(uint256,uint8,bytes)": { - "notice": "Emitted when configuration is updated." - } - }, - "notice": "The SystemConfig contract is used to manage configuration of an Optimism network. All configuration is stored on L1 and picked up by L2 as part of the derviation of the L2 chain." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/SystemConfigProxy.json b/packages/contracts-bedrock/deployments/goerli/SystemConfigProxy.json deleted file mode 100644 index 2e8d067d4c45..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/SystemConfigProxy.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "address": "0xAe851f927Ee40dE99aaBb7461C00f9622ab91d60", - "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": "0x1548358880f322e0aa66a35e43c8b572e1f9bac6891ef8833c6ed7479d459050", - "receipt": { - "to": null, - "from": "0x956a5152D0f498dBA0c5966577bb44262F8F7078", - "contractAddress": "0xAe851f927Ee40dE99aaBb7461C00f9622ab91d60", - "transactionIndex": 40, - "gasUsed": "523800", - "logsBloom": "0x00000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000400000000000000000000000000000000000000000000000000000000000000000000000100000000000000", - "blockHash": "0x5de788459065d418b2cee8cbbd8fbd6745ede0f93f7c59e7bb08a3d69b5ba009", - "transactionHash": "0x1548358880f322e0aa66a35e43c8b572e1f9bac6891ef8833c6ed7479d459050", - "logs": [ - { - "transactionIndex": 40, - "blockNumber": 8299687, - "transactionHash": "0x1548358880f322e0aa66a35e43c8b572e1f9bac6891ef8833c6ed7479d459050", - "address": "0xAe851f927Ee40dE99aaBb7461C00f9622ab91d60", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d3670863c3f4b24d7b107900f0b75d4bbc6e0d", - "logIndex": 147, - "blockHash": "0x5de788459065d418b2cee8cbbd8fbd6745ede0f93f7c59e7bb08a3d69b5ba009" - } - ], - "blockNumber": 8299687, - "cumulativeGasUsed": "8112613", - "status": 1, - "byzantium": true - }, - "args": [ - "0x01d3670863c3F4b24D7b107900f0b75d4BbC6e0d" - ], - "numDeployments": 1, - "solcInputHash": "672fbec9734a08fc34112408d6dc7f7b", - "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\":{\"contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0xfa08635f1866139673ac4fe7b07330f752f93800075b895d8fcb8484f4a3f753\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8f2247604d527f560edbb851c43b6c16b37e34972ddb305e16dd73623b8288cd\",\"dweb:/ipfs/QmfM8sLAZrxrnqyRdt1XJ5LyJh4wKbeEqk3VkvxG7BDqFj\"]}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "admin()": { - "returns": { - "_0": "Owner address." - } - }, - "changeAdmin(address)": { - "params": { - "_admin": "New owner of the proxy contract." - } - }, - "constructor": { - "params": { - "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "Address of the implementation contract." - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "Calldata to delegatecall the new implementation with.", - "_implementation": "Address of the implementation contract." - } - } - }, - "events": { - "AdminChanged(address,address)": { - "params": { - "newAdmin": "The new owner of the contract", - "previousAdmin": "The previous owner of the contract" - } - }, - "Upgraded(address)": { - "params": { - "implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "admin()": { - "notice": "Gets the owner of the proxy contract." - }, - "changeAdmin(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "constructor": { - "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." - }, - "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." - } - }, - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." - } - }, - "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/SystemDictator.json b/packages/contracts-bedrock/deployments/goerli/SystemDictator.json deleted file mode 100644 index f682c217aee9..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/SystemDictator.json +++ /dev/null @@ -1,1158 +0,0 @@ -{ - "address": "0xCdD9F7C335bFDF3eaBDB4dF29f7417Ce8552A833", - "abi": [ - { - "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": "EXIT_1_NO_RETURN_STEP", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PROXY_TRANSFER_STEP", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "config", - "outputs": [ - { - "components": [ - { - "internalType": "contract AddressManager", - "name": "addressManager", - "type": "address" - }, - { - "internalType": "contract ProxyAdmin", - "name": "proxyAdmin", - "type": "address" - }, - { - "internalType": "address", - "name": "controller", - "type": "address" - }, - { - "internalType": "address", - "name": "finalOwner", - "type": "address" - } - ], - "internalType": "struct SystemDictator.GlobalConfig", - "name": "globalConfig", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "l2OutputOracleProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismPortalProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "l1CrossDomainMessengerProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "l1StandardBridgeProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismMintableERC20FactoryProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "l1ERC721BridgeProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "systemConfigProxy", - "type": "address" - } - ], - "internalType": "struct SystemDictator.ProxyAddressConfig", - "name": "proxyAddressConfig", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "contract L2OutputOracle", - "name": "l2OutputOracleImpl", - "type": "address" - }, - { - "internalType": "contract OptimismPortal", - "name": "optimismPortalImpl", - "type": "address" - }, - { - "internalType": "contract L1CrossDomainMessenger", - "name": "l1CrossDomainMessengerImpl", - "type": "address" - }, - { - "internalType": "contract L1StandardBridge", - "name": "l1StandardBridgeImpl", - "type": "address" - }, - { - "internalType": "contract OptimismMintableERC20Factory", - "name": "optimismMintableERC20FactoryImpl", - "type": "address" - }, - { - "internalType": "contract L1ERC721Bridge", - "name": "l1ERC721BridgeImpl", - "type": "address" - }, - { - "internalType": "contract PortalSender", - "name": "portalSenderImpl", - "type": "address" - }, - { - "internalType": "contract SystemConfig", - "name": "systemConfigImpl", - "type": "address" - } - ], - "internalType": "struct SystemDictator.ImplementationAddressConfig", - "name": "implementationAddressConfig", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "overhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "scalar", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "batcherHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "gasLimit", - "type": "uint64" - }, - { - "internalType": "address", - "name": "unsafeBlockSigner", - "type": "address" - } - ], - "internalType": "struct SystemDictator.SystemConfigConfig", - "name": "systemConfigConfig", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "currentStep", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "dynamicConfigSet", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "exit1", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "finalize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "finalized", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "contract AddressManager", - "name": "addressManager", - "type": "address" - }, - { - "internalType": "contract ProxyAdmin", - "name": "proxyAdmin", - "type": "address" - }, - { - "internalType": "address", - "name": "controller", - "type": "address" - }, - { - "internalType": "address", - "name": "finalOwner", - "type": "address" - } - ], - "internalType": "struct SystemDictator.GlobalConfig", - "name": "globalConfig", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "l2OutputOracleProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismPortalProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "l1CrossDomainMessengerProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "l1StandardBridgeProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismMintableERC20FactoryProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "l1ERC721BridgeProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "systemConfigProxy", - "type": "address" - } - ], - "internalType": "struct SystemDictator.ProxyAddressConfig", - "name": "proxyAddressConfig", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "contract L2OutputOracle", - "name": "l2OutputOracleImpl", - "type": "address" - }, - { - "internalType": "contract OptimismPortal", - "name": "optimismPortalImpl", - "type": "address" - }, - { - "internalType": "contract L1CrossDomainMessenger", - "name": "l1CrossDomainMessengerImpl", - "type": "address" - }, - { - "internalType": "contract L1StandardBridge", - "name": "l1StandardBridgeImpl", - "type": "address" - }, - { - "internalType": "contract OptimismMintableERC20Factory", - "name": "optimismMintableERC20FactoryImpl", - "type": "address" - }, - { - "internalType": "contract L1ERC721Bridge", - "name": "l1ERC721BridgeImpl", - "type": "address" - }, - { - "internalType": "contract PortalSender", - "name": "portalSenderImpl", - "type": "address" - }, - { - "internalType": "contract SystemConfig", - "name": "systemConfigImpl", - "type": "address" - } - ], - "internalType": "struct SystemDictator.ImplementationAddressConfig", - "name": "implementationAddressConfig", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "overhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "scalar", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "batcherHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "gasLimit", - "type": "uint64" - }, - { - "internalType": "address", - "name": "unsafeBlockSigner", - "type": "address" - } - ], - "internalType": "struct SystemDictator.SystemConfigConfig", - "name": "systemConfigConfig", - "type": "tuple" - } - ], - "internalType": "struct SystemDictator.DeployConfig", - "name": "_config", - "type": "tuple" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l2OutputOracleDynamicConfig", - "outputs": [ - { - "internalType": "uint256", - "name": "l2OutputOracleStartingBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l2OutputOracleStartingTimestamp", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "oldL1CrossDomainMessenger", - "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": [], - "name": "step1", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "step2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "step3", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "step4", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "step5", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "step6", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "l2OutputOracleStartingBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l2OutputOracleStartingTimestamp", - "type": "uint256" - } - ], - "internalType": "struct SystemDictator.L2OutputOracleDynamicConfig", - "name": "_l2OutputOracleDynamicConfig", - "type": "tuple" - } - ], - "name": "updateL2OutputOracleDynamicConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xd690383a9a67077a377af6436e8e2ec96b2de52f87b3c6022a9735be3c2ad00e", - "receipt": { - "to": null, - "from": "0x956a5152D0f498dBA0c5966577bb44262F8F7078", - "contractAddress": "0xCdD9F7C335bFDF3eaBDB4dF29f7417Ce8552A833", - "transactionIndex": 17, - "gasUsed": "2874326", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x1f18d07ddb20ae302240bca1013adc9b239070038c71c82c22c7f1f5c1f15058", - "transactionHash": "0xd690383a9a67077a377af6436e8e2ec96b2de52f87b3c6022a9735be3c2ad00e", - "logs": [], - "blockNumber": 8299697, - "cumulativeGasUsed": "9427783", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "672fbec9734a08fc34112408d6dc7f7b", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"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\":\"EXIT_1_NO_RETURN_STEP\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROXY_TRANSFER_STEP\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"config\",\"outputs\":[{\"components\":[{\"internalType\":\"contract AddressManager\",\"name\":\"addressManager\",\"type\":\"address\"},{\"internalType\":\"contract ProxyAdmin\",\"name\":\"proxyAdmin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"controller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"finalOwner\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.GlobalConfig\",\"name\":\"globalConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"l2OutputOracleProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"optimismPortalProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1CrossDomainMessengerProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1StandardBridgeProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"optimismMintableERC20FactoryProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1ERC721BridgeProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"systemConfigProxy\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.ProxyAddressConfig\",\"name\":\"proxyAddressConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"l2OutputOracleImpl\",\"type\":\"address\"},{\"internalType\":\"contract OptimismPortal\",\"name\":\"optimismPortalImpl\",\"type\":\"address\"},{\"internalType\":\"contract L1CrossDomainMessenger\",\"name\":\"l1CrossDomainMessengerImpl\",\"type\":\"address\"},{\"internalType\":\"contract L1StandardBridge\",\"name\":\"l1StandardBridgeImpl\",\"type\":\"address\"},{\"internalType\":\"contract OptimismMintableERC20Factory\",\"name\":\"optimismMintableERC20FactoryImpl\",\"type\":\"address\"},{\"internalType\":\"contract L1ERC721Bridge\",\"name\":\"l1ERC721BridgeImpl\",\"type\":\"address\"},{\"internalType\":\"contract PortalSender\",\"name\":\"portalSenderImpl\",\"type\":\"address\"},{\"internalType\":\"contract SystemConfig\",\"name\":\"systemConfigImpl\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.ImplementationAddressConfig\",\"name\":\"implementationAddressConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"unsafeBlockSigner\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.SystemConfigConfig\",\"name\":\"systemConfigConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentStep\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dynamicConfigSet\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finalize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"contract AddressManager\",\"name\":\"addressManager\",\"type\":\"address\"},{\"internalType\":\"contract ProxyAdmin\",\"name\":\"proxyAdmin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"controller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"finalOwner\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.GlobalConfig\",\"name\":\"globalConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"l2OutputOracleProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"optimismPortalProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1CrossDomainMessengerProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1StandardBridgeProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"optimismMintableERC20FactoryProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1ERC721BridgeProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"systemConfigProxy\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.ProxyAddressConfig\",\"name\":\"proxyAddressConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"l2OutputOracleImpl\",\"type\":\"address\"},{\"internalType\":\"contract OptimismPortal\",\"name\":\"optimismPortalImpl\",\"type\":\"address\"},{\"internalType\":\"contract L1CrossDomainMessenger\",\"name\":\"l1CrossDomainMessengerImpl\",\"type\":\"address\"},{\"internalType\":\"contract L1StandardBridge\",\"name\":\"l1StandardBridgeImpl\",\"type\":\"address\"},{\"internalType\":\"contract OptimismMintableERC20Factory\",\"name\":\"optimismMintableERC20FactoryImpl\",\"type\":\"address\"},{\"internalType\":\"contract L1ERC721Bridge\",\"name\":\"l1ERC721BridgeImpl\",\"type\":\"address\"},{\"internalType\":\"contract PortalSender\",\"name\":\"portalSenderImpl\",\"type\":\"address\"},{\"internalType\":\"contract SystemConfig\",\"name\":\"systemConfigImpl\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.ImplementationAddressConfig\",\"name\":\"implementationAddressConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"unsafeBlockSigner\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.SystemConfigConfig\",\"name\":\"systemConfigConfig\",\"type\":\"tuple\"}],\"internalType\":\"struct SystemDictator.DeployConfig\",\"name\":\"_config\",\"type\":\"tuple\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2OutputOracleDynamicConfig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"l2OutputOracleStartingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"l2OutputOracleStartingTimestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oldL1CrossDomainMessenger\",\"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\":[],\"name\":\"step1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"step2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"step3\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"step4\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"step5\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"step6\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"l2OutputOracleStartingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"l2OutputOracleStartingTimestamp\",\"type\":\"uint256\"}],\"internalType\":\"struct SystemDictator.L2OutputOracleDynamicConfig\",\"name\":\"_l2OutputOracleDynamicConfig\",\"type\":\"tuple\"}],\"name\":\"updateL2OutputOracleDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"initialize(((address,address,address,address),(address,address,address,address,address,address,address),(address,address,address,address,address,address,address,address),(address,uint256,uint256,bytes32,uint64,address)))\":{\"params\":{\"_config\":\"System configuration.\"}},\"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.\"},\"updateL2OutputOracleDynamicConfig((uint256,uint256))\":{\"params\":{\"_l2OutputOracleDynamicConfig\":\"Dynamic L2OutputOracle config.\"}}},\"title\":\"SystemDictator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"EXIT_1_NO_RETURN_STEP()\":{\"notice\":\"Step after which exit 1 can no longer be used.\"},\"PROXY_TRANSFER_STEP()\":{\"notice\":\"Step where proxy ownership is transferred.\"},\"config()\":{\"notice\":\"System configuration.\"},\"currentStep()\":{\"notice\":\"Current step;\"},\"dynamicConfigSet()\":{\"notice\":\"Whether or not dynamic config has been set.\"},\"exit1()\":{\"notice\":\"First exit point, can only be called before step 3 is executed.\"},\"finalize()\":{\"notice\":\"Tranfers admin ownership to the final owner.\"},\"finalized()\":{\"notice\":\"Whether or not the deployment is finalized.\"},\"l2OutputOracleDynamicConfig()\":{\"notice\":\"Dynamic configuration for the L2OutputOracle.\"},\"oldL1CrossDomainMessenger()\":{\"notice\":\"Address of the old L1CrossDomainMessenger implementation.\"},\"step1()\":{\"notice\":\"Configures the ProxyAdmin contract.\"},\"step2()\":{\"notice\":\"Pauses the system by shutting down the L1CrossDomainMessenger and setting the deposit halt flag to tell the Sequencer's DTL to stop accepting deposits.\"},\"step3()\":{\"notice\":\"Removes deprecated addresses from the AddressManager.\"},\"step4()\":{\"notice\":\"Transfers system ownership to the ProxyAdmin.\"},\"step5()\":{\"notice\":\"Upgrades and initializes proxy contracts.\"},\"step6()\":{\"notice\":\"Unpauses the system at which point the system should be fully operational.\"},\"updateL2OutputOracleDynamicConfig((uint256,uint256))\":{\"notice\":\"Allows the owner to update dynamic L2OutputOracle config.\"}},\"notice\":\"The SystemDictator is responsible for coordinating the deployment of a full Bedrock system. The SystemDictator is designed to support both fresh network deployments and upgrades to existing pre-Bedrock systems.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/deployment/SystemDictator.sol\":\"SystemDictator\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/L1/L1CrossDomainMessenger.sol\":{\"keccak256\":\"0x73c9ef994396ea551b56ce6c96d7bff8dc825b22e6f31e7b10e38d2c38be2373\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2e713ca338ff223b4076a25554d4ba72ffeca4ed0bb161b170e4ed3ab0724e9f\",\"dweb:/ipfs/QmS1tFSzbcTdkPUeP6dMxrvDSna5JYrK1rTbukfzcU4MbM\"]},\"contracts/L1/L1ERC721Bridge.sol\":{\"keccak256\":\"0x9a410440dad639aa9b8facb8d99ad5a74e868fa20d75274f545a539cfd965745\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dd46b6bb8428d2e17ff15664a46e23b9e93188520b047dd406800792dd928118\",\"dweb:/ipfs/QmYode1mDZdLj7UdA8QqD8dDQFgst52DeFh8kn33njZJqh\"]},\"contracts/L1/L1StandardBridge.sol\":{\"keccak256\":\"0x19d06e31748c911064f6ee2b5d729468912cb2d055c1d847f266502f7857be22\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6bde1feaf637ea86ecd88605f312e4e85fe2a87d225859e2fbb183af8c283551\",\"dweb:/ipfs/QmVrTipEETDCat52cCYestK3AvUj1KrV9t2HrXJcMq58Tp\"]},\"contracts/L1/L2OutputOracle.sol\":{\"keccak256\":\"0xaa706785b6c6e01b21b47d050a19f83d6afaf8a1db152d0e48463eea55c0c366\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://84f6a9884c4cf7edf499e4182bd9db03876e33df66a0b64307e2c7b997c150b7\",\"dweb:/ipfs/QmR2prJL6HGxPjVjbW5o96C9ekavkarNEy2v11yCGxrdfX\"]},\"contracts/L1/OptimismPortal.sol\":{\"keccak256\":\"0xc9fa6b522c76e6f8de364b4e6f58ebcd073a47b37fb343e444687429bbc2b49e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b3ee3b286e2f5930ee0ec98864c6f51b0d33820678760b668689487a67771f48\",\"dweb:/ipfs/Qmb1KbJXBGzohdyzw5hsMkaEVtPjEEW5BdvDRAUN9Fv7Vy\"]},\"contracts/L1/ResourceMetering.sol\":{\"keccak256\":\"0x23045734df51c2f237d0def7f5e6dda69304bb3cfb554c6c1e934c4c8b07cecc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e6f84a34b842702c3ab4b06da997903046556f3f809716763a351b9f379b7e07\",\"dweb:/ipfs/QmQPyWcbuAMhghZdGSPwSBQdQgZi5hk6Bdg4s7qxaHpcMw\"]},\"contracts/L1/SystemConfig.sol\":{\"keccak256\":\"0xedc693eef1f791d8e4bf8e607481b82ab334b9eddc66e3a35f0ab3a7da6035d1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fe90c341ae0410d56f8ccf75b26aed89419558897fb815ff1133d0a1d726e810\",\"dweb:/ipfs/QmafjYWpfgPauDCKj2w8NTwa91HUQKgjYj5XjK5rPSjMsG\"]},\"contracts/L2/L2ERC721Bridge.sol\":{\"keccak256\":\"0x2ab1b8168d443b8c5fb6806fca9396d9ac8d0371c05b15992e1b38be22c4ca48\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c2df3e2944950a83eb9d6b7217a21a7d557ee08620962f9db4c6e53fb76cf7af\",\"dweb:/ipfs/QmZ124uFjoyK6pWiHRYVRhF5tr2wcUcGgsTF4G355ntL5N\"]},\"contracts/deployment/PortalSender.sol\":{\"keccak256\":\"0xe60d88036d9aa8f8e80a4108ee30ad987564ad996af87a79ba92f6ca35852881\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a4be187cd3d5926592491f722dfa1b1c41a8f4f1abdc8cf3883964f70acb0a44\",\"dweb:/ipfs/QmYsAK4YcRHmPoex2eX2x1r6N76AMk3rdBHHmp6gUT73Fa\"]},\"contracts/deployment/SystemDictator.sol\":{\"keccak256\":\"0x7ffcfb6bff9df395a113579141d762367e3144c058e6cb3abfec8ccc91e14c5a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4cf872132f3937d4a830e93bc7680f5749cccc0a0c0dd461b7782a922b9ab0d4\",\"dweb:/ipfs/QmWbNRKsBLD998mYvGD5cLKVmkdK27SXYYCByocin5oyoe\"]},\"contracts/legacy/AddressManager.sol\":{\"keccak256\":\"0x7a353d4c92eed32665fd2f0023c55054901293cf7a6e14ca108229d87c047b10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b92ba23601d1951271729a20db931a45639d9376b7c8e2705c23dc360833715a\",\"dweb:/ipfs/QmTKwYLNYYBKZpd31VNBANmguVUwFZifSg7joHSgLZjZCj\"]},\"contracts/legacy/L1ChugSplashProxy.sol\":{\"keccak256\":\"0x6ae7bf6ea9ac0e3511ee4cb15d946589da0dd35098ff762c0b2903d064f24875\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://02028d86c1d38563021d5ead5282271ccdf1c03a24f2eaee056ae2157f0554ee\",\"dweb:/ipfs/QmW9urkBBRTmZ8FjL5Y5zWbdnRhPDruxCCLnpr2CTkozKM\"]},\"contracts/libraries/Arithmetic.sol\":{\"keccak256\":\"0xc8858039f87e48e6f18c1af8bc0b03e57cfef564acddfd06e4d91e3db7ac5ed6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2fc79af1e844aa6dc1c68067bfe1d359df8d4e9a3e8881afb3bcfcbf68071714\",\"dweb:/ipfs/QmcNC4k8zmvwj4kZizSenTiWbx2DJQPbwqXXLF4iMbkRVD\"]},\"contracts/libraries/Burn.sol\":{\"keccak256\":\"0x54233b226ba6919dc46d438bc790108d8f855001002a1b9c3c37aed7a83e5f3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4051a4baca357a9191a6c9e3aa1593a17b69dd7915966e23e4cb269e9c1d9ed4\",\"dweb:/ipfs/QmadKjGKvxm53abVHQdsxrXBc8e9jXywu6vvhkAgjsx59J\"]},\"contracts/libraries/Bytes.sol\":{\"keccak256\":\"0x7aca6593fadf438ee9cd090d8fdc8f94a5202a2eb7f764c9a86f207712d87a48\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://aac32157885c5a08bd0bc7dcd5511f66db12bb20d0c263dd7be9f58b91538fc1\",\"dweb:/ipfs/Qmb1iG11Z53yt9wNbGsuTvoydJXFosDDpWwRSADKyqiCjw\"]},\"contracts/libraries/Constants.sol\":{\"keccak256\":\"0x50a2b69a5e9246945ee1588278753feae90285ff7e675369f0cc5b64acea333c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://75153213766bd271cce59d5284a4a0d2f6283e3c6a9dc31b8ce20a3a4c28c066\",\"dweb:/ipfs/QmcbpwMLYuKUPahVYJ3W7sfntQgHk9RTuR2DUzFMrfPMQr\"]},\"contracts/libraries/Encoding.sol\":{\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f18156216c1f9457c2e032a812ad70f2babbc5b89997554ff014d64c483fb2ff\",\"dweb:/ipfs/Qmc5rjMaBFn3jV7XqDrEvRbmatQvJxeVJYA5B5rdcKPkcJ\"]},\"contracts/libraries/Hashing.sol\":{\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6746ed0d26d603568818cc52a29d0209effd69f7e55bd0017a6b91bd6cf319fe\",\"dweb:/ipfs/QmPebCmCELMBRtDDxt5ziEPfRXUh6tfm2qJdwz3iyrDdWN\"]},\"contracts/libraries/Predeploys.sol\":{\"keccak256\":\"0xbf404ace304548f9824262f3efa079191f4fe9d475518c45f37626f3596a6c4b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://43122a0cd40564a776ea49186c4a3c9bf1a0fc74a542d850ff0bacfb072d013f\",\"dweb:/ipfs/QmWkwNAywCZGhTrXtNbkRq3gzdm9MRBPiRVVtBhH9sHyAk\"]},\"contracts/libraries/SafeCall.sol\":{\"keccak256\":\"0xbb0621c028c18e9d5a54cf1a8136cf2e77f161de48aeb8d911e230f6b280c9ed\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://924ecc629c7642bc19e2f8a390f1b946d22862c8889453da681b5bc1a45d7703\",\"dweb:/ipfs/QmbNknQ8pzssXDXGVjXxzZ8zh1YnNCWtRJVepiM1TnqoqQ\"]},\"contracts/libraries/Types.sol\":{\"keccak256\":\"0x822e7c7ac5d45eac20551ba602d8bff3d22db3538fb32be42c1ab12d7bfca110\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://970823854723de895ca7a24d34269e886a20824c75f706cb41541893b7c78838\",\"dweb:/ipfs/QmSQbEECeTxgUT65pK7Czc4ovAv2FdQ9EHyi5Z8mZgNkXc\"]},\"contracts/libraries/rlp/RLPReader.sol\":{\"keccak256\":\"0x50763c897f0fe84cb067985ec4d7c5721ce9004a69cf0327f96f8982ee8ca412\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://603af847b43933b075f9aac3a7b3cd65041ffe6d732826695458ca9575e1a809\",\"dweb:/ipfs/QmfByFEaCxT9y1VtqoLi5EsXZ9ihkPfj6g5x7pcPoQ7q2K\"]},\"contracts/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://921c44e6a0982b9a4011900fda1bda2c06b7a85894967de98b407a83fe9f90c0\",\"dweb:/ipfs/QmSsHLKDUQ82kpKdqB6VntVGKuPDb4W9VdotsubuqWBzio\"]},\"contracts/libraries/trie/MerkleTrie.sol\":{\"keccak256\":\"0xd27fc945d6dd2821636d840f3766f817823c8e9fbfdb87c2da7c73e4292d2f7f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://497cec37d09ebcdc8d1cccac608a4a0b9b9d83eac6cc7c9e8b73c4c6644e2209\",\"dweb:/ipfs/QmUYMsCcgU6epspvKV9Y6anHyyMb4hd1xVzUZheBY9mfG7\"]},\"contracts/libraries/trie/SecureMerkleTrie.sol\":{\"keccak256\":\"0x61b03a03779cb1f75cea3b88af16fdfd10629029b4b2d6be5238e71af8ef1b5f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1212951af291c0e033a7119b42de5cad6b6bf32da26777da7c2419e76fa8f314\",\"dweb:/ipfs/QmYbnifDmL6UkP9D1X9GaNLR1Q8wYwmDNeYqkJ71bycaE5\"]},\"contracts/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0xa8efcda6e2fec4edc379fa9128d9ae9c257c278f94c6b265fc267764d4006213\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://56f739b6a7ed1d2eda132365c112edbf5646c36ffbac1d85f753311d11df421b\",\"dweb:/ipfs/QmaCXcw3tSKHuQm3VqAggSEAGqr3k6Ru5cfLZyGpCShhQz\"]},\"contracts/universal/ERC721Bridge.sol\":{\"keccak256\":\"0xb47389fbec63e85b2d04fce538fe1b8e048278d631729458b70e32a31971c092\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7133f38e3d8d1911738057b1d4523989abd7cd029797b1d3b59cda29d42e9704\",\"dweb:/ipfs/QmUN31CLssESHrBwWA3WYP5L2xESo9Q4aq2Exua1e8UtUW\"]},\"contracts/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0xaafd7b92930a022efa765be7c6c693e36e005c73e7486b37244d7e63cd4ac432\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a9fa58ca28cd600fd9913495b65cf52cada126e76b9ceb37894ff7993b77d791\",\"dweb:/ipfs/QmcSDqAxfY4nQrcEcUp3AQcazqQTfqBXZeocUt9wsAiA6x\"]},\"contracts/universal/IOptimismMintableERC721.sol\":{\"keccak256\":\"0xf1a3dd4452df8882a65a31c5e2e8de7872b08cf078be7a5a7da51e6f75c53ad3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b09a2560cae35ca4789fe1ff5edb2bae9fa7dcda115a55f7ccdcc974a2e37526\",\"dweb:/ipfs/QmPQeTvrJ4SJpng5VGZNMf1u85NWxrdus4gGn8xYkHddKM\"]},\"contracts/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0xe77679aa54e918825fc2332f528085cd344874809853475e1502afe4b46de4e9\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://af64115cc7aa940c74fb9129fa01c85bb05e70e7b148c1dcf263789de1138479\",\"dweb:/ipfs/QmbnTbs4jbCsrhbfLDjnzAz5h47LsRHn9TJoPdJwRuQV3S\"]},\"contracts/universal/OptimismMintableERC20Factory.sol\":{\"keccak256\":\"0xf010ac4b7b9c9a65b06fe21c8234c1a9366286f8e286f822bfb595413f6887c5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b879b8a1e3151e0b7aa7befd4d0fa95a3bd7c1236ac777087d6d68fdeaffebc8\",\"dweb:/ipfs/QmRmyXgQk5bXW3giPdPtwVoFFt8nofDnTUa3Kmy4WAuPsL\"]},\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0xfa08635f1866139673ac4fe7b07330f752f93800075b895d8fcb8484f4a3f753\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8f2247604d527f560edbb851c43b6c16b37e34972ddb305e16dd73623b8288cd\",\"dweb:/ipfs/QmfM8sLAZrxrnqyRdt1XJ5LyJh4wKbeEqk3VkvxG7BDqFj\"]},\"contracts/universal/ProxyAdmin.sol\":{\"keccak256\":\"0x7326011ac425cc9ab4760c29ca559342d4832633b5019a9a61b9e63067374e2a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7d3541272c48443f0b339998553e44600b7bcb4f949e5c94acb5a3acfce19399\",\"dweb:/ipfs/QmNSd9jxACWg8bZE8EgxmRdXwLUQixVs4oiugrVegapUe4\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x979b13465de4996a1105850abbf48abe7f71d5e18a8d4af318597ee14c165fdf\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d0881ed7d8371fe1c12b931334e107746fa97d9ecd6aa3c0fca0c0db8581474e\",\"dweb:/ipfs/QmQ9UFwZgWkyFAHrzTtS7m6rghZ8nP9QybEuJ5y9vux5Gv\"]},\"contracts/universal/StandardBridge.sol\":{\"keccak256\":\"0x3751c9d342180b37f06c1a48366e785d424bb5bc43ee7468dd7062089808ddb2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5d2aecf267e340472f634af99bfec816472b61c2d99ac6e4ea48424bb486b2e1\",\"dweb:/ipfs/QmbRG1gTEy3h55reCb7ne7DWjR1zvtj7Yv9dJaPzCkLRbr\"]},\"contracts/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"]},\"node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"]},\"node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"]},\"node_modules/@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\":{\"keccak256\":\"0x40c636b4572ff5f1dc50cf22097e93c0723ee14eff87e99ac2b02636eeca1250\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9c7d1f5e15633ab912b74c2f57e24559e66b03232300d4b27ff0f25bc452ecad\",\"dweb:/ipfs/QmYTJkc1cntYkKQ1Tu11nBcJLakiy93Tjytc4XHELo4GmR\"]},\"node_modules/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"keccak256\":\"0x8cc03c5ac17e8a7396e487cda41fc1f1dfdb91db7d528e6da84bee3b6dd7e167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://607818f1b44548c2d8268176f73cdb290e1faed971b1061930d92698366e2a11\",\"dweb:/ipfs/QmQibMe3r5no95b6q7isGT5R75V8xSofWEDLXzp95b7LgZ\"]},\"node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"]},\"node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"]},\"node_modules/@openzeppelin/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"]},\"node_modules/@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b2717fd2bdac99daa960a6de500754ea1b932093c946388c381da48658234b95\",\"dweb:/ipfs/QmP6QVMn6UeA3ByahyJbYQr5M6coHKBKsf3ySZSfbyA8R7\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x032807210d1d7d218963d7355d62e021a84bf1b3339f4f50be2f63b53cccaf29\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://11756f42121f6541a35a8339ea899ee7514cfaa2e6d740625fcc844419296aa6\",\"dweb:/ipfs/QmekMuk6BY4DAjzeXr4MSbKdgoqqsZnA8JPtuyWc6CwXHf\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"keccak256\":\"0xed6a749c5373af398105ce6ee3ac4763aa450ea7285d268c85d9eeca809cdb1f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://20a97f891d06f0fe91560ea1a142aaa26fdd22bed1b51606b7d48f670deeb50f\",\"dweb:/ipfs/QmTbCtZKChpaX5H2iRiTDMcSz29GSLCpTCDgJpcMR4wg8x\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://26fef835622b46a5ba08b3ef6b46a22e94b5f285d0f0fb66b703bd30217d2c34\",\"dweb:/ipfs/QmZ548qdwfL1qF7aXz3xh1GCdTiST81kGGuKRqVUfYmPZR\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"]},\"node_modules/@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"]},\"node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"]},\"node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"]}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061337d806100206000396000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806389cb7343116100d8578063d40a71fb1161008c578063f2fde38b11610066578063f2fde38b1461042c578063fb5d73761461043f578063fe6b1ddf1461044757600080fd5b8063d40a71fb14610414578063df4ec2491461041c578063eb7c6f721461042457600080fd5b80638f4ed333116100bd5780638f4ed333146103d2578063b3f05b97146103da578063cf03c22d146103ed57600080fd5b806389cb7343146103715780638da5cb5b1461039357600080fd5b80635bc34f711161012f578063715018a611610114578063715018a61461020357806379502c551461020b5780637d1d95a61461036957600080fd5b80635bc34f71146101e35780636c4a5b1e146101f057600080fd5b806345f003641161016057806345f00364146101be5780634bb278f3146101d35780634fb4bcec146101db57600080fd5b8063204c881c1461017c578063289c6af7146101a4575b600080fd5b607d54607e5461018a919082565b604080519283526020830191909152015b60405180910390f35b6101ac600381565b60405160ff909116815260200161019b565b6101d16101cc3660046128b9565b61044f565b005b6101d1610491565b6101d161077d565b607f546101ac9060ff1681565b6101d16101fe366004612bf3565b6111ec565b6101d16115f7565b604080516080808201835260655473ffffffffffffffffffffffffffffffffffffffff908116835260665481166020808501919091526067548216848601526068548216606080860191909152855160e0808201885260695485168252606a54851682850152606b54851682890152606c54851682840152606d54851682870152606e54851660a080840191909152606f54861660c080850191909152895161010081018b52607054881681526071548816818801526072548816818c01526073548816818701526074548816818a015260755488168184015260765488168183015260775488169381019390935289519081018a526078548716815260795495810195909552607a5498850198909852607b5492840192909252607c5467ffffffffffffffff81169584019590955268010000000000000000909404909216948101949094526103599384565b60405161019b9493929190612cb8565b6101ac600481565b607f5461038390610100900460ff1681565b604051901515815260200161019b565b60335473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101d161160b565b607f546103839062010000900460ff1681565b607f546103ad906301000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6101d161189d565b6101d1611b3e565b6101d161200c565b6101d161043a366004612e6d565b612117565b6101d16121ce565b6101d16123d5565b6104576125c3565b8051607d5560200151607e55607f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b6104996125c3565b606b546068546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063f2fde38b90602401600060405180830381600087803b15801561050857600080fd5b505af115801561051c573d6000803e3d6000fd5b50506066546068546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201529116925063f2fde38b9150602401600060405180830381600087803b15801561058f57600080fd5b505af11580156105a3573d6000803e3d6000fd5b5050607f54600460ff90911611915061074e9050576065546068546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063f2fde38b90602401600060405180830381600087803b15801561062757600080fd5b505af115801561063b573d6000803e3d6000fd5b5050606c546068546040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152911692506313af40359150602401600060405180830381600087803b1580156106ae57600080fd5b505af11580156106c2573d6000803e3d6000fd5b5050606e546068546040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169250638f2839709150602401600060405180830381600087803b15801561073557600080fd5b505af1158015610749573d6000803e3d6000fd5b505050505b607f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000179055565b6107856125c3565b607f5460059060ff168114610821576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4261736553797374656d4469637461746f723a20696e636f727265637420737460448201527f657000000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b607f54610100900460ff166108b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603c60248201527f53797374656d4469637461746f723a2064796e616d6963206f7261636c65206360448201527f6f6e666967206973206e6f742079657420696e697469616c697a6564000000006064820152608401610818565b606654606954607054607d54607e546040516024810192909252604482015273ffffffffffffffffffffffffffffffffffffffff93841693639623609d938116921690606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fe4a3011600000000000000000000000000000000000000000000000000000000179052517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526109ad93929190600401612f07565b600060405180830381600087803b1580156109c757600080fd5b505af11580156109db573d6000803e3d6000fd5b5050606654606a546071546040805160048082526024820183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8129fc1c0000000000000000000000000000000000000000000000000000000017905291517f9623609d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9586169750639623609d9650610a9895948516949390931692909101612f07565b600060405180830381600087803b158015610ab257600080fd5b505af1158015610ac6573d6000803e3d6000fd5b5050606654606b546072546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b158015610b4457600080fd5b505af1158015610b58573d6000803e3d6000fd5b5050606b546040517fc4d66de800000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116925063c4d66de89150602401600060405180830381600087803b158015610bc757600080fd5b505af1925050508015610bd8575060015b610d3557610be4612f40565b806308c379a003610cab5750610bf8612f5c565b80610c035750610cad565b7f7a2a4e26842155ea933fe6eb6e3137eb5a296dcdf55721c552be7b4c3cc2375981604051602001610c359190613004565b604051602081830303815290604052805190602001201481604051602001610c5d9190613020565b60405160208183030381529060405290610ca4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610818919061308b565b5050610d35565b505b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f53797374656d4469637461746f723a20756e6578706563746564206572726f7260448201527f20696e697469616c697a696e67204c3158444d20286e6f20726561736f6e29006064820152608401610818565b606654606c546076546040805160048082526024820183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fed88c68e0000000000000000000000000000000000000000000000000000000017905291517f9623609d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff95861695639623609d95610deb95908216949116929101612f07565b600060405180830381600087803b158015610e0557600080fd5b505af1158015610e19573d6000803e3d6000fd5b5050606654606c546073546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b158015610e9757600080fd5b505af1158015610eab573d6000803e3d6000fd5b5050606654606d546074546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b5050606654606e546075546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b158015610fbb57600080fd5b505af1158015610fcf573d6000803e3d6000fd5b5050606654606f54607754607854607954607a54607b54607c5460405173ffffffffffffffffffffffffffffffffffffffff958616602482015260448101949094526064840192909252608483015267ffffffffffffffff811660a4830152680100000000000000009004821660c48201529381169550639623609d94509182169291169060e401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8f974d7f00000000000000000000000000000000000000000000000000000000179052517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815261110693929190600401612f07565b600060405180830381600087803b15801561112057600080fd5b505af1158015611134573d6000803e3d6000fd5b5050606b54604080517f8456cb59000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169350638456cb59925060048181019260009290919082900301818387803b1580156111a457600080fd5b505af11580156111b8573d6000803e3d6000fd5b5050607f805460ff169250905060006111d0836130cd565b91906101000a81548160ff021916908360ff1602179055505050565b600054610100900460ff161580801561120c5750600054600160ff909116105b806112265750303b158015611226575060005460ff166001145b6112b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610818565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561131057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b81518051606580547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560208084015160668054841691851691909117905560408085015160678054851691861691909117905560609485015160688054851691861691909117905581870151805160698054861691871691909117905580830151606a8054861691871691909117905580820151606b8054861691871691909117905580860151606c80548616918716919091179055608080820151606d8054871691881691909117905560a080830151606e8054881691891691909117905560c092830151606f80548816918916919091179055838a01518051607080548916918a1691909117905580860151607180548916918a1691909117905580850151607280548916918a1691909117905580890151607380548916918a1691909117905580830151607480548916918a1691909117905580820151607580548916918a169190911790559283015160768054881691891691909117905560e09092015160778054871691881691909117905586890151805160788054909716908816179095559284015160795590830151607a5593820151607b55810151607c8054929094015167ffffffffffffffff9091167fffffffff0000000000000000000000000000000000000000000000000000000090921691909117680100000000000000009190921602179055607f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561156e612644565b6067546115909073ffffffffffffffffffffffffffffffffffffffff166126e3565b80156115f357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115ff6125c3565b61160960006126e3565b565b6116136125c3565b607f5460029060ff1681146116aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4261736553797374656d4469637461746f723a20696e636f727265637420737460448201527f65700000000000000000000000000000000000000000000000000000000000006064820152608401610818565b6065546040517fbf40fac100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac1906116fe906004016130ec565b602060405180830381865afa15801561171b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173f919061312f565b607f80547fffffffffffffffffff0000000000000000000000000000000000000000ffffff16630100000073ffffffffffffffffffffffffffffffffffffffff938416021790556065546040517f9b2ea4bd000000000000000000000000000000000000000000000000000000008152911690639b2ea4bd906117c79060009060040161314c565b600060405180830381600087803b1580156117e157600080fd5b505af11580156117f5573d6000803e3d6000fd5b5050606554604080517f9b2ea4bd0000000000000000000000000000000000000000000000000000000081526004810191909152601160448201527f44544c5f534855544f46465f424c4f434b000000000000000000000000000000606482015273ffffffffffffffffffffffffffffffffffffffff43811660248301529091169250639b2ea4bd91506084015b600060405180830381600087803b1580156111a457600080fd5b6118a56125c3565b607f5460019060ff16811461193c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4261736553797374656d4469637461746f723a20696e636f727265637420737460448201527f65700000000000000000000000000000000000000000000000000000000000006064820152608401610818565b6066546065546040517f0652b57a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152911690630652b57a90602401600060405180830381600087803b1580156119ab57600080fd5b505af11580156119bf573d6000803e3d6000fd5b5050606654606b546040517f8d52d4a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450638d52d4a09350611a2192909116906002906004016131ad565b600060405180830381600087803b158015611a3b57600080fd5b505af1158015611a4f573d6000803e3d6000fd5b5050606654606b546040517f860f7cda00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff928316945063860f7cda9350611aae929091169060040161320e565b600060405180830381600087803b158015611ac857600080fd5b505af1158015611adc573d6000803e3d6000fd5b5050606654606c546040517f8d52d4a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450638d52d4a0935061188392909116906001906004016131ad565b611b466125c3565b607f5460039060ff168114611bdd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4261736553797374656d4469637461746f723a20696e636f727265637420737460448201527f65700000000000000000000000000000000000000000000000000000000000006064820152608401610818565b60006040518061022001604052806040518060400160405280601d81526020017f4f564d5f43616e6f6e6963616c5472616e73616374696f6e436861696e00000081525081526020016040518060400160405280601a81526020017f4f564d5f4c3243726f7373446f6d61696e4d657373656e67657200000000000081525081526020016040518060600160405280602281526020016133076022913981526020016040518060400160405280600d81526020017f4f564d5f53657175656e6365720000000000000000000000000000000000000081525081526020016040518060400160405280600c81526020017f4f564d5f50726f706f7365720000000000000000000000000000000000000000815250815260200160405180606001604052806025815260200161332960259139815260200160405180606001604052806023815260200161334e602391398152604080518082018252601d81527f4f564d5f43616e6f6e6963616c5472616e73616374696f6e436861696e0000006020828101919091528084019190915281518083018352601881527f4f564d5f5374617465436f6d6d69746d656e74436861696e0000000000000000818301528284015281518083018352600f81527f4f564d5f426f6e644d616e61676572000000000000000000000000000000000081830152606084015281518083018352601481527f4f564d5f457865637574696f6e4d616e616765720000000000000000000000008183015260808401528151808301835260118082527f4f564d5f467261756456657269666965720000000000000000000000000000008284015260a085019190915282518084018452601781527f4f564d5f53746174654d616e61676572466163746f72790000000000000000008184015260c085015282518084018452601c81527f4f564d5f53746174655472616e736974696f6e6572466163746f7279000000008184015260e0850152825180840184529081527f4f564d5f536166657479436865636b65720000000000000000000000000000008183015261010084015281518083018352601981527f4f564d5f4c314d756c74694d65737361676552656c6179657200000000000000818301526101208401528151808301909252600b82527f426f6e644d616e616765720000000000000000000000000000000000000000009082015261014090910152905060005b6011811015611ff75760655473ffffffffffffffffffffffffffffffffffffffff16639b2ea4bd838360118110611f8e57611f8e613267565b602002015160006040518363ffffffff1660e01b8152600401611fb2929190613296565b600060405180830381600087803b158015611fcc57600080fd5b505af1158015611fe0573d6000803e3d6000fd5b505050508080611fef906132ce565b915050611f55565b5050607f805460ff169060006111d0836130cd565b6120146125c3565b607f5460069060ff1681146120ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4261736553797374656d4469637461746f723a20696e636f727265637420737460448201527f65700000000000000000000000000000000000000000000000000000000000006064820152608401610818565b606b54604080517f3f4ba83a000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff90921691633f4ba83a9160048181019260009290919082900301818387803b1580156111a457600080fd5b61211f6125c3565b73ffffffffffffffffffffffffffffffffffffffff81166121c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610818565b6121cb816126e3565b50565b6121d66125c3565b607f5460049060ff16811461226d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4261736553797374656d4469637461746f723a20696e636f727265637420737460448201527f65700000000000000000000000000000000000000000000000000000000000006064820152608401610818565b6065546066546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063f2fde38b90602401600060405180830381600087803b1580156122dc57600080fd5b505af11580156122f0573d6000803e3d6000fd5b5050606c546066546040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152911692506313af40359150602401600060405180830381600087803b15801561236357600080fd5b505af1158015612377573d6000803e3d6000fd5b5050606e546066546040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169250638f2839709150602401611883565b6123dd6125c3565b607f5460ff16600314612472576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f53797374656d4469637461746f723a2063616e206f6e6c79206578697431206260448201527f65666f72652073746570203320697320657865637574656400000000000000006064820152608401610818565b606554607f546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831692639b2ea4bd926124d59263010000009091049091169060040161314c565b600060405180830381600087803b1580156124ef57600080fd5b505af1158015612503573d6000803e3d6000fd5b5050606554604080517f9b2ea4bd0000000000000000000000000000000000000000000000000000000081526004810191909152601160448201527f44544c5f534855544f46465f424c4f434b00000000000000000000000000000060648201526000602482015273ffffffffffffffffffffffffffffffffffffffff9091169250639b2ea4bd9150608401600060405180830381600087803b1580156125a957600080fd5b505af11580156125bd573d6000803e3d6000fd5b50505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314611609576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610818565b600054610100900460ff166126db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610818565b61160961275a565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166127f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610818565b611609336126e3565b6080810181811067ffffffffffffffff82111715612841577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405250565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff821117156128b2577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040525050565b6000604082840312156128cb57600080fd5b6040516040810181811067ffffffffffffffff82111715612915577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823581526020928301359281019290925250919050565b73ffffffffffffffffffffffffffffffffffffffff811681146121cb57600080fd5b803561295c8161292f565b919050565b600060e0828403121561297357600080fd5b60405160e0810181811067ffffffffffffffff821117156129bd577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290508082356129ce8161292f565b815260208301356129de8161292f565b60208201526129ef60408401612951565b6040820152612a0060608401612951565b6060820152612a1160808401612951565b6080820152612a2260a08401612951565b60a0820152612a3360c08401612951565b60c08201525092915050565b6000610100808385031215612a5357600080fd5b6040519081019067ffffffffffffffff82118183101715612a9d577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b81604052809250612aad84612951565b8152612abb60208501612951565b6020820152612acc60408501612951565b6040820152612add60608501612951565b6060820152612aee60808501612951565b6080820152612aff60a08501612951565b60a0820152612b1060c08501612951565b60c0820152612b2160e08501612951565b60e0820152505092915050565b600060c08284031215612b4057600080fd5b60405160c0810167ffffffffffffffff8282108183111715612b8b577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8160405282935084359150612b9f8261292f565b818352602085013560208401526040850135604084015260608501356060840152608085013591508082168214612bd557600080fd5b506080820152612be760a08401612951565b60a08201525092915050565b6000818303610320811215612c0757600080fd5b604051612c13816127fa565b6080821215612c2157600080fd5b6040519150612c2f826127fa565b8335612c3a8161292f565b82526020840135612c4a8161292f565b60208301526040840135612c5d8161292f565b60408301526060840135612c708161292f565b6060830152818152612c858560808601612961565b6020820152612c98856101608601612a3f565b6040820152612cab856102608601612b2e565b6060820152949350505050565b60006103208201905073ffffffffffffffffffffffffffffffffffffffff8087511683528060208801511660208401528060408801511660408401528060608801511660608401528086511660808401528060208701511660a08401528060408701511660c08401528060608701511660e0840152806080870151166101008401525060a0850151612d6361012084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c085015173ffffffffffffffffffffffffffffffffffffffff811661014084015250835173ffffffffffffffffffffffffffffffffffffffff90811661016084015260208501518116610180840152604085015181166101a0840152606085015181166101c0840152608085015181166101e084015260a0850151811661020084015260c0850151811661022084015260e085015116610240830152825173ffffffffffffffffffffffffffffffffffffffff908116610260840152602084015161028084015260408401516102a084015260608401516102c0840152608084015167ffffffffffffffff166102e084015260a0840151166103008301525b95945050505050565b600060208284031215612e7f57600080fd5b8135612e8a8161292f565b9392505050565b60005b83811015612eac578181015183820152602001612e94565b838111156125bd5750506000910152565b60008151808452612ed5816020860160208601612e91565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff808616835280851660208401525060606040830152612e646060830184612ebd565b600060033d1115612f595760046000803e5060005160e01c5b90565b600060443d1015612f6a5790565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc803d016004833e81513d67ffffffffffffffff8160248401118184111715612fb857505050505090565b8285019150815181811115612fd05750505050505090565b843d8701016020828501011115612fea5750505050505090565b612ff960208286010187612847565b509095945050505050565b60008251613016818460208701612e91565b9190910192915050565b7f53797374656d4469637461746f723a20756e6578706563746564206572726f7281527f20696e697469616c697a696e67204c3158444d3a20000000000000000000000060208201526000825161307e816035850160208701612e91565b9190910160350192915050565b602081526000612e8a6020830184612ebd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600060ff821660ff81036130e3576130e361309e565b60010192915050565b60208152600061312960208301601a81527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000602082015260400190565b92915050565b60006020828403121561314157600080fd5b8151612e8a8161292f565b60408152600061318960408301601a81527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000602082015260400190565b905073ffffffffffffffffffffffffffffffffffffffff8316602083015292915050565b73ffffffffffffffffffffffffffffffffffffffff831681526040810160038310613201577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8260208301529392505050565b73ffffffffffffffffffffffffffffffffffffffff82168152604060208201526000612e8a60408301601a81527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000602082015260400190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6040815260006132a96040830185612ebd565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036132ff576132ff61309e565b506001019056fe4f564d5f4465636f6d7072657373696f6e507265636f6d70696c65416464726573734f564d5f436861696e53746f72616765436f6e7461696e65722d4354432d626174636865734f564d5f436861696e53746f72616765436f6e7461696e65722d4354432d7175657565a164736f6c634300080f000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101775760003560e01c806389cb7343116100d8578063d40a71fb1161008c578063f2fde38b11610066578063f2fde38b1461042c578063fb5d73761461043f578063fe6b1ddf1461044757600080fd5b8063d40a71fb14610414578063df4ec2491461041c578063eb7c6f721461042457600080fd5b80638f4ed333116100bd5780638f4ed333146103d2578063b3f05b97146103da578063cf03c22d146103ed57600080fd5b806389cb7343146103715780638da5cb5b1461039357600080fd5b80635bc34f711161012f578063715018a611610114578063715018a61461020357806379502c551461020b5780637d1d95a61461036957600080fd5b80635bc34f71146101e35780636c4a5b1e146101f057600080fd5b806345f003641161016057806345f00364146101be5780634bb278f3146101d35780634fb4bcec146101db57600080fd5b8063204c881c1461017c578063289c6af7146101a4575b600080fd5b607d54607e5461018a919082565b604080519283526020830191909152015b60405180910390f35b6101ac600381565b60405160ff909116815260200161019b565b6101d16101cc3660046128b9565b61044f565b005b6101d1610491565b6101d161077d565b607f546101ac9060ff1681565b6101d16101fe366004612bf3565b6111ec565b6101d16115f7565b604080516080808201835260655473ffffffffffffffffffffffffffffffffffffffff908116835260665481166020808501919091526067548216848601526068548216606080860191909152855160e0808201885260695485168252606a54851682850152606b54851682890152606c54851682840152606d54851682870152606e54851660a080840191909152606f54861660c080850191909152895161010081018b52607054881681526071548816818801526072548816818c01526073548816818701526074548816818a015260755488168184015260765488168183015260775488169381019390935289519081018a526078548716815260795495810195909552607a5498850198909852607b5492840192909252607c5467ffffffffffffffff81169584019590955268010000000000000000909404909216948101949094526103599384565b60405161019b9493929190612cb8565b6101ac600481565b607f5461038390610100900460ff1681565b604051901515815260200161019b565b60335473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101d161160b565b607f546103839062010000900460ff1681565b607f546103ad906301000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6101d161189d565b6101d1611b3e565b6101d161200c565b6101d161043a366004612e6d565b612117565b6101d16121ce565b6101d16123d5565b6104576125c3565b8051607d5560200151607e55607f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b6104996125c3565b606b546068546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063f2fde38b90602401600060405180830381600087803b15801561050857600080fd5b505af115801561051c573d6000803e3d6000fd5b50506066546068546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201529116925063f2fde38b9150602401600060405180830381600087803b15801561058f57600080fd5b505af11580156105a3573d6000803e3d6000fd5b5050607f54600460ff90911611915061074e9050576065546068546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063f2fde38b90602401600060405180830381600087803b15801561062757600080fd5b505af115801561063b573d6000803e3d6000fd5b5050606c546068546040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152911692506313af40359150602401600060405180830381600087803b1580156106ae57600080fd5b505af11580156106c2573d6000803e3d6000fd5b5050606e546068546040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169250638f2839709150602401600060405180830381600087803b15801561073557600080fd5b505af1158015610749573d6000803e3d6000fd5b505050505b607f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff1662010000179055565b6107856125c3565b607f5460059060ff168114610821576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4261736553797374656d4469637461746f723a20696e636f727265637420737460448201527f657000000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b607f54610100900460ff166108b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603c60248201527f53797374656d4469637461746f723a2064796e616d6963206f7261636c65206360448201527f6f6e666967206973206e6f742079657420696e697469616c697a6564000000006064820152608401610818565b606654606954607054607d54607e546040516024810192909252604482015273ffffffffffffffffffffffffffffffffffffffff93841693639623609d938116921690606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fe4a3011600000000000000000000000000000000000000000000000000000000179052517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526109ad93929190600401612f07565b600060405180830381600087803b1580156109c757600080fd5b505af11580156109db573d6000803e3d6000fd5b5050606654606a546071546040805160048082526024820183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8129fc1c0000000000000000000000000000000000000000000000000000000017905291517f9623609d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9586169750639623609d9650610a9895948516949390931692909101612f07565b600060405180830381600087803b158015610ab257600080fd5b505af1158015610ac6573d6000803e3d6000fd5b5050606654606b546072546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b158015610b4457600080fd5b505af1158015610b58573d6000803e3d6000fd5b5050606b546040517fc4d66de800000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116925063c4d66de89150602401600060405180830381600087803b158015610bc757600080fd5b505af1925050508015610bd8575060015b610d3557610be4612f40565b806308c379a003610cab5750610bf8612f5c565b80610c035750610cad565b7f7a2a4e26842155ea933fe6eb6e3137eb5a296dcdf55721c552be7b4c3cc2375981604051602001610c359190613004565b604051602081830303815290604052805190602001201481604051602001610c5d9190613020565b60405160208183030381529060405290610ca4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610818919061308b565b5050610d35565b505b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f53797374656d4469637461746f723a20756e6578706563746564206572726f7260448201527f20696e697469616c697a696e67204c3158444d20286e6f20726561736f6e29006064820152608401610818565b606654606c546076546040805160048082526024820183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fed88c68e0000000000000000000000000000000000000000000000000000000017905291517f9623609d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff95861695639623609d95610deb95908216949116929101612f07565b600060405180830381600087803b158015610e0557600080fd5b505af1158015610e19573d6000803e3d6000fd5b5050606654606c546073546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b158015610e9757600080fd5b505af1158015610eab573d6000803e3d6000fd5b5050606654606d546074546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b5050606654606e546075546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b158015610fbb57600080fd5b505af1158015610fcf573d6000803e3d6000fd5b5050606654606f54607754607854607954607a54607b54607c5460405173ffffffffffffffffffffffffffffffffffffffff958616602482015260448101949094526064840192909252608483015267ffffffffffffffff811660a4830152680100000000000000009004821660c48201529381169550639623609d94509182169291169060e401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8f974d7f00000000000000000000000000000000000000000000000000000000179052517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815261110693929190600401612f07565b600060405180830381600087803b15801561112057600080fd5b505af1158015611134573d6000803e3d6000fd5b5050606b54604080517f8456cb59000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169350638456cb59925060048181019260009290919082900301818387803b1580156111a457600080fd5b505af11580156111b8573d6000803e3d6000fd5b5050607f805460ff169250905060006111d0836130cd565b91906101000a81548160ff021916908360ff1602179055505050565b600054610100900460ff161580801561120c5750600054600160ff909116105b806112265750303b158015611226575060005460ff166001145b6112b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610818565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561131057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b81518051606580547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560208084015160668054841691851691909117905560408085015160678054851691861691909117905560609485015160688054851691861691909117905581870151805160698054861691871691909117905580830151606a8054861691871691909117905580820151606b8054861691871691909117905580860151606c80548616918716919091179055608080820151606d8054871691881691909117905560a080830151606e8054881691891691909117905560c092830151606f80548816918916919091179055838a01518051607080548916918a1691909117905580860151607180548916918a1691909117905580850151607280548916918a1691909117905580890151607380548916918a1691909117905580830151607480548916918a1691909117905580820151607580548916918a169190911790559283015160768054881691891691909117905560e09092015160778054871691881691909117905586890151805160788054909716908816179095559284015160795590830151607a5593820151607b55810151607c8054929094015167ffffffffffffffff9091167fffffffff0000000000000000000000000000000000000000000000000000000090921691909117680100000000000000009190921602179055607f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561156e612644565b6067546115909073ffffffffffffffffffffffffffffffffffffffff166126e3565b80156115f357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115ff6125c3565b61160960006126e3565b565b6116136125c3565b607f5460029060ff1681146116aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4261736553797374656d4469637461746f723a20696e636f727265637420737460448201527f65700000000000000000000000000000000000000000000000000000000000006064820152608401610818565b6065546040517fbf40fac100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac1906116fe906004016130ec565b602060405180830381865afa15801561171b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173f919061312f565b607f80547fffffffffffffffffff0000000000000000000000000000000000000000ffffff16630100000073ffffffffffffffffffffffffffffffffffffffff938416021790556065546040517f9b2ea4bd000000000000000000000000000000000000000000000000000000008152911690639b2ea4bd906117c79060009060040161314c565b600060405180830381600087803b1580156117e157600080fd5b505af11580156117f5573d6000803e3d6000fd5b5050606554604080517f9b2ea4bd0000000000000000000000000000000000000000000000000000000081526004810191909152601160448201527f44544c5f534855544f46465f424c4f434b000000000000000000000000000000606482015273ffffffffffffffffffffffffffffffffffffffff43811660248301529091169250639b2ea4bd91506084015b600060405180830381600087803b1580156111a457600080fd5b6118a56125c3565b607f5460019060ff16811461193c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4261736553797374656d4469637461746f723a20696e636f727265637420737460448201527f65700000000000000000000000000000000000000000000000000000000000006064820152608401610818565b6066546065546040517f0652b57a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152911690630652b57a90602401600060405180830381600087803b1580156119ab57600080fd5b505af11580156119bf573d6000803e3d6000fd5b5050606654606b546040517f8d52d4a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450638d52d4a09350611a2192909116906002906004016131ad565b600060405180830381600087803b158015611a3b57600080fd5b505af1158015611a4f573d6000803e3d6000fd5b5050606654606b546040517f860f7cda00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff928316945063860f7cda9350611aae929091169060040161320e565b600060405180830381600087803b158015611ac857600080fd5b505af1158015611adc573d6000803e3d6000fd5b5050606654606c546040517f8d52d4a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450638d52d4a0935061188392909116906001906004016131ad565b611b466125c3565b607f5460039060ff168114611bdd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4261736553797374656d4469637461746f723a20696e636f727265637420737460448201527f65700000000000000000000000000000000000000000000000000000000000006064820152608401610818565b60006040518061022001604052806040518060400160405280601d81526020017f4f564d5f43616e6f6e6963616c5472616e73616374696f6e436861696e00000081525081526020016040518060400160405280601a81526020017f4f564d5f4c3243726f7373446f6d61696e4d657373656e67657200000000000081525081526020016040518060600160405280602281526020016133076022913981526020016040518060400160405280600d81526020017f4f564d5f53657175656e6365720000000000000000000000000000000000000081525081526020016040518060400160405280600c81526020017f4f564d5f50726f706f7365720000000000000000000000000000000000000000815250815260200160405180606001604052806025815260200161332960259139815260200160405180606001604052806023815260200161334e602391398152604080518082018252601d81527f4f564d5f43616e6f6e6963616c5472616e73616374696f6e436861696e0000006020828101919091528084019190915281518083018352601881527f4f564d5f5374617465436f6d6d69746d656e74436861696e0000000000000000818301528284015281518083018352600f81527f4f564d5f426f6e644d616e61676572000000000000000000000000000000000081830152606084015281518083018352601481527f4f564d5f457865637574696f6e4d616e616765720000000000000000000000008183015260808401528151808301835260118082527f4f564d5f467261756456657269666965720000000000000000000000000000008284015260a085019190915282518084018452601781527f4f564d5f53746174654d616e61676572466163746f72790000000000000000008184015260c085015282518084018452601c81527f4f564d5f53746174655472616e736974696f6e6572466163746f7279000000008184015260e0850152825180840184529081527f4f564d5f536166657479436865636b65720000000000000000000000000000008183015261010084015281518083018352601981527f4f564d5f4c314d756c74694d65737361676552656c6179657200000000000000818301526101208401528151808301909252600b82527f426f6e644d616e616765720000000000000000000000000000000000000000009082015261014090910152905060005b6011811015611ff75760655473ffffffffffffffffffffffffffffffffffffffff16639b2ea4bd838360118110611f8e57611f8e613267565b602002015160006040518363ffffffff1660e01b8152600401611fb2929190613296565b600060405180830381600087803b158015611fcc57600080fd5b505af1158015611fe0573d6000803e3d6000fd5b505050508080611fef906132ce565b915050611f55565b5050607f805460ff169060006111d0836130cd565b6120146125c3565b607f5460069060ff1681146120ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4261736553797374656d4469637461746f723a20696e636f727265637420737460448201527f65700000000000000000000000000000000000000000000000000000000000006064820152608401610818565b606b54604080517f3f4ba83a000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff90921691633f4ba83a9160048181019260009290919082900301818387803b1580156111a457600080fd5b61211f6125c3565b73ffffffffffffffffffffffffffffffffffffffff81166121c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610818565b6121cb816126e3565b50565b6121d66125c3565b607f5460049060ff16811461226d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4261736553797374656d4469637461746f723a20696e636f727265637420737460448201527f65700000000000000000000000000000000000000000000000000000000000006064820152608401610818565b6065546066546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063f2fde38b90602401600060405180830381600087803b1580156122dc57600080fd5b505af11580156122f0573d6000803e3d6000fd5b5050606c546066546040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152911692506313af40359150602401600060405180830381600087803b15801561236357600080fd5b505af1158015612377573d6000803e3d6000fd5b5050606e546066546040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169250638f2839709150602401611883565b6123dd6125c3565b607f5460ff16600314612472576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f53797374656d4469637461746f723a2063616e206f6e6c79206578697431206260448201527f65666f72652073746570203320697320657865637574656400000000000000006064820152608401610818565b606554607f546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831692639b2ea4bd926124d59263010000009091049091169060040161314c565b600060405180830381600087803b1580156124ef57600080fd5b505af1158015612503573d6000803e3d6000fd5b5050606554604080517f9b2ea4bd0000000000000000000000000000000000000000000000000000000081526004810191909152601160448201527f44544c5f534855544f46465f424c4f434b00000000000000000000000000000060648201526000602482015273ffffffffffffffffffffffffffffffffffffffff9091169250639b2ea4bd9150608401600060405180830381600087803b1580156125a957600080fd5b505af11580156125bd573d6000803e3d6000fd5b50505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314611609576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610818565b600054610100900460ff166126db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610818565b61160961275a565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166127f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610818565b611609336126e3565b6080810181811067ffffffffffffffff82111715612841577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405250565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff821117156128b2577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040525050565b6000604082840312156128cb57600080fd5b6040516040810181811067ffffffffffffffff82111715612915577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823581526020928301359281019290925250919050565b73ffffffffffffffffffffffffffffffffffffffff811681146121cb57600080fd5b803561295c8161292f565b919050565b600060e0828403121561297357600080fd5b60405160e0810181811067ffffffffffffffff821117156129bd577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290508082356129ce8161292f565b815260208301356129de8161292f565b60208201526129ef60408401612951565b6040820152612a0060608401612951565b6060820152612a1160808401612951565b6080820152612a2260a08401612951565b60a0820152612a3360c08401612951565b60c08201525092915050565b6000610100808385031215612a5357600080fd5b6040519081019067ffffffffffffffff82118183101715612a9d577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b81604052809250612aad84612951565b8152612abb60208501612951565b6020820152612acc60408501612951565b6040820152612add60608501612951565b6060820152612aee60808501612951565b6080820152612aff60a08501612951565b60a0820152612b1060c08501612951565b60c0820152612b2160e08501612951565b60e0820152505092915050565b600060c08284031215612b4057600080fd5b60405160c0810167ffffffffffffffff8282108183111715612b8b577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8160405282935084359150612b9f8261292f565b818352602085013560208401526040850135604084015260608501356060840152608085013591508082168214612bd557600080fd5b506080820152612be760a08401612951565b60a08201525092915050565b6000818303610320811215612c0757600080fd5b604051612c13816127fa565b6080821215612c2157600080fd5b6040519150612c2f826127fa565b8335612c3a8161292f565b82526020840135612c4a8161292f565b60208301526040840135612c5d8161292f565b60408301526060840135612c708161292f565b6060830152818152612c858560808601612961565b6020820152612c98856101608601612a3f565b6040820152612cab856102608601612b2e565b6060820152949350505050565b60006103208201905073ffffffffffffffffffffffffffffffffffffffff8087511683528060208801511660208401528060408801511660408401528060608801511660608401528086511660808401528060208701511660a08401528060408701511660c08401528060608701511660e0840152806080870151166101008401525060a0850151612d6361012084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c085015173ffffffffffffffffffffffffffffffffffffffff811661014084015250835173ffffffffffffffffffffffffffffffffffffffff90811661016084015260208501518116610180840152604085015181166101a0840152606085015181166101c0840152608085015181166101e084015260a0850151811661020084015260c0850151811661022084015260e085015116610240830152825173ffffffffffffffffffffffffffffffffffffffff908116610260840152602084015161028084015260408401516102a084015260608401516102c0840152608084015167ffffffffffffffff166102e084015260a0840151166103008301525b95945050505050565b600060208284031215612e7f57600080fd5b8135612e8a8161292f565b9392505050565b60005b83811015612eac578181015183820152602001612e94565b838111156125bd5750506000910152565b60008151808452612ed5816020860160208601612e91565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff808616835280851660208401525060606040830152612e646060830184612ebd565b600060033d1115612f595760046000803e5060005160e01c5b90565b600060443d1015612f6a5790565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc803d016004833e81513d67ffffffffffffffff8160248401118184111715612fb857505050505090565b8285019150815181811115612fd05750505050505090565b843d8701016020828501011115612fea5750505050505090565b612ff960208286010187612847565b509095945050505050565b60008251613016818460208701612e91565b9190910192915050565b7f53797374656d4469637461746f723a20756e6578706563746564206572726f7281527f20696e697469616c697a696e67204c3158444d3a20000000000000000000000060208201526000825161307e816035850160208701612e91565b9190910160350192915050565b602081526000612e8a6020830184612ebd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600060ff821660ff81036130e3576130e361309e565b60010192915050565b60208152600061312960208301601a81527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000602082015260400190565b92915050565b60006020828403121561314157600080fd5b8151612e8a8161292f565b60408152600061318960408301601a81527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000602082015260400190565b905073ffffffffffffffffffffffffffffffffffffffff8316602083015292915050565b73ffffffffffffffffffffffffffffffffffffffff831681526040810160038310613201577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8260208301529392505050565b73ffffffffffffffffffffffffffffffffffffffff82168152604060208201526000612e8a60408301601a81527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000602082015260400190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6040815260006132a96040830185612ebd565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036132ff576132ff61309e565b506001019056fe4f564d5f4465636f6d7072657373696f6e507265636f6d70696c65416464726573734f564d5f436861696e53746f72616765436f6e7461696e65722d4354432d626174636865734f564d5f436861696e53746f72616765436f6e7461696e65722d4354432d7175657565a164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "initialize(((address,address,address,address),(address,address,address,address,address,address,address),(address,address,address,address,address,address,address,address),(address,uint256,uint256,bytes32,uint64,address)))": { - "params": { - "_config": "System configuration." - } - }, - "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." - }, - "updateL2OutputOracleDynamicConfig((uint256,uint256))": { - "params": { - "_l2OutputOracleDynamicConfig": "Dynamic L2OutputOracle config." - } - } - }, - "title": "SystemDictator" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "EXIT_1_NO_RETURN_STEP()": { - "notice": "Step after which exit 1 can no longer be used." - }, - "PROXY_TRANSFER_STEP()": { - "notice": "Step where proxy ownership is transferred." - }, - "config()": { - "notice": "System configuration." - }, - "currentStep()": { - "notice": "Current step;" - }, - "dynamicConfigSet()": { - "notice": "Whether or not dynamic config has been set." - }, - "exit1()": { - "notice": "First exit point, can only be called before step 3 is executed." - }, - "finalize()": { - "notice": "Tranfers admin ownership to the final owner." - }, - "finalized()": { - "notice": "Whether or not the deployment is finalized." - }, - "l2OutputOracleDynamicConfig()": { - "notice": "Dynamic configuration for the L2OutputOracle." - }, - "oldL1CrossDomainMessenger()": { - "notice": "Address of the old L1CrossDomainMessenger implementation." - }, - "step1()": { - "notice": "Configures the ProxyAdmin contract." - }, - "step2()": { - "notice": "Pauses the system by shutting down the L1CrossDomainMessenger and setting the deposit halt flag to tell the Sequencer's DTL to stop accepting deposits." - }, - "step3()": { - "notice": "Removes deprecated addresses from the AddressManager." - }, - "step4()": { - "notice": "Transfers system ownership to the ProxyAdmin." - }, - "step5()": { - "notice": "Upgrades and initializes proxy contracts." - }, - "step6()": { - "notice": "Unpauses the system at which point the system should be fully operational." - }, - "updateL2OutputOracleDynamicConfig((uint256,uint256))": { - "notice": "Allows the owner to update dynamic L2OutputOracle config." - } - }, - "notice": "The SystemDictator is responsible for coordinating the deployment of a full Bedrock system. The SystemDictator is designed to support both fresh network deployments and upgrades to existing pre-Bedrock systems." - }, - "storageLayout": { - "storage": [ - { - "astId": 39752, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 39755, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 40366, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 39624, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 39744, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 3575, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "config", - "offset": 0, - "slot": "101", - "type": "t_struct(DeployConfig)3563_storage" - }, - { - "astId": 3579, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l2OutputOracleDynamicConfig", - "offset": 0, - "slot": "125", - "type": "t_struct(L2OutputOracleDynamicConfig)3537_storage" - }, - { - "astId": 3582, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "currentStep", - "offset": 0, - "slot": "127", - "type": "t_uint8" - }, - { - "astId": 3585, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "dynamicConfigSet", - "offset": 1, - "slot": "127", - "type": "t_bool" - }, - { - "astId": 3588, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "finalized", - "offset": 2, - "slot": "127", - "type": "t_bool" - }, - { - "astId": 3591, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "oldL1CrossDomainMessenger", - "offset": 3, - "slot": "127", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_array(t_uint256)50_storage": { - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(AddressManager)5619": { - "encoding": "inplace", - "label": "contract AddressManager", - "numberOfBytes": "20" - }, - "t_contract(L1CrossDomainMessenger)135": { - "encoding": "inplace", - "label": "contract L1CrossDomainMessenger", - "numberOfBytes": "20" - }, - "t_contract(L1ERC721Bridge)335": { - "encoding": "inplace", - "label": "contract L1ERC721Bridge", - "numberOfBytes": "20" - }, - "t_contract(L1StandardBridge)663": { - "encoding": "inplace", - "label": "contract L1StandardBridge", - "numberOfBytes": "20" - }, - "t_contract(L2OutputOracle)1088": { - "encoding": "inplace", - "label": "contract L2OutputOracle", - "numberOfBytes": "20" - }, - "t_contract(OptimismMintableERC20Factory)37809": { - "encoding": "inplace", - "label": "contract OptimismMintableERC20Factory", - "numberOfBytes": "20" - }, - "t_contract(OptimismPortal)1639": { - "encoding": "inplace", - "label": "contract OptimismPortal", - "numberOfBytes": "20" - }, - "t_contract(PortalSender)3450": { - "encoding": "inplace", - "label": "contract PortalSender", - "numberOfBytes": "20" - }, - "t_contract(ProxyAdmin)38861": { - "encoding": "inplace", - "label": "contract ProxyAdmin", - "numberOfBytes": "20" - }, - "t_contract(SystemConfig)2199": { - "encoding": "inplace", - "label": "contract SystemConfig", - "numberOfBytes": "20" - }, - "t_struct(DeployConfig)3563_storage": { - "encoding": "inplace", - "label": "struct SystemDictator.DeployConfig", - "numberOfBytes": "768", - "members": [ - { - "astId": 3553, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "globalConfig", - "offset": 0, - "slot": "0", - "type": "t_struct(GlobalConfig)3492_storage" - }, - { - "astId": 3556, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "proxyAddressConfig", - "offset": 0, - "slot": "4", - "type": "t_struct(ProxyAddressConfig)3507_storage" - }, - { - "astId": 3559, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "implementationAddressConfig", - "offset": 0, - "slot": "11", - "type": "t_struct(ImplementationAddressConfig)3532_storage" - }, - { - "astId": 3562, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "systemConfigConfig", - "offset": 0, - "slot": "19", - "type": "t_struct(SystemConfigConfig)3550_storage" - } - ] - }, - "t_struct(GlobalConfig)3492_storage": { - "encoding": "inplace", - "label": "struct SystemDictator.GlobalConfig", - "numberOfBytes": "128", - "members": [ - { - "astId": 3484, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "addressManager", - "offset": 0, - "slot": "0", - "type": "t_contract(AddressManager)5619" - }, - { - "astId": 3487, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "proxyAdmin", - "offset": 0, - "slot": "1", - "type": "t_contract(ProxyAdmin)38861" - }, - { - "astId": 3489, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "controller", - "offset": 0, - "slot": "2", - "type": "t_address" - }, - { - "astId": 3491, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "finalOwner", - "offset": 0, - "slot": "3", - "type": "t_address" - } - ] - }, - "t_struct(ImplementationAddressConfig)3532_storage": { - "encoding": "inplace", - "label": "struct SystemDictator.ImplementationAddressConfig", - "numberOfBytes": "256", - "members": [ - { - "astId": 3510, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l2OutputOracleImpl", - "offset": 0, - "slot": "0", - "type": "t_contract(L2OutputOracle)1088" - }, - { - "astId": 3513, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "optimismPortalImpl", - "offset": 0, - "slot": "1", - "type": "t_contract(OptimismPortal)1639" - }, - { - "astId": 3516, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l1CrossDomainMessengerImpl", - "offset": 0, - "slot": "2", - "type": "t_contract(L1CrossDomainMessenger)135" - }, - { - "astId": 3519, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l1StandardBridgeImpl", - "offset": 0, - "slot": "3", - "type": "t_contract(L1StandardBridge)663" - }, - { - "astId": 3522, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "optimismMintableERC20FactoryImpl", - "offset": 0, - "slot": "4", - "type": "t_contract(OptimismMintableERC20Factory)37809" - }, - { - "astId": 3525, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l1ERC721BridgeImpl", - "offset": 0, - "slot": "5", - "type": "t_contract(L1ERC721Bridge)335" - }, - { - "astId": 3528, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "portalSenderImpl", - "offset": 0, - "slot": "6", - "type": "t_contract(PortalSender)3450" - }, - { - "astId": 3531, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "systemConfigImpl", - "offset": 0, - "slot": "7", - "type": "t_contract(SystemConfig)2199" - } - ] - }, - "t_struct(L2OutputOracleDynamicConfig)3537_storage": { - "encoding": "inplace", - "label": "struct SystemDictator.L2OutputOracleDynamicConfig", - "numberOfBytes": "64", - "members": [ - { - "astId": 3534, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l2OutputOracleStartingBlockNumber", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 3536, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l2OutputOracleStartingTimestamp", - "offset": 0, - "slot": "1", - "type": "t_uint256" - } - ] - }, - "t_struct(ProxyAddressConfig)3507_storage": { - "encoding": "inplace", - "label": "struct SystemDictator.ProxyAddressConfig", - "numberOfBytes": "224", - "members": [ - { - "astId": 3494, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l2OutputOracleProxy", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 3496, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "optimismPortalProxy", - "offset": 0, - "slot": "1", - "type": "t_address" - }, - { - "astId": 3498, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l1CrossDomainMessengerProxy", - "offset": 0, - "slot": "2", - "type": "t_address" - }, - { - "astId": 3500, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l1StandardBridgeProxy", - "offset": 0, - "slot": "3", - "type": "t_address" - }, - { - "astId": 3502, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "optimismMintableERC20FactoryProxy", - "offset": 0, - "slot": "4", - "type": "t_address" - }, - { - "astId": 3504, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l1ERC721BridgeProxy", - "offset": 0, - "slot": "5", - "type": "t_address" - }, - { - "astId": 3506, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "systemConfigProxy", - "offset": 0, - "slot": "6", - "type": "t_address" - } - ] - }, - "t_struct(SystemConfigConfig)3550_storage": { - "encoding": "inplace", - "label": "struct SystemDictator.SystemConfigConfig", - "numberOfBytes": "160", - "members": [ - { - "astId": 3539, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "owner", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 3541, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "overhead", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 3543, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "scalar", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 3545, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "batcherHash", - "offset": 0, - "slot": "3", - "type": "t_bytes32" - }, - { - "astId": 3547, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "gasLimit", - "offset": 0, - "slot": "4", - "type": "t_uint64" - }, - { - "astId": 3549, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "unsafeBlockSigner", - "offset": 8, - "slot": "4", - "type": "t_address" - } - ] - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint64": { - "encoding": "inplace", - "label": "uint64", - "numberOfBytes": "8" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/SystemDictatorProxy.json b/packages/contracts-bedrock/deployments/goerli/SystemDictatorProxy.json deleted file mode 100644 index 3da70c541f0c..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/SystemDictatorProxy.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "address": "0x1f0613A44c9a8ECE7B3A2e0CdBdF0F5B47A50971", - "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": "0x9718b83cec53331007bb38bbce3481e739784c1e3ea892d32f56a68de7bd2583", - "receipt": { - "to": null, - "from": "0x956a5152D0f498dBA0c5966577bb44262F8F7078", - "contractAddress": "0x1f0613A44c9a8ECE7B3A2e0CdBdF0F5B47A50971", - "transactionIndex": 19, - "gasUsed": "523812", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000800000000000000000000000020000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x00e82f0ff03295b36f55417ba53194c468787db6efdeee96ea3b87c5ad87c2e7", - "transactionHash": "0x9718b83cec53331007bb38bbce3481e739784c1e3ea892d32f56a68de7bd2583", - "logs": [ - { - "transactionIndex": 19, - "blockNumber": 8299688, - "transactionHash": "0x9718b83cec53331007bb38bbce3481e739784c1e3ea892d32f56a68de7bd2583", - "address": "0x1f0613A44c9a8ECE7B3A2e0CdBdF0F5B47A50971", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000956a5152d0f498dba0c5966577bb44262f8f7078", - "logIndex": 41, - "blockHash": "0x00e82f0ff03295b36f55417ba53194c468787db6efdeee96ea3b87c5ad87c2e7" - } - ], - "blockNumber": 8299688, - "cumulativeGasUsed": "3019562", - "status": 1, - "byzantium": true - }, - "args": [ - "0x956a5152D0f498dBA0c5966577bb44262F8F7078" - ], - "numDeployments": 1, - "solcInputHash": "672fbec9734a08fc34112408d6dc7f7b", - "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\":{\"contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0xfa08635f1866139673ac4fe7b07330f752f93800075b895d8fcb8484f4a3f753\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8f2247604d527f560edbb851c43b6c16b37e34972ddb305e16dd73623b8288cd\",\"dweb:/ipfs/QmfM8sLAZrxrnqyRdt1XJ5LyJh4wKbeEqk3VkvxG7BDqFj\"]}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "admin()": { - "returns": { - "_0": "Owner address." - } - }, - "changeAdmin(address)": { - "params": { - "_admin": "New owner of the proxy contract." - } - }, - "constructor": { - "params": { - "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "Address of the implementation contract." - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "Calldata to delegatecall the new implementation with.", - "_implementation": "Address of the implementation contract." - } - } - }, - "events": { - "AdminChanged(address,address)": { - "params": { - "newAdmin": "The new owner of the contract", - "previousAdmin": "The previous owner of the contract" - } - }, - "Upgraded(address)": { - "params": { - "implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "admin()": { - "notice": "Gets the owner of the proxy contract." - }, - "changeAdmin(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "constructor": { - "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." - }, - "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." - } - }, - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." - } - }, - "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/solcInputs/1488cae0dec1a45bfa23bc28dafed7e1.json b/packages/contracts-bedrock/deployments/goerli/solcInputs/1488cae0dec1a45bfa23bc28dafed7e1.json deleted file mode 100644 index 359b0f6a7683..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/solcInputs/1488cae0dec1a45bfa23bc28dafed7e1.json +++ /dev/null @@ -1,552 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/L1/L1CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismPortal } from \"./OptimismPortal.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1CrossDomainMessenger\n * @notice The L1CrossDomainMessenger is a message passing interface between L1 and L2 responsible\n * for sending and receiving data on the L1 side. Users are encouraged to use this\n * interface instead of interacting with lower-level contracts directly.\n */\ncontract L1CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @notice Address of the OptimismPortal.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _portal Address of the OptimismPortal contract on this network.\n */\n constructor(OptimismPortal _portal)\n Semver(1, 1, 0)\n CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER)\n {\n PORTAL = _portal;\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n PORTAL.depositTransaction{ value: _value }(_to, _value, _gasLimit, false, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return msg.sender == address(PORTAL) && PORTAL.l2Sender() == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(PORTAL);\n }\n}\n" - }, - "contracts/L1/L1ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { L2ERC721Bridge } from \"../L2/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 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, 1, 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 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), \"L1ERC721Bridge: 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(OTHER_BRIDGE, message, _minGasLimit);\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L1/L1StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1StandardBridge\n * @notice The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L1, it will be escrowed within this\n * contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was\n * stored within this contract. After Bedrock, ETH is instead stored inside the\n * OptimismPortal contract.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L1StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a deposit of ETH from L1 into L2 is initiated.\n *\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of ETH deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ETHDepositInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal of ETH from L2 to L1 is finalized.\n *\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of ETH withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 withdrawal is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _messenger Address of the L1CrossDomainMessenger.\n */\n constructor(address payable _messenger)\n Semver(1, 1, 0)\n StandardBridge(_messenger, payable(Predeploys.L2_STANDARD_BRIDGE))\n {}\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n */\n receive() external payable override onlyEOA {\n _initiateETHDeposit(msg.sender, msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into the sender's account on L2.\n *\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETH(uint32 _minGasLimit, bytes calldata _extraData) external payable onlyEOA {\n _initiateETHDeposit(msg.sender, msg.sender, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into a target account on L2.\n * Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will\n * be locked in the L2StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n *\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable {\n _initiateETHDeposit(msg.sender, _to, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into the sender's account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20(\n address _l1Token,\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual onlyEOA {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into a target account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20To(\n address _l1Token,\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ETH from L2.\n *\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of ETH to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeETHWithdrawal(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable {\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ERC20 tokens from L2.\n *\n * @param _l1Token Address of the token on L1.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of the ERC20 to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeERC20Withdrawal(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external {\n finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L2 bridge contract.\n *\n * @return Address of the corresponding L2 bridge contract.\n */\n function l2TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @notice Internal function for initiating an ETH deposit.\n *\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateETHDeposit(\n address _from,\n address _to,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n _initiateBridgeETH(_from, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Internal function for initiating an ERC20 deposit.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateERC20Deposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n _initiateBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Emits the legacy ETHDepositInitiated event followed by the ETHBridgeInitiated event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ETHDepositInitiated(_from, _to, _amount, _extraData);\n super._emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ETHWithdrawalFinalized event followed by the ETHBridgeFinalized\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ETHWithdrawalFinalized(_from, _to, _amount, _extraData);\n super._emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ERC20DepositInitiated event followed by the ERC20BridgeInitiated\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ERC20DepositInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ERC20WithdrawalFinalized event followed by the ERC20BridgeFinalized\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ERC20WithdrawalFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/L1/L2OutputOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\n/**\n * @custom:proxied\n * @title L2OutputOracle\n * @notice The L2OutputOracle contains an array of L2 state outputs, where each output is a\n * commitment to the state of the L2 chain. Other contracts like the OptimismPortal use\n * these outputs to verify information about the state of L2.\n */\ncontract L2OutputOracle is Initializable, Semver {\n /**\n * @notice The interval in L2 blocks at which checkpoints must be submitted. Although this is\n * immutable, it can safely be modified by upgrading the implementation contract.\n */\n uint256 public immutable SUBMISSION_INTERVAL;\n\n /**\n * @notice The time between L2 blocks in seconds. Once set, this value MUST NOT be modified.\n */\n uint256 public immutable L2_BLOCK_TIME;\n\n /**\n * @notice The address of the challenger. Can be updated via upgrade.\n */\n address public immutable CHALLENGER;\n\n /**\n * @notice The address of the proposer. Can be updated via upgrade.\n */\n address public immutable PROPOSER;\n\n /**\n * @notice Minimum time (in seconds) that must elapse before a withdrawal can be finalized.\n */\n uint256 public immutable FINALIZATION_PERIOD_SECONDS;\n\n /**\n * @notice The number of the first L2 block recorded in this contract.\n */\n uint256 public startingBlockNumber;\n\n /**\n * @notice The timestamp of the first L2 block recorded in this contract.\n */\n uint256 public startingTimestamp;\n\n /**\n * @notice Array of L2 output proposals.\n */\n Types.OutputProposal[] internal l2Outputs;\n\n /**\n * @notice Emitted when an output is proposed.\n *\n * @param outputRoot The output root.\n * @param l2OutputIndex The index of the output in the l2Outputs array.\n * @param l2BlockNumber The L2 block number of the output root.\n * @param l1Timestamp The L1 timestamp when proposed.\n */\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n /**\n * @notice Emitted when outputs are deleted.\n *\n * @param prevNextOutputIndex Next L2 output index before the deletion.\n * @param newNextOutputIndex Next L2 output index after the deletion.\n */\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n /**\n * @custom:semver 1.2.0\n *\n * @param _submissionInterval Interval in blocks at which checkpoints must be submitted.\n * @param _l2BlockTime The time per L2 block, in seconds.\n * @param _startingBlockNumber The number of the first L2 block.\n * @param _startingTimestamp The timestamp of the first L2 block.\n * @param _proposer The address of the proposer.\n * @param _challenger The address of the challenger.\n */\n constructor(\n uint256 _submissionInterval,\n uint256 _l2BlockTime,\n uint256 _startingBlockNumber,\n uint256 _startingTimestamp,\n address _proposer,\n address _challenger,\n uint256 _finalizationPeriodSeconds\n ) Semver(1, 2, 0) {\n require(_l2BlockTime > 0, \"L2OutputOracle: L2 block time must be greater than 0\");\n require(\n _submissionInterval > _l2BlockTime,\n \"L2OutputOracle: submission interval must be greater than L2 block time\"\n );\n\n SUBMISSION_INTERVAL = _submissionInterval;\n L2_BLOCK_TIME = _l2BlockTime;\n PROPOSER = _proposer;\n CHALLENGER = _challenger;\n FINALIZATION_PERIOD_SECONDS = _finalizationPeriodSeconds;\n\n initialize(_startingBlockNumber, _startingTimestamp);\n }\n\n /**\n * @notice Initializer.\n *\n * @param _startingBlockNumber Block number for the first recoded L2 block.\n * @param _startingTimestamp Timestamp for the first recoded L2 block.\n */\n function initialize(uint256 _startingBlockNumber, uint256 _startingTimestamp)\n public\n initializer\n {\n require(\n _startingTimestamp <= block.timestamp,\n \"L2OutputOracle: starting L2 timestamp must be less than current time\"\n );\n\n startingTimestamp = _startingTimestamp;\n startingBlockNumber = _startingBlockNumber;\n }\n\n /**\n * @notice Deletes all output proposals after and including the proposal that corresponds to\n * the given output index. Only the challenger address can delete outputs.\n *\n * @param _l2OutputIndex Index of the first L2 output to be deleted. All outputs after this\n * output will also be deleted.\n */\n // solhint-disable-next-line ordering\n function deleteL2Outputs(uint256 _l2OutputIndex) external {\n require(\n msg.sender == CHALLENGER,\n \"L2OutputOracle: only the challenger address can delete outputs\"\n );\n\n // Make sure we're not *increasing* the length of the array.\n require(\n _l2OutputIndex < l2Outputs.length,\n \"L2OutputOracle: cannot delete outputs after the latest output index\"\n );\n\n // Do not allow deleting any outputs that have already been finalized.\n require(\n block.timestamp - l2Outputs[_l2OutputIndex].timestamp < FINALIZATION_PERIOD_SECONDS,\n \"L2OutputOracle: cannot delete outputs that have already been finalized\"\n );\n\n uint256 prevNextL2OutputIndex = nextOutputIndex();\n\n // Use assembly to delete the array elements because Solidity doesn't allow it.\n assembly {\n sstore(l2Outputs.slot, _l2OutputIndex)\n }\n\n emit OutputsDeleted(prevNextL2OutputIndex, _l2OutputIndex);\n }\n\n /**\n * @notice Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp\n * must be equal to the current value returned by `nextTimestamp()` in order to be\n * accepted. This function may only be called by the Proposer.\n *\n * @param _outputRoot The L2 output of the checkpoint block.\n * @param _l2BlockNumber The L2 block number that resulted in _outputRoot.\n * @param _l1BlockHash A block hash which must be included in the current chain.\n * @param _l1BlockNumber The block number with the specified block hash.\n */\n function proposeL2Output(\n bytes32 _outputRoot,\n uint256 _l2BlockNumber,\n bytes32 _l1BlockHash,\n uint256 _l1BlockNumber\n ) external payable {\n require(\n msg.sender == PROPOSER,\n \"L2OutputOracle: only the proposer address can propose new outputs\"\n );\n\n require(\n _l2BlockNumber == nextBlockNumber(),\n \"L2OutputOracle: block number must be equal to next expected block number\"\n );\n\n require(\n computeL2Timestamp(_l2BlockNumber) < block.timestamp,\n \"L2OutputOracle: cannot propose L2 output in the future\"\n );\n\n require(\n _outputRoot != bytes32(0),\n \"L2OutputOracle: L2 output proposal cannot be the zero hash\"\n );\n\n if (_l1BlockHash != bytes32(0)) {\n // This check allows the proposer to propose an output based on a given L1 block,\n // without fear that it will be reorged out.\n // It will also revert if the blockheight provided is more than 256 blocks behind the\n // chain tip (as the hash will return as zero). This does open the door to a griefing\n // attack in which the proposer's submission is censored until the block is no longer\n // retrievable, if the proposer is experiencing this attack it can simply leave out the\n // blockhash value, and delay submission until it is confident that the L1 block is\n // finalized.\n require(\n blockhash(_l1BlockNumber) == _l1BlockHash,\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n }\n\n emit OutputProposed(_outputRoot, nextOutputIndex(), _l2BlockNumber, block.timestamp);\n\n l2Outputs.push(\n Types.OutputProposal({\n outputRoot: _outputRoot,\n timestamp: uint128(block.timestamp),\n l2BlockNumber: uint128(_l2BlockNumber)\n })\n );\n }\n\n /**\n * @notice Returns an output by index. Exists because Solidity's array access will return a\n * tuple instead of a struct.\n *\n * @param _l2OutputIndex Index of the output to return.\n *\n * @return The output at the given index.\n */\n function getL2Output(uint256 _l2OutputIndex)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[_l2OutputIndex];\n }\n\n /**\n * @notice Returns the index of the L2 output that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return Index of the first checkpoint that commits to the given L2 block number.\n */\n function getL2OutputIndexAfter(uint256 _l2BlockNumber) public view returns (uint256) {\n // Make sure an output for this block number has actually been proposed.\n require(\n _l2BlockNumber <= latestBlockNumber(),\n \"L2OutputOracle: cannot get output for a block that has not been proposed\"\n );\n\n // Make sure there's at least one output proposed.\n require(\n l2Outputs.length > 0,\n \"L2OutputOracle: cannot get output as no outputs have been proposed yet\"\n );\n\n // Find the output via binary search, guaranteed to exist.\n uint256 lo = 0;\n uint256 hi = l2Outputs.length;\n while (lo < hi) {\n uint256 mid = (lo + hi) / 2;\n if (l2Outputs[mid].l2BlockNumber < _l2BlockNumber) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n return lo;\n }\n\n /**\n * @notice Returns the L2 output proposal that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return First checkpoint that commits to the given L2 block number.\n */\n function getL2OutputAfter(uint256 _l2BlockNumber)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[getL2OutputIndexAfter(_l2BlockNumber)];\n }\n\n /**\n * @notice Returns the number of outputs that have been proposed. Will revert if no outputs\n * have been proposed yet.\n *\n * @return The number of outputs that have been proposed.\n */\n function latestOutputIndex() external view returns (uint256) {\n return l2Outputs.length - 1;\n }\n\n /**\n * @notice Returns the index of the next output to be proposed.\n *\n * @return The index of the next output to be proposed.\n */\n function nextOutputIndex() public view returns (uint256) {\n return l2Outputs.length;\n }\n\n /**\n * @notice Returns the block number of the latest submitted L2 output proposal. If no proposals\n * been submitted yet then this function will return the starting block number.\n *\n * @return Latest submitted L2 block number.\n */\n function latestBlockNumber() public view returns (uint256) {\n return\n l2Outputs.length == 0\n ? startingBlockNumber\n : l2Outputs[l2Outputs.length - 1].l2BlockNumber;\n }\n\n /**\n * @notice Computes the block number of the next L2 block that needs to be checkpointed.\n *\n * @return Next L2 block number.\n */\n function nextBlockNumber() public view returns (uint256) {\n return latestBlockNumber() + SUBMISSION_INTERVAL;\n }\n\n /**\n * @notice Returns the L2 timestamp corresponding to a given L2 block number.\n *\n * @param _l2BlockNumber The L2 block number of the target block.\n *\n * @return L2 timestamp of the given block.\n */\n function computeL2Timestamp(uint256 _l2BlockNumber) public view returns (uint256) {\n return startingTimestamp + ((_l2BlockNumber - startingBlockNumber) * L2_BLOCK_TIME);\n }\n}\n" - }, - "contracts/L1/OptimismPortal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { L2OutputOracle } from \"./L2OutputOracle.sol\";\nimport { SystemConfig } from \"./SystemConfig.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { SecureMerkleTrie } from \"../libraries/trie/SecureMerkleTrie.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ResourceMetering } from \"./ResourceMetering.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title OptimismPortal\n * @notice The OptimismPortal is a low-level contract responsible for passing messages between L1\n * and L2. Messages sent directly to the OptimismPortal have no form of replayability.\n * Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface.\n */\ncontract OptimismPortal is Initializable, ResourceMetering, Semver {\n /**\n * @notice Represents a proven withdrawal.\n *\n * @custom:field outputRoot Root of the L2 output this was proven against.\n * @custom:field timestamp Timestamp at whcih the withdrawal was proven.\n * @custom:field l2OutputIndex Index of the output this was proven against.\n */\n struct ProvenWithdrawal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2OutputIndex;\n }\n\n /**\n * @notice Version of the deposit event.\n */\n uint256 internal constant DEPOSIT_VERSION = 0;\n\n /**\n * @notice The L2 gas limit set when eth is deposited using the receive() function.\n */\n uint64 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Address of the L2OutputOracle contract.\n */\n L2OutputOracle public immutable L2_ORACLE;\n\n /**\n * @notice Address of the SystemConfig contract.\n */\n SystemConfig public immutable SYSTEM_CONFIG;\n\n /**\n * @notice Address that has the ability to pause and unpause withdrawals.\n */\n address public immutable GUARDIAN;\n\n /**\n * @notice Address of the L2 account which initiated a withdrawal in this transaction. If the\n * of this variable is the default L2 sender address, then we are NOT inside of a call\n * to finalizeWithdrawalTransaction.\n */\n address public l2Sender;\n\n /**\n * @notice A list of withdrawal hashes which have been successfully finalized.\n */\n mapping(bytes32 => bool) public finalizedWithdrawals;\n\n /**\n * @notice A mapping of withdrawal hashes to `ProvenWithdrawal` data.\n */\n mapping(bytes32 => ProvenWithdrawal) public provenWithdrawals;\n\n /**\n * @notice Determines if cross domain messaging is paused. When set to true,\n * deposits and withdrawals are paused. This may be removed in the\n * future.\n */\n bool public paused;\n\n /**\n * @notice Emitted when a transaction is deposited from L1 to L2. The parameters of this event\n * are read by the rollup node and used to derive deposit transactions on L2.\n *\n * @param from Address that triggered the deposit transaction.\n * @param to Address that the deposit transaction is directed to.\n * @param version Version of this deposit transaction event.\n * @param opaqueData ABI encoded deposit data to be parsed off-chain.\n */\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is proven.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n */\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is finalized.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n * @param success Whether the withdrawal transaction was successful.\n */\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n\n /**\n * @notice Emitted when the pause is triggered.\n *\n * @param account Address of the account triggering the pause.\n */\n event Paused(address account);\n\n /**\n * @notice Emitted when the pause is lifted.\n *\n * @param account Address of the account triggering the unpause.\n */\n event Unpaused(address account);\n\n /**\n * @notice Reverts when paused.\n */\n modifier whenNotPaused() {\n require(paused == false, \"OptimismPortal: paused\");\n _;\n }\n\n /**\n * @custom:semver 1.3.0\n *\n * @param _l2Oracle Address of the L2OutputOracle contract.\n * @param _guardian Address that can pause deposits and withdrawals.\n * @param _paused Sets the contract's pausability state.\n * @param _config Address of the SystemConfig contract.\n */\n constructor(\n L2OutputOracle _l2Oracle,\n address _guardian,\n bool _paused,\n SystemConfig _config\n ) Semver(1, 3, 0) {\n L2_ORACLE = _l2Oracle;\n GUARDIAN = _guardian;\n SYSTEM_CONFIG = _config;\n initialize(_paused);\n }\n\n /**\n * @notice Initializer.\n */\n function initialize(bool _paused) public initializer {\n l2Sender = Constants.DEFAULT_L2_SENDER;\n paused = _paused;\n __ResourceMetering_init();\n }\n\n /**\n * @notice Pause deposits and withdrawals.\n */\n function pause() external {\n require(msg.sender == GUARDIAN, \"OptimismPortal: only guardian can pause\");\n paused = true;\n emit Paused(msg.sender);\n }\n\n /**\n * @notice Unpause deposits and withdrawals.\n */\n function unpause() external {\n require(msg.sender == GUARDIAN, \"OptimismPortal: only guardian can unpause\");\n paused = false;\n emit Unpaused(msg.sender);\n }\n\n /**\n * @notice Accepts value so that users can send ETH directly to this contract and have the\n * funds be deposited to their address on L2. This is intended as a convenience\n * function for EOAs. Contracts should call the depositTransaction() function directly\n * otherwise any deposited funds will be lost due to address aliasing.\n */\n // solhint-disable-next-line ordering\n receive() external payable {\n depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes(\"\"));\n }\n\n /**\n * @notice Accepts ETH value without triggering a deposit to L2. This function mainly exists\n * for the sake of the migration between the legacy Optimism system and Bedrock.\n */\n function donateETH() external payable {\n // Intentionally empty.\n }\n\n /**\n * @notice Getter for the resource config. Used internally by the ResourceMetering\n * contract. The SystemConfig is the source of truth for the resource config.\n *\n * @return ResourceMetering.ResourceConfig\n */\n function _resourceConfig()\n internal\n view\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return SYSTEM_CONFIG.resourceConfig();\n }\n\n /**\n * @notice Proves a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n * @param _l2OutputIndex L2 output index to prove against.\n * @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root.\n * @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract.\n */\n function proveWithdrawalTransaction(\n Types.WithdrawalTransaction memory _tx,\n uint256 _l2OutputIndex,\n Types.OutputRootProof calldata _outputRootProof,\n bytes[] calldata _withdrawalProof\n ) external whenNotPaused {\n // Prevent users from creating a deposit transaction where this address is the message\n // sender on L2. Because this is checked here, we do not need to check again in\n // `finalizeWithdrawalTransaction`.\n require(\n _tx.target != address(this),\n \"OptimismPortal: you cannot send messages to the portal contract\"\n );\n\n // Get the output root and load onto the stack to prevent multiple mloads. This will\n // revert if there is no output root for the given block number.\n bytes32 outputRoot = L2_ORACLE.getL2Output(_l2OutputIndex).outputRoot;\n\n // Verify that the output root can be generated with the elements in the proof.\n require(\n outputRoot == Hashing.hashOutputRootProof(_outputRootProof),\n \"OptimismPortal: invalid output root proof\"\n );\n\n // Load the ProvenWithdrawal into memory, using the withdrawal hash as a unique identifier.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // We generally want to prevent users from proving the same withdrawal multiple times\n // because each successive proof will update the timestamp. A malicious user can take\n // advantage of this to prevent other users from finalizing their withdrawal. However,\n // since withdrawals are proven before an output root is finalized, we need to allow users\n // to re-prove their withdrawal only in the case that the output root for their specified\n // output index has been updated.\n require(\n provenWithdrawal.timestamp == 0 ||\n L2_ORACLE.getL2Output(provenWithdrawal.l2OutputIndex).outputRoot !=\n provenWithdrawal.outputRoot,\n \"OptimismPortal: withdrawal hash has already been proven\"\n );\n\n // Compute the storage slot of the withdrawal hash in the L2ToL1MessagePasser contract.\n // Refer to the Solidity documentation for more information on how storage layouts are\n // computed for mappings.\n bytes32 storageKey = keccak256(\n abi.encode(\n withdrawalHash,\n uint256(0) // The withdrawals mapping is at the first slot in the layout.\n )\n );\n\n // Verify that the hash of this withdrawal was stored in the L2toL1MessagePasser contract\n // on L2. If this is true, under the assumption that the SecureMerkleTrie does not have\n // bugs, then we know that this withdrawal was actually triggered on L2 and can therefore\n // be relayed on L1.\n require(\n SecureMerkleTrie.verifyInclusionProof(\n abi.encode(storageKey),\n hex\"01\",\n _withdrawalProof,\n _outputRootProof.messagePasserStorageRoot\n ),\n \"OptimismPortal: invalid withdrawal inclusion proof\"\n );\n\n // Designate the withdrawalHash as proven by storing the `outputRoot`, `timestamp`, and\n // `l2BlockNumber` in the `provenWithdrawals` mapping. A `withdrawalHash` can only be\n // proven once unless it is submitted again with a different outputRoot.\n provenWithdrawals[withdrawalHash] = ProvenWithdrawal({\n outputRoot: outputRoot,\n timestamp: uint128(block.timestamp),\n l2OutputIndex: uint128(_l2OutputIndex)\n });\n\n // Emit a `WithdrawalProven` event.\n emit WithdrawalProven(withdrawalHash, _tx.sender, _tx.target);\n }\n\n /**\n * @notice Finalizes a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n */\n function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx)\n external\n whenNotPaused\n {\n // Make sure that the l2Sender has not yet been set. The l2Sender is set to a value other\n // than the default value when a withdrawal transaction is being finalized. This check is\n // a defacto reentrancy guard.\n require(\n l2Sender == Constants.DEFAULT_L2_SENDER,\n \"OptimismPortal: can only trigger one withdrawal per transaction\"\n );\n\n // Grab the proven withdrawal from the `provenWithdrawals` map.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // A withdrawal can only be finalized if it has been proven. We know that a withdrawal has\n // been proven at least once when its timestamp is non-zero. Unproven withdrawals will have\n // a timestamp of zero.\n require(\n provenWithdrawal.timestamp != 0,\n \"OptimismPortal: withdrawal has not been proven yet\"\n );\n\n // As a sanity check, we make sure that the proven withdrawal's timestamp is greater than\n // starting timestamp inside the L2OutputOracle. Not strictly necessary but extra layer of\n // safety against weird bugs in the proving step.\n require(\n provenWithdrawal.timestamp >= L2_ORACLE.startingTimestamp(),\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n\n // A proven withdrawal must wait at least the finalization period before it can be\n // finalized. This waiting period can elapse in parallel with the waiting period for the\n // output the withdrawal was proven against. In effect, this means that the minimum\n // withdrawal time is proposal submission time + finalization period.\n require(\n _isFinalizationPeriodElapsed(provenWithdrawal.timestamp),\n \"OptimismPortal: proven withdrawal finalization period has not elapsed\"\n );\n\n // Grab the OutputProposal from the L2OutputOracle, will revert if the output that\n // corresponds to the given index has not been proposed yet.\n Types.OutputProposal memory proposal = L2_ORACLE.getL2Output(\n provenWithdrawal.l2OutputIndex\n );\n\n // Check that the output root that was used to prove the withdrawal is the same as the\n // current output root for the given output index. An output root may change if it is\n // deleted by the challenger address and then re-proposed.\n require(\n proposal.outputRoot == provenWithdrawal.outputRoot,\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n\n // Check that the output proposal has also been finalized.\n require(\n _isFinalizationPeriodElapsed(proposal.timestamp),\n \"OptimismPortal: output proposal finalization period has not elapsed\"\n );\n\n // Check that this withdrawal has not already been finalized, this is replay protection.\n require(\n finalizedWithdrawals[withdrawalHash] == false,\n \"OptimismPortal: withdrawal has already been finalized\"\n );\n\n // Mark the withdrawal as finalized so it can't be replayed.\n finalizedWithdrawals[withdrawalHash] = true;\n\n // Set the l2Sender so contracts know who triggered this withdrawal on L2.\n l2Sender = _tx.sender;\n\n // Trigger the call to the target contract. We use a custom low level method\n // SafeCall.callWithMinGas to ensure two key properties\n // 1. Target contracts cannot force this call to run out of gas by returning a very large\n // amount of data (and this is OK because we don't care about the returndata here).\n // 2. The amount of gas provided to the call to the target contract is at least the gas\n // limit specified by the user. If there is not enough gas in the callframe to\n // accomplish this, `callWithMinGas` will revert.\n // Additionally, if there is not enough gas remaining to complete the execution after the\n // call returns, this function will revert.\n bool success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, _tx.value, _tx.data);\n\n // Reset the l2Sender back to the default value.\n l2Sender = Constants.DEFAULT_L2_SENDER;\n\n // All withdrawals are immediately finalized. Replayability can\n // be achieved through contracts built on top of this contract\n emit WithdrawalFinalized(withdrawalHash, success);\n\n // Reverting here is useful for determining the exact gas cost to successfully execute the\n // sub call to the target contract if the minimum gas limit specified by the user would not\n // be sufficient to execute the sub call.\n if (success == false && tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"OptimismPortal: withdrawal failed\");\n }\n }\n\n /**\n * @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in\n * deriving deposit transactions. Note that if a deposit is made by a contract, its\n * address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider\n * using the CrossDomainMessenger contracts for a simpler developer experience.\n *\n * @param _to Target address on L2.\n * @param _value ETH value to send to the recipient.\n * @param _gasLimit Minimum L2 gas limit (can be greater than or equal to this value).\n * @param _isCreation Whether or not the transaction is a contract creation.\n * @param _data Data to trigger the recipient with.\n */\n function depositTransaction(\n address _to,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable metered(_gasLimit) {\n // Just to be safe, make sure that people specify address(0) as the target when doing\n // contract creations.\n if (_isCreation) {\n require(\n _to == address(0),\n \"OptimismPortal: must send to address(0) when creating a contract\"\n );\n }\n\n // Prevent depositing transactions that have too small of a gas limit.\n require(_gasLimit >= 21_000, \"OptimismPortal: gas limit must cover instrinsic gas cost\");\n\n // Transform the from-address to its alias if the caller is a contract.\n address from = msg.sender;\n if (msg.sender != tx.origin) {\n from = AddressAliasHelper.applyL1ToL2Alias(msg.sender);\n }\n\n // Compute the opaque data that will be emitted as part of the TransactionDeposited event.\n // We use opaque data so that we can update the TransactionDeposited event in the future\n // without breaking the current interface.\n bytes memory opaqueData = abi.encodePacked(\n msg.value,\n _value,\n _gasLimit,\n _isCreation,\n _data\n );\n\n // Emit a TransactionDeposited event so that the rollup node can derive a deposit\n // transaction for this deposit.\n emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData);\n }\n\n /**\n * @notice Determine if a given output is finalized. Reverts if the call to\n * L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.\n *\n * @param _l2OutputIndex Index of the L2 output to check.\n *\n * @return Whether or not the output is finalized.\n */\n function isOutputFinalized(uint256 _l2OutputIndex) external view returns (bool) {\n return _isFinalizationPeriodElapsed(L2_ORACLE.getL2Output(_l2OutputIndex).timestamp);\n }\n\n /**\n * @notice Determines whether the finalization period has elapsed w/r/t a given timestamp.\n *\n * @param _timestamp Timestamp to check.\n *\n * @return Whether or not the finalization period has elapsed.\n */\n function _isFinalizationPeriodElapsed(uint256 _timestamp) internal view returns (bool) {\n return block.timestamp > _timestamp + L2_ORACLE.FINALIZATION_PERIOD_SECONDS();\n }\n}\n" - }, - "contracts/L1/ResourceMetering.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\n\n/**\n * @custom:upgradeable\n * @title ResourceMetering\n * @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing\n * updates automatically based on current demand.\n */\nabstract contract ResourceMetering is Initializable {\n /**\n * @notice Represents the various parameters that control the way in which resources are\n * metered. Corresponds to the EIP-1559 resource metering system.\n *\n * @custom:field prevBaseFee Base fee from the previous block(s).\n * @custom:field prevBoughtGas Amount of gas bought so far in the current block.\n * @custom:field prevBlockNum Last block number that the base fee was updated.\n */\n struct ResourceParams {\n uint128 prevBaseFee;\n uint64 prevBoughtGas;\n uint64 prevBlockNum;\n }\n\n /**\n * @notice Represents the configuration for the EIP-1559 based curve for the deposit gas\n * market. These values should be set with care as it is possible to set them in\n * a way that breaks the deposit gas market. The target resource limit is defined as\n * maxResourceLimit / elasticityMultiplier. This struct was designed to fit within a\n * single word. There is additional space for additions in the future.\n *\n * @custom:field maxResourceLimit Represents the maximum amount of deposit gas that\n * can be purchased per block.\n * @custom:field elasticityMultiplier Determines the target resource limit along with\n * the resource limit.\n * @custom:field baseFeeMaxChangeDenominator Determines max change on fee per block.\n * @custom:field minimumBaseFee The min deposit base fee, it is clamped to this\n * value.\n * @custom:field systemTxMaxGas The amount of gas supplied to the system\n * transaction. This should be set to the same number\n * that the op-node sets as the gas limit for the\n * system transaction.\n * @custom:field maximumBaseFee The max deposit base fee, it is clamped to this\n * value.\n */\n struct ResourceConfig {\n uint32 maxResourceLimit;\n uint8 elasticityMultiplier;\n uint8 baseFeeMaxChangeDenominator;\n uint32 minimumBaseFee;\n uint32 systemTxMaxGas;\n uint128 maximumBaseFee;\n }\n\n /**\n * @notice EIP-1559 style gas parameters.\n */\n ResourceParams public params;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n */\n uint256[48] private __gap;\n\n /**\n * @notice Meters access to a function based an amount of a requested resource.\n *\n * @param _amount Amount of the resource requested.\n */\n modifier metered(uint64 _amount) {\n // Record initial gas amount so we can refund for it later.\n uint256 initialGas = gasleft();\n\n // Run the underlying function.\n _;\n\n // Run the metering function.\n _metered(_amount, initialGas);\n }\n\n /**\n * @notice An internal function that holds all of the logic for metering a resource.\n *\n * @param _amount Amount of the resource requested.\n * @param _initialGas The amount of gas before any modifier execution.\n */\n function _metered(uint64 _amount, uint256 _initialGas) internal {\n // Update block number and base fee if necessary.\n uint256 blockDiff = block.number - params.prevBlockNum;\n\n ResourceConfig memory config = _resourceConfig();\n int256 targetResourceLimit = int256(uint256(config.maxResourceLimit)) /\n int256(uint256(config.elasticityMultiplier));\n\n if (blockDiff > 0) {\n // Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate\n // at which deposits can be created and therefore limit the potential for deposits to\n // spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes.\n int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - targetResourceLimit;\n int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) /\n (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator)));\n\n // Update base fee by adding the base fee delta and clamp the resulting value between\n // min and max.\n int256 newBaseFee = Arithmetic.clamp({\n _value: int256(uint256(params.prevBaseFee)) + baseFeeDelta,\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n\n // If we skipped more than one block, we also need to account for every empty block.\n // Empty block means there was no demand for deposits in that block, so we should\n // reflect this lack of demand in the fee.\n if (blockDiff > 1) {\n // Update the base fee by repeatedly applying the exponent 1-(1/change_denominator)\n // blockDiff - 1 times. Simulates multiple empty blocks. Clamp the resulting value\n // between min and max.\n newBaseFee = Arithmetic.clamp({\n _value: Arithmetic.cdexp({\n _coefficient: newBaseFee,\n _denominator: int256(uint256(config.baseFeeMaxChangeDenominator)),\n _exponent: int256(blockDiff - 1)\n }),\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n }\n\n // Update new base fee, reset bought gas, and update block number.\n params.prevBaseFee = uint128(uint256(newBaseFee));\n params.prevBoughtGas = 0;\n params.prevBlockNum = uint64(block.number);\n }\n\n // Make sure we can actually buy the resource amount requested by the user.\n params.prevBoughtGas += _amount;\n require(\n int256(uint256(params.prevBoughtGas)) <= int256(uint256(config.maxResourceLimit)),\n \"ResourceMetering: cannot buy more gas than available gas limit\"\n );\n\n // Determine the amount of ETH to be paid.\n uint256 resourceCost = uint256(_amount) * uint256(params.prevBaseFee);\n\n // We currently charge for this ETH amount as an L1 gas burn, so we convert the ETH amount\n // into gas by dividing by the L1 base fee. We assume a minimum base fee of 1 gwei to avoid\n // division by zero for L1s that don't support 1559 or to avoid excessive gas burns during\n // periods of extremely low L1 demand. One-day average gas fee hasn't dipped below 1 gwei\n // during any 1 day period in the last 5 years, so should be fine.\n uint256 gasCost = resourceCost / Math.max(block.basefee, 1 gwei);\n\n // Give the user a refund based on the amount of gas they used to do all of the work up to\n // this point. Since we're at the end of the modifier, this should be pretty accurate. Acts\n // effectively like a dynamic stipend (with a minimum value).\n uint256 usedGas = _initialGas - gasleft();\n if (gasCost > usedGas) {\n Burn.gas(gasCost - usedGas);\n }\n }\n\n /**\n * @notice Virtual function that returns the resource config. Contracts that inherit this\n * contract must implement this function.\n *\n * @return ResourceConfig\n */\n function _resourceConfig() internal virtual returns (ResourceConfig memory);\n\n /**\n * @notice Sets initial resource parameter values. This function must either be called by the\n * initializer function of an upgradeable child contract.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __ResourceMetering_init() internal onlyInitializing {\n params = ResourceParams({\n prevBaseFee: 1 gwei,\n prevBoughtGas: 0,\n prevBlockNum: uint64(block.number)\n });\n }\n}\n" - }, - "contracts/L1/SystemConfig.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { ResourceMetering } from \"./ResourceMetering.sol\";\n\n/**\n * @title SystemConfig\n * @notice The SystemConfig contract is used to manage configuration of an Optimism network. All\n * configuration is stored on L1 and picked up by L2 as part of the derviation of the L2\n * chain.\n */\ncontract SystemConfig is OwnableUpgradeable, Semver {\n /**\n * @notice Enum representing different types of updates.\n *\n * @custom:value BATCHER Represents an update to the batcher hash.\n * @custom:value GAS_CONFIG Represents an update to txn fee config on L2.\n * @custom:value GAS_LIMIT Represents an update to gas limit on L2.\n * @custom:value UNSAFE_BLOCK_SIGNER Represents an update to the signer key for unsafe\n * block distrubution.\n */\n enum UpdateType {\n BATCHER,\n GAS_CONFIG,\n GAS_LIMIT,\n UNSAFE_BLOCK_SIGNER\n }\n\n /**\n * @notice Version identifier, used for upgrades.\n */\n uint256 public constant VERSION = 0;\n\n /**\n * @notice Storage slot that the unsafe block signer is stored at. Storing it at this\n * deterministic storage slot allows for decoupling the storage layout from the way\n * that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value.\n */\n bytes32 public constant UNSAFE_BLOCK_SIGNER_SLOT = keccak256(\"systemconfig.unsafeblocksigner\");\n\n /**\n * @notice Minimum gas limit. This should not be lower than the maximum deposit gas resource\n * limit in the ResourceMetering contract used by OptimismPortal, to ensure the L2\n * block always has sufficient gas to process deposits.\n */\n uint64 public constant MINIMUM_GAS_LIMIT = 8_000_000;\n\n /**\n * @notice Fixed L2 gas overhead. Used as part of the L2 fee calculation.\n */\n uint256 public overhead;\n\n /**\n * @notice Dynamic L2 gas overhead. Used as part of the L2 fee calculation.\n */\n uint256 public scalar;\n\n /**\n * @notice Identifier for the batcher. For version 1 of this configuration, this is represented\n * as an address left-padded with zeros to 32 bytes.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice L2 block gas limit.\n */\n uint64 public gasLimit;\n\n /**\n * @notice The configuration for the deposit fee market. Used by the OptimismPortal\n * to meter the cost of buying L2 gas on L1. Set as internal and wrapped with a getter\n * so that the struct is returned instead of a tuple.\n */\n ResourceMetering.ResourceConfig internal _resourceConfig;\n\n /**\n * @notice Emitted when configuration is updated\n *\n * @param version SystemConfig version.\n * @param updateType Type of update.\n * @param data Encoded update data.\n */\n event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n * @param _unsafeBlockSigner Initial unsafe block signer address.\n * @param _config Initial resource config.\n */\n constructor(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner,\n ResourceMetering.ResourceConfig memory _config\n ) Semver(1, 1, 0) {\n initialize({\n _owner: _owner,\n _overhead: _overhead,\n _scalar: _scalar,\n _batcherHash: _batcherHash,\n _gasLimit: _gasLimit,\n _unsafeBlockSigner: _unsafeBlockSigner,\n _config: _config\n });\n }\n\n /**\n * @notice Initializer. The resource config must be set before the\n * require check.\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n * @param _unsafeBlockSigner Initial unsafe block signer address.\n * @param _config Initial ResourceConfig.\n */\n function initialize(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner,\n ResourceMetering.ResourceConfig memory _config\n ) public initializer {\n __Ownable_init();\n transferOwnership(_owner);\n overhead = _overhead;\n scalar = _scalar;\n batcherHash = _batcherHash;\n gasLimit = _gasLimit;\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n _setResourceConfig(_config);\n require(_gasLimit >= minimumGasLimit(), \"SystemConfig: gas limit too low\");\n }\n\n /**\n * @notice Returns the minimum L2 gas limit that can be safely set for the system to\n * operate. The L2 gas limit must be larger than or equal to the amount of\n * gas that is allocated for deposits per block plus the amount of gas that\n * is allocated for the system transaction.\n * This function is used to determine if changes to parameters are safe.\n *\n * @return uint64\n */\n function minimumGasLimit() public view returns (uint64) {\n return uint64(_resourceConfig.maxResourceLimit) + uint64(_resourceConfig.systemTxMaxGas);\n }\n\n /**\n * @notice High level getter for the unsafe block signer address. Unsafe blocks can be\n * propagated across the p2p network if they are signed by the key corresponding to\n * this address.\n *\n * @return Address of the unsafe block signer.\n */\n // solhint-disable-next-line ordering\n function unsafeBlockSigner() external view returns (address) {\n address addr;\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n addr := sload(slot)\n }\n return addr;\n }\n\n /**\n * @notice Updates the unsafe block signer address.\n *\n * @param _unsafeBlockSigner New unsafe block signer address.\n */\n function setUnsafeBlockSigner(address _unsafeBlockSigner) external onlyOwner {\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n\n bytes memory data = abi.encode(_unsafeBlockSigner);\n emit ConfigUpdate(VERSION, UpdateType.UNSAFE_BLOCK_SIGNER, data);\n }\n\n /**\n * @notice Updates the batcher hash.\n *\n * @param _batcherHash New batcher hash.\n */\n function setBatcherHash(bytes32 _batcherHash) external onlyOwner {\n batcherHash = _batcherHash;\n\n bytes memory data = abi.encode(_batcherHash);\n emit ConfigUpdate(VERSION, UpdateType.BATCHER, data);\n }\n\n /**\n * @notice Updates gas config.\n *\n * @param _overhead New overhead value.\n * @param _scalar New scalar value.\n */\n function setGasConfig(uint256 _overhead, uint256 _scalar) external onlyOwner {\n overhead = _overhead;\n scalar = _scalar;\n\n bytes memory data = abi.encode(_overhead, _scalar);\n emit ConfigUpdate(VERSION, UpdateType.GAS_CONFIG, data);\n }\n\n /**\n * @notice Updates the L2 gas limit.\n *\n * @param _gasLimit New gas limit.\n */\n function setGasLimit(uint64 _gasLimit) external onlyOwner {\n require(_gasLimit >= minimumGasLimit(), \"SystemConfig: gas limit too low\");\n gasLimit = _gasLimit;\n\n bytes memory data = abi.encode(_gasLimit);\n emit ConfigUpdate(VERSION, UpdateType.GAS_LIMIT, data);\n }\n\n /**\n * @notice Low level setter for the unsafe block signer address. This function exists to\n * deduplicate code around storing the unsafeBlockSigner address in storage.\n *\n * @param _unsafeBlockSigner New unsafeBlockSigner value.\n */\n function _setUnsafeBlockSigner(address _unsafeBlockSigner) internal {\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n sstore(slot, _unsafeBlockSigner)\n }\n }\n\n /**\n * @notice A getter for the resource config. Ensures that the struct is\n * returned instead of a tuple.\n *\n * @return ResourceConfig\n */\n function resourceConfig() external view returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig;\n }\n\n /**\n * @notice An external setter for the resource config. In the future, this\n * method may emit an event that the `op-node` picks up for when the\n * resource config is changed.\n *\n * @param _config The new resource config values.\n */\n function setResourceConfig(ResourceMetering.ResourceConfig memory _config) external onlyOwner {\n _setResourceConfig(_config);\n }\n\n /**\n * @notice An internal setter for the resource config. Ensures that the\n * config is sane before storing it by checking for invariants.\n *\n * @param _config The new resource config.\n */\n function _setResourceConfig(ResourceMetering.ResourceConfig memory _config) internal {\n // Min base fee must be less than or equal to max base fee.\n require(\n _config.minimumBaseFee <= _config.maximumBaseFee,\n \"SystemConfig: min base fee must be less than max base\"\n );\n // Base fee change denominator must be greater than 0.\n require(_config.baseFeeMaxChangeDenominator > 0, \"SystemConfig: denominator cannot be 0\");\n // Max resource limit plus system tx gas must be less than or equal to the L2 gas limit.\n // The gas limit must be increased before these values can be increased.\n require(\n _config.maxResourceLimit + _config.systemTxMaxGas <= gasLimit,\n \"SystemConfig: gas limit too low\"\n );\n // Elasticity multiplier must be greater than 0.\n require(\n _config.elasticityMultiplier > 0,\n \"SystemConfig: elasticity multiplier cannot be 0\"\n );\n // No precision loss when computing target resource limit.\n require(\n ((_config.maxResourceLimit / _config.elasticityMultiplier) *\n _config.elasticityMultiplier) == _config.maxResourceLimit,\n \"SystemConfig: precision loss with target resource limit\"\n );\n\n _resourceConfig = _config;\n }\n}\n" - }, - "contracts/L2/BaseFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000019\n * @title BaseFeeVault\n * @notice The BaseFeeVault accumulates the base fee that is paid by transactions.\n */\ncontract BaseFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 0, 0) {}\n}\n" - }, - "contracts/L2/CrossDomainOwnable.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\n/**\n * @title CrossDomainOwnable\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is only safe to be used if the\n * CrossDomainMessenger system is bypassed and the caller on L1 is calling the\n * OptimismPortal directly.\n */\nabstract contract CrossDomainOwnable is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `msg.sender` is the owner of the contract.\n */\n function _checkOwner() internal view override {\n require(\n owner() == AddressAliasHelper.undoL1ToL2Alias(msg.sender),\n \"CrossDomainOwnable: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/CrossDomainOwnable2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L2CrossDomainMessenger } from \"./L2CrossDomainMessenger.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title CrossDomainOwnable2\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is meant to be used with systems that use\n * the CrossDomainMessenger system. It will not work if the OptimismPortal is used\n * directly.\n */\nabstract contract CrossDomainOwnable2 is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `xDomainMessageSender` is the owner of the contract. This value is set to the caller\n * of the L1CrossDomainMessenger.\n */\n function _checkOwner() internal view override {\n L2CrossDomainMessenger messenger = L2CrossDomainMessenger(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER\n );\n\n require(\n msg.sender == address(messenger),\n \"CrossDomainOwnable2: caller is not the messenger\"\n );\n\n require(\n owner() == messenger.xDomainMessageSender(),\n \"CrossDomainOwnable2: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/CrossDomainOwnable3.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L2CrossDomainMessenger } from \"./L2CrossDomainMessenger.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title CrossDomainOwnable3\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on either L1 or L2. Note that this contract is meant to be used with systems\n * that use the CrossDomainMessenger system. It will not work if the OptimismPortal is\n * used directly.\n */\nabstract contract CrossDomainOwnable3 is Ownable {\n /**\n * @notice If true, the contract uses the cross domain _checkOwner function override. If false\n * it uses the standard Ownable _checkOwner function.\n */\n bool public isLocal = true;\n\n /**\n * @notice Emits when ownership of the contract is transferred. Includes the\n * isLocal field in addition to the standard `Ownable` OwnershipTransferred event.\n */\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner,\n bool isLocal\n );\n\n /**\n * @notice Allows for ownership to be transferred with specifying the locality.\n * @param _owner The new owner of the contract.\n * @param _isLocal Configures the locality of the ownership.\n */\n function transferOwnership(address _owner, bool _isLocal) external onlyOwner {\n require(_owner != address(0), \"CrossDomainOwnable3: new owner is the zero address\");\n\n address oldOwner = owner();\n _transferOwnership(_owner);\n isLocal = _isLocal;\n\n emit OwnershipTransferred(oldOwner, _owner, _isLocal);\n }\n\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `xDomainMessageSender` is the owner of the contract. This value is set to the caller\n * of the L1CrossDomainMessenger.\n */\n function _checkOwner() internal view override {\n if (isLocal) {\n require(owner() == msg.sender, \"CrossDomainOwnable3: caller is not the owner\");\n } else {\n L2CrossDomainMessenger messenger = L2CrossDomainMessenger(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER\n );\n\n require(\n msg.sender == address(messenger),\n \"CrossDomainOwnable3: caller is not the messenger\"\n );\n\n require(\n owner() == messenger.xDomainMessageSender(),\n \"CrossDomainOwnable3: caller is not the owner\"\n );\n }\n }\n}\n" - }, - "contracts/L2/GasPriceOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000000F\n * @title GasPriceOracle\n * @notice This contract maintains the variables responsible for computing the L1 portion of the\n * total fee charged on L2. Before Bedrock, this contract held variables in state that were\n * read during the state transition function to compute the L1 portion of the transaction\n * fee. After Bedrock, this contract now simply proxies the L1Block contract, which has\n * the values used to compute the L1 portion of the fee in its state.\n *\n * The contract exposes an API that is useful for knowing how large the L1 portion of the\n * transaction fee will be. The following events were deprecated with Bedrock:\n * - event OverheadUpdated(uint256 overhead);\n * - event ScalarUpdated(uint256 scalar);\n * - event DecimalsUpdated(uint256 decimals);\n */\ncontract GasPriceOracle is Semver {\n /**\n * @notice Number of decimals used in the scalar.\n */\n uint256 public constant DECIMALS = 6;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Computes the L1 portion of the fee based on the size of the rlp encoded input\n * transaction, the current L1 base fee, and the various dynamic parameters.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for.\n *\n * @return L1 fee that should be paid for the tx\n */\n function getL1Fee(bytes memory _data) external view returns (uint256) {\n uint256 l1GasUsed = getL1GasUsed(_data);\n uint256 l1Fee = l1GasUsed * l1BaseFee();\n uint256 divisor = 10**DECIMALS;\n uint256 unscaled = l1Fee * scalar();\n uint256 scaled = unscaled / divisor;\n return scaled;\n }\n\n /**\n * @notice Retrieves the current gas price (base fee).\n *\n * @return Current L2 gas price (base fee).\n */\n function gasPrice() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current base fee.\n *\n * @return Current L2 base fee.\n */\n function baseFee() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current fee overhead.\n *\n * @return Current fee overhead.\n */\n function overhead() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead();\n }\n\n /**\n * @notice Retrieves the current fee scalar.\n *\n * @return Current fee scalar.\n */\n function scalar() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar();\n }\n\n /**\n * @notice Retrieves the latest known L1 base fee.\n *\n * @return Latest known L1 base fee.\n */\n function l1BaseFee() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee();\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the number of decimals used in the scalar.\n *\n * @return Number of decimals used in the scalar.\n */\n function decimals() public pure returns (uint256) {\n return DECIMALS;\n }\n\n /**\n * @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which\n * represents the per-transaction gas overhead of posting the transaction and state\n * roots to L1. Adds 68 bytes of padding to account for the fact that the input does\n * not have a signature.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for.\n *\n * @return Amount of L1 gas used to publish the transaction.\n */\n function getL1GasUsed(bytes memory _data) public view returns (uint256) {\n uint256 total = 0;\n uint256 length = _data.length;\n for (uint256 i = 0; i < length; i++) {\n if (_data[i] == 0) {\n total += 4;\n } else {\n total += 16;\n }\n }\n uint256 unsigned = total + overhead();\n return unsigned + (68 * 16);\n }\n}\n" - }, - "contracts/L2/L1Block.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000015\n * @title L1Block\n * @notice The L1Block predeploy gives users access to information about the last known L1 block.\n * Values within this contract are updated once per epoch (every L1 block) and can only be\n * set by the \"depositor\" account, a special system address. Depositor account transactions\n * are created by the protocol whenever we move to a new epoch.\n */\ncontract L1Block is Semver {\n /**\n * @notice Address of the special depositor account.\n */\n address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001;\n\n /**\n * @notice The latest L1 block number known by the L2 system.\n */\n uint64 public number;\n\n /**\n * @notice The latest L1 timestamp known by the L2 system.\n */\n uint64 public timestamp;\n\n /**\n * @notice The latest L1 basefee.\n */\n uint256 public basefee;\n\n /**\n * @notice The latest L1 blockhash.\n */\n bytes32 public hash;\n\n /**\n * @notice The number of L2 blocks in the same epoch.\n */\n uint64 public sequenceNumber;\n\n /**\n * @notice The versioned hash to authenticate the batcher by.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice The overhead value applied to the L1 portion of the transaction\n * fee.\n */\n uint256 public l1FeeOverhead;\n\n /**\n * @notice The scalar value applied to the L1 portion of the transaction fee.\n */\n uint256 public l1FeeScalar;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Updates the L1 block values.\n *\n * @param _number L1 blocknumber.\n * @param _timestamp L1 timestamp.\n * @param _basefee L1 basefee.\n * @param _hash L1 blockhash.\n * @param _sequenceNumber Number of L2 blocks since epoch start.\n * @param _batcherHash Versioned hash to authenticate batcher by.\n * @param _l1FeeOverhead L1 fee overhead.\n * @param _l1FeeScalar L1 fee scalar.\n */\n function setL1BlockValues(\n uint64 _number,\n uint64 _timestamp,\n uint256 _basefee,\n bytes32 _hash,\n uint64 _sequenceNumber,\n bytes32 _batcherHash,\n uint256 _l1FeeOverhead,\n uint256 _l1FeeScalar\n ) external {\n require(\n msg.sender == DEPOSITOR_ACCOUNT,\n \"L1Block: only the depositor account can set L1 block values\"\n );\n\n number = _number;\n timestamp = _timestamp;\n basefee = _basefee;\n hash = _hash;\n sequenceNumber = _sequenceNumber;\n batcherHash = _batcherHash;\n l1FeeOverhead = _l1FeeOverhead;\n l1FeeScalar = _l1FeeScalar;\n }\n}\n" - }, - "contracts/L2/L1FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000001A\n * @title L1FeeVault\n * @notice The L1FeeVault accumulates the L1 portion of the transaction fees.\n */\ncontract L1FeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 0, 0) {}\n}\n" - }, - "contracts/L2/L2CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { L2ToL1MessagePasser } from \"./L2ToL1MessagePasser.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000007\n * @title L2CrossDomainMessenger\n * @notice The L2CrossDomainMessenger is a high-level interface for message passing between L1 and\n * L2 on the L2 side. Users are generally encouraged to use this contract instead of lower\n * level message passing contracts.\n */\ncontract L2CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _l1CrossDomainMessenger Address of the L1CrossDomainMessenger contract.\n */\n constructor(address _l1CrossDomainMessenger)\n Semver(1, 1, 0)\n CrossDomainMessenger(_l1CrossDomainMessenger)\n {\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote messenger. Use otherMessenger going forward.\n *\n * @return Address of the L1CrossDomainMessenger contract.\n */\n function l1CrossDomainMessenger() public view returns (address) {\n return OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)).initiateWithdrawal{\n value: _value\n }(_to, _gasLimit, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(Predeploys.L2_TO_L1_MESSAGE_PASSER);\n }\n}\n" - }, - "contracts/L2/L2ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../universal/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 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, 1, 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), \"L2ERC721Bridge: 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 \"L2ERC721Bridge: 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(OTHER_BRIDGE, message, _minGasLimit);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L2/L2StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000010\n * @title L2StandardBridge\n * @notice The L2StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L2, it will be escrowed within this\n * contract. If the ERC20 token is native to L1, it will be burnt.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L2StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal from L2 to L1 is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _otherBridge Address of the L1StandardBridge.\n */\n constructor(address payable _otherBridge)\n Semver(1, 1, 0)\n StandardBridge(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER), _otherBridge)\n {}\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n */\n receive() external payable override onlyEOA {\n _initiateWithdrawal(\n Predeploys.LEGACY_ERC20_ETH,\n msg.sender,\n msg.sender,\n msg.value,\n RECEIVE_DEFAULT_GAS_LIMIT,\n bytes(\"\")\n );\n }\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1.\n * This function only works with OptimismMintableERC20 tokens or ether. Use the\n * `bridgeERC20` function to bridge native L2 tokens to L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdraw(\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual onlyEOA {\n _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1 to a target account on L1.\n * Note that if ETH is sent to a contract on L1 and the call fails, then that ETH will\n * be locked in the L1StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n * This function only works with OptimismMintableERC20 tokens or ether. Use the\n * `bridgeERC20To` function to bridge native L2 tokens to L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdrawTo(\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual {\n _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a deposit from L1 to L2. To finalize a deposit of ether, use address(0)\n * and the l1Token and the Legacy ERC20 ether predeploy address as the l2Token.\n *\n * @param _l1Token Address of the L1 token to deposit.\n * @param _l2Token Address of the corresponding L2 token.\n * @param _from Address of the depositor.\n * @param _to Address of the recipient.\n * @param _amount Amount of the tokens being deposited.\n * @param _extraData Extra data attached to the deposit.\n */\n function finalizeDeposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable virtual {\n if (_l1Token == address(0) && _l2Token == Predeploys.LEGACY_ERC20_ETH) {\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n } else {\n finalizeBridgeERC20(_l2Token, _l1Token, _from, _to, _amount, _extraData);\n }\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L1 bridge contract.\n *\n * @return Address of the corresponding L1 bridge contract.\n */\n function l1TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @custom:legacy\n * @notice Internal function to a withdrawal from L2 to L1 to a target account on L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _from Address of the withdrawer.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function _initiateWithdrawal(\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n if (_l2Token == Predeploys.LEGACY_ERC20_ETH) {\n _initiateBridgeETH(_from, _to, _amount, _minGasLimit, _extraData);\n } else {\n address l1Token = OptimismMintableERC20(_l2Token).l1Token();\n _initiateBridgeERC20(_l2Token, l1Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n }\n\n /**\n * @notice Emits the legacy WithdrawalInitiated event followed by the ETHBridgeInitiated event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit WithdrawalInitiated(\n address(0),\n Predeploys.LEGACY_ERC20_ETH,\n _from,\n _to,\n _amount,\n _extraData\n );\n super._emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy DepositFinalized event followed by the ETHBridgeFinalized event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit DepositFinalized(\n address(0),\n Predeploys.LEGACY_ERC20_ETH,\n _from,\n _to,\n _amount,\n _extraData\n );\n super._emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy WithdrawalInitiated event followed by the ERC20BridgeInitiated\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit WithdrawalInitiated(_remoteToken, _localToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy DepositFinalized event followed by the ERC20BridgeFinalized event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit DepositFinalized(_remoteToken, _localToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/L2/L2ToL1MessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000016\n * @title L2ToL1MessagePasser\n * @notice The L2ToL1MessagePasser is a dedicated contract where messages that are being sent from\n * L2 to L1 can be stored. The storage root of this contract is pulled up to the top level\n * of the L2 output to reduce the cost of proving the existence of sent messages.\n */\ncontract L2ToL1MessagePasser is Semver {\n /**\n * @notice The L1 gas limit set when eth is withdrawn using the receive() function.\n */\n uint256 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Current message version identifier.\n */\n uint16 public constant MESSAGE_VERSION = 1;\n\n /**\n * @notice Includes the message hashes for all withdrawals\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @notice A unique value hashed with each withdrawal.\n */\n uint240 internal msgNonce;\n\n /**\n * @notice Emitted any time a withdrawal is initiated.\n *\n * @param nonce Unique value corresponding to each withdrawal.\n * @param sender The L2 account address which initiated the withdrawal.\n * @param target The L1 account address the call will be send to.\n * @param value The ETH value submitted for withdrawal, to be forwarded to the target.\n * @param gasLimit The minimum amount of gas that must be provided when withdrawing.\n * @param data The data to be forwarded to the target on L1.\n * @param withdrawalHash The hash of the withdrawal.\n */\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n /**\n * @notice Emitted when the balance of this contract is burned.\n *\n * @param amount Amount of ETh that was burned.\n */\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Allows users to withdraw ETH by sending directly to this contract.\n */\n receive() external payable {\n initiateWithdrawal(msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @notice Removes all ETH held by this contract from the state. Used to prevent the amount of\n * ETH on L2 inflating when ETH is withdrawn. Currently only way to do this is to\n * create a contract and self-destruct it to itself. Anyone can call this function. Not\n * incentivized since this function is very cheap.\n */\n function burn() external {\n uint256 balance = address(this).balance;\n Burn.eth(balance);\n emit WithdrawerBalanceBurnt(balance);\n }\n\n /**\n * @notice Sends a message from L2 to L1.\n *\n * @param _target Address to call on L1 execution.\n * @param _gasLimit Minimum gas limit for executing the message on L1.\n * @param _data Data to forward to L1 target.\n */\n function initiateWithdrawal(\n address _target,\n uint256 _gasLimit,\n bytes memory _data\n ) public payable {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messageNonce(),\n sender: msg.sender,\n target: _target,\n value: msg.value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n sentMessages[withdrawalHash] = true;\n\n emit MessagePassed(\n messageNonce(),\n msg.sender,\n _target,\n msg.value,\n _gasLimit,\n _data,\n withdrawalHash\n );\n\n unchecked {\n ++msgNonce;\n }\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" - }, - "contracts/L2/SequencerFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000011\n * @title SequencerFeeVault\n * @notice The SequencerFeeVault is the contract that holds any fees paid to the Sequencer during\n * transaction processing and block production.\n */\ncontract SequencerFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 0, 0) {}\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the recipient address.\n *\n * @return The recipient address.\n */\n function l1FeeWallet() public view returns (address) {\n return RECIPIENT;\n }\n}\n" - }, - "contracts/deployment/PortalSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/**\n * @title PortalSender\n * @notice The PortalSender is a simple intermediate contract that will transfer the balance of the\n * L1StandardBridge to the OptimismPortal during the Bedrock migration.\n */\ncontract PortalSender {\n /**\n * @notice Address of the OptimismPortal contract.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @param _portal Address of the OptimismPortal contract.\n */\n constructor(OptimismPortal _portal) {\n PORTAL = _portal;\n }\n\n /**\n * @notice Sends balance of this contract to the OptimismPortal.\n */\n function donate() public {\n PORTAL.donateETH{ value: address(this).balance }();\n }\n}\n" - }, - "contracts/deployment/SystemDictator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { PortalSender } from \"./PortalSender.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\n/**\n * @title SystemDictator\n * @notice The SystemDictator is responsible for coordinating the deployment of a full Bedrock\n * system. The SystemDictator is designed to support both fresh network deployments and\n * upgrades to existing pre-Bedrock systems.\n */\ncontract SystemDictator is OwnableUpgradeable {\n /**\n * @notice Basic system configuration.\n */\n struct GlobalConfig {\n AddressManager addressManager;\n ProxyAdmin proxyAdmin;\n address controller;\n address finalOwner;\n }\n\n /**\n * @notice Set of proxy addresses.\n */\n struct ProxyAddressConfig {\n address l2OutputOracleProxy;\n address optimismPortalProxy;\n address l1CrossDomainMessengerProxy;\n address l1StandardBridgeProxy;\n address optimismMintableERC20FactoryProxy;\n address l1ERC721BridgeProxy;\n address systemConfigProxy;\n }\n\n /**\n * @notice Set of implementation addresses.\n */\n struct ImplementationAddressConfig {\n L2OutputOracle l2OutputOracleImpl;\n OptimismPortal optimismPortalImpl;\n L1CrossDomainMessenger l1CrossDomainMessengerImpl;\n L1StandardBridge l1StandardBridgeImpl;\n OptimismMintableERC20Factory optimismMintableERC20FactoryImpl;\n L1ERC721Bridge l1ERC721BridgeImpl;\n PortalSender portalSenderImpl;\n SystemConfig systemConfigImpl;\n }\n\n /**\n * @notice Dynamic L2OutputOracle config.\n */\n struct L2OutputOracleDynamicConfig {\n uint256 l2OutputOracleStartingBlockNumber;\n uint256 l2OutputOracleStartingTimestamp;\n }\n\n /**\n * @notice Values for the system config contract.\n */\n struct SystemConfigConfig {\n address owner;\n uint256 overhead;\n uint256 scalar;\n bytes32 batcherHash;\n uint64 gasLimit;\n address unsafeBlockSigner;\n ResourceMetering.ResourceConfig resourceConfig;\n }\n\n /**\n * @notice Combined system configuration.\n */\n struct DeployConfig {\n GlobalConfig globalConfig;\n ProxyAddressConfig proxyAddressConfig;\n ImplementationAddressConfig implementationAddressConfig;\n SystemConfigConfig systemConfigConfig;\n }\n\n /**\n * @notice Step after which exit 1 can no longer be used.\n */\n uint8 public constant EXIT_1_NO_RETURN_STEP = 3;\n\n /**\n * @notice Step where proxy ownership is transferred.\n */\n uint8 public constant PROXY_TRANSFER_STEP = 4;\n\n /**\n * @notice System configuration.\n */\n DeployConfig public config;\n\n /**\n * @notice Dynamic configuration for the L2OutputOracle.\n */\n L2OutputOracleDynamicConfig public l2OutputOracleDynamicConfig;\n\n /**\n * @notice Dynamic configuration for the OptimismPortal. Determines\n * if the system should be paused when initialized.\n */\n bool public optimismPortalDynamicConfig;\n\n /**\n * @notice Current step;\n */\n uint8 public currentStep;\n\n /**\n * @notice Whether or not dynamic config has been set.\n */\n bool public dynamicConfigSet;\n\n /**\n * @notice Whether or not the deployment is finalized.\n */\n bool public finalized;\n\n /**\n * @notice Whether or not the deployment has been exited.\n */\n bool public exited;\n\n /**\n * @notice Address of the old L1CrossDomainMessenger implementation.\n */\n address public oldL1CrossDomainMessenger;\n\n /**\n * @notice Checks that the current step is the expected step, then bumps the current step.\n *\n * @param _step Current step.\n */\n modifier step(uint8 _step) {\n require(!finalized, \"SystemDictator: already finalized\");\n require(!exited, \"SystemDictator: already exited\");\n require(currentStep == _step, \"SystemDictator: incorrect step\");\n _;\n currentStep++;\n }\n\n /**\n * @notice Constructor required to ensure that the implementation of the SystemDictator is\n * initialized upon deployment.\n */\n constructor() {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n // Using this shorter variable as an alias for address(0) just prevents us from having to\n // to use a new line for every single parameter.\n address zero = address(0);\n initialize(\n DeployConfig(\n GlobalConfig(AddressManager(zero), ProxyAdmin(zero), zero, zero),\n ProxyAddressConfig(zero, zero, zero, zero, zero, zero, zero),\n ImplementationAddressConfig(\n L2OutputOracle(zero),\n OptimismPortal(payable(zero)),\n L1CrossDomainMessenger(zero),\n L1StandardBridge(payable(zero)),\n OptimismMintableERC20Factory(zero),\n L1ERC721Bridge(zero),\n PortalSender(zero),\n SystemConfig(zero)\n ),\n SystemConfigConfig(zero, 0, 0, bytes32(0), 0, zero, rcfg)\n )\n );\n }\n\n /**\n * @param _config System configuration.\n */\n function initialize(DeployConfig memory _config) public initializer {\n config = _config;\n currentStep = 1;\n __Ownable_init();\n _transferOwnership(config.globalConfig.controller);\n }\n\n /**\n * @notice Allows the owner to update dynamic config.\n *\n * @param _l2OutputOracleDynamicConfig Dynamic L2OutputOracle config.\n * @param _optimismPortalDynamicConfig Dynamic OptimismPortal config.\n */\n function updateDynamicConfig(\n L2OutputOracleDynamicConfig memory _l2OutputOracleDynamicConfig,\n bool _optimismPortalDynamicConfig\n ) external onlyOwner {\n l2OutputOracleDynamicConfig = _l2OutputOracleDynamicConfig;\n optimismPortalDynamicConfig = _optimismPortalDynamicConfig;\n dynamicConfigSet = true;\n }\n\n /**\n * @notice Configures the ProxyAdmin contract.\n */\n function step1() external onlyOwner step(1) {\n // Set the AddressManager in the ProxyAdmin.\n config.globalConfig.proxyAdmin.setAddressManager(config.globalConfig.addressManager);\n\n // Set the L1CrossDomainMessenger to the RESOLVED proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n ProxyAdmin.ProxyType.RESOLVED\n );\n\n // Set the implementation name for the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.setImplementationName(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Set the L1StandardBridge to the CHUGSPLASH proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1StandardBridgeProxy,\n ProxyAdmin.ProxyType.CHUGSPLASH\n );\n\n // Upgrade and initialize the SystemConfig so the Sequencer can start up.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.systemConfigProxy),\n address(config.implementationAddressConfig.systemConfigImpl),\n abi.encodeCall(\n SystemConfig.initialize,\n (\n config.systemConfigConfig.owner,\n config.systemConfigConfig.overhead,\n config.systemConfigConfig.scalar,\n config.systemConfigConfig.batcherHash,\n config.systemConfigConfig.gasLimit,\n config.systemConfigConfig.unsafeBlockSigner,\n config.systemConfigConfig.resourceConfig\n )\n )\n );\n }\n\n /**\n * @notice Pauses the system by shutting down the L1CrossDomainMessenger and setting the\n * deposit halt flag to tell the Sequencer's DTL to stop accepting deposits.\n */\n function step2() external onlyOwner step(2) {\n // Store the address of the old L1CrossDomainMessenger implementation. We will need this\n // address in the case that we have to exit early.\n oldL1CrossDomainMessenger = config.globalConfig.addressManager.getAddress(\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Temporarily brick the L1CrossDomainMessenger by setting its implementation address to\n // address(0) which will cause the ResolvedDelegateProxy to revert. Better than pausing\n // the L1CrossDomainMessenger via pause() because it can be easily reverted.\n config.globalConfig.addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(0));\n\n // Set the DTL shutoff block, which will tell the DTL to stop syncing new deposits from the\n // CanonicalTransactionChain. We do this by setting an address in the AddressManager\n // because the DTL already has a reference to the AddressManager and this way we don't also\n // need to give it a reference to the SystemDictator.\n config.globalConfig.addressManager.setAddress(\n \"DTL_SHUTOFF_BLOCK\",\n address(uint160(block.number))\n );\n }\n\n /**\n * @notice Removes deprecated addresses from the AddressManager.\n */\n function step3() external onlyOwner step(EXIT_1_NO_RETURN_STEP) {\n // Remove all deprecated addresses from the AddressManager\n string[17] memory deprecated = [\n \"OVM_CanonicalTransactionChain\",\n \"OVM_L2CrossDomainMessenger\",\n \"OVM_DecompressionPrecompileAddress\",\n \"OVM_Sequencer\",\n \"OVM_Proposer\",\n \"OVM_ChainStorageContainer-CTC-batches\",\n \"OVM_ChainStorageContainer-CTC-queue\",\n \"OVM_CanonicalTransactionChain\",\n \"OVM_StateCommitmentChain\",\n \"OVM_BondManager\",\n \"OVM_ExecutionManager\",\n \"OVM_FraudVerifier\",\n \"OVM_StateManagerFactory\",\n \"OVM_StateTransitionerFactory\",\n \"OVM_SafetyChecker\",\n \"OVM_L1MultiMessageRelayer\",\n \"BondManager\"\n ];\n\n for (uint256 i = 0; i < deprecated.length; i++) {\n config.globalConfig.addressManager.setAddress(deprecated[i], address(0));\n }\n }\n\n /**\n * @notice Transfers system ownership to the ProxyAdmin.\n */\n function step4() external onlyOwner step(PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the ProxyAdmin.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1StandardBridge to the ProxyAdmin.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the ProxyAdmin.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.proxyAdmin)\n );\n }\n\n /**\n * @notice Upgrades and initializes proxy contracts.\n */\n function step5() external onlyOwner step(5) {\n // Dynamic config must be set before we can initialize the L2OutputOracle.\n require(dynamicConfigSet, \"SystemDictator: dynamic oracle config is not yet initialized\");\n\n // Upgrade and initialize the L2OutputOracle.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l2OutputOracleProxy),\n address(config.implementationAddressConfig.l2OutputOracleImpl),\n abi.encodeCall(\n L2OutputOracle.initialize,\n (\n l2OutputOracleDynamicConfig.l2OutputOracleStartingBlockNumber,\n l2OutputOracleDynamicConfig.l2OutputOracleStartingTimestamp\n )\n )\n );\n\n // Upgrade and initialize the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.optimismPortalProxy),\n address(config.implementationAddressConfig.optimismPortalImpl),\n abi.encodeCall(OptimismPortal.initialize, (optimismPortalDynamicConfig))\n );\n\n // Upgrade the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1CrossDomainMessengerProxy),\n address(config.implementationAddressConfig.l1CrossDomainMessengerImpl)\n );\n\n // Try to initialize the L1CrossDomainMessenger, only fail if it's already been initialized.\n try\n L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy)\n .initialize()\n {\n // L1CrossDomainMessenger is the one annoying edge case difference between existing\n // networks and fresh networks because in existing networks it'll already be\n // initialized but in fresh networks it won't be. Try/catch is the easiest and most\n // consistent way to handle this because initialized() is not exposed publicly.\n } catch Error(string memory reason) {\n require(\n keccak256(abi.encodePacked(reason)) ==\n keccak256(\"Initializable: contract is already initialized\"),\n string.concat(\"SystemDictator: unexpected error initializing L1XDM: \", reason)\n );\n } catch {\n revert(\"SystemDictator: unexpected error initializing L1XDM (no reason)\");\n }\n\n // Transfer ETH from the L1StandardBridge to the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.portalSenderImpl),\n abi.encodeCall(PortalSender.donate, ())\n );\n\n // Upgrade the L1StandardBridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.l1StandardBridgeImpl)\n );\n\n // Upgrade the OptimismMintableERC20Factory (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.optimismMintableERC20FactoryProxy),\n address(config.implementationAddressConfig.optimismMintableERC20FactoryImpl)\n );\n\n // Upgrade the L1ERC721Bridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1ERC721BridgeProxy),\n address(config.implementationAddressConfig.l1ERC721BridgeImpl)\n );\n }\n\n /**\n * @notice Tranfers admin ownership to the final owner.\n */\n function finalize() external onlyOwner {\n // Transfer ownership of the ProxyAdmin to the final owner.\n config.globalConfig.proxyAdmin.transferOwnership(config.globalConfig.finalOwner);\n\n // Optionally also transfer AddressManager and L1StandardBridge if we still own it. Might\n // happen if we're exiting early.\n if (currentStep <= PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the final owner.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1StandardBridge to the final owner.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the final owner.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.finalOwner)\n );\n }\n\n // Mark the deployment as finalized.\n finalized = true;\n }\n\n /**\n * @notice First exit point, can only be called before step 3 is executed.\n */\n function exit1() external onlyOwner {\n require(\n currentStep == EXIT_1_NO_RETURN_STEP,\n \"SystemDictator: can only exit1 before step 3 is executed\"\n );\n\n // Reset the L1CrossDomainMessenger to the old implementation.\n config.globalConfig.addressManager.setAddress(\n \"OVM_L1CrossDomainMessenger\",\n oldL1CrossDomainMessenger\n );\n\n // Unset the DTL shutoff block which will allow the DTL to sync again.\n config.globalConfig.addressManager.setAddress(\"DTL_SHUTOFF_BLOCK\", address(0));\n\n // Mark the deployment as exited.\n exited = true;\n }\n}\n" - }, - "contracts/echidna/FuzzAddressAliasing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract EchidnaFuzzAddressAliasing {\n bool internal failedRoundtrip;\n\n /**\n * @notice Takes an address to be aliased with AddressAliasHelper and then unaliased\n * and updates the test contract's state indicating if the round trip encoding\n * failed.\n */\n function testRoundTrip(address addr) public {\n // Alias our address\n address aliasedAddr = AddressAliasHelper.applyL1ToL2Alias(addr);\n\n // Unalias our address\n address undoneAliasAddr = AddressAliasHelper.undoL1ToL2Alias(aliasedAddr);\n\n // If our round trip aliasing did not return the original result, set our state.\n if (addr != undoneAliasAddr) {\n failedRoundtrip = true;\n }\n }\n\n /**\n * @custom:invariant Address aliases are always able to be undone.\n *\n * Asserts that an address that has been aliased with `applyL1ToL2Alias` can always\n * be unaliased with `undoL1ToL2Alias`.\n */\n function echidna_round_trip_aliasing() public view returns (bool) {\n // ASSERTION: The round trip aliasing done in testRoundTrip(...) should never fail.\n return !failedRoundtrip;\n }\n}\n" - }, - "contracts/echidna/FuzzBurn.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\n\ncontract EchidnaFuzzBurnEth is StdUtils {\n bool internal failedEthBurn;\n\n /**\n * @notice Takes an integer amount of eth to burn through the Burn library and\n * updates the contract state if an incorrect amount of eth moved from the contract\n */\n function testBurn(uint256 _value) public {\n // cache the contract's eth balance\n uint256 preBurnBalance = address(this).balance;\n uint256 value = bound(_value, 0, preBurnBalance);\n\n // execute a burn of _value eth\n Burn.eth(value);\n\n // check that exactly value eth was transfered from the contract\n unchecked {\n if (address(this).balance != preBurnBalance - value) {\n failedEthBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `eth(uint256)` always burns the exact amount of eth passed.\n *\n * Asserts that when `Burn.eth(uint256)` is called, it always burns the exact amount\n * of ETH passed to the function.\n */\n function echidna_burn_eth() public view returns (bool) {\n // ASSERTION: The amount burned should always match the amount passed exactly\n return !failedEthBurn;\n }\n}\n\ncontract EchidnaFuzzBurnGas is StdUtils {\n bool internal failedGasBurn;\n\n /**\n * @notice Takes an integer amount of gas to burn through the Burn library and\n * updates the contract state if at least that amount of gas was not burned\n * by the library\n */\n function testGas(uint256 _value) public {\n // cap the value to the max resource limit\n uint256 MAX_RESOURCE_LIMIT = 8_000_000;\n uint256 value = bound(_value, 0, MAX_RESOURCE_LIMIT);\n\n // cache the contract's current remaining gas\n uint256 preBurnGas = gasleft();\n\n // execute the gas burn\n Burn.gas(value);\n\n // cache the remaining gas post burn\n uint256 postBurnGas = gasleft();\n\n // check that at least value gas was burnt (and that there was no underflow)\n unchecked {\n if (postBurnGas - preBurnGas > value || preBurnGas - value > preBurnGas) {\n failedGasBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `gas(uint256)` always burns at least the amount of gas passed.\n *\n * Asserts that when `Burn.gas(uint256)` is called, it always burns at least the amount\n * of gas passed to the function.\n */\n function echidna_burn_gas() public view returns (bool) {\n // ASSERTION: The amount of gas burned should be strictly greater than the\n // the amount passed as _value (minimum _value + whatever minor overhead to\n // the value after the call)\n return !failedGasBurn;\n }\n}\n" - }, - "contracts/echidna/FuzzEncoding.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzEncoding {\n bool internal failedRoundtripAToB;\n bool internal failedRoundtripBToA;\n\n /**\n * @notice Takes a pair of integers to be encoded into a versioned nonce with the\n * Encoding library and then decoded and updates the test contract's state\n * indicating if the round trip encoding failed.\n */\n function testRoundTripAToB(uint240 _nonce, uint16 _version) public {\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(encodedVersionedNonce);\n\n // If our round trip encoding did not return the original result, set our state.\n if ((decodedNonce != _nonce) || (decodedVersion != _version)) {\n failedRoundtripAToB = true;\n }\n }\n\n /**\n * @notice Takes an integer representing a packed version and nonce and attempts\n * to decode them using the Encoding library before re-encoding and updates\n * the test contract's state indicating if the round trip encoding failed.\n */\n function testRoundTripBToA(uint256 _versionedNonce) public {\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(_versionedNonce);\n\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(decodedNonce, decodedVersion);\n\n // If our round trip encoding did not return the original result, set our state.\n if (encodedVersionedNonce != _versionedNonce) {\n failedRoundtripBToA = true;\n }\n }\n\n /**\n * @custom:invariant `testRoundTripAToB` never fails.\n *\n * Asserts that a raw versioned nonce can be encoded / decoded to reach the same raw value.\n */\n function echidna_round_trip_encoding_AToB() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripAToB(...)\n return !failedRoundtripAToB;\n }\n\n /**\n * @custom:invariant `testRoundTripBToA` never fails.\n *\n * Asserts that an encoded versioned nonce can always be decoded / re-encoded to reach\n * the same encoded value.\n */\n function echidna_round_trip_encoding_BToA() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripBToA should never\n // fail.\n return !failedRoundtripBToA;\n }\n}\n" - }, - "contracts/echidna/FuzzHashing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzHashing {\n bool internal failedCrossDomainHashHighVersion;\n bool internal failedCrossDomainHashV0;\n bool internal failedCrossDomainHashV1;\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash with a randomly\n * generated version. Only schema versions 0 and 1 are supported and all others should revert.\n */\n function testHashCrossDomainMessageHighVersion(\n uint16 _version,\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // hash the cross domain message. we don't need to store the result since the function\n // validates and should revert if an invalid version (>1) is encoded\n Hashing.hashCrossDomainMessage(encodedNonce, _sender, _target, _value, _gasLimit, _data);\n\n // check that execution never makes it this far for an invalid version\n if (_version > 1) {\n failedCrossDomainHashHighVersion = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v0 schema\n * and compares the output of a call to the unversioned function to the v0 function directly\n */\n function testHashCrossDomainMessageV0(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 0\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 0);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV0(\n _target,\n _sender,\n _data,\n encodedNonce\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV0 = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v1 schema\n * and compares the output of a call to the unversioned function to the v1 function directly\n */\n function testHashCrossDomainMessageV1(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 1\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 1);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV1(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV1 = true;\n }\n }\n\n /**\n * @custom:invariant `hashCrossDomainMessage` reverts if `version` is > `1`.\n *\n * The `hashCrossDomainMessage` function should always revert if the `version` passed is > `1`.\n */\n function echidna_hash_xdomain_msg_high_version() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage will never succeed for a version > 1\n return !failedCrossDomainHashHighVersion;\n }\n\n /**\n * @custom:invariant `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0`\n * are equivalent.\n *\n * If the version passed is 0, `hashCrossDomainMessage` and `hashCrossDomainMessageV0` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_0() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV0\n // should always match when the version passed is 0\n return !failedCrossDomainHashV0;\n }\n\n /**\n * @custom:invariant `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1`\n * are equivalent.\n *\n * If the version passed is 1, `hashCrossDomainMessage` and `hashCrossDomainMessageV1` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_1() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV1\n // should always match when the version passed is 1\n return !failedCrossDomainHashV1;\n }\n}\n" - }, - "contracts/echidna/FuzzOptimismPortal.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract EchidnaFuzzOptimismPortal {\n OptimismPortal internal portal;\n bool internal failedToComplete;\n\n constructor() {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n SystemConfig systemConfig = new SystemConfig({\n _owner: address(1),\n _overhead: 0,\n _scalar: 10000,\n _batcherHash: bytes32(0),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(0),\n _config: rcfg\n });\n\n portal = new OptimismPortal({\n _l2Oracle: L2OutputOracle(address(0)),\n _guardian: address(0),\n _paused: false,\n _config: systemConfig\n });\n }\n\n // A test intended to identify any unexpected halting conditions\n function testDepositTransactionCompletes(\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable {\n failedToComplete = true;\n require(!_isCreation || _to == address(0), \"EchidnaFuzzOptimismPortal: invalid test case.\");\n portal.depositTransaction{ value: _mint }(_to, _value, _gasLimit, _isCreation, _data);\n failedToComplete = false;\n }\n\n /**\n * @custom:invariant Deposits of any value should always succeed unless\n * `_to` = `address(0)` or `_isCreation` = `true`.\n *\n * All deposits, barring creation transactions and transactions sent to `address(0)`,\n * should always succeed.\n */\n function echidna_deposit_completes() public view returns (bool) {\n return !failedToComplete;\n }\n}\n" - }, - "contracts/echidna/FuzzResourceMetering.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {\n bool internal failedMaxGasPerBlock;\n bool internal failedRaiseBaseFee;\n bool internal failedLowerBaseFee;\n bool internal failedNeverBelowMinBaseFee;\n bool internal failedMaxRaiseBaseFeePerBlock;\n bool internal failedMaxLowerBaseFeePerBlock;\n\n // Used as a special flag for the purpose of identifying unchecked math errors specifically\n // in the test contracts, not the target contracts themselves.\n bool internal underflow;\n\n constructor() {\n initialize();\n }\n\n function initialize() internal initializer {\n __ResourceMetering_init();\n }\n\n function resourceConfig() public pure returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig();\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n return rcfg;\n }\n\n /**\n * @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test\n * the underlying resource metering/gas market logic\n */\n function testBurn(uint256 _gasToBurn, bool _raiseBaseFee) public {\n // Part 1: we cache the current param values and do some basic checks on them.\n uint256 cachedPrevBaseFee = uint256(params.prevBaseFee);\n uint256 cachedPrevBoughtGas = uint256(params.prevBoughtGas);\n uint256 cachedPrevBlockNum = uint256(params.prevBlockNum);\n\n ResourceMetering.ResourceConfig memory rcfg = resourceConfig();\n uint256 targetResourceLimit = uint256(rcfg.maxResourceLimit) /\n uint256(rcfg.elasticityMultiplier);\n\n // check that the last block's base fee hasn't dropped below the minimum\n if (cachedPrevBaseFee < uint256(rcfg.minimumBaseFee)) {\n failedNeverBelowMinBaseFee = true;\n }\n // check that the last block didn't consume more than the max amount of gas\n if (cachedPrevBoughtGas > uint256(rcfg.maxResourceLimit)) {\n failedMaxGasPerBlock = true;\n }\n\n // Part2: we perform the gas burn\n\n // force the gasToBurn into the correct range based on whether we intend to\n // raise or lower the baseFee after this block, respectively\n uint256 gasToBurn;\n if (_raiseBaseFee) {\n gasToBurn = bound(\n _gasToBurn,\n uint256(targetResourceLimit),\n uint256(rcfg.maxResourceLimit)\n );\n } else {\n gasToBurn = bound(_gasToBurn, 0, targetResourceLimit);\n }\n\n _burnInternal(uint64(gasToBurn));\n\n // Part 3: we run checks and modify our invariant flags based on the updated params values\n\n // Calculate the maximum allowed baseFee change (per block)\n uint256 maxBaseFeeChange = cachedPrevBaseFee / uint256(rcfg.baseFeeMaxChangeDenominator);\n\n // If the last block used more than the target amount of gas (and there were no\n // empty blocks in between), ensure this block's baseFee increased, but not by\n // more than the max amount per block\n if (\n (cachedPrevBoughtGas > uint256(targetResourceLimit)) &&\n (uint256(params.prevBlockNum) - cachedPrevBlockNum == 1)\n ) {\n failedRaiseBaseFee = failedRaiseBaseFee || (params.prevBaseFee <= cachedPrevBaseFee);\n failedMaxRaiseBaseFeePerBlock =\n failedMaxRaiseBaseFeePerBlock ||\n ((uint256(params.prevBaseFee) - cachedPrevBaseFee) < maxBaseFeeChange);\n }\n\n // If the last block used less than the target amount of gas, (or was empty),\n // ensure that: this block's baseFee was decreased, but not by more than the max amount\n if (\n (cachedPrevBoughtGas < uint256(targetResourceLimit)) ||\n (uint256(params.prevBlockNum) - cachedPrevBlockNum > 1)\n ) {\n // Invariant: baseFee should decrease\n failedLowerBaseFee =\n failedLowerBaseFee ||\n (uint256(params.prevBaseFee) > cachedPrevBaseFee);\n\n if (params.prevBlockNum - cachedPrevBlockNum == 1) {\n // No empty blocks\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n } else if (params.prevBlockNum - cachedPrevBlockNum > 1) {\n // We have at least one empty block\n // Update the maxBaseFeeChange to account for multiple blocks having passed\n unchecked {\n maxBaseFeeChange = uint256(\n int256(cachedPrevBaseFee) -\n Arithmetic.clamp(\n Arithmetic.cdexp(\n int256(cachedPrevBaseFee),\n int256(uint256(rcfg.baseFeeMaxChangeDenominator)),\n int256(uint256(params.prevBlockNum) - cachedPrevBlockNum)\n ),\n int256(uint256(rcfg.minimumBaseFee)),\n int256(uint256(rcfg.maximumBaseFee))\n )\n );\n }\n\n // Detect an underflow in the previous calculation.\n // Without using unchecked above, and detecting the underflow here, echidna would\n // otherwise ignore the revert.\n underflow = underflow || maxBaseFeeChange > cachedPrevBaseFee;\n\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n }\n }\n }\n\n function _burnInternal(uint64 _gasToBurn) private metered(_gasToBurn) {}\n\n /**\n * @custom:invariant The base fee should increase if the last block used more\n * than the target amount of gas\n *\n * If the last block used more than the target amount of gas (and there were no\n * empty blocks in between), ensure this block's baseFee increased, but not by\n * more than the max amount per block.\n */\n function echidna_high_usage_raise_baseFee() public view returns (bool) {\n return !failedRaiseBaseFee;\n }\n\n /**\n * @custom:invariant The base fee should decrease if the last block used less\n * than the target amount of gas\n *\n * If the previous block used less than the target amount of gas, the base fee should decrease,\n * but not more than the max amount.\n */\n function echidna_low_usage_lower_baseFee() public view returns (bool) {\n return !failedLowerBaseFee;\n }\n\n /**\n * @custom:invariant A block's base fee should never be below `MINIMUM_BASE_FEE`\n *\n * This test asserts that a block's base fee can never drop below the\n * `MINIMUM_BASE_FEE` threshold.\n */\n function echidna_never_below_min_baseFee() public view returns (bool) {\n return !failedNeverBelowMinBaseFee;\n }\n\n /**\n * @custom:invariant A block can never consume more than `MAX_RESOURCE_LIMIT` gas.\n *\n * This test asserts that a block can never consume more than the `MAX_RESOURCE_LIMIT`\n * gas threshold.\n */\n function echidna_never_above_max_gas_limit() public view returns (bool) {\n return !failedMaxGasPerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be raised more than the max base fee change.\n *\n * After a block consumes more gas than the target gas, the base fee cannot be raised\n * more than the maximum amount allowed. The max base fee change (per-block) is derived\n * as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_increase() public view returns (bool) {\n return !failedMaxRaiseBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be lowered more than the max base fee change.\n *\n * After a block consumes less than the target gas, the base fee cannot be lowered more\n * than the maximum amount allowed. The max base fee change (per-block) is derived as\n *follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_decrease() public view returns (bool) {\n return !failedMaxLowerBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The `maxBaseFeeChange` calculation over multiple blocks can never\n * underflow.\n *\n * When calculating the `maxBaseFeeChange` after multiple empty blocks, the calculation\n * should never be allowed to underflow.\n */\n function echidna_underflow() public view returns (bool) {\n return !underflow;\n }\n}\n" - }, - "contracts/governance/GovernanceToken.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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 * @custom:predeploy 0x4200000000000000000000000000000000000042\n * @title GovernanceToken\n * @notice The Optimism token used in governance and supporting voting and delegation. Implements\n * EIP 2612 allowing signed approvals. Contract is \"owned\" by a `MintManager` instance with\n * permission to the `mint` function only, for the purposes of enforcing the token inflation\n * schedule.\n */\ncontract GovernanceToken is ERC20Burnable, ERC20Votes, Ownable {\n constructor() ERC20(\"Optimism\", \"OP\") ERC20Permit(\"Optimism\") {}\n\n /**\n * @notice Allows the owner to mint tokens.\n *\n * @param _account The account receiving minted tokens.\n * @param _amount The amount of tokens to mint.\n */\n function mint(address _account, uint256 _amount) public onlyOwner {\n _mint(_account, _amount);\n }\n\n /**\n * @notice Callback called after a token transfer.\n *\n * @param from The account sending tokens.\n * @param to The account receiving tokens.\n * @param amount The amount of tokens being transfered.\n */\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 /**\n * @notice Internal mint function.\n *\n * @param to The account receiving minted tokens.\n * @param amount The amount of tokens to mint.\n */\n function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._mint(to, amount);\n }\n\n /**\n * @notice Internal burn function.\n *\n * @param account The account that tokens will be burned from.\n * @param amount The amount of tokens that will be burned.\n */\n function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._burn(account, amount);\n }\n}\n" - }, - "contracts/governance/MintManager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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(\n mintPermittedAfter <= block.timestamp,\n \"MintManager: minting not permitted yet\"\n );\n\n require(\n _amount <= (governanceToken.totalSupply() * MINT_CAP) / DENOMINATOR,\n \"MintManager: mint amount exceeds cap\"\n );\n }\n\n mintPermittedAfter = block.timestamp + MINT_PERIOD;\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(\n _newMintManager != address(0),\n \"MintManager: mint manager cannot be the zero address\"\n );\n\n governanceToken.transferOwnership(_newMintManager);\n }\n}\n" - }, - "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" - }, - "contracts/legacy/DeployerWhitelist.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000002\n * @title DeployerWhitelist\n * @notice DeployerWhitelist is a legacy contract that was originally used to act as a whitelist of\n * addresses allowed to the Optimism network. The DeployerWhitelist has since been\n * disabled, but the code is kept in state for the sake of full backwards compatibility.\n * As of the Bedrock upgrade, the DeployerWhitelist is completely unused by the Optimism\n * system and could, in theory, be removed entirely.\n */\ncontract DeployerWhitelist is Semver {\n /**\n * @notice Address of the owner of this contract. Note that when this address is set to\n * address(0), the whitelist is disabled.\n */\n address public owner;\n\n /**\n * @notice Mapping of deployer addresses to boolean whitelist status.\n */\n mapping(address => bool) public whitelist;\n\n /**\n * @notice Emitted when the owner of this contract changes.\n *\n * @param oldOwner Address of the previous owner.\n * @param newOwner Address of the new owner.\n */\n event OwnerChanged(address oldOwner, address newOwner);\n\n /**\n * @notice Emitted when the whitelist status of a deployer changes.\n *\n * @param deployer Address of the deployer.\n * @param whitelisted Boolean indicating whether the deployer is whitelisted.\n */\n event WhitelistStatusChanged(address deployer, bool whitelisted);\n\n /**\n * @notice Emitted when the whitelist is disabled.\n *\n * @param oldOwner Address of the final owner of the whitelist.\n */\n event WhitelistDisabled(address oldOwner);\n\n /**\n * @notice Blocks functions to anyone except the contract owner.\n */\n modifier onlyOwner() {\n require(\n msg.sender == owner,\n \"DeployerWhitelist: function can only be called by the owner of this contract\"\n );\n _;\n }\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Adds or removes an address from the deployment whitelist.\n *\n * @param _deployer Address to update permissions for.\n * @param _isWhitelisted Whether or not the address is whitelisted.\n */\n function setWhitelistedDeployer(address _deployer, bool _isWhitelisted) external onlyOwner {\n whitelist[_deployer] = _isWhitelisted;\n emit WhitelistStatusChanged(_deployer, _isWhitelisted);\n }\n\n /**\n * @notice Updates the owner of this contract.\n *\n * @param _owner Address of the new owner.\n */\n function setOwner(address _owner) external onlyOwner {\n // Prevent users from setting the whitelist owner to address(0) except via\n // enableArbitraryContractDeployment. If you want to burn the whitelist owner, send it to\n // any other address that doesn't have a corresponding knowable private key.\n require(\n _owner != address(0),\n \"DeployerWhitelist: can only be disabled via enableArbitraryContractDeployment\"\n );\n\n emit OwnerChanged(owner, _owner);\n owner = _owner;\n }\n\n /**\n * @notice Permanently enables arbitrary contract deployment and deletes the owner.\n */\n function enableArbitraryContractDeployment() external onlyOwner {\n emit WhitelistDisabled(owner);\n owner = address(0);\n }\n\n /**\n * @notice Checks whether an address is allowed to deploy contracts.\n *\n * @param _deployer Address to check.\n *\n * @return Whether or not the address can deploy contracts.\n */\n function isDeployerAllowed(address _deployer) external view returns (bool) {\n return (owner == address(0) || whitelist[_deployer]);\n }\n}\n" - }, - "contracts/legacy/L1BlockNumber.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000013\n * @title L1BlockNumber\n * @notice L1BlockNumber is a legacy contract that fills the roll of the OVM_L1BlockNumber contract\n * in the old version of the Optimism system. Only necessary for backwards compatibility.\n * If you want to access the L1 block number going forward, you should use the L1Block\n * contract instead.\n */\ncontract L1BlockNumber is Semver {\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Returns the L1 block number.\n */\n receive() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Returns the L1 block number.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Retrieves the latest L1 block number.\n *\n * @return Latest L1 block number.\n */\n function getL1BlockNumber() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).number();\n }\n}\n" - }, - "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/legacy/LegacyERC20ETH.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000\n * @title LegacyERC20ETH\n * @notice LegacyERC20ETH is a legacy contract that held ETH balances before the Bedrock upgrade.\n * All ETH balances held within this contract were migrated to the state trie as part of\n * the Bedrock upgrade. Functions within this contract that mutate state were already\n * disabled as part of the EVM equivalence upgrade.\n */\ncontract LegacyERC20ETH is OptimismMintableERC20 {\n /**\n * @notice Initializes the contract as an Optimism Mintable ERC20.\n */\n constructor()\n OptimismMintableERC20(Predeploys.L2_STANDARD_BRIDGE, address(0), \"Ether\", \"ETH\")\n {}\n\n /**\n * @notice Returns the ETH balance of the target account. Overrides the base behavior of the\n * contract to preserve the invariant that the balance within this contract always\n * matches the balance in the state trie.\n *\n * @param _who Address of the account to query.\n *\n * @return The ETH balance of the target account.\n */\n function balanceOf(address _who) public view virtual override returns (uint256) {\n return address(_who).balance;\n }\n\n /**\n * @custom:blocked\n * @notice Mints some amount of ETH.\n */\n function mint(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: mint is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Burns some amount of ETH.\n */\n function burn(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: burn is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers some amount of ETH.\n */\n function transfer(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transfer is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Approves a spender to spend some amount of ETH.\n */\n function approve(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: approve is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers funds from some sender account.\n */\n function transferFrom(\n address,\n address,\n uint256\n ) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transferFrom is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Increases the allowance of a spender.\n */\n function increaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Decreases the allowance of a spender.\n */\n function decreaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n }\n}\n" - }, - "contracts/legacy/LegacyMessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000000\n * @title LegacyMessagePasser\n * @notice The LegacyMessagePasser was the low-level mechanism used to send messages from L2 to L1\n * before the Bedrock upgrade. It is now deprecated in favor of the new MessagePasser.\n */\ncontract LegacyMessagePasser is Semver {\n /**\n * @notice Mapping of sent message hashes to boolean status.\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Passes a message to L1.\n *\n * @param _message Message to pass to L1.\n */\n function passMessageToL1(bytes memory _message) external {\n sentMessages[keccak256(abi.encodePacked(_message, msg.sender))] = true;\n }\n}\n" - }, - "contracts/legacy/LegacyMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { ILegacyMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @title LegacyMintableERC20\n * @notice The legacy implementation of the OptimismMintableERC20. This\n * contract is deprecated and should no longer be used.\n */\ncontract LegacyMintableERC20 is ILegacyMintableERC20, ERC20 {\n /**\n * @notice Emitted when the token is minted by the bridge.\n */\n event Mint(address indexed _account, uint256 _amount);\n\n /**\n * @notice Emitted when a token is burned by the bridge.\n */\n event Burn(address indexed _account, uint256 _amount);\n\n /**\n * @notice The token on the remote domain.\n */\n address public l1Token;\n\n /**\n * @notice The local bridge.\n */\n address public l2Bridge;\n\n /**\n * @param _l2Bridge Address of the L2 standard bridge.\n * @param _l1Token Address of the corresponding L1 token.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n */\n constructor(\n address _l2Bridge,\n address _l1Token,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) {\n l1Token = _l1Token;\n l2Bridge = _l2Bridge;\n }\n\n /**\n * @notice Modifier that requires the contract was called by the bridge.\n */\n modifier onlyL2Bridge() {\n require(msg.sender == l2Bridge, \"Only L2 Bridge can mint and burn\");\n _;\n }\n\n /**\n * @notice EIP165 implementation.\n */\n function supportsInterface(bytes4 _interfaceId) public pure returns (bool) {\n bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^\n ILegacyMintableERC20.mint.selector ^\n ILegacyMintableERC20.burn.selector;\n return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n }\n\n /**\n * @notice Only the bridge can mint tokens.\n * @param _to The account receiving tokens.\n * @param _amount The amount of tokens to receive.\n */\n function mint(address _to, uint256 _amount) public virtual onlyL2Bridge {\n _mint(_to, _amount);\n\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Only the bridge can burn tokens.\n * @param _from The account having tokens burnt.\n * @param _amount The amount of tokens being burnt.\n */\n function burn(address _from, uint256 _amount) public virtual onlyL2Bridge {\n _burn(_from, _amount);\n\n emit Burn(_from, _amount);\n }\n}\n" - }, - "contracts/legacy/ResolvedDelegateProxy.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressManager } from \"./AddressManager.sol\";\n\n/**\n * @custom:legacy\n * @title ResolvedDelegateProxy\n * @notice ResolvedDelegateProxy is a legacy proxy contract that makes use of the AddressManager to\n * resolve the implementation address. We're maintaining this contract for backwards\n * compatibility so we can manage all legacy proxies where necessary.\n */\ncontract ResolvedDelegateProxy {\n /**\n * @notice Mapping used to store the implementation name that corresponds to this contract. A\n * mapping was originally used as a way to bypass the same issue normally solved by\n * storing the implementation address in a specific storage slot that does not conflict\n * with any other storage slot. Generally NOT a safe solution but works as long as the\n * implementation does not also keep a mapping in the first storage slot.\n */\n mapping(address => string) private implementationName;\n\n /**\n * @notice Mapping used to store the address of the AddressManager contract where the\n * implementation address will be resolved from. Same concept here as with the above\n * mapping. Also generally unsafe but fine if the implementation doesn't keep a mapping\n * in the second storage slot.\n */\n mapping(address => AddressManager) private addressManager;\n\n /**\n * @param _addressManager Address of the AddressManager.\n * @param _implementationName implementationName of the contract to proxy to.\n */\n constructor(AddressManager _addressManager, string memory _implementationName) {\n addressManager[address(this)] = _addressManager;\n implementationName[address(this)] = _implementationName;\n }\n\n /**\n * @notice Fallback, performs a delegatecall to the resolved implementation address.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n address target = addressManager[address(this)].getAddress(\n (implementationName[address(this)])\n );\n\n require(target != address(0), \"ResolvedDelegateProxy: target address must be initialized\");\n\n // slither-disable-next-line controlled-delegatecall\n (bool success, bytes memory returndata) = target.delegatecall(msg.data);\n\n if (success == true) {\n assembly {\n return(add(returndata, 0x20), mload(returndata))\n }\n } else {\n assembly {\n revert(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n" - }, - "contracts/libraries/Arithmetic.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { SignedMath } from \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\nimport { FixedPointMathLib } from \"@rari-capital/solmate/src/utils/FixedPointMathLib.sol\";\n\n/**\n * @title Arithmetic\n * @notice Even more math than before.\n */\nlibrary Arithmetic {\n /**\n * @notice Clamps a value between a minimum and maximum.\n *\n * @param _value The value to clamp.\n * @param _min The minimum value.\n * @param _max The maximum value.\n *\n * @return The clamped value.\n */\n function clamp(\n int256 _value,\n int256 _min,\n int256 _max\n ) internal pure returns (int256) {\n return SignedMath.min(SignedMath.max(_value, _min), _max);\n }\n\n /**\n * @notice (c)oefficient (d)enominator (exp)onentiation function.\n * Returns the result of: c * (1 - 1/d)^exp.\n *\n * @param _coefficient Coefficient of the function.\n * @param _denominator Fractional denominator.\n * @param _exponent Power function exponent.\n *\n * @return Result of c * (1 - 1/d)^exp.\n */\n function cdexp(\n int256 _coefficient,\n int256 _denominator,\n int256 _exponent\n ) internal pure returns (int256) {\n return\n (_coefficient *\n (FixedPointMathLib.powWad(1e18 - (1e18 / _denominator), _exponent * 1e18))) / 1e18;\n }\n}\n" - }, - "contracts/libraries/Burn.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Burn\n * @notice Utilities for burning stuff.\n */\nlibrary Burn {\n /**\n * Burns a given amount of ETH.\n *\n * @param _amount Amount of ETH to burn.\n */\n function eth(uint256 _amount) internal {\n new Burner{ value: _amount }();\n }\n\n /**\n * Burns a given amount of gas.\n *\n * @param _amount Amount of gas to burn.\n */\n function gas(uint256 _amount) internal view {\n uint256 i = 0;\n uint256 initialGas = gasleft();\n while (initialGas - gasleft() < _amount) {\n ++i;\n }\n }\n}\n\n/**\n * @title Burner\n * @notice Burner self-destructs on creation and sends all ETH to itself, removing all ETH given to\n * the contract from the circulating supply. Self-destructing is the only way to remove ETH\n * from the circulating supply.\n */\ncontract Burner {\n constructor() payable {\n selfdestruct(payable(address(this)));\n }\n}\n" - }, - "contracts/libraries/Bytes.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Bytes\n * @notice Bytes is a library for manipulating byte arrays.\n */\nlibrary Bytes {\n /**\n * @custom:attribution https://github.com/GNSPS/solidity-bytes-utils\n * @notice Slices a byte array with a given starting index and length. Returns a new byte array\n * as opposed to a pointer to the original array. Will throw if trying to slice more\n * bytes than exist in the array.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n * @param _length Length of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n unchecked {\n require(_length + 31 >= _length, \"slice_overflow\");\n require(_start + _length >= _start, \"slice_overflow\");\n require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n }\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n /**\n * @notice Slices a byte array with a given starting index up to the end of the original byte\n * array. Returns a new array rathern than a pointer to the original.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {\n if (_start >= _bytes.length) {\n return bytes(\"\");\n }\n return slice(_bytes, _start, _bytes.length - _start);\n }\n\n /**\n * @notice Converts a byte array into a nibble array by splitting each byte into two nibbles.\n * Resulting nibble array will be exactly twice as long as the input byte array.\n *\n * @param _bytes Input byte array to convert.\n *\n * @return Resulting nibble array.\n */\n function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n uint256 bytesLength = _bytes.length;\n bytes memory nibbles = new bytes(bytesLength * 2);\n bytes1 b;\n\n for (uint256 i = 0; i < bytesLength; ) {\n b = _bytes[i];\n nibbles[i * 2] = b >> 4;\n nibbles[i * 2 + 1] = b & 0x0f;\n unchecked {\n ++i;\n }\n }\n\n return nibbles;\n }\n\n /**\n * @notice Compares two byte arrays by comparing their keccak256 hashes.\n *\n * @param _bytes First byte array to compare.\n * @param _other Second byte array to compare.\n *\n * @return True if the two byte arrays are equal, false otherwise.\n */\n function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {\n return keccak256(_bytes) == keccak256(_other);\n }\n}\n" - }, - "contracts/libraries/Constants.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\n/**\n * @title Constants\n * @notice Constants is a library for storing constants. Simple! Don't put everything in here, just\n * the stuff used in multiple contracts. Constants that only apply to a single contract\n * should be defined in that contract instead.\n */\nlibrary Constants {\n /**\n * @notice Special address to be used as the tx origin for gas estimation calls in the\n * OptimismPortal and CrossDomainMessenger calls. You only need to use this address if\n * the minimum gas limit specified by the user is not actually enough to execute the\n * given message and you're attempting to estimate the actual necessary gas limit. We\n * use address(1) because it's the ecrecover precompile and therefore guaranteed to\n * never have any code on any EVM chain.\n */\n address internal constant ESTIMATION_ADDRESS = address(1);\n\n /**\n * @notice Value used for the L2 sender storage slot in both the OptimismPortal and the\n * CrossDomainMessenger contracts before an actual sender is set. This value is\n * non-zero to reduce the gas cost of message passing transactions.\n */\n address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD;\n\n /**\n * @notice Returns the default values for the ResourceConfig. These are the recommended values\n * for a production network.\n */\n function DEFAULT_RESOURCE_CONFIG()\n internal\n pure\n returns (ResourceMetering.ResourceConfig memory)\n {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n return config;\n }\n}\n" - }, - "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" - }, - "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" - }, - "contracts/libraries/LegacyCrossDomainUtils.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n// Importing from the legacy contracts package causes issues with the build of the contract bindings\n// so we just copy the library here from\n// /packages/contracts/contracts/libraries/bridge/Lib_CrossDomainUtils.sol at commit\n// 7866168c\n/**\n * @title LegacyCrossDomainUtils\n */\nlibrary LegacyCrossDomainUtils {\n /**\n * Generates the correct cross domain calldata for a message.\n * @param _target Target contract address.\n * @param _sender Message sender address.\n * @param _message Message to send to the target.\n * @param _messageNonce Nonce for the provided message.\n * @return ABI encoded cross domain calldata.\n */\n function encodeXDomainCalldata(\n address _target,\n address _sender,\n bytes memory _message,\n uint256 _messageNonce\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(address,address,bytes,uint256)\",\n _target,\n _sender,\n _message,\n _messageNonce\n );\n }\n}\n" - }, - "contracts/libraries/Predeploys.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Predeploys\n * @notice Contains constant addresses for contracts that are pre-deployed to the L2 system.\n */\nlibrary Predeploys {\n /**\n * @notice Address of the L2ToL1MessagePasser predeploy.\n */\n address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016;\n\n /**\n * @notice Address of the L2CrossDomainMessenger predeploy.\n */\n address internal constant L2_CROSS_DOMAIN_MESSENGER =\n 0x4200000000000000000000000000000000000007;\n\n /**\n * @notice Address of the L2StandardBridge predeploy.\n */\n address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;\n\n /**\n * @notice Address of the L2ERC721Bridge predeploy.\n */\n address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014;\n\n /**\n * @notice Address of the SequencerFeeWallet predeploy.\n */\n address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;\n\n /**\n * @notice Address of the OptimismMintableERC20Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY =\n 0x4200000000000000000000000000000000000012;\n\n /**\n * @notice Address of the OptimismMintableERC721Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY =\n 0x4200000000000000000000000000000000000017;\n\n /**\n * @notice Address of the L1Block predeploy.\n */\n address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015;\n\n /**\n * @notice Address of the GasPriceOracle predeploy. Includes fee information\n * and helpers for computing the L1 portion of the transaction fee.\n */\n address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F;\n\n /**\n * @custom:legacy\n * @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger\n * or access tx.origin (or msg.sender) in a L1 to L2 transaction instead.\n */\n address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;\n\n /**\n * @custom:legacy\n * @notice Address of the DeployerWhitelist predeploy. No longer active.\n */\n address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the\n * state trie as of the Bedrock upgrade. Contract has been locked and write functions\n * can no longer be accessed.\n */\n address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;\n\n /**\n * @custom:legacy\n * @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy\n * instead, which exposes more information about the L1 state.\n */\n address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated\n * L2ToL1MessagePasser contract instead.\n */\n address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;\n\n /**\n * @notice Address of the ProxyAdmin predeploy.\n */\n address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018;\n\n /**\n * @notice Address of the BaseFeeVault predeploy.\n */\n address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019;\n\n /**\n * @notice Address of the L1FeeVault predeploy.\n */\n address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A;\n\n /**\n * @notice Address of the GovernanceToken predeploy.\n */\n address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042;\n}\n" - }, - "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, 32), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n\n /**\n * @notice Perform a low level call without copying any returndata. This function\n * will revert if the call cannot be performed with the specified minimum\n * gas.\n *\n * @param _target Address to call\n * @param _minGas The minimum amount of gas that may be passed 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 callWithMinGas(\n address _target,\n uint256 _minGas,\n uint256 _value,\n bytes memory _calldata\n ) internal returns (bool) {\n bool _success;\n assembly {\n // Assertion: gasleft() >= ((_minGas + 200) * 64) / 63\n //\n // Because EIP-150 ensures that, a maximum of 63/64ths of the remaining gas in the call\n // frame may be passed to a subcontext, we need to ensure that the gas will not be\n // truncated to hold this function's invariant: \"If a call is performed by\n // `callWithMinGas`, it must receive at least the specified minimum gas limit.\" In\n // addition, exactly 51 gas is consumed between the below `GAS` opcode and the `CALL`\n // opcode, so it is factored in with some extra room for error.\n if lt(gas(), div(mul(64, add(_minGas, 200)), 63)) {\n // Store the \"Error(string)\" selector in scratch space.\n mstore(0, 0x08c379a0)\n // Store the pointer to the string length in scratch space.\n mstore(32, 32)\n // Store the string.\n //\n // SAFETY:\n // - We pad the beginning of the string with two zero bytes as well as the\n // length (24) to ensure that we override the free memory pointer at offset\n // 0x40. This is necessary because the free memory pointer is likely to\n // be greater than 1 byte when this function is called, but it is incredibly\n // unlikely that it will be greater than 3 bytes. As for the data within\n // 0x60, it is ensured that it is 0 due to 0x60 being the zero offset.\n // - It's fine to clobber the free memory pointer, we're reverting.\n mstore(88, 0x0000185361666543616c6c3a204e6f7420656e6f75676820676173)\n\n // Revert with 'Error(\"SafeCall: Not enough gas\")'\n revert(28, 100)\n }\n\n // The call will be supplied at least (((_minGas + 200) * 64) / 63) - 49 gas due to the\n // above assertion. This ensures that, in all circumstances, the call will\n // receive at least the minimum amount of gas specified.\n // We can prove this property by solving the inequalities:\n // ((((_minGas + 200) * 64) / 63) - 49) >= _minGas\n // ((((_minGas + 200) * 64) / 63) - 51) * (63 / 64) >= _minGas\n // Both inequalities hold true for all possible values of `_minGas`.\n _success := call(\n gas(), // gas\n _target, // recipient\n _value, // ether value\n add(_calldata, 32), // inloc\n mload(_calldata), // inlen\n 0x00, // outloc\n 0x00 // outlen\n )\n }\n return _success;\n }\n}\n" - }, - "contracts/libraries/Types.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 * @custom:field outputRoot Hash of the L2 output.\n * @custom:field timestamp Timestamp of the L1 block that the output root was submitted in.\n * @custom:field l2BlockNumber L2 block number that the output corresponds to.\n */\n struct OutputProposal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2BlockNumber;\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 * @custom:field version Version of the output root.\n * @custom:field stateRoot Root of the state trie at the block of this output.\n * @custom:field messagePasserStorageRoot Root of the message passer storage trie.\n * @custom:field latestBlockhash Hash of the block this output was generated from.\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 * @custom:field from Address of the sender of the transaction.\n * @custom:field to Address of the recipient of the transaction.\n * @custom:field isCreation True if the transaction is a contract creation.\n * @custom:field value Value to send to the recipient.\n * @custom:field mint Amount of ETH to mint.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the transaction.\n * @custom:field l1BlockHash Hash of the block the transaction was submitted in.\n * @custom:field logIndex Index of the log in the block the transaction was submitted in.\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 * @custom:field nonce Nonce of the withdrawal transaction\n * @custom:field sender Address of the sender of the transaction.\n * @custom:field target Address of the recipient of the transaction.\n * @custom:field value Value to send to the recipient.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the 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" - }, - "contracts/libraries/rlp/RLPReader.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\n/**\n * @custom:attribution https://github.com/hamdiallam/Solidity-RLP\n * @title RLPReader\n * @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted\n * from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with\n * various tweaks to improve readability.\n */\nlibrary RLPReader {\n /**\n * Custom pointer type to avoid confusion between pointers and uint256s.\n */\n type MemoryPointer is uint256;\n\n /**\n * @notice RLP item types.\n *\n * @custom:value DATA_ITEM Represents an RLP data item (NOT a list).\n * @custom:value LIST_ITEM Represents an RLP list item.\n */\n enum RLPItemType {\n DATA_ITEM,\n LIST_ITEM\n }\n\n /**\n * @notice Struct representing an RLP item.\n *\n * @custom:field length Length of the RLP item.\n * @custom:field ptr Pointer to the RLP item in memory.\n */\n struct RLPItem {\n uint256 length;\n MemoryPointer ptr;\n }\n\n /**\n * @notice Max list length that this library will accept.\n */\n uint256 internal constant MAX_LIST_LENGTH = 32;\n\n /**\n * @notice Converts bytes to a reference to memory position and length.\n *\n * @param _in Input bytes to convert.\n *\n * @return Output memory reference.\n */\n function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) {\n // Empty arrays are not RLP items.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr;\n assembly {\n ptr := add(_in, 32)\n }\n\n return RLPItem({ length: _in.length, ptr: ptr });\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) {\n (uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.LIST_ITEM,\n \"RLPReader: decoded item type for list is not a list item\"\n );\n\n require(\n listOffset + listLength == _in.length,\n \"RLPReader: list item has an invalid data remainder\"\n );\n\n // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by\n // writing to the length. Since we can't know the number of RLP items without looping over\n // the entire input, we'd have to loop twice to accurately size this array. It's easier to\n // simply set a reasonable maximum list length and decrease the size before we finish.\n RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH);\n\n uint256 itemCount = 0;\n uint256 offset = listOffset;\n while (offset < _in.length) {\n (uint256 itemOffset, uint256 itemLength, ) = _decodeLength(\n RLPItem({\n length: _in.length - offset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n })\n );\n\n // We don't need to check itemCount < out.length explicitly because Solidity already\n // handles this check on our behalf, we'd just be wasting gas.\n out[itemCount] = RLPItem({\n length: itemLength + itemOffset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n });\n\n itemCount += 1;\n offset += itemOffset + itemLength;\n }\n\n // Decrease the array size to match the actual item count.\n assembly {\n mstore(out, itemCount)\n }\n\n return out;\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(bytes memory _in) internal pure returns (RLPItem[] memory) {\n return readList(toRLPItem(_in));\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.DATA_ITEM,\n \"RLPReader: decoded item type for bytes is not a data item\"\n );\n\n require(\n _in.length == itemOffset + itemLength,\n \"RLPReader: bytes value contains an invalid remainder\"\n );\n\n return _copy(_in.ptr, itemOffset, itemLength);\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(bytes memory _in) internal pure returns (bytes memory) {\n return readBytes(toRLPItem(_in));\n }\n\n /**\n * @notice Reads the raw bytes of an RLP item.\n *\n * @param _in RLP item to read.\n *\n * @return Raw RLP bytes.\n */\n function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n return _copy(_in.ptr, 0, _in.length);\n }\n\n /**\n * @notice Decodes the length of an RLP item.\n *\n * @param _in RLP item to decode.\n *\n * @return Offset of the encoded data.\n * @return Length of the encoded data.\n * @return RLP item type (LIST_ITEM or DATA_ITEM).\n */\n function _decodeLength(RLPItem memory _in)\n private\n pure\n returns (\n uint256,\n uint256,\n RLPItemType\n )\n {\n // Short-circuit if there's nothing to decode, note that we perform this check when\n // the user creates an RLP item via toRLPItem, but it's always possible for them to bypass\n // that function and create an RLP item directly. So we need to check this anyway.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr = _in.ptr;\n uint256 prefix;\n assembly {\n prefix := byte(0, mload(ptr))\n }\n\n if (prefix <= 0x7f) {\n // Single byte.\n return (0, 1, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xb7) {\n // Short string.\n\n // slither-disable-next-line variable-scope\n uint256 strLen = prefix - 0x80;\n\n require(\n _in.length > strLen,\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n strLen != 1 || firstByteOfContent >= 0x80,\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n\n return (1, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xbf) {\n // Long string.\n uint256 lenOfStrLen = prefix - 0xb7;\n\n require(\n _in.length > lenOfStrLen,\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n\n uint256 strLen;\n assembly {\n strLen := shr(sub(256, mul(8, lenOfStrLen)), mload(add(ptr, 1)))\n }\n\n require(\n strLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long string)\"\n );\n\n require(\n _in.length > lenOfStrLen + strLen,\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n\n return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xf7) {\n // Short list.\n // slither-disable-next-line variable-scope\n uint256 listLen = prefix - 0xc0;\n\n require(\n _in.length > listLen,\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n\n return (1, listLen, RLPItemType.LIST_ITEM);\n } else {\n // Long list.\n uint256 lenOfListLen = prefix - 0xf7;\n\n require(\n _in.length > lenOfListLen,\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long list)\"\n );\n\n uint256 listLen;\n assembly {\n listLen := shr(sub(256, mul(8, lenOfListLen)), mload(add(ptr, 1)))\n }\n\n require(\n listLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long list)\"\n );\n\n require(\n _in.length > lenOfListLen + listLen,\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n\n return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);\n }\n }\n\n /**\n * @notice Copies the bytes from a memory location.\n *\n * @param _src Pointer to the location to read from.\n * @param _offset Offset to start reading from.\n * @param _length Number of bytes to read.\n *\n * @return Copied bytes.\n */\n function _copy(\n MemoryPointer _src,\n uint256 _offset,\n uint256 _length\n ) private pure returns (bytes memory) {\n bytes memory out = new bytes(_length);\n if (_length == 0) {\n return out;\n }\n\n // Mostly based on Solidity's copy_memory_to_memory:\n // solhint-disable max-line-length\n // https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114\n uint256 src = MemoryPointer.unwrap(_src) + _offset;\n assembly {\n let dest := add(out, 32)\n let i := 0\n for {\n\n } lt(i, _length) {\n i := add(i, 32)\n } {\n mstore(add(dest, i), mload(add(src, i)))\n }\n\n if gt(i, _length) {\n mstore(add(dest, _length), 0)\n }\n }\n\n return out;\n }\n}\n" - }, - "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" - }, - "contracts/libraries/trie/MerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Bytes } from \"../Bytes.sol\";\nimport { RLPReader } from \"../rlp/RLPReader.sol\";\n\n/**\n * @title MerkleTrie\n * @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie\n * inclusion proofs. By default, this library assumes a hexary trie. One can change the\n * trie radix constant to support other trie radixes.\n */\nlibrary MerkleTrie {\n /**\n * @notice Struct representing a node in the trie.\n *\n * @custom:field encoded The RLP-encoded node.\n * @custom:field decoded The RLP-decoded node.\n */\n struct TrieNode {\n bytes encoded;\n RLPReader.RLPItem[] decoded;\n }\n\n /**\n * @notice Determines the number of elements per branch node.\n */\n uint256 internal constant TREE_RADIX = 16;\n\n /**\n * @notice Branch nodes have TREE_RADIX elements and one value element.\n */\n uint256 internal constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;\n\n /**\n * @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.\n */\n uint256 internal constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;\n\n /**\n * @notice Prefix for even-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_EVEN = 0;\n\n /**\n * @notice Prefix for odd-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_ODD = 1;\n\n /**\n * @notice Prefix for even-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_EVEN = 2;\n\n /**\n * @notice Prefix for odd-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_ODD = 3;\n\n /**\n * @notice Verifies a proof that a given key/value pair is present in the trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n return Bytes.equal(_value, get(_key, _proof, _root));\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n require(_key.length > 0, \"MerkleTrie: empty key\");\n\n TrieNode[] memory proof = _parseProof(_proof);\n bytes memory key = Bytes.toNibbles(_key);\n bytes memory currentNodeID = abi.encodePacked(_root);\n uint256 currentKeyIndex = 0;\n\n // Proof is top-down, so we start at the first element (root).\n for (uint256 i = 0; i < proof.length; i++) {\n TrieNode memory currentNode = proof[i];\n\n // Key index should never exceed total key length or we'll be out of bounds.\n require(\n currentKeyIndex <= key.length,\n \"MerkleTrie: key index exceeds total key length\"\n );\n\n if (currentKeyIndex == 0) {\n // First proof element is always the root node.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid root hash\"\n );\n } else if (currentNode.encoded.length >= 32) {\n // Nodes 32 bytes or larger are hashed inside branch nodes.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid large internal hash\"\n );\n } else {\n // Nodes smaller than 32 bytes aren't hashed.\n require(\n Bytes.equal(currentNode.encoded, currentNodeID),\n \"MerkleTrie: invalid internal node hash\"\n );\n }\n\n if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {\n if (currentKeyIndex == key.length) {\n // Value is the last element of the decoded list (for branch nodes). There's\n // some ambiguity in the Merkle trie specification because bytes(0) is a\n // valid value to place into the trie, but for branch nodes bytes(0) can exist\n // even when the value wasn't explicitly placed there. Geth treats a value of\n // bytes(0) as \"key does not exist\" and so we do the same.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[TREE_RADIX]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (branch)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (branch)\"\n );\n\n return value;\n } else {\n // We're not at the end of the key yet.\n // Figure out what the next node ID should be and continue.\n uint8 branchKey = uint8(key[currentKeyIndex]);\n RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];\n currentNodeID = _getNodeID(nextNode);\n currentKeyIndex += 1;\n }\n } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {\n bytes memory path = _getNodePath(currentNode);\n uint8 prefix = uint8(path[0]);\n uint8 offset = 2 - (prefix % 2);\n bytes memory pathRemainder = Bytes.slice(path, offset);\n bytes memory keyRemainder = Bytes.slice(key, currentKeyIndex);\n uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);\n\n // Whether this is a leaf node or an extension node, the path remainder MUST be a\n // prefix of the key remainder (or be equal to the key remainder) or the proof is\n // considered invalid.\n require(\n pathRemainder.length == sharedNibbleLength,\n \"MerkleTrie: path remainder must share all nibbles with key\"\n );\n\n if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {\n // Prefix of 2 or 3 means this is a leaf node. For the leaf node to be valid,\n // the key remainder must be exactly equal to the path remainder. We already\n // did the necessary byte comparison, so it's more efficient here to check that\n // the key remainder length equals the shared nibble length, which implies\n // equality with the path remainder (since we already did the same check with\n // the path remainder and the shared nibble length).\n require(\n keyRemainder.length == sharedNibbleLength,\n \"MerkleTrie: key remainder must be identical to path remainder\"\n );\n\n // Our Merkle Trie is designed specifically for the purposes of the Ethereum\n // state trie. Empty values are not allowed in the state trie, so we can safely\n // say that if the value is empty, the key should not exist and the proof is\n // invalid.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[1]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (leaf)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (leaf)\"\n );\n\n return value;\n } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {\n // Prefix of 0 or 1 means this is an extension node. We move onto the next node\n // in the proof and increment the key index by the length of the path remainder\n // which is equal to the shared nibble length.\n currentNodeID = _getNodeID(currentNode.decoded[1]);\n currentKeyIndex += sharedNibbleLength;\n } else {\n revert(\"MerkleTrie: received a node with an unknown prefix\");\n }\n } else {\n revert(\"MerkleTrie: received an unparseable node\");\n }\n }\n\n revert(\"MerkleTrie: ran out of proof elements\");\n }\n\n /**\n * @notice Parses an array of proof elements into a new array that contains both the original\n * encoded element and the RLP-decoded element.\n *\n * @param _proof Array of proof elements to parse.\n *\n * @return Proof parsed into easily accessible structs.\n */\n function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory) {\n uint256 length = _proof.length;\n TrieNode[] memory proof = new TrieNode[](length);\n for (uint256 i = 0; i < length; ) {\n proof[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) });\n unchecked {\n ++i;\n }\n }\n return proof;\n }\n\n /**\n * @notice Picks out the ID for a node. Node ID is referred to as the \"hash\" within the\n * specification, but nodes < 32 bytes are not actually hashed.\n *\n * @param _node Node to pull an ID for.\n *\n * @return ID for the node, depending on the size of its contents.\n */\n function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes memory) {\n return _node.length < 32 ? RLPReader.readRawBytes(_node) : RLPReader.readBytes(_node);\n }\n\n /**\n * @notice Gets the path for a leaf or extension node.\n *\n * @param _node Node to get a path for.\n *\n * @return Node path, converted to an array of nibbles.\n */\n function _getNodePath(TrieNode memory _node) private pure returns (bytes memory) {\n return Bytes.toNibbles(RLPReader.readBytes(_node.decoded[0]));\n }\n\n /**\n * @notice Utility; determines the number of nibbles shared between two nibble arrays.\n *\n * @param _a First nibble array.\n * @param _b Second nibble array.\n *\n * @return Number of shared nibbles.\n */\n function _getSharedNibbleLength(bytes memory _a, bytes memory _b)\n private\n pure\n returns (uint256)\n {\n uint256 shared;\n uint256 max = (_a.length < _b.length) ? _a.length : _b.length;\n for (; shared < max && _a[shared] == _b[shared]; ) {\n unchecked {\n ++shared;\n }\n }\n return shared;\n }\n}\n" - }, - "contracts/libraries/trie/SecureMerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* Library Imports */\nimport { MerkleTrie } from \"./MerkleTrie.sol\";\n\n/**\n * @title SecureMerkleTrie\n * @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input\n * keys. Ethereum's state trie hashes input keys before storing them.\n */\nlibrary SecureMerkleTrie {\n /**\n * @notice Verifies a proof that a given key/value pair is present in the Merkle trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.get(key, _proof, _root);\n }\n\n /**\n * @notice Computes the hashed version of the input key.\n *\n * @param _key Key to hash.\n *\n * @return Hashed version of the key.\n */\n function _getSecureKey(bytes memory _key) private pure returns (bytes memory) {\n return abi.encodePacked(keccak256(_key));\n }\n}\n" - }, - "contracts/periphery/TransferOnion.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ReentrancyGuard } from \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @title TransferOnion\n * @notice TransferOnion is a hash onion for distributing tokens. The shell commits\n * to an ordered list of the token transfers and can be permissionlessly\n * unwrapped in order. The SENDER must `approve` this contract as\n * `transferFrom` is used to move the token balances.\n */\ncontract TransferOnion is ReentrancyGuard {\n using SafeERC20 for ERC20;\n\n /**\n * @notice Struct representing a layer of the onion.\n */\n struct Layer {\n address recipient;\n uint256 amount;\n bytes32 shell;\n }\n\n /**\n * @notice Address of the token to distribute.\n */\n ERC20 public immutable TOKEN;\n\n /**\n * @notice Address of the account to distribute tokens from.\n */\n address public immutable SENDER;\n\n /**\n * @notice Current shell hash.\n */\n bytes32 public shell;\n\n /**\n * @param _token Address of the token to distribute.\n * @param _sender Address of the sender to distribute from.\n * @param _shell Initial shell of the onion.\n */\n constructor(\n ERC20 _token,\n address _sender,\n bytes32 _shell\n ) {\n TOKEN = _token;\n SENDER = _sender;\n shell = _shell;\n }\n\n /**\n * @notice Peels layers from the onion and distributes tokens.\n *\n * @param _layers Array of onion layers to peel.\n */\n function peel(Layer[] memory _layers) public nonReentrant {\n bytes32 tempShell = shell;\n uint256 length = _layers.length;\n for (uint256 i = 0; i < length; ) {\n Layer memory layer = _layers[i];\n\n // Confirm that the onion layer is correct.\n require(\n keccak256(abi.encode(layer.recipient, layer.amount, layer.shell)) == tempShell,\n \"TransferOnion: what are you doing in my swamp?\"\n );\n\n // Update the onion layer.\n tempShell = layer.shell;\n\n // Transfer the tokens.\n TOKEN.safeTransferFrom(SENDER, layer.recipient, layer.amount);\n\n // Unchecked increment to save some gas.\n unchecked {\n ++i;\n }\n }\n\n shell = tempShell;\n }\n}\n" - }, - "contracts/test/AddressAliasHelper.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract AddressAliasHelper_applyAndUndo_Test is Test {\n /**\n * @notice Tests that applying and then undoing an alias results in the original address.\n */\n function testFuzz_applyAndUndo_succeeds(address _address) external {\n address aliased = AddressAliasHelper.applyL1ToL2Alias(_address);\n address unaliased = AddressAliasHelper.undoL1ToL2Alias(aliased);\n assertEq(_address, unaliased);\n }\n}\n" - }, - "contracts/test/BenchmarkTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test } from \"forge-std/Test.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport \"./CommonTest.t.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\n// Free function for setting the prevBaseFee param in the OptimismPortal.\nfunction setPrevBaseFee(\n Vm _vm,\n address _op,\n uint128 _prevBaseFee\n) {\n _vm.store(address(_op), bytes32(uint256(1)), bytes32((block.number << 192) | _prevBaseFee));\n}\n\ncontract SetPrevBaseFee_Test is Portal_Initializer {\n function test_setPrevBaseFee_succeeds() external {\n setPrevBaseFee(vm, address(op), 100 gwei);\n (uint128 prevBaseFee, , uint64 prevBlockNum) = op.params();\n assertEq(uint256(prevBaseFee), 100 gwei);\n assertEq(uint256(prevBlockNum), block.number);\n }\n}\n\n// Tests for obtaining pure gas cost estimates for commonly used functions.\n// The objective with these benchmarks is to strip down the actual test functions\n// so that they are nothing more than the call we want measure the gas cost of.\n// In order to achieve this we make no assertions, and handle everything else in the setUp()\n// function.\ncontract GasBenchMark_OptimismPortal is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n bytes32 _outputRoot;\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n\n // Get withdrawal proof data we can use for testing.\n bytes32 _storageRoot;\n bytes32 _stateRoot;\n (_stateRoot, _storageRoot, _outputRoot, , _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public virtual override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n function test_depositTransaction_benchmark() external {\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_depositTransaction_benchmark_1() external {\n setPrevBaseFee(vm, address(op), 1 gwei);\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_proveWithdrawalTransaction_benchmark() external {\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n}\n\ncontract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer {\n function test_sendMessage_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n vm.resumeGasMetering();\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n\n function test_sendMessage_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n vm.resumeGasMetering();\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), alice, 100000, true);\n vm.startPrank(alice, alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n }\n\n function test_depositETH_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n vm.resumeGasMetering();\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositETH_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n vm.resumeGasMetering();\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositERC20_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n vm.resumeGasMetering();\n L1Bridge.bridgeERC20({\n _localToken: address(L1Token),\n _remoteToken: address(L2Token),\n _amount: 100,\n _minGasLimit: 100_000,\n _extraData: hex\"\"\n });\n }\n\n function test_depositERC20_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n vm.resumeGasMetering();\n L1Bridge.bridgeERC20({\n _localToken: address(L1Token),\n _remoteToken: address(L2Token),\n _amount: 100,\n _minGasLimit: 100_000,\n _extraData: hex\"\"\n });\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Finalize is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), address(L1Bridge), 100, true);\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.startPrank(address(L1Bridge.messenger()));\n vm.deal(address(L1Bridge.messenger()), 100);\n }\n\n function test_finalizeETHWithdrawal_benchmark() external {\n // TODO: Make this more accurate. It is underestimating the cost because it pranks\n // the call coming from the messenger, which bypasses the portal\n // and oracle.\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n\ncontract GasBenchMark_L2OutputOracle is L2OutputOracle_Initializer {\n uint256 nextBlockNumber;\n\n function setUp() public override {\n super.setUp();\n nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.startPrank(proposer);\n }\n\n function test_proposeL2Output_benchmark() external {\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n}\n" - }, - "contracts/test/Bytes.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Bytes } from \"../libraries/Bytes.sol\";\n\ncontract Bytes_slice_Test is Test {\n /**\n * @notice Tests that the `slice` function works as expected when starting from index 0.\n */\n function test_slice_fromZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check if all possible slices starting from index 0 are correct.\n assertEq(Bytes.slice(input, 0, 0), hex\"\");\n assertEq(Bytes.slice(input, 0, 1), hex\"11\");\n assertEq(Bytes.slice(input, 0, 2), hex\"1122\");\n assertEq(Bytes.slice(input, 0, 3), hex\"112233\");\n assertEq(Bytes.slice(input, 0, 4), hex\"11223344\");\n assertEq(Bytes.slice(input, 0, 5), hex\"1122334455\");\n assertEq(Bytes.slice(input, 0, 6), hex\"112233445566\");\n assertEq(Bytes.slice(input, 0, 7), hex\"11223344556677\");\n assertEq(Bytes.slice(input, 0, 8), hex\"1122334455667788\");\n assertEq(Bytes.slice(input, 0, 9), hex\"112233445566778899\");\n assertEq(Bytes.slice(input, 0, 10), hex\"11223344556677889900\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when starting from indices [1, 9]\n * with lengths [1, 9], in reverse order.\n */\n function test_slice_fromNonZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check correctness of slices starting from indexes [1, 9]\n // and spanning [1, 9] bytes, in reverse order\n assertEq(Bytes.slice(input, 9, 1), hex\"00\");\n assertEq(Bytes.slice(input, 8, 2), hex\"9900\");\n assertEq(Bytes.slice(input, 7, 3), hex\"889900\");\n assertEq(Bytes.slice(input, 6, 4), hex\"77889900\");\n assertEq(Bytes.slice(input, 5, 5), hex\"6677889900\");\n assertEq(Bytes.slice(input, 4, 6), hex\"556677889900\");\n assertEq(Bytes.slice(input, 3, 7), hex\"44556677889900\");\n assertEq(Bytes.slice(input, 2, 8), hex\"3344556677889900\");\n assertEq(Bytes.slice(input, 1, 9), hex\"223344556677889900\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when slicing between multiple words\n * in memory. In this case, we test that a 2 byte slice between the 32nd byte of the\n * first word and the 1st byte of the second word is correct.\n */\n function test_slice_acrossWords_works() public {\n bytes\n memory input = hex\"00000000000000000000000000000000000000000000000000000000000000112200000000000000000000000000000000000000000000000000000000000000\";\n\n assertEq(Bytes.slice(input, 31, 2), hex\"1122\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when slicing between multiple\n * words in memory. In this case, we test that a 34 byte slice between 3 separate words\n * returns the correct result.\n */\n function test_slice_acrossMultipleWords_works() public {\n bytes\n memory input = hex\"000000000000000000000000000000000000000000000000000000000000001122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1100000000000000000000000000000000000000000000000000000000000000\";\n bytes\n memory expected = hex\"1122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11\";\n\n assertEq(Bytes.slice(input, 31, 34), expected);\n }\n\n /**\n * @notice Tests that, when given an input bytes array of length `n`, the `slice` function will\n * always revert if `_start + _length > n`.\n */\n function testFuzz_slice_outOfBounds_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // We want a valid start index and a length that will not overflow.\n vm.assume(_start < _input.length && _length < type(uint256).max - 31);\n // But, we want an invalid slice length.\n vm.assume(_start + _length > _input.length);\n\n vm.expectRevert(\"slice_outOfBounds\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that, when given a length `n` that is greater than `type(uint256).max - 31`,\n * the `slice` function reverts.\n */\n function testFuzz_slice_lengthOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that the `_length` will overflow if a number >= 31 is added to it.\n vm.assume(_length > type(uint256).max - 31);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that, when given a start index `n` that is greater than\n * `type(uint256).max - n`, the `slice` function reverts.\n */\n function testFuzz_slice_rangeOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that `_length` is a realistic length of a slice. This is to make sure\n // we revert on the correct require statement.\n vm.assume(_length < _input.length);\n // Ensure that `_start` will overflow if `_length` is added to it.\n vm.assume(_start > type(uint256).max - _length);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that the `slice` function correctly updates the free memory pointer depending\n * on the length of the slice.\n */\n function testFuzz_slice_memorySafety_succeeds(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // The start should never be more than the length of the input bytes array - 1\n vm.assume(_start < _input.length);\n // The length should never be more than the length of the input bytes array - the starting\n // slice index.\n vm.assume(_length <= _input.length - _start);\n\n // Grab the free memory pointer before the slice operation\n uint64 initPtr;\n assembly {\n initPtr := mload(0x40)\n }\n uint64 expectedPtr = uint64(initPtr + 0x20 + ((_length + 0x1f) & ~uint256(0x1f)));\n\n // Ensure that all memory outside of the expected range is safe.\n vm.expectSafeMemory(initPtr, expectedPtr);\n\n // Slice the input bytes array from `_start` to `_start + _length`\n bytes memory slice = Bytes.slice(_input, _start, _length);\n\n // Grab the free memory pointer after the slice operation\n uint64 finalPtr;\n assembly {\n finalPtr := mload(0x40)\n }\n\n // The free memory pointer should have been updated properly\n if (_length == 0) {\n // If the slice length is zero, only 32 bytes of memory should have been allocated.\n assertEq(finalPtr, initPtr + 0x20);\n } else {\n // If the slice length is greater than zero, the memory allocated should be the\n // length of the slice rounded up to the next 32 byte word + 32 bytes for the\n // length of the byte array.\n //\n // Note that we use a slightly less efficient, but equivalent method of rounding\n // up `_length` to the next multiple of 32 than is used in the `slice` function.\n // This is to diff test the method used in `slice`.\n uint64 _expectedPtr = uint64(initPtr + 0x20 + (((_length + 0x1F) >> 5) << 5));\n assertEq(finalPtr, _expectedPtr);\n\n // Sanity check for equivalence of the rounding methods.\n assertEq(_expectedPtr, expectedPtr);\n }\n\n // The slice length should be equal to `_length`\n assertEq(slice.length, _length);\n }\n}\n\ncontract Bytes_toNibbles_Test is Test {\n /**\n * @notice Diffs the test Solidity version of `toNibbles` against the Yul version.\n *\n * @param _bytes The `bytes` array to convert to nibbles.\n *\n * @return Yul version of `toNibbles` applied to `_bytes`.\n */\n function _toNibblesYul(bytes memory _bytes) internal pure returns (bytes memory) {\n // Allocate memory for the `nibbles` array.\n bytes memory nibbles = new bytes(_bytes.length << 1);\n\n assembly {\n // Load the length of the passed bytes array from memory\n let bytesLength := mload(_bytes)\n\n // Store the memory offset of the _bytes array's contents on the stack\n let bytesStart := add(_bytes, 0x20)\n\n // Store the memory offset of the nibbles array's contents on the stack\n let nibblesStart := add(nibbles, 0x20)\n\n // Loop through each byte in the input array\n for {\n let i := 0x00\n } lt(i, bytesLength) {\n i := add(i, 0x01)\n } {\n // Get the starting offset of the next 2 bytes in the nibbles array\n let offset := add(nibblesStart, shl(0x01, i))\n\n // Load the byte at the current index within the `_bytes` array\n let b := byte(0x00, mload(add(bytesStart, i)))\n\n // Pull out the first nibble and store it in the new array\n mstore8(offset, shr(0x04, b))\n // Pull out the second nibble and store it in the new array\n mstore8(add(offset, 0x01), and(b, 0x0F))\n }\n }\n\n return nibbles;\n }\n\n /**\n * @notice Tests that, given an input of 5 bytes, the `toNibbles` function returns an array of\n * 10 nibbles corresponding to the input data.\n */\n function test_toNibbles_expectedResult5Bytes_works() public {\n bytes memory input = hex\"1234567890\";\n bytes memory expected = hex\"01020304050607080900\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Tests that, given an input of 128 bytes, the `toNibbles` function returns an array\n * of 256 nibbles corresponding to the input data. This test exists to ensure that,\n * given a large input, the `toNibbles` function works as expected.\n */\n function test_toNibbles_expectedResult128Bytes_works() public {\n bytes\n memory input = hex\"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f\";\n bytes\n memory expected = hex\"0000000100020003000400050006000700080009000a000b000c000d000e000f0100010101020103010401050106010701080109010a010b010c010d010e010f0200020102020203020402050206020702080209020a020b020c020d020e020f0300030103020303030403050306030703080309030a030b030c030d030e030f0400040104020403040404050406040704080409040a040b040c040d040e040f0500050105020503050405050506050705080509050a050b050c050d050e050f0600060106020603060406050606060706080609060a060b060c060d060e060f0700070107020703070407050706070707080709070a070b070c070d070e070f\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Tests that, given an input of 0 bytes, the `toNibbles` function returns a zero\n * length array.\n */\n function test_toNibbles_zeroLengthInput_works() public {\n bytes memory input = hex\"\";\n bytes memory expected = hex\"\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length, 0);\n assertEq(expected.length, 0);\n assertEq(actual.length, 0);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Test that the `toNibbles` function in the `Bytes` library is equivalent to the Yul\n * implementation.\n */\n function testDiff_toNibbles_succeeds(bytes memory _input) public {\n assertEq(Bytes.toNibbles(_input), _toNibblesYul(_input));\n }\n}\n\ncontract Bytes_equal_Test is Test {\n /**\n * @notice Manually checks equality of two dynamic `bytes` arrays in memory.\n *\n * @param _a The first `bytes` array to compare.\n * @param _b The second `bytes` array to compare.\n *\n * @return True if the two `bytes` arrays are equal in memory.\n */\n function manualEq(bytes memory _a, bytes memory _b) internal pure returns (bool) {\n bool _eq;\n assembly {\n _eq := and(\n // Check if the contents of the two bytes arrays are equal in memory.\n eq(keccak256(add(0x20, _a), mload(_a)), keccak256(add(0x20, _b), mload(_b))),\n // Check if the length of the two bytes arrays are equal in memory.\n // This is redundant given the above check, but included for completeness.\n eq(mload(_a), mload(_b))\n )\n }\n return _eq;\n }\n\n /**\n * @notice Tests that the `equal` function in the `Bytes` library returns `false` if given two\n * non-equal byte arrays.\n */\n function testFuzz_equal_notEqual_works(bytes memory _a, bytes memory _b) public {\n vm.assume(!manualEq(_a, _b));\n assertFalse(Bytes.equal(_a, _b));\n }\n\n /**\n * @notice Test whether or not the `equal` function in the `Bytes` library is equivalent to\n * manually checking equality of the two dynamic `bytes` arrays in memory.\n */\n function testDiff_equal_works(bytes memory _a, bytes memory _b) public {\n assertEq(Bytes.equal(_a, _b), manualEq(_a, _b));\n }\n}\n" - }, - "contracts/test/CommonTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test, StdUtils } from \"forge-std/Test.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { IL1ChugSplashDeployer } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { LegacyMintableERC20 } from \"../legacy/LegacyMintableERC20.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract CommonTest is Test {\n address alice = address(128);\n address bob = address(256);\n address multisig = address(512);\n\n address immutable ZERO_ADDRESS = address(0);\n address immutable NON_ZERO_ADDRESS = address(1);\n uint256 immutable NON_ZERO_VALUE = 100;\n uint256 immutable ZERO_VALUE = 0;\n uint64 immutable NON_ZERO_GASLIMIT = 50000;\n bytes32 nonZeroHash = keccak256(abi.encode(\"NON_ZERO\"));\n bytes NON_ZERO_DATA = hex\"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000\";\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n FFIInterface ffi;\n\n function setUp() public virtual {\n // Give alice and bob some ETH\n vm.deal(alice, 1 << 16);\n vm.deal(bob, 1 << 16);\n vm.deal(multisig, 1 << 16);\n\n vm.label(alice, \"alice\");\n vm.label(bob, \"bob\");\n vm.label(multisig, \"multisig\");\n\n // Make sure we have a non-zero base fee\n vm.fee(1000000000);\n\n ffi = new FFIInterface();\n }\n\n function emitTransactionDeposited(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) internal {\n emit TransactionDeposited(\n _from,\n _to,\n 0,\n abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data)\n );\n }\n}\n\ncontract L2OutputOracle_Initializer is CommonTest {\n // Test target\n L2OutputOracle oracle;\n L2OutputOracle oracleImpl;\n\n L2ToL1MessagePasser messagePasser =\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER));\n\n // Constructor arguments\n address internal proposer = 0x000000000000000000000000000000000000AbBa;\n address internal owner = 0x000000000000000000000000000000000000ACDC;\n uint256 internal submissionInterval = 1800;\n uint256 internal l2BlockTime = 2;\n uint256 internal startingBlockNumber = 200;\n uint256 internal startingTimestamp = 1000;\n address guardian;\n\n // Test data\n uint256 initL1Time;\n\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n // Advance the evm's time to meet the L2OutputOracle's requirements for proposeL2Output\n function warpToProposeTime(uint256 _nextBlockNumber) public {\n vm.warp(oracle.computeL2Timestamp(_nextBlockNumber) + 1);\n }\n\n function setUp() public virtual override {\n super.setUp();\n guardian = makeAddr(\"guardian\");\n\n // By default the first block has timestamp and number zero, which will cause underflows in the\n // tests, so we'll move forward to these block values.\n initL1Time = startingTimestamp + 1;\n vm.warp(initL1Time);\n vm.roll(startingBlockNumber);\n // Deploy the L2OutputOracle and transfer owernship to the proposer\n oracleImpl = new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: startingTimestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(oracleImpl),\n abi.encodeCall(L2OutputOracle.initialize, (startingBlockNumber, startingTimestamp))\n );\n oracle = L2OutputOracle(address(proxy));\n vm.label(address(oracle), \"L2OutputOracle\");\n\n // Set the L2ToL1MessagePasser at the correct address\n vm.etch(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(new L2ToL1MessagePasser()).code);\n\n vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, \"L2ToL1MessagePasser\");\n }\n}\n\ncontract Portal_Initializer is L2OutputOracle_Initializer {\n // Test target\n OptimismPortal internal opImpl;\n OptimismPortal internal op;\n SystemConfig systemConfig;\n\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n function setUp() public virtual override {\n super.setUp();\n\n ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();\n\n systemConfig = new SystemConfig({\n _owner: address(1),\n _overhead: 0,\n _scalar: 10000,\n _batcherHash: bytes32(0),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(0),\n _config: config\n });\n\n opImpl = new OptimismPortal({\n _l2Oracle: oracle,\n _guardian: guardian,\n _paused: true,\n _config: systemConfig\n });\n\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(opImpl),\n abi.encodeWithSelector(OptimismPortal.initialize.selector, false)\n );\n op = OptimismPortal(payable(address(proxy)));\n vm.label(address(op), \"OptimismPortal\");\n }\n}\n\ncontract Messenger_Initializer is Portal_Initializer {\n AddressManager internal addressManager;\n L1CrossDomainMessenger internal L1Messenger;\n L2CrossDomainMessenger internal L2Messenger =\n L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER);\n\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n\n event SentMessageExtension1(address indexed sender, uint256 value);\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event RelayedMessage(bytes32 indexed msgHash);\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 mint,\n uint256 value,\n uint64 gasLimit,\n bool isCreation,\n bytes data\n );\n\n event WhatHappened(bool success, bytes returndata);\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the address manager\n vm.prank(multisig);\n addressManager = new AddressManager();\n\n // Setup implementation\n L1CrossDomainMessenger L1MessengerImpl = new L1CrossDomainMessenger(op);\n\n // Setup the address manager and proxy\n vm.prank(multisig);\n addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(L1MessengerImpl));\n ResolvedDelegateProxy proxy = new ResolvedDelegateProxy(\n addressManager,\n \"OVM_L1CrossDomainMessenger\"\n );\n L1Messenger = L1CrossDomainMessenger(address(proxy));\n L1Messenger.initialize();\n\n vm.etch(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n address(new L2CrossDomainMessenger(address(L1Messenger))).code\n );\n\n L2Messenger.initialize();\n\n // Label addresses\n vm.label(address(addressManager), \"AddressManager\");\n vm.label(address(L1MessengerImpl), \"L1CrossDomainMessenger_Impl\");\n vm.label(address(L1Messenger), \"L1CrossDomainMessenger_Proxy\");\n vm.label(Predeploys.LEGACY_ERC20_ETH, \"LegacyERC20ETH\");\n vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, \"L2CrossDomainMessenger\");\n\n vm.label(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n \"L1CrossDomainMessenger_aliased\"\n );\n }\n}\n\ncontract Bridge_Initializer is Messenger_Initializer {\n L1StandardBridge L1Bridge;\n L2StandardBridge L2Bridge;\n OptimismMintableERC20Factory L2TokenFactory;\n OptimismMintableERC20Factory L1TokenFactory;\n ERC20 L1Token;\n ERC20 BadL1Token;\n OptimismMintableERC20 L2Token;\n LegacyMintableERC20 LegacyL2Token;\n ERC20 NativeL2Token;\n ERC20 BadL2Token;\n OptimismMintableERC20 RemoteL1Token;\n\n event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes data\n );\n\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFailed(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ETHBridgeInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n function setUp() public virtual override {\n super.setUp();\n\n vm.label(Predeploys.L2_STANDARD_BRIDGE, \"L2StandardBridge\");\n vm.label(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, \"OptimismMintableERC20Factory\");\n\n // Deploy the L1 bridge and initialize it with the address of the\n // L1CrossDomainMessenger\n L1ChugSplashProxy proxy = new L1ChugSplashProxy(multisig);\n vm.mockCall(\n multisig,\n abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector),\n abi.encode(true)\n );\n vm.startPrank(multisig);\n proxy.setCode(address(new L1StandardBridge(payable(address(L1Messenger)))).code);\n vm.clearMockedCalls();\n address L1Bridge_Impl = proxy.getImplementation();\n vm.stopPrank();\n\n L1Bridge = L1StandardBridge(payable(address(proxy)));\n\n vm.label(address(proxy), \"L1StandardBridge_Proxy\");\n vm.label(address(L1Bridge_Impl), \"L1StandardBridge_Impl\");\n\n // Deploy the L2StandardBridge, move it to the correct predeploy\n // address and then initialize it\n L2StandardBridge l2B = new L2StandardBridge(payable(proxy));\n vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(l2B).code);\n L2Bridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE));\n\n // Set up the L2 mintable token factory\n OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory(\n Predeploys.L2_STANDARD_BRIDGE\n );\n vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(factory).code);\n L2TokenFactory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY);\n\n vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code);\n\n L1Token = new ERC20(\"Native L1 Token\", \"L1T\");\n\n LegacyL2Token = new LegacyMintableERC20({\n _l2Bridge: address(L2Bridge),\n _l1Token: address(L1Token),\n _name: string.concat(\"LegacyL2-\", L1Token.name()),\n _symbol: string.concat(\"LegacyL2-\", L1Token.symbol())\n });\n vm.label(address(LegacyL2Token), \"LegacyMintableERC20\");\n\n // Deploy the L2 ERC20 now\n L2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(L1Token),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n BadL2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n NativeL2Token = new ERC20(\"Native L2 Token\", \"L2T\");\n L1TokenFactory = new OptimismMintableERC20Factory(address(L1Bridge));\n\n RemoteL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(NativeL2Token),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n\n BadL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n }\n}\n\ncontract ERC721Bridge_Initializer is Messenger_Initializer {\n L1ERC721Bridge L1Bridge;\n L2ERC721Bridge L2Bridge;\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the L1ERC721Bridge.\n L1Bridge = new L1ERC721Bridge(address(L1Messenger), Predeploys.L2_ERC721_BRIDGE);\n\n // Deploy the implementation for the L2ERC721Bridge and etch it into the predeploy address.\n vm.etch(\n Predeploys.L2_ERC721_BRIDGE,\n address(new L2ERC721Bridge(Predeploys.L2_CROSS_DOMAIN_MESSENGER, address(L1Bridge)))\n .code\n );\n\n // Set up a reference to the L2ERC721Bridge.\n L2Bridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE);\n\n // Label the L1 and L2 bridges.\n vm.label(address(L1Bridge), \"L1ERC721Bridge\");\n vm.label(address(L2Bridge), \"L2ERC721Bridge\");\n }\n}\n\ncontract FFIInterface is Test {\n function getProveWithdrawalTransactionInputs(Types.WithdrawalTransaction memory _tx)\n external\n returns (\n bytes32,\n bytes32,\n bytes32,\n bytes32,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"getProveWithdrawalTransactionInputs\";\n cmds[2] = vm.toString(_tx.nonce);\n cmds[3] = vm.toString(_tx.sender);\n cmds[4] = vm.toString(_tx.target);\n cmds[5] = vm.toString(_tx.value);\n cmds[6] = vm.toString(_tx.gasLimit);\n cmds[7] = vm.toString(_tx.data);\n\n bytes memory result = vm.ffi(cmds);\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = abi.decode(result, (bytes32, bytes32, bytes32, bytes32, bytes[]));\n\n return (stateRoot, storageRoot, outputRoot, withdrawalHash, withdrawalProof);\n }\n\n function hashCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashCrossDomainMessage\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashWithdrawal(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashWithdrawal\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashOutputRootProof(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external returns (bytes32) {\n string[] memory cmds = new string[](6);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashOutputRootProof\";\n cmds[2] = Strings.toHexString(uint256(_version));\n cmds[3] = Strings.toHexString(uint256(_stateRoot));\n cmds[4] = Strings.toHexString(uint256(_messagePasserStorageRoot));\n cmds[5] = Strings.toHexString(uint256(_latestBlockhash));\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashDepositTransaction(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint64 _logIndex\n ) external returns (bytes32) {\n string[] memory cmds = new string[](10);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashDepositTransaction\";\n cmds[2] = \"0x0000000000000000000000000000000000000000000000000000000000000000\";\n cmds[3] = vm.toString(_logIndex);\n cmds[4] = vm.toString(_from);\n cmds[5] = vm.toString(_to);\n cmds[6] = vm.toString(_mint);\n cmds[7] = vm.toString(_value);\n cmds[8] = vm.toString(_gas);\n cmds[9] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function encodeDepositTransaction(Types.UserDepositTransaction calldata txn)\n external\n returns (bytes memory)\n {\n string[] memory cmds = new string[](11);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"encodeDepositTransaction\";\n cmds[2] = vm.toString(txn.from);\n cmds[3] = vm.toString(txn.to);\n cmds[4] = vm.toString(txn.value);\n cmds[5] = vm.toString(txn.mint);\n cmds[6] = vm.toString(txn.gasLimit);\n cmds[7] = vm.toString(txn.isCreation);\n cmds[8] = vm.toString(txn.data);\n cmds[9] = vm.toString(txn.l1BlockHash);\n cmds[10] = vm.toString(txn.logIndex);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function encodeCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes memory) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"encodeCrossDomainMessage\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function decodeVersionedNonce(uint256 nonce) external returns (uint256, uint256) {\n string[] memory cmds = new string[](3);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"decodeVersionedNonce\";\n cmds[2] = vm.toString(nonce);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (uint256, uint256));\n }\n\n function getMerkleTrieFuzzCase(string memory variant)\n external\n returns (\n bytes32,\n bytes memory,\n bytes memory,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](5);\n cmds[0] = \"./test-case-generator/fuzz\";\n cmds[1] = \"-m\";\n cmds[2] = \"trie\";\n cmds[3] = \"-v\";\n cmds[4] = variant;\n\n return abi.decode(vm.ffi(cmds), (bytes32, bytes, bytes, bytes[]));\n }\n}\n\n// Used for testing a future upgrade beyond the current implementations.\n// We include some variables so that we can sanity check accessing storage values after an upgrade.\ncontract NextImpl is Initializable {\n // Initializable occupies the zero-th slot.\n bytes32 slot1;\n bytes32[19] __gap;\n bytes32 slot21;\n bytes32 public constant slot21Init = bytes32(hex\"1337\");\n\n function initialize() public reinitializer(2) {\n // Slot21 is unused by an of our upgradeable contracts.\n // This is used to verify that we can access this value after an upgrade.\n slot21 = slot21Init;\n }\n}\n\ncontract Reverter {\n fallback() external {\n revert();\n }\n}\n\n// Useful for testing reentrancy guards\ncontract CallerCaller {\n event WhatHappened(bool success, bytes returndata);\n\n fallback() external {\n (bool success, bytes memory returndata) = msg.sender.call(msg.data);\n emit WhatHappened(success, returndata);\n assembly {\n switch success\n case 0 {\n revert(add(returndata, 0x20), mload(returndata))\n }\n default {\n return(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n\n// Used for testing the `CrossDomainMessenger`'s per-message reentrancy guard.\ncontract ConfigurableCaller {\n bool doRevert = true;\n address target;\n bytes payload;\n\n event WhatHappened(bool success, bytes returndata);\n\n /**\n * @notice Call the configured target with the configured payload OR revert.\n */\n function call() external {\n if (doRevert) {\n revert(\"ConfigurableCaller: revert\");\n } else {\n (bool success, bytes memory returndata) = address(target).call(payload);\n emit WhatHappened(success, returndata);\n assembly {\n switch success\n case 0 {\n revert(add(returndata, 0x20), mload(returndata))\n }\n default {\n return(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n }\n\n /**\n * @notice Set whether or not to have `call` revert.\n */\n function setDoRevert(bool _doRevert) external {\n doRevert = _doRevert;\n }\n\n /**\n * @notice Set the target for the call made in `call`.\n */\n function setTarget(address _target) external {\n target = _target;\n }\n\n /**\n * @notice Set the payload for the call made in `call`.\n */\n function setPayload(bytes calldata _payload) external {\n payload = _payload;\n }\n\n /**\n * @notice Fallback function that reverts if `doRevert` is true.\n * Otherwise, it does nothing.\n */\n fallback() external {\n if (doRevert) {\n revert(\"ConfigurableCaller: revert\");\n }\n }\n}\n" - }, - "contracts/test/CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, CallerCaller } from \"./CommonTest.t.sol\";\n\n// CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2\n// CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract.\ncontract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {\n // Ensure that baseGas passes for the max value of _minGasLimit,\n // this is about 4 Billion.\n function test_baseGas_succeeds() external view {\n L1Messenger.baseGas(hex\"ff\", type(uint32).max);\n }\n\n // Fuzz for other values which might cause a revert in baseGas.\n function testFuzz_baseGas_succeeds(uint32 _minGasLimit) external view {\n L1Messenger.baseGas(hex\"ff\", _minGasLimit);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest, Portal_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable } from \"../L2/CrossDomainOwnable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Vm, VmSafe } from \"forge-std/Vm.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract XDomainSetter is CrossDomainOwnable {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable_Test is CommonTest {\n XDomainSetter setter;\n\n function setUp() public override {\n super.setUp();\n setter = new XDomainSetter();\n }\n\n // Check that the revert message is correct\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable: caller is not the owner\");\n setter.set(1);\n }\n\n // Check that making a call can set the value properly\n function test_onlyOwner_succeeds() external {\n assertEq(setter.value(), 0);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(setter.owner()));\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n\ncontract CrossDomainOwnableThroughPortal_Test is Portal_Initializer {\n XDomainSetter setter;\n\n function setUp() public override {\n super.setUp();\n\n vm.prank(alice);\n setter = new XDomainSetter();\n }\n\n function test_depositTransaction_crossDomainOwner_succeeds() external {\n vm.recordLogs();\n\n vm.prank(alice);\n op.depositTransaction({\n _to: address(setter),\n _value: 0,\n _gasLimit: 21_000,\n _isCreation: false,\n _data: abi.encodeWithSelector(XDomainSetter.set.selector, 1)\n });\n\n // Simulate the operation of the `op-node` by parsing data\n // from logs\n VmSafe.Log[] memory logs = vm.getRecordedLogs();\n // Only 1 log emitted\n assertEq(logs.length, 1);\n\n VmSafe.Log memory log = logs[0];\n\n // It is the expected topic\n bytes32 topic = log.topics[0];\n assertEq(topic, keccak256(\"TransactionDeposited(address,address,uint256,bytes)\"));\n\n // from is indexed and the first argument to the event.\n bytes32 _from = log.topics[1];\n address from = Bytes32AddressLib.fromLast20Bytes(_from);\n\n assertEq(AddressAliasHelper.undoL1ToL2Alias(from), alice);\n\n // Make a call from the \"from\" value received from the log.\n // In theory the opaque data could be parsed from the log\n // and passed to a low level call to \"to\", but calling set\n // directly on the setter is good enough.\n vm.prank(from);\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable2.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\nimport { CommonTest, Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable2 } from \"../L2/CrossDomainOwnable2.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract XDomainSetter2 is CrossDomainOwnable2 {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable2_Test is Messenger_Initializer {\n XDomainSetter2 setter;\n\n function setUp() public override {\n super.setUp();\n vm.prank(alice);\n setter = new XDomainSetter2();\n }\n\n function test_onlyOwner_notMessenger_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the messenger\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n // set the xDomainMsgSender storage slot\n bytes32 key = bytes32(uint256(204));\n bytes32 value = Bytes32AddressLib.fillLast12Bytes(address(alice));\n vm.store(address(L2Messenger), key, value);\n\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the owner\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner2_reverts() external {\n uint240 nonce = 0;\n address sender = bob;\n address target = address(setter);\n uint256 value = 0;\n uint256 minGasLimit = 0;\n bytes memory message = abi.encodeWithSelector(XDomainSetter2.set.selector, 1);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n // It should be a failed message. The revert is caught,\n // so we cannot expectRevert here.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n assertEq(setter.value(), 0);\n }\n\n function test_onlyOwner_succeeds() external {\n address owner = setter.owner();\n\n // Simulate the L2 execution where the call is coming from\n // the L1CrossDomainMessenger\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(1, 1),\n owner,\n address(setter),\n 0,\n 0,\n abi.encodeWithSelector(XDomainSetter2.set.selector, 2)\n );\n\n assertEq(setter.value(), 2);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable3.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\nimport { CommonTest, Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable3 } from \"../L2/CrossDomainOwnable3.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract XDomainSetter3 is CrossDomainOwnable3 {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable3_Test is Messenger_Initializer {\n XDomainSetter3 setter;\n\n /**\n * @notice OpenZeppelin Ownable.sol transferOwnership event\n */\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @notice CrossDomainOwnable3.sol transferOwnership event\n */\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner,\n bool isLocal\n );\n\n function setUp() public override {\n super.setUp();\n vm.prank(alice);\n setter = new XDomainSetter3();\n }\n\n function test_constructor_succeeds() public {\n assertEq(setter.owner(), alice);\n assertEq(setter.isLocal(), true);\n }\n\n function test_localOnlyOwner_notOwner_reverts() public {\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.set(1);\n }\n\n function test_transferOwnership_notOwner_reverts() public {\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.transferOwnership({ _owner: bob, _isLocal: true });\n }\n\n function test_crossDomainOnlyOwner_notOwner_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n // set the xDomainMsgSender storage slot\n bytes32 key = bytes32(uint256(204));\n bytes32 value = Bytes32AddressLib.fillLast12Bytes(bob);\n vm.store(address(L2Messenger), key, value);\n\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.set(1);\n }\n\n function test_crossDomainOnlyOwner_notOwner2_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n assertEq(setter.isLocal(), false);\n\n uint240 nonce = 0;\n address sender = bob;\n address target = address(setter);\n uint256 value = 0;\n uint256 minGasLimit = 0;\n bytes memory message = abi.encodeWithSelector(XDomainSetter3.set.selector, 1);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n // It should be a failed message. The revert is caught,\n // so we cannot expectRevert here.\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit FailedRelayedMessage(hash);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n assertEq(setter.value(), 0);\n }\n\n function test_crossDomainOnlyOwner_notMessenger_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the messenger\");\n setter.set(1);\n }\n\n function test_transferOwnership_zeroAddress_reverts() public {\n vm.prank(setter.owner());\n vm.expectRevert(\"CrossDomainOwnable3: new owner is the zero address\");\n setter.transferOwnership({ _owner: address(0), _isLocal: true });\n }\n\n function test_transferOwnership_noLocalZeroAddress_reverts() public {\n vm.prank(setter.owner());\n vm.expectRevert(\"Ownable: new owner is the zero address\");\n setter.transferOwnership(address(0));\n }\n\n function test_localOnlyOwner_succeeds() public {\n assertEq(setter.isLocal(), true);\n vm.prank(setter.owner());\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n\n function test_localTransferOwnership_succeeds() public {\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n emit OwnershipTransferred(alice, bob, true);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: bob, _isLocal: true });\n\n assertEq(setter.isLocal(), true);\n\n vm.prank(bob);\n setter.set(2);\n assertEq(setter.value(), 2);\n }\n\n /**\n * @notice The existing transferOwnership(address) method\n * still exists on the contract\n */\n function test_transferOwnershipNoLocal_succeeds() public {\n bool isLocal = setter.isLocal();\n\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n\n vm.prank(setter.owner());\n setter.transferOwnership(bob);\n\n // isLocal has not changed\n assertEq(setter.isLocal(), isLocal);\n\n vm.prank(bob);\n setter.set(2);\n assertEq(setter.value(), 2);\n }\n\n function test_crossDomainTransferOwnership_succeeds() public {\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n emit OwnershipTransferred(alice, bob, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: bob, _isLocal: false });\n\n assertEq(setter.isLocal(), false);\n\n // Simulate the L2 execution where the call is coming from\n // the L1CrossDomainMessenger\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(1, 1),\n bob,\n address(setter),\n 0,\n 0,\n abi.encodeWithSelector(XDomainSetter3.set.selector, 2)\n );\n\n assertEq(setter.value(), 2);\n }\n}\n" - }, - "contracts/test/DeployerWhitelist.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { DeployerWhitelist } from \"../legacy/DeployerWhitelist.sol\";\n\ncontract DeployerWhitelist_Test is CommonTest {\n DeployerWhitelist list;\n\n function setUp() public virtual override {\n list = new DeployerWhitelist();\n }\n\n // The owner should be address(0)\n function test_owner_succeeds() external {\n assertEq(list.owner(), address(0));\n }\n\n // The storage slot for the owner must be the same\n function test_storageSlots_succeeds() external {\n vm.prank(list.owner());\n list.setOwner(address(1));\n\n assertEq(bytes32(uint256(1)), vm.load(address(list), bytes32(uint256(0))));\n }\n}\n" - }, - "contracts/test/Encoding.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { LegacyCrossDomainUtils } from \"../libraries/LegacyCrossDomainUtils.sol\";\n\ncontract Encoding_Test is CommonTest {\n function testFuzz_nonceVersioning_succeeds(uint240 _nonce, uint16 _version) external {\n (uint240 nonce, uint16 version) = Encoding.decodeVersionedNonce(\n Encoding.encodeVersionedNonce(_nonce, _version)\n );\n assertEq(version, _version);\n assertEq(nonce, _nonce);\n }\n\n function testDiff_decodeVersionedNonce_succeeds(uint240 _nonce, uint16 _version) external {\n uint256 nonce = uint256(Encoding.encodeVersionedNonce(_nonce, _version));\n (uint256 decodedNonce, uint256 decodedVersion) = ffi.decodeVersionedNonce(nonce);\n\n assertEq(_version, uint16(decodedVersion));\n\n assertEq(_nonce, uint240(decodedNonce));\n }\n\n function testDiff_encodeCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint8 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint8 version = _version % 2;\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes memory encoding = Encoding.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n bytes memory _encoding = ffi.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n assertEq(encoding, _encoding);\n }\n\n function testFuzz_encodeCrossDomainMessageV0_matchesLegacy_succeeds(\n uint240 _nonce,\n address _sender,\n address _target,\n bytes memory _data\n ) external {\n uint8 version = 0;\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes memory legacyEncoding = LegacyCrossDomainUtils.encodeXDomainCalldata(\n _target,\n _sender,\n _data,\n nonce\n );\n\n bytes memory bedrockEncoding = Encoding.encodeCrossDomainMessageV0(\n _target,\n _sender,\n _data,\n nonce\n );\n\n assertEq(legacyEncoding, bedrockEncoding);\n }\n\n function testDiff_encodeDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bool isCreate,\n bytes memory _data,\n uint64 _logIndex\n ) external {\n Types.UserDepositTransaction memory t = Types.UserDepositTransaction(\n _from,\n _to,\n isCreate,\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n );\n\n bytes memory txn = Encoding.encodeDepositTransaction(t);\n bytes memory _txn = ffi.encodeDepositTransaction(t);\n\n assertEq(txn, _txn);\n }\n}\n" - }, - "contracts/test/FeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { L1FeeVault } from \"../L2/L1FeeVault.sol\";\nimport { BaseFeeVault } from \"../L2/BaseFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n// Test the implementations of the FeeVault\ncontract FeeVault_Test is Bridge_Initializer {\n BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT));\n L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT));\n\n address constant recipient = address(0x10000);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.BASE_FEE_VAULT, address(new BaseFeeVault(recipient)).code);\n vm.etch(Predeploys.L1_FEE_VAULT, address(new L1FeeVault(recipient)).code);\n\n vm.label(Predeploys.BASE_FEE_VAULT, \"BaseFeeVault\");\n vm.label(Predeploys.L1_FEE_VAULT, \"L1FeeVault\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(baseFeeVault.RECIPIENT(), recipient);\n assertEq(l1FeeVault.RECIPIENT(), recipient);\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n}\n" - }, - "contracts/test/GasPriceOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GasPriceOracle } from \"../L2/GasPriceOracle.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract GasPriceOracle_Test is CommonTest {\n event OverheadUpdated(uint256);\n event ScalarUpdated(uint256);\n event DecimalsUpdated(uint256);\n\n GasPriceOracle gasOracle;\n L1Block l1Block;\n address depositor;\n\n // set the initial L1 context values\n uint64 constant number = 10;\n uint64 constant timestamp = 11;\n uint256 constant basefee = 100;\n bytes32 constant hash = bytes32(uint256(64));\n uint64 constant sequenceNumber = 0;\n bytes32 constant batcherHash = bytes32(uint256(777));\n uint256 constant l1FeeOverhead = 310;\n uint256 constant l1FeeScalar = 10;\n\n function setUp() public virtual override {\n super.setUp();\n // place the L1Block contract at the predeploy address\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n\n l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n depositor = l1Block.DEPOSITOR_ACCOUNT();\n\n // We are not setting the gas oracle at its predeploy\n // address for simplicity purposes. Nothing in this test\n // requires it to be at a particular address\n gasOracle = new GasPriceOracle();\n\n vm.prank(depositor);\n l1Block.setL1BlockValues({\n _number: number,\n _timestamp: timestamp,\n _basefee: basefee,\n _hash: hash,\n _sequenceNumber: sequenceNumber,\n _batcherHash: batcherHash,\n _l1FeeOverhead: l1FeeOverhead,\n _l1FeeScalar: l1FeeScalar\n });\n }\n\n function test_l1BaseFee_succeeds() external {\n assertEq(gasOracle.l1BaseFee(), basefee);\n }\n\n function test_gasPrice_succeeds() external {\n vm.fee(100);\n uint256 gasPrice = gasOracle.gasPrice();\n assertEq(gasPrice, 100);\n }\n\n function test_baseFee_succeeds() external {\n vm.fee(64);\n uint256 gasPrice = gasOracle.baseFee();\n assertEq(gasPrice, 64);\n }\n\n function test_scalar_succeeds() external {\n assertEq(gasOracle.scalar(), l1FeeScalar);\n }\n\n function test_overhead_succeeds() external {\n assertEq(gasOracle.overhead(), l1FeeOverhead);\n }\n\n function test_decimals_succeeds() external {\n assertEq(gasOracle.decimals(), 6);\n assertEq(gasOracle.DECIMALS(), 6);\n }\n\n // Removed in bedrock\n function test_setGasPrice_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setGasPrice(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n\n // Removed in bedrock\n function test_setL1BaseFee_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setL1BaseFee(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n}\n" - }, - "contracts/test/GovernanceToken.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract GovernanceToken_Test is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n\n function setUp() public virtual override {\n super.setUp();\n vm.prank(owner);\n gov = new GovernanceToken();\n }\n\n function test_constructor_succeeds() external {\n assertEq(gov.owner(), owner);\n assertEq(gov.name(), \"Optimism\");\n assertEq(gov.symbol(), \"OP\");\n assertEq(gov.decimals(), 18);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_mint_fromOwner_succeeds() external {\n // Mint 100 tokens.\n vm.prank(owner);\n gov.mint(owner, 100);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 100);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_mint_fromNotOwner_reverts() external {\n // Mint 100 tokens as rando.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n gov.mint(owner, 100);\n\n // Balance does not update.\n assertEq(gov.balanceOf(owner), 0);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_burn_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando burns their tokens.\n vm.prank(rando);\n gov.burn(50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_burnFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to burn 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner burns 50 tokens from rando.\n vm.prank(owner);\n gov.burnFrom(rando, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_transfer_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando transfers 50 tokens to owner.\n vm.prank(rando);\n gov.transfer(owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_approve_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n\n function test_transferFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner transfers 50 tokens from rando to owner.\n vm.prank(owner);\n gov.transferFrom(rando, owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_increaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Rando increases allowance by 50 tokens.\n vm.prank(rando);\n gov.increaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 100);\n }\n\n function test_decreaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 100 tokens.\n vm.prank(rando);\n gov.approve(owner, 100);\n\n // Rando decreases allowance by 50 tokens.\n vm.prank(rando);\n gov.decreaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n}\n" - }, - "contracts/test/Hashing.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { LegacyCrossDomainUtils } from \"../libraries/LegacyCrossDomainUtils.sol\";\n\ncontract Hashing_hashDepositSource_Test is CommonTest {\n /**\n * @notice Tests that hashDepositSource returns the correct hash in a simple case.\n */\n function test_hashDepositSource_succeeds() external {\n assertEq(\n Hashing.hashDepositSource(\n 0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959,\n 0x1\n ),\n 0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc\n );\n }\n}\n\ncontract Hashing_hashCrossDomainMessage_Test is CommonTest {\n /**\n * @notice Tests that hashCrossDomainMessage returns the correct hash in a simple case.\n */\n function testDiff_hashCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint16 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n // Ensure the version is valid.\n uint16 version = uint16(bound(uint256(_version), 0, 1));\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n assertEq(\n Hashing.hashCrossDomainMessage(nonce, _sender, _target, _value, _gasLimit, _data),\n ffi.hashCrossDomainMessage(nonce, _sender, _target, _value, _gasLimit, _data)\n );\n }\n\n /**\n * @notice Tests that hashCrossDomainMessageV0 matches the hash of the legacy encoding.\n */\n function testFuzz_hashCrossDomainMessageV0_matchesLegacy_succeeds(\n address _target,\n address _sender,\n bytes memory _message,\n uint256 _messageNonce\n ) external {\n assertEq(\n keccak256(\n LegacyCrossDomainUtils.encodeXDomainCalldata(\n _target,\n _sender,\n _message,\n _messageNonce\n )\n ),\n Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _messageNonce)\n );\n }\n}\n\ncontract Hashing_hashWithdrawal_Test is CommonTest {\n /**\n * @notice Tests that hashWithdrawal returns the correct hash in a simple case.\n */\n function testDiff_hashWithdrawal_succeeds(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n assertEq(\n Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(_nonce, _sender, _target, _value, _gasLimit, _data)\n ),\n ffi.hashWithdrawal(_nonce, _sender, _target, _value, _gasLimit, _data)\n );\n }\n}\n\ncontract Hashing_hashOutputRootProof_Test is CommonTest {\n /**\n * @notice Tests that hashOutputRootProof returns the correct hash in a simple case.\n */\n function testDiff_hashOutputRootProof_succeeds(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external {\n assertEq(\n Hashing.hashOutputRootProof(\n Types.OutputRootProof({\n version: _version,\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _messagePasserStorageRoot,\n latestBlockhash: _latestBlockhash\n })\n ),\n ffi.hashOutputRootProof(\n _version,\n _stateRoot,\n _messagePasserStorageRoot,\n _latestBlockhash\n )\n );\n }\n}\n\ncontract Hashing_hashDepositTransaction_Test is CommonTest {\n /**\n * @notice Tests that hashDepositTransaction returns the correct hash in a simple case.\n */\n function testDiff_hashDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint64 _logIndex\n ) external {\n assertEq(\n Hashing.hashDepositTransaction(\n Types.UserDepositTransaction(\n _from,\n _to,\n false, // isCreate\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n )\n ),\n ffi.hashDepositTransaction(_from, _to, _mint, _value, _gas, _data, _logIndex)\n );\n }\n}\n" - }, - "contracts/test/L1Block.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\ncontract L1BlockTest is CommonTest {\n L1Block lb;\n address depositor;\n bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1));\n\n function setUp() public virtual override {\n super.setUp();\n lb = new L1Block();\n depositor = lb.DEPOSITOR_ACCOUNT();\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: uint64(1),\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: NON_ZERO_HASH,\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(0),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function testFuzz_updatesValues_succeeds(\n uint64 n,\n uint64 t,\n uint256 b,\n bytes32 h,\n uint64 s,\n bytes32 bt,\n uint256 fo,\n uint256 fs\n ) external {\n vm.prank(depositor);\n lb.setL1BlockValues(n, t, b, h, s, bt, fo, fs);\n assertEq(lb.number(), n);\n assertEq(lb.timestamp(), t);\n assertEq(lb.basefee(), b);\n assertEq(lb.hash(), h);\n assertEq(lb.sequenceNumber(), s);\n assertEq(lb.batcherHash(), bt);\n assertEq(lb.l1FeeOverhead(), fo);\n assertEq(lb.l1FeeScalar(), fs);\n }\n\n function test_number_succeeds() external {\n assertEq(lb.number(), uint64(1));\n }\n\n function test_timestamp_succeeds() external {\n assertEq(lb.timestamp(), uint64(2));\n }\n\n function test_basefee_succeeds() external {\n assertEq(lb.basefee(), 3);\n }\n\n function test_hash_succeeds() external {\n assertEq(lb.hash(), NON_ZERO_HASH);\n }\n\n function test_sequenceNumber_succeeds() external {\n assertEq(lb.sequenceNumber(), uint64(4));\n }\n\n function test_updateValues_succeeds() external {\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: type(uint64).max,\n _timestamp: type(uint64).max,\n _basefee: type(uint256).max,\n _hash: keccak256(abi.encode(1)),\n _sequenceNumber: type(uint64).max,\n _batcherHash: bytes32(type(uint256).max),\n _l1FeeOverhead: type(uint256).max,\n _l1FeeScalar: type(uint256).max\n });\n }\n}\n" - }, - "contracts/test/L1BlockNumber.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { L1BlockNumber } from \"../legacy/L1BlockNumber.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract L1BlockNumberTest is Test {\n L1Block lb;\n L1BlockNumber bn;\n\n uint64 constant number = 99;\n\n function setUp() external {\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n lb = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n bn = new L1BlockNumber();\n vm.prank(lb.DEPOSITOR_ACCOUNT());\n\n lb.setL1BlockValues({\n _number: number,\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: bytes32(uint256(10)),\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(uint256(0)),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function test_getL1BlockNumber_succeeds() external {\n assertEq(bn.getL1BlockNumber(), number);\n }\n\n function test_fallback_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n\n function test_receive_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call{ value: 1 }(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n}\n" - }, - "contracts/test/L1CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Messenger_Initializer, Reverter, ConfigurableCaller } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle_Initializer } from \"./L2OutputOracle.t.sol\";\n\n/* Libraries */\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n/* Target contract dependencies */\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/* Target contract */\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\n\ncontract L1CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n // the version is encoded in the nonce\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L1Messenger.messageNonce());\n assertEq(version, L1Messenger.MESSAGE_VERSION());\n }\n\n // sendMessage: should be able to send a single message\n // TODO: this same test needs to be done with the legacy message type\n // by setting the message version to 0\n function test_sendMessage_succeeds() external {\n // deposit transaction on the optimism portal should be called\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n )\n );\n\n // TransactionDeposited event\n vm.expectEmit(true, true, true, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n );\n\n // SentMessage event\n vm.expectEmit(true, true, true, true);\n emit SentMessage(recipient, alice, hex\"ff\", L1Messenger.messageNonce(), 100);\n\n // SentMessageExtension1 event\n vm.expectEmit(true, true, true, true);\n emit SentMessageExtension1(alice, 0);\n\n vm.prank(alice);\n L1Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n // sendMessage: should be able to send the same message twice\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L1Messenger.messageNonce());\n }\n\n function test_xDomainSender_notSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n // xDomainMessageSender: should return the xDomainMsgSender address\n // TODO: might need a test contract\n // function test_xDomainSenderSetCorrectly() external {}\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(address(op));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 2 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n // relayMessage: should send a successful call to the target contract\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.expectCall(target, hex\"1111\");\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L1Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n // set the target to be the OptimismPortal\n address target = address(op);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.prank(address(op));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n\n vm.store(address(op), 0, bytes32(abi.encode(sender)));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: should revert if eth is sent from a contract other than the standard bridge\n function test_replayMessage_withValue_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.expectRevert(\n \"CrossDomainMessenger: value must be zero unless message is from a system address\"\n );\n L1Messenger.relayMessage{ value: 100 }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n vm.expectCall(target, hex\"1111\");\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n // relayMessage: Should revert if the recipient is trying to reenter with the\n // same message.\n function test_relayMessage_reentrancySameMessage_reverts() external {\n ConfigurableCaller caller = new ConfigurableCaller();\n address target = address(caller);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory callMessage = abi.encodeWithSelector(caller.call.selector);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Set the portal's `l2Sender` to the `sender`.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(uint256(uint160(sender))));\n\n // Act as the portal and call the `relayMessage` function with the `innerMessage`.\n vm.prank(address(op));\n vm.expectCall(target, callMessage);\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Assert that the message failed to be relayed\n assertFalse(L1Messenger.successfulMessages(hash));\n assertTrue(L1Messenger.failedMessages(hash));\n\n // Set the configurable caller's target to `L1Messenger` and set the payload to `relayMessage(...)`.\n caller.setDoRevert(false);\n caller.setTarget(address(L1Messenger));\n caller.setPayload(\n abi.encodeWithSelector(\n L1Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n callMessage\n )\n );\n\n // Attempt to replay the failed message, which will *not* immediately revert this time around,\n // but attempt to reenter `relayMessage` with the same message hash. The reentrancy attempt should\n // revert.\n vm.expectEmit(true, true, true, true, target);\n emit WhatHappened(\n false,\n abi.encodeWithSignature(\"Error(string)\", \"ReentrancyGuard: reentrant call\")\n );\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Assert that the message still failed to be relayed.\n assertFalse(L1Messenger.successfulMessages(hash));\n assertTrue(L1Messenger.failedMessages(hash));\n }\n\n // relayMessage: should not revert if the recipient reenters `relayMessage` with a different\n // message hash.\n function test_relayMessage_reentrancyDiffMessage_succeeds() external {\n ConfigurableCaller caller = new ConfigurableCaller();\n address target = address(caller);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory messageA = abi.encodeWithSelector(caller.call.selector);\n bytes memory messageB = hex\"\";\n\n bytes32 hashA = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n bytes32 hashB = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageB\n );\n\n // Set the portal's `l2Sender` to the `sender`.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(uint256(uint160(sender))));\n\n // Act as the portal and call the `relayMessage` function with both `messageA` and `messageB`.\n vm.startPrank(address(op));\n\n vm.expectCall(target, messageA);\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n vm.expectCall(target, messageB);\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageB\n );\n\n // Stop acting as the portal\n vm.stopPrank();\n\n // Assert that both messages failed to be relayed\n assertFalse(L1Messenger.successfulMessages(hashA));\n assertFalse(L1Messenger.successfulMessages(hashB));\n assertTrue(L1Messenger.failedMessages(hashA));\n assertTrue(L1Messenger.failedMessages(hashB));\n\n // Set the configurable caller's target to `L1Messenger` and set the payload to `relayMessage(...)`.\n caller.setDoRevert(false);\n caller.setTarget(address(L1Messenger));\n caller.setPayload(\n abi.encodeWithSelector(\n L1Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageB\n )\n );\n\n // Attempt to replay the failed message, which will *not* immediately revert this time around,\n // but attempt to reenter `relayMessage` with messageB. The reentrancy attempt should succeed\n // because the message hashes are different.\n vm.expectEmit(true, true, true, true, target);\n emit WhatHappened(true, hex\"\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n\n // Assert that both messages are now in the `successfulMessages` mapping.\n assertTrue(L1Messenger.successfulMessages(hashA));\n assertTrue(L1Messenger.successfulMessages(hashB));\n }\n\n function test_relayMessage_legacy_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyOldReplay_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Mark legacy message as already relayed.\n uint256 successfulMessagesSlot = 203;\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(target, sender, hex\"1111\", 0);\n bytes32 slot = keccak256(abi.encode(oldHash, successfulMessagesSlot));\n vm.store(address(L1Messenger), slot, bytes32(uint256(1)));\n\n // Expect revert.\n vm.expectRevert(\"CrossDomainMessenger: legacy withdrawal already relayed\");\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was not relayed.\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyRetryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect FailedRelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n function test_relayMessage_legacyRetryAfterSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message has already been relayed\");\n\n // Retry the message again.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n}\n" - }, - "contracts/test/L1ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.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\ncontract L1ERC721Bridge_Test is Messenger_Initializer {\n TestERC721 internal localToken;\n TestERC721 internal remoteToken;\n L1ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L1ERC721Bridge(address(L1Messenger), otherBridge);\n localToken = new TestERC721();\n remoteToken = new TestERC721();\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L1ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L1Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L1Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L1ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L1ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notEscrowed_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n" - }, - "contracts/test/L1StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\n\ncontract L1StandardBridge_Getter_Test is Bridge_Initializer {\n function test_getters_succeeds() external {\n assert(L1Bridge.l2TokenBridge() == address(L2Bridge));\n assert(L1Bridge.OTHER_BRIDGE() == L2Bridge);\n assert(L1Bridge.messenger() == L1Messenger);\n assert(L1Bridge.MESSENGER() == L1Messenger);\n assertEq(L1Bridge.version(), \"1.1.0\");\n }\n}\n\ncontract L1StandardBridge_Initialize_Test is Bridge_Initializer {\n function test_initialize_succeeds() external {\n assertEq(address(L1Bridge.messenger()), address(L1Messenger));\n\n assertEq(address(L1Bridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE);\n\n assertEq(address(L2Bridge), Predeploys.L2_STANDARD_BRIDGE);\n }\n}\n\ncontract L1StandardBridge_Initialize_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_Receive_Test is Bridge_Initializer {\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(op).balance, 0);\n\n // The legacy event must be emitted for backwards compatibility\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 100,\n hex\"\"\n ),\n 200_000\n )\n );\n\n vm.prank(alice, alice);\n (bool success, ) = address(L1Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(op).balance, 100);\n }\n}\n\ncontract L1StandardBridge_Receive_TestFail {}\n\ncontract PreBridgeETH is Bridge_Initializer {\n function _preBridgeETH(bool isLegacy) internal {\n assertEq(address(op).balance, 0);\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 500,\n hex\"dead\"\n );\n\n if (isLegacy) {\n vm.expectCall(\n address(L1Bridge),\n 500,\n abi.encodeWithSelector(L1Bridge.depositETH.selector, 50000, hex\"dead\")\n );\n } else {\n vm.expectCall(\n address(L1Bridge),\n 500,\n abi.encodeWithSelector(L1Bridge.bridgeETH.selector, 50000, hex\"dead\")\n );\n }\n vm.expectCall(\n address(L1Messenger),\n 500,\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 50000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 500,\n 50000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 50000);\n vm.expectCall(\n address(op),\n 500,\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 500,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(500),\n uint256(500),\n baseGas,\n false,\n innerMessage\n );\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, alice, 500, hex\"dead\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, alice, 500, hex\"dead\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 50000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 500);\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L1StandardBridge_DepositETH_Test is PreBridgeETH {\n // depositETH\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_depositETH_succeeds() external {\n _preBridgeETH({ isLegacy: true });\n L1Bridge.depositETH{ value: 500 }(50000, hex\"dead\");\n assertEq(address(op).balance, 500);\n }\n}\n\ncontract L1StandardBridge_BridgeETH_Test is PreBridgeETH {\n // BridgeETH\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_bridgeETH_succeeds() external {\n _preBridgeETH({ isLegacy: false });\n L1Bridge.bridgeETH{ value: 500 }(50000, hex\"dead\");\n assertEq(address(op).balance, 500);\n }\n}\n\ncontract L1StandardBridge_DepositETH_TestFail is Bridge_Initializer {\n function test_depositETH_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, address(L1Token).code);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice);\n L1Bridge.depositETH{ value: 1 }(300, hex\"\");\n }\n}\n\ncontract PreBridgeETHTo is Bridge_Initializer {\n function _preBridgeETHTo(bool isLegacy) internal {\n assertEq(address(op).balance, 0);\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n if (isLegacy) {\n vm.expectCall(\n address(L1Bridge),\n 600,\n abi.encodeWithSelector(L1Bridge.depositETHTo.selector, bob, 60000, hex\"dead\")\n );\n } else {\n vm.expectCall(\n address(L1Bridge),\n 600,\n abi.encodeWithSelector(L1Bridge.bridgeETHTo.selector, bob, 60000, hex\"dead\")\n );\n }\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n bob,\n 600,\n hex\"dead\"\n );\n\n // the L1 bridge should call\n // L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 60000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 600,\n 60000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 60000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 600,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(600),\n uint256(600),\n baseGas,\n false,\n innerMessage\n );\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, bob, 600, hex\"dead\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, bob, 600, hex\"dead\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 60000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 600);\n\n // deposit eth to bob\n vm.prank(alice, alice);\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_Test is PreBridgeETHTo {\n // depositETHTo\n // - emits ETHDepositInitiated\n // - calls optimismPortal.depositTransaction\n // - EOA or contract can call\n // - ETH ends up in the optimismPortal\n function test_depositETHTo_succeeds() external {\n _preBridgeETHTo({ isLegacy: true });\n L1Bridge.depositETHTo{ value: 600 }(bob, 60000, hex\"dead\");\n assertEq(address(op).balance, 600);\n }\n}\n\ncontract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo {\n // BridgeETHTo\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_bridgeETHTo_succeeds() external {\n _preBridgeETHTo({ isLegacy: false });\n L1Bridge.bridgeETHTo{ value: 600 }(bob, 60000, hex\"dead\");\n assertEq(address(op).balance, 600);\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_DepositERC20_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // depositERC20\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - only callable by EOA\n function test_depositERC20_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n // Deal Alice's ERC20 State\n deal(address(L1Token), alice, 100000, true);\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n // The L1Bridge should transfer alice's tokens to itself\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 100)\n );\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L2Token),\n address(L1Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n // the L1 bridge should call L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 10000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 0,\n 10000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 10000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 0,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(0),\n uint256(0),\n baseGas,\n false,\n innerMessage\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 0);\n\n vm.prank(alice);\n L1Bridge.depositERC20(address(L1Token), address(L2Token), 100, 10000, hex\"\");\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n }\n}\n\ncontract L1StandardBridge_DepositERC20_TestFail is Bridge_Initializer {\n function test_depositERC20_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, hex\"ffff\");\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice, alice);\n L1Bridge.depositERC20(address(0), address(0), 100, 100, hex\"\");\n }\n}\n\ncontract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer {\n // depositERC20To\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - callable by a contract\n function test_depositERC20To_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L2Token),\n address(L1Token),\n alice,\n bob,\n 1000,\n hex\"\"\n );\n\n // the L1 bridge should call L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 10000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 0,\n 10000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 10000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 0,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(0),\n uint256(0),\n baseGas,\n false,\n innerMessage\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex\"\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 0);\n\n deal(address(L1Token), alice, 100000, true);\n\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 1000)\n );\n\n vm.prank(alice);\n L1Bridge.depositERC20To(address(L1Token), address(L2Token), bob, 1000, 10000, hex\"\");\n\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 1000);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeETHWithdrawal\n // - emits ETHWithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeETHWithdrawal_succeeds() external {\n uint256 aliceBalance = alice.balance;\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHWithdrawalFinalized(alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n vm.expectCall(alice, hex\"\");\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n // ensure that the messenger has ETH to call with\n vm.deal(address(L1Bridge.messenger()), 100);\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n\n assertEq(address(L1Bridge.messenger()).balance, 0);\n assertEq(aliceBalance + 100, alice.balance);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeERC20Withdrawal\n // - updates bridge.deposits\n // - emits ERC20WithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeERC20Withdrawal_succeeds() external {\n deal(address(L1Token), address(L1Bridge), 100, true);\n\n uint256 slot = stdstore\n .target(address(L1Bridge))\n .sig(\"deposits(address,address)\")\n .with_key(address(L1Token))\n .with_key(address(L2Token))\n .find();\n\n // Give the L1 bridge some ERC20 tokens\n vm.store(address(L1Bridge), bytes32(slot), bytes32(uint256(100)));\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20WithdrawalFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transfer.selector, alice, 100)\n );\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n assertEq(L1Token.balanceOf(address(L1Bridge)), 0);\n assertEq(L1Token.balanceOf(address(alice)), 100);\n }\n}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer {\n function test_finalizeERC20Withdrawal_notMessenger_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(28));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n\n function test_finalizeERC20Withdrawal_notOtherBridge_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(address(0)))\n );\n vm.prank(address(L1Bridge.messenger()));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n}\n\ncontract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {\n function test_finalizeBridgeETH_succeeds() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n\ncontract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer {\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L1Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L1Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, ConfigurableCaller } from \"./CommonTest.t.sol\";\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L2Messenger.messageNonce());\n assertEq(version, L2Messenger.MESSAGE_VERSION());\n }\n\n function test_sendMessage_succeeds() external {\n bytes memory xDomainCallData = Encoding.encodeCrossDomainMessage(\n L2Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n );\n vm.expectCall(\n address(messagePasser),\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData\n )\n );\n\n // MessagePassed event\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(L2Messenger),\n address(L1Messenger),\n 0,\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData,\n Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messagePasser.messageNonce(),\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: L2Messenger.baseGas(hex\"ff\", 100),\n data: xDomainCallData\n })\n )\n );\n\n vm.prank(alice);\n L2Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L2Messenger.messageNonce();\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L2Messenger.messageNonce());\n }\n\n function test_xDomainSender_senderNotSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 2), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n vm.expectCall(target, hex\"1111\");\n\n vm.prank(caller);\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L2Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L2Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n address target = address(messagePasser);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n bytes memory message = hex\"1111\";\n\n vm.prank(caller);\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retry_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n uint256 value = 100;\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(caller), value);\n vm.prank(caller);\n L2Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L2Messenger.successfulMessages(hash), false);\n assertEq(L2Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L2Messenger.successfulMessages(hash), true);\n assertEq(L2Messenger.failedMessages(hash), true);\n }\n\n // relayMessage: Should revert if the recipient is trying to reenter with the\n // same message.\n function test_relayMessage_reentrancySameMessage_reverts() external {\n ConfigurableCaller caller = new ConfigurableCaller();\n address target = address(caller);\n address sender = address(L1Messenger);\n address l1XDMAlias = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n bytes memory callMessage = abi.encodeWithSelector(caller.call.selector);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Act as the L1XDM and call the `relayMessage` function with the `innerMessage`.\n vm.prank(l1XDMAlias);\n vm.expectCall(target, callMessage);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Assert that the message failed to be relayed\n assertFalse(L2Messenger.successfulMessages(hash));\n assertTrue(L2Messenger.failedMessages(hash));\n\n // Set the configurable caller's target to `L2Messenger` and set the payload to `relayMessage(...)`.\n caller.setDoRevert(false);\n caller.setTarget(address(L2Messenger));\n caller.setPayload(\n abi.encodeWithSelector(\n L2Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n callMessage\n )\n );\n\n // Attempt to replay the failed message, which will *not* immediately revert this time around,\n // but attempt to reenter `relayMessage` with the same message hash. The reentrancy attempt should\n // revert.\n vm.expectEmit(true, true, true, true, target);\n emit WhatHappened(\n false,\n abi.encodeWithSignature(\"Error(string)\", \"ReentrancyGuard: reentrant call\")\n );\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Assert that the message still failed to be relayed.\n assertFalse(L2Messenger.successfulMessages(hash));\n assertTrue(L2Messenger.failedMessages(hash));\n }\n\n // relayMessage: should not revert if the recipient reenters `relayMessage` with a different\n // message hash.\n function test_relayMessage_reentrancyDiffMessage_succeeds() external {\n ConfigurableCaller caller = new ConfigurableCaller();\n address target = address(caller);\n address sender = address(L1Messenger);\n address l1XDMAlias = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory messageA = abi.encodeWithSelector(caller.call.selector);\n bytes memory messageB = hex\"\";\n\n bytes32 hashA = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n bytes32 hashB = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageB\n );\n\n // Act as the L1XDM and call the `relayMessage` function with both `messageA` and `messageB`.\n vm.startPrank(l1XDMAlias);\n\n vm.expectCall(target, messageA);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n vm.expectCall(target, messageB);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageB\n );\n\n // Stop acting as the L1XDM\n vm.stopPrank();\n\n // Assert that both messages failed to be relayed\n assertFalse(L2Messenger.successfulMessages(hashA));\n assertFalse(L2Messenger.successfulMessages(hashB));\n assertTrue(L2Messenger.failedMessages(hashA));\n assertTrue(L2Messenger.failedMessages(hashB));\n\n // Set the configurable caller's target to `L2Messenger` and set the payload to `relayMessage(...)`.\n caller.setDoRevert(false);\n caller.setTarget(address(L2Messenger));\n caller.setPayload(\n abi.encodeWithSelector(\n L2Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageB\n )\n );\n\n // Attempt to replay the failed message, which will *not* immediately revert this time around,\n // but attempt to reenter `relayMessage` with messageB. The reentrancy attempt should succeed\n // because the message hashes are different.\n vm.expectEmit(true, true, true, true, target);\n emit WhatHappened(true, hex\"\");\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n\n // Assert that both messages are now in the `successfulMessages` mapping.\n assertTrue(L2Messenger.successfulMessages(hashA));\n assertTrue(L2Messenger.successfulMessages(hashB));\n }\n}\n" - }, - "contracts/test/L2ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.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\ncontract TestMintableERC721 is OptimismMintableERC721 {\n constructor(address _bridge, address _remoteToken)\n OptimismMintableERC721(_bridge, 1, _remoteToken, \"Test\", \"TST\")\n {}\n\n function mint(address to, uint256 tokenId) public {\n _mint(to, tokenId);\n }\n}\n\ncontract L2ERC721Bridge_Test is Messenger_Initializer {\n TestMintableERC721 internal localToken;\n TestERC721 internal remoteToken;\n L2ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L2ERC721Bridge(address(L2Messenger), otherBridge);\n remoteToken = new TestERC721();\n localToken = new TestMintableERC721(address(bridge), address(remoteToken));\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L2ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L2Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L2Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L2ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"L2ERC721Bridge: Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L1ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L2ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"L2ERC721Bridge: Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_interfaceNotCompliant_reverts() external {\n // Create a non-compliant token\n NonCompliantERC721 nonCompliantToken = new NonCompliantERC721(alice);\n\n // Bridge the non-compliant token.\n vm.prank(alice);\n bridge.bridgeERC721(address(nonCompliantToken), address(0x01), tokenId, 1234, hex\"5678\");\n\n // Attempt to finalize the withdrawal. Should revert because the token does not claim\n // to be compliant with the `IOptimismMintableERC721` interface.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"L2ERC721Bridge: local token interface is not compliant\");\n bridge.finalizeBridgeERC721(\n address(address(nonCompliantToken)),\n address(address(0x01)),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"L2ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_alreadyExists_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721: token already minted\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n\n/**\n * @dev A non-compliant ERC721 token that does not implement the full ERC721 interface.\n *\n * This is used to test that the bridge will revert if the token does not claim to support\n * the ERC721 interface.\n */\ncontract NonCompliantERC721 {\n address internal immutable owner;\n\n constructor(address _owner) {\n owner = _owner;\n }\n\n function ownerOf(uint256) external view returns (address) {\n return owner;\n }\n\n function remoteToken() external pure returns (address) {\n return address(0x01);\n }\n\n function burn(address, uint256) external {\n // Do nothing.\n }\n\n function supportsInterface(bytes4) external pure returns (bool) {\n return false;\n }\n}\n" - }, - "contracts/test/L2OutputOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { L2OutputOracle_Initializer, NextImpl } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2OutputOracleTest is L2OutputOracle_Initializer {\n bytes32 proposedOutput1 = keccak256(abi.encode(1));\n\n function test_constructor_succeeds() external {\n assertEq(oracle.PROPOSER(), proposer);\n assertEq(oracle.CHALLENGER(), owner);\n assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval);\n assertEq(oracle.latestBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingTimestamp(), startingTimestamp);\n }\n\n function test_constructor_badTimestamp_reverts() external {\n vm.expectRevert(\"L2OutputOracle: starting L2 timestamp must be less than current time\");\n\n // startingTimestamp is in the future\n new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp + 1,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n function test_constructor_l2BlockTimeZero_reverts() external {\n vm.expectRevert(\"L2OutputOracle: L2 block time must be greater than 0\");\n new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: 0,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n function testFuzz_constructor_submissionIntervalLteL2BlockTime_reverts(\n uint256 _submissionInterval,\n uint256 _l2BlockTime\n ) external {\n // Bound the _l2blockTime to be in the range of [1, type(uint256).max]\n _l2BlockTime = bound(_l2BlockTime, 1, type(uint256).max);\n // Roll the block number to _l2blockTime (the starting L2 timestamp must be less than or equal to the current time)\n vm.roll(_l2BlockTime);\n // Bound _submissionInterval to be less than or equal to _l2BlockTime\n _submissionInterval = bound(_submissionInterval, 0, _l2BlockTime);\n\n vm.expectRevert(\"L2OutputOracle: submission interval must be greater than L2 block time\");\n new L2OutputOracle({\n _submissionInterval: _submissionInterval,\n _l2BlockTime: _l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n /****************\n * Getter Tests *\n ****************/\n\n // Test: latestBlockNumber() should return the correct value\n function test_latestBlockNumber_succeeds() external {\n uint256 proposedNumber = oracle.nextBlockNumber();\n\n // Roll to after the block number we'll propose\n warpToProposeTime(proposedNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, proposedNumber, 0, 0);\n assertEq(oracle.latestBlockNumber(), proposedNumber);\n }\n\n // Test: getL2Output() should return the correct value\n function test_getL2Output_succeeds() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0);\n\n Types.OutputProposal memory proposal = oracle.getL2Output(nextOutputIndex);\n assertEq(proposal.outputRoot, proposedOutput1);\n assertEq(proposal.timestamp, block.timestamp);\n\n // The block number is larger than the latest proposed output:\n vm.expectRevert(stdError.indexOOBError);\n oracle.getL2Output(nextOutputIndex + 1);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is exact block\n function test_getL2OutputIndexAfter_sameBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with exact same block as proposed returns the proposal.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is previous block\n function test_getL2OutputIndexAfter_previousBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with previous block returns the proposal too.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 - 1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value during binary search\n function test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n bytes32 output2 = keccak256(abi.encode(2));\n uint256 nextBlockNumber2 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber2);\n vm.prank(proposer);\n oracle.proposeL2Output(output2, nextBlockNumber2, 0, 0);\n\n bytes32 output3 = keccak256(abi.encode(3));\n uint256 nextBlockNumber3 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber3);\n vm.prank(proposer);\n oracle.proposeL2Output(output3, nextBlockNumber3, 0, 0);\n\n bytes32 output4 = keccak256(abi.encode(4));\n uint256 nextBlockNumber4 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber4);\n vm.prank(proposer);\n oracle.proposeL2Output(output4, nextBlockNumber4, 0, 0);\n\n // Querying with a block number between the first and second proposal\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 + 1);\n assertEq(index1, 1);\n\n // Querying with a block number between the second and third proposal\n uint256 index2 = oracle.getL2OutputIndexAfter(nextBlockNumber2 + 1);\n assertEq(index2, 2);\n\n // Querying with a block number between the third and fourth proposal\n uint256 index3 = oracle.getL2OutputIndexAfter(nextBlockNumber3 + 1);\n assertEq(index3, 3);\n }\n\n // Test: getL2OutputIndexAfter() reverts when no output exists yet\n function test_getL2OutputIndexAfter_noOutputsExis_reverts() external {\n vm.expectRevert(\"L2OutputOracle: cannot get output as no outputs have been proposed yet\");\n oracle.getL2OutputIndexAfter(0);\n }\n\n // Test: nextBlockNumber() should return the correct value\n function test_nextBlockNumber_succeeds() external {\n assertEq(\n oracle.nextBlockNumber(),\n // The return value should match this arithmetic\n oracle.latestBlockNumber() + oracle.SUBMISSION_INTERVAL()\n );\n }\n\n function test_computeL2Timestamp_succeeds() external {\n // reverts if timestamp is too low\n vm.expectRevert(stdError.arithmeticError);\n oracle.computeL2Timestamp(startingBlockNumber - 1);\n\n // returns the correct value...\n // ... for the very first block\n assertEq(oracle.computeL2Timestamp(startingBlockNumber), startingTimestamp);\n\n // ... for the first block after the starting block\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 1),\n startingTimestamp + l2BlockTime\n );\n\n // ... for some other block number\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 96024),\n startingTimestamp + l2BlockTime * 96024\n );\n }\n\n /*****************************\n * Propose Tests - Happy Path *\n *****************************/\n\n // Test: proposeL2Output succeeds when given valid input, and no block hash and number are\n // specified.\n function test_proposeL2Output_proposeAnotherOutput_succeeds() public {\n bytes32 proposedOutput2 = keccak256(abi.encode());\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n uint256 proposedNumber = oracle.latestBlockNumber();\n\n // Ensure the submissionInterval is enforced\n assertEq(nextBlockNumber, proposedNumber + submissionInterval);\n\n vm.roll(nextBlockNumber + 1);\n\n vm.expectEmit(true, true, true, true);\n emit OutputProposed(proposedOutput2, nextOutputIndex, nextBlockNumber, block.timestamp);\n\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output succeeds when given valid input, and when a block hash and number are\n // specified for reorg protection.\n function test_proposeWithBlockhashAndHeight_succeeds() external {\n // Get the number and hash of a previous block in the chain\n uint256 prevL1BlockNumber = block.number - 1;\n bytes32 prevL1BlockHash = blockhash(prevL1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber);\n }\n\n /***************************\n * Propose Tests - Sad Path *\n ***************************/\n\n // Test: proposeL2Output fails if called by a party that is not the proposer.\n function test_proposeL2Output_notProposer_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n\n vm.prank(address(128));\n vm.expectRevert(\"L2OutputOracle: only the proposer address can propose new outputs\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails given a zero blockhash.\n function test_proposeL2Output_emptyOutput_reverts() external {\n bytes32 outputToPropose = bytes32(0);\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: L2 output proposal cannot be the zero hash\");\n oracle.proposeL2Output(outputToPropose, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if the block number doesn't match the next expected number.\n function test_proposeL2Output_unexpectedBlockNumber_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: block number must be equal to next expected block number\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0);\n }\n\n // Test: proposeL2Output fails if it would have a timestamp in the future.\n function test_proposeL2Output_futureTimetamp_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextTimestamp = oracle.computeL2Timestamp(nextBlockNumber);\n vm.warp(nextTimestamp);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: cannot propose L2 output in the future\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if a non-existent L1 block hash and number are provided for reorg\n // protection.\n function test_proposeL2Output_wrongFork_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(\n nonZeroHash,\n nextBlockNumber,\n bytes32(uint256(0x01)),\n block.number - 1\n );\n }\n\n // Test: proposeL2Output fails when given valid input, but the block hash and number do not\n // match.\n function test_proposeL2Output_unmatchedBlockhash_reverts() external {\n // Move ahead to block 100 so that we can reference historical blocks\n vm.roll(100);\n\n // Get the number and hash of a previous block in the chain\n uint256 l1BlockNumber = block.number - 1;\n bytes32 l1BlockHash = blockhash(l1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n\n // This will fail when foundry no longer returns zerod block hashes\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1);\n }\n\n /*****************************\n * Delete Tests - Happy Path *\n *****************************/\n\n function test_deleteOutputs_singleOutput_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 1);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex);\n oracle.deleteL2Outputs(latestOutputIndex);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n function test_deleteOutputs_multipleOutputs_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 3);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex - 2);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval * 3, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n /***************************\n * Delete Tests - Sad Path *\n ***************************/\n\n function test_deleteL2Outputs_ifNotChallenger_reverts() external {\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.expectRevert(\"L2OutputOracle: only the challenger address can delete outputs\");\n oracle.deleteL2Outputs(latestBlockNumber);\n }\n\n function test_deleteL2Outputs_nonExistent_reverts() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestBlockNumber + 1);\n }\n\n function test_deleteL2Outputs_afterLatest_reverts() external {\n // Start by proposing three outputs\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n // Delete the latest two outputs\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n vm.prank(owner);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // Now try to delete the same output again\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n }\n\n function test_deleteL2Outputs_finalized_reverts() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n // Warp past the finalization period + 1 second\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n\n // Try to delete a finalized output\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs that have already been finalized\");\n oracle.deleteL2Outputs(latestOutputIndex);\n }\n}\n\ncontract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {\n Proxy internal proxy;\n\n function setUp() public override {\n super.setUp();\n proxy = Proxy(payable(address(oracle)));\n }\n\n function test_initValuesOnProxy_succeeds() external {\n assertEq(submissionInterval, oracleImpl.SUBMISSION_INTERVAL());\n assertEq(l2BlockTime, oracleImpl.L2_BLOCK_TIME());\n assertEq(startingBlockNumber, oracleImpl.startingBlockNumber());\n assertEq(startingTimestamp, oracleImpl.startingTimestamp());\n\n assertEq(proposer, oracleImpl.PROPOSER());\n assertEq(owner, oracleImpl.CHALLENGER());\n }\n\n function test_initializeProxy_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(payable(proxy)).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_initializeImpl_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(oracleImpl).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(oracle), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(oracle), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(oracle)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n" - }, - "contracts/test/L2StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { console } from \"forge-std/console.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\ncontract L2StandardBridge_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n function test_initialize_succeeds() external {\n assertEq(address(L2Bridge.messenger()), address(L2Messenger));\n assertEq(L1Bridge.l2TokenBridge(), address(L2Bridge));\n assertEq(address(L2Bridge.OTHER_BRIDGE()), address(L1Bridge));\n }\n\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(messagePasser).balance, 0);\n uint256 nonce = L2Messenger.messageNonce();\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 200_000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 100,\n 200_000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 100,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalInitiated(address(0), Predeploys.LEGACY_ERC20_ETH, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n // L2ToL1MessagePasser will emit a MessagePassed event\n vm.expectEmit(true, true, true, true, address(messagePasser));\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 100,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 200_000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessageExtension1(address(L2Bridge), 100);\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 200_000 // StandardBridge's RECEIVE_DEFAULT_GAS_LIMIT\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n vm.prank(alice, alice);\n (bool success, ) = address(L2Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(messagePasser).balance, 100);\n }\n\n // withrdraw\n // - requires amount == msg.value\n function test_withdraw_insufficientValue_reverts() external {\n assertEq(address(messagePasser).balance, 0);\n\n vm.expectRevert(\"StandardBridge: bridging ETH must include sufficient ETH value\");\n vm.prank(alice, alice);\n L2Bridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 100, 1000, hex\"\");\n }\n\n /**\n * @notice Use the legacy `withdraw` interface on the L2StandardBridge to\n * withdraw ether from L2 to L1.\n */\n function test_withdraw_ether_succeeds() external {\n assertTrue(alice.balance >= 100);\n assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 0);\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit WithdrawalInitiated({\n l1Token: address(0),\n l2Token: Predeploys.LEGACY_ERC20_ETH,\n from: alice,\n to: alice,\n amount: 100,\n data: hex\"\"\n });\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ETHBridgeInitiated({ from: alice, to: alice, amount: 100, data: hex\"\" });\n\n vm.prank(alice, alice);\n L2Bridge.withdraw{ value: 100 }({\n _l2Token: Predeploys.LEGACY_ERC20_ETH,\n _amount: 100,\n _minGasLimit: 1000,\n _extraData: hex\"\"\n });\n\n assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 100);\n }\n}\n\ncontract PreBridgeERC20 is Bridge_Initializer {\n // withdraw and BridgeERC20 should behave the same when transferring ERC20 tokens\n // so they should share the same setup and expectEmit calls\n function _preBridgeERC20(bool _isLegacy, address _l2Token) internal {\n // Alice has 100 L2Token\n deal(_l2Token, alice, 100, true);\n assertEq(ERC20(_l2Token).balanceOf(alice), 100);\n uint256 nonce = L2Messenger.messageNonce();\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L1Token),\n _l2Token,\n alice,\n alice,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 1000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 0,\n 1000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n if (_isLegacy) {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(L2Bridge.withdraw.selector, _l2Token, 100, 1000, hex\"\")\n );\n } else {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.bridgeERC20.selector,\n _l2Token,\n address(L1Token),\n 100,\n 1000,\n hex\"\"\n )\n );\n }\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 1000\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n // The L2Bridge should burn the tokens\n vm.expectCall(\n _l2Token,\n abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalInitiated(address(L1Token), _l2Token, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 0,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true);\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true);\n emit SentMessageExtension1(address(L2Bridge), 0);\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {\n // withdraw\n // - token is burned\n // - emits WithdrawalInitiated\n // - calls Withdrawer.initiateWithdrawal\n function test_withdraw_withdrawingERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: true, _l2Token: address(L2Token) });\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n // BridgeERC20\n // - token is burned\n // - emits WithdrawalInitiated\n // - calls Withdrawer.initiateWithdrawal\n function test_bridgeERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: false, _l2Token: address(L2Token) });\n L2Bridge.bridgeERC20(address(L2Token), address(L1Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_withdrawLegacyERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: true, _l2Token: address(LegacyL2Token) });\n L2Bridge.withdraw(address(LegacyL2Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_bridgeLegacyERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: false, _l2Token: address(LegacyL2Token) });\n L2Bridge.bridgeERC20(address(LegacyL2Token), address(L1Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_withdraw_notEOA_reverts() external {\n // This contract has 100 L2Token\n deal(address(L2Token), address(this), 100, true);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n }\n}\n\ncontract PreBridgeERC20To is Bridge_Initializer {\n // withdrawTo and BridgeERC20To should behave the same when transferring ERC20 tokens\n // so they should share the same setup and expectEmit calls\n function _preBridgeERC20To(bool _isLegacy, address _l2Token) internal {\n deal(_l2Token, alice, 100, true);\n assertEq(ERC20(L2Token).balanceOf(alice), 100);\n uint256 nonce = L2Messenger.messageNonce();\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L1Token),\n _l2Token,\n alice,\n bob,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 1000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 0,\n 1000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit WithdrawalInitiated(address(L1Token), _l2Token, alice, bob, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, bob, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(messagePasser));\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 0,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessageExtension1(address(L2Bridge), 0);\n\n if (_isLegacy) {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.withdrawTo.selector,\n _l2Token,\n bob,\n 100,\n 1000,\n hex\"\"\n )\n );\n } else {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.bridgeERC20To.selector,\n _l2Token,\n address(L1Token),\n bob,\n 100,\n 1000,\n hex\"\"\n )\n );\n }\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 1000\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n // The L2Bridge should burn the tokens\n vm.expectCall(\n address(L2Token),\n abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)\n );\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To {\n // withdrawTo\n // - token is burned\n // - emits WithdrawalInitiated w/ correct recipient\n // - calls Withdrawer.initiateWithdrawal\n function test_withdrawTo_withdrawingERC20_succeeds() external {\n _preBridgeERC20To({ _isLegacy: true, _l2Token: address(L2Token) });\n L2Bridge.withdrawTo(address(L2Token), bob, 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n // bridgeERC20To\n // - token is burned\n // - emits WithdrawalInitiated w/ correct recipient\n // - calls Withdrawer.initiateWithdrawal\n function test_bridgeERC20To_succeeds() external {\n _preBridgeERC20To({ _isLegacy: false, _l2Token: address(L2Token) });\n L2Bridge.bridgeERC20To(address(L2Token), address(L1Token), bob, 100, 1000, hex\"\");\n assertEq(L2Token.balanceOf(alice), 0);\n }\n}\n\ncontract L2StandardBridge_Bridge_Test is Bridge_Initializer {\n // finalizeDeposit\n // - only callable by l1TokenBridge\n // - supported token pair emits DepositFinalized\n // - invalid deposit calls Withdrawer.initiateWithdrawal\n function test_finalizeDeposit_depositingERC20_succeeds() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n\n vm.expectCall(\n address(L2Token),\n abi.encodeWithSelector(OptimismMintableERC20.mint.selector, alice, 100)\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeFinalized(address(L2Token), address(L1Token), alice, alice, 100, hex\"\");\n\n vm.prank(address(L2Messenger));\n L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n }\n\n function test_finalizeDeposit_depositingETH_succeeds() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeFinalized(\n address(L2Token), // localToken\n address(L1Token), // remoteToken\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n vm.prank(address(L2Messenger));\n L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L2Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Messenger), 100, hex\"\");\n }\n}\n\ncontract L2StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {\n function test_finalizeBridgeETH_succeeds() external {\n address messenger = address(L2Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n\n vm.expectEmit(true, true, true, true);\n emit DepositFinalized(address(0), Predeploys.LEGACY_ERC20_ETH, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2ToL1MessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\n\ncontract L2ToL1MessagePasserTest is CommonTest {\n L2ToL1MessagePasser messagePasser;\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n function setUp() public virtual override {\n super.setUp();\n messagePasser = new L2ToL1MessagePasser();\n }\n\n function testFuzz_initiateWithdrawal_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint256 nonce = messagePasser.messageNonce();\n\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: _value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, _sender, _target, _value, _gasLimit, _data, withdrawalHash);\n\n vm.deal(_sender, _value);\n vm.prank(_sender);\n messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);\n\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n\n bytes32 slot = keccak256(bytes.concat(withdrawalHash, bytes32(0)));\n\n assertEq(vm.load(address(messagePasser), slot), bytes32(uint256(1)));\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by a contract\n function test_initiateWithdrawal_fromContract_succeeds() external {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\"\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\",\n withdrawalHash\n );\n\n vm.deal(address(this), 2**64);\n messagePasser.initiateWithdrawal{ value: 100 }(address(4), 64000, hex\"\");\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by an EOA\n function test_initiateWithdrawal_fromEOA_succeeds() external {\n uint256 gasLimit = 64000;\n address target = address(4);\n uint256 value = 100;\n bytes memory data = hex\"ff\";\n uint256 nonce = messagePasser.messageNonce();\n\n // EOA emulation\n vm.prank(alice, alice);\n vm.deal(alice, 2**64);\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(nonce, alice, target, value, gasLimit, data)\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, alice, target, value, gasLimit, data, withdrawalHash);\n\n messagePasser.initiateWithdrawal{ value: value }(target, gasLimit, data);\n\n // the sent messages mapping is filled\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n // the nonce increments\n assertEq(nonce + 1, messagePasser.messageNonce());\n }\n\n // Test: burn should destroy the ETH held in the contract\n function test_burn_succeeds() external {\n messagePasser.initiateWithdrawal{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n NON_ZERO_GASLIMIT,\n NON_ZERO_DATA\n );\n\n assertEq(address(messagePasser).balance, NON_ZERO_VALUE);\n vm.expectEmit(true, false, false, false);\n emit WithdrawerBalanceBurnt(NON_ZERO_VALUE);\n messagePasser.burn();\n\n // The Withdrawer should have no balance\n assertEq(address(messagePasser).balance, 0);\n }\n}\n" - }, - "contracts/test/LegacyERC20ETH.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyERC20ETH_Test is CommonTest {\n LegacyERC20ETH eth;\n\n function setUp() public virtual override {\n super.setUp();\n eth = new LegacyERC20ETH();\n }\n\n function test_metadata_succeeds() external {\n assertEq(eth.name(), \"Ether\");\n assertEq(eth.symbol(), \"ETH\");\n assertEq(eth.decimals(), 18);\n }\n\n function test_crossDomain_succeeds() external {\n assertEq(eth.l2Bridge(), Predeploys.L2_STANDARD_BRIDGE);\n assertEq(eth.l1Token(), address(0));\n }\n\n function test_transfer_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transfer is disabled\");\n eth.transfer(alice, 100);\n }\n\n function test_approve_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: approve is disabled\");\n eth.approve(alice, 100);\n }\n\n function test_transferFrom_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transferFrom is disabled\");\n eth.transferFrom(bob, alice, 100);\n }\n\n function test_increaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n eth.increaseAllowance(alice, 100);\n }\n\n function test_decreaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n eth.decreaseAllowance(alice, 100);\n }\n\n function test_mint_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: mint is disabled\");\n eth.mint(alice, 100);\n }\n\n function test_burn_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: burn is disabled\");\n eth.burn(alice, 100);\n }\n}\n" - }, - "contracts/test/LegacyMessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyMessagePasser } from \"../legacy/LegacyMessagePasser.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyMessagePasser_Test is CommonTest {\n LegacyMessagePasser messagePasser;\n\n function setUp() public virtual override {\n super.setUp();\n messagePasser = new LegacyMessagePasser();\n }\n\n function test_passMessageToL1_succeeds() external {\n vm.prank(alice);\n messagePasser.passMessageToL1(hex\"ff\");\n assert(messagePasser.sentMessages(keccak256(abi.encodePacked(hex\"ff\", alice))));\n }\n}\n" - }, - "contracts/test/MerkleTrie.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MerkleTrie } from \"../libraries/trie/MerkleTrie.sol\";\n\ncontract MerkleTrie_get_Test is CommonTest {\n function test_get_validProof1_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579326262\";\n bytes memory val = hex\"6176616c32\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof2_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[\n 2\n ] = hex\"ef83206161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof3_succeeds() external {\n bytes32 root = 0xf838216fa749aefa91e0b672a9c06d3e6e983f913d7107b5dab4af60b5f5abed;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"f387206b6579316161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof4_succeeds() external {\n bytes32 root = 0x37956bab6bba472308146808d5311ac19cb4a7daae5df7efcc0f32badc97f55e;\n bytes memory key = hex\"6b6579316161\";\n bytes memory val = hex\"3031323334\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"ce87206b6579316161853031323334\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof5_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657931\";\n bytes\n memory val = hex\"30313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f862808080808080a057895fdbd71e2c67c2f9274a56811ff5cf458720a7fa713a135e3890f8cafcf8808080808080808080b130313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof6_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657932\";\n bytes memory val = hex\"73686f7274\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[2] = hex\"df808080808080c9823262856176616c338080808080808080808573686f7274\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof7_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657933\";\n bytes memory val = hex\"31323334353637383930313233343536373839303132333435363738393031\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f839808080808080c9823363856176616c338080808080808080809f31323334353637383930313233343536373839303132333435363738393031\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof8_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"61\";\n bytes memory val = hex\"61\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22061\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof9_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"62\";\n bytes memory val = hex\"62\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22062\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof10_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"63\";\n bytes memory val = hex\"63\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22063\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_nonexistentKey1_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b657932\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_nonexistentKey2_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"616e7972616e646f6d6b6579\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_wrongKeyProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579316161\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e216a04892c039d654f1be9af20e88ae53e9ab5fa5520190e0fb2f805823e45ebad22f\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[2] = hex\"d687206e6f746865728d33343938683472697568677765\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_corruptedProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579326262\";\n bytes[] memory proof = new bytes[](5);\n proof[0] = hex\"2fd2ba5ee42358802ffbe0900152a55fabe953ae880ef29abef154d639c09248a016e2\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[\n 2\n ] = hex\"e583165793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 3\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[4] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidDataRemainder_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa000000000000000000000000000000\";\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidInternalNodeHash_reverts() external {\n bytes32 root = 0xa827dff1a657bb9bb9a1c3abe9db173e2f1359f15eb06f1647ea21ac7c95d8fa;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa09862c6b113008c4204c13755693cbb868acc25ebaa98db11df8c89a0c0dd3157\";\n proof[\n 1\n ] = hex\"f380808080808080808080a0de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f00c220118080808080\";\n proof[2] = hex\"de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroBranchValueLength_reverts() external {\n bytes32 root = 0xe04b3589eef96b237cd49ccb5dcf6e654a47682bfa0961d563ab843f7ad1e035;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](2);\n proof[0] = hex\"dd8200aad98080808080808080808080c43b82aabbc43c82aacc80808080\";\n proof[1] = hex\"d98080808080808080808080c43b82aabbc43c82aacc80808080\";\n\n vm.expectRevert(\"MerkleTrie: value length must be greater than zero (branch)\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroLengthKey_reverts() external {\n bytes32 root = 0x54157fd62cdf2f474e7bfec2d3cd581e807bee38488c9590cb887add98936b73;\n bytes memory key = hex\"\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"c78320f00082b443\";\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey1_reverts() external {\n bytes32 root = 0xa513ba530659356fb7588a2c831944e80fd8aedaa5a4dc36f918152be2be0605;\n bytes memory key = hex\"01\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"db10d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[1] = hex\"d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[2] = hex\"c582202381aa\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey2_reverts() external {\n bytes32 root = 0xa06abffaec4ebe8ccde595f4547b864b4421b21c1fc699973f94710c9bc17979;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa07ea462226a3dc0a46afb4ded39306d7a84d311ada3557dfc75a909fd25530905\";\n proof[\n 1\n ] = hex\"f380808080808080808080a027f11bd3af96d137b9287632f44dd00fea1ca1bd70386c30985ede8cc287476e808080c220338080\";\n proof[2] = hex\"e48200bba0a6911545ed01c2d3f4e15b8b27c7bfba97738bd5e6dd674dd07033428a4c53af\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_extraProofElements_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](4);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa\";\n proof[3] = hex\"c32081aa\";\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_validProofs_succeeds(bytes4) external {\n // Generate a test case with a valid proof of inclusion for the k/v pair in the trie.\n (bytes32 root, bytes memory key, bytes memory val, bytes[] memory proof) = ffi\n .getMerkleTrieFuzzCase(\"valid\");\n\n // Assert that our expected value is equal to our actual value.\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidRoot_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"valid\"\n );\n\n bytes32 rootHash = keccak256(abi.encodePacked(root));\n vm.expectRevert(\"MerkleTrie: invalid root hash\");\n MerkleTrie.get(key, proof, rootHash);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_extraProofElements_reverts(bytes4) external {\n // Generate an invalid test case with an extra proof element attached to an otherwise\n // valid proof of inclusion for the passed k/v.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"extra_proof_elems\"\n );\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidLargeInternalHash_reverts(bytes4) external {\n // Generate an invalid test case where a long proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_large_internal_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid large internal hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidInternalNodeHash_reverts(bytes4) external {\n // Generate an invalid test case where a small proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_internal_node_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_corruptedProof_reverts(bytes4) external {\n // Generate an invalid test case where the proof is malformed.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"corrupted_proof\"\n );\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidDataRemainder_reverts(bytes4) external {\n // Generate an invalid test case where a random element of the proof has more bytes than the\n // length designates within the RLP list encoding.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_data_remainder\"\n );\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_prefixedValidKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and a valid key that is prefixed\n // with random bytes\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"prefixed_valid_key\"\n );\n\n // Ambiguous revert check- all that we care is that it *does* fail. This case may\n // fail within different branches.\n vm.expectRevert();\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_emptyKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and an empty key\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"empty_key\"\n );\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_partialProof_reverts(bytes4) external {\n // Get a random test case with a valid trie / partially correct proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"partial_proof\"\n );\n\n vm.expectRevert(\"MerkleTrie: ran out of proof elements\");\n MerkleTrie.get(key, proof, root);\n }\n}\n" - }, - "contracts/test/MintManager.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MintManager } from \"../governance/MintManager.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract MintManager_Initializer is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n MintManager internal manager;\n\n function setUp() public virtual override {\n super.setUp();\n\n vm.prank(owner);\n gov = new GovernanceToken();\n\n vm.prank(owner);\n manager = new MintManager(owner, address(gov));\n\n vm.prank(owner);\n gov.transferOwnership(address(manager));\n }\n}\n\ncontract MintManager_constructor_Test is MintManager_Initializer {\n /**\n * @notice Tests that the constructor properly configures the contract.\n */\n function test_constructor_succeeds() external {\n assertEq(manager.owner(), owner);\n assertEq(address(manager.governanceToken()), address(gov));\n }\n}\n\ncontract MintManager_mint_Test is MintManager_Initializer {\n /**\n * @notice Tests that the mint function properly mints tokens when called by the owner.\n */\n function test_mint_fromOwner_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n /**\n * @notice Tests that the mint function reverts when called by a non-owner.\n */\n function test_mint_fromNotOwner_reverts() external {\n // Mint from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.mint(owner, 100);\n }\n\n /**\n * @notice Tests that the mint function properly mints tokens when called by the owner a second\n * time after the mint period has elapsed.\n */\n function test_mint_afterPeriodElapsed_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again after period elapsed (2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n manager.mint(owner, 2);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 102);\n }\n\n /**\n * @notice Tests that the mint function always reverts when called before the mint period has\n * elapsed, even if the caller is the owner.\n */\n function test_mint_beforePeriodElapsed_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: minting not permitted yet\");\n manager.mint(owner, 100);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n /**\n * @notice Tests that the owner cannot mint more than the mint cap.\n */\n function test_mint_moreThanCap_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again (greater than 2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint amount exceeds cap\");\n manager.mint(owner, 3);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n}\n\ncontract MintManager_upgrade_Test is MintManager_Initializer {\n /**\n * @notice Tests that the owner can upgrade the mint manager.\n */\n function test_upgrade_fromOwner_succeeds() external {\n // Upgrade to new manager.\n vm.prank(owner);\n manager.upgrade(rando);\n\n // New manager is rando.\n assertEq(gov.owner(), rando);\n }\n\n /**\n * @notice Tests that the upgrade function reverts when called by a non-owner.\n */\n function test_upgrade_fromNotOwner_reverts() external {\n // Upgrade from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.upgrade(rando);\n }\n\n /**\n * @notice Tests that the upgrade function reverts when attempting to update to the zero\n * address, even if the caller is the owner.\n */\n function test_upgrade_toZeroAddress_reverts() external {\n // Upgrade to zero address fails.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint manager cannot be the zero address\");\n manager.upgrade(address(0));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport {\n ILegacyMintableERC20,\n IOptimismMintableERC20\n} from \"../universal/IOptimismMintableERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ncontract OptimismMintableERC20_Test is Bridge_Initializer {\n event Mint(address indexed account, uint256 amount);\n event Burn(address indexed account, uint256 amount);\n\n function test_semver_succeeds() external {\n assertEq(L2Token.version(), \"1.0.0\");\n }\n\n function test_remoteToken_succeeds() external {\n assertEq(L2Token.remoteToken(), address(L1Token));\n }\n\n function test_bridge_succeeds() external {\n assertEq(L2Token.bridge(), address(L2Bridge));\n }\n\n function test_l1Token_succeeds() external {\n assertEq(L2Token.l1Token(), address(L1Token));\n }\n\n function test_l2Bridge_succeeds() external {\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_legacy_succeeds() external {\n // Getters for the remote token\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.l1Token(), address(L1Token));\n // Getters for the bridge\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_mint_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 100);\n }\n\n function test_mint_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.mint(alice, 100);\n }\n\n function test_burn_succeeds() external {\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_burn_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.burn(alice, 100);\n }\n\n function test_erc165_supportsInterface_succeeds() external {\n // The assertEq calls in this test are comparing the manual calculation of the iface,\n // with what is returned by the solidity's type().interfaceId, just to be safe.\n bytes4 iface1 = bytes4(keccak256(\"supportsInterface(bytes4)\"));\n assertEq(iface1, type(IERC165).interfaceId);\n assert(L2Token.supportsInterface(iface1));\n\n bytes4 iface2 = L2Token.l1Token.selector ^ L2Token.mint.selector ^ L2Token.burn.selector;\n assertEq(iface2, type(ILegacyMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface2));\n\n bytes4 iface3 = L2Token.remoteToken.selector ^\n L2Token.bridge.selector ^\n L2Token.mint.selector ^\n L2Token.burn.selector;\n assertEq(iface3, type(IOptimismMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface3));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\n\ncontract OptimismMintableTokenFactory_Test is Bridge_Initializer {\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n }\n\n function test_bridge_succeeds() external {\n assertEq(address(L2TokenFactory.BRIDGE()), address(L2Bridge));\n }\n\n function test_createStandardL2Token_succeeds() external {\n address remote = address(4);\n address local = LibRLP.computeAddress(address(L2TokenFactory), 2);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_sameTwice_succeeds() external {\n address remote = address(4);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n\n address local = LibRLP.computeAddress(address(L2TokenFactory), 3);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_remoteIsZero_succeeds() external {\n address remote = address(0);\n vm.expectRevert(\"OptimismMintableERC20Factory: must provide remote token address\");\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\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 { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.sol\";\n\ncontract OptimismMintableERC721_Test is ERC721Bridge_Initializer {\n ERC721 internal L1Token;\n OptimismMintableERC721 internal L2Token;\n\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n event Mint(address indexed account, uint256 tokenId);\n\n event Burn(address indexed account, uint256 tokenId);\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n L1Token = new ERC721(\"L1Token\", \"L1T\");\n L2Token = new OptimismMintableERC721(\n address(L2Bridge),\n 1,\n address(L1Token),\n \"L2Token\",\n \"L2T\"\n );\n\n // Label the addresses for nice traces.\n vm.label(address(L1Token), \"L1ERC721Token\");\n vm.label(address(L2Token), \"L2ERC721Token\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(L2Token.name(), \"L2Token\");\n assertEq(L2Token.symbol(), \"L2T\");\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.remoteChainId(), 1);\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.REMOTE_CHAIN_ID(), 1);\n assertEq(L2Token.version(), \"1.0.0\");\n }\n\n function test_safeMint_succeeds() external {\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(address(0), alice, 1);\n\n // Expect a mint event.\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 1);\n\n // Mint the token.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token should be owned by alice.\n assertEq(L2Token.ownerOf(1), alice);\n }\n\n function test_safeMint_notBridge_reverts() external {\n // Try to mint the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.safeMint(alice, 1);\n }\n\n function test_burn_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(alice, address(0), 1);\n\n // Expect a burn event.\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 1);\n\n // Burn the token.\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 1);\n\n // Token should be owned by address(0).\n vm.expectRevert(\"ERC721: invalid token ID\");\n L2Token.ownerOf(1);\n }\n\n function test_burn_notBridge_reverts() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Try to burn the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.burn(alice, 1);\n }\n\n function test_tokenURI_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token URI should be correct.\n assertEq(\n L2Token.tokenURI(1),\n string(\n abi.encodePacked(\n \"ethereum:\",\n Strings.toHexString(uint160(address(L1Token)), 20),\n \"@\",\n Strings.toString(1),\n \"/tokenURI?uint256=\",\n Strings.toString(1)\n )\n )\n );\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\n\ncontract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer {\n OptimismMintableERC721Factory internal factory;\n\n event OptimismMintableERC721Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n factory = new OptimismMintableERC721Factory(address(L2Bridge), 1);\n\n // Label the addresses for nice traces.\n vm.label(address(factory), \"OptimismMintableERC721Factory\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(factory.BRIDGE(), address(L2Bridge));\n assertEq(factory.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_succeeds() external {\n // Predict the address based on the factory address and nonce.\n address predicted = LibRLP.computeAddress(address(factory), 1);\n\n // Expect a token creation event.\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC721Created(predicted, address(1234), alice);\n\n // Create the token.\n vm.prank(alice);\n OptimismMintableERC721 created = OptimismMintableERC721(\n factory.createOptimismMintableERC721(address(1234), \"L2Token\", \"L2T\")\n );\n\n // Token address should be correct.\n assertEq(address(created), predicted);\n\n // Should be marked as created by the factory.\n assertEq(factory.isOptimismMintableERC721(address(created)), true);\n\n // Token should've been constructed correctly.\n assertEq(created.name(), \"L2Token\");\n assertEq(created.symbol(), \"L2T\");\n assertEq(created.REMOTE_TOKEN(), address(1234));\n assertEq(created.BRIDGE(), address(L2Bridge));\n assertEq(created.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_zeroRemoteToken_reverts() external {\n // Try to create a token with a zero remote token address.\n vm.expectRevert(\"OptimismMintableERC721Factory: L1 token address cannot be address(0)\");\n factory.createOptimismMintableERC721(address(0), \"L2Token\", \"L2T\");\n }\n}\n" - }, - "contracts/test/OptimismPortal.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { Portal_Initializer, CommonTest, NextImpl } from \"./CommonTest.t.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\ncontract OptimismPortal_Test is Portal_Initializer {\n event Paused(address);\n event Unpaused(address);\n\n function test_constructor_succeeds() external {\n assertEq(address(op.L2_ORACLE()), address(oracle));\n assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD);\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal can be paused by the GUARDIAN\n */\n function test_pause_succeeds() external {\n address guardian = op.GUARDIAN();\n\n assertEq(op.paused(), false);\n\n vm.expectEmit(true, true, true, true, address(op));\n emit Paused(guardian);\n\n vm.prank(guardian);\n op.pause();\n\n assertEq(op.paused(), true);\n }\n\n /**\n * @notice The OptimismPortal reverts when an account that is not the\n * GUARDIAN calls `pause()`\n */\n function test_pause_onlyGuardian_reverts() external {\n assertEq(op.paused(), false);\n\n assertTrue(op.GUARDIAN() != alice);\n vm.expectRevert(\"OptimismPortal: only guardian can pause\");\n vm.prank(alice);\n op.pause();\n\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal can be unpaused by the GUARDIAN\n */\n function test_unpause_succeeds() external {\n address guardian = op.GUARDIAN();\n\n vm.prank(guardian);\n op.pause();\n assertEq(op.paused(), true);\n\n vm.expectEmit(true, true, true, true, address(op));\n emit Unpaused(guardian);\n vm.prank(guardian);\n op.unpause();\n\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal reverts when an account that is not\n * the GUARDIAN calls `unpause()`\n */\n function test_unpause_onlyGuardian_reverts() external {\n address guardian = op.GUARDIAN();\n\n vm.prank(guardian);\n op.pause();\n assertEq(op.paused(), true);\n\n assertTrue(op.GUARDIAN() != alice);\n vm.expectRevert(\"OptimismPortal: only guardian can unpause\");\n vm.prank(alice);\n op.unpause();\n\n assertEq(op.paused(), true);\n }\n\n function test_receive_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(alice, alice, 100, 100, 100_000, false, hex\"\");\n\n // give alice money and send as an eoa\n vm.deal(alice, 2**64);\n vm.prank(alice, alice);\n (bool s, ) = address(op).call{ value: 100 }(hex\"\");\n\n assert(s);\n assertEq(address(op).balance, 100);\n }\n\n // Test: depositTransaction fails when contract creation has a non-zero destination address\n function test_depositTransaction_contractCreation_reverts() external {\n // contract creation must have a target of address(0)\n vm.expectRevert(\"OptimismPortal: must send to address(0) when creating a contract\");\n op.depositTransaction(address(1), 1, 0, true, hex\"\");\n }\n\n /**\n * @notice Prevent gasless deposits from being force processed in L2 by\n * ensuring that they have a large enough gas limit set.\n */\n function test_depositTransaction_smallGasLimit_reverts() external {\n vm.expectRevert(\"OptimismPortal: gas limit must cover instrinsic gas cost\");\n op.depositTransaction({\n _to: address(1),\n _value: 0,\n _gasLimit: 0,\n _isCreation: false,\n _data: hex\"\"\n });\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value\n function test_depositTransaction_noValueEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value\n function test_depositTransaction_noValueContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndContractContractCreation_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n function test_simple_isOutputFinalized_succeeds() external {\n uint256 ts = block.timestamp;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(bytes32(uint256(1)), uint128(ts), uint128(startingBlockNumber))\n )\n );\n\n // warp to the finalization period\n vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS());\n assertEq(op.isOutputFinalized(0), false);\n\n // warp past the finalization period\n vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n assertEq(op.isOutputFinalized(0), true);\n }\n\n function test_isOutputFinalized_succeeds() external {\n uint256 checkpoint = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n vm.roll(checkpoint);\n vm.warp(oracle.computeL2Timestamp(checkpoint) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(keccak256(abi.encode(2)), checkpoint, 0, 0);\n\n // warp to the final second of the finalization period\n uint256 finalizationHorizon = block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS();\n vm.warp(finalizationHorizon);\n // The checkpointed block should not be finalized until 1 second from now.\n assertEq(op.isOutputFinalized(nextOutputIndex), false);\n // Nor should a block after it\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n\n // warp past the finalization period\n vm.warp(finalizationHorizon + 1);\n // It should now be finalized.\n assertEq(op.isOutputFinalized(nextOutputIndex), true);\n // But not the block after it.\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n }\n}\n\ncontract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n // Utility function used in the subsequent test. This is necessary to assert that the\n // reentrant call will revert.\n function callPortalAndExpectRevert() external payable {\n vm.expectRevert(\"OptimismPortal: can only trigger one withdrawal per transaction\");\n // Arguments here don't matter, as the require check is the first thing that happens.\n // We assume that this has already been proven.\n op.finalizeWithdrawalTransaction(_defaultTx);\n // Assert that the withdrawal was not finalized.\n assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx)));\n }\n\n /**\n * @notice Proving withdrawal transactions should revert when paused\n */\n function test_proveWithdrawalTransaction_paused_reverts() external {\n vm.prank(op.GUARDIAN());\n op.pause();\n\n vm.expectRevert(\"OptimismPortal: paused\");\n op.proveWithdrawalTransaction({\n _tx: _defaultTx,\n _l2OutputIndex: _proposedOutputIndex,\n _outputRootProof: _outputRootProof,\n _withdrawalProof: _withdrawalProof\n });\n }\n\n // Test: proveWithdrawalTransaction cannot prove a withdrawal with itself (the OptimismPortal) as the target.\n function test_proveWithdrawalTransaction_onSelfCall_reverts() external {\n _defaultTx.target = address(op);\n vm.expectRevert(\"OptimismPortal: you cannot send messages to the portal contract\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the outputRootProof does not match the output root\n function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external {\n // Modify the version to invalidate the withdrawal proof.\n _outputRootProof.version = bytes32(uint256(1));\n vm.expectRevert(\"OptimismPortal: invalid output root proof\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the proof is invalid due to non-existence of\n // the withdrawal.\n function test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() external {\n // modify the default test values to invalidate the proof.\n _defaultTx.data = hex\"abcd\";\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the passed transaction's withdrawalHash has\n // already been proven.\n function test_proveWithdrawalTransaction_replayProve_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: withdrawal hash has already been proven\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has\n // already been proven AND the output root has changed AND the l2BlockNumber stays the same.\n function test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`\n // inside of the `provenWithdrawal`s mapping.\n bytes32 slot;\n assembly {\n mstore(0x00, sload(_withdrawalHash.slot))\n mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in the OptimismPortal\n slot := keccak256(0x00, 0x40)\n }\n\n // Store a different output root within the `provenWithdrawals` mapping without\n // touching the l2BlockNumber or timestamp.\n vm.store(address(op), slot, bytes32(0));\n\n // Warp ahead 1 second\n vm.warp(block.timestamp + 1);\n\n // Even though we have already proven this withdrawalHash, we should be allowed to re-submit\n // our proof with a changed outputRoot\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Ensure that the withdrawal was updated within the mapping\n (, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);\n assertEq(timestamp, block.timestamp);\n }\n\n // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has\n // already been proven AND the output root + output index + l2BlockNumber changes.\n function test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds()\n external\n {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`\n // inside of the `provenWithdrawal`s mapping.\n bytes32 slot;\n assembly {\n mstore(0x00, sload(_withdrawalHash.slot))\n mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in OptimismPortal\n slot := keccak256(0x00, 0x40)\n }\n\n // Store a dummy output root within the `provenWithdrawals` mapping without touching the\n // l2BlockNumber or timestamp.\n vm.store(address(op), slot, bytes32(0));\n\n // Fetch the output proposal at `_proposedOutputIndex` from the L2OutputOracle\n Types.OutputProposal memory proposal = op.L2_ORACLE().getL2Output(_proposedOutputIndex);\n\n // Propose the same output root again, creating the same output at a different index + l2BlockNumber.\n vm.startPrank(op.L2_ORACLE().PROPOSER());\n op.L2_ORACLE().proposeL2Output(\n proposal.outputRoot,\n op.L2_ORACLE().nextBlockNumber(),\n blockhash(block.number),\n block.number\n );\n vm.stopPrank();\n\n // Warp ahead 1 second\n vm.warp(block.timestamp + 1);\n\n // Even though we have already proven this withdrawalHash, we should be allowed to re-submit\n // our proof with a changed outputRoot + a different output index\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex + 1,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Ensure that the withdrawal was updated within the mapping\n (, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);\n assertEq(timestamp, block.timestamp);\n }\n\n // Test: proveWithdrawalTransaction succeeds and emits the WithdrawalProven event.\n function test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: finalizeWithdrawalTransaction succeeds and emits the WithdrawalFinalized event.\n function test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, false, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore + 100);\n }\n\n /**\n * @notice Finalizing withdrawal transactions should revert when paused\n */\n function test_finalizeWithdrawalTransaction_paused_reverts() external {\n vm.prank(op.GUARDIAN());\n op.pause();\n\n vm.expectRevert(\"OptimismPortal: paused\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has not been proven.\n function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectRevert(\"OptimismPortal: withdrawal has not been proven yet\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if withdrawal not proven long enough ago.\n function test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Mock a call where the resulting output root is anything but the original output root. In\n // this case we just use bytes32(uint256(1)).\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(bytes32(uint256(1)), _proposedBlockNumber)\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the provenWithdrawal's timestamp is less\n // than the L2 output oracle's starting timestamp\n function test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a startingTimestamp change on the L2 Oracle\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSignature(\"startingTimestamp()\"),\n abi.encode(block.timestamp + 1)\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output root proven is not the same as the\n // output root at the time of finalization.\n function test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock an outputRoot change on the output proposal before attempting\n // to finalize the withdrawal.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n bytes32(uint256(0)),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output proposal's timestamp has\n // not passed the finalization period.\n function test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a timestamp change on the output proposal that has not passed the\n // finalization period.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(block.timestamp + 1),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\"OptimismPortal: output proposal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction fails because the target reverts,\n // and emits the WithdrawalFinalized event with success=false.\n function test_finalizeWithdrawalTransaction_targetFails_fails() external {\n uint256 bobBalanceBefore = address(bob).balance;\n vm.etch(bob, hex\"fe\"); // Contract with just the invalid opcode.\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, false);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the finalization period has not yet passed.\n function test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() external {\n // Setup the Oracle to return an output with a recent timestamp\n uint256 recentTimestamp = block.timestamp - 1000;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(recentTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has already been finalized.\n function test_finalizeWithdrawalTransaction_onReplay_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if insufficient gas is supplied.\n function test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() external {\n // This number was identified through trial and error.\n uint256 gasLimit = 150_000;\n Types.WithdrawalTransaction memory insufficientGasTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: gasLimit,\n data: hex\"\"\n });\n\n // Get updated proof inputs.\n (bytes32 stateRoot, bytes32 storageRoot, , , bytes[] memory withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(insufficientGasTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n Hashing.hashOutputRootProof(outputRootProof),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n insufficientGasTx,\n _proposedOutputIndex,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectRevert(\"SafeCall: Not enough gas\");\n op.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if a sub-call attempts to finalize another\n // withdrawal.\n function test_finalizeWithdrawalTransaction_onReentrancy_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Copy and modify the default test values to attempt a reentrant call by first calling to\n // this contract's callPortalAndExpectRevert() function above.\n Types.WithdrawalTransaction memory _testTx = _defaultTx;\n _testTx.target = address(this);\n _testTx.data = abi.encodeWithSelector(this.callPortalAndExpectRevert.selector);\n\n // Get modified proof inputs.\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_testTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n // Setup the Oracle to return the outputRoot we want as well as a finalized timestamp.\n uint256 finalizedTimestamp = block.timestamp - oracle.FINALIZATION_PERIOD_SECONDS() - 1;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n outputRoot,\n uint128(finalizedTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(withdrawalHash, alice, address(this));\n op.proveWithdrawalTransaction(\n _testTx,\n _proposedBlockNumber,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectCall(address(this), _testTx.data);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_testTx);\n\n // Ensure that bob's balance was not changed by the reentrant call.\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n function testDiff_finalizeWithdrawalTransaction_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n // Cannot call the optimism portal\n vm.assume(_target != address(op));\n // Total ETH supply is currently about 120M ETH.\n uint256 value = bound(_value, 0, 200_000_000 ether);\n uint256 gasLimit = bound(_gasLimit, 0, 50_000_000);\n uint256 nonce = messagePasser.messageNonce();\n Types.WithdrawalTransaction memory _tx = Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: value,\n gasLimit: gasLimit,\n data: _data\n });\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_tx);\n\n Types.OutputRootProof memory proof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n\n // Ensure the values returned from ffi are correct\n assertEq(outputRoot, Hashing.hashOutputRootProof(proof));\n assertEq(withdrawalHash, Hashing.hashWithdrawal(_tx));\n\n // Mock the call to the oracle\n vm.mockCall(\n address(oracle),\n abi.encodeWithSelector(oracle.getL2Output.selector),\n abi.encode(outputRoot, 0)\n );\n\n // Start the withdrawal, it must be initiated by the _sender and the\n // correct value must be passed along\n vm.deal(_tx.sender, _tx.value);\n vm.prank(_tx.sender);\n messagePasser.initiateWithdrawal{ value: _tx.value }(_tx.target, _tx.gasLimit, _tx.data);\n\n // Ensure that the sentMessages is correct\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n op.proveWithdrawalTransaction(\n _tx,\n 100, // l2BlockNumber\n proof,\n withdrawalProof\n );\n }\n}\n\ncontract OptimismPortalUpgradeable_Test is Portal_Initializer {\n Proxy internal proxy;\n uint64 initialBlockNum;\n\n function setUp() public override {\n super.setUp();\n initialBlockNum = uint64(block.number);\n proxy = Proxy(payable(address(op)));\n }\n\n function test_params_initValuesOnProxy_succeeds() external {\n OptimismPortal p = OptimismPortal(payable(address(proxy)));\n\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = p.params();\n\n ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig();\n assertEq(prevBaseFee, rcfg.minimumBaseFee);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_initialize_cannotInitProxy_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(payable(proxy)).initialize(false);\n }\n\n function test_initialize_cannotInitImpl_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(opImpl).initialize(false);\n }\n\n function test_upgradeToAndCall_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(op), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(op), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(op)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n" - }, - "contracts/test/Proxy.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract SimpleStorage {\n mapping(uint256 => uint256) internal store;\n\n function get(uint256 key) external payable returns (uint256) {\n return store[key];\n }\n\n function set(uint256 key, uint256 value) external payable {\n store[key] = value;\n }\n}\n\ncontract Clasher {\n function upgradeTo(address) external pure {\n revert(\"upgradeTo\");\n }\n}\n\ncontract Proxy_Test is Test {\n event Upgraded(address indexed implementation);\n event AdminChanged(address previousAdmin, address newAdmin);\n\n address alice = address(64);\n\n bytes32 internal constant IMPLEMENTATION_KEY =\n bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1);\n\n bytes32 internal constant OWNER_KEY = bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1);\n\n Proxy proxy;\n SimpleStorage simpleStorage;\n\n function setUp() external {\n // Deploy a proxy and simple storage contract as\n // the implementation\n proxy = new Proxy(alice);\n simpleStorage = new SimpleStorage();\n\n vm.prank(alice);\n proxy.upgradeTo(address(simpleStorage));\n }\n\n function test_implementationKey_succeeds() external {\n // The hardcoded implementation key should be correct\n vm.prank(alice);\n proxy.upgradeTo(address(6));\n\n bytes32 key = vm.load(address(proxy), IMPLEMENTATION_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(6));\n }\n\n function test_ownerKey_succeeds() external {\n // The hardcoded owner key should be correct\n vm.prank(alice);\n proxy.changeAdmin(address(6));\n\n bytes32 key = vm.load(address(proxy), OWNER_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(address(6));\n address owner = proxy.admin();\n assertEq(owner, address(6));\n }\n\n function test_proxyCallToImp_notAdmin_succeeds() external {\n // The implementation does not have a `upgradeTo`\n // method, calling `upgradeTo` not as the owner\n // should revert.\n vm.expectRevert();\n proxy.upgradeTo(address(64));\n\n // Call `upgradeTo` as the owner, it should succeed\n // and emit the `Upgraded` event.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(64));\n vm.prank(alice);\n proxy.upgradeTo(address(64));\n\n // Get the implementation as the owner\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(64));\n }\n\n function test_ownerProxyCall_notAdmin_succeeds() external {\n // Calling `changeAdmin` not as the owner should revert\n // as the implementation does not have a `changeAdmin` method.\n vm.expectRevert();\n proxy.changeAdmin(address(1));\n\n // Call `changeAdmin` as the owner, it should succeed\n // and emit the `AdminChanged` event.\n vm.expectEmit(true, true, true, true);\n emit AdminChanged(alice, address(1));\n vm.prank(alice);\n proxy.changeAdmin(address(1));\n\n // Calling `admin` not as the owner should\n // revert as the implementation does not have\n // a `admin` method.\n vm.expectRevert();\n proxy.admin();\n\n // Calling `admin` as the owner should work.\n vm.prank(address(1));\n address owner = proxy.admin();\n assertEq(owner, address(1));\n }\n\n function test_delegatesToImpl_succeeds() external {\n // Call the storage setter on the proxy\n SimpleStorage(address(proxy)).set(1, 1);\n\n // The key should not be set in the implementation\n uint256 result = simpleStorage.get(1);\n assertEq(result, 0);\n {\n // The key should be set in the proxy\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n\n {\n // The owner should be able to call through the proxy\n // when there is not a function selector crash\n vm.prank(alice);\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n }\n\n function test_upgradeToAndCall_succeeds() external {\n {\n // There should be nothing in the current proxy storage\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 0);\n }\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(simpleStorage));\n vm.prank(alice);\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The call should have impacted the state\n uint256 result = SimpleStorage(address(proxy)).get(1);\n assertEq(result, 1);\n }\n\n function test_upgradeToAndCall_functionDoesNotExist_reverts() external {\n // Get the current implementation address\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call. This reverts because the calldata doesn't\n // match a function on the implementation.\n vm.expectRevert(\"Proxy: delegatecall to new implementation contract failed\");\n vm.prank(alice);\n proxy.upgradeToAndCall(address(simpleStorage), hex\"\");\n\n // The implementation address should have not\n // updated because the call to `upgradeToAndCall`\n // reverted.\n vm.prank(alice);\n address postImpl = proxy.implementation();\n assertEq(impl, postImpl);\n\n // The attempt to `upgradeToAndCall`\n // should revert when it is not called by the owner.\n vm.expectRevert();\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n }\n\n function test_upgradeToAndCall_isPayable_succeeds() external {\n // Give alice some funds\n vm.deal(alice, 1 ether);\n // Set the implementation and call and send\n // value.\n vm.prank(alice);\n proxy.upgradeToAndCall{ value: 1 ether }(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The implementation address should be correct\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // The proxy should have a balance\n assertEq(address(proxy).balance, 1 ether);\n }\n\n function test_upgradeTo_clashingFunctionSignatures_succeeds() external {\n // Clasher has a clashing function with the proxy.\n Clasher clasher = new Clasher();\n\n // Set the clasher as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(clasher));\n\n {\n // Assert that the implementation was set properly.\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(clasher));\n }\n\n // Call the clashing function on the proxy\n // not as the owner so that the call passes through.\n // The implementation will revert so we can be\n // sure that the call passed through.\n vm.expectRevert(bytes(\"upgradeTo\"));\n proxy.upgradeTo(address(0));\n\n {\n // Now call the clashing function as the owner\n // and be sure that it doesn't pass through to\n // the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(0));\n }\n }\n\n // Allow for `eth_call` to call proxy methods\n // by setting \"from\" to `address(0)`.\n function test_implementation_zeroAddressCaller_succeeds() external {\n vm.prank(address(0));\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n }\n\n function test_implementation_isZeroAddress_reverts() external {\n // Set `address(0)` as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n\n (bool success, bytes memory returndata) = address(proxy).call(hex\"\");\n assertEq(success, false);\n\n bytes memory err = abi.encodeWithSignature(\n \"Error(string)\",\n \"Proxy: implementation not initialized\"\n );\n\n assertEq(returndata, err);\n }\n}\n" - }, - "contracts/test/ProxyAdmin.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { SimpleStorage } from \"./Proxy.t.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\n\ncontract ProxyAdmin_Test is Test {\n address alice = address(64);\n\n Proxy proxy;\n L1ChugSplashProxy chugsplash;\n ResolvedDelegateProxy resolved;\n\n AddressManager addressManager;\n\n ProxyAdmin admin;\n\n SimpleStorage implementation;\n\n function setUp() external {\n // Deploy the proxy admin\n admin = new ProxyAdmin(alice);\n // Deploy the standard proxy\n proxy = new Proxy(address(admin));\n\n // Deploy the legacy L1ChugSplashProxy with the admin as the owner\n chugsplash = new L1ChugSplashProxy(address(admin));\n\n // Deploy the legacy AddressManager\n addressManager = new AddressManager();\n // The proxy admin must be the new owner of the address manager\n addressManager.transferOwnership(address(admin));\n // Deploy a legacy ResolvedDelegateProxy with the name `a`.\n // Whatever `a` is set to in AddressManager will be the address\n // that is used for the implementation.\n resolved = new ResolvedDelegateProxy(addressManager, \"a\");\n\n // Impersonate alice for setting up the admin.\n vm.startPrank(alice);\n // Set the address of the address manager in the admin so that it\n // can resolve the implementation address of legacy\n // ResolvedDelegateProxy based proxies.\n admin.setAddressManager(addressManager);\n // Set the reverse lookup of the ResolvedDelegateProxy\n // proxy\n admin.setImplementationName(address(resolved), \"a\");\n\n // Set the proxy types\n admin.setProxyType(address(proxy), ProxyAdmin.ProxyType.ERC1967);\n admin.setProxyType(address(chugsplash), ProxyAdmin.ProxyType.CHUGSPLASH);\n admin.setProxyType(address(resolved), ProxyAdmin.ProxyType.RESOLVED);\n vm.stopPrank();\n\n implementation = new SimpleStorage();\n }\n\n function test_setImplementationName_succeeds() external {\n vm.prank(alice);\n admin.setImplementationName(address(1), \"foo\");\n assertEq(admin.implementationName(address(1)), \"foo\");\n }\n\n function test_setAddressManager_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setAddressManager(AddressManager((address(0))));\n }\n\n function test_setImplementationName_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setImplementationName(address(0), \"foo\");\n }\n\n function test_setProxyType_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setProxyType(address(0), ProxyAdmin.ProxyType.CHUGSPLASH);\n }\n\n function test_owner_succeeds() external {\n assertEq(admin.owner(), alice);\n }\n\n function test_proxyType_succeeds() external {\n assertEq(uint256(admin.proxyType(address(proxy))), uint256(ProxyAdmin.ProxyType.ERC1967));\n assertEq(\n uint256(admin.proxyType(address(chugsplash))),\n uint256(ProxyAdmin.ProxyType.CHUGSPLASH)\n );\n assertEq(\n uint256(admin.proxyType(address(resolved))),\n uint256(ProxyAdmin.ProxyType.RESOLVED)\n );\n }\n\n function test_erc1967GetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(proxy));\n }\n\n function test_chugsplashGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(resolved));\n }\n\n function getProxyImplementation(address payable _proxy) internal {\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(0));\n }\n\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n }\n\n function test_erc1967GetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(resolved));\n }\n\n function getProxyAdmin(address payable _proxy) internal {\n address owner = admin.getProxyAdmin(_proxy);\n assertEq(owner, address(admin));\n }\n\n function test_erc1967ChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(resolved));\n }\n\n function changeProxyAdmin(address payable _proxy) internal {\n ProxyAdmin.ProxyType proxyType = admin.proxyType(address(_proxy));\n\n vm.prank(alice);\n admin.changeProxyAdmin(_proxy, address(128));\n\n // The proxy is no longer the admin and can\n // no longer call the proxy interface except for\n // the ResolvedDelegate type on which anybody can\n // call the admin interface.\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n vm.expectRevert(\"Proxy: implementation not initialized\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n vm.expectRevert(\"L1ChugSplashProxy: implementation is not set yet\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n // Just an empty block to show that all cases are covered\n } else {\n vm.expectRevert(\"ProxyAdmin: unknown proxy type\");\n }\n\n // Call the proxy contract directly to get the admin.\n // Different proxy types have different interfaces.\n vm.prank(address(128));\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n assertEq(Proxy(payable(_proxy)).admin(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n assertEq(L1ChugSplashProxy(payable(_proxy)).getOwner(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n assertEq(addressManager.owner(), address(128));\n } else {\n assert(false);\n }\n }\n\n function test_erc1967Upgrade_succeeds() external {\n upgrade(payable(proxy));\n }\n\n function test_chugsplashUpgrade_succeeds() external {\n upgrade(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgrade_succeeds() external {\n upgrade(payable(resolved));\n }\n\n function upgrade(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n\n function test_erc1967UpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(proxy));\n }\n\n function test_chugsplashUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(resolved));\n }\n\n function upgradeAndCall(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgradeAndCall(\n _proxy,\n address(implementation),\n abi.encodeWithSelector(SimpleStorage.set.selector, 1, 1)\n );\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n\n uint256 got = SimpleStorage(address(_proxy)).get(1);\n assertEq(got, 1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.changeProxyAdmin(payable(proxy), address(0));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgrade(payable(proxy), address(implementation));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgradeAndCall(payable(proxy), address(implementation), hex\"\");\n }\n\n function test_isUpgrading_succeeds() external {\n assertEq(false, admin.isUpgrading());\n\n vm.prank(alice);\n admin.setUpgrading(true);\n assertEq(true, admin.isUpgrading());\n }\n}\n" - }, - "contracts/test/RLP.t.sol": { - "content": "// SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\n/**\n * @title LibRLP\n * @notice Via https://github.com/Rari-Capital/solmate/issues/207.\n */\nlibrary LibRLP {\n using Bytes32AddressLib for bytes32;\n\n function computeAddress(address deployer, uint256 nonce) internal pure returns (address) {\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80)))\n .fromLast20Bytes();\n if (nonce <= 0x7f)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce)))\n .fromLast20Bytes();\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= type(uint8).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd7),\n bytes1(0x94),\n deployer,\n bytes1(0x81),\n uint8(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint16).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd8),\n bytes1(0x94),\n deployer,\n bytes1(0x82),\n uint16(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint24).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd9),\n bytes1(0x94),\n deployer,\n bytes1(0x83),\n uint24(nonce)\n )\n ).fromLast20Bytes();\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return\n keccak256(\n abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))\n ).fromLast20Bytes();\n }\n}\n" - }, - "contracts/test/RLPReader.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { RLPReader } from \"../libraries/rlp/RLPReader.sol\";\n\ncontract RLPReader_readBytes_Test is CommonTest {\n function test_readBytes_bytestring00_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"00\"), hex\"00\");\n }\n\n function test_readBytes_bytestring01_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"01\"), hex\"01\");\n }\n\n function test_readBytes_bytestring7f_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"7f\"), hex\"7f\");\n }\n\n function test_readBytes_revertListItem_reverts() external {\n vm.expectRevert(\"RLPReader: decoded item type for bytes is not a data item\");\n RLPReader.readBytes(hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_readBytes_invalidStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n RLPReader.readBytes(hex\"b9\");\n }\n\n function test_readBytes_invalidListLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n RLPReader.readBytes(hex\"ff\");\n }\n\n function test_readBytes_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: bytes value contains an invalid remainder\");\n RLPReader.readBytes(hex\"800a\");\n }\n\n function test_readBytes_invalidPrefix_reverts() external {\n vm.expectRevert(\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n RLPReader.readBytes(hex\"810a\");\n }\n}\n\ncontract RLPReader_readList_Test is CommonTest {\n function test_readList_empty_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c0\");\n assertEq(list.length, 0);\n }\n\n function test_readList_multiList_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c6827a77c10401\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"827a77\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c104\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"01\");\n }\n\n function test_readList_shortListMax1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n\n assertEq(list.length, 11);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[4]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[5]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[6]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[7]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[8]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[9]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[10]), hex\"8471776572\");\n }\n\n function test_readList_longList1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n\n assertEq(list.length, 4);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"cf84617364668471776572847a786376\");\n }\n\n function test_readList_longList2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n assertEq(list.length, 32);\n\n for (uint256 i = 0; i < 32; i++) {\n assertEq(RLPReader.readRawBytes(list[i]), hex\"cf84617364668471776572847a786376\");\n }\n }\n\n function test_readList_listLongerThan32Elements_reverts() external {\n vm.expectRevert(stdError.indexOOBError);\n RLPReader.readList(\n hex\"e1454545454545454545454545454545454545454545454545454545454545454545\"\n );\n }\n\n function test_readList_listOfLists_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c4c2c0c0c0\");\n assertEq(list.length, 2);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c2c0c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c0\");\n }\n\n function test_readList_listOfLists2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c7c0c1c0c3c0c1c0\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c1c0\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"c3c0c1c0\");\n }\n\n function test_readList_dictTest1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n assertEq(list.length, 4);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"ca846b6579318476616c31\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"ca846b6579328476616c32\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"ca846b6579338476616c33\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"ca846b6579348476616c34\");\n }\n\n function test_readList_invalidShortList_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efdebd\");\n }\n\n function test_readList_longStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efb83600\");\n }\n\n function test_readList_notLongEnough_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(\n hex\"efdebdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n );\n }\n\n function test_readList_int32Overflow_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"bf0f000000000000021111\");\n }\n\n function test_readList_int32Overflow2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ff0f000000000000021111\");\n }\n\n function test_readList_incorrectLengthInArray_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b9002100dc2b275d0f74e8a53e6f4ec61b27f24278820be3f82ea2110e582081b0565df0\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b90040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(hex\"b800\");\n }\n\n function test_readList_leadingZerosInLongLengthList1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must not have any leading zeros (long list)\");\n RLPReader.readList(\n hex\"fb00000040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_nonOptimalLongLengthArray1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b81000112233445566778899aabbccddeeff\");\n }\n\n function test_readList_nonOptimalLongLengthArray2_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b801ff\");\n }\n\n function test_readList_invalidValue_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n RLPReader.readList(hex\"91\");\n }\n\n function test_readList_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n RLPReader.readList(hex\"c000\");\n }\n\n function test_readList_notEnoughContentForString1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"ba010000aabbccddeeff\");\n }\n\n function test_readList_notEnoughContentForString2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"b840ffeeddccbbaa99887766554433221100\");\n }\n\n function test_readList_notEnoughContentForList1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"f90180\");\n }\n\n function test_readList_notEnoughContentForList2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ffffffffffffffffff0001020304050607\");\n }\n\n function test_readList_longStringLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b80100\");\n }\n\n function test_readList_longListLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long list)\");\n RLPReader.readList(hex\"f80100\");\n }\n}\n" - }, - "contracts/test/RLPWriter.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { RLPWriter } from \"../libraries/rlp/RLPWriter.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\n\ncontract RLPWriter_writeString_Test is CommonTest {\n function test_writeString_empty_succeeds() external {\n assertEq(RLPWriter.writeString(\"\"), hex\"80\");\n }\n\n function test_writeString_bytestring00_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0000\"), hex\"00\");\n }\n\n function test_writeString_bytestring01_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0001\"), hex\"01\");\n }\n\n function test_writeString_bytestring7f_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u007F\"), hex\"7f\");\n }\n\n function test_writeString_shortstring_succeeds() external {\n assertEq(RLPWriter.writeString(\"dog\"), hex\"83646f67\");\n }\n\n function test_writeString_shortstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing eli\"),\n hex\"b74c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c69\"\n );\n }\n\n function test_writeString_longstring_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing elit\"),\n hex\"b8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974\"\n );\n }\n\n function test_writeString_longstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\n \"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\"\n ),\n hex\"b904004c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20437572616269747572206d6175726973206d61676e612c20737573636970697420736564207665686963756c61206e6f6e2c20696163756c697320666175636962757320746f72746f722e2050726f696e20737573636970697420756c74726963696573206d616c6573756164612e204475697320746f72746f7220656c69742c2064696374756d2071756973207472697374697175652065752c20756c7472696365732061742072697375732e204d6f72626920612065737420696d70657264696574206d6920756c6c616d636f7270657220616c6971756574207375736369706974206e6563206c6f72656d2e2041656e65616e2071756973206c656f206d6f6c6c69732c2076756c70757461746520656c6974207661726975732c20636f6e73657175617420656e696d2e204e756c6c6120756c74726963657320747572706973206a7573746f2c20657420706f73756572652075726e6120636f6e7365637465747572206e65632e2050726f696e206e6f6e20636f6e76616c6c6973206d657475732e20446f6e65632074656d706f7220697073756d20696e206d617572697320636f6e67756520736f6c6c696369747564696e2e20566573746962756c756d20616e746520697073756d207072696d697320696e206661756369627573206f726369206c756374757320657420756c74726963657320706f737565726520637562696c69612043757261653b2053757370656e646973736520636f6e76616c6c69732073656d2076656c206d617373612066617563696275732c2065676574206c6163696e6961206c616375732074656d706f722e204e756c6c61207175697320756c747269636965732070757275732e2050726f696e20617563746f722072686f6e637573206e69626820636f6e64696d656e74756d206d6f6c6c69732e20416c697175616d20636f6e73657175617420656e696d206174206d65747573206c75637475732c206120656c656966656e6420707572757320656765737461732e20437572616269747572206174206e696268206d657475732e204e616d20626962656e64756d2c206e6571756520617420617563746f72207472697374697175652c206c6f72656d206c696265726f20616c697175657420617263752c206e6f6e20696e74657264756d2074656c6c7573206c65637475732073697420616d65742065726f732e20437261732072686f6e6375732c206d65747573206163206f726e617265206375727375732c20646f6c6f72206a7573746f20756c747269636573206d657475732c20617420756c6c616d636f7270657220766f6c7574706174\"\n );\n }\n}\n\ncontract RLPWriter_writeUint_Test is CommonTest {\n function test_writeUint_zero_succeeds() external {\n assertEq(RLPWriter.writeUint(0x0), hex\"80\");\n }\n\n function test_writeUint_smallint_succeeds() external {\n assertEq(RLPWriter.writeUint(1), hex\"01\");\n }\n\n function test_writeUint_smallint2_succeeds() external {\n assertEq(RLPWriter.writeUint(16), hex\"10\");\n }\n\n function test_writeUint_smallint3_succeeds() external {\n assertEq(RLPWriter.writeUint(79), hex\"4f\");\n }\n\n function test_writeUint_smallint4_succeeds() external {\n assertEq(RLPWriter.writeUint(127), hex\"7f\");\n }\n\n function test_writeUint_mediumint_succeeds() external {\n assertEq(RLPWriter.writeUint(128), hex\"8180\");\n }\n\n function test_writeUint_mediumint2_succeeds() external {\n assertEq(RLPWriter.writeUint(1000), hex\"8203e8\");\n }\n\n function test_writeUint_mediumint3_succeeds() external {\n assertEq(RLPWriter.writeUint(100000), hex\"830186a0\");\n }\n}\n\ncontract RLPWriter_writeList_Test is CommonTest {\n function test_writeList_empty_succeeds() external {\n assertEq(RLPWriter.writeList(new bytes[](0)), hex\"c0\");\n }\n\n function test_writeList_stringList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeString(\"dog\");\n list[1] = RLPWriter.writeString(\"god\");\n list[2] = RLPWriter.writeString(\"cat\");\n\n assertEq(RLPWriter.writeList(list), hex\"cc83646f6783676f6483636174\");\n }\n\n function test_writeList_multiList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeUint(4);\n\n list[0] = RLPWriter.writeString(\"zw\");\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeUint(1);\n\n assertEq(RLPWriter.writeList(list), hex\"c6827a77c10401\");\n }\n\n function test_writeList_shortListMax1_succeeds() external {\n bytes[] memory list = new bytes[](11);\n list[0] = RLPWriter.writeString(\"asdf\");\n list[1] = RLPWriter.writeString(\"qwer\");\n list[2] = RLPWriter.writeString(\"zxcv\");\n list[3] = RLPWriter.writeString(\"asdf\");\n list[4] = RLPWriter.writeString(\"qwer\");\n list[5] = RLPWriter.writeString(\"zxcv\");\n list[6] = RLPWriter.writeString(\"asdf\");\n list[7] = RLPWriter.writeString(\"qwer\");\n list[8] = RLPWriter.writeString(\"zxcv\");\n list[9] = RLPWriter.writeString(\"asdf\");\n list[10] = RLPWriter.writeString(\"qwer\");\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n }\n\n function test_writeList_longlist1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list2);\n list[3] = RLPWriter.writeList(list2);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_longlist2_succeeds() external {\n bytes[] memory list = new bytes[](32);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n for (uint256 i = 0; i < 32; i++) {\n list[i] = RLPWriter.writeList(list2);\n }\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_listoflists_succeeds() external {\n // [ [ [], [] ], [] ]\n bytes[] memory list = new bytes[](2);\n bytes[] memory list2 = new bytes[](2);\n\n list2[0] = RLPWriter.writeList(new bytes[](0));\n list2[1] = RLPWriter.writeList(new bytes[](0));\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(new bytes[](0));\n\n assertEq(RLPWriter.writeList(list), hex\"c4c2c0c0c0\");\n }\n\n function test_writeList_listoflists2_succeeds() external {\n // [ [], [[]], [ [], [[]] ] ]\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeList(new bytes[](0));\n\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeList(new bytes[](0));\n\n list[1] = RLPWriter.writeList(list2);\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeList(new bytes[](0));\n list3[1] = RLPWriter.writeList(list2);\n\n list[2] = RLPWriter.writeList(list3);\n\n assertEq(RLPWriter.writeList(list), hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_writeList_dictTest1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n\n bytes[] memory list1 = new bytes[](2);\n list1[0] = RLPWriter.writeString(\"key1\");\n list1[1] = RLPWriter.writeString(\"val1\");\n\n bytes[] memory list2 = new bytes[](2);\n list2[0] = RLPWriter.writeString(\"key2\");\n list2[1] = RLPWriter.writeString(\"val2\");\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeString(\"key3\");\n list3[1] = RLPWriter.writeString(\"val3\");\n\n bytes[] memory list4 = new bytes[](2);\n list4[0] = RLPWriter.writeString(\"key4\");\n list4[1] = RLPWriter.writeString(\"val4\");\n\n list[0] = RLPWriter.writeList(list1);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list3);\n list[3] = RLPWriter.writeList(list4);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n }\n}\n" - }, - "contracts/test/ResolvedDelegateProxy.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\n\ncontract ResolvedDelegateProxy_Test is Test {\n AddressManager internal addressManager;\n SimpleImplementation internal impl;\n SimpleImplementation internal proxy;\n\n function setUp() public {\n // Set up the address manager.\n addressManager = new AddressManager();\n impl = new SimpleImplementation();\n addressManager.setAddress(\"SimpleImplementation\", address(impl));\n\n // Set up the proxy.\n proxy = SimpleImplementation(\n address(new ResolvedDelegateProxy(addressManager, \"SimpleImplementation\"))\n );\n }\n\n // Tests that the proxy properly bubbles up returndata when the delegatecall succeeds.\n function testFuzz_fallback_delegateCallFoo_succeeds(uint256 x) public {\n vm.expectCall(address(impl), abi.encodeWithSelector(impl.foo.selector, x));\n assertEq(proxy.foo(x), x);\n }\n\n // Tests that the proxy properly bubbles up returndata when the delegatecall reverts.\n function test_fallback_delegateCallBar_reverts() public {\n vm.expectRevert(\"SimpleImplementation: revert\");\n vm.expectCall(address(impl), abi.encodeWithSelector(impl.bar.selector));\n proxy.bar();\n }\n\n // Tests that the proxy fallback reverts as expected if the implementation within the\n // address manager is not set.\n function test_fallback_addressManagerNotSet_reverts() public {\n AddressManager am = new AddressManager();\n SimpleImplementation p = SimpleImplementation(\n address(new ResolvedDelegateProxy(am, \"SimpleImplementation\"))\n );\n\n vm.expectRevert(\"ResolvedDelegateProxy: target address must be initialized\");\n p.foo(0);\n }\n}\n\ncontract SimpleImplementation {\n function foo(uint256 _x) public pure returns (uint256) {\n return _x;\n }\n\n function bar() public pure {\n revert(\"SimpleImplementation: revert\");\n }\n}\n" - }, - "contracts/test/ResourceMetering.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract MeterUser is ResourceMetering {\n constructor() {\n initialize();\n }\n\n function initialize() public initializer {\n __ResourceMetering_init();\n }\n\n function resourceConfig() public pure returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig();\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return Constants.DEFAULT_RESOURCE_CONFIG();\n }\n\n function use(uint64 _amount) public metered(_amount) {}\n\n function set(\n uint128 _prevBaseFee,\n uint64 _prevBoughtGas,\n uint64 _prevBlockNum\n ) public {\n params = ResourceMetering.ResourceParams({\n prevBaseFee: _prevBaseFee,\n prevBoughtGas: _prevBoughtGas,\n prevBlockNum: _prevBlockNum\n });\n }\n}\n\n/**\n * @title ResourceConfig\n * @notice The tests are based on the default config values. It is expected that\n * the config values used in these tests are ran in production.\n */\ncontract ResourceMetering_Test is Test {\n MeterUser internal meter;\n uint64 initialBlockNum;\n\n function setUp() public {\n meter = new MeterUser();\n initialBlockNum = uint64(block.number);\n }\n\n function test_meter_initialResourceParams_succeeds() external {\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n\n assertEq(prevBaseFee, rcfg.minimumBaseFee);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_updateParamsNoChange_succeeds() external {\n meter.use(0); // equivalent to just updating the base fee and block number\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n meter.use(0);\n (uint128 postBaseFee, uint64 postBoughtGas, uint64 postBlockNum) = meter.params();\n\n assertEq(postBaseFee, prevBaseFee);\n assertEq(postBoughtGas, prevBoughtGas);\n assertEq(postBlockNum, prevBlockNum);\n }\n\n function test_meter_updateOneEmptyBlock_succeeds() external {\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 1);\n }\n\n function test_meter_updateTwoEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 2);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 2);\n }\n\n function test_meter_updateTenEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 10);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 10);\n }\n\n function test_meter_updateNoGasDelta_succeeds() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint256 target = uint256(rcfg.maxResourceLimit) / uint256(rcfg.elasticityMultiplier);\n meter.use(uint64(target));\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1000000000);\n assertEq(prevBoughtGas, target);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_useMax_succeeds() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n meter.use(target * elasticityMultiplier);\n\n (, uint64 prevBoughtGas, ) = meter.params();\n assertEq(prevBoughtGas, target * elasticityMultiplier);\n\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 postBaseFee, , ) = meter.params();\n assertEq(postBaseFee, 2125000000);\n }\n\n function test_meter_useMoreThanMax_reverts() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n vm.expectRevert(\"ResourceMetering: cannot buy more gas than available gas limit\");\n meter.use(target * elasticityMultiplier + 1);\n }\n\n // Demonstrates that the resource metering arithmetic can tolerate very large gaps between\n // deposits.\n function testFuzz_meter_largeBlockDiff_succeeds(uint64 _amount, uint256 _blockDiff) external {\n // This test fails if the following line is commented out.\n // At 12 seconds per block, this number is effectively unreachable.\n vm.assume(_blockDiff < 433576281058164217753225238677900874458691);\n\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n vm.assume(_amount < target * elasticityMultiplier);\n vm.roll(initialBlockNum + _blockDiff);\n meter.use(_amount);\n }\n}\n\n/**\n * @title CustomMeterUser\n * @notice A simple wrapper around `ResourceMetering` that allows the initial\n * params to be set in the constructor.\n */\ncontract CustomMeterUser is ResourceMetering {\n uint256 public startGas;\n uint256 public endGas;\n\n constructor(\n uint128 _prevBaseFee,\n uint64 _prevBoughtGas,\n uint64 _prevBlockNum\n ) {\n params = ResourceMetering.ResourceParams({\n prevBaseFee: _prevBaseFee,\n prevBoughtGas: _prevBoughtGas,\n prevBlockNum: _prevBlockNum\n });\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return Constants.DEFAULT_RESOURCE_CONFIG();\n }\n\n function use(uint64 _amount) public returns (uint256) {\n uint256 initialGas = gasleft();\n _metered(_amount, initialGas);\n return initialGas - gasleft();\n }\n}\n\n/**\n * @title ArtifactResourceMetering_Test\n * @notice A table test that sets the state of the ResourceParams and then requests\n * various amounts of gas. This test ensures that a wide range of values\n * can safely be used with the `ResourceMetering` contract.\n * It also writes a CSV file to disk that includes useful information\n * about how much gas is used and how expensive it is in USD terms to\n * purchase the deposit gas.\n */\ncontract ArtifactResourceMetering_Test is Test {\n uint128 internal minimumBaseFee;\n uint128 internal maximumBaseFee;\n uint64 internal maxResourceLimit;\n uint64 internal targetResourceLimit;\n\n string internal outfile;\n\n // keccak256(abi.encodeWithSignature(\"Error(string)\", \"ResourceMetering: cannot buy more gas than available gas limit\"))\n bytes32 internal cannotBuyMoreGas =\n 0x84edc668cfd5e050b8999f43ff87a1faaa93e5f935b20bc1dd4d3ff157ccf429;\n // keccak256(abi.encodeWithSignature(\"Panic(uint256)\", 0x11))\n bytes32 internal overflowErr =\n 0x1ca389f2c8264faa4377de9ce8e14d6263ef29c68044a9272d405761bab2db27;\n // keccak256(hex\"\")\n bytes32 internal emptyReturnData =\n 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n\n /**\n * @notice Sets up the tests by getting constants from the ResourceMetering\n * contract.\n */\n function setUp() public {\n vm.roll(1_000_000);\n\n MeterUser base = new MeterUser();\n ResourceMetering.ResourceConfig memory rcfg = base.resourceConfig();\n minimumBaseFee = uint128(rcfg.minimumBaseFee);\n maximumBaseFee = rcfg.maximumBaseFee;\n maxResourceLimit = uint64(rcfg.maxResourceLimit);\n targetResourceLimit = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n\n outfile = string.concat(vm.projectRoot(), \"/.resource-metering.csv\");\n try vm.removeFile(outfile) {} catch {}\n }\n\n /**\n * @notice Generate a CSV file. The call to `meter` should be called with at\n * most the L1 block gas limit. Without specifying the amount of\n * gas, it can take very long to execute.\n */\n function test_meter_generateArtifact_succeeds() external {\n vm.writeLine(\n outfile,\n \"prevBaseFee,prevBoughtGas,prevBlockNumDiff,l1BaseFee,requestedGas,gasConsumed,ethPrice,usdCost,success\"\n );\n\n // prevBaseFee value in ResourceParams\n uint128[] memory prevBaseFees = new uint128[](5);\n prevBaseFees[0] = minimumBaseFee;\n prevBaseFees[1] = maximumBaseFee;\n prevBaseFees[2] = uint128(50 gwei);\n prevBaseFees[3] = uint128(100 gwei);\n prevBaseFees[4] = uint128(200 gwei);\n\n // prevBoughtGas value in ResourceParams\n uint64[] memory prevBoughtGases = new uint64[](1);\n prevBoughtGases[0] = uint64(0);\n\n // prevBlockNum diff, simulates blocks with no deposits when non zero\n uint64[] memory prevBlockNumDiffs = new uint64[](2);\n prevBlockNumDiffs[0] = 0;\n prevBlockNumDiffs[1] = 1;\n\n // The amount of L2 gas that a user requests\n uint64[] memory requestedGases = new uint64[](3);\n requestedGases[0] = maxResourceLimit;\n requestedGases[1] = targetResourceLimit;\n requestedGases[2] = uint64(100_000);\n\n // The L1 base fee\n uint256[] memory l1BaseFees = new uint256[](4);\n l1BaseFees[0] = 1 gwei;\n l1BaseFees[1] = 50 gwei;\n l1BaseFees[2] = 75 gwei;\n l1BaseFees[3] = 100 gwei;\n\n // USD price of 1 ether\n uint256[] memory ethPrices = new uint256[](2);\n ethPrices[0] = 1600;\n ethPrices[1] = 3200;\n\n // Iterate over all of the test values and run a test\n for (uint256 i; i < prevBaseFees.length; i++) {\n for (uint256 j; j < prevBoughtGases.length; j++) {\n for (uint256 k; k < prevBlockNumDiffs.length; k++) {\n for (uint256 l; l < requestedGases.length; l++) {\n for (uint256 m; m < l1BaseFees.length; m++) {\n for (uint256 n; n < ethPrices.length; n++) {\n uint256 snapshotId = vm.snapshot();\n\n uint128 prevBaseFee = prevBaseFees[i];\n uint64 prevBoughtGas = prevBoughtGases[j];\n uint64 prevBlockNumDiff = prevBlockNumDiffs[k];\n uint64 requestedGas = requestedGases[l];\n uint256 l1BaseFee = l1BaseFees[m];\n uint256 ethPrice = ethPrices[n];\n string memory result = \"success\";\n\n vm.fee(l1BaseFee);\n\n CustomMeterUser meter = new CustomMeterUser({\n _prevBaseFee: prevBaseFee,\n _prevBoughtGas: prevBoughtGas,\n _prevBlockNum: uint64(block.number)\n });\n\n vm.roll(block.number + prevBlockNumDiff);\n\n // Call the metering code and catch the various\n // types of errors.\n uint256 gasConsumed = 0;\n try meter.use{ gas: 30_000_000 }(requestedGas) returns (\n uint256 _gasConsumed\n ) {\n gasConsumed = _gasConsumed;\n } catch (bytes memory err) {\n bytes32 hash = keccak256(err);\n if (hash == cannotBuyMoreGas) {\n result = \"ResourceMetering: cannot buy more gas than available gas limit\";\n } else if (hash == overflowErr) {\n result = \"arithmetic overflow/underflow\";\n } else if (hash == emptyReturnData) {\n result = \"out of gas\";\n } else {\n result = \"UNKNOWN ERROR\";\n }\n }\n\n // Compute the USD cost of the gas used\n uint256 usdCost = (gasConsumed * l1BaseFee * ethPrice) / 1 ether;\n\n vm.writeLine(\n outfile,\n string.concat(\n vm.toString(prevBaseFee),\n \",\",\n vm.toString(prevBoughtGas),\n \",\",\n vm.toString(prevBlockNumDiff),\n \",\",\n vm.toString(l1BaseFee),\n \",\",\n vm.toString(requestedGas),\n \",\",\n vm.toString(gasConsumed),\n \",\",\n \"$\",\n vm.toString(ethPrice),\n \",\",\n \"$\",\n vm.toString(usdCost),\n \",\",\n result\n )\n );\n\n assertTrue(vm.revertTo(snapshotId));\n }\n }\n }\n }\n }\n }\n }\n}\n" - }, - "contracts/test/SafeCall.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\n\ncontract SafeCall_call_Test is CommonTest {\n function testFuzz_call_succeeds(\n address from,\n address to,\n uint256 gas,\n uint64 value,\n bytes memory data\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles (mainnet)\n assumeNoPrecompiles(to, 1);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n uint256[2] memory balancesBefore = [from.balance, to.balance];\n\n vm.expectCall(to, value, data);\n vm.prank(from);\n bool success = SafeCall.call(to, gas, value, data);\n\n assertTrue(success, \"call not successful\");\n if (from == to) {\n assertEq(from.balance, balancesBefore[0], \"Self-send did not change balance\");\n } else {\n assertEq(from.balance, balancesBefore[0] - value, \"from balance not drained\");\n assertEq(to.balance, balancesBefore[1] + value, \"to balance received\");\n }\n }\n\n function testFuzz_callWithMinGas_hasEnough_succeeds(\n address from,\n address to,\n uint64 minGas,\n uint64 value,\n bytes memory data\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles (mainnet)\n assumeNoPrecompiles(to, 1);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n // Bound minGas to [0, l1_block_gas_limit]\n minGas = uint64(bound(minGas, 0, 30_000_000));\n\n uint256[2] memory balancesBefore = [from.balance, to.balance];\n\n vm.expectCallMinGas(to, value, minGas, data);\n vm.prank(from);\n bool success = SafeCall.callWithMinGas(to, minGas, value, data);\n\n assertTrue(success, \"call not successful\");\n if (from == to) {\n assertEq(from.balance, balancesBefore[0], \"Self-send did not change balance\");\n } else {\n assertEq(from.balance, balancesBefore[0] - value, \"from balance not drained\");\n assertEq(to.balance, balancesBefore[1] + value, \"to balance received\");\n }\n }\n\n function test_callWithMinGas_noLeakageLow_succeeds() external {\n SimpleSafeCaller caller = new SimpleSafeCaller();\n\n for (uint64 i = 5000; i < 50_000; i++) {\n uint256 snapshot = vm.snapshot();\n\n // 26,071 is the exact amount of gas required to make the safe call\n // successfully.\n if (i < 26_071) {\n assertFalse(caller.makeSafeCall(i, 25_000));\n } else {\n vm.expectCallMinGas(\n address(caller),\n 0,\n 25_000,\n abi.encodeWithSelector(caller.setA.selector, 1)\n );\n assertTrue(caller.makeSafeCall(i, 25_000));\n }\n\n assertTrue(vm.revertTo(snapshot));\n }\n }\n\n function test_callWithMinGas_noLeakageHigh_succeeds() external {\n SimpleSafeCaller caller = new SimpleSafeCaller();\n\n for (uint64 i = 15_200_000; i < 15_300_000; i++) {\n uint256 snapshot = vm.snapshot();\n\n // 15,238,769 is the exact amount of gas required to make the safe call\n // successfully.\n if (i < 15_238_769) {\n assertFalse(caller.makeSafeCall(i, 15_000_000));\n } else {\n vm.expectCallMinGas(\n address(caller),\n 0,\n 15_000_000,\n abi.encodeWithSelector(caller.setA.selector, 1)\n );\n assertTrue(caller.makeSafeCall(i, 15_000_000));\n }\n\n assertTrue(vm.revertTo(snapshot));\n }\n }\n}\n\ncontract SimpleSafeCaller {\n uint256 public a;\n\n function makeSafeCall(uint64 gas, uint64 minGas) external returns (bool) {\n return\n SafeCall.call(\n address(this),\n gas,\n 0,\n abi.encodeWithSelector(this.makeSafeCallMinGas.selector, minGas)\n );\n }\n\n function makeSafeCallMinGas(uint64 minGas) external returns (bool) {\n return\n SafeCall.callWithMinGas(\n address(this),\n minGas,\n 0,\n abi.encodeWithSelector(this.setA.selector, 1)\n );\n }\n\n function setA(uint256 _a) external {\n a = _a;\n }\n}\n" - }, - "contracts/test/Semver.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\n\n/**\n * @notice Test the Semver contract that is used for semantic versioning\n * of various contracts.\n */\ncontract Semver_Test is CommonTest {\n /**\n * @notice Global semver contract deployed in setUp. This is used in\n * the test cases.\n */\n Semver semver;\n\n /**\n * @notice Deploy a Semver contract\n */\n function setUp() public virtual override {\n semver = new Semver(7, 8, 0);\n }\n\n /**\n * @notice Test the version getter\n */\n function test_version_succeeds() external {\n assertEq(semver.version(), \"7.8.0\");\n }\n\n /**\n * @notice Since the versions are all immutable, they should\n * be able to be accessed from behind a proxy without needing\n * to initialize the contract.\n */\n function test_behindProxy_succeeds() external {\n Proxy proxy = new Proxy(alice);\n vm.prank(alice);\n proxy.upgradeTo(address(semver));\n\n assertEq(Semver(address(proxy)).version(), \"7.8.0\");\n }\n}\n" - }, - "contracts/test/SequencerFeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { SequencerFeeVault } from \"../L2/SequencerFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract SequencerFeeVault_Test is Bridge_Initializer {\n SequencerFeeVault vault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET));\n address constant recipient = address(256);\n\n event Withdrawal(uint256 value, address to, address from);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.SEQUENCER_FEE_WALLET, address(new SequencerFeeVault(recipient)).code);\n vm.label(Predeploys.SEQUENCER_FEE_WALLET, \"SequencerFeeVault\");\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(vault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n\n function test_constructor_succeeds() external {\n assertEq(vault.l1FeeWallet(), recipient);\n }\n\n function test_receive_succeeds() external {\n uint256 balance = address(vault).balance;\n\n vm.prank(alice);\n (bool success, ) = address(vault).call{ value: 100 }(hex\"\");\n\n assertEq(success, true);\n assertEq(address(vault).balance, balance + 100);\n }\n\n function test_withdraw_notEnough_reverts() external {\n assert(address(vault).balance < vault.MIN_WITHDRAWAL_AMOUNT());\n\n vm.expectRevert(\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n vault.withdraw();\n }\n\n function test_withdraw_succeeds() external {\n uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1;\n vm.deal(address(vault), amount);\n\n // No ether has been withdrawn yet\n assertEq(vault.totalProcessed(), 0);\n\n vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));\n emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this));\n\n // The entire vault's balance is withdrawn\n vm.expectCall(\n Predeploys.L2_STANDARD_BRIDGE,\n address(vault).balance,\n abi.encodeWithSelector(\n StandardBridge.bridgeETHTo.selector,\n vault.l1FeeWallet(),\n 35_000,\n bytes(\"\")\n )\n );\n\n vault.withdraw();\n\n // The withdrawal was successful\n assertEq(vault.totalProcessed(), amount);\n }\n}\n" - }, - "contracts/test/StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport {\n OptimismMintableERC20,\n ILegacyMintableERC20\n} from \"../universal/OptimismMintableERC20.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/**\n * @title StandardBridgeTester\n * @notice Simple wrapper around the StandardBridge contract that exposes\n * internal functions so they can be more easily tested directly.\n */\ncontract StandardBridgeTester is StandardBridge {\n constructor(address payable _messenger, address payable _otherBridge)\n StandardBridge(_messenger, _otherBridge)\n {}\n\n function isOptimismMintableERC20(address _token) external view returns (bool) {\n return _isOptimismMintableERC20(_token);\n }\n\n function isCorrectTokenPair(address _mintableToken, address _otherToken)\n external\n view\n returns (bool)\n {\n return _isCorrectTokenPair(_mintableToken, _otherToken);\n }\n\n receive() external payable override {}\n}\n\n/**\n * @title LegacyMintable\n * @notice Simple implementation of the legacy OptimismMintableERC20.\n */\ncontract LegacyMintable is ERC20, ILegacyMintableERC20 {\n constructor(string memory _name, string memory _ticker) ERC20(_name, _ticker) {}\n\n function l1Token() external pure returns (address) {\n return address(0);\n }\n\n function mint(address _to, uint256 _amount) external pure {}\n\n function burn(address _from, uint256 _amount) external pure {}\n\n /**\n * @notice Implements ERC165. This implementation should not be changed as\n * it is how the actual legacy optimism mintable token does the\n * check. Allows for testing against code that is has been deployed,\n * assuming different compiler version is no problem.\n */\n function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {\n bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^\n ILegacyMintableERC20.mint.selector ^\n ILegacyMintableERC20.burn.selector;\n return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n }\n}\n\n/**\n * @title StandardBridge_Stateless_Test\n * @notice Tests internal functions that require no existing state or contract\n * interactions with the messenger.\n */\ncontract StandardBridge_Stateless_Test is CommonTest {\n StandardBridgeTester internal bridge;\n OptimismMintableERC20 internal mintable;\n ERC20 internal erc20;\n LegacyMintable internal legacy;\n\n function setUp() public override {\n super.setUp();\n\n bridge = new StandardBridgeTester({\n _messenger: payable(address(0)),\n _otherBridge: payable(address(0))\n });\n\n mintable = new OptimismMintableERC20({\n _bridge: address(0),\n _remoteToken: address(0),\n _name: \"Stonks\",\n _symbol: \"STONK\"\n });\n\n erc20 = new ERC20(\"Altcoin\", \"ALT\");\n legacy = new LegacyMintable(\"Legacy\", \"LEG\");\n }\n\n /**\n * @notice Test coverage for identifying OptimismMintableERC20 tokens.\n * This function should return true for both modern and legacy\n * OptimismMintableERC20 tokens and false for any accounts that\n * do not implement the interface.\n */\n function test_isOptimismMintableERC20_succeeds() external {\n // Both the modern and legacy mintable tokens should return true\n assertTrue(bridge.isOptimismMintableERC20(address(mintable)));\n assertTrue(bridge.isOptimismMintableERC20(address(legacy)));\n // A regular ERC20 should return false\n assertFalse(bridge.isOptimismMintableERC20(address(erc20)));\n // Non existent contracts should return false and not revert\n assertEq(address(0x20).code.length, 0);\n assertFalse(bridge.isOptimismMintableERC20(address(0x20)));\n }\n\n /**\n * @notice Test coverage of isCorrectTokenPair under different types of\n * tokens.\n */\n function test_isCorrectTokenPair_succeeds() external {\n // Modern + known to be correct remote token\n assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.remoteToken()));\n // Modern + known to be correct l1Token (legacy interface)\n assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.l1Token()));\n // Modern + known to be incorrect remote token\n assertTrue(mintable.remoteToken() != address(0x20));\n assertFalse(bridge.isCorrectTokenPair(address(mintable), address(0x20)));\n // Legacy + known to be correct l1Token\n assertTrue(bridge.isCorrectTokenPair(address(legacy), legacy.l1Token()));\n // Legacy + known to be incorrect l1Token\n assertTrue(legacy.l1Token() != address(0x20));\n assertFalse(bridge.isCorrectTokenPair(address(legacy), address(0x20)));\n // A token that doesn't support either modern or legacy interface\n // will revert\n vm.expectRevert();\n bridge.isCorrectTokenPair(address(erc20), address(1));\n }\n}\n" - }, - "contracts/test/SystemConfig.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract SystemConfig_Init is CommonTest {\n SystemConfig sysConf;\n\n function setUp() public virtual override {\n super.setUp();\n\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n\n sysConf = new SystemConfig({\n _owner: alice,\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(1),\n _config: config\n });\n }\n}\n\ncontract SystemConfig_Initialize_TestFail is SystemConfig_Init {\n function test_initialize_lowGasLimit_reverts() external {\n uint64 minimumGasLimit = sysConf.minimumGasLimit();\n\n ResourceMetering.ResourceConfig memory cfg = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n\n vm.expectRevert(\"SystemConfig: gas limit too low\");\n new SystemConfig({\n _owner: alice,\n _overhead: 0,\n _scalar: 0,\n _batcherHash: bytes32(hex\"\"),\n _gasLimit: minimumGasLimit - 1,\n _unsafeBlockSigner: address(1),\n _config: cfg\n });\n }\n}\n\ncontract SystemConfig_Setters_TestFail is SystemConfig_Init {\n function test_setBatcherHash_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setBatcherHash(bytes32(hex\"\"));\n }\n\n function test_setGasConfig_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasConfig(0, 0);\n }\n\n function test_setGasLimit_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasLimit(0);\n }\n\n function test_setUnsafeBlockSigner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setUnsafeBlockSigner(address(0x20));\n }\n\n function test_setResourceConfig_notOwner_reverts() external {\n ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_badMinMax_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 2 gwei,\n maximumBaseFee: 1 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: min base fee must be less than max base\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_zeroDenominator_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 0,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: denominator cannot be 0\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_lowGasLimit_reverts() external {\n uint64 gasLimit = sysConf.gasLimit();\n\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: uint32(gasLimit),\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: uint32(gasLimit),\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: gas limit too low\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_badPrecision_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 11,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: precision loss with target resource limit\");\n sysConf.setResourceConfig(config);\n }\n}\n\ncontract SystemConfig_Setters_Test is SystemConfig_Init {\n event ConfigUpdate(\n uint256 indexed version,\n SystemConfig.UpdateType indexed updateType,\n bytes data\n );\n\n function testFuzz_setBatcherHash_succeeds(bytes32 newBatcherHash) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash));\n\n vm.prank(sysConf.owner());\n sysConf.setBatcherHash(newBatcherHash);\n assertEq(sysConf.batcherHash(), newBatcherHash);\n }\n\n function testFuzz_setGasConfig_succeeds(uint256 newOverhead, uint256 newScalar) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.GAS_CONFIG,\n abi.encode(newOverhead, newScalar)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setGasConfig(newOverhead, newScalar);\n assertEq(sysConf.overhead(), newOverhead);\n assertEq(sysConf.scalar(), newScalar);\n }\n\n function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external {\n uint64 minimumGasLimit = sysConf.MINIMUM_GAS_LIMIT();\n newGasLimit = uint64(\n bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(type(uint64).max))\n );\n\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit));\n\n vm.prank(sysConf.owner());\n sysConf.setGasLimit(newGasLimit);\n assertEq(sysConf.gasLimit(), newGasLimit);\n }\n\n function testFuzz_setUnsafeBlockSigner_succeeds(address newUnsafeSigner) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER,\n abi.encode(newUnsafeSigner)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setUnsafeBlockSigner(newUnsafeSigner);\n assertEq(sysConf.unsafeBlockSigner(), newUnsafeSigner);\n }\n}\n" - }, - "contracts/test/TransferOnion.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { TransferOnion } from \"../periphery/TransferOnion.sol\";\n\n/**\n * @title TransferOnionTest\n * @notice Test coverage of TransferOnion\n */\ncontract TransferOnionTest is Test {\n /**\n * @notice TransferOnion\n */\n TransferOnion internal onion;\n\n /**\n * @notice token constructor arg\n */\n address internal _token;\n\n /**\n * @notice sender constructor arg\n */\n address internal _sender;\n\n /**\n * @notice Sets up addresses, deploys contracts and funds the owner.\n */\n function setUp() public {\n ERC20 token = new ERC20(\"Token\", \"TKN\");\n _token = address(token);\n _sender = makeAddr(\"sender\");\n }\n\n /**\n * @notice Deploy the TransferOnion with a dummy shell\n */\n function _deploy() public {\n _deploy(bytes32(0));\n }\n\n /**\n * @notice Deploy the TransferOnion with a specific shell\n */\n function _deploy(bytes32 _shell) public {\n onion = new TransferOnion({ _token: ERC20(_token), _sender: _sender, _shell: _shell });\n }\n\n /**\n * @notice Build the onion data\n */\n function _onionize(TransferOnion.Layer[] memory _layers)\n public\n pure\n returns (bytes32, TransferOnion.Layer[] memory)\n {\n uint256 length = _layers.length;\n bytes32 hash = bytes32(0);\n for (uint256 i; i < length; i++) {\n TransferOnion.Layer memory layer = _layers[i];\n _layers[i].shell = hash;\n hash = keccak256(abi.encode(layer.recipient, layer.amount, hash));\n }\n return (hash, _layers);\n }\n\n /**\n * @notice The constructor sets the variables as expected\n */\n function test_constructor_succeeds() external {\n _deploy();\n\n assertEq(address(onion.TOKEN()), _token);\n assertEq(onion.SENDER(), _sender);\n assertEq(onion.shell(), bytes32(0));\n }\n\n /**\n * @notice unwrap\n */\n function test_unwrap_succeeds() external {\n // Commit to transferring tiny amounts of tokens\n TransferOnion.Layer[] memory _layers = new TransferOnion.Layer[](2);\n _layers[0] = TransferOnion.Layer(address(1), 1, bytes32(0));\n _layers[1] = TransferOnion.Layer(address(2), 2, bytes32(0));\n\n // Build the onion shell\n (bytes32 shell, TransferOnion.Layer[] memory layers) = _onionize(_layers);\n _deploy(shell);\n\n assertEq(onion.shell(), shell);\n\n address token = address(onion.TOKEN());\n address sender = onion.SENDER();\n\n // give 3 units of token to sender\n deal(token, onion.SENDER(), 3);\n vm.prank(sender);\n ERC20(token).approve(address(onion), 3);\n\n // To build the inputs, to `peel`, need to reverse the list\n TransferOnion.Layer[] memory inputs = new TransferOnion.Layer[](2);\n int256 length = int256(layers.length);\n for (int256 i = length - 1; i >= 0; i--) {\n uint256 ui = uint256(i);\n uint256 revidx = uint256(length) - ui - 1;\n TransferOnion.Layer memory layer = layers[ui];\n inputs[revidx] = layer;\n }\n\n // The accounts have no balance\n assertEq(ERC20(_token).balanceOf(address(1)), 0);\n assertEq(ERC20(_token).balanceOf(address(2)), 0);\n\n onion.peel(inputs);\n\n // Now the accounts have the expected balance\n assertEq(ERC20(_token).balanceOf(address(1)), 1);\n assertEq(ERC20(_token).balanceOf(address(2)), 2);\n }\n}\n" - }, - "contracts/test/invariants/CrossDomainMessenger.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { StdUtils } from \"forge-std/StdUtils.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport { OptimismPortal } from \"../../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../../L1/L1CrossDomainMessenger.sol\";\nimport { Messenger_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\nimport { Predeploys } from \"../../libraries/Predeploys.sol\";\nimport { Encoding } from \"../../libraries/Encoding.sol\";\nimport { Hashing } from \"../../libraries/Hashing.sol\";\n\ncontract RelayActor is StdUtils {\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n uint256 public numHashes;\n bytes32[] public hashes;\n bool public reverted = false;\n\n OptimismPortal op;\n L1CrossDomainMessenger xdm;\n Vm vm;\n\n constructor(\n OptimismPortal _op,\n L1CrossDomainMessenger _xdm,\n Vm _vm\n ) {\n op = _op;\n xdm = _xdm;\n vm = _vm;\n }\n\n /**\n * Relays a message to the `L1CrossDomainMessenger` with a random `version`, `_minGasLimit`\n * and `_message`.\n */\n function relay(\n uint16 _version,\n uint32 _minGasLimit,\n bytes memory _message\n ) external {\n address target = address(0x04); // ID precompile\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Restrict `_minGasLimit` to a number in the range of the block gas limit.\n _minGasLimit = uint32(bound(_minGasLimit, 0, block.gaslimit));\n\n // Restrict version to the range of [0, 1]\n _version = _version % 2;\n\n // Compute the cross domain message hash and store it in `hashes`.\n // The `relayMessage` function will always encode the message as a version 1\n // message after checking that the V0 hash has not already been relayed.\n bytes32 _hash = Hashing.hashCrossDomainMessageV1(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n 0, // value\n _minGasLimit,\n _message\n );\n\n // Act as the optimism portal and call `relayMessage` on the `L1CrossDomainMessenger` with\n // the outer min gas limit.\n vm.startPrank(address(op));\n vm.expectCall(target, _message);\n try\n xdm.relayMessage{ gas: xdm.baseGas(_message, _minGasLimit) }(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n 0, // value\n _minGasLimit,\n _message\n )\n {} catch {\n // If any of these calls revert, set `reverted` to true to fail the invariant test.\n // NOTE: This is to get around forge's invariant fuzzer ignoring reverted calls\n // to this function.\n reverted = true;\n }\n vm.stopPrank();\n\n hashes.push(_hash);\n numHashes += 1;\n }\n}\n\ncontract XDM_MinGasLimits is Messenger_Initializer {\n RelayActor actor;\n\n function setUp() public virtual override {\n // Set up the `L1CrossDomainMessenger` and `OptimismPortal` contracts.\n super.setUp();\n\n // Deploy a relay actor\n actor = new RelayActor(op, L1Messenger, vm);\n\n // Target the `RelayActor` contract\n targetContract(address(actor));\n\n // Target the actor's `relay` function\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = actor.relay.selector;\n targetSelector(FuzzSelector({ addr: address(actor), selectors: selectors }));\n }\n\n /**\n * @custom:invariant A call to `relayMessage` should never revert if at least the proper minimum\n * gas limits are supplied.\n *\n * There are two minimum gas limits here:\n *\n * - The outer min gas limit is for the call from the `OptimismPortal` to the\n * `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function\n * with the `message` and inner limit.\n *\n * - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target\n * contract.\n */\n function invariant_minGasLimits() public {\n uint256 length = actor.numHashes();\n for (uint256 i = 0; i < length; ++i) {\n bytes32 hash = actor.hashes(i);\n // the message hash is in the successfulMessages mapping\n assertTrue(L1Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertFalse(L1Messenger.failedMessages(hash));\n }\n assertFalse(actor.reverted());\n }\n}\n" - }, - "contracts/test/invariants/L2OutputOracle.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { L2OutputOracle_Initializer } from \"../CommonTest.t.sol\";\nimport { L2OutputOracle } from \"../../L1/L2OutputOracle.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\n\ncontract L2OutputOracle_Proposer {\n L2OutputOracle internal oracle;\n Vm internal vm;\n\n constructor(L2OutputOracle _oracle, Vm _vm) {\n oracle = _oracle;\n vm = _vm;\n }\n\n /**\n * @dev Allows the actor to propose an L2 output to the `L2OutputOracle`\n */\n function proposeL2Output(\n bytes32 _outputRoot,\n uint256 _l2BlockNumber,\n bytes32 _l1BlockHash,\n uint256 _l1BlockNumber\n ) external {\n // Act as the proposer and propose a new output.\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _l2BlockNumber, _l1BlockHash, _l1BlockNumber);\n }\n}\n\ncontract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_Initializer {\n L2OutputOracle_Proposer internal actor;\n\n function setUp() public override {\n super.setUp();\n\n // Create a proposer actor.\n actor = new L2OutputOracle_Proposer(oracle, vm);\n\n // Set the target contract to the proposer actor.\n targetContract(address(actor));\n\n // Set the target selector for `proposeL2Output`\n // `proposeL2Output` is the only function we care about, as it is the only function\n // that can modify the `l2Outputs` array in the oracle.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = actor.proposeL2Output.selector;\n FuzzSelector memory selector = FuzzSelector({ addr: address(actor), selectors: selectors });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The block number of the output root proposals should monotonically\n * increase.\n *\n * When a new output is submitted, it should never be allowed to correspond to a block\n * number that is less than the current output.\n */\n function invariant_monotonicBlockNumIncrease() external {\n // Assert that the block number of proposals must monotonically increase.\n assertTrue(oracle.nextBlockNumber() >= oracle.latestBlockNumber());\n }\n}\n" - }, - "contracts/test/invariants/OptimismPortal.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Portal_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\n\ncontract OptimismPortal_Invariant_Harness is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n function setUp() public virtual override {\n super.setUp();\n\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n}\n\ncontract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the finalization\n * period has not elapsed.\n *\n * A withdrawal that has been proven should not be able to be finalized until after\n * the finalization period has elapsed.\n */\n function invariant_cannotFinalizeBeforePeriodHasPassed() external {\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Finalize the withdrawal transaction.\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal\n * has already been finalized.\n *\n * Ensures that there is no chain of calls that can be made that allows a withdrawal\n * to be finalized twice.\n */\n function invariant_cannotFinalizeTwice() external {\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant A withdrawal should **always** be able to be finalized\n * `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.\n *\n * This invariant asserts that there is no chain of calls that can be made that\n * will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS`\n * after it was successfully proven.\n */\n function invariant_canAlwaysFinalize() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assertEq(address(bob).balance, bobBalanceBefore + _defaultTx.value);\n }\n}\n" - }, - "contracts/test/invariants/SafeCall.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { StdUtils } from \"forge-std/StdUtils.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport { SafeCall } from \"../../libraries/SafeCall.sol\";\n\ncontract SafeCall_Succeeds_Invariants is Test {\n SafeCaller_Actor actor;\n\n function setUp() public {\n // Create a new safe caller actor.\n actor = new SafeCaller_Actor(vm, false);\n\n // Set the caller to this contract\n targetSender(address(this));\n\n // Target the safe caller actor.\n targetContract(address(actor));\n }\n\n /**\n * @custom:invariant If `callWithMinGas` performs a call, then it must always\n * provide at least the specified minimum gas limit to the subcontext.\n *\n * If the check for remaining gas in `SafeCall.callWithMinGas` passes, the\n * subcontext of the call below it must be provided at least `minGas` gas.\n */\n function invariant_callWithMinGas_alwaysForwardsMinGas_succeeds() public {\n assertEq(actor.numCalls(), 0, \"no failed calls allowed\");\n }\n\n function performSafeCallMinGas(uint64 minGas) external {\n SafeCall.callWithMinGas(address(0), minGas, 0, hex\"\");\n }\n}\n\ncontract SafeCall_Fails_Invariants is Test {\n SafeCaller_Actor actor;\n\n function setUp() public {\n // Create a new safe caller actor.\n actor = new SafeCaller_Actor(vm, true);\n\n // Set the caller to this contract\n targetSender(address(this));\n\n // Target the safe caller actor.\n targetContract(address(actor));\n }\n\n /**\n * @custom:invariant `callWithMinGas` reverts if there is not enough gas to pass\n * to the subcontext.\n *\n * If there is not enough gas in the callframe to ensure that `callWithMinGas`\n * can provide the specified minimum gas limit to the subcontext of the call,\n * then `callWithMinGas` must revert.\n */\n function invariant_callWithMinGas_neverForwardsMinGas_reverts() public {\n assertEq(actor.numCalls(), 0, \"no successful calls allowed\");\n }\n\n function performSafeCallMinGas(uint64 minGas) external {\n SafeCall.callWithMinGas(address(0), minGas, 0, hex\"\");\n }\n}\n\ncontract SafeCaller_Actor is StdUtils {\n bool internal immutable FAILS;\n\n Vm internal vm;\n uint256 public numCalls;\n\n constructor(Vm _vm, bool _fails) {\n vm = _vm;\n FAILS = _fails;\n }\n\n function performSafeCallMinGas(uint64 gas, uint64 minGas) external {\n if (FAILS) {\n // Bound the minimum gas amount to [2500, type(uint48).max]\n minGas = uint64(bound(minGas, 2500, type(uint48).max));\n // Bound the gas passed to [minGas, (((minGas + 200) * 64) / 63)]\n gas = uint64(bound(gas, minGas, (((minGas + 200) * 64) / 63)));\n } else {\n // Bound the minimum gas amount to [2500, type(uint48).max]\n minGas = uint64(bound(minGas, 2500, type(uint48).max));\n // Bound the gas passed to [(((minGas + 200) * 64) / 63) + 500, type(uint64).max]\n gas = uint64(bound(gas, (((minGas + 200) * 64) / 63) + 500, type(uint64).max));\n }\n\n vm.expectCallMinGas(address(0x00), 0, minGas, hex\"\");\n bool success = SafeCall.call(\n msg.sender,\n gas,\n 0,\n abi.encodeWithSelector(0x2ae57a41, minGas)\n );\n\n if (success && FAILS) numCalls++;\n if (!FAILS && !success) numCalls++;\n }\n}\n" - }, - "contracts/test/invariants/SystemConfig.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { SystemConfig } from \"../../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../../L1/ResourceMetering.sol\";\nimport { Constants } from \"../../libraries/Constants.sol\";\n\ncontract SystemConfig_GasLimitLowerBound_Invariant is Test {\n SystemConfig public config;\n\n function setUp() public {\n ResourceMetering.ResourceConfig memory cfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n config = new SystemConfig({\n _owner: address(0xbeef),\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(1),\n _config: cfg\n });\n\n // Set the target contract to the `config`\n targetContract(address(config));\n // Set the target sender to the `config`'s owner (0xbeef)\n targetSender(address(0xbeef));\n // Set the target selector for `setGasLimit`\n // `setGasLimit` is the only function we care about, as it is the only function\n // that can modify the gas limit within the SystemConfig.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = config.setGasLimit.selector;\n FuzzSelector memory selector = FuzzSelector({\n addr: address(config),\n selectors: selectors\n });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The gas limit of the `SystemConfig` contract can never be lower\n * than the hard-coded lower bound.\n */\n function invariant_gasLimitLowerBound() external {\n assertTrue(config.gasLimit() >= config.MINIMUM_GAS_LIMIT());\n }\n}\n" - }, - "contracts/universal/CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\n/**\n * @custom:legacy\n * @title CrossDomainMessengerLegacySpacer0\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 CrossDomainMessengerLegacySpacer0 {\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:legacy\n * @title CrossDomainMessengerLegacySpacer1\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\n * PausableUpgradable and OwnableUpgradeable variables used to exist. Must be\n * the third contract in the inheritance tree of the CrossDomainMessenger.\n */\ncontract CrossDomainMessengerLegacySpacer1 {\n /**\n * @custom:legacy\n * @custom:spacer __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * ContextUpgradable via OwnableUpgradeable.\n *\n */\n uint256[50] private spacer_1_0_1600;\n\n /**\n * @custom:legacy\n * @custom:spacer _owner\n * @notice Spacer for backwards compatibility.\n * Come from OpenZeppelin OwnableUpgradeable.\n */\n address private spacer_51_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * ContextUpgradable via PausableUpgradable.\n */\n uint256[49] private spacer_52_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer _paused\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n bool private spacer_101_0_1;\n\n /**\n * @custom:legacy\n * @custom:spacer __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n uint256[49] private spacer_102_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer ReentrancyGuardUpgradeable's `_status` field.\n * @notice Spacer for backwards compatibility\n */\n uint256 private spacer_151_0_32;\n\n /**\n * @custom:spacer ReentrancyGuardUpgradeable\n * @notice Spacer for backwards compatibility\n */\n uint256[49] private __gap_reentrancy_guard;\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/**\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 *\n * Any changes to this contract MUST result in a semver bump for contracts that inherit it.\n */\nabstract contract CrossDomainMessenger is\n CrossDomainMessengerLegacySpacer0,\n Initializable,\n CrossDomainMessengerLegacySpacer1\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 uint64 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 uint64 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 uint64 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 uint64 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\n\n /**\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\n */\n address public immutable OTHER_MESSENGER;\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 a boolean if and only if the message has failed to be\n * executed at least once. A message will not be present in this mapping if it\n * successfully executed on the first attempt.\n */\n mapping(bytes32 => bool) public failedMessages;\n\n /**\n * @notice A mapping of hashes to reentrancy locks.\n */\n mapping(bytes32 => bool) internal reentrancyLocks;\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[41] 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 OTHER_MESSENGER = _otherMessenger;\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 OTHER_MESSENGER,\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 {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n require(\n version < 2,\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // If the message is version 0, then it's a migrated legacy withdrawal. We therefore need\n // to check that the legacy version of the message has not already been relayed.\n if (version == 0) {\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _nonce);\n require(\n successfulMessages[oldHash] == false,\n \"CrossDomainMessenger: legacy withdrawal already relayed\"\n );\n }\n\n // We use the v1 message hash as the unique identifier for the message because it commits\n // to the value and minimum gas limit of the message.\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _minGasLimit,\n _message\n );\n\n // Check if the reentrancy lock for the `versionedHash` is already set.\n if (reentrancyLocks[versionedHash]) {\n revert(\"ReentrancyGuard: reentrant call\");\n }\n // Trigger the reentrancy lock for `versionedHash`\n reentrancyLocks[versionedHash] = true;\n\n if (_isOtherMessenger()) {\n // These properties should always hold when the message is first submitted (as\n // opposed to being replayed).\n assert(msg.value == _value);\n assert(!failedMessages[versionedHash]);\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 failedMessages[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 xDomainMsgSender = _sender;\n bool success = SafeCall.callWithMinGas(_target, _minGasLimit, _value, _message);\n xDomainMsgSender = Constants.DEFAULT_L2_SENDER;\n\n if (success) {\n successfulMessages[versionedHash] = true;\n emit RelayedMessage(versionedHash);\n } else {\n failedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n\n // Revert in this case if the transaction was triggered by the estimation address. This\n // should only be possible during gas estimation or we have bigger problems. Reverting\n // here will make the behavior of gas estimation change such that the gas limit\n // computed will be the amount required to relay the message, even if that amount is\n // greater than the minimum gas limit specified by the user.\n if (tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"CrossDomainMessenger: failed to relay message\");\n }\n }\n\n // Clear the reentrancy lock for `versionedHash`\n reentrancyLocks[versionedHash] = false;\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 != Constants.DEFAULT_L2_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 (uint64) {\n // We peform the following math on uint64s to avoid overflow errors. Multiplying the\n // by MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR would otherwise limit the _minGasLimit to\n // type(uint32).max / MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR ~= 4.2m.\n return\n // Dynamic overhead\n ((uint64(_minGasLimit) * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n // Calldata overhead\n (uint64(_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 = Constants.DEFAULT_L2_SENDER;\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" - }, - "contracts/universal/ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CrossDomainMessenger } from \"./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 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 OTHER_BRIDGE;\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 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 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() == OTHER_BRIDGE,\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 OTHER_BRIDGE = _otherBridge;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for other bridge address.\n *\n * @return Address of the bridge on the other network.\n */\n function otherBridge() external view returns (address) {\n return OTHER_BRIDGE;\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" - }, - "contracts/universal/FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n/**\n * @title FeeVault\n * @notice The FeeVault contract contains the basic logic for the various different vault contracts\n * used to hold fee revenue generated by the L2 system.\n */\nabstract contract FeeVault {\n /**\n * @notice Emits each time that a withdrawal occurs.\n *\n * @param value Amount that was withdrawn (in wei).\n * @param to Address that the funds were sent to.\n * @param from Address that triggered the withdrawal.\n */\n event Withdrawal(uint256 value, address to, address from);\n\n /**\n * @notice Minimum balance before a withdrawal can be triggered.\n */\n uint256 public immutable MIN_WITHDRAWAL_AMOUNT;\n\n /**\n * @notice Wallet that will receive the fees on L1.\n */\n address public immutable RECIPIENT;\n\n /**\n * @notice The minimum gas limit for the FeeVault withdrawal transaction.\n */\n uint32 internal constant WITHDRAWAL_MIN_GAS = 35_000;\n\n /**\n * @notice Total amount of wei processed by the contract.\n */\n uint256 public totalProcessed;\n\n /**\n * @param _recipient Wallet that will receive the fees on L1.\n * @param _minWithdrawalAmount Minimum balance before a withdrawal can be triggered.\n */\n constructor(address _recipient, uint256 _minWithdrawalAmount) {\n MIN_WITHDRAWAL_AMOUNT = _minWithdrawalAmount;\n RECIPIENT = _recipient;\n }\n\n /**\n * @notice Allow the contract to receive ETH.\n */\n receive() external payable {}\n\n /**\n * @notice Triggers a withdrawal of funds to the L1 fee wallet.\n */\n function withdraw() external {\n require(\n address(this).balance >= MIN_WITHDRAWAL_AMOUNT,\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n\n uint256 value = address(this).balance;\n totalProcessed += value;\n\n emit Withdrawal(value, RECIPIENT, msg.sender);\n\n L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)).bridgeETHTo{ value: value }(\n RECIPIENT,\n WITHDRAWAL_MIN_GAS,\n bytes(\"\")\n );\n }\n}\n" - }, - "contracts/universal/IOptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\n/**\n * @title IOptimismMintableERC20\n * @notice This interface is available on the OptimismMintableERC20 contract. We declare it as a\n * separate interface so that it can be used in custom implementations of\n * OptimismMintableERC20.\n */\ninterface IOptimismMintableERC20 is IERC165 {\n function remoteToken() external view returns (address);\n\n function bridge() external returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n\n/**\n * @custom:legacy\n * @title ILegacyMintableERC20\n * @notice This interface was available on the legacy L2StandardERC20 contract. It remains available\n * on the OptimismMintableERC20 contract for backwards compatibility.\n */\ninterface ILegacyMintableERC20 is IERC165 {\n function l1Token() external view returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n" - }, - "contracts/universal/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 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 /**\n * @notice Chain ID of the chain where the remote token is deployed.\n */\n function REMOTE_CHAIN_ID() external view returns (uint256);\n\n /**\n * @notice Address of the token on the remote domain.\n */\n function REMOTE_TOKEN() 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 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" - }, - "contracts/universal/OptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { ILegacyMintableERC20, IOptimismMintableERC20 } from \"./IOptimismMintableERC20.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @title OptimismMintableERC20\n * @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed\n * to allow the StandardBridge contracts to mint and burn tokens. This makes it possible to\n * use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa.\n * Designed to be backwards compatible with the older StandardL2ERC20 token which was only\n * meant for use on L2.\n */\ncontract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, Semver {\n /**\n * @notice Address of the corresponding version of this token on the remote chain.\n */\n address public immutable REMOTE_TOKEN;\n\n /**\n * @notice Address of the StandardBridge on this network.\n */\n address public immutable BRIDGE;\n\n /**\n * @notice Emitted whenever tokens are minted for an account.\n *\n * @param account Address of the account tokens are being minted for.\n * @param amount Amount of tokens minted.\n */\n event Mint(address indexed account, uint256 amount);\n\n /**\n * @notice Emitted whenever tokens are burned from an account.\n *\n * @param account Address of the account tokens are being burned from.\n * @param amount Amount of tokens burned.\n */\n event Burn(address indexed account, uint256 amount);\n\n /**\n * @notice A modifier that only allows the bridge to call\n */\n modifier onlyBridge() {\n require(msg.sender == BRIDGE, \"OptimismMintableERC20: only bridge can mint and burn\");\n _;\n }\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _bridge Address of the L2 standard bridge.\n * @param _remoteToken Address of the corresponding L1 token.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n */\n constructor(\n address _bridge,\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) Semver(1, 0, 0) {\n REMOTE_TOKEN = _remoteToken;\n BRIDGE = _bridge;\n }\n\n /**\n * @notice Allows the StandardBridge on this network to mint tokens.\n *\n * @param _to Address to mint tokens to.\n * @param _amount Amount of tokens to mint.\n */\n function mint(address _to, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _mint(_to, _amount);\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Allows the StandardBridge on this network to burn tokens.\n *\n * @param _from Address to burn tokens from.\n * @param _amount Amount of tokens to burn.\n */\n function burn(address _from, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _burn(_from, _amount);\n emit Burn(_from, _amount);\n }\n\n /**\n * @notice ERC165 interface check function.\n *\n * @param _interfaceId Interface ID to check.\n *\n * @return Whether or not the interface is supported by this contract.\n */\n function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {\n bytes4 iface1 = type(IERC165).interfaceId;\n // Interface corresponding to the legacy L2StandardERC20.\n bytes4 iface2 = type(ILegacyMintableERC20).interfaceId;\n // Interface corresponding to the updated OptimismMintableERC20 (this contract).\n bytes4 iface3 = type(IOptimismMintableERC20).interfaceId;\n return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward.\n */\n function l1Token() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the bridge. Use BRIDGE going forward.\n */\n function l2Bridge() public view returns (address) {\n return BRIDGE;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for REMOTE_TOKEN.\n */\n function remoteToken() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for BRIDGE.\n */\n function bridge() public view returns (address) {\n return BRIDGE;\n }\n}\n" - }, - "contracts/universal/OptimismMintableERC20Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Contract Imports */\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { Semver } from \"./Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000012\n * @title OptimismMintableERC20Factory\n * @notice OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20\n * contracts on the network it's deployed to. Simplifies the deployment process for users\n * who may be less familiar with deploying smart contracts. Designed to be backwards\n * compatible with the older StandardL2ERC20Factory contract.\n */\ncontract OptimismMintableERC20Factory is Semver {\n /**\n * @notice Address of the StandardBridge on this chain.\n */\n address public immutable BRIDGE;\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer\n * OptimismMintableERC20Created event. We recommend relying on that event instead.\n *\n * @param remoteToken Address of the token on the remote chain.\n * @param localToken Address of the created token on the local chain.\n */\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n\n /**\n * @notice Emitted whenever a new OptimismMintableERC20 is created.\n *\n * @param localToken Address of the created token on the local chain.\n * @param remoteToken Address of the corresponding token on the remote chain.\n * @param deployer Address of the account that deployed the token.\n */\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @notice The semver MUST be bumped any time that there is a change in\n * the OptimismMintableERC20 token contract since this contract\n * is responsible for deploying OptimismMintableERC20 contracts.\n *\n * @param _bridge Address of the StandardBridge on this chain.\n */\n constructor(address _bridge) Semver(1, 1, 0) {\n BRIDGE = _bridge;\n }\n\n /**\n * @custom:legacy\n * @notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the\n * newer createOptimismMintableERC20 function, which has a more intuitive name.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createStandardL2Token(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) external returns (address) {\n return createOptimismMintableERC20(_remoteToken, _name, _symbol);\n }\n\n /**\n * @notice Creates an instance of the OptimismMintableERC20 contract.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createOptimismMintableERC20(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) public returns (address) {\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC20Factory: must provide remote token address\"\n );\n\n address localToken = address(\n new OptimismMintableERC20(BRIDGE, _remoteToken, _name, _symbol)\n );\n\n // Emit the old event too for legacy support.\n emit StandardL2TokenCreated(_remoteToken, localToken);\n\n // Emit the updated event. The arguments here differ from the legacy event, but\n // are consistent with the ordering used in StandardBridge events.\n emit OptimismMintableERC20Created(localToken, _remoteToken, msg.sender);\n\n return localToken;\n }\n}\n" - }, - "contracts/universal/OptimismMintableERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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\";\nimport { Semver } from \"../universal/Semver.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, Semver {\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n uint256 public immutable REMOTE_CHAIN_ID;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable REMOTE_TOKEN;\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 * @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 * @custom:semver 1.0.0\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) Semver(1, 0, 0) {\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 REMOTE_CHAIN_ID = _remoteChainId;\n REMOTE_TOKEN = _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 * @inheritdoc IOptimismMintableERC721\n */\n function remoteChainId() external view returns (uint256) {\n return REMOTE_CHAIN_ID;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function remoteToken() external view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function bridge() external view returns (address) {\n return BRIDGE;\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" - }, - "contracts/universal/OptimismMintableERC721Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\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 {\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 REMOTE_CHAIN_ID;\n\n /**\n * @notice Tracks addresses created by this factory.\n */\n mapping(address => bool) public isOptimismMintableERC721;\n\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 * @custom:semver 1.1.0\n * @notice The semver MUST be bumped any time that there is a change in\n * the OptimismMintableERC721 token contract since this contract\n * is responsible for deploying OptimismMintableERC721 contracts.\n *\n * @param _bridge Address of the ERC721 bridge on this network.\n * @param _remoteChainId Chain ID for the remote network.\n */\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 1, 0) {\n BRIDGE = _bridge;\n REMOTE_CHAIN_ID = _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, REMOTE_CHAIN_ID, _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/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" - }, - "contracts/universal/ProxyAdmin.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.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 Ownable {\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 * @notice A mapping of proxy types, used for backwards compatibility.\n */\n mapping(address => ProxyType) public proxyType;\n\n /**\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 * @notice The address of the address manager, this is required to manage the\n * ResolvedDelegateProxy type.\n */\n AddressManager public addressManager;\n\n /**\n * @notice A legacy upgrading indicator used by the old Chugsplash Proxy.\n */\n bool internal upgrading;\n\n /**\n * @param _owner Address of the initial owner of this contract.\n */\n constructor(address _owner) Ownable() {\n _transferOwnership(_owner);\n }\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 * @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 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.\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 /**\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" - }, - "contracts/universal/Semver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 uint256 private immutable MAJOR_VERSION;\n\n /**\n * @notice Contract version number (minor).\n */\n uint256 private immutable MINOR_VERSION;\n\n /**\n * @notice Contract version number (patch).\n */\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" - }, - "contracts/universal/StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { IOptimismMintableERC20, ILegacyMintableERC20 } from \"./IOptimismMintableERC20.sol\";\nimport { CrossDomainMessenger } from \"./CrossDomainMessenger.sol\";\nimport { OptimismMintableERC20 } from \"./OptimismMintableERC20.sol\";\n\n/**\n * @custom:upgradeable\n * @title StandardBridge\n * @notice StandardBridge is a base contract for the L1 and L2 standard ERC20 bridges. It handles\n * the core bridging logic, including escrowing tokens that are native to the local chain\n * and minting/burning tokens that are native to the remote chain.\n */\nabstract contract StandardBridge {\n using SafeERC20 for IERC20;\n\n /**\n * @notice The L2 gas limit set when eth is depoisited using the receive() function.\n */\n uint32 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 200_000;\n\n /**\n * @notice Messenger contract on this domain.\n */\n CrossDomainMessenger public immutable MESSENGER;\n\n /**\n * @notice Corresponding bridge on the other domain.\n */\n StandardBridge public immutable OTHER_BRIDGE;\n\n /**\n * @custom:legacy\n * @custom:spacer messenger\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_0_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer l2TokenBridge\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_1_0_20;\n\n /**\n * @notice Mapping that stores deposits for a given pair of local and remote tokens.\n */\n mapping(address => mapping(address => uint256)) public deposits;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n * A gap size of 47 was chosen here, so that the first slot used in a child contract\n * would be a multiple of 50.\n */\n uint256[47] private __gap;\n\n /**\n * @notice Emitted when an ETH bridge is initiated to the other chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ETH bridge is finalized on this chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is initiated to the other chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is finalized on this chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Only allow EOAs to call the functions. Note that this is not safe against contracts\n * calling code within their constructors, but also doesn't really matter since we're\n * just trying to prevent users accidentally depositing with smart contract wallets.\n */\n modifier onlyEOA() {\n require(\n !Address.isContract(msg.sender),\n \"StandardBridge: function can only be called from an EOA\"\n );\n _;\n }\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) &&\n MESSENGER.xDomainMessageSender() == address(OTHER_BRIDGE),\n \"StandardBridge: function can only be called from the other bridge\"\n );\n _;\n }\n\n /**\n * @param _messenger Address of CrossDomainMessenger on this network.\n * @param _otherBridge Address of the other StandardBridge contract.\n */\n constructor(address payable _messenger, address payable _otherBridge) {\n MESSENGER = CrossDomainMessenger(_messenger);\n OTHER_BRIDGE = StandardBridge(_otherBridge);\n }\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n * Must be implemented by contracts that inherit.\n */\n receive() external payable virtual;\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @notice Sends ETH to the sender's address on the other chain.\n *\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETH(uint32 _minGasLimit, bytes calldata _extraData) public payable onlyEOA {\n _initiateBridgeETH(msg.sender, msg.sender, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a\n * smart contract and the call fails, the ETH will be temporarily locked in the\n * StandardBridge on the other chain until the call is replayed. If the call cannot be\n * replayed with any amount of gas (call always reverts), then the ETH will be\n * permanently locked in the StandardBridge on the other chain. ETH will also\n * be locked if the receiver is the other bridge, because finalizeBridgeETH will revert\n * in that case.\n *\n * @param _to Address of the receiver.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public payable {\n _initiateBridgeETH(msg.sender, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ERC20 tokens to the sender's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20(\n address _localToken,\n address _remoteToken,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual onlyEOA {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Finalizes an ETH bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public payable onlyOtherBridge {\n require(msg.value == _amount, \"StandardBridge: amount sent does not match amount required\");\n require(_to != address(this), \"StandardBridge: cannot send to self\");\n require(_to != address(MESSENGER), \"StandardBridge: cannot send to messenger\");\n\n // Emit the correct events. By default this will be _amount, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n\n bool success = SafeCall.call(_to, gasleft(), _amount, hex\"\");\n require(success, \"StandardBridge: ETH transfer failed\");\n }\n\n /**\n * @notice Finalizes an ERC20 bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public onlyOtherBridge {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).mint(_to, _amount);\n } else {\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] - _amount;\n IERC20(_localToken).safeTransfer(_to, _amount);\n }\n\n // Emit the correct events. By default this will be ERC20BridgeFinalized, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Initiates a bridge of ETH through the CrossDomainMessenger.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n require(\n msg.value == _amount,\n \"StandardBridge: bridging ETH must include sufficient ETH value\"\n );\n\n // Emit the correct events. By default this will be _amount, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage{ value: _amount }(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeETH.selector,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).burn(_from, _amount);\n } else {\n IERC20(_localToken).safeTransferFrom(_from, address(this), _amount);\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount;\n }\n\n // Emit the correct events. By default this will be ERC20BridgeInitiated, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeERC20.selector,\n // Because this call will be executed on the remote chain, we reverse the order of\n // the remote and local token addresses relative to their order in the\n // finalizeBridgeERC20 function.\n _remoteToken,\n _localToken,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Checks if a given address is an OptimismMintableERC20. Not perfect, but good enough.\n * Just the way we like it.\n *\n * @param _token Address of the token to check.\n *\n * @return True if the token is an OptimismMintableERC20.\n */\n function _isOptimismMintableERC20(address _token) internal view returns (bool) {\n return\n ERC165Checker.supportsInterface(_token, type(ILegacyMintableERC20).interfaceId) ||\n ERC165Checker.supportsInterface(_token, type(IOptimismMintableERC20).interfaceId);\n }\n\n /**\n * @notice Checks if the \"other token\" is the correct pair token for the OptimismMintableERC20.\n * Calls can be saved in the future by combining this logic with\n * `_isOptimismMintableERC20`.\n *\n * @param _mintableToken OptimismMintableERC20 to check against.\n * @param _otherToken Pair token to check.\n *\n * @return True if the other token is the correct pair token for the OptimismMintableERC20.\n */\n function _isCorrectTokenPair(address _mintableToken, address _otherToken)\n internal\n view\n returns (bool)\n {\n if (\n ERC165Checker.supportsInterface(_mintableToken, type(ILegacyMintableERC20).interfaceId)\n ) {\n return _otherToken == ILegacyMintableERC20(_mintableToken).l1Token();\n } else {\n return _otherToken == IOptimismMintableERC20(_mintableToken).remoteToken();\n }\n }\n\n /** @notice Emits the ETHBridgeInitiated event and if necessary the appropriate legacy event\n * when an ETH bridge is finalized on this chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ETHBridgeFinalized and if necessary the appropriate legacy event when an\n * ETH bridge is finalized on this chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ERC20BridgeInitiated event and if necessary the appropriate legacy\n * event when an ERC20 bridge is initiated to the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the ERC20 on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ERC20BridgeFinalized event and if necessary the appropriate legacy\n * event when an ERC20 bridge is initiated to the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the ERC20 on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/vendor/AddressAliasHelper.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npragma solidity ^0.8.0;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n unchecked {\n l2Address = address(uint160(l1Address) + offset);\n }\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n unchecked {\n l1Address = address(uint160(l2Address) - offset);\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/access/Ownable.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/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 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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/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/Address.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) || (!Address.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" - }, - "node_modules/@openzeppelin/contracts/security/ReentrancyGuard.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\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 ReentrancyGuard {\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 constructor() {\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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, allowance(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 = allowance(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 `from` to `to`.\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 Updates `owner` s allowance for `spender` based on spent `amount`.\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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 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 /**\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (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 constant _PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n /**\n * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\n * However, to ensure consistency with the upgradeable transpiler, we will continue\n * to reserve a slot.\n * @custom:oz-renamed-from _PERMIT_TYPEHASH\n */\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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: address zero is not a valid owner\");\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: invalid token ID\");\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 _requireMinted(tokenId);\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 token 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 _requireMinted(tokenId);\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: caller is not token 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: caller is not token 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 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 an {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 an {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 Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\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 /// @solidity memory-safe-assembly\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Address.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 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 /// @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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\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 /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.3) (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 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 /// @solidity memory-safe-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 {\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.2) (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 // prepare call\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n\n // perform static call\n bool success;\n uint256 returnSize;\n uint256 returnValue;\n assembly {\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\n returnSize := returndatasize()\n returnValue := mload(0x00)\n }\n\n return success && returnSize >= 0x20 && returnValue > 0;\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\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 == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`.\n // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.\n // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.\n // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a\n // good first aproximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1;\n uint256 x = a;\n if (x >> 128 > 0) {\n x >>= 128;\n result <<= 64;\n }\n if (x >> 64 > 0) {\n x >>= 64;\n result <<= 32;\n }\n if (x >> 32 > 0) {\n x >>= 32;\n result <<= 16;\n }\n if (x >> 16 > 0) {\n x >>= 16;\n result <<= 8;\n }\n if (x >> 8 > 0) {\n x >>= 8;\n result <<= 4;\n }\n if (x >> 4 > 0) {\n x >>= 4;\n result <<= 2;\n }\n if (x >> 2 > 0) {\n result <<= 1;\n }\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n uint256 result = sqrt(a);\n if (rounding == Rounding.Up && result * result < a) {\n result += 1;\n }\n return result;\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\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 * _Available since v4.2._\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 uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(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 * _Available since v2.5._\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 uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(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 * _Available since v4.2._\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 uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(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 * _Available since v2.5._\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 uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(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 * _Available since v2.5._\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 uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(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 * _Available since v2.5._\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 * _Available since v2.5._\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 * _Available since v3.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 int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248) {\n require(value >= type(int248).min && value <= type(int248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return int248(value);\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240) {\n require(value >= type(int240).min && value <= type(int240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return int240(value);\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232) {\n require(value >= type(int232).min && value <= type(int232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return int232(value);\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224) {\n require(value >= type(int224).min && value <= type(int224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return int224(value);\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216) {\n require(value >= type(int216).min && value <= type(int216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return int216(value);\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208) {\n require(value >= type(int208).min && value <= type(int208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return int208(value);\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200) {\n require(value >= type(int200).min && value <= type(int200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return int200(value);\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192) {\n require(value >= type(int192).min && value <= type(int192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return int192(value);\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184) {\n require(value >= type(int184).min && value <= type(int184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return int184(value);\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176) {\n require(value >= type(int176).min && value <= type(int176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return int176(value);\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168) {\n require(value >= type(int168).min && value <= type(int168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return int168(value);\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160) {\n require(value >= type(int160).min && value <= type(int160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return int160(value);\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152) {\n require(value >= type(int152).min && value <= type(int152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return int152(value);\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144) {\n require(value >= type(int144).min && value <= type(int144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return int144(value);\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136) {\n require(value >= type(int136).min && value <= type(int136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return int136(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 int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120) {\n require(value >= type(int120).min && value <= type(int120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return int120(value);\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112) {\n require(value >= type(int112).min && value <= type(int112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return int112(value);\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104) {\n require(value >= type(int104).min && value <= type(int104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return int104(value);\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96) {\n require(value >= type(int96).min && value <= type(int96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return int96(value);\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88) {\n require(value >= type(int88).min && value <= type(int88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return int88(value);\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80) {\n require(value >= type(int80).min && value <= type(int80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return int80(value);\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72) {\n require(value >= type(int72).min && value <= type(int72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return int72(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 int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56) {\n require(value >= type(int56).min && value <= type(int56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return int56(value);\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48) {\n require(value >= type(int48).min && value <= type(int48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return int48(value);\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40) {\n require(value >= type(int40).min && value <= type(int40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return int40(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 int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24) {\n require(value >= type(int24).min && value <= type(int24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return int24(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 * _Available since v3.0._\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" - }, - "node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@rari-capital/solmate/src/utils/Bytes32AddressLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Library for converting between addresses and bytes32 values.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/Bytes32AddressLib.sol)\nlibrary Bytes32AddressLib {\n function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n function fillLast12Bytes(address addressValue) internal pure returns (bytes32) {\n return bytes32(bytes20(addressValue));\n }\n}\n" - }, - "node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)\nlibrary FixedPointMathLib {\n /*//////////////////////////////////////////////////////////////\n SIMPLIFIED FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n }\n\n function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n }\n\n function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n }\n\n function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n }\n\n function powWad(int256 x, int256 y) internal pure returns (int256) {\n // Equivalent to x to the power of y because x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)\n return expWad((lnWad(x) * y) / int256(WAD)); // Using ln(x) means x must be greater than 0.\n }\n\n function expWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n // When the result is < 0.5 we return zero. This happens when\n // x <= floor(log(0.5e18) * 1e18) ~ -42e18\n if (x <= -42139678854452767551) return 0;\n\n // When the result is > (2**255 - 1) / 1e18 we can not represent it as an\n // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.\n if (x >= 135305999368893231589) revert(\"EXP_OVERFLOW\");\n\n // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96\n // for more intermediate precision and a binary basis. This base conversion\n // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.\n x = (x << 78) / 5**18;\n\n // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers\n // of two such that exp(x) = exp(x') * 2**k, where k is an integer.\n // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).\n int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96;\n x = x - k * 54916777467707473351141471128;\n\n // k is in the range [-61, 195].\n\n // Evaluate using a (6, 7)-term rational approximation.\n // p is made monic, we'll multiply by a scale factor later.\n int256 y = x + 1346386616545796478920950773328;\n y = ((y * x) >> 96) + 57155421227552351082224309758442;\n int256 p = y + x - 94201549194550492254356042504812;\n p = ((p * y) >> 96) + 28719021644029726153956944680412240;\n p = p * x + (4385272521454847904659076985693276 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n int256 q = x - 2855989394907223263936484059900;\n q = ((q * x) >> 96) + 50020603652535783019961831881945;\n q = ((q * x) >> 96) - 533845033583426703283633433725380;\n q = ((q * x) >> 96) + 3604857256930695427073651918091429;\n q = ((q * x) >> 96) - 14423608567350463180887372962807573;\n q = ((q * x) >> 96) + 26449188498355588339934803723976023;\n\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial won't have zeros in the domain as all its roots are complex.\n // No scaling is necessary because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r should be in the range (0.09, 0.25) * 2**96.\n\n // We now need to multiply r by:\n // * the scale factor s = ~6.031367120.\n // * the 2**k factor from the range reduction.\n // * the 1e18 / 2**96 factor for base conversion.\n // We do this all at once, with an intermediate result in 2**213\n // basis, so the final right shift is always by a positive amount.\n r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k));\n }\n }\n\n function lnWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n require(x > 0, \"UNDEFINED\");\n\n // We want to convert x from 10**18 fixed point to 2**96 fixed point.\n // We do this by multiplying by 2**96 / 10**18. But since\n // ln(x * C) = ln(x) + ln(C), we can simply do nothing here\n // and add ln(2**96 / 10**18) at the end.\n\n // Reduce range of x to (1, 2) * 2**96\n // ln(2^k * x) = k * ln(2) + ln(x)\n int256 k = int256(log2(uint256(x))) - 96;\n x <<= uint256(159 - k);\n x = int256(uint256(x) >> 159);\n\n // Evaluate using a (8, 8)-term rational approximation.\n // p is made monic, we will multiply by a scale factor later.\n int256 p = x + 3273285459638523848632254066296;\n p = ((p * x) >> 96) + 24828157081833163892658089445524;\n p = ((p * x) >> 96) + 43456485725739037958740375743393;\n p = ((p * x) >> 96) - 11111509109440967052023855526967;\n p = ((p * x) >> 96) - 45023709667254063763336534515857;\n p = ((p * x) >> 96) - 14706773417378608786704636184526;\n p = p * x - (795164235651350426258249787498 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n // q is monic by convention.\n int256 q = x + 5573035233440673466300451813936;\n q = ((q * x) >> 96) + 71694874799317883764090561454958;\n q = ((q * x) >> 96) + 283447036172924575727196451306956;\n q = ((q * x) >> 96) + 401686690394027663651624208769553;\n q = ((q * x) >> 96) + 204048457590392012362485061816622;\n q = ((q * x) >> 96) + 31853899698501571402653359427138;\n q = ((q * x) >> 96) + 909429971244387300277376558375;\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial is known not to have zeros in the domain.\n // No scaling required because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r is in the range (0, 0.125) * 2**96\n\n // Finalization, we need to:\n // * multiply by the scale factor s = 5.549…\n // * add ln(2**96 / 10**18)\n // * add k * ln(2)\n // * multiply by 10**18 / 2**96 = 5**18 >> 78\n\n // mul s * 5e18 * 2**96, base is now 5**18 * 2**192\n r *= 1677202110996718588342820967067443963516166;\n // add ln(2) * k * 5e18 * 2**192\n r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;\n // add ln(2**96 / 10**18) * 5e18 * 2**192\n r += 600920179829731861736702779321621459595472258049074101567377883020018308;\n // base conversion: mul 2**18 / 2**192\n r >>= 174;\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n LOW LEVEL FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function mulDivDown(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // Divide z by the denominator.\n z := div(z, denominator)\n }\n }\n\n function mulDivUp(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // First, divide z - 1 by the denominator and add 1.\n // We allow z - 1 to underflow if z is 0, because we multiply the\n // end result by 0 if z is zero, ensuring we return 0 if z is zero.\n z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))\n }\n }\n\n function rpow(\n uint256 x,\n uint256 n,\n uint256 scalar\n ) internal pure returns (uint256 z) {\n assembly {\n switch x\n case 0 {\n switch n\n case 0 {\n // 0 ** 0 = 1\n z := scalar\n }\n default {\n // 0 ** n = 0\n z := 0\n }\n }\n default {\n switch mod(n, 2)\n case 0 {\n // If n is even, store scalar in z for now.\n z := scalar\n }\n default {\n // If n is odd, store x in z for now.\n z := x\n }\n\n // Shifting right by 1 is like dividing by 2.\n let half := shr(1, scalar)\n\n for {\n // Shift n right by 1 before looping to halve it.\n n := shr(1, n)\n } n {\n // Shift n right by 1 each iteration to halve it.\n n := shr(1, n)\n } {\n // Revert immediately if x ** 2 would overflow.\n // Equivalent to iszero(eq(div(xx, x), x)) here.\n if shr(128, x) {\n revert(0, 0)\n }\n\n // Store x squared.\n let xx := mul(x, x)\n\n // Round to the nearest number.\n let xxRound := add(xx, half)\n\n // Revert if xx + half overflowed.\n if lt(xxRound, xx) {\n revert(0, 0)\n }\n\n // Set x to scaled xxRound.\n x := div(xxRound, scalar)\n\n // If n is even:\n if mod(n, 2) {\n // Compute z * x.\n let zx := mul(z, x)\n\n // If z * x overflowed:\n if iszero(eq(div(zx, x), z)) {\n // Revert if x is non-zero.\n if iszero(iszero(x)) {\n revert(0, 0)\n }\n }\n\n // Round to the nearest number.\n let zxRound := add(zx, half)\n\n // Revert if zx + half overflowed.\n if lt(zxRound, zx) {\n revert(0, 0)\n }\n\n // Return properly scaled zxRound.\n z := div(zxRound, scalar)\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n GENERAL NUMBER UTILITIES\n //////////////////////////////////////////////////////////////*/\n\n function sqrt(uint256 x) internal pure returns (uint256 z) {\n assembly {\n let y := x // We start y at x, which will help us make our initial estimate.\n\n z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n // We check y >= 2^(k + 8) but shift right by k bits\n // each branch to ensure that if x >= 256, then y >= 256.\n if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n y := shr(128, y)\n z := shl(64, z)\n }\n if iszero(lt(y, 0x1000000000000000000)) {\n y := shr(64, y)\n z := shl(32, z)\n }\n if iszero(lt(y, 0x10000000000)) {\n y := shr(32, y)\n z := shl(16, z)\n }\n if iszero(lt(y, 0x1000000)) {\n y := shr(16, y)\n z := shl(8, z)\n }\n\n // Goal was to get z*z*y within a small factor of x. More iterations could\n // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n // There is no overflow risk here since y < 2^136 after the first branch above.\n z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n\n // If x+1 is a perfect square, the Babylonian method cycles between\n // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n z := sub(z, lt(div(x, z), z))\n }\n }\n\n function log2(uint256 x) internal pure returns (uint256 r) {\n require(x > 0, \"UNDEFINED\");\n\n assembly {\n r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n r := or(r, shl(4, lt(0xffff, shr(r, x))))\n r := or(r, shl(3, lt(0xff, shr(r, x))))\n r := or(r, shl(2, lt(0xf, shr(r, x))))\n r := or(r, shl(1, lt(0x3, shr(r, x))))\n r := or(r, lt(0x1, shr(r, x)))\n }\n }\n}\n" - }, - "node_modules/ds-test/src/test.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see .\n\npragma solidity >=0.5.0;\n\ncontract DSTest {\n event log (string);\n event logs (bytes);\n\n event log_address (address);\n event log_bytes32 (bytes32);\n event log_int (int);\n event log_uint (uint);\n event log_bytes (bytes);\n event log_string (string);\n\n event log_named_address (string key, address val);\n event log_named_bytes32 (string key, bytes32 val);\n event log_named_decimal_int (string key, int val, uint decimals);\n event log_named_decimal_uint (string key, uint val, uint decimals);\n event log_named_int (string key, int val);\n event log_named_uint (string key, uint val);\n event log_named_bytes (string key, bytes val);\n event log_named_string (string key, string val);\n\n bool public IS_TEST = true;\n bool private _failed;\n\n address constant HEVM_ADDRESS =\n address(bytes20(uint160(uint256(keccak256('hevm cheat code')))));\n\n modifier mayRevert() { _; }\n modifier testopts(string memory) { _; }\n\n function failed() public returns (bool) {\n if (_failed) {\n return _failed;\n } else {\n bool globalFailed = false;\n if (hasHEVMContext()) {\n (, bytes memory retdata) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"load(address,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"))\n )\n );\n globalFailed = abi.decode(retdata, (bool));\n }\n return globalFailed;\n }\n } \n\n function fail() internal {\n if (hasHEVMContext()) {\n (bool status, ) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"store(address,bytes32,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"), bytes32(uint256(0x01)))\n )\n );\n status; // Silence compiler warnings\n }\n _failed = true;\n }\n\n function hasHEVMContext() internal view returns (bool) {\n uint256 hevmCodeSize = 0;\n assembly {\n hevmCodeSize := extcodesize(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D)\n }\n return hevmCodeSize > 0;\n }\n\n modifier logs_gas() {\n uint startGas = gasleft();\n _;\n uint endGas = gasleft();\n emit log_named_uint(\"gas\", startGas - endGas);\n }\n\n function assertTrue(bool condition) internal {\n if (!condition) {\n emit log(\"Error: Assertion Failed\");\n fail();\n }\n }\n\n function assertTrue(bool condition, string memory err) internal {\n if (!condition) {\n emit log_named_string(\"Error\", err);\n assertTrue(condition);\n }\n }\n\n function assertEq(address a, address b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [address]\");\n emit log_named_address(\" Expected\", b);\n emit log_named_address(\" Actual\", a);\n fail();\n }\n }\n function assertEq(address a, address b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes32 a, bytes32 b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bytes32]\");\n emit log_named_bytes32(\" Expected\", b);\n emit log_named_bytes32(\" Actual\", a);\n fail();\n }\n }\n function assertEq(bytes32 a, bytes32 b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq32(bytes32 a, bytes32 b) internal {\n assertEq(a, b);\n }\n function assertEq32(bytes32 a, bytes32 b, string memory err) internal {\n assertEq(a, b, err);\n }\n\n function assertEq(int a, int b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [int]\");\n emit log_named_int(\" Expected\", b);\n emit log_named_int(\" Actual\", a);\n fail();\n }\n }\n function assertEq(int a, int b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq(uint a, uint b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [uint]\");\n emit log_named_uint(\" Expected\", b);\n emit log_named_uint(\" Actual\", a);\n fail();\n }\n }\n function assertEq(uint a, uint b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEqDecimal(int a, int b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Expected\", b, decimals);\n emit log_named_decimal_int(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Expected\", b, decimals);\n emit log_named_decimal_uint(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n\n function assertGt(uint a, uint b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGt(uint a, uint b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGt(int a, int b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGt(int a, int b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGtDecimal(int a, int b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n\n function assertGe(uint a, uint b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGe(uint a, uint b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGe(int a, int b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGe(int a, int b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGeDecimal(int a, int b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertLt(uint a, uint b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLt(uint a, uint b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLt(int a, int b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLt(int a, int b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLtDecimal(int a, int b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n\n function assertLe(uint a, uint b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLe(uint a, uint b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLe(int a, int b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLe(int a, int b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLeDecimal(int a, int b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLeDecimal(a, b, decimals);\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertEq(string memory a, string memory b) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log(\"Error: a == b not satisfied [string]\");\n emit log_named_string(\" Expected\", b);\n emit log_named_string(\" Actual\", a);\n fail();\n }\n }\n function assertEq(string memory a, string memory b, string memory err) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function checkEq0(bytes memory a, bytes memory b) internal pure returns (bool ok) {\n ok = true;\n if (a.length == b.length) {\n for (uint i = 0; i < a.length; i++) {\n if (a[i] != b[i]) {\n ok = false;\n }\n }\n } else {\n ok = false;\n }\n }\n function assertEq0(bytes memory a, bytes memory b) internal {\n if (!checkEq0(a, b)) {\n emit log(\"Error: a == b not satisfied [bytes]\");\n emit log_named_bytes(\" Expected\", b);\n emit log_named_bytes(\" Actual\", a);\n fail();\n }\n }\n function assertEq0(bytes memory a, bytes memory b, string memory err) internal {\n if (!checkEq0(a, b)) {\n emit log_named_string(\"Error\", err);\n assertEq0(a, b);\n }\n }\n}\n" - }, - "node_modules/forge-std/src/Base.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {StdStorage} from \"./StdStorage.sol\";\nimport {Vm, VmSafe} from \"./Vm.sol\";\n\nabstract contract CommonBase {\n // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.\n address internal constant VM_ADDRESS = address(uint160(uint256(keccak256(\"hevm cheat code\"))));\n // console.sol and console2.sol work by executing a staticcall to this address.\n address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;\n // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38.\n address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256(\"foundry default caller\"))));\n // Address of the test contract, deployed by the DEFAULT_SENDER.\n address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;\n // Deterministic deployment address of the Multicall3 contract.\n address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11;\n\n uint256 internal constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n Vm internal constant vm = Vm(VM_ADDRESS);\n StdStorage internal stdstore;\n}\n\nabstract contract TestBase is CommonBase {}\n\nabstract contract ScriptBase is CommonBase {\n // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.\n address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;\n\n VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);\n}\n" - }, - "node_modules/forge-std/src/StdAssertions.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {DSTest} from \"ds-test/test.sol\";\nimport {stdMath} from \"./StdMath.sol\";\n\nabstract contract StdAssertions is DSTest {\n event log_array(uint256[] val);\n event log_array(int256[] val);\n event log_array(address[] val);\n event log_named_array(string key, uint256[] val);\n event log_named_array(string key, int256[] val);\n event log_named_array(string key, address[] val);\n\n function fail(string memory err) internal virtual {\n emit log_named_string(\"Error\", err);\n fail();\n }\n\n function assertFalse(bool data) internal virtual {\n assertTrue(!data);\n }\n\n function assertFalse(bool data, string memory err) internal virtual {\n assertTrue(!data, err);\n }\n\n function assertEq(bool a, bool b) internal virtual {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bool]\");\n emit log_named_string(\" Left\", a ? \"true\" : \"false\");\n emit log_named_string(\" Right\", b ? \"true\" : \"false\");\n fail();\n }\n }\n\n function assertEq(bool a, bool b, string memory err) internal virtual {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes memory a, bytes memory b) internal virtual {\n assertEq0(a, b);\n }\n\n function assertEq(bytes memory a, bytes memory b, string memory err) internal virtual {\n assertEq0(a, b, err);\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [uint[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [int[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(address[] memory a, address[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [address[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(address[] memory a, address[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n // Legacy helper\n function assertEqUint(uint256 a, uint256 b) internal virtual {\n assertEq(uint256(a), uint256(b));\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Left\", a);\n emit log_named_uint(\" Right\", b);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_decimal_uint(\" Left\", a, decimals);\n emit log_named_decimal_uint(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max Delta\", maxDelta, decimals);\n emit log_named_decimal_uint(\" Delta\", delta, decimals);\n fail();\n }\n }\n\n function assertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbsDecimal(a, b, maxDelta, decimals);\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Left\", a);\n emit log_named_int(\" Right\", b);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_decimal_int(\" Left\", a, decimals);\n emit log_named_decimal_int(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max Delta\", maxDelta, decimals);\n emit log_named_decimal_uint(\" Delta\", delta, decimals);\n fail();\n }\n }\n\n function assertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbsDecimal(a, b, maxDelta, decimals);\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%\n ) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Left\", a);\n emit log_named_uint(\" Right\", b);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n string memory err\n ) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n\n function assertApproxEqRelDecimal(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n uint256 decimals\n ) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_decimal_uint(\" Left\", a, decimals);\n emit log_named_decimal_uint(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRelDecimal(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n uint256 decimals,\n string memory err\n ) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Left\", a);\n emit log_named_int(\" Right\", b);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta, string memory err) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n\n function assertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_decimal_int(\" Left\", a, decimals);\n emit log_named_decimal_int(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);\n }\n }\n\n function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual {\n assertEqCall(target, callDataA, target, callDataB, true);\n }\n\n function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB)\n internal\n virtual\n {\n assertEqCall(targetA, callDataA, targetB, callDataB, true);\n }\n\n function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData)\n internal\n virtual\n {\n assertEqCall(target, callDataA, target, callDataB, strictRevertData);\n }\n\n function assertEqCall(\n address targetA,\n bytes memory callDataA,\n address targetB,\n bytes memory callDataB,\n bool strictRevertData\n ) internal virtual {\n (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA);\n (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB);\n\n if (successA && successB) {\n assertEq(returnDataA, returnDataB, \"Call return data does not match\");\n }\n\n if (!successA && !successB && strictRevertData) {\n assertEq(returnDataA, returnDataB, \"Call revert data does not match\");\n }\n\n if (!successA && successB) {\n emit log(\"Error: Calls were not equal\");\n emit log_named_bytes(\" Left call revert data\", returnDataA);\n emit log_named_bytes(\" Right call return data\", returnDataB);\n fail();\n }\n\n if (successA && !successB) {\n emit log(\"Error: Calls were not equal\");\n emit log_named_bytes(\" Left call return data\", returnDataA);\n emit log_named_bytes(\" Right call revert data\", returnDataB);\n fail();\n }\n }\n}\n" - }, - "node_modules/forge-std/src/StdChains.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n/**\n * StdChains provides information about EVM compatible chains that can be used in scripts/tests.\n * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are\n * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of\n * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the\n * alias used in this contract, which can be found as the first argument to the\n * `setChainWithDefaultRpcUrl` call in the `initialize` function.\n *\n * There are two main ways to use this contract:\n * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or\n * `setChain(string memory chainAlias, Chain memory chain)`\n * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.\n *\n * The first time either of those are used, chains are initialized with the default set of RPC URLs.\n * This is done in `initialize`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in\n * `defaultRpcUrls`.\n *\n * The `setChain` function is straightforward, and it simply saves off the given chain data.\n *\n * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say\n * we want to retrieve `mainnet`'s RPC URL:\n * - If you haven't set any mainnet chain info with `setChain`, you haven't specified that\n * chain in `foundry.toml` and no env var is set, the default data and RPC URL will be returned.\n * - If you have set a mainnet RPC URL in `foundry.toml` it will return that, if valid (e.g. if\n * a URL is given or if an environment variable is given and that environment variable exists).\n * Otherwise, the default data is returned.\n * - If you specified data with `setChain` it will return that.\n *\n * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults.\n */\nabstract contract StdChains {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private initialized;\n\n struct ChainData {\n string name;\n uint256 chainId;\n string rpcUrl;\n }\n\n struct Chain {\n // The chain name.\n string name;\n // The chain's Chain ID.\n uint256 chainId;\n // The chain's alias. (i.e. what gets specified in `foundry.toml`).\n string chainAlias;\n // A default RPC endpoint for this chain.\n // NOTE: This default RPC URL is included for convenience to facilitate quick tests and\n // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy\n // usage as you will be throttled and this is a disservice to others who need this endpoint.\n string rpcUrl;\n }\n\n // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.\n mapping(string => Chain) private chains;\n // Maps from the chain's alias to it's default RPC URL.\n mapping(string => string) private defaultRpcUrls;\n // Maps from a chain ID to it's alias.\n mapping(uint256 => string) private idToAlias;\n\n bool private fallbackToDefaultRpcUrls = true;\n\n // The RPC URL will be fetched from config or defaultRpcUrls if possible.\n function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {\n require(bytes(chainAlias).length != 0, \"StdChains getChain(string): Chain alias cannot be the empty string.\");\n\n initialize();\n chain = chains[chainAlias];\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(string): Chain with alias \\\"\", chainAlias, \"\\\" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {\n require(chainId != 0, \"StdChains getChain(uint256): Chain ID cannot be 0.\");\n initialize();\n string memory chainAlias = idToAlias[chainId];\n\n chain = chains[chainAlias];\n\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(uint256): Chain with ID \", vm.toString(chainId), \" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n // set chain info, with priority to argument's rpcUrl field.\n function setChain(string memory chainAlias, ChainData memory chain) internal virtual {\n require(\n bytes(chainAlias).length != 0,\n \"StdChains setChain(string,ChainData): Chain alias cannot be the empty string.\"\n );\n\n require(chain.chainId != 0, \"StdChains setChain(string,ChainData): Chain ID cannot be 0.\");\n\n initialize();\n string memory foundAlias = idToAlias[chain.chainId];\n\n require(\n bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)),\n string(\n abi.encodePacked(\n \"StdChains setChain(string,ChainData): Chain ID \",\n vm.toString(chain.chainId),\n \" already used by \\\"\",\n foundAlias,\n \"\\\".\"\n )\n )\n );\n\n uint256 oldChainId = chains[chainAlias].chainId;\n delete idToAlias[oldChainId];\n\n chains[chainAlias] =\n Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});\n idToAlias[chain.chainId] = chainAlias;\n }\n\n // set chain info, with priority to argument's rpcUrl field.\n function setChain(string memory chainAlias, Chain memory chain) internal virtual {\n setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));\n }\n\n function _toUpper(string memory str) private pure returns (string memory) {\n bytes memory strb = bytes(str);\n bytes memory copy = new bytes(strb.length);\n for (uint256 i = 0; i < strb.length; i++) {\n bytes1 b = strb[i];\n if (b >= 0x61 && b <= 0x7A) {\n copy[i] = bytes1(uint8(b) - 32);\n } else {\n copy[i] = b;\n }\n }\n return string(copy);\n }\n\n // lookup rpcUrl, in descending order of priority:\n // current -> config (foundry.toml) -> environment variable -> default\n function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) private returns (Chain memory) {\n if (bytes(chain.rpcUrl).length == 0) {\n try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {\n chain.rpcUrl = configRpcUrl;\n } catch (bytes memory err) {\n string memory envName = string(abi.encodePacked(_toUpper(chainAlias), \"_RPC_URL\"));\n if (fallbackToDefaultRpcUrls) {\n chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]);\n } else {\n chain.rpcUrl = vm.envString(envName);\n }\n // distinguish 'not found' from 'cannot read'\n bytes memory notFoundError =\n abi.encodeWithSignature(\"CheatCodeError\", string(abi.encodePacked(\"invalid rpc url \", chainAlias)));\n if (keccak256(notFoundError) != keccak256(err) || bytes(chain.rpcUrl).length == 0) {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, err), mload(err))\n }\n }\n }\n }\n return chain;\n }\n\n function setFallbackToDefaultRpcUrls(bool useDefault) internal {\n fallbackToDefaultRpcUrls = useDefault;\n }\n\n function initialize() private {\n if (initialized) return;\n\n initialized = true;\n\n // If adding an RPC here, make sure to test the default RPC URL in `testRpcs`\n setChainWithDefaultRpcUrl(\"anvil\", ChainData(\"Anvil\", 31337, \"http://127.0.0.1:8545\"));\n setChainWithDefaultRpcUrl(\n \"mainnet\", ChainData(\"Mainnet\", 1, \"https://mainnet.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\n \"goerli\", ChainData(\"Goerli\", 5, \"https://goerli.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\n \"sepolia\", ChainData(\"Sepolia\", 11155111, \"https://sepolia.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\"optimism\", ChainData(\"Optimism\", 10, \"https://mainnet.optimism.io\"));\n setChainWithDefaultRpcUrl(\"optimism_goerli\", ChainData(\"Optimism Goerli\", 420, \"https://goerli.optimism.io\"));\n setChainWithDefaultRpcUrl(\"arbitrum_one\", ChainData(\"Arbitrum One\", 42161, \"https://arb1.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\n \"arbitrum_one_goerli\", ChainData(\"Arbitrum One Goerli\", 421613, \"https://goerli-rollup.arbitrum.io/rpc\")\n );\n setChainWithDefaultRpcUrl(\"arbitrum_nova\", ChainData(\"Arbitrum Nova\", 42170, \"https://nova.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\"polygon\", ChainData(\"Polygon\", 137, \"https://polygon-rpc.com\"));\n setChainWithDefaultRpcUrl(\n \"polygon_mumbai\", ChainData(\"Polygon Mumbai\", 80001, \"https://rpc-mumbai.maticvigil.com\")\n );\n setChainWithDefaultRpcUrl(\"avalanche\", ChainData(\"Avalanche\", 43114, \"https://api.avax.network/ext/bc/C/rpc\"));\n setChainWithDefaultRpcUrl(\n \"avalanche_fuji\", ChainData(\"Avalanche Fuji\", 43113, \"https://api.avax-test.network/ext/bc/C/rpc\")\n );\n setChainWithDefaultRpcUrl(\n \"bnb_smart_chain\", ChainData(\"BNB Smart Chain\", 56, \"https://bsc-dataseed1.binance.org\")\n );\n setChainWithDefaultRpcUrl(\n \"bnb_smart_chain_testnet\",\n ChainData(\"BNB Smart Chain Testnet\", 97, \"https://rpc.ankr.com/bsc_testnet_chapel\")\n );\n setChainWithDefaultRpcUrl(\"gnosis_chain\", ChainData(\"Gnosis Chain\", 100, \"https://rpc.gnosischain.com\"));\n }\n\n // set chain info, with priority to chainAlias' rpc url in foundry.toml\n function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {\n string memory rpcUrl = chain.rpcUrl;\n defaultRpcUrls[chainAlias] = rpcUrl;\n chain.rpcUrl = \"\";\n setChain(chainAlias, chain);\n chain.rpcUrl = rpcUrl; // restore argument\n }\n}\n" - }, - "node_modules/forge-std/src/StdCheats.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {Vm} from \"./Vm.sol\";\n\nabstract contract StdCheatsSafe {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private gasMeteringOff;\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawTx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n // json value name = function\n string functionSig;\n bytes32 hash;\n // json value name = tx\n RawTx1559Detail txDetail;\n // json value name = type\n string opcode;\n }\n\n struct RawTx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n bytes gas;\n bytes nonce;\n address to;\n bytes txType;\n bytes value;\n }\n\n struct Tx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n bytes32 hash;\n Tx1559Detail txDetail;\n string opcode;\n }\n\n struct Tx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n uint256 gas;\n uint256 nonce;\n address to;\n uint256 txType;\n uint256 value;\n }\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct TxLegacy {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n string hash;\n string opcode;\n TxDetailLegacy transaction;\n }\n\n struct TxDetailLegacy {\n AccessList[] accessList;\n uint256 chainId;\n bytes data;\n address from;\n uint256 gas;\n uint256 gasPrice;\n bytes32 hash;\n uint256 nonce;\n bytes1 opcode;\n bytes32 r;\n bytes32 s;\n uint256 txType;\n address to;\n uint8 v;\n uint256 value;\n }\n\n struct AccessList {\n address accessAddress;\n bytes32[] storageKeys;\n }\n\n // Data structures to parse Receipt objects from the broadcast artifact.\n // The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawReceipt {\n bytes32 blockHash;\n bytes blockNumber;\n address contractAddress;\n bytes cumulativeGasUsed;\n bytes effectiveGasPrice;\n address from;\n bytes gasUsed;\n RawReceiptLog[] logs;\n bytes logsBloom;\n bytes status;\n address to;\n bytes32 transactionHash;\n bytes transactionIndex;\n }\n\n struct Receipt {\n bytes32 blockHash;\n uint256 blockNumber;\n address contractAddress;\n uint256 cumulativeGasUsed;\n uint256 effectiveGasPrice;\n address from;\n uint256 gasUsed;\n ReceiptLog[] logs;\n bytes logsBloom;\n uint256 status;\n address to;\n bytes32 transactionHash;\n uint256 transactionIndex;\n }\n\n // Data structures to parse the entire broadcast artifact, assuming the\n // transactions conform to EIP1559.\n\n struct EIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n Receipt[] receipts;\n uint256 timestamp;\n Tx1559[] transactions;\n TxReturn[] txReturns;\n }\n\n struct RawEIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n RawReceipt[] receipts;\n TxReturn[] txReturns;\n uint256 timestamp;\n RawTx1559[] transactions;\n }\n\n struct RawReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n bytes blockNumber;\n bytes data;\n bytes logIndex;\n bool removed;\n bytes32[] topics;\n bytes32 transactionHash;\n bytes transactionIndex;\n bytes transactionLogIndex;\n }\n\n struct ReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n uint256 blockNumber;\n bytes data;\n uint256 logIndex;\n bytes32[] topics;\n uint256 transactionIndex;\n uint256 transactionLogIndex;\n bool removed;\n }\n\n struct TxReturn {\n string internalType;\n string value;\n }\n\n function assumeNoPrecompiles(address addr) internal virtual {\n // Assembly required since `block.chainid` was introduced in 0.8.0.\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n assumeNoPrecompiles(addr, chainId);\n }\n\n function assumeNoPrecompiles(address addr, uint256 chainId) internal pure virtual {\n // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific\n // address), but the same rationale for excluding them applies so we include those too.\n\n // These should be present on all EVM-compatible chains.\n vm.assume(addr < address(0x1) || addr > address(0x9));\n\n // forgefmt: disable-start\n if (chainId == 10 || chainId == 420) {\n // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21\n vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));\n } else if (chainId == 42161 || chainId == 421613) {\n // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains\n vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));\n } else if (chainId == 43114 || chainId == 43113) {\n // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59\n vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));\n vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));\n vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));\n }\n // forgefmt: disable-end\n }\n\n function readEIP1559ScriptArtifact(string memory path)\n internal\n view\n virtual\n returns (EIP1559ScriptArtifact memory)\n {\n string memory data = vm.readFile(path);\n bytes memory parsedData = vm.parseJson(data);\n RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));\n EIP1559ScriptArtifact memory artifact;\n artifact.libraries = rawArtifact.libraries;\n artifact.path = rawArtifact.path;\n artifact.timestamp = rawArtifact.timestamp;\n artifact.pending = rawArtifact.pending;\n artifact.txReturns = rawArtifact.txReturns;\n artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);\n artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);\n return artifact;\n }\n\n function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {\n Tx1559[] memory txs = new Tx1559[](rawTxs.length);\n for (uint256 i; i < rawTxs.length; i++) {\n txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);\n }\n return txs;\n }\n\n function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {\n Tx1559 memory transaction;\n transaction.arguments = rawTx.arguments;\n transaction.contractName = rawTx.contractName;\n transaction.functionSig = rawTx.functionSig;\n transaction.hash = rawTx.hash;\n transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);\n transaction.opcode = rawTx.opcode;\n return transaction;\n }\n\n function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)\n internal\n pure\n virtual\n returns (Tx1559Detail memory)\n {\n Tx1559Detail memory txDetail;\n txDetail.data = rawDetail.data;\n txDetail.from = rawDetail.from;\n txDetail.to = rawDetail.to;\n txDetail.nonce = _bytesToUint(rawDetail.nonce);\n txDetail.txType = _bytesToUint(rawDetail.txType);\n txDetail.value = _bytesToUint(rawDetail.value);\n txDetail.gas = _bytesToUint(rawDetail.gas);\n txDetail.accessList = rawDetail.accessList;\n return txDetail;\n }\n\n function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".transactions\");\n RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));\n return rawToConvertedEIPTx1559s(rawTxs);\n }\n\n function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".transactions[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));\n return rawToConvertedEIPTx1559(rawTx);\n }\n\n // Analogous to readTransactions, but for receipts.\n function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".receipts\");\n RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));\n return rawToConvertedReceipts(rawReceipts);\n }\n\n function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".receipts[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));\n return rawToConvertedReceipt(rawReceipt);\n }\n\n function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {\n Receipt[] memory receipts = new Receipt[](rawReceipts.length);\n for (uint256 i; i < rawReceipts.length; i++) {\n receipts[i] = rawToConvertedReceipt(rawReceipts[i]);\n }\n return receipts;\n }\n\n function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {\n Receipt memory receipt;\n receipt.blockHash = rawReceipt.blockHash;\n receipt.to = rawReceipt.to;\n receipt.from = rawReceipt.from;\n receipt.contractAddress = rawReceipt.contractAddress;\n receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);\n receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);\n receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);\n receipt.status = _bytesToUint(rawReceipt.status);\n receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);\n receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);\n receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);\n receipt.logsBloom = rawReceipt.logsBloom;\n receipt.transactionHash = rawReceipt.transactionHash;\n return receipt;\n }\n\n function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)\n internal\n pure\n virtual\n returns (ReceiptLog[] memory)\n {\n ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);\n for (uint256 i; i < rawLogs.length; i++) {\n logs[i].logAddress = rawLogs[i].logAddress;\n logs[i].blockHash = rawLogs[i].blockHash;\n logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);\n logs[i].data = rawLogs[i].data;\n logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);\n logs[i].topics = rawLogs[i].topics;\n logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);\n logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);\n logs[i].removed = rawLogs[i].removed;\n }\n return logs;\n }\n\n // Deploy a contract by fetching the contract bytecode from\n // the artifacts directory\n // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`\n function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes): Deployment failed.\");\n }\n\n function deployCode(string memory what) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string): Deployment failed.\");\n }\n\n /// @dev deploy contract with value on construction\n function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes,uint256): Deployment failed.\");\n }\n\n function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,uint256): Deployment failed.\");\n }\n\n // creates a labeled address and the corresponding private key\n function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {\n privateKey = uint256(keccak256(abi.encodePacked(name)));\n addr = vm.addr(privateKey);\n vm.label(addr, name);\n }\n\n // creates a labeled address\n function makeAddr(string memory name) internal virtual returns (address addr) {\n (addr,) = makeAddrAndKey(name);\n }\n\n function deriveRememberKey(string memory mnemonic, uint32 index)\n internal\n virtual\n returns (address who, uint256 privateKey)\n {\n privateKey = vm.deriveKey(mnemonic, index);\n who = vm.rememberKey(privateKey);\n }\n\n function _bytesToUint(bytes memory b) private pure returns (uint256) {\n require(b.length <= 32, \"StdCheats _bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n function isFork() internal view virtual returns (bool status) {\n try vm.activeFork() {\n status = true;\n } catch (bytes memory) {}\n }\n\n modifier skipWhenForking() {\n if (!isFork()) {\n _;\n }\n }\n\n modifier skipWhenNotForking() {\n if (isFork()) {\n _;\n }\n }\n\n modifier noGasMetering() {\n vm.pauseGasMetering();\n // To prevent turning gas monitoring back on with nested functions that use this modifier,\n // we check if gasMetering started in the off position. If it did, we don't want to turn\n // it back on until we exit the top level function that used the modifier\n //\n // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.\n // funcA will have `gasStartedOff` as false, funcB will have it as true,\n // so we only turn metering back on at the end of the funcA\n bool gasStartedOff = gasMeteringOff;\n gasMeteringOff = true;\n\n _;\n\n // if gas metering was on when this modifier was called, turn it back on at the end\n if (!gasStartedOff) {\n gasMeteringOff = false;\n vm.resumeGasMetering();\n }\n }\n\n // a cheat for fuzzing addresses that are payable only\n // see https://github.com/foundry-rs/foundry/issues/3631\n function assumePayable(address addr) internal virtual {\n (bool success,) = payable(addr).call{value: 0}(\"\");\n vm.assume(success);\n }\n}\n\n// Wrappers around cheatcodes to avoid footguns\nabstract contract StdCheats is StdCheatsSafe {\n using stdStorage for StdStorage;\n\n StdStorage private stdstore;\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n // Skip forward or rewind time by the specified number of seconds\n function skip(uint256 time) internal virtual {\n vm.warp(block.timestamp + time);\n }\n\n function rewind(uint256 time) internal virtual {\n vm.warp(block.timestamp - time);\n }\n\n // Setup a prank from an address that has some ether\n function hoax(address msgSender) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.prank(msgSender);\n }\n\n function hoax(address msgSender, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.prank(msgSender);\n }\n\n function hoax(address msgSender, address origin) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.prank(msgSender, origin);\n }\n\n function hoax(address msgSender, address origin, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.prank(msgSender, origin);\n }\n\n // Start perpetual prank from an address that has some ether\n function startHoax(address msgSender) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.startPrank(msgSender);\n }\n\n function startHoax(address msgSender, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.startPrank(msgSender);\n }\n\n // Start perpetual prank from an address that has some ether\n // tx.origin is set to the origin parameter\n function startHoax(address msgSender, address origin) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.startPrank(msgSender, origin);\n }\n\n function startHoax(address msgSender, address origin, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.startPrank(msgSender, origin);\n }\n\n function changePrank(address msgSender) internal virtual {\n vm.stopPrank();\n vm.startPrank(msgSender);\n }\n\n function changePrank(address msgSender, address txOrigin) internal virtual {\n vm.stopPrank();\n vm.startPrank(msgSender, txOrigin);\n }\n\n // The same as Vm's `deal`\n // Use the alternative signature for ERC20 tokens\n function deal(address to, uint256 give) internal virtual {\n vm.deal(to, give);\n }\n\n // Set the balance of an account for any ERC20 token\n // Use the alternative signature to update `totalSupply`\n function deal(address token, address to, uint256 give) internal virtual {\n deal(token, to, give, false);\n }\n\n // Set the balance of an account for any ERC1155 token\n // Use the alternative signature to update `totalSupply`\n function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {\n dealERC1155(token, to, id, give, false);\n }\n\n function deal(address token, address to, uint256 give, bool adjust) internal virtual {\n // get current balance\n (, bytes memory balData) = token.call(abi.encodeWithSelector(0x70a08231, to));\n uint256 prevBal = abi.decode(balData, (uint256));\n\n // update balance\n stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);\n\n // update total supply\n if (adjust) {\n (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0x18160ddd));\n uint256 totSup = abi.decode(totSupData, (uint256));\n if (give < prevBal) {\n totSup -= (prevBal - give);\n } else {\n totSup += (give - prevBal);\n }\n stdstore.target(token).sig(0x18160ddd).checked_write(totSup);\n }\n }\n\n function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {\n // get current balance\n (, bytes memory balData) = token.call(abi.encodeWithSelector(0x00fdd58e, to, id));\n uint256 prevBal = abi.decode(balData, (uint256));\n\n // update balance\n stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);\n\n // update total supply\n if (adjust) {\n (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0xbd85b039, id));\n require(\n totSupData.length != 0,\n \"StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply.\"\n );\n uint256 totSup = abi.decode(totSupData, (uint256));\n if (give < prevBal) {\n totSup -= (prevBal - give);\n } else {\n totSup += (give - prevBal);\n }\n stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);\n }\n }\n\n function dealERC721(address token, address to, uint256 id) internal virtual {\n // check if token id is already minted and the actual owner.\n (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));\n require(successMinted, \"StdCheats deal(address,address,uint,bool): id not minted.\");\n\n // get owner current balance\n (, bytes memory fromBalData) = token.call(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));\n uint256 fromPrevBal = abi.decode(fromBalData, (uint256));\n\n // get new user current balance\n (, bytes memory toBalData) = token.call(abi.encodeWithSelector(0x70a08231, to));\n uint256 toPrevBal = abi.decode(toBalData, (uint256));\n\n // update balances\n stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);\n stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);\n\n // update owner\n stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);\n }\n}\n" - }, - "node_modules/forge-std/src/StdError.sol": { - "content": "// SPDX-License-Identifier: MIT\n// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdError {\n bytes public constant assertionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x01);\n bytes public constant arithmeticError = abi.encodeWithSignature(\"Panic(uint256)\", 0x11);\n bytes public constant divisionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x12);\n bytes public constant enumConversionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x21);\n bytes public constant encodeStorageError = abi.encodeWithSignature(\"Panic(uint256)\", 0x22);\n bytes public constant popError = abi.encodeWithSignature(\"Panic(uint256)\", 0x31);\n bytes public constant indexOOBError = abi.encodeWithSignature(\"Panic(uint256)\", 0x32);\n bytes public constant memOverflowError = abi.encodeWithSignature(\"Panic(uint256)\", 0x41);\n bytes public constant zeroVarError = abi.encodeWithSignature(\"Panic(uint256)\", 0x51);\n}\n" - }, - "node_modules/forge-std/src/StdInvariant.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\ncontract StdInvariant {\n struct FuzzSelector {\n address addr;\n bytes4[] selectors;\n }\n\n address[] private _excludedContracts;\n address[] private _excludedSenders;\n address[] private _targetedContracts;\n address[] private _targetedSenders;\n\n string[] private _excludedArtifacts;\n string[] private _targetedArtifacts;\n\n FuzzSelector[] private _targetedArtifactSelectors;\n FuzzSelector[] private _targetedSelectors;\n\n // Functions for users:\n // These are intended to be called in tests.\n\n function excludeContract(address newExcludedContract_) internal {\n _excludedContracts.push(newExcludedContract_);\n }\n\n function excludeSender(address newExcludedSender_) internal {\n _excludedSenders.push(newExcludedSender_);\n }\n\n function excludeArtifact(string memory newExcludedArtifact_) internal {\n _excludedArtifacts.push(newExcludedArtifact_);\n }\n\n function targetArtifact(string memory newTargetedArtifact_) internal {\n _targetedArtifacts.push(newTargetedArtifact_);\n }\n\n function targetArtifactSelector(FuzzSelector memory newTargetedArtifactSelector_) internal {\n _targetedArtifactSelectors.push(newTargetedArtifactSelector_);\n }\n\n function targetContract(address newTargetedContract_) internal {\n _targetedContracts.push(newTargetedContract_);\n }\n\n function targetSelector(FuzzSelector memory newTargetedSelector_) internal {\n _targetedSelectors.push(newTargetedSelector_);\n }\n\n function targetSender(address newTargetedSender_) internal {\n _targetedSenders.push(newTargetedSender_);\n }\n\n // Functions for forge:\n // These are called by forge to run invariant tests and don't need to be called in tests.\n\n function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) {\n excludedArtifacts_ = _excludedArtifacts;\n }\n\n function excludeContracts() public view returns (address[] memory excludedContracts_) {\n excludedContracts_ = _excludedContracts;\n }\n\n function excludeSenders() public view returns (address[] memory excludedSenders_) {\n excludedSenders_ = _excludedSenders;\n }\n\n function targetArtifacts() public view returns (string[] memory targetedArtifacts_) {\n targetedArtifacts_ = _targetedArtifacts;\n }\n\n function targetArtifactSelectors() public view returns (FuzzSelector[] memory targetedArtifactSelectors_) {\n targetedArtifactSelectors_ = _targetedArtifactSelectors;\n }\n\n function targetContracts() public view returns (address[] memory targetedContracts_) {\n targetedContracts_ = _targetedContracts;\n }\n\n function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) {\n targetedSelectors_ = _targetedSelectors;\n }\n\n function targetSenders() public view returns (address[] memory targetedSenders_) {\n targetedSenders_ = _targetedSenders;\n }\n}\n" - }, - "node_modules/forge-std/src/StdJson.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n// Helpers for parsing and writing JSON files\n// To parse:\n// ```\n// using stdJson for string;\n// string memory json = vm.readFile(\"some_peth\");\n// json.parseUint(\"\");\n// ```\n// To write:\n// ```\n// using stdJson for string;\n// string memory json = \"deploymentArtifact\";\n// Contract contract = new Contract();\n// json.serialize(\"contractAddress\", address(contract));\n// json = json.serialize(\"deploymentTimes\", uint(1));\n// // store the stringified JSON to the 'json' variable we have been using as a key\n// // as we won't need it any longer\n// string memory json2 = \"finalArtifact\";\n// string memory final = json2.serialize(\"depArtifact\", json);\n// final.write(\"\");\n// ```\n\nlibrary stdJson {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {\n return vm.parseJson(json, key);\n }\n\n function readUint(string memory json, string memory key) internal returns (uint256) {\n return vm.parseJsonUint(json, key);\n }\n\n function readUintArray(string memory json, string memory key) internal returns (uint256[] memory) {\n return vm.parseJsonUintArray(json, key);\n }\n\n function readInt(string memory json, string memory key) internal returns (int256) {\n return vm.parseJsonInt(json, key);\n }\n\n function readIntArray(string memory json, string memory key) internal returns (int256[] memory) {\n return vm.parseJsonIntArray(json, key);\n }\n\n function readBytes32(string memory json, string memory key) internal returns (bytes32) {\n return vm.parseJsonBytes32(json, key);\n }\n\n function readBytes32Array(string memory json, string memory key) internal returns (bytes32[] memory) {\n return vm.parseJsonBytes32Array(json, key);\n }\n\n function readString(string memory json, string memory key) internal returns (string memory) {\n return vm.parseJsonString(json, key);\n }\n\n function readStringArray(string memory json, string memory key) internal returns (string[] memory) {\n return vm.parseJsonStringArray(json, key);\n }\n\n function readAddress(string memory json, string memory key) internal returns (address) {\n return vm.parseJsonAddress(json, key);\n }\n\n function readAddressArray(string memory json, string memory key) internal returns (address[] memory) {\n return vm.parseJsonAddressArray(json, key);\n }\n\n function readBool(string memory json, string memory key) internal returns (bool) {\n return vm.parseJsonBool(json, key);\n }\n\n function readBoolArray(string memory json, string memory key) internal returns (bool[] memory) {\n return vm.parseJsonBoolArray(json, key);\n }\n\n function readBytes(string memory json, string memory key) internal returns (bytes memory) {\n return vm.parseJsonBytes(json, key);\n }\n\n function readBytesArray(string memory json, string memory key) internal returns (bytes[] memory) {\n return vm.parseJsonBytesArray(json, key);\n }\n\n function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bool[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function write(string memory jsonKey, string memory path) internal {\n vm.writeJson(jsonKey, path);\n }\n\n function write(string memory jsonKey, string memory path, string memory valueKey) internal {\n vm.writeJson(jsonKey, path, valueKey);\n }\n}\n" - }, - "node_modules/forge-std/src/StdMath.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdMath {\n int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;\n\n function abs(int256 a) internal pure returns (uint256) {\n // Required or it will fail when `a = type(int256).min`\n if (a == INT256_MIN) {\n return 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n }\n\n return uint256(a > 0 ? a : -a);\n }\n\n function delta(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a - b : b - a;\n }\n\n function delta(int256 a, int256 b) internal pure returns (uint256) {\n // a and b are of the same sign\n // this works thanks to two's complement, the left-most bit is the sign bit\n if ((a ^ b) > -1) {\n return delta(abs(a), abs(b));\n }\n\n // a and b are of opposite signs\n return abs(a) + abs(b);\n }\n\n function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n\n return absDelta * 1e18 / b;\n }\n\n function percentDelta(int256 a, int256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n uint256 absB = abs(b);\n\n return absDelta * 1e18 / absB;\n }\n}\n" - }, - "node_modules/forge-std/src/StdStorage.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {Vm} from \"./Vm.sol\";\n\nstruct StdStorage {\n mapping(address => mapping(bytes4 => mapping(bytes32 => uint256))) slots;\n mapping(address => mapping(bytes4 => mapping(bytes32 => bool))) finds;\n bytes32[] _keys;\n bytes4 _sig;\n uint256 _depth;\n address _target;\n bytes32 _set;\n}\n\nlibrary stdStorageSafe {\n event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);\n event WARNING_UninitedSlot(address who, uint256 slot);\n\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return bytes4(keccak256(bytes(sigStr)));\n }\n\n /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against\n // slot complexity:\n // if flat, will be bytes32(uint256(uint));\n // if map, will be keccak256(abi.encode(key, uint(slot)));\n // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));\n // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);\n function find(StdStorage storage self) internal returns (uint256) {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n // calldata to test against\n if (self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n vm.record();\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n (bytes32[] memory reads,) = vm.accesses(address(who));\n if (reads.length == 1) {\n bytes32 curr = vm.load(who, reads[0]);\n if (curr == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[0]));\n }\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[0]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[0]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n } else if (reads.length > 1) {\n for (uint256 i = 0; i < reads.length; i++) {\n bytes32 prev = vm.load(who, reads[i]);\n if (prev == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[i]));\n }\n // store\n vm.store(who, reads[i], bytes32(hex\"1337\"));\n bool success;\n bytes memory rdat;\n {\n (success, rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n if (success && fdat == bytes32(hex\"1337\")) {\n // we found which of the slots is the actual one\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[i]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[i]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n vm.store(who, reads[i], prev);\n break;\n }\n vm.store(who, reads[i], prev);\n }\n } else {\n revert(\"stdStorage find(StdStorage): No storage use detected for target.\");\n }\n\n require(\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))],\n \"stdStorage find(StdStorage): Slot(s) not found.\"\n );\n\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n self._target = _target;\n return self;\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n self._sig = _sig;\n return self;\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n self._sig = sigs(_sig);\n return self;\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n self._keys.push(bytes32(uint256(uint160(who))));\n return self;\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n self._keys.push(bytes32(amt));\n return self;\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n self._keys.push(key);\n return self;\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n self._depth = _depth;\n return self;\n }\n\n function read(StdStorage storage self) private returns (bytes memory) {\n address t = self._target;\n uint256 s = find(self);\n return abi.encode(vm.load(t, bytes32(s)));\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return abi.decode(read(self), (bytes32));\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n int256 v = read_int(self);\n if (v == 0) return false;\n if (v == 1) return true;\n revert(\"stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.\");\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return abi.decode(read(self), (address));\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return abi.decode(read(self), (uint256));\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return abi.decode(read(self), (int256));\n }\n\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n\nlibrary stdStorage {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return stdStorageSafe.sigs(sigStr);\n }\n\n function find(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.find(self);\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n return stdStorageSafe.target(self, _target);\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, who);\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, amt);\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, key);\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n return stdStorageSafe.depth(self, _depth);\n }\n\n function checked_write(StdStorage storage self, address who) internal {\n checked_write(self, bytes32(uint256(uint160(who))));\n }\n\n function checked_write(StdStorage storage self, uint256 amt) internal {\n checked_write(self, bytes32(amt));\n }\n\n function checked_write(StdStorage storage self, bool write) internal {\n bytes32 t;\n /// @solidity memory-safe-assembly\n assembly {\n t := write\n }\n checked_write(self, t);\n }\n\n function checked_write(StdStorage storage self, bytes32 set) internal {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n if (!self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n find(self);\n }\n bytes32 slot = bytes32(self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]);\n\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n bytes32 curr = vm.load(who, slot);\n\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n vm.store(who, slot, set);\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return stdStorageSafe.read_bytes32(self);\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n return stdStorageSafe.read_bool(self);\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return stdStorageSafe.read_address(self);\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.read_uint(self);\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return stdStorageSafe.read_int(self);\n }\n\n // Private function so needs to be copied over\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n // Private function so needs to be copied over\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n" - }, - "node_modules/forge-std/src/StdStyle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nimport {Vm} from \"./Vm.sol\";\n\nlibrary StdStyle {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n string constant RED = \"\\u001b[91m\";\n string constant GREEN = \"\\u001b[92m\";\n string constant YELLOW = \"\\u001b[93m\";\n string constant BLUE = \"\\u001b[94m\";\n string constant MAGENTA = \"\\u001b[95m\";\n string constant CYAN = \"\\u001b[96m\";\n string constant BOLD = \"\\u001b[1m\";\n string constant DIM = \"\\u001b[2m\";\n string constant ITALIC = \"\\u001b[3m\";\n string constant UNDERLINE = \"\\u001b[4m\";\n string constant INVERSE = \"\\u001b[7m\";\n string constant RESET = \"\\u001b[0m\";\n\n function styleConcat(string memory style, string memory self) private pure returns (string memory) {\n return string(abi.encodePacked(style, self, RESET));\n }\n\n function red(string memory self) internal pure returns (string memory) {\n return styleConcat(RED, self);\n }\n\n function red(uint256 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(int256 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(address self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(bool self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function redBytes(bytes memory self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function redBytes32(bytes32 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function green(string memory self) internal pure returns (string memory) {\n return styleConcat(GREEN, self);\n }\n\n function green(uint256 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(int256 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(address self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(bool self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function greenBytes(bytes memory self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function greenBytes32(bytes32 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function yellow(string memory self) internal pure returns (string memory) {\n return styleConcat(YELLOW, self);\n }\n\n function yellow(uint256 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(int256 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(address self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(bool self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellowBytes(bytes memory self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellowBytes32(bytes32 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function blue(string memory self) internal pure returns (string memory) {\n return styleConcat(BLUE, self);\n }\n\n function blue(uint256 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(int256 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(address self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(bool self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blueBytes(bytes memory self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blueBytes32(bytes32 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function magenta(string memory self) internal pure returns (string memory) {\n return styleConcat(MAGENTA, self);\n }\n\n function magenta(uint256 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(int256 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(address self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(bool self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magentaBytes(bytes memory self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magentaBytes32(bytes32 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function cyan(string memory self) internal pure returns (string memory) {\n return styleConcat(CYAN, self);\n }\n\n function cyan(uint256 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(int256 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(address self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(bool self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyanBytes(bytes memory self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyanBytes32(bytes32 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function bold(string memory self) internal pure returns (string memory) {\n return styleConcat(BOLD, self);\n }\n\n function bold(uint256 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(int256 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(address self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(bool self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function boldBytes(bytes memory self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function boldBytes32(bytes32 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function dim(string memory self) internal pure returns (string memory) {\n return styleConcat(DIM, self);\n }\n\n function dim(uint256 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(int256 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(address self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(bool self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dimBytes(bytes memory self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dimBytes32(bytes32 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function italic(string memory self) internal pure returns (string memory) {\n return styleConcat(ITALIC, self);\n }\n\n function italic(uint256 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(int256 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(address self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(bool self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italicBytes(bytes memory self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italicBytes32(bytes32 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function underline(string memory self) internal pure returns (string memory) {\n return styleConcat(UNDERLINE, self);\n }\n\n function underline(uint256 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(int256 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(address self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(bool self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underlineBytes(bytes memory self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underlineBytes32(bytes32 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function inverse(string memory self) internal pure returns (string memory) {\n return styleConcat(INVERSE, self);\n }\n\n function inverse(uint256 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(int256 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(address self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(bool self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverseBytes(bytes memory self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverseBytes32(bytes32 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n}\n" - }, - "node_modules/forge-std/src/StdUtils.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {IMulticall3} from \"./interfaces/IMulticall3.sol\";\n// TODO Remove import.\nimport {VmSafe} from \"./Vm.sol\";\n\nabstract contract StdUtils {\n /*//////////////////////////////////////////////////////////////////////////\n CONSTANTS\n //////////////////////////////////////////////////////////////////////////*/\n\n IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;\n uint256 private constant INT256_MIN_ABS =\n 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n uint256 private constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.\n address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;\n\n /*//////////////////////////////////////////////////////////////////////////\n INTERNAL FUNCTIONS\n //////////////////////////////////////////////////////////////////////////*/\n\n function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {\n require(min <= max, \"StdUtils bound(uint256,uint256,uint256): Max is less than min.\");\n // If x is between min and max, return x directly. This is to ensure that dictionary values\n // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188\n if (x >= min && x <= max) return x;\n\n uint256 size = max - min + 1;\n\n // If the value is 0, 1, 2, 3, warp that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.\n // This helps ensure coverage of the min/max values.\n if (x <= 3 && size > x) return min + x;\n if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);\n\n // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.\n if (x > max) {\n uint256 diff = x - max;\n uint256 rem = diff % size;\n if (rem == 0) return max;\n result = min + rem - 1;\n } else if (x < min) {\n uint256 diff = min - x;\n uint256 rem = diff % size;\n if (rem == 0) return min;\n result = max - rem + 1;\n }\n }\n\n function bound(uint256 x, uint256 min, uint256 max) internal view virtual returns (uint256 result) {\n result = _bound(x, min, max);\n console2_log(\"Bound Result\", result);\n }\n\n function bound(int256 x, int256 min, int256 max) internal view virtual returns (int256 result) {\n require(min <= max, \"StdUtils bound(int256,int256,int256): Max is less than min.\");\n\n // Shifting all int256 values to uint256 to use _bound function. The range of two types are:\n // int256 : -(2**255) ~ (2**255 - 1)\n // uint256: 0 ~ (2**256 - 1)\n // So, add 2**255, INT256_MIN_ABS to the integer values.\n //\n // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.\n // So, use `~uint256(x) + 1` instead.\n uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);\n uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);\n uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);\n\n uint256 y = _bound(_x, _min, _max);\n\n // To move it back to int256 value, subtract INT256_MIN_ABS at here.\n result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);\n console2_log(\"Bound result\", vm.toString(result));\n }\n\n function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {\n require(b.length <= 32, \"StdUtils bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce\n /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)\n function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {\n // forgefmt: disable-start\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))));\n if (nonce <= 0x7f) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))));\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= 2**8 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce))));\n if (nonce <= 2**16 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce))));\n if (nonce <= 2**24 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce))));\n // forgefmt: disable-end\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return addressFromLast20Bytes(\n keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce)))\n );\n }\n\n function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)\n internal\n pure\n virtual\n returns (address)\n {\n return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, initcodeHash)));\n }\n\n /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer\n function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {\n return computeCreate2Address(salt, initCodeHash, CREATE2_FACTORY);\n }\n\n /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments\n /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode\n function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {\n return hashInitCode(creationCode, \"\");\n }\n\n /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2\n /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode\n /// @param args the ABI-encoded arguments to the constructor of C\n function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(creationCode, args));\n }\n\n // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.\n function getTokenBalances(address token, address[] memory addresses)\n internal\n virtual\n returns (uint256[] memory balances)\n {\n uint256 tokenCodeSize;\n assembly {\n tokenCodeSize := extcodesize(token)\n }\n require(tokenCodeSize > 0, \"StdUtils getTokenBalances(address,address[]): Token address is not a contract.\");\n\n // ABI encode the aggregate call to Multicall3.\n uint256 length = addresses.length;\n IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);\n for (uint256 i = 0; i < length; ++i) {\n // 0x70a08231 = bytes4(\"balanceOf(address)\"))\n calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});\n }\n\n // Make the aggregate call.\n (, bytes[] memory returnData) = multicall.aggregate(calls);\n\n // ABI decode the return data and return the balances.\n balances = new uint256[](length);\n for (uint256 i = 0; i < length; ++i) {\n balances[i] = abi.decode(returnData[i], (uint256));\n }\n }\n\n /*//////////////////////////////////////////////////////////////////////////\n PRIVATE FUNCTIONS\n //////////////////////////////////////////////////////////////////////////*/\n\n function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.\n\n function console2_log(string memory p0, uint256 p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n status;\n }\n\n function console2_log(string memory p0, string memory p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n status;\n }\n}\n" - }, - "node_modules/forge-std/src/Test.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\n// 💬 ABOUT\n// Standard Library's default Test\n\n// 🧩 MODULES\nimport {console} from \"./console.sol\";\nimport {console2} from \"./console2.sol\";\nimport {StdAssertions} from \"./StdAssertions.sol\";\nimport {StdChains} from \"./StdChains.sol\";\nimport {StdCheats} from \"./StdCheats.sol\";\nimport {stdError} from \"./StdError.sol\";\nimport {StdInvariant} from \"./StdInvariant.sol\";\nimport {stdJson} from \"./StdJson.sol\";\nimport {stdMath} from \"./StdMath.sol\";\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {StdUtils} from \"./StdUtils.sol\";\nimport {Vm} from \"./Vm.sol\";\nimport {StdStyle} from \"./StdStyle.sol\";\n\n// 📦 BOILERPLATE\nimport {TestBase} from \"./Base.sol\";\nimport {DSTest} from \"ds-test/test.sol\";\n\n// ⭐️ TEST\nabstract contract Test is DSTest, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils, TestBase {\n// Note: IS_TEST() must return true.\n// Note: Must have failure system, https://github.com/dapphub/ds-test/blob/cd98eff28324bfac652e63a239a60632a761790b/src/test.sol#L39-L76.\n}\n" - }, - "node_modules/forge-std/src/Vm.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\n// Cheatcodes are marked as view/pure/none using the following rules:\n// 0. A call's observable behaviour includes its return value, logs, reverts and state writes,\n// 1. If you can influence a later call's observable behaviour, you're neither `view` nor `pure (you are modifying some state be it the EVM, interpreter, filesystem, etc),\n// 2. Otherwise if you can be influenced by an earlier call, or if reading some state, you're `view`,\n// 3. Otherwise you're `pure`.\n\ninterface VmSafe {\n struct Log {\n bytes32[] topics;\n bytes data;\n address emitter;\n }\n\n struct Rpc {\n string key;\n string url;\n }\n\n struct FsMetadata {\n bool isDir;\n bool isSymlink;\n uint256 length;\n bool readOnly;\n uint256 modified;\n uint256 accessed;\n uint256 created;\n }\n\n // Loads a storage slot from an address\n function load(address target, bytes32 slot) external view returns (bytes32 data);\n // Signs data\n function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);\n // Gets the address for a given private key\n function addr(uint256 privateKey) external pure returns (address keyAddr);\n // Gets the nonce of an account\n function getNonce(address account) external view returns (uint64 nonce);\n // Performs a foreign function call via the terminal\n function ffi(string[] calldata commandInput) external returns (bytes memory result);\n // Sets environment variables\n function setEnv(string calldata name, string calldata value) external;\n // Reads environment variables, (name) => (value)\n function envBool(string calldata name) external view returns (bool value);\n function envUint(string calldata name) external view returns (uint256 value);\n function envInt(string calldata name) external view returns (int256 value);\n function envAddress(string calldata name) external view returns (address value);\n function envBytes32(string calldata name) external view returns (bytes32 value);\n function envString(string calldata name) external view returns (string memory value);\n function envBytes(string calldata name) external view returns (bytes memory value);\n // Reads environment variables as arrays\n function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);\n function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);\n function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);\n function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);\n function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);\n function envString(string calldata name, string calldata delim) external view returns (string[] memory value);\n function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);\n // Read environment variables with default value\n function envOr(string calldata name, bool defaultValue) external returns (bool value);\n function envOr(string calldata name, uint256 defaultValue) external returns (uint256 value);\n function envOr(string calldata name, int256 defaultValue) external returns (int256 value);\n function envOr(string calldata name, address defaultValue) external returns (address value);\n function envOr(string calldata name, bytes32 defaultValue) external returns (bytes32 value);\n function envOr(string calldata name, string calldata defaultValue) external returns (string memory value);\n function envOr(string calldata name, bytes calldata defaultValue) external returns (bytes memory value);\n // Read environment variables as arrays with default value\n function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)\n external\n returns (bool[] memory value);\n function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)\n external\n returns (uint256[] memory value);\n function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)\n external\n returns (int256[] memory value);\n function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)\n external\n returns (address[] memory value);\n function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)\n external\n returns (bytes32[] memory value);\n function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)\n external\n returns (string[] memory value);\n function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)\n external\n returns (bytes[] memory value);\n // Records all storage reads and writes\n function record() external;\n // Gets all accessed reads and write slot from a recording session, for a given address\n function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);\n // Gets the _creation_ bytecode from an artifact file. Takes in the relative path to the json file\n function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);\n // Gets the _deployed_ bytecode from an artifact file. Takes in the relative path to the json file\n function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);\n // Labels an address in call traces\n function label(address account, string calldata newLabel) external;\n // Using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain\n function broadcast() external;\n // Has the next call (at this call depth only) create a transaction with the address provided as the sender that can later be signed and sent onchain\n function broadcast(address signer) external;\n // Has the next call (at this call depth only) create a transaction with the private key provided as the sender that can later be signed and sent onchain\n function broadcast(uint256 privateKey) external;\n // Using the address that calls the test contract, has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain\n function startBroadcast() external;\n // Has all subsequent calls (at this call depth only) create transactions with the address provided that can later be signed and sent onchain\n function startBroadcast(address signer) external;\n // Has all subsequent calls (at this call depth only) create transactions with the private key provided that can later be signed and sent onchain\n function startBroadcast(uint256 privateKey) external;\n // Stops collecting onchain transactions\n function stopBroadcast() external;\n // Reads the entire content of file to string\n function readFile(string calldata path) external view returns (string memory data);\n // Reads the entire content of file as binary. Path is relative to the project root.\n function readFileBinary(string calldata path) external view returns (bytes memory data);\n // Get the path of the current project root\n function projectRoot() external view returns (string memory path);\n // Get the metadata for a file/directory\n function fsMetadata(string calldata fileOrDir) external returns (FsMetadata memory metadata);\n // Reads next line of file to string\n function readLine(string calldata path) external view returns (string memory line);\n // Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.\n function writeFile(string calldata path, string calldata data) external;\n // Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.\n // Path is relative to the project root.\n function writeFileBinary(string calldata path, bytes calldata data) external;\n // Writes line to file, creating a file if it does not exist.\n function writeLine(string calldata path, string calldata data) external;\n // Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.\n function closeFile(string calldata path) external;\n // Removes file. This cheatcode will revert in the following situations, but is not limited to just these cases:\n // - Path points to a directory.\n // - The file doesn't exist.\n // - The user lacks permissions to remove the file.\n function removeFile(string calldata path) external;\n // Convert values to a string\n function toString(address value) external pure returns (string memory stringifiedValue);\n function toString(bytes calldata value) external pure returns (string memory stringifiedValue);\n function toString(bytes32 value) external pure returns (string memory stringifiedValue);\n function toString(bool value) external pure returns (string memory stringifiedValue);\n function toString(uint256 value) external pure returns (string memory stringifiedValue);\n function toString(int256 value) external pure returns (string memory stringifiedValue);\n // Convert values from a string\n function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);\n function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);\n function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);\n function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);\n function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);\n function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);\n // Record all the transaction logs\n function recordLogs() external;\n // Gets all the recorded logs\n function getRecordedLogs() external returns (Log[] memory logs);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path m/44'/60'/0'/0/{index}\n function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at {derivationPath}{index}\n function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)\n external\n pure\n returns (uint256 privateKey);\n // Adds a private key to the local forge wallet and returns the address\n function rememberKey(uint256 privateKey) external returns (address keyAddr);\n //\n // parseJson\n //\n // ----\n // In case the returned value is a JSON object, it's encoded as a ABI-encoded tuple. As JSON objects\n // don't have the notion of ordered, but tuples do, they JSON object is encoded with it's fields ordered in\n // ALPHABETICAL order. That means that in order to successfully decode the tuple, we need to define a tuple that\n // encodes the fields in the same order, which is alphabetical. In the case of Solidity structs, they are encoded\n // as tuples, with the attributes in the order in which they are defined.\n // For example: json = { 'a': 1, 'b': 0xa4tb......3xs}\n // a: uint256\n // b: address\n // To decode that json, we need to define a struct or a tuple as follows:\n // struct json = { uint256 a; address b; }\n // If we defined a json struct with the opposite order, meaning placing the address b first, it would try to\n // decode the tuple in that order, and thus fail.\n // ----\n // Given a string of JSON, return it as ABI-encoded\n function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);\n function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);\n\n // The following parseJson cheatcodes will do type coercion, for the type that they indicate.\n // For example, parseJsonUint will coerce all values to a uint256. That includes stringified numbers '12'\n // and hex numbers '0xEF'.\n // Type coercion works ONLY for discrete values or arrays. That means that the key must return a value or array, not\n // a JSON object.\n function parseJsonUint(string calldata, string calldata) external returns (uint256);\n function parseJsonUintArray(string calldata, string calldata) external returns (uint256[] memory);\n function parseJsonInt(string calldata, string calldata) external returns (int256);\n function parseJsonIntArray(string calldata, string calldata) external returns (int256[] memory);\n function parseJsonBool(string calldata, string calldata) external returns (bool);\n function parseJsonBoolArray(string calldata, string calldata) external returns (bool[] memory);\n function parseJsonAddress(string calldata, string calldata) external returns (address);\n function parseJsonAddressArray(string calldata, string calldata) external returns (address[] memory);\n function parseJsonString(string calldata, string calldata) external returns (string memory);\n function parseJsonStringArray(string calldata, string calldata) external returns (string[] memory);\n function parseJsonBytes(string calldata, string calldata) external returns (bytes memory);\n function parseJsonBytesArray(string calldata, string calldata) external returns (bytes[] memory);\n function parseJsonBytes32(string calldata, string calldata) external returns (bytes32);\n function parseJsonBytes32Array(string calldata, string calldata) external returns (bytes32[] memory);\n\n // Serialize a key and value to a JSON object stored in-memory that can be later written to a file\n // It returns the stringified version of the specific JSON file up to that moment.\n function serializeBool(string calldata objectKey, string calldata valueKey, bool value)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address value)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)\n external\n returns (string memory json);\n\n function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)\n external\n returns (string memory json);\n\n //\n // writeJson\n //\n // ----\n // Write a serialized JSON object to a file. If the file exists, it will be overwritten.\n // Let's assume we want to write the following JSON to a file:\n //\n // { \"boolean\": true, \"number\": 342, \"object\": { \"title\": \"finally json serialization\" } }\n //\n // ```\n // string memory json1 = \"some key\";\n // vm.serializeBool(json1, \"boolean\", true);\n // vm.serializeBool(json1, \"number\", uint256(342));\n // json2 = \"some other key\";\n // string memory output = vm.serializeString(json2, \"title\", \"finally json serialization\");\n // string memory finalJson = vm.serialize(json1, \"object\", output);\n // vm.writeJson(finalJson, \"./output/example.json\");\n // ```\n // The critical insight is that every invocation of serialization will return the stringified version of the JSON\n // up to that point. That means we can construct arbitrary JSON objects and then use the return stringified version\n // to serialize them as values to another JSON object.\n //\n // json1 and json2 are simply keys used by the backend to keep track of the objects. So vm.serializeJson(json1,..)\n // will find the object in-memory that is keyed by \"some key\".\n function writeJson(string calldata json, string calldata path) external;\n // Write a serialized JSON object to an **existing** JSON file, replacing a value with key = \n // This is useful to replace a specific value of a JSON file, without having to parse the entire thing\n function writeJson(string calldata json, string calldata path, string calldata valueKey) external;\n // Returns the RPC url for the given alias\n function rpcUrl(string calldata rpcAlias) external view returns (string memory json);\n // Returns all rpc urls and their aliases `[alias, url][]`\n function rpcUrls() external view returns (string[2][] memory urls);\n // Returns all rpc urls and their aliases as structs.\n function rpcUrlStructs() external view returns (Rpc[] memory urls);\n // If the condition is false, discard this run's fuzz inputs and generate new ones.\n function assume(bool condition) external pure;\n // Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.\n function pauseGasMetering() external;\n // Resumes gas metering (i.e. gas usage is counted again). Noop if already on.\n function resumeGasMetering() external;\n}\n\ninterface Vm is VmSafe {\n // Sets block.timestamp\n function warp(uint256 newTimestamp) external;\n // Sets block.height\n function roll(uint256 newHeight) external;\n // Sets block.basefee\n function fee(uint256 newBasefee) external;\n // Sets block.difficulty\n function difficulty(uint256 newDifficulty) external;\n // Sets block.chainid\n function chainId(uint256 newChainId) external;\n // Stores a value to an address' storage slot.\n function store(address target, bytes32 slot, bytes32 value) external;\n // Sets the nonce of an account; must be higher than the current nonce of the account\n function setNonce(address account, uint64 newNonce) external;\n // Sets the *next* call's msg.sender to be the input address\n function prank(address msgSender) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called\n function startPrank(address msgSender) external;\n // Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input\n function prank(address msgSender, address txOrigin) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input\n function startPrank(address msgSender, address txOrigin) external;\n // Resets subsequent calls' msg.sender to be `address(this)`\n function stopPrank() external;\n // Sets an address' balance\n function deal(address account, uint256 newBalance) external;\n // Sets an address' code\n function etch(address target, bytes calldata newRuntimeBytecode) external;\n // Expects an error on next call\n function expectRevert(bytes calldata revertData) external;\n function expectRevert(bytes4 revertData) external;\n function expectRevert() external;\n\n // Prepare an expected log with all four checks enabled.\n // Call this function, then emit an event, then call a function. Internally after the call, we check if\n // logs were emitted in the expected order with the expected topics and data.\n // Second form also checks supplied address against emitting contract.\n function expectEmit() external;\n function expectEmit(address emitter) external;\n\n // Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData).\n // Call this function, then emit an event, then call a function. Internally after the call, we check if\n // logs were emitted in the expected order with the expected topics and data (as specified by the booleans).\n // Second form also checks supplied address against emitting contract.\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)\n external;\n\n // Mocks a call to an address, returning specified data.\n // Calldata can either be strict or a partial match, e.g. if you only\n // pass a Solidity selector to the expected calldata, then the entire Solidity\n // function will be mocked.\n function mockCall(address callee, bytes calldata data, bytes calldata returnData) external;\n // Mocks a call to an address with a specific msg.value, returning specified data.\n // Calldata match takes precedence over msg.value in case of ambiguity.\n function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external;\n // Clears all mocked calls\n function clearMockedCalls() external;\n // Expects a call to an address with the specified calldata.\n // Calldata can either be a strict or a partial match\n function expectCall(address callee, bytes calldata data) external;\n // Expects a call to an address with the specified msg.value and calldata\n function expectCall(address callee, uint256 msgValue, bytes calldata data) external;\n // Expect a call to an address with the specified msg.value, gas, and calldata.\n function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external;\n // Expect a call to an address with the specified msg.value and calldata, and a *minimum* amount of gas.\n function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external;\n // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other\n // memory is written to, the test will fail. Can be called multiple times to add more ranges to the set.\n function expectSafeMemory(uint64 min, uint64 max) external;\n // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext.\n // If any other memory is written to, the test will fail. Can be called multiple times to add more ranges\n // to the set.\n function expectSafeMemoryCall(uint64 min, uint64 max) external;\n // Sets block.coinbase\n function coinbase(address newCoinbase) external;\n // Snapshot the current state of the evm.\n // Returns the id of the snapshot that was created.\n // To revert a snapshot use `revertTo`\n function snapshot() external returns (uint256 snapshotId);\n // Revert the state of the EVM to a previous snapshot\n // Takes the snapshot id to revert to.\n // This deletes the snapshot and all snapshots taken after the given snapshot id.\n function revertTo(uint256 snapshotId) external returns (bool success);\n // Creates a new fork with the given endpoint and block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before the transaction,\n // and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates _and_ also selects new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before\n // the transaction, returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.\n function selectFork(uint256 forkId) external;\n /// Returns the identifier of the currently active fork. Reverts if no fork is currently active.\n function activeFork() external view returns (uint256 forkId);\n // Updates the currently active fork to given block number\n // This is similar to `roll` but for the currently active fork\n function rollFork(uint256 blockNumber) external;\n // Updates the currently active fork to given transaction\n // this will `rollFork` with the number of the block the transaction was mined in and replays all transaction mined before it in the block\n function rollFork(bytes32 txHash) external;\n // Updates the given fork to given block number\n function rollFork(uint256 forkId, uint256 blockNumber) external;\n // Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block\n function rollFork(uint256 forkId, bytes32 txHash) external;\n // Marks that the account(s) should use persistent storage across fork swaps in a multifork setup\n // Meaning, changes made to the state of this account will be kept when switching forks\n function makePersistent(address account) external;\n function makePersistent(address account0, address account1) external;\n function makePersistent(address account0, address account1, address account2) external;\n function makePersistent(address[] calldata accounts) external;\n // Revokes persistent status from the address, previously added via `makePersistent`\n function revokePersistent(address account) external;\n function revokePersistent(address[] calldata accounts) external;\n // Returns true if the account is marked as persistent\n function isPersistent(address account) external view returns (bool persistent);\n // In forking mode, explicitly grant the given address cheatcode access\n function allowCheatcodes(address account) external;\n // Fetches the given transaction from the active fork and executes it on the current state\n function transact(bytes32 txHash) external;\n // Fetches the given transaction from the given fork and executes it on the current state\n function transact(uint256 forkId, bytes32 txHash) external;\n}\n" - }, - "node_modules/forge-std/src/console.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nlibrary console {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int)\", p0));\n }\n\n function logUint(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint)\", p0, p1));\n }\n\n function log(uint p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string)\", p0, p1));\n }\n\n function log(uint p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool)\", p0, p1));\n }\n\n function log(uint p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address)\", p0, p1));\n }\n\n function log(string memory p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - }, - "node_modules/forge-std/src/console2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\n/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should\n/// use `int256` and `uint256`. This modified version fixes that. This version is recommended\n/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in\n/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.\n/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178\nlibrary console2 {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function logUint(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function log(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint256 p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256)\", p0, p1));\n }\n\n function log(uint256 p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string)\", p0, p1));\n }\n\n function log(uint256 p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool)\", p0, p1));\n }\n\n function log(uint256 p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address)\", p0, p1));\n }\n\n function log(string memory p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n }\n\n function log(string memory p0, int256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,int256)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - }, - "node_modules/forge-std/src/interfaces/IMulticall3.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\ninterface IMulticall3 {\n struct Call {\n address target;\n bytes callData;\n }\n\n struct Call3 {\n address target;\n bool allowFailure;\n bytes callData;\n }\n\n struct Call3Value {\n address target;\n bool allowFailure;\n uint256 value;\n bytes callData;\n }\n\n struct Result {\n bool success;\n bytes returnData;\n }\n\n function aggregate(Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes[] memory returnData);\n\n function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData);\n\n function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData);\n\n function blockAndAggregate(Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);\n\n function getBasefee() external view returns (uint256 basefee);\n\n function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash);\n\n function getBlockNumber() external view returns (uint256 blockNumber);\n\n function getChainId() external view returns (uint256 chainid);\n\n function getCurrentBlockCoinbase() external view returns (address coinbase);\n\n function getCurrentBlockDifficulty() external view returns (uint256 difficulty);\n\n function getCurrentBlockGasLimit() external view returns (uint256 gaslimit);\n\n function getCurrentBlockTimestamp() external view returns (uint256 timestamp);\n\n function getEthBalance(address addr) external view returns (uint256 balance);\n\n function getLastBlockHash() external view returns (bytes32 blockHash);\n\n function tryAggregate(bool requireSuccess, Call[] calldata calls)\n external\n payable\n returns (Result[] memory returnData);\n\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);\n}\n" - } - }, - "settings": { - "remappings": [ - "@openzeppelin/=node_modules/@openzeppelin/", - "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", - "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", - "@rari-capital/=node_modules/@rari-capital/", - "@rari-capital/solmate/=node_modules/@rari-capital/solmate/", - "ds-test/=node_modules/ds-test/src/", - "forge-std/=node_modules/forge-std/src/" - ], - "optimizer": { - "enabled": true, - "runs": 999999 - }, - "metadata": { - "bytecodeHash": "none" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "storageLayout", - "devdoc", - "userdoc" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/solcInputs/672fbec9734a08fc34112408d6dc7f7b.json b/packages/contracts-bedrock/deployments/goerli/solcInputs/672fbec9734a08fc34112408d6dc7f7b.json deleted file mode 100644 index 5d4c6cfd35a4..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/solcInputs/672fbec9734a08fc34112408d6dc7f7b.json +++ /dev/null @@ -1,522 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/L1/L1CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismPortal } from \"./OptimismPortal.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1CrossDomainMessenger\n * @notice The L1CrossDomainMessenger is a message passing interface between L1 and L2 responsible\n * for sending and receiving data on the L1 side. Users are encouraged to use this\n * interface instead of interacting with lower-level contracts directly.\n */\ncontract L1CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @notice Address of the OptimismPortal.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _portal Address of the OptimismPortal contract on this network.\n */\n constructor(OptimismPortal _portal)\n Semver(1, 0, 0)\n CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER)\n {\n PORTAL = _portal;\n initialize(address(0));\n }\n\n /**\n * @notice Initializer.\n *\n * @param _owner Address of the initial owner of this contract.\n */\n function initialize(address _owner) public initializer {\n __CrossDomainMessenger_init();\n _transferOwnership(_owner);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n PORTAL.depositTransaction{ value: _value }(_to, _value, _gasLimit, false, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return msg.sender == address(PORTAL) && PORTAL.l2Sender() == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(PORTAL);\n }\n}\n" - }, - "contracts/L1/L1ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { L2ERC721Bridge } from \"../L2/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 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 * @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(OTHER_BRIDGE, message, _minGasLimit);\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L1/L1StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1StandardBridge\n * @notice The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L1, it will be escrowed within this\n * contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was\n * stored within this contract. After Bedrock, ETH is instead stored inside the\n * OptimismPortal contract.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L1StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a deposit of ETH from L1 into L2 is initiated.\n *\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of ETH deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ETHDepositInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal of ETH from L2 to L1 is finalized.\n *\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of ETH withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 withdrawal is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _messenger Address of the L1CrossDomainMessenger.\n */\n constructor(address payable _messenger)\n Semver(1, 0, 0)\n StandardBridge(_messenger, payable(Predeploys.L2_STANDARD_BRIDGE))\n {}\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ERC20 tokens from L2.\n *\n * @param _l1Token Address of the token on L1.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of the ERC20 to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeERC20Withdrawal(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external onlyOtherBridge {\n emit ERC20WithdrawalFinalized(_l1Token, _l2Token, _from, _to, _amount, _extraData);\n finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into the sender's account on L2.\n *\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETH(uint32 _minGasLimit, bytes calldata _extraData) external payable onlyEOA {\n _initiateETHDeposit(msg.sender, msg.sender, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into a target account on L2.\n * Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will\n * be locked in the L2StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n *\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable {\n _initiateETHDeposit(msg.sender, _to, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into the sender's account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20(\n address _l1Token,\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual onlyEOA {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into a target account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20To(\n address _l1Token,\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ETH from L2.\n *\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of ETH to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeETHWithdrawal(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable onlyOtherBridge {\n emit ETHWithdrawalFinalized(_from, _to, _amount, _extraData);\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L2 bridge contract.\n *\n * @return Address of the corresponding L2 bridge contract.\n */\n function l2TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @notice Internal function for initiating an ETH deposit.\n *\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateETHDeposit(\n address _from,\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal {\n emit ETHDepositInitiated(_from, _to, msg.value, _extraData);\n _initiateBridgeETH(_from, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Internal function for initiating an ERC20 deposit.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateERC20Deposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal {\n emit ERC20DepositInitiated(_l1Token, _l2Token, _from, _to, _amount, _extraData);\n _initiateBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n}\n" - }, - "contracts/L1/L2OutputOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\n/**\n * @custom:proxied\n * @title L2OutputOracle\n * @notice The L2OutputOracle contains an array of L2 state outputs, where each output is a\n * commitment to the state of the L2 chain. Other contracts like the OptimismPortal use\n * these outputs to verify information about the state of L2.\n */\ncontract L2OutputOracle is Initializable, Semver {\n /**\n * @notice The interval in L2 blocks at which checkpoints must be submitted. Although this is\n * immutable, it can safely be modified by upgrading the implementation contract.\n */\n uint256 public immutable SUBMISSION_INTERVAL;\n\n /**\n * @notice The time between L2 blocks in seconds. Once set, this value MUST NOT be modified.\n */\n uint256 public immutable L2_BLOCK_TIME;\n\n /**\n * @notice The address of the challenger. Can be updated via upgrade.\n */\n address public immutable CHALLENGER;\n\n /**\n * @notice The address of the proposer. Can be updated via upgrade.\n */\n address public immutable PROPOSER;\n\n /**\n * @notice The number of the first L2 block recorded in this contract.\n */\n uint256 public startingBlockNumber;\n\n /**\n * @notice The timestamp of the first L2 block recorded in this contract.\n */\n uint256 public startingTimestamp;\n\n /**\n * @notice Array of L2 output proposals.\n */\n Types.OutputProposal[] internal l2Outputs;\n\n /**\n * @notice Emitted when an output is proposed.\n *\n * @param outputRoot The output root.\n * @param l2OutputIndex The index of the output in the l2Outputs array.\n * @param l2BlockNumber The L2 block number of the output root.\n * @param l1Timestamp The L1 timestamp when proposed.\n */\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n /**\n * @notice Emitted when outputs are deleted.\n *\n * @param prevNextOutputIndex Next L2 output index before the deletion.\n * @param newNextOutputIndex Next L2 output index after the deletion.\n */\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _submissionInterval Interval in blocks at which checkpoints must be submitted.\n * @param _l2BlockTime The time per L2 block, in seconds.\n * @param _startingBlockNumber The number of the first L2 block.\n * @param _startingTimestamp The timestamp of the first L2 block.\n * @param _proposer The address of the proposer.\n * @param _challenger The address of the challenger.\n */\n constructor(\n uint256 _submissionInterval,\n uint256 _l2BlockTime,\n uint256 _startingBlockNumber,\n uint256 _startingTimestamp,\n address _proposer,\n address _challenger\n ) Semver(1, 0, 0) {\n SUBMISSION_INTERVAL = _submissionInterval;\n L2_BLOCK_TIME = _l2BlockTime;\n PROPOSER = _proposer;\n CHALLENGER = _challenger;\n\n initialize(_startingBlockNumber, _startingTimestamp);\n }\n\n /**\n * @notice Initializer.\n *\n * @param _startingBlockNumber Block number for the first recoded L2 block.\n * @param _startingTimestamp Timestamp for the first recoded L2 block.\n */\n function initialize(uint256 _startingBlockNumber, uint256 _startingTimestamp)\n public\n initializer\n {\n require(\n _startingTimestamp <= block.timestamp,\n \"L2OutputOracle: starting L2 timestamp must be less than current time\"\n );\n\n startingTimestamp = _startingTimestamp;\n startingBlockNumber = _startingBlockNumber;\n }\n\n /**\n * @notice Deletes all output proposals after and including the proposal that corresponds to\n * the given output index. Only the challenger address can delete outputs.\n *\n * @param _l2OutputIndex Index of the first L2 output to be deleted. All outputs after this\n * output will also be deleted.\n */\n // solhint-disable-next-line ordering\n function deleteL2Outputs(uint256 _l2OutputIndex) external {\n require(\n msg.sender == CHALLENGER,\n \"L2OutputOracle: only the challenger address can delete outputs\"\n );\n\n // Make sure we're not *increasing* the length of the array.\n require(\n _l2OutputIndex < l2Outputs.length,\n \"L2OutputOracle: cannot delete outputs after the latest output index\"\n );\n\n uint256 prevNextL2OutputIndex = nextOutputIndex();\n\n // Use assembly to delete the array elements because Solidity doesn't allow it.\n assembly {\n sstore(l2Outputs.slot, _l2OutputIndex)\n }\n\n emit OutputsDeleted(prevNextL2OutputIndex, _l2OutputIndex);\n }\n\n /**\n * @notice Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp\n * must be equal to the current value returned by `nextTimestamp()` in order to be\n * accepted. This function may only be called by the Proposer.\n *\n * @param _outputRoot The L2 output of the checkpoint block.\n * @param _l2BlockNumber The L2 block number that resulted in _outputRoot.\n * @param _l1BlockHash A block hash which must be included in the current chain.\n * @param _l1BlockNumber The block number with the specified block hash.\n */\n function proposeL2Output(\n bytes32 _outputRoot,\n uint256 _l2BlockNumber,\n bytes32 _l1BlockHash,\n uint256 _l1BlockNumber\n ) external payable {\n require(\n msg.sender == PROPOSER,\n \"L2OutputOracle: only the proposer address can propose new outputs\"\n );\n\n require(\n _l2BlockNumber == nextBlockNumber(),\n \"L2OutputOracle: block number must be equal to next expected block number\"\n );\n\n require(\n computeL2Timestamp(_l2BlockNumber) < block.timestamp,\n \"L2OutputOracle: cannot propose L2 output in the future\"\n );\n\n require(\n _outputRoot != bytes32(0),\n \"L2OutputOracle: L2 output proposal cannot be the zero hash\"\n );\n\n if (_l1BlockHash != bytes32(0)) {\n // This check allows the proposer to propose an output based on a given L1 block,\n // without fear that it will be reorged out.\n // It will also revert if the blockheight provided is more than 256 blocks behind the\n // chain tip (as the hash will return as zero). This does open the door to a griefing\n // attack in which the proposer's submission is censored until the block is no longer\n // retrievable, if the proposer is experiencing this attack it can simply leave out the\n // blockhash value, and delay submission until it is confident that the L1 block is\n // finalized.\n require(\n blockhash(_l1BlockNumber) == _l1BlockHash,\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n }\n\n emit OutputProposed(_outputRoot, nextOutputIndex(), _l2BlockNumber, block.timestamp);\n\n l2Outputs.push(\n Types.OutputProposal({\n outputRoot: _outputRoot,\n timestamp: uint128(block.timestamp),\n l2BlockNumber: uint128(_l2BlockNumber)\n })\n );\n }\n\n /**\n * @notice Returns an output by index. Exists because Solidity's array access will return a\n * tuple instead of a struct.\n *\n * @param _l2OutputIndex Index of the output to return.\n *\n * @return The output at the given index.\n */\n function getL2Output(uint256 _l2OutputIndex)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[_l2OutputIndex];\n }\n\n /**\n * @notice Returns the index of the L2 output that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return Index of the first checkpoint that commits to the given L2 block number.\n */\n function getL2OutputIndexAfter(uint256 _l2BlockNumber) public view returns (uint256) {\n // Make sure an output for this block number has actually been proposed.\n require(\n _l2BlockNumber <= latestBlockNumber(),\n \"L2OutputOracle: cannot get output for a block that has not been proposed\"\n );\n\n // Make sure there's at least one output proposed.\n require(\n l2Outputs.length > 0,\n \"L2OutputOracle: cannot get output as no outputs have been proposed yet\"\n );\n\n // Find the output via binary search, guaranteed to exist.\n uint256 lo = 0;\n uint256 hi = l2Outputs.length;\n while (lo < hi) {\n uint256 mid = (lo + hi) / 2;\n if (l2Outputs[mid].l2BlockNumber < _l2BlockNumber) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n return lo;\n }\n\n /**\n * @notice Returns the L2 output proposal that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return First checkpoint that commits to the given L2 block number.\n */\n function getL2OutputAfter(uint256 _l2BlockNumber)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[getL2OutputIndexAfter(_l2BlockNumber)];\n }\n\n /**\n * @notice Returns the number of outputs that have been proposed. Will revert if no outputs\n * have been proposed yet.\n *\n * @return The number of outputs that have been proposed.\n */\n function latestOutputIndex() external view returns (uint256) {\n return l2Outputs.length - 1;\n }\n\n /**\n * @notice Returns the index of the next output to be proposed.\n *\n * @return The index of the next output to be proposed.\n */\n function nextOutputIndex() public view returns (uint256) {\n return l2Outputs.length;\n }\n\n /**\n * @notice Returns the block number of the latest submitted L2 output proposal. If no proposals\n * been submitted yet then this function will return the starting block number.\n *\n * @return Latest submitted L2 block number.\n */\n function latestBlockNumber() public view returns (uint256) {\n return\n l2Outputs.length == 0\n ? startingBlockNumber\n : l2Outputs[l2Outputs.length - 1].l2BlockNumber;\n }\n\n /**\n * @notice Computes the block number of the next L2 block that needs to be checkpointed.\n *\n * @return Next L2 block number.\n */\n function nextBlockNumber() public view returns (uint256) {\n return latestBlockNumber() + SUBMISSION_INTERVAL;\n }\n\n /**\n * @notice Returns the L2 timestamp corresponding to a given L2 block number.\n *\n * @param _l2BlockNumber The L2 block number of the target block.\n *\n * @return L2 timestamp of the given block.\n */\n function computeL2Timestamp(uint256 _l2BlockNumber) public view returns (uint256) {\n return startingTimestamp + ((_l2BlockNumber - startingBlockNumber) * L2_BLOCK_TIME);\n }\n}\n" - }, - "contracts/L1/OptimismPortal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { L2OutputOracle } from \"./L2OutputOracle.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { SecureMerkleTrie } from \"../libraries/trie/SecureMerkleTrie.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ResourceMetering } from \"./ResourceMetering.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title OptimismPortal\n * @notice The OptimismPortal is a low-level contract responsible for passing messages between L1\n * and L2. Messages sent directly to the OptimismPortal have no form of replayability.\n * Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface.\n */\ncontract OptimismPortal is Initializable, ResourceMetering, Semver {\n /**\n * @notice Represents a proven withdrawal.\n *\n * @custom:field outputRoot Root of the L2 output this was proven against.\n * @custom:field timestamp Timestamp at whcih the withdrawal was proven.\n * @custom:field l2OutputIndex Index of the output this was proven against.\n */\n struct ProvenWithdrawal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2OutputIndex;\n }\n\n /**\n * @notice Version of the deposit event.\n */\n uint256 internal constant DEPOSIT_VERSION = 0;\n\n /**\n * @notice The L2 gas limit set when eth is deposited using the receive() function.\n */\n uint64 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Additional gas reserved for clean up after finalizing a transaction withdrawal.\n */\n uint256 internal constant FINALIZE_GAS_BUFFER = 20_000;\n\n /**\n * @notice Minimum time (in seconds) that must elapse before a withdrawal can be finalized.\n */\n uint256 public immutable FINALIZATION_PERIOD_SECONDS;\n\n /**\n * @notice Address of the L2OutputOracle.\n */\n L2OutputOracle public immutable L2_ORACLE;\n\n /**\n * @notice Address of the L2 account which initiated a withdrawal in this transaction. If the\n * of this variable is the default L2 sender address, then we are NOT inside of a call\n * to finalizeWithdrawalTransaction.\n */\n address public l2Sender;\n\n /**\n * @notice A list of withdrawal hashes which have been successfully finalized.\n */\n mapping(bytes32 => bool) public finalizedWithdrawals;\n\n /**\n * @notice A mapping of withdrawal hashes to `ProvenWithdrawal` data.\n */\n mapping(bytes32 => ProvenWithdrawal) public provenWithdrawals;\n\n /**\n * @notice Emitted when a transaction is deposited from L1 to L2. The parameters of this event\n * are read by the rollup node and used to derive deposit transactions on L2.\n *\n * @param from Address that triggered the deposit transaction.\n * @param to Address that the deposit transaction is directed to.\n * @param version Version of this deposit transaction event.\n * @param opaqueData ABI encoded deposit data to be parsed off-chain.\n */\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is proven.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n */\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is finalized.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n * @param success Whether the withdrawal transaction was successful.\n */\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _l2Oracle Address of the L2OutputOracle contract.\n * @param _finalizationPeriodSeconds Output finalization time in seconds.\n */\n constructor(L2OutputOracle _l2Oracle, uint256 _finalizationPeriodSeconds) Semver(1, 0, 0) {\n L2_ORACLE = _l2Oracle;\n FINALIZATION_PERIOD_SECONDS = _finalizationPeriodSeconds;\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n l2Sender = Constants.DEFAULT_L2_SENDER;\n __ResourceMetering_init();\n }\n\n /**\n * @notice Accepts value so that users can send ETH directly to this contract and have the\n * funds be deposited to their address on L2. This is intended as a convenience\n * function for EOAs. Contracts should call the depositTransaction() function directly\n * otherwise any deposited funds will be lost due to address aliasing.\n */\n // solhint-disable-next-line ordering\n receive() external payable {\n depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes(\"\"));\n }\n\n /**\n * @notice Accepts ETH value without triggering a deposit to L2. This function mainly exists\n * for the sake of the migration between the legacy Optimism system and Bedrock.\n */\n function donateETH() external payable {\n // Intentionally empty.\n }\n\n /**\n * @notice Proves a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n * @param _l2OutputIndex L2 output index to prove against.\n * @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root.\n * @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract.\n */\n function proveWithdrawalTransaction(\n Types.WithdrawalTransaction memory _tx,\n uint256 _l2OutputIndex,\n Types.OutputRootProof calldata _outputRootProof,\n bytes[] calldata _withdrawalProof\n ) external {\n // Prevent users from creating a deposit transaction where this address is the message\n // sender on L2. Because this is checked here, we do not need to check again in\n // `finalizeWithdrawalTransaction`.\n require(\n _tx.target != address(this),\n \"OptimismPortal: you cannot send messages to the portal contract\"\n );\n\n // Get the output root and load onto the stack to prevent multiple mloads. This will\n // revert if there is no output root for the given block number.\n bytes32 outputRoot = L2_ORACLE.getL2Output(_l2OutputIndex).outputRoot;\n\n // Verify that the output root can be generated with the elements in the proof.\n require(\n outputRoot == Hashing.hashOutputRootProof(_outputRootProof),\n \"OptimismPortal: invalid output root proof\"\n );\n\n // Load the ProvenWithdrawal into memory, using the withdrawal hash as a unique identifier.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // We generally want to prevent users from proving the same withdrawal multiple times\n // because each successive proof will update the timestamp. A malicious user can take\n // advantage of this to prevent other users from finalizing their withdrawal. However,\n // since withdrawals are proven before an output root is finalized, we need to allow users\n // to re-prove their withdrawal only in the case that the output root for their specified\n // output index has been updated.\n require(\n provenWithdrawal.timestamp == 0 ||\n (_l2OutputIndex == provenWithdrawal.l2OutputIndex &&\n outputRoot != provenWithdrawal.outputRoot),\n \"OptimismPortal: withdrawal hash has already been proven\"\n );\n\n // Compute the storage slot of the withdrawal hash in the L2ToL1MessagePasser contract.\n // Refer to the Solidity documentation for more information on how storage layouts are\n // computed for mappings.\n bytes32 storageKey = keccak256(\n abi.encode(\n withdrawalHash,\n uint256(0) // The withdrawals mapping is at the first slot in the layout.\n )\n );\n\n // Verify that the hash of this withdrawal was stored in the L2toL1MessagePasser contract\n // on L2. If this is true, under the assumption that the SecureMerkleTrie does not have\n // bugs, then we know that this withdrawal was actually triggered on L2 and can therefore\n // be relayed on L1.\n require(\n SecureMerkleTrie.verifyInclusionProof(\n abi.encode(storageKey),\n hex\"01\",\n _withdrawalProof,\n _outputRootProof.messagePasserStorageRoot\n ),\n \"OptimismPortal: invalid withdrawal inclusion proof\"\n );\n\n // Designate the withdrawalHash as proven by storing the `outputRoot`, `timestamp`, and\n // `l2BlockNumber` in the `provenWithdrawals` mapping. A `withdrawalHash` can only be\n // proven once unless it is submitted again with a different outputRoot.\n provenWithdrawals[withdrawalHash] = ProvenWithdrawal({\n outputRoot: outputRoot,\n timestamp: uint128(block.timestamp),\n l2OutputIndex: uint128(_l2OutputIndex)\n });\n\n // Emit a `WithdrawalProven` event.\n emit WithdrawalProven(withdrawalHash, _tx.sender, _tx.target);\n }\n\n /**\n * @notice Finalizes a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n */\n function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external {\n // Make sure that the l2Sender has not yet been set. The l2Sender is set to a value other\n // than the default value when a withdrawal transaction is being finalized. This check is\n // a defacto reentrancy guard.\n require(\n l2Sender == Constants.DEFAULT_L2_SENDER,\n \"OptimismPortal: can only trigger one withdrawal per transaction\"\n );\n\n // Grab the proven withdrawal from the `provenWithdrawals` map.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // A withdrawal can only be finalized if it has been proven. We know that a withdrawal has\n // been proven at least once when its timestamp is non-zero. Unproven withdrawals will have\n // a timestamp of zero.\n require(\n provenWithdrawal.timestamp != 0,\n \"OptimismPortal: withdrawal has not been proven yet\"\n );\n\n // As a sanity check, we make sure that the proven withdrawal's timestamp is greater than\n // starting timestamp inside the L2OutputOracle. Not strictly necessary but extra layer of\n // safety against weird bugs in the proving step.\n require(\n provenWithdrawal.timestamp >= L2_ORACLE.startingTimestamp(),\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n\n // A proven withdrawal must wait at least the finalization period before it can be\n // finalized. This waiting period can elapse in parallel with the waiting period for the\n // output the withdrawal was proven against. In effect, this means that the minimum\n // withdrawal time is proposal submission time + finalization period.\n require(\n _isFinalizationPeriodElapsed(provenWithdrawal.timestamp),\n \"OptimismPortal: proven withdrawal finalization period has not elapsed\"\n );\n\n // Grab the OutputProposal from the L2OutputOracle, will revert if the output that\n // corresponds to the given index has not been proposed yet.\n Types.OutputProposal memory proposal = L2_ORACLE.getL2Output(\n provenWithdrawal.l2OutputIndex\n );\n\n // Check that the output root that was used to prove the withdrawal is the same as the\n // current output root for the given output index. An output root may change if it is\n // deleted by the challenger address and then re-proposed.\n require(\n proposal.outputRoot == provenWithdrawal.outputRoot,\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n\n // Check that the output proposal has also been finalized.\n require(\n _isFinalizationPeriodElapsed(proposal.timestamp),\n \"OptimismPortal: output proposal finalization period has not elapsed\"\n );\n\n // Check that this withdrawal has not already been finalized, this is replay protection.\n require(\n finalizedWithdrawals[withdrawalHash] == false,\n \"OptimismPortal: withdrawal has already been finalized\"\n );\n\n // Mark the withdrawal as finalized so it can't be replayed.\n finalizedWithdrawals[withdrawalHash] = true;\n\n // We want to maintain the property that the amount of gas supplied to the call to the\n // target contract is at least the gas limit specified by the user. We can do this by\n // enforcing that, at this point in time, we still have gaslimit + buffer gas available.\n require(\n gasleft() >= _tx.gasLimit + FINALIZE_GAS_BUFFER,\n \"OptimismPortal: insufficient gas to finalize withdrawal\"\n );\n\n // Set the l2Sender so contracts know who triggered this withdrawal on L2.\n l2Sender = _tx.sender;\n\n // Trigger the call to the target contract. We use SafeCall because we don't\n // care about the returndata and we don't want target contracts to be able to force this\n // call to run out of gas via a returndata bomb.\n bool success = SafeCall.call(\n _tx.target,\n gasleft() - FINALIZE_GAS_BUFFER,\n _tx.value,\n _tx.data\n );\n\n // Reset the l2Sender back to the default value.\n l2Sender = Constants.DEFAULT_L2_SENDER;\n\n // All withdrawals are immediately finalized. Replayability can\n // be achieved through contracts built on top of this contract\n emit WithdrawalFinalized(withdrawalHash, success);\n\n // Reverting here is useful for determining the exact gas cost to successfully execute the\n // sub call to the target contract if the minimum gas limit specified by the user would not\n // be sufficient to execute the sub call.\n if (success == false && tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"OptimismPortal: withdrawal failed\");\n }\n }\n\n /**\n * @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in\n * deriving deposit transactions. Note that if a deposit is made by a contract, its\n * address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider\n * using the CrossDomainMessenger contracts for a simpler developer experience.\n *\n * @param _to Target address on L2.\n * @param _value ETH value to send to the recipient.\n * @param _gasLimit Minimum L2 gas limit (can be greater than or equal to this value).\n * @param _isCreation Whether or not the transaction is a contract creation.\n * @param _data Data to trigger the recipient with.\n */\n function depositTransaction(\n address _to,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable metered(_gasLimit) {\n // Just to be safe, make sure that people specify address(0) as the target when doing\n // contract creations.\n if (_isCreation) {\n require(\n _to == address(0),\n \"OptimismPortal: must send to address(0) when creating a contract\"\n );\n }\n\n // Transform the from-address to its alias if the caller is a contract.\n address from = msg.sender;\n if (msg.sender != tx.origin) {\n from = AddressAliasHelper.applyL1ToL2Alias(msg.sender);\n }\n\n // Compute the opaque data that will be emitted as part of the TransactionDeposited event.\n // We use opaque data so that we can update the TransactionDeposited event in the future\n // without breaking the current interface.\n bytes memory opaqueData = abi.encodePacked(\n msg.value,\n _value,\n _gasLimit,\n _isCreation,\n _data\n );\n\n // Emit a TransactionDeposited event so that the rollup node can derive a deposit\n // transaction for this deposit.\n emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData);\n }\n\n /**\n * @notice Determine if a given output is finalized. Reverts if the call to\n * L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.\n *\n * @param _l2OutputIndex Index of the L2 output to check.\n *\n * @return Whether or not the output is finalized.\n */\n function isOutputFinalized(uint256 _l2OutputIndex) external view returns (bool) {\n return _isFinalizationPeriodElapsed(L2_ORACLE.getL2Output(_l2OutputIndex).timestamp);\n }\n\n /**\n * @notice Determines whether the finalization period has elapsed w/r/t a given timestamp.\n *\n * @param _timestamp Timestamp to check.\n *\n * @return Whether or not the finalization period has elapsed.\n */\n function _isFinalizationPeriodElapsed(uint256 _timestamp) internal view returns (bool) {\n return block.timestamp > _timestamp + FINALIZATION_PERIOD_SECONDS;\n }\n}\n" - }, - "contracts/L1/ResourceMetering.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\n\n/**\n * @custom:upgradeable\n * @title ResourceMetering\n * @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing\n * updates automatically based on current demand.\n */\nabstract contract ResourceMetering is Initializable {\n /**\n * @notice Represents the various parameters that control the way in which resources are\n * metered. Corresponds to the EIP-1559 resource metering system.\n *\n * @custom:field prevBaseFee Base fee from the previous block(s).\n * @custom:field prevBoughtGas Amount of gas bought so far in the current block.\n * @custom:field prevBlockNum Last block number that the base fee was updated.\n */\n struct ResourceParams {\n uint128 prevBaseFee;\n uint64 prevBoughtGas;\n uint64 prevBlockNum;\n }\n\n /**\n * @notice Maximum amount of the resource that can be used within this block.\n */\n int256 public constant MAX_RESOURCE_LIMIT = 8_000_000;\n\n /**\n * @notice Along with the resource limit, determines the target resource limit.\n */\n int256 public constant ELASTICITY_MULTIPLIER = 4;\n\n /**\n * @notice Target amount of the resource that should be used within this block.\n */\n int256 public constant TARGET_RESOURCE_LIMIT = MAX_RESOURCE_LIMIT / ELASTICITY_MULTIPLIER;\n\n /**\n * @notice Denominator that determines max change on fee per block.\n */\n int256 public constant BASE_FEE_MAX_CHANGE_DENOMINATOR = 8;\n\n /**\n * @notice Minimum base fee value, cannot go lower than this.\n */\n int256 public constant MINIMUM_BASE_FEE = 10_000;\n\n /**\n * @notice Maximum base fee value, cannot go higher than this.\n */\n int256 public constant MAXIMUM_BASE_FEE = int256(uint256(type(uint128).max));\n\n /**\n * @notice Initial base fee value.\n */\n uint128 public constant INITIAL_BASE_FEE = 1_000_000_000;\n\n /**\n * @notice EIP-1559 style gas parameters.\n */\n ResourceParams public params;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n */\n uint256[48] private __gap;\n\n /**\n * @notice Meters access to a function based an amount of a requested resource.\n *\n * @param _amount Amount of the resource requested.\n */\n modifier metered(uint64 _amount) {\n // Record initial gas amount so we can refund for it later.\n uint256 initialGas = gasleft();\n\n // Run the underlying function.\n _;\n\n // Update block number and base fee if necessary.\n uint256 blockDiff = block.number - params.prevBlockNum;\n if (blockDiff > 0) {\n // Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate\n // at which deposits can be created and therefore limit the potential for deposits to\n // spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes.\n int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - TARGET_RESOURCE_LIMIT;\n int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) /\n TARGET_RESOURCE_LIMIT /\n BASE_FEE_MAX_CHANGE_DENOMINATOR;\n\n // Update base fee by adding the base fee delta and clamp the resulting value between\n // min and max.\n int256 newBaseFee = Arithmetic.clamp(\n int256(uint256(params.prevBaseFee)) + baseFeeDelta,\n MINIMUM_BASE_FEE,\n MAXIMUM_BASE_FEE\n );\n\n // If we skipped more than one block, we also need to account for every empty block.\n // Empty block means there was no demand for deposits in that block, so we should\n // reflect this lack of demand in the fee.\n if (blockDiff > 1) {\n // Update the base fee by repeatedly applying the exponent 1-(1/change_denominator)\n // blockDiff - 1 times. Simulates multiple empty blocks. Clamp the resulting value\n // between min and max.\n newBaseFee = Arithmetic.clamp(\n Arithmetic.cdexp(\n newBaseFee,\n BASE_FEE_MAX_CHANGE_DENOMINATOR,\n int256(blockDiff - 1)\n ),\n MINIMUM_BASE_FEE,\n MAXIMUM_BASE_FEE\n );\n }\n\n // Update new base fee, reset bought gas, and update block number.\n params.prevBaseFee = uint128(uint256(newBaseFee));\n params.prevBoughtGas = 0;\n params.prevBlockNum = uint64(block.number);\n }\n\n // Make sure we can actually buy the resource amount requested by the user.\n params.prevBoughtGas += _amount;\n require(\n int256(uint256(params.prevBoughtGas)) <= MAX_RESOURCE_LIMIT,\n \"ResourceMetering: cannot buy more gas than available gas limit\"\n );\n\n // Determine the amount of ETH to be paid.\n uint256 resourceCost = _amount * params.prevBaseFee;\n\n // We currently charge for this ETH amount as an L1 gas burn, so we convert the ETH amount\n // into gas by dividing by the L1 base fee. We assume a minimum base fee of 1 gwei to avoid\n // division by zero for L1s that don't support 1559 or to avoid excessive gas burns during\n // periods of extremely low L1 demand. One-day average gas fee hasn't dipped below 1 gwei\n // during any 1 day period in the last 5 years, so should be fine.\n uint256 gasCost = resourceCost / Math.max(block.basefee, 1000000000);\n\n // Give the user a refund based on the amount of gas they used to do all of the work up to\n // this point. Since we're at the end of the modifier, this should be pretty accurate. Acts\n // effectively like a dynamic stipend (with a minimum value).\n uint256 usedGas = initialGas - gasleft();\n if (gasCost > usedGas) {\n Burn.gas(gasCost - usedGas);\n }\n }\n\n /**\n * @notice Sets initial resource parameter values. This function must either be called by the\n * initializer function of an upgradeable child contract.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __ResourceMetering_init() internal onlyInitializing {\n params = ResourceParams({\n prevBaseFee: INITIAL_BASE_FEE,\n prevBoughtGas: 0,\n prevBlockNum: uint64(block.number)\n });\n }\n}\n" - }, - "contracts/L1/SystemConfig.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @title SystemConfig\n * @notice The SystemConfig contract is used to manage configuration of an Optimism network. All\n * configuration is stored on L1 and picked up by L2 as part of the derviation of the L2\n * chain.\n */\ncontract SystemConfig is OwnableUpgradeable, Semver {\n /**\n * @notice Enum representing different types of updates.\n *\n * @custom:value BATCHER Represents an update to the batcher hash.\n * @custom:value GAS_CONFIG Represents an update to txn fee config on L2.\n * @custom:value GAS_LIMIT Represents an update to gas limit on L2.\n * @custom:value UNSAFE_BLOCK_SIGNER Represents an update to the signer key for unsafe\n * block distrubution.\n */\n enum UpdateType {\n BATCHER,\n GAS_CONFIG,\n GAS_LIMIT,\n UNSAFE_BLOCK_SIGNER\n }\n\n /**\n * @notice Version identifier, used for upgrades.\n */\n uint256 public constant VERSION = 0;\n\n /**\n * @notice Storage slot that the unsafe block signer is stored at. Storing it at this\n * deterministic storage slot allows for decoupling the storage layout from the way\n * that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value.\n */\n bytes32 public constant UNSAFE_BLOCK_SIGNER_SLOT = keccak256(\"systemconfig.unsafeblocksigner\");\n\n /**\n * @notice Minimum gas limit. This should not be lower than the maximum deposit gas resource\n * limit in the ResourceMetering contract used by OptimismPortal, to ensure the L2\n * block always has sufficient gas to process deposits.\n */\n uint64 public constant MINIMUM_GAS_LIMIT = 8_000_000;\n\n /**\n * @notice Fixed L2 gas overhead.\n */\n uint256 public overhead;\n\n /**\n * @notice Dynamic L2 gas overhead.\n */\n uint256 public scalar;\n\n /**\n * @notice Identifier for the batcher. For version 1 of this configuration, this is represented\n * as an address left-padded with zeros to 32 bytes.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice L2 gas limit.\n */\n uint64 public gasLimit;\n\n /**\n * @notice Emitted when configuration is updated\n *\n * @param version SystemConfig version.\n * @param updateType Type of update.\n * @param data Encoded update data.\n */\n event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n */\n constructor(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner\n ) Semver(1, 0, 0) {\n initialize(_owner, _overhead, _scalar, _batcherHash, _gasLimit, _unsafeBlockSigner);\n }\n\n /**\n * @notice Initializer.\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n */\n function initialize(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner\n ) public initializer {\n require(_gasLimit >= MINIMUM_GAS_LIMIT, \"SystemConfig: gas limit too low\");\n __Ownable_init();\n transferOwnership(_owner);\n overhead = _overhead;\n scalar = _scalar;\n batcherHash = _batcherHash;\n gasLimit = _gasLimit;\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n }\n\n /**\n * @notice High level getter for the unsafe block signer address.\n * Unsafe blocks can be propagated across the p2p network\n * if they are signed by the key corresponding to this address.\n */\n function unsafeBlockSigner() public view returns (address) {\n address addr;\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n addr := sload(slot)\n }\n return addr;\n }\n\n /**\n * @notice Updates the batcher hash.\n *\n * @param _batcherHash New batcher hash.\n */\n // solhint-disable-next-line ordering\n function setBatcherHash(bytes32 _batcherHash) external onlyOwner {\n batcherHash = _batcherHash;\n\n bytes memory data = abi.encode(_batcherHash);\n emit ConfigUpdate(VERSION, UpdateType.BATCHER, data);\n }\n\n /**\n * @notice Updates gas config.\n *\n * @param _overhead New overhead value.\n * @param _scalar New scalar value.\n */\n function setGasConfig(uint256 _overhead, uint256 _scalar) external onlyOwner {\n overhead = _overhead;\n scalar = _scalar;\n\n bytes memory data = abi.encode(_overhead, _scalar);\n emit ConfigUpdate(VERSION, UpdateType.GAS_CONFIG, data);\n }\n\n function setUnsafeBlockSigner(address _unsafeBlockSigner) external onlyOwner {\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n\n bytes memory data = abi.encode(_unsafeBlockSigner);\n emit ConfigUpdate(VERSION, UpdateType.UNSAFE_BLOCK_SIGNER, data);\n }\n\n /**\n * @notice Low level setter for the unsafe block signer address.\n * This function exists to deduplicate code around storing\n * the unsafeBlockSigner address in storage.\n *\n * @param _unsafeBlockSigner New unsafeBlockSigner value\n */\n function _setUnsafeBlockSigner(address _unsafeBlockSigner) internal {\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n sstore(slot, _unsafeBlockSigner)\n }\n }\n\n /**\n * @notice Updates the L2 gas limit.\n *\n * @param _gasLimit New gas limit.\n */\n function setGasLimit(uint64 _gasLimit) external onlyOwner {\n require(_gasLimit >= MINIMUM_GAS_LIMIT, \"SystemConfig: gas limit too low\");\n gasLimit = _gasLimit;\n\n bytes memory data = abi.encode(_gasLimit);\n emit ConfigUpdate(VERSION, UpdateType.GAS_LIMIT, data);\n }\n}\n" - }, - "contracts/L2/BaseFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000019\n * @title BaseFeeVault\n * @notice The BaseFeeVault accumulates the base fee that is paid by transactions.\n */\ncontract BaseFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 0, 0) {}\n}\n" - }, - "contracts/L2/CrossDomainOwnable.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\n/**\n * @title CrossDomainOwnable\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is only safe to be used if the\n * CrossDomainMessenger system is bypassed and the caller on L1 is calling the\n * OptimismPortal directly.\n */\nabstract contract CrossDomainOwnable is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `msg.sender` is the owner of the contract.\n */\n function _checkOwner() internal view override {\n require(\n owner() == AddressAliasHelper.undoL1ToL2Alias(msg.sender),\n \"CrossDomainOwnable: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/CrossDomainOwnable2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L2CrossDomainMessenger } from \"./L2CrossDomainMessenger.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title CrossDomainOwnable2\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is meant to be used with systems that use\n * the CrossDomainMessenger system. It will not work if the OptimismPortal is used\n * directly.\n */\nabstract contract CrossDomainOwnable2 is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `xDomainMessageSender` is the owner of the contract. This value is set to the caller\n * of the L1CrossDomainMessenger.\n */\n function _checkOwner() internal view override {\n L2CrossDomainMessenger messenger = L2CrossDomainMessenger(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER\n );\n\n require(\n msg.sender == address(messenger),\n \"CrossDomainOwnable2: caller is not the messenger\"\n );\n\n require(\n owner() == messenger.xDomainMessageSender(),\n \"CrossDomainOwnable2: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/GasPriceOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000000F\n * @title GasPriceOracle\n * @notice This contract maintains the variables responsible for computing the L1 portion of the\n * total fee charged on L2. Before Bedrock, this contract held variables in state that were\n * read during the state transition function to compute the L1 portion of the transaction\n * fee. After Bedrock, this contract now simply proxies the L1Block contract, which has\n * the values used to compute the L1 portion of the fee in its state.\n *\n * The contract exposes an API that is useful for knowing how large the L1 portion of the\n * transaction fee will be. The following events were deprecated with Bedrock:\n * - event OverheadUpdated(uint256 overhead);\n * - event ScalarUpdated(uint256 scalar);\n * - event DecimalsUpdated(uint256 decimals);\n */\ncontract GasPriceOracle is Semver {\n /**\n * @notice Number of decimals used in the scalar.\n */\n uint256 public constant DECIMALS = 6;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Computes the L1 portion of the fee based on the size of the rlp encoded input\n * transaction, the current L1 base fee, and the various dynamic parameters.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for.\n *\n * @return L1 fee that should be paid for the tx\n */\n function getL1Fee(bytes memory _data) external view returns (uint256) {\n uint256 l1GasUsed = getL1GasUsed(_data);\n uint256 l1Fee = l1GasUsed * l1BaseFee();\n uint256 divisor = 10**DECIMALS;\n uint256 unscaled = l1Fee * scalar();\n uint256 scaled = unscaled / divisor;\n return scaled;\n }\n\n /**\n * @notice Retrieves the current gas price (base fee).\n *\n * @return Current L2 gas price (base fee).\n */\n function gasPrice() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current base fee.\n *\n * @return Current L2 base fee.\n */\n function baseFee() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current fee overhead.\n *\n * @return Current fee overhead.\n */\n function overhead() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead();\n }\n\n /**\n * @notice Retrieves the current fee scalar.\n *\n * @return Current fee scalar.\n */\n function scalar() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar();\n }\n\n /**\n * @notice Retrieves the latest known L1 base fee.\n *\n * @return Latest known L1 base fee.\n */\n function l1BaseFee() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee();\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the number of decimals used in the scalar.\n *\n * @return Number of decimals used in the scalar.\n */\n function decimals() public pure returns (uint256) {\n return DECIMALS;\n }\n\n /**\n * @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which\n * represents the per-transaction gas overhead of posting the transaction and state\n * roots to L1. Adds 68 bytes of padding to account for the fact that the input does\n * not have a signature.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for.\n *\n * @return Amount of L1 gas used to publish the transaction.\n */\n function getL1GasUsed(bytes memory _data) public view returns (uint256) {\n uint256 total = 0;\n uint256 length = _data.length;\n for (uint256 i = 0; i < length; i++) {\n if (_data[i] == 0) {\n total += 4;\n } else {\n total += 16;\n }\n }\n uint256 unsigned = total + overhead();\n return unsigned + (68 * 16);\n }\n}\n" - }, - "contracts/L2/L1Block.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000015\n * @title L1Block\n * @notice The L1Block predeploy gives users access to information about the last known L1 block.\n * Values within this contract are updated once per epoch (every L1 block) and can only be\n * set by the \"depositor\" account, a special system address. Depositor account transactions\n * are created by the protocol whenever we move to a new epoch.\n */\ncontract L1Block is Semver {\n /**\n * @notice Address of the special depositor account.\n */\n address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001;\n\n /**\n * @notice The latest L1 block number known by the L2 system.\n */\n uint64 public number;\n\n /**\n * @notice The latest L1 timestamp known by the L2 system.\n */\n uint64 public timestamp;\n\n /**\n * @notice The latest L1 basefee.\n */\n uint256 public basefee;\n\n /**\n * @notice The latest L1 blockhash.\n */\n bytes32 public hash;\n\n /**\n * @notice The number of L2 blocks in the same epoch.\n */\n uint64 public sequenceNumber;\n\n /**\n * @notice The versioned hash to authenticate the batcher by.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice The overhead value applied to the L1 portion of the transaction\n * fee.\n */\n uint256 public l1FeeOverhead;\n\n /**\n * @notice The scalar value applied to the L1 portion of the transaction fee.\n */\n uint256 public l1FeeScalar;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Updates the L1 block values.\n *\n * @param _number L1 blocknumber.\n * @param _timestamp L1 timestamp.\n * @param _basefee L1 basefee.\n * @param _hash L1 blockhash.\n * @param _sequenceNumber Number of L2 blocks since epoch start.\n * @param _batcherHash Versioned hash to authenticate batcher by.\n * @param _l1FeeOverhead L1 fee overhead.\n * @param _l1FeeScalar L1 fee scalar.\n */\n function setL1BlockValues(\n uint64 _number,\n uint64 _timestamp,\n uint256 _basefee,\n bytes32 _hash,\n uint64 _sequenceNumber,\n bytes32 _batcherHash,\n uint256 _l1FeeOverhead,\n uint256 _l1FeeScalar\n ) external {\n require(\n msg.sender == DEPOSITOR_ACCOUNT,\n \"L1Block: only the depositor account can set L1 block values\"\n );\n\n number = _number;\n timestamp = _timestamp;\n basefee = _basefee;\n hash = _hash;\n sequenceNumber = _sequenceNumber;\n batcherHash = _batcherHash;\n l1FeeOverhead = _l1FeeOverhead;\n l1FeeScalar = _l1FeeScalar;\n }\n}\n" - }, - "contracts/L2/L1FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000001A\n * @title L1FeeVault\n * @notice The L1FeeVault accumulates the L1 portion of the transaction fees.\n */\ncontract L1FeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 0, 0) {}\n}\n" - }, - "contracts/L2/L2CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { L2ToL1MessagePasser } from \"./L2ToL1MessagePasser.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000007\n * @title L2CrossDomainMessenger\n * @notice The L2CrossDomainMessenger is a high-level interface for message passing between L1 and\n * L2 on the L2 side. Users are generally encouraged to use this contract instead of lower\n * level message passing contracts.\n */\ncontract L2CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _l1CrossDomainMessenger Address of the L1CrossDomainMessenger contract.\n */\n constructor(address _l1CrossDomainMessenger)\n Semver(1, 0, 0)\n CrossDomainMessenger(_l1CrossDomainMessenger)\n {\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote messenger. Use otherMessenger going forward.\n *\n * @return Address of the L1CrossDomainMessenger contract.\n */\n function l1CrossDomainMessenger() public view returns (address) {\n return OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)).initiateWithdrawal{\n value: _value\n }(_to, _gasLimit, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(Predeploys.L2_TO_L1_MESSAGE_PASSER);\n }\n}\n" - }, - "contracts/L2/L2ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../universal/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 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(OTHER_BRIDGE, message, _minGasLimit);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L2/L2StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000010\n * @title L2StandardBridge\n * @notice The L2StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L2, it will be escrowed within this\n * contract. If the ERC20 token is native to L1, it will be burnt.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L2StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal from L2 to L1 is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _otherBridge Address of the L1StandardBridge.\n */\n constructor(address payable _otherBridge)\n Semver(1, 0, 0)\n StandardBridge(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER), _otherBridge)\n {}\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdraw(\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual onlyEOA {\n _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1 to a target account on L1.\n * Note that if ETH is sent to a contract on L1 and the call fails, then that ETH will\n * be locked in the L1StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdrawTo(\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual {\n _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a deposit from L1 to L2.\n *\n * @param _l1Token Address of the L1 token to deposit.\n * @param _l2Token Address of the corresponding L2 token.\n * @param _from Address of the depositor.\n * @param _to Address of the recipient.\n * @param _amount Amount of the tokens being deposited.\n * @param _extraData Extra data attached to the deposit.\n */\n function finalizeDeposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable virtual {\n if (_l1Token == address(0) && _l2Token == Predeploys.LEGACY_ERC20_ETH) {\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n } else {\n finalizeBridgeERC20(_l2Token, _l1Token, _from, _to, _amount, _extraData);\n }\n\n emit DepositFinalized(_l1Token, _l2Token, _from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L1 bridge contract.\n *\n * @return Address of the corresponding L1 bridge contract.\n */\n function l1TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @custom:legacy\n * @notice Internal function to a withdrawal from L2 to L1 to a target account on L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _from Address of the withdrawer.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function _initiateWithdrawal(\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal {\n address l1Token = OptimismMintableERC20(_l2Token).l1Token();\n if (_l2Token == Predeploys.LEGACY_ERC20_ETH) {\n _initiateBridgeETH(_from, _to, _amount, _minGasLimit, _extraData);\n } else {\n _initiateBridgeERC20(_l2Token, l1Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n\n emit WithdrawalInitiated(l1Token, _l2Token, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/L2/L2ToL1MessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000016\n * @title L2ToL1MessagePasser\n * @notice The L2ToL1MessagePasser is a dedicated contract where messages that are being sent from\n * L2 to L1 can be stored. The storage root of this contract is pulled up to the top level\n * of the L2 output to reduce the cost of proving the existence of sent messages.\n */\ncontract L2ToL1MessagePasser is Semver {\n /**\n * @notice The L1 gas limit set when eth is withdrawn using the receive() function.\n */\n uint256 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Current message version identifier.\n */\n uint16 public constant MESSAGE_VERSION = 1;\n\n /**\n * @notice Includes the message hashes for all withdrawals\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @notice A unique value hashed with each withdrawal.\n */\n uint240 internal msgNonce;\n\n /**\n * @notice Emitted any time a withdrawal is initiated.\n *\n * @param nonce Unique value corresponding to each withdrawal.\n * @param sender The L2 account address which initiated the withdrawal.\n * @param target The L1 account address the call will be send to.\n * @param value The ETH value submitted for withdrawal, to be forwarded to the target.\n * @param gasLimit The minimum amount of gas that must be provided when withdrawing.\n * @param data The data to be forwarded to the target on L1.\n * @param withdrawalHash The hash of the withdrawal.\n */\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n /**\n * @notice Emitted when the balance of this contract is burned.\n *\n * @param amount Amount of ETh that was burned.\n */\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Allows users to withdraw ETH by sending directly to this contract.\n */\n receive() external payable {\n initiateWithdrawal(msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @notice Removes all ETH held by this contract from the state. Used to prevent the amount of\n * ETH on L2 inflating when ETH is withdrawn. Currently only way to do this is to\n * create a contract and self-destruct it to itself. Anyone can call this function. Not\n * incentivized since this function is very cheap.\n */\n function burn() external {\n uint256 balance = address(this).balance;\n Burn.eth(balance);\n emit WithdrawerBalanceBurnt(balance);\n }\n\n /**\n * @notice Sends a message from L2 to L1.\n *\n * @param _target Address to call on L1 execution.\n * @param _gasLimit Minimum gas limit for executing the message on L1.\n * @param _data Data to forward to L1 target.\n */\n function initiateWithdrawal(\n address _target,\n uint256 _gasLimit,\n bytes memory _data\n ) public payable {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messageNonce(),\n sender: msg.sender,\n target: _target,\n value: msg.value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n sentMessages[withdrawalHash] = true;\n\n emit MessagePassed(\n messageNonce(),\n msg.sender,\n _target,\n msg.value,\n _gasLimit,\n _data,\n withdrawalHash\n );\n\n unchecked {\n ++msgNonce;\n }\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" - }, - "contracts/L2/SequencerFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000011\n * @title SequencerFeeVault\n * @notice The SequencerFeeVault is the contract that holds any fees paid to the Sequencer during\n * transaction processing and block production.\n */\ncontract SequencerFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 0, 0) {}\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the recipient address.\n *\n * @return The recipient address.\n */\n function l1FeeWallet() public view returns (address) {\n return RECIPIENT;\n }\n}\n" - }, - "contracts/deployment/PortalSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/**\n * @title PortalSender\n * @notice The PortalSender is a simple intermediate contract that will transfer the balance of the\n * L1StandardBridge to the OptimismPortal during the Bedrock migration.\n */\ncontract PortalSender {\n /**\n * @notice Address of the OptimismPortal contract.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @param _portal Address of the OptimismPortal contract.\n */\n constructor(OptimismPortal _portal) {\n PORTAL = _portal;\n }\n\n /**\n * @notice Sends balance of this contract to the OptimismPortal.\n */\n function donate() public {\n PORTAL.donateETH{ value: address(this).balance }();\n }\n}\n" - }, - "contracts/deployment/SystemDictator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { PortalSender } from \"./PortalSender.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\n\n/**\n * @title SystemDictator\n * @notice The SystemDictator is responsible for coordinating the deployment of a full Bedrock\n * system. The SystemDictator is designed to support both fresh network deployments and\n * upgrades to existing pre-Bedrock systems.\n */\ncontract SystemDictator is OwnableUpgradeable {\n /**\n * @notice Basic system configuration.\n */\n struct GlobalConfig {\n AddressManager addressManager;\n ProxyAdmin proxyAdmin;\n address controller;\n address finalOwner;\n }\n\n /**\n * @notice Set of proxy addresses.\n */\n struct ProxyAddressConfig {\n address l2OutputOracleProxy;\n address optimismPortalProxy;\n address l1CrossDomainMessengerProxy;\n address l1StandardBridgeProxy;\n address optimismMintableERC20FactoryProxy;\n address l1ERC721BridgeProxy;\n address systemConfigProxy;\n }\n\n /**\n * @notice Set of implementation addresses.\n */\n struct ImplementationAddressConfig {\n L2OutputOracle l2OutputOracleImpl;\n OptimismPortal optimismPortalImpl;\n L1CrossDomainMessenger l1CrossDomainMessengerImpl;\n L1StandardBridge l1StandardBridgeImpl;\n OptimismMintableERC20Factory optimismMintableERC20FactoryImpl;\n L1ERC721Bridge l1ERC721BridgeImpl;\n PortalSender portalSenderImpl;\n SystemConfig systemConfigImpl;\n }\n\n /**\n * @notice Dynamic L2OutputOracle config.\n */\n struct L2OutputOracleDynamicConfig {\n uint256 l2OutputOracleStartingBlockNumber;\n uint256 l2OutputOracleStartingTimestamp;\n }\n\n /**\n * @notice Values for the system config contract.\n */\n struct SystemConfigConfig {\n address owner;\n uint256 overhead;\n uint256 scalar;\n bytes32 batcherHash;\n uint64 gasLimit;\n address unsafeBlockSigner;\n }\n\n /**\n * @notice Combined system configuration.\n */\n struct DeployConfig {\n GlobalConfig globalConfig;\n ProxyAddressConfig proxyAddressConfig;\n ImplementationAddressConfig implementationAddressConfig;\n SystemConfigConfig systemConfigConfig;\n }\n\n /**\n * @notice Step after which exit 1 can no longer be used.\n */\n uint8 public constant EXIT_1_NO_RETURN_STEP = 3;\n\n /**\n * @notice Step where proxy ownership is transferred.\n */\n uint8 public constant PROXY_TRANSFER_STEP = 4;\n\n /**\n * @notice System configuration.\n */\n DeployConfig public config;\n\n /**\n * @notice Dynamic configuration for the L2OutputOracle.\n */\n L2OutputOracleDynamicConfig public l2OutputOracleDynamicConfig;\n\n /**\n * @notice Current step;\n */\n uint8 public currentStep;\n\n /**\n * @notice Whether or not dynamic config has been set.\n */\n bool public dynamicConfigSet;\n\n /**\n * @notice Whether or not the deployment is finalized.\n */\n bool public finalized;\n\n /**\n * @notice Address of the old L1CrossDomainMessenger implementation.\n */\n address public oldL1CrossDomainMessenger;\n\n /**\n * @notice Checks that the current step is the expected step, then bumps the current step.\n *\n * @param _step Current step.\n */\n modifier step(uint8 _step) {\n require(currentStep == _step, \"BaseSystemDictator: incorrect step\");\n _;\n currentStep++;\n }\n\n /**\n * @param _config System configuration.\n */\n function initialize(DeployConfig memory _config) public initializer {\n config = _config;\n currentStep = 1;\n __Ownable_init();\n _transferOwnership(config.globalConfig.controller);\n }\n\n /**\n * @notice Allows the owner to update dynamic L2OutputOracle config.\n *\n * @param _l2OutputOracleDynamicConfig Dynamic L2OutputOracle config.\n */\n function updateL2OutputOracleDynamicConfig(\n L2OutputOracleDynamicConfig memory _l2OutputOracleDynamicConfig\n ) external onlyOwner {\n l2OutputOracleDynamicConfig = _l2OutputOracleDynamicConfig;\n dynamicConfigSet = true;\n }\n\n /**\n * @notice Configures the ProxyAdmin contract.\n */\n function step1() external onlyOwner step(1) {\n // Set the AddressManager in the ProxyAdmin.\n config.globalConfig.proxyAdmin.setAddressManager(config.globalConfig.addressManager);\n\n // Set the L1CrossDomainMessenger to the RESOLVED proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n ProxyAdmin.ProxyType.RESOLVED\n );\n\n // Set the implementation name for the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.setImplementationName(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Set the L1StandardBridge to the CHUGSPLASH proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1StandardBridgeProxy,\n ProxyAdmin.ProxyType.CHUGSPLASH\n );\n }\n\n /**\n * @notice Pauses the system by shutting down the L1CrossDomainMessenger and setting the\n * deposit halt flag to tell the Sequencer's DTL to stop accepting deposits.\n */\n function step2() external onlyOwner step(2) {\n // Store the address of the old L1CrossDomainMessenger implementation. We will need this\n // address in the case that we have to exit early.\n oldL1CrossDomainMessenger = config.globalConfig.addressManager.getAddress(\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Temporarily brick the L1CrossDomainMessenger by setting its implementation address to\n // address(0) which will cause the ResolvedDelegateProxy to revert. Better than pausing\n // the L1CrossDomainMessenger via pause() because it can be easily reverted.\n config.globalConfig.addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(0));\n\n // Set the DTL shutoff block, which will tell the DTL to stop syncing new deposits from the\n // CanonicalTransactionChain. We do this by setting an address in the AddressManager\n // because the DTL already has a reference to the AddressManager and this way we don't also\n // need to give it a reference to the SystemDictator.\n config.globalConfig.addressManager.setAddress(\n \"DTL_SHUTOFF_BLOCK\",\n address(uint160(block.number))\n );\n }\n\n /**\n * @notice Removes deprecated addresses from the AddressManager.\n */\n function step3() external onlyOwner step(EXIT_1_NO_RETURN_STEP) {\n // Remove all deprecated addresses from the AddressManager\n string[17] memory deprecated = [\n \"OVM_CanonicalTransactionChain\",\n \"OVM_L2CrossDomainMessenger\",\n \"OVM_DecompressionPrecompileAddress\",\n \"OVM_Sequencer\",\n \"OVM_Proposer\",\n \"OVM_ChainStorageContainer-CTC-batches\",\n \"OVM_ChainStorageContainer-CTC-queue\",\n \"OVM_CanonicalTransactionChain\",\n \"OVM_StateCommitmentChain\",\n \"OVM_BondManager\",\n \"OVM_ExecutionManager\",\n \"OVM_FraudVerifier\",\n \"OVM_StateManagerFactory\",\n \"OVM_StateTransitionerFactory\",\n \"OVM_SafetyChecker\",\n \"OVM_L1MultiMessageRelayer\",\n \"BondManager\"\n ];\n\n for (uint256 i = 0; i < deprecated.length; i++) {\n config.globalConfig.addressManager.setAddress(deprecated[i], address(0));\n }\n }\n\n /**\n * @notice Transfers system ownership to the ProxyAdmin.\n */\n function step4() external onlyOwner step(PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the ProxyAdmin.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1StandardBridge to the ProxyAdmin.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the ProxyAdmin.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.proxyAdmin)\n );\n }\n\n /**\n * @notice Upgrades and initializes proxy contracts.\n */\n function step5() external onlyOwner step(5) {\n // Dynamic config must be set before we can initialize the L2OutputOracle.\n require(dynamicConfigSet, \"SystemDictator: dynamic oracle config is not yet initialized\");\n\n // Upgrade and initialize the L2OutputOracle.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l2OutputOracleProxy),\n address(config.implementationAddressConfig.l2OutputOracleImpl),\n abi.encodeCall(\n L2OutputOracle.initialize,\n (\n l2OutputOracleDynamicConfig.l2OutputOracleStartingBlockNumber,\n l2OutputOracleDynamicConfig.l2OutputOracleStartingTimestamp\n )\n )\n );\n\n // Upgrade and initialize the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.optimismPortalProxy),\n address(config.implementationAddressConfig.optimismPortalImpl),\n abi.encodeCall(OptimismPortal.initialize, ())\n );\n\n // Upgrade the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1CrossDomainMessengerProxy),\n address(config.implementationAddressConfig.l1CrossDomainMessengerImpl)\n );\n\n // Try to initialize the L1CrossDomainMessenger, only fail if it's already been initialized.\n try\n L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy)\n .initialize(address(this))\n {\n // L1CrossDomainMessenger is the one annoying edge case difference between existing\n // networks and fresh networks because in existing networks it'll already be\n // initialized but in fresh networks it won't be. Try/catch is the easiest and most\n // consistent way to handle this because initialized() is not exposed publicly.\n } catch Error(string memory reason) {\n require(\n keccak256(abi.encodePacked(reason)) ==\n keccak256(\"Initializable: contract is already initialized\"),\n string.concat(\"SystemDictator: unexpected error initializing L1XDM: \", reason)\n );\n } catch {\n revert(\"SystemDictator: unexpected error initializing L1XDM (no reason)\");\n }\n\n // Transfer ETH from the L1StandardBridge to the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.portalSenderImpl),\n abi.encodeCall(PortalSender.donate, ())\n );\n\n // Upgrade the L1StandardBridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.l1StandardBridgeImpl)\n );\n\n // Upgrade the OptimismMintableERC20Factory (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.optimismMintableERC20FactoryProxy),\n address(config.implementationAddressConfig.optimismMintableERC20FactoryImpl)\n );\n\n // Upgrade the L1ERC721Bridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1ERC721BridgeProxy),\n address(config.implementationAddressConfig.l1ERC721BridgeImpl)\n );\n\n // Upgrade and initialize the SystemConfig.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.systemConfigProxy),\n address(config.implementationAddressConfig.systemConfigImpl),\n abi.encodeCall(\n SystemConfig.initialize,\n (\n config.systemConfigConfig.owner,\n config.systemConfigConfig.overhead,\n config.systemConfigConfig.scalar,\n config.systemConfigConfig.batcherHash,\n config.systemConfigConfig.gasLimit,\n config.systemConfigConfig.unsafeBlockSigner\n )\n )\n );\n\n // Pause the L1CrossDomainMessenger, chance to check that everything is OK.\n L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy).pause();\n }\n\n /**\n * @notice Unpauses the system at which point the system should be fully operational.\n */\n function step6() external onlyOwner step(6) {\n // Unpause the L1CrossDomainMessenger.\n L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy).unpause();\n }\n\n /**\n * @notice Tranfers admin ownership to the final owner.\n */\n function finalize() external onlyOwner {\n // Transfer ownership of the L1CrossDomainMessenger to the final owner.\n L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy)\n .transferOwnership(config.globalConfig.finalOwner);\n\n // Transfer ownership of the ProxyAdmin to the final owner.\n config.globalConfig.proxyAdmin.transferOwnership(config.globalConfig.finalOwner);\n\n // Optionally also transfer AddressManager and L1StandardBridge if we still own it. Might\n // happen if we're exiting early.\n if (currentStep <= PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the final owner.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1StandardBridge to the final owner.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the final owner.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.finalOwner)\n );\n }\n\n finalized = true;\n }\n\n /**\n * @notice First exit point, can only be called before step 3 is executed.\n */\n function exit1() external onlyOwner {\n require(\n currentStep == EXIT_1_NO_RETURN_STEP,\n \"SystemDictator: can only exit1 before step 3 is executed\"\n );\n\n // Reset the L1CrossDomainMessenger to the old implementation.\n config.globalConfig.addressManager.setAddress(\n \"OVM_L1CrossDomainMessenger\",\n oldL1CrossDomainMessenger\n );\n\n // Unset the DTL shutoff block which will allow the DTL to sync again.\n config.globalConfig.addressManager.setAddress(\"DTL_SHUTOFF_BLOCK\", address(0));\n }\n}\n" - }, - "contracts/echidna/FuzzAddressAliasing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract EchidnaFuzzAddressAliasing {\n bool internal failedRoundtrip;\n\n /**\n * @notice Takes an address to be aliased with AddressAliasHelper and then unaliased\n * and updates the test contract's state indicating if the round trip encoding\n * failed.\n */\n function testRoundTrip(address addr) public {\n // Alias our address\n address aliasedAddr = AddressAliasHelper.applyL1ToL2Alias(addr);\n\n // Unalias our address\n address undoneAliasAddr = AddressAliasHelper.undoL1ToL2Alias(aliasedAddr);\n\n // If our round trip aliasing did not return the original result, set our state.\n if (addr != undoneAliasAddr) {\n failedRoundtrip = true;\n }\n }\n\n /**\n * @custom:invariant Address aliases are always able to be undone.\n *\n * Asserts that an address that has been aliased with `applyL1ToL2Alias` can always\n * be unaliased with `undoL1ToL2Alias`.\n */\n function echidna_round_trip_aliasing() public view returns (bool) {\n // ASSERTION: The round trip aliasing done in testRoundTrip(...) should never fail.\n return !failedRoundtrip;\n }\n}\n" - }, - "contracts/echidna/FuzzBurn.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\n\ncontract EchidnaFuzzBurnEth is StdUtils {\n bool internal failedEthBurn;\n\n /**\n * @notice Takes an integer amount of eth to burn through the Burn library and\n * updates the contract state if an incorrect amount of eth moved from the contract\n */\n function testBurn(uint256 _value) public {\n // cache the contract's eth balance\n uint256 preBurnBalance = address(this).balance;\n uint256 value = bound(_value, 0, preBurnBalance);\n\n // execute a burn of _value eth\n Burn.eth(value);\n\n // check that exactly value eth was transfered from the contract\n unchecked {\n if (address(this).balance != preBurnBalance - value) {\n failedEthBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `eth(uint256)` always burns the exact amount of eth passed.\n *\n * Asserts that when `Burn.eth(uint256)` is called, it always burns the exact amount\n * of ETH passed to the function.\n */\n function echidna_burn_eth() public view returns (bool) {\n // ASSERTION: The amount burned should always match the amount passed exactly\n return !failedEthBurn;\n }\n}\n\ncontract EchidnaFuzzBurnGas is StdUtils {\n bool internal failedGasBurn;\n\n /**\n * @notice Takes an integer amount of gas to burn through the Burn library and\n * updates the contract state if at least that amount of gas was not burned\n * by the library\n */\n function testGas(uint256 _value) public {\n // cap the value to the max resource limit\n uint256 MAX_RESOURCE_LIMIT = 8_000_000;\n uint256 value = bound(_value, 0, MAX_RESOURCE_LIMIT);\n\n // cache the contract's current remaining gas\n uint256 preBurnGas = gasleft();\n\n // execute the gas burn\n Burn.gas(value);\n\n // cache the remaining gas post burn\n uint256 postBurnGas = gasleft();\n\n // check that at least value gas was burnt (and that there was no underflow)\n unchecked {\n if (postBurnGas - preBurnGas > value || preBurnGas - value > preBurnGas) {\n failedGasBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `gas(uint256)` always burns at least the amount of gas passed.\n *\n * Asserts that when `Burn.gas(uint256)` is called, it always burns at least the amount\n * of gas passed to the function.\n */\n function echidna_burn_gas() public view returns (bool) {\n // ASSERTION: The amount of gas burned should be strictly greater than the\n // the amount passed as _value (minimum _value + whatever minor overhead to\n // the value after the call)\n return !failedGasBurn;\n }\n}\n" - }, - "contracts/echidna/FuzzEncoding.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzEncoding {\n bool internal failedRoundtripAToB;\n bool internal failedRoundtripBToA;\n\n /**\n * @notice Takes a pair of integers to be encoded into a versioned nonce with the\n * Encoding library and then decoded and updates the test contract's state\n * indicating if the round trip encoding failed.\n */\n function testRoundTripAToB(uint240 _nonce, uint16 _version) public {\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(encodedVersionedNonce);\n\n // If our round trip encoding did not return the original result, set our state.\n if ((decodedNonce != _nonce) || (decodedVersion != _version)) {\n failedRoundtripAToB = true;\n }\n }\n\n /**\n * @notice Takes an integer representing a packed version and nonce and attempts\n * to decode them using the Encoding library before re-encoding and updates\n * the test contract's state indicating if the round trip encoding failed.\n */\n function testRoundTripBToA(uint256 _versionedNonce) public {\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(_versionedNonce);\n\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(decodedNonce, decodedVersion);\n\n // If our round trip encoding did not return the original result, set our state.\n if (encodedVersionedNonce != _versionedNonce) {\n failedRoundtripBToA = true;\n }\n }\n\n /**\n * @custom:invariant `testRoundTripAToB` never fails.\n *\n * Asserts that a raw versioned nonce can be encoded / decoded to reach the same raw value.\n */\n function echidna_round_trip_encoding_AToB() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripAToB(...)\n return !failedRoundtripAToB;\n }\n\n /**\n * @custom:invariant `testRoundTripBToA` never fails.\n *\n * Asserts that an encoded versioned nonce can always be decoded / re-encoded to reach\n * the same encoded value.\n */\n function echidna_round_trip_encoding_BToA() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripBToA should never\n // fail.\n return !failedRoundtripBToA;\n }\n}\n" - }, - "contracts/echidna/FuzzHashing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzHashing {\n bool internal failedCrossDomainHashHighVersion;\n bool internal failedCrossDomainHashV0;\n bool internal failedCrossDomainHashV1;\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash with a randomly\n * generated version. Only schema versions 0 and 1 are supported and all others should revert.\n */\n function testHashCrossDomainMessageHighVersion(\n uint16 _version,\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // hash the cross domain message. we don't need to store the result since the function\n // validates and should revert if an invalid version (>1) is encoded\n Hashing.hashCrossDomainMessage(encodedNonce, _sender, _target, _value, _gasLimit, _data);\n\n // check that execution never makes it this far for an invalid version\n if (_version > 1) {\n failedCrossDomainHashHighVersion = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v0 schema\n * and compares the output of a call to the unversioned function to the v0 function directly\n */\n function testHashCrossDomainMessageV0(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 0\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 0);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV0(\n _target,\n _sender,\n _data,\n encodedNonce\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV0 = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v1 schema\n * and compares the output of a call to the unversioned function to the v1 function directly\n */\n function testHashCrossDomainMessageV1(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 1\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 1);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV1(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV1 = true;\n }\n }\n\n /**\n * @custom:invariant `hashCrossDomainMessage` reverts if `version` is > `1`.\n *\n * The `hashCrossDomainMessage` function should always revert if the `version` passed is > `1`.\n */\n function echidna_hash_xdomain_msg_high_version() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage will never succeed for a version > 1\n return !failedCrossDomainHashHighVersion;\n }\n\n /**\n * @custom:invariant `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0`\n * are equivalent.\n *\n * If the version passed is 0, `hashCrossDomainMessage` and `hashCrossDomainMessageV0` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_0() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV0\n // should always match when the version passed is 0\n return !failedCrossDomainHashV0;\n }\n\n /**\n * @custom:invariant `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1`\n * are equivalent.\n *\n * If the version passed is 1, `hashCrossDomainMessage` and `hashCrossDomainMessageV1` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_1() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV1\n // should always match when the version passed is 1\n return !failedCrossDomainHashV1;\n }\n}\n" - }, - "contracts/echidna/FuzzOptimismPortal.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract EchidnaFuzzOptimismPortal {\n OptimismPortal internal portal;\n bool internal failedToComplete;\n\n constructor() {\n portal = new OptimismPortal(L2OutputOracle(address(0)), 10);\n }\n\n // A test intended to identify any unexpected halting conditions\n function testDepositTransactionCompletes(\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable {\n failedToComplete = true;\n require(!_isCreation || _to == address(0), \"EchidnaFuzzOptimismPortal: invalid test case.\");\n portal.depositTransaction{ value: _mint }(_to, _value, _gasLimit, _isCreation, _data);\n failedToComplete = false;\n }\n\n /**\n * @custom:invariant Deposits of any value should always succeed unless\n * `_to` = `address(0)` or `_isCreation` = `true`.\n *\n * All deposits, barring creation transactions and transactions sent to `address(0)`,\n * should always succeed.\n */\n function echidna_deposit_completes() public view returns (bool) {\n return !failedToComplete;\n }\n}\n" - }, - "contracts/echidna/FuzzResourceMetering.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\n\ncontract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {\n bool internal failedMaxGasPerBlock;\n bool internal failedRaiseBaseFee;\n bool internal failedLowerBaseFee;\n bool internal failedNeverBelowMinBaseFee;\n bool internal failedMaxRaiseBaseFeePerBlock;\n bool internal failedMaxLowerBaseFeePerBlock;\n\n // Used as a special flag for the purpose of identifying unchecked math errors specifically\n // in the test contracts, not the target contracts themselves.\n bool internal underflow;\n\n constructor() {\n initialize();\n }\n\n function initialize() internal initializer {\n __ResourceMetering_init();\n }\n\n /**\n * @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test\n * the underlying resource metering/gas market logic\n */\n function testBurn(uint256 _gasToBurn, bool _raiseBaseFee) public {\n // Part 1: we cache the current param values and do some basic checks on them.\n uint256 cachedPrevBaseFee = uint256(params.prevBaseFee);\n uint256 cachedPrevBoughtGas = uint256(params.prevBoughtGas);\n uint256 cachedPrevBlockNum = uint256(params.prevBlockNum);\n\n // check that the last block's base fee hasn't dropped below the minimum\n if (cachedPrevBaseFee < uint256(MINIMUM_BASE_FEE)) {\n failedNeverBelowMinBaseFee = true;\n }\n // check that the last block didn't consume more than the max amount of gas\n if (cachedPrevBoughtGas > uint256(MAX_RESOURCE_LIMIT)) {\n failedMaxGasPerBlock = true;\n }\n\n // Part2: we perform the gas burn\n\n // force the gasToBurn into the correct range based on whether we intend to\n // raise or lower the baseFee after this block, respectively\n uint256 gasToBurn;\n if (_raiseBaseFee) {\n gasToBurn = bound(\n _gasToBurn,\n uint256(TARGET_RESOURCE_LIMIT),\n uint256(MAX_RESOURCE_LIMIT)\n );\n } else {\n gasToBurn = bound(_gasToBurn, 0, uint256(TARGET_RESOURCE_LIMIT));\n }\n\n _burnInternal(uint64(gasToBurn));\n\n // Part 3: we run checks and modify our invariant flags based on the updated params values\n\n // Calculate the maximum allowed baseFee change (per block)\n uint256 maxBaseFeeChange = cachedPrevBaseFee / uint256(BASE_FEE_MAX_CHANGE_DENOMINATOR);\n\n // If the last block used more than the target amount of gas (and there were no\n // empty blocks in between), ensure this block's baseFee increased, but not by\n // more than the max amount per block\n if (\n (cachedPrevBoughtGas > uint256(TARGET_RESOURCE_LIMIT)) &&\n (uint256(params.prevBlockNum) - cachedPrevBlockNum == 1)\n ) {\n failedRaiseBaseFee = failedRaiseBaseFee || (params.prevBaseFee <= cachedPrevBaseFee);\n failedMaxRaiseBaseFeePerBlock =\n failedMaxRaiseBaseFeePerBlock ||\n ((uint256(params.prevBaseFee) - cachedPrevBaseFee) < maxBaseFeeChange);\n }\n\n // If the last block used less than the target amount of gas, (or was empty),\n // ensure that: this block's baseFee was decreased, but not by more than the max amount\n if (\n (cachedPrevBoughtGas < uint256(TARGET_RESOURCE_LIMIT)) ||\n (uint256(params.prevBlockNum) - cachedPrevBlockNum > 1)\n ) {\n // Invariant: baseFee should decrease\n failedLowerBaseFee =\n failedLowerBaseFee ||\n (uint256(params.prevBaseFee) > cachedPrevBaseFee);\n\n if (params.prevBlockNum - cachedPrevBlockNum == 1) {\n // No empty blocks\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n } else if (params.prevBlockNum - cachedPrevBlockNum > 1) {\n // We have at least one empty block\n // Update the maxBaseFeeChange to account for multiple blocks having passed\n unchecked {\n maxBaseFeeChange = uint256(\n int256(cachedPrevBaseFee) -\n Arithmetic.clamp(\n Arithmetic.cdexp(\n int256(cachedPrevBaseFee),\n BASE_FEE_MAX_CHANGE_DENOMINATOR,\n int256(uint256(params.prevBlockNum) - cachedPrevBlockNum)\n ),\n MINIMUM_BASE_FEE,\n MAXIMUM_BASE_FEE\n )\n );\n }\n\n // Detect an underflow in the previous calculation.\n // Without using unchecked above, and detecting the underflow here, echidna would\n // otherwise ignore the revert.\n underflow = underflow || maxBaseFeeChange > cachedPrevBaseFee;\n\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n }\n }\n }\n\n function _burnInternal(uint64 _gasToBurn) private metered(_gasToBurn) {}\n\n /**\n * @custom:invariant The base fee should increase if the last block used more\n * than the target amount of gas\n *\n * If the last block used more than the target amount of gas (and there were no\n * empty blocks in between), ensure this block's baseFee increased, but not by\n * more than the max amount per block.\n */\n function echidna_high_usage_raise_baseFee() public view returns (bool) {\n return !failedRaiseBaseFee;\n }\n\n /**\n * @custom:invariant The base fee should decrease if the last block used less\n * than the target amount of gas\n *\n * If the previous block used less than the target amount of gas, the base fee should decrease,\n * but not more than the max amount.\n */\n function echidna_low_usage_lower_baseFee() public view returns (bool) {\n return !failedLowerBaseFee;\n }\n\n /**\n * @custom:invariant A block's base fee should never be below `MINIMUM_BASE_FEE`\n *\n * This test asserts that a block's base fee can never drop below the\n * `MINIMUM_BASE_FEE` threshold.\n */\n function echidna_never_below_min_baseFee() public view returns (bool) {\n return !failedNeverBelowMinBaseFee;\n }\n\n /**\n * @custom:invariant A block can never consume more than `MAX_RESOURCE_LIMIT` gas.\n *\n * This test asserts that a block can never consume more than the `MAX_RESOURCE_LIMIT`\n * gas threshold.\n */\n function echidna_never_above_max_gas_limit() public view returns (bool) {\n return !failedMaxGasPerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be raised more than the max base fee change.\n *\n * After a block consumes more gas than the target gas, the base fee cannot be raised\n * more than the maximum amount allowed. The max base fee change (per-block) is derived\n * as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_increase() public view returns (bool) {\n return !failedMaxRaiseBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be lowered more than the max base fee change.\n *\n * After a block consumes less than the target gas, the base fee cannot be lowered more\n * than the maximum amount allowed. The max base fee change (per-block) is derived as\n *follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_decrease() public view returns (bool) {\n return !failedMaxLowerBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The `maxBaseFeeChange` calculation over multiple blocks can never\n * underflow.\n *\n * When calculating the `maxBaseFeeChange` after multiple empty blocks, the calculation\n * should never be allowed to underflow.\n */\n function echidna_underflow() public view returns (bool) {\n return !underflow;\n }\n}\n" - }, - "contracts/governance/GovernanceToken.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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 * @custom:predeploy 0x4200000000000000000000000000000000000042\n * @title GovernanceToken\n * @notice The Optimism token used in governance and supporting voting and delegation. Implements\n * EIP 2612 allowing signed approvals. Contract is \"owned\" by a `MintManager` instance with\n * permission to the `mint` function only, for the purposes of enforcing the token inflation\n * schedule.\n */\ncontract GovernanceToken is ERC20Burnable, ERC20Votes, Ownable {\n constructor() ERC20(\"Optimism\", \"OP\") ERC20Permit(\"Optimism\") {}\n\n /**\n * @notice Allows the owner to mint tokens.\n *\n * @param _account The account receiving minted tokens.\n * @param _amount The amount of tokens to mint.\n */\n function mint(address _account, uint256 _amount) public onlyOwner {\n _mint(_account, _amount);\n }\n\n /**\n * @notice Callback called after a token transfer.\n *\n * @param from The account sending tokens.\n * @param to The account receiving tokens.\n * @param amount The amount of tokens being transfered.\n */\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 /**\n * @notice Internal mint function.\n *\n * @param to The account receiving minted tokens.\n * @param amount The amount of tokens to mint.\n */\n function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._mint(to, amount);\n }\n\n /**\n * @notice Internal burn function.\n *\n * @param account The account that tokens will be burned from.\n * @param amount The amount of tokens that will be burned.\n */\n function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._burn(account, amount);\n }\n}\n" - }, - "contracts/governance/MintManager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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(\n mintPermittedAfter <= block.timestamp,\n \"MintManager: minting not permitted yet\"\n );\n\n require(\n _amount <= (governanceToken.totalSupply() * MINT_CAP) / DENOMINATOR,\n \"MintManager: mint amount exceeds cap\"\n );\n }\n\n mintPermittedAfter = block.timestamp + MINT_PERIOD;\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(\n _newMintManager != address(0),\n \"MintManager: mint manager cannot be the zero address\"\n );\n\n governanceToken.transferOwnership(_newMintManager);\n }\n}\n" - }, - "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" - }, - "contracts/legacy/DeployerWhitelist.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000002\n * @title DeployerWhitelist\n * @notice DeployerWhitelist is a legacy contract that was originally used to act as a whitelist of\n * addresses allowed to the Optimism network. The DeployerWhitelist has since been\n * disabled, but the code is kept in state for the sake of full backwards compatibility.\n * As of the Bedrock upgrade, the DeployerWhitelist is completely unused by the Optimism\n * system and could, in theory, be removed entirely.\n */\ncontract DeployerWhitelist is Semver {\n /**\n * @notice Address of the owner of this contract. Note that when this address is set to\n * address(0), the whitelist is disabled.\n */\n address public owner;\n\n /**\n * @notice Mapping of deployer addresses to boolean whitelist status.\n */\n mapping(address => bool) public whitelist;\n\n /**\n * @notice Emitted when the owner of this contract changes.\n *\n * @param oldOwner Address of the previous owner.\n * @param newOwner Address of the new owner.\n */\n event OwnerChanged(address oldOwner, address newOwner);\n\n /**\n * @notice Emitted when the whitelist status of a deployer changes.\n *\n * @param deployer Address of the deployer.\n * @param whitelisted Boolean indicating whether the deployer is whitelisted.\n */\n event WhitelistStatusChanged(address deployer, bool whitelisted);\n\n /**\n * @notice Emitted when the whitelist is disabled.\n *\n * @param oldOwner Address of the final owner of the whitelist.\n */\n event WhitelistDisabled(address oldOwner);\n\n /**\n * @notice Blocks functions to anyone except the contract owner.\n */\n modifier onlyOwner() {\n require(\n msg.sender == owner,\n \"DeployerWhitelist: function can only be called by the owner of this contract\"\n );\n _;\n }\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Adds or removes an address from the deployment whitelist.\n *\n * @param _deployer Address to update permissions for.\n * @param _isWhitelisted Whether or not the address is whitelisted.\n */\n function setWhitelistedDeployer(address _deployer, bool _isWhitelisted) external onlyOwner {\n whitelist[_deployer] = _isWhitelisted;\n emit WhitelistStatusChanged(_deployer, _isWhitelisted);\n }\n\n /**\n * @notice Updates the owner of this contract.\n *\n * @param _owner Address of the new owner.\n */\n function setOwner(address _owner) external onlyOwner {\n // Prevent users from setting the whitelist owner to address(0) except via\n // enableArbitraryContractDeployment. If you want to burn the whitelist owner, send it to\n // any other address that doesn't have a corresponding knowable private key.\n require(\n _owner != address(0),\n \"DeployerWhitelist: can only be disabled via enableArbitraryContractDeployment\"\n );\n\n emit OwnerChanged(owner, _owner);\n owner = _owner;\n }\n\n /**\n * @notice Permanently enables arbitrary contract deployment and deletes the owner.\n */\n function enableArbitraryContractDeployment() external onlyOwner {\n emit WhitelistDisabled(owner);\n owner = address(0);\n }\n\n /**\n * @notice Checks whether an address is allowed to deploy contracts.\n *\n * @param _deployer Address to check.\n *\n * @return Whether or not the address can deploy contracts.\n */\n function isDeployerAllowed(address _deployer) external view returns (bool) {\n return (owner == address(0) || whitelist[_deployer]);\n }\n}\n" - }, - "contracts/legacy/L1BlockNumber.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000013\n * @title L1BlockNumber\n * @notice L1BlockNumber is a legacy contract that fills the roll of the OVM_L1BlockNumber contract\n * in the old version of the Optimism system. Only necessary for backwards compatibility.\n * If you want to access the L1 block number going forward, you should use the L1Block\n * contract instead.\n */\ncontract L1BlockNumber is Semver {\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Returns the L1 block number.\n */\n receive() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Returns the L1 block number.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Retrieves the latest L1 block number.\n *\n * @return Latest L1 block number.\n */\n function getL1BlockNumber() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).number();\n }\n}\n" - }, - "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/legacy/LegacyERC20ETH.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000\n * @title LegacyERC20ETH\n * @notice LegacyERC20ETH is a legacy contract that held ETH balances before the Bedrock upgrade.\n * All ETH balances held within this contract were migrated to the state trie as part of\n * the Bedrock upgrade. Functions within this contract that mutate state were already\n * disabled as part of the EVM equivalence upgrade.\n */\ncontract LegacyERC20ETH is OptimismMintableERC20 {\n /**\n * @notice Initializes the contract as an Optimism Mintable ERC20.\n */\n constructor()\n OptimismMintableERC20(Predeploys.L2_STANDARD_BRIDGE, address(0), \"Ether\", \"ETH\")\n {}\n\n /**\n * @notice Returns the ETH balance of the target account. Overrides the base behavior of the\n * contract to preserve the invariant that the balance within this contract always\n * matches the balance in the state trie.\n *\n * @param _who Address of the account to query.\n *\n * @return The ETH balance of the target account.\n */\n function balanceOf(address _who) public view virtual override returns (uint256) {\n return address(_who).balance;\n }\n\n /**\n * @custom:blocked\n * @notice Mints some amount of ETH.\n */\n function mint(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: mint is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Burns some amount of ETH.\n */\n function burn(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: burn is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers some amount of ETH.\n */\n function transfer(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transfer is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Approves a spender to spend some amount of ETH.\n */\n function approve(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: approve is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers funds from some sender account.\n */\n function transferFrom(\n address,\n address,\n uint256\n ) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transferFrom is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Increases the allowance of a spender.\n */\n function increaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Decreases the allowance of a spender.\n */\n function decreaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n }\n}\n" - }, - "contracts/legacy/LegacyMessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000000\n * @title LegacyMessagePasser\n * @notice The LegacyMessagePasser was the low-level mechanism used to send messages from L2 to L1\n * before the Bedrock upgrade. It is now deprecated in favor of the new MessagePasser.\n */\ncontract LegacyMessagePasser is Semver {\n /**\n * @notice Mapping of sent message hashes to boolean status.\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Passes a message to L1.\n *\n * @param _message Message to pass to L1.\n */\n function passMessageToL1(bytes memory _message) external {\n sentMessages[keccak256(abi.encodePacked(_message, msg.sender))] = true;\n }\n}\n" - }, - "contracts/legacy/ResolvedDelegateProxy.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressManager } from \"./AddressManager.sol\";\n\n/**\n * @custom:legacy\n * @title ResolvedDelegateProxy\n * @notice ResolvedDelegateProxy is a legacy proxy contract that makes use of the AddressManager to\n * resolve the implementation address. We're maintaining this contract for backwards\n * compatibility so we can manage all legacy proxies where necessary.\n */\ncontract ResolvedDelegateProxy {\n /**\n * @notice Mapping used to store the implementation name that corresponds to this contract. A\n * mapping was originally used as a way to bypass the same issue normally solved by\n * storing the implementation address in a specific storage slot that does not conflict\n * with any other storage slot. Generally NOT a safe solution but works as long as the\n * implementation does not also keep a mapping in the first storage slot.\n */\n mapping(address => string) private implementationName;\n\n /**\n * @notice Mapping used to store the address of the AddressManager contract where the\n * implementation address will be resolved from. Same concept here as with the above\n * mapping. Also generally unsafe but fine if the implementation doesn't keep a mapping\n * in the second storage slot.\n */\n mapping(address => AddressManager) private addressManager;\n\n /**\n * @param _addressManager Address of the AddressManager.\n * @param _implementationName implementationName of the contract to proxy to.\n */\n constructor(AddressManager _addressManager, string memory _implementationName) {\n addressManager[address(this)] = _addressManager;\n implementationName[address(this)] = _implementationName;\n }\n\n /**\n * @notice Fallback, performs a delegatecall to the resolved implementation address.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n address target = addressManager[address(this)].getAddress(\n (implementationName[address(this)])\n );\n\n require(target != address(0), \"ResolvedDelegateProxy: target address must be initialized\");\n\n // slither-disable-next-line controlled-delegatecall\n (bool success, bytes memory returndata) = target.delegatecall(msg.data);\n\n if (success == true) {\n assembly {\n return(add(returndata, 0x20), mload(returndata))\n }\n } else {\n assembly {\n revert(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n" - }, - "contracts/libraries/Arithmetic.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { SignedMath } from \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\nimport { FixedPointMathLib } from \"@rari-capital/solmate/src/utils/FixedPointMathLib.sol\";\n\n/**\n * @title Arithmetic\n * @notice Even more math than before.\n */\nlibrary Arithmetic {\n /**\n * @notice Clamps a value between a minimum and maximum.\n *\n * @param _value The value to clamp.\n * @param _min The minimum value.\n * @param _max The maximum value.\n *\n * @return The clamped value.\n */\n function clamp(\n int256 _value,\n int256 _min,\n int256 _max\n ) internal pure returns (int256) {\n return SignedMath.min(SignedMath.max(_value, _min), _max);\n }\n\n /**\n * @notice (c)oefficient (d)enominator (exp)onentiation function.\n * Returns the result of: c * (1 - 1/d)^exp.\n *\n * @param _coefficient Coefficient of the function.\n * @param _denominator Fractional denominator.\n * @param _exponent Power function exponent.\n *\n * @return Result of c * (1 - 1/d)^exp.\n */\n function cdexp(\n int256 _coefficient,\n int256 _denominator,\n int256 _exponent\n ) internal pure returns (int256) {\n return\n (_coefficient *\n (FixedPointMathLib.powWad(1e18 - (1e18 / _denominator), _exponent * 1e18))) / 1e18;\n }\n}\n" - }, - "contracts/libraries/Burn.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Burn\n * @notice Utilities for burning stuff.\n */\nlibrary Burn {\n /**\n * Burns a given amount of ETH.\n *\n * @param _amount Amount of ETH to burn.\n */\n function eth(uint256 _amount) internal {\n new Burner{ value: _amount }();\n }\n\n /**\n * Burns a given amount of gas.\n *\n * @param _amount Amount of gas to burn.\n */\n function gas(uint256 _amount) internal view {\n uint256 i = 0;\n uint256 initialGas = gasleft();\n while (initialGas - gasleft() < _amount) {\n ++i;\n }\n }\n}\n\n/**\n * @title Burner\n * @notice Burner self-destructs on creation and sends all ETH to itself, removing all ETH given to\n * the contract from the circulating supply. Self-destructing is the only way to remove ETH\n * from the circulating supply.\n */\ncontract Burner {\n constructor() payable {\n selfdestruct(payable(address(this)));\n }\n}\n" - }, - "contracts/libraries/Bytes.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Bytes\n * @notice Bytes is a library for manipulating byte arrays.\n */\nlibrary Bytes {\n /**\n * @custom:attribution https://github.com/GNSPS/solidity-bytes-utils\n * @notice Slices a byte array with a given starting index and length. Returns a new byte array\n * as opposed to a pointer to the original array. Will throw if trying to slice more\n * bytes than exist in the array.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n * @param _length Length of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n unchecked {\n require(_length + 31 >= _length, \"slice_overflow\");\n require(_start + _length >= _start, \"slice_overflow\");\n require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n }\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n /**\n * @notice Slices a byte array with a given starting index up to the end of the original byte\n * array. Returns a new array rathern than a pointer to the original.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {\n if (_start >= _bytes.length) {\n return bytes(\"\");\n }\n return slice(_bytes, _start, _bytes.length - _start);\n }\n\n /**\n * @notice Converts a byte array into a nibble array by splitting each byte into two nibbles.\n * Resulting nibble array will be exactly twice as long as the input byte array.\n *\n * @param _bytes Input byte array to convert.\n *\n * @return Resulting nibble array.\n */\n function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n uint256 bytesLength = _bytes.length;\n bytes memory nibbles = new bytes(bytesLength * 2);\n bytes1 b;\n\n for (uint256 i = 0; i < bytesLength; ) {\n b = _bytes[i];\n nibbles[i * 2] = b >> 4;\n nibbles[i * 2 + 1] = b & 0x0f;\n unchecked {\n ++i;\n }\n }\n\n return nibbles;\n }\n\n /**\n * @notice Compares two byte arrays by comparing their keccak256 hashes.\n *\n * @param _bytes First byte array to compare.\n * @param _other Second byte array to compare.\n *\n * @return True if the two byte arrays are equal, false otherwise.\n */\n function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {\n return keccak256(_bytes) == keccak256(_other);\n }\n}\n" - }, - "contracts/libraries/Constants.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Constants\n * @notice Constants is a library for storing constants. Simple! Don't put everything in here, just\n * the stuff used in multiple contracts. Constants that only apply to a single contract\n * should be defined in that contract instead.\n */\nlibrary Constants {\n /**\n * @notice Special address to be used as the tx origin for gas estimation calls in the\n * OptimismPortal and CrossDomainMessenger calls. You only need to use this address if\n * the minimum gas limit specified by the user is not actually enough to execute the\n * given message and you're attempting to estimate the actual necessary gas limit. We\n * use address(1) because it's the ecrecover precompile and therefore guaranteed to\n * never have any code on any EVM chain.\n */\n address internal constant ESTIMATION_ADDRESS = address(1);\n\n /**\n * @notice Value used for the L2 sender storage slot in both the OptimismPortal and the\n * CrossDomainMessenger contracts before an actual sender is set. This value is\n * non-zero to reduce the gas cost of message passing transactions.\n */\n address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD;\n}\n" - }, - "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" - }, - "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" - }, - "contracts/libraries/Predeploys.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Predeploys\n * @notice Contains constant addresses for contracts that are pre-deployed to the L2 system.\n */\nlibrary Predeploys {\n /**\n * @notice Address of the L2ToL1MessagePasser predeploy.\n */\n address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016;\n\n /**\n * @notice Address of the L2CrossDomainMessenger predeploy.\n */\n address internal constant L2_CROSS_DOMAIN_MESSENGER =\n 0x4200000000000000000000000000000000000007;\n\n /**\n * @notice Address of the L2StandardBridge predeploy.\n */\n address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;\n\n /**\n * @notice Address of the L2ERC721Bridge predeploy.\n */\n address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014;\n\n /**\n * @notice Address of the SequencerFeeWallet predeploy.\n */\n address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;\n\n /**\n * @notice Address of the OptimismMintableERC20Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY =\n 0x4200000000000000000000000000000000000012;\n\n /**\n * @notice Address of the OptimismMintableERC721Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY =\n 0x4200000000000000000000000000000000000017;\n\n /**\n * @notice Address of the L1Block predeploy.\n */\n address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015;\n\n /**\n * @notice Address of the GasPriceOracle predeploy. Includes fee information\n * and helpers for computing the L1 portion of the transaction fee.\n */\n address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F;\n\n /**\n * @custom:legacy\n * @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger\n * or access tx.origin (or msg.sender) in a L1 to L2 transaction instead.\n */\n address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;\n\n /**\n * @custom:legacy\n * @notice Address of the DeployerWhitelist predeploy. No longer active.\n */\n address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the\n * state trie as of the Bedrock upgrade. Contract has been locked and write functions\n * can no longer be accessed.\n */\n address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;\n\n /**\n * @custom:legacy\n * @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy\n * instead, which exposes more information about the L1 state.\n */\n address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated\n * L2ToL1MessagePasser contract instead.\n */\n address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;\n\n /**\n * @notice Address of the ProxyAdmin predeploy.\n */\n address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018;\n\n /**\n * @notice Address of the BaseFeeVault predeploy.\n */\n address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019;\n\n /**\n * @notice Address of the L1FeeVault predeploy.\n */\n address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A;\n}\n" - }, - "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" - }, - "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 * @custom:field outputRoot Hash of the L2 output.\n * @custom:field timestamp Timestamp of the L1 block that the output root was submitted in.\n * @custom:field l2BlockNumber L2 block number that the output corresponds to.\n */\n struct OutputProposal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2BlockNumber;\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 * @custom:field version Version of the output root.\n * @custom:field stateRoot Root of the state trie at the block of this output.\n * @custom:field messagePasserStorageRoot Root of the message passer storage trie.\n * @custom:field latestBlockhash Hash of the block this output was generated from.\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 * @custom:field from Address of the sender of the transaction.\n * @custom:field to Address of the recipient of the transaction.\n * @custom:field isCreation True if the transaction is a contract creation.\n * @custom:field value Value to send to the recipient.\n * @custom:field mint Amount of ETH to mint.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the transaction.\n * @custom:field l1BlockHash Hash of the block the transaction was submitted in.\n * @custom:field logIndex Index of the log in the block the transaction was submitted in.\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 * @custom:field nonce Nonce of the withdrawal transaction\n * @custom:field sender Address of the sender of the transaction.\n * @custom:field target Address of the recipient of the transaction.\n * @custom:field value Value to send to the recipient.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the 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" - }, - "contracts/libraries/rlp/RLPReader.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\n/**\n * @custom:attribution https://github.com/hamdiallam/Solidity-RLP\n * @title RLPReader\n * @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted\n * from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with\n * various tweaks to improve readability.\n */\nlibrary RLPReader {\n /**\n * Custom pointer type to avoid confusion between pointers and uint256s.\n */\n type MemoryPointer is uint256;\n\n /**\n * @notice RLP item types.\n *\n * @custom:value DATA_ITEM Represents an RLP data item (NOT a list).\n * @custom:value LIST_ITEM Represents an RLP list item.\n */\n enum RLPItemType {\n DATA_ITEM,\n LIST_ITEM\n }\n\n /**\n * @notice Struct representing an RLP item.\n *\n * @custom:field length Length of the RLP item.\n * @custom:field ptr Pointer to the RLP item in memory.\n */\n struct RLPItem {\n uint256 length;\n MemoryPointer ptr;\n }\n\n /**\n * @notice Max list length that this library will accept.\n */\n uint256 internal constant MAX_LIST_LENGTH = 32;\n\n /**\n * @notice Converts bytes to a reference to memory position and length.\n *\n * @param _in Input bytes to convert.\n *\n * @return Output memory reference.\n */\n function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) {\n // Empty arrays are not RLP items.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr;\n assembly {\n ptr := add(_in, 32)\n }\n\n return RLPItem({ length: _in.length, ptr: ptr });\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) {\n (uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.LIST_ITEM,\n \"RLPReader: decoded item type for list is not a list item\"\n );\n\n require(\n listOffset + listLength == _in.length,\n \"RLPReader: list item has an invalid data remainder\"\n );\n\n // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by\n // writing to the length. Since we can't know the number of RLP items without looping over\n // the entire input, we'd have to loop twice to accurately size this array. It's easier to\n // simply set a reasonable maximum list length and decrease the size before we finish.\n RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH);\n\n uint256 itemCount = 0;\n uint256 offset = listOffset;\n while (offset < _in.length) {\n (uint256 itemOffset, uint256 itemLength, ) = _decodeLength(\n RLPItem({\n length: _in.length - offset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n })\n );\n\n // We don't need to check itemCount < out.length explicitly because Solidity already\n // handles this check on our behalf, we'd just be wasting gas.\n out[itemCount] = RLPItem({\n length: itemLength + itemOffset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n });\n\n itemCount += 1;\n offset += itemOffset + itemLength;\n }\n\n // Decrease the array size to match the actual item count.\n assembly {\n mstore(out, itemCount)\n }\n\n return out;\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(bytes memory _in) internal pure returns (RLPItem[] memory) {\n return readList(toRLPItem(_in));\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.DATA_ITEM,\n \"RLPReader: decoded item type for bytes is not a data item\"\n );\n\n require(\n _in.length == itemOffset + itemLength,\n \"RLPReader: bytes value contains an invalid remainder\"\n );\n\n return _copy(_in.ptr, itemOffset, itemLength);\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(bytes memory _in) internal pure returns (bytes memory) {\n return readBytes(toRLPItem(_in));\n }\n\n /**\n * @notice Reads the raw bytes of an RLP item.\n *\n * @param _in RLP item to read.\n *\n * @return Raw RLP bytes.\n */\n function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n return _copy(_in.ptr, 0, _in.length);\n }\n\n /**\n * @notice Decodes the length of an RLP item.\n *\n * @param _in RLP item to decode.\n *\n * @return Offset of the encoded data.\n * @return Length of the encoded data.\n * @return RLP item type (LIST_ITEM or DATA_ITEM).\n */\n function _decodeLength(RLPItem memory _in)\n private\n pure\n returns (\n uint256,\n uint256,\n RLPItemType\n )\n {\n // Short-circuit if there's nothing to decode, note that we perform this check when\n // the user creates an RLP item via toRLPItem, but it's always possible for them to bypass\n // that function and create an RLP item directly. So we need to check this anyway.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr = _in.ptr;\n uint256 prefix;\n assembly {\n prefix := byte(0, mload(ptr))\n }\n\n if (prefix <= 0x7f) {\n // Single byte.\n return (0, 1, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xb7) {\n // Short string.\n\n // slither-disable-next-line variable-scope\n uint256 strLen = prefix - 0x80;\n\n require(\n _in.length > strLen,\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n strLen != 1 || firstByteOfContent >= 0x80,\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n\n return (1, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xbf) {\n // Long string.\n uint256 lenOfStrLen = prefix - 0xb7;\n\n require(\n _in.length > lenOfStrLen,\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n\n uint256 strLen;\n assembly {\n strLen := shr(sub(256, mul(8, lenOfStrLen)), mload(add(ptr, 1)))\n }\n\n require(\n strLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long string)\"\n );\n\n require(\n _in.length > lenOfStrLen + strLen,\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n\n return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xf7) {\n // Short list.\n // slither-disable-next-line variable-scope\n uint256 listLen = prefix - 0xc0;\n\n require(\n _in.length > listLen,\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n\n return (1, listLen, RLPItemType.LIST_ITEM);\n } else {\n // Long list.\n uint256 lenOfListLen = prefix - 0xf7;\n\n require(\n _in.length > lenOfListLen,\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long list)\"\n );\n\n uint256 listLen;\n assembly {\n listLen := shr(sub(256, mul(8, lenOfListLen)), mload(add(ptr, 1)))\n }\n\n require(\n listLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long list)\"\n );\n\n require(\n _in.length > lenOfListLen + listLen,\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n\n return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);\n }\n }\n\n /**\n * @notice Copies the bytes from a memory location.\n *\n * @param _src Pointer to the location to read from.\n * @param _offset Offset to start reading from.\n * @param _length Number of bytes to read.\n *\n * @return Copied bytes.\n */\n function _copy(\n MemoryPointer _src,\n uint256 _offset,\n uint256 _length\n ) private pure returns (bytes memory) {\n bytes memory out = new bytes(_length);\n if (_length == 0) {\n return out;\n }\n\n // Mostly based on Solidity's copy_memory_to_memory:\n // solhint-disable max-line-length\n // https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114\n uint256 src = MemoryPointer.unwrap(_src) + _offset;\n assembly {\n let dest := add(out, 32)\n let i := 0\n for {\n\n } lt(i, _length) {\n i := add(i, 32)\n } {\n mstore(add(dest, i), mload(add(src, i)))\n }\n\n if gt(i, _length) {\n mstore(add(dest, _length), 0)\n }\n }\n\n return out;\n }\n}\n" - }, - "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" - }, - "contracts/libraries/trie/MerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Bytes } from \"../Bytes.sol\";\nimport { RLPReader } from \"../rlp/RLPReader.sol\";\n\n/**\n * @title MerkleTrie\n * @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie\n * inclusion proofs. By default, this library assumes a hexary trie. One can change the\n * trie radix constant to support other trie radixes.\n */\nlibrary MerkleTrie {\n /**\n * @notice Struct representing a node in the trie.\n *\n * @custom:field encoded The RLP-encoded node.\n * @custom:field decoded The RLP-decoded node.\n */\n struct TrieNode {\n bytes encoded;\n RLPReader.RLPItem[] decoded;\n }\n\n /**\n * @notice Determines the number of elements per branch node.\n */\n uint256 internal constant TREE_RADIX = 16;\n\n /**\n * @notice Branch nodes have TREE_RADIX elements and one value element.\n */\n uint256 internal constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;\n\n /**\n * @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.\n */\n uint256 internal constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;\n\n /**\n * @notice Prefix for even-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_EVEN = 0;\n\n /**\n * @notice Prefix for odd-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_ODD = 1;\n\n /**\n * @notice Prefix for even-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_EVEN = 2;\n\n /**\n * @notice Prefix for odd-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_ODD = 3;\n\n /**\n * @notice Verifies a proof that a given key/value pair is present in the trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n return Bytes.equal(_value, get(_key, _proof, _root));\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n require(_key.length > 0, \"MerkleTrie: empty key\");\n\n TrieNode[] memory proof = _parseProof(_proof);\n bytes memory key = Bytes.toNibbles(_key);\n bytes memory currentNodeID = abi.encodePacked(_root);\n uint256 currentKeyIndex = 0;\n\n // Proof is top-down, so we start at the first element (root).\n for (uint256 i = 0; i < proof.length; i++) {\n TrieNode memory currentNode = proof[i];\n\n // Key index should never exceed total key length or we'll be out of bounds.\n require(\n currentKeyIndex <= key.length,\n \"MerkleTrie: key index exceeds total key length\"\n );\n\n if (currentKeyIndex == 0) {\n // First proof element is always the root node.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid root hash\"\n );\n } else if (currentNode.encoded.length >= 32) {\n // Nodes 32 bytes or larger are hashed inside branch nodes.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid large internal hash\"\n );\n } else {\n // Nodes smaller than 32 bytes aren't hashed.\n require(\n Bytes.equal(currentNode.encoded, currentNodeID),\n \"MerkleTrie: invalid internal node hash\"\n );\n }\n\n if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {\n if (currentKeyIndex == key.length) {\n // Value is the last element of the decoded list (for branch nodes). There's\n // some ambiguity in the Merkle trie specification because bytes(0) is a\n // valid value to place into the trie, but for branch nodes bytes(0) can exist\n // even when the value wasn't explicitly placed there. Geth treats a value of\n // bytes(0) as \"key does not exist\" and so we do the same.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[TREE_RADIX]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (branch)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (branch)\"\n );\n\n return value;\n } else {\n // We're not at the end of the key yet.\n // Figure out what the next node ID should be and continue.\n uint8 branchKey = uint8(key[currentKeyIndex]);\n RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];\n currentNodeID = _getNodeID(nextNode);\n currentKeyIndex += 1;\n }\n } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {\n bytes memory path = _getNodePath(currentNode);\n uint8 prefix = uint8(path[0]);\n uint8 offset = 2 - (prefix % 2);\n bytes memory pathRemainder = Bytes.slice(path, offset);\n bytes memory keyRemainder = Bytes.slice(key, currentKeyIndex);\n uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);\n\n // Whether this is a leaf node or an extension node, the path remainder MUST be a\n // prefix of the key remainder (or be equal to the key remainder) or the proof is\n // considered invalid.\n require(\n pathRemainder.length == sharedNibbleLength,\n \"MerkleTrie: path remainder must share all nibbles with key\"\n );\n\n if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {\n // Prefix of 2 or 3 means this is a leaf node. For the leaf node to be valid,\n // the key remainder must be exactly equal to the path remainder. We already\n // did the necessary byte comparison, so it's more efficient here to check that\n // the key remainder length equals the shared nibble length, which implies\n // equality with the path remainder (since we already did the same check with\n // the path remainder and the shared nibble length).\n require(\n keyRemainder.length == sharedNibbleLength,\n \"MerkleTrie: key remainder must be identical to path remainder\"\n );\n\n // Our Merkle Trie is designed specifically for the purposes of the Ethereum\n // state trie. Empty values are not allowed in the state trie, so we can safely\n // say that if the value is empty, the key should not exist and the proof is\n // invalid.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[1]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (leaf)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (leaf)\"\n );\n\n return value;\n } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {\n // Prefix of 0 or 1 means this is an extension node. We move onto the next node\n // in the proof and increment the key index by the length of the path remainder\n // which is equal to the shared nibble length.\n currentNodeID = _getNodeID(currentNode.decoded[1]);\n currentKeyIndex += sharedNibbleLength;\n } else {\n revert(\"MerkleTrie: received a node with an unknown prefix\");\n }\n } else {\n revert(\"MerkleTrie: received an unparseable node\");\n }\n }\n\n revert(\"MerkleTrie: ran out of proof elements\");\n }\n\n /**\n * @notice Parses an array of proof elements into a new array that contains both the original\n * encoded element and the RLP-decoded element.\n *\n * @param _proof Array of proof elements to parse.\n *\n * @return Proof parsed into easily accessible structs.\n */\n function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory) {\n uint256 length = _proof.length;\n TrieNode[] memory proof = new TrieNode[](length);\n for (uint256 i = 0; i < length; ) {\n proof[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) });\n unchecked {\n ++i;\n }\n }\n return proof;\n }\n\n /**\n * @notice Picks out the ID for a node. Node ID is referred to as the \"hash\" within the\n * specification, but nodes < 32 bytes are not actually hashed.\n *\n * @param _node Node to pull an ID for.\n *\n * @return ID for the node, depending on the size of its contents.\n */\n function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes memory) {\n return _node.length < 32 ? RLPReader.readRawBytes(_node) : RLPReader.readBytes(_node);\n }\n\n /**\n * @notice Gets the path for a leaf or extension node.\n *\n * @param _node Node to get a path for.\n *\n * @return Node path, converted to an array of nibbles.\n */\n function _getNodePath(TrieNode memory _node) private pure returns (bytes memory) {\n return Bytes.toNibbles(RLPReader.readBytes(_node.decoded[0]));\n }\n\n /**\n * @notice Utility; determines the number of nibbles shared between two nibble arrays.\n *\n * @param _a First nibble array.\n * @param _b Second nibble array.\n *\n * @return Number of shared nibbles.\n */\n function _getSharedNibbleLength(bytes memory _a, bytes memory _b)\n private\n pure\n returns (uint256)\n {\n uint256 shared;\n uint256 max = (_a.length < _b.length) ? _a.length : _b.length;\n for (; shared < max && _a[shared] == _b[shared]; ) {\n unchecked {\n ++shared;\n }\n }\n return shared;\n }\n}\n" - }, - "contracts/libraries/trie/SecureMerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* Library Imports */\nimport { MerkleTrie } from \"./MerkleTrie.sol\";\n\n/**\n * @title SecureMerkleTrie\n * @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input\n * keys. Ethereum's state trie hashes input keys before storing them.\n */\nlibrary SecureMerkleTrie {\n /**\n * @notice Verifies a proof that a given key/value pair is present in the Merkle trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.get(key, _proof, _root);\n }\n\n /**\n * @notice Computes the hashed version of the input key.\n *\n * @param _key Key to hash.\n *\n * @return Hashed version of the key.\n */\n function _getSecureKey(bytes memory _key) private pure returns (bytes memory) {\n return abi.encodePacked(keccak256(_key));\n }\n}\n" - }, - "contracts/test/AddressAliasHelper.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract AddressAliasHelper_Test is Test {\n function testFuzz_applyAndUndo_succeeds(address _address) external {\n address aliased = AddressAliasHelper.applyL1ToL2Alias(_address);\n address unaliased = AddressAliasHelper.undoL1ToL2Alias(aliased);\n assertEq(_address, unaliased);\n }\n}\n" - }, - "contracts/test/BenchmarkTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test } from \"forge-std/Test.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport \"./CommonTest.t.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\nuint128 constant INITIAL_BASE_FEE = 1_000_000_000;\n\n// Free function for setting the prevBaseFee param in the OptimismPortal.\nfunction setPrevBaseFee(\n Vm _vm,\n address _op,\n uint128 _prevBaseFee\n) {\n _vm.store(\n address(_op),\n bytes32(uint256(1)),\n bytes32(\n abi.encode(\n ResourceMetering.ResourceParams({\n prevBaseFee: _prevBaseFee,\n prevBoughtGas: 0,\n prevBlockNum: uint64(block.number)\n })\n )\n )\n );\n}\n\n// Tests for obtaining pure gas cost estimates for commonly used functions.\n// The objective with these benchmarks is to strip down the actual test functions\n// so that they are nothing more than the call we want measure the gas cost of.\n// In order to achieve this we make no assertions, and handle everything else in the setUp()\n// function.\ncontract GasBenchMark_OptimismPortal is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n bytes32 _outputRoot;\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n\n // Get withdrawal proof data we can use for testing.\n bytes32 _storageRoot;\n bytes32 _stateRoot;\n (_stateRoot, _storageRoot, _outputRoot, , _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n op.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n function test_depositTransaction_benchmark() external {\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_depositTransaction_benchmark_1() external {\n setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_proveWithdrawalTransaction_benchmark() external {\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n}\n\ncontract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer {\n function test_sendMessage_benchmark_0() external {\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n\n function test_sendMessage_benchmark_1() external {\n setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), alice, 100000, true);\n vm.startPrank(alice, alice);\n }\n\n function test_depositETH_benchmark_0() external {\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositETH_benchmark_1() external {\n setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositERC20_benchmark_0() external {\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositERC20_benchmark_1() external {\n setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE);\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Finalize is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), address(L1Bridge), 100, true);\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.startPrank(address(L1Bridge.messenger()));\n vm.deal(address(L1Bridge.messenger()), 100);\n }\n\n function test_finalizeETHWithdrawal_benchmark() external {\n // TODO: Make this more accurate. It is underestimating the cost because it pranks\n // the call coming from the messenger, which bypasses the portal\n // and oracle.\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n\ncontract GasBenchMark_L2OutputOracle is L2OutputOracle_Initializer {\n uint256 nextBlockNumber;\n\n function setUp() public override {\n super.setUp();\n nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.startPrank(proposer);\n }\n\n function test_proposeL2Output_benchmark() external {\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n}\n" - }, - "contracts/test/Bytes.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Bytes } from \"../libraries/Bytes.sol\";\n\n/// @title BytesTest\ncontract Bytes_Test is Test {\n /// @dev Tests that the `slice` function works as expected when starting from\n /// index 0.\n function test_slice_fromZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check if all possible slices starting from index 0 are correct.\n assertEq(Bytes.slice(input, 0, 0), hex\"\");\n assertEq(Bytes.slice(input, 0, 1), hex\"11\");\n assertEq(Bytes.slice(input, 0, 2), hex\"1122\");\n assertEq(Bytes.slice(input, 0, 3), hex\"112233\");\n assertEq(Bytes.slice(input, 0, 4), hex\"11223344\");\n assertEq(Bytes.slice(input, 0, 5), hex\"1122334455\");\n assertEq(Bytes.slice(input, 0, 6), hex\"112233445566\");\n assertEq(Bytes.slice(input, 0, 7), hex\"11223344556677\");\n assertEq(Bytes.slice(input, 0, 8), hex\"1122334455667788\");\n assertEq(Bytes.slice(input, 0, 9), hex\"112233445566778899\");\n assertEq(Bytes.slice(input, 0, 10), hex\"11223344556677889900\");\n }\n\n /// @dev Tests that the `slice` function works as expected when starting from\n /// indexes [1, 9] with lengths [1, 9], in reverse order.\n function test_slice_fromNonZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check correctness of slices starting from indexes [1, 9]\n // and spanning [1, 9] bytes, in reverse order\n assertEq(Bytes.slice(input, 9, 1), hex\"00\");\n assertEq(Bytes.slice(input, 8, 2), hex\"9900\");\n assertEq(Bytes.slice(input, 7, 3), hex\"889900\");\n assertEq(Bytes.slice(input, 6, 4), hex\"77889900\");\n assertEq(Bytes.slice(input, 5, 5), hex\"6677889900\");\n assertEq(Bytes.slice(input, 4, 6), hex\"556677889900\");\n assertEq(Bytes.slice(input, 3, 7), hex\"44556677889900\");\n assertEq(Bytes.slice(input, 2, 8), hex\"3344556677889900\");\n assertEq(Bytes.slice(input, 1, 9), hex\"223344556677889900\");\n }\n\n /// @dev Tests that the `slice` function works as expected when slicing between\n /// multiple words in memory. In this case, we test that a 2 byte slice between\n /// the 32nd byte of the first word and the 1st byte of the second word is\n /// correct.\n function test_slice_acrossWords_works() public {\n bytes\n memory input = hex\"00000000000000000000000000000000000000000000000000000000000000112200000000000000000000000000000000000000000000000000000000000000\";\n\n assertEq(Bytes.slice(input, 31, 2), hex\"1122\");\n }\n\n /// @dev Tests that the `slice` function works as expected when slicing between\n /// multiple words in memory. In this case, we test that a 34 byte slice between\n /// 3 separate words returns the correct result.\n function test_slice_acrossMultipleWords_works() public {\n bytes\n memory input = hex\"000000000000000000000000000000000000000000000000000000000000001122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1100000000000000000000000000000000000000000000000000000000000000\";\n bytes\n memory expected = hex\"1122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11\";\n\n assertEq(Bytes.slice(input, 31, 34), expected);\n }\n\n /// @dev Tests that, when given an input bytes array of length `n`,\n /// the `slice` function will always revert if `_start + _length > n`.\n function testFuzz_slice_outOfBounds_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // We want a valid start index and a length that will not overflow.\n vm.assume(_start < _input.length && _length < type(uint256).max - 31);\n // But, we want an invalid slice length.\n vm.assume(_start + _length > _input.length);\n\n vm.expectRevert(\"slice_outOfBounds\");\n Bytes.slice(_input, _start, _length);\n }\n\n /// @dev Tests that, when given a length `n` that is greater than `type(uint256).max - 31`,\n /// the `slice` function reverts.\n function testFuzz_slice_lengthOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that the `_length` will overflow if a number >= 31 is added to it.\n vm.assume(_length > type(uint256).max - 31);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /// @dev Tests that, when given a length `n` that is greater than `type(uint256).max - 31`,\n /// the `slice` function reverts.\n function testFuzz_slice_rangeOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that `_length` is a realistic length of a slice. This is to make sure\n // we revert on the correct require statement.\n vm.assume(_length < _input.length);\n // Ensure that `_start` will overflow if `_length` is added to it.\n vm.assume(_start > type(uint256).max - _length);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /// @dev Tests that, given an input of 5 bytes, the `toNibbles` function returns\n /// an array of 10 nibbles corresponding to the input data.\n function test_toNibbles_expectedResult5Bytes_works() public {\n bytes memory input = hex\"1234567890\";\n bytes memory expected = hex\"01020304050607080900\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /// @dev Tests that, given an input of 128 bytes, the `toNibbles` function returns\n /// an array of 256 nibbles corresponding to the input data.\n /// This test exists to ensure that, given a large input, the `toNibbles` function\n /// works as expected.\n function test_toNibbles_expectedResult128Bytes_works() public {\n bytes\n memory input = hex\"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f\";\n bytes\n memory expected = hex\"0000000100020003000400050006000700080009000a000b000c000d000e000f0100010101020103010401050106010701080109010a010b010c010d010e010f0200020102020203020402050206020702080209020a020b020c020d020e020f0300030103020303030403050306030703080309030a030b030c030d030e030f0400040104020403040404050406040704080409040a040b040c040d040e040f0500050105020503050405050506050705080509050a050b050c050d050e050f0600060106020603060406050606060706080609060a060b060c060d060e060f0700070107020703070407050706070707080709070a070b070c070d070e070f\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /// @dev Tests that, given an input of 0 bytes, the `toNibbles` function returns\n /// a zero length array.\n function test_toNibbles_zeroLengthInput_works() public {\n bytes memory input = hex\"\";\n bytes memory expected = hex\"\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length, 0);\n assertEq(expected.length, 0);\n assertEq(actual.length, 0);\n assertEq(actual, expected);\n }\n\n /// @dev Test that the `toNibbles` function in the `Bytes` library is equivalent to the\n /// Yul implementation.\n function testDiff_toNibbles_succeeds(bytes memory _input) public {\n assertEq(Bytes.toNibbles(_input), toNibblesYul(_input));\n }\n\n /// @dev Test that the `equal` function in the `Bytes` library returns `false` if given\n /// two non-equal byte arrays.\n function testFuzz_equal_notEqual_works(bytes memory _a, bytes memory _b) public {\n vm.assume(!manualEq(_a, _b));\n assertFalse(Bytes.equal(_a, _b));\n }\n\n /// @dev Test whether or not the `equal` function in the `Bytes` library is equivalent\n /// to manually checking equality of the two dynamic `bytes` arrays in memory.\n function testDiff_equal_works(bytes memory _a, bytes memory _b) public {\n assertEq(Bytes.equal(_a, _b), manualEq(_a, _b));\n }\n\n ////////////////////////////////////////////////////////////////\n // HELPERS //\n ////////////////////////////////////////////////////////////////\n\n /// @dev Utility function to manually check equality of two dynamic `bytes` arrays in memory.\n function manualEq(bytes memory _a, bytes memory _b) internal pure returns (bool) {\n bool _eq;\n assembly {\n _eq := and(\n // Check if the contents of the two bytes arrays are equal in memory.\n eq(keccak256(add(0x20, _a), mload(_a)), keccak256(add(0x20, _b), mload(_b))),\n // Check if the length of the two bytes arrays are equal in memory.\n // This is redundant given the above check, but included for completeness.\n eq(mload(_a), mload(_b))\n )\n }\n return _eq;\n }\n\n /// @dev Utility function to diff test Solidity version of `toNibbles`\n function toNibblesYul(bytes memory _bytes) internal pure returns (bytes memory) {\n // Allocate memory for the `nibbles` array.\n bytes memory nibbles = new bytes(_bytes.length << 1);\n\n assembly {\n // Load the length of the passed bytes array from memory\n let bytesLength := mload(_bytes)\n\n // Store the memory offset of the _bytes array's contents on the stack\n let bytesStart := add(_bytes, 0x20)\n\n // Store the memory offset of the nibbles array's contents on the stack\n let nibblesStart := add(nibbles, 0x20)\n\n // Loop through each byte in the input array\n for {\n let i := 0x00\n } lt(i, bytesLength) {\n i := add(i, 0x01)\n } {\n // Get the starting offset of the next 2 bytes in the nibbles array\n let offset := add(nibblesStart, shl(0x01, i))\n\n // Load the byte at the current index within the `_bytes` array\n let b := byte(0x00, mload(add(bytesStart, i)))\n\n // Pull out the first nibble and store it in the new array\n mstore8(offset, shr(0x04, b))\n // Pull out the second nibble and store it in the new array\n mstore8(add(offset, 0x01), and(b, 0x0F))\n }\n }\n\n return nibbles;\n }\n}\n" - }, - "contracts/test/CommonTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test, StdUtils } from \"forge-std/Test.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { IL1ChugSplashDeployer } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\n\ncontract CommonTest is Test {\n address alice = address(128);\n address bob = address(256);\n address multisig = address(512);\n\n address immutable ZERO_ADDRESS = address(0);\n address immutable NON_ZERO_ADDRESS = address(1);\n uint256 immutable NON_ZERO_VALUE = 100;\n uint256 immutable ZERO_VALUE = 0;\n uint64 immutable NON_ZERO_GASLIMIT = 50000;\n bytes32 nonZeroHash = keccak256(abi.encode(\"NON_ZERO\"));\n bytes NON_ZERO_DATA = hex\"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000\";\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n FFIInterface ffi;\n\n function _setUp() public {\n // Give alice and bob some ETH\n vm.deal(alice, 1 << 16);\n vm.deal(bob, 1 << 16);\n vm.deal(multisig, 1 << 16);\n\n vm.label(alice, \"alice\");\n vm.label(bob, \"bob\");\n vm.label(multisig, \"multisig\");\n\n // Make sure we have a non-zero base fee\n vm.fee(1000000000);\n\n ffi = new FFIInterface();\n }\n\n function emitTransactionDeposited(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) internal {\n emit TransactionDeposited(\n _from,\n _to,\n 0,\n abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data)\n );\n }\n}\n\ncontract L2OutputOracle_Initializer is CommonTest {\n // Test target\n L2OutputOracle oracle;\n L2OutputOracle oracleImpl;\n\n L2ToL1MessagePasser messagePasser =\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER));\n\n // Constructor arguments\n address internal proposer = 0x000000000000000000000000000000000000AbBa;\n address internal owner = 0x000000000000000000000000000000000000ACDC;\n uint256 internal submissionInterval = 1800;\n uint256 internal l2BlockTime = 2;\n uint256 internal startingBlockNumber = 200;\n uint256 internal startingTimestamp = 1000;\n\n // Test data\n uint256 initL1Time;\n\n // Advance the evm's time to meet the L2OutputOracle's requirements for proposeL2Output\n function warpToProposeTime(uint256 _nextBlockNumber) public {\n vm.warp(oracle.computeL2Timestamp(_nextBlockNumber) + 1);\n }\n\n function setUp() public virtual {\n _setUp();\n\n // By default the first block has timestamp and number zero, which will cause underflows in the\n // tests, so we'll move forward to these block values.\n initL1Time = startingTimestamp + 1;\n vm.warp(initL1Time);\n vm.roll(startingBlockNumber);\n // Deploy the L2OutputOracle and transfer owernship to the proposer\n oracleImpl = new L2OutputOracle(\n submissionInterval,\n l2BlockTime,\n startingBlockNumber,\n startingTimestamp,\n proposer,\n owner\n );\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(oracleImpl),\n abi.encodeCall(L2OutputOracle.initialize, (startingBlockNumber, startingTimestamp))\n );\n oracle = L2OutputOracle(address(proxy));\n vm.label(address(oracle), \"L2OutputOracle\");\n\n // Set the L2ToL1MessagePasser at the correct address\n vm.etch(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(new L2ToL1MessagePasser()).code);\n\n vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, \"L2ToL1MessagePasser\");\n }\n}\n\ncontract Portal_Initializer is L2OutputOracle_Initializer {\n // Test target\n OptimismPortal opImpl;\n OptimismPortal op;\n\n function setUp() public virtual override {\n L2OutputOracle_Initializer.setUp();\n\n opImpl = new OptimismPortal(oracle, 7 days);\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(opImpl),\n abi.encodeWithSelector(OptimismPortal.initialize.selector)\n );\n op = OptimismPortal(payable(address(proxy)));\n }\n}\n\ncontract Messenger_Initializer is L2OutputOracle_Initializer {\n OptimismPortal op;\n AddressManager addressManager;\n L1CrossDomainMessenger L1Messenger;\n L2CrossDomainMessenger L2Messenger =\n L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER);\n\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n\n event SentMessageExtension1(address indexed sender, uint256 value);\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event RelayedMessage(bytes32 indexed msgHash);\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 mint,\n uint256 value,\n uint64 gasLimit,\n bool isCreation,\n bytes data\n );\n\n event WithdrawalFinalized(bytes32 indexed, bool success);\n\n event WhatHappened(bool success, bytes returndata);\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the OptimismPortal\n op = new OptimismPortal(oracle, 7 days);\n vm.label(address(op), \"OptimismPortal\");\n\n // Deploy the address manager\n vm.prank(multisig);\n addressManager = new AddressManager();\n\n // Setup implementation\n L1CrossDomainMessenger L1MessengerImpl = new L1CrossDomainMessenger(op);\n\n // Setup the address manager and proxy\n vm.prank(multisig);\n addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(L1MessengerImpl));\n ResolvedDelegateProxy proxy = new ResolvedDelegateProxy(\n addressManager,\n \"OVM_L1CrossDomainMessenger\"\n );\n L1Messenger = L1CrossDomainMessenger(address(proxy));\n L1Messenger.initialize(alice);\n\n vm.etch(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n address(new L2CrossDomainMessenger(address(L1Messenger))).code\n );\n\n L2Messenger.initialize();\n\n // Label addresses\n vm.label(address(addressManager), \"AddressManager\");\n vm.label(address(L1MessengerImpl), \"L1CrossDomainMessenger_Impl\");\n vm.label(address(L1Messenger), \"L1CrossDomainMessenger_Proxy\");\n vm.label(Predeploys.LEGACY_ERC20_ETH, \"LegacyERC20ETH\");\n vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, \"L2CrossDomainMessenger\");\n\n vm.label(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n \"L1CrossDomainMessenger_aliased\"\n );\n }\n}\n\ncontract Bridge_Initializer is Messenger_Initializer {\n L1StandardBridge L1Bridge;\n L2StandardBridge L2Bridge;\n OptimismMintableERC20Factory L2TokenFactory;\n OptimismMintableERC20Factory L1TokenFactory;\n ERC20 L1Token;\n ERC20 BadL1Token;\n OptimismMintableERC20 L2Token;\n ERC20 NativeL2Token;\n ERC20 BadL2Token;\n OptimismMintableERC20 RemoteL1Token;\n\n event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes data\n );\n\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFailed(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ETHBridgeInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n function setUp() public virtual override {\n super.setUp();\n\n vm.label(Predeploys.L2_STANDARD_BRIDGE, \"L2StandardBridge\");\n vm.label(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, \"OptimismMintableERC20Factory\");\n\n // Deploy the L1 bridge and initialize it with the address of the\n // L1CrossDomainMessenger\n L1ChugSplashProxy proxy = new L1ChugSplashProxy(multisig);\n vm.mockCall(\n multisig,\n abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector),\n abi.encode(true)\n );\n vm.startPrank(multisig);\n proxy.setCode(address(new L1StandardBridge(payable(address(L1Messenger)))).code);\n vm.clearMockedCalls();\n address L1Bridge_Impl = proxy.getImplementation();\n vm.stopPrank();\n\n L1Bridge = L1StandardBridge(payable(address(proxy)));\n\n vm.label(address(proxy), \"L1StandardBridge_Proxy\");\n vm.label(address(L1Bridge_Impl), \"L1StandardBridge_Impl\");\n\n // Deploy the L2StandardBridge, move it to the correct predeploy\n // address and then initialize it\n L2StandardBridge l2B = new L2StandardBridge(payable(proxy));\n vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(l2B).code);\n L2Bridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE));\n\n // Set up the L2 mintable token factory\n OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory(\n Predeploys.L2_STANDARD_BRIDGE\n );\n vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(factory).code);\n L2TokenFactory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY);\n\n vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code);\n\n L1Token = new ERC20(\"Native L1 Token\", \"L1T\");\n\n // Deploy the L2 ERC20 now\n L2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(L1Token),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n BadL2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n NativeL2Token = new ERC20(\"Native L2 Token\", \"L2T\");\n L1TokenFactory = new OptimismMintableERC20Factory(address(L1Bridge));\n\n RemoteL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(NativeL2Token),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n\n BadL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n }\n}\n\ncontract ERC721Bridge_Initializer is Messenger_Initializer {\n L1ERC721Bridge L1Bridge;\n L2ERC721Bridge L2Bridge;\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the L1ERC721Bridge.\n L1Bridge = new L1ERC721Bridge(address(L1Messenger), Predeploys.L2_ERC721_BRIDGE);\n\n // Deploy the implementation for the L2ERC721Bridge and etch it into the predeploy address.\n vm.etch(\n Predeploys.L2_ERC721_BRIDGE,\n address(new L2ERC721Bridge(Predeploys.L2_CROSS_DOMAIN_MESSENGER, address(L1Bridge)))\n .code\n );\n\n // Set up a reference to the L2ERC721Bridge.\n L2Bridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE);\n\n // Label the L1 and L2 bridges.\n vm.label(address(L1Bridge), \"L1ERC721Bridge\");\n vm.label(address(L2Bridge), \"L2ERC721Bridge\");\n }\n}\n\ncontract FFIInterface is Test {\n function getProveWithdrawalTransactionInputs(Types.WithdrawalTransaction memory _tx)\n external\n returns (\n bytes32,\n bytes32,\n bytes32,\n bytes32,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](9);\n cmds[0] = \"node\";\n cmds[1] = \"dist/scripts/differential-testing.js\";\n cmds[2] = \"getProveWithdrawalTransactionInputs\";\n cmds[3] = vm.toString(_tx.nonce);\n cmds[4] = vm.toString(_tx.sender);\n cmds[5] = vm.toString(_tx.target);\n cmds[6] = vm.toString(_tx.value);\n cmds[7] = vm.toString(_tx.gasLimit);\n cmds[8] = vm.toString(_tx.data);\n\n bytes memory result = vm.ffi(cmds);\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = abi.decode(result, (bytes32, bytes32, bytes32, bytes32, bytes[]));\n\n return (stateRoot, storageRoot, outputRoot, withdrawalHash, withdrawalProof);\n }\n\n function hashCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](9);\n cmds[0] = \"node\";\n cmds[1] = \"dist/scripts/differential-testing.js\";\n cmds[2] = \"hashCrossDomainMessage\";\n cmds[3] = vm.toString(_nonce);\n cmds[4] = vm.toString(_sender);\n cmds[5] = vm.toString(_target);\n cmds[6] = vm.toString(_value);\n cmds[7] = vm.toString(_gasLimit);\n cmds[8] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashWithdrawal(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](9);\n cmds[0] = \"node\";\n cmds[1] = \"dist/scripts/differential-testing.js\";\n cmds[2] = \"hashWithdrawal\";\n cmds[3] = vm.toString(_nonce);\n cmds[4] = vm.toString(_sender);\n cmds[5] = vm.toString(_target);\n cmds[6] = vm.toString(_value);\n cmds[7] = vm.toString(_gasLimit);\n cmds[8] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashOutputRootProof(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external returns (bytes32) {\n string[] memory cmds = new string[](7);\n cmds[0] = \"node\";\n cmds[1] = \"dist/scripts/differential-testing.js\";\n cmds[2] = \"hashOutputRootProof\";\n cmds[3] = Strings.toHexString(uint256(_version));\n cmds[4] = Strings.toHexString(uint256(_stateRoot));\n cmds[5] = Strings.toHexString(uint256(_messagePasserStorageRoot));\n cmds[6] = Strings.toHexString(uint256(_latestBlockhash));\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashDepositTransaction(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint256 _logIndex\n ) external returns (bytes32) {\n string[] memory cmds = new string[](11);\n cmds[0] = \"node\";\n cmds[1] = \"dist/scripts/differential-testing.js\";\n cmds[2] = \"hashDepositTransaction\";\n cmds[3] = \"0x0000000000000000000000000000000000000000000000000000000000000000\";\n cmds[4] = vm.toString(_logIndex);\n cmds[5] = vm.toString(_from);\n cmds[6] = vm.toString(_to);\n cmds[7] = vm.toString(_mint);\n cmds[8] = vm.toString(_value);\n cmds[9] = vm.toString(_gas);\n cmds[10] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function encodeDepositTransaction(Types.UserDepositTransaction calldata txn)\n external\n returns (bytes memory)\n {\n string[] memory cmds = new string[](12);\n cmds[0] = \"node\";\n cmds[1] = \"dist/scripts/differential-testing.js\";\n cmds[2] = \"encodeDepositTransaction\";\n cmds[3] = vm.toString(txn.from);\n cmds[4] = vm.toString(txn.to);\n cmds[5] = vm.toString(txn.value);\n cmds[6] = vm.toString(txn.mint);\n cmds[7] = vm.toString(txn.gasLimit);\n cmds[8] = vm.toString(txn.isCreation);\n cmds[9] = vm.toString(txn.data);\n cmds[10] = vm.toString(txn.l1BlockHash);\n cmds[11] = vm.toString(txn.logIndex);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function encodeCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes memory) {\n string[] memory cmds = new string[](9);\n cmds[0] = \"node\";\n cmds[1] = \"dist/scripts/differential-testing.js\";\n cmds[2] = \"encodeCrossDomainMessage\";\n cmds[3] = vm.toString(_nonce);\n cmds[4] = vm.toString(_sender);\n cmds[5] = vm.toString(_target);\n cmds[6] = vm.toString(_value);\n cmds[7] = vm.toString(_gasLimit);\n cmds[8] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function decodeVersionedNonce(uint256 nonce) external returns (uint256, uint256) {\n string[] memory cmds = new string[](4);\n cmds[0] = \"node\";\n cmds[1] = \"dist/scripts/differential-testing.js\";\n cmds[2] = \"decodeVersionedNonce\";\n cmds[3] = vm.toString(nonce);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (uint256, uint256));\n }\n\n function getMerkleTrieFuzzCase(string memory variant)\n external\n returns (\n bytes32,\n bytes memory,\n bytes memory,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](5);\n cmds[0] = \"./test-case-generator/fuzz\";\n cmds[1] = \"-m\";\n cmds[2] = \"trie\";\n cmds[3] = \"-v\";\n cmds[4] = variant;\n\n return abi.decode(vm.ffi(cmds), (bytes32, bytes, bytes, bytes[]));\n }\n}\n\n// Used for testing a future upgrade beyond the current implementations.\n// We include some variables so that we can sanity check accessing storage values after an upgrade.\ncontract NextImpl is Initializable {\n // Initializable occupies the zero-th slot.\n bytes32 slot1;\n bytes32[19] __gap;\n bytes32 slot21;\n bytes32 public constant slot21Init = bytes32(hex\"1337\");\n\n function initialize() public reinitializer(2) {\n // Slot21 is unused by an of our upgradeable contracts.\n // This is used to verify that we can access this value after an upgrade.\n slot21 = slot21Init;\n }\n}\n\ncontract Reverter {\n fallback() external {\n revert();\n }\n}\n\n// Useful for testing reentrancy guards\ncontract CallerCaller {\n event WhatHappened(bool success, bytes returndata);\n\n fallback() external {\n (bool success, bytes memory returndata) = msg.sender.call(msg.data);\n emit WhatHappened(success, returndata);\n assembly {\n switch success\n case 0 {\n revert(add(returndata, 0x20), mload(returndata))\n }\n default {\n return(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n" - }, - "contracts/test/CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, CallerCaller } from \"./CommonTest.t.sol\";\n\n// CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2\n// CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract.\ncontract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {\n // Ensure that baseGas passes for the max value of _minGasLimit,\n // this is about 4 Billion.\n function test_baseGas_succeeds() external view {\n L1Messenger.baseGas(hex\"ff\", type(uint32).max);\n }\n\n // Fuzz for other values which might cause a revert in baseGas.\n function testFuzz_baseGas_succeeds(uint32 _minGasLimit) external view {\n L1Messenger.baseGas(hex\"ff\", _minGasLimit);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest, Portal_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable } from \"../L2/CrossDomainOwnable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Vm, VmSafe } from \"forge-std/Vm.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract XDomainSetter is CrossDomainOwnable {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable_Test is CommonTest {\n XDomainSetter setter;\n\n function setUp() external {\n setter = new XDomainSetter();\n }\n\n // Check that the revert message is correct\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable: caller is not the owner\");\n setter.set(1);\n }\n\n // Check that making a call can set the value properly\n function test_onlyOwner_succeeds() external {\n assertEq(setter.value(), 0);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(setter.owner()));\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n\ncontract CrossDomainOwnableThroughPortal_Test is Portal_Initializer {\n XDomainSetter setter;\n\n function setUp() public override {\n super.setUp();\n\n vm.prank(alice);\n setter = new XDomainSetter();\n }\n\n function test_depositTransaction_crossDomainOwner_succeeds() external {\n vm.recordLogs();\n\n vm.prank(alice);\n op.depositTransaction(\n address(setter),\n 0,\n 10000,\n false,\n abi.encodeWithSelector(XDomainSetter.set.selector, 1)\n );\n\n // Simulate the operation of the `op-node` by parsing data\n // from logs\n VmSafe.Log[] memory logs = vm.getRecordedLogs();\n // Only 1 log emitted\n assertEq(logs.length, 1);\n\n VmSafe.Log memory log = logs[0];\n\n // It is the expected topic\n bytes32 topic = log.topics[0];\n assertEq(topic, keccak256(\"TransactionDeposited(address,address,uint256,bytes)\"));\n\n // from is indexed and the first argument to the event.\n bytes32 _from = log.topics[1];\n address from = Bytes32AddressLib.fromLast20Bytes(_from);\n\n assertEq(AddressAliasHelper.undoL1ToL2Alias(from), alice);\n\n // Make a call from the \"from\" value received from the log.\n // In theory the opaque data could be parsed from the log\n // and passed to a low level call to \"to\", but calling set\n // directly on the setter is good enough.\n vm.prank(from);\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable2.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\nimport { CommonTest, Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable2 } from \"../L2/CrossDomainOwnable2.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract XDomainSetter2 is CrossDomainOwnable2 {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable2_Test is Messenger_Initializer {\n XDomainSetter2 setter;\n\n function setUp() public override {\n super.setUp();\n vm.prank(alice);\n setter = new XDomainSetter2();\n }\n\n function test_onlyOwner_notMessenger_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the messenger\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n // set the xDomainMsgSender storage slot\n bytes32 key = bytes32(uint256(204));\n bytes32 value = Bytes32AddressLib.fillLast12Bytes(address(alice));\n vm.store(address(L2Messenger), key, value);\n\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the owner\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner2_reverts() external {\n uint240 nonce = 0;\n address sender = bob;\n address target = address(setter);\n uint256 value = 0;\n uint256 minGasLimit = 0;\n bytes memory message = abi.encodeWithSelector(XDomainSetter2.set.selector, 1);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n // It should be a failed message. The revert is caught,\n // so we cannot expectRevert here.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n assertEq(setter.value(), 0);\n }\n\n function test_onlyOwner_succeeds() external {\n address owner = setter.owner();\n\n // Simulate the L2 execution where the call is coming from\n // the L1CrossDomainMessenger\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(1, 1),\n owner,\n address(setter),\n 0,\n 0,\n abi.encodeWithSelector(XDomainSetter2.set.selector, 2)\n );\n\n assertEq(setter.value(), 2);\n }\n}\n" - }, - "contracts/test/DeployerWhitelist.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { DeployerWhitelist } from \"../legacy/DeployerWhitelist.sol\";\n\ncontract DeployerWhitelist_Test is CommonTest {\n DeployerWhitelist list;\n\n function setUp() external {\n list = new DeployerWhitelist();\n }\n\n // The owner should be address(0)\n function test_owner_succeeds() external {\n assertEq(list.owner(), address(0));\n }\n\n // The storage slot for the owner must be the same\n function test_storageSlots_succeeds() external {\n vm.prank(list.owner());\n list.setOwner(address(1));\n\n assertEq(bytes32(uint256(1)), vm.load(address(list), bytes32(uint256(0))));\n }\n}\n" - }, - "contracts/test/Encoding.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract Encoding_Test is CommonTest {\n function setUp() external {\n _setUp();\n }\n\n function testFuzz_nonceVersioning_succeeds(uint240 _nonce, uint16 _version) external {\n (uint240 nonce, uint16 version) = Encoding.decodeVersionedNonce(\n Encoding.encodeVersionedNonce(_nonce, _version)\n );\n assertEq(version, _version);\n assertEq(nonce, _nonce);\n }\n\n function testDiff_decodeVersionedNonce_succeeds(uint240 _nonce, uint16 _version) external {\n uint256 nonce = uint256(Encoding.encodeVersionedNonce(_nonce, _version));\n (uint256 decodedNonce, uint256 decodedVersion) = ffi.decodeVersionedNonce(nonce);\n\n assertEq(_version, uint16(decodedVersion));\n\n assertEq(_nonce, uint240(decodedNonce));\n }\n\n function testDiff_encodeCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint8 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint8 version = _version % 2;\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes memory encoding = Encoding.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n bytes memory _encoding = ffi.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n assertEq(encoding, _encoding);\n }\n\n function testDiff_encodeDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bool isCreate,\n bytes memory _data,\n uint256 _logIndex\n ) external {\n Types.UserDepositTransaction memory t = Types.UserDepositTransaction(\n _from,\n _to,\n isCreate,\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n );\n\n bytes memory txn = Encoding.encodeDepositTransaction(t);\n bytes memory _txn = ffi.encodeDepositTransaction(t);\n\n assertEq(txn, _txn);\n }\n}\n" - }, - "contracts/test/FeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { L1FeeVault } from \"../L2/L1FeeVault.sol\";\nimport { BaseFeeVault } from \"../L2/BaseFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n// Test the implementations of the FeeVault\ncontract FeeVault_Test is Bridge_Initializer {\n BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT));\n L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT));\n\n address constant recipient = address(0x10000);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.BASE_FEE_VAULT, address(new BaseFeeVault(recipient)).code);\n vm.etch(Predeploys.L1_FEE_VAULT, address(new L1FeeVault(recipient)).code);\n }\n\n function test_constructor_succeeds() external {\n assertEq(baseFeeVault.RECIPIENT(), recipient);\n assertEq(l1FeeVault.RECIPIENT(), recipient);\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n}\n" - }, - "contracts/test/GasPriceOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GasPriceOracle } from \"../L2/GasPriceOracle.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract GasPriceOracle_Test is CommonTest {\n event OverheadUpdated(uint256);\n event ScalarUpdated(uint256);\n event DecimalsUpdated(uint256);\n\n GasPriceOracle gasOracle;\n L1Block l1Block;\n address depositor;\n\n // set the initial L1 context values\n uint64 constant number = 10;\n uint64 constant timestamp = 11;\n uint256 constant basefee = 100;\n bytes32 constant hash = bytes32(uint256(64));\n uint64 constant sequenceNumber = 0;\n bytes32 constant batcherHash = bytes32(uint256(777));\n uint256 constant l1FeeOverhead = 310;\n uint256 constant l1FeeScalar = 10;\n\n function setUp() external {\n // place the L1Block contract at the predeploy address\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n\n l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n depositor = l1Block.DEPOSITOR_ACCOUNT();\n\n // We are not setting the gas oracle at its predeploy\n // address for simplicity purposes. Nothing in this test\n // requires it to be at a particular address\n gasOracle = new GasPriceOracle();\n\n vm.prank(depositor);\n l1Block.setL1BlockValues({\n _number: number,\n _timestamp: timestamp,\n _basefee: basefee,\n _hash: hash,\n _sequenceNumber: sequenceNumber,\n _batcherHash: batcherHash,\n _l1FeeOverhead: l1FeeOverhead,\n _l1FeeScalar: l1FeeScalar\n });\n }\n\n function test_l1BaseFee_succeeds() external {\n assertEq(gasOracle.l1BaseFee(), basefee);\n }\n\n function test_gasPrice_succeeds() external {\n vm.fee(100);\n uint256 gasPrice = gasOracle.gasPrice();\n assertEq(gasPrice, 100);\n }\n\n function test_baseFee_succeeds() external {\n vm.fee(64);\n uint256 gasPrice = gasOracle.baseFee();\n assertEq(gasPrice, 64);\n }\n\n function test_scalar_succeeds() external {\n assertEq(gasOracle.scalar(), l1FeeScalar);\n }\n\n function test_overhead_succeeds() external {\n assertEq(gasOracle.overhead(), l1FeeOverhead);\n }\n\n function test_decimals_succeeds() external {\n assertEq(gasOracle.decimals(), 6);\n assertEq(gasOracle.DECIMALS(), 6);\n }\n\n // Removed in bedrock\n function test_setGasPrice_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setGasPrice(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n\n // Removed in bedrock\n function test_setL1BaseFee_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setL1BaseFee(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n}\n" - }, - "contracts/test/GovernanceToken.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract GovernanceToken_Test is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n\n function setUp() external {\n vm.prank(owner);\n gov = new GovernanceToken();\n }\n\n function test_constructor_succeeds() external {\n assertEq(gov.owner(), owner);\n assertEq(gov.name(), \"Optimism\");\n assertEq(gov.symbol(), \"OP\");\n assertEq(gov.decimals(), 18);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_mint_fromOwner_succeeds() external {\n // Mint 100 tokens.\n vm.prank(owner);\n gov.mint(owner, 100);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 100);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_mint_fromNotOwner_reverts() external {\n // Mint 100 tokens as rando.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n gov.mint(owner, 100);\n\n // Balance does not update.\n assertEq(gov.balanceOf(owner), 0);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_burn_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando burns their tokens.\n vm.prank(rando);\n gov.burn(50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_burnFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to burn 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner burns 50 tokens from rando.\n vm.prank(owner);\n gov.burnFrom(rando, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_transfer_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando transfers 50 tokens to owner.\n vm.prank(rando);\n gov.transfer(owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_approve_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n\n function test_transferFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner transfers 50 tokens from rando to owner.\n vm.prank(owner);\n gov.transferFrom(rando, owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_increaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Rando increases allowance by 50 tokens.\n vm.prank(rando);\n gov.increaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 100);\n }\n\n function test_decreaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 100 tokens.\n vm.prank(rando);\n gov.approve(owner, 100);\n\n // Rando decreases allowance by 50 tokens.\n vm.prank(rando);\n gov.decreaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n}\n" - }, - "contracts/test/Hashing.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract Hashing_Test is CommonTest {\n function setUp() external {\n _setUp();\n }\n\n function test_hashDepositSource_succeeds() external {\n bytes32 sourceHash = Hashing.hashDepositSource(\n 0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959,\n 0x1\n );\n\n assertEq(sourceHash, 0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc);\n }\n\n function testDiff_hashCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint16 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n // Ensure the version is valid\n uint16 version = uint16(bound(uint256(_version), 0, 1));\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes32 _hash = ffi.hashCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n assertEq(hash, _hash);\n }\n\n function testDiff_hashWithdrawal_succeeds(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n bytes32 hash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(_nonce, _sender, _target, _value, _gasLimit, _data)\n );\n\n bytes32 _hash = ffi.hashWithdrawal(_nonce, _sender, _target, _value, _gasLimit, _data);\n\n assertEq(hash, _hash);\n }\n\n function testDiff_hashOutputRootProof_succeeds(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external {\n Types.OutputRootProof memory proof = Types.OutputRootProof({\n version: _version,\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _messagePasserStorageRoot,\n latestBlockhash: _latestBlockhash\n });\n\n bytes32 hash = Hashing.hashOutputRootProof(proof);\n\n bytes32 _hash = ffi.hashOutputRootProof(\n _version,\n _stateRoot,\n _messagePasserStorageRoot,\n _latestBlockhash\n );\n\n assertEq(hash, _hash);\n }\n\n // TODO(tynes): foundry bug cannot serialize\n // bytes32 as strings with vm.toString\n function testDiff_hashDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint256 _logIndex\n ) external {\n bytes32 hash = Hashing.hashDepositTransaction(\n Types.UserDepositTransaction(\n _from,\n _to,\n false, // isCreate\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n )\n );\n\n bytes32 _hash = ffi.hashDepositTransaction(\n _from,\n _to,\n _mint,\n _value,\n _gas,\n _data,\n _logIndex\n );\n\n assertEq(hash, _hash);\n }\n}\n" - }, - "contracts/test/L1Block.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\ncontract L1BlockTest is CommonTest {\n L1Block lb;\n address depositor;\n bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1));\n\n function setUp() external {\n lb = new L1Block();\n depositor = lb.DEPOSITOR_ACCOUNT();\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: uint64(1),\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: NON_ZERO_HASH,\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(0),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function testFuzz_updatesValues_succeeds(\n uint64 n,\n uint64 t,\n uint256 b,\n bytes32 h,\n uint64 s,\n bytes32 bt,\n uint256 fo,\n uint256 fs\n ) external {\n vm.prank(depositor);\n lb.setL1BlockValues(n, t, b, h, s, bt, fo, fs);\n assertEq(lb.number(), n);\n assertEq(lb.timestamp(), t);\n assertEq(lb.basefee(), b);\n assertEq(lb.hash(), h);\n assertEq(lb.sequenceNumber(), s);\n assertEq(lb.batcherHash(), bt);\n assertEq(lb.l1FeeOverhead(), fo);\n assertEq(lb.l1FeeScalar(), fs);\n }\n\n function test_number_succeeds() external {\n assertEq(lb.number(), uint64(1));\n }\n\n function test_timestamp_succeeds() external {\n assertEq(lb.timestamp(), uint64(2));\n }\n\n function test_basefee_succeeds() external {\n assertEq(lb.basefee(), 3);\n }\n\n function test_hash_succeeds() external {\n assertEq(lb.hash(), NON_ZERO_HASH);\n }\n\n function test_sequenceNumber_succeeds() external {\n assertEq(lb.sequenceNumber(), uint64(4));\n }\n\n function test_updateValues_succeeds() external {\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: type(uint64).max,\n _timestamp: type(uint64).max,\n _basefee: type(uint256).max,\n _hash: keccak256(abi.encode(1)),\n _sequenceNumber: type(uint64).max,\n _batcherHash: bytes32(type(uint256).max),\n _l1FeeOverhead: type(uint256).max,\n _l1FeeScalar: type(uint256).max\n });\n }\n}\n" - }, - "contracts/test/L1BlockNumber.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { L1BlockNumber } from \"../legacy/L1BlockNumber.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract L1BlockNumberTest is Test {\n L1Block lb;\n L1BlockNumber bn;\n\n uint64 constant number = 99;\n\n function setUp() external {\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n lb = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n bn = new L1BlockNumber();\n vm.prank(lb.DEPOSITOR_ACCOUNT());\n\n lb.setL1BlockValues({\n _number: number,\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: bytes32(uint256(10)),\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(uint256(0)),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function test_getL1BlockNumber_succeeds() external {\n assertEq(bn.getL1BlockNumber(), number);\n }\n\n function test_fallback_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n\n function test_receive_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call{ value: 1 }(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n}\n" - }, - "contracts/test/L1CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Messenger_Initializer, Reverter, CallerCaller } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle_Initializer } from \"./L2OutputOracle.t.sol\";\n\n/* Libraries */\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n/* Target contract dependencies */\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/* Target contract */\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\n\ncontract L1CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n function setUp() public override {\n super.setUp();\n }\n\n // pause: should pause the contract when called by the current owner\n function test_pause_succeeds() external {\n vm.prank(alice);\n L1Messenger.pause();\n assert(L1Messenger.paused());\n }\n\n // pause: should not pause the contract when called by account other than the owner\n function test_pause_callerIsNotOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n vm.prank(address(0xABBA));\n L1Messenger.pause();\n }\n\n // unpause: should unpause the contract when called by the current owner\n function test_unpause_succeeds() external {\n vm.prank(alice);\n L1Messenger.pause();\n assert(L1Messenger.paused());\n\n vm.prank(alice);\n L1Messenger.unpause();\n assert(!L1Messenger.paused());\n }\n\n // unpause: should not unpause the contract when called by account other than the owner\n function test_unpause_callerIsNotOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n vm.prank(address(0xABBA));\n L1Messenger.unpause();\n }\n\n // the version is encoded in the nonce\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L1Messenger.messageNonce());\n assertEq(version, L1Messenger.MESSAGE_VERSION());\n }\n\n // sendMessage: should be able to send a single message\n // TODO: this same test needs to be done with the legacy message type\n // by setting the message version to 0\n function test_sendMessage_succeeds() external {\n // deposit transaction on the optimism portal should be called\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n )\n );\n\n // TransactionDeposited event\n vm.expectEmit(true, true, true, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n );\n\n // SentMessage event\n vm.expectEmit(true, true, true, true);\n emit SentMessage(recipient, alice, hex\"ff\", L1Messenger.messageNonce(), 100);\n\n // SentMessageExtension1 event\n vm.expectEmit(true, true, true, true);\n emit SentMessageExtension1(alice, 0);\n\n vm.prank(alice);\n L1Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n // sendMessage: should be able to send the same message twice\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L1Messenger.messageNonce());\n }\n\n function test_xDomainSender_notSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n // xDomainMessageSender: should return the xDomainMsgSender address\n // TODO: might need a test contract\n // function test_xDomainSenderSetCorrectly() external {}\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(address(op));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 2), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n // relayMessage: should send a successful call to the target contract\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.expectCall(target, hex\"1111\");\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L1Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n // set the target to be the OptimismPortal\n address target = address(op);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.prank(address(op));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n message\n );\n\n vm.store(address(op), 0, bytes32(abi.encode(sender)));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: should revert if eth is sent from a contract other than the standard bridge\n function test_replayMessage_withValue_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.expectRevert(\n \"CrossDomainMessenger: value must be zero unless message is from a system address\"\n );\n L1Messenger.relayMessage{ value: 100 }(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should revert if paused\n function test_relayMessage_paused_reverts() external {\n vm.prank(L1Messenger.owner());\n L1Messenger.pause();\n\n vm.expectRevert(\"Pausable: paused\");\n L1Messenger.relayMessage(0, address(0), address(0), 0, 0, hex\"\");\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n vm.expectCall(target, hex\"1111\");\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n // relayMessage: should revert if recipient is trying to reenter\n function test_relayMessage_reentrancy_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = abi.encodeWithSelector(\n L1Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n message\n );\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.etch(target, address(new CallerCaller()).code);\n\n vm.expectEmit(true, true, true, true, target);\n\n emit WhatHappened(\n false,\n abi.encodeWithSignature(\"Error(string)\", \"ReentrancyGuard: reentrant call\")\n );\n\n vm.prank(address(op));\n vm.expectCall(target, message);\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n 0, // value\n 0,\n message\n );\n\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n function test_relayMessage_legacy_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce(0, 0),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 0), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyOldReplay_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce(0, 0),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Mark legacy message as already relayed.\n uint256 successfulMessagesSlot = 203;\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(target, sender, hex\"1111\", 0);\n bytes32 slot = keccak256(abi.encode(oldHash, successfulMessagesSlot));\n vm.store(address(L1Messenger), slot, bytes32(uint256(1)));\n\n // Expect revert.\n vm.expectRevert(\"CrossDomainMessenger: legacy withdrawal already relayed\");\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 0), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was not relayed.\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyRetryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce(0, 0),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect FailedRelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce(0, 0), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 0), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n function test_relayMessage_legacyRetryAfterSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce(0, 0),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce(0, 0), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 0), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce(0, 0),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce(0, 0), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 0), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message has already been relayed\");\n\n // Retry the message again.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 0), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n}\n" - }, - "contracts/test/L1ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.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\ncontract L1ERC721Bridge_Test is Messenger_Initializer {\n TestERC721 internal localToken;\n TestERC721 internal remoteToken;\n L1ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L1ERC721Bridge(address(L1Messenger), otherBridge);\n localToken = new TestERC721();\n remoteToken = new TestERC721();\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L1ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L1Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L1Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notEscrowed_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n" - }, - "contracts/test/L1StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\n\ncontract L1StandardBridge_Getter_Test is Bridge_Initializer {\n function test_getters_succeeds() external {\n assert(L1Bridge.l2TokenBridge() == address(L2Bridge));\n assert(L1Bridge.OTHER_BRIDGE() == L2Bridge);\n assert(L1Bridge.messenger() == L1Messenger);\n assert(L1Bridge.MESSENGER() == L1Messenger);\n assertEq(L1Bridge.version(), \"1.0.0\");\n }\n}\n\ncontract L1StandardBridge_Initialize_Test is Bridge_Initializer {\n function test_initialize_succeeds() external {\n assertEq(address(L1Bridge.messenger()), address(L1Messenger));\n\n assertEq(address(L1Bridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE);\n\n assertEq(address(L2Bridge), Predeploys.L2_STANDARD_BRIDGE);\n }\n}\n\ncontract L1StandardBridge_Initialize_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_Receive_Test is Bridge_Initializer {\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(op).balance, 0);\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 100,\n hex\"\"\n ),\n 200_000\n )\n );\n\n vm.prank(alice, alice);\n (bool success, ) = address(L1Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(op).balance, 100);\n }\n}\n\ncontract L1StandardBridge_Receive_TestFail {}\n\ncontract L1StandardBridge_DepositETH_Test is Bridge_Initializer {\n // depositETH\n // - emits ETHDepositInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_depositETH_succeeds() external {\n assertEq(address(op).balance, 0);\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeInitiated(alice, alice, 500, hex\"ff\");\n\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 500,\n hex\"ff\"\n ),\n 50000\n )\n );\n\n vm.prank(alice, alice);\n L1Bridge.depositETH{ value: 500 }(50000, hex\"ff\");\n assertEq(address(op).balance, 500);\n }\n}\n\ncontract L1StandardBridge_DepositETH_TestFail is Bridge_Initializer {\n function test_depositETH_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, address(L1Token).code);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice);\n L1Bridge.depositETH{ value: 1 }(300, hex\"\");\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_Test is Bridge_Initializer {\n // depositETHTo\n // - emits ETHDepositInitiated\n // - calls optimismPortal.depositTransaction\n // - EOA or contract can call\n // - ETH ends up in the optimismPortal\n function test_depositETHTo_succeeds() external {\n assertEq(address(op).balance, 0);\n\n vm.expectEmit(true, true, true, true);\n emit ETHDepositInitiated(alice, bob, 600, hex\"dead\");\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeInitiated(alice, bob, 600, hex\"dead\");\n\n // depositETHTo on the L1 bridge should be called\n vm.expectCall(\n address(L1Bridge),\n abi.encodeWithSelector(L1Bridge.depositETHTo.selector, bob, 1000, hex\"dead\")\n );\n\n // the L1 bridge should call\n // L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n bob,\n 600,\n hex\"dead\"\n ),\n 1000\n )\n );\n\n // TODO: assert on OptimismPortal being called\n // and the event being emitted correctly\n\n // deposit eth to bob\n vm.prank(alice, alice);\n L1Bridge.depositETHTo{ value: 600 }(bob, 1000, hex\"dead\");\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_DepositERC20_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // depositERC20\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - only callable by EOA\n function test_depositERC20_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n deal(address(L1Token), alice, 100000, true);\n\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n // The L1Bridge should transfer alice's tokens\n // to itself\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 100)\n );\n\n // TODO: optimismPortal.depositTransaction call + event\n\n vm.prank(alice);\n L1Bridge.depositERC20(address(L1Token), address(L2Token), 100, 10000, hex\"\");\n\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n }\n}\n\ncontract L1StandardBridge_DepositERC20_TestFail is Bridge_Initializer {\n function test_depositERC20_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, hex\"ffff\");\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice, alice);\n L1Bridge.depositERC20(address(0), address(0), 100, 100, hex\"\");\n }\n}\n\ncontract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer {\n // depositERC20To\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - callable by a contract\n function test_depositERC20To_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex\"\");\n\n deal(address(L1Token), alice, 100000, true);\n\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 1000)\n );\n\n vm.prank(alice);\n L1Bridge.depositERC20To(address(L1Token), address(L2Token), bob, 1000, 10000, hex\"\");\n\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 1000);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeETHWithdrawal\n // - emits ETHWithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeETHWithdrawal_succeeds() external {\n uint256 aliceBalance = alice.balance;\n\n vm.expectEmit(true, true, true, true);\n emit ETHWithdrawalFinalized(alice, alice, 100, hex\"\");\n\n vm.expectCall(alice, hex\"\");\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n // ensure that the messenger has ETH to call with\n vm.deal(address(L1Bridge.messenger()), 100);\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n\n assertEq(address(L1Bridge.messenger()).balance, 0);\n assertEq(aliceBalance + 100, alice.balance);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeERC20Withdrawal\n // - updates bridge.deposits\n // - emits ERC20WithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeERC20Withdrawal_succeeds() external {\n deal(address(L1Token), address(L1Bridge), 100, true);\n\n uint256 slot = stdstore\n .target(address(L1Bridge))\n .sig(\"deposits(address,address)\")\n .with_key(address(L1Token))\n .with_key(address(L2Token))\n .find();\n\n // Give the L1 bridge some ERC20 tokens\n vm.store(address(L1Bridge), bytes32(slot), bytes32(uint256(100)));\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n\n vm.expectEmit(true, true, true, true);\n emit ERC20WithdrawalFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transfer.selector, alice, 100)\n );\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n assertEq(L1Token.balanceOf(address(L1Bridge)), 0);\n assertEq(L1Token.balanceOf(address(alice)), 100);\n }\n}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer {\n function test_finalizeERC20Withdrawal_notMessenger_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(28));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n\n function test_finalizeERC20Withdrawal_notOtherBridge_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(address(0)))\n );\n vm.prank(address(L1Bridge.messenger()));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n}\n\n// Todo: move these next two contracts into a test file specific to the direction agnostic\n// StandardBridge interface\ncontract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {\n\n}\n\ncontract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer {\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L1Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L1Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, CallerCaller } from \"./CommonTest.t.sol\";\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n function setUp() public override {\n super.setUp();\n }\n\n function test_pause_succeeds() external {\n L2Messenger.pause();\n assert(L2Messenger.paused());\n }\n\n function test_pause_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n vm.prank(address(0xABBA));\n L2Messenger.pause();\n }\n\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L2Messenger.messageNonce());\n assertEq(version, L2Messenger.MESSAGE_VERSION());\n }\n\n function test_sendMessage_succeeds() external {\n bytes memory xDomainCallData = Encoding.encodeCrossDomainMessage(\n L2Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n );\n vm.expectCall(\n address(messagePasser),\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData\n )\n );\n\n // MessagePassed event\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(L2Messenger),\n address(L1Messenger),\n 0,\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData,\n Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messagePasser.messageNonce(),\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: L2Messenger.baseGas(hex\"ff\", 100),\n data: xDomainCallData\n })\n )\n );\n\n vm.prank(alice);\n L2Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L2Messenger.messageNonce();\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L2Messenger.messageNonce());\n }\n\n function test_xDomainSender_senderNotSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 2), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n vm.expectCall(target, hex\"1111\");\n\n vm.prank(caller);\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L2Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L2Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n address target = address(messagePasser);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n bytes memory message = hex\"1111\";\n\n vm.prank(caller);\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should revert if paused\n function test_relayMessage_paused_reverts() external {\n vm.prank(L2Messenger.owner());\n L2Messenger.pause();\n\n vm.expectRevert(\"Pausable: paused\");\n L2Messenger.relayMessage(0, address(0), address(0), 0, 0, hex\"\");\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retry_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n uint256 value = 100;\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(caller), value);\n vm.prank(caller);\n L2Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L2Messenger.successfulMessages(hash), false);\n assertEq(L2Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L2Messenger.successfulMessages(hash), true);\n assertEq(L2Messenger.failedMessages(hash), true);\n }\n\n // relayMessage: should revert if recipient is trying to reenter\n function test_relayMessage_reentrancy_reverts() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n bytes memory message = abi.encodeWithSelector(\n L2Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n message\n );\n\n vm.etch(target, address(new CallerCaller()).code);\n\n vm.expectEmit(true, true, true, true, target);\n\n emit WhatHappened(\n false,\n abi.encodeWithSignature(\"Error(string)\", \"ReentrancyGuard: reentrant call\")\n );\n\n vm.prank(caller);\n vm.expectCall(target, message);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n 0, // value\n 0,\n message\n );\n\n assertEq(L2Messenger.successfulMessages(hash), false);\n assertEq(L2Messenger.failedMessages(hash), true);\n }\n}\n" - }, - "contracts/test/L2ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.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\ncontract TestMintableERC721 is OptimismMintableERC721 {\n constructor(address _bridge, address _remoteToken)\n OptimismMintableERC721(_bridge, 1, _remoteToken, \"Test\", \"TST\")\n {}\n\n function mint(address to, uint256 tokenId) public {\n _mint(to, tokenId);\n }\n}\n\ncontract L2ERC721Bridge_Test is Messenger_Initializer {\n TestMintableERC721 internal localToken;\n TestERC721 internal remoteToken;\n L2ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L2ERC721Bridge(address(L2Messenger), otherBridge);\n remoteToken = new TestERC721();\n localToken = new TestMintableERC721(address(bridge), address(remoteToken));\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L2ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L2Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L2Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L1ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"L2ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_alreadyExists_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721: token already minted\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n" - }, - "contracts/test/L2OutputOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { L2OutputOracle_Initializer, NextImpl } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2OutputOracleTest is L2OutputOracle_Initializer {\n bytes32 proposedOutput1 = keccak256(abi.encode(1));\n\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n function setUp() public override {\n super.setUp();\n }\n\n function test_constructor_succeeds() external {\n assertEq(oracle.PROPOSER(), proposer);\n assertEq(oracle.CHALLENGER(), owner);\n assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval);\n assertEq(oracle.latestBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingTimestamp(), startingTimestamp);\n }\n\n function test_constructor_badTimestamp_reverts() external {\n vm.expectRevert(\"L2OutputOracle: starting L2 timestamp must be less than current time\");\n\n new L2OutputOracle(\n submissionInterval,\n l2BlockTime,\n startingBlockNumber,\n // startingTimestamp is in the future\n block.timestamp + 1,\n proposer,\n owner\n );\n }\n\n /****************\n * Getter Tests *\n ****************/\n\n // Test: latestBlockNumber() should return the correct value\n function test_latestBlockNumber_succeeds() external {\n uint256 proposedNumber = oracle.nextBlockNumber();\n\n // Roll to after the block number we'll propose\n warpToProposeTime(proposedNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, proposedNumber, 0, 0);\n assertEq(oracle.latestBlockNumber(), proposedNumber);\n }\n\n // Test: getL2Output() should return the correct value\n function test_getL2Output_succeeds() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0);\n\n Types.OutputProposal memory proposal = oracle.getL2Output(nextOutputIndex);\n assertEq(proposal.outputRoot, proposedOutput1);\n assertEq(proposal.timestamp, block.timestamp);\n\n // The block number is larger than the latest proposed output:\n vm.expectRevert(stdError.indexOOBError);\n oracle.getL2Output(nextOutputIndex + 1);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is exact block\n function test_getL2OutputIndexAfter_sameBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with exact same block as proposed returns the proposal.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is previous block\n function test_getL2OutputIndexAfter_previousBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with previous block returns the proposal too.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 - 1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value during binary search\n function test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n bytes32 output2 = keccak256(abi.encode(2));\n uint256 nextBlockNumber2 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber2);\n vm.prank(proposer);\n oracle.proposeL2Output(output2, nextBlockNumber2, 0, 0);\n\n bytes32 output3 = keccak256(abi.encode(3));\n uint256 nextBlockNumber3 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber3);\n vm.prank(proposer);\n oracle.proposeL2Output(output3, nextBlockNumber3, 0, 0);\n\n bytes32 output4 = keccak256(abi.encode(4));\n uint256 nextBlockNumber4 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber4);\n vm.prank(proposer);\n oracle.proposeL2Output(output4, nextBlockNumber4, 0, 0);\n\n // Querying with a block number between the first and second proposal\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 + 1);\n assertEq(index1, 1);\n\n // Querying with a block number between the second and third proposal\n uint256 index2 = oracle.getL2OutputIndexAfter(nextBlockNumber2 + 1);\n assertEq(index2, 2);\n\n // Querying with a block number between the third and fourth proposal\n uint256 index3 = oracle.getL2OutputIndexAfter(nextBlockNumber3 + 1);\n assertEq(index3, 3);\n }\n\n // Test: getL2OutputIndexAfter() reverts when no output exists yet\n function test_getL2OutputIndexAfter_noOutputsExis_reverts() external {\n vm.expectRevert(\"L2OutputOracle: cannot get output as no outputs have been proposed yet\");\n oracle.getL2OutputIndexAfter(0);\n }\n\n // Test: nextBlockNumber() should return the correct value\n function test_nextBlockNumber_succeeds() external {\n assertEq(\n oracle.nextBlockNumber(),\n // The return value should match this arithmetic\n oracle.latestBlockNumber() + oracle.SUBMISSION_INTERVAL()\n );\n }\n\n function test_computeL2Timestamp_succeeds() external {\n // reverts if timestamp is too low\n vm.expectRevert(stdError.arithmeticError);\n oracle.computeL2Timestamp(startingBlockNumber - 1);\n\n // returns the correct value...\n // ... for the very first block\n assertEq(oracle.computeL2Timestamp(startingBlockNumber), startingTimestamp);\n\n // ... for the first block after the starting block\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 1),\n startingTimestamp + l2BlockTime\n );\n\n // ... for some other block number\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 96024),\n startingTimestamp + l2BlockTime * 96024\n );\n }\n\n /*****************************\n * Propose Tests - Happy Path *\n *****************************/\n\n // Test: proposeL2Output succeeds when given valid input, and no block hash and number are\n // specified.\n function test_proposeL2Output_proposeAnotherOutput_succeeds() public {\n bytes32 proposedOutput2 = keccak256(abi.encode());\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n uint256 proposedNumber = oracle.latestBlockNumber();\n\n // Ensure the submissionInterval is enforced\n assertEq(nextBlockNumber, proposedNumber + submissionInterval);\n\n vm.roll(nextBlockNumber + 1);\n\n vm.expectEmit(true, true, true, true);\n emit OutputProposed(proposedOutput2, nextOutputIndex, nextBlockNumber, block.timestamp);\n\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output succeeds when given valid input, and when a block hash and number are\n // specified for reorg protection.\n function test_proposeWithBlockhashAndHeight_succeeds() external {\n // Get the number and hash of a previous block in the chain\n uint256 prevL1BlockNumber = block.number - 1;\n bytes32 prevL1BlockHash = blockhash(prevL1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber);\n }\n\n /***************************\n * Propose Tests - Sad Path *\n ***************************/\n\n // Test: proposeL2Output fails if called by a party that is not the proposer.\n function test_proposeL2Output_notProposer_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n\n vm.prank(address(128));\n vm.expectRevert(\"L2OutputOracle: only the proposer address can propose new outputs\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails given a zero blockhash.\n function test_proposeL2Output_emptyOutput_reverts() external {\n bytes32 outputToPropose = bytes32(0);\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: L2 output proposal cannot be the zero hash\");\n oracle.proposeL2Output(outputToPropose, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if the block number doesn't match the next expected number.\n function test_proposeL2Output_unexpectedBlockNumber_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: block number must be equal to next expected block number\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0);\n }\n\n // Test: proposeL2Output fails if it would have a timestamp in the future.\n function test_proposeL2Output_futureTimetamp_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextTimestamp = oracle.computeL2Timestamp(nextBlockNumber);\n vm.warp(nextTimestamp);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: cannot propose L2 output in the future\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if a non-existent L1 block hash and number are provided for reorg\n // protection.\n function test_proposeL2Output_wrongFork_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(\n nonZeroHash,\n nextBlockNumber,\n bytes32(uint256(0x01)),\n block.number - 1\n );\n }\n\n // Test: proposeL2Output fails when given valid input, but the block hash and number do not\n // match.\n function test_proposeL2Output_unmatchedBlockhash_reverts() external {\n // Move ahead to block 100 so that we can reference historical blocks\n vm.roll(100);\n\n // Get the number and hash of a previous block in the chain\n uint256 l1BlockNumber = block.number - 1;\n bytes32 l1BlockHash = blockhash(l1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n\n // This will fail when foundry no longer returns zerod block hashes\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1);\n }\n\n /*****************************\n * Delete Tests - Happy Path *\n *****************************/\n\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n function test_deleteOutputs_singleOutput_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 1);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex);\n oracle.deleteL2Outputs(latestOutputIndex);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n function test_deleteOutputs_multipleOutputs_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 3);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex - 2);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval * 3, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n /***************************\n * Delete Tests - Sad Path *\n ***************************/\n\n function test_deleteL2Outputs_ifNotChallenger_reverts() external {\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.expectRevert(\"L2OutputOracle: only the challenger address can delete outputs\");\n oracle.deleteL2Outputs(latestBlockNumber);\n }\n\n function test_deleteL2Outputs_nonExistent_reverts() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestBlockNumber + 1);\n }\n\n function test_deleteL2Outputs_afterLatest_reverts() external {\n // Start by proposing three outputs\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n // Delete the latest two outputs\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n vm.prank(owner);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // Now try to delete the same output again\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n }\n}\n\ncontract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {\n Proxy internal proxy;\n\n function setUp() public override {\n super.setUp();\n proxy = Proxy(payable(address(oracle)));\n }\n\n function test_initValuesOnProxy_succeeds() external {\n assertEq(submissionInterval, oracleImpl.SUBMISSION_INTERVAL());\n assertEq(l2BlockTime, oracleImpl.L2_BLOCK_TIME());\n assertEq(startingBlockNumber, oracleImpl.startingBlockNumber());\n assertEq(startingTimestamp, oracleImpl.startingTimestamp());\n\n assertEq(proposer, oracleImpl.PROPOSER());\n assertEq(owner, oracleImpl.CHALLENGER());\n }\n\n function test_initializeProxy_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(payable(proxy)).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_initializeImpl_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(oracleImpl).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(oracle), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(oracle), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(oracle)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n" - }, - "contracts/test/L2StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { console } from \"forge-std/console.sol\";\n\ncontract L2StandardBridge_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n function setUp() public override {\n super.setUp();\n }\n\n function test_initialize_succeeds() external {\n assertEq(address(L2Bridge.messenger()), address(L2Messenger));\n assertEq(L1Bridge.l2TokenBridge(), address(L2Bridge));\n assertEq(address(L2Bridge.OTHER_BRIDGE()), address(L1Bridge));\n }\n\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(messagePasser).balance, 0);\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n // TODO: L2Messenger should be called\n // TODO: L2ToL1MessagePasser should be called\n // TODO: withdrawal hash should be computed correctly\n // TODO: events from each contract\n\n vm.prank(alice, alice);\n (bool success, ) = address(L2Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(messagePasser).balance, 100);\n }\n\n // withrdraw\n // - requires amount == msg.value\n function test_withdraw_insufficientValue_reverts() external {\n assertEq(address(messagePasser).balance, 0);\n\n vm.expectRevert(\"StandardBridge: bridging ETH must include sufficient ETH value\");\n vm.prank(alice, alice);\n L2Bridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 100, 1000, hex\"\");\n }\n\n // withdraw\n // - token is burned\n // - emits WithdrawalInitiated\n // - calls Withdrawer.initiateWithdrawal\n function test_withdraw_succeeds() external {\n // Alice has 100 L2Token\n deal(address(L2Token), alice, 100, true);\n assertEq(L2Token.balanceOf(alice), 100);\n\n vm.prank(alice, alice);\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n\n // TODO: events and calls\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_withdraw_notEOA_reverts() external {\n // This contract has 100 L2Token\n deal(address(L2Token), address(this), 100, true);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n }\n\n // withdrawTo\n // - token is burned\n // - emits WithdrawalInitiated w/ correct recipient\n // - calls Withdrawer.initiateWithdrawal\n function test_withdrawTo_succeeds() external {\n deal(address(L2Token), alice, 100, true);\n\n vm.prank(alice, alice);\n L2Bridge.withdrawTo(address(L2Token), bob, 100, 1000, hex\"\");\n\n // TODO: events and calls\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n // finalizeDeposit\n // - only callable by l1TokenBridge\n // - supported token pair emits DepositFinalized\n // - invalid deposit calls Withdrawer.initiateWithdrawal\n function test_finalizeDeposit_succeeds() external {\n // TODO: events and calls\n\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeFinalized(\n address(L2Token), // localToken\n address(L1Token), // remoteToken\n alice,\n alice,\n 100,\n hex\"\"\n );\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n vm.prank(address(L2Messenger));\n L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L2Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Messenger), 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2ToL1MessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\n\ncontract L2ToL1MessagePasserTest is CommonTest {\n L2ToL1MessagePasser messagePasser;\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n function setUp() public virtual {\n messagePasser = new L2ToL1MessagePasser();\n }\n\n function testFuzz_initiateWithdrawal_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint256 nonce = messagePasser.messageNonce();\n\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: _value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, _sender, _target, _value, _gasLimit, _data, withdrawalHash);\n\n vm.deal(_sender, _value);\n vm.prank(_sender);\n messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);\n\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n\n bytes32 slot = keccak256(bytes.concat(withdrawalHash, bytes32(0)));\n\n assertEq(vm.load(address(messagePasser), slot), bytes32(uint256(1)));\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by a contract\n function test_initiateWithdrawal_fromContract_succeeds() external {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\"\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\",\n withdrawalHash\n );\n\n vm.deal(address(this), 2**64);\n messagePasser.initiateWithdrawal{ value: 100 }(address(4), 64000, hex\"\");\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by an EOA\n function test_initiateWithdrawal_fromEOA_succeeds() external {\n uint256 gasLimit = 64000;\n address target = address(4);\n uint256 value = 100;\n bytes memory data = hex\"ff\";\n uint256 nonce = messagePasser.messageNonce();\n\n // EOA emulation\n vm.prank(alice, alice);\n vm.deal(alice, 2**64);\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(nonce, alice, target, value, gasLimit, data)\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, alice, target, value, gasLimit, data, withdrawalHash);\n\n messagePasser.initiateWithdrawal{ value: value }(target, gasLimit, data);\n\n // the sent messages mapping is filled\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n // the nonce increments\n assertEq(nonce + 1, messagePasser.messageNonce());\n }\n\n // Test: burn should destroy the ETH held in the contract\n function test_burn_succeeds() external {\n messagePasser.initiateWithdrawal{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n NON_ZERO_GASLIMIT,\n NON_ZERO_DATA\n );\n\n assertEq(address(messagePasser).balance, NON_ZERO_VALUE);\n vm.expectEmit(true, false, false, false);\n emit WithdrawerBalanceBurnt(NON_ZERO_VALUE);\n messagePasser.burn();\n\n // The Withdrawer should have no balance\n assertEq(address(messagePasser).balance, 0);\n }\n}\n" - }, - "contracts/test/LegacyERC20ETH.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyERC20ETH_Test is CommonTest {\n LegacyERC20ETH eth;\n\n function setUp() external {\n eth = new LegacyERC20ETH();\n }\n\n function test_metadata_succeeds() external {\n assertEq(eth.name(), \"Ether\");\n assertEq(eth.symbol(), \"ETH\");\n assertEq(eth.decimals(), 18);\n }\n\n function test_crossDomain_succeeds() external {\n assertEq(eth.l2Bridge(), Predeploys.L2_STANDARD_BRIDGE);\n assertEq(eth.l1Token(), address(0));\n }\n\n function test_transfer_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transfer is disabled\");\n eth.transfer(alice, 100);\n }\n\n function test_approve_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: approve is disabled\");\n eth.approve(alice, 100);\n }\n\n function test_transferFrom_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transferFrom is disabled\");\n eth.transferFrom(bob, alice, 100);\n }\n\n function test_increaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n eth.increaseAllowance(alice, 100);\n }\n\n function test_decreaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n eth.decreaseAllowance(alice, 100);\n }\n\n function test_mint_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: mint is disabled\");\n eth.mint(alice, 100);\n }\n\n function test_burn_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: burn is disabled\");\n eth.burn(alice, 100);\n }\n}\n" - }, - "contracts/test/LegacyMessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyMessagePasser } from \"../legacy/LegacyMessagePasser.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyMessagePasser_Test is CommonTest {\n LegacyMessagePasser messagePasser;\n\n function setUp() external {\n messagePasser = new LegacyMessagePasser();\n }\n\n function test_passMessageToL1_succeeds() external {\n vm.prank(alice);\n messagePasser.passMessageToL1(hex\"ff\");\n assert(messagePasser.sentMessages(keccak256(abi.encodePacked(hex\"ff\", alice))));\n }\n}\n" - }, - "contracts/test/MerkleTrie.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MerkleTrie } from \"../libraries/trie/MerkleTrie.sol\";\n\ncontract MerkleTrie_Test is CommonTest {\n function setUp() public {\n _setUp();\n }\n\n function test_get_validProof1_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579326262\";\n bytes memory val = hex\"6176616c32\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof2_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[\n 2\n ] = hex\"ef83206161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof3_succeeds() external {\n bytes32 root = 0xf838216fa749aefa91e0b672a9c06d3e6e983f913d7107b5dab4af60b5f5abed;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"f387206b6579316161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof4_succeeds() external {\n bytes32 root = 0x37956bab6bba472308146808d5311ac19cb4a7daae5df7efcc0f32badc97f55e;\n bytes memory key = hex\"6b6579316161\";\n bytes memory val = hex\"3031323334\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"ce87206b6579316161853031323334\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof5_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657931\";\n bytes\n memory val = hex\"30313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f862808080808080a057895fdbd71e2c67c2f9274a56811ff5cf458720a7fa713a135e3890f8cafcf8808080808080808080b130313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof6_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657932\";\n bytes memory val = hex\"73686f7274\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[2] = hex\"df808080808080c9823262856176616c338080808080808080808573686f7274\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof7_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657933\";\n bytes memory val = hex\"31323334353637383930313233343536373839303132333435363738393031\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f839808080808080c9823363856176616c338080808080808080809f31323334353637383930313233343536373839303132333435363738393031\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof8_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"61\";\n bytes memory val = hex\"61\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22061\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof9_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"62\";\n bytes memory val = hex\"62\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22062\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof10_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"63\";\n bytes memory val = hex\"63\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22063\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_nonexistentKey1_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b657932\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_nonexistentKey2_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"616e7972616e646f6d6b6579\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_wrongKeyProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579316161\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e216a04892c039d654f1be9af20e88ae53e9ab5fa5520190e0fb2f805823e45ebad22f\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[2] = hex\"d687206e6f746865728d33343938683472697568677765\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_corruptedProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579326262\";\n bytes[] memory proof = new bytes[](5);\n proof[0] = hex\"2fd2ba5ee42358802ffbe0900152a55fabe953ae880ef29abef154d639c09248a016e2\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[\n 2\n ] = hex\"e583165793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 3\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[4] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidDataRemainder_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa000000000000000000000000000000\";\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidInternalNodeHash_reverts() external {\n bytes32 root = 0xa827dff1a657bb9bb9a1c3abe9db173e2f1359f15eb06f1647ea21ac7c95d8fa;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa09862c6b113008c4204c13755693cbb868acc25ebaa98db11df8c89a0c0dd3157\";\n proof[\n 1\n ] = hex\"f380808080808080808080a0de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f00c220118080808080\";\n proof[2] = hex\"de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroBranchValueLength_reverts() external {\n bytes32 root = 0xe04b3589eef96b237cd49ccb5dcf6e654a47682bfa0961d563ab843f7ad1e035;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](2);\n proof[0] = hex\"dd8200aad98080808080808080808080c43b82aabbc43c82aacc80808080\";\n proof[1] = hex\"d98080808080808080808080c43b82aabbc43c82aacc80808080\";\n\n vm.expectRevert(\"MerkleTrie: value length must be greater than zero (branch)\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroLengthKey_reverts() external {\n bytes32 root = 0x54157fd62cdf2f474e7bfec2d3cd581e807bee38488c9590cb887add98936b73;\n bytes memory key = hex\"\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"c78320f00082b443\";\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey1_reverts() external {\n bytes32 root = 0xa513ba530659356fb7588a2c831944e80fd8aedaa5a4dc36f918152be2be0605;\n bytes memory key = hex\"01\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"db10d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[1] = hex\"d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[2] = hex\"c582202381aa\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey2_reverts() external {\n bytes32 root = 0xa06abffaec4ebe8ccde595f4547b864b4421b21c1fc699973f94710c9bc17979;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa07ea462226a3dc0a46afb4ded39306d7a84d311ada3557dfc75a909fd25530905\";\n proof[\n 1\n ] = hex\"f380808080808080808080a027f11bd3af96d137b9287632f44dd00fea1ca1bd70386c30985ede8cc287476e808080c220338080\";\n proof[2] = hex\"e48200bba0a6911545ed01c2d3f4e15b8b27c7bfba97738bd5e6dd674dd07033428a4c53af\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_extraProofElements_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](4);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa\";\n proof[3] = hex\"c32081aa\";\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_validProofs_succeeds(bytes4) external {\n // Generate a test case with a valid proof of inclusion for the k/v pair in the trie.\n (bytes32 root, bytes memory key, bytes memory val, bytes[] memory proof) = ffi\n .getMerkleTrieFuzzCase(\"valid\");\n\n // Assert that our expected value is equal to our actual value.\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidRoot_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"valid\"\n );\n\n bytes32 rootHash = keccak256(abi.encodePacked(root));\n vm.expectRevert(\"MerkleTrie: invalid root hash\");\n MerkleTrie.get(key, proof, rootHash);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_extraProofElements_reverts(bytes4) external {\n // Generate an invalid test case with an extra proof element attached to an otherwise\n // valid proof of inclusion for the passed k/v.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"extra_proof_elems\"\n );\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidLargeInternalHash_reverts(bytes4) external {\n // Generate an invalid test case where a long proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_large_internal_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid large internal hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidInternalNodeHash_reverts(bytes4) external {\n // Generate an invalid test case where a small proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_internal_node_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_corruptedProof_reverts(bytes4) external {\n // Generate an invalid test case where the proof is malformed.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"corrupted_proof\"\n );\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidDataRemainder_reverts(bytes4) external {\n // Generate an invalid test case where a random element of the proof has more bytes than the\n // length designates within the RLP list encoding.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_data_remainder\"\n );\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_prefixedValidKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and a valid key that is prefixed\n // with random bytes\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"prefixed_valid_key\"\n );\n\n // Ambiguous revert check- all that we care is that it *does* fail. This case may\n // fail within different branches.\n vm.expectRevert();\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_emptyKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and an empty key\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"empty_key\"\n );\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_partialProof_reverts(bytes4) external {\n // Get a random test case with a valid trie / partially correct proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"partial_proof\"\n );\n\n vm.expectRevert(\"MerkleTrie: ran out of proof elements\");\n MerkleTrie.get(key, proof, root);\n }\n}\n" - }, - "contracts/test/MintManager.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MintManager } from \"../governance/MintManager.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract MintManager_Test is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n MintManager internal manager;\n\n function setUp() external {\n vm.prank(owner);\n gov = new GovernanceToken();\n\n vm.prank(owner);\n manager = new MintManager(owner, address(gov));\n\n vm.prank(owner);\n gov.transferOwnership(address(manager));\n }\n\n function test_constructor_succeeds() external {\n assertEq(manager.owner(), owner);\n assertEq(address(manager.governanceToken()), address(gov));\n }\n\n function test_mint_fromOwner_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n function test_mint_fromNotOwner_reverts() external {\n // Mint from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.mint(owner, 100);\n }\n\n function test_mint_afterPeriodElapsed_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again after period elapsed (2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n manager.mint(owner, 2);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 102);\n }\n\n function test_mint_beforePeriodElapsed_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: minting not permitted yet\");\n manager.mint(owner, 100);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n function test_mint_moreThanCap_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again (greater than 2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint amount exceeds cap\");\n manager.mint(owner, 3);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n function test_upgrade_fromOwner_succeeds() external {\n // Upgrade to new manager.\n vm.prank(owner);\n manager.upgrade(rando);\n\n // New manager is rando.\n assertEq(gov.owner(), rando);\n }\n\n function test_upgrade_fromNotOwner_reverts() external {\n // Upgrade from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.upgrade(rando);\n }\n\n function test_upgrade_toZeroAddress_reverts() external {\n // Upgrade to zero address fails.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint manager cannot be the zero address\");\n manager.upgrade(address(0));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport {\n ILegacyMintableERC20,\n IOptimismMintableERC20\n} from \"../universal/IOptimismMintableERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ncontract OptimismMintableERC20_Test is Bridge_Initializer {\n event Mint(address indexed account, uint256 amount);\n event Burn(address indexed account, uint256 amount);\n\n function setUp() public override {\n super.setUp();\n }\n\n function test_remoteToken_succeeds() external {\n assertEq(L2Token.remoteToken(), address(L1Token));\n }\n\n function test_bridge_succeeds() external {\n assertEq(L2Token.bridge(), address(L2Bridge));\n }\n\n function test_l1Token_succeeds() external {\n assertEq(L2Token.l1Token(), address(L1Token));\n }\n\n function test_l2Bridge_succeeds() external {\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_legacy_succeeds() external {\n // Getters for the remote token\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.l1Token(), address(L1Token));\n // Getters for the bridge\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_mint_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 100);\n }\n\n function test_mint_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.mint(alice, 100);\n }\n\n function test_burn_succeeds() external {\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_burn_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.burn(alice, 100);\n }\n\n function test_erc165_supportsInterface_succeeds() external {\n // The assertEq calls in this test are comparing the manual calculation of the iface,\n // with what is returned by the solidity's type().interfaceId, just to be safe.\n bytes4 iface1 = bytes4(keccak256(\"supportsInterface(bytes4)\"));\n assertEq(iface1, type(IERC165).interfaceId);\n assert(L2Token.supportsInterface(iface1));\n\n bytes4 iface2 = L2Token.l1Token.selector ^ L2Token.mint.selector ^ L2Token.burn.selector;\n assertEq(iface2, type(ILegacyMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface2));\n\n bytes4 iface3 = L2Token.remoteToken.selector ^\n L2Token.bridge.selector ^\n L2Token.mint.selector ^\n L2Token.burn.selector;\n assertEq(iface3, type(IOptimismMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface3));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\n\ncontract OptimismMintableTokenFactory_Test is Bridge_Initializer {\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n }\n\n function test_bridge_succeeds() external {\n assertEq(address(L2TokenFactory.BRIDGE()), address(L2Bridge));\n }\n\n function test_createStandardL2Token_succeeds() external {\n address remote = address(4);\n address local = LibRLP.computeAddress(address(L2TokenFactory), 2);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_sameTwice_succeeds() external {\n address remote = address(4);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n\n address local = LibRLP.computeAddress(address(L2TokenFactory), 3);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_remoteIsZero_succeeds() external {\n address remote = address(0);\n vm.expectRevert(\"OptimismMintableERC20Factory: must provide remote token address\");\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\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 { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.sol\";\n\ncontract OptimismMintableERC721_Test is ERC721Bridge_Initializer {\n ERC721 internal L1Token;\n OptimismMintableERC721 internal L2Token;\n\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n event Mint(address indexed account, uint256 tokenId);\n\n event Burn(address indexed account, uint256 tokenId);\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n L1Token = new ERC721(\"L1Token\", \"L1T\");\n L2Token = new OptimismMintableERC721(\n address(L2Bridge),\n 1,\n address(L1Token),\n \"L2Token\",\n \"L2T\"\n );\n\n // Label the addresses for nice traces.\n vm.label(address(L1Token), \"L1ERC721Token\");\n vm.label(address(L2Token), \"L2ERC721Token\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(L2Token.name(), \"L2Token\");\n assertEq(L2Token.symbol(), \"L2T\");\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.remoteChainId(), 1);\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_safeMint_succeeds() external {\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(address(0), alice, 1);\n\n // Expect a mint event.\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 1);\n\n // Mint the token.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token should be owned by alice.\n assertEq(L2Token.ownerOf(1), alice);\n }\n\n function test_safeMint_notBridge_reverts() external {\n // Try to mint the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.safeMint(alice, 1);\n }\n\n function test_burn_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(alice, address(0), 1);\n\n // Expect a burn event.\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 1);\n\n // Burn the token.\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 1);\n\n // Token should be owned by address(0).\n vm.expectRevert(\"ERC721: invalid token ID\");\n L2Token.ownerOf(1);\n }\n\n function test_burn_notBridge_reverts() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Try to burn the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.burn(alice, 1);\n }\n\n function test_tokenURI_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token URI should be correct.\n assertEq(\n L2Token.tokenURI(1),\n string(\n abi.encodePacked(\n \"ethereum:\",\n Strings.toHexString(uint160(address(L1Token)), 20),\n \"@\",\n Strings.toString(1),\n \"/tokenURI?uint256=\",\n Strings.toString(1)\n )\n )\n );\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\n\ncontract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer {\n OptimismMintableERC721Factory internal factory;\n\n event OptimismMintableERC721Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n factory = new OptimismMintableERC721Factory(address(L2Bridge), 1);\n\n // Label the addresses for nice traces.\n vm.label(address(factory), \"OptimismMintableERC721Factory\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(factory.BRIDGE(), address(L2Bridge));\n assertEq(factory.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_succeeds() external {\n // Predict the address based on the factory address and nonce.\n address predicted = LibRLP.computeAddress(address(factory), 1);\n\n // Expect a token creation event.\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC721Created(predicted, address(1234), alice);\n\n // Create the token.\n vm.prank(alice);\n OptimismMintableERC721 created = OptimismMintableERC721(\n factory.createOptimismMintableERC721(address(1234), \"L2Token\", \"L2T\")\n );\n\n // Token address should be correct.\n assertEq(address(created), predicted);\n\n // Should be marked as created by the factory.\n assertEq(factory.isOptimismMintableERC721(address(created)), true);\n\n // Token should've been constructed correctly.\n assertEq(created.name(), \"L2Token\");\n assertEq(created.symbol(), \"L2T\");\n assertEq(created.REMOTE_TOKEN(), address(1234));\n assertEq(created.BRIDGE(), address(L2Bridge));\n assertEq(created.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_zeroRemoteToken_reverts() external {\n // Try to create a token with a zero remote token address.\n vm.expectRevert(\"OptimismMintableERC721Factory: L1 token address cannot be address(0)\");\n factory.createOptimismMintableERC721(address(0), \"L2Token\", \"L2T\");\n }\n}\n" - }, - "contracts/test/OptimismPortal.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { Portal_Initializer, CommonTest, NextImpl } from \"./CommonTest.t.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\n\ncontract OptimismPortal_Test is Portal_Initializer {\n function test_constructor_succeeds() external {\n assertEq(op.FINALIZATION_PERIOD_SECONDS(), 7 days);\n assertEq(address(op.L2_ORACLE()), address(oracle));\n assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD);\n }\n\n function test_receive_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(alice, alice, 100, 100, 100_000, false, hex\"\");\n\n // give alice money and send as an eoa\n vm.deal(alice, 2**64);\n vm.prank(alice, alice);\n (bool s, ) = address(op).call{ value: 100 }(hex\"\");\n\n assert(s);\n assertEq(address(op).balance, 100);\n }\n\n // Test: depositTransaction fails when contract creation has a non-zero destination address\n function test_depositTransaction_contractCreation_reverts() external {\n // contract creation must have a target of address(0)\n vm.expectRevert(\"OptimismPortal: must send to address(0) when creating a contract\");\n op.depositTransaction(address(1), 1, 0, true, hex\"\");\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value\n function test_depositTransaction_noValueEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value\n function test_depositTransaction_noValueContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndContractContractCreation_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n function test_simple_isOutputFinalized_succeeds() external {\n uint256 ts = block.timestamp;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(bytes32(uint256(1)), uint128(ts), uint128(startingBlockNumber))\n )\n );\n\n // warp to the finalization period\n vm.warp(ts + op.FINALIZATION_PERIOD_SECONDS());\n assertEq(op.isOutputFinalized(0), false);\n\n // warp past the finalization period\n vm.warp(ts + op.FINALIZATION_PERIOD_SECONDS() + 1);\n assertEq(op.isOutputFinalized(0), true);\n }\n\n function test_isOutputFinalized_succeeds() external {\n uint256 checkpoint = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n vm.roll(checkpoint);\n vm.warp(oracle.computeL2Timestamp(checkpoint) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(keccak256(abi.encode(2)), checkpoint, 0, 0);\n\n // warp to the final second of the finalization period\n uint256 finalizationHorizon = block.timestamp + op.FINALIZATION_PERIOD_SECONDS();\n vm.warp(finalizationHorizon);\n // The checkpointed block should not be finalized until 1 second from now.\n assertEq(op.isOutputFinalized(nextOutputIndex), false);\n // Nor should a block after it\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n\n // warp past the finalization period\n vm.warp(finalizationHorizon + 1);\n // It should now be finalized.\n assertEq(op.isOutputFinalized(nextOutputIndex), true);\n // But not the block after it.\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n }\n}\n\ncontract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n op.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n // Utility function used in the subsequent test. This is necessary to assert that the\n // reentrant call will revert.\n function callPortalAndExpectRevert() external payable {\n vm.expectRevert(\"OptimismPortal: can only trigger one withdrawal per transaction\");\n // Arguments here don't matter, as the require check is the first thing that happens.\n // We assume that this has already been proven.\n op.finalizeWithdrawalTransaction(_defaultTx);\n // Assert that the withdrawal was not finalized.\n assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx)));\n }\n\n // Test: proveWithdrawalTransaction cannot prove a withdrawal with itself (the OptimismPortal) as the target.\n function test_proveWithdrawalTransaction_onSelfCall_reverts() external {\n _defaultTx.target = address(op);\n vm.expectRevert(\"OptimismPortal: you cannot send messages to the portal contract\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the outputRootProof does not match the output root\n function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external {\n // Modify the version to invalidate the withdrawal proof.\n _outputRootProof.version = bytes32(uint256(1));\n vm.expectRevert(\"OptimismPortal: invalid output root proof\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the proof is invalid due to non-existence of\n // the withdrawal.\n function test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() external {\n // modify the default test values to invalidate the proof.\n _defaultTx.data = hex\"abcd\";\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the passed transaction's withdrawalHash has\n // already been proven.\n function test_proveWithdrawalTransaction_replayProve_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: withdrawal hash has already been proven\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has\n // already been proven AND the output root has changed AND the l2BlockNumber stays the same.\n function test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`\n // inside of the `provenWithdrawal`s mapping.\n bytes32 slot;\n assembly {\n mstore(0x00, sload(_withdrawalHash.slot))\n mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in OptimismPortal\n slot := keccak256(0x00, 0x40)\n }\n\n // Store a different output root within the `provenWithdrawals` mapping without\n // touching the l2BlockNumber or timestamp.\n vm.store(address(op), slot, bytes32(0));\n\n // Warp ahead 1 second\n vm.warp(block.timestamp + 1);\n\n // Even though we have already proven this withdrawalHash, we should be allowed to re-submit\n // our proof with a changed outputRoot\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Ensure that the withdrawal was updated within the mapping\n (, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);\n assertEq(timestamp, block.timestamp);\n }\n\n // Test: proveWithdrawalTransaction succeeds and emits the WithdrawalProven event.\n function test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: finalizeWithdrawalTransaction succeeds and emits the WithdrawalFinalized event.\n function test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, false, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore + 100);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has not been proven.\n function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectRevert(\"OptimismPortal: withdrawal has not been proven yet\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if withdrawal not proven long enough ago.\n function test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Mock a call where the resulting output root is anything but the original output root. In\n // this case we just use bytes32(uint256(1)).\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(bytes32(uint256(1)), _proposedBlockNumber)\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the provenWithdrawal's timestamp is less\n // than the L2 output oracle's starting timestamp\n function test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a startingTimestamp change on the L2 Oracle\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSignature(\"startingTimestamp()\"),\n abi.encode(block.timestamp + 1)\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output root proven is not the same as the\n // output root at the time of finalization.\n function test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock an outputRoot change on the output proposal before attempting\n // to finalize the withdrawal.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n bytes32(uint256(0)),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output proposal's timestamp has\n // not passed the finalization period.\n function test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a timestamp change on the output proposal that has not passed the\n // finalization period.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(block.timestamp + 1),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\"OptimismPortal: output proposal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction fails because the target reverts,\n // and emits the WithdrawalFinalized event with success=false.\n function test_finalizeWithdrawalTransaction_targetFails_fails() external {\n uint256 bobBalanceBefore = address(bob).balance;\n vm.etch(bob, hex\"fe\"); // Contract with just the invalid opcode.\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, false);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the finalization period has not yet passed.\n function test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() external {\n // Setup the Oracle to return an output with a recent timestamp\n uint256 recentTimestamp = block.timestamp - 1000;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(recentTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has already been finalized.\n function test_finalizeWithdrawalTransaction_onReplay_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if insufficient gas is supplied.\n function test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() external {\n // This number was identified through trial and error.\n uint256 gasLimit = 150_000;\n Types.WithdrawalTransaction memory insufficientGasTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: gasLimit,\n data: hex\"\"\n });\n\n // Get updated proof inputs.\n (bytes32 stateRoot, bytes32 storageRoot, , , bytes[] memory withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(insufficientGasTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n Hashing.hashOutputRootProof(outputRootProof),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n insufficientGasTx,\n _proposedOutputIndex,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectRevert(\"OptimismPortal: insufficient gas to finalize withdrawal\");\n op.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if a sub-call attempts to finalize another\n // withdrawal.\n function test_finalizeWithdrawalTransaction_onReentrancy_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Copy and modify the default test values to attempt a reentrant call by first calling to\n // this contract's callPortalAndExpectRevert() function above.\n Types.WithdrawalTransaction memory _testTx = _defaultTx;\n _testTx.target = address(this);\n _testTx.data = abi.encodeWithSelector(this.callPortalAndExpectRevert.selector);\n\n // Get modified proof inputs.\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_testTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n // Setup the Oracle to return the outputRoot we want as well as a finalized timestamp.\n uint256 finalizedTimestamp = block.timestamp - op.FINALIZATION_PERIOD_SECONDS() - 1;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n outputRoot,\n uint128(finalizedTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(withdrawalHash, alice, address(this));\n op.proveWithdrawalTransaction(\n _testTx,\n _proposedBlockNumber,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectCall(address(this), _testTx.data);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_testTx);\n\n // Ensure that bob's balance was not changed by the reentrant call.\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n function testDiff_finalizeWithdrawalTransaction_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n // Cannot call the optimism portal\n vm.assume(_target != address(op));\n // Total ETH supply is currently about 120M ETH.\n uint256 value = bound(_value, 0, 200_000_000 ether);\n uint256 gasLimit = bound(_gasLimit, 0, 50_000_000);\n uint256 nonce = messagePasser.messageNonce();\n Types.WithdrawalTransaction memory _tx = Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: value,\n gasLimit: gasLimit,\n data: _data\n });\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_tx);\n\n Types.OutputRootProof memory proof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n\n // Ensure the values returned from ffi are correct\n assertEq(outputRoot, Hashing.hashOutputRootProof(proof));\n assertEq(withdrawalHash, Hashing.hashWithdrawal(_tx));\n\n // Mock the call to the oracle\n vm.mockCall(\n address(oracle),\n abi.encodeWithSelector(oracle.getL2Output.selector),\n abi.encode(outputRoot, 0)\n );\n\n // Start the withdrawal, it must be initiated by the _sender and the\n // correct value must be passed along\n vm.deal(_tx.sender, _tx.value);\n vm.prank(_tx.sender);\n messagePasser.initiateWithdrawal{ value: _tx.value }(_tx.target, _tx.gasLimit, _tx.data);\n\n // Ensure that the sentMessages is correct\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n\n vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1);\n op.proveWithdrawalTransaction(\n _tx,\n 100, // l2BlockNumber\n proof,\n withdrawalProof\n );\n }\n}\n\ncontract OptimismPortalUpgradeable_Test is Portal_Initializer {\n Proxy internal proxy;\n uint64 initialBlockNum;\n\n function setUp() public override {\n super.setUp();\n initialBlockNum = uint64(block.number);\n proxy = Proxy(payable(address(op)));\n }\n\n function test_params_initValuesOnProxy_succeeds() external {\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = OptimismPortal(\n payable(address(proxy))\n ).params();\n assertEq(prevBaseFee, opImpl.INITIAL_BASE_FEE());\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_initialize_cannotInitProxy_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(payable(proxy)).initialize();\n }\n\n function test_initialize_cannotInitImpl_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(opImpl).initialize();\n }\n\n function test_upgradeToAndCall_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(op), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(op), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(op)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n" - }, - "contracts/test/Proxy.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract SimpleStorage {\n mapping(uint256 => uint256) internal store;\n\n function get(uint256 key) external payable returns (uint256) {\n return store[key];\n }\n\n function set(uint256 key, uint256 value) external payable {\n store[key] = value;\n }\n}\n\ncontract Clasher {\n function upgradeTo(address) external pure {\n revert(\"upgradeTo\");\n }\n}\n\ncontract Proxy_Test is Test {\n event Upgraded(address indexed implementation);\n event AdminChanged(address previousAdmin, address newAdmin);\n\n address alice = address(64);\n\n bytes32 internal constant IMPLEMENTATION_KEY =\n bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1);\n\n bytes32 internal constant OWNER_KEY = bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1);\n\n Proxy proxy;\n SimpleStorage simpleStorage;\n\n function setUp() external {\n // Deploy a proxy and simple storage contract as\n // the implementation\n proxy = new Proxy(alice);\n simpleStorage = new SimpleStorage();\n\n vm.prank(alice);\n proxy.upgradeTo(address(simpleStorage));\n }\n\n function test_implementationKey_succeeds() external {\n // The hardcoded implementation key should be correct\n vm.prank(alice);\n proxy.upgradeTo(address(6));\n\n bytes32 key = vm.load(address(proxy), IMPLEMENTATION_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(6));\n }\n\n function test_ownerKey_succeeds() external {\n // The hardcoded owner key should be correct\n vm.prank(alice);\n proxy.changeAdmin(address(6));\n\n bytes32 key = vm.load(address(proxy), OWNER_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(address(6));\n address owner = proxy.admin();\n assertEq(owner, address(6));\n }\n\n function test_proxyCallToImp_notAdmin_succeeds() external {\n // The implementation does not have a `upgradeTo`\n // method, calling `upgradeTo` not as the owner\n // should revert.\n vm.expectRevert();\n proxy.upgradeTo(address(64));\n\n // Call `upgradeTo` as the owner, it should succeed\n // and emit the `Upgraded` event.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(64));\n vm.prank(alice);\n proxy.upgradeTo(address(64));\n\n // Get the implementation as the owner\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(64));\n }\n\n function test_ownerProxyCall_notAdmin_succeeds() external {\n // Calling `changeAdmin` not as the owner should revert\n // as the implementation does not have a `changeAdmin` method.\n vm.expectRevert();\n proxy.changeAdmin(address(1));\n\n // Call `changeAdmin` as the owner, it should succeed\n // and emit the `AdminChanged` event.\n vm.expectEmit(true, true, true, true);\n emit AdminChanged(alice, address(1));\n vm.prank(alice);\n proxy.changeAdmin(address(1));\n\n // Calling `admin` not as the owner should\n // revert as the implementation does not have\n // a `admin` method.\n vm.expectRevert();\n proxy.admin();\n\n // Calling `admin` as the owner should work.\n vm.prank(address(1));\n address owner = proxy.admin();\n assertEq(owner, address(1));\n }\n\n function test_delegatesToImpl_succeeds() external {\n // Call the storage setter on the proxy\n SimpleStorage(address(proxy)).set(1, 1);\n\n // The key should not be set in the implementation\n uint256 result = simpleStorage.get(1);\n assertEq(result, 0);\n {\n // The key should be set in the proxy\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n\n {\n // The owner should be able to call through the proxy\n // when there is not a function selector crash\n vm.prank(alice);\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n }\n\n function test_upgradeToAndCall_succeeds() external {\n {\n // There should be nothing in the current proxy storage\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 0);\n }\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(simpleStorage));\n vm.prank(alice);\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The call should have impacted the state\n uint256 result = SimpleStorage(address(proxy)).get(1);\n assertEq(result, 1);\n }\n\n function test_upgradeToAndCall_functionDoesNotExist_reverts() external {\n // Get the current implementation address\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call. This reverts because the calldata doesn't\n // match a function on the implementation.\n vm.expectRevert(\"Proxy: delegatecall to new implementation contract failed\");\n vm.prank(alice);\n proxy.upgradeToAndCall(address(simpleStorage), hex\"\");\n\n // The implementation address should have not\n // updated because the call to `upgradeToAndCall`\n // reverted.\n vm.prank(alice);\n address postImpl = proxy.implementation();\n assertEq(impl, postImpl);\n\n // The attempt to `upgradeToAndCall`\n // should revert when it is not called by the owner.\n vm.expectRevert();\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n }\n\n function test_upgradeToAndCall_isPayable_succeeds() external {\n // Give alice some funds\n vm.deal(alice, 1 ether);\n // Set the implementation and call and send\n // value.\n vm.prank(alice);\n proxy.upgradeToAndCall{ value: 1 ether }(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The implementation address should be correct\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // The proxy should have a balance\n assertEq(address(proxy).balance, 1 ether);\n }\n\n function test_upgradeTo_clashingFunctionSignatures_succeeds() external {\n // Clasher has a clashing function with the proxy.\n Clasher clasher = new Clasher();\n\n // Set the clasher as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(clasher));\n\n {\n // Assert that the implementation was set properly.\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(clasher));\n }\n\n // Call the clashing function on the proxy\n // not as the owner so that the call passes through.\n // The implementation will revert so we can be\n // sure that the call passed through.\n vm.expectRevert(bytes(\"upgradeTo\"));\n proxy.upgradeTo(address(0));\n\n {\n // Now call the clashing function as the owner\n // and be sure that it doesn't pass through to\n // the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(0));\n }\n }\n\n // Allow for `eth_call` to call proxy methods\n // by setting \"from\" to `address(0)`.\n function test_implementation_zeroAddressCaller_succeeds() external {\n vm.prank(address(0));\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n }\n\n function test_implementation_isZeroAddress_reverts() external {\n // Set `address(0)` as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n\n (bool success, bytes memory returndata) = address(proxy).call(hex\"\");\n assertEq(success, false);\n\n bytes memory err = abi.encodeWithSignature(\n \"Error(string)\",\n \"Proxy: implementation not initialized\"\n );\n\n assertEq(returndata, err);\n }\n}\n" - }, - "contracts/test/ProxyAdmin.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { SimpleStorage } from \"./Proxy.t.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\n\ncontract ProxyAdmin_Test is Test {\n address alice = address(64);\n\n Proxy proxy;\n L1ChugSplashProxy chugsplash;\n ResolvedDelegateProxy resolved;\n\n AddressManager addressManager;\n\n ProxyAdmin admin;\n\n SimpleStorage implementation;\n\n function setUp() external {\n // Deploy the proxy admin\n admin = new ProxyAdmin(alice);\n // Deploy the standard proxy\n proxy = new Proxy(address(admin));\n\n // Deploy the legacy L1ChugSplashProxy with the admin as the owner\n chugsplash = new L1ChugSplashProxy(address(admin));\n\n // Deploy the legacy AddressManager\n addressManager = new AddressManager();\n // The proxy admin must be the new owner of the address manager\n addressManager.transferOwnership(address(admin));\n // Deploy a legacy ResolvedDelegateProxy with the name `a`.\n // Whatever `a` is set to in AddressManager will be the address\n // that is used for the implementation.\n resolved = new ResolvedDelegateProxy(addressManager, \"a\");\n\n // Impersonate alice for setting up the admin.\n vm.startPrank(alice);\n // Set the address of the address manager in the admin so that it\n // can resolve the implementation address of legacy\n // ResolvedDelegateProxy based proxies.\n admin.setAddressManager(addressManager);\n // Set the reverse lookup of the ResolvedDelegateProxy\n // proxy\n admin.setImplementationName(address(resolved), \"a\");\n\n // Set the proxy types\n admin.setProxyType(address(proxy), ProxyAdmin.ProxyType.ERC1967);\n admin.setProxyType(address(chugsplash), ProxyAdmin.ProxyType.CHUGSPLASH);\n admin.setProxyType(address(resolved), ProxyAdmin.ProxyType.RESOLVED);\n vm.stopPrank();\n\n implementation = new SimpleStorage();\n }\n\n function test_setImplementationName_succeeds() external {\n vm.prank(alice);\n admin.setImplementationName(address(1), \"foo\");\n assertEq(admin.implementationName(address(1)), \"foo\");\n }\n\n function test_setAddressManager_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setAddressManager(AddressManager((address(0))));\n }\n\n function test_setImplementationName_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setImplementationName(address(0), \"foo\");\n }\n\n function test_setProxyType_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setProxyType(address(0), ProxyAdmin.ProxyType.CHUGSPLASH);\n }\n\n function test_owner_succeeds() external {\n assertEq(admin.owner(), alice);\n }\n\n function test_proxyType_succeeds() external {\n assertEq(uint256(admin.proxyType(address(proxy))), uint256(ProxyAdmin.ProxyType.ERC1967));\n assertEq(\n uint256(admin.proxyType(address(chugsplash))),\n uint256(ProxyAdmin.ProxyType.CHUGSPLASH)\n );\n assertEq(\n uint256(admin.proxyType(address(resolved))),\n uint256(ProxyAdmin.ProxyType.RESOLVED)\n );\n }\n\n function test_erc1967GetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(proxy));\n }\n\n function test_chugsplashGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(resolved));\n }\n\n function getProxyImplementation(address payable _proxy) internal {\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(0));\n }\n\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n }\n\n function test_erc1967GetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(resolved));\n }\n\n function getProxyAdmin(address payable _proxy) internal {\n address owner = admin.getProxyAdmin(_proxy);\n assertEq(owner, address(admin));\n }\n\n function test_erc1967ChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(resolved));\n }\n\n function changeProxyAdmin(address payable _proxy) internal {\n ProxyAdmin.ProxyType proxyType = admin.proxyType(address(_proxy));\n\n vm.prank(alice);\n admin.changeProxyAdmin(_proxy, address(128));\n\n // The proxy is no longer the admin and can\n // no longer call the proxy interface except for\n // the ResolvedDelegate type on which anybody can\n // call the admin interface.\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n vm.expectRevert(\"Proxy: implementation not initialized\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n vm.expectRevert(\"L1ChugSplashProxy: implementation is not set yet\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n // Just an empty block to show that all cases are covered\n } else {\n vm.expectRevert(\"ProxyAdmin: unknown proxy type\");\n }\n\n // Call the proxy contract directly to get the admin.\n // Different proxy types have different interfaces.\n vm.prank(address(128));\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n assertEq(Proxy(payable(_proxy)).admin(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n assertEq(L1ChugSplashProxy(payable(_proxy)).getOwner(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n assertEq(addressManager.owner(), address(128));\n } else {\n assert(false);\n }\n }\n\n function test_erc1967Upgrade_succeeds() external {\n upgrade(payable(proxy));\n }\n\n function test_chugsplashUpgrade_succeeds() external {\n upgrade(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgrade_succeeds() external {\n upgrade(payable(resolved));\n }\n\n function upgrade(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n\n function test_erc1967UpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(proxy));\n }\n\n function test_chugsplashUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(resolved));\n }\n\n function upgradeAndCall(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgradeAndCall(\n _proxy,\n address(implementation),\n abi.encodeWithSelector(SimpleStorage.set.selector, 1, 1)\n );\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n\n uint256 got = SimpleStorage(address(_proxy)).get(1);\n assertEq(got, 1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.changeProxyAdmin(payable(proxy), address(0));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgrade(payable(proxy), address(implementation));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgradeAndCall(payable(proxy), address(implementation), hex\"\");\n }\n\n function test_isUpgrading_succeeds() external {\n assertEq(false, admin.isUpgrading());\n\n vm.prank(alice);\n admin.setUpgrading(true);\n assertEq(true, admin.isUpgrading());\n }\n}\n" - }, - "contracts/test/RLP.t.sol": { - "content": "// SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\n/**\n * @title LibRLP\n * @notice Via https://github.com/Rari-Capital/solmate/issues/207.\n */\nlibrary LibRLP {\n using Bytes32AddressLib for bytes32;\n\n function computeAddress(address deployer, uint256 nonce) internal pure returns (address) {\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80)))\n .fromLast20Bytes();\n if (nonce <= 0x7f)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce)))\n .fromLast20Bytes();\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= type(uint8).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd7),\n bytes1(0x94),\n deployer,\n bytes1(0x81),\n uint8(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint16).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd8),\n bytes1(0x94),\n deployer,\n bytes1(0x82),\n uint16(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint24).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd9),\n bytes1(0x94),\n deployer,\n bytes1(0x83),\n uint24(nonce)\n )\n ).fromLast20Bytes();\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return\n keccak256(\n abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))\n ).fromLast20Bytes();\n }\n}\n" - }, - "contracts/test/RLPReader.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { RLPReader } from \"../libraries/rlp/RLPReader.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { stdError } from \"forge-std/Test.sol\";\n\ncontract RLPReader_Test is CommonTest {\n function test_readBytes_bytestring00_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"00\"), hex\"00\");\n }\n\n function test_readBytes_bytestring01_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"01\"), hex\"01\");\n }\n\n function test_readBytes_bytestring7f_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"7f\"), hex\"7f\");\n }\n\n function test_readBytes_revertListItem_reverts() external {\n vm.expectRevert(\"RLPReader: decoded item type for bytes is not a data item\");\n RLPReader.readBytes(hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_readBytes_invalidStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n RLPReader.readBytes(hex\"b9\");\n }\n\n function test_readBytes_invalidListLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n RLPReader.readBytes(hex\"ff\");\n }\n\n function test_readBytes_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: bytes value contains an invalid remainder\");\n RLPReader.readBytes(hex\"800a\");\n }\n\n function test_readBytes_invalidPrefix_reverts() external {\n vm.expectRevert(\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n RLPReader.readBytes(hex\"810a\");\n }\n\n function test_readList_empty_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c0\");\n assertEq(list.length, 0);\n }\n\n function test_readList_multiList_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c6827a77c10401\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"827a77\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c104\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"01\");\n }\n\n function test_readList_shortListMax1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n\n assertEq(list.length, 11);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[4]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[5]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[6]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[7]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[8]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[9]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[10]), hex\"8471776572\");\n }\n\n function test_readList_longList1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n\n assertEq(list.length, 4);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"cf84617364668471776572847a786376\");\n }\n\n function test_readList_longList2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n assertEq(list.length, 32);\n\n for (uint256 i = 0; i < 32; i++) {\n assertEq(RLPReader.readRawBytes(list[i]), hex\"cf84617364668471776572847a786376\");\n }\n }\n\n function test_readList_listLongerThan32Elements_reverts() external {\n vm.expectRevert(stdError.indexOOBError);\n RLPReader.readList(\n hex\"e1454545454545454545454545454545454545454545454545454545454545454545\"\n );\n }\n\n function test_readList_listOfLists_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c4c2c0c0c0\");\n assertEq(list.length, 2);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c2c0c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c0\");\n }\n\n function test_readList_listOfLists2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c7c0c1c0c3c0c1c0\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c1c0\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"c3c0c1c0\");\n }\n\n function test_readList_dictTest1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n assertEq(list.length, 4);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"ca846b6579318476616c31\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"ca846b6579328476616c32\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"ca846b6579338476616c33\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"ca846b6579348476616c34\");\n }\n\n function test_readList_invalidShortList_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efdebd\");\n }\n\n function test_readList_longStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efb83600\");\n }\n\n function test_readList_notLongEnough_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(\n hex\"efdebdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n );\n }\n\n function test_readList_int32Overflow_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"bf0f000000000000021111\");\n }\n\n function test_readList_int32Overflow2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ff0f000000000000021111\");\n }\n\n function test_readList_incorrectLengthInArray_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b9002100dc2b275d0f74e8a53e6f4ec61b27f24278820be3f82ea2110e582081b0565df0\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b90040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(hex\"b800\");\n }\n\n function test_readList_leadingZerosInLongLengthList1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must not have any leading zeros (long list)\");\n RLPReader.readList(\n hex\"fb00000040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_nonOptimalLongLengthArray1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b81000112233445566778899aabbccddeeff\");\n }\n\n function test_readList_nonOptimalLongLengthArray2_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b801ff\");\n }\n\n function test_readList_invalidValue_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n RLPReader.readList(hex\"91\");\n }\n\n function test_readList_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n RLPReader.readList(hex\"c000\");\n }\n\n function test_readList_notEnoughContentForString1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"ba010000aabbccddeeff\");\n }\n\n function test_readList_notEnoughContentForString2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"b840ffeeddccbbaa99887766554433221100\");\n }\n\n function test_readList_notEnoughContentForList1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"f90180\");\n }\n\n function test_readList_notEnoughContentForList2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ffffffffffffffffff0001020304050607\");\n }\n\n function test_readList_longStringLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b80100\");\n }\n\n function test_readList_longListLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long list)\");\n RLPReader.readList(hex\"f80100\");\n }\n}\n" - }, - "contracts/test/RLPWriter.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { RLPWriter } from \"../libraries/rlp/RLPWriter.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\n\ncontract RLPWriter_Test is CommonTest {\n function test_writeString_empty_succeeds() external {\n assertEq(RLPWriter.writeString(\"\"), hex\"80\");\n }\n\n function test_writeString_bytestring00_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0000\"), hex\"00\");\n }\n\n function test_writeString_bytestring01_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0001\"), hex\"01\");\n }\n\n function test_writeString_bytestring7f_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u007F\"), hex\"7f\");\n }\n\n function test_writeString_shortstring_succeeds() external {\n assertEq(RLPWriter.writeString(\"dog\"), hex\"83646f67\");\n }\n\n function test_writeString_shortstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing eli\"),\n hex\"b74c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c69\"\n );\n }\n\n function test_writeString_longstring_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing elit\"),\n hex\"b8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974\"\n );\n }\n\n function test_writeString_longstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\n \"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\"\n ),\n hex\"b904004c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20437572616269747572206d6175726973206d61676e612c20737573636970697420736564207665686963756c61206e6f6e2c20696163756c697320666175636962757320746f72746f722e2050726f696e20737573636970697420756c74726963696573206d616c6573756164612e204475697320746f72746f7220656c69742c2064696374756d2071756973207472697374697175652065752c20756c7472696365732061742072697375732e204d6f72626920612065737420696d70657264696574206d6920756c6c616d636f7270657220616c6971756574207375736369706974206e6563206c6f72656d2e2041656e65616e2071756973206c656f206d6f6c6c69732c2076756c70757461746520656c6974207661726975732c20636f6e73657175617420656e696d2e204e756c6c6120756c74726963657320747572706973206a7573746f2c20657420706f73756572652075726e6120636f6e7365637465747572206e65632e2050726f696e206e6f6e20636f6e76616c6c6973206d657475732e20446f6e65632074656d706f7220697073756d20696e206d617572697320636f6e67756520736f6c6c696369747564696e2e20566573746962756c756d20616e746520697073756d207072696d697320696e206661756369627573206f726369206c756374757320657420756c74726963657320706f737565726520637562696c69612043757261653b2053757370656e646973736520636f6e76616c6c69732073656d2076656c206d617373612066617563696275732c2065676574206c6163696e6961206c616375732074656d706f722e204e756c6c61207175697320756c747269636965732070757275732e2050726f696e20617563746f722072686f6e637573206e69626820636f6e64696d656e74756d206d6f6c6c69732e20416c697175616d20636f6e73657175617420656e696d206174206d65747573206c75637475732c206120656c656966656e6420707572757320656765737461732e20437572616269747572206174206e696268206d657475732e204e616d20626962656e64756d2c206e6571756520617420617563746f72207472697374697175652c206c6f72656d206c696265726f20616c697175657420617263752c206e6f6e20696e74657264756d2074656c6c7573206c65637475732073697420616d65742065726f732e20437261732072686f6e6375732c206d65747573206163206f726e617265206375727375732c20646f6c6f72206a7573746f20756c747269636573206d657475732c20617420756c6c616d636f7270657220766f6c7574706174\"\n );\n }\n\n function test_writeUint_zero_succeeds() external {\n assertEq(RLPWriter.writeUint(0x0), hex\"80\");\n }\n\n function test_writeUint_smallint_succeeds() external {\n assertEq(RLPWriter.writeUint(1), hex\"01\");\n }\n\n function test_writeUint_smallint2_succeeds() external {\n assertEq(RLPWriter.writeUint(16), hex\"10\");\n }\n\n function test_writeUint_smallint3_succeeds() external {\n assertEq(RLPWriter.writeUint(79), hex\"4f\");\n }\n\n function test_writeUint_smallint4_succeeds() external {\n assertEq(RLPWriter.writeUint(127), hex\"7f\");\n }\n\n function test_writeUint_mediumint_succeeds() external {\n assertEq(RLPWriter.writeUint(128), hex\"8180\");\n }\n\n function test_writeUint_mediumint2_succeeds() external {\n assertEq(RLPWriter.writeUint(1000), hex\"8203e8\");\n }\n\n function test_writeUint_mediumint3_succeeds() external {\n assertEq(RLPWriter.writeUint(100000), hex\"830186a0\");\n }\n\n function test_writeList_empty_succeeds() external {\n assertEq(RLPWriter.writeList(new bytes[](0)), hex\"c0\");\n }\n\n function test_writeList_stringList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeString(\"dog\");\n list[1] = RLPWriter.writeString(\"god\");\n list[2] = RLPWriter.writeString(\"cat\");\n\n assertEq(RLPWriter.writeList(list), hex\"cc83646f6783676f6483636174\");\n }\n\n function test_writeList_multiList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeUint(4);\n\n list[0] = RLPWriter.writeString(\"zw\");\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeUint(1);\n\n assertEq(RLPWriter.writeList(list), hex\"c6827a77c10401\");\n }\n\n function test_writeList_shortListMax1_succeeds() external {\n bytes[] memory list = new bytes[](11);\n list[0] = RLPWriter.writeString(\"asdf\");\n list[1] = RLPWriter.writeString(\"qwer\");\n list[2] = RLPWriter.writeString(\"zxcv\");\n list[3] = RLPWriter.writeString(\"asdf\");\n list[4] = RLPWriter.writeString(\"qwer\");\n list[5] = RLPWriter.writeString(\"zxcv\");\n list[6] = RLPWriter.writeString(\"asdf\");\n list[7] = RLPWriter.writeString(\"qwer\");\n list[8] = RLPWriter.writeString(\"zxcv\");\n list[9] = RLPWriter.writeString(\"asdf\");\n list[10] = RLPWriter.writeString(\"qwer\");\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n }\n\n function test_writeList_longlist1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list2);\n list[3] = RLPWriter.writeList(list2);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_longlist2_succeeds() external {\n bytes[] memory list = new bytes[](32);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n for (uint256 i = 0; i < 32; i++) {\n list[i] = RLPWriter.writeList(list2);\n }\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_listoflists_succeeds() external {\n // [ [ [], [] ], [] ]\n bytes[] memory list = new bytes[](2);\n bytes[] memory list2 = new bytes[](2);\n\n list2[0] = RLPWriter.writeList(new bytes[](0));\n list2[1] = RLPWriter.writeList(new bytes[](0));\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(new bytes[](0));\n\n assertEq(RLPWriter.writeList(list), hex\"c4c2c0c0c0\");\n }\n\n function test_writeList_listoflists2_succeeds() external {\n // [ [], [[]], [ [], [[]] ] ]\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeList(new bytes[](0));\n\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeList(new bytes[](0));\n\n list[1] = RLPWriter.writeList(list2);\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeList(new bytes[](0));\n list3[1] = RLPWriter.writeList(list2);\n\n list[2] = RLPWriter.writeList(list3);\n\n assertEq(RLPWriter.writeList(list), hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_writeList_dictTest1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n\n bytes[] memory list1 = new bytes[](2);\n list1[0] = RLPWriter.writeString(\"key1\");\n list1[1] = RLPWriter.writeString(\"val1\");\n\n bytes[] memory list2 = new bytes[](2);\n list2[0] = RLPWriter.writeString(\"key2\");\n list2[1] = RLPWriter.writeString(\"val2\");\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeString(\"key3\");\n list3[1] = RLPWriter.writeString(\"val3\");\n\n bytes[] memory list4 = new bytes[](2);\n list4[0] = RLPWriter.writeString(\"key4\");\n list4[1] = RLPWriter.writeString(\"val4\");\n\n list[0] = RLPWriter.writeList(list1);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list3);\n list[3] = RLPWriter.writeList(list4);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n }\n}\n" - }, - "contracts/test/ResourceMetering.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\n\ncontract MeterUser is ResourceMetering {\n constructor() {\n initialize();\n }\n\n function initialize() public initializer {\n __ResourceMetering_init();\n }\n\n function use(uint64 _amount) public metered(_amount) {}\n}\n\ncontract ResourceMetering_Test is CommonTest {\n MeterUser internal meter;\n uint64 initialBlockNum;\n\n function setUp() external {\n _setUp();\n meter = new MeterUser();\n initialBlockNum = uint64(block.number);\n }\n\n function test_meter_initialResourceParams_succeeds() external {\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, meter.INITIAL_BASE_FEE());\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_updateParamsNoChange_succeeds() external {\n meter.use(0); // equivalent to just updating the base fee and block number\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n meter.use(0);\n (uint128 postBaseFee, uint64 postBoughtGas, uint64 postBlockNum) = meter.params();\n\n assertEq(postBaseFee, prevBaseFee);\n assertEq(postBoughtGas, prevBoughtGas);\n assertEq(postBlockNum, prevBlockNum);\n }\n\n function test_meter_updateOneEmptyBlock_succeeds() external {\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n // Base fee decreases by 12.5%\n assertEq(prevBaseFee, 875000000);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 1);\n }\n\n function test_meter_updateTwoEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 2);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 765624999);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 2);\n }\n\n function test_meter_updateTenEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 10);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 263075576);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 10);\n }\n\n function test_meter_updateNoGasDelta_succeeds() external {\n uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT()));\n meter.use(target);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1000000000);\n assertEq(prevBoughtGas, target);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_useMax_succeeds() external {\n uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT()));\n uint64 elasticity = uint64(uint256(meter.ELASTICITY_MULTIPLIER()));\n meter.use(target * elasticity);\n\n (, uint64 prevBoughtGas, ) = meter.params();\n assertEq(prevBoughtGas, target * elasticity);\n\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 postBaseFee, , ) = meter.params();\n // Base fee increases by 1/8 the difference\n assertEq(postBaseFee, 1375000000);\n }\n\n function test_meter_useMoreThanMax_reverts() external {\n uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT()));\n uint64 elasticity = uint64(uint256(meter.ELASTICITY_MULTIPLIER()));\n vm.expectRevert(\"ResourceMetering: cannot buy more gas than available gas limit\");\n meter.use(target * elasticity + 1);\n }\n}\n" - }, - "contracts/test/SafeCall.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\n\ncontract SafeCall_Test is CommonTest {\n function testFuzz_safeCall_succeeds(\n address from,\n address to,\n uint256 gas,\n uint64 value,\n bytes memory data\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles\n vm.assume(uint160(to) > 10);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n // don't send funds to self\n vm.assume(from != to);\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n vm.expectCall(to, value, data);\n\n vm.prank(from);\n bool success = SafeCall.call(to, gas, value, data);\n\n assertEq(success, true, \"call not successful\");\n assertEq(to.balance, value, \"to balance received\");\n assertEq(from.balance, 0, \"from balance not drained\");\n }\n}\n" - }, - "contracts/test/Semver.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\n\n/**\n * @notice Test the Semver contract that is used for semantic versioning\n * of various contracts.\n */\ncontract Semver_Test is CommonTest {\n /**\n * @notice Global semver contract deployed in setUp. This is used in\n * the test cases.\n */\n Semver semver;\n\n /**\n * @notice Deploy a Semver contract\n */\n function setUp() external {\n semver = new Semver(7, 8, 0);\n }\n\n /**\n * @notice Test the version getter\n */\n function test_version_succeeds() external {\n assertEq(semver.version(), \"7.8.0\");\n }\n\n /**\n * @notice Since the versions are all immutable, they should\n * be able to be accessed from behind a proxy without needing\n * to initialize the contract.\n */\n function test_behindProxy_succeeds() external {\n Proxy proxy = new Proxy(alice);\n vm.prank(alice);\n proxy.upgradeTo(address(semver));\n\n assertEq(Semver(address(proxy)).version(), \"7.8.0\");\n }\n}\n" - }, - "contracts/test/SequencerFeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { SequencerFeeVault } from \"../L2/SequencerFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract SequencerFeeVault_Test is Bridge_Initializer {\n SequencerFeeVault vault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET));\n address constant recipient = address(256);\n\n event Withdrawal(uint256 value, address to, address from);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.SEQUENCER_FEE_WALLET, address(new SequencerFeeVault(recipient)).code);\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(vault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n\n function test_constructor_succeeds() external {\n assertEq(vault.l1FeeWallet(), recipient);\n }\n\n function test_receive_succeeds() external {\n assertEq(address(vault).balance, 0);\n\n vm.prank(alice);\n (bool success, ) = address(vault).call{ value: 100 }(hex\"\");\n\n assertEq(success, true);\n assertEq(address(vault).balance, 100);\n }\n\n function test_withdraw_notEnough_reverts() external {\n assert(address(vault).balance < vault.MIN_WITHDRAWAL_AMOUNT());\n\n vm.expectRevert(\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n vault.withdraw();\n }\n\n function test_withdraw_succeeds() external {\n uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1;\n vm.deal(address(vault), amount);\n\n // No ether has been withdrawn yet\n assertEq(vault.totalProcessed(), 0);\n\n vm.expectEmit(true, true, true, true);\n emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this));\n\n // The entire vault's balance is withdrawn\n vm.expectCall(\n Predeploys.L2_STANDARD_BRIDGE,\n address(vault).balance,\n abi.encodeWithSelector(\n StandardBridge.bridgeETHTo.selector,\n vault.l1FeeWallet(),\n 20000,\n bytes(\"\")\n )\n );\n\n vault.withdraw();\n\n // The withdrawal was successful\n assertEq(vault.totalProcessed(), amount);\n }\n}\n" - }, - "contracts/test/SystemConfig.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\n\ncontract SystemConfig_Init is CommonTest {\n SystemConfig sysConf;\n\n function setUp() external {\n sysConf = new SystemConfig({\n _owner: alice,\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 9_000_000,\n _unsafeBlockSigner: address(1)\n });\n }\n}\n\ncontract SystemConfig_Initialize_TestFail is CommonTest {\n function test_initialize_lowGasLimit_reverts() external {\n vm.expectRevert(\"SystemConfig: gas limit too low\");\n\n // The minimum gas limit defined in SystemConfig:\n uint64 MINIMUM_GAS_LIMIT = 8_000_000;\n new SystemConfig({\n _owner: alice,\n _overhead: 0,\n _scalar: 0,\n _batcherHash: bytes32(hex\"\"),\n _gasLimit: MINIMUM_GAS_LIMIT - 1,\n _unsafeBlockSigner: address(1)\n });\n }\n}\n\ncontract SystemConfig_Setters_TestFail is SystemConfig_Init {\n function test_setBatcherHash_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setBatcherHash(bytes32(hex\"\"));\n }\n\n function test_setGasConfig_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasConfig(0, 0);\n }\n\n function test_setGasLimit_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasLimit(0);\n }\n\n function test_setUnsafeBlockSigner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setUnsafeBlockSigner(address(0x20));\n }\n}\n\ncontract SystemConfig_Setters_Test is SystemConfig_Init {\n event ConfigUpdate(\n uint256 indexed version,\n SystemConfig.UpdateType indexed updateType,\n bytes data\n );\n\n function testFuzz_setBatcherHash_succeeds(bytes32 newBatcherHash) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash));\n\n vm.prank(sysConf.owner());\n sysConf.setBatcherHash(newBatcherHash);\n assertEq(sysConf.batcherHash(), newBatcherHash);\n }\n\n function testFuzz_setGasConfig_succeeds(uint256 newOverhead, uint256 newScalar) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.GAS_CONFIG,\n abi.encode(newOverhead, newScalar)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setGasConfig(newOverhead, newScalar);\n assertEq(sysConf.overhead(), newOverhead);\n assertEq(sysConf.scalar(), newScalar);\n }\n\n function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external {\n uint64 minimumGasLimit = sysConf.MINIMUM_GAS_LIMIT();\n newGasLimit = uint64(\n bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(type(uint64).max))\n );\n\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit));\n\n vm.prank(sysConf.owner());\n sysConf.setGasLimit(newGasLimit);\n assertEq(sysConf.gasLimit(), newGasLimit);\n }\n\n function testFuzz_setUnsafeBlockSigner_succeeds(address newUnsafeSigner) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER,\n abi.encode(newUnsafeSigner)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setUnsafeBlockSigner(newUnsafeSigner);\n assertEq(sysConf.unsafeBlockSigner(), newUnsafeSigner);\n }\n}\n" - }, - "contracts/test/invariants/CrossDomainMessenger.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { InvariantTest } from \"forge-std/InvariantTest.sol\";\nimport { StdUtils } from \"forge-std/StdUtils.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport { OptimismPortal } from \"../../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../../L1/L1CrossDomainMessenger.sol\";\nimport { Messenger_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\nimport { Predeploys } from \"../../libraries/Predeploys.sol\";\nimport { Encoding } from \"../../libraries/Encoding.sol\";\nimport { Hashing } from \"../../libraries/Hashing.sol\";\n\ncontract RelayActor is StdUtils {\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n uint256 public numHashes;\n bytes32[] public hashes;\n bool public reverted = false;\n\n OptimismPortal op;\n L1CrossDomainMessenger xdm;\n Vm vm;\n\n constructor(\n OptimismPortal _op,\n L1CrossDomainMessenger _xdm,\n Vm _vm\n ) {\n op = _op;\n xdm = _xdm;\n vm = _vm;\n }\n\n /**\n * Relays a message to the `L1CrossDomainMessenger` with a random `version`, `_minGasLimit`\n * and `_message`.\n */\n function relay(\n uint16 _version,\n uint32 _minGasLimit,\n bytes memory _message\n ) external {\n address target = address(0x04); // ID precompile\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Restrict `_minGasLimit` to a number in the range of the block gas limit.\n _minGasLimit = uint32(bound(_minGasLimit, 0, block.gaslimit));\n\n // Restrict version to the range of [0, 1]\n _version = _version % 2;\n\n // Compute the cross domain message hash and store it in `hashes`.\n // The `relayMessage` function will always encode the message as a version 1\n // message after checking that the V0 hash has not already been relayed.\n bytes32 _hash = Hashing.hashCrossDomainMessageV1(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n 0, // value\n _minGasLimit,\n _message\n );\n\n // Act as the optimism portal and call `relayMessage` on the `L1CrossDomainMessenger` with\n // the outer min gas limit.\n vm.startPrank(address(op));\n vm.expectCall(target, _message);\n try\n xdm.relayMessage{ gas: xdm.baseGas(_message, _minGasLimit) }(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n 0, // value\n _minGasLimit,\n _message\n )\n {} catch {\n // If any of these calls revert, set `reverted` to true to fail the invariant test.\n // NOTE: This is to get around forge's invariant fuzzer ignoring reverted calls\n // to this function.\n reverted = true;\n }\n vm.stopPrank();\n\n hashes.push(_hash);\n numHashes += 1;\n }\n}\n\ncontract XDM_MinGasLimits is Messenger_Initializer, InvariantTest {\n RelayActor actor;\n\n function setUp() public override {\n // Set up the `L1CrossDomainMessenger` and `OptimismPortal` contracts.\n super.setUp();\n\n // Deploy a relay actor\n actor = new RelayActor(op, L1Messenger, vm);\n\n // Target the `RelayActor` contract\n targetContract(address(actor));\n\n // Target the actor's `relay` function\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = actor.relay.selector;\n targetSelector(FuzzSelector({ addr: address(actor), selectors: selectors }));\n }\n\n /**\n * @custom:invariant A call to `relayMessage` should never revert if at least the proper minimum\n * gas limits are supplied.\n *\n * There are two minimum gas limits here:\n *\n * - The outer min gas limit is for the call from the `OptimismPortal` to the\n * `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function\n * with the `message` and inner limit.\n *\n * - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target\n * contract.\n */\n function invariant_minGasLimits() public {\n uint256 length = actor.numHashes();\n for (uint256 i = 0; i < length; ++i) {\n bytes32 hash = actor.hashes(i);\n // the message hash is in the successfulMessages mapping\n assertTrue(L1Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertFalse(L1Messenger.failedMessages(hash));\n }\n assertFalse(actor.reverted());\n }\n}\n" - }, - "contracts/test/invariants/L2OutputOracle.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { InvariantTest } from \"forge-std/InvariantTest.sol\";\nimport { L2OutputOracle_Initializer } from \"../CommonTest.t.sol\";\n\ncontract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is\n InvariantTest,\n L2OutputOracle_Initializer\n{\n function setUp() public override {\n super.setUp();\n\n // Set the target contract to the oracle proxy\n targetContract(address(oracle));\n // Set the target sender to the proposer\n targetSender(address(proposer));\n // Set the target selector for `proposeL2Output`\n // `proposeL2Output` is the only function we care about, as it is the only function\n // that can modify the `l2Outputs` array in the oracle.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = oracle.proposeL2Output.selector;\n FuzzSelector memory selector = FuzzSelector({\n addr: address(oracle),\n selectors: selectors\n });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The block number of the output root proposals should monotonically\n * increase.\n *\n * When a new output is submitted, it should never be allowed to correspond to a block\n * number that is less than the current output.\n */\n function invariant_monotonicBlockNumIncrease() external {\n // Assert that the block number of proposals must monotonically increase.\n assertTrue(oracle.nextBlockNumber() >= oracle.latestBlockNumber());\n }\n}\n" - }, - "contracts/test/invariants/OptimismPortal.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { InvariantTest } from \"forge-std/InvariantTest.sol\";\nimport { Portal_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\n\ncontract OptimismPortal_Invariant_Harness is Portal_Initializer, InvariantTest {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n function setUp() public virtual override {\n super.setUp();\n\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n op.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n}\n\ncontract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the finalization\n * period has not elapsed.\n *\n * A withdrawal that has been proven should not be able to be finalized until after\n * the finalization period has elapsed.\n */\n function invariant_cannotFinalizeBeforePeriodHasPassed() external {\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Finalize the withdrawal transaction.\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal\n * has already been finalized.\n *\n * Ensures that there is no chain of calls that can be made that allows a withdrawal\n * to be finalized twice.\n */\n function invariant_cannotFinalizeTwice() external {\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant A withdrawal should **always** be able to be finalized\n * `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.\n *\n * This invariant asserts that there is no chain of calls that can be made that\n * will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS`\n * after it was successfully proven.\n */\n function invariant_canAlwaysFinalize() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assertEq(address(bob).balance, bobBalanceBefore + _defaultTx.value);\n }\n}\n" - }, - "contracts/test/invariants/SystemConfig.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { InvariantTest } from \"forge-std/InvariantTest.sol\";\nimport { StdAssertions } from \"forge-std/StdAssertions.sol\";\nimport { SystemConfig } from \"../../L1/SystemConfig.sol\";\n\ncontract SystemConfig_GasLimitLowerBound_Invariant is InvariantTest, StdAssertions {\n SystemConfig public config;\n\n function setUp() public {\n config = new SystemConfig({\n _owner: address(0xbeef),\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 8_000_000,\n _unsafeBlockSigner: address(1)\n });\n\n // Set the target contract to the `config`\n targetContract(address(config));\n // Set the target sender to the `config`'s owner (0xbeef)\n targetSender(address(0xbeef));\n // Set the target selector for `setGasLimit`\n // `setGasLimit` is the only function we care about, as it is the only function\n // that can modify the gas limit within the SystemConfig.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = config.setGasLimit.selector;\n FuzzSelector memory selector = FuzzSelector({\n addr: address(config),\n selectors: selectors\n });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The gas limit of the `SystemConfig` contract can never be lower\n * than the hard-coded lower bound.\n */\n function invariant_gasLimitLowerBound() external {\n assertTrue(config.gasLimit() >= config.MINIMUM_GAS_LIMIT());\n }\n}\n" - }, - "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\";\nimport { Constants } from \"../libraries/Constants.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 uint64 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 uint64 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 uint64 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 uint64 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 Address of the paired CrossDomainMessenger contract on the other chain.\n */\n address public immutable OTHER_MESSENGER;\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 a boolean if and only if the message has failed to be\n * executed at least once. A message will not be present in this mapping if it\n * successfully executed on the first attempt.\n */\n mapping(bytes32 => bool) public failedMessages;\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 OTHER_MESSENGER = _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 OTHER_MESSENGER,\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 require(\n version < 2,\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // If the message is version 0, then it's a migrated legacy withdrawal. We therefore need\n // to check that the legacy version of the message has not already been relayed.\n if (version == 0) {\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _nonce);\n require(\n successfulMessages[oldHash] == false,\n \"CrossDomainMessenger: legacy withdrawal already relayed\"\n );\n }\n\n // We use the v1 message hash as the unique identifier for the message because it commits\n // to the value and minimum gas limit of the message.\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _minGasLimit,\n _message\n );\n\n if (_isOtherMessenger()) {\n // These properties should always hold when the message is first submitted (as\n // opposed to being replayed).\n assert(msg.value == _value);\n assert(!failedMessages[versionedHash]);\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 failedMessages[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 = Constants.DEFAULT_L2_SENDER;\n\n if (success == true) {\n successfulMessages[versionedHash] = true;\n emit RelayedMessage(versionedHash);\n } else {\n failedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n\n // Revert in this case if the transaction was triggered by the estimation address. This\n // should only be possible during gas estimation or we have bigger problems. Reverting\n // here will make the behavior of gas estimation change such that the gas limit\n // computed will be the amount required to relay the message, even if that amount is\n // greater than the minimum gas limit specified by the user.\n if (tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"CrossDomainMessenger: failed to relay message\");\n }\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 != Constants.DEFAULT_L2_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 (uint64) {\n // We peform the following math on uint64s to avoid overflow errors. Multiplying the\n // by MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR would otherwise limit the _minGasLimit to\n // type(uint32).max / MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR ~= 4.2m.\n return\n // Dynamic overhead\n ((uint64(_minGasLimit) * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n // Calldata overhead\n (uint64(_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 = Constants.DEFAULT_L2_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" - }, - "contracts/universal/ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CrossDomainMessenger } from \"./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 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 OTHER_BRIDGE;\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 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 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() == OTHER_BRIDGE,\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 OTHER_BRIDGE = _otherBridge;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for other bridge address.\n *\n * @return Address of the bridge on the other network.\n */\n function otherBridge() external view returns (address) {\n return OTHER_BRIDGE;\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" - }, - "contracts/universal/FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n/**\n * @title FeeVault\n * @notice The FeeVault contract contains the basic logic for the various different vault contracts\n * used to hold fee revenue generated by the L2 system.\n */\nabstract contract FeeVault {\n /**\n * @notice Emits each time that a withdrawal occurs.\n *\n * @param value Amount that was withdrawn (in wei).\n * @param to Address that the funds were sent to.\n * @param from Address that triggered the withdrawal.\n */\n event Withdrawal(uint256 value, address to, address from);\n\n /**\n * @notice Minimum balance before a withdrawal can be triggered.\n */\n uint256 public immutable MIN_WITHDRAWAL_AMOUNT;\n\n /**\n * @notice Wallet that will receive the fees on L1.\n */\n address public immutable RECIPIENT;\n\n /**\n * @notice Total amount of wei processed by the contract.\n */\n uint256 public totalProcessed;\n\n /**\n * @param _recipient Wallet that will receive the fees on L1.\n * @param _minWithdrawalAmount Minimum balance before a withdrawal can be triggered.\n */\n constructor(address _recipient, uint256 _minWithdrawalAmount) {\n MIN_WITHDRAWAL_AMOUNT = _minWithdrawalAmount;\n RECIPIENT = _recipient;\n }\n\n /**\n * @notice Allow the contract to receive ETH.\n */\n receive() external payable {}\n\n /**\n * @notice Triggers a withdrawal of funds to the L1 fee wallet.\n */\n function withdraw() external {\n require(\n address(this).balance >= MIN_WITHDRAWAL_AMOUNT,\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n\n uint256 value = address(this).balance;\n totalProcessed += value;\n\n emit Withdrawal(value, RECIPIENT, msg.sender);\n\n L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)).bridgeETHTo{ value: value }(\n RECIPIENT,\n 20000,\n bytes(\"\")\n );\n }\n}\n" - }, - "contracts/universal/IOptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\n/**\n * @title IOptimismMintableERC20\n * @notice This interface is available on the OptimismMintableERC20 contract. We declare it as a\n * separate interface so that it can be used in custom implementations of\n * OptimismMintableERC20.\n */\ninterface IOptimismMintableERC20 {\n function remoteToken() external returns (address);\n\n function bridge() external returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n\n/**\n * @custom:legacy\n * @title ILegacyMintableERC20\n * @notice This interface was available on the legacy L2StandardERC20 contract. It remains available\n * on the OptimismMintableERC20 contract for backwards compatibility.\n */\ninterface ILegacyMintableERC20 is IERC165 {\n function l1Token() external returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n" - }, - "contracts/universal/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 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 /**\n * @notice Chain ID of the chain where the remote token is deployed.\n */\n function REMOTE_CHAIN_ID() external view returns (uint256);\n\n /**\n * @notice Address of the token on the remote domain.\n */\n function REMOTE_TOKEN() 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 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" - }, - "contracts/universal/OptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { ILegacyMintableERC20, IOptimismMintableERC20 } from \"./IOptimismMintableERC20.sol\";\n\n/**\n * @title OptimismMintableERC20\n * @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed\n * to allow the StandardBridge contracts to mint and burn tokens. This makes it possible to\n * use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa.\n * Designed to be backwards compatible with the older StandardL2ERC20 token which was only\n * meant for use on L2.\n */\ncontract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20 {\n /**\n * @notice Address of the corresponding version of this token on the remote chain.\n */\n address public immutable REMOTE_TOKEN;\n\n /**\n * @notice Address of the StandardBridge on this network.\n */\n address public immutable BRIDGE;\n\n /**\n * @notice Emitted whenever tokens are minted for an account.\n *\n * @param account Address of the account tokens are being minted for.\n * @param amount Amount of tokens minted.\n */\n event Mint(address indexed account, uint256 amount);\n\n /**\n * @notice Emitted whenever tokens are burned from an account.\n *\n * @param account Address of the account tokens are being burned from.\n * @param amount Amount of tokens burned.\n */\n event Burn(address indexed account, uint256 amount);\n\n /**\n * @notice A modifier that only allows the bridge to call\n */\n modifier onlyBridge() {\n require(msg.sender == BRIDGE, \"OptimismMintableERC20: only bridge can mint and burn\");\n _;\n }\n\n /**\n * @param _bridge Address of the L2 standard bridge.\n * @param _remoteToken Address of the corresponding L1 token.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n */\n constructor(\n address _bridge,\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) {\n REMOTE_TOKEN = _remoteToken;\n BRIDGE = _bridge;\n }\n\n /**\n * @notice Allows the StandardBridge on this network to mint tokens.\n *\n * @param _to Address to mint tokens to.\n * @param _amount Amount of tokens to mint.\n */\n function mint(address _to, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _mint(_to, _amount);\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Allows the StandardBridge on this network to burn tokens.\n *\n * @param _from Address to burn tokens from.\n * @param _amount Amount of tokens to burn.\n */\n function burn(address _from, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _burn(_from, _amount);\n emit Burn(_from, _amount);\n }\n\n /**\n * @notice ERC165 interface check function.\n *\n * @param _interfaceId Interface ID to check.\n *\n * @return Whether or not the interface is supported by this contract.\n */\n function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {\n bytes4 iface1 = type(IERC165).interfaceId;\n // Interface corresponding to the legacy L2StandardERC20.\n bytes4 iface2 = type(ILegacyMintableERC20).interfaceId;\n // Interface corresponding to the updated OptimismMintableERC20 (this contract).\n bytes4 iface3 = type(IOptimismMintableERC20).interfaceId;\n return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward.\n */\n function l1Token() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the bridge. Use BRIDGE going forward.\n */\n function l2Bridge() public view returns (address) {\n return BRIDGE;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for REMOTE_TOKEN.\n */\n function remoteToken() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for BRIDGE.\n */\n function bridge() public view returns (address) {\n return BRIDGE;\n }\n}\n" - }, - "contracts/universal/OptimismMintableERC20Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Contract Imports */\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { Semver } from \"./Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000012\n * @title OptimismMintableERC20Factory\n * @notice OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20\n * contracts on the network it's deployed to. Simplifies the deployment process for users\n * who may be less familiar with deploying smart contracts. Designed to be backwards\n * compatible with the older StandardL2ERC20Factory contract.\n */\ncontract OptimismMintableERC20Factory is Semver {\n /**\n * @notice Address of the StandardBridge on this chain.\n */\n address public immutable BRIDGE;\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer\n * OptimismMintableERC20Created event. We recommend relying on that event instead.\n *\n * @param remoteToken Address of the token on the remote chain.\n * @param localToken Address of the created token on the local chain.\n */\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n\n /**\n * @notice Emitted whenever a new OptimismMintableERC20 is created.\n *\n * @param localToken Address of the created token on the local chain.\n * @param remoteToken Address of the corresponding token on the remote chain.\n * @param deployer Address of the account that deployed the token.\n */\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _bridge Address of the StandardBridge on this chain.\n */\n constructor(address _bridge) Semver(1, 0, 0) {\n BRIDGE = _bridge;\n }\n\n /**\n * @custom:legacy\n * @notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the\n * newer createOptimismMintableERC20 function, which has a more intuitive name.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createStandardL2Token(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) external returns (address) {\n return createOptimismMintableERC20(_remoteToken, _name, _symbol);\n }\n\n /**\n * @notice Creates an instance of the OptimismMintableERC20 contract.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createOptimismMintableERC20(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) public returns (address) {\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC20Factory: must provide remote token address\"\n );\n\n address localToken = address(\n new OptimismMintableERC20(BRIDGE, _remoteToken, _name, _symbol)\n );\n\n // Emit the old event too for legacy support.\n emit StandardL2TokenCreated(_remoteToken, localToken);\n\n // Emit the updated event. The arguments here differ from the legacy event, but\n // are consistent with the ordering used in StandardBridge events.\n emit OptimismMintableERC20Created(localToken, _remoteToken, msg.sender);\n\n return localToken;\n }\n}\n" - }, - "contracts/universal/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 REMOTE_CHAIN_ID;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable REMOTE_TOKEN;\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 * @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 * @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 REMOTE_CHAIN_ID = _remoteChainId;\n REMOTE_TOKEN = _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 * @inheritdoc IOptimismMintableERC721\n */\n function remoteChainId() external view returns (uint256) {\n return REMOTE_CHAIN_ID;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function remoteToken() external view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function bridge() external view returns (address) {\n return BRIDGE;\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" - }, - "contracts/universal/OptimismMintableERC721Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\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 {\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 REMOTE_CHAIN_ID;\n\n /**\n * @notice Tracks addresses created by this factory.\n */\n mapping(address => bool) public isOptimismMintableERC721;\n\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 * @custom:semver 1.0.0\n *\n * @param _bridge Address of the ERC721 bridge on this network.\n * @param _remoteChainId Chain ID for the remote network.\n */\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 0, 0) {\n BRIDGE = _bridge;\n REMOTE_CHAIN_ID = _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, REMOTE_CHAIN_ID, _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/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" - }, - "contracts/universal/ProxyAdmin.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.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 Ownable {\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 * @notice A mapping of proxy types, used for backwards compatibility.\n */\n mapping(address => ProxyType) public proxyType;\n\n /**\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 * @notice The address of the address manager, this is required to manage the\n * ResolvedDelegateProxy type.\n */\n AddressManager public addressManager;\n\n /**\n * @notice A legacy upgrading indicator used by the old Chugsplash Proxy.\n */\n bool internal upgrading;\n\n /**\n * @param _owner Address of the initial owner of this contract.\n */\n constructor(address _owner) Ownable() {\n _transferOwnership(_owner);\n }\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 * @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 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.\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 /**\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" - }, - "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 uint256 private immutable MAJOR_VERSION;\n\n /**\n * @notice Contract version number (minor).\n */\n uint256 private immutable MINOR_VERSION;\n\n /**\n * @notice Contract version number (patch).\n */\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" - }, - "contracts/universal/StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { IOptimismMintableERC20, ILegacyMintableERC20 } from \"./IOptimismMintableERC20.sol\";\nimport { CrossDomainMessenger } from \"./CrossDomainMessenger.sol\";\nimport { OptimismMintableERC20 } from \"./OptimismMintableERC20.sol\";\n\n/**\n * @custom:upgradeable\n * @title StandardBridge\n * @notice StandardBridge is a base contract for the L1 and L2 standard ERC20 bridges. It handles\n * the core bridging logic, including escrowing tokens that are native to the local chain\n * and minting/burning tokens that are native to the remote chain.\n */\nabstract contract StandardBridge {\n using SafeERC20 for IERC20;\n\n /**\n * @notice The L2 gas limit set when eth is depoisited using the receive() function.\n */\n uint32 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 200_000;\n\n /**\n * @notice Messenger contract on this domain.\n */\n CrossDomainMessenger public immutable MESSENGER;\n\n /**\n * @notice Corresponding bridge on the other domain.\n */\n StandardBridge public immutable OTHER_BRIDGE;\n\n /**\n * @custom:legacy\n * @custom:spacer messenger\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_0_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer l2TokenBridge\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_1_0_20;\n\n /**\n * @notice Mapping that stores deposits for a given pair of local and remote tokens.\n */\n mapping(address => mapping(address => uint256)) public deposits;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n * A gap size of 47 was chosen here, so that the first slot used in a child contract\n * would be a multiple of 50.\n */\n uint256[47] private __gap;\n\n /**\n * @notice Emitted when an ETH bridge is initiated to the other chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ETH bridge is finalized on this chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is initiated to the other chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is finalized on this chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Only allow EOAs to call the functions. Note that this is not safe against contracts\n * calling code within their constructors, but also doesn't really matter since we're\n * just trying to prevent users accidentally depositing with smart contract wallets.\n */\n modifier onlyEOA() {\n require(\n !Address.isContract(msg.sender),\n \"StandardBridge: function can only be called from an EOA\"\n );\n _;\n }\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) &&\n MESSENGER.xDomainMessageSender() == address(OTHER_BRIDGE),\n \"StandardBridge: function can only be called from the other bridge\"\n );\n _;\n }\n\n /**\n * @param _messenger Address of CrossDomainMessenger on this network.\n * @param _otherBridge Address of the other StandardBridge contract.\n */\n constructor(address payable _messenger, address payable _otherBridge) {\n MESSENGER = CrossDomainMessenger(_messenger);\n OTHER_BRIDGE = StandardBridge(_otherBridge);\n }\n\n /**\n * @notice Allows EOAs to deposit ETH by sending directly to the bridge.\n */\n receive() external payable onlyEOA {\n _initiateBridgeETH(msg.sender, msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @notice Sends ETH to the sender's address on the other chain.\n *\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETH(uint32 _minGasLimit, bytes calldata _extraData) public payable onlyEOA {\n _initiateBridgeETH(msg.sender, msg.sender, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a\n * smart contract and the call fails, the ETH will be temporarily locked in the\n * StandardBridge on the other chain until the call is replayed. If the call cannot be\n * replayed with any amount of gas (call always reverts), then the ETH will be\n * permanently locked in the StandardBridge on the other chain. ETH will also\n * be locked if the receiver is the other bridge, because finalizeBridgeETH will revert\n * in that case.\n *\n * @param _to Address of the receiver.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public payable {\n _initiateBridgeETH(msg.sender, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ERC20 tokens to the sender's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20(\n address _localToken,\n address _remoteToken,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual onlyEOA {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Finalizes an ETH bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public payable onlyOtherBridge {\n require(msg.value == _amount, \"StandardBridge: amount sent does not match amount required\");\n require(_to != address(this), \"StandardBridge: cannot send to self\");\n require(_to != address(MESSENGER), \"StandardBridge: cannot send to messenger\");\n\n emit ETHBridgeFinalized(_from, _to, _amount, _extraData);\n\n bool success = SafeCall.call(_to, gasleft(), _amount, hex\"\");\n require(success, \"StandardBridge: ETH transfer failed\");\n }\n\n /**\n * @notice Finalizes an ERC20 bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public onlyOtherBridge {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).mint(_to, _amount);\n } else {\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] - _amount;\n IERC20(_localToken).safeTransfer(_to, _amount);\n }\n\n emit ERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Initiates a bridge of ETH through the CrossDomainMessenger.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n require(\n msg.value == _amount,\n \"StandardBridge: bridging ETH must include sufficient ETH value\"\n );\n\n emit ETHBridgeInitiated(_from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage{ value: _amount }(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeETH.selector,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) internal {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).burn(_from, _amount);\n } else {\n IERC20(_localToken).safeTransferFrom(_from, address(this), _amount);\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount;\n }\n\n emit ERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeERC20.selector,\n // Because this call will be executed on the remote chain, we reverse the order of\n // the remote and local token addresses relative to their order in the\n // finalizeBridgeERC20 function.\n _remoteToken,\n _localToken,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Checks if a given address is an OptimismMintableERC20. Not perfect, but good enough.\n * Just the way we like it.\n *\n * @param _token Address of the token to check.\n *\n * @return True if the token is an OptimismMintableERC20.\n */\n function _isOptimismMintableERC20(address _token) internal view returns (bool) {\n return\n ERC165Checker.supportsInterface(_token, type(ILegacyMintableERC20).interfaceId) ||\n ERC165Checker.supportsInterface(_token, type(IOptimismMintableERC20).interfaceId);\n }\n\n /**\n * @notice Checks if the \"other token\" is the correct pair token for the OptimismMintableERC20.\n *\n * @param _mintableToken OptimismMintableERC20 to check against.\n * @param _otherToken Pair token to check.\n *\n * @return True if the other token is the correct pair token for the OptimismMintableERC20.\n */\n function _isCorrectTokenPair(address _mintableToken, address _otherToken)\n internal\n view\n returns (bool)\n {\n return _otherToken == OptimismMintableERC20(_mintableToken).l1Token();\n }\n}\n" - }, - "contracts/vendor/AddressAliasHelper.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npragma solidity ^0.8.0;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n unchecked {\n l2Address = address(uint160(l1Address) + offset);\n }\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n unchecked {\n l1Address = address(uint160(l2Address) - offset);\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/access/Ownable.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/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 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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/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/Address.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) || (!Address.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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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, allowance(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 = allowance(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 `from` to `to`.\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 Updates `owner` s allowance for `spender` based on spent `amount`.\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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 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 /**\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (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 constant _PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n /**\n * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\n * However, to ensure consistency with the upgradeable transpiler, we will continue\n * to reserve a slot.\n * @custom:oz-renamed-from _PERMIT_TYPEHASH\n */\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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: address zero is not a valid owner\");\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: invalid token ID\");\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 _requireMinted(tokenId);\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 token 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 _requireMinted(tokenId);\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: caller is not token 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: caller is not token 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 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 an {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 an {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 Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\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 /// @solidity memory-safe-assembly\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Address.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 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 /// @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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\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 /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.3) (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 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 /// @solidity memory-safe-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 {\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.2) (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 // prepare call\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n\n // perform static call\n bool success;\n uint256 returnSize;\n uint256 returnValue;\n assembly {\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\n returnSize := returndatasize()\n returnValue := mload(0x00)\n }\n\n return success && returnSize >= 0x20 && returnValue > 0;\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\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 == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`.\n // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.\n // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.\n // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a\n // good first aproximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1;\n uint256 x = a;\n if (x >> 128 > 0) {\n x >>= 128;\n result <<= 64;\n }\n if (x >> 64 > 0) {\n x >>= 64;\n result <<= 32;\n }\n if (x >> 32 > 0) {\n x >>= 32;\n result <<= 16;\n }\n if (x >> 16 > 0) {\n x >>= 16;\n result <<= 8;\n }\n if (x >> 8 > 0) {\n x >>= 8;\n result <<= 4;\n }\n if (x >> 4 > 0) {\n x >>= 4;\n result <<= 2;\n }\n if (x >> 2 > 0) {\n result <<= 1;\n }\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n uint256 result = sqrt(a);\n if (rounding == Rounding.Up && result * result < a) {\n result += 1;\n }\n return result;\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\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 * _Available since v4.2._\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 uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(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 * _Available since v2.5._\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 uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(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 * _Available since v4.2._\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 uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(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 * _Available since v2.5._\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 uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(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 * _Available since v2.5._\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 uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(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 * _Available since v2.5._\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 * _Available since v2.5._\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 * _Available since v3.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 int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248) {\n require(value >= type(int248).min && value <= type(int248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return int248(value);\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240) {\n require(value >= type(int240).min && value <= type(int240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return int240(value);\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232) {\n require(value >= type(int232).min && value <= type(int232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return int232(value);\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224) {\n require(value >= type(int224).min && value <= type(int224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return int224(value);\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216) {\n require(value >= type(int216).min && value <= type(int216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return int216(value);\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208) {\n require(value >= type(int208).min && value <= type(int208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return int208(value);\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200) {\n require(value >= type(int200).min && value <= type(int200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return int200(value);\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192) {\n require(value >= type(int192).min && value <= type(int192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return int192(value);\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184) {\n require(value >= type(int184).min && value <= type(int184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return int184(value);\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176) {\n require(value >= type(int176).min && value <= type(int176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return int176(value);\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168) {\n require(value >= type(int168).min && value <= type(int168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return int168(value);\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160) {\n require(value >= type(int160).min && value <= type(int160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return int160(value);\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152) {\n require(value >= type(int152).min && value <= type(int152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return int152(value);\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144) {\n require(value >= type(int144).min && value <= type(int144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return int144(value);\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136) {\n require(value >= type(int136).min && value <= type(int136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return int136(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 int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120) {\n require(value >= type(int120).min && value <= type(int120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return int120(value);\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112) {\n require(value >= type(int112).min && value <= type(int112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return int112(value);\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104) {\n require(value >= type(int104).min && value <= type(int104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return int104(value);\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96) {\n require(value >= type(int96).min && value <= type(int96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return int96(value);\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88) {\n require(value >= type(int88).min && value <= type(int88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return int88(value);\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80) {\n require(value >= type(int80).min && value <= type(int80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return int80(value);\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72) {\n require(value >= type(int72).min && value <= type(int72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return int72(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 int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56) {\n require(value >= type(int56).min && value <= type(int56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return int56(value);\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48) {\n require(value >= type(int48).min && value <= type(int48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return int48(value);\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40) {\n require(value >= type(int40).min && value <= type(int40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return int40(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 int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24) {\n require(value >= type(int24).min && value <= type(int24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return int24(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 * _Available since v3.0._\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" - }, - "node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@rari-capital/solmate/src/utils/Bytes32AddressLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Library for converting between addresses and bytes32 values.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/Bytes32AddressLib.sol)\nlibrary Bytes32AddressLib {\n function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n function fillLast12Bytes(address addressValue) internal pure returns (bytes32) {\n return bytes32(bytes20(addressValue));\n }\n}\n" - }, - "node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)\nlibrary FixedPointMathLib {\n /*//////////////////////////////////////////////////////////////\n SIMPLIFIED FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n }\n\n function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n }\n\n function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n }\n\n function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n }\n\n function powWad(int256 x, int256 y) internal pure returns (int256) {\n // Equivalent to x to the power of y because x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)\n return expWad((lnWad(x) * y) / int256(WAD)); // Using ln(x) means x must be greater than 0.\n }\n\n function expWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n // When the result is < 0.5 we return zero. This happens when\n // x <= floor(log(0.5e18) * 1e18) ~ -42e18\n if (x <= -42139678854452767551) return 0;\n\n // When the result is > (2**255 - 1) / 1e18 we can not represent it as an\n // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.\n if (x >= 135305999368893231589) revert(\"EXP_OVERFLOW\");\n\n // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96\n // for more intermediate precision and a binary basis. This base conversion\n // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.\n x = (x << 78) / 5**18;\n\n // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers\n // of two such that exp(x) = exp(x') * 2**k, where k is an integer.\n // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).\n int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96;\n x = x - k * 54916777467707473351141471128;\n\n // k is in the range [-61, 195].\n\n // Evaluate using a (6, 7)-term rational approximation.\n // p is made monic, we'll multiply by a scale factor later.\n int256 y = x + 1346386616545796478920950773328;\n y = ((y * x) >> 96) + 57155421227552351082224309758442;\n int256 p = y + x - 94201549194550492254356042504812;\n p = ((p * y) >> 96) + 28719021644029726153956944680412240;\n p = p * x + (4385272521454847904659076985693276 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n int256 q = x - 2855989394907223263936484059900;\n q = ((q * x) >> 96) + 50020603652535783019961831881945;\n q = ((q * x) >> 96) - 533845033583426703283633433725380;\n q = ((q * x) >> 96) + 3604857256930695427073651918091429;\n q = ((q * x) >> 96) - 14423608567350463180887372962807573;\n q = ((q * x) >> 96) + 26449188498355588339934803723976023;\n\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial won't have zeros in the domain as all its roots are complex.\n // No scaling is necessary because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r should be in the range (0.09, 0.25) * 2**96.\n\n // We now need to multiply r by:\n // * the scale factor s = ~6.031367120.\n // * the 2**k factor from the range reduction.\n // * the 1e18 / 2**96 factor for base conversion.\n // We do this all at once, with an intermediate result in 2**213\n // basis, so the final right shift is always by a positive amount.\n r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k));\n }\n }\n\n function lnWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n require(x > 0, \"UNDEFINED\");\n\n // We want to convert x from 10**18 fixed point to 2**96 fixed point.\n // We do this by multiplying by 2**96 / 10**18. But since\n // ln(x * C) = ln(x) + ln(C), we can simply do nothing here\n // and add ln(2**96 / 10**18) at the end.\n\n // Reduce range of x to (1, 2) * 2**96\n // ln(2^k * x) = k * ln(2) + ln(x)\n int256 k = int256(log2(uint256(x))) - 96;\n x <<= uint256(159 - k);\n x = int256(uint256(x) >> 159);\n\n // Evaluate using a (8, 8)-term rational approximation.\n // p is made monic, we will multiply by a scale factor later.\n int256 p = x + 3273285459638523848632254066296;\n p = ((p * x) >> 96) + 24828157081833163892658089445524;\n p = ((p * x) >> 96) + 43456485725739037958740375743393;\n p = ((p * x) >> 96) - 11111509109440967052023855526967;\n p = ((p * x) >> 96) - 45023709667254063763336534515857;\n p = ((p * x) >> 96) - 14706773417378608786704636184526;\n p = p * x - (795164235651350426258249787498 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n // q is monic by convention.\n int256 q = x + 5573035233440673466300451813936;\n q = ((q * x) >> 96) + 71694874799317883764090561454958;\n q = ((q * x) >> 96) + 283447036172924575727196451306956;\n q = ((q * x) >> 96) + 401686690394027663651624208769553;\n q = ((q * x) >> 96) + 204048457590392012362485061816622;\n q = ((q * x) >> 96) + 31853899698501571402653359427138;\n q = ((q * x) >> 96) + 909429971244387300277376558375;\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial is known not to have zeros in the domain.\n // No scaling required because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r is in the range (0, 0.125) * 2**96\n\n // Finalization, we need to:\n // * multiply by the scale factor s = 5.549…\n // * add ln(2**96 / 10**18)\n // * add k * ln(2)\n // * multiply by 10**18 / 2**96 = 5**18 >> 78\n\n // mul s * 5e18 * 2**96, base is now 5**18 * 2**192\n r *= 1677202110996718588342820967067443963516166;\n // add ln(2) * k * 5e18 * 2**192\n r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;\n // add ln(2**96 / 10**18) * 5e18 * 2**192\n r += 600920179829731861736702779321621459595472258049074101567377883020018308;\n // base conversion: mul 2**18 / 2**192\n r >>= 174;\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n LOW LEVEL FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function mulDivDown(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // Divide z by the denominator.\n z := div(z, denominator)\n }\n }\n\n function mulDivUp(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // First, divide z - 1 by the denominator and add 1.\n // We allow z - 1 to underflow if z is 0, because we multiply the\n // end result by 0 if z is zero, ensuring we return 0 if z is zero.\n z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))\n }\n }\n\n function rpow(\n uint256 x,\n uint256 n,\n uint256 scalar\n ) internal pure returns (uint256 z) {\n assembly {\n switch x\n case 0 {\n switch n\n case 0 {\n // 0 ** 0 = 1\n z := scalar\n }\n default {\n // 0 ** n = 0\n z := 0\n }\n }\n default {\n switch mod(n, 2)\n case 0 {\n // If n is even, store scalar in z for now.\n z := scalar\n }\n default {\n // If n is odd, store x in z for now.\n z := x\n }\n\n // Shifting right by 1 is like dividing by 2.\n let half := shr(1, scalar)\n\n for {\n // Shift n right by 1 before looping to halve it.\n n := shr(1, n)\n } n {\n // Shift n right by 1 each iteration to halve it.\n n := shr(1, n)\n } {\n // Revert immediately if x ** 2 would overflow.\n // Equivalent to iszero(eq(div(xx, x), x)) here.\n if shr(128, x) {\n revert(0, 0)\n }\n\n // Store x squared.\n let xx := mul(x, x)\n\n // Round to the nearest number.\n let xxRound := add(xx, half)\n\n // Revert if xx + half overflowed.\n if lt(xxRound, xx) {\n revert(0, 0)\n }\n\n // Set x to scaled xxRound.\n x := div(xxRound, scalar)\n\n // If n is even:\n if mod(n, 2) {\n // Compute z * x.\n let zx := mul(z, x)\n\n // If z * x overflowed:\n if iszero(eq(div(zx, x), z)) {\n // Revert if x is non-zero.\n if iszero(iszero(x)) {\n revert(0, 0)\n }\n }\n\n // Round to the nearest number.\n let zxRound := add(zx, half)\n\n // Revert if zx + half overflowed.\n if lt(zxRound, zx) {\n revert(0, 0)\n }\n\n // Return properly scaled zxRound.\n z := div(zxRound, scalar)\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n GENERAL NUMBER UTILITIES\n //////////////////////////////////////////////////////////////*/\n\n function sqrt(uint256 x) internal pure returns (uint256 z) {\n assembly {\n let y := x // We start y at x, which will help us make our initial estimate.\n\n z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n // We check y >= 2^(k + 8) but shift right by k bits\n // each branch to ensure that if x >= 256, then y >= 256.\n if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n y := shr(128, y)\n z := shl(64, z)\n }\n if iszero(lt(y, 0x1000000000000000000)) {\n y := shr(64, y)\n z := shl(32, z)\n }\n if iszero(lt(y, 0x10000000000)) {\n y := shr(32, y)\n z := shl(16, z)\n }\n if iszero(lt(y, 0x1000000)) {\n y := shr(16, y)\n z := shl(8, z)\n }\n\n // Goal was to get z*z*y within a small factor of x. More iterations could\n // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n // There is no overflow risk here since y < 2^136 after the first branch above.\n z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n\n // If x+1 is a perfect square, the Babylonian method cycles between\n // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n z := sub(z, lt(div(x, z), z))\n }\n }\n\n function log2(uint256 x) internal pure returns (uint256 r) {\n require(x > 0, \"UNDEFINED\");\n\n assembly {\n r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n r := or(r, shl(4, lt(0xffff, shr(r, x))))\n r := or(r, shl(3, lt(0xff, shr(r, x))))\n r := or(r, shl(2, lt(0xf, shr(r, x))))\n r := or(r, shl(1, lt(0x3, shr(r, x))))\n r := or(r, lt(0x1, shr(r, x)))\n }\n }\n}\n" - }, - "node_modules/ds-test/src/test.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see .\n\npragma solidity >=0.5.0;\n\ncontract DSTest {\n event log (string);\n event logs (bytes);\n\n event log_address (address);\n event log_bytes32 (bytes32);\n event log_int (int);\n event log_uint (uint);\n event log_bytes (bytes);\n event log_string (string);\n\n event log_named_address (string key, address val);\n event log_named_bytes32 (string key, bytes32 val);\n event log_named_decimal_int (string key, int val, uint decimals);\n event log_named_decimal_uint (string key, uint val, uint decimals);\n event log_named_int (string key, int val);\n event log_named_uint (string key, uint val);\n event log_named_bytes (string key, bytes val);\n event log_named_string (string key, string val);\n\n bool public IS_TEST = true;\n bool private _failed;\n\n address constant HEVM_ADDRESS =\n address(bytes20(uint160(uint256(keccak256('hevm cheat code')))));\n\n modifier mayRevert() { _; }\n modifier testopts(string memory) { _; }\n\n function failed() public returns (bool) {\n if (_failed) {\n return _failed;\n } else {\n bool globalFailed = false;\n if (hasHEVMContext()) {\n (, bytes memory retdata) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"load(address,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"))\n )\n );\n globalFailed = abi.decode(retdata, (bool));\n }\n return globalFailed;\n }\n } \n\n function fail() internal {\n if (hasHEVMContext()) {\n (bool status, ) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"store(address,bytes32,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"), bytes32(uint256(0x01)))\n )\n );\n status; // Silence compiler warnings\n }\n _failed = true;\n }\n\n function hasHEVMContext() internal view returns (bool) {\n uint256 hevmCodeSize = 0;\n assembly {\n hevmCodeSize := extcodesize(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D)\n }\n return hevmCodeSize > 0;\n }\n\n modifier logs_gas() {\n uint startGas = gasleft();\n _;\n uint endGas = gasleft();\n emit log_named_uint(\"gas\", startGas - endGas);\n }\n\n function assertTrue(bool condition) internal {\n if (!condition) {\n emit log(\"Error: Assertion Failed\");\n fail();\n }\n }\n\n function assertTrue(bool condition, string memory err) internal {\n if (!condition) {\n emit log_named_string(\"Error\", err);\n assertTrue(condition);\n }\n }\n\n function assertEq(address a, address b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [address]\");\n emit log_named_address(\" Expected\", b);\n emit log_named_address(\" Actual\", a);\n fail();\n }\n }\n function assertEq(address a, address b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes32 a, bytes32 b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bytes32]\");\n emit log_named_bytes32(\" Expected\", b);\n emit log_named_bytes32(\" Actual\", a);\n fail();\n }\n }\n function assertEq(bytes32 a, bytes32 b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq32(bytes32 a, bytes32 b) internal {\n assertEq(a, b);\n }\n function assertEq32(bytes32 a, bytes32 b, string memory err) internal {\n assertEq(a, b, err);\n }\n\n function assertEq(int a, int b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [int]\");\n emit log_named_int(\" Expected\", b);\n emit log_named_int(\" Actual\", a);\n fail();\n }\n }\n function assertEq(int a, int b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq(uint a, uint b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [uint]\");\n emit log_named_uint(\" Expected\", b);\n emit log_named_uint(\" Actual\", a);\n fail();\n }\n }\n function assertEq(uint a, uint b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEqDecimal(int a, int b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Expected\", b, decimals);\n emit log_named_decimal_int(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Expected\", b, decimals);\n emit log_named_decimal_uint(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n\n function assertGt(uint a, uint b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGt(uint a, uint b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGt(int a, int b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGt(int a, int b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGtDecimal(int a, int b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n\n function assertGe(uint a, uint b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGe(uint a, uint b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGe(int a, int b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGe(int a, int b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGeDecimal(int a, int b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertLt(uint a, uint b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLt(uint a, uint b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLt(int a, int b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLt(int a, int b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLtDecimal(int a, int b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n\n function assertLe(uint a, uint b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLe(uint a, uint b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLe(int a, int b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLe(int a, int b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLeDecimal(int a, int b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLeDecimal(a, b, decimals);\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertEq(string memory a, string memory b) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log(\"Error: a == b not satisfied [string]\");\n emit log_named_string(\" Expected\", b);\n emit log_named_string(\" Actual\", a);\n fail();\n }\n }\n function assertEq(string memory a, string memory b, string memory err) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function checkEq0(bytes memory a, bytes memory b) internal pure returns (bool ok) {\n ok = true;\n if (a.length == b.length) {\n for (uint i = 0; i < a.length; i++) {\n if (a[i] != b[i]) {\n ok = false;\n }\n }\n } else {\n ok = false;\n }\n }\n function assertEq0(bytes memory a, bytes memory b) internal {\n if (!checkEq0(a, b)) {\n emit log(\"Error: a == b not satisfied [bytes]\");\n emit log_named_bytes(\" Expected\", b);\n emit log_named_bytes(\" Actual\", a);\n fail();\n }\n }\n function assertEq0(bytes memory a, bytes memory b, string memory err) internal {\n if (!checkEq0(a, b)) {\n emit log_named_string(\"Error\", err);\n assertEq0(a, b);\n }\n }\n}\n" - }, - "node_modules/forge-std/src/Base.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {StdStorage} from \"./StdStorage.sol\";\nimport {Vm, VmSafe} from \"./Vm.sol\";\n\nabstract contract CommonBase {\n // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.\n address internal constant VM_ADDRESS = address(uint160(uint256(keccak256(\"hevm cheat code\"))));\n // console.sol and console2.sol work by executing a staticcall to this address.\n address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;\n // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38.\n address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256(\"foundry default caller\"))));\n // Address of the test contract, deployed by the DEFAULT_SENDER.\n address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;\n\n uint256 internal constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n Vm internal constant vm = Vm(VM_ADDRESS);\n StdStorage internal stdstore;\n}\n\nabstract contract TestBase is CommonBase {}\n\nabstract contract ScriptBase is CommonBase {\n // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.\n address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;\n\n VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);\n}\n" - }, - "node_modules/forge-std/src/InvariantTest.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\ncontract InvariantTest {\n struct FuzzSelector {\n address addr;\n bytes4[] selectors;\n }\n\n address[] private _excludedContracts;\n address[] private _excludedSenders;\n address[] private _targetedContracts;\n address[] private _targetedSenders;\n\n string[] private _excludedArtifacts;\n string[] private _targetedArtifacts;\n\n FuzzSelector[] internal _targetedArtifactSelectors;\n FuzzSelector[] internal _targetedSelectors;\n\n function excludeArtifact(string memory newExcludedArtifact_) internal {\n _excludedArtifacts.push(newExcludedArtifact_);\n }\n\n function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) {\n require(_excludedArtifacts.length != uint256(0), \"NO_EXCLUDED_ARTIFACTS\");\n excludedArtifacts_ = _excludedArtifacts;\n }\n\n function excludeContract(address newExcludedContract_) internal {\n _excludedContracts.push(newExcludedContract_);\n }\n\n function excludeContracts() public view returns (address[] memory excludedContracts_) {\n require(_excludedContracts.length != uint256(0), \"NO_EXCLUDED_CONTRACTS\");\n excludedContracts_ = _excludedContracts;\n }\n\n function excludeSender(address newExcludedSender_) internal {\n _excludedSenders.push(newExcludedSender_);\n }\n\n function excludeSenders() public view returns (address[] memory excludedSenders_) {\n require(_excludedSenders.length != uint256(0), \"NO_EXCLUDED_SENDERS\");\n excludedSenders_ = _excludedSenders;\n }\n\n function targetArtifact(string memory newTargetedArtifact_) internal {\n _targetedArtifacts.push(newTargetedArtifact_);\n }\n\n function targetArtifacts() public view returns (string[] memory targetedArtifacts_) {\n require(_targetedArtifacts.length != uint256(0), \"NO_TARGETED_ARTIFACTS\");\n targetedArtifacts_ = _targetedArtifacts;\n }\n\n function targetArtifactSelector(FuzzSelector memory newTargetedArtifactSelector_) internal {\n _targetedArtifactSelectors.push(newTargetedArtifactSelector_);\n }\n\n function targetArtifactSelectors() public view returns (FuzzSelector[] memory targetedArtifactSelectors_) {\n require(targetedArtifactSelectors_.length != uint256(0), \"NO_TARGETED_ARTIFACT_SELECTORS\");\n targetedArtifactSelectors_ = _targetedArtifactSelectors;\n }\n\n function targetContract(address newTargetedContract_) internal {\n _targetedContracts.push(newTargetedContract_);\n }\n\n function targetContracts() public view returns (address[] memory targetedContracts_) {\n require(_targetedContracts.length != uint256(0), \"NO_TARGETED_CONTRACTS\");\n targetedContracts_ = _targetedContracts;\n }\n\n function targetSelector(FuzzSelector memory newTargetedSelector_) internal {\n _targetedSelectors.push(newTargetedSelector_);\n }\n\n function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) {\n require(targetedSelectors_.length != uint256(0), \"NO_TARGETED_SELECTORS\");\n targetedSelectors_ = _targetedSelectors;\n }\n\n function targetSender(address newTargetedSender_) internal {\n _targetedSenders.push(newTargetedSender_);\n }\n\n function targetSenders() public view returns (address[] memory targetedSenders_) {\n require(_targetedSenders.length != uint256(0), \"NO_TARGETED_SENDERS\");\n targetedSenders_ = _targetedSenders;\n }\n}\n" - }, - "node_modules/forge-std/src/StdAssertions.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {DSTest} from \"ds-test/test.sol\";\nimport {stdMath} from \"./StdMath.sol\";\n\nabstract contract StdAssertions is DSTest {\n event log_array(uint256[] val);\n event log_array(int256[] val);\n event log_array(address[] val);\n event log_named_array(string key, uint256[] val);\n event log_named_array(string key, int256[] val);\n event log_named_array(string key, address[] val);\n\n function fail(string memory err) internal virtual {\n emit log_named_string(\"Error\", err);\n fail();\n }\n\n function assertFalse(bool data) internal virtual {\n assertTrue(!data);\n }\n\n function assertFalse(bool data, string memory err) internal virtual {\n assertTrue(!data, err);\n }\n\n function assertEq(bool a, bool b) internal virtual {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bool]\");\n emit log_named_string(\" Expected\", b ? \"true\" : \"false\");\n emit log_named_string(\" Actual\", a ? \"true\" : \"false\");\n fail();\n }\n }\n\n function assertEq(bool a, bool b, string memory err) internal virtual {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes memory a, bytes memory b) internal virtual {\n assertEq0(a, b);\n }\n\n function assertEq(bytes memory a, bytes memory b, string memory err) internal virtual {\n assertEq0(a, b, err);\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [uint[]]\");\n emit log_named_array(\" Expected\", b);\n emit log_named_array(\" Actual\", a);\n fail();\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [int[]]\");\n emit log_named_array(\" Expected\", b);\n emit log_named_array(\" Actual\", a);\n fail();\n }\n }\n\n function assertEq(address[] memory a, address[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [address[]]\");\n emit log_named_array(\" Expected\", b);\n emit log_named_array(\" Actual\", a);\n fail();\n }\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(address[] memory a, address[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n // Legacy helper\n function assertEqUint(uint256 a, uint256 b) internal virtual {\n assertEq(uint256(a), uint256(b));\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Expected\", b);\n emit log_named_uint(\" Actual\", a);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Expected\", b);\n emit log_named_int(\" Actual\", a);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%\n ) internal virtual {\n if (b == 0) return assertEq(a, b); // If the expected is 0, actual must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Expected\", b);\n emit log_named_uint(\" Actual\", a);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n string memory err\n ) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the expected is 0, actual must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta) internal virtual {\n if (b == 0) return assertEq(a, b); // If the expected is 0, actual must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Expected\", b);\n emit log_named_int(\" Actual\", a);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta, string memory err) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the expected is 0, actual must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n}\n" - }, - "node_modules/forge-std/src/StdChains.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n/**\n * StdChains provides information about EVM compatible chains that can be used in scripts/tests.\n * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are\n * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of\n * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the\n * alias used in this contract, which can be found as the first argument to the\n * `setChainWithDefaultRpcUrl` call in the `initialize` function.\n *\n * There are two main ways to use this contract:\n * 1. Set a chain with `setChain(string memory chainAlias, Chain memory chain)`\n * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.\n *\n * The first time either of those are used, chains are initialized with the default set of RPC URLs.\n * This is done in `initialize`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in\n * `defaultRpcUrls`.\n *\n * The `setChain` function is straightforward, and it simply saves off the given chain data.\n *\n * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say\n * we want to retrieve `mainnet`'s RPC URL:\n * - If you haven't set any mainnet chain info with `setChain` and you haven't specified that\n * chain in `foundry.toml`, the default data and RPC URL will be returned.\n * - If you have set a mainnet RPC URL in `foundry.toml` it will return that, if valid (e.g. if\n * a URL is given or if an environment variable is given and that environment variable exists).\n * Otherwise, the default data is returned.\n * - If you specified data with `setChain` it will return that.\n *\n * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> defaults.\n */\nabstract contract StdChains {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private initialized;\n\n struct Chain {\n // The chain name.\n string name;\n // The chain's Chain ID.\n uint256 chainId;\n // A default RPC endpoint for this chain.\n // NOTE: This default RPC URL is included for convenience to facilitate quick tests and\n // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy\n // usage as you will be throttled and this is a disservice to others who need this endpoint.\n string rpcUrl;\n }\n\n // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.\n mapping(string => Chain) private chains;\n // Maps from the chain's alias to it's default RPC URL.\n mapping(string => string) private defaultRpcUrls;\n // Maps from a chain ID to it's alias.\n mapping(uint256 => string) private idToAlias;\n\n // The RPC URL will be fetched from config or defaultRpcUrls if possible.\n function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {\n require(bytes(chainAlias).length != 0, \"StdChains getChain(string): Chain alias cannot be the empty string.\");\n\n initialize();\n chain = chains[chainAlias];\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(string): Chain with alias \\\"\", chainAlias, \"\\\" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {\n require(chainId != 0, \"StdChains getChain(uint256): Chain ID cannot be 0.\");\n initialize();\n string memory chainAlias = idToAlias[chainId];\n\n chain = chains[chainAlias];\n\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(uint256): Chain with ID \", vm.toString(chainId), \" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n // set chain info, with priority to argument's rpcUrl field.\n function setChain(string memory chainAlias, Chain memory chain) internal virtual {\n require(\n bytes(chainAlias).length != 0, \"StdChains setChain(string,Chain): Chain alias cannot be the empty string.\"\n );\n\n require(chain.chainId != 0, \"StdChains setChain(string,Chain): Chain ID cannot be 0.\");\n\n initialize();\n string memory foundAlias = idToAlias[chain.chainId];\n\n require(\n bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)),\n string(\n abi.encodePacked(\n \"StdChains setChain(string,Chain): Chain ID \",\n vm.toString(chain.chainId),\n \" already used by \\\"\",\n foundAlias,\n \"\\\".\"\n )\n )\n );\n\n uint256 oldChainId = chains[chainAlias].chainId;\n delete idToAlias[oldChainId];\n\n chains[chainAlias] = chain;\n idToAlias[chain.chainId] = chainAlias;\n }\n\n // lookup rpcUrl, in descending order of priority:\n // current -> config (foundry.toml) -> default\n function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain)\n private\n view\n returns (Chain memory)\n {\n if (bytes(chain.rpcUrl).length == 0) {\n try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {\n chain.rpcUrl = configRpcUrl;\n } catch (bytes memory err) {\n chain.rpcUrl = defaultRpcUrls[chainAlias];\n // distinguish 'not found' from 'cannot read'\n bytes memory notFoundError =\n abi.encodeWithSignature(\"CheatCodeError\", string(abi.encodePacked(\"invalid rpc url \", chainAlias)));\n if (keccak256(notFoundError) != keccak256(err) || bytes(chain.rpcUrl).length == 0) {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, err), mload(err))\n }\n }\n }\n }\n return chain;\n }\n\n function initialize() private {\n if (initialized) return;\n\n initialized = true;\n\n // If adding an RPC here, make sure to test the default RPC URL in `testRpcs`\n setChainWithDefaultRpcUrl(\"anvil\", Chain(\"Anvil\", 31337, \"http://127.0.0.1:8545\"));\n setChainWithDefaultRpcUrl(\n \"mainnet\", Chain(\"Mainnet\", 1, \"https://mainnet.infura.io/v3/6770454bc6ea42c58aac12978531b93f\")\n );\n setChainWithDefaultRpcUrl(\n \"goerli\", Chain(\"Goerli\", 5, \"https://goerli.infura.io/v3/6770454bc6ea42c58aac12978531b93f\")\n );\n setChainWithDefaultRpcUrl(\n \"sepolia\", Chain(\"Sepolia\", 11155111, \"https://sepolia.infura.io/v3/6770454bc6ea42c58aac12978531b93f\")\n );\n setChainWithDefaultRpcUrl(\"optimism\", Chain(\"Optimism\", 10, \"https://mainnet.optimism.io\"));\n setChainWithDefaultRpcUrl(\"optimism_goerli\", Chain(\"Optimism Goerli\", 420, \"https://goerli.optimism.io\"));\n setChainWithDefaultRpcUrl(\"arbitrum_one\", Chain(\"Arbitrum One\", 42161, \"https://arb1.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\n \"arbitrum_one_goerli\", Chain(\"Arbitrum One Goerli\", 421613, \"https://goerli-rollup.arbitrum.io/rpc\")\n );\n setChainWithDefaultRpcUrl(\"arbitrum_nova\", Chain(\"Arbitrum Nova\", 42170, \"https://nova.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\"polygon\", Chain(\"Polygon\", 137, \"https://polygon-rpc.com\"));\n setChainWithDefaultRpcUrl(\"polygon_mumbai\", Chain(\"Polygon Mumbai\", 80001, \"https://rpc-mumbai.maticvigil.com\"));\n setChainWithDefaultRpcUrl(\"avalanche\", Chain(\"Avalanche\", 43114, \"https://api.avax.network/ext/bc/C/rpc\"));\n setChainWithDefaultRpcUrl(\n \"avalanche_fuji\", Chain(\"Avalanche Fuji\", 43113, \"https://api.avax-test.network/ext/bc/C/rpc\")\n );\n setChainWithDefaultRpcUrl(\"bnb_smart_chain\", Chain(\"BNB Smart Chain\", 56, \"https://bsc-dataseed1.binance.org\"));\n setChainWithDefaultRpcUrl(\"bnb_smart_chain_testnet\", Chain(\"BNB Smart Chain Testnet\", 97, \"https://data-seed-prebsc-1-s1.binance.org:8545\"));// forgefmt: disable-line\n setChainWithDefaultRpcUrl(\"gnosis_chain\", Chain(\"Gnosis Chain\", 100, \"https://rpc.gnosischain.com\"));\n }\n\n // set chain info, with priority to chainAlias' rpc url in foundry.toml\n function setChainWithDefaultRpcUrl(string memory chainAlias, Chain memory chain) private {\n string memory rpcUrl = chain.rpcUrl;\n defaultRpcUrls[chainAlias] = rpcUrl;\n chain.rpcUrl = \"\";\n setChain(chainAlias, chain);\n chain.rpcUrl = rpcUrl; // restore argument\n }\n}\n" - }, - "node_modules/forge-std/src/StdCheats.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {Vm} from \"./Vm.sol\";\n\nabstract contract StdCheatsSafe {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private gasMeteringOff;\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawTx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n // json value name = function\n string functionSig;\n bytes32 hash;\n // json value name = tx\n RawTx1559Detail txDetail;\n // json value name = type\n string opcode;\n }\n\n struct RawTx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n bytes gas;\n bytes nonce;\n address to;\n bytes txType;\n bytes value;\n }\n\n struct Tx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n bytes32 hash;\n Tx1559Detail txDetail;\n string opcode;\n }\n\n struct Tx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n uint256 gas;\n uint256 nonce;\n address to;\n uint256 txType;\n uint256 value;\n }\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct TxLegacy {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n string hash;\n string opcode;\n TxDetailLegacy transaction;\n }\n\n struct TxDetailLegacy {\n AccessList[] accessList;\n uint256 chainId;\n bytes data;\n address from;\n uint256 gas;\n uint256 gasPrice;\n bytes32 hash;\n uint256 nonce;\n bytes1 opcode;\n bytes32 r;\n bytes32 s;\n uint256 txType;\n address to;\n uint8 v;\n uint256 value;\n }\n\n struct AccessList {\n address accessAddress;\n bytes32[] storageKeys;\n }\n\n // Data structures to parse Receipt objects from the broadcast artifact.\n // The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawReceipt {\n bytes32 blockHash;\n bytes blockNumber;\n address contractAddress;\n bytes cumulativeGasUsed;\n bytes effectiveGasPrice;\n address from;\n bytes gasUsed;\n RawReceiptLog[] logs;\n bytes logsBloom;\n bytes status;\n address to;\n bytes32 transactionHash;\n bytes transactionIndex;\n }\n\n struct Receipt {\n bytes32 blockHash;\n uint256 blockNumber;\n address contractAddress;\n uint256 cumulativeGasUsed;\n uint256 effectiveGasPrice;\n address from;\n uint256 gasUsed;\n ReceiptLog[] logs;\n bytes logsBloom;\n uint256 status;\n address to;\n bytes32 transactionHash;\n uint256 transactionIndex;\n }\n\n // Data structures to parse the entire broadcast artifact, assuming the\n // transactions conform to EIP1559.\n\n struct EIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n Receipt[] receipts;\n uint256 timestamp;\n Tx1559[] transactions;\n TxReturn[] txReturns;\n }\n\n struct RawEIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n RawReceipt[] receipts;\n TxReturn[] txReturns;\n uint256 timestamp;\n RawTx1559[] transactions;\n }\n\n struct RawReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n bytes blockNumber;\n bytes data;\n bytes logIndex;\n bool removed;\n bytes32[] topics;\n bytes32 transactionHash;\n bytes transactionIndex;\n bytes transactionLogIndex;\n }\n\n struct ReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n uint256 blockNumber;\n bytes data;\n uint256 logIndex;\n bytes32[] topics;\n uint256 transactionIndex;\n uint256 transactionLogIndex;\n bool removed;\n }\n\n struct TxReturn {\n string internalType;\n string value;\n }\n\n function assumeNoPrecompiles(address addr) internal virtual {\n // Assembly required since `block.chainid` was introduced in 0.8.0.\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n assumeNoPrecompiles(addr, chainId);\n }\n\n function assumeNoPrecompiles(address addr, uint256 chainId) internal pure virtual {\n // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific\n // address), but the same rationale for excluding them applies so we include those too.\n\n // These should be present on all EVM-compatible chains.\n vm.assume(addr < address(0x1) || addr > address(0x9));\n\n // forgefmt: disable-start\n if (chainId == 10 || chainId == 420) {\n // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21\n vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));\n } else if (chainId == 42161 || chainId == 421613) {\n // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains\n vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));\n } else if (chainId == 43114 || chainId == 43113) {\n // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59\n vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));\n vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));\n vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));\n }\n // forgefmt: disable-end\n }\n\n function readEIP1559ScriptArtifact(string memory path)\n internal\n view\n virtual\n returns (EIP1559ScriptArtifact memory)\n {\n string memory data = vm.readFile(path);\n bytes memory parsedData = vm.parseJson(data);\n RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));\n EIP1559ScriptArtifact memory artifact;\n artifact.libraries = rawArtifact.libraries;\n artifact.path = rawArtifact.path;\n artifact.timestamp = rawArtifact.timestamp;\n artifact.pending = rawArtifact.pending;\n artifact.txReturns = rawArtifact.txReturns;\n artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);\n artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);\n return artifact;\n }\n\n function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {\n Tx1559[] memory txs = new Tx1559[](rawTxs.length);\n for (uint256 i; i < rawTxs.length; i++) {\n txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);\n }\n return txs;\n }\n\n function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {\n Tx1559 memory transaction;\n transaction.arguments = rawTx.arguments;\n transaction.contractName = rawTx.contractName;\n transaction.functionSig = rawTx.functionSig;\n transaction.hash = rawTx.hash;\n transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);\n transaction.opcode = rawTx.opcode;\n return transaction;\n }\n\n function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)\n internal\n pure\n virtual\n returns (Tx1559Detail memory)\n {\n Tx1559Detail memory txDetail;\n txDetail.data = rawDetail.data;\n txDetail.from = rawDetail.from;\n txDetail.to = rawDetail.to;\n txDetail.nonce = _bytesToUint(rawDetail.nonce);\n txDetail.txType = _bytesToUint(rawDetail.txType);\n txDetail.value = _bytesToUint(rawDetail.value);\n txDetail.gas = _bytesToUint(rawDetail.gas);\n txDetail.accessList = rawDetail.accessList;\n return txDetail;\n }\n\n function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".transactions\");\n RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));\n return rawToConvertedEIPTx1559s(rawTxs);\n }\n\n function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".transactions[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));\n return rawToConvertedEIPTx1559(rawTx);\n }\n\n // Analogous to readTransactions, but for receipts.\n function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".receipts\");\n RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));\n return rawToConvertedReceipts(rawReceipts);\n }\n\n function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".receipts[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));\n return rawToConvertedReceipt(rawReceipt);\n }\n\n function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {\n Receipt[] memory receipts = new Receipt[](rawReceipts.length);\n for (uint256 i; i < rawReceipts.length; i++) {\n receipts[i] = rawToConvertedReceipt(rawReceipts[i]);\n }\n return receipts;\n }\n\n function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {\n Receipt memory receipt;\n receipt.blockHash = rawReceipt.blockHash;\n receipt.to = rawReceipt.to;\n receipt.from = rawReceipt.from;\n receipt.contractAddress = rawReceipt.contractAddress;\n receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);\n receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);\n receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);\n receipt.status = _bytesToUint(rawReceipt.status);\n receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);\n receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);\n receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);\n receipt.logsBloom = rawReceipt.logsBloom;\n receipt.transactionHash = rawReceipt.transactionHash;\n return receipt;\n }\n\n function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)\n internal\n pure\n virtual\n returns (ReceiptLog[] memory)\n {\n ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);\n for (uint256 i; i < rawLogs.length; i++) {\n logs[i].logAddress = rawLogs[i].logAddress;\n logs[i].blockHash = rawLogs[i].blockHash;\n logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);\n logs[i].data = rawLogs[i].data;\n logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);\n logs[i].topics = rawLogs[i].topics;\n logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);\n logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);\n logs[i].removed = rawLogs[i].removed;\n }\n return logs;\n }\n\n // Deploy a contract by fetching the contract bytecode from\n // the artifacts directory\n // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`\n function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes): Deployment failed.\");\n }\n\n function deployCode(string memory what) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string): Deployment failed.\");\n }\n\n /// @dev deploy contract with value on construction\n function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes,uint256): Deployment failed.\");\n }\n\n function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,uint256): Deployment failed.\");\n }\n\n // creates a labeled address and the corresponding private key\n function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {\n privateKey = uint256(keccak256(abi.encodePacked(name)));\n addr = vm.addr(privateKey);\n vm.label(addr, name);\n }\n\n // creates a labeled address\n function makeAddr(string memory name) internal virtual returns (address addr) {\n (addr,) = makeAddrAndKey(name);\n }\n\n function deriveRememberKey(string memory mnemonic, uint32 index)\n internal\n virtual\n returns (address who, uint256 privateKey)\n {\n privateKey = vm.deriveKey(mnemonic, index);\n who = vm.rememberKey(privateKey);\n }\n\n function _bytesToUint(bytes memory b) private pure returns (uint256) {\n require(b.length <= 32, \"StdCheats _bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n function isFork() internal view virtual returns (bool status) {\n try vm.activeFork() {\n status = true;\n } catch (bytes memory) {}\n }\n\n modifier skipWhenForking() {\n if (!isFork()) {\n _;\n }\n }\n\n modifier skipWhenNotForking() {\n if (isFork()) {\n _;\n }\n }\n\n modifier noGasMetering() {\n vm.pauseGasMetering();\n // To prevent turning gas monitoring back on with nested functions that use this modifier,\n // we check if gasMetering started in the off position. If it did, we don't want to turn\n // it back on until we exit the top level function that used the modifier\n //\n // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.\n // funcA will have `gasStartedOff` as false, funcB will have it as true,\n // so we only turn metering back on at the end of the funcA\n bool gasStartedOff = gasMeteringOff;\n gasMeteringOff = true;\n\n _;\n\n // if gas metering was on when this modifier was called, turn it back on at the end\n if (!gasStartedOff) {\n gasMeteringOff = false;\n vm.resumeGasMetering();\n }\n }\n}\n\n// Wrappers around cheatcodes to avoid footguns\nabstract contract StdCheats is StdCheatsSafe {\n using stdStorage for StdStorage;\n\n StdStorage private stdstore;\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n // Skip forward or rewind time by the specified number of seconds\n function skip(uint256 time) internal virtual {\n vm.warp(block.timestamp + time);\n }\n\n function rewind(uint256 time) internal virtual {\n vm.warp(block.timestamp - time);\n }\n\n // Setup a prank from an address that has some ether\n function hoax(address who) internal virtual {\n vm.deal(who, 1 << 128);\n vm.prank(who);\n }\n\n function hoax(address who, uint256 give) internal virtual {\n vm.deal(who, give);\n vm.prank(who);\n }\n\n function hoax(address who, address origin) internal virtual {\n vm.deal(who, 1 << 128);\n vm.prank(who, origin);\n }\n\n function hoax(address who, address origin, uint256 give) internal virtual {\n vm.deal(who, give);\n vm.prank(who, origin);\n }\n\n // Start perpetual prank from an address that has some ether\n function startHoax(address who) internal virtual {\n vm.deal(who, 1 << 128);\n vm.startPrank(who);\n }\n\n function startHoax(address who, uint256 give) internal virtual {\n vm.deal(who, give);\n vm.startPrank(who);\n }\n\n // Start perpetual prank from an address that has some ether\n // tx.origin is set to the origin parameter\n function startHoax(address who, address origin) internal virtual {\n vm.deal(who, 1 << 128);\n vm.startPrank(who, origin);\n }\n\n function startHoax(address who, address origin, uint256 give) internal virtual {\n vm.deal(who, give);\n vm.startPrank(who, origin);\n }\n\n function changePrank(address who) internal virtual {\n vm.stopPrank();\n vm.startPrank(who);\n }\n\n // The same as Vm's `deal`\n // Use the alternative signature for ERC20 tokens\n function deal(address to, uint256 give) internal virtual {\n vm.deal(to, give);\n }\n\n // Set the balance of an account for any ERC20 token\n // Use the alternative signature to update `totalSupply`\n function deal(address token, address to, uint256 give) internal virtual {\n deal(token, to, give, false);\n }\n\n function deal(address token, address to, uint256 give, bool adjust) internal virtual {\n // get current balance\n (, bytes memory balData) = token.call(abi.encodeWithSelector(0x70a08231, to));\n uint256 prevBal = abi.decode(balData, (uint256));\n\n // update balance\n stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);\n\n // update total supply\n if (adjust) {\n (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0x18160ddd));\n uint256 totSup = abi.decode(totSupData, (uint256));\n if (give < prevBal) {\n totSup -= (prevBal - give);\n } else {\n totSup += (give - prevBal);\n }\n stdstore.target(token).sig(0x18160ddd).checked_write(totSup);\n }\n }\n}\n" - }, - "node_modules/forge-std/src/StdError.sol": { - "content": "// SPDX-License-Identifier: MIT\n// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdError {\n bytes public constant assertionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x01);\n bytes public constant arithmeticError = abi.encodeWithSignature(\"Panic(uint256)\", 0x11);\n bytes public constant divisionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x12);\n bytes public constant enumConversionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x21);\n bytes public constant encodeStorageError = abi.encodeWithSignature(\"Panic(uint256)\", 0x22);\n bytes public constant popError = abi.encodeWithSignature(\"Panic(uint256)\", 0x31);\n bytes public constant indexOOBError = abi.encodeWithSignature(\"Panic(uint256)\", 0x32);\n bytes public constant memOverflowError = abi.encodeWithSignature(\"Panic(uint256)\", 0x41);\n bytes public constant zeroVarError = abi.encodeWithSignature(\"Panic(uint256)\", 0x51);\n}\n" - }, - "node_modules/forge-std/src/StdJson.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n// Helpers for parsing and writing JSON files\n// To parse:\n// ```\n// using stdJson for string;\n// string memory json = vm.readFile(\"some_peth\");\n// json.parseUint(\"\");\n// ```\n// To write:\n// ```\n// using stdJson for string;\n// string memory json = \"deploymentArtifact\";\n// Contract contract = new Contract();\n// json.serialize(\"contractAddress\", address(contract));\n// json = json.serialize(\"deploymentTimes\", uint(1));\n// // store the stringified JSON to the 'json' variable we have been using as a key\n// // as we won't need it any longer\n// string memory json2 = \"finalArtifact\";\n// string memory final = json2.serialize(\"depArtifact\", json);\n// final.write(\"\");\n// ```\n\nlibrary stdJson {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {\n return vm.parseJson(json, key);\n }\n\n function readUint(string memory json, string memory key) internal pure returns (uint256) {\n return abi.decode(vm.parseJson(json, key), (uint256));\n }\n\n function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) {\n return abi.decode(vm.parseJson(json, key), (uint256[]));\n }\n\n function readInt(string memory json, string memory key) internal pure returns (int256) {\n return abi.decode(vm.parseJson(json, key), (int256));\n }\n\n function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) {\n return abi.decode(vm.parseJson(json, key), (int256[]));\n }\n\n function readBytes32(string memory json, string memory key) internal pure returns (bytes32) {\n return abi.decode(vm.parseJson(json, key), (bytes32));\n }\n\n function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) {\n return abi.decode(vm.parseJson(json, key), (bytes32[]));\n }\n\n function readString(string memory json, string memory key) internal pure returns (string memory) {\n return abi.decode(vm.parseJson(json, key), (string));\n }\n\n function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) {\n return abi.decode(vm.parseJson(json, key), (string[]));\n }\n\n function readAddress(string memory json, string memory key) internal pure returns (address) {\n return abi.decode(vm.parseJson(json, key), (address));\n }\n\n function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) {\n return abi.decode(vm.parseJson(json, key), (address[]));\n }\n\n function readBool(string memory json, string memory key) internal pure returns (bool) {\n return abi.decode(vm.parseJson(json, key), (bool));\n }\n\n function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) {\n return abi.decode(vm.parseJson(json, key), (bool[]));\n }\n\n function readBytes(string memory json, string memory key) internal pure returns (bytes memory) {\n return abi.decode(vm.parseJson(json, key), (bytes));\n }\n\n function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) {\n return abi.decode(vm.parseJson(json, key), (bytes[]));\n }\n\n function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bool[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function write(string memory jsonKey, string memory path) internal {\n vm.writeJson(jsonKey, path);\n }\n\n function write(string memory jsonKey, string memory path, string memory valueKey) internal {\n vm.writeJson(jsonKey, path, valueKey);\n }\n}\n" - }, - "node_modules/forge-std/src/StdMath.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdMath {\n int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;\n\n function abs(int256 a) internal pure returns (uint256) {\n // Required or it will fail when `a = type(int256).min`\n if (a == INT256_MIN) {\n return 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n }\n\n return uint256(a > 0 ? a : -a);\n }\n\n function delta(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a - b : b - a;\n }\n\n function delta(int256 a, int256 b) internal pure returns (uint256) {\n // a and b are of the same sign\n // this works thanks to two's complement, the left-most bit is the sign bit\n if ((a ^ b) > -1) {\n return delta(abs(a), abs(b));\n }\n\n // a and b are of opposite signs\n return abs(a) + abs(b);\n }\n\n function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n\n return absDelta * 1e18 / b;\n }\n\n function percentDelta(int256 a, int256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n uint256 absB = abs(b);\n\n return absDelta * 1e18 / absB;\n }\n}\n" - }, - "node_modules/forge-std/src/StdStorage.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {Vm} from \"./Vm.sol\";\n\nstruct StdStorage {\n mapping(address => mapping(bytes4 => mapping(bytes32 => uint256))) slots;\n mapping(address => mapping(bytes4 => mapping(bytes32 => bool))) finds;\n bytes32[] _keys;\n bytes4 _sig;\n uint256 _depth;\n address _target;\n bytes32 _set;\n}\n\nlibrary stdStorageSafe {\n event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);\n event WARNING_UninitedSlot(address who, uint256 slot);\n\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return bytes4(keccak256(bytes(sigStr)));\n }\n\n /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against\n // slot complexity:\n // if flat, will be bytes32(uint256(uint));\n // if map, will be keccak256(abi.encode(key, uint(slot)));\n // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));\n // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);\n function find(StdStorage storage self) internal returns (uint256) {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n // calldata to test against\n if (self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n vm.record();\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n (bytes32[] memory reads,) = vm.accesses(address(who));\n if (reads.length == 1) {\n bytes32 curr = vm.load(who, reads[0]);\n if (curr == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[0]));\n }\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[0]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[0]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n } else if (reads.length > 1) {\n for (uint256 i = 0; i < reads.length; i++) {\n bytes32 prev = vm.load(who, reads[i]);\n if (prev == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[i]));\n }\n // store\n vm.store(who, reads[i], bytes32(hex\"1337\"));\n bool success;\n bytes memory rdat;\n {\n (success, rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n if (success && fdat == bytes32(hex\"1337\")) {\n // we found which of the slots is the actual one\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[i]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[i]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n vm.store(who, reads[i], prev);\n break;\n }\n vm.store(who, reads[i], prev);\n }\n } else {\n require(false, \"stdStorage find(StdStorage): No storage use detected for target.\");\n }\n\n require(\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))],\n \"stdStorage find(StdStorage): Slot(s) not found.\"\n );\n\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n self._target = _target;\n return self;\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n self._sig = _sig;\n return self;\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n self._sig = sigs(_sig);\n return self;\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n self._keys.push(bytes32(uint256(uint160(who))));\n return self;\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n self._keys.push(bytes32(amt));\n return self;\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n self._keys.push(key);\n return self;\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n self._depth = _depth;\n return self;\n }\n\n function read(StdStorage storage self) private returns (bytes memory) {\n address t = self._target;\n uint256 s = find(self);\n return abi.encode(vm.load(t, bytes32(s)));\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return abi.decode(read(self), (bytes32));\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n int256 v = read_int(self);\n if (v == 0) return false;\n if (v == 1) return true;\n revert(\"stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.\");\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return abi.decode(read(self), (address));\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return abi.decode(read(self), (uint256));\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return abi.decode(read(self), (int256));\n }\n\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n\nlibrary stdStorage {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return stdStorageSafe.sigs(sigStr);\n }\n\n function find(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.find(self);\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n return stdStorageSafe.target(self, _target);\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, who);\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, amt);\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, key);\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n return stdStorageSafe.depth(self, _depth);\n }\n\n function checked_write(StdStorage storage self, address who) internal {\n checked_write(self, bytes32(uint256(uint160(who))));\n }\n\n function checked_write(StdStorage storage self, uint256 amt) internal {\n checked_write(self, bytes32(amt));\n }\n\n function checked_write(StdStorage storage self, bool write) internal {\n bytes32 t;\n /// @solidity memory-safe-assembly\n assembly {\n t := write\n }\n checked_write(self, t);\n }\n\n function checked_write(StdStorage storage self, bytes32 set) internal {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n if (!self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n find(self);\n }\n bytes32 slot = bytes32(self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]);\n\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n bytes32 curr = vm.load(who, slot);\n\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n vm.store(who, slot, set);\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return stdStorageSafe.read_bytes32(self);\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n return stdStorageSafe.read_bool(self);\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return stdStorageSafe.read_address(self);\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.read_uint(self);\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return stdStorageSafe.read_int(self);\n }\n\n // Private function so needs to be copied over\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n // Private function so needs to be copied over\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n" - }, - "node_modules/forge-std/src/StdUtils.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\n// TODO Remove import.\nimport {VmSafe} from \"./Vm.sol\";\n\nabstract contract StdUtils {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;\n\n uint256 private constant INT256_MIN_ABS =\n 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n uint256 private constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {\n require(min <= max, \"StdUtils bound(uint256,uint256,uint256): Max is less than min.\");\n // If x is between min and max, return x directly. This is to ensure that dictionary values\n // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188\n if (x >= min && x <= max) return x;\n\n uint256 size = max - min + 1;\n\n // If the value is 0, 1, 2, 3, warp that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.\n // This helps ensure coverage of the min/max values.\n if (x <= 3 && size > x) return min + x;\n if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);\n\n // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.\n if (x > max) {\n uint256 diff = x - max;\n uint256 rem = diff % size;\n if (rem == 0) return max;\n result = min + rem - 1;\n } else if (x < min) {\n uint256 diff = min - x;\n uint256 rem = diff % size;\n if (rem == 0) return min;\n result = max - rem + 1;\n }\n }\n\n function bound(uint256 x, uint256 min, uint256 max) internal view virtual returns (uint256 result) {\n result = _bound(x, min, max);\n console2_log(\"Bound Result\", result);\n }\n\n function bound(int256 x, int256 min, int256 max) internal view virtual returns (int256 result) {\n require(min <= max, \"StdUtils bound(int256,int256,int256): Max is less than min.\");\n\n // Shifting all int256 values to uint256 to use _bound function. The range of two types are:\n // int256 : -(2**255) ~ (2**255 - 1)\n // uint256: 0 ~ (2**256 - 1)\n // So, add 2**255, INT256_MIN_ABS to the integer values.\n //\n // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.\n // So, use `~uint256(x) + 1` instead.\n uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);\n uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);\n uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);\n\n uint256 y = _bound(_x, _min, _max);\n\n // To move it back to int256 value, subtract INT256_MIN_ABS at here.\n result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);\n console2_log(\"Bound result\", vm.toString(result));\n }\n\n /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce\n /// @notice adapated from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)\n function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {\n // forgefmt: disable-start\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))));\n if (nonce <= 0x7f) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))));\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= 2**8 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce))));\n if (nonce <= 2**16 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce))));\n if (nonce <= 2**24 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce))));\n // forgefmt: disable-end\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return addressFromLast20Bytes(\n keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce)))\n );\n }\n\n function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)\n internal\n pure\n virtual\n returns (address)\n {\n return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, initcodeHash)));\n }\n\n function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {\n require(b.length <= 32, \"StdUtils bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.\n\n function console2_log(string memory p0, uint256 p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n status;\n }\n\n function console2_log(string memory p0, string memory p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n status;\n }\n}\n" - }, - "node_modules/forge-std/src/Test.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\n// 💬 ABOUT\n// Standard Library's default Test\n\n// 🧩 MODULES\nimport {console} from \"./console.sol\";\nimport {console2} from \"./console2.sol\";\nimport {StdAssertions} from \"./StdAssertions.sol\";\nimport {StdChains} from \"./StdChains.sol\";\nimport {StdCheats} from \"./StdCheats.sol\";\nimport {stdError} from \"./StdError.sol\";\nimport {stdJson} from \"./StdJson.sol\";\nimport {stdMath} from \"./StdMath.sol\";\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {StdUtils} from \"./StdUtils.sol\";\nimport {Vm} from \"./Vm.sol\";\n\n// 📦 BOILERPLATE\nimport {TestBase} from \"./Base.sol\";\nimport {DSTest} from \"ds-test/test.sol\";\n\n// ⭐️ TEST\nabstract contract Test is DSTest, StdAssertions, StdChains, StdCheats, StdUtils, TestBase {\n// Note: IS_TEST() must return true.\n// Note: Must have failure system, https://github.com/dapphub/ds-test/blob/cd98eff28324bfac652e63a239a60632a761790b/src/test.sol#L39-L76.\n}\n" - }, - "node_modules/forge-std/src/Vm.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\n// Cheatcodes are marked as view/pure/none using the following rules:\n// 0. A call's observable behaviour includes its return value, logs, reverts and state writes,\n// 1. If you can influence a later call's observable behaviour, you're neither `view` nor `pure (you are modifying some state be it the EVM, interpreter, filesystem, etc),\n// 2. Otherwise if you can be influenced by an earlier call, or if reading some state, you're `view`,\n// 3. Otherwise you're `pure`.\n\ninterface VmSafe {\n struct Log {\n bytes32[] topics;\n bytes data;\n address emitter;\n }\n\n struct Rpc {\n string key;\n string url;\n }\n\n struct FsMetadata {\n bool isDir;\n bool isSymlink;\n uint256 length;\n bool readOnly;\n uint256 modified;\n uint256 accessed;\n uint256 created;\n }\n\n // Loads a storage slot from an address\n function load(address target, bytes32 slot) external view returns (bytes32 data);\n // Signs data\n function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);\n // Gets the address for a given private key\n function addr(uint256 privateKey) external pure returns (address keyAddr);\n // Gets the nonce of an account\n function getNonce(address account) external view returns (uint64 nonce);\n // Performs a foreign function call via the terminal\n function ffi(string[] calldata commandInput) external returns (bytes memory result);\n // Sets environment variables\n function setEnv(string calldata name, string calldata value) external;\n // Reads environment variables, (name) => (value)\n function envBool(string calldata name) external view returns (bool value);\n function envUint(string calldata name) external view returns (uint256 value);\n function envInt(string calldata name) external view returns (int256 value);\n function envAddress(string calldata name) external view returns (address value);\n function envBytes32(string calldata name) external view returns (bytes32 value);\n function envString(string calldata name) external view returns (string memory value);\n function envBytes(string calldata name) external view returns (bytes memory value);\n // Reads environment variables as arrays\n function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);\n function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);\n function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);\n function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);\n function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);\n function envString(string calldata name, string calldata delim) external view returns (string[] memory value);\n function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);\n // Read environment variables with default value\n function envOr(string calldata name, bool defaultValue) external returns (bool value);\n function envOr(string calldata name, uint256 defaultValue) external returns (uint256 value);\n function envOr(string calldata name, int256 defaultValue) external returns (int256 value);\n function envOr(string calldata name, address defaultValue) external returns (address value);\n function envOr(string calldata name, bytes32 defaultValue) external returns (bytes32 value);\n function envOr(string calldata name, string calldata defaultValue) external returns (string memory value);\n function envOr(string calldata name, bytes calldata defaultValue) external returns (bytes memory value);\n // Read environment variables as arrays with default value\n function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)\n external\n returns (bool[] memory value);\n function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)\n external\n returns (uint256[] memory value);\n function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)\n external\n returns (int256[] memory value);\n function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)\n external\n returns (address[] memory value);\n function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)\n external\n returns (bytes32[] memory value);\n function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)\n external\n returns (string[] memory value);\n function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)\n external\n returns (bytes[] memory value);\n // Records all storage reads and writes\n function record() external;\n // Gets all accessed reads and write slot from a recording session, for a given address\n function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);\n // Gets the _creation_ bytecode from an artifact file. Takes in the relative path to the json file\n function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);\n // Gets the _deployed_ bytecode from an artifact file. Takes in the relative path to the json file\n function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);\n // Labels an address in call traces\n function label(address account, string calldata newLabel) external;\n // Using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain\n function broadcast() external;\n // Has the next call (at this call depth only) create a transaction with the address provided as the sender that can later be signed and sent onchain\n function broadcast(address signer) external;\n // Has the next call (at this call depth only) create a transaction with the private key provided as the sender that can later be signed and sent onchain\n function broadcast(uint256 privateKey) external;\n // Using the address that calls the test contract, has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain\n function startBroadcast() external;\n // Has all subsequent calls (at this call depth only) create transactions with the address provided that can later be signed and sent onchain\n function startBroadcast(address signer) external;\n // Has all subsequent calls (at this call depth only) create transactions with the private key provided that can later be signed and sent onchain\n function startBroadcast(uint256 privateKey) external;\n // Stops collecting onchain transactions\n function stopBroadcast() external;\n // Reads the entire content of file to string\n function readFile(string calldata path) external view returns (string memory data);\n // Reads the entire content of file as binary. Path is relative to the project root.\n function readFileBinary(string calldata path) external view returns (bytes memory data);\n // Get the path of the current project root\n function projectRoot() external view returns (string memory path);\n // Get the metadata for a file/directory\n function fsMetadata(string calldata fileOrDir) external returns (FsMetadata memory metadata);\n // Reads next line of file to string\n function readLine(string calldata path) external view returns (string memory line);\n // Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.\n function writeFile(string calldata path, string calldata data) external;\n // Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.\n // Path is relative to the project root.\n function writeFileBinary(string calldata path, bytes calldata data) external;\n // Writes line to file, creating a file if it does not exist.\n function writeLine(string calldata path, string calldata data) external;\n // Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.\n function closeFile(string calldata path) external;\n // Removes file. This cheatcode will revert in the following situations, but is not limited to just these cases:\n // - Path points to a directory.\n // - The file doesn't exist.\n // - The user lacks permissions to remove the file.\n function removeFile(string calldata path) external;\n // Convert values to a string\n function toString(address value) external pure returns (string memory stringifiedValue);\n function toString(bytes calldata value) external pure returns (string memory stringifiedValue);\n function toString(bytes32 value) external pure returns (string memory stringifiedValue);\n function toString(bool value) external pure returns (string memory stringifiedValue);\n function toString(uint256 value) external pure returns (string memory stringifiedValue);\n function toString(int256 value) external pure returns (string memory stringifiedValue);\n // Convert values from a string\n function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);\n function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);\n function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);\n function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);\n function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);\n function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);\n // Record all the transaction logs\n function recordLogs() external;\n // Gets all the recorded logs\n function getRecordedLogs() external returns (Log[] memory logs);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path m/44'/60'/0'/0/{index}\n function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at {derivationPath}{index}\n function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)\n external\n pure\n returns (uint256 privateKey);\n // Adds a private key to the local forge wallet and returns the address\n function rememberKey(uint256 privateKey) external returns (address keyAddr);\n //\n // parseJson\n //\n // ----\n // In case the returned value is a JSON object, it's encoded as a ABI-encoded tuple. As JSON objects\n // don't have the notion of ordered, but tuples do, they JSON object is encoded with it's fields ordered in\n // ALPHABETICAL order. That means that in order to successfully decode the tuple, we need to define a tuple that\n // encodes the fields in the same order, which is alphabetical. In the case of Solidity structs, they are encoded\n // as tuples, with the attributes in the order in which they are defined.\n // For example: json = { 'a': 1, 'b': 0xa4tb......3xs}\n // a: uint256\n // b: address\n // To decode that json, we need to define a struct or a tuple as follows:\n // struct json = { uint256 a; address b; }\n // If we defined a json struct with the opposite order, meaning placing the address b first, it would try to\n // decode the tuple in that order, and thus fail.\n // ----\n // Given a string of JSON, return it as ABI-encoded\n function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);\n function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);\n\n // Serialize a key and value to a JSON object stored in-memory that can be later written to a file\n // It returns the stringified version of the specific JSON file up to that moment.\n function serializeBool(string calldata objectKey, string calldata valueKey, bool value)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address value)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)\n external\n returns (string memory json);\n\n function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)\n external\n returns (string memory json);\n\n //\n // writeJson\n //\n // ----\n // Write a serialized JSON object to a file. If the file exists, it will be overwritten.\n // Let's assume we want to write the following JSON to a file:\n //\n // { \"boolean\": true, \"number\": 342, \"object\": { \"title\": \"finally json serialization\" } }\n //\n // ```\n // string memory json1 = \"some key\";\n // vm.serializeBool(json1, \"boolean\", true);\n // vm.serializeBool(json1, \"number\", uint256(342));\n // json2 = \"some other key\";\n // string memory output = vm.serializeString(json2, \"title\", \"finally json serialization\");\n // string memory finalJson = vm.serialize(json1, \"object\", output);\n // vm.writeJson(finalJson, \"./output/example.json\");\n // ```\n // The critical insight is that every invocation of serialization will return the stringified version of the JSON\n // up to that point. That means we can construct arbitrary JSON objects and then use the return stringified version\n // to serialize them as values to another JSON object.\n //\n // json1 and json2 are simply keys used by the backend to keep track of the objects. So vm.serializeJson(json1,..)\n // will find the object in-memory that is keyed by \"some key\".\n function writeJson(string calldata json, string calldata path) external;\n // Write a serialized JSON object to an **existing** JSON file, replacing a value with key = \n // This is useful to replace a specific value of a JSON file, without having to parse the entire thing\n function writeJson(string calldata json, string calldata path, string calldata valueKey) external;\n // Returns the RPC url for the given alias\n function rpcUrl(string calldata rpcAlias) external view returns (string memory json);\n // Returns all rpc urls and their aliases `[alias, url][]`\n function rpcUrls() external view returns (string[2][] memory urls);\n // Returns all rpc urls and their aliases as structs.\n function rpcUrlStructs() external view returns (Rpc[] memory urls);\n // If the condition is false, discard this run's fuzz inputs and generate new ones.\n function assume(bool condition) external pure;\n // Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.\n function pauseGasMetering() external;\n // Resumes gas metering (i.e. gas usage is counted again). Noop if already on.\n function resumeGasMetering() external;\n}\n\ninterface Vm is VmSafe {\n // Sets block.timestamp\n function warp(uint256 newTimestamp) external;\n // Sets block.height\n function roll(uint256 newHeight) external;\n // Sets block.basefee\n function fee(uint256 newBasefee) external;\n // Sets block.difficulty\n function difficulty(uint256 newDifficulty) external;\n // Sets block.chainid\n function chainId(uint256 newChainId) external;\n // Stores a value to an address' storage slot.\n function store(address target, bytes32 slot, bytes32 value) external;\n // Sets the nonce of an account; must be higher than the current nonce of the account\n function setNonce(address account, uint64 newNonce) external;\n // Sets the *next* call's msg.sender to be the input address\n function prank(address msgSender) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called\n function startPrank(address msgSender) external;\n // Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input\n function prank(address msgSender, address txOrigin) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input\n function startPrank(address msgSender, address txOrigin) external;\n // Resets subsequent calls' msg.sender to be `address(this)`\n function stopPrank() external;\n // Sets an address' balance\n function deal(address account, uint256 newBalance) external;\n // Sets an address' code\n function etch(address target, bytes calldata newRuntimeBytecode) external;\n // Expects an error on next call\n function expectRevert(bytes calldata revertData) external;\n function expectRevert(bytes4 revertData) external;\n function expectRevert() external;\n // Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData).\n // Call this function, then emit an event, then call a function. Internally after the call, we check if\n // logs were emitted in the expected order with the expected topics and data (as specified by the booleans)\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)\n external;\n // Mocks a call to an address, returning specified data.\n // Calldata can either be strict or a partial match, e.g. if you only\n // pass a Solidity selector to the expected calldata, then the entire Solidity\n // function will be mocked.\n function mockCall(address callee, bytes calldata data, bytes calldata returnData) external;\n // Mocks a call to an address with a specific msg.value, returning specified data.\n // Calldata match takes precedence over msg.value in case of ambiguity.\n function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external;\n // Clears all mocked calls\n function clearMockedCalls() external;\n // Expects a call to an address with the specified calldata.\n // Calldata can either be a strict or a partial match\n function expectCall(address callee, bytes calldata data) external;\n // Expects a call to an address with the specified msg.value and calldata\n function expectCall(address callee, uint256 msgValue, bytes calldata data) external;\n // Sets block.coinbase\n function coinbase(address newCoinbase) external;\n // Snapshot the current state of the evm.\n // Returns the id of the snapshot that was created.\n // To revert a snapshot use `revertTo`\n function snapshot() external returns (uint256 snapshotId);\n // Revert the state of the EVM to a previous snapshot\n // Takes the snapshot id to revert to.\n // This deletes the snapshot and all snapshots taken after the given snapshot id.\n function revertTo(uint256 snapshotId) external returns (bool success);\n // Creates a new fork with the given endpoint and block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before the transaction,\n // and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates _and_ also selects new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before\n // the transaction, returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.\n function selectFork(uint256 forkId) external;\n /// Returns the identifier of the currently active fork. Reverts if no fork is currently active.\n function activeFork() external view returns (uint256 forkId);\n // Updates the currently active fork to given block number\n // This is similar to `roll` but for the currently active fork\n function rollFork(uint256 blockNumber) external;\n // Updates the currently active fork to given transaction\n // this will `rollFork` with the number of the block the transaction was mined in and replays all transaction mined before it in the block\n function rollFork(bytes32 txHash) external;\n // Updates the given fork to given block number\n function rollFork(uint256 forkId, uint256 blockNumber) external;\n // Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block\n function rollFork(uint256 forkId, bytes32 txHash) external;\n // Marks that the account(s) should use persistent storage across fork swaps in a multifork setup\n // Meaning, changes made to the state of this account will be kept when switching forks\n function makePersistent(address account) external;\n function makePersistent(address account0, address account1) external;\n function makePersistent(address account0, address account1, address account2) external;\n function makePersistent(address[] calldata accounts) external;\n // Revokes persistent status from the address, previously added via `makePersistent`\n function revokePersistent(address account) external;\n function revokePersistent(address[] calldata accounts) external;\n // Returns true if the account is marked as persistent\n function isPersistent(address account) external view returns (bool persistent);\n // In forking mode, explicitly grant the given address cheatcode access\n function allowCheatcodes(address account) external;\n // Fetches the given transaction from the active fork and executes it on the current state\n function transact(bytes32 txHash) external;\n // Fetches the given transaction from the given fork and executes it on the current state\n function transact(uint256 forkId, bytes32 txHash) external;\n}\n" - }, - "node_modules/forge-std/src/console.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nlibrary console {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int)\", p0));\n }\n\n function logUint(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint)\", p0, p1));\n }\n\n function log(uint p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string)\", p0, p1));\n }\n\n function log(uint p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool)\", p0, p1));\n }\n\n function log(uint p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address)\", p0, p1));\n }\n\n function log(string memory p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - }, - "node_modules/forge-std/src/console2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\n/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should\n/// use `int256` and `uint256`. This modified version fixes that. This version is recommended\n/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in\n/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.\n/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178\nlibrary console2 {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function logUint(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function log(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint256 p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256)\", p0, p1));\n }\n\n function log(uint256 p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string)\", p0, p1));\n }\n\n function log(uint256 p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool)\", p0, p1));\n }\n\n function log(uint256 p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address)\", p0, p1));\n }\n\n function log(string memory p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n }\n\n function log(string memory p0, int256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,int256)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - } - }, - "settings": { - "remappings": [ - "@openzeppelin/=node_modules/@openzeppelin/", - "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", - "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", - "@rari-capital/=node_modules/@rari-capital/", - "@rari-capital/solmate/=node_modules/@rari-capital/solmate/", - "ds-test/=node_modules/ds-test/src/", - "forge-std/=node_modules/forge-std/src/" - ], - "optimizer": { - "enabled": true, - "runs": 999999 - }, - "metadata": { - "bytecodeHash": "none" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "storageLayout", - "devdoc", - "userdoc" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/solcInputs/86f4d300b3e19ace2c129703d85e47d6.json b/packages/contracts-bedrock/deployments/goerli/solcInputs/86f4d300b3e19ace2c129703d85e47d6.json deleted file mode 100644 index f1c72d28761e..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/solcInputs/86f4d300b3e19ace2c129703d85e47d6.json +++ /dev/null @@ -1,552 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/L1/L1CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismPortal } from \"./OptimismPortal.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1CrossDomainMessenger\n * @notice The L1CrossDomainMessenger is a message passing interface between L1 and L2 responsible\n * for sending and receiving data on the L1 side. Users are encouraged to use this\n * interface instead of interacting with lower-level contracts directly.\n */\ncontract L1CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @notice Address of the OptimismPortal.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @custom:semver 1.4.0\n *\n * @param _portal Address of the OptimismPortal contract on this network.\n */\n constructor(OptimismPortal _portal)\n Semver(1, 4, 0)\n CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER)\n {\n PORTAL = _portal;\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n PORTAL.depositTransaction{ value: _value }(_to, _value, _gasLimit, false, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return msg.sender == address(PORTAL) && PORTAL.l2Sender() == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(PORTAL);\n }\n}\n" - }, - "contracts/L1/L1ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { L2ERC721Bridge } from \"../L2/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 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.1.1\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, 1, 1)\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 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), \"L1ERC721Bridge: 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(OTHER_BRIDGE, message, _minGasLimit);\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L1/L1StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1StandardBridge\n * @notice The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L1, it will be escrowed within this\n * contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was\n * stored within this contract. After Bedrock, ETH is instead stored inside the\n * OptimismPortal contract.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L1StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a deposit of ETH from L1 into L2 is initiated.\n *\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of ETH deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ETHDepositInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal of ETH from L2 to L1 is finalized.\n *\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of ETH withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 withdrawal is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _messenger Address of the L1CrossDomainMessenger.\n */\n constructor(address payable _messenger)\n Semver(1, 1, 0)\n StandardBridge(_messenger, payable(Predeploys.L2_STANDARD_BRIDGE))\n {}\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n */\n receive() external payable override onlyEOA {\n _initiateETHDeposit(msg.sender, msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into the sender's account on L2.\n *\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETH(uint32 _minGasLimit, bytes calldata _extraData) external payable onlyEOA {\n _initiateETHDeposit(msg.sender, msg.sender, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into a target account on L2.\n * Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will\n * be locked in the L2StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n *\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable {\n _initiateETHDeposit(msg.sender, _to, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into the sender's account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20(\n address _l1Token,\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual onlyEOA {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into a target account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20To(\n address _l1Token,\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ETH from L2.\n *\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of ETH to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeETHWithdrawal(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable {\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ERC20 tokens from L2.\n *\n * @param _l1Token Address of the token on L1.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of the ERC20 to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeERC20Withdrawal(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external {\n finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L2 bridge contract.\n *\n * @return Address of the corresponding L2 bridge contract.\n */\n function l2TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @notice Internal function for initiating an ETH deposit.\n *\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateETHDeposit(\n address _from,\n address _to,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n _initiateBridgeETH(_from, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Internal function for initiating an ERC20 deposit.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateERC20Deposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n _initiateBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Emits the legacy ETHDepositInitiated event followed by the ETHBridgeInitiated event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ETHDepositInitiated(_from, _to, _amount, _extraData);\n super._emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ETHWithdrawalFinalized event followed by the ETHBridgeFinalized\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ETHWithdrawalFinalized(_from, _to, _amount, _extraData);\n super._emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ERC20DepositInitiated event followed by the ERC20BridgeInitiated\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ERC20DepositInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ERC20WithdrawalFinalized event followed by the ERC20BridgeFinalized\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ERC20WithdrawalFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/L1/L2OutputOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\n/**\n * @custom:proxied\n * @title L2OutputOracle\n * @notice The L2OutputOracle contains an array of L2 state outputs, where each output is a\n * commitment to the state of the L2 chain. Other contracts like the OptimismPortal use\n * these outputs to verify information about the state of L2.\n */\ncontract L2OutputOracle is Initializable, Semver {\n /**\n * @notice The interval in L2 blocks at which checkpoints must be submitted. Although this is\n * immutable, it can safely be modified by upgrading the implementation contract.\n */\n uint256 public immutable SUBMISSION_INTERVAL;\n\n /**\n * @notice The time between L2 blocks in seconds. Once set, this value MUST NOT be modified.\n */\n uint256 public immutable L2_BLOCK_TIME;\n\n /**\n * @notice The address of the challenger. Can be updated via upgrade.\n */\n address public immutable CHALLENGER;\n\n /**\n * @notice The address of the proposer. Can be updated via upgrade.\n */\n address public immutable PROPOSER;\n\n /**\n * @notice Minimum time (in seconds) that must elapse before a withdrawal can be finalized.\n */\n uint256 public immutable FINALIZATION_PERIOD_SECONDS;\n\n /**\n * @notice The number of the first L2 block recorded in this contract.\n */\n uint256 public startingBlockNumber;\n\n /**\n * @notice The timestamp of the first L2 block recorded in this contract.\n */\n uint256 public startingTimestamp;\n\n /**\n * @notice Array of L2 output proposals.\n */\n Types.OutputProposal[] internal l2Outputs;\n\n /**\n * @notice Emitted when an output is proposed.\n *\n * @param outputRoot The output root.\n * @param l2OutputIndex The index of the output in the l2Outputs array.\n * @param l2BlockNumber The L2 block number of the output root.\n * @param l1Timestamp The L1 timestamp when proposed.\n */\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n /**\n * @notice Emitted when outputs are deleted.\n *\n * @param prevNextOutputIndex Next L2 output index before the deletion.\n * @param newNextOutputIndex Next L2 output index after the deletion.\n */\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n /**\n * @custom:semver 1.3.0\n *\n * @param _submissionInterval Interval in blocks at which checkpoints must be submitted.\n * @param _l2BlockTime The time per L2 block, in seconds.\n * @param _startingBlockNumber The number of the first L2 block.\n * @param _startingTimestamp The timestamp of the first L2 block.\n * @param _proposer The address of the proposer.\n * @param _challenger The address of the challenger.\n */\n constructor(\n uint256 _submissionInterval,\n uint256 _l2BlockTime,\n uint256 _startingBlockNumber,\n uint256 _startingTimestamp,\n address _proposer,\n address _challenger,\n uint256 _finalizationPeriodSeconds\n ) Semver(1, 3, 0) {\n require(_l2BlockTime > 0, \"L2OutputOracle: L2 block time must be greater than 0\");\n require(\n _submissionInterval > 0,\n \"L2OutputOracle: submission interval must be greater than 0\"\n );\n\n SUBMISSION_INTERVAL = _submissionInterval;\n L2_BLOCK_TIME = _l2BlockTime;\n PROPOSER = _proposer;\n CHALLENGER = _challenger;\n FINALIZATION_PERIOD_SECONDS = _finalizationPeriodSeconds;\n\n initialize(_startingBlockNumber, _startingTimestamp);\n }\n\n /**\n * @notice Initializer.\n *\n * @param _startingBlockNumber Block number for the first recoded L2 block.\n * @param _startingTimestamp Timestamp for the first recoded L2 block.\n */\n function initialize(uint256 _startingBlockNumber, uint256 _startingTimestamp)\n public\n initializer\n {\n require(\n _startingTimestamp <= block.timestamp,\n \"L2OutputOracle: starting L2 timestamp must be less than current time\"\n );\n\n startingTimestamp = _startingTimestamp;\n startingBlockNumber = _startingBlockNumber;\n }\n\n /**\n * @notice Deletes all output proposals after and including the proposal that corresponds to\n * the given output index. Only the challenger address can delete outputs.\n *\n * @param _l2OutputIndex Index of the first L2 output to be deleted. All outputs after this\n * output will also be deleted.\n */\n // solhint-disable-next-line ordering\n function deleteL2Outputs(uint256 _l2OutputIndex) external {\n require(\n msg.sender == CHALLENGER,\n \"L2OutputOracle: only the challenger address can delete outputs\"\n );\n\n // Make sure we're not *increasing* the length of the array.\n require(\n _l2OutputIndex < l2Outputs.length,\n \"L2OutputOracle: cannot delete outputs after the latest output index\"\n );\n\n // Do not allow deleting any outputs that have already been finalized.\n require(\n block.timestamp - l2Outputs[_l2OutputIndex].timestamp < FINALIZATION_PERIOD_SECONDS,\n \"L2OutputOracle: cannot delete outputs that have already been finalized\"\n );\n\n uint256 prevNextL2OutputIndex = nextOutputIndex();\n\n // Use assembly to delete the array elements because Solidity doesn't allow it.\n assembly {\n sstore(l2Outputs.slot, _l2OutputIndex)\n }\n\n emit OutputsDeleted(prevNextL2OutputIndex, _l2OutputIndex);\n }\n\n /**\n * @notice Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp\n * must be equal to the current value returned by `nextTimestamp()` in order to be\n * accepted. This function may only be called by the Proposer.\n *\n * @param _outputRoot The L2 output of the checkpoint block.\n * @param _l2BlockNumber The L2 block number that resulted in _outputRoot.\n * @param _l1BlockHash A block hash which must be included in the current chain.\n * @param _l1BlockNumber The block number with the specified block hash.\n */\n function proposeL2Output(\n bytes32 _outputRoot,\n uint256 _l2BlockNumber,\n bytes32 _l1BlockHash,\n uint256 _l1BlockNumber\n ) external payable {\n require(\n msg.sender == PROPOSER,\n \"L2OutputOracle: only the proposer address can propose new outputs\"\n );\n\n require(\n _l2BlockNumber == nextBlockNumber(),\n \"L2OutputOracle: block number must be equal to next expected block number\"\n );\n\n require(\n computeL2Timestamp(_l2BlockNumber) < block.timestamp,\n \"L2OutputOracle: cannot propose L2 output in the future\"\n );\n\n require(\n _outputRoot != bytes32(0),\n \"L2OutputOracle: L2 output proposal cannot be the zero hash\"\n );\n\n if (_l1BlockHash != bytes32(0)) {\n // This check allows the proposer to propose an output based on a given L1 block,\n // without fear that it will be reorged out.\n // It will also revert if the blockheight provided is more than 256 blocks behind the\n // chain tip (as the hash will return as zero). This does open the door to a griefing\n // attack in which the proposer's submission is censored until the block is no longer\n // retrievable, if the proposer is experiencing this attack it can simply leave out the\n // blockhash value, and delay submission until it is confident that the L1 block is\n // finalized.\n require(\n blockhash(_l1BlockNumber) == _l1BlockHash,\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n }\n\n emit OutputProposed(_outputRoot, nextOutputIndex(), _l2BlockNumber, block.timestamp);\n\n l2Outputs.push(\n Types.OutputProposal({\n outputRoot: _outputRoot,\n timestamp: uint128(block.timestamp),\n l2BlockNumber: uint128(_l2BlockNumber)\n })\n );\n }\n\n /**\n * @notice Returns an output by index. Exists because Solidity's array access will return a\n * tuple instead of a struct.\n *\n * @param _l2OutputIndex Index of the output to return.\n *\n * @return The output at the given index.\n */\n function getL2Output(uint256 _l2OutputIndex)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[_l2OutputIndex];\n }\n\n /**\n * @notice Returns the index of the L2 output that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return Index of the first checkpoint that commits to the given L2 block number.\n */\n function getL2OutputIndexAfter(uint256 _l2BlockNumber) public view returns (uint256) {\n // Make sure an output for this block number has actually been proposed.\n require(\n _l2BlockNumber <= latestBlockNumber(),\n \"L2OutputOracle: cannot get output for a block that has not been proposed\"\n );\n\n // Make sure there's at least one output proposed.\n require(\n l2Outputs.length > 0,\n \"L2OutputOracle: cannot get output as no outputs have been proposed yet\"\n );\n\n // Find the output via binary search, guaranteed to exist.\n uint256 lo = 0;\n uint256 hi = l2Outputs.length;\n while (lo < hi) {\n uint256 mid = (lo + hi) / 2;\n if (l2Outputs[mid].l2BlockNumber < _l2BlockNumber) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n return lo;\n }\n\n /**\n * @notice Returns the L2 output proposal that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return First checkpoint that commits to the given L2 block number.\n */\n function getL2OutputAfter(uint256 _l2BlockNumber)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[getL2OutputIndexAfter(_l2BlockNumber)];\n }\n\n /**\n * @notice Returns the number of outputs that have been proposed. Will revert if no outputs\n * have been proposed yet.\n *\n * @return The number of outputs that have been proposed.\n */\n function latestOutputIndex() external view returns (uint256) {\n return l2Outputs.length - 1;\n }\n\n /**\n * @notice Returns the index of the next output to be proposed.\n *\n * @return The index of the next output to be proposed.\n */\n function nextOutputIndex() public view returns (uint256) {\n return l2Outputs.length;\n }\n\n /**\n * @notice Returns the block number of the latest submitted L2 output proposal. If no proposals\n * been submitted yet then this function will return the starting block number.\n *\n * @return Latest submitted L2 block number.\n */\n function latestBlockNumber() public view returns (uint256) {\n return\n l2Outputs.length == 0\n ? startingBlockNumber\n : l2Outputs[l2Outputs.length - 1].l2BlockNumber;\n }\n\n /**\n * @notice Computes the block number of the next L2 block that needs to be checkpointed.\n *\n * @return Next L2 block number.\n */\n function nextBlockNumber() public view returns (uint256) {\n return latestBlockNumber() + SUBMISSION_INTERVAL;\n }\n\n /**\n * @notice Returns the L2 timestamp corresponding to a given L2 block number.\n *\n * @param _l2BlockNumber The L2 block number of the target block.\n *\n * @return L2 timestamp of the given block.\n */\n function computeL2Timestamp(uint256 _l2BlockNumber) public view returns (uint256) {\n return startingTimestamp + ((_l2BlockNumber - startingBlockNumber) * L2_BLOCK_TIME);\n }\n}\n" - }, - "contracts/L1/OptimismPortal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { L2OutputOracle } from \"./L2OutputOracle.sol\";\nimport { SystemConfig } from \"./SystemConfig.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { SecureMerkleTrie } from \"../libraries/trie/SecureMerkleTrie.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ResourceMetering } from \"./ResourceMetering.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title OptimismPortal\n * @notice The OptimismPortal is a low-level contract responsible for passing messages between L1\n * and L2. Messages sent directly to the OptimismPortal have no form of replayability.\n * Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface.\n */\ncontract OptimismPortal is Initializable, ResourceMetering, Semver {\n /**\n * @notice Represents a proven withdrawal.\n *\n * @custom:field outputRoot Root of the L2 output this was proven against.\n * @custom:field timestamp Timestamp at whcih the withdrawal was proven.\n * @custom:field l2OutputIndex Index of the output this was proven against.\n */\n struct ProvenWithdrawal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2OutputIndex;\n }\n\n /**\n * @notice Version of the deposit event.\n */\n uint256 internal constant DEPOSIT_VERSION = 0;\n\n /**\n * @notice The L2 gas limit set when eth is deposited using the receive() function.\n */\n uint64 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Address of the L2OutputOracle contract.\n */\n L2OutputOracle public immutable L2_ORACLE;\n\n /**\n * @notice Address of the SystemConfig contract.\n */\n SystemConfig public immutable SYSTEM_CONFIG;\n\n /**\n * @notice Address that has the ability to pause and unpause withdrawals.\n */\n address public immutable GUARDIAN;\n\n /**\n * @notice Address of the L2 account which initiated a withdrawal in this transaction. If the\n * of this variable is the default L2 sender address, then we are NOT inside of a call\n * to finalizeWithdrawalTransaction.\n */\n address public l2Sender;\n\n /**\n * @notice A list of withdrawal hashes which have been successfully finalized.\n */\n mapping(bytes32 => bool) public finalizedWithdrawals;\n\n /**\n * @notice A mapping of withdrawal hashes to `ProvenWithdrawal` data.\n */\n mapping(bytes32 => ProvenWithdrawal) public provenWithdrawals;\n\n /**\n * @notice Determines if cross domain messaging is paused. When set to true,\n * withdrawals are paused. This may be removed in the future.\n */\n bool public paused;\n\n /**\n * @notice Emitted when a transaction is deposited from L1 to L2. The parameters of this event\n * are read by the rollup node and used to derive deposit transactions on L2.\n *\n * @param from Address that triggered the deposit transaction.\n * @param to Address that the deposit transaction is directed to.\n * @param version Version of this deposit transaction event.\n * @param opaqueData ABI encoded deposit data to be parsed off-chain.\n */\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is proven.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n */\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is finalized.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n * @param success Whether the withdrawal transaction was successful.\n */\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n\n /**\n * @notice Emitted when the pause is triggered.\n *\n * @param account Address of the account triggering the pause.\n */\n event Paused(address account);\n\n /**\n * @notice Emitted when the pause is lifted.\n *\n * @param account Address of the account triggering the unpause.\n */\n event Unpaused(address account);\n\n /**\n * @notice Reverts when paused.\n */\n modifier whenNotPaused() {\n require(paused == false, \"OptimismPortal: paused\");\n _;\n }\n\n /**\n * @custom:semver 1.6.0\n *\n * @param _l2Oracle Address of the L2OutputOracle contract.\n * @param _guardian Address that can pause deposits and withdrawals.\n * @param _paused Sets the contract's pausability state.\n * @param _config Address of the SystemConfig contract.\n */\n constructor(\n L2OutputOracle _l2Oracle,\n address _guardian,\n bool _paused,\n SystemConfig _config\n ) Semver(1, 6, 0) {\n L2_ORACLE = _l2Oracle;\n GUARDIAN = _guardian;\n SYSTEM_CONFIG = _config;\n initialize(_paused);\n }\n\n /**\n * @notice Initializer.\n */\n function initialize(bool _paused) public initializer {\n l2Sender = Constants.DEFAULT_L2_SENDER;\n paused = _paused;\n __ResourceMetering_init();\n }\n\n /**\n * @notice Pause deposits and withdrawals.\n */\n function pause() external {\n require(msg.sender == GUARDIAN, \"OptimismPortal: only guardian can pause\");\n paused = true;\n emit Paused(msg.sender);\n }\n\n /**\n * @notice Unpause deposits and withdrawals.\n */\n function unpause() external {\n require(msg.sender == GUARDIAN, \"OptimismPortal: only guardian can unpause\");\n paused = false;\n emit Unpaused(msg.sender);\n }\n\n /**\n * @notice Computes the minimum gas limit for a deposit. The minimum gas limit\n * linearly increases based on the size of the calldata. This is to prevent\n * users from creating L2 resource usage without paying for it. This function\n * can be used when interacting with the portal to ensure forwards compatibility.\n *\n */\n function minimumGasLimit(uint64 _byteCount) public pure returns (uint64) {\n return _byteCount * 16 + 21000;\n }\n\n /**\n * @notice Accepts value so that users can send ETH directly to this contract and have the\n * funds be deposited to their address on L2. This is intended as a convenience\n * function for EOAs. Contracts should call the depositTransaction() function directly\n * otherwise any deposited funds will be lost due to address aliasing.\n */\n // solhint-disable-next-line ordering\n receive() external payable {\n depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes(\"\"));\n }\n\n /**\n * @notice Accepts ETH value without triggering a deposit to L2. This function mainly exists\n * for the sake of the migration between the legacy Optimism system and Bedrock.\n */\n function donateETH() external payable {\n // Intentionally empty.\n }\n\n /**\n * @notice Getter for the resource config. Used internally by the ResourceMetering\n * contract. The SystemConfig is the source of truth for the resource config.\n *\n * @return ResourceMetering.ResourceConfig\n */\n function _resourceConfig()\n internal\n view\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return SYSTEM_CONFIG.resourceConfig();\n }\n\n /**\n * @notice Proves a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n * @param _l2OutputIndex L2 output index to prove against.\n * @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root.\n * @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract.\n */\n function proveWithdrawalTransaction(\n Types.WithdrawalTransaction memory _tx,\n uint256 _l2OutputIndex,\n Types.OutputRootProof calldata _outputRootProof,\n bytes[] calldata _withdrawalProof\n ) external whenNotPaused {\n // Prevent users from creating a deposit transaction where this address is the message\n // sender on L2. Because this is checked here, we do not need to check again in\n // `finalizeWithdrawalTransaction`.\n require(\n _tx.target != address(this),\n \"OptimismPortal: you cannot send messages to the portal contract\"\n );\n\n // Get the output root and load onto the stack to prevent multiple mloads. This will\n // revert if there is no output root for the given block number.\n bytes32 outputRoot = L2_ORACLE.getL2Output(_l2OutputIndex).outputRoot;\n\n // Verify that the output root can be generated with the elements in the proof.\n require(\n outputRoot == Hashing.hashOutputRootProof(_outputRootProof),\n \"OptimismPortal: invalid output root proof\"\n );\n\n // Load the ProvenWithdrawal into memory, using the withdrawal hash as a unique identifier.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // We generally want to prevent users from proving the same withdrawal multiple times\n // because each successive proof will update the timestamp. A malicious user can take\n // advantage of this to prevent other users from finalizing their withdrawal. However,\n // since withdrawals are proven before an output root is finalized, we need to allow users\n // to re-prove their withdrawal only in the case that the output root for their specified\n // output index has been updated.\n require(\n provenWithdrawal.timestamp == 0 ||\n L2_ORACLE.getL2Output(provenWithdrawal.l2OutputIndex).outputRoot !=\n provenWithdrawal.outputRoot,\n \"OptimismPortal: withdrawal hash has already been proven\"\n );\n\n // Compute the storage slot of the withdrawal hash in the L2ToL1MessagePasser contract.\n // Refer to the Solidity documentation for more information on how storage layouts are\n // computed for mappings.\n bytes32 storageKey = keccak256(\n abi.encode(\n withdrawalHash,\n uint256(0) // The withdrawals mapping is at the first slot in the layout.\n )\n );\n\n // Verify that the hash of this withdrawal was stored in the L2toL1MessagePasser contract\n // on L2. If this is true, under the assumption that the SecureMerkleTrie does not have\n // bugs, then we know that this withdrawal was actually triggered on L2 and can therefore\n // be relayed on L1.\n require(\n SecureMerkleTrie.verifyInclusionProof(\n abi.encode(storageKey),\n hex\"01\",\n _withdrawalProof,\n _outputRootProof.messagePasserStorageRoot\n ),\n \"OptimismPortal: invalid withdrawal inclusion proof\"\n );\n\n // Designate the withdrawalHash as proven by storing the `outputRoot`, `timestamp`, and\n // `l2BlockNumber` in the `provenWithdrawals` mapping. A `withdrawalHash` can only be\n // proven once unless it is submitted again with a different outputRoot.\n provenWithdrawals[withdrawalHash] = ProvenWithdrawal({\n outputRoot: outputRoot,\n timestamp: uint128(block.timestamp),\n l2OutputIndex: uint128(_l2OutputIndex)\n });\n\n // Emit a `WithdrawalProven` event.\n emit WithdrawalProven(withdrawalHash, _tx.sender, _tx.target);\n }\n\n /**\n * @notice Finalizes a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n */\n function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx)\n external\n whenNotPaused\n {\n // Make sure that the l2Sender has not yet been set. The l2Sender is set to a value other\n // than the default value when a withdrawal transaction is being finalized. This check is\n // a defacto reentrancy guard.\n require(\n l2Sender == Constants.DEFAULT_L2_SENDER,\n \"OptimismPortal: can only trigger one withdrawal per transaction\"\n );\n\n // Grab the proven withdrawal from the `provenWithdrawals` map.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // A withdrawal can only be finalized if it has been proven. We know that a withdrawal has\n // been proven at least once when its timestamp is non-zero. Unproven withdrawals will have\n // a timestamp of zero.\n require(\n provenWithdrawal.timestamp != 0,\n \"OptimismPortal: withdrawal has not been proven yet\"\n );\n\n // As a sanity check, we make sure that the proven withdrawal's timestamp is greater than\n // starting timestamp inside the L2OutputOracle. Not strictly necessary but extra layer of\n // safety against weird bugs in the proving step.\n require(\n provenWithdrawal.timestamp >= L2_ORACLE.startingTimestamp(),\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n\n // A proven withdrawal must wait at least the finalization period before it can be\n // finalized. This waiting period can elapse in parallel with the waiting period for the\n // output the withdrawal was proven against. In effect, this means that the minimum\n // withdrawal time is proposal submission time + finalization period.\n require(\n _isFinalizationPeriodElapsed(provenWithdrawal.timestamp),\n \"OptimismPortal: proven withdrawal finalization period has not elapsed\"\n );\n\n // Grab the OutputProposal from the L2OutputOracle, will revert if the output that\n // corresponds to the given index has not been proposed yet.\n Types.OutputProposal memory proposal = L2_ORACLE.getL2Output(\n provenWithdrawal.l2OutputIndex\n );\n\n // Check that the output root that was used to prove the withdrawal is the same as the\n // current output root for the given output index. An output root may change if it is\n // deleted by the challenger address and then re-proposed.\n require(\n proposal.outputRoot == provenWithdrawal.outputRoot,\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n\n // Check that the output proposal has also been finalized.\n require(\n _isFinalizationPeriodElapsed(proposal.timestamp),\n \"OptimismPortal: output proposal finalization period has not elapsed\"\n );\n\n // Check that this withdrawal has not already been finalized, this is replay protection.\n require(\n finalizedWithdrawals[withdrawalHash] == false,\n \"OptimismPortal: withdrawal has already been finalized\"\n );\n\n // Mark the withdrawal as finalized so it can't be replayed.\n finalizedWithdrawals[withdrawalHash] = true;\n\n // Set the l2Sender so contracts know who triggered this withdrawal on L2.\n l2Sender = _tx.sender;\n\n // Trigger the call to the target contract. We use a custom low level method\n // SafeCall.callWithMinGas to ensure two key properties\n // 1. Target contracts cannot force this call to run out of gas by returning a very large\n // amount of data (and this is OK because we don't care about the returndata here).\n // 2. The amount of gas provided to the execution context of the target is at least the\n // gas limit specified by the user. If there is not enough gas in the current context\n // to accomplish this, `callWithMinGas` will revert.\n bool success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, _tx.value, _tx.data);\n\n // Reset the l2Sender back to the default value.\n l2Sender = Constants.DEFAULT_L2_SENDER;\n\n // All withdrawals are immediately finalized. Replayability can\n // be achieved through contracts built on top of this contract\n emit WithdrawalFinalized(withdrawalHash, success);\n\n // Reverting here is useful for determining the exact gas cost to successfully execute the\n // sub call to the target contract if the minimum gas limit specified by the user would not\n // be sufficient to execute the sub call.\n if (success == false && tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"OptimismPortal: withdrawal failed\");\n }\n }\n\n /**\n * @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in\n * deriving deposit transactions. Note that if a deposit is made by a contract, its\n * address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider\n * using the CrossDomainMessenger contracts for a simpler developer experience.\n *\n * @param _to Target address on L2.\n * @param _value ETH value to send to the recipient.\n * @param _gasLimit Minimum L2 gas limit (can be greater than or equal to this value).\n * @param _isCreation Whether or not the transaction is a contract creation.\n * @param _data Data to trigger the recipient with.\n */\n function depositTransaction(\n address _to,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable metered(_gasLimit) {\n // Just to be safe, make sure that people specify address(0) as the target when doing\n // contract creations.\n if (_isCreation) {\n require(\n _to == address(0),\n \"OptimismPortal: must send to address(0) when creating a contract\"\n );\n }\n\n // Prevent depositing transactions that have too small of a gas limit. Users should pay\n // more for more resource usage.\n require(\n _gasLimit >= minimumGasLimit(uint64(_data.length)),\n \"OptimismPortal: gas limit too small\"\n );\n\n // Prevent the creation of deposit transactions that have too much calldata. This gives an\n // upper limit on the size of unsafe blocks over the p2p network. 120kb is chosen to ensure\n // that the transaction can fit into the p2p network policy of 128kb even though deposit\n // transactions are not gossipped over the p2p network.\n require(_data.length <= 120_000, \"OptimismPortal: data too large\");\n\n // Transform the from-address to its alias if the caller is a contract.\n address from = msg.sender;\n if (msg.sender != tx.origin) {\n from = AddressAliasHelper.applyL1ToL2Alias(msg.sender);\n }\n\n // Compute the opaque data that will be emitted as part of the TransactionDeposited event.\n // We use opaque data so that we can update the TransactionDeposited event in the future\n // without breaking the current interface.\n bytes memory opaqueData = abi.encodePacked(\n msg.value,\n _value,\n _gasLimit,\n _isCreation,\n _data\n );\n\n // Emit a TransactionDeposited event so that the rollup node can derive a deposit\n // transaction for this deposit.\n emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData);\n }\n\n /**\n * @notice Determine if a given output is finalized. Reverts if the call to\n * L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.\n *\n * @param _l2OutputIndex Index of the L2 output to check.\n *\n * @return Whether or not the output is finalized.\n */\n function isOutputFinalized(uint256 _l2OutputIndex) external view returns (bool) {\n return _isFinalizationPeriodElapsed(L2_ORACLE.getL2Output(_l2OutputIndex).timestamp);\n }\n\n /**\n * @notice Determines whether the finalization period has elapsed w/r/t a given timestamp.\n *\n * @param _timestamp Timestamp to check.\n *\n * @return Whether or not the finalization period has elapsed.\n */\n function _isFinalizationPeriodElapsed(uint256 _timestamp) internal view returns (bool) {\n return block.timestamp > _timestamp + L2_ORACLE.FINALIZATION_PERIOD_SECONDS();\n }\n}\n" - }, - "contracts/L1/ResourceMetering.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\n\n/**\n * @custom:upgradeable\n * @title ResourceMetering\n * @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing\n * updates automatically based on current demand.\n */\nabstract contract ResourceMetering is Initializable {\n /**\n * @notice Represents the various parameters that control the way in which resources are\n * metered. Corresponds to the EIP-1559 resource metering system.\n *\n * @custom:field prevBaseFee Base fee from the previous block(s).\n * @custom:field prevBoughtGas Amount of gas bought so far in the current block.\n * @custom:field prevBlockNum Last block number that the base fee was updated.\n */\n struct ResourceParams {\n uint128 prevBaseFee;\n uint64 prevBoughtGas;\n uint64 prevBlockNum;\n }\n\n /**\n * @notice Represents the configuration for the EIP-1559 based curve for the deposit gas\n * market. These values should be set with care as it is possible to set them in\n * a way that breaks the deposit gas market. The target resource limit is defined as\n * maxResourceLimit / elasticityMultiplier. This struct was designed to fit within a\n * single word. There is additional space for additions in the future.\n *\n * @custom:field maxResourceLimit Represents the maximum amount of deposit gas that\n * can be purchased per block.\n * @custom:field elasticityMultiplier Determines the target resource limit along with\n * the resource limit.\n * @custom:field baseFeeMaxChangeDenominator Determines max change on fee per block.\n * @custom:field minimumBaseFee The min deposit base fee, it is clamped to this\n * value.\n * @custom:field systemTxMaxGas The amount of gas supplied to the system\n * transaction. This should be set to the same number\n * that the op-node sets as the gas limit for the\n * system transaction.\n * @custom:field maximumBaseFee The max deposit base fee, it is clamped to this\n * value.\n */\n struct ResourceConfig {\n uint32 maxResourceLimit;\n uint8 elasticityMultiplier;\n uint8 baseFeeMaxChangeDenominator;\n uint32 minimumBaseFee;\n uint32 systemTxMaxGas;\n uint128 maximumBaseFee;\n }\n\n /**\n * @notice EIP-1559 style gas parameters.\n */\n ResourceParams public params;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n */\n uint256[48] private __gap;\n\n /**\n * @notice Meters access to a function based an amount of a requested resource.\n *\n * @param _amount Amount of the resource requested.\n */\n modifier metered(uint64 _amount) {\n // Record initial gas amount so we can refund for it later.\n uint256 initialGas = gasleft();\n\n // Run the underlying function.\n _;\n\n // Run the metering function.\n _metered(_amount, initialGas);\n }\n\n /**\n * @notice An internal function that holds all of the logic for metering a resource.\n *\n * @param _amount Amount of the resource requested.\n * @param _initialGas The amount of gas before any modifier execution.\n */\n function _metered(uint64 _amount, uint256 _initialGas) internal {\n // Update block number and base fee if necessary.\n uint256 blockDiff = block.number - params.prevBlockNum;\n\n ResourceConfig memory config = _resourceConfig();\n int256 targetResourceLimit = int256(uint256(config.maxResourceLimit)) /\n int256(uint256(config.elasticityMultiplier));\n\n if (blockDiff > 0) {\n // Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate\n // at which deposits can be created and therefore limit the potential for deposits to\n // spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes.\n int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - targetResourceLimit;\n int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) /\n (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator)));\n\n // Update base fee by adding the base fee delta and clamp the resulting value between\n // min and max.\n int256 newBaseFee = Arithmetic.clamp({\n _value: int256(uint256(params.prevBaseFee)) + baseFeeDelta,\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n\n // If we skipped more than one block, we also need to account for every empty block.\n // Empty block means there was no demand for deposits in that block, so we should\n // reflect this lack of demand in the fee.\n if (blockDiff > 1) {\n // Update the base fee by repeatedly applying the exponent 1-(1/change_denominator)\n // blockDiff - 1 times. Simulates multiple empty blocks. Clamp the resulting value\n // between min and max.\n newBaseFee = Arithmetic.clamp({\n _value: Arithmetic.cdexp({\n _coefficient: newBaseFee,\n _denominator: int256(uint256(config.baseFeeMaxChangeDenominator)),\n _exponent: int256(blockDiff - 1)\n }),\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n }\n\n // Update new base fee, reset bought gas, and update block number.\n params.prevBaseFee = uint128(uint256(newBaseFee));\n params.prevBoughtGas = 0;\n params.prevBlockNum = uint64(block.number);\n }\n\n // Make sure we can actually buy the resource amount requested by the user.\n params.prevBoughtGas += _amount;\n require(\n int256(uint256(params.prevBoughtGas)) <= int256(uint256(config.maxResourceLimit)),\n \"ResourceMetering: cannot buy more gas than available gas limit\"\n );\n\n // Determine the amount of ETH to be paid.\n uint256 resourceCost = uint256(_amount) * uint256(params.prevBaseFee);\n\n // We currently charge for this ETH amount as an L1 gas burn, so we convert the ETH amount\n // into gas by dividing by the L1 base fee. We assume a minimum base fee of 1 gwei to avoid\n // division by zero for L1s that don't support 1559 or to avoid excessive gas burns during\n // periods of extremely low L1 demand. One-day average gas fee hasn't dipped below 1 gwei\n // during any 1 day period in the last 5 years, so should be fine.\n uint256 gasCost = resourceCost / Math.max(block.basefee, 1 gwei);\n\n // Give the user a refund based on the amount of gas they used to do all of the work up to\n // this point. Since we're at the end of the modifier, this should be pretty accurate. Acts\n // effectively like a dynamic stipend (with a minimum value).\n uint256 usedGas = _initialGas - gasleft();\n if (gasCost > usedGas) {\n Burn.gas(gasCost - usedGas);\n }\n }\n\n /**\n * @notice Virtual function that returns the resource config. Contracts that inherit this\n * contract must implement this function.\n *\n * @return ResourceConfig\n */\n function _resourceConfig() internal virtual returns (ResourceConfig memory);\n\n /**\n * @notice Sets initial resource parameter values. This function must either be called by the\n * initializer function of an upgradeable child contract.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __ResourceMetering_init() internal onlyInitializing {\n params = ResourceParams({\n prevBaseFee: 1 gwei,\n prevBoughtGas: 0,\n prevBlockNum: uint64(block.number)\n });\n }\n}\n" - }, - "contracts/L1/SystemConfig.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { ResourceMetering } from \"./ResourceMetering.sol\";\n\n/**\n * @title SystemConfig\n * @notice The SystemConfig contract is used to manage configuration of an Optimism network. All\n * configuration is stored on L1 and picked up by L2 as part of the derviation of the L2\n * chain.\n */\ncontract SystemConfig is OwnableUpgradeable, Semver {\n /**\n * @notice Enum representing different types of updates.\n *\n * @custom:value BATCHER Represents an update to the batcher hash.\n * @custom:value GAS_CONFIG Represents an update to txn fee config on L2.\n * @custom:value GAS_LIMIT Represents an update to gas limit on L2.\n * @custom:value UNSAFE_BLOCK_SIGNER Represents an update to the signer key for unsafe\n * block distrubution.\n */\n enum UpdateType {\n BATCHER,\n GAS_CONFIG,\n GAS_LIMIT,\n UNSAFE_BLOCK_SIGNER\n }\n\n /**\n * @notice Version identifier, used for upgrades.\n */\n uint256 public constant VERSION = 0;\n\n /**\n * @notice Storage slot that the unsafe block signer is stored at. Storing it at this\n * deterministic storage slot allows for decoupling the storage layout from the way\n * that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value.\n */\n bytes32 public constant UNSAFE_BLOCK_SIGNER_SLOT = keccak256(\"systemconfig.unsafeblocksigner\");\n\n /**\n * @notice Fixed L2 gas overhead. Used as part of the L2 fee calculation.\n */\n uint256 public overhead;\n\n /**\n * @notice Dynamic L2 gas overhead. Used as part of the L2 fee calculation.\n */\n uint256 public scalar;\n\n /**\n * @notice Identifier for the batcher. For version 1 of this configuration, this is represented\n * as an address left-padded with zeros to 32 bytes.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice L2 block gas limit.\n */\n uint64 public gasLimit;\n\n /**\n * @notice The configuration for the deposit fee market. Used by the OptimismPortal\n * to meter the cost of buying L2 gas on L1. Set as internal and wrapped with a getter\n * so that the struct is returned instead of a tuple.\n */\n ResourceMetering.ResourceConfig internal _resourceConfig;\n\n /**\n * @notice Emitted when configuration is updated\n *\n * @param version SystemConfig version.\n * @param updateType Type of update.\n * @param data Encoded update data.\n */\n event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);\n\n /**\n * @custom:semver 1.3.0\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n * @param _unsafeBlockSigner Initial unsafe block signer address.\n * @param _config Initial resource config.\n */\n constructor(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner,\n ResourceMetering.ResourceConfig memory _config\n ) Semver(1, 3, 0) {\n initialize({\n _owner: _owner,\n _overhead: _overhead,\n _scalar: _scalar,\n _batcherHash: _batcherHash,\n _gasLimit: _gasLimit,\n _unsafeBlockSigner: _unsafeBlockSigner,\n _config: _config\n });\n }\n\n /**\n * @notice Initializer. The resource config must be set before the\n * require check.\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n * @param _unsafeBlockSigner Initial unsafe block signer address.\n * @param _config Initial ResourceConfig.\n */\n function initialize(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner,\n ResourceMetering.ResourceConfig memory _config\n ) public initializer {\n __Ownable_init();\n transferOwnership(_owner);\n overhead = _overhead;\n scalar = _scalar;\n batcherHash = _batcherHash;\n gasLimit = _gasLimit;\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n _setResourceConfig(_config);\n require(_gasLimit >= minimumGasLimit(), \"SystemConfig: gas limit too low\");\n }\n\n /**\n * @notice Returns the minimum L2 gas limit that can be safely set for the system to\n * operate. The L2 gas limit must be larger than or equal to the amount of\n * gas that is allocated for deposits per block plus the amount of gas that\n * is allocated for the system transaction.\n * This function is used to determine if changes to parameters are safe.\n *\n * @return uint64\n */\n function minimumGasLimit() public view returns (uint64) {\n return uint64(_resourceConfig.maxResourceLimit) + uint64(_resourceConfig.systemTxMaxGas);\n }\n\n /**\n * @notice High level getter for the unsafe block signer address. Unsafe blocks can be\n * propagated across the p2p network if they are signed by the key corresponding to\n * this address.\n *\n * @return Address of the unsafe block signer.\n */\n // solhint-disable-next-line ordering\n function unsafeBlockSigner() external view returns (address) {\n address addr;\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n addr := sload(slot)\n }\n return addr;\n }\n\n /**\n * @notice Updates the unsafe block signer address.\n *\n * @param _unsafeBlockSigner New unsafe block signer address.\n */\n function setUnsafeBlockSigner(address _unsafeBlockSigner) external onlyOwner {\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n\n bytes memory data = abi.encode(_unsafeBlockSigner);\n emit ConfigUpdate(VERSION, UpdateType.UNSAFE_BLOCK_SIGNER, data);\n }\n\n /**\n * @notice Updates the batcher hash.\n *\n * @param _batcherHash New batcher hash.\n */\n function setBatcherHash(bytes32 _batcherHash) external onlyOwner {\n batcherHash = _batcherHash;\n\n bytes memory data = abi.encode(_batcherHash);\n emit ConfigUpdate(VERSION, UpdateType.BATCHER, data);\n }\n\n /**\n * @notice Updates gas config.\n *\n * @param _overhead New overhead value.\n * @param _scalar New scalar value.\n */\n function setGasConfig(uint256 _overhead, uint256 _scalar) external onlyOwner {\n overhead = _overhead;\n scalar = _scalar;\n\n bytes memory data = abi.encode(_overhead, _scalar);\n emit ConfigUpdate(VERSION, UpdateType.GAS_CONFIG, data);\n }\n\n /**\n * @notice Updates the L2 gas limit.\n *\n * @param _gasLimit New gas limit.\n */\n function setGasLimit(uint64 _gasLimit) external onlyOwner {\n require(_gasLimit >= minimumGasLimit(), \"SystemConfig: gas limit too low\");\n gasLimit = _gasLimit;\n\n bytes memory data = abi.encode(_gasLimit);\n emit ConfigUpdate(VERSION, UpdateType.GAS_LIMIT, data);\n }\n\n /**\n * @notice Low level setter for the unsafe block signer address. This function exists to\n * deduplicate code around storing the unsafeBlockSigner address in storage.\n *\n * @param _unsafeBlockSigner New unsafeBlockSigner value.\n */\n function _setUnsafeBlockSigner(address _unsafeBlockSigner) internal {\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n sstore(slot, _unsafeBlockSigner)\n }\n }\n\n /**\n * @notice A getter for the resource config. Ensures that the struct is\n * returned instead of a tuple.\n *\n * @return ResourceConfig\n */\n function resourceConfig() external view returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig;\n }\n\n /**\n * @notice An external setter for the resource config. In the future, this\n * method may emit an event that the `op-node` picks up for when the\n * resource config is changed.\n *\n * @param _config The new resource config values.\n */\n function setResourceConfig(ResourceMetering.ResourceConfig memory _config) external onlyOwner {\n _setResourceConfig(_config);\n }\n\n /**\n * @notice An internal setter for the resource config. Ensures that the\n * config is sane before storing it by checking for invariants.\n *\n * @param _config The new resource config.\n */\n function _setResourceConfig(ResourceMetering.ResourceConfig memory _config) internal {\n // Min base fee must be less than or equal to max base fee.\n require(\n _config.minimumBaseFee <= _config.maximumBaseFee,\n \"SystemConfig: min base fee must be less than max base\"\n );\n // Base fee change denominator must be greater than 1.\n require(\n _config.baseFeeMaxChangeDenominator > 1,\n \"SystemConfig: denominator must be larger than 1\"\n );\n // Max resource limit plus system tx gas must be less than or equal to the L2 gas limit.\n // The gas limit must be increased before these values can be increased.\n require(\n _config.maxResourceLimit + _config.systemTxMaxGas <= gasLimit,\n \"SystemConfig: gas limit too low\"\n );\n // Elasticity multiplier must be greater than 0.\n require(\n _config.elasticityMultiplier > 0,\n \"SystemConfig: elasticity multiplier cannot be 0\"\n );\n // No precision loss when computing target resource limit.\n require(\n ((_config.maxResourceLimit / _config.elasticityMultiplier) *\n _config.elasticityMultiplier) == _config.maxResourceLimit,\n \"SystemConfig: precision loss with target resource limit\"\n );\n\n _resourceConfig = _config;\n }\n}\n" - }, - "contracts/L2/BaseFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000019\n * @title BaseFeeVault\n * @notice The BaseFeeVault accumulates the base fee that is paid by transactions.\n */\ncontract BaseFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}\n}\n" - }, - "contracts/L2/CrossDomainOwnable.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\n/**\n * @title CrossDomainOwnable\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is only safe to be used if the\n * CrossDomainMessenger system is bypassed and the caller on L1 is calling the\n * OptimismPortal directly.\n */\nabstract contract CrossDomainOwnable is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `msg.sender` is the owner of the contract.\n */\n function _checkOwner() internal view override {\n require(\n owner() == AddressAliasHelper.undoL1ToL2Alias(msg.sender),\n \"CrossDomainOwnable: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/CrossDomainOwnable2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L2CrossDomainMessenger } from \"./L2CrossDomainMessenger.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title CrossDomainOwnable2\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is meant to be used with systems that use\n * the CrossDomainMessenger system. It will not work if the OptimismPortal is used\n * directly.\n */\nabstract contract CrossDomainOwnable2 is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `xDomainMessageSender` is the owner of the contract. This value is set to the caller\n * of the L1CrossDomainMessenger.\n */\n function _checkOwner() internal view override {\n L2CrossDomainMessenger messenger = L2CrossDomainMessenger(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER\n );\n\n require(\n msg.sender == address(messenger),\n \"CrossDomainOwnable2: caller is not the messenger\"\n );\n\n require(\n owner() == messenger.xDomainMessageSender(),\n \"CrossDomainOwnable2: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/CrossDomainOwnable3.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L2CrossDomainMessenger } from \"./L2CrossDomainMessenger.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title CrossDomainOwnable3\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on either L1 or L2. Note that this contract is meant to be used with systems\n * that use the CrossDomainMessenger system. It will not work if the OptimismPortal is\n * used directly.\n */\nabstract contract CrossDomainOwnable3 is Ownable {\n /**\n * @notice If true, the contract uses the cross domain _checkOwner function override. If false\n * it uses the standard Ownable _checkOwner function.\n */\n bool public isLocal = true;\n\n /**\n * @notice Emits when ownership of the contract is transferred. Includes the\n * isLocal field in addition to the standard `Ownable` OwnershipTransferred event.\n */\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner,\n bool isLocal\n );\n\n /**\n * @notice Allows for ownership to be transferred with specifying the locality.\n * @param _owner The new owner of the contract.\n * @param _isLocal Configures the locality of the ownership.\n */\n function transferOwnership(address _owner, bool _isLocal) external onlyOwner {\n require(_owner != address(0), \"CrossDomainOwnable3: new owner is the zero address\");\n\n address oldOwner = owner();\n _transferOwnership(_owner);\n isLocal = _isLocal;\n\n emit OwnershipTransferred(oldOwner, _owner, _isLocal);\n }\n\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `xDomainMessageSender` is the owner of the contract. This value is set to the caller\n * of the L1CrossDomainMessenger.\n */\n function _checkOwner() internal view override {\n if (isLocal) {\n require(owner() == msg.sender, \"CrossDomainOwnable3: caller is not the owner\");\n } else {\n L2CrossDomainMessenger messenger = L2CrossDomainMessenger(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER\n );\n\n require(\n msg.sender == address(messenger),\n \"CrossDomainOwnable3: caller is not the messenger\"\n );\n\n require(\n owner() == messenger.xDomainMessageSender(),\n \"CrossDomainOwnable3: caller is not the owner\"\n );\n }\n }\n}\n" - }, - "contracts/L2/GasPriceOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000000F\n * @title GasPriceOracle\n * @notice This contract maintains the variables responsible for computing the L1 portion of the\n * total fee charged on L2. Before Bedrock, this contract held variables in state that were\n * read during the state transition function to compute the L1 portion of the transaction\n * fee. After Bedrock, this contract now simply proxies the L1Block contract, which has\n * the values used to compute the L1 portion of the fee in its state.\n *\n * The contract exposes an API that is useful for knowing how large the L1 portion of the\n * transaction fee will be. The following events were deprecated with Bedrock:\n * - event OverheadUpdated(uint256 overhead);\n * - event ScalarUpdated(uint256 scalar);\n * - event DecimalsUpdated(uint256 decimals);\n */\ncontract GasPriceOracle is Semver {\n /**\n * @notice Number of decimals used in the scalar.\n */\n uint256 public constant DECIMALS = 6;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Computes the L1 portion of the fee based on the size of the rlp encoded input\n * transaction, the current L1 base fee, and the various dynamic parameters.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for.\n *\n * @return L1 fee that should be paid for the tx\n */\n function getL1Fee(bytes memory _data) external view returns (uint256) {\n uint256 l1GasUsed = getL1GasUsed(_data);\n uint256 l1Fee = l1GasUsed * l1BaseFee();\n uint256 divisor = 10**DECIMALS;\n uint256 unscaled = l1Fee * scalar();\n uint256 scaled = unscaled / divisor;\n return scaled;\n }\n\n /**\n * @notice Retrieves the current gas price (base fee).\n *\n * @return Current L2 gas price (base fee).\n */\n function gasPrice() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current base fee.\n *\n * @return Current L2 base fee.\n */\n function baseFee() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current fee overhead.\n *\n * @return Current fee overhead.\n */\n function overhead() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead();\n }\n\n /**\n * @notice Retrieves the current fee scalar.\n *\n * @return Current fee scalar.\n */\n function scalar() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar();\n }\n\n /**\n * @notice Retrieves the latest known L1 base fee.\n *\n * @return Latest known L1 base fee.\n */\n function l1BaseFee() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee();\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the number of decimals used in the scalar.\n *\n * @return Number of decimals used in the scalar.\n */\n function decimals() public pure returns (uint256) {\n return DECIMALS;\n }\n\n /**\n * @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which\n * represents the per-transaction gas overhead of posting the transaction and state\n * roots to L1. Adds 68 bytes of padding to account for the fact that the input does\n * not have a signature.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for.\n *\n * @return Amount of L1 gas used to publish the transaction.\n */\n function getL1GasUsed(bytes memory _data) public view returns (uint256) {\n uint256 total = 0;\n uint256 length = _data.length;\n for (uint256 i = 0; i < length; i++) {\n if (_data[i] == 0) {\n total += 4;\n } else {\n total += 16;\n }\n }\n uint256 unsigned = total + overhead();\n return unsigned + (68 * 16);\n }\n}\n" - }, - "contracts/L2/L1Block.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000015\n * @title L1Block\n * @notice The L1Block predeploy gives users access to information about the last known L1 block.\n * Values within this contract are updated once per epoch (every L1 block) and can only be\n * set by the \"depositor\" account, a special system address. Depositor account transactions\n * are created by the protocol whenever we move to a new epoch.\n */\ncontract L1Block is Semver {\n /**\n * @notice Address of the special depositor account.\n */\n address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001;\n\n /**\n * @notice The latest L1 block number known by the L2 system.\n */\n uint64 public number;\n\n /**\n * @notice The latest L1 timestamp known by the L2 system.\n */\n uint64 public timestamp;\n\n /**\n * @notice The latest L1 basefee.\n */\n uint256 public basefee;\n\n /**\n * @notice The latest L1 blockhash.\n */\n bytes32 public hash;\n\n /**\n * @notice The number of L2 blocks in the same epoch.\n */\n uint64 public sequenceNumber;\n\n /**\n * @notice The versioned hash to authenticate the batcher by.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice The overhead value applied to the L1 portion of the transaction\n * fee.\n */\n uint256 public l1FeeOverhead;\n\n /**\n * @notice The scalar value applied to the L1 portion of the transaction fee.\n */\n uint256 public l1FeeScalar;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Updates the L1 block values.\n *\n * @param _number L1 blocknumber.\n * @param _timestamp L1 timestamp.\n * @param _basefee L1 basefee.\n * @param _hash L1 blockhash.\n * @param _sequenceNumber Number of L2 blocks since epoch start.\n * @param _batcherHash Versioned hash to authenticate batcher by.\n * @param _l1FeeOverhead L1 fee overhead.\n * @param _l1FeeScalar L1 fee scalar.\n */\n function setL1BlockValues(\n uint64 _number,\n uint64 _timestamp,\n uint256 _basefee,\n bytes32 _hash,\n uint64 _sequenceNumber,\n bytes32 _batcherHash,\n uint256 _l1FeeOverhead,\n uint256 _l1FeeScalar\n ) external {\n require(\n msg.sender == DEPOSITOR_ACCOUNT,\n \"L1Block: only the depositor account can set L1 block values\"\n );\n\n number = _number;\n timestamp = _timestamp;\n basefee = _basefee;\n hash = _hash;\n sequenceNumber = _sequenceNumber;\n batcherHash = _batcherHash;\n l1FeeOverhead = _l1FeeOverhead;\n l1FeeScalar = _l1FeeScalar;\n }\n}\n" - }, - "contracts/L2/L1FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000001A\n * @title L1FeeVault\n * @notice The L1FeeVault accumulates the L1 portion of the transaction fees.\n */\ncontract L1FeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}\n}\n" - }, - "contracts/L2/L2CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { L2ToL1MessagePasser } from \"./L2ToL1MessagePasser.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000007\n * @title L2CrossDomainMessenger\n * @notice The L2CrossDomainMessenger is a high-level interface for message passing between L1 and\n * L2 on the L2 side. Users are generally encouraged to use this contract instead of lower\n * level message passing contracts.\n */\ncontract L2CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @custom:semver 1.4.0\n *\n * @param _l1CrossDomainMessenger Address of the L1CrossDomainMessenger contract.\n */\n constructor(address _l1CrossDomainMessenger)\n Semver(1, 4, 0)\n CrossDomainMessenger(_l1CrossDomainMessenger)\n {\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote messenger. Use otherMessenger going forward.\n *\n * @return Address of the L1CrossDomainMessenger contract.\n */\n function l1CrossDomainMessenger() public view returns (address) {\n return OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)).initiateWithdrawal{\n value: _value\n }(_to, _gasLimit, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(Predeploys.L2_TO_L1_MESSAGE_PASSER);\n }\n}\n" - }, - "contracts/L2/L2ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../universal/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 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.1.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, 1, 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), \"L2ERC721Bridge: 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 \"L2ERC721Bridge: 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(OTHER_BRIDGE, message, _minGasLimit);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L2/L2StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000010\n * @title L2StandardBridge\n * @notice The L2StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L2, it will be escrowed within this\n * contract. If the ERC20 token is native to L1, it will be burnt.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L2StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal from L2 to L1 is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _otherBridge Address of the L1StandardBridge.\n */\n constructor(address payable _otherBridge)\n Semver(1, 1, 0)\n StandardBridge(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER), _otherBridge)\n {}\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n */\n receive() external payable override onlyEOA {\n _initiateWithdrawal(\n Predeploys.LEGACY_ERC20_ETH,\n msg.sender,\n msg.sender,\n msg.value,\n RECEIVE_DEFAULT_GAS_LIMIT,\n bytes(\"\")\n );\n }\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1.\n * This function only works with OptimismMintableERC20 tokens or ether. Use the\n * `bridgeERC20` function to bridge native L2 tokens to L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdraw(\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual onlyEOA {\n _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1 to a target account on L1.\n * Note that if ETH is sent to a contract on L1 and the call fails, then that ETH will\n * be locked in the L1StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n * This function only works with OptimismMintableERC20 tokens or ether. Use the\n * `bridgeERC20To` function to bridge native L2 tokens to L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdrawTo(\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual {\n _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a deposit from L1 to L2. To finalize a deposit of ether, use address(0)\n * and the l1Token and the Legacy ERC20 ether predeploy address as the l2Token.\n *\n * @param _l1Token Address of the L1 token to deposit.\n * @param _l2Token Address of the corresponding L2 token.\n * @param _from Address of the depositor.\n * @param _to Address of the recipient.\n * @param _amount Amount of the tokens being deposited.\n * @param _extraData Extra data attached to the deposit.\n */\n function finalizeDeposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable virtual {\n if (_l1Token == address(0) && _l2Token == Predeploys.LEGACY_ERC20_ETH) {\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n } else {\n finalizeBridgeERC20(_l2Token, _l1Token, _from, _to, _amount, _extraData);\n }\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L1 bridge contract.\n *\n * @return Address of the corresponding L1 bridge contract.\n */\n function l1TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @custom:legacy\n * @notice Internal function to a withdrawal from L2 to L1 to a target account on L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _from Address of the withdrawer.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function _initiateWithdrawal(\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n if (_l2Token == Predeploys.LEGACY_ERC20_ETH) {\n _initiateBridgeETH(_from, _to, _amount, _minGasLimit, _extraData);\n } else {\n address l1Token = OptimismMintableERC20(_l2Token).l1Token();\n _initiateBridgeERC20(_l2Token, l1Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n }\n\n /**\n * @notice Emits the legacy WithdrawalInitiated event followed by the ETHBridgeInitiated event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit WithdrawalInitiated(\n address(0),\n Predeploys.LEGACY_ERC20_ETH,\n _from,\n _to,\n _amount,\n _extraData\n );\n super._emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy DepositFinalized event followed by the ETHBridgeFinalized event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit DepositFinalized(\n address(0),\n Predeploys.LEGACY_ERC20_ETH,\n _from,\n _to,\n _amount,\n _extraData\n );\n super._emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy WithdrawalInitiated event followed by the ERC20BridgeInitiated\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit WithdrawalInitiated(_remoteToken, _localToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy DepositFinalized event followed by the ERC20BridgeFinalized event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit DepositFinalized(_remoteToken, _localToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/L2/L2ToL1MessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000016\n * @title L2ToL1MessagePasser\n * @notice The L2ToL1MessagePasser is a dedicated contract where messages that are being sent from\n * L2 to L1 can be stored. The storage root of this contract is pulled up to the top level\n * of the L2 output to reduce the cost of proving the existence of sent messages.\n */\ncontract L2ToL1MessagePasser is Semver {\n /**\n * @notice The L1 gas limit set when eth is withdrawn using the receive() function.\n */\n uint256 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Current message version identifier.\n */\n uint16 public constant MESSAGE_VERSION = 1;\n\n /**\n * @notice Includes the message hashes for all withdrawals\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @notice A unique value hashed with each withdrawal.\n */\n uint240 internal msgNonce;\n\n /**\n * @notice Emitted any time a withdrawal is initiated.\n *\n * @param nonce Unique value corresponding to each withdrawal.\n * @param sender The L2 account address which initiated the withdrawal.\n * @param target The L1 account address the call will be send to.\n * @param value The ETH value submitted for withdrawal, to be forwarded to the target.\n * @param gasLimit The minimum amount of gas that must be provided when withdrawing.\n * @param data The data to be forwarded to the target on L1.\n * @param withdrawalHash The hash of the withdrawal.\n */\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n /**\n * @notice Emitted when the balance of this contract is burned.\n *\n * @param amount Amount of ETh that was burned.\n */\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Allows users to withdraw ETH by sending directly to this contract.\n */\n receive() external payable {\n initiateWithdrawal(msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @notice Removes all ETH held by this contract from the state. Used to prevent the amount of\n * ETH on L2 inflating when ETH is withdrawn. Currently only way to do this is to\n * create a contract and self-destruct it to itself. Anyone can call this function. Not\n * incentivized since this function is very cheap.\n */\n function burn() external {\n uint256 balance = address(this).balance;\n Burn.eth(balance);\n emit WithdrawerBalanceBurnt(balance);\n }\n\n /**\n * @notice Sends a message from L2 to L1.\n *\n * @param _target Address to call on L1 execution.\n * @param _gasLimit Minimum gas limit for executing the message on L1.\n * @param _data Data to forward to L1 target.\n */\n function initiateWithdrawal(\n address _target,\n uint256 _gasLimit,\n bytes memory _data\n ) public payable {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messageNonce(),\n sender: msg.sender,\n target: _target,\n value: msg.value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n sentMessages[withdrawalHash] = true;\n\n emit MessagePassed(\n messageNonce(),\n msg.sender,\n _target,\n msg.value,\n _gasLimit,\n _data,\n withdrawalHash\n );\n\n unchecked {\n ++msgNonce;\n }\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" - }, - "contracts/L2/SequencerFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000011\n * @title SequencerFeeVault\n * @notice The SequencerFeeVault is the contract that holds any fees paid to the Sequencer during\n * transaction processing and block production.\n */\ncontract SequencerFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the recipient address.\n *\n * @return The recipient address.\n */\n function l1FeeWallet() public view returns (address) {\n return RECIPIENT;\n }\n}\n" - }, - "contracts/deployment/PortalSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/**\n * @title PortalSender\n * @notice The PortalSender is a simple intermediate contract that will transfer the balance of the\n * L1StandardBridge to the OptimismPortal during the Bedrock migration.\n */\ncontract PortalSender {\n /**\n * @notice Address of the OptimismPortal contract.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @param _portal Address of the OptimismPortal contract.\n */\n constructor(OptimismPortal _portal) {\n PORTAL = _portal;\n }\n\n /**\n * @notice Sends balance of this contract to the OptimismPortal.\n */\n function donate() public {\n PORTAL.donateETH{ value: address(this).balance }();\n }\n}\n" - }, - "contracts/deployment/SystemDictator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { PortalSender } from \"./PortalSender.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\n/**\n * @title SystemDictator\n * @notice The SystemDictator is responsible for coordinating the deployment of a full Bedrock\n * system. The SystemDictator is designed to support both fresh network deployments and\n * upgrades to existing pre-Bedrock systems.\n */\ncontract SystemDictator is OwnableUpgradeable {\n /**\n * @notice Basic system configuration.\n */\n struct GlobalConfig {\n AddressManager addressManager;\n ProxyAdmin proxyAdmin;\n address controller;\n address finalOwner;\n }\n\n /**\n * @notice Set of proxy addresses.\n */\n struct ProxyAddressConfig {\n address l2OutputOracleProxy;\n address optimismPortalProxy;\n address l1CrossDomainMessengerProxy;\n address l1StandardBridgeProxy;\n address optimismMintableERC20FactoryProxy;\n address l1ERC721BridgeProxy;\n address systemConfigProxy;\n }\n\n /**\n * @notice Set of implementation addresses.\n */\n struct ImplementationAddressConfig {\n L2OutputOracle l2OutputOracleImpl;\n OptimismPortal optimismPortalImpl;\n L1CrossDomainMessenger l1CrossDomainMessengerImpl;\n L1StandardBridge l1StandardBridgeImpl;\n OptimismMintableERC20Factory optimismMintableERC20FactoryImpl;\n L1ERC721Bridge l1ERC721BridgeImpl;\n PortalSender portalSenderImpl;\n SystemConfig systemConfigImpl;\n }\n\n /**\n * @notice Dynamic L2OutputOracle config.\n */\n struct L2OutputOracleDynamicConfig {\n uint256 l2OutputOracleStartingBlockNumber;\n uint256 l2OutputOracleStartingTimestamp;\n }\n\n /**\n * @notice Values for the system config contract.\n */\n struct SystemConfigConfig {\n address owner;\n uint256 overhead;\n uint256 scalar;\n bytes32 batcherHash;\n uint64 gasLimit;\n address unsafeBlockSigner;\n ResourceMetering.ResourceConfig resourceConfig;\n }\n\n /**\n * @notice Combined system configuration.\n */\n struct DeployConfig {\n GlobalConfig globalConfig;\n ProxyAddressConfig proxyAddressConfig;\n ImplementationAddressConfig implementationAddressConfig;\n SystemConfigConfig systemConfigConfig;\n }\n\n /**\n * @notice Step after which exit 1 can no longer be used.\n */\n uint8 public constant EXIT_1_NO_RETURN_STEP = 3;\n\n /**\n * @notice Step where proxy ownership is transferred.\n */\n uint8 public constant PROXY_TRANSFER_STEP = 4;\n\n /**\n * @notice System configuration.\n */\n DeployConfig public config;\n\n /**\n * @notice Dynamic configuration for the L2OutputOracle.\n */\n L2OutputOracleDynamicConfig public l2OutputOracleDynamicConfig;\n\n /**\n * @notice Dynamic configuration for the OptimismPortal. Determines\n * if the system should be paused when initialized.\n */\n bool public optimismPortalDynamicConfig;\n\n /**\n * @notice Current step;\n */\n uint8 public currentStep;\n\n /**\n * @notice Whether or not dynamic config has been set.\n */\n bool public dynamicConfigSet;\n\n /**\n * @notice Whether or not the deployment is finalized.\n */\n bool public finalized;\n\n /**\n * @notice Whether or not the deployment has been exited.\n */\n bool public exited;\n\n /**\n * @notice Address of the old L1CrossDomainMessenger implementation.\n */\n address public oldL1CrossDomainMessenger;\n\n /**\n * @notice Checks that the current step is the expected step, then bumps the current step.\n *\n * @param _step Current step.\n */\n modifier step(uint8 _step) {\n require(!finalized, \"SystemDictator: already finalized\");\n require(!exited, \"SystemDictator: already exited\");\n require(currentStep == _step, \"SystemDictator: incorrect step\");\n _;\n currentStep++;\n }\n\n /**\n * @notice Constructor required to ensure that the implementation of the SystemDictator is\n * initialized upon deployment.\n */\n constructor() {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n // Using this shorter variable as an alias for address(0) just prevents us from having to\n // to use a new line for every single parameter.\n address zero = address(0);\n initialize(\n DeployConfig(\n GlobalConfig(AddressManager(zero), ProxyAdmin(zero), zero, zero),\n ProxyAddressConfig(zero, zero, zero, zero, zero, zero, zero),\n ImplementationAddressConfig(\n L2OutputOracle(zero),\n OptimismPortal(payable(zero)),\n L1CrossDomainMessenger(zero),\n L1StandardBridge(payable(zero)),\n OptimismMintableERC20Factory(zero),\n L1ERC721Bridge(zero),\n PortalSender(zero),\n SystemConfig(zero)\n ),\n SystemConfigConfig(zero, 0, 0, bytes32(0), 0, zero, rcfg)\n )\n );\n }\n\n /**\n * @param _config System configuration.\n */\n function initialize(DeployConfig memory _config) public initializer {\n config = _config;\n currentStep = 1;\n __Ownable_init();\n _transferOwnership(config.globalConfig.controller);\n }\n\n /**\n * @notice Allows the owner to update dynamic config.\n *\n * @param _l2OutputOracleDynamicConfig Dynamic L2OutputOracle config.\n * @param _optimismPortalDynamicConfig Dynamic OptimismPortal config.\n */\n function updateDynamicConfig(\n L2OutputOracleDynamicConfig memory _l2OutputOracleDynamicConfig,\n bool _optimismPortalDynamicConfig\n ) external onlyOwner {\n l2OutputOracleDynamicConfig = _l2OutputOracleDynamicConfig;\n optimismPortalDynamicConfig = _optimismPortalDynamicConfig;\n dynamicConfigSet = true;\n }\n\n /**\n * @notice Configures the ProxyAdmin contract.\n */\n function step1() public onlyOwner step(1) {\n // Set the AddressManager in the ProxyAdmin.\n config.globalConfig.proxyAdmin.setAddressManager(config.globalConfig.addressManager);\n\n // Set the L1CrossDomainMessenger to the RESOLVED proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n ProxyAdmin.ProxyType.RESOLVED\n );\n\n // Set the implementation name for the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.setImplementationName(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Set the L1StandardBridge to the CHUGSPLASH proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1StandardBridgeProxy,\n ProxyAdmin.ProxyType.CHUGSPLASH\n );\n\n // Upgrade and initialize the SystemConfig so the Sequencer can start up.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.systemConfigProxy),\n address(config.implementationAddressConfig.systemConfigImpl),\n abi.encodeCall(\n SystemConfig.initialize,\n (\n config.systemConfigConfig.owner,\n config.systemConfigConfig.overhead,\n config.systemConfigConfig.scalar,\n config.systemConfigConfig.batcherHash,\n config.systemConfigConfig.gasLimit,\n config.systemConfigConfig.unsafeBlockSigner,\n config.systemConfigConfig.resourceConfig\n )\n )\n );\n }\n\n /**\n * @notice Pauses the system by shutting down the L1CrossDomainMessenger and setting the\n * deposit halt flag to tell the Sequencer's DTL to stop accepting deposits.\n */\n function step2() public onlyOwner step(2) {\n // Store the address of the old L1CrossDomainMessenger implementation. We will need this\n // address in the case that we have to exit early.\n oldL1CrossDomainMessenger = config.globalConfig.addressManager.getAddress(\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Temporarily brick the L1CrossDomainMessenger by setting its implementation address to\n // address(0) which will cause the ResolvedDelegateProxy to revert. Better than pausing\n // the L1CrossDomainMessenger via pause() because it can be easily reverted.\n config.globalConfig.addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(0));\n\n // Set the DTL shutoff block, which will tell the DTL to stop syncing new deposits from the\n // CanonicalTransactionChain. We do this by setting an address in the AddressManager\n // because the DTL already has a reference to the AddressManager and this way we don't also\n // need to give it a reference to the SystemDictator.\n config.globalConfig.addressManager.setAddress(\n \"DTL_SHUTOFF_BLOCK\",\n address(uint160(block.number))\n );\n }\n\n /**\n * @notice Removes deprecated addresses from the AddressManager.\n */\n function step3() external onlyOwner step(EXIT_1_NO_RETURN_STEP) {\n // Remove all deprecated addresses from the AddressManager\n string[17] memory deprecated = [\n \"OVM_CanonicalTransactionChain\",\n \"OVM_L2CrossDomainMessenger\",\n \"OVM_DecompressionPrecompileAddress\",\n \"OVM_Sequencer\",\n \"OVM_Proposer\",\n \"OVM_ChainStorageContainer-CTC-batches\",\n \"OVM_ChainStorageContainer-CTC-queue\",\n \"OVM_CanonicalTransactionChain\",\n \"OVM_StateCommitmentChain\",\n \"OVM_BondManager\",\n \"OVM_ExecutionManager\",\n \"OVM_FraudVerifier\",\n \"OVM_StateManagerFactory\",\n \"OVM_StateTransitionerFactory\",\n \"OVM_SafetyChecker\",\n \"OVM_L1MultiMessageRelayer\",\n \"BondManager\"\n ];\n\n for (uint256 i = 0; i < deprecated.length; i++) {\n config.globalConfig.addressManager.setAddress(deprecated[i], address(0));\n }\n }\n\n /**\n * @notice Transfers system ownership to the ProxyAdmin.\n */\n function step4() external onlyOwner step(PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the ProxyAdmin.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1StandardBridge to the ProxyAdmin.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the ProxyAdmin.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.proxyAdmin)\n );\n }\n\n /**\n * @notice Upgrades and initializes proxy contracts.\n */\n function step5() external onlyOwner step(5) {\n // Dynamic config must be set before we can initialize the L2OutputOracle.\n require(dynamicConfigSet, \"SystemDictator: dynamic oracle config is not yet initialized\");\n\n // Upgrade and initialize the L2OutputOracle.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l2OutputOracleProxy),\n address(config.implementationAddressConfig.l2OutputOracleImpl),\n abi.encodeCall(\n L2OutputOracle.initialize,\n (\n l2OutputOracleDynamicConfig.l2OutputOracleStartingBlockNumber,\n l2OutputOracleDynamicConfig.l2OutputOracleStartingTimestamp\n )\n )\n );\n\n // Upgrade and initialize the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.optimismPortalProxy),\n address(config.implementationAddressConfig.optimismPortalImpl),\n abi.encodeCall(OptimismPortal.initialize, (optimismPortalDynamicConfig))\n );\n\n // Upgrade the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1CrossDomainMessengerProxy),\n address(config.implementationAddressConfig.l1CrossDomainMessengerImpl)\n );\n\n // Try to initialize the L1CrossDomainMessenger, only fail if it's already been initialized.\n try\n L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy)\n .initialize()\n {\n // L1CrossDomainMessenger is the one annoying edge case difference between existing\n // networks and fresh networks because in existing networks it'll already be\n // initialized but in fresh networks it won't be. Try/catch is the easiest and most\n // consistent way to handle this because initialized() is not exposed publicly.\n } catch Error(string memory reason) {\n require(\n keccak256(abi.encodePacked(reason)) ==\n keccak256(\"Initializable: contract is already initialized\"),\n string.concat(\"SystemDictator: unexpected error initializing L1XDM: \", reason)\n );\n } catch {\n revert(\"SystemDictator: unexpected error initializing L1XDM (no reason)\");\n }\n\n // Transfer ETH from the L1StandardBridge to the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.portalSenderImpl),\n abi.encodeCall(PortalSender.donate, ())\n );\n\n // Upgrade the L1StandardBridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.l1StandardBridgeImpl)\n );\n\n // Upgrade the OptimismMintableERC20Factory (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.optimismMintableERC20FactoryProxy),\n address(config.implementationAddressConfig.optimismMintableERC20FactoryImpl)\n );\n\n // Upgrade the L1ERC721Bridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1ERC721BridgeProxy),\n address(config.implementationAddressConfig.l1ERC721BridgeImpl)\n );\n }\n\n /**\n * @notice Calls the first 2 steps of the migration process.\n */\n function phase1() external onlyOwner {\n step1();\n step2();\n }\n\n /**\n * @notice Tranfers admin ownership to the final owner.\n */\n function finalize() external onlyOwner {\n // Transfer ownership of the ProxyAdmin to the final owner.\n config.globalConfig.proxyAdmin.transferOwnership(config.globalConfig.finalOwner);\n\n // Optionally also transfer AddressManager and L1StandardBridge if we still own it. Might\n // happen if we're exiting early.\n if (currentStep <= PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the final owner.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1StandardBridge to the final owner.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the final owner.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.finalOwner)\n );\n }\n\n // Mark the deployment as finalized.\n finalized = true;\n }\n\n /**\n * @notice First exit point, can only be called before step 3 is executed.\n */\n function exit1() external onlyOwner {\n require(\n currentStep == EXIT_1_NO_RETURN_STEP,\n \"SystemDictator: can only exit1 before step 3 is executed\"\n );\n\n // Reset the L1CrossDomainMessenger to the old implementation.\n config.globalConfig.addressManager.setAddress(\n \"OVM_L1CrossDomainMessenger\",\n oldL1CrossDomainMessenger\n );\n\n // Unset the DTL shutoff block which will allow the DTL to sync again.\n config.globalConfig.addressManager.setAddress(\"DTL_SHUTOFF_BLOCK\", address(0));\n\n // Mark the deployment as exited.\n exited = true;\n }\n}\n" - }, - "contracts/echidna/FuzzAddressAliasing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract EchidnaFuzzAddressAliasing {\n bool internal failedRoundtrip;\n\n /**\n * @notice Takes an address to be aliased with AddressAliasHelper and then unaliased\n * and updates the test contract's state indicating if the round trip encoding\n * failed.\n */\n function testRoundTrip(address addr) public {\n // Alias our address\n address aliasedAddr = AddressAliasHelper.applyL1ToL2Alias(addr);\n\n // Unalias our address\n address undoneAliasAddr = AddressAliasHelper.undoL1ToL2Alias(aliasedAddr);\n\n // If our round trip aliasing did not return the original result, set our state.\n if (addr != undoneAliasAddr) {\n failedRoundtrip = true;\n }\n }\n\n /**\n * @custom:invariant Address aliases are always able to be undone.\n *\n * Asserts that an address that has been aliased with `applyL1ToL2Alias` can always\n * be unaliased with `undoL1ToL2Alias`.\n */\n function echidna_round_trip_aliasing() public view returns (bool) {\n // ASSERTION: The round trip aliasing done in testRoundTrip(...) should never fail.\n return !failedRoundtrip;\n }\n}\n" - }, - "contracts/echidna/FuzzBurn.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\n\ncontract EchidnaFuzzBurnEth is StdUtils {\n bool internal failedEthBurn;\n\n /**\n * @notice Takes an integer amount of eth to burn through the Burn library and\n * updates the contract state if an incorrect amount of eth moved from the contract\n */\n function testBurn(uint256 _value) public {\n // cache the contract's eth balance\n uint256 preBurnBalance = address(this).balance;\n uint256 value = bound(_value, 0, preBurnBalance);\n\n // execute a burn of _value eth\n Burn.eth(value);\n\n // check that exactly value eth was transfered from the contract\n unchecked {\n if (address(this).balance != preBurnBalance - value) {\n failedEthBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `eth(uint256)` always burns the exact amount of eth passed.\n *\n * Asserts that when `Burn.eth(uint256)` is called, it always burns the exact amount\n * of ETH passed to the function.\n */\n function echidna_burn_eth() public view returns (bool) {\n // ASSERTION: The amount burned should always match the amount passed exactly\n return !failedEthBurn;\n }\n}\n\ncontract EchidnaFuzzBurnGas is StdUtils {\n bool internal failedGasBurn;\n\n /**\n * @notice Takes an integer amount of gas to burn through the Burn library and\n * updates the contract state if at least that amount of gas was not burned\n * by the library\n */\n function testGas(uint256 _value) public {\n // cap the value to the max resource limit\n uint256 MAX_RESOURCE_LIMIT = 8_000_000;\n uint256 value = bound(_value, 0, MAX_RESOURCE_LIMIT);\n\n // cache the contract's current remaining gas\n uint256 preBurnGas = gasleft();\n\n // execute the gas burn\n Burn.gas(value);\n\n // cache the remaining gas post burn\n uint256 postBurnGas = gasleft();\n\n // check that at least value gas was burnt (and that there was no underflow)\n unchecked {\n if (postBurnGas - preBurnGas > value || preBurnGas - value > preBurnGas) {\n failedGasBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `gas(uint256)` always burns at least the amount of gas passed.\n *\n * Asserts that when `Burn.gas(uint256)` is called, it always burns at least the amount\n * of gas passed to the function.\n */\n function echidna_burn_gas() public view returns (bool) {\n // ASSERTION: The amount of gas burned should be strictly greater than the\n // the amount passed as _value (minimum _value + whatever minor overhead to\n // the value after the call)\n return !failedGasBurn;\n }\n}\n" - }, - "contracts/echidna/FuzzEncoding.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzEncoding {\n bool internal failedRoundtripAToB;\n bool internal failedRoundtripBToA;\n\n /**\n * @notice Takes a pair of integers to be encoded into a versioned nonce with the\n * Encoding library and then decoded and updates the test contract's state\n * indicating if the round trip encoding failed.\n */\n function testRoundTripAToB(uint240 _nonce, uint16 _version) public {\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(encodedVersionedNonce);\n\n // If our round trip encoding did not return the original result, set our state.\n if ((decodedNonce != _nonce) || (decodedVersion != _version)) {\n failedRoundtripAToB = true;\n }\n }\n\n /**\n * @notice Takes an integer representing a packed version and nonce and attempts\n * to decode them using the Encoding library before re-encoding and updates\n * the test contract's state indicating if the round trip encoding failed.\n */\n function testRoundTripBToA(uint256 _versionedNonce) public {\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(_versionedNonce);\n\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(decodedNonce, decodedVersion);\n\n // If our round trip encoding did not return the original result, set our state.\n if (encodedVersionedNonce != _versionedNonce) {\n failedRoundtripBToA = true;\n }\n }\n\n /**\n * @custom:invariant `testRoundTripAToB` never fails.\n *\n * Asserts that a raw versioned nonce can be encoded / decoded to reach the same raw value.\n */\n function echidna_round_trip_encoding_AToB() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripAToB(...)\n return !failedRoundtripAToB;\n }\n\n /**\n * @custom:invariant `testRoundTripBToA` never fails.\n *\n * Asserts that an encoded versioned nonce can always be decoded / re-encoded to reach\n * the same encoded value.\n */\n function echidna_round_trip_encoding_BToA() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripBToA should never\n // fail.\n return !failedRoundtripBToA;\n }\n}\n" - }, - "contracts/echidna/FuzzHashing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzHashing {\n bool internal failedCrossDomainHashHighVersion;\n bool internal failedCrossDomainHashV0;\n bool internal failedCrossDomainHashV1;\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash with a randomly\n * generated version. Only schema versions 0 and 1 are supported and all others should revert.\n */\n function testHashCrossDomainMessageHighVersion(\n uint16 _version,\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // hash the cross domain message. we don't need to store the result since the function\n // validates and should revert if an invalid version (>1) is encoded\n Hashing.hashCrossDomainMessage(encodedNonce, _sender, _target, _value, _gasLimit, _data);\n\n // check that execution never makes it this far for an invalid version\n if (_version > 1) {\n failedCrossDomainHashHighVersion = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v0 schema\n * and compares the output of a call to the unversioned function to the v0 function directly\n */\n function testHashCrossDomainMessageV0(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 0\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 0);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV0(\n _target,\n _sender,\n _data,\n encodedNonce\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV0 = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v1 schema\n * and compares the output of a call to the unversioned function to the v1 function directly\n */\n function testHashCrossDomainMessageV1(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 1\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 1);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV1(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV1 = true;\n }\n }\n\n /**\n * @custom:invariant `hashCrossDomainMessage` reverts if `version` is > `1`.\n *\n * The `hashCrossDomainMessage` function should always revert if the `version` passed is > `1`.\n */\n function echidna_hash_xdomain_msg_high_version() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage will never succeed for a version > 1\n return !failedCrossDomainHashHighVersion;\n }\n\n /**\n * @custom:invariant `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0`\n * are equivalent.\n *\n * If the version passed is 0, `hashCrossDomainMessage` and `hashCrossDomainMessageV0` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_0() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV0\n // should always match when the version passed is 0\n return !failedCrossDomainHashV0;\n }\n\n /**\n * @custom:invariant `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1`\n * are equivalent.\n *\n * If the version passed is 1, `hashCrossDomainMessage` and `hashCrossDomainMessageV1` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_1() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV1\n // should always match when the version passed is 1\n return !failedCrossDomainHashV1;\n }\n}\n" - }, - "contracts/echidna/FuzzOptimismPortal.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract EchidnaFuzzOptimismPortal {\n OptimismPortal internal portal;\n bool internal failedToComplete;\n\n constructor() {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n SystemConfig systemConfig = new SystemConfig({\n _owner: address(1),\n _overhead: 0,\n _scalar: 10000,\n _batcherHash: bytes32(0),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(0),\n _config: rcfg\n });\n\n portal = new OptimismPortal({\n _l2Oracle: L2OutputOracle(address(0)),\n _guardian: address(0),\n _paused: false,\n _config: systemConfig\n });\n }\n\n // A test intended to identify any unexpected halting conditions\n function testDepositTransactionCompletes(\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable {\n failedToComplete = true;\n require(!_isCreation || _to == address(0), \"EchidnaFuzzOptimismPortal: invalid test case.\");\n portal.depositTransaction{ value: _mint }(_to, _value, _gasLimit, _isCreation, _data);\n failedToComplete = false;\n }\n\n /**\n * @custom:invariant Deposits of any value should always succeed unless\n * `_to` = `address(0)` or `_isCreation` = `true`.\n *\n * All deposits, barring creation transactions and transactions sent to `address(0)`,\n * should always succeed.\n */\n function echidna_deposit_completes() public view returns (bool) {\n return !failedToComplete;\n }\n}\n" - }, - "contracts/echidna/FuzzResourceMetering.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {\n bool internal failedMaxGasPerBlock;\n bool internal failedRaiseBaseFee;\n bool internal failedLowerBaseFee;\n bool internal failedNeverBelowMinBaseFee;\n bool internal failedMaxRaiseBaseFeePerBlock;\n bool internal failedMaxLowerBaseFeePerBlock;\n\n // Used as a special flag for the purpose of identifying unchecked math errors specifically\n // in the test contracts, not the target contracts themselves.\n bool internal underflow;\n\n constructor() {\n initialize();\n }\n\n function initialize() internal initializer {\n __ResourceMetering_init();\n }\n\n function resourceConfig() public pure returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig();\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n return rcfg;\n }\n\n /**\n * @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test\n * the underlying resource metering/gas market logic\n */\n function testBurn(uint256 _gasToBurn, bool _raiseBaseFee) public {\n // Part 1: we cache the current param values and do some basic checks on them.\n uint256 cachedPrevBaseFee = uint256(params.prevBaseFee);\n uint256 cachedPrevBoughtGas = uint256(params.prevBoughtGas);\n uint256 cachedPrevBlockNum = uint256(params.prevBlockNum);\n\n ResourceMetering.ResourceConfig memory rcfg = resourceConfig();\n uint256 targetResourceLimit = uint256(rcfg.maxResourceLimit) /\n uint256(rcfg.elasticityMultiplier);\n\n // check that the last block's base fee hasn't dropped below the minimum\n if (cachedPrevBaseFee < uint256(rcfg.minimumBaseFee)) {\n failedNeverBelowMinBaseFee = true;\n }\n // check that the last block didn't consume more than the max amount of gas\n if (cachedPrevBoughtGas > uint256(rcfg.maxResourceLimit)) {\n failedMaxGasPerBlock = true;\n }\n\n // Part2: we perform the gas burn\n\n // force the gasToBurn into the correct range based on whether we intend to\n // raise or lower the baseFee after this block, respectively\n uint256 gasToBurn;\n if (_raiseBaseFee) {\n gasToBurn = bound(\n _gasToBurn,\n uint256(targetResourceLimit),\n uint256(rcfg.maxResourceLimit)\n );\n } else {\n gasToBurn = bound(_gasToBurn, 0, targetResourceLimit);\n }\n\n _burnInternal(uint64(gasToBurn));\n\n // Part 3: we run checks and modify our invariant flags based on the updated params values\n\n // Calculate the maximum allowed baseFee change (per block)\n uint256 maxBaseFeeChange = cachedPrevBaseFee / uint256(rcfg.baseFeeMaxChangeDenominator);\n\n // If the last block used more than the target amount of gas (and there were no\n // empty blocks in between), ensure this block's baseFee increased, but not by\n // more than the max amount per block\n if (\n (cachedPrevBoughtGas > uint256(targetResourceLimit)) &&\n (uint256(params.prevBlockNum) - cachedPrevBlockNum == 1)\n ) {\n failedRaiseBaseFee = failedRaiseBaseFee || (params.prevBaseFee <= cachedPrevBaseFee);\n failedMaxRaiseBaseFeePerBlock =\n failedMaxRaiseBaseFeePerBlock ||\n ((uint256(params.prevBaseFee) - cachedPrevBaseFee) < maxBaseFeeChange);\n }\n\n // If the last block used less than the target amount of gas, (or was empty),\n // ensure that: this block's baseFee was decreased, but not by more than the max amount\n if (\n (cachedPrevBoughtGas < uint256(targetResourceLimit)) ||\n (uint256(params.prevBlockNum) - cachedPrevBlockNum > 1)\n ) {\n // Invariant: baseFee should decrease\n failedLowerBaseFee =\n failedLowerBaseFee ||\n (uint256(params.prevBaseFee) > cachedPrevBaseFee);\n\n if (params.prevBlockNum - cachedPrevBlockNum == 1) {\n // No empty blocks\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n } else if (params.prevBlockNum - cachedPrevBlockNum > 1) {\n // We have at least one empty block\n // Update the maxBaseFeeChange to account for multiple blocks having passed\n unchecked {\n maxBaseFeeChange = uint256(\n int256(cachedPrevBaseFee) -\n Arithmetic.clamp(\n Arithmetic.cdexp(\n int256(cachedPrevBaseFee),\n int256(uint256(rcfg.baseFeeMaxChangeDenominator)),\n int256(uint256(params.prevBlockNum) - cachedPrevBlockNum)\n ),\n int256(uint256(rcfg.minimumBaseFee)),\n int256(uint256(rcfg.maximumBaseFee))\n )\n );\n }\n\n // Detect an underflow in the previous calculation.\n // Without using unchecked above, and detecting the underflow here, echidna would\n // otherwise ignore the revert.\n underflow = underflow || maxBaseFeeChange > cachedPrevBaseFee;\n\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n }\n }\n }\n\n function _burnInternal(uint64 _gasToBurn) private metered(_gasToBurn) {}\n\n /**\n * @custom:invariant The base fee should increase if the last block used more\n * than the target amount of gas\n *\n * If the last block used more than the target amount of gas (and there were no\n * empty blocks in between), ensure this block's baseFee increased, but not by\n * more than the max amount per block.\n */\n function echidna_high_usage_raise_baseFee() public view returns (bool) {\n return !failedRaiseBaseFee;\n }\n\n /**\n * @custom:invariant The base fee should decrease if the last block used less\n * than the target amount of gas\n *\n * If the previous block used less than the target amount of gas, the base fee should decrease,\n * but not more than the max amount.\n */\n function echidna_low_usage_lower_baseFee() public view returns (bool) {\n return !failedLowerBaseFee;\n }\n\n /**\n * @custom:invariant A block's base fee should never be below `MINIMUM_BASE_FEE`\n *\n * This test asserts that a block's base fee can never drop below the\n * `MINIMUM_BASE_FEE` threshold.\n */\n function echidna_never_below_min_baseFee() public view returns (bool) {\n return !failedNeverBelowMinBaseFee;\n }\n\n /**\n * @custom:invariant A block can never consume more than `MAX_RESOURCE_LIMIT` gas.\n *\n * This test asserts that a block can never consume more than the `MAX_RESOURCE_LIMIT`\n * gas threshold.\n */\n function echidna_never_above_max_gas_limit() public view returns (bool) {\n return !failedMaxGasPerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be raised more than the max base fee change.\n *\n * After a block consumes more gas than the target gas, the base fee cannot be raised\n * more than the maximum amount allowed. The max base fee change (per-block) is derived\n * as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_increase() public view returns (bool) {\n return !failedMaxRaiseBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be lowered more than the max base fee change.\n *\n * After a block consumes less than the target gas, the base fee cannot be lowered more\n * than the maximum amount allowed. The max base fee change (per-block) is derived as\n *follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_decrease() public view returns (bool) {\n return !failedMaxLowerBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The `maxBaseFeeChange` calculation over multiple blocks can never\n * underflow.\n *\n * When calculating the `maxBaseFeeChange` after multiple empty blocks, the calculation\n * should never be allowed to underflow.\n */\n function echidna_underflow() public view returns (bool) {\n return !underflow;\n }\n}\n" - }, - "contracts/governance/GovernanceToken.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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 * @custom:predeploy 0x4200000000000000000000000000000000000042\n * @title GovernanceToken\n * @notice The Optimism token used in governance and supporting voting and delegation. Implements\n * EIP 2612 allowing signed approvals. Contract is \"owned\" by a `MintManager` instance with\n * permission to the `mint` function only, for the purposes of enforcing the token inflation\n * schedule.\n */\ncontract GovernanceToken is ERC20Burnable, ERC20Votes, Ownable {\n constructor() ERC20(\"Optimism\", \"OP\") ERC20Permit(\"Optimism\") {}\n\n /**\n * @notice Allows the owner to mint tokens.\n *\n * @param _account The account receiving minted tokens.\n * @param _amount The amount of tokens to mint.\n */\n function mint(address _account, uint256 _amount) public onlyOwner {\n _mint(_account, _amount);\n }\n\n /**\n * @notice Callback called after a token transfer.\n *\n * @param from The account sending tokens.\n * @param to The account receiving tokens.\n * @param amount The amount of tokens being transfered.\n */\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 /**\n * @notice Internal mint function.\n *\n * @param to The account receiving minted tokens.\n * @param amount The amount of tokens to mint.\n */\n function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._mint(to, amount);\n }\n\n /**\n * @notice Internal burn function.\n *\n * @param account The account that tokens will be burned from.\n * @param amount The amount of tokens that will be burned.\n */\n function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._burn(account, amount);\n }\n}\n" - }, - "contracts/governance/MintManager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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(\n mintPermittedAfter <= block.timestamp,\n \"MintManager: minting not permitted yet\"\n );\n\n require(\n _amount <= (governanceToken.totalSupply() * MINT_CAP) / DENOMINATOR,\n \"MintManager: mint amount exceeds cap\"\n );\n }\n\n mintPermittedAfter = block.timestamp + MINT_PERIOD;\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(\n _newMintManager != address(0),\n \"MintManager: mint manager cannot be the zero address\"\n );\n\n governanceToken.transferOwnership(_newMintManager);\n }\n}\n" - }, - "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" - }, - "contracts/legacy/DeployerWhitelist.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000002\n * @title DeployerWhitelist\n * @notice DeployerWhitelist is a legacy contract that was originally used to act as a whitelist of\n * addresses allowed to the Optimism network. The DeployerWhitelist has since been\n * disabled, but the code is kept in state for the sake of full backwards compatibility.\n * As of the Bedrock upgrade, the DeployerWhitelist is completely unused by the Optimism\n * system and could, in theory, be removed entirely.\n */\ncontract DeployerWhitelist is Semver {\n /**\n * @notice Address of the owner of this contract. Note that when this address is set to\n * address(0), the whitelist is disabled.\n */\n address public owner;\n\n /**\n * @notice Mapping of deployer addresses to boolean whitelist status.\n */\n mapping(address => bool) public whitelist;\n\n /**\n * @notice Emitted when the owner of this contract changes.\n *\n * @param oldOwner Address of the previous owner.\n * @param newOwner Address of the new owner.\n */\n event OwnerChanged(address oldOwner, address newOwner);\n\n /**\n * @notice Emitted when the whitelist status of a deployer changes.\n *\n * @param deployer Address of the deployer.\n * @param whitelisted Boolean indicating whether the deployer is whitelisted.\n */\n event WhitelistStatusChanged(address deployer, bool whitelisted);\n\n /**\n * @notice Emitted when the whitelist is disabled.\n *\n * @param oldOwner Address of the final owner of the whitelist.\n */\n event WhitelistDisabled(address oldOwner);\n\n /**\n * @notice Blocks functions to anyone except the contract owner.\n */\n modifier onlyOwner() {\n require(\n msg.sender == owner,\n \"DeployerWhitelist: function can only be called by the owner of this contract\"\n );\n _;\n }\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Adds or removes an address from the deployment whitelist.\n *\n * @param _deployer Address to update permissions for.\n * @param _isWhitelisted Whether or not the address is whitelisted.\n */\n function setWhitelistedDeployer(address _deployer, bool _isWhitelisted) external onlyOwner {\n whitelist[_deployer] = _isWhitelisted;\n emit WhitelistStatusChanged(_deployer, _isWhitelisted);\n }\n\n /**\n * @notice Updates the owner of this contract.\n *\n * @param _owner Address of the new owner.\n */\n function setOwner(address _owner) external onlyOwner {\n // Prevent users from setting the whitelist owner to address(0) except via\n // enableArbitraryContractDeployment. If you want to burn the whitelist owner, send it to\n // any other address that doesn't have a corresponding knowable private key.\n require(\n _owner != address(0),\n \"DeployerWhitelist: can only be disabled via enableArbitraryContractDeployment\"\n );\n\n emit OwnerChanged(owner, _owner);\n owner = _owner;\n }\n\n /**\n * @notice Permanently enables arbitrary contract deployment and deletes the owner.\n */\n function enableArbitraryContractDeployment() external onlyOwner {\n emit WhitelistDisabled(owner);\n owner = address(0);\n }\n\n /**\n * @notice Checks whether an address is allowed to deploy contracts.\n *\n * @param _deployer Address to check.\n *\n * @return Whether or not the address can deploy contracts.\n */\n function isDeployerAllowed(address _deployer) external view returns (bool) {\n return (owner == address(0) || whitelist[_deployer]);\n }\n}\n" - }, - "contracts/legacy/L1BlockNumber.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000013\n * @title L1BlockNumber\n * @notice L1BlockNumber is a legacy contract that fills the roll of the OVM_L1BlockNumber contract\n * in the old version of the Optimism system. Only necessary for backwards compatibility.\n * If you want to access the L1 block number going forward, you should use the L1Block\n * contract instead.\n */\ncontract L1BlockNumber is Semver {\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Returns the L1 block number.\n */\n receive() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Returns the L1 block number.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Retrieves the latest L1 block number.\n *\n * @return Latest L1 block number.\n */\n function getL1BlockNumber() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).number();\n }\n}\n" - }, - "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/legacy/LegacyERC20ETH.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000\n * @title LegacyERC20ETH\n * @notice LegacyERC20ETH is a legacy contract that held ETH balances before the Bedrock upgrade.\n * All ETH balances held within this contract were migrated to the state trie as part of\n * the Bedrock upgrade. Functions within this contract that mutate state were already\n * disabled as part of the EVM equivalence upgrade.\n */\ncontract LegacyERC20ETH is OptimismMintableERC20 {\n /**\n * @notice Initializes the contract as an Optimism Mintable ERC20.\n */\n constructor()\n OptimismMintableERC20(Predeploys.L2_STANDARD_BRIDGE, address(0), \"Ether\", \"ETH\")\n {}\n\n /**\n * @notice Returns the ETH balance of the target account. Overrides the base behavior of the\n * contract to preserve the invariant that the balance within this contract always\n * matches the balance in the state trie.\n *\n * @param _who Address of the account to query.\n *\n * @return The ETH balance of the target account.\n */\n function balanceOf(address _who) public view virtual override returns (uint256) {\n return address(_who).balance;\n }\n\n /**\n * @custom:blocked\n * @notice Mints some amount of ETH.\n */\n function mint(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: mint is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Burns some amount of ETH.\n */\n function burn(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: burn is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers some amount of ETH.\n */\n function transfer(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transfer is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Approves a spender to spend some amount of ETH.\n */\n function approve(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: approve is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers funds from some sender account.\n */\n function transferFrom(\n address,\n address,\n uint256\n ) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transferFrom is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Increases the allowance of a spender.\n */\n function increaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Decreases the allowance of a spender.\n */\n function decreaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n }\n}\n" - }, - "contracts/legacy/LegacyMessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000000\n * @title LegacyMessagePasser\n * @notice The LegacyMessagePasser was the low-level mechanism used to send messages from L2 to L1\n * before the Bedrock upgrade. It is now deprecated in favor of the new MessagePasser.\n */\ncontract LegacyMessagePasser is Semver {\n /**\n * @notice Mapping of sent message hashes to boolean status.\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Passes a message to L1.\n *\n * @param _message Message to pass to L1.\n */\n function passMessageToL1(bytes memory _message) external {\n sentMessages[keccak256(abi.encodePacked(_message, msg.sender))] = true;\n }\n}\n" - }, - "contracts/legacy/LegacyMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { ILegacyMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @title LegacyMintableERC20\n * @notice The legacy implementation of the OptimismMintableERC20. This\n * contract is deprecated and should no longer be used.\n */\ncontract LegacyMintableERC20 is ILegacyMintableERC20, ERC20 {\n /**\n * @notice Emitted when the token is minted by the bridge.\n */\n event Mint(address indexed _account, uint256 _amount);\n\n /**\n * @notice Emitted when a token is burned by the bridge.\n */\n event Burn(address indexed _account, uint256 _amount);\n\n /**\n * @notice The token on the remote domain.\n */\n address public l1Token;\n\n /**\n * @notice The local bridge.\n */\n address public l2Bridge;\n\n /**\n * @param _l2Bridge Address of the L2 standard bridge.\n * @param _l1Token Address of the corresponding L1 token.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n */\n constructor(\n address _l2Bridge,\n address _l1Token,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) {\n l1Token = _l1Token;\n l2Bridge = _l2Bridge;\n }\n\n /**\n * @notice Modifier that requires the contract was called by the bridge.\n */\n modifier onlyL2Bridge() {\n require(msg.sender == l2Bridge, \"Only L2 Bridge can mint and burn\");\n _;\n }\n\n /**\n * @notice EIP165 implementation.\n */\n function supportsInterface(bytes4 _interfaceId) public pure returns (bool) {\n bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^\n ILegacyMintableERC20.mint.selector ^\n ILegacyMintableERC20.burn.selector;\n return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n }\n\n /**\n * @notice Only the bridge can mint tokens.\n * @param _to The account receiving tokens.\n * @param _amount The amount of tokens to receive.\n */\n function mint(address _to, uint256 _amount) public virtual onlyL2Bridge {\n _mint(_to, _amount);\n\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Only the bridge can burn tokens.\n * @param _from The account having tokens burnt.\n * @param _amount The amount of tokens being burnt.\n */\n function burn(address _from, uint256 _amount) public virtual onlyL2Bridge {\n _burn(_from, _amount);\n\n emit Burn(_from, _amount);\n }\n}\n" - }, - "contracts/legacy/ResolvedDelegateProxy.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressManager } from \"./AddressManager.sol\";\n\n/**\n * @custom:legacy\n * @title ResolvedDelegateProxy\n * @notice ResolvedDelegateProxy is a legacy proxy contract that makes use of the AddressManager to\n * resolve the implementation address. We're maintaining this contract for backwards\n * compatibility so we can manage all legacy proxies where necessary.\n */\ncontract ResolvedDelegateProxy {\n /**\n * @notice Mapping used to store the implementation name that corresponds to this contract. A\n * mapping was originally used as a way to bypass the same issue normally solved by\n * storing the implementation address in a specific storage slot that does not conflict\n * with any other storage slot. Generally NOT a safe solution but works as long as the\n * implementation does not also keep a mapping in the first storage slot.\n */\n mapping(address => string) private implementationName;\n\n /**\n * @notice Mapping used to store the address of the AddressManager contract where the\n * implementation address will be resolved from. Same concept here as with the above\n * mapping. Also generally unsafe but fine if the implementation doesn't keep a mapping\n * in the second storage slot.\n */\n mapping(address => AddressManager) private addressManager;\n\n /**\n * @param _addressManager Address of the AddressManager.\n * @param _implementationName implementationName of the contract to proxy to.\n */\n constructor(AddressManager _addressManager, string memory _implementationName) {\n addressManager[address(this)] = _addressManager;\n implementationName[address(this)] = _implementationName;\n }\n\n /**\n * @notice Fallback, performs a delegatecall to the resolved implementation address.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n address target = addressManager[address(this)].getAddress(\n (implementationName[address(this)])\n );\n\n require(target != address(0), \"ResolvedDelegateProxy: target address must be initialized\");\n\n // slither-disable-next-line controlled-delegatecall\n (bool success, bytes memory returndata) = target.delegatecall(msg.data);\n\n if (success == true) {\n assembly {\n return(add(returndata, 0x20), mload(returndata))\n }\n } else {\n assembly {\n revert(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n" - }, - "contracts/libraries/Arithmetic.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { SignedMath } from \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\nimport { FixedPointMathLib } from \"@rari-capital/solmate/src/utils/FixedPointMathLib.sol\";\n\n/**\n * @title Arithmetic\n * @notice Even more math than before.\n */\nlibrary Arithmetic {\n /**\n * @notice Clamps a value between a minimum and maximum.\n *\n * @param _value The value to clamp.\n * @param _min The minimum value.\n * @param _max The maximum value.\n *\n * @return The clamped value.\n */\n function clamp(\n int256 _value,\n int256 _min,\n int256 _max\n ) internal pure returns (int256) {\n return SignedMath.min(SignedMath.max(_value, _min), _max);\n }\n\n /**\n * @notice (c)oefficient (d)enominator (exp)onentiation function.\n * Returns the result of: c * (1 - 1/d)^exp.\n *\n * @param _coefficient Coefficient of the function.\n * @param _denominator Fractional denominator.\n * @param _exponent Power function exponent.\n *\n * @return Result of c * (1 - 1/d)^exp.\n */\n function cdexp(\n int256 _coefficient,\n int256 _denominator,\n int256 _exponent\n ) internal pure returns (int256) {\n return\n (_coefficient *\n (FixedPointMathLib.powWad(1e18 - (1e18 / _denominator), _exponent * 1e18))) / 1e18;\n }\n}\n" - }, - "contracts/libraries/Burn.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Burn\n * @notice Utilities for burning stuff.\n */\nlibrary Burn {\n /**\n * Burns a given amount of ETH.\n *\n * @param _amount Amount of ETH to burn.\n */\n function eth(uint256 _amount) internal {\n new Burner{ value: _amount }();\n }\n\n /**\n * Burns a given amount of gas.\n *\n * @param _amount Amount of gas to burn.\n */\n function gas(uint256 _amount) internal view {\n uint256 i = 0;\n uint256 initialGas = gasleft();\n while (initialGas - gasleft() < _amount) {\n ++i;\n }\n }\n}\n\n/**\n * @title Burner\n * @notice Burner self-destructs on creation and sends all ETH to itself, removing all ETH given to\n * the contract from the circulating supply. Self-destructing is the only way to remove ETH\n * from the circulating supply.\n */\ncontract Burner {\n constructor() payable {\n selfdestruct(payable(address(this)));\n }\n}\n" - }, - "contracts/libraries/Bytes.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Bytes\n * @notice Bytes is a library for manipulating byte arrays.\n */\nlibrary Bytes {\n /**\n * @custom:attribution https://github.com/GNSPS/solidity-bytes-utils\n * @notice Slices a byte array with a given starting index and length. Returns a new byte array\n * as opposed to a pointer to the original array. Will throw if trying to slice more\n * bytes than exist in the array.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n * @param _length Length of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n unchecked {\n require(_length + 31 >= _length, \"slice_overflow\");\n require(_start + _length >= _start, \"slice_overflow\");\n require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n }\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n /**\n * @notice Slices a byte array with a given starting index up to the end of the original byte\n * array. Returns a new array rathern than a pointer to the original.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {\n if (_start >= _bytes.length) {\n return bytes(\"\");\n }\n return slice(_bytes, _start, _bytes.length - _start);\n }\n\n /**\n * @notice Converts a byte array into a nibble array by splitting each byte into two nibbles.\n * Resulting nibble array will be exactly twice as long as the input byte array.\n *\n * @param _bytes Input byte array to convert.\n *\n * @return Resulting nibble array.\n */\n function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n uint256 bytesLength = _bytes.length;\n bytes memory nibbles = new bytes(bytesLength * 2);\n bytes1 b;\n\n for (uint256 i = 0; i < bytesLength; ) {\n b = _bytes[i];\n nibbles[i * 2] = b >> 4;\n nibbles[i * 2 + 1] = b & 0x0f;\n unchecked {\n ++i;\n }\n }\n\n return nibbles;\n }\n\n /**\n * @notice Compares two byte arrays by comparing their keccak256 hashes.\n *\n * @param _bytes First byte array to compare.\n * @param _other Second byte array to compare.\n *\n * @return True if the two byte arrays are equal, false otherwise.\n */\n function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {\n return keccak256(_bytes) == keccak256(_other);\n }\n}\n" - }, - "contracts/libraries/Constants.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\n/**\n * @title Constants\n * @notice Constants is a library for storing constants. Simple! Don't put everything in here, just\n * the stuff used in multiple contracts. Constants that only apply to a single contract\n * should be defined in that contract instead.\n */\nlibrary Constants {\n /**\n * @notice Special address to be used as the tx origin for gas estimation calls in the\n * OptimismPortal and CrossDomainMessenger calls. You only need to use this address if\n * the minimum gas limit specified by the user is not actually enough to execute the\n * given message and you're attempting to estimate the actual necessary gas limit. We\n * use address(1) because it's the ecrecover precompile and therefore guaranteed to\n * never have any code on any EVM chain.\n */\n address internal constant ESTIMATION_ADDRESS = address(1);\n\n /**\n * @notice Value used for the L2 sender storage slot in both the OptimismPortal and the\n * CrossDomainMessenger contracts before an actual sender is set. This value is\n * non-zero to reduce the gas cost of message passing transactions.\n */\n address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD;\n\n /**\n * @notice Returns the default values for the ResourceConfig. These are the recommended values\n * for a production network.\n */\n function DEFAULT_RESOURCE_CONFIG()\n internal\n pure\n returns (ResourceMetering.ResourceConfig memory)\n {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n return config;\n }\n}\n" - }, - "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" - }, - "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" - }, - "contracts/libraries/LegacyCrossDomainUtils.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n// Importing from the legacy contracts package causes issues with the build of the contract bindings\n// so we just copy the library here from\n// /packages/contracts/contracts/libraries/bridge/Lib_CrossDomainUtils.sol at commit\n// 7866168c\n/**\n * @title LegacyCrossDomainUtils\n */\nlibrary LegacyCrossDomainUtils {\n /**\n * Generates the correct cross domain calldata for a message.\n * @param _target Target contract address.\n * @param _sender Message sender address.\n * @param _message Message to send to the target.\n * @param _messageNonce Nonce for the provided message.\n * @return ABI encoded cross domain calldata.\n */\n function encodeXDomainCalldata(\n address _target,\n address _sender,\n bytes memory _message,\n uint256 _messageNonce\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(address,address,bytes,uint256)\",\n _target,\n _sender,\n _message,\n _messageNonce\n );\n }\n}\n" - }, - "contracts/libraries/Predeploys.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Predeploys\n * @notice Contains constant addresses for contracts that are pre-deployed to the L2 system.\n */\nlibrary Predeploys {\n /**\n * @notice Address of the L2ToL1MessagePasser predeploy.\n */\n address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016;\n\n /**\n * @notice Address of the L2CrossDomainMessenger predeploy.\n */\n address internal constant L2_CROSS_DOMAIN_MESSENGER =\n 0x4200000000000000000000000000000000000007;\n\n /**\n * @notice Address of the L2StandardBridge predeploy.\n */\n address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;\n\n /**\n * @notice Address of the L2ERC721Bridge predeploy.\n */\n address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014;\n\n /**\n * @notice Address of the SequencerFeeWallet predeploy.\n */\n address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;\n\n /**\n * @notice Address of the OptimismMintableERC20Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY =\n 0x4200000000000000000000000000000000000012;\n\n /**\n * @notice Address of the OptimismMintableERC721Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY =\n 0x4200000000000000000000000000000000000017;\n\n /**\n * @notice Address of the L1Block predeploy.\n */\n address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015;\n\n /**\n * @notice Address of the GasPriceOracle predeploy. Includes fee information\n * and helpers for computing the L1 portion of the transaction fee.\n */\n address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F;\n\n /**\n * @custom:legacy\n * @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger\n * or access tx.origin (or msg.sender) in a L1 to L2 transaction instead.\n */\n address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;\n\n /**\n * @custom:legacy\n * @notice Address of the DeployerWhitelist predeploy. No longer active.\n */\n address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the\n * state trie as of the Bedrock upgrade. Contract has been locked and write functions\n * can no longer be accessed.\n */\n address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;\n\n /**\n * @custom:legacy\n * @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy\n * instead, which exposes more information about the L1 state.\n */\n address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated\n * L2ToL1MessagePasser contract instead.\n */\n address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;\n\n /**\n * @notice Address of the ProxyAdmin predeploy.\n */\n address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018;\n\n /**\n * @notice Address of the BaseFeeVault predeploy.\n */\n address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019;\n\n /**\n * @notice Address of the L1FeeVault predeploy.\n */\n address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A;\n\n /**\n * @notice Address of the GovernanceToken predeploy.\n */\n address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042;\n}\n" - }, - "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, 32), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n\n /**\n * @notice Helper function to determine if there is sufficient gas remaining within the context\n * to guarantee that the minimum gas requirement for a call will be met as well as\n * optionally reserving a specified amount of gas for after the call has concluded.\n * @param _minGas The minimum amount of gas that may be passed to the target context.\n * @param _reservedGas Optional amount of gas to reserve for the caller after the execution\n * of the target context.\n * @return `true` if there is enough gas remaining to safely supply `_minGas` to the target\n * context as well as reserve `_reservedGas` for the caller after the execution of\n * the target context.\n * @dev !!!!! FOOTGUN ALERT !!!!!\n * 1.) The 40_000 base buffer is to account for the worst case of the dynamic cost of the\n * `CALL` opcode's `address_access_cost`, `positive_value_cost`, and\n * `value_to_empty_account_cost` factors with an added buffer of 5,700 gas. It is\n * still possible to self-rekt by initiating a withdrawal with a minimum gas limit\n * that does not account for the `memory_expansion_cost` & `code_execution_cost`\n * factors of the dynamic cost of the `CALL` opcode.\n * 2.) This function should *directly* precede the external call if possible. There is an\n * added buffer to account for gas consumed between this check and the call, but it\n * is only 5,700 gas.\n * 3.) Because EIP-150 ensures that a maximum of 63/64ths of the remaining gas in the call\n * frame may be passed to a subcontext, we need to ensure that the gas will not be\n * truncated.\n * 4.) Use wisely. This function is not a silver bullet.\n */\n function hasMinGas(uint256 _minGas, uint256 _reservedGas) internal view returns (bool) {\n bool _hasMinGas;\n assembly {\n // Equation: gas × 63 ≥ minGas × 64 + 63(40_000 + reservedGas)\n _hasMinGas := iszero(\n lt(mul(gas(), 63), add(mul(_minGas, 64), mul(add(40000, _reservedGas), 63)))\n )\n }\n return _hasMinGas;\n }\n\n /**\n * @notice Perform a low level call without copying any returndata. This function\n * will revert if the call cannot be performed with the specified minimum\n * gas.\n *\n * @param _target Address to call\n * @param _minGas The minimum amount of gas that may be passed 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 callWithMinGas(\n address _target,\n uint256 _minGas,\n uint256 _value,\n bytes memory _calldata\n ) internal returns (bool) {\n bool _success;\n bool _hasMinGas = hasMinGas(_minGas, 0);\n assembly {\n // Assertion: gasleft() >= (_minGas * 64) / 63 + 40_000\n if iszero(_hasMinGas) {\n // Store the \"Error(string)\" selector in scratch space.\n mstore(0, 0x08c379a0)\n // Store the pointer to the string length in scratch space.\n mstore(32, 32)\n // Store the string.\n //\n // SAFETY:\n // - We pad the beginning of the string with two zero bytes as well as the\n // length (24) to ensure that we override the free memory pointer at offset\n // 0x40. This is necessary because the free memory pointer is likely to\n // be greater than 1 byte when this function is called, but it is incredibly\n // unlikely that it will be greater than 3 bytes. As for the data within\n // 0x60, it is ensured that it is 0 due to 0x60 being the zero offset.\n // - It's fine to clobber the free memory pointer, we're reverting.\n mstore(88, 0x0000185361666543616c6c3a204e6f7420656e6f75676820676173)\n\n // Revert with 'Error(\"SafeCall: Not enough gas\")'\n revert(28, 100)\n }\n\n // The call will be supplied at least ((_minGas * 64) / 63) gas due to the\n // above assertion. This ensures that, in all circumstances (except for when the\n // `_minGas` does not account for the `memory_expansion_cost` and `code_execution_cost`\n // factors of the dynamic cost of the `CALL` opcode), the call will receive at least\n // the minimum amount of gas specified.\n _success := call(\n gas(), // gas\n _target, // recipient\n _value, // ether value\n add(_calldata, 32), // inloc\n mload(_calldata), // inlen\n 0x00, // outloc\n 0x00 // outlen\n )\n }\n return _success;\n }\n}\n" - }, - "contracts/libraries/Types.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 * @custom:field outputRoot Hash of the L2 output.\n * @custom:field timestamp Timestamp of the L1 block that the output root was submitted in.\n * @custom:field l2BlockNumber L2 block number that the output corresponds to.\n */\n struct OutputProposal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2BlockNumber;\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 * @custom:field version Version of the output root.\n * @custom:field stateRoot Root of the state trie at the block of this output.\n * @custom:field messagePasserStorageRoot Root of the message passer storage trie.\n * @custom:field latestBlockhash Hash of the block this output was generated from.\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 * @custom:field from Address of the sender of the transaction.\n * @custom:field to Address of the recipient of the transaction.\n * @custom:field isCreation True if the transaction is a contract creation.\n * @custom:field value Value to send to the recipient.\n * @custom:field mint Amount of ETH to mint.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the transaction.\n * @custom:field l1BlockHash Hash of the block the transaction was submitted in.\n * @custom:field logIndex Index of the log in the block the transaction was submitted in.\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 * @custom:field nonce Nonce of the withdrawal transaction\n * @custom:field sender Address of the sender of the transaction.\n * @custom:field target Address of the recipient of the transaction.\n * @custom:field value Value to send to the recipient.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the 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" - }, - "contracts/libraries/rlp/RLPReader.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\n/**\n * @custom:attribution https://github.com/hamdiallam/Solidity-RLP\n * @title RLPReader\n * @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted\n * from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with\n * various tweaks to improve readability.\n */\nlibrary RLPReader {\n /**\n * Custom pointer type to avoid confusion between pointers and uint256s.\n */\n type MemoryPointer is uint256;\n\n /**\n * @notice RLP item types.\n *\n * @custom:value DATA_ITEM Represents an RLP data item (NOT a list).\n * @custom:value LIST_ITEM Represents an RLP list item.\n */\n enum RLPItemType {\n DATA_ITEM,\n LIST_ITEM\n }\n\n /**\n * @notice Struct representing an RLP item.\n *\n * @custom:field length Length of the RLP item.\n * @custom:field ptr Pointer to the RLP item in memory.\n */\n struct RLPItem {\n uint256 length;\n MemoryPointer ptr;\n }\n\n /**\n * @notice Max list length that this library will accept.\n */\n uint256 internal constant MAX_LIST_LENGTH = 32;\n\n /**\n * @notice Converts bytes to a reference to memory position and length.\n *\n * @param _in Input bytes to convert.\n *\n * @return Output memory reference.\n */\n function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) {\n // Empty arrays are not RLP items.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr;\n assembly {\n ptr := add(_in, 32)\n }\n\n return RLPItem({ length: _in.length, ptr: ptr });\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) {\n (uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.LIST_ITEM,\n \"RLPReader: decoded item type for list is not a list item\"\n );\n\n require(\n listOffset + listLength == _in.length,\n \"RLPReader: list item has an invalid data remainder\"\n );\n\n // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by\n // writing to the length. Since we can't know the number of RLP items without looping over\n // the entire input, we'd have to loop twice to accurately size this array. It's easier to\n // simply set a reasonable maximum list length and decrease the size before we finish.\n RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH);\n\n uint256 itemCount = 0;\n uint256 offset = listOffset;\n while (offset < _in.length) {\n (uint256 itemOffset, uint256 itemLength, ) = _decodeLength(\n RLPItem({\n length: _in.length - offset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n })\n );\n\n // We don't need to check itemCount < out.length explicitly because Solidity already\n // handles this check on our behalf, we'd just be wasting gas.\n out[itemCount] = RLPItem({\n length: itemLength + itemOffset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n });\n\n itemCount += 1;\n offset += itemOffset + itemLength;\n }\n\n // Decrease the array size to match the actual item count.\n assembly {\n mstore(out, itemCount)\n }\n\n return out;\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(bytes memory _in) internal pure returns (RLPItem[] memory) {\n return readList(toRLPItem(_in));\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.DATA_ITEM,\n \"RLPReader: decoded item type for bytes is not a data item\"\n );\n\n require(\n _in.length == itemOffset + itemLength,\n \"RLPReader: bytes value contains an invalid remainder\"\n );\n\n return _copy(_in.ptr, itemOffset, itemLength);\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(bytes memory _in) internal pure returns (bytes memory) {\n return readBytes(toRLPItem(_in));\n }\n\n /**\n * @notice Reads the raw bytes of an RLP item.\n *\n * @param _in RLP item to read.\n *\n * @return Raw RLP bytes.\n */\n function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n return _copy(_in.ptr, 0, _in.length);\n }\n\n /**\n * @notice Decodes the length of an RLP item.\n *\n * @param _in RLP item to decode.\n *\n * @return Offset of the encoded data.\n * @return Length of the encoded data.\n * @return RLP item type (LIST_ITEM or DATA_ITEM).\n */\n function _decodeLength(RLPItem memory _in)\n private\n pure\n returns (\n uint256,\n uint256,\n RLPItemType\n )\n {\n // Short-circuit if there's nothing to decode, note that we perform this check when\n // the user creates an RLP item via toRLPItem, but it's always possible for them to bypass\n // that function and create an RLP item directly. So we need to check this anyway.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr = _in.ptr;\n uint256 prefix;\n assembly {\n prefix := byte(0, mload(ptr))\n }\n\n if (prefix <= 0x7f) {\n // Single byte.\n return (0, 1, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xb7) {\n // Short string.\n\n // slither-disable-next-line variable-scope\n uint256 strLen = prefix - 0x80;\n\n require(\n _in.length > strLen,\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n strLen != 1 || firstByteOfContent >= 0x80,\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n\n return (1, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xbf) {\n // Long string.\n uint256 lenOfStrLen = prefix - 0xb7;\n\n require(\n _in.length > lenOfStrLen,\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n\n uint256 strLen;\n assembly {\n strLen := shr(sub(256, mul(8, lenOfStrLen)), mload(add(ptr, 1)))\n }\n\n require(\n strLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long string)\"\n );\n\n require(\n _in.length > lenOfStrLen + strLen,\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n\n return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xf7) {\n // Short list.\n // slither-disable-next-line variable-scope\n uint256 listLen = prefix - 0xc0;\n\n require(\n _in.length > listLen,\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n\n return (1, listLen, RLPItemType.LIST_ITEM);\n } else {\n // Long list.\n uint256 lenOfListLen = prefix - 0xf7;\n\n require(\n _in.length > lenOfListLen,\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long list)\"\n );\n\n uint256 listLen;\n assembly {\n listLen := shr(sub(256, mul(8, lenOfListLen)), mload(add(ptr, 1)))\n }\n\n require(\n listLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long list)\"\n );\n\n require(\n _in.length > lenOfListLen + listLen,\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n\n return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);\n }\n }\n\n /**\n * @notice Copies the bytes from a memory location.\n *\n * @param _src Pointer to the location to read from.\n * @param _offset Offset to start reading from.\n * @param _length Number of bytes to read.\n *\n * @return Copied bytes.\n */\n function _copy(\n MemoryPointer _src,\n uint256 _offset,\n uint256 _length\n ) private pure returns (bytes memory) {\n bytes memory out = new bytes(_length);\n if (_length == 0) {\n return out;\n }\n\n // Mostly based on Solidity's copy_memory_to_memory:\n // solhint-disable max-line-length\n // https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114\n uint256 src = MemoryPointer.unwrap(_src) + _offset;\n assembly {\n let dest := add(out, 32)\n let i := 0\n for {\n\n } lt(i, _length) {\n i := add(i, 32)\n } {\n mstore(add(dest, i), mload(add(src, i)))\n }\n\n if gt(i, _length) {\n mstore(add(dest, _length), 0)\n }\n }\n\n return out;\n }\n}\n" - }, - "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" - }, - "contracts/libraries/trie/MerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Bytes } from \"../Bytes.sol\";\nimport { RLPReader } from \"../rlp/RLPReader.sol\";\n\n/**\n * @title MerkleTrie\n * @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie\n * inclusion proofs. By default, this library assumes a hexary trie. One can change the\n * trie radix constant to support other trie radixes.\n */\nlibrary MerkleTrie {\n /**\n * @notice Struct representing a node in the trie.\n *\n * @custom:field encoded The RLP-encoded node.\n * @custom:field decoded The RLP-decoded node.\n */\n struct TrieNode {\n bytes encoded;\n RLPReader.RLPItem[] decoded;\n }\n\n /**\n * @notice Determines the number of elements per branch node.\n */\n uint256 internal constant TREE_RADIX = 16;\n\n /**\n * @notice Branch nodes have TREE_RADIX elements and one value element.\n */\n uint256 internal constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;\n\n /**\n * @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.\n */\n uint256 internal constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;\n\n /**\n * @notice Prefix for even-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_EVEN = 0;\n\n /**\n * @notice Prefix for odd-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_ODD = 1;\n\n /**\n * @notice Prefix for even-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_EVEN = 2;\n\n /**\n * @notice Prefix for odd-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_ODD = 3;\n\n /**\n * @notice Verifies a proof that a given key/value pair is present in the trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n return Bytes.equal(_value, get(_key, _proof, _root));\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n require(_key.length > 0, \"MerkleTrie: empty key\");\n\n TrieNode[] memory proof = _parseProof(_proof);\n bytes memory key = Bytes.toNibbles(_key);\n bytes memory currentNodeID = abi.encodePacked(_root);\n uint256 currentKeyIndex = 0;\n\n // Proof is top-down, so we start at the first element (root).\n for (uint256 i = 0; i < proof.length; i++) {\n TrieNode memory currentNode = proof[i];\n\n // Key index should never exceed total key length or we'll be out of bounds.\n require(\n currentKeyIndex <= key.length,\n \"MerkleTrie: key index exceeds total key length\"\n );\n\n if (currentKeyIndex == 0) {\n // First proof element is always the root node.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid root hash\"\n );\n } else if (currentNode.encoded.length >= 32) {\n // Nodes 32 bytes or larger are hashed inside branch nodes.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid large internal hash\"\n );\n } else {\n // Nodes smaller than 32 bytes aren't hashed.\n require(\n Bytes.equal(currentNode.encoded, currentNodeID),\n \"MerkleTrie: invalid internal node hash\"\n );\n }\n\n if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {\n if (currentKeyIndex == key.length) {\n // Value is the last element of the decoded list (for branch nodes). There's\n // some ambiguity in the Merkle trie specification because bytes(0) is a\n // valid value to place into the trie, but for branch nodes bytes(0) can exist\n // even when the value wasn't explicitly placed there. Geth treats a value of\n // bytes(0) as \"key does not exist\" and so we do the same.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[TREE_RADIX]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (branch)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (branch)\"\n );\n\n return value;\n } else {\n // We're not at the end of the key yet.\n // Figure out what the next node ID should be and continue.\n uint8 branchKey = uint8(key[currentKeyIndex]);\n RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];\n currentNodeID = _getNodeID(nextNode);\n currentKeyIndex += 1;\n }\n } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {\n bytes memory path = _getNodePath(currentNode);\n uint8 prefix = uint8(path[0]);\n uint8 offset = 2 - (prefix % 2);\n bytes memory pathRemainder = Bytes.slice(path, offset);\n bytes memory keyRemainder = Bytes.slice(key, currentKeyIndex);\n uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);\n\n // Whether this is a leaf node or an extension node, the path remainder MUST be a\n // prefix of the key remainder (or be equal to the key remainder) or the proof is\n // considered invalid.\n require(\n pathRemainder.length == sharedNibbleLength,\n \"MerkleTrie: path remainder must share all nibbles with key\"\n );\n\n if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {\n // Prefix of 2 or 3 means this is a leaf node. For the leaf node to be valid,\n // the key remainder must be exactly equal to the path remainder. We already\n // did the necessary byte comparison, so it's more efficient here to check that\n // the key remainder length equals the shared nibble length, which implies\n // equality with the path remainder (since we already did the same check with\n // the path remainder and the shared nibble length).\n require(\n keyRemainder.length == sharedNibbleLength,\n \"MerkleTrie: key remainder must be identical to path remainder\"\n );\n\n // Our Merkle Trie is designed specifically for the purposes of the Ethereum\n // state trie. Empty values are not allowed in the state trie, so we can safely\n // say that if the value is empty, the key should not exist and the proof is\n // invalid.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[1]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (leaf)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (leaf)\"\n );\n\n return value;\n } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {\n // Prefix of 0 or 1 means this is an extension node. We move onto the next node\n // in the proof and increment the key index by the length of the path remainder\n // which is equal to the shared nibble length.\n currentNodeID = _getNodeID(currentNode.decoded[1]);\n currentKeyIndex += sharedNibbleLength;\n } else {\n revert(\"MerkleTrie: received a node with an unknown prefix\");\n }\n } else {\n revert(\"MerkleTrie: received an unparseable node\");\n }\n }\n\n revert(\"MerkleTrie: ran out of proof elements\");\n }\n\n /**\n * @notice Parses an array of proof elements into a new array that contains both the original\n * encoded element and the RLP-decoded element.\n *\n * @param _proof Array of proof elements to parse.\n *\n * @return Proof parsed into easily accessible structs.\n */\n function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory) {\n uint256 length = _proof.length;\n TrieNode[] memory proof = new TrieNode[](length);\n for (uint256 i = 0; i < length; ) {\n proof[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) });\n unchecked {\n ++i;\n }\n }\n return proof;\n }\n\n /**\n * @notice Picks out the ID for a node. Node ID is referred to as the \"hash\" within the\n * specification, but nodes < 32 bytes are not actually hashed.\n *\n * @param _node Node to pull an ID for.\n *\n * @return ID for the node, depending on the size of its contents.\n */\n function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes memory) {\n return _node.length < 32 ? RLPReader.readRawBytes(_node) : RLPReader.readBytes(_node);\n }\n\n /**\n * @notice Gets the path for a leaf or extension node.\n *\n * @param _node Node to get a path for.\n *\n * @return Node path, converted to an array of nibbles.\n */\n function _getNodePath(TrieNode memory _node) private pure returns (bytes memory) {\n return Bytes.toNibbles(RLPReader.readBytes(_node.decoded[0]));\n }\n\n /**\n * @notice Utility; determines the number of nibbles shared between two nibble arrays.\n *\n * @param _a First nibble array.\n * @param _b Second nibble array.\n *\n * @return Number of shared nibbles.\n */\n function _getSharedNibbleLength(bytes memory _a, bytes memory _b)\n private\n pure\n returns (uint256)\n {\n uint256 shared;\n uint256 max = (_a.length < _b.length) ? _a.length : _b.length;\n for (; shared < max && _a[shared] == _b[shared]; ) {\n unchecked {\n ++shared;\n }\n }\n return shared;\n }\n}\n" - }, - "contracts/libraries/trie/SecureMerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* Library Imports */\nimport { MerkleTrie } from \"./MerkleTrie.sol\";\n\n/**\n * @title SecureMerkleTrie\n * @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input\n * keys. Ethereum's state trie hashes input keys before storing them.\n */\nlibrary SecureMerkleTrie {\n /**\n * @notice Verifies a proof that a given key/value pair is present in the Merkle trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.get(key, _proof, _root);\n }\n\n /**\n * @notice Computes the hashed version of the input key.\n *\n * @param _key Key to hash.\n *\n * @return Hashed version of the key.\n */\n function _getSecureKey(bytes memory _key) private pure returns (bytes memory) {\n return abi.encodePacked(keccak256(_key));\n }\n}\n" - }, - "contracts/periphery/TransferOnion.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ReentrancyGuard } from \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @title TransferOnion\n * @notice TransferOnion is a hash onion for distributing tokens. The shell commits\n * to an ordered list of the token transfers and can be permissionlessly\n * unwrapped in order. The SENDER must `approve` this contract as\n * `transferFrom` is used to move the token balances.\n */\ncontract TransferOnion is ReentrancyGuard {\n using SafeERC20 for ERC20;\n\n /**\n * @notice Struct representing a layer of the onion.\n */\n struct Layer {\n address recipient;\n uint256 amount;\n bytes32 shell;\n }\n\n /**\n * @notice Address of the token to distribute.\n */\n ERC20 public immutable TOKEN;\n\n /**\n * @notice Address of the account to distribute tokens from.\n */\n address public immutable SENDER;\n\n /**\n * @notice Current shell hash.\n */\n bytes32 public shell;\n\n /**\n * @param _token Address of the token to distribute.\n * @param _sender Address of the sender to distribute from.\n * @param _shell Initial shell of the onion.\n */\n constructor(\n ERC20 _token,\n address _sender,\n bytes32 _shell\n ) {\n TOKEN = _token;\n SENDER = _sender;\n shell = _shell;\n }\n\n /**\n * @notice Peels layers from the onion and distributes tokens.\n *\n * @param _layers Array of onion layers to peel.\n */\n function peel(Layer[] memory _layers) public nonReentrant {\n bytes32 tempShell = shell;\n uint256 length = _layers.length;\n for (uint256 i = 0; i < length; ) {\n Layer memory layer = _layers[i];\n\n // Confirm that the onion layer is correct.\n require(\n keccak256(abi.encode(layer.recipient, layer.amount, layer.shell)) == tempShell,\n \"TransferOnion: what are you doing in my swamp?\"\n );\n\n // Update the onion layer.\n tempShell = layer.shell;\n\n // Transfer the tokens.\n TOKEN.safeTransferFrom(SENDER, layer.recipient, layer.amount);\n\n // Unchecked increment to save some gas.\n unchecked {\n ++i;\n }\n }\n\n shell = tempShell;\n }\n}\n" - }, - "contracts/test/AddressAliasHelper.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract AddressAliasHelper_applyAndUndo_Test is Test {\n /**\n * @notice Tests that applying and then undoing an alias results in the original address.\n */\n function testFuzz_applyAndUndo_succeeds(address _address) external {\n address aliased = AddressAliasHelper.applyL1ToL2Alias(_address);\n address unaliased = AddressAliasHelper.undoL1ToL2Alias(aliased);\n assertEq(_address, unaliased);\n }\n}\n" - }, - "contracts/test/BenchmarkTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test } from \"forge-std/Test.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport \"./CommonTest.t.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\n// Free function for setting the prevBaseFee param in the OptimismPortal.\nfunction setPrevBaseFee(\n Vm _vm,\n address _op,\n uint128 _prevBaseFee\n) {\n _vm.store(address(_op), bytes32(uint256(1)), bytes32((block.number << 192) | _prevBaseFee));\n}\n\ncontract SetPrevBaseFee_Test is Portal_Initializer {\n function test_setPrevBaseFee_succeeds() external {\n setPrevBaseFee(vm, address(op), 100 gwei);\n (uint128 prevBaseFee, , uint64 prevBlockNum) = op.params();\n assertEq(uint256(prevBaseFee), 100 gwei);\n assertEq(uint256(prevBlockNum), block.number);\n }\n}\n\n// Tests for obtaining pure gas cost estimates for commonly used functions.\n// The objective with these benchmarks is to strip down the actual test functions\n// so that they are nothing more than the call we want measure the gas cost of.\n// In order to achieve this we make no assertions, and handle everything else in the setUp()\n// function.\ncontract GasBenchMark_OptimismPortal is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n bytes32 _outputRoot;\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n\n // Get withdrawal proof data we can use for testing.\n bytes32 _storageRoot;\n bytes32 _stateRoot;\n (_stateRoot, _storageRoot, _outputRoot, , _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public virtual override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n function test_depositTransaction_benchmark() external {\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_depositTransaction_benchmark_1() external {\n setPrevBaseFee(vm, address(op), 1 gwei);\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_proveWithdrawalTransaction_benchmark() external {\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n}\n\ncontract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer {\n function test_sendMessage_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n vm.resumeGasMetering();\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n\n function test_sendMessage_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n vm.resumeGasMetering();\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), alice, 100000, true);\n vm.startPrank(alice, alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n }\n\n function test_depositETH_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n vm.resumeGasMetering();\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositETH_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n vm.resumeGasMetering();\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositERC20_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n vm.resumeGasMetering();\n L1Bridge.bridgeERC20({\n _localToken: address(L1Token),\n _remoteToken: address(L2Token),\n _amount: 100,\n _minGasLimit: 100_000,\n _extraData: hex\"\"\n });\n }\n\n function test_depositERC20_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n vm.resumeGasMetering();\n L1Bridge.bridgeERC20({\n _localToken: address(L1Token),\n _remoteToken: address(L2Token),\n _amount: 100,\n _minGasLimit: 100_000,\n _extraData: hex\"\"\n });\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Finalize is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), address(L1Bridge), 100, true);\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.startPrank(address(L1Bridge.messenger()));\n vm.deal(address(L1Bridge.messenger()), 100);\n }\n\n function test_finalizeETHWithdrawal_benchmark() external {\n // TODO: Make this more accurate. It is underestimating the cost because it pranks\n // the call coming from the messenger, which bypasses the portal\n // and oracle.\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n\ncontract GasBenchMark_L2OutputOracle is L2OutputOracle_Initializer {\n uint256 nextBlockNumber;\n\n function setUp() public override {\n super.setUp();\n nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.startPrank(proposer);\n }\n\n function test_proposeL2Output_benchmark() external {\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n}\n" - }, - "contracts/test/Bytes.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Bytes } from \"../libraries/Bytes.sol\";\n\ncontract Bytes_slice_Test is Test {\n /**\n * @notice Tests that the `slice` function works as expected when starting from index 0.\n */\n function test_slice_fromZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check if all possible slices starting from index 0 are correct.\n assertEq(Bytes.slice(input, 0, 0), hex\"\");\n assertEq(Bytes.slice(input, 0, 1), hex\"11\");\n assertEq(Bytes.slice(input, 0, 2), hex\"1122\");\n assertEq(Bytes.slice(input, 0, 3), hex\"112233\");\n assertEq(Bytes.slice(input, 0, 4), hex\"11223344\");\n assertEq(Bytes.slice(input, 0, 5), hex\"1122334455\");\n assertEq(Bytes.slice(input, 0, 6), hex\"112233445566\");\n assertEq(Bytes.slice(input, 0, 7), hex\"11223344556677\");\n assertEq(Bytes.slice(input, 0, 8), hex\"1122334455667788\");\n assertEq(Bytes.slice(input, 0, 9), hex\"112233445566778899\");\n assertEq(Bytes.slice(input, 0, 10), hex\"11223344556677889900\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when starting from indices [1, 9]\n * with lengths [1, 9], in reverse order.\n */\n function test_slice_fromNonZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check correctness of slices starting from indexes [1, 9]\n // and spanning [1, 9] bytes, in reverse order\n assertEq(Bytes.slice(input, 9, 1), hex\"00\");\n assertEq(Bytes.slice(input, 8, 2), hex\"9900\");\n assertEq(Bytes.slice(input, 7, 3), hex\"889900\");\n assertEq(Bytes.slice(input, 6, 4), hex\"77889900\");\n assertEq(Bytes.slice(input, 5, 5), hex\"6677889900\");\n assertEq(Bytes.slice(input, 4, 6), hex\"556677889900\");\n assertEq(Bytes.slice(input, 3, 7), hex\"44556677889900\");\n assertEq(Bytes.slice(input, 2, 8), hex\"3344556677889900\");\n assertEq(Bytes.slice(input, 1, 9), hex\"223344556677889900\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when slicing between multiple words\n * in memory. In this case, we test that a 2 byte slice between the 32nd byte of the\n * first word and the 1st byte of the second word is correct.\n */\n function test_slice_acrossWords_works() public {\n bytes\n memory input = hex\"00000000000000000000000000000000000000000000000000000000000000112200000000000000000000000000000000000000000000000000000000000000\";\n\n assertEq(Bytes.slice(input, 31, 2), hex\"1122\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when slicing between multiple\n * words in memory. In this case, we test that a 34 byte slice between 3 separate words\n * returns the correct result.\n */\n function test_slice_acrossMultipleWords_works() public {\n bytes\n memory input = hex\"000000000000000000000000000000000000000000000000000000000000001122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1100000000000000000000000000000000000000000000000000000000000000\";\n bytes\n memory expected = hex\"1122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11\";\n\n assertEq(Bytes.slice(input, 31, 34), expected);\n }\n\n /**\n * @notice Tests that, when given an input bytes array of length `n`, the `slice` function will\n * always revert if `_start + _length > n`.\n */\n function testFuzz_slice_outOfBounds_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // We want a valid start index and a length that will not overflow.\n vm.assume(_start < _input.length && _length < type(uint256).max - 31);\n // But, we want an invalid slice length.\n vm.assume(_start + _length > _input.length);\n\n vm.expectRevert(\"slice_outOfBounds\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that, when given a length `n` that is greater than `type(uint256).max - 31`,\n * the `slice` function reverts.\n */\n function testFuzz_slice_lengthOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that the `_length` will overflow if a number >= 31 is added to it.\n vm.assume(_length > type(uint256).max - 31);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that, when given a start index `n` that is greater than\n * `type(uint256).max - n`, the `slice` function reverts.\n */\n function testFuzz_slice_rangeOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that `_length` is a realistic length of a slice. This is to make sure\n // we revert on the correct require statement.\n vm.assume(_length < _input.length);\n // Ensure that `_start` will overflow if `_length` is added to it.\n vm.assume(_start > type(uint256).max - _length);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that the `slice` function correctly updates the free memory pointer depending\n * on the length of the slice.\n */\n function testFuzz_slice_memorySafety_succeeds(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // The start should never be more than the length of the input bytes array - 1\n vm.assume(_start < _input.length);\n // The length should never be more than the length of the input bytes array - the starting\n // slice index.\n vm.assume(_length <= _input.length - _start);\n\n // Grab the free memory pointer before the slice operation\n uint64 initPtr;\n assembly {\n initPtr := mload(0x40)\n }\n uint64 expectedPtr = uint64(initPtr + 0x20 + ((_length + 0x1f) & ~uint256(0x1f)));\n\n // Ensure that all memory outside of the expected range is safe.\n vm.expectSafeMemory(initPtr, expectedPtr);\n\n // Slice the input bytes array from `_start` to `_start + _length`\n bytes memory slice = Bytes.slice(_input, _start, _length);\n\n // Grab the free memory pointer after the slice operation\n uint64 finalPtr;\n assembly {\n finalPtr := mload(0x40)\n }\n\n // The free memory pointer should have been updated properly\n if (_length == 0) {\n // If the slice length is zero, only 32 bytes of memory should have been allocated.\n assertEq(finalPtr, initPtr + 0x20);\n } else {\n // If the slice length is greater than zero, the memory allocated should be the\n // length of the slice rounded up to the next 32 byte word + 32 bytes for the\n // length of the byte array.\n //\n // Note that we use a slightly less efficient, but equivalent method of rounding\n // up `_length` to the next multiple of 32 than is used in the `slice` function.\n // This is to diff test the method used in `slice`.\n uint64 _expectedPtr = uint64(initPtr + 0x20 + (((_length + 0x1F) >> 5) << 5));\n assertEq(finalPtr, _expectedPtr);\n\n // Sanity check for equivalence of the rounding methods.\n assertEq(_expectedPtr, expectedPtr);\n }\n\n // The slice length should be equal to `_length`\n assertEq(slice.length, _length);\n }\n}\n\ncontract Bytes_toNibbles_Test is Test {\n /**\n * @notice Diffs the test Solidity version of `toNibbles` against the Yul version.\n *\n * @param _bytes The `bytes` array to convert to nibbles.\n *\n * @return Yul version of `toNibbles` applied to `_bytes`.\n */\n function _toNibblesYul(bytes memory _bytes) internal pure returns (bytes memory) {\n // Allocate memory for the `nibbles` array.\n bytes memory nibbles = new bytes(_bytes.length << 1);\n\n assembly {\n // Load the length of the passed bytes array from memory\n let bytesLength := mload(_bytes)\n\n // Store the memory offset of the _bytes array's contents on the stack\n let bytesStart := add(_bytes, 0x20)\n\n // Store the memory offset of the nibbles array's contents on the stack\n let nibblesStart := add(nibbles, 0x20)\n\n // Loop through each byte in the input array\n for {\n let i := 0x00\n } lt(i, bytesLength) {\n i := add(i, 0x01)\n } {\n // Get the starting offset of the next 2 bytes in the nibbles array\n let offset := add(nibblesStart, shl(0x01, i))\n\n // Load the byte at the current index within the `_bytes` array\n let b := byte(0x00, mload(add(bytesStart, i)))\n\n // Pull out the first nibble and store it in the new array\n mstore8(offset, shr(0x04, b))\n // Pull out the second nibble and store it in the new array\n mstore8(add(offset, 0x01), and(b, 0x0F))\n }\n }\n\n return nibbles;\n }\n\n /**\n * @notice Tests that, given an input of 5 bytes, the `toNibbles` function returns an array of\n * 10 nibbles corresponding to the input data.\n */\n function test_toNibbles_expectedResult5Bytes_works() public {\n bytes memory input = hex\"1234567890\";\n bytes memory expected = hex\"01020304050607080900\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Tests that, given an input of 128 bytes, the `toNibbles` function returns an array\n * of 256 nibbles corresponding to the input data. This test exists to ensure that,\n * given a large input, the `toNibbles` function works as expected.\n */\n function test_toNibbles_expectedResult128Bytes_works() public {\n bytes\n memory input = hex\"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f\";\n bytes\n memory expected = hex\"0000000100020003000400050006000700080009000a000b000c000d000e000f0100010101020103010401050106010701080109010a010b010c010d010e010f0200020102020203020402050206020702080209020a020b020c020d020e020f0300030103020303030403050306030703080309030a030b030c030d030e030f0400040104020403040404050406040704080409040a040b040c040d040e040f0500050105020503050405050506050705080509050a050b050c050d050e050f0600060106020603060406050606060706080609060a060b060c060d060e060f0700070107020703070407050706070707080709070a070b070c070d070e070f\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Tests that, given an input of 0 bytes, the `toNibbles` function returns a zero\n * length array.\n */\n function test_toNibbles_zeroLengthInput_works() public {\n bytes memory input = hex\"\";\n bytes memory expected = hex\"\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length, 0);\n assertEq(expected.length, 0);\n assertEq(actual.length, 0);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Test that the `toNibbles` function in the `Bytes` library is equivalent to the Yul\n * implementation.\n */\n function testDiff_toNibbles_succeeds(bytes memory _input) public {\n assertEq(Bytes.toNibbles(_input), _toNibblesYul(_input));\n }\n}\n\ncontract Bytes_equal_Test is Test {\n /**\n * @notice Manually checks equality of two dynamic `bytes` arrays in memory.\n *\n * @param _a The first `bytes` array to compare.\n * @param _b The second `bytes` array to compare.\n *\n * @return True if the two `bytes` arrays are equal in memory.\n */\n function manualEq(bytes memory _a, bytes memory _b) internal pure returns (bool) {\n bool _eq;\n assembly {\n _eq := and(\n // Check if the contents of the two bytes arrays are equal in memory.\n eq(keccak256(add(0x20, _a), mload(_a)), keccak256(add(0x20, _b), mload(_b))),\n // Check if the length of the two bytes arrays are equal in memory.\n // This is redundant given the above check, but included for completeness.\n eq(mload(_a), mload(_b))\n )\n }\n return _eq;\n }\n\n /**\n * @notice Tests that the `equal` function in the `Bytes` library returns `false` if given two\n * non-equal byte arrays.\n */\n function testFuzz_equal_notEqual_works(bytes memory _a, bytes memory _b) public {\n vm.assume(!manualEq(_a, _b));\n assertFalse(Bytes.equal(_a, _b));\n }\n\n /**\n * @notice Test whether or not the `equal` function in the `Bytes` library is equivalent to\n * manually checking equality of the two dynamic `bytes` arrays in memory.\n */\n function testDiff_equal_works(bytes memory _a, bytes memory _b) public {\n assertEq(Bytes.equal(_a, _b), manualEq(_a, _b));\n }\n}\n" - }, - "contracts/test/CommonTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test, StdUtils } from \"forge-std/Test.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { IL1ChugSplashDeployer } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { LegacyMintableERC20 } from \"../legacy/LegacyMintableERC20.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract CommonTest is Test {\n address alice = address(128);\n address bob = address(256);\n address multisig = address(512);\n\n address immutable ZERO_ADDRESS = address(0);\n address immutable NON_ZERO_ADDRESS = address(1);\n uint256 immutable NON_ZERO_VALUE = 100;\n uint256 immutable ZERO_VALUE = 0;\n uint64 immutable NON_ZERO_GASLIMIT = 50000;\n bytes32 nonZeroHash = keccak256(abi.encode(\"NON_ZERO\"));\n bytes NON_ZERO_DATA = hex\"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000\";\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n FFIInterface ffi;\n\n function setUp() public virtual {\n // Give alice and bob some ETH\n vm.deal(alice, 1 << 16);\n vm.deal(bob, 1 << 16);\n vm.deal(multisig, 1 << 16);\n\n vm.label(alice, \"alice\");\n vm.label(bob, \"bob\");\n vm.label(multisig, \"multisig\");\n\n // Make sure we have a non-zero base fee\n vm.fee(1000000000);\n\n ffi = new FFIInterface();\n }\n\n function emitTransactionDeposited(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) internal {\n emit TransactionDeposited(\n _from,\n _to,\n 0,\n abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data)\n );\n }\n}\n\ncontract L2OutputOracle_Initializer is CommonTest {\n // Test target\n L2OutputOracle oracle;\n L2OutputOracle oracleImpl;\n\n L2ToL1MessagePasser messagePasser =\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER));\n\n // Constructor arguments\n address internal proposer = 0x000000000000000000000000000000000000AbBa;\n address internal owner = 0x000000000000000000000000000000000000ACDC;\n uint256 internal submissionInterval = 1800;\n uint256 internal l2BlockTime = 2;\n uint256 internal startingBlockNumber = 200;\n uint256 internal startingTimestamp = 1000;\n address guardian;\n\n // Test data\n uint256 initL1Time;\n\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n // Advance the evm's time to meet the L2OutputOracle's requirements for proposeL2Output\n function warpToProposeTime(uint256 _nextBlockNumber) public {\n vm.warp(oracle.computeL2Timestamp(_nextBlockNumber) + 1);\n }\n\n function setUp() public virtual override {\n super.setUp();\n guardian = makeAddr(\"guardian\");\n\n // By default the first block has timestamp and number zero, which will cause underflows in the\n // tests, so we'll move forward to these block values.\n initL1Time = startingTimestamp + 1;\n vm.warp(initL1Time);\n vm.roll(startingBlockNumber);\n // Deploy the L2OutputOracle and transfer owernship to the proposer\n oracleImpl = new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: startingTimestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(oracleImpl),\n abi.encodeCall(L2OutputOracle.initialize, (startingBlockNumber, startingTimestamp))\n );\n oracle = L2OutputOracle(address(proxy));\n vm.label(address(oracle), \"L2OutputOracle\");\n\n // Set the L2ToL1MessagePasser at the correct address\n vm.etch(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(new L2ToL1MessagePasser()).code);\n\n vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, \"L2ToL1MessagePasser\");\n }\n}\n\ncontract Portal_Initializer is L2OutputOracle_Initializer {\n // Test target\n OptimismPortal internal opImpl;\n OptimismPortal internal op;\n SystemConfig systemConfig;\n\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n function setUp() public virtual override {\n super.setUp();\n\n ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();\n\n systemConfig = new SystemConfig({\n _owner: address(1),\n _overhead: 0,\n _scalar: 10000,\n _batcherHash: bytes32(0),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(0),\n _config: config\n });\n\n opImpl = new OptimismPortal({\n _l2Oracle: oracle,\n _guardian: guardian,\n _paused: true,\n _config: systemConfig\n });\n\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(opImpl),\n abi.encodeWithSelector(OptimismPortal.initialize.selector, false)\n );\n op = OptimismPortal(payable(address(proxy)));\n vm.label(address(op), \"OptimismPortal\");\n }\n}\n\ncontract Messenger_Initializer is Portal_Initializer {\n AddressManager internal addressManager;\n L1CrossDomainMessenger internal L1Messenger;\n L2CrossDomainMessenger internal L2Messenger =\n L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER);\n\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n\n event SentMessageExtension1(address indexed sender, uint256 value);\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event RelayedMessage(bytes32 indexed msgHash);\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 mint,\n uint256 value,\n uint64 gasLimit,\n bool isCreation,\n bytes data\n );\n\n event WhatHappened(bool success, bytes returndata);\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the address manager\n vm.prank(multisig);\n addressManager = new AddressManager();\n\n // Setup implementation\n L1CrossDomainMessenger L1MessengerImpl = new L1CrossDomainMessenger(op);\n\n // Setup the address manager and proxy\n vm.prank(multisig);\n addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(L1MessengerImpl));\n ResolvedDelegateProxy proxy = new ResolvedDelegateProxy(\n addressManager,\n \"OVM_L1CrossDomainMessenger\"\n );\n L1Messenger = L1CrossDomainMessenger(address(proxy));\n L1Messenger.initialize();\n\n vm.etch(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n address(new L2CrossDomainMessenger(address(L1Messenger))).code\n );\n\n L2Messenger.initialize();\n\n // Label addresses\n vm.label(address(addressManager), \"AddressManager\");\n vm.label(address(L1MessengerImpl), \"L1CrossDomainMessenger_Impl\");\n vm.label(address(L1Messenger), \"L1CrossDomainMessenger_Proxy\");\n vm.label(Predeploys.LEGACY_ERC20_ETH, \"LegacyERC20ETH\");\n vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, \"L2CrossDomainMessenger\");\n\n vm.label(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n \"L1CrossDomainMessenger_aliased\"\n );\n }\n}\n\ncontract Bridge_Initializer is Messenger_Initializer {\n L1StandardBridge L1Bridge;\n L2StandardBridge L2Bridge;\n OptimismMintableERC20Factory L2TokenFactory;\n OptimismMintableERC20Factory L1TokenFactory;\n ERC20 L1Token;\n ERC20 BadL1Token;\n OptimismMintableERC20 L2Token;\n LegacyMintableERC20 LegacyL2Token;\n ERC20 NativeL2Token;\n ERC20 BadL2Token;\n OptimismMintableERC20 RemoteL1Token;\n\n event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes data\n );\n\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFailed(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ETHBridgeInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n function setUp() public virtual override {\n super.setUp();\n\n vm.label(Predeploys.L2_STANDARD_BRIDGE, \"L2StandardBridge\");\n vm.label(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, \"OptimismMintableERC20Factory\");\n\n // Deploy the L1 bridge and initialize it with the address of the\n // L1CrossDomainMessenger\n L1ChugSplashProxy proxy = new L1ChugSplashProxy(multisig);\n vm.mockCall(\n multisig,\n abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector),\n abi.encode(true)\n );\n vm.startPrank(multisig);\n proxy.setCode(address(new L1StandardBridge(payable(address(L1Messenger)))).code);\n vm.clearMockedCalls();\n address L1Bridge_Impl = proxy.getImplementation();\n vm.stopPrank();\n\n L1Bridge = L1StandardBridge(payable(address(proxy)));\n\n vm.label(address(proxy), \"L1StandardBridge_Proxy\");\n vm.label(address(L1Bridge_Impl), \"L1StandardBridge_Impl\");\n\n // Deploy the L2StandardBridge, move it to the correct predeploy\n // address and then initialize it\n L2StandardBridge l2B = new L2StandardBridge(payable(proxy));\n vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(l2B).code);\n L2Bridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE));\n\n // Set up the L2 mintable token factory\n OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory(\n Predeploys.L2_STANDARD_BRIDGE\n );\n vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(factory).code);\n L2TokenFactory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY);\n\n vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code);\n\n L1Token = new ERC20(\"Native L1 Token\", \"L1T\");\n\n LegacyL2Token = new LegacyMintableERC20({\n _l2Bridge: address(L2Bridge),\n _l1Token: address(L1Token),\n _name: string.concat(\"LegacyL2-\", L1Token.name()),\n _symbol: string.concat(\"LegacyL2-\", L1Token.symbol())\n });\n vm.label(address(LegacyL2Token), \"LegacyMintableERC20\");\n\n // Deploy the L2 ERC20 now\n L2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(L1Token),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n BadL2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n NativeL2Token = new ERC20(\"Native L2 Token\", \"L2T\");\n L1TokenFactory = new OptimismMintableERC20Factory(address(L1Bridge));\n\n RemoteL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(NativeL2Token),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n\n BadL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n }\n}\n\ncontract ERC721Bridge_Initializer is Messenger_Initializer {\n L1ERC721Bridge L1Bridge;\n L2ERC721Bridge L2Bridge;\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the L1ERC721Bridge.\n L1Bridge = new L1ERC721Bridge(address(L1Messenger), Predeploys.L2_ERC721_BRIDGE);\n\n // Deploy the implementation for the L2ERC721Bridge and etch it into the predeploy address.\n vm.etch(\n Predeploys.L2_ERC721_BRIDGE,\n address(new L2ERC721Bridge(Predeploys.L2_CROSS_DOMAIN_MESSENGER, address(L1Bridge)))\n .code\n );\n\n // Set up a reference to the L2ERC721Bridge.\n L2Bridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE);\n\n // Label the L1 and L2 bridges.\n vm.label(address(L1Bridge), \"L1ERC721Bridge\");\n vm.label(address(L2Bridge), \"L2ERC721Bridge\");\n }\n}\n\ncontract FFIInterface is Test {\n function getProveWithdrawalTransactionInputs(Types.WithdrawalTransaction memory _tx)\n external\n returns (\n bytes32,\n bytes32,\n bytes32,\n bytes32,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"getProveWithdrawalTransactionInputs\";\n cmds[2] = vm.toString(_tx.nonce);\n cmds[3] = vm.toString(_tx.sender);\n cmds[4] = vm.toString(_tx.target);\n cmds[5] = vm.toString(_tx.value);\n cmds[6] = vm.toString(_tx.gasLimit);\n cmds[7] = vm.toString(_tx.data);\n\n bytes memory result = vm.ffi(cmds);\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = abi.decode(result, (bytes32, bytes32, bytes32, bytes32, bytes[]));\n\n return (stateRoot, storageRoot, outputRoot, withdrawalHash, withdrawalProof);\n }\n\n function hashCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashCrossDomainMessage\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashWithdrawal(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashWithdrawal\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashOutputRootProof(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external returns (bytes32) {\n string[] memory cmds = new string[](6);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashOutputRootProof\";\n cmds[2] = Strings.toHexString(uint256(_version));\n cmds[3] = Strings.toHexString(uint256(_stateRoot));\n cmds[4] = Strings.toHexString(uint256(_messagePasserStorageRoot));\n cmds[5] = Strings.toHexString(uint256(_latestBlockhash));\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashDepositTransaction(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint64 _logIndex\n ) external returns (bytes32) {\n string[] memory cmds = new string[](10);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashDepositTransaction\";\n cmds[2] = \"0x0000000000000000000000000000000000000000000000000000000000000000\";\n cmds[3] = vm.toString(_logIndex);\n cmds[4] = vm.toString(_from);\n cmds[5] = vm.toString(_to);\n cmds[6] = vm.toString(_mint);\n cmds[7] = vm.toString(_value);\n cmds[8] = vm.toString(_gas);\n cmds[9] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function encodeDepositTransaction(Types.UserDepositTransaction calldata txn)\n external\n returns (bytes memory)\n {\n string[] memory cmds = new string[](11);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"encodeDepositTransaction\";\n cmds[2] = vm.toString(txn.from);\n cmds[3] = vm.toString(txn.to);\n cmds[4] = vm.toString(txn.value);\n cmds[5] = vm.toString(txn.mint);\n cmds[6] = vm.toString(txn.gasLimit);\n cmds[7] = vm.toString(txn.isCreation);\n cmds[8] = vm.toString(txn.data);\n cmds[9] = vm.toString(txn.l1BlockHash);\n cmds[10] = vm.toString(txn.logIndex);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function encodeCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes memory) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"encodeCrossDomainMessage\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function decodeVersionedNonce(uint256 nonce) external returns (uint256, uint256) {\n string[] memory cmds = new string[](3);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"decodeVersionedNonce\";\n cmds[2] = vm.toString(nonce);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (uint256, uint256));\n }\n\n function getMerkleTrieFuzzCase(string memory variant)\n external\n returns (\n bytes32,\n bytes memory,\n bytes memory,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](5);\n cmds[0] = \"./test-case-generator/fuzz\";\n cmds[1] = \"-m\";\n cmds[2] = \"trie\";\n cmds[3] = \"-v\";\n cmds[4] = variant;\n\n return abi.decode(vm.ffi(cmds), (bytes32, bytes, bytes, bytes[]));\n }\n}\n\n// Used for testing a future upgrade beyond the current implementations.\n// We include some variables so that we can sanity check accessing storage values after an upgrade.\ncontract NextImpl is Initializable {\n // Initializable occupies the zero-th slot.\n bytes32 slot1;\n bytes32[19] __gap;\n bytes32 slot21;\n bytes32 public constant slot21Init = bytes32(hex\"1337\");\n\n function initialize() public reinitializer(2) {\n // Slot21 is unused by an of our upgradeable contracts.\n // This is used to verify that we can access this value after an upgrade.\n slot21 = slot21Init;\n }\n}\n\ncontract Reverter {\n fallback() external {\n revert();\n }\n}\n\n// Useful for testing reentrancy guards\ncontract CallerCaller {\n event WhatHappened(bool success, bytes returndata);\n\n fallback() external {\n (bool success, bytes memory returndata) = msg.sender.call(msg.data);\n emit WhatHappened(success, returndata);\n assembly {\n switch success\n case 0 {\n revert(add(returndata, 0x20), mload(returndata))\n }\n default {\n return(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n\n// Used for testing the `CrossDomainMessenger`'s per-message reentrancy guard.\ncontract ConfigurableCaller {\n bool doRevert = true;\n address target;\n bytes payload;\n\n event WhatHappened(bool success, bytes returndata);\n\n /**\n * @notice Call the configured target with the configured payload OR revert.\n */\n function call() external {\n if (doRevert) {\n revert(\"ConfigurableCaller: revert\");\n } else {\n (bool success, bytes memory returndata) = address(target).call(payload);\n emit WhatHappened(success, returndata);\n assembly {\n switch success\n case 0 {\n revert(add(returndata, 0x20), mload(returndata))\n }\n default {\n return(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n }\n\n /**\n * @notice Set whether or not to have `call` revert.\n */\n function setDoRevert(bool _doRevert) external {\n doRevert = _doRevert;\n }\n\n /**\n * @notice Set the target for the call made in `call`.\n */\n function setTarget(address _target) external {\n target = _target;\n }\n\n /**\n * @notice Set the payload for the call made in `call`.\n */\n function setPayload(bytes calldata _payload) external {\n payload = _payload;\n }\n\n /**\n * @notice Fallback function that reverts if `doRevert` is true.\n * Otherwise, it does nothing.\n */\n fallback() external {\n if (doRevert) {\n revert(\"ConfigurableCaller: revert\");\n }\n }\n}\n" - }, - "contracts/test/CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, CallerCaller, CommonTest } from \"./CommonTest.t.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\n\n// Libraries\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n// CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2\n// CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract.\ncontract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {\n // Ensure that baseGas passes for the max value of _minGasLimit,\n // this is about 4 Billion.\n function test_baseGas_succeeds() external view {\n L1Messenger.baseGas(hex\"ff\", type(uint32).max);\n }\n\n // Fuzz for other values which might cause a revert in baseGas.\n function testFuzz_baseGas_succeeds(uint32 _minGasLimit) external view {\n L1Messenger.baseGas(hex\"ff\", _minGasLimit);\n }\n\n /**\n * @notice The baseGas function should always return a value greater than\n * or equal to the minimum gas limit value on the OptimismPortal.\n * This guarantees that the messengers will always pass sufficient\n * gas to the OptimismPortal.\n */\n function testFuzz_baseGas_portalMinGasLimit_succeeds(bytes memory _data, uint32 _minGasLimit)\n external\n {\n vm.assume(_data.length <= type(uint64).max);\n uint64 baseGas = L1Messenger.baseGas(_data, _minGasLimit);\n uint64 minGasLimit = op.minimumGasLimit(uint64(_data.length));\n assertTrue(baseGas >= minGasLimit);\n }\n}\n\n/**\n * @title ExternalRelay\n * @notice A mock external contract called via the SafeCall inside\n * the CrossDomainMessenger's `relayMessage` function.\n */\ncontract ExternalRelay is CommonTest {\n address internal op;\n address internal fuzzedSender;\n L1CrossDomainMessenger internal L1Messenger;\n\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n constructor(L1CrossDomainMessenger _l1Messenger, address _op) {\n L1Messenger = _l1Messenger;\n op = _op;\n }\n\n /**\n * @notice Internal helper function to relay a message and perform assertions.\n */\n function _internalRelay(address _innerSender) internal {\n address initialSender = L1Messenger.xDomainMessageSender();\n\n bytes memory callMessage = getCallData();\n\n bytes32 hash = Hashing.hashCrossDomainMessage({\n _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n _sender: _innerSender,\n _target: address(this),\n _value: 0,\n _gasLimit: 0,\n _data: callMessage\n });\n\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n vm.prank(address(op));\n L1Messenger.relayMessage({\n _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n _sender: _innerSender,\n _target: address(this),\n _value: 0,\n _minGasLimit: 0,\n _message: callMessage\n });\n\n assertTrue(L1Messenger.failedMessages(hash));\n assertFalse(L1Messenger.successfulMessages(hash));\n assertEq(initialSender, L1Messenger.xDomainMessageSender());\n }\n\n /**\n * @notice externalCallWithMinGas is called by the CrossDomainMessenger.\n */\n function externalCallWithMinGas() external payable {\n for (uint256 i = 0; i < 10; i++) {\n address _innerSender;\n unchecked {\n _innerSender = address(uint160(uint256(uint160(fuzzedSender)) + i));\n }\n _internalRelay(_innerSender);\n }\n }\n\n /**\n * @notice Helper function to get the callData for an `externalCallWithMinGas\n */\n function getCallData() public pure returns (bytes memory) {\n return abi.encodeWithSelector(ExternalRelay.externalCallWithMinGas.selector);\n }\n\n /**\n * @notice Helper function to set the fuzzed sender\n */\n function setFuzzedSender(address _fuzzedSender) public {\n fuzzedSender = _fuzzedSender;\n }\n}\n\n/**\n * @title CrossDomainMessenger_RelayMessage_Test\n * @notice Fuzz tests re-entrancy into the CrossDomainMessenger relayMessage function.\n */\ncontract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n ExternalRelay public er;\n\n function setUp() public override {\n super.setUp();\n er = new ExternalRelay(L1Messenger, address(op));\n }\n\n /**\n * @dev This test mocks an OptimismPortal call to the L1CrossDomainMessenger via\n * the relayMessage function. The relayMessage function will then use SafeCall's\n * callWithMinGas to call the target with call data packed in the callMessage.\n * For this test, the callWithMinGas will call the mock ExternalRelay test contract\n * defined above, executing the externalCallWithMinGas function which will try to\n * re-enter the CrossDomainMessenger's relayMessage function, resulting in that message\n * being recorded as failed.\n */\n function testFuzz_relayMessageReenter_succeeds(address _sender, uint256 _gasLimit) external {\n vm.assume(_sender != Predeploys.L2_CROSS_DOMAIN_MESSENGER);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n er.setFuzzedSender(_sender);\n address target = address(er);\n bytes memory callMessage = er.getCallData();\n\n vm.expectCall(target, callMessage);\n\n uint64 gasLimit = uint64(bound(_gasLimit, 0, 30_000_000));\n\n bytes32 hash = Hashing.hashCrossDomainMessage({\n _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n _sender: sender,\n _target: target,\n _value: 0,\n _gasLimit: gasLimit,\n _data: callMessage\n });\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n L1Messenger.relayMessage({\n _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n _sender: sender,\n _target: target,\n _value: 0,\n _minGasLimit: gasLimit,\n _message: callMessage\n });\n\n assertTrue(L1Messenger.successfulMessages(hash));\n assertEq(L1Messenger.failedMessages(hash), false);\n\n // Ensures that the `xDomainMsgSender` is set back to `Predeploys.L2_CROSS_DOMAIN_MESSENGER`\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest, Portal_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable } from \"../L2/CrossDomainOwnable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Vm, VmSafe } from \"forge-std/Vm.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract XDomainSetter is CrossDomainOwnable {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable_Test is CommonTest {\n XDomainSetter setter;\n\n function setUp() public override {\n super.setUp();\n setter = new XDomainSetter();\n }\n\n // Check that the revert message is correct\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable: caller is not the owner\");\n setter.set(1);\n }\n\n // Check that making a call can set the value properly\n function test_onlyOwner_succeeds() external {\n assertEq(setter.value(), 0);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(setter.owner()));\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n\ncontract CrossDomainOwnableThroughPortal_Test is Portal_Initializer {\n XDomainSetter setter;\n\n function setUp() public override {\n super.setUp();\n\n vm.prank(alice);\n setter = new XDomainSetter();\n }\n\n function test_depositTransaction_crossDomainOwner_succeeds() external {\n vm.recordLogs();\n\n vm.prank(alice);\n op.depositTransaction({\n _to: address(setter),\n _value: 0,\n _gasLimit: 30_000,\n _isCreation: false,\n _data: abi.encodeWithSelector(XDomainSetter.set.selector, 1)\n });\n\n // Simulate the operation of the `op-node` by parsing data\n // from logs\n VmSafe.Log[] memory logs = vm.getRecordedLogs();\n // Only 1 log emitted\n assertEq(logs.length, 1);\n\n VmSafe.Log memory log = logs[0];\n\n // It is the expected topic\n bytes32 topic = log.topics[0];\n assertEq(topic, keccak256(\"TransactionDeposited(address,address,uint256,bytes)\"));\n\n // from is indexed and the first argument to the event.\n bytes32 _from = log.topics[1];\n address from = Bytes32AddressLib.fromLast20Bytes(_from);\n\n assertEq(AddressAliasHelper.undoL1ToL2Alias(from), alice);\n\n // Make a call from the \"from\" value received from the log.\n // In theory the opaque data could be parsed from the log\n // and passed to a low level call to \"to\", but calling set\n // directly on the setter is good enough.\n vm.prank(from);\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable2.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\nimport { CommonTest, Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable2 } from \"../L2/CrossDomainOwnable2.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract XDomainSetter2 is CrossDomainOwnable2 {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable2_Test is Messenger_Initializer {\n XDomainSetter2 setter;\n\n function setUp() public override {\n super.setUp();\n vm.prank(alice);\n setter = new XDomainSetter2();\n }\n\n function test_onlyOwner_notMessenger_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the messenger\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n // set the xDomainMsgSender storage slot\n bytes32 key = bytes32(uint256(204));\n bytes32 value = Bytes32AddressLib.fillLast12Bytes(address(alice));\n vm.store(address(L2Messenger), key, value);\n\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the owner\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner2_reverts() external {\n uint240 nonce = 0;\n address sender = bob;\n address target = address(setter);\n uint256 value = 0;\n uint256 minGasLimit = 0;\n bytes memory message = abi.encodeWithSelector(XDomainSetter2.set.selector, 1);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n // It should be a failed message. The revert is caught,\n // so we cannot expectRevert here.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n assertEq(setter.value(), 0);\n }\n\n function test_onlyOwner_succeeds() external {\n address owner = setter.owner();\n\n // Simulate the L2 execution where the call is coming from\n // the L1CrossDomainMessenger\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(1, 1),\n owner,\n address(setter),\n 0,\n 0,\n abi.encodeWithSelector(XDomainSetter2.set.selector, 2)\n );\n\n assertEq(setter.value(), 2);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable3.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\nimport { CommonTest, Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable3 } from \"../L2/CrossDomainOwnable3.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract XDomainSetter3 is CrossDomainOwnable3 {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable3_Test is Messenger_Initializer {\n XDomainSetter3 setter;\n\n /**\n * @notice OpenZeppelin Ownable.sol transferOwnership event\n */\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @notice CrossDomainOwnable3.sol transferOwnership event\n */\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner,\n bool isLocal\n );\n\n function setUp() public override {\n super.setUp();\n vm.prank(alice);\n setter = new XDomainSetter3();\n }\n\n function test_constructor_succeeds() public {\n assertEq(setter.owner(), alice);\n assertEq(setter.isLocal(), true);\n }\n\n function test_localOnlyOwner_notOwner_reverts() public {\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.set(1);\n }\n\n function test_transferOwnership_notOwner_reverts() public {\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.transferOwnership({ _owner: bob, _isLocal: true });\n }\n\n function test_crossDomainOnlyOwner_notOwner_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n // set the xDomainMsgSender storage slot\n bytes32 key = bytes32(uint256(204));\n bytes32 value = Bytes32AddressLib.fillLast12Bytes(bob);\n vm.store(address(L2Messenger), key, value);\n\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.set(1);\n }\n\n function test_crossDomainOnlyOwner_notOwner2_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n assertEq(setter.isLocal(), false);\n\n uint240 nonce = 0;\n address sender = bob;\n address target = address(setter);\n uint256 value = 0;\n uint256 minGasLimit = 0;\n bytes memory message = abi.encodeWithSelector(XDomainSetter3.set.selector, 1);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n // It should be a failed message. The revert is caught,\n // so we cannot expectRevert here.\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit FailedRelayedMessage(hash);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n assertEq(setter.value(), 0);\n }\n\n function test_crossDomainOnlyOwner_notMessenger_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the messenger\");\n setter.set(1);\n }\n\n function test_transferOwnership_zeroAddress_reverts() public {\n vm.prank(setter.owner());\n vm.expectRevert(\"CrossDomainOwnable3: new owner is the zero address\");\n setter.transferOwnership({ _owner: address(0), _isLocal: true });\n }\n\n function test_transferOwnership_noLocalZeroAddress_reverts() public {\n vm.prank(setter.owner());\n vm.expectRevert(\"Ownable: new owner is the zero address\");\n setter.transferOwnership(address(0));\n }\n\n function test_localOnlyOwner_succeeds() public {\n assertEq(setter.isLocal(), true);\n vm.prank(setter.owner());\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n\n function test_localTransferOwnership_succeeds() public {\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n emit OwnershipTransferred(alice, bob, true);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: bob, _isLocal: true });\n\n assertEq(setter.isLocal(), true);\n\n vm.prank(bob);\n setter.set(2);\n assertEq(setter.value(), 2);\n }\n\n /**\n * @notice The existing transferOwnership(address) method\n * still exists on the contract\n */\n function test_transferOwnershipNoLocal_succeeds() public {\n bool isLocal = setter.isLocal();\n\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n\n vm.prank(setter.owner());\n setter.transferOwnership(bob);\n\n // isLocal has not changed\n assertEq(setter.isLocal(), isLocal);\n\n vm.prank(bob);\n setter.set(2);\n assertEq(setter.value(), 2);\n }\n\n function test_crossDomainTransferOwnership_succeeds() public {\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n emit OwnershipTransferred(alice, bob, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: bob, _isLocal: false });\n\n assertEq(setter.isLocal(), false);\n\n // Simulate the L2 execution where the call is coming from\n // the L1CrossDomainMessenger\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(1, 1),\n bob,\n address(setter),\n 0,\n 0,\n abi.encodeWithSelector(XDomainSetter3.set.selector, 2)\n );\n\n assertEq(setter.value(), 2);\n }\n}\n" - }, - "contracts/test/DeployerWhitelist.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { DeployerWhitelist } from \"../legacy/DeployerWhitelist.sol\";\n\ncontract DeployerWhitelist_Test is CommonTest {\n DeployerWhitelist list;\n\n function setUp() public virtual override {\n list = new DeployerWhitelist();\n }\n\n // The owner should be address(0)\n function test_owner_succeeds() external {\n assertEq(list.owner(), address(0));\n }\n\n // The storage slot for the owner must be the same\n function test_storageSlots_succeeds() external {\n vm.prank(list.owner());\n list.setOwner(address(1));\n\n assertEq(bytes32(uint256(1)), vm.load(address(list), bytes32(uint256(0))));\n }\n}\n" - }, - "contracts/test/Encoding.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { LegacyCrossDomainUtils } from \"../libraries/LegacyCrossDomainUtils.sol\";\n\ncontract Encoding_Test is CommonTest {\n function testFuzz_nonceVersioning_succeeds(uint240 _nonce, uint16 _version) external {\n (uint240 nonce, uint16 version) = Encoding.decodeVersionedNonce(\n Encoding.encodeVersionedNonce(_nonce, _version)\n );\n assertEq(version, _version);\n assertEq(nonce, _nonce);\n }\n\n function testDiff_decodeVersionedNonce_succeeds(uint240 _nonce, uint16 _version) external {\n uint256 nonce = uint256(Encoding.encodeVersionedNonce(_nonce, _version));\n (uint256 decodedNonce, uint256 decodedVersion) = ffi.decodeVersionedNonce(nonce);\n\n assertEq(_version, uint16(decodedVersion));\n\n assertEq(_nonce, uint240(decodedNonce));\n }\n\n function testDiff_encodeCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint8 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint8 version = _version % 2;\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes memory encoding = Encoding.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n bytes memory _encoding = ffi.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n assertEq(encoding, _encoding);\n }\n\n function testFuzz_encodeCrossDomainMessageV0_matchesLegacy_succeeds(\n uint240 _nonce,\n address _sender,\n address _target,\n bytes memory _data\n ) external {\n uint8 version = 0;\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes memory legacyEncoding = LegacyCrossDomainUtils.encodeXDomainCalldata(\n _target,\n _sender,\n _data,\n nonce\n );\n\n bytes memory bedrockEncoding = Encoding.encodeCrossDomainMessageV0(\n _target,\n _sender,\n _data,\n nonce\n );\n\n assertEq(legacyEncoding, bedrockEncoding);\n }\n\n function testDiff_encodeDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bool isCreate,\n bytes memory _data,\n uint64 _logIndex\n ) external {\n Types.UserDepositTransaction memory t = Types.UserDepositTransaction(\n _from,\n _to,\n isCreate,\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n );\n\n bytes memory txn = Encoding.encodeDepositTransaction(t);\n bytes memory _txn = ffi.encodeDepositTransaction(t);\n\n assertEq(txn, _txn);\n }\n}\n" - }, - "contracts/test/FeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { L1FeeVault } from \"../L2/L1FeeVault.sol\";\nimport { BaseFeeVault } from \"../L2/BaseFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n// Test the implementations of the FeeVault\ncontract FeeVault_Test is Bridge_Initializer {\n BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT));\n L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT));\n\n address constant recipient = address(0x10000);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.BASE_FEE_VAULT, address(new BaseFeeVault(recipient)).code);\n vm.etch(Predeploys.L1_FEE_VAULT, address(new L1FeeVault(recipient)).code);\n\n vm.label(Predeploys.BASE_FEE_VAULT, \"BaseFeeVault\");\n vm.label(Predeploys.L1_FEE_VAULT, \"L1FeeVault\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(baseFeeVault.RECIPIENT(), recipient);\n assertEq(l1FeeVault.RECIPIENT(), recipient);\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n}\n" - }, - "contracts/test/GasPriceOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GasPriceOracle } from \"../L2/GasPriceOracle.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract GasPriceOracle_Test is CommonTest {\n event OverheadUpdated(uint256);\n event ScalarUpdated(uint256);\n event DecimalsUpdated(uint256);\n\n GasPriceOracle gasOracle;\n L1Block l1Block;\n address depositor;\n\n // set the initial L1 context values\n uint64 constant number = 10;\n uint64 constant timestamp = 11;\n uint256 constant basefee = 100;\n bytes32 constant hash = bytes32(uint256(64));\n uint64 constant sequenceNumber = 0;\n bytes32 constant batcherHash = bytes32(uint256(777));\n uint256 constant l1FeeOverhead = 310;\n uint256 constant l1FeeScalar = 10;\n\n function setUp() public virtual override {\n super.setUp();\n // place the L1Block contract at the predeploy address\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n\n l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n depositor = l1Block.DEPOSITOR_ACCOUNT();\n\n // We are not setting the gas oracle at its predeploy\n // address for simplicity purposes. Nothing in this test\n // requires it to be at a particular address\n gasOracle = new GasPriceOracle();\n\n vm.prank(depositor);\n l1Block.setL1BlockValues({\n _number: number,\n _timestamp: timestamp,\n _basefee: basefee,\n _hash: hash,\n _sequenceNumber: sequenceNumber,\n _batcherHash: batcherHash,\n _l1FeeOverhead: l1FeeOverhead,\n _l1FeeScalar: l1FeeScalar\n });\n }\n\n function test_l1BaseFee_succeeds() external {\n assertEq(gasOracle.l1BaseFee(), basefee);\n }\n\n function test_gasPrice_succeeds() external {\n vm.fee(100);\n uint256 gasPrice = gasOracle.gasPrice();\n assertEq(gasPrice, 100);\n }\n\n function test_baseFee_succeeds() external {\n vm.fee(64);\n uint256 gasPrice = gasOracle.baseFee();\n assertEq(gasPrice, 64);\n }\n\n function test_scalar_succeeds() external {\n assertEq(gasOracle.scalar(), l1FeeScalar);\n }\n\n function test_overhead_succeeds() external {\n assertEq(gasOracle.overhead(), l1FeeOverhead);\n }\n\n function test_decimals_succeeds() external {\n assertEq(gasOracle.decimals(), 6);\n assertEq(gasOracle.DECIMALS(), 6);\n }\n\n // Removed in bedrock\n function test_setGasPrice_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setGasPrice(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n\n // Removed in bedrock\n function test_setL1BaseFee_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setL1BaseFee(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n}\n" - }, - "contracts/test/GovernanceToken.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract GovernanceToken_Test is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n\n function setUp() public virtual override {\n super.setUp();\n vm.prank(owner);\n gov = new GovernanceToken();\n }\n\n function test_constructor_succeeds() external {\n assertEq(gov.owner(), owner);\n assertEq(gov.name(), \"Optimism\");\n assertEq(gov.symbol(), \"OP\");\n assertEq(gov.decimals(), 18);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_mint_fromOwner_succeeds() external {\n // Mint 100 tokens.\n vm.prank(owner);\n gov.mint(owner, 100);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 100);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_mint_fromNotOwner_reverts() external {\n // Mint 100 tokens as rando.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n gov.mint(owner, 100);\n\n // Balance does not update.\n assertEq(gov.balanceOf(owner), 0);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_burn_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando burns their tokens.\n vm.prank(rando);\n gov.burn(50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_burnFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to burn 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner burns 50 tokens from rando.\n vm.prank(owner);\n gov.burnFrom(rando, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_transfer_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando transfers 50 tokens to owner.\n vm.prank(rando);\n gov.transfer(owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_approve_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n\n function test_transferFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner transfers 50 tokens from rando to owner.\n vm.prank(owner);\n gov.transferFrom(rando, owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_increaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Rando increases allowance by 50 tokens.\n vm.prank(rando);\n gov.increaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 100);\n }\n\n function test_decreaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 100 tokens.\n vm.prank(rando);\n gov.approve(owner, 100);\n\n // Rando decreases allowance by 50 tokens.\n vm.prank(rando);\n gov.decreaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n}\n" - }, - "contracts/test/Hashing.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { LegacyCrossDomainUtils } from \"../libraries/LegacyCrossDomainUtils.sol\";\n\ncontract Hashing_hashDepositSource_Test is CommonTest {\n /**\n * @notice Tests that hashDepositSource returns the correct hash in a simple case.\n */\n function test_hashDepositSource_succeeds() external {\n assertEq(\n Hashing.hashDepositSource(\n 0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959,\n 0x1\n ),\n 0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc\n );\n }\n}\n\ncontract Hashing_hashCrossDomainMessage_Test is CommonTest {\n /**\n * @notice Tests that hashCrossDomainMessage returns the correct hash in a simple case.\n */\n function testDiff_hashCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint16 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n // Ensure the version is valid.\n uint16 version = uint16(bound(uint256(_version), 0, 1));\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n assertEq(\n Hashing.hashCrossDomainMessage(nonce, _sender, _target, _value, _gasLimit, _data),\n ffi.hashCrossDomainMessage(nonce, _sender, _target, _value, _gasLimit, _data)\n );\n }\n\n /**\n * @notice Tests that hashCrossDomainMessageV0 matches the hash of the legacy encoding.\n */\n function testFuzz_hashCrossDomainMessageV0_matchesLegacy_succeeds(\n address _target,\n address _sender,\n bytes memory _message,\n uint256 _messageNonce\n ) external {\n assertEq(\n keccak256(\n LegacyCrossDomainUtils.encodeXDomainCalldata(\n _target,\n _sender,\n _message,\n _messageNonce\n )\n ),\n Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _messageNonce)\n );\n }\n}\n\ncontract Hashing_hashWithdrawal_Test is CommonTest {\n /**\n * @notice Tests that hashWithdrawal returns the correct hash in a simple case.\n */\n function testDiff_hashWithdrawal_succeeds(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n assertEq(\n Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(_nonce, _sender, _target, _value, _gasLimit, _data)\n ),\n ffi.hashWithdrawal(_nonce, _sender, _target, _value, _gasLimit, _data)\n );\n }\n}\n\ncontract Hashing_hashOutputRootProof_Test is CommonTest {\n /**\n * @notice Tests that hashOutputRootProof returns the correct hash in a simple case.\n */\n function testDiff_hashOutputRootProof_succeeds(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external {\n assertEq(\n Hashing.hashOutputRootProof(\n Types.OutputRootProof({\n version: _version,\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _messagePasserStorageRoot,\n latestBlockhash: _latestBlockhash\n })\n ),\n ffi.hashOutputRootProof(\n _version,\n _stateRoot,\n _messagePasserStorageRoot,\n _latestBlockhash\n )\n );\n }\n}\n\ncontract Hashing_hashDepositTransaction_Test is CommonTest {\n /**\n * @notice Tests that hashDepositTransaction returns the correct hash in a simple case.\n */\n function testDiff_hashDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint64 _logIndex\n ) external {\n assertEq(\n Hashing.hashDepositTransaction(\n Types.UserDepositTransaction(\n _from,\n _to,\n false, // isCreate\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n )\n ),\n ffi.hashDepositTransaction(_from, _to, _mint, _value, _gas, _data, _logIndex)\n );\n }\n}\n" - }, - "contracts/test/L1Block.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\ncontract L1BlockTest is CommonTest {\n L1Block lb;\n address depositor;\n bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1));\n\n function setUp() public virtual override {\n super.setUp();\n lb = new L1Block();\n depositor = lb.DEPOSITOR_ACCOUNT();\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: uint64(1),\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: NON_ZERO_HASH,\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(0),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function testFuzz_updatesValues_succeeds(\n uint64 n,\n uint64 t,\n uint256 b,\n bytes32 h,\n uint64 s,\n bytes32 bt,\n uint256 fo,\n uint256 fs\n ) external {\n vm.prank(depositor);\n lb.setL1BlockValues(n, t, b, h, s, bt, fo, fs);\n assertEq(lb.number(), n);\n assertEq(lb.timestamp(), t);\n assertEq(lb.basefee(), b);\n assertEq(lb.hash(), h);\n assertEq(lb.sequenceNumber(), s);\n assertEq(lb.batcherHash(), bt);\n assertEq(lb.l1FeeOverhead(), fo);\n assertEq(lb.l1FeeScalar(), fs);\n }\n\n function test_number_succeeds() external {\n assertEq(lb.number(), uint64(1));\n }\n\n function test_timestamp_succeeds() external {\n assertEq(lb.timestamp(), uint64(2));\n }\n\n function test_basefee_succeeds() external {\n assertEq(lb.basefee(), 3);\n }\n\n function test_hash_succeeds() external {\n assertEq(lb.hash(), NON_ZERO_HASH);\n }\n\n function test_sequenceNumber_succeeds() external {\n assertEq(lb.sequenceNumber(), uint64(4));\n }\n\n function test_updateValues_succeeds() external {\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: type(uint64).max,\n _timestamp: type(uint64).max,\n _basefee: type(uint256).max,\n _hash: keccak256(abi.encode(1)),\n _sequenceNumber: type(uint64).max,\n _batcherHash: bytes32(type(uint256).max),\n _l1FeeOverhead: type(uint256).max,\n _l1FeeScalar: type(uint256).max\n });\n }\n}\n" - }, - "contracts/test/L1BlockNumber.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { L1BlockNumber } from \"../legacy/L1BlockNumber.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract L1BlockNumberTest is Test {\n L1Block lb;\n L1BlockNumber bn;\n\n uint64 constant number = 99;\n\n function setUp() external {\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n lb = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n bn = new L1BlockNumber();\n vm.prank(lb.DEPOSITOR_ACCOUNT());\n\n lb.setL1BlockValues({\n _number: number,\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: bytes32(uint256(10)),\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(uint256(0)),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function test_getL1BlockNumber_succeeds() external {\n assertEq(bn.getL1BlockNumber(), number);\n }\n\n function test_fallback_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n\n function test_receive_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call{ value: 1 }(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n}\n" - }, - "contracts/test/L1CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Messenger_Initializer, Reverter, ConfigurableCaller } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle_Initializer } from \"./L2OutputOracle.t.sol\";\n\n/* Libraries */\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n/* Target contract dependencies */\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/* Target contract */\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\n\ncontract L1CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n // the version is encoded in the nonce\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L1Messenger.messageNonce());\n assertEq(version, L1Messenger.MESSAGE_VERSION());\n }\n\n // sendMessage: should be able to send a single message\n // TODO: this same test needs to be done with the legacy message type\n // by setting the message version to 0\n function test_sendMessage_succeeds() external {\n // deposit transaction on the optimism portal should be called\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n )\n );\n\n // TransactionDeposited event\n vm.expectEmit(true, true, true, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n );\n\n // SentMessage event\n vm.expectEmit(true, true, true, true);\n emit SentMessage(recipient, alice, hex\"ff\", L1Messenger.messageNonce(), 100);\n\n // SentMessageExtension1 event\n vm.expectEmit(true, true, true, true);\n emit SentMessageExtension1(alice, 0);\n\n vm.prank(alice);\n L1Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n // sendMessage: should be able to send the same message twice\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L1Messenger.messageNonce());\n }\n\n function test_xDomainSender_notSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(address(op));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 2 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n // relayMessage: should send a successful call to the target contract\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.expectCall(target, hex\"1111\");\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L1Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n // set the target to be the OptimismPortal\n address target = address(op);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.prank(address(op));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n\n vm.store(address(op), 0, bytes32(abi.encode(sender)));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: should revert if eth is sent from a contract other than the standard bridge\n function test_replayMessage_withValue_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.expectRevert(\n \"CrossDomainMessenger: value must be zero unless message is from a system address\"\n );\n L1Messenger.relayMessage{ value: 100 }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n vm.expectCall(target, hex\"1111\");\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n function test_relayMessage_legacy_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyOldReplay_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Mark legacy message as already relayed.\n uint256 successfulMessagesSlot = 203;\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(target, sender, hex\"1111\", 0);\n bytes32 slot = keccak256(abi.encode(oldHash, successfulMessagesSlot));\n vm.store(address(L1Messenger), slot, bytes32(uint256(1)));\n\n // Expect revert.\n vm.expectRevert(\"CrossDomainMessenger: legacy withdrawal already relayed\");\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was not relayed.\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyRetryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect FailedRelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n function test_relayMessage_legacyRetryAfterSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message has already been relayed\");\n\n // Retry the message again.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n}\n" - }, - "contracts/test/L1ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.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\ncontract L1ERC721Bridge_Test is Messenger_Initializer {\n TestERC721 internal localToken;\n TestERC721 internal remoteToken;\n L1ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L1ERC721Bridge(address(L1Messenger), otherBridge);\n localToken = new TestERC721();\n remoteToken = new TestERC721();\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L1ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L1Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L1Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L1ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L1ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notEscrowed_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n" - }, - "contracts/test/L1StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\n\ncontract L1StandardBridge_Getter_Test is Bridge_Initializer {\n function test_getters_succeeds() external {\n assert(L1Bridge.l2TokenBridge() == address(L2Bridge));\n assert(L1Bridge.OTHER_BRIDGE() == L2Bridge);\n assert(L1Bridge.messenger() == L1Messenger);\n assert(L1Bridge.MESSENGER() == L1Messenger);\n assertEq(L1Bridge.version(), \"1.1.0\");\n }\n}\n\ncontract L1StandardBridge_Initialize_Test is Bridge_Initializer {\n function test_initialize_succeeds() external {\n assertEq(address(L1Bridge.messenger()), address(L1Messenger));\n\n assertEq(address(L1Bridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE);\n\n assertEq(address(L2Bridge), Predeploys.L2_STANDARD_BRIDGE);\n }\n}\n\ncontract L1StandardBridge_Initialize_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_Receive_Test is Bridge_Initializer {\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(op).balance, 0);\n\n // The legacy event must be emitted for backwards compatibility\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 100,\n hex\"\"\n ),\n 200_000\n )\n );\n\n vm.prank(alice, alice);\n (bool success, ) = address(L1Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(op).balance, 100);\n }\n}\n\ncontract L1StandardBridge_Receive_TestFail {}\n\ncontract PreBridgeETH is Bridge_Initializer {\n function _preBridgeETH(bool isLegacy) internal {\n assertEq(address(op).balance, 0);\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 500,\n hex\"dead\"\n );\n\n if (isLegacy) {\n vm.expectCall(\n address(L1Bridge),\n 500,\n abi.encodeWithSelector(L1Bridge.depositETH.selector, 50000, hex\"dead\")\n );\n } else {\n vm.expectCall(\n address(L1Bridge),\n 500,\n abi.encodeWithSelector(L1Bridge.bridgeETH.selector, 50000, hex\"dead\")\n );\n }\n vm.expectCall(\n address(L1Messenger),\n 500,\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 50000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 500,\n 50000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 50000);\n vm.expectCall(\n address(op),\n 500,\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 500,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(500),\n uint256(500),\n baseGas,\n false,\n innerMessage\n );\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, alice, 500, hex\"dead\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, alice, 500, hex\"dead\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 50000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 500);\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L1StandardBridge_DepositETH_Test is PreBridgeETH {\n // depositETH\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_depositETH_succeeds() external {\n _preBridgeETH({ isLegacy: true });\n L1Bridge.depositETH{ value: 500 }(50000, hex\"dead\");\n assertEq(address(op).balance, 500);\n }\n}\n\ncontract L1StandardBridge_BridgeETH_Test is PreBridgeETH {\n // BridgeETH\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_bridgeETH_succeeds() external {\n _preBridgeETH({ isLegacy: false });\n L1Bridge.bridgeETH{ value: 500 }(50000, hex\"dead\");\n assertEq(address(op).balance, 500);\n }\n}\n\ncontract L1StandardBridge_DepositETH_TestFail is Bridge_Initializer {\n function test_depositETH_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, address(L1Token).code);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice);\n L1Bridge.depositETH{ value: 1 }(300, hex\"\");\n }\n}\n\ncontract PreBridgeETHTo is Bridge_Initializer {\n function _preBridgeETHTo(bool isLegacy) internal {\n assertEq(address(op).balance, 0);\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n if (isLegacy) {\n vm.expectCall(\n address(L1Bridge),\n 600,\n abi.encodeWithSelector(L1Bridge.depositETHTo.selector, bob, 60000, hex\"dead\")\n );\n } else {\n vm.expectCall(\n address(L1Bridge),\n 600,\n abi.encodeWithSelector(L1Bridge.bridgeETHTo.selector, bob, 60000, hex\"dead\")\n );\n }\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n bob,\n 600,\n hex\"dead\"\n );\n\n // the L1 bridge should call\n // L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 60000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 600,\n 60000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 60000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 600,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(600),\n uint256(600),\n baseGas,\n false,\n innerMessage\n );\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, bob, 600, hex\"dead\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, bob, 600, hex\"dead\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 60000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 600);\n\n // deposit eth to bob\n vm.prank(alice, alice);\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_Test is PreBridgeETHTo {\n // depositETHTo\n // - emits ETHDepositInitiated\n // - calls optimismPortal.depositTransaction\n // - EOA or contract can call\n // - ETH ends up in the optimismPortal\n function test_depositETHTo_succeeds() external {\n _preBridgeETHTo({ isLegacy: true });\n L1Bridge.depositETHTo{ value: 600 }(bob, 60000, hex\"dead\");\n assertEq(address(op).balance, 600);\n }\n}\n\ncontract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo {\n // BridgeETHTo\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_bridgeETHTo_succeeds() external {\n _preBridgeETHTo({ isLegacy: false });\n L1Bridge.bridgeETHTo{ value: 600 }(bob, 60000, hex\"dead\");\n assertEq(address(op).balance, 600);\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_DepositERC20_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // depositERC20\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - only callable by EOA\n function test_depositERC20_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n // Deal Alice's ERC20 State\n deal(address(L1Token), alice, 100000, true);\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n // The L1Bridge should transfer alice's tokens to itself\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 100)\n );\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L2Token),\n address(L1Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n // the L1 bridge should call L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 10000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 0,\n 10000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 10000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 0,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(0),\n uint256(0),\n baseGas,\n false,\n innerMessage\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 0);\n\n vm.prank(alice);\n L1Bridge.depositERC20(address(L1Token), address(L2Token), 100, 10000, hex\"\");\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n }\n}\n\ncontract L1StandardBridge_DepositERC20_TestFail is Bridge_Initializer {\n function test_depositERC20_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, hex\"ffff\");\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice, alice);\n L1Bridge.depositERC20(address(0), address(0), 100, 100, hex\"\");\n }\n}\n\ncontract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer {\n // depositERC20To\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - callable by a contract\n function test_depositERC20To_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L2Token),\n address(L1Token),\n alice,\n bob,\n 1000,\n hex\"\"\n );\n\n // the L1 bridge should call L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 10000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 0,\n 10000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 10000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 0,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(0),\n uint256(0),\n baseGas,\n false,\n innerMessage\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex\"\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 0);\n\n deal(address(L1Token), alice, 100000, true);\n\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 1000)\n );\n\n vm.prank(alice);\n L1Bridge.depositERC20To(address(L1Token), address(L2Token), bob, 1000, 10000, hex\"\");\n\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 1000);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeETHWithdrawal\n // - emits ETHWithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeETHWithdrawal_succeeds() external {\n uint256 aliceBalance = alice.balance;\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHWithdrawalFinalized(alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n vm.expectCall(alice, hex\"\");\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n // ensure that the messenger has ETH to call with\n vm.deal(address(L1Bridge.messenger()), 100);\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n\n assertEq(address(L1Bridge.messenger()).balance, 0);\n assertEq(aliceBalance + 100, alice.balance);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeERC20Withdrawal\n // - updates bridge.deposits\n // - emits ERC20WithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeERC20Withdrawal_succeeds() external {\n deal(address(L1Token), address(L1Bridge), 100, true);\n\n uint256 slot = stdstore\n .target(address(L1Bridge))\n .sig(\"deposits(address,address)\")\n .with_key(address(L1Token))\n .with_key(address(L2Token))\n .find();\n\n // Give the L1 bridge some ERC20 tokens\n vm.store(address(L1Bridge), bytes32(slot), bytes32(uint256(100)));\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20WithdrawalFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transfer.selector, alice, 100)\n );\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n assertEq(L1Token.balanceOf(address(L1Bridge)), 0);\n assertEq(L1Token.balanceOf(address(alice)), 100);\n }\n}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer {\n function test_finalizeERC20Withdrawal_notMessenger_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(28));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n\n function test_finalizeERC20Withdrawal_notOtherBridge_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(address(0)))\n );\n vm.prank(address(L1Bridge.messenger()));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n}\n\ncontract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {\n function test_finalizeBridgeETH_succeeds() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n\ncontract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer {\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L1Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L1Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, ConfigurableCaller } from \"./CommonTest.t.sol\";\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L2Messenger.messageNonce());\n assertEq(version, L2Messenger.MESSAGE_VERSION());\n }\n\n function test_sendMessage_succeeds() external {\n bytes memory xDomainCallData = Encoding.encodeCrossDomainMessage(\n L2Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n );\n vm.expectCall(\n address(messagePasser),\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData\n )\n );\n\n // MessagePassed event\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(L2Messenger),\n address(L1Messenger),\n 0,\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData,\n Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messagePasser.messageNonce(),\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: L2Messenger.baseGas(hex\"ff\", 100),\n data: xDomainCallData\n })\n )\n );\n\n vm.prank(alice);\n L2Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L2Messenger.messageNonce();\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L2Messenger.messageNonce());\n }\n\n function test_xDomainSender_senderNotSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 2), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n vm.expectCall(target, hex\"1111\");\n\n vm.prank(caller);\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L2Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L2Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n address target = address(messagePasser);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n bytes memory message = hex\"1111\";\n\n vm.prank(caller);\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retry_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n uint256 value = 100;\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(caller), value);\n vm.prank(caller);\n L2Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L2Messenger.successfulMessages(hash), false);\n assertEq(L2Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L2Messenger.successfulMessages(hash), true);\n assertEq(L2Messenger.failedMessages(hash), true);\n }\n}\n" - }, - "contracts/test/L2ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.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\ncontract TestMintableERC721 is OptimismMintableERC721 {\n constructor(address _bridge, address _remoteToken)\n OptimismMintableERC721(_bridge, 1, _remoteToken, \"Test\", \"TST\")\n {}\n\n function mint(address to, uint256 tokenId) public {\n _mint(to, tokenId);\n }\n}\n\ncontract L2ERC721Bridge_Test is Messenger_Initializer {\n TestMintableERC721 internal localToken;\n TestERC721 internal remoteToken;\n L2ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L2ERC721Bridge(address(L2Messenger), otherBridge);\n remoteToken = new TestERC721();\n localToken = new TestMintableERC721(address(bridge), address(remoteToken));\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L2ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L2Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L2Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L2ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"L2ERC721Bridge: Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L1ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L2ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"L2ERC721Bridge: Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_interfaceNotCompliant_reverts() external {\n // Create a non-compliant token\n NonCompliantERC721 nonCompliantToken = new NonCompliantERC721(alice);\n\n // Bridge the non-compliant token.\n vm.prank(alice);\n bridge.bridgeERC721(address(nonCompliantToken), address(0x01), tokenId, 1234, hex\"5678\");\n\n // Attempt to finalize the withdrawal. Should revert because the token does not claim\n // to be compliant with the `IOptimismMintableERC721` interface.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"L2ERC721Bridge: local token interface is not compliant\");\n bridge.finalizeBridgeERC721(\n address(address(nonCompliantToken)),\n address(address(0x01)),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"L2ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_alreadyExists_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721: token already minted\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n\n/**\n * @dev A non-compliant ERC721 token that does not implement the full ERC721 interface.\n *\n * This is used to test that the bridge will revert if the token does not claim to support\n * the ERC721 interface.\n */\ncontract NonCompliantERC721 {\n address internal immutable owner;\n\n constructor(address _owner) {\n owner = _owner;\n }\n\n function ownerOf(uint256) external view returns (address) {\n return owner;\n }\n\n function remoteToken() external pure returns (address) {\n return address(0x01);\n }\n\n function burn(address, uint256) external {\n // Do nothing.\n }\n\n function supportsInterface(bytes4) external pure returns (bool) {\n return false;\n }\n}\n" - }, - "contracts/test/L2OutputOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { L2OutputOracle_Initializer, NextImpl } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2OutputOracleTest is L2OutputOracle_Initializer {\n bytes32 proposedOutput1 = keccak256(abi.encode(1));\n\n function test_constructor_succeeds() external {\n assertEq(oracle.PROPOSER(), proposer);\n assertEq(oracle.CHALLENGER(), owner);\n assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval);\n assertEq(oracle.latestBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingTimestamp(), startingTimestamp);\n }\n\n function test_constructor_badTimestamp_reverts() external {\n vm.expectRevert(\"L2OutputOracle: starting L2 timestamp must be less than current time\");\n\n // startingTimestamp is in the future\n new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp + 1,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n function test_constructor_l2BlockTimeZero_reverts() external {\n vm.expectRevert(\"L2OutputOracle: L2 block time must be greater than 0\");\n new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: 0,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n function test_constructor_submissionInterval_reverts() external {\n vm.expectRevert(\"L2OutputOracle: submission interval must be greater than 0\");\n new L2OutputOracle({\n _submissionInterval: 0,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n /****************\n * Getter Tests *\n ****************/\n\n // Test: latestBlockNumber() should return the correct value\n function test_latestBlockNumber_succeeds() external {\n uint256 proposedNumber = oracle.nextBlockNumber();\n\n // Roll to after the block number we'll propose\n warpToProposeTime(proposedNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, proposedNumber, 0, 0);\n assertEq(oracle.latestBlockNumber(), proposedNumber);\n }\n\n // Test: getL2Output() should return the correct value\n function test_getL2Output_succeeds() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0);\n\n Types.OutputProposal memory proposal = oracle.getL2Output(nextOutputIndex);\n assertEq(proposal.outputRoot, proposedOutput1);\n assertEq(proposal.timestamp, block.timestamp);\n\n // The block number is larger than the latest proposed output:\n vm.expectRevert(stdError.indexOOBError);\n oracle.getL2Output(nextOutputIndex + 1);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is exact block\n function test_getL2OutputIndexAfter_sameBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with exact same block as proposed returns the proposal.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is previous block\n function test_getL2OutputIndexAfter_previousBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with previous block returns the proposal too.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 - 1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value during binary search\n function test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n bytes32 output2 = keccak256(abi.encode(2));\n uint256 nextBlockNumber2 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber2);\n vm.prank(proposer);\n oracle.proposeL2Output(output2, nextBlockNumber2, 0, 0);\n\n bytes32 output3 = keccak256(abi.encode(3));\n uint256 nextBlockNumber3 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber3);\n vm.prank(proposer);\n oracle.proposeL2Output(output3, nextBlockNumber3, 0, 0);\n\n bytes32 output4 = keccak256(abi.encode(4));\n uint256 nextBlockNumber4 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber4);\n vm.prank(proposer);\n oracle.proposeL2Output(output4, nextBlockNumber4, 0, 0);\n\n // Querying with a block number between the first and second proposal\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 + 1);\n assertEq(index1, 1);\n\n // Querying with a block number between the second and third proposal\n uint256 index2 = oracle.getL2OutputIndexAfter(nextBlockNumber2 + 1);\n assertEq(index2, 2);\n\n // Querying with a block number between the third and fourth proposal\n uint256 index3 = oracle.getL2OutputIndexAfter(nextBlockNumber3 + 1);\n assertEq(index3, 3);\n }\n\n // Test: getL2OutputIndexAfter() reverts when no output exists yet\n function test_getL2OutputIndexAfter_noOutputsExis_reverts() external {\n vm.expectRevert(\"L2OutputOracle: cannot get output as no outputs have been proposed yet\");\n oracle.getL2OutputIndexAfter(0);\n }\n\n // Test: nextBlockNumber() should return the correct value\n function test_nextBlockNumber_succeeds() external {\n assertEq(\n oracle.nextBlockNumber(),\n // The return value should match this arithmetic\n oracle.latestBlockNumber() + oracle.SUBMISSION_INTERVAL()\n );\n }\n\n function test_computeL2Timestamp_succeeds() external {\n // reverts if timestamp is too low\n vm.expectRevert(stdError.arithmeticError);\n oracle.computeL2Timestamp(startingBlockNumber - 1);\n\n // returns the correct value...\n // ... for the very first block\n assertEq(oracle.computeL2Timestamp(startingBlockNumber), startingTimestamp);\n\n // ... for the first block after the starting block\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 1),\n startingTimestamp + l2BlockTime\n );\n\n // ... for some other block number\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 96024),\n startingTimestamp + l2BlockTime * 96024\n );\n }\n\n /*****************************\n * Propose Tests - Happy Path *\n *****************************/\n\n // Test: proposeL2Output succeeds when given valid input, and no block hash and number are\n // specified.\n function test_proposeL2Output_proposeAnotherOutput_succeeds() public {\n bytes32 proposedOutput2 = keccak256(abi.encode());\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n uint256 proposedNumber = oracle.latestBlockNumber();\n\n // Ensure the submissionInterval is enforced\n assertEq(nextBlockNumber, proposedNumber + submissionInterval);\n\n vm.roll(nextBlockNumber + 1);\n\n vm.expectEmit(true, true, true, true);\n emit OutputProposed(proposedOutput2, nextOutputIndex, nextBlockNumber, block.timestamp);\n\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output succeeds when given valid input, and when a block hash and number are\n // specified for reorg protection.\n function test_proposeWithBlockhashAndHeight_succeeds() external {\n // Get the number and hash of a previous block in the chain\n uint256 prevL1BlockNumber = block.number - 1;\n bytes32 prevL1BlockHash = blockhash(prevL1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber);\n }\n\n /***************************\n * Propose Tests - Sad Path *\n ***************************/\n\n // Test: proposeL2Output fails if called by a party that is not the proposer.\n function test_proposeL2Output_notProposer_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n\n vm.prank(address(128));\n vm.expectRevert(\"L2OutputOracle: only the proposer address can propose new outputs\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails given a zero blockhash.\n function test_proposeL2Output_emptyOutput_reverts() external {\n bytes32 outputToPropose = bytes32(0);\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: L2 output proposal cannot be the zero hash\");\n oracle.proposeL2Output(outputToPropose, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if the block number doesn't match the next expected number.\n function test_proposeL2Output_unexpectedBlockNumber_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: block number must be equal to next expected block number\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0);\n }\n\n // Test: proposeL2Output fails if it would have a timestamp in the future.\n function test_proposeL2Output_futureTimetamp_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextTimestamp = oracle.computeL2Timestamp(nextBlockNumber);\n vm.warp(nextTimestamp);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: cannot propose L2 output in the future\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if a non-existent L1 block hash and number are provided for reorg\n // protection.\n function test_proposeL2Output_wrongFork_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(\n nonZeroHash,\n nextBlockNumber,\n bytes32(uint256(0x01)),\n block.number - 1\n );\n }\n\n // Test: proposeL2Output fails when given valid input, but the block hash and number do not\n // match.\n function test_proposeL2Output_unmatchedBlockhash_reverts() external {\n // Move ahead to block 100 so that we can reference historical blocks\n vm.roll(100);\n\n // Get the number and hash of a previous block in the chain\n uint256 l1BlockNumber = block.number - 1;\n bytes32 l1BlockHash = blockhash(l1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n\n // This will fail when foundry no longer returns zerod block hashes\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1);\n }\n\n /*****************************\n * Delete Tests - Happy Path *\n *****************************/\n\n function test_deleteOutputs_singleOutput_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 1);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex);\n oracle.deleteL2Outputs(latestOutputIndex);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n function test_deleteOutputs_multipleOutputs_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 3);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex - 2);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval * 3, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n /***************************\n * Delete Tests - Sad Path *\n ***************************/\n\n function test_deleteL2Outputs_ifNotChallenger_reverts() external {\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.expectRevert(\"L2OutputOracle: only the challenger address can delete outputs\");\n oracle.deleteL2Outputs(latestBlockNumber);\n }\n\n function test_deleteL2Outputs_nonExistent_reverts() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestBlockNumber + 1);\n }\n\n function test_deleteL2Outputs_afterLatest_reverts() external {\n // Start by proposing three outputs\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n // Delete the latest two outputs\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n vm.prank(owner);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // Now try to delete the same output again\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n }\n\n function test_deleteL2Outputs_finalized_reverts() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n // Warp past the finalization period + 1 second\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n\n // Try to delete a finalized output\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs that have already been finalized\");\n oracle.deleteL2Outputs(latestOutputIndex);\n }\n}\n\ncontract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {\n Proxy internal proxy;\n\n function setUp() public override {\n super.setUp();\n proxy = Proxy(payable(address(oracle)));\n }\n\n function test_initValuesOnProxy_succeeds() external {\n assertEq(submissionInterval, oracleImpl.SUBMISSION_INTERVAL());\n assertEq(l2BlockTime, oracleImpl.L2_BLOCK_TIME());\n assertEq(startingBlockNumber, oracleImpl.startingBlockNumber());\n assertEq(startingTimestamp, oracleImpl.startingTimestamp());\n\n assertEq(proposer, oracleImpl.PROPOSER());\n assertEq(owner, oracleImpl.CHALLENGER());\n }\n\n function test_initializeProxy_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(payable(proxy)).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_initializeImpl_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(oracleImpl).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(oracle), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(oracle), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(oracle)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n" - }, - "contracts/test/L2StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { console } from \"forge-std/console.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\ncontract L2StandardBridge_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n function test_initialize_succeeds() external {\n assertEq(address(L2Bridge.messenger()), address(L2Messenger));\n assertEq(L1Bridge.l2TokenBridge(), address(L2Bridge));\n assertEq(address(L2Bridge.OTHER_BRIDGE()), address(L1Bridge));\n }\n\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(messagePasser).balance, 0);\n uint256 nonce = L2Messenger.messageNonce();\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 200_000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 100,\n 200_000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 100,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalInitiated(address(0), Predeploys.LEGACY_ERC20_ETH, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n // L2ToL1MessagePasser will emit a MessagePassed event\n vm.expectEmit(true, true, true, true, address(messagePasser));\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 100,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 200_000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessageExtension1(address(L2Bridge), 100);\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 200_000 // StandardBridge's RECEIVE_DEFAULT_GAS_LIMIT\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n vm.prank(alice, alice);\n (bool success, ) = address(L2Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(messagePasser).balance, 100);\n }\n\n // withrdraw\n // - requires amount == msg.value\n function test_withdraw_insufficientValue_reverts() external {\n assertEq(address(messagePasser).balance, 0);\n\n vm.expectRevert(\"StandardBridge: bridging ETH must include sufficient ETH value\");\n vm.prank(alice, alice);\n L2Bridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 100, 1000, hex\"\");\n }\n\n /**\n * @notice Use the legacy `withdraw` interface on the L2StandardBridge to\n * withdraw ether from L2 to L1.\n */\n function test_withdraw_ether_succeeds() external {\n assertTrue(alice.balance >= 100);\n assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 0);\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit WithdrawalInitiated({\n l1Token: address(0),\n l2Token: Predeploys.LEGACY_ERC20_ETH,\n from: alice,\n to: alice,\n amount: 100,\n data: hex\"\"\n });\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ETHBridgeInitiated({ from: alice, to: alice, amount: 100, data: hex\"\" });\n\n vm.prank(alice, alice);\n L2Bridge.withdraw{ value: 100 }({\n _l2Token: Predeploys.LEGACY_ERC20_ETH,\n _amount: 100,\n _minGasLimit: 1000,\n _extraData: hex\"\"\n });\n\n assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 100);\n }\n}\n\ncontract PreBridgeERC20 is Bridge_Initializer {\n // withdraw and BridgeERC20 should behave the same when transferring ERC20 tokens\n // so they should share the same setup and expectEmit calls\n function _preBridgeERC20(bool _isLegacy, address _l2Token) internal {\n // Alice has 100 L2Token\n deal(_l2Token, alice, 100, true);\n assertEq(ERC20(_l2Token).balanceOf(alice), 100);\n uint256 nonce = L2Messenger.messageNonce();\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L1Token),\n _l2Token,\n alice,\n alice,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 1000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 0,\n 1000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n if (_isLegacy) {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(L2Bridge.withdraw.selector, _l2Token, 100, 1000, hex\"\")\n );\n } else {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.bridgeERC20.selector,\n _l2Token,\n address(L1Token),\n 100,\n 1000,\n hex\"\"\n )\n );\n }\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 1000\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n // The L2Bridge should burn the tokens\n vm.expectCall(\n _l2Token,\n abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalInitiated(address(L1Token), _l2Token, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 0,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true);\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true);\n emit SentMessageExtension1(address(L2Bridge), 0);\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {\n // withdraw\n // - token is burned\n // - emits WithdrawalInitiated\n // - calls Withdrawer.initiateWithdrawal\n function test_withdraw_withdrawingERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: true, _l2Token: address(L2Token) });\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n // BridgeERC20\n // - token is burned\n // - emits WithdrawalInitiated\n // - calls Withdrawer.initiateWithdrawal\n function test_bridgeERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: false, _l2Token: address(L2Token) });\n L2Bridge.bridgeERC20(address(L2Token), address(L1Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_withdrawLegacyERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: true, _l2Token: address(LegacyL2Token) });\n L2Bridge.withdraw(address(LegacyL2Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_bridgeLegacyERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: false, _l2Token: address(LegacyL2Token) });\n L2Bridge.bridgeERC20(address(LegacyL2Token), address(L1Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_withdraw_notEOA_reverts() external {\n // This contract has 100 L2Token\n deal(address(L2Token), address(this), 100, true);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n }\n}\n\ncontract PreBridgeERC20To is Bridge_Initializer {\n // withdrawTo and BridgeERC20To should behave the same when transferring ERC20 tokens\n // so they should share the same setup and expectEmit calls\n function _preBridgeERC20To(bool _isLegacy, address _l2Token) internal {\n deal(_l2Token, alice, 100, true);\n assertEq(ERC20(L2Token).balanceOf(alice), 100);\n uint256 nonce = L2Messenger.messageNonce();\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L1Token),\n _l2Token,\n alice,\n bob,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 1000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 0,\n 1000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit WithdrawalInitiated(address(L1Token), _l2Token, alice, bob, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, bob, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(messagePasser));\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 0,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessageExtension1(address(L2Bridge), 0);\n\n if (_isLegacy) {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.withdrawTo.selector,\n _l2Token,\n bob,\n 100,\n 1000,\n hex\"\"\n )\n );\n } else {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.bridgeERC20To.selector,\n _l2Token,\n address(L1Token),\n bob,\n 100,\n 1000,\n hex\"\"\n )\n );\n }\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 1000\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n // The L2Bridge should burn the tokens\n vm.expectCall(\n address(L2Token),\n abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)\n );\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To {\n // withdrawTo\n // - token is burned\n // - emits WithdrawalInitiated w/ correct recipient\n // - calls Withdrawer.initiateWithdrawal\n function test_withdrawTo_withdrawingERC20_succeeds() external {\n _preBridgeERC20To({ _isLegacy: true, _l2Token: address(L2Token) });\n L2Bridge.withdrawTo(address(L2Token), bob, 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n // bridgeERC20To\n // - token is burned\n // - emits WithdrawalInitiated w/ correct recipient\n // - calls Withdrawer.initiateWithdrawal\n function test_bridgeERC20To_succeeds() external {\n _preBridgeERC20To({ _isLegacy: false, _l2Token: address(L2Token) });\n L2Bridge.bridgeERC20To(address(L2Token), address(L1Token), bob, 100, 1000, hex\"\");\n assertEq(L2Token.balanceOf(alice), 0);\n }\n}\n\ncontract L2StandardBridge_Bridge_Test is Bridge_Initializer {\n // finalizeDeposit\n // - only callable by l1TokenBridge\n // - supported token pair emits DepositFinalized\n // - invalid deposit calls Withdrawer.initiateWithdrawal\n function test_finalizeDeposit_depositingERC20_succeeds() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n\n vm.expectCall(\n address(L2Token),\n abi.encodeWithSelector(OptimismMintableERC20.mint.selector, alice, 100)\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeFinalized(address(L2Token), address(L1Token), alice, alice, 100, hex\"\");\n\n vm.prank(address(L2Messenger));\n L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n }\n\n function test_finalizeDeposit_depositingETH_succeeds() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeFinalized(\n address(L2Token), // localToken\n address(L1Token), // remoteToken\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n vm.prank(address(L2Messenger));\n L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L2Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Messenger), 100, hex\"\");\n }\n}\n\ncontract L2StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {\n function test_finalizeBridgeETH_succeeds() external {\n address messenger = address(L2Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n\n vm.expectEmit(true, true, true, true);\n emit DepositFinalized(address(0), Predeploys.LEGACY_ERC20_ETH, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2ToL1MessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\n\ncontract L2ToL1MessagePasserTest is CommonTest {\n L2ToL1MessagePasser messagePasser;\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n function setUp() public virtual override {\n super.setUp();\n messagePasser = new L2ToL1MessagePasser();\n }\n\n function testFuzz_initiateWithdrawal_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint256 nonce = messagePasser.messageNonce();\n\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: _value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, _sender, _target, _value, _gasLimit, _data, withdrawalHash);\n\n vm.deal(_sender, _value);\n vm.prank(_sender);\n messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);\n\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n\n bytes32 slot = keccak256(bytes.concat(withdrawalHash, bytes32(0)));\n\n assertEq(vm.load(address(messagePasser), slot), bytes32(uint256(1)));\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by a contract\n function test_initiateWithdrawal_fromContract_succeeds() external {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\"\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\",\n withdrawalHash\n );\n\n vm.deal(address(this), 2**64);\n messagePasser.initiateWithdrawal{ value: 100 }(address(4), 64000, hex\"\");\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by an EOA\n function test_initiateWithdrawal_fromEOA_succeeds() external {\n uint256 gasLimit = 64000;\n address target = address(4);\n uint256 value = 100;\n bytes memory data = hex\"ff\";\n uint256 nonce = messagePasser.messageNonce();\n\n // EOA emulation\n vm.prank(alice, alice);\n vm.deal(alice, 2**64);\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(nonce, alice, target, value, gasLimit, data)\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, alice, target, value, gasLimit, data, withdrawalHash);\n\n messagePasser.initiateWithdrawal{ value: value }(target, gasLimit, data);\n\n // the sent messages mapping is filled\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n // the nonce increments\n assertEq(nonce + 1, messagePasser.messageNonce());\n }\n\n // Test: burn should destroy the ETH held in the contract\n function test_burn_succeeds() external {\n messagePasser.initiateWithdrawal{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n NON_ZERO_GASLIMIT,\n NON_ZERO_DATA\n );\n\n assertEq(address(messagePasser).balance, NON_ZERO_VALUE);\n vm.expectEmit(true, false, false, false);\n emit WithdrawerBalanceBurnt(NON_ZERO_VALUE);\n messagePasser.burn();\n\n // The Withdrawer should have no balance\n assertEq(address(messagePasser).balance, 0);\n }\n}\n" - }, - "contracts/test/LegacyERC20ETH.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyERC20ETH_Test is CommonTest {\n LegacyERC20ETH eth;\n\n function setUp() public virtual override {\n super.setUp();\n eth = new LegacyERC20ETH();\n }\n\n function test_metadata_succeeds() external {\n assertEq(eth.name(), \"Ether\");\n assertEq(eth.symbol(), \"ETH\");\n assertEq(eth.decimals(), 18);\n }\n\n function test_crossDomain_succeeds() external {\n assertEq(eth.l2Bridge(), Predeploys.L2_STANDARD_BRIDGE);\n assertEq(eth.l1Token(), address(0));\n }\n\n function test_transfer_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transfer is disabled\");\n eth.transfer(alice, 100);\n }\n\n function test_approve_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: approve is disabled\");\n eth.approve(alice, 100);\n }\n\n function test_transferFrom_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transferFrom is disabled\");\n eth.transferFrom(bob, alice, 100);\n }\n\n function test_increaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n eth.increaseAllowance(alice, 100);\n }\n\n function test_decreaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n eth.decreaseAllowance(alice, 100);\n }\n\n function test_mint_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: mint is disabled\");\n eth.mint(alice, 100);\n }\n\n function test_burn_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: burn is disabled\");\n eth.burn(alice, 100);\n }\n}\n" - }, - "contracts/test/LegacyMessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyMessagePasser } from \"../legacy/LegacyMessagePasser.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyMessagePasser_Test is CommonTest {\n LegacyMessagePasser messagePasser;\n\n function setUp() public virtual override {\n super.setUp();\n messagePasser = new LegacyMessagePasser();\n }\n\n function test_passMessageToL1_succeeds() external {\n vm.prank(alice);\n messagePasser.passMessageToL1(hex\"ff\");\n assert(messagePasser.sentMessages(keccak256(abi.encodePacked(hex\"ff\", alice))));\n }\n}\n" - }, - "contracts/test/MerkleTrie.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MerkleTrie } from \"../libraries/trie/MerkleTrie.sol\";\n\ncontract MerkleTrie_get_Test is CommonTest {\n function test_get_validProof1_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579326262\";\n bytes memory val = hex\"6176616c32\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof2_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[\n 2\n ] = hex\"ef83206161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof3_succeeds() external {\n bytes32 root = 0xf838216fa749aefa91e0b672a9c06d3e6e983f913d7107b5dab4af60b5f5abed;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"f387206b6579316161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof4_succeeds() external {\n bytes32 root = 0x37956bab6bba472308146808d5311ac19cb4a7daae5df7efcc0f32badc97f55e;\n bytes memory key = hex\"6b6579316161\";\n bytes memory val = hex\"3031323334\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"ce87206b6579316161853031323334\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof5_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657931\";\n bytes\n memory val = hex\"30313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f862808080808080a057895fdbd71e2c67c2f9274a56811ff5cf458720a7fa713a135e3890f8cafcf8808080808080808080b130313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof6_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657932\";\n bytes memory val = hex\"73686f7274\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[2] = hex\"df808080808080c9823262856176616c338080808080808080808573686f7274\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof7_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657933\";\n bytes memory val = hex\"31323334353637383930313233343536373839303132333435363738393031\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f839808080808080c9823363856176616c338080808080808080809f31323334353637383930313233343536373839303132333435363738393031\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof8_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"61\";\n bytes memory val = hex\"61\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22061\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof9_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"62\";\n bytes memory val = hex\"62\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22062\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof10_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"63\";\n bytes memory val = hex\"63\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22063\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_nonexistentKey1_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b657932\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_nonexistentKey2_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"616e7972616e646f6d6b6579\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_wrongKeyProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579316161\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e216a04892c039d654f1be9af20e88ae53e9ab5fa5520190e0fb2f805823e45ebad22f\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[2] = hex\"d687206e6f746865728d33343938683472697568677765\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_corruptedProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579326262\";\n bytes[] memory proof = new bytes[](5);\n proof[0] = hex\"2fd2ba5ee42358802ffbe0900152a55fabe953ae880ef29abef154d639c09248a016e2\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[\n 2\n ] = hex\"e583165793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 3\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[4] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidDataRemainder_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa000000000000000000000000000000\";\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidInternalNodeHash_reverts() external {\n bytes32 root = 0xa827dff1a657bb9bb9a1c3abe9db173e2f1359f15eb06f1647ea21ac7c95d8fa;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa09862c6b113008c4204c13755693cbb868acc25ebaa98db11df8c89a0c0dd3157\";\n proof[\n 1\n ] = hex\"f380808080808080808080a0de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f00c220118080808080\";\n proof[2] = hex\"de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroBranchValueLength_reverts() external {\n bytes32 root = 0xe04b3589eef96b237cd49ccb5dcf6e654a47682bfa0961d563ab843f7ad1e035;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](2);\n proof[0] = hex\"dd8200aad98080808080808080808080c43b82aabbc43c82aacc80808080\";\n proof[1] = hex\"d98080808080808080808080c43b82aabbc43c82aacc80808080\";\n\n vm.expectRevert(\"MerkleTrie: value length must be greater than zero (branch)\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroLengthKey_reverts() external {\n bytes32 root = 0x54157fd62cdf2f474e7bfec2d3cd581e807bee38488c9590cb887add98936b73;\n bytes memory key = hex\"\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"c78320f00082b443\";\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey1_reverts() external {\n bytes32 root = 0xa513ba530659356fb7588a2c831944e80fd8aedaa5a4dc36f918152be2be0605;\n bytes memory key = hex\"01\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"db10d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[1] = hex\"d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[2] = hex\"c582202381aa\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey2_reverts() external {\n bytes32 root = 0xa06abffaec4ebe8ccde595f4547b864b4421b21c1fc699973f94710c9bc17979;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa07ea462226a3dc0a46afb4ded39306d7a84d311ada3557dfc75a909fd25530905\";\n proof[\n 1\n ] = hex\"f380808080808080808080a027f11bd3af96d137b9287632f44dd00fea1ca1bd70386c30985ede8cc287476e808080c220338080\";\n proof[2] = hex\"e48200bba0a6911545ed01c2d3f4e15b8b27c7bfba97738bd5e6dd674dd07033428a4c53af\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_extraProofElements_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](4);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa\";\n proof[3] = hex\"c32081aa\";\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_validProofs_succeeds(bytes4) external {\n // Generate a test case with a valid proof of inclusion for the k/v pair in the trie.\n (bytes32 root, bytes memory key, bytes memory val, bytes[] memory proof) = ffi\n .getMerkleTrieFuzzCase(\"valid\");\n\n // Assert that our expected value is equal to our actual value.\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidRoot_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"valid\"\n );\n\n bytes32 rootHash = keccak256(abi.encodePacked(root));\n vm.expectRevert(\"MerkleTrie: invalid root hash\");\n MerkleTrie.get(key, proof, rootHash);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_extraProofElements_reverts(bytes4) external {\n // Generate an invalid test case with an extra proof element attached to an otherwise\n // valid proof of inclusion for the passed k/v.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"extra_proof_elems\"\n );\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidLargeInternalHash_reverts(bytes4) external {\n // Generate an invalid test case where a long proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_large_internal_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid large internal hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidInternalNodeHash_reverts(bytes4) external {\n // Generate an invalid test case where a small proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_internal_node_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_corruptedProof_reverts(bytes4) external {\n // Generate an invalid test case where the proof is malformed.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"corrupted_proof\"\n );\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidDataRemainder_reverts(bytes4) external {\n // Generate an invalid test case where a random element of the proof has more bytes than the\n // length designates within the RLP list encoding.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_data_remainder\"\n );\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_prefixedValidKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and a valid key that is prefixed\n // with random bytes\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"prefixed_valid_key\"\n );\n\n // Ambiguous revert check- all that we care is that it *does* fail. This case may\n // fail within different branches.\n vm.expectRevert();\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_emptyKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and an empty key\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"empty_key\"\n );\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_partialProof_reverts(bytes4) external {\n // Get a random test case with a valid trie / partially correct proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"partial_proof\"\n );\n\n vm.expectRevert(\"MerkleTrie: ran out of proof elements\");\n MerkleTrie.get(key, proof, root);\n }\n}\n" - }, - "contracts/test/MintManager.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MintManager } from \"../governance/MintManager.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract MintManager_Initializer is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n MintManager internal manager;\n\n function setUp() public virtual override {\n super.setUp();\n\n vm.prank(owner);\n gov = new GovernanceToken();\n\n vm.prank(owner);\n manager = new MintManager(owner, address(gov));\n\n vm.prank(owner);\n gov.transferOwnership(address(manager));\n }\n}\n\ncontract MintManager_constructor_Test is MintManager_Initializer {\n /**\n * @notice Tests that the constructor properly configures the contract.\n */\n function test_constructor_succeeds() external {\n assertEq(manager.owner(), owner);\n assertEq(address(manager.governanceToken()), address(gov));\n }\n}\n\ncontract MintManager_mint_Test is MintManager_Initializer {\n /**\n * @notice Tests that the mint function properly mints tokens when called by the owner.\n */\n function test_mint_fromOwner_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n /**\n * @notice Tests that the mint function reverts when called by a non-owner.\n */\n function test_mint_fromNotOwner_reverts() external {\n // Mint from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.mint(owner, 100);\n }\n\n /**\n * @notice Tests that the mint function properly mints tokens when called by the owner a second\n * time after the mint period has elapsed.\n */\n function test_mint_afterPeriodElapsed_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again after period elapsed (2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n manager.mint(owner, 2);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 102);\n }\n\n /**\n * @notice Tests that the mint function always reverts when called before the mint period has\n * elapsed, even if the caller is the owner.\n */\n function test_mint_beforePeriodElapsed_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: minting not permitted yet\");\n manager.mint(owner, 100);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n /**\n * @notice Tests that the owner cannot mint more than the mint cap.\n */\n function test_mint_moreThanCap_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again (greater than 2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint amount exceeds cap\");\n manager.mint(owner, 3);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n}\n\ncontract MintManager_upgrade_Test is MintManager_Initializer {\n /**\n * @notice Tests that the owner can upgrade the mint manager.\n */\n function test_upgrade_fromOwner_succeeds() external {\n // Upgrade to new manager.\n vm.prank(owner);\n manager.upgrade(rando);\n\n // New manager is rando.\n assertEq(gov.owner(), rando);\n }\n\n /**\n * @notice Tests that the upgrade function reverts when called by a non-owner.\n */\n function test_upgrade_fromNotOwner_reverts() external {\n // Upgrade from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.upgrade(rando);\n }\n\n /**\n * @notice Tests that the upgrade function reverts when attempting to update to the zero\n * address, even if the caller is the owner.\n */\n function test_upgrade_toZeroAddress_reverts() external {\n // Upgrade to zero address fails.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint manager cannot be the zero address\");\n manager.upgrade(address(0));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport {\n ILegacyMintableERC20,\n IOptimismMintableERC20\n} from \"../universal/IOptimismMintableERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ncontract OptimismMintableERC20_Test is Bridge_Initializer {\n event Mint(address indexed account, uint256 amount);\n event Burn(address indexed account, uint256 amount);\n\n function test_semver_succeeds() external {\n assertEq(L2Token.version(), \"1.0.0\");\n }\n\n function test_remoteToken_succeeds() external {\n assertEq(L2Token.remoteToken(), address(L1Token));\n }\n\n function test_bridge_succeeds() external {\n assertEq(L2Token.bridge(), address(L2Bridge));\n }\n\n function test_l1Token_succeeds() external {\n assertEq(L2Token.l1Token(), address(L1Token));\n }\n\n function test_l2Bridge_succeeds() external {\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_legacy_succeeds() external {\n // Getters for the remote token\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.l1Token(), address(L1Token));\n // Getters for the bridge\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_mint_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 100);\n }\n\n function test_mint_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.mint(alice, 100);\n }\n\n function test_burn_succeeds() external {\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_burn_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.burn(alice, 100);\n }\n\n function test_erc165_supportsInterface_succeeds() external {\n // The assertEq calls in this test are comparing the manual calculation of the iface,\n // with what is returned by the solidity's type().interfaceId, just to be safe.\n bytes4 iface1 = bytes4(keccak256(\"supportsInterface(bytes4)\"));\n assertEq(iface1, type(IERC165).interfaceId);\n assert(L2Token.supportsInterface(iface1));\n\n bytes4 iface2 = L2Token.l1Token.selector ^ L2Token.mint.selector ^ L2Token.burn.selector;\n assertEq(iface2, type(ILegacyMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface2));\n\n bytes4 iface3 = L2Token.remoteToken.selector ^\n L2Token.bridge.selector ^\n L2Token.mint.selector ^\n L2Token.burn.selector;\n assertEq(iface3, type(IOptimismMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface3));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\n\ncontract OptimismMintableTokenFactory_Test is Bridge_Initializer {\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n }\n\n function test_bridge_succeeds() external {\n assertEq(address(L2TokenFactory.BRIDGE()), address(L2Bridge));\n }\n\n function test_createStandardL2Token_succeeds() external {\n address remote = address(4);\n address local = LibRLP.computeAddress(address(L2TokenFactory), 2);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_sameTwice_succeeds() external {\n address remote = address(4);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n\n address local = LibRLP.computeAddress(address(L2TokenFactory), 3);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_remoteIsZero_succeeds() external {\n address remote = address(0);\n vm.expectRevert(\"OptimismMintableERC20Factory: must provide remote token address\");\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721, IERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport {\n IERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport {\n OptimismMintableERC721,\n IOptimismMintableERC721\n} from \"../universal/OptimismMintableERC721.sol\";\n\ncontract OptimismMintableERC721_Test is ERC721Bridge_Initializer {\n ERC721 internal L1Token;\n OptimismMintableERC721 internal L2Token;\n\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n event Mint(address indexed account, uint256 tokenId);\n\n event Burn(address indexed account, uint256 tokenId);\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n L1Token = new ERC721(\"L1Token\", \"L1T\");\n L2Token = new OptimismMintableERC721(\n address(L2Bridge),\n 1,\n address(L1Token),\n \"L2Token\",\n \"L2T\"\n );\n\n // Label the addresses for nice traces.\n vm.label(address(L1Token), \"L1ERC721Token\");\n vm.label(address(L2Token), \"L2ERC721Token\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(L2Token.name(), \"L2Token\");\n assertEq(L2Token.symbol(), \"L2T\");\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.remoteChainId(), 1);\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.REMOTE_CHAIN_ID(), 1);\n assertEq(L2Token.version(), \"1.1.0\");\n }\n\n /**\n * @notice Ensure that the contract supports the expected interfaces.\n */\n function test_supportsInterfaces_succeeds() external {\n // Checks if the contract supports the IOptimismMintableERC721 interface.\n assertTrue(L2Token.supportsInterface(type(IOptimismMintableERC721).interfaceId));\n // Checks if the contract supports the IERC721Enumerable interface.\n assertTrue(L2Token.supportsInterface(type(IERC721Enumerable).interfaceId));\n // Checks if the contract supports the IERC721 interface.\n assertTrue(L2Token.supportsInterface(type(IERC721).interfaceId));\n // Checks if the contract supports the IERC165 interface.\n assertTrue(L2Token.supportsInterface(type(IERC165).interfaceId));\n }\n\n function test_safeMint_succeeds() external {\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(address(0), alice, 1);\n\n // Expect a mint event.\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 1);\n\n // Mint the token.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token should be owned by alice.\n assertEq(L2Token.ownerOf(1), alice);\n }\n\n function test_safeMint_notBridge_reverts() external {\n // Try to mint the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.safeMint(alice, 1);\n }\n\n function test_burn_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(alice, address(0), 1);\n\n // Expect a burn event.\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 1);\n\n // Burn the token.\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 1);\n\n // Token should be owned by address(0).\n vm.expectRevert(\"ERC721: invalid token ID\");\n L2Token.ownerOf(1);\n }\n\n function test_burn_notBridge_reverts() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Try to burn the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.burn(alice, 1);\n }\n\n function test_tokenURI_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token URI should be correct.\n assertEq(\n L2Token.tokenURI(1),\n string(\n abi.encodePacked(\n \"ethereum:\",\n Strings.toHexString(uint160(address(L1Token)), 20),\n \"@\",\n Strings.toString(1),\n \"/tokenURI?uint256=\",\n Strings.toString(1)\n )\n )\n );\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\n\ncontract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer {\n OptimismMintableERC721Factory internal factory;\n\n event OptimismMintableERC721Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n factory = new OptimismMintableERC721Factory(address(L2Bridge), 1);\n\n // Label the addresses for nice traces.\n vm.label(address(factory), \"OptimismMintableERC721Factory\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(factory.BRIDGE(), address(L2Bridge));\n assertEq(factory.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_succeeds() external {\n // Predict the address based on the factory address and nonce.\n address predicted = LibRLP.computeAddress(address(factory), 1);\n\n // Expect a token creation event.\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC721Created(predicted, address(1234), alice);\n\n // Create the token.\n vm.prank(alice);\n OptimismMintableERC721 created = OptimismMintableERC721(\n factory.createOptimismMintableERC721(address(1234), \"L2Token\", \"L2T\")\n );\n\n // Token address should be correct.\n assertEq(address(created), predicted);\n\n // Should be marked as created by the factory.\n assertEq(factory.isOptimismMintableERC721(address(created)), true);\n\n // Token should've been constructed correctly.\n assertEq(created.name(), \"L2Token\");\n assertEq(created.symbol(), \"L2T\");\n assertEq(created.REMOTE_TOKEN(), address(1234));\n assertEq(created.BRIDGE(), address(L2Bridge));\n assertEq(created.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_zeroRemoteToken_reverts() external {\n // Try to create a token with a zero remote token address.\n vm.expectRevert(\"OptimismMintableERC721Factory: L1 token address cannot be address(0)\");\n factory.createOptimismMintableERC721(address(0), \"L2Token\", \"L2T\");\n }\n}\n" - }, - "contracts/test/OptimismPortal.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { Portal_Initializer, CommonTest, NextImpl } from \"./CommonTest.t.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\ncontract OptimismPortal_Test is Portal_Initializer {\n event Paused(address);\n event Unpaused(address);\n\n function test_constructor_succeeds() external {\n assertEq(address(op.L2_ORACLE()), address(oracle));\n assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD);\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal can be paused by the GUARDIAN\n */\n function test_pause_succeeds() external {\n address guardian = op.GUARDIAN();\n\n assertEq(op.paused(), false);\n\n vm.expectEmit(true, true, true, true, address(op));\n emit Paused(guardian);\n\n vm.prank(guardian);\n op.pause();\n\n assertEq(op.paused(), true);\n }\n\n /**\n * @notice The OptimismPortal reverts when an account that is not the\n * GUARDIAN calls `pause()`\n */\n function test_pause_onlyGuardian_reverts() external {\n assertEq(op.paused(), false);\n\n assertTrue(op.GUARDIAN() != alice);\n vm.expectRevert(\"OptimismPortal: only guardian can pause\");\n vm.prank(alice);\n op.pause();\n\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal can be unpaused by the GUARDIAN\n */\n function test_unpause_succeeds() external {\n address guardian = op.GUARDIAN();\n\n vm.prank(guardian);\n op.pause();\n assertEq(op.paused(), true);\n\n vm.expectEmit(true, true, true, true, address(op));\n emit Unpaused(guardian);\n vm.prank(guardian);\n op.unpause();\n\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal reverts when an account that is not\n * the GUARDIAN calls `unpause()`\n */\n function test_unpause_onlyGuardian_reverts() external {\n address guardian = op.GUARDIAN();\n\n vm.prank(guardian);\n op.pause();\n assertEq(op.paused(), true);\n\n assertTrue(op.GUARDIAN() != alice);\n vm.expectRevert(\"OptimismPortal: only guardian can unpause\");\n vm.prank(alice);\n op.unpause();\n\n assertEq(op.paused(), true);\n }\n\n function test_receive_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(alice, alice, 100, 100, 100_000, false, hex\"\");\n\n // give alice money and send as an eoa\n vm.deal(alice, 2**64);\n vm.prank(alice, alice);\n (bool s, ) = address(op).call{ value: 100 }(hex\"\");\n\n assert(s);\n assertEq(address(op).balance, 100);\n }\n\n // Test: depositTransaction fails when contract creation has a non-zero destination address\n function test_depositTransaction_contractCreation_reverts() external {\n // contract creation must have a target of address(0)\n vm.expectRevert(\"OptimismPortal: must send to address(0) when creating a contract\");\n op.depositTransaction(address(1), 1, 0, true, hex\"\");\n }\n\n /**\n * @notice Prevent deposits from being too large to have a sane upper bound\n * on unsafe blocks sent over the p2p network.\n */\n function test_depositTransaction_largeData_reverts() external {\n uint256 size = 120_001;\n uint64 gasLimit = op.minimumGasLimit(uint64(size));\n vm.expectRevert(\"OptimismPortal: data too large\");\n op.depositTransaction({\n _to: address(0),\n _value: 0,\n _gasLimit: gasLimit,\n _isCreation: false,\n _data: new bytes(size)\n });\n }\n\n /**\n * @notice Prevent gasless deposits from being force processed in L2 by\n * ensuring that they have a large enough gas limit set.\n */\n function test_depositTransaction_smallGasLimit_reverts() external {\n vm.expectRevert(\"OptimismPortal: gas limit too small\");\n op.depositTransaction({\n _to: address(1),\n _value: 0,\n _gasLimit: 0,\n _isCreation: false,\n _data: hex\"\"\n });\n }\n\n /**\n * @notice Fuzz for too small of gas limits\n */\n function testFuzz_depositTransaction_smallGasLimit_succeeds(\n bytes memory _data,\n bool _shouldFail\n ) external {\n vm.assume(_data.length <= type(uint64).max);\n\n uint64 gasLimit = op.minimumGasLimit(uint64(_data.length));\n if (_shouldFail) {\n gasLimit = uint64(bound(gasLimit, 0, gasLimit - 1));\n vm.expectRevert(\"OptimismPortal: gas limit too small\");\n }\n\n op.depositTransaction({\n _to: address(0x40),\n _value: 0,\n _gasLimit: gasLimit,\n _isCreation: false,\n _data: _data\n });\n }\n\n /**\n * @notice Ensure that the 0 calldata case is covered and there is a linearly\n * increasing gas limit for larger calldata sizes.\n */\n function test_minimumGasLimit_succeeds() external {\n assertEq(op.minimumGasLimit(0), 21_000);\n assertTrue(op.minimumGasLimit(2) > op.minimumGasLimit(1));\n assertTrue(op.minimumGasLimit(3) > op.minimumGasLimit(2));\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value\n function test_depositTransaction_noValueEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value\n function test_depositTransaction_noValueContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndContractContractCreation_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n function test_simple_isOutputFinalized_succeeds() external {\n uint256 ts = block.timestamp;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(bytes32(uint256(1)), uint128(ts), uint128(startingBlockNumber))\n )\n );\n\n // warp to the finalization period\n vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS());\n assertEq(op.isOutputFinalized(0), false);\n\n // warp past the finalization period\n vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n assertEq(op.isOutputFinalized(0), true);\n }\n\n function test_isOutputFinalized_succeeds() external {\n uint256 checkpoint = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n vm.roll(checkpoint);\n vm.warp(oracle.computeL2Timestamp(checkpoint) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(keccak256(abi.encode(2)), checkpoint, 0, 0);\n\n // warp to the final second of the finalization period\n uint256 finalizationHorizon = block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS();\n vm.warp(finalizationHorizon);\n // The checkpointed block should not be finalized until 1 second from now.\n assertEq(op.isOutputFinalized(nextOutputIndex), false);\n // Nor should a block after it\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n\n // warp past the finalization period\n vm.warp(finalizationHorizon + 1);\n // It should now be finalized.\n assertEq(op.isOutputFinalized(nextOutputIndex), true);\n // But not the block after it.\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n }\n}\n\ncontract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n // Utility function used in the subsequent test. This is necessary to assert that the\n // reentrant call will revert.\n function callPortalAndExpectRevert() external payable {\n vm.expectRevert(\"OptimismPortal: can only trigger one withdrawal per transaction\");\n // Arguments here don't matter, as the require check is the first thing that happens.\n // We assume that this has already been proven.\n op.finalizeWithdrawalTransaction(_defaultTx);\n // Assert that the withdrawal was not finalized.\n assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx)));\n }\n\n /**\n * @notice Proving withdrawal transactions should revert when paused\n */\n function test_proveWithdrawalTransaction_paused_reverts() external {\n vm.prank(op.GUARDIAN());\n op.pause();\n\n vm.expectRevert(\"OptimismPortal: paused\");\n op.proveWithdrawalTransaction({\n _tx: _defaultTx,\n _l2OutputIndex: _proposedOutputIndex,\n _outputRootProof: _outputRootProof,\n _withdrawalProof: _withdrawalProof\n });\n }\n\n // Test: proveWithdrawalTransaction cannot prove a withdrawal with itself (the OptimismPortal) as the target.\n function test_proveWithdrawalTransaction_onSelfCall_reverts() external {\n _defaultTx.target = address(op);\n vm.expectRevert(\"OptimismPortal: you cannot send messages to the portal contract\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the outputRootProof does not match the output root\n function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external {\n // Modify the version to invalidate the withdrawal proof.\n _outputRootProof.version = bytes32(uint256(1));\n vm.expectRevert(\"OptimismPortal: invalid output root proof\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the proof is invalid due to non-existence of\n // the withdrawal.\n function test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() external {\n // modify the default test values to invalidate the proof.\n _defaultTx.data = hex\"abcd\";\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the passed transaction's withdrawalHash has\n // already been proven.\n function test_proveWithdrawalTransaction_replayProve_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: withdrawal hash has already been proven\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has\n // already been proven AND the output root has changed AND the l2BlockNumber stays the same.\n function test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`\n // inside of the `provenWithdrawal`s mapping.\n bytes32 slot;\n assembly {\n mstore(0x00, sload(_withdrawalHash.slot))\n mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in the OptimismPortal\n slot := keccak256(0x00, 0x40)\n }\n\n // Store a different output root within the `provenWithdrawals` mapping without\n // touching the l2BlockNumber or timestamp.\n vm.store(address(op), slot, bytes32(0));\n\n // Warp ahead 1 second\n vm.warp(block.timestamp + 1);\n\n // Even though we have already proven this withdrawalHash, we should be allowed to re-submit\n // our proof with a changed outputRoot\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Ensure that the withdrawal was updated within the mapping\n (, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);\n assertEq(timestamp, block.timestamp);\n }\n\n // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has\n // already been proven AND the output root + output index + l2BlockNumber changes.\n function test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds()\n external\n {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`\n // inside of the `provenWithdrawal`s mapping.\n bytes32 slot;\n assembly {\n mstore(0x00, sload(_withdrawalHash.slot))\n mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in OptimismPortal\n slot := keccak256(0x00, 0x40)\n }\n\n // Store a dummy output root within the `provenWithdrawals` mapping without touching the\n // l2BlockNumber or timestamp.\n vm.store(address(op), slot, bytes32(0));\n\n // Fetch the output proposal at `_proposedOutputIndex` from the L2OutputOracle\n Types.OutputProposal memory proposal = op.L2_ORACLE().getL2Output(_proposedOutputIndex);\n\n // Propose the same output root again, creating the same output at a different index + l2BlockNumber.\n vm.startPrank(op.L2_ORACLE().PROPOSER());\n op.L2_ORACLE().proposeL2Output(\n proposal.outputRoot,\n op.L2_ORACLE().nextBlockNumber(),\n blockhash(block.number),\n block.number\n );\n vm.stopPrank();\n\n // Warp ahead 1 second\n vm.warp(block.timestamp + 1);\n\n // Even though we have already proven this withdrawalHash, we should be allowed to re-submit\n // our proof with a changed outputRoot + a different output index\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex + 1,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Ensure that the withdrawal was updated within the mapping\n (, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);\n assertEq(timestamp, block.timestamp);\n }\n\n // Test: proveWithdrawalTransaction succeeds and emits the WithdrawalProven event.\n function test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: finalizeWithdrawalTransaction succeeds and emits the WithdrawalFinalized event.\n function test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, false, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore + 100);\n }\n\n /**\n * @notice Finalizing withdrawal transactions should revert when paused\n */\n function test_finalizeWithdrawalTransaction_paused_reverts() external {\n vm.prank(op.GUARDIAN());\n op.pause();\n\n vm.expectRevert(\"OptimismPortal: paused\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has not been proven.\n function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectRevert(\"OptimismPortal: withdrawal has not been proven yet\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if withdrawal not proven long enough ago.\n function test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Mock a call where the resulting output root is anything but the original output root. In\n // this case we just use bytes32(uint256(1)).\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(bytes32(uint256(1)), _proposedBlockNumber)\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the provenWithdrawal's timestamp is less\n // than the L2 output oracle's starting timestamp\n function test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a startingTimestamp change on the L2 Oracle\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSignature(\"startingTimestamp()\"),\n abi.encode(block.timestamp + 1)\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output root proven is not the same as the\n // output root at the time of finalization.\n function test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock an outputRoot change on the output proposal before attempting\n // to finalize the withdrawal.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n bytes32(uint256(0)),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output proposal's timestamp has\n // not passed the finalization period.\n function test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a timestamp change on the output proposal that has not passed the\n // finalization period.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(block.timestamp + 1),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\"OptimismPortal: output proposal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction fails because the target reverts,\n // and emits the WithdrawalFinalized event with success=false.\n function test_finalizeWithdrawalTransaction_targetFails_fails() external {\n uint256 bobBalanceBefore = address(bob).balance;\n vm.etch(bob, hex\"fe\"); // Contract with just the invalid opcode.\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, false);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the finalization period has not yet passed.\n function test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() external {\n // Setup the Oracle to return an output with a recent timestamp\n uint256 recentTimestamp = block.timestamp - 1000;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(recentTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has already been finalized.\n function test_finalizeWithdrawalTransaction_onReplay_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if insufficient gas is supplied.\n function test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() external {\n // This number was identified through trial and error.\n uint256 gasLimit = 150_000;\n Types.WithdrawalTransaction memory insufficientGasTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: gasLimit,\n data: hex\"\"\n });\n\n // Get updated proof inputs.\n (bytes32 stateRoot, bytes32 storageRoot, , , bytes[] memory withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(insufficientGasTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n Hashing.hashOutputRootProof(outputRootProof),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n insufficientGasTx,\n _proposedOutputIndex,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectRevert(\"SafeCall: Not enough gas\");\n op.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if a sub-call attempts to finalize another\n // withdrawal.\n function test_finalizeWithdrawalTransaction_onReentrancy_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Copy and modify the default test values to attempt a reentrant call by first calling to\n // this contract's callPortalAndExpectRevert() function above.\n Types.WithdrawalTransaction memory _testTx = _defaultTx;\n _testTx.target = address(this);\n _testTx.data = abi.encodeWithSelector(this.callPortalAndExpectRevert.selector);\n\n // Get modified proof inputs.\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_testTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n // Setup the Oracle to return the outputRoot we want as well as a finalized timestamp.\n uint256 finalizedTimestamp = block.timestamp - oracle.FINALIZATION_PERIOD_SECONDS() - 1;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n outputRoot,\n uint128(finalizedTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(withdrawalHash, alice, address(this));\n op.proveWithdrawalTransaction(\n _testTx,\n _proposedBlockNumber,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectCall(address(this), _testTx.data);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_testTx);\n\n // Ensure that bob's balance was not changed by the reentrant call.\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n function testDiff_finalizeWithdrawalTransaction_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n vm.assume(\n _target != address(op) && // Cannot call the optimism portal or a contract\n _target.code.length == 0 && // No accounts with code\n _target != CONSOLE && // The console has no code but behaves like a contract\n uint160(_target) > 9 // No precompiles (or zero address)\n );\n\n // Total ETH supply is currently about 120M ETH.\n uint256 value = bound(_value, 0, 200_000_000 ether);\n vm.deal(address(op), value);\n\n uint256 gasLimit = bound(_gasLimit, 0, 50_000_000);\n uint256 nonce = messagePasser.messageNonce();\n\n // Get a withdrawal transaction and mock proof from the differential testing script.\n Types.WithdrawalTransaction memory _tx = Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: value,\n gasLimit: gasLimit,\n data: _data\n });\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_tx);\n\n // Create the output root proof\n Types.OutputRootProof memory proof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n\n // Ensure the values returned from ffi are correct\n assertEq(outputRoot, Hashing.hashOutputRootProof(proof));\n assertEq(withdrawalHash, Hashing.hashWithdrawal(_tx));\n\n // Setup the Oracle to return the outputRoot\n vm.mockCall(\n address(oracle),\n abi.encodeWithSelector(oracle.getL2Output.selector),\n abi.encode(outputRoot, block.timestamp, 100)\n );\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _tx,\n 100, // l2BlockNumber\n proof,\n withdrawalProof\n );\n (bytes32 _root, , ) = op.provenWithdrawals(withdrawalHash);\n assertTrue(_root != bytes32(0));\n\n // Warp past the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Finalize the withdrawal transaction\n vm.expectCallMinGas(_tx.target, _tx.value, uint64(_tx.gasLimit), _tx.data);\n op.finalizeWithdrawalTransaction(_tx);\n assertTrue(op.finalizedWithdrawals(withdrawalHash));\n }\n}\n\ncontract OptimismPortalUpgradeable_Test is Portal_Initializer {\n Proxy internal proxy;\n uint64 initialBlockNum;\n\n function setUp() public override {\n super.setUp();\n initialBlockNum = uint64(block.number);\n proxy = Proxy(payable(address(op)));\n }\n\n function test_params_initValuesOnProxy_succeeds() external {\n OptimismPortal p = OptimismPortal(payable(address(proxy)));\n\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = p.params();\n\n ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig();\n assertEq(prevBaseFee, rcfg.minimumBaseFee);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_initialize_cannotInitProxy_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(payable(proxy)).initialize(false);\n }\n\n function test_initialize_cannotInitImpl_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(opImpl).initialize(false);\n }\n\n function test_upgradeToAndCall_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(op), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(op), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(op)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n\n/**\n * @title OptimismPortalResourceFuzz_Test\n * @dev Test various values of the resource metering config to ensure that deposits cannot be\n * broken by changing the config.\n */\ncontract OptimismPortalResourceFuzz_Test is Portal_Initializer {\n /**\n * @dev The max gas limit observed throughout this test. Setting this too high can cause\n * the test to take too long to run.\n */\n uint256 constant MAX_GAS_LIMIT = 30_000_000;\n\n /**\n * @dev Test that various values of the resource metering config will not break deposits.\n */\n function testFuzz_systemConfigDeposit_succeeds(\n uint32 _maxResourceLimit,\n uint8 _elasticityMultiplier,\n uint8 _baseFeeMaxChangeDenominator,\n uint32 _minimumBaseFee,\n uint32 _systemTxMaxGas,\n uint128 _maximumBaseFee,\n uint64 _gasLimit,\n uint64 _prevBoughtGas,\n uint128 _prevBaseFee,\n uint8 _blockDiff\n ) external {\n // Get the set system gas limit\n uint64 gasLimit = systemConfig.gasLimit();\n // Bound resource config\n _maxResourceLimit = uint32(bound(_maxResourceLimit, 21000, MAX_GAS_LIMIT / 8));\n _gasLimit = uint64(bound(_gasLimit, 21000, _maxResourceLimit));\n _prevBaseFee = uint128(bound(_prevBaseFee, 0, 3 gwei));\n // Prevent values that would cause reverts\n vm.assume(gasLimit >= _gasLimit);\n vm.assume(_minimumBaseFee < _maximumBaseFee);\n vm.assume(_baseFeeMaxChangeDenominator > 1);\n vm.assume(uint256(_maxResourceLimit) + uint256(_systemTxMaxGas) <= gasLimit);\n vm.assume(_elasticityMultiplier > 0);\n vm.assume(\n ((_maxResourceLimit / _elasticityMultiplier) * _elasticityMultiplier) ==\n _maxResourceLimit\n );\n _prevBoughtGas = uint64(bound(_prevBoughtGas, 0, _maxResourceLimit - _gasLimit));\n _blockDiff = uint8(bound(_blockDiff, 0, 3));\n\n // Create a resource config to mock the call to the system config with\n ResourceMetering.ResourceConfig memory rcfg = ResourceMetering.ResourceConfig({\n maxResourceLimit: _maxResourceLimit,\n elasticityMultiplier: _elasticityMultiplier,\n baseFeeMaxChangeDenominator: _baseFeeMaxChangeDenominator,\n minimumBaseFee: _minimumBaseFee,\n systemTxMaxGas: _systemTxMaxGas,\n maximumBaseFee: _maximumBaseFee\n });\n vm.mockCall(\n address(systemConfig),\n abi.encodeWithSelector(systemConfig.resourceConfig.selector),\n abi.encode(rcfg)\n );\n\n // Set the resource params\n uint256 _prevBlockNum = block.number - _blockDiff;\n vm.store(\n address(op),\n bytes32(uint256(1)),\n bytes32((_prevBlockNum << 192) | (uint256(_prevBoughtGas) << 128) | _prevBaseFee)\n );\n // Ensure that the storage setting is correct\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = op.params();\n assertEq(prevBaseFee, _prevBaseFee);\n assertEq(prevBoughtGas, _prevBoughtGas);\n assertEq(prevBlockNum, _prevBlockNum);\n\n // Do a deposit, should not revert\n op.depositTransaction{ gas: MAX_GAS_LIMIT }({\n _to: address(0x20),\n _value: 0x40,\n _gasLimit: _gasLimit,\n _isCreation: false,\n _data: hex\"\"\n });\n }\n}\n" - }, - "contracts/test/Proxy.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract SimpleStorage {\n mapping(uint256 => uint256) internal store;\n\n function get(uint256 key) external payable returns (uint256) {\n return store[key];\n }\n\n function set(uint256 key, uint256 value) external payable {\n store[key] = value;\n }\n}\n\ncontract Clasher {\n function upgradeTo(address) external pure {\n revert(\"upgradeTo\");\n }\n}\n\ncontract Proxy_Test is Test {\n event Upgraded(address indexed implementation);\n event AdminChanged(address previousAdmin, address newAdmin);\n\n address alice = address(64);\n\n bytes32 internal constant IMPLEMENTATION_KEY =\n bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1);\n\n bytes32 internal constant OWNER_KEY = bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1);\n\n Proxy proxy;\n SimpleStorage simpleStorage;\n\n function setUp() external {\n // Deploy a proxy and simple storage contract as\n // the implementation\n proxy = new Proxy(alice);\n simpleStorage = new SimpleStorage();\n\n vm.prank(alice);\n proxy.upgradeTo(address(simpleStorage));\n }\n\n function test_implementationKey_succeeds() external {\n // The hardcoded implementation key should be correct\n vm.prank(alice);\n proxy.upgradeTo(address(6));\n\n bytes32 key = vm.load(address(proxy), IMPLEMENTATION_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(6));\n }\n\n function test_ownerKey_succeeds() external {\n // The hardcoded owner key should be correct\n vm.prank(alice);\n proxy.changeAdmin(address(6));\n\n bytes32 key = vm.load(address(proxy), OWNER_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(address(6));\n address owner = proxy.admin();\n assertEq(owner, address(6));\n }\n\n function test_proxyCallToImp_notAdmin_succeeds() external {\n // The implementation does not have a `upgradeTo`\n // method, calling `upgradeTo` not as the owner\n // should revert.\n vm.expectRevert();\n proxy.upgradeTo(address(64));\n\n // Call `upgradeTo` as the owner, it should succeed\n // and emit the `Upgraded` event.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(64));\n vm.prank(alice);\n proxy.upgradeTo(address(64));\n\n // Get the implementation as the owner\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(64));\n }\n\n function test_ownerProxyCall_notAdmin_succeeds() external {\n // Calling `changeAdmin` not as the owner should revert\n // as the implementation does not have a `changeAdmin` method.\n vm.expectRevert();\n proxy.changeAdmin(address(1));\n\n // Call `changeAdmin` as the owner, it should succeed\n // and emit the `AdminChanged` event.\n vm.expectEmit(true, true, true, true);\n emit AdminChanged(alice, address(1));\n vm.prank(alice);\n proxy.changeAdmin(address(1));\n\n // Calling `admin` not as the owner should\n // revert as the implementation does not have\n // a `admin` method.\n vm.expectRevert();\n proxy.admin();\n\n // Calling `admin` as the owner should work.\n vm.prank(address(1));\n address owner = proxy.admin();\n assertEq(owner, address(1));\n }\n\n function test_delegatesToImpl_succeeds() external {\n // Call the storage setter on the proxy\n SimpleStorage(address(proxy)).set(1, 1);\n\n // The key should not be set in the implementation\n uint256 result = simpleStorage.get(1);\n assertEq(result, 0);\n {\n // The key should be set in the proxy\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n\n {\n // The owner should be able to call through the proxy\n // when there is not a function selector crash\n vm.prank(alice);\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n }\n\n function test_upgradeToAndCall_succeeds() external {\n {\n // There should be nothing in the current proxy storage\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 0);\n }\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(simpleStorage));\n vm.prank(alice);\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The call should have impacted the state\n uint256 result = SimpleStorage(address(proxy)).get(1);\n assertEq(result, 1);\n }\n\n function test_upgradeToAndCall_functionDoesNotExist_reverts() external {\n // Get the current implementation address\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call. This reverts because the calldata doesn't\n // match a function on the implementation.\n vm.expectRevert(\"Proxy: delegatecall to new implementation contract failed\");\n vm.prank(alice);\n proxy.upgradeToAndCall(address(simpleStorage), hex\"\");\n\n // The implementation address should have not\n // updated because the call to `upgradeToAndCall`\n // reverted.\n vm.prank(alice);\n address postImpl = proxy.implementation();\n assertEq(impl, postImpl);\n\n // The attempt to `upgradeToAndCall`\n // should revert when it is not called by the owner.\n vm.expectRevert();\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n }\n\n function test_upgradeToAndCall_isPayable_succeeds() external {\n // Give alice some funds\n vm.deal(alice, 1 ether);\n // Set the implementation and call and send\n // value.\n vm.prank(alice);\n proxy.upgradeToAndCall{ value: 1 ether }(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The implementation address should be correct\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // The proxy should have a balance\n assertEq(address(proxy).balance, 1 ether);\n }\n\n function test_upgradeTo_clashingFunctionSignatures_succeeds() external {\n // Clasher has a clashing function with the proxy.\n Clasher clasher = new Clasher();\n\n // Set the clasher as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(clasher));\n\n {\n // Assert that the implementation was set properly.\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(clasher));\n }\n\n // Call the clashing function on the proxy\n // not as the owner so that the call passes through.\n // The implementation will revert so we can be\n // sure that the call passed through.\n vm.expectRevert(bytes(\"upgradeTo\"));\n proxy.upgradeTo(address(0));\n\n {\n // Now call the clashing function as the owner\n // and be sure that it doesn't pass through to\n // the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(0));\n }\n }\n\n // Allow for `eth_call` to call proxy methods\n // by setting \"from\" to `address(0)`.\n function test_implementation_zeroAddressCaller_succeeds() external {\n vm.prank(address(0));\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n }\n\n function test_implementation_isZeroAddress_reverts() external {\n // Set `address(0)` as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n\n (bool success, bytes memory returndata) = address(proxy).call(hex\"\");\n assertEq(success, false);\n\n bytes memory err = abi.encodeWithSignature(\n \"Error(string)\",\n \"Proxy: implementation not initialized\"\n );\n\n assertEq(returndata, err);\n }\n}\n" - }, - "contracts/test/ProxyAdmin.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { SimpleStorage } from \"./Proxy.t.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\n\ncontract ProxyAdmin_Test is Test {\n address alice = address(64);\n\n Proxy proxy;\n L1ChugSplashProxy chugsplash;\n ResolvedDelegateProxy resolved;\n\n AddressManager addressManager;\n\n ProxyAdmin admin;\n\n SimpleStorage implementation;\n\n function setUp() external {\n // Deploy the proxy admin\n admin = new ProxyAdmin(alice);\n // Deploy the standard proxy\n proxy = new Proxy(address(admin));\n\n // Deploy the legacy L1ChugSplashProxy with the admin as the owner\n chugsplash = new L1ChugSplashProxy(address(admin));\n\n // Deploy the legacy AddressManager\n addressManager = new AddressManager();\n // The proxy admin must be the new owner of the address manager\n addressManager.transferOwnership(address(admin));\n // Deploy a legacy ResolvedDelegateProxy with the name `a`.\n // Whatever `a` is set to in AddressManager will be the address\n // that is used for the implementation.\n resolved = new ResolvedDelegateProxy(addressManager, \"a\");\n\n // Impersonate alice for setting up the admin.\n vm.startPrank(alice);\n // Set the address of the address manager in the admin so that it\n // can resolve the implementation address of legacy\n // ResolvedDelegateProxy based proxies.\n admin.setAddressManager(addressManager);\n // Set the reverse lookup of the ResolvedDelegateProxy\n // proxy\n admin.setImplementationName(address(resolved), \"a\");\n\n // Set the proxy types\n admin.setProxyType(address(proxy), ProxyAdmin.ProxyType.ERC1967);\n admin.setProxyType(address(chugsplash), ProxyAdmin.ProxyType.CHUGSPLASH);\n admin.setProxyType(address(resolved), ProxyAdmin.ProxyType.RESOLVED);\n vm.stopPrank();\n\n implementation = new SimpleStorage();\n }\n\n function test_setImplementationName_succeeds() external {\n vm.prank(alice);\n admin.setImplementationName(address(1), \"foo\");\n assertEq(admin.implementationName(address(1)), \"foo\");\n }\n\n function test_setAddressManager_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setAddressManager(AddressManager((address(0))));\n }\n\n function test_setImplementationName_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setImplementationName(address(0), \"foo\");\n }\n\n function test_setProxyType_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setProxyType(address(0), ProxyAdmin.ProxyType.CHUGSPLASH);\n }\n\n function test_owner_succeeds() external {\n assertEq(admin.owner(), alice);\n }\n\n function test_proxyType_succeeds() external {\n assertEq(uint256(admin.proxyType(address(proxy))), uint256(ProxyAdmin.ProxyType.ERC1967));\n assertEq(\n uint256(admin.proxyType(address(chugsplash))),\n uint256(ProxyAdmin.ProxyType.CHUGSPLASH)\n );\n assertEq(\n uint256(admin.proxyType(address(resolved))),\n uint256(ProxyAdmin.ProxyType.RESOLVED)\n );\n }\n\n function test_erc1967GetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(proxy));\n }\n\n function test_chugsplashGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(resolved));\n }\n\n function getProxyImplementation(address payable _proxy) internal {\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(0));\n }\n\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n }\n\n function test_erc1967GetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(resolved));\n }\n\n function getProxyAdmin(address payable _proxy) internal {\n address owner = admin.getProxyAdmin(_proxy);\n assertEq(owner, address(admin));\n }\n\n function test_erc1967ChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(resolved));\n }\n\n function changeProxyAdmin(address payable _proxy) internal {\n ProxyAdmin.ProxyType proxyType = admin.proxyType(address(_proxy));\n\n vm.prank(alice);\n admin.changeProxyAdmin(_proxy, address(128));\n\n // The proxy is no longer the admin and can\n // no longer call the proxy interface except for\n // the ResolvedDelegate type on which anybody can\n // call the admin interface.\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n vm.expectRevert(\"Proxy: implementation not initialized\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n vm.expectRevert(\"L1ChugSplashProxy: implementation is not set yet\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n // Just an empty block to show that all cases are covered\n } else {\n vm.expectRevert(\"ProxyAdmin: unknown proxy type\");\n }\n\n // Call the proxy contract directly to get the admin.\n // Different proxy types have different interfaces.\n vm.prank(address(128));\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n assertEq(Proxy(payable(_proxy)).admin(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n assertEq(L1ChugSplashProxy(payable(_proxy)).getOwner(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n assertEq(addressManager.owner(), address(128));\n } else {\n assert(false);\n }\n }\n\n function test_erc1967Upgrade_succeeds() external {\n upgrade(payable(proxy));\n }\n\n function test_chugsplashUpgrade_succeeds() external {\n upgrade(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgrade_succeeds() external {\n upgrade(payable(resolved));\n }\n\n function upgrade(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n\n function test_erc1967UpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(proxy));\n }\n\n function test_chugsplashUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(resolved));\n }\n\n function upgradeAndCall(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgradeAndCall(\n _proxy,\n address(implementation),\n abi.encodeWithSelector(SimpleStorage.set.selector, 1, 1)\n );\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n\n uint256 got = SimpleStorage(address(_proxy)).get(1);\n assertEq(got, 1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.changeProxyAdmin(payable(proxy), address(0));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgrade(payable(proxy), address(implementation));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgradeAndCall(payable(proxy), address(implementation), hex\"\");\n }\n\n function test_isUpgrading_succeeds() external {\n assertEq(false, admin.isUpgrading());\n\n vm.prank(alice);\n admin.setUpgrading(true);\n assertEq(true, admin.isUpgrading());\n }\n}\n" - }, - "contracts/test/RLP.t.sol": { - "content": "// SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\n/**\n * @title LibRLP\n * @notice Via https://github.com/Rari-Capital/solmate/issues/207.\n */\nlibrary LibRLP {\n using Bytes32AddressLib for bytes32;\n\n function computeAddress(address deployer, uint256 nonce) internal pure returns (address) {\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80)))\n .fromLast20Bytes();\n if (nonce <= 0x7f)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce)))\n .fromLast20Bytes();\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= type(uint8).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd7),\n bytes1(0x94),\n deployer,\n bytes1(0x81),\n uint8(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint16).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd8),\n bytes1(0x94),\n deployer,\n bytes1(0x82),\n uint16(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint24).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd9),\n bytes1(0x94),\n deployer,\n bytes1(0x83),\n uint24(nonce)\n )\n ).fromLast20Bytes();\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return\n keccak256(\n abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))\n ).fromLast20Bytes();\n }\n}\n" - }, - "contracts/test/RLPReader.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { RLPReader } from \"../libraries/rlp/RLPReader.sol\";\n\ncontract RLPReader_readBytes_Test is CommonTest {\n function test_readBytes_bytestring00_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"00\"), hex\"00\");\n }\n\n function test_readBytes_bytestring01_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"01\"), hex\"01\");\n }\n\n function test_readBytes_bytestring7f_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"7f\"), hex\"7f\");\n }\n\n function test_readBytes_revertListItem_reverts() external {\n vm.expectRevert(\"RLPReader: decoded item type for bytes is not a data item\");\n RLPReader.readBytes(hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_readBytes_invalidStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n RLPReader.readBytes(hex\"b9\");\n }\n\n function test_readBytes_invalidListLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n RLPReader.readBytes(hex\"ff\");\n }\n\n function test_readBytes_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: bytes value contains an invalid remainder\");\n RLPReader.readBytes(hex\"800a\");\n }\n\n function test_readBytes_invalidPrefix_reverts() external {\n vm.expectRevert(\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n RLPReader.readBytes(hex\"810a\");\n }\n}\n\ncontract RLPReader_readList_Test is CommonTest {\n function test_readList_empty_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c0\");\n assertEq(list.length, 0);\n }\n\n function test_readList_multiList_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c6827a77c10401\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"827a77\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c104\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"01\");\n }\n\n function test_readList_shortListMax1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n\n assertEq(list.length, 11);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[4]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[5]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[6]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[7]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[8]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[9]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[10]), hex\"8471776572\");\n }\n\n function test_readList_longList1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n\n assertEq(list.length, 4);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"cf84617364668471776572847a786376\");\n }\n\n function test_readList_longList2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n assertEq(list.length, 32);\n\n for (uint256 i = 0; i < 32; i++) {\n assertEq(RLPReader.readRawBytes(list[i]), hex\"cf84617364668471776572847a786376\");\n }\n }\n\n function test_readList_listLongerThan32Elements_reverts() external {\n vm.expectRevert(stdError.indexOOBError);\n RLPReader.readList(\n hex\"e1454545454545454545454545454545454545454545454545454545454545454545\"\n );\n }\n\n function test_readList_listOfLists_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c4c2c0c0c0\");\n assertEq(list.length, 2);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c2c0c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c0\");\n }\n\n function test_readList_listOfLists2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c7c0c1c0c3c0c1c0\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c1c0\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"c3c0c1c0\");\n }\n\n function test_readList_dictTest1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n assertEq(list.length, 4);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"ca846b6579318476616c31\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"ca846b6579328476616c32\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"ca846b6579338476616c33\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"ca846b6579348476616c34\");\n }\n\n function test_readList_invalidShortList_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efdebd\");\n }\n\n function test_readList_longStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efb83600\");\n }\n\n function test_readList_notLongEnough_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(\n hex\"efdebdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n );\n }\n\n function test_readList_int32Overflow_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"bf0f000000000000021111\");\n }\n\n function test_readList_int32Overflow2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ff0f000000000000021111\");\n }\n\n function test_readList_incorrectLengthInArray_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b9002100dc2b275d0f74e8a53e6f4ec61b27f24278820be3f82ea2110e582081b0565df0\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b90040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(hex\"b800\");\n }\n\n function test_readList_leadingZerosInLongLengthList1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must not have any leading zeros (long list)\");\n RLPReader.readList(\n hex\"fb00000040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_nonOptimalLongLengthArray1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b81000112233445566778899aabbccddeeff\");\n }\n\n function test_readList_nonOptimalLongLengthArray2_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b801ff\");\n }\n\n function test_readList_invalidValue_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n RLPReader.readList(hex\"91\");\n }\n\n function test_readList_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n RLPReader.readList(hex\"c000\");\n }\n\n function test_readList_notEnoughContentForString1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"ba010000aabbccddeeff\");\n }\n\n function test_readList_notEnoughContentForString2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"b840ffeeddccbbaa99887766554433221100\");\n }\n\n function test_readList_notEnoughContentForList1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"f90180\");\n }\n\n function test_readList_notEnoughContentForList2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ffffffffffffffffff0001020304050607\");\n }\n\n function test_readList_longStringLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b80100\");\n }\n\n function test_readList_longListLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long list)\");\n RLPReader.readList(hex\"f80100\");\n }\n}\n" - }, - "contracts/test/RLPWriter.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { RLPWriter } from \"../libraries/rlp/RLPWriter.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\n\ncontract RLPWriter_writeString_Test is CommonTest {\n function test_writeString_empty_succeeds() external {\n assertEq(RLPWriter.writeString(\"\"), hex\"80\");\n }\n\n function test_writeString_bytestring00_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0000\"), hex\"00\");\n }\n\n function test_writeString_bytestring01_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0001\"), hex\"01\");\n }\n\n function test_writeString_bytestring7f_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u007F\"), hex\"7f\");\n }\n\n function test_writeString_shortstring_succeeds() external {\n assertEq(RLPWriter.writeString(\"dog\"), hex\"83646f67\");\n }\n\n function test_writeString_shortstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing eli\"),\n hex\"b74c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c69\"\n );\n }\n\n function test_writeString_longstring_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing elit\"),\n hex\"b8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974\"\n );\n }\n\n function test_writeString_longstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\n \"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\"\n ),\n hex\"b904004c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20437572616269747572206d6175726973206d61676e612c20737573636970697420736564207665686963756c61206e6f6e2c20696163756c697320666175636962757320746f72746f722e2050726f696e20737573636970697420756c74726963696573206d616c6573756164612e204475697320746f72746f7220656c69742c2064696374756d2071756973207472697374697175652065752c20756c7472696365732061742072697375732e204d6f72626920612065737420696d70657264696574206d6920756c6c616d636f7270657220616c6971756574207375736369706974206e6563206c6f72656d2e2041656e65616e2071756973206c656f206d6f6c6c69732c2076756c70757461746520656c6974207661726975732c20636f6e73657175617420656e696d2e204e756c6c6120756c74726963657320747572706973206a7573746f2c20657420706f73756572652075726e6120636f6e7365637465747572206e65632e2050726f696e206e6f6e20636f6e76616c6c6973206d657475732e20446f6e65632074656d706f7220697073756d20696e206d617572697320636f6e67756520736f6c6c696369747564696e2e20566573746962756c756d20616e746520697073756d207072696d697320696e206661756369627573206f726369206c756374757320657420756c74726963657320706f737565726520637562696c69612043757261653b2053757370656e646973736520636f6e76616c6c69732073656d2076656c206d617373612066617563696275732c2065676574206c6163696e6961206c616375732074656d706f722e204e756c6c61207175697320756c747269636965732070757275732e2050726f696e20617563746f722072686f6e637573206e69626820636f6e64696d656e74756d206d6f6c6c69732e20416c697175616d20636f6e73657175617420656e696d206174206d65747573206c75637475732c206120656c656966656e6420707572757320656765737461732e20437572616269747572206174206e696268206d657475732e204e616d20626962656e64756d2c206e6571756520617420617563746f72207472697374697175652c206c6f72656d206c696265726f20616c697175657420617263752c206e6f6e20696e74657264756d2074656c6c7573206c65637475732073697420616d65742065726f732e20437261732072686f6e6375732c206d65747573206163206f726e617265206375727375732c20646f6c6f72206a7573746f20756c747269636573206d657475732c20617420756c6c616d636f7270657220766f6c7574706174\"\n );\n }\n}\n\ncontract RLPWriter_writeUint_Test is CommonTest {\n function test_writeUint_zero_succeeds() external {\n assertEq(RLPWriter.writeUint(0x0), hex\"80\");\n }\n\n function test_writeUint_smallint_succeeds() external {\n assertEq(RLPWriter.writeUint(1), hex\"01\");\n }\n\n function test_writeUint_smallint2_succeeds() external {\n assertEq(RLPWriter.writeUint(16), hex\"10\");\n }\n\n function test_writeUint_smallint3_succeeds() external {\n assertEq(RLPWriter.writeUint(79), hex\"4f\");\n }\n\n function test_writeUint_smallint4_succeeds() external {\n assertEq(RLPWriter.writeUint(127), hex\"7f\");\n }\n\n function test_writeUint_mediumint_succeeds() external {\n assertEq(RLPWriter.writeUint(128), hex\"8180\");\n }\n\n function test_writeUint_mediumint2_succeeds() external {\n assertEq(RLPWriter.writeUint(1000), hex\"8203e8\");\n }\n\n function test_writeUint_mediumint3_succeeds() external {\n assertEq(RLPWriter.writeUint(100000), hex\"830186a0\");\n }\n}\n\ncontract RLPWriter_writeList_Test is CommonTest {\n function test_writeList_empty_succeeds() external {\n assertEq(RLPWriter.writeList(new bytes[](0)), hex\"c0\");\n }\n\n function test_writeList_stringList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeString(\"dog\");\n list[1] = RLPWriter.writeString(\"god\");\n list[2] = RLPWriter.writeString(\"cat\");\n\n assertEq(RLPWriter.writeList(list), hex\"cc83646f6783676f6483636174\");\n }\n\n function test_writeList_multiList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeUint(4);\n\n list[0] = RLPWriter.writeString(\"zw\");\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeUint(1);\n\n assertEq(RLPWriter.writeList(list), hex\"c6827a77c10401\");\n }\n\n function test_writeList_shortListMax1_succeeds() external {\n bytes[] memory list = new bytes[](11);\n list[0] = RLPWriter.writeString(\"asdf\");\n list[1] = RLPWriter.writeString(\"qwer\");\n list[2] = RLPWriter.writeString(\"zxcv\");\n list[3] = RLPWriter.writeString(\"asdf\");\n list[4] = RLPWriter.writeString(\"qwer\");\n list[5] = RLPWriter.writeString(\"zxcv\");\n list[6] = RLPWriter.writeString(\"asdf\");\n list[7] = RLPWriter.writeString(\"qwer\");\n list[8] = RLPWriter.writeString(\"zxcv\");\n list[9] = RLPWriter.writeString(\"asdf\");\n list[10] = RLPWriter.writeString(\"qwer\");\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n }\n\n function test_writeList_longlist1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list2);\n list[3] = RLPWriter.writeList(list2);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_longlist2_succeeds() external {\n bytes[] memory list = new bytes[](32);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n for (uint256 i = 0; i < 32; i++) {\n list[i] = RLPWriter.writeList(list2);\n }\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_listoflists_succeeds() external {\n // [ [ [], [] ], [] ]\n bytes[] memory list = new bytes[](2);\n bytes[] memory list2 = new bytes[](2);\n\n list2[0] = RLPWriter.writeList(new bytes[](0));\n list2[1] = RLPWriter.writeList(new bytes[](0));\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(new bytes[](0));\n\n assertEq(RLPWriter.writeList(list), hex\"c4c2c0c0c0\");\n }\n\n function test_writeList_listoflists2_succeeds() external {\n // [ [], [[]], [ [], [[]] ] ]\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeList(new bytes[](0));\n\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeList(new bytes[](0));\n\n list[1] = RLPWriter.writeList(list2);\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeList(new bytes[](0));\n list3[1] = RLPWriter.writeList(list2);\n\n list[2] = RLPWriter.writeList(list3);\n\n assertEq(RLPWriter.writeList(list), hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_writeList_dictTest1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n\n bytes[] memory list1 = new bytes[](2);\n list1[0] = RLPWriter.writeString(\"key1\");\n list1[1] = RLPWriter.writeString(\"val1\");\n\n bytes[] memory list2 = new bytes[](2);\n list2[0] = RLPWriter.writeString(\"key2\");\n list2[1] = RLPWriter.writeString(\"val2\");\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeString(\"key3\");\n list3[1] = RLPWriter.writeString(\"val3\");\n\n bytes[] memory list4 = new bytes[](2);\n list4[0] = RLPWriter.writeString(\"key4\");\n list4[1] = RLPWriter.writeString(\"val4\");\n\n list[0] = RLPWriter.writeList(list1);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list3);\n list[3] = RLPWriter.writeList(list4);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n }\n}\n" - }, - "contracts/test/ResolvedDelegateProxy.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\n\ncontract ResolvedDelegateProxy_Test is Test {\n AddressManager internal addressManager;\n SimpleImplementation internal impl;\n SimpleImplementation internal proxy;\n\n function setUp() public {\n // Set up the address manager.\n addressManager = new AddressManager();\n impl = new SimpleImplementation();\n addressManager.setAddress(\"SimpleImplementation\", address(impl));\n\n // Set up the proxy.\n proxy = SimpleImplementation(\n address(new ResolvedDelegateProxy(addressManager, \"SimpleImplementation\"))\n );\n }\n\n // Tests that the proxy properly bubbles up returndata when the delegatecall succeeds.\n function testFuzz_fallback_delegateCallFoo_succeeds(uint256 x) public {\n vm.expectCall(address(impl), abi.encodeWithSelector(impl.foo.selector, x));\n assertEq(proxy.foo(x), x);\n }\n\n // Tests that the proxy properly bubbles up returndata when the delegatecall reverts.\n function test_fallback_delegateCallBar_reverts() public {\n vm.expectRevert(\"SimpleImplementation: revert\");\n vm.expectCall(address(impl), abi.encodeWithSelector(impl.bar.selector));\n proxy.bar();\n }\n\n // Tests that the proxy fallback reverts as expected if the implementation within the\n // address manager is not set.\n function test_fallback_addressManagerNotSet_reverts() public {\n AddressManager am = new AddressManager();\n SimpleImplementation p = SimpleImplementation(\n address(new ResolvedDelegateProxy(am, \"SimpleImplementation\"))\n );\n\n vm.expectRevert(\"ResolvedDelegateProxy: target address must be initialized\");\n p.foo(0);\n }\n}\n\ncontract SimpleImplementation {\n function foo(uint256 _x) public pure returns (uint256) {\n return _x;\n }\n\n function bar() public pure {\n revert(\"SimpleImplementation: revert\");\n }\n}\n" - }, - "contracts/test/ResourceMetering.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract MeterUser is ResourceMetering {\n ResourceMetering.ResourceConfig public innerConfig;\n\n constructor() {\n initialize();\n innerConfig = Constants.DEFAULT_RESOURCE_CONFIG();\n }\n\n function initialize() public initializer {\n __ResourceMetering_init();\n }\n\n function resourceConfig() public view returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig();\n }\n\n function _resourceConfig()\n internal\n view\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return innerConfig;\n }\n\n function use(uint64 _amount) public metered(_amount) {}\n\n function set(\n uint128 _prevBaseFee,\n uint64 _prevBoughtGas,\n uint64 _prevBlockNum\n ) public {\n params = ResourceMetering.ResourceParams({\n prevBaseFee: _prevBaseFee,\n prevBoughtGas: _prevBoughtGas,\n prevBlockNum: _prevBlockNum\n });\n }\n\n function setParams(ResourceMetering.ResourceConfig memory newConfig) public {\n innerConfig = newConfig;\n }\n}\n\n/**\n * @title ResourceConfig\n * @notice The tests are based on the default config values. It is expected that\n * the config values used in these tests are ran in production.\n */\ncontract ResourceMetering_Test is Test {\n MeterUser internal meter;\n uint64 initialBlockNum;\n\n function setUp() public {\n meter = new MeterUser();\n initialBlockNum = uint64(block.number);\n }\n\n function test_meter_initialResourceParams_succeeds() external {\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n\n assertEq(prevBaseFee, rcfg.minimumBaseFee);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_updateParamsNoChange_succeeds() external {\n meter.use(0); // equivalent to just updating the base fee and block number\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n meter.use(0);\n (uint128 postBaseFee, uint64 postBoughtGas, uint64 postBlockNum) = meter.params();\n\n assertEq(postBaseFee, prevBaseFee);\n assertEq(postBoughtGas, prevBoughtGas);\n assertEq(postBlockNum, prevBlockNum);\n }\n\n function test_meter_updateOneEmptyBlock_succeeds() external {\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 1);\n }\n\n function test_meter_updateTwoEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 2);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 2);\n }\n\n function test_meter_updateTenEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 10);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 10);\n }\n\n function test_meter_updateNoGasDelta_succeeds() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint256 target = uint256(rcfg.maxResourceLimit) / uint256(rcfg.elasticityMultiplier);\n meter.use(uint64(target));\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1000000000);\n assertEq(prevBoughtGas, target);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_useMax_succeeds() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n meter.use(target * elasticityMultiplier);\n\n (, uint64 prevBoughtGas, ) = meter.params();\n assertEq(prevBoughtGas, target * elasticityMultiplier);\n\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 postBaseFee, , ) = meter.params();\n assertEq(postBaseFee, 2125000000);\n }\n\n /**\n * @notice This tests that the metered modifier reverts if\n * the ResourceConfig baseFeeMaxChangeDenominator\n * is set to 1.\n * Since the metered modifier internally calls\n * solmate's powWad function, it will revert\n * with the error string \"UNDEFINED\" since the\n * first parameter will be computed as 0.\n */\n function test_meter_denominatorEq1_reverts() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n rcfg.baseFeeMaxChangeDenominator = 1;\n meter.setParams(rcfg);\n meter.use(target * elasticityMultiplier);\n\n (, uint64 prevBoughtGas, ) = meter.params();\n assertEq(prevBoughtGas, target * elasticityMultiplier);\n\n vm.roll(initialBlockNum + 2);\n\n vm.expectRevert(\"UNDEFINED\");\n meter.use(0);\n }\n\n function test_meter_useMoreThanMax_reverts() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n vm.expectRevert(\"ResourceMetering: cannot buy more gas than available gas limit\");\n meter.use(target * elasticityMultiplier + 1);\n }\n\n // Demonstrates that the resource metering arithmetic can tolerate very large gaps between\n // deposits.\n function testFuzz_meter_largeBlockDiff_succeeds(uint64 _amount, uint256 _blockDiff) external {\n // This test fails if the following line is commented out.\n // At 12 seconds per block, this number is effectively unreachable.\n vm.assume(_blockDiff < 433576281058164217753225238677900874458691);\n\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n vm.assume(_amount < target * elasticityMultiplier);\n vm.roll(initialBlockNum + _blockDiff);\n meter.use(_amount);\n }\n}\n\n/**\n * @title CustomMeterUser\n * @notice A simple wrapper around `ResourceMetering` that allows the initial\n * params to be set in the constructor.\n */\ncontract CustomMeterUser is ResourceMetering {\n uint256 public startGas;\n uint256 public endGas;\n\n constructor(\n uint128 _prevBaseFee,\n uint64 _prevBoughtGas,\n uint64 _prevBlockNum\n ) {\n params = ResourceMetering.ResourceParams({\n prevBaseFee: _prevBaseFee,\n prevBoughtGas: _prevBoughtGas,\n prevBlockNum: _prevBlockNum\n });\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return Constants.DEFAULT_RESOURCE_CONFIG();\n }\n\n function use(uint64 _amount) public returns (uint256) {\n uint256 initialGas = gasleft();\n _metered(_amount, initialGas);\n return initialGas - gasleft();\n }\n}\n\n/**\n * @title ArtifactResourceMetering_Test\n * @notice A table test that sets the state of the ResourceParams and then requests\n * various amounts of gas. This test ensures that a wide range of values\n * can safely be used with the `ResourceMetering` contract.\n * It also writes a CSV file to disk that includes useful information\n * about how much gas is used and how expensive it is in USD terms to\n * purchase the deposit gas.\n */\ncontract ArtifactResourceMetering_Test is Test {\n uint128 internal minimumBaseFee;\n uint128 internal maximumBaseFee;\n uint64 internal maxResourceLimit;\n uint64 internal targetResourceLimit;\n\n string internal outfile;\n\n // keccak256(abi.encodeWithSignature(\"Error(string)\", \"ResourceMetering: cannot buy more gas than available gas limit\"))\n bytes32 internal cannotBuyMoreGas =\n 0x84edc668cfd5e050b8999f43ff87a1faaa93e5f935b20bc1dd4d3ff157ccf429;\n // keccak256(abi.encodeWithSignature(\"Panic(uint256)\", 0x11))\n bytes32 internal overflowErr =\n 0x1ca389f2c8264faa4377de9ce8e14d6263ef29c68044a9272d405761bab2db27;\n // keccak256(hex\"\")\n bytes32 internal emptyReturnData =\n 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n\n /**\n * @notice Sets up the tests by getting constants from the ResourceMetering\n * contract.\n */\n function setUp() public {\n vm.roll(1_000_000);\n\n MeterUser base = new MeterUser();\n ResourceMetering.ResourceConfig memory rcfg = base.resourceConfig();\n minimumBaseFee = uint128(rcfg.minimumBaseFee);\n maximumBaseFee = rcfg.maximumBaseFee;\n maxResourceLimit = uint64(rcfg.maxResourceLimit);\n targetResourceLimit = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n\n outfile = string.concat(vm.projectRoot(), \"/.resource-metering.csv\");\n try vm.removeFile(outfile) {} catch {}\n }\n\n /**\n * @notice Generate a CSV file. The call to `meter` should be called with at\n * most the L1 block gas limit. Without specifying the amount of\n * gas, it can take very long to execute.\n */\n function test_meter_generateArtifact_succeeds() external {\n vm.writeLine(\n outfile,\n \"prevBaseFee,prevBoughtGas,prevBlockNumDiff,l1BaseFee,requestedGas,gasConsumed,ethPrice,usdCost,success\"\n );\n\n // prevBaseFee value in ResourceParams\n uint128[] memory prevBaseFees = new uint128[](5);\n prevBaseFees[0] = minimumBaseFee;\n prevBaseFees[1] = maximumBaseFee;\n prevBaseFees[2] = uint128(50 gwei);\n prevBaseFees[3] = uint128(100 gwei);\n prevBaseFees[4] = uint128(200 gwei);\n\n // prevBoughtGas value in ResourceParams\n uint64[] memory prevBoughtGases = new uint64[](1);\n prevBoughtGases[0] = uint64(0);\n\n // prevBlockNum diff, simulates blocks with no deposits when non zero\n uint64[] memory prevBlockNumDiffs = new uint64[](2);\n prevBlockNumDiffs[0] = 0;\n prevBlockNumDiffs[1] = 1;\n\n // The amount of L2 gas that a user requests\n uint64[] memory requestedGases = new uint64[](3);\n requestedGases[0] = maxResourceLimit;\n requestedGases[1] = targetResourceLimit;\n requestedGases[2] = uint64(100_000);\n\n // The L1 base fee\n uint256[] memory l1BaseFees = new uint256[](4);\n l1BaseFees[0] = 1 gwei;\n l1BaseFees[1] = 50 gwei;\n l1BaseFees[2] = 75 gwei;\n l1BaseFees[3] = 100 gwei;\n\n // USD price of 1 ether\n uint256[] memory ethPrices = new uint256[](2);\n ethPrices[0] = 1600;\n ethPrices[1] = 3200;\n\n // Iterate over all of the test values and run a test\n for (uint256 i; i < prevBaseFees.length; i++) {\n for (uint256 j; j < prevBoughtGases.length; j++) {\n for (uint256 k; k < prevBlockNumDiffs.length; k++) {\n for (uint256 l; l < requestedGases.length; l++) {\n for (uint256 m; m < l1BaseFees.length; m++) {\n for (uint256 n; n < ethPrices.length; n++) {\n uint256 snapshotId = vm.snapshot();\n\n uint128 prevBaseFee = prevBaseFees[i];\n uint64 prevBoughtGas = prevBoughtGases[j];\n uint64 prevBlockNumDiff = prevBlockNumDiffs[k];\n uint64 requestedGas = requestedGases[l];\n uint256 l1BaseFee = l1BaseFees[m];\n uint256 ethPrice = ethPrices[n];\n string memory result = \"success\";\n\n vm.fee(l1BaseFee);\n\n CustomMeterUser meter = new CustomMeterUser({\n _prevBaseFee: prevBaseFee,\n _prevBoughtGas: prevBoughtGas,\n _prevBlockNum: uint64(block.number)\n });\n\n vm.roll(block.number + prevBlockNumDiff);\n\n // Call the metering code and catch the various\n // types of errors.\n uint256 gasConsumed = 0;\n try meter.use{ gas: 30_000_000 }(requestedGas) returns (\n uint256 _gasConsumed\n ) {\n gasConsumed = _gasConsumed;\n } catch (bytes memory err) {\n bytes32 hash = keccak256(err);\n if (hash == cannotBuyMoreGas) {\n result = \"ResourceMetering: cannot buy more gas than available gas limit\";\n } else if (hash == overflowErr) {\n result = \"arithmetic overflow/underflow\";\n } else if (hash == emptyReturnData) {\n result = \"out of gas\";\n } else {\n result = \"UNKNOWN ERROR\";\n }\n }\n\n // Compute the USD cost of the gas used\n uint256 usdCost = (gasConsumed * l1BaseFee * ethPrice) / 1 ether;\n\n vm.writeLine(\n outfile,\n string.concat(\n vm.toString(prevBaseFee),\n \",\",\n vm.toString(prevBoughtGas),\n \",\",\n vm.toString(prevBlockNumDiff),\n \",\",\n vm.toString(l1BaseFee),\n \",\",\n vm.toString(requestedGas),\n \",\",\n vm.toString(gasConsumed),\n \",\",\n \"$\",\n vm.toString(ethPrice),\n \",\",\n \"$\",\n vm.toString(usdCost),\n \",\",\n result\n )\n );\n\n assertTrue(vm.revertTo(snapshotId));\n }\n }\n }\n }\n }\n }\n }\n}\n" - }, - "contracts/test/SafeCall.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\n\ncontract SafeCall_Test is CommonTest {\n function testFuzz_call_succeeds(\n address from,\n address to,\n uint256 gas,\n uint64 value,\n bytes memory data\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles (mainnet)\n assumeNoPrecompiles(to, 1);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n // don't call the ffi interface\n vm.assume(to != address(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f));\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n uint256[2] memory balancesBefore = [from.balance, to.balance];\n\n vm.expectCall(to, value, data);\n vm.prank(from);\n bool success = SafeCall.call(to, gas, value, data);\n\n assertTrue(success, \"call not successful\");\n if (from == to) {\n assertEq(from.balance, balancesBefore[0], \"Self-send did not change balance\");\n } else {\n assertEq(from.balance, balancesBefore[0] - value, \"from balance not drained\");\n assertEq(to.balance, balancesBefore[1] + value, \"to balance received\");\n }\n }\n\n function testFuzz_callWithMinGas_hasEnough_succeeds(\n address from,\n address to,\n uint64 minGas,\n uint64 value,\n bytes memory data\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles (mainnet)\n assumeNoPrecompiles(to, 1);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n // don't call the FFIInterface\n vm.assume(to != address(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f));\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n // Bound minGas to [0, l1_block_gas_limit]\n minGas = uint64(bound(minGas, 0, 30_000_000));\n\n uint256[2] memory balancesBefore = [from.balance, to.balance];\n\n vm.expectCallMinGas(to, value, minGas, data);\n vm.prank(from);\n bool success = SafeCall.callWithMinGas(to, minGas, value, data);\n\n assertTrue(success, \"call not successful\");\n if (from == to) {\n assertEq(from.balance, balancesBefore[0], \"Self-send did not change balance\");\n } else {\n assertEq(from.balance, balancesBefore[0] - value, \"from balance not drained\");\n assertEq(to.balance, balancesBefore[1] + value, \"to balance received\");\n }\n }\n\n function test_callWithMinGas_noLeakageLow_succeeds() external {\n SimpleSafeCaller caller = new SimpleSafeCaller();\n\n for (uint64 i = 40_000; i < 100_000; i++) {\n uint256 snapshot = vm.snapshot();\n\n // 65_907 is the exact amount of gas required to make the safe call\n // successfully.\n if (i < 65_907) {\n assertFalse(caller.makeSafeCall(i, 25_000));\n } else {\n vm.expectCallMinGas(\n address(caller),\n 0,\n 25_000,\n abi.encodeWithSelector(caller.setA.selector, 1)\n );\n assertTrue(caller.makeSafeCall(i, 25_000));\n }\n\n assertTrue(vm.revertTo(snapshot));\n }\n }\n\n function test_callWithMinGas_noLeakageHigh_succeeds() external {\n SimpleSafeCaller caller = new SimpleSafeCaller();\n\n for (uint64 i = 15_200_000; i < 15_300_000; i++) {\n uint256 snapshot = vm.snapshot();\n\n // 15_278_606 is the exact amount of gas required to make the safe call\n // successfully.\n if (i < 15_278_606) {\n assertFalse(caller.makeSafeCall(i, 15_000_000));\n } else {\n vm.expectCallMinGas(\n address(caller),\n 0,\n 15_000_000,\n abi.encodeWithSelector(caller.setA.selector, 1)\n );\n assertTrue(caller.makeSafeCall(i, 15_000_000));\n }\n\n assertTrue(vm.revertTo(snapshot));\n }\n }\n}\n\ncontract SimpleSafeCaller {\n uint256 public a;\n\n function makeSafeCall(uint64 gas, uint64 minGas) external returns (bool) {\n return\n SafeCall.call(\n address(this),\n gas,\n 0,\n abi.encodeWithSelector(this.makeSafeCallMinGas.selector, minGas)\n );\n }\n\n function makeSafeCallMinGas(uint64 minGas) external returns (bool) {\n return\n SafeCall.callWithMinGas(\n address(this),\n minGas,\n 0,\n abi.encodeWithSelector(this.setA.selector, 1)\n );\n }\n\n function setA(uint256 _a) external {\n a = _a;\n }\n}\n" - }, - "contracts/test/Semver.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\n\n/**\n * @notice Test the Semver contract that is used for semantic versioning\n * of various contracts.\n */\ncontract Semver_Test is CommonTest {\n /**\n * @notice Global semver contract deployed in setUp. This is used in\n * the test cases.\n */\n Semver semver;\n\n /**\n * @notice Deploy a Semver contract\n */\n function setUp() public virtual override {\n semver = new Semver(7, 8, 0);\n }\n\n /**\n * @notice Test the version getter\n */\n function test_version_succeeds() external {\n assertEq(semver.version(), \"7.8.0\");\n }\n\n /**\n * @notice Since the versions are all immutable, they should\n * be able to be accessed from behind a proxy without needing\n * to initialize the contract.\n */\n function test_behindProxy_succeeds() external {\n Proxy proxy = new Proxy(alice);\n vm.prank(alice);\n proxy.upgradeTo(address(semver));\n\n assertEq(Semver(address(proxy)).version(), \"7.8.0\");\n }\n}\n" - }, - "contracts/test/SequencerFeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { SequencerFeeVault } from \"../L2/SequencerFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract SequencerFeeVault_Test is Bridge_Initializer {\n SequencerFeeVault vault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET));\n address constant recipient = address(256);\n\n event Withdrawal(uint256 value, address to, address from);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.SEQUENCER_FEE_WALLET, address(new SequencerFeeVault(recipient)).code);\n vm.label(Predeploys.SEQUENCER_FEE_WALLET, \"SequencerFeeVault\");\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(vault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n\n function test_constructor_succeeds() external {\n assertEq(vault.l1FeeWallet(), recipient);\n }\n\n function test_receive_succeeds() external {\n uint256 balance = address(vault).balance;\n\n vm.prank(alice);\n (bool success, ) = address(vault).call{ value: 100 }(hex\"\");\n\n assertEq(success, true);\n assertEq(address(vault).balance, balance + 100);\n }\n\n function test_withdraw_notEnough_reverts() external {\n assert(address(vault).balance < vault.MIN_WITHDRAWAL_AMOUNT());\n\n vm.expectRevert(\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n vault.withdraw();\n }\n\n function test_withdraw_succeeds() external {\n uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1;\n vm.deal(address(vault), amount);\n\n // No ether has been withdrawn yet\n assertEq(vault.totalProcessed(), 0);\n\n vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));\n emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this));\n\n // The entire vault's balance is withdrawn\n vm.expectCall(\n Predeploys.L2_STANDARD_BRIDGE,\n address(vault).balance,\n abi.encodeWithSelector(\n StandardBridge.bridgeETHTo.selector,\n vault.l1FeeWallet(),\n 35_000,\n bytes(\"\")\n )\n );\n\n vault.withdraw();\n\n // The withdrawal was successful\n assertEq(vault.totalProcessed(), amount);\n }\n}\n" - }, - "contracts/test/StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport {\n OptimismMintableERC20,\n ILegacyMintableERC20\n} from \"../universal/OptimismMintableERC20.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/**\n * @title StandardBridgeTester\n * @notice Simple wrapper around the StandardBridge contract that exposes\n * internal functions so they can be more easily tested directly.\n */\ncontract StandardBridgeTester is StandardBridge {\n constructor(address payable _messenger, address payable _otherBridge)\n StandardBridge(_messenger, _otherBridge)\n {}\n\n function isOptimismMintableERC20(address _token) external view returns (bool) {\n return _isOptimismMintableERC20(_token);\n }\n\n function isCorrectTokenPair(address _mintableToken, address _otherToken)\n external\n view\n returns (bool)\n {\n return _isCorrectTokenPair(_mintableToken, _otherToken);\n }\n\n receive() external payable override {}\n}\n\n/**\n * @title LegacyMintable\n * @notice Simple implementation of the legacy OptimismMintableERC20.\n */\ncontract LegacyMintable is ERC20, ILegacyMintableERC20 {\n constructor(string memory _name, string memory _ticker) ERC20(_name, _ticker) {}\n\n function l1Token() external pure returns (address) {\n return address(0);\n }\n\n function mint(address _to, uint256 _amount) external pure {}\n\n function burn(address _from, uint256 _amount) external pure {}\n\n /**\n * @notice Implements ERC165. This implementation should not be changed as\n * it is how the actual legacy optimism mintable token does the\n * check. Allows for testing against code that is has been deployed,\n * assuming different compiler version is no problem.\n */\n function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {\n bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^\n ILegacyMintableERC20.mint.selector ^\n ILegacyMintableERC20.burn.selector;\n return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n }\n}\n\n/**\n * @title StandardBridge_Stateless_Test\n * @notice Tests internal functions that require no existing state or contract\n * interactions with the messenger.\n */\ncontract StandardBridge_Stateless_Test is CommonTest {\n StandardBridgeTester internal bridge;\n OptimismMintableERC20 internal mintable;\n ERC20 internal erc20;\n LegacyMintable internal legacy;\n\n function setUp() public override {\n super.setUp();\n\n bridge = new StandardBridgeTester({\n _messenger: payable(address(0)),\n _otherBridge: payable(address(0))\n });\n\n mintable = new OptimismMintableERC20({\n _bridge: address(0),\n _remoteToken: address(0),\n _name: \"Stonks\",\n _symbol: \"STONK\"\n });\n\n erc20 = new ERC20(\"Altcoin\", \"ALT\");\n legacy = new LegacyMintable(\"Legacy\", \"LEG\");\n }\n\n /**\n * @notice Test coverage for identifying OptimismMintableERC20 tokens.\n * This function should return true for both modern and legacy\n * OptimismMintableERC20 tokens and false for any accounts that\n * do not implement the interface.\n */\n function test_isOptimismMintableERC20_succeeds() external {\n // Both the modern and legacy mintable tokens should return true\n assertTrue(bridge.isOptimismMintableERC20(address(mintable)));\n assertTrue(bridge.isOptimismMintableERC20(address(legacy)));\n // A regular ERC20 should return false\n assertFalse(bridge.isOptimismMintableERC20(address(erc20)));\n // Non existent contracts should return false and not revert\n assertEq(address(0x20).code.length, 0);\n assertFalse(bridge.isOptimismMintableERC20(address(0x20)));\n }\n\n /**\n * @notice Test coverage of isCorrectTokenPair under different types of\n * tokens.\n */\n function test_isCorrectTokenPair_succeeds() external {\n // Modern + known to be correct remote token\n assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.remoteToken()));\n // Modern + known to be correct l1Token (legacy interface)\n assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.l1Token()));\n // Modern + known to be incorrect remote token\n assertTrue(mintable.remoteToken() != address(0x20));\n assertFalse(bridge.isCorrectTokenPair(address(mintable), address(0x20)));\n // Legacy + known to be correct l1Token\n assertTrue(bridge.isCorrectTokenPair(address(legacy), legacy.l1Token()));\n // Legacy + known to be incorrect l1Token\n assertTrue(legacy.l1Token() != address(0x20));\n assertFalse(bridge.isCorrectTokenPair(address(legacy), address(0x20)));\n // A token that doesn't support either modern or legacy interface\n // will revert\n vm.expectRevert();\n bridge.isCorrectTokenPair(address(erc20), address(1));\n }\n}\n" - }, - "contracts/test/SystemConfig.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract SystemConfig_Init is CommonTest {\n SystemConfig sysConf;\n\n function setUp() public virtual override {\n super.setUp();\n\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n\n sysConf = new SystemConfig({\n _owner: alice,\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(1),\n _config: config\n });\n }\n}\n\ncontract SystemConfig_Initialize_TestFail is SystemConfig_Init {\n function test_initialize_lowGasLimit_reverts() external {\n uint64 minimumGasLimit = sysConf.minimumGasLimit();\n\n ResourceMetering.ResourceConfig memory cfg = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n\n vm.expectRevert(\"SystemConfig: gas limit too low\");\n new SystemConfig({\n _owner: alice,\n _overhead: 0,\n _scalar: 0,\n _batcherHash: bytes32(hex\"\"),\n _gasLimit: minimumGasLimit - 1,\n _unsafeBlockSigner: address(1),\n _config: cfg\n });\n }\n}\n\ncontract SystemConfig_Setters_TestFail is SystemConfig_Init {\n function test_setBatcherHash_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setBatcherHash(bytes32(hex\"\"));\n }\n\n function test_setGasConfig_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasConfig(0, 0);\n }\n\n function test_setGasLimit_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasLimit(0);\n }\n\n function test_setUnsafeBlockSigner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setUnsafeBlockSigner(address(0x20));\n }\n\n function test_setResourceConfig_notOwner_reverts() external {\n ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_badMinMax_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 2 gwei,\n maximumBaseFee: 1 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: min base fee must be less than max base\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_zeroDenominator_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 0,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: denominator must be larger than 1\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_lowGasLimit_reverts() external {\n uint64 gasLimit = sysConf.gasLimit();\n\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: uint32(gasLimit),\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: uint32(gasLimit),\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: gas limit too low\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_badPrecision_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 11,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: precision loss with target resource limit\");\n sysConf.setResourceConfig(config);\n }\n}\n\ncontract SystemConfig_Setters_Test is SystemConfig_Init {\n event ConfigUpdate(\n uint256 indexed version,\n SystemConfig.UpdateType indexed updateType,\n bytes data\n );\n\n function testFuzz_setBatcherHash_succeeds(bytes32 newBatcherHash) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash));\n\n vm.prank(sysConf.owner());\n sysConf.setBatcherHash(newBatcherHash);\n assertEq(sysConf.batcherHash(), newBatcherHash);\n }\n\n function testFuzz_setGasConfig_succeeds(uint256 newOverhead, uint256 newScalar) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.GAS_CONFIG,\n abi.encode(newOverhead, newScalar)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setGasConfig(newOverhead, newScalar);\n assertEq(sysConf.overhead(), newOverhead);\n assertEq(sysConf.scalar(), newScalar);\n }\n\n function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external {\n uint64 minimumGasLimit = sysConf.minimumGasLimit();\n newGasLimit = uint64(\n bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(type(uint64).max))\n );\n\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit));\n\n vm.prank(sysConf.owner());\n sysConf.setGasLimit(newGasLimit);\n assertEq(sysConf.gasLimit(), newGasLimit);\n }\n\n function testFuzz_setUnsafeBlockSigner_succeeds(address newUnsafeSigner) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER,\n abi.encode(newUnsafeSigner)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setUnsafeBlockSigner(newUnsafeSigner);\n assertEq(sysConf.unsafeBlockSigner(), newUnsafeSigner);\n }\n}\n" - }, - "contracts/test/TransferOnion.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { TransferOnion } from \"../periphery/TransferOnion.sol\";\n\n/**\n * @title TransferOnionTest\n * @notice Test coverage of TransferOnion\n */\ncontract TransferOnionTest is Test {\n /**\n * @notice TransferOnion\n */\n TransferOnion internal onion;\n\n /**\n * @notice token constructor arg\n */\n address internal _token;\n\n /**\n * @notice sender constructor arg\n */\n address internal _sender;\n\n /**\n * @notice Sets up addresses, deploys contracts and funds the owner.\n */\n function setUp() public {\n ERC20 token = new ERC20(\"Token\", \"TKN\");\n _token = address(token);\n _sender = makeAddr(\"sender\");\n }\n\n /**\n * @notice Deploy the TransferOnion with a dummy shell\n */\n function _deploy() public {\n _deploy(bytes32(0));\n }\n\n /**\n * @notice Deploy the TransferOnion with a specific shell\n */\n function _deploy(bytes32 _shell) public {\n onion = new TransferOnion({ _token: ERC20(_token), _sender: _sender, _shell: _shell });\n }\n\n /**\n * @notice Build the onion data\n */\n function _onionize(TransferOnion.Layer[] memory _layers)\n public\n pure\n returns (bytes32, TransferOnion.Layer[] memory)\n {\n uint256 length = _layers.length;\n bytes32 hash = bytes32(0);\n for (uint256 i; i < length; i++) {\n TransferOnion.Layer memory layer = _layers[i];\n _layers[i].shell = hash;\n hash = keccak256(abi.encode(layer.recipient, layer.amount, hash));\n }\n return (hash, _layers);\n }\n\n /**\n * @notice The constructor sets the variables as expected\n */\n function test_constructor_succeeds() external {\n _deploy();\n\n assertEq(address(onion.TOKEN()), _token);\n assertEq(onion.SENDER(), _sender);\n assertEq(onion.shell(), bytes32(0));\n }\n\n /**\n * @notice unwrap\n */\n function test_unwrap_succeeds() external {\n // Commit to transferring tiny amounts of tokens\n TransferOnion.Layer[] memory _layers = new TransferOnion.Layer[](2);\n _layers[0] = TransferOnion.Layer(address(1), 1, bytes32(0));\n _layers[1] = TransferOnion.Layer(address(2), 2, bytes32(0));\n\n // Build the onion shell\n (bytes32 shell, TransferOnion.Layer[] memory layers) = _onionize(_layers);\n _deploy(shell);\n\n assertEq(onion.shell(), shell);\n\n address token = address(onion.TOKEN());\n address sender = onion.SENDER();\n\n // give 3 units of token to sender\n deal(token, onion.SENDER(), 3);\n vm.prank(sender);\n ERC20(token).approve(address(onion), 3);\n\n // To build the inputs, to `peel`, need to reverse the list\n TransferOnion.Layer[] memory inputs = new TransferOnion.Layer[](2);\n int256 length = int256(layers.length);\n for (int256 i = length - 1; i >= 0; i--) {\n uint256 ui = uint256(i);\n uint256 revidx = uint256(length) - ui - 1;\n TransferOnion.Layer memory layer = layers[ui];\n inputs[revidx] = layer;\n }\n\n // The accounts have no balance\n assertEq(ERC20(_token).balanceOf(address(1)), 0);\n assertEq(ERC20(_token).balanceOf(address(2)), 0);\n\n onion.peel(inputs);\n\n // Now the accounts have the expected balance\n assertEq(ERC20(_token).balanceOf(address(1)), 1);\n assertEq(ERC20(_token).balanceOf(address(2)), 2);\n }\n}\n" - }, - "contracts/test/invariants/CrossDomainMessenger.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { StdUtils } from \"forge-std/StdUtils.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport { OptimismPortal } from \"../../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../../L1/L1CrossDomainMessenger.sol\";\nimport { Messenger_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\nimport { Predeploys } from \"../../libraries/Predeploys.sol\";\nimport { Constants } from \"../../libraries/Constants.sol\";\nimport { Encoding } from \"../../libraries/Encoding.sol\";\nimport { Hashing } from \"../../libraries/Hashing.sol\";\n\ncontract RelayActor is StdUtils {\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n uint256 public numHashes;\n bytes32[] public hashes;\n bool public reverted = false;\n\n OptimismPortal op;\n L1CrossDomainMessenger xdm;\n Vm vm;\n bool doFail;\n\n constructor(\n OptimismPortal _op,\n L1CrossDomainMessenger _xdm,\n Vm _vm,\n bool _doFail\n ) {\n op = _op;\n xdm = _xdm;\n vm = _vm;\n doFail = _doFail;\n }\n\n /**\n * Relays a message to the `L1CrossDomainMessenger` with a random `version`, and `_message`.\n */\n function relay(\n uint8 _version,\n uint8 _value,\n bytes memory _message\n ) external {\n address target = address(0x04); // ID precompile\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Set the minimum gas limit to the cost of the identity precompile's execution for\n // the given message.\n // ID Precompile cost can be determined by calculating: 15 + 3 * data_word_length\n uint32 minGasLimit = uint32(15 + 3 * ((_message.length + 31) / 32));\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Restrict version to the range of [0, 1]\n _version = _version % 2;\n\n // Restrict the value to the range of [0, 1]\n // This is just so we get variance of calls with and without value. The ID precompile\n // will not reject value being sent to it.\n _value = _value % 2;\n\n // If the message should succeed, supply it `baseGas`. If not, supply it an amount of\n // gas that is too low to complete the call.\n uint256 gas = doFail\n ? bound(minGasLimit, 60_000, 80_000)\n : xdm.baseGas(_message, minGasLimit);\n\n // Compute the cross domain message hash and store it in `hashes`.\n // The `relayMessage` function will always encode the message as a version 1\n // message after checking that the V0 hash has not already been relayed.\n bytes32 _hash = Hashing.hashCrossDomainMessageV1(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n _value,\n minGasLimit,\n _message\n );\n hashes.push(_hash);\n numHashes += 1;\n\n // Make sure we've got a fresh message.\n vm.assume(xdm.successfulMessages(_hash) == false && xdm.failedMessages(_hash) == false);\n\n // Act as the optimism portal and call `relayMessage` on the `L1CrossDomainMessenger` with\n // the outer min gas limit.\n vm.startPrank(address(op));\n if (!doFail) {\n vm.expectCallMinGas(address(0x04), _value, minGasLimit, _message);\n }\n try\n xdm.relayMessage{ gas: gas, value: _value }(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n _value,\n minGasLimit,\n _message\n )\n {} catch {\n // If any of these calls revert, set `reverted` to true to fail the invariant test.\n // NOTE: This is to get around forge's invariant fuzzer ignoring reverted calls\n // to this function.\n reverted = true;\n }\n vm.stopPrank();\n }\n}\n\ncontract XDM_MinGasLimits is Messenger_Initializer {\n RelayActor actor;\n\n function init(bool doFail) public virtual {\n // Set up the `L1CrossDomainMessenger` and `OptimismPortal` contracts.\n super.setUp();\n\n // Deploy a relay actor\n actor = new RelayActor(op, L1Messenger, vm, doFail);\n\n // Give the portal some ether to send to `relayMessage`\n vm.deal(address(op), type(uint128).max);\n\n // Target the `RelayActor` contract\n targetContract(address(actor));\n\n // Don't allow the estimation address to be the sender\n excludeSender(Constants.ESTIMATION_ADDRESS);\n\n // Target the actor's `relay` function\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = actor.relay.selector;\n targetSelector(FuzzSelector({ addr: address(actor), selectors: selectors }));\n }\n}\n\ncontract XDM_MinGasLimits_Succeeds is XDM_MinGasLimits {\n function setUp() public override {\n // Don't fail\n super.init(false);\n }\n\n /**\n * @custom:invariant A call to `relayMessage` should succeed if at least the minimum gas limit\n * can be supplied to the target context, there is enough gas to complete\n * execution of `relayMessage` after the target context's execution is\n * finished, and the target context did not revert.\n *\n * There are two minimum gas limits here:\n *\n * - The outer min gas limit is for the call from the `OptimismPortal` to the\n * `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function\n * with the `message` and inner limit.\n *\n * - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target\n * contract.\n */\n function invariant_minGasLimits() external {\n uint256 length = actor.numHashes();\n for (uint256 i = 0; i < length; ++i) {\n bytes32 hash = actor.hashes(i);\n // The message hash is set in the successfulMessages mapping\n assertTrue(L1Messenger.successfulMessages(hash));\n // The message hash is not set in the failedMessages mapping\n assertFalse(L1Messenger.failedMessages(hash));\n }\n assertFalse(actor.reverted());\n }\n}\n\ncontract XDM_MinGasLimits_Reverts is XDM_MinGasLimits {\n function setUp() public override {\n // Do fail\n super.init(true);\n }\n\n /**\n * @custom:invariant A call to `relayMessage` should assign the message hash to the\n * `failedMessages` mapping if not enough gas is supplied to forward\n * `minGasLimit` to the target context or if there is not enough gas to\n * complete execution of `relayMessage` after the target context's execution\n * is finished.\n *\n * There are two minimum gas limits here:\n *\n * - The outer min gas limit is for the call from the `OptimismPortal` to the\n * `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function\n * with the `message` and inner limit.\n *\n * - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target\n * contract.\n */\n function invariant_minGasLimits() external {\n uint256 length = actor.numHashes();\n for (uint256 i = 0; i < length; ++i) {\n bytes32 hash = actor.hashes(i);\n // The message hash is not set in the successfulMessages mapping\n assertFalse(L1Messenger.successfulMessages(hash));\n // The message hash is set in the failedMessages mapping\n assertTrue(L1Messenger.failedMessages(hash));\n }\n assertFalse(actor.reverted());\n }\n}\n" - }, - "contracts/test/invariants/L2OutputOracle.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { L2OutputOracle_Initializer } from \"../CommonTest.t.sol\";\nimport { L2OutputOracle } from \"../../L1/L2OutputOracle.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\n\ncontract L2OutputOracle_Proposer {\n L2OutputOracle internal oracle;\n Vm internal vm;\n\n constructor(L2OutputOracle _oracle, Vm _vm) {\n oracle = _oracle;\n vm = _vm;\n }\n\n /**\n * @dev Allows the actor to propose an L2 output to the `L2OutputOracle`\n */\n function proposeL2Output(\n bytes32 _outputRoot,\n uint256 _l2BlockNumber,\n bytes32 _l1BlockHash,\n uint256 _l1BlockNumber\n ) external {\n // Act as the proposer and propose a new output.\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _l2BlockNumber, _l1BlockHash, _l1BlockNumber);\n }\n}\n\ncontract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_Initializer {\n L2OutputOracle_Proposer internal actor;\n\n function setUp() public override {\n super.setUp();\n\n // Create a proposer actor.\n actor = new L2OutputOracle_Proposer(oracle, vm);\n\n // Set the target contract to the proposer actor.\n targetContract(address(actor));\n\n // Set the target selector for `proposeL2Output`\n // `proposeL2Output` is the only function we care about, as it is the only function\n // that can modify the `l2Outputs` array in the oracle.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = actor.proposeL2Output.selector;\n FuzzSelector memory selector = FuzzSelector({ addr: address(actor), selectors: selectors });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The block number of the output root proposals should monotonically\n * increase.\n *\n * When a new output is submitted, it should never be allowed to correspond to a block\n * number that is less than the current output.\n */\n function invariant_monotonicBlockNumIncrease() external {\n // Assert that the block number of proposals must monotonically increase.\n assertTrue(oracle.nextBlockNumber() >= oracle.latestBlockNumber());\n }\n}\n" - }, - "contracts/test/invariants/OptimismPortal.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Portal_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\n\ncontract OptimismPortal_Invariant_Harness is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n function setUp() public virtual override {\n super.setUp();\n\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n}\n\ncontract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the finalization\n * period has not elapsed.\n *\n * A withdrawal that has been proven should not be able to be finalized until after\n * the finalization period has elapsed.\n */\n function invariant_cannotFinalizeBeforePeriodHasPassed() external {\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Finalize the withdrawal transaction.\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal\n * has already been finalized.\n *\n * Ensures that there is no chain of calls that can be made that allows a withdrawal\n * to be finalized twice.\n */\n function invariant_cannotFinalizeTwice() external {\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant A withdrawal should **always** be able to be finalized\n * `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.\n *\n * This invariant asserts that there is no chain of calls that can be made that\n * will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS`\n * after it was successfully proven.\n */\n function invariant_canAlwaysFinalize() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assertEq(address(bob).balance, bobBalanceBefore + _defaultTx.value);\n }\n}\n" - }, - "contracts/test/invariants/SafeCall.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { StdUtils } from \"forge-std/StdUtils.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport { SafeCall } from \"../../libraries/SafeCall.sol\";\n\ncontract SafeCall_Succeeds_Invariants is Test {\n SafeCaller_Actor actor;\n\n function setUp() public {\n // Create a new safe caller actor.\n actor = new SafeCaller_Actor(vm, false);\n\n // Set the caller to this contract\n targetSender(address(this));\n\n // Target the safe caller actor.\n targetContract(address(actor));\n\n // Give the actor some ETH to work with\n vm.deal(address(actor), type(uint128).max);\n }\n\n /**\n * @custom:invariant If `callWithMinGas` performs a call, then it must always\n * provide at least the specified minimum gas limit to the subcontext.\n *\n * If the check for remaining gas in `SafeCall.callWithMinGas` passes, the\n * subcontext of the call below it must be provided at least `minGas` gas.\n */\n function invariant_callWithMinGas_alwaysForwardsMinGas_succeeds() public {\n assertEq(actor.numCalls(), 0, \"no failed calls allowed\");\n }\n\n function performSafeCallMinGas(address to, uint64 minGas) external payable {\n SafeCall.callWithMinGas(to, minGas, msg.value, hex\"\");\n }\n}\n\ncontract SafeCall_Fails_Invariants is Test {\n SafeCaller_Actor actor;\n\n function setUp() public {\n // Create a new safe caller actor.\n actor = new SafeCaller_Actor(vm, true);\n\n // Set the caller to this contract\n targetSender(address(this));\n\n // Target the safe caller actor.\n targetContract(address(actor));\n\n // Give the actor some ETH to work with\n vm.deal(address(actor), type(uint128).max);\n }\n\n /**\n * @custom:invariant `callWithMinGas` reverts if there is not enough gas to pass\n * to the subcontext.\n *\n * If there is not enough gas in the callframe to ensure that `callWithMinGas`\n * can provide the specified minimum gas limit to the subcontext of the call,\n * then `callWithMinGas` must revert.\n */\n function invariant_callWithMinGas_neverForwardsMinGas_reverts() public {\n assertEq(actor.numCalls(), 0, \"no successful calls allowed\");\n }\n\n function performSafeCallMinGas(address to, uint64 minGas) external payable {\n SafeCall.callWithMinGas(to, minGas, msg.value, hex\"\");\n }\n}\n\ncontract SafeCaller_Actor is StdUtils {\n bool internal immutable FAILS;\n\n Vm internal vm;\n uint256 public numCalls;\n\n constructor(Vm _vm, bool _fails) {\n vm = _vm;\n FAILS = _fails;\n }\n\n function performSafeCallMinGas(\n uint64 gas,\n uint64 minGas,\n address to,\n uint8 value\n ) external {\n // Only send to EOAs - we exclude the console as it has no code but reverts when called\n // with a selector that doesn't exist due to the foundry hook.\n vm.assume(to.code.length == 0 && to != 0x000000000000000000636F6e736F6c652e6c6f67);\n\n // Bound the minimum gas amount to [2500, type(uint48).max]\n minGas = uint64(bound(minGas, 2500, type(uint48).max));\n if (FAILS) {\n // Bound the gas passed to [minGas, ((minGas * 64) / 63)]\n gas = uint64(bound(gas, minGas, (minGas * 64) / 63));\n } else {\n // Bound the gas passed to\n // [((minGas * 64) / 63) + 40_000 + 1000, type(uint64).max]\n // The extra 1000 gas is to account for the gas used by the `SafeCall.call` call\n // itself.\n gas = uint64(bound(gas, ((minGas * 64) / 63) + 40_000 + 1000, type(uint64).max));\n }\n\n vm.expectCallMinGas(to, value, minGas, hex\"\");\n bool success = SafeCall.call(\n msg.sender,\n gas,\n value,\n abi.encodeWithSelector(\n SafeCall_Succeeds_Invariants.performSafeCallMinGas.selector,\n to,\n minGas\n )\n );\n\n if (success && FAILS) numCalls++;\n if (!FAILS && !success) numCalls++;\n }\n}\n" - }, - "contracts/test/invariants/SystemConfig.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { SystemConfig } from \"../../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../../L1/ResourceMetering.sol\";\nimport { Constants } from \"../../libraries/Constants.sol\";\n\ncontract SystemConfig_GasLimitLowerBound_Invariant is Test {\n SystemConfig public config;\n\n function setUp() public {\n ResourceMetering.ResourceConfig memory cfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n config = new SystemConfig({\n _owner: address(0xbeef),\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(1),\n _config: cfg\n });\n\n // Set the target contract to the `config`\n targetContract(address(config));\n // Set the target sender to the `config`'s owner (0xbeef)\n targetSender(address(0xbeef));\n // Set the target selector for `setGasLimit`\n // `setGasLimit` is the only function we care about, as it is the only function\n // that can modify the gas limit within the SystemConfig.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = config.setGasLimit.selector;\n FuzzSelector memory selector = FuzzSelector({\n addr: address(config),\n selectors: selectors\n });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The gas limit of the `SystemConfig` contract can never be lower\n * than the hard-coded lower bound.\n */\n function invariant_gasLimitLowerBound() external {\n assertTrue(config.gasLimit() >= config.minimumGasLimit());\n }\n}\n" - }, - "contracts/universal/CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\n/**\n * @custom:legacy\n * @title CrossDomainMessengerLegacySpacer0\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 CrossDomainMessengerLegacySpacer0 {\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:legacy\n * @title CrossDomainMessengerLegacySpacer1\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\n * PausableUpgradable and OwnableUpgradeable variables used to exist. Must be\n * the third contract in the inheritance tree of the CrossDomainMessenger.\n */\ncontract CrossDomainMessengerLegacySpacer1 {\n /**\n * @custom:legacy\n * @custom:spacer ContextUpgradable's __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * ContextUpgradable.\n *\n */\n uint256[50] private spacer_1_0_1600;\n\n /**\n * @custom:legacy\n * @custom:spacer OwnableUpgradeable's _owner\n * @notice Spacer for backwards compatibility.\n * Come from OpenZeppelin OwnableUpgradeable.\n */\n address private spacer_51_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer OwnableUpgradeable's __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * OwnableUpgradeable.\n */\n uint256[49] private spacer_52_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer PausableUpgradable's _paused\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n bool private spacer_101_0_1;\n\n /**\n * @custom:legacy\n * @custom:spacer PausableUpgradable's __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n uint256[49] private spacer_102_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer ReentrancyGuardUpgradeable's `_status` field.\n * @notice Spacer for backwards compatibility.\n */\n uint256 private spacer_151_0_32;\n\n /**\n * @custom:legacy\n * @custom:spacer ReentrancyGuardUpgradeable's __gap\n * @notice Spacer for backwards compatibility.\n */\n uint256[49] private spacer_152_0_1568;\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/**\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 *\n * Any changes to this contract MUST result in a semver bump for contracts that inherit it.\n */\nabstract contract CrossDomainMessenger is\n CrossDomainMessengerLegacySpacer0,\n Initializable,\n CrossDomainMessengerLegacySpacer1\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 uint64 public constant RELAY_CONSTANT_OVERHEAD = 200_000;\n\n /**\n * @notice Numerator for dynamic overhead added to the base gas for a message.\n */\n uint64 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 64;\n\n /**\n * @notice Denominator for dynamic overhead added to the base gas for a message.\n */\n uint64 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 63;\n\n /**\n * @notice Extra gas added to base gas for each byte of calldata in a message.\n */\n uint64 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\n\n /**\n * @notice Gas reserved for performing the external call in `relayMessage`.\n */\n uint64 public constant RELAY_CALL_OVERHEAD = 40_000;\n\n /**\n * @notice Gas reserved for finalizing the execution of `relayMessage` after the safe call.\n */\n uint64 public constant RELAY_RESERVED_GAS = 40_000;\n\n /**\n * @notice Gas reserved for the execution between the `hasMinGas` check and the external\n * call in `relayMessage`.\n */\n uint64 public constant RELAY_GAS_CHECK_BUFFER = 5_000;\n\n /**\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\n */\n address public immutable OTHER_MESSENGER;\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 a boolean if and only if the message has failed to be\n * executed at least once. A message will not be present in this mapping if it\n * successfully executed on the first attempt.\n */\n mapping(bytes32 => bool) public failedMessages;\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 OTHER_MESSENGER = _otherMessenger;\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 OTHER_MESSENGER,\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 {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n require(\n version < 2,\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // If the message is version 0, then it's a migrated legacy withdrawal. We therefore need\n // to check that the legacy version of the message has not already been relayed.\n if (version == 0) {\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _nonce);\n require(\n successfulMessages[oldHash] == false,\n \"CrossDomainMessenger: legacy withdrawal already relayed\"\n );\n }\n\n // We use the v1 message hash as the unique identifier for the message because it commits\n // to the value and minimum gas limit of the message.\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _minGasLimit,\n _message\n );\n\n if (_isOtherMessenger()) {\n // These properties should always hold when the message is first submitted (as\n // opposed to being replayed).\n assert(msg.value == _value);\n assert(!failedMessages[versionedHash]);\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 failedMessages[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 // If there is not enough gas left to perform the external call and finish the execution,\n // return early and assign the message to the failedMessages mapping.\n // We are asserting that we have enough gas to:\n // 1. Call the target contract (_minGasLimit + RELAY_CALL_OVERHEAD + RELAY_GAS_CHECK_BUFFER)\n // 1.a. The RELAY_CALL_OVERHEAD is included in `hasMinGas`.\n // 2. Finish the execution after the external call (RELAY_RESERVED_GAS).\n //\n // If `xDomainMsgSender` is not the default L2 sender, this function\n // is being re-entered. This marks the message as failed to allow it to be replayed.\n if (\n !SafeCall.hasMinGas(_minGasLimit, RELAY_RESERVED_GAS + RELAY_GAS_CHECK_BUFFER) ||\n xDomainMsgSender != Constants.DEFAULT_L2_SENDER\n ) {\n failedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n\n // Revert in this case if the transaction was triggered by the estimation address. This\n // should only be possible during gas estimation or we have bigger problems. Reverting\n // here will make the behavior of gas estimation change such that the gas limit\n // computed will be the amount required to relay the message, even if that amount is\n // greater than the minimum gas limit specified by the user.\n if (tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"CrossDomainMessenger: failed to relay message\");\n }\n\n return;\n }\n\n xDomainMsgSender = _sender;\n bool success = SafeCall.call(_target, gasleft() - RELAY_RESERVED_GAS, _value, _message);\n xDomainMsgSender = Constants.DEFAULT_L2_SENDER;\n\n if (success) {\n successfulMessages[versionedHash] = true;\n emit RelayedMessage(versionedHash);\n } else {\n failedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n\n // Revert in this case if the transaction was triggered by the estimation address. This\n // should only be possible during gas estimation or we have bigger problems. Reverting\n // here will make the behavior of gas estimation change such that the gas limit\n // computed will be the amount required to relay the message, even if that amount is\n // greater than the minimum gas limit specified by the user.\n if (tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"CrossDomainMessenger: failed to relay message\");\n }\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 != Constants.DEFAULT_L2_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 (uint64) {\n return\n // Constant overhead\n RELAY_CONSTANT_OVERHEAD +\n // Calldata overhead\n (uint64(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +\n // Dynamic overhead (EIP-150)\n ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n // Gas reserved for the worst-case cost of 3/5 of the `CALL` opcode's dynamic gas\n // factors. (Conservative)\n RELAY_CALL_OVERHEAD +\n // Relay reserved gas (to ensure execution of `relayMessage` completes after the\n // subcontext finishes executing) (Conservative)\n RELAY_RESERVED_GAS +\n // Gas reserved for the execution between the `hasMinGas` check and the `CALL`\n // opcode. (Conservative)\n RELAY_GAS_CHECK_BUFFER;\n }\n\n /**\n * @notice Intializer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __CrossDomainMessenger_init() internal onlyInitializing {\n xDomainMsgSender = Constants.DEFAULT_L2_SENDER;\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" - }, - "contracts/universal/ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CrossDomainMessenger } from \"./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 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 OTHER_BRIDGE;\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 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 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() == OTHER_BRIDGE,\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 OTHER_BRIDGE = _otherBridge;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for other bridge address.\n *\n * @return Address of the bridge on the other network.\n */\n function otherBridge() external view returns (address) {\n return OTHER_BRIDGE;\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" - }, - "contracts/universal/FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n/**\n * @title FeeVault\n * @notice The FeeVault contract contains the basic logic for the various different vault contracts\n * used to hold fee revenue generated by the L2 system.\n */\nabstract contract FeeVault {\n /**\n * @notice Emits each time that a withdrawal occurs.\n *\n * @param value Amount that was withdrawn (in wei).\n * @param to Address that the funds were sent to.\n * @param from Address that triggered the withdrawal.\n */\n event Withdrawal(uint256 value, address to, address from);\n\n /**\n * @notice Minimum balance before a withdrawal can be triggered.\n */\n uint256 public immutable MIN_WITHDRAWAL_AMOUNT;\n\n /**\n * @notice Wallet that will receive the fees on L1.\n */\n address public immutable RECIPIENT;\n\n /**\n * @notice The minimum gas limit for the FeeVault withdrawal transaction.\n */\n uint32 internal constant WITHDRAWAL_MIN_GAS = 35_000;\n\n /**\n * @notice Total amount of wei processed by the contract.\n */\n uint256 public totalProcessed;\n\n /**\n * @param _recipient Wallet that will receive the fees on L1.\n * @param _minWithdrawalAmount Minimum balance before a withdrawal can be triggered.\n */\n constructor(address _recipient, uint256 _minWithdrawalAmount) {\n MIN_WITHDRAWAL_AMOUNT = _minWithdrawalAmount;\n RECIPIENT = _recipient;\n }\n\n /**\n * @notice Allow the contract to receive ETH.\n */\n receive() external payable {}\n\n /**\n * @notice Triggers a withdrawal of funds to the L1 fee wallet.\n */\n function withdraw() external {\n require(\n address(this).balance >= MIN_WITHDRAWAL_AMOUNT,\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n\n uint256 value = address(this).balance;\n totalProcessed += value;\n\n emit Withdrawal(value, RECIPIENT, msg.sender);\n\n L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)).bridgeETHTo{ value: value }(\n RECIPIENT,\n WITHDRAWAL_MIN_GAS,\n bytes(\"\")\n );\n }\n}\n" - }, - "contracts/universal/IOptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\n/**\n * @title IOptimismMintableERC20\n * @notice This interface is available on the OptimismMintableERC20 contract. We declare it as a\n * separate interface so that it can be used in custom implementations of\n * OptimismMintableERC20.\n */\ninterface IOptimismMintableERC20 is IERC165 {\n function remoteToken() external view returns (address);\n\n function bridge() external returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n\n/**\n * @custom:legacy\n * @title ILegacyMintableERC20\n * @notice This interface was available on the legacy L2StandardERC20 contract. It remains available\n * on the OptimismMintableERC20 contract for backwards compatibility.\n */\ninterface ILegacyMintableERC20 is IERC165 {\n function l1Token() external view returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n" - }, - "contracts/universal/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 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 /**\n * @notice Chain ID of the chain where the remote token is deployed.\n */\n function REMOTE_CHAIN_ID() external view returns (uint256);\n\n /**\n * @notice Address of the token on the remote domain.\n */\n function REMOTE_TOKEN() 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 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" - }, - "contracts/universal/OptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { ILegacyMintableERC20, IOptimismMintableERC20 } from \"./IOptimismMintableERC20.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @title OptimismMintableERC20\n * @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed\n * to allow the StandardBridge contracts to mint and burn tokens. This makes it possible to\n * use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa.\n * Designed to be backwards compatible with the older StandardL2ERC20 token which was only\n * meant for use on L2.\n */\ncontract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, Semver {\n /**\n * @notice Address of the corresponding version of this token on the remote chain.\n */\n address public immutable REMOTE_TOKEN;\n\n /**\n * @notice Address of the StandardBridge on this network.\n */\n address public immutable BRIDGE;\n\n /**\n * @notice Emitted whenever tokens are minted for an account.\n *\n * @param account Address of the account tokens are being minted for.\n * @param amount Amount of tokens minted.\n */\n event Mint(address indexed account, uint256 amount);\n\n /**\n * @notice Emitted whenever tokens are burned from an account.\n *\n * @param account Address of the account tokens are being burned from.\n * @param amount Amount of tokens burned.\n */\n event Burn(address indexed account, uint256 amount);\n\n /**\n * @notice A modifier that only allows the bridge to call\n */\n modifier onlyBridge() {\n require(msg.sender == BRIDGE, \"OptimismMintableERC20: only bridge can mint and burn\");\n _;\n }\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _bridge Address of the L2 standard bridge.\n * @param _remoteToken Address of the corresponding L1 token.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n */\n constructor(\n address _bridge,\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) Semver(1, 0, 0) {\n REMOTE_TOKEN = _remoteToken;\n BRIDGE = _bridge;\n }\n\n /**\n * @notice Allows the StandardBridge on this network to mint tokens.\n *\n * @param _to Address to mint tokens to.\n * @param _amount Amount of tokens to mint.\n */\n function mint(address _to, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _mint(_to, _amount);\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Allows the StandardBridge on this network to burn tokens.\n *\n * @param _from Address to burn tokens from.\n * @param _amount Amount of tokens to burn.\n */\n function burn(address _from, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _burn(_from, _amount);\n emit Burn(_from, _amount);\n }\n\n /**\n * @notice ERC165 interface check function.\n *\n * @param _interfaceId Interface ID to check.\n *\n * @return Whether or not the interface is supported by this contract.\n */\n function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {\n bytes4 iface1 = type(IERC165).interfaceId;\n // Interface corresponding to the legacy L2StandardERC20.\n bytes4 iface2 = type(ILegacyMintableERC20).interfaceId;\n // Interface corresponding to the updated OptimismMintableERC20 (this contract).\n bytes4 iface3 = type(IOptimismMintableERC20).interfaceId;\n return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward.\n */\n function l1Token() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the bridge. Use BRIDGE going forward.\n */\n function l2Bridge() public view returns (address) {\n return BRIDGE;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for REMOTE_TOKEN.\n */\n function remoteToken() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for BRIDGE.\n */\n function bridge() public view returns (address) {\n return BRIDGE;\n }\n}\n" - }, - "contracts/universal/OptimismMintableERC20Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Contract Imports */\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { Semver } from \"./Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000012\n * @title OptimismMintableERC20Factory\n * @notice OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20\n * contracts on the network it's deployed to. Simplifies the deployment process for users\n * who may be less familiar with deploying smart contracts. Designed to be backwards\n * compatible with the older StandardL2ERC20Factory contract.\n */\ncontract OptimismMintableERC20Factory is Semver {\n /**\n * @notice Address of the StandardBridge on this chain.\n */\n address public immutable BRIDGE;\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer\n * OptimismMintableERC20Created event. We recommend relying on that event instead.\n *\n * @param remoteToken Address of the token on the remote chain.\n * @param localToken Address of the created token on the local chain.\n */\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n\n /**\n * @notice Emitted whenever a new OptimismMintableERC20 is created.\n *\n * @param localToken Address of the created token on the local chain.\n * @param remoteToken Address of the corresponding token on the remote chain.\n * @param deployer Address of the account that deployed the token.\n */\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @notice The semver MUST be bumped any time that there is a change in\n * the OptimismMintableERC20 token contract since this contract\n * is responsible for deploying OptimismMintableERC20 contracts.\n *\n * @param _bridge Address of the StandardBridge on this chain.\n */\n constructor(address _bridge) Semver(1, 1, 0) {\n BRIDGE = _bridge;\n }\n\n /**\n * @custom:legacy\n * @notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the\n * newer createOptimismMintableERC20 function, which has a more intuitive name.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createStandardL2Token(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) external returns (address) {\n return createOptimismMintableERC20(_remoteToken, _name, _symbol);\n }\n\n /**\n * @notice Creates an instance of the OptimismMintableERC20 contract.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createOptimismMintableERC20(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) public returns (address) {\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC20Factory: must provide remote token address\"\n );\n\n address localToken = address(\n new OptimismMintableERC20(BRIDGE, _remoteToken, _name, _symbol)\n );\n\n // Emit the old event too for legacy support.\n emit StandardL2TokenCreated(_remoteToken, localToken);\n\n // Emit the updated event. The arguments here differ from the legacy event, but\n // are consistent with the ordering used in StandardBridge events.\n emit OptimismMintableERC20Created(localToken, _remoteToken, msg.sender);\n\n return localToken;\n }\n}\n" - }, - "contracts/universal/OptimismMintableERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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\";\nimport { Semver } from \"../universal/Semver.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, Semver {\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n uint256 public immutable REMOTE_CHAIN_ID;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable REMOTE_TOKEN;\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 * @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 * @custom:semver 1.1.0\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) Semver(1, 1, 0) {\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 REMOTE_CHAIN_ID = _remoteChainId;\n REMOTE_TOKEN = _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 * @inheritdoc IOptimismMintableERC721\n */\n function remoteChainId() external view returns (uint256) {\n return REMOTE_CHAIN_ID;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function remoteToken() external view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function bridge() external view returns (address) {\n return BRIDGE;\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 iface = type(IOptimismMintableERC721).interfaceId;\n return _interfaceId == iface || 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" - }, - "contracts/universal/OptimismMintableERC721Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\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 {\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 REMOTE_CHAIN_ID;\n\n /**\n * @notice Tracks addresses created by this factory.\n */\n mapping(address => bool) public isOptimismMintableERC721;\n\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 * @custom:semver 1.2.0\n * @notice The semver MUST be bumped any time that there is a change in\n * the OptimismMintableERC721 token contract since this contract\n * is responsible for deploying OptimismMintableERC721 contracts.\n *\n * @param _bridge Address of the ERC721 bridge on this network.\n * @param _remoteChainId Chain ID for the remote network.\n */\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 2, 0) {\n BRIDGE = _bridge;\n REMOTE_CHAIN_ID = _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, REMOTE_CHAIN_ID, _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/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) public virtual 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 public\n payable\n virtual\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) public virtual 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() public virtual proxyCallIfNotAdmin returns (address) {\n return _getAdmin();\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function implementation() public virtual 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" - }, - "contracts/universal/ProxyAdmin.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.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 Ownable {\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 * @notice A mapping of proxy types, used for backwards compatibility.\n */\n mapping(address => ProxyType) public proxyType;\n\n /**\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 * @notice The address of the address manager, this is required to manage the\n * ResolvedDelegateProxy type.\n */\n AddressManager public addressManager;\n\n /**\n * @notice A legacy upgrading indicator used by the old Chugsplash Proxy.\n */\n bool internal upgrading;\n\n /**\n * @param _owner Address of the initial owner of this contract.\n */\n constructor(address _owner) Ownable() {\n _transferOwnership(_owner);\n }\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 * @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 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.\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 /**\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" - }, - "contracts/universal/Semver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 uint256 private immutable MAJOR_VERSION;\n\n /**\n * @notice Contract version number (minor).\n */\n uint256 private immutable MINOR_VERSION;\n\n /**\n * @notice Contract version number (patch).\n */\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" - }, - "contracts/universal/StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { IOptimismMintableERC20, ILegacyMintableERC20 } from \"./IOptimismMintableERC20.sol\";\nimport { CrossDomainMessenger } from \"./CrossDomainMessenger.sol\";\nimport { OptimismMintableERC20 } from \"./OptimismMintableERC20.sol\";\n\n/**\n * @custom:upgradeable\n * @title StandardBridge\n * @notice StandardBridge is a base contract for the L1 and L2 standard ERC20 bridges. It handles\n * the core bridging logic, including escrowing tokens that are native to the local chain\n * and minting/burning tokens that are native to the remote chain.\n */\nabstract contract StandardBridge {\n using SafeERC20 for IERC20;\n\n /**\n * @notice The L2 gas limit set when eth is depoisited using the receive() function.\n */\n uint32 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 200_000;\n\n /**\n * @notice Messenger contract on this domain.\n */\n CrossDomainMessenger public immutable MESSENGER;\n\n /**\n * @notice Corresponding bridge on the other domain.\n */\n StandardBridge public immutable OTHER_BRIDGE;\n\n /**\n * @custom:legacy\n * @custom:spacer messenger\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_0_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer l2TokenBridge\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_1_0_20;\n\n /**\n * @notice Mapping that stores deposits for a given pair of local and remote tokens.\n */\n mapping(address => mapping(address => uint256)) public deposits;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n * A gap size of 47 was chosen here, so that the first slot used in a child contract\n * would be a multiple of 50.\n */\n uint256[47] private __gap;\n\n /**\n * @notice Emitted when an ETH bridge is initiated to the other chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ETH bridge is finalized on this chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is initiated to the other chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is finalized on this chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Only allow EOAs to call the functions. Note that this is not safe against contracts\n * calling code within their constructors, but also doesn't really matter since we're\n * just trying to prevent users accidentally depositing with smart contract wallets.\n */\n modifier onlyEOA() {\n require(\n !Address.isContract(msg.sender),\n \"StandardBridge: function can only be called from an EOA\"\n );\n _;\n }\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) &&\n MESSENGER.xDomainMessageSender() == address(OTHER_BRIDGE),\n \"StandardBridge: function can only be called from the other bridge\"\n );\n _;\n }\n\n /**\n * @param _messenger Address of CrossDomainMessenger on this network.\n * @param _otherBridge Address of the other StandardBridge contract.\n */\n constructor(address payable _messenger, address payable _otherBridge) {\n MESSENGER = CrossDomainMessenger(_messenger);\n OTHER_BRIDGE = StandardBridge(_otherBridge);\n }\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n * Must be implemented by contracts that inherit.\n */\n receive() external payable virtual;\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @notice Sends ETH to the sender's address on the other chain.\n *\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETH(uint32 _minGasLimit, bytes calldata _extraData) public payable onlyEOA {\n _initiateBridgeETH(msg.sender, msg.sender, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a\n * smart contract and the call fails, the ETH will be temporarily locked in the\n * StandardBridge on the other chain until the call is replayed. If the call cannot be\n * replayed with any amount of gas (call always reverts), then the ETH will be\n * permanently locked in the StandardBridge on the other chain. ETH will also\n * be locked if the receiver is the other bridge, because finalizeBridgeETH will revert\n * in that case.\n *\n * @param _to Address of the receiver.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public payable {\n _initiateBridgeETH(msg.sender, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ERC20 tokens to the sender's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20(\n address _localToken,\n address _remoteToken,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual onlyEOA {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Finalizes an ETH bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public payable onlyOtherBridge {\n require(msg.value == _amount, \"StandardBridge: amount sent does not match amount required\");\n require(_to != address(this), \"StandardBridge: cannot send to self\");\n require(_to != address(MESSENGER), \"StandardBridge: cannot send to messenger\");\n\n // Emit the correct events. By default this will be _amount, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n\n bool success = SafeCall.call(_to, gasleft(), _amount, hex\"\");\n require(success, \"StandardBridge: ETH transfer failed\");\n }\n\n /**\n * @notice Finalizes an ERC20 bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public onlyOtherBridge {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).mint(_to, _amount);\n } else {\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] - _amount;\n IERC20(_localToken).safeTransfer(_to, _amount);\n }\n\n // Emit the correct events. By default this will be ERC20BridgeFinalized, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Initiates a bridge of ETH through the CrossDomainMessenger.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n require(\n msg.value == _amount,\n \"StandardBridge: bridging ETH must include sufficient ETH value\"\n );\n\n // Emit the correct events. By default this will be _amount, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage{ value: _amount }(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeETH.selector,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).burn(_from, _amount);\n } else {\n IERC20(_localToken).safeTransferFrom(_from, address(this), _amount);\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount;\n }\n\n // Emit the correct events. By default this will be ERC20BridgeInitiated, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeERC20.selector,\n // Because this call will be executed on the remote chain, we reverse the order of\n // the remote and local token addresses relative to their order in the\n // finalizeBridgeERC20 function.\n _remoteToken,\n _localToken,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Checks if a given address is an OptimismMintableERC20. Not perfect, but good enough.\n * Just the way we like it.\n *\n * @param _token Address of the token to check.\n *\n * @return True if the token is an OptimismMintableERC20.\n */\n function _isOptimismMintableERC20(address _token) internal view returns (bool) {\n return\n ERC165Checker.supportsInterface(_token, type(ILegacyMintableERC20).interfaceId) ||\n ERC165Checker.supportsInterface(_token, type(IOptimismMintableERC20).interfaceId);\n }\n\n /**\n * @notice Checks if the \"other token\" is the correct pair token for the OptimismMintableERC20.\n * Calls can be saved in the future by combining this logic with\n * `_isOptimismMintableERC20`.\n *\n * @param _mintableToken OptimismMintableERC20 to check against.\n * @param _otherToken Pair token to check.\n *\n * @return True if the other token is the correct pair token for the OptimismMintableERC20.\n */\n function _isCorrectTokenPair(address _mintableToken, address _otherToken)\n internal\n view\n returns (bool)\n {\n if (\n ERC165Checker.supportsInterface(_mintableToken, type(ILegacyMintableERC20).interfaceId)\n ) {\n return _otherToken == ILegacyMintableERC20(_mintableToken).l1Token();\n } else {\n return _otherToken == IOptimismMintableERC20(_mintableToken).remoteToken();\n }\n }\n\n /** @notice Emits the ETHBridgeInitiated event and if necessary the appropriate legacy event\n * when an ETH bridge is finalized on this chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ETHBridgeFinalized and if necessary the appropriate legacy event when an\n * ETH bridge is finalized on this chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ERC20BridgeInitiated event and if necessary the appropriate legacy\n * event when an ERC20 bridge is initiated to the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the ERC20 on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ERC20BridgeFinalized event and if necessary the appropriate legacy\n * event when an ERC20 bridge is initiated to the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the ERC20 on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/vendor/AddressAliasHelper.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npragma solidity ^0.8.0;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n unchecked {\n l2Address = address(uint160(l1Address) + offset);\n }\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n unchecked {\n l1Address = address(uint160(l2Address) - offset);\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/access/Ownable.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/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 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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/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/Address.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) || (!Address.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" - }, - "node_modules/@openzeppelin/contracts/security/ReentrancyGuard.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\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 ReentrancyGuard {\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 constructor() {\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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, allowance(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 = allowance(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 `from` to `to`.\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 Updates `owner` s allowance for `spender` based on spent `amount`.\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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 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 /**\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (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 constant _PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n /**\n * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\n * However, to ensure consistency with the upgradeable transpiler, we will continue\n * to reserve a slot.\n * @custom:oz-renamed-from _PERMIT_TYPEHASH\n */\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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: address zero is not a valid owner\");\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: invalid token ID\");\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 _requireMinted(tokenId);\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 token 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 _requireMinted(tokenId);\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: caller is not token 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: caller is not token 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 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 an {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 an {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 Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\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 /// @solidity memory-safe-assembly\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Address.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 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 /// @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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\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 /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.3) (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 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 /// @solidity memory-safe-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 {\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.2) (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 // prepare call\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n\n // perform static call\n bool success;\n uint256 returnSize;\n uint256 returnValue;\n assembly {\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\n returnSize := returndatasize()\n returnValue := mload(0x00)\n }\n\n return success && returnSize >= 0x20 && returnValue > 0;\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\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 == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`.\n // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.\n // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.\n // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a\n // good first aproximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1;\n uint256 x = a;\n if (x >> 128 > 0) {\n x >>= 128;\n result <<= 64;\n }\n if (x >> 64 > 0) {\n x >>= 64;\n result <<= 32;\n }\n if (x >> 32 > 0) {\n x >>= 32;\n result <<= 16;\n }\n if (x >> 16 > 0) {\n x >>= 16;\n result <<= 8;\n }\n if (x >> 8 > 0) {\n x >>= 8;\n result <<= 4;\n }\n if (x >> 4 > 0) {\n x >>= 4;\n result <<= 2;\n }\n if (x >> 2 > 0) {\n result <<= 1;\n }\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n uint256 result = sqrt(a);\n if (rounding == Rounding.Up && result * result < a) {\n result += 1;\n }\n return result;\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\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 * _Available since v4.2._\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 uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(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 * _Available since v2.5._\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 uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(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 * _Available since v4.2._\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 uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(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 * _Available since v2.5._\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 uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(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 * _Available since v2.5._\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 uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(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 * _Available since v2.5._\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 * _Available since v2.5._\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 * _Available since v3.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 int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248) {\n require(value >= type(int248).min && value <= type(int248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return int248(value);\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240) {\n require(value >= type(int240).min && value <= type(int240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return int240(value);\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232) {\n require(value >= type(int232).min && value <= type(int232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return int232(value);\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224) {\n require(value >= type(int224).min && value <= type(int224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return int224(value);\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216) {\n require(value >= type(int216).min && value <= type(int216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return int216(value);\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208) {\n require(value >= type(int208).min && value <= type(int208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return int208(value);\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200) {\n require(value >= type(int200).min && value <= type(int200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return int200(value);\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192) {\n require(value >= type(int192).min && value <= type(int192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return int192(value);\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184) {\n require(value >= type(int184).min && value <= type(int184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return int184(value);\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176) {\n require(value >= type(int176).min && value <= type(int176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return int176(value);\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168) {\n require(value >= type(int168).min && value <= type(int168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return int168(value);\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160) {\n require(value >= type(int160).min && value <= type(int160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return int160(value);\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152) {\n require(value >= type(int152).min && value <= type(int152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return int152(value);\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144) {\n require(value >= type(int144).min && value <= type(int144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return int144(value);\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136) {\n require(value >= type(int136).min && value <= type(int136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return int136(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 int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120) {\n require(value >= type(int120).min && value <= type(int120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return int120(value);\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112) {\n require(value >= type(int112).min && value <= type(int112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return int112(value);\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104) {\n require(value >= type(int104).min && value <= type(int104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return int104(value);\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96) {\n require(value >= type(int96).min && value <= type(int96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return int96(value);\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88) {\n require(value >= type(int88).min && value <= type(int88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return int88(value);\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80) {\n require(value >= type(int80).min && value <= type(int80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return int80(value);\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72) {\n require(value >= type(int72).min && value <= type(int72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return int72(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 int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56) {\n require(value >= type(int56).min && value <= type(int56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return int56(value);\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48) {\n require(value >= type(int48).min && value <= type(int48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return int48(value);\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40) {\n require(value >= type(int40).min && value <= type(int40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return int40(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 int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24) {\n require(value >= type(int24).min && value <= type(int24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return int24(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 * _Available since v3.0._\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" - }, - "node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@rari-capital/solmate/src/utils/Bytes32AddressLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Library for converting between addresses and bytes32 values.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/Bytes32AddressLib.sol)\nlibrary Bytes32AddressLib {\n function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n function fillLast12Bytes(address addressValue) internal pure returns (bytes32) {\n return bytes32(bytes20(addressValue));\n }\n}\n" - }, - "node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)\nlibrary FixedPointMathLib {\n /*//////////////////////////////////////////////////////////////\n SIMPLIFIED FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n }\n\n function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n }\n\n function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n }\n\n function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n }\n\n function powWad(int256 x, int256 y) internal pure returns (int256) {\n // Equivalent to x to the power of y because x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)\n return expWad((lnWad(x) * y) / int256(WAD)); // Using ln(x) means x must be greater than 0.\n }\n\n function expWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n // When the result is < 0.5 we return zero. This happens when\n // x <= floor(log(0.5e18) * 1e18) ~ -42e18\n if (x <= -42139678854452767551) return 0;\n\n // When the result is > (2**255 - 1) / 1e18 we can not represent it as an\n // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.\n if (x >= 135305999368893231589) revert(\"EXP_OVERFLOW\");\n\n // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96\n // for more intermediate precision and a binary basis. This base conversion\n // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.\n x = (x << 78) / 5**18;\n\n // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers\n // of two such that exp(x) = exp(x') * 2**k, where k is an integer.\n // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).\n int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96;\n x = x - k * 54916777467707473351141471128;\n\n // k is in the range [-61, 195].\n\n // Evaluate using a (6, 7)-term rational approximation.\n // p is made monic, we'll multiply by a scale factor later.\n int256 y = x + 1346386616545796478920950773328;\n y = ((y * x) >> 96) + 57155421227552351082224309758442;\n int256 p = y + x - 94201549194550492254356042504812;\n p = ((p * y) >> 96) + 28719021644029726153956944680412240;\n p = p * x + (4385272521454847904659076985693276 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n int256 q = x - 2855989394907223263936484059900;\n q = ((q * x) >> 96) + 50020603652535783019961831881945;\n q = ((q * x) >> 96) - 533845033583426703283633433725380;\n q = ((q * x) >> 96) + 3604857256930695427073651918091429;\n q = ((q * x) >> 96) - 14423608567350463180887372962807573;\n q = ((q * x) >> 96) + 26449188498355588339934803723976023;\n\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial won't have zeros in the domain as all its roots are complex.\n // No scaling is necessary because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r should be in the range (0.09, 0.25) * 2**96.\n\n // We now need to multiply r by:\n // * the scale factor s = ~6.031367120.\n // * the 2**k factor from the range reduction.\n // * the 1e18 / 2**96 factor for base conversion.\n // We do this all at once, with an intermediate result in 2**213\n // basis, so the final right shift is always by a positive amount.\n r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k));\n }\n }\n\n function lnWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n require(x > 0, \"UNDEFINED\");\n\n // We want to convert x from 10**18 fixed point to 2**96 fixed point.\n // We do this by multiplying by 2**96 / 10**18. But since\n // ln(x * C) = ln(x) + ln(C), we can simply do nothing here\n // and add ln(2**96 / 10**18) at the end.\n\n // Reduce range of x to (1, 2) * 2**96\n // ln(2^k * x) = k * ln(2) + ln(x)\n int256 k = int256(log2(uint256(x))) - 96;\n x <<= uint256(159 - k);\n x = int256(uint256(x) >> 159);\n\n // Evaluate using a (8, 8)-term rational approximation.\n // p is made monic, we will multiply by a scale factor later.\n int256 p = x + 3273285459638523848632254066296;\n p = ((p * x) >> 96) + 24828157081833163892658089445524;\n p = ((p * x) >> 96) + 43456485725739037958740375743393;\n p = ((p * x) >> 96) - 11111509109440967052023855526967;\n p = ((p * x) >> 96) - 45023709667254063763336534515857;\n p = ((p * x) >> 96) - 14706773417378608786704636184526;\n p = p * x - (795164235651350426258249787498 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n // q is monic by convention.\n int256 q = x + 5573035233440673466300451813936;\n q = ((q * x) >> 96) + 71694874799317883764090561454958;\n q = ((q * x) >> 96) + 283447036172924575727196451306956;\n q = ((q * x) >> 96) + 401686690394027663651624208769553;\n q = ((q * x) >> 96) + 204048457590392012362485061816622;\n q = ((q * x) >> 96) + 31853899698501571402653359427138;\n q = ((q * x) >> 96) + 909429971244387300277376558375;\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial is known not to have zeros in the domain.\n // No scaling required because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r is in the range (0, 0.125) * 2**96\n\n // Finalization, we need to:\n // * multiply by the scale factor s = 5.549…\n // * add ln(2**96 / 10**18)\n // * add k * ln(2)\n // * multiply by 10**18 / 2**96 = 5**18 >> 78\n\n // mul s * 5e18 * 2**96, base is now 5**18 * 2**192\n r *= 1677202110996718588342820967067443963516166;\n // add ln(2) * k * 5e18 * 2**192\n r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;\n // add ln(2**96 / 10**18) * 5e18 * 2**192\n r += 600920179829731861736702779321621459595472258049074101567377883020018308;\n // base conversion: mul 2**18 / 2**192\n r >>= 174;\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n LOW LEVEL FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function mulDivDown(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // Divide z by the denominator.\n z := div(z, denominator)\n }\n }\n\n function mulDivUp(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // First, divide z - 1 by the denominator and add 1.\n // We allow z - 1 to underflow if z is 0, because we multiply the\n // end result by 0 if z is zero, ensuring we return 0 if z is zero.\n z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))\n }\n }\n\n function rpow(\n uint256 x,\n uint256 n,\n uint256 scalar\n ) internal pure returns (uint256 z) {\n assembly {\n switch x\n case 0 {\n switch n\n case 0 {\n // 0 ** 0 = 1\n z := scalar\n }\n default {\n // 0 ** n = 0\n z := 0\n }\n }\n default {\n switch mod(n, 2)\n case 0 {\n // If n is even, store scalar in z for now.\n z := scalar\n }\n default {\n // If n is odd, store x in z for now.\n z := x\n }\n\n // Shifting right by 1 is like dividing by 2.\n let half := shr(1, scalar)\n\n for {\n // Shift n right by 1 before looping to halve it.\n n := shr(1, n)\n } n {\n // Shift n right by 1 each iteration to halve it.\n n := shr(1, n)\n } {\n // Revert immediately if x ** 2 would overflow.\n // Equivalent to iszero(eq(div(xx, x), x)) here.\n if shr(128, x) {\n revert(0, 0)\n }\n\n // Store x squared.\n let xx := mul(x, x)\n\n // Round to the nearest number.\n let xxRound := add(xx, half)\n\n // Revert if xx + half overflowed.\n if lt(xxRound, xx) {\n revert(0, 0)\n }\n\n // Set x to scaled xxRound.\n x := div(xxRound, scalar)\n\n // If n is even:\n if mod(n, 2) {\n // Compute z * x.\n let zx := mul(z, x)\n\n // If z * x overflowed:\n if iszero(eq(div(zx, x), z)) {\n // Revert if x is non-zero.\n if iszero(iszero(x)) {\n revert(0, 0)\n }\n }\n\n // Round to the nearest number.\n let zxRound := add(zx, half)\n\n // Revert if zx + half overflowed.\n if lt(zxRound, zx) {\n revert(0, 0)\n }\n\n // Return properly scaled zxRound.\n z := div(zxRound, scalar)\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n GENERAL NUMBER UTILITIES\n //////////////////////////////////////////////////////////////*/\n\n function sqrt(uint256 x) internal pure returns (uint256 z) {\n assembly {\n let y := x // We start y at x, which will help us make our initial estimate.\n\n z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n // We check y >= 2^(k + 8) but shift right by k bits\n // each branch to ensure that if x >= 256, then y >= 256.\n if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n y := shr(128, y)\n z := shl(64, z)\n }\n if iszero(lt(y, 0x1000000000000000000)) {\n y := shr(64, y)\n z := shl(32, z)\n }\n if iszero(lt(y, 0x10000000000)) {\n y := shr(32, y)\n z := shl(16, z)\n }\n if iszero(lt(y, 0x1000000)) {\n y := shr(16, y)\n z := shl(8, z)\n }\n\n // Goal was to get z*z*y within a small factor of x. More iterations could\n // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n // There is no overflow risk here since y < 2^136 after the first branch above.\n z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n\n // If x+1 is a perfect square, the Babylonian method cycles between\n // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n z := sub(z, lt(div(x, z), z))\n }\n }\n\n function log2(uint256 x) internal pure returns (uint256 r) {\n require(x > 0, \"UNDEFINED\");\n\n assembly {\n r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n r := or(r, shl(4, lt(0xffff, shr(r, x))))\n r := or(r, shl(3, lt(0xff, shr(r, x))))\n r := or(r, shl(2, lt(0xf, shr(r, x))))\n r := or(r, shl(1, lt(0x3, shr(r, x))))\n r := or(r, lt(0x1, shr(r, x)))\n }\n }\n}\n" - }, - "node_modules/ds-test/src/test.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see .\n\npragma solidity >=0.5.0;\n\ncontract DSTest {\n event log (string);\n event logs (bytes);\n\n event log_address (address);\n event log_bytes32 (bytes32);\n event log_int (int);\n event log_uint (uint);\n event log_bytes (bytes);\n event log_string (string);\n\n event log_named_address (string key, address val);\n event log_named_bytes32 (string key, bytes32 val);\n event log_named_decimal_int (string key, int val, uint decimals);\n event log_named_decimal_uint (string key, uint val, uint decimals);\n event log_named_int (string key, int val);\n event log_named_uint (string key, uint val);\n event log_named_bytes (string key, bytes val);\n event log_named_string (string key, string val);\n\n bool public IS_TEST = true;\n bool private _failed;\n\n address constant HEVM_ADDRESS =\n address(bytes20(uint160(uint256(keccak256('hevm cheat code')))));\n\n modifier mayRevert() { _; }\n modifier testopts(string memory) { _; }\n\n function failed() public returns (bool) {\n if (_failed) {\n return _failed;\n } else {\n bool globalFailed = false;\n if (hasHEVMContext()) {\n (, bytes memory retdata) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"load(address,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"))\n )\n );\n globalFailed = abi.decode(retdata, (bool));\n }\n return globalFailed;\n }\n } \n\n function fail() internal {\n if (hasHEVMContext()) {\n (bool status, ) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"store(address,bytes32,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"), bytes32(uint256(0x01)))\n )\n );\n status; // Silence compiler warnings\n }\n _failed = true;\n }\n\n function hasHEVMContext() internal view returns (bool) {\n uint256 hevmCodeSize = 0;\n assembly {\n hevmCodeSize := extcodesize(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D)\n }\n return hevmCodeSize > 0;\n }\n\n modifier logs_gas() {\n uint startGas = gasleft();\n _;\n uint endGas = gasleft();\n emit log_named_uint(\"gas\", startGas - endGas);\n }\n\n function assertTrue(bool condition) internal {\n if (!condition) {\n emit log(\"Error: Assertion Failed\");\n fail();\n }\n }\n\n function assertTrue(bool condition, string memory err) internal {\n if (!condition) {\n emit log_named_string(\"Error\", err);\n assertTrue(condition);\n }\n }\n\n function assertEq(address a, address b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [address]\");\n emit log_named_address(\" Expected\", b);\n emit log_named_address(\" Actual\", a);\n fail();\n }\n }\n function assertEq(address a, address b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes32 a, bytes32 b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bytes32]\");\n emit log_named_bytes32(\" Expected\", b);\n emit log_named_bytes32(\" Actual\", a);\n fail();\n }\n }\n function assertEq(bytes32 a, bytes32 b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq32(bytes32 a, bytes32 b) internal {\n assertEq(a, b);\n }\n function assertEq32(bytes32 a, bytes32 b, string memory err) internal {\n assertEq(a, b, err);\n }\n\n function assertEq(int a, int b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [int]\");\n emit log_named_int(\" Expected\", b);\n emit log_named_int(\" Actual\", a);\n fail();\n }\n }\n function assertEq(int a, int b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq(uint a, uint b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [uint]\");\n emit log_named_uint(\" Expected\", b);\n emit log_named_uint(\" Actual\", a);\n fail();\n }\n }\n function assertEq(uint a, uint b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEqDecimal(int a, int b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Expected\", b, decimals);\n emit log_named_decimal_int(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Expected\", b, decimals);\n emit log_named_decimal_uint(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n\n function assertGt(uint a, uint b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGt(uint a, uint b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGt(int a, int b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGt(int a, int b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGtDecimal(int a, int b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n\n function assertGe(uint a, uint b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGe(uint a, uint b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGe(int a, int b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGe(int a, int b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGeDecimal(int a, int b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertLt(uint a, uint b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLt(uint a, uint b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLt(int a, int b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLt(int a, int b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLtDecimal(int a, int b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n\n function assertLe(uint a, uint b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLe(uint a, uint b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLe(int a, int b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLe(int a, int b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLeDecimal(int a, int b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLeDecimal(a, b, decimals);\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertEq(string memory a, string memory b) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log(\"Error: a == b not satisfied [string]\");\n emit log_named_string(\" Expected\", b);\n emit log_named_string(\" Actual\", a);\n fail();\n }\n }\n function assertEq(string memory a, string memory b, string memory err) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function checkEq0(bytes memory a, bytes memory b) internal pure returns (bool ok) {\n ok = true;\n if (a.length == b.length) {\n for (uint i = 0; i < a.length; i++) {\n if (a[i] != b[i]) {\n ok = false;\n }\n }\n } else {\n ok = false;\n }\n }\n function assertEq0(bytes memory a, bytes memory b) internal {\n if (!checkEq0(a, b)) {\n emit log(\"Error: a == b not satisfied [bytes]\");\n emit log_named_bytes(\" Expected\", b);\n emit log_named_bytes(\" Actual\", a);\n fail();\n }\n }\n function assertEq0(bytes memory a, bytes memory b, string memory err) internal {\n if (!checkEq0(a, b)) {\n emit log_named_string(\"Error\", err);\n assertEq0(a, b);\n }\n }\n}\n" - }, - "node_modules/forge-std/src/Base.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {StdStorage} from \"./StdStorage.sol\";\nimport {Vm, VmSafe} from \"./Vm.sol\";\n\nabstract contract CommonBase {\n // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.\n address internal constant VM_ADDRESS = address(uint160(uint256(keccak256(\"hevm cheat code\"))));\n // console.sol and console2.sol work by executing a staticcall to this address.\n address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;\n // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38.\n address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256(\"foundry default caller\"))));\n // Address of the test contract, deployed by the DEFAULT_SENDER.\n address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;\n // Deterministic deployment address of the Multicall3 contract.\n address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11;\n\n uint256 internal constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n Vm internal constant vm = Vm(VM_ADDRESS);\n StdStorage internal stdstore;\n}\n\nabstract contract TestBase is CommonBase {}\n\nabstract contract ScriptBase is CommonBase {\n // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.\n address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;\n\n VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);\n}\n" - }, - "node_modules/forge-std/src/StdAssertions.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {DSTest} from \"ds-test/test.sol\";\nimport {stdMath} from \"./StdMath.sol\";\n\nabstract contract StdAssertions is DSTest {\n event log_array(uint256[] val);\n event log_array(int256[] val);\n event log_array(address[] val);\n event log_named_array(string key, uint256[] val);\n event log_named_array(string key, int256[] val);\n event log_named_array(string key, address[] val);\n\n function fail(string memory err) internal virtual {\n emit log_named_string(\"Error\", err);\n fail();\n }\n\n function assertFalse(bool data) internal virtual {\n assertTrue(!data);\n }\n\n function assertFalse(bool data, string memory err) internal virtual {\n assertTrue(!data, err);\n }\n\n function assertEq(bool a, bool b) internal virtual {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bool]\");\n emit log_named_string(\" Left\", a ? \"true\" : \"false\");\n emit log_named_string(\" Right\", b ? \"true\" : \"false\");\n fail();\n }\n }\n\n function assertEq(bool a, bool b, string memory err) internal virtual {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes memory a, bytes memory b) internal virtual {\n assertEq0(a, b);\n }\n\n function assertEq(bytes memory a, bytes memory b, string memory err) internal virtual {\n assertEq0(a, b, err);\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [uint[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [int[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(address[] memory a, address[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [address[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(address[] memory a, address[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n // Legacy helper\n function assertEqUint(uint256 a, uint256 b) internal virtual {\n assertEq(uint256(a), uint256(b));\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Left\", a);\n emit log_named_uint(\" Right\", b);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_decimal_uint(\" Left\", a, decimals);\n emit log_named_decimal_uint(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max Delta\", maxDelta, decimals);\n emit log_named_decimal_uint(\" Delta\", delta, decimals);\n fail();\n }\n }\n\n function assertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbsDecimal(a, b, maxDelta, decimals);\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Left\", a);\n emit log_named_int(\" Right\", b);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_decimal_int(\" Left\", a, decimals);\n emit log_named_decimal_int(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max Delta\", maxDelta, decimals);\n emit log_named_decimal_uint(\" Delta\", delta, decimals);\n fail();\n }\n }\n\n function assertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbsDecimal(a, b, maxDelta, decimals);\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%\n ) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Left\", a);\n emit log_named_uint(\" Right\", b);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n string memory err\n ) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n\n function assertApproxEqRelDecimal(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n uint256 decimals\n ) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_decimal_uint(\" Left\", a, decimals);\n emit log_named_decimal_uint(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRelDecimal(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n uint256 decimals,\n string memory err\n ) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Left\", a);\n emit log_named_int(\" Right\", b);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta, string memory err) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n\n function assertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_decimal_int(\" Left\", a, decimals);\n emit log_named_decimal_int(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);\n }\n }\n\n function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual {\n assertEqCall(target, callDataA, target, callDataB, true);\n }\n\n function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB)\n internal\n virtual\n {\n assertEqCall(targetA, callDataA, targetB, callDataB, true);\n }\n\n function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData)\n internal\n virtual\n {\n assertEqCall(target, callDataA, target, callDataB, strictRevertData);\n }\n\n function assertEqCall(\n address targetA,\n bytes memory callDataA,\n address targetB,\n bytes memory callDataB,\n bool strictRevertData\n ) internal virtual {\n (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA);\n (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB);\n\n if (successA && successB) {\n assertEq(returnDataA, returnDataB, \"Call return data does not match\");\n }\n\n if (!successA && !successB && strictRevertData) {\n assertEq(returnDataA, returnDataB, \"Call revert data does not match\");\n }\n\n if (!successA && successB) {\n emit log(\"Error: Calls were not equal\");\n emit log_named_bytes(\" Left call revert data\", returnDataA);\n emit log_named_bytes(\" Right call return data\", returnDataB);\n fail();\n }\n\n if (successA && !successB) {\n emit log(\"Error: Calls were not equal\");\n emit log_named_bytes(\" Left call return data\", returnDataA);\n emit log_named_bytes(\" Right call revert data\", returnDataB);\n fail();\n }\n }\n}\n" - }, - "node_modules/forge-std/src/StdChains.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n/**\n * StdChains provides information about EVM compatible chains that can be used in scripts/tests.\n * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are\n * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of\n * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the\n * alias used in this contract, which can be found as the first argument to the\n * `setChainWithDefaultRpcUrl` call in the `initialize` function.\n *\n * There are two main ways to use this contract:\n * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or\n * `setChain(string memory chainAlias, Chain memory chain)`\n * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.\n *\n * The first time either of those are used, chains are initialized with the default set of RPC URLs.\n * This is done in `initialize`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in\n * `defaultRpcUrls`.\n *\n * The `setChain` function is straightforward, and it simply saves off the given chain data.\n *\n * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say\n * we want to retrieve `mainnet`'s RPC URL:\n * - If you haven't set any mainnet chain info with `setChain`, you haven't specified that\n * chain in `foundry.toml` and no env var is set, the default data and RPC URL will be returned.\n * - If you have set a mainnet RPC URL in `foundry.toml` it will return that, if valid (e.g. if\n * a URL is given or if an environment variable is given and that environment variable exists).\n * Otherwise, the default data is returned.\n * - If you specified data with `setChain` it will return that.\n *\n * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults.\n */\nabstract contract StdChains {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private initialized;\n\n struct ChainData {\n string name;\n uint256 chainId;\n string rpcUrl;\n }\n\n struct Chain {\n // The chain name.\n string name;\n // The chain's Chain ID.\n uint256 chainId;\n // The chain's alias. (i.e. what gets specified in `foundry.toml`).\n string chainAlias;\n // A default RPC endpoint for this chain.\n // NOTE: This default RPC URL is included for convenience to facilitate quick tests and\n // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy\n // usage as you will be throttled and this is a disservice to others who need this endpoint.\n string rpcUrl;\n }\n\n // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.\n mapping(string => Chain) private chains;\n // Maps from the chain's alias to it's default RPC URL.\n mapping(string => string) private defaultRpcUrls;\n // Maps from a chain ID to it's alias.\n mapping(uint256 => string) private idToAlias;\n\n bool private fallbackToDefaultRpcUrls = true;\n\n // The RPC URL will be fetched from config or defaultRpcUrls if possible.\n function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {\n require(bytes(chainAlias).length != 0, \"StdChains getChain(string): Chain alias cannot be the empty string.\");\n\n initialize();\n chain = chains[chainAlias];\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(string): Chain with alias \\\"\", chainAlias, \"\\\" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {\n require(chainId != 0, \"StdChains getChain(uint256): Chain ID cannot be 0.\");\n initialize();\n string memory chainAlias = idToAlias[chainId];\n\n chain = chains[chainAlias];\n\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(uint256): Chain with ID \", vm.toString(chainId), \" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n // set chain info, with priority to argument's rpcUrl field.\n function setChain(string memory chainAlias, ChainData memory chain) internal virtual {\n require(\n bytes(chainAlias).length != 0,\n \"StdChains setChain(string,ChainData): Chain alias cannot be the empty string.\"\n );\n\n require(chain.chainId != 0, \"StdChains setChain(string,ChainData): Chain ID cannot be 0.\");\n\n initialize();\n string memory foundAlias = idToAlias[chain.chainId];\n\n require(\n bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)),\n string(\n abi.encodePacked(\n \"StdChains setChain(string,ChainData): Chain ID \",\n vm.toString(chain.chainId),\n \" already used by \\\"\",\n foundAlias,\n \"\\\".\"\n )\n )\n );\n\n uint256 oldChainId = chains[chainAlias].chainId;\n delete idToAlias[oldChainId];\n\n chains[chainAlias] =\n Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});\n idToAlias[chain.chainId] = chainAlias;\n }\n\n // set chain info, with priority to argument's rpcUrl field.\n function setChain(string memory chainAlias, Chain memory chain) internal virtual {\n setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));\n }\n\n function _toUpper(string memory str) private pure returns (string memory) {\n bytes memory strb = bytes(str);\n bytes memory copy = new bytes(strb.length);\n for (uint256 i = 0; i < strb.length; i++) {\n bytes1 b = strb[i];\n if (b >= 0x61 && b <= 0x7A) {\n copy[i] = bytes1(uint8(b) - 32);\n } else {\n copy[i] = b;\n }\n }\n return string(copy);\n }\n\n // lookup rpcUrl, in descending order of priority:\n // current -> config (foundry.toml) -> environment variable -> default\n function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) private returns (Chain memory) {\n if (bytes(chain.rpcUrl).length == 0) {\n try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {\n chain.rpcUrl = configRpcUrl;\n } catch (bytes memory err) {\n string memory envName = string(abi.encodePacked(_toUpper(chainAlias), \"_RPC_URL\"));\n if (fallbackToDefaultRpcUrls) {\n chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]);\n } else {\n chain.rpcUrl = vm.envString(envName);\n }\n // distinguish 'not found' from 'cannot read'\n bytes memory notFoundError =\n abi.encodeWithSignature(\"CheatCodeError\", string(abi.encodePacked(\"invalid rpc url \", chainAlias)));\n if (keccak256(notFoundError) != keccak256(err) || bytes(chain.rpcUrl).length == 0) {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, err), mload(err))\n }\n }\n }\n }\n return chain;\n }\n\n function setFallbackToDefaultRpcUrls(bool useDefault) internal {\n fallbackToDefaultRpcUrls = useDefault;\n }\n\n function initialize() private {\n if (initialized) return;\n\n initialized = true;\n\n // If adding an RPC here, make sure to test the default RPC URL in `testRpcs`\n setChainWithDefaultRpcUrl(\"anvil\", ChainData(\"Anvil\", 31337, \"http://127.0.0.1:8545\"));\n setChainWithDefaultRpcUrl(\n \"mainnet\", ChainData(\"Mainnet\", 1, \"https://mainnet.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\n \"goerli\", ChainData(\"Goerli\", 5, \"https://goerli.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\n \"sepolia\", ChainData(\"Sepolia\", 11155111, \"https://sepolia.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\"optimism\", ChainData(\"Optimism\", 10, \"https://mainnet.optimism.io\"));\n setChainWithDefaultRpcUrl(\"optimism_goerli\", ChainData(\"Optimism Goerli\", 420, \"https://goerli.optimism.io\"));\n setChainWithDefaultRpcUrl(\"arbitrum_one\", ChainData(\"Arbitrum One\", 42161, \"https://arb1.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\n \"arbitrum_one_goerli\", ChainData(\"Arbitrum One Goerli\", 421613, \"https://goerli-rollup.arbitrum.io/rpc\")\n );\n setChainWithDefaultRpcUrl(\"arbitrum_nova\", ChainData(\"Arbitrum Nova\", 42170, \"https://nova.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\"polygon\", ChainData(\"Polygon\", 137, \"https://polygon-rpc.com\"));\n setChainWithDefaultRpcUrl(\n \"polygon_mumbai\", ChainData(\"Polygon Mumbai\", 80001, \"https://rpc-mumbai.maticvigil.com\")\n );\n setChainWithDefaultRpcUrl(\"avalanche\", ChainData(\"Avalanche\", 43114, \"https://api.avax.network/ext/bc/C/rpc\"));\n setChainWithDefaultRpcUrl(\n \"avalanche_fuji\", ChainData(\"Avalanche Fuji\", 43113, \"https://api.avax-test.network/ext/bc/C/rpc\")\n );\n setChainWithDefaultRpcUrl(\n \"bnb_smart_chain\", ChainData(\"BNB Smart Chain\", 56, \"https://bsc-dataseed1.binance.org\")\n );\n setChainWithDefaultRpcUrl(\n \"bnb_smart_chain_testnet\",\n ChainData(\"BNB Smart Chain Testnet\", 97, \"https://rpc.ankr.com/bsc_testnet_chapel\")\n );\n setChainWithDefaultRpcUrl(\"gnosis_chain\", ChainData(\"Gnosis Chain\", 100, \"https://rpc.gnosischain.com\"));\n }\n\n // set chain info, with priority to chainAlias' rpc url in foundry.toml\n function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {\n string memory rpcUrl = chain.rpcUrl;\n defaultRpcUrls[chainAlias] = rpcUrl;\n chain.rpcUrl = \"\";\n setChain(chainAlias, chain);\n chain.rpcUrl = rpcUrl; // restore argument\n }\n}\n" - }, - "node_modules/forge-std/src/StdCheats.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {Vm} from \"./Vm.sol\";\n\nabstract contract StdCheatsSafe {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private gasMeteringOff;\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawTx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n // json value name = function\n string functionSig;\n bytes32 hash;\n // json value name = tx\n RawTx1559Detail txDetail;\n // json value name = type\n string opcode;\n }\n\n struct RawTx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n bytes gas;\n bytes nonce;\n address to;\n bytes txType;\n bytes value;\n }\n\n struct Tx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n bytes32 hash;\n Tx1559Detail txDetail;\n string opcode;\n }\n\n struct Tx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n uint256 gas;\n uint256 nonce;\n address to;\n uint256 txType;\n uint256 value;\n }\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct TxLegacy {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n string hash;\n string opcode;\n TxDetailLegacy transaction;\n }\n\n struct TxDetailLegacy {\n AccessList[] accessList;\n uint256 chainId;\n bytes data;\n address from;\n uint256 gas;\n uint256 gasPrice;\n bytes32 hash;\n uint256 nonce;\n bytes1 opcode;\n bytes32 r;\n bytes32 s;\n uint256 txType;\n address to;\n uint8 v;\n uint256 value;\n }\n\n struct AccessList {\n address accessAddress;\n bytes32[] storageKeys;\n }\n\n // Data structures to parse Receipt objects from the broadcast artifact.\n // The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawReceipt {\n bytes32 blockHash;\n bytes blockNumber;\n address contractAddress;\n bytes cumulativeGasUsed;\n bytes effectiveGasPrice;\n address from;\n bytes gasUsed;\n RawReceiptLog[] logs;\n bytes logsBloom;\n bytes status;\n address to;\n bytes32 transactionHash;\n bytes transactionIndex;\n }\n\n struct Receipt {\n bytes32 blockHash;\n uint256 blockNumber;\n address contractAddress;\n uint256 cumulativeGasUsed;\n uint256 effectiveGasPrice;\n address from;\n uint256 gasUsed;\n ReceiptLog[] logs;\n bytes logsBloom;\n uint256 status;\n address to;\n bytes32 transactionHash;\n uint256 transactionIndex;\n }\n\n // Data structures to parse the entire broadcast artifact, assuming the\n // transactions conform to EIP1559.\n\n struct EIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n Receipt[] receipts;\n uint256 timestamp;\n Tx1559[] transactions;\n TxReturn[] txReturns;\n }\n\n struct RawEIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n RawReceipt[] receipts;\n TxReturn[] txReturns;\n uint256 timestamp;\n RawTx1559[] transactions;\n }\n\n struct RawReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n bytes blockNumber;\n bytes data;\n bytes logIndex;\n bool removed;\n bytes32[] topics;\n bytes32 transactionHash;\n bytes transactionIndex;\n bytes transactionLogIndex;\n }\n\n struct ReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n uint256 blockNumber;\n bytes data;\n uint256 logIndex;\n bytes32[] topics;\n uint256 transactionIndex;\n uint256 transactionLogIndex;\n bool removed;\n }\n\n struct TxReturn {\n string internalType;\n string value;\n }\n\n function assumeNoPrecompiles(address addr) internal virtual {\n // Assembly required since `block.chainid` was introduced in 0.8.0.\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n assumeNoPrecompiles(addr, chainId);\n }\n\n function assumeNoPrecompiles(address addr, uint256 chainId) internal pure virtual {\n // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific\n // address), but the same rationale for excluding them applies so we include those too.\n\n // These should be present on all EVM-compatible chains.\n vm.assume(addr < address(0x1) || addr > address(0x9));\n\n // forgefmt: disable-start\n if (chainId == 10 || chainId == 420) {\n // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21\n vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));\n } else if (chainId == 42161 || chainId == 421613) {\n // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains\n vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));\n } else if (chainId == 43114 || chainId == 43113) {\n // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59\n vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));\n vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));\n vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));\n }\n // forgefmt: disable-end\n }\n\n function readEIP1559ScriptArtifact(string memory path)\n internal\n view\n virtual\n returns (EIP1559ScriptArtifact memory)\n {\n string memory data = vm.readFile(path);\n bytes memory parsedData = vm.parseJson(data);\n RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));\n EIP1559ScriptArtifact memory artifact;\n artifact.libraries = rawArtifact.libraries;\n artifact.path = rawArtifact.path;\n artifact.timestamp = rawArtifact.timestamp;\n artifact.pending = rawArtifact.pending;\n artifact.txReturns = rawArtifact.txReturns;\n artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);\n artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);\n return artifact;\n }\n\n function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {\n Tx1559[] memory txs = new Tx1559[](rawTxs.length);\n for (uint256 i; i < rawTxs.length; i++) {\n txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);\n }\n return txs;\n }\n\n function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {\n Tx1559 memory transaction;\n transaction.arguments = rawTx.arguments;\n transaction.contractName = rawTx.contractName;\n transaction.functionSig = rawTx.functionSig;\n transaction.hash = rawTx.hash;\n transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);\n transaction.opcode = rawTx.opcode;\n return transaction;\n }\n\n function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)\n internal\n pure\n virtual\n returns (Tx1559Detail memory)\n {\n Tx1559Detail memory txDetail;\n txDetail.data = rawDetail.data;\n txDetail.from = rawDetail.from;\n txDetail.to = rawDetail.to;\n txDetail.nonce = _bytesToUint(rawDetail.nonce);\n txDetail.txType = _bytesToUint(rawDetail.txType);\n txDetail.value = _bytesToUint(rawDetail.value);\n txDetail.gas = _bytesToUint(rawDetail.gas);\n txDetail.accessList = rawDetail.accessList;\n return txDetail;\n }\n\n function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".transactions\");\n RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));\n return rawToConvertedEIPTx1559s(rawTxs);\n }\n\n function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".transactions[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));\n return rawToConvertedEIPTx1559(rawTx);\n }\n\n // Analogous to readTransactions, but for receipts.\n function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".receipts\");\n RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));\n return rawToConvertedReceipts(rawReceipts);\n }\n\n function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".receipts[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));\n return rawToConvertedReceipt(rawReceipt);\n }\n\n function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {\n Receipt[] memory receipts = new Receipt[](rawReceipts.length);\n for (uint256 i; i < rawReceipts.length; i++) {\n receipts[i] = rawToConvertedReceipt(rawReceipts[i]);\n }\n return receipts;\n }\n\n function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {\n Receipt memory receipt;\n receipt.blockHash = rawReceipt.blockHash;\n receipt.to = rawReceipt.to;\n receipt.from = rawReceipt.from;\n receipt.contractAddress = rawReceipt.contractAddress;\n receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);\n receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);\n receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);\n receipt.status = _bytesToUint(rawReceipt.status);\n receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);\n receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);\n receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);\n receipt.logsBloom = rawReceipt.logsBloom;\n receipt.transactionHash = rawReceipt.transactionHash;\n return receipt;\n }\n\n function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)\n internal\n pure\n virtual\n returns (ReceiptLog[] memory)\n {\n ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);\n for (uint256 i; i < rawLogs.length; i++) {\n logs[i].logAddress = rawLogs[i].logAddress;\n logs[i].blockHash = rawLogs[i].blockHash;\n logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);\n logs[i].data = rawLogs[i].data;\n logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);\n logs[i].topics = rawLogs[i].topics;\n logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);\n logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);\n logs[i].removed = rawLogs[i].removed;\n }\n return logs;\n }\n\n // Deploy a contract by fetching the contract bytecode from\n // the artifacts directory\n // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`\n function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes): Deployment failed.\");\n }\n\n function deployCode(string memory what) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string): Deployment failed.\");\n }\n\n /// @dev deploy contract with value on construction\n function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes,uint256): Deployment failed.\");\n }\n\n function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,uint256): Deployment failed.\");\n }\n\n // creates a labeled address and the corresponding private key\n function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {\n privateKey = uint256(keccak256(abi.encodePacked(name)));\n addr = vm.addr(privateKey);\n vm.label(addr, name);\n }\n\n // creates a labeled address\n function makeAddr(string memory name) internal virtual returns (address addr) {\n (addr,) = makeAddrAndKey(name);\n }\n\n function deriveRememberKey(string memory mnemonic, uint32 index)\n internal\n virtual\n returns (address who, uint256 privateKey)\n {\n privateKey = vm.deriveKey(mnemonic, index);\n who = vm.rememberKey(privateKey);\n }\n\n function _bytesToUint(bytes memory b) private pure returns (uint256) {\n require(b.length <= 32, \"StdCheats _bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n function isFork() internal view virtual returns (bool status) {\n try vm.activeFork() {\n status = true;\n } catch (bytes memory) {}\n }\n\n modifier skipWhenForking() {\n if (!isFork()) {\n _;\n }\n }\n\n modifier skipWhenNotForking() {\n if (isFork()) {\n _;\n }\n }\n\n modifier noGasMetering() {\n vm.pauseGasMetering();\n // To prevent turning gas monitoring back on with nested functions that use this modifier,\n // we check if gasMetering started in the off position. If it did, we don't want to turn\n // it back on until we exit the top level function that used the modifier\n //\n // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.\n // funcA will have `gasStartedOff` as false, funcB will have it as true,\n // so we only turn metering back on at the end of the funcA\n bool gasStartedOff = gasMeteringOff;\n gasMeteringOff = true;\n\n _;\n\n // if gas metering was on when this modifier was called, turn it back on at the end\n if (!gasStartedOff) {\n gasMeteringOff = false;\n vm.resumeGasMetering();\n }\n }\n\n // a cheat for fuzzing addresses that are payable only\n // see https://github.com/foundry-rs/foundry/issues/3631\n function assumePayable(address addr) internal virtual {\n (bool success,) = payable(addr).call{value: 0}(\"\");\n vm.assume(success);\n }\n}\n\n// Wrappers around cheatcodes to avoid footguns\nabstract contract StdCheats is StdCheatsSafe {\n using stdStorage for StdStorage;\n\n StdStorage private stdstore;\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n // Skip forward or rewind time by the specified number of seconds\n function skip(uint256 time) internal virtual {\n vm.warp(block.timestamp + time);\n }\n\n function rewind(uint256 time) internal virtual {\n vm.warp(block.timestamp - time);\n }\n\n // Setup a prank from an address that has some ether\n function hoax(address msgSender) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.prank(msgSender);\n }\n\n function hoax(address msgSender, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.prank(msgSender);\n }\n\n function hoax(address msgSender, address origin) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.prank(msgSender, origin);\n }\n\n function hoax(address msgSender, address origin, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.prank(msgSender, origin);\n }\n\n // Start perpetual prank from an address that has some ether\n function startHoax(address msgSender) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.startPrank(msgSender);\n }\n\n function startHoax(address msgSender, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.startPrank(msgSender);\n }\n\n // Start perpetual prank from an address that has some ether\n // tx.origin is set to the origin parameter\n function startHoax(address msgSender, address origin) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.startPrank(msgSender, origin);\n }\n\n function startHoax(address msgSender, address origin, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.startPrank(msgSender, origin);\n }\n\n function changePrank(address msgSender) internal virtual {\n vm.stopPrank();\n vm.startPrank(msgSender);\n }\n\n function changePrank(address msgSender, address txOrigin) internal virtual {\n vm.stopPrank();\n vm.startPrank(msgSender, txOrigin);\n }\n\n // The same as Vm's `deal`\n // Use the alternative signature for ERC20 tokens\n function deal(address to, uint256 give) internal virtual {\n vm.deal(to, give);\n }\n\n // Set the balance of an account for any ERC20 token\n // Use the alternative signature to update `totalSupply`\n function deal(address token, address to, uint256 give) internal virtual {\n deal(token, to, give, false);\n }\n\n // Set the balance of an account for any ERC1155 token\n // Use the alternative signature to update `totalSupply`\n function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {\n dealERC1155(token, to, id, give, false);\n }\n\n function deal(address token, address to, uint256 give, bool adjust) internal virtual {\n // get current balance\n (, bytes memory balData) = token.call(abi.encodeWithSelector(0x70a08231, to));\n uint256 prevBal = abi.decode(balData, (uint256));\n\n // update balance\n stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);\n\n // update total supply\n if (adjust) {\n (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0x18160ddd));\n uint256 totSup = abi.decode(totSupData, (uint256));\n if (give < prevBal) {\n totSup -= (prevBal - give);\n } else {\n totSup += (give - prevBal);\n }\n stdstore.target(token).sig(0x18160ddd).checked_write(totSup);\n }\n }\n\n function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {\n // get current balance\n (, bytes memory balData) = token.call(abi.encodeWithSelector(0x00fdd58e, to, id));\n uint256 prevBal = abi.decode(balData, (uint256));\n\n // update balance\n stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);\n\n // update total supply\n if (adjust) {\n (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0xbd85b039, id));\n require(\n totSupData.length != 0,\n \"StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply.\"\n );\n uint256 totSup = abi.decode(totSupData, (uint256));\n if (give < prevBal) {\n totSup -= (prevBal - give);\n } else {\n totSup += (give - prevBal);\n }\n stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);\n }\n }\n\n function dealERC721(address token, address to, uint256 id) internal virtual {\n // check if token id is already minted and the actual owner.\n (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));\n require(successMinted, \"StdCheats deal(address,address,uint,bool): id not minted.\");\n\n // get owner current balance\n (, bytes memory fromBalData) = token.call(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));\n uint256 fromPrevBal = abi.decode(fromBalData, (uint256));\n\n // get new user current balance\n (, bytes memory toBalData) = token.call(abi.encodeWithSelector(0x70a08231, to));\n uint256 toPrevBal = abi.decode(toBalData, (uint256));\n\n // update balances\n stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);\n stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);\n\n // update owner\n stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);\n }\n}\n" - }, - "node_modules/forge-std/src/StdError.sol": { - "content": "// SPDX-License-Identifier: MIT\n// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdError {\n bytes public constant assertionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x01);\n bytes public constant arithmeticError = abi.encodeWithSignature(\"Panic(uint256)\", 0x11);\n bytes public constant divisionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x12);\n bytes public constant enumConversionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x21);\n bytes public constant encodeStorageError = abi.encodeWithSignature(\"Panic(uint256)\", 0x22);\n bytes public constant popError = abi.encodeWithSignature(\"Panic(uint256)\", 0x31);\n bytes public constant indexOOBError = abi.encodeWithSignature(\"Panic(uint256)\", 0x32);\n bytes public constant memOverflowError = abi.encodeWithSignature(\"Panic(uint256)\", 0x41);\n bytes public constant zeroVarError = abi.encodeWithSignature(\"Panic(uint256)\", 0x51);\n}\n" - }, - "node_modules/forge-std/src/StdInvariant.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\ncontract StdInvariant {\n struct FuzzSelector {\n address addr;\n bytes4[] selectors;\n }\n\n address[] private _excludedContracts;\n address[] private _excludedSenders;\n address[] private _targetedContracts;\n address[] private _targetedSenders;\n\n string[] private _excludedArtifacts;\n string[] private _targetedArtifacts;\n\n FuzzSelector[] private _targetedArtifactSelectors;\n FuzzSelector[] private _targetedSelectors;\n\n // Functions for users:\n // These are intended to be called in tests.\n\n function excludeContract(address newExcludedContract_) internal {\n _excludedContracts.push(newExcludedContract_);\n }\n\n function excludeSender(address newExcludedSender_) internal {\n _excludedSenders.push(newExcludedSender_);\n }\n\n function excludeArtifact(string memory newExcludedArtifact_) internal {\n _excludedArtifacts.push(newExcludedArtifact_);\n }\n\n function targetArtifact(string memory newTargetedArtifact_) internal {\n _targetedArtifacts.push(newTargetedArtifact_);\n }\n\n function targetArtifactSelector(FuzzSelector memory newTargetedArtifactSelector_) internal {\n _targetedArtifactSelectors.push(newTargetedArtifactSelector_);\n }\n\n function targetContract(address newTargetedContract_) internal {\n _targetedContracts.push(newTargetedContract_);\n }\n\n function targetSelector(FuzzSelector memory newTargetedSelector_) internal {\n _targetedSelectors.push(newTargetedSelector_);\n }\n\n function targetSender(address newTargetedSender_) internal {\n _targetedSenders.push(newTargetedSender_);\n }\n\n // Functions for forge:\n // These are called by forge to run invariant tests and don't need to be called in tests.\n\n function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) {\n excludedArtifacts_ = _excludedArtifacts;\n }\n\n function excludeContracts() public view returns (address[] memory excludedContracts_) {\n excludedContracts_ = _excludedContracts;\n }\n\n function excludeSenders() public view returns (address[] memory excludedSenders_) {\n excludedSenders_ = _excludedSenders;\n }\n\n function targetArtifacts() public view returns (string[] memory targetedArtifacts_) {\n targetedArtifacts_ = _targetedArtifacts;\n }\n\n function targetArtifactSelectors() public view returns (FuzzSelector[] memory targetedArtifactSelectors_) {\n targetedArtifactSelectors_ = _targetedArtifactSelectors;\n }\n\n function targetContracts() public view returns (address[] memory targetedContracts_) {\n targetedContracts_ = _targetedContracts;\n }\n\n function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) {\n targetedSelectors_ = _targetedSelectors;\n }\n\n function targetSenders() public view returns (address[] memory targetedSenders_) {\n targetedSenders_ = _targetedSenders;\n }\n}\n" - }, - "node_modules/forge-std/src/StdJson.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n// Helpers for parsing and writing JSON files\n// To parse:\n// ```\n// using stdJson for string;\n// string memory json = vm.readFile(\"some_peth\");\n// json.parseUint(\"\");\n// ```\n// To write:\n// ```\n// using stdJson for string;\n// string memory json = \"deploymentArtifact\";\n// Contract contract = new Contract();\n// json.serialize(\"contractAddress\", address(contract));\n// json = json.serialize(\"deploymentTimes\", uint(1));\n// // store the stringified JSON to the 'json' variable we have been using as a key\n// // as we won't need it any longer\n// string memory json2 = \"finalArtifact\";\n// string memory final = json2.serialize(\"depArtifact\", json);\n// final.write(\"\");\n// ```\n\nlibrary stdJson {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {\n return vm.parseJson(json, key);\n }\n\n function readUint(string memory json, string memory key) internal returns (uint256) {\n return vm.parseJsonUint(json, key);\n }\n\n function readUintArray(string memory json, string memory key) internal returns (uint256[] memory) {\n return vm.parseJsonUintArray(json, key);\n }\n\n function readInt(string memory json, string memory key) internal returns (int256) {\n return vm.parseJsonInt(json, key);\n }\n\n function readIntArray(string memory json, string memory key) internal returns (int256[] memory) {\n return vm.parseJsonIntArray(json, key);\n }\n\n function readBytes32(string memory json, string memory key) internal returns (bytes32) {\n return vm.parseJsonBytes32(json, key);\n }\n\n function readBytes32Array(string memory json, string memory key) internal returns (bytes32[] memory) {\n return vm.parseJsonBytes32Array(json, key);\n }\n\n function readString(string memory json, string memory key) internal returns (string memory) {\n return vm.parseJsonString(json, key);\n }\n\n function readStringArray(string memory json, string memory key) internal returns (string[] memory) {\n return vm.parseJsonStringArray(json, key);\n }\n\n function readAddress(string memory json, string memory key) internal returns (address) {\n return vm.parseJsonAddress(json, key);\n }\n\n function readAddressArray(string memory json, string memory key) internal returns (address[] memory) {\n return vm.parseJsonAddressArray(json, key);\n }\n\n function readBool(string memory json, string memory key) internal returns (bool) {\n return vm.parseJsonBool(json, key);\n }\n\n function readBoolArray(string memory json, string memory key) internal returns (bool[] memory) {\n return vm.parseJsonBoolArray(json, key);\n }\n\n function readBytes(string memory json, string memory key) internal returns (bytes memory) {\n return vm.parseJsonBytes(json, key);\n }\n\n function readBytesArray(string memory json, string memory key) internal returns (bytes[] memory) {\n return vm.parseJsonBytesArray(json, key);\n }\n\n function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bool[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function write(string memory jsonKey, string memory path) internal {\n vm.writeJson(jsonKey, path);\n }\n\n function write(string memory jsonKey, string memory path, string memory valueKey) internal {\n vm.writeJson(jsonKey, path, valueKey);\n }\n}\n" - }, - "node_modules/forge-std/src/StdMath.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdMath {\n int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;\n\n function abs(int256 a) internal pure returns (uint256) {\n // Required or it will fail when `a = type(int256).min`\n if (a == INT256_MIN) {\n return 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n }\n\n return uint256(a > 0 ? a : -a);\n }\n\n function delta(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a - b : b - a;\n }\n\n function delta(int256 a, int256 b) internal pure returns (uint256) {\n // a and b are of the same sign\n // this works thanks to two's complement, the left-most bit is the sign bit\n if ((a ^ b) > -1) {\n return delta(abs(a), abs(b));\n }\n\n // a and b are of opposite signs\n return abs(a) + abs(b);\n }\n\n function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n\n return absDelta * 1e18 / b;\n }\n\n function percentDelta(int256 a, int256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n uint256 absB = abs(b);\n\n return absDelta * 1e18 / absB;\n }\n}\n" - }, - "node_modules/forge-std/src/StdStorage.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {Vm} from \"./Vm.sol\";\n\nstruct StdStorage {\n mapping(address => mapping(bytes4 => mapping(bytes32 => uint256))) slots;\n mapping(address => mapping(bytes4 => mapping(bytes32 => bool))) finds;\n bytes32[] _keys;\n bytes4 _sig;\n uint256 _depth;\n address _target;\n bytes32 _set;\n}\n\nlibrary stdStorageSafe {\n event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);\n event WARNING_UninitedSlot(address who, uint256 slot);\n\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return bytes4(keccak256(bytes(sigStr)));\n }\n\n /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against\n // slot complexity:\n // if flat, will be bytes32(uint256(uint));\n // if map, will be keccak256(abi.encode(key, uint(slot)));\n // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));\n // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);\n function find(StdStorage storage self) internal returns (uint256) {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n // calldata to test against\n if (self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n vm.record();\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n (bytes32[] memory reads,) = vm.accesses(address(who));\n if (reads.length == 1) {\n bytes32 curr = vm.load(who, reads[0]);\n if (curr == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[0]));\n }\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[0]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[0]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n } else if (reads.length > 1) {\n for (uint256 i = 0; i < reads.length; i++) {\n bytes32 prev = vm.load(who, reads[i]);\n if (prev == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[i]));\n }\n // store\n vm.store(who, reads[i], bytes32(hex\"1337\"));\n bool success;\n bytes memory rdat;\n {\n (success, rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n if (success && fdat == bytes32(hex\"1337\")) {\n // we found which of the slots is the actual one\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[i]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[i]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n vm.store(who, reads[i], prev);\n break;\n }\n vm.store(who, reads[i], prev);\n }\n } else {\n revert(\"stdStorage find(StdStorage): No storage use detected for target.\");\n }\n\n require(\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))],\n \"stdStorage find(StdStorage): Slot(s) not found.\"\n );\n\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n self._target = _target;\n return self;\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n self._sig = _sig;\n return self;\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n self._sig = sigs(_sig);\n return self;\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n self._keys.push(bytes32(uint256(uint160(who))));\n return self;\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n self._keys.push(bytes32(amt));\n return self;\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n self._keys.push(key);\n return self;\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n self._depth = _depth;\n return self;\n }\n\n function read(StdStorage storage self) private returns (bytes memory) {\n address t = self._target;\n uint256 s = find(self);\n return abi.encode(vm.load(t, bytes32(s)));\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return abi.decode(read(self), (bytes32));\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n int256 v = read_int(self);\n if (v == 0) return false;\n if (v == 1) return true;\n revert(\"stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.\");\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return abi.decode(read(self), (address));\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return abi.decode(read(self), (uint256));\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return abi.decode(read(self), (int256));\n }\n\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n\nlibrary stdStorage {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return stdStorageSafe.sigs(sigStr);\n }\n\n function find(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.find(self);\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n return stdStorageSafe.target(self, _target);\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, who);\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, amt);\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, key);\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n return stdStorageSafe.depth(self, _depth);\n }\n\n function checked_write(StdStorage storage self, address who) internal {\n checked_write(self, bytes32(uint256(uint160(who))));\n }\n\n function checked_write(StdStorage storage self, uint256 amt) internal {\n checked_write(self, bytes32(amt));\n }\n\n function checked_write(StdStorage storage self, bool write) internal {\n bytes32 t;\n /// @solidity memory-safe-assembly\n assembly {\n t := write\n }\n checked_write(self, t);\n }\n\n function checked_write(StdStorage storage self, bytes32 set) internal {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n if (!self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n find(self);\n }\n bytes32 slot = bytes32(self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]);\n\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n bytes32 curr = vm.load(who, slot);\n\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n vm.store(who, slot, set);\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return stdStorageSafe.read_bytes32(self);\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n return stdStorageSafe.read_bool(self);\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return stdStorageSafe.read_address(self);\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.read_uint(self);\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return stdStorageSafe.read_int(self);\n }\n\n // Private function so needs to be copied over\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n // Private function so needs to be copied over\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n" - }, - "node_modules/forge-std/src/StdStyle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nimport {Vm} from \"./Vm.sol\";\n\nlibrary StdStyle {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n string constant RED = \"\\u001b[91m\";\n string constant GREEN = \"\\u001b[92m\";\n string constant YELLOW = \"\\u001b[93m\";\n string constant BLUE = \"\\u001b[94m\";\n string constant MAGENTA = \"\\u001b[95m\";\n string constant CYAN = \"\\u001b[96m\";\n string constant BOLD = \"\\u001b[1m\";\n string constant DIM = \"\\u001b[2m\";\n string constant ITALIC = \"\\u001b[3m\";\n string constant UNDERLINE = \"\\u001b[4m\";\n string constant INVERSE = \"\\u001b[7m\";\n string constant RESET = \"\\u001b[0m\";\n\n function styleConcat(string memory style, string memory self) private pure returns (string memory) {\n return string(abi.encodePacked(style, self, RESET));\n }\n\n function red(string memory self) internal pure returns (string memory) {\n return styleConcat(RED, self);\n }\n\n function red(uint256 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(int256 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(address self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(bool self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function redBytes(bytes memory self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function redBytes32(bytes32 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function green(string memory self) internal pure returns (string memory) {\n return styleConcat(GREEN, self);\n }\n\n function green(uint256 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(int256 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(address self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(bool self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function greenBytes(bytes memory self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function greenBytes32(bytes32 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function yellow(string memory self) internal pure returns (string memory) {\n return styleConcat(YELLOW, self);\n }\n\n function yellow(uint256 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(int256 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(address self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(bool self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellowBytes(bytes memory self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellowBytes32(bytes32 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function blue(string memory self) internal pure returns (string memory) {\n return styleConcat(BLUE, self);\n }\n\n function blue(uint256 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(int256 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(address self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(bool self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blueBytes(bytes memory self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blueBytes32(bytes32 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function magenta(string memory self) internal pure returns (string memory) {\n return styleConcat(MAGENTA, self);\n }\n\n function magenta(uint256 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(int256 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(address self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(bool self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magentaBytes(bytes memory self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magentaBytes32(bytes32 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function cyan(string memory self) internal pure returns (string memory) {\n return styleConcat(CYAN, self);\n }\n\n function cyan(uint256 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(int256 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(address self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(bool self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyanBytes(bytes memory self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyanBytes32(bytes32 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function bold(string memory self) internal pure returns (string memory) {\n return styleConcat(BOLD, self);\n }\n\n function bold(uint256 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(int256 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(address self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(bool self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function boldBytes(bytes memory self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function boldBytes32(bytes32 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function dim(string memory self) internal pure returns (string memory) {\n return styleConcat(DIM, self);\n }\n\n function dim(uint256 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(int256 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(address self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(bool self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dimBytes(bytes memory self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dimBytes32(bytes32 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function italic(string memory self) internal pure returns (string memory) {\n return styleConcat(ITALIC, self);\n }\n\n function italic(uint256 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(int256 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(address self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(bool self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italicBytes(bytes memory self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italicBytes32(bytes32 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function underline(string memory self) internal pure returns (string memory) {\n return styleConcat(UNDERLINE, self);\n }\n\n function underline(uint256 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(int256 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(address self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(bool self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underlineBytes(bytes memory self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underlineBytes32(bytes32 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function inverse(string memory self) internal pure returns (string memory) {\n return styleConcat(INVERSE, self);\n }\n\n function inverse(uint256 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(int256 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(address self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(bool self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverseBytes(bytes memory self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverseBytes32(bytes32 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n}\n" - }, - "node_modules/forge-std/src/StdUtils.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {IMulticall3} from \"./interfaces/IMulticall3.sol\";\n// TODO Remove import.\nimport {VmSafe} from \"./Vm.sol\";\n\nabstract contract StdUtils {\n /*//////////////////////////////////////////////////////////////////////////\n CONSTANTS\n //////////////////////////////////////////////////////////////////////////*/\n\n IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;\n uint256 private constant INT256_MIN_ABS =\n 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n uint256 private constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.\n address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;\n\n /*//////////////////////////////////////////////////////////////////////////\n INTERNAL FUNCTIONS\n //////////////////////////////////////////////////////////////////////////*/\n\n function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {\n require(min <= max, \"StdUtils bound(uint256,uint256,uint256): Max is less than min.\");\n // If x is between min and max, return x directly. This is to ensure that dictionary values\n // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188\n if (x >= min && x <= max) return x;\n\n uint256 size = max - min + 1;\n\n // If the value is 0, 1, 2, 3, warp that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.\n // This helps ensure coverage of the min/max values.\n if (x <= 3 && size > x) return min + x;\n if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);\n\n // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.\n if (x > max) {\n uint256 diff = x - max;\n uint256 rem = diff % size;\n if (rem == 0) return max;\n result = min + rem - 1;\n } else if (x < min) {\n uint256 diff = min - x;\n uint256 rem = diff % size;\n if (rem == 0) return min;\n result = max - rem + 1;\n }\n }\n\n function bound(uint256 x, uint256 min, uint256 max) internal view virtual returns (uint256 result) {\n result = _bound(x, min, max);\n console2_log(\"Bound Result\", result);\n }\n\n function bound(int256 x, int256 min, int256 max) internal view virtual returns (int256 result) {\n require(min <= max, \"StdUtils bound(int256,int256,int256): Max is less than min.\");\n\n // Shifting all int256 values to uint256 to use _bound function. The range of two types are:\n // int256 : -(2**255) ~ (2**255 - 1)\n // uint256: 0 ~ (2**256 - 1)\n // So, add 2**255, INT256_MIN_ABS to the integer values.\n //\n // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.\n // So, use `~uint256(x) + 1` instead.\n uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);\n uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);\n uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);\n\n uint256 y = _bound(_x, _min, _max);\n\n // To move it back to int256 value, subtract INT256_MIN_ABS at here.\n result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);\n console2_log(\"Bound result\", vm.toString(result));\n }\n\n function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {\n require(b.length <= 32, \"StdUtils bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce\n /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)\n function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {\n // forgefmt: disable-start\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))));\n if (nonce <= 0x7f) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))));\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= 2**8 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce))));\n if (nonce <= 2**16 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce))));\n if (nonce <= 2**24 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce))));\n // forgefmt: disable-end\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return addressFromLast20Bytes(\n keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce)))\n );\n }\n\n function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)\n internal\n pure\n virtual\n returns (address)\n {\n return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, initcodeHash)));\n }\n\n /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer\n function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {\n return computeCreate2Address(salt, initCodeHash, CREATE2_FACTORY);\n }\n\n /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments\n /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode\n function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {\n return hashInitCode(creationCode, \"\");\n }\n\n /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2\n /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode\n /// @param args the ABI-encoded arguments to the constructor of C\n function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(creationCode, args));\n }\n\n // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.\n function getTokenBalances(address token, address[] memory addresses)\n internal\n virtual\n returns (uint256[] memory balances)\n {\n uint256 tokenCodeSize;\n assembly {\n tokenCodeSize := extcodesize(token)\n }\n require(tokenCodeSize > 0, \"StdUtils getTokenBalances(address,address[]): Token address is not a contract.\");\n\n // ABI encode the aggregate call to Multicall3.\n uint256 length = addresses.length;\n IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);\n for (uint256 i = 0; i < length; ++i) {\n // 0x70a08231 = bytes4(\"balanceOf(address)\"))\n calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});\n }\n\n // Make the aggregate call.\n (, bytes[] memory returnData) = multicall.aggregate(calls);\n\n // ABI decode the return data and return the balances.\n balances = new uint256[](length);\n for (uint256 i = 0; i < length; ++i) {\n balances[i] = abi.decode(returnData[i], (uint256));\n }\n }\n\n /*//////////////////////////////////////////////////////////////////////////\n PRIVATE FUNCTIONS\n //////////////////////////////////////////////////////////////////////////*/\n\n function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.\n\n function console2_log(string memory p0, uint256 p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n status;\n }\n\n function console2_log(string memory p0, string memory p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n status;\n }\n}\n" - }, - "node_modules/forge-std/src/Test.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\n// 💬 ABOUT\n// Standard Library's default Test\n\n// 🧩 MODULES\nimport {console} from \"./console.sol\";\nimport {console2} from \"./console2.sol\";\nimport {StdAssertions} from \"./StdAssertions.sol\";\nimport {StdChains} from \"./StdChains.sol\";\nimport {StdCheats} from \"./StdCheats.sol\";\nimport {stdError} from \"./StdError.sol\";\nimport {StdInvariant} from \"./StdInvariant.sol\";\nimport {stdJson} from \"./StdJson.sol\";\nimport {stdMath} from \"./StdMath.sol\";\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {StdUtils} from \"./StdUtils.sol\";\nimport {Vm} from \"./Vm.sol\";\nimport {StdStyle} from \"./StdStyle.sol\";\n\n// 📦 BOILERPLATE\nimport {TestBase} from \"./Base.sol\";\nimport {DSTest} from \"ds-test/test.sol\";\n\n// ⭐️ TEST\nabstract contract Test is DSTest, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils, TestBase {\n// Note: IS_TEST() must return true.\n// Note: Must have failure system, https://github.com/dapphub/ds-test/blob/cd98eff28324bfac652e63a239a60632a761790b/src/test.sol#L39-L76.\n}\n" - }, - "node_modules/forge-std/src/Vm.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\n// Cheatcodes are marked as view/pure/none using the following rules:\n// 0. A call's observable behaviour includes its return value, logs, reverts and state writes,\n// 1. If you can influence a later call's observable behaviour, you're neither `view` nor `pure (you are modifying some state be it the EVM, interpreter, filesystem, etc),\n// 2. Otherwise if you can be influenced by an earlier call, or if reading some state, you're `view`,\n// 3. Otherwise you're `pure`.\n\ninterface VmSafe {\n struct Log {\n bytes32[] topics;\n bytes data;\n address emitter;\n }\n\n struct Rpc {\n string key;\n string url;\n }\n\n struct FsMetadata {\n bool isDir;\n bool isSymlink;\n uint256 length;\n bool readOnly;\n uint256 modified;\n uint256 accessed;\n uint256 created;\n }\n\n // Loads a storage slot from an address\n function load(address target, bytes32 slot) external view returns (bytes32 data);\n // Signs data\n function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);\n // Gets the address for a given private key\n function addr(uint256 privateKey) external pure returns (address keyAddr);\n // Gets the nonce of an account\n function getNonce(address account) external view returns (uint64 nonce);\n // Performs a foreign function call via the terminal\n function ffi(string[] calldata commandInput) external returns (bytes memory result);\n // Sets environment variables\n function setEnv(string calldata name, string calldata value) external;\n // Reads environment variables, (name) => (value)\n function envBool(string calldata name) external view returns (bool value);\n function envUint(string calldata name) external view returns (uint256 value);\n function envInt(string calldata name) external view returns (int256 value);\n function envAddress(string calldata name) external view returns (address value);\n function envBytes32(string calldata name) external view returns (bytes32 value);\n function envString(string calldata name) external view returns (string memory value);\n function envBytes(string calldata name) external view returns (bytes memory value);\n // Reads environment variables as arrays\n function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);\n function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);\n function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);\n function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);\n function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);\n function envString(string calldata name, string calldata delim) external view returns (string[] memory value);\n function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);\n // Read environment variables with default value\n function envOr(string calldata name, bool defaultValue) external returns (bool value);\n function envOr(string calldata name, uint256 defaultValue) external returns (uint256 value);\n function envOr(string calldata name, int256 defaultValue) external returns (int256 value);\n function envOr(string calldata name, address defaultValue) external returns (address value);\n function envOr(string calldata name, bytes32 defaultValue) external returns (bytes32 value);\n function envOr(string calldata name, string calldata defaultValue) external returns (string memory value);\n function envOr(string calldata name, bytes calldata defaultValue) external returns (bytes memory value);\n // Read environment variables as arrays with default value\n function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)\n external\n returns (bool[] memory value);\n function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)\n external\n returns (uint256[] memory value);\n function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)\n external\n returns (int256[] memory value);\n function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)\n external\n returns (address[] memory value);\n function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)\n external\n returns (bytes32[] memory value);\n function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)\n external\n returns (string[] memory value);\n function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)\n external\n returns (bytes[] memory value);\n // Records all storage reads and writes\n function record() external;\n // Gets all accessed reads and write slot from a recording session, for a given address\n function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);\n // Gets the _creation_ bytecode from an artifact file. Takes in the relative path to the json file\n function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);\n // Gets the _deployed_ bytecode from an artifact file. Takes in the relative path to the json file\n function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);\n // Labels an address in call traces\n function label(address account, string calldata newLabel) external;\n // Using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain\n function broadcast() external;\n // Has the next call (at this call depth only) create a transaction with the address provided as the sender that can later be signed and sent onchain\n function broadcast(address signer) external;\n // Has the next call (at this call depth only) create a transaction with the private key provided as the sender that can later be signed and sent onchain\n function broadcast(uint256 privateKey) external;\n // Using the address that calls the test contract, has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain\n function startBroadcast() external;\n // Has all subsequent calls (at this call depth only) create transactions with the address provided that can later be signed and sent onchain\n function startBroadcast(address signer) external;\n // Has all subsequent calls (at this call depth only) create transactions with the private key provided that can later be signed and sent onchain\n function startBroadcast(uint256 privateKey) external;\n // Stops collecting onchain transactions\n function stopBroadcast() external;\n // Reads the entire content of file to string\n function readFile(string calldata path) external view returns (string memory data);\n // Reads the entire content of file as binary. Path is relative to the project root.\n function readFileBinary(string calldata path) external view returns (bytes memory data);\n // Get the path of the current project root\n function projectRoot() external view returns (string memory path);\n // Get the metadata for a file/directory\n function fsMetadata(string calldata fileOrDir) external returns (FsMetadata memory metadata);\n // Reads next line of file to string\n function readLine(string calldata path) external view returns (string memory line);\n // Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.\n function writeFile(string calldata path, string calldata data) external;\n // Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.\n // Path is relative to the project root.\n function writeFileBinary(string calldata path, bytes calldata data) external;\n // Writes line to file, creating a file if it does not exist.\n function writeLine(string calldata path, string calldata data) external;\n // Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.\n function closeFile(string calldata path) external;\n // Removes file. This cheatcode will revert in the following situations, but is not limited to just these cases:\n // - Path points to a directory.\n // - The file doesn't exist.\n // - The user lacks permissions to remove the file.\n function removeFile(string calldata path) external;\n // Convert values to a string\n function toString(address value) external pure returns (string memory stringifiedValue);\n function toString(bytes calldata value) external pure returns (string memory stringifiedValue);\n function toString(bytes32 value) external pure returns (string memory stringifiedValue);\n function toString(bool value) external pure returns (string memory stringifiedValue);\n function toString(uint256 value) external pure returns (string memory stringifiedValue);\n function toString(int256 value) external pure returns (string memory stringifiedValue);\n // Convert values from a string\n function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);\n function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);\n function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);\n function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);\n function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);\n function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);\n // Record all the transaction logs\n function recordLogs() external;\n // Gets all the recorded logs\n function getRecordedLogs() external returns (Log[] memory logs);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path m/44'/60'/0'/0/{index}\n function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at {derivationPath}{index}\n function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)\n external\n pure\n returns (uint256 privateKey);\n // Adds a private key to the local forge wallet and returns the address\n function rememberKey(uint256 privateKey) external returns (address keyAddr);\n //\n // parseJson\n //\n // ----\n // In case the returned value is a JSON object, it's encoded as a ABI-encoded tuple. As JSON objects\n // don't have the notion of ordered, but tuples do, they JSON object is encoded with it's fields ordered in\n // ALPHABETICAL order. That means that in order to successfully decode the tuple, we need to define a tuple that\n // encodes the fields in the same order, which is alphabetical. In the case of Solidity structs, they are encoded\n // as tuples, with the attributes in the order in which they are defined.\n // For example: json = { 'a': 1, 'b': 0xa4tb......3xs}\n // a: uint256\n // b: address\n // To decode that json, we need to define a struct or a tuple as follows:\n // struct json = { uint256 a; address b; }\n // If we defined a json struct with the opposite order, meaning placing the address b first, it would try to\n // decode the tuple in that order, and thus fail.\n // ----\n // Given a string of JSON, return it as ABI-encoded\n function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);\n function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);\n\n // The following parseJson cheatcodes will do type coercion, for the type that they indicate.\n // For example, parseJsonUint will coerce all values to a uint256. That includes stringified numbers '12'\n // and hex numbers '0xEF'.\n // Type coercion works ONLY for discrete values or arrays. That means that the key must return a value or array, not\n // a JSON object.\n function parseJsonUint(string calldata, string calldata) external returns (uint256);\n function parseJsonUintArray(string calldata, string calldata) external returns (uint256[] memory);\n function parseJsonInt(string calldata, string calldata) external returns (int256);\n function parseJsonIntArray(string calldata, string calldata) external returns (int256[] memory);\n function parseJsonBool(string calldata, string calldata) external returns (bool);\n function parseJsonBoolArray(string calldata, string calldata) external returns (bool[] memory);\n function parseJsonAddress(string calldata, string calldata) external returns (address);\n function parseJsonAddressArray(string calldata, string calldata) external returns (address[] memory);\n function parseJsonString(string calldata, string calldata) external returns (string memory);\n function parseJsonStringArray(string calldata, string calldata) external returns (string[] memory);\n function parseJsonBytes(string calldata, string calldata) external returns (bytes memory);\n function parseJsonBytesArray(string calldata, string calldata) external returns (bytes[] memory);\n function parseJsonBytes32(string calldata, string calldata) external returns (bytes32);\n function parseJsonBytes32Array(string calldata, string calldata) external returns (bytes32[] memory);\n\n // Serialize a key and value to a JSON object stored in-memory that can be later written to a file\n // It returns the stringified version of the specific JSON file up to that moment.\n function serializeBool(string calldata objectKey, string calldata valueKey, bool value)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address value)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)\n external\n returns (string memory json);\n\n function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)\n external\n returns (string memory json);\n\n //\n // writeJson\n //\n // ----\n // Write a serialized JSON object to a file. If the file exists, it will be overwritten.\n // Let's assume we want to write the following JSON to a file:\n //\n // { \"boolean\": true, \"number\": 342, \"object\": { \"title\": \"finally json serialization\" } }\n //\n // ```\n // string memory json1 = \"some key\";\n // vm.serializeBool(json1, \"boolean\", true);\n // vm.serializeBool(json1, \"number\", uint256(342));\n // json2 = \"some other key\";\n // string memory output = vm.serializeString(json2, \"title\", \"finally json serialization\");\n // string memory finalJson = vm.serialize(json1, \"object\", output);\n // vm.writeJson(finalJson, \"./output/example.json\");\n // ```\n // The critical insight is that every invocation of serialization will return the stringified version of the JSON\n // up to that point. That means we can construct arbitrary JSON objects and then use the return stringified version\n // to serialize them as values to another JSON object.\n //\n // json1 and json2 are simply keys used by the backend to keep track of the objects. So vm.serializeJson(json1,..)\n // will find the object in-memory that is keyed by \"some key\".\n function writeJson(string calldata json, string calldata path) external;\n // Write a serialized JSON object to an **existing** JSON file, replacing a value with key = \n // This is useful to replace a specific value of a JSON file, without having to parse the entire thing\n function writeJson(string calldata json, string calldata path, string calldata valueKey) external;\n // Returns the RPC url for the given alias\n function rpcUrl(string calldata rpcAlias) external view returns (string memory json);\n // Returns all rpc urls and their aliases `[alias, url][]`\n function rpcUrls() external view returns (string[2][] memory urls);\n // Returns all rpc urls and their aliases as structs.\n function rpcUrlStructs() external view returns (Rpc[] memory urls);\n // If the condition is false, discard this run's fuzz inputs and generate new ones.\n function assume(bool condition) external pure;\n // Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.\n function pauseGasMetering() external;\n // Resumes gas metering (i.e. gas usage is counted again). Noop if already on.\n function resumeGasMetering() external;\n}\n\ninterface Vm is VmSafe {\n // Sets block.timestamp\n function warp(uint256 newTimestamp) external;\n // Sets block.height\n function roll(uint256 newHeight) external;\n // Sets block.basefee\n function fee(uint256 newBasefee) external;\n // Sets block.difficulty\n function difficulty(uint256 newDifficulty) external;\n // Sets block.chainid\n function chainId(uint256 newChainId) external;\n // Stores a value to an address' storage slot.\n function store(address target, bytes32 slot, bytes32 value) external;\n // Sets the nonce of an account; must be higher than the current nonce of the account\n function setNonce(address account, uint64 newNonce) external;\n // Sets the *next* call's msg.sender to be the input address\n function prank(address msgSender) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called\n function startPrank(address msgSender) external;\n // Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input\n function prank(address msgSender, address txOrigin) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input\n function startPrank(address msgSender, address txOrigin) external;\n // Resets subsequent calls' msg.sender to be `address(this)`\n function stopPrank() external;\n // Sets an address' balance\n function deal(address account, uint256 newBalance) external;\n // Sets an address' code\n function etch(address target, bytes calldata newRuntimeBytecode) external;\n // Expects an error on next call\n function expectRevert(bytes calldata revertData) external;\n function expectRevert(bytes4 revertData) external;\n function expectRevert() external;\n\n // Prepare an expected log with all four checks enabled.\n // Call this function, then emit an event, then call a function. Internally after the call, we check if\n // logs were emitted in the expected order with the expected topics and data.\n // Second form also checks supplied address against emitting contract.\n function expectEmit() external;\n function expectEmit(address emitter) external;\n\n // Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData).\n // Call this function, then emit an event, then call a function. Internally after the call, we check if\n // logs were emitted in the expected order with the expected topics and data (as specified by the booleans).\n // Second form also checks supplied address against emitting contract.\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)\n external;\n\n // Mocks a call to an address, returning specified data.\n // Calldata can either be strict or a partial match, e.g. if you only\n // pass a Solidity selector to the expected calldata, then the entire Solidity\n // function will be mocked.\n function mockCall(address callee, bytes calldata data, bytes calldata returnData) external;\n // Mocks a call to an address with a specific msg.value, returning specified data.\n // Calldata match takes precedence over msg.value in case of ambiguity.\n function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external;\n // Clears all mocked calls\n function clearMockedCalls() external;\n // Expects a call to an address with the specified calldata.\n // Calldata can either be a strict or a partial match\n function expectCall(address callee, bytes calldata data) external;\n // Expects a call to an address with the specified msg.value and calldata\n function expectCall(address callee, uint256 msgValue, bytes calldata data) external;\n // Expect a call to an address with the specified msg.value, gas, and calldata.\n function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external;\n // Expect a call to an address with the specified msg.value and calldata, and a *minimum* amount of gas.\n function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external;\n // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other\n // memory is written to, the test will fail. Can be called multiple times to add more ranges to the set.\n function expectSafeMemory(uint64 min, uint64 max) external;\n // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext.\n // If any other memory is written to, the test will fail. Can be called multiple times to add more ranges\n // to the set.\n function expectSafeMemoryCall(uint64 min, uint64 max) external;\n // Sets block.coinbase\n function coinbase(address newCoinbase) external;\n // Snapshot the current state of the evm.\n // Returns the id of the snapshot that was created.\n // To revert a snapshot use `revertTo`\n function snapshot() external returns (uint256 snapshotId);\n // Revert the state of the EVM to a previous snapshot\n // Takes the snapshot id to revert to.\n // This deletes the snapshot and all snapshots taken after the given snapshot id.\n function revertTo(uint256 snapshotId) external returns (bool success);\n // Creates a new fork with the given endpoint and block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before the transaction,\n // and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates _and_ also selects new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before\n // the transaction, returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.\n function selectFork(uint256 forkId) external;\n /// Returns the identifier of the currently active fork. Reverts if no fork is currently active.\n function activeFork() external view returns (uint256 forkId);\n // Updates the currently active fork to given block number\n // This is similar to `roll` but for the currently active fork\n function rollFork(uint256 blockNumber) external;\n // Updates the currently active fork to given transaction\n // this will `rollFork` with the number of the block the transaction was mined in and replays all transaction mined before it in the block\n function rollFork(bytes32 txHash) external;\n // Updates the given fork to given block number\n function rollFork(uint256 forkId, uint256 blockNumber) external;\n // Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block\n function rollFork(uint256 forkId, bytes32 txHash) external;\n // Marks that the account(s) should use persistent storage across fork swaps in a multifork setup\n // Meaning, changes made to the state of this account will be kept when switching forks\n function makePersistent(address account) external;\n function makePersistent(address account0, address account1) external;\n function makePersistent(address account0, address account1, address account2) external;\n function makePersistent(address[] calldata accounts) external;\n // Revokes persistent status from the address, previously added via `makePersistent`\n function revokePersistent(address account) external;\n function revokePersistent(address[] calldata accounts) external;\n // Returns true if the account is marked as persistent\n function isPersistent(address account) external view returns (bool persistent);\n // In forking mode, explicitly grant the given address cheatcode access\n function allowCheatcodes(address account) external;\n // Fetches the given transaction from the active fork and executes it on the current state\n function transact(bytes32 txHash) external;\n // Fetches the given transaction from the given fork and executes it on the current state\n function transact(uint256 forkId, bytes32 txHash) external;\n}\n" - }, - "node_modules/forge-std/src/console.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nlibrary console {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int)\", p0));\n }\n\n function logUint(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint)\", p0, p1));\n }\n\n function log(uint p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string)\", p0, p1));\n }\n\n function log(uint p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool)\", p0, p1));\n }\n\n function log(uint p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address)\", p0, p1));\n }\n\n function log(string memory p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - }, - "node_modules/forge-std/src/console2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\n/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should\n/// use `int256` and `uint256`. This modified version fixes that. This version is recommended\n/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in\n/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.\n/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178\nlibrary console2 {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function logUint(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function log(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint256 p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256)\", p0, p1));\n }\n\n function log(uint256 p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string)\", p0, p1));\n }\n\n function log(uint256 p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool)\", p0, p1));\n }\n\n function log(uint256 p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address)\", p0, p1));\n }\n\n function log(string memory p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n }\n\n function log(string memory p0, int256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,int256)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - }, - "node_modules/forge-std/src/interfaces/IMulticall3.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\ninterface IMulticall3 {\n struct Call {\n address target;\n bytes callData;\n }\n\n struct Call3 {\n address target;\n bool allowFailure;\n bytes callData;\n }\n\n struct Call3Value {\n address target;\n bool allowFailure;\n uint256 value;\n bytes callData;\n }\n\n struct Result {\n bool success;\n bytes returnData;\n }\n\n function aggregate(Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes[] memory returnData);\n\n function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData);\n\n function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData);\n\n function blockAndAggregate(Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);\n\n function getBasefee() external view returns (uint256 basefee);\n\n function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash);\n\n function getBlockNumber() external view returns (uint256 blockNumber);\n\n function getChainId() external view returns (uint256 chainid);\n\n function getCurrentBlockCoinbase() external view returns (address coinbase);\n\n function getCurrentBlockDifficulty() external view returns (uint256 difficulty);\n\n function getCurrentBlockGasLimit() external view returns (uint256 gaslimit);\n\n function getCurrentBlockTimestamp() external view returns (uint256 timestamp);\n\n function getEthBalance(address addr) external view returns (uint256 balance);\n\n function getLastBlockHash() external view returns (bytes32 blockHash);\n\n function tryAggregate(bool requireSuccess, Call[] calldata calls)\n external\n payable\n returns (Result[] memory returnData);\n\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);\n}\n" - } - }, - "settings": { - "remappings": [ - "@openzeppelin/=node_modules/@openzeppelin/", - "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", - "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", - "@rari-capital/=node_modules/@rari-capital/", - "@rari-capital/solmate/=node_modules/@rari-capital/solmate/", - "ds-test/=node_modules/ds-test/src/", - "forge-std/=node_modules/forge-std/src/" - ], - "optimizer": { - "enabled": true, - "runs": 999999 - }, - "metadata": { - "bytecodeHash": "none" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "storageLayout", - "devdoc", - "userdoc" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/goerli/solcInputs/b86bd90311e4718458829d4a71bc5df9.json b/packages/contracts-bedrock/deployments/goerli/solcInputs/b86bd90311e4718458829d4a71bc5df9.json deleted file mode 100644 index 82819b8dc9ce..000000000000 --- a/packages/contracts-bedrock/deployments/goerli/solcInputs/b86bd90311e4718458829d4a71bc5df9.json +++ /dev/null @@ -1,552 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/L1/L1CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismPortal } from \"./OptimismPortal.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1CrossDomainMessenger\n * @notice The L1CrossDomainMessenger is a message passing interface between L1 and L2 responsible\n * for sending and receiving data on the L1 side. Users are encouraged to use this\n * interface instead of interacting with lower-level contracts directly.\n */\ncontract L1CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @notice Address of the OptimismPortal.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _portal Address of the OptimismPortal contract on this network.\n */\n constructor(OptimismPortal _portal)\n Semver(1, 1, 0)\n CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER)\n {\n PORTAL = _portal;\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n PORTAL.depositTransaction{ value: _value }(_to, _value, _gasLimit, false, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return msg.sender == address(PORTAL) && PORTAL.l2Sender() == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(PORTAL);\n }\n}\n" - }, - "contracts/L1/L1ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { L2ERC721Bridge } from \"../L2/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 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, 1, 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 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), \"L1ERC721Bridge: 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(OTHER_BRIDGE, message, _minGasLimit);\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L1/L1StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1StandardBridge\n * @notice The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L1, it will be escrowed within this\n * contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was\n * stored within this contract. After Bedrock, ETH is instead stored inside the\n * OptimismPortal contract.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L1StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a deposit of ETH from L1 into L2 is initiated.\n *\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of ETH deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ETHDepositInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal of ETH from L2 to L1 is finalized.\n *\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of ETH withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 withdrawal is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _messenger Address of the L1CrossDomainMessenger.\n */\n constructor(address payable _messenger)\n Semver(1, 1, 0)\n StandardBridge(_messenger, payable(Predeploys.L2_STANDARD_BRIDGE))\n {}\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n */\n receive() external payable override onlyEOA {\n _initiateETHDeposit(msg.sender, msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into the sender's account on L2.\n *\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETH(uint32 _minGasLimit, bytes calldata _extraData) external payable onlyEOA {\n _initiateETHDeposit(msg.sender, msg.sender, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into a target account on L2.\n * Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will\n * be locked in the L2StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n *\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable {\n _initiateETHDeposit(msg.sender, _to, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into the sender's account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20(\n address _l1Token,\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual onlyEOA {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into a target account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20To(\n address _l1Token,\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ETH from L2.\n *\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of ETH to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeETHWithdrawal(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable {\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ERC20 tokens from L2.\n *\n * @param _l1Token Address of the token on L1.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of the ERC20 to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeERC20Withdrawal(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external {\n finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L2 bridge contract.\n *\n * @return Address of the corresponding L2 bridge contract.\n */\n function l2TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @notice Internal function for initiating an ETH deposit.\n *\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateETHDeposit(\n address _from,\n address _to,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n _initiateBridgeETH(_from, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Internal function for initiating an ERC20 deposit.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateERC20Deposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n _initiateBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Emits the legacy ETHDepositInitiated event followed by the ETHBridgeInitiated event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ETHDepositInitiated(_from, _to, _amount, _extraData);\n super._emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ETHWithdrawalFinalized event followed by the ETHBridgeFinalized\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ETHWithdrawalFinalized(_from, _to, _amount, _extraData);\n super._emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ERC20DepositInitiated event followed by the ERC20BridgeInitiated\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ERC20DepositInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ERC20WithdrawalFinalized event followed by the ERC20BridgeFinalized\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ERC20WithdrawalFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/L1/L2OutputOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\n/**\n * @custom:proxied\n * @title L2OutputOracle\n * @notice The L2OutputOracle contains an array of L2 state outputs, where each output is a\n * commitment to the state of the L2 chain. Other contracts like the OptimismPortal use\n * these outputs to verify information about the state of L2.\n */\ncontract L2OutputOracle is Initializable, Semver {\n /**\n * @notice The interval in L2 blocks at which checkpoints must be submitted. Although this is\n * immutable, it can safely be modified by upgrading the implementation contract.\n */\n uint256 public immutable SUBMISSION_INTERVAL;\n\n /**\n * @notice The time between L2 blocks in seconds. Once set, this value MUST NOT be modified.\n */\n uint256 public immutable L2_BLOCK_TIME;\n\n /**\n * @notice The address of the challenger. Can be updated via upgrade.\n */\n address public immutable CHALLENGER;\n\n /**\n * @notice The address of the proposer. Can be updated via upgrade.\n */\n address public immutable PROPOSER;\n\n /**\n * @notice Minimum time (in seconds) that must elapse before a withdrawal can be finalized.\n */\n uint256 public immutable FINALIZATION_PERIOD_SECONDS;\n\n /**\n * @notice The number of the first L2 block recorded in this contract.\n */\n uint256 public startingBlockNumber;\n\n /**\n * @notice The timestamp of the first L2 block recorded in this contract.\n */\n uint256 public startingTimestamp;\n\n /**\n * @notice Array of L2 output proposals.\n */\n Types.OutputProposal[] internal l2Outputs;\n\n /**\n * @notice Emitted when an output is proposed.\n *\n * @param outputRoot The output root.\n * @param l2OutputIndex The index of the output in the l2Outputs array.\n * @param l2BlockNumber The L2 block number of the output root.\n * @param l1Timestamp The L1 timestamp when proposed.\n */\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n /**\n * @notice Emitted when outputs are deleted.\n *\n * @param prevNextOutputIndex Next L2 output index before the deletion.\n * @param newNextOutputIndex Next L2 output index after the deletion.\n */\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n /**\n * @custom:semver 1.2.0\n *\n * @param _submissionInterval Interval in blocks at which checkpoints must be submitted.\n * @param _l2BlockTime The time per L2 block, in seconds.\n * @param _startingBlockNumber The number of the first L2 block.\n * @param _startingTimestamp The timestamp of the first L2 block.\n * @param _proposer The address of the proposer.\n * @param _challenger The address of the challenger.\n */\n constructor(\n uint256 _submissionInterval,\n uint256 _l2BlockTime,\n uint256 _startingBlockNumber,\n uint256 _startingTimestamp,\n address _proposer,\n address _challenger,\n uint256 _finalizationPeriodSeconds\n ) Semver(1, 2, 0) {\n require(_l2BlockTime > 0, \"L2OutputOracle: L2 block time must be greater than 0\");\n require(\n _submissionInterval > _l2BlockTime,\n \"L2OutputOracle: submission interval must be greater than L2 block time\"\n );\n\n SUBMISSION_INTERVAL = _submissionInterval;\n L2_BLOCK_TIME = _l2BlockTime;\n PROPOSER = _proposer;\n CHALLENGER = _challenger;\n FINALIZATION_PERIOD_SECONDS = _finalizationPeriodSeconds;\n\n initialize(_startingBlockNumber, _startingTimestamp);\n }\n\n /**\n * @notice Initializer.\n *\n * @param _startingBlockNumber Block number for the first recoded L2 block.\n * @param _startingTimestamp Timestamp for the first recoded L2 block.\n */\n function initialize(uint256 _startingBlockNumber, uint256 _startingTimestamp)\n public\n initializer\n {\n require(\n _startingTimestamp <= block.timestamp,\n \"L2OutputOracle: starting L2 timestamp must be less than current time\"\n );\n\n startingTimestamp = _startingTimestamp;\n startingBlockNumber = _startingBlockNumber;\n }\n\n /**\n * @notice Deletes all output proposals after and including the proposal that corresponds to\n * the given output index. Only the challenger address can delete outputs.\n *\n * @param _l2OutputIndex Index of the first L2 output to be deleted. All outputs after this\n * output will also be deleted.\n */\n // solhint-disable-next-line ordering\n function deleteL2Outputs(uint256 _l2OutputIndex) external {\n require(\n msg.sender == CHALLENGER,\n \"L2OutputOracle: only the challenger address can delete outputs\"\n );\n\n // Make sure we're not *increasing* the length of the array.\n require(\n _l2OutputIndex < l2Outputs.length,\n \"L2OutputOracle: cannot delete outputs after the latest output index\"\n );\n\n // Do not allow deleting any outputs that have already been finalized.\n require(\n block.timestamp - l2Outputs[_l2OutputIndex].timestamp < FINALIZATION_PERIOD_SECONDS,\n \"L2OutputOracle: cannot delete outputs that have already been finalized\"\n );\n\n uint256 prevNextL2OutputIndex = nextOutputIndex();\n\n // Use assembly to delete the array elements because Solidity doesn't allow it.\n assembly {\n sstore(l2Outputs.slot, _l2OutputIndex)\n }\n\n emit OutputsDeleted(prevNextL2OutputIndex, _l2OutputIndex);\n }\n\n /**\n * @notice Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp\n * must be equal to the current value returned by `nextTimestamp()` in order to be\n * accepted. This function may only be called by the Proposer.\n *\n * @param _outputRoot The L2 output of the checkpoint block.\n * @param _l2BlockNumber The L2 block number that resulted in _outputRoot.\n * @param _l1BlockHash A block hash which must be included in the current chain.\n * @param _l1BlockNumber The block number with the specified block hash.\n */\n function proposeL2Output(\n bytes32 _outputRoot,\n uint256 _l2BlockNumber,\n bytes32 _l1BlockHash,\n uint256 _l1BlockNumber\n ) external payable {\n require(\n msg.sender == PROPOSER,\n \"L2OutputOracle: only the proposer address can propose new outputs\"\n );\n\n require(\n _l2BlockNumber == nextBlockNumber(),\n \"L2OutputOracle: block number must be equal to next expected block number\"\n );\n\n require(\n computeL2Timestamp(_l2BlockNumber) < block.timestamp,\n \"L2OutputOracle: cannot propose L2 output in the future\"\n );\n\n require(\n _outputRoot != bytes32(0),\n \"L2OutputOracle: L2 output proposal cannot be the zero hash\"\n );\n\n if (_l1BlockHash != bytes32(0)) {\n // This check allows the proposer to propose an output based on a given L1 block,\n // without fear that it will be reorged out.\n // It will also revert if the blockheight provided is more than 256 blocks behind the\n // chain tip (as the hash will return as zero). This does open the door to a griefing\n // attack in which the proposer's submission is censored until the block is no longer\n // retrievable, if the proposer is experiencing this attack it can simply leave out the\n // blockhash value, and delay submission until it is confident that the L1 block is\n // finalized.\n require(\n blockhash(_l1BlockNumber) == _l1BlockHash,\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n }\n\n emit OutputProposed(_outputRoot, nextOutputIndex(), _l2BlockNumber, block.timestamp);\n\n l2Outputs.push(\n Types.OutputProposal({\n outputRoot: _outputRoot,\n timestamp: uint128(block.timestamp),\n l2BlockNumber: uint128(_l2BlockNumber)\n })\n );\n }\n\n /**\n * @notice Returns an output by index. Exists because Solidity's array access will return a\n * tuple instead of a struct.\n *\n * @param _l2OutputIndex Index of the output to return.\n *\n * @return The output at the given index.\n */\n function getL2Output(uint256 _l2OutputIndex)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[_l2OutputIndex];\n }\n\n /**\n * @notice Returns the index of the L2 output that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return Index of the first checkpoint that commits to the given L2 block number.\n */\n function getL2OutputIndexAfter(uint256 _l2BlockNumber) public view returns (uint256) {\n // Make sure an output for this block number has actually been proposed.\n require(\n _l2BlockNumber <= latestBlockNumber(),\n \"L2OutputOracle: cannot get output for a block that has not been proposed\"\n );\n\n // Make sure there's at least one output proposed.\n require(\n l2Outputs.length > 0,\n \"L2OutputOracle: cannot get output as no outputs have been proposed yet\"\n );\n\n // Find the output via binary search, guaranteed to exist.\n uint256 lo = 0;\n uint256 hi = l2Outputs.length;\n while (lo < hi) {\n uint256 mid = (lo + hi) / 2;\n if (l2Outputs[mid].l2BlockNumber < _l2BlockNumber) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n return lo;\n }\n\n /**\n * @notice Returns the L2 output proposal that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return First checkpoint that commits to the given L2 block number.\n */\n function getL2OutputAfter(uint256 _l2BlockNumber)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[getL2OutputIndexAfter(_l2BlockNumber)];\n }\n\n /**\n * @notice Returns the number of outputs that have been proposed. Will revert if no outputs\n * have been proposed yet.\n *\n * @return The number of outputs that have been proposed.\n */\n function latestOutputIndex() external view returns (uint256) {\n return l2Outputs.length - 1;\n }\n\n /**\n * @notice Returns the index of the next output to be proposed.\n *\n * @return The index of the next output to be proposed.\n */\n function nextOutputIndex() public view returns (uint256) {\n return l2Outputs.length;\n }\n\n /**\n * @notice Returns the block number of the latest submitted L2 output proposal. If no proposals\n * been submitted yet then this function will return the starting block number.\n *\n * @return Latest submitted L2 block number.\n */\n function latestBlockNumber() public view returns (uint256) {\n return\n l2Outputs.length == 0\n ? startingBlockNumber\n : l2Outputs[l2Outputs.length - 1].l2BlockNumber;\n }\n\n /**\n * @notice Computes the block number of the next L2 block that needs to be checkpointed.\n *\n * @return Next L2 block number.\n */\n function nextBlockNumber() public view returns (uint256) {\n return latestBlockNumber() + SUBMISSION_INTERVAL;\n }\n\n /**\n * @notice Returns the L2 timestamp corresponding to a given L2 block number.\n *\n * @param _l2BlockNumber The L2 block number of the target block.\n *\n * @return L2 timestamp of the given block.\n */\n function computeL2Timestamp(uint256 _l2BlockNumber) public view returns (uint256) {\n return startingTimestamp + ((_l2BlockNumber - startingBlockNumber) * L2_BLOCK_TIME);\n }\n}\n" - }, - "contracts/L1/OptimismPortal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { L2OutputOracle } from \"./L2OutputOracle.sol\";\nimport { SystemConfig } from \"./SystemConfig.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { SecureMerkleTrie } from \"../libraries/trie/SecureMerkleTrie.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ResourceMetering } from \"./ResourceMetering.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title OptimismPortal\n * @notice The OptimismPortal is a low-level contract responsible for passing messages between L1\n * and L2. Messages sent directly to the OptimismPortal have no form of replayability.\n * Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface.\n */\ncontract OptimismPortal is Initializable, ResourceMetering, Semver {\n /**\n * @notice Represents a proven withdrawal.\n *\n * @custom:field outputRoot Root of the L2 output this was proven against.\n * @custom:field timestamp Timestamp at whcih the withdrawal was proven.\n * @custom:field l2OutputIndex Index of the output this was proven against.\n */\n struct ProvenWithdrawal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2OutputIndex;\n }\n\n /**\n * @notice Version of the deposit event.\n */\n uint256 internal constant DEPOSIT_VERSION = 0;\n\n /**\n * @notice The L2 gas limit set when eth is deposited using the receive() function.\n */\n uint64 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Address of the L2OutputOracle contract.\n */\n L2OutputOracle public immutable L2_ORACLE;\n\n /**\n * @notice Address of the SystemConfig contract.\n */\n SystemConfig public immutable SYSTEM_CONFIG;\n\n /**\n * @notice Address that has the ability to pause and unpause withdrawals.\n */\n address public immutable GUARDIAN;\n\n /**\n * @notice Address of the L2 account which initiated a withdrawal in this transaction. If the\n * of this variable is the default L2 sender address, then we are NOT inside of a call\n * to finalizeWithdrawalTransaction.\n */\n address public l2Sender;\n\n /**\n * @notice A list of withdrawal hashes which have been successfully finalized.\n */\n mapping(bytes32 => bool) public finalizedWithdrawals;\n\n /**\n * @notice A mapping of withdrawal hashes to `ProvenWithdrawal` data.\n */\n mapping(bytes32 => ProvenWithdrawal) public provenWithdrawals;\n\n /**\n * @notice Determines if cross domain messaging is paused. When set to true,\n * deposits and withdrawals are paused. This may be removed in the\n * future.\n */\n bool public paused;\n\n /**\n * @notice Emitted when a transaction is deposited from L1 to L2. The parameters of this event\n * are read by the rollup node and used to derive deposit transactions on L2.\n *\n * @param from Address that triggered the deposit transaction.\n * @param to Address that the deposit transaction is directed to.\n * @param version Version of this deposit transaction event.\n * @param opaqueData ABI encoded deposit data to be parsed off-chain.\n */\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is proven.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n */\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is finalized.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n * @param success Whether the withdrawal transaction was successful.\n */\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n\n /**\n * @notice Emitted when the pause is triggered.\n *\n * @param account Address of the account triggering the pause.\n */\n event Paused(address account);\n\n /**\n * @notice Emitted when the pause is lifted.\n *\n * @param account Address of the account triggering the unpause.\n */\n event Unpaused(address account);\n\n /**\n * @notice Reverts when paused.\n */\n modifier whenNotPaused() {\n require(paused == false, \"OptimismPortal: paused\");\n _;\n }\n\n /**\n * @custom:semver 1.3.0\n *\n * @param _l2Oracle Address of the L2OutputOracle contract.\n * @param _guardian Address that can pause deposits and withdrawals.\n * @param _paused Sets the contract's pausability state.\n * @param _config Address of the SystemConfig contract.\n */\n constructor(\n L2OutputOracle _l2Oracle,\n address _guardian,\n bool _paused,\n SystemConfig _config\n ) Semver(1, 3, 0) {\n L2_ORACLE = _l2Oracle;\n GUARDIAN = _guardian;\n SYSTEM_CONFIG = _config;\n initialize(_paused);\n }\n\n /**\n * @notice Initializer.\n */\n function initialize(bool _paused) public initializer {\n l2Sender = Constants.DEFAULT_L2_SENDER;\n paused = _paused;\n __ResourceMetering_init();\n }\n\n /**\n * @notice Pause deposits and withdrawals.\n */\n function pause() external {\n require(msg.sender == GUARDIAN, \"OptimismPortal: only guardian can pause\");\n paused = true;\n emit Paused(msg.sender);\n }\n\n /**\n * @notice Unpause deposits and withdrawals.\n */\n function unpause() external {\n require(msg.sender == GUARDIAN, \"OptimismPortal: only guardian can unpause\");\n paused = false;\n emit Unpaused(msg.sender);\n }\n\n /**\n * @notice Accepts value so that users can send ETH directly to this contract and have the\n * funds be deposited to their address on L2. This is intended as a convenience\n * function for EOAs. Contracts should call the depositTransaction() function directly\n * otherwise any deposited funds will be lost due to address aliasing.\n */\n // solhint-disable-next-line ordering\n receive() external payable {\n depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes(\"\"));\n }\n\n /**\n * @notice Accepts ETH value without triggering a deposit to L2. This function mainly exists\n * for the sake of the migration between the legacy Optimism system and Bedrock.\n */\n function donateETH() external payable {\n // Intentionally empty.\n }\n\n /**\n * @notice Getter for the resource config. Used internally by the ResourceMetering\n * contract. The SystemConfig is the source of truth for the resource config.\n *\n * @return ResourceMetering.ResourceConfig\n */\n function _resourceConfig()\n internal\n view\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return SYSTEM_CONFIG.resourceConfig();\n }\n\n /**\n * @notice Proves a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n * @param _l2OutputIndex L2 output index to prove against.\n * @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root.\n * @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract.\n */\n function proveWithdrawalTransaction(\n Types.WithdrawalTransaction memory _tx,\n uint256 _l2OutputIndex,\n Types.OutputRootProof calldata _outputRootProof,\n bytes[] calldata _withdrawalProof\n ) external whenNotPaused {\n // Prevent users from creating a deposit transaction where this address is the message\n // sender on L2. Because this is checked here, we do not need to check again in\n // `finalizeWithdrawalTransaction`.\n require(\n _tx.target != address(this),\n \"OptimismPortal: you cannot send messages to the portal contract\"\n );\n\n // Get the output root and load onto the stack to prevent multiple mloads. This will\n // revert if there is no output root for the given block number.\n bytes32 outputRoot = L2_ORACLE.getL2Output(_l2OutputIndex).outputRoot;\n\n // Verify that the output root can be generated with the elements in the proof.\n require(\n outputRoot == Hashing.hashOutputRootProof(_outputRootProof),\n \"OptimismPortal: invalid output root proof\"\n );\n\n // Load the ProvenWithdrawal into memory, using the withdrawal hash as a unique identifier.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // We generally want to prevent users from proving the same withdrawal multiple times\n // because each successive proof will update the timestamp. A malicious user can take\n // advantage of this to prevent other users from finalizing their withdrawal. However,\n // since withdrawals are proven before an output root is finalized, we need to allow users\n // to re-prove their withdrawal only in the case that the output root for their specified\n // output index has been updated.\n require(\n provenWithdrawal.timestamp == 0 ||\n L2_ORACLE.getL2Output(provenWithdrawal.l2OutputIndex).outputRoot !=\n provenWithdrawal.outputRoot,\n \"OptimismPortal: withdrawal hash has already been proven\"\n );\n\n // Compute the storage slot of the withdrawal hash in the L2ToL1MessagePasser contract.\n // Refer to the Solidity documentation for more information on how storage layouts are\n // computed for mappings.\n bytes32 storageKey = keccak256(\n abi.encode(\n withdrawalHash,\n uint256(0) // The withdrawals mapping is at the first slot in the layout.\n )\n );\n\n // Verify that the hash of this withdrawal was stored in the L2toL1MessagePasser contract\n // on L2. If this is true, under the assumption that the SecureMerkleTrie does not have\n // bugs, then we know that this withdrawal was actually triggered on L2 and can therefore\n // be relayed on L1.\n require(\n SecureMerkleTrie.verifyInclusionProof(\n abi.encode(storageKey),\n hex\"01\",\n _withdrawalProof,\n _outputRootProof.messagePasserStorageRoot\n ),\n \"OptimismPortal: invalid withdrawal inclusion proof\"\n );\n\n // Designate the withdrawalHash as proven by storing the `outputRoot`, `timestamp`, and\n // `l2BlockNumber` in the `provenWithdrawals` mapping. A `withdrawalHash` can only be\n // proven once unless it is submitted again with a different outputRoot.\n provenWithdrawals[withdrawalHash] = ProvenWithdrawal({\n outputRoot: outputRoot,\n timestamp: uint128(block.timestamp),\n l2OutputIndex: uint128(_l2OutputIndex)\n });\n\n // Emit a `WithdrawalProven` event.\n emit WithdrawalProven(withdrawalHash, _tx.sender, _tx.target);\n }\n\n /**\n * @notice Finalizes a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n */\n function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx)\n external\n whenNotPaused\n {\n // Make sure that the l2Sender has not yet been set. The l2Sender is set to a value other\n // than the default value when a withdrawal transaction is being finalized. This check is\n // a defacto reentrancy guard.\n require(\n l2Sender == Constants.DEFAULT_L2_SENDER,\n \"OptimismPortal: can only trigger one withdrawal per transaction\"\n );\n\n // Grab the proven withdrawal from the `provenWithdrawals` map.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // A withdrawal can only be finalized if it has been proven. We know that a withdrawal has\n // been proven at least once when its timestamp is non-zero. Unproven withdrawals will have\n // a timestamp of zero.\n require(\n provenWithdrawal.timestamp != 0,\n \"OptimismPortal: withdrawal has not been proven yet\"\n );\n\n // As a sanity check, we make sure that the proven withdrawal's timestamp is greater than\n // starting timestamp inside the L2OutputOracle. Not strictly necessary but extra layer of\n // safety against weird bugs in the proving step.\n require(\n provenWithdrawal.timestamp >= L2_ORACLE.startingTimestamp(),\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n\n // A proven withdrawal must wait at least the finalization period before it can be\n // finalized. This waiting period can elapse in parallel with the waiting period for the\n // output the withdrawal was proven against. In effect, this means that the minimum\n // withdrawal time is proposal submission time + finalization period.\n require(\n _isFinalizationPeriodElapsed(provenWithdrawal.timestamp),\n \"OptimismPortal: proven withdrawal finalization period has not elapsed\"\n );\n\n // Grab the OutputProposal from the L2OutputOracle, will revert if the output that\n // corresponds to the given index has not been proposed yet.\n Types.OutputProposal memory proposal = L2_ORACLE.getL2Output(\n provenWithdrawal.l2OutputIndex\n );\n\n // Check that the output root that was used to prove the withdrawal is the same as the\n // current output root for the given output index. An output root may change if it is\n // deleted by the challenger address and then re-proposed.\n require(\n proposal.outputRoot == provenWithdrawal.outputRoot,\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n\n // Check that the output proposal has also been finalized.\n require(\n _isFinalizationPeriodElapsed(proposal.timestamp),\n \"OptimismPortal: output proposal finalization period has not elapsed\"\n );\n\n // Check that this withdrawal has not already been finalized, this is replay protection.\n require(\n finalizedWithdrawals[withdrawalHash] == false,\n \"OptimismPortal: withdrawal has already been finalized\"\n );\n\n // Mark the withdrawal as finalized so it can't be replayed.\n finalizedWithdrawals[withdrawalHash] = true;\n\n // Set the l2Sender so contracts know who triggered this withdrawal on L2.\n l2Sender = _tx.sender;\n\n // Trigger the call to the target contract. We use a custom low level method\n // SafeCall.callWithMinGas to ensure two key properties\n // 1. Target contracts cannot force this call to run out of gas by returning a very large\n // amount of data (and this is OK because we don't care about the returndata here).\n // 2. The amount of gas provided to the call to the target contract is at least the gas\n // limit specified by the user. If there is not enough gas in the callframe to\n // accomplish this, `callWithMinGas` will revert.\n // Additionally, if there is not enough gas remaining to complete the execution after the\n // call returns, this function will revert.\n bool success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, _tx.value, _tx.data);\n\n // Reset the l2Sender back to the default value.\n l2Sender = Constants.DEFAULT_L2_SENDER;\n\n // All withdrawals are immediately finalized. Replayability can\n // be achieved through contracts built on top of this contract\n emit WithdrawalFinalized(withdrawalHash, success);\n\n // Reverting here is useful for determining the exact gas cost to successfully execute the\n // sub call to the target contract if the minimum gas limit specified by the user would not\n // be sufficient to execute the sub call.\n if (success == false && tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"OptimismPortal: withdrawal failed\");\n }\n }\n\n /**\n * @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in\n * deriving deposit transactions. Note that if a deposit is made by a contract, its\n * address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider\n * using the CrossDomainMessenger contracts for a simpler developer experience.\n *\n * @param _to Target address on L2.\n * @param _value ETH value to send to the recipient.\n * @param _gasLimit Minimum L2 gas limit (can be greater than or equal to this value).\n * @param _isCreation Whether or not the transaction is a contract creation.\n * @param _data Data to trigger the recipient with.\n */\n function depositTransaction(\n address _to,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable metered(_gasLimit) {\n // Just to be safe, make sure that people specify address(0) as the target when doing\n // contract creations.\n if (_isCreation) {\n require(\n _to == address(0),\n \"OptimismPortal: must send to address(0) when creating a contract\"\n );\n }\n\n // Prevent depositing transactions that have too small of a gas limit.\n require(_gasLimit >= 21_000, \"OptimismPortal: gas limit must cover instrinsic gas cost\");\n\n // Transform the from-address to its alias if the caller is a contract.\n address from = msg.sender;\n if (msg.sender != tx.origin) {\n from = AddressAliasHelper.applyL1ToL2Alias(msg.sender);\n }\n\n // Compute the opaque data that will be emitted as part of the TransactionDeposited event.\n // We use opaque data so that we can update the TransactionDeposited event in the future\n // without breaking the current interface.\n bytes memory opaqueData = abi.encodePacked(\n msg.value,\n _value,\n _gasLimit,\n _isCreation,\n _data\n );\n\n // Emit a TransactionDeposited event so that the rollup node can derive a deposit\n // transaction for this deposit.\n emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData);\n }\n\n /**\n * @notice Determine if a given output is finalized. Reverts if the call to\n * L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.\n *\n * @param _l2OutputIndex Index of the L2 output to check.\n *\n * @return Whether or not the output is finalized.\n */\n function isOutputFinalized(uint256 _l2OutputIndex) external view returns (bool) {\n return _isFinalizationPeriodElapsed(L2_ORACLE.getL2Output(_l2OutputIndex).timestamp);\n }\n\n /**\n * @notice Determines whether the finalization period has elapsed w/r/t a given timestamp.\n *\n * @param _timestamp Timestamp to check.\n *\n * @return Whether or not the finalization period has elapsed.\n */\n function _isFinalizationPeriodElapsed(uint256 _timestamp) internal view returns (bool) {\n return block.timestamp > _timestamp + L2_ORACLE.FINALIZATION_PERIOD_SECONDS();\n }\n}\n" - }, - "contracts/L1/ResourceMetering.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\n\n/**\n * @custom:upgradeable\n * @title ResourceMetering\n * @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing\n * updates automatically based on current demand.\n */\nabstract contract ResourceMetering is Initializable {\n /**\n * @notice Represents the various parameters that control the way in which resources are\n * metered. Corresponds to the EIP-1559 resource metering system.\n *\n * @custom:field prevBaseFee Base fee from the previous block(s).\n * @custom:field prevBoughtGas Amount of gas bought so far in the current block.\n * @custom:field prevBlockNum Last block number that the base fee was updated.\n */\n struct ResourceParams {\n uint128 prevBaseFee;\n uint64 prevBoughtGas;\n uint64 prevBlockNum;\n }\n\n /**\n * @notice Represents the configuration for the EIP-1559 based curve for the deposit gas\n * market. These values should be set with care as it is possible to set them in\n * a way that breaks the deposit gas market. The target resource limit is defined as\n * maxResourceLimit / elasticityMultiplier. This struct was designed to fit within a\n * single word. There is additional space for additions in the future.\n *\n * @custom:field maxResourceLimit Represents the maximum amount of deposit gas that\n * can be purchased per block.\n * @custom:field elasticityMultiplier Determines the target resource limit along with\n * the resource limit.\n * @custom:field baseFeeMaxChangeDenominator Determines max change on fee per block.\n * @custom:field minimumBaseFee The min deposit base fee, it is clamped to this\n * value.\n * @custom:field systemTxMaxGas The amount of gas supplied to the system\n * transaction. This should be set to the same number\n * that the op-node sets as the gas limit for the\n * system transaction.\n * @custom:field maximumBaseFee The max deposit base fee, it is clamped to this\n * value.\n */\n struct ResourceConfig {\n uint32 maxResourceLimit;\n uint8 elasticityMultiplier;\n uint8 baseFeeMaxChangeDenominator;\n uint32 minimumBaseFee;\n uint32 systemTxMaxGas;\n uint128 maximumBaseFee;\n }\n\n /**\n * @notice EIP-1559 style gas parameters.\n */\n ResourceParams public params;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n */\n uint256[48] private __gap;\n\n /**\n * @notice Meters access to a function based an amount of a requested resource.\n *\n * @param _amount Amount of the resource requested.\n */\n modifier metered(uint64 _amount) {\n // Record initial gas amount so we can refund for it later.\n uint256 initialGas = gasleft();\n\n // Run the underlying function.\n _;\n\n // Run the metering function.\n _metered(_amount, initialGas);\n }\n\n /**\n * @notice An internal function that holds all of the logic for metering a resource.\n *\n * @param _amount Amount of the resource requested.\n * @param _initialGas The amount of gas before any modifier execution.\n */\n function _metered(uint64 _amount, uint256 _initialGas) internal {\n // Update block number and base fee if necessary.\n uint256 blockDiff = block.number - params.prevBlockNum;\n\n ResourceConfig memory config = _resourceConfig();\n int256 targetResourceLimit = int256(uint256(config.maxResourceLimit)) /\n int256(uint256(config.elasticityMultiplier));\n\n if (blockDiff > 0) {\n // Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate\n // at which deposits can be created and therefore limit the potential for deposits to\n // spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes.\n int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - targetResourceLimit;\n int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) /\n (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator)));\n\n // Update base fee by adding the base fee delta and clamp the resulting value between\n // min and max.\n int256 newBaseFee = Arithmetic.clamp({\n _value: int256(uint256(params.prevBaseFee)) + baseFeeDelta,\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n\n // If we skipped more than one block, we also need to account for every empty block.\n // Empty block means there was no demand for deposits in that block, so we should\n // reflect this lack of demand in the fee.\n if (blockDiff > 1) {\n // Update the base fee by repeatedly applying the exponent 1-(1/change_denominator)\n // blockDiff - 1 times. Simulates multiple empty blocks. Clamp the resulting value\n // between min and max.\n newBaseFee = Arithmetic.clamp({\n _value: Arithmetic.cdexp({\n _coefficient: newBaseFee,\n _denominator: int256(uint256(config.baseFeeMaxChangeDenominator)),\n _exponent: int256(blockDiff - 1)\n }),\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n }\n\n // Update new base fee, reset bought gas, and update block number.\n params.prevBaseFee = uint128(uint256(newBaseFee));\n params.prevBoughtGas = 0;\n params.prevBlockNum = uint64(block.number);\n }\n\n // Make sure we can actually buy the resource amount requested by the user.\n params.prevBoughtGas += _amount;\n require(\n int256(uint256(params.prevBoughtGas)) <= int256(uint256(config.maxResourceLimit)),\n \"ResourceMetering: cannot buy more gas than available gas limit\"\n );\n\n // Determine the amount of ETH to be paid.\n uint256 resourceCost = uint256(_amount) * uint256(params.prevBaseFee);\n\n // We currently charge for this ETH amount as an L1 gas burn, so we convert the ETH amount\n // into gas by dividing by the L1 base fee. We assume a minimum base fee of 1 gwei to avoid\n // division by zero for L1s that don't support 1559 or to avoid excessive gas burns during\n // periods of extremely low L1 demand. One-day average gas fee hasn't dipped below 1 gwei\n // during any 1 day period in the last 5 years, so should be fine.\n uint256 gasCost = resourceCost / Math.max(block.basefee, 1 gwei);\n\n // Give the user a refund based on the amount of gas they used to do all of the work up to\n // this point. Since we're at the end of the modifier, this should be pretty accurate. Acts\n // effectively like a dynamic stipend (with a minimum value).\n uint256 usedGas = _initialGas - gasleft();\n if (gasCost > usedGas) {\n Burn.gas(gasCost - usedGas);\n }\n }\n\n /**\n * @notice Virtual function that returns the resource config. Contracts that inherit this\n * contract must implement this function.\n *\n * @return ResourceConfig\n */\n function _resourceConfig() internal virtual returns (ResourceConfig memory);\n\n /**\n * @notice Sets initial resource parameter values. This function must either be called by the\n * initializer function of an upgradeable child contract.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __ResourceMetering_init() internal onlyInitializing {\n params = ResourceParams({\n prevBaseFee: 1 gwei,\n prevBoughtGas: 0,\n prevBlockNum: uint64(block.number)\n });\n }\n}\n" - }, - "contracts/L1/SystemConfig.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { ResourceMetering } from \"./ResourceMetering.sol\";\n\n/**\n * @title SystemConfig\n * @notice The SystemConfig contract is used to manage configuration of an Optimism network. All\n * configuration is stored on L1 and picked up by L2 as part of the derviation of the L2\n * chain.\n */\ncontract SystemConfig is OwnableUpgradeable, Semver {\n /**\n * @notice Enum representing different types of updates.\n *\n * @custom:value BATCHER Represents an update to the batcher hash.\n * @custom:value GAS_CONFIG Represents an update to txn fee config on L2.\n * @custom:value GAS_LIMIT Represents an update to gas limit on L2.\n * @custom:value UNSAFE_BLOCK_SIGNER Represents an update to the signer key for unsafe\n * block distrubution.\n */\n enum UpdateType {\n BATCHER,\n GAS_CONFIG,\n GAS_LIMIT,\n UNSAFE_BLOCK_SIGNER\n }\n\n /**\n * @notice Version identifier, used for upgrades.\n */\n uint256 public constant VERSION = 0;\n\n /**\n * @notice Storage slot that the unsafe block signer is stored at. Storing it at this\n * deterministic storage slot allows for decoupling the storage layout from the way\n * that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value.\n */\n bytes32 public constant UNSAFE_BLOCK_SIGNER_SLOT = keccak256(\"systemconfig.unsafeblocksigner\");\n\n /**\n * @notice Fixed L2 gas overhead. Used as part of the L2 fee calculation.\n */\n uint256 public overhead;\n\n /**\n * @notice Dynamic L2 gas overhead. Used as part of the L2 fee calculation.\n */\n uint256 public scalar;\n\n /**\n * @notice Identifier for the batcher. For version 1 of this configuration, this is represented\n * as an address left-padded with zeros to 32 bytes.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice L2 block gas limit.\n */\n uint64 public gasLimit;\n\n /**\n * @notice The configuration for the deposit fee market. Used by the OptimismPortal\n * to meter the cost of buying L2 gas on L1. Set as internal and wrapped with a getter\n * so that the struct is returned instead of a tuple.\n */\n ResourceMetering.ResourceConfig internal _resourceConfig;\n\n /**\n * @notice Emitted when configuration is updated\n *\n * @param version SystemConfig version.\n * @param updateType Type of update.\n * @param data Encoded update data.\n */\n event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);\n\n /**\n * @custom:semver 1.2.0\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n * @param _unsafeBlockSigner Initial unsafe block signer address.\n * @param _config Initial resource config.\n */\n constructor(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner,\n ResourceMetering.ResourceConfig memory _config\n ) Semver(1, 2, 0) {\n initialize({\n _owner: _owner,\n _overhead: _overhead,\n _scalar: _scalar,\n _batcherHash: _batcherHash,\n _gasLimit: _gasLimit,\n _unsafeBlockSigner: _unsafeBlockSigner,\n _config: _config\n });\n }\n\n /**\n * @notice Initializer. The resource config must be set before the\n * require check.\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n * @param _unsafeBlockSigner Initial unsafe block signer address.\n * @param _config Initial ResourceConfig.\n */\n function initialize(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner,\n ResourceMetering.ResourceConfig memory _config\n ) public initializer {\n __Ownable_init();\n transferOwnership(_owner);\n overhead = _overhead;\n scalar = _scalar;\n batcherHash = _batcherHash;\n gasLimit = _gasLimit;\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n _setResourceConfig(_config);\n require(_gasLimit >= minimumGasLimit(), \"SystemConfig: gas limit too low\");\n }\n\n /**\n * @notice Returns the minimum L2 gas limit that can be safely set for the system to\n * operate. The L2 gas limit must be larger than or equal to the amount of\n * gas that is allocated for deposits per block plus the amount of gas that\n * is allocated for the system transaction.\n * This function is used to determine if changes to parameters are safe.\n *\n * @return uint64\n */\n function minimumGasLimit() public view returns (uint64) {\n return uint64(_resourceConfig.maxResourceLimit) + uint64(_resourceConfig.systemTxMaxGas);\n }\n\n /**\n * @notice High level getter for the unsafe block signer address. Unsafe blocks can be\n * propagated across the p2p network if they are signed by the key corresponding to\n * this address.\n *\n * @return Address of the unsafe block signer.\n */\n // solhint-disable-next-line ordering\n function unsafeBlockSigner() external view returns (address) {\n address addr;\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n addr := sload(slot)\n }\n return addr;\n }\n\n /**\n * @notice Updates the unsafe block signer address.\n *\n * @param _unsafeBlockSigner New unsafe block signer address.\n */\n function setUnsafeBlockSigner(address _unsafeBlockSigner) external onlyOwner {\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n\n bytes memory data = abi.encode(_unsafeBlockSigner);\n emit ConfigUpdate(VERSION, UpdateType.UNSAFE_BLOCK_SIGNER, data);\n }\n\n /**\n * @notice Updates the batcher hash.\n *\n * @param _batcherHash New batcher hash.\n */\n function setBatcherHash(bytes32 _batcherHash) external onlyOwner {\n batcherHash = _batcherHash;\n\n bytes memory data = abi.encode(_batcherHash);\n emit ConfigUpdate(VERSION, UpdateType.BATCHER, data);\n }\n\n /**\n * @notice Updates gas config.\n *\n * @param _overhead New overhead value.\n * @param _scalar New scalar value.\n */\n function setGasConfig(uint256 _overhead, uint256 _scalar) external onlyOwner {\n overhead = _overhead;\n scalar = _scalar;\n\n bytes memory data = abi.encode(_overhead, _scalar);\n emit ConfigUpdate(VERSION, UpdateType.GAS_CONFIG, data);\n }\n\n /**\n * @notice Updates the L2 gas limit.\n *\n * @param _gasLimit New gas limit.\n */\n function setGasLimit(uint64 _gasLimit) external onlyOwner {\n require(_gasLimit >= minimumGasLimit(), \"SystemConfig: gas limit too low\");\n gasLimit = _gasLimit;\n\n bytes memory data = abi.encode(_gasLimit);\n emit ConfigUpdate(VERSION, UpdateType.GAS_LIMIT, data);\n }\n\n /**\n * @notice Low level setter for the unsafe block signer address. This function exists to\n * deduplicate code around storing the unsafeBlockSigner address in storage.\n *\n * @param _unsafeBlockSigner New unsafeBlockSigner value.\n */\n function _setUnsafeBlockSigner(address _unsafeBlockSigner) internal {\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n sstore(slot, _unsafeBlockSigner)\n }\n }\n\n /**\n * @notice A getter for the resource config. Ensures that the struct is\n * returned instead of a tuple.\n *\n * @return ResourceConfig\n */\n function resourceConfig() external view returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig;\n }\n\n /**\n * @notice An external setter for the resource config. In the future, this\n * method may emit an event that the `op-node` picks up for when the\n * resource config is changed.\n *\n * @param _config The new resource config values.\n */\n function setResourceConfig(ResourceMetering.ResourceConfig memory _config) external onlyOwner {\n _setResourceConfig(_config);\n }\n\n /**\n * @notice An internal setter for the resource config. Ensures that the\n * config is sane before storing it by checking for invariants.\n *\n * @param _config The new resource config.\n */\n function _setResourceConfig(ResourceMetering.ResourceConfig memory _config) internal {\n // Min base fee must be less than or equal to max base fee.\n require(\n _config.minimumBaseFee <= _config.maximumBaseFee,\n \"SystemConfig: min base fee must be less than max base\"\n );\n // Base fee change denominator must be greater than 0.\n require(_config.baseFeeMaxChangeDenominator > 0, \"SystemConfig: denominator cannot be 0\");\n // Max resource limit plus system tx gas must be less than or equal to the L2 gas limit.\n // The gas limit must be increased before these values can be increased.\n require(\n _config.maxResourceLimit + _config.systemTxMaxGas <= gasLimit,\n \"SystemConfig: gas limit too low\"\n );\n // Elasticity multiplier must be greater than 0.\n require(\n _config.elasticityMultiplier > 0,\n \"SystemConfig: elasticity multiplier cannot be 0\"\n );\n // No precision loss when computing target resource limit.\n require(\n ((_config.maxResourceLimit / _config.elasticityMultiplier) *\n _config.elasticityMultiplier) == _config.maxResourceLimit,\n \"SystemConfig: precision loss with target resource limit\"\n );\n\n _resourceConfig = _config;\n }\n}\n" - }, - "contracts/L2/BaseFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000019\n * @title BaseFeeVault\n * @notice The BaseFeeVault accumulates the base fee that is paid by transactions.\n */\ncontract BaseFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 0, 0) {}\n}\n" - }, - "contracts/L2/CrossDomainOwnable.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\n/**\n * @title CrossDomainOwnable\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is only safe to be used if the\n * CrossDomainMessenger system is bypassed and the caller on L1 is calling the\n * OptimismPortal directly.\n */\nabstract contract CrossDomainOwnable is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `msg.sender` is the owner of the contract.\n */\n function _checkOwner() internal view override {\n require(\n owner() == AddressAliasHelper.undoL1ToL2Alias(msg.sender),\n \"CrossDomainOwnable: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/CrossDomainOwnable2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L2CrossDomainMessenger } from \"./L2CrossDomainMessenger.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title CrossDomainOwnable2\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is meant to be used with systems that use\n * the CrossDomainMessenger system. It will not work if the OptimismPortal is used\n * directly.\n */\nabstract contract CrossDomainOwnable2 is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `xDomainMessageSender` is the owner of the contract. This value is set to the caller\n * of the L1CrossDomainMessenger.\n */\n function _checkOwner() internal view override {\n L2CrossDomainMessenger messenger = L2CrossDomainMessenger(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER\n );\n\n require(\n msg.sender == address(messenger),\n \"CrossDomainOwnable2: caller is not the messenger\"\n );\n\n require(\n owner() == messenger.xDomainMessageSender(),\n \"CrossDomainOwnable2: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/CrossDomainOwnable3.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L2CrossDomainMessenger } from \"./L2CrossDomainMessenger.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title CrossDomainOwnable3\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on either L1 or L2. Note that this contract is meant to be used with systems\n * that use the CrossDomainMessenger system. It will not work if the OptimismPortal is\n * used directly.\n */\nabstract contract CrossDomainOwnable3 is Ownable {\n /**\n * @notice If true, the contract uses the cross domain _checkOwner function override. If false\n * it uses the standard Ownable _checkOwner function.\n */\n bool public isLocal = true;\n\n /**\n * @notice Emits when ownership of the contract is transferred. Includes the\n * isLocal field in addition to the standard `Ownable` OwnershipTransferred event.\n */\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner,\n bool isLocal\n );\n\n /**\n * @notice Allows for ownership to be transferred with specifying the locality.\n * @param _owner The new owner of the contract.\n * @param _isLocal Configures the locality of the ownership.\n */\n function transferOwnership(address _owner, bool _isLocal) external onlyOwner {\n require(_owner != address(0), \"CrossDomainOwnable3: new owner is the zero address\");\n\n address oldOwner = owner();\n _transferOwnership(_owner);\n isLocal = _isLocal;\n\n emit OwnershipTransferred(oldOwner, _owner, _isLocal);\n }\n\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `xDomainMessageSender` is the owner of the contract. This value is set to the caller\n * of the L1CrossDomainMessenger.\n */\n function _checkOwner() internal view override {\n if (isLocal) {\n require(owner() == msg.sender, \"CrossDomainOwnable3: caller is not the owner\");\n } else {\n L2CrossDomainMessenger messenger = L2CrossDomainMessenger(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER\n );\n\n require(\n msg.sender == address(messenger),\n \"CrossDomainOwnable3: caller is not the messenger\"\n );\n\n require(\n owner() == messenger.xDomainMessageSender(),\n \"CrossDomainOwnable3: caller is not the owner\"\n );\n }\n }\n}\n" - }, - "contracts/L2/GasPriceOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000000F\n * @title GasPriceOracle\n * @notice This contract maintains the variables responsible for computing the L1 portion of the\n * total fee charged on L2. Before Bedrock, this contract held variables in state that were\n * read during the state transition function to compute the L1 portion of the transaction\n * fee. After Bedrock, this contract now simply proxies the L1Block contract, which has\n * the values used to compute the L1 portion of the fee in its state.\n *\n * The contract exposes an API that is useful for knowing how large the L1 portion of the\n * transaction fee will be. The following events were deprecated with Bedrock:\n * - event OverheadUpdated(uint256 overhead);\n * - event ScalarUpdated(uint256 scalar);\n * - event DecimalsUpdated(uint256 decimals);\n */\ncontract GasPriceOracle is Semver {\n /**\n * @notice Number of decimals used in the scalar.\n */\n uint256 public constant DECIMALS = 6;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Computes the L1 portion of the fee based on the size of the rlp encoded input\n * transaction, the current L1 base fee, and the various dynamic parameters.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for.\n *\n * @return L1 fee that should be paid for the tx\n */\n function getL1Fee(bytes memory _data) external view returns (uint256) {\n uint256 l1GasUsed = getL1GasUsed(_data);\n uint256 l1Fee = l1GasUsed * l1BaseFee();\n uint256 divisor = 10**DECIMALS;\n uint256 unscaled = l1Fee * scalar();\n uint256 scaled = unscaled / divisor;\n return scaled;\n }\n\n /**\n * @notice Retrieves the current gas price (base fee).\n *\n * @return Current L2 gas price (base fee).\n */\n function gasPrice() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current base fee.\n *\n * @return Current L2 base fee.\n */\n function baseFee() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current fee overhead.\n *\n * @return Current fee overhead.\n */\n function overhead() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead();\n }\n\n /**\n * @notice Retrieves the current fee scalar.\n *\n * @return Current fee scalar.\n */\n function scalar() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar();\n }\n\n /**\n * @notice Retrieves the latest known L1 base fee.\n *\n * @return Latest known L1 base fee.\n */\n function l1BaseFee() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee();\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the number of decimals used in the scalar.\n *\n * @return Number of decimals used in the scalar.\n */\n function decimals() public pure returns (uint256) {\n return DECIMALS;\n }\n\n /**\n * @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which\n * represents the per-transaction gas overhead of posting the transaction and state\n * roots to L1. Adds 68 bytes of padding to account for the fact that the input does\n * not have a signature.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for.\n *\n * @return Amount of L1 gas used to publish the transaction.\n */\n function getL1GasUsed(bytes memory _data) public view returns (uint256) {\n uint256 total = 0;\n uint256 length = _data.length;\n for (uint256 i = 0; i < length; i++) {\n if (_data[i] == 0) {\n total += 4;\n } else {\n total += 16;\n }\n }\n uint256 unsigned = total + overhead();\n return unsigned + (68 * 16);\n }\n}\n" - }, - "contracts/L2/L1Block.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000015\n * @title L1Block\n * @notice The L1Block predeploy gives users access to information about the last known L1 block.\n * Values within this contract are updated once per epoch (every L1 block) and can only be\n * set by the \"depositor\" account, a special system address. Depositor account transactions\n * are created by the protocol whenever we move to a new epoch.\n */\ncontract L1Block is Semver {\n /**\n * @notice Address of the special depositor account.\n */\n address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001;\n\n /**\n * @notice The latest L1 block number known by the L2 system.\n */\n uint64 public number;\n\n /**\n * @notice The latest L1 timestamp known by the L2 system.\n */\n uint64 public timestamp;\n\n /**\n * @notice The latest L1 basefee.\n */\n uint256 public basefee;\n\n /**\n * @notice The latest L1 blockhash.\n */\n bytes32 public hash;\n\n /**\n * @notice The number of L2 blocks in the same epoch.\n */\n uint64 public sequenceNumber;\n\n /**\n * @notice The versioned hash to authenticate the batcher by.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice The overhead value applied to the L1 portion of the transaction\n * fee.\n */\n uint256 public l1FeeOverhead;\n\n /**\n * @notice The scalar value applied to the L1 portion of the transaction fee.\n */\n uint256 public l1FeeScalar;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Updates the L1 block values.\n *\n * @param _number L1 blocknumber.\n * @param _timestamp L1 timestamp.\n * @param _basefee L1 basefee.\n * @param _hash L1 blockhash.\n * @param _sequenceNumber Number of L2 blocks since epoch start.\n * @param _batcherHash Versioned hash to authenticate batcher by.\n * @param _l1FeeOverhead L1 fee overhead.\n * @param _l1FeeScalar L1 fee scalar.\n */\n function setL1BlockValues(\n uint64 _number,\n uint64 _timestamp,\n uint256 _basefee,\n bytes32 _hash,\n uint64 _sequenceNumber,\n bytes32 _batcherHash,\n uint256 _l1FeeOverhead,\n uint256 _l1FeeScalar\n ) external {\n require(\n msg.sender == DEPOSITOR_ACCOUNT,\n \"L1Block: only the depositor account can set L1 block values\"\n );\n\n number = _number;\n timestamp = _timestamp;\n basefee = _basefee;\n hash = _hash;\n sequenceNumber = _sequenceNumber;\n batcherHash = _batcherHash;\n l1FeeOverhead = _l1FeeOverhead;\n l1FeeScalar = _l1FeeScalar;\n }\n}\n" - }, - "contracts/L2/L1FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000001A\n * @title L1FeeVault\n * @notice The L1FeeVault accumulates the L1 portion of the transaction fees.\n */\ncontract L1FeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 0, 0) {}\n}\n" - }, - "contracts/L2/L2CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { L2ToL1MessagePasser } from \"./L2ToL1MessagePasser.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000007\n * @title L2CrossDomainMessenger\n * @notice The L2CrossDomainMessenger is a high-level interface for message passing between L1 and\n * L2 on the L2 side. Users are generally encouraged to use this contract instead of lower\n * level message passing contracts.\n */\ncontract L2CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _l1CrossDomainMessenger Address of the L1CrossDomainMessenger contract.\n */\n constructor(address _l1CrossDomainMessenger)\n Semver(1, 1, 0)\n CrossDomainMessenger(_l1CrossDomainMessenger)\n {\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote messenger. Use otherMessenger going forward.\n *\n * @return Address of the L1CrossDomainMessenger contract.\n */\n function l1CrossDomainMessenger() public view returns (address) {\n return OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)).initiateWithdrawal{\n value: _value\n }(_to, _gasLimit, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(Predeploys.L2_TO_L1_MESSAGE_PASSER);\n }\n}\n" - }, - "contracts/L2/L2ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../universal/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 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, 1, 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), \"L2ERC721Bridge: 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 \"L2ERC721Bridge: 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(OTHER_BRIDGE, message, _minGasLimit);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L2/L2StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000010\n * @title L2StandardBridge\n * @notice The L2StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L2, it will be escrowed within this\n * contract. If the ERC20 token is native to L1, it will be burnt.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L2StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal from L2 to L1 is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _otherBridge Address of the L1StandardBridge.\n */\n constructor(address payable _otherBridge)\n Semver(1, 1, 0)\n StandardBridge(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER), _otherBridge)\n {}\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n */\n receive() external payable override onlyEOA {\n _initiateWithdrawal(\n Predeploys.LEGACY_ERC20_ETH,\n msg.sender,\n msg.sender,\n msg.value,\n RECEIVE_DEFAULT_GAS_LIMIT,\n bytes(\"\")\n );\n }\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1.\n * This function only works with OptimismMintableERC20 tokens or ether. Use the\n * `bridgeERC20` function to bridge native L2 tokens to L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdraw(\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual onlyEOA {\n _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1 to a target account on L1.\n * Note that if ETH is sent to a contract on L1 and the call fails, then that ETH will\n * be locked in the L1StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n * This function only works with OptimismMintableERC20 tokens or ether. Use the\n * `bridgeERC20To` function to bridge native L2 tokens to L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdrawTo(\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual {\n _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a deposit from L1 to L2. To finalize a deposit of ether, use address(0)\n * and the l1Token and the Legacy ERC20 ether predeploy address as the l2Token.\n *\n * @param _l1Token Address of the L1 token to deposit.\n * @param _l2Token Address of the corresponding L2 token.\n * @param _from Address of the depositor.\n * @param _to Address of the recipient.\n * @param _amount Amount of the tokens being deposited.\n * @param _extraData Extra data attached to the deposit.\n */\n function finalizeDeposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable virtual {\n if (_l1Token == address(0) && _l2Token == Predeploys.LEGACY_ERC20_ETH) {\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n } else {\n finalizeBridgeERC20(_l2Token, _l1Token, _from, _to, _amount, _extraData);\n }\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L1 bridge contract.\n *\n * @return Address of the corresponding L1 bridge contract.\n */\n function l1TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @custom:legacy\n * @notice Internal function to a withdrawal from L2 to L1 to a target account on L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _from Address of the withdrawer.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function _initiateWithdrawal(\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n if (_l2Token == Predeploys.LEGACY_ERC20_ETH) {\n _initiateBridgeETH(_from, _to, _amount, _minGasLimit, _extraData);\n } else {\n address l1Token = OptimismMintableERC20(_l2Token).l1Token();\n _initiateBridgeERC20(_l2Token, l1Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n }\n\n /**\n * @notice Emits the legacy WithdrawalInitiated event followed by the ETHBridgeInitiated event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit WithdrawalInitiated(\n address(0),\n Predeploys.LEGACY_ERC20_ETH,\n _from,\n _to,\n _amount,\n _extraData\n );\n super._emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy DepositFinalized event followed by the ETHBridgeFinalized event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit DepositFinalized(\n address(0),\n Predeploys.LEGACY_ERC20_ETH,\n _from,\n _to,\n _amount,\n _extraData\n );\n super._emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy WithdrawalInitiated event followed by the ERC20BridgeInitiated\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit WithdrawalInitiated(_remoteToken, _localToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy DepositFinalized event followed by the ERC20BridgeFinalized event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit DepositFinalized(_remoteToken, _localToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/L2/L2ToL1MessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000016\n * @title L2ToL1MessagePasser\n * @notice The L2ToL1MessagePasser is a dedicated contract where messages that are being sent from\n * L2 to L1 can be stored. The storage root of this contract is pulled up to the top level\n * of the L2 output to reduce the cost of proving the existence of sent messages.\n */\ncontract L2ToL1MessagePasser is Semver {\n /**\n * @notice The L1 gas limit set when eth is withdrawn using the receive() function.\n */\n uint256 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Current message version identifier.\n */\n uint16 public constant MESSAGE_VERSION = 1;\n\n /**\n * @notice Includes the message hashes for all withdrawals\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @notice A unique value hashed with each withdrawal.\n */\n uint240 internal msgNonce;\n\n /**\n * @notice Emitted any time a withdrawal is initiated.\n *\n * @param nonce Unique value corresponding to each withdrawal.\n * @param sender The L2 account address which initiated the withdrawal.\n * @param target The L1 account address the call will be send to.\n * @param value The ETH value submitted for withdrawal, to be forwarded to the target.\n * @param gasLimit The minimum amount of gas that must be provided when withdrawing.\n * @param data The data to be forwarded to the target on L1.\n * @param withdrawalHash The hash of the withdrawal.\n */\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n /**\n * @notice Emitted when the balance of this contract is burned.\n *\n * @param amount Amount of ETh that was burned.\n */\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Allows users to withdraw ETH by sending directly to this contract.\n */\n receive() external payable {\n initiateWithdrawal(msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @notice Removes all ETH held by this contract from the state. Used to prevent the amount of\n * ETH on L2 inflating when ETH is withdrawn. Currently only way to do this is to\n * create a contract and self-destruct it to itself. Anyone can call this function. Not\n * incentivized since this function is very cheap.\n */\n function burn() external {\n uint256 balance = address(this).balance;\n Burn.eth(balance);\n emit WithdrawerBalanceBurnt(balance);\n }\n\n /**\n * @notice Sends a message from L2 to L1.\n *\n * @param _target Address to call on L1 execution.\n * @param _gasLimit Minimum gas limit for executing the message on L1.\n * @param _data Data to forward to L1 target.\n */\n function initiateWithdrawal(\n address _target,\n uint256 _gasLimit,\n bytes memory _data\n ) public payable {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messageNonce(),\n sender: msg.sender,\n target: _target,\n value: msg.value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n sentMessages[withdrawalHash] = true;\n\n emit MessagePassed(\n messageNonce(),\n msg.sender,\n _target,\n msg.value,\n _gasLimit,\n _data,\n withdrawalHash\n );\n\n unchecked {\n ++msgNonce;\n }\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" - }, - "contracts/L2/SequencerFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000011\n * @title SequencerFeeVault\n * @notice The SequencerFeeVault is the contract that holds any fees paid to the Sequencer during\n * transaction processing and block production.\n */\ncontract SequencerFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 0, 0) {}\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the recipient address.\n *\n * @return The recipient address.\n */\n function l1FeeWallet() public view returns (address) {\n return RECIPIENT;\n }\n}\n" - }, - "contracts/deployment/PortalSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/**\n * @title PortalSender\n * @notice The PortalSender is a simple intermediate contract that will transfer the balance of the\n * L1StandardBridge to the OptimismPortal during the Bedrock migration.\n */\ncontract PortalSender {\n /**\n * @notice Address of the OptimismPortal contract.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @param _portal Address of the OptimismPortal contract.\n */\n constructor(OptimismPortal _portal) {\n PORTAL = _portal;\n }\n\n /**\n * @notice Sends balance of this contract to the OptimismPortal.\n */\n function donate() public {\n PORTAL.donateETH{ value: address(this).balance }();\n }\n}\n" - }, - "contracts/deployment/SystemDictator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { PortalSender } from \"./PortalSender.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\n/**\n * @title SystemDictator\n * @notice The SystemDictator is responsible for coordinating the deployment of a full Bedrock\n * system. The SystemDictator is designed to support both fresh network deployments and\n * upgrades to existing pre-Bedrock systems.\n */\ncontract SystemDictator is OwnableUpgradeable {\n /**\n * @notice Basic system configuration.\n */\n struct GlobalConfig {\n AddressManager addressManager;\n ProxyAdmin proxyAdmin;\n address controller;\n address finalOwner;\n }\n\n /**\n * @notice Set of proxy addresses.\n */\n struct ProxyAddressConfig {\n address l2OutputOracleProxy;\n address optimismPortalProxy;\n address l1CrossDomainMessengerProxy;\n address l1StandardBridgeProxy;\n address optimismMintableERC20FactoryProxy;\n address l1ERC721BridgeProxy;\n address systemConfigProxy;\n }\n\n /**\n * @notice Set of implementation addresses.\n */\n struct ImplementationAddressConfig {\n L2OutputOracle l2OutputOracleImpl;\n OptimismPortal optimismPortalImpl;\n L1CrossDomainMessenger l1CrossDomainMessengerImpl;\n L1StandardBridge l1StandardBridgeImpl;\n OptimismMintableERC20Factory optimismMintableERC20FactoryImpl;\n L1ERC721Bridge l1ERC721BridgeImpl;\n PortalSender portalSenderImpl;\n SystemConfig systemConfigImpl;\n }\n\n /**\n * @notice Dynamic L2OutputOracle config.\n */\n struct L2OutputOracleDynamicConfig {\n uint256 l2OutputOracleStartingBlockNumber;\n uint256 l2OutputOracleStartingTimestamp;\n }\n\n /**\n * @notice Values for the system config contract.\n */\n struct SystemConfigConfig {\n address owner;\n uint256 overhead;\n uint256 scalar;\n bytes32 batcherHash;\n uint64 gasLimit;\n address unsafeBlockSigner;\n ResourceMetering.ResourceConfig resourceConfig;\n }\n\n /**\n * @notice Combined system configuration.\n */\n struct DeployConfig {\n GlobalConfig globalConfig;\n ProxyAddressConfig proxyAddressConfig;\n ImplementationAddressConfig implementationAddressConfig;\n SystemConfigConfig systemConfigConfig;\n }\n\n /**\n * @notice Step after which exit 1 can no longer be used.\n */\n uint8 public constant EXIT_1_NO_RETURN_STEP = 3;\n\n /**\n * @notice Step where proxy ownership is transferred.\n */\n uint8 public constant PROXY_TRANSFER_STEP = 4;\n\n /**\n * @notice System configuration.\n */\n DeployConfig public config;\n\n /**\n * @notice Dynamic configuration for the L2OutputOracle.\n */\n L2OutputOracleDynamicConfig public l2OutputOracleDynamicConfig;\n\n /**\n * @notice Dynamic configuration for the OptimismPortal. Determines\n * if the system should be paused when initialized.\n */\n bool public optimismPortalDynamicConfig;\n\n /**\n * @notice Current step;\n */\n uint8 public currentStep;\n\n /**\n * @notice Whether or not dynamic config has been set.\n */\n bool public dynamicConfigSet;\n\n /**\n * @notice Whether or not the deployment is finalized.\n */\n bool public finalized;\n\n /**\n * @notice Whether or not the deployment has been exited.\n */\n bool public exited;\n\n /**\n * @notice Address of the old L1CrossDomainMessenger implementation.\n */\n address public oldL1CrossDomainMessenger;\n\n /**\n * @notice Checks that the current step is the expected step, then bumps the current step.\n *\n * @param _step Current step.\n */\n modifier step(uint8 _step) {\n require(!finalized, \"SystemDictator: already finalized\");\n require(!exited, \"SystemDictator: already exited\");\n require(currentStep == _step, \"SystemDictator: incorrect step\");\n _;\n currentStep++;\n }\n\n /**\n * @notice Constructor required to ensure that the implementation of the SystemDictator is\n * initialized upon deployment.\n */\n constructor() {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n // Using this shorter variable as an alias for address(0) just prevents us from having to\n // to use a new line for every single parameter.\n address zero = address(0);\n initialize(\n DeployConfig(\n GlobalConfig(AddressManager(zero), ProxyAdmin(zero), zero, zero),\n ProxyAddressConfig(zero, zero, zero, zero, zero, zero, zero),\n ImplementationAddressConfig(\n L2OutputOracle(zero),\n OptimismPortal(payable(zero)),\n L1CrossDomainMessenger(zero),\n L1StandardBridge(payable(zero)),\n OptimismMintableERC20Factory(zero),\n L1ERC721Bridge(zero),\n PortalSender(zero),\n SystemConfig(zero)\n ),\n SystemConfigConfig(zero, 0, 0, bytes32(0), 0, zero, rcfg)\n )\n );\n }\n\n /**\n * @param _config System configuration.\n */\n function initialize(DeployConfig memory _config) public initializer {\n config = _config;\n currentStep = 1;\n __Ownable_init();\n _transferOwnership(config.globalConfig.controller);\n }\n\n /**\n * @notice Allows the owner to update dynamic config.\n *\n * @param _l2OutputOracleDynamicConfig Dynamic L2OutputOracle config.\n * @param _optimismPortalDynamicConfig Dynamic OptimismPortal config.\n */\n function updateDynamicConfig(\n L2OutputOracleDynamicConfig memory _l2OutputOracleDynamicConfig,\n bool _optimismPortalDynamicConfig\n ) external onlyOwner {\n l2OutputOracleDynamicConfig = _l2OutputOracleDynamicConfig;\n optimismPortalDynamicConfig = _optimismPortalDynamicConfig;\n dynamicConfigSet = true;\n }\n\n /**\n * @notice Configures the ProxyAdmin contract.\n */\n function step1() external onlyOwner step(1) {\n // Set the AddressManager in the ProxyAdmin.\n config.globalConfig.proxyAdmin.setAddressManager(config.globalConfig.addressManager);\n\n // Set the L1CrossDomainMessenger to the RESOLVED proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n ProxyAdmin.ProxyType.RESOLVED\n );\n\n // Set the implementation name for the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.setImplementationName(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Set the L1StandardBridge to the CHUGSPLASH proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1StandardBridgeProxy,\n ProxyAdmin.ProxyType.CHUGSPLASH\n );\n\n // Upgrade and initialize the SystemConfig so the Sequencer can start up.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.systemConfigProxy),\n address(config.implementationAddressConfig.systemConfigImpl),\n abi.encodeCall(\n SystemConfig.initialize,\n (\n config.systemConfigConfig.owner,\n config.systemConfigConfig.overhead,\n config.systemConfigConfig.scalar,\n config.systemConfigConfig.batcherHash,\n config.systemConfigConfig.gasLimit,\n config.systemConfigConfig.unsafeBlockSigner,\n config.systemConfigConfig.resourceConfig\n )\n )\n );\n }\n\n /**\n * @notice Pauses the system by shutting down the L1CrossDomainMessenger and setting the\n * deposit halt flag to tell the Sequencer's DTL to stop accepting deposits.\n */\n function step2() external onlyOwner step(2) {\n // Store the address of the old L1CrossDomainMessenger implementation. We will need this\n // address in the case that we have to exit early.\n oldL1CrossDomainMessenger = config.globalConfig.addressManager.getAddress(\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Temporarily brick the L1CrossDomainMessenger by setting its implementation address to\n // address(0) which will cause the ResolvedDelegateProxy to revert. Better than pausing\n // the L1CrossDomainMessenger via pause() because it can be easily reverted.\n config.globalConfig.addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(0));\n\n // Set the DTL shutoff block, which will tell the DTL to stop syncing new deposits from the\n // CanonicalTransactionChain. We do this by setting an address in the AddressManager\n // because the DTL already has a reference to the AddressManager and this way we don't also\n // need to give it a reference to the SystemDictator.\n config.globalConfig.addressManager.setAddress(\n \"DTL_SHUTOFF_BLOCK\",\n address(uint160(block.number))\n );\n }\n\n /**\n * @notice Removes deprecated addresses from the AddressManager.\n */\n function step3() external onlyOwner step(EXIT_1_NO_RETURN_STEP) {\n // Remove all deprecated addresses from the AddressManager\n string[17] memory deprecated = [\n \"OVM_CanonicalTransactionChain\",\n \"OVM_L2CrossDomainMessenger\",\n \"OVM_DecompressionPrecompileAddress\",\n \"OVM_Sequencer\",\n \"OVM_Proposer\",\n \"OVM_ChainStorageContainer-CTC-batches\",\n \"OVM_ChainStorageContainer-CTC-queue\",\n \"OVM_CanonicalTransactionChain\",\n \"OVM_StateCommitmentChain\",\n \"OVM_BondManager\",\n \"OVM_ExecutionManager\",\n \"OVM_FraudVerifier\",\n \"OVM_StateManagerFactory\",\n \"OVM_StateTransitionerFactory\",\n \"OVM_SafetyChecker\",\n \"OVM_L1MultiMessageRelayer\",\n \"BondManager\"\n ];\n\n for (uint256 i = 0; i < deprecated.length; i++) {\n config.globalConfig.addressManager.setAddress(deprecated[i], address(0));\n }\n }\n\n /**\n * @notice Transfers system ownership to the ProxyAdmin.\n */\n function step4() external onlyOwner step(PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the ProxyAdmin.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1StandardBridge to the ProxyAdmin.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the ProxyAdmin.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.proxyAdmin)\n );\n }\n\n /**\n * @notice Upgrades and initializes proxy contracts.\n */\n function step5() external onlyOwner step(5) {\n // Dynamic config must be set before we can initialize the L2OutputOracle.\n require(dynamicConfigSet, \"SystemDictator: dynamic oracle config is not yet initialized\");\n\n // Upgrade and initialize the L2OutputOracle.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l2OutputOracleProxy),\n address(config.implementationAddressConfig.l2OutputOracleImpl),\n abi.encodeCall(\n L2OutputOracle.initialize,\n (\n l2OutputOracleDynamicConfig.l2OutputOracleStartingBlockNumber,\n l2OutputOracleDynamicConfig.l2OutputOracleStartingTimestamp\n )\n )\n );\n\n // Upgrade and initialize the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.optimismPortalProxy),\n address(config.implementationAddressConfig.optimismPortalImpl),\n abi.encodeCall(OptimismPortal.initialize, (optimismPortalDynamicConfig))\n );\n\n // Upgrade the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1CrossDomainMessengerProxy),\n address(config.implementationAddressConfig.l1CrossDomainMessengerImpl)\n );\n\n // Try to initialize the L1CrossDomainMessenger, only fail if it's already been initialized.\n try\n L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy)\n .initialize()\n {\n // L1CrossDomainMessenger is the one annoying edge case difference between existing\n // networks and fresh networks because in existing networks it'll already be\n // initialized but in fresh networks it won't be. Try/catch is the easiest and most\n // consistent way to handle this because initialized() is not exposed publicly.\n } catch Error(string memory reason) {\n require(\n keccak256(abi.encodePacked(reason)) ==\n keccak256(\"Initializable: contract is already initialized\"),\n string.concat(\"SystemDictator: unexpected error initializing L1XDM: \", reason)\n );\n } catch {\n revert(\"SystemDictator: unexpected error initializing L1XDM (no reason)\");\n }\n\n // Transfer ETH from the L1StandardBridge to the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.portalSenderImpl),\n abi.encodeCall(PortalSender.donate, ())\n );\n\n // Upgrade the L1StandardBridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.l1StandardBridgeImpl)\n );\n\n // Upgrade the OptimismMintableERC20Factory (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.optimismMintableERC20FactoryProxy),\n address(config.implementationAddressConfig.optimismMintableERC20FactoryImpl)\n );\n\n // Upgrade the L1ERC721Bridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1ERC721BridgeProxy),\n address(config.implementationAddressConfig.l1ERC721BridgeImpl)\n );\n }\n\n /**\n * @notice Tranfers admin ownership to the final owner.\n */\n function finalize() external onlyOwner {\n // Transfer ownership of the ProxyAdmin to the final owner.\n config.globalConfig.proxyAdmin.transferOwnership(config.globalConfig.finalOwner);\n\n // Optionally also transfer AddressManager and L1StandardBridge if we still own it. Might\n // happen if we're exiting early.\n if (currentStep <= PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the final owner.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1StandardBridge to the final owner.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the final owner.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.finalOwner)\n );\n }\n\n // Mark the deployment as finalized.\n finalized = true;\n }\n\n /**\n * @notice First exit point, can only be called before step 3 is executed.\n */\n function exit1() external onlyOwner {\n require(\n currentStep == EXIT_1_NO_RETURN_STEP,\n \"SystemDictator: can only exit1 before step 3 is executed\"\n );\n\n // Reset the L1CrossDomainMessenger to the old implementation.\n config.globalConfig.addressManager.setAddress(\n \"OVM_L1CrossDomainMessenger\",\n oldL1CrossDomainMessenger\n );\n\n // Unset the DTL shutoff block which will allow the DTL to sync again.\n config.globalConfig.addressManager.setAddress(\"DTL_SHUTOFF_BLOCK\", address(0));\n\n // Mark the deployment as exited.\n exited = true;\n }\n}\n" - }, - "contracts/echidna/FuzzAddressAliasing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract EchidnaFuzzAddressAliasing {\n bool internal failedRoundtrip;\n\n /**\n * @notice Takes an address to be aliased with AddressAliasHelper and then unaliased\n * and updates the test contract's state indicating if the round trip encoding\n * failed.\n */\n function testRoundTrip(address addr) public {\n // Alias our address\n address aliasedAddr = AddressAliasHelper.applyL1ToL2Alias(addr);\n\n // Unalias our address\n address undoneAliasAddr = AddressAliasHelper.undoL1ToL2Alias(aliasedAddr);\n\n // If our round trip aliasing did not return the original result, set our state.\n if (addr != undoneAliasAddr) {\n failedRoundtrip = true;\n }\n }\n\n /**\n * @custom:invariant Address aliases are always able to be undone.\n *\n * Asserts that an address that has been aliased with `applyL1ToL2Alias` can always\n * be unaliased with `undoL1ToL2Alias`.\n */\n function echidna_round_trip_aliasing() public view returns (bool) {\n // ASSERTION: The round trip aliasing done in testRoundTrip(...) should never fail.\n return !failedRoundtrip;\n }\n}\n" - }, - "contracts/echidna/FuzzBurn.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\n\ncontract EchidnaFuzzBurnEth is StdUtils {\n bool internal failedEthBurn;\n\n /**\n * @notice Takes an integer amount of eth to burn through the Burn library and\n * updates the contract state if an incorrect amount of eth moved from the contract\n */\n function testBurn(uint256 _value) public {\n // cache the contract's eth balance\n uint256 preBurnBalance = address(this).balance;\n uint256 value = bound(_value, 0, preBurnBalance);\n\n // execute a burn of _value eth\n Burn.eth(value);\n\n // check that exactly value eth was transfered from the contract\n unchecked {\n if (address(this).balance != preBurnBalance - value) {\n failedEthBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `eth(uint256)` always burns the exact amount of eth passed.\n *\n * Asserts that when `Burn.eth(uint256)` is called, it always burns the exact amount\n * of ETH passed to the function.\n */\n function echidna_burn_eth() public view returns (bool) {\n // ASSERTION: The amount burned should always match the amount passed exactly\n return !failedEthBurn;\n }\n}\n\ncontract EchidnaFuzzBurnGas is StdUtils {\n bool internal failedGasBurn;\n\n /**\n * @notice Takes an integer amount of gas to burn through the Burn library and\n * updates the contract state if at least that amount of gas was not burned\n * by the library\n */\n function testGas(uint256 _value) public {\n // cap the value to the max resource limit\n uint256 MAX_RESOURCE_LIMIT = 8_000_000;\n uint256 value = bound(_value, 0, MAX_RESOURCE_LIMIT);\n\n // cache the contract's current remaining gas\n uint256 preBurnGas = gasleft();\n\n // execute the gas burn\n Burn.gas(value);\n\n // cache the remaining gas post burn\n uint256 postBurnGas = gasleft();\n\n // check that at least value gas was burnt (and that there was no underflow)\n unchecked {\n if (postBurnGas - preBurnGas > value || preBurnGas - value > preBurnGas) {\n failedGasBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `gas(uint256)` always burns at least the amount of gas passed.\n *\n * Asserts that when `Burn.gas(uint256)` is called, it always burns at least the amount\n * of gas passed to the function.\n */\n function echidna_burn_gas() public view returns (bool) {\n // ASSERTION: The amount of gas burned should be strictly greater than the\n // the amount passed as _value (minimum _value + whatever minor overhead to\n // the value after the call)\n return !failedGasBurn;\n }\n}\n" - }, - "contracts/echidna/FuzzEncoding.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzEncoding {\n bool internal failedRoundtripAToB;\n bool internal failedRoundtripBToA;\n\n /**\n * @notice Takes a pair of integers to be encoded into a versioned nonce with the\n * Encoding library and then decoded and updates the test contract's state\n * indicating if the round trip encoding failed.\n */\n function testRoundTripAToB(uint240 _nonce, uint16 _version) public {\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(encodedVersionedNonce);\n\n // If our round trip encoding did not return the original result, set our state.\n if ((decodedNonce != _nonce) || (decodedVersion != _version)) {\n failedRoundtripAToB = true;\n }\n }\n\n /**\n * @notice Takes an integer representing a packed version and nonce and attempts\n * to decode them using the Encoding library before re-encoding and updates\n * the test contract's state indicating if the round trip encoding failed.\n */\n function testRoundTripBToA(uint256 _versionedNonce) public {\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(_versionedNonce);\n\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(decodedNonce, decodedVersion);\n\n // If our round trip encoding did not return the original result, set our state.\n if (encodedVersionedNonce != _versionedNonce) {\n failedRoundtripBToA = true;\n }\n }\n\n /**\n * @custom:invariant `testRoundTripAToB` never fails.\n *\n * Asserts that a raw versioned nonce can be encoded / decoded to reach the same raw value.\n */\n function echidna_round_trip_encoding_AToB() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripAToB(...)\n return !failedRoundtripAToB;\n }\n\n /**\n * @custom:invariant `testRoundTripBToA` never fails.\n *\n * Asserts that an encoded versioned nonce can always be decoded / re-encoded to reach\n * the same encoded value.\n */\n function echidna_round_trip_encoding_BToA() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripBToA should never\n // fail.\n return !failedRoundtripBToA;\n }\n}\n" - }, - "contracts/echidna/FuzzHashing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzHashing {\n bool internal failedCrossDomainHashHighVersion;\n bool internal failedCrossDomainHashV0;\n bool internal failedCrossDomainHashV1;\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash with a randomly\n * generated version. Only schema versions 0 and 1 are supported and all others should revert.\n */\n function testHashCrossDomainMessageHighVersion(\n uint16 _version,\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // hash the cross domain message. we don't need to store the result since the function\n // validates and should revert if an invalid version (>1) is encoded\n Hashing.hashCrossDomainMessage(encodedNonce, _sender, _target, _value, _gasLimit, _data);\n\n // check that execution never makes it this far for an invalid version\n if (_version > 1) {\n failedCrossDomainHashHighVersion = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v0 schema\n * and compares the output of a call to the unversioned function to the v0 function directly\n */\n function testHashCrossDomainMessageV0(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 0\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 0);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV0(\n _target,\n _sender,\n _data,\n encodedNonce\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV0 = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v1 schema\n * and compares the output of a call to the unversioned function to the v1 function directly\n */\n function testHashCrossDomainMessageV1(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 1\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 1);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV1(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV1 = true;\n }\n }\n\n /**\n * @custom:invariant `hashCrossDomainMessage` reverts if `version` is > `1`.\n *\n * The `hashCrossDomainMessage` function should always revert if the `version` passed is > `1`.\n */\n function echidna_hash_xdomain_msg_high_version() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage will never succeed for a version > 1\n return !failedCrossDomainHashHighVersion;\n }\n\n /**\n * @custom:invariant `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0`\n * are equivalent.\n *\n * If the version passed is 0, `hashCrossDomainMessage` and `hashCrossDomainMessageV0` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_0() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV0\n // should always match when the version passed is 0\n return !failedCrossDomainHashV0;\n }\n\n /**\n * @custom:invariant `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1`\n * are equivalent.\n *\n * If the version passed is 1, `hashCrossDomainMessage` and `hashCrossDomainMessageV1` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_1() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV1\n // should always match when the version passed is 1\n return !failedCrossDomainHashV1;\n }\n}\n" - }, - "contracts/echidna/FuzzOptimismPortal.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract EchidnaFuzzOptimismPortal {\n OptimismPortal internal portal;\n bool internal failedToComplete;\n\n constructor() {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n SystemConfig systemConfig = new SystemConfig({\n _owner: address(1),\n _overhead: 0,\n _scalar: 10000,\n _batcherHash: bytes32(0),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(0),\n _config: rcfg\n });\n\n portal = new OptimismPortal({\n _l2Oracle: L2OutputOracle(address(0)),\n _guardian: address(0),\n _paused: false,\n _config: systemConfig\n });\n }\n\n // A test intended to identify any unexpected halting conditions\n function testDepositTransactionCompletes(\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable {\n failedToComplete = true;\n require(!_isCreation || _to == address(0), \"EchidnaFuzzOptimismPortal: invalid test case.\");\n portal.depositTransaction{ value: _mint }(_to, _value, _gasLimit, _isCreation, _data);\n failedToComplete = false;\n }\n\n /**\n * @custom:invariant Deposits of any value should always succeed unless\n * `_to` = `address(0)` or `_isCreation` = `true`.\n *\n * All deposits, barring creation transactions and transactions sent to `address(0)`,\n * should always succeed.\n */\n function echidna_deposit_completes() public view returns (bool) {\n return !failedToComplete;\n }\n}\n" - }, - "contracts/echidna/FuzzResourceMetering.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {\n bool internal failedMaxGasPerBlock;\n bool internal failedRaiseBaseFee;\n bool internal failedLowerBaseFee;\n bool internal failedNeverBelowMinBaseFee;\n bool internal failedMaxRaiseBaseFeePerBlock;\n bool internal failedMaxLowerBaseFeePerBlock;\n\n // Used as a special flag for the purpose of identifying unchecked math errors specifically\n // in the test contracts, not the target contracts themselves.\n bool internal underflow;\n\n constructor() {\n initialize();\n }\n\n function initialize() internal initializer {\n __ResourceMetering_init();\n }\n\n function resourceConfig() public pure returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig();\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n return rcfg;\n }\n\n /**\n * @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test\n * the underlying resource metering/gas market logic\n */\n function testBurn(uint256 _gasToBurn, bool _raiseBaseFee) public {\n // Part 1: we cache the current param values and do some basic checks on them.\n uint256 cachedPrevBaseFee = uint256(params.prevBaseFee);\n uint256 cachedPrevBoughtGas = uint256(params.prevBoughtGas);\n uint256 cachedPrevBlockNum = uint256(params.prevBlockNum);\n\n ResourceMetering.ResourceConfig memory rcfg = resourceConfig();\n uint256 targetResourceLimit = uint256(rcfg.maxResourceLimit) /\n uint256(rcfg.elasticityMultiplier);\n\n // check that the last block's base fee hasn't dropped below the minimum\n if (cachedPrevBaseFee < uint256(rcfg.minimumBaseFee)) {\n failedNeverBelowMinBaseFee = true;\n }\n // check that the last block didn't consume more than the max amount of gas\n if (cachedPrevBoughtGas > uint256(rcfg.maxResourceLimit)) {\n failedMaxGasPerBlock = true;\n }\n\n // Part2: we perform the gas burn\n\n // force the gasToBurn into the correct range based on whether we intend to\n // raise or lower the baseFee after this block, respectively\n uint256 gasToBurn;\n if (_raiseBaseFee) {\n gasToBurn = bound(\n _gasToBurn,\n uint256(targetResourceLimit),\n uint256(rcfg.maxResourceLimit)\n );\n } else {\n gasToBurn = bound(_gasToBurn, 0, targetResourceLimit);\n }\n\n _burnInternal(uint64(gasToBurn));\n\n // Part 3: we run checks and modify our invariant flags based on the updated params values\n\n // Calculate the maximum allowed baseFee change (per block)\n uint256 maxBaseFeeChange = cachedPrevBaseFee / uint256(rcfg.baseFeeMaxChangeDenominator);\n\n // If the last block used more than the target amount of gas (and there were no\n // empty blocks in between), ensure this block's baseFee increased, but not by\n // more than the max amount per block\n if (\n (cachedPrevBoughtGas > uint256(targetResourceLimit)) &&\n (uint256(params.prevBlockNum) - cachedPrevBlockNum == 1)\n ) {\n failedRaiseBaseFee = failedRaiseBaseFee || (params.prevBaseFee <= cachedPrevBaseFee);\n failedMaxRaiseBaseFeePerBlock =\n failedMaxRaiseBaseFeePerBlock ||\n ((uint256(params.prevBaseFee) - cachedPrevBaseFee) < maxBaseFeeChange);\n }\n\n // If the last block used less than the target amount of gas, (or was empty),\n // ensure that: this block's baseFee was decreased, but not by more than the max amount\n if (\n (cachedPrevBoughtGas < uint256(targetResourceLimit)) ||\n (uint256(params.prevBlockNum) - cachedPrevBlockNum > 1)\n ) {\n // Invariant: baseFee should decrease\n failedLowerBaseFee =\n failedLowerBaseFee ||\n (uint256(params.prevBaseFee) > cachedPrevBaseFee);\n\n if (params.prevBlockNum - cachedPrevBlockNum == 1) {\n // No empty blocks\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n } else if (params.prevBlockNum - cachedPrevBlockNum > 1) {\n // We have at least one empty block\n // Update the maxBaseFeeChange to account for multiple blocks having passed\n unchecked {\n maxBaseFeeChange = uint256(\n int256(cachedPrevBaseFee) -\n Arithmetic.clamp(\n Arithmetic.cdexp(\n int256(cachedPrevBaseFee),\n int256(uint256(rcfg.baseFeeMaxChangeDenominator)),\n int256(uint256(params.prevBlockNum) - cachedPrevBlockNum)\n ),\n int256(uint256(rcfg.minimumBaseFee)),\n int256(uint256(rcfg.maximumBaseFee))\n )\n );\n }\n\n // Detect an underflow in the previous calculation.\n // Without using unchecked above, and detecting the underflow here, echidna would\n // otherwise ignore the revert.\n underflow = underflow || maxBaseFeeChange > cachedPrevBaseFee;\n\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n }\n }\n }\n\n function _burnInternal(uint64 _gasToBurn) private metered(_gasToBurn) {}\n\n /**\n * @custom:invariant The base fee should increase if the last block used more\n * than the target amount of gas\n *\n * If the last block used more than the target amount of gas (and there were no\n * empty blocks in between), ensure this block's baseFee increased, but not by\n * more than the max amount per block.\n */\n function echidna_high_usage_raise_baseFee() public view returns (bool) {\n return !failedRaiseBaseFee;\n }\n\n /**\n * @custom:invariant The base fee should decrease if the last block used less\n * than the target amount of gas\n *\n * If the previous block used less than the target amount of gas, the base fee should decrease,\n * but not more than the max amount.\n */\n function echidna_low_usage_lower_baseFee() public view returns (bool) {\n return !failedLowerBaseFee;\n }\n\n /**\n * @custom:invariant A block's base fee should never be below `MINIMUM_BASE_FEE`\n *\n * This test asserts that a block's base fee can never drop below the\n * `MINIMUM_BASE_FEE` threshold.\n */\n function echidna_never_below_min_baseFee() public view returns (bool) {\n return !failedNeverBelowMinBaseFee;\n }\n\n /**\n * @custom:invariant A block can never consume more than `MAX_RESOURCE_LIMIT` gas.\n *\n * This test asserts that a block can never consume more than the `MAX_RESOURCE_LIMIT`\n * gas threshold.\n */\n function echidna_never_above_max_gas_limit() public view returns (bool) {\n return !failedMaxGasPerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be raised more than the max base fee change.\n *\n * After a block consumes more gas than the target gas, the base fee cannot be raised\n * more than the maximum amount allowed. The max base fee change (per-block) is derived\n * as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_increase() public view returns (bool) {\n return !failedMaxRaiseBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be lowered more than the max base fee change.\n *\n * After a block consumes less than the target gas, the base fee cannot be lowered more\n * than the maximum amount allowed. The max base fee change (per-block) is derived as\n *follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_decrease() public view returns (bool) {\n return !failedMaxLowerBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The `maxBaseFeeChange` calculation over multiple blocks can never\n * underflow.\n *\n * When calculating the `maxBaseFeeChange` after multiple empty blocks, the calculation\n * should never be allowed to underflow.\n */\n function echidna_underflow() public view returns (bool) {\n return !underflow;\n }\n}\n" - }, - "contracts/governance/GovernanceToken.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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 * @custom:predeploy 0x4200000000000000000000000000000000000042\n * @title GovernanceToken\n * @notice The Optimism token used in governance and supporting voting and delegation. Implements\n * EIP 2612 allowing signed approvals. Contract is \"owned\" by a `MintManager` instance with\n * permission to the `mint` function only, for the purposes of enforcing the token inflation\n * schedule.\n */\ncontract GovernanceToken is ERC20Burnable, ERC20Votes, Ownable {\n constructor() ERC20(\"Optimism\", \"OP\") ERC20Permit(\"Optimism\") {}\n\n /**\n * @notice Allows the owner to mint tokens.\n *\n * @param _account The account receiving minted tokens.\n * @param _amount The amount of tokens to mint.\n */\n function mint(address _account, uint256 _amount) public onlyOwner {\n _mint(_account, _amount);\n }\n\n /**\n * @notice Callback called after a token transfer.\n *\n * @param from The account sending tokens.\n * @param to The account receiving tokens.\n * @param amount The amount of tokens being transfered.\n */\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 /**\n * @notice Internal mint function.\n *\n * @param to The account receiving minted tokens.\n * @param amount The amount of tokens to mint.\n */\n function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._mint(to, amount);\n }\n\n /**\n * @notice Internal burn function.\n *\n * @param account The account that tokens will be burned from.\n * @param amount The amount of tokens that will be burned.\n */\n function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._burn(account, amount);\n }\n}\n" - }, - "contracts/governance/MintManager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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(\n mintPermittedAfter <= block.timestamp,\n \"MintManager: minting not permitted yet\"\n );\n\n require(\n _amount <= (governanceToken.totalSupply() * MINT_CAP) / DENOMINATOR,\n \"MintManager: mint amount exceeds cap\"\n );\n }\n\n mintPermittedAfter = block.timestamp + MINT_PERIOD;\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(\n _newMintManager != address(0),\n \"MintManager: mint manager cannot be the zero address\"\n );\n\n governanceToken.transferOwnership(_newMintManager);\n }\n}\n" - }, - "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" - }, - "contracts/legacy/DeployerWhitelist.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000002\n * @title DeployerWhitelist\n * @notice DeployerWhitelist is a legacy contract that was originally used to act as a whitelist of\n * addresses allowed to the Optimism network. The DeployerWhitelist has since been\n * disabled, but the code is kept in state for the sake of full backwards compatibility.\n * As of the Bedrock upgrade, the DeployerWhitelist is completely unused by the Optimism\n * system and could, in theory, be removed entirely.\n */\ncontract DeployerWhitelist is Semver {\n /**\n * @notice Address of the owner of this contract. Note that when this address is set to\n * address(0), the whitelist is disabled.\n */\n address public owner;\n\n /**\n * @notice Mapping of deployer addresses to boolean whitelist status.\n */\n mapping(address => bool) public whitelist;\n\n /**\n * @notice Emitted when the owner of this contract changes.\n *\n * @param oldOwner Address of the previous owner.\n * @param newOwner Address of the new owner.\n */\n event OwnerChanged(address oldOwner, address newOwner);\n\n /**\n * @notice Emitted when the whitelist status of a deployer changes.\n *\n * @param deployer Address of the deployer.\n * @param whitelisted Boolean indicating whether the deployer is whitelisted.\n */\n event WhitelistStatusChanged(address deployer, bool whitelisted);\n\n /**\n * @notice Emitted when the whitelist is disabled.\n *\n * @param oldOwner Address of the final owner of the whitelist.\n */\n event WhitelistDisabled(address oldOwner);\n\n /**\n * @notice Blocks functions to anyone except the contract owner.\n */\n modifier onlyOwner() {\n require(\n msg.sender == owner,\n \"DeployerWhitelist: function can only be called by the owner of this contract\"\n );\n _;\n }\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Adds or removes an address from the deployment whitelist.\n *\n * @param _deployer Address to update permissions for.\n * @param _isWhitelisted Whether or not the address is whitelisted.\n */\n function setWhitelistedDeployer(address _deployer, bool _isWhitelisted) external onlyOwner {\n whitelist[_deployer] = _isWhitelisted;\n emit WhitelistStatusChanged(_deployer, _isWhitelisted);\n }\n\n /**\n * @notice Updates the owner of this contract.\n *\n * @param _owner Address of the new owner.\n */\n function setOwner(address _owner) external onlyOwner {\n // Prevent users from setting the whitelist owner to address(0) except via\n // enableArbitraryContractDeployment. If you want to burn the whitelist owner, send it to\n // any other address that doesn't have a corresponding knowable private key.\n require(\n _owner != address(0),\n \"DeployerWhitelist: can only be disabled via enableArbitraryContractDeployment\"\n );\n\n emit OwnerChanged(owner, _owner);\n owner = _owner;\n }\n\n /**\n * @notice Permanently enables arbitrary contract deployment and deletes the owner.\n */\n function enableArbitraryContractDeployment() external onlyOwner {\n emit WhitelistDisabled(owner);\n owner = address(0);\n }\n\n /**\n * @notice Checks whether an address is allowed to deploy contracts.\n *\n * @param _deployer Address to check.\n *\n * @return Whether or not the address can deploy contracts.\n */\n function isDeployerAllowed(address _deployer) external view returns (bool) {\n return (owner == address(0) || whitelist[_deployer]);\n }\n}\n" - }, - "contracts/legacy/L1BlockNumber.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000013\n * @title L1BlockNumber\n * @notice L1BlockNumber is a legacy contract that fills the roll of the OVM_L1BlockNumber contract\n * in the old version of the Optimism system. Only necessary for backwards compatibility.\n * If you want to access the L1 block number going forward, you should use the L1Block\n * contract instead.\n */\ncontract L1BlockNumber is Semver {\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Returns the L1 block number.\n */\n receive() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Returns the L1 block number.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Retrieves the latest L1 block number.\n *\n * @return Latest L1 block number.\n */\n function getL1BlockNumber() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).number();\n }\n}\n" - }, - "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/legacy/LegacyERC20ETH.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000\n * @title LegacyERC20ETH\n * @notice LegacyERC20ETH is a legacy contract that held ETH balances before the Bedrock upgrade.\n * All ETH balances held within this contract were migrated to the state trie as part of\n * the Bedrock upgrade. Functions within this contract that mutate state were already\n * disabled as part of the EVM equivalence upgrade.\n */\ncontract LegacyERC20ETH is OptimismMintableERC20 {\n /**\n * @notice Initializes the contract as an Optimism Mintable ERC20.\n */\n constructor()\n OptimismMintableERC20(Predeploys.L2_STANDARD_BRIDGE, address(0), \"Ether\", \"ETH\")\n {}\n\n /**\n * @notice Returns the ETH balance of the target account. Overrides the base behavior of the\n * contract to preserve the invariant that the balance within this contract always\n * matches the balance in the state trie.\n *\n * @param _who Address of the account to query.\n *\n * @return The ETH balance of the target account.\n */\n function balanceOf(address _who) public view virtual override returns (uint256) {\n return address(_who).balance;\n }\n\n /**\n * @custom:blocked\n * @notice Mints some amount of ETH.\n */\n function mint(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: mint is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Burns some amount of ETH.\n */\n function burn(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: burn is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers some amount of ETH.\n */\n function transfer(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transfer is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Approves a spender to spend some amount of ETH.\n */\n function approve(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: approve is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers funds from some sender account.\n */\n function transferFrom(\n address,\n address,\n uint256\n ) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transferFrom is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Increases the allowance of a spender.\n */\n function increaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Decreases the allowance of a spender.\n */\n function decreaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n }\n}\n" - }, - "contracts/legacy/LegacyMessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000000\n * @title LegacyMessagePasser\n * @notice The LegacyMessagePasser was the low-level mechanism used to send messages from L2 to L1\n * before the Bedrock upgrade. It is now deprecated in favor of the new MessagePasser.\n */\ncontract LegacyMessagePasser is Semver {\n /**\n * @notice Mapping of sent message hashes to boolean status.\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Passes a message to L1.\n *\n * @param _message Message to pass to L1.\n */\n function passMessageToL1(bytes memory _message) external {\n sentMessages[keccak256(abi.encodePacked(_message, msg.sender))] = true;\n }\n}\n" - }, - "contracts/legacy/LegacyMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { ILegacyMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @title LegacyMintableERC20\n * @notice The legacy implementation of the OptimismMintableERC20. This\n * contract is deprecated and should no longer be used.\n */\ncontract LegacyMintableERC20 is ILegacyMintableERC20, ERC20 {\n /**\n * @notice Emitted when the token is minted by the bridge.\n */\n event Mint(address indexed _account, uint256 _amount);\n\n /**\n * @notice Emitted when a token is burned by the bridge.\n */\n event Burn(address indexed _account, uint256 _amount);\n\n /**\n * @notice The token on the remote domain.\n */\n address public l1Token;\n\n /**\n * @notice The local bridge.\n */\n address public l2Bridge;\n\n /**\n * @param _l2Bridge Address of the L2 standard bridge.\n * @param _l1Token Address of the corresponding L1 token.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n */\n constructor(\n address _l2Bridge,\n address _l1Token,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) {\n l1Token = _l1Token;\n l2Bridge = _l2Bridge;\n }\n\n /**\n * @notice Modifier that requires the contract was called by the bridge.\n */\n modifier onlyL2Bridge() {\n require(msg.sender == l2Bridge, \"Only L2 Bridge can mint and burn\");\n _;\n }\n\n /**\n * @notice EIP165 implementation.\n */\n function supportsInterface(bytes4 _interfaceId) public pure returns (bool) {\n bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^\n ILegacyMintableERC20.mint.selector ^\n ILegacyMintableERC20.burn.selector;\n return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n }\n\n /**\n * @notice Only the bridge can mint tokens.\n * @param _to The account receiving tokens.\n * @param _amount The amount of tokens to receive.\n */\n function mint(address _to, uint256 _amount) public virtual onlyL2Bridge {\n _mint(_to, _amount);\n\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Only the bridge can burn tokens.\n * @param _from The account having tokens burnt.\n * @param _amount The amount of tokens being burnt.\n */\n function burn(address _from, uint256 _amount) public virtual onlyL2Bridge {\n _burn(_from, _amount);\n\n emit Burn(_from, _amount);\n }\n}\n" - }, - "contracts/legacy/ResolvedDelegateProxy.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressManager } from \"./AddressManager.sol\";\n\n/**\n * @custom:legacy\n * @title ResolvedDelegateProxy\n * @notice ResolvedDelegateProxy is a legacy proxy contract that makes use of the AddressManager to\n * resolve the implementation address. We're maintaining this contract for backwards\n * compatibility so we can manage all legacy proxies where necessary.\n */\ncontract ResolvedDelegateProxy {\n /**\n * @notice Mapping used to store the implementation name that corresponds to this contract. A\n * mapping was originally used as a way to bypass the same issue normally solved by\n * storing the implementation address in a specific storage slot that does not conflict\n * with any other storage slot. Generally NOT a safe solution but works as long as the\n * implementation does not also keep a mapping in the first storage slot.\n */\n mapping(address => string) private implementationName;\n\n /**\n * @notice Mapping used to store the address of the AddressManager contract where the\n * implementation address will be resolved from. Same concept here as with the above\n * mapping. Also generally unsafe but fine if the implementation doesn't keep a mapping\n * in the second storage slot.\n */\n mapping(address => AddressManager) private addressManager;\n\n /**\n * @param _addressManager Address of the AddressManager.\n * @param _implementationName implementationName of the contract to proxy to.\n */\n constructor(AddressManager _addressManager, string memory _implementationName) {\n addressManager[address(this)] = _addressManager;\n implementationName[address(this)] = _implementationName;\n }\n\n /**\n * @notice Fallback, performs a delegatecall to the resolved implementation address.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n address target = addressManager[address(this)].getAddress(\n (implementationName[address(this)])\n );\n\n require(target != address(0), \"ResolvedDelegateProxy: target address must be initialized\");\n\n // slither-disable-next-line controlled-delegatecall\n (bool success, bytes memory returndata) = target.delegatecall(msg.data);\n\n if (success == true) {\n assembly {\n return(add(returndata, 0x20), mload(returndata))\n }\n } else {\n assembly {\n revert(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n" - }, - "contracts/libraries/Arithmetic.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { SignedMath } from \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\nimport { FixedPointMathLib } from \"@rari-capital/solmate/src/utils/FixedPointMathLib.sol\";\n\n/**\n * @title Arithmetic\n * @notice Even more math than before.\n */\nlibrary Arithmetic {\n /**\n * @notice Clamps a value between a minimum and maximum.\n *\n * @param _value The value to clamp.\n * @param _min The minimum value.\n * @param _max The maximum value.\n *\n * @return The clamped value.\n */\n function clamp(\n int256 _value,\n int256 _min,\n int256 _max\n ) internal pure returns (int256) {\n return SignedMath.min(SignedMath.max(_value, _min), _max);\n }\n\n /**\n * @notice (c)oefficient (d)enominator (exp)onentiation function.\n * Returns the result of: c * (1 - 1/d)^exp.\n *\n * @param _coefficient Coefficient of the function.\n * @param _denominator Fractional denominator.\n * @param _exponent Power function exponent.\n *\n * @return Result of c * (1 - 1/d)^exp.\n */\n function cdexp(\n int256 _coefficient,\n int256 _denominator,\n int256 _exponent\n ) internal pure returns (int256) {\n return\n (_coefficient *\n (FixedPointMathLib.powWad(1e18 - (1e18 / _denominator), _exponent * 1e18))) / 1e18;\n }\n}\n" - }, - "contracts/libraries/Burn.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Burn\n * @notice Utilities for burning stuff.\n */\nlibrary Burn {\n /**\n * Burns a given amount of ETH.\n *\n * @param _amount Amount of ETH to burn.\n */\n function eth(uint256 _amount) internal {\n new Burner{ value: _amount }();\n }\n\n /**\n * Burns a given amount of gas.\n *\n * @param _amount Amount of gas to burn.\n */\n function gas(uint256 _amount) internal view {\n uint256 i = 0;\n uint256 initialGas = gasleft();\n while (initialGas - gasleft() < _amount) {\n ++i;\n }\n }\n}\n\n/**\n * @title Burner\n * @notice Burner self-destructs on creation and sends all ETH to itself, removing all ETH given to\n * the contract from the circulating supply. Self-destructing is the only way to remove ETH\n * from the circulating supply.\n */\ncontract Burner {\n constructor() payable {\n selfdestruct(payable(address(this)));\n }\n}\n" - }, - "contracts/libraries/Bytes.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Bytes\n * @notice Bytes is a library for manipulating byte arrays.\n */\nlibrary Bytes {\n /**\n * @custom:attribution https://github.com/GNSPS/solidity-bytes-utils\n * @notice Slices a byte array with a given starting index and length. Returns a new byte array\n * as opposed to a pointer to the original array. Will throw if trying to slice more\n * bytes than exist in the array.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n * @param _length Length of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n unchecked {\n require(_length + 31 >= _length, \"slice_overflow\");\n require(_start + _length >= _start, \"slice_overflow\");\n require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n }\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n /**\n * @notice Slices a byte array with a given starting index up to the end of the original byte\n * array. Returns a new array rathern than a pointer to the original.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {\n if (_start >= _bytes.length) {\n return bytes(\"\");\n }\n return slice(_bytes, _start, _bytes.length - _start);\n }\n\n /**\n * @notice Converts a byte array into a nibble array by splitting each byte into two nibbles.\n * Resulting nibble array will be exactly twice as long as the input byte array.\n *\n * @param _bytes Input byte array to convert.\n *\n * @return Resulting nibble array.\n */\n function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n uint256 bytesLength = _bytes.length;\n bytes memory nibbles = new bytes(bytesLength * 2);\n bytes1 b;\n\n for (uint256 i = 0; i < bytesLength; ) {\n b = _bytes[i];\n nibbles[i * 2] = b >> 4;\n nibbles[i * 2 + 1] = b & 0x0f;\n unchecked {\n ++i;\n }\n }\n\n return nibbles;\n }\n\n /**\n * @notice Compares two byte arrays by comparing their keccak256 hashes.\n *\n * @param _bytes First byte array to compare.\n * @param _other Second byte array to compare.\n *\n * @return True if the two byte arrays are equal, false otherwise.\n */\n function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {\n return keccak256(_bytes) == keccak256(_other);\n }\n}\n" - }, - "contracts/libraries/Constants.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\n/**\n * @title Constants\n * @notice Constants is a library for storing constants. Simple! Don't put everything in here, just\n * the stuff used in multiple contracts. Constants that only apply to a single contract\n * should be defined in that contract instead.\n */\nlibrary Constants {\n /**\n * @notice Special address to be used as the tx origin for gas estimation calls in the\n * OptimismPortal and CrossDomainMessenger calls. You only need to use this address if\n * the minimum gas limit specified by the user is not actually enough to execute the\n * given message and you're attempting to estimate the actual necessary gas limit. We\n * use address(1) because it's the ecrecover precompile and therefore guaranteed to\n * never have any code on any EVM chain.\n */\n address internal constant ESTIMATION_ADDRESS = address(1);\n\n /**\n * @notice Value used for the L2 sender storage slot in both the OptimismPortal and the\n * CrossDomainMessenger contracts before an actual sender is set. This value is\n * non-zero to reduce the gas cost of message passing transactions.\n */\n address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD;\n\n /**\n * @notice Returns the default values for the ResourceConfig. These are the recommended values\n * for a production network.\n */\n function DEFAULT_RESOURCE_CONFIG()\n internal\n pure\n returns (ResourceMetering.ResourceConfig memory)\n {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n return config;\n }\n}\n" - }, - "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" - }, - "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" - }, - "contracts/libraries/LegacyCrossDomainUtils.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n// Importing from the legacy contracts package causes issues with the build of the contract bindings\n// so we just copy the library here from\n// /packages/contracts/contracts/libraries/bridge/Lib_CrossDomainUtils.sol at commit\n// 7866168c\n/**\n * @title LegacyCrossDomainUtils\n */\nlibrary LegacyCrossDomainUtils {\n /**\n * Generates the correct cross domain calldata for a message.\n * @param _target Target contract address.\n * @param _sender Message sender address.\n * @param _message Message to send to the target.\n * @param _messageNonce Nonce for the provided message.\n * @return ABI encoded cross domain calldata.\n */\n function encodeXDomainCalldata(\n address _target,\n address _sender,\n bytes memory _message,\n uint256 _messageNonce\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(address,address,bytes,uint256)\",\n _target,\n _sender,\n _message,\n _messageNonce\n );\n }\n}\n" - }, - "contracts/libraries/Predeploys.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Predeploys\n * @notice Contains constant addresses for contracts that are pre-deployed to the L2 system.\n */\nlibrary Predeploys {\n /**\n * @notice Address of the L2ToL1MessagePasser predeploy.\n */\n address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016;\n\n /**\n * @notice Address of the L2CrossDomainMessenger predeploy.\n */\n address internal constant L2_CROSS_DOMAIN_MESSENGER =\n 0x4200000000000000000000000000000000000007;\n\n /**\n * @notice Address of the L2StandardBridge predeploy.\n */\n address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;\n\n /**\n * @notice Address of the L2ERC721Bridge predeploy.\n */\n address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014;\n\n /**\n * @notice Address of the SequencerFeeWallet predeploy.\n */\n address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;\n\n /**\n * @notice Address of the OptimismMintableERC20Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY =\n 0x4200000000000000000000000000000000000012;\n\n /**\n * @notice Address of the OptimismMintableERC721Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY =\n 0x4200000000000000000000000000000000000017;\n\n /**\n * @notice Address of the L1Block predeploy.\n */\n address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015;\n\n /**\n * @notice Address of the GasPriceOracle predeploy. Includes fee information\n * and helpers for computing the L1 portion of the transaction fee.\n */\n address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F;\n\n /**\n * @custom:legacy\n * @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger\n * or access tx.origin (or msg.sender) in a L1 to L2 transaction instead.\n */\n address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;\n\n /**\n * @custom:legacy\n * @notice Address of the DeployerWhitelist predeploy. No longer active.\n */\n address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the\n * state trie as of the Bedrock upgrade. Contract has been locked and write functions\n * can no longer be accessed.\n */\n address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;\n\n /**\n * @custom:legacy\n * @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy\n * instead, which exposes more information about the L1 state.\n */\n address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated\n * L2ToL1MessagePasser contract instead.\n */\n address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;\n\n /**\n * @notice Address of the ProxyAdmin predeploy.\n */\n address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018;\n\n /**\n * @notice Address of the BaseFeeVault predeploy.\n */\n address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019;\n\n /**\n * @notice Address of the L1FeeVault predeploy.\n */\n address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A;\n\n /**\n * @notice Address of the GovernanceToken predeploy.\n */\n address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042;\n}\n" - }, - "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, 32), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n\n /**\n * @notice Perform a low level call without copying any returndata. This function\n * will revert if the call cannot be performed with the specified minimum\n * gas.\n *\n * @param _target Address to call\n * @param _minGas The minimum amount of gas that may be passed 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 callWithMinGas(\n address _target,\n uint256 _minGas,\n uint256 _value,\n bytes memory _calldata\n ) internal returns (bool) {\n bool _success;\n assembly {\n // Assertion: gasleft() >= ((_minGas + 200) * 64) / 63\n //\n // Because EIP-150 ensures that, a maximum of 63/64ths of the remaining gas in the call\n // frame may be passed to a subcontext, we need to ensure that the gas will not be\n // truncated to hold this function's invariant: \"If a call is performed by\n // `callWithMinGas`, it must receive at least the specified minimum gas limit.\" In\n // addition, exactly 51 gas is consumed between the below `GAS` opcode and the `CALL`\n // opcode, so it is factored in with some extra room for error.\n if lt(gas(), div(mul(64, add(_minGas, 200)), 63)) {\n // Store the \"Error(string)\" selector in scratch space.\n mstore(0, 0x08c379a0)\n // Store the pointer to the string length in scratch space.\n mstore(32, 32)\n // Store the string.\n //\n // SAFETY:\n // - We pad the beginning of the string with two zero bytes as well as the\n // length (24) to ensure that we override the free memory pointer at offset\n // 0x40. This is necessary because the free memory pointer is likely to\n // be greater than 1 byte when this function is called, but it is incredibly\n // unlikely that it will be greater than 3 bytes. As for the data within\n // 0x60, it is ensured that it is 0 due to 0x60 being the zero offset.\n // - It's fine to clobber the free memory pointer, we're reverting.\n mstore(88, 0x0000185361666543616c6c3a204e6f7420656e6f75676820676173)\n\n // Revert with 'Error(\"SafeCall: Not enough gas\")'\n revert(28, 100)\n }\n\n // The call will be supplied at least (((_minGas + 200) * 64) / 63) - 49 gas due to the\n // above assertion. This ensures that, in all circumstances, the call will\n // receive at least the minimum amount of gas specified.\n // We can prove this property by solving the inequalities:\n // ((((_minGas + 200) * 64) / 63) - 49) >= _minGas\n // ((((_minGas + 200) * 64) / 63) - 51) * (63 / 64) >= _minGas\n // Both inequalities hold true for all possible values of `_minGas`.\n _success := call(\n gas(), // gas\n _target, // recipient\n _value, // ether value\n add(_calldata, 32), // inloc\n mload(_calldata), // inlen\n 0x00, // outloc\n 0x00 // outlen\n )\n }\n return _success;\n }\n}\n" - }, - "contracts/libraries/Types.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 * @custom:field outputRoot Hash of the L2 output.\n * @custom:field timestamp Timestamp of the L1 block that the output root was submitted in.\n * @custom:field l2BlockNumber L2 block number that the output corresponds to.\n */\n struct OutputProposal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2BlockNumber;\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 * @custom:field version Version of the output root.\n * @custom:field stateRoot Root of the state trie at the block of this output.\n * @custom:field messagePasserStorageRoot Root of the message passer storage trie.\n * @custom:field latestBlockhash Hash of the block this output was generated from.\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 * @custom:field from Address of the sender of the transaction.\n * @custom:field to Address of the recipient of the transaction.\n * @custom:field isCreation True if the transaction is a contract creation.\n * @custom:field value Value to send to the recipient.\n * @custom:field mint Amount of ETH to mint.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the transaction.\n * @custom:field l1BlockHash Hash of the block the transaction was submitted in.\n * @custom:field logIndex Index of the log in the block the transaction was submitted in.\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 * @custom:field nonce Nonce of the withdrawal transaction\n * @custom:field sender Address of the sender of the transaction.\n * @custom:field target Address of the recipient of the transaction.\n * @custom:field value Value to send to the recipient.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the 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" - }, - "contracts/libraries/rlp/RLPReader.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\n/**\n * @custom:attribution https://github.com/hamdiallam/Solidity-RLP\n * @title RLPReader\n * @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted\n * from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with\n * various tweaks to improve readability.\n */\nlibrary RLPReader {\n /**\n * Custom pointer type to avoid confusion between pointers and uint256s.\n */\n type MemoryPointer is uint256;\n\n /**\n * @notice RLP item types.\n *\n * @custom:value DATA_ITEM Represents an RLP data item (NOT a list).\n * @custom:value LIST_ITEM Represents an RLP list item.\n */\n enum RLPItemType {\n DATA_ITEM,\n LIST_ITEM\n }\n\n /**\n * @notice Struct representing an RLP item.\n *\n * @custom:field length Length of the RLP item.\n * @custom:field ptr Pointer to the RLP item in memory.\n */\n struct RLPItem {\n uint256 length;\n MemoryPointer ptr;\n }\n\n /**\n * @notice Max list length that this library will accept.\n */\n uint256 internal constant MAX_LIST_LENGTH = 32;\n\n /**\n * @notice Converts bytes to a reference to memory position and length.\n *\n * @param _in Input bytes to convert.\n *\n * @return Output memory reference.\n */\n function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) {\n // Empty arrays are not RLP items.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr;\n assembly {\n ptr := add(_in, 32)\n }\n\n return RLPItem({ length: _in.length, ptr: ptr });\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) {\n (uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.LIST_ITEM,\n \"RLPReader: decoded item type for list is not a list item\"\n );\n\n require(\n listOffset + listLength == _in.length,\n \"RLPReader: list item has an invalid data remainder\"\n );\n\n // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by\n // writing to the length. Since we can't know the number of RLP items without looping over\n // the entire input, we'd have to loop twice to accurately size this array. It's easier to\n // simply set a reasonable maximum list length and decrease the size before we finish.\n RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH);\n\n uint256 itemCount = 0;\n uint256 offset = listOffset;\n while (offset < _in.length) {\n (uint256 itemOffset, uint256 itemLength, ) = _decodeLength(\n RLPItem({\n length: _in.length - offset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n })\n );\n\n // We don't need to check itemCount < out.length explicitly because Solidity already\n // handles this check on our behalf, we'd just be wasting gas.\n out[itemCount] = RLPItem({\n length: itemLength + itemOffset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n });\n\n itemCount += 1;\n offset += itemOffset + itemLength;\n }\n\n // Decrease the array size to match the actual item count.\n assembly {\n mstore(out, itemCount)\n }\n\n return out;\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(bytes memory _in) internal pure returns (RLPItem[] memory) {\n return readList(toRLPItem(_in));\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.DATA_ITEM,\n \"RLPReader: decoded item type for bytes is not a data item\"\n );\n\n require(\n _in.length == itemOffset + itemLength,\n \"RLPReader: bytes value contains an invalid remainder\"\n );\n\n return _copy(_in.ptr, itemOffset, itemLength);\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(bytes memory _in) internal pure returns (bytes memory) {\n return readBytes(toRLPItem(_in));\n }\n\n /**\n * @notice Reads the raw bytes of an RLP item.\n *\n * @param _in RLP item to read.\n *\n * @return Raw RLP bytes.\n */\n function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n return _copy(_in.ptr, 0, _in.length);\n }\n\n /**\n * @notice Decodes the length of an RLP item.\n *\n * @param _in RLP item to decode.\n *\n * @return Offset of the encoded data.\n * @return Length of the encoded data.\n * @return RLP item type (LIST_ITEM or DATA_ITEM).\n */\n function _decodeLength(RLPItem memory _in)\n private\n pure\n returns (\n uint256,\n uint256,\n RLPItemType\n )\n {\n // Short-circuit if there's nothing to decode, note that we perform this check when\n // the user creates an RLP item via toRLPItem, but it's always possible for them to bypass\n // that function and create an RLP item directly. So we need to check this anyway.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr = _in.ptr;\n uint256 prefix;\n assembly {\n prefix := byte(0, mload(ptr))\n }\n\n if (prefix <= 0x7f) {\n // Single byte.\n return (0, 1, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xb7) {\n // Short string.\n\n // slither-disable-next-line variable-scope\n uint256 strLen = prefix - 0x80;\n\n require(\n _in.length > strLen,\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n strLen != 1 || firstByteOfContent >= 0x80,\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n\n return (1, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xbf) {\n // Long string.\n uint256 lenOfStrLen = prefix - 0xb7;\n\n require(\n _in.length > lenOfStrLen,\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n\n uint256 strLen;\n assembly {\n strLen := shr(sub(256, mul(8, lenOfStrLen)), mload(add(ptr, 1)))\n }\n\n require(\n strLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long string)\"\n );\n\n require(\n _in.length > lenOfStrLen + strLen,\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n\n return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xf7) {\n // Short list.\n // slither-disable-next-line variable-scope\n uint256 listLen = prefix - 0xc0;\n\n require(\n _in.length > listLen,\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n\n return (1, listLen, RLPItemType.LIST_ITEM);\n } else {\n // Long list.\n uint256 lenOfListLen = prefix - 0xf7;\n\n require(\n _in.length > lenOfListLen,\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long list)\"\n );\n\n uint256 listLen;\n assembly {\n listLen := shr(sub(256, mul(8, lenOfListLen)), mload(add(ptr, 1)))\n }\n\n require(\n listLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long list)\"\n );\n\n require(\n _in.length > lenOfListLen + listLen,\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n\n return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);\n }\n }\n\n /**\n * @notice Copies the bytes from a memory location.\n *\n * @param _src Pointer to the location to read from.\n * @param _offset Offset to start reading from.\n * @param _length Number of bytes to read.\n *\n * @return Copied bytes.\n */\n function _copy(\n MemoryPointer _src,\n uint256 _offset,\n uint256 _length\n ) private pure returns (bytes memory) {\n bytes memory out = new bytes(_length);\n if (_length == 0) {\n return out;\n }\n\n // Mostly based on Solidity's copy_memory_to_memory:\n // solhint-disable max-line-length\n // https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114\n uint256 src = MemoryPointer.unwrap(_src) + _offset;\n assembly {\n let dest := add(out, 32)\n let i := 0\n for {\n\n } lt(i, _length) {\n i := add(i, 32)\n } {\n mstore(add(dest, i), mload(add(src, i)))\n }\n\n if gt(i, _length) {\n mstore(add(dest, _length), 0)\n }\n }\n\n return out;\n }\n}\n" - }, - "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" - }, - "contracts/libraries/trie/MerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Bytes } from \"../Bytes.sol\";\nimport { RLPReader } from \"../rlp/RLPReader.sol\";\n\n/**\n * @title MerkleTrie\n * @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie\n * inclusion proofs. By default, this library assumes a hexary trie. One can change the\n * trie radix constant to support other trie radixes.\n */\nlibrary MerkleTrie {\n /**\n * @notice Struct representing a node in the trie.\n *\n * @custom:field encoded The RLP-encoded node.\n * @custom:field decoded The RLP-decoded node.\n */\n struct TrieNode {\n bytes encoded;\n RLPReader.RLPItem[] decoded;\n }\n\n /**\n * @notice Determines the number of elements per branch node.\n */\n uint256 internal constant TREE_RADIX = 16;\n\n /**\n * @notice Branch nodes have TREE_RADIX elements and one value element.\n */\n uint256 internal constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;\n\n /**\n * @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.\n */\n uint256 internal constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;\n\n /**\n * @notice Prefix for even-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_EVEN = 0;\n\n /**\n * @notice Prefix for odd-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_ODD = 1;\n\n /**\n * @notice Prefix for even-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_EVEN = 2;\n\n /**\n * @notice Prefix for odd-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_ODD = 3;\n\n /**\n * @notice Verifies a proof that a given key/value pair is present in the trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n return Bytes.equal(_value, get(_key, _proof, _root));\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n require(_key.length > 0, \"MerkleTrie: empty key\");\n\n TrieNode[] memory proof = _parseProof(_proof);\n bytes memory key = Bytes.toNibbles(_key);\n bytes memory currentNodeID = abi.encodePacked(_root);\n uint256 currentKeyIndex = 0;\n\n // Proof is top-down, so we start at the first element (root).\n for (uint256 i = 0; i < proof.length; i++) {\n TrieNode memory currentNode = proof[i];\n\n // Key index should never exceed total key length or we'll be out of bounds.\n require(\n currentKeyIndex <= key.length,\n \"MerkleTrie: key index exceeds total key length\"\n );\n\n if (currentKeyIndex == 0) {\n // First proof element is always the root node.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid root hash\"\n );\n } else if (currentNode.encoded.length >= 32) {\n // Nodes 32 bytes or larger are hashed inside branch nodes.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid large internal hash\"\n );\n } else {\n // Nodes smaller than 32 bytes aren't hashed.\n require(\n Bytes.equal(currentNode.encoded, currentNodeID),\n \"MerkleTrie: invalid internal node hash\"\n );\n }\n\n if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {\n if (currentKeyIndex == key.length) {\n // Value is the last element of the decoded list (for branch nodes). There's\n // some ambiguity in the Merkle trie specification because bytes(0) is a\n // valid value to place into the trie, but for branch nodes bytes(0) can exist\n // even when the value wasn't explicitly placed there. Geth treats a value of\n // bytes(0) as \"key does not exist\" and so we do the same.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[TREE_RADIX]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (branch)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (branch)\"\n );\n\n return value;\n } else {\n // We're not at the end of the key yet.\n // Figure out what the next node ID should be and continue.\n uint8 branchKey = uint8(key[currentKeyIndex]);\n RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];\n currentNodeID = _getNodeID(nextNode);\n currentKeyIndex += 1;\n }\n } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {\n bytes memory path = _getNodePath(currentNode);\n uint8 prefix = uint8(path[0]);\n uint8 offset = 2 - (prefix % 2);\n bytes memory pathRemainder = Bytes.slice(path, offset);\n bytes memory keyRemainder = Bytes.slice(key, currentKeyIndex);\n uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);\n\n // Whether this is a leaf node or an extension node, the path remainder MUST be a\n // prefix of the key remainder (or be equal to the key remainder) or the proof is\n // considered invalid.\n require(\n pathRemainder.length == sharedNibbleLength,\n \"MerkleTrie: path remainder must share all nibbles with key\"\n );\n\n if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {\n // Prefix of 2 or 3 means this is a leaf node. For the leaf node to be valid,\n // the key remainder must be exactly equal to the path remainder. We already\n // did the necessary byte comparison, so it's more efficient here to check that\n // the key remainder length equals the shared nibble length, which implies\n // equality with the path remainder (since we already did the same check with\n // the path remainder and the shared nibble length).\n require(\n keyRemainder.length == sharedNibbleLength,\n \"MerkleTrie: key remainder must be identical to path remainder\"\n );\n\n // Our Merkle Trie is designed specifically for the purposes of the Ethereum\n // state trie. Empty values are not allowed in the state trie, so we can safely\n // say that if the value is empty, the key should not exist and the proof is\n // invalid.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[1]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (leaf)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (leaf)\"\n );\n\n return value;\n } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {\n // Prefix of 0 or 1 means this is an extension node. We move onto the next node\n // in the proof and increment the key index by the length of the path remainder\n // which is equal to the shared nibble length.\n currentNodeID = _getNodeID(currentNode.decoded[1]);\n currentKeyIndex += sharedNibbleLength;\n } else {\n revert(\"MerkleTrie: received a node with an unknown prefix\");\n }\n } else {\n revert(\"MerkleTrie: received an unparseable node\");\n }\n }\n\n revert(\"MerkleTrie: ran out of proof elements\");\n }\n\n /**\n * @notice Parses an array of proof elements into a new array that contains both the original\n * encoded element and the RLP-decoded element.\n *\n * @param _proof Array of proof elements to parse.\n *\n * @return Proof parsed into easily accessible structs.\n */\n function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory) {\n uint256 length = _proof.length;\n TrieNode[] memory proof = new TrieNode[](length);\n for (uint256 i = 0; i < length; ) {\n proof[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) });\n unchecked {\n ++i;\n }\n }\n return proof;\n }\n\n /**\n * @notice Picks out the ID for a node. Node ID is referred to as the \"hash\" within the\n * specification, but nodes < 32 bytes are not actually hashed.\n *\n * @param _node Node to pull an ID for.\n *\n * @return ID for the node, depending on the size of its contents.\n */\n function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes memory) {\n return _node.length < 32 ? RLPReader.readRawBytes(_node) : RLPReader.readBytes(_node);\n }\n\n /**\n * @notice Gets the path for a leaf or extension node.\n *\n * @param _node Node to get a path for.\n *\n * @return Node path, converted to an array of nibbles.\n */\n function _getNodePath(TrieNode memory _node) private pure returns (bytes memory) {\n return Bytes.toNibbles(RLPReader.readBytes(_node.decoded[0]));\n }\n\n /**\n * @notice Utility; determines the number of nibbles shared between two nibble arrays.\n *\n * @param _a First nibble array.\n * @param _b Second nibble array.\n *\n * @return Number of shared nibbles.\n */\n function _getSharedNibbleLength(bytes memory _a, bytes memory _b)\n private\n pure\n returns (uint256)\n {\n uint256 shared;\n uint256 max = (_a.length < _b.length) ? _a.length : _b.length;\n for (; shared < max && _a[shared] == _b[shared]; ) {\n unchecked {\n ++shared;\n }\n }\n return shared;\n }\n}\n" - }, - "contracts/libraries/trie/SecureMerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* Library Imports */\nimport { MerkleTrie } from \"./MerkleTrie.sol\";\n\n/**\n * @title SecureMerkleTrie\n * @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input\n * keys. Ethereum's state trie hashes input keys before storing them.\n */\nlibrary SecureMerkleTrie {\n /**\n * @notice Verifies a proof that a given key/value pair is present in the Merkle trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.get(key, _proof, _root);\n }\n\n /**\n * @notice Computes the hashed version of the input key.\n *\n * @param _key Key to hash.\n *\n * @return Hashed version of the key.\n */\n function _getSecureKey(bytes memory _key) private pure returns (bytes memory) {\n return abi.encodePacked(keccak256(_key));\n }\n}\n" - }, - "contracts/periphery/TransferOnion.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ReentrancyGuard } from \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @title TransferOnion\n * @notice TransferOnion is a hash onion for distributing tokens. The shell commits\n * to an ordered list of the token transfers and can be permissionlessly\n * unwrapped in order. The SENDER must `approve` this contract as\n * `transferFrom` is used to move the token balances.\n */\ncontract TransferOnion is ReentrancyGuard {\n using SafeERC20 for ERC20;\n\n /**\n * @notice Struct representing a layer of the onion.\n */\n struct Layer {\n address recipient;\n uint256 amount;\n bytes32 shell;\n }\n\n /**\n * @notice Address of the token to distribute.\n */\n ERC20 public immutable TOKEN;\n\n /**\n * @notice Address of the account to distribute tokens from.\n */\n address public immutable SENDER;\n\n /**\n * @notice Current shell hash.\n */\n bytes32 public shell;\n\n /**\n * @param _token Address of the token to distribute.\n * @param _sender Address of the sender to distribute from.\n * @param _shell Initial shell of the onion.\n */\n constructor(\n ERC20 _token,\n address _sender,\n bytes32 _shell\n ) {\n TOKEN = _token;\n SENDER = _sender;\n shell = _shell;\n }\n\n /**\n * @notice Peels layers from the onion and distributes tokens.\n *\n * @param _layers Array of onion layers to peel.\n */\n function peel(Layer[] memory _layers) public nonReentrant {\n bytes32 tempShell = shell;\n uint256 length = _layers.length;\n for (uint256 i = 0; i < length; ) {\n Layer memory layer = _layers[i];\n\n // Confirm that the onion layer is correct.\n require(\n keccak256(abi.encode(layer.recipient, layer.amount, layer.shell)) == tempShell,\n \"TransferOnion: what are you doing in my swamp?\"\n );\n\n // Update the onion layer.\n tempShell = layer.shell;\n\n // Transfer the tokens.\n TOKEN.safeTransferFrom(SENDER, layer.recipient, layer.amount);\n\n // Unchecked increment to save some gas.\n unchecked {\n ++i;\n }\n }\n\n shell = tempShell;\n }\n}\n" - }, - "contracts/test/AddressAliasHelper.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract AddressAliasHelper_applyAndUndo_Test is Test {\n /**\n * @notice Tests that applying and then undoing an alias results in the original address.\n */\n function testFuzz_applyAndUndo_succeeds(address _address) external {\n address aliased = AddressAliasHelper.applyL1ToL2Alias(_address);\n address unaliased = AddressAliasHelper.undoL1ToL2Alias(aliased);\n assertEq(_address, unaliased);\n }\n}\n" - }, - "contracts/test/BenchmarkTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test } from \"forge-std/Test.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport \"./CommonTest.t.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\n// Free function for setting the prevBaseFee param in the OptimismPortal.\nfunction setPrevBaseFee(\n Vm _vm,\n address _op,\n uint128 _prevBaseFee\n) {\n _vm.store(address(_op), bytes32(uint256(1)), bytes32((block.number << 192) | _prevBaseFee));\n}\n\ncontract SetPrevBaseFee_Test is Portal_Initializer {\n function test_setPrevBaseFee_succeeds() external {\n setPrevBaseFee(vm, address(op), 100 gwei);\n (uint128 prevBaseFee, , uint64 prevBlockNum) = op.params();\n assertEq(uint256(prevBaseFee), 100 gwei);\n assertEq(uint256(prevBlockNum), block.number);\n }\n}\n\n// Tests for obtaining pure gas cost estimates for commonly used functions.\n// The objective with these benchmarks is to strip down the actual test functions\n// so that they are nothing more than the call we want measure the gas cost of.\n// In order to achieve this we make no assertions, and handle everything else in the setUp()\n// function.\ncontract GasBenchMark_OptimismPortal is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n bytes32 _outputRoot;\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n\n // Get withdrawal proof data we can use for testing.\n bytes32 _storageRoot;\n bytes32 _stateRoot;\n (_stateRoot, _storageRoot, _outputRoot, , _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public virtual override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n function test_depositTransaction_benchmark() external {\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_depositTransaction_benchmark_1() external {\n setPrevBaseFee(vm, address(op), 1 gwei);\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_proveWithdrawalTransaction_benchmark() external {\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n}\n\ncontract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer {\n function test_sendMessage_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n vm.resumeGasMetering();\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n\n function test_sendMessage_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n vm.resumeGasMetering();\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), alice, 100000, true);\n vm.startPrank(alice, alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n }\n\n function test_depositETH_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n vm.resumeGasMetering();\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositETH_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n vm.resumeGasMetering();\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositERC20_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n vm.resumeGasMetering();\n L1Bridge.bridgeERC20({\n _localToken: address(L1Token),\n _remoteToken: address(L2Token),\n _amount: 100,\n _minGasLimit: 100_000,\n _extraData: hex\"\"\n });\n }\n\n function test_depositERC20_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n vm.resumeGasMetering();\n L1Bridge.bridgeERC20({\n _localToken: address(L1Token),\n _remoteToken: address(L2Token),\n _amount: 100,\n _minGasLimit: 100_000,\n _extraData: hex\"\"\n });\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Finalize is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), address(L1Bridge), 100, true);\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.startPrank(address(L1Bridge.messenger()));\n vm.deal(address(L1Bridge.messenger()), 100);\n }\n\n function test_finalizeETHWithdrawal_benchmark() external {\n // TODO: Make this more accurate. It is underestimating the cost because it pranks\n // the call coming from the messenger, which bypasses the portal\n // and oracle.\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n\ncontract GasBenchMark_L2OutputOracle is L2OutputOracle_Initializer {\n uint256 nextBlockNumber;\n\n function setUp() public override {\n super.setUp();\n nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.startPrank(proposer);\n }\n\n function test_proposeL2Output_benchmark() external {\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n}\n" - }, - "contracts/test/Bytes.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Bytes } from \"../libraries/Bytes.sol\";\n\ncontract Bytes_slice_Test is Test {\n /**\n * @notice Tests that the `slice` function works as expected when starting from index 0.\n */\n function test_slice_fromZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check if all possible slices starting from index 0 are correct.\n assertEq(Bytes.slice(input, 0, 0), hex\"\");\n assertEq(Bytes.slice(input, 0, 1), hex\"11\");\n assertEq(Bytes.slice(input, 0, 2), hex\"1122\");\n assertEq(Bytes.slice(input, 0, 3), hex\"112233\");\n assertEq(Bytes.slice(input, 0, 4), hex\"11223344\");\n assertEq(Bytes.slice(input, 0, 5), hex\"1122334455\");\n assertEq(Bytes.slice(input, 0, 6), hex\"112233445566\");\n assertEq(Bytes.slice(input, 0, 7), hex\"11223344556677\");\n assertEq(Bytes.slice(input, 0, 8), hex\"1122334455667788\");\n assertEq(Bytes.slice(input, 0, 9), hex\"112233445566778899\");\n assertEq(Bytes.slice(input, 0, 10), hex\"11223344556677889900\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when starting from indices [1, 9]\n * with lengths [1, 9], in reverse order.\n */\n function test_slice_fromNonZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check correctness of slices starting from indexes [1, 9]\n // and spanning [1, 9] bytes, in reverse order\n assertEq(Bytes.slice(input, 9, 1), hex\"00\");\n assertEq(Bytes.slice(input, 8, 2), hex\"9900\");\n assertEq(Bytes.slice(input, 7, 3), hex\"889900\");\n assertEq(Bytes.slice(input, 6, 4), hex\"77889900\");\n assertEq(Bytes.slice(input, 5, 5), hex\"6677889900\");\n assertEq(Bytes.slice(input, 4, 6), hex\"556677889900\");\n assertEq(Bytes.slice(input, 3, 7), hex\"44556677889900\");\n assertEq(Bytes.slice(input, 2, 8), hex\"3344556677889900\");\n assertEq(Bytes.slice(input, 1, 9), hex\"223344556677889900\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when slicing between multiple words\n * in memory. In this case, we test that a 2 byte slice between the 32nd byte of the\n * first word and the 1st byte of the second word is correct.\n */\n function test_slice_acrossWords_works() public {\n bytes\n memory input = hex\"00000000000000000000000000000000000000000000000000000000000000112200000000000000000000000000000000000000000000000000000000000000\";\n\n assertEq(Bytes.slice(input, 31, 2), hex\"1122\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when slicing between multiple\n * words in memory. In this case, we test that a 34 byte slice between 3 separate words\n * returns the correct result.\n */\n function test_slice_acrossMultipleWords_works() public {\n bytes\n memory input = hex\"000000000000000000000000000000000000000000000000000000000000001122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1100000000000000000000000000000000000000000000000000000000000000\";\n bytes\n memory expected = hex\"1122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11\";\n\n assertEq(Bytes.slice(input, 31, 34), expected);\n }\n\n /**\n * @notice Tests that, when given an input bytes array of length `n`, the `slice` function will\n * always revert if `_start + _length > n`.\n */\n function testFuzz_slice_outOfBounds_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // We want a valid start index and a length that will not overflow.\n vm.assume(_start < _input.length && _length < type(uint256).max - 31);\n // But, we want an invalid slice length.\n vm.assume(_start + _length > _input.length);\n\n vm.expectRevert(\"slice_outOfBounds\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that, when given a length `n` that is greater than `type(uint256).max - 31`,\n * the `slice` function reverts.\n */\n function testFuzz_slice_lengthOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that the `_length` will overflow if a number >= 31 is added to it.\n vm.assume(_length > type(uint256).max - 31);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that, when given a start index `n` that is greater than\n * `type(uint256).max - n`, the `slice` function reverts.\n */\n function testFuzz_slice_rangeOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that `_length` is a realistic length of a slice. This is to make sure\n // we revert on the correct require statement.\n vm.assume(_length < _input.length);\n // Ensure that `_start` will overflow if `_length` is added to it.\n vm.assume(_start > type(uint256).max - _length);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that the `slice` function correctly updates the free memory pointer depending\n * on the length of the slice.\n */\n function testFuzz_slice_memorySafety_succeeds(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // The start should never be more than the length of the input bytes array - 1\n vm.assume(_start < _input.length);\n // The length should never be more than the length of the input bytes array - the starting\n // slice index.\n vm.assume(_length <= _input.length - _start);\n\n // Grab the free memory pointer before the slice operation\n uint64 initPtr;\n assembly {\n initPtr := mload(0x40)\n }\n uint64 expectedPtr = uint64(initPtr + 0x20 + ((_length + 0x1f) & ~uint256(0x1f)));\n\n // Ensure that all memory outside of the expected range is safe.\n vm.expectSafeMemory(initPtr, expectedPtr);\n\n // Slice the input bytes array from `_start` to `_start + _length`\n bytes memory slice = Bytes.slice(_input, _start, _length);\n\n // Grab the free memory pointer after the slice operation\n uint64 finalPtr;\n assembly {\n finalPtr := mload(0x40)\n }\n\n // The free memory pointer should have been updated properly\n if (_length == 0) {\n // If the slice length is zero, only 32 bytes of memory should have been allocated.\n assertEq(finalPtr, initPtr + 0x20);\n } else {\n // If the slice length is greater than zero, the memory allocated should be the\n // length of the slice rounded up to the next 32 byte word + 32 bytes for the\n // length of the byte array.\n //\n // Note that we use a slightly less efficient, but equivalent method of rounding\n // up `_length` to the next multiple of 32 than is used in the `slice` function.\n // This is to diff test the method used in `slice`.\n uint64 _expectedPtr = uint64(initPtr + 0x20 + (((_length + 0x1F) >> 5) << 5));\n assertEq(finalPtr, _expectedPtr);\n\n // Sanity check for equivalence of the rounding methods.\n assertEq(_expectedPtr, expectedPtr);\n }\n\n // The slice length should be equal to `_length`\n assertEq(slice.length, _length);\n }\n}\n\ncontract Bytes_toNibbles_Test is Test {\n /**\n * @notice Diffs the test Solidity version of `toNibbles` against the Yul version.\n *\n * @param _bytes The `bytes` array to convert to nibbles.\n *\n * @return Yul version of `toNibbles` applied to `_bytes`.\n */\n function _toNibblesYul(bytes memory _bytes) internal pure returns (bytes memory) {\n // Allocate memory for the `nibbles` array.\n bytes memory nibbles = new bytes(_bytes.length << 1);\n\n assembly {\n // Load the length of the passed bytes array from memory\n let bytesLength := mload(_bytes)\n\n // Store the memory offset of the _bytes array's contents on the stack\n let bytesStart := add(_bytes, 0x20)\n\n // Store the memory offset of the nibbles array's contents on the stack\n let nibblesStart := add(nibbles, 0x20)\n\n // Loop through each byte in the input array\n for {\n let i := 0x00\n } lt(i, bytesLength) {\n i := add(i, 0x01)\n } {\n // Get the starting offset of the next 2 bytes in the nibbles array\n let offset := add(nibblesStart, shl(0x01, i))\n\n // Load the byte at the current index within the `_bytes` array\n let b := byte(0x00, mload(add(bytesStart, i)))\n\n // Pull out the first nibble and store it in the new array\n mstore8(offset, shr(0x04, b))\n // Pull out the second nibble and store it in the new array\n mstore8(add(offset, 0x01), and(b, 0x0F))\n }\n }\n\n return nibbles;\n }\n\n /**\n * @notice Tests that, given an input of 5 bytes, the `toNibbles` function returns an array of\n * 10 nibbles corresponding to the input data.\n */\n function test_toNibbles_expectedResult5Bytes_works() public {\n bytes memory input = hex\"1234567890\";\n bytes memory expected = hex\"01020304050607080900\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Tests that, given an input of 128 bytes, the `toNibbles` function returns an array\n * of 256 nibbles corresponding to the input data. This test exists to ensure that,\n * given a large input, the `toNibbles` function works as expected.\n */\n function test_toNibbles_expectedResult128Bytes_works() public {\n bytes\n memory input = hex\"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f\";\n bytes\n memory expected = hex\"0000000100020003000400050006000700080009000a000b000c000d000e000f0100010101020103010401050106010701080109010a010b010c010d010e010f0200020102020203020402050206020702080209020a020b020c020d020e020f0300030103020303030403050306030703080309030a030b030c030d030e030f0400040104020403040404050406040704080409040a040b040c040d040e040f0500050105020503050405050506050705080509050a050b050c050d050e050f0600060106020603060406050606060706080609060a060b060c060d060e060f0700070107020703070407050706070707080709070a070b070c070d070e070f\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Tests that, given an input of 0 bytes, the `toNibbles` function returns a zero\n * length array.\n */\n function test_toNibbles_zeroLengthInput_works() public {\n bytes memory input = hex\"\";\n bytes memory expected = hex\"\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length, 0);\n assertEq(expected.length, 0);\n assertEq(actual.length, 0);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Test that the `toNibbles` function in the `Bytes` library is equivalent to the Yul\n * implementation.\n */\n function testDiff_toNibbles_succeeds(bytes memory _input) public {\n assertEq(Bytes.toNibbles(_input), _toNibblesYul(_input));\n }\n}\n\ncontract Bytes_equal_Test is Test {\n /**\n * @notice Manually checks equality of two dynamic `bytes` arrays in memory.\n *\n * @param _a The first `bytes` array to compare.\n * @param _b The second `bytes` array to compare.\n *\n * @return True if the two `bytes` arrays are equal in memory.\n */\n function manualEq(bytes memory _a, bytes memory _b) internal pure returns (bool) {\n bool _eq;\n assembly {\n _eq := and(\n // Check if the contents of the two bytes arrays are equal in memory.\n eq(keccak256(add(0x20, _a), mload(_a)), keccak256(add(0x20, _b), mload(_b))),\n // Check if the length of the two bytes arrays are equal in memory.\n // This is redundant given the above check, but included for completeness.\n eq(mload(_a), mload(_b))\n )\n }\n return _eq;\n }\n\n /**\n * @notice Tests that the `equal` function in the `Bytes` library returns `false` if given two\n * non-equal byte arrays.\n */\n function testFuzz_equal_notEqual_works(bytes memory _a, bytes memory _b) public {\n vm.assume(!manualEq(_a, _b));\n assertFalse(Bytes.equal(_a, _b));\n }\n\n /**\n * @notice Test whether or not the `equal` function in the `Bytes` library is equivalent to\n * manually checking equality of the two dynamic `bytes` arrays in memory.\n */\n function testDiff_equal_works(bytes memory _a, bytes memory _b) public {\n assertEq(Bytes.equal(_a, _b), manualEq(_a, _b));\n }\n}\n" - }, - "contracts/test/CommonTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test, StdUtils } from \"forge-std/Test.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { IL1ChugSplashDeployer } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { LegacyMintableERC20 } from \"../legacy/LegacyMintableERC20.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract CommonTest is Test {\n address alice = address(128);\n address bob = address(256);\n address multisig = address(512);\n\n address immutable ZERO_ADDRESS = address(0);\n address immutable NON_ZERO_ADDRESS = address(1);\n uint256 immutable NON_ZERO_VALUE = 100;\n uint256 immutable ZERO_VALUE = 0;\n uint64 immutable NON_ZERO_GASLIMIT = 50000;\n bytes32 nonZeroHash = keccak256(abi.encode(\"NON_ZERO\"));\n bytes NON_ZERO_DATA = hex\"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000\";\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n FFIInterface ffi;\n\n function setUp() public virtual {\n // Give alice and bob some ETH\n vm.deal(alice, 1 << 16);\n vm.deal(bob, 1 << 16);\n vm.deal(multisig, 1 << 16);\n\n vm.label(alice, \"alice\");\n vm.label(bob, \"bob\");\n vm.label(multisig, \"multisig\");\n\n // Make sure we have a non-zero base fee\n vm.fee(1000000000);\n\n ffi = new FFIInterface();\n }\n\n function emitTransactionDeposited(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) internal {\n emit TransactionDeposited(\n _from,\n _to,\n 0,\n abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data)\n );\n }\n}\n\ncontract L2OutputOracle_Initializer is CommonTest {\n // Test target\n L2OutputOracle oracle;\n L2OutputOracle oracleImpl;\n\n L2ToL1MessagePasser messagePasser =\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER));\n\n // Constructor arguments\n address internal proposer = 0x000000000000000000000000000000000000AbBa;\n address internal owner = 0x000000000000000000000000000000000000ACDC;\n uint256 internal submissionInterval = 1800;\n uint256 internal l2BlockTime = 2;\n uint256 internal startingBlockNumber = 200;\n uint256 internal startingTimestamp = 1000;\n address guardian;\n\n // Test data\n uint256 initL1Time;\n\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n // Advance the evm's time to meet the L2OutputOracle's requirements for proposeL2Output\n function warpToProposeTime(uint256 _nextBlockNumber) public {\n vm.warp(oracle.computeL2Timestamp(_nextBlockNumber) + 1);\n }\n\n function setUp() public virtual override {\n super.setUp();\n guardian = makeAddr(\"guardian\");\n\n // By default the first block has timestamp and number zero, which will cause underflows in the\n // tests, so we'll move forward to these block values.\n initL1Time = startingTimestamp + 1;\n vm.warp(initL1Time);\n vm.roll(startingBlockNumber);\n // Deploy the L2OutputOracle and transfer owernship to the proposer\n oracleImpl = new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: startingTimestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(oracleImpl),\n abi.encodeCall(L2OutputOracle.initialize, (startingBlockNumber, startingTimestamp))\n );\n oracle = L2OutputOracle(address(proxy));\n vm.label(address(oracle), \"L2OutputOracle\");\n\n // Set the L2ToL1MessagePasser at the correct address\n vm.etch(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(new L2ToL1MessagePasser()).code);\n\n vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, \"L2ToL1MessagePasser\");\n }\n}\n\ncontract Portal_Initializer is L2OutputOracle_Initializer {\n // Test target\n OptimismPortal internal opImpl;\n OptimismPortal internal op;\n SystemConfig systemConfig;\n\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n function setUp() public virtual override {\n super.setUp();\n\n ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();\n\n systemConfig = new SystemConfig({\n _owner: address(1),\n _overhead: 0,\n _scalar: 10000,\n _batcherHash: bytes32(0),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(0),\n _config: config\n });\n\n opImpl = new OptimismPortal({\n _l2Oracle: oracle,\n _guardian: guardian,\n _paused: true,\n _config: systemConfig\n });\n\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(opImpl),\n abi.encodeWithSelector(OptimismPortal.initialize.selector, false)\n );\n op = OptimismPortal(payable(address(proxy)));\n vm.label(address(op), \"OptimismPortal\");\n }\n}\n\ncontract Messenger_Initializer is Portal_Initializer {\n AddressManager internal addressManager;\n L1CrossDomainMessenger internal L1Messenger;\n L2CrossDomainMessenger internal L2Messenger =\n L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER);\n\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n\n event SentMessageExtension1(address indexed sender, uint256 value);\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event RelayedMessage(bytes32 indexed msgHash);\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 mint,\n uint256 value,\n uint64 gasLimit,\n bool isCreation,\n bytes data\n );\n\n event WhatHappened(bool success, bytes returndata);\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the address manager\n vm.prank(multisig);\n addressManager = new AddressManager();\n\n // Setup implementation\n L1CrossDomainMessenger L1MessengerImpl = new L1CrossDomainMessenger(op);\n\n // Setup the address manager and proxy\n vm.prank(multisig);\n addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(L1MessengerImpl));\n ResolvedDelegateProxy proxy = new ResolvedDelegateProxy(\n addressManager,\n \"OVM_L1CrossDomainMessenger\"\n );\n L1Messenger = L1CrossDomainMessenger(address(proxy));\n L1Messenger.initialize();\n\n vm.etch(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n address(new L2CrossDomainMessenger(address(L1Messenger))).code\n );\n\n L2Messenger.initialize();\n\n // Label addresses\n vm.label(address(addressManager), \"AddressManager\");\n vm.label(address(L1MessengerImpl), \"L1CrossDomainMessenger_Impl\");\n vm.label(address(L1Messenger), \"L1CrossDomainMessenger_Proxy\");\n vm.label(Predeploys.LEGACY_ERC20_ETH, \"LegacyERC20ETH\");\n vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, \"L2CrossDomainMessenger\");\n\n vm.label(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n \"L1CrossDomainMessenger_aliased\"\n );\n }\n}\n\ncontract Bridge_Initializer is Messenger_Initializer {\n L1StandardBridge L1Bridge;\n L2StandardBridge L2Bridge;\n OptimismMintableERC20Factory L2TokenFactory;\n OptimismMintableERC20Factory L1TokenFactory;\n ERC20 L1Token;\n ERC20 BadL1Token;\n OptimismMintableERC20 L2Token;\n LegacyMintableERC20 LegacyL2Token;\n ERC20 NativeL2Token;\n ERC20 BadL2Token;\n OptimismMintableERC20 RemoteL1Token;\n\n event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes data\n );\n\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFailed(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ETHBridgeInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n function setUp() public virtual override {\n super.setUp();\n\n vm.label(Predeploys.L2_STANDARD_BRIDGE, \"L2StandardBridge\");\n vm.label(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, \"OptimismMintableERC20Factory\");\n\n // Deploy the L1 bridge and initialize it with the address of the\n // L1CrossDomainMessenger\n L1ChugSplashProxy proxy = new L1ChugSplashProxy(multisig);\n vm.mockCall(\n multisig,\n abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector),\n abi.encode(true)\n );\n vm.startPrank(multisig);\n proxy.setCode(address(new L1StandardBridge(payable(address(L1Messenger)))).code);\n vm.clearMockedCalls();\n address L1Bridge_Impl = proxy.getImplementation();\n vm.stopPrank();\n\n L1Bridge = L1StandardBridge(payable(address(proxy)));\n\n vm.label(address(proxy), \"L1StandardBridge_Proxy\");\n vm.label(address(L1Bridge_Impl), \"L1StandardBridge_Impl\");\n\n // Deploy the L2StandardBridge, move it to the correct predeploy\n // address and then initialize it\n L2StandardBridge l2B = new L2StandardBridge(payable(proxy));\n vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(l2B).code);\n L2Bridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE));\n\n // Set up the L2 mintable token factory\n OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory(\n Predeploys.L2_STANDARD_BRIDGE\n );\n vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(factory).code);\n L2TokenFactory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY);\n\n vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code);\n\n L1Token = new ERC20(\"Native L1 Token\", \"L1T\");\n\n LegacyL2Token = new LegacyMintableERC20({\n _l2Bridge: address(L2Bridge),\n _l1Token: address(L1Token),\n _name: string.concat(\"LegacyL2-\", L1Token.name()),\n _symbol: string.concat(\"LegacyL2-\", L1Token.symbol())\n });\n vm.label(address(LegacyL2Token), \"LegacyMintableERC20\");\n\n // Deploy the L2 ERC20 now\n L2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(L1Token),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n BadL2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n NativeL2Token = new ERC20(\"Native L2 Token\", \"L2T\");\n L1TokenFactory = new OptimismMintableERC20Factory(address(L1Bridge));\n\n RemoteL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(NativeL2Token),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n\n BadL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n }\n}\n\ncontract ERC721Bridge_Initializer is Messenger_Initializer {\n L1ERC721Bridge L1Bridge;\n L2ERC721Bridge L2Bridge;\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the L1ERC721Bridge.\n L1Bridge = new L1ERC721Bridge(address(L1Messenger), Predeploys.L2_ERC721_BRIDGE);\n\n // Deploy the implementation for the L2ERC721Bridge and etch it into the predeploy address.\n vm.etch(\n Predeploys.L2_ERC721_BRIDGE,\n address(new L2ERC721Bridge(Predeploys.L2_CROSS_DOMAIN_MESSENGER, address(L1Bridge)))\n .code\n );\n\n // Set up a reference to the L2ERC721Bridge.\n L2Bridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE);\n\n // Label the L1 and L2 bridges.\n vm.label(address(L1Bridge), \"L1ERC721Bridge\");\n vm.label(address(L2Bridge), \"L2ERC721Bridge\");\n }\n}\n\ncontract FFIInterface is Test {\n function getProveWithdrawalTransactionInputs(Types.WithdrawalTransaction memory _tx)\n external\n returns (\n bytes32,\n bytes32,\n bytes32,\n bytes32,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"getProveWithdrawalTransactionInputs\";\n cmds[2] = vm.toString(_tx.nonce);\n cmds[3] = vm.toString(_tx.sender);\n cmds[4] = vm.toString(_tx.target);\n cmds[5] = vm.toString(_tx.value);\n cmds[6] = vm.toString(_tx.gasLimit);\n cmds[7] = vm.toString(_tx.data);\n\n bytes memory result = vm.ffi(cmds);\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = abi.decode(result, (bytes32, bytes32, bytes32, bytes32, bytes[]));\n\n return (stateRoot, storageRoot, outputRoot, withdrawalHash, withdrawalProof);\n }\n\n function hashCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashCrossDomainMessage\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashWithdrawal(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashWithdrawal\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashOutputRootProof(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external returns (bytes32) {\n string[] memory cmds = new string[](6);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashOutputRootProof\";\n cmds[2] = Strings.toHexString(uint256(_version));\n cmds[3] = Strings.toHexString(uint256(_stateRoot));\n cmds[4] = Strings.toHexString(uint256(_messagePasserStorageRoot));\n cmds[5] = Strings.toHexString(uint256(_latestBlockhash));\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashDepositTransaction(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint64 _logIndex\n ) external returns (bytes32) {\n string[] memory cmds = new string[](10);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashDepositTransaction\";\n cmds[2] = \"0x0000000000000000000000000000000000000000000000000000000000000000\";\n cmds[3] = vm.toString(_logIndex);\n cmds[4] = vm.toString(_from);\n cmds[5] = vm.toString(_to);\n cmds[6] = vm.toString(_mint);\n cmds[7] = vm.toString(_value);\n cmds[8] = vm.toString(_gas);\n cmds[9] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function encodeDepositTransaction(Types.UserDepositTransaction calldata txn)\n external\n returns (bytes memory)\n {\n string[] memory cmds = new string[](11);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"encodeDepositTransaction\";\n cmds[2] = vm.toString(txn.from);\n cmds[3] = vm.toString(txn.to);\n cmds[4] = vm.toString(txn.value);\n cmds[5] = vm.toString(txn.mint);\n cmds[6] = vm.toString(txn.gasLimit);\n cmds[7] = vm.toString(txn.isCreation);\n cmds[8] = vm.toString(txn.data);\n cmds[9] = vm.toString(txn.l1BlockHash);\n cmds[10] = vm.toString(txn.logIndex);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function encodeCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes memory) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"encodeCrossDomainMessage\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function decodeVersionedNonce(uint256 nonce) external returns (uint256, uint256) {\n string[] memory cmds = new string[](3);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"decodeVersionedNonce\";\n cmds[2] = vm.toString(nonce);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (uint256, uint256));\n }\n\n function getMerkleTrieFuzzCase(string memory variant)\n external\n returns (\n bytes32,\n bytes memory,\n bytes memory,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](5);\n cmds[0] = \"./test-case-generator/fuzz\";\n cmds[1] = \"-m\";\n cmds[2] = \"trie\";\n cmds[3] = \"-v\";\n cmds[4] = variant;\n\n return abi.decode(vm.ffi(cmds), (bytes32, bytes, bytes, bytes[]));\n }\n}\n\n// Used for testing a future upgrade beyond the current implementations.\n// We include some variables so that we can sanity check accessing storage values after an upgrade.\ncontract NextImpl is Initializable {\n // Initializable occupies the zero-th slot.\n bytes32 slot1;\n bytes32[19] __gap;\n bytes32 slot21;\n bytes32 public constant slot21Init = bytes32(hex\"1337\");\n\n function initialize() public reinitializer(2) {\n // Slot21 is unused by an of our upgradeable contracts.\n // This is used to verify that we can access this value after an upgrade.\n slot21 = slot21Init;\n }\n}\n\ncontract Reverter {\n fallback() external {\n revert();\n }\n}\n\n// Useful for testing reentrancy guards\ncontract CallerCaller {\n event WhatHappened(bool success, bytes returndata);\n\n fallback() external {\n (bool success, bytes memory returndata) = msg.sender.call(msg.data);\n emit WhatHappened(success, returndata);\n assembly {\n switch success\n case 0 {\n revert(add(returndata, 0x20), mload(returndata))\n }\n default {\n return(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n\n// Used for testing the `CrossDomainMessenger`'s per-message reentrancy guard.\ncontract ConfigurableCaller {\n bool doRevert = true;\n address target;\n bytes payload;\n\n event WhatHappened(bool success, bytes returndata);\n\n /**\n * @notice Call the configured target with the configured payload OR revert.\n */\n function call() external {\n if (doRevert) {\n revert(\"ConfigurableCaller: revert\");\n } else {\n (bool success, bytes memory returndata) = address(target).call(payload);\n emit WhatHappened(success, returndata);\n assembly {\n switch success\n case 0 {\n revert(add(returndata, 0x20), mload(returndata))\n }\n default {\n return(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n }\n\n /**\n * @notice Set whether or not to have `call` revert.\n */\n function setDoRevert(bool _doRevert) external {\n doRevert = _doRevert;\n }\n\n /**\n * @notice Set the target for the call made in `call`.\n */\n function setTarget(address _target) external {\n target = _target;\n }\n\n /**\n * @notice Set the payload for the call made in `call`.\n */\n function setPayload(bytes calldata _payload) external {\n payload = _payload;\n }\n\n /**\n * @notice Fallback function that reverts if `doRevert` is true.\n * Otherwise, it does nothing.\n */\n fallback() external {\n if (doRevert) {\n revert(\"ConfigurableCaller: revert\");\n }\n }\n}\n" - }, - "contracts/test/CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, CallerCaller } from \"./CommonTest.t.sol\";\n\n// CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2\n// CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract.\ncontract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {\n // Ensure that baseGas passes for the max value of _minGasLimit,\n // this is about 4 Billion.\n function test_baseGas_succeeds() external view {\n L1Messenger.baseGas(hex\"ff\", type(uint32).max);\n }\n\n // Fuzz for other values which might cause a revert in baseGas.\n function testFuzz_baseGas_succeeds(uint32 _minGasLimit) external view {\n L1Messenger.baseGas(hex\"ff\", _minGasLimit);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest, Portal_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable } from \"../L2/CrossDomainOwnable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Vm, VmSafe } from \"forge-std/Vm.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract XDomainSetter is CrossDomainOwnable {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable_Test is CommonTest {\n XDomainSetter setter;\n\n function setUp() public override {\n super.setUp();\n setter = new XDomainSetter();\n }\n\n // Check that the revert message is correct\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable: caller is not the owner\");\n setter.set(1);\n }\n\n // Check that making a call can set the value properly\n function test_onlyOwner_succeeds() external {\n assertEq(setter.value(), 0);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(setter.owner()));\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n\ncontract CrossDomainOwnableThroughPortal_Test is Portal_Initializer {\n XDomainSetter setter;\n\n function setUp() public override {\n super.setUp();\n\n vm.prank(alice);\n setter = new XDomainSetter();\n }\n\n function test_depositTransaction_crossDomainOwner_succeeds() external {\n vm.recordLogs();\n\n vm.prank(alice);\n op.depositTransaction({\n _to: address(setter),\n _value: 0,\n _gasLimit: 21_000,\n _isCreation: false,\n _data: abi.encodeWithSelector(XDomainSetter.set.selector, 1)\n });\n\n // Simulate the operation of the `op-node` by parsing data\n // from logs\n VmSafe.Log[] memory logs = vm.getRecordedLogs();\n // Only 1 log emitted\n assertEq(logs.length, 1);\n\n VmSafe.Log memory log = logs[0];\n\n // It is the expected topic\n bytes32 topic = log.topics[0];\n assertEq(topic, keccak256(\"TransactionDeposited(address,address,uint256,bytes)\"));\n\n // from is indexed and the first argument to the event.\n bytes32 _from = log.topics[1];\n address from = Bytes32AddressLib.fromLast20Bytes(_from);\n\n assertEq(AddressAliasHelper.undoL1ToL2Alias(from), alice);\n\n // Make a call from the \"from\" value received from the log.\n // In theory the opaque data could be parsed from the log\n // and passed to a low level call to \"to\", but calling set\n // directly on the setter is good enough.\n vm.prank(from);\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable2.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\nimport { CommonTest, Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable2 } from \"../L2/CrossDomainOwnable2.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract XDomainSetter2 is CrossDomainOwnable2 {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable2_Test is Messenger_Initializer {\n XDomainSetter2 setter;\n\n function setUp() public override {\n super.setUp();\n vm.prank(alice);\n setter = new XDomainSetter2();\n }\n\n function test_onlyOwner_notMessenger_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the messenger\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n // set the xDomainMsgSender storage slot\n bytes32 key = bytes32(uint256(204));\n bytes32 value = Bytes32AddressLib.fillLast12Bytes(address(alice));\n vm.store(address(L2Messenger), key, value);\n\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the owner\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner2_reverts() external {\n uint240 nonce = 0;\n address sender = bob;\n address target = address(setter);\n uint256 value = 0;\n uint256 minGasLimit = 0;\n bytes memory message = abi.encodeWithSelector(XDomainSetter2.set.selector, 1);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n // It should be a failed message. The revert is caught,\n // so we cannot expectRevert here.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n assertEq(setter.value(), 0);\n }\n\n function test_onlyOwner_succeeds() external {\n address owner = setter.owner();\n\n // Simulate the L2 execution where the call is coming from\n // the L1CrossDomainMessenger\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(1, 1),\n owner,\n address(setter),\n 0,\n 0,\n abi.encodeWithSelector(XDomainSetter2.set.selector, 2)\n );\n\n assertEq(setter.value(), 2);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable3.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\nimport { CommonTest, Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable3 } from \"../L2/CrossDomainOwnable3.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract XDomainSetter3 is CrossDomainOwnable3 {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable3_Test is Messenger_Initializer {\n XDomainSetter3 setter;\n\n /**\n * @notice OpenZeppelin Ownable.sol transferOwnership event\n */\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @notice CrossDomainOwnable3.sol transferOwnership event\n */\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner,\n bool isLocal\n );\n\n function setUp() public override {\n super.setUp();\n vm.prank(alice);\n setter = new XDomainSetter3();\n }\n\n function test_constructor_succeeds() public {\n assertEq(setter.owner(), alice);\n assertEq(setter.isLocal(), true);\n }\n\n function test_localOnlyOwner_notOwner_reverts() public {\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.set(1);\n }\n\n function test_transferOwnership_notOwner_reverts() public {\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.transferOwnership({ _owner: bob, _isLocal: true });\n }\n\n function test_crossDomainOnlyOwner_notOwner_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n // set the xDomainMsgSender storage slot\n bytes32 key = bytes32(uint256(204));\n bytes32 value = Bytes32AddressLib.fillLast12Bytes(bob);\n vm.store(address(L2Messenger), key, value);\n\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.set(1);\n }\n\n function test_crossDomainOnlyOwner_notOwner2_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n assertEq(setter.isLocal(), false);\n\n uint240 nonce = 0;\n address sender = bob;\n address target = address(setter);\n uint256 value = 0;\n uint256 minGasLimit = 0;\n bytes memory message = abi.encodeWithSelector(XDomainSetter3.set.selector, 1);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n // It should be a failed message. The revert is caught,\n // so we cannot expectRevert here.\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit FailedRelayedMessage(hash);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n assertEq(setter.value(), 0);\n }\n\n function test_crossDomainOnlyOwner_notMessenger_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the messenger\");\n setter.set(1);\n }\n\n function test_transferOwnership_zeroAddress_reverts() public {\n vm.prank(setter.owner());\n vm.expectRevert(\"CrossDomainOwnable3: new owner is the zero address\");\n setter.transferOwnership({ _owner: address(0), _isLocal: true });\n }\n\n function test_transferOwnership_noLocalZeroAddress_reverts() public {\n vm.prank(setter.owner());\n vm.expectRevert(\"Ownable: new owner is the zero address\");\n setter.transferOwnership(address(0));\n }\n\n function test_localOnlyOwner_succeeds() public {\n assertEq(setter.isLocal(), true);\n vm.prank(setter.owner());\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n\n function test_localTransferOwnership_succeeds() public {\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n emit OwnershipTransferred(alice, bob, true);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: bob, _isLocal: true });\n\n assertEq(setter.isLocal(), true);\n\n vm.prank(bob);\n setter.set(2);\n assertEq(setter.value(), 2);\n }\n\n /**\n * @notice The existing transferOwnership(address) method\n * still exists on the contract\n */\n function test_transferOwnershipNoLocal_succeeds() public {\n bool isLocal = setter.isLocal();\n\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n\n vm.prank(setter.owner());\n setter.transferOwnership(bob);\n\n // isLocal has not changed\n assertEq(setter.isLocal(), isLocal);\n\n vm.prank(bob);\n setter.set(2);\n assertEq(setter.value(), 2);\n }\n\n function test_crossDomainTransferOwnership_succeeds() public {\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n emit OwnershipTransferred(alice, bob, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: bob, _isLocal: false });\n\n assertEq(setter.isLocal(), false);\n\n // Simulate the L2 execution where the call is coming from\n // the L1CrossDomainMessenger\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(1, 1),\n bob,\n address(setter),\n 0,\n 0,\n abi.encodeWithSelector(XDomainSetter3.set.selector, 2)\n );\n\n assertEq(setter.value(), 2);\n }\n}\n" - }, - "contracts/test/DeployerWhitelist.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { DeployerWhitelist } from \"../legacy/DeployerWhitelist.sol\";\n\ncontract DeployerWhitelist_Test is CommonTest {\n DeployerWhitelist list;\n\n function setUp() public virtual override {\n list = new DeployerWhitelist();\n }\n\n // The owner should be address(0)\n function test_owner_succeeds() external {\n assertEq(list.owner(), address(0));\n }\n\n // The storage slot for the owner must be the same\n function test_storageSlots_succeeds() external {\n vm.prank(list.owner());\n list.setOwner(address(1));\n\n assertEq(bytes32(uint256(1)), vm.load(address(list), bytes32(uint256(0))));\n }\n}\n" - }, - "contracts/test/Encoding.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { LegacyCrossDomainUtils } from \"../libraries/LegacyCrossDomainUtils.sol\";\n\ncontract Encoding_Test is CommonTest {\n function testFuzz_nonceVersioning_succeeds(uint240 _nonce, uint16 _version) external {\n (uint240 nonce, uint16 version) = Encoding.decodeVersionedNonce(\n Encoding.encodeVersionedNonce(_nonce, _version)\n );\n assertEq(version, _version);\n assertEq(nonce, _nonce);\n }\n\n function testDiff_decodeVersionedNonce_succeeds(uint240 _nonce, uint16 _version) external {\n uint256 nonce = uint256(Encoding.encodeVersionedNonce(_nonce, _version));\n (uint256 decodedNonce, uint256 decodedVersion) = ffi.decodeVersionedNonce(nonce);\n\n assertEq(_version, uint16(decodedVersion));\n\n assertEq(_nonce, uint240(decodedNonce));\n }\n\n function testDiff_encodeCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint8 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint8 version = _version % 2;\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes memory encoding = Encoding.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n bytes memory _encoding = ffi.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n assertEq(encoding, _encoding);\n }\n\n function testFuzz_encodeCrossDomainMessageV0_matchesLegacy_succeeds(\n uint240 _nonce,\n address _sender,\n address _target,\n bytes memory _data\n ) external {\n uint8 version = 0;\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes memory legacyEncoding = LegacyCrossDomainUtils.encodeXDomainCalldata(\n _target,\n _sender,\n _data,\n nonce\n );\n\n bytes memory bedrockEncoding = Encoding.encodeCrossDomainMessageV0(\n _target,\n _sender,\n _data,\n nonce\n );\n\n assertEq(legacyEncoding, bedrockEncoding);\n }\n\n function testDiff_encodeDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bool isCreate,\n bytes memory _data,\n uint64 _logIndex\n ) external {\n Types.UserDepositTransaction memory t = Types.UserDepositTransaction(\n _from,\n _to,\n isCreate,\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n );\n\n bytes memory txn = Encoding.encodeDepositTransaction(t);\n bytes memory _txn = ffi.encodeDepositTransaction(t);\n\n assertEq(txn, _txn);\n }\n}\n" - }, - "contracts/test/FeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { L1FeeVault } from \"../L2/L1FeeVault.sol\";\nimport { BaseFeeVault } from \"../L2/BaseFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n// Test the implementations of the FeeVault\ncontract FeeVault_Test is Bridge_Initializer {\n BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT));\n L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT));\n\n address constant recipient = address(0x10000);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.BASE_FEE_VAULT, address(new BaseFeeVault(recipient)).code);\n vm.etch(Predeploys.L1_FEE_VAULT, address(new L1FeeVault(recipient)).code);\n\n vm.label(Predeploys.BASE_FEE_VAULT, \"BaseFeeVault\");\n vm.label(Predeploys.L1_FEE_VAULT, \"L1FeeVault\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(baseFeeVault.RECIPIENT(), recipient);\n assertEq(l1FeeVault.RECIPIENT(), recipient);\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n}\n" - }, - "contracts/test/GasPriceOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GasPriceOracle } from \"../L2/GasPriceOracle.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract GasPriceOracle_Test is CommonTest {\n event OverheadUpdated(uint256);\n event ScalarUpdated(uint256);\n event DecimalsUpdated(uint256);\n\n GasPriceOracle gasOracle;\n L1Block l1Block;\n address depositor;\n\n // set the initial L1 context values\n uint64 constant number = 10;\n uint64 constant timestamp = 11;\n uint256 constant basefee = 100;\n bytes32 constant hash = bytes32(uint256(64));\n uint64 constant sequenceNumber = 0;\n bytes32 constant batcherHash = bytes32(uint256(777));\n uint256 constant l1FeeOverhead = 310;\n uint256 constant l1FeeScalar = 10;\n\n function setUp() public virtual override {\n super.setUp();\n // place the L1Block contract at the predeploy address\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n\n l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n depositor = l1Block.DEPOSITOR_ACCOUNT();\n\n // We are not setting the gas oracle at its predeploy\n // address for simplicity purposes. Nothing in this test\n // requires it to be at a particular address\n gasOracle = new GasPriceOracle();\n\n vm.prank(depositor);\n l1Block.setL1BlockValues({\n _number: number,\n _timestamp: timestamp,\n _basefee: basefee,\n _hash: hash,\n _sequenceNumber: sequenceNumber,\n _batcherHash: batcherHash,\n _l1FeeOverhead: l1FeeOverhead,\n _l1FeeScalar: l1FeeScalar\n });\n }\n\n function test_l1BaseFee_succeeds() external {\n assertEq(gasOracle.l1BaseFee(), basefee);\n }\n\n function test_gasPrice_succeeds() external {\n vm.fee(100);\n uint256 gasPrice = gasOracle.gasPrice();\n assertEq(gasPrice, 100);\n }\n\n function test_baseFee_succeeds() external {\n vm.fee(64);\n uint256 gasPrice = gasOracle.baseFee();\n assertEq(gasPrice, 64);\n }\n\n function test_scalar_succeeds() external {\n assertEq(gasOracle.scalar(), l1FeeScalar);\n }\n\n function test_overhead_succeeds() external {\n assertEq(gasOracle.overhead(), l1FeeOverhead);\n }\n\n function test_decimals_succeeds() external {\n assertEq(gasOracle.decimals(), 6);\n assertEq(gasOracle.DECIMALS(), 6);\n }\n\n // Removed in bedrock\n function test_setGasPrice_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setGasPrice(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n\n // Removed in bedrock\n function test_setL1BaseFee_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setL1BaseFee(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n}\n" - }, - "contracts/test/GovernanceToken.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract GovernanceToken_Test is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n\n function setUp() public virtual override {\n super.setUp();\n vm.prank(owner);\n gov = new GovernanceToken();\n }\n\n function test_constructor_succeeds() external {\n assertEq(gov.owner(), owner);\n assertEq(gov.name(), \"Optimism\");\n assertEq(gov.symbol(), \"OP\");\n assertEq(gov.decimals(), 18);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_mint_fromOwner_succeeds() external {\n // Mint 100 tokens.\n vm.prank(owner);\n gov.mint(owner, 100);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 100);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_mint_fromNotOwner_reverts() external {\n // Mint 100 tokens as rando.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n gov.mint(owner, 100);\n\n // Balance does not update.\n assertEq(gov.balanceOf(owner), 0);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_burn_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando burns their tokens.\n vm.prank(rando);\n gov.burn(50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_burnFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to burn 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner burns 50 tokens from rando.\n vm.prank(owner);\n gov.burnFrom(rando, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_transfer_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando transfers 50 tokens to owner.\n vm.prank(rando);\n gov.transfer(owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_approve_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n\n function test_transferFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner transfers 50 tokens from rando to owner.\n vm.prank(owner);\n gov.transferFrom(rando, owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_increaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Rando increases allowance by 50 tokens.\n vm.prank(rando);\n gov.increaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 100);\n }\n\n function test_decreaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 100 tokens.\n vm.prank(rando);\n gov.approve(owner, 100);\n\n // Rando decreases allowance by 50 tokens.\n vm.prank(rando);\n gov.decreaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n}\n" - }, - "contracts/test/Hashing.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { LegacyCrossDomainUtils } from \"../libraries/LegacyCrossDomainUtils.sol\";\n\ncontract Hashing_hashDepositSource_Test is CommonTest {\n /**\n * @notice Tests that hashDepositSource returns the correct hash in a simple case.\n */\n function test_hashDepositSource_succeeds() external {\n assertEq(\n Hashing.hashDepositSource(\n 0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959,\n 0x1\n ),\n 0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc\n );\n }\n}\n\ncontract Hashing_hashCrossDomainMessage_Test is CommonTest {\n /**\n * @notice Tests that hashCrossDomainMessage returns the correct hash in a simple case.\n */\n function testDiff_hashCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint16 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n // Ensure the version is valid.\n uint16 version = uint16(bound(uint256(_version), 0, 1));\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n assertEq(\n Hashing.hashCrossDomainMessage(nonce, _sender, _target, _value, _gasLimit, _data),\n ffi.hashCrossDomainMessage(nonce, _sender, _target, _value, _gasLimit, _data)\n );\n }\n\n /**\n * @notice Tests that hashCrossDomainMessageV0 matches the hash of the legacy encoding.\n */\n function testFuzz_hashCrossDomainMessageV0_matchesLegacy_succeeds(\n address _target,\n address _sender,\n bytes memory _message,\n uint256 _messageNonce\n ) external {\n assertEq(\n keccak256(\n LegacyCrossDomainUtils.encodeXDomainCalldata(\n _target,\n _sender,\n _message,\n _messageNonce\n )\n ),\n Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _messageNonce)\n );\n }\n}\n\ncontract Hashing_hashWithdrawal_Test is CommonTest {\n /**\n * @notice Tests that hashWithdrawal returns the correct hash in a simple case.\n */\n function testDiff_hashWithdrawal_succeeds(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n assertEq(\n Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(_nonce, _sender, _target, _value, _gasLimit, _data)\n ),\n ffi.hashWithdrawal(_nonce, _sender, _target, _value, _gasLimit, _data)\n );\n }\n}\n\ncontract Hashing_hashOutputRootProof_Test is CommonTest {\n /**\n * @notice Tests that hashOutputRootProof returns the correct hash in a simple case.\n */\n function testDiff_hashOutputRootProof_succeeds(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external {\n assertEq(\n Hashing.hashOutputRootProof(\n Types.OutputRootProof({\n version: _version,\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _messagePasserStorageRoot,\n latestBlockhash: _latestBlockhash\n })\n ),\n ffi.hashOutputRootProof(\n _version,\n _stateRoot,\n _messagePasserStorageRoot,\n _latestBlockhash\n )\n );\n }\n}\n\ncontract Hashing_hashDepositTransaction_Test is CommonTest {\n /**\n * @notice Tests that hashDepositTransaction returns the correct hash in a simple case.\n */\n function testDiff_hashDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint64 _logIndex\n ) external {\n assertEq(\n Hashing.hashDepositTransaction(\n Types.UserDepositTransaction(\n _from,\n _to,\n false, // isCreate\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n )\n ),\n ffi.hashDepositTransaction(_from, _to, _mint, _value, _gas, _data, _logIndex)\n );\n }\n}\n" - }, - "contracts/test/L1Block.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\ncontract L1BlockTest is CommonTest {\n L1Block lb;\n address depositor;\n bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1));\n\n function setUp() public virtual override {\n super.setUp();\n lb = new L1Block();\n depositor = lb.DEPOSITOR_ACCOUNT();\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: uint64(1),\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: NON_ZERO_HASH,\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(0),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function testFuzz_updatesValues_succeeds(\n uint64 n,\n uint64 t,\n uint256 b,\n bytes32 h,\n uint64 s,\n bytes32 bt,\n uint256 fo,\n uint256 fs\n ) external {\n vm.prank(depositor);\n lb.setL1BlockValues(n, t, b, h, s, bt, fo, fs);\n assertEq(lb.number(), n);\n assertEq(lb.timestamp(), t);\n assertEq(lb.basefee(), b);\n assertEq(lb.hash(), h);\n assertEq(lb.sequenceNumber(), s);\n assertEq(lb.batcherHash(), bt);\n assertEq(lb.l1FeeOverhead(), fo);\n assertEq(lb.l1FeeScalar(), fs);\n }\n\n function test_number_succeeds() external {\n assertEq(lb.number(), uint64(1));\n }\n\n function test_timestamp_succeeds() external {\n assertEq(lb.timestamp(), uint64(2));\n }\n\n function test_basefee_succeeds() external {\n assertEq(lb.basefee(), 3);\n }\n\n function test_hash_succeeds() external {\n assertEq(lb.hash(), NON_ZERO_HASH);\n }\n\n function test_sequenceNumber_succeeds() external {\n assertEq(lb.sequenceNumber(), uint64(4));\n }\n\n function test_updateValues_succeeds() external {\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: type(uint64).max,\n _timestamp: type(uint64).max,\n _basefee: type(uint256).max,\n _hash: keccak256(abi.encode(1)),\n _sequenceNumber: type(uint64).max,\n _batcherHash: bytes32(type(uint256).max),\n _l1FeeOverhead: type(uint256).max,\n _l1FeeScalar: type(uint256).max\n });\n }\n}\n" - }, - "contracts/test/L1BlockNumber.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { L1BlockNumber } from \"../legacy/L1BlockNumber.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract L1BlockNumberTest is Test {\n L1Block lb;\n L1BlockNumber bn;\n\n uint64 constant number = 99;\n\n function setUp() external {\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n lb = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n bn = new L1BlockNumber();\n vm.prank(lb.DEPOSITOR_ACCOUNT());\n\n lb.setL1BlockValues({\n _number: number,\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: bytes32(uint256(10)),\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(uint256(0)),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function test_getL1BlockNumber_succeeds() external {\n assertEq(bn.getL1BlockNumber(), number);\n }\n\n function test_fallback_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n\n function test_receive_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call{ value: 1 }(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n}\n" - }, - "contracts/test/L1CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Messenger_Initializer, Reverter, ConfigurableCaller } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle_Initializer } from \"./L2OutputOracle.t.sol\";\n\n/* Libraries */\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n/* Target contract dependencies */\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/* Target contract */\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\n\ncontract L1CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n // the version is encoded in the nonce\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L1Messenger.messageNonce());\n assertEq(version, L1Messenger.MESSAGE_VERSION());\n }\n\n // sendMessage: should be able to send a single message\n // TODO: this same test needs to be done with the legacy message type\n // by setting the message version to 0\n function test_sendMessage_succeeds() external {\n // deposit transaction on the optimism portal should be called\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n )\n );\n\n // TransactionDeposited event\n vm.expectEmit(true, true, true, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n );\n\n // SentMessage event\n vm.expectEmit(true, true, true, true);\n emit SentMessage(recipient, alice, hex\"ff\", L1Messenger.messageNonce(), 100);\n\n // SentMessageExtension1 event\n vm.expectEmit(true, true, true, true);\n emit SentMessageExtension1(alice, 0);\n\n vm.prank(alice);\n L1Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n // sendMessage: should be able to send the same message twice\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L1Messenger.messageNonce());\n }\n\n function test_xDomainSender_notSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n // xDomainMessageSender: should return the xDomainMsgSender address\n // TODO: might need a test contract\n // function test_xDomainSenderSetCorrectly() external {}\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(address(op));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 2 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n // relayMessage: should send a successful call to the target contract\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.expectCall(target, hex\"1111\");\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L1Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n // set the target to be the OptimismPortal\n address target = address(op);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.prank(address(op));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n\n vm.store(address(op), 0, bytes32(abi.encode(sender)));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: should revert if eth is sent from a contract other than the standard bridge\n function test_replayMessage_withValue_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.expectRevert(\n \"CrossDomainMessenger: value must be zero unless message is from a system address\"\n );\n L1Messenger.relayMessage{ value: 100 }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n vm.expectCall(target, hex\"1111\");\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n // relayMessage: Should revert if the recipient is trying to reenter with the\n // same message.\n function test_relayMessage_reentrancySameMessage_reverts() external {\n ConfigurableCaller caller = new ConfigurableCaller();\n address target = address(caller);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory callMessage = abi.encodeWithSelector(caller.call.selector);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Set the portal's `l2Sender` to the `sender`.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(uint256(uint160(sender))));\n\n // Act as the portal and call the `relayMessage` function with the `innerMessage`.\n vm.prank(address(op));\n vm.expectCall(target, callMessage);\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Assert that the message failed to be relayed\n assertFalse(L1Messenger.successfulMessages(hash));\n assertTrue(L1Messenger.failedMessages(hash));\n\n // Set the configurable caller's target to `L1Messenger` and set the payload to `relayMessage(...)`.\n caller.setDoRevert(false);\n caller.setTarget(address(L1Messenger));\n caller.setPayload(\n abi.encodeWithSelector(\n L1Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n callMessage\n )\n );\n\n // Attempt to replay the failed message, which will *not* immediately revert this time around,\n // but attempt to reenter `relayMessage` with the same message hash. The reentrancy attempt should\n // revert.\n vm.expectEmit(true, true, true, true, target);\n emit WhatHappened(\n false,\n abi.encodeWithSignature(\"Error(string)\", \"ReentrancyGuard: reentrant call\")\n );\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Assert that the message still failed to be relayed.\n assertFalse(L1Messenger.successfulMessages(hash));\n assertTrue(L1Messenger.failedMessages(hash));\n }\n\n // relayMessage: should not revert if the recipient reenters `relayMessage` with a different\n // message hash.\n function test_relayMessage_reentrancyDiffMessage_succeeds() external {\n ConfigurableCaller caller = new ConfigurableCaller();\n address target = address(caller);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory messageA = abi.encodeWithSelector(caller.call.selector);\n bytes memory messageB = hex\"\";\n\n bytes32 hashA = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n bytes32 hashB = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageB\n );\n\n // Set the portal's `l2Sender` to the `sender`.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(uint256(uint160(sender))));\n\n // Act as the portal and call the `relayMessage` function with both `messageA` and `messageB`.\n vm.startPrank(address(op));\n\n vm.expectCall(target, messageA);\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n vm.expectCall(target, messageB);\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageB\n );\n\n // Stop acting as the portal\n vm.stopPrank();\n\n // Assert that both messages failed to be relayed\n assertFalse(L1Messenger.successfulMessages(hashA));\n assertFalse(L1Messenger.successfulMessages(hashB));\n assertTrue(L1Messenger.failedMessages(hashA));\n assertTrue(L1Messenger.failedMessages(hashB));\n\n // Set the configurable caller's target to `L1Messenger` and set the payload to `relayMessage(...)`.\n caller.setDoRevert(false);\n caller.setTarget(address(L1Messenger));\n caller.setPayload(\n abi.encodeWithSelector(\n L1Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageB\n )\n );\n\n // Attempt to replay the failed message, which will *not* immediately revert this time around,\n // but attempt to reenter `relayMessage` with messageB. The reentrancy attempt should succeed\n // because the message hashes are different.\n vm.expectEmit(true, true, true, true, target);\n emit WhatHappened(true, hex\"\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n\n // Assert that both messages are now in the `successfulMessages` mapping.\n assertTrue(L1Messenger.successfulMessages(hashA));\n assertTrue(L1Messenger.successfulMessages(hashB));\n }\n\n function test_relayMessage_legacy_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyOldReplay_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Mark legacy message as already relayed.\n uint256 successfulMessagesSlot = 203;\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(target, sender, hex\"1111\", 0);\n bytes32 slot = keccak256(abi.encode(oldHash, successfulMessagesSlot));\n vm.store(address(L1Messenger), slot, bytes32(uint256(1)));\n\n // Expect revert.\n vm.expectRevert(\"CrossDomainMessenger: legacy withdrawal already relayed\");\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was not relayed.\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyRetryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect FailedRelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n function test_relayMessage_legacyRetryAfterSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message has already been relayed\");\n\n // Retry the message again.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n}\n" - }, - "contracts/test/L1ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.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\ncontract L1ERC721Bridge_Test is Messenger_Initializer {\n TestERC721 internal localToken;\n TestERC721 internal remoteToken;\n L1ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L1ERC721Bridge(address(L1Messenger), otherBridge);\n localToken = new TestERC721();\n remoteToken = new TestERC721();\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L1ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L1Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L1Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L1ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L1ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notEscrowed_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n" - }, - "contracts/test/L1StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\n\ncontract L1StandardBridge_Getter_Test is Bridge_Initializer {\n function test_getters_succeeds() external {\n assert(L1Bridge.l2TokenBridge() == address(L2Bridge));\n assert(L1Bridge.OTHER_BRIDGE() == L2Bridge);\n assert(L1Bridge.messenger() == L1Messenger);\n assert(L1Bridge.MESSENGER() == L1Messenger);\n assertEq(L1Bridge.version(), \"1.1.0\");\n }\n}\n\ncontract L1StandardBridge_Initialize_Test is Bridge_Initializer {\n function test_initialize_succeeds() external {\n assertEq(address(L1Bridge.messenger()), address(L1Messenger));\n\n assertEq(address(L1Bridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE);\n\n assertEq(address(L2Bridge), Predeploys.L2_STANDARD_BRIDGE);\n }\n}\n\ncontract L1StandardBridge_Initialize_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_Receive_Test is Bridge_Initializer {\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(op).balance, 0);\n\n // The legacy event must be emitted for backwards compatibility\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 100,\n hex\"\"\n ),\n 200_000\n )\n );\n\n vm.prank(alice, alice);\n (bool success, ) = address(L1Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(op).balance, 100);\n }\n}\n\ncontract L1StandardBridge_Receive_TestFail {}\n\ncontract PreBridgeETH is Bridge_Initializer {\n function _preBridgeETH(bool isLegacy) internal {\n assertEq(address(op).balance, 0);\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 500,\n hex\"dead\"\n );\n\n if (isLegacy) {\n vm.expectCall(\n address(L1Bridge),\n 500,\n abi.encodeWithSelector(L1Bridge.depositETH.selector, 50000, hex\"dead\")\n );\n } else {\n vm.expectCall(\n address(L1Bridge),\n 500,\n abi.encodeWithSelector(L1Bridge.bridgeETH.selector, 50000, hex\"dead\")\n );\n }\n vm.expectCall(\n address(L1Messenger),\n 500,\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 50000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 500,\n 50000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 50000);\n vm.expectCall(\n address(op),\n 500,\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 500,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(500),\n uint256(500),\n baseGas,\n false,\n innerMessage\n );\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, alice, 500, hex\"dead\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, alice, 500, hex\"dead\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 50000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 500);\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L1StandardBridge_DepositETH_Test is PreBridgeETH {\n // depositETH\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_depositETH_succeeds() external {\n _preBridgeETH({ isLegacy: true });\n L1Bridge.depositETH{ value: 500 }(50000, hex\"dead\");\n assertEq(address(op).balance, 500);\n }\n}\n\ncontract L1StandardBridge_BridgeETH_Test is PreBridgeETH {\n // BridgeETH\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_bridgeETH_succeeds() external {\n _preBridgeETH({ isLegacy: false });\n L1Bridge.bridgeETH{ value: 500 }(50000, hex\"dead\");\n assertEq(address(op).balance, 500);\n }\n}\n\ncontract L1StandardBridge_DepositETH_TestFail is Bridge_Initializer {\n function test_depositETH_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, address(L1Token).code);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice);\n L1Bridge.depositETH{ value: 1 }(300, hex\"\");\n }\n}\n\ncontract PreBridgeETHTo is Bridge_Initializer {\n function _preBridgeETHTo(bool isLegacy) internal {\n assertEq(address(op).balance, 0);\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n if (isLegacy) {\n vm.expectCall(\n address(L1Bridge),\n 600,\n abi.encodeWithSelector(L1Bridge.depositETHTo.selector, bob, 60000, hex\"dead\")\n );\n } else {\n vm.expectCall(\n address(L1Bridge),\n 600,\n abi.encodeWithSelector(L1Bridge.bridgeETHTo.selector, bob, 60000, hex\"dead\")\n );\n }\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n bob,\n 600,\n hex\"dead\"\n );\n\n // the L1 bridge should call\n // L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 60000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 600,\n 60000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 60000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 600,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(600),\n uint256(600),\n baseGas,\n false,\n innerMessage\n );\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, bob, 600, hex\"dead\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, bob, 600, hex\"dead\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 60000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 600);\n\n // deposit eth to bob\n vm.prank(alice, alice);\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_Test is PreBridgeETHTo {\n // depositETHTo\n // - emits ETHDepositInitiated\n // - calls optimismPortal.depositTransaction\n // - EOA or contract can call\n // - ETH ends up in the optimismPortal\n function test_depositETHTo_succeeds() external {\n _preBridgeETHTo({ isLegacy: true });\n L1Bridge.depositETHTo{ value: 600 }(bob, 60000, hex\"dead\");\n assertEq(address(op).balance, 600);\n }\n}\n\ncontract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo {\n // BridgeETHTo\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_bridgeETHTo_succeeds() external {\n _preBridgeETHTo({ isLegacy: false });\n L1Bridge.bridgeETHTo{ value: 600 }(bob, 60000, hex\"dead\");\n assertEq(address(op).balance, 600);\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_DepositERC20_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // depositERC20\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - only callable by EOA\n function test_depositERC20_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n // Deal Alice's ERC20 State\n deal(address(L1Token), alice, 100000, true);\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n // The L1Bridge should transfer alice's tokens to itself\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 100)\n );\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L2Token),\n address(L1Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n // the L1 bridge should call L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 10000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 0,\n 10000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 10000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 0,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(0),\n uint256(0),\n baseGas,\n false,\n innerMessage\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 0);\n\n vm.prank(alice);\n L1Bridge.depositERC20(address(L1Token), address(L2Token), 100, 10000, hex\"\");\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n }\n}\n\ncontract L1StandardBridge_DepositERC20_TestFail is Bridge_Initializer {\n function test_depositERC20_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, hex\"ffff\");\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice, alice);\n L1Bridge.depositERC20(address(0), address(0), 100, 100, hex\"\");\n }\n}\n\ncontract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer {\n // depositERC20To\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - callable by a contract\n function test_depositERC20To_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L2Token),\n address(L1Token),\n alice,\n bob,\n 1000,\n hex\"\"\n );\n\n // the L1 bridge should call L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 10000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 0,\n 10000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 10000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 0,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(0),\n uint256(0),\n baseGas,\n false,\n innerMessage\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex\"\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 0);\n\n deal(address(L1Token), alice, 100000, true);\n\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 1000)\n );\n\n vm.prank(alice);\n L1Bridge.depositERC20To(address(L1Token), address(L2Token), bob, 1000, 10000, hex\"\");\n\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 1000);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeETHWithdrawal\n // - emits ETHWithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeETHWithdrawal_succeeds() external {\n uint256 aliceBalance = alice.balance;\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHWithdrawalFinalized(alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n vm.expectCall(alice, hex\"\");\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n // ensure that the messenger has ETH to call with\n vm.deal(address(L1Bridge.messenger()), 100);\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n\n assertEq(address(L1Bridge.messenger()).balance, 0);\n assertEq(aliceBalance + 100, alice.balance);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeERC20Withdrawal\n // - updates bridge.deposits\n // - emits ERC20WithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeERC20Withdrawal_succeeds() external {\n deal(address(L1Token), address(L1Bridge), 100, true);\n\n uint256 slot = stdstore\n .target(address(L1Bridge))\n .sig(\"deposits(address,address)\")\n .with_key(address(L1Token))\n .with_key(address(L2Token))\n .find();\n\n // Give the L1 bridge some ERC20 tokens\n vm.store(address(L1Bridge), bytes32(slot), bytes32(uint256(100)));\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20WithdrawalFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transfer.selector, alice, 100)\n );\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n assertEq(L1Token.balanceOf(address(L1Bridge)), 0);\n assertEq(L1Token.balanceOf(address(alice)), 100);\n }\n}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer {\n function test_finalizeERC20Withdrawal_notMessenger_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(28));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n\n function test_finalizeERC20Withdrawal_notOtherBridge_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(address(0)))\n );\n vm.prank(address(L1Bridge.messenger()));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n}\n\ncontract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {\n function test_finalizeBridgeETH_succeeds() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n\ncontract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer {\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L1Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L1Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, ConfigurableCaller } from \"./CommonTest.t.sol\";\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L2Messenger.messageNonce());\n assertEq(version, L2Messenger.MESSAGE_VERSION());\n }\n\n function test_sendMessage_succeeds() external {\n bytes memory xDomainCallData = Encoding.encodeCrossDomainMessage(\n L2Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n );\n vm.expectCall(\n address(messagePasser),\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData\n )\n );\n\n // MessagePassed event\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(L2Messenger),\n address(L1Messenger),\n 0,\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData,\n Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messagePasser.messageNonce(),\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: L2Messenger.baseGas(hex\"ff\", 100),\n data: xDomainCallData\n })\n )\n );\n\n vm.prank(alice);\n L2Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L2Messenger.messageNonce();\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L2Messenger.messageNonce());\n }\n\n function test_xDomainSender_senderNotSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 2), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n vm.expectCall(target, hex\"1111\");\n\n vm.prank(caller);\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L2Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L2Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n address target = address(messagePasser);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n bytes memory message = hex\"1111\";\n\n vm.prank(caller);\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retry_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n uint256 value = 100;\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(caller), value);\n vm.prank(caller);\n L2Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L2Messenger.successfulMessages(hash), false);\n assertEq(L2Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L2Messenger.successfulMessages(hash), true);\n assertEq(L2Messenger.failedMessages(hash), true);\n }\n\n // relayMessage: Should revert if the recipient is trying to reenter with the\n // same message.\n function test_relayMessage_reentrancySameMessage_reverts() external {\n ConfigurableCaller caller = new ConfigurableCaller();\n address target = address(caller);\n address sender = address(L1Messenger);\n address l1XDMAlias = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n bytes memory callMessage = abi.encodeWithSelector(caller.call.selector);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Act as the L1XDM and call the `relayMessage` function with the `innerMessage`.\n vm.prank(l1XDMAlias);\n vm.expectCall(target, callMessage);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Assert that the message failed to be relayed\n assertFalse(L2Messenger.successfulMessages(hash));\n assertTrue(L2Messenger.failedMessages(hash));\n\n // Set the configurable caller's target to `L2Messenger` and set the payload to `relayMessage(...)`.\n caller.setDoRevert(false);\n caller.setTarget(address(L2Messenger));\n caller.setPayload(\n abi.encodeWithSelector(\n L2Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n callMessage\n )\n );\n\n // Attempt to replay the failed message, which will *not* immediately revert this time around,\n // but attempt to reenter `relayMessage` with the same message hash. The reentrancy attempt should\n // revert.\n vm.expectEmit(true, true, true, true, target);\n emit WhatHappened(\n false,\n abi.encodeWithSignature(\"Error(string)\", \"ReentrancyGuard: reentrant call\")\n );\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Assert that the message still failed to be relayed.\n assertFalse(L2Messenger.successfulMessages(hash));\n assertTrue(L2Messenger.failedMessages(hash));\n }\n\n // relayMessage: should not revert if the recipient reenters `relayMessage` with a different\n // message hash.\n function test_relayMessage_reentrancyDiffMessage_succeeds() external {\n ConfigurableCaller caller = new ConfigurableCaller();\n address target = address(caller);\n address sender = address(L1Messenger);\n address l1XDMAlias = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory messageA = abi.encodeWithSelector(caller.call.selector);\n bytes memory messageB = hex\"\";\n\n bytes32 hashA = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n bytes32 hashB = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageB\n );\n\n // Act as the L1XDM and call the `relayMessage` function with both `messageA` and `messageB`.\n vm.startPrank(l1XDMAlias);\n\n vm.expectCall(target, messageA);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n vm.expectCall(target, messageB);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageB\n );\n\n // Stop acting as the L1XDM\n vm.stopPrank();\n\n // Assert that both messages failed to be relayed\n assertFalse(L2Messenger.successfulMessages(hashA));\n assertFalse(L2Messenger.successfulMessages(hashB));\n assertTrue(L2Messenger.failedMessages(hashA));\n assertTrue(L2Messenger.failedMessages(hashB));\n\n // Set the configurable caller's target to `L2Messenger` and set the payload to `relayMessage(...)`.\n caller.setDoRevert(false);\n caller.setTarget(address(L2Messenger));\n caller.setPayload(\n abi.encodeWithSelector(\n L2Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageB\n )\n );\n\n // Attempt to replay the failed message, which will *not* immediately revert this time around,\n // but attempt to reenter `relayMessage` with messageB. The reentrancy attempt should succeed\n // because the message hashes are different.\n vm.expectEmit(true, true, true, true, target);\n emit WhatHappened(true, hex\"\");\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n\n // Assert that both messages are now in the `successfulMessages` mapping.\n assertTrue(L2Messenger.successfulMessages(hashA));\n assertTrue(L2Messenger.successfulMessages(hashB));\n }\n}\n" - }, - "contracts/test/L2ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.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\ncontract TestMintableERC721 is OptimismMintableERC721 {\n constructor(address _bridge, address _remoteToken)\n OptimismMintableERC721(_bridge, 1, _remoteToken, \"Test\", \"TST\")\n {}\n\n function mint(address to, uint256 tokenId) public {\n _mint(to, tokenId);\n }\n}\n\ncontract L2ERC721Bridge_Test is Messenger_Initializer {\n TestMintableERC721 internal localToken;\n TestERC721 internal remoteToken;\n L2ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L2ERC721Bridge(address(L2Messenger), otherBridge);\n remoteToken = new TestERC721();\n localToken = new TestMintableERC721(address(bridge), address(remoteToken));\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L2ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L2Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L2Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L2ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"L2ERC721Bridge: Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L1ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L2ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"L2ERC721Bridge: Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_interfaceNotCompliant_reverts() external {\n // Create a non-compliant token\n NonCompliantERC721 nonCompliantToken = new NonCompliantERC721(alice);\n\n // Bridge the non-compliant token.\n vm.prank(alice);\n bridge.bridgeERC721(address(nonCompliantToken), address(0x01), tokenId, 1234, hex\"5678\");\n\n // Attempt to finalize the withdrawal. Should revert because the token does not claim\n // to be compliant with the `IOptimismMintableERC721` interface.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"L2ERC721Bridge: local token interface is not compliant\");\n bridge.finalizeBridgeERC721(\n address(address(nonCompliantToken)),\n address(address(0x01)),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"L2ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_alreadyExists_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721: token already minted\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n\n/**\n * @dev A non-compliant ERC721 token that does not implement the full ERC721 interface.\n *\n * This is used to test that the bridge will revert if the token does not claim to support\n * the ERC721 interface.\n */\ncontract NonCompliantERC721 {\n address internal immutable owner;\n\n constructor(address _owner) {\n owner = _owner;\n }\n\n function ownerOf(uint256) external view returns (address) {\n return owner;\n }\n\n function remoteToken() external pure returns (address) {\n return address(0x01);\n }\n\n function burn(address, uint256) external {\n // Do nothing.\n }\n\n function supportsInterface(bytes4) external pure returns (bool) {\n return false;\n }\n}\n" - }, - "contracts/test/L2OutputOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { L2OutputOracle_Initializer, NextImpl } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2OutputOracleTest is L2OutputOracle_Initializer {\n bytes32 proposedOutput1 = keccak256(abi.encode(1));\n\n function test_constructor_succeeds() external {\n assertEq(oracle.PROPOSER(), proposer);\n assertEq(oracle.CHALLENGER(), owner);\n assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval);\n assertEq(oracle.latestBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingTimestamp(), startingTimestamp);\n }\n\n function test_constructor_badTimestamp_reverts() external {\n vm.expectRevert(\"L2OutputOracle: starting L2 timestamp must be less than current time\");\n\n // startingTimestamp is in the future\n new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp + 1,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n function test_constructor_l2BlockTimeZero_reverts() external {\n vm.expectRevert(\"L2OutputOracle: L2 block time must be greater than 0\");\n new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: 0,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n function testFuzz_constructor_submissionIntervalLteL2BlockTime_reverts(\n uint256 _submissionInterval,\n uint256 _l2BlockTime\n ) external {\n // Bound the _l2blockTime to be in the range of [1, type(uint256).max]\n _l2BlockTime = bound(_l2BlockTime, 1, type(uint256).max);\n // Roll the block number to _l2blockTime (the starting L2 timestamp must be less than or equal to the current time)\n vm.roll(_l2BlockTime);\n // Bound _submissionInterval to be less than or equal to _l2BlockTime\n _submissionInterval = bound(_submissionInterval, 0, _l2BlockTime);\n\n vm.expectRevert(\"L2OutputOracle: submission interval must be greater than L2 block time\");\n new L2OutputOracle({\n _submissionInterval: _submissionInterval,\n _l2BlockTime: _l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n /****************\n * Getter Tests *\n ****************/\n\n // Test: latestBlockNumber() should return the correct value\n function test_latestBlockNumber_succeeds() external {\n uint256 proposedNumber = oracle.nextBlockNumber();\n\n // Roll to after the block number we'll propose\n warpToProposeTime(proposedNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, proposedNumber, 0, 0);\n assertEq(oracle.latestBlockNumber(), proposedNumber);\n }\n\n // Test: getL2Output() should return the correct value\n function test_getL2Output_succeeds() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0);\n\n Types.OutputProposal memory proposal = oracle.getL2Output(nextOutputIndex);\n assertEq(proposal.outputRoot, proposedOutput1);\n assertEq(proposal.timestamp, block.timestamp);\n\n // The block number is larger than the latest proposed output:\n vm.expectRevert(stdError.indexOOBError);\n oracle.getL2Output(nextOutputIndex + 1);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is exact block\n function test_getL2OutputIndexAfter_sameBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with exact same block as proposed returns the proposal.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is previous block\n function test_getL2OutputIndexAfter_previousBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with previous block returns the proposal too.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 - 1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value during binary search\n function test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n bytes32 output2 = keccak256(abi.encode(2));\n uint256 nextBlockNumber2 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber2);\n vm.prank(proposer);\n oracle.proposeL2Output(output2, nextBlockNumber2, 0, 0);\n\n bytes32 output3 = keccak256(abi.encode(3));\n uint256 nextBlockNumber3 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber3);\n vm.prank(proposer);\n oracle.proposeL2Output(output3, nextBlockNumber3, 0, 0);\n\n bytes32 output4 = keccak256(abi.encode(4));\n uint256 nextBlockNumber4 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber4);\n vm.prank(proposer);\n oracle.proposeL2Output(output4, nextBlockNumber4, 0, 0);\n\n // Querying with a block number between the first and second proposal\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 + 1);\n assertEq(index1, 1);\n\n // Querying with a block number between the second and third proposal\n uint256 index2 = oracle.getL2OutputIndexAfter(nextBlockNumber2 + 1);\n assertEq(index2, 2);\n\n // Querying with a block number between the third and fourth proposal\n uint256 index3 = oracle.getL2OutputIndexAfter(nextBlockNumber3 + 1);\n assertEq(index3, 3);\n }\n\n // Test: getL2OutputIndexAfter() reverts when no output exists yet\n function test_getL2OutputIndexAfter_noOutputsExis_reverts() external {\n vm.expectRevert(\"L2OutputOracle: cannot get output as no outputs have been proposed yet\");\n oracle.getL2OutputIndexAfter(0);\n }\n\n // Test: nextBlockNumber() should return the correct value\n function test_nextBlockNumber_succeeds() external {\n assertEq(\n oracle.nextBlockNumber(),\n // The return value should match this arithmetic\n oracle.latestBlockNumber() + oracle.SUBMISSION_INTERVAL()\n );\n }\n\n function test_computeL2Timestamp_succeeds() external {\n // reverts if timestamp is too low\n vm.expectRevert(stdError.arithmeticError);\n oracle.computeL2Timestamp(startingBlockNumber - 1);\n\n // returns the correct value...\n // ... for the very first block\n assertEq(oracle.computeL2Timestamp(startingBlockNumber), startingTimestamp);\n\n // ... for the first block after the starting block\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 1),\n startingTimestamp + l2BlockTime\n );\n\n // ... for some other block number\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 96024),\n startingTimestamp + l2BlockTime * 96024\n );\n }\n\n /*****************************\n * Propose Tests - Happy Path *\n *****************************/\n\n // Test: proposeL2Output succeeds when given valid input, and no block hash and number are\n // specified.\n function test_proposeL2Output_proposeAnotherOutput_succeeds() public {\n bytes32 proposedOutput2 = keccak256(abi.encode());\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n uint256 proposedNumber = oracle.latestBlockNumber();\n\n // Ensure the submissionInterval is enforced\n assertEq(nextBlockNumber, proposedNumber + submissionInterval);\n\n vm.roll(nextBlockNumber + 1);\n\n vm.expectEmit(true, true, true, true);\n emit OutputProposed(proposedOutput2, nextOutputIndex, nextBlockNumber, block.timestamp);\n\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output succeeds when given valid input, and when a block hash and number are\n // specified for reorg protection.\n function test_proposeWithBlockhashAndHeight_succeeds() external {\n // Get the number and hash of a previous block in the chain\n uint256 prevL1BlockNumber = block.number - 1;\n bytes32 prevL1BlockHash = blockhash(prevL1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber);\n }\n\n /***************************\n * Propose Tests - Sad Path *\n ***************************/\n\n // Test: proposeL2Output fails if called by a party that is not the proposer.\n function test_proposeL2Output_notProposer_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n\n vm.prank(address(128));\n vm.expectRevert(\"L2OutputOracle: only the proposer address can propose new outputs\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails given a zero blockhash.\n function test_proposeL2Output_emptyOutput_reverts() external {\n bytes32 outputToPropose = bytes32(0);\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: L2 output proposal cannot be the zero hash\");\n oracle.proposeL2Output(outputToPropose, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if the block number doesn't match the next expected number.\n function test_proposeL2Output_unexpectedBlockNumber_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: block number must be equal to next expected block number\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0);\n }\n\n // Test: proposeL2Output fails if it would have a timestamp in the future.\n function test_proposeL2Output_futureTimetamp_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextTimestamp = oracle.computeL2Timestamp(nextBlockNumber);\n vm.warp(nextTimestamp);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: cannot propose L2 output in the future\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if a non-existent L1 block hash and number are provided for reorg\n // protection.\n function test_proposeL2Output_wrongFork_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(\n nonZeroHash,\n nextBlockNumber,\n bytes32(uint256(0x01)),\n block.number - 1\n );\n }\n\n // Test: proposeL2Output fails when given valid input, but the block hash and number do not\n // match.\n function test_proposeL2Output_unmatchedBlockhash_reverts() external {\n // Move ahead to block 100 so that we can reference historical blocks\n vm.roll(100);\n\n // Get the number and hash of a previous block in the chain\n uint256 l1BlockNumber = block.number - 1;\n bytes32 l1BlockHash = blockhash(l1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n\n // This will fail when foundry no longer returns zerod block hashes\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1);\n }\n\n /*****************************\n * Delete Tests - Happy Path *\n *****************************/\n\n function test_deleteOutputs_singleOutput_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 1);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex);\n oracle.deleteL2Outputs(latestOutputIndex);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n function test_deleteOutputs_multipleOutputs_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 3);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex - 2);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval * 3, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n /***************************\n * Delete Tests - Sad Path *\n ***************************/\n\n function test_deleteL2Outputs_ifNotChallenger_reverts() external {\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.expectRevert(\"L2OutputOracle: only the challenger address can delete outputs\");\n oracle.deleteL2Outputs(latestBlockNumber);\n }\n\n function test_deleteL2Outputs_nonExistent_reverts() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestBlockNumber + 1);\n }\n\n function test_deleteL2Outputs_afterLatest_reverts() external {\n // Start by proposing three outputs\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n // Delete the latest two outputs\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n vm.prank(owner);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // Now try to delete the same output again\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n }\n\n function test_deleteL2Outputs_finalized_reverts() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n // Warp past the finalization period + 1 second\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n\n // Try to delete a finalized output\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs that have already been finalized\");\n oracle.deleteL2Outputs(latestOutputIndex);\n }\n}\n\ncontract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {\n Proxy internal proxy;\n\n function setUp() public override {\n super.setUp();\n proxy = Proxy(payable(address(oracle)));\n }\n\n function test_initValuesOnProxy_succeeds() external {\n assertEq(submissionInterval, oracleImpl.SUBMISSION_INTERVAL());\n assertEq(l2BlockTime, oracleImpl.L2_BLOCK_TIME());\n assertEq(startingBlockNumber, oracleImpl.startingBlockNumber());\n assertEq(startingTimestamp, oracleImpl.startingTimestamp());\n\n assertEq(proposer, oracleImpl.PROPOSER());\n assertEq(owner, oracleImpl.CHALLENGER());\n }\n\n function test_initializeProxy_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(payable(proxy)).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_initializeImpl_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(oracleImpl).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(oracle), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(oracle), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(oracle)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n" - }, - "contracts/test/L2StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { console } from \"forge-std/console.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\ncontract L2StandardBridge_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n function test_initialize_succeeds() external {\n assertEq(address(L2Bridge.messenger()), address(L2Messenger));\n assertEq(L1Bridge.l2TokenBridge(), address(L2Bridge));\n assertEq(address(L2Bridge.OTHER_BRIDGE()), address(L1Bridge));\n }\n\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(messagePasser).balance, 0);\n uint256 nonce = L2Messenger.messageNonce();\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 200_000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 100,\n 200_000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 100,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalInitiated(address(0), Predeploys.LEGACY_ERC20_ETH, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n // L2ToL1MessagePasser will emit a MessagePassed event\n vm.expectEmit(true, true, true, true, address(messagePasser));\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 100,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 200_000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessageExtension1(address(L2Bridge), 100);\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 200_000 // StandardBridge's RECEIVE_DEFAULT_GAS_LIMIT\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n vm.prank(alice, alice);\n (bool success, ) = address(L2Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(messagePasser).balance, 100);\n }\n\n // withrdraw\n // - requires amount == msg.value\n function test_withdraw_insufficientValue_reverts() external {\n assertEq(address(messagePasser).balance, 0);\n\n vm.expectRevert(\"StandardBridge: bridging ETH must include sufficient ETH value\");\n vm.prank(alice, alice);\n L2Bridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 100, 1000, hex\"\");\n }\n\n /**\n * @notice Use the legacy `withdraw` interface on the L2StandardBridge to\n * withdraw ether from L2 to L1.\n */\n function test_withdraw_ether_succeeds() external {\n assertTrue(alice.balance >= 100);\n assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 0);\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit WithdrawalInitiated({\n l1Token: address(0),\n l2Token: Predeploys.LEGACY_ERC20_ETH,\n from: alice,\n to: alice,\n amount: 100,\n data: hex\"\"\n });\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ETHBridgeInitiated({ from: alice, to: alice, amount: 100, data: hex\"\" });\n\n vm.prank(alice, alice);\n L2Bridge.withdraw{ value: 100 }({\n _l2Token: Predeploys.LEGACY_ERC20_ETH,\n _amount: 100,\n _minGasLimit: 1000,\n _extraData: hex\"\"\n });\n\n assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 100);\n }\n}\n\ncontract PreBridgeERC20 is Bridge_Initializer {\n // withdraw and BridgeERC20 should behave the same when transferring ERC20 tokens\n // so they should share the same setup and expectEmit calls\n function _preBridgeERC20(bool _isLegacy, address _l2Token) internal {\n // Alice has 100 L2Token\n deal(_l2Token, alice, 100, true);\n assertEq(ERC20(_l2Token).balanceOf(alice), 100);\n uint256 nonce = L2Messenger.messageNonce();\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L1Token),\n _l2Token,\n alice,\n alice,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 1000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 0,\n 1000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n if (_isLegacy) {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(L2Bridge.withdraw.selector, _l2Token, 100, 1000, hex\"\")\n );\n } else {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.bridgeERC20.selector,\n _l2Token,\n address(L1Token),\n 100,\n 1000,\n hex\"\"\n )\n );\n }\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 1000\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n // The L2Bridge should burn the tokens\n vm.expectCall(\n _l2Token,\n abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalInitiated(address(L1Token), _l2Token, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 0,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true);\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true);\n emit SentMessageExtension1(address(L2Bridge), 0);\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {\n // withdraw\n // - token is burned\n // - emits WithdrawalInitiated\n // - calls Withdrawer.initiateWithdrawal\n function test_withdraw_withdrawingERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: true, _l2Token: address(L2Token) });\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n // BridgeERC20\n // - token is burned\n // - emits WithdrawalInitiated\n // - calls Withdrawer.initiateWithdrawal\n function test_bridgeERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: false, _l2Token: address(L2Token) });\n L2Bridge.bridgeERC20(address(L2Token), address(L1Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_withdrawLegacyERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: true, _l2Token: address(LegacyL2Token) });\n L2Bridge.withdraw(address(LegacyL2Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_bridgeLegacyERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: false, _l2Token: address(LegacyL2Token) });\n L2Bridge.bridgeERC20(address(LegacyL2Token), address(L1Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_withdraw_notEOA_reverts() external {\n // This contract has 100 L2Token\n deal(address(L2Token), address(this), 100, true);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n }\n}\n\ncontract PreBridgeERC20To is Bridge_Initializer {\n // withdrawTo and BridgeERC20To should behave the same when transferring ERC20 tokens\n // so they should share the same setup and expectEmit calls\n function _preBridgeERC20To(bool _isLegacy, address _l2Token) internal {\n deal(_l2Token, alice, 100, true);\n assertEq(ERC20(L2Token).balanceOf(alice), 100);\n uint256 nonce = L2Messenger.messageNonce();\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L1Token),\n _l2Token,\n alice,\n bob,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 1000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 0,\n 1000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit WithdrawalInitiated(address(L1Token), _l2Token, alice, bob, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, bob, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(messagePasser));\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 0,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessageExtension1(address(L2Bridge), 0);\n\n if (_isLegacy) {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.withdrawTo.selector,\n _l2Token,\n bob,\n 100,\n 1000,\n hex\"\"\n )\n );\n } else {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.bridgeERC20To.selector,\n _l2Token,\n address(L1Token),\n bob,\n 100,\n 1000,\n hex\"\"\n )\n );\n }\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 1000\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n // The L2Bridge should burn the tokens\n vm.expectCall(\n address(L2Token),\n abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)\n );\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To {\n // withdrawTo\n // - token is burned\n // - emits WithdrawalInitiated w/ correct recipient\n // - calls Withdrawer.initiateWithdrawal\n function test_withdrawTo_withdrawingERC20_succeeds() external {\n _preBridgeERC20To({ _isLegacy: true, _l2Token: address(L2Token) });\n L2Bridge.withdrawTo(address(L2Token), bob, 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n // bridgeERC20To\n // - token is burned\n // - emits WithdrawalInitiated w/ correct recipient\n // - calls Withdrawer.initiateWithdrawal\n function test_bridgeERC20To_succeeds() external {\n _preBridgeERC20To({ _isLegacy: false, _l2Token: address(L2Token) });\n L2Bridge.bridgeERC20To(address(L2Token), address(L1Token), bob, 100, 1000, hex\"\");\n assertEq(L2Token.balanceOf(alice), 0);\n }\n}\n\ncontract L2StandardBridge_Bridge_Test is Bridge_Initializer {\n // finalizeDeposit\n // - only callable by l1TokenBridge\n // - supported token pair emits DepositFinalized\n // - invalid deposit calls Withdrawer.initiateWithdrawal\n function test_finalizeDeposit_depositingERC20_succeeds() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n\n vm.expectCall(\n address(L2Token),\n abi.encodeWithSelector(OptimismMintableERC20.mint.selector, alice, 100)\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeFinalized(address(L2Token), address(L1Token), alice, alice, 100, hex\"\");\n\n vm.prank(address(L2Messenger));\n L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n }\n\n function test_finalizeDeposit_depositingETH_succeeds() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeFinalized(\n address(L2Token), // localToken\n address(L1Token), // remoteToken\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n vm.prank(address(L2Messenger));\n L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L2Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Messenger), 100, hex\"\");\n }\n}\n\ncontract L2StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {\n function test_finalizeBridgeETH_succeeds() external {\n address messenger = address(L2Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n\n vm.expectEmit(true, true, true, true);\n emit DepositFinalized(address(0), Predeploys.LEGACY_ERC20_ETH, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2ToL1MessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\n\ncontract L2ToL1MessagePasserTest is CommonTest {\n L2ToL1MessagePasser messagePasser;\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n function setUp() public virtual override {\n super.setUp();\n messagePasser = new L2ToL1MessagePasser();\n }\n\n function testFuzz_initiateWithdrawal_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint256 nonce = messagePasser.messageNonce();\n\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: _value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, _sender, _target, _value, _gasLimit, _data, withdrawalHash);\n\n vm.deal(_sender, _value);\n vm.prank(_sender);\n messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);\n\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n\n bytes32 slot = keccak256(bytes.concat(withdrawalHash, bytes32(0)));\n\n assertEq(vm.load(address(messagePasser), slot), bytes32(uint256(1)));\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by a contract\n function test_initiateWithdrawal_fromContract_succeeds() external {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\"\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\",\n withdrawalHash\n );\n\n vm.deal(address(this), 2**64);\n messagePasser.initiateWithdrawal{ value: 100 }(address(4), 64000, hex\"\");\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by an EOA\n function test_initiateWithdrawal_fromEOA_succeeds() external {\n uint256 gasLimit = 64000;\n address target = address(4);\n uint256 value = 100;\n bytes memory data = hex\"ff\";\n uint256 nonce = messagePasser.messageNonce();\n\n // EOA emulation\n vm.prank(alice, alice);\n vm.deal(alice, 2**64);\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(nonce, alice, target, value, gasLimit, data)\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, alice, target, value, gasLimit, data, withdrawalHash);\n\n messagePasser.initiateWithdrawal{ value: value }(target, gasLimit, data);\n\n // the sent messages mapping is filled\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n // the nonce increments\n assertEq(nonce + 1, messagePasser.messageNonce());\n }\n\n // Test: burn should destroy the ETH held in the contract\n function test_burn_succeeds() external {\n messagePasser.initiateWithdrawal{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n NON_ZERO_GASLIMIT,\n NON_ZERO_DATA\n );\n\n assertEq(address(messagePasser).balance, NON_ZERO_VALUE);\n vm.expectEmit(true, false, false, false);\n emit WithdrawerBalanceBurnt(NON_ZERO_VALUE);\n messagePasser.burn();\n\n // The Withdrawer should have no balance\n assertEq(address(messagePasser).balance, 0);\n }\n}\n" - }, - "contracts/test/LegacyERC20ETH.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyERC20ETH_Test is CommonTest {\n LegacyERC20ETH eth;\n\n function setUp() public virtual override {\n super.setUp();\n eth = new LegacyERC20ETH();\n }\n\n function test_metadata_succeeds() external {\n assertEq(eth.name(), \"Ether\");\n assertEq(eth.symbol(), \"ETH\");\n assertEq(eth.decimals(), 18);\n }\n\n function test_crossDomain_succeeds() external {\n assertEq(eth.l2Bridge(), Predeploys.L2_STANDARD_BRIDGE);\n assertEq(eth.l1Token(), address(0));\n }\n\n function test_transfer_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transfer is disabled\");\n eth.transfer(alice, 100);\n }\n\n function test_approve_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: approve is disabled\");\n eth.approve(alice, 100);\n }\n\n function test_transferFrom_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transferFrom is disabled\");\n eth.transferFrom(bob, alice, 100);\n }\n\n function test_increaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n eth.increaseAllowance(alice, 100);\n }\n\n function test_decreaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n eth.decreaseAllowance(alice, 100);\n }\n\n function test_mint_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: mint is disabled\");\n eth.mint(alice, 100);\n }\n\n function test_burn_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: burn is disabled\");\n eth.burn(alice, 100);\n }\n}\n" - }, - "contracts/test/LegacyMessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyMessagePasser } from \"../legacy/LegacyMessagePasser.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyMessagePasser_Test is CommonTest {\n LegacyMessagePasser messagePasser;\n\n function setUp() public virtual override {\n super.setUp();\n messagePasser = new LegacyMessagePasser();\n }\n\n function test_passMessageToL1_succeeds() external {\n vm.prank(alice);\n messagePasser.passMessageToL1(hex\"ff\");\n assert(messagePasser.sentMessages(keccak256(abi.encodePacked(hex\"ff\", alice))));\n }\n}\n" - }, - "contracts/test/MerkleTrie.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MerkleTrie } from \"../libraries/trie/MerkleTrie.sol\";\n\ncontract MerkleTrie_get_Test is CommonTest {\n function test_get_validProof1_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579326262\";\n bytes memory val = hex\"6176616c32\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof2_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[\n 2\n ] = hex\"ef83206161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof3_succeeds() external {\n bytes32 root = 0xf838216fa749aefa91e0b672a9c06d3e6e983f913d7107b5dab4af60b5f5abed;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"f387206b6579316161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof4_succeeds() external {\n bytes32 root = 0x37956bab6bba472308146808d5311ac19cb4a7daae5df7efcc0f32badc97f55e;\n bytes memory key = hex\"6b6579316161\";\n bytes memory val = hex\"3031323334\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"ce87206b6579316161853031323334\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof5_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657931\";\n bytes\n memory val = hex\"30313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f862808080808080a057895fdbd71e2c67c2f9274a56811ff5cf458720a7fa713a135e3890f8cafcf8808080808080808080b130313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof6_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657932\";\n bytes memory val = hex\"73686f7274\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[2] = hex\"df808080808080c9823262856176616c338080808080808080808573686f7274\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof7_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657933\";\n bytes memory val = hex\"31323334353637383930313233343536373839303132333435363738393031\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f839808080808080c9823363856176616c338080808080808080809f31323334353637383930313233343536373839303132333435363738393031\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof8_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"61\";\n bytes memory val = hex\"61\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22061\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof9_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"62\";\n bytes memory val = hex\"62\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22062\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof10_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"63\";\n bytes memory val = hex\"63\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22063\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_nonexistentKey1_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b657932\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_nonexistentKey2_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"616e7972616e646f6d6b6579\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_wrongKeyProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579316161\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e216a04892c039d654f1be9af20e88ae53e9ab5fa5520190e0fb2f805823e45ebad22f\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[2] = hex\"d687206e6f746865728d33343938683472697568677765\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_corruptedProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579326262\";\n bytes[] memory proof = new bytes[](5);\n proof[0] = hex\"2fd2ba5ee42358802ffbe0900152a55fabe953ae880ef29abef154d639c09248a016e2\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[\n 2\n ] = hex\"e583165793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 3\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[4] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidDataRemainder_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa000000000000000000000000000000\";\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidInternalNodeHash_reverts() external {\n bytes32 root = 0xa827dff1a657bb9bb9a1c3abe9db173e2f1359f15eb06f1647ea21ac7c95d8fa;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa09862c6b113008c4204c13755693cbb868acc25ebaa98db11df8c89a0c0dd3157\";\n proof[\n 1\n ] = hex\"f380808080808080808080a0de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f00c220118080808080\";\n proof[2] = hex\"de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroBranchValueLength_reverts() external {\n bytes32 root = 0xe04b3589eef96b237cd49ccb5dcf6e654a47682bfa0961d563ab843f7ad1e035;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](2);\n proof[0] = hex\"dd8200aad98080808080808080808080c43b82aabbc43c82aacc80808080\";\n proof[1] = hex\"d98080808080808080808080c43b82aabbc43c82aacc80808080\";\n\n vm.expectRevert(\"MerkleTrie: value length must be greater than zero (branch)\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroLengthKey_reverts() external {\n bytes32 root = 0x54157fd62cdf2f474e7bfec2d3cd581e807bee38488c9590cb887add98936b73;\n bytes memory key = hex\"\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"c78320f00082b443\";\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey1_reverts() external {\n bytes32 root = 0xa513ba530659356fb7588a2c831944e80fd8aedaa5a4dc36f918152be2be0605;\n bytes memory key = hex\"01\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"db10d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[1] = hex\"d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[2] = hex\"c582202381aa\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey2_reverts() external {\n bytes32 root = 0xa06abffaec4ebe8ccde595f4547b864b4421b21c1fc699973f94710c9bc17979;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa07ea462226a3dc0a46afb4ded39306d7a84d311ada3557dfc75a909fd25530905\";\n proof[\n 1\n ] = hex\"f380808080808080808080a027f11bd3af96d137b9287632f44dd00fea1ca1bd70386c30985ede8cc287476e808080c220338080\";\n proof[2] = hex\"e48200bba0a6911545ed01c2d3f4e15b8b27c7bfba97738bd5e6dd674dd07033428a4c53af\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_extraProofElements_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](4);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa\";\n proof[3] = hex\"c32081aa\";\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_validProofs_succeeds(bytes4) external {\n // Generate a test case with a valid proof of inclusion for the k/v pair in the trie.\n (bytes32 root, bytes memory key, bytes memory val, bytes[] memory proof) = ffi\n .getMerkleTrieFuzzCase(\"valid\");\n\n // Assert that our expected value is equal to our actual value.\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidRoot_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"valid\"\n );\n\n bytes32 rootHash = keccak256(abi.encodePacked(root));\n vm.expectRevert(\"MerkleTrie: invalid root hash\");\n MerkleTrie.get(key, proof, rootHash);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_extraProofElements_reverts(bytes4) external {\n // Generate an invalid test case with an extra proof element attached to an otherwise\n // valid proof of inclusion for the passed k/v.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"extra_proof_elems\"\n );\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidLargeInternalHash_reverts(bytes4) external {\n // Generate an invalid test case where a long proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_large_internal_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid large internal hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidInternalNodeHash_reverts(bytes4) external {\n // Generate an invalid test case where a small proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_internal_node_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_corruptedProof_reverts(bytes4) external {\n // Generate an invalid test case where the proof is malformed.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"corrupted_proof\"\n );\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidDataRemainder_reverts(bytes4) external {\n // Generate an invalid test case where a random element of the proof has more bytes than the\n // length designates within the RLP list encoding.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_data_remainder\"\n );\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_prefixedValidKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and a valid key that is prefixed\n // with random bytes\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"prefixed_valid_key\"\n );\n\n // Ambiguous revert check- all that we care is that it *does* fail. This case may\n // fail within different branches.\n vm.expectRevert();\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_emptyKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and an empty key\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"empty_key\"\n );\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_partialProof_reverts(bytes4) external {\n // Get a random test case with a valid trie / partially correct proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"partial_proof\"\n );\n\n vm.expectRevert(\"MerkleTrie: ran out of proof elements\");\n MerkleTrie.get(key, proof, root);\n }\n}\n" - }, - "contracts/test/MintManager.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MintManager } from \"../governance/MintManager.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract MintManager_Initializer is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n MintManager internal manager;\n\n function setUp() public virtual override {\n super.setUp();\n\n vm.prank(owner);\n gov = new GovernanceToken();\n\n vm.prank(owner);\n manager = new MintManager(owner, address(gov));\n\n vm.prank(owner);\n gov.transferOwnership(address(manager));\n }\n}\n\ncontract MintManager_constructor_Test is MintManager_Initializer {\n /**\n * @notice Tests that the constructor properly configures the contract.\n */\n function test_constructor_succeeds() external {\n assertEq(manager.owner(), owner);\n assertEq(address(manager.governanceToken()), address(gov));\n }\n}\n\ncontract MintManager_mint_Test is MintManager_Initializer {\n /**\n * @notice Tests that the mint function properly mints tokens when called by the owner.\n */\n function test_mint_fromOwner_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n /**\n * @notice Tests that the mint function reverts when called by a non-owner.\n */\n function test_mint_fromNotOwner_reverts() external {\n // Mint from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.mint(owner, 100);\n }\n\n /**\n * @notice Tests that the mint function properly mints tokens when called by the owner a second\n * time after the mint period has elapsed.\n */\n function test_mint_afterPeriodElapsed_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again after period elapsed (2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n manager.mint(owner, 2);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 102);\n }\n\n /**\n * @notice Tests that the mint function always reverts when called before the mint period has\n * elapsed, even if the caller is the owner.\n */\n function test_mint_beforePeriodElapsed_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: minting not permitted yet\");\n manager.mint(owner, 100);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n /**\n * @notice Tests that the owner cannot mint more than the mint cap.\n */\n function test_mint_moreThanCap_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again (greater than 2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint amount exceeds cap\");\n manager.mint(owner, 3);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n}\n\ncontract MintManager_upgrade_Test is MintManager_Initializer {\n /**\n * @notice Tests that the owner can upgrade the mint manager.\n */\n function test_upgrade_fromOwner_succeeds() external {\n // Upgrade to new manager.\n vm.prank(owner);\n manager.upgrade(rando);\n\n // New manager is rando.\n assertEq(gov.owner(), rando);\n }\n\n /**\n * @notice Tests that the upgrade function reverts when called by a non-owner.\n */\n function test_upgrade_fromNotOwner_reverts() external {\n // Upgrade from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.upgrade(rando);\n }\n\n /**\n * @notice Tests that the upgrade function reverts when attempting to update to the zero\n * address, even if the caller is the owner.\n */\n function test_upgrade_toZeroAddress_reverts() external {\n // Upgrade to zero address fails.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint manager cannot be the zero address\");\n manager.upgrade(address(0));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport {\n ILegacyMintableERC20,\n IOptimismMintableERC20\n} from \"../universal/IOptimismMintableERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ncontract OptimismMintableERC20_Test is Bridge_Initializer {\n event Mint(address indexed account, uint256 amount);\n event Burn(address indexed account, uint256 amount);\n\n function test_semver_succeeds() external {\n assertEq(L2Token.version(), \"1.0.0\");\n }\n\n function test_remoteToken_succeeds() external {\n assertEq(L2Token.remoteToken(), address(L1Token));\n }\n\n function test_bridge_succeeds() external {\n assertEq(L2Token.bridge(), address(L2Bridge));\n }\n\n function test_l1Token_succeeds() external {\n assertEq(L2Token.l1Token(), address(L1Token));\n }\n\n function test_l2Bridge_succeeds() external {\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_legacy_succeeds() external {\n // Getters for the remote token\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.l1Token(), address(L1Token));\n // Getters for the bridge\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_mint_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 100);\n }\n\n function test_mint_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.mint(alice, 100);\n }\n\n function test_burn_succeeds() external {\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_burn_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.burn(alice, 100);\n }\n\n function test_erc165_supportsInterface_succeeds() external {\n // The assertEq calls in this test are comparing the manual calculation of the iface,\n // with what is returned by the solidity's type().interfaceId, just to be safe.\n bytes4 iface1 = bytes4(keccak256(\"supportsInterface(bytes4)\"));\n assertEq(iface1, type(IERC165).interfaceId);\n assert(L2Token.supportsInterface(iface1));\n\n bytes4 iface2 = L2Token.l1Token.selector ^ L2Token.mint.selector ^ L2Token.burn.selector;\n assertEq(iface2, type(ILegacyMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface2));\n\n bytes4 iface3 = L2Token.remoteToken.selector ^\n L2Token.bridge.selector ^\n L2Token.mint.selector ^\n L2Token.burn.selector;\n assertEq(iface3, type(IOptimismMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface3));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\n\ncontract OptimismMintableTokenFactory_Test is Bridge_Initializer {\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n }\n\n function test_bridge_succeeds() external {\n assertEq(address(L2TokenFactory.BRIDGE()), address(L2Bridge));\n }\n\n function test_createStandardL2Token_succeeds() external {\n address remote = address(4);\n address local = LibRLP.computeAddress(address(L2TokenFactory), 2);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_sameTwice_succeeds() external {\n address remote = address(4);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n\n address local = LibRLP.computeAddress(address(L2TokenFactory), 3);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_remoteIsZero_succeeds() external {\n address remote = address(0);\n vm.expectRevert(\"OptimismMintableERC20Factory: must provide remote token address\");\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\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 { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.sol\";\n\ncontract OptimismMintableERC721_Test is ERC721Bridge_Initializer {\n ERC721 internal L1Token;\n OptimismMintableERC721 internal L2Token;\n\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n event Mint(address indexed account, uint256 tokenId);\n\n event Burn(address indexed account, uint256 tokenId);\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n L1Token = new ERC721(\"L1Token\", \"L1T\");\n L2Token = new OptimismMintableERC721(\n address(L2Bridge),\n 1,\n address(L1Token),\n \"L2Token\",\n \"L2T\"\n );\n\n // Label the addresses for nice traces.\n vm.label(address(L1Token), \"L1ERC721Token\");\n vm.label(address(L2Token), \"L2ERC721Token\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(L2Token.name(), \"L2Token\");\n assertEq(L2Token.symbol(), \"L2T\");\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.remoteChainId(), 1);\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.REMOTE_CHAIN_ID(), 1);\n assertEq(L2Token.version(), \"1.0.0\");\n }\n\n function test_safeMint_succeeds() external {\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(address(0), alice, 1);\n\n // Expect a mint event.\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 1);\n\n // Mint the token.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token should be owned by alice.\n assertEq(L2Token.ownerOf(1), alice);\n }\n\n function test_safeMint_notBridge_reverts() external {\n // Try to mint the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.safeMint(alice, 1);\n }\n\n function test_burn_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(alice, address(0), 1);\n\n // Expect a burn event.\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 1);\n\n // Burn the token.\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 1);\n\n // Token should be owned by address(0).\n vm.expectRevert(\"ERC721: invalid token ID\");\n L2Token.ownerOf(1);\n }\n\n function test_burn_notBridge_reverts() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Try to burn the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.burn(alice, 1);\n }\n\n function test_tokenURI_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token URI should be correct.\n assertEq(\n L2Token.tokenURI(1),\n string(\n abi.encodePacked(\n \"ethereum:\",\n Strings.toHexString(uint160(address(L1Token)), 20),\n \"@\",\n Strings.toString(1),\n \"/tokenURI?uint256=\",\n Strings.toString(1)\n )\n )\n );\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\n\ncontract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer {\n OptimismMintableERC721Factory internal factory;\n\n event OptimismMintableERC721Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n factory = new OptimismMintableERC721Factory(address(L2Bridge), 1);\n\n // Label the addresses for nice traces.\n vm.label(address(factory), \"OptimismMintableERC721Factory\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(factory.BRIDGE(), address(L2Bridge));\n assertEq(factory.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_succeeds() external {\n // Predict the address based on the factory address and nonce.\n address predicted = LibRLP.computeAddress(address(factory), 1);\n\n // Expect a token creation event.\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC721Created(predicted, address(1234), alice);\n\n // Create the token.\n vm.prank(alice);\n OptimismMintableERC721 created = OptimismMintableERC721(\n factory.createOptimismMintableERC721(address(1234), \"L2Token\", \"L2T\")\n );\n\n // Token address should be correct.\n assertEq(address(created), predicted);\n\n // Should be marked as created by the factory.\n assertEq(factory.isOptimismMintableERC721(address(created)), true);\n\n // Token should've been constructed correctly.\n assertEq(created.name(), \"L2Token\");\n assertEq(created.symbol(), \"L2T\");\n assertEq(created.REMOTE_TOKEN(), address(1234));\n assertEq(created.BRIDGE(), address(L2Bridge));\n assertEq(created.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_zeroRemoteToken_reverts() external {\n // Try to create a token with a zero remote token address.\n vm.expectRevert(\"OptimismMintableERC721Factory: L1 token address cannot be address(0)\");\n factory.createOptimismMintableERC721(address(0), \"L2Token\", \"L2T\");\n }\n}\n" - }, - "contracts/test/OptimismPortal.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { Portal_Initializer, CommonTest, NextImpl } from \"./CommonTest.t.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\ncontract OptimismPortal_Test is Portal_Initializer {\n event Paused(address);\n event Unpaused(address);\n\n function test_constructor_succeeds() external {\n assertEq(address(op.L2_ORACLE()), address(oracle));\n assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD);\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal can be paused by the GUARDIAN\n */\n function test_pause_succeeds() external {\n address guardian = op.GUARDIAN();\n\n assertEq(op.paused(), false);\n\n vm.expectEmit(true, true, true, true, address(op));\n emit Paused(guardian);\n\n vm.prank(guardian);\n op.pause();\n\n assertEq(op.paused(), true);\n }\n\n /**\n * @notice The OptimismPortal reverts when an account that is not the\n * GUARDIAN calls `pause()`\n */\n function test_pause_onlyGuardian_reverts() external {\n assertEq(op.paused(), false);\n\n assertTrue(op.GUARDIAN() != alice);\n vm.expectRevert(\"OptimismPortal: only guardian can pause\");\n vm.prank(alice);\n op.pause();\n\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal can be unpaused by the GUARDIAN\n */\n function test_unpause_succeeds() external {\n address guardian = op.GUARDIAN();\n\n vm.prank(guardian);\n op.pause();\n assertEq(op.paused(), true);\n\n vm.expectEmit(true, true, true, true, address(op));\n emit Unpaused(guardian);\n vm.prank(guardian);\n op.unpause();\n\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal reverts when an account that is not\n * the GUARDIAN calls `unpause()`\n */\n function test_unpause_onlyGuardian_reverts() external {\n address guardian = op.GUARDIAN();\n\n vm.prank(guardian);\n op.pause();\n assertEq(op.paused(), true);\n\n assertTrue(op.GUARDIAN() != alice);\n vm.expectRevert(\"OptimismPortal: only guardian can unpause\");\n vm.prank(alice);\n op.unpause();\n\n assertEq(op.paused(), true);\n }\n\n function test_receive_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(alice, alice, 100, 100, 100_000, false, hex\"\");\n\n // give alice money and send as an eoa\n vm.deal(alice, 2**64);\n vm.prank(alice, alice);\n (bool s, ) = address(op).call{ value: 100 }(hex\"\");\n\n assert(s);\n assertEq(address(op).balance, 100);\n }\n\n // Test: depositTransaction fails when contract creation has a non-zero destination address\n function test_depositTransaction_contractCreation_reverts() external {\n // contract creation must have a target of address(0)\n vm.expectRevert(\"OptimismPortal: must send to address(0) when creating a contract\");\n op.depositTransaction(address(1), 1, 0, true, hex\"\");\n }\n\n /**\n * @notice Prevent gasless deposits from being force processed in L2 by\n * ensuring that they have a large enough gas limit set.\n */\n function test_depositTransaction_smallGasLimit_reverts() external {\n vm.expectRevert(\"OptimismPortal: gas limit must cover instrinsic gas cost\");\n op.depositTransaction({\n _to: address(1),\n _value: 0,\n _gasLimit: 0,\n _isCreation: false,\n _data: hex\"\"\n });\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value\n function test_depositTransaction_noValueEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value\n function test_depositTransaction_noValueContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndContractContractCreation_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n function test_simple_isOutputFinalized_succeeds() external {\n uint256 ts = block.timestamp;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(bytes32(uint256(1)), uint128(ts), uint128(startingBlockNumber))\n )\n );\n\n // warp to the finalization period\n vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS());\n assertEq(op.isOutputFinalized(0), false);\n\n // warp past the finalization period\n vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n assertEq(op.isOutputFinalized(0), true);\n }\n\n function test_isOutputFinalized_succeeds() external {\n uint256 checkpoint = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n vm.roll(checkpoint);\n vm.warp(oracle.computeL2Timestamp(checkpoint) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(keccak256(abi.encode(2)), checkpoint, 0, 0);\n\n // warp to the final second of the finalization period\n uint256 finalizationHorizon = block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS();\n vm.warp(finalizationHorizon);\n // The checkpointed block should not be finalized until 1 second from now.\n assertEq(op.isOutputFinalized(nextOutputIndex), false);\n // Nor should a block after it\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n\n // warp past the finalization period\n vm.warp(finalizationHorizon + 1);\n // It should now be finalized.\n assertEq(op.isOutputFinalized(nextOutputIndex), true);\n // But not the block after it.\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n }\n}\n\ncontract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n // Utility function used in the subsequent test. This is necessary to assert that the\n // reentrant call will revert.\n function callPortalAndExpectRevert() external payable {\n vm.expectRevert(\"OptimismPortal: can only trigger one withdrawal per transaction\");\n // Arguments here don't matter, as the require check is the first thing that happens.\n // We assume that this has already been proven.\n op.finalizeWithdrawalTransaction(_defaultTx);\n // Assert that the withdrawal was not finalized.\n assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx)));\n }\n\n /**\n * @notice Proving withdrawal transactions should revert when paused\n */\n function test_proveWithdrawalTransaction_paused_reverts() external {\n vm.prank(op.GUARDIAN());\n op.pause();\n\n vm.expectRevert(\"OptimismPortal: paused\");\n op.proveWithdrawalTransaction({\n _tx: _defaultTx,\n _l2OutputIndex: _proposedOutputIndex,\n _outputRootProof: _outputRootProof,\n _withdrawalProof: _withdrawalProof\n });\n }\n\n // Test: proveWithdrawalTransaction cannot prove a withdrawal with itself (the OptimismPortal) as the target.\n function test_proveWithdrawalTransaction_onSelfCall_reverts() external {\n _defaultTx.target = address(op);\n vm.expectRevert(\"OptimismPortal: you cannot send messages to the portal contract\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the outputRootProof does not match the output root\n function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external {\n // Modify the version to invalidate the withdrawal proof.\n _outputRootProof.version = bytes32(uint256(1));\n vm.expectRevert(\"OptimismPortal: invalid output root proof\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the proof is invalid due to non-existence of\n // the withdrawal.\n function test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() external {\n // modify the default test values to invalidate the proof.\n _defaultTx.data = hex\"abcd\";\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the passed transaction's withdrawalHash has\n // already been proven.\n function test_proveWithdrawalTransaction_replayProve_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: withdrawal hash has already been proven\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has\n // already been proven AND the output root has changed AND the l2BlockNumber stays the same.\n function test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`\n // inside of the `provenWithdrawal`s mapping.\n bytes32 slot;\n assembly {\n mstore(0x00, sload(_withdrawalHash.slot))\n mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in the OptimismPortal\n slot := keccak256(0x00, 0x40)\n }\n\n // Store a different output root within the `provenWithdrawals` mapping without\n // touching the l2BlockNumber or timestamp.\n vm.store(address(op), slot, bytes32(0));\n\n // Warp ahead 1 second\n vm.warp(block.timestamp + 1);\n\n // Even though we have already proven this withdrawalHash, we should be allowed to re-submit\n // our proof with a changed outputRoot\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Ensure that the withdrawal was updated within the mapping\n (, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);\n assertEq(timestamp, block.timestamp);\n }\n\n // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has\n // already been proven AND the output root + output index + l2BlockNumber changes.\n function test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds()\n external\n {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`\n // inside of the `provenWithdrawal`s mapping.\n bytes32 slot;\n assembly {\n mstore(0x00, sload(_withdrawalHash.slot))\n mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in OptimismPortal\n slot := keccak256(0x00, 0x40)\n }\n\n // Store a dummy output root within the `provenWithdrawals` mapping without touching the\n // l2BlockNumber or timestamp.\n vm.store(address(op), slot, bytes32(0));\n\n // Fetch the output proposal at `_proposedOutputIndex` from the L2OutputOracle\n Types.OutputProposal memory proposal = op.L2_ORACLE().getL2Output(_proposedOutputIndex);\n\n // Propose the same output root again, creating the same output at a different index + l2BlockNumber.\n vm.startPrank(op.L2_ORACLE().PROPOSER());\n op.L2_ORACLE().proposeL2Output(\n proposal.outputRoot,\n op.L2_ORACLE().nextBlockNumber(),\n blockhash(block.number),\n block.number\n );\n vm.stopPrank();\n\n // Warp ahead 1 second\n vm.warp(block.timestamp + 1);\n\n // Even though we have already proven this withdrawalHash, we should be allowed to re-submit\n // our proof with a changed outputRoot + a different output index\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex + 1,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Ensure that the withdrawal was updated within the mapping\n (, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);\n assertEq(timestamp, block.timestamp);\n }\n\n // Test: proveWithdrawalTransaction succeeds and emits the WithdrawalProven event.\n function test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: finalizeWithdrawalTransaction succeeds and emits the WithdrawalFinalized event.\n function test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, false, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore + 100);\n }\n\n /**\n * @notice Finalizing withdrawal transactions should revert when paused\n */\n function test_finalizeWithdrawalTransaction_paused_reverts() external {\n vm.prank(op.GUARDIAN());\n op.pause();\n\n vm.expectRevert(\"OptimismPortal: paused\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has not been proven.\n function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectRevert(\"OptimismPortal: withdrawal has not been proven yet\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if withdrawal not proven long enough ago.\n function test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Mock a call where the resulting output root is anything but the original output root. In\n // this case we just use bytes32(uint256(1)).\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(bytes32(uint256(1)), _proposedBlockNumber)\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the provenWithdrawal's timestamp is less\n // than the L2 output oracle's starting timestamp\n function test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a startingTimestamp change on the L2 Oracle\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSignature(\"startingTimestamp()\"),\n abi.encode(block.timestamp + 1)\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output root proven is not the same as the\n // output root at the time of finalization.\n function test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock an outputRoot change on the output proposal before attempting\n // to finalize the withdrawal.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n bytes32(uint256(0)),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output proposal's timestamp has\n // not passed the finalization period.\n function test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a timestamp change on the output proposal that has not passed the\n // finalization period.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(block.timestamp + 1),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\"OptimismPortal: output proposal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction fails because the target reverts,\n // and emits the WithdrawalFinalized event with success=false.\n function test_finalizeWithdrawalTransaction_targetFails_fails() external {\n uint256 bobBalanceBefore = address(bob).balance;\n vm.etch(bob, hex\"fe\"); // Contract with just the invalid opcode.\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, false);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the finalization period has not yet passed.\n function test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() external {\n // Setup the Oracle to return an output with a recent timestamp\n uint256 recentTimestamp = block.timestamp - 1000;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(recentTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has already been finalized.\n function test_finalizeWithdrawalTransaction_onReplay_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if insufficient gas is supplied.\n function test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() external {\n // This number was identified through trial and error.\n uint256 gasLimit = 150_000;\n Types.WithdrawalTransaction memory insufficientGasTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: gasLimit,\n data: hex\"\"\n });\n\n // Get updated proof inputs.\n (bytes32 stateRoot, bytes32 storageRoot, , , bytes[] memory withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(insufficientGasTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n Hashing.hashOutputRootProof(outputRootProof),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n insufficientGasTx,\n _proposedOutputIndex,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectRevert(\"SafeCall: Not enough gas\");\n op.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if a sub-call attempts to finalize another\n // withdrawal.\n function test_finalizeWithdrawalTransaction_onReentrancy_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Copy and modify the default test values to attempt a reentrant call by first calling to\n // this contract's callPortalAndExpectRevert() function above.\n Types.WithdrawalTransaction memory _testTx = _defaultTx;\n _testTx.target = address(this);\n _testTx.data = abi.encodeWithSelector(this.callPortalAndExpectRevert.selector);\n\n // Get modified proof inputs.\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_testTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n // Setup the Oracle to return the outputRoot we want as well as a finalized timestamp.\n uint256 finalizedTimestamp = block.timestamp - oracle.FINALIZATION_PERIOD_SECONDS() - 1;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n outputRoot,\n uint128(finalizedTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(withdrawalHash, alice, address(this));\n op.proveWithdrawalTransaction(\n _testTx,\n _proposedBlockNumber,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectCall(address(this), _testTx.data);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_testTx);\n\n // Ensure that bob's balance was not changed by the reentrant call.\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n function testDiff_finalizeWithdrawalTransaction_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n // Cannot call the optimism portal\n vm.assume(_target != address(op));\n // Total ETH supply is currently about 120M ETH.\n uint256 value = bound(_value, 0, 200_000_000 ether);\n uint256 gasLimit = bound(_gasLimit, 0, 50_000_000);\n uint256 nonce = messagePasser.messageNonce();\n Types.WithdrawalTransaction memory _tx = Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: value,\n gasLimit: gasLimit,\n data: _data\n });\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_tx);\n\n Types.OutputRootProof memory proof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n\n // Ensure the values returned from ffi are correct\n assertEq(outputRoot, Hashing.hashOutputRootProof(proof));\n assertEq(withdrawalHash, Hashing.hashWithdrawal(_tx));\n\n // Mock the call to the oracle\n vm.mockCall(\n address(oracle),\n abi.encodeWithSelector(oracle.getL2Output.selector),\n abi.encode(outputRoot, 0)\n );\n\n // Start the withdrawal, it must be initiated by the _sender and the\n // correct value must be passed along\n vm.deal(_tx.sender, _tx.value);\n vm.prank(_tx.sender);\n messagePasser.initiateWithdrawal{ value: _tx.value }(_tx.target, _tx.gasLimit, _tx.data);\n\n // Ensure that the sentMessages is correct\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n op.proveWithdrawalTransaction(\n _tx,\n 100, // l2BlockNumber\n proof,\n withdrawalProof\n );\n }\n}\n\ncontract OptimismPortalUpgradeable_Test is Portal_Initializer {\n Proxy internal proxy;\n uint64 initialBlockNum;\n\n function setUp() public override {\n super.setUp();\n initialBlockNum = uint64(block.number);\n proxy = Proxy(payable(address(op)));\n }\n\n function test_params_initValuesOnProxy_succeeds() external {\n OptimismPortal p = OptimismPortal(payable(address(proxy)));\n\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = p.params();\n\n ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig();\n assertEq(prevBaseFee, rcfg.minimumBaseFee);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_initialize_cannotInitProxy_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(payable(proxy)).initialize(false);\n }\n\n function test_initialize_cannotInitImpl_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(opImpl).initialize(false);\n }\n\n function test_upgradeToAndCall_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(op), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(op), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(op)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n" - }, - "contracts/test/Proxy.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract SimpleStorage {\n mapping(uint256 => uint256) internal store;\n\n function get(uint256 key) external payable returns (uint256) {\n return store[key];\n }\n\n function set(uint256 key, uint256 value) external payable {\n store[key] = value;\n }\n}\n\ncontract Clasher {\n function upgradeTo(address) external pure {\n revert(\"upgradeTo\");\n }\n}\n\ncontract Proxy_Test is Test {\n event Upgraded(address indexed implementation);\n event AdminChanged(address previousAdmin, address newAdmin);\n\n address alice = address(64);\n\n bytes32 internal constant IMPLEMENTATION_KEY =\n bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1);\n\n bytes32 internal constant OWNER_KEY = bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1);\n\n Proxy proxy;\n SimpleStorage simpleStorage;\n\n function setUp() external {\n // Deploy a proxy and simple storage contract as\n // the implementation\n proxy = new Proxy(alice);\n simpleStorage = new SimpleStorage();\n\n vm.prank(alice);\n proxy.upgradeTo(address(simpleStorage));\n }\n\n function test_implementationKey_succeeds() external {\n // The hardcoded implementation key should be correct\n vm.prank(alice);\n proxy.upgradeTo(address(6));\n\n bytes32 key = vm.load(address(proxy), IMPLEMENTATION_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(6));\n }\n\n function test_ownerKey_succeeds() external {\n // The hardcoded owner key should be correct\n vm.prank(alice);\n proxy.changeAdmin(address(6));\n\n bytes32 key = vm.load(address(proxy), OWNER_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(address(6));\n address owner = proxy.admin();\n assertEq(owner, address(6));\n }\n\n function test_proxyCallToImp_notAdmin_succeeds() external {\n // The implementation does not have a `upgradeTo`\n // method, calling `upgradeTo` not as the owner\n // should revert.\n vm.expectRevert();\n proxy.upgradeTo(address(64));\n\n // Call `upgradeTo` as the owner, it should succeed\n // and emit the `Upgraded` event.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(64));\n vm.prank(alice);\n proxy.upgradeTo(address(64));\n\n // Get the implementation as the owner\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(64));\n }\n\n function test_ownerProxyCall_notAdmin_succeeds() external {\n // Calling `changeAdmin` not as the owner should revert\n // as the implementation does not have a `changeAdmin` method.\n vm.expectRevert();\n proxy.changeAdmin(address(1));\n\n // Call `changeAdmin` as the owner, it should succeed\n // and emit the `AdminChanged` event.\n vm.expectEmit(true, true, true, true);\n emit AdminChanged(alice, address(1));\n vm.prank(alice);\n proxy.changeAdmin(address(1));\n\n // Calling `admin` not as the owner should\n // revert as the implementation does not have\n // a `admin` method.\n vm.expectRevert();\n proxy.admin();\n\n // Calling `admin` as the owner should work.\n vm.prank(address(1));\n address owner = proxy.admin();\n assertEq(owner, address(1));\n }\n\n function test_delegatesToImpl_succeeds() external {\n // Call the storage setter on the proxy\n SimpleStorage(address(proxy)).set(1, 1);\n\n // The key should not be set in the implementation\n uint256 result = simpleStorage.get(1);\n assertEq(result, 0);\n {\n // The key should be set in the proxy\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n\n {\n // The owner should be able to call through the proxy\n // when there is not a function selector crash\n vm.prank(alice);\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n }\n\n function test_upgradeToAndCall_succeeds() external {\n {\n // There should be nothing in the current proxy storage\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 0);\n }\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(simpleStorage));\n vm.prank(alice);\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The call should have impacted the state\n uint256 result = SimpleStorage(address(proxy)).get(1);\n assertEq(result, 1);\n }\n\n function test_upgradeToAndCall_functionDoesNotExist_reverts() external {\n // Get the current implementation address\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call. This reverts because the calldata doesn't\n // match a function on the implementation.\n vm.expectRevert(\"Proxy: delegatecall to new implementation contract failed\");\n vm.prank(alice);\n proxy.upgradeToAndCall(address(simpleStorage), hex\"\");\n\n // The implementation address should have not\n // updated because the call to `upgradeToAndCall`\n // reverted.\n vm.prank(alice);\n address postImpl = proxy.implementation();\n assertEq(impl, postImpl);\n\n // The attempt to `upgradeToAndCall`\n // should revert when it is not called by the owner.\n vm.expectRevert();\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n }\n\n function test_upgradeToAndCall_isPayable_succeeds() external {\n // Give alice some funds\n vm.deal(alice, 1 ether);\n // Set the implementation and call and send\n // value.\n vm.prank(alice);\n proxy.upgradeToAndCall{ value: 1 ether }(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The implementation address should be correct\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // The proxy should have a balance\n assertEq(address(proxy).balance, 1 ether);\n }\n\n function test_upgradeTo_clashingFunctionSignatures_succeeds() external {\n // Clasher has a clashing function with the proxy.\n Clasher clasher = new Clasher();\n\n // Set the clasher as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(clasher));\n\n {\n // Assert that the implementation was set properly.\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(clasher));\n }\n\n // Call the clashing function on the proxy\n // not as the owner so that the call passes through.\n // The implementation will revert so we can be\n // sure that the call passed through.\n vm.expectRevert(bytes(\"upgradeTo\"));\n proxy.upgradeTo(address(0));\n\n {\n // Now call the clashing function as the owner\n // and be sure that it doesn't pass through to\n // the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(0));\n }\n }\n\n // Allow for `eth_call` to call proxy methods\n // by setting \"from\" to `address(0)`.\n function test_implementation_zeroAddressCaller_succeeds() external {\n vm.prank(address(0));\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n }\n\n function test_implementation_isZeroAddress_reverts() external {\n // Set `address(0)` as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n\n (bool success, bytes memory returndata) = address(proxy).call(hex\"\");\n assertEq(success, false);\n\n bytes memory err = abi.encodeWithSignature(\n \"Error(string)\",\n \"Proxy: implementation not initialized\"\n );\n\n assertEq(returndata, err);\n }\n}\n" - }, - "contracts/test/ProxyAdmin.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { SimpleStorage } from \"./Proxy.t.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\n\ncontract ProxyAdmin_Test is Test {\n address alice = address(64);\n\n Proxy proxy;\n L1ChugSplashProxy chugsplash;\n ResolvedDelegateProxy resolved;\n\n AddressManager addressManager;\n\n ProxyAdmin admin;\n\n SimpleStorage implementation;\n\n function setUp() external {\n // Deploy the proxy admin\n admin = new ProxyAdmin(alice);\n // Deploy the standard proxy\n proxy = new Proxy(address(admin));\n\n // Deploy the legacy L1ChugSplashProxy with the admin as the owner\n chugsplash = new L1ChugSplashProxy(address(admin));\n\n // Deploy the legacy AddressManager\n addressManager = new AddressManager();\n // The proxy admin must be the new owner of the address manager\n addressManager.transferOwnership(address(admin));\n // Deploy a legacy ResolvedDelegateProxy with the name `a`.\n // Whatever `a` is set to in AddressManager will be the address\n // that is used for the implementation.\n resolved = new ResolvedDelegateProxy(addressManager, \"a\");\n\n // Impersonate alice for setting up the admin.\n vm.startPrank(alice);\n // Set the address of the address manager in the admin so that it\n // can resolve the implementation address of legacy\n // ResolvedDelegateProxy based proxies.\n admin.setAddressManager(addressManager);\n // Set the reverse lookup of the ResolvedDelegateProxy\n // proxy\n admin.setImplementationName(address(resolved), \"a\");\n\n // Set the proxy types\n admin.setProxyType(address(proxy), ProxyAdmin.ProxyType.ERC1967);\n admin.setProxyType(address(chugsplash), ProxyAdmin.ProxyType.CHUGSPLASH);\n admin.setProxyType(address(resolved), ProxyAdmin.ProxyType.RESOLVED);\n vm.stopPrank();\n\n implementation = new SimpleStorage();\n }\n\n function test_setImplementationName_succeeds() external {\n vm.prank(alice);\n admin.setImplementationName(address(1), \"foo\");\n assertEq(admin.implementationName(address(1)), \"foo\");\n }\n\n function test_setAddressManager_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setAddressManager(AddressManager((address(0))));\n }\n\n function test_setImplementationName_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setImplementationName(address(0), \"foo\");\n }\n\n function test_setProxyType_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setProxyType(address(0), ProxyAdmin.ProxyType.CHUGSPLASH);\n }\n\n function test_owner_succeeds() external {\n assertEq(admin.owner(), alice);\n }\n\n function test_proxyType_succeeds() external {\n assertEq(uint256(admin.proxyType(address(proxy))), uint256(ProxyAdmin.ProxyType.ERC1967));\n assertEq(\n uint256(admin.proxyType(address(chugsplash))),\n uint256(ProxyAdmin.ProxyType.CHUGSPLASH)\n );\n assertEq(\n uint256(admin.proxyType(address(resolved))),\n uint256(ProxyAdmin.ProxyType.RESOLVED)\n );\n }\n\n function test_erc1967GetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(proxy));\n }\n\n function test_chugsplashGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(resolved));\n }\n\n function getProxyImplementation(address payable _proxy) internal {\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(0));\n }\n\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n }\n\n function test_erc1967GetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(resolved));\n }\n\n function getProxyAdmin(address payable _proxy) internal {\n address owner = admin.getProxyAdmin(_proxy);\n assertEq(owner, address(admin));\n }\n\n function test_erc1967ChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(resolved));\n }\n\n function changeProxyAdmin(address payable _proxy) internal {\n ProxyAdmin.ProxyType proxyType = admin.proxyType(address(_proxy));\n\n vm.prank(alice);\n admin.changeProxyAdmin(_proxy, address(128));\n\n // The proxy is no longer the admin and can\n // no longer call the proxy interface except for\n // the ResolvedDelegate type on which anybody can\n // call the admin interface.\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n vm.expectRevert(\"Proxy: implementation not initialized\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n vm.expectRevert(\"L1ChugSplashProxy: implementation is not set yet\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n // Just an empty block to show that all cases are covered\n } else {\n vm.expectRevert(\"ProxyAdmin: unknown proxy type\");\n }\n\n // Call the proxy contract directly to get the admin.\n // Different proxy types have different interfaces.\n vm.prank(address(128));\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n assertEq(Proxy(payable(_proxy)).admin(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n assertEq(L1ChugSplashProxy(payable(_proxy)).getOwner(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n assertEq(addressManager.owner(), address(128));\n } else {\n assert(false);\n }\n }\n\n function test_erc1967Upgrade_succeeds() external {\n upgrade(payable(proxy));\n }\n\n function test_chugsplashUpgrade_succeeds() external {\n upgrade(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgrade_succeeds() external {\n upgrade(payable(resolved));\n }\n\n function upgrade(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n\n function test_erc1967UpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(proxy));\n }\n\n function test_chugsplashUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(resolved));\n }\n\n function upgradeAndCall(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgradeAndCall(\n _proxy,\n address(implementation),\n abi.encodeWithSelector(SimpleStorage.set.selector, 1, 1)\n );\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n\n uint256 got = SimpleStorage(address(_proxy)).get(1);\n assertEq(got, 1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.changeProxyAdmin(payable(proxy), address(0));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgrade(payable(proxy), address(implementation));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgradeAndCall(payable(proxy), address(implementation), hex\"\");\n }\n\n function test_isUpgrading_succeeds() external {\n assertEq(false, admin.isUpgrading());\n\n vm.prank(alice);\n admin.setUpgrading(true);\n assertEq(true, admin.isUpgrading());\n }\n}\n" - }, - "contracts/test/RLP.t.sol": { - "content": "// SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\n/**\n * @title LibRLP\n * @notice Via https://github.com/Rari-Capital/solmate/issues/207.\n */\nlibrary LibRLP {\n using Bytes32AddressLib for bytes32;\n\n function computeAddress(address deployer, uint256 nonce) internal pure returns (address) {\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80)))\n .fromLast20Bytes();\n if (nonce <= 0x7f)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce)))\n .fromLast20Bytes();\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= type(uint8).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd7),\n bytes1(0x94),\n deployer,\n bytes1(0x81),\n uint8(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint16).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd8),\n bytes1(0x94),\n deployer,\n bytes1(0x82),\n uint16(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint24).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd9),\n bytes1(0x94),\n deployer,\n bytes1(0x83),\n uint24(nonce)\n )\n ).fromLast20Bytes();\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return\n keccak256(\n abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))\n ).fromLast20Bytes();\n }\n}\n" - }, - "contracts/test/RLPReader.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { RLPReader } from \"../libraries/rlp/RLPReader.sol\";\n\ncontract RLPReader_readBytes_Test is CommonTest {\n function test_readBytes_bytestring00_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"00\"), hex\"00\");\n }\n\n function test_readBytes_bytestring01_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"01\"), hex\"01\");\n }\n\n function test_readBytes_bytestring7f_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"7f\"), hex\"7f\");\n }\n\n function test_readBytes_revertListItem_reverts() external {\n vm.expectRevert(\"RLPReader: decoded item type for bytes is not a data item\");\n RLPReader.readBytes(hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_readBytes_invalidStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n RLPReader.readBytes(hex\"b9\");\n }\n\n function test_readBytes_invalidListLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n RLPReader.readBytes(hex\"ff\");\n }\n\n function test_readBytes_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: bytes value contains an invalid remainder\");\n RLPReader.readBytes(hex\"800a\");\n }\n\n function test_readBytes_invalidPrefix_reverts() external {\n vm.expectRevert(\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n RLPReader.readBytes(hex\"810a\");\n }\n}\n\ncontract RLPReader_readList_Test is CommonTest {\n function test_readList_empty_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c0\");\n assertEq(list.length, 0);\n }\n\n function test_readList_multiList_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c6827a77c10401\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"827a77\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c104\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"01\");\n }\n\n function test_readList_shortListMax1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n\n assertEq(list.length, 11);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[4]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[5]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[6]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[7]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[8]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[9]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[10]), hex\"8471776572\");\n }\n\n function test_readList_longList1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n\n assertEq(list.length, 4);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"cf84617364668471776572847a786376\");\n }\n\n function test_readList_longList2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n assertEq(list.length, 32);\n\n for (uint256 i = 0; i < 32; i++) {\n assertEq(RLPReader.readRawBytes(list[i]), hex\"cf84617364668471776572847a786376\");\n }\n }\n\n function test_readList_listLongerThan32Elements_reverts() external {\n vm.expectRevert(stdError.indexOOBError);\n RLPReader.readList(\n hex\"e1454545454545454545454545454545454545454545454545454545454545454545\"\n );\n }\n\n function test_readList_listOfLists_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c4c2c0c0c0\");\n assertEq(list.length, 2);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c2c0c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c0\");\n }\n\n function test_readList_listOfLists2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c7c0c1c0c3c0c1c0\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c1c0\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"c3c0c1c0\");\n }\n\n function test_readList_dictTest1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n assertEq(list.length, 4);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"ca846b6579318476616c31\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"ca846b6579328476616c32\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"ca846b6579338476616c33\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"ca846b6579348476616c34\");\n }\n\n function test_readList_invalidShortList_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efdebd\");\n }\n\n function test_readList_longStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efb83600\");\n }\n\n function test_readList_notLongEnough_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(\n hex\"efdebdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n );\n }\n\n function test_readList_int32Overflow_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"bf0f000000000000021111\");\n }\n\n function test_readList_int32Overflow2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ff0f000000000000021111\");\n }\n\n function test_readList_incorrectLengthInArray_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b9002100dc2b275d0f74e8a53e6f4ec61b27f24278820be3f82ea2110e582081b0565df0\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b90040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(hex\"b800\");\n }\n\n function test_readList_leadingZerosInLongLengthList1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must not have any leading zeros (long list)\");\n RLPReader.readList(\n hex\"fb00000040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_nonOptimalLongLengthArray1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b81000112233445566778899aabbccddeeff\");\n }\n\n function test_readList_nonOptimalLongLengthArray2_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b801ff\");\n }\n\n function test_readList_invalidValue_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n RLPReader.readList(hex\"91\");\n }\n\n function test_readList_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n RLPReader.readList(hex\"c000\");\n }\n\n function test_readList_notEnoughContentForString1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"ba010000aabbccddeeff\");\n }\n\n function test_readList_notEnoughContentForString2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"b840ffeeddccbbaa99887766554433221100\");\n }\n\n function test_readList_notEnoughContentForList1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"f90180\");\n }\n\n function test_readList_notEnoughContentForList2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ffffffffffffffffff0001020304050607\");\n }\n\n function test_readList_longStringLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b80100\");\n }\n\n function test_readList_longListLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long list)\");\n RLPReader.readList(hex\"f80100\");\n }\n}\n" - }, - "contracts/test/RLPWriter.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { RLPWriter } from \"../libraries/rlp/RLPWriter.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\n\ncontract RLPWriter_writeString_Test is CommonTest {\n function test_writeString_empty_succeeds() external {\n assertEq(RLPWriter.writeString(\"\"), hex\"80\");\n }\n\n function test_writeString_bytestring00_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0000\"), hex\"00\");\n }\n\n function test_writeString_bytestring01_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0001\"), hex\"01\");\n }\n\n function test_writeString_bytestring7f_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u007F\"), hex\"7f\");\n }\n\n function test_writeString_shortstring_succeeds() external {\n assertEq(RLPWriter.writeString(\"dog\"), hex\"83646f67\");\n }\n\n function test_writeString_shortstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing eli\"),\n hex\"b74c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c69\"\n );\n }\n\n function test_writeString_longstring_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing elit\"),\n hex\"b8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974\"\n );\n }\n\n function test_writeString_longstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\n \"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\"\n ),\n hex\"b904004c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20437572616269747572206d6175726973206d61676e612c20737573636970697420736564207665686963756c61206e6f6e2c20696163756c697320666175636962757320746f72746f722e2050726f696e20737573636970697420756c74726963696573206d616c6573756164612e204475697320746f72746f7220656c69742c2064696374756d2071756973207472697374697175652065752c20756c7472696365732061742072697375732e204d6f72626920612065737420696d70657264696574206d6920756c6c616d636f7270657220616c6971756574207375736369706974206e6563206c6f72656d2e2041656e65616e2071756973206c656f206d6f6c6c69732c2076756c70757461746520656c6974207661726975732c20636f6e73657175617420656e696d2e204e756c6c6120756c74726963657320747572706973206a7573746f2c20657420706f73756572652075726e6120636f6e7365637465747572206e65632e2050726f696e206e6f6e20636f6e76616c6c6973206d657475732e20446f6e65632074656d706f7220697073756d20696e206d617572697320636f6e67756520736f6c6c696369747564696e2e20566573746962756c756d20616e746520697073756d207072696d697320696e206661756369627573206f726369206c756374757320657420756c74726963657320706f737565726520637562696c69612043757261653b2053757370656e646973736520636f6e76616c6c69732073656d2076656c206d617373612066617563696275732c2065676574206c6163696e6961206c616375732074656d706f722e204e756c6c61207175697320756c747269636965732070757275732e2050726f696e20617563746f722072686f6e637573206e69626820636f6e64696d656e74756d206d6f6c6c69732e20416c697175616d20636f6e73657175617420656e696d206174206d65747573206c75637475732c206120656c656966656e6420707572757320656765737461732e20437572616269747572206174206e696268206d657475732e204e616d20626962656e64756d2c206e6571756520617420617563746f72207472697374697175652c206c6f72656d206c696265726f20616c697175657420617263752c206e6f6e20696e74657264756d2074656c6c7573206c65637475732073697420616d65742065726f732e20437261732072686f6e6375732c206d65747573206163206f726e617265206375727375732c20646f6c6f72206a7573746f20756c747269636573206d657475732c20617420756c6c616d636f7270657220766f6c7574706174\"\n );\n }\n}\n\ncontract RLPWriter_writeUint_Test is CommonTest {\n function test_writeUint_zero_succeeds() external {\n assertEq(RLPWriter.writeUint(0x0), hex\"80\");\n }\n\n function test_writeUint_smallint_succeeds() external {\n assertEq(RLPWriter.writeUint(1), hex\"01\");\n }\n\n function test_writeUint_smallint2_succeeds() external {\n assertEq(RLPWriter.writeUint(16), hex\"10\");\n }\n\n function test_writeUint_smallint3_succeeds() external {\n assertEq(RLPWriter.writeUint(79), hex\"4f\");\n }\n\n function test_writeUint_smallint4_succeeds() external {\n assertEq(RLPWriter.writeUint(127), hex\"7f\");\n }\n\n function test_writeUint_mediumint_succeeds() external {\n assertEq(RLPWriter.writeUint(128), hex\"8180\");\n }\n\n function test_writeUint_mediumint2_succeeds() external {\n assertEq(RLPWriter.writeUint(1000), hex\"8203e8\");\n }\n\n function test_writeUint_mediumint3_succeeds() external {\n assertEq(RLPWriter.writeUint(100000), hex\"830186a0\");\n }\n}\n\ncontract RLPWriter_writeList_Test is CommonTest {\n function test_writeList_empty_succeeds() external {\n assertEq(RLPWriter.writeList(new bytes[](0)), hex\"c0\");\n }\n\n function test_writeList_stringList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeString(\"dog\");\n list[1] = RLPWriter.writeString(\"god\");\n list[2] = RLPWriter.writeString(\"cat\");\n\n assertEq(RLPWriter.writeList(list), hex\"cc83646f6783676f6483636174\");\n }\n\n function test_writeList_multiList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeUint(4);\n\n list[0] = RLPWriter.writeString(\"zw\");\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeUint(1);\n\n assertEq(RLPWriter.writeList(list), hex\"c6827a77c10401\");\n }\n\n function test_writeList_shortListMax1_succeeds() external {\n bytes[] memory list = new bytes[](11);\n list[0] = RLPWriter.writeString(\"asdf\");\n list[1] = RLPWriter.writeString(\"qwer\");\n list[2] = RLPWriter.writeString(\"zxcv\");\n list[3] = RLPWriter.writeString(\"asdf\");\n list[4] = RLPWriter.writeString(\"qwer\");\n list[5] = RLPWriter.writeString(\"zxcv\");\n list[6] = RLPWriter.writeString(\"asdf\");\n list[7] = RLPWriter.writeString(\"qwer\");\n list[8] = RLPWriter.writeString(\"zxcv\");\n list[9] = RLPWriter.writeString(\"asdf\");\n list[10] = RLPWriter.writeString(\"qwer\");\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n }\n\n function test_writeList_longlist1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list2);\n list[3] = RLPWriter.writeList(list2);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_longlist2_succeeds() external {\n bytes[] memory list = new bytes[](32);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n for (uint256 i = 0; i < 32; i++) {\n list[i] = RLPWriter.writeList(list2);\n }\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_listoflists_succeeds() external {\n // [ [ [], [] ], [] ]\n bytes[] memory list = new bytes[](2);\n bytes[] memory list2 = new bytes[](2);\n\n list2[0] = RLPWriter.writeList(new bytes[](0));\n list2[1] = RLPWriter.writeList(new bytes[](0));\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(new bytes[](0));\n\n assertEq(RLPWriter.writeList(list), hex\"c4c2c0c0c0\");\n }\n\n function test_writeList_listoflists2_succeeds() external {\n // [ [], [[]], [ [], [[]] ] ]\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeList(new bytes[](0));\n\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeList(new bytes[](0));\n\n list[1] = RLPWriter.writeList(list2);\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeList(new bytes[](0));\n list3[1] = RLPWriter.writeList(list2);\n\n list[2] = RLPWriter.writeList(list3);\n\n assertEq(RLPWriter.writeList(list), hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_writeList_dictTest1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n\n bytes[] memory list1 = new bytes[](2);\n list1[0] = RLPWriter.writeString(\"key1\");\n list1[1] = RLPWriter.writeString(\"val1\");\n\n bytes[] memory list2 = new bytes[](2);\n list2[0] = RLPWriter.writeString(\"key2\");\n list2[1] = RLPWriter.writeString(\"val2\");\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeString(\"key3\");\n list3[1] = RLPWriter.writeString(\"val3\");\n\n bytes[] memory list4 = new bytes[](2);\n list4[0] = RLPWriter.writeString(\"key4\");\n list4[1] = RLPWriter.writeString(\"val4\");\n\n list[0] = RLPWriter.writeList(list1);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list3);\n list[3] = RLPWriter.writeList(list4);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n }\n}\n" - }, - "contracts/test/ResolvedDelegateProxy.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\n\ncontract ResolvedDelegateProxy_Test is Test {\n AddressManager internal addressManager;\n SimpleImplementation internal impl;\n SimpleImplementation internal proxy;\n\n function setUp() public {\n // Set up the address manager.\n addressManager = new AddressManager();\n impl = new SimpleImplementation();\n addressManager.setAddress(\"SimpleImplementation\", address(impl));\n\n // Set up the proxy.\n proxy = SimpleImplementation(\n address(new ResolvedDelegateProxy(addressManager, \"SimpleImplementation\"))\n );\n }\n\n // Tests that the proxy properly bubbles up returndata when the delegatecall succeeds.\n function testFuzz_fallback_delegateCallFoo_succeeds(uint256 x) public {\n vm.expectCall(address(impl), abi.encodeWithSelector(impl.foo.selector, x));\n assertEq(proxy.foo(x), x);\n }\n\n // Tests that the proxy properly bubbles up returndata when the delegatecall reverts.\n function test_fallback_delegateCallBar_reverts() public {\n vm.expectRevert(\"SimpleImplementation: revert\");\n vm.expectCall(address(impl), abi.encodeWithSelector(impl.bar.selector));\n proxy.bar();\n }\n\n // Tests that the proxy fallback reverts as expected if the implementation within the\n // address manager is not set.\n function test_fallback_addressManagerNotSet_reverts() public {\n AddressManager am = new AddressManager();\n SimpleImplementation p = SimpleImplementation(\n address(new ResolvedDelegateProxy(am, \"SimpleImplementation\"))\n );\n\n vm.expectRevert(\"ResolvedDelegateProxy: target address must be initialized\");\n p.foo(0);\n }\n}\n\ncontract SimpleImplementation {\n function foo(uint256 _x) public pure returns (uint256) {\n return _x;\n }\n\n function bar() public pure {\n revert(\"SimpleImplementation: revert\");\n }\n}\n" - }, - "contracts/test/ResourceMetering.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract MeterUser is ResourceMetering {\n constructor() {\n initialize();\n }\n\n function initialize() public initializer {\n __ResourceMetering_init();\n }\n\n function resourceConfig() public pure returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig();\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return Constants.DEFAULT_RESOURCE_CONFIG();\n }\n\n function use(uint64 _amount) public metered(_amount) {}\n\n function set(\n uint128 _prevBaseFee,\n uint64 _prevBoughtGas,\n uint64 _prevBlockNum\n ) public {\n params = ResourceMetering.ResourceParams({\n prevBaseFee: _prevBaseFee,\n prevBoughtGas: _prevBoughtGas,\n prevBlockNum: _prevBlockNum\n });\n }\n}\n\n/**\n * @title ResourceConfig\n * @notice The tests are based on the default config values. It is expected that\n * the config values used in these tests are ran in production.\n */\ncontract ResourceMetering_Test is Test {\n MeterUser internal meter;\n uint64 initialBlockNum;\n\n function setUp() public {\n meter = new MeterUser();\n initialBlockNum = uint64(block.number);\n }\n\n function test_meter_initialResourceParams_succeeds() external {\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n\n assertEq(prevBaseFee, rcfg.minimumBaseFee);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_updateParamsNoChange_succeeds() external {\n meter.use(0); // equivalent to just updating the base fee and block number\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n meter.use(0);\n (uint128 postBaseFee, uint64 postBoughtGas, uint64 postBlockNum) = meter.params();\n\n assertEq(postBaseFee, prevBaseFee);\n assertEq(postBoughtGas, prevBoughtGas);\n assertEq(postBlockNum, prevBlockNum);\n }\n\n function test_meter_updateOneEmptyBlock_succeeds() external {\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 1);\n }\n\n function test_meter_updateTwoEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 2);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 2);\n }\n\n function test_meter_updateTenEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 10);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 10);\n }\n\n function test_meter_updateNoGasDelta_succeeds() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint256 target = uint256(rcfg.maxResourceLimit) / uint256(rcfg.elasticityMultiplier);\n meter.use(uint64(target));\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1000000000);\n assertEq(prevBoughtGas, target);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_useMax_succeeds() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n meter.use(target * elasticityMultiplier);\n\n (, uint64 prevBoughtGas, ) = meter.params();\n assertEq(prevBoughtGas, target * elasticityMultiplier);\n\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 postBaseFee, , ) = meter.params();\n assertEq(postBaseFee, 2125000000);\n }\n\n function test_meter_useMoreThanMax_reverts() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n vm.expectRevert(\"ResourceMetering: cannot buy more gas than available gas limit\");\n meter.use(target * elasticityMultiplier + 1);\n }\n\n // Demonstrates that the resource metering arithmetic can tolerate very large gaps between\n // deposits.\n function testFuzz_meter_largeBlockDiff_succeeds(uint64 _amount, uint256 _blockDiff) external {\n // This test fails if the following line is commented out.\n // At 12 seconds per block, this number is effectively unreachable.\n vm.assume(_blockDiff < 433576281058164217753225238677900874458691);\n\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n vm.assume(_amount < target * elasticityMultiplier);\n vm.roll(initialBlockNum + _blockDiff);\n meter.use(_amount);\n }\n}\n\n/**\n * @title CustomMeterUser\n * @notice A simple wrapper around `ResourceMetering` that allows the initial\n * params to be set in the constructor.\n */\ncontract CustomMeterUser is ResourceMetering {\n uint256 public startGas;\n uint256 public endGas;\n\n constructor(\n uint128 _prevBaseFee,\n uint64 _prevBoughtGas,\n uint64 _prevBlockNum\n ) {\n params = ResourceMetering.ResourceParams({\n prevBaseFee: _prevBaseFee,\n prevBoughtGas: _prevBoughtGas,\n prevBlockNum: _prevBlockNum\n });\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return Constants.DEFAULT_RESOURCE_CONFIG();\n }\n\n function use(uint64 _amount) public returns (uint256) {\n uint256 initialGas = gasleft();\n _metered(_amount, initialGas);\n return initialGas - gasleft();\n }\n}\n\n/**\n * @title ArtifactResourceMetering_Test\n * @notice A table test that sets the state of the ResourceParams and then requests\n * various amounts of gas. This test ensures that a wide range of values\n * can safely be used with the `ResourceMetering` contract.\n * It also writes a CSV file to disk that includes useful information\n * about how much gas is used and how expensive it is in USD terms to\n * purchase the deposit gas.\n */\ncontract ArtifactResourceMetering_Test is Test {\n uint128 internal minimumBaseFee;\n uint128 internal maximumBaseFee;\n uint64 internal maxResourceLimit;\n uint64 internal targetResourceLimit;\n\n string internal outfile;\n\n // keccak256(abi.encodeWithSignature(\"Error(string)\", \"ResourceMetering: cannot buy more gas than available gas limit\"))\n bytes32 internal cannotBuyMoreGas =\n 0x84edc668cfd5e050b8999f43ff87a1faaa93e5f935b20bc1dd4d3ff157ccf429;\n // keccak256(abi.encodeWithSignature(\"Panic(uint256)\", 0x11))\n bytes32 internal overflowErr =\n 0x1ca389f2c8264faa4377de9ce8e14d6263ef29c68044a9272d405761bab2db27;\n // keccak256(hex\"\")\n bytes32 internal emptyReturnData =\n 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n\n /**\n * @notice Sets up the tests by getting constants from the ResourceMetering\n * contract.\n */\n function setUp() public {\n vm.roll(1_000_000);\n\n MeterUser base = new MeterUser();\n ResourceMetering.ResourceConfig memory rcfg = base.resourceConfig();\n minimumBaseFee = uint128(rcfg.minimumBaseFee);\n maximumBaseFee = rcfg.maximumBaseFee;\n maxResourceLimit = uint64(rcfg.maxResourceLimit);\n targetResourceLimit = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n\n outfile = string.concat(vm.projectRoot(), \"/.resource-metering.csv\");\n try vm.removeFile(outfile) {} catch {}\n }\n\n /**\n * @notice Generate a CSV file. The call to `meter` should be called with at\n * most the L1 block gas limit. Without specifying the amount of\n * gas, it can take very long to execute.\n */\n function test_meter_generateArtifact_succeeds() external {\n vm.writeLine(\n outfile,\n \"prevBaseFee,prevBoughtGas,prevBlockNumDiff,l1BaseFee,requestedGas,gasConsumed,ethPrice,usdCost,success\"\n );\n\n // prevBaseFee value in ResourceParams\n uint128[] memory prevBaseFees = new uint128[](5);\n prevBaseFees[0] = minimumBaseFee;\n prevBaseFees[1] = maximumBaseFee;\n prevBaseFees[2] = uint128(50 gwei);\n prevBaseFees[3] = uint128(100 gwei);\n prevBaseFees[4] = uint128(200 gwei);\n\n // prevBoughtGas value in ResourceParams\n uint64[] memory prevBoughtGases = new uint64[](1);\n prevBoughtGases[0] = uint64(0);\n\n // prevBlockNum diff, simulates blocks with no deposits when non zero\n uint64[] memory prevBlockNumDiffs = new uint64[](2);\n prevBlockNumDiffs[0] = 0;\n prevBlockNumDiffs[1] = 1;\n\n // The amount of L2 gas that a user requests\n uint64[] memory requestedGases = new uint64[](3);\n requestedGases[0] = maxResourceLimit;\n requestedGases[1] = targetResourceLimit;\n requestedGases[2] = uint64(100_000);\n\n // The L1 base fee\n uint256[] memory l1BaseFees = new uint256[](4);\n l1BaseFees[0] = 1 gwei;\n l1BaseFees[1] = 50 gwei;\n l1BaseFees[2] = 75 gwei;\n l1BaseFees[3] = 100 gwei;\n\n // USD price of 1 ether\n uint256[] memory ethPrices = new uint256[](2);\n ethPrices[0] = 1600;\n ethPrices[1] = 3200;\n\n // Iterate over all of the test values and run a test\n for (uint256 i; i < prevBaseFees.length; i++) {\n for (uint256 j; j < prevBoughtGases.length; j++) {\n for (uint256 k; k < prevBlockNumDiffs.length; k++) {\n for (uint256 l; l < requestedGases.length; l++) {\n for (uint256 m; m < l1BaseFees.length; m++) {\n for (uint256 n; n < ethPrices.length; n++) {\n uint256 snapshotId = vm.snapshot();\n\n uint128 prevBaseFee = prevBaseFees[i];\n uint64 prevBoughtGas = prevBoughtGases[j];\n uint64 prevBlockNumDiff = prevBlockNumDiffs[k];\n uint64 requestedGas = requestedGases[l];\n uint256 l1BaseFee = l1BaseFees[m];\n uint256 ethPrice = ethPrices[n];\n string memory result = \"success\";\n\n vm.fee(l1BaseFee);\n\n CustomMeterUser meter = new CustomMeterUser({\n _prevBaseFee: prevBaseFee,\n _prevBoughtGas: prevBoughtGas,\n _prevBlockNum: uint64(block.number)\n });\n\n vm.roll(block.number + prevBlockNumDiff);\n\n // Call the metering code and catch the various\n // types of errors.\n uint256 gasConsumed = 0;\n try meter.use{ gas: 30_000_000 }(requestedGas) returns (\n uint256 _gasConsumed\n ) {\n gasConsumed = _gasConsumed;\n } catch (bytes memory err) {\n bytes32 hash = keccak256(err);\n if (hash == cannotBuyMoreGas) {\n result = \"ResourceMetering: cannot buy more gas than available gas limit\";\n } else if (hash == overflowErr) {\n result = \"arithmetic overflow/underflow\";\n } else if (hash == emptyReturnData) {\n result = \"out of gas\";\n } else {\n result = \"UNKNOWN ERROR\";\n }\n }\n\n // Compute the USD cost of the gas used\n uint256 usdCost = (gasConsumed * l1BaseFee * ethPrice) / 1 ether;\n\n vm.writeLine(\n outfile,\n string.concat(\n vm.toString(prevBaseFee),\n \",\",\n vm.toString(prevBoughtGas),\n \",\",\n vm.toString(prevBlockNumDiff),\n \",\",\n vm.toString(l1BaseFee),\n \",\",\n vm.toString(requestedGas),\n \",\",\n vm.toString(gasConsumed),\n \",\",\n \"$\",\n vm.toString(ethPrice),\n \",\",\n \"$\",\n vm.toString(usdCost),\n \",\",\n result\n )\n );\n\n assertTrue(vm.revertTo(snapshotId));\n }\n }\n }\n }\n }\n }\n }\n}\n" - }, - "contracts/test/SafeCall.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\n\ncontract SafeCall_call_Test is CommonTest {\n function testFuzz_call_succeeds(\n address from,\n address to,\n uint256 gas,\n uint64 value,\n bytes memory data\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles (mainnet)\n assumeNoPrecompiles(to, 1);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n uint256[2] memory balancesBefore = [from.balance, to.balance];\n\n vm.expectCall(to, value, data);\n vm.prank(from);\n bool success = SafeCall.call(to, gas, value, data);\n\n assertTrue(success, \"call not successful\");\n if (from == to) {\n assertEq(from.balance, balancesBefore[0], \"Self-send did not change balance\");\n } else {\n assertEq(from.balance, balancesBefore[0] - value, \"from balance not drained\");\n assertEq(to.balance, balancesBefore[1] + value, \"to balance received\");\n }\n }\n\n function testFuzz_callWithMinGas_hasEnough_succeeds(\n address from,\n address to,\n uint64 minGas,\n uint64 value,\n bytes memory data\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles (mainnet)\n assumeNoPrecompiles(to, 1);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n // Bound minGas to [0, l1_block_gas_limit]\n minGas = uint64(bound(minGas, 0, 30_000_000));\n\n uint256[2] memory balancesBefore = [from.balance, to.balance];\n\n vm.expectCallMinGas(to, value, minGas, data);\n vm.prank(from);\n bool success = SafeCall.callWithMinGas(to, minGas, value, data);\n\n assertTrue(success, \"call not successful\");\n if (from == to) {\n assertEq(from.balance, balancesBefore[0], \"Self-send did not change balance\");\n } else {\n assertEq(from.balance, balancesBefore[0] - value, \"from balance not drained\");\n assertEq(to.balance, balancesBefore[1] + value, \"to balance received\");\n }\n }\n\n function test_callWithMinGas_noLeakageLow_succeeds() external {\n SimpleSafeCaller caller = new SimpleSafeCaller();\n\n for (uint64 i = 5000; i < 50_000; i++) {\n uint256 snapshot = vm.snapshot();\n\n // 26,071 is the exact amount of gas required to make the safe call\n // successfully.\n if (i < 26_071) {\n assertFalse(caller.makeSafeCall(i, 25_000));\n } else {\n vm.expectCallMinGas(\n address(caller),\n 0,\n 25_000,\n abi.encodeWithSelector(caller.setA.selector, 1)\n );\n assertTrue(caller.makeSafeCall(i, 25_000));\n }\n\n assertTrue(vm.revertTo(snapshot));\n }\n }\n\n function test_callWithMinGas_noLeakageHigh_succeeds() external {\n SimpleSafeCaller caller = new SimpleSafeCaller();\n\n for (uint64 i = 15_200_000; i < 15_300_000; i++) {\n uint256 snapshot = vm.snapshot();\n\n // 15,238,769 is the exact amount of gas required to make the safe call\n // successfully.\n if (i < 15_238_769) {\n assertFalse(caller.makeSafeCall(i, 15_000_000));\n } else {\n vm.expectCallMinGas(\n address(caller),\n 0,\n 15_000_000,\n abi.encodeWithSelector(caller.setA.selector, 1)\n );\n assertTrue(caller.makeSafeCall(i, 15_000_000));\n }\n\n assertTrue(vm.revertTo(snapshot));\n }\n }\n}\n\ncontract SimpleSafeCaller {\n uint256 public a;\n\n function makeSafeCall(uint64 gas, uint64 minGas) external returns (bool) {\n return\n SafeCall.call(\n address(this),\n gas,\n 0,\n abi.encodeWithSelector(this.makeSafeCallMinGas.selector, minGas)\n );\n }\n\n function makeSafeCallMinGas(uint64 minGas) external returns (bool) {\n return\n SafeCall.callWithMinGas(\n address(this),\n minGas,\n 0,\n abi.encodeWithSelector(this.setA.selector, 1)\n );\n }\n\n function setA(uint256 _a) external {\n a = _a;\n }\n}\n" - }, - "contracts/test/Semver.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\n\n/**\n * @notice Test the Semver contract that is used for semantic versioning\n * of various contracts.\n */\ncontract Semver_Test is CommonTest {\n /**\n * @notice Global semver contract deployed in setUp. This is used in\n * the test cases.\n */\n Semver semver;\n\n /**\n * @notice Deploy a Semver contract\n */\n function setUp() public virtual override {\n semver = new Semver(7, 8, 0);\n }\n\n /**\n * @notice Test the version getter\n */\n function test_version_succeeds() external {\n assertEq(semver.version(), \"7.8.0\");\n }\n\n /**\n * @notice Since the versions are all immutable, they should\n * be able to be accessed from behind a proxy without needing\n * to initialize the contract.\n */\n function test_behindProxy_succeeds() external {\n Proxy proxy = new Proxy(alice);\n vm.prank(alice);\n proxy.upgradeTo(address(semver));\n\n assertEq(Semver(address(proxy)).version(), \"7.8.0\");\n }\n}\n" - }, - "contracts/test/SequencerFeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { SequencerFeeVault } from \"../L2/SequencerFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract SequencerFeeVault_Test is Bridge_Initializer {\n SequencerFeeVault vault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET));\n address constant recipient = address(256);\n\n event Withdrawal(uint256 value, address to, address from);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.SEQUENCER_FEE_WALLET, address(new SequencerFeeVault(recipient)).code);\n vm.label(Predeploys.SEQUENCER_FEE_WALLET, \"SequencerFeeVault\");\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(vault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n\n function test_constructor_succeeds() external {\n assertEq(vault.l1FeeWallet(), recipient);\n }\n\n function test_receive_succeeds() external {\n uint256 balance = address(vault).balance;\n\n vm.prank(alice);\n (bool success, ) = address(vault).call{ value: 100 }(hex\"\");\n\n assertEq(success, true);\n assertEq(address(vault).balance, balance + 100);\n }\n\n function test_withdraw_notEnough_reverts() external {\n assert(address(vault).balance < vault.MIN_WITHDRAWAL_AMOUNT());\n\n vm.expectRevert(\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n vault.withdraw();\n }\n\n function test_withdraw_succeeds() external {\n uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1;\n vm.deal(address(vault), amount);\n\n // No ether has been withdrawn yet\n assertEq(vault.totalProcessed(), 0);\n\n vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));\n emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this));\n\n // The entire vault's balance is withdrawn\n vm.expectCall(\n Predeploys.L2_STANDARD_BRIDGE,\n address(vault).balance,\n abi.encodeWithSelector(\n StandardBridge.bridgeETHTo.selector,\n vault.l1FeeWallet(),\n 35_000,\n bytes(\"\")\n )\n );\n\n vault.withdraw();\n\n // The withdrawal was successful\n assertEq(vault.totalProcessed(), amount);\n }\n}\n" - }, - "contracts/test/StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport {\n OptimismMintableERC20,\n ILegacyMintableERC20\n} from \"../universal/OptimismMintableERC20.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/**\n * @title StandardBridgeTester\n * @notice Simple wrapper around the StandardBridge contract that exposes\n * internal functions so they can be more easily tested directly.\n */\ncontract StandardBridgeTester is StandardBridge {\n constructor(address payable _messenger, address payable _otherBridge)\n StandardBridge(_messenger, _otherBridge)\n {}\n\n function isOptimismMintableERC20(address _token) external view returns (bool) {\n return _isOptimismMintableERC20(_token);\n }\n\n function isCorrectTokenPair(address _mintableToken, address _otherToken)\n external\n view\n returns (bool)\n {\n return _isCorrectTokenPair(_mintableToken, _otherToken);\n }\n\n receive() external payable override {}\n}\n\n/**\n * @title LegacyMintable\n * @notice Simple implementation of the legacy OptimismMintableERC20.\n */\ncontract LegacyMintable is ERC20, ILegacyMintableERC20 {\n constructor(string memory _name, string memory _ticker) ERC20(_name, _ticker) {}\n\n function l1Token() external pure returns (address) {\n return address(0);\n }\n\n function mint(address _to, uint256 _amount) external pure {}\n\n function burn(address _from, uint256 _amount) external pure {}\n\n /**\n * @notice Implements ERC165. This implementation should not be changed as\n * it is how the actual legacy optimism mintable token does the\n * check. Allows for testing against code that is has been deployed,\n * assuming different compiler version is no problem.\n */\n function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {\n bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^\n ILegacyMintableERC20.mint.selector ^\n ILegacyMintableERC20.burn.selector;\n return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n }\n}\n\n/**\n * @title StandardBridge_Stateless_Test\n * @notice Tests internal functions that require no existing state or contract\n * interactions with the messenger.\n */\ncontract StandardBridge_Stateless_Test is CommonTest {\n StandardBridgeTester internal bridge;\n OptimismMintableERC20 internal mintable;\n ERC20 internal erc20;\n LegacyMintable internal legacy;\n\n function setUp() public override {\n super.setUp();\n\n bridge = new StandardBridgeTester({\n _messenger: payable(address(0)),\n _otherBridge: payable(address(0))\n });\n\n mintable = new OptimismMintableERC20({\n _bridge: address(0),\n _remoteToken: address(0),\n _name: \"Stonks\",\n _symbol: \"STONK\"\n });\n\n erc20 = new ERC20(\"Altcoin\", \"ALT\");\n legacy = new LegacyMintable(\"Legacy\", \"LEG\");\n }\n\n /**\n * @notice Test coverage for identifying OptimismMintableERC20 tokens.\n * This function should return true for both modern and legacy\n * OptimismMintableERC20 tokens and false for any accounts that\n * do not implement the interface.\n */\n function test_isOptimismMintableERC20_succeeds() external {\n // Both the modern and legacy mintable tokens should return true\n assertTrue(bridge.isOptimismMintableERC20(address(mintable)));\n assertTrue(bridge.isOptimismMintableERC20(address(legacy)));\n // A regular ERC20 should return false\n assertFalse(bridge.isOptimismMintableERC20(address(erc20)));\n // Non existent contracts should return false and not revert\n assertEq(address(0x20).code.length, 0);\n assertFalse(bridge.isOptimismMintableERC20(address(0x20)));\n }\n\n /**\n * @notice Test coverage of isCorrectTokenPair under different types of\n * tokens.\n */\n function test_isCorrectTokenPair_succeeds() external {\n // Modern + known to be correct remote token\n assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.remoteToken()));\n // Modern + known to be correct l1Token (legacy interface)\n assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.l1Token()));\n // Modern + known to be incorrect remote token\n assertTrue(mintable.remoteToken() != address(0x20));\n assertFalse(bridge.isCorrectTokenPair(address(mintable), address(0x20)));\n // Legacy + known to be correct l1Token\n assertTrue(bridge.isCorrectTokenPair(address(legacy), legacy.l1Token()));\n // Legacy + known to be incorrect l1Token\n assertTrue(legacy.l1Token() != address(0x20));\n assertFalse(bridge.isCorrectTokenPair(address(legacy), address(0x20)));\n // A token that doesn't support either modern or legacy interface\n // will revert\n vm.expectRevert();\n bridge.isCorrectTokenPair(address(erc20), address(1));\n }\n}\n" - }, - "contracts/test/SystemConfig.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract SystemConfig_Init is CommonTest {\n SystemConfig sysConf;\n\n function setUp() public virtual override {\n super.setUp();\n\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n\n sysConf = new SystemConfig({\n _owner: alice,\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(1),\n _config: config\n });\n }\n}\n\ncontract SystemConfig_Initialize_TestFail is SystemConfig_Init {\n function test_initialize_lowGasLimit_reverts() external {\n uint64 minimumGasLimit = sysConf.minimumGasLimit();\n\n ResourceMetering.ResourceConfig memory cfg = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n\n vm.expectRevert(\"SystemConfig: gas limit too low\");\n new SystemConfig({\n _owner: alice,\n _overhead: 0,\n _scalar: 0,\n _batcherHash: bytes32(hex\"\"),\n _gasLimit: minimumGasLimit - 1,\n _unsafeBlockSigner: address(1),\n _config: cfg\n });\n }\n}\n\ncontract SystemConfig_Setters_TestFail is SystemConfig_Init {\n function test_setBatcherHash_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setBatcherHash(bytes32(hex\"\"));\n }\n\n function test_setGasConfig_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasConfig(0, 0);\n }\n\n function test_setGasLimit_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasLimit(0);\n }\n\n function test_setUnsafeBlockSigner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setUnsafeBlockSigner(address(0x20));\n }\n\n function test_setResourceConfig_notOwner_reverts() external {\n ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_badMinMax_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 2 gwei,\n maximumBaseFee: 1 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: min base fee must be less than max base\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_zeroDenominator_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 0,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: denominator cannot be 0\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_lowGasLimit_reverts() external {\n uint64 gasLimit = sysConf.gasLimit();\n\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: uint32(gasLimit),\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: uint32(gasLimit),\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: gas limit too low\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_badPrecision_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 11,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: precision loss with target resource limit\");\n sysConf.setResourceConfig(config);\n }\n}\n\ncontract SystemConfig_Setters_Test is SystemConfig_Init {\n event ConfigUpdate(\n uint256 indexed version,\n SystemConfig.UpdateType indexed updateType,\n bytes data\n );\n\n function testFuzz_setBatcherHash_succeeds(bytes32 newBatcherHash) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash));\n\n vm.prank(sysConf.owner());\n sysConf.setBatcherHash(newBatcherHash);\n assertEq(sysConf.batcherHash(), newBatcherHash);\n }\n\n function testFuzz_setGasConfig_succeeds(uint256 newOverhead, uint256 newScalar) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.GAS_CONFIG,\n abi.encode(newOverhead, newScalar)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setGasConfig(newOverhead, newScalar);\n assertEq(sysConf.overhead(), newOverhead);\n assertEq(sysConf.scalar(), newScalar);\n }\n\n function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external {\n uint64 minimumGasLimit = sysConf.minimumGasLimit();\n newGasLimit = uint64(\n bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(type(uint64).max))\n );\n\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit));\n\n vm.prank(sysConf.owner());\n sysConf.setGasLimit(newGasLimit);\n assertEq(sysConf.gasLimit(), newGasLimit);\n }\n\n function testFuzz_setUnsafeBlockSigner_succeeds(address newUnsafeSigner) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER,\n abi.encode(newUnsafeSigner)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setUnsafeBlockSigner(newUnsafeSigner);\n assertEq(sysConf.unsafeBlockSigner(), newUnsafeSigner);\n }\n}\n" - }, - "contracts/test/TransferOnion.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { TransferOnion } from \"../periphery/TransferOnion.sol\";\n\n/**\n * @title TransferOnionTest\n * @notice Test coverage of TransferOnion\n */\ncontract TransferOnionTest is Test {\n /**\n * @notice TransferOnion\n */\n TransferOnion internal onion;\n\n /**\n * @notice token constructor arg\n */\n address internal _token;\n\n /**\n * @notice sender constructor arg\n */\n address internal _sender;\n\n /**\n * @notice Sets up addresses, deploys contracts and funds the owner.\n */\n function setUp() public {\n ERC20 token = new ERC20(\"Token\", \"TKN\");\n _token = address(token);\n _sender = makeAddr(\"sender\");\n }\n\n /**\n * @notice Deploy the TransferOnion with a dummy shell\n */\n function _deploy() public {\n _deploy(bytes32(0));\n }\n\n /**\n * @notice Deploy the TransferOnion with a specific shell\n */\n function _deploy(bytes32 _shell) public {\n onion = new TransferOnion({ _token: ERC20(_token), _sender: _sender, _shell: _shell });\n }\n\n /**\n * @notice Build the onion data\n */\n function _onionize(TransferOnion.Layer[] memory _layers)\n public\n pure\n returns (bytes32, TransferOnion.Layer[] memory)\n {\n uint256 length = _layers.length;\n bytes32 hash = bytes32(0);\n for (uint256 i; i < length; i++) {\n TransferOnion.Layer memory layer = _layers[i];\n _layers[i].shell = hash;\n hash = keccak256(abi.encode(layer.recipient, layer.amount, hash));\n }\n return (hash, _layers);\n }\n\n /**\n * @notice The constructor sets the variables as expected\n */\n function test_constructor_succeeds() external {\n _deploy();\n\n assertEq(address(onion.TOKEN()), _token);\n assertEq(onion.SENDER(), _sender);\n assertEq(onion.shell(), bytes32(0));\n }\n\n /**\n * @notice unwrap\n */\n function test_unwrap_succeeds() external {\n // Commit to transferring tiny amounts of tokens\n TransferOnion.Layer[] memory _layers = new TransferOnion.Layer[](2);\n _layers[0] = TransferOnion.Layer(address(1), 1, bytes32(0));\n _layers[1] = TransferOnion.Layer(address(2), 2, bytes32(0));\n\n // Build the onion shell\n (bytes32 shell, TransferOnion.Layer[] memory layers) = _onionize(_layers);\n _deploy(shell);\n\n assertEq(onion.shell(), shell);\n\n address token = address(onion.TOKEN());\n address sender = onion.SENDER();\n\n // give 3 units of token to sender\n deal(token, onion.SENDER(), 3);\n vm.prank(sender);\n ERC20(token).approve(address(onion), 3);\n\n // To build the inputs, to `peel`, need to reverse the list\n TransferOnion.Layer[] memory inputs = new TransferOnion.Layer[](2);\n int256 length = int256(layers.length);\n for (int256 i = length - 1; i >= 0; i--) {\n uint256 ui = uint256(i);\n uint256 revidx = uint256(length) - ui - 1;\n TransferOnion.Layer memory layer = layers[ui];\n inputs[revidx] = layer;\n }\n\n // The accounts have no balance\n assertEq(ERC20(_token).balanceOf(address(1)), 0);\n assertEq(ERC20(_token).balanceOf(address(2)), 0);\n\n onion.peel(inputs);\n\n // Now the accounts have the expected balance\n assertEq(ERC20(_token).balanceOf(address(1)), 1);\n assertEq(ERC20(_token).balanceOf(address(2)), 2);\n }\n}\n" - }, - "contracts/test/invariants/CrossDomainMessenger.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { StdUtils } from \"forge-std/StdUtils.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport { OptimismPortal } from \"../../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../../L1/L1CrossDomainMessenger.sol\";\nimport { Messenger_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\nimport { Predeploys } from \"../../libraries/Predeploys.sol\";\nimport { Encoding } from \"../../libraries/Encoding.sol\";\nimport { Hashing } from \"../../libraries/Hashing.sol\";\n\ncontract RelayActor is StdUtils {\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n uint256 public numHashes;\n bytes32[] public hashes;\n bool public reverted = false;\n\n OptimismPortal op;\n L1CrossDomainMessenger xdm;\n Vm vm;\n\n constructor(\n OptimismPortal _op,\n L1CrossDomainMessenger _xdm,\n Vm _vm\n ) {\n op = _op;\n xdm = _xdm;\n vm = _vm;\n }\n\n /**\n * Relays a message to the `L1CrossDomainMessenger` with a random `version`, `_minGasLimit`\n * and `_message`.\n */\n function relay(\n uint16 _version,\n uint32 _minGasLimit,\n bytes memory _message\n ) external {\n address target = address(0x04); // ID precompile\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Restrict `_minGasLimit` to a number in the range of the block gas limit.\n _minGasLimit = uint32(bound(_minGasLimit, 0, block.gaslimit));\n\n // Restrict version to the range of [0, 1]\n _version = _version % 2;\n\n // Compute the cross domain message hash and store it in `hashes`.\n // The `relayMessage` function will always encode the message as a version 1\n // message after checking that the V0 hash has not already been relayed.\n bytes32 _hash = Hashing.hashCrossDomainMessageV1(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n 0, // value\n _minGasLimit,\n _message\n );\n\n // Act as the optimism portal and call `relayMessage` on the `L1CrossDomainMessenger` with\n // the outer min gas limit.\n vm.startPrank(address(op));\n vm.expectCall(target, _message);\n try\n xdm.relayMessage{ gas: xdm.baseGas(_message, _minGasLimit) }(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n 0, // value\n _minGasLimit,\n _message\n )\n {} catch {\n // If any of these calls revert, set `reverted` to true to fail the invariant test.\n // NOTE: This is to get around forge's invariant fuzzer ignoring reverted calls\n // to this function.\n reverted = true;\n }\n vm.stopPrank();\n\n hashes.push(_hash);\n numHashes += 1;\n }\n}\n\ncontract XDM_MinGasLimits is Messenger_Initializer {\n RelayActor actor;\n\n function setUp() public virtual override {\n // Set up the `L1CrossDomainMessenger` and `OptimismPortal` contracts.\n super.setUp();\n\n // Deploy a relay actor\n actor = new RelayActor(op, L1Messenger, vm);\n\n // Target the `RelayActor` contract\n targetContract(address(actor));\n\n // Target the actor's `relay` function\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = actor.relay.selector;\n targetSelector(FuzzSelector({ addr: address(actor), selectors: selectors }));\n }\n\n /**\n * @custom:invariant A call to `relayMessage` should never revert if at least the proper minimum\n * gas limits are supplied.\n *\n * There are two minimum gas limits here:\n *\n * - The outer min gas limit is for the call from the `OptimismPortal` to the\n * `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function\n * with the `message` and inner limit.\n *\n * - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target\n * contract.\n */\n function invariant_minGasLimits() public {\n uint256 length = actor.numHashes();\n for (uint256 i = 0; i < length; ++i) {\n bytes32 hash = actor.hashes(i);\n // the message hash is in the successfulMessages mapping\n assertTrue(L1Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertFalse(L1Messenger.failedMessages(hash));\n }\n assertFalse(actor.reverted());\n }\n}\n" - }, - "contracts/test/invariants/L2OutputOracle.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { L2OutputOracle_Initializer } from \"../CommonTest.t.sol\";\nimport { L2OutputOracle } from \"../../L1/L2OutputOracle.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\n\ncontract L2OutputOracle_Proposer {\n L2OutputOracle internal oracle;\n Vm internal vm;\n\n constructor(L2OutputOracle _oracle, Vm _vm) {\n oracle = _oracle;\n vm = _vm;\n }\n\n /**\n * @dev Allows the actor to propose an L2 output to the `L2OutputOracle`\n */\n function proposeL2Output(\n bytes32 _outputRoot,\n uint256 _l2BlockNumber,\n bytes32 _l1BlockHash,\n uint256 _l1BlockNumber\n ) external {\n // Act as the proposer and propose a new output.\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _l2BlockNumber, _l1BlockHash, _l1BlockNumber);\n }\n}\n\ncontract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_Initializer {\n L2OutputOracle_Proposer internal actor;\n\n function setUp() public override {\n super.setUp();\n\n // Create a proposer actor.\n actor = new L2OutputOracle_Proposer(oracle, vm);\n\n // Set the target contract to the proposer actor.\n targetContract(address(actor));\n\n // Set the target selector for `proposeL2Output`\n // `proposeL2Output` is the only function we care about, as it is the only function\n // that can modify the `l2Outputs` array in the oracle.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = actor.proposeL2Output.selector;\n FuzzSelector memory selector = FuzzSelector({ addr: address(actor), selectors: selectors });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The block number of the output root proposals should monotonically\n * increase.\n *\n * When a new output is submitted, it should never be allowed to correspond to a block\n * number that is less than the current output.\n */\n function invariant_monotonicBlockNumIncrease() external {\n // Assert that the block number of proposals must monotonically increase.\n assertTrue(oracle.nextBlockNumber() >= oracle.latestBlockNumber());\n }\n}\n" - }, - "contracts/test/invariants/OptimismPortal.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Portal_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\n\ncontract OptimismPortal_Invariant_Harness is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n function setUp() public virtual override {\n super.setUp();\n\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n}\n\ncontract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the finalization\n * period has not elapsed.\n *\n * A withdrawal that has been proven should not be able to be finalized until after\n * the finalization period has elapsed.\n */\n function invariant_cannotFinalizeBeforePeriodHasPassed() external {\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Finalize the withdrawal transaction.\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal\n * has already been finalized.\n *\n * Ensures that there is no chain of calls that can be made that allows a withdrawal\n * to be finalized twice.\n */\n function invariant_cannotFinalizeTwice() external {\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant A withdrawal should **always** be able to be finalized\n * `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.\n *\n * This invariant asserts that there is no chain of calls that can be made that\n * will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS`\n * after it was successfully proven.\n */\n function invariant_canAlwaysFinalize() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assertEq(address(bob).balance, bobBalanceBefore + _defaultTx.value);\n }\n}\n" - }, - "contracts/test/invariants/SafeCall.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { StdUtils } from \"forge-std/StdUtils.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport { SafeCall } from \"../../libraries/SafeCall.sol\";\n\ncontract SafeCall_Succeeds_Invariants is Test {\n SafeCaller_Actor actor;\n\n function setUp() public {\n // Create a new safe caller actor.\n actor = new SafeCaller_Actor(vm, false);\n\n // Set the caller to this contract\n targetSender(address(this));\n\n // Target the safe caller actor.\n targetContract(address(actor));\n }\n\n /**\n * @custom:invariant If `callWithMinGas` performs a call, then it must always\n * provide at least the specified minimum gas limit to the subcontext.\n *\n * If the check for remaining gas in `SafeCall.callWithMinGas` passes, the\n * subcontext of the call below it must be provided at least `minGas` gas.\n */\n function invariant_callWithMinGas_alwaysForwardsMinGas_succeeds() public {\n assertEq(actor.numCalls(), 0, \"no failed calls allowed\");\n }\n\n function performSafeCallMinGas(uint64 minGas) external {\n SafeCall.callWithMinGas(address(0), minGas, 0, hex\"\");\n }\n}\n\ncontract SafeCall_Fails_Invariants is Test {\n SafeCaller_Actor actor;\n\n function setUp() public {\n // Create a new safe caller actor.\n actor = new SafeCaller_Actor(vm, true);\n\n // Set the caller to this contract\n targetSender(address(this));\n\n // Target the safe caller actor.\n targetContract(address(actor));\n }\n\n /**\n * @custom:invariant `callWithMinGas` reverts if there is not enough gas to pass\n * to the subcontext.\n *\n * If there is not enough gas in the callframe to ensure that `callWithMinGas`\n * can provide the specified minimum gas limit to the subcontext of the call,\n * then `callWithMinGas` must revert.\n */\n function invariant_callWithMinGas_neverForwardsMinGas_reverts() public {\n assertEq(actor.numCalls(), 0, \"no successful calls allowed\");\n }\n\n function performSafeCallMinGas(uint64 minGas) external {\n SafeCall.callWithMinGas(address(0), minGas, 0, hex\"\");\n }\n}\n\ncontract SafeCaller_Actor is StdUtils {\n bool internal immutable FAILS;\n\n Vm internal vm;\n uint256 public numCalls;\n\n constructor(Vm _vm, bool _fails) {\n vm = _vm;\n FAILS = _fails;\n }\n\n function performSafeCallMinGas(uint64 gas, uint64 minGas) external {\n if (FAILS) {\n // Bound the minimum gas amount to [2500, type(uint48).max]\n minGas = uint64(bound(minGas, 2500, type(uint48).max));\n // Bound the gas passed to [minGas, (((minGas + 200) * 64) / 63)]\n gas = uint64(bound(gas, minGas, (((minGas + 200) * 64) / 63)));\n } else {\n // Bound the minimum gas amount to [2500, type(uint48).max]\n minGas = uint64(bound(minGas, 2500, type(uint48).max));\n // Bound the gas passed to [(((minGas + 200) * 64) / 63) + 500, type(uint64).max]\n gas = uint64(bound(gas, (((minGas + 200) * 64) / 63) + 500, type(uint64).max));\n }\n\n vm.expectCallMinGas(address(0x00), 0, minGas, hex\"\");\n bool success = SafeCall.call(\n msg.sender,\n gas,\n 0,\n abi.encodeWithSelector(0x2ae57a41, minGas)\n );\n\n if (success && FAILS) numCalls++;\n if (!FAILS && !success) numCalls++;\n }\n}\n" - }, - "contracts/test/invariants/SystemConfig.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { SystemConfig } from \"../../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../../L1/ResourceMetering.sol\";\nimport { Constants } from \"../../libraries/Constants.sol\";\n\ncontract SystemConfig_GasLimitLowerBound_Invariant is Test {\n SystemConfig public config;\n\n function setUp() public {\n ResourceMetering.ResourceConfig memory cfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n config = new SystemConfig({\n _owner: address(0xbeef),\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(1),\n _config: cfg\n });\n\n // Set the target contract to the `config`\n targetContract(address(config));\n // Set the target sender to the `config`'s owner (0xbeef)\n targetSender(address(0xbeef));\n // Set the target selector for `setGasLimit`\n // `setGasLimit` is the only function we care about, as it is the only function\n // that can modify the gas limit within the SystemConfig.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = config.setGasLimit.selector;\n FuzzSelector memory selector = FuzzSelector({\n addr: address(config),\n selectors: selectors\n });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The gas limit of the `SystemConfig` contract can never be lower\n * than the hard-coded lower bound.\n */\n function invariant_gasLimitLowerBound() external {\n assertTrue(config.gasLimit() >= config.minimumGasLimit());\n }\n}\n" - }, - "contracts/universal/CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\n/**\n * @custom:legacy\n * @title CrossDomainMessengerLegacySpacer0\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 CrossDomainMessengerLegacySpacer0 {\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:legacy\n * @title CrossDomainMessengerLegacySpacer1\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\n * PausableUpgradable and OwnableUpgradeable variables used to exist. Must be\n * the third contract in the inheritance tree of the CrossDomainMessenger.\n */\ncontract CrossDomainMessengerLegacySpacer1 {\n /**\n * @custom:legacy\n * @custom:spacer __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * ContextUpgradable via OwnableUpgradeable.\n *\n */\n uint256[50] private spacer_1_0_1600;\n\n /**\n * @custom:legacy\n * @custom:spacer _owner\n * @notice Spacer for backwards compatibility.\n * Come from OpenZeppelin OwnableUpgradeable.\n */\n address private spacer_51_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * ContextUpgradable via PausableUpgradable.\n */\n uint256[49] private spacer_52_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer _paused\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n bool private spacer_101_0_1;\n\n /**\n * @custom:legacy\n * @custom:spacer __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n uint256[49] private spacer_102_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer ReentrancyGuardUpgradeable's `_status` field.\n * @notice Spacer for backwards compatibility\n */\n uint256 private spacer_151_0_32;\n\n /**\n * @custom:spacer ReentrancyGuardUpgradeable\n * @notice Spacer for backwards compatibility\n */\n uint256[49] private __gap_reentrancy_guard;\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/**\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 *\n * Any changes to this contract MUST result in a semver bump for contracts that inherit it.\n */\nabstract contract CrossDomainMessenger is\n CrossDomainMessengerLegacySpacer0,\n Initializable,\n CrossDomainMessengerLegacySpacer1\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 uint64 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 uint64 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 uint64 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 uint64 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\n\n /**\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\n */\n address public immutable OTHER_MESSENGER;\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 a boolean if and only if the message has failed to be\n * executed at least once. A message will not be present in this mapping if it\n * successfully executed on the first attempt.\n */\n mapping(bytes32 => bool) public failedMessages;\n\n /**\n * @notice A mapping of hashes to reentrancy locks.\n */\n mapping(bytes32 => bool) internal reentrancyLocks;\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[41] 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 OTHER_MESSENGER = _otherMessenger;\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 OTHER_MESSENGER,\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 {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n require(\n version < 2,\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // If the message is version 0, then it's a migrated legacy withdrawal. We therefore need\n // to check that the legacy version of the message has not already been relayed.\n if (version == 0) {\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _nonce);\n require(\n successfulMessages[oldHash] == false,\n \"CrossDomainMessenger: legacy withdrawal already relayed\"\n );\n }\n\n // We use the v1 message hash as the unique identifier for the message because it commits\n // to the value and minimum gas limit of the message.\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _minGasLimit,\n _message\n );\n\n // Check if the reentrancy lock for the `versionedHash` is already set.\n if (reentrancyLocks[versionedHash]) {\n revert(\"ReentrancyGuard: reentrant call\");\n }\n // Trigger the reentrancy lock for `versionedHash`\n reentrancyLocks[versionedHash] = true;\n\n if (_isOtherMessenger()) {\n // These properties should always hold when the message is first submitted (as\n // opposed to being replayed).\n assert(msg.value == _value);\n assert(!failedMessages[versionedHash]);\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 failedMessages[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 xDomainMsgSender = _sender;\n bool success = SafeCall.callWithMinGas(_target, _minGasLimit, _value, _message);\n xDomainMsgSender = Constants.DEFAULT_L2_SENDER;\n\n if (success) {\n successfulMessages[versionedHash] = true;\n emit RelayedMessage(versionedHash);\n } else {\n failedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n\n // Revert in this case if the transaction was triggered by the estimation address. This\n // should only be possible during gas estimation or we have bigger problems. Reverting\n // here will make the behavior of gas estimation change such that the gas limit\n // computed will be the amount required to relay the message, even if that amount is\n // greater than the minimum gas limit specified by the user.\n if (tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"CrossDomainMessenger: failed to relay message\");\n }\n }\n\n // Clear the reentrancy lock for `versionedHash`\n reentrancyLocks[versionedHash] = false;\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 != Constants.DEFAULT_L2_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 (uint64) {\n // We peform the following math on uint64s to avoid overflow errors. Multiplying the\n // by MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR would otherwise limit the _minGasLimit to\n // type(uint32).max / MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR ~= 4.2m.\n return\n // Dynamic overhead\n ((uint64(_minGasLimit) * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n // Calldata overhead\n (uint64(_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 = Constants.DEFAULT_L2_SENDER;\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" - }, - "contracts/universal/ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CrossDomainMessenger } from \"./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 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 OTHER_BRIDGE;\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 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 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() == OTHER_BRIDGE,\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 OTHER_BRIDGE = _otherBridge;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for other bridge address.\n *\n * @return Address of the bridge on the other network.\n */\n function otherBridge() external view returns (address) {\n return OTHER_BRIDGE;\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" - }, - "contracts/universal/FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n/**\n * @title FeeVault\n * @notice The FeeVault contract contains the basic logic for the various different vault contracts\n * used to hold fee revenue generated by the L2 system.\n */\nabstract contract FeeVault {\n /**\n * @notice Emits each time that a withdrawal occurs.\n *\n * @param value Amount that was withdrawn (in wei).\n * @param to Address that the funds were sent to.\n * @param from Address that triggered the withdrawal.\n */\n event Withdrawal(uint256 value, address to, address from);\n\n /**\n * @notice Minimum balance before a withdrawal can be triggered.\n */\n uint256 public immutable MIN_WITHDRAWAL_AMOUNT;\n\n /**\n * @notice Wallet that will receive the fees on L1.\n */\n address public immutable RECIPIENT;\n\n /**\n * @notice The minimum gas limit for the FeeVault withdrawal transaction.\n */\n uint32 internal constant WITHDRAWAL_MIN_GAS = 35_000;\n\n /**\n * @notice Total amount of wei processed by the contract.\n */\n uint256 public totalProcessed;\n\n /**\n * @param _recipient Wallet that will receive the fees on L1.\n * @param _minWithdrawalAmount Minimum balance before a withdrawal can be triggered.\n */\n constructor(address _recipient, uint256 _minWithdrawalAmount) {\n MIN_WITHDRAWAL_AMOUNT = _minWithdrawalAmount;\n RECIPIENT = _recipient;\n }\n\n /**\n * @notice Allow the contract to receive ETH.\n */\n receive() external payable {}\n\n /**\n * @notice Triggers a withdrawal of funds to the L1 fee wallet.\n */\n function withdraw() external {\n require(\n address(this).balance >= MIN_WITHDRAWAL_AMOUNT,\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n\n uint256 value = address(this).balance;\n totalProcessed += value;\n\n emit Withdrawal(value, RECIPIENT, msg.sender);\n\n L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)).bridgeETHTo{ value: value }(\n RECIPIENT,\n WITHDRAWAL_MIN_GAS,\n bytes(\"\")\n );\n }\n}\n" - }, - "contracts/universal/IOptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\n/**\n * @title IOptimismMintableERC20\n * @notice This interface is available on the OptimismMintableERC20 contract. We declare it as a\n * separate interface so that it can be used in custom implementations of\n * OptimismMintableERC20.\n */\ninterface IOptimismMintableERC20 is IERC165 {\n function remoteToken() external view returns (address);\n\n function bridge() external returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n\n/**\n * @custom:legacy\n * @title ILegacyMintableERC20\n * @notice This interface was available on the legacy L2StandardERC20 contract. It remains available\n * on the OptimismMintableERC20 contract for backwards compatibility.\n */\ninterface ILegacyMintableERC20 is IERC165 {\n function l1Token() external view returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n" - }, - "contracts/universal/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 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 /**\n * @notice Chain ID of the chain where the remote token is deployed.\n */\n function REMOTE_CHAIN_ID() external view returns (uint256);\n\n /**\n * @notice Address of the token on the remote domain.\n */\n function REMOTE_TOKEN() 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 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" - }, - "contracts/universal/OptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { ILegacyMintableERC20, IOptimismMintableERC20 } from \"./IOptimismMintableERC20.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @title OptimismMintableERC20\n * @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed\n * to allow the StandardBridge contracts to mint and burn tokens. This makes it possible to\n * use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa.\n * Designed to be backwards compatible with the older StandardL2ERC20 token which was only\n * meant for use on L2.\n */\ncontract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, Semver {\n /**\n * @notice Address of the corresponding version of this token on the remote chain.\n */\n address public immutable REMOTE_TOKEN;\n\n /**\n * @notice Address of the StandardBridge on this network.\n */\n address public immutable BRIDGE;\n\n /**\n * @notice Emitted whenever tokens are minted for an account.\n *\n * @param account Address of the account tokens are being minted for.\n * @param amount Amount of tokens minted.\n */\n event Mint(address indexed account, uint256 amount);\n\n /**\n * @notice Emitted whenever tokens are burned from an account.\n *\n * @param account Address of the account tokens are being burned from.\n * @param amount Amount of tokens burned.\n */\n event Burn(address indexed account, uint256 amount);\n\n /**\n * @notice A modifier that only allows the bridge to call\n */\n modifier onlyBridge() {\n require(msg.sender == BRIDGE, \"OptimismMintableERC20: only bridge can mint and burn\");\n _;\n }\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _bridge Address of the L2 standard bridge.\n * @param _remoteToken Address of the corresponding L1 token.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n */\n constructor(\n address _bridge,\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) Semver(1, 0, 0) {\n REMOTE_TOKEN = _remoteToken;\n BRIDGE = _bridge;\n }\n\n /**\n * @notice Allows the StandardBridge on this network to mint tokens.\n *\n * @param _to Address to mint tokens to.\n * @param _amount Amount of tokens to mint.\n */\n function mint(address _to, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _mint(_to, _amount);\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Allows the StandardBridge on this network to burn tokens.\n *\n * @param _from Address to burn tokens from.\n * @param _amount Amount of tokens to burn.\n */\n function burn(address _from, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _burn(_from, _amount);\n emit Burn(_from, _amount);\n }\n\n /**\n * @notice ERC165 interface check function.\n *\n * @param _interfaceId Interface ID to check.\n *\n * @return Whether or not the interface is supported by this contract.\n */\n function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {\n bytes4 iface1 = type(IERC165).interfaceId;\n // Interface corresponding to the legacy L2StandardERC20.\n bytes4 iface2 = type(ILegacyMintableERC20).interfaceId;\n // Interface corresponding to the updated OptimismMintableERC20 (this contract).\n bytes4 iface3 = type(IOptimismMintableERC20).interfaceId;\n return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward.\n */\n function l1Token() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the bridge. Use BRIDGE going forward.\n */\n function l2Bridge() public view returns (address) {\n return BRIDGE;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for REMOTE_TOKEN.\n */\n function remoteToken() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for BRIDGE.\n */\n function bridge() public view returns (address) {\n return BRIDGE;\n }\n}\n" - }, - "contracts/universal/OptimismMintableERC20Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Contract Imports */\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { Semver } from \"./Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000012\n * @title OptimismMintableERC20Factory\n * @notice OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20\n * contracts on the network it's deployed to. Simplifies the deployment process for users\n * who may be less familiar with deploying smart contracts. Designed to be backwards\n * compatible with the older StandardL2ERC20Factory contract.\n */\ncontract OptimismMintableERC20Factory is Semver {\n /**\n * @notice Address of the StandardBridge on this chain.\n */\n address public immutable BRIDGE;\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer\n * OptimismMintableERC20Created event. We recommend relying on that event instead.\n *\n * @param remoteToken Address of the token on the remote chain.\n * @param localToken Address of the created token on the local chain.\n */\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n\n /**\n * @notice Emitted whenever a new OptimismMintableERC20 is created.\n *\n * @param localToken Address of the created token on the local chain.\n * @param remoteToken Address of the corresponding token on the remote chain.\n * @param deployer Address of the account that deployed the token.\n */\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @notice The semver MUST be bumped any time that there is a change in\n * the OptimismMintableERC20 token contract since this contract\n * is responsible for deploying OptimismMintableERC20 contracts.\n *\n * @param _bridge Address of the StandardBridge on this chain.\n */\n constructor(address _bridge) Semver(1, 1, 0) {\n BRIDGE = _bridge;\n }\n\n /**\n * @custom:legacy\n * @notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the\n * newer createOptimismMintableERC20 function, which has a more intuitive name.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createStandardL2Token(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) external returns (address) {\n return createOptimismMintableERC20(_remoteToken, _name, _symbol);\n }\n\n /**\n * @notice Creates an instance of the OptimismMintableERC20 contract.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createOptimismMintableERC20(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) public returns (address) {\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC20Factory: must provide remote token address\"\n );\n\n address localToken = address(\n new OptimismMintableERC20(BRIDGE, _remoteToken, _name, _symbol)\n );\n\n // Emit the old event too for legacy support.\n emit StandardL2TokenCreated(_remoteToken, localToken);\n\n // Emit the updated event. The arguments here differ from the legacy event, but\n // are consistent with the ordering used in StandardBridge events.\n emit OptimismMintableERC20Created(localToken, _remoteToken, msg.sender);\n\n return localToken;\n }\n}\n" - }, - "contracts/universal/OptimismMintableERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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\";\nimport { Semver } from \"../universal/Semver.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, Semver {\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n uint256 public immutable REMOTE_CHAIN_ID;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable REMOTE_TOKEN;\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 * @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 * @custom:semver 1.0.0\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) Semver(1, 0, 0) {\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 REMOTE_CHAIN_ID = _remoteChainId;\n REMOTE_TOKEN = _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 * @inheritdoc IOptimismMintableERC721\n */\n function remoteChainId() external view returns (uint256) {\n return REMOTE_CHAIN_ID;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function remoteToken() external view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function bridge() external view returns (address) {\n return BRIDGE;\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" - }, - "contracts/universal/OptimismMintableERC721Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\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 {\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 REMOTE_CHAIN_ID;\n\n /**\n * @notice Tracks addresses created by this factory.\n */\n mapping(address => bool) public isOptimismMintableERC721;\n\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 * @custom:semver 1.1.0\n * @notice The semver MUST be bumped any time that there is a change in\n * the OptimismMintableERC721 token contract since this contract\n * is responsible for deploying OptimismMintableERC721 contracts.\n *\n * @param _bridge Address of the ERC721 bridge on this network.\n * @param _remoteChainId Chain ID for the remote network.\n */\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 1, 0) {\n BRIDGE = _bridge;\n REMOTE_CHAIN_ID = _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, REMOTE_CHAIN_ID, _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/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" - }, - "contracts/universal/ProxyAdmin.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.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 Ownable {\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 * @notice A mapping of proxy types, used for backwards compatibility.\n */\n mapping(address => ProxyType) public proxyType;\n\n /**\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 * @notice The address of the address manager, this is required to manage the\n * ResolvedDelegateProxy type.\n */\n AddressManager public addressManager;\n\n /**\n * @notice A legacy upgrading indicator used by the old Chugsplash Proxy.\n */\n bool internal upgrading;\n\n /**\n * @param _owner Address of the initial owner of this contract.\n */\n constructor(address _owner) Ownable() {\n _transferOwnership(_owner);\n }\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 * @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 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.\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 /**\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" - }, - "contracts/universal/Semver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 uint256 private immutable MAJOR_VERSION;\n\n /**\n * @notice Contract version number (minor).\n */\n uint256 private immutable MINOR_VERSION;\n\n /**\n * @notice Contract version number (patch).\n */\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" - }, - "contracts/universal/StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { IOptimismMintableERC20, ILegacyMintableERC20 } from \"./IOptimismMintableERC20.sol\";\nimport { CrossDomainMessenger } from \"./CrossDomainMessenger.sol\";\nimport { OptimismMintableERC20 } from \"./OptimismMintableERC20.sol\";\n\n/**\n * @custom:upgradeable\n * @title StandardBridge\n * @notice StandardBridge is a base contract for the L1 and L2 standard ERC20 bridges. It handles\n * the core bridging logic, including escrowing tokens that are native to the local chain\n * and minting/burning tokens that are native to the remote chain.\n */\nabstract contract StandardBridge {\n using SafeERC20 for IERC20;\n\n /**\n * @notice The L2 gas limit set when eth is depoisited using the receive() function.\n */\n uint32 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 200_000;\n\n /**\n * @notice Messenger contract on this domain.\n */\n CrossDomainMessenger public immutable MESSENGER;\n\n /**\n * @notice Corresponding bridge on the other domain.\n */\n StandardBridge public immutable OTHER_BRIDGE;\n\n /**\n * @custom:legacy\n * @custom:spacer messenger\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_0_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer l2TokenBridge\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_1_0_20;\n\n /**\n * @notice Mapping that stores deposits for a given pair of local and remote tokens.\n */\n mapping(address => mapping(address => uint256)) public deposits;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n * A gap size of 47 was chosen here, so that the first slot used in a child contract\n * would be a multiple of 50.\n */\n uint256[47] private __gap;\n\n /**\n * @notice Emitted when an ETH bridge is initiated to the other chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ETH bridge is finalized on this chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is initiated to the other chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is finalized on this chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Only allow EOAs to call the functions. Note that this is not safe against contracts\n * calling code within their constructors, but also doesn't really matter since we're\n * just trying to prevent users accidentally depositing with smart contract wallets.\n */\n modifier onlyEOA() {\n require(\n !Address.isContract(msg.sender),\n \"StandardBridge: function can only be called from an EOA\"\n );\n _;\n }\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) &&\n MESSENGER.xDomainMessageSender() == address(OTHER_BRIDGE),\n \"StandardBridge: function can only be called from the other bridge\"\n );\n _;\n }\n\n /**\n * @param _messenger Address of CrossDomainMessenger on this network.\n * @param _otherBridge Address of the other StandardBridge contract.\n */\n constructor(address payable _messenger, address payable _otherBridge) {\n MESSENGER = CrossDomainMessenger(_messenger);\n OTHER_BRIDGE = StandardBridge(_otherBridge);\n }\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n * Must be implemented by contracts that inherit.\n */\n receive() external payable virtual;\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @notice Sends ETH to the sender's address on the other chain.\n *\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETH(uint32 _minGasLimit, bytes calldata _extraData) public payable onlyEOA {\n _initiateBridgeETH(msg.sender, msg.sender, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a\n * smart contract and the call fails, the ETH will be temporarily locked in the\n * StandardBridge on the other chain until the call is replayed. If the call cannot be\n * replayed with any amount of gas (call always reverts), then the ETH will be\n * permanently locked in the StandardBridge on the other chain. ETH will also\n * be locked if the receiver is the other bridge, because finalizeBridgeETH will revert\n * in that case.\n *\n * @param _to Address of the receiver.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public payable {\n _initiateBridgeETH(msg.sender, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ERC20 tokens to the sender's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20(\n address _localToken,\n address _remoteToken,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual onlyEOA {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Finalizes an ETH bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public payable onlyOtherBridge {\n require(msg.value == _amount, \"StandardBridge: amount sent does not match amount required\");\n require(_to != address(this), \"StandardBridge: cannot send to self\");\n require(_to != address(MESSENGER), \"StandardBridge: cannot send to messenger\");\n\n // Emit the correct events. By default this will be _amount, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n\n bool success = SafeCall.call(_to, gasleft(), _amount, hex\"\");\n require(success, \"StandardBridge: ETH transfer failed\");\n }\n\n /**\n * @notice Finalizes an ERC20 bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public onlyOtherBridge {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).mint(_to, _amount);\n } else {\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] - _amount;\n IERC20(_localToken).safeTransfer(_to, _amount);\n }\n\n // Emit the correct events. By default this will be ERC20BridgeFinalized, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Initiates a bridge of ETH through the CrossDomainMessenger.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n require(\n msg.value == _amount,\n \"StandardBridge: bridging ETH must include sufficient ETH value\"\n );\n\n // Emit the correct events. By default this will be _amount, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage{ value: _amount }(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeETH.selector,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).burn(_from, _amount);\n } else {\n IERC20(_localToken).safeTransferFrom(_from, address(this), _amount);\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount;\n }\n\n // Emit the correct events. By default this will be ERC20BridgeInitiated, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeERC20.selector,\n // Because this call will be executed on the remote chain, we reverse the order of\n // the remote and local token addresses relative to their order in the\n // finalizeBridgeERC20 function.\n _remoteToken,\n _localToken,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Checks if a given address is an OptimismMintableERC20. Not perfect, but good enough.\n * Just the way we like it.\n *\n * @param _token Address of the token to check.\n *\n * @return True if the token is an OptimismMintableERC20.\n */\n function _isOptimismMintableERC20(address _token) internal view returns (bool) {\n return\n ERC165Checker.supportsInterface(_token, type(ILegacyMintableERC20).interfaceId) ||\n ERC165Checker.supportsInterface(_token, type(IOptimismMintableERC20).interfaceId);\n }\n\n /**\n * @notice Checks if the \"other token\" is the correct pair token for the OptimismMintableERC20.\n * Calls can be saved in the future by combining this logic with\n * `_isOptimismMintableERC20`.\n *\n * @param _mintableToken OptimismMintableERC20 to check against.\n * @param _otherToken Pair token to check.\n *\n * @return True if the other token is the correct pair token for the OptimismMintableERC20.\n */\n function _isCorrectTokenPair(address _mintableToken, address _otherToken)\n internal\n view\n returns (bool)\n {\n if (\n ERC165Checker.supportsInterface(_mintableToken, type(ILegacyMintableERC20).interfaceId)\n ) {\n return _otherToken == ILegacyMintableERC20(_mintableToken).l1Token();\n } else {\n return _otherToken == IOptimismMintableERC20(_mintableToken).remoteToken();\n }\n }\n\n /** @notice Emits the ETHBridgeInitiated event and if necessary the appropriate legacy event\n * when an ETH bridge is finalized on this chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ETHBridgeFinalized and if necessary the appropriate legacy event when an\n * ETH bridge is finalized on this chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ERC20BridgeInitiated event and if necessary the appropriate legacy\n * event when an ERC20 bridge is initiated to the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the ERC20 on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ERC20BridgeFinalized event and if necessary the appropriate legacy\n * event when an ERC20 bridge is initiated to the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the ERC20 on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/vendor/AddressAliasHelper.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npragma solidity ^0.8.0;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n unchecked {\n l2Address = address(uint160(l1Address) + offset);\n }\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n unchecked {\n l1Address = address(uint160(l2Address) - offset);\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/access/Ownable.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/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 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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/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/Address.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) || (!Address.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" - }, - "node_modules/@openzeppelin/contracts/security/ReentrancyGuard.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\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 ReentrancyGuard {\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 constructor() {\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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, allowance(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 = allowance(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 `from` to `to`.\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 Updates `owner` s allowance for `spender` based on spent `amount`.\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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 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 /**\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (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 constant _PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n /**\n * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\n * However, to ensure consistency with the upgradeable transpiler, we will continue\n * to reserve a slot.\n * @custom:oz-renamed-from _PERMIT_TYPEHASH\n */\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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: address zero is not a valid owner\");\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: invalid token ID\");\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 _requireMinted(tokenId);\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 token 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 _requireMinted(tokenId);\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: caller is not token 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: caller is not token 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 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 an {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 an {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 Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\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 /// @solidity memory-safe-assembly\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Address.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 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 /// @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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\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 /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.3) (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 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 /// @solidity memory-safe-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 {\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.2) (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 // prepare call\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n\n // perform static call\n bool success;\n uint256 returnSize;\n uint256 returnValue;\n assembly {\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\n returnSize := returndatasize()\n returnValue := mload(0x00)\n }\n\n return success && returnSize >= 0x20 && returnValue > 0;\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\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 == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`.\n // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.\n // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.\n // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a\n // good first aproximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1;\n uint256 x = a;\n if (x >> 128 > 0) {\n x >>= 128;\n result <<= 64;\n }\n if (x >> 64 > 0) {\n x >>= 64;\n result <<= 32;\n }\n if (x >> 32 > 0) {\n x >>= 32;\n result <<= 16;\n }\n if (x >> 16 > 0) {\n x >>= 16;\n result <<= 8;\n }\n if (x >> 8 > 0) {\n x >>= 8;\n result <<= 4;\n }\n if (x >> 4 > 0) {\n x >>= 4;\n result <<= 2;\n }\n if (x >> 2 > 0) {\n result <<= 1;\n }\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n uint256 result = sqrt(a);\n if (rounding == Rounding.Up && result * result < a) {\n result += 1;\n }\n return result;\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\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 * _Available since v4.2._\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 uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(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 * _Available since v2.5._\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 uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(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 * _Available since v4.2._\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 uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(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 * _Available since v2.5._\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 uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(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 * _Available since v2.5._\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 uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(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 * _Available since v2.5._\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 * _Available since v2.5._\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 * _Available since v3.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 int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248) {\n require(value >= type(int248).min && value <= type(int248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return int248(value);\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240) {\n require(value >= type(int240).min && value <= type(int240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return int240(value);\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232) {\n require(value >= type(int232).min && value <= type(int232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return int232(value);\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224) {\n require(value >= type(int224).min && value <= type(int224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return int224(value);\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216) {\n require(value >= type(int216).min && value <= type(int216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return int216(value);\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208) {\n require(value >= type(int208).min && value <= type(int208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return int208(value);\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200) {\n require(value >= type(int200).min && value <= type(int200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return int200(value);\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192) {\n require(value >= type(int192).min && value <= type(int192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return int192(value);\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184) {\n require(value >= type(int184).min && value <= type(int184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return int184(value);\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176) {\n require(value >= type(int176).min && value <= type(int176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return int176(value);\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168) {\n require(value >= type(int168).min && value <= type(int168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return int168(value);\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160) {\n require(value >= type(int160).min && value <= type(int160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return int160(value);\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152) {\n require(value >= type(int152).min && value <= type(int152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return int152(value);\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144) {\n require(value >= type(int144).min && value <= type(int144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return int144(value);\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136) {\n require(value >= type(int136).min && value <= type(int136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return int136(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 int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120) {\n require(value >= type(int120).min && value <= type(int120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return int120(value);\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112) {\n require(value >= type(int112).min && value <= type(int112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return int112(value);\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104) {\n require(value >= type(int104).min && value <= type(int104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return int104(value);\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96) {\n require(value >= type(int96).min && value <= type(int96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return int96(value);\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88) {\n require(value >= type(int88).min && value <= type(int88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return int88(value);\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80) {\n require(value >= type(int80).min && value <= type(int80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return int80(value);\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72) {\n require(value >= type(int72).min && value <= type(int72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return int72(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 int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56) {\n require(value >= type(int56).min && value <= type(int56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return int56(value);\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48) {\n require(value >= type(int48).min && value <= type(int48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return int48(value);\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40) {\n require(value >= type(int40).min && value <= type(int40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return int40(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 int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24) {\n require(value >= type(int24).min && value <= type(int24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return int24(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 * _Available since v3.0._\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" - }, - "node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@rari-capital/solmate/src/utils/Bytes32AddressLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Library for converting between addresses and bytes32 values.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/Bytes32AddressLib.sol)\nlibrary Bytes32AddressLib {\n function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n function fillLast12Bytes(address addressValue) internal pure returns (bytes32) {\n return bytes32(bytes20(addressValue));\n }\n}\n" - }, - "node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)\nlibrary FixedPointMathLib {\n /*//////////////////////////////////////////////////////////////\n SIMPLIFIED FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n }\n\n function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n }\n\n function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n }\n\n function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n }\n\n function powWad(int256 x, int256 y) internal pure returns (int256) {\n // Equivalent to x to the power of y because x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)\n return expWad((lnWad(x) * y) / int256(WAD)); // Using ln(x) means x must be greater than 0.\n }\n\n function expWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n // When the result is < 0.5 we return zero. This happens when\n // x <= floor(log(0.5e18) * 1e18) ~ -42e18\n if (x <= -42139678854452767551) return 0;\n\n // When the result is > (2**255 - 1) / 1e18 we can not represent it as an\n // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.\n if (x >= 135305999368893231589) revert(\"EXP_OVERFLOW\");\n\n // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96\n // for more intermediate precision and a binary basis. This base conversion\n // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.\n x = (x << 78) / 5**18;\n\n // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers\n // of two such that exp(x) = exp(x') * 2**k, where k is an integer.\n // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).\n int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96;\n x = x - k * 54916777467707473351141471128;\n\n // k is in the range [-61, 195].\n\n // Evaluate using a (6, 7)-term rational approximation.\n // p is made monic, we'll multiply by a scale factor later.\n int256 y = x + 1346386616545796478920950773328;\n y = ((y * x) >> 96) + 57155421227552351082224309758442;\n int256 p = y + x - 94201549194550492254356042504812;\n p = ((p * y) >> 96) + 28719021644029726153956944680412240;\n p = p * x + (4385272521454847904659076985693276 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n int256 q = x - 2855989394907223263936484059900;\n q = ((q * x) >> 96) + 50020603652535783019961831881945;\n q = ((q * x) >> 96) - 533845033583426703283633433725380;\n q = ((q * x) >> 96) + 3604857256930695427073651918091429;\n q = ((q * x) >> 96) - 14423608567350463180887372962807573;\n q = ((q * x) >> 96) + 26449188498355588339934803723976023;\n\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial won't have zeros in the domain as all its roots are complex.\n // No scaling is necessary because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r should be in the range (0.09, 0.25) * 2**96.\n\n // We now need to multiply r by:\n // * the scale factor s = ~6.031367120.\n // * the 2**k factor from the range reduction.\n // * the 1e18 / 2**96 factor for base conversion.\n // We do this all at once, with an intermediate result in 2**213\n // basis, so the final right shift is always by a positive amount.\n r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k));\n }\n }\n\n function lnWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n require(x > 0, \"UNDEFINED\");\n\n // We want to convert x from 10**18 fixed point to 2**96 fixed point.\n // We do this by multiplying by 2**96 / 10**18. But since\n // ln(x * C) = ln(x) + ln(C), we can simply do nothing here\n // and add ln(2**96 / 10**18) at the end.\n\n // Reduce range of x to (1, 2) * 2**96\n // ln(2^k * x) = k * ln(2) + ln(x)\n int256 k = int256(log2(uint256(x))) - 96;\n x <<= uint256(159 - k);\n x = int256(uint256(x) >> 159);\n\n // Evaluate using a (8, 8)-term rational approximation.\n // p is made monic, we will multiply by a scale factor later.\n int256 p = x + 3273285459638523848632254066296;\n p = ((p * x) >> 96) + 24828157081833163892658089445524;\n p = ((p * x) >> 96) + 43456485725739037958740375743393;\n p = ((p * x) >> 96) - 11111509109440967052023855526967;\n p = ((p * x) >> 96) - 45023709667254063763336534515857;\n p = ((p * x) >> 96) - 14706773417378608786704636184526;\n p = p * x - (795164235651350426258249787498 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n // q is monic by convention.\n int256 q = x + 5573035233440673466300451813936;\n q = ((q * x) >> 96) + 71694874799317883764090561454958;\n q = ((q * x) >> 96) + 283447036172924575727196451306956;\n q = ((q * x) >> 96) + 401686690394027663651624208769553;\n q = ((q * x) >> 96) + 204048457590392012362485061816622;\n q = ((q * x) >> 96) + 31853899698501571402653359427138;\n q = ((q * x) >> 96) + 909429971244387300277376558375;\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial is known not to have zeros in the domain.\n // No scaling required because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r is in the range (0, 0.125) * 2**96\n\n // Finalization, we need to:\n // * multiply by the scale factor s = 5.549…\n // * add ln(2**96 / 10**18)\n // * add k * ln(2)\n // * multiply by 10**18 / 2**96 = 5**18 >> 78\n\n // mul s * 5e18 * 2**96, base is now 5**18 * 2**192\n r *= 1677202110996718588342820967067443963516166;\n // add ln(2) * k * 5e18 * 2**192\n r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;\n // add ln(2**96 / 10**18) * 5e18 * 2**192\n r += 600920179829731861736702779321621459595472258049074101567377883020018308;\n // base conversion: mul 2**18 / 2**192\n r >>= 174;\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n LOW LEVEL FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function mulDivDown(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // Divide z by the denominator.\n z := div(z, denominator)\n }\n }\n\n function mulDivUp(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // First, divide z - 1 by the denominator and add 1.\n // We allow z - 1 to underflow if z is 0, because we multiply the\n // end result by 0 if z is zero, ensuring we return 0 if z is zero.\n z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))\n }\n }\n\n function rpow(\n uint256 x,\n uint256 n,\n uint256 scalar\n ) internal pure returns (uint256 z) {\n assembly {\n switch x\n case 0 {\n switch n\n case 0 {\n // 0 ** 0 = 1\n z := scalar\n }\n default {\n // 0 ** n = 0\n z := 0\n }\n }\n default {\n switch mod(n, 2)\n case 0 {\n // If n is even, store scalar in z for now.\n z := scalar\n }\n default {\n // If n is odd, store x in z for now.\n z := x\n }\n\n // Shifting right by 1 is like dividing by 2.\n let half := shr(1, scalar)\n\n for {\n // Shift n right by 1 before looping to halve it.\n n := shr(1, n)\n } n {\n // Shift n right by 1 each iteration to halve it.\n n := shr(1, n)\n } {\n // Revert immediately if x ** 2 would overflow.\n // Equivalent to iszero(eq(div(xx, x), x)) here.\n if shr(128, x) {\n revert(0, 0)\n }\n\n // Store x squared.\n let xx := mul(x, x)\n\n // Round to the nearest number.\n let xxRound := add(xx, half)\n\n // Revert if xx + half overflowed.\n if lt(xxRound, xx) {\n revert(0, 0)\n }\n\n // Set x to scaled xxRound.\n x := div(xxRound, scalar)\n\n // If n is even:\n if mod(n, 2) {\n // Compute z * x.\n let zx := mul(z, x)\n\n // If z * x overflowed:\n if iszero(eq(div(zx, x), z)) {\n // Revert if x is non-zero.\n if iszero(iszero(x)) {\n revert(0, 0)\n }\n }\n\n // Round to the nearest number.\n let zxRound := add(zx, half)\n\n // Revert if zx + half overflowed.\n if lt(zxRound, zx) {\n revert(0, 0)\n }\n\n // Return properly scaled zxRound.\n z := div(zxRound, scalar)\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n GENERAL NUMBER UTILITIES\n //////////////////////////////////////////////////////////////*/\n\n function sqrt(uint256 x) internal pure returns (uint256 z) {\n assembly {\n let y := x // We start y at x, which will help us make our initial estimate.\n\n z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n // We check y >= 2^(k + 8) but shift right by k bits\n // each branch to ensure that if x >= 256, then y >= 256.\n if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n y := shr(128, y)\n z := shl(64, z)\n }\n if iszero(lt(y, 0x1000000000000000000)) {\n y := shr(64, y)\n z := shl(32, z)\n }\n if iszero(lt(y, 0x10000000000)) {\n y := shr(32, y)\n z := shl(16, z)\n }\n if iszero(lt(y, 0x1000000)) {\n y := shr(16, y)\n z := shl(8, z)\n }\n\n // Goal was to get z*z*y within a small factor of x. More iterations could\n // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n // There is no overflow risk here since y < 2^136 after the first branch above.\n z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n\n // If x+1 is a perfect square, the Babylonian method cycles between\n // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n z := sub(z, lt(div(x, z), z))\n }\n }\n\n function log2(uint256 x) internal pure returns (uint256 r) {\n require(x > 0, \"UNDEFINED\");\n\n assembly {\n r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n r := or(r, shl(4, lt(0xffff, shr(r, x))))\n r := or(r, shl(3, lt(0xff, shr(r, x))))\n r := or(r, shl(2, lt(0xf, shr(r, x))))\n r := or(r, shl(1, lt(0x3, shr(r, x))))\n r := or(r, lt(0x1, shr(r, x)))\n }\n }\n}\n" - }, - "node_modules/ds-test/src/test.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see .\n\npragma solidity >=0.5.0;\n\ncontract DSTest {\n event log (string);\n event logs (bytes);\n\n event log_address (address);\n event log_bytes32 (bytes32);\n event log_int (int);\n event log_uint (uint);\n event log_bytes (bytes);\n event log_string (string);\n\n event log_named_address (string key, address val);\n event log_named_bytes32 (string key, bytes32 val);\n event log_named_decimal_int (string key, int val, uint decimals);\n event log_named_decimal_uint (string key, uint val, uint decimals);\n event log_named_int (string key, int val);\n event log_named_uint (string key, uint val);\n event log_named_bytes (string key, bytes val);\n event log_named_string (string key, string val);\n\n bool public IS_TEST = true;\n bool private _failed;\n\n address constant HEVM_ADDRESS =\n address(bytes20(uint160(uint256(keccak256('hevm cheat code')))));\n\n modifier mayRevert() { _; }\n modifier testopts(string memory) { _; }\n\n function failed() public returns (bool) {\n if (_failed) {\n return _failed;\n } else {\n bool globalFailed = false;\n if (hasHEVMContext()) {\n (, bytes memory retdata) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"load(address,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"))\n )\n );\n globalFailed = abi.decode(retdata, (bool));\n }\n return globalFailed;\n }\n } \n\n function fail() internal {\n if (hasHEVMContext()) {\n (bool status, ) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"store(address,bytes32,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"), bytes32(uint256(0x01)))\n )\n );\n status; // Silence compiler warnings\n }\n _failed = true;\n }\n\n function hasHEVMContext() internal view returns (bool) {\n uint256 hevmCodeSize = 0;\n assembly {\n hevmCodeSize := extcodesize(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D)\n }\n return hevmCodeSize > 0;\n }\n\n modifier logs_gas() {\n uint startGas = gasleft();\n _;\n uint endGas = gasleft();\n emit log_named_uint(\"gas\", startGas - endGas);\n }\n\n function assertTrue(bool condition) internal {\n if (!condition) {\n emit log(\"Error: Assertion Failed\");\n fail();\n }\n }\n\n function assertTrue(bool condition, string memory err) internal {\n if (!condition) {\n emit log_named_string(\"Error\", err);\n assertTrue(condition);\n }\n }\n\n function assertEq(address a, address b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [address]\");\n emit log_named_address(\" Expected\", b);\n emit log_named_address(\" Actual\", a);\n fail();\n }\n }\n function assertEq(address a, address b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes32 a, bytes32 b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bytes32]\");\n emit log_named_bytes32(\" Expected\", b);\n emit log_named_bytes32(\" Actual\", a);\n fail();\n }\n }\n function assertEq(bytes32 a, bytes32 b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq32(bytes32 a, bytes32 b) internal {\n assertEq(a, b);\n }\n function assertEq32(bytes32 a, bytes32 b, string memory err) internal {\n assertEq(a, b, err);\n }\n\n function assertEq(int a, int b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [int]\");\n emit log_named_int(\" Expected\", b);\n emit log_named_int(\" Actual\", a);\n fail();\n }\n }\n function assertEq(int a, int b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq(uint a, uint b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [uint]\");\n emit log_named_uint(\" Expected\", b);\n emit log_named_uint(\" Actual\", a);\n fail();\n }\n }\n function assertEq(uint a, uint b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEqDecimal(int a, int b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Expected\", b, decimals);\n emit log_named_decimal_int(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Expected\", b, decimals);\n emit log_named_decimal_uint(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n\n function assertGt(uint a, uint b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGt(uint a, uint b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGt(int a, int b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGt(int a, int b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGtDecimal(int a, int b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n\n function assertGe(uint a, uint b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGe(uint a, uint b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGe(int a, int b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGe(int a, int b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGeDecimal(int a, int b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertLt(uint a, uint b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLt(uint a, uint b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLt(int a, int b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLt(int a, int b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLtDecimal(int a, int b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n\n function assertLe(uint a, uint b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLe(uint a, uint b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLe(int a, int b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLe(int a, int b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLeDecimal(int a, int b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLeDecimal(a, b, decimals);\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertEq(string memory a, string memory b) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log(\"Error: a == b not satisfied [string]\");\n emit log_named_string(\" Expected\", b);\n emit log_named_string(\" Actual\", a);\n fail();\n }\n }\n function assertEq(string memory a, string memory b, string memory err) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function checkEq0(bytes memory a, bytes memory b) internal pure returns (bool ok) {\n ok = true;\n if (a.length == b.length) {\n for (uint i = 0; i < a.length; i++) {\n if (a[i] != b[i]) {\n ok = false;\n }\n }\n } else {\n ok = false;\n }\n }\n function assertEq0(bytes memory a, bytes memory b) internal {\n if (!checkEq0(a, b)) {\n emit log(\"Error: a == b not satisfied [bytes]\");\n emit log_named_bytes(\" Expected\", b);\n emit log_named_bytes(\" Actual\", a);\n fail();\n }\n }\n function assertEq0(bytes memory a, bytes memory b, string memory err) internal {\n if (!checkEq0(a, b)) {\n emit log_named_string(\"Error\", err);\n assertEq0(a, b);\n }\n }\n}\n" - }, - "node_modules/forge-std/src/Base.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {StdStorage} from \"./StdStorage.sol\";\nimport {Vm, VmSafe} from \"./Vm.sol\";\n\nabstract contract CommonBase {\n // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.\n address internal constant VM_ADDRESS = address(uint160(uint256(keccak256(\"hevm cheat code\"))));\n // console.sol and console2.sol work by executing a staticcall to this address.\n address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;\n // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38.\n address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256(\"foundry default caller\"))));\n // Address of the test contract, deployed by the DEFAULT_SENDER.\n address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;\n // Deterministic deployment address of the Multicall3 contract.\n address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11;\n\n uint256 internal constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n Vm internal constant vm = Vm(VM_ADDRESS);\n StdStorage internal stdstore;\n}\n\nabstract contract TestBase is CommonBase {}\n\nabstract contract ScriptBase is CommonBase {\n // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.\n address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;\n\n VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);\n}\n" - }, - "node_modules/forge-std/src/StdAssertions.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {DSTest} from \"ds-test/test.sol\";\nimport {stdMath} from \"./StdMath.sol\";\n\nabstract contract StdAssertions is DSTest {\n event log_array(uint256[] val);\n event log_array(int256[] val);\n event log_array(address[] val);\n event log_named_array(string key, uint256[] val);\n event log_named_array(string key, int256[] val);\n event log_named_array(string key, address[] val);\n\n function fail(string memory err) internal virtual {\n emit log_named_string(\"Error\", err);\n fail();\n }\n\n function assertFalse(bool data) internal virtual {\n assertTrue(!data);\n }\n\n function assertFalse(bool data, string memory err) internal virtual {\n assertTrue(!data, err);\n }\n\n function assertEq(bool a, bool b) internal virtual {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bool]\");\n emit log_named_string(\" Left\", a ? \"true\" : \"false\");\n emit log_named_string(\" Right\", b ? \"true\" : \"false\");\n fail();\n }\n }\n\n function assertEq(bool a, bool b, string memory err) internal virtual {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes memory a, bytes memory b) internal virtual {\n assertEq0(a, b);\n }\n\n function assertEq(bytes memory a, bytes memory b, string memory err) internal virtual {\n assertEq0(a, b, err);\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [uint[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [int[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(address[] memory a, address[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [address[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(address[] memory a, address[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n // Legacy helper\n function assertEqUint(uint256 a, uint256 b) internal virtual {\n assertEq(uint256(a), uint256(b));\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Left\", a);\n emit log_named_uint(\" Right\", b);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_decimal_uint(\" Left\", a, decimals);\n emit log_named_decimal_uint(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max Delta\", maxDelta, decimals);\n emit log_named_decimal_uint(\" Delta\", delta, decimals);\n fail();\n }\n }\n\n function assertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbsDecimal(a, b, maxDelta, decimals);\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Left\", a);\n emit log_named_int(\" Right\", b);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_decimal_int(\" Left\", a, decimals);\n emit log_named_decimal_int(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max Delta\", maxDelta, decimals);\n emit log_named_decimal_uint(\" Delta\", delta, decimals);\n fail();\n }\n }\n\n function assertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbsDecimal(a, b, maxDelta, decimals);\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%\n ) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Left\", a);\n emit log_named_uint(\" Right\", b);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n string memory err\n ) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n\n function assertApproxEqRelDecimal(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n uint256 decimals\n ) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_decimal_uint(\" Left\", a, decimals);\n emit log_named_decimal_uint(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRelDecimal(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n uint256 decimals,\n string memory err\n ) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Left\", a);\n emit log_named_int(\" Right\", b);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta, string memory err) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n\n function assertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_decimal_int(\" Left\", a, decimals);\n emit log_named_decimal_int(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);\n }\n }\n\n function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual {\n assertEqCall(target, callDataA, target, callDataB, true);\n }\n\n function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB)\n internal\n virtual\n {\n assertEqCall(targetA, callDataA, targetB, callDataB, true);\n }\n\n function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData)\n internal\n virtual\n {\n assertEqCall(target, callDataA, target, callDataB, strictRevertData);\n }\n\n function assertEqCall(\n address targetA,\n bytes memory callDataA,\n address targetB,\n bytes memory callDataB,\n bool strictRevertData\n ) internal virtual {\n (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA);\n (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB);\n\n if (successA && successB) {\n assertEq(returnDataA, returnDataB, \"Call return data does not match\");\n }\n\n if (!successA && !successB && strictRevertData) {\n assertEq(returnDataA, returnDataB, \"Call revert data does not match\");\n }\n\n if (!successA && successB) {\n emit log(\"Error: Calls were not equal\");\n emit log_named_bytes(\" Left call revert data\", returnDataA);\n emit log_named_bytes(\" Right call return data\", returnDataB);\n fail();\n }\n\n if (successA && !successB) {\n emit log(\"Error: Calls were not equal\");\n emit log_named_bytes(\" Left call return data\", returnDataA);\n emit log_named_bytes(\" Right call revert data\", returnDataB);\n fail();\n }\n }\n}\n" - }, - "node_modules/forge-std/src/StdChains.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n/**\n * StdChains provides information about EVM compatible chains that can be used in scripts/tests.\n * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are\n * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of\n * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the\n * alias used in this contract, which can be found as the first argument to the\n * `setChainWithDefaultRpcUrl` call in the `initialize` function.\n *\n * There are two main ways to use this contract:\n * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or\n * `setChain(string memory chainAlias, Chain memory chain)`\n * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.\n *\n * The first time either of those are used, chains are initialized with the default set of RPC URLs.\n * This is done in `initialize`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in\n * `defaultRpcUrls`.\n *\n * The `setChain` function is straightforward, and it simply saves off the given chain data.\n *\n * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say\n * we want to retrieve `mainnet`'s RPC URL:\n * - If you haven't set any mainnet chain info with `setChain`, you haven't specified that\n * chain in `foundry.toml` and no env var is set, the default data and RPC URL will be returned.\n * - If you have set a mainnet RPC URL in `foundry.toml` it will return that, if valid (e.g. if\n * a URL is given or if an environment variable is given and that environment variable exists).\n * Otherwise, the default data is returned.\n * - If you specified data with `setChain` it will return that.\n *\n * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults.\n */\nabstract contract StdChains {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private initialized;\n\n struct ChainData {\n string name;\n uint256 chainId;\n string rpcUrl;\n }\n\n struct Chain {\n // The chain name.\n string name;\n // The chain's Chain ID.\n uint256 chainId;\n // The chain's alias. (i.e. what gets specified in `foundry.toml`).\n string chainAlias;\n // A default RPC endpoint for this chain.\n // NOTE: This default RPC URL is included for convenience to facilitate quick tests and\n // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy\n // usage as you will be throttled and this is a disservice to others who need this endpoint.\n string rpcUrl;\n }\n\n // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.\n mapping(string => Chain) private chains;\n // Maps from the chain's alias to it's default RPC URL.\n mapping(string => string) private defaultRpcUrls;\n // Maps from a chain ID to it's alias.\n mapping(uint256 => string) private idToAlias;\n\n bool private fallbackToDefaultRpcUrls = true;\n\n // The RPC URL will be fetched from config or defaultRpcUrls if possible.\n function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {\n require(bytes(chainAlias).length != 0, \"StdChains getChain(string): Chain alias cannot be the empty string.\");\n\n initialize();\n chain = chains[chainAlias];\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(string): Chain with alias \\\"\", chainAlias, \"\\\" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {\n require(chainId != 0, \"StdChains getChain(uint256): Chain ID cannot be 0.\");\n initialize();\n string memory chainAlias = idToAlias[chainId];\n\n chain = chains[chainAlias];\n\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(uint256): Chain with ID \", vm.toString(chainId), \" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n // set chain info, with priority to argument's rpcUrl field.\n function setChain(string memory chainAlias, ChainData memory chain) internal virtual {\n require(\n bytes(chainAlias).length != 0,\n \"StdChains setChain(string,ChainData): Chain alias cannot be the empty string.\"\n );\n\n require(chain.chainId != 0, \"StdChains setChain(string,ChainData): Chain ID cannot be 0.\");\n\n initialize();\n string memory foundAlias = idToAlias[chain.chainId];\n\n require(\n bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)),\n string(\n abi.encodePacked(\n \"StdChains setChain(string,ChainData): Chain ID \",\n vm.toString(chain.chainId),\n \" already used by \\\"\",\n foundAlias,\n \"\\\".\"\n )\n )\n );\n\n uint256 oldChainId = chains[chainAlias].chainId;\n delete idToAlias[oldChainId];\n\n chains[chainAlias] =\n Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});\n idToAlias[chain.chainId] = chainAlias;\n }\n\n // set chain info, with priority to argument's rpcUrl field.\n function setChain(string memory chainAlias, Chain memory chain) internal virtual {\n setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));\n }\n\n function _toUpper(string memory str) private pure returns (string memory) {\n bytes memory strb = bytes(str);\n bytes memory copy = new bytes(strb.length);\n for (uint256 i = 0; i < strb.length; i++) {\n bytes1 b = strb[i];\n if (b >= 0x61 && b <= 0x7A) {\n copy[i] = bytes1(uint8(b) - 32);\n } else {\n copy[i] = b;\n }\n }\n return string(copy);\n }\n\n // lookup rpcUrl, in descending order of priority:\n // current -> config (foundry.toml) -> environment variable -> default\n function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) private returns (Chain memory) {\n if (bytes(chain.rpcUrl).length == 0) {\n try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {\n chain.rpcUrl = configRpcUrl;\n } catch (bytes memory err) {\n string memory envName = string(abi.encodePacked(_toUpper(chainAlias), \"_RPC_URL\"));\n if (fallbackToDefaultRpcUrls) {\n chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]);\n } else {\n chain.rpcUrl = vm.envString(envName);\n }\n // distinguish 'not found' from 'cannot read'\n bytes memory notFoundError =\n abi.encodeWithSignature(\"CheatCodeError\", string(abi.encodePacked(\"invalid rpc url \", chainAlias)));\n if (keccak256(notFoundError) != keccak256(err) || bytes(chain.rpcUrl).length == 0) {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, err), mload(err))\n }\n }\n }\n }\n return chain;\n }\n\n function setFallbackToDefaultRpcUrls(bool useDefault) internal {\n fallbackToDefaultRpcUrls = useDefault;\n }\n\n function initialize() private {\n if (initialized) return;\n\n initialized = true;\n\n // If adding an RPC here, make sure to test the default RPC URL in `testRpcs`\n setChainWithDefaultRpcUrl(\"anvil\", ChainData(\"Anvil\", 31337, \"http://127.0.0.1:8545\"));\n setChainWithDefaultRpcUrl(\n \"mainnet\", ChainData(\"Mainnet\", 1, \"https://mainnet.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\n \"goerli\", ChainData(\"Goerli\", 5, \"https://goerli.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\n \"sepolia\", ChainData(\"Sepolia\", 11155111, \"https://sepolia.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\"optimism\", ChainData(\"Optimism\", 10, \"https://mainnet.optimism.io\"));\n setChainWithDefaultRpcUrl(\"optimism_goerli\", ChainData(\"Optimism Goerli\", 420, \"https://goerli.optimism.io\"));\n setChainWithDefaultRpcUrl(\"arbitrum_one\", ChainData(\"Arbitrum One\", 42161, \"https://arb1.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\n \"arbitrum_one_goerli\", ChainData(\"Arbitrum One Goerli\", 421613, \"https://goerli-rollup.arbitrum.io/rpc\")\n );\n setChainWithDefaultRpcUrl(\"arbitrum_nova\", ChainData(\"Arbitrum Nova\", 42170, \"https://nova.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\"polygon\", ChainData(\"Polygon\", 137, \"https://polygon-rpc.com\"));\n setChainWithDefaultRpcUrl(\n \"polygon_mumbai\", ChainData(\"Polygon Mumbai\", 80001, \"https://rpc-mumbai.maticvigil.com\")\n );\n setChainWithDefaultRpcUrl(\"avalanche\", ChainData(\"Avalanche\", 43114, \"https://api.avax.network/ext/bc/C/rpc\"));\n setChainWithDefaultRpcUrl(\n \"avalanche_fuji\", ChainData(\"Avalanche Fuji\", 43113, \"https://api.avax-test.network/ext/bc/C/rpc\")\n );\n setChainWithDefaultRpcUrl(\n \"bnb_smart_chain\", ChainData(\"BNB Smart Chain\", 56, \"https://bsc-dataseed1.binance.org\")\n );\n setChainWithDefaultRpcUrl(\n \"bnb_smart_chain_testnet\",\n ChainData(\"BNB Smart Chain Testnet\", 97, \"https://rpc.ankr.com/bsc_testnet_chapel\")\n );\n setChainWithDefaultRpcUrl(\"gnosis_chain\", ChainData(\"Gnosis Chain\", 100, \"https://rpc.gnosischain.com\"));\n }\n\n // set chain info, with priority to chainAlias' rpc url in foundry.toml\n function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {\n string memory rpcUrl = chain.rpcUrl;\n defaultRpcUrls[chainAlias] = rpcUrl;\n chain.rpcUrl = \"\";\n setChain(chainAlias, chain);\n chain.rpcUrl = rpcUrl; // restore argument\n }\n}\n" - }, - "node_modules/forge-std/src/StdCheats.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {Vm} from \"./Vm.sol\";\n\nabstract contract StdCheatsSafe {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private gasMeteringOff;\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawTx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n // json value name = function\n string functionSig;\n bytes32 hash;\n // json value name = tx\n RawTx1559Detail txDetail;\n // json value name = type\n string opcode;\n }\n\n struct RawTx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n bytes gas;\n bytes nonce;\n address to;\n bytes txType;\n bytes value;\n }\n\n struct Tx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n bytes32 hash;\n Tx1559Detail txDetail;\n string opcode;\n }\n\n struct Tx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n uint256 gas;\n uint256 nonce;\n address to;\n uint256 txType;\n uint256 value;\n }\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct TxLegacy {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n string hash;\n string opcode;\n TxDetailLegacy transaction;\n }\n\n struct TxDetailLegacy {\n AccessList[] accessList;\n uint256 chainId;\n bytes data;\n address from;\n uint256 gas;\n uint256 gasPrice;\n bytes32 hash;\n uint256 nonce;\n bytes1 opcode;\n bytes32 r;\n bytes32 s;\n uint256 txType;\n address to;\n uint8 v;\n uint256 value;\n }\n\n struct AccessList {\n address accessAddress;\n bytes32[] storageKeys;\n }\n\n // Data structures to parse Receipt objects from the broadcast artifact.\n // The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawReceipt {\n bytes32 blockHash;\n bytes blockNumber;\n address contractAddress;\n bytes cumulativeGasUsed;\n bytes effectiveGasPrice;\n address from;\n bytes gasUsed;\n RawReceiptLog[] logs;\n bytes logsBloom;\n bytes status;\n address to;\n bytes32 transactionHash;\n bytes transactionIndex;\n }\n\n struct Receipt {\n bytes32 blockHash;\n uint256 blockNumber;\n address contractAddress;\n uint256 cumulativeGasUsed;\n uint256 effectiveGasPrice;\n address from;\n uint256 gasUsed;\n ReceiptLog[] logs;\n bytes logsBloom;\n uint256 status;\n address to;\n bytes32 transactionHash;\n uint256 transactionIndex;\n }\n\n // Data structures to parse the entire broadcast artifact, assuming the\n // transactions conform to EIP1559.\n\n struct EIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n Receipt[] receipts;\n uint256 timestamp;\n Tx1559[] transactions;\n TxReturn[] txReturns;\n }\n\n struct RawEIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n RawReceipt[] receipts;\n TxReturn[] txReturns;\n uint256 timestamp;\n RawTx1559[] transactions;\n }\n\n struct RawReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n bytes blockNumber;\n bytes data;\n bytes logIndex;\n bool removed;\n bytes32[] topics;\n bytes32 transactionHash;\n bytes transactionIndex;\n bytes transactionLogIndex;\n }\n\n struct ReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n uint256 blockNumber;\n bytes data;\n uint256 logIndex;\n bytes32[] topics;\n uint256 transactionIndex;\n uint256 transactionLogIndex;\n bool removed;\n }\n\n struct TxReturn {\n string internalType;\n string value;\n }\n\n function assumeNoPrecompiles(address addr) internal virtual {\n // Assembly required since `block.chainid` was introduced in 0.8.0.\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n assumeNoPrecompiles(addr, chainId);\n }\n\n function assumeNoPrecompiles(address addr, uint256 chainId) internal pure virtual {\n // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific\n // address), but the same rationale for excluding them applies so we include those too.\n\n // These should be present on all EVM-compatible chains.\n vm.assume(addr < address(0x1) || addr > address(0x9));\n\n // forgefmt: disable-start\n if (chainId == 10 || chainId == 420) {\n // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21\n vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));\n } else if (chainId == 42161 || chainId == 421613) {\n // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains\n vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));\n } else if (chainId == 43114 || chainId == 43113) {\n // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59\n vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));\n vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));\n vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));\n }\n // forgefmt: disable-end\n }\n\n function readEIP1559ScriptArtifact(string memory path)\n internal\n view\n virtual\n returns (EIP1559ScriptArtifact memory)\n {\n string memory data = vm.readFile(path);\n bytes memory parsedData = vm.parseJson(data);\n RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));\n EIP1559ScriptArtifact memory artifact;\n artifact.libraries = rawArtifact.libraries;\n artifact.path = rawArtifact.path;\n artifact.timestamp = rawArtifact.timestamp;\n artifact.pending = rawArtifact.pending;\n artifact.txReturns = rawArtifact.txReturns;\n artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);\n artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);\n return artifact;\n }\n\n function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {\n Tx1559[] memory txs = new Tx1559[](rawTxs.length);\n for (uint256 i; i < rawTxs.length; i++) {\n txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);\n }\n return txs;\n }\n\n function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {\n Tx1559 memory transaction;\n transaction.arguments = rawTx.arguments;\n transaction.contractName = rawTx.contractName;\n transaction.functionSig = rawTx.functionSig;\n transaction.hash = rawTx.hash;\n transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);\n transaction.opcode = rawTx.opcode;\n return transaction;\n }\n\n function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)\n internal\n pure\n virtual\n returns (Tx1559Detail memory)\n {\n Tx1559Detail memory txDetail;\n txDetail.data = rawDetail.data;\n txDetail.from = rawDetail.from;\n txDetail.to = rawDetail.to;\n txDetail.nonce = _bytesToUint(rawDetail.nonce);\n txDetail.txType = _bytesToUint(rawDetail.txType);\n txDetail.value = _bytesToUint(rawDetail.value);\n txDetail.gas = _bytesToUint(rawDetail.gas);\n txDetail.accessList = rawDetail.accessList;\n return txDetail;\n }\n\n function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".transactions\");\n RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));\n return rawToConvertedEIPTx1559s(rawTxs);\n }\n\n function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".transactions[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));\n return rawToConvertedEIPTx1559(rawTx);\n }\n\n // Analogous to readTransactions, but for receipts.\n function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".receipts\");\n RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));\n return rawToConvertedReceipts(rawReceipts);\n }\n\n function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".receipts[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));\n return rawToConvertedReceipt(rawReceipt);\n }\n\n function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {\n Receipt[] memory receipts = new Receipt[](rawReceipts.length);\n for (uint256 i; i < rawReceipts.length; i++) {\n receipts[i] = rawToConvertedReceipt(rawReceipts[i]);\n }\n return receipts;\n }\n\n function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {\n Receipt memory receipt;\n receipt.blockHash = rawReceipt.blockHash;\n receipt.to = rawReceipt.to;\n receipt.from = rawReceipt.from;\n receipt.contractAddress = rawReceipt.contractAddress;\n receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);\n receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);\n receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);\n receipt.status = _bytesToUint(rawReceipt.status);\n receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);\n receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);\n receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);\n receipt.logsBloom = rawReceipt.logsBloom;\n receipt.transactionHash = rawReceipt.transactionHash;\n return receipt;\n }\n\n function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)\n internal\n pure\n virtual\n returns (ReceiptLog[] memory)\n {\n ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);\n for (uint256 i; i < rawLogs.length; i++) {\n logs[i].logAddress = rawLogs[i].logAddress;\n logs[i].blockHash = rawLogs[i].blockHash;\n logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);\n logs[i].data = rawLogs[i].data;\n logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);\n logs[i].topics = rawLogs[i].topics;\n logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);\n logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);\n logs[i].removed = rawLogs[i].removed;\n }\n return logs;\n }\n\n // Deploy a contract by fetching the contract bytecode from\n // the artifacts directory\n // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`\n function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes): Deployment failed.\");\n }\n\n function deployCode(string memory what) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string): Deployment failed.\");\n }\n\n /// @dev deploy contract with value on construction\n function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes,uint256): Deployment failed.\");\n }\n\n function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,uint256): Deployment failed.\");\n }\n\n // creates a labeled address and the corresponding private key\n function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {\n privateKey = uint256(keccak256(abi.encodePacked(name)));\n addr = vm.addr(privateKey);\n vm.label(addr, name);\n }\n\n // creates a labeled address\n function makeAddr(string memory name) internal virtual returns (address addr) {\n (addr,) = makeAddrAndKey(name);\n }\n\n function deriveRememberKey(string memory mnemonic, uint32 index)\n internal\n virtual\n returns (address who, uint256 privateKey)\n {\n privateKey = vm.deriveKey(mnemonic, index);\n who = vm.rememberKey(privateKey);\n }\n\n function _bytesToUint(bytes memory b) private pure returns (uint256) {\n require(b.length <= 32, \"StdCheats _bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n function isFork() internal view virtual returns (bool status) {\n try vm.activeFork() {\n status = true;\n } catch (bytes memory) {}\n }\n\n modifier skipWhenForking() {\n if (!isFork()) {\n _;\n }\n }\n\n modifier skipWhenNotForking() {\n if (isFork()) {\n _;\n }\n }\n\n modifier noGasMetering() {\n vm.pauseGasMetering();\n // To prevent turning gas monitoring back on with nested functions that use this modifier,\n // we check if gasMetering started in the off position. If it did, we don't want to turn\n // it back on until we exit the top level function that used the modifier\n //\n // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.\n // funcA will have `gasStartedOff` as false, funcB will have it as true,\n // so we only turn metering back on at the end of the funcA\n bool gasStartedOff = gasMeteringOff;\n gasMeteringOff = true;\n\n _;\n\n // if gas metering was on when this modifier was called, turn it back on at the end\n if (!gasStartedOff) {\n gasMeteringOff = false;\n vm.resumeGasMetering();\n }\n }\n\n // a cheat for fuzzing addresses that are payable only\n // see https://github.com/foundry-rs/foundry/issues/3631\n function assumePayable(address addr) internal virtual {\n (bool success,) = payable(addr).call{value: 0}(\"\");\n vm.assume(success);\n }\n}\n\n// Wrappers around cheatcodes to avoid footguns\nabstract contract StdCheats is StdCheatsSafe {\n using stdStorage for StdStorage;\n\n StdStorage private stdstore;\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n // Skip forward or rewind time by the specified number of seconds\n function skip(uint256 time) internal virtual {\n vm.warp(block.timestamp + time);\n }\n\n function rewind(uint256 time) internal virtual {\n vm.warp(block.timestamp - time);\n }\n\n // Setup a prank from an address that has some ether\n function hoax(address msgSender) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.prank(msgSender);\n }\n\n function hoax(address msgSender, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.prank(msgSender);\n }\n\n function hoax(address msgSender, address origin) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.prank(msgSender, origin);\n }\n\n function hoax(address msgSender, address origin, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.prank(msgSender, origin);\n }\n\n // Start perpetual prank from an address that has some ether\n function startHoax(address msgSender) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.startPrank(msgSender);\n }\n\n function startHoax(address msgSender, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.startPrank(msgSender);\n }\n\n // Start perpetual prank from an address that has some ether\n // tx.origin is set to the origin parameter\n function startHoax(address msgSender, address origin) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.startPrank(msgSender, origin);\n }\n\n function startHoax(address msgSender, address origin, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.startPrank(msgSender, origin);\n }\n\n function changePrank(address msgSender) internal virtual {\n vm.stopPrank();\n vm.startPrank(msgSender);\n }\n\n function changePrank(address msgSender, address txOrigin) internal virtual {\n vm.stopPrank();\n vm.startPrank(msgSender, txOrigin);\n }\n\n // The same as Vm's `deal`\n // Use the alternative signature for ERC20 tokens\n function deal(address to, uint256 give) internal virtual {\n vm.deal(to, give);\n }\n\n // Set the balance of an account for any ERC20 token\n // Use the alternative signature to update `totalSupply`\n function deal(address token, address to, uint256 give) internal virtual {\n deal(token, to, give, false);\n }\n\n // Set the balance of an account for any ERC1155 token\n // Use the alternative signature to update `totalSupply`\n function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {\n dealERC1155(token, to, id, give, false);\n }\n\n function deal(address token, address to, uint256 give, bool adjust) internal virtual {\n // get current balance\n (, bytes memory balData) = token.call(abi.encodeWithSelector(0x70a08231, to));\n uint256 prevBal = abi.decode(balData, (uint256));\n\n // update balance\n stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);\n\n // update total supply\n if (adjust) {\n (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0x18160ddd));\n uint256 totSup = abi.decode(totSupData, (uint256));\n if (give < prevBal) {\n totSup -= (prevBal - give);\n } else {\n totSup += (give - prevBal);\n }\n stdstore.target(token).sig(0x18160ddd).checked_write(totSup);\n }\n }\n\n function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {\n // get current balance\n (, bytes memory balData) = token.call(abi.encodeWithSelector(0x00fdd58e, to, id));\n uint256 prevBal = abi.decode(balData, (uint256));\n\n // update balance\n stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);\n\n // update total supply\n if (adjust) {\n (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0xbd85b039, id));\n require(\n totSupData.length != 0,\n \"StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply.\"\n );\n uint256 totSup = abi.decode(totSupData, (uint256));\n if (give < prevBal) {\n totSup -= (prevBal - give);\n } else {\n totSup += (give - prevBal);\n }\n stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);\n }\n }\n\n function dealERC721(address token, address to, uint256 id) internal virtual {\n // check if token id is already minted and the actual owner.\n (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));\n require(successMinted, \"StdCheats deal(address,address,uint,bool): id not minted.\");\n\n // get owner current balance\n (, bytes memory fromBalData) = token.call(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));\n uint256 fromPrevBal = abi.decode(fromBalData, (uint256));\n\n // get new user current balance\n (, bytes memory toBalData) = token.call(abi.encodeWithSelector(0x70a08231, to));\n uint256 toPrevBal = abi.decode(toBalData, (uint256));\n\n // update balances\n stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);\n stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);\n\n // update owner\n stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);\n }\n}\n" - }, - "node_modules/forge-std/src/StdError.sol": { - "content": "// SPDX-License-Identifier: MIT\n// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdError {\n bytes public constant assertionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x01);\n bytes public constant arithmeticError = abi.encodeWithSignature(\"Panic(uint256)\", 0x11);\n bytes public constant divisionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x12);\n bytes public constant enumConversionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x21);\n bytes public constant encodeStorageError = abi.encodeWithSignature(\"Panic(uint256)\", 0x22);\n bytes public constant popError = abi.encodeWithSignature(\"Panic(uint256)\", 0x31);\n bytes public constant indexOOBError = abi.encodeWithSignature(\"Panic(uint256)\", 0x32);\n bytes public constant memOverflowError = abi.encodeWithSignature(\"Panic(uint256)\", 0x41);\n bytes public constant zeroVarError = abi.encodeWithSignature(\"Panic(uint256)\", 0x51);\n}\n" - }, - "node_modules/forge-std/src/StdInvariant.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\ncontract StdInvariant {\n struct FuzzSelector {\n address addr;\n bytes4[] selectors;\n }\n\n address[] private _excludedContracts;\n address[] private _excludedSenders;\n address[] private _targetedContracts;\n address[] private _targetedSenders;\n\n string[] private _excludedArtifacts;\n string[] private _targetedArtifacts;\n\n FuzzSelector[] private _targetedArtifactSelectors;\n FuzzSelector[] private _targetedSelectors;\n\n // Functions for users:\n // These are intended to be called in tests.\n\n function excludeContract(address newExcludedContract_) internal {\n _excludedContracts.push(newExcludedContract_);\n }\n\n function excludeSender(address newExcludedSender_) internal {\n _excludedSenders.push(newExcludedSender_);\n }\n\n function excludeArtifact(string memory newExcludedArtifact_) internal {\n _excludedArtifacts.push(newExcludedArtifact_);\n }\n\n function targetArtifact(string memory newTargetedArtifact_) internal {\n _targetedArtifacts.push(newTargetedArtifact_);\n }\n\n function targetArtifactSelector(FuzzSelector memory newTargetedArtifactSelector_) internal {\n _targetedArtifactSelectors.push(newTargetedArtifactSelector_);\n }\n\n function targetContract(address newTargetedContract_) internal {\n _targetedContracts.push(newTargetedContract_);\n }\n\n function targetSelector(FuzzSelector memory newTargetedSelector_) internal {\n _targetedSelectors.push(newTargetedSelector_);\n }\n\n function targetSender(address newTargetedSender_) internal {\n _targetedSenders.push(newTargetedSender_);\n }\n\n // Functions for forge:\n // These are called by forge to run invariant tests and don't need to be called in tests.\n\n function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) {\n excludedArtifacts_ = _excludedArtifacts;\n }\n\n function excludeContracts() public view returns (address[] memory excludedContracts_) {\n excludedContracts_ = _excludedContracts;\n }\n\n function excludeSenders() public view returns (address[] memory excludedSenders_) {\n excludedSenders_ = _excludedSenders;\n }\n\n function targetArtifacts() public view returns (string[] memory targetedArtifacts_) {\n targetedArtifacts_ = _targetedArtifacts;\n }\n\n function targetArtifactSelectors() public view returns (FuzzSelector[] memory targetedArtifactSelectors_) {\n targetedArtifactSelectors_ = _targetedArtifactSelectors;\n }\n\n function targetContracts() public view returns (address[] memory targetedContracts_) {\n targetedContracts_ = _targetedContracts;\n }\n\n function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) {\n targetedSelectors_ = _targetedSelectors;\n }\n\n function targetSenders() public view returns (address[] memory targetedSenders_) {\n targetedSenders_ = _targetedSenders;\n }\n}\n" - }, - "node_modules/forge-std/src/StdJson.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n// Helpers for parsing and writing JSON files\n// To parse:\n// ```\n// using stdJson for string;\n// string memory json = vm.readFile(\"some_peth\");\n// json.parseUint(\"\");\n// ```\n// To write:\n// ```\n// using stdJson for string;\n// string memory json = \"deploymentArtifact\";\n// Contract contract = new Contract();\n// json.serialize(\"contractAddress\", address(contract));\n// json = json.serialize(\"deploymentTimes\", uint(1));\n// // store the stringified JSON to the 'json' variable we have been using as a key\n// // as we won't need it any longer\n// string memory json2 = \"finalArtifact\";\n// string memory final = json2.serialize(\"depArtifact\", json);\n// final.write(\"\");\n// ```\n\nlibrary stdJson {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {\n return vm.parseJson(json, key);\n }\n\n function readUint(string memory json, string memory key) internal returns (uint256) {\n return vm.parseJsonUint(json, key);\n }\n\n function readUintArray(string memory json, string memory key) internal returns (uint256[] memory) {\n return vm.parseJsonUintArray(json, key);\n }\n\n function readInt(string memory json, string memory key) internal returns (int256) {\n return vm.parseJsonInt(json, key);\n }\n\n function readIntArray(string memory json, string memory key) internal returns (int256[] memory) {\n return vm.parseJsonIntArray(json, key);\n }\n\n function readBytes32(string memory json, string memory key) internal returns (bytes32) {\n return vm.parseJsonBytes32(json, key);\n }\n\n function readBytes32Array(string memory json, string memory key) internal returns (bytes32[] memory) {\n return vm.parseJsonBytes32Array(json, key);\n }\n\n function readString(string memory json, string memory key) internal returns (string memory) {\n return vm.parseJsonString(json, key);\n }\n\n function readStringArray(string memory json, string memory key) internal returns (string[] memory) {\n return vm.parseJsonStringArray(json, key);\n }\n\n function readAddress(string memory json, string memory key) internal returns (address) {\n return vm.parseJsonAddress(json, key);\n }\n\n function readAddressArray(string memory json, string memory key) internal returns (address[] memory) {\n return vm.parseJsonAddressArray(json, key);\n }\n\n function readBool(string memory json, string memory key) internal returns (bool) {\n return vm.parseJsonBool(json, key);\n }\n\n function readBoolArray(string memory json, string memory key) internal returns (bool[] memory) {\n return vm.parseJsonBoolArray(json, key);\n }\n\n function readBytes(string memory json, string memory key) internal returns (bytes memory) {\n return vm.parseJsonBytes(json, key);\n }\n\n function readBytesArray(string memory json, string memory key) internal returns (bytes[] memory) {\n return vm.parseJsonBytesArray(json, key);\n }\n\n function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bool[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function write(string memory jsonKey, string memory path) internal {\n vm.writeJson(jsonKey, path);\n }\n\n function write(string memory jsonKey, string memory path, string memory valueKey) internal {\n vm.writeJson(jsonKey, path, valueKey);\n }\n}\n" - }, - "node_modules/forge-std/src/StdMath.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdMath {\n int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;\n\n function abs(int256 a) internal pure returns (uint256) {\n // Required or it will fail when `a = type(int256).min`\n if (a == INT256_MIN) {\n return 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n }\n\n return uint256(a > 0 ? a : -a);\n }\n\n function delta(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a - b : b - a;\n }\n\n function delta(int256 a, int256 b) internal pure returns (uint256) {\n // a and b are of the same sign\n // this works thanks to two's complement, the left-most bit is the sign bit\n if ((a ^ b) > -1) {\n return delta(abs(a), abs(b));\n }\n\n // a and b are of opposite signs\n return abs(a) + abs(b);\n }\n\n function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n\n return absDelta * 1e18 / b;\n }\n\n function percentDelta(int256 a, int256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n uint256 absB = abs(b);\n\n return absDelta * 1e18 / absB;\n }\n}\n" - }, - "node_modules/forge-std/src/StdStorage.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {Vm} from \"./Vm.sol\";\n\nstruct StdStorage {\n mapping(address => mapping(bytes4 => mapping(bytes32 => uint256))) slots;\n mapping(address => mapping(bytes4 => mapping(bytes32 => bool))) finds;\n bytes32[] _keys;\n bytes4 _sig;\n uint256 _depth;\n address _target;\n bytes32 _set;\n}\n\nlibrary stdStorageSafe {\n event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);\n event WARNING_UninitedSlot(address who, uint256 slot);\n\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return bytes4(keccak256(bytes(sigStr)));\n }\n\n /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against\n // slot complexity:\n // if flat, will be bytes32(uint256(uint));\n // if map, will be keccak256(abi.encode(key, uint(slot)));\n // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));\n // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);\n function find(StdStorage storage self) internal returns (uint256) {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n // calldata to test against\n if (self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n vm.record();\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n (bytes32[] memory reads,) = vm.accesses(address(who));\n if (reads.length == 1) {\n bytes32 curr = vm.load(who, reads[0]);\n if (curr == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[0]));\n }\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[0]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[0]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n } else if (reads.length > 1) {\n for (uint256 i = 0; i < reads.length; i++) {\n bytes32 prev = vm.load(who, reads[i]);\n if (prev == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[i]));\n }\n // store\n vm.store(who, reads[i], bytes32(hex\"1337\"));\n bool success;\n bytes memory rdat;\n {\n (success, rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n if (success && fdat == bytes32(hex\"1337\")) {\n // we found which of the slots is the actual one\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[i]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[i]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n vm.store(who, reads[i], prev);\n break;\n }\n vm.store(who, reads[i], prev);\n }\n } else {\n revert(\"stdStorage find(StdStorage): No storage use detected for target.\");\n }\n\n require(\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))],\n \"stdStorage find(StdStorage): Slot(s) not found.\"\n );\n\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n self._target = _target;\n return self;\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n self._sig = _sig;\n return self;\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n self._sig = sigs(_sig);\n return self;\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n self._keys.push(bytes32(uint256(uint160(who))));\n return self;\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n self._keys.push(bytes32(amt));\n return self;\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n self._keys.push(key);\n return self;\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n self._depth = _depth;\n return self;\n }\n\n function read(StdStorage storage self) private returns (bytes memory) {\n address t = self._target;\n uint256 s = find(self);\n return abi.encode(vm.load(t, bytes32(s)));\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return abi.decode(read(self), (bytes32));\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n int256 v = read_int(self);\n if (v == 0) return false;\n if (v == 1) return true;\n revert(\"stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.\");\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return abi.decode(read(self), (address));\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return abi.decode(read(self), (uint256));\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return abi.decode(read(self), (int256));\n }\n\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n\nlibrary stdStorage {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return stdStorageSafe.sigs(sigStr);\n }\n\n function find(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.find(self);\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n return stdStorageSafe.target(self, _target);\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, who);\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, amt);\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, key);\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n return stdStorageSafe.depth(self, _depth);\n }\n\n function checked_write(StdStorage storage self, address who) internal {\n checked_write(self, bytes32(uint256(uint160(who))));\n }\n\n function checked_write(StdStorage storage self, uint256 amt) internal {\n checked_write(self, bytes32(amt));\n }\n\n function checked_write(StdStorage storage self, bool write) internal {\n bytes32 t;\n /// @solidity memory-safe-assembly\n assembly {\n t := write\n }\n checked_write(self, t);\n }\n\n function checked_write(StdStorage storage self, bytes32 set) internal {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n if (!self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n find(self);\n }\n bytes32 slot = bytes32(self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]);\n\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n bytes32 curr = vm.load(who, slot);\n\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n vm.store(who, slot, set);\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return stdStorageSafe.read_bytes32(self);\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n return stdStorageSafe.read_bool(self);\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return stdStorageSafe.read_address(self);\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.read_uint(self);\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return stdStorageSafe.read_int(self);\n }\n\n // Private function so needs to be copied over\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n // Private function so needs to be copied over\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n" - }, - "node_modules/forge-std/src/StdStyle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nimport {Vm} from \"./Vm.sol\";\n\nlibrary StdStyle {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n string constant RED = \"\\u001b[91m\";\n string constant GREEN = \"\\u001b[92m\";\n string constant YELLOW = \"\\u001b[93m\";\n string constant BLUE = \"\\u001b[94m\";\n string constant MAGENTA = \"\\u001b[95m\";\n string constant CYAN = \"\\u001b[96m\";\n string constant BOLD = \"\\u001b[1m\";\n string constant DIM = \"\\u001b[2m\";\n string constant ITALIC = \"\\u001b[3m\";\n string constant UNDERLINE = \"\\u001b[4m\";\n string constant INVERSE = \"\\u001b[7m\";\n string constant RESET = \"\\u001b[0m\";\n\n function styleConcat(string memory style, string memory self) private pure returns (string memory) {\n return string(abi.encodePacked(style, self, RESET));\n }\n\n function red(string memory self) internal pure returns (string memory) {\n return styleConcat(RED, self);\n }\n\n function red(uint256 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(int256 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(address self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(bool self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function redBytes(bytes memory self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function redBytes32(bytes32 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function green(string memory self) internal pure returns (string memory) {\n return styleConcat(GREEN, self);\n }\n\n function green(uint256 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(int256 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(address self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(bool self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function greenBytes(bytes memory self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function greenBytes32(bytes32 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function yellow(string memory self) internal pure returns (string memory) {\n return styleConcat(YELLOW, self);\n }\n\n function yellow(uint256 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(int256 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(address self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(bool self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellowBytes(bytes memory self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellowBytes32(bytes32 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function blue(string memory self) internal pure returns (string memory) {\n return styleConcat(BLUE, self);\n }\n\n function blue(uint256 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(int256 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(address self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(bool self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blueBytes(bytes memory self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blueBytes32(bytes32 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function magenta(string memory self) internal pure returns (string memory) {\n return styleConcat(MAGENTA, self);\n }\n\n function magenta(uint256 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(int256 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(address self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(bool self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magentaBytes(bytes memory self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magentaBytes32(bytes32 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function cyan(string memory self) internal pure returns (string memory) {\n return styleConcat(CYAN, self);\n }\n\n function cyan(uint256 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(int256 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(address self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(bool self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyanBytes(bytes memory self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyanBytes32(bytes32 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function bold(string memory self) internal pure returns (string memory) {\n return styleConcat(BOLD, self);\n }\n\n function bold(uint256 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(int256 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(address self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(bool self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function boldBytes(bytes memory self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function boldBytes32(bytes32 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function dim(string memory self) internal pure returns (string memory) {\n return styleConcat(DIM, self);\n }\n\n function dim(uint256 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(int256 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(address self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(bool self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dimBytes(bytes memory self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dimBytes32(bytes32 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function italic(string memory self) internal pure returns (string memory) {\n return styleConcat(ITALIC, self);\n }\n\n function italic(uint256 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(int256 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(address self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(bool self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italicBytes(bytes memory self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italicBytes32(bytes32 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function underline(string memory self) internal pure returns (string memory) {\n return styleConcat(UNDERLINE, self);\n }\n\n function underline(uint256 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(int256 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(address self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(bool self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underlineBytes(bytes memory self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underlineBytes32(bytes32 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function inverse(string memory self) internal pure returns (string memory) {\n return styleConcat(INVERSE, self);\n }\n\n function inverse(uint256 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(int256 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(address self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(bool self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverseBytes(bytes memory self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverseBytes32(bytes32 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n}\n" - }, - "node_modules/forge-std/src/StdUtils.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {IMulticall3} from \"./interfaces/IMulticall3.sol\";\n// TODO Remove import.\nimport {VmSafe} from \"./Vm.sol\";\n\nabstract contract StdUtils {\n /*//////////////////////////////////////////////////////////////////////////\n CONSTANTS\n //////////////////////////////////////////////////////////////////////////*/\n\n IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;\n uint256 private constant INT256_MIN_ABS =\n 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n uint256 private constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.\n address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;\n\n /*//////////////////////////////////////////////////////////////////////////\n INTERNAL FUNCTIONS\n //////////////////////////////////////////////////////////////////////////*/\n\n function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {\n require(min <= max, \"StdUtils bound(uint256,uint256,uint256): Max is less than min.\");\n // If x is between min and max, return x directly. This is to ensure that dictionary values\n // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188\n if (x >= min && x <= max) return x;\n\n uint256 size = max - min + 1;\n\n // If the value is 0, 1, 2, 3, warp that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.\n // This helps ensure coverage of the min/max values.\n if (x <= 3 && size > x) return min + x;\n if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);\n\n // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.\n if (x > max) {\n uint256 diff = x - max;\n uint256 rem = diff % size;\n if (rem == 0) return max;\n result = min + rem - 1;\n } else if (x < min) {\n uint256 diff = min - x;\n uint256 rem = diff % size;\n if (rem == 0) return min;\n result = max - rem + 1;\n }\n }\n\n function bound(uint256 x, uint256 min, uint256 max) internal view virtual returns (uint256 result) {\n result = _bound(x, min, max);\n console2_log(\"Bound Result\", result);\n }\n\n function bound(int256 x, int256 min, int256 max) internal view virtual returns (int256 result) {\n require(min <= max, \"StdUtils bound(int256,int256,int256): Max is less than min.\");\n\n // Shifting all int256 values to uint256 to use _bound function. The range of two types are:\n // int256 : -(2**255) ~ (2**255 - 1)\n // uint256: 0 ~ (2**256 - 1)\n // So, add 2**255, INT256_MIN_ABS to the integer values.\n //\n // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.\n // So, use `~uint256(x) + 1` instead.\n uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);\n uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);\n uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);\n\n uint256 y = _bound(_x, _min, _max);\n\n // To move it back to int256 value, subtract INT256_MIN_ABS at here.\n result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);\n console2_log(\"Bound result\", vm.toString(result));\n }\n\n function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {\n require(b.length <= 32, \"StdUtils bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce\n /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)\n function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {\n // forgefmt: disable-start\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))));\n if (nonce <= 0x7f) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))));\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= 2**8 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce))));\n if (nonce <= 2**16 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce))));\n if (nonce <= 2**24 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce))));\n // forgefmt: disable-end\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return addressFromLast20Bytes(\n keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce)))\n );\n }\n\n function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)\n internal\n pure\n virtual\n returns (address)\n {\n return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, initcodeHash)));\n }\n\n /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer\n function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {\n return computeCreate2Address(salt, initCodeHash, CREATE2_FACTORY);\n }\n\n /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments\n /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode\n function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {\n return hashInitCode(creationCode, \"\");\n }\n\n /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2\n /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode\n /// @param args the ABI-encoded arguments to the constructor of C\n function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(creationCode, args));\n }\n\n // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.\n function getTokenBalances(address token, address[] memory addresses)\n internal\n virtual\n returns (uint256[] memory balances)\n {\n uint256 tokenCodeSize;\n assembly {\n tokenCodeSize := extcodesize(token)\n }\n require(tokenCodeSize > 0, \"StdUtils getTokenBalances(address,address[]): Token address is not a contract.\");\n\n // ABI encode the aggregate call to Multicall3.\n uint256 length = addresses.length;\n IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);\n for (uint256 i = 0; i < length; ++i) {\n // 0x70a08231 = bytes4(\"balanceOf(address)\"))\n calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});\n }\n\n // Make the aggregate call.\n (, bytes[] memory returnData) = multicall.aggregate(calls);\n\n // ABI decode the return data and return the balances.\n balances = new uint256[](length);\n for (uint256 i = 0; i < length; ++i) {\n balances[i] = abi.decode(returnData[i], (uint256));\n }\n }\n\n /*//////////////////////////////////////////////////////////////////////////\n PRIVATE FUNCTIONS\n //////////////////////////////////////////////////////////////////////////*/\n\n function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.\n\n function console2_log(string memory p0, uint256 p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n status;\n }\n\n function console2_log(string memory p0, string memory p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n status;\n }\n}\n" - }, - "node_modules/forge-std/src/Test.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\n// 💬 ABOUT\n// Standard Library's default Test\n\n// 🧩 MODULES\nimport {console} from \"./console.sol\";\nimport {console2} from \"./console2.sol\";\nimport {StdAssertions} from \"./StdAssertions.sol\";\nimport {StdChains} from \"./StdChains.sol\";\nimport {StdCheats} from \"./StdCheats.sol\";\nimport {stdError} from \"./StdError.sol\";\nimport {StdInvariant} from \"./StdInvariant.sol\";\nimport {stdJson} from \"./StdJson.sol\";\nimport {stdMath} from \"./StdMath.sol\";\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {StdUtils} from \"./StdUtils.sol\";\nimport {Vm} from \"./Vm.sol\";\nimport {StdStyle} from \"./StdStyle.sol\";\n\n// 📦 BOILERPLATE\nimport {TestBase} from \"./Base.sol\";\nimport {DSTest} from \"ds-test/test.sol\";\n\n// ⭐️ TEST\nabstract contract Test is DSTest, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils, TestBase {\n// Note: IS_TEST() must return true.\n// Note: Must have failure system, https://github.com/dapphub/ds-test/blob/cd98eff28324bfac652e63a239a60632a761790b/src/test.sol#L39-L76.\n}\n" - }, - "node_modules/forge-std/src/Vm.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\n// Cheatcodes are marked as view/pure/none using the following rules:\n// 0. A call's observable behaviour includes its return value, logs, reverts and state writes,\n// 1. If you can influence a later call's observable behaviour, you're neither `view` nor `pure (you are modifying some state be it the EVM, interpreter, filesystem, etc),\n// 2. Otherwise if you can be influenced by an earlier call, or if reading some state, you're `view`,\n// 3. Otherwise you're `pure`.\n\ninterface VmSafe {\n struct Log {\n bytes32[] topics;\n bytes data;\n address emitter;\n }\n\n struct Rpc {\n string key;\n string url;\n }\n\n struct FsMetadata {\n bool isDir;\n bool isSymlink;\n uint256 length;\n bool readOnly;\n uint256 modified;\n uint256 accessed;\n uint256 created;\n }\n\n // Loads a storage slot from an address\n function load(address target, bytes32 slot) external view returns (bytes32 data);\n // Signs data\n function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);\n // Gets the address for a given private key\n function addr(uint256 privateKey) external pure returns (address keyAddr);\n // Gets the nonce of an account\n function getNonce(address account) external view returns (uint64 nonce);\n // Performs a foreign function call via the terminal\n function ffi(string[] calldata commandInput) external returns (bytes memory result);\n // Sets environment variables\n function setEnv(string calldata name, string calldata value) external;\n // Reads environment variables, (name) => (value)\n function envBool(string calldata name) external view returns (bool value);\n function envUint(string calldata name) external view returns (uint256 value);\n function envInt(string calldata name) external view returns (int256 value);\n function envAddress(string calldata name) external view returns (address value);\n function envBytes32(string calldata name) external view returns (bytes32 value);\n function envString(string calldata name) external view returns (string memory value);\n function envBytes(string calldata name) external view returns (bytes memory value);\n // Reads environment variables as arrays\n function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);\n function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);\n function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);\n function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);\n function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);\n function envString(string calldata name, string calldata delim) external view returns (string[] memory value);\n function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);\n // Read environment variables with default value\n function envOr(string calldata name, bool defaultValue) external returns (bool value);\n function envOr(string calldata name, uint256 defaultValue) external returns (uint256 value);\n function envOr(string calldata name, int256 defaultValue) external returns (int256 value);\n function envOr(string calldata name, address defaultValue) external returns (address value);\n function envOr(string calldata name, bytes32 defaultValue) external returns (bytes32 value);\n function envOr(string calldata name, string calldata defaultValue) external returns (string memory value);\n function envOr(string calldata name, bytes calldata defaultValue) external returns (bytes memory value);\n // Read environment variables as arrays with default value\n function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)\n external\n returns (bool[] memory value);\n function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)\n external\n returns (uint256[] memory value);\n function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)\n external\n returns (int256[] memory value);\n function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)\n external\n returns (address[] memory value);\n function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)\n external\n returns (bytes32[] memory value);\n function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)\n external\n returns (string[] memory value);\n function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)\n external\n returns (bytes[] memory value);\n // Records all storage reads and writes\n function record() external;\n // Gets all accessed reads and write slot from a recording session, for a given address\n function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);\n // Gets the _creation_ bytecode from an artifact file. Takes in the relative path to the json file\n function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);\n // Gets the _deployed_ bytecode from an artifact file. Takes in the relative path to the json file\n function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);\n // Labels an address in call traces\n function label(address account, string calldata newLabel) external;\n // Using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain\n function broadcast() external;\n // Has the next call (at this call depth only) create a transaction with the address provided as the sender that can later be signed and sent onchain\n function broadcast(address signer) external;\n // Has the next call (at this call depth only) create a transaction with the private key provided as the sender that can later be signed and sent onchain\n function broadcast(uint256 privateKey) external;\n // Using the address that calls the test contract, has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain\n function startBroadcast() external;\n // Has all subsequent calls (at this call depth only) create transactions with the address provided that can later be signed and sent onchain\n function startBroadcast(address signer) external;\n // Has all subsequent calls (at this call depth only) create transactions with the private key provided that can later be signed and sent onchain\n function startBroadcast(uint256 privateKey) external;\n // Stops collecting onchain transactions\n function stopBroadcast() external;\n // Reads the entire content of file to string\n function readFile(string calldata path) external view returns (string memory data);\n // Reads the entire content of file as binary. Path is relative to the project root.\n function readFileBinary(string calldata path) external view returns (bytes memory data);\n // Get the path of the current project root\n function projectRoot() external view returns (string memory path);\n // Get the metadata for a file/directory\n function fsMetadata(string calldata fileOrDir) external returns (FsMetadata memory metadata);\n // Reads next line of file to string\n function readLine(string calldata path) external view returns (string memory line);\n // Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.\n function writeFile(string calldata path, string calldata data) external;\n // Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.\n // Path is relative to the project root.\n function writeFileBinary(string calldata path, bytes calldata data) external;\n // Writes line to file, creating a file if it does not exist.\n function writeLine(string calldata path, string calldata data) external;\n // Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.\n function closeFile(string calldata path) external;\n // Removes file. This cheatcode will revert in the following situations, but is not limited to just these cases:\n // - Path points to a directory.\n // - The file doesn't exist.\n // - The user lacks permissions to remove the file.\n function removeFile(string calldata path) external;\n // Convert values to a string\n function toString(address value) external pure returns (string memory stringifiedValue);\n function toString(bytes calldata value) external pure returns (string memory stringifiedValue);\n function toString(bytes32 value) external pure returns (string memory stringifiedValue);\n function toString(bool value) external pure returns (string memory stringifiedValue);\n function toString(uint256 value) external pure returns (string memory stringifiedValue);\n function toString(int256 value) external pure returns (string memory stringifiedValue);\n // Convert values from a string\n function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);\n function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);\n function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);\n function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);\n function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);\n function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);\n // Record all the transaction logs\n function recordLogs() external;\n // Gets all the recorded logs\n function getRecordedLogs() external returns (Log[] memory logs);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path m/44'/60'/0'/0/{index}\n function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at {derivationPath}{index}\n function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)\n external\n pure\n returns (uint256 privateKey);\n // Adds a private key to the local forge wallet and returns the address\n function rememberKey(uint256 privateKey) external returns (address keyAddr);\n //\n // parseJson\n //\n // ----\n // In case the returned value is a JSON object, it's encoded as a ABI-encoded tuple. As JSON objects\n // don't have the notion of ordered, but tuples do, they JSON object is encoded with it's fields ordered in\n // ALPHABETICAL order. That means that in order to successfully decode the tuple, we need to define a tuple that\n // encodes the fields in the same order, which is alphabetical. In the case of Solidity structs, they are encoded\n // as tuples, with the attributes in the order in which they are defined.\n // For example: json = { 'a': 1, 'b': 0xa4tb......3xs}\n // a: uint256\n // b: address\n // To decode that json, we need to define a struct or a tuple as follows:\n // struct json = { uint256 a; address b; }\n // If we defined a json struct with the opposite order, meaning placing the address b first, it would try to\n // decode the tuple in that order, and thus fail.\n // ----\n // Given a string of JSON, return it as ABI-encoded\n function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);\n function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);\n\n // The following parseJson cheatcodes will do type coercion, for the type that they indicate.\n // For example, parseJsonUint will coerce all values to a uint256. That includes stringified numbers '12'\n // and hex numbers '0xEF'.\n // Type coercion works ONLY for discrete values or arrays. That means that the key must return a value or array, not\n // a JSON object.\n function parseJsonUint(string calldata, string calldata) external returns (uint256);\n function parseJsonUintArray(string calldata, string calldata) external returns (uint256[] memory);\n function parseJsonInt(string calldata, string calldata) external returns (int256);\n function parseJsonIntArray(string calldata, string calldata) external returns (int256[] memory);\n function parseJsonBool(string calldata, string calldata) external returns (bool);\n function parseJsonBoolArray(string calldata, string calldata) external returns (bool[] memory);\n function parseJsonAddress(string calldata, string calldata) external returns (address);\n function parseJsonAddressArray(string calldata, string calldata) external returns (address[] memory);\n function parseJsonString(string calldata, string calldata) external returns (string memory);\n function parseJsonStringArray(string calldata, string calldata) external returns (string[] memory);\n function parseJsonBytes(string calldata, string calldata) external returns (bytes memory);\n function parseJsonBytesArray(string calldata, string calldata) external returns (bytes[] memory);\n function parseJsonBytes32(string calldata, string calldata) external returns (bytes32);\n function parseJsonBytes32Array(string calldata, string calldata) external returns (bytes32[] memory);\n\n // Serialize a key and value to a JSON object stored in-memory that can be later written to a file\n // It returns the stringified version of the specific JSON file up to that moment.\n function serializeBool(string calldata objectKey, string calldata valueKey, bool value)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address value)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)\n external\n returns (string memory json);\n\n function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)\n external\n returns (string memory json);\n\n //\n // writeJson\n //\n // ----\n // Write a serialized JSON object to a file. If the file exists, it will be overwritten.\n // Let's assume we want to write the following JSON to a file:\n //\n // { \"boolean\": true, \"number\": 342, \"object\": { \"title\": \"finally json serialization\" } }\n //\n // ```\n // string memory json1 = \"some key\";\n // vm.serializeBool(json1, \"boolean\", true);\n // vm.serializeBool(json1, \"number\", uint256(342));\n // json2 = \"some other key\";\n // string memory output = vm.serializeString(json2, \"title\", \"finally json serialization\");\n // string memory finalJson = vm.serialize(json1, \"object\", output);\n // vm.writeJson(finalJson, \"./output/example.json\");\n // ```\n // The critical insight is that every invocation of serialization will return the stringified version of the JSON\n // up to that point. That means we can construct arbitrary JSON objects and then use the return stringified version\n // to serialize them as values to another JSON object.\n //\n // json1 and json2 are simply keys used by the backend to keep track of the objects. So vm.serializeJson(json1,..)\n // will find the object in-memory that is keyed by \"some key\".\n function writeJson(string calldata json, string calldata path) external;\n // Write a serialized JSON object to an **existing** JSON file, replacing a value with key = \n // This is useful to replace a specific value of a JSON file, without having to parse the entire thing\n function writeJson(string calldata json, string calldata path, string calldata valueKey) external;\n // Returns the RPC url for the given alias\n function rpcUrl(string calldata rpcAlias) external view returns (string memory json);\n // Returns all rpc urls and their aliases `[alias, url][]`\n function rpcUrls() external view returns (string[2][] memory urls);\n // Returns all rpc urls and their aliases as structs.\n function rpcUrlStructs() external view returns (Rpc[] memory urls);\n // If the condition is false, discard this run's fuzz inputs and generate new ones.\n function assume(bool condition) external pure;\n // Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.\n function pauseGasMetering() external;\n // Resumes gas metering (i.e. gas usage is counted again). Noop if already on.\n function resumeGasMetering() external;\n}\n\ninterface Vm is VmSafe {\n // Sets block.timestamp\n function warp(uint256 newTimestamp) external;\n // Sets block.height\n function roll(uint256 newHeight) external;\n // Sets block.basefee\n function fee(uint256 newBasefee) external;\n // Sets block.difficulty\n function difficulty(uint256 newDifficulty) external;\n // Sets block.chainid\n function chainId(uint256 newChainId) external;\n // Stores a value to an address' storage slot.\n function store(address target, bytes32 slot, bytes32 value) external;\n // Sets the nonce of an account; must be higher than the current nonce of the account\n function setNonce(address account, uint64 newNonce) external;\n // Sets the *next* call's msg.sender to be the input address\n function prank(address msgSender) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called\n function startPrank(address msgSender) external;\n // Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input\n function prank(address msgSender, address txOrigin) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input\n function startPrank(address msgSender, address txOrigin) external;\n // Resets subsequent calls' msg.sender to be `address(this)`\n function stopPrank() external;\n // Sets an address' balance\n function deal(address account, uint256 newBalance) external;\n // Sets an address' code\n function etch(address target, bytes calldata newRuntimeBytecode) external;\n // Expects an error on next call\n function expectRevert(bytes calldata revertData) external;\n function expectRevert(bytes4 revertData) external;\n function expectRevert() external;\n\n // Prepare an expected log with all four checks enabled.\n // Call this function, then emit an event, then call a function. Internally after the call, we check if\n // logs were emitted in the expected order with the expected topics and data.\n // Second form also checks supplied address against emitting contract.\n function expectEmit() external;\n function expectEmit(address emitter) external;\n\n // Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData).\n // Call this function, then emit an event, then call a function. Internally after the call, we check if\n // logs were emitted in the expected order with the expected topics and data (as specified by the booleans).\n // Second form also checks supplied address against emitting contract.\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)\n external;\n\n // Mocks a call to an address, returning specified data.\n // Calldata can either be strict or a partial match, e.g. if you only\n // pass a Solidity selector to the expected calldata, then the entire Solidity\n // function will be mocked.\n function mockCall(address callee, bytes calldata data, bytes calldata returnData) external;\n // Mocks a call to an address with a specific msg.value, returning specified data.\n // Calldata match takes precedence over msg.value in case of ambiguity.\n function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external;\n // Clears all mocked calls\n function clearMockedCalls() external;\n // Expects a call to an address with the specified calldata.\n // Calldata can either be a strict or a partial match\n function expectCall(address callee, bytes calldata data) external;\n // Expects a call to an address with the specified msg.value and calldata\n function expectCall(address callee, uint256 msgValue, bytes calldata data) external;\n // Expect a call to an address with the specified msg.value, gas, and calldata.\n function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external;\n // Expect a call to an address with the specified msg.value and calldata, and a *minimum* amount of gas.\n function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external;\n // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other\n // memory is written to, the test will fail. Can be called multiple times to add more ranges to the set.\n function expectSafeMemory(uint64 min, uint64 max) external;\n // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext.\n // If any other memory is written to, the test will fail. Can be called multiple times to add more ranges\n // to the set.\n function expectSafeMemoryCall(uint64 min, uint64 max) external;\n // Sets block.coinbase\n function coinbase(address newCoinbase) external;\n // Snapshot the current state of the evm.\n // Returns the id of the snapshot that was created.\n // To revert a snapshot use `revertTo`\n function snapshot() external returns (uint256 snapshotId);\n // Revert the state of the EVM to a previous snapshot\n // Takes the snapshot id to revert to.\n // This deletes the snapshot and all snapshots taken after the given snapshot id.\n function revertTo(uint256 snapshotId) external returns (bool success);\n // Creates a new fork with the given endpoint and block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before the transaction,\n // and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates _and_ also selects new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before\n // the transaction, returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.\n function selectFork(uint256 forkId) external;\n /// Returns the identifier of the currently active fork. Reverts if no fork is currently active.\n function activeFork() external view returns (uint256 forkId);\n // Updates the currently active fork to given block number\n // This is similar to `roll` but for the currently active fork\n function rollFork(uint256 blockNumber) external;\n // Updates the currently active fork to given transaction\n // this will `rollFork` with the number of the block the transaction was mined in and replays all transaction mined before it in the block\n function rollFork(bytes32 txHash) external;\n // Updates the given fork to given block number\n function rollFork(uint256 forkId, uint256 blockNumber) external;\n // Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block\n function rollFork(uint256 forkId, bytes32 txHash) external;\n // Marks that the account(s) should use persistent storage across fork swaps in a multifork setup\n // Meaning, changes made to the state of this account will be kept when switching forks\n function makePersistent(address account) external;\n function makePersistent(address account0, address account1) external;\n function makePersistent(address account0, address account1, address account2) external;\n function makePersistent(address[] calldata accounts) external;\n // Revokes persistent status from the address, previously added via `makePersistent`\n function revokePersistent(address account) external;\n function revokePersistent(address[] calldata accounts) external;\n // Returns true if the account is marked as persistent\n function isPersistent(address account) external view returns (bool persistent);\n // In forking mode, explicitly grant the given address cheatcode access\n function allowCheatcodes(address account) external;\n // Fetches the given transaction from the active fork and executes it on the current state\n function transact(bytes32 txHash) external;\n // Fetches the given transaction from the given fork and executes it on the current state\n function transact(uint256 forkId, bytes32 txHash) external;\n}\n" - }, - "node_modules/forge-std/src/console.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nlibrary console {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int)\", p0));\n }\n\n function logUint(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint)\", p0, p1));\n }\n\n function log(uint p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string)\", p0, p1));\n }\n\n function log(uint p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool)\", p0, p1));\n }\n\n function log(uint p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address)\", p0, p1));\n }\n\n function log(string memory p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - }, - "node_modules/forge-std/src/console2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\n/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should\n/// use `int256` and `uint256`. This modified version fixes that. This version is recommended\n/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in\n/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.\n/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178\nlibrary console2 {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function logUint(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function log(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint256 p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256)\", p0, p1));\n }\n\n function log(uint256 p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string)\", p0, p1));\n }\n\n function log(uint256 p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool)\", p0, p1));\n }\n\n function log(uint256 p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address)\", p0, p1));\n }\n\n function log(string memory p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n }\n\n function log(string memory p0, int256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,int256)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - }, - "node_modules/forge-std/src/interfaces/IMulticall3.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\ninterface IMulticall3 {\n struct Call {\n address target;\n bytes callData;\n }\n\n struct Call3 {\n address target;\n bool allowFailure;\n bytes callData;\n }\n\n struct Call3Value {\n address target;\n bool allowFailure;\n uint256 value;\n bytes callData;\n }\n\n struct Result {\n bool success;\n bytes returnData;\n }\n\n function aggregate(Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes[] memory returnData);\n\n function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData);\n\n function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData);\n\n function blockAndAggregate(Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);\n\n function getBasefee() external view returns (uint256 basefee);\n\n function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash);\n\n function getBlockNumber() external view returns (uint256 blockNumber);\n\n function getChainId() external view returns (uint256 chainid);\n\n function getCurrentBlockCoinbase() external view returns (address coinbase);\n\n function getCurrentBlockDifficulty() external view returns (uint256 difficulty);\n\n function getCurrentBlockGasLimit() external view returns (uint256 gaslimit);\n\n function getCurrentBlockTimestamp() external view returns (uint256 timestamp);\n\n function getEthBalance(address addr) external view returns (uint256 balance);\n\n function getLastBlockHash() external view returns (bytes32 blockHash);\n\n function tryAggregate(bool requireSuccess, Call[] calldata calls)\n external\n payable\n returns (Result[] memory returnData);\n\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);\n}\n" - } - }, - "settings": { - "remappings": [ - "@openzeppelin/=node_modules/@openzeppelin/", - "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", - "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", - "@rari-capital/=node_modules/@rari-capital/", - "@rari-capital/solmate/=node_modules/@rari-capital/solmate/", - "ds-test/=node_modules/ds-test/src/", - "forge-std/=node_modules/forge-std/src/" - ], - "optimizer": { - "enabled": true, - "runs": 999999 - }, - "metadata": { - "bytecodeHash": "none" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "storageLayout", - "devdoc", - "userdoc" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/.chainId b/packages/contracts-bedrock/deployments/mainnet/.chainId deleted file mode 100644 index 56a6051ca2b0..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/.chainId +++ /dev/null @@ -1 +0,0 @@ -1 \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/AddressManager.json b/packages/contracts-bedrock/deployments/mainnet/AddressManager.json deleted file mode 100644 index 0bb340041f27..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/AddressManager.json +++ /dev/null @@ -1,236 +0,0 @@ -{ - "address": "0xdE1FCfB0851916CA5101820A69b13a4E276bd81F", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "indexed": false, - "internalType": "address", - "name": "_newAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "_oldAddress", - "type": "address" - } - ], - "name": "AddressSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - } - ], - "name": "getAddress", - "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": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "address", - "name": "_address", - "type": "address" - } - ], - "name": "setAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x8803c67a0032b8dea6b0e3a9d2ff1708346a41a8d2945d4e84e5d81862f1cb54", - "receipt": { - "to": null, - "from": "0x9996571372066A1545D3435C6935e3F9593A7eF5", - "contractAddress": "0xdE1FCfB0851916CA5101820A69b13a4E276bd81F", - "transactionIndex": 43, - "gasUsed": "425357", - "logsBloom": "0x00800000002000000000000000000000000000000000000000800000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000001000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000040000000000000000000000000000000000000000000", - "blockHash": "0x6eeca8dcaa51370f0048dcc0569ebb0c62ba9841e5414b362aa15915c29428d1", - "transactionHash": "0x8803c67a0032b8dea6b0e3a9d2ff1708346a41a8d2945d4e84e5d81862f1cb54", - "logs": [ - { - "transactionIndex": 43, - "blockNumber": 12686687, - "transactionHash": "0x8803c67a0032b8dea6b0e3a9d2ff1708346a41a8d2945d4e84e5d81862f1cb54", - "address": "0xdE1FCfB0851916CA5101820A69b13a4E276bd81F", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000009996571372066a1545d3435c6935e3f9593a7ef5" - ], - "data": "0x", - "logIndex": 195, - "blockHash": "0x6eeca8dcaa51370f0048dcc0569ebb0c62ba9841e5414b362aa15915c29428d1" - } - ], - "blockNumber": 12686687, - "cumulativeGasUsed": "6131161", - "status": 1, - "byzantium": true - }, - "args": [], - "solcInputHash": "ef3f334bac4d7e77d91b457a0d89ab0a", - "metadata": "{\"compiler\":{\"version\":\"0.7.6+commit.7338295f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_newAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_oldAddress\",\"type\":\"address\"}],\"name\":\"AddressSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"getAddress\",\"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\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getAddress(string)\":{\"params\":{\"_name\":\"Name to retrieve an address for.\"},\"returns\":{\"_0\":\"Address associated with the given name.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAddress(string,address)\":{\"params\":{\"_address\":\"Address to associate with the name.\",\"_name\":\"String name to associate an address with.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"title\":\"Lib_AddressManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getAddress(string)\":{\"notice\":\"Retrieves the address associated with a given name.\"},\"setAddress(string,address)\":{\"notice\":\"Changes the address associated with a particular name.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/optimistic-ethereum/libraries/resolver/Lib_AddressManager.sol\":\"Lib_AddressManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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 () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), 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 emit OwnershipTransferred(_owner, address(0));\\n _owner = 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 emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/optimistic-ethereum/libraries/resolver/Lib_AddressManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >0.5.0 <0.8.0;\\n\\n/* External Imports */\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n/**\\n * @title Lib_AddressManager\\n */\\ncontract Lib_AddressManager is Ownable {\\n\\n /**********\\n * Events *\\n **********/\\n\\n event AddressSet(\\n string indexed _name,\\n address _newAddress,\\n address _oldAddress\\n );\\n\\n\\n /*************\\n * Variables *\\n *************/\\n\\n mapping (bytes32 => address) private addresses;\\n\\n\\n /********************\\n * Public Functions *\\n ********************/\\n\\n /**\\n * Changes the address associated with a particular name.\\n * @param _name String name to associate an address with.\\n * @param _address Address to associate with the name.\\n */\\n function setAddress(\\n string memory _name,\\n address _address\\n )\\n external\\n onlyOwner\\n {\\n bytes32 nameHash = _getNameHash(_name);\\n address oldAddress = addresses[nameHash];\\n addresses[nameHash] = _address;\\n\\n emit AddressSet(\\n _name,\\n _address,\\n oldAddress\\n );\\n }\\n\\n /**\\n * Retrieves the address associated with a given name.\\n * @param _name Name to retrieve an address for.\\n * @return Address associated with the given name.\\n */\\n function getAddress(\\n string memory _name\\n )\\n external\\n view\\n returns (\\n address\\n )\\n {\\n return addresses[_getNameHash(_name)];\\n }\\n\\n\\n /**********************\\n * Internal Functions *\\n **********************/\\n\\n /**\\n * Computes the hash of a name.\\n * @param _name Name to compute a hash for.\\n * @return Hash of the given name.\\n */\\n function _getNameHash(\\n string memory _name\\n )\\n internal\\n pure\\n returns (\\n bytes32\\n )\\n {\\n return keccak256(abi.encodePacked(_name));\\n }\\n}\\n\",\"keccak256\":\"0x636defb785a5c6650d101def6790d9104724cc7570e0d875138624d069eed257\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50600061001b61006a565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35061006e565b3390565b6106478061007d6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063715018a61461005c5780638da5cb5b146100665780639b2ea4bd1461008a578063bf40fac11461013b578063f2fde38b146101e1575b600080fd5b610064610207565b005b61006e6102c5565b604080516001600160a01b039092168252519081900360200190f35b610064600480360360408110156100a057600080fd5b8101906020810181356401000000008111156100bb57600080fd5b8201836020820111156100cd57600080fd5b803590602001918460018302840111640100000000831117156100ef57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b031691506102d49050565b61006e6004803603602081101561015157600080fd5b81019060208101813564010000000081111561016c57600080fd5b82018360208201111561017e57600080fd5b803590602001918460018302840111640100000000831117156101a057600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061042d945050505050565b610064600480360360208110156101f757600080fd5b50356001600160a01b031661045c565b61020f610570565b6001600160a01b03166102206102c5565b6001600160a01b03161461027b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031690565b6102dc610570565b6001600160a01b03166102ed6102c5565b6001600160a01b031614610348576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600061035383610574565b60008181526001602090815260409182902080546001600160a01b038781166001600160a01b0319831617909255925187519495509216928692918291908401908083835b602083106103b75780518252601f199092019160209182019101610398565b51815160001960209485036101000a01908116901991909116179052604080519490920184900384206001600160a01b03808b16865288169185019190915281519095507f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c94509283900301919050a250505050565b60006001600061043c84610574565b81526020810191909152604001600020546001600160a01b031692915050565b610464610570565b6001600160a01b03166104756102c5565b6001600160a01b0316146104d0576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166105155760405162461bcd60e51b81526004018080602001828103825260268152602001806105ec6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b6000816040516020018082805190602001908083835b602083106105a95780518252601f19909201916020918201910161058a565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905091905056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373a2646970667358221220b47b03a0c984a0faed73425d34ee172acb8f5010c64751f78c7f645cf8dc2aad64736f6c63430007060033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063715018a61461005c5780638da5cb5b146100665780639b2ea4bd1461008a578063bf40fac11461013b578063f2fde38b146101e1575b600080fd5b610064610207565b005b61006e6102c5565b604080516001600160a01b039092168252519081900360200190f35b610064600480360360408110156100a057600080fd5b8101906020810181356401000000008111156100bb57600080fd5b8201836020820111156100cd57600080fd5b803590602001918460018302840111640100000000831117156100ef57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b031691506102d49050565b61006e6004803603602081101561015157600080fd5b81019060208101813564010000000081111561016c57600080fd5b82018360208201111561017e57600080fd5b803590602001918460018302840111640100000000831117156101a057600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061042d945050505050565b610064600480360360208110156101f757600080fd5b50356001600160a01b031661045c565b61020f610570565b6001600160a01b03166102206102c5565b6001600160a01b03161461027b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031690565b6102dc610570565b6001600160a01b03166102ed6102c5565b6001600160a01b031614610348576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600061035383610574565b60008181526001602090815260409182902080546001600160a01b038781166001600160a01b0319831617909255925187519495509216928692918291908401908083835b602083106103b75780518252601f199092019160209182019101610398565b51815160001960209485036101000a01908116901991909116179052604080519490920184900384206001600160a01b03808b16865288169185019190915281519095507f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c94509283900301919050a250505050565b60006001600061043c84610574565b81526020810191909152604001600020546001600160a01b031692915050565b610464610570565b6001600160a01b03166104756102c5565b6001600160a01b0316146104d0576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166105155760405162461bcd60e51b81526004018080602001828103825260268152602001806105ec6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b6000816040516020018082805190602001908083835b602083106105a95780518252601f19909201916020918201910161058a565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905091905056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373a2646970667358221220b47b03a0c984a0faed73425d34ee172acb8f5010c64751f78c7f645cf8dc2aad64736f6c63430007060033", - "devdoc": { - "kind": "dev", - "methods": { - "getAddress(string)": { - "params": { - "_name": "Name to retrieve an address for." - }, - "returns": { - "_0": "Address associated with the given name." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "setAddress(string,address)": { - "params": { - "_address": "Address to associate with the name.", - "_name": "String name to associate an address with." - } - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - } - }, - "title": "Lib_AddressManager", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "getAddress(string)": { - "notice": "Retrieves the address associated with a given name." - }, - "setAddress(string,address)": { - "notice": "Changes the address associated with a particular name." - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 664, - "contract": "contracts/optimistic-ethereum/libraries/resolver/Lib_AddressManager.sol:Lib_AddressManager", - "label": "_owner", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 15229, - "contract": "contracts/optimistic-ethereum/libraries/resolver/Lib_AddressManager.sol:Lib_AddressManager", - "label": "addresses", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_bytes32,t_address)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes32,t_address)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => address)", - "numberOfBytes": "32", - "value": "t_address" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/AssetReceiver.json b/packages/contracts-bedrock/deployments/mainnet/AssetReceiver.json deleted file mode 100644 index 352f7018e222..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/AssetReceiver.json +++ /dev/null @@ -1,505 +0,0 @@ -{ - "address": "0x15DdA60616Ffca20371ED1659dBB78E888f65556", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ReceivedETH", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrewERC20", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "WithdrewERC721", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrewETH", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_gas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "CALL", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_gas", - "type": "uint256" - } - ], - "name": "DELEGATECALL", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "setOwner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC20", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC20", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC721", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "withdrawERC721", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdrawETH", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - } - ], - "name": "withdrawETH", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0xb71ff0a1159385a03ad097a57d1cb37b62c5d6bc82be2e642a8d25d4ff4e1814", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 31, - "gasUsed": "887432", - "logsBloom": "0x00100000000000000001000000000000000000000000000000000000000000000000100000000000000000100000080000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000020000000000000000000000000000000000000000000000", - "blockHash": "0x2b65d7c70a739ca85d8fd598096aa680cd2eb267e73036afd4cb974edebda524", - "transactionHash": "0xb71ff0a1159385a03ad097a57d1cb37b62c5d6bc82be2e642a8d25d4ff4e1814", - "logs": [ - { - "transactionIndex": 31, - "blockNumber": 14904330, - "transactionHash": "0xb71ff0a1159385a03ad097a57d1cb37b62c5d6bc82be2e642a8d25d4ff4e1814", - "address": "0x15DdA60616Ffca20371ED1659dBB78E888f65556", - "topics": [ - "0x8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58" - ], - "data": "0x", - "logIndex": 57, - "blockHash": "0x2b65d7c70a739ca85d8fd598096aa680cd2eb267e73036afd4cb974edebda524" - } - ], - "blockNumber": 14904330, - "cumulativeGasUsed": "3130678", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 2, - "solcInputHash": "66d28de48de020e62747d42ffe3118e7", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ReceivedETH\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrewERC20\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"WithdrewERC721\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrewETH\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_gas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"CALL\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_gas\",\"type\":\"uint256\"}],\"name\":\"DELEGATECALL\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"withdrawERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC721\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"withdrawERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"withdrawETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"CALL(address,bytes,uint256,uint256)\":{\"params\":{\"_data\":\"Data to send with the call.\",\"_gas\":\"Amount of gas to send with the call.\",\"_target\":\"Address to call.\",\"_value\":\"ETH value to send with the call.\"},\"returns\":{\"_0\":\"Boolean success value.\",\"_1\":\"Bytes data returned by the call.\"}},\"DELEGATECALL(address,bytes,uint256)\":{\"params\":{\"_data\":\"Data to send with the call.\",\"_gas\":\"Amount of gas to send with the call.\",\"_target\":\"Address to call.\"},\"returns\":{\"_0\":\"Boolean success value.\",\"_1\":\"Bytes data returned by the call.\"}},\"constructor\":{\"params\":{\"_owner\":\"Initial contract owner.\"}},\"withdrawERC20(address,address)\":{\"params\":{\"_asset\":\"ERC20 token to withdraw.\",\"_to\":\"Address to receive the ERC20 balance.\"}},\"withdrawERC20(address,address,uint256)\":{\"params\":{\"_amount\":\"Amount of ERC20 to withdraw.\",\"_asset\":\"ERC20 token to withdraw.\",\"_to\":\"Address to receive the ERC20 balance.\"}},\"withdrawERC721(address,address,uint256)\":{\"params\":{\"_asset\":\"ERC721 token to withdraw.\",\"_id\":\"Token ID of the ERC721 token to withdraw.\",\"_to\":\"Address to receive the ERC721 token.\"}},\"withdrawETH(address)\":{\"params\":{\"_to\":\"Address to receive the ETH balance.\"}},\"withdrawETH(address,uint256)\":{\"params\":{\"_amount\":\"Amount of ETH to withdraw.\",\"_to\":\"Address to receive the ETH balance.\"}}},\"title\":\"AssetReceiver\",\"version\":1},\"userdoc\":{\"events\":{\"ReceivedETH(address,uint256)\":{\"notice\":\"Emitted when ETH is received by this address.\"},\"WithdrewERC20(address,address,address,uint256)\":{\"notice\":\"Emitted when ERC20 tokens are withdrawn from this address.\"},\"WithdrewERC721(address,address,address,uint256)\":{\"notice\":\"Emitted when ERC721 tokens are withdrawn from this address.\"},\"WithdrewETH(address,address,uint256)\":{\"notice\":\"Emitted when ETH is withdrawn from this address.\"}},\"kind\":\"user\",\"methods\":{\"CALL(address,bytes,uint256,uint256)\":{\"notice\":\"Sends a CALL to a target address.\"},\"DELEGATECALL(address,bytes,uint256)\":{\"notice\":\"Sends a DELEGATECALL to a target address.\"},\"withdrawERC20(address,address)\":{\"notice\":\"Withdraws full ERC20 balance to the recipient.\"},\"withdrawERC20(address,address,uint256)\":{\"notice\":\"Withdraws partial ERC20 balance to the recipient.\"},\"withdrawERC721(address,address,uint256)\":{\"notice\":\"Withdraws ERC721 token to the recipient.\"},\"withdrawETH(address)\":{\"notice\":\"Withdraws full ETH balance to the recipient.\"},\"withdrawETH(address,uint256)\":{\"notice\":\"Withdraws partial ETH balance to the recipient.\"}},\"notice\":\"AssetReceiver is a minimal contract for receiving funds assets in the form of either ETH, ERC20 tokens, or ERC721 tokens. Only the contract owner may withdraw the assets.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/AssetReceiver.sol\":\"AssetReceiver\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x7e91c80b0dd1a14a19cb9e661b99924043adab6d9d893bbfcf3a6a3dc23a6743\",\"license\":\"AGPL-3.0-only\"},\"@rari-capital/solmate/src/tokens/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\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\",\"keccak256\":\"0x0240f7703cff32a61ee3e9fbb339e09a944260432a9ef37debf3692b1a6c8049\",\"license\":\"AGPL-3.0-only\"},\"@rari-capital/solmate/src/tokens/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\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 require(\\n to.code.length == 0 ||\\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 require(\\n to.code.length == 0 ||\\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 require(\\n to.code.length == 0 ||\\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 require(\\n to.code.length == 0 ||\\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\",\"keccak256\":\"0xb59c7c25eca386f39da4819a9f70f89b73b7583d5f5127a83ffe5339800b1183\",\"license\":\"AGPL-3.0-only\"},\"contracts/universal/AssetReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\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 * Emitted when ETH is received by this address.\\n */\\n event ReceivedETH(address indexed from, uint256 amount);\\n\\n /**\\n * Emitted when ETH is withdrawn from this address.\\n */\\n event WithdrewETH(address indexed withdrawer, address indexed recipient, uint256 amount);\\n\\n /**\\n * Emitted when ERC20 tokens are withdrawn from this address.\\n */\\n event WithdrewERC20(\\n address indexed withdrawer,\\n address indexed recipient,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /**\\n * Emitted when ERC721 tokens are withdrawn from this address.\\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 * Make sure we can receive ETH.\\n */\\n receive() external payable {\\n emit ReceivedETH(msg.sender, msg.value);\\n }\\n\\n /**\\n * 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 * 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 _to.transfer(_amount);\\n emit WithdrewETH(msg.sender, _to, _amount);\\n }\\n\\n /**\\n * 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 * 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 * 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\",\"keccak256\":\"0x1f82aff6f4e5a4bebebbfb4a2e0e4378ef9bc5bee8b81f88b27fc0ce73546d5f\",\"license\":\"MIT\"},\"contracts/universal/Transactor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\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 _gas Amount of gas to send with the call.\\n * @param _value ETH value to send with the call.\\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 _gas,\\n uint256 _value\\n ) external payable onlyOwner returns (bool, bytes memory) {\\n return _target.call{ gas: _gas, 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 * @param _gas Amount of gas to send with the call.\\n * @return Boolean success value.\\n * @return Bytes data returned by the call.\\n */\\n function DELEGATECALL(\\n address _target,\\n bytes memory _data,\\n uint256 _gas\\n ) external payable onlyOwner returns (bool, bytes memory) {\\n // slither-disable-next-line controlled-delegatecall\\n return _target.delegatecall{ gas: _gas }(_data);\\n }\\n}\\n\",\"keccak256\":\"0xfe0d9c05a423d36775047e3285f76b874f8b887444d412a0d680c302c3b06a50\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50604051610f6e380380610f6e83398101604081905261002f91610081565b600080546001600160a01b0319166001600160a01b038316908117825560405183928392917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a35050506100b1565b60006020828403121561009357600080fd5b81516001600160a01b03811681146100aa57600080fd5b9392505050565b610eae806100c06000396000f3fe60806040526004361061009a5760003560e01c80635cef8b4a116100695780638da5cb5b1161004e5780638da5cb5b146101a75780639456fbcc146101f95780639e73dbea1461021957600080fd5b80635cef8b4a1461015d578063690d83201461018757600080fd5b806313af4035146100db5780634025feb2146100fd57806344004cc11461011d5780634782f7791461013d57600080fd5b366100d65760405134815233907f4103257eaac983ca79a70d28f90dfc4fa16b619bb0c17ee7cab0d4034c2796249060200160405180910390a2005b600080fd5b3480156100e757600080fd5b506100fb6100f6366004610b3a565b61022c565b005b34801561010957600080fd5b506100fb610118366004610b5e565b610322565b34801561012957600080fd5b506100fb610138366004610b5e565b6104b4565b34801561014957600080fd5b506100fb610158366004610b9f565b610654565b61017061016b366004610ca5565b61076a565b60405161017e929190610d2e565b60405180910390f35b34801561019357600080fd5b506100fb6101a2366004610b3a565b610863565b3480156101b357600080fd5b506000546101d49073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161017e565b34801561020557600080fd5b506100fb610214366004610d88565b6108f1565b610170610227366004610dc1565b610a1b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b15801561041957600080fd5b505af115801561042d573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f30b478a5e196e55886228aa87ba74a7dfeba655e0a4d7ba275eabfc22aabb7a8846040516104a791815260200190565b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb90604401602060405180830381600087803b1580156105a557600080fd5b505af11580156105b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105dd9190610e21565b508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f6b00f1c7883f053ba83e907fd1965b22fffe3c4111383e725f04638a566cdbfa846040516104a791815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b60405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610718573d6000803e3d6000fd5b5060405181815273ffffffffffffffffffffffffffffffffffffffff83169033907f1f12aa8b6d492dd9b98e2b00b0b20830c2a7ded65afac13b60d169a034ae90bc9060200160405180910390a35050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff1633146107ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b8473ffffffffffffffffffffffffffffffffffffffff1683856040516108159190610e43565b6000604051808303818686f4925050503d8060008114610851576040519150601f19603f3d011682016040523d82523d6000602084013e610856565b606091505b5091509150935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6108ee8147610654565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610a17908390839073ffffffffffffffffffffffffffffffffffffffff8316906370a082319060240160206040518083038186803b1580156109df57600080fd5b505afa1580156109f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101389190610e5f565b5050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610aa0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b8573ffffffffffffffffffffffffffffffffffffffff16848487604051610ac79190610e43565b600060405180830381858888f193505050503d8060008114610b05576040519150601f19603f3d011682016040523d82523d6000602084013e610b0a565b606091505b509150915094509492505050565b73ffffffffffffffffffffffffffffffffffffffff811681146108ee57600080fd5b600060208284031215610b4c57600080fd5b8135610b5781610b18565b9392505050565b600080600060608486031215610b7357600080fd5b8335610b7e81610b18565b92506020840135610b8e81610b18565b929592945050506040919091013590565b60008060408385031215610bb257600080fd5b8235610bbd81610b18565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610c0b57600080fd5b813567ffffffffffffffff80821115610c2657610c26610bcb565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610c6c57610c6c610bcb565b81604052838152866020858801011115610c8557600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215610cba57600080fd5b8335610cc581610b18565b9250602084013567ffffffffffffffff811115610ce157600080fd5b610ced86828701610bfa565b925050604084013590509250925092565b60005b83811015610d19578181015183820152602001610d01565b83811115610d28576000848401525b50505050565b82151581526040602082015260008251806040840152610d55816060850160208701610cfe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b60008060408385031215610d9b57600080fd5b8235610da681610b18565b91506020830135610db681610b18565b809150509250929050565b60008060008060808587031215610dd757600080fd5b8435610de281610b18565b9350602085013567ffffffffffffffff811115610dfe57600080fd5b610e0a87828801610bfa565b949794965050505060408301359260600135919050565b600060208284031215610e3357600080fd5b81518015158114610b5757600080fd5b60008251610e55818460208701610cfe565b9190910192915050565b600060208284031215610e7157600080fd5b505191905056fea2646970667358221220a79fda18860baa011a378f2e4963a1c9eb8fa5184c5fd3130308ce3c35ba96da64736f6c63430008090033", - "deployedBytecode": "0x60806040526004361061009a5760003560e01c80635cef8b4a116100695780638da5cb5b1161004e5780638da5cb5b146101a75780639456fbcc146101f95780639e73dbea1461021957600080fd5b80635cef8b4a1461015d578063690d83201461018757600080fd5b806313af4035146100db5780634025feb2146100fd57806344004cc11461011d5780634782f7791461013d57600080fd5b366100d65760405134815233907f4103257eaac983ca79a70d28f90dfc4fa16b619bb0c17ee7cab0d4034c2796249060200160405180910390a2005b600080fd5b3480156100e757600080fd5b506100fb6100f6366004610b3a565b61022c565b005b34801561010957600080fd5b506100fb610118366004610b5e565b610322565b34801561012957600080fd5b506100fb610138366004610b5e565b6104b4565b34801561014957600080fd5b506100fb610158366004610b9f565b610654565b61017061016b366004610ca5565b61076a565b60405161017e929190610d2e565b60405180910390f35b34801561019357600080fd5b506100fb6101a2366004610b3a565b610863565b3480156101b357600080fd5b506000546101d49073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161017e565b34801561020557600080fd5b506100fb610214366004610d88565b6108f1565b610170610227366004610dc1565b610a1b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b15801561041957600080fd5b505af115801561042d573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f30b478a5e196e55886228aa87ba74a7dfeba655e0a4d7ba275eabfc22aabb7a8846040516104a791815260200190565b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb90604401602060405180830381600087803b1580156105a557600080fd5b505af11580156105b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105dd9190610e21565b508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f6b00f1c7883f053ba83e907fd1965b22fffe3c4111383e725f04638a566cdbfa846040516104a791815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b60405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610718573d6000803e3d6000fd5b5060405181815273ffffffffffffffffffffffffffffffffffffffff83169033907f1f12aa8b6d492dd9b98e2b00b0b20830c2a7ded65afac13b60d169a034ae90bc9060200160405180910390a35050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff1633146107ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b8473ffffffffffffffffffffffffffffffffffffffff1683856040516108159190610e43565b6000604051808303818686f4925050503d8060008114610851576040519150601f19603f3d011682016040523d82523d6000602084013e610856565b606091505b5091509150935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6108ee8147610654565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610a17908390839073ffffffffffffffffffffffffffffffffffffffff8316906370a082319060240160206040518083038186803b1580156109df57600080fd5b505afa1580156109f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101389190610e5f565b5050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610aa0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b8573ffffffffffffffffffffffffffffffffffffffff16848487604051610ac79190610e43565b600060405180830381858888f193505050503d8060008114610b05576040519150601f19603f3d011682016040523d82523d6000602084013e610b0a565b606091505b509150915094509492505050565b73ffffffffffffffffffffffffffffffffffffffff811681146108ee57600080fd5b600060208284031215610b4c57600080fd5b8135610b5781610b18565b9392505050565b600080600060608486031215610b7357600080fd5b8335610b7e81610b18565b92506020840135610b8e81610b18565b929592945050506040919091013590565b60008060408385031215610bb257600080fd5b8235610bbd81610b18565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610c0b57600080fd5b813567ffffffffffffffff80821115610c2657610c26610bcb565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610c6c57610c6c610bcb565b81604052838152866020858801011115610c8557600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215610cba57600080fd5b8335610cc581610b18565b9250602084013567ffffffffffffffff811115610ce157600080fd5b610ced86828701610bfa565b925050604084013590509250925092565b60005b83811015610d19578181015183820152602001610d01565b83811115610d28576000848401525b50505050565b82151581526040602082015260008251806040840152610d55816060850160208701610cfe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b60008060408385031215610d9b57600080fd5b8235610da681610b18565b91506020830135610db681610b18565b809150509250929050565b60008060008060808587031215610dd757600080fd5b8435610de281610b18565b9350602085013567ffffffffffffffff811115610dfe57600080fd5b610e0a87828801610bfa565b949794965050505060408301359260600135919050565b600060208284031215610e3357600080fd5b81518015158114610b5757600080fd5b60008251610e55818460208701610cfe565b9190910192915050565b600060208284031215610e7157600080fd5b505191905056fea2646970667358221220a79fda18860baa011a378f2e4963a1c9eb8fa5184c5fd3130308ce3c35ba96da64736f6c63430008090033", - "devdoc": { - "kind": "dev", - "methods": { - "CALL(address,bytes,uint256,uint256)": { - "params": { - "_data": "Data to send with the call.", - "_gas": "Amount of gas to send with the call.", - "_target": "Address to call.", - "_value": "ETH value to send with the call." - }, - "returns": { - "_0": "Boolean success value.", - "_1": "Bytes data returned by the call." - } - }, - "DELEGATECALL(address,bytes,uint256)": { - "params": { - "_data": "Data to send with the call.", - "_gas": "Amount of gas to send with the call.", - "_target": "Address to call." - }, - "returns": { - "_0": "Boolean success value.", - "_1": "Bytes data returned by the call." - } - }, - "constructor": { - "params": { - "_owner": "Initial contract owner." - } - }, - "withdrawERC20(address,address)": { - "params": { - "_asset": "ERC20 token to withdraw.", - "_to": "Address to receive the ERC20 balance." - } - }, - "withdrawERC20(address,address,uint256)": { - "params": { - "_amount": "Amount of ERC20 to withdraw.", - "_asset": "ERC20 token to withdraw.", - "_to": "Address to receive the ERC20 balance." - } - }, - "withdrawERC721(address,address,uint256)": { - "params": { - "_asset": "ERC721 token to withdraw.", - "_id": "Token ID of the ERC721 token to withdraw.", - "_to": "Address to receive the ERC721 token." - } - }, - "withdrawETH(address)": { - "params": { - "_to": "Address to receive the ETH balance." - } - }, - "withdrawETH(address,uint256)": { - "params": { - "_amount": "Amount of ETH to withdraw.", - "_to": "Address to receive the ETH balance." - } - } - }, - "title": "AssetReceiver", - "version": 1 - }, - "userdoc": { - "events": { - "ReceivedETH(address,uint256)": { - "notice": "Emitted when ETH is received by this address." - }, - "WithdrewERC20(address,address,address,uint256)": { - "notice": "Emitted when ERC20 tokens are withdrawn from this address." - }, - "WithdrewERC721(address,address,address,uint256)": { - "notice": "Emitted when ERC721 tokens are withdrawn from this address." - }, - "WithdrewETH(address,address,uint256)": { - "notice": "Emitted when ETH is withdrawn from this address." - } - }, - "kind": "user", - "methods": { - "CALL(address,bytes,uint256,uint256)": { - "notice": "Sends a CALL to a target address." - }, - "DELEGATECALL(address,bytes,uint256)": { - "notice": "Sends a DELEGATECALL to a target address." - }, - "withdrawERC20(address,address)": { - "notice": "Withdraws full ERC20 balance to the recipient." - }, - "withdrawERC20(address,address,uint256)": { - "notice": "Withdraws partial ERC20 balance to the recipient." - }, - "withdrawERC721(address,address,uint256)": { - "notice": "Withdraws ERC721 token to the recipient." - }, - "withdrawETH(address)": { - "notice": "Withdraws full ETH balance to the recipient." - }, - "withdrawETH(address,uint256)": { - "notice": "Withdraws partial ETH balance to the recipient." - } - }, - "notice": "AssetReceiver is a minimal contract for receiving funds assets in the form of either ETH, ERC20 tokens, or ERC721 tokens. Only the contract owner may withdraw the assets.", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 10, - "contract": "contracts/universal/AssetReceiver.sol:AssetReceiver", - "label": "owner", - "offset": 0, - "slot": "0", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/CheckBalanceHigh.json b/packages/contracts-bedrock/deployments/mainnet/CheckBalanceHigh.json deleted file mode 100644 index a38a2f0a8748..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/CheckBalanceHigh.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "address": "0x7eC64a8a591bFf829ff6C8be76074D540ACb813F", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "threshold", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct CheckBalanceHigh.Params", - "name": "params", - "type": "tuple" - } - ], - "name": "_EventToExposeStructInABI__Params", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_params", - "type": "bytes" - } - ], - "name": "check", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x29af2bb56b520b9f7115dd3f4deda3dec0d6db0dfe45ef6a440a1f1b678242be", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 158, - "gasUsed": "176628", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x64d24a3fac9011c7cb71b7811a78d0220251808bd5b4c5c71ac234ca77e1f792", - "transactionHash": "0x29af2bb56b520b9f7115dd3f4deda3dec0d6db0dfe45ef6a440a1f1b678242be", - "logs": [], - "blockNumber": 16485623, - "cumulativeGasUsed": "13944967", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 2, - "solcInputHash": "2373b7ba869baea4fec58e6e7f7b8988", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"struct CheckBalanceHigh.Params\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"_EventToExposeStructInABI__Params\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_params\",\"type\":\"bytes\"}],\"name\":\"check\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"_EventToExposeStructInABI__Params((address,uint256))\":{\"params\":{\"params\":\"Parameters to encode.\"}}},\"kind\":\"dev\",\"methods\":{\"check(bytes)\":{\"params\":{\"_params\":\"Encoded parameters for the drip check.\"},\"returns\":{\"_0\":\"Whether the drip should be executed.\"}}},\"title\":\"CheckBalanceHigh\",\"version\":1},\"userdoc\":{\"events\":{\"_EventToExposeStructInABI__Params((address,uint256))\":{\"notice\":\"External event used to help client-side tooling encode parameters.\"}},\"kind\":\"user\",\"methods\":{\"check(bytes)\":{\"notice\":\"Checks whether a drip should be executable.\"}},\"notice\":\"DripCheck for checking if an account's balance is above a given threshold.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/dripchecks/CheckBalanceHigh.sol\":\"CheckBalanceHigh\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n /**\\n * @notice Checks whether a drip should be executable.\\n *\\n * @param _params Encoded parameters for the drip check.\\n *\\n * @return Whether the drip should be executed.\\n */\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb52c89360566b2963dfd82cb2cc23f0c3ce4503a69e8563878e8aa80b6c60b3f\",\"license\":\"MIT\"},\"contracts/universal/drippie/dripchecks/CheckBalanceHigh.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.16;\\n\\nimport { IDripCheck } from \\\"../IDripCheck.sol\\\";\\n\\n/**\\n * @title CheckBalanceHigh\\n * @notice DripCheck for checking if an account's balance is above a given threshold.\\n */\\ncontract CheckBalanceHigh is IDripCheck {\\n struct Params {\\n address target;\\n uint256 threshold;\\n }\\n\\n /**\\n * @notice External event used to help client-side tooling encode parameters.\\n *\\n * @param params Parameters to encode.\\n */\\n event _EventToExposeStructInABI__Params(Params params);\\n\\n /**\\n * @inheritdoc IDripCheck\\n */\\n function check(bytes memory _params) external view returns (bool) {\\n Params memory params = abi.decode(_params, (Params));\\n\\n // Check target balance is above threshold.\\n return params.target.balance > params.threshold;\\n }\\n}\\n\",\"keccak256\":\"0xcb27d9e50a7c32406872b8fdc4ca62ee0d27372eb9077657f6d16f3cd3b58c85\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610239806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e3660046100c3565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610192565b6020810151905173ffffffffffffffffffffffffffffffffffffffff1631119392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156100d557600080fd5b813567ffffffffffffffff808211156100ed57600080fd5b818401915084601f83011261010157600080fd5b81358181111561011357610113610094565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561015957610159610094565b8160405282815287602084870101111561017257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000604082840312156101a457600080fd5b6040516040810181811067ffffffffffffffff821117156101c7576101c7610094565b604052825173ffffffffffffffffffffffffffffffffffffffff811681146101ee57600080fd5b8152602092830151928101929092525091905056fea26469706673582212203818d112b628fa60d8cffe88e7198c860e268b9375b8b118dacdbf531c397ef864736f6c63430008100033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e3660046100c3565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610192565b6020810151905173ffffffffffffffffffffffffffffffffffffffff1631119392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156100d557600080fd5b813567ffffffffffffffff808211156100ed57600080fd5b818401915084601f83011261010157600080fd5b81358181111561011357610113610094565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561015957610159610094565b8160405282815287602084870101111561017257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000604082840312156101a457600080fd5b6040516040810181811067ffffffffffffffff821117156101c7576101c7610094565b604052825173ffffffffffffffffffffffffffffffffffffffff811681146101ee57600080fd5b8152602092830151928101929092525091905056fea26469706673582212203818d112b628fa60d8cffe88e7198c860e268b9375b8b118dacdbf531c397ef864736f6c63430008100033", - "devdoc": { - "events": { - "_EventToExposeStructInABI__Params((address,uint256))": { - "params": { - "params": "Parameters to encode." - } - } - }, - "kind": "dev", - "methods": { - "check(bytes)": { - "params": { - "_params": "Encoded parameters for the drip check." - }, - "returns": { - "_0": "Whether the drip should be executed." - } - } - }, - "title": "CheckBalanceHigh", - "version": 1 - }, - "userdoc": { - "events": { - "_EventToExposeStructInABI__Params((address,uint256))": { - "notice": "External event used to help client-side tooling encode parameters." - } - }, - "kind": "user", - "methods": { - "check(bytes)": { - "notice": "Checks whether a drip should be executable." - } - }, - "notice": "DripCheck for checking if an account's balance is above a given threshold.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/CheckBalanceLow.json b/packages/contracts-bedrock/deployments/mainnet/CheckBalanceLow.json deleted file mode 100644 index 7080cf7b3fb7..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/CheckBalanceLow.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "address": "0x381a4eFC2A2C914eA1889722bB4B44Fa6BD5b640", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "threshold", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct CheckBalanceLow.Params", - "name": "params", - "type": "tuple" - } - ], - "name": "_EventToExposeStructInABI__Params", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_params", - "type": "bytes" - } - ], - "name": "check", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x914ed8cd67ba7ae6117f48f54d28a8bc95c024bcf81892fb5e3ef7cc3e6816bf", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 142, - "gasUsed": "176640", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x1146150967938fa2bc31b565eec819de4993de51c9f26921139c6c5251316d68", - "transactionHash": "0x914ed8cd67ba7ae6117f48f54d28a8bc95c024bcf81892fb5e3ef7cc3e6816bf", - "logs": [], - "blockNumber": 16485625, - "cumulativeGasUsed": "11747659", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 2, - "solcInputHash": "2373b7ba869baea4fec58e6e7f7b8988", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"struct CheckBalanceLow.Params\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"_EventToExposeStructInABI__Params\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_params\",\"type\":\"bytes\"}],\"name\":\"check\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"_EventToExposeStructInABI__Params((address,uint256))\":{\"params\":{\"params\":\"Parameters to encode.\"}}},\"kind\":\"dev\",\"methods\":{\"check(bytes)\":{\"params\":{\"_params\":\"Encoded parameters for the drip check.\"},\"returns\":{\"_0\":\"Whether the drip should be executed.\"}}},\"title\":\"CheckBalanceLow\",\"version\":1},\"userdoc\":{\"events\":{\"_EventToExposeStructInABI__Params((address,uint256))\":{\"notice\":\"External event used to help client-side tooling encode parameters.\"}},\"kind\":\"user\",\"methods\":{\"check(bytes)\":{\"notice\":\"Checks whether a drip should be executable.\"}},\"notice\":\"DripCheck for checking if an account's balance is below a given threshold.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/dripchecks/CheckBalanceLow.sol\":\"CheckBalanceLow\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n /**\\n * @notice Checks whether a drip should be executable.\\n *\\n * @param _params Encoded parameters for the drip check.\\n *\\n * @return Whether the drip should be executed.\\n */\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb52c89360566b2963dfd82cb2cc23f0c3ce4503a69e8563878e8aa80b6c60b3f\",\"license\":\"MIT\"},\"contracts/universal/drippie/dripchecks/CheckBalanceLow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.16;\\n\\nimport { IDripCheck } from \\\"../IDripCheck.sol\\\";\\n\\n/**\\n * @title CheckBalanceLow\\n * @notice DripCheck for checking if an account's balance is below a given threshold.\\n */\\ncontract CheckBalanceLow is IDripCheck {\\n struct Params {\\n address target;\\n uint256 threshold;\\n }\\n\\n /**\\n * @notice External event used to help client-side tooling encode parameters.\\n *\\n * @param params Parameters to encode.\\n */\\n event _EventToExposeStructInABI__Params(Params params);\\n\\n /**\\n * @inheritdoc IDripCheck\\n */\\n function check(bytes memory _params) external view returns (bool) {\\n Params memory params = abi.decode(_params, (Params));\\n\\n // Check target ETH balance is below threshold.\\n return params.target.balance < params.threshold;\\n }\\n}\\n\",\"keccak256\":\"0x6a1187a80093770931296d3360b1ecc7d17f69157fe88f628989b257548b564b\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610239806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e3660046100c3565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610192565b6020810151905173ffffffffffffffffffffffffffffffffffffffff1631109392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156100d557600080fd5b813567ffffffffffffffff808211156100ed57600080fd5b818401915084601f83011261010157600080fd5b81358181111561011357610113610094565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561015957610159610094565b8160405282815287602084870101111561017257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000604082840312156101a457600080fd5b6040516040810181811067ffffffffffffffff821117156101c7576101c7610094565b604052825173ffffffffffffffffffffffffffffffffffffffff811681146101ee57600080fd5b8152602092830151928101929092525091905056fea2646970667358221220cc86d01120737597addcccffd841244801dcb64ce402d73b8d8569a52348996464736f6c63430008100033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e3660046100c3565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610192565b6020810151905173ffffffffffffffffffffffffffffffffffffffff1631109392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156100d557600080fd5b813567ffffffffffffffff808211156100ed57600080fd5b818401915084601f83011261010157600080fd5b81358181111561011357610113610094565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561015957610159610094565b8160405282815287602084870101111561017257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000604082840312156101a457600080fd5b6040516040810181811067ffffffffffffffff821117156101c7576101c7610094565b604052825173ffffffffffffffffffffffffffffffffffffffff811681146101ee57600080fd5b8152602092830151928101929092525091905056fea2646970667358221220cc86d01120737597addcccffd841244801dcb64ce402d73b8d8569a52348996464736f6c63430008100033", - "devdoc": { - "events": { - "_EventToExposeStructInABI__Params((address,uint256))": { - "params": { - "params": "Parameters to encode." - } - } - }, - "kind": "dev", - "methods": { - "check(bytes)": { - "params": { - "_params": "Encoded parameters for the drip check." - }, - "returns": { - "_0": "Whether the drip should be executed." - } - } - }, - "title": "CheckBalanceLow", - "version": 1 - }, - "userdoc": { - "events": { - "_EventToExposeStructInABI__Params((address,uint256))": { - "notice": "External event used to help client-side tooling encode parameters." - } - }, - "kind": "user", - "methods": { - "check(bytes)": { - "notice": "Checks whether a drip should be executable." - } - }, - "notice": "DripCheck for checking if an account's balance is below a given threshold.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/CheckGelatoLow.json b/packages/contracts-bedrock/deployments/mainnet/CheckGelatoLow.json deleted file mode 100644 index c030a4477879..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/CheckGelatoLow.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "address": "0x4f7CFc43f6D262a085F3b946cAC69E7a8E39BBAa", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "treasury", - "type": "address" - }, - { - "internalType": "uint256", - "name": "threshold", - "type": "uint256" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "indexed": false, - "internalType": "struct CheckGelatoLow.Params", - "name": "params", - "type": "tuple" - } - ], - "name": "_EventToExposeStructInABI__Params", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_params", - "type": "bytes" - } - ], - "name": "check", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x18d80365aa0edda05af40c91fa32c610df2101f8c388d274cb50b882f5147167", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 47, - "gasUsed": "222032", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe3b313c0071bf10c41546a0f95ad53cda542f1b487fe1452e137ef652a0089a1", - "transactionHash": "0x18d80365aa0edda05af40c91fa32c610df2101f8c388d274cb50b882f5147167", - "logs": [], - "blockNumber": 16485627, - "cumulativeGasUsed": "5224175", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 2, - "solcInputHash": "2373b7ba869baea4fec58e6e7f7b8988", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"treasury\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct CheckGelatoLow.Params\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"_EventToExposeStructInABI__Params\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_params\",\"type\":\"bytes\"}],\"name\":\"check\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"_EventToExposeStructInABI__Params((address,uint256,address))\":{\"params\":{\"params\":\"Parameters to encode.\"}}},\"kind\":\"dev\",\"methods\":{\"check(bytes)\":{\"params\":{\"_params\":\"Encoded parameters for the drip check.\"},\"returns\":{\"_0\":\"Whether the drip should be executed.\"}}},\"title\":\"CheckGelatoLow\",\"version\":1},\"userdoc\":{\"events\":{\"_EventToExposeStructInABI__Params((address,uint256,address))\":{\"notice\":\"External event used to help client-side tooling encode parameters.\"}},\"kind\":\"user\",\"methods\":{\"check(bytes)\":{\"notice\":\"Checks whether a drip should be executable.\"}},\"notice\":\"DripCheck for checking if an account's Gelato ETH balance is below some threshold.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/dripchecks/CheckGelatoLow.sol\":\"CheckGelatoLow\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n /**\\n * @notice Checks whether a drip should be executable.\\n *\\n * @param _params Encoded parameters for the drip check.\\n *\\n * @return Whether the drip should be executed.\\n */\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb52c89360566b2963dfd82cb2cc23f0c3ce4503a69e8563878e8aa80b6c60b3f\",\"license\":\"MIT\"},\"contracts/universal/drippie/dripchecks/CheckGelatoLow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.16;\\n\\nimport { IDripCheck } from \\\"../IDripCheck.sol\\\";\\n\\ninterface IGelatoTreasury {\\n function userTokenBalance(address _user, address _token) external view returns (uint256);\\n}\\n\\n/**\\n * @title CheckGelatoLow\\n * @notice DripCheck for checking if an account's Gelato ETH balance is below some threshold.\\n */\\ncontract CheckGelatoLow is IDripCheck {\\n struct Params {\\n address treasury;\\n uint256 threshold;\\n address recipient;\\n }\\n\\n /**\\n * @notice External event used to help client-side tooling encode parameters.\\n *\\n * @param params Parameters to encode.\\n */\\n event _EventToExposeStructInABI__Params(Params params);\\n\\n /**\\n * @inheritdoc IDripCheck\\n */\\n function check(bytes memory _params) external view returns (bool) {\\n Params memory params = abi.decode(_params, (Params));\\n\\n // Check GelatoTreasury ETH balance is below threshold.\\n return\\n IGelatoTreasury(params.treasury).userTokenBalance(\\n params.recipient,\\n // Gelato represents ETH as 0xeeeee....eeeee\\n 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\\n ) < params.threshold;\\n }\\n}\\n\",\"keccak256\":\"0x1a127a2c8955525cc2e5cd3c6703edc785c662a79222f524df4574cf47ddd864\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061030c806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e366004610160565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610258565b6020810151815160408084015190517fb47064c800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6024820152939450919291169063b47064c890604401602060405180830381865afa158015610105573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061012991906102bd565b109392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561017257600080fd5b813567ffffffffffffffff8082111561018a57600080fd5b818401915084601f83011261019e57600080fd5b8135818111156101b0576101b0610131565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101f6576101f6610131565b8160405282815287602084870101111561020f57600080fd5b826020860160208301376000928101602001929092525095945050505050565b805173ffffffffffffffffffffffffffffffffffffffff8116811461025357600080fd5b919050565b60006060828403121561026a57600080fd5b6040516060810181811067ffffffffffffffff8211171561028d5761028d610131565b6040526102998361022f565b8152602083015160208201526102b16040840161022f565b60408201529392505050565b6000602082840312156102cf57600080fd5b505191905056fea2646970667358221220d5d7b760af134f89109f20dbf88fd89e78bb4b81bed97f9aa45772b3775b388964736f6c63430008100033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e366004610160565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610258565b6020810151815160408084015190517fb47064c800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6024820152939450919291169063b47064c890604401602060405180830381865afa158015610105573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061012991906102bd565b109392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561017257600080fd5b813567ffffffffffffffff8082111561018a57600080fd5b818401915084601f83011261019e57600080fd5b8135818111156101b0576101b0610131565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101f6576101f6610131565b8160405282815287602084870101111561020f57600080fd5b826020860160208301376000928101602001929092525095945050505050565b805173ffffffffffffffffffffffffffffffffffffffff8116811461025357600080fd5b919050565b60006060828403121561026a57600080fd5b6040516060810181811067ffffffffffffffff8211171561028d5761028d610131565b6040526102998361022f565b8152602083015160208201526102b16040840161022f565b60408201529392505050565b6000602082840312156102cf57600080fd5b505191905056fea2646970667358221220d5d7b760af134f89109f20dbf88fd89e78bb4b81bed97f9aa45772b3775b388964736f6c63430008100033", - "devdoc": { - "events": { - "_EventToExposeStructInABI__Params((address,uint256,address))": { - "params": { - "params": "Parameters to encode." - } - } - }, - "kind": "dev", - "methods": { - "check(bytes)": { - "params": { - "_params": "Encoded parameters for the drip check." - }, - "returns": { - "_0": "Whether the drip should be executed." - } - } - }, - "title": "CheckGelatoLow", - "version": 1 - }, - "userdoc": { - "events": { - "_EventToExposeStructInABI__Params((address,uint256,address))": { - "notice": "External event used to help client-side tooling encode parameters." - } - }, - "kind": "user", - "methods": { - "check(bytes)": { - "notice": "Checks whether a drip should be executable." - } - }, - "notice": "DripCheck for checking if an account's Gelato ETH balance is below some threshold.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/CheckTrue.json b/packages/contracts-bedrock/deployments/mainnet/CheckTrue.json deleted file mode 100644 index 54ec93a5ad54..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/CheckTrue.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "address": "0x5c741a38cb11424711231777D71689C458eE835D", - "abi": [ - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "check", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - } - ], - "transactionHash": "0xf9c55443c3afb82190503b06ac5914eb3ea85179ec1572a0f22d781452f624dd", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 129, - "gasUsed": "139230", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x5a37331d49bcc789cd37c2dd45be47bb35724fd974aab0573e8b6eb58f1690e5", - "transactionHash": "0xf9c55443c3afb82190503b06ac5914eb3ea85179ec1572a0f22d781452f624dd", - "logs": [], - "blockNumber": 16485630, - "cumulativeGasUsed": "13196107", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 2, - "solcInputHash": "2373b7ba869baea4fec58e6e7f7b8988", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"check\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"check(bytes)\":{\"params\":{\"_params\":\"Encoded parameters for the drip check.\"},\"returns\":{\"_0\":\"Whether the drip should be executed.\"}}},\"title\":\"CheckTrue\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"check(bytes)\":{\"notice\":\"Checks whether a drip should be executable.\"}},\"notice\":\"DripCheck that always returns true.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/dripchecks/CheckTrue.sol\":\"CheckTrue\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n /**\\n * @notice Checks whether a drip should be executable.\\n *\\n * @param _params Encoded parameters for the drip check.\\n *\\n * @return Whether the drip should be executed.\\n */\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb52c89360566b2963dfd82cb2cc23f0c3ce4503a69e8563878e8aa80b6c60b3f\",\"license\":\"MIT\"},\"contracts/universal/drippie/dripchecks/CheckTrue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.16;\\n\\nimport { IDripCheck } from \\\"../IDripCheck.sol\\\";\\n\\n/**\\n * @title CheckTrue\\n * @notice DripCheck that always returns true.\\n */\\ncontract CheckTrue is IDripCheck {\\n /**\\n * @inheritdoc IDripCheck\\n */\\n function check(bytes memory) external pure returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xf2f5474f12983c30ca4fe9d19e7f88e6d2262e4a6f779e86b4a2117498fdbea5\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061018c806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004461003e366004610087565b50600190565b604051901515815260200160405180910390f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561009957600080fd5b813567ffffffffffffffff808211156100b157600080fd5b818401915084601f8301126100c557600080fd5b8135818111156100d7576100d7610058565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561011d5761011d610058565b8160405282815287602084870101111561013657600080fd5b82602086016020830137600092810160200192909252509594505050505056fea26469706673582212200bb899cb0e5f9dce180ebe72a1dfade46ffc5ec3cab398d1f2af09e8b9ce76d164736f6c63430008100033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004461003e366004610087565b50600190565b604051901515815260200160405180910390f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561009957600080fd5b813567ffffffffffffffff808211156100b157600080fd5b818401915084601f8301126100c557600080fd5b8135818111156100d7576100d7610058565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561011d5761011d610058565b8160405282815287602084870101111561013657600080fd5b82602086016020830137600092810160200192909252509594505050505056fea26469706673582212200bb899cb0e5f9dce180ebe72a1dfade46ffc5ec3cab398d1f2af09e8b9ce76d164736f6c63430008100033", - "devdoc": { - "kind": "dev", - "methods": { - "check(bytes)": { - "params": { - "_params": "Encoded parameters for the drip check." - }, - "returns": { - "_0": "Whether the drip should be executed." - } - } - }, - "title": "CheckTrue", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "check(bytes)": { - "notice": "Checks whether a drip should be executable." - } - }, - "notice": "DripCheck that always returns true.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/Drippie.json b/packages/contracts-bedrock/deployments/mainnet/Drippie.json deleted file mode 100644 index 5a7c32a96996..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/Drippie.json +++ /dev/null @@ -1,1054 +0,0 @@ -{ - "address": "0x44b3A2a040057eBafC601A78647e805fd58B1f50", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "nameref", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "components": [ - { - "internalType": "bool", - "name": "reentrant", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "interval", - "type": "uint256" - }, - { - "internalType": "contract IDripCheck", - "name": "dripcheck", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkparams", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address payable", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct Drippie.DripAction[]", - "name": "actions", - "type": "tuple[]" - } - ], - "indexed": false, - "internalType": "struct Drippie.DripConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "DripCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "nameref", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "address", - "name": "executor", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - } - ], - "name": "DripExecuted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "nameref", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "enum Drippie.DripStatus", - "name": "status", - "type": "uint8" - } - ], - "name": "DripStatusUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ReceivedETH", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrewERC20", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "WithdrewERC721", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrewETH", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "CALL", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "DELEGATECALL", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "components": [ - { - "internalType": "bool", - "name": "reentrant", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "interval", - "type": "uint256" - }, - { - "internalType": "contract IDripCheck", - "name": "dripcheck", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkparams", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address payable", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct Drippie.DripAction[]", - "name": "actions", - "type": "tuple[]" - } - ], - "internalType": "struct Drippie.DripConfig", - "name": "_config", - "type": "tuple" - } - ], - "name": "create", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - } - ], - "name": "drip", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "drips", - "outputs": [ - { - "internalType": "enum Drippie.DripStatus", - "name": "status", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "bool", - "name": "reentrant", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "interval", - "type": "uint256" - }, - { - "internalType": "contract IDripCheck", - "name": "dripcheck", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkparams", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address payable", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct Drippie.DripAction[]", - "name": "actions", - "type": "tuple[]" - } - ], - "internalType": "struct Drippie.DripConfig", - "name": "config", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "last", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "count", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - } - ], - "name": "executable", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "setOwner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "enum Drippie.DripStatus", - "name": "_status", - "type": "uint8" - } - ], - "name": "status", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC20", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC20", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC721", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "withdrawERC721", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdrawETH", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - } - ], - "name": "withdrawETH", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0xba5b80505317eddf6bacd476eb97124d4d9c85f7a91433f977bf171d5555d897", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 142, - "gasUsed": "2419585", - "logsBloom": "0x00000000000000000001000000000000000000000000000000000000000000000000100000000000000000000000080000000000000000000000000000000004000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000400000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000020000000000000000000000000000000000000000000000", - "blockHash": "0x99cd54a5b44c3158251a863f70ce60ffe923d5500e0f828b2188a2a64f44ff65", - "transactionHash": "0xba5b80505317eddf6bacd476eb97124d4d9c85f7a91433f977bf171d5555d897", - "logs": [ - { - "transactionIndex": 142, - "blockNumber": 16485618, - "transactionHash": "0xba5b80505317eddf6bacd476eb97124d4d9c85f7a91433f977bf171d5555d897", - "address": "0x44b3A2a040057eBafC601A78647e805fd58B1f50", - "topics": [ - "0x8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58" - ], - "data": "0x", - "logIndex": 312, - "blockHash": "0x99cd54a5b44c3158251a863f70ce60ffe923d5500e0f828b2188a2a64f44ff65" - } - ], - "blockNumber": 16485618, - "cumulativeGasUsed": "16386332", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 2, - "solcInputHash": "2373b7ba869baea4fec58e6e7f7b8988", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"nameref\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"reentrant\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"interval\",\"type\":\"uint256\"},{\"internalType\":\"contract IDripCheck\",\"name\":\"dripcheck\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkparams\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address payable\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"struct Drippie.DripAction[]\",\"name\":\"actions\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"struct Drippie.DripConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DripCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"nameref\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"executor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"DripExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"nameref\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"enum Drippie.DripStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"name\":\"DripStatusUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ReceivedETH\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrewERC20\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"WithdrewERC721\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrewETH\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"CALL\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"DELEGATECALL\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"reentrant\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"interval\",\"type\":\"uint256\"},{\"internalType\":\"contract IDripCheck\",\"name\":\"dripcheck\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkparams\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address payable\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"struct Drippie.DripAction[]\",\"name\":\"actions\",\"type\":\"tuple[]\"}],\"internalType\":\"struct Drippie.DripConfig\",\"name\":\"_config\",\"type\":\"tuple\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"drip\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"drips\",\"outputs\":[{\"internalType\":\"enum Drippie.DripStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"reentrant\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"interval\",\"type\":\"uint256\"},{\"internalType\":\"contract IDripCheck\",\"name\":\"dripcheck\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkparams\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address payable\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"struct Drippie.DripAction[]\",\"name\":\"actions\",\"type\":\"tuple[]\"}],\"internalType\":\"struct Drippie.DripConfig\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"last\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"executable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"enum Drippie.DripStatus\",\"name\":\"_status\",\"type\":\"uint8\"}],\"name\":\"status\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"withdrawERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC721\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"withdrawERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"withdrawETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"events\":{\"DripCreated(string,string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))\":{\"params\":{\"config\":\"Config for the created drip.\",\"name\":\"Unindexed name parameter (unhashed).\",\"nameref\":\"Indexed name parameter (hashed).\"}},\"DripExecuted(string,string,address,uint256)\":{\"params\":{\"executor\":\"Address that executed the drip.\",\"name\":\"Unindexed name parameter (unhashed).\",\"nameref\":\"Indexed name parameter (hashed).\",\"timestamp\":\"Time when the drip was executed.\"}},\"DripStatusUpdated(string,string,uint8)\":{\"params\":{\"name\":\"Unindexed name parameter (unhashed).\",\"nameref\":\"Indexed name parameter (hashed).\",\"status\":\"New drip status.\"}}},\"kind\":\"dev\",\"methods\":{\"CALL(address,bytes,uint256)\":{\"params\":{\"_data\":\"Data to send with the call.\",\"_target\":\"Address to call.\",\"_value\":\"ETH value to send with the call.\"},\"returns\":{\"_0\":\"Boolean success value.\",\"_1\":\"Bytes data returned by the call.\"}},\"DELEGATECALL(address,bytes)\":{\"params\":{\"_data\":\"Data to send with the call.\",\"_target\":\"Address to call.\"},\"returns\":{\"_0\":\"Boolean success value.\",\"_1\":\"Bytes data returned by the call.\"}},\"constructor\":{\"params\":{\"_owner\":\"Initial contract owner.\"}},\"create(string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))\":{\"params\":{\"_config\":\"Configuration for the drip.\",\"_name\":\"Name of the drip.\"}},\"drip(string)\":{\"params\":{\"_name\":\"Name of the drip to trigger.\"}},\"executable(string)\":{\"params\":{\"_name\":\"Drip to check.\"},\"returns\":{\"_0\":\"True if the drip is executable, reverts otherwise.\"}},\"status(string,uint8)\":{\"params\":{\"_name\":\"Name of the drip to update.\",\"_status\":\"New drip status.\"}},\"withdrawERC20(address,address)\":{\"params\":{\"_asset\":\"ERC20 token to withdraw.\",\"_to\":\"Address to receive the ERC20 balance.\"}},\"withdrawERC20(address,address,uint256)\":{\"params\":{\"_amount\":\"Amount of ERC20 to withdraw.\",\"_asset\":\"ERC20 token to withdraw.\",\"_to\":\"Address to receive the ERC20 balance.\"}},\"withdrawERC721(address,address,uint256)\":{\"params\":{\"_asset\":\"ERC721 token to withdraw.\",\"_id\":\"Token ID of the ERC721 token to withdraw.\",\"_to\":\"Address to receive the ERC721 token.\"}},\"withdrawETH(address)\":{\"params\":{\"_to\":\"Address to receive the ETH balance.\"}},\"withdrawETH(address,uint256)\":{\"params\":{\"_amount\":\"Amount of ETH to withdraw.\",\"_to\":\"Address to receive the ETH balance.\"}}},\"title\":\"Drippie\",\"version\":1},\"userdoc\":{\"events\":{\"DripCreated(string,string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))\":{\"notice\":\"Emitted when a new drip is created.\"},\"DripExecuted(string,string,address,uint256)\":{\"notice\":\"Emitted when a drip is executed.\"},\"DripStatusUpdated(string,string,uint8)\":{\"notice\":\"Emitted when a drip status is updated.\"},\"ReceivedETH(address,uint256)\":{\"notice\":\"Emitted when ETH is received by this address.\"},\"WithdrewERC20(address,address,address,uint256)\":{\"notice\":\"Emitted when ERC20 tokens are withdrawn from this address.\"},\"WithdrewERC721(address,address,address,uint256)\":{\"notice\":\"Emitted when ERC20 tokens are withdrawn from this address.\"},\"WithdrewETH(address,address,uint256)\":{\"notice\":\"Emitted when ETH is withdrawn from this address.\"}},\"kind\":\"user\",\"methods\":{\"CALL(address,bytes,uint256)\":{\"notice\":\"Sends a CALL to a target address.\"},\"DELEGATECALL(address,bytes)\":{\"notice\":\"Sends a DELEGATECALL to a target address.\"},\"create(string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))\":{\"notice\":\"Creates a new drip with the given name and configuration. Once created, drips cannot be modified in any way (this is a security measure). If you want to update a drip, simply pause (and potentially archive) the existing drip and create a new one.\"},\"drip(string)\":{\"notice\":\"Triggers a drip. This function is deliberately left as a public function because the assumption being made here is that setting the drip to ACTIVE is an affirmative signal that the drip should be executable according to the drip parameters, drip check, and drip interval. Note that drip parameters are read entirely from the state and are not supplied as user input, so there should not be any way for a non-authorized user to influence the behavior of the drip. Note that the drip check is executed only **once** at the beginning of the call to the drip function and will not be executed again between the drip actions within this call.\"},\"drips(string)\":{\"notice\":\"Maps from drip names to drip states.\"},\"executable(string)\":{\"notice\":\"Checks if a given drip is executable.\"},\"status(string,uint8)\":{\"notice\":\"Sets the status for a given drip. The behavior of this function depends on the status that the user is trying to set. A drip can always move between ACTIVE and PAUSED, but it can never move back to NONE and once ARCHIVED, it can never move back to ACTIVE or PAUSED.\"},\"withdrawERC20(address,address)\":{\"notice\":\"Withdraws full ERC20 balance to the recipient.\"},\"withdrawERC20(address,address,uint256)\":{\"notice\":\"Withdraws partial ERC20 balance to the recipient.\"},\"withdrawERC721(address,address,uint256)\":{\"notice\":\"Withdraws ERC721 token to the recipient.\"},\"withdrawETH(address)\":{\"notice\":\"Withdraws full ETH balance to the recipient.\"},\"withdrawETH(address,uint256)\":{\"notice\":\"Withdraws partial ETH balance to the recipient.\"}},\"notice\":\"Drippie is a system for managing automated contract interactions. A specific interaction is called a \\\"drip\\\" and can be executed according to some condition (called a dripcheck) and an execution interval. Drips cannot be executed faster than the execution interval. Drips can trigger arbitrary contract calls where the calling contract is this contract address. Drips can also send ETH value, which makes them ideal for keeping addresses sufficiently funded with ETH. Drippie is designed to be connected with smart contract automation services so that drips can be executed automatically. However, Drippie is specifically designed to be separated from these services so that trust assumptions are better compartmentalized.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/Drippie.sol\":\"Drippie\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x7e91c80b0dd1a14a19cb9e661b99924043adab6d9d893bbfcf3a6a3dc23a6743\",\"license\":\"AGPL-3.0-only\"},\"@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\",\"keccak256\":\"0x43aa1509bb753f053143530705d9c4eee415691d26a4779769bf028a74e6ac69\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xdac91feb466e74905737338d80cac5303eb7aedcbe76eda11c45eaa728451075\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x7e9bcbf8e23cb5f48e4eca605da6b7d96f88b9499e91a92cbf74d82e9e91cdf1\",\"license\":\"MIT\"},\"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\",\"keccak256\":\"0x6a9e687b2f333bcc8ade530325005cb67ab7f78fd31407d4f2274324e71fc0fb\",\"license\":\"MIT\"},\"contracts/universal/drippie/Drippie.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.16;\\n\\nimport { AssetReceiver } from \\\"../AssetReceiver.sol\\\";\\nimport { IDripCheck } from \\\"./IDripCheck.sol\\\";\\n\\n/**\\n * @title Drippie\\n * @notice Drippie is a system for managing automated contract interactions. A specific interaction\\n * is called a \\\"drip\\\" and can be executed according to some condition (called a dripcheck)\\n * and an execution interval. Drips cannot be executed faster than the execution interval.\\n * Drips can trigger arbitrary contract calls where the calling contract is this contract\\n * address. Drips can also send ETH value, which makes them ideal for keeping addresses\\n * sufficiently funded with ETH. Drippie is designed to be connected with smart contract\\n * automation services so that drips can be executed automatically. However, Drippie is\\n * specifically designed to be separated from these services so that trust assumptions are\\n * better compartmentalized.\\n */\\ncontract Drippie is AssetReceiver {\\n /**\\n * @notice Enum representing different status options for a given drip.\\n *\\n * @custom:value NONE Drip does not exist.\\n * @custom:value PAUSED Drip is paused and cannot be executed until reactivated.\\n * @custom:value ACTIVE Drip is active and can be executed.\\n * @custom:value ARCHIVED Drip is archived and can no longer be executed or reactivated.\\n */\\n enum DripStatus {\\n NONE,\\n PAUSED,\\n ACTIVE,\\n ARCHIVED\\n }\\n\\n /**\\n * @notice Represents a drip action.\\n */\\n struct DripAction {\\n address payable target;\\n bytes data;\\n uint256 value;\\n }\\n\\n /**\\n * @notice Represents the configuration for a given drip.\\n */\\n struct DripConfig {\\n bool reentrant;\\n uint256 interval;\\n IDripCheck dripcheck;\\n bytes checkparams;\\n DripAction[] actions;\\n }\\n\\n /**\\n * @notice Represents the state of an active drip.\\n */\\n struct DripState {\\n DripStatus status;\\n DripConfig config;\\n uint256 last;\\n uint256 count;\\n }\\n\\n /**\\n * @notice Emitted when a new drip is created.\\n *\\n * @param nameref Indexed name parameter (hashed).\\n * @param name Unindexed name parameter (unhashed).\\n * @param config Config for the created drip.\\n */\\n event DripCreated(\\n // Emit name twice because indexed version is hashed.\\n string indexed nameref,\\n string name,\\n DripConfig config\\n );\\n\\n /**\\n * @notice Emitted when a drip status is updated.\\n *\\n * @param nameref Indexed name parameter (hashed).\\n * @param name Unindexed name parameter (unhashed).\\n * @param status New drip status.\\n */\\n event DripStatusUpdated(\\n // Emit name twice because indexed version is hashed.\\n string indexed nameref,\\n string name,\\n DripStatus status\\n );\\n\\n /**\\n * @notice Emitted when a drip is executed.\\n *\\n * @param nameref Indexed name parameter (hashed).\\n * @param name Unindexed name parameter (unhashed).\\n * @param executor Address that executed the drip.\\n * @param timestamp Time when the drip was executed.\\n */\\n event DripExecuted(\\n // Emit name twice because indexed version is hashed.\\n string indexed nameref,\\n string name,\\n address executor,\\n uint256 timestamp\\n );\\n\\n /**\\n * @notice Maps from drip names to drip states.\\n */\\n mapping(string => DripState) public drips;\\n\\n /**\\n * @param _owner Initial contract owner.\\n */\\n constructor(address _owner) AssetReceiver(_owner) {}\\n\\n /**\\n * @notice Creates a new drip with the given name and configuration. Once created, drips cannot\\n * be modified in any way (this is a security measure). If you want to update a drip,\\n * simply pause (and potentially archive) the existing drip and create a new one.\\n *\\n * @param _name Name of the drip.\\n * @param _config Configuration for the drip.\\n */\\n function create(string calldata _name, DripConfig calldata _config) external onlyOwner {\\n // Make sure this drip doesn't already exist. We *must* guarantee that no other function\\n // will ever set the status of a drip back to NONE after it's been created. This is why\\n // archival is a separate status.\\n require(\\n drips[_name].status == DripStatus.NONE,\\n \\\"Drippie: drip with that name already exists\\\"\\n );\\n\\n // Validate the drip interval, only allowing an interval of zero if the drip has explicitly\\n // been marked as reentrant. Prevents client-side bugs making a drip infinitely executable\\n // within the same block (of course, restricted by gas limits).\\n if (_config.reentrant) {\\n require(\\n _config.interval == 0,\\n \\\"Drippie: if allowing reentrant drip, must set interval to zero\\\"\\n );\\n } else {\\n require(\\n _config.interval > 0,\\n \\\"Drippie: interval must be greater than zero if drip is not reentrant\\\"\\n );\\n }\\n\\n // We initialize this way because Solidity won't let us copy arrays into storage yet.\\n DripState storage state = drips[_name];\\n state.status = DripStatus.PAUSED;\\n state.config.reentrant = _config.reentrant;\\n state.config.interval = _config.interval;\\n state.config.dripcheck = _config.dripcheck;\\n state.config.checkparams = _config.checkparams;\\n\\n // Solidity doesn't let us copy arrays into storage, so we push each array one by one.\\n for (uint256 i = 0; i < _config.actions.length; i++) {\\n state.config.actions.push(_config.actions[i]);\\n }\\n\\n // Tell the world!\\n emit DripCreated(_name, _name, _config);\\n }\\n\\n /**\\n * @notice Sets the status for a given drip. The behavior of this function depends on the\\n * status that the user is trying to set. A drip can always move between ACTIVE and\\n * PAUSED, but it can never move back to NONE and once ARCHIVED, it can never move back\\n * to ACTIVE or PAUSED.\\n *\\n * @param _name Name of the drip to update.\\n * @param _status New drip status.\\n */\\n function status(string calldata _name, DripStatus _status) external onlyOwner {\\n // Make sure we can never set drip status back to NONE. A simple security measure to\\n // prevent accidental overwrites if this code is ever updated down the line.\\n require(\\n _status != DripStatus.NONE,\\n \\\"Drippie: drip status can never be set back to NONE after creation\\\"\\n );\\n\\n // Load the drip status once to avoid unnecessary SLOADs.\\n DripStatus curr = drips[_name].status;\\n\\n // Make sure the drip in question actually exists. Not strictly necessary but there doesn't\\n // seem to be any clear reason why you would want to do this, and it may save some gas in\\n // the case of a front-end bug.\\n require(\\n curr != DripStatus.NONE,\\n \\\"Drippie: drip with that name does not exist and cannot be updated\\\"\\n );\\n\\n // Once a drip has been archived, it cannot be un-archived. This is, after all, the entire\\n // point of archiving a drip.\\n require(\\n curr != DripStatus.ARCHIVED,\\n \\\"Drippie: drip with that name has been archived and cannot be updated\\\"\\n );\\n\\n // Although not strictly necessary, we make sure that the status here is actually changing.\\n // This may save the client some gas if there's a front-end bug and the user accidentally\\n // tries to \\\"change\\\" the status to the same value as before.\\n require(\\n curr != _status,\\n \\\"Drippie: cannot set drip status to the same status as its current status\\\"\\n );\\n\\n // If the user is trying to archive this drip, make sure the drip has been paused. We do\\n // not allow users to archive active drips so that the effects of this action are more\\n // abundantly clear.\\n if (_status == DripStatus.ARCHIVED) {\\n require(\\n curr == DripStatus.PAUSED,\\n \\\"Drippie: drip must first be paused before being archived\\\"\\n );\\n }\\n\\n // If we made it here then we can safely update the status.\\n drips[_name].status = _status;\\n emit DripStatusUpdated(_name, _name, _status);\\n }\\n\\n /**\\n * @notice Checks if a given drip is executable.\\n *\\n * @param _name Drip to check.\\n *\\n * @return True if the drip is executable, reverts otherwise.\\n */\\n function executable(string calldata _name) public view returns (bool) {\\n DripState storage state = drips[_name];\\n\\n // Only allow active drips to be executed, an obvious security measure.\\n require(\\n state.status == DripStatus.ACTIVE,\\n \\\"Drippie: selected drip does not exist or is not currently active\\\"\\n );\\n\\n // Don't drip if the drip interval has not yet elapsed since the last time we dripped. This\\n // is a safety measure that prevents a malicious recipient from, e.g., spending all of\\n // their funds and repeatedly requesting new drips. Limits the potential impact of a\\n // compromised recipient to just a single drip interval, after which the drip can be paused\\n // by the owner address.\\n require(\\n state.last + state.config.interval <= block.timestamp,\\n \\\"Drippie: drip interval has not elapsed since last drip\\\"\\n );\\n\\n // Make sure we're allowed to execute this drip.\\n require(\\n state.config.dripcheck.check(state.config.checkparams),\\n \\\"Drippie: dripcheck failed so drip is not yet ready to be triggered\\\"\\n );\\n\\n // Alright, we're good to execute.\\n return true;\\n }\\n\\n /**\\n * @notice Triggers a drip. This function is deliberately left as a public function because the\\n * assumption being made here is that setting the drip to ACTIVE is an affirmative\\n * signal that the drip should be executable according to the drip parameters, drip\\n * check, and drip interval. Note that drip parameters are read entirely from the state\\n * and are not supplied as user input, so there should not be any way for a\\n * non-authorized user to influence the behavior of the drip. Note that the drip check\\n * is executed only **once** at the beginning of the call to the drip function and will\\n * not be executed again between the drip actions within this call.\\n *\\n * @param _name Name of the drip to trigger.\\n */\\n function drip(string calldata _name) external {\\n DripState storage state = drips[_name];\\n\\n // Make sure the drip can be executed. Since executable reverts if the drip is not ready to\\n // be executed, we don't need to do an assertion that the returned value is true.\\n executable(_name);\\n\\n // Update the last execution time for this drip before the call. Note that it's entirely\\n // possible for a drip to be executed multiple times per block or even multiple times\\n // within the same transaction (via re-entrancy) if the drip interval is set to zero. Users\\n // should set a drip interval of 1 if they'd like the drip to be executed only once per\\n // block (since this will then prevent re-entrancy).\\n state.last = block.timestamp;\\n\\n // Update the number of times this drip has been executed. Although this increases the cost\\n // of using Drippie, it slightly simplifies the client-side by not having to worry about\\n // counting drips via events. Useful for monitoring the rate of drip execution.\\n state.count++;\\n\\n // Execute each action in the drip. We allow drips to have multiple actions because there\\n // are scenarios in which a contract must do multiple things atomically. For example, the\\n // contract may need to withdraw ETH from one account and then deposit that ETH into\\n // another account within the same transaction.\\n uint256 len = state.config.actions.length;\\n for (uint256 i = 0; i < len; i++) {\\n // Must be marked as \\\"storage\\\" because copying structs into memory is not yet supported\\n // by Solidity. Won't significantly reduce gas costs but at least makes it easier to\\n // read what the rest of this section is doing.\\n DripAction storage action = state.config.actions[i];\\n\\n // Actually execute the action. We could use ExcessivelySafeCall here but not strictly\\n // necessary (worst case, a drip gets bricked IFF the target is malicious, doubt this\\n // will ever happen in practice). Could save a marginal amount of gas to ignore the\\n // returndata.\\n // slither-disable-next-line calls-loop\\n (bool success, ) = action.target.call{ value: action.value }(action.data);\\n\\n // Generally should not happen, but could if there's a misconfiguration (e.g., passing\\n // the wrong data to the target contract), the recipient is not payable, or\\n // insufficient gas was supplied to this transaction. We revert so the drip can be\\n // fixed and triggered again later. Means we cannot emit an event to alert of the\\n // failure, but can reasonably be detected by off-chain services even without an event.\\n // Note that this forces the drip executor to supply sufficient gas to the call\\n // (assuming there is some sufficient gas limit that exists, otherwise the drip will\\n // not execute).\\n require(\\n success,\\n \\\"Drippie: drip was unsuccessful, please check your configuration for mistakes\\\"\\n );\\n }\\n\\n emit DripExecuted(_name, _name, msg.sender, block.timestamp);\\n }\\n}\\n\",\"keccak256\":\"0x60aac1f170b36ddd9523a48eccae75ad408ecbad6b32bcf5567e7f680ab10c94\",\"license\":\"MIT\"},\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n /**\\n * @notice Checks whether a drip should be executable.\\n *\\n * @param _params Encoded parameters for the drip check.\\n *\\n * @return Whether the drip should be executed.\\n */\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xb52c89360566b2963dfd82cb2cc23f0c3ce4503a69e8563878e8aa80b6c60b3f\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162002b3138038062002b3183398101604081905262000034916200008c565b600080546001600160a01b0319166001600160a01b03831690811782556040518392839283929091907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a350505050620000be565b6000602082840312156200009f57600080fd5b81516001600160a01b0381168114620000b757600080fd5b9392505050565b612a6380620000ce6000396000f3fe6080604052600436106100e15760003560e01c80636e2d44ae1161007f5780639bc94d01116100595780639bc94d01146102b0578063e551cdaa146102d0578063edee6239146102f0578063fc3e3eba1461030357600080fd5b80636e2d44ae1461021d5780638da5cb5b1461023e5780639456fbcc1461029057600080fd5b80634782f779116100bb5780634782f779146101845780634d7fba6e146101a457806367148cd2146101dd578063690d8320146101fd57600080fd5b806313af4035146101225780634025feb21461014457806344004cc11461016457600080fd5b3661011d5760405134815233907f4103257eaac983ca79a70d28f90dfc4fa16b619bb0c17ee7cab0d4034c2796249060200160405180910390a2005b600080fd5b34801561012e57600080fd5b5061014261013d366004611af9565b610333565b005b34801561015057600080fd5b5061014261015f366004611b1d565b61040f565b34801561017057600080fd5b5061014261017f366004611b1d565b610587565b34801561019057600080fd5b5061014261019f366004611b5e565b6106fe565b3480156101b057600080fd5b506101c46101bf366004611c2f565b610834565b6040516101d49493929190611d3a565b60405180910390f35b3480156101e957600080fd5b506101426101f8366004611e94565b610a66565b34801561020957600080fd5b50610142610218366004611af9565b610c6f565b61023061022b366004611ef6565b610ce3565b6040516101d4929190611f4f565b34801561024a57600080fd5b5060005461026b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d4565b34801561029c57600080fd5b506101426102ab366004611f6a565b610dc3565b3480156102bc57600080fd5b506101426102cb366004611fa3565b610ec4565b3480156102dc57600080fd5b506101426102eb366004611ffe565b611363565b6102306102fe366004612063565b61177f565b34801561030f57600080fd5b5061032361031e366004611e94565b61185c565b60405190151581526020016101d4565b60005473ffffffffffffffffffffffffffffffffffffffff16331461039f5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104765760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b1580156104ec57600080fd5b505af1158015610500573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f30b478a5e196e55886228aa87ba74a7dfeba655e0a4d7ba275eabfc22aabb7a88460405161057a91815260200190565b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105ee5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb906044016020604051808303816000875af1158015610663573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068791906120c1565b508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f6b00f1c7883f053ba83e907fd1965b22fffe3c4111383e725f04638a566cdbfa8460405161057a91815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107655760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146107bf576040519150601f19603f3d011682016040523d82523d6000602084013e6107c4565b606091505b505090508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f1f12aa8b6d492dd9b98e2b00b0b20830c2a7ded65afac13b60d169a034ae90bc8460405161082791815260200190565b60405180910390a3505050565b805160208183018101805160018083529383019483019490942093905282546040805160a081018252938501805460ff90811615158652600287015494860194909452600386015473ffffffffffffffffffffffffffffffffffffffff169185019190915260048501805493909216949392909160608401916108b6906120de565b80601f01602080910402602001604051908101604052809291908181526020018280546108e2906120de565b801561092f5780601f106109045761010080835404028352916020019161092f565b820191906000526020600020905b81548152906001019060200180831161091257829003601f168201915b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b82821015610a4e576000848152602090819020604080516060810190915260038502909101805473ffffffffffffffffffffffffffffffffffffffff16825260018101805492939192918401916109b3906120de565b80601f01602080910402602001604051908101604052809291908181526020018280546109df906120de565b8015610a2c5780601f10610a0157610100808354040283529160200191610a2c565b820191906000526020600020905b815481529060010190602001808311610a0f57829003601f168201915b505050505081526020016002820154815250508152602001906001019061095d565b50505091525050600682015460079092015490919084565b600060018383604051610a7a929190612131565b90815260200160405180910390209050610a94838361185c565b50426006820155600781018054906000610aad83612170565b9091555050600581015460005b81811015610c13576000836001016004018281548110610adc57610adc6121a8565b6000918252602082206003909102018054600282015460405192945073ffffffffffffffffffffffffffffffffffffffff90911691610b1f9060018601906121d7565b60006040518083038185875af1925050503d8060008114610b5c576040519150601f19603f3d011682016040523d82523d6000602084013e610b61565b606091505b5050905080610bfe5760405162461bcd60e51b815260206004820152604c60248201527f447269707069653a20647269702077617320756e7375636365737366756c2c2060448201527f706c6561736520636865636b20796f757220636f6e66696775726174696f6e2060648201527f666f72206d697374616b65730000000000000000000000000000000000000000608482015260a401610396565b50508080610c0b90612170565b915050610aba565b508383604051610c24929190612131565b60405180910390207fea21435419aad9c54a9d90e2522b6f60bd566401f36fcef661f5f5a28cc0d2c685853342604051610c619493929190612296565b60405180910390a250505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610cd65760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b610ce081476106fe565b50565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610d4e5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b8473ffffffffffffffffffffffffffffffffffffffff168385604051610d7491906122d3565b60006040518083038185875af1925050503d8060008114610db1576040519150601f19603f3d011682016040523d82523d6000602084013e610db6565b606091505b5091509150935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e2a5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610ec0908390839073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610e9c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061017f91906122ef565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610f2b5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6000816003811115610f3f57610f3f611c80565b03610fd85760405162461bcd60e51b815260206004820152604160248201527f447269707069653a2064726970207374617475732063616e206e65766572206260448201527f6520736574206261636b20746f204e4f4e45206166746572206372656174696f60648201527f6e00000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b600060018484604051610fec929190612131565b9081526040519081900360200190205460ff169050600081600381111561101557611015611c80565b036110ae5760405162461bcd60e51b815260206004820152604160248201527f447269707069653a206472697020776974682074686174206e616d6520646f6560448201527f73206e6f7420657869737420616e642063616e6e6f742062652075706461746560648201527f6400000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b60038160038111156110c2576110c2611c80565b0361115c5760405162461bcd60e51b8152602060048201526044602482018190527f447269707069653a206472697020776974682074686174206e616d6520686173908201527f206265656e20617263686976656420616e642063616e6e6f742062652075706460648201527f6174656400000000000000000000000000000000000000000000000000000000608482015260a401610396565b81600381111561116e5761116e611c80565b81600381111561118057611180611c80565b036112195760405162461bcd60e51b815260206004820152604860248201527f447269707069653a2063616e6e6f74207365742064726970207374617475732060448201527f746f207468652073616d6520737461747573206173206974732063757272656e60648201527f7420737461747573000000000000000000000000000000000000000000000000608482015260a401610396565b600382600381111561122d5761122d611c80565b036112b957600181600381111561124657611246611c80565b146112b95760405162461bcd60e51b815260206004820152603860248201527f447269707069653a2064726970206d757374206669727374206265207061757360448201527f6564206265666f7265206265696e6720617263686976656400000000000000006064820152608401610396565b81600185856040516112cc929190612131565b90815260405190819003602001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183600381111561131357611313611c80565b02179055508383604051611328929190612131565b60405180910390207f407cb3ad05e60ec498fb39417c7a4f6b82d5ba80f82fe512a37b02c93181a2a1858585604051610c6193929190612308565b60005473ffffffffffffffffffffffffffffffffffffffff1633146113ca5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6000600184846040516113de929190612131565b9081526040519081900360200190205460ff16600381111561140257611402611c80565b146114755760405162461bcd60e51b815260206004820152602b60248201527f447269707069653a206472697020776974682074686174206e616d6520616c7260448201527f65616479206578697374730000000000000000000000000000000000000000006064820152608401610396565b611482602082018261232b565b15611504576020810135156114ff5760405162461bcd60e51b815260206004820152603e60248201527f447269707069653a20696620616c6c6f77696e67207265656e7472616e74206460448201527f7269702c206d7573742073657420696e74657276616c20746f207a65726f00006064820152608401610396565b6115a5565b60008160200135116115a55760405162461bcd60e51b8152602060048201526044602482018190527f447269707069653a20696e74657276616c206d75737420626520677265617465908201527f72207468616e207a65726f2069662064726970206973206e6f74207265656e7460648201527f72616e7400000000000000000000000000000000000000000000000000000000608482015260a401610396565b6000600184846040516115b9929190612131565b9081526040516020918190038201902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117815591506116009083018361232b565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556020820135600282015561164b6060830160408401611af9565b6003820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905561169f6060830183612348565b60048301916116af9190836123fc565b5060005b6116c060808401846124f9565b905081101561173357600582016116da60808501856124f9565b838181106116ea576116ea6121a8565b90506020028101906116fc9190612561565b81546001810183556000928352602090922090916003020161171e8282612595565b5050808061172b90612170565b9150506116b3565b508383604051611744929190612131565b60405180910390207fe38d8d98e6cc66f6f520d483c6c5a89289681f897799c4c29d767cf57e76d9a6858585604051610c619392919061286a565b6000805460609073ffffffffffffffffffffffffffffffffffffffff1633146117ea5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b8373ffffffffffffffffffffffffffffffffffffffff168360405161180f91906122d3565b600060405180830381855af49150503d806000811461184a576040519150601f19603f3d011682016040523d82523d6000602084013e61184f565b606091505b50915091505b9250929050565b60008060018484604051611871929190612131565b90815260405190819003602001902090506002815460ff16600381111561189a5761189a611c80565b1461190f576040805162461bcd60e51b81526020600482015260248101919091527f447269707069653a2073656c6563746564206472697020646f6573206e6f742060448201527f6578697374206f72206973206e6f742063757272656e746c79206163746976656064820152608401610396565b60028101546006820154429161192491612971565b11156119985760405162461bcd60e51b815260206004820152603660248201527f447269707069653a206472697020696e74657276616c20686173206e6f74206560448201527f6c61707365642073696e6365206c6173742064726970000000000000000000006064820152608401610396565b60038101546040517fc64b3bb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063c64b3bb5906119f29060048086019101612984565b602060405180830381865afa158015611a0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3391906120c1565b611acb5760405162461bcd60e51b815260206004820152604260248201527f447269707069653a2064726970636865636b206661696c656420736f2064726960448201527f70206973206e6f742079657420726561647920746f206265207472696767657260648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b60019150505b92915050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce057600080fd5b600060208284031215611b0b57600080fd5b8135611b1681611ad7565b9392505050565b600080600060608486031215611b3257600080fd5b8335611b3d81611ad7565b92506020840135611b4d81611ad7565b929592945050506040919091013590565b60008060408385031215611b7157600080fd5b8235611b7c81611ad7565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600067ffffffffffffffff80841115611bd457611bd4611b8a565b604051601f8501601f19908116603f01168101908282118183101715611bfc57611bfc611b8a565b81604052809350858152868686011115611c1557600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215611c4157600080fd5b813567ffffffffffffffff811115611c5857600080fd5b8201601f81018413611c6957600080fd5b611c7884823560208401611bb9565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110611ce6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b60005b83811015611d05578181015183820152602001611ced565b50506000910152565b60008151808452611d26816020860160208601611cea565b601f01601f19169290920160200192915050565b611d448186611caf565b600060206080818401528551151560808401528086015160a084015260408087015173ffffffffffffffffffffffffffffffffffffffff80821660c0870152606091508189015160a060e0880152611da0610120880182611d0e565b60808b01518882037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80016101008a0152805180835291925086019086830190600581901b8401880160005b82811015611e3657601f1986830301845284518781511683528a810151898c850152611e198a850182611d0e565b918b0151938b0193909352948a0194938a01939150600101611deb565b50968a019b909b52505050509093019390935250949350505050565b60008083601f840112611e6457600080fd5b50813567ffffffffffffffff811115611e7c57600080fd5b60208301915083602082850101111561185557600080fd5b60008060208385031215611ea757600080fd5b823567ffffffffffffffff811115611ebe57600080fd5b611eca85828601611e52565b90969095509350505050565b600082601f830112611ee757600080fd5b611b1683833560208501611bb9565b600080600060608486031215611f0b57600080fd5b8335611f1681611ad7565b9250602084013567ffffffffffffffff811115611f3257600080fd5b611f3e86828701611ed6565b925050604084013590509250925092565b8215158152604060208201526000611c786040830184611d0e565b60008060408385031215611f7d57600080fd5b8235611f8881611ad7565b91506020830135611f9881611ad7565b809150509250929050565b600080600060408486031215611fb857600080fd5b833567ffffffffffffffff811115611fcf57600080fd5b611fdb86828701611e52565b909450925050602084013560048110611ff357600080fd5b809150509250925092565b60008060006040848603121561201357600080fd5b833567ffffffffffffffff8082111561202b57600080fd5b61203787838801611e52565b9095509350602086013591508082111561205057600080fd5b50840160a08187031215611ff357600080fd5b6000806040838503121561207657600080fd5b823561208181611ad7565b9150602083013567ffffffffffffffff81111561209d57600080fd5b6120a985828601611ed6565b9150509250929050565b8015158114610ce057600080fd5b6000602082840312156120d357600080fd5b8151611b16816120b3565b600181811c908216806120f257607f821691505b60208210810361212b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121a1576121a1612141565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083546121e5816120de565b600182811680156121fd57600181146122305761225f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008416875282151583028701945061225f565b8760005260208060002060005b858110156122565781548a82015290840190820161223d565b50505082870194505b50929695505050505050565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b6060815260006122aa60608301868861226b565b73ffffffffffffffffffffffffffffffffffffffff949094166020830152506040015292915050565b600082516122e5818460208701611cea565b9190910192915050565b60006020828403121561230157600080fd5b5051919050565b60408152600061231c60408301858761226b565b9050611c786020830184611caf565b60006020828403121561233d57600080fd5b8135611b16816120b3565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261237d57600080fd5b83018035915067ffffffffffffffff82111561239857600080fd5b60200191503681900382131561185557600080fd5b601f8211156123f757600081815260208120601f850160051c810160208610156123d45750805b601f850160051c820191505b818110156123f3578281556001016123e0565b5050505b505050565b67ffffffffffffffff83111561241457612414611b8a565b6124288361242283546120de565b836123ad565b6000601f84116001811461247a57600085156124445750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556124f2565b600083815260209020601f19861690835b828110156124ab578685013582556020948501946001909201910161248b565b50868210156124e6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261252e57600080fd5b83018035915067ffffffffffffffff82111561254957600080fd5b6020019150600581901b360382131561185557600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126122e557600080fd5b81356125a081611ad7565b73ffffffffffffffffffffffffffffffffffffffff81167fffffffffffffffffffffffff00000000000000000000000000000000000000008354161782555060018082016020808501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe186360301811261261a57600080fd5b8501803567ffffffffffffffff81111561263357600080fd5b803603838301131561264457600080fd5b6126588161265286546120de565b866123ad565b6000601f8211600181146126ac576000831561267657508382018501355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b178655612723565b600086815260209020601f19841690835b828110156126dc578685018801358255938701939089019087016126bd565b5084821015612719577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c198785880101351681555b50508683881b0186555b50505050505050604082013560028201555050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261276d57600080fd5b830160208101925035905067ffffffffffffffff81111561278d57600080fd5b80360382131561185557600080fd5b81835260006020808501808196508560051b81019150846000805b8881101561285c578385038a5282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18936030181126127f5578283fd5b88016060813561280481611ad7565b73ffffffffffffffffffffffffffffffffffffffff16875261282882890183612738565b828a8a015261283a838a01828461226b565b60409485013599909401989098525050998601999450918501916001016127b7565b509298975050505050505050565b60408152600061287e60408301858761226b565b82810360208401528335612891816120b3565b151581526020848101359082015260408401356128ad81611ad7565b73ffffffffffffffffffffffffffffffffffffffff1660408201526128d56060850185612738565b60a060608401526128ea60a08401828461226b565b91505060808501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe186360301811261292257600080fd5b850160208101903567ffffffffffffffff81111561293f57600080fd5b8060051b360382131561295157600080fd5b838303608085015261296483828461279c565b9998505050505050505050565b80820180821115611ad157611ad1612141565b6000602080835260008454612998816120de565b808487015260406001808416600081146129b957600181146129f157612a1f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550612a1f565b896000528660002060005b85811015612a175781548b82018601529083019088016129fc565b8a0184019650505b50939897505050505050505056fea26469706673582212208d60ccb026b0dcc2e3511887db1b30dfd98f123af2a2a96714cbeca8ed21494464736f6c63430008100033", - "deployedBytecode": "0x6080604052600436106100e15760003560e01c80636e2d44ae1161007f5780639bc94d01116100595780639bc94d01146102b0578063e551cdaa146102d0578063edee6239146102f0578063fc3e3eba1461030357600080fd5b80636e2d44ae1461021d5780638da5cb5b1461023e5780639456fbcc1461029057600080fd5b80634782f779116100bb5780634782f779146101845780634d7fba6e146101a457806367148cd2146101dd578063690d8320146101fd57600080fd5b806313af4035146101225780634025feb21461014457806344004cc11461016457600080fd5b3661011d5760405134815233907f4103257eaac983ca79a70d28f90dfc4fa16b619bb0c17ee7cab0d4034c2796249060200160405180910390a2005b600080fd5b34801561012e57600080fd5b5061014261013d366004611af9565b610333565b005b34801561015057600080fd5b5061014261015f366004611b1d565b61040f565b34801561017057600080fd5b5061014261017f366004611b1d565b610587565b34801561019057600080fd5b5061014261019f366004611b5e565b6106fe565b3480156101b057600080fd5b506101c46101bf366004611c2f565b610834565b6040516101d49493929190611d3a565b60405180910390f35b3480156101e957600080fd5b506101426101f8366004611e94565b610a66565b34801561020957600080fd5b50610142610218366004611af9565b610c6f565b61023061022b366004611ef6565b610ce3565b6040516101d4929190611f4f565b34801561024a57600080fd5b5060005461026b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d4565b34801561029c57600080fd5b506101426102ab366004611f6a565b610dc3565b3480156102bc57600080fd5b506101426102cb366004611fa3565b610ec4565b3480156102dc57600080fd5b506101426102eb366004611ffe565b611363565b6102306102fe366004612063565b61177f565b34801561030f57600080fd5b5061032361031e366004611e94565b61185c565b60405190151581526020016101d4565b60005473ffffffffffffffffffffffffffffffffffffffff16331461039f5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104765760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b1580156104ec57600080fd5b505af1158015610500573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f30b478a5e196e55886228aa87ba74a7dfeba655e0a4d7ba275eabfc22aabb7a88460405161057a91815260200190565b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105ee5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb906044016020604051808303816000875af1158015610663573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068791906120c1565b508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f6b00f1c7883f053ba83e907fd1965b22fffe3c4111383e725f04638a566cdbfa8460405161057a91815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107655760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146107bf576040519150601f19603f3d011682016040523d82523d6000602084013e6107c4565b606091505b505090508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f1f12aa8b6d492dd9b98e2b00b0b20830c2a7ded65afac13b60d169a034ae90bc8460405161082791815260200190565b60405180910390a3505050565b805160208183018101805160018083529383019483019490942093905282546040805160a081018252938501805460ff90811615158652600287015494860194909452600386015473ffffffffffffffffffffffffffffffffffffffff169185019190915260048501805493909216949392909160608401916108b6906120de565b80601f01602080910402602001604051908101604052809291908181526020018280546108e2906120de565b801561092f5780601f106109045761010080835404028352916020019161092f565b820191906000526020600020905b81548152906001019060200180831161091257829003601f168201915b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b82821015610a4e576000848152602090819020604080516060810190915260038502909101805473ffffffffffffffffffffffffffffffffffffffff16825260018101805492939192918401916109b3906120de565b80601f01602080910402602001604051908101604052809291908181526020018280546109df906120de565b8015610a2c5780601f10610a0157610100808354040283529160200191610a2c565b820191906000526020600020905b815481529060010190602001808311610a0f57829003601f168201915b505050505081526020016002820154815250508152602001906001019061095d565b50505091525050600682015460079092015490919084565b600060018383604051610a7a929190612131565b90815260200160405180910390209050610a94838361185c565b50426006820155600781018054906000610aad83612170565b9091555050600581015460005b81811015610c13576000836001016004018281548110610adc57610adc6121a8565b6000918252602082206003909102018054600282015460405192945073ffffffffffffffffffffffffffffffffffffffff90911691610b1f9060018601906121d7565b60006040518083038185875af1925050503d8060008114610b5c576040519150601f19603f3d011682016040523d82523d6000602084013e610b61565b606091505b5050905080610bfe5760405162461bcd60e51b815260206004820152604c60248201527f447269707069653a20647269702077617320756e7375636365737366756c2c2060448201527f706c6561736520636865636b20796f757220636f6e66696775726174696f6e2060648201527f666f72206d697374616b65730000000000000000000000000000000000000000608482015260a401610396565b50508080610c0b90612170565b915050610aba565b508383604051610c24929190612131565b60405180910390207fea21435419aad9c54a9d90e2522b6f60bd566401f36fcef661f5f5a28cc0d2c685853342604051610c619493929190612296565b60405180910390a250505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610cd65760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b610ce081476106fe565b50565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610d4e5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b8473ffffffffffffffffffffffffffffffffffffffff168385604051610d7491906122d3565b60006040518083038185875af1925050503d8060008114610db1576040519150601f19603f3d011682016040523d82523d6000602084013e610db6565b606091505b5091509150935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e2a5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610ec0908390839073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610e9c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061017f91906122ef565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610f2b5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6000816003811115610f3f57610f3f611c80565b03610fd85760405162461bcd60e51b815260206004820152604160248201527f447269707069653a2064726970207374617475732063616e206e65766572206260448201527f6520736574206261636b20746f204e4f4e45206166746572206372656174696f60648201527f6e00000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b600060018484604051610fec929190612131565b9081526040519081900360200190205460ff169050600081600381111561101557611015611c80565b036110ae5760405162461bcd60e51b815260206004820152604160248201527f447269707069653a206472697020776974682074686174206e616d6520646f6560448201527f73206e6f7420657869737420616e642063616e6e6f742062652075706461746560648201527f6400000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b60038160038111156110c2576110c2611c80565b0361115c5760405162461bcd60e51b8152602060048201526044602482018190527f447269707069653a206472697020776974682074686174206e616d6520686173908201527f206265656e20617263686976656420616e642063616e6e6f742062652075706460648201527f6174656400000000000000000000000000000000000000000000000000000000608482015260a401610396565b81600381111561116e5761116e611c80565b81600381111561118057611180611c80565b036112195760405162461bcd60e51b815260206004820152604860248201527f447269707069653a2063616e6e6f74207365742064726970207374617475732060448201527f746f207468652073616d6520737461747573206173206974732063757272656e60648201527f7420737461747573000000000000000000000000000000000000000000000000608482015260a401610396565b600382600381111561122d5761122d611c80565b036112b957600181600381111561124657611246611c80565b146112b95760405162461bcd60e51b815260206004820152603860248201527f447269707069653a2064726970206d757374206669727374206265207061757360448201527f6564206265666f7265206265696e6720617263686976656400000000000000006064820152608401610396565b81600185856040516112cc929190612131565b90815260405190819003602001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600183600381111561131357611313611c80565b02179055508383604051611328929190612131565b60405180910390207f407cb3ad05e60ec498fb39417c7a4f6b82d5ba80f82fe512a37b02c93181a2a1858585604051610c6193929190612308565b60005473ffffffffffffffffffffffffffffffffffffffff1633146113ca5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6000600184846040516113de929190612131565b9081526040519081900360200190205460ff16600381111561140257611402611c80565b146114755760405162461bcd60e51b815260206004820152602b60248201527f447269707069653a206472697020776974682074686174206e616d6520616c7260448201527f65616479206578697374730000000000000000000000000000000000000000006064820152608401610396565b611482602082018261232b565b15611504576020810135156114ff5760405162461bcd60e51b815260206004820152603e60248201527f447269707069653a20696620616c6c6f77696e67207265656e7472616e74206460448201527f7269702c206d7573742073657420696e74657276616c20746f207a65726f00006064820152608401610396565b6115a5565b60008160200135116115a55760405162461bcd60e51b8152602060048201526044602482018190527f447269707069653a20696e74657276616c206d75737420626520677265617465908201527f72207468616e207a65726f2069662064726970206973206e6f74207265656e7460648201527f72616e7400000000000000000000000000000000000000000000000000000000608482015260a401610396565b6000600184846040516115b9929190612131565b9081526040516020918190038201902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117815591506116009083018361232b565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556020820135600282015561164b6060830160408401611af9565b6003820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905561169f6060830183612348565b60048301916116af9190836123fc565b5060005b6116c060808401846124f9565b905081101561173357600582016116da60808501856124f9565b838181106116ea576116ea6121a8565b90506020028101906116fc9190612561565b81546001810183556000928352602090922090916003020161171e8282612595565b5050808061172b90612170565b9150506116b3565b508383604051611744929190612131565b60405180910390207fe38d8d98e6cc66f6f520d483c6c5a89289681f897799c4c29d767cf57e76d9a6858585604051610c619392919061286a565b6000805460609073ffffffffffffffffffffffffffffffffffffffff1633146117ea5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b8373ffffffffffffffffffffffffffffffffffffffff168360405161180f91906122d3565b600060405180830381855af49150503d806000811461184a576040519150601f19603f3d011682016040523d82523d6000602084013e61184f565b606091505b50915091505b9250929050565b60008060018484604051611871929190612131565b90815260405190819003602001902090506002815460ff16600381111561189a5761189a611c80565b1461190f576040805162461bcd60e51b81526020600482015260248101919091527f447269707069653a2073656c6563746564206472697020646f6573206e6f742060448201527f6578697374206f72206973206e6f742063757272656e746c79206163746976656064820152608401610396565b60028101546006820154429161192491612971565b11156119985760405162461bcd60e51b815260206004820152603660248201527f447269707069653a206472697020696e74657276616c20686173206e6f74206560448201527f6c61707365642073696e6365206c6173742064726970000000000000000000006064820152608401610396565b60038101546040517fc64b3bb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063c64b3bb5906119f29060048086019101612984565b602060405180830381865afa158015611a0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3391906120c1565b611acb5760405162461bcd60e51b815260206004820152604260248201527f447269707069653a2064726970636865636b206661696c656420736f2064726960448201527f70206973206e6f742079657420726561647920746f206265207472696767657260648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b60019150505b92915050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce057600080fd5b600060208284031215611b0b57600080fd5b8135611b1681611ad7565b9392505050565b600080600060608486031215611b3257600080fd5b8335611b3d81611ad7565b92506020840135611b4d81611ad7565b929592945050506040919091013590565b60008060408385031215611b7157600080fd5b8235611b7c81611ad7565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600067ffffffffffffffff80841115611bd457611bd4611b8a565b604051601f8501601f19908116603f01168101908282118183101715611bfc57611bfc611b8a565b81604052809350858152868686011115611c1557600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215611c4157600080fd5b813567ffffffffffffffff811115611c5857600080fd5b8201601f81018413611c6957600080fd5b611c7884823560208401611bb9565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110611ce6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b60005b83811015611d05578181015183820152602001611ced565b50506000910152565b60008151808452611d26816020860160208601611cea565b601f01601f19169290920160200192915050565b611d448186611caf565b600060206080818401528551151560808401528086015160a084015260408087015173ffffffffffffffffffffffffffffffffffffffff80821660c0870152606091508189015160a060e0880152611da0610120880182611d0e565b60808b01518882037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80016101008a0152805180835291925086019086830190600581901b8401880160005b82811015611e3657601f1986830301845284518781511683528a810151898c850152611e198a850182611d0e565b918b0151938b0193909352948a0194938a01939150600101611deb565b50968a019b909b52505050509093019390935250949350505050565b60008083601f840112611e6457600080fd5b50813567ffffffffffffffff811115611e7c57600080fd5b60208301915083602082850101111561185557600080fd5b60008060208385031215611ea757600080fd5b823567ffffffffffffffff811115611ebe57600080fd5b611eca85828601611e52565b90969095509350505050565b600082601f830112611ee757600080fd5b611b1683833560208501611bb9565b600080600060608486031215611f0b57600080fd5b8335611f1681611ad7565b9250602084013567ffffffffffffffff811115611f3257600080fd5b611f3e86828701611ed6565b925050604084013590509250925092565b8215158152604060208201526000611c786040830184611d0e565b60008060408385031215611f7d57600080fd5b8235611f8881611ad7565b91506020830135611f9881611ad7565b809150509250929050565b600080600060408486031215611fb857600080fd5b833567ffffffffffffffff811115611fcf57600080fd5b611fdb86828701611e52565b909450925050602084013560048110611ff357600080fd5b809150509250925092565b60008060006040848603121561201357600080fd5b833567ffffffffffffffff8082111561202b57600080fd5b61203787838801611e52565b9095509350602086013591508082111561205057600080fd5b50840160a08187031215611ff357600080fd5b6000806040838503121561207657600080fd5b823561208181611ad7565b9150602083013567ffffffffffffffff81111561209d57600080fd5b6120a985828601611ed6565b9150509250929050565b8015158114610ce057600080fd5b6000602082840312156120d357600080fd5b8151611b16816120b3565b600181811c908216806120f257607f821691505b60208210810361212b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036121a1576121a1612141565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083546121e5816120de565b600182811680156121fd57600181146122305761225f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008416875282151583028701945061225f565b8760005260208060002060005b858110156122565781548a82015290840190820161223d565b50505082870194505b50929695505050505050565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b6060815260006122aa60608301868861226b565b73ffffffffffffffffffffffffffffffffffffffff949094166020830152506040015292915050565b600082516122e5818460208701611cea565b9190910192915050565b60006020828403121561230157600080fd5b5051919050565b60408152600061231c60408301858761226b565b9050611c786020830184611caf565b60006020828403121561233d57600080fd5b8135611b16816120b3565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261237d57600080fd5b83018035915067ffffffffffffffff82111561239857600080fd5b60200191503681900382131561185557600080fd5b601f8211156123f757600081815260208120601f850160051c810160208610156123d45750805b601f850160051c820191505b818110156123f3578281556001016123e0565b5050505b505050565b67ffffffffffffffff83111561241457612414611b8a565b6124288361242283546120de565b836123ad565b6000601f84116001811461247a57600085156124445750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556124f2565b600083815260209020601f19861690835b828110156124ab578685013582556020948501946001909201910161248b565b50868210156124e6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261252e57600080fd5b83018035915067ffffffffffffffff82111561254957600080fd5b6020019150600581901b360382131561185557600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126122e557600080fd5b81356125a081611ad7565b73ffffffffffffffffffffffffffffffffffffffff81167fffffffffffffffffffffffff00000000000000000000000000000000000000008354161782555060018082016020808501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe186360301811261261a57600080fd5b8501803567ffffffffffffffff81111561263357600080fd5b803603838301131561264457600080fd5b6126588161265286546120de565b866123ad565b6000601f8211600181146126ac576000831561267657508382018501355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b178655612723565b600086815260209020601f19841690835b828110156126dc578685018801358255938701939089019087016126bd565b5084821015612719577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c198785880101351681555b50508683881b0186555b50505050505050604082013560028201555050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261276d57600080fd5b830160208101925035905067ffffffffffffffff81111561278d57600080fd5b80360382131561185557600080fd5b81835260006020808501808196508560051b81019150846000805b8881101561285c578385038a5282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18936030181126127f5578283fd5b88016060813561280481611ad7565b73ffffffffffffffffffffffffffffffffffffffff16875261282882890183612738565b828a8a015261283a838a01828461226b565b60409485013599909401989098525050998601999450918501916001016127b7565b509298975050505050505050565b60408152600061287e60408301858761226b565b82810360208401528335612891816120b3565b151581526020848101359082015260408401356128ad81611ad7565b73ffffffffffffffffffffffffffffffffffffffff1660408201526128d56060850185612738565b60a060608401526128ea60a08401828461226b565b91505060808501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe186360301811261292257600080fd5b850160208101903567ffffffffffffffff81111561293f57600080fd5b8060051b360382131561295157600080fd5b838303608085015261296483828461279c565b9998505050505050505050565b80820180821115611ad157611ad1612141565b6000602080835260008454612998816120de565b808487015260406001808416600081146129b957600181146129f157612a1f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a01019550612a1f565b896000528660002060005b85811015612a175781548b82018601529083019088016129fc565b8a0184019650505b50939897505050505050505056fea26469706673582212208d60ccb026b0dcc2e3511887db1b30dfd98f123af2a2a96714cbeca8ed21494464736f6c63430008100033", - "devdoc": { - "events": { - "DripCreated(string,string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))": { - "params": { - "config": "Config for the created drip.", - "name": "Unindexed name parameter (unhashed).", - "nameref": "Indexed name parameter (hashed)." - } - }, - "DripExecuted(string,string,address,uint256)": { - "params": { - "executor": "Address that executed the drip.", - "name": "Unindexed name parameter (unhashed).", - "nameref": "Indexed name parameter (hashed).", - "timestamp": "Time when the drip was executed." - } - }, - "DripStatusUpdated(string,string,uint8)": { - "params": { - "name": "Unindexed name parameter (unhashed).", - "nameref": "Indexed name parameter (hashed).", - "status": "New drip status." - } - } - }, - "kind": "dev", - "methods": { - "CALL(address,bytes,uint256)": { - "params": { - "_data": "Data to send with the call.", - "_target": "Address to call.", - "_value": "ETH value to send with the call." - }, - "returns": { - "_0": "Boolean success value.", - "_1": "Bytes data returned by the call." - } - }, - "DELEGATECALL(address,bytes)": { - "params": { - "_data": "Data to send with the call.", - "_target": "Address to call." - }, - "returns": { - "_0": "Boolean success value.", - "_1": "Bytes data returned by the call." - } - }, - "constructor": { - "params": { - "_owner": "Initial contract owner." - } - }, - "create(string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))": { - "params": { - "_config": "Configuration for the drip.", - "_name": "Name of the drip." - } - }, - "drip(string)": { - "params": { - "_name": "Name of the drip to trigger." - } - }, - "executable(string)": { - "params": { - "_name": "Drip to check." - }, - "returns": { - "_0": "True if the drip is executable, reverts otherwise." - } - }, - "status(string,uint8)": { - "params": { - "_name": "Name of the drip to update.", - "_status": "New drip status." - } - }, - "withdrawERC20(address,address)": { - "params": { - "_asset": "ERC20 token to withdraw.", - "_to": "Address to receive the ERC20 balance." - } - }, - "withdrawERC20(address,address,uint256)": { - "params": { - "_amount": "Amount of ERC20 to withdraw.", - "_asset": "ERC20 token to withdraw.", - "_to": "Address to receive the ERC20 balance." - } - }, - "withdrawERC721(address,address,uint256)": { - "params": { - "_asset": "ERC721 token to withdraw.", - "_id": "Token ID of the ERC721 token to withdraw.", - "_to": "Address to receive the ERC721 token." - } - }, - "withdrawETH(address)": { - "params": { - "_to": "Address to receive the ETH balance." - } - }, - "withdrawETH(address,uint256)": { - "params": { - "_amount": "Amount of ETH to withdraw.", - "_to": "Address to receive the ETH balance." - } - } - }, - "title": "Drippie", - "version": 1 - }, - "userdoc": { - "events": { - "DripCreated(string,string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))": { - "notice": "Emitted when a new drip is created." - }, - "DripExecuted(string,string,address,uint256)": { - "notice": "Emitted when a drip is executed." - }, - "DripStatusUpdated(string,string,uint8)": { - "notice": "Emitted when a drip status is updated." - }, - "ReceivedETH(address,uint256)": { - "notice": "Emitted when ETH is received by this address." - }, - "WithdrewERC20(address,address,address,uint256)": { - "notice": "Emitted when ERC20 tokens are withdrawn from this address." - }, - "WithdrewERC721(address,address,address,uint256)": { - "notice": "Emitted when ERC20 tokens are withdrawn from this address." - }, - "WithdrewETH(address,address,uint256)": { - "notice": "Emitted when ETH is withdrawn from this address." - } - }, - "kind": "user", - "methods": { - "CALL(address,bytes,uint256)": { - "notice": "Sends a CALL to a target address." - }, - "DELEGATECALL(address,bytes)": { - "notice": "Sends a DELEGATECALL to a target address." - }, - "create(string,(bool,uint256,address,bytes,(address,bytes,uint256)[]))": { - "notice": "Creates a new drip with the given name and configuration. Once created, drips cannot be modified in any way (this is a security measure). If you want to update a drip, simply pause (and potentially archive) the existing drip and create a new one." - }, - "drip(string)": { - "notice": "Triggers a drip. This function is deliberately left as a public function because the assumption being made here is that setting the drip to ACTIVE is an affirmative signal that the drip should be executable according to the drip parameters, drip check, and drip interval. Note that drip parameters are read entirely from the state and are not supplied as user input, so there should not be any way for a non-authorized user to influence the behavior of the drip. Note that the drip check is executed only **once** at the beginning of the call to the drip function and will not be executed again between the drip actions within this call." - }, - "drips(string)": { - "notice": "Maps from drip names to drip states." - }, - "executable(string)": { - "notice": "Checks if a given drip is executable." - }, - "status(string,uint8)": { - "notice": "Sets the status for a given drip. The behavior of this function depends on the status that the user is trying to set. A drip can always move between ACTIVE and PAUSED, but it can never move back to NONE and once ARCHIVED, it can never move back to ACTIVE or PAUSED." - }, - "withdrawERC20(address,address)": { - "notice": "Withdraws full ERC20 balance to the recipient." - }, - "withdrawERC20(address,address,uint256)": { - "notice": "Withdraws partial ERC20 balance to the recipient." - }, - "withdrawERC721(address,address,uint256)": { - "notice": "Withdraws ERC721 token to the recipient." - }, - "withdrawETH(address)": { - "notice": "Withdraws full ETH balance to the recipient." - }, - "withdrawETH(address,uint256)": { - "notice": "Withdraws partial ETH balance to the recipient." - } - }, - "notice": "Drippie is a system for managing automated contract interactions. A specific interaction is called a \"drip\" and can be executed according to some condition (called a dripcheck) and an execution interval. Drips cannot be executed faster than the execution interval. Drips can trigger arbitrary contract calls where the calling contract is this contract address. Drips can also send ETH value, which makes them ideal for keeping addresses sufficiently funded with ETH. Drippie is designed to be connected with smart contract automation services so that drips can be executed automatically. However, Drippie is specifically designed to be separated from these services so that trust assumptions are better compartmentalized.", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 10, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "owner", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 1431, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "drips", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_string_memory_ptr,t_struct(DripState)1394_storage)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_address_payable": { - "encoding": "inplace", - "label": "address payable", - "numberOfBytes": "20" - }, - "t_array(t_struct(DripAction)1369_storage)dyn_storage": { - "base": "t_struct(DripAction)1369_storage", - "encoding": "dynamic_array", - "label": "struct Drippie.DripAction[]", - "numberOfBytes": "32" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes_storage": { - "encoding": "bytes", - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(IDripCheck)1794": { - "encoding": "inplace", - "label": "contract IDripCheck", - "numberOfBytes": "20" - }, - "t_enum(DripStatus)1362": { - "encoding": "inplace", - "label": "enum Drippie.DripStatus", - "numberOfBytes": "1" - }, - "t_mapping(t_string_memory_ptr,t_struct(DripState)1394_storage)": { - "encoding": "mapping", - "key": "t_string_memory_ptr", - "label": "mapping(string => struct Drippie.DripState)", - "numberOfBytes": "32", - "value": "t_struct(DripState)1394_storage" - }, - "t_string_memory_ptr": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_struct(DripAction)1369_storage": { - "encoding": "inplace", - "label": "struct Drippie.DripAction", - "members": [ - { - "astId": 1364, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "target", - "offset": 0, - "slot": "0", - "type": "t_address_payable" - }, - { - "astId": 1366, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "data", - "offset": 0, - "slot": "1", - "type": "t_bytes_storage" - }, - { - "astId": 1368, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "value", - "offset": 0, - "slot": "2", - "type": "t_uint256" - } - ], - "numberOfBytes": "96" - }, - "t_struct(DripConfig)1383_storage": { - "encoding": "inplace", - "label": "struct Drippie.DripConfig", - "members": [ - { - "astId": 1371, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "reentrant", - "offset": 0, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 1373, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "interval", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 1376, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "dripcheck", - "offset": 0, - "slot": "2", - "type": "t_contract(IDripCheck)1794" - }, - { - "astId": 1378, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "checkparams", - "offset": 0, - "slot": "3", - "type": "t_bytes_storage" - }, - { - "astId": 1382, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "actions", - "offset": 0, - "slot": "4", - "type": "t_array(t_struct(DripAction)1369_storage)dyn_storage" - } - ], - "numberOfBytes": "160" - }, - "t_struct(DripState)1394_storage": { - "encoding": "inplace", - "label": "struct Drippie.DripState", - "members": [ - { - "astId": 1386, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "status", - "offset": 0, - "slot": "0", - "type": "t_enum(DripStatus)1362" - }, - { - "astId": 1389, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "config", - "offset": 0, - "slot": "1", - "type": "t_struct(DripConfig)1383_storage" - }, - { - "astId": 1391, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "last", - "offset": 0, - "slot": "6", - "type": "t_uint256" - }, - { - "astId": 1393, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "count", - "offset": 0, - "slot": "7", - "type": "t_uint256" - } - ], - "numberOfBytes": "256" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/L1CrossDomainMessenger.json b/packages/contracts-bedrock/deployments/mainnet/L1CrossDomainMessenger.json deleted file mode 100644 index 8be23c6179f0..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/L1CrossDomainMessenger.json +++ /dev/null @@ -1,772 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "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": "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" - }, - { - "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_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": [], - "name": "OTHER_MESSENGER", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PORTAL", - "outputs": [ - { - "internalType": "contract OptimismPortal", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAY_CALL_OVERHEAD", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAY_CONSTANT_OVERHEAD", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAY_GAS_CHECK_BUFFER", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAY_RESERVED_GAS", - "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": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "failedMessages", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract OptimismPortal", - "name": "_portal", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "messageNonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "portal", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "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": [ - { - "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": [], - "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" - } - ], - "address": "0xDa2332D0a7608919Cd331B1304Cd179129a90495", - "args": [], - "bytecode": "0x60a06040523480156200001157600080fd5b507342000000000000000000000000000000000000076080526200003660006200003c565b620001ea565b600054600390600160a81b900460ff1615801562000068575060005460ff808316600160a01b90920416105b620000d15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b60008054600160a81b61ffff60a01b19909116600160a01b60ff85160260ff60a81b19161717905560f980546001600160a01b0319166001600160a01b0384161790556200011e62000165565b6000805460ff60a81b1916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b600054600160a81b900460ff16620001d45760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000c8565b60cc80546001600160a01b03191661dead179055565b608051611cee620002146000396000818161033b0152818161048a01526114ef0152611cee6000f3fe60806040526004361061015f5760003560e01c80636e296e45116100c0578063b1b1b20911610074578063c4d66de811610059578063c4d66de8146103ed578063d764ad0b1461040d578063ecc704281461042057600080fd5b8063b1b1b2091461039d578063b28ade25146103cd57600080fd5b80638cbeeef2116100a55780638cbeeef2146102505780639fce812c14610329578063a4e7f8bd1461035d57600080fd5b80636e296e45146102fd57806383a740741461031257600080fd5b80633f827a5a1161011757806354fd4d50116100fc57806354fd4d50146102665780635644cfdf146102bc5780636425666b146102d257600080fd5b80633f827a5a146102285780634c1d6a691461025057600080fd5b80630ff754ea116101485780630ff754ea146101ac5780632828d7e8146101fe5780633dbb202b1461021357600080fd5b8063028f85f7146101645780630c56849814610197575b600080fd5b34801561017057600080fd5b50610179601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101a357600080fd5b50610179603f81565b3480156101b857600080fd5b5060f9546101d99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161018e565b34801561020a57600080fd5b50610179604081565b6102266102213660046117ba565b610485565b005b34801561023457600080fd5b5061023d600181565b60405161ffff909116815260200161018e565b34801561025c57600080fd5b50610179619c4081565b34801561027257600080fd5b506102af6040518060400160405280600581526020017f312e372e3000000000000000000000000000000000000000000000000000000081525081565b60405161018e919061188c565b3480156102c857600080fd5b5061017961138881565b3480156102de57600080fd5b5060f95473ffffffffffffffffffffffffffffffffffffffff166101d9565b34801561030957600080fd5b506101d96106e9565b34801561031e57600080fd5b5061017962030d4081565b34801561033557600080fd5b506101d97f000000000000000000000000000000000000000000000000000000000000000081565b34801561036957600080fd5b5061038d6103783660046118a6565b60ce6020526000908152604090205460ff1681565b604051901515815260200161018e565b3480156103a957600080fd5b5061038d6103b83660046118a6565b60cb6020526000908152604090205460ff1681565b3480156103d957600080fd5b506101796103e83660046118bf565b6107d5565b3480156103f957600080fd5b50610226610408366004611913565b610843565b61022661041b366004611930565b610a47565b34801561042c57600080fd5b5061047760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b60405190815260200161018e565b6105be7f00000000000000000000000000000000000000000000000000000000000000006104b48585856107d5565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061052060cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c60405160240161053c97969594939291906119ff565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526112d3565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561064360cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b86604051610655959493929190611a5e565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016107b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6107f1604063ffffffff8816611adb565b6107fb9190611b0b565b610806601088611adb565b6108139062030d40611b59565b61081d9190611b59565b6108279190611b59565b6108319190611b59565b61083b9190611b59565b949350505050565b6000546003907501000000000000000000000000000000000000000000900460ff16158015610891575060005460ff8083167401000000000000000000000000000000000000000090920416105b61091d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107af565b6000805475010000000000000000000000000000000000000000007fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff9091167401000000000000000000000000000000000000000060ff8516027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff161717905560f980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556109e561136c565b600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b60f087901c60028110610b02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016107af565b8061ffff16600003610bf7576000610b53878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f9250611445915050565b600081815260cb602052604090205490915060ff1615610bf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016107af565b505b6000610c3d898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061146492505050565b9050610c47611487565b15610c7f57853414610c5b57610c5b611b85565b600081815260ce602052604090205460ff1615610c7a57610c7a611b85565b610dd1565b3415610d33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016107af565b600081815260ce602052604090205460ff16610dd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016107af565b610dda8761157d565b15610e8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016107af565b600081815260cb602052604090205460ff1615610f2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016107af565b610f4d85610f3e611388619c40611b59565b67ffffffffffffffff166115c3565b1580610f73575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561108c57600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3201611085576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016107af565b50506112c5565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a16179055600061111d88619c405a6110e09190611bb4565b8988888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115e192505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080156111b457600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26112c1565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016112c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016107af565b5050505b50505050505050565b905090565b60f9546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c42908490611334908890839089906000908990600401611bcb565b6000604051808303818588803b15801561134d57600080fd5b505af1158015611361573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107af565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b6000611453858585856115fb565b805190602001209050949350505050565b6000611474878787878787611694565b8051906020012090509695505050505050565b60f95460009073ffffffffffffffffffffffffffffffffffffffff16331480156112ce575060f954604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116931691639bf62d829160048083019260209291908290030181865afa15801561153d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115619190611c23565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff82163014806115bd575060f95473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b6060848484846040516024016116149493929190611c40565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b60608686868686866040516024016116b196959493929190611c8a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461175557600080fd5b50565b60008083601f84011261176a57600080fd5b50813567ffffffffffffffff81111561178257600080fd5b60208301915083602082850101111561179a57600080fd5b9250929050565b803563ffffffff811681146117b557600080fd5b919050565b600080600080606085870312156117d057600080fd5b84356117db81611733565b9350602085013567ffffffffffffffff8111156117f757600080fd5b61180387828801611758565b90945092506118169050604086016117a1565b905092959194509250565b6000815180845260005b818110156118475760208185018101518683018201520161182b565b81811115611859576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061189f6020830184611821565b9392505050565b6000602082840312156118b857600080fd5b5035919050565b6000806000604084860312156118d457600080fd5b833567ffffffffffffffff8111156118eb57600080fd5b6118f786828701611758565b909450925061190a9050602085016117a1565b90509250925092565b60006020828403121561192557600080fd5b813561189f81611733565b600080600080600080600060c0888a03121561194b57600080fd5b87359650602088013561195d81611733565b9550604088013561196d81611733565b9450606088013593506080880135925060a088013567ffffffffffffffff81111561199757600080fd5b6119a38a828b01611758565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611a5160c0830184866119b6565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611a8e6080830186886119b6565b905083604083015263ffffffff831660608301529695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611b0257611b02611aac565b02949350505050565b600067ffffffffffffffff80841680611b4d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611b7c57611b7c611aac565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611bc657611bc6611aac565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611c1860a0830184611821565b979650505050505050565b600060208284031215611c3557600080fd5b815161189f81611733565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611c796080830185611821565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611cd560c0830184611821565b9897505050505050505056fea164736f6c634300080f000a", - "deployedBytecode": "0x60806040526004361061015f5760003560e01c80636e296e45116100c0578063b1b1b20911610074578063c4d66de811610059578063c4d66de8146103ed578063d764ad0b1461040d578063ecc704281461042057600080fd5b8063b1b1b2091461039d578063b28ade25146103cd57600080fd5b80638cbeeef2116100a55780638cbeeef2146102505780639fce812c14610329578063a4e7f8bd1461035d57600080fd5b80636e296e45146102fd57806383a740741461031257600080fd5b80633f827a5a1161011757806354fd4d50116100fc57806354fd4d50146102665780635644cfdf146102bc5780636425666b146102d257600080fd5b80633f827a5a146102285780634c1d6a691461025057600080fd5b80630ff754ea116101485780630ff754ea146101ac5780632828d7e8146101fe5780633dbb202b1461021357600080fd5b8063028f85f7146101645780630c56849814610197575b600080fd5b34801561017057600080fd5b50610179601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101a357600080fd5b50610179603f81565b3480156101b857600080fd5b5060f9546101d99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161018e565b34801561020a57600080fd5b50610179604081565b6102266102213660046117ba565b610485565b005b34801561023457600080fd5b5061023d600181565b60405161ffff909116815260200161018e565b34801561025c57600080fd5b50610179619c4081565b34801561027257600080fd5b506102af6040518060400160405280600581526020017f312e372e3000000000000000000000000000000000000000000000000000000081525081565b60405161018e919061188c565b3480156102c857600080fd5b5061017961138881565b3480156102de57600080fd5b5060f95473ffffffffffffffffffffffffffffffffffffffff166101d9565b34801561030957600080fd5b506101d96106e9565b34801561031e57600080fd5b5061017962030d4081565b34801561033557600080fd5b506101d97f000000000000000000000000000000000000000000000000000000000000000081565b34801561036957600080fd5b5061038d6103783660046118a6565b60ce6020526000908152604090205460ff1681565b604051901515815260200161018e565b3480156103a957600080fd5b5061038d6103b83660046118a6565b60cb6020526000908152604090205460ff1681565b3480156103d957600080fd5b506101796103e83660046118bf565b6107d5565b3480156103f957600080fd5b50610226610408366004611913565b610843565b61022661041b366004611930565b610a47565b34801561042c57600080fd5b5061047760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b60405190815260200161018e565b6105be7f00000000000000000000000000000000000000000000000000000000000000006104b48585856107d5565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061052060cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c60405160240161053c97969594939291906119ff565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526112d3565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561064360cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b86604051610655959493929190611a5e565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016107b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6107f1604063ffffffff8816611adb565b6107fb9190611b0b565b610806601088611adb565b6108139062030d40611b59565b61081d9190611b59565b6108279190611b59565b6108319190611b59565b61083b9190611b59565b949350505050565b6000546003907501000000000000000000000000000000000000000000900460ff16158015610891575060005460ff8083167401000000000000000000000000000000000000000090920416105b61091d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107af565b6000805475010000000000000000000000000000000000000000007fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff9091167401000000000000000000000000000000000000000060ff8516027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff161717905560f980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556109e561136c565b600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b60f087901c60028110610b02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016107af565b8061ffff16600003610bf7576000610b53878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f9250611445915050565b600081815260cb602052604090205490915060ff1615610bf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016107af565b505b6000610c3d898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061146492505050565b9050610c47611487565b15610c7f57853414610c5b57610c5b611b85565b600081815260ce602052604090205460ff1615610c7a57610c7a611b85565b610dd1565b3415610d33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016107af565b600081815260ce602052604090205460ff16610dd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016107af565b610dda8761157d565b15610e8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016107af565b600081815260cb602052604090205460ff1615610f2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016107af565b610f4d85610f3e611388619c40611b59565b67ffffffffffffffff166115c3565b1580610f73575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561108c57600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3201611085576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016107af565b50506112c5565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a16179055600061111d88619c405a6110e09190611bb4565b8988888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115e192505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080156111b457600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26112c1565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016112c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016107af565b5050505b50505050505050565b905090565b60f9546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c42908490611334908890839089906000908990600401611bcb565b6000604051808303818588803b15801561134d57600080fd5b505af1158015611361573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107af565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b6000611453858585856115fb565b805190602001209050949350505050565b6000611474878787878787611694565b8051906020012090509695505050505050565b60f95460009073ffffffffffffffffffffffffffffffffffffffff16331480156112ce575060f954604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116931691639bf62d829160048083019260209291908290030181865afa15801561153d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115619190611c23565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff82163014806115bd575060f95473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b6060848484846040516024016116149493929190611c40565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b60608686868686866040516024016116b196959493929190611c8a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461175557600080fd5b50565b60008083601f84011261176a57600080fd5b50813567ffffffffffffffff81111561178257600080fd5b60208301915083602082850101111561179a57600080fd5b9250929050565b803563ffffffff811681146117b557600080fd5b919050565b600080600080606085870312156117d057600080fd5b84356117db81611733565b9350602085013567ffffffffffffffff8111156117f757600080fd5b61180387828801611758565b90945092506118169050604086016117a1565b905092959194509250565b6000815180845260005b818110156118475760208185018101518683018201520161182b565b81811115611859576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061189f6020830184611821565b9392505050565b6000602082840312156118b857600080fd5b5035919050565b6000806000604084860312156118d457600080fd5b833567ffffffffffffffff8111156118eb57600080fd5b6118f786828701611758565b909450925061190a9050602085016117a1565b90509250925092565b60006020828403121561192557600080fd5b813561189f81611733565b600080600080600080600060c0888a03121561194b57600080fd5b87359650602088013561195d81611733565b9550604088013561196d81611733565b9450606088013593506080880135925060a088013567ffffffffffffffff81111561199757600080fd5b6119a38a828b01611758565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611a5160c0830184866119b6565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611a8e6080830186886119b6565b905083604083015263ffffffff831660608301529695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611b0257611b02611aac565b02949350505050565b600067ffffffffffffffff80841680611b4d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611b7c57611b7c611aac565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611bc657611bc6611aac565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611c1860a0830184611821565b979650505050505050565b600060208284031215611c3557600080fd5b815161189f81611733565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611c796080830185611821565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611cd560c0830184611821565b9897505050505050505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "baseGas(bytes,uint32)": { - "params": { - "_message": "Message to compute the amount of required gas for.", - "_minGasLimit": "Minimum desired gas limit when message goes to target." - }, - "returns": { - "_0": "Amount of gas required to guarantee message receipt." - } - }, - "initialize(address)": { - "params": { - "_portal": "Address of the OptimismPortal contract on this network." - } - }, - "messageNonce()": { - "returns": { - "_0": "Nonce of the next message to be sent, with added message version." - } - }, - "relayMessage(uint256,address,address,uint256,uint256,bytes)": { - "params": { - "_message": "Message to send to the target.", - "_minGasLimit": "Minimum amount of gas that the message can be executed with.", - "_nonce": "Nonce of the message being relayed.", - "_sender": "Address of the user who sent the message.", - "_target": "Address that the message is targeted at.", - "_value": "ETH value to send with the message." - } - }, - "sendMessage(address,bytes,uint32)": { - "params": { - "_message": "Message to trigger the target address with.", - "_minGasLimit": "Minimum gas limit that the message can be executed with.", - "_target": "Target contract or wallet address." - } - }, - "xDomainMessageSender()": { - "returns": { - "_0": "Address of the sender of the currently executing message on the other chain." - } - } - } - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"FailedRelayedMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"msgHash\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"RelayedMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"messageNonce\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"SentMessage\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"SentMessageExtension1\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSAGE_VERSION\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_CALLDATA_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_MESSENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"PORTAL\",\"outputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_CALL_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_CONSTANT_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_GAS_CHECK_BUFFER\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RELAY_RESERVED_GAS\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"baseGas\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"failedMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"_portal\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messageNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"portal\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"relayMessage\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"sendMessage\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"successfulMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"xDomainMessageSender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"baseGas(bytes,uint32)\":{\"params\":{\"_message\":\"Message to compute the amount of required gas for.\",\"_minGasLimit\":\"Minimum desired gas limit when message goes to target.\"},\"returns\":{\"_0\":\"Amount of gas required to guarantee message receipt.\"}},\"initialize(address)\":{\"params\":{\"_portal\":\"Address of the OptimismPortal contract on this network.\"}},\"messageNonce()\":{\"returns\":{\"_0\":\"Nonce of the next message to be sent, with added message version.\"}},\"relayMessage(uint256,address,address,uint256,uint256,bytes)\":{\"params\":{\"_message\":\"Message to send to the target.\",\"_minGasLimit\":\"Minimum amount of gas that the message can be executed with.\",\"_nonce\":\"Nonce of the message being relayed.\",\"_sender\":\"Address of the user who sent the message.\",\"_target\":\"Address that the message is targeted at.\",\"_value\":\"ETH value to send with the message.\"}},\"sendMessage(address,bytes,uint32)\":{\"params\":{\"_message\":\"Message to trigger the target address with.\",\"_minGasLimit\":\"Minimum gas limit that the message can be executed with.\",\"_target\":\"Target contract or wallet address.\"}},\"xDomainMessageSender()\":{\"returns\":{\"_0\":\"Address of the sender of the currently executing message on the other chain.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSAGE_VERSION()\":{\"notice\":\"Current message version identifier.\"},\"MIN_GAS_CALLDATA_OVERHEAD()\":{\"notice\":\"Extra gas added to base gas for each byte of calldata in a message.\"},\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR()\":{\"notice\":\"Denominator for dynamic overhead added to the base gas for a message.\"},\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR()\":{\"notice\":\"Numerator for dynamic overhead added to the base gas for a message.\"},\"OTHER_MESSENGER()\":{\"notice\":\"Address of the paired CrossDomainMessenger contract on the other chain.\"},\"PORTAL()\":{\"notice\":\"Address of the OptimismPortal. The public getter for this is legacy and will be removed in the future. Use `portal()` instead.\"},\"RELAY_CALL_OVERHEAD()\":{\"notice\":\"Gas reserved for performing the external call in `relayMessage`.\"},\"RELAY_CONSTANT_OVERHEAD()\":{\"notice\":\"Constant overhead added to the base gas for a message.\"},\"RELAY_GAS_CHECK_BUFFER()\":{\"notice\":\"Gas reserved for the execution between the `hasMinGas` check and the external call in `relayMessage`.\"},\"RELAY_RESERVED_GAS()\":{\"notice\":\"Gas reserved for finalizing the execution of `relayMessage` after the safe call.\"},\"baseGas(bytes,uint32)\":{\"notice\":\"Computes the amount of gas required to guarantee that a given message will be received on the other chain without running out of gas. Guaranteeing that a message will not run out of gas is important because this ensures that a message can always be replayed on the other chain if it fails to execute completely.\"},\"constructor\":{\"notice\":\"Constructs the L1CrossDomainMessenger contract.\"},\"failedMessages(bytes32)\":{\"notice\":\"Mapping of message hashes to a boolean if and only if the message has failed to be executed at least once. A message will not be present in this mapping if it successfully executed on the first attempt.\"},\"initialize(address)\":{\"notice\":\"Initializes the contract.\"},\"messageNonce()\":{\"notice\":\"Retrieves the next message nonce. Message version will be added to the upper two bytes of the message nonce. Message version allows us to treat messages as having different structures.\"},\"portal()\":{\"notice\":\"Getter for the OptimismPortal address.\"},\"relayMessage(uint256,address,address,uint256,uint256,bytes)\":{\"notice\":\"Relays a message that was sent by the other CrossDomainMessenger contract. Can only be executed via cross-chain call from the other messenger OR if the message was already received once and is currently being replayed.\"},\"sendMessage(address,bytes,uint32)\":{\"notice\":\"Sends a message to some target address on the other chain. Note that if the call always reverts, then the message will be unrelayable, and any ETH sent will be permanently locked. The same will occur if the target on the other chain is considered unsafe (see the _isUnsafeTarget() function).\"},\"successfulMessages(bytes32)\":{\"notice\":\"Mapping of message hashes to boolean receipt values. Note that a message will only be present in this mapping if it has successfully been relayed on this chain, and can therefore not be relayed again.\"},\"version()\":{\"notice\":\"Semantic version.\"},\"xDomainMessageSender()\":{\"notice\":\"Retrieves the address of the contract or wallet that initiated the currently executing message on the other chain. Will throw an error if there is no message currently being executed. Allows the recipient of a call to see who triggered it.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1CrossDomainMessenger.sol\":\"L1CrossDomainMessenger\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1CrossDomainMessenger.sol\":{\"keccak256\":\"0xe3fdf4102a94b9383f1ca917499ffeb8dd9be6317ef4ed9626a5ff44daf54461\",\"urls\":[\"bzz-raw://1c1a5f8612f0b170350e2436a64695c3e7fffd04ea1a617a64eacd4d2342a07c\",\"dweb:/ipfs/QmdoehaP6a9kyWR73LqRdqSCShiXKePwM7WJedwikvYR1w\"],\"license\":\"MIT\"},\"src/L1/L2OutputOracle.sol\":{\"keccak256\":\"0x60042eb3e619518cab9a8f2480b62871c2d813716e2e60d9a5e0c5f271c58705\",\"urls\":[\"bzz-raw://08538ef2aa99c508b56a8bb9b3c7b93476cba9dbf0b47783141e5e50a02156cc\",\"dweb:/ipfs/QmdvFZ1fUaTkNdmtB66rNAo73RxY7kccsgR6Uqz7psoXGN\"],\"license\":\"MIT\"},\"src/L1/OptimismPortal.sol\":{\"keccak256\":\"0xdca91a921b402d82b455d7f11027514e8a16dca906cf820b3afffe271beb8a13\",\"urls\":[\"bzz-raw://688912b9d6005af8395d5c2eb5c4e3367a8be7b50ea97c34fc6a7ac0e2d8fd6a\",\"dweb:/ipfs/QmNPJDwHpNmJ5VPWAJB8muRpZxYeySZDVoV1TMVN7roijJ\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x4bbbc7868e948c44f29285a69383e93251a0c330a67929fb72def01cec060d4e\",\"urls\":[\"bzz-raw://1e7ea2f8b3d49bee9c753f107ede6eda93b2cc0e34d0643fa14ebbb26c19e71b\",\"dweb:/ipfs/QmRP81F8FRVXVZs6u2f2poEPDnbFZhNwNYxHgCVEhGpEmB\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Bytes.sol\":{\"keccak256\":\"0x827f47d123b0fdf3b08816d5b33831811704dbf4e554e53f2269354f6bba8859\",\"urls\":[\"bzz-raw://3137ac7204d30a245a8b0d67aa6da5286f1bd8c90379daab561f84963b6db782\",\"dweb:/ipfs/QmWRhisw3axJK833gUScs23ETh2MLFbVzzqzYVMKSDN3S9\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x5af3a849f68f7c9108858ebac5c769da8f1c0309b5c0cb42eb5cbb15e3fe6058\",\"urls\":[\"bzz-raw://6ffe76429a96d274577be66627eddad5cd05ad36d0cb6b9b3c3f9fa8a609dd7e\",\"dweb:/ipfs/QmVhWnB7Avg684TEQ9BExWqSN1YfLehUTWoqpjymeQEQHm\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPReader.sol\":{\"keccak256\":\"0x9ba74a3b0a11693e622380807d213d5d1250d974e18b2cd768da9cbe719a6778\",\"urls\":[\"bzz-raw://0808d721ed9e05707526ee134faa051d707a95ee6b8bd6e0b1972275da8e5723\",\"dweb:/ipfs/QmcTTPu9xgckfWdbFUAcr2RAgk3J6vzyR4FpV798TjFMeN\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/libraries/trie/MerkleTrie.sol\":{\"keccak256\":\"0xf8ba770ee6666e73ae43184c700e9c704b2c4ace71f9e3c2227ddc11a8148b4c\",\"urls\":[\"bzz-raw://4702ccee1fe44aea3ee01d59e6152eb755da083f786f00947fec4437c064fe74\",\"dweb:/ipfs/QmQjFj5J7hrEM1dxJjFszzW2Cs7g7eMhYNBXonF2DXBstE\"],\"license\":\"MIT\"},\"src/libraries/trie/SecureMerkleTrie.sol\":{\"keccak256\":\"0xeaff8315cfd21197bc6bc859c2decf5d4f4838c9c357c502cdf2b1eac863d288\",\"urls\":[\"bzz-raw://79dcdcaa560aea51d138da4f5dc553a1808b6de090b2dc1629f18375edbff681\",\"dweb:/ipfs/QmbE4pUPhf5fLKW4W6cEjhQs55gEDvHmbmoBqkW1yz3bnw\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x4302ae78bcafde2737d4048bbf8fdb3dd4cd7254c015b91dfa14fdaafd412f4a\",\"urls\":[\"bzz-raw://78d3d1823ad4e1fba15921a0a361b452c85d111e2d53cbbed11a8632782ea8f3\",\"dweb:/ipfs/QmVc2rTRpn7g7WAUxDShSuy6dY5zmtbJ7hHC6sT9PcD3Gj\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"],\"license\":\"Apache-2.0\"}},\"version\":1}", - "numDeployments": 2, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 75013, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_0_0_20", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 29536, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "_initialized", - "offset": 20, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 29539, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "_initializing", - "offset": 21, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 75020, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_1_0_1600", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 75023, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_51_0_20", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 75028, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_52_0_1568", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 75031, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_101_0_1", - "offset": 0, - "slot": "101", - "type": "t_bool" - }, - { - "astId": 75036, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_102_0_1568", - "offset": 0, - "slot": "102", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 75039, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_151_0_32", - "offset": 0, - "slot": "151", - "type": "t_uint256" - }, - { - "astId": 75044, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_152_0_1568", - "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 75049, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_201_0_32", - "offset": 0, - "slot": "201", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 75054, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "spacer_202_0_32", - "offset": 0, - "slot": "202", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 75102, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "successfulMessages", - "offset": 0, - "slot": "203", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 75105, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "xDomainMsgSender", - "offset": 0, - "slot": "204", - "type": "t_address" - }, - { - "astId": 75108, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "msgNonce", - "offset": 0, - "slot": "205", - "type": "t_uint240" - }, - { - "astId": 75113, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "failedMessages", - "offset": 0, - "slot": "206", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 75118, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "__gap", - "offset": 0, - "slot": "207", - "type": "t_array(t_uint256)42_storage" - }, - { - "astId": 58481, - "contract": "src/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger", - "label": "PORTAL", - "offset": 0, - "slot": "249", - "type": "t_contract(OptimismPortal)60545" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)42_storage": { - "encoding": "inplace", - "label": "uint256[42]", - "numberOfBytes": "1344", - "base": "t_uint256" - }, - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_array(t_uint256)50_storage": { - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(OptimismPortal)60545": { - "encoding": "inplace", - "label": "contract OptimismPortal", - "numberOfBytes": "20" - }, - "t_mapping(t_bytes32,t_bool)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_uint240": { - "encoding": "inplace", - "label": "uint240", - "numberOfBytes": "30" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x526e8310c1c7d4278246e50dd7ecf7c6677e7c4c0be7a130985fa52806851526", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MESSAGE_VERSION()": { - "notice": "Current message version identifier." - }, - "MIN_GAS_CALLDATA_OVERHEAD()": { - "notice": "Extra gas added to base gas for each byte of calldata in a message." - }, - "MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR()": { - "notice": "Denominator for dynamic overhead added to the base gas for a message." - }, - "MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR()": { - "notice": "Numerator for dynamic overhead added to the base gas for a message." - }, - "OTHER_MESSENGER()": { - "notice": "Address of the paired CrossDomainMessenger contract on the other chain." - }, - "PORTAL()": { - "notice": "Address of the OptimismPortal. The public getter for this is legacy and will be removed in the future. Use `portal()` instead." - }, - "RELAY_CALL_OVERHEAD()": { - "notice": "Gas reserved for performing the external call in `relayMessage`." - }, - "RELAY_CONSTANT_OVERHEAD()": { - "notice": "Constant overhead added to the base gas for a message." - }, - "RELAY_GAS_CHECK_BUFFER()": { - "notice": "Gas reserved for the execution between the `hasMinGas` check and the external call in `relayMessage`." - }, - "RELAY_RESERVED_GAS()": { - "notice": "Gas reserved for finalizing the execution of `relayMessage` after the safe call." - }, - "baseGas(bytes,uint32)": { - "notice": "Computes the amount of gas required to guarantee that a given message will be received on the other chain without running out of gas. Guaranteeing that a message will not run out of gas is important because this ensures that a message can always be replayed on the other chain if it fails to execute completely." - }, - "constructor": { - "notice": "Constructs the L1CrossDomainMessenger contract." - }, - "failedMessages(bytes32)": { - "notice": "Mapping of message hashes to a boolean if and only if the message has failed to be executed at least once. A message will not be present in this mapping if it successfully executed on the first attempt." - }, - "initialize(address)": { - "notice": "Initializes the contract." - }, - "messageNonce()": { - "notice": "Retrieves the next message nonce. Message version will be added to the upper two bytes of the message nonce. Message version allows us to treat messages as having different structures." - }, - "portal()": { - "notice": "Getter for the OptimismPortal address." - }, - "relayMessage(uint256,address,address,uint256,uint256,bytes)": { - "notice": "Relays a message that was sent by the other CrossDomainMessenger contract. Can only be executed via cross-chain call from the other messenger OR if the message was already received once and is currently being replayed." - }, - "sendMessage(address,bytes,uint32)": { - "notice": "Sends a message to some target address on the other chain. Note that if the call always reverts, then the message will be unrelayable, and any ETH sent will be permanently locked. The same will occur if the target on the other chain is considered unsafe (see the _isUnsafeTarget() function)." - }, - "successfulMessages(bytes32)": { - "notice": "Mapping of message hashes to boolean receipt values. Note that a message will only be present in this mapping if it has successfully been relayed on this chain, and can therefore not be relayed again." - }, - "version()": { - "notice": "Semantic version." - }, - "xDomainMessageSender()": { - "notice": "Retrieves the address of the contract or wallet that initiated the currently executing message on the other chain. Will throw an error if there is no message currently being executed. Allows the recipient of a call to see who triggered it." - } - }, - "events": { - "FailedRelayedMessage(bytes32)": { - "notice": "Emitted whenever a message fails to be relayed on this chain." - }, - "RelayedMessage(bytes32)": { - "notice": "Emitted whenever a message is successfully relayed on this chain." - }, - "SentMessage(address,address,bytes,uint256,uint256)": { - "notice": "Emitted whenever a message is sent to the other chain." - }, - "SentMessageExtension1(address,uint256)": { - "notice": "Additional event data to emit, required as of Bedrock. Cannot be merged with the SentMessage event without breaking the ABI of this contract, this is good enough." - } - }, - "notice": "The L1CrossDomainMessenger is a message passing interface between L1 and L2 responsible for sending and receiving data on the L1 side. Users are encouraged to use this interface instead of interacting with lower-level contracts directly." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/L1CrossDomainMessengerProxy.json b/packages/contracts-bedrock/deployments/mainnet/L1CrossDomainMessengerProxy.json deleted file mode 100644 index 363133f4ec6c..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/L1CrossDomainMessengerProxy.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "address": "0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_libAddressManager", - "type": "address" - }, - { - "internalType": "string", - "name": "_implementationName", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "stateMutability": "payable", - "type": "fallback" - } - ], - "transactionHash": "0x3061bc0332ef45e8809cee450c3c487eba2520084c71ff38da85459aee6b9a1d", - "receipt": { - "to": null, - "from": "0x9996571372066A1545D3435C6935e3F9593A7eF5", - "contractAddress": "0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1", - "transactionIndex": 153, - "gasUsed": "225024", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd4ac3db2a7b6711dabac13ef84b398e86c647e5a24f0ffdd3458b3c66ab6cef1", - "transactionHash": "0x3061bc0332ef45e8809cee450c3c487eba2520084c71ff38da85459aee6b9a1d", - "logs": [], - "blockNumber": 12686757, - "cumulativeGasUsed": "11815865", - "status": 1, - "byzantium": true - }, - "args": [ - "0xdE1FCfB0851916CA5101820A69b13a4E276bd81F", - "OVM_L1CrossDomainMessenger" - ], - "solcInputHash": "ef3f334bac4d7e77d91b457a0d89ab0a", - "metadata": "{\"compiler\":{\"version\":\"0.7.6+commit.7338295f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_libAddressManager\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_implementationName\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_implementationName\":\"implementationName of the contract to proxy to.\",\"_libAddressManager\":\"Address of the Lib_AddressManager.\"}}},\"title\":\"Lib_ResolvedDelegateProxy\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/optimistic-ethereum/libraries/resolver/Lib_ResolvedDelegateProxy.sol\":\"Lib_ResolvedDelegateProxy\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\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 () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), 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 emit OwnershipTransferred(_owner, address(0));\\n _owner = 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 emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <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 GSN 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 payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"contracts/optimistic-ethereum/libraries/resolver/Lib_AddressManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >0.5.0 <0.8.0;\\n\\n/* External Imports */\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n/**\\n * @title Lib_AddressManager\\n */\\ncontract Lib_AddressManager is Ownable {\\n\\n /**********\\n * Events *\\n **********/\\n\\n event AddressSet(\\n string indexed _name,\\n address _newAddress,\\n address _oldAddress\\n );\\n\\n\\n /*************\\n * Variables *\\n *************/\\n\\n mapping (bytes32 => address) private addresses;\\n\\n\\n /********************\\n * Public Functions *\\n ********************/\\n\\n /**\\n * Changes the address associated with a particular name.\\n * @param _name String name to associate an address with.\\n * @param _address Address to associate with the name.\\n */\\n function setAddress(\\n string memory _name,\\n address _address\\n )\\n external\\n onlyOwner\\n {\\n bytes32 nameHash = _getNameHash(_name);\\n address oldAddress = addresses[nameHash];\\n addresses[nameHash] = _address;\\n\\n emit AddressSet(\\n _name,\\n _address,\\n oldAddress\\n );\\n }\\n\\n /**\\n * Retrieves the address associated with a given name.\\n * @param _name Name to retrieve an address for.\\n * @return Address associated with the given name.\\n */\\n function getAddress(\\n string memory _name\\n )\\n external\\n view\\n returns (\\n address\\n )\\n {\\n return addresses[_getNameHash(_name)];\\n }\\n\\n\\n /**********************\\n * Internal Functions *\\n **********************/\\n\\n /**\\n * Computes the hash of a name.\\n * @param _name Name to compute a hash for.\\n * @return Hash of the given name.\\n */\\n function _getNameHash(\\n string memory _name\\n )\\n internal\\n pure\\n returns (\\n bytes32\\n )\\n {\\n return keccak256(abi.encodePacked(_name));\\n }\\n}\\n\",\"keccak256\":\"0x636defb785a5c6650d101def6790d9104724cc7570e0d875138624d069eed257\",\"license\":\"MIT\"},\"contracts/optimistic-ethereum/libraries/resolver/Lib_ResolvedDelegateProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >0.5.0 <0.8.0;\\n\\n/* Library Imports */\\nimport { Lib_AddressManager } from \\\"./Lib_AddressManager.sol\\\";\\n\\n/**\\n * @title Lib_ResolvedDelegateProxy\\n */\\ncontract Lib_ResolvedDelegateProxy {\\n\\n /*************\\n * Variables *\\n *************/\\n\\n // Using mappings to store fields to avoid overwriting storage slots in the\\n // implementation contract. For example, instead of storing these fields at\\n // storage slot `0` & `1`, they are stored at `keccak256(key + slot)`.\\n // See: https://solidity.readthedocs.io/en/v0.7.0/internals/layout_in_storage.html\\n // NOTE: Do not use this code in your own contract system.\\n // There is a known flaw in this contract, and we will remove it from the repository\\n // in the near future. Due to the very limited way that we are using it, this flaw is\\n // not an issue in our system.\\n mapping (address => string) private implementationName;\\n mapping (address => Lib_AddressManager) private addressManager;\\n\\n\\n /***************\\n * Constructor *\\n ***************/\\n\\n /**\\n * @param _libAddressManager Address of the Lib_AddressManager.\\n * @param _implementationName implementationName of the contract to proxy to.\\n */\\n constructor(\\n address _libAddressManager,\\n string memory _implementationName\\n ) {\\n addressManager[address(this)] = Lib_AddressManager(_libAddressManager);\\n implementationName[address(this)] = _implementationName;\\n }\\n\\n\\n /*********************\\n * Fallback Function *\\n *********************/\\n\\n fallback()\\n external\\n payable\\n {\\n address target = addressManager[address(this)].getAddress(\\n (implementationName[address(this)])\\n );\\n\\n require(\\n target != address(0),\\n \\\"Target address must be initialized.\\\"\\n );\\n\\n (bool success, bytes memory returndata) = target.delegatecall(msg.data);\\n\\n if (success == true) {\\n assembly {\\n return(add(returndata, 0x20), mload(returndata))\\n }\\n } else {\\n assembly {\\n revert(add(returndata, 0x20), mload(returndata))\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfaecb051b37f1d87d588cafb17a575723cbdf7c3c2079772110f33e747e05027\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506040516104083803806104088339818101604052604081101561003357600080fd5b81516020830180516040519294929383019291908464010000000082111561005a57600080fd5b90830190602082018581111561006f57600080fd5b825164010000000081118282018810171561008957600080fd5b82525081516020918201929091019080838360005b838110156100b657818101518382015260200161009e565b50505050905090810190601f1680156100e35780820380516001836020036101000a031916815260200191505b5060409081523060009081526001602090815282822080546001600160a01b0319166001600160a01b038a16179055818152919020855161012c95509093509085019150610134565b5050506101d5565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928261016a57600085556101b0565b82601f1061018357805160ff19168380011785556101b0565b828001600101855582156101b0579182015b828111156101b0578251825591602001919060010190610195565b506101bc9291506101c0565b5090565b5b808211156101bc57600081556001016101c1565b610224806101e46000396000f3fe60806040818152306000908152600160208181528383205483825293832063bf40fac160e01b909552608490815284546002610100938216159390930260001901169190910460a481905291936001600160a01b039093169263bf40fac192909190819060c490849080156100b55780601f1061008a576101008083540402835291602001916100b5565b820191906000526020600020905b81548152906001019060200180831161009857829003601f168201915b50509250505060206040518083038186803b1580156100d357600080fd5b505afa1580156100e7573d6000803e3d6000fd5b505050506040513d60208110156100fd57600080fd5b505190506001600160a01b0381166101465760405162461bcd60e51b81526004018080602001828103825260238152602001806101cc6023913960400191505060405180910390fd5b600080826001600160a01b03166000366040518083838082843760405192019450600093509091505080830381855af49150503d80600081146101a5576040519150601f19603f3d011682016040523d82523d6000602084013e6101aa565b606091505b509092509050600182151514156101c357805160208201f35b805160208201fdfe5461726765742061646472657373206d75737420626520696e697469616c697a65642ea2646970667358221220d96dd78b72a44c11bfa8efb98d29ee53776a02c67052599da176325fcbf95b6464736f6c63430007060033", - "deployedBytecode": "0x60806040818152306000908152600160208181528383205483825293832063bf40fac160e01b909552608490815284546002610100938216159390930260001901169190910460a481905291936001600160a01b039093169263bf40fac192909190819060c490849080156100b55780601f1061008a576101008083540402835291602001916100b5565b820191906000526020600020905b81548152906001019060200180831161009857829003601f168201915b50509250505060206040518083038186803b1580156100d357600080fd5b505afa1580156100e7573d6000803e3d6000fd5b505050506040513d60208110156100fd57600080fd5b505190506001600160a01b0381166101465760405162461bcd60e51b81526004018080602001828103825260238152602001806101cc6023913960400191505060405180910390fd5b600080826001600160a01b03166000366040518083838082843760405192019450600093509091505080830381855af49150503d80600081146101a5576040519150601f19603f3d011682016040523d82523d6000602084013e6101aa565b606091505b509092509050600182151514156101c357805160208201f35b805160208201fdfe5461726765742061646472657373206d75737420626520696e697469616c697a65642ea2646970667358221220d96dd78b72a44c11bfa8efb98d29ee53776a02c67052599da176325fcbf95b6464736f6c63430007060033", - "devdoc": { - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_implementationName": "implementationName of the contract to proxy to.", - "_libAddressManager": "Address of the Lib_AddressManager." - } - } - }, - "title": "Lib_ResolvedDelegateProxy", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 15340, - "contract": "contracts/optimistic-ethereum/libraries/resolver/Lib_ResolvedDelegateProxy.sol:Lib_ResolvedDelegateProxy", - "label": "implementationName", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_address,t_string_storage)" - }, - { - "astId": 15344, - "contract": "contracts/optimistic-ethereum/libraries/resolver/Lib_ResolvedDelegateProxy.sol:Lib_ResolvedDelegateProxy", - "label": "addressManager", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_address,t_contract(Lib_AddressManager)15296)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_contract(Lib_AddressManager)15296": { - "encoding": "inplace", - "label": "contract Lib_AddressManager", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_contract(Lib_AddressManager)15296)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => contract Lib_AddressManager)", - "numberOfBytes": "32", - "value": "t_contract(Lib_AddressManager)15296" - }, - "t_mapping(t_address,t_string_storage)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => string)", - "numberOfBytes": "32", - "value": "t_string_storage" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/L1ERC721Bridge.json b/packages/contracts-bedrock/deployments/mainnet/L1ERC721Bridge.json deleted file mode 100644 index b9af96e9a073..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/L1ERC721Bridge.json +++ /dev/null @@ -1,525 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "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" - }, - { - "inputs": [], - "name": "MESSENGER", - "outputs": [ - { - "internalType": "contract CrossDomainMessenger", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OTHER_BRIDGE", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "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": "contract CrossDomainMessenger", - "name": "_messenger", - "type": "address" - } - ], - "name": "initialize", - "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" - } - ], - "address": "0x806C2d0d2BDDFf9279CB2A8722F9117f0b0aDE73", - "args": [], - "bytecode": "0x60a060405234801561001057600080fd5b50734200000000000000000000000000000000000014610034565b60405180910390fd5b6001600160a01b031660805261004a600061004f565b6101cb565b600054600390610100900460ff16158015610071575060005460ff8083169116105b6100d45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161002b565b6000805461ffff191660ff8316176101001790556100f182610136565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b600054610100900460ff166101a15760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161002b565b600080546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b6080516112116101fb600039600081816101cd0152818161023b015281816103350152610bf101526112116000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637f46ddb211610076578063aa5574521161005b578063aa55745214610213578063c4d66de814610226578063c89701a21461023957600080fd5b80637f46ddb2146101c8578063927ede2d146101ef57600080fd5b806354fd4d50116100a757806354fd4d50146101285780635d93a3fc14610171578063761f4493146101b557600080fd5b80633687011a146100c35780633cb747bf146100d8575b600080fd5b6100d66100d1366004610e47565b61025f565b005b6000546100fe9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101646040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b60405161011f9190610f35565b6101a561017f366004610f4f565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b604051901515815260200161011f565b6100d66101c3366004610f90565b61030b565b6100fe7f000000000000000000000000000000000000000000000000000000000000000081565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff166100fe565b6100d6610221366004611028565b610776565b6100d661023436600461109f565b610832565b7f00000000000000000000000000000000000000000000000000000000000000006100fe565b333b156102f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b610303868633338888888861097c565b505050505050565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff163314801561041357507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103fb91906110bc565b73ffffffffffffffffffffffffffffffffffffffff16145b61049f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f74686572206272696467650060648201526084016102ea565b3073ffffffffffffffffffffffffffffffffffffffff881603610544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c660000000000000000000000000000000000000000000060648201526084016102ea565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff161515600114610613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c31204272696467650000000000000060648201526084016102ea565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156106d357600080fd5b505af11580156106e7573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516107659493929190611122565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610819576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f7420626520616464726573732830290000000000000000000000000000000060648201526084016102ea565b610829878733888888888861097c565b50505050505050565b600054600390610100900460ff16158015610854575060005460ff8083169116105b6108e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016102ea565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905561091a82610cdc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b73ffffffffffffffffffffffffffffffffffffffff8716610a1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f74206265206164647265737328302900000000000000000000000000000060648201526084016102ea565b600063761f449360e01b888a8989898888604051602401610a469796959493929190611162565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610b8657600080fd5b505af1158015610b9a573d6000803e3d6000fd5b50506000546040517f3dbb202b0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169250633dbb202b9150610c1d907f000000000000000000000000000000000000000000000000000000000000000090859089906004016111bf565b600060405180830381600087803b158015610c3757600080fd5b505af1158015610c4b573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610cc99493929190611122565b60405180910390a4505050505050505050565b600054610100900460ff16610d73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ea565b6000805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610de257600080fd5b50565b803563ffffffff81168114610df957600080fd5b919050565b60008083601f840112610e1057600080fd5b50813567ffffffffffffffff811115610e2857600080fd5b602083019150836020828501011115610e4057600080fd5b9250929050565b60008060008060008060a08789031215610e6057600080fd5b8635610e6b81610dc0565b95506020870135610e7b81610dc0565b945060408701359350610e9060608801610de5565b9250608087013567ffffffffffffffff811115610eac57600080fd5b610eb889828a01610dfe565b979a9699509497509295939492505050565b6000815180845260005b81811015610ef057602081850181015186830182015201610ed4565b81811115610f02576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610f486020830184610eca565b9392505050565b600080600060608486031215610f6457600080fd5b8335610f6f81610dc0565b92506020840135610f7f81610dc0565b929592945050506040919091013590565b600080600080600080600060c0888a031215610fab57600080fd5b8735610fb681610dc0565b96506020880135610fc681610dc0565b95506040880135610fd681610dc0565b94506060880135610fe681610dc0565b93506080880135925060a088013567ffffffffffffffff81111561100957600080fd5b6110158a828b01610dfe565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561104357600080fd5b873561104e81610dc0565b9650602088013561105e81610dc0565b9550604088013561106e81610dc0565b94506060880135935061108360808901610de5565b925060a088013567ffffffffffffffff81111561100957600080fd5b6000602082840312156110b157600080fd5b8135610f4881610dc0565b6000602082840312156110ce57600080fd5b8151610f4881610dc0565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006111586060830184866110d9565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a08301526111b260c0830184866110d9565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006111ee6060830185610eca565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100be5760003560e01c80637f46ddb211610076578063aa5574521161005b578063aa55745214610213578063c4d66de814610226578063c89701a21461023957600080fd5b80637f46ddb2146101c8578063927ede2d146101ef57600080fd5b806354fd4d50116100a757806354fd4d50146101285780635d93a3fc14610171578063761f4493146101b557600080fd5b80633687011a146100c35780633cb747bf146100d8575b600080fd5b6100d66100d1366004610e47565b61025f565b005b6000546100fe9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101646040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b60405161011f9190610f35565b6101a561017f366004610f4f565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b604051901515815260200161011f565b6100d66101c3366004610f90565b61030b565b6100fe7f000000000000000000000000000000000000000000000000000000000000000081565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff166100fe565b6100d6610221366004611028565b610776565b6100d661023436600461109f565b610832565b7f00000000000000000000000000000000000000000000000000000000000000006100fe565b333b156102f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b610303868633338888888861097c565b505050505050565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff163314801561041357507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103fb91906110bc565b73ffffffffffffffffffffffffffffffffffffffff16145b61049f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f74686572206272696467650060648201526084016102ea565b3073ffffffffffffffffffffffffffffffffffffffff881603610544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c660000000000000000000000000000000000000000000060648201526084016102ea565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff161515600114610613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c31204272696467650000000000000060648201526084016102ea565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156106d357600080fd5b505af11580156106e7573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516107659493929190611122565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610819576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f7420626520616464726573732830290000000000000000000000000000000060648201526084016102ea565b610829878733888888888861097c565b50505050505050565b600054600390610100900460ff16158015610854575060005460ff8083169116105b6108e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016102ea565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905561091a82610cdc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b73ffffffffffffffffffffffffffffffffffffffff8716610a1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f74206265206164647265737328302900000000000000000000000000000060648201526084016102ea565b600063761f449360e01b888a8989898888604051602401610a469796959493929190611162565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610b8657600080fd5b505af1158015610b9a573d6000803e3d6000fd5b50506000546040517f3dbb202b0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169250633dbb202b9150610c1d907f000000000000000000000000000000000000000000000000000000000000000090859089906004016111bf565b600060405180830381600087803b158015610c3757600080fd5b505af1158015610c4b573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610cc99493929190611122565b60405180910390a4505050505050505050565b600054610100900460ff16610d73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ea565b6000805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610de257600080fd5b50565b803563ffffffff81168114610df957600080fd5b919050565b60008083601f840112610e1057600080fd5b50813567ffffffffffffffff811115610e2857600080fd5b602083019150836020828501011115610e4057600080fd5b9250929050565b60008060008060008060a08789031215610e6057600080fd5b8635610e6b81610dc0565b95506020870135610e7b81610dc0565b945060408701359350610e9060608801610de5565b9250608087013567ffffffffffffffff811115610eac57600080fd5b610eb889828a01610dfe565b979a9699509497509295939492505050565b6000815180845260005b81811015610ef057602081850181015186830182015201610ed4565b81811115610f02576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610f486020830184610eca565b9392505050565b600080600060608486031215610f6457600080fd5b8335610f6f81610dc0565b92506020840135610f7f81610dc0565b929592945050506040919091013590565b600080600080600080600060c0888a031215610fab57600080fd5b8735610fb681610dc0565b96506020880135610fc681610dc0565b95506040880135610fd681610dc0565b94506060880135610fe681610dc0565b93506080880135925060a088013567ffffffffffffffff81111561100957600080fd5b6110158a828b01610dfe565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561104357600080fd5b873561104e81610dc0565b9650602088013561105e81610dc0565b9550604088013561106e81610dc0565b94506060880135935061108360808901610de5565b925060a088013567ffffffffffffffff81111561100957600080fd5b6000602082840312156110b157600080fd5b8135610f4881610dc0565b6000602082840312156110ce57600080fd5b8151610f4881610dc0565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006111586060830184866110d9565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a08301526111b260c0830184866110d9565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006111ee6060830185610eca565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "bridgeERC721(address,address,uint256,uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.", - "_localToken": "Address of the ERC721 on this domain.", - "_minGasLimit": "Minimum gas limit for the bridge message on the other domain.", - "_remoteToken": "Address of the ERC721 on the remote domain.", - "_tokenId": "Token ID to bridge." - } - }, - "bridgeERC721To(address,address,address,uint256,uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.", - "_localToken": "Address of the ERC721 on this domain.", - "_minGasLimit": "Minimum gas limit for the bridge message on the other domain.", - "_remoteToken": "Address of the ERC721 on the remote domain.", - "_to": "Address to receive the token on the other domain.", - "_tokenId": "Token ID to bridge." - } - }, - "finalizeBridgeERC721(address,address,address,address,uint256,bytes)": { - "params": { - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_from": "Address that triggered the bridge on the other domain.", - "_localToken": "Address of the ERC721 token on this domain.", - "_remoteToken": "Address of the ERC721 token on the other domain.", - "_to": "Address to receive the token on this domain.", - "_tokenId": "ID of the token being deposited." - } - }, - "initialize(address)": { - "params": { - "_messenger": "Address of the CrossDomainMessenger on this network." - } - }, - "otherBridge()": { - "returns": { - "_0": "Address of the bridge on the other network." - } - } - }, - "title": "L1ERC721Bridge" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC721BridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC721BridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC721\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC721To\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeBridgeERC721\"},{\"inputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"_messenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bridgeERC721(address,address,uint256,uint32,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.\",\"_localToken\":\"Address of the ERC721 on this domain.\",\"_minGasLimit\":\"Minimum gas limit for the bridge message on the other domain.\",\"_remoteToken\":\"Address of the ERC721 on the remote domain.\",\"_tokenId\":\"Token ID to bridge.\"}},\"bridgeERC721To(address,address,address,uint256,uint32,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.\",\"_localToken\":\"Address of the ERC721 on this domain.\",\"_minGasLimit\":\"Minimum gas limit for the bridge message on the other domain.\",\"_remoteToken\":\"Address of the ERC721 on the remote domain.\",\"_to\":\"Address to receive the token on the other domain.\",\"_tokenId\":\"Token ID to bridge.\"}},\"finalizeBridgeERC721(address,address,address,address,uint256,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_from\":\"Address that triggered the bridge on the other domain.\",\"_localToken\":\"Address of the ERC721 token on this domain.\",\"_remoteToken\":\"Address of the ERC721 token on the other domain.\",\"_to\":\"Address to receive the token on this domain.\",\"_tokenId\":\"ID of the token being deposited.\"}},\"initialize(address)\":{\"params\":{\"_messenger\":\"Address of the CrossDomainMessenger on this network.\"}},\"otherBridge()\":{\"returns\":{\"_0\":\"Address of the bridge on the other network.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSENGER()\":{\"notice\":\"Getter for messenger contract.\"},\"OTHER_BRIDGE()\":{\"notice\":\"Address of the bridge on the other network.\"},\"bridgeERC721(address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to the caller's account on the other chain. Note that this function can only be called by EOAs. Smart contract wallets should use the `bridgeERC721To` function after ensuring that the recipient address on the remote chain exists. Also note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2.\"},\"bridgeERC721To(address,address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to some recipient's account on the other chain. Note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2.\"},\"constructor\":{\"notice\":\"Constructs the contract.\"},\"deposits(address,address,uint256)\":{\"notice\":\"Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token by ID was deposited for a given L2 token.\"},\"finalizeBridgeERC721(address,address,address,address,uint256,bytes)\":{\"notice\":\"Completes an ERC721 bridge from the other domain and sends the ERC721 token to the recipient on this domain.\"},\"initialize(address)\":{\"notice\":\"Initializes the contract.\"},\"messenger()\":{\"notice\":\"Messenger contract on this domain.\"},\"otherBridge()\":{\"notice\":\"Getter for other bridge address.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1ERC721Bridge.sol\":\"L1ERC721Bridge\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"keccak256\":\"0xed6a749c5373af398105ce6ee3ac4763aa450ea7285d268c85d9eeca809cdb1f\",\"urls\":[\"bzz-raw://20a97f891d06f0fe91560ea1a142aaa26fdd22bed1b51606b7d48f670deeb50f\",\"dweb:/ipfs/QmTbCtZKChpaX5H2iRiTDMcSz29GSLCpTCDgJpcMR4wg8x\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"urls\":[\"bzz-raw://26fef835622b46a5ba08b3ef6b46a22e94b5f285d0f0fb66b703bd30217d2c34\",\"dweb:/ipfs/QmZ548qdwfL1qF7aXz3xh1GCdTiST81kGGuKRqVUfYmPZR\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1ERC721Bridge.sol\":{\"keccak256\":\"0xfcbde0f08cd5601aac88a40ee9224f59af9c7f5c404d67f37cbb0abd5f298b1f\",\"urls\":[\"bzz-raw://f1d26441cb269c4e1d45b2739342c016d8ec461dcb99c30da6e649e58d3b376d\",\"dweb:/ipfs/QmU4sYC5ZBGWtgwV2isLp8pXhvNum34d6Fsdsj7UNLEcUw\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L2/L2ERC721Bridge.sol\":{\"keccak256\":\"0xcc0de3ee4e726fe4a0a52a0684fc30454a49190d600c7cbeade798ae020d70f6\",\"urls\":[\"bzz-raw://bfa81e6c23f59237794bce97ad55cca091980c3db50bb295f836ab20cb58e4c8\",\"dweb:/ipfs/QmSpfckbZeoCEAASqxWdFm7t8q6Rqkqwk2jQFSCKEBXEVs\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x5af3a849f68f7c9108858ebac5c769da8f1c0309b5c0cb42eb5cbb15e3fe6058\",\"urls\":[\"bzz-raw://6ffe76429a96d274577be66627eddad5cd05ad36d0cb6b9b3c3f9fa8a609dd7e\",\"dweb:/ipfs/QmVhWnB7Avg684TEQ9BExWqSN1YfLehUTWoqpjymeQEQHm\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x4302ae78bcafde2737d4048bbf8fdb3dd4cd7254c015b91dfa14fdaafd412f4a\",\"urls\":[\"bzz-raw://78d3d1823ad4e1fba15921a0a361b452c85d111e2d53cbbed11a8632782ea8f3\",\"dweb:/ipfs/QmVc2rTRpn7g7WAUxDShSuy6dY5zmtbJ7hHC6sT9PcD3Gj\"],\"license\":\"MIT\"},\"src/universal/ERC721Bridge.sol\":{\"keccak256\":\"0x1aba1c039fa759d7d081e0d60c5d742e8d3147f0eda19af5c17cf291b4f53213\",\"urls\":[\"bzz-raw://a3581c48036bf901da4dd823f4b2fc65870414a116b32ed042d89778a2027e3f\",\"dweb:/ipfs/QmVqTCMR6NroWCQzjc1vkznHp1XbNFSYXNDgrvXUDEuZoA\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC721.sol\":{\"keccak256\":\"0xb3a65b067e67a9e1fa0493401c8d247970377c6725eba4e7b02ce8099c4f4f52\",\"urls\":[\"bzz-raw://86bb6864027560ade2f4ced6a6e34213cbff8002977dc365377e5a0b473cf17b\",\"dweb:/ipfs/QmQvjtodTK27as1g1PzsYk9NyJJ3X6a6251o1vrBwx7DPT\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 2, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 32100, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 32103, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 75549, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "messenger", - "offset": 2, - "slot": "0", - "type": "t_contract(CrossDomainMessenger)75534" - }, - { - "astId": 75557, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)48_storage" - }, - { - "astId": 58637, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "deposits", - "offset": 0, - "slot": "49", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)48_storage": { - "encoding": "inplace", - "label": "uint256[48]", - "numberOfBytes": "1536", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(CrossDomainMessenger)75534": { - "encoding": "inplace", - "label": "contract CrossDomainMessenger", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => mapping(uint256 => bool)))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_bool))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(uint256 => bool))", - "numberOfBytes": "32", - "value": "t_mapping(t_uint256,t_bool)" - }, - "t_mapping(t_uint256,t_bool)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0xd3deadba9121b516e8005639f785bf7d6db2d8089880d88878e9641cc564d313", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MESSENGER()": { - "notice": "Getter for messenger contract." - }, - "OTHER_BRIDGE()": { - "notice": "Address of the bridge on the other network." - }, - "bridgeERC721(address,address,uint256,uint32,bytes)": { - "notice": "Initiates a bridge of an NFT to the caller's account on the other chain. Note that this function can only be called by EOAs. Smart contract wallets should use the `bridgeERC721To` function after ensuring that the recipient address on the remote chain exists. Also note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2." - }, - "bridgeERC721To(address,address,address,uint256,uint32,bytes)": { - "notice": "Initiates a bridge of an NFT to some recipient's account on the other chain. Note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2." - }, - "constructor": { - "notice": "Constructs the contract." - }, - "deposits(address,address,uint256)": { - "notice": "Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token by ID was deposited for a given L2 token." - }, - "finalizeBridgeERC721(address,address,address,address,uint256,bytes)": { - "notice": "Completes an ERC721 bridge from the other domain and sends the ERC721 token to the recipient on this domain." - }, - "initialize(address)": { - "notice": "Initializes the contract." - }, - "messenger()": { - "notice": "Messenger contract on this domain." - }, - "otherBridge()": { - "notice": "Getter for other bridge address." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "ERC721BridgeFinalized(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC721 bridge from the other network is finalized." - }, - "ERC721BridgeInitiated(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC721 bridge to the other network is initiated." - } - }, - "notice": "The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract acts as an escrow for ERC721 tokens deposited into L2." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/L1ERC721BridgeProxy.json b/packages/contracts-bedrock/deployments/mainnet/L1ERC721BridgeProxy.json deleted file mode 100644 index 6be5dc01aedd..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/L1ERC721BridgeProxy.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "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-bedrock/deployments/mainnet/L1StandardBridge.json b/packages/contracts-bedrock/deployments/mainnet/L1StandardBridge.json deleted file mode 100644 index 03c2d8ed82bd..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/L1StandardBridge.json +++ /dev/null @@ -1,1122 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "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": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20BridgeFinalized", - "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": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20BridgeInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l1Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20DepositInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l1Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20WithdrawalFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHBridgeFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHBridgeInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHDepositInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHWithdrawalFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "inputs": [], - "name": "MESSENGER", - "outputs": [ - { - "internalType": "contract CrossDomainMessenger", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OTHER_BRIDGE", - "outputs": [ - { - "internalType": "contract StandardBridge", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_localToken", - "type": "address" - }, - { - "internalType": "address", - "name": "_remoteToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeERC20", - "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": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeERC20To", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeETH", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeETHTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "depositERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "depositERC20To", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "depositETH", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "depositETHTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "deposits", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "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": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeBridgeERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeBridgeETH", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeERC20Withdrawal", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeETHWithdrawal", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract CrossDomainMessenger", - "name": "_messenger", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l2TokenBridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "messenger", - "outputs": [ - { - "internalType": "contract CrossDomainMessenger", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "otherBridge", - "outputs": [ - { - "internalType": "contract StandardBridge", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "address": "0xcfBCbA6d9E84A3c4FaE0eda9684cE39a09aa2c8A", - "args": [], - "bytecode": "0x60a06040523480156200001157600080fd5b507342000000000000000000000000000000000000106080526200003660006200003c565b620001bb565b600054600390610100900460ff161580156200005f575060005460ff8083169116105b620000c85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805461ffff191660ff831617610100179055620000e7826200012c565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b600054610100900460ff16620001995760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000bf565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b608051612a44620001fa60003960008181610379015281816104300152818161057001528181610a22015281816113d80152611a8b0152612a446000f3fe6080604052600436106101635760003560e01c806387087623116100c0578063a9f9e67511610074578063c4d66de811610059578063c4d66de8146104c5578063c89701a214610421578063e11013dd146104e557600080fd5b8063a9f9e67514610492578063b1a1a882146104b257600080fd5b806391c49bf8116100a557806391c49bf814610421578063927ede2d146104545780639a2ac6d51461047f57600080fd5b806387087623146103bb5780638f601f66146103db57600080fd5b8063540abf731161011757806358a997f6116100fc57806358a997f6146103475780637f46ddb214610367578063838b25201461039b57600080fd5b8063540abf73146102d157806354fd4d50146102f157600080fd5b80631532ec34116101485780631532ec34146102545780631635f5fd146102675780633cb747bf1461027a57600080fd5b80630166a07a1461022157806309fc88431461024157600080fd5b3661021c57333b156101fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61021a333362030d40604051806020016040528060008152506104f8565b005b600080fd5b34801561022d57600080fd5b5061021a61023c36600461248b565b61050b565b61021a61024f36600461253c565b6108d2565b61021a61026236600461258f565b6109a9565b61021a61027536600461258f565b6109bd565b34801561028657600080fd5b506003546102a79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102dd57600080fd5b5061021a6102ec366004612602565b610e33565b3480156102fd57600080fd5b5061033a6040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516102c891906126ef565b34801561035357600080fd5b5061021a610362366004612702565b610e78565b34801561037357600080fd5b506102a77f000000000000000000000000000000000000000000000000000000000000000081565b3480156103a757600080fd5b5061021a6103b6366004612602565b610f4c565b3480156103c757600080fd5b5061021a6103d6366004612702565b610f91565b3480156103e757600080fd5b506104136103f6366004612785565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c8565b34801561042d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102a7565b34801561046057600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a7565b61021a61048d3660046127be565b611065565b34801561049e57600080fd5b5061021a6104ad36600461248b565b6110a7565b61021a6104c036600461253c565b6110b6565b3480156104d157600080fd5b5061021a6104e0366004612821565b611187565b61021a6104f33660046127be565b6112d1565b6105058484348585611314565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff16331480156105fa5750600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116931691636e296e459160048083019260209291908290030181865afa1580156105be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e2919061283e565b73ffffffffffffffffffffffffffffffffffffffff16145b6106ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101f3565b6106b5876114fa565b15610803576106c4878761155c565b610776576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101f3565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156107e657600080fd5b505af11580156107fa573d6000803e3d6000fd5b50505050610885565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461084190849061288a565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c168352939052919091209190915561088590858561167c565b6108c9878787878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175092505050565b50505050505050565b333b15610961576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101f3565b6109a43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061131492505050565b505050565b6109b685858585856109bd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610aac5750600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116931691636e296e459160048083019260209291908290030181865afa158015610a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a94919061283e565b73ffffffffffffffffffffffffffffffffffffffff16145b610b5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101f3565b823414610bed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101f3565b3073ffffffffffffffffffffffffffffffffffffffff851603610c92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101f3565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610d3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101f3565b610d7f85858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117de92505050565b6000610d9c855a8660405180602001604052806000815250611851565b905080610e2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101f3565b505050505050565b6108c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061186b92505050565b333b15610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101f3565b610e2b86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bb392505050565b6108c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bb392505050565b333b15611020576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101f3565b610e2b86863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061186b92505050565b61050533858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104f892505050565b6108c98787878787878761050b565b333b15611145576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101f3565b6109a433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104f892505050565b600054600390610100900460ff161580156111a9575060005460ff8083169116105b611235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101f3565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905561126f82611bc2565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6105053385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061131492505050565b8234146113a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101f3565b6113af85858584611ca0565b60035460405173ffffffffffffffffffffffffffffffffffffffff90911690633dbb202b9085907f0000000000000000000000000000000000000000000000000000000000000000907f1635f5fd000000000000000000000000000000000000000000000000000000009061142e908b908b9086908a906024016128a1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526114c1929188906004016128ea565b6000604051808303818588803b1580156114da57600080fd5b505af11580156114ee573d6000803e3d6000fd5b50505050505050505050565b6000611526827f1d1d8b6300000000000000000000000000000000000000000000000000000000611d13565b806115565750611556827fec4fc8e300000000000000000000000000000000000000000000000000000000611d13565b92915050565b6000611588837f1d1d8b6300000000000000000000000000000000000000000000000000000000611d13565b15611631578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc919061283e565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611556565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d8573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109a49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611d36565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b38686866040516117c89392919061292f565b60405180910390a4610e2b868686868686611e42565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e631848460405161183d92919061296d565b60405180910390a361050584848484611eca565b600080600080845160208601878a8af19695505050505050565b611874876114fa565b156119c257611883878761155c565b611935576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101f3565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b1580156119a557600080fd5b505af11580156119b9573d6000803e3d6000fd5b50505050611a56565b6119e473ffffffffffffffffffffffffffffffffffffffff8816863086611f37565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611a22908490612986565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611a64878787878786611f95565b60035460405173ffffffffffffffffffffffffffffffffffffffff90911690633dbb202b907f0000000000000000000000000000000000000000000000000000000000000000907f0166a07a0000000000000000000000000000000000000000000000000000000090611ae5908b908d908c908c908c908b9060240161299e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611b78929187906004016128ea565b600060405180830381600087803b158015611b9257600080fd5b505af1158015611ba6573d6000803e3d6000fd5b5050505050505050505050565b6108c98787878787878761186b565b600054610100900460ff16611c59576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101f3565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611cff92919061296d565b60405180910390a361050584848484612023565b6000611d1e83612082565b8015611d2f5750611d2f83836120e6565b9392505050565b6000611d98826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166121b59092919063ffffffff16565b8051909150156109a45780806020019051810190611db691906129f9565b6109a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101f3565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd868686604051611eba9392919061292f565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051611f2992919061296d565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105059085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016116ce565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161200d9392919061292f565b60405180910390a4610e2b8686868686866121cc565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051611f2992919061296d565b60006120ae827f01ffc9a7000000000000000000000000000000000000000000000000000000006120e6565b801561155657506120df827fffffffff000000000000000000000000000000000000000000000000000000006120e6565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d9150600051905082801561219e575060208210155b80156121aa5750600081115b979650505050505050565b60606121c48484600085612244565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf868686604051611eba9392919061292f565b6060824710156122d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101f3565b73ffffffffffffffffffffffffffffffffffffffff85163b612354576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101f3565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161237d9190612a1b565b60006040518083038185875af1925050503d80600081146123ba576040519150601f19603f3d011682016040523d82523d6000602084013e6123bf565b606091505b50915091506121aa828286606083156123d9575081611d2f565b8251156123e95782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101f391906126ef565b73ffffffffffffffffffffffffffffffffffffffff8116811461243f57600080fd5b50565b60008083601f84011261245457600080fd5b50813567ffffffffffffffff81111561246c57600080fd5b60208301915083602082850101111561248457600080fd5b9250929050565b600080600080600080600060c0888a0312156124a657600080fd5b87356124b18161241d565b965060208801356124c18161241d565b955060408801356124d18161241d565b945060608801356124e18161241d565b93506080880135925060a088013567ffffffffffffffff81111561250457600080fd5b6125108a828b01612442565b989b979a50959850939692959293505050565b803563ffffffff8116811461253757600080fd5b919050565b60008060006040848603121561255157600080fd5b61255a84612523565b9250602084013567ffffffffffffffff81111561257657600080fd5b61258286828701612442565b9497909650939450505050565b6000806000806000608086880312156125a757600080fd5b85356125b28161241d565b945060208601356125c28161241d565b935060408601359250606086013567ffffffffffffffff8111156125e557600080fd5b6125f188828901612442565b969995985093965092949392505050565b600080600080600080600060c0888a03121561261d57600080fd5b87356126288161241d565b965060208801356126388161241d565b955060408801356126488161241d565b94506060880135935061265d60808901612523565b925060a088013567ffffffffffffffff81111561250457600080fd5b60005b8381101561269457818101518382015260200161267c565b838111156105055750506000910152565b600081518084526126bd816020860160208601612679565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611d2f60208301846126a5565b60008060008060008060a0878903121561271b57600080fd5b86356127268161241d565b955060208701356127368161241d565b94506040870135935061274b60608801612523565b9250608087013567ffffffffffffffff81111561276757600080fd5b61277389828a01612442565b979a9699509497509295939492505050565b6000806040838503121561279857600080fd5b82356127a38161241d565b915060208301356127b38161241d565b809150509250929050565b600080600080606085870312156127d457600080fd5b84356127df8161241d565b93506127ed60208601612523565b9250604085013567ffffffffffffffff81111561280957600080fd5b61281587828801612442565b95989497509550505050565b60006020828403121561283357600080fd5b8135611d2f8161241d565b60006020828403121561285057600080fd5b8151611d2f8161241d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561289c5761289c61285b565b500390565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526128e060808301846126a5565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061291960608301856126a5565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061296460608301846126a5565b95945050505050565b8281526040602082015260006121c460408301846126a5565b600082198211156129995761299961285b565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526129ed60c08301846126a5565b98975050505050505050565b600060208284031215612a0b57600080fd5b81518015158114611d2f57600080fd5b60008251612a2d818460208701612679565b919091019291505056fea164736f6c634300080f000a", - "deployedBytecode": "0x6080604052600436106101635760003560e01c806387087623116100c0578063a9f9e67511610074578063c4d66de811610059578063c4d66de8146104c5578063c89701a214610421578063e11013dd146104e557600080fd5b8063a9f9e67514610492578063b1a1a882146104b257600080fd5b806391c49bf8116100a557806391c49bf814610421578063927ede2d146104545780639a2ac6d51461047f57600080fd5b806387087623146103bb5780638f601f66146103db57600080fd5b8063540abf731161011757806358a997f6116100fc57806358a997f6146103475780637f46ddb214610367578063838b25201461039b57600080fd5b8063540abf73146102d157806354fd4d50146102f157600080fd5b80631532ec34116101485780631532ec34146102545780631635f5fd146102675780633cb747bf1461027a57600080fd5b80630166a07a1461022157806309fc88431461024157600080fd5b3661021c57333b156101fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61021a333362030d40604051806020016040528060008152506104f8565b005b600080fd5b34801561022d57600080fd5b5061021a61023c36600461248b565b61050b565b61021a61024f36600461253c565b6108d2565b61021a61026236600461258f565b6109a9565b61021a61027536600461258f565b6109bd565b34801561028657600080fd5b506003546102a79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102dd57600080fd5b5061021a6102ec366004612602565b610e33565b3480156102fd57600080fd5b5061033a6040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516102c891906126ef565b34801561035357600080fd5b5061021a610362366004612702565b610e78565b34801561037357600080fd5b506102a77f000000000000000000000000000000000000000000000000000000000000000081565b3480156103a757600080fd5b5061021a6103b6366004612602565b610f4c565b3480156103c757600080fd5b5061021a6103d6366004612702565b610f91565b3480156103e757600080fd5b506104136103f6366004612785565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c8565b34801561042d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102a7565b34801561046057600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a7565b61021a61048d3660046127be565b611065565b34801561049e57600080fd5b5061021a6104ad36600461248b565b6110a7565b61021a6104c036600461253c565b6110b6565b3480156104d157600080fd5b5061021a6104e0366004612821565b611187565b61021a6104f33660046127be565b6112d1565b6105058484348585611314565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff16331480156105fa5750600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116931691636e296e459160048083019260209291908290030181865afa1580156105be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e2919061283e565b73ffffffffffffffffffffffffffffffffffffffff16145b6106ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101f3565b6106b5876114fa565b15610803576106c4878761155c565b610776576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101f3565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156107e657600080fd5b505af11580156107fa573d6000803e3d6000fd5b50505050610885565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461084190849061288a565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c168352939052919091209190915561088590858561167c565b6108c9878787878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175092505050565b50505050505050565b333b15610961576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101f3565b6109a43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061131492505050565b505050565b6109b685858585856109bd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610aac5750600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116931691636e296e459160048083019260209291908290030181865afa158015610a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a94919061283e565b73ffffffffffffffffffffffffffffffffffffffff16145b610b5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101f3565b823414610bed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101f3565b3073ffffffffffffffffffffffffffffffffffffffff851603610c92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101f3565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610d3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101f3565b610d7f85858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506117de92505050565b6000610d9c855a8660405180602001604052806000815250611851565b905080610e2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101f3565b505050505050565b6108c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061186b92505050565b333b15610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101f3565b610e2b86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bb392505050565b6108c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bb392505050565b333b15611020576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101f3565b610e2b86863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061186b92505050565b61050533858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104f892505050565b6108c98787878787878761050b565b333b15611145576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101f3565b6109a433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506104f892505050565b600054600390610100900460ff161580156111a9575060005460ff8083169116105b611235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101f3565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905561126f82611bc2565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6105053385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061131492505050565b8234146113a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101f3565b6113af85858584611ca0565b60035460405173ffffffffffffffffffffffffffffffffffffffff90911690633dbb202b9085907f0000000000000000000000000000000000000000000000000000000000000000907f1635f5fd000000000000000000000000000000000000000000000000000000009061142e908b908b9086908a906024016128a1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526114c1929188906004016128ea565b6000604051808303818588803b1580156114da57600080fd5b505af11580156114ee573d6000803e3d6000fd5b50505050505050505050565b6000611526827f1d1d8b6300000000000000000000000000000000000000000000000000000000611d13565b806115565750611556827fec4fc8e300000000000000000000000000000000000000000000000000000000611d13565b92915050565b6000611588837f1d1d8b6300000000000000000000000000000000000000000000000000000000611d13565b15611631578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc919061283e565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611556565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d8573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109a49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611d36565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b38686866040516117c89392919061292f565b60405180910390a4610e2b868686868686611e42565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e631848460405161183d92919061296d565b60405180910390a361050584848484611eca565b600080600080845160208601878a8af19695505050505050565b611874876114fa565b156119c257611883878761155c565b611935576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101f3565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b1580156119a557600080fd5b505af11580156119b9573d6000803e3d6000fd5b50505050611a56565b6119e473ffffffffffffffffffffffffffffffffffffffff8816863086611f37565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611a22908490612986565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611a64878787878786611f95565b60035460405173ffffffffffffffffffffffffffffffffffffffff90911690633dbb202b907f0000000000000000000000000000000000000000000000000000000000000000907f0166a07a0000000000000000000000000000000000000000000000000000000090611ae5908b908d908c908c908c908b9060240161299e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611b78929187906004016128ea565b600060405180830381600087803b158015611b9257600080fd5b505af1158015611ba6573d6000803e3d6000fd5b5050505050505050505050565b6108c98787878787878761186b565b600054610100900460ff16611c59576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101f3565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611cff92919061296d565b60405180910390a361050584848484612023565b6000611d1e83612082565b8015611d2f5750611d2f83836120e6565b9392505050565b6000611d98826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166121b59092919063ffffffff16565b8051909150156109a45780806020019051810190611db691906129f9565b6109a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101f3565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd868686604051611eba9392919061292f565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051611f2992919061296d565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105059085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016116ce565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161200d9392919061292f565b60405180910390a4610e2b8686868686866121cc565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051611f2992919061296d565b60006120ae827f01ffc9a7000000000000000000000000000000000000000000000000000000006120e6565b801561155657506120df827fffffffff000000000000000000000000000000000000000000000000000000006120e6565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d9150600051905082801561219e575060208210155b80156121aa5750600081115b979650505050505050565b60606121c48484600085612244565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf868686604051611eba9392919061292f565b6060824710156122d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101f3565b73ffffffffffffffffffffffffffffffffffffffff85163b612354576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101f3565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161237d9190612a1b565b60006040518083038185875af1925050503d80600081146123ba576040519150601f19603f3d011682016040523d82523d6000602084013e6123bf565b606091505b50915091506121aa828286606083156123d9575081611d2f565b8251156123e95782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101f391906126ef565b73ffffffffffffffffffffffffffffffffffffffff8116811461243f57600080fd5b50565b60008083601f84011261245457600080fd5b50813567ffffffffffffffff81111561246c57600080fd5b60208301915083602082850101111561248457600080fd5b9250929050565b600080600080600080600060c0888a0312156124a657600080fd5b87356124b18161241d565b965060208801356124c18161241d565b955060408801356124d18161241d565b945060608801356124e18161241d565b93506080880135925060a088013567ffffffffffffffff81111561250457600080fd5b6125108a828b01612442565b989b979a50959850939692959293505050565b803563ffffffff8116811461253757600080fd5b919050565b60008060006040848603121561255157600080fd5b61255a84612523565b9250602084013567ffffffffffffffff81111561257657600080fd5b61258286828701612442565b9497909650939450505050565b6000806000806000608086880312156125a757600080fd5b85356125b28161241d565b945060208601356125c28161241d565b935060408601359250606086013567ffffffffffffffff8111156125e557600080fd5b6125f188828901612442565b969995985093965092949392505050565b600080600080600080600060c0888a03121561261d57600080fd5b87356126288161241d565b965060208801356126388161241d565b955060408801356126488161241d565b94506060880135935061265d60808901612523565b925060a088013567ffffffffffffffff81111561250457600080fd5b60005b8381101561269457818101518382015260200161267c565b838111156105055750506000910152565b600081518084526126bd816020860160208601612679565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611d2f60208301846126a5565b60008060008060008060a0878903121561271b57600080fd5b86356127268161241d565b955060208701356127368161241d565b94506040870135935061274b60608801612523565b9250608087013567ffffffffffffffff81111561276757600080fd5b61277389828a01612442565b979a9699509497509295939492505050565b6000806040838503121561279857600080fd5b82356127a38161241d565b915060208301356127b38161241d565b809150509250929050565b600080600080606085870312156127d457600080fd5b84356127df8161241d565b93506127ed60208601612523565b9250604085013567ffffffffffffffff81111561280957600080fd5b61281587828801612442565b95989497509550505050565b60006020828403121561283357600080fd5b8135611d2f8161241d565b60006020828403121561285057600080fd5b8151611d2f8161241d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561289c5761289c61285b565b500390565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526128e060808301846126a5565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061291960608301856126a5565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061296460608301846126a5565b95945050505050565b8281526040602082015260006121c460408301846126a5565b600082198211156129995761299961285b565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526129ed60c08301846126a5565b98975050505050505050565b600060208284031215612a0b57600080fd5b81518015158114611d2f57600080fd5b60008251612a2d818460208701612679565b919091019291505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "MESSENGER()": {}, - "bridgeERC20(address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of local tokens to deposit.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_localToken": "Address of the ERC20 on this chain.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", - "_remoteToken": "Address of the corresponding token on the remote chain." - } - }, - "bridgeERC20To(address,address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of local tokens to deposit.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_localToken": "Address of the ERC20 on this chain.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", - "_remoteToken": "Address of the corresponding token on the remote chain.", - "_to": "Address of the receiver." - } - }, - "bridgeETH(uint32,bytes)": { - "params": { - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with." - } - }, - "bridgeETHTo(address,uint32,bytes)": { - "params": { - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", - "_to": "Address of the receiver." - } - }, - "depositERC20(address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of the ERC20 to deposit.", - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_l1Token": "Address of the L1 token being deposited.", - "_l2Token": "Address of the corresponding token on L2.", - "_minGasLimit": "Minimum gas limit for the deposit message on L2." - } - }, - "depositERC20To(address,address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of the ERC20 to deposit.", - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_l1Token": "Address of the L1 token being deposited.", - "_l2Token": "Address of the corresponding token on L2.", - "_minGasLimit": "Minimum gas limit for the deposit message on L2.", - "_to": "Address of the recipient on L2." - } - }, - "depositETH(uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_minGasLimit": "Minimum gas limit for the deposit message on L2." - } - }, - "depositETHTo(address,uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_minGasLimit": "Minimum gas limit for the deposit message on L2.", - "_to": "Address of the recipient on L2." - } - }, - "finalizeBridgeERC20(address,address,address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of the ERC20 being bridged.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_from": "Address of the sender.", - "_localToken": "Address of the ERC20 on this chain.", - "_remoteToken": "Address of the corresponding token on the remote chain.", - "_to": "Address of the receiver." - } - }, - "finalizeBridgeETH(address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of ETH being bridged.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_from": "Address of the sender.", - "_to": "Address of the receiver." - } - }, - "finalizeERC20Withdrawal(address,address,address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of the ERC20 to withdraw.", - "_extraData": "Optional data forwarded from L2.", - "_from": "Address of the withdrawer on L2.", - "_l1Token": "Address of the token on L1.", - "_l2Token": "Address of the corresponding token on L2.", - "_to": "Address of the recipient on L1." - } - }, - "finalizeETHWithdrawal(address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of ETH to withdraw.", - "_extraData": "Optional data forwarded from L2.", - "_from": "Address of the withdrawer on L2.", - "_to": "Address of the recipient on L1." - } - }, - "l2TokenBridge()": { - "returns": { - "_0": "Address of the corresponding L2 bridge contract." - } - } - }, - "events": { - "ERC20DepositInitiated(address,address,address,address,uint256,bytes)": { - "params": { - "amount": "Amount of the ERC20 deposited.", - "extraData": "Extra data attached to the deposit.", - "from": "Address of the depositor.", - "l1Token": "Address of the token on L1.", - "l2Token": "Address of the corresponding token on L2.", - "to": "Address of the recipient on L2." - } - }, - "ERC20WithdrawalFinalized(address,address,address,address,uint256,bytes)": { - "params": { - "amount": "Amount of the ERC20 withdrawn.", - "extraData": "Extra data attached to the withdrawal.", - "from": "Address of the withdrawer.", - "l1Token": "Address of the token on L1.", - "l2Token": "Address of the corresponding token on L2.", - "to": "Address of the recipient on L1." - } - }, - "ETHDepositInitiated(address,address,uint256,bytes)": { - "params": { - "amount": "Amount of ETH deposited.", - "extraData": "Extra data attached to the deposit.", - "from": "Address of the depositor.", - "to": "Address of the recipient on L2." - } - }, - "ETHWithdrawalFinalized(address,address,uint256,bytes)": { - "params": { - "amount": "Amount of ETH withdrawn.", - "extraData": "Extra data attached to the withdrawal.", - "from": "Address of the withdrawer.", - "to": "Address of the recipient on L1." - } - } - } - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20BridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20BridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20DepositInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20WithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHBridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHBridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHDepositInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHWithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"contract StandardBridge\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC20To\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"bridgeETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"bridgeETHTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"depositERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"depositERC20To\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositETHTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeBridgeERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"finalizeBridgeETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeERC20Withdrawal\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"finalizeETHWithdrawal\"},{\"inputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"_messenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2TokenBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"contract StandardBridge\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"MESSENGER()\":{\"custom:legacy\":\"@return Messenger contract on this domain.\"},\"bridgeERC20(address,address,uint256,uint32,bytes)\":{\"params\":{\"_amount\":\"Amount of local tokens to deposit.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\"}},\"bridgeERC20To(address,address,address,uint256,uint32,bytes)\":{\"params\":{\"_amount\":\"Amount of local tokens to deposit.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\",\"_to\":\"Address of the receiver.\"}},\"bridgeETH(uint32,bytes)\":{\"params\":{\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\"}},\"bridgeETHTo(address,uint32,bytes)\":{\"params\":{\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_to\":\"Address of the receiver.\"}},\"depositERC20(address,address,uint256,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ERC20 tokens into the sender's account on L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to deposit.\",\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_l1Token\":\"Address of the L1 token being deposited.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\"}},\"depositERC20To(address,address,address,uint256,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ERC20 tokens into a target account on L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to deposit.\",\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_l1Token\":\"Address of the L1 token being deposited.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\",\"_to\":\"Address of the recipient on L2.\"}},\"depositETH(uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ETH into the sender's account on L2.\",\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\"}},\"depositETHTo(address,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ETH into a target account on L2. Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will be locked in the L2StandardBridge. ETH may be recoverable if the call can be successfully replayed by increasing the amount of gas supplied to the call. If the call will fail for any amount of gas, then the ETH will be locked permanently.\",\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\",\"_to\":\"Address of the recipient on L2.\"}},\"finalizeBridgeERC20(address,address,address,address,uint256,bytes)\":{\"params\":{\"_amount\":\"Amount of the ERC20 being bridged.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_from\":\"Address of the sender.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\",\"_to\":\"Address of the receiver.\"}},\"finalizeBridgeETH(address,address,uint256,bytes)\":{\"params\":{\"_amount\":\"Amount of ETH being bridged.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_from\":\"Address of the sender.\",\"_to\":\"Address of the receiver.\"}},\"finalizeERC20Withdrawal(address,address,address,address,uint256,bytes)\":{\"custom:legacy\":\"@notice Finalizes a withdrawal of ERC20 tokens from L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to withdraw.\",\"_extraData\":\"Optional data forwarded from L2.\",\"_from\":\"Address of the withdrawer on L2.\",\"_l1Token\":\"Address of the token on L1.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_to\":\"Address of the recipient on L1.\"}},\"finalizeETHWithdrawal(address,address,uint256,bytes)\":{\"custom:legacy\":\"@notice Finalizes a withdrawal of ETH from L2.\",\"params\":{\"_amount\":\"Amount of ETH to withdraw.\",\"_extraData\":\"Optional data forwarded from L2.\",\"_from\":\"Address of the withdrawer on L2.\",\"_to\":\"Address of the recipient on L1.\"}},\"l2TokenBridge()\":{\"custom:legacy\":\"@notice Retrieves the access of the corresponding L2 bridge contract.\",\"returns\":{\"_0\":\"Address of the corresponding L2 bridge contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSENGER()\":{\"notice\":\"Getter for messenger contract.\"},\"OTHER_BRIDGE()\":{\"notice\":\"Corresponding bridge on the other domain. This public getter is deprecated and will be removed in the future. Please use `otherBridge` instead. This can safely be an immutable because for the L1StandardBridge, it will be set to the L2StandardBridge address, which is the same for all OP Stack chains. For the L2StandardBridge, there are not multiple proxies using the same implementation.\"},\"bridgeERC20(address,address,uint256,uint32,bytes)\":{\"notice\":\"Sends ERC20 tokens to the sender's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain.\"},\"bridgeERC20To(address,address,address,uint256,uint32,bytes)\":{\"notice\":\"Sends ERC20 tokens to a receiver's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain.\"},\"bridgeETH(uint32,bytes)\":{\"notice\":\"Sends ETH to the sender's address on the other chain.\"},\"bridgeETHTo(address,uint32,bytes)\":{\"notice\":\"Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a smart contract and the call fails, the ETH will be temporarily locked in the StandardBridge on the other chain until the call is replayed. If the call cannot be replayed with any amount of gas (call always reverts), then the ETH will be permanently locked in the StandardBridge on the other chain. ETH will also be locked if the receiver is the other bridge, because finalizeBridgeETH will revert in that case.\"},\"constructor\":{\"notice\":\"Constructs the L1StandardBridge contract.\"},\"deposits(address,address)\":{\"notice\":\"Mapping that stores deposits for a given pair of local and remote tokens.\"},\"finalizeBridgeERC20(address,address,address,address,uint256,bytes)\":{\"notice\":\"Finalizes an ERC20 bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain.\"},\"finalizeBridgeETH(address,address,uint256,bytes)\":{\"notice\":\"Finalizes an ETH bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain.\"},\"initialize(address)\":{\"notice\":\"Initializer\"},\"messenger()\":{\"notice\":\"Messenger contract on this domain. This public getter is deprecated and will be removed in the future. Please use `messenger` instead.\"},\"otherBridge()\":{\"notice\":\"Getter for the remote domain bridge contract.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1StandardBridge.sol\":\"L1StandardBridge\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"urls\":[\"bzz-raw://b2717fd2bdac99daa960a6de500754ea1b932093c946388c381da48658234b95\",\"dweb:/ipfs/QmP6QVMn6UeA3ByahyJbYQr5M6coHKBKsf3ySZSfbyA8R7\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x032807210d1d7d218963d7355d62e021a84bf1b3339f4f50be2f63b53cccaf29\",\"urls\":[\"bzz-raw://11756f42121f6541a35a8339ea899ee7514cfaa2e6d740625fcc844419296aa6\",\"dweb:/ipfs/QmekMuk6BY4DAjzeXr4MSbKdgoqqsZnA8JPtuyWc6CwXHf\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1StandardBridge.sol\":{\"keccak256\":\"0x6838bb9b120c2c55e5f86591180053fd213141310c59a7856c55289079e26818\",\"urls\":[\"bzz-raw://193330432139af7aa03e97e0bb451c8204cc0f63452edc2312fe9465f36cf48c\",\"dweb:/ipfs/Qmchazs1JtQ84dCjVUFFHFQxpL8Byh4RCEWVGVfXqZbPNi\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x5af3a849f68f7c9108858ebac5c769da8f1c0309b5c0cb42eb5cbb15e3fe6058\",\"urls\":[\"bzz-raw://6ffe76429a96d274577be66627eddad5cd05ad36d0cb6b9b3c3f9fa8a609dd7e\",\"dweb:/ipfs/QmVhWnB7Avg684TEQ9BExWqSN1YfLehUTWoqpjymeQEQHm\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x4302ae78bcafde2737d4048bbf8fdb3dd4cd7254c015b91dfa14fdaafd412f4a\",\"urls\":[\"bzz-raw://78d3d1823ad4e1fba15921a0a361b452c85d111e2d53cbbed11a8632782ea8f3\",\"dweb:/ipfs/QmVc2rTRpn7g7WAUxDShSuy6dY5zmtbJ7hHC6sT9PcD3Gj\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x6f8133b39efcbcbd5088f195dfacf1bedc3146508429c3865443909af735a04c\",\"urls\":[\"bzz-raw://adc36971e2e120458769f050428d9d2b0504516660345020c2521ee46e6d8abf\",\"dweb:/ipfs/QmPbFusQkZgGKpU8Fv5JoqL4oVeJtM3yqnhRGLY9eZT5zZ\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x39af021e492020fbeb5401371010d4a2fb69debe9596dbbead7bcd7fae248b0b\",\"urls\":[\"bzz-raw://dbeea52e586d2d7de55491a660ca76f75167ba6b43b65d29564864ee9c34a174\",\"dweb:/ipfs/QmS23vFqQxyUXhGuV1nSowZZS93CUkSnsb41uuyRtSeAED\"],\"license\":\"MIT\"},\"src/universal/Semver.sol\":{\"keccak256\":\"0x9de68ce536aee1aa616b4bf88d7ccc335460e6edd0e7170bdbf94c4fe3d41c60\",\"urls\":[\"bzz-raw://d5909c0b049b03a2bc24816ecf15b0aaf18c04a963174e1eba7624321bef330d\",\"dweb:/ipfs/QmeqdutwZWHqQMXauNR6WY8PrUpfsTiWTQyanbnGM9QqzT\"],\"license\":\"MIT\"},\"src/universal/StandardBridge.sol\":{\"keccak256\":\"0xc6ab09f73ee243757df19b3304b6ca289af84c2ce3ea4bf370a89c39c6ae5b04\",\"urls\":[\"bzz-raw://f5a3a6a7240ddb7c78b446e0647b7f5e7a8948b368a59d433efd70e927ea5c32\",\"dweb:/ipfs/QmVjEgX5LtCKz7HauTag8ukFgt5edPCVAsve6Mb3mKnXJN\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 2, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 32100, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 32103, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 77650, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "spacer_0_2_20", - "offset": 2, - "slot": "0", - "type": "t_address" - }, - { - "astId": 77653, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "spacer_1_0_20", - "offset": 0, - "slot": "1", - "type": "t_address" - }, - { - "astId": 77660, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "deposits", - "offset": 0, - "slot": "2", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" - }, - { - "astId": 77664, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "messenger", - "offset": 0, - "slot": "3", - "type": "t_contract(CrossDomainMessenger)75534" - }, - { - "astId": 77669, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "__gap", - "offset": 0, - "slot": "4", - "type": "t_array(t_uint256)46_storage" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)46_storage": { - "encoding": "inplace", - "label": "uint256[46]", - "numberOfBytes": "1472", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(CrossDomainMessenger)75534": { - "encoding": "inplace", - "label": "contract CrossDomainMessenger", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x8ce28138f3c8011f31062c645f45841bf876c5320b528e069535fa200552d919", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MESSENGER()": { - "notice": "Getter for messenger contract." - }, - "OTHER_BRIDGE()": { - "notice": "Corresponding bridge on the other domain. This public getter is deprecated and will be removed in the future. Please use `otherBridge` instead. This can safely be an immutable because for the L1StandardBridge, it will be set to the L2StandardBridge address, which is the same for all OP Stack chains. For the L2StandardBridge, there are not multiple proxies using the same implementation." - }, - "bridgeERC20(address,address,uint256,uint32,bytes)": { - "notice": "Sends ERC20 tokens to the sender's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain." - }, - "bridgeERC20To(address,address,address,uint256,uint32,bytes)": { - "notice": "Sends ERC20 tokens to a receiver's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain." - }, - "bridgeETH(uint32,bytes)": { - "notice": "Sends ETH to the sender's address on the other chain." - }, - "bridgeETHTo(address,uint32,bytes)": { - "notice": "Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a smart contract and the call fails, the ETH will be temporarily locked in the StandardBridge on the other chain until the call is replayed. If the call cannot be replayed with any amount of gas (call always reverts), then the ETH will be permanently locked in the StandardBridge on the other chain. ETH will also be locked if the receiver is the other bridge, because finalizeBridgeETH will revert in that case." - }, - "constructor": { - "notice": "Constructs the L1StandardBridge contract." - }, - "deposits(address,address)": { - "notice": "Mapping that stores deposits for a given pair of local and remote tokens." - }, - "finalizeBridgeERC20(address,address,address,address,uint256,bytes)": { - "notice": "Finalizes an ERC20 bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain." - }, - "finalizeBridgeETH(address,address,uint256,bytes)": { - "notice": "Finalizes an ETH bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain." - }, - "initialize(address)": { - "notice": "Initializer" - }, - "messenger()": { - "notice": "Messenger contract on this domain. This public getter is deprecated and will be removed in the future. Please use `messenger` instead." - }, - "otherBridge()": { - "notice": "Getter for the remote domain bridge contract." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "ERC20BridgeFinalized(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC20 bridge is finalized on this chain." - }, - "ERC20BridgeInitiated(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC20 bridge is initiated to the other chain." - }, - "ETHBridgeFinalized(address,address,uint256,bytes)": { - "notice": "Emitted when an ETH bridge is finalized on this chain." - }, - "ETHBridgeInitiated(address,address,uint256,bytes)": { - "notice": "Emitted when an ETH bridge is initiated to the other chain." - } - }, - "notice": "The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and L2. In the case that an ERC20 token is native to L1, it will be escrowed within this contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was stored within this contract. After Bedrock, ETH is instead stored inside the OptimismPortal contract. NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples of some token types that may not be properly supported by this contract include, but are not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/L1StandardBridgeProxy.json b/packages/contracts-bedrock/deployments/mainnet/L1StandardBridgeProxy.json deleted file mode 100644 index 4e1fbf899bfb..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/L1StandardBridgeProxy.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - "address": "0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "getImplementation", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_code", - "type": "bytes" - } - ], - "name": "setCode", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "setOwner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_key", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_value", - "type": "bytes32" - } - ], - "name": "setStorage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x3fb736def76e27e507bc4e451e5498f1f1beee3e82e6aa67ecef434c638a04ac", - "receipt": { - "to": null, - "from": "0x9996571372066A1545D3435C6935e3F9593A7eF5", - "contractAddress": "0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1", - "transactionIndex": 70, - "gasUsed": "471232", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xb6578d9e60cce4713437b5cf0898dd7040c9284e178aadfb7dfbb590f4f083af", - "transactionHash": "0x3fb736def76e27e507bc4e451e5498f1f1beee3e82e6aa67ecef434c638a04ac", - "logs": [], - "blockNumber": 12686786, - "cumulativeGasUsed": "6551653", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9996571372066A1545D3435C6935e3F9593A7eF5" - ], - "solcInputHash": "7531d7762a77038a37e7490a7b4b176f", - "metadata": "{\"compiler\":{\"version\":\"0.7.6+commit.7338295f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"getImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_code\",\"type\":\"bytes\"}],\"name\":\"setCode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_value\",\"type\":\"bytes32\"}],\"name\":\"setStorage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added functions `setCode` and `setStorage` for changing the code or storage of the contract. Nifty! Note for future developers: do NOT make anything in this contract 'public' unless you know what you're doing. Anything public can potentially have a function signature that conflicts with a signature attached to the implementation contract. Public functions SHOULD always have the 'proxyCallIfNotOwner' modifier unless there's some *really* good reason not to have that modifier. And there almost certainly is not a good reason to not have that modifier. Beware!\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_owner\":\"Address of the initial contract owner.\"}},\"getImplementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"getOwner()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"setCode(bytes)\":{\"params\":{\"_code\":\"New contract code to run inside this contract.\"}},\"setOwner(address)\":{\"params\":{\"_owner\":\"New owner of the proxy contract.\"}},\"setStorage(bytes32,bytes32)\":{\"params\":{\"_key\":\"Storage key to modify.\",\"_value\":\"New value for the storage key.\"}}},\"title\":\"L1ChugSplashProxy\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getImplementation()\":{\"notice\":\"Queries the implementation address. Can only be called by the owner OR by making an eth_call and setting the \\\"from\\\" address to address(0).\"},\"getOwner()\":{\"notice\":\"Queries the owner of the proxy contract. Can only be called by the owner OR by making an eth_call and setting the \\\"from\\\" address to address(0).\"},\"setCode(bytes)\":{\"notice\":\"Sets the code that should be running behind this proxy. Note that this scheme is a bit different from the standard proxy scheme where one would typically deploy the code separately and then set the implementation address. We're doing it this way because it gives us a lot more freedom on the client side. Can only be triggered by the contract owner.\"},\"setOwner(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"setStorage(bytes32,bytes32)\":{\"notice\":\"Modifies some storage slot within the proxy contract. Gives us a lot of power to perform upgrades in a more transparent way. Only callable by the owner.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/chugsplash/L1ChugSplashProxy.sol\":\"L1ChugSplashProxy\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/chugsplash/L1ChugSplashProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >0.5.0 <0.8.0;\\n\\nimport { iL1ChugSplashDeployer } from \\\"./interfaces/iL1ChugSplashDeployer.sol\\\";\\n\\n/**\\n * @title L1ChugSplashProxy\\n * @dev 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. Nifty!\\n *\\n * Note for future developers: do NOT make anything in this contract 'public' unless you know what\\n * you're doing. Anything public can potentially have a function signature that conflicts with a\\n * signature attached to the implementation contract. Public functions SHOULD always have the\\n * 'proxyCallIfNotOwner' modifier unless there's some *really* good reason not to have that\\n * modifier. And there almost certainly is not a good reason to not have that modifier. Beware!\\n */\\ncontract L1ChugSplashProxy {\\n\\n /*************\\n * Constants *\\n *************/\\n\\n // \\\"Magic\\\" prefix. When prepended to some arbitrary bytecode and used to create a contract, the\\n // appended bytecode will be deployed as given.\\n bytes13 constant internal DEPLOY_CODE_PREFIX = 0x600D380380600D6000396000f3;\\n\\n // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\\n bytes32 constant internal IMPLEMENTATION_KEY = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n // bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)\\n bytes32 constant internal OWNER_KEY = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n\\n /***************\\n * Constructor *\\n ***************/\\n \\n /**\\n * @param _owner Address of the initial contract owner.\\n */\\n constructor(\\n address _owner\\n ) {\\n _setOwner(_owner);\\n }\\n\\n\\n /**********************\\n * Function Modifiers *\\n **********************/\\n\\n /**\\n * Blocks a function from being called when the parent signals that the system should be paused\\n * 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(\\n iL1ChugSplashDeployer.isUpgrading.selector\\n )\\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(\\n ret == 0,\\n \\\"L1ChugSplashProxy: system is currently being upgraded\\\"\\n );\\n }\\n\\n _;\\n }\\n\\n /**\\n * Makes a proxy call instead of triggering the given function when the caller is either the\\n * owner or the zero address. Caller can only ever be the zero address if this function is\\n * being called off-chain via eth_call, which is totally fine and can be convenient for\\n * client-side tooling. Avoids situations where the proxy and implementation share a sighash\\n * and the proxy function ends up being called instead of the implementation one.\\n *\\n * Note: msg.sender == address(0) can ONLY be triggered off-chain via eth_call. If there's a\\n * way for someone to send a transaction with msg.sender == address(0) in any real context then\\n * we have much bigger problems. Primary reason to include this additional allowed sender is\\n * because the owner address can be changed dynamically and we do not want clients to have to\\n * keep track of the current owner in order to make an eth_call that doesn't trigger the\\n * proxied contract.\\n */\\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 /*********************\\n * Fallback Function *\\n *********************/\\n\\n fallback()\\n external\\n payable\\n {\\n // Proxy call by default.\\n _doProxyCall();\\n }\\n\\n\\n /********************\\n * Public Functions *\\n ********************/\\n\\n /**\\n * Sets the code that should be running behind this proxy. Note that this scheme is a bit\\n * different from the standard proxy scheme where one would typically deploy the code\\n * separately and then set the implementation address. We're doing it this way because it gives\\n * us a lot more freedom on the client side. Can only be triggered by the contract owner.\\n * @param _code New contract code to run inside this contract.\\n */\\n function setCode(\\n bytes memory _code\\n )\\n proxyCallIfNotOwner\\n public\\n {\\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(\\n DEPLOY_CODE_PREFIX,\\n _code\\n );\\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 * Modifies some storage slot within the proxy contract. Gives us a lot of power to perform\\n * upgrades in a more transparent way. Only callable by the owner.\\n * @param _key Storage key to modify.\\n * @param _value New value for the storage key.\\n */\\n function setStorage(\\n bytes32 _key,\\n bytes32 _value\\n )\\n proxyCallIfNotOwner\\n public\\n {\\n assembly {\\n sstore(_key, _value)\\n }\\n }\\n\\n /**\\n * Changes the owner of the proxy contract. Only callable by the owner.\\n * @param _owner New owner of the proxy contract.\\n */\\n function setOwner(\\n address _owner\\n )\\n proxyCallIfNotOwner\\n public\\n {\\n _setOwner(_owner);\\n }\\n\\n /**\\n * Queries the owner of the proxy contract. Can only be called by the owner OR by making an\\n * eth_call and setting the \\\"from\\\" address to address(0).\\n * @return Owner address.\\n */\\n function getOwner()\\n proxyCallIfNotOwner\\n public\\n returns (\\n address\\n )\\n {\\n return _getOwner();\\n }\\n\\n /**\\n * 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 * @return Implementation address.\\n */\\n function getImplementation()\\n proxyCallIfNotOwner\\n public\\n returns (\\n address\\n )\\n {\\n return _getImplementation();\\n }\\n\\n\\n /**********************\\n * Internal Functions *\\n **********************/\\n\\n /**\\n * Sets the implementation address.\\n * @param _implementation New implementation address.\\n */\\n function _setImplementation(\\n address _implementation\\n )\\n internal\\n {\\n assembly {\\n sstore(IMPLEMENTATION_KEY, _implementation)\\n }\\n }\\n\\n /**\\n * Queries the implementation address.\\n * @return Implementation address.\\n */\\n function _getImplementation()\\n internal\\n view\\n returns (\\n address\\n )\\n {\\n address implementation;\\n assembly {\\n implementation := sload(IMPLEMENTATION_KEY)\\n }\\n return implementation;\\n }\\n\\n /**\\n * Changes the owner of the proxy contract.\\n * @param _owner New owner of the proxy contract.\\n */\\n function _setOwner(\\n address _owner\\n )\\n internal\\n {\\n assembly {\\n sstore(OWNER_KEY, _owner)\\n }\\n }\\n\\n /**\\n * Queries the owner of the proxy contract.\\n * @return Owner address.\\n */\\n function _getOwner()\\n internal\\n view \\n returns (\\n address\\n )\\n {\\n address owner;\\n assembly {\\n owner := sload(OWNER_KEY)\\n }\\n return owner;\\n }\\n\\n /**\\n * Gets the code hash for a given account.\\n * @param _account Address of the account to get a code hash for.\\n * @return Code hash for the account.\\n */\\n function _getAccountCodeHash(\\n address _account\\n )\\n internal\\n view\\n returns (\\n bytes32\\n )\\n {\\n bytes32 codeHash;\\n assembly {\\n codeHash := extcodehash(_account)\\n }\\n return codeHash;\\n }\\n\\n /**\\n * Performs the proxy call via a delegatecall.\\n */\\n function _doProxyCall()\\n onlyWhenNotPaused\\n internal\\n {\\n address implementation = _getImplementation();\\n\\n require(\\n implementation != address(0),\\n \\\"L1ChugSplashProxy: implementation is not set yet\\\"\\n );\\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\":\"0x654af4f1d1aab76467c49fcce992eaf3522040ed806d656d98735c50ac235eeb\",\"license\":\"MIT\"},\"contracts/chugsplash/interfaces/iL1ChugSplashDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >0.5.0 <0.8.0;\\n\\n/**\\n * @title iL1ChugSplashDeployer\\n */\\ninterface iL1ChugSplashDeployer {\\n function isUpgrading()\\n external\\n view\\n returns (\\n bool\\n );\\n}\\n\",\"keccak256\":\"0xdab3ecb1ce03376523cd2f2ce5f991389c388829c56907987da01d99d3fc44c7\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506040516107983803806107988339818101604052602081101561003357600080fd5b505161003e81610044565b50610068565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b610721806100776000396000f3fe60806040526004361061004a5760003560e01c806313af4035146100545780636c5d4ad014610087578063893d20e81461013a5780639b0b0fda1461016b578063aaf10f421461019b575b6100526101b0565b005b34801561006057600080fd5b506100526004803603602081101561007757600080fd5b50356001600160a01b031661036c565b34801561009357600080fd5b50610052600480360360208110156100aa57600080fd5b8101906020810181356401000000008111156100c557600080fd5b8201836020820111156100d757600080fd5b803590602001918460018302840111640100000000831117156100f957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506103af945050505050565b34801561014657600080fd5b5061014f610505565b604080516001600160a01b039092168252519081900360200190f35b34801561017757600080fd5b506100526004803603604081101561018e57600080fd5b508035906020013561054b565b3480156101a757600080fd5b5061014f610589565b60006101ba6105bd565b60408051600481526024810182526020810180516001600160e01b0316635bca393160e11b1781529151815193945060009384936001600160a01b0387169392918291908083835b602083106102215780518252601f199092019160209182019101610202565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114610281576040519150601f19603f3d011682016040523d82523d6000602084013e610286565b606091505b5091509150818015610299575080516020145b156102f85760008180602001905160208110156102b557600080fd5b5051905080156102f65760405162461bcd60e51b81526004018080602001828103825260358152602001806106b76035913960400191505060405180910390fd5b505b60006103026105e2565b90506001600160a01b0381166103495760405162461bcd60e51b81526004018080602001828103825260308152602001806106546030913960400191505060405180910390fd5b3660008037600080366000845af43d6000803e80610366573d6000fd5b503d6000f35b6103746105bd565b6001600160a01b0316336001600160a01b03161480610391575033155b156103a45761039f81610607565b6103ac565b6103ac6101b0565b50565b6103b76105bd565b6001600160a01b0316336001600160a01b031614806103d4575033155b156103a45760006103e36105e2565b90506103ee8161062b565b825160208401201415610401575061039f565b60006c600d380380600d6000396000f360981b83604051602001808372ffffffffffffffffffffffffffffffffffffff19168152600d0182805190602001908083835b602083106104635780518252601f199092019160209182019101610444565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052905060008151602083016000f0905083805190602001206104b88261062b565b146104f45760405162461bcd60e51b81526004018080602001828103825260338152602001806106846033913960400191505060405180910390fd5b6104fd8161062f565b5050506103ac565b600061050f6105bd565b6001600160a01b0316336001600160a01b0316148061052c575033155b15610540576105396105bd565b9050610548565b6105486101b0565b90565b6105536105bd565b6001600160a01b0316336001600160a01b03161480610570575033155b1561057d57808255610585565b6105856101b0565b5050565b60006105936105bd565b6001600160a01b0316336001600160a01b031614806105b0575033155b15610540576105396105e2565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b3f90565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5556fe4c314368756753706c61736850726f78793a20696d706c656d656e746174696f6e206973206e6f7420736574207965744c314368756753706c61736850726f78793a20636f646520776173206e6f7420636f72726563746c79206465706c6f7965642e4c314368756753706c61736850726f78793a2073797374656d2069732063757272656e746c79206265696e67207570677261646564a26469706673582212202e20c1d0062b5a698d49624edce72a713b117e88f4cd70877869b53519c1d1f964736f6c63430007060033", - "deployedBytecode": "0x60806040526004361061004a5760003560e01c806313af4035146100545780636c5d4ad014610087578063893d20e81461013a5780639b0b0fda1461016b578063aaf10f421461019b575b6100526101b0565b005b34801561006057600080fd5b506100526004803603602081101561007757600080fd5b50356001600160a01b031661036c565b34801561009357600080fd5b50610052600480360360208110156100aa57600080fd5b8101906020810181356401000000008111156100c557600080fd5b8201836020820111156100d757600080fd5b803590602001918460018302840111640100000000831117156100f957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506103af945050505050565b34801561014657600080fd5b5061014f610505565b604080516001600160a01b039092168252519081900360200190f35b34801561017757600080fd5b506100526004803603604081101561018e57600080fd5b508035906020013561054b565b3480156101a757600080fd5b5061014f610589565b60006101ba6105bd565b60408051600481526024810182526020810180516001600160e01b0316635bca393160e11b1781529151815193945060009384936001600160a01b0387169392918291908083835b602083106102215780518252601f199092019160209182019101610202565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114610281576040519150601f19603f3d011682016040523d82523d6000602084013e610286565b606091505b5091509150818015610299575080516020145b156102f85760008180602001905160208110156102b557600080fd5b5051905080156102f65760405162461bcd60e51b81526004018080602001828103825260358152602001806106b76035913960400191505060405180910390fd5b505b60006103026105e2565b90506001600160a01b0381166103495760405162461bcd60e51b81526004018080602001828103825260308152602001806106546030913960400191505060405180910390fd5b3660008037600080366000845af43d6000803e80610366573d6000fd5b503d6000f35b6103746105bd565b6001600160a01b0316336001600160a01b03161480610391575033155b156103a45761039f81610607565b6103ac565b6103ac6101b0565b50565b6103b76105bd565b6001600160a01b0316336001600160a01b031614806103d4575033155b156103a45760006103e36105e2565b90506103ee8161062b565b825160208401201415610401575061039f565b60006c600d380380600d6000396000f360981b83604051602001808372ffffffffffffffffffffffffffffffffffffff19168152600d0182805190602001908083835b602083106104635780518252601f199092019160209182019101610444565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052905060008151602083016000f0905083805190602001206104b88261062b565b146104f45760405162461bcd60e51b81526004018080602001828103825260338152602001806106846033913960400191505060405180910390fd5b6104fd8161062f565b5050506103ac565b600061050f6105bd565b6001600160a01b0316336001600160a01b0316148061052c575033155b15610540576105396105bd565b9050610548565b6105486101b0565b90565b6105536105bd565b6001600160a01b0316336001600160a01b03161480610570575033155b1561057d57808255610585565b6105856101b0565b5050565b60006105936105bd565b6001600160a01b0316336001600160a01b031614806105b0575033155b15610540576105396105e2565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b3f90565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5556fe4c314368756753706c61736850726f78793a20696d706c656d656e746174696f6e206973206e6f7420736574207965744c314368756753706c61736850726f78793a20636f646520776173206e6f7420636f72726563746c79206465706c6f7965642e4c314368756753706c61736850726f78793a2073797374656d2069732063757272656e746c79206265696e67207570677261646564a26469706673582212202e20c1d0062b5a698d49624edce72a713b117e88f4cd70877869b53519c1d1f964736f6c63430007060033", - "devdoc": { - "details": "Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added functions `setCode` and `setStorage` for changing the code or storage of the contract. Nifty! Note for future developers: do NOT make anything in this contract 'public' unless you know what you're doing. Anything public can potentially have a function signature that conflicts with a signature attached to the implementation contract. Public functions SHOULD always have the 'proxyCallIfNotOwner' modifier unless there's some *really* good reason not to have that modifier. And there almost certainly is not a good reason to not have that modifier. Beware!", - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_owner": "Address of the initial contract owner." - } - }, - "getImplementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "getOwner()": { - "returns": { - "_0": "Owner address." - } - }, - "setCode(bytes)": { - "params": { - "_code": "New contract code to run inside this contract." - } - }, - "setOwner(address)": { - "params": { - "_owner": "New owner of the proxy contract." - } - }, - "setStorage(bytes32,bytes32)": { - "params": { - "_key": "Storage key to modify.", - "_value": "New value for the storage key." - } - } - }, - "title": "L1ChugSplashProxy", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "getImplementation()": { - "notice": "Queries the implementation address. Can only be called by the owner OR by making an eth_call and setting the \"from\" address to address(0)." - }, - "getOwner()": { - "notice": "Queries the owner of the proxy contract. Can only be called by the owner OR by making an eth_call and setting the \"from\" address to address(0)." - }, - "setCode(bytes)": { - "notice": "Sets the code that should be running behind this proxy. Note that this scheme is a bit different from the standard proxy scheme where one would typically deploy the code separately and then set the implementation address. We're doing it this way because it gives us a lot more freedom on the client side. Can only be triggered by the contract owner." - }, - "setOwner(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "setStorage(bytes32,bytes32)": { - "notice": "Modifies some storage slot within the proxy contract. Gives us a lot of power to perform upgrades in a more transparent way. Only callable by the owner." - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/L2OutputOracle.json b/packages/contracts-bedrock/deployments/mainnet/L2OutputOracle.json deleted file mode 100644 index ae9da3da298d..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/L2OutputOracle.json +++ /dev/null @@ -1,817 +0,0 @@ -{ - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_submissionInterval", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_l2BlockTime", - "type": "uint256" - }, - { - "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": "bytes32", - "name": "outputRoot", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "l2OutputIndex", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "l2BlockNumber", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "l1Timestamp", - "type": "uint256" - } - ], - "name": "OutputProposed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "prevNextOutputIndex", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "newNextOutputIndex", - "type": "uint256" - } - ], - "name": "OutputsDeleted", - "type": "event" - }, - { - "inputs": [], - "name": "CHALLENGER", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "FINALIZATION_PERIOD_SECONDS", - "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": "PROPOSER", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SUBMISSION_INTERVAL", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "challenger", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2BlockNumber", - "type": "uint256" - } - ], - "name": "computeL2Timestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2OutputIndex", - "type": "uint256" - } - ], - "name": "deleteL2Outputs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "finalizationPeriodSeconds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2OutputIndex", - "type": "uint256" - } - ], - "name": "getL2Output", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "outputRoot", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "timestamp", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "l2BlockNumber", - "type": "uint128" - } - ], - "internalType": "struct Types.OutputProposal", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2BlockNumber", - "type": "uint256" - } - ], - "name": "getL2OutputAfter", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "outputRoot", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "timestamp", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "l2BlockNumber", - "type": "uint128" - } - ], - "internalType": "struct Types.OutputProposal", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2BlockNumber", - "type": "uint256" - } - ], - "name": "getL2OutputIndexAfter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_startingBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_startingTimestamp", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_proposer", - "type": "address" - }, - { - "internalType": "address", - "name": "_challenger", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l2BlockTime", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestBlockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestOutputIndex", - "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": "nextOutputIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "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": "startingBlockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "startingTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "submissionInterval", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "address": "0xB48B1827BC7218b1aB7B000b4f0416DF8F14B16A", - "args": [], - "bytecode": "0x60e06040523480156200001157600080fd5b50604051620018ae380380620018ae8339810160408190526200003491620002f3565b60008211620000b05760405162461bcd60e51b815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e203000000000000000000000000060648201526084015b60405180910390fd5b60008311620001285760405162461bcd60e51b815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e20300000000000006064820152608401620000a7565b608083905260a082905260c08190526200014660008080806200014f565b50505062000322565b600054600390610100900460ff1615801562000172575060005460ff8083169116105b620001d75760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000a7565b6000805461ffff191660ff83161761010017905542841115620002715760405162461bcd60e51b8152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201526374696d6560e01b608482015260a401620000a7565b60028490556001859055600580546001600160a01b038581166001600160a01b03199283161790925560048054928516929091169190911790556000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6000806000606084860312156200030957600080fd5b8351925060208401519150604084015190509250925092565b60805160a05160c0516115326200037c600039600081816104b3015281816105710152610beb0152600081816101a1015281816103b9015261127401526000818161021f0152818161053b01526112c201526115326000f3fe60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec334814610517578063e1a41bcf1461052c578063f4daa2911461055f57600080fd5b8063ce5db8d6146104a4578063cf8e5cf0146104d7578063d1de856c146104f757600080fd5b8063a25ae557116100b0578063a25ae557146103f0578063a8e4fb901461044c578063bffa7f0f1461047957600080fd5b806389c44cbb1461038a57806393991af3146103aa5780639aaab648146103dd57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa51461033e5780637f00642014610354578063887862721461037457600080fd5b806369f16eec146102e95780636abcf563146102fe5780636b4d98dd1461031357600080fd5b8063529933df11610169578063529933df1461020d578063534db0e21461024157806354fd4d501461029357600080fd5b80622134cc1461018f578063019e2729146101d65780634599c788146101f8575b600080fd5b34801561019b57600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b3480156101e257600080fd5b506101f66101f136600461131c565b610593565b005b34801561020457600080fd5b506101c36107f2565b34801561021957600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b34801561024d57600080fd5b5060045461026e9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101cd565b34801561029f57600080fd5b506102dc6040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101cd9190611362565b3480156102f557600080fd5b506101c3610865565b34801561030a57600080fd5b506003546101c3565b34801561031f57600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff1661026e565b34801561034a57600080fd5b506101c360015481565b34801561036057600080fd5b506101c361036f3660046113d5565b610877565b34801561038057600080fd5b506101c360025481565b34801561039657600080fd5b506101f66103a53660046113d5565b610a8b565b3480156103b657600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b6101f66103eb3660046113ee565b610d43565b3480156103fc57600080fd5b5061041061040b3660046113d5565b6111a4565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101cd565b34801561045857600080fd5b5060055461026e9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561048557600080fd5b5060055473ffffffffffffffffffffffffffffffffffffffff1661026e565b3480156104b057600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b3480156104e357600080fd5b506104106104f23660046113d5565b611238565b34801561050357600080fd5b506101c36105123660046113d5565b611270565b34801561052357600080fd5b506101c36112be565b34801561053857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b34801561056b57600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b600054600390610100900460ff161580156105b5575060005460ff8083169116105b610646576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff8316176101001790554284111561072e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161063d565b600284905560018590556005805473ffffffffffffffffffffffffffffffffffffffff8581167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556004805492851692909116919091179055600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6003546000901561085c576003805461080d9060019061144f565b8154811061081d5761081d611466565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b6003546000906108609060019061144f565b60006108816107f2565b821115610936576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161063d565b6003546109eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161063d565b6003546000905b80821015610a845760006002610a088385611495565b610a1291906114ad565b90508460038281548110610a2857610a28611466565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610a7a57610a73816001611495565b9250610a7e565b8091505b506109f2565b5092915050565b60045473ffffffffffffffffffffffffffffffffffffffff163314610b32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161063d565b6003548110610be9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161063d565b7f000000000000000000000000000000000000000000000000000000000000000060038281548110610c1d57610c1d611466565b6000918252602090912060016002909202010154610c4d906fffffffffffffffffffffffffffffffff164261144f565b10610d00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161063d565b6000610d0b60035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60055473ffffffffffffffffffffffffffffffffffffffff163314610e10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161063d565b610e186112be565b8314610ecc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161063d565b42610ed684611270565b10610f63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161063d565b83610ff0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161063d565b81156110ac57818140146110ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161063d565b826110b660035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e2426040516110e891815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b6040805160608101825260008082526020820181905291810191909152600382815481106111d4576111d4611466565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b6040805160608101825260008082526020820181905291810191909152600361126083610877565b815481106111d4576111d4611466565b60007f0000000000000000000000000000000000000000000000000000000000000000600154836112a1919061144f565b6112ab91906114e8565b6002546112b89190611495565b92915050565b60007f00000000000000000000000000000000000000000000000000000000000000006112e96107f2565b6108609190611495565b803573ffffffffffffffffffffffffffffffffffffffff8116811461131757600080fd5b919050565b6000806000806080858703121561133257600080fd5b8435935060208501359250611349604086016112f3565b9150611357606086016112f3565b905092959194509250565b600060208083528351808285015260005b8181101561138f57858101830151858201604001528201611373565b818111156113a1576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000602082840312156113e757600080fd5b5035919050565b6000806000806080858703121561140457600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561146157611461611420565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156114a8576114a8611420565b500190565b6000826114e3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561152057611520611420565b50029056fea164736f6c634300080f000a", - "deployedBytecode": "0x60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec334814610517578063e1a41bcf1461052c578063f4daa2911461055f57600080fd5b8063ce5db8d6146104a4578063cf8e5cf0146104d7578063d1de856c146104f757600080fd5b8063a25ae557116100b0578063a25ae557146103f0578063a8e4fb901461044c578063bffa7f0f1461047957600080fd5b806389c44cbb1461038a57806393991af3146103aa5780639aaab648146103dd57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa51461033e5780637f00642014610354578063887862721461037457600080fd5b806369f16eec146102e95780636abcf563146102fe5780636b4d98dd1461031357600080fd5b8063529933df11610169578063529933df1461020d578063534db0e21461024157806354fd4d501461029357600080fd5b80622134cc1461018f578063019e2729146101d65780634599c788146101f8575b600080fd5b34801561019b57600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b3480156101e257600080fd5b506101f66101f136600461131c565b610593565b005b34801561020457600080fd5b506101c36107f2565b34801561021957600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b34801561024d57600080fd5b5060045461026e9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101cd565b34801561029f57600080fd5b506102dc6040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b6040516101cd9190611362565b3480156102f557600080fd5b506101c3610865565b34801561030a57600080fd5b506003546101c3565b34801561031f57600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff1661026e565b34801561034a57600080fd5b506101c360015481565b34801561036057600080fd5b506101c361036f3660046113d5565b610877565b34801561038057600080fd5b506101c360025481565b34801561039657600080fd5b506101f66103a53660046113d5565b610a8b565b3480156103b657600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b6101f66103eb3660046113ee565b610d43565b3480156103fc57600080fd5b5061041061040b3660046113d5565b6111a4565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101cd565b34801561045857600080fd5b5060055461026e9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561048557600080fd5b5060055473ffffffffffffffffffffffffffffffffffffffff1661026e565b3480156104b057600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b3480156104e357600080fd5b506104106104f23660046113d5565b611238565b34801561050357600080fd5b506101c36105123660046113d5565b611270565b34801561052357600080fd5b506101c36112be565b34801561053857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b34801561056b57600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b600054600390610100900460ff161580156105b5575060005460ff8083169116105b610646576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff8316176101001790554284111561072e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161063d565b600284905560018590556005805473ffffffffffffffffffffffffffffffffffffffff8581167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556004805492851692909116919091179055600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6003546000901561085c576003805461080d9060019061144f565b8154811061081d5761081d611466565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b6003546000906108609060019061144f565b60006108816107f2565b821115610936576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161063d565b6003546109eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161063d565b6003546000905b80821015610a845760006002610a088385611495565b610a1291906114ad565b90508460038281548110610a2857610a28611466565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610a7a57610a73816001611495565b9250610a7e565b8091505b506109f2565b5092915050565b60045473ffffffffffffffffffffffffffffffffffffffff163314610b32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161063d565b6003548110610be9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161063d565b7f000000000000000000000000000000000000000000000000000000000000000060038281548110610c1d57610c1d611466565b6000918252602090912060016002909202010154610c4d906fffffffffffffffffffffffffffffffff164261144f565b10610d00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161063d565b6000610d0b60035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60055473ffffffffffffffffffffffffffffffffffffffff163314610e10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161063d565b610e186112be565b8314610ecc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161063d565b42610ed684611270565b10610f63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161063d565b83610ff0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161063d565b81156110ac57818140146110ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161063d565b826110b660035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e2426040516110e891815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b6040805160608101825260008082526020820181905291810191909152600382815481106111d4576111d4611466565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b6040805160608101825260008082526020820181905291810191909152600361126083610877565b815481106111d4576111d4611466565b60007f0000000000000000000000000000000000000000000000000000000000000000600154836112a1919061144f565b6112ab91906114e8565b6002546112b89190611495565b92915050565b60007f00000000000000000000000000000000000000000000000000000000000000006112e96107f2565b6108609190611495565b803573ffffffffffffffffffffffffffffffffffffffff8116811461131757600080fd5b919050565b6000806000806080858703121561133257600080fd5b8435935060208501359250611349604086016112f3565b9150611357606086016112f3565b905092959194509250565b600060208083528351808285015260005b8181101561138f57858101830151858201604001528201611373565b818111156113a1576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000602082840312156113e757600080fd5b5035919050565b6000806000806080858703121561140457600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561146157611461611420565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156114a8576114a8611420565b500190565b6000826114e3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561152057611520611420565b50029056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "CHALLENGER()": {}, - "PROPOSER()": {}, - "computeL2Timestamp(uint256)": { - "params": { - "_l2BlockNumber": "The L2 block number of the target block." - }, - "returns": { - "_0": "L2 timestamp of the given block." - } - }, - "constructor": { - "params": { - "_finalizationPeriodSeconds": "The amount of time that must pass for an output proposal", - "_l2BlockTime": "The time per L2 block, in seconds.", - "_submissionInterval": "Interval in blocks at which checkpoints must be submitted." - } - }, - "deleteL2Outputs(uint256)": { - "params": { - "_l2OutputIndex": "Index of the first L2 output to be deleted. All outputs after this output will also be deleted." - } - }, - "getL2Output(uint256)": { - "params": { - "_l2OutputIndex": "Index of the output to return." - }, - "returns": { - "_0": "The output at the given index." - } - }, - "getL2OutputAfter(uint256)": { - "params": { - "_l2BlockNumber": "L2 block number to find a checkpoint for." - }, - "returns": { - "_0": "First checkpoint that commits to the given L2 block number." - } - }, - "getL2OutputIndexAfter(uint256)": { - "params": { - "_l2BlockNumber": "L2 block number to find a checkpoint for." - }, - "returns": { - "_0": "Index of the first checkpoint that commits to the given L2 block number." - } - }, - "initialize(uint256,uint256,address,address)": { - "params": { - "_challenger": "The address of the challenger.", - "_proposer": "The address of the proposer.", - "_startingBlockNumber": "Block number for the first recoded L2 block.", - "_startingTimestamp": "Timestamp for the first recoded L2 block." - } - }, - "latestBlockNumber()": { - "returns": { - "_0": "Latest submitted L2 block number." - } - }, - "latestOutputIndex()": { - "returns": { - "_0": "The number of outputs that have been proposed." - } - }, - "nextBlockNumber()": { - "returns": { - "_0": "Next L2 block number." - } - }, - "nextOutputIndex()": { - "returns": { - "_0": "The index of the next output to be proposed." - } - }, - "proposeL2Output(bytes32,uint256,bytes32,uint256)": { - "params": { - "_l1BlockHash": "A block hash which must be included in the current chain.", - "_l1BlockNumber": "The block number with the specified block hash.", - "_l2BlockNumber": "The L2 block number that resulted in _outputRoot.", - "_outputRoot": "The L2 output of the checkpoint block." - } - } - }, - "events": { - "OutputProposed(bytes32,uint256,uint256,uint256)": { - "params": { - "l1Timestamp": "The L1 timestamp when proposed.", - "l2BlockNumber": "The L2 block number of the output root.", - "l2OutputIndex": "The index of the output in the l2Outputs array.", - "outputRoot": "The output root." - } - }, - "OutputsDeleted(uint256,uint256)": { - "params": { - "newNextOutputIndex": "Next L2 output index after the deletion.", - "prevNextOutputIndex": "Next L2 output index before the deletion." - } - } - } - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_submissionInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriodSeconds\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"l2OutputIndex\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"l2BlockNumber\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"l1Timestamp\",\"type\":\"uint256\",\"indexed\":false}],\"type\":\"event\",\"name\":\"OutputProposed\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prevNextOutputIndex\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"newNextOutputIndex\",\"type\":\"uint256\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OutputsDeleted\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"CHALLENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"FINALIZATION_PERIOD_SECONDS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L2_BLOCK_TIME\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"PROPOSER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"SUBMISSION_INTERVAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"challenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"computeL2Timestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"deleteL2Outputs\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"finalizationPeriodSeconds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getL2Output\",\"outputs\":[{\"internalType\":\"struct Types.OutputProposal\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"}]}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getL2OutputAfter\",\"outputs\":[{\"internalType\":\"struct Types.OutputProposal\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"}]}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getL2OutputIndexAfter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_startingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startingTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_proposer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_challenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2BlockTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"latestBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"latestOutputIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"nextBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"nextOutputIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l2BlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_l1BlockHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1BlockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"proposeL2Output\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"proposer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"startingBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"startingTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"submissionInterval\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"CHALLENGER()\":{\"custom:legacy\":\"\"},\"PROPOSER()\":{\"custom:legacy\":\"\"},\"computeL2Timestamp(uint256)\":{\"params\":{\"_l2BlockNumber\":\"The L2 block number of the target block.\"},\"returns\":{\"_0\":\"L2 timestamp of the given block.\"}},\"constructor\":{\"params\":{\"_finalizationPeriodSeconds\":\"The amount of time that must pass for an output proposal\",\"_l2BlockTime\":\"The time per L2 block, in seconds.\",\"_submissionInterval\":\"Interval in blocks at which checkpoints must be submitted.\"}},\"deleteL2Outputs(uint256)\":{\"params\":{\"_l2OutputIndex\":\"Index of the first L2 output to be deleted. All outputs after this output will also be deleted.\"}},\"getL2Output(uint256)\":{\"params\":{\"_l2OutputIndex\":\"Index of the output to return.\"},\"returns\":{\"_0\":\"The output at the given index.\"}},\"getL2OutputAfter(uint256)\":{\"params\":{\"_l2BlockNumber\":\"L2 block number to find a checkpoint for.\"},\"returns\":{\"_0\":\"First checkpoint that commits to the given L2 block number.\"}},\"getL2OutputIndexAfter(uint256)\":{\"params\":{\"_l2BlockNumber\":\"L2 block number to find a checkpoint for.\"},\"returns\":{\"_0\":\"Index of the first checkpoint that commits to the given L2 block number.\"}},\"initialize(uint256,uint256,address,address)\":{\"params\":{\"_challenger\":\"The address of the challenger.\",\"_proposer\":\"The address of the proposer.\",\"_startingBlockNumber\":\"Block number for the first recoded L2 block.\",\"_startingTimestamp\":\"Timestamp for the first recoded L2 block.\"}},\"latestBlockNumber()\":{\"returns\":{\"_0\":\"Latest submitted L2 block number.\"}},\"latestOutputIndex()\":{\"returns\":{\"_0\":\"The number of outputs that have been proposed.\"}},\"nextBlockNumber()\":{\"returns\":{\"_0\":\"Next L2 block number.\"}},\"nextOutputIndex()\":{\"returns\":{\"_0\":\"The index of the next output to be proposed.\"}},\"proposeL2Output(bytes32,uint256,bytes32,uint256)\":{\"params\":{\"_l1BlockHash\":\"A block hash which must be included in the current chain.\",\"_l1BlockNumber\":\"The block number with the specified block hash.\",\"_l2BlockNumber\":\"The L2 block number that resulted in _outputRoot.\",\"_outputRoot\":\"The L2 output of the checkpoint block.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"CHALLENGER()\":{\"notice\":\"Getter for the challenger address. This will be removed in the future, use `challenger` instead.\"},\"L2_BLOCK_TIME()\":{\"notice\":\"The time between L2 blocks in seconds. Once set, this value MUST NOT be modified. Public getter is legacy and will be removed in the future. Use `l2BlockTime` instead.\"},\"PROPOSER()\":{\"notice\":\"Getter for the proposer address. This will be removed in the future, use `proposer` instead.\"},\"SUBMISSION_INTERVAL()\":{\"notice\":\"The interval in L2 blocks at which checkpoints must be submitted. Although this is immutable, it can safely be modified by upgrading the implementation contract. Public getter is legacy and will be removed in the future. Use `submissionInterval` instead.\"},\"challenger()\":{\"notice\":\"The address of the challenger. Can be updated via reinitialize.\"},\"computeL2Timestamp(uint256)\":{\"notice\":\"Returns the L2 timestamp corresponding to a given L2 block number.\"},\"constructor\":{\"notice\":\"Constructs the L2OutputOracle contract.\"},\"deleteL2Outputs(uint256)\":{\"notice\":\"Deletes all output proposals after and including the proposal that corresponds to the given output index. Only the challenger address can delete outputs.\"},\"finalizationPeriodSeconds()\":{\"notice\":\"Getter for the finalization period.\"},\"getL2Output(uint256)\":{\"notice\":\"Returns an output by index. Needed to return a struct instead of a tuple.\"},\"getL2OutputAfter(uint256)\":{\"notice\":\"Returns the L2 output proposal that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block.\"},\"getL2OutputIndexAfter(uint256)\":{\"notice\":\"Returns the index of the L2 output that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block.\"},\"initialize(uint256,uint256,address,address)\":{\"notice\":\"Initializer.\"},\"l2BlockTime()\":{\"notice\":\"Getter for the L2 block time.\"},\"latestBlockNumber()\":{\"notice\":\"Returns the block number of the latest submitted L2 output proposal. If no proposals been submitted yet then this function will return the starting block number.\"},\"latestOutputIndex()\":{\"notice\":\"Returns the number of outputs that have been proposed. Will revert if no outputs have been proposed yet.\"},\"nextBlockNumber()\":{\"notice\":\"Computes the block number of the next L2 block that needs to be checkpointed.\"},\"nextOutputIndex()\":{\"notice\":\"Returns the index of the next output to be proposed.\"},\"proposeL2Output(bytes32,uint256,bytes32,uint256)\":{\"notice\":\"Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp must be equal to the current value returned by `nextTimestamp()` in order to be accepted. This function may only be called by the Proposer.\"},\"proposer()\":{\"notice\":\"The address of the proposer. Can be updated via reinitialize.\"},\"startingBlockNumber()\":{\"notice\":\"The number of the first L2 block recorded in this contract.\"},\"startingTimestamp()\":{\"notice\":\"The timestamp of the first L2 block recorded in this contract.\"},\"submissionInterval()\":{\"notice\":\"Getter for the output proposal submission interval.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L2OutputOracle.sol\":\"L2OutputOracle\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L2OutputOracle.sol\":{\"keccak256\":\"0x60042eb3e619518cab9a8f2480b62871c2d813716e2e60d9a5e0c5f271c58705\",\"urls\":[\"bzz-raw://08538ef2aa99c508b56a8bb9b3c7b93476cba9dbf0b47783141e5e50a02156cc\",\"dweb:/ipfs/QmdvFZ1fUaTkNdmtB66rNAo73RxY7kccsgR6Uqz7psoXGN\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 2, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 32100, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 32103, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 59334, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "startingBlockNumber", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 59337, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "startingTimestamp", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 59342, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "l2Outputs", - "offset": 0, - "slot": "3", - "type": "t_array(t_struct(OutputProposal)71073_storage)dyn_storage" - }, - { - "astId": 59345, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "challenger", - "offset": 0, - "slot": "4", - "type": "t_address" - }, - { - "astId": 59348, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "proposer", - "offset": 0, - "slot": "5", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_struct(OutputProposal)71073_storage)dyn_storage": { - "encoding": "dynamic_array", - "label": "struct Types.OutputProposal[]", - "numberOfBytes": "32", - "base": "t_struct(OutputProposal)71073_storage" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_struct(OutputProposal)71073_storage": { - "encoding": "inplace", - "label": "struct Types.OutputProposal", - "numberOfBytes": "64", - "members": [ - { - "astId": 71068, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "outputRoot", - "offset": 0, - "slot": "0", - "type": "t_bytes32" - }, - { - "astId": 71070, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "timestamp", - "offset": 0, - "slot": "1", - "type": "t_uint128" - }, - { - "astId": 71072, - "contract": "src/L1/L2OutputOracle.sol:L2OutputOracle", - "label": "l2BlockNumber", - "offset": 16, - "slot": "1", - "type": "t_uint128" - } - ] - }, - "t_uint128": { - "encoding": "inplace", - "label": "uint128", - "numberOfBytes": "16" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x565a488c01592b4ff53ccc2c0a842f0975ac1957ac67358deffc5ca07b2640ef", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "CHALLENGER()": { - "notice": "Getter for the challenger address. This will be removed in the future, use `challenger` instead." - }, - "L2_BLOCK_TIME()": { - "notice": "The time between L2 blocks in seconds. Once set, this value MUST NOT be modified. Public getter is legacy and will be removed in the future. Use `l2BlockTime` instead." - }, - "PROPOSER()": { - "notice": "Getter for the proposer address. This will be removed in the future, use `proposer` instead." - }, - "SUBMISSION_INTERVAL()": { - "notice": "The interval in L2 blocks at which checkpoints must be submitted. Although this is immutable, it can safely be modified by upgrading the implementation contract. Public getter is legacy and will be removed in the future. Use `submissionInterval` instead." - }, - "challenger()": { - "notice": "The address of the challenger. Can be updated via reinitialize." - }, - "computeL2Timestamp(uint256)": { - "notice": "Returns the L2 timestamp corresponding to a given L2 block number." - }, - "constructor": { - "notice": "Constructs the L2OutputOracle contract." - }, - "deleteL2Outputs(uint256)": { - "notice": "Deletes all output proposals after and including the proposal that corresponds to the given output index. Only the challenger address can delete outputs." - }, - "finalizationPeriodSeconds()": { - "notice": "Getter for the finalization period." - }, - "getL2Output(uint256)": { - "notice": "Returns an output by index. Needed to return a struct instead of a tuple." - }, - "getL2OutputAfter(uint256)": { - "notice": "Returns the L2 output proposal that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block." - }, - "getL2OutputIndexAfter(uint256)": { - "notice": "Returns the index of the L2 output that checkpoints a given L2 block number. Uses a binary search to find the first output greater than or equal to the given block." - }, - "initialize(uint256,uint256,address,address)": { - "notice": "Initializer." - }, - "l2BlockTime()": { - "notice": "Getter for the L2 block time." - }, - "latestBlockNumber()": { - "notice": "Returns the block number of the latest submitted L2 output proposal. If no proposals been submitted yet then this function will return the starting block number." - }, - "latestOutputIndex()": { - "notice": "Returns the number of outputs that have been proposed. Will revert if no outputs have been proposed yet." - }, - "nextBlockNumber()": { - "notice": "Computes the block number of the next L2 block that needs to be checkpointed." - }, - "nextOutputIndex()": { - "notice": "Returns the index of the next output to be proposed." - }, - "proposeL2Output(bytes32,uint256,bytes32,uint256)": { - "notice": "Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp must be equal to the current value returned by `nextTimestamp()` in order to be accepted. This function may only be called by the Proposer." - }, - "proposer()": { - "notice": "The address of the proposer. Can be updated via reinitialize." - }, - "startingBlockNumber()": { - "notice": "The number of the first L2 block recorded in this contract." - }, - "startingTimestamp()": { - "notice": "The timestamp of the first L2 block recorded in this contract." - }, - "submissionInterval()": { - "notice": "Getter for the output proposal submission interval." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "OutputProposed(bytes32,uint256,uint256,uint256)": { - "notice": "Emitted when an output is proposed." - }, - "OutputsDeleted(uint256,uint256)": { - "notice": "Emitted when outputs are deleted." - } - }, - "notice": "The L2OutputOracle contains an array of L2 state outputs, where each output is a commitment to the state of the L2 chain. Other contracts like the OptimismPortal use these outputs to verify information about the state of L2." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/L2OutputOracleProxy.json b/packages/contracts-bedrock/deployments/mainnet/L2OutputOracleProxy.json deleted file mode 100644 index e0b918270152..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/L2OutputOracleProxy.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "address": "0xdfe97868233d1aa22e815a266982f2cf17685a27", - "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": "0x615bd360561ef00aff4b75adda59f04e792a2f0f17d518d4906a892cf677b5ed", - "receipt": { - "to": null, - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "contractAddress": "0xdfe97868233d1aa22e815a266982f2cf17685a27", - "transactionIndex": 90, - "gasUsed": "523960", - "logsBloom": "0x00000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000001000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xde6e8af7a3ffcf7716ac9153f6b44c92945f293cb0b6c5decf66ff6d1050ccae", - "transactionHash": "0x615bd360561ef00aff4b75adda59f04e792a2f0f17d518d4906a892cf677b5ed", - "logs": [ - { - "transactionIndex": 90, - "blockNumber": 17365801, - "transactionHash": "0x615bd360561ef00aff4b75adda59f04e792a2f0f17d518d4906a892cf677b5ed", - "address": "0xdfe97868233d1aa22e815a266982f2cf17685a27", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000543ba4aadbab8f9025686bd03993043599c6fb04", - "logIndex": 271, - "blockHash": "0xde6e8af7a3ffcf7716ac9153f6b44c92945f293cb0b6c5decf66ff6d1050ccae" - } - ], - "blockNumber": 17365801, - "cumulativeGasUsed": "9803453", - "status": 1, - "byzantium": true - }, - "args": [ - "0x543bA4AADBAb8f9025686Bd03993043599c6fB04" - ], - "numDeployments": 1, - "solcInputHash": "13ac93d026822f719ad110af836d1582", - "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\":{\"contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@cwia/=node_modules/clones-with-immutable-args/src/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":clones-with-immutable-args/=node_modules/clones-with-immutable-args/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0x64d67f1936d97c87a2e42317eb162744ad5cefdc9bc8b1138ee4afe2886eb885\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://33b903585eb9cfc60a70bcdf4ee44220b173caff16dfb9071cd0668c7a551265\",\"dweb:/ipfs/QmXHUZ9brinN1WS9i63ocRQsQidY96WePDBhBsFRhDmVjr\"]}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "admin()": { - "returns": { - "_0": "Owner address." - } - }, - "changeAdmin(address)": { - "params": { - "_admin": "New owner of the proxy contract." - } - }, - "constructor": { - "params": { - "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "Address of the implementation contract." - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "Calldata to delegatecall the new implementation with.", - "_implementation": "Address of the implementation contract." - } - } - }, - "events": { - "AdminChanged(address,address)": { - "params": { - "newAdmin": "The new owner of the contract", - "previousAdmin": "The previous owner of the contract" - } - }, - "Upgraded(address)": { - "params": { - "implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "admin()": { - "notice": "Gets the owner of the proxy contract." - }, - "changeAdmin(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "constructor": { - "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." - }, - "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." - } - }, - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." - } - }, - "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/OptimismMintableERC20Factory.json b/packages/contracts-bedrock/deployments/mainnet/OptimismMintableERC20Factory.json deleted file mode 100644 index f68bcda2b225..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/OptimismMintableERC20Factory.json +++ /dev/null @@ -1,356 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "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": "localToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "deployer", - "type": "address" - } - ], - "name": "OptimismMintableERC20Created", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "localToken", - "type": "address" - } - ], - "name": "StandardL2TokenCreated", - "type": "event" - }, - { - "inputs": [], - "name": "BRIDGE", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "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": "createOptimismMintableERC20", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_remoteToken", - "type": "address" - }, - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - }, - { - "internalType": "uint8", - "name": "_decimals", - "type": "uint8" - } - ], - "name": "createOptimismMintableERC20WithDecimals", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_remoteToken", - "type": "address" - }, - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - } - ], - "name": "createStandardL2Token", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_bridge", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "address": "0x373B66bd178cb2716D5A9596B1a42Ed39b87A535", - "args": [], - "bytecode": "0x608060405234801561001057600080fd5b5061001b6000610020565b610118565b600054600390610100900460ff16158015610042575060005460ff8083169116105b6100a95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805461010060ff841661ffff19909216821717610100600160b01b03191661ff0019620100006001600160a01b0387160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6123cf806101276000396000f3fe60806040523480156200001157600080fd5b5060043610620000875760003560e01c8063c4d66de81162000062578063c4d66de81462000135578063ce5ac90f146200014e578063e78cea921462000165578063ee9a31a2146200018c57600080fd5b806354fd4d50146200008c578063896f93d114620000e15780638cf0629c146200011e575b600080fd5b620000c96040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b604051620000d89190620005d1565b60405180910390f35b620000f8620000f2366004620006f9565b620001b1565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620000f86200012f36600462000776565b620001c8565b6200014c620001463660046200080d565b620003c6565b005b620000f86200015f366004620006f9565b62000544565b600054620000f89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000f8565b6000620001c084848462000544565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b6000858585856040516020016200028e94939291906200082b565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688888888604051620002de9062000555565b620002ee95949392919062000885565b8190604051809103906000f59050801580156200030f573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054600390610100900460ff16158015620003e9575060005460ff8083169116105b62000477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200026a565b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000620001c08484846012620001c8565b611ad880620008eb83390190565b6000815180845260005b818110156200058b576020818501810151868301820152016200056d565b818111156200059e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005e6602083018462000563565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061257600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200065857600080fd5b813567ffffffffffffffff8082111562000676576200067662000617565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006bf57620006bf62000617565b81604052838152866020858801011115620006d957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200070f57600080fd5b6200071a84620005ed565b9250602084013567ffffffffffffffff808211156200073857600080fd5b620007468783880162000646565b935060408601359150808211156200075d57600080fd5b506200076c8682870162000646565b9150509250925092565b600080600080608085870312156200078d57600080fd5b6200079885620005ed565b9350602085013567ffffffffffffffff80821115620007b657600080fd5b620007c48883890162000646565b94506040870135915080821115620007db57600080fd5b50620007ea8782880162000646565b925050606085013560ff811681146200080257600080fd5b939692955090935050565b6000602082840312156200082057600080fd5b620005e682620005ed565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200085c608083018662000563565b828103604084015262000870818662000563565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620008c060a083018662000563565b8281036060840152620008d4818662000563565b91505060ff83166080830152969550505050505056fe6101406040523480156200001257600080fd5b5060405162001ad838038062001ad8833981016040819052620000359162000178565b600160026000858560036200004b8382620002b3565b5060046200005a8282620002b3565b50505060809290925260a05260c0526001600160a01b0393841660e0529390921661010052505060ff16610120526200037f565b80516001600160a01b0381168114620000a657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000d357600080fd5b81516001600160401b0380821115620000f057620000f0620000ab565b604051601f8301601f19908116603f011681019082821181831017156200011b576200011b620000ab565b816040528381526020925086838588010111156200013857600080fd5b600091505b838210156200015c57858201830151818301840152908201906200013d565b838211156200016e5760008385830101525b9695505050505050565b600080600080600060a086880312156200019157600080fd5b6200019c866200008e565b9450620001ac602087016200008e565b60408701519094506001600160401b0380821115620001ca57600080fd5b620001d889838a01620000c1565b94506060880151915080821115620001ef57600080fd5b50620001fe88828901620000c1565b925050608086015160ff811681146200021657600080fd5b809150509295509295909350565b600181811c908216806200023957607f821691505b6020821081036200025a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002ae57600081815260208120601f850160051c81016020861015620002895750805b601f850160051c820191505b81811015620002aa5782815560010162000295565b5050505b505050565b81516001600160401b03811115620002cf57620002cf620000ab565b620002e781620002e0845462000224565b8462000260565b602080601f8311600181146200031f5760008415620003065750858301515b600019600386901b1c1916600185901b178555620002aa565b600085815260208120601f198616915b8281101562000350578886015182559484019460019091019084016200032f565b50858210156200036f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161010051610120516116ed620003eb6000396000610244015260008181610317015281816103ac015281816105f101526107cb0152600081816101a9015261033d0152600061075a015260006107310152600061070801526116ed6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610361578063e78cea9214610315578063ee9a31a2146103a757600080fd5b8063ae1f6aaf14610315578063c01e1bd61461033b578063d6c0b2c41461033b57600080fd5b80639dc29fac116100bd5780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb1461030257600080fd5b806370a082311461029e57806395d89b41146102d457600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611329565b6103ce565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104bf565b60405161019b919061139e565b61018f610213366004611418565b610551565b6002545b60405190815260200161019b565b61018f610238366004611442565b610569565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611418565b61058d565b61029461028f366004611418565b6105d9565b005b6101f8610701565b61021c6102ac36600461147e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f86107a4565b6102946102ea366004611418565b6107b3565b61018f6102fd366004611418565b6108ca565b61018f610310366004611418565b61099b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61036f366004611499565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061048757507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104b657507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ce906114cc565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa906114cc565b80156105475780601f1061051c57610100808354040283529160200191610547565b820191906000526020600020905b81548152906001019060200180831161052a57829003601f168201915b5050505050905090565b60003361055f8185856109a9565b5060019392505050565b600033610577858285610b5d565b610582858585610c34565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061055f90829086906105d490879061154e565b6109a9565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106ad8282610ee7565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106f591815260200190565b60405180910390a25050565b606061072c7f0000000000000000000000000000000000000000000000000000000000000000611007565b6107557f0000000000000000000000000000000000000000000000000000000000000000611007565b61077e7f0000000000000000000000000000000000000000000000000000000000000000611007565b60405160200161079093929190611566565b604051602081830303815290604052905090565b6060600480546104ce906114cc565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610878576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161069a565b6108828282611144565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106f591815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561098e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161069a565b61058282868684036109a9565b60003361055f818585610c34565b73ffffffffffffffffffffffffffffffffffffffff8316610a4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610aee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2e5781811015610c21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161069a565b610c2e84848484036109a9565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e7490849061154e565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eda91815260200190565b60405180910390a3610c2e565b73ffffffffffffffffffffffffffffffffffffffff8216610f64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161069a565b8060026000828254610f76919061154e565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610fb090849061154e565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361104a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611074578061105e816115dc565b915061106d9050600a83611643565b915061104e565b60008167ffffffffffffffff81111561108f5761108f611657565b6040519080825280601f01601f1916602001820160405280156110b9576020820181803683370190505b5090505b841561113c576110ce600183611686565b91506110db600a8661169d565b6110e690603061154e565b60f81b8183815181106110fb576110fb6116b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611135600a86611643565b94506110bd565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561129d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112d9908490611686565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b50565b60006020828403121561133b57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461136b57600080fd5b9392505050565b60005b8381101561138d578181015183820152602001611375565b83811115610c2e5750506000910152565b60208152600082518060208401526113bd816040850160208701611372565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461141357600080fd5b919050565b6000806040838503121561142b57600080fd5b611434836113ef565b946020939093013593505050565b60008060006060848603121561145757600080fd5b611460846113ef565b925061146e602085016113ef565b9150604084013590509250925092565b60006020828403121561149057600080fd5b61136b826113ef565b600080604083850312156114ac57600080fd5b6114b5836113ef565b91506114c3602084016113ef565b90509250929050565b600181811c908216806114e057607f821691505b602082108103611519577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115615761156161151f565b500190565b60008451611578818460208901611372565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516115b4816001850160208a01611372565b600192019182015283516115cf816002840160208801611372565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361160d5761160d61151f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165257611652611614565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156116985761169861151f565b500390565b6000826116ac576116ac611614565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a", - "deployedBytecode": "0x60806040523480156200001157600080fd5b5060043610620000875760003560e01c8063c4d66de81162000062578063c4d66de81462000135578063ce5ac90f146200014e578063e78cea921462000165578063ee9a31a2146200018c57600080fd5b806354fd4d50146200008c578063896f93d114620000e15780638cf0629c146200011e575b600080fd5b620000c96040518060400160405280600581526020017f312e362e3000000000000000000000000000000000000000000000000000000081525081565b604051620000d89190620005d1565b60405180910390f35b620000f8620000f2366004620006f9565b620001b1565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620000d8565b620000f86200012f36600462000776565b620001c8565b6200014c620001463660046200080d565b620003c6565b005b620000f86200015f366004620006f9565b62000544565b600054620000f89062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff16620000f8565b6000620001c084848462000544565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff851662000273576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b6000858585856040516020016200028e94939291906200082b565b604051602081830303815290604052805190602001209050600081600060029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1688888888604051620002de9062000555565b620002ee95949392919062000885565b8190604051809103906000f59050801580156200030f573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054600390610100900460ff16158015620003e9575060005460ff8083169116105b62000477576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200026a565b6000805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009092168217177fffffffffffffffffffff000000000000000000000000000000000000000000ff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6201000073ffffffffffffffffffffffffffffffffffffffff87160216179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6000620001c08484846012620001c8565b611ad880620008eb83390190565b6000815180845260005b818110156200058b576020818501810151868301820152016200056d565b818111156200059e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005e6602083018462000563565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061257600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200065857600080fd5b813567ffffffffffffffff8082111562000676576200067662000617565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006bf57620006bf62000617565b81604052838152866020858801011115620006d957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200070f57600080fd5b6200071a84620005ed565b9250602084013567ffffffffffffffff808211156200073857600080fd5b620007468783880162000646565b935060408601359150808211156200075d57600080fd5b506200076c8682870162000646565b9150509250925092565b600080600080608085870312156200078d57600080fd5b6200079885620005ed565b9350602085013567ffffffffffffffff80821115620007b657600080fd5b620007c48883890162000646565b94506040870135915080821115620007db57600080fd5b50620007ea8782880162000646565b925050606085013560ff811681146200080257600080fd5b939692955090935050565b6000602082840312156200082057600080fd5b620005e682620005ed565b73ffffffffffffffffffffffffffffffffffffffff851681526080602082015260006200085c608083018662000563565b828103604084015262000870818662000563565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a06040830152620008c060a083018662000563565b8281036060840152620008d4818662000563565b91505060ff83166080830152969550505050505056fe6101406040523480156200001257600080fd5b5060405162001ad838038062001ad8833981016040819052620000359162000178565b600160026000858560036200004b8382620002b3565b5060046200005a8282620002b3565b50505060809290925260a05260c0526001600160a01b0393841660e0529390921661010052505060ff16610120526200037f565b80516001600160a01b0381168114620000a657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000d357600080fd5b81516001600160401b0380821115620000f057620000f0620000ab565b604051601f8301601f19908116603f011681019082821181831017156200011b576200011b620000ab565b816040528381526020925086838588010111156200013857600080fd5b600091505b838210156200015c57858201830151818301840152908201906200013d565b838211156200016e5760008385830101525b9695505050505050565b600080600080600060a086880312156200019157600080fd5b6200019c866200008e565b9450620001ac602087016200008e565b60408701519094506001600160401b0380821115620001ca57600080fd5b620001d889838a01620000c1565b94506060880151915080821115620001ef57600080fd5b50620001fe88828901620000c1565b925050608086015160ff811681146200021657600080fd5b809150509295509295909350565b600181811c908216806200023957607f821691505b6020821081036200025a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002ae57600081815260208120601f850160051c81016020861015620002895750805b601f850160051c820191505b81811015620002aa5782815560010162000295565b5050505b505050565b81516001600160401b03811115620002cf57620002cf620000ab565b620002e781620002e0845462000224565b8462000260565b602080601f8311600181146200031f5760008415620003065750858301515b600019600386901b1c1916600185901b178555620002aa565b600085815260208120601f198616915b8281101562000350578886015182559484019460019091019084016200032f565b50858210156200036f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161010051610120516116ed620003eb6000396000610244015260008181610317015281816103ac015281816105f101526107cb0152600081816101a9015261033d0152600061075a015260006107310152600061070801526116ed6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610361578063e78cea9214610315578063ee9a31a2146103a757600080fd5b8063ae1f6aaf14610315578063c01e1bd61461033b578063d6c0b2c41461033b57600080fd5b80639dc29fac116100bd5780639dc29fac146102dc578063a457c2d7146102ef578063a9059cbb1461030257600080fd5b806370a082311461029e57806395d89b41146102d457600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611329565b6103ce565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104bf565b60405161019b919061139e565b61018f610213366004611418565b610551565b6002545b60405190815260200161019b565b61018f610238366004611442565b610569565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611418565b61058d565b61029461028f366004611418565b6105d9565b005b6101f8610701565b61021c6102ac36600461147e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f86107a4565b6102946102ea366004611418565b6107b3565b61018f6102fd366004611418565b6108ca565b61018f610310366004611418565b61099b565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61036f366004611499565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061048757507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104b657507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ce906114cc565b80601f01602080910402602001604051908101604052809291908181526020018280546104fa906114cc565b80156105475780601f1061051c57610100808354040283529160200191610547565b820191906000526020600020905b81548152906001019060200180831161052a57829003601f168201915b5050505050905090565b60003361055f8185856109a9565b5060019392505050565b600033610577858285610b5d565b610582858585610c34565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061055f90829086906105d490879061154e565b6109a9565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106ad8282610ee7565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106f591815260200190565b60405180910390a25050565b606061072c7f0000000000000000000000000000000000000000000000000000000000000000611007565b6107557f0000000000000000000000000000000000000000000000000000000000000000611007565b61077e7f0000000000000000000000000000000000000000000000000000000000000000611007565b60405160200161079093929190611566565b604051602081830303815290604052905090565b6060600480546104ce906114cc565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610878576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161069a565b6108828282611144565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106f591815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561098e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161069a565b61058282868684036109a9565b60003361055f818585610c34565b73ffffffffffffffffffffffffffffffffffffffff8316610a4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610aee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c2e5781811015610c21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161069a565b610c2e84848484036109a9565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff8216610d7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e7490849061154e565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eda91815260200190565b60405180910390a3610c2e565b73ffffffffffffffffffffffffffffffffffffffff8216610f64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161069a565b8060026000828254610f76919061154e565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610fb090849061154e565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361104a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611074578061105e816115dc565b915061106d9050600a83611643565b915061104e565b60008167ffffffffffffffff81111561108f5761108f611657565b6040519080825280601f01601f1916602001820160405280156110b9576020820181803683370190505b5090505b841561113c576110ce600183611686565b91506110db600a8661169d565b6110e690603061154e565b60f81b8183815181106110fb576110fb6116b1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611135600a86611643565b94506110bd565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561129d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161069a565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112d9908490611686565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b50565b60006020828403121561133b57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461136b57600080fd5b9392505050565b60005b8381101561138d578181015183820152602001611375565b83811115610c2e5750506000910152565b60208152600082518060208401526113bd816040850160208701611372565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461141357600080fd5b919050565b6000806040838503121561142b57600080fd5b611434836113ef565b946020939093013593505050565b60008060006060848603121561145757600080fd5b611460846113ef565b925061146e602085016113ef565b9150604084013590509250925092565b60006020828403121561149057600080fd5b61136b826113ef565b600080604083850312156114ac57600080fd5b6114b5836113ef565b91506114c3602084016113ef565b90509250929050565b600181811c908216806114e057607f821691505b602082108103611519577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115615761156161151f565b500190565b60008451611578818460208901611372565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516115b4816001850160208a01611372565b600192019182015283516115cf816002840160208801611372565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361160d5761160d61151f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261165257611652611614565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156116985761169861151f565b500390565b6000826116ac576116ac611614565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "BRIDGE()": {}, - "createOptimismMintableERC20(address,string,string)": { - "params": { - "_name": "ERC20 name.", - "_remoteToken": "Address of the token on the remote chain.", - "_symbol": "ERC20 symbol." - }, - "returns": { - "_0": "Address of the newly created token." - } - }, - "createOptimismMintableERC20WithDecimals(address,string,string,uint8)": { - "params": { - "_decimals": "ERC20 decimals", - "_name": "ERC20 name.", - "_remoteToken": "Address of the token on the remote chain.", - "_symbol": "ERC20 symbol." - }, - "returns": { - "_0": "Address of the newly created token." - } - }, - "createStandardL2Token(address,string,string)": { - "params": { - "_name": "ERC20 name.", - "_remoteToken": "Address of the token on the remote chain.", - "_symbol": "ERC20 symbol." - }, - "returns": { - "_0": "Address of the newly created token." - } - }, - "initialize(address)": { - "params": { - "_bridge": "Address of the StandardBridge on this chain." - } - } - }, - "events": { - "OptimismMintableERC20Created(address,address,address)": { - "params": { - "deployer": "Address of the account that deployed the token.", - "localToken": "Address of the created token on the local chain.", - "remoteToken": "Address of the corresponding token on the remote chain." - } - }, - "StandardL2TokenCreated(address,address)": { - "params": { - "localToken": "Address of the created token on the local chain.", - "remoteToken": "Address of the token on the remote chain." - } - } - }, - "title": "OptimismMintableERC20Factory" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"deployer\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"OptimismMintableERC20Created\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"StandardL2TokenCreated\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createOptimismMintableERC20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createOptimismMintableERC20WithDecimals\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"createStandardL2Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"BRIDGE()\":{\"custom:legacy\":\"\"},\"createOptimismMintableERC20(address,string,string)\":{\"params\":{\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}},\"createOptimismMintableERC20WithDecimals(address,string,string,uint8)\":{\"params\":{\"_decimals\":\"ERC20 decimals\",\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}},\"createStandardL2Token(address,string,string)\":{\"custom:legacy\":\"@notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the newer createOptimismMintableERC20 function, which has a more intuitive name.\",\"params\":{\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}},\"initialize(address)\":{\"params\":{\"_bridge\":\"Address of the StandardBridge on this chain.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"BRIDGE()\":{\"notice\":\"Returns the address of the StandardBridge on this chain. This is a legacy getter, use `bridge` instead.\"},\"bridge()\":{\"notice\":\"Address of the StandardBridge on this chain.\"},\"constructor\":{\"notice\":\"The semver MUST be bumped any time that there is a change in the OptimismMintableERC20 token contract since this contract is responsible for deploying OptimismMintableERC20 contracts.\"},\"createOptimismMintableERC20(address,string,string)\":{\"notice\":\"Creates an instance of the OptimismMintableERC20 contract.\"},\"createOptimismMintableERC20WithDecimals(address,string,string,uint8)\":{\"notice\":\"Creates an instance of the OptimismMintableERC20 contract, with specified decimals.\"},\"initialize(address)\":{\"notice\":\"Initializer.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/OptimismMintableERC20Factory.sol\":\"OptimismMintableERC20Factory\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x6f8133b39efcbcbd5088f195dfacf1bedc3146508429c3865443909af735a04c\",\"urls\":[\"bzz-raw://adc36971e2e120458769f050428d9d2b0504516660345020c2521ee46e6d8abf\",\"dweb:/ipfs/QmPbFusQkZgGKpU8Fv5JoqL4oVeJtM3yqnhRGLY9eZT5zZ\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x39af021e492020fbeb5401371010d4a2fb69debe9596dbbead7bcd7fae248b0b\",\"urls\":[\"bzz-raw://dbeea52e586d2d7de55491a660ca76f75167ba6b43b65d29564864ee9c34a174\",\"dweb:/ipfs/QmS23vFqQxyUXhGuV1nSowZZS93CUkSnsb41uuyRtSeAED\"],\"license\":\"MIT\"},\"src/universal/OptimismMintableERC20Factory.sol\":{\"keccak256\":\"0x60862069899142dc4803d5f5754fd22339980bf74cfc4e2573bb59ff88a99c69\",\"urls\":[\"bzz-raw://8018f9fb11105ab80d4d6fb0bceabf8435d20d0883efa95070ae9e9983e3895c\",\"dweb:/ipfs/Qmf2ghxThySJA1pRvZfj3Q9yJwAZHSxwXAV9GDEqXxEWY9\"],\"license\":\"MIT\"},\"src/universal/Semver.sol\":{\"keccak256\":\"0x9de68ce536aee1aa616b4bf88d7ccc335460e6edd0e7170bdbf94c4fe3d41c60\",\"urls\":[\"bzz-raw://d5909c0b049b03a2bc24816ecf15b0aaf18c04a963174e1eba7624321bef330d\",\"dweb:/ipfs/QmeqdutwZWHqQMXauNR6WY8PrUpfsTiWTQyanbnGM9QqzT\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 2, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 32100, - "contract": "src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 32103, - "contract": "src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 76303, - "contract": "src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory", - "label": "bridge", - "offset": 2, - "slot": "0", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0xeebcd491eb8713084bb8faecbce88997f5e83b0b17fc49247a74fac89e5cb361", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "BRIDGE()": { - "notice": "Returns the address of the StandardBridge on this chain. This is a legacy getter, use `bridge` instead." - }, - "bridge()": { - "notice": "Address of the StandardBridge on this chain." - }, - "constructor": { - "notice": "The semver MUST be bumped any time that there is a change in the OptimismMintableERC20 token contract since this contract is responsible for deploying OptimismMintableERC20 contracts." - }, - "createOptimismMintableERC20(address,string,string)": { - "notice": "Creates an instance of the OptimismMintableERC20 contract." - }, - "createOptimismMintableERC20WithDecimals(address,string,string,uint8)": { - "notice": "Creates an instance of the OptimismMintableERC20 contract, with specified decimals." - }, - "initialize(address)": { - "notice": "Initializer." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "OptimismMintableERC20Created(address,address,address)": { - "notice": "Emitted whenever a new OptimismMintableERC20 is created." - } - }, - "notice": "OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20 contracts on the network it's deployed to. Simplifies the deployment process for users who may be less familiar with deploying smart contracts. Designed to be backwards compatible with the older StandardL2ERC20Factory contract." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/OptimismMintableERC20FactoryProxy.json b/packages/contracts-bedrock/deployments/mainnet/OptimismMintableERC20FactoryProxy.json deleted file mode 100644 index c52844b225ad..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/OptimismMintableERC20FactoryProxy.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "address": "0x75505a97BD334E7BD3C476893285569C4136Fa0F", - "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": "0x4c2e632670c595a93c9c92fe2c0154130c5e3869758ba1c2119274f44280bb59", - "receipt": { - "to": null, - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "contractAddress": "0x75505a97BD334E7BD3C476893285569C4136Fa0F", - "transactionIndex": 102, - "gasUsed": "523960", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000100000000000000000020000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x21734904e880a46f858627a4ac837db2f58e61c30a3669e001ff6fdde604ccf5", - "transactionHash": "0x4c2e632670c595a93c9c92fe2c0154130c5e3869758ba1c2119274f44280bb59", - "logs": [ - { - "transactionIndex": 102, - "blockNumber": 17365803, - "transactionHash": "0x4c2e632670c595a93c9c92fe2c0154130c5e3869758ba1c2119274f44280bb59", - "address": "0x75505a97BD334E7BD3C476893285569C4136Fa0F", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000543ba4aadbab8f9025686bd03993043599c6fb04", - "logIndex": 293, - "blockHash": "0x21734904e880a46f858627a4ac837db2f58e61c30a3669e001ff6fdde604ccf5" - } - ], - "blockNumber": 17365803, - "cumulativeGasUsed": "13364850", - "status": 1, - "byzantium": true - }, - "args": [ - "0x543bA4AADBAb8f9025686Bd03993043599c6fB04" - ], - "numDeployments": 1, - "solcInputHash": "13ac93d026822f719ad110af836d1582", - "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\":{\"contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@cwia/=node_modules/clones-with-immutable-args/src/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":clones-with-immutable-args/=node_modules/clones-with-immutable-args/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0x64d67f1936d97c87a2e42317eb162744ad5cefdc9bc8b1138ee4afe2886eb885\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://33b903585eb9cfc60a70bcdf4ee44220b173caff16dfb9071cd0668c7a551265\",\"dweb:/ipfs/QmXHUZ9brinN1WS9i63ocRQsQidY96WePDBhBsFRhDmVjr\"]}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "admin()": { - "returns": { - "_0": "Owner address." - } - }, - "changeAdmin(address)": { - "params": { - "_admin": "New owner of the proxy contract." - } - }, - "constructor": { - "params": { - "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "Address of the implementation contract." - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "Calldata to delegatecall the new implementation with.", - "_implementation": "Address of the implementation contract." - } - } - }, - "events": { - "AdminChanged(address,address)": { - "params": { - "newAdmin": "The new owner of the contract", - "previousAdmin": "The previous owner of the contract" - } - }, - "Upgraded(address)": { - "params": { - "implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "admin()": { - "notice": "Gets the owner of the proxy contract." - }, - "changeAdmin(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "constructor": { - "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." - }, - "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." - } - }, - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." - } - }, - "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/OptimismPortal.json b/packages/contracts-bedrock/deployments/mainnet/OptimismPortal.json deleted file mode 100644 index 501d0716fffc..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/OptimismPortal.json +++ /dev/null @@ -1,970 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "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": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "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" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "withdrawalHash", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "WithdrawalProven", - "type": "event" - }, - { - "inputs": [], - "name": "GUARDIAN", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L2_ORACLE", - "outputs": [ - { - "internalType": "contract L2OutputOracle", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SYSTEM_CONFIG", - "outputs": [ - { - "internalType": "contract SystemConfig", - "name": "", - "type": "address" - } - ], - "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": [], - "name": "donateETH", - "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": "struct Types.WithdrawalTransaction", - "name": "_tx", - "type": "tuple" - } - ], - "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": "guardian", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract L2OutputOracle", - "name": "_l2Oracle", - "type": "address" - }, - { - "internalType": "address", - "name": "_guardian", - "type": "address" - }, - { - "internalType": "contract SystemConfig", - "name": "_systemConfig", - "type": "address" - }, - { - "internalType": "bool", - "name": "_paused", - "type": "bool" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2OutputIndex", - "type": "uint256" - } - ], - "name": "isOutputFinalized", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l2Oracle", - "outputs": [ - { - "internalType": "contract L2OutputOracle", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l2Sender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_byteCount", - "type": "uint64" - } - ], - "name": "minimumGasLimit", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "pure", - "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": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "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": "struct Types.WithdrawalTransaction", - "name": "_tx", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "_l2OutputIndex", - "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": "struct Types.OutputRootProof", - "name": "_outputRootProof", - "type": "tuple" - }, - { - "internalType": "bytes[]", - "name": "_withdrawalProof", - "type": "bytes[]" - } - ], - "name": "proveWithdrawalTransaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "provenWithdrawals", - "outputs": [ - { - "internalType": "bytes32", - "name": "outputRoot", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "timestamp", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "l2OutputIndex", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "systemConfig", - "outputs": [ - { - "internalType": "contract SystemConfig", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "address": "0xD14AA6C7B6D92803F3910Ec1DADCCd0757341862", - "args": [], - "bytecode": "0x60806040523480156200001157600080fd5b506200002260008080600162000028565b62000224565b600054600390610100900460ff161580156200004b575060005460ff8083169116105b620000b45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805461ffff191660ff831617610100908117909155603280546001600160a01b031990811661dead1790915560358054603680546001600160a01b0389811691861691909117909155603780548a831695169490941790935585151592891690930260ff19166001600160a81b0319909316929092171790556200013962000181565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600054610100900460ff16620001ee5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000ab565b60408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b0217600155565b61545c80620002346000396000f3fe60806040526004361061016d5760003560e01c80638b4c40b0116100cb578063a35d99df1161007f578063e9e05c4211610059578063e9e05c4214610573578063f049875014610586578063fecf9734146105b157600080fd5b8063a35d99df1461040d578063cff0ab9614610446578063e965084c146104e757600080fd5b80639b5f694a116100b05780639b5f694a1461037e5780639bf62d82146103b0578063a14238e7146103dd57600080fd5b80638b4c40b0146101925780638c3152e91461035e57600080fd5b806354fd4d50116101225780636dbffb78116101075780636dbffb78146102fe578063724c184c1461031e5780638456cb591461034957600080fd5b806354fd4d501461027e5780635c975abb146102d457600080fd5b80633f4ba83a116101535780633f4ba83a1461021c578063452a9320146102315780634870496f1461025e57600080fd5b80621c2ff61461019957806333d7e2bd146101ef57600080fd5b36610194576101923334620186a06000604051806020016040528060008152506105d1565b005b600080fd5b3480156101a557600080fd5b50603554610100900473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101fb57600080fd5b506036546101c59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561022857600080fd5b5061019261086c565b34801561023d57600080fd5b506037546101c59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561026a57600080fd5b50610192610279366004614a4a565b610971565b34801561028a57600080fd5b506102c76040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b6040516101e69190614ba0565b3480156102e057600080fd5b506035546102ee9060ff1681565b60405190151581526020016101e6565b34801561030a57600080fd5b506102ee610319366004614bb3565b610fa6565b34801561032a57600080fd5b5060375473ffffffffffffffffffffffffffffffffffffffff166101c5565b34801561035557600080fd5b50610192611065565b34801561036a57600080fd5b50610192610379366004614bcc565b611167565b34801561038a57600080fd5b506035546101c590610100900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156103bc57600080fd5b506032546101c59073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103e957600080fd5b506102ee6103f8366004614bb3565b60336020526000908152604090205460ff1681565b34801561041957600080fd5b5061042d610428366004614c26565b611a2b565b60405167ffffffffffffffff90911681526020016101e6565b34801561045257600080fd5b506001546104ae906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101e6565b3480156104f357600080fd5b50610545610502366004614bb3565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101e6565b610192610581366004614c51565b6105d1565b34801561059257600080fd5b5060365473ffffffffffffffffffffffffffffffffffffffff166101c5565b3480156105bd57600080fd5b506101926105cc366004614ccc565b611a44565b8260005a905083156106885773ffffffffffffffffffffffffffffffffffffffff87161561068857604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b6106928351611a2b565b67ffffffffffffffff168567ffffffffffffffff161015610735576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c0000000000000000000000000000000000000000000000000000000000606482015260840161067f565b6201d4c0835111156107a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c617267650000604482015260640161067f565b333281146107c4575033731111000000000000000000000000000000001111015b600034888888886040516020016107df959493929190614d26565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161084f9190614ba0565b60405180910390a450506108638282611c52565b50505050505050565b60375473ffffffffffffffffffffffffffffffffffffffff163314610913576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a206f6e6c7920677561726469616e20636160448201527f6e20756e70617573650000000000000000000000000000000000000000000000606482015260840161067f565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60355460ff16156109de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a2070617573656400000000000000000000604482015260640161067f565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610a9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e747261637400606482015260840161067f565b6035546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101869052600091610100900473ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b369190614dab565b519050610b50610b4b36869003860186614e10565b611f7f565b8114610bde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f660000000000000000000000000000000000000000000000606482015260840161067f565b6000610be987611fdb565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610d035750805160355460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015261010090910473ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610cdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cff9190614dab565b5114155b610d8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e000000000000000000606482015260840161067f565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610e589101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610e4e888a614e76565b8a6040013561200b565b610ee4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f660000000000000000000000000000606482015260840161067f565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6035546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810183905260009161105f9161010090910473ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015611020573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110449190614dab565b602001516fffffffffffffffffffffffffffffffff1661202f565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff16331461110c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4f7074696d69736d506f7274616c3a206f6e6c7920677561726469616e20636160448201527f6e20706175736500000000000000000000000000000000000000000000000000606482015260840161067f565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610967565b60355460ff16156111d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a2070617573656400000000000000000000604482015260640161067f565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461127d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e00606482015260840161067f565b600061128882611fdb565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611373576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e207965740000000000000000000000000000606482015260840161067f565b603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114049190614efa565b81602001516fffffffffffffffffffffffffffffffff1610156114cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a40161067f565b6114ee81602001516fffffffffffffffffffffffffffffffff1661202f565b6115a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a40161067f565b60355460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff9091166004820152600091610100900473ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa15801561162c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116509190614dab565b825181519192501461170a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a40161067f565b61172981602001516fffffffffffffffffffffffffffffffff1661202f565b6117db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a40161067f565b60008381526033602052604090205460ff161561187a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a65640000000000000000000000606482015260840161067f565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a088015161191c939291906120d4565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061198190841515815260200190565b60405180910390a2801580156119975750326001145b15611a24576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015260840161067f565b5050505050565b6000611a38826010614f42565b61105f90615208614f72565b600054600390610100900460ff16158015611a66575060005460ff8083169116105b611af2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161067f565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff831617610100908117909155603280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811661dead17909155603580546036805473ffffffffffffffffffffffffffffffffffffffff89811691861691909117909155603780548a83169516949094179093558515159289169093027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00167fffffffffffffffffffffff00000000000000000000000000000000000000000090931692909217179055611bed612132565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600154600090611c88907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643614f9e565b90506000611c94612215565b90506000816020015160ff16826000015163ffffffff16611cb59190614fe4565b90508215611dec57600154600090611cec908390700100000000000000000000000000000000900467ffffffffffffffff1661504c565b90506000836040015160ff1683611d0391906150c0565b600154611d239084906fffffffffffffffffffffffffffffffff166150c0565b611d2d9190614fe4565b600154909150600090611d7e90611d579084906fffffffffffffffffffffffffffffffff1661517c565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff166122db565b90506001861115611dad57611daa611d5782876040015160ff1660018a611da59190614f9e565b6122fa565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611e1f908490700100000000000000000000000000000000900467ffffffffffffffff16614f72565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611f02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d69740000606482015260840161067f565b600154600090611f2e906fffffffffffffffffffffffffffffffff1667ffffffffffffffff88166151f0565b90506000611f4048633b9aca0061234f565b611f4a908361522d565b905060005a611f599088614f9e565b905080821115611f7557611f75611f708284614f9e565b612366565b5050505050505050565b60008160000151826020015183604001518460600151604051602001611fbe949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097611fbe979096959101615241565b60008061201786612394565b9050612025818686866123c6565b9695505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa15801561209e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c29190614efa565b6120cc9083615298565b421192915050565b60008060006120e48660006123f6565b90508061211a576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff166121c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161067f565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260365483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa1580156122b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d691906152d5565b905090565b60006122f06122ea8585612414565b83612424565b90505b9392505050565b6000670de0b6b3a764000061233b6123128583614fe4565b61232490670de0b6b3a764000061504c565b61233685670de0b6b3a76400006150c0565b612433565b61234590866150c0565b6122f09190614fe4565b60008183101561235f57816122f3565b5090919050565b6000805a90505b825a6123799083614f9e565b101561238f5761238882615374565b915061236d565b505050565b606081805190602001206040516020016123b091815260200190565b6040516020818303038152906040529050919050565b60006123ed846123d7878686612464565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b60008183121561235f57816122f3565b600081831261235f57816122f3565b60006122f3670de0b6b3a76400008361244b86612ee2565b61245591906150c0565b61245f9190614fe4565b613126565b606060008451116124d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b65790000000000000000000000604482015260640161067f565b60006124dc84613365565b905060006124e986613451565b905060008460405160200161250091815260200190565b60405160208183030381529060405290506000805b8451811015612e59576000858281518110612532576125326153ac565b6020026020010151905084518311156125cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e677468000000000000000000000000000000000000606482015260840161067f565b82600003612686578051805160209182012060405161261b926125f592910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612681576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f742068617368000000604482015260640161067f565b6127dd565b80515160201161273c57805180516020918201206040516126b0926125f592910190815260200190565b612681576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c206861736800000000000000000000000000000000000000000000000000606482015260840161067f565b8051845160208087019190912082519190920120146127dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f6520686173680000000000000000000000000000000000000000000000000000606482015260840161067f565b6127e960106001615298565b816020015151036129c5578451830361295d576128238160200151601081518110612816576128166153ac565b60200260200101516134b4565b965060008751116128b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e6368290000000000606482015260840161067f565b600186516128c49190614f9e565b8214612952576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e636829000000000000606482015260840161067f565b5050505050506122f3565b6000858481518110612971576129716153ac565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061299c5761299c6153ac565b602002602001015190506129af81613614565b95506129bc600186615298565b94505050612e46565b600281602001515103612dbe5760006129dd82613639565b90506000816000815181106129f4576129f46153ac565b016020015160f81c90506000612a0b6002836153db565b612a169060026153fd565b90506000612a27848360ff1661365d565b90506000612a358a8961365d565b90506000612a438383613693565b905080835114612ad5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b6579000000000000606482015260840161067f565b60ff851660021480612aea575060ff85166003145b15612cd95780825114612b7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e646572000000606482015260840161067f565b612b998760200151600181518110612816576128166153ac565b9c5060008d5111612c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c6561662900000000000000606482015260840161067f565b60018c51612c3a9190614f9e565b8814612cc8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c656166290000000000000000606482015260840161067f565b5050505050505050505050506122f3565b60ff85161580612cec575060ff85166001145b15612d2b57612d188760200151600181518110612d0b57612d0b6153ac565b6020026020010151613614565b9950612d24818a615298565b9850612db3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e207072656669780000000000000000000000000000606482015260840161067f565b505050505050612e46565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f6465000000000000000000000000000000000000000000000000606482015260840161067f565b5080612e5181615374565b915050612515565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e7473000000000000000000000000000000000000000000000000000000606482015260840161067f565b6000808213612f4d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161067f565b60006060612f5a84613747565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361315757506000919050565b680755bf798b4a1bf1e582126131c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f570000000000000000000000000000000000000000604482015260640161067f565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff8111156133835761338361486a565b6040519080825280602002602001820160405280156133c857816020015b60408051808201909152606080825260208201528152602001906001900390816133a15790505b50915060005b8181101561344a5760405180604001604052808583815181106133f3576133f36153ac565b60200260200101518152602001613422868481518110613415576134156153ac565b602002602001015161381d565b815250838281518110613437576134376153ac565b60209081029190910101526001016133ce565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b838110156134a9578060011b82018184015160001a8060041c8253600f81166001830153505060010161347b565b509295945050505050565b606060008060006134c485613830565b9194509250905060008160018111156134df576134df615420565b1461356c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d00000000000000606482015260840161067f565b6135768284615298565b855114613605576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e646572000000000000000000000000606482015260840161067f565b6123ed8560200151848461429d565b606060208260000151106136305761362b826134b4565b61105f565b61105f82614331565b606061105f6136588360200151600081518110612816576128166153ac565b613451565b60608251821061367c575060408051602081019091526000815261105f565b6122f3838384865161368e9190614f9e565b614347565b60008082518451106136a65782516136a9565b83515b90505b808210801561373057508282815181106136c8576136c86153ac565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613707576137076153ac565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613740578160010191506136ac565b5092915050565b60008082116137b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161067f565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606061105f61382b8361451f565b614608565b6000806000808460000151116138ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a40161067f565b6020840151805160001a607f8111613913576000600160009450945094505050614296565b60b78111613b21576000613928608083614f9e565b9050808760000151116139e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a40161067f565b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082141580613a5c57507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613b0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a40161067f565b5060019550935060009250614296915050565b60bf8111613e6f576000613b3660b783614f9e565b905080876000015111613bf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a40161067f565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613ccf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a40161067f565b600184015160088302610100031c60378111613d93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a40161067f565b613d9d8184615298565b895111613e52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a40161067f565b613e5d836001615298565b97509550600094506142969350505050565b60f78111613f50576000613e8460c083614f9e565b905080876000015111613f3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a40161067f565b600195509350849250614296915050565b6000613f5d60f783614f9e565b905080876000015111614018576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a40161067f565b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036140f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a40161067f565b600184015160088302610100031c603781116141ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a40161067f565b6141c48184615298565b895111614279576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a40161067f565b614284836001615298565b97509550600194506142969350505050565b9193909250565b60608167ffffffffffffffff8111156142b8576142b861486a565b6040519080825280601f01601f1916602001820160405280156142e2576020820181803683370190505b50905081156122f35760006142f78486615298565b90506020820160005b84811015614318578281015182820152602001614300565b84811115614327576000858301525b5050509392505050565b606061105f82602001516000846000015161429d565b60608182601f0110156143b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161067f565b828284011015614422576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161067f565b8183018451101561448f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015260640161067f565b6060821580156144ae5760405191506000825260208201604052614516565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156144e75780518352602092830192016144cf565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b604080518082019091526000808252602082015260008251116145ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a40161067f565b50604080518082019091528151815260209182019181019190915290565b6060600080600061461885613830565b91945092509050600181600181111561463357614633615420565b146146c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d0000000000000000606482015260840161067f565b84516146cc8385615298565b14614759576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e6465720000000000000000000000000000606482015260840161067f565b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816147705790505093506000835b865181101561485e576000806147e36040518060400160405280858c600001516147c79190614f9e565b8152602001858c602001516147dc9190615298565b9052613830565b5091509150604051806040016040528083836147ff9190615298565b8152602001848b602001516148149190615298565b815250888581518110614829576148296153ac565b602090810291909101015261483f600185615298565b935061484b8183615298565b6148559084615298565b9250505061479d565b50845250919392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156148e0576148e061486a565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461490a57600080fd5b50565b600082601f83011261491e57600080fd5b813567ffffffffffffffff8111156149385761493861486a565b61496960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614899565b81815284602083860101111561497e57600080fd5b816020850160208301376000918101602001919091529392505050565b600060c082840312156149ad57600080fd5b60405160c0810167ffffffffffffffff82821081831117156149d1576149d161486a565b8160405282935084358352602085013591506149ec826148e8565b81602084015260408501359150614a02826148e8565b816040840152606085013560608401526080850135608084015260a0850135915080821115614a3057600080fd5b50614a3d8582860161490d565b60a0830152505092915050565b600080600080600085870360e0811215614a6357600080fd5b863567ffffffffffffffff80821115614a7b57600080fd5b614a878a838b0161499b565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614ac057600080fd5b60408901955060c0890135925080831115614ada57600080fd5b828901925089601f840112614aee57600080fd5b8235915080821115614aff57600080fd5b508860208260051b8401011115614b1557600080fd5b959894975092955050506020019190565b60005b83811015614b41578181015183820152602001614b29565b83811115614b50576000848401525b50505050565b60008151808452614b6e816020860160208601614b26565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122f36020830184614b56565b600060208284031215614bc557600080fd5b5035919050565b600060208284031215614bde57600080fd5b813567ffffffffffffffff811115614bf557600080fd5b614c018482850161499b565b949350505050565b803567ffffffffffffffff81168114614c2157600080fd5b919050565b600060208284031215614c3857600080fd5b6122f382614c09565b80358015158114614c2157600080fd5b600080600080600060a08688031215614c6957600080fd5b8535614c74816148e8565b945060208601359350614c8960408701614c09565b9250614c9760608701614c41565b9150608086013567ffffffffffffffff811115614cb357600080fd5b614cbf8882890161490d565b9150509295509295909350565b60008060008060808587031215614ce257600080fd5b8435614ced816148e8565b93506020850135614cfd816148e8565b92506040850135614d0d816148e8565b9150614d1b60608601614c41565b905092959194509250565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614d7a816049850160208701614b26565b919091016049019695505050505050565b80516fffffffffffffffffffffffffffffffff81168114614c2157600080fd5b600060608284031215614dbd57600080fd5b6040516060810181811067ffffffffffffffff82111715614de057614de061486a565b60405282518152614df360208401614d8b565b6020820152614e0460408401614d8b565b60408201529392505050565b600060808284031215614e2257600080fd5b6040516080810181811067ffffffffffffffff82111715614e4557614e4561486a565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614e9157614e9161486a565b8360051b6020614ea2818301614899565b868152918501918181019036841115614eba57600080fd5b865b84811015614eee57803586811115614ed45760008081fd5b614ee036828b0161490d565b845250918301918301614ebc565b50979650505050505050565b600060208284031215614f0c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615614f6957614f69614f13565b02949350505050565b600067ffffffffffffffff808316818516808303821115614f9557614f95614f13565b01949350505050565b600082821015614fb057614fb0614f13565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614ff357614ff3614fb5565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561504757615047614f13565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561508657615086614f13565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156150ba576150ba614f13565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561510157615101614f13565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561513c5761513c614f13565b6000871292508782058712848416161561515857615158614f13565b8785058712818416161561516e5761516e614f13565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156151b6576151b6614f13565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156151ea576151ea614f13565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561522857615228614f13565b500290565b60008261523c5761523c614fb5565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261528c60c0830184614b56565b98975050505050505050565b600082198211156152ab576152ab614f13565b500190565b805163ffffffff81168114614c2157600080fd5b805160ff81168114614c2157600080fd5b600060c082840312156152e757600080fd5b60405160c0810181811067ffffffffffffffff8211171561530a5761530a61486a565b604052615316836152b0565b8152615324602084016152c4565b6020820152615335604084016152c4565b6040820152615346606084016152b0565b6060820152615357608084016152b0565b608082015261536860a08401614d8b565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036153a5576153a5614f13565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff8316806153ee576153ee614fb5565b8060ff84160691505092915050565b600060ff821660ff84168082101561541757615417614f13565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", - "deployedBytecode": "0x60806040526004361061016d5760003560e01c80638b4c40b0116100cb578063a35d99df1161007f578063e9e05c4211610059578063e9e05c4214610573578063f049875014610586578063fecf9734146105b157600080fd5b8063a35d99df1461040d578063cff0ab9614610446578063e965084c146104e757600080fd5b80639b5f694a116100b05780639b5f694a1461037e5780639bf62d82146103b0578063a14238e7146103dd57600080fd5b80638b4c40b0146101925780638c3152e91461035e57600080fd5b806354fd4d50116101225780636dbffb78116101075780636dbffb78146102fe578063724c184c1461031e5780638456cb591461034957600080fd5b806354fd4d501461027e5780635c975abb146102d457600080fd5b80633f4ba83a116101535780633f4ba83a1461021c578063452a9320146102315780634870496f1461025e57600080fd5b80621c2ff61461019957806333d7e2bd146101ef57600080fd5b36610194576101923334620186a06000604051806020016040528060008152506105d1565b005b600080fd5b3480156101a557600080fd5b50603554610100900473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101fb57600080fd5b506036546101c59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561022857600080fd5b5061019261086c565b34801561023d57600080fd5b506037546101c59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561026a57600080fd5b50610192610279366004614a4a565b610971565b34801561028a57600080fd5b506102c76040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b6040516101e69190614ba0565b3480156102e057600080fd5b506035546102ee9060ff1681565b60405190151581526020016101e6565b34801561030a57600080fd5b506102ee610319366004614bb3565b610fa6565b34801561032a57600080fd5b5060375473ffffffffffffffffffffffffffffffffffffffff166101c5565b34801561035557600080fd5b50610192611065565b34801561036a57600080fd5b50610192610379366004614bcc565b611167565b34801561038a57600080fd5b506035546101c590610100900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156103bc57600080fd5b506032546101c59073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103e957600080fd5b506102ee6103f8366004614bb3565b60336020526000908152604090205460ff1681565b34801561041957600080fd5b5061042d610428366004614c26565b611a2b565b60405167ffffffffffffffff90911681526020016101e6565b34801561045257600080fd5b506001546104ae906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101e6565b3480156104f357600080fd5b50610545610502366004614bb3565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101e6565b610192610581366004614c51565b6105d1565b34801561059257600080fd5b5060365473ffffffffffffffffffffffffffffffffffffffff166101c5565b3480156105bd57600080fd5b506101926105cc366004614ccc565b611a44565b8260005a905083156106885773ffffffffffffffffffffffffffffffffffffffff87161561068857604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b6106928351611a2b565b67ffffffffffffffff168567ffffffffffffffff161015610735576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c0000000000000000000000000000000000000000000000000000000000606482015260840161067f565b6201d4c0835111156107a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c617267650000604482015260640161067f565b333281146107c4575033731111000000000000000000000000000000001111015b600034888888886040516020016107df959493929190614d26565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161084f9190614ba0565b60405180910390a450506108638282611c52565b50505050505050565b60375473ffffffffffffffffffffffffffffffffffffffff163314610913576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a206f6e6c7920677561726469616e20636160448201527f6e20756e70617573650000000000000000000000000000000000000000000000606482015260840161067f565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60355460ff16156109de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a2070617573656400000000000000000000604482015260640161067f565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610a9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e747261637400606482015260840161067f565b6035546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101869052600091610100900473ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b369190614dab565b519050610b50610b4b36869003860186614e10565b611f7f565b8114610bde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f660000000000000000000000000000000000000000000000606482015260840161067f565b6000610be987611fdb565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610d035750805160355460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015261010090910473ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610cdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cff9190614dab565b5114155b610d8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e000000000000000000606482015260840161067f565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610e589101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610e4e888a614e76565b8a6040013561200b565b610ee4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f660000000000000000000000000000606482015260840161067f565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6035546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810183905260009161105f9161010090910473ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015611020573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110449190614dab565b602001516fffffffffffffffffffffffffffffffff1661202f565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff16331461110c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4f7074696d69736d506f7274616c3a206f6e6c7920677561726469616e20636160448201527f6e20706175736500000000000000000000000000000000000000000000000000606482015260840161067f565b603580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602001610967565b60355460ff16156111d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a2070617573656400000000000000000000604482015260640161067f565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461127d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e00606482015260840161067f565b600061128882611fdb565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611373576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e207965740000000000000000000000000000606482015260840161067f565b603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114049190614efa565b81602001516fffffffffffffffffffffffffffffffff1610156114cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a40161067f565b6114ee81602001516fffffffffffffffffffffffffffffffff1661202f565b6115a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a40161067f565b60355460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff9091166004820152600091610100900473ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa15801561162c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116509190614dab565b825181519192501461170a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a40161067f565b61172981602001516fffffffffffffffffffffffffffffffff1661202f565b6117db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a40161067f565b60008381526033602052604090205460ff161561187a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a65640000000000000000000000606482015260840161067f565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a088015161191c939291906120d4565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061198190841515815260200190565b60405180910390a2801580156119975750326001145b15611a24576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015260840161067f565b5050505050565b6000611a38826010614f42565b61105f90615208614f72565b600054600390610100900460ff16158015611a66575060005460ff8083169116105b611af2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161067f565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff831617610100908117909155603280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811661dead17909155603580546036805473ffffffffffffffffffffffffffffffffffffffff89811691861691909117909155603780548a83169516949094179093558515159289169093027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00167fffffffffffffffffffffff00000000000000000000000000000000000000000090931692909217179055611bed612132565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600154600090611c88907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643614f9e565b90506000611c94612215565b90506000816020015160ff16826000015163ffffffff16611cb59190614fe4565b90508215611dec57600154600090611cec908390700100000000000000000000000000000000900467ffffffffffffffff1661504c565b90506000836040015160ff1683611d0391906150c0565b600154611d239084906fffffffffffffffffffffffffffffffff166150c0565b611d2d9190614fe4565b600154909150600090611d7e90611d579084906fffffffffffffffffffffffffffffffff1661517c565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff166122db565b90506001861115611dad57611daa611d5782876040015160ff1660018a611da59190614f9e565b6122fa565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611e1f908490700100000000000000000000000000000000900467ffffffffffffffff16614f72565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611f02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d69740000606482015260840161067f565b600154600090611f2e906fffffffffffffffffffffffffffffffff1667ffffffffffffffff88166151f0565b90506000611f4048633b9aca0061234f565b611f4a908361522d565b905060005a611f599088614f9e565b905080821115611f7557611f75611f708284614f9e565b612366565b5050505050505050565b60008160000151826020015183604001518460600151604051602001611fbe949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097611fbe979096959101615241565b60008061201786612394565b9050612025818686866123c6565b9695505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa15801561209e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c29190614efa565b6120cc9083615298565b421192915050565b60008060006120e48660006123f6565b90508061211a576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff166121c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161067f565b60408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260365483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa1580156122b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d691906152d5565b905090565b60006122f06122ea8585612414565b83612424565b90505b9392505050565b6000670de0b6b3a764000061233b6123128583614fe4565b61232490670de0b6b3a764000061504c565b61233685670de0b6b3a76400006150c0565b612433565b61234590866150c0565b6122f09190614fe4565b60008183101561235f57816122f3565b5090919050565b6000805a90505b825a6123799083614f9e565b101561238f5761238882615374565b915061236d565b505050565b606081805190602001206040516020016123b091815260200190565b6040516020818303038152906040529050919050565b60006123ed846123d7878686612464565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b60008183121561235f57816122f3565b600081831261235f57816122f3565b60006122f3670de0b6b3a76400008361244b86612ee2565b61245591906150c0565b61245f9190614fe4565b613126565b606060008451116124d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b65790000000000000000000000604482015260640161067f565b60006124dc84613365565b905060006124e986613451565b905060008460405160200161250091815260200190565b60405160208183030381529060405290506000805b8451811015612e59576000858281518110612532576125326153ac565b6020026020010151905084518311156125cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e677468000000000000000000000000000000000000606482015260840161067f565b82600003612686578051805160209182012060405161261b926125f592910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612681576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f742068617368000000604482015260640161067f565b6127dd565b80515160201161273c57805180516020918201206040516126b0926125f592910190815260200190565b612681576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c206861736800000000000000000000000000000000000000000000000000606482015260840161067f565b8051845160208087019190912082519190920120146127dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f6520686173680000000000000000000000000000000000000000000000000000606482015260840161067f565b6127e960106001615298565b816020015151036129c5578451830361295d576128238160200151601081518110612816576128166153ac565b60200260200101516134b4565b965060008751116128b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e6368290000000000606482015260840161067f565b600186516128c49190614f9e565b8214612952576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e636829000000000000606482015260840161067f565b5050505050506122f3565b6000858481518110612971576129716153ac565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061299c5761299c6153ac565b602002602001015190506129af81613614565b95506129bc600186615298565b94505050612e46565b600281602001515103612dbe5760006129dd82613639565b90506000816000815181106129f4576129f46153ac565b016020015160f81c90506000612a0b6002836153db565b612a169060026153fd565b90506000612a27848360ff1661365d565b90506000612a358a8961365d565b90506000612a438383613693565b905080835114612ad5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b6579000000000000606482015260840161067f565b60ff851660021480612aea575060ff85166003145b15612cd95780825114612b7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e646572000000606482015260840161067f565b612b998760200151600181518110612816576128166153ac565b9c5060008d5111612c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c6561662900000000000000606482015260840161067f565b60018c51612c3a9190614f9e565b8814612cc8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c656166290000000000000000606482015260840161067f565b5050505050505050505050506122f3565b60ff85161580612cec575060ff85166001145b15612d2b57612d188760200151600181518110612d0b57612d0b6153ac565b6020026020010151613614565b9950612d24818a615298565b9850612db3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e207072656669780000000000000000000000000000606482015260840161067f565b505050505050612e46565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f6465000000000000000000000000000000000000000000000000606482015260840161067f565b5080612e5181615374565b915050612515565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e7473000000000000000000000000000000000000000000000000000000606482015260840161067f565b6000808213612f4d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161067f565b60006060612f5a84613747565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361315757506000919050565b680755bf798b4a1bf1e582126131c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f570000000000000000000000000000000000000000604482015260640161067f565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff8111156133835761338361486a565b6040519080825280602002602001820160405280156133c857816020015b60408051808201909152606080825260208201528152602001906001900390816133a15790505b50915060005b8181101561344a5760405180604001604052808583815181106133f3576133f36153ac565b60200260200101518152602001613422868481518110613415576134156153ac565b602002602001015161381d565b815250838281518110613437576134376153ac565b60209081029190910101526001016133ce565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b838110156134a9578060011b82018184015160001a8060041c8253600f81166001830153505060010161347b565b509295945050505050565b606060008060006134c485613830565b9194509250905060008160018111156134df576134df615420565b1461356c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d00000000000000606482015260840161067f565b6135768284615298565b855114613605576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e646572000000000000000000000000606482015260840161067f565b6123ed8560200151848461429d565b606060208260000151106136305761362b826134b4565b61105f565b61105f82614331565b606061105f6136588360200151600081518110612816576128166153ac565b613451565b60608251821061367c575060408051602081019091526000815261105f565b6122f3838384865161368e9190614f9e565b614347565b60008082518451106136a65782516136a9565b83515b90505b808210801561373057508282815181106136c8576136c86153ac565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613707576137076153ac565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613740578160010191506136ac565b5092915050565b60008082116137b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161067f565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606061105f61382b8361451f565b614608565b6000806000808460000151116138ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a40161067f565b6020840151805160001a607f8111613913576000600160009450945094505050614296565b60b78111613b21576000613928608083614f9e565b9050808760000151116139e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a40161067f565b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082141580613a5c57507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613b0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a40161067f565b5060019550935060009250614296915050565b60bf8111613e6f576000613b3660b783614f9e565b905080876000015111613bf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a40161067f565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613ccf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a40161067f565b600184015160088302610100031c60378111613d93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a40161067f565b613d9d8184615298565b895111613e52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a40161067f565b613e5d836001615298565b97509550600094506142969350505050565b60f78111613f50576000613e8460c083614f9e565b905080876000015111613f3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a40161067f565b600195509350849250614296915050565b6000613f5d60f783614f9e565b905080876000015111614018576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a40161067f565b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036140f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a40161067f565b600184015160088302610100031c603781116141ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a40161067f565b6141c48184615298565b895111614279576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a40161067f565b614284836001615298565b97509550600194506142969350505050565b9193909250565b60608167ffffffffffffffff8111156142b8576142b861486a565b6040519080825280601f01601f1916602001820160405280156142e2576020820181803683370190505b50905081156122f35760006142f78486615298565b90506020820160005b84811015614318578281015182820152602001614300565b84811115614327576000858301525b5050509392505050565b606061105f82602001516000846000015161429d565b60608182601f0110156143b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161067f565b828284011015614422576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161067f565b8183018451101561448f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015260640161067f565b6060821580156144ae5760405191506000825260208201604052614516565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156144e75780518352602092830192016144cf565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b604080518082019091526000808252602082015260008251116145ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a40161067f565b50604080518082019091528151815260209182019181019190915290565b6060600080600061461885613830565b91945092509050600181600181111561463357614633615420565b146146c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d0000000000000000606482015260840161067f565b84516146cc8385615298565b14614759576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e6465720000000000000000000000000000606482015260840161067f565b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816147705790505093506000835b865181101561485e576000806147e36040518060400160405280858c600001516147c79190614f9e565b8152602001858c602001516147dc9190615298565b9052613830565b5091509150604051806040016040528083836147ff9190615298565b8152602001848b602001516148149190615298565b815250888581518110614829576148296153ac565b602090810291909101015261483f600185615298565b935061484b8183615298565b6148559084615298565b9250505061479d565b50845250919392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156148e0576148e061486a565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461490a57600080fd5b50565b600082601f83011261491e57600080fd5b813567ffffffffffffffff8111156149385761493861486a565b61496960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614899565b81815284602083860101111561497e57600080fd5b816020850160208301376000918101602001919091529392505050565b600060c082840312156149ad57600080fd5b60405160c0810167ffffffffffffffff82821081831117156149d1576149d161486a565b8160405282935084358352602085013591506149ec826148e8565b81602084015260408501359150614a02826148e8565b816040840152606085013560608401526080850135608084015260a0850135915080821115614a3057600080fd5b50614a3d8582860161490d565b60a0830152505092915050565b600080600080600085870360e0811215614a6357600080fd5b863567ffffffffffffffff80821115614a7b57600080fd5b614a878a838b0161499b565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614ac057600080fd5b60408901955060c0890135925080831115614ada57600080fd5b828901925089601f840112614aee57600080fd5b8235915080821115614aff57600080fd5b508860208260051b8401011115614b1557600080fd5b959894975092955050506020019190565b60005b83811015614b41578181015183820152602001614b29565b83811115614b50576000848401525b50505050565b60008151808452614b6e816020860160208601614b26565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122f36020830184614b56565b600060208284031215614bc557600080fd5b5035919050565b600060208284031215614bde57600080fd5b813567ffffffffffffffff811115614bf557600080fd5b614c018482850161499b565b949350505050565b803567ffffffffffffffff81168114614c2157600080fd5b919050565b600060208284031215614c3857600080fd5b6122f382614c09565b80358015158114614c2157600080fd5b600080600080600060a08688031215614c6957600080fd5b8535614c74816148e8565b945060208601359350614c8960408701614c09565b9250614c9760608701614c41565b9150608086013567ffffffffffffffff811115614cb357600080fd5b614cbf8882890161490d565b9150509295509295909350565b60008060008060808587031215614ce257600080fd5b8435614ced816148e8565b93506020850135614cfd816148e8565b92506040850135614d0d816148e8565b9150614d1b60608601614c41565b905092959194509250565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614d7a816049850160208701614b26565b919091016049019695505050505050565b80516fffffffffffffffffffffffffffffffff81168114614c2157600080fd5b600060608284031215614dbd57600080fd5b6040516060810181811067ffffffffffffffff82111715614de057614de061486a565b60405282518152614df360208401614d8b565b6020820152614e0460408401614d8b565b60408201529392505050565b600060808284031215614e2257600080fd5b6040516080810181811067ffffffffffffffff82111715614e4557614e4561486a565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614e9157614e9161486a565b8360051b6020614ea2818301614899565b868152918501918181019036841115614eba57600080fd5b865b84811015614eee57803586811115614ed45760008081fd5b614ee036828b0161490d565b845250918301918301614ebc565b50979650505050505050565b600060208284031215614f0c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615614f6957614f69614f13565b02949350505050565b600067ffffffffffffffff808316818516808303821115614f9557614f95614f13565b01949350505050565b600082821015614fb057614fb0614f13565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614ff357614ff3614fb5565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561504757615047614f13565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561508657615086614f13565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156150ba576150ba614f13565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561510157615101614f13565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561513c5761513c614f13565b6000871292508782058712848416161561515857615158614f13565b8785058712818416161561516e5761516e614f13565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156151b6576151b6614f13565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156151ea576151ea614f13565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561522857615228614f13565b500290565b60008261523c5761523c614fb5565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261528c60c0830184614b56565b98975050505050505050565b600082198211156152ab576152ab614f13565b500190565b805163ffffffff81168114614c2157600080fd5b805160ff81168114614c2157600080fd5b600060c082840312156152e757600080fd5b60405160c0810181811067ffffffffffffffff8211171561530a5761530a61486a565b604052615316836152b0565b8152615324602084016152c4565b6020820152615335604084016152c4565b6040820152615346606084016152b0565b6060820152615357608084016152b0565b608082015261536860a08401614d8b565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036153a5576153a5614f13565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff8316806153ee576153ee614fb5565b8060ff84160691505092915050565b600060ff821660ff84168082101561541757615417614f13565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "GUARDIAN()": {}, - "L2_ORACLE()": {}, - "SYSTEM_CONFIG()": {}, - "depositTransaction(address,uint256,uint64,bool,bytes)": { - "params": { - "_data": "Data to trigger the recipient with.", - "_gasLimit": "Amount of L2 gas to purchase by burning gas on L1.", - "_isCreation": "Whether or not the transaction is a contract creation.", - "_to": "Target address on L2.", - "_value": "ETH value to send to the recipient." - } - }, - "finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))": { - "params": { - "_tx": "Withdrawal transaction to finalize." - } - }, - "initialize(address,address,address,bool)": { - "params": { - "_guardian": "Address that can pause withdrawals.", - "_l2Oracle": "Address of the L2OutputOracle contract.", - "_paused": "Sets the contract's pausability state.", - "_systemConfig": "Address of the SystemConfig contract." - } - }, - "isOutputFinalized(uint256)": { - "params": { - "_l2OutputIndex": "Index of the L2 output to check." - }, - "returns": { - "_0": "Whether or not the output is finalized." - } - }, - "minimumGasLimit(uint64)": { - "params": { - "_byteCount": "Number of bytes in the calldata." - }, - "returns": { - "_0": "The minimum gas limit for a deposit." - } - }, - "proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])": { - "params": { - "_l2OutputIndex": "L2 output index to prove against.", - "_outputRootProof": "Inclusion proof of the L2ToL1MessagePasser contract's storage root.", - "_tx": "Withdrawal transaction to finalize.", - "_withdrawalProof": "Inclusion proof of the withdrawal in L2ToL1MessagePasser contract." - } - } - }, - "events": { - "Paused(address)": { - "params": { - "account": "Address of the account triggering the pause." - } - }, - "TransactionDeposited(address,address,uint256,bytes)": { - "params": { - "from": "Address that triggered the deposit transaction.", - "opaqueData": "ABI encoded deposit data to be parsed off-chain.", - "to": "Address that the deposit transaction is directed to.", - "version": "Version of this deposit transaction event." - } - }, - "Unpaused(address)": { - "params": { - "account": "Address of the account triggering the unpause." - } - }, - "WithdrawalFinalized(bytes32,bool)": { - "params": { - "success": "Whether the withdrawal transaction was successful.", - "withdrawalHash": "Hash of the withdrawal transaction." - } - }, - "WithdrawalProven(bytes32,address,address)": { - "params": { - "from": "Address that triggered the withdrawal transaction.", - "to": "Address that the withdrawal transaction is directed to.", - "withdrawalHash": "Hash of the withdrawal transaction." - } - } - } - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Paused\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"opaqueData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"TransactionDeposited\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Unpaused\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\",\"indexed\":false}],\"type\":\"event\",\"name\":\"WithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"WithdrawalProven\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"GUARDIAN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"SYSTEM_CONFIG\",\"outputs\":[{\"internalType\":\"contract SystemConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositTransaction\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"donateETH\"},{\"inputs\":[{\"internalType\":\"struct Types.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeWithdrawalTransaction\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"guardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_guardian\",\"type\":\"address\"},{\"internalType\":\"contract SystemConfig\",\"name\":\"_systemConfig\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_paused\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"isOutputFinalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2Oracle\",\"outputs\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_byteCount\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"minimumGasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"params\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"prevBaseFee\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"prevBoughtGas\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"prevBlockNum\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"pause\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"struct Types.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}]},{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"},{\"internalType\":\"struct Types.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messagePasserStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}]},{\"internalType\":\"bytes[]\",\"name\":\"_withdrawalProof\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"proveWithdrawalTransaction\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"provenWithdrawals\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2OutputIndex\",\"type\":\"uint128\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"systemConfig\",\"outputs\":[{\"internalType\":\"contract SystemConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"unpause\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"GUARDIAN()\":{\"custom:legacy\":\"\"},\"L2_ORACLE()\":{\"custom:legacy\":\"\"},\"SYSTEM_CONFIG()\":{\"custom:legacy\":\"\"},\"depositTransaction(address,uint256,uint64,bool,bytes)\":{\"params\":{\"_data\":\"Data to trigger the recipient with.\",\"_gasLimit\":\"Amount of L2 gas to purchase by burning gas on L1.\",\"_isCreation\":\"Whether or not the transaction is a contract creation.\",\"_to\":\"Target address on L2.\",\"_value\":\"ETH value to send to the recipient.\"}},\"finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))\":{\"params\":{\"_tx\":\"Withdrawal transaction to finalize.\"}},\"initialize(address,address,address,bool)\":{\"params\":{\"_guardian\":\"Address that can pause withdrawals.\",\"_l2Oracle\":\"Address of the L2OutputOracle contract.\",\"_paused\":\"Sets the contract's pausability state.\",\"_systemConfig\":\"Address of the SystemConfig contract.\"}},\"isOutputFinalized(uint256)\":{\"params\":{\"_l2OutputIndex\":\"Index of the L2 output to check.\"},\"returns\":{\"_0\":\"Whether or not the output is finalized.\"}},\"minimumGasLimit(uint64)\":{\"params\":{\"_byteCount\":\"Number of bytes in the calldata.\"},\"returns\":{\"_0\":\"The minimum gas limit for a deposit.\"}},\"proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])\":{\"params\":{\"_l2OutputIndex\":\"L2 output index to prove against.\",\"_outputRootProof\":\"Inclusion proof of the L2ToL1MessagePasser contract's storage root.\",\"_tx\":\"Withdrawal transaction to finalize.\",\"_withdrawalProof\":\"Inclusion proof of the withdrawal in L2ToL1MessagePasser contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"GUARDIAN()\":{\"notice\":\"Getter for the Guardian\"},\"L2_ORACLE()\":{\"notice\":\"Getter for the L2OutputOracle\"},\"SYSTEM_CONFIG()\":{\"notice\":\"Getter for the SystemConfig\"},\"constructor\":{\"notice\":\"Constructs the OptimismPortal contract.\"},\"depositTransaction(address,uint256,uint64,bool,bytes)\":{\"notice\":\"Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in deriving deposit transactions. Note that if a deposit is made by a contract, its address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider using the CrossDomainMessenger contracts for a simpler developer experience.\"},\"donateETH()\":{\"notice\":\"Accepts ETH value without triggering a deposit to L2. This function mainly exists for the sake of the migration between the legacy Optimism system and Bedrock.\"},\"finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))\":{\"notice\":\"Finalizes a withdrawal transaction.\"},\"finalizedWithdrawals(bytes32)\":{\"notice\":\"A list of withdrawal hashes which have been successfully finalized.\"},\"guardian()\":{\"notice\":\"Address that has the ability to pause and unpause withdrawals.\"},\"initialize(address,address,address,bool)\":{\"notice\":\"Initializer.\"},\"isOutputFinalized(uint256)\":{\"notice\":\"Determine if a given output is finalized. Reverts if the call to L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.\"},\"l2Oracle()\":{\"notice\":\"Address of the L2OutputOracle contract.\"},\"l2Sender()\":{\"notice\":\"Address of the L2 account which initiated a withdrawal in this transaction. If the of this variable is the default L2 sender address, then we are NOT inside of a call to finalizeWithdrawalTransaction.\"},\"minimumGasLimit(uint64)\":{\"notice\":\"Computes the minimum gas limit for a deposit. The minimum gas limit linearly increases based on the size of the calldata. This is to prevent users from creating L2 resource usage without paying for it. This function can be used when interacting with the portal to ensure forwards compatibility.\"},\"params()\":{\"notice\":\"EIP-1559 style gas parameters.\"},\"pause()\":{\"notice\":\"Pauses withdrawals.\"},\"paused()\":{\"notice\":\"Determines if cross domain messaging is paused. When set to true, withdrawals are paused. This may be removed in the future.\"},\"proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])\":{\"notice\":\"Proves a withdrawal transaction.\"},\"provenWithdrawals(bytes32)\":{\"notice\":\"A mapping of withdrawal hashes to `ProvenWithdrawal` data.\"},\"systemConfig()\":{\"notice\":\"Address of the SystemConfig contract.\"},\"unpause()\":{\"notice\":\"Unpauses withdrawals.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/OptimismPortal.sol\":\"OptimismPortal\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L2OutputOracle.sol\":{\"keccak256\":\"0x60042eb3e619518cab9a8f2480b62871c2d813716e2e60d9a5e0c5f271c58705\",\"urls\":[\"bzz-raw://08538ef2aa99c508b56a8bb9b3c7b93476cba9dbf0b47783141e5e50a02156cc\",\"dweb:/ipfs/QmdvFZ1fUaTkNdmtB66rNAo73RxY7kccsgR6Uqz7psoXGN\"],\"license\":\"MIT\"},\"src/L1/OptimismPortal.sol\":{\"keccak256\":\"0xdca91a921b402d82b455d7f11027514e8a16dca906cf820b3afffe271beb8a13\",\"urls\":[\"bzz-raw://688912b9d6005af8395d5c2eb5c4e3367a8be7b50ea97c34fc6a7ac0e2d8fd6a\",\"dweb:/ipfs/QmNPJDwHpNmJ5VPWAJB8muRpZxYeySZDVoV1TMVN7roijJ\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x4bbbc7868e948c44f29285a69383e93251a0c330a67929fb72def01cec060d4e\",\"urls\":[\"bzz-raw://1e7ea2f8b3d49bee9c753f107ede6eda93b2cc0e34d0643fa14ebbb26c19e71b\",\"dweb:/ipfs/QmRP81F8FRVXVZs6u2f2poEPDnbFZhNwNYxHgCVEhGpEmB\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Bytes.sol\":{\"keccak256\":\"0x827f47d123b0fdf3b08816d5b33831811704dbf4e554e53f2269354f6bba8859\",\"urls\":[\"bzz-raw://3137ac7204d30a245a8b0d67aa6da5286f1bd8c90379daab561f84963b6db782\",\"dweb:/ipfs/QmWRhisw3axJK833gUScs23ETh2MLFbVzzqzYVMKSDN3S9\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPReader.sol\":{\"keccak256\":\"0x9ba74a3b0a11693e622380807d213d5d1250d974e18b2cd768da9cbe719a6778\",\"urls\":[\"bzz-raw://0808d721ed9e05707526ee134faa051d707a95ee6b8bd6e0b1972275da8e5723\",\"dweb:/ipfs/QmcTTPu9xgckfWdbFUAcr2RAgk3J6vzyR4FpV798TjFMeN\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/libraries/trie/MerkleTrie.sol\":{\"keccak256\":\"0xf8ba770ee6666e73ae43184c700e9c704b2c4ace71f9e3c2227ddc11a8148b4c\",\"urls\":[\"bzz-raw://4702ccee1fe44aea3ee01d59e6152eb755da083f786f00947fec4437c064fe74\",\"dweb:/ipfs/QmQjFj5J7hrEM1dxJjFszzW2Cs7g7eMhYNBXonF2DXBstE\"],\"license\":\"MIT\"},\"src/libraries/trie/SecureMerkleTrie.sol\":{\"keccak256\":\"0xeaff8315cfd21197bc6bc859c2decf5d4f4838c9c357c502cdf2b1eac863d288\",\"urls\":[\"bzz-raw://79dcdcaa560aea51d138da4f5dc553a1808b6de090b2dc1629f18375edbff681\",\"dweb:/ipfs/QmbE4pUPhf5fLKW4W6cEjhQs55gEDvHmbmoBqkW1yz3bnw\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"],\"license\":\"Apache-2.0\"}},\"version\":1}", - "numDeployments": 2, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 32100, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 32103, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 60835, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "params", - "offset": 0, - "slot": "1", - "type": "t_struct(ResourceParams)60818_storage" - }, - { - "astId": 60840, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "__gap", - "offset": 0, - "slot": "2", - "type": "t_array(t_uint256)48_storage" - }, - { - "astId": 59871, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "l2Sender", - "offset": 0, - "slot": "50", - "type": "t_address" - }, - { - "astId": 59876, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "finalizedWithdrawals", - "offset": 0, - "slot": "51", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 59882, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "provenWithdrawals", - "offset": 0, - "slot": "52", - "type": "t_mapping(t_bytes32,t_struct(ProvenWithdrawal)59860_storage)" - }, - { - "astId": 59885, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "paused", - "offset": 0, - "slot": "53", - "type": "t_bool" - }, - { - "astId": 59889, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "l2Oracle", - "offset": 1, - "slot": "53", - "type": "t_contract(L2OutputOracle)59820" - }, - { - "astId": 59893, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "systemConfig", - "offset": 0, - "slot": "54", - "type": "t_contract(SystemConfig)61941" - }, - { - "astId": 59896, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "guardian", - "offset": 0, - "slot": "55", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)48_storage": { - "encoding": "inplace", - "label": "uint256[48]", - "numberOfBytes": "1536", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(L2OutputOracle)59820": { - "encoding": "inplace", - "label": "contract L2OutputOracle", - "numberOfBytes": "20" - }, - "t_contract(SystemConfig)61941": { - "encoding": "inplace", - "label": "contract SystemConfig", - "numberOfBytes": "20" - }, - "t_mapping(t_bytes32,t_bool)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_mapping(t_bytes32,t_struct(ProvenWithdrawal)59860_storage)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => struct OptimismPortal.ProvenWithdrawal)", - "numberOfBytes": "32", - "value": "t_struct(ProvenWithdrawal)59860_storage" - }, - "t_struct(ProvenWithdrawal)59860_storage": { - "encoding": "inplace", - "label": "struct OptimismPortal.ProvenWithdrawal", - "numberOfBytes": "64", - "members": [ - { - "astId": 59855, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "outputRoot", - "offset": 0, - "slot": "0", - "type": "t_bytes32" - }, - { - "astId": 59857, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "timestamp", - "offset": 0, - "slot": "1", - "type": "t_uint128" - }, - { - "astId": 59859, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "l2OutputIndex", - "offset": 16, - "slot": "1", - "type": "t_uint128" - } - ] - }, - "t_struct(ResourceParams)60818_storage": { - "encoding": "inplace", - "label": "struct ResourceMetering.ResourceParams", - "numberOfBytes": "32", - "members": [ - { - "astId": 60813, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "prevBaseFee", - "offset": 0, - "slot": "0", - "type": "t_uint128" - }, - { - "astId": 60815, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "prevBoughtGas", - "offset": 16, - "slot": "0", - "type": "t_uint64" - }, - { - "astId": 60817, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "prevBlockNum", - "offset": 24, - "slot": "0", - "type": "t_uint64" - } - ] - }, - "t_uint128": { - "encoding": "inplace", - "label": "uint128", - "numberOfBytes": "16" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint64": { - "encoding": "inplace", - "label": "uint64", - "numberOfBytes": "8" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x53b24743fdd00ac90ab5b91a531a7f8ab74d29e8db7a85db5e489fa5d8d08702", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "GUARDIAN()": { - "notice": "Getter for the Guardian" - }, - "L2_ORACLE()": { - "notice": "Getter for the L2OutputOracle" - }, - "SYSTEM_CONFIG()": { - "notice": "Getter for the SystemConfig" - }, - "constructor": { - "notice": "Constructs the OptimismPortal contract." - }, - "depositTransaction(address,uint256,uint64,bool,bytes)": { - "notice": "Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in deriving deposit transactions. Note that if a deposit is made by a contract, its address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider using the CrossDomainMessenger contracts for a simpler developer experience." - }, - "donateETH()": { - "notice": "Accepts ETH value without triggering a deposit to L2. This function mainly exists for the sake of the migration between the legacy Optimism system and Bedrock." - }, - "finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))": { - "notice": "Finalizes a withdrawal transaction." - }, - "finalizedWithdrawals(bytes32)": { - "notice": "A list of withdrawal hashes which have been successfully finalized." - }, - "guardian()": { - "notice": "Address that has the ability to pause and unpause withdrawals." - }, - "initialize(address,address,address,bool)": { - "notice": "Initializer." - }, - "isOutputFinalized(uint256)": { - "notice": "Determine if a given output is finalized. Reverts if the call to L2_ORACLE.getL2Output reverts. Returns a boolean otherwise." - }, - "l2Oracle()": { - "notice": "Address of the L2OutputOracle contract." - }, - "l2Sender()": { - "notice": "Address of the L2 account which initiated a withdrawal in this transaction. If the of this variable is the default L2 sender address, then we are NOT inside of a call to finalizeWithdrawalTransaction." - }, - "minimumGasLimit(uint64)": { - "notice": "Computes the minimum gas limit for a deposit. The minimum gas limit linearly increases based on the size of the calldata. This is to prevent users from creating L2 resource usage without paying for it. This function can be used when interacting with the portal to ensure forwards compatibility." - }, - "params()": { - "notice": "EIP-1559 style gas parameters." - }, - "pause()": { - "notice": "Pauses withdrawals." - }, - "paused()": { - "notice": "Determines if cross domain messaging is paused. When set to true, withdrawals are paused. This may be removed in the future." - }, - "proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])": { - "notice": "Proves a withdrawal transaction." - }, - "provenWithdrawals(bytes32)": { - "notice": "A mapping of withdrawal hashes to `ProvenWithdrawal` data." - }, - "systemConfig()": { - "notice": "Address of the SystemConfig contract." - }, - "unpause()": { - "notice": "Unpauses withdrawals." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "Paused(address)": { - "notice": "Emitted when the pause is triggered." - }, - "TransactionDeposited(address,address,uint256,bytes)": { - "notice": "Emitted when a transaction is deposited from L1 to L2. The parameters of this event are read by the rollup node and used to derive deposit transactions on L2." - }, - "Unpaused(address)": { - "notice": "Emitted when the pause is lifted." - }, - "WithdrawalFinalized(bytes32,bool)": { - "notice": "Emitted when a withdrawal transaction is finalized." - }, - "WithdrawalProven(bytes32,address,address)": { - "notice": "Emitted when a withdrawal transaction is proven." - } - }, - "notice": "The OptimismPortal is a low-level contract responsible for passing messages between L1 and L2. Messages sent directly to the OptimismPortal have no form of replayability. Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/OptimismPortalProxy.json b/packages/contracts-bedrock/deployments/mainnet/OptimismPortalProxy.json deleted file mode 100644 index 37b62aa64690..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/OptimismPortalProxy.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "address": "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed", - "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": "0x8da60c6cebf2d2c87437952eb159c6be86edb98cf0f98bba058df16b4d8aa943", - "receipt": { - "to": null, - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "contractAddress": "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed", - "transactionIndex": 110, - "gasUsed": "523960", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x46d5b502bf0b4473d984d51e838c2fe8221d19ed75adcab17844d6e746e3643b", - "transactionHash": "0x8da60c6cebf2d2c87437952eb159c6be86edb98cf0f98bba058df16b4d8aa943", - "logs": [ - { - "transactionIndex": 110, - "blockNumber": 17365802, - "transactionHash": "0x8da60c6cebf2d2c87437952eb159c6be86edb98cf0f98bba058df16b4d8aa943", - "address": "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000543ba4aadbab8f9025686bd03993043599c6fb04", - "logIndex": 291, - "blockHash": "0x46d5b502bf0b4473d984d51e838c2fe8221d19ed75adcab17844d6e746e3643b" - } - ], - "blockNumber": 17365802, - "cumulativeGasUsed": "10917526", - "status": 1, - "byzantium": true - }, - "args": [ - "0x543bA4AADBAb8f9025686Bd03993043599c6fB04" - ], - "numDeployments": 1, - "solcInputHash": "13ac93d026822f719ad110af836d1582", - "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\":{\"contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@cwia/=node_modules/clones-with-immutable-args/src/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":clones-with-immutable-args/=node_modules/clones-with-immutable-args/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0x64d67f1936d97c87a2e42317eb162744ad5cefdc9bc8b1138ee4afe2886eb885\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://33b903585eb9cfc60a70bcdf4ee44220b173caff16dfb9071cd0668c7a551265\",\"dweb:/ipfs/QmXHUZ9brinN1WS9i63ocRQsQidY96WePDBhBsFRhDmVjr\"]}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "admin()": { - "returns": { - "_0": "Owner address." - } - }, - "changeAdmin(address)": { - "params": { - "_admin": "New owner of the proxy contract." - } - }, - "constructor": { - "params": { - "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "Address of the implementation contract." - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "Calldata to delegatecall the new implementation with.", - "_implementation": "Address of the implementation contract." - } - } - }, - "events": { - "AdminChanged(address,address)": { - "params": { - "newAdmin": "The new owner of the contract", - "previousAdmin": "The previous owner of the contract" - } - }, - "Upgraded(address)": { - "params": { - "implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "admin()": { - "notice": "Gets the owner of the proxy contract." - }, - "changeAdmin(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "constructor": { - "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." - }, - "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." - } - }, - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." - } - }, - "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/PortalSender.json b/packages/contracts-bedrock/deployments/mainnet/PortalSender.json deleted file mode 100644 index f3111b0c1446..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/PortalSender.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "address": "0x0A893d9576b9cFD9EF78595963dc973238E78210", - "abi": [ - { - "inputs": [ - { - "internalType": "contract OptimismPortal", - "name": "_portal", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "PORTAL", - "outputs": [ - { - "internalType": "contract OptimismPortal", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "donate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xec487a1d2cd607cad1c88ad2769a694901b268a97e45f662afe6a39266b93d60", - "receipt": { - "to": null, - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "contractAddress": "0x0A893d9576b9cFD9EF78595963dc973238E78210", - "transactionIndex": 92, - "gasUsed": "118186", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd88eeaeb10110aa57b00c2e414b1e69979c14d265bc571884450dad5bab60a79", - "transactionHash": "0xec487a1d2cd607cad1c88ad2769a694901b268a97e45f662afe6a39266b93d60", - "logs": [], - "blockNumber": 17365811, - "cumulativeGasUsed": "9259464", - "status": 1, - "byzantium": true - }, - "args": [ - "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed" - ], - "numDeployments": 1, - "solcInputHash": "13ac93d026822f719ad110af836d1582", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"_portal\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"PORTAL\",\"outputs\":[{\"internalType\":\"contract OptimismPortal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"donate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_portal\":\"Address of the OptimismPortal contract.\"}}},\"title\":\"PortalSender\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"PORTAL()\":{\"notice\":\"Address of the OptimismPortal contract.\"},\"donate()\":{\"notice\":\"Sends balance of this contract to the OptimismPortal.\"}},\"notice\":\"The PortalSender is a simple intermediate contract that will transfer the balance of the L1StandardBridge to the OptimismPortal during the Bedrock migration.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/deployment/PortalSender.sol\":\"PortalSender\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@cwia/=node_modules/clones-with-immutable-args/src/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":clones-with-immutable-args/=node_modules/clones-with-immutable-args/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/L1/L2OutputOracle.sol\":{\"keccak256\":\"0xba09a5005080e6c7ccc9e0dab17165f20ae0ef9d9c04a13d0b5c158dc1c2a4bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fce7e5b5fb4882f05ddcd540f4781225bcf95870b5206e1b423a98ddd3e80df2\",\"dweb:/ipfs/QmQxsgVPaZmkW8SKxKtQEmP5ApeXAxaEEC6Hf4AQ4xL3wC\"]},\"contracts/L1/OptimismPortal.sol\":{\"keccak256\":\"0x3b16493feec098a6d70b98a83e0f7c5f541ac33c5265edee77c2c0229c343fd2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://795b7f9aca7930f9b446d81071ba7d35872f3fbd53faa0e7acb1f51df4edb7f2\",\"dweb:/ipfs/QmTwr3pGnVVN2qfTjPqC5svhM7rLVLgiEj1SthHVz1v4k8\"]},\"contracts/L1/ResourceMetering.sol\":{\"keccak256\":\"0xbd7b9532a70d8c842bfce0ea971be50d02fbbf0227c9ad55c71ac68d438010f4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4969f478dd54e89392cda2ea0c5edcf1be55a5dee43a0e410527b6e3bcb85c88\",\"dweb:/ipfs/QmU2crAojw8DRDsz7PAPrereazjFsKh9wtfTpTDVh6NLfW\"]},\"contracts/L1/SystemConfig.sol\":{\"keccak256\":\"0x2202e03df7b5f70b0cf1cf942afe51cab165bf35864a77d6a77dc82c55653689\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://42ec7d69b192c6199bf28ccf1d19d896f01807039f6bdc3e871b52eb7d9ee645\",\"dweb:/ipfs/QmPmWLf9a9FJ2fYQi9nP73e4QRnAMDbrfNwLS1u8KZgrEs\"]},\"contracts/deployment/PortalSender.sol\":{\"keccak256\":\"0xe60d88036d9aa8f8e80a4108ee30ad987564ad996af87a79ba92f6ca35852881\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a4be187cd3d5926592491f722dfa1b1c41a8f4f1abdc8cf3883964f70acb0a44\",\"dweb:/ipfs/QmYsAK4YcRHmPoex2eX2x1r6N76AMk3rdBHHmp6gUT73Fa\"]},\"contracts/libraries/Arithmetic.sol\":{\"keccak256\":\"0xc8858039f87e48e6f18c1af8bc0b03e57cfef564acddfd06e4d91e3db7ac5ed6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2fc79af1e844aa6dc1c68067bfe1d359df8d4e9a3e8881afb3bcfcbf68071714\",\"dweb:/ipfs/QmcNC4k8zmvwj4kZizSenTiWbx2DJQPbwqXXLF4iMbkRVD\"]},\"contracts/libraries/Burn.sol\":{\"keccak256\":\"0x54233b226ba6919dc46d438bc790108d8f855001002a1b9c3c37aed7a83e5f3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4051a4baca357a9191a6c9e3aa1593a17b69dd7915966e23e4cb269e9c1d9ed4\",\"dweb:/ipfs/QmadKjGKvxm53abVHQdsxrXBc8e9jXywu6vvhkAgjsx59J\"]},\"contracts/libraries/Bytes.sol\":{\"keccak256\":\"0x7aca6593fadf438ee9cd090d8fdc8f94a5202a2eb7f764c9a86f207712d87a48\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://aac32157885c5a08bd0bc7dcd5511f66db12bb20d0c263dd7be9f58b91538fc1\",\"dweb:/ipfs/Qmb1iG11Z53yt9wNbGsuTvoydJXFosDDpWwRSADKyqiCjw\"]},\"contracts/libraries/Constants.sol\":{\"keccak256\":\"0x8c7be28a175eb732995a7f704560163c30261f9f70d377f865c5060882509f5d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f72aba26553b10ca88708e05461691b36b0d2ec7a87f718022fe119ca9c70852\",\"dweb:/ipfs/QmQtDEB1F3D8RsgG63KSJ9t7ZyFLaXc2Av81vKD9y2TMn7\"]},\"contracts/libraries/Encoding.sol\":{\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f18156216c1f9457c2e032a812ad70f2babbc5b89997554ff014d64c483fb2ff\",\"dweb:/ipfs/Qmc5rjMaBFn3jV7XqDrEvRbmatQvJxeVJYA5B5rdcKPkcJ\"]},\"contracts/libraries/Hashing.sol\":{\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6746ed0d26d603568818cc52a29d0209effd69f7e55bd0017a6b91bd6cf319fe\",\"dweb:/ipfs/QmPebCmCELMBRtDDxt5ziEPfRXUh6tfm2qJdwz3iyrDdWN\"]},\"contracts/libraries/SafeCall.sol\":{\"keccak256\":\"0x3deedbfc0a57228366531a4f09c94d174f0bb4ea49476a92226d471f3abb349b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e8091b178f6710cb7738f07b1706fe18c241b6275b6641b32724d4ecf5a087dd\",\"dweb:/ipfs/Qmd5kchcZhHepJ3boHRTVDJUr9jsuweWEyoUmNmMFJB6vp\"]},\"contracts/libraries/Types.sol\":{\"keccak256\":\"0x4fe8ec920798661a828430bd30dc2715eeb40534ec01c0a7bf41cb4ab422e134\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://74c8471869900bd459358cd990bda1c8d234c06b788804c7049cf465ae1e299f\",\"dweb:/ipfs/QmakcfP6NmbVUQsKqH7rEyJsbiqckigLahw9g74oencEJ7\"]},\"contracts/libraries/rlp/RLPReader.sol\":{\"keccak256\":\"0x50763c897f0fe84cb067985ec4d7c5721ce9004a69cf0327f96f8982ee8ca412\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://603af847b43933b075f9aac3a7b3cd65041ffe6d732826695458ca9575e1a809\",\"dweb:/ipfs/QmfByFEaCxT9y1VtqoLi5EsXZ9ihkPfj6g5x7pcPoQ7q2K\"]},\"contracts/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://921c44e6a0982b9a4011900fda1bda2c06b7a85894967de98b407a83fe9f90c0\",\"dweb:/ipfs/QmSsHLKDUQ82kpKdqB6VntVGKuPDb4W9VdotsubuqWBzio\"]},\"contracts/libraries/trie/MerkleTrie.sol\":{\"keccak256\":\"0xd27fc945d6dd2821636d840f3766f817823c8e9fbfdb87c2da7c73e4292d2f7f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://497cec37d09ebcdc8d1cccac608a4a0b9b9d83eac6cc7c9e8b73c4c6644e2209\",\"dweb:/ipfs/QmUYMsCcgU6epspvKV9Y6anHyyMb4hd1xVzUZheBY9mfG7\"]},\"contracts/libraries/trie/SecureMerkleTrie.sol\":{\"keccak256\":\"0x61b03a03779cb1f75cea3b88af16fdfd10629029b4b2d6be5238e71af8ef1b5f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1212951af291c0e033a7119b42de5cad6b6bf32da26777da7c2419e76fa8f314\",\"dweb:/ipfs/QmYbnifDmL6UkP9D1X9GaNLR1Q8wYwmDNeYqkJ71bycaE5\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9baf7797439c0ae6512f4639dfc6a1934dbd4e4d7cbb8e63e99264ff47682c9e\",\"dweb:/ipfs/QmawAuhppPyeoZH3rC1uh87xDELa9Lyfw5pYsBqE8myE1m\"]},\"contracts/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"]},\"node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"]},\"node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"]},\"node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"]},\"node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"]},\"node_modules/@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]},\"node_modules/@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"]},\"node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"]},\"node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"]}},\"version\":1}", - "bytecode": "0x60a060405234801561001057600080fd5b506040516101b53803806101b583398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b6080516101256100906000396000818160400152609701526101256000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630ff754ea1461003b578063ed88c68e1461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610093610095565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638b4c40b0476040518263ffffffff1660e01b81526004016000604051808303818588803b1580156100fd57600080fd5b505af1158015610111573d6000803e3d6000fd5b505050505056fea164736f6c634300080f000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80630ff754ea1461003b578063ed88c68e1461008b575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b610093610095565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638b4c40b0476040518263ffffffff1660e01b81526004016000604051808303818588803b1580156100fd57600080fd5b505af1158015610111573d6000803e3d6000fd5b505050505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_portal": "Address of the OptimismPortal contract." - } - } - }, - "title": "PortalSender" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "PORTAL()": { - "notice": "Address of the OptimismPortal contract." - }, - "donate()": { - "notice": "Sends balance of this contract to the OptimismPortal." - } - }, - "notice": "The PortalSender is a simple intermediate contract that will transfer the balance of the L1StandardBridge to the OptimismPortal during the Bedrock migration." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/ProtocolVersions.json b/packages/contracts-bedrock/deployments/mainnet/ProtocolVersions.json deleted file mode 100644 index ed490ec191c0..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/ProtocolVersions.json +++ /dev/null @@ -1,496 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "version", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "enum ProtocolVersions.UpdateType", - "name": "updateType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "ConfigUpdate", - "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": "RECOMMENDED_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REQUIRED_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "ProtocolVersion", - "name": "_required", - "type": "uint256" - }, - { - "internalType": "ProtocolVersion", - "name": "_recommended", - "type": "uint256" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "recommended", - "outputs": [ - { - "internalType": "ProtocolVersion", - "name": "out_", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "required", - "outputs": [ - { - "internalType": "ProtocolVersion", - "name": "out_", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "ProtocolVersion", - "name": "_recommended", - "type": "uint256" - } - ], - "name": "setRecommended", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "ProtocolVersion", - "name": "_required", - "type": "uint256" - } - ], - "name": "setRequired", - "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" - } - ], - "address": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "args": [], - "bytecode": "0x60806040523480156200001157600080fd5b506200002261dead60008062000028565b620004c9565b600054600390610100900460ff161580156200004b575060005460ff8083169116105b620000b45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805461ffff191660ff831617610100179055620000d26200013a565b620000dd84620001a2565b620000e88362000221565b620000f382620002d1565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b600054610100900460ff16620001965760405162461bcd60e51b815260206004820152602b602482015260008051602062000e9683398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000ab565b620001a062000332565b565b620001ac62000399565b6001600160a01b038116620002135760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620000ab565b6200021e81620003f5565b50565b620002676200025260017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16200044b565b60001b826200044760201b620004f51760201c565b6000816040516020016200027d91815260200190565b60408051601f19818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051620002c5919062000471565b60405180910390a35050565b620003026200025260017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6200044b565b6000816040516020016200031891815260200190565b60408051601f198184030181529190529050600162000292565b600054610100900460ff166200038e5760405162461bcd60e51b815260206004820152602b602482015260008051602062000e9683398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000ab565b620001a033620003f5565b6033546001600160a01b03163314620001a05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620000ab565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b9055565b6000828210156200046c57634e487b7160e01b600052601160045260246000fd5b500390565b600060208083528351808285015260005b81811015620004a05785810183015185820160400152820162000482565b81811115620004b3576000604083870101525b50601f01601f1916929092016040019392505050565b6109bd80620004d96000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e736600461085d565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161010091906108e1565b6100ec61016036600461085d565b61021d565b6100ec61022e565b6100ec61017b366004610924565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103ad565b6100f66103e6565b6100ec6101c6366004610957565b610416565b6100f66104ca565b6100f6600081565b6101e36104f9565b6101ec8161057a565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b81565b6102256104f9565b6101ec81610632565b6102366104f9565b61024060006106ac565b565b600054600390610100900460ff16158015610264575060005460ff8083169116105b6102f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905561032e610723565b61033784610416565b6103408361057a565b61034982610632565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b60006103e16103dd60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b5490565b905090565b60006103e16103dd60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b61041e6104f9565b73ffffffffffffffffffffffffffffffffffffffff81166104c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102ec565b6101ec816106ac565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102ec565b6105ad6105a860017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b829055565b6000816040516020016105c291815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161062691906108e1565b60405180910390a35050565b6106606105a860017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b60008160405160200161067591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060016105f5565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166107ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ec565b610240600054610100900460ff16610854576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ec565b610240336106ac565b60006020828403121561086f57600080fd5b5035919050565b6000815180845260005b8181101561089c57602081850181015186830182015201610880565b818111156108ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006108f46020830184610876565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091f57600080fd5b919050565b60008060006060848603121561093957600080fd5b610942846108fb565b95602085013595506040909401359392505050565b60006020828403121561096957600080fd5b6108f4826108fb565b6000828210156109ab577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e736600461085d565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161010091906108e1565b6100ec61016036600461085d565b61021d565b6100ec61022e565b6100ec61017b366004610924565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103ad565b6100f66103e6565b6100ec6101c6366004610957565b610416565b6100f66104ca565b6100f6600081565b6101e36104f9565b6101ec8161057a565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b81565b6102256104f9565b6101ec81610632565b6102366104f9565b61024060006106ac565b565b600054600390610100900460ff16158015610264575060005460ff8083169116105b6102f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905561032e610723565b61033784610416565b6103408361057a565b61034982610632565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b60006103e16103dd60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b5490565b905090565b60006103e16103dd60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b61041e6104f9565b73ffffffffffffffffffffffffffffffffffffffff81166104c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102ec565b6101ec816106ac565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102ec565b6105ad6105a860017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b829055565b6000816040516020016105c291815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161062691906108e1565b60405180910390a35050565b6106606105a860017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b60008160405160200161067591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060016105f5565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166107ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ec565b610240600054610100900460ff16610854576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ec565b610240336106ac565b60006020828403121561086f57600080fd5b5035919050565b6000815180845260005b8181101561089c57602081850181015186830182015201610880565b818111156108ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006108f46020830184610876565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091f57600080fd5b919050565b60008060006060848603121561093957600080fd5b610942846108fb565b95602085013595506040909401359392505050565b60006020828403121561096957600080fd5b6108f4826108fb565b6000828210156109ab577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "initialize(address,uint256,uint256)": { - "params": { - "_owner": "Initial owner of the contract.", - "_recommended": "Recommended protocol version to operate on thi chain.", - "_required": "Required protocol version to operate on this chain." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "recommended()": { - "returns": { - "out_": "Recommended protocol version to sync to the head of the chain." - } - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "required()": { - "returns": { - "out_": "Required protocol version to sync to the head of the chain." - } - }, - "setRecommended(uint256)": { - "params": { - "_recommended": "New recommended protocol version." - } - }, - "setRequired(uint256)": { - "params": { - "_required": "New required protocol version." - } - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - } - }, - "events": { - "ConfigUpdate(uint256,uint8,bytes)": { - "params": { - "data": "Encoded update data.", - "updateType": "Type of update.", - "version": "ProtocolVersion version." - } - } - }, - "title": "ProtocolVersions" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"enum ProtocolVersions.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ConfigUpdate\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RECOMMENDED_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"REQUIRED_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"ProtocolVersion\",\"name\":\"_required\",\"type\":\"uint256\"},{\"internalType\":\"ProtocolVersion\",\"name\":\"_recommended\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"recommended\",\"outputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"out_\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"required\",\"outputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"out_\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"_recommended\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setRecommended\"},{\"inputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"_required\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setRequired\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"initialize(address,uint256,uint256)\":{\"params\":{\"_owner\":\"Initial owner of the contract.\",\"_recommended\":\"Recommended protocol version to operate on thi chain.\",\"_required\":\"Required protocol version to operate on this chain.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"recommended()\":{\"returns\":{\"out_\":\"Recommended protocol version to sync to the head of the chain.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"required()\":{\"returns\":{\"out_\":\"Required protocol version to sync to the head of the chain.\"}},\"setRecommended(uint256)\":{\"params\":{\"_recommended\":\"New recommended protocol version.\"}},\"setRequired(uint256)\":{\"params\":{\"_required\":\"New required protocol version.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"RECOMMENDED_SLOT()\":{\"notice\":\"Storage slot that the recommended protocol version is stored at.\"},\"REQUIRED_SLOT()\":{\"notice\":\"Storage slot that the required protocol version is stored at.\"},\"VERSION()\":{\"notice\":\"Version identifier, used for upgrades.\"},\"constructor\":{\"notice\":\"Constructs the ProtocolVersion contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)` A zero version is considered empty and is ignored by nodes.\"},\"initialize(address,uint256,uint256)\":{\"notice\":\"Initializer.\"},\"recommended()\":{\"notice\":\"High level getter for the recommended protocol version.\"},\"required()\":{\"notice\":\"High level getter for the required protocol version.\"},\"setRecommended(uint256)\":{\"notice\":\"Updates the recommended protocol version. Can only be called by the owner.\"},\"setRequired(uint256)\":{\"notice\":\"Updates the required protocol version. Can only be called by the owner.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/ProtocolVersions.sol\":\"ProtocolVersions\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ProtocolVersions.sol\":{\"keccak256\":\"0xa283721c36e2ba3ea1c61faebc364a8884bf3a276f80374cc8017d0e23ea1dfc\",\"urls\":[\"bzz-raw://4ee23cbc9772213c637c767747e5fb1db7c3f0f17d6a1ff576b638f25c6799e8\",\"dweb:/ipfs/QmfKZfFC6fyhQdLk2YrjVBL6eRX1d9CTrPHj7fNPUNXmEq\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 1, - "receipt": { - "transactionHash": "0x34e5f1585a2404da7aa6108fbef8d63a4e9d5b077b17b791dfb3aed69d9486cc", - "transactionIndex": "0x7f", - "blockHash": "0x209f9de05c2399a0abd737a44aa0ec55bf2221c7dfedbfe61724b0a831c8f0c8", - "blockNumber": "0x11842d9", - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "cumulativeGasUsed": "0x12caf91", - "gasUsed": "0xa3523", - "contractAddress": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "logs": [ - { - "address": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c" - ], - "data": "0x", - "blockHash": "0x209f9de05c2399a0abd737a44aa0ec55bf2221c7dfedbfe61724b0a831c8f0c8", - "blockNumber": "0x11842d9", - "transactionHash": "0x34e5f1585a2404da7aa6108fbef8d63a4e9d5b077b17b791dfb3aed69d9486cc", - "transactionIndex": "0x7f", - "logIndex": "0x63e", - "removed": false - }, - { - "address": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "0x000000000000000000000000000000000000000000000000000000000000dead" - ], - "data": "0x", - "blockHash": "0x209f9de05c2399a0abd737a44aa0ec55bf2221c7dfedbfe61724b0a831c8f0c8", - "blockNumber": "0x11842d9", - "transactionHash": "0x34e5f1585a2404da7aa6108fbef8d63a4e9d5b077b17b791dfb3aed69d9486cc", - "transactionIndex": "0x7f", - "logIndex": "0x63f", - "removed": false - }, - { - "address": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "topics": [ - "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x209f9de05c2399a0abd737a44aa0ec55bf2221c7dfedbfe61724b0a831c8f0c8", - "blockNumber": "0x11842d9", - "transactionHash": "0x34e5f1585a2404da7aa6108fbef8d63a4e9d5b077b17b791dfb3aed69d9486cc", - "transactionIndex": "0x7f", - "logIndex": "0x640", - "removed": false - }, - { - "address": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "topics": [ - "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x209f9de05c2399a0abd737a44aa0ec55bf2221c7dfedbfe61724b0a831c8f0c8", - "blockNumber": "0x11842d9", - "transactionHash": "0x34e5f1585a2404da7aa6108fbef8d63a4e9d5b077b17b791dfb3aed69d9486cc", - "transactionIndex": "0x7f", - "logIndex": "0x641", - "removed": false - }, - { - "address": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000003", - "blockHash": "0x209f9de05c2399a0abd737a44aa0ec55bf2221c7dfedbfe61724b0a831c8f0c8", - "blockNumber": "0x11842d9", - "transactionHash": "0x34e5f1585a2404da7aa6108fbef8d63a4e9d5b077b17b791dfb3aed69d9486cc", - "transactionIndex": "0x7f", - "logIndex": "0x642", - "removed": false - } - ], - "status": "0x1", - "logsBloom": "0x00000000000010000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000008000001000000040000000000000000000000000000000000000001000000040000000000000000000000000000020000000000000000000800000000000000000000000800000000400000000000000000000004040000000000000000001080000000000000000000000000000001000000000080000400000000000000000000000000000000000000000400000000000000000000040000000000000000000000000000000060000000000000000000000000000000000080000000000000000000008000000000", - "type": "0x2", - "effectiveGasPrice": "0x200dd2d8d" - }, - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 29536, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 29539, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 29964, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 29408, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 29528, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_array(t_uint256)50_storage": { - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x34e5f1585a2404da7aa6108fbef8d63a4e9d5b077b17b791dfb3aed69d9486cc", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "RECOMMENDED_SLOT()": { - "notice": "Storage slot that the recommended protocol version is stored at." - }, - "REQUIRED_SLOT()": { - "notice": "Storage slot that the required protocol version is stored at." - }, - "VERSION()": { - "notice": "Version identifier, used for upgrades." - }, - "constructor": { - "notice": "Constructs the ProtocolVersion contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)` A zero version is considered empty and is ignored by nodes." - }, - "initialize(address,uint256,uint256)": { - "notice": "Initializer." - }, - "recommended()": { - "notice": "High level getter for the recommended protocol version." - }, - "required()": { - "notice": "High level getter for the required protocol version." - }, - "setRecommended(uint256)": { - "notice": "Updates the recommended protocol version. Can only be called by the owner." - }, - "setRequired(uint256)": { - "notice": "Updates the required protocol version. Can only be called by the owner." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "ConfigUpdate(uint256,uint8,bytes)": { - "notice": "Emitted when configuration is updated." - } - }, - "notice": "The ProtocolVersions contract is used to manage superchain protocol version information." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/ProxyAdmin.json b/packages/contracts-bedrock/deployments/mainnet/ProxyAdmin.json deleted file mode 100644 index 75bbae585653..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/ProxyAdmin.json +++ /dev/null @@ -1,576 +0,0 @@ -{ - "address": "0x543bA4AADBAb8f9025686Bd03993043599c6fB04", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "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": "addressManager", - "outputs": [ - { - "internalType": "contract AddressManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_proxy", - "type": "address" - }, - { - "internalType": "address", - "name": "_newAdmin", - "type": "address" - } - ], - "name": "changeProxyAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_proxy", - "type": "address" - } - ], - "name": "getProxyAdmin", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_proxy", - "type": "address" - } - ], - "name": "getProxyImplementation", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "implementationName", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "isUpgrading", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "proxyType", - "outputs": [ - { - "internalType": "enum ProxyAdmin.ProxyType", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "address", - "name": "_address", - "type": "address" - } - ], - "name": "setAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract AddressManager", - "name": "_address", - "type": "address" - } - ], - "name": "setAddressManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_address", - "type": "address" - }, - { - "internalType": "string", - "name": "_name", - "type": "string" - } - ], - "name": "setImplementationName", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_address", - "type": "address" - }, - { - "internalType": "enum ProxyAdmin.ProxyType", - "name": "_type", - "type": "uint8" - } - ], - "name": "setProxyType", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_upgrading", - "type": "bool" - } - ], - "name": "setUpgrading", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_proxy", - "type": "address" - }, - { - "internalType": "address", - "name": "_implementation", - "type": "address" - } - ], - "name": "upgrade", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_proxy", - "type": "address" - }, - { - "internalType": "address", - "name": "_implementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "upgradeAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } - ], - "transactionHash": "0x1c5704eb14508af3d2ef1690aae89f3410a891af903103ab344bd789402f97bf", - "receipt": { - "to": null, - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "contractAddress": "0x543bA4AADBAb8f9025686Bd03993043599c6fB04", - "transactionIndex": 74, - "gasUsed": "1483961", - "logsBloom": "0x00000800000000000000000000000000000000000000000000800000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000020000000000000080000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x5767112801dab6286e5971d21c61a4861a61fe193604f117bef04a32144cd230", - "transactionHash": "0x1c5704eb14508af3d2ef1690aae89f3410a891af903103ab344bd789402f97bf", - "logs": [ - { - "transactionIndex": 74, - "blockNumber": 17365800, - "transactionHash": "0x1c5704eb14508af3d2ef1690aae89f3410a891af903103ab344bd789402f97bf", - "address": "0x543bA4AADBAb8f9025686Bd03993043599c6fB04", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000354f3f4ecdca5e0a7ace08d71348cdc1dab48960" - ], - "data": "0x", - "logIndex": 207, - "blockHash": "0x5767112801dab6286e5971d21c61a4861a61fe193604f117bef04a32144cd230" - }, - { - "transactionIndex": 74, - "blockNumber": 17365800, - "transactionHash": "0x1c5704eb14508af3d2ef1690aae89f3410a891af903103ab344bd789402f97bf", - "address": "0x543bA4AADBAb8f9025686Bd03993043599c6fB04", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x000000000000000000000000354f3f4ecdca5e0a7ace08d71348cdc1dab48960", - "0x000000000000000000000000354f3f4ecdca5e0a7ace08d71348cdc1dab48960" - ], - "data": "0x", - "logIndex": 208, - "blockHash": "0x5767112801dab6286e5971d21c61a4861a61fe193604f117bef04a32144cd230" - } - ], - "blockNumber": 17365800, - "cumulativeGasUsed": "7925562", - "status": 1, - "byzantium": true - }, - "args": [ - "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960" - ], - "numDeployments": 1, - "solcInputHash": "13ac93d026822f719ad110af836d1582", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"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\":\"addressManager\",\"outputs\":[{\"internalType\":\"contract AddressManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_newAdmin\",\"type\":\"address\"}],\"name\":\"changeProxyAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"getProxyAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_proxy\",\"type\":\"address\"}],\"name\":\"getProxyImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"implementationName\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isUpgrading\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"proxyType\",\"outputs\":[{\"internalType\":\"enum ProxyAdmin.ProxyType\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract AddressManager\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setAddressManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"setImplementationName\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"enum ProxyAdmin.ProxyType\",\"name\":\"_type\",\"type\":\"uint8\"}],\"name\":\"setProxyType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_upgrading\",\"type\":\"bool\"}],\"name\":\"setUpgrading\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"upgrade\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"upgradeAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"changeProxyAdmin(address,address)\":{\"params\":{\"_newAdmin\":\"Address of the new proxy admin.\",\"_proxy\":\"Address of the proxy to update.\"}},\"constructor\":{\"params\":{\"_owner\":\"Address of the initial owner of this contract.\"}},\"getProxyAdmin(address)\":{\"params\":{\"_proxy\":\"Address of the proxy to get the admin of.\"},\"returns\":{\"_0\":\"Address of the admin of the proxy.\"}},\"getProxyImplementation(address)\":{\"params\":{\"_proxy\":\"Address of the proxy to get the implementation of.\"},\"returns\":{\"_0\":\"Address of the implementation of the proxy.\"}},\"isUpgrading()\":{\"custom:legacy\":\"@notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening.\",\"returns\":{\"_0\":\"Whether or not there is an upgrade going on. May not actually tell you whether an upgrade is going on, since we don't currently plan to use this variable for anything other than a legacy indicator to fix a UX bug in the ChugSplash proxy.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAddress(string,address)\":{\"custom:legacy\":\"@notice Set an address in the address manager. Since only the owner of the AddressManager can directly modify addresses and the ProxyAdmin will own the AddressManager, this gives the owner of the ProxyAdmin the ability to modify addresses directly.\",\"params\":{\"_address\":\"Address to attach to the given name.\",\"_name\":\"Name to set within the AddressManager.\"}},\"setAddressManager(address)\":{\"params\":{\"_address\":\"Address of the AddressManager.\"}},\"setImplementationName(address,string)\":{\"params\":{\"_address\":\"Address of the ResolvedDelegateProxy.\",\"_name\":\"Name of the implementation for the proxy.\"}},\"setProxyType(address,uint8)\":{\"params\":{\"_address\":\"Address of the proxy.\",\"_type\":\"Type of the proxy.\"}},\"setUpgrading(bool)\":{\"custom:legacy\":\"@notice Set the upgrading status for the Chugsplash proxy type.\",\"params\":{\"_upgrading\":\"Whether or not the system is upgrading.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgrade(address,address)\":{\"params\":{\"_implementation\":\"Address of the new implementation address.\",\"_proxy\":\"Address of the proxy to upgrade.\"}},\"upgradeAndCall(address,address,bytes)\":{\"params\":{\"_data\":\"Data to trigger the new implementation with.\",\"_implementation\":\"Address of the new implementation address.\",\"_proxy\":\"Address of the proxy to upgrade.\"}}},\"title\":\"ProxyAdmin\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addressManager()\":{\"notice\":\"The address of the address manager, this is required to manage the ResolvedDelegateProxy type.\"},\"changeProxyAdmin(address,address)\":{\"notice\":\"Updates the admin of the given proxy address.\"},\"getProxyAdmin(address)\":{\"notice\":\"Returns the admin of the given proxy address.\"},\"getProxyImplementation(address)\":{\"notice\":\"Returns the implementation of the given proxy address.\"},\"implementationName(address)\":{\"notice\":\"A reverse mapping of addresses to names held in the AddressManager. This must be manually kept up to date with changes in the AddressManager for this contract to be able to work as an admin for the ResolvedDelegateProxy type.\"},\"proxyType(address)\":{\"notice\":\"A mapping of proxy types, used for backwards compatibility.\"},\"setAddressManager(address)\":{\"notice\":\"Set the address of the AddressManager. This is required to manage legacy ResolvedDelegateProxy type proxy contracts.\"},\"setImplementationName(address,string)\":{\"notice\":\"Sets the implementation name for a given address. Only required for ResolvedDelegateProxy type proxies that have an implementation name.\"},\"setProxyType(address,uint8)\":{\"notice\":\"Sets the proxy type for a given address. Only required for non-standard (legacy) proxy types.\"},\"upgrade(address,address)\":{\"notice\":\"Changes a proxy's implementation contract.\"},\"upgradeAndCall(address,address,bytes)\":{\"notice\":\"Changes a proxy's implementation contract and delegatecalls the new implementation with some given data. Useful for atomic upgrade-and-initialize calls.\"}},\"notice\":\"This is an auxiliary contract meant to be assigned as the admin of an ERC1967 Proxy, based on the OpenZeppelin implementation. It has backwards compatibility logic to work with the various types of proxies that have been deployed by Optimism in the past.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/ProxyAdmin.sol\":\"ProxyAdmin\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@cwia/=node_modules/clones-with-immutable-args/src/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":clones-with-immutable-args/=node_modules/clones-with-immutable-args/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/legacy/AddressManager.sol\":{\"keccak256\":\"0x7a353d4c92eed32665fd2f0023c55054901293cf7a6e14ca108229d87c047b10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b92ba23601d1951271729a20db931a45639d9376b7c8e2705c23dc360833715a\",\"dweb:/ipfs/QmTKwYLNYYBKZpd31VNBANmguVUwFZifSg7joHSgLZjZCj\"]},\"contracts/legacy/L1ChugSplashProxy.sol\":{\"keccak256\":\"0x6ae7bf6ea9ac0e3511ee4cb15d946589da0dd35098ff762c0b2903d064f24875\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://02028d86c1d38563021d5ead5282271ccdf1c03a24f2eaee056ae2157f0554ee\",\"dweb:/ipfs/QmW9urkBBRTmZ8FjL5Y5zWbdnRhPDruxCCLnpr2CTkozKM\"]},\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0x64d67f1936d97c87a2e42317eb162744ad5cefdc9bc8b1138ee4afe2886eb885\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://33b903585eb9cfc60a70bcdf4ee44220b173caff16dfb9071cd0668c7a551265\",\"dweb:/ipfs/QmXHUZ9brinN1WS9i63ocRQsQidY96WePDBhBsFRhDmVjr\"]},\"contracts/universal/ProxyAdmin.sol\":{\"keccak256\":\"0x7326011ac425cc9ab4760c29ca559342d4832633b5019a9a61b9e63067374e2a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7d3541272c48443f0b339998553e44600b7bcb4f949e5c94acb5a3acfce19399\",\"dweb:/ipfs/QmNSd9jxACWg8bZE8EgxmRdXwLUQixVs4oiugrVegapUe4\"]},\"node_modules/@openzeppelin/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162001a5f38038062001a5f8339810160408190526200003491620000a1565b6200003f3362000051565b6200004a8162000051565b50620000d3565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215620000b457600080fd5b81516001600160a01b0381168114620000cc57600080fd5b9392505050565b61197c80620000e36000396000f3fe60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a", - "deployedBytecode": "0x60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "changeProxyAdmin(address,address)": { - "params": { - "_newAdmin": "Address of the new proxy admin.", - "_proxy": "Address of the proxy to update." - } - }, - "constructor": { - "params": { - "_owner": "Address of the initial owner of this contract." - } - }, - "getProxyAdmin(address)": { - "params": { - "_proxy": "Address of the proxy to get the admin of." - }, - "returns": { - "_0": "Address of the admin of the proxy." - } - }, - "getProxyImplementation(address)": { - "params": { - "_proxy": "Address of the proxy to get the implementation of." - }, - "returns": { - "_0": "Address of the implementation of the proxy." - } - }, - "isUpgrading()": { - "returns": { - "_0": "Whether or not there is an upgrade going on. May not actually tell you whether an upgrade is going on, since we don't currently plan to use this variable for anything other than a legacy indicator to fix a UX bug in the ChugSplash proxy." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "setAddress(string,address)": { - "params": { - "_address": "Address to attach to the given name.", - "_name": "Name to set within the AddressManager." - } - }, - "setAddressManager(address)": { - "params": { - "_address": "Address of the AddressManager." - } - }, - "setImplementationName(address,string)": { - "params": { - "_address": "Address of the ResolvedDelegateProxy.", - "_name": "Name of the implementation for the proxy." - } - }, - "setProxyType(address,uint8)": { - "params": { - "_address": "Address of the proxy.", - "_type": "Type of the proxy." - } - }, - "setUpgrading(bool)": { - "params": { - "_upgrading": "Whether or not the system is upgrading." - } - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - }, - "upgrade(address,address)": { - "params": { - "_implementation": "Address of the new implementation address.", - "_proxy": "Address of the proxy to upgrade." - } - }, - "upgradeAndCall(address,address,bytes)": { - "params": { - "_data": "Data to trigger the new implementation with.", - "_implementation": "Address of the new implementation address.", - "_proxy": "Address of the proxy to upgrade." - } - } - }, - "title": "ProxyAdmin" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "addressManager()": { - "notice": "The address of the address manager, this is required to manage the ResolvedDelegateProxy type." - }, - "changeProxyAdmin(address,address)": { - "notice": "Updates the admin of the given proxy address." - }, - "getProxyAdmin(address)": { - "notice": "Returns the admin of the given proxy address." - }, - "getProxyImplementation(address)": { - "notice": "Returns the implementation of the given proxy address." - }, - "implementationName(address)": { - "notice": "A reverse mapping of addresses to names held in the AddressManager. This must be manually kept up to date with changes in the AddressManager for this contract to be able to work as an admin for the ResolvedDelegateProxy type." - }, - "proxyType(address)": { - "notice": "A mapping of proxy types, used for backwards compatibility." - }, - "setAddressManager(address)": { - "notice": "Set the address of the AddressManager. This is required to manage legacy ResolvedDelegateProxy type proxy contracts." - }, - "setImplementationName(address,string)": { - "notice": "Sets the implementation name for a given address. Only required for ResolvedDelegateProxy type proxies that have an implementation name." - }, - "setProxyType(address,uint8)": { - "notice": "Sets the proxy type for a given address. Only required for non-standard (legacy) proxy types." - }, - "upgrade(address,address)": { - "notice": "Changes a proxy's implementation contract." - }, - "upgradeAndCall(address,address,bytes)": { - "notice": "Changes a proxy's implementation contract and delegatecalls the new implementation with some given data. Useful for atomic upgrade-and-initialize calls." - } - }, - "notice": "This is an auxiliary contract meant to be assigned as the admin of an ERC1967 Proxy, based on the OpenZeppelin implementation. It has backwards compatibility logic to work with the various types of proxies that have been deployed by Optimism in the past." - }, - "storageLayout": { - "storage": [ - { - "astId": 53108, - "contract": "contracts/universal/ProxyAdmin.sol:ProxyAdmin", - "label": "_owner", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 51261, - "contract": "contracts/universal/ProxyAdmin.sol:ProxyAdmin", - "label": "proxyType", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_address,t_enum(ProxyType)51255)" - }, - { - "astId": 51266, - "contract": "contracts/universal/ProxyAdmin.sol:ProxyAdmin", - "label": "implementationName", - "offset": 0, - "slot": "2", - "type": "t_mapping(t_address,t_string_storage)" - }, - { - "astId": 51270, - "contract": "contracts/universal/ProxyAdmin.sol:ProxyAdmin", - "label": "addressManager", - "offset": 0, - "slot": "3", - "type": "t_contract(AddressManager)7678" - }, - { - "astId": 51273, - "contract": "contracts/universal/ProxyAdmin.sol:ProxyAdmin", - "label": "upgrading", - "offset": 20, - "slot": "3", - "type": "t_bool" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(AddressManager)7678": { - "encoding": "inplace", - "label": "contract AddressManager", - "numberOfBytes": "20" - }, - "t_enum(ProxyType)51255": { - "encoding": "inplace", - "label": "enum ProxyAdmin.ProxyType", - "numberOfBytes": "1" - }, - "t_mapping(t_address,t_enum(ProxyType)51255)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => enum ProxyAdmin.ProxyType)", - "numberOfBytes": "32", - "value": "t_enum(ProxyType)51255" - }, - "t_mapping(t_address,t_string_storage)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => string)", - "numberOfBytes": "32", - "value": "t_string_storage" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/SystemConfig.json b/packages/contracts-bedrock/deployments/mainnet/SystemConfig.json deleted file mode 100644 index 3f42750565ea..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/SystemConfig.json +++ /dev/null @@ -1,1078 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "version", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "enum SystemConfig.UpdateType", - "name": "updateType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "ConfigUpdate", - "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": "BATCH_INBOX_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L1_CROSS_DOMAIN_MESSENGER_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L1_ERC_721_BRIDGE_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L1_STANDARD_BRIDGE_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L2_OUTPUT_ORACLE_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMISM_PORTAL_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UNSAFE_BLOCK_SIGNER_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "batchInbox", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "batcherHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasLimit", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_overhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_scalar", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_batcherHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "_gasLimit", - "type": "uint64" - }, - { - "internalType": "address", - "name": "_unsafeBlockSigner", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "maxResourceLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "elasticityMultiplier", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "baseFeeMaxChangeDenominator", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "minimumBaseFee", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "systemTxMaxGas", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "maximumBaseFee", - "type": "uint128" - } - ], - "internalType": "struct ResourceMetering.ResourceConfig", - "name": "_config", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "_startBlock", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_batchInbox", - "type": "address" - }, - { - "components": [ - { - "internalType": "address", - "name": "l1CrossDomainMessenger", - "type": "address" - }, - { - "internalType": "address", - "name": "l1ERC721Bridge", - "type": "address" - }, - { - "internalType": "address", - "name": "l1StandardBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "l2OutputOracle", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismPortal", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismMintableERC20Factory", - "type": "address" - } - ], - "internalType": "struct SystemConfig.Addresses", - "name": "_addresses", - "type": "tuple" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1CrossDomainMessenger", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1ERC721Bridge", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1StandardBridge", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l2OutputOracle", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minimumGasLimit", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "optimismMintableERC20Factory", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "optimismPortal", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "overhead", - "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": [], - "name": "resourceConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "maxResourceLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "elasticityMultiplier", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "baseFeeMaxChangeDenominator", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "minimumBaseFee", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "systemTxMaxGas", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "maximumBaseFee", - "type": "uint128" - } - ], - "internalType": "struct ResourceMetering.ResourceConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "scalar", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_batcherHash", - "type": "bytes32" - } - ], - "name": "setBatcherHash", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_overhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_scalar", - "type": "uint256" - } - ], - "name": "setGasConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_gasLimit", - "type": "uint64" - } - ], - "name": "setGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "maxResourceLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "elasticityMultiplier", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "baseFeeMaxChangeDenominator", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "minimumBaseFee", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "systemTxMaxGas", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "maximumBaseFee", - "type": "uint128" - } - ], - "internalType": "struct ResourceMetering.ResourceConfig", - "name": "_config", - "type": "tuple" - } - ], - "name": "setResourceConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_unsafeBlockSigner", - "type": "address" - } - ], - "name": "setUnsafeBlockSigner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "startBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unsafeBlockSigner", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "address": "0x3b6090d4ba84B94C20a789436B9010F340AaaC70", - "args": [], - "bytecode": "0x60806040523480156200001157600080fd5b506040805160c080820183526001808352602080840182905260028486015260006060808601829052608080870183905260a08088018490528851968701895283875293860183905296850182905284018190529483018590528201849052620000909361dead93909283928392909183919060001990839062000096565b62000ccc565b600054600390610100900460ff16158015620000b9575060005460ff8083169116105b620001225760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805461ffff191660ff831617610100179055620001406200043a565b6200014b8b620004a2565b620001568862000521565b620001628a8a62000573565b6200016d87620005d7565b620001788662000674565b620001be620001a960017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59862000ba9565b60001b84620006dc60201b62000d211760201c565b62000208620001ef60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063762000ba9565b60001b8360000151620006dc60201b62000d211760201c565b620002526200023960017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a862000ba9565b60001b8360200151620006dc60201b62000d211760201c565b6200029c6200028360017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637762000ba9565b60001b8360400151620006dc60201b62000d211760201c565b620002e6620002cd60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a687181662000ba9565b60001b8360600151620006dc60201b62000d211760201c565b620003306200031760017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad62000ba9565b60001b8360800151620006dc60201b62000d211760201c565b6200037a6200036160017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d62000ba9565b60001b8360a00151620006dc60201b62000d211760201c565b6200038584620006e0565b62000390856200070d565b6200039a62000a51565b6001600160401b0316876001600160401b03161015620003ec5760405162461bcd60e51b815260206004820152601f60248201526000805160206200281f833981519152604482015260640162000119565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050505050565b600054610100900460ff16620004965760405162461bcd60e51b815260206004820152602b60248201526000805160206200285f83398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000119565b620004a062000a7e565b565b620004ac62000ae5565b6001600160a01b038116620005135760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000119565b6200051e8162000b41565b50565b60678190556040805160208082018490528251808303909101815290820190915260005b60006000805160206200283f8339815191528360405162000567919062000bc3565b60405180910390a35050565b60658290556066819055604080516020810184905290810182905260009060600160408051601f198184030181529190529050600160006000805160206200283f83398151915283604051620005ca919062000bc3565b60405180910390a3505050565b620005e162000a51565b6001600160401b0316816001600160401b03161015620006335760405162461bcd60e51b815260206004820152601f60248201526000805160206200281f833981519152604482015260640162000119565b606880546001600160401b0319166001600160401b038316908117909155604080516020808201939093528151808203909301835281019052600262000545565b620006ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0882620006dc60201b62000d211760201c565b604080516001600160a01b03831660208201526000910160408051601f198184030181529190529050600362000545565b9055565b8015801590620006f05750606a54155b15620006fb57606a55565b606a546000036200051e5743606a5550565b8060a001516001600160801b0316816060015163ffffffff1611156200079c5760405162461bcd60e51b815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d617820626173650000000000000000000000606482015260840162000119565b6001816040015160ff16116200080d5760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201526e65206c6172676572207468616e203160881b606482015260840162000119565b606854608082015182516001600160401b03909216916200082f919062000c1b565b63ffffffff161115620008745760405162461bcd60e51b815260206004820152601f60248201526000805160206200281f833981519152604482015260640162000119565b6000816020015160ff1611620008e55760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201526e06965722063616e6e6f74206265203608c1b606482015260840162000119565b8051602082015163ffffffff82169160ff909116906200090790829062000c46565b62000913919062000c78565b63ffffffff16146200098e5760405162461bcd60e51b815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d6974000000000000000000606482015260840162000119565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff96871664ffffffffff199095169490941764010000000060ff948516021764ffffffffff60281b191665010000000000939092169290920263ffffffff60301b19161766010000000000009185169190910217600160501b600160f01b0319166a01000000000000000000009390941692909202600160701b600160f01b03191692909217600160701b6001600160801b0390921691909102179055565b60695460009062000a799063ffffffff6a010000000000000000000082048116911662000ca7565b905090565b600054610100900460ff1662000ada5760405162461bcd60e51b815260206004820152602b60248201526000805160206200285f83398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000119565b620004a03362000b41565b6033546001600160a01b03163314620004a05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000119565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052601160045260246000fd5b60008282101562000bbe5762000bbe62000b93565b500390565b600060208083528351808285015260005b8181101562000bf25785810183015185820160400152820162000bd4565b8181111562000c05576000604083870101525b50601f01601f1916929092016040019392505050565b600063ffffffff80831681851680830382111562000c3d5762000c3d62000b93565b01949350505050565b600063ffffffff8084168062000c6c57634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b600063ffffffff8083168185168183048111821515161562000c9e5762000c9e62000b93565b02949350505050565b60006001600160401b0382811684821680830382111562000c3d5762000c3d62000b93565b611b438062000cdc6000396000f3fe608060405234801561001057600080fd5b50600436106102265760003560e01c8063935f029e1161012a578063cc731b02116100bd578063f45e65d81161008c578063f8c68de011610071578063f8c68de014610575578063fd32aa0f1461057d578063ffa1ad741461058557600080fd5b8063f45e65d814610558578063f68016b71461056157600080fd5b8063cc731b0214610400578063dac6e63a14610534578063e81b2c6d1461053c578063f2fde38b1461054557600080fd5b8063bc49ce5f116100f9578063bc49ce5f146103ca578063c4e8ddfa146103d2578063c71973f6146103da578063c9b26f61146103ed57600080fd5b8063935f029e146103945780639b7d7f0a146103a7578063a7119869146103af578063b40a817c146103b757600080fd5b80634add321d116101bd57806354fd4d501161018c57806361d157681161017157806361d1576814610366578063715018a61461036e5780638da5cb5b1461037657600080fd5b806354fd4d50146103155780635d73369c1461035e57600080fd5b80634add321d146102b25780634d9f1559146102d35780634f16540b146102db5780635228a6ac1461030257600080fd5b806318d13918116101f957806318d139181461028457806319f5cea8146102995780631fd19ee1146102a157806348cd4cb1146102a957600080fd5b806306c926571461022b578063078f29cf146102465780630a49cb03146102735780630c18c1621461027b575b600080fd5b61023361058d565b6040519081526020015b60405180910390f35b61024e6105bb565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161023d565b61024e6105f4565b61023360655481565b610297610292366004611677565b610624565b005b610233610638565b61024e610663565b610233606a5481565b6102ba61068d565b60405167ffffffffffffffff909116815260200161023d565b61024e6106b3565b6102337f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b610297610310366004611807565b6106e3565b6103516040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b60405161023d91906119aa565b610233610a79565b610233610aa4565b610297610acf565b60335473ffffffffffffffffffffffffffffffffffffffff1661024e565b6102976103a23660046119bd565b610ae3565b61024e610af9565b61024e610b29565b6102976103c53660046119df565b610b59565b610233610b6a565b61024e610b95565b6102976103e83660046119fa565b610bc5565b6102976103fb366004611a16565b610bd6565b6104c46040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b60405161023d9190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61024e610be7565b61023360675481565b610297610553366004611677565b610c17565b61023360665481565b6068546102ba9067ffffffffffffffff1681565b610233610ccb565b610233610cf6565b610233600081565b6105b860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611a5e565b81565b60006105ef6105eb60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611a5e565b5490565b905090565b60006105ef6105eb60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611a5e565b61062c610d25565b61063581610da6565b50565b6105b860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611a5e565b60006105ef7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b6069546000906105ef9063ffffffff6a0100000000000000000000820481169116611a75565b60006105ef6105eb60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611a5e565b600054600390610100900460ff16158015610705575060005460ff8083169116105b610796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff8316176101001790556107cf610e63565b6107d88b610c17565b6107e188610f02565b6107eb8a8a610f2a565b6107f487610fbb565b6107fd86610da6565b61083061082b60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611a5e565b849055565b61086461085e60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611a5e565b83519055565b61089b61089260017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611a5e565b60208401519055565b6108d26108c960017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611a5e565b60408401519055565b61090961090060017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611a5e565b60608401519055565b61094061093760017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611a5e565b60808401519055565b61097761096e60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611a5e565b60a08401519055565b61098084611099565b610989856110c3565b61099161068d565b67ffffffffffffffff168767ffffffffffffffff161015610a0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640161078d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050505050565b6105b860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611a5e565b6105b860017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611a5e565b610ad7610d25565b610ae16000611537565b565b610aeb610d25565b610af58282610f2a565b5050565b60006105ef6105eb60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611a5e565b60006105ef6105eb60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611a5e565b610b61610d25565b61063581610fbb565b6105b860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611a5e565b60006105ef6105eb60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611a5e565b610bcd610d25565b610635816110c3565b610bde610d25565b61063581610f02565b60006105ef6105eb60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611a5e565b610c1f610d25565b73ffffffffffffffffffffffffffffffffffffffff8116610cc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161078d565b61063581611537565b6105b860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611a5e565b6105b860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611a5e565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ae1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161078d565b610dcf7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610e5791906119aa565b60405180910390a35050565b600054610100900460ff16610efa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161078d565b610ae16115ae565b6067819055604080516020808201849052825180830390910181529082019091526000610e26565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610fae91906119aa565b60405180910390a3505050565b610fc361068d565b67ffffffffffffffff168167ffffffffffffffff161015611040576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640161078d565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610e26565b80158015906110a85750606a54155b156110b257606a55565b606a546000036106355743606a5550565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611173576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d617820626173650000000000000000000000606482015260840161078d565b6001816040015160ff161161120a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e20310000000000000000000000000000000000606482015260840161078d565b6068546080820151825167ffffffffffffffff9092169161122b9190611aa1565b63ffffffff161115611299576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640161078d565b6000816020015160ff1611611330576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f7420626520300000000000000000000000000000000000606482015260840161078d565b8051602082015163ffffffff82169160ff90911690611350908290611ac0565b61135a9190611b0a565b63ffffffff16146113ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d6974000000000000000000606482015260840161078d565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611645576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161078d565b610ae133611537565b803573ffffffffffffffffffffffffffffffffffffffff8116811461167257600080fd5b919050565b60006020828403121561168957600080fd5b6116928261164e565b9392505050565b803567ffffffffffffffff8116811461167257600080fd5b60405160c0810167ffffffffffffffff811182821017156116fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290565b803563ffffffff8116811461167257600080fd5b803560ff8116811461167257600080fd5b600060c0828403121561173857600080fd5b60405160c0810181811067ffffffffffffffff82111715611782577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290508061179183611701565b815261179f60208401611715565b60208201526117b060408401611715565b60408201526117c160608401611701565b60608201526117d260808401611701565b608082015260a08301356fffffffffffffffffffffffffffffffff811681146117fa57600080fd5b60a0919091015292915050565b6000806000806000806000806000808a8c0361028081121561182857600080fd5b6118318c61164e565b9a5060208c0135995060408c0135985060608c0135975061185460808d01611699565b965061186260a08d0161164e565b95506118718d60c08e01611726565b94506101808c013593506118886101a08d0161164e565b925060c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe40820112156118ba57600080fd5b506118c36116b1565b6118d06101c08d0161164e565b81526118df6101e08d0161164e565b60208201526118f16102008d0161164e565b60408201526119036102208d0161164e565b60608201526119156102408d0161164e565b60808201526119276102608d0161164e565b60a0820152809150509295989b9194979a5092959850565b6000815180845260005b8181101561196557602081850181015186830182015201611949565b81811115611977576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611692602083018461193f565b600080604083850312156119d057600080fd5b50508035926020909101359150565b6000602082840312156119f157600080fd5b61169282611699565b600060c08284031215611a0c57600080fd5b6116928383611726565b600060208284031215611a2857600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611a7057611a70611a2f565b500390565b600067ffffffffffffffff808316818516808303821115611a9857611a98611a2f565b01949350505050565b600063ffffffff808316818516808303821115611a9857611a98611a2f565b600063ffffffff80841680611afe577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff80831681851681830481118215151615611b2d57611b2d611a2f565b0294935050505056fea164736f6c634300080f000a53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77001d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102265760003560e01c8063935f029e1161012a578063cc731b02116100bd578063f45e65d81161008c578063f8c68de011610071578063f8c68de014610575578063fd32aa0f1461057d578063ffa1ad741461058557600080fd5b8063f45e65d814610558578063f68016b71461056157600080fd5b8063cc731b0214610400578063dac6e63a14610534578063e81b2c6d1461053c578063f2fde38b1461054557600080fd5b8063bc49ce5f116100f9578063bc49ce5f146103ca578063c4e8ddfa146103d2578063c71973f6146103da578063c9b26f61146103ed57600080fd5b8063935f029e146103945780639b7d7f0a146103a7578063a7119869146103af578063b40a817c146103b757600080fd5b80634add321d116101bd57806354fd4d501161018c57806361d157681161017157806361d1576814610366578063715018a61461036e5780638da5cb5b1461037657600080fd5b806354fd4d50146103155780635d73369c1461035e57600080fd5b80634add321d146102b25780634d9f1559146102d35780634f16540b146102db5780635228a6ac1461030257600080fd5b806318d13918116101f957806318d139181461028457806319f5cea8146102995780631fd19ee1146102a157806348cd4cb1146102a957600080fd5b806306c926571461022b578063078f29cf146102465780630a49cb03146102735780630c18c1621461027b575b600080fd5b61023361058d565b6040519081526020015b60405180910390f35b61024e6105bb565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161023d565b61024e6105f4565b61023360655481565b610297610292366004611677565b610624565b005b610233610638565b61024e610663565b610233606a5481565b6102ba61068d565b60405167ffffffffffffffff909116815260200161023d565b61024e6106b3565b6102337f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b610297610310366004611807565b6106e3565b6103516040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b60405161023d91906119aa565b610233610a79565b610233610aa4565b610297610acf565b60335473ffffffffffffffffffffffffffffffffffffffff1661024e565b6102976103a23660046119bd565b610ae3565b61024e610af9565b61024e610b29565b6102976103c53660046119df565b610b59565b610233610b6a565b61024e610b95565b6102976103e83660046119fa565b610bc5565b6102976103fb366004611a16565b610bd6565b6104c46040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b60405161023d9190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61024e610be7565b61023360675481565b610297610553366004611677565b610c17565b61023360665481565b6068546102ba9067ffffffffffffffff1681565b610233610ccb565b610233610cf6565b610233600081565b6105b860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611a5e565b81565b60006105ef6105eb60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611a5e565b5490565b905090565b60006105ef6105eb60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611a5e565b61062c610d25565b61063581610da6565b50565b6105b860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611a5e565b60006105ef7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b6069546000906105ef9063ffffffff6a0100000000000000000000820481169116611a75565b60006105ef6105eb60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611a5e565b600054600390610100900460ff16158015610705575060005460ff8083169116105b610796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff8316176101001790556107cf610e63565b6107d88b610c17565b6107e188610f02565b6107eb8a8a610f2a565b6107f487610fbb565b6107fd86610da6565b61083061082b60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611a5e565b849055565b61086461085e60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611a5e565b83519055565b61089b61089260017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611a5e565b60208401519055565b6108d26108c960017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611a5e565b60408401519055565b61090961090060017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611a5e565b60608401519055565b61094061093760017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611a5e565b60808401519055565b61097761096e60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611a5e565b60a08401519055565b61098084611099565b610989856110c3565b61099161068d565b67ffffffffffffffff168767ffffffffffffffff161015610a0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640161078d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050505050565b6105b860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611a5e565b6105b860017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611a5e565b610ad7610d25565b610ae16000611537565b565b610aeb610d25565b610af58282610f2a565b5050565b60006105ef6105eb60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611a5e565b60006105ef6105eb60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611a5e565b610b61610d25565b61063581610fbb565b6105b860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611a5e565b60006105ef6105eb60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611a5e565b610bcd610d25565b610635816110c3565b610bde610d25565b61063581610f02565b60006105ef6105eb60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611a5e565b610c1f610d25565b73ffffffffffffffffffffffffffffffffffffffff8116610cc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161078d565b61063581611537565b6105b860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611a5e565b6105b860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611a5e565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ae1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161078d565b610dcf7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610e5791906119aa565b60405180910390a35050565b600054610100900460ff16610efa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161078d565b610ae16115ae565b6067819055604080516020808201849052825180830390910181529082019091526000610e26565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610fae91906119aa565b60405180910390a3505050565b610fc361068d565b67ffffffffffffffff168167ffffffffffffffff161015611040576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640161078d565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610e26565b80158015906110a85750606a54155b156110b257606a55565b606a546000036106355743606a5550565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611173576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d617820626173650000000000000000000000606482015260840161078d565b6001816040015160ff161161120a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e20310000000000000000000000000000000000606482015260840161078d565b6068546080820151825167ffffffffffffffff9092169161122b9190611aa1565b63ffffffff161115611299576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f7700604482015260640161078d565b6000816020015160ff1611611330576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f7420626520300000000000000000000000000000000000606482015260840161078d565b8051602082015163ffffffff82169160ff90911690611350908290611ac0565b61135a9190611b0a565b63ffffffff16146113ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d6974000000000000000000606482015260840161078d565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611645576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161078d565b610ae133611537565b803573ffffffffffffffffffffffffffffffffffffffff8116811461167257600080fd5b919050565b60006020828403121561168957600080fd5b6116928261164e565b9392505050565b803567ffffffffffffffff8116811461167257600080fd5b60405160c0810167ffffffffffffffff811182821017156116fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290565b803563ffffffff8116811461167257600080fd5b803560ff8116811461167257600080fd5b600060c0828403121561173857600080fd5b60405160c0810181811067ffffffffffffffff82111715611782577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290508061179183611701565b815261179f60208401611715565b60208201526117b060408401611715565b60408201526117c160608401611701565b60608201526117d260808401611701565b608082015260a08301356fffffffffffffffffffffffffffffffff811681146117fa57600080fd5b60a0919091015292915050565b6000806000806000806000806000808a8c0361028081121561182857600080fd5b6118318c61164e565b9a5060208c0135995060408c0135985060608c0135975061185460808d01611699565b965061186260a08d0161164e565b95506118718d60c08e01611726565b94506101808c013593506118886101a08d0161164e565b925060c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe40820112156118ba57600080fd5b506118c36116b1565b6118d06101c08d0161164e565b81526118df6101e08d0161164e565b60208201526118f16102008d0161164e565b60408201526119036102208d0161164e565b60608201526119156102408d0161164e565b60808201526119276102608d0161164e565b60a0820152809150509295989b9194979a5092959850565b6000815180845260005b8181101561196557602081850181015186830182015201611949565b81811115611977576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611692602083018461193f565b600080604083850312156119d057600080fd5b50508035926020909101359150565b6000602082840312156119f157600080fd5b61169282611699565b600060c08284031215611a0c57600080fd5b6116928383611726565b600060208284031215611a2857600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611a7057611a70611a2f565b500390565b600067ffffffffffffffff808316818516808303821115611a9857611a98611a2f565b01949350505050565b600063ffffffff808316818516808303821115611a9857611a98611a2f565b600063ffffffff80841680611afe577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff80831681851681830481118215151615611b2d57611b2d611a2f565b0294935050505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128),uint256,address,(address,address,address,address,address,address))": { - "params": { - "_addresses": "Set of L1 contract addresses. These should be the proxies.", - "_batchInbox": "Batch inbox address. An identifier for the op-node to find canonical data.", - "_batcherHash": "Initial batcher hash.", - "_config": "Initial ResourceConfig.", - "_gasLimit": "Initial gas limit.", - "_overhead": "Initial overhead value.", - "_owner": "Initial owner of the contract.", - "_scalar": "Initial scalar value.", - "_startBlock": "Starting block for the op-node to search for logs from. Contracts that were deployed before this field existed need to have this field set manually via an override. Newly deployed contracts should set this value to uint256(0).", - "_unsafeBlockSigner": "Initial unsafe block signer address." - } - }, - "minimumGasLimit()": { - "returns": { - "_0": "uint64 Minimum gas limit." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "resourceConfig()": { - "returns": { - "_0": "ResourceConfig" - } - }, - "setBatcherHash(bytes32)": { - "params": { - "_batcherHash": "New batcher hash." - } - }, - "setGasConfig(uint256,uint256)": { - "params": { - "_overhead": "New overhead value.", - "_scalar": "New scalar value." - } - }, - "setGasLimit(uint64)": { - "params": { - "_gasLimit": "New gas limit." - } - }, - "setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))": { - "params": { - "_config": "The new resource config values." - } - }, - "setUnsafeBlockSigner(address)": { - "params": { - "_unsafeBlockSigner": "New unsafe block signer address." - } - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - }, - "unsafeBlockSigner()": { - "returns": { - "addr_": "Address of the unsafe block signer." - } - } - }, - "events": { - "ConfigUpdate(uint256,uint8,bytes)": { - "params": { - "data": "Encoded update data.", - "updateType": "Type of update.", - "version": "SystemConfig version." - } - } - }, - "title": "SystemConfig" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"enum SystemConfig.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ConfigUpdate\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"BATCH_INBOX_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L1_CROSS_DOMAIN_MESSENGER_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L1_ERC_721_BRIDGE_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L1_STANDARD_BRIDGE_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L2_OUTPUT_ORACLE_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OPTIMISM_PORTAL_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"UNSAFE_BLOCK_SIGNER_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"batchInbox\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"batcherHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"gasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"},{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]},{\"internalType\":\"uint256\",\"name\":\"_startBlock\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_batchInbox\",\"type\":\"address\"},{\"internalType\":\"struct SystemConfig.Addresses\",\"name\":\"_addresses\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"address\",\"name\":\"l1CrossDomainMessenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1ERC721Bridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1StandardBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l2OutputOracle\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"optimismPortal\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"optimismMintableERC20Factory\",\"type\":\"address\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l1CrossDomainMessenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l1ERC721Bridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l1StandardBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2OutputOracle\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"minimumGasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"optimismMintableERC20Factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"optimismPortal\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"overhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"resourceConfig\",\"outputs\":[{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"scalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setBatcherHash\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_scalar\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setGasConfig\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setGasLimit\"},{\"inputs\":[{\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"_config\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setResourceConfig\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_unsafeBlockSigner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setUnsafeBlockSigner\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"startBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"unsafeBlockSigner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128),uint256,address,(address,address,address,address,address,address))\":{\"params\":{\"_addresses\":\"Set of L1 contract addresses. These should be the proxies.\",\"_batchInbox\":\"Batch inbox address. An identifier for the op-node to find canonical data.\",\"_batcherHash\":\"Initial batcher hash.\",\"_config\":\"Initial ResourceConfig.\",\"_gasLimit\":\"Initial gas limit.\",\"_overhead\":\"Initial overhead value.\",\"_owner\":\"Initial owner of the contract.\",\"_scalar\":\"Initial scalar value.\",\"_startBlock\":\"Starting block for the op-node to search for logs from. Contracts that were deployed before this field existed need to have this field set manually via an override. Newly deployed contracts should set this value to uint256(0).\",\"_unsafeBlockSigner\":\"Initial unsafe block signer address.\"}},\"minimumGasLimit()\":{\"returns\":{\"_0\":\"uint64 Minimum gas limit.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"resourceConfig()\":{\"returns\":{\"_0\":\"ResourceConfig\"}},\"setBatcherHash(bytes32)\":{\"params\":{\"_batcherHash\":\"New batcher hash.\"}},\"setGasConfig(uint256,uint256)\":{\"params\":{\"_overhead\":\"New overhead value.\",\"_scalar\":\"New scalar value.\"}},\"setGasLimit(uint64)\":{\"params\":{\"_gasLimit\":\"New gas limit.\"}},\"setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))\":{\"params\":{\"_config\":\"The new resource config values.\"}},\"setUnsafeBlockSigner(address)\":{\"params\":{\"_unsafeBlockSigner\":\"New unsafe block signer address.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsafeBlockSigner()\":{\"returns\":{\"addr_\":\"Address of the unsafe block signer.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"BATCH_INBOX_SLOT()\":{\"notice\":\"Storage slot that the batch inbox address is stored at.\"},\"L1_CROSS_DOMAIN_MESSENGER_SLOT()\":{\"notice\":\"Storage slot that the L1CrossDomainMessenger address is stored at.\"},\"L1_ERC_721_BRIDGE_SLOT()\":{\"notice\":\"Storage slot that the L1ERC721Bridge address is stored at.\"},\"L1_STANDARD_BRIDGE_SLOT()\":{\"notice\":\"Storage slot that the L1StandardBridge address is stored at.\"},\"L2_OUTPUT_ORACLE_SLOT()\":{\"notice\":\"Storage slot that the L2OutputOracle address is stored at.\"},\"OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT()\":{\"notice\":\"Storage slot that the OptimismMintableERC20Factory address is stored at.\"},\"OPTIMISM_PORTAL_SLOT()\":{\"notice\":\"Storage slot that the OptimismPortal address is stored at.\"},\"UNSAFE_BLOCK_SIGNER_SLOT()\":{\"notice\":\"Storage slot that the unsafe block signer is stored at. Storing it at this deterministic storage slot allows for decoupling the storage layout from the way that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value.\"},\"VERSION()\":{\"notice\":\"Version identifier, used for upgrades.\"},\"batchInbox()\":{\"notice\":\"Getter for the BatchInbox address.\"},\"batcherHash()\":{\"notice\":\"Identifier for the batcher. For version 1 of this configuration, this is represented as an address left-padded with zeros to 32 bytes.\"},\"constructor\":{\"notice\":\"Constructs the SystemConfig contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)`\"},\"gasLimit()\":{\"notice\":\"L2 block gas limit.\"},\"initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128),uint256,address,(address,address,address,address,address,address))\":{\"notice\":\"Initializer. The resource config must be set before the require check.\"},\"l1CrossDomainMessenger()\":{\"notice\":\"Getter for the L1CrossDomainMessenger address.\"},\"l1ERC721Bridge()\":{\"notice\":\"Getter for the L1ERC721Bridge address.\"},\"l1StandardBridge()\":{\"notice\":\"Getter for the L1StandardBridge address.\"},\"l2OutputOracle()\":{\"notice\":\"Getter for the L2OutputOracle address.\"},\"minimumGasLimit()\":{\"notice\":\"Returns the minimum L2 gas limit that can be safely set for the system to operate. The L2 gas limit must be larger than or equal to the amount of gas that is allocated for deposits per block plus the amount of gas that is allocated for the system transaction. This function is used to determine if changes to parameters are safe.\"},\"optimismMintableERC20Factory()\":{\"notice\":\"Getter for the OptimismMintableERC20Factory address.\"},\"optimismPortal()\":{\"notice\":\"Getter for the OptimismPortal address.\"},\"overhead()\":{\"notice\":\"Fixed L2 gas overhead. Used as part of the L2 fee calculation.\"},\"resourceConfig()\":{\"notice\":\"A getter for the resource config. Ensures that the struct is returned instead of a tuple.\"},\"scalar()\":{\"notice\":\"Dynamic L2 gas overhead. Used as part of the L2 fee calculation.\"},\"setBatcherHash(bytes32)\":{\"notice\":\"Updates the batcher hash. Can only be called by the owner.\"},\"setGasConfig(uint256,uint256)\":{\"notice\":\"Updates gas config. Can only be called by the owner.\"},\"setGasLimit(uint64)\":{\"notice\":\"Updates the L2 gas limit. Can only be called by the owner.\"},\"setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))\":{\"notice\":\"An external setter for the resource config. In the future, this method may emit an event that the `op-node` picks up for when the resource config is changed.\"},\"setUnsafeBlockSigner(address)\":{\"notice\":\"Updates the unsafe block signer address. Can only be called by the owner.\"},\"startBlock()\":{\"notice\":\"The block at which the op-node can start searching for logs from.\"},\"unsafeBlockSigner()\":{\"notice\":\"High level getter for the unsafe block signer address. Unsafe blocks can be propagated across the p2p network if they are signed by the key corresponding to this address.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/SystemConfig.sol\":\"SystemConfig\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x4bbbc7868e948c44f29285a69383e93251a0c330a67929fb72def01cec060d4e\",\"urls\":[\"bzz-raw://1e7ea2f8b3d49bee9c753f107ede6eda93b2cc0e34d0643fa14ebbb26c19e71b\",\"dweb:/ipfs/QmRP81F8FRVXVZs6u2f2poEPDnbFZhNwNYxHgCVEhGpEmB\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 2, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 29536, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 29539, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 31067, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 29408, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 29528, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 61293, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "overhead", - "offset": 0, - "slot": "101", - "type": "t_uint256" - }, - { - "astId": 61296, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "scalar", - "offset": 0, - "slot": "102", - "type": "t_uint256" - }, - { - "astId": 61299, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "batcherHash", - "offset": 0, - "slot": "103", - "type": "t_bytes32" - }, - { - "astId": 61302, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "gasLimit", - "offset": 0, - "slot": "104", - "type": "t_uint64" - }, - { - "astId": 61306, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "_resourceConfig", - "offset": 0, - "slot": "105", - "type": "t_struct(ResourceConfig)60831_storage" - }, - { - "astId": 61319, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "startBlock", - "offset": 0, - "slot": "106", - "type": "t_uint256" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_array(t_uint256)50_storage": { - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_struct(ResourceConfig)60831_storage": { - "encoding": "inplace", - "label": "struct ResourceMetering.ResourceConfig", - "numberOfBytes": "32", - "members": [ - { - "astId": 60820, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "maxResourceLimit", - "offset": 0, - "slot": "0", - "type": "t_uint32" - }, - { - "astId": 60822, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "elasticityMultiplier", - "offset": 4, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 60824, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "baseFeeMaxChangeDenominator", - "offset": 5, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 60826, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "minimumBaseFee", - "offset": 6, - "slot": "0", - "type": "t_uint32" - }, - { - "astId": 60828, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "systemTxMaxGas", - "offset": 10, - "slot": "0", - "type": "t_uint32" - }, - { - "astId": 60830, - "contract": "src/L1/SystemConfig.sol:SystemConfig", - "label": "maximumBaseFee", - "offset": 14, - "slot": "0", - "type": "t_uint128" - } - ] - }, - "t_uint128": { - "encoding": "inplace", - "label": "uint128", - "numberOfBytes": "16" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint32": { - "encoding": "inplace", - "label": "uint32", - "numberOfBytes": "4" - }, - "t_uint64": { - "encoding": "inplace", - "label": "uint64", - "numberOfBytes": "8" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0xc0537bec4365c978607ef4cc2d92b13f50fec84f8f4e7692779c5a473edba743", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "BATCH_INBOX_SLOT()": { - "notice": "Storage slot that the batch inbox address is stored at." - }, - "L1_CROSS_DOMAIN_MESSENGER_SLOT()": { - "notice": "Storage slot that the L1CrossDomainMessenger address is stored at." - }, - "L1_ERC_721_BRIDGE_SLOT()": { - "notice": "Storage slot that the L1ERC721Bridge address is stored at." - }, - "L1_STANDARD_BRIDGE_SLOT()": { - "notice": "Storage slot that the L1StandardBridge address is stored at." - }, - "L2_OUTPUT_ORACLE_SLOT()": { - "notice": "Storage slot that the L2OutputOracle address is stored at." - }, - "OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT()": { - "notice": "Storage slot that the OptimismMintableERC20Factory address is stored at." - }, - "OPTIMISM_PORTAL_SLOT()": { - "notice": "Storage slot that the OptimismPortal address is stored at." - }, - "UNSAFE_BLOCK_SIGNER_SLOT()": { - "notice": "Storage slot that the unsafe block signer is stored at. Storing it at this deterministic storage slot allows for decoupling the storage layout from the way that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value." - }, - "VERSION()": { - "notice": "Version identifier, used for upgrades." - }, - "batchInbox()": { - "notice": "Getter for the BatchInbox address." - }, - "batcherHash()": { - "notice": "Identifier for the batcher. For version 1 of this configuration, this is represented as an address left-padded with zeros to 32 bytes." - }, - "constructor": { - "notice": "Constructs the SystemConfig contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)`" - }, - "gasLimit()": { - "notice": "L2 block gas limit." - }, - "initialize(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128),uint256,address,(address,address,address,address,address,address))": { - "notice": "Initializer. The resource config must be set before the require check." - }, - "l1CrossDomainMessenger()": { - "notice": "Getter for the L1CrossDomainMessenger address." - }, - "l1ERC721Bridge()": { - "notice": "Getter for the L1ERC721Bridge address." - }, - "l1StandardBridge()": { - "notice": "Getter for the L1StandardBridge address." - }, - "l2OutputOracle()": { - "notice": "Getter for the L2OutputOracle address." - }, - "minimumGasLimit()": { - "notice": "Returns the minimum L2 gas limit that can be safely set for the system to operate. The L2 gas limit must be larger than or equal to the amount of gas that is allocated for deposits per block plus the amount of gas that is allocated for the system transaction. This function is used to determine if changes to parameters are safe." - }, - "optimismMintableERC20Factory()": { - "notice": "Getter for the OptimismMintableERC20Factory address." - }, - "optimismPortal()": { - "notice": "Getter for the OptimismPortal address." - }, - "overhead()": { - "notice": "Fixed L2 gas overhead. Used as part of the L2 fee calculation." - }, - "resourceConfig()": { - "notice": "A getter for the resource config. Ensures that the struct is returned instead of a tuple." - }, - "scalar()": { - "notice": "Dynamic L2 gas overhead. Used as part of the L2 fee calculation." - }, - "setBatcherHash(bytes32)": { - "notice": "Updates the batcher hash. Can only be called by the owner." - }, - "setGasConfig(uint256,uint256)": { - "notice": "Updates gas config. Can only be called by the owner." - }, - "setGasLimit(uint64)": { - "notice": "Updates the L2 gas limit. Can only be called by the owner." - }, - "setResourceConfig((uint32,uint8,uint8,uint32,uint32,uint128))": { - "notice": "An external setter for the resource config. In the future, this method may emit an event that the `op-node` picks up for when the resource config is changed." - }, - "setUnsafeBlockSigner(address)": { - "notice": "Updates the unsafe block signer address. Can only be called by the owner." - }, - "startBlock()": { - "notice": "The block at which the op-node can start searching for logs from." - }, - "unsafeBlockSigner()": { - "notice": "High level getter for the unsafe block signer address. Unsafe blocks can be propagated across the p2p network if they are signed by the key corresponding to this address." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "ConfigUpdate(uint256,uint8,bytes)": { - "notice": "Emitted when configuration is updated." - } - }, - "notice": "The SystemConfig contract is used to manage configuration of an Optimism network. All configuration is stored on L1 and picked up by L2 as part of the derviation of the L2 chain." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/SystemConfigProxy.json b/packages/contracts-bedrock/deployments/mainnet/SystemConfigProxy.json deleted file mode 100644 index 9887fb571564..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/SystemConfigProxy.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "address": "0x229047fed2591dbec1eF1118d64F7aF3dB9EB290", - "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": "0x17a29cb8106fa26e61bd5eff33b448b7ba10864f201d973f1abcfa608af87015", - "receipt": { - "to": null, - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "contractAddress": "0x229047fed2591dbec1eF1118d64F7aF3dB9EB290", - "transactionIndex": 87, - "gasUsed": "523960", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000800000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000400000000", - "blockHash": "0xb2f954f82f28e496964b136b4d99833bccc1b9f51e53e85170ff4afaffdd7ed2", - "transactionHash": "0x17a29cb8106fa26e61bd5eff33b448b7ba10864f201d973f1abcfa608af87015", - "logs": [ - { - "transactionIndex": 87, - "blockNumber": 17365804, - "transactionHash": "0x17a29cb8106fa26e61bd5eff33b448b7ba10864f201d973f1abcfa608af87015", - "address": "0x229047fed2591dbec1eF1118d64F7aF3dB9EB290", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000543ba4aadbab8f9025686bd03993043599c6fb04", - "logIndex": 226, - "blockHash": "0xb2f954f82f28e496964b136b4d99833bccc1b9f51e53e85170ff4afaffdd7ed2" - } - ], - "blockNumber": 17365804, - "cumulativeGasUsed": "8661026", - "status": 1, - "byzantium": true - }, - "args": [ - "0x543bA4AADBAb8f9025686Bd03993043599c6fB04" - ], - "numDeployments": 1, - "solcInputHash": "13ac93d026822f719ad110af836d1582", - "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\":{\"contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@cwia/=node_modules/clones-with-immutable-args/src/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":clones-with-immutable-args/=node_modules/clones-with-immutable-args/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0x64d67f1936d97c87a2e42317eb162744ad5cefdc9bc8b1138ee4afe2886eb885\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://33b903585eb9cfc60a70bcdf4ee44220b173caff16dfb9071cd0668c7a551265\",\"dweb:/ipfs/QmXHUZ9brinN1WS9i63ocRQsQidY96WePDBhBsFRhDmVjr\"]}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "admin()": { - "returns": { - "_0": "Owner address." - } - }, - "changeAdmin(address)": { - "params": { - "_admin": "New owner of the proxy contract." - } - }, - "constructor": { - "params": { - "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "Address of the implementation contract." - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "Calldata to delegatecall the new implementation with.", - "_implementation": "Address of the implementation contract." - } - } - }, - "events": { - "AdminChanged(address,address)": { - "params": { - "newAdmin": "The new owner of the contract", - "previousAdmin": "The previous owner of the contract" - } - }, - "Upgraded(address)": { - "params": { - "implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "admin()": { - "notice": "Gets the owner of the proxy contract." - }, - "changeAdmin(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "constructor": { - "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." - }, - "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." - } - }, - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." - } - }, - "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/SystemDictator.json b/packages/contracts-bedrock/deployments/mainnet/SystemDictator.json deleted file mode 100644 index d42b0bbd35e5..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/SystemDictator.json +++ /dev/null @@ -1,1418 +0,0 @@ -{ - "address": "0x09E040a72FD3492355C5aEEdbC3154075f83488a", - "abi": [ - { - "inputs": [], - "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": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "EXIT_1_NO_RETURN_STEP", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PROXY_TRANSFER_STEP", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "config", - "outputs": [ - { - "components": [ - { - "internalType": "contract AddressManager", - "name": "addressManager", - "type": "address" - }, - { - "internalType": "contract ProxyAdmin", - "name": "proxyAdmin", - "type": "address" - }, - { - "internalType": "address", - "name": "controller", - "type": "address" - }, - { - "internalType": "address", - "name": "finalOwner", - "type": "address" - } - ], - "internalType": "struct SystemDictator.GlobalConfig", - "name": "globalConfig", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "l2OutputOracleProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismPortalProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "l1CrossDomainMessengerProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "l1StandardBridgeProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismMintableERC20FactoryProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "l1ERC721BridgeProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "systemConfigProxy", - "type": "address" - } - ], - "internalType": "struct SystemDictator.ProxyAddressConfig", - "name": "proxyAddressConfig", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "contract L2OutputOracle", - "name": "l2OutputOracleImpl", - "type": "address" - }, - { - "internalType": "contract OptimismPortal", - "name": "optimismPortalImpl", - "type": "address" - }, - { - "internalType": "contract L1CrossDomainMessenger", - "name": "l1CrossDomainMessengerImpl", - "type": "address" - }, - { - "internalType": "contract L1StandardBridge", - "name": "l1StandardBridgeImpl", - "type": "address" - }, - { - "internalType": "contract OptimismMintableERC20Factory", - "name": "optimismMintableERC20FactoryImpl", - "type": "address" - }, - { - "internalType": "contract L1ERC721Bridge", - "name": "l1ERC721BridgeImpl", - "type": "address" - }, - { - "internalType": "contract PortalSender", - "name": "portalSenderImpl", - "type": "address" - }, - { - "internalType": "contract SystemConfig", - "name": "systemConfigImpl", - "type": "address" - } - ], - "internalType": "struct SystemDictator.ImplementationAddressConfig", - "name": "implementationAddressConfig", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "overhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "scalar", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "batcherHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "gasLimit", - "type": "uint64" - }, - { - "internalType": "address", - "name": "unsafeBlockSigner", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "maxResourceLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "elasticityMultiplier", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "baseFeeMaxChangeDenominator", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "minimumBaseFee", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "systemTxMaxGas", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "maximumBaseFee", - "type": "uint128" - } - ], - "internalType": "struct ResourceMetering.ResourceConfig", - "name": "resourceConfig", - "type": "tuple" - } - ], - "internalType": "struct SystemDictator.SystemConfigConfig", - "name": "systemConfigConfig", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "currentStep", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "dynamicConfigSet", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "exit1", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "exited", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "finalize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "finalized", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "contract AddressManager", - "name": "addressManager", - "type": "address" - }, - { - "internalType": "contract ProxyAdmin", - "name": "proxyAdmin", - "type": "address" - }, - { - "internalType": "address", - "name": "controller", - "type": "address" - }, - { - "internalType": "address", - "name": "finalOwner", - "type": "address" - } - ], - "internalType": "struct SystemDictator.GlobalConfig", - "name": "globalConfig", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "l2OutputOracleProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismPortalProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "l1CrossDomainMessengerProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "l1StandardBridgeProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "optimismMintableERC20FactoryProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "l1ERC721BridgeProxy", - "type": "address" - }, - { - "internalType": "address", - "name": "systemConfigProxy", - "type": "address" - } - ], - "internalType": "struct SystemDictator.ProxyAddressConfig", - "name": "proxyAddressConfig", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "contract L2OutputOracle", - "name": "l2OutputOracleImpl", - "type": "address" - }, - { - "internalType": "contract OptimismPortal", - "name": "optimismPortalImpl", - "type": "address" - }, - { - "internalType": "contract L1CrossDomainMessenger", - "name": "l1CrossDomainMessengerImpl", - "type": "address" - }, - { - "internalType": "contract L1StandardBridge", - "name": "l1StandardBridgeImpl", - "type": "address" - }, - { - "internalType": "contract OptimismMintableERC20Factory", - "name": "optimismMintableERC20FactoryImpl", - "type": "address" - }, - { - "internalType": "contract L1ERC721Bridge", - "name": "l1ERC721BridgeImpl", - "type": "address" - }, - { - "internalType": "contract PortalSender", - "name": "portalSenderImpl", - "type": "address" - }, - { - "internalType": "contract SystemConfig", - "name": "systemConfigImpl", - "type": "address" - } - ], - "internalType": "struct SystemDictator.ImplementationAddressConfig", - "name": "implementationAddressConfig", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint256", - "name": "overhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "scalar", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "batcherHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "gasLimit", - "type": "uint64" - }, - { - "internalType": "address", - "name": "unsafeBlockSigner", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "maxResourceLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "elasticityMultiplier", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "baseFeeMaxChangeDenominator", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "minimumBaseFee", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "systemTxMaxGas", - "type": "uint32" - }, - { - "internalType": "uint128", - "name": "maximumBaseFee", - "type": "uint128" - } - ], - "internalType": "struct ResourceMetering.ResourceConfig", - "name": "resourceConfig", - "type": "tuple" - } - ], - "internalType": "struct SystemDictator.SystemConfigConfig", - "name": "systemConfigConfig", - "type": "tuple" - } - ], - "internalType": "struct SystemDictator.DeployConfig", - "name": "_config", - "type": "tuple" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l2OutputOracleDynamicConfig", - "outputs": [ - { - "internalType": "uint256", - "name": "l2OutputOracleStartingBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l2OutputOracleStartingTimestamp", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "oldL1CrossDomainMessenger", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "optimismPortalDynamicConfig", - "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": "phase1", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "phase2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "step1", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "step2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "step3", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "step4", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "step5", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "l2OutputOracleStartingBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l2OutputOracleStartingTimestamp", - "type": "uint256" - } - ], - "internalType": "struct SystemDictator.L2OutputOracleDynamicConfig", - "name": "_l2OutputOracleDynamicConfig", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "_optimismPortalDynamicConfig", - "type": "bool" - } - ], - "name": "updateDynamicConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xaca6cdc0a101d28f869a0acfb58a6527ffbbee2bb929bd33cc143f8256639dce", - "receipt": { - "to": null, - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "contractAddress": "0x09E040a72FD3492355C5aEEdbC3154075f83488a", - "transactionIndex": 107, - "gasUsed": "3480736", - "logsBloom": "0x00000800000000000000000000000000000000000000400000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040001000000000000000000000000000000000000020000000000000000000800000000000020000000000000000000400000000000000000000000020000000000000000000080000000000000000000000000010000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x03e7785abc4b15223aad4b7a52b0ece0c5b9c21d4efa3473435697f373d16dd9", - "transactionHash": "0xaca6cdc0a101d28f869a0acfb58a6527ffbbee2bb929bd33cc143f8256639dce", - "logs": [ - { - "transactionIndex": 107, - "blockNumber": 17365813, - "transactionHash": "0xaca6cdc0a101d28f869a0acfb58a6527ffbbee2bb929bd33cc143f8256639dce", - "address": "0x09E040a72FD3492355C5aEEdbC3154075f83488a", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000354f3f4ecdca5e0a7ace08d71348cdc1dab48960" - ], - "data": "0x", - "logIndex": 273, - "blockHash": "0x03e7785abc4b15223aad4b7a52b0ece0c5b9c21d4efa3473435697f373d16dd9" - }, - { - "transactionIndex": 107, - "blockNumber": 17365813, - "transactionHash": "0xaca6cdc0a101d28f869a0acfb58a6527ffbbee2bb929bd33cc143f8256639dce", - "address": "0x09E040a72FD3492355C5aEEdbC3154075f83488a", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x000000000000000000000000354f3f4ecdca5e0a7ace08d71348cdc1dab48960", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ], - "data": "0x", - "logIndex": 274, - "blockHash": "0x03e7785abc4b15223aad4b7a52b0ece0c5b9c21d4efa3473435697f373d16dd9" - }, - { - "transactionIndex": 107, - "blockNumber": 17365813, - "transactionHash": "0xaca6cdc0a101d28f869a0acfb58a6527ffbbee2bb929bd33cc143f8256639dce", - "address": "0x09E040a72FD3492355C5aEEdbC3154075f83488a", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 275, - "blockHash": "0x03e7785abc4b15223aad4b7a52b0ece0c5b9c21d4efa3473435697f373d16dd9" - } - ], - "blockNumber": 17365813, - "cumulativeGasUsed": "12742741", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "13ac93d026822f719ad110af836d1582", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"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\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"EXIT_1_NO_RETURN_STEP\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PROXY_TRANSFER_STEP\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"config\",\"outputs\":[{\"components\":[{\"internalType\":\"contract AddressManager\",\"name\":\"addressManager\",\"type\":\"address\"},{\"internalType\":\"contract ProxyAdmin\",\"name\":\"proxyAdmin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"controller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"finalOwner\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.GlobalConfig\",\"name\":\"globalConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"l2OutputOracleProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"optimismPortalProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1CrossDomainMessengerProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1StandardBridgeProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"optimismMintableERC20FactoryProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1ERC721BridgeProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"systemConfigProxy\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.ProxyAddressConfig\",\"name\":\"proxyAddressConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"l2OutputOracleImpl\",\"type\":\"address\"},{\"internalType\":\"contract OptimismPortal\",\"name\":\"optimismPortalImpl\",\"type\":\"address\"},{\"internalType\":\"contract L1CrossDomainMessenger\",\"name\":\"l1CrossDomainMessengerImpl\",\"type\":\"address\"},{\"internalType\":\"contract L1StandardBridge\",\"name\":\"l1StandardBridgeImpl\",\"type\":\"address\"},{\"internalType\":\"contract OptimismMintableERC20Factory\",\"name\":\"optimismMintableERC20FactoryImpl\",\"type\":\"address\"},{\"internalType\":\"contract L1ERC721Bridge\",\"name\":\"l1ERC721BridgeImpl\",\"type\":\"address\"},{\"internalType\":\"contract PortalSender\",\"name\":\"portalSenderImpl\",\"type\":\"address\"},{\"internalType\":\"contract SystemConfig\",\"name\":\"systemConfigImpl\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.ImplementationAddressConfig\",\"name\":\"implementationAddressConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"unsafeBlockSigner\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}],\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"resourceConfig\",\"type\":\"tuple\"}],\"internalType\":\"struct SystemDictator.SystemConfigConfig\",\"name\":\"systemConfigConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentStep\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dynamicConfigSet\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exit1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"exited\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finalize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"contract AddressManager\",\"name\":\"addressManager\",\"type\":\"address\"},{\"internalType\":\"contract ProxyAdmin\",\"name\":\"proxyAdmin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"controller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"finalOwner\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.GlobalConfig\",\"name\":\"globalConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"l2OutputOracleProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"optimismPortalProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1CrossDomainMessengerProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1StandardBridgeProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"optimismMintableERC20FactoryProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1ERC721BridgeProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"systemConfigProxy\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.ProxyAddressConfig\",\"name\":\"proxyAddressConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"l2OutputOracleImpl\",\"type\":\"address\"},{\"internalType\":\"contract OptimismPortal\",\"name\":\"optimismPortalImpl\",\"type\":\"address\"},{\"internalType\":\"contract L1CrossDomainMessenger\",\"name\":\"l1CrossDomainMessengerImpl\",\"type\":\"address\"},{\"internalType\":\"contract L1StandardBridge\",\"name\":\"l1StandardBridgeImpl\",\"type\":\"address\"},{\"internalType\":\"contract OptimismMintableERC20Factory\",\"name\":\"optimismMintableERC20FactoryImpl\",\"type\":\"address\"},{\"internalType\":\"contract L1ERC721Bridge\",\"name\":\"l1ERC721BridgeImpl\",\"type\":\"address\"},{\"internalType\":\"contract PortalSender\",\"name\":\"portalSenderImpl\",\"type\":\"address\"},{\"internalType\":\"contract SystemConfig\",\"name\":\"systemConfigImpl\",\"type\":\"address\"}],\"internalType\":\"struct SystemDictator.ImplementationAddressConfig\",\"name\":\"implementationAddressConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"overhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"scalar\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"unsafeBlockSigner\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxResourceLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"elasticityMultiplier\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"baseFeeMaxChangeDenominator\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"minimumBaseFee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"systemTxMaxGas\",\"type\":\"uint32\"},{\"internalType\":\"uint128\",\"name\":\"maximumBaseFee\",\"type\":\"uint128\"}],\"internalType\":\"struct ResourceMetering.ResourceConfig\",\"name\":\"resourceConfig\",\"type\":\"tuple\"}],\"internalType\":\"struct SystemDictator.SystemConfigConfig\",\"name\":\"systemConfigConfig\",\"type\":\"tuple\"}],\"internalType\":\"struct SystemDictator.DeployConfig\",\"name\":\"_config\",\"type\":\"tuple\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2OutputOracleDynamicConfig\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"l2OutputOracleStartingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"l2OutputOracleStartingTimestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oldL1CrossDomainMessenger\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"optimismPortalDynamicConfig\",\"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\":\"phase1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"phase2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"step1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"step2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"step3\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"step4\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"step5\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"l2OutputOracleStartingBlockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"l2OutputOracleStartingTimestamp\",\"type\":\"uint256\"}],\"internalType\":\"struct SystemDictator.L2OutputOracleDynamicConfig\",\"name\":\"_l2OutputOracleDynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"_optimismPortalDynamicConfig\",\"type\":\"bool\"}],\"name\":\"updateDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"initialize(((address,address,address,address),(address,address,address,address,address,address,address),(address,address,address,address,address,address,address,address),(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128))))\":{\"params\":{\"_config\":\"System configuration.\"}},\"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.\"},\"updateDynamicConfig((uint256,uint256),bool)\":{\"params\":{\"_l2OutputOracleDynamicConfig\":\"Dynamic L2OutputOracle config.\",\"_optimismPortalDynamicConfig\":\"Dynamic OptimismPortal config.\"}}},\"title\":\"SystemDictator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"EXIT_1_NO_RETURN_STEP()\":{\"notice\":\"Step after which exit 1 can no longer be used.\"},\"PROXY_TRANSFER_STEP()\":{\"notice\":\"Step where proxy ownership is transferred.\"},\"config()\":{\"notice\":\"System configuration.\"},\"constructor\":{\"notice\":\"Constructor required to ensure that the implementation of the SystemDictator is initialized upon deployment.\"},\"currentStep()\":{\"notice\":\"Current step;\"},\"dynamicConfigSet()\":{\"notice\":\"Whether or not dynamic config has been set.\"},\"exit1()\":{\"notice\":\"First exit point, can only be called before step 3 is executed.\"},\"exited()\":{\"notice\":\"Whether or not the deployment has been exited.\"},\"finalize()\":{\"notice\":\"Tranfers admin ownership to the final owner.\"},\"finalized()\":{\"notice\":\"Whether or not the deployment is finalized.\"},\"l2OutputOracleDynamicConfig()\":{\"notice\":\"Dynamic configuration for the L2OutputOracle.\"},\"oldL1CrossDomainMessenger()\":{\"notice\":\"Address of the old L1CrossDomainMessenger implementation.\"},\"optimismPortalDynamicConfig()\":{\"notice\":\"Dynamic configuration for the OptimismPortal. Determines if the system should be paused when initialized.\"},\"phase1()\":{\"notice\":\"Calls the first 2 steps of the migration process.\"},\"phase2()\":{\"notice\":\"Calls the remaining steps of the migration process, and finalizes.\"},\"step1()\":{\"notice\":\"Configures the ProxyAdmin contract.\"},\"step2()\":{\"notice\":\"Pauses the system by shutting down the L1CrossDomainMessenger and setting the deposit halt flag to tell the Sequencer's DTL to stop accepting deposits.\"},\"step3()\":{\"notice\":\"Removes deprecated addresses from the AddressManager.\"},\"step4()\":{\"notice\":\"Transfers system ownership to the ProxyAdmin.\"},\"step5()\":{\"notice\":\"Upgrades and initializes proxy contracts.\"},\"updateDynamicConfig((uint256,uint256),bool)\":{\"notice\":\"Allows the owner to update dynamic config.\"}},\"notice\":\"The SystemDictator is responsible for coordinating the deployment of a full Bedrock system. The SystemDictator is designed to support both fresh network deployments and upgrades to existing pre-Bedrock systems.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/deployment/SystemDictator.sol\":\"SystemDictator\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@cwia/=node_modules/clones-with-immutable-args/src/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":clones-with-immutable-args/=node_modules/clones-with-immutable-args/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/L1/L1CrossDomainMessenger.sol\":{\"keccak256\":\"0xeaaa55074aa93641ab9423033a25beeee8b93900b556a059338d77c29b1c7e5f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://cdce427876bf3cce02395d716a23675990800c4236f1b99f606ea63ae535ca06\",\"dweb:/ipfs/QmT5gBeR4dH5M6KRvtUKfKVMk4b3528vB49Bn9fNEKSPwH\"]},\"contracts/L1/L1ERC721Bridge.sol\":{\"keccak256\":\"0xe1e81e114ab32473e7cbc88a6e686f166e686ae6cc75ecb7cb3f929a30c92458\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e41cf7b7912446293b5b916c0045bfd25b914fdc1fad0b3b0b471479b55812c4\",\"dweb:/ipfs/QmXkQj7f8pFuoW8UqdW3Mj9u4FdKA6b6qXWHpRJywi3Fwk\"]},\"contracts/L1/L1StandardBridge.sol\":{\"keccak256\":\"0xb2c96bbf32c948863e20a4cd27c0813ae72d8694aaa777fcffb36245bdac6fe3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://229bb8837204c9996f0b91b8886af05e97095563b376aa9a6e3094d7b6622ffb\",\"dweb:/ipfs/QmXaqGWCxGVQ8B27kKeStP1mYW9H22tyrxaHsuUogttz7N\"]},\"contracts/L1/L2OutputOracle.sol\":{\"keccak256\":\"0xba09a5005080e6c7ccc9e0dab17165f20ae0ef9d9c04a13d0b5c158dc1c2a4bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fce7e5b5fb4882f05ddcd540f4781225bcf95870b5206e1b423a98ddd3e80df2\",\"dweb:/ipfs/QmQxsgVPaZmkW8SKxKtQEmP5ApeXAxaEEC6Hf4AQ4xL3wC\"]},\"contracts/L1/OptimismPortal.sol\":{\"keccak256\":\"0x3b16493feec098a6d70b98a83e0f7c5f541ac33c5265edee77c2c0229c343fd2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://795b7f9aca7930f9b446d81071ba7d35872f3fbd53faa0e7acb1f51df4edb7f2\",\"dweb:/ipfs/QmTwr3pGnVVN2qfTjPqC5svhM7rLVLgiEj1SthHVz1v4k8\"]},\"contracts/L1/ResourceMetering.sol\":{\"keccak256\":\"0xbd7b9532a70d8c842bfce0ea971be50d02fbbf0227c9ad55c71ac68d438010f4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4969f478dd54e89392cda2ea0c5edcf1be55a5dee43a0e410527b6e3bcb85c88\",\"dweb:/ipfs/QmU2crAojw8DRDsz7PAPrereazjFsKh9wtfTpTDVh6NLfW\"]},\"contracts/L1/SystemConfig.sol\":{\"keccak256\":\"0x2202e03df7b5f70b0cf1cf942afe51cab165bf35864a77d6a77dc82c55653689\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://42ec7d69b192c6199bf28ccf1d19d896f01807039f6bdc3e871b52eb7d9ee645\",\"dweb:/ipfs/QmPmWLf9a9FJ2fYQi9nP73e4QRnAMDbrfNwLS1u8KZgrEs\"]},\"contracts/L2/L2ERC721Bridge.sol\":{\"keccak256\":\"0x94d240acff616f7ec4281bb3c2d3cace1c398bfca754fb3ca7bc795c875b4f10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7613d2506fc31214e3e36c8cd9b0845c9bcaaf063be6fc611ce8efe3fce71584\",\"dweb:/ipfs/QmX8eBBgEWvUPXgpQsPQN3ZhZbwMawFQRuqyTF8Rcv1u1S\"]},\"contracts/deployment/PortalSender.sol\":{\"keccak256\":\"0xe60d88036d9aa8f8e80a4108ee30ad987564ad996af87a79ba92f6ca35852881\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a4be187cd3d5926592491f722dfa1b1c41a8f4f1abdc8cf3883964f70acb0a44\",\"dweb:/ipfs/QmYsAK4YcRHmPoex2eX2x1r6N76AMk3rdBHHmp6gUT73Fa\"]},\"contracts/deployment/SystemDictator.sol\":{\"keccak256\":\"0x4539f2205aa2b1f0502d2b58f6f97772768dc4424333a2acae89dd00c6b0901d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3917b358bf76ee85a534406a12e149df92dca5d404f3aab6a0c4f6dc490f3ad0\",\"dweb:/ipfs/QmdvBYGNKR6pdMBgQGjSgy75i4PtYtr6ZWgjRgv9kMqcq1\"]},\"contracts/legacy/AddressManager.sol\":{\"keccak256\":\"0x7a353d4c92eed32665fd2f0023c55054901293cf7a6e14ca108229d87c047b10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b92ba23601d1951271729a20db931a45639d9376b7c8e2705c23dc360833715a\",\"dweb:/ipfs/QmTKwYLNYYBKZpd31VNBANmguVUwFZifSg7joHSgLZjZCj\"]},\"contracts/legacy/L1ChugSplashProxy.sol\":{\"keccak256\":\"0x6ae7bf6ea9ac0e3511ee4cb15d946589da0dd35098ff762c0b2903d064f24875\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://02028d86c1d38563021d5ead5282271ccdf1c03a24f2eaee056ae2157f0554ee\",\"dweb:/ipfs/QmW9urkBBRTmZ8FjL5Y5zWbdnRhPDruxCCLnpr2CTkozKM\"]},\"contracts/libraries/Arithmetic.sol\":{\"keccak256\":\"0xc8858039f87e48e6f18c1af8bc0b03e57cfef564acddfd06e4d91e3db7ac5ed6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2fc79af1e844aa6dc1c68067bfe1d359df8d4e9a3e8881afb3bcfcbf68071714\",\"dweb:/ipfs/QmcNC4k8zmvwj4kZizSenTiWbx2DJQPbwqXXLF4iMbkRVD\"]},\"contracts/libraries/Burn.sol\":{\"keccak256\":\"0x54233b226ba6919dc46d438bc790108d8f855001002a1b9c3c37aed7a83e5f3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4051a4baca357a9191a6c9e3aa1593a17b69dd7915966e23e4cb269e9c1d9ed4\",\"dweb:/ipfs/QmadKjGKvxm53abVHQdsxrXBc8e9jXywu6vvhkAgjsx59J\"]},\"contracts/libraries/Bytes.sol\":{\"keccak256\":\"0x7aca6593fadf438ee9cd090d8fdc8f94a5202a2eb7f764c9a86f207712d87a48\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://aac32157885c5a08bd0bc7dcd5511f66db12bb20d0c263dd7be9f58b91538fc1\",\"dweb:/ipfs/Qmb1iG11Z53yt9wNbGsuTvoydJXFosDDpWwRSADKyqiCjw\"]},\"contracts/libraries/Constants.sol\":{\"keccak256\":\"0x8c7be28a175eb732995a7f704560163c30261f9f70d377f865c5060882509f5d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f72aba26553b10ca88708e05461691b36b0d2ec7a87f718022fe119ca9c70852\",\"dweb:/ipfs/QmQtDEB1F3D8RsgG63KSJ9t7ZyFLaXc2Av81vKD9y2TMn7\"]},\"contracts/libraries/Encoding.sol\":{\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f18156216c1f9457c2e032a812ad70f2babbc5b89997554ff014d64c483fb2ff\",\"dweb:/ipfs/Qmc5rjMaBFn3jV7XqDrEvRbmatQvJxeVJYA5B5rdcKPkcJ\"]},\"contracts/libraries/Hashing.sol\":{\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6746ed0d26d603568818cc52a29d0209effd69f7e55bd0017a6b91bd6cf319fe\",\"dweb:/ipfs/QmPebCmCELMBRtDDxt5ziEPfRXUh6tfm2qJdwz3iyrDdWN\"]},\"contracts/libraries/Predeploys.sol\":{\"keccak256\":\"0xfc30fb239b5f00284f4b8f578a62f0882597e939335c91ea9bc4aab3070ddc43\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fa132267b3a9d98568b4e02cbb68fe2d2c0ca630826242c1b2293a8fa35bd302\",\"dweb:/ipfs/QmdYvcGbaykP6wyBu5T2obXrWK56xGnfWqbYeeWpTChq3w\"]},\"contracts/libraries/SafeCall.sol\":{\"keccak256\":\"0x3deedbfc0a57228366531a4f09c94d174f0bb4ea49476a92226d471f3abb349b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e8091b178f6710cb7738f07b1706fe18c241b6275b6641b32724d4ecf5a087dd\",\"dweb:/ipfs/Qmd5kchcZhHepJ3boHRTVDJUr9jsuweWEyoUmNmMFJB6vp\"]},\"contracts/libraries/Types.sol\":{\"keccak256\":\"0x4fe8ec920798661a828430bd30dc2715eeb40534ec01c0a7bf41cb4ab422e134\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://74c8471869900bd459358cd990bda1c8d234c06b788804c7049cf465ae1e299f\",\"dweb:/ipfs/QmakcfP6NmbVUQsKqH7rEyJsbiqckigLahw9g74oencEJ7\"]},\"contracts/libraries/rlp/RLPReader.sol\":{\"keccak256\":\"0x50763c897f0fe84cb067985ec4d7c5721ce9004a69cf0327f96f8982ee8ca412\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://603af847b43933b075f9aac3a7b3cd65041ffe6d732826695458ca9575e1a809\",\"dweb:/ipfs/QmfByFEaCxT9y1VtqoLi5EsXZ9ihkPfj6g5x7pcPoQ7q2K\"]},\"contracts/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://921c44e6a0982b9a4011900fda1bda2c06b7a85894967de98b407a83fe9f90c0\",\"dweb:/ipfs/QmSsHLKDUQ82kpKdqB6VntVGKuPDb4W9VdotsubuqWBzio\"]},\"contracts/libraries/trie/MerkleTrie.sol\":{\"keccak256\":\"0xd27fc945d6dd2821636d840f3766f817823c8e9fbfdb87c2da7c73e4292d2f7f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://497cec37d09ebcdc8d1cccac608a4a0b9b9d83eac6cc7c9e8b73c4c6644e2209\",\"dweb:/ipfs/QmUYMsCcgU6epspvKV9Y6anHyyMb4hd1xVzUZheBY9mfG7\"]},\"contracts/libraries/trie/SecureMerkleTrie.sol\":{\"keccak256\":\"0x61b03a03779cb1f75cea3b88af16fdfd10629029b4b2d6be5238e71af8ef1b5f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1212951af291c0e033a7119b42de5cad6b6bf32da26777da7c2419e76fa8f314\",\"dweb:/ipfs/QmYbnifDmL6UkP9D1X9GaNLR1Q8wYwmDNeYqkJ71bycaE5\"]},\"contracts/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x3c99b1e768cc4c1e064ccc137b1b4d5961bf4edf071be84cc216c5b20f1c00da\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e36b2a6325c2f804d769271575669b62ab2da2df3c81921ac7487399fe02af07\",\"dweb:/ipfs/QmTCmcEKwvD8Xvjyev268Bkz27FC7TJpUbw1nADcsThnUr\"]},\"contracts/universal/ERC721Bridge.sol\":{\"keccak256\":\"0xb47389fbec63e85b2d04fce538fe1b8e048278d631729458b70e32a31971c092\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7133f38e3d8d1911738057b1d4523989abd7cd029797b1d3b59cda29d42e9704\",\"dweb:/ipfs/QmUN31CLssESHrBwWA3WYP5L2xESo9Q4aq2Exua1e8UtUW\"]},\"contracts/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x2fea0ee05071c9c6b06a34a8e805801e247e861359b376a8918106e1d6f77ebe\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://198c91bda2edf864ddad1f8ab6168155d13d6ba5487418e5531ff040ff250686\",\"dweb:/ipfs/QmQzxfHY4P7zdVFRh2DTdGt1KeMHaGKNRf3KPZ1mRTYEGB\"]},\"contracts/universal/IOptimismMintableERC721.sol\":{\"keccak256\":\"0xf1a3dd4452df8882a65a31c5e2e8de7872b08cf078be7a5a7da51e6f75c53ad3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b09a2560cae35ca4789fe1ff5edb2bae9fa7dcda115a55f7ccdcc974a2e37526\",\"dweb:/ipfs/QmPQeTvrJ4SJpng5VGZNMf1u85NWxrdus4gGn8xYkHddKM\"]},\"contracts/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x302094342a45ebdf7f46f4fb48821960d2a4134f66fd7f458f73fc4ddf34d219\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8b0e2b496e966ca6037e1c9be1d44417c0180fda2a27f68114e93b899defb783\",\"dweb:/ipfs/QmXP76ivMLxYxscC7B9E9qtW3u6HJ2MNaRVeo3x24VEAQH\"]},\"contracts/universal/OptimismMintableERC20Factory.sol\":{\"keccak256\":\"0x87fde59e9b0d43c415cb26d0cb13d7b1aab1f725750291dd257276efdf83774b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e76b70b637fd5d4daf121ba201dd3c85e5ca9763adf65f032c49753057d2c9af\",\"dweb:/ipfs/Qmf5SWFCS2TB1VM5BfGfb8EG84H8mdVwXe9A5jipgf4Lgr\"]},\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0x64d67f1936d97c87a2e42317eb162744ad5cefdc9bc8b1138ee4afe2886eb885\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://33b903585eb9cfc60a70bcdf4ee44220b173caff16dfb9071cd0668c7a551265\",\"dweb:/ipfs/QmXHUZ9brinN1WS9i63ocRQsQidY96WePDBhBsFRhDmVjr\"]},\"contracts/universal/ProxyAdmin.sol\":{\"keccak256\":\"0x7326011ac425cc9ab4760c29ca559342d4832633b5019a9a61b9e63067374e2a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7d3541272c48443f0b339998553e44600b7bcb4f949e5c94acb5a3acfce19399\",\"dweb:/ipfs/QmNSd9jxACWg8bZE8EgxmRdXwLUQixVs4oiugrVegapUe4\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9baf7797439c0ae6512f4639dfc6a1934dbd4e4d7cbb8e63e99264ff47682c9e\",\"dweb:/ipfs/QmawAuhppPyeoZH3rC1uh87xDELa9Lyfw5pYsBqE8myE1m\"]},\"contracts/universal/StandardBridge.sol\":{\"keccak256\":\"0xaa45044774fa70ed322983c3c0138b21d26d75f4b7e8f5324d53c3eef91adec4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c65c95d0cb71f2e32f5ffdea92151a9a46bbd538ba110389a134963fd16a33e9\",\"dweb:/ipfs/QmaPNZokt4j5SCXaWwVtw6qxu5GXWFa3SWBgaSWPPA9KUG\"]},\"contracts/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"]},\"node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"]},\"node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"]},\"node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"]},\"node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"]},\"node_modules/@openzeppelin/contracts/access/Ownable.sol\":{\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://40fb1b5102468f783961d0af743f91b9980cf66b50d1d12009f6bb1869cea4d2\",\"dweb:/ipfs/QmYqEbJML4jB1GHbzD4cUZDtJg5wVwNm3vDJq1GbyDus8y\"]},\"node_modules/@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b2717fd2bdac99daa960a6de500754ea1b932093c946388c381da48658234b95\",\"dweb:/ipfs/QmP6QVMn6UeA3ByahyJbYQr5M6coHKBKsf3ySZSfbyA8R7\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x032807210d1d7d218963d7355d62e021a84bf1b3339f4f50be2f63b53cccaf29\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://11756f42121f6541a35a8339ea899ee7514cfaa2e6d740625fcc844419296aa6\",\"dweb:/ipfs/QmekMuk6BY4DAjzeXr4MSbKdgoqqsZnA8JPtuyWc6CwXHf\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"keccak256\":\"0xed6a749c5373af398105ce6ee3ac4763aa450ea7285d268c85d9eeca809cdb1f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://20a97f891d06f0fe91560ea1a142aaa26fdd22bed1b51606b7d48f670deeb50f\",\"dweb:/ipfs/QmTbCtZKChpaX5H2iRiTDMcSz29GSLCpTCDgJpcMR4wg8x\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://26fef835622b46a5ba08b3ef6b46a22e94b5f285d0f0fb66b703bd30217d2c34\",\"dweb:/ipfs/QmZ548qdwfL1qF7aXz3xh1GCdTiST81kGGuKRqVUfYmPZR\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"]},\"node_modules/@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"]},\"node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"]},\"node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"]}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b506000620000296200011a60201b62002b551760201c565b6040805161010080820183526000608080840182815260a080860184905260c080870185905260e0808801869052928752875180840189528581526020818101879052818a018790526060808301889052828701889052828501889052828401889052818a019290925289519788018a52868852878101879052878a01879052878201879052878601879052878401879052878301879052878501879052888a0197909752885193840189528584529583018590529682018490528185018490529181018390529081018290529384018590529082019290925291925090620001129062000191565b5050620006d2565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c0810182526301312d008152600a6020820152600891810191909152633b9aca006060820152620f424060808201526001600160801b0360a082015290565b600054610100900460ff1615808015620001b25750600054600160ff909116105b80620001e25750620001cf30620005a260201b62002bd51760201c565b158015620001e2575060005460ff166001145b6200024b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200026f576000805461ff0019166101001790555b81518051606580546001600160a01b03199081166001600160a01b039384161790915560208084015160668054841691851691909117905560408085015160678054851691861691909117905560609485015160688054851691861691909117905581870151805160698054861691871691909117905580830151606a8054861691871691909117905580820151606b8054861691871691909117905580860151606c80548616918716919091179055608080820151606d8054871691881691909117905560a080830151606e8054881691891691909117905560c092830151606f80548816918916919091179055838a01518051607080548916918a1691909117905580860151607180548916918a1691909117905580850151607280548916918a1691909117905580890151607380548916918a1691909117905580830151607480548916918a1691909117905580820151607580548916918a1691909117905580840151607680548916918a1691909117905560e00151607780548816918916919091179055878a0151805160788054909816908916179096558585015160795585840151607a5585880151607b5585820151607c8054888401516001600160401b039093166001600160e01b031990911617680100000000000000009290991691909102979097179096559301518051607d805494830151938301519783015183870151939097015163ffffffff92831664ffffffffff199096169590951764010000000060ff958616021764ffffffffff60281b191665010000000000949098169390930263ffffffff60301b19169690961766010000000000009587169590950294909417600160501b600160f01b0319166a01000000000000000000009590941694909402600160701b600160f01b03191692909217600160701b6001600160801b039093169290920291909117909155805461010061ff001990911617905562000540620005b1565b60675462000557906001600160a01b031662000619565b80156200059e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff166200060d5760405162461bcd60e51b815260206004820152602b60248201526000805160206200428d83398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000242565b620006176200066b565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620006c75760405162461bcd60e51b815260206004820152602b60248201526000805160206200428d83398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000242565b620006173362000619565b613bab80620006e26000396000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c8063b3f05b97116100e3578063d7efbb301161008c578063f2fde38b11610066578063f2fde38b14610503578063fb5d737614610516578063fe6b1ddf1461051e57600080fd5b8063d7efbb30146104e6578063df4ec249146104f3578063e7c56229146104fb57600080fd5b8063d36ec430116100bd578063d36ec430146104c3578063d40a71fb146104d6578063d4deb3b6146104de57600080fd5b8063b3f05b9714610473578063bc5df61414610487578063cf03c22d1461049a57600080fd5b8063715018a61161014557806389cb73431161011f57806389cb7343146104195780638da5cb5b1461042c5780638f4ed3331461046b57600080fd5b8063715018a61461022857806379502c55146102305780637d1d95a61461041157600080fd5b80634fb4bcec116101765780634fb4bcec146101e95780635bc34f71146101f15780635ce6c3271461020357600080fd5b8063204c881c1461019d578063289c6af7146101c55780634bb278f3146101df575b600080fd5b607e54607f546101ab919082565b604080519283526020830191909152015b60405180910390f35b6101cd600381565b60405160ff90911681526020016101bc565b6101e7610526565b005b6101e7610790565b6080546101cd90610100900460ff1681565b60805461021890640100000000900460ff1681565b60405190151581526020016101bc565b6101e7611148565b604080516080808201835260655473ffffffffffffffffffffffffffffffffffffffff908116835260665481166020808501919091526067548216848601526068548216606080860191909152855160e0808201885260695485168252606a54851682850152606b54851682890152606c54851682840152606d54851682870152606e54851660a080840191909152606f54861660c080850191909152895161010081018b52607054881681526071548816818801526072548816818c01526073548816818701526074548816818a01526075548816818401526076548816818301526077548816818501528a519384018b526078548816845260795484880152607a54848c0152607b5484870152607c5467ffffffffffffffff8116858b01526801000000000000000090049097168383015289518082018b52607d5463ffffffff8082168352640100000000820460ff908116998401999099526501000000000082049098169b82019b909b5266010000000000008b048716958101959095526a01000000000000000000008a04909516968401969096526e0100000000000000000000000000009097046fffffffffffffffffffffffffffffffff1694820194909452908501526104019384565b6040516101bc9493929190612e23565b6101cd600481565b6080546102189062010000900460ff1681565b60335473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b6101e761115c565b608054610218906301000000900460ff1681565b6101e761049536600461346e565b6114cb565b6080546104469065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6101e76104d1366004613533565b611a29565b6101e7611a9c565b6101e7611f7e565b6080546102189060ff1681565b6101e7611fa6565b6101e761256a565b6101e76105113660046135d2565b612582565b6101e7612639565b6101e7612931565b61052e612bf1565b6066546068546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063f2fde38b90602401600060405180830381600087803b15801561059d57600080fd5b505af11580156105b1573d6000803e3d6000fd5b5050608054600461010090910460ff161191506107609050576065546068546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063f2fde38b90602401600060405180830381600087803b15801561063957600080fd5b505af115801561064d573d6000803e3d6000fd5b5050606c546068546040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152911692506313af40359150602401600060405180830381600087803b1580156106c057600080fd5b505af11580156106d4573d6000803e3d6000fd5b5050606e546068546040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169250638f2839709150602401600060405180830381600087803b15801561074757600080fd5b505af115801561075b573d6000803e3d6000fd5b505050505b608080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffff166301000000179055565b610798612bf1565b6080546005906301000000900460ff161561083a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d4469637461746f723a20616c72656164792066696e616c697a6560448201527f640000000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b608054640100000000900460ff16156108af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20616c72656164792065786974656400006044820152606401610831565b60805460ff8281166101009092041614610925576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20696e636f7272656374207374657000006044820152606401610831565b60805462010000900460ff166109bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603c60248201527f53797374656d4469637461746f723a2064796e616d6963206f7261636c65206360448201527f6f6e666967206973206e6f742079657420696e697469616c697a6564000000006064820152608401610831565b606654606954607054607e54607f546040516024810192909252604482015273ffffffffffffffffffffffffffffffffffffffff93841693639623609d938116921690606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fe4a3011600000000000000000000000000000000000000000000000000000000179052517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b168152610ab293929190600401613670565b600060405180830381600087803b158015610acc57600080fd5b505af1158015610ae0573d6000803e3d6000fd5b5050606654606a5460715460805460405160ff9091161515602482015273ffffffffffffffffffffffffffffffffffffffff9384169550639623609d9450918316921690604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd53a822f00000000000000000000000000000000000000000000000000000000179052517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b168152610bd693929190600401613670565b600060405180830381600087803b158015610bf057600080fd5b505af1158015610c04573d6000803e3d6000fd5b5050606654606b546072546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b158015610c8257600080fd5b505af1158015610c96573d6000803e3d6000fd5b5050606b54604080517f8129fc1c000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169350638129fc1c925060048181019260009290919082900301818387803b158015610d0657600080fd5b505af1925050508015610d17575060015b610e7457610d236136a9565b806308c379a003610dea5750610d376136c5565b80610d425750610dec565b7f7a2a4e26842155ea933fe6eb6e3137eb5a296dcdf55721c552be7b4c3cc2375981604051602001610d74919061376d565b604051602081830303815290604052805190602001201481604051602001610d9c9190613789565b60405160208183030381529060405290610de3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083191906137f4565b5050610e74565b505b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f53797374656d4469637461746f723a20756e6578706563746564206572726f7260448201527f20696e697469616c697a696e67204c3158444d20286e6f20726561736f6e29006064820152608401610831565b606654606c546076546040805160048082526024820183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fed88c68e0000000000000000000000000000000000000000000000000000000017905291517f9623609d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff95861695639623609d95610f2a95908216949116929101613670565b600060405180830381600087803b158015610f4457600080fd5b505af1158015610f58573d6000803e3d6000fd5b5050606654606c546073546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b158015610fd657600080fd5b505af1158015610fea573d6000803e3d6000fd5b5050606654606d546074546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b15801561106857600080fd5b505af115801561107c573d6000803e3d6000fd5b5050606654606e546075546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec491506044015b600060405180830381600087803b1580156110fb57600080fd5b505af115801561110f573d6000803e3d6000fd5b505060808054610100900460ff1692509050600161112c83613836565b91906101000a81548160ff021916908360ff1602179055505050565b611150612bf1565b61115a6000612c72565b565b611164612bf1565b6080546002906301000000900460ff1615611201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d4469637461746f723a20616c72656164792066696e616c697a6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610831565b608054640100000000900460ff1615611276576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20616c72656164792065786974656400006044820152606401610831565b60805460ff82811661010090920416146112ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20696e636f7272656374207374657000006044820152606401610831565b6065546040517fbf40fac100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac19061134090600401613855565b602060405180830381865afa15801561135d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113819190613898565b608080547fffffffffffffff0000000000000000000000000000000000000000ffffffffff166501000000000073ffffffffffffffffffffffffffffffffffffffff938416021790556065546040517f9b2ea4bd000000000000000000000000000000000000000000000000000000008152911690639b2ea4bd9061140b906000906004016138b5565b600060405180830381600087803b15801561142557600080fd5b505af1158015611439573d6000803e3d6000fd5b5050606554604080517f9b2ea4bd0000000000000000000000000000000000000000000000000000000081526004810191909152601160448201527f44544c5f534855544f46465f424c4f434b000000000000000000000000000000606482015273ffffffffffffffffffffffffffffffffffffffff43811660248301529091169250639b2ea4bd91506084016110e1565b600054610100900460ff16158080156114eb5750600054600160ff909116105b806115055750303b158015611505575060005460ff166001145b611591576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610831565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156115ef57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b81518051606580547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560208084015160668054841691851691909117905560408085015160678054851691861691909117905560609485015160688054851691861691909117905581870151805160698054861691871691909117905580830151606a8054861691871691909117905580820151606b8054861691871691909117905580860151606c80548616918716919091179055608080820151606d8054871691881691909117905560a080830151606e8054881691891691909117905560c092830151606f80548816918916919091179055838a01518051607080548916918a1691909117905580860151607180548916918a1691909117905580850151607280548916918a1691909117905580890151607380548916918a1691909117905580830151607480548916918a1691909117905580820151607580548916918a1691909117905580840151607680548916918a1691909117905560e00151607780548816918916919091179055878a0151805160788054909816908916179096558585015160795585840151607a5585880151607b5585820151607c80548884015167ffffffffffffffff9093167fffffffff0000000000000000000000000000000000000000000000000000000090911617680100000000000000009290991691909102979097179096559301518051607d805494830151938301519783015183870151939097015163ffffffff9283167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009096169590951764010000000060ff95861602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000094909816939093027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1696909617660100000000000095871695909502949094177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000095909416949094027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff909316929092029190911790915580546101007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff9091161790556119a0612ce9565b6067546119c29073ffffffffffffffffffffffffffffffffffffffff16612c72565b8015611a2557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b611a31612bf1565b8151607e55602090910151607f55608080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff009092169190911762010000179055565b611aa4612bf1565b6080546001906301000000900460ff1615611b41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d4469637461746f723a20616c72656164792066696e616c697a6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610831565b608054640100000000900460ff1615611bb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20616c72656164792065786974656400006044820152606401610831565b60805460ff8281166101009092041614611c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20696e636f7272656374207374657000006044820152606401610831565b6066546065546040517f0652b57a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152911690630652b57a90602401600060405180830381600087803b158015611c9b57600080fd5b505af1158015611caf573d6000803e3d6000fd5b5050606654606b546040517f8d52d4a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450638d52d4a09350611d119290911690600290600401613916565b600060405180830381600087803b158015611d2b57600080fd5b505af1158015611d3f573d6000803e3d6000fd5b5050606654606b546040517f860f7cda00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff928316945063860f7cda9350611d9e9290911690600401613977565b600060405180830381600087803b158015611db857600080fd5b505af1158015611dcc573d6000803e3d6000fd5b5050606654606c546040517f8d52d4a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450638d52d4a09350611e2e9290911690600190600401613916565b600060405180830381600087803b158015611e4857600080fd5b505af1158015611e5c573d6000803e3d6000fd5b5050606654606f54607754607854607954607a54607b54607c5460405173ffffffffffffffffffffffffffffffffffffffff9889169a50639623609d99509688169795861696611ecf969586169567ffffffffffffffff8316926801000000000000000090041690607d906024016139d0565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff975e92500000000000000000000000000000000000000000000000000000000179052517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526110e193929190600401613670565b611f86612bf1565b611f8e611fa6565b611f96612639565b611f9e610790565b61115a610526565b611fae612bf1565b6080546003906301000000900460ff161561204b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d4469637461746f723a20616c72656164792066696e616c697a6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610831565b608054640100000000900460ff16156120c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20616c72656164792065786974656400006044820152606401610831565b60805460ff8281166101009092041614612136576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20696e636f7272656374207374657000006044820152606401610831565b60006040518061022001604052806040518060400160405280601d81526020017f4f564d5f43616e6f6e6963616c5472616e73616374696f6e436861696e00000081525081526020016040518060400160405280601a81526020017f4f564d5f4c3243726f7373446f6d61696e4d657373656e6765720000000000008152508152602001604051806060016040528060228152602001613b356022913981526020016040518060400160405280600d81526020017f4f564d5f53657175656e6365720000000000000000000000000000000000000081525081526020016040518060400160405280600c81526020017f4f564d5f50726f706f73657200000000000000000000000000000000000000008152508152602001604051806060016040528060258152602001613b57602591398152602001604051806060016040528060238152602001613b7c602391398152604080518082018252601d81527f4f564d5f43616e6f6e6963616c5472616e73616374696f6e436861696e0000006020828101919091528084019190915281518083018352601881527f4f564d5f5374617465436f6d6d69746d656e74436861696e0000000000000000818301528284015281518083018352600f81527f4f564d5f426f6e644d616e61676572000000000000000000000000000000000081830152606084015281518083018352601481527f4f564d5f457865637574696f6e4d616e616765720000000000000000000000008183015260808401528151808301835260118082527f4f564d5f467261756456657269666965720000000000000000000000000000008284015260a085019190915282518084018452601781527f4f564d5f53746174654d616e61676572466163746f72790000000000000000008184015260c085015282518084018452601c81527f4f564d5f53746174655472616e736974696f6e6572466163746f7279000000008184015260e0850152825180840184529081527f4f564d5f536166657479436865636b65720000000000000000000000000000008183015261010084015281518083018352601981527f4f564d5f4c314d756c74694d65737361676552656c6179657200000000000000818301526101208401528151808301909252600b82527f426f6e644d616e616765720000000000000000000000000000000000000000009082015261014090910152905060005b60118110156125505760655473ffffffffffffffffffffffffffffffffffffffff16639b2ea4bd8383601181106124e7576124e7613a95565b602002015160006040518363ffffffff1660e01b815260040161250b929190613ac4565b600060405180830381600087803b15801561252557600080fd5b505af1158015612539573d6000803e3d6000fd5b50505050808061254890613afc565b9150506124ae565b505060808054610100900460ff1690600161112c83613836565b612572612bf1565b61257a611a9c565b61115a61115c565b61258a612bf1565b73ffffffffffffffffffffffffffffffffffffffff811661262d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610831565b61263681612c72565b50565b612641612bf1565b6080546004906301000000900460ff16156126de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d4469637461746f723a20616c72656164792066696e616c697a6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610831565b608054640100000000900460ff1615612753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20616c72656164792065786974656400006044820152606401610831565b60805460ff82811661010090920416146127c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20696e636f7272656374207374657000006044820152606401610831565b6065546066546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063f2fde38b90602401600060405180830381600087803b15801561283857600080fd5b505af115801561284c573d6000803e3d6000fd5b5050606c546066546040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152911692506313af40359150602401600060405180830381600087803b1580156128bf57600080fd5b505af11580156128d3573d6000803e3d6000fd5b5050606e546066546040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169250638f28397091506024016110e1565b612939612bf1565b608054610100900460ff166003146129d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f53797374656d4469637461746f723a2063616e206f6e6c79206578697431206260448201527f65666f72652073746570203320697320657865637574656400000000000000006064820152608401610831565b6065546080546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831692639b2ea4bd92612a389265010000000000909104909116906004016138b5565b600060405180830381600087803b158015612a5257600080fd5b505af1158015612a66573d6000803e3d6000fd5b5050606554604080517f9b2ea4bd0000000000000000000000000000000000000000000000000000000081526004810191909152601160448201527f44544c5f534855544f46465f424c4f434b00000000000000000000000000000060648201526000602482015273ffffffffffffffffffffffffffffffffffffffff9091169250639b2ea4bd9150608401600060405180830381600087803b158015612b0c57600080fd5b505af1158015612b20573d6000803e3d6000fd5b5050608080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790555050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c0810182526301312d008152600a6020820152600891810191909152633b9aca006060820152620f424060808201526fffffffffffffffffffffffffffffffff60a082015290565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff16331461115a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610831565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16612d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610831565b61115a600054610100900460ff16612e1a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610831565b61115a33612c72565b60006103e08201905073ffffffffffffffffffffffffffffffffffffffff8087511683528060208801511660208401528060408801511660408401528060608801511660608401528086511660808401528060208701511660a08401528060408701511660c08401528060608701511660e0840152806080870151166101008401525060a0850151612ece61012084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c08581015173ffffffffffffffffffffffffffffffffffffffff90811661014085015285518116610160850152602080870151821661018086015260408088015183166101a087015260608089015184166101c08801526080808a015185166101e089015260a0808b015186166102008a01528a87015186166102208a015260e08b015186166102408a0152895186166102608a0152898501516102808a0152898401516102a08a0152898301516102c08a01528982015167ffffffffffffffff166102e08a01528981015190951661030089015294880151805163ffffffff9081166103208a01529381015160ff9081166103408a015292810151909216610360880152810151821661038087015292830151166103a085015201516fffffffffffffffffffffffffffffffff166103c08301525b95945050505050565b60e0810181811067ffffffffffffffff82111715613056577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405250565b6080810181811067ffffffffffffffff82111715613056577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff8211171561310e577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040525050565b73ffffffffffffffffffffffffffffffffffffffff8116811461263657600080fd5b803561314281613115565b919050565b600060e0828403121561315957600080fd5b6040516131658161300f565b809150823561317381613115565b8152602083013561318381613115565b6020820152604083013561319681613115565b604082015260608301356131a981613115565b606082015260808301356131bc81613115565b608082015260a08301356131cf81613115565b60a08201526131e060c08401613137565b60c08201525092915050565b600061010080838503121561320057600080fd5b6040519081019067ffffffffffffffff8211818310171561324a577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8160405280925061325a84613137565b815261326860208501613137565b602082015261327960408501613137565b604082015261328a60608501613137565b606082015261329b60808501613137565b60808201526132ac60a08501613137565b60a08201526132bd60c08501613137565b60c08201526132ce60e08501613137565b60e0820152505092915050565b803563ffffffff8116811461314257600080fd5b803560ff8116811461314257600080fd5b600060c0828403121561331257600080fd5b60405160c0810181811067ffffffffffffffff8211171561335c577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290508061336b836132db565b8152613379602084016132ef565b602082015261338a604084016132ef565b604082015261339b606084016132db565b60608201526133ac608084016132db565b608082015260a08301356fffffffffffffffffffffffffffffffff811681146133d457600080fd5b60a0919091015292915050565b600061018082840312156133f457600080fd5b6040516134008161300f565b809150823561340e81613115565b80825250602083013560208201526040830135604082015260608301356060820152608083013567ffffffffffffffff8116811461344b57600080fd5b608082015261345c60a08401613137565b60a08201526131e08460c08501613300565b60008183036103e081121561348257600080fd5b60405161348e8161305c565b608082121561349c57600080fd5b60405191506134aa8261305c565b83356134b581613115565b825260208401356134c581613115565b602083015260408401356134d881613115565b604083015260608401356134eb81613115565b60608301528181526135008560808601613147565b60208201526135138561016086016131ec565b60408201526135268561026086016133e1565b6060820152949350505050565b600080828403606081121561354757600080fd5b604081121561355557600080fd5b506040516040810181811067ffffffffffffffff821117156135a0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040908152843582526020808601359083015290925083013580151581146135c757600080fd5b809150509250929050565b6000602082840312156135e457600080fd5b81356135ef81613115565b9392505050565b60005b838110156136115781810151838201526020016135f9565b83811115613620576000848401525b50505050565b6000815180845261363e8160208601602086016135f6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff8086168352808516602084015250606060408301526130066060830184613626565b600060033d11156136c25760046000803e5060005160e01c5b90565b600060443d10156136d35790565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc803d016004833e81513d67ffffffffffffffff816024840111818411171561372157505050505090565b82850191508151818111156137395750505050505090565b843d87010160208285010111156137535750505050505090565b613762602082860101876130a3565b509095945050505050565b6000825161377f8184602087016135f6565b9190910192915050565b7f53797374656d4469637461746f723a20756e6578706563746564206572726f7281527f20696e697469616c697a696e67204c3158444d3a2000000000000000000000006020820152600082516137e78160358501602087016135f6565b9190910160350192915050565b6020815260006135ef6020830184613626565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600060ff821660ff810361384c5761384c613807565b60010192915050565b60208152600061389260208301601a81527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000602082015260400190565b92915050565b6000602082840312156138aa57600080fd5b81516135ef81613115565b6040815260006138f260408301601a81527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000602082015260400190565b905073ffffffffffffffffffffffffffffffffffffffff8316602083015292915050565b73ffffffffffffffffffffffffffffffffffffffff83168152604081016003831061396a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8260208301529392505050565b73ffffffffffffffffffffffffffffffffffffffff821681526040602082015260006135ef60408301601a81527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000602082015260400190565b60006101808201905073ffffffffffffffffffffffffffffffffffffffff808a16835288602084015287604084015286606084015267ffffffffffffffff8616608084015280851660a084015250825463ffffffff80821660c085015260ff8260201c1660e085015260ff8260281c16610100850152808260301c16610120850152613a6a6101408501828460501c1663ffffffff169052565b50607081901c6fffffffffffffffffffffffffffffffff166101608401525098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b604081526000613ad76040830185613626565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613b2d57613b2d613807565b506001019056fe4f564d5f4465636f6d7072657373696f6e507265636f6d70696c65416464726573734f564d5f436861696e53746f72616765436f6e7461696e65722d4354432d626174636865734f564d5f436861696e53746f72616765436f6e7461696e65722d4354432d7175657565a164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101985760003560e01c8063b3f05b97116100e3578063d7efbb301161008c578063f2fde38b11610066578063f2fde38b14610503578063fb5d737614610516578063fe6b1ddf1461051e57600080fd5b8063d7efbb30146104e6578063df4ec249146104f3578063e7c56229146104fb57600080fd5b8063d36ec430116100bd578063d36ec430146104c3578063d40a71fb146104d6578063d4deb3b6146104de57600080fd5b8063b3f05b9714610473578063bc5df61414610487578063cf03c22d1461049a57600080fd5b8063715018a61161014557806389cb73431161011f57806389cb7343146104195780638da5cb5b1461042c5780638f4ed3331461046b57600080fd5b8063715018a61461022857806379502c55146102305780637d1d95a61461041157600080fd5b80634fb4bcec116101765780634fb4bcec146101e95780635bc34f71146101f15780635ce6c3271461020357600080fd5b8063204c881c1461019d578063289c6af7146101c55780634bb278f3146101df575b600080fd5b607e54607f546101ab919082565b604080519283526020830191909152015b60405180910390f35b6101cd600381565b60405160ff90911681526020016101bc565b6101e7610526565b005b6101e7610790565b6080546101cd90610100900460ff1681565b60805461021890640100000000900460ff1681565b60405190151581526020016101bc565b6101e7611148565b604080516080808201835260655473ffffffffffffffffffffffffffffffffffffffff908116835260665481166020808501919091526067548216848601526068548216606080860191909152855160e0808201885260695485168252606a54851682850152606b54851682890152606c54851682840152606d54851682870152606e54851660a080840191909152606f54861660c080850191909152895161010081018b52607054881681526071548816818801526072548816818c01526073548816818701526074548816818a01526075548816818401526076548816818301526077548816818501528a519384018b526078548816845260795484880152607a54848c0152607b5484870152607c5467ffffffffffffffff8116858b01526801000000000000000090049097168383015289518082018b52607d5463ffffffff8082168352640100000000820460ff908116998401999099526501000000000082049098169b82019b909b5266010000000000008b048716958101959095526a01000000000000000000008a04909516968401969096526e0100000000000000000000000000009097046fffffffffffffffffffffffffffffffff1694820194909452908501526104019384565b6040516101bc9493929190612e23565b6101cd600481565b6080546102189062010000900460ff1681565b60335473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b6101e761115c565b608054610218906301000000900460ff1681565b6101e761049536600461346e565b6114cb565b6080546104469065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6101e76104d1366004613533565b611a29565b6101e7611a9c565b6101e7611f7e565b6080546102189060ff1681565b6101e7611fa6565b6101e761256a565b6101e76105113660046135d2565b612582565b6101e7612639565b6101e7612931565b61052e612bf1565b6066546068546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063f2fde38b90602401600060405180830381600087803b15801561059d57600080fd5b505af11580156105b1573d6000803e3d6000fd5b5050608054600461010090910460ff161191506107609050576065546068546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063f2fde38b90602401600060405180830381600087803b15801561063957600080fd5b505af115801561064d573d6000803e3d6000fd5b5050606c546068546040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152911692506313af40359150602401600060405180830381600087803b1580156106c057600080fd5b505af11580156106d4573d6000803e3d6000fd5b5050606e546068546040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169250638f2839709150602401600060405180830381600087803b15801561074757600080fd5b505af115801561075b573d6000803e3d6000fd5b505050505b608080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffff166301000000179055565b610798612bf1565b6080546005906301000000900460ff161561083a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d4469637461746f723a20616c72656164792066696e616c697a6560448201527f640000000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b608054640100000000900460ff16156108af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20616c72656164792065786974656400006044820152606401610831565b60805460ff8281166101009092041614610925576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20696e636f7272656374207374657000006044820152606401610831565b60805462010000900460ff166109bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603c60248201527f53797374656d4469637461746f723a2064796e616d6963206f7261636c65206360448201527f6f6e666967206973206e6f742079657420696e697469616c697a6564000000006064820152608401610831565b606654606954607054607e54607f546040516024810192909252604482015273ffffffffffffffffffffffffffffffffffffffff93841693639623609d938116921690606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fe4a3011600000000000000000000000000000000000000000000000000000000179052517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b168152610ab293929190600401613670565b600060405180830381600087803b158015610acc57600080fd5b505af1158015610ae0573d6000803e3d6000fd5b5050606654606a5460715460805460405160ff9091161515602482015273ffffffffffffffffffffffffffffffffffffffff9384169550639623609d9450918316921690604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd53a822f00000000000000000000000000000000000000000000000000000000179052517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b168152610bd693929190600401613670565b600060405180830381600087803b158015610bf057600080fd5b505af1158015610c04573d6000803e3d6000fd5b5050606654606b546072546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b158015610c8257600080fd5b505af1158015610c96573d6000803e3d6000fd5b5050606b54604080517f8129fc1c000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169350638129fc1c925060048181019260009290919082900301818387803b158015610d0657600080fd5b505af1925050508015610d17575060015b610e7457610d236136a9565b806308c379a003610dea5750610d376136c5565b80610d425750610dec565b7f7a2a4e26842155ea933fe6eb6e3137eb5a296dcdf55721c552be7b4c3cc2375981604051602001610d74919061376d565b604051602081830303815290604052805190602001201481604051602001610d9c9190613789565b60405160208183030381529060405290610de3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083191906137f4565b5050610e74565b505b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f53797374656d4469637461746f723a20756e6578706563746564206572726f7260448201527f20696e697469616c697a696e67204c3158444d20286e6f20726561736f6e29006064820152608401610831565b606654606c546076546040805160048082526024820183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fed88c68e0000000000000000000000000000000000000000000000000000000017905291517f9623609d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff95861695639623609d95610f2a95908216949116929101613670565b600060405180830381600087803b158015610f4457600080fd5b505af1158015610f58573d6000803e3d6000fd5b5050606654606c546073546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b158015610fd657600080fd5b505af1158015610fea573d6000803e3d6000fd5b5050606654606d546074546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec49150604401600060405180830381600087803b15801561106857600080fd5b505af115801561107c573d6000803e3d6000fd5b5050606654606e546075546040517f99a88ec400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831660048201529082166024820152911692506399a88ec491506044015b600060405180830381600087803b1580156110fb57600080fd5b505af115801561110f573d6000803e3d6000fd5b505060808054610100900460ff1692509050600161112c83613836565b91906101000a81548160ff021916908360ff1602179055505050565b611150612bf1565b61115a6000612c72565b565b611164612bf1565b6080546002906301000000900460ff1615611201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d4469637461746f723a20616c72656164792066696e616c697a6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610831565b608054640100000000900460ff1615611276576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20616c72656164792065786974656400006044820152606401610831565b60805460ff82811661010090920416146112ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20696e636f7272656374207374657000006044820152606401610831565b6065546040517fbf40fac100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac19061134090600401613855565b602060405180830381865afa15801561135d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113819190613898565b608080547fffffffffffffff0000000000000000000000000000000000000000ffffffffff166501000000000073ffffffffffffffffffffffffffffffffffffffff938416021790556065546040517f9b2ea4bd000000000000000000000000000000000000000000000000000000008152911690639b2ea4bd9061140b906000906004016138b5565b600060405180830381600087803b15801561142557600080fd5b505af1158015611439573d6000803e3d6000fd5b5050606554604080517f9b2ea4bd0000000000000000000000000000000000000000000000000000000081526004810191909152601160448201527f44544c5f534855544f46465f424c4f434b000000000000000000000000000000606482015273ffffffffffffffffffffffffffffffffffffffff43811660248301529091169250639b2ea4bd91506084016110e1565b600054610100900460ff16158080156114eb5750600054600160ff909116105b806115055750303b158015611505575060005460ff166001145b611591576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610831565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156115ef57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b81518051606580547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161790915560208084015160668054841691851691909117905560408085015160678054851691861691909117905560609485015160688054851691861691909117905581870151805160698054861691871691909117905580830151606a8054861691871691909117905580820151606b8054861691871691909117905580860151606c80548616918716919091179055608080820151606d8054871691881691909117905560a080830151606e8054881691891691909117905560c092830151606f80548816918916919091179055838a01518051607080548916918a1691909117905580860151607180548916918a1691909117905580850151607280548916918a1691909117905580890151607380548916918a1691909117905580830151607480548916918a1691909117905580820151607580548916918a1691909117905580840151607680548916918a1691909117905560e00151607780548816918916919091179055878a0151805160788054909816908916179096558585015160795585840151607a5585880151607b5585820151607c80548884015167ffffffffffffffff9093167fffffffff0000000000000000000000000000000000000000000000000000000090911617680100000000000000009290991691909102979097179096559301518051607d805494830151938301519783015183870151939097015163ffffffff9283167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009096169590951764010000000060ff95861602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000094909816939093027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1696909617660100000000000095871695909502949094177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000095909416949094027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff909316929092029190911790915580546101007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff9091161790556119a0612ce9565b6067546119c29073ffffffffffffffffffffffffffffffffffffffff16612c72565b8015611a2557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b611a31612bf1565b8151607e55602090910151607f55608080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff009092169190911762010000179055565b611aa4612bf1565b6080546001906301000000900460ff1615611b41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d4469637461746f723a20616c72656164792066696e616c697a6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610831565b608054640100000000900460ff1615611bb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20616c72656164792065786974656400006044820152606401610831565b60805460ff8281166101009092041614611c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20696e636f7272656374207374657000006044820152606401610831565b6066546065546040517f0652b57a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152911690630652b57a90602401600060405180830381600087803b158015611c9b57600080fd5b505af1158015611caf573d6000803e3d6000fd5b5050606654606b546040517f8d52d4a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450638d52d4a09350611d119290911690600290600401613916565b600060405180830381600087803b158015611d2b57600080fd5b505af1158015611d3f573d6000803e3d6000fd5b5050606654606b546040517f860f7cda00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff928316945063860f7cda9350611d9e9290911690600401613977565b600060405180830381600087803b158015611db857600080fd5b505af1158015611dcc573d6000803e3d6000fd5b5050606654606c546040517f8d52d4a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450638d52d4a09350611e2e9290911690600190600401613916565b600060405180830381600087803b158015611e4857600080fd5b505af1158015611e5c573d6000803e3d6000fd5b5050606654606f54607754607854607954607a54607b54607c5460405173ffffffffffffffffffffffffffffffffffffffff9889169a50639623609d99509688169795861696611ecf969586169567ffffffffffffffff8316926801000000000000000090041690607d906024016139d0565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff975e92500000000000000000000000000000000000000000000000000000000179052517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526110e193929190600401613670565b611f86612bf1565b611f8e611fa6565b611f96612639565b611f9e610790565b61115a610526565b611fae612bf1565b6080546003906301000000900460ff161561204b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d4469637461746f723a20616c72656164792066696e616c697a6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610831565b608054640100000000900460ff16156120c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20616c72656164792065786974656400006044820152606401610831565b60805460ff8281166101009092041614612136576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20696e636f7272656374207374657000006044820152606401610831565b60006040518061022001604052806040518060400160405280601d81526020017f4f564d5f43616e6f6e6963616c5472616e73616374696f6e436861696e00000081525081526020016040518060400160405280601a81526020017f4f564d5f4c3243726f7373446f6d61696e4d657373656e6765720000000000008152508152602001604051806060016040528060228152602001613b356022913981526020016040518060400160405280600d81526020017f4f564d5f53657175656e6365720000000000000000000000000000000000000081525081526020016040518060400160405280600c81526020017f4f564d5f50726f706f73657200000000000000000000000000000000000000008152508152602001604051806060016040528060258152602001613b57602591398152602001604051806060016040528060238152602001613b7c602391398152604080518082018252601d81527f4f564d5f43616e6f6e6963616c5472616e73616374696f6e436861696e0000006020828101919091528084019190915281518083018352601881527f4f564d5f5374617465436f6d6d69746d656e74436861696e0000000000000000818301528284015281518083018352600f81527f4f564d5f426f6e644d616e61676572000000000000000000000000000000000081830152606084015281518083018352601481527f4f564d5f457865637574696f6e4d616e616765720000000000000000000000008183015260808401528151808301835260118082527f4f564d5f467261756456657269666965720000000000000000000000000000008284015260a085019190915282518084018452601781527f4f564d5f53746174654d616e61676572466163746f72790000000000000000008184015260c085015282518084018452601c81527f4f564d5f53746174655472616e736974696f6e6572466163746f7279000000008184015260e0850152825180840184529081527f4f564d5f536166657479436865636b65720000000000000000000000000000008183015261010084015281518083018352601981527f4f564d5f4c314d756c74694d65737361676552656c6179657200000000000000818301526101208401528151808301909252600b82527f426f6e644d616e616765720000000000000000000000000000000000000000009082015261014090910152905060005b60118110156125505760655473ffffffffffffffffffffffffffffffffffffffff16639b2ea4bd8383601181106124e7576124e7613a95565b602002015160006040518363ffffffff1660e01b815260040161250b929190613ac4565b600060405180830381600087803b15801561252557600080fd5b505af1158015612539573d6000803e3d6000fd5b50505050808061254890613afc565b9150506124ae565b505060808054610100900460ff1690600161112c83613836565b612572612bf1565b61257a611a9c565b61115a61115c565b61258a612bf1565b73ffffffffffffffffffffffffffffffffffffffff811661262d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610831565b61263681612c72565b50565b612641612bf1565b6080546004906301000000900460ff16156126de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d4469637461746f723a20616c72656164792066696e616c697a6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610831565b608054640100000000900460ff1615612753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20616c72656164792065786974656400006044820152606401610831565b60805460ff82811661010090920416146127c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f53797374656d4469637461746f723a20696e636f7272656374207374657000006044820152606401610831565b6065546066546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063f2fde38b90602401600060405180830381600087803b15801561283857600080fd5b505af115801561284c573d6000803e3d6000fd5b5050606c546066546040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152911692506313af40359150602401600060405180830381600087803b1580156128bf57600080fd5b505af11580156128d3573d6000803e3d6000fd5b5050606e546066546040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169250638f28397091506024016110e1565b612939612bf1565b608054610100900460ff166003146129d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f53797374656d4469637461746f723a2063616e206f6e6c79206578697431206260448201527f65666f72652073746570203320697320657865637574656400000000000000006064820152608401610831565b6065546080546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff92831692639b2ea4bd92612a389265010000000000909104909116906004016138b5565b600060405180830381600087803b158015612a5257600080fd5b505af1158015612a66573d6000803e3d6000fd5b5050606554604080517f9b2ea4bd0000000000000000000000000000000000000000000000000000000081526004810191909152601160448201527f44544c5f534855544f46465f424c4f434b00000000000000000000000000000060648201526000602482015273ffffffffffffffffffffffffffffffffffffffff9091169250639b2ea4bd9150608401600060405180830381600087803b158015612b0c57600080fd5b505af1158015612b20573d6000803e3d6000fd5b5050608080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790555050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c0810182526301312d008152600a6020820152600891810191909152633b9aca006060820152620f424060808201526fffffffffffffffffffffffffffffffff60a082015290565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff16331461115a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610831565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16612d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610831565b61115a600054610100900460ff16612e1a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610831565b61115a33612c72565b60006103e08201905073ffffffffffffffffffffffffffffffffffffffff8087511683528060208801511660208401528060408801511660408401528060608801511660608401528086511660808401528060208701511660a08401528060408701511660c08401528060608701511660e0840152806080870151166101008401525060a0850151612ece61012084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c08581015173ffffffffffffffffffffffffffffffffffffffff90811661014085015285518116610160850152602080870151821661018086015260408088015183166101a087015260608089015184166101c08801526080808a015185166101e089015260a0808b015186166102008a01528a87015186166102208a015260e08b015186166102408a0152895186166102608a0152898501516102808a0152898401516102a08a0152898301516102c08a01528982015167ffffffffffffffff166102e08a01528981015190951661030089015294880151805163ffffffff9081166103208a01529381015160ff9081166103408a015292810151909216610360880152810151821661038087015292830151166103a085015201516fffffffffffffffffffffffffffffffff166103c08301525b95945050505050565b60e0810181811067ffffffffffffffff82111715613056577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405250565b6080810181811067ffffffffffffffff82111715613056577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff8211171561310e577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040525050565b73ffffffffffffffffffffffffffffffffffffffff8116811461263657600080fd5b803561314281613115565b919050565b600060e0828403121561315957600080fd5b6040516131658161300f565b809150823561317381613115565b8152602083013561318381613115565b6020820152604083013561319681613115565b604082015260608301356131a981613115565b606082015260808301356131bc81613115565b608082015260a08301356131cf81613115565b60a08201526131e060c08401613137565b60c08201525092915050565b600061010080838503121561320057600080fd5b6040519081019067ffffffffffffffff8211818310171561324a577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8160405280925061325a84613137565b815261326860208501613137565b602082015261327960408501613137565b604082015261328a60608501613137565b606082015261329b60808501613137565b60808201526132ac60a08501613137565b60a08201526132bd60c08501613137565b60c08201526132ce60e08501613137565b60e0820152505092915050565b803563ffffffff8116811461314257600080fd5b803560ff8116811461314257600080fd5b600060c0828403121561331257600080fd5b60405160c0810181811067ffffffffffffffff8211171561335c577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290508061336b836132db565b8152613379602084016132ef565b602082015261338a604084016132ef565b604082015261339b606084016132db565b60608201526133ac608084016132db565b608082015260a08301356fffffffffffffffffffffffffffffffff811681146133d457600080fd5b60a0919091015292915050565b600061018082840312156133f457600080fd5b6040516134008161300f565b809150823561340e81613115565b80825250602083013560208201526040830135604082015260608301356060820152608083013567ffffffffffffffff8116811461344b57600080fd5b608082015261345c60a08401613137565b60a08201526131e08460c08501613300565b60008183036103e081121561348257600080fd5b60405161348e8161305c565b608082121561349c57600080fd5b60405191506134aa8261305c565b83356134b581613115565b825260208401356134c581613115565b602083015260408401356134d881613115565b604083015260608401356134eb81613115565b60608301528181526135008560808601613147565b60208201526135138561016086016131ec565b60408201526135268561026086016133e1565b6060820152949350505050565b600080828403606081121561354757600080fd5b604081121561355557600080fd5b506040516040810181811067ffffffffffffffff821117156135a0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040908152843582526020808601359083015290925083013580151581146135c757600080fd5b809150509250929050565b6000602082840312156135e457600080fd5b81356135ef81613115565b9392505050565b60005b838110156136115781810151838201526020016135f9565b83811115613620576000848401525b50505050565b6000815180845261363e8160208601602086016135f6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600073ffffffffffffffffffffffffffffffffffffffff8086168352808516602084015250606060408301526130066060830184613626565b600060033d11156136c25760046000803e5060005160e01c5b90565b600060443d10156136d35790565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc803d016004833e81513d67ffffffffffffffff816024840111818411171561372157505050505090565b82850191508151818111156137395750505050505090565b843d87010160208285010111156137535750505050505090565b613762602082860101876130a3565b509095945050505050565b6000825161377f8184602087016135f6565b9190910192915050565b7f53797374656d4469637461746f723a20756e6578706563746564206572726f7281527f20696e697469616c697a696e67204c3158444d3a2000000000000000000000006020820152600082516137e78160358501602087016135f6565b9190910160350192915050565b6020815260006135ef6020830184613626565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600060ff821660ff810361384c5761384c613807565b60010192915050565b60208152600061389260208301601a81527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000602082015260400190565b92915050565b6000602082840312156138aa57600080fd5b81516135ef81613115565b6040815260006138f260408301601a81527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000602082015260400190565b905073ffffffffffffffffffffffffffffffffffffffff8316602083015292915050565b73ffffffffffffffffffffffffffffffffffffffff83168152604081016003831061396a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8260208301529392505050565b73ffffffffffffffffffffffffffffffffffffffff821681526040602082015260006135ef60408301601a81527f4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000602082015260400190565b60006101808201905073ffffffffffffffffffffffffffffffffffffffff808a16835288602084015287604084015286606084015267ffffffffffffffff8616608084015280851660a084015250825463ffffffff80821660c085015260ff8260201c1660e085015260ff8260281c16610100850152808260301c16610120850152613a6a6101408501828460501c1663ffffffff169052565b50607081901c6fffffffffffffffffffffffffffffffff166101608401525098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b604081526000613ad76040830185613626565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613b2d57613b2d613807565b506001019056fe4f564d5f4465636f6d7072657373696f6e507265636f6d70696c65416464726573734f564d5f436861696e53746f72616765436f6e7461696e65722d4354432d626174636865734f564d5f436861696e53746f72616765436f6e7461696e65722d4354432d7175657565a164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "initialize(((address,address,address,address),(address,address,address,address,address,address,address),(address,address,address,address,address,address,address,address),(address,uint256,uint256,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128))))": { - "params": { - "_config": "System configuration." - } - }, - "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." - }, - "updateDynamicConfig((uint256,uint256),bool)": { - "params": { - "_l2OutputOracleDynamicConfig": "Dynamic L2OutputOracle config.", - "_optimismPortalDynamicConfig": "Dynamic OptimismPortal config." - } - } - }, - "title": "SystemDictator" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "EXIT_1_NO_RETURN_STEP()": { - "notice": "Step after which exit 1 can no longer be used." - }, - "PROXY_TRANSFER_STEP()": { - "notice": "Step where proxy ownership is transferred." - }, - "config()": { - "notice": "System configuration." - }, - "constructor": { - "notice": "Constructor required to ensure that the implementation of the SystemDictator is initialized upon deployment." - }, - "currentStep()": { - "notice": "Current step;" - }, - "dynamicConfigSet()": { - "notice": "Whether or not dynamic config has been set." - }, - "exit1()": { - "notice": "First exit point, can only be called before step 3 is executed." - }, - "exited()": { - "notice": "Whether or not the deployment has been exited." - }, - "finalize()": { - "notice": "Tranfers admin ownership to the final owner." - }, - "finalized()": { - "notice": "Whether or not the deployment is finalized." - }, - "l2OutputOracleDynamicConfig()": { - "notice": "Dynamic configuration for the L2OutputOracle." - }, - "oldL1CrossDomainMessenger()": { - "notice": "Address of the old L1CrossDomainMessenger implementation." - }, - "optimismPortalDynamicConfig()": { - "notice": "Dynamic configuration for the OptimismPortal. Determines if the system should be paused when initialized." - }, - "phase1()": { - "notice": "Calls the first 2 steps of the migration process." - }, - "phase2()": { - "notice": "Calls the remaining steps of the migration process, and finalizes." - }, - "step1()": { - "notice": "Configures the ProxyAdmin contract." - }, - "step2()": { - "notice": "Pauses the system by shutting down the L1CrossDomainMessenger and setting the deposit halt flag to tell the Sequencer's DTL to stop accepting deposits." - }, - "step3()": { - "notice": "Removes deprecated addresses from the AddressManager." - }, - "step4()": { - "notice": "Transfers system ownership to the ProxyAdmin." - }, - "step5()": { - "notice": "Upgrades and initializes proxy contracts." - }, - "updateDynamicConfig((uint256,uint256),bool)": { - "notice": "Allows the owner to update dynamic config." - } - }, - "notice": "The SystemDictator is responsible for coordinating the deployment of a full Bedrock system. The SystemDictator is designed to support both fresh network deployments and upgrades to existing pre-Bedrock systems." - }, - "storageLayout": { - "storage": [ - { - "astId": 52671, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 52674, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 53099, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 52543, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 52663, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 4322, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "config", - "offset": 0, - "slot": "101", - "type": "t_struct(DeployConfig)4310_storage" - }, - { - "astId": 4326, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l2OutputOracleDynamicConfig", - "offset": 0, - "slot": "126", - "type": "t_struct(L2OutputOracleDynamicConfig)4281_storage" - }, - { - "astId": 4329, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "optimismPortalDynamicConfig", - "offset": 0, - "slot": "128", - "type": "t_bool" - }, - { - "astId": 4332, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "currentStep", - "offset": 1, - "slot": "128", - "type": "t_uint8" - }, - { - "astId": 4335, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "dynamicConfigSet", - "offset": 2, - "slot": "128", - "type": "t_bool" - }, - { - "astId": 4338, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "finalized", - "offset": 3, - "slot": "128", - "type": "t_bool" - }, - { - "astId": 4341, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "exited", - "offset": 4, - "slot": "128", - "type": "t_bool" - }, - { - "astId": 4344, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "oldL1CrossDomainMessenger", - "offset": 5, - "slot": "128", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_array(t_uint256)50_storage": { - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(AddressManager)7678": { - "encoding": "inplace", - "label": "contract AddressManager", - "numberOfBytes": "20" - }, - "t_contract(L1CrossDomainMessenger)125": { - "encoding": "inplace", - "label": "contract L1CrossDomainMessenger", - "numberOfBytes": "20" - }, - "t_contract(L1ERC721Bridge)325": { - "encoding": "inplace", - "label": "contract L1ERC721Bridge", - "numberOfBytes": "20" - }, - "t_contract(L1StandardBridge)772": { - "encoding": "inplace", - "label": "contract L1StandardBridge", - "numberOfBytes": "20" - }, - "t_contract(L2OutputOracle)1233": { - "encoding": "inplace", - "label": "contract L2OutputOracle", - "numberOfBytes": "20" - }, - "t_contract(OptimismMintableERC20Factory)50636": { - "encoding": "inplace", - "label": "contract OptimismMintableERC20Factory", - "numberOfBytes": "20" - }, - "t_contract(OptimismPortal)1912": { - "encoding": "inplace", - "label": "contract OptimismPortal", - "numberOfBytes": "20" - }, - "t_contract(PortalSender)4190": { - "encoding": "inplace", - "label": "contract PortalSender", - "numberOfBytes": "20" - }, - "t_contract(ProxyAdmin)51686": { - "encoding": "inplace", - "label": "contract ProxyAdmin", - "numberOfBytes": "20" - }, - "t_contract(SystemConfig)2672": { - "encoding": "inplace", - "label": "contract SystemConfig", - "numberOfBytes": "20" - }, - "t_struct(DeployConfig)4310_storage": { - "encoding": "inplace", - "label": "struct SystemDictator.DeployConfig", - "numberOfBytes": "800", - "members": [ - { - "astId": 4300, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "globalConfig", - "offset": 0, - "slot": "0", - "type": "t_struct(GlobalConfig)4236_storage" - }, - { - "astId": 4303, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "proxyAddressConfig", - "offset": 0, - "slot": "4", - "type": "t_struct(ProxyAddressConfig)4251_storage" - }, - { - "astId": 4306, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "implementationAddressConfig", - "offset": 0, - "slot": "11", - "type": "t_struct(ImplementationAddressConfig)4276_storage" - }, - { - "astId": 4309, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "systemConfigConfig", - "offset": 0, - "slot": "19", - "type": "t_struct(SystemConfigConfig)4297_storage" - } - ] - }, - "t_struct(GlobalConfig)4236_storage": { - "encoding": "inplace", - "label": "struct SystemDictator.GlobalConfig", - "numberOfBytes": "128", - "members": [ - { - "astId": 4228, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "addressManager", - "offset": 0, - "slot": "0", - "type": "t_contract(AddressManager)7678" - }, - { - "astId": 4231, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "proxyAdmin", - "offset": 0, - "slot": "1", - "type": "t_contract(ProxyAdmin)51686" - }, - { - "astId": 4233, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "controller", - "offset": 0, - "slot": "2", - "type": "t_address" - }, - { - "astId": 4235, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "finalOwner", - "offset": 0, - "slot": "3", - "type": "t_address" - } - ] - }, - "t_struct(ImplementationAddressConfig)4276_storage": { - "encoding": "inplace", - "label": "struct SystemDictator.ImplementationAddressConfig", - "numberOfBytes": "256", - "members": [ - { - "astId": 4254, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l2OutputOracleImpl", - "offset": 0, - "slot": "0", - "type": "t_contract(L2OutputOracle)1233" - }, - { - "astId": 4257, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "optimismPortalImpl", - "offset": 0, - "slot": "1", - "type": "t_contract(OptimismPortal)1912" - }, - { - "astId": 4260, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l1CrossDomainMessengerImpl", - "offset": 0, - "slot": "2", - "type": "t_contract(L1CrossDomainMessenger)125" - }, - { - "astId": 4263, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l1StandardBridgeImpl", - "offset": 0, - "slot": "3", - "type": "t_contract(L1StandardBridge)772" - }, - { - "astId": 4266, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "optimismMintableERC20FactoryImpl", - "offset": 0, - "slot": "4", - "type": "t_contract(OptimismMintableERC20Factory)50636" - }, - { - "astId": 4269, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l1ERC721BridgeImpl", - "offset": 0, - "slot": "5", - "type": "t_contract(L1ERC721Bridge)325" - }, - { - "astId": 4272, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "portalSenderImpl", - "offset": 0, - "slot": "6", - "type": "t_contract(PortalSender)4190" - }, - { - "astId": 4275, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "systemConfigImpl", - "offset": 0, - "slot": "7", - "type": "t_contract(SystemConfig)2672" - } - ] - }, - "t_struct(L2OutputOracleDynamicConfig)4281_storage": { - "encoding": "inplace", - "label": "struct SystemDictator.L2OutputOracleDynamicConfig", - "numberOfBytes": "64", - "members": [ - { - "astId": 4278, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l2OutputOracleStartingBlockNumber", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 4280, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l2OutputOracleStartingTimestamp", - "offset": 0, - "slot": "1", - "type": "t_uint256" - } - ] - }, - "t_struct(ProxyAddressConfig)4251_storage": { - "encoding": "inplace", - "label": "struct SystemDictator.ProxyAddressConfig", - "numberOfBytes": "224", - "members": [ - { - "astId": 4238, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l2OutputOracleProxy", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 4240, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "optimismPortalProxy", - "offset": 0, - "slot": "1", - "type": "t_address" - }, - { - "astId": 4242, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l1CrossDomainMessengerProxy", - "offset": 0, - "slot": "2", - "type": "t_address" - }, - { - "astId": 4244, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l1StandardBridgeProxy", - "offset": 0, - "slot": "3", - "type": "t_address" - }, - { - "astId": 4246, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "optimismMintableERC20FactoryProxy", - "offset": 0, - "slot": "4", - "type": "t_address" - }, - { - "astId": 4248, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "l1ERC721BridgeProxy", - "offset": 0, - "slot": "5", - "type": "t_address" - }, - { - "astId": 4250, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "systemConfigProxy", - "offset": 0, - "slot": "6", - "type": "t_address" - } - ] - }, - "t_struct(ResourceConfig)1945_storage": { - "encoding": "inplace", - "label": "struct ResourceMetering.ResourceConfig", - "numberOfBytes": "32", - "members": [ - { - "astId": 1934, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "maxResourceLimit", - "offset": 0, - "slot": "0", - "type": "t_uint32" - }, - { - "astId": 1936, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "elasticityMultiplier", - "offset": 4, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 1938, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "baseFeeMaxChangeDenominator", - "offset": 5, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 1940, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "minimumBaseFee", - "offset": 6, - "slot": "0", - "type": "t_uint32" - }, - { - "astId": 1942, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "systemTxMaxGas", - "offset": 10, - "slot": "0", - "type": "t_uint32" - }, - { - "astId": 1944, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "maximumBaseFee", - "offset": 14, - "slot": "0", - "type": "t_uint128" - } - ] - }, - "t_struct(SystemConfigConfig)4297_storage": { - "encoding": "inplace", - "label": "struct SystemDictator.SystemConfigConfig", - "numberOfBytes": "192", - "members": [ - { - "astId": 4283, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "owner", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 4285, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "overhead", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 4287, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "scalar", - "offset": 0, - "slot": "2", - "type": "t_uint256" - }, - { - "astId": 4289, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "batcherHash", - "offset": 0, - "slot": "3", - "type": "t_bytes32" - }, - { - "astId": 4291, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "gasLimit", - "offset": 0, - "slot": "4", - "type": "t_uint64" - }, - { - "astId": 4293, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "unsafeBlockSigner", - "offset": 8, - "slot": "4", - "type": "t_address" - }, - { - "astId": 4296, - "contract": "contracts/deployment/SystemDictator.sol:SystemDictator", - "label": "resourceConfig", - "offset": 0, - "slot": "5", - "type": "t_struct(ResourceConfig)1945_storage" - } - ] - }, - "t_uint128": { - "encoding": "inplace", - "label": "uint128", - "numberOfBytes": "16" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint32": { - "encoding": "inplace", - "label": "uint32", - "numberOfBytes": "4" - }, - "t_uint64": { - "encoding": "inplace", - "label": "uint64", - "numberOfBytes": "8" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/SystemDictatorProxy.json b/packages/contracts-bedrock/deployments/mainnet/SystemDictatorProxy.json deleted file mode 100644 index e7b927edfa0a..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/SystemDictatorProxy.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "address": "0xB4453CEb33d2e67FA244A24acf2E50CEF31F53cB", - "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": "0x459dd62834451eddd153403a761496e35d35c842ac4c4bcc480fa87573636607", - "receipt": { - "to": null, - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "contractAddress": "0xB4453CEb33d2e67FA244A24acf2E50CEF31F53cB", - "transactionIndex": 90, - "gasUsed": "523960", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200800000000000000000000000000000000000000000000000008000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x9b2a75b95bdd1b95733c9b104eb82d4be0495755dc2ae9b100f6760e83d2bb5d", - "transactionHash": "0x459dd62834451eddd153403a761496e35d35c842ac4c4bcc480fa87573636607", - "logs": [ - { - "transactionIndex": 90, - "blockNumber": 17365805, - "transactionHash": "0x459dd62834451eddd153403a761496e35d35c842ac4c4bcc480fa87573636607", - "address": "0xB4453CEb33d2e67FA244A24acf2E50CEF31F53cB", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000354f3f4ecdca5e0a7ace08d71348cdc1dab48960", - "logIndex": 267, - "blockHash": "0x9b2a75b95bdd1b95733c9b104eb82d4be0495755dc2ae9b100f6760e83d2bb5d" - } - ], - "blockNumber": 17365805, - "cumulativeGasUsed": "9446906", - "status": 1, - "byzantium": true - }, - "args": [ - "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960" - ], - "numDeployments": 1, - "solcInputHash": "13ac93d026822f719ad110af836d1582", - "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\":{\"contracts/universal/Proxy.sol\":\"Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@cwia/=node_modules/clones-with-immutable-args/src/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":clones-with-immutable-args/=node_modules/clones-with-immutable-args/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/universal/Proxy.sol\":{\"keccak256\":\"0x64d67f1936d97c87a2e42317eb162744ad5cefdc9bc8b1138ee4afe2886eb885\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://33b903585eb9cfc60a70bcdf4ee44220b173caff16dfb9071cd0668c7a551265\",\"dweb:/ipfs/QmXHUZ9brinN1WS9i63ocRQsQidY96WePDBhBsFRhDmVjr\"]}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "admin()": { - "returns": { - "_0": "Owner address." - } - }, - "changeAdmin(address)": { - "params": { - "_admin": "New owner of the proxy contract." - } - }, - "constructor": { - "params": { - "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "Address of the implementation contract." - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "Calldata to delegatecall the new implementation with.", - "_implementation": "Address of the implementation contract." - } - } - }, - "events": { - "AdminChanged(address,address)": { - "params": { - "newAdmin": "The new owner of the contract", - "previousAdmin": "The previous owner of the contract" - } - }, - "Upgraded(address)": { - "params": { - "implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "admin()": { - "notice": "Gets the owner of the proxy contract." - }, - "changeAdmin(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "constructor": { - "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." - }, - "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." - } - }, - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." - } - }, - "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/TeleportrWithdrawer.json b/packages/contracts-bedrock/deployments/mainnet/TeleportrWithdrawer.json deleted file mode 100644 index 3681aea4c38e..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/TeleportrWithdrawer.json +++ /dev/null @@ -1,655 +0,0 @@ -{ - "address": "0x78A25524D90E3D0596558fb43789bD800a5c3007", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ReceivedETH", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrewERC20", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "WithdrewERC721", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrewETH", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_gas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "CALL", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_gas", - "type": "uint256" - } - ], - "name": "DELEGATECALL", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "data", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "recipient", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "setData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "setOwner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "name": "setRecipient", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_teleportr", - "type": "address" - } - ], - "name": "setTeleportr", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "teleportr", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC20", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC20", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC721", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "withdrawERC721", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdrawETH", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - } - ], - "name": "withdrawETH", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawFromTeleportr", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0xe7914c509af8b99ef3421601b487ccdf2c7ef5955ffbd58bbb7d786452df3638", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xc37f6a6c4AB335E20d10F034B90386E2fb70bbF5", - "contractAddress": null, - "transactionIndex": 249, - "gasUsed": "1233027", - "logsBloom": "0x00000000000000000001000000000000000000000000000000000000000000000000100000000000000000000000080000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000080000000020000000000000000000800000000000080000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000004000000020000000000000000000000000000000000000000000000", - "blockHash": "0xbdb85532b8a9423604350b1254f5b465838c92bffaecd1768cf94b95e58ffa80", - "transactionHash": "0xe7914c509af8b99ef3421601b487ccdf2c7ef5955ffbd58bbb7d786452df3638", - "logs": [ - { - "transactionIndex": 249, - "blockNumber": 14981055, - "transactionHash": "0xe7914c509af8b99ef3421601b487ccdf2c7ef5955ffbd58bbb7d786452df3638", - "address": "0x78A25524D90E3D0596558fb43789bD800a5c3007", - "topics": [ - "0x8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58" - ], - "data": "0x", - "logIndex": 574, - "blockHash": "0xbdb85532b8a9423604350b1254f5b465838c92bffaecd1768cf94b95e58ffa80" - } - ], - "blockNumber": 14981055, - "cumulativeGasUsed": "26253070", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "b09909e91a3ff9823ceba49a3a845230", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ReceivedETH\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrewERC20\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"WithdrewERC721\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrewETH\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_gas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"CALL\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_gas\",\"type\":\"uint256\"}],\"name\":\"DELEGATECALL\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"data\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"recipient\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"setData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"setRecipient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_teleportr\",\"type\":\"address\"}],\"name\":\"setTeleportr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"teleportr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"withdrawERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC721\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"withdrawERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"withdrawETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFromTeleportr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"CALL(address,bytes,uint256,uint256)\":{\"params\":{\"_data\":\"Data to send with the call.\",\"_gas\":\"Amount of gas to send with the call.\",\"_target\":\"Address to call.\",\"_value\":\"ETH value to send with the call.\"},\"returns\":{\"_0\":\"Boolean success value.\",\"_1\":\"Bytes data returned by the call.\"}},\"DELEGATECALL(address,bytes,uint256)\":{\"params\":{\"_data\":\"Data to send with the call.\",\"_gas\":\"Amount of gas to send with the call.\",\"_target\":\"Address to call.\"},\"returns\":{\"_0\":\"Boolean success value.\",\"_1\":\"Bytes data returned by the call.\"}},\"constructor\":{\"params\":{\"_owner\":\"Initial owner of the contract.\"}},\"setData(bytes)\":{\"params\":{\"_data\":\"New data to be sent to the recipient address.\"}},\"setRecipient(address)\":{\"params\":{\"_recipient\":\"New recipient address.\"}},\"setTeleportr(address)\":{\"params\":{\"_teleportr\":\"New Teleportr contract address.\"}},\"withdrawERC20(address,address)\":{\"params\":{\"_asset\":\"ERC20 token to withdraw.\",\"_to\":\"Address to receive the ERC20 balance.\"}},\"withdrawERC20(address,address,uint256)\":{\"params\":{\"_amount\":\"Amount of ERC20 to withdraw.\",\"_asset\":\"ERC20 token to withdraw.\",\"_to\":\"Address to receive the ERC20 balance.\"}},\"withdrawERC721(address,address,uint256)\":{\"params\":{\"_asset\":\"ERC721 token to withdraw.\",\"_id\":\"Token ID of the ERC721 token to withdraw.\",\"_to\":\"Address to receive the ERC721 token.\"}},\"withdrawETH(address)\":{\"params\":{\"_to\":\"Address to receive the ETH balance.\"}},\"withdrawETH(address,uint256)\":{\"params\":{\"_amount\":\"Amount of ETH to withdraw.\",\"_to\":\"Address to receive the ETH balance.\"}}},\"title\":\"TeleportrWithdrawer\",\"version\":1},\"userdoc\":{\"events\":{\"ReceivedETH(address,uint256)\":{\"notice\":\"Emitted when ETH is received by this address.\"},\"WithdrewERC20(address,address,address,uint256)\":{\"notice\":\"Emitted when ERC20 tokens are withdrawn from this address.\"},\"WithdrewERC721(address,address,address,uint256)\":{\"notice\":\"Emitted when ERC721 tokens are withdrawn from this address.\"},\"WithdrewETH(address,address,uint256)\":{\"notice\":\"Emitted when ETH is withdrawn from this address.\"}},\"kind\":\"user\",\"methods\":{\"CALL(address,bytes,uint256,uint256)\":{\"notice\":\"Sends a CALL to a target address.\"},\"DELEGATECALL(address,bytes,uint256)\":{\"notice\":\"Sends a DELEGATECALL to a target address.\"},\"data()\":{\"notice\":\"Data to be sent to the recipient address.\"},\"recipient()\":{\"notice\":\"Address that will receive Teleportr withdrawals.\"},\"setData(bytes)\":{\"notice\":\"Allows the owner to update the data to be sent to the recipient address.\"},\"setRecipient(address)\":{\"notice\":\"Allows the owner to update the recipient address.\"},\"setTeleportr(address)\":{\"notice\":\"Allows the owner to update the Teleportr contract address.\"},\"teleportr()\":{\"notice\":\"Address of the Teleportr contract.\"},\"withdrawERC20(address,address)\":{\"notice\":\"Withdraws full ERC20 balance to the recipient.\"},\"withdrawERC20(address,address,uint256)\":{\"notice\":\"Withdraws partial ERC20 balance to the recipient.\"},\"withdrawERC721(address,address,uint256)\":{\"notice\":\"Withdraws ERC721 token to the recipient.\"},\"withdrawETH(address)\":{\"notice\":\"Withdraws full ETH balance to the recipient.\"},\"withdrawETH(address,uint256)\":{\"notice\":\"Withdraws partial ETH balance to the recipient.\"},\"withdrawFromTeleportr()\":{\"notice\":\"Withdraws the full balance of the Teleportr contract to the recipient address. Anyone is allowed to trigger this function since the recipient address cannot be controlled by the msg.sender.\"}},\"notice\":\"The TeleportrWithdrawer is a simple contract capable of withdrawing funds from the TeleportrContract and sending them to some recipient address.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/TeleportrWithdrawer.sol\":\"TeleportrWithdrawer\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x7e91c80b0dd1a14a19cb9e661b99924043adab6d9d893bbfcf3a6a3dc23a6743\",\"license\":\"AGPL-3.0-only\"},\"@rari-capital/solmate/src/tokens/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\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\",\"keccak256\":\"0x0240f7703cff32a61ee3e9fbb339e09a944260432a9ef37debf3692b1a6c8049\",\"license\":\"AGPL-3.0-only\"},\"@rari-capital/solmate/src/tokens/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\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 require(\\n to.code.length == 0 ||\\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 require(\\n to.code.length == 0 ||\\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 require(\\n to.code.length == 0 ||\\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 require(\\n to.code.length == 0 ||\\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\",\"keccak256\":\"0xb59c7c25eca386f39da4819a9f70f89b73b7583d5f5127a83ffe5339800b1183\",\"license\":\"AGPL-3.0-only\"},\"contracts/universal/AssetReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\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 * Emitted when ETH is received by this address.\\n */\\n event ReceivedETH(address indexed from, uint256 amount);\\n\\n /**\\n * Emitted when ETH is withdrawn from this address.\\n */\\n event WithdrewETH(address indexed withdrawer, address indexed recipient, uint256 amount);\\n\\n /**\\n * Emitted when ERC20 tokens are withdrawn from this address.\\n */\\n event WithdrewERC20(\\n address indexed withdrawer,\\n address indexed recipient,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /**\\n * Emitted when ERC721 tokens are withdrawn from this address.\\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 * Make sure we can receive ETH.\\n */\\n receive() external payable {\\n emit ReceivedETH(msg.sender, msg.value);\\n }\\n\\n /**\\n * 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 * 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 _to.transfer(_amount);\\n emit WithdrewETH(msg.sender, _to, _amount);\\n }\\n\\n /**\\n * 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 * 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 * 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\",\"keccak256\":\"0x1f82aff6f4e5a4bebebbfb4a2e0e4378ef9bc5bee8b81f88b27fc0ce73546d5f\",\"license\":\"MIT\"},\"contracts/universal/TeleportrWithdrawer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\n\\nimport { AssetReceiver } from \\\"./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\",\"keccak256\":\"0x26414ae14c7aee927c18075ee60757383e0202c2a2691f23b86c200c0ac24713\",\"license\":\"MIT\"},\"contracts/universal/Transactor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\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 _gas Amount of gas to send with the call.\\n * @param _value ETH value to send with the call.\\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 _gas,\\n uint256 _value\\n ) external payable onlyOwner returns (bool, bytes memory) {\\n return _target.call{ gas: _gas, 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 * @param _gas Amount of gas to send with the call.\\n * @return Boolean success value.\\n * @return Bytes data returned by the call.\\n */\\n function DELEGATECALL(\\n address _target,\\n bytes memory _data,\\n uint256 _gas\\n ) external payable onlyOwner returns (bool, bytes memory) {\\n // slither-disable-next-line controlled-delegatecall\\n return _target.delegatecall{ gas: _gas }(_data);\\n }\\n}\\n\",\"keccak256\":\"0xfe0d9c05a423d36775047e3285f76b874f8b887444d412a0d680c302c3b06a50\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506040516115ac3803806115ac83398101604081905261002f91610086565b600080546001600160a01b0319166001600160a01b03831690811782556040518392839283929091907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a3505050506100b6565b60006020828403121561009857600080fd5b81516001600160a01b03811681146100af57600080fd5b9392505050565b6114e7806100c56000396000f3fe6080604052600436106100f75760003560e01c8063617d55421161008a5780638da5cb5b116100595780638da5cb5b146102f65780639456fbcc146103235780639e73dbea14610343578063ab62f0e11461035657600080fd5b8063617d55421461026757806366d003ac14610287578063690d8320146102b457806373d4a13a146102d457600080fd5b80634025feb2116100c65780634025feb2146101e657806344004cc1146102065780634782f779146102265780635cef8b4a1461024657600080fd5b806306fa29b21461013857806313af40351461018f5780633afe48c2146101b15780633bbed4a0146101c657600080fd5b366101335760405134815233907f4103257eaac983ca79a70d28f90dfc4fa16b619bb0c17ee7cab0d4034c2796249060200160405180910390a2005b600080fd5b34801561014457600080fd5b506001546101659073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561019b57600080fd5b506101af6101aa366004610ff1565b610376565b005b3480156101bd57600080fd5b506101af610452565b3480156101d257600080fd5b506101af6101e1366004610ff1565b61059a565b3480156101f257600080fd5b506101af610201366004611015565b610648565b34801561021257600080fd5b506101af610221366004611015565b6107c0565b34801561023257600080fd5b506101af610241366004611056565b610946565b61025961025436600461115c565b610a42565b60405161018692919061122f565b34801561027357600080fd5b506101af610282366004610ff1565b610b21565b34801561029357600080fd5b506002546101659073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102c057600080fd5b506101af6102cf366004610ff1565b610bcf565b3480156102e057600080fd5b506102e9610c40565b6040516101869190611252565b34801561030257600080fd5b506000546101659073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032f57600080fd5b506101af61033e366004611265565b610cce565b61025961035136600461129e565b610dde565b34801561036257600080fd5b506101af6103713660046112fe565b610ec1565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103e25760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635fd8c7106040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104bc57600080fd5b505af11580156104d0573d6000803e3d6000fd5b50506002546040516000935073ffffffffffffffffffffffffffffffffffffffff9091169150479061050490600390611387565b60006040518083038185875af1925050503d8060008114610541576040519150601f19603f3d011682016040523d82523d6000602084013e610546565b606091505b50509050806105975760405162461bcd60e51b815260206004820181905260248201527f54656c65706f727472576974686472617765723a2073656e64206661696c656460448201526064016103d9565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106015760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106af5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b15801561072557600080fd5b505af1158015610739573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f30b478a5e196e55886228aa87ba74a7dfeba655e0a4d7ba275eabfc22aabb7a8846040516107b391815260200190565b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108275760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb90604401602060405180830381600087803b15801561089757600080fd5b505af11580156108ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108cf919061145a565b508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f6b00f1c7883f053ba83e907fd1965b22fffe3c4111383e725f04638a566cdbfa846040516107b391815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109ad5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b60405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f193505050501580156109f0573d6000803e3d6000fd5b5060405181815273ffffffffffffffffffffffffffffffffffffffff83169033907f1f12aa8b6d492dd9b98e2b00b0b20830c2a7ded65afac13b60d169a034ae90bc9060200160405180910390a35050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610aad5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b8473ffffffffffffffffffffffffffffffffffffffff168385604051610ad3919061147c565b6000604051808303818686f4925050503d8060008114610b0f576040519150601f19603f3d011682016040523d82523d6000602084013e610b14565b606091505b5091509150935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b885760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c365760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b6105978147610946565b60038054610c4d90611333565b80601f0160208091040260200160405190810160405280929190818152602001828054610c7990611333565b8015610cc65780601f10610c9b57610100808354040283529160200191610cc6565b820191906000526020600020905b815481529060010190602001808311610ca957829003601f168201915b505050505081565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d355760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610dda908390839073ffffffffffffffffffffffffffffffffffffffff8316906370a082319060240160206040518083038186803b158015610da257600080fd5b505afa158015610db6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102219190611498565b5050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610e495760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b8573ffffffffffffffffffffffffffffffffffffffff16848487604051610e70919061147c565b600060405180830381858888f193505050503d8060008114610eae576040519150601f19603f3d011682016040523d82523d6000602084013e610eb3565b606091505b509150915094509492505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610f285760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b8051610dda906003906020840190828054610f4290611333565b90600052602060002090601f016020900481019282610f645760008555610faa565b82601f10610f7d57805160ff1916838001178555610faa565b82800160010185558215610faa579182015b82811115610faa578251825591602001919060010190610f8f565b50610fb6929150610fba565b5090565b5b80821115610fb65760008155600101610fbb565b73ffffffffffffffffffffffffffffffffffffffff8116811461059757600080fd5b60006020828403121561100357600080fd5b813561100e81610fcf565b9392505050565b60008060006060848603121561102a57600080fd5b833561103581610fcf565b9250602084013561104581610fcf565b929592945050506040919091013590565b6000806040838503121561106957600080fd5b823561107481610fcf565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126110c257600080fd5b813567ffffffffffffffff808211156110dd576110dd611082565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561112357611123611082565b8160405283815286602085880101111561113c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561117157600080fd5b833561117c81610fcf565b9250602084013567ffffffffffffffff81111561119857600080fd5b6111a4868287016110b1565b925050604084013590509250925092565b60005b838110156111d05781810151838201526020016111b8565b838111156111df576000848401525b50505050565b600081518084526111fd8160208601602086016111b5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b821515815260406020820152600061124a60408301846111e5565b949350505050565b60208152600061100e60208301846111e5565b6000806040838503121561127857600080fd5b823561128381610fcf565b9150602083013561129381610fcf565b809150509250929050565b600080600080608085870312156112b457600080fd5b84356112bf81610fcf565b9350602085013567ffffffffffffffff8111156112db57600080fd5b6112e7878288016110b1565b949794965050505060408301359260600135919050565b60006020828403121561131057600080fd5b813567ffffffffffffffff81111561132757600080fd5b61124a848285016110b1565b600181811c9082168061134757607f821691505b60208210811415611381577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600080835481600182811c9150808316806113a357607f831692505b60208084108214156113dc577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b8180156113f0576001811461141f5761144c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0086168952848901965061144c565b60008a81526020902060005b868110156114445781548b82015290850190830161142b565b505084890196505b509498975050505050505050565b60006020828403121561146c57600080fd5b8151801515811461100e57600080fd5b6000825161148e8184602087016111b5565b9190910192915050565b6000602082840312156114aa57600080fd5b505191905056fea26469706673582212203903a2f3f310c1942ac6f552df9012c64af2d384894531650c63a359397535f364736f6c63430008090033", - "deployedBytecode": "0x6080604052600436106100f75760003560e01c8063617d55421161008a5780638da5cb5b116100595780638da5cb5b146102f65780639456fbcc146103235780639e73dbea14610343578063ab62f0e11461035657600080fd5b8063617d55421461026757806366d003ac14610287578063690d8320146102b457806373d4a13a146102d457600080fd5b80634025feb2116100c65780634025feb2146101e657806344004cc1146102065780634782f779146102265780635cef8b4a1461024657600080fd5b806306fa29b21461013857806313af40351461018f5780633afe48c2146101b15780633bbed4a0146101c657600080fd5b366101335760405134815233907f4103257eaac983ca79a70d28f90dfc4fa16b619bb0c17ee7cab0d4034c2796249060200160405180910390a2005b600080fd5b34801561014457600080fd5b506001546101659073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561019b57600080fd5b506101af6101aa366004610ff1565b610376565b005b3480156101bd57600080fd5b506101af610452565b3480156101d257600080fd5b506101af6101e1366004610ff1565b61059a565b3480156101f257600080fd5b506101af610201366004611015565b610648565b34801561021257600080fd5b506101af610221366004611015565b6107c0565b34801561023257600080fd5b506101af610241366004611056565b610946565b61025961025436600461115c565b610a42565b60405161018692919061122f565b34801561027357600080fd5b506101af610282366004610ff1565b610b21565b34801561029357600080fd5b506002546101659073ffffffffffffffffffffffffffffffffffffffff1681565b3480156102c057600080fd5b506101af6102cf366004610ff1565b610bcf565b3480156102e057600080fd5b506102e9610c40565b6040516101869190611252565b34801561030257600080fd5b506000546101659073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032f57600080fd5b506101af61033e366004611265565b610cce565b61025961035136600461129e565b610dde565b34801561036257600080fd5b506101af6103713660046112fe565b610ec1565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103e25760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635fd8c7106040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104bc57600080fd5b505af11580156104d0573d6000803e3d6000fd5b50506002546040516000935073ffffffffffffffffffffffffffffffffffffffff9091169150479061050490600390611387565b60006040518083038185875af1925050503d8060008114610541576040519150601f19603f3d011682016040523d82523d6000602084013e610546565b606091505b50509050806105975760405162461bcd60e51b815260206004820181905260248201527f54656c65706f727472576974686472617765723a2073656e64206661696c656460448201526064016103d9565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106015760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106af5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b15801561072557600080fd5b505af1158015610739573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f30b478a5e196e55886228aa87ba74a7dfeba655e0a4d7ba275eabfc22aabb7a8846040516107b391815260200190565b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108275760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb90604401602060405180830381600087803b15801561089757600080fd5b505af11580156108ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108cf919061145a565b508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f6b00f1c7883f053ba83e907fd1965b22fffe3c4111383e725f04638a566cdbfa846040516107b391815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109ad5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b60405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f193505050501580156109f0573d6000803e3d6000fd5b5060405181815273ffffffffffffffffffffffffffffffffffffffff83169033907f1f12aa8b6d492dd9b98e2b00b0b20830c2a7ded65afac13b60d169a034ae90bc9060200160405180910390a35050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610aad5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b8473ffffffffffffffffffffffffffffffffffffffff168385604051610ad3919061147c565b6000604051808303818686f4925050503d8060008114610b0f576040519150601f19603f3d011682016040523d82523d6000602084013e610b14565b606091505b5091509150935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b885760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c365760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b6105978147610946565b60038054610c4d90611333565b80601f0160208091040260200160405190810160405280929190818152602001828054610c7990611333565b8015610cc65780601f10610c9b57610100808354040283529160200191610cc6565b820191906000526020600020905b815481529060010190602001808311610ca957829003601f168201915b505050505081565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d355760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610dda908390839073ffffffffffffffffffffffffffffffffffffffff8316906370a082319060240160206040518083038186803b158015610da257600080fd5b505afa158015610db6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102219190611498565b5050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610e495760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b8573ffffffffffffffffffffffffffffffffffffffff16848487604051610e70919061147c565b600060405180830381858888f193505050503d8060008114610eae576040519150601f19603f3d011682016040523d82523d6000602084013e610eb3565b606091505b509150915094509492505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610f285760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016103d9565b8051610dda906003906020840190828054610f4290611333565b90600052602060002090601f016020900481019282610f645760008555610faa565b82601f10610f7d57805160ff1916838001178555610faa565b82800160010185558215610faa579182015b82811115610faa578251825591602001919060010190610f8f565b50610fb6929150610fba565b5090565b5b80821115610fb65760008155600101610fbb565b73ffffffffffffffffffffffffffffffffffffffff8116811461059757600080fd5b60006020828403121561100357600080fd5b813561100e81610fcf565b9392505050565b60008060006060848603121561102a57600080fd5b833561103581610fcf565b9250602084013561104581610fcf565b929592945050506040919091013590565b6000806040838503121561106957600080fd5b823561107481610fcf565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126110c257600080fd5b813567ffffffffffffffff808211156110dd576110dd611082565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561112357611123611082565b8160405283815286602085880101111561113c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561117157600080fd5b833561117c81610fcf565b9250602084013567ffffffffffffffff81111561119857600080fd5b6111a4868287016110b1565b925050604084013590509250925092565b60005b838110156111d05781810151838201526020016111b8565b838111156111df576000848401525b50505050565b600081518084526111fd8160208601602086016111b5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b821515815260406020820152600061124a60408301846111e5565b949350505050565b60208152600061100e60208301846111e5565b6000806040838503121561127857600080fd5b823561128381610fcf565b9150602083013561129381610fcf565b809150509250929050565b600080600080608085870312156112b457600080fd5b84356112bf81610fcf565b9350602085013567ffffffffffffffff8111156112db57600080fd5b6112e7878288016110b1565b949794965050505060408301359260600135919050565b60006020828403121561131057600080fd5b813567ffffffffffffffff81111561132757600080fd5b61124a848285016110b1565b600181811c9082168061134757607f821691505b60208210811415611381577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600080835481600182811c9150808316806113a357607f831692505b60208084108214156113dc577f4e487b710000000000000000000000000000000000000000000000000000000086526022600452602486fd5b8180156113f0576001811461141f5761144c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0086168952848901965061144c565b60008a81526020902060005b868110156114445781548b82015290850190830161142b565b505084890196505b509498975050505050505050565b60006020828403121561146c57600080fd5b8151801515811461100e57600080fd5b6000825161148e8184602087016111b5565b9190910192915050565b6000602082840312156114aa57600080fd5b505191905056fea26469706673582212203903a2f3f310c1942ac6f552df9012c64af2d384894531650c63a359397535f364736f6c63430008090033", - "devdoc": { - "kind": "dev", - "methods": { - "CALL(address,bytes,uint256,uint256)": { - "params": { - "_data": "Data to send with the call.", - "_gas": "Amount of gas to send with the call.", - "_target": "Address to call.", - "_value": "ETH value to send with the call." - }, - "returns": { - "_0": "Boolean success value.", - "_1": "Bytes data returned by the call." - } - }, - "DELEGATECALL(address,bytes,uint256)": { - "params": { - "_data": "Data to send with the call.", - "_gas": "Amount of gas to send with the call.", - "_target": "Address to call." - }, - "returns": { - "_0": "Boolean success value.", - "_1": "Bytes data returned by the call." - } - }, - "constructor": { - "params": { - "_owner": "Initial owner of the contract." - } - }, - "setData(bytes)": { - "params": { - "_data": "New data to be sent to the recipient address." - } - }, - "setRecipient(address)": { - "params": { - "_recipient": "New recipient address." - } - }, - "setTeleportr(address)": { - "params": { - "_teleportr": "New Teleportr contract address." - } - }, - "withdrawERC20(address,address)": { - "params": { - "_asset": "ERC20 token to withdraw.", - "_to": "Address to receive the ERC20 balance." - } - }, - "withdrawERC20(address,address,uint256)": { - "params": { - "_amount": "Amount of ERC20 to withdraw.", - "_asset": "ERC20 token to withdraw.", - "_to": "Address to receive the ERC20 balance." - } - }, - "withdrawERC721(address,address,uint256)": { - "params": { - "_asset": "ERC721 token to withdraw.", - "_id": "Token ID of the ERC721 token to withdraw.", - "_to": "Address to receive the ERC721 token." - } - }, - "withdrawETH(address)": { - "params": { - "_to": "Address to receive the ETH balance." - } - }, - "withdrawETH(address,uint256)": { - "params": { - "_amount": "Amount of ETH to withdraw.", - "_to": "Address to receive the ETH balance." - } - } - }, - "title": "TeleportrWithdrawer", - "version": 1 - }, - "userdoc": { - "events": { - "ReceivedETH(address,uint256)": { - "notice": "Emitted when ETH is received by this address." - }, - "WithdrewERC20(address,address,address,uint256)": { - "notice": "Emitted when ERC20 tokens are withdrawn from this address." - }, - "WithdrewERC721(address,address,address,uint256)": { - "notice": "Emitted when ERC721 tokens are withdrawn from this address." - }, - "WithdrewETH(address,address,uint256)": { - "notice": "Emitted when ETH is withdrawn from this address." - } - }, - "kind": "user", - "methods": { - "CALL(address,bytes,uint256,uint256)": { - "notice": "Sends a CALL to a target address." - }, - "DELEGATECALL(address,bytes,uint256)": { - "notice": "Sends a DELEGATECALL to a target address." - }, - "data()": { - "notice": "Data to be sent to the recipient address." - }, - "recipient()": { - "notice": "Address that will receive Teleportr withdrawals." - }, - "setData(bytes)": { - "notice": "Allows the owner to update the data to be sent to the recipient address." - }, - "setRecipient(address)": { - "notice": "Allows the owner to update the recipient address." - }, - "setTeleportr(address)": { - "notice": "Allows the owner to update the Teleportr contract address." - }, - "teleportr()": { - "notice": "Address of the Teleportr contract." - }, - "withdrawERC20(address,address)": { - "notice": "Withdraws full ERC20 balance to the recipient." - }, - "withdrawERC20(address,address,uint256)": { - "notice": "Withdraws partial ERC20 balance to the recipient." - }, - "withdrawERC721(address,address,uint256)": { - "notice": "Withdraws ERC721 token to the recipient." - }, - "withdrawETH(address)": { - "notice": "Withdraws full ETH balance to the recipient." - }, - "withdrawETH(address,uint256)": { - "notice": "Withdraws partial ETH balance to the recipient." - }, - "withdrawFromTeleportr()": { - "notice": "Withdraws the full balance of the Teleportr contract to the recipient address. Anyone is allowed to trigger this function since the recipient address cannot be controlled by the msg.sender." - } - }, - "notice": "The TeleportrWithdrawer is a simple contract capable of withdrawing funds from the TeleportrContract and sending them to some recipient address.", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 4371, - "contract": "contracts/universal/TeleportrWithdrawer.sol:TeleportrWithdrawer", - "label": "owner", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 6314, - "contract": "contracts/universal/TeleportrWithdrawer.sol:TeleportrWithdrawer", - "label": "teleportr", - "offset": 0, - "slot": "1", - "type": "t_address" - }, - { - "astId": 6317, - "contract": "contracts/universal/TeleportrWithdrawer.sol:TeleportrWithdrawer", - "label": "recipient", - "offset": 0, - "slot": "2", - "type": "t_address" - }, - { - "astId": 6320, - "contract": "contracts/universal/TeleportrWithdrawer.sol:TeleportrWithdrawer", - "label": "data", - "offset": 0, - "slot": "3", - "type": "t_bytes_storage" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bytes_storage": { - "encoding": "bytes", - "label": "bytes", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/mainnet/solcInputs/13ac93d026822f719ad110af836d1582.json b/packages/contracts-bedrock/deployments/mainnet/solcInputs/13ac93d026822f719ad110af836d1582.json deleted file mode 100644 index cde6d404005a..000000000000 --- a/packages/contracts-bedrock/deployments/mainnet/solcInputs/13ac93d026822f719ad110af836d1582.json +++ /dev/null @@ -1,596 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/L1/L1CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismPortal } from \"./OptimismPortal.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1CrossDomainMessenger\n * @notice The L1CrossDomainMessenger is a message passing interface between L1 and L2 responsible\n * for sending and receiving data on the L1 side. Users are encouraged to use this\n * interface instead of interacting with lower-level contracts directly.\n */\ncontract L1CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @notice Address of the OptimismPortal.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @custom:semver 1.4.0\n *\n * @param _portal Address of the OptimismPortal contract on this network.\n */\n constructor(OptimismPortal _portal)\n Semver(1, 4, 0)\n CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER)\n {\n PORTAL = _portal;\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n PORTAL.depositTransaction{ value: _value }(_to, _value, _gasLimit, false, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return msg.sender == address(PORTAL) && PORTAL.l2Sender() == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(PORTAL);\n }\n}\n" - }, - "contracts/L1/L1ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { L2ERC721Bridge } from \"../L2/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 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.1.1\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, 1, 1)\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 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), \"L1ERC721Bridge: 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(OTHER_BRIDGE, message, _minGasLimit);\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L1/L1StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1StandardBridge\n * @notice The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L1, it will be escrowed within this\n * contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was\n * stored within this contract. After Bedrock, ETH is instead stored inside the\n * OptimismPortal contract.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L1StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a deposit of ETH from L1 into L2 is initiated.\n *\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of ETH deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ETHDepositInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal of ETH from L2 to L1 is finalized.\n *\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of ETH withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 withdrawal is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _messenger Address of the L1CrossDomainMessenger.\n */\n constructor(address payable _messenger)\n Semver(1, 1, 0)\n StandardBridge(_messenger, payable(Predeploys.L2_STANDARD_BRIDGE))\n {}\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n */\n receive() external payable override onlyEOA {\n _initiateETHDeposit(msg.sender, msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into the sender's account on L2.\n *\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETH(uint32 _minGasLimit, bytes calldata _extraData) external payable onlyEOA {\n _initiateETHDeposit(msg.sender, msg.sender, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into a target account on L2.\n * Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will\n * be locked in the L2StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n *\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable {\n _initiateETHDeposit(msg.sender, _to, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into the sender's account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20(\n address _l1Token,\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual onlyEOA {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into a target account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20To(\n address _l1Token,\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ETH from L2.\n *\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of ETH to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeETHWithdrawal(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable {\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ERC20 tokens from L2.\n *\n * @param _l1Token Address of the token on L1.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of the ERC20 to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeERC20Withdrawal(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external {\n finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L2 bridge contract.\n *\n * @return Address of the corresponding L2 bridge contract.\n */\n function l2TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @notice Internal function for initiating an ETH deposit.\n *\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateETHDeposit(\n address _from,\n address _to,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n _initiateBridgeETH(_from, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Internal function for initiating an ERC20 deposit.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateERC20Deposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n _initiateBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Emits the legacy ETHDepositInitiated event followed by the ETHBridgeInitiated event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ETHDepositInitiated(_from, _to, _amount, _extraData);\n super._emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ETHWithdrawalFinalized event followed by the ETHBridgeFinalized\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ETHWithdrawalFinalized(_from, _to, _amount, _extraData);\n super._emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ERC20DepositInitiated event followed by the ERC20BridgeInitiated\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ERC20DepositInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ERC20WithdrawalFinalized event followed by the ERC20BridgeFinalized\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ERC20WithdrawalFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/L1/L2OutputOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\n/**\n * @custom:proxied\n * @title L2OutputOracle\n * @notice The L2OutputOracle contains an array of L2 state outputs, where each output is a\n * commitment to the state of the L2 chain. Other contracts like the OptimismPortal use\n * these outputs to verify information about the state of L2.\n */\ncontract L2OutputOracle is Initializable, Semver {\n /**\n * @notice The interval in L2 blocks at which checkpoints must be submitted. Although this is\n * immutable, it can safely be modified by upgrading the implementation contract.\n */\n uint256 public immutable SUBMISSION_INTERVAL;\n\n /**\n * @notice The time between L2 blocks in seconds. Once set, this value MUST NOT be modified.\n */\n uint256 public immutable L2_BLOCK_TIME;\n\n /**\n * @notice The address of the challenger. Can be updated via upgrade.\n */\n address public immutable CHALLENGER;\n\n /**\n * @notice The address of the proposer. Can be updated via upgrade.\n */\n address public immutable PROPOSER;\n\n /**\n * @notice Minimum time (in seconds) that must elapse before a withdrawal can be finalized.\n */\n uint256 public immutable FINALIZATION_PERIOD_SECONDS;\n\n /**\n * @notice The number of the first L2 block recorded in this contract.\n */\n uint256 public startingBlockNumber;\n\n /**\n * @notice The timestamp of the first L2 block recorded in this contract.\n */\n uint256 public startingTimestamp;\n\n /**\n * @notice Array of L2 output proposals.\n */\n Types.OutputProposal[] internal l2Outputs;\n\n /**\n * @notice Emitted when an output is proposed.\n *\n * @param outputRoot The output root.\n * @param l2OutputIndex The index of the output in the l2Outputs array.\n * @param l2BlockNumber The L2 block number of the output root.\n * @param l1Timestamp The L1 timestamp when proposed.\n */\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n /**\n * @notice Emitted when outputs are deleted.\n *\n * @param prevNextOutputIndex Next L2 output index before the deletion.\n * @param newNextOutputIndex Next L2 output index after the deletion.\n */\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n /**\n * @custom:semver 1.3.0\n *\n * @param _submissionInterval Interval in blocks at which checkpoints must be submitted.\n * @param _l2BlockTime The time per L2 block, in seconds.\n * @param _startingBlockNumber The number of the first L2 block.\n * @param _startingTimestamp The timestamp of the first L2 block.\n * @param _proposer The address of the proposer.\n * @param _challenger The address of the challenger.\n */\n constructor(\n uint256 _submissionInterval,\n uint256 _l2BlockTime,\n uint256 _startingBlockNumber,\n uint256 _startingTimestamp,\n address _proposer,\n address _challenger,\n uint256 _finalizationPeriodSeconds\n ) Semver(1, 3, 0) {\n require(_l2BlockTime > 0, \"L2OutputOracle: L2 block time must be greater than 0\");\n require(\n _submissionInterval > 0,\n \"L2OutputOracle: submission interval must be greater than 0\"\n );\n\n SUBMISSION_INTERVAL = _submissionInterval;\n L2_BLOCK_TIME = _l2BlockTime;\n PROPOSER = _proposer;\n CHALLENGER = _challenger;\n FINALIZATION_PERIOD_SECONDS = _finalizationPeriodSeconds;\n\n initialize(_startingBlockNumber, _startingTimestamp);\n }\n\n /**\n * @notice Initializer.\n *\n * @param _startingBlockNumber Block number for the first recoded L2 block.\n * @param _startingTimestamp Timestamp for the first recoded L2 block.\n */\n function initialize(uint256 _startingBlockNumber, uint256 _startingTimestamp)\n public\n initializer\n {\n require(\n _startingTimestamp <= block.timestamp,\n \"L2OutputOracle: starting L2 timestamp must be less than current time\"\n );\n\n startingTimestamp = _startingTimestamp;\n startingBlockNumber = _startingBlockNumber;\n }\n\n /**\n * @notice Deletes all output proposals after and including the proposal that corresponds to\n * the given output index. Only the challenger address can delete outputs.\n *\n * @param _l2OutputIndex Index of the first L2 output to be deleted. All outputs after this\n * output will also be deleted.\n */\n // solhint-disable-next-line ordering\n function deleteL2Outputs(uint256 _l2OutputIndex) external {\n require(\n msg.sender == CHALLENGER,\n \"L2OutputOracle: only the challenger address can delete outputs\"\n );\n\n // Make sure we're not *increasing* the length of the array.\n require(\n _l2OutputIndex < l2Outputs.length,\n \"L2OutputOracle: cannot delete outputs after the latest output index\"\n );\n\n // Do not allow deleting any outputs that have already been finalized.\n require(\n block.timestamp - l2Outputs[_l2OutputIndex].timestamp < FINALIZATION_PERIOD_SECONDS,\n \"L2OutputOracle: cannot delete outputs that have already been finalized\"\n );\n\n uint256 prevNextL2OutputIndex = nextOutputIndex();\n\n // Use assembly to delete the array elements because Solidity doesn't allow it.\n assembly {\n sstore(l2Outputs.slot, _l2OutputIndex)\n }\n\n emit OutputsDeleted(prevNextL2OutputIndex, _l2OutputIndex);\n }\n\n /**\n * @notice Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp\n * must be equal to the current value returned by `nextTimestamp()` in order to be\n * accepted. This function may only be called by the Proposer.\n *\n * @param _outputRoot The L2 output of the checkpoint block.\n * @param _l2BlockNumber The L2 block number that resulted in _outputRoot.\n * @param _l1BlockHash A block hash which must be included in the current chain.\n * @param _l1BlockNumber The block number with the specified block hash.\n */\n function proposeL2Output(\n bytes32 _outputRoot,\n uint256 _l2BlockNumber,\n bytes32 _l1BlockHash,\n uint256 _l1BlockNumber\n ) external payable {\n require(\n msg.sender == PROPOSER,\n \"L2OutputOracle: only the proposer address can propose new outputs\"\n );\n\n require(\n _l2BlockNumber == nextBlockNumber(),\n \"L2OutputOracle: block number must be equal to next expected block number\"\n );\n\n require(\n computeL2Timestamp(_l2BlockNumber) < block.timestamp,\n \"L2OutputOracle: cannot propose L2 output in the future\"\n );\n\n require(\n _outputRoot != bytes32(0),\n \"L2OutputOracle: L2 output proposal cannot be the zero hash\"\n );\n\n if (_l1BlockHash != bytes32(0)) {\n // This check allows the proposer to propose an output based on a given L1 block,\n // without fear that it will be reorged out.\n // It will also revert if the blockheight provided is more than 256 blocks behind the\n // chain tip (as the hash will return as zero). This does open the door to a griefing\n // attack in which the proposer's submission is censored until the block is no longer\n // retrievable, if the proposer is experiencing this attack it can simply leave out the\n // blockhash value, and delay submission until it is confident that the L1 block is\n // finalized.\n require(\n blockhash(_l1BlockNumber) == _l1BlockHash,\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n }\n\n emit OutputProposed(_outputRoot, nextOutputIndex(), _l2BlockNumber, block.timestamp);\n\n l2Outputs.push(\n Types.OutputProposal({\n outputRoot: _outputRoot,\n timestamp: uint128(block.timestamp),\n l2BlockNumber: uint128(_l2BlockNumber)\n })\n );\n }\n\n /**\n * @notice Returns an output by index. Exists because Solidity's array access will return a\n * tuple instead of a struct.\n *\n * @param _l2OutputIndex Index of the output to return.\n *\n * @return The output at the given index.\n */\n function getL2Output(uint256 _l2OutputIndex)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[_l2OutputIndex];\n }\n\n /**\n * @notice Returns the index of the L2 output that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return Index of the first checkpoint that commits to the given L2 block number.\n */\n function getL2OutputIndexAfter(uint256 _l2BlockNumber) public view returns (uint256) {\n // Make sure an output for this block number has actually been proposed.\n require(\n _l2BlockNumber <= latestBlockNumber(),\n \"L2OutputOracle: cannot get output for a block that has not been proposed\"\n );\n\n // Make sure there's at least one output proposed.\n require(\n l2Outputs.length > 0,\n \"L2OutputOracle: cannot get output as no outputs have been proposed yet\"\n );\n\n // Find the output via binary search, guaranteed to exist.\n uint256 lo = 0;\n uint256 hi = l2Outputs.length;\n while (lo < hi) {\n uint256 mid = (lo + hi) / 2;\n if (l2Outputs[mid].l2BlockNumber < _l2BlockNumber) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n return lo;\n }\n\n /**\n * @notice Returns the L2 output proposal that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return First checkpoint that commits to the given L2 block number.\n */\n function getL2OutputAfter(uint256 _l2BlockNumber)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[getL2OutputIndexAfter(_l2BlockNumber)];\n }\n\n /**\n * @notice Returns the number of outputs that have been proposed. Will revert if no outputs\n * have been proposed yet.\n *\n * @return The number of outputs that have been proposed.\n */\n function latestOutputIndex() external view returns (uint256) {\n return l2Outputs.length - 1;\n }\n\n /**\n * @notice Returns the index of the next output to be proposed.\n *\n * @return The index of the next output to be proposed.\n */\n function nextOutputIndex() public view returns (uint256) {\n return l2Outputs.length;\n }\n\n /**\n * @notice Returns the block number of the latest submitted L2 output proposal. If no proposals\n * been submitted yet then this function will return the starting block number.\n *\n * @return Latest submitted L2 block number.\n */\n function latestBlockNumber() public view returns (uint256) {\n return\n l2Outputs.length == 0\n ? startingBlockNumber\n : l2Outputs[l2Outputs.length - 1].l2BlockNumber;\n }\n\n /**\n * @notice Computes the block number of the next L2 block that needs to be checkpointed.\n *\n * @return Next L2 block number.\n */\n function nextBlockNumber() public view returns (uint256) {\n return latestBlockNumber() + SUBMISSION_INTERVAL;\n }\n\n /**\n * @notice Returns the L2 timestamp corresponding to a given L2 block number.\n *\n * @param _l2BlockNumber The L2 block number of the target block.\n *\n * @return L2 timestamp of the given block.\n */\n function computeL2Timestamp(uint256 _l2BlockNumber) public view returns (uint256) {\n return startingTimestamp + ((_l2BlockNumber - startingBlockNumber) * L2_BLOCK_TIME);\n }\n}\n" - }, - "contracts/L1/OptimismPortal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { L2OutputOracle } from \"./L2OutputOracle.sol\";\nimport { SystemConfig } from \"./SystemConfig.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { SecureMerkleTrie } from \"../libraries/trie/SecureMerkleTrie.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ResourceMetering } from \"./ResourceMetering.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title OptimismPortal\n * @notice The OptimismPortal is a low-level contract responsible for passing messages between L1\n * and L2. Messages sent directly to the OptimismPortal have no form of replayability.\n * Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface.\n */\ncontract OptimismPortal is Initializable, ResourceMetering, Semver {\n /**\n * @notice Represents a proven withdrawal.\n *\n * @custom:field outputRoot Root of the L2 output this was proven against.\n * @custom:field timestamp Timestamp at whcih the withdrawal was proven.\n * @custom:field l2OutputIndex Index of the output this was proven against.\n */\n struct ProvenWithdrawal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2OutputIndex;\n }\n\n /**\n * @notice Version of the deposit event.\n */\n uint256 internal constant DEPOSIT_VERSION = 0;\n\n /**\n * @notice The L2 gas limit set when eth is deposited using the receive() function.\n */\n uint64 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Address of the L2OutputOracle contract.\n */\n L2OutputOracle public immutable L2_ORACLE;\n\n /**\n * @notice Address of the SystemConfig contract.\n */\n SystemConfig public immutable SYSTEM_CONFIG;\n\n /**\n * @notice Address that has the ability to pause and unpause withdrawals.\n */\n address public immutable GUARDIAN;\n\n /**\n * @notice Address of the L2 account which initiated a withdrawal in this transaction. If the\n * of this variable is the default L2 sender address, then we are NOT inside of a call\n * to finalizeWithdrawalTransaction.\n */\n address public l2Sender;\n\n /**\n * @notice A list of withdrawal hashes which have been successfully finalized.\n */\n mapping(bytes32 => bool) public finalizedWithdrawals;\n\n /**\n * @notice A mapping of withdrawal hashes to `ProvenWithdrawal` data.\n */\n mapping(bytes32 => ProvenWithdrawal) public provenWithdrawals;\n\n /**\n * @notice Determines if cross domain messaging is paused. When set to true,\n * withdrawals are paused. This may be removed in the future.\n */\n bool public paused;\n\n /**\n * @notice Emitted when a transaction is deposited from L1 to L2. The parameters of this event\n * are read by the rollup node and used to derive deposit transactions on L2.\n *\n * @param from Address that triggered the deposit transaction.\n * @param to Address that the deposit transaction is directed to.\n * @param version Version of this deposit transaction event.\n * @param opaqueData ABI encoded deposit data to be parsed off-chain.\n */\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is proven.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n */\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is finalized.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n * @param success Whether the withdrawal transaction was successful.\n */\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n\n /**\n * @notice Emitted when the pause is triggered.\n *\n * @param account Address of the account triggering the pause.\n */\n event Paused(address account);\n\n /**\n * @notice Emitted when the pause is lifted.\n *\n * @param account Address of the account triggering the unpause.\n */\n event Unpaused(address account);\n\n /**\n * @notice Reverts when paused.\n */\n modifier whenNotPaused() {\n require(paused == false, \"OptimismPortal: paused\");\n _;\n }\n\n /**\n * @custom:semver 1.6.0\n *\n * @param _l2Oracle Address of the L2OutputOracle contract.\n * @param _guardian Address that can pause deposits and withdrawals.\n * @param _paused Sets the contract's pausability state.\n * @param _config Address of the SystemConfig contract.\n */\n constructor(\n L2OutputOracle _l2Oracle,\n address _guardian,\n bool _paused,\n SystemConfig _config\n ) Semver(1, 6, 0) {\n L2_ORACLE = _l2Oracle;\n GUARDIAN = _guardian;\n SYSTEM_CONFIG = _config;\n initialize(_paused);\n }\n\n /**\n * @notice Initializer.\n */\n function initialize(bool _paused) public initializer {\n l2Sender = Constants.DEFAULT_L2_SENDER;\n paused = _paused;\n __ResourceMetering_init();\n }\n\n /**\n * @notice Pause deposits and withdrawals.\n */\n function pause() external {\n require(msg.sender == GUARDIAN, \"OptimismPortal: only guardian can pause\");\n paused = true;\n emit Paused(msg.sender);\n }\n\n /**\n * @notice Unpause deposits and withdrawals.\n */\n function unpause() external {\n require(msg.sender == GUARDIAN, \"OptimismPortal: only guardian can unpause\");\n paused = false;\n emit Unpaused(msg.sender);\n }\n\n /**\n * @notice Computes the minimum gas limit for a deposit. The minimum gas limit\n * linearly increases based on the size of the calldata. This is to prevent\n * users from creating L2 resource usage without paying for it. This function\n * can be used when interacting with the portal to ensure forwards compatibility.\n *\n */\n function minimumGasLimit(uint64 _byteCount) public pure returns (uint64) {\n return _byteCount * 16 + 21000;\n }\n\n /**\n * @notice Accepts value so that users can send ETH directly to this contract and have the\n * funds be deposited to their address on L2. This is intended as a convenience\n * function for EOAs. Contracts should call the depositTransaction() function directly\n * otherwise any deposited funds will be lost due to address aliasing.\n */\n // solhint-disable-next-line ordering\n receive() external payable {\n depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes(\"\"));\n }\n\n /**\n * @notice Accepts ETH value without triggering a deposit to L2. This function mainly exists\n * for the sake of the migration between the legacy Optimism system and Bedrock.\n */\n function donateETH() external payable {\n // Intentionally empty.\n }\n\n /**\n * @notice Getter for the resource config. Used internally by the ResourceMetering\n * contract. The SystemConfig is the source of truth for the resource config.\n *\n * @return ResourceMetering.ResourceConfig\n */\n function _resourceConfig()\n internal\n view\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return SYSTEM_CONFIG.resourceConfig();\n }\n\n /**\n * @notice Proves a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n * @param _l2OutputIndex L2 output index to prove against.\n * @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root.\n * @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract.\n */\n function proveWithdrawalTransaction(\n Types.WithdrawalTransaction memory _tx,\n uint256 _l2OutputIndex,\n Types.OutputRootProof calldata _outputRootProof,\n bytes[] calldata _withdrawalProof\n ) external whenNotPaused {\n // Prevent users from creating a deposit transaction where this address is the message\n // sender on L2. Because this is checked here, we do not need to check again in\n // `finalizeWithdrawalTransaction`.\n require(\n _tx.target != address(this),\n \"OptimismPortal: you cannot send messages to the portal contract\"\n );\n\n // Get the output root and load onto the stack to prevent multiple mloads. This will\n // revert if there is no output root for the given block number.\n bytes32 outputRoot = L2_ORACLE.getL2Output(_l2OutputIndex).outputRoot;\n\n // Verify that the output root can be generated with the elements in the proof.\n require(\n outputRoot == Hashing.hashOutputRootProof(_outputRootProof),\n \"OptimismPortal: invalid output root proof\"\n );\n\n // Load the ProvenWithdrawal into memory, using the withdrawal hash as a unique identifier.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // We generally want to prevent users from proving the same withdrawal multiple times\n // because each successive proof will update the timestamp. A malicious user can take\n // advantage of this to prevent other users from finalizing their withdrawal. However,\n // since withdrawals are proven before an output root is finalized, we need to allow users\n // to re-prove their withdrawal only in the case that the output root for their specified\n // output index has been updated.\n require(\n provenWithdrawal.timestamp == 0 ||\n L2_ORACLE.getL2Output(provenWithdrawal.l2OutputIndex).outputRoot !=\n provenWithdrawal.outputRoot,\n \"OptimismPortal: withdrawal hash has already been proven\"\n );\n\n // Compute the storage slot of the withdrawal hash in the L2ToL1MessagePasser contract.\n // Refer to the Solidity documentation for more information on how storage layouts are\n // computed for mappings.\n bytes32 storageKey = keccak256(\n abi.encode(\n withdrawalHash,\n uint256(0) // The withdrawals mapping is at the first slot in the layout.\n )\n );\n\n // Verify that the hash of this withdrawal was stored in the L2toL1MessagePasser contract\n // on L2. If this is true, under the assumption that the SecureMerkleTrie does not have\n // bugs, then we know that this withdrawal was actually triggered on L2 and can therefore\n // be relayed on L1.\n require(\n SecureMerkleTrie.verifyInclusionProof(\n abi.encode(storageKey),\n hex\"01\",\n _withdrawalProof,\n _outputRootProof.messagePasserStorageRoot\n ),\n \"OptimismPortal: invalid withdrawal inclusion proof\"\n );\n\n // Designate the withdrawalHash as proven by storing the `outputRoot`, `timestamp`, and\n // `l2BlockNumber` in the `provenWithdrawals` mapping. A `withdrawalHash` can only be\n // proven once unless it is submitted again with a different outputRoot.\n provenWithdrawals[withdrawalHash] = ProvenWithdrawal({\n outputRoot: outputRoot,\n timestamp: uint128(block.timestamp),\n l2OutputIndex: uint128(_l2OutputIndex)\n });\n\n // Emit a `WithdrawalProven` event.\n emit WithdrawalProven(withdrawalHash, _tx.sender, _tx.target);\n }\n\n /**\n * @notice Finalizes a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n */\n function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx)\n external\n whenNotPaused\n {\n // Make sure that the l2Sender has not yet been set. The l2Sender is set to a value other\n // than the default value when a withdrawal transaction is being finalized. This check is\n // a defacto reentrancy guard.\n require(\n l2Sender == Constants.DEFAULT_L2_SENDER,\n \"OptimismPortal: can only trigger one withdrawal per transaction\"\n );\n\n // Grab the proven withdrawal from the `provenWithdrawals` map.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // A withdrawal can only be finalized if it has been proven. We know that a withdrawal has\n // been proven at least once when its timestamp is non-zero. Unproven withdrawals will have\n // a timestamp of zero.\n require(\n provenWithdrawal.timestamp != 0,\n \"OptimismPortal: withdrawal has not been proven yet\"\n );\n\n // As a sanity check, we make sure that the proven withdrawal's timestamp is greater than\n // starting timestamp inside the L2OutputOracle. Not strictly necessary but extra layer of\n // safety against weird bugs in the proving step.\n require(\n provenWithdrawal.timestamp >= L2_ORACLE.startingTimestamp(),\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n\n // A proven withdrawal must wait at least the finalization period before it can be\n // finalized. This waiting period can elapse in parallel with the waiting period for the\n // output the withdrawal was proven against. In effect, this means that the minimum\n // withdrawal time is proposal submission time + finalization period.\n require(\n _isFinalizationPeriodElapsed(provenWithdrawal.timestamp),\n \"OptimismPortal: proven withdrawal finalization period has not elapsed\"\n );\n\n // Grab the OutputProposal from the L2OutputOracle, will revert if the output that\n // corresponds to the given index has not been proposed yet.\n Types.OutputProposal memory proposal = L2_ORACLE.getL2Output(\n provenWithdrawal.l2OutputIndex\n );\n\n // Check that the output root that was used to prove the withdrawal is the same as the\n // current output root for the given output index. An output root may change if it is\n // deleted by the challenger address and then re-proposed.\n require(\n proposal.outputRoot == provenWithdrawal.outputRoot,\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n\n // Check that the output proposal has also been finalized.\n require(\n _isFinalizationPeriodElapsed(proposal.timestamp),\n \"OptimismPortal: output proposal finalization period has not elapsed\"\n );\n\n // Check that this withdrawal has not already been finalized, this is replay protection.\n require(\n finalizedWithdrawals[withdrawalHash] == false,\n \"OptimismPortal: withdrawal has already been finalized\"\n );\n\n // Mark the withdrawal as finalized so it can't be replayed.\n finalizedWithdrawals[withdrawalHash] = true;\n\n // Set the l2Sender so contracts know who triggered this withdrawal on L2.\n l2Sender = _tx.sender;\n\n // Trigger the call to the target contract. We use a custom low level method\n // SafeCall.callWithMinGas to ensure two key properties\n // 1. Target contracts cannot force this call to run out of gas by returning a very large\n // amount of data (and this is OK because we don't care about the returndata here).\n // 2. The amount of gas provided to the execution context of the target is at least the\n // gas limit specified by the user. If there is not enough gas in the current context\n // to accomplish this, `callWithMinGas` will revert.\n bool success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, _tx.value, _tx.data);\n\n // Reset the l2Sender back to the default value.\n l2Sender = Constants.DEFAULT_L2_SENDER;\n\n // All withdrawals are immediately finalized. Replayability can\n // be achieved through contracts built on top of this contract\n emit WithdrawalFinalized(withdrawalHash, success);\n\n // Reverting here is useful for determining the exact gas cost to successfully execute the\n // sub call to the target contract if the minimum gas limit specified by the user would not\n // be sufficient to execute the sub call.\n if (success == false && tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"OptimismPortal: withdrawal failed\");\n }\n }\n\n /**\n * @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in\n * deriving deposit transactions. Note that if a deposit is made by a contract, its\n * address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider\n * using the CrossDomainMessenger contracts for a simpler developer experience.\n *\n * @param _to Target address on L2.\n * @param _value ETH value to send to the recipient.\n * @param _gasLimit Minimum L2 gas limit (can be greater than or equal to this value).\n * @param _isCreation Whether or not the transaction is a contract creation.\n * @param _data Data to trigger the recipient with.\n */\n function depositTransaction(\n address _to,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable metered(_gasLimit) {\n // Just to be safe, make sure that people specify address(0) as the target when doing\n // contract creations.\n if (_isCreation) {\n require(\n _to == address(0),\n \"OptimismPortal: must send to address(0) when creating a contract\"\n );\n }\n\n // Prevent depositing transactions that have too small of a gas limit. Users should pay\n // more for more resource usage.\n require(\n _gasLimit >= minimumGasLimit(uint64(_data.length)),\n \"OptimismPortal: gas limit too small\"\n );\n\n // Prevent the creation of deposit transactions that have too much calldata. This gives an\n // upper limit on the size of unsafe blocks over the p2p network. 120kb is chosen to ensure\n // that the transaction can fit into the p2p network policy of 128kb even though deposit\n // transactions are not gossipped over the p2p network.\n require(_data.length <= 120_000, \"OptimismPortal: data too large\");\n\n // Transform the from-address to its alias if the caller is a contract.\n address from = msg.sender;\n if (msg.sender != tx.origin) {\n from = AddressAliasHelper.applyL1ToL2Alias(msg.sender);\n }\n\n // Compute the opaque data that will be emitted as part of the TransactionDeposited event.\n // We use opaque data so that we can update the TransactionDeposited event in the future\n // without breaking the current interface.\n bytes memory opaqueData = abi.encodePacked(\n msg.value,\n _value,\n _gasLimit,\n _isCreation,\n _data\n );\n\n // Emit a TransactionDeposited event so that the rollup node can derive a deposit\n // transaction for this deposit.\n emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData);\n }\n\n /**\n * @notice Determine if a given output is finalized. Reverts if the call to\n * L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.\n *\n * @param _l2OutputIndex Index of the L2 output to check.\n *\n * @return Whether or not the output is finalized.\n */\n function isOutputFinalized(uint256 _l2OutputIndex) external view returns (bool) {\n return _isFinalizationPeriodElapsed(L2_ORACLE.getL2Output(_l2OutputIndex).timestamp);\n }\n\n /**\n * @notice Determines whether the finalization period has elapsed w/r/t a given timestamp.\n *\n * @param _timestamp Timestamp to check.\n *\n * @return Whether or not the finalization period has elapsed.\n */\n function _isFinalizationPeriodElapsed(uint256 _timestamp) internal view returns (bool) {\n return block.timestamp > _timestamp + L2_ORACLE.FINALIZATION_PERIOD_SECONDS();\n }\n}\n" - }, - "contracts/L1/ResourceMetering.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\n\n/**\n * @custom:upgradeable\n * @title ResourceMetering\n * @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing\n * updates automatically based on current demand.\n */\nabstract contract ResourceMetering is Initializable {\n /**\n * @notice Represents the various parameters that control the way in which resources are\n * metered. Corresponds to the EIP-1559 resource metering system.\n *\n * @custom:field prevBaseFee Base fee from the previous block(s).\n * @custom:field prevBoughtGas Amount of gas bought so far in the current block.\n * @custom:field prevBlockNum Last block number that the base fee was updated.\n */\n struct ResourceParams {\n uint128 prevBaseFee;\n uint64 prevBoughtGas;\n uint64 prevBlockNum;\n }\n\n /**\n * @notice Represents the configuration for the EIP-1559 based curve for the deposit gas\n * market. These values should be set with care as it is possible to set them in\n * a way that breaks the deposit gas market. The target resource limit is defined as\n * maxResourceLimit / elasticityMultiplier. This struct was designed to fit within a\n * single word. There is additional space for additions in the future.\n *\n * @custom:field maxResourceLimit Represents the maximum amount of deposit gas that\n * can be purchased per block.\n * @custom:field elasticityMultiplier Determines the target resource limit along with\n * the resource limit.\n * @custom:field baseFeeMaxChangeDenominator Determines max change on fee per block.\n * @custom:field minimumBaseFee The min deposit base fee, it is clamped to this\n * value.\n * @custom:field systemTxMaxGas The amount of gas supplied to the system\n * transaction. This should be set to the same number\n * that the op-node sets as the gas limit for the\n * system transaction.\n * @custom:field maximumBaseFee The max deposit base fee, it is clamped to this\n * value.\n */\n struct ResourceConfig {\n uint32 maxResourceLimit;\n uint8 elasticityMultiplier;\n uint8 baseFeeMaxChangeDenominator;\n uint32 minimumBaseFee;\n uint32 systemTxMaxGas;\n uint128 maximumBaseFee;\n }\n\n /**\n * @notice EIP-1559 style gas parameters.\n */\n ResourceParams public params;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n */\n uint256[48] private __gap;\n\n /**\n * @notice Meters access to a function based an amount of a requested resource.\n *\n * @param _amount Amount of the resource requested.\n */\n modifier metered(uint64 _amount) {\n // Record initial gas amount so we can refund for it later.\n uint256 initialGas = gasleft();\n\n // Run the underlying function.\n _;\n\n // Run the metering function.\n _metered(_amount, initialGas);\n }\n\n /**\n * @notice An internal function that holds all of the logic for metering a resource.\n *\n * @param _amount Amount of the resource requested.\n * @param _initialGas The amount of gas before any modifier execution.\n */\n function _metered(uint64 _amount, uint256 _initialGas) internal {\n // Update block number and base fee if necessary.\n uint256 blockDiff = block.number - params.prevBlockNum;\n\n ResourceConfig memory config = _resourceConfig();\n int256 targetResourceLimit = int256(uint256(config.maxResourceLimit)) /\n int256(uint256(config.elasticityMultiplier));\n\n if (blockDiff > 0) {\n // Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate\n // at which deposits can be created and therefore limit the potential for deposits to\n // spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes.\n int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - targetResourceLimit;\n int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) /\n (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator)));\n\n // Update base fee by adding the base fee delta and clamp the resulting value between\n // min and max.\n int256 newBaseFee = Arithmetic.clamp({\n _value: int256(uint256(params.prevBaseFee)) + baseFeeDelta,\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n\n // If we skipped more than one block, we also need to account for every empty block.\n // Empty block means there was no demand for deposits in that block, so we should\n // reflect this lack of demand in the fee.\n if (blockDiff > 1) {\n // Update the base fee by repeatedly applying the exponent 1-(1/change_denominator)\n // blockDiff - 1 times. Simulates multiple empty blocks. Clamp the resulting value\n // between min and max.\n newBaseFee = Arithmetic.clamp({\n _value: Arithmetic.cdexp({\n _coefficient: newBaseFee,\n _denominator: int256(uint256(config.baseFeeMaxChangeDenominator)),\n _exponent: int256(blockDiff - 1)\n }),\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n }\n\n // Update new base fee, reset bought gas, and update block number.\n params.prevBaseFee = uint128(uint256(newBaseFee));\n params.prevBoughtGas = 0;\n params.prevBlockNum = uint64(block.number);\n }\n\n // Make sure we can actually buy the resource amount requested by the user.\n params.prevBoughtGas += _amount;\n require(\n int256(uint256(params.prevBoughtGas)) <= int256(uint256(config.maxResourceLimit)),\n \"ResourceMetering: cannot buy more gas than available gas limit\"\n );\n\n // Determine the amount of ETH to be paid.\n uint256 resourceCost = uint256(_amount) * uint256(params.prevBaseFee);\n\n // We currently charge for this ETH amount as an L1 gas burn, so we convert the ETH amount\n // into gas by dividing by the L1 base fee. We assume a minimum base fee of 1 gwei to avoid\n // division by zero for L1s that don't support 1559 or to avoid excessive gas burns during\n // periods of extremely low L1 demand. One-day average gas fee hasn't dipped below 1 gwei\n // during any 1 day period in the last 5 years, so should be fine.\n uint256 gasCost = resourceCost / Math.max(block.basefee, 1 gwei);\n\n // Give the user a refund based on the amount of gas they used to do all of the work up to\n // this point. Since we're at the end of the modifier, this should be pretty accurate. Acts\n // effectively like a dynamic stipend (with a minimum value).\n uint256 usedGas = _initialGas - gasleft();\n if (gasCost > usedGas) {\n Burn.gas(gasCost - usedGas);\n }\n }\n\n /**\n * @notice Virtual function that returns the resource config. Contracts that inherit this\n * contract must implement this function.\n *\n * @return ResourceConfig\n */\n function _resourceConfig() internal virtual returns (ResourceConfig memory);\n\n /**\n * @notice Sets initial resource parameter values. This function must either be called by the\n * initializer function of an upgradeable child contract.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __ResourceMetering_init() internal onlyInitializing {\n params = ResourceParams({\n prevBaseFee: 1 gwei,\n prevBoughtGas: 0,\n prevBlockNum: uint64(block.number)\n });\n }\n}\n" - }, - "contracts/L1/SystemConfig.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { ResourceMetering } from \"./ResourceMetering.sol\";\n\n/**\n * @title SystemConfig\n * @notice The SystemConfig contract is used to manage configuration of an Optimism network. All\n * configuration is stored on L1 and picked up by L2 as part of the derviation of the L2\n * chain.\n */\ncontract SystemConfig is OwnableUpgradeable, Semver {\n /**\n * @notice Enum representing different types of updates.\n *\n * @custom:value BATCHER Represents an update to the batcher hash.\n * @custom:value GAS_CONFIG Represents an update to txn fee config on L2.\n * @custom:value GAS_LIMIT Represents an update to gas limit on L2.\n * @custom:value UNSAFE_BLOCK_SIGNER Represents an update to the signer key for unsafe\n * block distrubution.\n */\n enum UpdateType {\n BATCHER,\n GAS_CONFIG,\n GAS_LIMIT,\n UNSAFE_BLOCK_SIGNER\n }\n\n /**\n * @notice Version identifier, used for upgrades.\n */\n uint256 public constant VERSION = 0;\n\n /**\n * @notice Storage slot that the unsafe block signer is stored at. Storing it at this\n * deterministic storage slot allows for decoupling the storage layout from the way\n * that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value.\n */\n bytes32 public constant UNSAFE_BLOCK_SIGNER_SLOT = keccak256(\"systemconfig.unsafeblocksigner\");\n\n /**\n * @notice Fixed L2 gas overhead. Used as part of the L2 fee calculation.\n */\n uint256 public overhead;\n\n /**\n * @notice Dynamic L2 gas overhead. Used as part of the L2 fee calculation.\n */\n uint256 public scalar;\n\n /**\n * @notice Identifier for the batcher. For version 1 of this configuration, this is represented\n * as an address left-padded with zeros to 32 bytes.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice L2 block gas limit.\n */\n uint64 public gasLimit;\n\n /**\n * @notice The configuration for the deposit fee market. Used by the OptimismPortal\n * to meter the cost of buying L2 gas on L1. Set as internal and wrapped with a getter\n * so that the struct is returned instead of a tuple.\n */\n ResourceMetering.ResourceConfig internal _resourceConfig;\n\n /**\n * @notice Emitted when configuration is updated\n *\n * @param version SystemConfig version.\n * @param updateType Type of update.\n * @param data Encoded update data.\n */\n event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);\n\n /**\n * @custom:semver 1.3.0\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n * @param _unsafeBlockSigner Initial unsafe block signer address.\n * @param _config Initial resource config.\n */\n constructor(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner,\n ResourceMetering.ResourceConfig memory _config\n ) Semver(1, 3, 0) {\n initialize({\n _owner: _owner,\n _overhead: _overhead,\n _scalar: _scalar,\n _batcherHash: _batcherHash,\n _gasLimit: _gasLimit,\n _unsafeBlockSigner: _unsafeBlockSigner,\n _config: _config\n });\n }\n\n /**\n * @notice Initializer. The resource config must be set before the\n * require check.\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n * @param _unsafeBlockSigner Initial unsafe block signer address.\n * @param _config Initial ResourceConfig.\n */\n function initialize(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner,\n ResourceMetering.ResourceConfig memory _config\n ) public initializer {\n __Ownable_init();\n transferOwnership(_owner);\n overhead = _overhead;\n scalar = _scalar;\n batcherHash = _batcherHash;\n gasLimit = _gasLimit;\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n _setResourceConfig(_config);\n require(_gasLimit >= minimumGasLimit(), \"SystemConfig: gas limit too low\");\n }\n\n /**\n * @notice Returns the minimum L2 gas limit that can be safely set for the system to\n * operate. The L2 gas limit must be larger than or equal to the amount of\n * gas that is allocated for deposits per block plus the amount of gas that\n * is allocated for the system transaction.\n * This function is used to determine if changes to parameters are safe.\n *\n * @return uint64\n */\n function minimumGasLimit() public view returns (uint64) {\n return uint64(_resourceConfig.maxResourceLimit) + uint64(_resourceConfig.systemTxMaxGas);\n }\n\n /**\n * @notice High level getter for the unsafe block signer address. Unsafe blocks can be\n * propagated across the p2p network if they are signed by the key corresponding to\n * this address.\n *\n * @return Address of the unsafe block signer.\n */\n // solhint-disable-next-line ordering\n function unsafeBlockSigner() external view returns (address) {\n address addr;\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n addr := sload(slot)\n }\n return addr;\n }\n\n /**\n * @notice Updates the unsafe block signer address.\n *\n * @param _unsafeBlockSigner New unsafe block signer address.\n */\n function setUnsafeBlockSigner(address _unsafeBlockSigner) external onlyOwner {\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n\n bytes memory data = abi.encode(_unsafeBlockSigner);\n emit ConfigUpdate(VERSION, UpdateType.UNSAFE_BLOCK_SIGNER, data);\n }\n\n /**\n * @notice Updates the batcher hash.\n *\n * @param _batcherHash New batcher hash.\n */\n function setBatcherHash(bytes32 _batcherHash) external onlyOwner {\n batcherHash = _batcherHash;\n\n bytes memory data = abi.encode(_batcherHash);\n emit ConfigUpdate(VERSION, UpdateType.BATCHER, data);\n }\n\n /**\n * @notice Updates gas config.\n *\n * @param _overhead New overhead value.\n * @param _scalar New scalar value.\n */\n function setGasConfig(uint256 _overhead, uint256 _scalar) external onlyOwner {\n overhead = _overhead;\n scalar = _scalar;\n\n bytes memory data = abi.encode(_overhead, _scalar);\n emit ConfigUpdate(VERSION, UpdateType.GAS_CONFIG, data);\n }\n\n /**\n * @notice Updates the L2 gas limit.\n *\n * @param _gasLimit New gas limit.\n */\n function setGasLimit(uint64 _gasLimit) external onlyOwner {\n require(_gasLimit >= minimumGasLimit(), \"SystemConfig: gas limit too low\");\n gasLimit = _gasLimit;\n\n bytes memory data = abi.encode(_gasLimit);\n emit ConfigUpdate(VERSION, UpdateType.GAS_LIMIT, data);\n }\n\n /**\n * @notice Low level setter for the unsafe block signer address. This function exists to\n * deduplicate code around storing the unsafeBlockSigner address in storage.\n *\n * @param _unsafeBlockSigner New unsafeBlockSigner value.\n */\n function _setUnsafeBlockSigner(address _unsafeBlockSigner) internal {\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n sstore(slot, _unsafeBlockSigner)\n }\n }\n\n /**\n * @notice A getter for the resource config. Ensures that the struct is\n * returned instead of a tuple.\n *\n * @return ResourceConfig\n */\n function resourceConfig() external view returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig;\n }\n\n /**\n * @notice An external setter for the resource config. In the future, this\n * method may emit an event that the `op-node` picks up for when the\n * resource config is changed.\n *\n * @param _config The new resource config values.\n */\n function setResourceConfig(ResourceMetering.ResourceConfig memory _config) external onlyOwner {\n _setResourceConfig(_config);\n }\n\n /**\n * @notice An internal setter for the resource config. Ensures that the\n * config is sane before storing it by checking for invariants.\n *\n * @param _config The new resource config.\n */\n function _setResourceConfig(ResourceMetering.ResourceConfig memory _config) internal {\n // Min base fee must be less than or equal to max base fee.\n require(\n _config.minimumBaseFee <= _config.maximumBaseFee,\n \"SystemConfig: min base fee must be less than max base\"\n );\n // Base fee change denominator must be greater than 1.\n require(\n _config.baseFeeMaxChangeDenominator > 1,\n \"SystemConfig: denominator must be larger than 1\"\n );\n // Max resource limit plus system tx gas must be less than or equal to the L2 gas limit.\n // The gas limit must be increased before these values can be increased.\n require(\n _config.maxResourceLimit + _config.systemTxMaxGas <= gasLimit,\n \"SystemConfig: gas limit too low\"\n );\n // Elasticity multiplier must be greater than 0.\n require(\n _config.elasticityMultiplier > 0,\n \"SystemConfig: elasticity multiplier cannot be 0\"\n );\n // No precision loss when computing target resource limit.\n require(\n ((_config.maxResourceLimit / _config.elasticityMultiplier) *\n _config.elasticityMultiplier) == _config.maxResourceLimit,\n \"SystemConfig: precision loss with target resource limit\"\n );\n\n _resourceConfig = _config;\n }\n}\n" - }, - "contracts/L2/BaseFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000019\n * @title BaseFeeVault\n * @notice The BaseFeeVault accumulates the base fee that is paid by transactions.\n */\ncontract BaseFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}\n}\n" - }, - "contracts/L2/CrossDomainOwnable.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\n/**\n * @title CrossDomainOwnable\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is only safe to be used if the\n * CrossDomainMessenger system is bypassed and the caller on L1 is calling the\n * OptimismPortal directly.\n */\nabstract contract CrossDomainOwnable is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `msg.sender` is the owner of the contract.\n */\n function _checkOwner() internal view override {\n require(\n owner() == AddressAliasHelper.undoL1ToL2Alias(msg.sender),\n \"CrossDomainOwnable: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/CrossDomainOwnable2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L2CrossDomainMessenger } from \"./L2CrossDomainMessenger.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title CrossDomainOwnable2\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is meant to be used with systems that use\n * the CrossDomainMessenger system. It will not work if the OptimismPortal is used\n * directly.\n */\nabstract contract CrossDomainOwnable2 is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `xDomainMessageSender` is the owner of the contract. This value is set to the caller\n * of the L1CrossDomainMessenger.\n */\n function _checkOwner() internal view override {\n L2CrossDomainMessenger messenger = L2CrossDomainMessenger(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER\n );\n\n require(\n msg.sender == address(messenger),\n \"CrossDomainOwnable2: caller is not the messenger\"\n );\n\n require(\n owner() == messenger.xDomainMessageSender(),\n \"CrossDomainOwnable2: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/CrossDomainOwnable3.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L2CrossDomainMessenger } from \"./L2CrossDomainMessenger.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title CrossDomainOwnable3\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on either L1 or L2. Note that this contract is meant to be used with systems\n * that use the CrossDomainMessenger system. It will not work if the OptimismPortal is\n * used directly.\n */\nabstract contract CrossDomainOwnable3 is Ownable {\n /**\n * @notice If true, the contract uses the cross domain _checkOwner function override. If false\n * it uses the standard Ownable _checkOwner function.\n */\n bool public isLocal = true;\n\n /**\n * @notice Emits when ownership of the contract is transferred. Includes the\n * isLocal field in addition to the standard `Ownable` OwnershipTransferred event.\n */\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner,\n bool isLocal\n );\n\n /**\n * @notice Allows for ownership to be transferred with specifying the locality.\n * @param _owner The new owner of the contract.\n * @param _isLocal Configures the locality of the ownership.\n */\n function transferOwnership(address _owner, bool _isLocal) external onlyOwner {\n require(_owner != address(0), \"CrossDomainOwnable3: new owner is the zero address\");\n\n address oldOwner = owner();\n _transferOwnership(_owner);\n isLocal = _isLocal;\n\n emit OwnershipTransferred(oldOwner, _owner, _isLocal);\n }\n\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `xDomainMessageSender` is the owner of the contract. This value is set to the caller\n * of the L1CrossDomainMessenger.\n */\n function _checkOwner() internal view override {\n if (isLocal) {\n require(owner() == msg.sender, \"CrossDomainOwnable3: caller is not the owner\");\n } else {\n L2CrossDomainMessenger messenger = L2CrossDomainMessenger(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER\n );\n\n require(\n msg.sender == address(messenger),\n \"CrossDomainOwnable3: caller is not the messenger\"\n );\n\n require(\n owner() == messenger.xDomainMessageSender(),\n \"CrossDomainOwnable3: caller is not the owner\"\n );\n }\n }\n}\n" - }, - "contracts/L2/GasPriceOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000000F\n * @title GasPriceOracle\n * @notice This contract maintains the variables responsible for computing the L1 portion of the\n * total fee charged on L2. Before Bedrock, this contract held variables in state that were\n * read during the state transition function to compute the L1 portion of the transaction\n * fee. After Bedrock, this contract now simply proxies the L1Block contract, which has\n * the values used to compute the L1 portion of the fee in its state.\n *\n * The contract exposes an API that is useful for knowing how large the L1 portion of the\n * transaction fee will be. The following events were deprecated with Bedrock:\n * - event OverheadUpdated(uint256 overhead);\n * - event ScalarUpdated(uint256 scalar);\n * - event DecimalsUpdated(uint256 decimals);\n */\ncontract GasPriceOracle is Semver {\n /**\n * @notice Number of decimals used in the scalar.\n */\n uint256 public constant DECIMALS = 6;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Computes the L1 portion of the fee based on the size of the rlp encoded input\n * transaction, the current L1 base fee, and the various dynamic parameters.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for.\n *\n * @return L1 fee that should be paid for the tx\n */\n function getL1Fee(bytes memory _data) external view returns (uint256) {\n uint256 l1GasUsed = getL1GasUsed(_data);\n uint256 l1Fee = l1GasUsed * l1BaseFee();\n uint256 divisor = 10**DECIMALS;\n uint256 unscaled = l1Fee * scalar();\n uint256 scaled = unscaled / divisor;\n return scaled;\n }\n\n /**\n * @notice Retrieves the current gas price (base fee).\n *\n * @return Current L2 gas price (base fee).\n */\n function gasPrice() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current base fee.\n *\n * @return Current L2 base fee.\n */\n function baseFee() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current fee overhead.\n *\n * @return Current fee overhead.\n */\n function overhead() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead();\n }\n\n /**\n * @notice Retrieves the current fee scalar.\n *\n * @return Current fee scalar.\n */\n function scalar() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar();\n }\n\n /**\n * @notice Retrieves the latest known L1 base fee.\n *\n * @return Latest known L1 base fee.\n */\n function l1BaseFee() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee();\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the number of decimals used in the scalar.\n *\n * @return Number of decimals used in the scalar.\n */\n function decimals() public pure returns (uint256) {\n return DECIMALS;\n }\n\n /**\n * @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which\n * represents the per-transaction gas overhead of posting the transaction and state\n * roots to L1. Adds 68 bytes of padding to account for the fact that the input does\n * not have a signature.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for.\n *\n * @return Amount of L1 gas used to publish the transaction.\n */\n function getL1GasUsed(bytes memory _data) public view returns (uint256) {\n uint256 total = 0;\n uint256 length = _data.length;\n for (uint256 i = 0; i < length; i++) {\n if (_data[i] == 0) {\n total += 4;\n } else {\n total += 16;\n }\n }\n uint256 unsigned = total + overhead();\n return unsigned + (68 * 16);\n }\n}\n" - }, - "contracts/L2/L1Block.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000015\n * @title L1Block\n * @notice The L1Block predeploy gives users access to information about the last known L1 block.\n * Values within this contract are updated once per epoch (every L1 block) and can only be\n * set by the \"depositor\" account, a special system address. Depositor account transactions\n * are created by the protocol whenever we move to a new epoch.\n */\ncontract L1Block is Semver {\n /**\n * @notice Address of the special depositor account.\n */\n address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001;\n\n /**\n * @notice The latest L1 block number known by the L2 system.\n */\n uint64 public number;\n\n /**\n * @notice The latest L1 timestamp known by the L2 system.\n */\n uint64 public timestamp;\n\n /**\n * @notice The latest L1 basefee.\n */\n uint256 public basefee;\n\n /**\n * @notice The latest L1 blockhash.\n */\n bytes32 public hash;\n\n /**\n * @notice The number of L2 blocks in the same epoch.\n */\n uint64 public sequenceNumber;\n\n /**\n * @notice The versioned hash to authenticate the batcher by.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice The overhead value applied to the L1 portion of the transaction\n * fee.\n */\n uint256 public l1FeeOverhead;\n\n /**\n * @notice The scalar value applied to the L1 portion of the transaction fee.\n */\n uint256 public l1FeeScalar;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Updates the L1 block values.\n *\n * @param _number L1 blocknumber.\n * @param _timestamp L1 timestamp.\n * @param _basefee L1 basefee.\n * @param _hash L1 blockhash.\n * @param _sequenceNumber Number of L2 blocks since epoch start.\n * @param _batcherHash Versioned hash to authenticate batcher by.\n * @param _l1FeeOverhead L1 fee overhead.\n * @param _l1FeeScalar L1 fee scalar.\n */\n function setL1BlockValues(\n uint64 _number,\n uint64 _timestamp,\n uint256 _basefee,\n bytes32 _hash,\n uint64 _sequenceNumber,\n bytes32 _batcherHash,\n uint256 _l1FeeOverhead,\n uint256 _l1FeeScalar\n ) external {\n require(\n msg.sender == DEPOSITOR_ACCOUNT,\n \"L1Block: only the depositor account can set L1 block values\"\n );\n\n number = _number;\n timestamp = _timestamp;\n basefee = _basefee;\n hash = _hash;\n sequenceNumber = _sequenceNumber;\n batcherHash = _batcherHash;\n l1FeeOverhead = _l1FeeOverhead;\n l1FeeScalar = _l1FeeScalar;\n }\n}\n" - }, - "contracts/L2/L1FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000001A\n * @title L1FeeVault\n * @notice The L1FeeVault accumulates the L1 portion of the transaction fees.\n */\ncontract L1FeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}\n}\n" - }, - "contracts/L2/L2CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { L2ToL1MessagePasser } from \"./L2ToL1MessagePasser.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000007\n * @title L2CrossDomainMessenger\n * @notice The L2CrossDomainMessenger is a high-level interface for message passing between L1 and\n * L2 on the L2 side. Users are generally encouraged to use this contract instead of lower\n * level message passing contracts.\n */\ncontract L2CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @custom:semver 1.4.0\n *\n * @param _l1CrossDomainMessenger Address of the L1CrossDomainMessenger contract.\n */\n constructor(address _l1CrossDomainMessenger)\n Semver(1, 4, 0)\n CrossDomainMessenger(_l1CrossDomainMessenger)\n {\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote messenger. Use otherMessenger going forward.\n *\n * @return Address of the L1CrossDomainMessenger contract.\n */\n function l1CrossDomainMessenger() public view returns (address) {\n return OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)).initiateWithdrawal{\n value: _value\n }(_to, _gasLimit, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(Predeploys.L2_TO_L1_MESSAGE_PASSER);\n }\n}\n" - }, - "contracts/L2/L2ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../universal/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 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.1.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, 1, 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), \"L2ERC721Bridge: 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 \"L2ERC721Bridge: 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(OTHER_BRIDGE, message, _minGasLimit);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L2/L2StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000010\n * @title L2StandardBridge\n * @notice The L2StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L2, it will be escrowed within this\n * contract. If the ERC20 token is native to L1, it will be burnt.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L2StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal from L2 to L1 is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _otherBridge Address of the L1StandardBridge.\n */\n constructor(address payable _otherBridge)\n Semver(1, 1, 0)\n StandardBridge(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER), _otherBridge)\n {}\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n */\n receive() external payable override onlyEOA {\n _initiateWithdrawal(\n Predeploys.LEGACY_ERC20_ETH,\n msg.sender,\n msg.sender,\n msg.value,\n RECEIVE_DEFAULT_GAS_LIMIT,\n bytes(\"\")\n );\n }\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1.\n * This function only works with OptimismMintableERC20 tokens or ether. Use the\n * `bridgeERC20` function to bridge native L2 tokens to L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdraw(\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual onlyEOA {\n _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1 to a target account on L1.\n * Note that if ETH is sent to a contract on L1 and the call fails, then that ETH will\n * be locked in the L1StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n * This function only works with OptimismMintableERC20 tokens or ether. Use the\n * `bridgeERC20To` function to bridge native L2 tokens to L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdrawTo(\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual {\n _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a deposit from L1 to L2. To finalize a deposit of ether, use address(0)\n * and the l1Token and the Legacy ERC20 ether predeploy address as the l2Token.\n *\n * @param _l1Token Address of the L1 token to deposit.\n * @param _l2Token Address of the corresponding L2 token.\n * @param _from Address of the depositor.\n * @param _to Address of the recipient.\n * @param _amount Amount of the tokens being deposited.\n * @param _extraData Extra data attached to the deposit.\n */\n function finalizeDeposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable virtual {\n if (_l1Token == address(0) && _l2Token == Predeploys.LEGACY_ERC20_ETH) {\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n } else {\n finalizeBridgeERC20(_l2Token, _l1Token, _from, _to, _amount, _extraData);\n }\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L1 bridge contract.\n *\n * @return Address of the corresponding L1 bridge contract.\n */\n function l1TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @custom:legacy\n * @notice Internal function to a withdrawal from L2 to L1 to a target account on L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _from Address of the withdrawer.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function _initiateWithdrawal(\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n if (_l2Token == Predeploys.LEGACY_ERC20_ETH) {\n _initiateBridgeETH(_from, _to, _amount, _minGasLimit, _extraData);\n } else {\n address l1Token = OptimismMintableERC20(_l2Token).l1Token();\n _initiateBridgeERC20(_l2Token, l1Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n }\n\n /**\n * @notice Emits the legacy WithdrawalInitiated event followed by the ETHBridgeInitiated event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit WithdrawalInitiated(\n address(0),\n Predeploys.LEGACY_ERC20_ETH,\n _from,\n _to,\n _amount,\n _extraData\n );\n super._emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy DepositFinalized event followed by the ETHBridgeFinalized event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit DepositFinalized(\n address(0),\n Predeploys.LEGACY_ERC20_ETH,\n _from,\n _to,\n _amount,\n _extraData\n );\n super._emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy WithdrawalInitiated event followed by the ERC20BridgeInitiated\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit WithdrawalInitiated(_remoteToken, _localToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy DepositFinalized event followed by the ERC20BridgeFinalized event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit DepositFinalized(_remoteToken, _localToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/L2/L2ToL1MessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000016\n * @title L2ToL1MessagePasser\n * @notice The L2ToL1MessagePasser is a dedicated contract where messages that are being sent from\n * L2 to L1 can be stored. The storage root of this contract is pulled up to the top level\n * of the L2 output to reduce the cost of proving the existence of sent messages.\n */\ncontract L2ToL1MessagePasser is Semver {\n /**\n * @notice The L1 gas limit set when eth is withdrawn using the receive() function.\n */\n uint256 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Current message version identifier.\n */\n uint16 public constant MESSAGE_VERSION = 1;\n\n /**\n * @notice Includes the message hashes for all withdrawals\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @notice A unique value hashed with each withdrawal.\n */\n uint240 internal msgNonce;\n\n /**\n * @notice Emitted any time a withdrawal is initiated.\n *\n * @param nonce Unique value corresponding to each withdrawal.\n * @param sender The L2 account address which initiated the withdrawal.\n * @param target The L1 account address the call will be send to.\n * @param value The ETH value submitted for withdrawal, to be forwarded to the target.\n * @param gasLimit The minimum amount of gas that must be provided when withdrawing.\n * @param data The data to be forwarded to the target on L1.\n * @param withdrawalHash The hash of the withdrawal.\n */\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n /**\n * @notice Emitted when the balance of this contract is burned.\n *\n * @param amount Amount of ETh that was burned.\n */\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Allows users to withdraw ETH by sending directly to this contract.\n */\n receive() external payable {\n initiateWithdrawal(msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @notice Removes all ETH held by this contract from the state. Used to prevent the amount of\n * ETH on L2 inflating when ETH is withdrawn. Currently only way to do this is to\n * create a contract and self-destruct it to itself. Anyone can call this function. Not\n * incentivized since this function is very cheap.\n */\n function burn() external {\n uint256 balance = address(this).balance;\n Burn.eth(balance);\n emit WithdrawerBalanceBurnt(balance);\n }\n\n /**\n * @notice Sends a message from L2 to L1.\n *\n * @param _target Address to call on L1 execution.\n * @param _gasLimit Minimum gas limit for executing the message on L1.\n * @param _data Data to forward to L1 target.\n */\n function initiateWithdrawal(\n address _target,\n uint256 _gasLimit,\n bytes memory _data\n ) public payable {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messageNonce(),\n sender: msg.sender,\n target: _target,\n value: msg.value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n sentMessages[withdrawalHash] = true;\n\n emit MessagePassed(\n messageNonce(),\n msg.sender,\n _target,\n msg.value,\n _gasLimit,\n _data,\n withdrawalHash\n );\n\n unchecked {\n ++msgNonce;\n }\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" - }, - "contracts/L2/SequencerFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000011\n * @title SequencerFeeVault\n * @notice The SequencerFeeVault is the contract that holds any fees paid to the Sequencer during\n * transaction processing and block production.\n */\ncontract SequencerFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the recipient address.\n *\n * @return The recipient address.\n */\n function l1FeeWallet() public view returns (address) {\n return RECIPIENT;\n }\n}\n" - }, - "contracts/deployment/PortalSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/**\n * @title PortalSender\n * @notice The PortalSender is a simple intermediate contract that will transfer the balance of the\n * L1StandardBridge to the OptimismPortal during the Bedrock migration.\n */\ncontract PortalSender {\n /**\n * @notice Address of the OptimismPortal contract.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @param _portal Address of the OptimismPortal contract.\n */\n constructor(OptimismPortal _portal) {\n PORTAL = _portal;\n }\n\n /**\n * @notice Sends balance of this contract to the OptimismPortal.\n */\n function donate() public {\n PORTAL.donateETH{ value: address(this).balance }();\n }\n}\n" - }, - "contracts/deployment/SystemDictator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { PortalSender } from \"./PortalSender.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\n/**\n * @title SystemDictator\n * @notice The SystemDictator is responsible for coordinating the deployment of a full Bedrock\n * system. The SystemDictator is designed to support both fresh network deployments and\n * upgrades to existing pre-Bedrock systems.\n */\ncontract SystemDictator is OwnableUpgradeable {\n /**\n * @notice Basic system configuration.\n */\n struct GlobalConfig {\n AddressManager addressManager;\n ProxyAdmin proxyAdmin;\n address controller;\n address finalOwner;\n }\n\n /**\n * @notice Set of proxy addresses.\n */\n struct ProxyAddressConfig {\n address l2OutputOracleProxy;\n address optimismPortalProxy;\n address l1CrossDomainMessengerProxy;\n address l1StandardBridgeProxy;\n address optimismMintableERC20FactoryProxy;\n address l1ERC721BridgeProxy;\n address systemConfigProxy;\n }\n\n /**\n * @notice Set of implementation addresses.\n */\n struct ImplementationAddressConfig {\n L2OutputOracle l2OutputOracleImpl;\n OptimismPortal optimismPortalImpl;\n L1CrossDomainMessenger l1CrossDomainMessengerImpl;\n L1StandardBridge l1StandardBridgeImpl;\n OptimismMintableERC20Factory optimismMintableERC20FactoryImpl;\n L1ERC721Bridge l1ERC721BridgeImpl;\n PortalSender portalSenderImpl;\n SystemConfig systemConfigImpl;\n }\n\n /**\n * @notice Dynamic L2OutputOracle config.\n */\n struct L2OutputOracleDynamicConfig {\n uint256 l2OutputOracleStartingBlockNumber;\n uint256 l2OutputOracleStartingTimestamp;\n }\n\n /**\n * @notice Values for the system config contract.\n */\n struct SystemConfigConfig {\n address owner;\n uint256 overhead;\n uint256 scalar;\n bytes32 batcherHash;\n uint64 gasLimit;\n address unsafeBlockSigner;\n ResourceMetering.ResourceConfig resourceConfig;\n }\n\n /**\n * @notice Combined system configuration.\n */\n struct DeployConfig {\n GlobalConfig globalConfig;\n ProxyAddressConfig proxyAddressConfig;\n ImplementationAddressConfig implementationAddressConfig;\n SystemConfigConfig systemConfigConfig;\n }\n\n /**\n * @notice Step after which exit 1 can no longer be used.\n */\n uint8 public constant EXIT_1_NO_RETURN_STEP = 3;\n\n /**\n * @notice Step where proxy ownership is transferred.\n */\n uint8 public constant PROXY_TRANSFER_STEP = 4;\n\n /**\n * @notice System configuration.\n */\n DeployConfig public config;\n\n /**\n * @notice Dynamic configuration for the L2OutputOracle.\n */\n L2OutputOracleDynamicConfig public l2OutputOracleDynamicConfig;\n\n /**\n * @notice Dynamic configuration for the OptimismPortal. Determines\n * if the system should be paused when initialized.\n */\n bool public optimismPortalDynamicConfig;\n\n /**\n * @notice Current step;\n */\n uint8 public currentStep;\n\n /**\n * @notice Whether or not dynamic config has been set.\n */\n bool public dynamicConfigSet;\n\n /**\n * @notice Whether or not the deployment is finalized.\n */\n bool public finalized;\n\n /**\n * @notice Whether or not the deployment has been exited.\n */\n bool public exited;\n\n /**\n * @notice Address of the old L1CrossDomainMessenger implementation.\n */\n address public oldL1CrossDomainMessenger;\n\n /**\n * @notice Checks that the current step is the expected step, then bumps the current step.\n *\n * @param _step Current step.\n */\n modifier step(uint8 _step) {\n require(!finalized, \"SystemDictator: already finalized\");\n require(!exited, \"SystemDictator: already exited\");\n require(currentStep == _step, \"SystemDictator: incorrect step\");\n _;\n currentStep++;\n }\n\n /**\n * @notice Constructor required to ensure that the implementation of the SystemDictator is\n * initialized upon deployment.\n */\n constructor() {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n // Using this shorter variable as an alias for address(0) just prevents us from having to\n // to use a new line for every single parameter.\n address zero = address(0);\n initialize(\n DeployConfig(\n GlobalConfig(AddressManager(zero), ProxyAdmin(zero), zero, zero),\n ProxyAddressConfig(zero, zero, zero, zero, zero, zero, zero),\n ImplementationAddressConfig(\n L2OutputOracle(zero),\n OptimismPortal(payable(zero)),\n L1CrossDomainMessenger(zero),\n L1StandardBridge(payable(zero)),\n OptimismMintableERC20Factory(zero),\n L1ERC721Bridge(zero),\n PortalSender(zero),\n SystemConfig(zero)\n ),\n SystemConfigConfig(zero, 0, 0, bytes32(0), 0, zero, rcfg)\n )\n );\n }\n\n /**\n * @param _config System configuration.\n */\n function initialize(DeployConfig memory _config) public initializer {\n config = _config;\n currentStep = 1;\n __Ownable_init();\n _transferOwnership(config.globalConfig.controller);\n }\n\n /**\n * @notice Allows the owner to update dynamic config.\n *\n * @param _l2OutputOracleDynamicConfig Dynamic L2OutputOracle config.\n * @param _optimismPortalDynamicConfig Dynamic OptimismPortal config.\n */\n function updateDynamicConfig(\n L2OutputOracleDynamicConfig memory _l2OutputOracleDynamicConfig,\n bool _optimismPortalDynamicConfig\n ) external onlyOwner {\n l2OutputOracleDynamicConfig = _l2OutputOracleDynamicConfig;\n optimismPortalDynamicConfig = _optimismPortalDynamicConfig;\n dynamicConfigSet = true;\n }\n\n /**\n * @notice Configures the ProxyAdmin contract.\n */\n function step1() public onlyOwner step(1) {\n // Set the AddressManager in the ProxyAdmin.\n config.globalConfig.proxyAdmin.setAddressManager(config.globalConfig.addressManager);\n\n // Set the L1CrossDomainMessenger to the RESOLVED proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n ProxyAdmin.ProxyType.RESOLVED\n );\n\n // Set the implementation name for the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.setImplementationName(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Set the L1StandardBridge to the CHUGSPLASH proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1StandardBridgeProxy,\n ProxyAdmin.ProxyType.CHUGSPLASH\n );\n\n // Upgrade and initialize the SystemConfig so the Sequencer can start up.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.systemConfigProxy),\n address(config.implementationAddressConfig.systemConfigImpl),\n abi.encodeCall(\n SystemConfig.initialize,\n (\n config.systemConfigConfig.owner,\n config.systemConfigConfig.overhead,\n config.systemConfigConfig.scalar,\n config.systemConfigConfig.batcherHash,\n config.systemConfigConfig.gasLimit,\n config.systemConfigConfig.unsafeBlockSigner,\n config.systemConfigConfig.resourceConfig\n )\n )\n );\n }\n\n /**\n * @notice Pauses the system by shutting down the L1CrossDomainMessenger and setting the\n * deposit halt flag to tell the Sequencer's DTL to stop accepting deposits.\n */\n function step2() public onlyOwner step(2) {\n // Store the address of the old L1CrossDomainMessenger implementation. We will need this\n // address in the case that we have to exit early.\n oldL1CrossDomainMessenger = config.globalConfig.addressManager.getAddress(\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Temporarily brick the L1CrossDomainMessenger by setting its implementation address to\n // address(0) which will cause the ResolvedDelegateProxy to revert. Better than pausing\n // the L1CrossDomainMessenger via pause() because it can be easily reverted.\n config.globalConfig.addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(0));\n\n // Set the DTL shutoff block, which will tell the DTL to stop syncing new deposits from the\n // CanonicalTransactionChain. We do this by setting an address in the AddressManager\n // because the DTL already has a reference to the AddressManager and this way we don't also\n // need to give it a reference to the SystemDictator.\n config.globalConfig.addressManager.setAddress(\n \"DTL_SHUTOFF_BLOCK\",\n address(uint160(block.number))\n );\n }\n\n /**\n * @notice Removes deprecated addresses from the AddressManager.\n */\n function step3() public onlyOwner step(EXIT_1_NO_RETURN_STEP) {\n // Remove all deprecated addresses from the AddressManager\n string[17] memory deprecated = [\n \"OVM_CanonicalTransactionChain\",\n \"OVM_L2CrossDomainMessenger\",\n \"OVM_DecompressionPrecompileAddress\",\n \"OVM_Sequencer\",\n \"OVM_Proposer\",\n \"OVM_ChainStorageContainer-CTC-batches\",\n \"OVM_ChainStorageContainer-CTC-queue\",\n \"OVM_CanonicalTransactionChain\",\n \"OVM_StateCommitmentChain\",\n \"OVM_BondManager\",\n \"OVM_ExecutionManager\",\n \"OVM_FraudVerifier\",\n \"OVM_StateManagerFactory\",\n \"OVM_StateTransitionerFactory\",\n \"OVM_SafetyChecker\",\n \"OVM_L1MultiMessageRelayer\",\n \"BondManager\"\n ];\n\n for (uint256 i = 0; i < deprecated.length; i++) {\n config.globalConfig.addressManager.setAddress(deprecated[i], address(0));\n }\n }\n\n /**\n * @notice Transfers system ownership to the ProxyAdmin.\n */\n function step4() public onlyOwner step(PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the ProxyAdmin.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1StandardBridge to the ProxyAdmin.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the ProxyAdmin.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.proxyAdmin)\n );\n }\n\n /**\n * @notice Upgrades and initializes proxy contracts.\n */\n function step5() public onlyOwner step(5) {\n // Dynamic config must be set before we can initialize the L2OutputOracle.\n require(dynamicConfigSet, \"SystemDictator: dynamic oracle config is not yet initialized\");\n\n // Upgrade and initialize the L2OutputOracle.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l2OutputOracleProxy),\n address(config.implementationAddressConfig.l2OutputOracleImpl),\n abi.encodeCall(\n L2OutputOracle.initialize,\n (\n l2OutputOracleDynamicConfig.l2OutputOracleStartingBlockNumber,\n l2OutputOracleDynamicConfig.l2OutputOracleStartingTimestamp\n )\n )\n );\n\n // Upgrade and initialize the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.optimismPortalProxy),\n address(config.implementationAddressConfig.optimismPortalImpl),\n abi.encodeCall(OptimismPortal.initialize, (optimismPortalDynamicConfig))\n );\n\n // Upgrade the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1CrossDomainMessengerProxy),\n address(config.implementationAddressConfig.l1CrossDomainMessengerImpl)\n );\n\n // Try to initialize the L1CrossDomainMessenger, only fail if it's already been initialized.\n try\n L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy)\n .initialize()\n {\n // L1CrossDomainMessenger is the one annoying edge case difference between existing\n // networks and fresh networks because in existing networks it'll already be\n // initialized but in fresh networks it won't be. Try/catch is the easiest and most\n // consistent way to handle this because initialized() is not exposed publicly.\n } catch Error(string memory reason) {\n require(\n keccak256(abi.encodePacked(reason)) ==\n keccak256(\"Initializable: contract is already initialized\"),\n string.concat(\"SystemDictator: unexpected error initializing L1XDM: \", reason)\n );\n } catch {\n revert(\"SystemDictator: unexpected error initializing L1XDM (no reason)\");\n }\n\n // Transfer ETH from the L1StandardBridge to the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.portalSenderImpl),\n abi.encodeCall(PortalSender.donate, ())\n );\n\n // Upgrade the L1StandardBridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.l1StandardBridgeImpl)\n );\n\n // Upgrade the OptimismMintableERC20Factory (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.optimismMintableERC20FactoryProxy),\n address(config.implementationAddressConfig.optimismMintableERC20FactoryImpl)\n );\n\n // Upgrade the L1ERC721Bridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1ERC721BridgeProxy),\n address(config.implementationAddressConfig.l1ERC721BridgeImpl)\n );\n }\n\n /**\n * @notice Calls the first 2 steps of the migration process.\n */\n function phase1() external onlyOwner {\n step1();\n step2();\n }\n\n /**\n * @notice Calls the remaining steps of the migration process, and finalizes.\n */\n function phase2() external onlyOwner {\n step3();\n step4();\n step5();\n finalize();\n }\n\n /**\n * @notice Tranfers admin ownership to the final owner.\n */\n function finalize() public onlyOwner {\n // Transfer ownership of the ProxyAdmin to the final owner.\n config.globalConfig.proxyAdmin.transferOwnership(config.globalConfig.finalOwner);\n\n // Optionally also transfer AddressManager and L1StandardBridge if we still own it. Might\n // happen if we're exiting early.\n if (currentStep <= PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the final owner.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1StandardBridge to the final owner.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the final owner.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.finalOwner)\n );\n }\n\n // Mark the deployment as finalized.\n finalized = true;\n }\n\n /**\n * @notice First exit point, can only be called before step 3 is executed.\n */\n function exit1() external onlyOwner {\n require(\n currentStep == EXIT_1_NO_RETURN_STEP,\n \"SystemDictator: can only exit1 before step 3 is executed\"\n );\n\n // Reset the L1CrossDomainMessenger to the old implementation.\n config.globalConfig.addressManager.setAddress(\n \"OVM_L1CrossDomainMessenger\",\n oldL1CrossDomainMessenger\n );\n\n // Unset the DTL shutoff block which will allow the DTL to sync again.\n config.globalConfig.addressManager.setAddress(\"DTL_SHUTOFF_BLOCK\", address(0));\n\n // Mark the deployment as exited.\n exited = true;\n }\n}\n" - }, - "contracts/dispute/BondManager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport { GameType } from \"../libraries/DisputeTypes.sol\";\nimport { GameStatus } from \"../libraries/DisputeTypes.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\n\nimport { IDisputeGame } from \"./IDisputeGame.sol\";\nimport { IDisputeGameFactory } from \"./IDisputeGameFactory.sol\";\n\n/**\n * @title BondManager\n * @notice The Bond Manager serves as an escrow for permissionless output proposal bonds.\n */\ncontract BondManager {\n /**\n * @notice The Bond Type\n */\n struct Bond {\n address owner;\n uint256 expiration;\n bytes32 id;\n uint256 amount;\n }\n\n /**\n * @notice Mapping from bondId to bond.\n */\n mapping(bytes32 => Bond) public bonds;\n\n /**\n * @notice BondPosted is emitted when a bond is posted.\n * @param bondId is the id of the bond.\n * @param owner is the address that owns the bond.\n * @param expiration is the time at which the bond expires.\n * @param amount is the amount of the bond.\n */\n event BondPosted(bytes32 bondId, address owner, uint256 expiration, uint256 amount);\n\n /**\n * @notice BondSeized is emitted when a bond is seized.\n * @param bondId is the id of the bond.\n * @param owner is the address that owns the bond.\n * @param seizer is the address that seized the bond.\n * @param amount is the amount of the bond.\n */\n event BondSeized(bytes32 bondId, address owner, address seizer, uint256 amount);\n\n /**\n * @notice BondReclaimed is emitted when a bond is reclaimed by the owner.\n * @param bondId is the id of the bond.\n * @param claiment is the address that reclaimed the bond.\n * @param amount is the amount of the bond.\n */\n event BondReclaimed(bytes32 bondId, address claiment, uint256 amount);\n\n /**\n * @notice The permissioned dispute game factory.\n * @dev Used to verify the status of bonds.\n */\n IDisputeGameFactory public immutable DISPUTE_GAME_FACTORY;\n\n /**\n * @notice Amount of gas used to transfer ether when splitting the bond.\n * This is a reasonable amount of gas for a transfer, even to a smart contract.\n * The number of participants is bound of by the block gas limit.\n */\n uint256 private constant TRANSFER_GAS = 30_000;\n\n /**\n * @notice Instantiates the bond maanger with the registered dispute game factory.\n * @param _disputeGameFactory is the dispute game factory.\n */\n constructor(IDisputeGameFactory _disputeGameFactory) {\n DISPUTE_GAME_FACTORY = _disputeGameFactory;\n }\n\n /**\n * @notice Post a bond with a given id and owner.\n * @dev This function will revert if the provided bondId is already in use.\n * @param _bondId is the id of the bond.\n * @param _bondOwner is the address that owns the bond.\n * @param _minClaimHold is the minimum amount of time the owner\n * must wait before reclaiming their bond.\n */\n function post(\n bytes32 _bondId,\n address _bondOwner,\n uint256 _minClaimHold\n ) external payable {\n require(bonds[_bondId].owner == address(0), \"BondManager: BondId already posted.\");\n require(_bondOwner != address(0), \"BondManager: Owner cannot be the zero address.\");\n require(msg.value > 0, \"BondManager: Value must be non-zero.\");\n\n uint256 expiration = _minClaimHold + block.timestamp;\n bonds[_bondId] = Bond({\n owner: _bondOwner,\n expiration: expiration,\n id: _bondId,\n amount: msg.value\n });\n\n emit BondPosted(_bondId, _bondOwner, expiration, msg.value);\n }\n\n /**\n * @notice Seizes the bond with the given id.\n * @dev This function will revert if there is no bond at the given id.\n * @param _bondId is the id of the bond.\n */\n function seize(bytes32 _bondId) external {\n Bond memory b = bonds[_bondId];\n require(b.owner != address(0), \"BondManager: The bond does not exist.\");\n require(b.expiration >= block.timestamp, \"BondManager: Bond expired.\");\n\n IDisputeGame caller = IDisputeGame(msg.sender);\n IDisputeGame game = DISPUTE_GAME_FACTORY.games(\n GameType.ATTESTATION,\n caller.rootClaim(),\n caller.extraData()\n );\n require(msg.sender == address(game), \"BondManager: Unauthorized seizure.\");\n require(game.status() == GameStatus.CHALLENGER_WINS, \"BondManager: Game incomplete.\");\n\n delete bonds[_bondId];\n\n emit BondSeized(_bondId, b.owner, msg.sender, b.amount);\n\n bool success = SafeCall.send(payable(msg.sender), gasleft(), b.amount);\n require(success, \"BondManager: Failed to send Ether.\");\n }\n\n /**\n * @notice Seizes the bond with the given id and distributes it to recipients.\n * @dev This function will revert if there is no bond at the given id.\n * @param _bondId is the id of the bond.\n * @param _claimRecipients is a set of addresses to split the bond amongst.\n */\n function seizeAndSplit(bytes32 _bondId, address[] calldata _claimRecipients) external {\n Bond memory b = bonds[_bondId];\n require(b.owner != address(0), \"BondManager: The bond does not exist.\");\n require(b.expiration >= block.timestamp, \"BondManager: Bond expired.\");\n\n IDisputeGame caller = IDisputeGame(msg.sender);\n IDisputeGame game = DISPUTE_GAME_FACTORY.games(\n GameType.ATTESTATION,\n caller.rootClaim(),\n caller.extraData()\n );\n require(msg.sender == address(game), \"BondManager: Unauthorized seizure.\");\n require(game.status() == GameStatus.CHALLENGER_WINS, \"BondManager: Game incomplete.\");\n\n delete bonds[_bondId];\n\n emit BondSeized(_bondId, b.owner, msg.sender, b.amount);\n\n uint256 len = _claimRecipients.length;\n uint256 proportionalAmount = b.amount / len;\n // Send the proportional amount to each recipient. Do not revert if a send fails as that\n // will prevent other recipients from receiving their share.\n for (uint256 i; i < len; i++) {\n SafeCall.send({\n _target: payable(_claimRecipients[i]),\n _gas: TRANSFER_GAS,\n _value: proportionalAmount\n });\n }\n }\n\n /**\n * @notice Reclaims the bond of the bond owner.\n * @dev This function will revert if there is no bond at the given id.\n * @param _bondId is the id of the bond.\n */\n function reclaim(bytes32 _bondId) external {\n Bond memory b = bonds[_bondId];\n require(b.owner == msg.sender, \"BondManager: Unauthorized claimant.\");\n require(b.expiration <= block.timestamp, \"BondManager: Bond isn't claimable yet.\");\n\n delete bonds[_bondId];\n\n emit BondReclaimed(_bondId, msg.sender, b.amount);\n\n bool success = SafeCall.send(payable(msg.sender), gasleft(), b.amount);\n require(success, \"BondManager: Failed to send Ether.\");\n }\n}\n" - }, - "contracts/dispute/DisputeGameFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { ClonesWithImmutableArgs } from \"@cwia/ClonesWithImmutableArgs.sol\";\n\nimport { Claim } from \"../libraries/DisputeTypes.sol\";\nimport { Hash } from \"../libraries/DisputeTypes.sol\";\nimport { GameType } from \"../libraries/DisputeTypes.sol\";\n\nimport { NoImplementation } from \"../libraries/DisputeErrors.sol\";\nimport { GameAlreadyExists } from \"../libraries/DisputeErrors.sol\";\n\nimport { IDisputeGame } from \"./IDisputeGame.sol\";\nimport { IDisputeGameFactory } from \"./IDisputeGameFactory.sol\";\n\n/**\n * @title DisputeGameFactory\n * @notice A factory contract for creating `IDisputeGame` contracts.\n */\ncontract DisputeGameFactory is Ownable, IDisputeGameFactory {\n /**\n * @dev Allows for the creation of clone proxies with immutable arguments.\n */\n using ClonesWithImmutableArgs for address;\n\n /**\n * @notice Mapping of `GameType`s to their respective `IDisputeGame` implementations.\n */\n mapping(GameType => IDisputeGame) public gameImpls;\n\n /**\n * @notice Mapping of a hash of `gameType . rootClaim . extraData` to\n * the deployed `IDisputeGame` clone.\n * @dev Note: `.` denotes concatenation.\n */\n mapping(Hash => IDisputeGame) internal disputeGames;\n\n /**\n * @notice Constructs a new DisputeGameFactory contract.\n * @param _owner The owner of the contract.\n */\n constructor(address _owner) Ownable() {\n transferOwnership(_owner);\n }\n\n /**\n * @notice Retrieves the hash of `gameType . rootClaim . extraData`\n * to the deployed `DisputeGame` clone.\n * @dev Note: `.` denotes concatenation.\n * @param gameType The type of the DisputeGame.\n * Used to decide the implementation to clone.\n * @param rootClaim The root claim of the DisputeGame.\n * @param extraData Any extra data that should be provided to the\n * created dispute game.\n * @return _proxy The clone of the `DisputeGame` created with the\n * given parameters. `address(0)` if nonexistent.\n */\n function games(\n GameType gameType,\n Claim rootClaim,\n bytes calldata extraData\n ) external view returns (IDisputeGame _proxy) {\n return disputeGames[getGameUUID(gameType, rootClaim, extraData)];\n }\n\n /**\n * @notice Creates a new DisputeGame proxy contract.\n * @notice If a dispute game with the given parameters already exists,\n * it will be returned.\n * @param gameType The type of the DisputeGame.\n * Used to decide the proxy implementation.\n * @param rootClaim The root claim of the DisputeGame.\n * @param extraData Any extra data that should be provided\n * to the created dispute game.\n * @return proxy The clone of the `DisputeGame`.\n */\n function create(\n GameType gameType,\n Claim rootClaim,\n bytes calldata extraData\n ) external returns (IDisputeGame proxy) {\n // Grab the implementation contract for the given `GameType`.\n IDisputeGame impl = gameImpls[gameType];\n\n // If there is no implementation to clone for the given `GameType`, revert.\n if (address(impl) == address(0)) {\n revert NoImplementation(gameType);\n }\n\n // Clone the implementation contract and initialize it with the given parameters.\n bytes memory data = abi.encodePacked(rootClaim, extraData);\n proxy = IDisputeGame(address(impl).clone(data));\n proxy.initialize();\n\n // Compute the unique identifier for the dispute game.\n Hash uuid = getGameUUID(gameType, rootClaim, extraData);\n\n // If a dispute game with the same UUID already exists, revert.\n if (address(disputeGames[uuid]) != address(0)) {\n revert GameAlreadyExists(uuid);\n }\n\n // Store the dispute game in the mapping & emit the `DisputeGameCreated` event.\n disputeGames[uuid] = proxy;\n emit DisputeGameCreated(address(proxy), gameType, rootClaim);\n }\n\n /**\n * @notice Sets the implementation contract for a specific `GameType`.\n * @param gameType The type of the DisputeGame.\n * @param impl The implementation contract for the given `GameType`.\n */\n function setImplementation(GameType gameType, IDisputeGame impl) external onlyOwner {\n gameImpls[gameType] = impl;\n emit ImplementationSet(address(impl), gameType);\n }\n\n /**\n * @notice Returns a unique identifier for the given dispute game parameters.\n * @dev Hashes the concatenation of `gameType . rootClaim . extraData`\n * without expanding memory.\n * @param gameType The type of the DisputeGame.\n * @param rootClaim The root claim of the DisputeGame.\n * @param extraData Any extra data that should be provided to the created dispute game.\n * @return _uuid The unique identifier for the given dispute game parameters.\n */\n function getGameUUID(\n GameType gameType,\n Claim rootClaim,\n bytes memory extraData\n ) public pure returns (Hash _uuid) {\n assembly {\n // Grab the offsets of the other memory locations we will need to temporarily overwrite.\n let gameTypeOffset := sub(extraData, 0x60)\n let rootClaimOffset := add(gameTypeOffset, 0x20)\n let pointerOffset := add(rootClaimOffset, 0x20)\n\n // Copy the memory that we will temporarily overwrite onto the stack\n // so we can restore it later\n let tempA := mload(gameTypeOffset)\n let tempB := mload(rootClaimOffset)\n let tempC := mload(pointerOffset)\n\n // Overwrite the memory with the data we want to hash\n mstore(gameTypeOffset, gameType)\n mstore(rootClaimOffset, rootClaim)\n mstore(pointerOffset, 0x60)\n\n // Compute the length of the memory to hash\n // `0x60 + 0x20 + extraData.length` rounded to the *next* multiple of 32.\n let hashLen := and(add(mload(extraData), 0x9F), not(0x1F))\n\n // Hash the memory to produce the UUID digest\n _uuid := keccak256(gameTypeOffset, hashLen)\n\n // Restore the memory prior to `extraData`\n mstore(gameTypeOffset, tempA)\n mstore(rootClaimOffset, tempB)\n mstore(pointerOffset, tempC)\n }\n }\n}\n" - }, - "contracts/dispute/IAttestationDisputeGame.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport { IDisputeGame } from \"./IDisputeGame.sol\";\n\n/**\n * @title IAttestationDisputeGame\n * @notice The interface for an attestation-based DisputeGame meant to contest output\n * proposals in Optimism's `L2OutputOracle` contract.\n */\ninterface IAttestationDisputeGame is IDisputeGame {\n /**\n * @notice A mapping of addresses from the `signerSet` to booleans signifying whether\n * or not they have authorized the `rootClaim` to be invalidated.\n * @param challenger The address to check for authorization.\n * @return _challenged Whether or not the `challenger` has challenged the `rootClaim`.\n */\n function challenges(address challenger) external view returns (bool _challenged);\n\n /**\n * @notice The signer set consists of authorized public keys that may challenge\n * the `rootClaim`.\n * @param addr The address to check for authorization.\n * @return _isAuthorized Whether or not the `addr` is part of the signer set.\n */\n function signerSet(address addr) external view returns (bool _isAuthorized);\n\n /**\n * @notice The amount of signatures required to successfully challenge the `rootClaim`\n * output proposal. Once this threshold is met by members of the `signerSet`\n * calling `challenge`, the game will be resolved to `CHALLENGER_WINS`.\n * @custom:invariant The `signatureThreshold` may never be greater than the length\n * of the `signerSet`.\n * @return _signatureThreshold The amount of signatures required to successfully\n * challenge the `rootClaim` output proposal.\n */\n function frozenSignatureThreshold() external view returns (uint256 _signatureThreshold);\n\n /**\n * @notice Returns the L2 Block Number that the `rootClaim` commits to.\n * Exists within the `extraData`.\n * @return _l2BlockNumber The L2 Block Number that the `rootClaim` commits to.\n */\n function l2BlockNumber() external view returns (uint256 _l2BlockNumber);\n\n /**\n * @notice Challenge the `rootClaim`.\n * @dev - If the `ecrecover`ed address that created the signature is not a part of\n * the signer set returned by `signerSet`, this function should revert.\n * - If the `ecrecover`ed address that created the signature is not the\n * msg.sender, this function should revert.\n * - If the signature provided is the signature that breaches the signature\n * threshold, the function should call the `resolve` function to resolve\n * the game as `CHALLENGER_WINS`.\n * - When the game resolves, the bond attached to the root claim should be\n * distributed among the signers who participated in challenging the\n * invalid claim.\n * @param signature An EIP-712 signature committing to the `rootClaim` and\n * `l2BlockNumber` (within the `extraData`) from a key that exists\n * within the `signerSet`.\n */\n function challenge(bytes calldata signature) external;\n}\n" - }, - "contracts/dispute/IBondManager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\n/**\n * @title IBondManager\n * @notice The Bond Manager holds ether posted as a bond for a bond id.\n */\ninterface IBondManager {\n /**\n * @notice Post a bond with a given id and owner.\n * @dev This function will revert if the provided bondId is already in use.\n * @param _bondId is the id of the bond.\n * @param _bondOwner is the address that owns the bond.\n * @param _minClaimHold is the minimum amount of time the owner\n * must wait before reclaiming their bond.\n */\n function post(\n bytes32 _bondId,\n address _bondOwner,\n uint256 _minClaimHold\n ) external payable;\n\n /**\n * @notice Seizes the bond with the given id.\n * @dev This function will revert if there is no bond at the given id.\n * @param _bondId is the id of the bond.\n */\n function seize(bytes32 _bondId) external;\n\n /**\n * @notice Seizes the bond with the given id and distributes it to recipients.\n * @dev This function will revert if there is no bond at the given id.\n * @param _bondId is the id of the bond.\n * @param _claimRecipients is a set of addresses to split the bond amongst.\n */\n function seizeAndSplit(bytes32 _bondId, address[] calldata _claimRecipients) external;\n\n /**\n * @notice Reclaims the bond of the bond owner.\n * @dev This function will revert if there is no bond at the given id.\n * @param _bondId is the id of the bond.\n */\n function reclaim(bytes32 _bondId) external;\n}\n" - }, - "contracts/dispute/IDisputeGame.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport { Claim } from \"../libraries/DisputeTypes.sol\";\nimport { GameType } from \"../libraries/DisputeTypes.sol\";\nimport { GameStatus } from \"../libraries/DisputeTypes.sol\";\nimport { Timestamp } from \"../libraries/DisputeTypes.sol\";\n\nimport { IVersioned } from \"./IVersioned.sol\";\nimport { IBondManager } from \"./IBondManager.sol\";\nimport { IInitializable } from \"./IInitializable.sol\";\n\n/**\n * @title IDisputeGame\n * @notice The generic interface for a DisputeGame contract.\n */\ninterface IDisputeGame is IInitializable, IVersioned {\n /**\n * @notice Emitted when the game is resolved.\n * @param status The status of the game after resolution.\n */\n event Resolved(GameStatus indexed status);\n\n /// @notice Returns the timestamp that the DisputeGame contract was created at.\n\n /**\n * @notice Returns the timestamp that the DisputeGame contract was created at.\n * @return _createdAt The timestamp that the DisputeGame contract was created at.\n */\n function createdAt() external view returns (Timestamp _createdAt);\n\n /**\n * @notice Returns the current status of the game.\n * @return _status The current status of the game.\n */\n function status() external view returns (GameStatus _status);\n\n /**\n * @notice Getter for the game type.\n * @dev `clones-with-immutable-args` argument #1\n * @dev The reference impl should be entirely different depending on the type (fault, validity)\n * i.e. The game type should indicate the security model.\n * @return _gameType The type of proof system being used.\n */\n function gameType() external view returns (GameType _gameType);\n\n /**\n * @notice Getter for the root claim.\n * @dev `clones-with-immutable-args` argument #2\n * @return _rootClaim The root claim of the DisputeGame.\n */\n function rootClaim() external view returns (Claim _rootClaim);\n\n /**\n * @notice Getter for the extra data.\n * @dev `clones-with-immutable-args` argument #3\n * @return _extraData Any extra data supplied to the dispute game contract by the creator.\n */\n function extraData() external view returns (bytes memory _extraData);\n\n /**\n * @notice Returns the address of the `BondManager` used.\n * @return _bondManager The address of the `BondManager` used.\n */\n function bondManager() external view returns (IBondManager _bondManager);\n\n /**\n * @notice If all necessary information has been gathered, this function should mark the game\n * status as either `CHALLENGER_WINS` or `DEFENDER_WINS` and return the status of\n * the resolved game. It is at this stage that the bonds should be awarded to the\n * necessary parties.\n * @dev May only be called if the `status` is `IN_PROGRESS`.\n * @return _status The status of the game after resolution.\n */\n function resolve() external returns (GameStatus _status);\n}\n" - }, - "contracts/dispute/IDisputeGameFactory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport { Claim } from \"../libraries/DisputeTypes.sol\";\nimport { GameType } from \"../libraries/DisputeTypes.sol\";\n\nimport { IDisputeGame } from \"./IDisputeGame.sol\";\n\n/**\n * @title IDisputeGameFactory\n * @notice The interface for a DisputeGameFactory contract.\n */\ninterface IDisputeGameFactory {\n /**\n * @notice Emitted when a new dispute game is created\n * @param disputeProxy The address of the dispute game proxy\n * @param gameType The type of the dispute game proxy's implementation\n * @param rootClaim The root claim of the dispute game\n */\n event DisputeGameCreated(\n address indexed disputeProxy,\n GameType indexed gameType,\n Claim indexed rootClaim\n );\n\n /**\n * @notice Emitted when a new game implementation added to the factory\n * @param impl The implementation contract for the given `GameType`.\n * @param gameType The type of the DisputeGame.\n */\n event ImplementationSet(address indexed impl, GameType indexed gameType);\n\n /**\n * @notice `games` queries an internal a mapping that maps the hash of\n * `gameType ++ rootClaim ++ extraData` to the deployed `DisputeGame` clone.\n * @dev `++` equates to concatenation.\n * @param gameType The type of the DisputeGame - used to decide the proxy implementation\n * @param rootClaim The root claim of the DisputeGame.\n * @param extraData Any extra data that should be provided to the created dispute game.\n * @return _proxy The clone of the `DisputeGame` created with the given parameters.\n * Returns `address(0)` if nonexistent.\n */\n function games(\n GameType gameType,\n Claim rootClaim,\n bytes calldata extraData\n ) external view returns (IDisputeGame _proxy);\n\n /**\n * @notice `gameImpls` is a mapping that maps `GameType`s to their respective\n * `IDisputeGame` implementations.\n * @param gameType The type of the dispute game.\n * @return _impl The address of the implementation of the game type.\n * Will be cloned on creation of a new dispute game with the given `gameType`.\n */\n function gameImpls(GameType gameType) external view returns (IDisputeGame _impl);\n\n /**\n * @notice Creates a new DisputeGame proxy contract.\n * @param gameType The type of the DisputeGame - used to decide the proxy implementation\n * @param rootClaim The root claim of the DisputeGame.\n * @param extraData Any extra data that should be provided to the created dispute game.\n * @return proxy The address of the created DisputeGame proxy.\n */\n function create(\n GameType gameType,\n Claim rootClaim,\n bytes calldata extraData\n ) external returns (IDisputeGame proxy);\n\n /**\n * @notice Sets the implementation contract for a specific `GameType`.\n * @dev May only be called by the `owner`.\n * @param gameType The type of the DisputeGame.\n * @param impl The implementation contract for the given `GameType`.\n */\n function setImplementation(GameType gameType, IDisputeGame impl) external;\n}\n" - }, - "contracts/dispute/IFaultDisputeGame.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport { Clock } from \"../libraries/DisputeTypes.sol\";\nimport { Claim } from \"../libraries/DisputeTypes.sol\";\nimport { Position } from \"../libraries/DisputeTypes.sol\";\nimport { Timestamp } from \"../libraries/DisputeTypes.sol\";\nimport { ClaimHash } from \"../libraries/DisputeTypes.sol\";\nimport { BondAmount } from \"../libraries/DisputeTypes.sol\";\n\nimport { IDisputeGame } from \"./IDisputeGame.sol\";\n\n/**\n * @title IFaultDisputeGame\n * @notice The interface for a fault proof backed dispute game.\n */\ninterface IFaultDisputeGame is IDisputeGame {\n /**\n * @notice Emitted when a subclaim is disagreed upon by `claimant`\n * @dev Disagreeing with a subclaim is akin to attacking it.\n * @param claimHash The unique ClaimHash that is being disagreed upon\n * @param pivot The claim for the following pivot (disagreement = go left)\n * @param claimant The address of the claimant\n */\n event Attack(ClaimHash indexed claimHash, Claim indexed pivot, address indexed claimant);\n\n /**\n * @notice Emitted when a subclaim is agreed upon by `claimant`\n * @dev Agreeing with a subclaim is akin to defending it.\n * @param claimHash The unique ClaimHash that is being agreed upon\n * @param pivot The claim for the following pivot (agreement = go right)\n * @param claimant The address of the claimant\n */\n event Defend(ClaimHash indexed claimHash, Claim indexed pivot, address indexed claimant);\n\n /**\n * @notice State variable of the starting timestamp of the game, set on deployment.\n * @return The starting timestamp of the game\n */\n function gameStart() external view returns (Timestamp);\n\n /**\n * @notice Maps a unique ClaimHash to a Claim.\n * @param claimHash The unique ClaimHash\n * @return claim The Claim associated with the ClaimHash\n */\n function claims(ClaimHash claimHash) external view returns (Claim claim);\n\n /**\n * @notice Maps a unique ClaimHash to its parent.\n * @param claimHash The unique ClaimHash\n * @return parent The parent ClaimHash of the passed ClaimHash\n */\n function parents(ClaimHash claimHash) external view returns (ClaimHash parent);\n\n /**\n * @notice Maps a unique ClaimHash to its Position.\n * @param claimHash The unique ClaimHash\n * @return position The Position associated with the ClaimHash\n */\n function positions(ClaimHash claimHash) external view returns (Position position);\n\n /**\n * @notice Maps a unique ClaimHash to a Bond.\n * @param claimHash The unique ClaimHash\n * @return bond The Bond associated with the ClaimHash\n */\n function bonds(ClaimHash claimHash) external view returns (BondAmount bond);\n\n /**\n * @notice Maps a unique ClaimHash its chess clock.\n * @param claimHash The unique ClaimHash\n * @return clock The chess clock associated with the ClaimHash\n */\n function clocks(ClaimHash claimHash) external view returns (Clock clock);\n\n /**\n * @notice Maps a unique ClaimHash to its reference counter.\n * @param claimHash The unique ClaimHash\n * @return _rc The reference counter associated with the ClaimHash\n */\n function rc(ClaimHash claimHash) external view returns (uint64 _rc);\n\n /**\n * @notice Maps a unique ClaimHash to a boolean indicating whether or not it has been countered.\n * @param claimHash The unique claimHash\n * @return _countered Whether or not `claimHash` has been countered\n */\n function countered(ClaimHash claimHash) external view returns (bool _countered);\n\n /**\n * @notice Disagree with a subclaim\n * @param disagreement The ClaimHash of the disagreement\n * @param pivot The claimed pivot\n */\n function attack(ClaimHash disagreement, Claim pivot) external;\n\n /**\n * @notice Agree with a subclaim\n * @param agreement The ClaimHash of the agreement\n * @param pivot The claimed pivot\n */\n function defend(ClaimHash agreement, Claim pivot) external;\n\n /**\n * @notice Perform the final step via an on-chain fault proof processor\n * @dev This function should point to a fault proof processor in order to execute\n * a step in the fault proof program on-chain. The interface of the fault proof\n * processor contract should be generic enough such that we can use different\n * fault proof VMs (MIPS, RiscV5, etc.)\n * @param disagreement The ClaimHash of the disagreement\n */\n function step(ClaimHash disagreement) external;\n}\n" - }, - "contracts/dispute/IInitializable.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\n/**\n * @title IInitializable\n * @notice An interface for initializable contracts.\n */\ninterface IInitializable {\n /**\n * @notice Initializes the contract.\n * @dev This function may only be called once.\n */\n function initialize() external;\n}\n" - }, - "contracts/dispute/IVersioned.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\n/**\n * @title IVersioned\n * @notice An interface for semantically versioned contracts.\n */\ninterface IVersioned {\n /**\n * @notice Returns the semantic version of the contract\n * @return _version The semantic version of the contract\n */\n function version() external pure returns (string memory _version);\n}\n" - }, - "contracts/echidna/FuzzAddressAliasing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract EchidnaFuzzAddressAliasing {\n bool internal failedRoundtrip;\n\n /**\n * @notice Takes an address to be aliased with AddressAliasHelper and then unaliased\n * and updates the test contract's state indicating if the round trip encoding\n * failed.\n */\n function testRoundTrip(address addr) public {\n // Alias our address\n address aliasedAddr = AddressAliasHelper.applyL1ToL2Alias(addr);\n\n // Unalias our address\n address undoneAliasAddr = AddressAliasHelper.undoL1ToL2Alias(aliasedAddr);\n\n // If our round trip aliasing did not return the original result, set our state.\n if (addr != undoneAliasAddr) {\n failedRoundtrip = true;\n }\n }\n\n /**\n * @custom:invariant Address aliases are always able to be undone.\n *\n * Asserts that an address that has been aliased with `applyL1ToL2Alias` can always\n * be unaliased with `undoL1ToL2Alias`.\n */\n function echidna_round_trip_aliasing() public view returns (bool) {\n // ASSERTION: The round trip aliasing done in testRoundTrip(...) should never fail.\n return !failedRoundtrip;\n }\n}\n" - }, - "contracts/echidna/FuzzBurn.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\n\ncontract EchidnaFuzzBurnEth is StdUtils {\n bool internal failedEthBurn;\n\n /**\n * @notice Takes an integer amount of eth to burn through the Burn library and\n * updates the contract state if an incorrect amount of eth moved from the contract\n */\n function testBurn(uint256 _value) public {\n // cache the contract's eth balance\n uint256 preBurnBalance = address(this).balance;\n uint256 value = bound(_value, 0, preBurnBalance);\n\n // execute a burn of _value eth\n Burn.eth(value);\n\n // check that exactly value eth was transfered from the contract\n unchecked {\n if (address(this).balance != preBurnBalance - value) {\n failedEthBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `eth(uint256)` always burns the exact amount of eth passed.\n *\n * Asserts that when `Burn.eth(uint256)` is called, it always burns the exact amount\n * of ETH passed to the function.\n */\n function echidna_burn_eth() public view returns (bool) {\n // ASSERTION: The amount burned should always match the amount passed exactly\n return !failedEthBurn;\n }\n}\n\ncontract EchidnaFuzzBurnGas is StdUtils {\n bool internal failedGasBurn;\n\n /**\n * @notice Takes an integer amount of gas to burn through the Burn library and\n * updates the contract state if at least that amount of gas was not burned\n * by the library\n */\n function testGas(uint256 _value) public {\n // cap the value to the max resource limit\n uint256 MAX_RESOURCE_LIMIT = 8_000_000;\n uint256 value = bound(_value, 0, MAX_RESOURCE_LIMIT);\n\n // cache the contract's current remaining gas\n uint256 preBurnGas = gasleft();\n\n // execute the gas burn\n Burn.gas(value);\n\n // cache the remaining gas post burn\n uint256 postBurnGas = gasleft();\n\n // check that at least value gas was burnt (and that there was no underflow)\n unchecked {\n if (postBurnGas - preBurnGas > value || preBurnGas - value > preBurnGas) {\n failedGasBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `gas(uint256)` always burns at least the amount of gas passed.\n *\n * Asserts that when `Burn.gas(uint256)` is called, it always burns at least the amount\n * of gas passed to the function.\n */\n function echidna_burn_gas() public view returns (bool) {\n // ASSERTION: The amount of gas burned should be strictly greater than the\n // the amount passed as _value (minimum _value + whatever minor overhead to\n // the value after the call)\n return !failedGasBurn;\n }\n}\n" - }, - "contracts/echidna/FuzzEncoding.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzEncoding {\n bool internal failedRoundtripAToB;\n bool internal failedRoundtripBToA;\n\n /**\n * @notice Takes a pair of integers to be encoded into a versioned nonce with the\n * Encoding library and then decoded and updates the test contract's state\n * indicating if the round trip encoding failed.\n */\n function testRoundTripAToB(uint240 _nonce, uint16 _version) public {\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(encodedVersionedNonce);\n\n // If our round trip encoding did not return the original result, set our state.\n if ((decodedNonce != _nonce) || (decodedVersion != _version)) {\n failedRoundtripAToB = true;\n }\n }\n\n /**\n * @notice Takes an integer representing a packed version and nonce and attempts\n * to decode them using the Encoding library before re-encoding and updates\n * the test contract's state indicating if the round trip encoding failed.\n */\n function testRoundTripBToA(uint256 _versionedNonce) public {\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(_versionedNonce);\n\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(decodedNonce, decodedVersion);\n\n // If our round trip encoding did not return the original result, set our state.\n if (encodedVersionedNonce != _versionedNonce) {\n failedRoundtripBToA = true;\n }\n }\n\n /**\n * @custom:invariant `testRoundTripAToB` never fails.\n *\n * Asserts that a raw versioned nonce can be encoded / decoded to reach the same raw value.\n */\n function echidna_round_trip_encoding_AToB() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripAToB(...)\n return !failedRoundtripAToB;\n }\n\n /**\n * @custom:invariant `testRoundTripBToA` never fails.\n *\n * Asserts that an encoded versioned nonce can always be decoded / re-encoded to reach\n * the same encoded value.\n */\n function echidna_round_trip_encoding_BToA() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripBToA should never\n // fail.\n return !failedRoundtripBToA;\n }\n}\n" - }, - "contracts/echidna/FuzzHashing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzHashing {\n bool internal failedCrossDomainHashHighVersion;\n bool internal failedCrossDomainHashV0;\n bool internal failedCrossDomainHashV1;\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash with a randomly\n * generated version. Only schema versions 0 and 1 are supported and all others should revert.\n */\n function testHashCrossDomainMessageHighVersion(\n uint16 _version,\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // hash the cross domain message. we don't need to store the result since the function\n // validates and should revert if an invalid version (>1) is encoded\n Hashing.hashCrossDomainMessage(encodedNonce, _sender, _target, _value, _gasLimit, _data);\n\n // check that execution never makes it this far for an invalid version\n if (_version > 1) {\n failedCrossDomainHashHighVersion = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v0 schema\n * and compares the output of a call to the unversioned function to the v0 function directly\n */\n function testHashCrossDomainMessageV0(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 0\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 0);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV0(\n _target,\n _sender,\n _data,\n encodedNonce\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV0 = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v1 schema\n * and compares the output of a call to the unversioned function to the v1 function directly\n */\n function testHashCrossDomainMessageV1(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 1\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 1);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV1(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV1 = true;\n }\n }\n\n /**\n * @custom:invariant `hashCrossDomainMessage` reverts if `version` is > `1`.\n *\n * The `hashCrossDomainMessage` function should always revert if the `version` passed is > `1`.\n */\n function echidna_hash_xdomain_msg_high_version() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage will never succeed for a version > 1\n return !failedCrossDomainHashHighVersion;\n }\n\n /**\n * @custom:invariant `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0`\n * are equivalent.\n *\n * If the version passed is 0, `hashCrossDomainMessage` and `hashCrossDomainMessageV0` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_0() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV0\n // should always match when the version passed is 0\n return !failedCrossDomainHashV0;\n }\n\n /**\n * @custom:invariant `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1`\n * are equivalent.\n *\n * If the version passed is 1, `hashCrossDomainMessage` and `hashCrossDomainMessageV1` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_1() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV1\n // should always match when the version passed is 1\n return !failedCrossDomainHashV1;\n }\n}\n" - }, - "contracts/echidna/FuzzOptimismPortal.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract EchidnaFuzzOptimismPortal {\n OptimismPortal internal portal;\n bool internal failedToComplete;\n\n constructor() {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n SystemConfig systemConfig = new SystemConfig({\n _owner: address(1),\n _overhead: 0,\n _scalar: 10000,\n _batcherHash: bytes32(0),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(0),\n _config: rcfg\n });\n\n portal = new OptimismPortal({\n _l2Oracle: L2OutputOracle(address(0)),\n _guardian: address(0),\n _paused: false,\n _config: systemConfig\n });\n }\n\n // A test intended to identify any unexpected halting conditions\n function testDepositTransactionCompletes(\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable {\n failedToComplete = true;\n require(!_isCreation || _to == address(0), \"EchidnaFuzzOptimismPortal: invalid test case.\");\n portal.depositTransaction{ value: _mint }(_to, _value, _gasLimit, _isCreation, _data);\n failedToComplete = false;\n }\n\n /**\n * @custom:invariant Deposits of any value should always succeed unless\n * `_to` = `address(0)` or `_isCreation` = `true`.\n *\n * All deposits, barring creation transactions and transactions sent to `address(0)`,\n * should always succeed.\n */\n function echidna_deposit_completes() public view returns (bool) {\n return !failedToComplete;\n }\n}\n" - }, - "contracts/echidna/FuzzResourceMetering.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {\n bool internal failedMaxGasPerBlock;\n bool internal failedRaiseBaseFee;\n bool internal failedLowerBaseFee;\n bool internal failedNeverBelowMinBaseFee;\n bool internal failedMaxRaiseBaseFeePerBlock;\n bool internal failedMaxLowerBaseFeePerBlock;\n\n // Used as a special flag for the purpose of identifying unchecked math errors specifically\n // in the test contracts, not the target contracts themselves.\n bool internal underflow;\n\n constructor() {\n initialize();\n }\n\n function initialize() internal initializer {\n __ResourceMetering_init();\n }\n\n function resourceConfig() public pure returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig();\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n return rcfg;\n }\n\n /**\n * @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test\n * the underlying resource metering/gas market logic\n */\n function testBurn(uint256 _gasToBurn, bool _raiseBaseFee) public {\n // Part 1: we cache the current param values and do some basic checks on them.\n uint256 cachedPrevBaseFee = uint256(params.prevBaseFee);\n uint256 cachedPrevBoughtGas = uint256(params.prevBoughtGas);\n uint256 cachedPrevBlockNum = uint256(params.prevBlockNum);\n\n ResourceMetering.ResourceConfig memory rcfg = resourceConfig();\n uint256 targetResourceLimit = uint256(rcfg.maxResourceLimit) /\n uint256(rcfg.elasticityMultiplier);\n\n // check that the last block's base fee hasn't dropped below the minimum\n if (cachedPrevBaseFee < uint256(rcfg.minimumBaseFee)) {\n failedNeverBelowMinBaseFee = true;\n }\n // check that the last block didn't consume more than the max amount of gas\n if (cachedPrevBoughtGas > uint256(rcfg.maxResourceLimit)) {\n failedMaxGasPerBlock = true;\n }\n\n // Part2: we perform the gas burn\n\n // force the gasToBurn into the correct range based on whether we intend to\n // raise or lower the baseFee after this block, respectively\n uint256 gasToBurn;\n if (_raiseBaseFee) {\n gasToBurn = bound(\n _gasToBurn,\n uint256(targetResourceLimit),\n uint256(rcfg.maxResourceLimit)\n );\n } else {\n gasToBurn = bound(_gasToBurn, 0, targetResourceLimit);\n }\n\n _burnInternal(uint64(gasToBurn));\n\n // Part 3: we run checks and modify our invariant flags based on the updated params values\n\n // Calculate the maximum allowed baseFee change (per block)\n uint256 maxBaseFeeChange = cachedPrevBaseFee / uint256(rcfg.baseFeeMaxChangeDenominator);\n\n // If the last block used more than the target amount of gas (and there were no\n // empty blocks in between), ensure this block's baseFee increased, but not by\n // more than the max amount per block\n if (\n (cachedPrevBoughtGas > uint256(targetResourceLimit)) &&\n (uint256(params.prevBlockNum) - cachedPrevBlockNum == 1)\n ) {\n failedRaiseBaseFee = failedRaiseBaseFee || (params.prevBaseFee <= cachedPrevBaseFee);\n failedMaxRaiseBaseFeePerBlock =\n failedMaxRaiseBaseFeePerBlock ||\n ((uint256(params.prevBaseFee) - cachedPrevBaseFee) < maxBaseFeeChange);\n }\n\n // If the last block used less than the target amount of gas, (or was empty),\n // ensure that: this block's baseFee was decreased, but not by more than the max amount\n if (\n (cachedPrevBoughtGas < uint256(targetResourceLimit)) ||\n (uint256(params.prevBlockNum) - cachedPrevBlockNum > 1)\n ) {\n // Invariant: baseFee should decrease\n failedLowerBaseFee =\n failedLowerBaseFee ||\n (uint256(params.prevBaseFee) > cachedPrevBaseFee);\n\n if (params.prevBlockNum - cachedPrevBlockNum == 1) {\n // No empty blocks\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n } else if (params.prevBlockNum - cachedPrevBlockNum > 1) {\n // We have at least one empty block\n // Update the maxBaseFeeChange to account for multiple blocks having passed\n unchecked {\n maxBaseFeeChange = uint256(\n int256(cachedPrevBaseFee) -\n Arithmetic.clamp(\n Arithmetic.cdexp(\n int256(cachedPrevBaseFee),\n int256(uint256(rcfg.baseFeeMaxChangeDenominator)),\n int256(uint256(params.prevBlockNum) - cachedPrevBlockNum)\n ),\n int256(uint256(rcfg.minimumBaseFee)),\n int256(uint256(rcfg.maximumBaseFee))\n )\n );\n }\n\n // Detect an underflow in the previous calculation.\n // Without using unchecked above, and detecting the underflow here, echidna would\n // otherwise ignore the revert.\n underflow = underflow || maxBaseFeeChange > cachedPrevBaseFee;\n\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n }\n }\n }\n\n function _burnInternal(uint64 _gasToBurn) private metered(_gasToBurn) {}\n\n /**\n * @custom:invariant The base fee should increase if the last block used more\n * than the target amount of gas\n *\n * If the last block used more than the target amount of gas (and there were no\n * empty blocks in between), ensure this block's baseFee increased, but not by\n * more than the max amount per block.\n */\n function echidna_high_usage_raise_baseFee() public view returns (bool) {\n return !failedRaiseBaseFee;\n }\n\n /**\n * @custom:invariant The base fee should decrease if the last block used less\n * than the target amount of gas\n *\n * If the previous block used less than the target amount of gas, the base fee should decrease,\n * but not more than the max amount.\n */\n function echidna_low_usage_lower_baseFee() public view returns (bool) {\n return !failedLowerBaseFee;\n }\n\n /**\n * @custom:invariant A block's base fee should never be below `MINIMUM_BASE_FEE`\n *\n * This test asserts that a block's base fee can never drop below the\n * `MINIMUM_BASE_FEE` threshold.\n */\n function echidna_never_below_min_baseFee() public view returns (bool) {\n return !failedNeverBelowMinBaseFee;\n }\n\n /**\n * @custom:invariant A block can never consume more than `MAX_RESOURCE_LIMIT` gas.\n *\n * This test asserts that a block can never consume more than the `MAX_RESOURCE_LIMIT`\n * gas threshold.\n */\n function echidna_never_above_max_gas_limit() public view returns (bool) {\n return !failedMaxGasPerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be raised more than the max base fee change.\n *\n * After a block consumes more gas than the target gas, the base fee cannot be raised\n * more than the maximum amount allowed. The max base fee change (per-block) is derived\n * as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_increase() public view returns (bool) {\n return !failedMaxRaiseBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be lowered more than the max base fee change.\n *\n * After a block consumes less than the target gas, the base fee cannot be lowered more\n * than the maximum amount allowed. The max base fee change (per-block) is derived as\n *follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_decrease() public view returns (bool) {\n return !failedMaxLowerBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The `maxBaseFeeChange` calculation over multiple blocks can never\n * underflow.\n *\n * When calculating the `maxBaseFeeChange` after multiple empty blocks, the calculation\n * should never be allowed to underflow.\n */\n function echidna_underflow() public view returns (bool) {\n return !underflow;\n }\n}\n" - }, - "contracts/governance/GovernanceToken.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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 * @custom:predeploy 0x4200000000000000000000000000000000000042\n * @title GovernanceToken\n * @notice The Optimism token used in governance and supporting voting and delegation. Implements\n * EIP 2612 allowing signed approvals. Contract is \"owned\" by a `MintManager` instance with\n * permission to the `mint` function only, for the purposes of enforcing the token inflation\n * schedule.\n */\ncontract GovernanceToken is ERC20Burnable, ERC20Votes, Ownable {\n constructor() ERC20(\"Optimism\", \"OP\") ERC20Permit(\"Optimism\") {}\n\n /**\n * @notice Allows the owner to mint tokens.\n *\n * @param _account The account receiving minted tokens.\n * @param _amount The amount of tokens to mint.\n */\n function mint(address _account, uint256 _amount) public onlyOwner {\n _mint(_account, _amount);\n }\n\n /**\n * @notice Callback called after a token transfer.\n *\n * @param from The account sending tokens.\n * @param to The account receiving tokens.\n * @param amount The amount of tokens being transfered.\n */\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 /**\n * @notice Internal mint function.\n *\n * @param to The account receiving minted tokens.\n * @param amount The amount of tokens to mint.\n */\n function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._mint(to, amount);\n }\n\n /**\n * @notice Internal burn function.\n *\n * @param account The account that tokens will be burned from.\n * @param amount The amount of tokens that will be burned.\n */\n function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._burn(account, amount);\n }\n}\n" - }, - "contracts/governance/MintManager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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(\n mintPermittedAfter <= block.timestamp,\n \"MintManager: minting not permitted yet\"\n );\n\n require(\n _amount <= (governanceToken.totalSupply() * MINT_CAP) / DENOMINATOR,\n \"MintManager: mint amount exceeds cap\"\n );\n }\n\n mintPermittedAfter = block.timestamp + MINT_PERIOD;\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(\n _newMintManager != address(0),\n \"MintManager: mint manager cannot be the zero address\"\n );\n\n governanceToken.transferOwnership(_newMintManager);\n }\n}\n" - }, - "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" - }, - "contracts/legacy/DeployerWhitelist.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000002\n * @title DeployerWhitelist\n * @notice DeployerWhitelist is a legacy contract that was originally used to act as a whitelist of\n * addresses allowed to the Optimism network. The DeployerWhitelist has since been\n * disabled, but the code is kept in state for the sake of full backwards compatibility.\n * As of the Bedrock upgrade, the DeployerWhitelist is completely unused by the Optimism\n * system and could, in theory, be removed entirely.\n */\ncontract DeployerWhitelist is Semver {\n /**\n * @notice Address of the owner of this contract. Note that when this address is set to\n * address(0), the whitelist is disabled.\n */\n address public owner;\n\n /**\n * @notice Mapping of deployer addresses to boolean whitelist status.\n */\n mapping(address => bool) public whitelist;\n\n /**\n * @notice Emitted when the owner of this contract changes.\n *\n * @param oldOwner Address of the previous owner.\n * @param newOwner Address of the new owner.\n */\n event OwnerChanged(address oldOwner, address newOwner);\n\n /**\n * @notice Emitted when the whitelist status of a deployer changes.\n *\n * @param deployer Address of the deployer.\n * @param whitelisted Boolean indicating whether the deployer is whitelisted.\n */\n event WhitelistStatusChanged(address deployer, bool whitelisted);\n\n /**\n * @notice Emitted when the whitelist is disabled.\n *\n * @param oldOwner Address of the final owner of the whitelist.\n */\n event WhitelistDisabled(address oldOwner);\n\n /**\n * @notice Blocks functions to anyone except the contract owner.\n */\n modifier onlyOwner() {\n require(\n msg.sender == owner,\n \"DeployerWhitelist: function can only be called by the owner of this contract\"\n );\n _;\n }\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Adds or removes an address from the deployment whitelist.\n *\n * @param _deployer Address to update permissions for.\n * @param _isWhitelisted Whether or not the address is whitelisted.\n */\n function setWhitelistedDeployer(address _deployer, bool _isWhitelisted) external onlyOwner {\n whitelist[_deployer] = _isWhitelisted;\n emit WhitelistStatusChanged(_deployer, _isWhitelisted);\n }\n\n /**\n * @notice Updates the owner of this contract.\n *\n * @param _owner Address of the new owner.\n */\n function setOwner(address _owner) external onlyOwner {\n // Prevent users from setting the whitelist owner to address(0) except via\n // enableArbitraryContractDeployment. If you want to burn the whitelist owner, send it to\n // any other address that doesn't have a corresponding knowable private key.\n require(\n _owner != address(0),\n \"DeployerWhitelist: can only be disabled via enableArbitraryContractDeployment\"\n );\n\n emit OwnerChanged(owner, _owner);\n owner = _owner;\n }\n\n /**\n * @notice Permanently enables arbitrary contract deployment and deletes the owner.\n */\n function enableArbitraryContractDeployment() external onlyOwner {\n emit WhitelistDisabled(owner);\n owner = address(0);\n }\n\n /**\n * @notice Checks whether an address is allowed to deploy contracts.\n *\n * @param _deployer Address to check.\n *\n * @return Whether or not the address can deploy contracts.\n */\n function isDeployerAllowed(address _deployer) external view returns (bool) {\n return (owner == address(0) || whitelist[_deployer]);\n }\n}\n" - }, - "contracts/legacy/L1BlockNumber.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000013\n * @title L1BlockNumber\n * @notice L1BlockNumber is a legacy contract that fills the roll of the OVM_L1BlockNumber contract\n * in the old version of the Optimism system. Only necessary for backwards compatibility.\n * If you want to access the L1 block number going forward, you should use the L1Block\n * contract instead.\n */\ncontract L1BlockNumber is Semver {\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Returns the L1 block number.\n */\n receive() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Returns the L1 block number.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Retrieves the latest L1 block number.\n *\n * @return Latest L1 block number.\n */\n function getL1BlockNumber() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).number();\n }\n}\n" - }, - "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/legacy/LegacyERC20ETH.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000\n * @title LegacyERC20ETH\n * @notice LegacyERC20ETH is a legacy contract that held ETH balances before the Bedrock upgrade.\n * All ETH balances held within this contract were migrated to the state trie as part of\n * the Bedrock upgrade. Functions within this contract that mutate state were already\n * disabled as part of the EVM equivalence upgrade.\n */\ncontract LegacyERC20ETH is OptimismMintableERC20 {\n /**\n * @notice Initializes the contract as an Optimism Mintable ERC20.\n */\n constructor()\n OptimismMintableERC20(Predeploys.L2_STANDARD_BRIDGE, address(0), \"Ether\", \"ETH\")\n {}\n\n /**\n * @notice Returns the ETH balance of the target account. Overrides the base behavior of the\n * contract to preserve the invariant that the balance within this contract always\n * matches the balance in the state trie.\n *\n * @param _who Address of the account to query.\n *\n * @return The ETH balance of the target account.\n */\n function balanceOf(address _who) public view virtual override returns (uint256) {\n return address(_who).balance;\n }\n\n /**\n * @custom:blocked\n * @notice Mints some amount of ETH.\n */\n function mint(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: mint is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Burns some amount of ETH.\n */\n function burn(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: burn is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers some amount of ETH.\n */\n function transfer(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transfer is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Approves a spender to spend some amount of ETH.\n */\n function approve(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: approve is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers funds from some sender account.\n */\n function transferFrom(\n address,\n address,\n uint256\n ) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transferFrom is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Increases the allowance of a spender.\n */\n function increaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Decreases the allowance of a spender.\n */\n function decreaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n }\n}\n" - }, - "contracts/legacy/LegacyMessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000000\n * @title LegacyMessagePasser\n * @notice The LegacyMessagePasser was the low-level mechanism used to send messages from L2 to L1\n * before the Bedrock upgrade. It is now deprecated in favor of the new MessagePasser.\n */\ncontract LegacyMessagePasser is Semver {\n /**\n * @notice Mapping of sent message hashes to boolean status.\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Passes a message to L1.\n *\n * @param _message Message to pass to L1.\n */\n function passMessageToL1(bytes memory _message) external {\n sentMessages[keccak256(abi.encodePacked(_message, msg.sender))] = true;\n }\n}\n" - }, - "contracts/legacy/LegacyMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { ILegacyMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @title LegacyMintableERC20\n * @notice The legacy implementation of the OptimismMintableERC20. This\n * contract is deprecated and should no longer be used.\n */\ncontract LegacyMintableERC20 is ILegacyMintableERC20, ERC20 {\n /**\n * @notice Emitted when the token is minted by the bridge.\n */\n event Mint(address indexed _account, uint256 _amount);\n\n /**\n * @notice Emitted when a token is burned by the bridge.\n */\n event Burn(address indexed _account, uint256 _amount);\n\n /**\n * @notice The token on the remote domain.\n */\n address public l1Token;\n\n /**\n * @notice The local bridge.\n */\n address public l2Bridge;\n\n /**\n * @param _l2Bridge Address of the L2 standard bridge.\n * @param _l1Token Address of the corresponding L1 token.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n */\n constructor(\n address _l2Bridge,\n address _l1Token,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) {\n l1Token = _l1Token;\n l2Bridge = _l2Bridge;\n }\n\n /**\n * @notice Modifier that requires the contract was called by the bridge.\n */\n modifier onlyL2Bridge() {\n require(msg.sender == l2Bridge, \"Only L2 Bridge can mint and burn\");\n _;\n }\n\n /**\n * @notice EIP165 implementation.\n */\n function supportsInterface(bytes4 _interfaceId) public pure returns (bool) {\n bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^\n ILegacyMintableERC20.mint.selector ^\n ILegacyMintableERC20.burn.selector;\n return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n }\n\n /**\n * @notice Only the bridge can mint tokens.\n * @param _to The account receiving tokens.\n * @param _amount The amount of tokens to receive.\n */\n function mint(address _to, uint256 _amount) public virtual onlyL2Bridge {\n _mint(_to, _amount);\n\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Only the bridge can burn tokens.\n * @param _from The account having tokens burnt.\n * @param _amount The amount of tokens being burnt.\n */\n function burn(address _from, uint256 _amount) public virtual onlyL2Bridge {\n _burn(_from, _amount);\n\n emit Burn(_from, _amount);\n }\n}\n" - }, - "contracts/legacy/ResolvedDelegateProxy.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressManager } from \"./AddressManager.sol\";\n\n/**\n * @custom:legacy\n * @title ResolvedDelegateProxy\n * @notice ResolvedDelegateProxy is a legacy proxy contract that makes use of the AddressManager to\n * resolve the implementation address. We're maintaining this contract for backwards\n * compatibility so we can manage all legacy proxies where necessary.\n */\ncontract ResolvedDelegateProxy {\n /**\n * @notice Mapping used to store the implementation name that corresponds to this contract. A\n * mapping was originally used as a way to bypass the same issue normally solved by\n * storing the implementation address in a specific storage slot that does not conflict\n * with any other storage slot. Generally NOT a safe solution but works as long as the\n * implementation does not also keep a mapping in the first storage slot.\n */\n mapping(address => string) private implementationName;\n\n /**\n * @notice Mapping used to store the address of the AddressManager contract where the\n * implementation address will be resolved from. Same concept here as with the above\n * mapping. Also generally unsafe but fine if the implementation doesn't keep a mapping\n * in the second storage slot.\n */\n mapping(address => AddressManager) private addressManager;\n\n /**\n * @param _addressManager Address of the AddressManager.\n * @param _implementationName implementationName of the contract to proxy to.\n */\n constructor(AddressManager _addressManager, string memory _implementationName) {\n addressManager[address(this)] = _addressManager;\n implementationName[address(this)] = _implementationName;\n }\n\n /**\n * @notice Fallback, performs a delegatecall to the resolved implementation address.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n address target = addressManager[address(this)].getAddress(\n (implementationName[address(this)])\n );\n\n require(target != address(0), \"ResolvedDelegateProxy: target address must be initialized\");\n\n // slither-disable-next-line controlled-delegatecall\n (bool success, bytes memory returndata) = target.delegatecall(msg.data);\n\n if (success == true) {\n assembly {\n return(add(returndata, 0x20), mload(returndata))\n }\n } else {\n assembly {\n revert(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n" - }, - "contracts/libraries/Arithmetic.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { SignedMath } from \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\nimport { FixedPointMathLib } from \"@rari-capital/solmate/src/utils/FixedPointMathLib.sol\";\n\n/**\n * @title Arithmetic\n * @notice Even more math than before.\n */\nlibrary Arithmetic {\n /**\n * @notice Clamps a value between a minimum and maximum.\n *\n * @param _value The value to clamp.\n * @param _min The minimum value.\n * @param _max The maximum value.\n *\n * @return The clamped value.\n */\n function clamp(\n int256 _value,\n int256 _min,\n int256 _max\n ) internal pure returns (int256) {\n return SignedMath.min(SignedMath.max(_value, _min), _max);\n }\n\n /**\n * @notice (c)oefficient (d)enominator (exp)onentiation function.\n * Returns the result of: c * (1 - 1/d)^exp.\n *\n * @param _coefficient Coefficient of the function.\n * @param _denominator Fractional denominator.\n * @param _exponent Power function exponent.\n *\n * @return Result of c * (1 - 1/d)^exp.\n */\n function cdexp(\n int256 _coefficient,\n int256 _denominator,\n int256 _exponent\n ) internal pure returns (int256) {\n return\n (_coefficient *\n (FixedPointMathLib.powWad(1e18 - (1e18 / _denominator), _exponent * 1e18))) / 1e18;\n }\n}\n" - }, - "contracts/libraries/Burn.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Burn\n * @notice Utilities for burning stuff.\n */\nlibrary Burn {\n /**\n * Burns a given amount of ETH.\n *\n * @param _amount Amount of ETH to burn.\n */\n function eth(uint256 _amount) internal {\n new Burner{ value: _amount }();\n }\n\n /**\n * Burns a given amount of gas.\n *\n * @param _amount Amount of gas to burn.\n */\n function gas(uint256 _amount) internal view {\n uint256 i = 0;\n uint256 initialGas = gasleft();\n while (initialGas - gasleft() < _amount) {\n ++i;\n }\n }\n}\n\n/**\n * @title Burner\n * @notice Burner self-destructs on creation and sends all ETH to itself, removing all ETH given to\n * the contract from the circulating supply. Self-destructing is the only way to remove ETH\n * from the circulating supply.\n */\ncontract Burner {\n constructor() payable {\n selfdestruct(payable(address(this)));\n }\n}\n" - }, - "contracts/libraries/Bytes.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Bytes\n * @notice Bytes is a library for manipulating byte arrays.\n */\nlibrary Bytes {\n /**\n * @custom:attribution https://github.com/GNSPS/solidity-bytes-utils\n * @notice Slices a byte array with a given starting index and length. Returns a new byte array\n * as opposed to a pointer to the original array. Will throw if trying to slice more\n * bytes than exist in the array.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n * @param _length Length of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n unchecked {\n require(_length + 31 >= _length, \"slice_overflow\");\n require(_start + _length >= _start, \"slice_overflow\");\n require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n }\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n /**\n * @notice Slices a byte array with a given starting index up to the end of the original byte\n * array. Returns a new array rathern than a pointer to the original.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {\n if (_start >= _bytes.length) {\n return bytes(\"\");\n }\n return slice(_bytes, _start, _bytes.length - _start);\n }\n\n /**\n * @notice Converts a byte array into a nibble array by splitting each byte into two nibbles.\n * Resulting nibble array will be exactly twice as long as the input byte array.\n *\n * @param _bytes Input byte array to convert.\n *\n * @return Resulting nibble array.\n */\n function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n uint256 bytesLength = _bytes.length;\n bytes memory nibbles = new bytes(bytesLength * 2);\n bytes1 b;\n\n for (uint256 i = 0; i < bytesLength; ) {\n b = _bytes[i];\n nibbles[i * 2] = b >> 4;\n nibbles[i * 2 + 1] = b & 0x0f;\n unchecked {\n ++i;\n }\n }\n\n return nibbles;\n }\n\n /**\n * @notice Compares two byte arrays by comparing their keccak256 hashes.\n *\n * @param _bytes First byte array to compare.\n * @param _other Second byte array to compare.\n *\n * @return True if the two byte arrays are equal, false otherwise.\n */\n function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {\n return keccak256(_bytes) == keccak256(_other);\n }\n}\n" - }, - "contracts/libraries/Constants.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\n/**\n * @title Constants\n * @notice Constants is a library for storing constants. Simple! Don't put everything in here, just\n * the stuff used in multiple contracts. Constants that only apply to a single contract\n * should be defined in that contract instead.\n */\nlibrary Constants {\n /**\n * @notice Special address to be used as the tx origin for gas estimation calls in the\n * OptimismPortal and CrossDomainMessenger calls. You only need to use this address if\n * the minimum gas limit specified by the user is not actually enough to execute the\n * given message and you're attempting to estimate the actual necessary gas limit. We\n * use address(1) because it's the ecrecover precompile and therefore guaranteed to\n * never have any code on any EVM chain.\n */\n address internal constant ESTIMATION_ADDRESS = address(1);\n\n /**\n * @notice Value used for the L2 sender storage slot in both the OptimismPortal and the\n * CrossDomainMessenger contracts before an actual sender is set. This value is\n * non-zero to reduce the gas cost of message passing transactions.\n */\n address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD;\n\n /**\n * @notice Returns the default values for the ResourceConfig. These are the recommended values\n * for a production network.\n */\n function DEFAULT_RESOURCE_CONFIG()\n internal\n pure\n returns (ResourceMetering.ResourceConfig memory)\n {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n return config;\n }\n}\n" - }, - "contracts/libraries/DisputeErrors.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport \"./DisputeTypes.sol\";\n\n////////////////////////////////////////////////////////////////\n// `DisputeGameFactory` Errors //\n////////////////////////////////////////////////////////////////\n\n/**\n * @notice Thrown when a dispute game is attempted to be created with an unsupported game type.\n * @param gameType The unsupported game type.\n */\nerror NoImplementation(GameType gameType);\n\n/**\n * @notice Thrown when a dispute game that already exists is attempted to be created.\n * @param uuid The UUID of the dispute game that already exists.\n */\nerror GameAlreadyExists(Hash uuid);\n\n////////////////////////////////////////////////////////////////\n// `DisputeGame_Fault.sol` Errors //\n////////////////////////////////////////////////////////////////\n\n/**\n * @notice Thrown when a supplied bond is too low to cover the\n * cost of the next possible counter claim.\n */\nerror BondTooLow();\n\n/**\n * @notice Thrown when a defense against the root claim is attempted.\n */\nerror CannotDefendRootClaim();\n\n/**\n * @notice Thrown when a claim is attempting to be made that already exists.\n */\nerror ClaimAlreadyExists();\n\n////////////////////////////////////////////////////////////////\n// `AttestationDisputeGame` Errors //\n////////////////////////////////////////////////////////////////\n\n/**\n * @notice Thrown when an invalid signature is submitted to `challenge`.\n */\nerror InvalidSignature();\n\n/**\n * @notice Thrown when a signature that has already been used to support the\n * `rootClaim` is submitted to `challenge`.\n */\nerror AlreadyChallenged();\n\n////////////////////////////////////////////////////////////////\n// `Ownable` Errors //\n////////////////////////////////////////////////////////////////\n\n/**\n * @notice Thrown when a function that is protected by the `onlyOwner` modifier\n * is called from an account other than the owner.\n */\nerror NotOwner();\n" - }, - "contracts/libraries/DisputeTypes.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\n/**\n * @notice A custom type for a generic hash.\n */\ntype Hash is bytes32;\n\n/**\n * @notice A claim represents an MPT root representing the state of the fault proof program.\n */\ntype Claim is bytes32;\n\n/**\n * @notice A claim hash represents a hash of a claim and a position within the game tree.\n * @dev Keccak hash of abi.encodePacked(Claim, Position);\n */\ntype ClaimHash is bytes32;\n\n/**\n * @notice A bondamount represents the amount of collateral that a user has locked up in a claim.\n */\ntype BondAmount is uint256;\n\n/**\n * @notice A dedicated timestamp type.\n */\ntype Timestamp is uint64;\n\n/**\n * @notice A dedicated duration type.\n * @dev Unit: seconds\n */\ntype Duration is uint64;\n\n/**\n * @notice A `Clock` represents a packed `Duration` and `Timestamp`\n * @dev The packed layout of this type is as follows:\n * ┌────────────┬────────────────┐\n * │ Bits │ Value │\n * ├────────────┼────────────────┤\n * │ [0, 128) │ Duration │\n * │ [128, 256) │ Timestamp │\n * └────────────┴────────────────┘\n */\ntype Clock is uint256;\n\n/**\n * @notice A `Position` represents a position of a claim within the game tree.\n * @dev The packed layout of this type is as follows:\n * ┌────────────┬────────────────┐\n * │ Bits │ Value │\n * ├────────────┼────────────────┤\n * │ [0, 128) │ Depth │\n * │ [128, 256) │ Index at depth │\n * └────────────┴────────────────┘\n */\ntype Position is uint256;\n\n/**\n * @notice The current status of the dispute game.\n */\nenum GameStatus {\n // The game is currently in progress, and has not been resolved.\n IN_PROGRESS,\n // The game has concluded, and the `rootClaim` was challenged successfully.\n CHALLENGER_WINS,\n // The game has concluded, and the `rootClaim` could not be contested.\n DEFENDER_WINS\n}\n\n/**\n * @notice The type of proof system being used.\n */\nenum GameType {\n // The game will use a `IDisputeGame` implementation that utilizes fault proofs.\n FAULT,\n // The game will use a `IDisputeGame` implementation that utilizes validity proofs.\n VALIDITY,\n // The game will use a `IDisputeGame` implementation that utilizes attestation proofs.\n ATTESTATION\n}\n" - }, - "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" - }, - "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" - }, - "contracts/libraries/LegacyCrossDomainUtils.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n// Importing from the legacy contracts package causes issues with the build of the contract bindings\n// so we just copy the library here from\n// /packages/contracts/contracts/libraries/bridge/Lib_CrossDomainUtils.sol at commit\n// 7866168c\n/**\n * @title LegacyCrossDomainUtils\n */\nlibrary LegacyCrossDomainUtils {\n /**\n * Generates the correct cross domain calldata for a message.\n * @param _target Target contract address.\n * @param _sender Message sender address.\n * @param _message Message to send to the target.\n * @param _messageNonce Nonce for the provided message.\n * @return ABI encoded cross domain calldata.\n */\n function encodeXDomainCalldata(\n address _target,\n address _sender,\n bytes memory _message,\n uint256 _messageNonce\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(address,address,bytes,uint256)\",\n _target,\n _sender,\n _message,\n _messageNonce\n );\n }\n}\n" - }, - "contracts/libraries/Predeploys.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Predeploys\n * @notice Contains constant addresses for contracts that are pre-deployed to the L2 system.\n */\nlibrary Predeploys {\n /**\n * @notice Address of the L2ToL1MessagePasser predeploy.\n */\n address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016;\n\n /**\n * @notice Address of the L2CrossDomainMessenger predeploy.\n */\n address internal constant L2_CROSS_DOMAIN_MESSENGER =\n 0x4200000000000000000000000000000000000007;\n\n /**\n * @notice Address of the L2StandardBridge predeploy.\n */\n address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;\n\n /**\n * @notice Address of the L2ERC721Bridge predeploy.\n */\n address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014;\n\n /**\n * @notice Address of the SequencerFeeWallet predeploy.\n */\n address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;\n\n /**\n * @notice Address of the OptimismMintableERC20Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY =\n 0x4200000000000000000000000000000000000012;\n\n /**\n * @notice Address of the OptimismMintableERC721Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY =\n 0x4200000000000000000000000000000000000017;\n\n /**\n * @notice Address of the L1Block predeploy.\n */\n address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015;\n\n /**\n * @notice Address of the GasPriceOracle predeploy. Includes fee information\n * and helpers for computing the L1 portion of the transaction fee.\n */\n address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F;\n\n /**\n * @custom:legacy\n * @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger\n * or access tx.origin (or msg.sender) in a L1 to L2 transaction instead.\n */\n address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;\n\n /**\n * @custom:legacy\n * @notice Address of the DeployerWhitelist predeploy. No longer active.\n */\n address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the\n * state trie as of the Bedrock upgrade. Contract has been locked and write functions\n * can no longer be accessed.\n */\n address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;\n\n /**\n * @custom:legacy\n * @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy\n * instead, which exposes more information about the L1 state.\n */\n address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated\n * L2ToL1MessagePasser contract instead.\n */\n address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;\n\n /**\n * @notice Address of the ProxyAdmin predeploy.\n */\n address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018;\n\n /**\n * @notice Address of the BaseFeeVault predeploy.\n */\n address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019;\n\n /**\n * @notice Address of the L1FeeVault predeploy.\n */\n address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A;\n\n /**\n * @notice Address of the GovernanceToken predeploy.\n */\n address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042;\n}\n" - }, - "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 Performs a low level call without copying any returndata.\n * @dev Passes no calldata to the call context.\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 */\n function send(\n address _target,\n uint256 _gas,\n uint256 _value\n ) internal returns (bool) {\n bool _success;\n assembly {\n _success := call(\n _gas, // gas\n _target, // recipient\n _value, // ether value\n 0, // inloc\n 0, // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n\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, 32), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n\n /**\n * @notice Helper function to determine if there is sufficient gas remaining within the context\n * to guarantee that the minimum gas requirement for a call will be met as well as\n * optionally reserving a specified amount of gas for after the call has concluded.\n * @param _minGas The minimum amount of gas that may be passed to the target context.\n * @param _reservedGas Optional amount of gas to reserve for the caller after the execution\n * of the target context.\n * @return `true` if there is enough gas remaining to safely supply `_minGas` to the target\n * context as well as reserve `_reservedGas` for the caller after the execution of\n * the target context.\n * @dev !!!!! FOOTGUN ALERT !!!!!\n * 1.) The 40_000 base buffer is to account for the worst case of the dynamic cost of the\n * `CALL` opcode's `address_access_cost`, `positive_value_cost`, and\n * `value_to_empty_account_cost` factors with an added buffer of 5,700 gas. It is\n * still possible to self-rekt by initiating a withdrawal with a minimum gas limit\n * that does not account for the `memory_expansion_cost` & `code_execution_cost`\n * factors of the dynamic cost of the `CALL` opcode.\n * 2.) This function should *directly* precede the external call if possible. There is an\n * added buffer to account for gas consumed between this check and the call, but it\n * is only 5,700 gas.\n * 3.) Because EIP-150 ensures that a maximum of 63/64ths of the remaining gas in the call\n * frame may be passed to a subcontext, we need to ensure that the gas will not be\n * truncated.\n * 4.) Use wisely. This function is not a silver bullet.\n */\n function hasMinGas(uint256 _minGas, uint256 _reservedGas) internal view returns (bool) {\n bool _hasMinGas;\n assembly {\n // Equation: gas × 63 ≥ minGas × 64 + 63(40_000 + reservedGas)\n _hasMinGas := iszero(\n lt(mul(gas(), 63), add(mul(_minGas, 64), mul(add(40000, _reservedGas), 63)))\n )\n }\n return _hasMinGas;\n }\n\n /**\n * @notice Perform a low level call without copying any returndata. This function\n * will revert if the call cannot be performed with the specified minimum\n * gas.\n *\n * @param _target Address to call\n * @param _minGas The minimum amount of gas that may be passed 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 callWithMinGas(\n address _target,\n uint256 _minGas,\n uint256 _value,\n bytes memory _calldata\n ) internal returns (bool) {\n bool _success;\n bool _hasMinGas = hasMinGas(_minGas, 0);\n assembly {\n // Assertion: gasleft() >= (_minGas * 64) / 63 + 40_000\n if iszero(_hasMinGas) {\n // Store the \"Error(string)\" selector in scratch space.\n mstore(0, 0x08c379a0)\n // Store the pointer to the string length in scratch space.\n mstore(32, 32)\n // Store the string.\n //\n // SAFETY:\n // - We pad the beginning of the string with two zero bytes as well as the\n // length (24) to ensure that we override the free memory pointer at offset\n // 0x40. This is necessary because the free memory pointer is likely to\n // be greater than 1 byte when this function is called, but it is incredibly\n // unlikely that it will be greater than 3 bytes. As for the data within\n // 0x60, it is ensured that it is 0 due to 0x60 being the zero offset.\n // - It's fine to clobber the free memory pointer, we're reverting.\n mstore(88, 0x0000185361666543616c6c3a204e6f7420656e6f75676820676173)\n\n // Revert with 'Error(\"SafeCall: Not enough gas\")'\n revert(28, 100)\n }\n\n // The call will be supplied at least ((_minGas * 64) / 63) gas due to the\n // above assertion. This ensures that, in all circumstances (except for when the\n // `_minGas` does not account for the `memory_expansion_cost` and `code_execution_cost`\n // factors of the dynamic cost of the `CALL` opcode), the call will receive at least\n // the minimum amount of gas specified.\n _success := call(\n gas(), // gas\n _target, // recipient\n _value, // ether value\n add(_calldata, 32), // inloc\n mload(_calldata), // inlen\n 0x00, // outloc\n 0x00 // outlen\n )\n }\n return _success;\n }\n}\n" - }, - "contracts/libraries/Types.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 * @custom:field outputRoot Hash of the L2 output.\n * @custom:field timestamp Timestamp of the L1 block that the output root was submitted in.\n * @custom:field l2BlockNumber L2 block number that the output corresponds to.\n */\n struct OutputProposal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2BlockNumber;\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 * @custom:field version Version of the output root.\n * @custom:field stateRoot Root of the state trie at the block of this output.\n * @custom:field messagePasserStorageRoot Root of the message passer storage trie.\n * @custom:field latestBlockhash Hash of the block this output was generated from.\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 * @custom:field from Address of the sender of the transaction.\n * @custom:field to Address of the recipient of the transaction.\n * @custom:field isCreation True if the transaction is a contract creation.\n * @custom:field value Value to send to the recipient.\n * @custom:field mint Amount of ETH to mint.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the transaction.\n * @custom:field l1BlockHash Hash of the block the transaction was submitted in.\n * @custom:field logIndex Index of the log in the block the transaction was submitted in.\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 * @custom:field nonce Nonce of the withdrawal transaction\n * @custom:field sender Address of the sender of the transaction.\n * @custom:field target Address of the recipient of the transaction.\n * @custom:field value Value to send to the recipient.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the 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" - }, - "contracts/libraries/rlp/RLPReader.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\n/**\n * @custom:attribution https://github.com/hamdiallam/Solidity-RLP\n * @title RLPReader\n * @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted\n * from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with\n * various tweaks to improve readability.\n */\nlibrary RLPReader {\n /**\n * Custom pointer type to avoid confusion between pointers and uint256s.\n */\n type MemoryPointer is uint256;\n\n /**\n * @notice RLP item types.\n *\n * @custom:value DATA_ITEM Represents an RLP data item (NOT a list).\n * @custom:value LIST_ITEM Represents an RLP list item.\n */\n enum RLPItemType {\n DATA_ITEM,\n LIST_ITEM\n }\n\n /**\n * @notice Struct representing an RLP item.\n *\n * @custom:field length Length of the RLP item.\n * @custom:field ptr Pointer to the RLP item in memory.\n */\n struct RLPItem {\n uint256 length;\n MemoryPointer ptr;\n }\n\n /**\n * @notice Max list length that this library will accept.\n */\n uint256 internal constant MAX_LIST_LENGTH = 32;\n\n /**\n * @notice Converts bytes to a reference to memory position and length.\n *\n * @param _in Input bytes to convert.\n *\n * @return Output memory reference.\n */\n function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) {\n // Empty arrays are not RLP items.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr;\n assembly {\n ptr := add(_in, 32)\n }\n\n return RLPItem({ length: _in.length, ptr: ptr });\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) {\n (uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.LIST_ITEM,\n \"RLPReader: decoded item type for list is not a list item\"\n );\n\n require(\n listOffset + listLength == _in.length,\n \"RLPReader: list item has an invalid data remainder\"\n );\n\n // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by\n // writing to the length. Since we can't know the number of RLP items without looping over\n // the entire input, we'd have to loop twice to accurately size this array. It's easier to\n // simply set a reasonable maximum list length and decrease the size before we finish.\n RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH);\n\n uint256 itemCount = 0;\n uint256 offset = listOffset;\n while (offset < _in.length) {\n (uint256 itemOffset, uint256 itemLength, ) = _decodeLength(\n RLPItem({\n length: _in.length - offset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n })\n );\n\n // We don't need to check itemCount < out.length explicitly because Solidity already\n // handles this check on our behalf, we'd just be wasting gas.\n out[itemCount] = RLPItem({\n length: itemLength + itemOffset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n });\n\n itemCount += 1;\n offset += itemOffset + itemLength;\n }\n\n // Decrease the array size to match the actual item count.\n assembly {\n mstore(out, itemCount)\n }\n\n return out;\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(bytes memory _in) internal pure returns (RLPItem[] memory) {\n return readList(toRLPItem(_in));\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.DATA_ITEM,\n \"RLPReader: decoded item type for bytes is not a data item\"\n );\n\n require(\n _in.length == itemOffset + itemLength,\n \"RLPReader: bytes value contains an invalid remainder\"\n );\n\n return _copy(_in.ptr, itemOffset, itemLength);\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(bytes memory _in) internal pure returns (bytes memory) {\n return readBytes(toRLPItem(_in));\n }\n\n /**\n * @notice Reads the raw bytes of an RLP item.\n *\n * @param _in RLP item to read.\n *\n * @return Raw RLP bytes.\n */\n function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n return _copy(_in.ptr, 0, _in.length);\n }\n\n /**\n * @notice Decodes the length of an RLP item.\n *\n * @param _in RLP item to decode.\n *\n * @return Offset of the encoded data.\n * @return Length of the encoded data.\n * @return RLP item type (LIST_ITEM or DATA_ITEM).\n */\n function _decodeLength(RLPItem memory _in)\n private\n pure\n returns (\n uint256,\n uint256,\n RLPItemType\n )\n {\n // Short-circuit if there's nothing to decode, note that we perform this check when\n // the user creates an RLP item via toRLPItem, but it's always possible for them to bypass\n // that function and create an RLP item directly. So we need to check this anyway.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr = _in.ptr;\n uint256 prefix;\n assembly {\n prefix := byte(0, mload(ptr))\n }\n\n if (prefix <= 0x7f) {\n // Single byte.\n return (0, 1, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xb7) {\n // Short string.\n\n // slither-disable-next-line variable-scope\n uint256 strLen = prefix - 0x80;\n\n require(\n _in.length > strLen,\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n strLen != 1 || firstByteOfContent >= 0x80,\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n\n return (1, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xbf) {\n // Long string.\n uint256 lenOfStrLen = prefix - 0xb7;\n\n require(\n _in.length > lenOfStrLen,\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n\n uint256 strLen;\n assembly {\n strLen := shr(sub(256, mul(8, lenOfStrLen)), mload(add(ptr, 1)))\n }\n\n require(\n strLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long string)\"\n );\n\n require(\n _in.length > lenOfStrLen + strLen,\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n\n return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xf7) {\n // Short list.\n // slither-disable-next-line variable-scope\n uint256 listLen = prefix - 0xc0;\n\n require(\n _in.length > listLen,\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n\n return (1, listLen, RLPItemType.LIST_ITEM);\n } else {\n // Long list.\n uint256 lenOfListLen = prefix - 0xf7;\n\n require(\n _in.length > lenOfListLen,\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long list)\"\n );\n\n uint256 listLen;\n assembly {\n listLen := shr(sub(256, mul(8, lenOfListLen)), mload(add(ptr, 1)))\n }\n\n require(\n listLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long list)\"\n );\n\n require(\n _in.length > lenOfListLen + listLen,\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n\n return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);\n }\n }\n\n /**\n * @notice Copies the bytes from a memory location.\n *\n * @param _src Pointer to the location to read from.\n * @param _offset Offset to start reading from.\n * @param _length Number of bytes to read.\n *\n * @return Copied bytes.\n */\n function _copy(\n MemoryPointer _src,\n uint256 _offset,\n uint256 _length\n ) private pure returns (bytes memory) {\n bytes memory out = new bytes(_length);\n if (_length == 0) {\n return out;\n }\n\n // Mostly based on Solidity's copy_memory_to_memory:\n // solhint-disable max-line-length\n // https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114\n uint256 src = MemoryPointer.unwrap(_src) + _offset;\n assembly {\n let dest := add(out, 32)\n let i := 0\n for {\n\n } lt(i, _length) {\n i := add(i, 32)\n } {\n mstore(add(dest, i), mload(add(src, i)))\n }\n\n if gt(i, _length) {\n mstore(add(dest, _length), 0)\n }\n }\n\n return out;\n }\n}\n" - }, - "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" - }, - "contracts/libraries/trie/MerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Bytes } from \"../Bytes.sol\";\nimport { RLPReader } from \"../rlp/RLPReader.sol\";\n\n/**\n * @title MerkleTrie\n * @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie\n * inclusion proofs. By default, this library assumes a hexary trie. One can change the\n * trie radix constant to support other trie radixes.\n */\nlibrary MerkleTrie {\n /**\n * @notice Struct representing a node in the trie.\n *\n * @custom:field encoded The RLP-encoded node.\n * @custom:field decoded The RLP-decoded node.\n */\n struct TrieNode {\n bytes encoded;\n RLPReader.RLPItem[] decoded;\n }\n\n /**\n * @notice Determines the number of elements per branch node.\n */\n uint256 internal constant TREE_RADIX = 16;\n\n /**\n * @notice Branch nodes have TREE_RADIX elements and one value element.\n */\n uint256 internal constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;\n\n /**\n * @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.\n */\n uint256 internal constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;\n\n /**\n * @notice Prefix for even-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_EVEN = 0;\n\n /**\n * @notice Prefix for odd-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_ODD = 1;\n\n /**\n * @notice Prefix for even-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_EVEN = 2;\n\n /**\n * @notice Prefix for odd-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_ODD = 3;\n\n /**\n * @notice Verifies a proof that a given key/value pair is present in the trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n return Bytes.equal(_value, get(_key, _proof, _root));\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n require(_key.length > 0, \"MerkleTrie: empty key\");\n\n TrieNode[] memory proof = _parseProof(_proof);\n bytes memory key = Bytes.toNibbles(_key);\n bytes memory currentNodeID = abi.encodePacked(_root);\n uint256 currentKeyIndex = 0;\n\n // Proof is top-down, so we start at the first element (root).\n for (uint256 i = 0; i < proof.length; i++) {\n TrieNode memory currentNode = proof[i];\n\n // Key index should never exceed total key length or we'll be out of bounds.\n require(\n currentKeyIndex <= key.length,\n \"MerkleTrie: key index exceeds total key length\"\n );\n\n if (currentKeyIndex == 0) {\n // First proof element is always the root node.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid root hash\"\n );\n } else if (currentNode.encoded.length >= 32) {\n // Nodes 32 bytes or larger are hashed inside branch nodes.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid large internal hash\"\n );\n } else {\n // Nodes smaller than 32 bytes aren't hashed.\n require(\n Bytes.equal(currentNode.encoded, currentNodeID),\n \"MerkleTrie: invalid internal node hash\"\n );\n }\n\n if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {\n if (currentKeyIndex == key.length) {\n // Value is the last element of the decoded list (for branch nodes). There's\n // some ambiguity in the Merkle trie specification because bytes(0) is a\n // valid value to place into the trie, but for branch nodes bytes(0) can exist\n // even when the value wasn't explicitly placed there. Geth treats a value of\n // bytes(0) as \"key does not exist\" and so we do the same.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[TREE_RADIX]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (branch)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (branch)\"\n );\n\n return value;\n } else {\n // We're not at the end of the key yet.\n // Figure out what the next node ID should be and continue.\n uint8 branchKey = uint8(key[currentKeyIndex]);\n RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];\n currentNodeID = _getNodeID(nextNode);\n currentKeyIndex += 1;\n }\n } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {\n bytes memory path = _getNodePath(currentNode);\n uint8 prefix = uint8(path[0]);\n uint8 offset = 2 - (prefix % 2);\n bytes memory pathRemainder = Bytes.slice(path, offset);\n bytes memory keyRemainder = Bytes.slice(key, currentKeyIndex);\n uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);\n\n // Whether this is a leaf node or an extension node, the path remainder MUST be a\n // prefix of the key remainder (or be equal to the key remainder) or the proof is\n // considered invalid.\n require(\n pathRemainder.length == sharedNibbleLength,\n \"MerkleTrie: path remainder must share all nibbles with key\"\n );\n\n if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {\n // Prefix of 2 or 3 means this is a leaf node. For the leaf node to be valid,\n // the key remainder must be exactly equal to the path remainder. We already\n // did the necessary byte comparison, so it's more efficient here to check that\n // the key remainder length equals the shared nibble length, which implies\n // equality with the path remainder (since we already did the same check with\n // the path remainder and the shared nibble length).\n require(\n keyRemainder.length == sharedNibbleLength,\n \"MerkleTrie: key remainder must be identical to path remainder\"\n );\n\n // Our Merkle Trie is designed specifically for the purposes of the Ethereum\n // state trie. Empty values are not allowed in the state trie, so we can safely\n // say that if the value is empty, the key should not exist and the proof is\n // invalid.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[1]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (leaf)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (leaf)\"\n );\n\n return value;\n } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {\n // Prefix of 0 or 1 means this is an extension node. We move onto the next node\n // in the proof and increment the key index by the length of the path remainder\n // which is equal to the shared nibble length.\n currentNodeID = _getNodeID(currentNode.decoded[1]);\n currentKeyIndex += sharedNibbleLength;\n } else {\n revert(\"MerkleTrie: received a node with an unknown prefix\");\n }\n } else {\n revert(\"MerkleTrie: received an unparseable node\");\n }\n }\n\n revert(\"MerkleTrie: ran out of proof elements\");\n }\n\n /**\n * @notice Parses an array of proof elements into a new array that contains both the original\n * encoded element and the RLP-decoded element.\n *\n * @param _proof Array of proof elements to parse.\n *\n * @return Proof parsed into easily accessible structs.\n */\n function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory) {\n uint256 length = _proof.length;\n TrieNode[] memory proof = new TrieNode[](length);\n for (uint256 i = 0; i < length; ) {\n proof[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) });\n unchecked {\n ++i;\n }\n }\n return proof;\n }\n\n /**\n * @notice Picks out the ID for a node. Node ID is referred to as the \"hash\" within the\n * specification, but nodes < 32 bytes are not actually hashed.\n *\n * @param _node Node to pull an ID for.\n *\n * @return ID for the node, depending on the size of its contents.\n */\n function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes memory) {\n return _node.length < 32 ? RLPReader.readRawBytes(_node) : RLPReader.readBytes(_node);\n }\n\n /**\n * @notice Gets the path for a leaf or extension node.\n *\n * @param _node Node to get a path for.\n *\n * @return Node path, converted to an array of nibbles.\n */\n function _getNodePath(TrieNode memory _node) private pure returns (bytes memory) {\n return Bytes.toNibbles(RLPReader.readBytes(_node.decoded[0]));\n }\n\n /**\n * @notice Utility; determines the number of nibbles shared between two nibble arrays.\n *\n * @param _a First nibble array.\n * @param _b Second nibble array.\n *\n * @return Number of shared nibbles.\n */\n function _getSharedNibbleLength(bytes memory _a, bytes memory _b)\n private\n pure\n returns (uint256)\n {\n uint256 shared;\n uint256 max = (_a.length < _b.length) ? _a.length : _b.length;\n for (; shared < max && _a[shared] == _b[shared]; ) {\n unchecked {\n ++shared;\n }\n }\n return shared;\n }\n}\n" - }, - "contracts/libraries/trie/SecureMerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* Library Imports */\nimport { MerkleTrie } from \"./MerkleTrie.sol\";\n\n/**\n * @title SecureMerkleTrie\n * @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input\n * keys. Ethereum's state trie hashes input keys before storing them.\n */\nlibrary SecureMerkleTrie {\n /**\n * @notice Verifies a proof that a given key/value pair is present in the Merkle trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.get(key, _proof, _root);\n }\n\n /**\n * @notice Computes the hashed version of the input key.\n *\n * @param _key Key to hash.\n *\n * @return Hashed version of the key.\n */\n function _getSecureKey(bytes memory _key) private pure returns (bytes memory) {\n return abi.encodePacked(keccak256(_key));\n }\n}\n" - }, - "contracts/periphery/TransferOnion.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ReentrancyGuard } from \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @title TransferOnion\n * @notice TransferOnion is a hash onion for distributing tokens. The shell commits\n * to an ordered list of the token transfers and can be permissionlessly\n * unwrapped in order. The SENDER must `approve` this contract as\n * `transferFrom` is used to move the token balances.\n */\ncontract TransferOnion is ReentrancyGuard {\n using SafeERC20 for ERC20;\n\n /**\n * @notice Struct representing a layer of the onion.\n */\n struct Layer {\n address recipient;\n uint256 amount;\n bytes32 shell;\n }\n\n /**\n * @notice Address of the token to distribute.\n */\n ERC20 public immutable TOKEN;\n\n /**\n * @notice Address of the account to distribute tokens from.\n */\n address public immutable SENDER;\n\n /**\n * @notice Current shell hash.\n */\n bytes32 public shell;\n\n /**\n * @param _token Address of the token to distribute.\n * @param _sender Address of the sender to distribute from.\n * @param _shell Initial shell of the onion.\n */\n constructor(\n ERC20 _token,\n address _sender,\n bytes32 _shell\n ) {\n TOKEN = _token;\n SENDER = _sender;\n shell = _shell;\n }\n\n /**\n * @notice Peels layers from the onion and distributes tokens.\n *\n * @param _layers Array of onion layers to peel.\n */\n function peel(Layer[] memory _layers) public nonReentrant {\n bytes32 tempShell = shell;\n uint256 length = _layers.length;\n for (uint256 i = 0; i < length; ) {\n Layer memory layer = _layers[i];\n\n // Confirm that the onion layer is correct.\n require(\n keccak256(abi.encode(layer.recipient, layer.amount, layer.shell)) == tempShell,\n \"TransferOnion: what are you doing in my swamp?\"\n );\n\n // Update the onion layer.\n tempShell = layer.shell;\n\n // Transfer the tokens.\n TOKEN.safeTransferFrom(SENDER, layer.recipient, layer.amount);\n\n // Unchecked increment to save some gas.\n unchecked {\n ++i;\n }\n }\n\n shell = tempShell;\n }\n}\n" - }, - "contracts/test/AddressAliasHelper.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract AddressAliasHelper_applyAndUndo_Test is Test {\n /**\n * @notice Tests that applying and then undoing an alias results in the original address.\n */\n function testFuzz_applyAndUndo_succeeds(address _address) external {\n address aliased = AddressAliasHelper.applyL1ToL2Alias(_address);\n address unaliased = AddressAliasHelper.undoL1ToL2Alias(aliased);\n assertEq(_address, unaliased);\n }\n}\n" - }, - "contracts/test/BenchmarkTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test } from \"forge-std/Test.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport \"./CommonTest.t.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\n// Free function for setting the prevBaseFee param in the OptimismPortal.\nfunction setPrevBaseFee(\n Vm _vm,\n address _op,\n uint128 _prevBaseFee\n) {\n _vm.store(address(_op), bytes32(uint256(1)), bytes32((block.number << 192) | _prevBaseFee));\n}\n\ncontract SetPrevBaseFee_Test is Portal_Initializer {\n function test_setPrevBaseFee_succeeds() external {\n setPrevBaseFee(vm, address(op), 100 gwei);\n (uint128 prevBaseFee, , uint64 prevBlockNum) = op.params();\n assertEq(uint256(prevBaseFee), 100 gwei);\n assertEq(uint256(prevBlockNum), block.number);\n }\n}\n\n// Tests for obtaining pure gas cost estimates for commonly used functions.\n// The objective with these benchmarks is to strip down the actual test functions\n// so that they are nothing more than the call we want measure the gas cost of.\n// In order to achieve this we make no assertions, and handle everything else in the setUp()\n// function.\ncontract GasBenchMark_OptimismPortal is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n bytes32 _outputRoot;\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n\n // Get withdrawal proof data we can use for testing.\n bytes32 _storageRoot;\n bytes32 _stateRoot;\n (_stateRoot, _storageRoot, _outputRoot, , _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public virtual override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n function test_depositTransaction_benchmark() external {\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_depositTransaction_benchmark_1() external {\n setPrevBaseFee(vm, address(op), 1 gwei);\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_proveWithdrawalTransaction_benchmark() external {\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n}\n\ncontract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer {\n function test_sendMessage_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n vm.resumeGasMetering();\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n\n function test_sendMessage_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n vm.resumeGasMetering();\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), alice, 100000, true);\n vm.startPrank(alice, alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n }\n\n function test_depositETH_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n vm.resumeGasMetering();\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositETH_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n vm.resumeGasMetering();\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositERC20_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n vm.resumeGasMetering();\n L1Bridge.bridgeERC20({\n _localToken: address(L1Token),\n _remoteToken: address(L2Token),\n _amount: 100,\n _minGasLimit: 100_000,\n _extraData: hex\"\"\n });\n }\n\n function test_depositERC20_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n vm.resumeGasMetering();\n L1Bridge.bridgeERC20({\n _localToken: address(L1Token),\n _remoteToken: address(L2Token),\n _amount: 100,\n _minGasLimit: 100_000,\n _extraData: hex\"\"\n });\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Finalize is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), address(L1Bridge), 100, true);\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.startPrank(address(L1Bridge.messenger()));\n vm.deal(address(L1Bridge.messenger()), 100);\n }\n\n function test_finalizeETHWithdrawal_benchmark() external {\n // TODO: Make this more accurate. It is underestimating the cost because it pranks\n // the call coming from the messenger, which bypasses the portal\n // and oracle.\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n\ncontract GasBenchMark_L2OutputOracle is L2OutputOracle_Initializer {\n uint256 nextBlockNumber;\n\n function setUp() public override {\n super.setUp();\n nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.startPrank(proposer);\n }\n\n function test_proposeL2Output_benchmark() external {\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n}\n" - }, - "contracts/test/BondManager.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport \"forge-std/Test.sol\";\n\nimport \"../libraries/DisputeTypes.sol\";\n\nimport { IDisputeGame } from \"../dispute/IDisputeGame.sol\";\nimport { IBondManager } from \"../dispute/IBondManager.sol\";\n\nimport { DisputeGameFactory } from \"../dispute/DisputeGameFactory.sol\";\n\nimport { BondManager } from \"../dispute/BondManager.sol\";\n\ncontract BondManager_Test is Test {\n DisputeGameFactory factory;\n BondManager bm;\n\n // DisputeGameFactory events\n event DisputeGameCreated(\n address indexed disputeProxy,\n GameType indexed gameType,\n Claim indexed rootClaim\n );\n\n // BondManager events\n event BondPosted(bytes32 bondId, address owner, uint256 expiration, uint256 amount);\n event BondSeized(bytes32 bondId, address owner, address seizer, uint256 amount);\n event BondReclaimed(bytes32 bondId, address claiment, uint256 amount);\n\n function setUp() public {\n factory = new DisputeGameFactory(address(this));\n bm = new BondManager(factory);\n }\n\n /**\n * -------------------------------------------\n * Test Bond Posting\n * -------------------------------------------\n */\n\n /**\n * @notice Tests that posting a bond succeeds.\n */\n function testFuzz_post_succeeds(\n bytes32 bondId,\n address owner,\n uint256 minClaimHold,\n uint256 amount\n ) public {\n vm.assume(owner != address(0));\n vm.assume(owner != address(bm));\n vm.assume(owner != address(this));\n // Create2Deployer\n vm.assume(owner != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n vm.assume(amount != 0);\n unchecked {\n vm.assume(block.timestamp + minClaimHold > minClaimHold);\n }\n\n vm.deal(address(this), amount);\n\n vm.expectEmit(true, true, true, true);\n uint256 expiration = block.timestamp + minClaimHold;\n emit BondPosted(bondId, owner, expiration, amount);\n\n bm.post{ value: amount }(bondId, owner, minClaimHold);\n\n // Validate the bond\n (\n address newFetchedOwner,\n uint256 fetchedExpiration,\n bytes32 fetchedBondId,\n uint256 bondAmount\n ) = bm.bonds(bondId);\n assertEq(newFetchedOwner, owner);\n assertEq(fetchedExpiration, block.timestamp + minClaimHold);\n assertEq(fetchedBondId, bondId);\n assertEq(bondAmount, amount);\n }\n\n /**\n * @notice Tests that posting a bond with the same id twice reverts.\n */\n function testFuzz_post_duplicates_reverts(\n bytes32 bondId,\n address owner,\n uint256 minClaimHold,\n uint256 amount\n ) public {\n vm.assume(owner != address(0));\n amount = amount / 2;\n vm.assume(amount != 0);\n unchecked {\n vm.assume(block.timestamp + minClaimHold > minClaimHold);\n }\n\n vm.deal(address(this), amount);\n bm.post{ value: amount }(bondId, owner, minClaimHold);\n\n vm.deal(address(this), amount);\n vm.expectRevert(\"BondManager: BondId already posted.\");\n bm.post{ value: amount }(bondId, owner, minClaimHold);\n }\n\n /**\n * @notice Posting with the zero address as the owner fails.\n */\n function testFuzz_post_zeroAddress_reverts(\n bytes32 bondId,\n uint256 minClaimHold,\n uint256 amount\n ) public {\n address owner = address(0);\n vm.deal(address(this), amount);\n vm.expectRevert(\"BondManager: Owner cannot be the zero address.\");\n bm.post{ value: amount }(bondId, owner, minClaimHold);\n }\n\n /**\n * @notice Posting zero value bonds should revert.\n */\n function testFuzz_post_zeroAddress_reverts(\n bytes32 bondId,\n address owner,\n uint256 minClaimHold\n ) public {\n vm.assume(owner != address(0));\n uint256 amount = 0;\n vm.deal(address(this), amount);\n vm.expectRevert(\"BondManager: Value must be non-zero.\");\n bm.post{ value: amount }(bondId, owner, minClaimHold);\n }\n\n /**\n * -------------------------------------------\n * Test Bond Seizing\n * -------------------------------------------\n */\n\n /**\n * @notice Non-existing bonds shouldn't be seizable.\n */\n function testFuzz_seize_missingBond_reverts(bytes32 bondId) public {\n vm.expectRevert(\"BondManager: The bond does not exist.\");\n bm.seize(bondId);\n }\n\n /**\n * @notice Bonds that expired cannot be seized.\n */\n function testFuzz_seize_expired_reverts(\n bytes32 bondId,\n address owner,\n uint256 minClaimHold,\n uint256 amount\n ) public {\n vm.assume(owner != address(0));\n vm.assume(owner != address(bm));\n vm.assume(owner != address(this));\n vm.assume(amount != 0);\n unchecked {\n vm.assume(block.timestamp + minClaimHold + 1 > minClaimHold);\n }\n vm.deal(address(this), amount);\n bm.post{ value: amount }(bondId, owner, minClaimHold);\n\n vm.warp(block.timestamp + minClaimHold + 1);\n vm.expectRevert(\"BondManager: Bond expired.\");\n bm.seize(bondId);\n }\n\n /**\n * @notice Bonds cannot be seized by unauthorized parties.\n */\n function testFuzz_seize_unauthorized_reverts(\n bytes32 bondId,\n address owner,\n uint256 minClaimHold,\n uint256 amount\n ) public {\n vm.assume(owner != address(0));\n vm.assume(owner != address(bm));\n vm.assume(owner != address(this));\n vm.assume(amount != 0);\n unchecked {\n vm.assume(block.timestamp + minClaimHold > minClaimHold);\n }\n vm.deal(address(this), amount);\n bm.post{ value: amount }(bondId, owner, minClaimHold);\n\n MockAttestationDisputeGame game = new MockAttestationDisputeGame();\n vm.prank(address(game));\n vm.expectRevert(\"BondManager: Unauthorized seizure.\");\n bm.seize(bondId);\n }\n\n /**\n * @notice Seizing a bond should succeed if the game resolves.\n */\n function testFuzz_seize_succeeds(\n bytes32 bondId,\n uint256 minClaimHold,\n bytes calldata extraData\n ) public {\n unchecked {\n vm.assume(block.timestamp + minClaimHold > minClaimHold);\n }\n\n vm.deal(address(this), 1 ether);\n bm.post{ value: 1 ether }(bondId, address(0xba5ed), minClaimHold);\n\n // Create a mock dispute game in the factory\n IDisputeGame proxy;\n Claim rootClaim;\n bytes memory ed = extraData;\n {\n rootClaim = Claim.wrap(bytes32(\"\"));\n MockAttestationDisputeGame implementation = new MockAttestationDisputeGame();\n GameType gt = GameType.ATTESTATION;\n factory.setImplementation(gt, IDisputeGame(address(implementation)));\n vm.expectEmit(false, true, true, false);\n emit DisputeGameCreated(address(0), gt, rootClaim);\n proxy = factory.create(gt, rootClaim, extraData);\n assertEq(address(factory.games(gt, rootClaim, extraData)), address(proxy));\n }\n\n // Update the game fields\n MockAttestationDisputeGame spawned = MockAttestationDisputeGame(payable(address(proxy)));\n spawned.setBondManager(bm);\n spawned.setRootClaim(rootClaim);\n spawned.setGameStatus(GameStatus.CHALLENGER_WINS);\n spawned.setBondId(bondId);\n spawned.setExtraData(ed);\n\n // Seize the bond by calling resolve\n vm.expectEmit(true, true, true, true);\n emit BondSeized(bondId, address(0xba5ed), address(spawned), 1 ether);\n spawned.resolve();\n assertEq(address(spawned).balance, 1 ether);\n\n // Validate that the bond was deleted\n (address newFetchedOwner, , , ) = bm.bonds(bondId);\n assertEq(newFetchedOwner, address(0));\n }\n\n /**\n * -------------------------------------------\n * Test Bond Split and Seizing\n * -------------------------------------------\n */\n\n /**\n * @notice Seizing and splitting a bond should succeed if the game resolves.\n */\n function testFuzz_seizeAndSplit_succeeds(\n bytes32 bondId,\n uint256 minClaimHold,\n bytes calldata extraData\n ) public {\n unchecked {\n vm.assume(block.timestamp + minClaimHold > minClaimHold);\n }\n\n vm.deal(address(this), 1 ether);\n bm.post{ value: 1 ether }(bondId, address(0xba5ed), minClaimHold);\n\n // Create a mock dispute game in the factory\n IDisputeGame proxy;\n Claim rootClaim;\n bytes memory ed = extraData;\n {\n rootClaim = Claim.wrap(bytes32(\"\"));\n MockAttestationDisputeGame implementation = new MockAttestationDisputeGame();\n GameType gt = GameType.ATTESTATION;\n factory.setImplementation(gt, IDisputeGame(address(implementation)));\n vm.expectEmit(false, true, true, false);\n emit DisputeGameCreated(address(0), gt, rootClaim);\n proxy = factory.create(gt, rootClaim, extraData);\n assertEq(address(factory.games(gt, rootClaim, extraData)), address(proxy));\n }\n\n // Update the game fields\n MockAttestationDisputeGame spawned = MockAttestationDisputeGame(payable(address(proxy)));\n spawned.setBondManager(bm);\n spawned.setRootClaim(rootClaim);\n spawned.setGameStatus(GameStatus.CHALLENGER_WINS);\n spawned.setBondId(bondId);\n spawned.setExtraData(ed);\n\n // Seize the bond by calling resolve\n vm.expectEmit(true, true, true, true);\n emit BondSeized(bondId, address(0xba5ed), address(spawned), 1 ether);\n spawned.splitResolve();\n assertEq(address(spawned).balance, 0);\n address[] memory challengers = spawned.getChallengers();\n uint256 proportionalAmount = 1 ether / challengers.length;\n for (uint256 i = 0; i < challengers.length; i++) {\n assertEq(address(challengers[i]).balance, proportionalAmount);\n }\n\n // Validate that the bond was deleted\n (address newFetchedOwner, , , ) = bm.bonds(bondId);\n assertEq(newFetchedOwner, address(0));\n }\n\n /**\n * -------------------------------------------\n * Test Bond Reclaiming\n * -------------------------------------------\n */\n\n /**\n * @notice Bonds can be reclaimed after the specified amount of time.\n */\n function testFuzz_reclaim_succeeds(\n bytes32 bondId,\n address owner,\n uint256 minClaimHold,\n uint256 amount\n ) public {\n vm.assume(owner != address(0));\n vm.assume(owner.code.length == 0);\n vm.assume(amount != 0);\n unchecked {\n vm.assume(block.timestamp + minClaimHold > minClaimHold);\n }\n assumeNoPrecompiles(owner);\n\n // Post the bond\n vm.deal(address(this), amount);\n bm.post{ value: amount }(bondId, owner, minClaimHold);\n\n // We can't claim if the block.timestamp is less than the bond expiration.\n (, uint256 expiration, , ) = bm.bonds(bondId);\n if (expiration > block.timestamp) {\n vm.prank(owner);\n vm.expectRevert(\"BondManager: Bond isn't claimable yet.\");\n bm.reclaim(bondId);\n }\n\n // Past expiration, the owner can reclaim\n vm.warp(expiration);\n vm.prank(owner);\n bm.reclaim(bondId);\n assertEq(owner.balance, amount);\n }\n}\n\n/**\n * @title MockAttestationDisputeGame\n * @dev A mock dispute game for testing bond seizures.\n */\ncontract MockAttestationDisputeGame is IDisputeGame {\n GameStatus internal gameStatus;\n BondManager bm;\n Claim internal rc;\n bytes internal ed;\n bytes32 internal bondId;\n\n address[] internal challengers;\n\n function getChallengers() public view returns (address[] memory) {\n return challengers;\n }\n\n function setBondId(bytes32 bid) external {\n bondId = bid;\n }\n\n function setBondManager(BondManager _bm) external {\n bm = _bm;\n }\n\n function setGameStatus(GameStatus _gs) external {\n gameStatus = _gs;\n }\n\n function setRootClaim(Claim _rc) external {\n rc = _rc;\n }\n\n function setExtraData(bytes memory _ed) external {\n ed = _ed;\n }\n\n receive() external payable {}\n\n fallback() external payable {}\n\n function splitResolve() public {\n challengers = [address(1), address(2)];\n bm.seizeAndSplit(bondId, challengers);\n }\n\n /**\n * -------------------------------------------\n * Initializable Functions\n * -------------------------------------------\n */\n\n function initialize() external {\n /* noop */\n }\n\n /**\n * -------------------------------------------\n * IVersioned Functions\n * -------------------------------------------\n */\n\n function version() external pure returns (string memory _version) {\n return \"0.1.0\";\n }\n\n /**\n * -------------------------------------------\n * IDisputeGame Functions\n * -------------------------------------------\n */\n\n function createdAt() external pure override returns (Timestamp _createdAt) {\n return Timestamp.wrap(uint64(0));\n }\n\n function status() external view override returns (GameStatus _status) {\n return gameStatus;\n }\n\n function gameType() external pure returns (GameType _gameType) {\n return GameType.ATTESTATION;\n }\n\n function rootClaim() external view override returns (Claim _rootClaim) {\n return rc;\n }\n\n function extraData() external view returns (bytes memory _extraData) {\n return ed;\n }\n\n function bondManager() external view override returns (IBondManager _bondManager) {\n return IBondManager(address(bm));\n }\n\n function resolve() external returns (GameStatus _status) {\n bm.seize(bondId);\n return gameStatus;\n }\n}\n" - }, - "contracts/test/Bytes.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Bytes } from \"../libraries/Bytes.sol\";\n\ncontract Bytes_slice_Test is Test {\n /**\n * @notice Tests that the `slice` function works as expected when starting from index 0.\n */\n function test_slice_fromZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check if all possible slices starting from index 0 are correct.\n assertEq(Bytes.slice(input, 0, 0), hex\"\");\n assertEq(Bytes.slice(input, 0, 1), hex\"11\");\n assertEq(Bytes.slice(input, 0, 2), hex\"1122\");\n assertEq(Bytes.slice(input, 0, 3), hex\"112233\");\n assertEq(Bytes.slice(input, 0, 4), hex\"11223344\");\n assertEq(Bytes.slice(input, 0, 5), hex\"1122334455\");\n assertEq(Bytes.slice(input, 0, 6), hex\"112233445566\");\n assertEq(Bytes.slice(input, 0, 7), hex\"11223344556677\");\n assertEq(Bytes.slice(input, 0, 8), hex\"1122334455667788\");\n assertEq(Bytes.slice(input, 0, 9), hex\"112233445566778899\");\n assertEq(Bytes.slice(input, 0, 10), hex\"11223344556677889900\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when starting from indices [1, 9]\n * with lengths [1, 9], in reverse order.\n */\n function test_slice_fromNonZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check correctness of slices starting from indexes [1, 9]\n // and spanning [1, 9] bytes, in reverse order\n assertEq(Bytes.slice(input, 9, 1), hex\"00\");\n assertEq(Bytes.slice(input, 8, 2), hex\"9900\");\n assertEq(Bytes.slice(input, 7, 3), hex\"889900\");\n assertEq(Bytes.slice(input, 6, 4), hex\"77889900\");\n assertEq(Bytes.slice(input, 5, 5), hex\"6677889900\");\n assertEq(Bytes.slice(input, 4, 6), hex\"556677889900\");\n assertEq(Bytes.slice(input, 3, 7), hex\"44556677889900\");\n assertEq(Bytes.slice(input, 2, 8), hex\"3344556677889900\");\n assertEq(Bytes.slice(input, 1, 9), hex\"223344556677889900\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when slicing between multiple words\n * in memory. In this case, we test that a 2 byte slice between the 32nd byte of the\n * first word and the 1st byte of the second word is correct.\n */\n function test_slice_acrossWords_works() public {\n bytes\n memory input = hex\"00000000000000000000000000000000000000000000000000000000000000112200000000000000000000000000000000000000000000000000000000000000\";\n\n assertEq(Bytes.slice(input, 31, 2), hex\"1122\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when slicing between multiple\n * words in memory. In this case, we test that a 34 byte slice between 3 separate words\n * returns the correct result.\n */\n function test_slice_acrossMultipleWords_works() public {\n bytes\n memory input = hex\"000000000000000000000000000000000000000000000000000000000000001122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1100000000000000000000000000000000000000000000000000000000000000\";\n bytes\n memory expected = hex\"1122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11\";\n\n assertEq(Bytes.slice(input, 31, 34), expected);\n }\n\n /**\n * @notice Tests that, when given an input bytes array of length `n`, the `slice` function will\n * always revert if `_start + _length > n`.\n */\n function testFuzz_slice_outOfBounds_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // We want a valid start index and a length that will not overflow.\n vm.assume(_start < _input.length && _length < type(uint256).max - 31);\n // But, we want an invalid slice length.\n vm.assume(_start + _length > _input.length);\n\n vm.expectRevert(\"slice_outOfBounds\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that, when given a length `n` that is greater than `type(uint256).max - 31`,\n * the `slice` function reverts.\n */\n function testFuzz_slice_lengthOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that the `_length` will overflow if a number >= 31 is added to it.\n vm.assume(_length > type(uint256).max - 31);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that, when given a start index `n` that is greater than\n * `type(uint256).max - n`, the `slice` function reverts.\n */\n function testFuzz_slice_rangeOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that `_length` is a realistic length of a slice. This is to make sure\n // we revert on the correct require statement.\n vm.assume(_length < _input.length);\n // Ensure that `_start` will overflow if `_length` is added to it.\n vm.assume(_start > type(uint256).max - _length);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that the `slice` function correctly updates the free memory pointer depending\n * on the length of the slice.\n */\n function testFuzz_slice_memorySafety_succeeds(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // The start should never be more than the length of the input bytes array - 1\n vm.assume(_start < _input.length);\n // The length should never be more than the length of the input bytes array - the starting\n // slice index.\n vm.assume(_length <= _input.length - _start);\n\n // Grab the free memory pointer before the slice operation\n uint64 initPtr;\n assembly {\n initPtr := mload(0x40)\n }\n uint64 expectedPtr = uint64(initPtr + 0x20 + ((_length + 0x1f) & ~uint256(0x1f)));\n\n // Ensure that all memory outside of the expected range is safe.\n vm.expectSafeMemory(initPtr, expectedPtr);\n\n // Slice the input bytes array from `_start` to `_start + _length`\n bytes memory slice = Bytes.slice(_input, _start, _length);\n\n // Grab the free memory pointer after the slice operation\n uint64 finalPtr;\n assembly {\n finalPtr := mload(0x40)\n }\n\n // The free memory pointer should have been updated properly\n if (_length == 0) {\n // If the slice length is zero, only 32 bytes of memory should have been allocated.\n assertEq(finalPtr, initPtr + 0x20);\n } else {\n // If the slice length is greater than zero, the memory allocated should be the\n // length of the slice rounded up to the next 32 byte word + 32 bytes for the\n // length of the byte array.\n //\n // Note that we use a slightly less efficient, but equivalent method of rounding\n // up `_length` to the next multiple of 32 than is used in the `slice` function.\n // This is to diff test the method used in `slice`.\n uint64 _expectedPtr = uint64(initPtr + 0x20 + (((_length + 0x1F) >> 5) << 5));\n assertEq(finalPtr, _expectedPtr);\n\n // Sanity check for equivalence of the rounding methods.\n assertEq(_expectedPtr, expectedPtr);\n }\n\n // The slice length should be equal to `_length`\n assertEq(slice.length, _length);\n }\n}\n\ncontract Bytes_toNibbles_Test is Test {\n /**\n * @notice Diffs the test Solidity version of `toNibbles` against the Yul version.\n *\n * @param _bytes The `bytes` array to convert to nibbles.\n *\n * @return Yul version of `toNibbles` applied to `_bytes`.\n */\n function _toNibblesYul(bytes memory _bytes) internal pure returns (bytes memory) {\n // Allocate memory for the `nibbles` array.\n bytes memory nibbles = new bytes(_bytes.length << 1);\n\n assembly {\n // Load the length of the passed bytes array from memory\n let bytesLength := mload(_bytes)\n\n // Store the memory offset of the _bytes array's contents on the stack\n let bytesStart := add(_bytes, 0x20)\n\n // Store the memory offset of the nibbles array's contents on the stack\n let nibblesStart := add(nibbles, 0x20)\n\n // Loop through each byte in the input array\n for {\n let i := 0x00\n } lt(i, bytesLength) {\n i := add(i, 0x01)\n } {\n // Get the starting offset of the next 2 bytes in the nibbles array\n let offset := add(nibblesStart, shl(0x01, i))\n\n // Load the byte at the current index within the `_bytes` array\n let b := byte(0x00, mload(add(bytesStart, i)))\n\n // Pull out the first nibble and store it in the new array\n mstore8(offset, shr(0x04, b))\n // Pull out the second nibble and store it in the new array\n mstore8(add(offset, 0x01), and(b, 0x0F))\n }\n }\n\n return nibbles;\n }\n\n /**\n * @notice Tests that, given an input of 5 bytes, the `toNibbles` function returns an array of\n * 10 nibbles corresponding to the input data.\n */\n function test_toNibbles_expectedResult5Bytes_works() public {\n bytes memory input = hex\"1234567890\";\n bytes memory expected = hex\"01020304050607080900\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Tests that, given an input of 128 bytes, the `toNibbles` function returns an array\n * of 256 nibbles corresponding to the input data. This test exists to ensure that,\n * given a large input, the `toNibbles` function works as expected.\n */\n function test_toNibbles_expectedResult128Bytes_works() public {\n bytes\n memory input = hex\"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f\";\n bytes\n memory expected = hex\"0000000100020003000400050006000700080009000a000b000c000d000e000f0100010101020103010401050106010701080109010a010b010c010d010e010f0200020102020203020402050206020702080209020a020b020c020d020e020f0300030103020303030403050306030703080309030a030b030c030d030e030f0400040104020403040404050406040704080409040a040b040c040d040e040f0500050105020503050405050506050705080509050a050b050c050d050e050f0600060106020603060406050606060706080609060a060b060c060d060e060f0700070107020703070407050706070707080709070a070b070c070d070e070f\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Tests that, given an input of 0 bytes, the `toNibbles` function returns a zero\n * length array.\n */\n function test_toNibbles_zeroLengthInput_works() public {\n bytes memory input = hex\"\";\n bytes memory expected = hex\"\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length, 0);\n assertEq(expected.length, 0);\n assertEq(actual.length, 0);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Test that the `toNibbles` function in the `Bytes` library is equivalent to the Yul\n * implementation.\n */\n function testDiff_toNibbles_succeeds(bytes memory _input) public {\n assertEq(Bytes.toNibbles(_input), _toNibblesYul(_input));\n }\n}\n\ncontract Bytes_equal_Test is Test {\n /**\n * @notice Manually checks equality of two dynamic `bytes` arrays in memory.\n *\n * @param _a The first `bytes` array to compare.\n * @param _b The second `bytes` array to compare.\n *\n * @return True if the two `bytes` arrays are equal in memory.\n */\n function manualEq(bytes memory _a, bytes memory _b) internal pure returns (bool) {\n bool _eq;\n assembly {\n _eq := and(\n // Check if the contents of the two bytes arrays are equal in memory.\n eq(keccak256(add(0x20, _a), mload(_a)), keccak256(add(0x20, _b), mload(_b))),\n // Check if the length of the two bytes arrays are equal in memory.\n // This is redundant given the above check, but included for completeness.\n eq(mload(_a), mload(_b))\n )\n }\n return _eq;\n }\n\n /**\n * @notice Tests that the `equal` function in the `Bytes` library returns `false` if given two\n * non-equal byte arrays.\n */\n function testFuzz_equal_notEqual_works(bytes memory _a, bytes memory _b) public {\n vm.assume(!manualEq(_a, _b));\n assertFalse(Bytes.equal(_a, _b));\n }\n\n /**\n * @notice Test whether or not the `equal` function in the `Bytes` library is equivalent to\n * manually checking equality of the two dynamic `bytes` arrays in memory.\n */\n function testDiff_equal_works(bytes memory _a, bytes memory _b) public {\n assertEq(Bytes.equal(_a, _b), manualEq(_a, _b));\n }\n}\n" - }, - "contracts/test/CommonTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test, StdUtils } from \"forge-std/Test.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { IL1ChugSplashDeployer } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { LegacyMintableERC20 } from \"../legacy/LegacyMintableERC20.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract CommonTest is Test {\n address alice = address(128);\n address bob = address(256);\n address multisig = address(512);\n\n address immutable ZERO_ADDRESS = address(0);\n address immutable NON_ZERO_ADDRESS = address(1);\n uint256 immutable NON_ZERO_VALUE = 100;\n uint256 immutable ZERO_VALUE = 0;\n uint64 immutable NON_ZERO_GASLIMIT = 50000;\n bytes32 nonZeroHash = keccak256(abi.encode(\"NON_ZERO\"));\n bytes NON_ZERO_DATA = hex\"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000\";\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n FFIInterface ffi;\n\n function setUp() public virtual {\n // Give alice and bob some ETH\n vm.deal(alice, 1 << 16);\n vm.deal(bob, 1 << 16);\n vm.deal(multisig, 1 << 16);\n\n vm.label(alice, \"alice\");\n vm.label(bob, \"bob\");\n vm.label(multisig, \"multisig\");\n\n // Make sure we have a non-zero base fee\n vm.fee(1000000000);\n\n ffi = new FFIInterface();\n }\n\n function emitTransactionDeposited(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) internal {\n emit TransactionDeposited(\n _from,\n _to,\n 0,\n abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data)\n );\n }\n}\n\ncontract L2OutputOracle_Initializer is CommonTest {\n // Test target\n L2OutputOracle oracle;\n L2OutputOracle oracleImpl;\n\n L2ToL1MessagePasser messagePasser =\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER));\n\n // Constructor arguments\n address internal proposer = 0x000000000000000000000000000000000000AbBa;\n address internal owner = 0x000000000000000000000000000000000000ACDC;\n uint256 internal submissionInterval = 1800;\n uint256 internal l2BlockTime = 2;\n uint256 internal startingBlockNumber = 200;\n uint256 internal startingTimestamp = 1000;\n address guardian;\n\n // Test data\n uint256 initL1Time;\n\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n // Advance the evm's time to meet the L2OutputOracle's requirements for proposeL2Output\n function warpToProposeTime(uint256 _nextBlockNumber) public {\n vm.warp(oracle.computeL2Timestamp(_nextBlockNumber) + 1);\n }\n\n function setUp() public virtual override {\n super.setUp();\n guardian = makeAddr(\"guardian\");\n\n // By default the first block has timestamp and number zero, which will cause underflows in the\n // tests, so we'll move forward to these block values.\n initL1Time = startingTimestamp + 1;\n vm.warp(initL1Time);\n vm.roll(startingBlockNumber);\n // Deploy the L2OutputOracle and transfer owernship to the proposer\n oracleImpl = new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: startingTimestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(oracleImpl),\n abi.encodeCall(L2OutputOracle.initialize, (startingBlockNumber, startingTimestamp))\n );\n oracle = L2OutputOracle(address(proxy));\n vm.label(address(oracle), \"L2OutputOracle\");\n\n // Set the L2ToL1MessagePasser at the correct address\n vm.etch(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(new L2ToL1MessagePasser()).code);\n\n vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, \"L2ToL1MessagePasser\");\n }\n}\n\ncontract Portal_Initializer is L2OutputOracle_Initializer {\n // Test target\n OptimismPortal internal opImpl;\n OptimismPortal internal op;\n SystemConfig systemConfig;\n\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n function setUp() public virtual override {\n super.setUp();\n\n ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();\n\n systemConfig = new SystemConfig({\n _owner: address(1),\n _overhead: 0,\n _scalar: 10000,\n _batcherHash: bytes32(0),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(0),\n _config: config\n });\n\n opImpl = new OptimismPortal({\n _l2Oracle: oracle,\n _guardian: guardian,\n _paused: true,\n _config: systemConfig\n });\n\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(opImpl),\n abi.encodeWithSelector(OptimismPortal.initialize.selector, false)\n );\n op = OptimismPortal(payable(address(proxy)));\n vm.label(address(op), \"OptimismPortal\");\n }\n}\n\ncontract Messenger_Initializer is Portal_Initializer {\n AddressManager internal addressManager;\n L1CrossDomainMessenger internal L1Messenger;\n L2CrossDomainMessenger internal L2Messenger =\n L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER);\n\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n\n event SentMessageExtension1(address indexed sender, uint256 value);\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event RelayedMessage(bytes32 indexed msgHash);\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 mint,\n uint256 value,\n uint64 gasLimit,\n bool isCreation,\n bytes data\n );\n\n event WhatHappened(bool success, bytes returndata);\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the address manager\n vm.prank(multisig);\n addressManager = new AddressManager();\n\n // Setup implementation\n L1CrossDomainMessenger L1MessengerImpl = new L1CrossDomainMessenger(op);\n\n // Setup the address manager and proxy\n vm.prank(multisig);\n addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(L1MessengerImpl));\n ResolvedDelegateProxy proxy = new ResolvedDelegateProxy(\n addressManager,\n \"OVM_L1CrossDomainMessenger\"\n );\n L1Messenger = L1CrossDomainMessenger(address(proxy));\n L1Messenger.initialize();\n\n vm.etch(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n address(new L2CrossDomainMessenger(address(L1Messenger))).code\n );\n\n L2Messenger.initialize();\n\n // Label addresses\n vm.label(address(addressManager), \"AddressManager\");\n vm.label(address(L1MessengerImpl), \"L1CrossDomainMessenger_Impl\");\n vm.label(address(L1Messenger), \"L1CrossDomainMessenger_Proxy\");\n vm.label(Predeploys.LEGACY_ERC20_ETH, \"LegacyERC20ETH\");\n vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, \"L2CrossDomainMessenger\");\n\n vm.label(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n \"L1CrossDomainMessenger_aliased\"\n );\n }\n}\n\ncontract Bridge_Initializer is Messenger_Initializer {\n L1StandardBridge L1Bridge;\n L2StandardBridge L2Bridge;\n OptimismMintableERC20Factory L2TokenFactory;\n OptimismMintableERC20Factory L1TokenFactory;\n ERC20 L1Token;\n ERC20 BadL1Token;\n OptimismMintableERC20 L2Token;\n LegacyMintableERC20 LegacyL2Token;\n ERC20 NativeL2Token;\n ERC20 BadL2Token;\n OptimismMintableERC20 RemoteL1Token;\n\n event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes data\n );\n\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFailed(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ETHBridgeInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n function setUp() public virtual override {\n super.setUp();\n\n vm.label(Predeploys.L2_STANDARD_BRIDGE, \"L2StandardBridge\");\n vm.label(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, \"OptimismMintableERC20Factory\");\n\n // Deploy the L1 bridge and initialize it with the address of the\n // L1CrossDomainMessenger\n L1ChugSplashProxy proxy = new L1ChugSplashProxy(multisig);\n vm.mockCall(\n multisig,\n abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector),\n abi.encode(true)\n );\n vm.startPrank(multisig);\n proxy.setCode(address(new L1StandardBridge(payable(address(L1Messenger)))).code);\n vm.clearMockedCalls();\n address L1Bridge_Impl = proxy.getImplementation();\n vm.stopPrank();\n\n L1Bridge = L1StandardBridge(payable(address(proxy)));\n\n vm.label(address(proxy), \"L1StandardBridge_Proxy\");\n vm.label(address(L1Bridge_Impl), \"L1StandardBridge_Impl\");\n\n // Deploy the L2StandardBridge, move it to the correct predeploy\n // address and then initialize it\n L2StandardBridge l2B = new L2StandardBridge(payable(proxy));\n vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(l2B).code);\n L2Bridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE));\n\n // Set up the L2 mintable token factory\n OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory(\n Predeploys.L2_STANDARD_BRIDGE\n );\n vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(factory).code);\n L2TokenFactory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY);\n\n vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code);\n\n L1Token = new ERC20(\"Native L1 Token\", \"L1T\");\n\n LegacyL2Token = new LegacyMintableERC20({\n _l2Bridge: address(L2Bridge),\n _l1Token: address(L1Token),\n _name: string.concat(\"LegacyL2-\", L1Token.name()),\n _symbol: string.concat(\"LegacyL2-\", L1Token.symbol())\n });\n vm.label(address(LegacyL2Token), \"LegacyMintableERC20\");\n\n // Deploy the L2 ERC20 now\n L2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(L1Token),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n BadL2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n NativeL2Token = new ERC20(\"Native L2 Token\", \"L2T\");\n L1TokenFactory = new OptimismMintableERC20Factory(address(L1Bridge));\n\n RemoteL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(NativeL2Token),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n\n BadL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n }\n}\n\ncontract ERC721Bridge_Initializer is Messenger_Initializer {\n L1ERC721Bridge L1Bridge;\n L2ERC721Bridge L2Bridge;\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the L1ERC721Bridge.\n L1Bridge = new L1ERC721Bridge(address(L1Messenger), Predeploys.L2_ERC721_BRIDGE);\n\n // Deploy the implementation for the L2ERC721Bridge and etch it into the predeploy address.\n vm.etch(\n Predeploys.L2_ERC721_BRIDGE,\n address(new L2ERC721Bridge(Predeploys.L2_CROSS_DOMAIN_MESSENGER, address(L1Bridge)))\n .code\n );\n\n // Set up a reference to the L2ERC721Bridge.\n L2Bridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE);\n\n // Label the L1 and L2 bridges.\n vm.label(address(L1Bridge), \"L1ERC721Bridge\");\n vm.label(address(L2Bridge), \"L2ERC721Bridge\");\n }\n}\n\ncontract FFIInterface is Test {\n function getProveWithdrawalTransactionInputs(Types.WithdrawalTransaction memory _tx)\n external\n returns (\n bytes32,\n bytes32,\n bytes32,\n bytes32,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"getProveWithdrawalTransactionInputs\";\n cmds[2] = vm.toString(_tx.nonce);\n cmds[3] = vm.toString(_tx.sender);\n cmds[4] = vm.toString(_tx.target);\n cmds[5] = vm.toString(_tx.value);\n cmds[6] = vm.toString(_tx.gasLimit);\n cmds[7] = vm.toString(_tx.data);\n\n bytes memory result = vm.ffi(cmds);\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = abi.decode(result, (bytes32, bytes32, bytes32, bytes32, bytes[]));\n\n return (stateRoot, storageRoot, outputRoot, withdrawalHash, withdrawalProof);\n }\n\n function hashCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashCrossDomainMessage\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashWithdrawal(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashWithdrawal\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashOutputRootProof(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external returns (bytes32) {\n string[] memory cmds = new string[](6);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashOutputRootProof\";\n cmds[2] = Strings.toHexString(uint256(_version));\n cmds[3] = Strings.toHexString(uint256(_stateRoot));\n cmds[4] = Strings.toHexString(uint256(_messagePasserStorageRoot));\n cmds[5] = Strings.toHexString(uint256(_latestBlockhash));\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashDepositTransaction(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint64 _logIndex\n ) external returns (bytes32) {\n string[] memory cmds = new string[](10);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashDepositTransaction\";\n cmds[2] = \"0x0000000000000000000000000000000000000000000000000000000000000000\";\n cmds[3] = vm.toString(_logIndex);\n cmds[4] = vm.toString(_from);\n cmds[5] = vm.toString(_to);\n cmds[6] = vm.toString(_mint);\n cmds[7] = vm.toString(_value);\n cmds[8] = vm.toString(_gas);\n cmds[9] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function encodeDepositTransaction(Types.UserDepositTransaction calldata txn)\n external\n returns (bytes memory)\n {\n string[] memory cmds = new string[](11);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"encodeDepositTransaction\";\n cmds[2] = vm.toString(txn.from);\n cmds[3] = vm.toString(txn.to);\n cmds[4] = vm.toString(txn.value);\n cmds[5] = vm.toString(txn.mint);\n cmds[6] = vm.toString(txn.gasLimit);\n cmds[7] = vm.toString(txn.isCreation);\n cmds[8] = vm.toString(txn.data);\n cmds[9] = vm.toString(txn.l1BlockHash);\n cmds[10] = vm.toString(txn.logIndex);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function encodeCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes memory) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"encodeCrossDomainMessage\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function decodeVersionedNonce(uint256 nonce) external returns (uint256, uint256) {\n string[] memory cmds = new string[](3);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"decodeVersionedNonce\";\n cmds[2] = vm.toString(nonce);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (uint256, uint256));\n }\n\n function getMerkleTrieFuzzCase(string memory variant)\n external\n returns (\n bytes32,\n bytes memory,\n bytes memory,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](5);\n cmds[0] = \"./test-case-generator/fuzz\";\n cmds[1] = \"-m\";\n cmds[2] = \"trie\";\n cmds[3] = \"-v\";\n cmds[4] = variant;\n\n return abi.decode(vm.ffi(cmds), (bytes32, bytes, bytes, bytes[]));\n }\n}\n\n// Used for testing a future upgrade beyond the current implementations.\n// We include some variables so that we can sanity check accessing storage values after an upgrade.\ncontract NextImpl is Initializable {\n // Initializable occupies the zero-th slot.\n bytes32 slot1;\n bytes32[19] __gap;\n bytes32 slot21;\n bytes32 public constant slot21Init = bytes32(hex\"1337\");\n\n function initialize() public reinitializer(2) {\n // Slot21 is unused by an of our upgradeable contracts.\n // This is used to verify that we can access this value after an upgrade.\n slot21 = slot21Init;\n }\n}\n\ncontract Reverter {\n fallback() external {\n revert();\n }\n}\n\n// Useful for testing reentrancy guards\ncontract CallerCaller {\n event WhatHappened(bool success, bytes returndata);\n\n fallback() external {\n (bool success, bytes memory returndata) = msg.sender.call(msg.data);\n emit WhatHappened(success, returndata);\n assembly {\n switch success\n case 0 {\n revert(add(returndata, 0x20), mload(returndata))\n }\n default {\n return(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n\n// Used for testing the `CrossDomainMessenger`'s per-message reentrancy guard.\ncontract ConfigurableCaller {\n bool doRevert = true;\n address target;\n bytes payload;\n\n event WhatHappened(bool success, bytes returndata);\n\n /**\n * @notice Call the configured target with the configured payload OR revert.\n */\n function call() external {\n if (doRevert) {\n revert(\"ConfigurableCaller: revert\");\n } else {\n (bool success, bytes memory returndata) = address(target).call(payload);\n emit WhatHappened(success, returndata);\n assembly {\n switch success\n case 0 {\n revert(add(returndata, 0x20), mload(returndata))\n }\n default {\n return(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n }\n\n /**\n * @notice Set whether or not to have `call` revert.\n */\n function setDoRevert(bool _doRevert) external {\n doRevert = _doRevert;\n }\n\n /**\n * @notice Set the target for the call made in `call`.\n */\n function setTarget(address _target) external {\n target = _target;\n }\n\n /**\n * @notice Set the payload for the call made in `call`.\n */\n function setPayload(bytes calldata _payload) external {\n payload = _payload;\n }\n\n /**\n * @notice Fallback function that reverts if `doRevert` is true.\n * Otherwise, it does nothing.\n */\n fallback() external {\n if (doRevert) {\n revert(\"ConfigurableCaller: revert\");\n }\n }\n}\n" - }, - "contracts/test/CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, CallerCaller, CommonTest } from \"./CommonTest.t.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\n\n// Libraries\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n// CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2\n// CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract.\ncontract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {\n // Ensure that baseGas passes for the max value of _minGasLimit,\n // this is about 4 Billion.\n function test_baseGas_succeeds() external view {\n L1Messenger.baseGas(hex\"ff\", type(uint32).max);\n }\n\n // Fuzz for other values which might cause a revert in baseGas.\n function testFuzz_baseGas_succeeds(uint32 _minGasLimit) external view {\n L1Messenger.baseGas(hex\"ff\", _minGasLimit);\n }\n\n /**\n * @notice The baseGas function should always return a value greater than\n * or equal to the minimum gas limit value on the OptimismPortal.\n * This guarantees that the messengers will always pass sufficient\n * gas to the OptimismPortal.\n */\n function testFuzz_baseGas_portalMinGasLimit_succeeds(bytes memory _data, uint32 _minGasLimit)\n external\n {\n vm.assume(_data.length <= type(uint64).max);\n uint64 baseGas = L1Messenger.baseGas(_data, _minGasLimit);\n uint64 minGasLimit = op.minimumGasLimit(uint64(_data.length));\n assertTrue(baseGas >= minGasLimit);\n }\n}\n\n/**\n * @title ExternalRelay\n * @notice A mock external contract called via the SafeCall inside\n * the CrossDomainMessenger's `relayMessage` function.\n */\ncontract ExternalRelay is CommonTest {\n address internal op;\n address internal fuzzedSender;\n L1CrossDomainMessenger internal L1Messenger;\n\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n constructor(L1CrossDomainMessenger _l1Messenger, address _op) {\n L1Messenger = _l1Messenger;\n op = _op;\n }\n\n /**\n * @notice Internal helper function to relay a message and perform assertions.\n */\n function _internalRelay(address _innerSender) internal {\n address initialSender = L1Messenger.xDomainMessageSender();\n\n bytes memory callMessage = getCallData();\n\n bytes32 hash = Hashing.hashCrossDomainMessage({\n _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n _sender: _innerSender,\n _target: address(this),\n _value: 0,\n _gasLimit: 0,\n _data: callMessage\n });\n\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n vm.prank(address(op));\n L1Messenger.relayMessage({\n _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n _sender: _innerSender,\n _target: address(this),\n _value: 0,\n _minGasLimit: 0,\n _message: callMessage\n });\n\n assertTrue(L1Messenger.failedMessages(hash));\n assertFalse(L1Messenger.successfulMessages(hash));\n assertEq(initialSender, L1Messenger.xDomainMessageSender());\n }\n\n /**\n * @notice externalCallWithMinGas is called by the CrossDomainMessenger.\n */\n function externalCallWithMinGas() external payable {\n for (uint256 i = 0; i < 10; i++) {\n address _innerSender;\n unchecked {\n _innerSender = address(uint160(uint256(uint160(fuzzedSender)) + i));\n }\n _internalRelay(_innerSender);\n }\n }\n\n /**\n * @notice Helper function to get the callData for an `externalCallWithMinGas\n */\n function getCallData() public pure returns (bytes memory) {\n return abi.encodeWithSelector(ExternalRelay.externalCallWithMinGas.selector);\n }\n\n /**\n * @notice Helper function to set the fuzzed sender\n */\n function setFuzzedSender(address _fuzzedSender) public {\n fuzzedSender = _fuzzedSender;\n }\n}\n\n/**\n * @title CrossDomainMessenger_RelayMessage_Test\n * @notice Fuzz tests re-entrancy into the CrossDomainMessenger relayMessage function.\n */\ncontract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n ExternalRelay public er;\n\n function setUp() public override {\n super.setUp();\n er = new ExternalRelay(L1Messenger, address(op));\n }\n\n /**\n * @dev This test mocks an OptimismPortal call to the L1CrossDomainMessenger via\n * the relayMessage function. The relayMessage function will then use SafeCall's\n * callWithMinGas to call the target with call data packed in the callMessage.\n * For this test, the callWithMinGas will call the mock ExternalRelay test contract\n * defined above, executing the externalCallWithMinGas function which will try to\n * re-enter the CrossDomainMessenger's relayMessage function, resulting in that message\n * being recorded as failed.\n */\n function testFuzz_relayMessageReenter_succeeds(address _sender, uint256 _gasLimit) external {\n vm.assume(_sender != Predeploys.L2_CROSS_DOMAIN_MESSENGER);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n er.setFuzzedSender(_sender);\n address target = address(er);\n bytes memory callMessage = er.getCallData();\n\n vm.expectCall(target, callMessage);\n\n uint64 gasLimit = uint64(bound(_gasLimit, 0, 30_000_000));\n\n bytes32 hash = Hashing.hashCrossDomainMessage({\n _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n _sender: sender,\n _target: target,\n _value: 0,\n _gasLimit: gasLimit,\n _data: callMessage\n });\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n L1Messenger.relayMessage({\n _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n _sender: sender,\n _target: target,\n _value: 0,\n _minGasLimit: gasLimit,\n _message: callMessage\n });\n\n assertTrue(L1Messenger.successfulMessages(hash));\n assertEq(L1Messenger.failedMessages(hash), false);\n\n // Ensures that the `xDomainMsgSender` is set back to `Predeploys.L2_CROSS_DOMAIN_MESSENGER`\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest, Portal_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable } from \"../L2/CrossDomainOwnable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Vm, VmSafe } from \"forge-std/Vm.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract XDomainSetter is CrossDomainOwnable {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable_Test is CommonTest {\n XDomainSetter setter;\n\n function setUp() public override {\n super.setUp();\n setter = new XDomainSetter();\n }\n\n // Check that the revert message is correct\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable: caller is not the owner\");\n setter.set(1);\n }\n\n // Check that making a call can set the value properly\n function test_onlyOwner_succeeds() external {\n assertEq(setter.value(), 0);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(setter.owner()));\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n\ncontract CrossDomainOwnableThroughPortal_Test is Portal_Initializer {\n XDomainSetter setter;\n\n function setUp() public override {\n super.setUp();\n\n vm.prank(alice);\n setter = new XDomainSetter();\n }\n\n function test_depositTransaction_crossDomainOwner_succeeds() external {\n vm.recordLogs();\n\n vm.prank(alice);\n op.depositTransaction({\n _to: address(setter),\n _value: 0,\n _gasLimit: 30_000,\n _isCreation: false,\n _data: abi.encodeWithSelector(XDomainSetter.set.selector, 1)\n });\n\n // Simulate the operation of the `op-node` by parsing data\n // from logs\n VmSafe.Log[] memory logs = vm.getRecordedLogs();\n // Only 1 log emitted\n assertEq(logs.length, 1);\n\n VmSafe.Log memory log = logs[0];\n\n // It is the expected topic\n bytes32 topic = log.topics[0];\n assertEq(topic, keccak256(\"TransactionDeposited(address,address,uint256,bytes)\"));\n\n // from is indexed and the first argument to the event.\n bytes32 _from = log.topics[1];\n address from = Bytes32AddressLib.fromLast20Bytes(_from);\n\n assertEq(AddressAliasHelper.undoL1ToL2Alias(from), alice);\n\n // Make a call from the \"from\" value received from the log.\n // In theory the opaque data could be parsed from the log\n // and passed to a low level call to \"to\", but calling set\n // directly on the setter is good enough.\n vm.prank(from);\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable2.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\nimport { CommonTest, Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable2 } from \"../L2/CrossDomainOwnable2.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract XDomainSetter2 is CrossDomainOwnable2 {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable2_Test is Messenger_Initializer {\n XDomainSetter2 setter;\n\n function setUp() public override {\n super.setUp();\n vm.prank(alice);\n setter = new XDomainSetter2();\n }\n\n function test_onlyOwner_notMessenger_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the messenger\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n // set the xDomainMsgSender storage slot\n bytes32 key = bytes32(uint256(204));\n bytes32 value = Bytes32AddressLib.fillLast12Bytes(address(alice));\n vm.store(address(L2Messenger), key, value);\n\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the owner\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner2_reverts() external {\n uint240 nonce = 0;\n address sender = bob;\n address target = address(setter);\n uint256 value = 0;\n uint256 minGasLimit = 0;\n bytes memory message = abi.encodeWithSelector(XDomainSetter2.set.selector, 1);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n // It should be a failed message. The revert is caught,\n // so we cannot expectRevert here.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n assertEq(setter.value(), 0);\n }\n\n function test_onlyOwner_succeeds() external {\n address owner = setter.owner();\n\n // Simulate the L2 execution where the call is coming from\n // the L1CrossDomainMessenger\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(1, 1),\n owner,\n address(setter),\n 0,\n 0,\n abi.encodeWithSelector(XDomainSetter2.set.selector, 2)\n );\n\n assertEq(setter.value(), 2);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable3.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\nimport { CommonTest, Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable3 } from \"../L2/CrossDomainOwnable3.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract XDomainSetter3 is CrossDomainOwnable3 {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable3_Test is Messenger_Initializer {\n XDomainSetter3 setter;\n\n /**\n * @notice OpenZeppelin Ownable.sol transferOwnership event\n */\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @notice CrossDomainOwnable3.sol transferOwnership event\n */\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner,\n bool isLocal\n );\n\n function setUp() public override {\n super.setUp();\n vm.prank(alice);\n setter = new XDomainSetter3();\n }\n\n function test_constructor_succeeds() public {\n assertEq(setter.owner(), alice);\n assertEq(setter.isLocal(), true);\n }\n\n function test_localOnlyOwner_notOwner_reverts() public {\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.set(1);\n }\n\n function test_transferOwnership_notOwner_reverts() public {\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.transferOwnership({ _owner: bob, _isLocal: true });\n }\n\n function test_crossDomainOnlyOwner_notOwner_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n // set the xDomainMsgSender storage slot\n bytes32 key = bytes32(uint256(204));\n bytes32 value = Bytes32AddressLib.fillLast12Bytes(bob);\n vm.store(address(L2Messenger), key, value);\n\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.set(1);\n }\n\n function test_crossDomainOnlyOwner_notOwner2_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n assertEq(setter.isLocal(), false);\n\n uint240 nonce = 0;\n address sender = bob;\n address target = address(setter);\n uint256 value = 0;\n uint256 minGasLimit = 0;\n bytes memory message = abi.encodeWithSelector(XDomainSetter3.set.selector, 1);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n // It should be a failed message. The revert is caught,\n // so we cannot expectRevert here.\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit FailedRelayedMessage(hash);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n assertEq(setter.value(), 0);\n }\n\n function test_crossDomainOnlyOwner_notMessenger_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the messenger\");\n setter.set(1);\n }\n\n function test_transferOwnership_zeroAddress_reverts() public {\n vm.prank(setter.owner());\n vm.expectRevert(\"CrossDomainOwnable3: new owner is the zero address\");\n setter.transferOwnership({ _owner: address(0), _isLocal: true });\n }\n\n function test_transferOwnership_noLocalZeroAddress_reverts() public {\n vm.prank(setter.owner());\n vm.expectRevert(\"Ownable: new owner is the zero address\");\n setter.transferOwnership(address(0));\n }\n\n function test_localOnlyOwner_succeeds() public {\n assertEq(setter.isLocal(), true);\n vm.prank(setter.owner());\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n\n function test_localTransferOwnership_succeeds() public {\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n emit OwnershipTransferred(alice, bob, true);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: bob, _isLocal: true });\n\n assertEq(setter.isLocal(), true);\n\n vm.prank(bob);\n setter.set(2);\n assertEq(setter.value(), 2);\n }\n\n /**\n * @notice The existing transferOwnership(address) method\n * still exists on the contract\n */\n function test_transferOwnershipNoLocal_succeeds() public {\n bool isLocal = setter.isLocal();\n\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n\n vm.prank(setter.owner());\n setter.transferOwnership(bob);\n\n // isLocal has not changed\n assertEq(setter.isLocal(), isLocal);\n\n vm.prank(bob);\n setter.set(2);\n assertEq(setter.value(), 2);\n }\n\n function test_crossDomainTransferOwnership_succeeds() public {\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n emit OwnershipTransferred(alice, bob, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: bob, _isLocal: false });\n\n assertEq(setter.isLocal(), false);\n\n // Simulate the L2 execution where the call is coming from\n // the L1CrossDomainMessenger\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(1, 1),\n bob,\n address(setter),\n 0,\n 0,\n abi.encodeWithSelector(XDomainSetter3.set.selector, 2)\n );\n\n assertEq(setter.value(), 2);\n }\n}\n" - }, - "contracts/test/DeployerWhitelist.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { DeployerWhitelist } from \"../legacy/DeployerWhitelist.sol\";\n\ncontract DeployerWhitelist_Test is CommonTest {\n DeployerWhitelist list;\n\n function setUp() public virtual override {\n list = new DeployerWhitelist();\n }\n\n // The owner should be address(0)\n function test_owner_succeeds() external {\n assertEq(list.owner(), address(0));\n }\n\n // The storage slot for the owner must be the same\n function test_storageSlots_succeeds() external {\n vm.prank(list.owner());\n list.setOwner(address(1));\n\n assertEq(bytes32(uint256(1)), vm.load(address(list), bytes32(uint256(0))));\n }\n}\n" - }, - "contracts/test/DisputeGameFactory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport \"../libraries/DisputeTypes.sol\";\nimport \"../libraries/DisputeErrors.sol\";\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { DisputeGameFactory } from \"../dispute/DisputeGameFactory.sol\";\nimport { IDisputeGame } from \"../dispute/IDisputeGame.sol\";\n\ncontract DisputeGameFactory_Test is Test {\n DisputeGameFactory factory;\n FakeClone fakeClone;\n\n event DisputeGameCreated(\n address indexed disputeProxy,\n GameType indexed gameType,\n Claim indexed rootClaim\n );\n\n event ImplementationSet(address indexed impl, GameType indexed gameType);\n\n function setUp() public {\n factory = new DisputeGameFactory(address(this));\n fakeClone = new FakeClone();\n }\n\n /**\n * @dev Tests that the `create` function succeeds when creating a new dispute game\n * with a `GameType` that has an implementation set.\n */\n function testFuzz_create_succeeds(\n uint8 gameType,\n Claim rootClaim,\n bytes calldata extraData\n ) public {\n // Ensure that the `gameType` is within the bounds of the `GameType` enum's possible values.\n GameType gt = GameType(uint8(bound(gameType, 0, 2)));\n\n // Set all three implementations to the same `FakeClone` contract.\n for (uint8 i; i < 3; i++) {\n factory.setImplementation(GameType(i), IDisputeGame(address(fakeClone)));\n }\n\n vm.expectEmit(false, true, true, false);\n emit DisputeGameCreated(address(0), gt, rootClaim);\n IDisputeGame proxy = factory.create(gt, rootClaim, extraData);\n\n // Ensure that the dispute game was assigned to the `disputeGames` mapping.\n assertEq(address(factory.games(gt, rootClaim, extraData)), address(proxy));\n }\n\n /**\n * @dev Tests that the `create` function reverts when there is no implementation\n * set for the given `GameType`.\n */\n function testFuzz_create_noImpl_reverts(\n uint8 gameType,\n Claim rootClaim,\n bytes calldata extraData\n ) public {\n // Ensure that the `gameType` is within the bounds of the `GameType` enum's possible values.\n GameType gt = GameType(uint8(bound(gameType, 0, 2)));\n\n vm.expectRevert(abi.encodeWithSelector(NoImplementation.selector, gt));\n factory.create(gt, rootClaim, extraData);\n }\n\n /**\n * @dev Tests that the `create` function reverts when there exists a dispute game with the same UUID.\n */\n function testFuzz_create_sameUUID_reverts(\n uint8 gameType,\n Claim rootClaim,\n bytes calldata extraData\n ) public {\n // Ensure that the `gameType` is within the bounds of the `GameType` enum's possible values.\n GameType gt = GameType(uint8(bound(gameType, 0, 2)));\n\n // Set all three implementations to the same `FakeClone` contract.\n for (uint8 i; i < 3; i++) {\n factory.setImplementation(GameType(i), IDisputeGame(address(fakeClone)));\n }\n\n // Create our first dispute game - this should succeed.\n vm.expectEmit(false, true, true, false);\n emit DisputeGameCreated(address(0), gt, rootClaim);\n IDisputeGame proxy = factory.create(gt, rootClaim, extraData);\n\n // Ensure that the dispute game was assigned to the `disputeGames` mapping.\n assertEq(address(factory.games(gt, rootClaim, extraData)), address(proxy));\n\n // Ensure that the `create` function reverts when called with parameters that would result in the same UUID.\n vm.expectRevert(\n abi.encodeWithSelector(\n GameAlreadyExists.selector,\n factory.getGameUUID(gt, rootClaim, extraData)\n )\n );\n factory.create(gt, rootClaim, extraData);\n }\n\n /**\n * @dev Tests that the `setImplementation` function properly sets the implementation for a given `GameType`.\n */\n function test_setImplementation_succeeds() public {\n // There should be no implementation for the `GameType.FAULT` enum value, it has not been set.\n assertEq(address(factory.gameImpls(GameType.FAULT)), address(0));\n\n vm.expectEmit(true, true, true, true, address(factory));\n emit ImplementationSet(address(1), GameType.FAULT);\n\n // Set the implementation for the `GameType.FAULT` enum value.\n factory.setImplementation(GameType.FAULT, IDisputeGame(address(1)));\n\n // Ensure that the implementation for the `GameType.FAULT` enum value is set.\n assertEq(address(factory.gameImpls(GameType.FAULT)), address(1));\n }\n\n /**\n * @dev Tests that the `setImplementation` function reverts when called by a non-owner.\n */\n function test_setImplementation_notOwner_reverts() public {\n // Ensure that the `setImplementation` function reverts when called by a non-owner.\n vm.prank(address(0));\n vm.expectRevert(\"Ownable: caller is not the owner\");\n factory.setImplementation(GameType.FAULT, IDisputeGame(address(1)));\n }\n\n /**\n * @dev Tests that the `getGameUUID` function returns the correct hash when comparing\n * against the keccak256 hash of the abi-encoded parameters.\n */\n function testDiff_getGameUUID_succeeds(\n uint8 gameType,\n Claim rootClaim,\n bytes calldata extraData\n ) public {\n // Ensure that the `gameType` is within the bounds of the `GameType` enum's possible values.\n GameType gt = GameType(uint8(bound(gameType, 0, 2)));\n\n assertEq(\n Hash.unwrap(factory.getGameUUID(gt, rootClaim, extraData)),\n keccak256(abi.encode(gt, rootClaim, extraData))\n );\n }\n\n /**\n * @dev Tests that the `owner` function returns the correct address after deployment.\n */\n function test_owner_succeeds() public {\n assertEq(factory.owner(), address(this));\n }\n\n /**\n * @dev Tests that the `transferOwnership` function succeeds when called by the owner.\n */\n function test_transferOwnership_succeeds() public {\n factory.transferOwnership(address(1));\n assertEq(factory.owner(), address(1));\n }\n\n /**\n * @dev Tests that the `transferOwnership` function reverts when called by a non-owner.\n */\n function test_transferOwnership_notOwner_reverts() public {\n vm.prank(address(0));\n vm.expectRevert(\"Ownable: caller is not the owner\");\n factory.transferOwnership(address(1));\n }\n}\n\n/**\n * @dev A fake clone used for testing the `DisputeGameFactory` contract's `create` function.\n */\ncontract FakeClone {\n function initialize() external {\n // noop\n }\n}\n" - }, - "contracts/test/Encoding.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { LegacyCrossDomainUtils } from \"../libraries/LegacyCrossDomainUtils.sol\";\n\ncontract Encoding_Test is CommonTest {\n function testFuzz_nonceVersioning_succeeds(uint240 _nonce, uint16 _version) external {\n (uint240 nonce, uint16 version) = Encoding.decodeVersionedNonce(\n Encoding.encodeVersionedNonce(_nonce, _version)\n );\n assertEq(version, _version);\n assertEq(nonce, _nonce);\n }\n\n function testDiff_decodeVersionedNonce_succeeds(uint240 _nonce, uint16 _version) external {\n uint256 nonce = uint256(Encoding.encodeVersionedNonce(_nonce, _version));\n (uint256 decodedNonce, uint256 decodedVersion) = ffi.decodeVersionedNonce(nonce);\n\n assertEq(_version, uint16(decodedVersion));\n\n assertEq(_nonce, uint240(decodedNonce));\n }\n\n function testDiff_encodeCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint8 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint8 version = _version % 2;\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes memory encoding = Encoding.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n bytes memory _encoding = ffi.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n assertEq(encoding, _encoding);\n }\n\n function testFuzz_encodeCrossDomainMessageV0_matchesLegacy_succeeds(\n uint240 _nonce,\n address _sender,\n address _target,\n bytes memory _data\n ) external {\n uint8 version = 0;\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes memory legacyEncoding = LegacyCrossDomainUtils.encodeXDomainCalldata(\n _target,\n _sender,\n _data,\n nonce\n );\n\n bytes memory bedrockEncoding = Encoding.encodeCrossDomainMessageV0(\n _target,\n _sender,\n _data,\n nonce\n );\n\n assertEq(legacyEncoding, bedrockEncoding);\n }\n\n function testDiff_encodeDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bool isCreate,\n bytes memory _data,\n uint64 _logIndex\n ) external {\n Types.UserDepositTransaction memory t = Types.UserDepositTransaction(\n _from,\n _to,\n isCreate,\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n );\n\n bytes memory txn = Encoding.encodeDepositTransaction(t);\n bytes memory _txn = ffi.encodeDepositTransaction(t);\n\n assertEq(txn, _txn);\n }\n}\n" - }, - "contracts/test/FeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { L1FeeVault } from \"../L2/L1FeeVault.sol\";\nimport { BaseFeeVault } from \"../L2/BaseFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n// Test the implementations of the FeeVault\ncontract FeeVault_Test is Bridge_Initializer {\n BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT));\n L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT));\n\n address constant recipient = address(0x10000);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.BASE_FEE_VAULT, address(new BaseFeeVault(recipient)).code);\n vm.etch(Predeploys.L1_FEE_VAULT, address(new L1FeeVault(recipient)).code);\n\n vm.label(Predeploys.BASE_FEE_VAULT, \"BaseFeeVault\");\n vm.label(Predeploys.L1_FEE_VAULT, \"L1FeeVault\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(baseFeeVault.RECIPIENT(), recipient);\n assertEq(l1FeeVault.RECIPIENT(), recipient);\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n}\n" - }, - "contracts/test/GasPriceOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GasPriceOracle } from \"../L2/GasPriceOracle.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract GasPriceOracle_Test is CommonTest {\n event OverheadUpdated(uint256);\n event ScalarUpdated(uint256);\n event DecimalsUpdated(uint256);\n\n GasPriceOracle gasOracle;\n L1Block l1Block;\n address depositor;\n\n // set the initial L1 context values\n uint64 constant number = 10;\n uint64 constant timestamp = 11;\n uint256 constant basefee = 100;\n bytes32 constant hash = bytes32(uint256(64));\n uint64 constant sequenceNumber = 0;\n bytes32 constant batcherHash = bytes32(uint256(777));\n uint256 constant l1FeeOverhead = 310;\n uint256 constant l1FeeScalar = 10;\n\n function setUp() public virtual override {\n super.setUp();\n // place the L1Block contract at the predeploy address\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n\n l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n depositor = l1Block.DEPOSITOR_ACCOUNT();\n\n // We are not setting the gas oracle at its predeploy\n // address for simplicity purposes. Nothing in this test\n // requires it to be at a particular address\n gasOracle = new GasPriceOracle();\n\n vm.prank(depositor);\n l1Block.setL1BlockValues({\n _number: number,\n _timestamp: timestamp,\n _basefee: basefee,\n _hash: hash,\n _sequenceNumber: sequenceNumber,\n _batcherHash: batcherHash,\n _l1FeeOverhead: l1FeeOverhead,\n _l1FeeScalar: l1FeeScalar\n });\n }\n\n function test_l1BaseFee_succeeds() external {\n assertEq(gasOracle.l1BaseFee(), basefee);\n }\n\n function test_gasPrice_succeeds() external {\n vm.fee(100);\n uint256 gasPrice = gasOracle.gasPrice();\n assertEq(gasPrice, 100);\n }\n\n function test_baseFee_succeeds() external {\n vm.fee(64);\n uint256 gasPrice = gasOracle.baseFee();\n assertEq(gasPrice, 64);\n }\n\n function test_scalar_succeeds() external {\n assertEq(gasOracle.scalar(), l1FeeScalar);\n }\n\n function test_overhead_succeeds() external {\n assertEq(gasOracle.overhead(), l1FeeOverhead);\n }\n\n function test_decimals_succeeds() external {\n assertEq(gasOracle.decimals(), 6);\n assertEq(gasOracle.DECIMALS(), 6);\n }\n\n // Removed in bedrock\n function test_setGasPrice_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setGasPrice(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n\n // Removed in bedrock\n function test_setL1BaseFee_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setL1BaseFee(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n}\n" - }, - "contracts/test/GovernanceToken.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract GovernanceToken_Test is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n\n function setUp() public virtual override {\n super.setUp();\n vm.prank(owner);\n gov = new GovernanceToken();\n }\n\n function test_constructor_succeeds() external {\n assertEq(gov.owner(), owner);\n assertEq(gov.name(), \"Optimism\");\n assertEq(gov.symbol(), \"OP\");\n assertEq(gov.decimals(), 18);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_mint_fromOwner_succeeds() external {\n // Mint 100 tokens.\n vm.prank(owner);\n gov.mint(owner, 100);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 100);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_mint_fromNotOwner_reverts() external {\n // Mint 100 tokens as rando.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n gov.mint(owner, 100);\n\n // Balance does not update.\n assertEq(gov.balanceOf(owner), 0);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_burn_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando burns their tokens.\n vm.prank(rando);\n gov.burn(50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_burnFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to burn 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner burns 50 tokens from rando.\n vm.prank(owner);\n gov.burnFrom(rando, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_transfer_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando transfers 50 tokens to owner.\n vm.prank(rando);\n gov.transfer(owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_approve_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n\n function test_transferFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner transfers 50 tokens from rando to owner.\n vm.prank(owner);\n gov.transferFrom(rando, owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_increaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Rando increases allowance by 50 tokens.\n vm.prank(rando);\n gov.increaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 100);\n }\n\n function test_decreaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 100 tokens.\n vm.prank(rando);\n gov.approve(owner, 100);\n\n // Rando decreases allowance by 50 tokens.\n vm.prank(rando);\n gov.decreaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n}\n" - }, - "contracts/test/Hashing.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { LegacyCrossDomainUtils } from \"../libraries/LegacyCrossDomainUtils.sol\";\n\ncontract Hashing_hashDepositSource_Test is CommonTest {\n /**\n * @notice Tests that hashDepositSource returns the correct hash in a simple case.\n */\n function test_hashDepositSource_succeeds() external {\n assertEq(\n Hashing.hashDepositSource(\n 0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959,\n 0x1\n ),\n 0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc\n );\n }\n}\n\ncontract Hashing_hashCrossDomainMessage_Test is CommonTest {\n /**\n * @notice Tests that hashCrossDomainMessage returns the correct hash in a simple case.\n */\n function testDiff_hashCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint16 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n // Ensure the version is valid.\n uint16 version = uint16(bound(uint256(_version), 0, 1));\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n assertEq(\n Hashing.hashCrossDomainMessage(nonce, _sender, _target, _value, _gasLimit, _data),\n ffi.hashCrossDomainMessage(nonce, _sender, _target, _value, _gasLimit, _data)\n );\n }\n\n /**\n * @notice Tests that hashCrossDomainMessageV0 matches the hash of the legacy encoding.\n */\n function testFuzz_hashCrossDomainMessageV0_matchesLegacy_succeeds(\n address _target,\n address _sender,\n bytes memory _message,\n uint256 _messageNonce\n ) external {\n assertEq(\n keccak256(\n LegacyCrossDomainUtils.encodeXDomainCalldata(\n _target,\n _sender,\n _message,\n _messageNonce\n )\n ),\n Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _messageNonce)\n );\n }\n}\n\ncontract Hashing_hashWithdrawal_Test is CommonTest {\n /**\n * @notice Tests that hashWithdrawal returns the correct hash in a simple case.\n */\n function testDiff_hashWithdrawal_succeeds(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n assertEq(\n Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(_nonce, _sender, _target, _value, _gasLimit, _data)\n ),\n ffi.hashWithdrawal(_nonce, _sender, _target, _value, _gasLimit, _data)\n );\n }\n}\n\ncontract Hashing_hashOutputRootProof_Test is CommonTest {\n /**\n * @notice Tests that hashOutputRootProof returns the correct hash in a simple case.\n */\n function testDiff_hashOutputRootProof_succeeds(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external {\n assertEq(\n Hashing.hashOutputRootProof(\n Types.OutputRootProof({\n version: _version,\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _messagePasserStorageRoot,\n latestBlockhash: _latestBlockhash\n })\n ),\n ffi.hashOutputRootProof(\n _version,\n _stateRoot,\n _messagePasserStorageRoot,\n _latestBlockhash\n )\n );\n }\n}\n\ncontract Hashing_hashDepositTransaction_Test is CommonTest {\n /**\n * @notice Tests that hashDepositTransaction returns the correct hash in a simple case.\n */\n function testDiff_hashDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint64 _logIndex\n ) external {\n assertEq(\n Hashing.hashDepositTransaction(\n Types.UserDepositTransaction(\n _from,\n _to,\n false, // isCreate\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n )\n ),\n ffi.hashDepositTransaction(_from, _to, _mint, _value, _gas, _data, _logIndex)\n );\n }\n}\n" - }, - "contracts/test/L1Block.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\ncontract L1BlockTest is CommonTest {\n L1Block lb;\n address depositor;\n bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1));\n\n function setUp() public virtual override {\n super.setUp();\n lb = new L1Block();\n depositor = lb.DEPOSITOR_ACCOUNT();\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: uint64(1),\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: NON_ZERO_HASH,\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(0),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function testFuzz_updatesValues_succeeds(\n uint64 n,\n uint64 t,\n uint256 b,\n bytes32 h,\n uint64 s,\n bytes32 bt,\n uint256 fo,\n uint256 fs\n ) external {\n vm.prank(depositor);\n lb.setL1BlockValues(n, t, b, h, s, bt, fo, fs);\n assertEq(lb.number(), n);\n assertEq(lb.timestamp(), t);\n assertEq(lb.basefee(), b);\n assertEq(lb.hash(), h);\n assertEq(lb.sequenceNumber(), s);\n assertEq(lb.batcherHash(), bt);\n assertEq(lb.l1FeeOverhead(), fo);\n assertEq(lb.l1FeeScalar(), fs);\n }\n\n function test_number_succeeds() external {\n assertEq(lb.number(), uint64(1));\n }\n\n function test_timestamp_succeeds() external {\n assertEq(lb.timestamp(), uint64(2));\n }\n\n function test_basefee_succeeds() external {\n assertEq(lb.basefee(), 3);\n }\n\n function test_hash_succeeds() external {\n assertEq(lb.hash(), NON_ZERO_HASH);\n }\n\n function test_sequenceNumber_succeeds() external {\n assertEq(lb.sequenceNumber(), uint64(4));\n }\n\n function test_updateValues_succeeds() external {\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: type(uint64).max,\n _timestamp: type(uint64).max,\n _basefee: type(uint256).max,\n _hash: keccak256(abi.encode(1)),\n _sequenceNumber: type(uint64).max,\n _batcherHash: bytes32(type(uint256).max),\n _l1FeeOverhead: type(uint256).max,\n _l1FeeScalar: type(uint256).max\n });\n }\n}\n" - }, - "contracts/test/L1BlockNumber.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { L1BlockNumber } from \"../legacy/L1BlockNumber.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract L1BlockNumberTest is Test {\n L1Block lb;\n L1BlockNumber bn;\n\n uint64 constant number = 99;\n\n function setUp() external {\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n lb = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n bn = new L1BlockNumber();\n vm.prank(lb.DEPOSITOR_ACCOUNT());\n\n lb.setL1BlockValues({\n _number: number,\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: bytes32(uint256(10)),\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(uint256(0)),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function test_getL1BlockNumber_succeeds() external {\n assertEq(bn.getL1BlockNumber(), number);\n }\n\n function test_fallback_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n\n function test_receive_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call{ value: 1 }(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n}\n" - }, - "contracts/test/L1CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Messenger_Initializer, Reverter, ConfigurableCaller } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle_Initializer } from \"./L2OutputOracle.t.sol\";\n\n/* Libraries */\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n/* Target contract dependencies */\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/* Target contract */\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\n\ncontract L1CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n // the version is encoded in the nonce\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L1Messenger.messageNonce());\n assertEq(version, L1Messenger.MESSAGE_VERSION());\n }\n\n // sendMessage: should be able to send a single message\n // TODO: this same test needs to be done with the legacy message type\n // by setting the message version to 0\n function test_sendMessage_succeeds() external {\n // deposit transaction on the optimism portal should be called\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n )\n );\n\n // TransactionDeposited event\n vm.expectEmit(true, true, true, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n );\n\n // SentMessage event\n vm.expectEmit(true, true, true, true);\n emit SentMessage(recipient, alice, hex\"ff\", L1Messenger.messageNonce(), 100);\n\n // SentMessageExtension1 event\n vm.expectEmit(true, true, true, true);\n emit SentMessageExtension1(alice, 0);\n\n vm.prank(alice);\n L1Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n // sendMessage: should be able to send the same message twice\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L1Messenger.messageNonce());\n }\n\n function test_xDomainSender_notSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(address(op));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 2 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n // relayMessage: should send a successful call to the target contract\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.expectCall(target, hex\"1111\");\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L1Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n // set the target to be the OptimismPortal\n address target = address(op);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.prank(address(op));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n\n vm.store(address(op), 0, bytes32(abi.encode(sender)));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: should revert if eth is sent from a contract other than the standard bridge\n function test_replayMessage_withValue_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.expectRevert(\n \"CrossDomainMessenger: value must be zero unless message is from a system address\"\n );\n L1Messenger.relayMessage{ value: 100 }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n vm.expectCall(target, hex\"1111\");\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n function test_relayMessage_legacy_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyOldReplay_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Mark legacy message as already relayed.\n uint256 successfulMessagesSlot = 203;\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(target, sender, hex\"1111\", 0);\n bytes32 slot = keccak256(abi.encode(oldHash, successfulMessagesSlot));\n vm.store(address(L1Messenger), slot, bytes32(uint256(1)));\n\n // Expect revert.\n vm.expectRevert(\"CrossDomainMessenger: legacy withdrawal already relayed\");\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was not relayed.\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyRetryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect FailedRelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n function test_relayMessage_legacyRetryAfterSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message has already been relayed\");\n\n // Retry the message again.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n}\n" - }, - "contracts/test/L1ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.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\ncontract L1ERC721Bridge_Test is Messenger_Initializer {\n TestERC721 internal localToken;\n TestERC721 internal remoteToken;\n L1ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L1ERC721Bridge(address(L1Messenger), otherBridge);\n localToken = new TestERC721();\n remoteToken = new TestERC721();\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L1ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L1Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L1Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L1ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L1ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notEscrowed_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n" - }, - "contracts/test/L1StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\n\ncontract L1StandardBridge_Getter_Test is Bridge_Initializer {\n function test_getters_succeeds() external {\n assert(L1Bridge.l2TokenBridge() == address(L2Bridge));\n assert(L1Bridge.OTHER_BRIDGE() == L2Bridge);\n assert(L1Bridge.messenger() == L1Messenger);\n assert(L1Bridge.MESSENGER() == L1Messenger);\n assertEq(L1Bridge.version(), \"1.1.0\");\n }\n}\n\ncontract L1StandardBridge_Initialize_Test is Bridge_Initializer {\n function test_initialize_succeeds() external {\n assertEq(address(L1Bridge.messenger()), address(L1Messenger));\n\n assertEq(address(L1Bridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE);\n\n assertEq(address(L2Bridge), Predeploys.L2_STANDARD_BRIDGE);\n }\n}\n\ncontract L1StandardBridge_Initialize_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_Receive_Test is Bridge_Initializer {\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(op).balance, 0);\n\n // The legacy event must be emitted for backwards compatibility\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 100,\n hex\"\"\n ),\n 200_000\n )\n );\n\n vm.prank(alice, alice);\n (bool success, ) = address(L1Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(op).balance, 100);\n }\n}\n\ncontract L1StandardBridge_Receive_TestFail {}\n\ncontract PreBridgeETH is Bridge_Initializer {\n function _preBridgeETH(bool isLegacy) internal {\n assertEq(address(op).balance, 0);\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 500,\n hex\"dead\"\n );\n\n if (isLegacy) {\n vm.expectCall(\n address(L1Bridge),\n 500,\n abi.encodeWithSelector(L1Bridge.depositETH.selector, 50000, hex\"dead\")\n );\n } else {\n vm.expectCall(\n address(L1Bridge),\n 500,\n abi.encodeWithSelector(L1Bridge.bridgeETH.selector, 50000, hex\"dead\")\n );\n }\n vm.expectCall(\n address(L1Messenger),\n 500,\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 50000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 500,\n 50000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 50000);\n vm.expectCall(\n address(op),\n 500,\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 500,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(500),\n uint256(500),\n baseGas,\n false,\n innerMessage\n );\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, alice, 500, hex\"dead\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, alice, 500, hex\"dead\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 50000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 500);\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L1StandardBridge_DepositETH_Test is PreBridgeETH {\n // depositETH\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_depositETH_succeeds() external {\n _preBridgeETH({ isLegacy: true });\n L1Bridge.depositETH{ value: 500 }(50000, hex\"dead\");\n assertEq(address(op).balance, 500);\n }\n}\n\ncontract L1StandardBridge_BridgeETH_Test is PreBridgeETH {\n // BridgeETH\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_bridgeETH_succeeds() external {\n _preBridgeETH({ isLegacy: false });\n L1Bridge.bridgeETH{ value: 500 }(50000, hex\"dead\");\n assertEq(address(op).balance, 500);\n }\n}\n\ncontract L1StandardBridge_DepositETH_TestFail is Bridge_Initializer {\n function test_depositETH_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, address(L1Token).code);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice);\n L1Bridge.depositETH{ value: 1 }(300, hex\"\");\n }\n}\n\ncontract PreBridgeETHTo is Bridge_Initializer {\n function _preBridgeETHTo(bool isLegacy) internal {\n assertEq(address(op).balance, 0);\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n if (isLegacy) {\n vm.expectCall(\n address(L1Bridge),\n 600,\n abi.encodeWithSelector(L1Bridge.depositETHTo.selector, bob, 60000, hex\"dead\")\n );\n } else {\n vm.expectCall(\n address(L1Bridge),\n 600,\n abi.encodeWithSelector(L1Bridge.bridgeETHTo.selector, bob, 60000, hex\"dead\")\n );\n }\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n bob,\n 600,\n hex\"dead\"\n );\n\n // the L1 bridge should call\n // L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 60000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 600,\n 60000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 60000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 600,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(600),\n uint256(600),\n baseGas,\n false,\n innerMessage\n );\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, bob, 600, hex\"dead\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, bob, 600, hex\"dead\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 60000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 600);\n\n // deposit eth to bob\n vm.prank(alice, alice);\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_Test is PreBridgeETHTo {\n // depositETHTo\n // - emits ETHDepositInitiated\n // - calls optimismPortal.depositTransaction\n // - EOA or contract can call\n // - ETH ends up in the optimismPortal\n function test_depositETHTo_succeeds() external {\n _preBridgeETHTo({ isLegacy: true });\n L1Bridge.depositETHTo{ value: 600 }(bob, 60000, hex\"dead\");\n assertEq(address(op).balance, 600);\n }\n}\n\ncontract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo {\n // BridgeETHTo\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_bridgeETHTo_succeeds() external {\n _preBridgeETHTo({ isLegacy: false });\n L1Bridge.bridgeETHTo{ value: 600 }(bob, 60000, hex\"dead\");\n assertEq(address(op).balance, 600);\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_DepositERC20_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // depositERC20\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - only callable by EOA\n function test_depositERC20_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n // Deal Alice's ERC20 State\n deal(address(L1Token), alice, 100000, true);\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n // The L1Bridge should transfer alice's tokens to itself\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 100)\n );\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L2Token),\n address(L1Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n // the L1 bridge should call L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 10000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 0,\n 10000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 10000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 0,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(0),\n uint256(0),\n baseGas,\n false,\n innerMessage\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 0);\n\n vm.prank(alice);\n L1Bridge.depositERC20(address(L1Token), address(L2Token), 100, 10000, hex\"\");\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n }\n}\n\ncontract L1StandardBridge_DepositERC20_TestFail is Bridge_Initializer {\n function test_depositERC20_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, hex\"ffff\");\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice, alice);\n L1Bridge.depositERC20(address(0), address(0), 100, 100, hex\"\");\n }\n}\n\ncontract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer {\n // depositERC20To\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - callable by a contract\n function test_depositERC20To_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L2Token),\n address(L1Token),\n alice,\n bob,\n 1000,\n hex\"\"\n );\n\n // the L1 bridge should call L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 10000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 0,\n 10000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 10000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 0,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(0),\n uint256(0),\n baseGas,\n false,\n innerMessage\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex\"\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 0);\n\n deal(address(L1Token), alice, 100000, true);\n\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 1000)\n );\n\n vm.prank(alice);\n L1Bridge.depositERC20To(address(L1Token), address(L2Token), bob, 1000, 10000, hex\"\");\n\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 1000);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeETHWithdrawal\n // - emits ETHWithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeETHWithdrawal_succeeds() external {\n uint256 aliceBalance = alice.balance;\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHWithdrawalFinalized(alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n vm.expectCall(alice, hex\"\");\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n // ensure that the messenger has ETH to call with\n vm.deal(address(L1Bridge.messenger()), 100);\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n\n assertEq(address(L1Bridge.messenger()).balance, 0);\n assertEq(aliceBalance + 100, alice.balance);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeERC20Withdrawal\n // - updates bridge.deposits\n // - emits ERC20WithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeERC20Withdrawal_succeeds() external {\n deal(address(L1Token), address(L1Bridge), 100, true);\n\n uint256 slot = stdstore\n .target(address(L1Bridge))\n .sig(\"deposits(address,address)\")\n .with_key(address(L1Token))\n .with_key(address(L2Token))\n .find();\n\n // Give the L1 bridge some ERC20 tokens\n vm.store(address(L1Bridge), bytes32(slot), bytes32(uint256(100)));\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20WithdrawalFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transfer.selector, alice, 100)\n );\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n assertEq(L1Token.balanceOf(address(L1Bridge)), 0);\n assertEq(L1Token.balanceOf(address(alice)), 100);\n }\n}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer {\n function test_finalizeERC20Withdrawal_notMessenger_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(28));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n\n function test_finalizeERC20Withdrawal_notOtherBridge_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(address(0)))\n );\n vm.prank(address(L1Bridge.messenger()));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n}\n\ncontract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {\n function test_finalizeBridgeETH_succeeds() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n\ncontract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer {\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L1Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L1Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, ConfigurableCaller } from \"./CommonTest.t.sol\";\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L2Messenger.messageNonce());\n assertEq(version, L2Messenger.MESSAGE_VERSION());\n }\n\n function test_sendMessage_succeeds() external {\n bytes memory xDomainCallData = Encoding.encodeCrossDomainMessage(\n L2Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n );\n vm.expectCall(\n address(messagePasser),\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData\n )\n );\n\n // MessagePassed event\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(L2Messenger),\n address(L1Messenger),\n 0,\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData,\n Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messagePasser.messageNonce(),\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: L2Messenger.baseGas(hex\"ff\", 100),\n data: xDomainCallData\n })\n )\n );\n\n vm.prank(alice);\n L2Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L2Messenger.messageNonce();\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L2Messenger.messageNonce());\n }\n\n function test_xDomainSender_senderNotSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 2), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n vm.expectCall(target, hex\"1111\");\n\n vm.prank(caller);\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L2Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L2Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n address target = address(messagePasser);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n bytes memory message = hex\"1111\";\n\n vm.prank(caller);\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retry_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n uint256 value = 100;\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(caller), value);\n vm.prank(caller);\n L2Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L2Messenger.successfulMessages(hash), false);\n assertEq(L2Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L2Messenger.successfulMessages(hash), true);\n assertEq(L2Messenger.failedMessages(hash), true);\n }\n}\n" - }, - "contracts/test/L2ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.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\ncontract TestMintableERC721 is OptimismMintableERC721 {\n constructor(address _bridge, address _remoteToken)\n OptimismMintableERC721(_bridge, 1, _remoteToken, \"Test\", \"TST\")\n {}\n\n function mint(address to, uint256 tokenId) public {\n _mint(to, tokenId);\n }\n}\n\ncontract L2ERC721Bridge_Test is Messenger_Initializer {\n TestMintableERC721 internal localToken;\n TestERC721 internal remoteToken;\n L2ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L2ERC721Bridge(address(L2Messenger), otherBridge);\n remoteToken = new TestERC721();\n localToken = new TestMintableERC721(address(bridge), address(remoteToken));\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L2ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L2Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L2Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L2ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"L2ERC721Bridge: Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L1ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L2ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"L2ERC721Bridge: Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_interfaceNotCompliant_reverts() external {\n // Create a non-compliant token\n NonCompliantERC721 nonCompliantToken = new NonCompliantERC721(alice);\n\n // Bridge the non-compliant token.\n vm.prank(alice);\n bridge.bridgeERC721(address(nonCompliantToken), address(0x01), tokenId, 1234, hex\"5678\");\n\n // Attempt to finalize the withdrawal. Should revert because the token does not claim\n // to be compliant with the `IOptimismMintableERC721` interface.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"L2ERC721Bridge: local token interface is not compliant\");\n bridge.finalizeBridgeERC721(\n address(address(nonCompliantToken)),\n address(address(0x01)),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"L2ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_alreadyExists_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721: token already minted\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n\n/**\n * @dev A non-compliant ERC721 token that does not implement the full ERC721 interface.\n *\n * This is used to test that the bridge will revert if the token does not claim to support\n * the ERC721 interface.\n */\ncontract NonCompliantERC721 {\n address internal immutable owner;\n\n constructor(address _owner) {\n owner = _owner;\n }\n\n function ownerOf(uint256) external view returns (address) {\n return owner;\n }\n\n function remoteToken() external pure returns (address) {\n return address(0x01);\n }\n\n function burn(address, uint256) external {\n // Do nothing.\n }\n\n function supportsInterface(bytes4) external pure returns (bool) {\n return false;\n }\n}\n" - }, - "contracts/test/L2OutputOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { L2OutputOracle_Initializer, NextImpl } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2OutputOracleTest is L2OutputOracle_Initializer {\n bytes32 proposedOutput1 = keccak256(abi.encode(1));\n\n function test_constructor_succeeds() external {\n assertEq(oracle.PROPOSER(), proposer);\n assertEq(oracle.CHALLENGER(), owner);\n assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval);\n assertEq(oracle.latestBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingTimestamp(), startingTimestamp);\n }\n\n function test_constructor_badTimestamp_reverts() external {\n vm.expectRevert(\"L2OutputOracle: starting L2 timestamp must be less than current time\");\n\n // startingTimestamp is in the future\n new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp + 1,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n function test_constructor_l2BlockTimeZero_reverts() external {\n vm.expectRevert(\"L2OutputOracle: L2 block time must be greater than 0\");\n new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: 0,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n function test_constructor_submissionInterval_reverts() external {\n vm.expectRevert(\"L2OutputOracle: submission interval must be greater than 0\");\n new L2OutputOracle({\n _submissionInterval: 0,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n /****************\n * Getter Tests *\n ****************/\n\n // Test: latestBlockNumber() should return the correct value\n function test_latestBlockNumber_succeeds() external {\n uint256 proposedNumber = oracle.nextBlockNumber();\n\n // Roll to after the block number we'll propose\n warpToProposeTime(proposedNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, proposedNumber, 0, 0);\n assertEq(oracle.latestBlockNumber(), proposedNumber);\n }\n\n // Test: getL2Output() should return the correct value\n function test_getL2Output_succeeds() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0);\n\n Types.OutputProposal memory proposal = oracle.getL2Output(nextOutputIndex);\n assertEq(proposal.outputRoot, proposedOutput1);\n assertEq(proposal.timestamp, block.timestamp);\n\n // The block number is larger than the latest proposed output:\n vm.expectRevert(stdError.indexOOBError);\n oracle.getL2Output(nextOutputIndex + 1);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is exact block\n function test_getL2OutputIndexAfter_sameBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with exact same block as proposed returns the proposal.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is previous block\n function test_getL2OutputIndexAfter_previousBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with previous block returns the proposal too.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 - 1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value during binary search\n function test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n bytes32 output2 = keccak256(abi.encode(2));\n uint256 nextBlockNumber2 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber2);\n vm.prank(proposer);\n oracle.proposeL2Output(output2, nextBlockNumber2, 0, 0);\n\n bytes32 output3 = keccak256(abi.encode(3));\n uint256 nextBlockNumber3 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber3);\n vm.prank(proposer);\n oracle.proposeL2Output(output3, nextBlockNumber3, 0, 0);\n\n bytes32 output4 = keccak256(abi.encode(4));\n uint256 nextBlockNumber4 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber4);\n vm.prank(proposer);\n oracle.proposeL2Output(output4, nextBlockNumber4, 0, 0);\n\n // Querying with a block number between the first and second proposal\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 + 1);\n assertEq(index1, 1);\n\n // Querying with a block number between the second and third proposal\n uint256 index2 = oracle.getL2OutputIndexAfter(nextBlockNumber2 + 1);\n assertEq(index2, 2);\n\n // Querying with a block number between the third and fourth proposal\n uint256 index3 = oracle.getL2OutputIndexAfter(nextBlockNumber3 + 1);\n assertEq(index3, 3);\n }\n\n // Test: getL2OutputIndexAfter() reverts when no output exists yet\n function test_getL2OutputIndexAfter_noOutputsExis_reverts() external {\n vm.expectRevert(\"L2OutputOracle: cannot get output as no outputs have been proposed yet\");\n oracle.getL2OutputIndexAfter(0);\n }\n\n // Test: nextBlockNumber() should return the correct value\n function test_nextBlockNumber_succeeds() external {\n assertEq(\n oracle.nextBlockNumber(),\n // The return value should match this arithmetic\n oracle.latestBlockNumber() + oracle.SUBMISSION_INTERVAL()\n );\n }\n\n function test_computeL2Timestamp_succeeds() external {\n // reverts if timestamp is too low\n vm.expectRevert(stdError.arithmeticError);\n oracle.computeL2Timestamp(startingBlockNumber - 1);\n\n // returns the correct value...\n // ... for the very first block\n assertEq(oracle.computeL2Timestamp(startingBlockNumber), startingTimestamp);\n\n // ... for the first block after the starting block\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 1),\n startingTimestamp + l2BlockTime\n );\n\n // ... for some other block number\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 96024),\n startingTimestamp + l2BlockTime * 96024\n );\n }\n\n /*****************************\n * Propose Tests - Happy Path *\n *****************************/\n\n // Test: proposeL2Output succeeds when given valid input, and no block hash and number are\n // specified.\n function test_proposeL2Output_proposeAnotherOutput_succeeds() public {\n bytes32 proposedOutput2 = keccak256(abi.encode());\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n uint256 proposedNumber = oracle.latestBlockNumber();\n\n // Ensure the submissionInterval is enforced\n assertEq(nextBlockNumber, proposedNumber + submissionInterval);\n\n vm.roll(nextBlockNumber + 1);\n\n vm.expectEmit(true, true, true, true);\n emit OutputProposed(proposedOutput2, nextOutputIndex, nextBlockNumber, block.timestamp);\n\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output succeeds when given valid input, and when a block hash and number are\n // specified for reorg protection.\n function test_proposeWithBlockhashAndHeight_succeeds() external {\n // Get the number and hash of a previous block in the chain\n uint256 prevL1BlockNumber = block.number - 1;\n bytes32 prevL1BlockHash = blockhash(prevL1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber);\n }\n\n /***************************\n * Propose Tests - Sad Path *\n ***************************/\n\n // Test: proposeL2Output fails if called by a party that is not the proposer.\n function test_proposeL2Output_notProposer_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n\n vm.prank(address(128));\n vm.expectRevert(\"L2OutputOracle: only the proposer address can propose new outputs\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails given a zero blockhash.\n function test_proposeL2Output_emptyOutput_reverts() external {\n bytes32 outputToPropose = bytes32(0);\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: L2 output proposal cannot be the zero hash\");\n oracle.proposeL2Output(outputToPropose, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if the block number doesn't match the next expected number.\n function test_proposeL2Output_unexpectedBlockNumber_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: block number must be equal to next expected block number\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0);\n }\n\n // Test: proposeL2Output fails if it would have a timestamp in the future.\n function test_proposeL2Output_futureTimetamp_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextTimestamp = oracle.computeL2Timestamp(nextBlockNumber);\n vm.warp(nextTimestamp);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: cannot propose L2 output in the future\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if a non-existent L1 block hash and number are provided for reorg\n // protection.\n function test_proposeL2Output_wrongFork_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(\n nonZeroHash,\n nextBlockNumber,\n bytes32(uint256(0x01)),\n block.number - 1\n );\n }\n\n // Test: proposeL2Output fails when given valid input, but the block hash and number do not\n // match.\n function test_proposeL2Output_unmatchedBlockhash_reverts() external {\n // Move ahead to block 100 so that we can reference historical blocks\n vm.roll(100);\n\n // Get the number and hash of a previous block in the chain\n uint256 l1BlockNumber = block.number - 1;\n bytes32 l1BlockHash = blockhash(l1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n\n // This will fail when foundry no longer returns zerod block hashes\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1);\n }\n\n /*****************************\n * Delete Tests - Happy Path *\n *****************************/\n\n function test_deleteOutputs_singleOutput_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 1);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex);\n oracle.deleteL2Outputs(latestOutputIndex);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n function test_deleteOutputs_multipleOutputs_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 3);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex - 2);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval * 3, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n /***************************\n * Delete Tests - Sad Path *\n ***************************/\n\n function test_deleteL2Outputs_ifNotChallenger_reverts() external {\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.expectRevert(\"L2OutputOracle: only the challenger address can delete outputs\");\n oracle.deleteL2Outputs(latestBlockNumber);\n }\n\n function test_deleteL2Outputs_nonExistent_reverts() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestBlockNumber + 1);\n }\n\n function test_deleteL2Outputs_afterLatest_reverts() external {\n // Start by proposing three outputs\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n // Delete the latest two outputs\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n vm.prank(owner);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // Now try to delete the same output again\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n }\n\n function test_deleteL2Outputs_finalized_reverts() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n // Warp past the finalization period + 1 second\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n\n // Try to delete a finalized output\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs that have already been finalized\");\n oracle.deleteL2Outputs(latestOutputIndex);\n }\n}\n\ncontract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {\n Proxy internal proxy;\n\n function setUp() public override {\n super.setUp();\n proxy = Proxy(payable(address(oracle)));\n }\n\n function test_initValuesOnProxy_succeeds() external {\n assertEq(submissionInterval, oracleImpl.SUBMISSION_INTERVAL());\n assertEq(l2BlockTime, oracleImpl.L2_BLOCK_TIME());\n assertEq(startingBlockNumber, oracleImpl.startingBlockNumber());\n assertEq(startingTimestamp, oracleImpl.startingTimestamp());\n\n assertEq(proposer, oracleImpl.PROPOSER());\n assertEq(owner, oracleImpl.CHALLENGER());\n }\n\n function test_initializeProxy_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(payable(proxy)).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_initializeImpl_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(oracleImpl).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(oracle), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(oracle), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(oracle)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n" - }, - "contracts/test/L2StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { console } from \"forge-std/console.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\ncontract L2StandardBridge_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n function test_initialize_succeeds() external {\n assertEq(address(L2Bridge.messenger()), address(L2Messenger));\n assertEq(L1Bridge.l2TokenBridge(), address(L2Bridge));\n assertEq(address(L2Bridge.OTHER_BRIDGE()), address(L1Bridge));\n }\n\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(messagePasser).balance, 0);\n uint256 nonce = L2Messenger.messageNonce();\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 200_000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 100,\n 200_000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 100,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalInitiated(address(0), Predeploys.LEGACY_ERC20_ETH, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n // L2ToL1MessagePasser will emit a MessagePassed event\n vm.expectEmit(true, true, true, true, address(messagePasser));\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 100,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 200_000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessageExtension1(address(L2Bridge), 100);\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 200_000 // StandardBridge's RECEIVE_DEFAULT_GAS_LIMIT\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n vm.prank(alice, alice);\n (bool success, ) = address(L2Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(messagePasser).balance, 100);\n }\n\n // withrdraw\n // - requires amount == msg.value\n function test_withdraw_insufficientValue_reverts() external {\n assertEq(address(messagePasser).balance, 0);\n\n vm.expectRevert(\"StandardBridge: bridging ETH must include sufficient ETH value\");\n vm.prank(alice, alice);\n L2Bridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 100, 1000, hex\"\");\n }\n\n /**\n * @notice Use the legacy `withdraw` interface on the L2StandardBridge to\n * withdraw ether from L2 to L1.\n */\n function test_withdraw_ether_succeeds() external {\n assertTrue(alice.balance >= 100);\n assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 0);\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit WithdrawalInitiated({\n l1Token: address(0),\n l2Token: Predeploys.LEGACY_ERC20_ETH,\n from: alice,\n to: alice,\n amount: 100,\n data: hex\"\"\n });\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ETHBridgeInitiated({ from: alice, to: alice, amount: 100, data: hex\"\" });\n\n vm.prank(alice, alice);\n L2Bridge.withdraw{ value: 100 }({\n _l2Token: Predeploys.LEGACY_ERC20_ETH,\n _amount: 100,\n _minGasLimit: 1000,\n _extraData: hex\"\"\n });\n\n assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 100);\n }\n}\n\ncontract PreBridgeERC20 is Bridge_Initializer {\n // withdraw and BridgeERC20 should behave the same when transferring ERC20 tokens\n // so they should share the same setup and expectEmit calls\n function _preBridgeERC20(bool _isLegacy, address _l2Token) internal {\n // Alice has 100 L2Token\n deal(_l2Token, alice, 100, true);\n assertEq(ERC20(_l2Token).balanceOf(alice), 100);\n uint256 nonce = L2Messenger.messageNonce();\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L1Token),\n _l2Token,\n alice,\n alice,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 1000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 0,\n 1000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n if (_isLegacy) {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(L2Bridge.withdraw.selector, _l2Token, 100, 1000, hex\"\")\n );\n } else {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.bridgeERC20.selector,\n _l2Token,\n address(L1Token),\n 100,\n 1000,\n hex\"\"\n )\n );\n }\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 1000\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n // The L2Bridge should burn the tokens\n vm.expectCall(\n _l2Token,\n abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalInitiated(address(L1Token), _l2Token, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 0,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true);\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true);\n emit SentMessageExtension1(address(L2Bridge), 0);\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {\n // withdraw\n // - token is burned\n // - emits WithdrawalInitiated\n // - calls Withdrawer.initiateWithdrawal\n function test_withdraw_withdrawingERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: true, _l2Token: address(L2Token) });\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n // BridgeERC20\n // - token is burned\n // - emits WithdrawalInitiated\n // - calls Withdrawer.initiateWithdrawal\n function test_bridgeERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: false, _l2Token: address(L2Token) });\n L2Bridge.bridgeERC20(address(L2Token), address(L1Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_withdrawLegacyERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: true, _l2Token: address(LegacyL2Token) });\n L2Bridge.withdraw(address(LegacyL2Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_bridgeLegacyERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: false, _l2Token: address(LegacyL2Token) });\n L2Bridge.bridgeERC20(address(LegacyL2Token), address(L1Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_withdraw_notEOA_reverts() external {\n // This contract has 100 L2Token\n deal(address(L2Token), address(this), 100, true);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n }\n}\n\ncontract PreBridgeERC20To is Bridge_Initializer {\n // withdrawTo and BridgeERC20To should behave the same when transferring ERC20 tokens\n // so they should share the same setup and expectEmit calls\n function _preBridgeERC20To(bool _isLegacy, address _l2Token) internal {\n deal(_l2Token, alice, 100, true);\n assertEq(ERC20(L2Token).balanceOf(alice), 100);\n uint256 nonce = L2Messenger.messageNonce();\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L1Token),\n _l2Token,\n alice,\n bob,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 1000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 0,\n 1000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit WithdrawalInitiated(address(L1Token), _l2Token, alice, bob, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, bob, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(messagePasser));\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 0,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessageExtension1(address(L2Bridge), 0);\n\n if (_isLegacy) {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.withdrawTo.selector,\n _l2Token,\n bob,\n 100,\n 1000,\n hex\"\"\n )\n );\n } else {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.bridgeERC20To.selector,\n _l2Token,\n address(L1Token),\n bob,\n 100,\n 1000,\n hex\"\"\n )\n );\n }\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 1000\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n // The L2Bridge should burn the tokens\n vm.expectCall(\n address(L2Token),\n abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)\n );\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To {\n // withdrawTo\n // - token is burned\n // - emits WithdrawalInitiated w/ correct recipient\n // - calls Withdrawer.initiateWithdrawal\n function test_withdrawTo_withdrawingERC20_succeeds() external {\n _preBridgeERC20To({ _isLegacy: true, _l2Token: address(L2Token) });\n L2Bridge.withdrawTo(address(L2Token), bob, 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n // bridgeERC20To\n // - token is burned\n // - emits WithdrawalInitiated w/ correct recipient\n // - calls Withdrawer.initiateWithdrawal\n function test_bridgeERC20To_succeeds() external {\n _preBridgeERC20To({ _isLegacy: false, _l2Token: address(L2Token) });\n L2Bridge.bridgeERC20To(address(L2Token), address(L1Token), bob, 100, 1000, hex\"\");\n assertEq(L2Token.balanceOf(alice), 0);\n }\n}\n\ncontract L2StandardBridge_Bridge_Test is Bridge_Initializer {\n // finalizeDeposit\n // - only callable by l1TokenBridge\n // - supported token pair emits DepositFinalized\n // - invalid deposit calls Withdrawer.initiateWithdrawal\n function test_finalizeDeposit_depositingERC20_succeeds() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n\n vm.expectCall(\n address(L2Token),\n abi.encodeWithSelector(OptimismMintableERC20.mint.selector, alice, 100)\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeFinalized(address(L2Token), address(L1Token), alice, alice, 100, hex\"\");\n\n vm.prank(address(L2Messenger));\n L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n }\n\n function test_finalizeDeposit_depositingETH_succeeds() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeFinalized(\n address(L2Token), // localToken\n address(L1Token), // remoteToken\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n vm.prank(address(L2Messenger));\n L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L2Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Messenger), 100, hex\"\");\n }\n}\n\ncontract L2StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {\n function test_finalizeBridgeETH_succeeds() external {\n address messenger = address(L2Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n\n vm.expectEmit(true, true, true, true);\n emit DepositFinalized(address(0), Predeploys.LEGACY_ERC20_ETH, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2ToL1MessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\n\ncontract L2ToL1MessagePasserTest is CommonTest {\n L2ToL1MessagePasser messagePasser;\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n function setUp() public virtual override {\n super.setUp();\n messagePasser = new L2ToL1MessagePasser();\n }\n\n function testFuzz_initiateWithdrawal_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint256 nonce = messagePasser.messageNonce();\n\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: _value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, _sender, _target, _value, _gasLimit, _data, withdrawalHash);\n\n vm.deal(_sender, _value);\n vm.prank(_sender);\n messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);\n\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n\n bytes32 slot = keccak256(bytes.concat(withdrawalHash, bytes32(0)));\n\n assertEq(vm.load(address(messagePasser), slot), bytes32(uint256(1)));\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by a contract\n function test_initiateWithdrawal_fromContract_succeeds() external {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\"\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\",\n withdrawalHash\n );\n\n vm.deal(address(this), 2**64);\n messagePasser.initiateWithdrawal{ value: 100 }(address(4), 64000, hex\"\");\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by an EOA\n function test_initiateWithdrawal_fromEOA_succeeds() external {\n uint256 gasLimit = 64000;\n address target = address(4);\n uint256 value = 100;\n bytes memory data = hex\"ff\";\n uint256 nonce = messagePasser.messageNonce();\n\n // EOA emulation\n vm.prank(alice, alice);\n vm.deal(alice, 2**64);\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(nonce, alice, target, value, gasLimit, data)\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, alice, target, value, gasLimit, data, withdrawalHash);\n\n messagePasser.initiateWithdrawal{ value: value }(target, gasLimit, data);\n\n // the sent messages mapping is filled\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n // the nonce increments\n assertEq(nonce + 1, messagePasser.messageNonce());\n }\n\n // Test: burn should destroy the ETH held in the contract\n function test_burn_succeeds() external {\n messagePasser.initiateWithdrawal{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n NON_ZERO_GASLIMIT,\n NON_ZERO_DATA\n );\n\n assertEq(address(messagePasser).balance, NON_ZERO_VALUE);\n vm.expectEmit(true, false, false, false);\n emit WithdrawerBalanceBurnt(NON_ZERO_VALUE);\n messagePasser.burn();\n\n // The Withdrawer should have no balance\n assertEq(address(messagePasser).balance, 0);\n }\n}\n" - }, - "contracts/test/LegacyERC20ETH.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyERC20ETH_Test is CommonTest {\n LegacyERC20ETH eth;\n\n function setUp() public virtual override {\n super.setUp();\n eth = new LegacyERC20ETH();\n }\n\n function test_metadata_succeeds() external {\n assertEq(eth.name(), \"Ether\");\n assertEq(eth.symbol(), \"ETH\");\n assertEq(eth.decimals(), 18);\n }\n\n function test_crossDomain_succeeds() external {\n assertEq(eth.l2Bridge(), Predeploys.L2_STANDARD_BRIDGE);\n assertEq(eth.l1Token(), address(0));\n }\n\n function test_transfer_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transfer is disabled\");\n eth.transfer(alice, 100);\n }\n\n function test_approve_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: approve is disabled\");\n eth.approve(alice, 100);\n }\n\n function test_transferFrom_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transferFrom is disabled\");\n eth.transferFrom(bob, alice, 100);\n }\n\n function test_increaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n eth.increaseAllowance(alice, 100);\n }\n\n function test_decreaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n eth.decreaseAllowance(alice, 100);\n }\n\n function test_mint_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: mint is disabled\");\n eth.mint(alice, 100);\n }\n\n function test_burn_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: burn is disabled\");\n eth.burn(alice, 100);\n }\n}\n" - }, - "contracts/test/LegacyMessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyMessagePasser } from \"../legacy/LegacyMessagePasser.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyMessagePasser_Test is CommonTest {\n LegacyMessagePasser messagePasser;\n\n function setUp() public virtual override {\n super.setUp();\n messagePasser = new LegacyMessagePasser();\n }\n\n function test_passMessageToL1_succeeds() external {\n vm.prank(alice);\n messagePasser.passMessageToL1(hex\"ff\");\n assert(messagePasser.sentMessages(keccak256(abi.encodePacked(hex\"ff\", alice))));\n }\n}\n" - }, - "contracts/test/MerkleTrie.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MerkleTrie } from \"../libraries/trie/MerkleTrie.sol\";\n\ncontract MerkleTrie_get_Test is CommonTest {\n function test_get_validProof1_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579326262\";\n bytes memory val = hex\"6176616c32\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof2_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[\n 2\n ] = hex\"ef83206161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof3_succeeds() external {\n bytes32 root = 0xf838216fa749aefa91e0b672a9c06d3e6e983f913d7107b5dab4af60b5f5abed;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"f387206b6579316161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof4_succeeds() external {\n bytes32 root = 0x37956bab6bba472308146808d5311ac19cb4a7daae5df7efcc0f32badc97f55e;\n bytes memory key = hex\"6b6579316161\";\n bytes memory val = hex\"3031323334\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"ce87206b6579316161853031323334\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof5_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657931\";\n bytes\n memory val = hex\"30313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f862808080808080a057895fdbd71e2c67c2f9274a56811ff5cf458720a7fa713a135e3890f8cafcf8808080808080808080b130313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof6_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657932\";\n bytes memory val = hex\"73686f7274\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[2] = hex\"df808080808080c9823262856176616c338080808080808080808573686f7274\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof7_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657933\";\n bytes memory val = hex\"31323334353637383930313233343536373839303132333435363738393031\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f839808080808080c9823363856176616c338080808080808080809f31323334353637383930313233343536373839303132333435363738393031\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof8_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"61\";\n bytes memory val = hex\"61\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22061\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof9_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"62\";\n bytes memory val = hex\"62\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22062\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof10_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"63\";\n bytes memory val = hex\"63\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22063\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_nonexistentKey1_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b657932\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_nonexistentKey2_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"616e7972616e646f6d6b6579\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_wrongKeyProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579316161\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e216a04892c039d654f1be9af20e88ae53e9ab5fa5520190e0fb2f805823e45ebad22f\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[2] = hex\"d687206e6f746865728d33343938683472697568677765\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_corruptedProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579326262\";\n bytes[] memory proof = new bytes[](5);\n proof[0] = hex\"2fd2ba5ee42358802ffbe0900152a55fabe953ae880ef29abef154d639c09248a016e2\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[\n 2\n ] = hex\"e583165793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 3\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[4] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidDataRemainder_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa000000000000000000000000000000\";\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidInternalNodeHash_reverts() external {\n bytes32 root = 0xa827dff1a657bb9bb9a1c3abe9db173e2f1359f15eb06f1647ea21ac7c95d8fa;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa09862c6b113008c4204c13755693cbb868acc25ebaa98db11df8c89a0c0dd3157\";\n proof[\n 1\n ] = hex\"f380808080808080808080a0de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f00c220118080808080\";\n proof[2] = hex\"de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroBranchValueLength_reverts() external {\n bytes32 root = 0xe04b3589eef96b237cd49ccb5dcf6e654a47682bfa0961d563ab843f7ad1e035;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](2);\n proof[0] = hex\"dd8200aad98080808080808080808080c43b82aabbc43c82aacc80808080\";\n proof[1] = hex\"d98080808080808080808080c43b82aabbc43c82aacc80808080\";\n\n vm.expectRevert(\"MerkleTrie: value length must be greater than zero (branch)\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroLengthKey_reverts() external {\n bytes32 root = 0x54157fd62cdf2f474e7bfec2d3cd581e807bee38488c9590cb887add98936b73;\n bytes memory key = hex\"\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"c78320f00082b443\";\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey1_reverts() external {\n bytes32 root = 0xa513ba530659356fb7588a2c831944e80fd8aedaa5a4dc36f918152be2be0605;\n bytes memory key = hex\"01\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"db10d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[1] = hex\"d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[2] = hex\"c582202381aa\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey2_reverts() external {\n bytes32 root = 0xa06abffaec4ebe8ccde595f4547b864b4421b21c1fc699973f94710c9bc17979;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa07ea462226a3dc0a46afb4ded39306d7a84d311ada3557dfc75a909fd25530905\";\n proof[\n 1\n ] = hex\"f380808080808080808080a027f11bd3af96d137b9287632f44dd00fea1ca1bd70386c30985ede8cc287476e808080c220338080\";\n proof[2] = hex\"e48200bba0a6911545ed01c2d3f4e15b8b27c7bfba97738bd5e6dd674dd07033428a4c53af\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_extraProofElements_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](4);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa\";\n proof[3] = hex\"c32081aa\";\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_validProofs_succeeds(bytes4) external {\n // Generate a test case with a valid proof of inclusion for the k/v pair in the trie.\n (bytes32 root, bytes memory key, bytes memory val, bytes[] memory proof) = ffi\n .getMerkleTrieFuzzCase(\"valid\");\n\n // Assert that our expected value is equal to our actual value.\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidRoot_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"valid\"\n );\n\n bytes32 rootHash = keccak256(abi.encodePacked(root));\n vm.expectRevert(\"MerkleTrie: invalid root hash\");\n MerkleTrie.get(key, proof, rootHash);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_extraProofElements_reverts(bytes4) external {\n // Generate an invalid test case with an extra proof element attached to an otherwise\n // valid proof of inclusion for the passed k/v.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"extra_proof_elems\"\n );\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidLargeInternalHash_reverts(bytes4) external {\n // Generate an invalid test case where a long proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_large_internal_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid large internal hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidInternalNodeHash_reverts(bytes4) external {\n // Generate an invalid test case where a small proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_internal_node_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_corruptedProof_reverts(bytes4) external {\n // Generate an invalid test case where the proof is malformed.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"corrupted_proof\"\n );\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidDataRemainder_reverts(bytes4) external {\n // Generate an invalid test case where a random element of the proof has more bytes than the\n // length designates within the RLP list encoding.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_data_remainder\"\n );\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_prefixedValidKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and a valid key that is prefixed\n // with random bytes\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"prefixed_valid_key\"\n );\n\n // Ambiguous revert check- all that we care is that it *does* fail. This case may\n // fail within different branches.\n vm.expectRevert();\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_emptyKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and an empty key\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"empty_key\"\n );\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_partialProof_reverts(bytes4) external {\n // Get a random test case with a valid trie / partially correct proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"partial_proof\"\n );\n\n vm.expectRevert(\"MerkleTrie: ran out of proof elements\");\n MerkleTrie.get(key, proof, root);\n }\n}\n" - }, - "contracts/test/MintManager.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MintManager } from \"../governance/MintManager.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract MintManager_Initializer is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n MintManager internal manager;\n\n function setUp() public virtual override {\n super.setUp();\n\n vm.prank(owner);\n gov = new GovernanceToken();\n\n vm.prank(owner);\n manager = new MintManager(owner, address(gov));\n\n vm.prank(owner);\n gov.transferOwnership(address(manager));\n }\n}\n\ncontract MintManager_constructor_Test is MintManager_Initializer {\n /**\n * @notice Tests that the constructor properly configures the contract.\n */\n function test_constructor_succeeds() external {\n assertEq(manager.owner(), owner);\n assertEq(address(manager.governanceToken()), address(gov));\n }\n}\n\ncontract MintManager_mint_Test is MintManager_Initializer {\n /**\n * @notice Tests that the mint function properly mints tokens when called by the owner.\n */\n function test_mint_fromOwner_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n /**\n * @notice Tests that the mint function reverts when called by a non-owner.\n */\n function test_mint_fromNotOwner_reverts() external {\n // Mint from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.mint(owner, 100);\n }\n\n /**\n * @notice Tests that the mint function properly mints tokens when called by the owner a second\n * time after the mint period has elapsed.\n */\n function test_mint_afterPeriodElapsed_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again after period elapsed (2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n manager.mint(owner, 2);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 102);\n }\n\n /**\n * @notice Tests that the mint function always reverts when called before the mint period has\n * elapsed, even if the caller is the owner.\n */\n function test_mint_beforePeriodElapsed_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: minting not permitted yet\");\n manager.mint(owner, 100);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n /**\n * @notice Tests that the owner cannot mint more than the mint cap.\n */\n function test_mint_moreThanCap_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again (greater than 2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint amount exceeds cap\");\n manager.mint(owner, 3);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n}\n\ncontract MintManager_upgrade_Test is MintManager_Initializer {\n /**\n * @notice Tests that the owner can upgrade the mint manager.\n */\n function test_upgrade_fromOwner_succeeds() external {\n // Upgrade to new manager.\n vm.prank(owner);\n manager.upgrade(rando);\n\n // New manager is rando.\n assertEq(gov.owner(), rando);\n }\n\n /**\n * @notice Tests that the upgrade function reverts when called by a non-owner.\n */\n function test_upgrade_fromNotOwner_reverts() external {\n // Upgrade from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.upgrade(rando);\n }\n\n /**\n * @notice Tests that the upgrade function reverts when attempting to update to the zero\n * address, even if the caller is the owner.\n */\n function test_upgrade_toZeroAddress_reverts() external {\n // Upgrade to zero address fails.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint manager cannot be the zero address\");\n manager.upgrade(address(0));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport {\n ILegacyMintableERC20,\n IOptimismMintableERC20\n} from \"../universal/IOptimismMintableERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ncontract OptimismMintableERC20_Test is Bridge_Initializer {\n event Mint(address indexed account, uint256 amount);\n event Burn(address indexed account, uint256 amount);\n\n function test_semver_succeeds() external {\n assertEq(L2Token.version(), \"1.0.0\");\n }\n\n function test_remoteToken_succeeds() external {\n assertEq(L2Token.remoteToken(), address(L1Token));\n }\n\n function test_bridge_succeeds() external {\n assertEq(L2Token.bridge(), address(L2Bridge));\n }\n\n function test_l1Token_succeeds() external {\n assertEq(L2Token.l1Token(), address(L1Token));\n }\n\n function test_l2Bridge_succeeds() external {\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_legacy_succeeds() external {\n // Getters for the remote token\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.l1Token(), address(L1Token));\n // Getters for the bridge\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_mint_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 100);\n }\n\n function test_mint_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.mint(alice, 100);\n }\n\n function test_burn_succeeds() external {\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_burn_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.burn(alice, 100);\n }\n\n function test_erc165_supportsInterface_succeeds() external {\n // The assertEq calls in this test are comparing the manual calculation of the iface,\n // with what is returned by the solidity's type().interfaceId, just to be safe.\n bytes4 iface1 = bytes4(keccak256(\"supportsInterface(bytes4)\"));\n assertEq(iface1, type(IERC165).interfaceId);\n assert(L2Token.supportsInterface(iface1));\n\n bytes4 iface2 = L2Token.l1Token.selector ^ L2Token.mint.selector ^ L2Token.burn.selector;\n assertEq(iface2, type(ILegacyMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface2));\n\n bytes4 iface3 = L2Token.remoteToken.selector ^\n L2Token.bridge.selector ^\n L2Token.mint.selector ^\n L2Token.burn.selector;\n assertEq(iface3, type(IOptimismMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface3));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\n\ncontract OptimismMintableTokenFactory_Test is Bridge_Initializer {\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n }\n\n function test_bridge_succeeds() external {\n assertEq(address(L2TokenFactory.BRIDGE()), address(L2Bridge));\n }\n\n function test_createStandardL2Token_succeeds() external {\n address remote = address(4);\n address local = LibRLP.computeAddress(address(L2TokenFactory), 2);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_sameTwice_succeeds() external {\n address remote = address(4);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n\n address local = LibRLP.computeAddress(address(L2TokenFactory), 3);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_remoteIsZero_succeeds() external {\n address remote = address(0);\n vm.expectRevert(\"OptimismMintableERC20Factory: must provide remote token address\");\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721, IERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport {\n IERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport {\n OptimismMintableERC721,\n IOptimismMintableERC721\n} from \"../universal/OptimismMintableERC721.sol\";\n\ncontract OptimismMintableERC721_Test is ERC721Bridge_Initializer {\n ERC721 internal L1Token;\n OptimismMintableERC721 internal L2Token;\n\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n event Mint(address indexed account, uint256 tokenId);\n\n event Burn(address indexed account, uint256 tokenId);\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n L1Token = new ERC721(\"L1Token\", \"L1T\");\n L2Token = new OptimismMintableERC721(\n address(L2Bridge),\n 1,\n address(L1Token),\n \"L2Token\",\n \"L2T\"\n );\n\n // Label the addresses for nice traces.\n vm.label(address(L1Token), \"L1ERC721Token\");\n vm.label(address(L2Token), \"L2ERC721Token\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(L2Token.name(), \"L2Token\");\n assertEq(L2Token.symbol(), \"L2T\");\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.remoteChainId(), 1);\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.REMOTE_CHAIN_ID(), 1);\n assertEq(L2Token.version(), \"1.1.0\");\n }\n\n /**\n * @notice Ensure that the contract supports the expected interfaces.\n */\n function test_supportsInterfaces_succeeds() external {\n // Checks if the contract supports the IOptimismMintableERC721 interface.\n assertTrue(L2Token.supportsInterface(type(IOptimismMintableERC721).interfaceId));\n // Checks if the contract supports the IERC721Enumerable interface.\n assertTrue(L2Token.supportsInterface(type(IERC721Enumerable).interfaceId));\n // Checks if the contract supports the IERC721 interface.\n assertTrue(L2Token.supportsInterface(type(IERC721).interfaceId));\n // Checks if the contract supports the IERC165 interface.\n assertTrue(L2Token.supportsInterface(type(IERC165).interfaceId));\n }\n\n function test_safeMint_succeeds() external {\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(address(0), alice, 1);\n\n // Expect a mint event.\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 1);\n\n // Mint the token.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token should be owned by alice.\n assertEq(L2Token.ownerOf(1), alice);\n }\n\n function test_safeMint_notBridge_reverts() external {\n // Try to mint the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.safeMint(alice, 1);\n }\n\n function test_burn_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(alice, address(0), 1);\n\n // Expect a burn event.\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 1);\n\n // Burn the token.\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 1);\n\n // Token should be owned by address(0).\n vm.expectRevert(\"ERC721: invalid token ID\");\n L2Token.ownerOf(1);\n }\n\n function test_burn_notBridge_reverts() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Try to burn the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.burn(alice, 1);\n }\n\n function test_tokenURI_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token URI should be correct.\n assertEq(\n L2Token.tokenURI(1),\n string(\n abi.encodePacked(\n \"ethereum:\",\n Strings.toHexString(uint160(address(L1Token)), 20),\n \"@\",\n Strings.toString(1),\n \"/tokenURI?uint256=\",\n Strings.toString(1)\n )\n )\n );\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\n\ncontract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer {\n OptimismMintableERC721Factory internal factory;\n\n event OptimismMintableERC721Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n factory = new OptimismMintableERC721Factory(address(L2Bridge), 1);\n\n // Label the addresses for nice traces.\n vm.label(address(factory), \"OptimismMintableERC721Factory\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(factory.BRIDGE(), address(L2Bridge));\n assertEq(factory.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_succeeds() external {\n // Predict the address based on the factory address and nonce.\n address predicted = LibRLP.computeAddress(address(factory), 1);\n\n // Expect a token creation event.\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC721Created(predicted, address(1234), alice);\n\n // Create the token.\n vm.prank(alice);\n OptimismMintableERC721 created = OptimismMintableERC721(\n factory.createOptimismMintableERC721(address(1234), \"L2Token\", \"L2T\")\n );\n\n // Token address should be correct.\n assertEq(address(created), predicted);\n\n // Should be marked as created by the factory.\n assertEq(factory.isOptimismMintableERC721(address(created)), true);\n\n // Token should've been constructed correctly.\n assertEq(created.name(), \"L2Token\");\n assertEq(created.symbol(), \"L2T\");\n assertEq(created.REMOTE_TOKEN(), address(1234));\n assertEq(created.BRIDGE(), address(L2Bridge));\n assertEq(created.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_zeroRemoteToken_reverts() external {\n // Try to create a token with a zero remote token address.\n vm.expectRevert(\"OptimismMintableERC721Factory: L1 token address cannot be address(0)\");\n factory.createOptimismMintableERC721(address(0), \"L2Token\", \"L2T\");\n }\n}\n" - }, - "contracts/test/OptimismPortal.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { Portal_Initializer, CommonTest, NextImpl } from \"./CommonTest.t.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\ncontract OptimismPortal_Test is Portal_Initializer {\n event Paused(address);\n event Unpaused(address);\n\n function test_constructor_succeeds() external {\n assertEq(address(op.L2_ORACLE()), address(oracle));\n assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD);\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal can be paused by the GUARDIAN\n */\n function test_pause_succeeds() external {\n address guardian = op.GUARDIAN();\n\n assertEq(op.paused(), false);\n\n vm.expectEmit(true, true, true, true, address(op));\n emit Paused(guardian);\n\n vm.prank(guardian);\n op.pause();\n\n assertEq(op.paused(), true);\n }\n\n /**\n * @notice The OptimismPortal reverts when an account that is not the\n * GUARDIAN calls `pause()`\n */\n function test_pause_onlyGuardian_reverts() external {\n assertEq(op.paused(), false);\n\n assertTrue(op.GUARDIAN() != alice);\n vm.expectRevert(\"OptimismPortal: only guardian can pause\");\n vm.prank(alice);\n op.pause();\n\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal can be unpaused by the GUARDIAN\n */\n function test_unpause_succeeds() external {\n address guardian = op.GUARDIAN();\n\n vm.prank(guardian);\n op.pause();\n assertEq(op.paused(), true);\n\n vm.expectEmit(true, true, true, true, address(op));\n emit Unpaused(guardian);\n vm.prank(guardian);\n op.unpause();\n\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal reverts when an account that is not\n * the GUARDIAN calls `unpause()`\n */\n function test_unpause_onlyGuardian_reverts() external {\n address guardian = op.GUARDIAN();\n\n vm.prank(guardian);\n op.pause();\n assertEq(op.paused(), true);\n\n assertTrue(op.GUARDIAN() != alice);\n vm.expectRevert(\"OptimismPortal: only guardian can unpause\");\n vm.prank(alice);\n op.unpause();\n\n assertEq(op.paused(), true);\n }\n\n function test_receive_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(alice, alice, 100, 100, 100_000, false, hex\"\");\n\n // give alice money and send as an eoa\n vm.deal(alice, 2**64);\n vm.prank(alice, alice);\n (bool s, ) = address(op).call{ value: 100 }(hex\"\");\n\n assert(s);\n assertEq(address(op).balance, 100);\n }\n\n // Test: depositTransaction fails when contract creation has a non-zero destination address\n function test_depositTransaction_contractCreation_reverts() external {\n // contract creation must have a target of address(0)\n vm.expectRevert(\"OptimismPortal: must send to address(0) when creating a contract\");\n op.depositTransaction(address(1), 1, 0, true, hex\"\");\n }\n\n /**\n * @notice Prevent deposits from being too large to have a sane upper bound\n * on unsafe blocks sent over the p2p network.\n */\n function test_depositTransaction_largeData_reverts() external {\n uint256 size = 120_001;\n uint64 gasLimit = op.minimumGasLimit(uint64(size));\n vm.expectRevert(\"OptimismPortal: data too large\");\n op.depositTransaction({\n _to: address(0),\n _value: 0,\n _gasLimit: gasLimit,\n _isCreation: false,\n _data: new bytes(size)\n });\n }\n\n /**\n * @notice Prevent gasless deposits from being force processed in L2 by\n * ensuring that they have a large enough gas limit set.\n */\n function test_depositTransaction_smallGasLimit_reverts() external {\n vm.expectRevert(\"OptimismPortal: gas limit too small\");\n op.depositTransaction({\n _to: address(1),\n _value: 0,\n _gasLimit: 0,\n _isCreation: false,\n _data: hex\"\"\n });\n }\n\n /**\n * @notice Fuzz for too small of gas limits\n */\n function testFuzz_depositTransaction_smallGasLimit_succeeds(\n bytes memory _data,\n bool _shouldFail\n ) external {\n vm.assume(_data.length <= type(uint64).max);\n\n uint64 gasLimit = op.minimumGasLimit(uint64(_data.length));\n if (_shouldFail) {\n gasLimit = uint64(bound(gasLimit, 0, gasLimit - 1));\n vm.expectRevert(\"OptimismPortal: gas limit too small\");\n }\n\n op.depositTransaction({\n _to: address(0x40),\n _value: 0,\n _gasLimit: gasLimit,\n _isCreation: false,\n _data: _data\n });\n }\n\n /**\n * @notice Ensure that the 0 calldata case is covered and there is a linearly\n * increasing gas limit for larger calldata sizes.\n */\n function test_minimumGasLimit_succeeds() external {\n assertEq(op.minimumGasLimit(0), 21_000);\n assertTrue(op.minimumGasLimit(2) > op.minimumGasLimit(1));\n assertTrue(op.minimumGasLimit(3) > op.minimumGasLimit(2));\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value\n function test_depositTransaction_noValueEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value\n function test_depositTransaction_noValueContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndContractContractCreation_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n function test_simple_isOutputFinalized_succeeds() external {\n uint256 ts = block.timestamp;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(bytes32(uint256(1)), uint128(ts), uint128(startingBlockNumber))\n )\n );\n\n // warp to the finalization period\n vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS());\n assertEq(op.isOutputFinalized(0), false);\n\n // warp past the finalization period\n vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n assertEq(op.isOutputFinalized(0), true);\n }\n\n function test_isOutputFinalized_succeeds() external {\n uint256 checkpoint = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n vm.roll(checkpoint);\n vm.warp(oracle.computeL2Timestamp(checkpoint) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(keccak256(abi.encode(2)), checkpoint, 0, 0);\n\n // warp to the final second of the finalization period\n uint256 finalizationHorizon = block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS();\n vm.warp(finalizationHorizon);\n // The checkpointed block should not be finalized until 1 second from now.\n assertEq(op.isOutputFinalized(nextOutputIndex), false);\n // Nor should a block after it\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n\n // warp past the finalization period\n vm.warp(finalizationHorizon + 1);\n // It should now be finalized.\n assertEq(op.isOutputFinalized(nextOutputIndex), true);\n // But not the block after it.\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n }\n}\n\ncontract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n // Utility function used in the subsequent test. This is necessary to assert that the\n // reentrant call will revert.\n function callPortalAndExpectRevert() external payable {\n vm.expectRevert(\"OptimismPortal: can only trigger one withdrawal per transaction\");\n // Arguments here don't matter, as the require check is the first thing that happens.\n // We assume that this has already been proven.\n op.finalizeWithdrawalTransaction(_defaultTx);\n // Assert that the withdrawal was not finalized.\n assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx)));\n }\n\n /**\n * @notice Proving withdrawal transactions should revert when paused\n */\n function test_proveWithdrawalTransaction_paused_reverts() external {\n vm.prank(op.GUARDIAN());\n op.pause();\n\n vm.expectRevert(\"OptimismPortal: paused\");\n op.proveWithdrawalTransaction({\n _tx: _defaultTx,\n _l2OutputIndex: _proposedOutputIndex,\n _outputRootProof: _outputRootProof,\n _withdrawalProof: _withdrawalProof\n });\n }\n\n // Test: proveWithdrawalTransaction cannot prove a withdrawal with itself (the OptimismPortal) as the target.\n function test_proveWithdrawalTransaction_onSelfCall_reverts() external {\n _defaultTx.target = address(op);\n vm.expectRevert(\"OptimismPortal: you cannot send messages to the portal contract\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the outputRootProof does not match the output root\n function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external {\n // Modify the version to invalidate the withdrawal proof.\n _outputRootProof.version = bytes32(uint256(1));\n vm.expectRevert(\"OptimismPortal: invalid output root proof\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the proof is invalid due to non-existence of\n // the withdrawal.\n function test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() external {\n // modify the default test values to invalidate the proof.\n _defaultTx.data = hex\"abcd\";\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the passed transaction's withdrawalHash has\n // already been proven.\n function test_proveWithdrawalTransaction_replayProve_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: withdrawal hash has already been proven\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has\n // already been proven AND the output root has changed AND the l2BlockNumber stays the same.\n function test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`\n // inside of the `provenWithdrawal`s mapping.\n bytes32 slot;\n assembly {\n mstore(0x00, sload(_withdrawalHash.slot))\n mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in the OptimismPortal\n slot := keccak256(0x00, 0x40)\n }\n\n // Store a different output root within the `provenWithdrawals` mapping without\n // touching the l2BlockNumber or timestamp.\n vm.store(address(op), slot, bytes32(0));\n\n // Warp ahead 1 second\n vm.warp(block.timestamp + 1);\n\n // Even though we have already proven this withdrawalHash, we should be allowed to re-submit\n // our proof with a changed outputRoot\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Ensure that the withdrawal was updated within the mapping\n (, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);\n assertEq(timestamp, block.timestamp);\n }\n\n // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has\n // already been proven AND the output root + output index + l2BlockNumber changes.\n function test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds()\n external\n {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`\n // inside of the `provenWithdrawal`s mapping.\n bytes32 slot;\n assembly {\n mstore(0x00, sload(_withdrawalHash.slot))\n mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in OptimismPortal\n slot := keccak256(0x00, 0x40)\n }\n\n // Store a dummy output root within the `provenWithdrawals` mapping without touching the\n // l2BlockNumber or timestamp.\n vm.store(address(op), slot, bytes32(0));\n\n // Fetch the output proposal at `_proposedOutputIndex` from the L2OutputOracle\n Types.OutputProposal memory proposal = op.L2_ORACLE().getL2Output(_proposedOutputIndex);\n\n // Propose the same output root again, creating the same output at a different index + l2BlockNumber.\n vm.startPrank(op.L2_ORACLE().PROPOSER());\n op.L2_ORACLE().proposeL2Output(\n proposal.outputRoot,\n op.L2_ORACLE().nextBlockNumber(),\n blockhash(block.number),\n block.number\n );\n vm.stopPrank();\n\n // Warp ahead 1 second\n vm.warp(block.timestamp + 1);\n\n // Even though we have already proven this withdrawalHash, we should be allowed to re-submit\n // our proof with a changed outputRoot + a different output index\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex + 1,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Ensure that the withdrawal was updated within the mapping\n (, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);\n assertEq(timestamp, block.timestamp);\n }\n\n // Test: proveWithdrawalTransaction succeeds and emits the WithdrawalProven event.\n function test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: finalizeWithdrawalTransaction succeeds and emits the WithdrawalFinalized event.\n function test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, false, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore + 100);\n }\n\n /**\n * @notice Finalizing withdrawal transactions should revert when paused\n */\n function test_finalizeWithdrawalTransaction_paused_reverts() external {\n vm.prank(op.GUARDIAN());\n op.pause();\n\n vm.expectRevert(\"OptimismPortal: paused\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has not been proven.\n function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectRevert(\"OptimismPortal: withdrawal has not been proven yet\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if withdrawal not proven long enough ago.\n function test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Mock a call where the resulting output root is anything but the original output root. In\n // this case we just use bytes32(uint256(1)).\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(bytes32(uint256(1)), _proposedBlockNumber)\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the provenWithdrawal's timestamp is less\n // than the L2 output oracle's starting timestamp\n function test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a startingTimestamp change on the L2 Oracle\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSignature(\"startingTimestamp()\"),\n abi.encode(block.timestamp + 1)\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output root proven is not the same as the\n // output root at the time of finalization.\n function test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock an outputRoot change on the output proposal before attempting\n // to finalize the withdrawal.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n bytes32(uint256(0)),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output proposal's timestamp has\n // not passed the finalization period.\n function test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a timestamp change on the output proposal that has not passed the\n // finalization period.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(block.timestamp + 1),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\"OptimismPortal: output proposal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction fails because the target reverts,\n // and emits the WithdrawalFinalized event with success=false.\n function test_finalizeWithdrawalTransaction_targetFails_fails() external {\n uint256 bobBalanceBefore = address(bob).balance;\n vm.etch(bob, hex\"fe\"); // Contract with just the invalid opcode.\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, false);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the finalization period has not yet passed.\n function test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() external {\n // Setup the Oracle to return an output with a recent timestamp\n uint256 recentTimestamp = block.timestamp - 1000;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(recentTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has already been finalized.\n function test_finalizeWithdrawalTransaction_onReplay_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if insufficient gas is supplied.\n function test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() external {\n // This number was identified through trial and error.\n uint256 gasLimit = 150_000;\n Types.WithdrawalTransaction memory insufficientGasTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: gasLimit,\n data: hex\"\"\n });\n\n // Get updated proof inputs.\n (bytes32 stateRoot, bytes32 storageRoot, , , bytes[] memory withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(insufficientGasTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n Hashing.hashOutputRootProof(outputRootProof),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n insufficientGasTx,\n _proposedOutputIndex,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectRevert(\"SafeCall: Not enough gas\");\n op.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if a sub-call attempts to finalize another\n // withdrawal.\n function test_finalizeWithdrawalTransaction_onReentrancy_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Copy and modify the default test values to attempt a reentrant call by first calling to\n // this contract's callPortalAndExpectRevert() function above.\n Types.WithdrawalTransaction memory _testTx = _defaultTx;\n _testTx.target = address(this);\n _testTx.data = abi.encodeWithSelector(this.callPortalAndExpectRevert.selector);\n\n // Get modified proof inputs.\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_testTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n // Setup the Oracle to return the outputRoot we want as well as a finalized timestamp.\n uint256 finalizedTimestamp = block.timestamp - oracle.FINALIZATION_PERIOD_SECONDS() - 1;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n outputRoot,\n uint128(finalizedTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(withdrawalHash, alice, address(this));\n op.proveWithdrawalTransaction(\n _testTx,\n _proposedBlockNumber,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectCall(address(this), _testTx.data);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_testTx);\n\n // Ensure that bob's balance was not changed by the reentrant call.\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n function testDiff_finalizeWithdrawalTransaction_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n vm.assume(\n _target != address(op) && // Cannot call the optimism portal or a contract\n _target.code.length == 0 && // No accounts with code\n _target != CONSOLE && // The console has no code but behaves like a contract\n uint160(_target) > 9 // No precompiles (or zero address)\n );\n\n // Total ETH supply is currently about 120M ETH.\n uint256 value = bound(_value, 0, 200_000_000 ether);\n vm.deal(address(op), value);\n\n uint256 gasLimit = bound(_gasLimit, 0, 50_000_000);\n uint256 nonce = messagePasser.messageNonce();\n\n // Get a withdrawal transaction and mock proof from the differential testing script.\n Types.WithdrawalTransaction memory _tx = Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: value,\n gasLimit: gasLimit,\n data: _data\n });\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_tx);\n\n // Create the output root proof\n Types.OutputRootProof memory proof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n\n // Ensure the values returned from ffi are correct\n assertEq(outputRoot, Hashing.hashOutputRootProof(proof));\n assertEq(withdrawalHash, Hashing.hashWithdrawal(_tx));\n\n // Setup the Oracle to return the outputRoot\n vm.mockCall(\n address(oracle),\n abi.encodeWithSelector(oracle.getL2Output.selector),\n abi.encode(outputRoot, block.timestamp, 100)\n );\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _tx,\n 100, // l2BlockNumber\n proof,\n withdrawalProof\n );\n (bytes32 _root, , ) = op.provenWithdrawals(withdrawalHash);\n assertTrue(_root != bytes32(0));\n\n // Warp past the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Finalize the withdrawal transaction\n vm.expectCallMinGas(_tx.target, _tx.value, uint64(_tx.gasLimit), _tx.data);\n op.finalizeWithdrawalTransaction(_tx);\n assertTrue(op.finalizedWithdrawals(withdrawalHash));\n }\n}\n\ncontract OptimismPortalUpgradeable_Test is Portal_Initializer {\n Proxy internal proxy;\n uint64 initialBlockNum;\n\n function setUp() public override {\n super.setUp();\n initialBlockNum = uint64(block.number);\n proxy = Proxy(payable(address(op)));\n }\n\n function test_params_initValuesOnProxy_succeeds() external {\n OptimismPortal p = OptimismPortal(payable(address(proxy)));\n\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = p.params();\n\n ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig();\n assertEq(prevBaseFee, rcfg.minimumBaseFee);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_initialize_cannotInitProxy_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(payable(proxy)).initialize(false);\n }\n\n function test_initialize_cannotInitImpl_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(opImpl).initialize(false);\n }\n\n function test_upgradeToAndCall_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(op), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(op), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(op)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n\n/**\n * @title OptimismPortalResourceFuzz_Test\n * @dev Test various values of the resource metering config to ensure that deposits cannot be\n * broken by changing the config.\n */\ncontract OptimismPortalResourceFuzz_Test is Portal_Initializer {\n /**\n * @dev The max gas limit observed throughout this test. Setting this too high can cause\n * the test to take too long to run.\n */\n uint256 constant MAX_GAS_LIMIT = 30_000_000;\n\n /**\n * @dev Test that various values of the resource metering config will not break deposits.\n */\n function testFuzz_systemConfigDeposit_succeeds(\n uint32 _maxResourceLimit,\n uint8 _elasticityMultiplier,\n uint8 _baseFeeMaxChangeDenominator,\n uint32 _minimumBaseFee,\n uint32 _systemTxMaxGas,\n uint128 _maximumBaseFee,\n uint64 _gasLimit,\n uint64 _prevBoughtGas,\n uint128 _prevBaseFee,\n uint8 _blockDiff\n ) external {\n // Get the set system gas limit\n uint64 gasLimit = systemConfig.gasLimit();\n // Bound resource config\n _maxResourceLimit = uint32(bound(_maxResourceLimit, 21000, MAX_GAS_LIMIT / 8));\n _gasLimit = uint64(bound(_gasLimit, 21000, _maxResourceLimit));\n _prevBaseFee = uint128(bound(_prevBaseFee, 0, 3 gwei));\n // Prevent values that would cause reverts\n vm.assume(gasLimit >= _gasLimit);\n vm.assume(_minimumBaseFee < _maximumBaseFee);\n vm.assume(_baseFeeMaxChangeDenominator > 1);\n vm.assume(uint256(_maxResourceLimit) + uint256(_systemTxMaxGas) <= gasLimit);\n vm.assume(_elasticityMultiplier > 0);\n vm.assume(\n ((_maxResourceLimit / _elasticityMultiplier) * _elasticityMultiplier) ==\n _maxResourceLimit\n );\n _prevBoughtGas = uint64(bound(_prevBoughtGas, 0, _maxResourceLimit - _gasLimit));\n _blockDiff = uint8(bound(_blockDiff, 0, 3));\n\n // Create a resource config to mock the call to the system config with\n ResourceMetering.ResourceConfig memory rcfg = ResourceMetering.ResourceConfig({\n maxResourceLimit: _maxResourceLimit,\n elasticityMultiplier: _elasticityMultiplier,\n baseFeeMaxChangeDenominator: _baseFeeMaxChangeDenominator,\n minimumBaseFee: _minimumBaseFee,\n systemTxMaxGas: _systemTxMaxGas,\n maximumBaseFee: _maximumBaseFee\n });\n vm.mockCall(\n address(systemConfig),\n abi.encodeWithSelector(systemConfig.resourceConfig.selector),\n abi.encode(rcfg)\n );\n\n // Set the resource params\n uint256 _prevBlockNum = block.number - _blockDiff;\n vm.store(\n address(op),\n bytes32(uint256(1)),\n bytes32((_prevBlockNum << 192) | (uint256(_prevBoughtGas) << 128) | _prevBaseFee)\n );\n // Ensure that the storage setting is correct\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = op.params();\n assertEq(prevBaseFee, _prevBaseFee);\n assertEq(prevBoughtGas, _prevBoughtGas);\n assertEq(prevBlockNum, _prevBlockNum);\n\n // Do a deposit, should not revert\n op.depositTransaction{ gas: MAX_GAS_LIMIT }({\n _to: address(0x20),\n _value: 0x40,\n _gasLimit: _gasLimit,\n _isCreation: false,\n _data: hex\"\"\n });\n }\n}\n" - }, - "contracts/test/Proxy.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract SimpleStorage {\n mapping(uint256 => uint256) internal store;\n\n function get(uint256 key) external payable returns (uint256) {\n return store[key];\n }\n\n function set(uint256 key, uint256 value) external payable {\n store[key] = value;\n }\n}\n\ncontract Clasher {\n function upgradeTo(address) external pure {\n revert(\"upgradeTo\");\n }\n}\n\ncontract Proxy_Test is Test {\n event Upgraded(address indexed implementation);\n event AdminChanged(address previousAdmin, address newAdmin);\n\n address alice = address(64);\n\n bytes32 internal constant IMPLEMENTATION_KEY =\n bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1);\n\n bytes32 internal constant OWNER_KEY = bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1);\n\n Proxy proxy;\n SimpleStorage simpleStorage;\n\n function setUp() external {\n // Deploy a proxy and simple storage contract as\n // the implementation\n proxy = new Proxy(alice);\n simpleStorage = new SimpleStorage();\n\n vm.prank(alice);\n proxy.upgradeTo(address(simpleStorage));\n }\n\n function test_implementationKey_succeeds() external {\n // The hardcoded implementation key should be correct\n vm.prank(alice);\n proxy.upgradeTo(address(6));\n\n bytes32 key = vm.load(address(proxy), IMPLEMENTATION_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(6));\n }\n\n function test_ownerKey_succeeds() external {\n // The hardcoded owner key should be correct\n vm.prank(alice);\n proxy.changeAdmin(address(6));\n\n bytes32 key = vm.load(address(proxy), OWNER_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(address(6));\n address owner = proxy.admin();\n assertEq(owner, address(6));\n }\n\n function test_proxyCallToImp_notAdmin_succeeds() external {\n // The implementation does not have a `upgradeTo`\n // method, calling `upgradeTo` not as the owner\n // should revert.\n vm.expectRevert();\n proxy.upgradeTo(address(64));\n\n // Call `upgradeTo` as the owner, it should succeed\n // and emit the `Upgraded` event.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(64));\n vm.prank(alice);\n proxy.upgradeTo(address(64));\n\n // Get the implementation as the owner\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(64));\n }\n\n function test_ownerProxyCall_notAdmin_succeeds() external {\n // Calling `changeAdmin` not as the owner should revert\n // as the implementation does not have a `changeAdmin` method.\n vm.expectRevert();\n proxy.changeAdmin(address(1));\n\n // Call `changeAdmin` as the owner, it should succeed\n // and emit the `AdminChanged` event.\n vm.expectEmit(true, true, true, true);\n emit AdminChanged(alice, address(1));\n vm.prank(alice);\n proxy.changeAdmin(address(1));\n\n // Calling `admin` not as the owner should\n // revert as the implementation does not have\n // a `admin` method.\n vm.expectRevert();\n proxy.admin();\n\n // Calling `admin` as the owner should work.\n vm.prank(address(1));\n address owner = proxy.admin();\n assertEq(owner, address(1));\n }\n\n function test_delegatesToImpl_succeeds() external {\n // Call the storage setter on the proxy\n SimpleStorage(address(proxy)).set(1, 1);\n\n // The key should not be set in the implementation\n uint256 result = simpleStorage.get(1);\n assertEq(result, 0);\n {\n // The key should be set in the proxy\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n\n {\n // The owner should be able to call through the proxy\n // when there is not a function selector crash\n vm.prank(alice);\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n }\n\n function test_upgradeToAndCall_succeeds() external {\n {\n // There should be nothing in the current proxy storage\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 0);\n }\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(simpleStorage));\n vm.prank(alice);\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The call should have impacted the state\n uint256 result = SimpleStorage(address(proxy)).get(1);\n assertEq(result, 1);\n }\n\n function test_upgradeToAndCall_functionDoesNotExist_reverts() external {\n // Get the current implementation address\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call. This reverts because the calldata doesn't\n // match a function on the implementation.\n vm.expectRevert(\"Proxy: delegatecall to new implementation contract failed\");\n vm.prank(alice);\n proxy.upgradeToAndCall(address(simpleStorage), hex\"\");\n\n // The implementation address should have not\n // updated because the call to `upgradeToAndCall`\n // reverted.\n vm.prank(alice);\n address postImpl = proxy.implementation();\n assertEq(impl, postImpl);\n\n // The attempt to `upgradeToAndCall`\n // should revert when it is not called by the owner.\n vm.expectRevert();\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n }\n\n function test_upgradeToAndCall_isPayable_succeeds() external {\n // Give alice some funds\n vm.deal(alice, 1 ether);\n // Set the implementation and call and send\n // value.\n vm.prank(alice);\n proxy.upgradeToAndCall{ value: 1 ether }(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The implementation address should be correct\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // The proxy should have a balance\n assertEq(address(proxy).balance, 1 ether);\n }\n\n function test_upgradeTo_clashingFunctionSignatures_succeeds() external {\n // Clasher has a clashing function with the proxy.\n Clasher clasher = new Clasher();\n\n // Set the clasher as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(clasher));\n\n {\n // Assert that the implementation was set properly.\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(clasher));\n }\n\n // Call the clashing function on the proxy\n // not as the owner so that the call passes through.\n // The implementation will revert so we can be\n // sure that the call passed through.\n vm.expectRevert(bytes(\"upgradeTo\"));\n proxy.upgradeTo(address(0));\n\n {\n // Now call the clashing function as the owner\n // and be sure that it doesn't pass through to\n // the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(0));\n }\n }\n\n // Allow for `eth_call` to call proxy methods\n // by setting \"from\" to `address(0)`.\n function test_implementation_zeroAddressCaller_succeeds() external {\n vm.prank(address(0));\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n }\n\n function test_implementation_isZeroAddress_reverts() external {\n // Set `address(0)` as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n\n (bool success, bytes memory returndata) = address(proxy).call(hex\"\");\n assertEq(success, false);\n\n bytes memory err = abi.encodeWithSignature(\n \"Error(string)\",\n \"Proxy: implementation not initialized\"\n );\n\n assertEq(returndata, err);\n }\n}\n" - }, - "contracts/test/ProxyAdmin.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { SimpleStorage } from \"./Proxy.t.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\n\ncontract ProxyAdmin_Test is Test {\n address alice = address(64);\n\n Proxy proxy;\n L1ChugSplashProxy chugsplash;\n ResolvedDelegateProxy resolved;\n\n AddressManager addressManager;\n\n ProxyAdmin admin;\n\n SimpleStorage implementation;\n\n function setUp() external {\n // Deploy the proxy admin\n admin = new ProxyAdmin(alice);\n // Deploy the standard proxy\n proxy = new Proxy(address(admin));\n\n // Deploy the legacy L1ChugSplashProxy with the admin as the owner\n chugsplash = new L1ChugSplashProxy(address(admin));\n\n // Deploy the legacy AddressManager\n addressManager = new AddressManager();\n // The proxy admin must be the new owner of the address manager\n addressManager.transferOwnership(address(admin));\n // Deploy a legacy ResolvedDelegateProxy with the name `a`.\n // Whatever `a` is set to in AddressManager will be the address\n // that is used for the implementation.\n resolved = new ResolvedDelegateProxy(addressManager, \"a\");\n\n // Impersonate alice for setting up the admin.\n vm.startPrank(alice);\n // Set the address of the address manager in the admin so that it\n // can resolve the implementation address of legacy\n // ResolvedDelegateProxy based proxies.\n admin.setAddressManager(addressManager);\n // Set the reverse lookup of the ResolvedDelegateProxy\n // proxy\n admin.setImplementationName(address(resolved), \"a\");\n\n // Set the proxy types\n admin.setProxyType(address(proxy), ProxyAdmin.ProxyType.ERC1967);\n admin.setProxyType(address(chugsplash), ProxyAdmin.ProxyType.CHUGSPLASH);\n admin.setProxyType(address(resolved), ProxyAdmin.ProxyType.RESOLVED);\n vm.stopPrank();\n\n implementation = new SimpleStorage();\n }\n\n function test_setImplementationName_succeeds() external {\n vm.prank(alice);\n admin.setImplementationName(address(1), \"foo\");\n assertEq(admin.implementationName(address(1)), \"foo\");\n }\n\n function test_setAddressManager_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setAddressManager(AddressManager((address(0))));\n }\n\n function test_setImplementationName_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setImplementationName(address(0), \"foo\");\n }\n\n function test_setProxyType_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setProxyType(address(0), ProxyAdmin.ProxyType.CHUGSPLASH);\n }\n\n function test_owner_succeeds() external {\n assertEq(admin.owner(), alice);\n }\n\n function test_proxyType_succeeds() external {\n assertEq(uint256(admin.proxyType(address(proxy))), uint256(ProxyAdmin.ProxyType.ERC1967));\n assertEq(\n uint256(admin.proxyType(address(chugsplash))),\n uint256(ProxyAdmin.ProxyType.CHUGSPLASH)\n );\n assertEq(\n uint256(admin.proxyType(address(resolved))),\n uint256(ProxyAdmin.ProxyType.RESOLVED)\n );\n }\n\n function test_erc1967GetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(proxy));\n }\n\n function test_chugsplashGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(resolved));\n }\n\n function getProxyImplementation(address payable _proxy) internal {\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(0));\n }\n\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n }\n\n function test_erc1967GetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(resolved));\n }\n\n function getProxyAdmin(address payable _proxy) internal {\n address owner = admin.getProxyAdmin(_proxy);\n assertEq(owner, address(admin));\n }\n\n function test_erc1967ChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(resolved));\n }\n\n function changeProxyAdmin(address payable _proxy) internal {\n ProxyAdmin.ProxyType proxyType = admin.proxyType(address(_proxy));\n\n vm.prank(alice);\n admin.changeProxyAdmin(_proxy, address(128));\n\n // The proxy is no longer the admin and can\n // no longer call the proxy interface except for\n // the ResolvedDelegate type on which anybody can\n // call the admin interface.\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n vm.expectRevert(\"Proxy: implementation not initialized\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n vm.expectRevert(\"L1ChugSplashProxy: implementation is not set yet\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n // Just an empty block to show that all cases are covered\n } else {\n vm.expectRevert(\"ProxyAdmin: unknown proxy type\");\n }\n\n // Call the proxy contract directly to get the admin.\n // Different proxy types have different interfaces.\n vm.prank(address(128));\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n assertEq(Proxy(payable(_proxy)).admin(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n assertEq(L1ChugSplashProxy(payable(_proxy)).getOwner(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n assertEq(addressManager.owner(), address(128));\n } else {\n assert(false);\n }\n }\n\n function test_erc1967Upgrade_succeeds() external {\n upgrade(payable(proxy));\n }\n\n function test_chugsplashUpgrade_succeeds() external {\n upgrade(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgrade_succeeds() external {\n upgrade(payable(resolved));\n }\n\n function upgrade(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n\n function test_erc1967UpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(proxy));\n }\n\n function test_chugsplashUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(resolved));\n }\n\n function upgradeAndCall(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgradeAndCall(\n _proxy,\n address(implementation),\n abi.encodeWithSelector(SimpleStorage.set.selector, 1, 1)\n );\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n\n uint256 got = SimpleStorage(address(_proxy)).get(1);\n assertEq(got, 1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.changeProxyAdmin(payable(proxy), address(0));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgrade(payable(proxy), address(implementation));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgradeAndCall(payable(proxy), address(implementation), hex\"\");\n }\n\n function test_isUpgrading_succeeds() external {\n assertEq(false, admin.isUpgrading());\n\n vm.prank(alice);\n admin.setUpgrading(true);\n assertEq(true, admin.isUpgrading());\n }\n}\n" - }, - "contracts/test/RLP.t.sol": { - "content": "// SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\n/**\n * @title LibRLP\n * @notice Via https://github.com/Rari-Capital/solmate/issues/207.\n */\nlibrary LibRLP {\n using Bytes32AddressLib for bytes32;\n\n function computeAddress(address deployer, uint256 nonce) internal pure returns (address) {\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80)))\n .fromLast20Bytes();\n if (nonce <= 0x7f)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce)))\n .fromLast20Bytes();\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= type(uint8).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd7),\n bytes1(0x94),\n deployer,\n bytes1(0x81),\n uint8(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint16).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd8),\n bytes1(0x94),\n deployer,\n bytes1(0x82),\n uint16(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint24).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd9),\n bytes1(0x94),\n deployer,\n bytes1(0x83),\n uint24(nonce)\n )\n ).fromLast20Bytes();\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return\n keccak256(\n abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))\n ).fromLast20Bytes();\n }\n}\n" - }, - "contracts/test/RLPReader.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { RLPReader } from \"../libraries/rlp/RLPReader.sol\";\n\ncontract RLPReader_readBytes_Test is CommonTest {\n function test_readBytes_bytestring00_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"00\"), hex\"00\");\n }\n\n function test_readBytes_bytestring01_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"01\"), hex\"01\");\n }\n\n function test_readBytes_bytestring7f_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"7f\"), hex\"7f\");\n }\n\n function test_readBytes_revertListItem_reverts() external {\n vm.expectRevert(\"RLPReader: decoded item type for bytes is not a data item\");\n RLPReader.readBytes(hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_readBytes_invalidStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n RLPReader.readBytes(hex\"b9\");\n }\n\n function test_readBytes_invalidListLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n RLPReader.readBytes(hex\"ff\");\n }\n\n function test_readBytes_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: bytes value contains an invalid remainder\");\n RLPReader.readBytes(hex\"800a\");\n }\n\n function test_readBytes_invalidPrefix_reverts() external {\n vm.expectRevert(\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n RLPReader.readBytes(hex\"810a\");\n }\n}\n\ncontract RLPReader_readList_Test is CommonTest {\n function test_readList_empty_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c0\");\n assertEq(list.length, 0);\n }\n\n function test_readList_multiList_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c6827a77c10401\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"827a77\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c104\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"01\");\n }\n\n function test_readList_shortListMax1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n\n assertEq(list.length, 11);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[4]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[5]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[6]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[7]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[8]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[9]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[10]), hex\"8471776572\");\n }\n\n function test_readList_longList1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n\n assertEq(list.length, 4);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"cf84617364668471776572847a786376\");\n }\n\n function test_readList_longList2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n assertEq(list.length, 32);\n\n for (uint256 i = 0; i < 32; i++) {\n assertEq(RLPReader.readRawBytes(list[i]), hex\"cf84617364668471776572847a786376\");\n }\n }\n\n function test_readList_listLongerThan32Elements_reverts() external {\n vm.expectRevert(stdError.indexOOBError);\n RLPReader.readList(\n hex\"e1454545454545454545454545454545454545454545454545454545454545454545\"\n );\n }\n\n function test_readList_listOfLists_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c4c2c0c0c0\");\n assertEq(list.length, 2);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c2c0c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c0\");\n }\n\n function test_readList_listOfLists2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c7c0c1c0c3c0c1c0\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c1c0\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"c3c0c1c0\");\n }\n\n function test_readList_dictTest1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n assertEq(list.length, 4);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"ca846b6579318476616c31\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"ca846b6579328476616c32\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"ca846b6579338476616c33\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"ca846b6579348476616c34\");\n }\n\n function test_readList_invalidShortList_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efdebd\");\n }\n\n function test_readList_longStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efb83600\");\n }\n\n function test_readList_notLongEnough_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(\n hex\"efdebdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n );\n }\n\n function test_readList_int32Overflow_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"bf0f000000000000021111\");\n }\n\n function test_readList_int32Overflow2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ff0f000000000000021111\");\n }\n\n function test_readList_incorrectLengthInArray_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b9002100dc2b275d0f74e8a53e6f4ec61b27f24278820be3f82ea2110e582081b0565df0\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b90040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(hex\"b800\");\n }\n\n function test_readList_leadingZerosInLongLengthList1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must not have any leading zeros (long list)\");\n RLPReader.readList(\n hex\"fb00000040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_nonOptimalLongLengthArray1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b81000112233445566778899aabbccddeeff\");\n }\n\n function test_readList_nonOptimalLongLengthArray2_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b801ff\");\n }\n\n function test_readList_invalidValue_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n RLPReader.readList(hex\"91\");\n }\n\n function test_readList_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n RLPReader.readList(hex\"c000\");\n }\n\n function test_readList_notEnoughContentForString1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"ba010000aabbccddeeff\");\n }\n\n function test_readList_notEnoughContentForString2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"b840ffeeddccbbaa99887766554433221100\");\n }\n\n function test_readList_notEnoughContentForList1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"f90180\");\n }\n\n function test_readList_notEnoughContentForList2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ffffffffffffffffff0001020304050607\");\n }\n\n function test_readList_longStringLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b80100\");\n }\n\n function test_readList_longListLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long list)\");\n RLPReader.readList(hex\"f80100\");\n }\n}\n" - }, - "contracts/test/RLPWriter.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { RLPWriter } from \"../libraries/rlp/RLPWriter.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\n\ncontract RLPWriter_writeString_Test is CommonTest {\n function test_writeString_empty_succeeds() external {\n assertEq(RLPWriter.writeString(\"\"), hex\"80\");\n }\n\n function test_writeString_bytestring00_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0000\"), hex\"00\");\n }\n\n function test_writeString_bytestring01_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0001\"), hex\"01\");\n }\n\n function test_writeString_bytestring7f_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u007F\"), hex\"7f\");\n }\n\n function test_writeString_shortstring_succeeds() external {\n assertEq(RLPWriter.writeString(\"dog\"), hex\"83646f67\");\n }\n\n function test_writeString_shortstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing eli\"),\n hex\"b74c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c69\"\n );\n }\n\n function test_writeString_longstring_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing elit\"),\n hex\"b8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974\"\n );\n }\n\n function test_writeString_longstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\n \"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\"\n ),\n hex\"b904004c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20437572616269747572206d6175726973206d61676e612c20737573636970697420736564207665686963756c61206e6f6e2c20696163756c697320666175636962757320746f72746f722e2050726f696e20737573636970697420756c74726963696573206d616c6573756164612e204475697320746f72746f7220656c69742c2064696374756d2071756973207472697374697175652065752c20756c7472696365732061742072697375732e204d6f72626920612065737420696d70657264696574206d6920756c6c616d636f7270657220616c6971756574207375736369706974206e6563206c6f72656d2e2041656e65616e2071756973206c656f206d6f6c6c69732c2076756c70757461746520656c6974207661726975732c20636f6e73657175617420656e696d2e204e756c6c6120756c74726963657320747572706973206a7573746f2c20657420706f73756572652075726e6120636f6e7365637465747572206e65632e2050726f696e206e6f6e20636f6e76616c6c6973206d657475732e20446f6e65632074656d706f7220697073756d20696e206d617572697320636f6e67756520736f6c6c696369747564696e2e20566573746962756c756d20616e746520697073756d207072696d697320696e206661756369627573206f726369206c756374757320657420756c74726963657320706f737565726520637562696c69612043757261653b2053757370656e646973736520636f6e76616c6c69732073656d2076656c206d617373612066617563696275732c2065676574206c6163696e6961206c616375732074656d706f722e204e756c6c61207175697320756c747269636965732070757275732e2050726f696e20617563746f722072686f6e637573206e69626820636f6e64696d656e74756d206d6f6c6c69732e20416c697175616d20636f6e73657175617420656e696d206174206d65747573206c75637475732c206120656c656966656e6420707572757320656765737461732e20437572616269747572206174206e696268206d657475732e204e616d20626962656e64756d2c206e6571756520617420617563746f72207472697374697175652c206c6f72656d206c696265726f20616c697175657420617263752c206e6f6e20696e74657264756d2074656c6c7573206c65637475732073697420616d65742065726f732e20437261732072686f6e6375732c206d65747573206163206f726e617265206375727375732c20646f6c6f72206a7573746f20756c747269636573206d657475732c20617420756c6c616d636f7270657220766f6c7574706174\"\n );\n }\n}\n\ncontract RLPWriter_writeUint_Test is CommonTest {\n function test_writeUint_zero_succeeds() external {\n assertEq(RLPWriter.writeUint(0x0), hex\"80\");\n }\n\n function test_writeUint_smallint_succeeds() external {\n assertEq(RLPWriter.writeUint(1), hex\"01\");\n }\n\n function test_writeUint_smallint2_succeeds() external {\n assertEq(RLPWriter.writeUint(16), hex\"10\");\n }\n\n function test_writeUint_smallint3_succeeds() external {\n assertEq(RLPWriter.writeUint(79), hex\"4f\");\n }\n\n function test_writeUint_smallint4_succeeds() external {\n assertEq(RLPWriter.writeUint(127), hex\"7f\");\n }\n\n function test_writeUint_mediumint_succeeds() external {\n assertEq(RLPWriter.writeUint(128), hex\"8180\");\n }\n\n function test_writeUint_mediumint2_succeeds() external {\n assertEq(RLPWriter.writeUint(1000), hex\"8203e8\");\n }\n\n function test_writeUint_mediumint3_succeeds() external {\n assertEq(RLPWriter.writeUint(100000), hex\"830186a0\");\n }\n}\n\ncontract RLPWriter_writeList_Test is CommonTest {\n function test_writeList_empty_succeeds() external {\n assertEq(RLPWriter.writeList(new bytes[](0)), hex\"c0\");\n }\n\n function test_writeList_stringList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeString(\"dog\");\n list[1] = RLPWriter.writeString(\"god\");\n list[2] = RLPWriter.writeString(\"cat\");\n\n assertEq(RLPWriter.writeList(list), hex\"cc83646f6783676f6483636174\");\n }\n\n function test_writeList_multiList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeUint(4);\n\n list[0] = RLPWriter.writeString(\"zw\");\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeUint(1);\n\n assertEq(RLPWriter.writeList(list), hex\"c6827a77c10401\");\n }\n\n function test_writeList_shortListMax1_succeeds() external {\n bytes[] memory list = new bytes[](11);\n list[0] = RLPWriter.writeString(\"asdf\");\n list[1] = RLPWriter.writeString(\"qwer\");\n list[2] = RLPWriter.writeString(\"zxcv\");\n list[3] = RLPWriter.writeString(\"asdf\");\n list[4] = RLPWriter.writeString(\"qwer\");\n list[5] = RLPWriter.writeString(\"zxcv\");\n list[6] = RLPWriter.writeString(\"asdf\");\n list[7] = RLPWriter.writeString(\"qwer\");\n list[8] = RLPWriter.writeString(\"zxcv\");\n list[9] = RLPWriter.writeString(\"asdf\");\n list[10] = RLPWriter.writeString(\"qwer\");\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n }\n\n function test_writeList_longlist1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list2);\n list[3] = RLPWriter.writeList(list2);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_longlist2_succeeds() external {\n bytes[] memory list = new bytes[](32);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n for (uint256 i = 0; i < 32; i++) {\n list[i] = RLPWriter.writeList(list2);\n }\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_listoflists_succeeds() external {\n // [ [ [], [] ], [] ]\n bytes[] memory list = new bytes[](2);\n bytes[] memory list2 = new bytes[](2);\n\n list2[0] = RLPWriter.writeList(new bytes[](0));\n list2[1] = RLPWriter.writeList(new bytes[](0));\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(new bytes[](0));\n\n assertEq(RLPWriter.writeList(list), hex\"c4c2c0c0c0\");\n }\n\n function test_writeList_listoflists2_succeeds() external {\n // [ [], [[]], [ [], [[]] ] ]\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeList(new bytes[](0));\n\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeList(new bytes[](0));\n\n list[1] = RLPWriter.writeList(list2);\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeList(new bytes[](0));\n list3[1] = RLPWriter.writeList(list2);\n\n list[2] = RLPWriter.writeList(list3);\n\n assertEq(RLPWriter.writeList(list), hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_writeList_dictTest1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n\n bytes[] memory list1 = new bytes[](2);\n list1[0] = RLPWriter.writeString(\"key1\");\n list1[1] = RLPWriter.writeString(\"val1\");\n\n bytes[] memory list2 = new bytes[](2);\n list2[0] = RLPWriter.writeString(\"key2\");\n list2[1] = RLPWriter.writeString(\"val2\");\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeString(\"key3\");\n list3[1] = RLPWriter.writeString(\"val3\");\n\n bytes[] memory list4 = new bytes[](2);\n list4[0] = RLPWriter.writeString(\"key4\");\n list4[1] = RLPWriter.writeString(\"val4\");\n\n list[0] = RLPWriter.writeList(list1);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list3);\n list[3] = RLPWriter.writeList(list4);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n }\n}\n" - }, - "contracts/test/ResolvedDelegateProxy.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\n\ncontract ResolvedDelegateProxy_Test is Test {\n AddressManager internal addressManager;\n SimpleImplementation internal impl;\n SimpleImplementation internal proxy;\n\n function setUp() public {\n // Set up the address manager.\n addressManager = new AddressManager();\n impl = new SimpleImplementation();\n addressManager.setAddress(\"SimpleImplementation\", address(impl));\n\n // Set up the proxy.\n proxy = SimpleImplementation(\n address(new ResolvedDelegateProxy(addressManager, \"SimpleImplementation\"))\n );\n }\n\n // Tests that the proxy properly bubbles up returndata when the delegatecall succeeds.\n function testFuzz_fallback_delegateCallFoo_succeeds(uint256 x) public {\n vm.expectCall(address(impl), abi.encodeWithSelector(impl.foo.selector, x));\n assertEq(proxy.foo(x), x);\n }\n\n // Tests that the proxy properly bubbles up returndata when the delegatecall reverts.\n function test_fallback_delegateCallBar_reverts() public {\n vm.expectRevert(\"SimpleImplementation: revert\");\n vm.expectCall(address(impl), abi.encodeWithSelector(impl.bar.selector));\n proxy.bar();\n }\n\n // Tests that the proxy fallback reverts as expected if the implementation within the\n // address manager is not set.\n function test_fallback_addressManagerNotSet_reverts() public {\n AddressManager am = new AddressManager();\n SimpleImplementation p = SimpleImplementation(\n address(new ResolvedDelegateProxy(am, \"SimpleImplementation\"))\n );\n\n vm.expectRevert(\"ResolvedDelegateProxy: target address must be initialized\");\n p.foo(0);\n }\n}\n\ncontract SimpleImplementation {\n function foo(uint256 _x) public pure returns (uint256) {\n return _x;\n }\n\n function bar() public pure {\n revert(\"SimpleImplementation: revert\");\n }\n}\n" - }, - "contracts/test/ResourceMetering.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract MeterUser is ResourceMetering {\n ResourceMetering.ResourceConfig public innerConfig;\n\n constructor() {\n initialize();\n innerConfig = Constants.DEFAULT_RESOURCE_CONFIG();\n }\n\n function initialize() public initializer {\n __ResourceMetering_init();\n }\n\n function resourceConfig() public view returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig();\n }\n\n function _resourceConfig()\n internal\n view\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return innerConfig;\n }\n\n function use(uint64 _amount) public metered(_amount) {}\n\n function set(\n uint128 _prevBaseFee,\n uint64 _prevBoughtGas,\n uint64 _prevBlockNum\n ) public {\n params = ResourceMetering.ResourceParams({\n prevBaseFee: _prevBaseFee,\n prevBoughtGas: _prevBoughtGas,\n prevBlockNum: _prevBlockNum\n });\n }\n\n function setParams(ResourceMetering.ResourceConfig memory newConfig) public {\n innerConfig = newConfig;\n }\n}\n\n/**\n * @title ResourceConfig\n * @notice The tests are based on the default config values. It is expected that\n * the config values used in these tests are ran in production.\n */\ncontract ResourceMetering_Test is Test {\n MeterUser internal meter;\n uint64 initialBlockNum;\n\n function setUp() public {\n meter = new MeterUser();\n initialBlockNum = uint64(block.number);\n }\n\n function test_meter_initialResourceParams_succeeds() external {\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n\n assertEq(prevBaseFee, rcfg.minimumBaseFee);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_updateParamsNoChange_succeeds() external {\n meter.use(0); // equivalent to just updating the base fee and block number\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n meter.use(0);\n (uint128 postBaseFee, uint64 postBoughtGas, uint64 postBlockNum) = meter.params();\n\n assertEq(postBaseFee, prevBaseFee);\n assertEq(postBoughtGas, prevBoughtGas);\n assertEq(postBlockNum, prevBlockNum);\n }\n\n function test_meter_updateOneEmptyBlock_succeeds() external {\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 1);\n }\n\n function test_meter_updateTwoEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 2);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 2);\n }\n\n function test_meter_updateTenEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 10);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 10);\n }\n\n function test_meter_updateNoGasDelta_succeeds() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint256 target = uint256(rcfg.maxResourceLimit) / uint256(rcfg.elasticityMultiplier);\n meter.use(uint64(target));\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1000000000);\n assertEq(prevBoughtGas, target);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_useMax_succeeds() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n meter.use(target * elasticityMultiplier);\n\n (, uint64 prevBoughtGas, ) = meter.params();\n assertEq(prevBoughtGas, target * elasticityMultiplier);\n\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 postBaseFee, , ) = meter.params();\n assertEq(postBaseFee, 2125000000);\n }\n\n /**\n * @notice This tests that the metered modifier reverts if\n * the ResourceConfig baseFeeMaxChangeDenominator\n * is set to 1.\n * Since the metered modifier internally calls\n * solmate's powWad function, it will revert\n * with the error string \"UNDEFINED\" since the\n * first parameter will be computed as 0.\n */\n function test_meter_denominatorEq1_reverts() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n rcfg.baseFeeMaxChangeDenominator = 1;\n meter.setParams(rcfg);\n meter.use(target * elasticityMultiplier);\n\n (, uint64 prevBoughtGas, ) = meter.params();\n assertEq(prevBoughtGas, target * elasticityMultiplier);\n\n vm.roll(initialBlockNum + 2);\n\n vm.expectRevert(\"UNDEFINED\");\n meter.use(0);\n }\n\n function test_meter_useMoreThanMax_reverts() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n vm.expectRevert(\"ResourceMetering: cannot buy more gas than available gas limit\");\n meter.use(target * elasticityMultiplier + 1);\n }\n\n // Demonstrates that the resource metering arithmetic can tolerate very large gaps between\n // deposits.\n function testFuzz_meter_largeBlockDiff_succeeds(uint64 _amount, uint256 _blockDiff) external {\n // This test fails if the following line is commented out.\n // At 12 seconds per block, this number is effectively unreachable.\n vm.assume(_blockDiff < 433576281058164217753225238677900874458691);\n\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n vm.assume(_amount < target * elasticityMultiplier);\n vm.roll(initialBlockNum + _blockDiff);\n meter.use(_amount);\n }\n}\n\n/**\n * @title CustomMeterUser\n * @notice A simple wrapper around `ResourceMetering` that allows the initial\n * params to be set in the constructor.\n */\ncontract CustomMeterUser is ResourceMetering {\n uint256 public startGas;\n uint256 public endGas;\n\n constructor(\n uint128 _prevBaseFee,\n uint64 _prevBoughtGas,\n uint64 _prevBlockNum\n ) {\n params = ResourceMetering.ResourceParams({\n prevBaseFee: _prevBaseFee,\n prevBoughtGas: _prevBoughtGas,\n prevBlockNum: _prevBlockNum\n });\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return Constants.DEFAULT_RESOURCE_CONFIG();\n }\n\n function use(uint64 _amount) public returns (uint256) {\n uint256 initialGas = gasleft();\n _metered(_amount, initialGas);\n return initialGas - gasleft();\n }\n}\n\n/**\n * @title ArtifactResourceMetering_Test\n * @notice A table test that sets the state of the ResourceParams and then requests\n * various amounts of gas. This test ensures that a wide range of values\n * can safely be used with the `ResourceMetering` contract.\n * It also writes a CSV file to disk that includes useful information\n * about how much gas is used and how expensive it is in USD terms to\n * purchase the deposit gas.\n */\ncontract ArtifactResourceMetering_Test is Test {\n uint128 internal minimumBaseFee;\n uint128 internal maximumBaseFee;\n uint64 internal maxResourceLimit;\n uint64 internal targetResourceLimit;\n\n string internal outfile;\n\n // keccak256(abi.encodeWithSignature(\"Error(string)\", \"ResourceMetering: cannot buy more gas than available gas limit\"))\n bytes32 internal cannotBuyMoreGas =\n 0x84edc668cfd5e050b8999f43ff87a1faaa93e5f935b20bc1dd4d3ff157ccf429;\n // keccak256(abi.encodeWithSignature(\"Panic(uint256)\", 0x11))\n bytes32 internal overflowErr =\n 0x1ca389f2c8264faa4377de9ce8e14d6263ef29c68044a9272d405761bab2db27;\n // keccak256(hex\"\")\n bytes32 internal emptyReturnData =\n 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n\n /**\n * @notice Sets up the tests by getting constants from the ResourceMetering\n * contract.\n */\n function setUp() public {\n vm.roll(1_000_000);\n\n MeterUser base = new MeterUser();\n ResourceMetering.ResourceConfig memory rcfg = base.resourceConfig();\n minimumBaseFee = uint128(rcfg.minimumBaseFee);\n maximumBaseFee = rcfg.maximumBaseFee;\n maxResourceLimit = uint64(rcfg.maxResourceLimit);\n targetResourceLimit = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n\n outfile = string.concat(vm.projectRoot(), \"/.resource-metering.csv\");\n try vm.removeFile(outfile) {} catch {}\n }\n\n /**\n * @notice Generate a CSV file. The call to `meter` should be called with at\n * most the L1 block gas limit. Without specifying the amount of\n * gas, it can take very long to execute.\n */\n function test_meter_generateArtifact_succeeds() external {\n vm.writeLine(\n outfile,\n \"prevBaseFee,prevBoughtGas,prevBlockNumDiff,l1BaseFee,requestedGas,gasConsumed,ethPrice,usdCost,success\"\n );\n\n // prevBaseFee value in ResourceParams\n uint128[] memory prevBaseFees = new uint128[](5);\n prevBaseFees[0] = minimumBaseFee;\n prevBaseFees[1] = maximumBaseFee;\n prevBaseFees[2] = uint128(50 gwei);\n prevBaseFees[3] = uint128(100 gwei);\n prevBaseFees[4] = uint128(200 gwei);\n\n // prevBoughtGas value in ResourceParams\n uint64[] memory prevBoughtGases = new uint64[](1);\n prevBoughtGases[0] = uint64(0);\n\n // prevBlockNum diff, simulates blocks with no deposits when non zero\n uint64[] memory prevBlockNumDiffs = new uint64[](2);\n prevBlockNumDiffs[0] = 0;\n prevBlockNumDiffs[1] = 1;\n\n // The amount of L2 gas that a user requests\n uint64[] memory requestedGases = new uint64[](3);\n requestedGases[0] = maxResourceLimit;\n requestedGases[1] = targetResourceLimit;\n requestedGases[2] = uint64(100_000);\n\n // The L1 base fee\n uint256[] memory l1BaseFees = new uint256[](4);\n l1BaseFees[0] = 1 gwei;\n l1BaseFees[1] = 50 gwei;\n l1BaseFees[2] = 75 gwei;\n l1BaseFees[3] = 100 gwei;\n\n // USD price of 1 ether\n uint256[] memory ethPrices = new uint256[](2);\n ethPrices[0] = 1600;\n ethPrices[1] = 3200;\n\n // Iterate over all of the test values and run a test\n for (uint256 i; i < prevBaseFees.length; i++) {\n for (uint256 j; j < prevBoughtGases.length; j++) {\n for (uint256 k; k < prevBlockNumDiffs.length; k++) {\n for (uint256 l; l < requestedGases.length; l++) {\n for (uint256 m; m < l1BaseFees.length; m++) {\n for (uint256 n; n < ethPrices.length; n++) {\n uint256 snapshotId = vm.snapshot();\n\n uint128 prevBaseFee = prevBaseFees[i];\n uint64 prevBoughtGas = prevBoughtGases[j];\n uint64 prevBlockNumDiff = prevBlockNumDiffs[k];\n uint64 requestedGas = requestedGases[l];\n uint256 l1BaseFee = l1BaseFees[m];\n uint256 ethPrice = ethPrices[n];\n string memory result = \"success\";\n\n vm.fee(l1BaseFee);\n\n CustomMeterUser meter = new CustomMeterUser({\n _prevBaseFee: prevBaseFee,\n _prevBoughtGas: prevBoughtGas,\n _prevBlockNum: uint64(block.number)\n });\n\n vm.roll(block.number + prevBlockNumDiff);\n\n // Call the metering code and catch the various\n // types of errors.\n uint256 gasConsumed = 0;\n try meter.use{ gas: 30_000_000 }(requestedGas) returns (\n uint256 _gasConsumed\n ) {\n gasConsumed = _gasConsumed;\n } catch (bytes memory err) {\n bytes32 hash = keccak256(err);\n if (hash == cannotBuyMoreGas) {\n result = \"ResourceMetering: cannot buy more gas than available gas limit\";\n } else if (hash == overflowErr) {\n result = \"arithmetic overflow/underflow\";\n } else if (hash == emptyReturnData) {\n result = \"out of gas\";\n } else {\n result = \"UNKNOWN ERROR\";\n }\n }\n\n // Compute the USD cost of the gas used\n uint256 usdCost = (gasConsumed * l1BaseFee * ethPrice) / 1 ether;\n\n vm.writeLine(\n outfile,\n string.concat(\n vm.toString(prevBaseFee),\n \",\",\n vm.toString(prevBoughtGas),\n \",\",\n vm.toString(prevBlockNumDiff),\n \",\",\n vm.toString(l1BaseFee),\n \",\",\n vm.toString(requestedGas),\n \",\",\n vm.toString(gasConsumed),\n \",\",\n \"$\",\n vm.toString(ethPrice),\n \",\",\n \"$\",\n vm.toString(usdCost),\n \",\",\n result\n )\n );\n\n assertTrue(vm.revertTo(snapshotId));\n }\n }\n }\n }\n }\n }\n }\n}\n" - }, - "contracts/test/SafeCall.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\n\ncontract SafeCall_Test is CommonTest {\n function testFuzz_send_succeeds(\n address from,\n address to,\n uint256 gas,\n uint64 value\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles (mainnet)\n assumeNoPrecompiles(to, 1);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n // don't call the ffi interface\n vm.assume(to != address(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f));\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n uint256[2] memory balancesBefore = [from.balance, to.balance];\n\n vm.expectCall(to, value, bytes(\"\"));\n vm.prank(from);\n bool success = SafeCall.send(to, gas, value);\n\n assertTrue(success, \"send not successful\");\n if (from == to) {\n assertEq(from.balance, balancesBefore[0], \"Self-send did not change balance\");\n } else {\n assertEq(from.balance, balancesBefore[0] - value, \"from balance not drained\");\n assertEq(to.balance, balancesBefore[1] + value, \"to balance received\");\n }\n }\n\n function testFuzz_call_succeeds(\n address from,\n address to,\n uint256 gas,\n uint64 value,\n bytes memory data\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles (mainnet)\n assumeNoPrecompiles(to, 1);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n // don't call the ffi interface\n vm.assume(to != address(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f));\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n uint256[2] memory balancesBefore = [from.balance, to.balance];\n\n vm.expectCall(to, value, data);\n vm.prank(from);\n bool success = SafeCall.call(to, gas, value, data);\n\n assertTrue(success, \"call not successful\");\n if (from == to) {\n assertEq(from.balance, balancesBefore[0], \"Self-send did not change balance\");\n } else {\n assertEq(from.balance, balancesBefore[0] - value, \"from balance not drained\");\n assertEq(to.balance, balancesBefore[1] + value, \"to balance received\");\n }\n }\n\n function testFuzz_callWithMinGas_hasEnough_succeeds(\n address from,\n address to,\n uint64 minGas,\n uint64 value,\n bytes memory data\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles (mainnet)\n assumeNoPrecompiles(to, 1);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n // don't call the FFIInterface\n vm.assume(to != address(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f));\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n // Bound minGas to [0, l1_block_gas_limit]\n minGas = uint64(bound(minGas, 0, 30_000_000));\n\n uint256[2] memory balancesBefore = [from.balance, to.balance];\n\n vm.expectCallMinGas(to, value, minGas, data);\n vm.prank(from);\n bool success = SafeCall.callWithMinGas(to, minGas, value, data);\n\n assertTrue(success, \"call not successful\");\n if (from == to) {\n assertEq(from.balance, balancesBefore[0], \"Self-send did not change balance\");\n } else {\n assertEq(from.balance, balancesBefore[0] - value, \"from balance not drained\");\n assertEq(to.balance, balancesBefore[1] + value, \"to balance received\");\n }\n }\n\n function test_callWithMinGas_noLeakageLow_succeeds() external {\n SimpleSafeCaller caller = new SimpleSafeCaller();\n\n for (uint64 i = 40_000; i < 100_000; i++) {\n uint256 snapshot = vm.snapshot();\n\n // 65_907 is the exact amount of gas required to make the safe call\n // successfully.\n if (i < 65_907) {\n assertFalse(caller.makeSafeCall(i, 25_000));\n } else {\n vm.expectCallMinGas(\n address(caller),\n 0,\n 25_000,\n abi.encodeWithSelector(caller.setA.selector, 1)\n );\n assertTrue(caller.makeSafeCall(i, 25_000));\n }\n\n assertTrue(vm.revertTo(snapshot));\n }\n }\n\n function test_callWithMinGas_noLeakageHigh_succeeds() external {\n SimpleSafeCaller caller = new SimpleSafeCaller();\n\n for (uint64 i = 15_200_000; i < 15_300_000; i++) {\n uint256 snapshot = vm.snapshot();\n\n // 15_278_606 is the exact amount of gas required to make the safe call\n // successfully.\n if (i < 15_278_606) {\n assertFalse(caller.makeSafeCall(i, 15_000_000));\n } else {\n vm.expectCallMinGas(\n address(caller),\n 0,\n 15_000_000,\n abi.encodeWithSelector(caller.setA.selector, 1)\n );\n assertTrue(caller.makeSafeCall(i, 15_000_000));\n }\n\n assertTrue(vm.revertTo(snapshot));\n }\n }\n}\n\ncontract SimpleSafeCaller {\n uint256 public a;\n\n function makeSafeCall(uint64 gas, uint64 minGas) external returns (bool) {\n return\n SafeCall.call(\n address(this),\n gas,\n 0,\n abi.encodeWithSelector(this.makeSafeCallMinGas.selector, minGas)\n );\n }\n\n function makeSafeCallMinGas(uint64 minGas) external returns (bool) {\n return\n SafeCall.callWithMinGas(\n address(this),\n minGas,\n 0,\n abi.encodeWithSelector(this.setA.selector, 1)\n );\n }\n\n function setA(uint256 _a) external {\n a = _a;\n }\n}\n" - }, - "contracts/test/Semver.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\n\n/**\n * @notice Test the Semver contract that is used for semantic versioning\n * of various contracts.\n */\ncontract Semver_Test is CommonTest {\n /**\n * @notice Global semver contract deployed in setUp. This is used in\n * the test cases.\n */\n Semver semver;\n\n /**\n * @notice Deploy a Semver contract\n */\n function setUp() public virtual override {\n semver = new Semver(7, 8, 0);\n }\n\n /**\n * @notice Test the version getter\n */\n function test_version_succeeds() external {\n assertEq(semver.version(), \"7.8.0\");\n }\n\n /**\n * @notice Since the versions are all immutable, they should\n * be able to be accessed from behind a proxy without needing\n * to initialize the contract.\n */\n function test_behindProxy_succeeds() external {\n Proxy proxy = new Proxy(alice);\n vm.prank(alice);\n proxy.upgradeTo(address(semver));\n\n assertEq(Semver(address(proxy)).version(), \"7.8.0\");\n }\n}\n" - }, - "contracts/test/SequencerFeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { SequencerFeeVault } from \"../L2/SequencerFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract SequencerFeeVault_Test is Bridge_Initializer {\n SequencerFeeVault vault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET));\n address constant recipient = address(256);\n\n event Withdrawal(uint256 value, address to, address from);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.SEQUENCER_FEE_WALLET, address(new SequencerFeeVault(recipient)).code);\n vm.label(Predeploys.SEQUENCER_FEE_WALLET, \"SequencerFeeVault\");\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(vault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n\n function test_constructor_succeeds() external {\n assertEq(vault.l1FeeWallet(), recipient);\n }\n\n function test_receive_succeeds() external {\n uint256 balance = address(vault).balance;\n\n vm.prank(alice);\n (bool success, ) = address(vault).call{ value: 100 }(hex\"\");\n\n assertEq(success, true);\n assertEq(address(vault).balance, balance + 100);\n }\n\n function test_withdraw_notEnough_reverts() external {\n assert(address(vault).balance < vault.MIN_WITHDRAWAL_AMOUNT());\n\n vm.expectRevert(\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n vault.withdraw();\n }\n\n function test_withdraw_succeeds() external {\n uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1;\n vm.deal(address(vault), amount);\n\n // No ether has been withdrawn yet\n assertEq(vault.totalProcessed(), 0);\n\n vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));\n emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this));\n\n // The entire vault's balance is withdrawn\n vm.expectCall(\n Predeploys.L2_STANDARD_BRIDGE,\n address(vault).balance,\n abi.encodeWithSelector(\n StandardBridge.bridgeETHTo.selector,\n vault.l1FeeWallet(),\n 35_000,\n bytes(\"\")\n )\n );\n\n vault.withdraw();\n\n // The withdrawal was successful\n assertEq(vault.totalProcessed(), amount);\n }\n}\n" - }, - "contracts/test/StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport {\n OptimismMintableERC20,\n ILegacyMintableERC20\n} from \"../universal/OptimismMintableERC20.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/**\n * @title StandardBridgeTester\n * @notice Simple wrapper around the StandardBridge contract that exposes\n * internal functions so they can be more easily tested directly.\n */\ncontract StandardBridgeTester is StandardBridge {\n constructor(address payable _messenger, address payable _otherBridge)\n StandardBridge(_messenger, _otherBridge)\n {}\n\n function isOptimismMintableERC20(address _token) external view returns (bool) {\n return _isOptimismMintableERC20(_token);\n }\n\n function isCorrectTokenPair(address _mintableToken, address _otherToken)\n external\n view\n returns (bool)\n {\n return _isCorrectTokenPair(_mintableToken, _otherToken);\n }\n\n receive() external payable override {}\n}\n\n/**\n * @title LegacyMintable\n * @notice Simple implementation of the legacy OptimismMintableERC20.\n */\ncontract LegacyMintable is ERC20, ILegacyMintableERC20 {\n constructor(string memory _name, string memory _ticker) ERC20(_name, _ticker) {}\n\n function l1Token() external pure returns (address) {\n return address(0);\n }\n\n function mint(address _to, uint256 _amount) external pure {}\n\n function burn(address _from, uint256 _amount) external pure {}\n\n /**\n * @notice Implements ERC165. This implementation should not be changed as\n * it is how the actual legacy optimism mintable token does the\n * check. Allows for testing against code that is has been deployed,\n * assuming different compiler version is no problem.\n */\n function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {\n bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^\n ILegacyMintableERC20.mint.selector ^\n ILegacyMintableERC20.burn.selector;\n return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n }\n}\n\n/**\n * @title StandardBridge_Stateless_Test\n * @notice Tests internal functions that require no existing state or contract\n * interactions with the messenger.\n */\ncontract StandardBridge_Stateless_Test is CommonTest {\n StandardBridgeTester internal bridge;\n OptimismMintableERC20 internal mintable;\n ERC20 internal erc20;\n LegacyMintable internal legacy;\n\n function setUp() public override {\n super.setUp();\n\n bridge = new StandardBridgeTester({\n _messenger: payable(address(0)),\n _otherBridge: payable(address(0))\n });\n\n mintable = new OptimismMintableERC20({\n _bridge: address(0),\n _remoteToken: address(0),\n _name: \"Stonks\",\n _symbol: \"STONK\"\n });\n\n erc20 = new ERC20(\"Altcoin\", \"ALT\");\n legacy = new LegacyMintable(\"Legacy\", \"LEG\");\n }\n\n /**\n * @notice Test coverage for identifying OptimismMintableERC20 tokens.\n * This function should return true for both modern and legacy\n * OptimismMintableERC20 tokens and false for any accounts that\n * do not implement the interface.\n */\n function test_isOptimismMintableERC20_succeeds() external {\n // Both the modern and legacy mintable tokens should return true\n assertTrue(bridge.isOptimismMintableERC20(address(mintable)));\n assertTrue(bridge.isOptimismMintableERC20(address(legacy)));\n // A regular ERC20 should return false\n assertFalse(bridge.isOptimismMintableERC20(address(erc20)));\n // Non existent contracts should return false and not revert\n assertEq(address(0x20).code.length, 0);\n assertFalse(bridge.isOptimismMintableERC20(address(0x20)));\n }\n\n /**\n * @notice Test coverage of isCorrectTokenPair under different types of\n * tokens.\n */\n function test_isCorrectTokenPair_succeeds() external {\n // Modern + known to be correct remote token\n assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.remoteToken()));\n // Modern + known to be correct l1Token (legacy interface)\n assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.l1Token()));\n // Modern + known to be incorrect remote token\n assertTrue(mintable.remoteToken() != address(0x20));\n assertFalse(bridge.isCorrectTokenPair(address(mintable), address(0x20)));\n // Legacy + known to be correct l1Token\n assertTrue(bridge.isCorrectTokenPair(address(legacy), legacy.l1Token()));\n // Legacy + known to be incorrect l1Token\n assertTrue(legacy.l1Token() != address(0x20));\n assertFalse(bridge.isCorrectTokenPair(address(legacy), address(0x20)));\n // A token that doesn't support either modern or legacy interface\n // will revert\n vm.expectRevert();\n bridge.isCorrectTokenPair(address(erc20), address(1));\n }\n}\n" - }, - "contracts/test/SystemConfig.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract SystemConfig_Init is CommonTest {\n SystemConfig sysConf;\n\n function setUp() public virtual override {\n super.setUp();\n\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n\n sysConf = new SystemConfig({\n _owner: alice,\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(1),\n _config: config\n });\n }\n}\n\ncontract SystemConfig_Initialize_TestFail is SystemConfig_Init {\n function test_initialize_lowGasLimit_reverts() external {\n uint64 minimumGasLimit = sysConf.minimumGasLimit();\n\n ResourceMetering.ResourceConfig memory cfg = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n\n vm.expectRevert(\"SystemConfig: gas limit too low\");\n new SystemConfig({\n _owner: alice,\n _overhead: 0,\n _scalar: 0,\n _batcherHash: bytes32(hex\"\"),\n _gasLimit: minimumGasLimit - 1,\n _unsafeBlockSigner: address(1),\n _config: cfg\n });\n }\n}\n\ncontract SystemConfig_Setters_TestFail is SystemConfig_Init {\n function test_setBatcherHash_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setBatcherHash(bytes32(hex\"\"));\n }\n\n function test_setGasConfig_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasConfig(0, 0);\n }\n\n function test_setGasLimit_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasLimit(0);\n }\n\n function test_setUnsafeBlockSigner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setUnsafeBlockSigner(address(0x20));\n }\n\n function test_setResourceConfig_notOwner_reverts() external {\n ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_badMinMax_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 2 gwei,\n maximumBaseFee: 1 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: min base fee must be less than max base\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_zeroDenominator_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 0,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: denominator must be larger than 1\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_lowGasLimit_reverts() external {\n uint64 gasLimit = sysConf.gasLimit();\n\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: uint32(gasLimit),\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: uint32(gasLimit),\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: gas limit too low\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_badPrecision_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 11,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: precision loss with target resource limit\");\n sysConf.setResourceConfig(config);\n }\n}\n\ncontract SystemConfig_Setters_Test is SystemConfig_Init {\n event ConfigUpdate(\n uint256 indexed version,\n SystemConfig.UpdateType indexed updateType,\n bytes data\n );\n\n function testFuzz_setBatcherHash_succeeds(bytes32 newBatcherHash) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash));\n\n vm.prank(sysConf.owner());\n sysConf.setBatcherHash(newBatcherHash);\n assertEq(sysConf.batcherHash(), newBatcherHash);\n }\n\n function testFuzz_setGasConfig_succeeds(uint256 newOverhead, uint256 newScalar) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.GAS_CONFIG,\n abi.encode(newOverhead, newScalar)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setGasConfig(newOverhead, newScalar);\n assertEq(sysConf.overhead(), newOverhead);\n assertEq(sysConf.scalar(), newScalar);\n }\n\n function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external {\n uint64 minimumGasLimit = sysConf.minimumGasLimit();\n newGasLimit = uint64(\n bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(type(uint64).max))\n );\n\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit));\n\n vm.prank(sysConf.owner());\n sysConf.setGasLimit(newGasLimit);\n assertEq(sysConf.gasLimit(), newGasLimit);\n }\n\n function testFuzz_setUnsafeBlockSigner_succeeds(address newUnsafeSigner) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER,\n abi.encode(newUnsafeSigner)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setUnsafeBlockSigner(newUnsafeSigner);\n assertEq(sysConf.unsafeBlockSigner(), newUnsafeSigner);\n }\n}\n" - }, - "contracts/test/TransferOnion.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { TransferOnion } from \"../periphery/TransferOnion.sol\";\n\n/**\n * @title TransferOnionTest\n * @notice Test coverage of TransferOnion\n */\ncontract TransferOnionTest is Test {\n /**\n * @notice TransferOnion\n */\n TransferOnion internal onion;\n\n /**\n * @notice token constructor arg\n */\n address internal _token;\n\n /**\n * @notice sender constructor arg\n */\n address internal _sender;\n\n /**\n * @notice Sets up addresses, deploys contracts and funds the owner.\n */\n function setUp() public {\n ERC20 token = new ERC20(\"Token\", \"TKN\");\n _token = address(token);\n _sender = makeAddr(\"sender\");\n }\n\n /**\n * @notice Deploy the TransferOnion with a dummy shell\n */\n function _deploy() public {\n _deploy(bytes32(0));\n }\n\n /**\n * @notice Deploy the TransferOnion with a specific shell\n */\n function _deploy(bytes32 _shell) public {\n onion = new TransferOnion({ _token: ERC20(_token), _sender: _sender, _shell: _shell });\n }\n\n /**\n * @notice Build the onion data\n */\n function _onionize(TransferOnion.Layer[] memory _layers)\n public\n pure\n returns (bytes32, TransferOnion.Layer[] memory)\n {\n uint256 length = _layers.length;\n bytes32 hash = bytes32(0);\n for (uint256 i; i < length; i++) {\n TransferOnion.Layer memory layer = _layers[i];\n _layers[i].shell = hash;\n hash = keccak256(abi.encode(layer.recipient, layer.amount, hash));\n }\n return (hash, _layers);\n }\n\n /**\n * @notice The constructor sets the variables as expected\n */\n function test_constructor_succeeds() external {\n _deploy();\n\n assertEq(address(onion.TOKEN()), _token);\n assertEq(onion.SENDER(), _sender);\n assertEq(onion.shell(), bytes32(0));\n }\n\n /**\n * @notice unwrap\n */\n function test_unwrap_succeeds() external {\n // Commit to transferring tiny amounts of tokens\n TransferOnion.Layer[] memory _layers = new TransferOnion.Layer[](2);\n _layers[0] = TransferOnion.Layer(address(1), 1, bytes32(0));\n _layers[1] = TransferOnion.Layer(address(2), 2, bytes32(0));\n\n // Build the onion shell\n (bytes32 shell, TransferOnion.Layer[] memory layers) = _onionize(_layers);\n _deploy(shell);\n\n assertEq(onion.shell(), shell);\n\n address token = address(onion.TOKEN());\n address sender = onion.SENDER();\n\n // give 3 units of token to sender\n deal(token, onion.SENDER(), 3);\n vm.prank(sender);\n ERC20(token).approve(address(onion), 3);\n\n // To build the inputs, to `peel`, need to reverse the list\n TransferOnion.Layer[] memory inputs = new TransferOnion.Layer[](2);\n int256 length = int256(layers.length);\n for (int256 i = length - 1; i >= 0; i--) {\n uint256 ui = uint256(i);\n uint256 revidx = uint256(length) - ui - 1;\n TransferOnion.Layer memory layer = layers[ui];\n inputs[revidx] = layer;\n }\n\n // The accounts have no balance\n assertEq(ERC20(_token).balanceOf(address(1)), 0);\n assertEq(ERC20(_token).balanceOf(address(2)), 0);\n\n onion.peel(inputs);\n\n // Now the accounts have the expected balance\n assertEq(ERC20(_token).balanceOf(address(1)), 1);\n assertEq(ERC20(_token).balanceOf(address(2)), 2);\n }\n}\n" - }, - "contracts/test/invariants/CrossDomainMessenger.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { StdUtils } from \"forge-std/StdUtils.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport { OptimismPortal } from \"../../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../../L1/L1CrossDomainMessenger.sol\";\nimport { Messenger_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\nimport { Predeploys } from \"../../libraries/Predeploys.sol\";\nimport { Constants } from \"../../libraries/Constants.sol\";\nimport { Encoding } from \"../../libraries/Encoding.sol\";\nimport { Hashing } from \"../../libraries/Hashing.sol\";\n\ncontract RelayActor is StdUtils {\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n uint256 public numHashes;\n bytes32[] public hashes;\n bool public reverted = false;\n\n OptimismPortal op;\n L1CrossDomainMessenger xdm;\n Vm vm;\n bool doFail;\n\n constructor(\n OptimismPortal _op,\n L1CrossDomainMessenger _xdm,\n Vm _vm,\n bool _doFail\n ) {\n op = _op;\n xdm = _xdm;\n vm = _vm;\n doFail = _doFail;\n }\n\n /**\n * Relays a message to the `L1CrossDomainMessenger` with a random `version`, and `_message`.\n */\n function relay(\n uint8 _version,\n uint8 _value,\n bytes memory _message\n ) external {\n address target = address(0x04); // ID precompile\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Set the minimum gas limit to the cost of the identity precompile's execution for\n // the given message.\n // ID Precompile cost can be determined by calculating: 15 + 3 * data_word_length\n uint32 minGasLimit = uint32(15 + 3 * ((_message.length + 31) / 32));\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Restrict version to the range of [0, 1]\n _version = _version % 2;\n\n // Restrict the value to the range of [0, 1]\n // This is just so we get variance of calls with and without value. The ID precompile\n // will not reject value being sent to it.\n _value = _value % 2;\n\n // If the message should succeed, supply it `baseGas`. If not, supply it an amount of\n // gas that is too low to complete the call.\n uint256 gas = doFail\n ? bound(minGasLimit, 60_000, 80_000)\n : xdm.baseGas(_message, minGasLimit);\n\n // Compute the cross domain message hash and store it in `hashes`.\n // The `relayMessage` function will always encode the message as a version 1\n // message after checking that the V0 hash has not already been relayed.\n bytes32 _hash = Hashing.hashCrossDomainMessageV1(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n _value,\n minGasLimit,\n _message\n );\n hashes.push(_hash);\n numHashes += 1;\n\n // Make sure we've got a fresh message.\n vm.assume(xdm.successfulMessages(_hash) == false && xdm.failedMessages(_hash) == false);\n\n // Act as the optimism portal and call `relayMessage` on the `L1CrossDomainMessenger` with\n // the outer min gas limit.\n vm.startPrank(address(op));\n if (!doFail) {\n vm.expectCallMinGas(address(0x04), _value, minGasLimit, _message);\n }\n try\n xdm.relayMessage{ gas: gas, value: _value }(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n _value,\n minGasLimit,\n _message\n )\n {} catch {\n // If any of these calls revert, set `reverted` to true to fail the invariant test.\n // NOTE: This is to get around forge's invariant fuzzer ignoring reverted calls\n // to this function.\n reverted = true;\n }\n vm.stopPrank();\n }\n}\n\ncontract XDM_MinGasLimits is Messenger_Initializer {\n RelayActor actor;\n\n function init(bool doFail) public virtual {\n // Set up the `L1CrossDomainMessenger` and `OptimismPortal` contracts.\n super.setUp();\n\n // Deploy a relay actor\n actor = new RelayActor(op, L1Messenger, vm, doFail);\n\n // Give the portal some ether to send to `relayMessage`\n vm.deal(address(op), type(uint128).max);\n\n // Target the `RelayActor` contract\n targetContract(address(actor));\n\n // Don't allow the estimation address to be the sender\n excludeSender(Constants.ESTIMATION_ADDRESS);\n\n // Target the actor's `relay` function\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = actor.relay.selector;\n targetSelector(FuzzSelector({ addr: address(actor), selectors: selectors }));\n }\n}\n\ncontract XDM_MinGasLimits_Succeeds is XDM_MinGasLimits {\n function setUp() public override {\n // Don't fail\n super.init(false);\n }\n\n /**\n * @custom:invariant A call to `relayMessage` should succeed if at least the minimum gas limit\n * can be supplied to the target context, there is enough gas to complete\n * execution of `relayMessage` after the target context's execution is\n * finished, and the target context did not revert.\n *\n * There are two minimum gas limits here:\n *\n * - The outer min gas limit is for the call from the `OptimismPortal` to the\n * `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function\n * with the `message` and inner limit.\n *\n * - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target\n * contract.\n */\n function invariant_minGasLimits() external {\n uint256 length = actor.numHashes();\n for (uint256 i = 0; i < length; ++i) {\n bytes32 hash = actor.hashes(i);\n // The message hash is set in the successfulMessages mapping\n assertTrue(L1Messenger.successfulMessages(hash));\n // The message hash is not set in the failedMessages mapping\n assertFalse(L1Messenger.failedMessages(hash));\n }\n assertFalse(actor.reverted());\n }\n}\n\ncontract XDM_MinGasLimits_Reverts is XDM_MinGasLimits {\n function setUp() public override {\n // Do fail\n super.init(true);\n }\n\n /**\n * @custom:invariant A call to `relayMessage` should assign the message hash to the\n * `failedMessages` mapping if not enough gas is supplied to forward\n * `minGasLimit` to the target context or if there is not enough gas to\n * complete execution of `relayMessage` after the target context's execution\n * is finished.\n *\n * There are two minimum gas limits here:\n *\n * - The outer min gas limit is for the call from the `OptimismPortal` to the\n * `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function\n * with the `message` and inner limit.\n *\n * - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target\n * contract.\n */\n function invariant_minGasLimits() external {\n uint256 length = actor.numHashes();\n for (uint256 i = 0; i < length; ++i) {\n bytes32 hash = actor.hashes(i);\n // The message hash is not set in the successfulMessages mapping\n assertFalse(L1Messenger.successfulMessages(hash));\n // The message hash is set in the failedMessages mapping\n assertTrue(L1Messenger.failedMessages(hash));\n }\n assertFalse(actor.reverted());\n }\n}\n" - }, - "contracts/test/invariants/L2OutputOracle.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { L2OutputOracle_Initializer } from \"../CommonTest.t.sol\";\nimport { L2OutputOracle } from \"../../L1/L2OutputOracle.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\n\ncontract L2OutputOracle_Proposer {\n L2OutputOracle internal oracle;\n Vm internal vm;\n\n constructor(L2OutputOracle _oracle, Vm _vm) {\n oracle = _oracle;\n vm = _vm;\n }\n\n /**\n * @dev Allows the actor to propose an L2 output to the `L2OutputOracle`\n */\n function proposeL2Output(\n bytes32 _outputRoot,\n uint256 _l2BlockNumber,\n bytes32 _l1BlockHash,\n uint256 _l1BlockNumber\n ) external {\n // Act as the proposer and propose a new output.\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _l2BlockNumber, _l1BlockHash, _l1BlockNumber);\n }\n}\n\ncontract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_Initializer {\n L2OutputOracle_Proposer internal actor;\n\n function setUp() public override {\n super.setUp();\n\n // Create a proposer actor.\n actor = new L2OutputOracle_Proposer(oracle, vm);\n\n // Set the target contract to the proposer actor.\n targetContract(address(actor));\n\n // Set the target selector for `proposeL2Output`\n // `proposeL2Output` is the only function we care about, as it is the only function\n // that can modify the `l2Outputs` array in the oracle.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = actor.proposeL2Output.selector;\n FuzzSelector memory selector = FuzzSelector({ addr: address(actor), selectors: selectors });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The block number of the output root proposals should monotonically\n * increase.\n *\n * When a new output is submitted, it should never be allowed to correspond to a block\n * number that is less than the current output.\n */\n function invariant_monotonicBlockNumIncrease() external {\n // Assert that the block number of proposals must monotonically increase.\n assertTrue(oracle.nextBlockNumber() >= oracle.latestBlockNumber());\n }\n}\n" - }, - "contracts/test/invariants/OptimismPortal.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Portal_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\n\ncontract OptimismPortal_Invariant_Harness is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n function setUp() public virtual override {\n super.setUp();\n\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n}\n\ncontract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the finalization\n * period has not elapsed.\n *\n * A withdrawal that has been proven should not be able to be finalized until after\n * the finalization period has elapsed.\n */\n function invariant_cannotFinalizeBeforePeriodHasPassed() external {\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Finalize the withdrawal transaction.\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal\n * has already been finalized.\n *\n * Ensures that there is no chain of calls that can be made that allows a withdrawal\n * to be finalized twice.\n */\n function invariant_cannotFinalizeTwice() external {\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant A withdrawal should **always** be able to be finalized\n * `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.\n *\n * This invariant asserts that there is no chain of calls that can be made that\n * will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS`\n * after it was successfully proven.\n */\n function invariant_canAlwaysFinalize() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assertEq(address(bob).balance, bobBalanceBefore + _defaultTx.value);\n }\n}\n" - }, - "contracts/test/invariants/SafeCall.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { StdUtils } from \"forge-std/StdUtils.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport { SafeCall } from \"../../libraries/SafeCall.sol\";\n\ncontract SafeCall_Succeeds_Invariants is Test {\n SafeCaller_Actor actor;\n\n function setUp() public {\n // Create a new safe caller actor.\n actor = new SafeCaller_Actor(vm, false);\n\n // Set the caller to this contract\n targetSender(address(this));\n\n // Target the safe caller actor.\n targetContract(address(actor));\n\n // Give the actor some ETH to work with\n vm.deal(address(actor), type(uint128).max);\n }\n\n /**\n * @custom:invariant If `callWithMinGas` performs a call, then it must always\n * provide at least the specified minimum gas limit to the subcontext.\n *\n * If the check for remaining gas in `SafeCall.callWithMinGas` passes, the\n * subcontext of the call below it must be provided at least `minGas` gas.\n */\n function invariant_callWithMinGas_alwaysForwardsMinGas_succeeds() public {\n assertEq(actor.numCalls(), 0, \"no failed calls allowed\");\n }\n\n function performSafeCallMinGas(address to, uint64 minGas) external payable {\n SafeCall.callWithMinGas(to, minGas, msg.value, hex\"\");\n }\n}\n\ncontract SafeCall_Fails_Invariants is Test {\n SafeCaller_Actor actor;\n\n function setUp() public {\n // Create a new safe caller actor.\n actor = new SafeCaller_Actor(vm, true);\n\n // Set the caller to this contract\n targetSender(address(this));\n\n // Target the safe caller actor.\n targetContract(address(actor));\n\n // Give the actor some ETH to work with\n vm.deal(address(actor), type(uint128).max);\n }\n\n /**\n * @custom:invariant `callWithMinGas` reverts if there is not enough gas to pass\n * to the subcontext.\n *\n * If there is not enough gas in the callframe to ensure that `callWithMinGas`\n * can provide the specified minimum gas limit to the subcontext of the call,\n * then `callWithMinGas` must revert.\n */\n function invariant_callWithMinGas_neverForwardsMinGas_reverts() public {\n assertEq(actor.numCalls(), 0, \"no successful calls allowed\");\n }\n\n function performSafeCallMinGas(address to, uint64 minGas) external payable {\n SafeCall.callWithMinGas(to, minGas, msg.value, hex\"\");\n }\n}\n\ncontract SafeCaller_Actor is StdUtils {\n bool internal immutable FAILS;\n\n Vm internal vm;\n uint256 public numCalls;\n\n constructor(Vm _vm, bool _fails) {\n vm = _vm;\n FAILS = _fails;\n }\n\n function performSafeCallMinGas(\n uint64 gas,\n uint64 minGas,\n address to,\n uint8 value\n ) external {\n // Only send to EOAs - we exclude the console as it has no code but reverts when called\n // with a selector that doesn't exist due to the foundry hook.\n vm.assume(to.code.length == 0 && to != 0x000000000000000000636F6e736F6c652e6c6f67);\n\n // Bound the minimum gas amount to [2500, type(uint48).max]\n minGas = uint64(bound(minGas, 2500, type(uint48).max));\n if (FAILS) {\n // Bound the gas passed to [minGas, ((minGas * 64) / 63)]\n gas = uint64(bound(gas, minGas, (minGas * 64) / 63));\n } else {\n // Bound the gas passed to\n // [((minGas * 64) / 63) + 40_000 + 1000, type(uint64).max]\n // The extra 1000 gas is to account for the gas used by the `SafeCall.call` call\n // itself.\n gas = uint64(bound(gas, ((minGas * 64) / 63) + 40_000 + 1000, type(uint64).max));\n }\n\n vm.expectCallMinGas(to, value, minGas, hex\"\");\n bool success = SafeCall.call(\n msg.sender,\n gas,\n value,\n abi.encodeWithSelector(\n SafeCall_Succeeds_Invariants.performSafeCallMinGas.selector,\n to,\n minGas\n )\n );\n\n if (success && FAILS) numCalls++;\n if (!FAILS && !success) numCalls++;\n }\n}\n" - }, - "contracts/test/invariants/SystemConfig.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { SystemConfig } from \"../../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../../L1/ResourceMetering.sol\";\nimport { Constants } from \"../../libraries/Constants.sol\";\n\ncontract SystemConfig_GasLimitLowerBound_Invariant is Test {\n SystemConfig public config;\n\n function setUp() public {\n ResourceMetering.ResourceConfig memory cfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n config = new SystemConfig({\n _owner: address(0xbeef),\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(1),\n _config: cfg\n });\n\n // Set the target contract to the `config`\n targetContract(address(config));\n // Set the target sender to the `config`'s owner (0xbeef)\n targetSender(address(0xbeef));\n // Set the target selector for `setGasLimit`\n // `setGasLimit` is the only function we care about, as it is the only function\n // that can modify the gas limit within the SystemConfig.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = config.setGasLimit.selector;\n FuzzSelector memory selector = FuzzSelector({\n addr: address(config),\n selectors: selectors\n });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The gas limit of the `SystemConfig` contract can never be lower\n * than the hard-coded lower bound.\n */\n function invariant_gasLimitLowerBound() external {\n assertTrue(config.gasLimit() >= config.minimumGasLimit());\n }\n}\n" - }, - "contracts/universal/CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\n/**\n * @custom:legacy\n * @title CrossDomainMessengerLegacySpacer0\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 CrossDomainMessengerLegacySpacer0 {\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:legacy\n * @title CrossDomainMessengerLegacySpacer1\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\n * PausableUpgradable and OwnableUpgradeable variables used to exist. Must be\n * the third contract in the inheritance tree of the CrossDomainMessenger.\n */\ncontract CrossDomainMessengerLegacySpacer1 {\n /**\n * @custom:legacy\n * @custom:spacer ContextUpgradable's __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * ContextUpgradable.\n *\n */\n uint256[50] private spacer_1_0_1600;\n\n /**\n * @custom:legacy\n * @custom:spacer OwnableUpgradeable's _owner\n * @notice Spacer for backwards compatibility.\n * Come from OpenZeppelin OwnableUpgradeable.\n */\n address private spacer_51_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer OwnableUpgradeable's __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * OwnableUpgradeable.\n */\n uint256[49] private spacer_52_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer PausableUpgradable's _paused\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n bool private spacer_101_0_1;\n\n /**\n * @custom:legacy\n * @custom:spacer PausableUpgradable's __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n uint256[49] private spacer_102_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer ReentrancyGuardUpgradeable's `_status` field.\n * @notice Spacer for backwards compatibility.\n */\n uint256 private spacer_151_0_32;\n\n /**\n * @custom:legacy\n * @custom:spacer ReentrancyGuardUpgradeable's __gap\n * @notice Spacer for backwards compatibility.\n */\n uint256[49] private spacer_152_0_1568;\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/**\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 *\n * Any changes to this contract MUST result in a semver bump for contracts that inherit it.\n */\nabstract contract CrossDomainMessenger is\n CrossDomainMessengerLegacySpacer0,\n Initializable,\n CrossDomainMessengerLegacySpacer1\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 uint64 public constant RELAY_CONSTANT_OVERHEAD = 200_000;\n\n /**\n * @notice Numerator for dynamic overhead added to the base gas for a message.\n */\n uint64 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 64;\n\n /**\n * @notice Denominator for dynamic overhead added to the base gas for a message.\n */\n uint64 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 63;\n\n /**\n * @notice Extra gas added to base gas for each byte of calldata in a message.\n */\n uint64 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\n\n /**\n * @notice Gas reserved for performing the external call in `relayMessage`.\n */\n uint64 public constant RELAY_CALL_OVERHEAD = 40_000;\n\n /**\n * @notice Gas reserved for finalizing the execution of `relayMessage` after the safe call.\n */\n uint64 public constant RELAY_RESERVED_GAS = 40_000;\n\n /**\n * @notice Gas reserved for the execution between the `hasMinGas` check and the external\n * call in `relayMessage`.\n */\n uint64 public constant RELAY_GAS_CHECK_BUFFER = 5_000;\n\n /**\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\n */\n address public immutable OTHER_MESSENGER;\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 a boolean if and only if the message has failed to be\n * executed at least once. A message will not be present in this mapping if it\n * successfully executed on the first attempt.\n */\n mapping(bytes32 => bool) public failedMessages;\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 OTHER_MESSENGER = _otherMessenger;\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 OTHER_MESSENGER,\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 {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n require(\n version < 2,\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // If the message is version 0, then it's a migrated legacy withdrawal. We therefore need\n // to check that the legacy version of the message has not already been relayed.\n if (version == 0) {\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _nonce);\n require(\n successfulMessages[oldHash] == false,\n \"CrossDomainMessenger: legacy withdrawal already relayed\"\n );\n }\n\n // We use the v1 message hash as the unique identifier for the message because it commits\n // to the value and minimum gas limit of the message.\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _minGasLimit,\n _message\n );\n\n if (_isOtherMessenger()) {\n // These properties should always hold when the message is first submitted (as\n // opposed to being replayed).\n assert(msg.value == _value);\n assert(!failedMessages[versionedHash]);\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 failedMessages[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 // If there is not enough gas left to perform the external call and finish the execution,\n // return early and assign the message to the failedMessages mapping.\n // We are asserting that we have enough gas to:\n // 1. Call the target contract (_minGasLimit + RELAY_CALL_OVERHEAD + RELAY_GAS_CHECK_BUFFER)\n // 1.a. The RELAY_CALL_OVERHEAD is included in `hasMinGas`.\n // 2. Finish the execution after the external call (RELAY_RESERVED_GAS).\n //\n // If `xDomainMsgSender` is not the default L2 sender, this function\n // is being re-entered. This marks the message as failed to allow it to be replayed.\n if (\n !SafeCall.hasMinGas(_minGasLimit, RELAY_RESERVED_GAS + RELAY_GAS_CHECK_BUFFER) ||\n xDomainMsgSender != Constants.DEFAULT_L2_SENDER\n ) {\n failedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n\n // Revert in this case if the transaction was triggered by the estimation address. This\n // should only be possible during gas estimation or we have bigger problems. Reverting\n // here will make the behavior of gas estimation change such that the gas limit\n // computed will be the amount required to relay the message, even if that amount is\n // greater than the minimum gas limit specified by the user.\n if (tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"CrossDomainMessenger: failed to relay message\");\n }\n\n return;\n }\n\n xDomainMsgSender = _sender;\n bool success = SafeCall.call(_target, gasleft() - RELAY_RESERVED_GAS, _value, _message);\n xDomainMsgSender = Constants.DEFAULT_L2_SENDER;\n\n if (success) {\n successfulMessages[versionedHash] = true;\n emit RelayedMessage(versionedHash);\n } else {\n failedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n\n // Revert in this case if the transaction was triggered by the estimation address. This\n // should only be possible during gas estimation or we have bigger problems. Reverting\n // here will make the behavior of gas estimation change such that the gas limit\n // computed will be the amount required to relay the message, even if that amount is\n // greater than the minimum gas limit specified by the user.\n if (tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"CrossDomainMessenger: failed to relay message\");\n }\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 != Constants.DEFAULT_L2_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 (uint64) {\n return\n // Constant overhead\n RELAY_CONSTANT_OVERHEAD +\n // Calldata overhead\n (uint64(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +\n // Dynamic overhead (EIP-150)\n ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n // Gas reserved for the worst-case cost of 3/5 of the `CALL` opcode's dynamic gas\n // factors. (Conservative)\n RELAY_CALL_OVERHEAD +\n // Relay reserved gas (to ensure execution of `relayMessage` completes after the\n // subcontext finishes executing) (Conservative)\n RELAY_RESERVED_GAS +\n // Gas reserved for the execution between the `hasMinGas` check and the `CALL`\n // opcode. (Conservative)\n RELAY_GAS_CHECK_BUFFER;\n }\n\n /**\n * @notice Intializer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __CrossDomainMessenger_init() internal onlyInitializing {\n xDomainMsgSender = Constants.DEFAULT_L2_SENDER;\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" - }, - "contracts/universal/ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CrossDomainMessenger } from \"./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 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 OTHER_BRIDGE;\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 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 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() == OTHER_BRIDGE,\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 OTHER_BRIDGE = _otherBridge;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for other bridge address.\n *\n * @return Address of the bridge on the other network.\n */\n function otherBridge() external view returns (address) {\n return OTHER_BRIDGE;\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" - }, - "contracts/universal/FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n/**\n * @title FeeVault\n * @notice The FeeVault contract contains the basic logic for the various different vault contracts\n * used to hold fee revenue generated by the L2 system.\n */\nabstract contract FeeVault {\n /**\n * @notice Emits each time that a withdrawal occurs.\n *\n * @param value Amount that was withdrawn (in wei).\n * @param to Address that the funds were sent to.\n * @param from Address that triggered the withdrawal.\n */\n event Withdrawal(uint256 value, address to, address from);\n\n /**\n * @notice Minimum balance before a withdrawal can be triggered.\n */\n uint256 public immutable MIN_WITHDRAWAL_AMOUNT;\n\n /**\n * @notice Wallet that will receive the fees on L1.\n */\n address public immutable RECIPIENT;\n\n /**\n * @notice The minimum gas limit for the FeeVault withdrawal transaction.\n */\n uint32 internal constant WITHDRAWAL_MIN_GAS = 35_000;\n\n /**\n * @notice Total amount of wei processed by the contract.\n */\n uint256 public totalProcessed;\n\n /**\n * @param _recipient Wallet that will receive the fees on L1.\n * @param _minWithdrawalAmount Minimum balance before a withdrawal can be triggered.\n */\n constructor(address _recipient, uint256 _minWithdrawalAmount) {\n MIN_WITHDRAWAL_AMOUNT = _minWithdrawalAmount;\n RECIPIENT = _recipient;\n }\n\n /**\n * @notice Allow the contract to receive ETH.\n */\n receive() external payable {}\n\n /**\n * @notice Triggers a withdrawal of funds to the L1 fee wallet.\n */\n function withdraw() external {\n require(\n address(this).balance >= MIN_WITHDRAWAL_AMOUNT,\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n\n uint256 value = address(this).balance;\n totalProcessed += value;\n\n emit Withdrawal(value, RECIPIENT, msg.sender);\n\n L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)).bridgeETHTo{ value: value }(\n RECIPIENT,\n WITHDRAWAL_MIN_GAS,\n bytes(\"\")\n );\n }\n}\n" - }, - "contracts/universal/IOptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\n/**\n * @title IOptimismMintableERC20\n * @notice This interface is available on the OptimismMintableERC20 contract. We declare it as a\n * separate interface so that it can be used in custom implementations of\n * OptimismMintableERC20.\n */\ninterface IOptimismMintableERC20 is IERC165 {\n function remoteToken() external view returns (address);\n\n function bridge() external returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n\n/**\n * @custom:legacy\n * @title ILegacyMintableERC20\n * @notice This interface was available on the legacy L2StandardERC20 contract. It remains available\n * on the OptimismMintableERC20 contract for backwards compatibility.\n */\ninterface ILegacyMintableERC20 is IERC165 {\n function l1Token() external view returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n" - }, - "contracts/universal/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 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 /**\n * @notice Chain ID of the chain where the remote token is deployed.\n */\n function REMOTE_CHAIN_ID() external view returns (uint256);\n\n /**\n * @notice Address of the token on the remote domain.\n */\n function REMOTE_TOKEN() 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 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" - }, - "contracts/universal/OptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { ILegacyMintableERC20, IOptimismMintableERC20 } from \"./IOptimismMintableERC20.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @title OptimismMintableERC20\n * @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed\n * to allow the StandardBridge contracts to mint and burn tokens. This makes it possible to\n * use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa.\n * Designed to be backwards compatible with the older StandardL2ERC20 token which was only\n * meant for use on L2.\n */\ncontract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, Semver {\n /**\n * @notice Address of the corresponding version of this token on the remote chain.\n */\n address public immutable REMOTE_TOKEN;\n\n /**\n * @notice Address of the StandardBridge on this network.\n */\n address public immutable BRIDGE;\n\n /**\n * @notice Emitted whenever tokens are minted for an account.\n *\n * @param account Address of the account tokens are being minted for.\n * @param amount Amount of tokens minted.\n */\n event Mint(address indexed account, uint256 amount);\n\n /**\n * @notice Emitted whenever tokens are burned from an account.\n *\n * @param account Address of the account tokens are being burned from.\n * @param amount Amount of tokens burned.\n */\n event Burn(address indexed account, uint256 amount);\n\n /**\n * @notice A modifier that only allows the bridge to call\n */\n modifier onlyBridge() {\n require(msg.sender == BRIDGE, \"OptimismMintableERC20: only bridge can mint and burn\");\n _;\n }\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _bridge Address of the L2 standard bridge.\n * @param _remoteToken Address of the corresponding L1 token.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n */\n constructor(\n address _bridge,\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) Semver(1, 0, 0) {\n REMOTE_TOKEN = _remoteToken;\n BRIDGE = _bridge;\n }\n\n /**\n * @notice Allows the StandardBridge on this network to mint tokens.\n *\n * @param _to Address to mint tokens to.\n * @param _amount Amount of tokens to mint.\n */\n function mint(address _to, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _mint(_to, _amount);\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Allows the StandardBridge on this network to burn tokens.\n *\n * @param _from Address to burn tokens from.\n * @param _amount Amount of tokens to burn.\n */\n function burn(address _from, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _burn(_from, _amount);\n emit Burn(_from, _amount);\n }\n\n /**\n * @notice ERC165 interface check function.\n *\n * @param _interfaceId Interface ID to check.\n *\n * @return Whether or not the interface is supported by this contract.\n */\n function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {\n bytes4 iface1 = type(IERC165).interfaceId;\n // Interface corresponding to the legacy L2StandardERC20.\n bytes4 iface2 = type(ILegacyMintableERC20).interfaceId;\n // Interface corresponding to the updated OptimismMintableERC20 (this contract).\n bytes4 iface3 = type(IOptimismMintableERC20).interfaceId;\n return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward.\n */\n function l1Token() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the bridge. Use BRIDGE going forward.\n */\n function l2Bridge() public view returns (address) {\n return BRIDGE;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for REMOTE_TOKEN.\n */\n function remoteToken() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for BRIDGE.\n */\n function bridge() public view returns (address) {\n return BRIDGE;\n }\n}\n" - }, - "contracts/universal/OptimismMintableERC20Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Contract Imports */\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { Semver } from \"./Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000012\n * @title OptimismMintableERC20Factory\n * @notice OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20\n * contracts on the network it's deployed to. Simplifies the deployment process for users\n * who may be less familiar with deploying smart contracts. Designed to be backwards\n * compatible with the older StandardL2ERC20Factory contract.\n */\ncontract OptimismMintableERC20Factory is Semver {\n /**\n * @notice Address of the StandardBridge on this chain.\n */\n address public immutable BRIDGE;\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer\n * OptimismMintableERC20Created event. We recommend relying on that event instead.\n *\n * @param remoteToken Address of the token on the remote chain.\n * @param localToken Address of the created token on the local chain.\n */\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n\n /**\n * @notice Emitted whenever a new OptimismMintableERC20 is created.\n *\n * @param localToken Address of the created token on the local chain.\n * @param remoteToken Address of the corresponding token on the remote chain.\n * @param deployer Address of the account that deployed the token.\n */\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @notice The semver MUST be bumped any time that there is a change in\n * the OptimismMintableERC20 token contract since this contract\n * is responsible for deploying OptimismMintableERC20 contracts.\n *\n * @param _bridge Address of the StandardBridge on this chain.\n */\n constructor(address _bridge) Semver(1, 1, 0) {\n BRIDGE = _bridge;\n }\n\n /**\n * @custom:legacy\n * @notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the\n * newer createOptimismMintableERC20 function, which has a more intuitive name.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createStandardL2Token(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) external returns (address) {\n return createOptimismMintableERC20(_remoteToken, _name, _symbol);\n }\n\n /**\n * @notice Creates an instance of the OptimismMintableERC20 contract.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createOptimismMintableERC20(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) public returns (address) {\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC20Factory: must provide remote token address\"\n );\n\n address localToken = address(\n new OptimismMintableERC20(BRIDGE, _remoteToken, _name, _symbol)\n );\n\n // Emit the old event too for legacy support.\n emit StandardL2TokenCreated(_remoteToken, localToken);\n\n // Emit the updated event. The arguments here differ from the legacy event, but\n // are consistent with the ordering used in StandardBridge events.\n emit OptimismMintableERC20Created(localToken, _remoteToken, msg.sender);\n\n return localToken;\n }\n}\n" - }, - "contracts/universal/OptimismMintableERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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\";\nimport { Semver } from \"../universal/Semver.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, Semver {\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n uint256 public immutable REMOTE_CHAIN_ID;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable REMOTE_TOKEN;\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 * @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 * @custom:semver 1.1.0\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) Semver(1, 1, 0) {\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 REMOTE_CHAIN_ID = _remoteChainId;\n REMOTE_TOKEN = _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 * @inheritdoc IOptimismMintableERC721\n */\n function remoteChainId() external view returns (uint256) {\n return REMOTE_CHAIN_ID;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function remoteToken() external view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function bridge() external view returns (address) {\n return BRIDGE;\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 iface = type(IOptimismMintableERC721).interfaceId;\n return _interfaceId == iface || 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" - }, - "contracts/universal/OptimismMintableERC721Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\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 {\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 REMOTE_CHAIN_ID;\n\n /**\n * @notice Tracks addresses created by this factory.\n */\n mapping(address => bool) public isOptimismMintableERC721;\n\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 * @custom:semver 1.2.0\n * @notice The semver MUST be bumped any time that there is a change in\n * the OptimismMintableERC721 token contract since this contract\n * is responsible for deploying OptimismMintableERC721 contracts.\n *\n * @param _bridge Address of the ERC721 bridge on this network.\n * @param _remoteChainId Chain ID for the remote network.\n */\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 2, 0) {\n BRIDGE = _bridge;\n REMOTE_CHAIN_ID = _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, REMOTE_CHAIN_ID, _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/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) public virtual 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 public\n payable\n virtual\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) public virtual 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() public virtual proxyCallIfNotAdmin returns (address) {\n return _getAdmin();\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function implementation() public virtual 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" - }, - "contracts/universal/ProxyAdmin.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.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 Ownable {\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 * @notice A mapping of proxy types, used for backwards compatibility.\n */\n mapping(address => ProxyType) public proxyType;\n\n /**\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 * @notice The address of the address manager, this is required to manage the\n * ResolvedDelegateProxy type.\n */\n AddressManager public addressManager;\n\n /**\n * @notice A legacy upgrading indicator used by the old Chugsplash Proxy.\n */\n bool internal upgrading;\n\n /**\n * @param _owner Address of the initial owner of this contract.\n */\n constructor(address _owner) Ownable() {\n _transferOwnership(_owner);\n }\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 * @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 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.\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 /**\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" - }, - "contracts/universal/Semver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 uint256 private immutable MAJOR_VERSION;\n\n /**\n * @notice Contract version number (minor).\n */\n uint256 private immutable MINOR_VERSION;\n\n /**\n * @notice Contract version number (patch).\n */\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" - }, - "contracts/universal/StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { IOptimismMintableERC20, ILegacyMintableERC20 } from \"./IOptimismMintableERC20.sol\";\nimport { CrossDomainMessenger } from \"./CrossDomainMessenger.sol\";\nimport { OptimismMintableERC20 } from \"./OptimismMintableERC20.sol\";\n\n/**\n * @custom:upgradeable\n * @title StandardBridge\n * @notice StandardBridge is a base contract for the L1 and L2 standard ERC20 bridges. It handles\n * the core bridging logic, including escrowing tokens that are native to the local chain\n * and minting/burning tokens that are native to the remote chain.\n */\nabstract contract StandardBridge {\n using SafeERC20 for IERC20;\n\n /**\n * @notice The L2 gas limit set when eth is depoisited using the receive() function.\n */\n uint32 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 200_000;\n\n /**\n * @notice Messenger contract on this domain.\n */\n CrossDomainMessenger public immutable MESSENGER;\n\n /**\n * @notice Corresponding bridge on the other domain.\n */\n StandardBridge public immutable OTHER_BRIDGE;\n\n /**\n * @custom:legacy\n * @custom:spacer messenger\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_0_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer l2TokenBridge\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_1_0_20;\n\n /**\n * @notice Mapping that stores deposits for a given pair of local and remote tokens.\n */\n mapping(address => mapping(address => uint256)) public deposits;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n * A gap size of 47 was chosen here, so that the first slot used in a child contract\n * would be a multiple of 50.\n */\n uint256[47] private __gap;\n\n /**\n * @notice Emitted when an ETH bridge is initiated to the other chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ETH bridge is finalized on this chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is initiated to the other chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is finalized on this chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Only allow EOAs to call the functions. Note that this is not safe against contracts\n * calling code within their constructors, but also doesn't really matter since we're\n * just trying to prevent users accidentally depositing with smart contract wallets.\n */\n modifier onlyEOA() {\n require(\n !Address.isContract(msg.sender),\n \"StandardBridge: function can only be called from an EOA\"\n );\n _;\n }\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) &&\n MESSENGER.xDomainMessageSender() == address(OTHER_BRIDGE),\n \"StandardBridge: function can only be called from the other bridge\"\n );\n _;\n }\n\n /**\n * @param _messenger Address of CrossDomainMessenger on this network.\n * @param _otherBridge Address of the other StandardBridge contract.\n */\n constructor(address payable _messenger, address payable _otherBridge) {\n MESSENGER = CrossDomainMessenger(_messenger);\n OTHER_BRIDGE = StandardBridge(_otherBridge);\n }\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n * Must be implemented by contracts that inherit.\n */\n receive() external payable virtual;\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @notice Sends ETH to the sender's address on the other chain.\n *\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETH(uint32 _minGasLimit, bytes calldata _extraData) public payable onlyEOA {\n _initiateBridgeETH(msg.sender, msg.sender, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a\n * smart contract and the call fails, the ETH will be temporarily locked in the\n * StandardBridge on the other chain until the call is replayed. If the call cannot be\n * replayed with any amount of gas (call always reverts), then the ETH will be\n * permanently locked in the StandardBridge on the other chain. ETH will also\n * be locked if the receiver is the other bridge, because finalizeBridgeETH will revert\n * in that case.\n *\n * @param _to Address of the receiver.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public payable {\n _initiateBridgeETH(msg.sender, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ERC20 tokens to the sender's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20(\n address _localToken,\n address _remoteToken,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual onlyEOA {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Finalizes an ETH bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public payable onlyOtherBridge {\n require(msg.value == _amount, \"StandardBridge: amount sent does not match amount required\");\n require(_to != address(this), \"StandardBridge: cannot send to self\");\n require(_to != address(MESSENGER), \"StandardBridge: cannot send to messenger\");\n\n // Emit the correct events. By default this will be _amount, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n\n bool success = SafeCall.call(_to, gasleft(), _amount, hex\"\");\n require(success, \"StandardBridge: ETH transfer failed\");\n }\n\n /**\n * @notice Finalizes an ERC20 bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public onlyOtherBridge {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).mint(_to, _amount);\n } else {\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] - _amount;\n IERC20(_localToken).safeTransfer(_to, _amount);\n }\n\n // Emit the correct events. By default this will be ERC20BridgeFinalized, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Initiates a bridge of ETH through the CrossDomainMessenger.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n require(\n msg.value == _amount,\n \"StandardBridge: bridging ETH must include sufficient ETH value\"\n );\n\n // Emit the correct events. By default this will be _amount, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage{ value: _amount }(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeETH.selector,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).burn(_from, _amount);\n } else {\n IERC20(_localToken).safeTransferFrom(_from, address(this), _amount);\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount;\n }\n\n // Emit the correct events. By default this will be ERC20BridgeInitiated, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeERC20.selector,\n // Because this call will be executed on the remote chain, we reverse the order of\n // the remote and local token addresses relative to their order in the\n // finalizeBridgeERC20 function.\n _remoteToken,\n _localToken,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Checks if a given address is an OptimismMintableERC20. Not perfect, but good enough.\n * Just the way we like it.\n *\n * @param _token Address of the token to check.\n *\n * @return True if the token is an OptimismMintableERC20.\n */\n function _isOptimismMintableERC20(address _token) internal view returns (bool) {\n return\n ERC165Checker.supportsInterface(_token, type(ILegacyMintableERC20).interfaceId) ||\n ERC165Checker.supportsInterface(_token, type(IOptimismMintableERC20).interfaceId);\n }\n\n /**\n * @notice Checks if the \"other token\" is the correct pair token for the OptimismMintableERC20.\n * Calls can be saved in the future by combining this logic with\n * `_isOptimismMintableERC20`.\n *\n * @param _mintableToken OptimismMintableERC20 to check against.\n * @param _otherToken Pair token to check.\n *\n * @return True if the other token is the correct pair token for the OptimismMintableERC20.\n */\n function _isCorrectTokenPair(address _mintableToken, address _otherToken)\n internal\n view\n returns (bool)\n {\n if (\n ERC165Checker.supportsInterface(_mintableToken, type(ILegacyMintableERC20).interfaceId)\n ) {\n return _otherToken == ILegacyMintableERC20(_mintableToken).l1Token();\n } else {\n return _otherToken == IOptimismMintableERC20(_mintableToken).remoteToken();\n }\n }\n\n /** @notice Emits the ETHBridgeInitiated event and if necessary the appropriate legacy event\n * when an ETH bridge is finalized on this chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ETHBridgeFinalized and if necessary the appropriate legacy event when an\n * ETH bridge is finalized on this chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ERC20BridgeInitiated event and if necessary the appropriate legacy\n * event when an ERC20 bridge is initiated to the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the ERC20 on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ERC20BridgeFinalized event and if necessary the appropriate legacy\n * event when an ERC20 bridge is initiated to the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the ERC20 on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/vendor/AddressAliasHelper.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npragma solidity ^0.8.0;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n unchecked {\n l2Address = address(uint160(l1Address) + offset);\n }\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n unchecked {\n l1Address = address(uint160(l2Address) - offset);\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/access/Ownable.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/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 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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/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/Address.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) || (!Address.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" - }, - "node_modules/@openzeppelin/contracts/security/ReentrancyGuard.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\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 ReentrancyGuard {\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 constructor() {\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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, allowance(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 = allowance(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 `from` to `to`.\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 Updates `owner` s allowance for `spender` based on spent `amount`.\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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 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 /**\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (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 constant _PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n /**\n * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\n * However, to ensure consistency with the upgradeable transpiler, we will continue\n * to reserve a slot.\n * @custom:oz-renamed-from _PERMIT_TYPEHASH\n */\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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: address zero is not a valid owner\");\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: invalid token ID\");\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 _requireMinted(tokenId);\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 token 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 _requireMinted(tokenId);\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: caller is not token 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: caller is not token 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 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 an {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 an {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 Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\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 /// @solidity memory-safe-assembly\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Address.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 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 /// @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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\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 /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.3) (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 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 /// @solidity memory-safe-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 {\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.2) (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 // prepare call\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n\n // perform static call\n bool success;\n uint256 returnSize;\n uint256 returnValue;\n assembly {\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\n returnSize := returndatasize()\n returnValue := mload(0x00)\n }\n\n return success && returnSize >= 0x20 && returnValue > 0;\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\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 == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`.\n // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.\n // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.\n // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a\n // good first aproximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1;\n uint256 x = a;\n if (x >> 128 > 0) {\n x >>= 128;\n result <<= 64;\n }\n if (x >> 64 > 0) {\n x >>= 64;\n result <<= 32;\n }\n if (x >> 32 > 0) {\n x >>= 32;\n result <<= 16;\n }\n if (x >> 16 > 0) {\n x >>= 16;\n result <<= 8;\n }\n if (x >> 8 > 0) {\n x >>= 8;\n result <<= 4;\n }\n if (x >> 4 > 0) {\n x >>= 4;\n result <<= 2;\n }\n if (x >> 2 > 0) {\n result <<= 1;\n }\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n uint256 result = sqrt(a);\n if (rounding == Rounding.Up && result * result < a) {\n result += 1;\n }\n return result;\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\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 * _Available since v4.2._\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 uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(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 * _Available since v2.5._\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 uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(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 * _Available since v4.2._\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 uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(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 * _Available since v2.5._\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 uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(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 * _Available since v2.5._\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 uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(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 * _Available since v2.5._\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 * _Available since v2.5._\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 * _Available since v3.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 int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248) {\n require(value >= type(int248).min && value <= type(int248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return int248(value);\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240) {\n require(value >= type(int240).min && value <= type(int240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return int240(value);\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232) {\n require(value >= type(int232).min && value <= type(int232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return int232(value);\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224) {\n require(value >= type(int224).min && value <= type(int224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return int224(value);\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216) {\n require(value >= type(int216).min && value <= type(int216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return int216(value);\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208) {\n require(value >= type(int208).min && value <= type(int208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return int208(value);\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200) {\n require(value >= type(int200).min && value <= type(int200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return int200(value);\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192) {\n require(value >= type(int192).min && value <= type(int192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return int192(value);\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184) {\n require(value >= type(int184).min && value <= type(int184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return int184(value);\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176) {\n require(value >= type(int176).min && value <= type(int176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return int176(value);\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168) {\n require(value >= type(int168).min && value <= type(int168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return int168(value);\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160) {\n require(value >= type(int160).min && value <= type(int160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return int160(value);\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152) {\n require(value >= type(int152).min && value <= type(int152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return int152(value);\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144) {\n require(value >= type(int144).min && value <= type(int144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return int144(value);\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136) {\n require(value >= type(int136).min && value <= type(int136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return int136(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 int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120) {\n require(value >= type(int120).min && value <= type(int120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return int120(value);\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112) {\n require(value >= type(int112).min && value <= type(int112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return int112(value);\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104) {\n require(value >= type(int104).min && value <= type(int104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return int104(value);\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96) {\n require(value >= type(int96).min && value <= type(int96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return int96(value);\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88) {\n require(value >= type(int88).min && value <= type(int88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return int88(value);\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80) {\n require(value >= type(int80).min && value <= type(int80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return int80(value);\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72) {\n require(value >= type(int72).min && value <= type(int72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return int72(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 int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56) {\n require(value >= type(int56).min && value <= type(int56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return int56(value);\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48) {\n require(value >= type(int48).min && value <= type(int48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return int48(value);\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40) {\n require(value >= type(int40).min && value <= type(int40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return int40(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 int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24) {\n require(value >= type(int24).min && value <= type(int24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return int24(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 * _Available since v3.0._\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" - }, - "node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@rari-capital/solmate/src/utils/Bytes32AddressLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Library for converting between addresses and bytes32 values.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/Bytes32AddressLib.sol)\nlibrary Bytes32AddressLib {\n function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n function fillLast12Bytes(address addressValue) internal pure returns (bytes32) {\n return bytes32(bytes20(addressValue));\n }\n}\n" - }, - "node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)\nlibrary FixedPointMathLib {\n /*//////////////////////////////////////////////////////////////\n SIMPLIFIED FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n }\n\n function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n }\n\n function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n }\n\n function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n }\n\n function powWad(int256 x, int256 y) internal pure returns (int256) {\n // Equivalent to x to the power of y because x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)\n return expWad((lnWad(x) * y) / int256(WAD)); // Using ln(x) means x must be greater than 0.\n }\n\n function expWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n // When the result is < 0.5 we return zero. This happens when\n // x <= floor(log(0.5e18) * 1e18) ~ -42e18\n if (x <= -42139678854452767551) return 0;\n\n // When the result is > (2**255 - 1) / 1e18 we can not represent it as an\n // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.\n if (x >= 135305999368893231589) revert(\"EXP_OVERFLOW\");\n\n // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96\n // for more intermediate precision and a binary basis. This base conversion\n // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.\n x = (x << 78) / 5**18;\n\n // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers\n // of two such that exp(x) = exp(x') * 2**k, where k is an integer.\n // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).\n int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96;\n x = x - k * 54916777467707473351141471128;\n\n // k is in the range [-61, 195].\n\n // Evaluate using a (6, 7)-term rational approximation.\n // p is made monic, we'll multiply by a scale factor later.\n int256 y = x + 1346386616545796478920950773328;\n y = ((y * x) >> 96) + 57155421227552351082224309758442;\n int256 p = y + x - 94201549194550492254356042504812;\n p = ((p * y) >> 96) + 28719021644029726153956944680412240;\n p = p * x + (4385272521454847904659076985693276 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n int256 q = x - 2855989394907223263936484059900;\n q = ((q * x) >> 96) + 50020603652535783019961831881945;\n q = ((q * x) >> 96) - 533845033583426703283633433725380;\n q = ((q * x) >> 96) + 3604857256930695427073651918091429;\n q = ((q * x) >> 96) - 14423608567350463180887372962807573;\n q = ((q * x) >> 96) + 26449188498355588339934803723976023;\n\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial won't have zeros in the domain as all its roots are complex.\n // No scaling is necessary because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r should be in the range (0.09, 0.25) * 2**96.\n\n // We now need to multiply r by:\n // * the scale factor s = ~6.031367120.\n // * the 2**k factor from the range reduction.\n // * the 1e18 / 2**96 factor for base conversion.\n // We do this all at once, with an intermediate result in 2**213\n // basis, so the final right shift is always by a positive amount.\n r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k));\n }\n }\n\n function lnWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n require(x > 0, \"UNDEFINED\");\n\n // We want to convert x from 10**18 fixed point to 2**96 fixed point.\n // We do this by multiplying by 2**96 / 10**18. But since\n // ln(x * C) = ln(x) + ln(C), we can simply do nothing here\n // and add ln(2**96 / 10**18) at the end.\n\n // Reduce range of x to (1, 2) * 2**96\n // ln(2^k * x) = k * ln(2) + ln(x)\n int256 k = int256(log2(uint256(x))) - 96;\n x <<= uint256(159 - k);\n x = int256(uint256(x) >> 159);\n\n // Evaluate using a (8, 8)-term rational approximation.\n // p is made monic, we will multiply by a scale factor later.\n int256 p = x + 3273285459638523848632254066296;\n p = ((p * x) >> 96) + 24828157081833163892658089445524;\n p = ((p * x) >> 96) + 43456485725739037958740375743393;\n p = ((p * x) >> 96) - 11111509109440967052023855526967;\n p = ((p * x) >> 96) - 45023709667254063763336534515857;\n p = ((p * x) >> 96) - 14706773417378608786704636184526;\n p = p * x - (795164235651350426258249787498 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n // q is monic by convention.\n int256 q = x + 5573035233440673466300451813936;\n q = ((q * x) >> 96) + 71694874799317883764090561454958;\n q = ((q * x) >> 96) + 283447036172924575727196451306956;\n q = ((q * x) >> 96) + 401686690394027663651624208769553;\n q = ((q * x) >> 96) + 204048457590392012362485061816622;\n q = ((q * x) >> 96) + 31853899698501571402653359427138;\n q = ((q * x) >> 96) + 909429971244387300277376558375;\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial is known not to have zeros in the domain.\n // No scaling required because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r is in the range (0, 0.125) * 2**96\n\n // Finalization, we need to:\n // * multiply by the scale factor s = 5.549…\n // * add ln(2**96 / 10**18)\n // * add k * ln(2)\n // * multiply by 10**18 / 2**96 = 5**18 >> 78\n\n // mul s * 5e18 * 2**96, base is now 5**18 * 2**192\n r *= 1677202110996718588342820967067443963516166;\n // add ln(2) * k * 5e18 * 2**192\n r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;\n // add ln(2**96 / 10**18) * 5e18 * 2**192\n r += 600920179829731861736702779321621459595472258049074101567377883020018308;\n // base conversion: mul 2**18 / 2**192\n r >>= 174;\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n LOW LEVEL FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function mulDivDown(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // Divide z by the denominator.\n z := div(z, denominator)\n }\n }\n\n function mulDivUp(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // First, divide z - 1 by the denominator and add 1.\n // We allow z - 1 to underflow if z is 0, because we multiply the\n // end result by 0 if z is zero, ensuring we return 0 if z is zero.\n z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))\n }\n }\n\n function rpow(\n uint256 x,\n uint256 n,\n uint256 scalar\n ) internal pure returns (uint256 z) {\n assembly {\n switch x\n case 0 {\n switch n\n case 0 {\n // 0 ** 0 = 1\n z := scalar\n }\n default {\n // 0 ** n = 0\n z := 0\n }\n }\n default {\n switch mod(n, 2)\n case 0 {\n // If n is even, store scalar in z for now.\n z := scalar\n }\n default {\n // If n is odd, store x in z for now.\n z := x\n }\n\n // Shifting right by 1 is like dividing by 2.\n let half := shr(1, scalar)\n\n for {\n // Shift n right by 1 before looping to halve it.\n n := shr(1, n)\n } n {\n // Shift n right by 1 each iteration to halve it.\n n := shr(1, n)\n } {\n // Revert immediately if x ** 2 would overflow.\n // Equivalent to iszero(eq(div(xx, x), x)) here.\n if shr(128, x) {\n revert(0, 0)\n }\n\n // Store x squared.\n let xx := mul(x, x)\n\n // Round to the nearest number.\n let xxRound := add(xx, half)\n\n // Revert if xx + half overflowed.\n if lt(xxRound, xx) {\n revert(0, 0)\n }\n\n // Set x to scaled xxRound.\n x := div(xxRound, scalar)\n\n // If n is even:\n if mod(n, 2) {\n // Compute z * x.\n let zx := mul(z, x)\n\n // If z * x overflowed:\n if iszero(eq(div(zx, x), z)) {\n // Revert if x is non-zero.\n if iszero(iszero(x)) {\n revert(0, 0)\n }\n }\n\n // Round to the nearest number.\n let zxRound := add(zx, half)\n\n // Revert if zx + half overflowed.\n if lt(zxRound, zx) {\n revert(0, 0)\n }\n\n // Return properly scaled zxRound.\n z := div(zxRound, scalar)\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n GENERAL NUMBER UTILITIES\n //////////////////////////////////////////////////////////////*/\n\n function sqrt(uint256 x) internal pure returns (uint256 z) {\n assembly {\n let y := x // We start y at x, which will help us make our initial estimate.\n\n z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n // We check y >= 2^(k + 8) but shift right by k bits\n // each branch to ensure that if x >= 256, then y >= 256.\n if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n y := shr(128, y)\n z := shl(64, z)\n }\n if iszero(lt(y, 0x1000000000000000000)) {\n y := shr(64, y)\n z := shl(32, z)\n }\n if iszero(lt(y, 0x10000000000)) {\n y := shr(32, y)\n z := shl(16, z)\n }\n if iszero(lt(y, 0x1000000)) {\n y := shr(16, y)\n z := shl(8, z)\n }\n\n // Goal was to get z*z*y within a small factor of x. More iterations could\n // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n // There is no overflow risk here since y < 2^136 after the first branch above.\n z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n\n // If x+1 is a perfect square, the Babylonian method cycles between\n // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n z := sub(z, lt(div(x, z), z))\n }\n }\n\n function log2(uint256 x) internal pure returns (uint256 r) {\n require(x > 0, \"UNDEFINED\");\n\n assembly {\n r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n r := or(r, shl(4, lt(0xffff, shr(r, x))))\n r := or(r, shl(3, lt(0xff, shr(r, x))))\n r := or(r, shl(2, lt(0xf, shr(r, x))))\n r := or(r, shl(1, lt(0x3, shr(r, x))))\n r := or(r, lt(0x1, shr(r, x)))\n }\n }\n}\n" - }, - "node_modules/clones-with-immutable-args/src/ClonesWithImmutableArgs.sol": { - "content": "// SPDX-License-Identifier: BSD\n\npragma solidity ^0.8.4;\n\n/// @title ClonesWithImmutableArgs\n/// @author wighawag, zefram.eth, Saw-mon & Natalie\n/// @notice Enables creating clone contracts with immutable args\nlibrary ClonesWithImmutableArgs {\n uint256 private constant FREE_MEMORY_POINTER_SLOT = 0x40;\n uint256 private constant BOOTSTRAP_LENGTH = 0x3f;\n uint256 private constant ONE_WORD = 0x20;\n uint256 private constant MAX_UINT256 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n bytes32 private constant CREATE_FAIL_ERROR = 0xebfef18800000000000000000000000000000000000000000000000000000000;\n\n /// @notice Creates a clone proxy of the implementation contract, with immutable args\n /// @dev data cannot exceed 65535 bytes, since 2 bytes are used to store the data length\n /// @param implementation The implementation contract to clone\n /// @param data Encoded immutable args\n /// @return instance The address of the created clone\n function clone(address implementation, bytes memory data)\n internal\n returns (address payable instance)\n {\n // unrealistic for memory ptr or data length to exceed 256 bits\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let extraLength := add(mload(data), 2) // +2 bytes for telling how much data there is appended to the call\n let creationSize := add(extraLength, BOOTSTRAP_LENGTH)\n let runSize := sub(creationSize, 0x0a)\n\n // free memory pointer\n let ptr := mload(FREE_MEMORY_POINTER_SLOT)\n \n // -------------------------------------------------------------------------------------------------------------\n // CREATION (10 bytes)\n // -------------------------------------------------------------------------------------------------------------\n\n // 61 runtime | PUSH2 runtime (r) | r | –\n // 3d | RETURNDATASIZE | 0 r | –\n // 81 | DUP2 | r 0 r | –\n // 60 offset | PUSH1 offset (o) | o r 0 r | –\n // 3d | RETURNDATASIZE | 0 o r 0 r | –\n // 39 | CODECOPY | 0 r | [0 - runSize): runtime code\n // f3 | RETURN | | [0 - runSize): runtime code\n\n // -------------------------------------------------------------------------------------------------------------\n // RUNTIME (53 bytes + extraLength)\n // -------------------------------------------------------------------------------------------------------------\n\n // --- copy calldata to memmory ---\n // 36 | CALLDATASIZE | cds | –\n // 3d | RETURNDATASIZE | 0 cds | –\n // 3d | RETURNDATASIZE | 0 0 cds | –\n // 37 | CALLDATACOPY | | [0 - cds): calldata\n\n // --- keep some values in stack ---\n // 3d | RETURNDATASIZE | 0 | [0 - cds): calldata\n // 3d | RETURNDATASIZE | 0 0 | [0 - cds): calldata\n // 3d | RETURNDATASIZE | 0 0 0 | [0 - cds): calldata\n // 3d | RETURNDATASIZE | 0 0 0 0 | [0 - cds): calldata\n // 61 extra | PUSH2 extra (e) | e 0 0 0 0 | [0 - cds): calldata\n\n // --- copy extra data to memory ---\n // 80 | DUP1 | e e 0 0 0 0 | [0 - cds): calldata\n // 60 0x35 | PUSH1 0x35 | 0x35 e e 0 0 0 0 | [0 - cds): calldata\n // 36 | CALLDATASIZE | cds 0x35 e e 0 0 0 0 | [0 - cds): calldata\n // 39 | CODECOPY | e 0 0 0 0 | [0 - cds): calldata, [cds - cds + e): extraData\n\n // --- delegate call to the implementation contract ---\n // 36 | CALLDATASIZE | cds e 0 0 0 0 | [0 - cds): calldata, [cds - cds + e): extraData\n // 01 | ADD | cds+e 0 0 0 0 | [0 - cds): calldata, [cds - cds + e): extraData\n // 3d | RETURNDATASIZE | 0 cds+e 0 0 0 0 | [0 - cds): calldata, [cds - cds + e): extraData\n // 73 addr | PUSH20 addr | addr 0 cds+e 0 0 0 0 | [0 - cds): calldata, [cds - cds + e): extraData\n // 5a | GAS | gas addr 0 cds+e 0 0 0 0| [0 - cds): calldata, [cds - cds + e): extraData\n // f4 | DELEGATECALL | success 0 0 | [0 - cds): calldata, [cds - cds + e): extraData\n\n // --- copy return data to memory ---\n // 3d | RETURNDATASIZE | rds success 0 0 | [0 - cds): calldata, [cds - cds + e): extraData\n // 3d | RETURNDATASIZE | rds rds success 0 0 | [0 - cds): calldata, [cds - cds + e): extraData\n // 93 | SWAP4 | 0 rds success 0 rds | [0 - cds): calldata, [cds - cds + e): extraData\n // 80 | DUP1 | 0 0 rds success 0 rds | [0 - cds): calldata, [cds - cds + e): extraData\n // 3e | RETURNDATACOPY | success 0 rds | [0 - rds): returndata, ... the rest might be dirty\n \n // 60 0x33 | PUSH1 0x33 | 0x33 success 0 rds | [0 - rds): returndata, ... the rest might be dirty\n // 57 | JUMPI | 0 rds | [0 - rds): returndata, ... the rest might be dirty\n\n // --- revert ---\n // fd | REVERT | | [0 - rds): returndata, ... the rest might be dirty\n\n // --- return ---\n // 5b | JUMPDEST | 0 rds | [0 - rds): returndata, ... the rest might be dirty\n // f3 | RETURN | | [0 - rds): returndata, ... the rest might be dirty\n\n mstore(\n ptr,\n or(\n hex\"610000_3d_81_600a_3d_39_f3_36_3d_3d_37_3d_3d_3d_3d_610000_80_6035_36_39_36_01_3d_73\",\n or(\n shl(0xe8, runSize),\n shl(0x58, extraLength)\n )\n )\n )\n \n mstore(\n add(ptr, 0x1e),\n shl(0x60, implementation)\n )\n\n mstore(\n add(ptr, 0x32),\n hex\"5a_f4_3d_3d_93_80_3e_6033_57_fd_5b_f3\"\n )\n\n\n // -------------------------------------------------------------------------------------------------------------\n // APPENDED DATA (Accessible from extcodecopy)\n // (but also send as appended data to the delegatecall)\n // -------------------------------------------------------------------------------------------------------------\n\n let counter := mload(data)\n let copyPtr := add(ptr, BOOTSTRAP_LENGTH)\n let dataPtr := add(data, ONE_WORD)\n\n for {} true {} {\n if lt(counter, ONE_WORD) {\n break\n }\n\n mstore(copyPtr, mload(dataPtr))\n\n copyPtr := add(copyPtr, ONE_WORD)\n dataPtr := add(dataPtr, ONE_WORD)\n\n counter := sub(counter, ONE_WORD)\n }\n \n let mask := shl(\n shl(3, sub(ONE_WORD, counter)), \n MAX_UINT256\n )\n\n mstore(copyPtr, and(mload(dataPtr), mask))\n copyPtr := add(copyPtr, counter)\n mstore(copyPtr, shl(0xf0, extraLength))\n\n instance := create(0, ptr, creationSize)\n\n if iszero(instance) {\n // revert CreateFail()\n mstore(0, CREATE_FAIL_ERROR)\n revert(0, ONE_WORD)\n }\n\n // Update free memory pointer\n mstore(FREE_MEMORY_POINTER_SLOT, add(ptr, creationSize))\n }\n }\n}\n" - }, - "node_modules/ds-test/src/test.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see .\n\npragma solidity >=0.5.0;\n\ncontract DSTest {\n event log (string);\n event logs (bytes);\n\n event log_address (address);\n event log_bytes32 (bytes32);\n event log_int (int);\n event log_uint (uint);\n event log_bytes (bytes);\n event log_string (string);\n\n event log_named_address (string key, address val);\n event log_named_bytes32 (string key, bytes32 val);\n event log_named_decimal_int (string key, int val, uint decimals);\n event log_named_decimal_uint (string key, uint val, uint decimals);\n event log_named_int (string key, int val);\n event log_named_uint (string key, uint val);\n event log_named_bytes (string key, bytes val);\n event log_named_string (string key, string val);\n\n bool public IS_TEST = true;\n bool private _failed;\n\n address constant HEVM_ADDRESS =\n address(bytes20(uint160(uint256(keccak256('hevm cheat code')))));\n\n modifier mayRevert() { _; }\n modifier testopts(string memory) { _; }\n\n function failed() public returns (bool) {\n if (_failed) {\n return _failed;\n } else {\n bool globalFailed = false;\n if (hasHEVMContext()) {\n (, bytes memory retdata) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"load(address,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"))\n )\n );\n globalFailed = abi.decode(retdata, (bool));\n }\n return globalFailed;\n }\n } \n\n function fail() internal {\n if (hasHEVMContext()) {\n (bool status, ) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"store(address,bytes32,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"), bytes32(uint256(0x01)))\n )\n );\n status; // Silence compiler warnings\n }\n _failed = true;\n }\n\n function hasHEVMContext() internal view returns (bool) {\n uint256 hevmCodeSize = 0;\n assembly {\n hevmCodeSize := extcodesize(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D)\n }\n return hevmCodeSize > 0;\n }\n\n modifier logs_gas() {\n uint startGas = gasleft();\n _;\n uint endGas = gasleft();\n emit log_named_uint(\"gas\", startGas - endGas);\n }\n\n function assertTrue(bool condition) internal {\n if (!condition) {\n emit log(\"Error: Assertion Failed\");\n fail();\n }\n }\n\n function assertTrue(bool condition, string memory err) internal {\n if (!condition) {\n emit log_named_string(\"Error\", err);\n assertTrue(condition);\n }\n }\n\n function assertEq(address a, address b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [address]\");\n emit log_named_address(\" Expected\", b);\n emit log_named_address(\" Actual\", a);\n fail();\n }\n }\n function assertEq(address a, address b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes32 a, bytes32 b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bytes32]\");\n emit log_named_bytes32(\" Expected\", b);\n emit log_named_bytes32(\" Actual\", a);\n fail();\n }\n }\n function assertEq(bytes32 a, bytes32 b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq32(bytes32 a, bytes32 b) internal {\n assertEq(a, b);\n }\n function assertEq32(bytes32 a, bytes32 b, string memory err) internal {\n assertEq(a, b, err);\n }\n\n function assertEq(int a, int b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [int]\");\n emit log_named_int(\" Expected\", b);\n emit log_named_int(\" Actual\", a);\n fail();\n }\n }\n function assertEq(int a, int b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq(uint a, uint b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [uint]\");\n emit log_named_uint(\" Expected\", b);\n emit log_named_uint(\" Actual\", a);\n fail();\n }\n }\n function assertEq(uint a, uint b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEqDecimal(int a, int b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Expected\", b, decimals);\n emit log_named_decimal_int(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Expected\", b, decimals);\n emit log_named_decimal_uint(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n\n function assertGt(uint a, uint b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGt(uint a, uint b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGt(int a, int b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGt(int a, int b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGtDecimal(int a, int b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n\n function assertGe(uint a, uint b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGe(uint a, uint b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGe(int a, int b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGe(int a, int b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGeDecimal(int a, int b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertLt(uint a, uint b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLt(uint a, uint b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLt(int a, int b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLt(int a, int b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLtDecimal(int a, int b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n\n function assertLe(uint a, uint b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLe(uint a, uint b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLe(int a, int b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLe(int a, int b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLeDecimal(int a, int b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLeDecimal(a, b, decimals);\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertEq(string memory a, string memory b) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log(\"Error: a == b not satisfied [string]\");\n emit log_named_string(\" Expected\", b);\n emit log_named_string(\" Actual\", a);\n fail();\n }\n }\n function assertEq(string memory a, string memory b, string memory err) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function checkEq0(bytes memory a, bytes memory b) internal pure returns (bool ok) {\n ok = true;\n if (a.length == b.length) {\n for (uint i = 0; i < a.length; i++) {\n if (a[i] != b[i]) {\n ok = false;\n }\n }\n } else {\n ok = false;\n }\n }\n function assertEq0(bytes memory a, bytes memory b) internal {\n if (!checkEq0(a, b)) {\n emit log(\"Error: a == b not satisfied [bytes]\");\n emit log_named_bytes(\" Expected\", b);\n emit log_named_bytes(\" Actual\", a);\n fail();\n }\n }\n function assertEq0(bytes memory a, bytes memory b, string memory err) internal {\n if (!checkEq0(a, b)) {\n emit log_named_string(\"Error\", err);\n assertEq0(a, b);\n }\n }\n}\n" - }, - "node_modules/forge-std/src/Base.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {StdStorage} from \"./StdStorage.sol\";\nimport {Vm, VmSafe} from \"./Vm.sol\";\n\nabstract contract CommonBase {\n // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.\n address internal constant VM_ADDRESS = address(uint160(uint256(keccak256(\"hevm cheat code\"))));\n // console.sol and console2.sol work by executing a staticcall to this address.\n address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;\n // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38.\n address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256(\"foundry default caller\"))));\n // Address of the test contract, deployed by the DEFAULT_SENDER.\n address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;\n // Deterministic deployment address of the Multicall3 contract.\n address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11;\n\n uint256 internal constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n Vm internal constant vm = Vm(VM_ADDRESS);\n StdStorage internal stdstore;\n}\n\nabstract contract TestBase is CommonBase {}\n\nabstract contract ScriptBase is CommonBase {\n // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.\n address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;\n\n VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);\n}\n" - }, - "node_modules/forge-std/src/StdAssertions.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {DSTest} from \"ds-test/test.sol\";\nimport {stdMath} from \"./StdMath.sol\";\n\nabstract contract StdAssertions is DSTest {\n event log_array(uint256[] val);\n event log_array(int256[] val);\n event log_array(address[] val);\n event log_named_array(string key, uint256[] val);\n event log_named_array(string key, int256[] val);\n event log_named_array(string key, address[] val);\n\n function fail(string memory err) internal virtual {\n emit log_named_string(\"Error\", err);\n fail();\n }\n\n function assertFalse(bool data) internal virtual {\n assertTrue(!data);\n }\n\n function assertFalse(bool data, string memory err) internal virtual {\n assertTrue(!data, err);\n }\n\n function assertEq(bool a, bool b) internal virtual {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bool]\");\n emit log_named_string(\" Left\", a ? \"true\" : \"false\");\n emit log_named_string(\" Right\", b ? \"true\" : \"false\");\n fail();\n }\n }\n\n function assertEq(bool a, bool b, string memory err) internal virtual {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes memory a, bytes memory b) internal virtual {\n assertEq0(a, b);\n }\n\n function assertEq(bytes memory a, bytes memory b, string memory err) internal virtual {\n assertEq0(a, b, err);\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [uint[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [int[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(address[] memory a, address[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [address[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(address[] memory a, address[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n // Legacy helper\n function assertEqUint(uint256 a, uint256 b) internal virtual {\n assertEq(uint256(a), uint256(b));\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Left\", a);\n emit log_named_uint(\" Right\", b);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_decimal_uint(\" Left\", a, decimals);\n emit log_named_decimal_uint(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max Delta\", maxDelta, decimals);\n emit log_named_decimal_uint(\" Delta\", delta, decimals);\n fail();\n }\n }\n\n function assertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbsDecimal(a, b, maxDelta, decimals);\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Left\", a);\n emit log_named_int(\" Right\", b);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_decimal_int(\" Left\", a, decimals);\n emit log_named_decimal_int(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max Delta\", maxDelta, decimals);\n emit log_named_decimal_uint(\" Delta\", delta, decimals);\n fail();\n }\n }\n\n function assertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbsDecimal(a, b, maxDelta, decimals);\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%\n ) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Left\", a);\n emit log_named_uint(\" Right\", b);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n string memory err\n ) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n\n function assertApproxEqRelDecimal(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n uint256 decimals\n ) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_decimal_uint(\" Left\", a, decimals);\n emit log_named_decimal_uint(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRelDecimal(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n uint256 decimals,\n string memory err\n ) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Left\", a);\n emit log_named_int(\" Right\", b);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta, string memory err) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n\n function assertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_decimal_int(\" Left\", a, decimals);\n emit log_named_decimal_int(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);\n }\n }\n\n function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual {\n assertEqCall(target, callDataA, target, callDataB, true);\n }\n\n function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB)\n internal\n virtual\n {\n assertEqCall(targetA, callDataA, targetB, callDataB, true);\n }\n\n function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData)\n internal\n virtual\n {\n assertEqCall(target, callDataA, target, callDataB, strictRevertData);\n }\n\n function assertEqCall(\n address targetA,\n bytes memory callDataA,\n address targetB,\n bytes memory callDataB,\n bool strictRevertData\n ) internal virtual {\n (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA);\n (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB);\n\n if (successA && successB) {\n assertEq(returnDataA, returnDataB, \"Call return data does not match\");\n }\n\n if (!successA && !successB && strictRevertData) {\n assertEq(returnDataA, returnDataB, \"Call revert data does not match\");\n }\n\n if (!successA && successB) {\n emit log(\"Error: Calls were not equal\");\n emit log_named_bytes(\" Left call revert data\", returnDataA);\n emit log_named_bytes(\" Right call return data\", returnDataB);\n fail();\n }\n\n if (successA && !successB) {\n emit log(\"Error: Calls were not equal\");\n emit log_named_bytes(\" Left call return data\", returnDataA);\n emit log_named_bytes(\" Right call revert data\", returnDataB);\n fail();\n }\n }\n}\n" - }, - "node_modules/forge-std/src/StdChains.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n/**\n * StdChains provides information about EVM compatible chains that can be used in scripts/tests.\n * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are\n * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of\n * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the\n * alias used in this contract, which can be found as the first argument to the\n * `setChainWithDefaultRpcUrl` call in the `initialize` function.\n *\n * There are two main ways to use this contract:\n * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or\n * `setChain(string memory chainAlias, Chain memory chain)`\n * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.\n *\n * The first time either of those are used, chains are initialized with the default set of RPC URLs.\n * This is done in `initialize`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in\n * `defaultRpcUrls`.\n *\n * The `setChain` function is straightforward, and it simply saves off the given chain data.\n *\n * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say\n * we want to retrieve `mainnet`'s RPC URL:\n * - If you haven't set any mainnet chain info with `setChain`, you haven't specified that\n * chain in `foundry.toml` and no env var is set, the default data and RPC URL will be returned.\n * - If you have set a mainnet RPC URL in `foundry.toml` it will return that, if valid (e.g. if\n * a URL is given or if an environment variable is given and that environment variable exists).\n * Otherwise, the default data is returned.\n * - If you specified data with `setChain` it will return that.\n *\n * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults.\n */\nabstract contract StdChains {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private initialized;\n\n struct ChainData {\n string name;\n uint256 chainId;\n string rpcUrl;\n }\n\n struct Chain {\n // The chain name.\n string name;\n // The chain's Chain ID.\n uint256 chainId;\n // The chain's alias. (i.e. what gets specified in `foundry.toml`).\n string chainAlias;\n // A default RPC endpoint for this chain.\n // NOTE: This default RPC URL is included for convenience to facilitate quick tests and\n // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy\n // usage as you will be throttled and this is a disservice to others who need this endpoint.\n string rpcUrl;\n }\n\n // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.\n mapping(string => Chain) private chains;\n // Maps from the chain's alias to it's default RPC URL.\n mapping(string => string) private defaultRpcUrls;\n // Maps from a chain ID to it's alias.\n mapping(uint256 => string) private idToAlias;\n\n bool private fallbackToDefaultRpcUrls = true;\n\n // The RPC URL will be fetched from config or defaultRpcUrls if possible.\n function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {\n require(bytes(chainAlias).length != 0, \"StdChains getChain(string): Chain alias cannot be the empty string.\");\n\n initialize();\n chain = chains[chainAlias];\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(string): Chain with alias \\\"\", chainAlias, \"\\\" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {\n require(chainId != 0, \"StdChains getChain(uint256): Chain ID cannot be 0.\");\n initialize();\n string memory chainAlias = idToAlias[chainId];\n\n chain = chains[chainAlias];\n\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(uint256): Chain with ID \", vm.toString(chainId), \" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n // set chain info, with priority to argument's rpcUrl field.\n function setChain(string memory chainAlias, ChainData memory chain) internal virtual {\n require(\n bytes(chainAlias).length != 0,\n \"StdChains setChain(string,ChainData): Chain alias cannot be the empty string.\"\n );\n\n require(chain.chainId != 0, \"StdChains setChain(string,ChainData): Chain ID cannot be 0.\");\n\n initialize();\n string memory foundAlias = idToAlias[chain.chainId];\n\n require(\n bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)),\n string(\n abi.encodePacked(\n \"StdChains setChain(string,ChainData): Chain ID \",\n vm.toString(chain.chainId),\n \" already used by \\\"\",\n foundAlias,\n \"\\\".\"\n )\n )\n );\n\n uint256 oldChainId = chains[chainAlias].chainId;\n delete idToAlias[oldChainId];\n\n chains[chainAlias] =\n Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});\n idToAlias[chain.chainId] = chainAlias;\n }\n\n // set chain info, with priority to argument's rpcUrl field.\n function setChain(string memory chainAlias, Chain memory chain) internal virtual {\n setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));\n }\n\n function _toUpper(string memory str) private pure returns (string memory) {\n bytes memory strb = bytes(str);\n bytes memory copy = new bytes(strb.length);\n for (uint256 i = 0; i < strb.length; i++) {\n bytes1 b = strb[i];\n if (b >= 0x61 && b <= 0x7A) {\n copy[i] = bytes1(uint8(b) - 32);\n } else {\n copy[i] = b;\n }\n }\n return string(copy);\n }\n\n // lookup rpcUrl, in descending order of priority:\n // current -> config (foundry.toml) -> environment variable -> default\n function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) private returns (Chain memory) {\n if (bytes(chain.rpcUrl).length == 0) {\n try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {\n chain.rpcUrl = configRpcUrl;\n } catch (bytes memory err) {\n string memory envName = string(abi.encodePacked(_toUpper(chainAlias), \"_RPC_URL\"));\n if (fallbackToDefaultRpcUrls) {\n chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]);\n } else {\n chain.rpcUrl = vm.envString(envName);\n }\n // distinguish 'not found' from 'cannot read'\n bytes memory notFoundError =\n abi.encodeWithSignature(\"CheatCodeError\", string(abi.encodePacked(\"invalid rpc url \", chainAlias)));\n if (keccak256(notFoundError) != keccak256(err) || bytes(chain.rpcUrl).length == 0) {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, err), mload(err))\n }\n }\n }\n }\n return chain;\n }\n\n function setFallbackToDefaultRpcUrls(bool useDefault) internal {\n fallbackToDefaultRpcUrls = useDefault;\n }\n\n function initialize() private {\n if (initialized) return;\n\n initialized = true;\n\n // If adding an RPC here, make sure to test the default RPC URL in `testRpcs`\n setChainWithDefaultRpcUrl(\"anvil\", ChainData(\"Anvil\", 31337, \"http://127.0.0.1:8545\"));\n setChainWithDefaultRpcUrl(\n \"mainnet\", ChainData(\"Mainnet\", 1, \"https://mainnet.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\n \"goerli\", ChainData(\"Goerli\", 5, \"https://goerli.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\n \"sepolia\", ChainData(\"Sepolia\", 11155111, \"https://sepolia.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\"optimism\", ChainData(\"Optimism\", 10, \"https://mainnet.optimism.io\"));\n setChainWithDefaultRpcUrl(\"optimism_goerli\", ChainData(\"Optimism Goerli\", 420, \"https://goerli.optimism.io\"));\n setChainWithDefaultRpcUrl(\"arbitrum_one\", ChainData(\"Arbitrum One\", 42161, \"https://arb1.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\n \"arbitrum_one_goerli\", ChainData(\"Arbitrum One Goerli\", 421613, \"https://goerli-rollup.arbitrum.io/rpc\")\n );\n setChainWithDefaultRpcUrl(\"arbitrum_nova\", ChainData(\"Arbitrum Nova\", 42170, \"https://nova.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\"polygon\", ChainData(\"Polygon\", 137, \"https://polygon-rpc.com\"));\n setChainWithDefaultRpcUrl(\n \"polygon_mumbai\", ChainData(\"Polygon Mumbai\", 80001, \"https://rpc-mumbai.maticvigil.com\")\n );\n setChainWithDefaultRpcUrl(\"avalanche\", ChainData(\"Avalanche\", 43114, \"https://api.avax.network/ext/bc/C/rpc\"));\n setChainWithDefaultRpcUrl(\n \"avalanche_fuji\", ChainData(\"Avalanche Fuji\", 43113, \"https://api.avax-test.network/ext/bc/C/rpc\")\n );\n setChainWithDefaultRpcUrl(\n \"bnb_smart_chain\", ChainData(\"BNB Smart Chain\", 56, \"https://bsc-dataseed1.binance.org\")\n );\n setChainWithDefaultRpcUrl(\n \"bnb_smart_chain_testnet\",\n ChainData(\"BNB Smart Chain Testnet\", 97, \"https://rpc.ankr.com/bsc_testnet_chapel\")\n );\n setChainWithDefaultRpcUrl(\"gnosis_chain\", ChainData(\"Gnosis Chain\", 100, \"https://rpc.gnosischain.com\"));\n }\n\n // set chain info, with priority to chainAlias' rpc url in foundry.toml\n function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {\n string memory rpcUrl = chain.rpcUrl;\n defaultRpcUrls[chainAlias] = rpcUrl;\n chain.rpcUrl = \"\";\n setChain(chainAlias, chain);\n chain.rpcUrl = rpcUrl; // restore argument\n }\n}\n" - }, - "node_modules/forge-std/src/StdCheats.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {Vm} from \"./Vm.sol\";\n\nabstract contract StdCheatsSafe {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private gasMeteringOff;\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawTx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n // json value name = function\n string functionSig;\n bytes32 hash;\n // json value name = tx\n RawTx1559Detail txDetail;\n // json value name = type\n string opcode;\n }\n\n struct RawTx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n bytes gas;\n bytes nonce;\n address to;\n bytes txType;\n bytes value;\n }\n\n struct Tx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n bytes32 hash;\n Tx1559Detail txDetail;\n string opcode;\n }\n\n struct Tx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n uint256 gas;\n uint256 nonce;\n address to;\n uint256 txType;\n uint256 value;\n }\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct TxLegacy {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n string hash;\n string opcode;\n TxDetailLegacy transaction;\n }\n\n struct TxDetailLegacy {\n AccessList[] accessList;\n uint256 chainId;\n bytes data;\n address from;\n uint256 gas;\n uint256 gasPrice;\n bytes32 hash;\n uint256 nonce;\n bytes1 opcode;\n bytes32 r;\n bytes32 s;\n uint256 txType;\n address to;\n uint8 v;\n uint256 value;\n }\n\n struct AccessList {\n address accessAddress;\n bytes32[] storageKeys;\n }\n\n // Data structures to parse Receipt objects from the broadcast artifact.\n // The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawReceipt {\n bytes32 blockHash;\n bytes blockNumber;\n address contractAddress;\n bytes cumulativeGasUsed;\n bytes effectiveGasPrice;\n address from;\n bytes gasUsed;\n RawReceiptLog[] logs;\n bytes logsBloom;\n bytes status;\n address to;\n bytes32 transactionHash;\n bytes transactionIndex;\n }\n\n struct Receipt {\n bytes32 blockHash;\n uint256 blockNumber;\n address contractAddress;\n uint256 cumulativeGasUsed;\n uint256 effectiveGasPrice;\n address from;\n uint256 gasUsed;\n ReceiptLog[] logs;\n bytes logsBloom;\n uint256 status;\n address to;\n bytes32 transactionHash;\n uint256 transactionIndex;\n }\n\n // Data structures to parse the entire broadcast artifact, assuming the\n // transactions conform to EIP1559.\n\n struct EIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n Receipt[] receipts;\n uint256 timestamp;\n Tx1559[] transactions;\n TxReturn[] txReturns;\n }\n\n struct RawEIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n RawReceipt[] receipts;\n TxReturn[] txReturns;\n uint256 timestamp;\n RawTx1559[] transactions;\n }\n\n struct RawReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n bytes blockNumber;\n bytes data;\n bytes logIndex;\n bool removed;\n bytes32[] topics;\n bytes32 transactionHash;\n bytes transactionIndex;\n bytes transactionLogIndex;\n }\n\n struct ReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n uint256 blockNumber;\n bytes data;\n uint256 logIndex;\n bytes32[] topics;\n uint256 transactionIndex;\n uint256 transactionLogIndex;\n bool removed;\n }\n\n struct TxReturn {\n string internalType;\n string value;\n }\n\n function assumeNoPrecompiles(address addr) internal virtual {\n // Assembly required since `block.chainid` was introduced in 0.8.0.\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n assumeNoPrecompiles(addr, chainId);\n }\n\n function assumeNoPrecompiles(address addr, uint256 chainId) internal pure virtual {\n // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific\n // address), but the same rationale for excluding them applies so we include those too.\n\n // These should be present on all EVM-compatible chains.\n vm.assume(addr < address(0x1) || addr > address(0x9));\n\n // forgefmt: disable-start\n if (chainId == 10 || chainId == 420) {\n // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21\n vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));\n } else if (chainId == 42161 || chainId == 421613) {\n // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains\n vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));\n } else if (chainId == 43114 || chainId == 43113) {\n // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59\n vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));\n vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));\n vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));\n }\n // forgefmt: disable-end\n }\n\n function readEIP1559ScriptArtifact(string memory path)\n internal\n view\n virtual\n returns (EIP1559ScriptArtifact memory)\n {\n string memory data = vm.readFile(path);\n bytes memory parsedData = vm.parseJson(data);\n RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));\n EIP1559ScriptArtifact memory artifact;\n artifact.libraries = rawArtifact.libraries;\n artifact.path = rawArtifact.path;\n artifact.timestamp = rawArtifact.timestamp;\n artifact.pending = rawArtifact.pending;\n artifact.txReturns = rawArtifact.txReturns;\n artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);\n artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);\n return artifact;\n }\n\n function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {\n Tx1559[] memory txs = new Tx1559[](rawTxs.length);\n for (uint256 i; i < rawTxs.length; i++) {\n txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);\n }\n return txs;\n }\n\n function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {\n Tx1559 memory transaction;\n transaction.arguments = rawTx.arguments;\n transaction.contractName = rawTx.contractName;\n transaction.functionSig = rawTx.functionSig;\n transaction.hash = rawTx.hash;\n transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);\n transaction.opcode = rawTx.opcode;\n return transaction;\n }\n\n function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)\n internal\n pure\n virtual\n returns (Tx1559Detail memory)\n {\n Tx1559Detail memory txDetail;\n txDetail.data = rawDetail.data;\n txDetail.from = rawDetail.from;\n txDetail.to = rawDetail.to;\n txDetail.nonce = _bytesToUint(rawDetail.nonce);\n txDetail.txType = _bytesToUint(rawDetail.txType);\n txDetail.value = _bytesToUint(rawDetail.value);\n txDetail.gas = _bytesToUint(rawDetail.gas);\n txDetail.accessList = rawDetail.accessList;\n return txDetail;\n }\n\n function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".transactions\");\n RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));\n return rawToConvertedEIPTx1559s(rawTxs);\n }\n\n function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".transactions[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));\n return rawToConvertedEIPTx1559(rawTx);\n }\n\n // Analogous to readTransactions, but for receipts.\n function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".receipts\");\n RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));\n return rawToConvertedReceipts(rawReceipts);\n }\n\n function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".receipts[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));\n return rawToConvertedReceipt(rawReceipt);\n }\n\n function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {\n Receipt[] memory receipts = new Receipt[](rawReceipts.length);\n for (uint256 i; i < rawReceipts.length; i++) {\n receipts[i] = rawToConvertedReceipt(rawReceipts[i]);\n }\n return receipts;\n }\n\n function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {\n Receipt memory receipt;\n receipt.blockHash = rawReceipt.blockHash;\n receipt.to = rawReceipt.to;\n receipt.from = rawReceipt.from;\n receipt.contractAddress = rawReceipt.contractAddress;\n receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);\n receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);\n receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);\n receipt.status = _bytesToUint(rawReceipt.status);\n receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);\n receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);\n receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);\n receipt.logsBloom = rawReceipt.logsBloom;\n receipt.transactionHash = rawReceipt.transactionHash;\n return receipt;\n }\n\n function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)\n internal\n pure\n virtual\n returns (ReceiptLog[] memory)\n {\n ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);\n for (uint256 i; i < rawLogs.length; i++) {\n logs[i].logAddress = rawLogs[i].logAddress;\n logs[i].blockHash = rawLogs[i].blockHash;\n logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);\n logs[i].data = rawLogs[i].data;\n logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);\n logs[i].topics = rawLogs[i].topics;\n logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);\n logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);\n logs[i].removed = rawLogs[i].removed;\n }\n return logs;\n }\n\n // Deploy a contract by fetching the contract bytecode from\n // the artifacts directory\n // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`\n function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes): Deployment failed.\");\n }\n\n function deployCode(string memory what) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string): Deployment failed.\");\n }\n\n /// @dev deploy contract with value on construction\n function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes,uint256): Deployment failed.\");\n }\n\n function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,uint256): Deployment failed.\");\n }\n\n // creates a labeled address and the corresponding private key\n function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {\n privateKey = uint256(keccak256(abi.encodePacked(name)));\n addr = vm.addr(privateKey);\n vm.label(addr, name);\n }\n\n // creates a labeled address\n function makeAddr(string memory name) internal virtual returns (address addr) {\n (addr,) = makeAddrAndKey(name);\n }\n\n function deriveRememberKey(string memory mnemonic, uint32 index)\n internal\n virtual\n returns (address who, uint256 privateKey)\n {\n privateKey = vm.deriveKey(mnemonic, index);\n who = vm.rememberKey(privateKey);\n }\n\n function _bytesToUint(bytes memory b) private pure returns (uint256) {\n require(b.length <= 32, \"StdCheats _bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n function isFork() internal view virtual returns (bool status) {\n try vm.activeFork() {\n status = true;\n } catch (bytes memory) {}\n }\n\n modifier skipWhenForking() {\n if (!isFork()) {\n _;\n }\n }\n\n modifier skipWhenNotForking() {\n if (isFork()) {\n _;\n }\n }\n\n modifier noGasMetering() {\n vm.pauseGasMetering();\n // To prevent turning gas monitoring back on with nested functions that use this modifier,\n // we check if gasMetering started in the off position. If it did, we don't want to turn\n // it back on until we exit the top level function that used the modifier\n //\n // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.\n // funcA will have `gasStartedOff` as false, funcB will have it as true,\n // so we only turn metering back on at the end of the funcA\n bool gasStartedOff = gasMeteringOff;\n gasMeteringOff = true;\n\n _;\n\n // if gas metering was on when this modifier was called, turn it back on at the end\n if (!gasStartedOff) {\n gasMeteringOff = false;\n vm.resumeGasMetering();\n }\n }\n\n // a cheat for fuzzing addresses that are payable only\n // see https://github.com/foundry-rs/foundry/issues/3631\n function assumePayable(address addr) internal virtual {\n (bool success,) = payable(addr).call{value: 0}(\"\");\n vm.assume(success);\n }\n}\n\n// Wrappers around cheatcodes to avoid footguns\nabstract contract StdCheats is StdCheatsSafe {\n using stdStorage for StdStorage;\n\n StdStorage private stdstore;\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n // Skip forward or rewind time by the specified number of seconds\n function skip(uint256 time) internal virtual {\n vm.warp(block.timestamp + time);\n }\n\n function rewind(uint256 time) internal virtual {\n vm.warp(block.timestamp - time);\n }\n\n // Setup a prank from an address that has some ether\n function hoax(address msgSender) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.prank(msgSender);\n }\n\n function hoax(address msgSender, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.prank(msgSender);\n }\n\n function hoax(address msgSender, address origin) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.prank(msgSender, origin);\n }\n\n function hoax(address msgSender, address origin, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.prank(msgSender, origin);\n }\n\n // Start perpetual prank from an address that has some ether\n function startHoax(address msgSender) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.startPrank(msgSender);\n }\n\n function startHoax(address msgSender, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.startPrank(msgSender);\n }\n\n // Start perpetual prank from an address that has some ether\n // tx.origin is set to the origin parameter\n function startHoax(address msgSender, address origin) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.startPrank(msgSender, origin);\n }\n\n function startHoax(address msgSender, address origin, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.startPrank(msgSender, origin);\n }\n\n function changePrank(address msgSender) internal virtual {\n vm.stopPrank();\n vm.startPrank(msgSender);\n }\n\n function changePrank(address msgSender, address txOrigin) internal virtual {\n vm.stopPrank();\n vm.startPrank(msgSender, txOrigin);\n }\n\n // The same as Vm's `deal`\n // Use the alternative signature for ERC20 tokens\n function deal(address to, uint256 give) internal virtual {\n vm.deal(to, give);\n }\n\n // Set the balance of an account for any ERC20 token\n // Use the alternative signature to update `totalSupply`\n function deal(address token, address to, uint256 give) internal virtual {\n deal(token, to, give, false);\n }\n\n // Set the balance of an account for any ERC1155 token\n // Use the alternative signature to update `totalSupply`\n function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {\n dealERC1155(token, to, id, give, false);\n }\n\n function deal(address token, address to, uint256 give, bool adjust) internal virtual {\n // get current balance\n (, bytes memory balData) = token.call(abi.encodeWithSelector(0x70a08231, to));\n uint256 prevBal = abi.decode(balData, (uint256));\n\n // update balance\n stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);\n\n // update total supply\n if (adjust) {\n (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0x18160ddd));\n uint256 totSup = abi.decode(totSupData, (uint256));\n if (give < prevBal) {\n totSup -= (prevBal - give);\n } else {\n totSup += (give - prevBal);\n }\n stdstore.target(token).sig(0x18160ddd).checked_write(totSup);\n }\n }\n\n function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {\n // get current balance\n (, bytes memory balData) = token.call(abi.encodeWithSelector(0x00fdd58e, to, id));\n uint256 prevBal = abi.decode(balData, (uint256));\n\n // update balance\n stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);\n\n // update total supply\n if (adjust) {\n (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0xbd85b039, id));\n require(\n totSupData.length != 0,\n \"StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply.\"\n );\n uint256 totSup = abi.decode(totSupData, (uint256));\n if (give < prevBal) {\n totSup -= (prevBal - give);\n } else {\n totSup += (give - prevBal);\n }\n stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);\n }\n }\n\n function dealERC721(address token, address to, uint256 id) internal virtual {\n // check if token id is already minted and the actual owner.\n (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));\n require(successMinted, \"StdCheats deal(address,address,uint,bool): id not minted.\");\n\n // get owner current balance\n (, bytes memory fromBalData) = token.call(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));\n uint256 fromPrevBal = abi.decode(fromBalData, (uint256));\n\n // get new user current balance\n (, bytes memory toBalData) = token.call(abi.encodeWithSelector(0x70a08231, to));\n uint256 toPrevBal = abi.decode(toBalData, (uint256));\n\n // update balances\n stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);\n stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);\n\n // update owner\n stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);\n }\n}\n" - }, - "node_modules/forge-std/src/StdError.sol": { - "content": "// SPDX-License-Identifier: MIT\n// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdError {\n bytes public constant assertionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x01);\n bytes public constant arithmeticError = abi.encodeWithSignature(\"Panic(uint256)\", 0x11);\n bytes public constant divisionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x12);\n bytes public constant enumConversionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x21);\n bytes public constant encodeStorageError = abi.encodeWithSignature(\"Panic(uint256)\", 0x22);\n bytes public constant popError = abi.encodeWithSignature(\"Panic(uint256)\", 0x31);\n bytes public constant indexOOBError = abi.encodeWithSignature(\"Panic(uint256)\", 0x32);\n bytes public constant memOverflowError = abi.encodeWithSignature(\"Panic(uint256)\", 0x41);\n bytes public constant zeroVarError = abi.encodeWithSignature(\"Panic(uint256)\", 0x51);\n}\n" - }, - "node_modules/forge-std/src/StdInvariant.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\ncontract StdInvariant {\n struct FuzzSelector {\n address addr;\n bytes4[] selectors;\n }\n\n address[] private _excludedContracts;\n address[] private _excludedSenders;\n address[] private _targetedContracts;\n address[] private _targetedSenders;\n\n string[] private _excludedArtifacts;\n string[] private _targetedArtifacts;\n\n FuzzSelector[] private _targetedArtifactSelectors;\n FuzzSelector[] private _targetedSelectors;\n\n // Functions for users:\n // These are intended to be called in tests.\n\n function excludeContract(address newExcludedContract_) internal {\n _excludedContracts.push(newExcludedContract_);\n }\n\n function excludeSender(address newExcludedSender_) internal {\n _excludedSenders.push(newExcludedSender_);\n }\n\n function excludeArtifact(string memory newExcludedArtifact_) internal {\n _excludedArtifacts.push(newExcludedArtifact_);\n }\n\n function targetArtifact(string memory newTargetedArtifact_) internal {\n _targetedArtifacts.push(newTargetedArtifact_);\n }\n\n function targetArtifactSelector(FuzzSelector memory newTargetedArtifactSelector_) internal {\n _targetedArtifactSelectors.push(newTargetedArtifactSelector_);\n }\n\n function targetContract(address newTargetedContract_) internal {\n _targetedContracts.push(newTargetedContract_);\n }\n\n function targetSelector(FuzzSelector memory newTargetedSelector_) internal {\n _targetedSelectors.push(newTargetedSelector_);\n }\n\n function targetSender(address newTargetedSender_) internal {\n _targetedSenders.push(newTargetedSender_);\n }\n\n // Functions for forge:\n // These are called by forge to run invariant tests and don't need to be called in tests.\n\n function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) {\n excludedArtifacts_ = _excludedArtifacts;\n }\n\n function excludeContracts() public view returns (address[] memory excludedContracts_) {\n excludedContracts_ = _excludedContracts;\n }\n\n function excludeSenders() public view returns (address[] memory excludedSenders_) {\n excludedSenders_ = _excludedSenders;\n }\n\n function targetArtifacts() public view returns (string[] memory targetedArtifacts_) {\n targetedArtifacts_ = _targetedArtifacts;\n }\n\n function targetArtifactSelectors() public view returns (FuzzSelector[] memory targetedArtifactSelectors_) {\n targetedArtifactSelectors_ = _targetedArtifactSelectors;\n }\n\n function targetContracts() public view returns (address[] memory targetedContracts_) {\n targetedContracts_ = _targetedContracts;\n }\n\n function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) {\n targetedSelectors_ = _targetedSelectors;\n }\n\n function targetSenders() public view returns (address[] memory targetedSenders_) {\n targetedSenders_ = _targetedSenders;\n }\n}\n" - }, - "node_modules/forge-std/src/StdJson.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n// Helpers for parsing and writing JSON files\n// To parse:\n// ```\n// using stdJson for string;\n// string memory json = vm.readFile(\"some_peth\");\n// json.parseUint(\"\");\n// ```\n// To write:\n// ```\n// using stdJson for string;\n// string memory json = \"deploymentArtifact\";\n// Contract contract = new Contract();\n// json.serialize(\"contractAddress\", address(contract));\n// json = json.serialize(\"deploymentTimes\", uint(1));\n// // store the stringified JSON to the 'json' variable we have been using as a key\n// // as we won't need it any longer\n// string memory json2 = \"finalArtifact\";\n// string memory final = json2.serialize(\"depArtifact\", json);\n// final.write(\"\");\n// ```\n\nlibrary stdJson {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {\n return vm.parseJson(json, key);\n }\n\n function readUint(string memory json, string memory key) internal returns (uint256) {\n return vm.parseJsonUint(json, key);\n }\n\n function readUintArray(string memory json, string memory key) internal returns (uint256[] memory) {\n return vm.parseJsonUintArray(json, key);\n }\n\n function readInt(string memory json, string memory key) internal returns (int256) {\n return vm.parseJsonInt(json, key);\n }\n\n function readIntArray(string memory json, string memory key) internal returns (int256[] memory) {\n return vm.parseJsonIntArray(json, key);\n }\n\n function readBytes32(string memory json, string memory key) internal returns (bytes32) {\n return vm.parseJsonBytes32(json, key);\n }\n\n function readBytes32Array(string memory json, string memory key) internal returns (bytes32[] memory) {\n return vm.parseJsonBytes32Array(json, key);\n }\n\n function readString(string memory json, string memory key) internal returns (string memory) {\n return vm.parseJsonString(json, key);\n }\n\n function readStringArray(string memory json, string memory key) internal returns (string[] memory) {\n return vm.parseJsonStringArray(json, key);\n }\n\n function readAddress(string memory json, string memory key) internal returns (address) {\n return vm.parseJsonAddress(json, key);\n }\n\n function readAddressArray(string memory json, string memory key) internal returns (address[] memory) {\n return vm.parseJsonAddressArray(json, key);\n }\n\n function readBool(string memory json, string memory key) internal returns (bool) {\n return vm.parseJsonBool(json, key);\n }\n\n function readBoolArray(string memory json, string memory key) internal returns (bool[] memory) {\n return vm.parseJsonBoolArray(json, key);\n }\n\n function readBytes(string memory json, string memory key) internal returns (bytes memory) {\n return vm.parseJsonBytes(json, key);\n }\n\n function readBytesArray(string memory json, string memory key) internal returns (bytes[] memory) {\n return vm.parseJsonBytesArray(json, key);\n }\n\n function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bool[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function write(string memory jsonKey, string memory path) internal {\n vm.writeJson(jsonKey, path);\n }\n\n function write(string memory jsonKey, string memory path, string memory valueKey) internal {\n vm.writeJson(jsonKey, path, valueKey);\n }\n}\n" - }, - "node_modules/forge-std/src/StdMath.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdMath {\n int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;\n\n function abs(int256 a) internal pure returns (uint256) {\n // Required or it will fail when `a = type(int256).min`\n if (a == INT256_MIN) {\n return 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n }\n\n return uint256(a > 0 ? a : -a);\n }\n\n function delta(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a - b : b - a;\n }\n\n function delta(int256 a, int256 b) internal pure returns (uint256) {\n // a and b are of the same sign\n // this works thanks to two's complement, the left-most bit is the sign bit\n if ((a ^ b) > -1) {\n return delta(abs(a), abs(b));\n }\n\n // a and b are of opposite signs\n return abs(a) + abs(b);\n }\n\n function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n\n return absDelta * 1e18 / b;\n }\n\n function percentDelta(int256 a, int256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n uint256 absB = abs(b);\n\n return absDelta * 1e18 / absB;\n }\n}\n" - }, - "node_modules/forge-std/src/StdStorage.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {Vm} from \"./Vm.sol\";\n\nstruct StdStorage {\n mapping(address => mapping(bytes4 => mapping(bytes32 => uint256))) slots;\n mapping(address => mapping(bytes4 => mapping(bytes32 => bool))) finds;\n bytes32[] _keys;\n bytes4 _sig;\n uint256 _depth;\n address _target;\n bytes32 _set;\n}\n\nlibrary stdStorageSafe {\n event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);\n event WARNING_UninitedSlot(address who, uint256 slot);\n\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return bytes4(keccak256(bytes(sigStr)));\n }\n\n /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against\n // slot complexity:\n // if flat, will be bytes32(uint256(uint));\n // if map, will be keccak256(abi.encode(key, uint(slot)));\n // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));\n // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);\n function find(StdStorage storage self) internal returns (uint256) {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n // calldata to test against\n if (self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n vm.record();\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n (bytes32[] memory reads,) = vm.accesses(address(who));\n if (reads.length == 1) {\n bytes32 curr = vm.load(who, reads[0]);\n if (curr == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[0]));\n }\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[0]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[0]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n } else if (reads.length > 1) {\n for (uint256 i = 0; i < reads.length; i++) {\n bytes32 prev = vm.load(who, reads[i]);\n if (prev == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[i]));\n }\n // store\n vm.store(who, reads[i], bytes32(hex\"1337\"));\n bool success;\n bytes memory rdat;\n {\n (success, rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n if (success && fdat == bytes32(hex\"1337\")) {\n // we found which of the slots is the actual one\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[i]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[i]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n vm.store(who, reads[i], prev);\n break;\n }\n vm.store(who, reads[i], prev);\n }\n } else {\n revert(\"stdStorage find(StdStorage): No storage use detected for target.\");\n }\n\n require(\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))],\n \"stdStorage find(StdStorage): Slot(s) not found.\"\n );\n\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n self._target = _target;\n return self;\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n self._sig = _sig;\n return self;\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n self._sig = sigs(_sig);\n return self;\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n self._keys.push(bytes32(uint256(uint160(who))));\n return self;\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n self._keys.push(bytes32(amt));\n return self;\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n self._keys.push(key);\n return self;\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n self._depth = _depth;\n return self;\n }\n\n function read(StdStorage storage self) private returns (bytes memory) {\n address t = self._target;\n uint256 s = find(self);\n return abi.encode(vm.load(t, bytes32(s)));\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return abi.decode(read(self), (bytes32));\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n int256 v = read_int(self);\n if (v == 0) return false;\n if (v == 1) return true;\n revert(\"stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.\");\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return abi.decode(read(self), (address));\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return abi.decode(read(self), (uint256));\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return abi.decode(read(self), (int256));\n }\n\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n\nlibrary stdStorage {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return stdStorageSafe.sigs(sigStr);\n }\n\n function find(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.find(self);\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n return stdStorageSafe.target(self, _target);\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, who);\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, amt);\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, key);\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n return stdStorageSafe.depth(self, _depth);\n }\n\n function checked_write(StdStorage storage self, address who) internal {\n checked_write(self, bytes32(uint256(uint160(who))));\n }\n\n function checked_write(StdStorage storage self, uint256 amt) internal {\n checked_write(self, bytes32(amt));\n }\n\n function checked_write(StdStorage storage self, bool write) internal {\n bytes32 t;\n /// @solidity memory-safe-assembly\n assembly {\n t := write\n }\n checked_write(self, t);\n }\n\n function checked_write(StdStorage storage self, bytes32 set) internal {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n if (!self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n find(self);\n }\n bytes32 slot = bytes32(self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]);\n\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n bytes32 curr = vm.load(who, slot);\n\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n vm.store(who, slot, set);\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return stdStorageSafe.read_bytes32(self);\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n return stdStorageSafe.read_bool(self);\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return stdStorageSafe.read_address(self);\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.read_uint(self);\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return stdStorageSafe.read_int(self);\n }\n\n // Private function so needs to be copied over\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n // Private function so needs to be copied over\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n" - }, - "node_modules/forge-std/src/StdStyle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nimport {Vm} from \"./Vm.sol\";\n\nlibrary StdStyle {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n string constant RED = \"\\u001b[91m\";\n string constant GREEN = \"\\u001b[92m\";\n string constant YELLOW = \"\\u001b[93m\";\n string constant BLUE = \"\\u001b[94m\";\n string constant MAGENTA = \"\\u001b[95m\";\n string constant CYAN = \"\\u001b[96m\";\n string constant BOLD = \"\\u001b[1m\";\n string constant DIM = \"\\u001b[2m\";\n string constant ITALIC = \"\\u001b[3m\";\n string constant UNDERLINE = \"\\u001b[4m\";\n string constant INVERSE = \"\\u001b[7m\";\n string constant RESET = \"\\u001b[0m\";\n\n function styleConcat(string memory style, string memory self) private pure returns (string memory) {\n return string(abi.encodePacked(style, self, RESET));\n }\n\n function red(string memory self) internal pure returns (string memory) {\n return styleConcat(RED, self);\n }\n\n function red(uint256 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(int256 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(address self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(bool self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function redBytes(bytes memory self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function redBytes32(bytes32 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function green(string memory self) internal pure returns (string memory) {\n return styleConcat(GREEN, self);\n }\n\n function green(uint256 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(int256 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(address self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(bool self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function greenBytes(bytes memory self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function greenBytes32(bytes32 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function yellow(string memory self) internal pure returns (string memory) {\n return styleConcat(YELLOW, self);\n }\n\n function yellow(uint256 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(int256 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(address self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(bool self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellowBytes(bytes memory self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellowBytes32(bytes32 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function blue(string memory self) internal pure returns (string memory) {\n return styleConcat(BLUE, self);\n }\n\n function blue(uint256 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(int256 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(address self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(bool self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blueBytes(bytes memory self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blueBytes32(bytes32 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function magenta(string memory self) internal pure returns (string memory) {\n return styleConcat(MAGENTA, self);\n }\n\n function magenta(uint256 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(int256 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(address self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(bool self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magentaBytes(bytes memory self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magentaBytes32(bytes32 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function cyan(string memory self) internal pure returns (string memory) {\n return styleConcat(CYAN, self);\n }\n\n function cyan(uint256 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(int256 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(address self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(bool self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyanBytes(bytes memory self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyanBytes32(bytes32 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function bold(string memory self) internal pure returns (string memory) {\n return styleConcat(BOLD, self);\n }\n\n function bold(uint256 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(int256 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(address self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(bool self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function boldBytes(bytes memory self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function boldBytes32(bytes32 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function dim(string memory self) internal pure returns (string memory) {\n return styleConcat(DIM, self);\n }\n\n function dim(uint256 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(int256 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(address self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(bool self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dimBytes(bytes memory self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dimBytes32(bytes32 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function italic(string memory self) internal pure returns (string memory) {\n return styleConcat(ITALIC, self);\n }\n\n function italic(uint256 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(int256 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(address self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(bool self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italicBytes(bytes memory self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italicBytes32(bytes32 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function underline(string memory self) internal pure returns (string memory) {\n return styleConcat(UNDERLINE, self);\n }\n\n function underline(uint256 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(int256 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(address self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(bool self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underlineBytes(bytes memory self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underlineBytes32(bytes32 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function inverse(string memory self) internal pure returns (string memory) {\n return styleConcat(INVERSE, self);\n }\n\n function inverse(uint256 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(int256 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(address self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(bool self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverseBytes(bytes memory self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverseBytes32(bytes32 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n}\n" - }, - "node_modules/forge-std/src/StdUtils.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {IMulticall3} from \"./interfaces/IMulticall3.sol\";\n// TODO Remove import.\nimport {VmSafe} from \"./Vm.sol\";\n\nabstract contract StdUtils {\n /*//////////////////////////////////////////////////////////////////////////\n CONSTANTS\n //////////////////////////////////////////////////////////////////////////*/\n\n IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;\n uint256 private constant INT256_MIN_ABS =\n 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n uint256 private constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.\n address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;\n\n /*//////////////////////////////////////////////////////////////////////////\n INTERNAL FUNCTIONS\n //////////////////////////////////////////////////////////////////////////*/\n\n function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {\n require(min <= max, \"StdUtils bound(uint256,uint256,uint256): Max is less than min.\");\n // If x is between min and max, return x directly. This is to ensure that dictionary values\n // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188\n if (x >= min && x <= max) return x;\n\n uint256 size = max - min + 1;\n\n // If the value is 0, 1, 2, 3, warp that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.\n // This helps ensure coverage of the min/max values.\n if (x <= 3 && size > x) return min + x;\n if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);\n\n // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.\n if (x > max) {\n uint256 diff = x - max;\n uint256 rem = diff % size;\n if (rem == 0) return max;\n result = min + rem - 1;\n } else if (x < min) {\n uint256 diff = min - x;\n uint256 rem = diff % size;\n if (rem == 0) return min;\n result = max - rem + 1;\n }\n }\n\n function bound(uint256 x, uint256 min, uint256 max) internal view virtual returns (uint256 result) {\n result = _bound(x, min, max);\n console2_log(\"Bound Result\", result);\n }\n\n function bound(int256 x, int256 min, int256 max) internal view virtual returns (int256 result) {\n require(min <= max, \"StdUtils bound(int256,int256,int256): Max is less than min.\");\n\n // Shifting all int256 values to uint256 to use _bound function. The range of two types are:\n // int256 : -(2**255) ~ (2**255 - 1)\n // uint256: 0 ~ (2**256 - 1)\n // So, add 2**255, INT256_MIN_ABS to the integer values.\n //\n // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.\n // So, use `~uint256(x) + 1` instead.\n uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);\n uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);\n uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);\n\n uint256 y = _bound(_x, _min, _max);\n\n // To move it back to int256 value, subtract INT256_MIN_ABS at here.\n result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);\n console2_log(\"Bound result\", vm.toString(result));\n }\n\n function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {\n require(b.length <= 32, \"StdUtils bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce\n /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)\n function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {\n // forgefmt: disable-start\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))));\n if (nonce <= 0x7f) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))));\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= 2**8 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce))));\n if (nonce <= 2**16 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce))));\n if (nonce <= 2**24 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce))));\n // forgefmt: disable-end\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return addressFromLast20Bytes(\n keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce)))\n );\n }\n\n function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)\n internal\n pure\n virtual\n returns (address)\n {\n return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, initcodeHash)));\n }\n\n /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer\n function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {\n return computeCreate2Address(salt, initCodeHash, CREATE2_FACTORY);\n }\n\n /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments\n /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode\n function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {\n return hashInitCode(creationCode, \"\");\n }\n\n /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2\n /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode\n /// @param args the ABI-encoded arguments to the constructor of C\n function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(creationCode, args));\n }\n\n // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.\n function getTokenBalances(address token, address[] memory addresses)\n internal\n virtual\n returns (uint256[] memory balances)\n {\n uint256 tokenCodeSize;\n assembly {\n tokenCodeSize := extcodesize(token)\n }\n require(tokenCodeSize > 0, \"StdUtils getTokenBalances(address,address[]): Token address is not a contract.\");\n\n // ABI encode the aggregate call to Multicall3.\n uint256 length = addresses.length;\n IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);\n for (uint256 i = 0; i < length; ++i) {\n // 0x70a08231 = bytes4(\"balanceOf(address)\"))\n calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});\n }\n\n // Make the aggregate call.\n (, bytes[] memory returnData) = multicall.aggregate(calls);\n\n // ABI decode the return data and return the balances.\n balances = new uint256[](length);\n for (uint256 i = 0; i < length; ++i) {\n balances[i] = abi.decode(returnData[i], (uint256));\n }\n }\n\n /*//////////////////////////////////////////////////////////////////////////\n PRIVATE FUNCTIONS\n //////////////////////////////////////////////////////////////////////////*/\n\n function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.\n\n function console2_log(string memory p0, uint256 p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n status;\n }\n\n function console2_log(string memory p0, string memory p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n status;\n }\n}\n" - }, - "node_modules/forge-std/src/Test.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\n// 💬 ABOUT\n// Standard Library's default Test\n\n// 🧩 MODULES\nimport {console} from \"./console.sol\";\nimport {console2} from \"./console2.sol\";\nimport {StdAssertions} from \"./StdAssertions.sol\";\nimport {StdChains} from \"./StdChains.sol\";\nimport {StdCheats} from \"./StdCheats.sol\";\nimport {stdError} from \"./StdError.sol\";\nimport {StdInvariant} from \"./StdInvariant.sol\";\nimport {stdJson} from \"./StdJson.sol\";\nimport {stdMath} from \"./StdMath.sol\";\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {StdUtils} from \"./StdUtils.sol\";\nimport {Vm} from \"./Vm.sol\";\nimport {StdStyle} from \"./StdStyle.sol\";\n\n// 📦 BOILERPLATE\nimport {TestBase} from \"./Base.sol\";\nimport {DSTest} from \"ds-test/test.sol\";\n\n// ⭐️ TEST\nabstract contract Test is DSTest, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils, TestBase {\n// Note: IS_TEST() must return true.\n// Note: Must have failure system, https://github.com/dapphub/ds-test/blob/cd98eff28324bfac652e63a239a60632a761790b/src/test.sol#L39-L76.\n}\n" - }, - "node_modules/forge-std/src/Vm.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\n// Cheatcodes are marked as view/pure/none using the following rules:\n// 0. A call's observable behaviour includes its return value, logs, reverts and state writes,\n// 1. If you can influence a later call's observable behaviour, you're neither `view` nor `pure (you are modifying some state be it the EVM, interpreter, filesystem, etc),\n// 2. Otherwise if you can be influenced by an earlier call, or if reading some state, you're `view`,\n// 3. Otherwise you're `pure`.\n\ninterface VmSafe {\n struct Log {\n bytes32[] topics;\n bytes data;\n address emitter;\n }\n\n struct Rpc {\n string key;\n string url;\n }\n\n struct FsMetadata {\n bool isDir;\n bool isSymlink;\n uint256 length;\n bool readOnly;\n uint256 modified;\n uint256 accessed;\n uint256 created;\n }\n\n // Loads a storage slot from an address\n function load(address target, bytes32 slot) external view returns (bytes32 data);\n // Signs data\n function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);\n // Gets the address for a given private key\n function addr(uint256 privateKey) external pure returns (address keyAddr);\n // Gets the nonce of an account\n function getNonce(address account) external view returns (uint64 nonce);\n // Performs a foreign function call via the terminal\n function ffi(string[] calldata commandInput) external returns (bytes memory result);\n // Sets environment variables\n function setEnv(string calldata name, string calldata value) external;\n // Reads environment variables, (name) => (value)\n function envBool(string calldata name) external view returns (bool value);\n function envUint(string calldata name) external view returns (uint256 value);\n function envInt(string calldata name) external view returns (int256 value);\n function envAddress(string calldata name) external view returns (address value);\n function envBytes32(string calldata name) external view returns (bytes32 value);\n function envString(string calldata name) external view returns (string memory value);\n function envBytes(string calldata name) external view returns (bytes memory value);\n // Reads environment variables as arrays\n function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);\n function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);\n function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);\n function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);\n function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);\n function envString(string calldata name, string calldata delim) external view returns (string[] memory value);\n function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);\n // Read environment variables with default value\n function envOr(string calldata name, bool defaultValue) external returns (bool value);\n function envOr(string calldata name, uint256 defaultValue) external returns (uint256 value);\n function envOr(string calldata name, int256 defaultValue) external returns (int256 value);\n function envOr(string calldata name, address defaultValue) external returns (address value);\n function envOr(string calldata name, bytes32 defaultValue) external returns (bytes32 value);\n function envOr(string calldata name, string calldata defaultValue) external returns (string memory value);\n function envOr(string calldata name, bytes calldata defaultValue) external returns (bytes memory value);\n // Read environment variables as arrays with default value\n function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)\n external\n returns (bool[] memory value);\n function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)\n external\n returns (uint256[] memory value);\n function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)\n external\n returns (int256[] memory value);\n function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)\n external\n returns (address[] memory value);\n function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)\n external\n returns (bytes32[] memory value);\n function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)\n external\n returns (string[] memory value);\n function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)\n external\n returns (bytes[] memory value);\n // Records all storage reads and writes\n function record() external;\n // Gets all accessed reads and write slot from a recording session, for a given address\n function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);\n // Gets the _creation_ bytecode from an artifact file. Takes in the relative path to the json file\n function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);\n // Gets the _deployed_ bytecode from an artifact file. Takes in the relative path to the json file\n function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);\n // Labels an address in call traces\n function label(address account, string calldata newLabel) external;\n // Using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain\n function broadcast() external;\n // Has the next call (at this call depth only) create a transaction with the address provided as the sender that can later be signed and sent onchain\n function broadcast(address signer) external;\n // Has the next call (at this call depth only) create a transaction with the private key provided as the sender that can later be signed and sent onchain\n function broadcast(uint256 privateKey) external;\n // Using the address that calls the test contract, has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain\n function startBroadcast() external;\n // Has all subsequent calls (at this call depth only) create transactions with the address provided that can later be signed and sent onchain\n function startBroadcast(address signer) external;\n // Has all subsequent calls (at this call depth only) create transactions with the private key provided that can later be signed and sent onchain\n function startBroadcast(uint256 privateKey) external;\n // Stops collecting onchain transactions\n function stopBroadcast() external;\n // Reads the entire content of file to string\n function readFile(string calldata path) external view returns (string memory data);\n // Reads the entire content of file as binary. Path is relative to the project root.\n function readFileBinary(string calldata path) external view returns (bytes memory data);\n // Get the path of the current project root\n function projectRoot() external view returns (string memory path);\n // Get the metadata for a file/directory\n function fsMetadata(string calldata fileOrDir) external returns (FsMetadata memory metadata);\n // Reads next line of file to string\n function readLine(string calldata path) external view returns (string memory line);\n // Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.\n function writeFile(string calldata path, string calldata data) external;\n // Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.\n // Path is relative to the project root.\n function writeFileBinary(string calldata path, bytes calldata data) external;\n // Writes line to file, creating a file if it does not exist.\n function writeLine(string calldata path, string calldata data) external;\n // Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.\n function closeFile(string calldata path) external;\n // Removes file. This cheatcode will revert in the following situations, but is not limited to just these cases:\n // - Path points to a directory.\n // - The file doesn't exist.\n // - The user lacks permissions to remove the file.\n function removeFile(string calldata path) external;\n // Convert values to a string\n function toString(address value) external pure returns (string memory stringifiedValue);\n function toString(bytes calldata value) external pure returns (string memory stringifiedValue);\n function toString(bytes32 value) external pure returns (string memory stringifiedValue);\n function toString(bool value) external pure returns (string memory stringifiedValue);\n function toString(uint256 value) external pure returns (string memory stringifiedValue);\n function toString(int256 value) external pure returns (string memory stringifiedValue);\n // Convert values from a string\n function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);\n function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);\n function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);\n function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);\n function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);\n function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);\n // Record all the transaction logs\n function recordLogs() external;\n // Gets all the recorded logs\n function getRecordedLogs() external returns (Log[] memory logs);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path m/44'/60'/0'/0/{index}\n function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at {derivationPath}{index}\n function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)\n external\n pure\n returns (uint256 privateKey);\n // Adds a private key to the local forge wallet and returns the address\n function rememberKey(uint256 privateKey) external returns (address keyAddr);\n //\n // parseJson\n //\n // ----\n // In case the returned value is a JSON object, it's encoded as a ABI-encoded tuple. As JSON objects\n // don't have the notion of ordered, but tuples do, they JSON object is encoded with it's fields ordered in\n // ALPHABETICAL order. That means that in order to successfully decode the tuple, we need to define a tuple that\n // encodes the fields in the same order, which is alphabetical. In the case of Solidity structs, they are encoded\n // as tuples, with the attributes in the order in which they are defined.\n // For example: json = { 'a': 1, 'b': 0xa4tb......3xs}\n // a: uint256\n // b: address\n // To decode that json, we need to define a struct or a tuple as follows:\n // struct json = { uint256 a; address b; }\n // If we defined a json struct with the opposite order, meaning placing the address b first, it would try to\n // decode the tuple in that order, and thus fail.\n // ----\n // Given a string of JSON, return it as ABI-encoded\n function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);\n function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);\n\n // The following parseJson cheatcodes will do type coercion, for the type that they indicate.\n // For example, parseJsonUint will coerce all values to a uint256. That includes stringified numbers '12'\n // and hex numbers '0xEF'.\n // Type coercion works ONLY for discrete values or arrays. That means that the key must return a value or array, not\n // a JSON object.\n function parseJsonUint(string calldata, string calldata) external returns (uint256);\n function parseJsonUintArray(string calldata, string calldata) external returns (uint256[] memory);\n function parseJsonInt(string calldata, string calldata) external returns (int256);\n function parseJsonIntArray(string calldata, string calldata) external returns (int256[] memory);\n function parseJsonBool(string calldata, string calldata) external returns (bool);\n function parseJsonBoolArray(string calldata, string calldata) external returns (bool[] memory);\n function parseJsonAddress(string calldata, string calldata) external returns (address);\n function parseJsonAddressArray(string calldata, string calldata) external returns (address[] memory);\n function parseJsonString(string calldata, string calldata) external returns (string memory);\n function parseJsonStringArray(string calldata, string calldata) external returns (string[] memory);\n function parseJsonBytes(string calldata, string calldata) external returns (bytes memory);\n function parseJsonBytesArray(string calldata, string calldata) external returns (bytes[] memory);\n function parseJsonBytes32(string calldata, string calldata) external returns (bytes32);\n function parseJsonBytes32Array(string calldata, string calldata) external returns (bytes32[] memory);\n\n // Serialize a key and value to a JSON object stored in-memory that can be later written to a file\n // It returns the stringified version of the specific JSON file up to that moment.\n function serializeBool(string calldata objectKey, string calldata valueKey, bool value)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address value)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)\n external\n returns (string memory json);\n\n function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)\n external\n returns (string memory json);\n\n //\n // writeJson\n //\n // ----\n // Write a serialized JSON object to a file. If the file exists, it will be overwritten.\n // Let's assume we want to write the following JSON to a file:\n //\n // { \"boolean\": true, \"number\": 342, \"object\": { \"title\": \"finally json serialization\" } }\n //\n // ```\n // string memory json1 = \"some key\";\n // vm.serializeBool(json1, \"boolean\", true);\n // vm.serializeBool(json1, \"number\", uint256(342));\n // json2 = \"some other key\";\n // string memory output = vm.serializeString(json2, \"title\", \"finally json serialization\");\n // string memory finalJson = vm.serialize(json1, \"object\", output);\n // vm.writeJson(finalJson, \"./output/example.json\");\n // ```\n // The critical insight is that every invocation of serialization will return the stringified version of the JSON\n // up to that point. That means we can construct arbitrary JSON objects and then use the return stringified version\n // to serialize them as values to another JSON object.\n //\n // json1 and json2 are simply keys used by the backend to keep track of the objects. So vm.serializeJson(json1,..)\n // will find the object in-memory that is keyed by \"some key\".\n function writeJson(string calldata json, string calldata path) external;\n // Write a serialized JSON object to an **existing** JSON file, replacing a value with key = \n // This is useful to replace a specific value of a JSON file, without having to parse the entire thing\n function writeJson(string calldata json, string calldata path, string calldata valueKey) external;\n // Returns the RPC url for the given alias\n function rpcUrl(string calldata rpcAlias) external view returns (string memory json);\n // Returns all rpc urls and their aliases `[alias, url][]`\n function rpcUrls() external view returns (string[2][] memory urls);\n // Returns all rpc urls and their aliases as structs.\n function rpcUrlStructs() external view returns (Rpc[] memory urls);\n // If the condition is false, discard this run's fuzz inputs and generate new ones.\n function assume(bool condition) external pure;\n // Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.\n function pauseGasMetering() external;\n // Resumes gas metering (i.e. gas usage is counted again). Noop if already on.\n function resumeGasMetering() external;\n}\n\ninterface Vm is VmSafe {\n // Sets block.timestamp\n function warp(uint256 newTimestamp) external;\n // Sets block.height\n function roll(uint256 newHeight) external;\n // Sets block.basefee\n function fee(uint256 newBasefee) external;\n // Sets block.difficulty\n function difficulty(uint256 newDifficulty) external;\n // Sets block.chainid\n function chainId(uint256 newChainId) external;\n // Stores a value to an address' storage slot.\n function store(address target, bytes32 slot, bytes32 value) external;\n // Sets the nonce of an account; must be higher than the current nonce of the account\n function setNonce(address account, uint64 newNonce) external;\n // Sets the *next* call's msg.sender to be the input address\n function prank(address msgSender) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called\n function startPrank(address msgSender) external;\n // Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input\n function prank(address msgSender, address txOrigin) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input\n function startPrank(address msgSender, address txOrigin) external;\n // Resets subsequent calls' msg.sender to be `address(this)`\n function stopPrank() external;\n // Sets an address' balance\n function deal(address account, uint256 newBalance) external;\n // Sets an address' code\n function etch(address target, bytes calldata newRuntimeBytecode) external;\n // Expects an error on next call\n function expectRevert(bytes calldata revertData) external;\n function expectRevert(bytes4 revertData) external;\n function expectRevert() external;\n\n // Prepare an expected log with all four checks enabled.\n // Call this function, then emit an event, then call a function. Internally after the call, we check if\n // logs were emitted in the expected order with the expected topics and data.\n // Second form also checks supplied address against emitting contract.\n function expectEmit() external;\n function expectEmit(address emitter) external;\n\n // Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData).\n // Call this function, then emit an event, then call a function. Internally after the call, we check if\n // logs were emitted in the expected order with the expected topics and data (as specified by the booleans).\n // Second form also checks supplied address against emitting contract.\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)\n external;\n\n // Mocks a call to an address, returning specified data.\n // Calldata can either be strict or a partial match, e.g. if you only\n // pass a Solidity selector to the expected calldata, then the entire Solidity\n // function will be mocked.\n function mockCall(address callee, bytes calldata data, bytes calldata returnData) external;\n // Mocks a call to an address with a specific msg.value, returning specified data.\n // Calldata match takes precedence over msg.value in case of ambiguity.\n function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external;\n // Clears all mocked calls\n function clearMockedCalls() external;\n // Expects a call to an address with the specified calldata.\n // Calldata can either be a strict or a partial match\n function expectCall(address callee, bytes calldata data) external;\n // Expects a call to an address with the specified msg.value and calldata\n function expectCall(address callee, uint256 msgValue, bytes calldata data) external;\n // Expect a call to an address with the specified msg.value, gas, and calldata.\n function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external;\n // Expect a call to an address with the specified msg.value and calldata, and a *minimum* amount of gas.\n function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external;\n // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other\n // memory is written to, the test will fail. Can be called multiple times to add more ranges to the set.\n function expectSafeMemory(uint64 min, uint64 max) external;\n // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext.\n // If any other memory is written to, the test will fail. Can be called multiple times to add more ranges\n // to the set.\n function expectSafeMemoryCall(uint64 min, uint64 max) external;\n // Sets block.coinbase\n function coinbase(address newCoinbase) external;\n // Snapshot the current state of the evm.\n // Returns the id of the snapshot that was created.\n // To revert a snapshot use `revertTo`\n function snapshot() external returns (uint256 snapshotId);\n // Revert the state of the EVM to a previous snapshot\n // Takes the snapshot id to revert to.\n // This deletes the snapshot and all snapshots taken after the given snapshot id.\n function revertTo(uint256 snapshotId) external returns (bool success);\n // Creates a new fork with the given endpoint and block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before the transaction,\n // and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates _and_ also selects new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before\n // the transaction, returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.\n function selectFork(uint256 forkId) external;\n /// Returns the identifier of the currently active fork. Reverts if no fork is currently active.\n function activeFork() external view returns (uint256 forkId);\n // Updates the currently active fork to given block number\n // This is similar to `roll` but for the currently active fork\n function rollFork(uint256 blockNumber) external;\n // Updates the currently active fork to given transaction\n // this will `rollFork` with the number of the block the transaction was mined in and replays all transaction mined before it in the block\n function rollFork(bytes32 txHash) external;\n // Updates the given fork to given block number\n function rollFork(uint256 forkId, uint256 blockNumber) external;\n // Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block\n function rollFork(uint256 forkId, bytes32 txHash) external;\n // Marks that the account(s) should use persistent storage across fork swaps in a multifork setup\n // Meaning, changes made to the state of this account will be kept when switching forks\n function makePersistent(address account) external;\n function makePersistent(address account0, address account1) external;\n function makePersistent(address account0, address account1, address account2) external;\n function makePersistent(address[] calldata accounts) external;\n // Revokes persistent status from the address, previously added via `makePersistent`\n function revokePersistent(address account) external;\n function revokePersistent(address[] calldata accounts) external;\n // Returns true if the account is marked as persistent\n function isPersistent(address account) external view returns (bool persistent);\n // In forking mode, explicitly grant the given address cheatcode access\n function allowCheatcodes(address account) external;\n // Fetches the given transaction from the active fork and executes it on the current state\n function transact(bytes32 txHash) external;\n // Fetches the given transaction from the given fork and executes it on the current state\n function transact(uint256 forkId, bytes32 txHash) external;\n}\n" - }, - "node_modules/forge-std/src/console.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nlibrary console {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int)\", p0));\n }\n\n function logUint(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint)\", p0, p1));\n }\n\n function log(uint p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string)\", p0, p1));\n }\n\n function log(uint p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool)\", p0, p1));\n }\n\n function log(uint p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address)\", p0, p1));\n }\n\n function log(string memory p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - }, - "node_modules/forge-std/src/console2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\n/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should\n/// use `int256` and `uint256`. This modified version fixes that. This version is recommended\n/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in\n/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.\n/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178\nlibrary console2 {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function logUint(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function log(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint256 p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256)\", p0, p1));\n }\n\n function log(uint256 p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string)\", p0, p1));\n }\n\n function log(uint256 p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool)\", p0, p1));\n }\n\n function log(uint256 p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address)\", p0, p1));\n }\n\n function log(string memory p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n }\n\n function log(string memory p0, int256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,int256)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - }, - "node_modules/forge-std/src/interfaces/IMulticall3.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\ninterface IMulticall3 {\n struct Call {\n address target;\n bytes callData;\n }\n\n struct Call3 {\n address target;\n bool allowFailure;\n bytes callData;\n }\n\n struct Call3Value {\n address target;\n bool allowFailure;\n uint256 value;\n bytes callData;\n }\n\n struct Result {\n bool success;\n bytes returnData;\n }\n\n function aggregate(Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes[] memory returnData);\n\n function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData);\n\n function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData);\n\n function blockAndAggregate(Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);\n\n function getBasefee() external view returns (uint256 basefee);\n\n function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash);\n\n function getBlockNumber() external view returns (uint256 blockNumber);\n\n function getChainId() external view returns (uint256 chainid);\n\n function getCurrentBlockCoinbase() external view returns (address coinbase);\n\n function getCurrentBlockDifficulty() external view returns (uint256 difficulty);\n\n function getCurrentBlockGasLimit() external view returns (uint256 gaslimit);\n\n function getCurrentBlockTimestamp() external view returns (uint256 timestamp);\n\n function getEthBalance(address addr) external view returns (uint256 balance);\n\n function getLastBlockHash() external view returns (bytes32 blockHash);\n\n function tryAggregate(bool requireSuccess, Call[] calldata calls)\n external\n payable\n returns (Result[] memory returnData);\n\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);\n}\n" - } - }, - "settings": { - "remappings": [ - "@cwia/=node_modules/clones-with-immutable-args/src/", - "@openzeppelin/=node_modules/@openzeppelin/", - "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", - "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", - "@rari-capital/=node_modules/@rari-capital/", - "@rari-capital/solmate/=node_modules/@rari-capital/solmate/", - "clones-with-immutable-args/=node_modules/clones-with-immutable-args/", - "ds-test/=node_modules/ds-test/src/", - "forge-std/=node_modules/forge-std/src/" - ], - "optimizer": { - "enabled": true, - "runs": 999999 - }, - "metadata": { - "bytecodeHash": "none" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "storageLayout", - "devdoc", - "userdoc" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/.chainId b/packages/contracts-bedrock/deployments/optimism-goerli/.chainId deleted file mode 100644 index 1e59c84a3a51..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/.chainId +++ /dev/null @@ -1 +0,0 @@ -420 \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/AttestationStation.json b/packages/contracts-bedrock/deployments/optimism-goerli/AttestationStation.json deleted file mode 100644 index c2c9d3e8681a..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/AttestationStation.json +++ /dev/null @@ -1,270 +0,0 @@ -{ - "address": "0xbeD744818e96AAD8a51324291a6f6Cb20A0c22be", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "creator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "about", - "type": "address" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "val", - "type": "bytes" - } - ], - "name": "AttestationCreated", - "type": "event" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "about", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "val", - "type": "bytes" - } - ], - "internalType": "struct AttestationStation.AttestationData[]", - "name": "_attestations", - "type": "tuple[]" - } - ], - "name": "attest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_about", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_key", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "_val", - "type": "bytes" - } - ], - "name": "attest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "attestations", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x4c0aae61c0030872cb5f8654c36fbc192cfab6f09f93df5c0f80268382d964e9", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x956a5152D0f498dBA0c5966577bb44262F8F7078", - "contractAddress": null, - "transactionIndex": 1, - "gasUsed": "666309", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe683044625d767223da2ecd65fd81a34251ffbef27abd3302530be36e99971d0", - "transactionHash": "0x4c0aae61c0030872cb5f8654c36fbc192cfab6f09f93df5c0f80268382d964e9", - "logs": [], - "blockNumber": 4667191, - "cumulativeGasUsed": "666309", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 2, - "solcInputHash": "3aa2ad7d005d9515a1f12df8da17d178", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"about\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"val\",\"type\":\"bytes\"}],\"name\":\"AttestationCreated\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"about\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"val\",\"type\":\"bytes\"}],\"internalType\":\"struct AttestationStation.AttestationData[]\",\"name\":\"_attestations\",\"type\":\"tuple[]\"}],\"name\":\"attest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_about\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_val\",\"type\":\"bytes\"}],\"name\":\"attest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"attestations\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Optimism CollectiveGitcoin\",\"events\":{\"AttestationCreated(address,address,bytes32,bytes)\":{\"params\":{\"about\":\"Address attestation is about.\",\"creator\":\"Address that made the attestation.\",\"key\":\"Key of the attestation.\",\"val\":\"Value of the attestation.\"}}},\"kind\":\"dev\",\"methods\":{\"attest((address,bytes32,bytes)[])\":{\"params\":{\"_attestations\":\"An array of attestation data.\"}},\"attest(address,bytes32,bytes)\":{\"params\":{\"_about\":\"Address that the attestation is about.\",\"_key\":\"A key used to namespace the attestation.\",\"_val\":\"An arbitrary value stored as part of the attestation.\"}},\"constructor\":{\"custom:semver\":\"1.1.0\"},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"AttestationStation\",\"version\":1},\"userdoc\":{\"events\":{\"AttestationCreated(address,address,bytes32,bytes)\":{\"notice\":\"Emitted when Attestation is created.\"}},\"kind\":\"user\",\"methods\":{\"attest((address,bytes32,bytes)[])\":{\"notice\":\"Allows anyone to create attestations.\"},\"attest(address,bytes32,bytes)\":{\"notice\":\"Allows anyone to create an attestation.\"},\"attestations(address,address,bytes32)\":{\"notice\":\"Maps addresses to attestations. Creator => About => Key => Value.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"Where attestations live.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/op-nft/AttestationStation.sol\":\"AttestationStation\"},\"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 uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\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\":\"0x979b13465de4996a1105850abbf48abe7f71d5e18a8d4af318597ee14c165fdf\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\\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 /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/universal/op-nft/AttestationStation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title AttestationStation\\n * @author Optimism Collective\\n * @author Gitcoin\\n * @notice Where attestations live.\\n */\\ncontract AttestationStation is Semver {\\n /**\\n * @notice Struct representing data that is being attested.\\n *\\n * @custom:field about Address for which the attestation is about.\\n * @custom:field key A bytes32 key for the attestation.\\n * @custom:field val The attestation as arbitrary bytes.\\n */\\n struct AttestationData {\\n address about;\\n bytes32 key;\\n bytes val;\\n }\\n\\n /**\\n * @notice Maps addresses to attestations. Creator => About => Key => Value.\\n */\\n mapping(address => mapping(address => mapping(bytes32 => bytes))) public attestations;\\n\\n /**\\n * @notice Emitted when Attestation is created.\\n *\\n * @param creator Address that made the attestation.\\n * @param about Address attestation is about.\\n * @param key Key of the attestation.\\n * @param val Value of the attestation.\\n */\\n event AttestationCreated(\\n address indexed creator,\\n address indexed about,\\n bytes32 indexed key,\\n bytes val\\n );\\n\\n /**\\n * @custom:semver 1.1.0\\n */\\n constructor() Semver(1, 1, 0) {}\\n\\n /**\\n * @notice Allows anyone to create an attestation.\\n *\\n * @param _about Address that the attestation is about.\\n * @param _key A key used to namespace the attestation.\\n * @param _val An arbitrary value stored as part of the attestation.\\n */\\n function attest(\\n address _about,\\n bytes32 _key,\\n bytes memory _val\\n ) public {\\n attestations[msg.sender][_about][_key] = _val;\\n\\n emit AttestationCreated(msg.sender, _about, _key, _val);\\n }\\n\\n /**\\n * @notice Allows anyone to create attestations.\\n *\\n * @param _attestations An array of attestation data.\\n */\\n function attest(AttestationData[] calldata _attestations) external {\\n uint256 length = _attestations.length;\\n for (uint256 i = 0; i < length; ) {\\n AttestationData memory attestation = _attestations[i];\\n\\n attest(attestation.about, attestation.key, attestation.val);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x80718fdc09061ea8f8b99a0b846eee46c5a2a1372dbb0cbc3d40953cb3af19e0\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60e060405234801561001057600080fd5b506001608081905260a052600060c05260805160a05160c051610b1c61004f60003960006101ad015260006101840152600061015b0152610b1c6000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c806329b42cb51461005157806354fd4d501461007a5780635eb5ea1014610082578063702b9dee14610097575b600080fd5b61006461005f36600461046c565b6100aa565b604051610071919061051e565b60405180910390f35b610064610154565b610095610090366004610538565b6101f7565b005b6100956100a5366004610687565b61025a565b60006020818152938152604080822085529281528281209093528252902080546100d3906106de565b80601f01602080910402602001604051908101604052809291908181526020018280546100ff906106de565b801561014c5780601f106101215761010080835404028352916020019161014c565b820191906000526020600020905b81548152906001019060200180831161012f57829003601f168201915b505050505081565b606061017f7f0000000000000000000000000000000000000000000000000000000000000000610306565b6101a87f0000000000000000000000000000000000000000000000000000000000000000610306565b6101d17f0000000000000000000000000000000000000000000000000000000000000000610306565b6040516020016101e393929190610731565b604051602081830303815290604052905090565b8060005b81811015610254576000848483818110610217576102176107a7565b905060200281019061022991906107d6565b61023290610814565b905061024b81600001518260200151836040015161025a565b506001016101fb565b50505050565b3360009081526020818152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320858452909152902061029a82826108df565b50818373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f28710dfecab43d1e29e02aa56b2e1e610c0bae19135c9cf7a83a1adb6df96d85846040516102f9919061051e565b60405180910390a4505050565b60608160000361034957505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610373578061035d81610a28565b915061036c9050600a83610a8f565b915061034d565b60008167ffffffffffffffff81111561038e5761038e6105ad565b6040519080825280601f01601f1916602001820160405280156103b8576020820181803683370190505b5090505b841561043b576103cd600183610aa3565b91506103da600a86610aba565b6103e5906030610ace565b60f81b8183815181106103fa576103fa6107a7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610434600a86610a8f565b94506103bc565b949350505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461046757600080fd5b919050565b60008060006060848603121561048157600080fd5b61048a84610443565b925061049860208501610443565b9150604084013590509250925092565b60005b838110156104c35781810151838201526020016104ab565b838111156102545750506000910152565b600081518084526104ec8160208601602086016104a8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061053160208301846104d4565b9392505050565b6000806020838503121561054b57600080fd5b823567ffffffffffffffff8082111561056357600080fd5b818501915085601f83011261057757600080fd5b81358181111561058657600080fd5b8660208260051b850101111561059b57600080fd5b60209290920196919550909350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126105ed57600080fd5b813567ffffffffffffffff80821115610608576106086105ad565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561064e5761064e6105ad565b8160405283815286602085880101111561066757600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561069c57600080fd5b6106a584610443565b925060208401359150604084013567ffffffffffffffff8111156106c857600080fd5b6106d4868287016105dc565b9150509250925092565b600181811c908216806106f257607f821691505b60208210810361072b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600084516107438184602089016104a8565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161077f816001850160208a016104a8565b6001920191820152835161079a8160028401602088016104a8565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261080a57600080fd5b9190910192915050565b60006060823603121561082657600080fd5b6040516060810167ffffffffffffffff828210818311171561084a5761084a6105ad565b8160405261085785610443565b835260208501356020840152604085013591508082111561087757600080fd5b50610884368286016105dc565b60408301525092915050565b601f8211156108da57600081815260208120601f850160051c810160208610156108b75750805b601f850160051c820191505b818110156108d6578281556001016108c3565b5050505b505050565b815167ffffffffffffffff8111156108f9576108f96105ad565b61090d8161090784546106de565b84610890565b602080601f831160018114610960576000841561092a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556108d6565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156109ad5788860151825594840194600190910190840161098e565b50858210156109e957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610a5957610a596109f9565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a9e57610a9e610a60565b500490565b600082821015610ab557610ab56109f9565b500390565b600082610ac957610ac9610a60565b500690565b60008219821115610ae157610ae16109f9565b50019056fea2646970667358221220bfd4abacc1c2510682b093eea8745255cdd9f45c5b16c168540522a65ddc1f3264736f6c634300080f0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806329b42cb51461005157806354fd4d501461007a5780635eb5ea1014610082578063702b9dee14610097575b600080fd5b61006461005f36600461046c565b6100aa565b604051610071919061051e565b60405180910390f35b610064610154565b610095610090366004610538565b6101f7565b005b6100956100a5366004610687565b61025a565b60006020818152938152604080822085529281528281209093528252902080546100d3906106de565b80601f01602080910402602001604051908101604052809291908181526020018280546100ff906106de565b801561014c5780601f106101215761010080835404028352916020019161014c565b820191906000526020600020905b81548152906001019060200180831161012f57829003601f168201915b505050505081565b606061017f7f0000000000000000000000000000000000000000000000000000000000000000610306565b6101a87f0000000000000000000000000000000000000000000000000000000000000000610306565b6101d17f0000000000000000000000000000000000000000000000000000000000000000610306565b6040516020016101e393929190610731565b604051602081830303815290604052905090565b8060005b81811015610254576000848483818110610217576102176107a7565b905060200281019061022991906107d6565b61023290610814565b905061024b81600001518260200151836040015161025a565b506001016101fb565b50505050565b3360009081526020818152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320858452909152902061029a82826108df565b50818373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f28710dfecab43d1e29e02aa56b2e1e610c0bae19135c9cf7a83a1adb6df96d85846040516102f9919061051e565b60405180910390a4505050565b60608160000361034957505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610373578061035d81610a28565b915061036c9050600a83610a8f565b915061034d565b60008167ffffffffffffffff81111561038e5761038e6105ad565b6040519080825280601f01601f1916602001820160405280156103b8576020820181803683370190505b5090505b841561043b576103cd600183610aa3565b91506103da600a86610aba565b6103e5906030610ace565b60f81b8183815181106103fa576103fa6107a7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610434600a86610a8f565b94506103bc565b949350505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461046757600080fd5b919050565b60008060006060848603121561048157600080fd5b61048a84610443565b925061049860208501610443565b9150604084013590509250925092565b60005b838110156104c35781810151838201526020016104ab565b838111156102545750506000910152565b600081518084526104ec8160208601602086016104a8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061053160208301846104d4565b9392505050565b6000806020838503121561054b57600080fd5b823567ffffffffffffffff8082111561056357600080fd5b818501915085601f83011261057757600080fd5b81358181111561058657600080fd5b8660208260051b850101111561059b57600080fd5b60209290920196919550909350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126105ed57600080fd5b813567ffffffffffffffff80821115610608576106086105ad565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561064e5761064e6105ad565b8160405283815286602085880101111561066757600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561069c57600080fd5b6106a584610443565b925060208401359150604084013567ffffffffffffffff8111156106c857600080fd5b6106d4868287016105dc565b9150509250925092565b600181811c908216806106f257607f821691505b60208210810361072b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600084516107438184602089016104a8565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161077f816001850160208a016104a8565b6001920191820152835161079a8160028401602088016104a8565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261080a57600080fd5b9190910192915050565b60006060823603121561082657600080fd5b6040516060810167ffffffffffffffff828210818311171561084a5761084a6105ad565b8160405261085785610443565b835260208501356020840152604085013591508082111561087757600080fd5b50610884368286016105dc565b60408301525092915050565b601f8211156108da57600081815260208120601f850160051c810160208610156108b75750805b601f850160051c820191505b818110156108d6578281556001016108c3565b5050505b505050565b815167ffffffffffffffff8111156108f9576108f96105ad565b61090d8161090784546106de565b84610890565b602080601f831160018114610960576000841561092a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556108d6565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156109ad5788860151825594840194600190910190840161098e565b50858210156109e957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610a5957610a596109f9565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a9e57610a9e610a60565b500490565b600082821015610ab557610ab56109f9565b500390565b600082610ac957610ac9610a60565b500690565b60008219821115610ae157610ae16109f9565b50019056fea2646970667358221220bfd4abacc1c2510682b093eea8745255cdd9f45c5b16c168540522a65ddc1f3264736f6c634300080f0033", - "devdoc": { - "author": "Optimism CollectiveGitcoin", - "events": { - "AttestationCreated(address,address,bytes32,bytes)": { - "params": { - "about": "Address attestation is about.", - "creator": "Address that made the attestation.", - "key": "Key of the attestation.", - "val": "Value of the attestation." - } - } - }, - "kind": "dev", - "methods": { - "attest((address,bytes32,bytes)[])": { - "params": { - "_attestations": "An array of attestation data." - } - }, - "attest(address,bytes32,bytes)": { - "params": { - "_about": "Address that the attestation is about.", - "_key": "A key used to namespace the attestation.", - "_val": "An arbitrary value stored as part of the attestation." - } - }, - "constructor": { - "custom:semver": "1.1.0" - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "title": "AttestationStation", - "version": 1 - }, - "userdoc": { - "events": { - "AttestationCreated(address,address,bytes32,bytes)": { - "notice": "Emitted when Attestation is created." - } - }, - "kind": "user", - "methods": { - "attest((address,bytes32,bytes)[])": { - "notice": "Allows anyone to create attestations." - }, - "attest(address,bytes32,bytes)": { - "notice": "Allows anyone to create an attestation." - }, - "attestations(address,address,bytes32)": { - "notice": "Maps addresses to attestations. Creator => About => Key => Value." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "Where attestations live.", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 2135, - "contract": "contracts/universal/op-nft/AttestationStation.sol:AttestationStation", - "label": "attestations", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_bytes32,t_bytes_storage)))" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_bytes_storage": { - "encoding": "bytes", - "label": "bytes", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_mapping(t_bytes32,t_bytes_storage)))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => mapping(bytes32 => bytes)))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_mapping(t_bytes32,t_bytes_storage))" - }, - "t_mapping(t_address,t_mapping(t_bytes32,t_bytes_storage))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(bytes32 => bytes))", - "numberOfBytes": "32", - "value": "t_mapping(t_bytes32,t_bytes_storage)" - }, - "t_mapping(t_bytes32,t_bytes_storage)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => bytes)", - "numberOfBytes": "32", - "value": "t_bytes_storage" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/AttestationStationProxy.json b/packages/contracts-bedrock/deployments/optimism-goerli/AttestationStationProxy.json deleted file mode 100644 index bb87ce216cf2..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/AttestationStationProxy.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "address": "0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77", - "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": "0x784bf644f4af308c768373d6599c71c976fe8977b1b663bdec2025a16f6bff56", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "534190", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000008000000000000000000000000", - "blockHash": "0x7085d08eb9d49fc1ecaa8568a338414983ced83535d8fd2931113b981dea986f", - "transactionHash": "0x784bf644f4af308c768373d6599c71c976fe8977b1b663bdec2025a16f6bff56", - "logs": [ - { - "transactionIndex": 0, - "blockNumber": 3451201, - "transactionHash": "0x784bf644f4af308c768373d6599c71c976fe8977b1b663bdec2025a16f6bff56", - "address": "0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58", - "logIndex": 0, - "blockHash": "0x7085d08eb9d49fc1ecaa8568a338414983ced83535d8fd2931113b981dea986f" - } - ], - "blockNumber": 3451201, - "cumulativeGasUsed": "534190", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "45837d34ff24b9cb2ae34232b60ea874", - "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-bedrock/deployments/optimism-goerli/BaseFeeVault.json b/packages/contracts-bedrock/deployments/optimism-goerli/BaseFeeVault.json deleted file mode 100644 index ca4ebf274bcb..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/BaseFeeVault.json +++ /dev/null @@ -1,191 +0,0 @@ -{ - "address": "0x984eBeFb32A5c2862e92ce90EA0C81Ab69F026B5", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "inputs": [], - "name": "MIN_WITHDRAWAL_AMOUNT", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RECIPIENT", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalProcessed", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0x8200dcd39f9e6c14017c508bf58527bea3dafd1eb06a5fe006b3345009f107d8", - "receipt": { - "to": null, - "from": "0xf80267194936da1E98dB10bcE06F3147D580a62e", - "contractAddress": "0x984eBeFb32A5c2862e92ce90EA0C81Ab69F026B5", - "transactionIndex": 1, - "gasUsed": "492913", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x2271d21bc9c675c55be64016d7c610f82108dfc2a31b690ef0cbee4b0efa6709", - "transactionHash": "0x8200dcd39f9e6c14017c508bf58527bea3dafd1eb06a5fe006b3345009f107d8", - "logs": [], - "blockNumber": 8579696, - "cumulativeGasUsed": "539814", - "status": 1, - "byzantium": true - }, - "args": [ - "0xBc1233d0C3e6B5d53Ab455cF65A6623F6dCd7e4f" - ], - "numDeployments": 1, - "solcInputHash": "2d538e296d12ca6101a896ac2e894043", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MIN_WITHDRAWAL_AMOUNT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RECIPIENT\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalProcessed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"custom:proxied\":\"@custom:predeploy 0x4200000000000000000000000000000000000019\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:semver\":\"1.1.0\",\"params\":{\"_recipient\":\"Address that will receive the accumulated fees.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"BaseFeeVault\",\"version\":1},\"userdoc\":{\"events\":{\"Withdrawal(uint256,address,address)\":{\"notice\":\"Emits each time that a withdrawal occurs.\"}},\"kind\":\"user\",\"methods\":{\"MIN_WITHDRAWAL_AMOUNT()\":{\"notice\":\"Minimum balance before a withdrawal can be triggered.\"},\"RECIPIENT()\":{\"notice\":\"Wallet that will receive the fees on L1.\"},\"totalProcessed()\":{\"notice\":\"Total amount of wei processed by the contract.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"},\"withdraw()\":{\"notice\":\"Triggers a withdrawal of funds to the L1 fee wallet.\"}},\"notice\":\"The BaseFeeVault accumulates the base fee that is paid by transactions.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2/BaseFeeVault.sol\":\"BaseFeeVault\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/L1/ResourceMetering.sol\":{\"keccak256\":\"0xbd7b9532a70d8c842bfce0ea971be50d02fbbf0227c9ad55c71ac68d438010f4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4969f478dd54e89392cda2ea0c5edcf1be55a5dee43a0e410527b6e3bcb85c88\",\"dweb:/ipfs/QmU2crAojw8DRDsz7PAPrereazjFsKh9wtfTpTDVh6NLfW\"]},\"contracts/L2/BaseFeeVault.sol\":{\"keccak256\":\"0xa2d3cb58a2f00b25aea98e0cc532c44ab5c97f28c6f9e3348a31ddc54ffffcb7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://506dbf5211d511db2407d0551e2a5cc2c4754520acad08ee1d9a5d0cffaa71e0\",\"dweb:/ipfs/QmYftWQRoB7CE6huatMncAVUtGYJc42E9heW26snTQqfXn\"]},\"contracts/L2/L2StandardBridge.sol\":{\"keccak256\":\"0xd77e04c57f33cd32c32f326cd06e213d8a27a9fd372cfc4269953a49243c8c41\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f59627bf4c08c85886e819b29b8565b48fa7e9c230732fedfbb0b9c9a0ee04c5\",\"dweb:/ipfs/Qmao1VbQ57h6gdCZTYfipa8LB1wBwAthop5tPd9TgDXES2\"]},\"contracts/libraries/Arithmetic.sol\":{\"keccak256\":\"0xc8858039f87e48e6f18c1af8bc0b03e57cfef564acddfd06e4d91e3db7ac5ed6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2fc79af1e844aa6dc1c68067bfe1d359df8d4e9a3e8881afb3bcfcbf68071714\",\"dweb:/ipfs/QmcNC4k8zmvwj4kZizSenTiWbx2DJQPbwqXXLF4iMbkRVD\"]},\"contracts/libraries/Burn.sol\":{\"keccak256\":\"0x54233b226ba6919dc46d438bc790108d8f855001002a1b9c3c37aed7a83e5f3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4051a4baca357a9191a6c9e3aa1593a17b69dd7915966e23e4cb269e9c1d9ed4\",\"dweb:/ipfs/QmadKjGKvxm53abVHQdsxrXBc8e9jXywu6vvhkAgjsx59J\"]},\"contracts/libraries/Constants.sol\":{\"keccak256\":\"0x8c7be28a175eb732995a7f704560163c30261f9f70d377f865c5060882509f5d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f72aba26553b10ca88708e05461691b36b0d2ec7a87f718022fe119ca9c70852\",\"dweb:/ipfs/QmQtDEB1F3D8RsgG63KSJ9t7ZyFLaXc2Av81vKD9y2TMn7\"]},\"contracts/libraries/Encoding.sol\":{\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f18156216c1f9457c2e032a812ad70f2babbc5b89997554ff014d64c483fb2ff\",\"dweb:/ipfs/Qmc5rjMaBFn3jV7XqDrEvRbmatQvJxeVJYA5B5rdcKPkcJ\"]},\"contracts/libraries/Hashing.sol\":{\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6746ed0d26d603568818cc52a29d0209effd69f7e55bd0017a6b91bd6cf319fe\",\"dweb:/ipfs/QmPebCmCELMBRtDDxt5ziEPfRXUh6tfm2qJdwz3iyrDdWN\"]},\"contracts/libraries/Predeploys.sol\":{\"keccak256\":\"0xfc30fb239b5f00284f4b8f578a62f0882597e939335c91ea9bc4aab3070ddc43\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fa132267b3a9d98568b4e02cbb68fe2d2c0ca630826242c1b2293a8fa35bd302\",\"dweb:/ipfs/QmdYvcGbaykP6wyBu5T2obXrWK56xGnfWqbYeeWpTChq3w\"]},\"contracts/libraries/SafeCall.sol\":{\"keccak256\":\"0x6e815b62528d452a4f63040d75ff7a08db8ba8096050a53355fc49abaebdf245\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e27e542a11165c82cbb6961f4d8c2a58527fba1ab915afeeded50e96ce929777\",\"dweb:/ipfs/QmRPXdmUAbL1WHZBvENKWkFuHb9bQyrbiJWwDvzEQBLVi8\"]},\"contracts/libraries/Types.sol\":{\"keccak256\":\"0x4fe8ec920798661a828430bd30dc2715eeb40534ec01c0a7bf41cb4ab422e134\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://74c8471869900bd459358cd990bda1c8d234c06b788804c7049cf465ae1e299f\",\"dweb:/ipfs/QmakcfP6NmbVUQsKqH7rEyJsbiqckigLahw9g74oencEJ7\"]},\"contracts/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://921c44e6a0982b9a4011900fda1bda2c06b7a85894967de98b407a83fe9f90c0\",\"dweb:/ipfs/QmSsHLKDUQ82kpKdqB6VntVGKuPDb4W9VdotsubuqWBzio\"]},\"contracts/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x3c99b1e768cc4c1e064ccc137b1b4d5961bf4edf071be84cc216c5b20f1c00da\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e36b2a6325c2f804d769271575669b62ab2da2df3c81921ac7487399fe02af07\",\"dweb:/ipfs/QmTCmcEKwvD8Xvjyev268Bkz27FC7TJpUbw1nADcsThnUr\"]},\"contracts/universal/FeeVault.sol\":{\"keccak256\":\"0x73eb2c835495ec308c69783db55c6cc315ed2a55ee6811ccda4e7dbbde04b2c8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b5e46201184138d60e339c98276e3b265717a12795270a1d0ef03157e452e9a0\",\"dweb:/ipfs/QmWGLhTcPuF9ZZfrjGj4QGCzEuDwiyRAMpnQvxd2oLFX75\"]},\"contracts/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x2fea0ee05071c9c6b06a34a8e805801e247e861359b376a8918106e1d6f77ebe\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://198c91bda2edf864ddad1f8ab6168155d13d6ba5487418e5531ff040ff250686\",\"dweb:/ipfs/QmQzxfHY4P7zdVFRh2DTdGt1KeMHaGKNRf3KPZ1mRTYEGB\"]},\"contracts/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x302094342a45ebdf7f46f4fb48821960d2a4134f66fd7f458f73fc4ddf34d219\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8b0e2b496e966ca6037e1c9be1d44417c0180fda2a27f68114e93b899defb783\",\"dweb:/ipfs/QmXP76ivMLxYxscC7B9E9qtW3u6HJ2MNaRVeo3x24VEAQH\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9baf7797439c0ae6512f4639dfc6a1934dbd4e4d7cbb8e63e99264ff47682c9e\",\"dweb:/ipfs/QmawAuhppPyeoZH3rC1uh87xDELa9Lyfw5pYsBqE8myE1m\"]},\"contracts/universal/StandardBridge.sol\":{\"keccak256\":\"0xaa45044774fa70ed322983c3c0138b21d26d75f4b7e8f5324d53c3eef91adec4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c65c95d0cb71f2e32f5ffdea92151a9a46bbd538ba110389a134963fd16a33e9\",\"dweb:/ipfs/QmaPNZokt4j5SCXaWwVtw6qxu5GXWFa3SWBgaSWPPA9KUG\"]},\"node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"]},\"node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"]},\"node_modules/@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b2717fd2bdac99daa960a6de500754ea1b932093c946388c381da48658234b95\",\"dweb:/ipfs/QmP6QVMn6UeA3ByahyJbYQr5M6coHKBKsf3ySZSfbyA8R7\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x032807210d1d7d218963d7355d62e021a84bf1b3339f4f50be2f63b53cccaf29\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://11756f42121f6541a35a8339ea899ee7514cfaa2e6d740625fcc844419296aa6\",\"dweb:/ipfs/QmekMuk6BY4DAjzeXr4MSbKdgoqqsZnA8JPtuyWc6CwXHf\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"]},\"node_modules/@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"]},\"node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"]},\"node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"]}},\"version\":1}", - "bytecode": "0x61012060405234801561001157600080fd5b506040516108e53803806108e58339810160408190526100309161005d565b678ac7230489e800006080526001600160a01b031660a052600160c081905260e05260006101005261008d565b60006020828403121561006f57600080fd5b81516001600160a01b038116811461008657600080fd5b9392505050565b60805160a05160c05160e051610100516108006100e560003960006103d3015260006103aa01526000610381015260008181607c015281816102570152610319015260008181610137015261015b01526108006000f3fe60806040526004361061005e5760003560e01c806354fd4d501161004357806354fd4d50146100df57806384411d6514610101578063d3e5792b1461012557600080fd5b80630d9019e11461006a5780633ccfd60b146100c857600080fd5b3661006557005b600080fd5b34801561007657600080fd5b5061009e7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100d457600080fd5b506100dd610159565b005b3480156100eb57600080fd5b506100f461037a565b6040516100bf91906105d4565b34801561010d57600080fd5b5061011760005481565b6040519081526020016100bf565b34801561013157600080fd5b506101177f000000000000000000000000000000000000000000000000000000000000000081565b7f0000000000000000000000000000000000000000000000000000000000000000471015610233576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a40160405180910390fd5b600047905080600080828254610249919061061d565b9091555050604080518281527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020820152338183015290517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a1604080516020810182526000815290517fe11013dd0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109163e11013dd918491610345917f0000000000000000000000000000000000000000000000000000000000000000916188b891600401610635565b6000604051808303818588803b15801561035e57600080fd5b505af1158015610372573d6000803e3d6000fd5b505050505050565b60606103a57f000000000000000000000000000000000000000000000000000000000000000061041d565b6103ce7f000000000000000000000000000000000000000000000000000000000000000061041d565b6103f77f000000000000000000000000000000000000000000000000000000000000000061041d565b60405160200161040993929190610679565b604051602081830303815290604052905090565b60608160000361046057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561048a5780610474816106ef565b91506104839050600a83610756565b9150610464565b60008167ffffffffffffffff8111156104a5576104a561076a565b6040519080825280601f01601f1916602001820160405280156104cf576020820181803683370190505b5090505b8415610552576104e4600183610799565b91506104f1600a866107b0565b6104fc90603061061d565b60f81b818381518110610511576105116107c4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061054b600a86610756565b94506104d3565b949350505050565b60005b8381101561057557818101518382015260200161055d565b83811115610584576000848401525b50505050565b600081518084526105a281602086016020860161055a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006105e7602083018461058a565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610630576106306105ee565b500190565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff83166020820152606060408201526000610670606083018461058a565b95945050505050565b6000845161068b81846020890161055a565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516106c7816001850160208a0161055a565b600192019182015283516106e281600284016020880161055a565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610720576107206105ee565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261076557610765610727565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107ab576107ab6105ee565b500390565b6000826107bf576107bf610727565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c806354fd4d501161004357806354fd4d50146100df57806384411d6514610101578063d3e5792b1461012557600080fd5b80630d9019e11461006a5780633ccfd60b146100c857600080fd5b3661006557005b600080fd5b34801561007657600080fd5b5061009e7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100d457600080fd5b506100dd610159565b005b3480156100eb57600080fd5b506100f461037a565b6040516100bf91906105d4565b34801561010d57600080fd5b5061011760005481565b6040519081526020016100bf565b34801561013157600080fd5b506101177f000000000000000000000000000000000000000000000000000000000000000081565b7f0000000000000000000000000000000000000000000000000000000000000000471015610233576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a40160405180910390fd5b600047905080600080828254610249919061061d565b9091555050604080518281527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020820152338183015290517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a1604080516020810182526000815290517fe11013dd0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109163e11013dd918491610345917f0000000000000000000000000000000000000000000000000000000000000000916188b891600401610635565b6000604051808303818588803b15801561035e57600080fd5b505af1158015610372573d6000803e3d6000fd5b505050505050565b60606103a57f000000000000000000000000000000000000000000000000000000000000000061041d565b6103ce7f000000000000000000000000000000000000000000000000000000000000000061041d565b6103f77f000000000000000000000000000000000000000000000000000000000000000061041d565b60405160200161040993929190610679565b604051602081830303815290604052905090565b60608160000361046057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561048a5780610474816106ef565b91506104839050600a83610756565b9150610464565b60008167ffffffffffffffff8111156104a5576104a561076a565b6040519080825280601f01601f1916602001820160405280156104cf576020820181803683370190505b5090505b8415610552576104e4600183610799565b91506104f1600a866107b0565b6104fc90603061061d565b60f81b818381518110610511576105116107c4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061054b600a86610756565b94506104d3565b949350505050565b60005b8381101561057557818101518382015260200161055d565b83811115610584576000848401525b50505050565b600081518084526105a281602086016020860161055a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006105e7602083018461058a565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610630576106306105ee565b500190565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff83166020820152606060408201526000610670606083018461058a565b95945050505050565b6000845161068b81846020890161055a565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516106c7816001850160208a0161055a565b600192019182015283516106e281600284016020880161055a565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610720576107206105ee565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261076557610765610727565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107ab576107ab6105ee565b500390565b6000826107bf576107bf610727565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_recipient": "Address that will receive the accumulated fees." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "title": "BaseFeeVault" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MIN_WITHDRAWAL_AMOUNT()": { - "notice": "Minimum balance before a withdrawal can be triggered." - }, - "RECIPIENT()": { - "notice": "Wallet that will receive the fees on L1." - }, - "totalProcessed()": { - "notice": "Total amount of wei processed by the contract." - }, - "version()": { - "notice": "Returns the full semver contract version." - }, - "withdraw()": { - "notice": "Triggers a withdrawal of funds to the L1 fee wallet." - } - }, - "events": { - "Withdrawal(uint256,address,address)": { - "notice": "Emits each time that a withdrawal occurs." - } - }, - "notice": "The BaseFeeVault accumulates the base fee that is paid by transactions." - }, - "storageLayout": { - "storage": [ - { - "astId": 46671, - "contract": "contracts/L2/BaseFeeVault.sol:BaseFeeVault", - "label": "totalProcessed", - "offset": 0, - "slot": "0", - "type": "t_uint256" - } - ], - "types": { - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/CheckBalanceHigh.json b/packages/contracts-bedrock/deployments/optimism-goerli/CheckBalanceHigh.json deleted file mode 100644 index 5d65f8d86ea3..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/CheckBalanceHigh.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "address": "0x5d7103853f12109A7d27F118e54BbC654ad847E9", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "threshold", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct CheckBalanceHigh.Params", - "name": "params", - "type": "tuple" - } - ], - "name": "_EventToExposeStructInABI__Params", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_params", - "type": "bytes" - } - ], - "name": "check", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x3471e90c7d79ad0c4b5e48740c5c3bbc1dd95df6d6b2b84b2f41f0ec1426c101", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xc37f6a6c4AB335E20d10F034B90386E2fb70bbF5", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "176628", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x132ca8cc42fb4d0b9a111b739b00c60e504a5242b4303a10a0dd3d1940416b58", - "transactionHash": "0x3471e90c7d79ad0c4b5e48740c5c3bbc1dd95df6d6b2b84b2f41f0ec1426c101", - "logs": [], - "blockNumber": 379105, - "cumulativeGasUsed": "176628", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "cb12280dddcf446d7c90129cbaba29bb", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"struct CheckBalanceHigh.Params\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"_EventToExposeStructInABI__Params\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_params\",\"type\":\"bytes\"}],\"name\":\"check\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"title\":\"CheckBalanceHigh\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"DripCheck for checking if an account's balance is above a given threshold.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/dripchecks/CheckBalanceHigh.sol\":\"CheckBalanceHigh\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xbf1b9be6bbcbbbd2268023a169382c9a62a58a343420e4bc4494a9f463f86042\",\"license\":\"MIT\"},\"contracts/universal/drippie/dripchecks/CheckBalanceHigh.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { IDripCheck } from \\\"../IDripCheck.sol\\\";\\n\\n/**\\n * @title CheckBalanceHigh\\n * @notice DripCheck for checking if an account's balance is above a given threshold.\\n */\\ncontract CheckBalanceHigh is IDripCheck {\\n event _EventToExposeStructInABI__Params(Params params);\\n struct Params {\\n address target;\\n uint256 threshold;\\n }\\n\\n function check(bytes memory _params) external view returns (bool) {\\n Params memory params = abi.decode(_params, (Params));\\n\\n // Check target balance is above threshold.\\n return params.target.balance > params.threshold;\\n }\\n}\\n\",\"keccak256\":\"0x413fddb77f3ceb396907ac4caa30070051897867cc914cf34f8abed5d2f19c9f\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610239806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e3660046100c3565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610192565b6020810151905173ffffffffffffffffffffffffffffffffffffffff1631119392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156100d557600080fd5b813567ffffffffffffffff808211156100ed57600080fd5b818401915084601f83011261010157600080fd5b81358181111561011357610113610094565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561015957610159610094565b8160405282815287602084870101111561017257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000604082840312156101a457600080fd5b6040516040810181811067ffffffffffffffff821117156101c7576101c7610094565b604052825173ffffffffffffffffffffffffffffffffffffffff811681146101ee57600080fd5b8152602092830151928101929092525091905056fea26469706673582212202670037ac2f0df3fc2c19f630f10737e037f1732829274c37513beda7d16439864736f6c634300080f0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e3660046100c3565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610192565b6020810151905173ffffffffffffffffffffffffffffffffffffffff1631119392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156100d557600080fd5b813567ffffffffffffffff808211156100ed57600080fd5b818401915084601f83011261010157600080fd5b81358181111561011357610113610094565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561015957610159610094565b8160405282815287602084870101111561017257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000604082840312156101a457600080fd5b6040516040810181811067ffffffffffffffff821117156101c7576101c7610094565b604052825173ffffffffffffffffffffffffffffffffffffffff811681146101ee57600080fd5b8152602092830151928101929092525091905056fea26469706673582212202670037ac2f0df3fc2c19f630f10737e037f1732829274c37513beda7d16439864736f6c634300080f0033", - "devdoc": { - "kind": "dev", - "methods": {}, - "title": "CheckBalanceHigh", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "notice": "DripCheck for checking if an account's balance is above a given threshold.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/CheckBalanceLow.json b/packages/contracts-bedrock/deployments/optimism-goerli/CheckBalanceLow.json deleted file mode 100644 index 2b1fb5e12233..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/CheckBalanceLow.json +++ /dev/null @@ -1,87 +0,0 @@ -{ - "address": "0x7Ce13D154FAEE5C8B3E6b19d4Add16f21d884474", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "threshold", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct CheckBalanceLow.Params", - "name": "params", - "type": "tuple" - } - ], - "name": "_EventToExposeStructInABI__Params", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_params", - "type": "bytes" - } - ], - "name": "check", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0xa033cbc354b12f1ce14dd09985d91cdf764a9c9f2c40fd10dff29729579c4b8f", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xc37f6a6c4AB335E20d10F034B90386E2fb70bbF5", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "176640", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x355bce78cb18977b9744bb3f52d9b6be1a7b9eebeb8ac23b6e5dfab7567cb18b", - "transactionHash": "0xa033cbc354b12f1ce14dd09985d91cdf764a9c9f2c40fd10dff29729579c4b8f", - "logs": [], - "blockNumber": 379110, - "cumulativeGasUsed": "176640", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "cb12280dddcf446d7c90129cbaba29bb", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"struct CheckBalanceLow.Params\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"_EventToExposeStructInABI__Params\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_params\",\"type\":\"bytes\"}],\"name\":\"check\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"title\":\"CheckBalanceLow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"DripCheck for checking if an account's balance is below a given threshold.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/dripchecks/CheckBalanceLow.sol\":\"CheckBalanceLow\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xbf1b9be6bbcbbbd2268023a169382c9a62a58a343420e4bc4494a9f463f86042\",\"license\":\"MIT\"},\"contracts/universal/drippie/dripchecks/CheckBalanceLow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { IDripCheck } from \\\"../IDripCheck.sol\\\";\\n\\n/**\\n * @title CheckBalanceLow\\n * @notice DripCheck for checking if an account's balance is below a given threshold.\\n */\\ncontract CheckBalanceLow is IDripCheck {\\n event _EventToExposeStructInABI__Params(Params params);\\n struct Params {\\n address target;\\n uint256 threshold;\\n }\\n\\n function check(bytes memory _params) external view returns (bool) {\\n Params memory params = abi.decode(_params, (Params));\\n\\n // Check target ETH balance is below threshold.\\n return params.target.balance < params.threshold;\\n }\\n}\\n\",\"keccak256\":\"0xb705b39a2a2ba956a75059191b89ccc6a8f398bea09fea6a671fcb8ceaac5e23\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610239806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e3660046100c3565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610192565b6020810151905173ffffffffffffffffffffffffffffffffffffffff1631109392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156100d557600080fd5b813567ffffffffffffffff808211156100ed57600080fd5b818401915084601f83011261010157600080fd5b81358181111561011357610113610094565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561015957610159610094565b8160405282815287602084870101111561017257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000604082840312156101a457600080fd5b6040516040810181811067ffffffffffffffff821117156101c7576101c7610094565b604052825173ffffffffffffffffffffffffffffffffffffffff811681146101ee57600080fd5b8152602092830151928101929092525091905056fea2646970667358221220f1fe79edf6cb1b21a2c196070aaf9fd8aa207004c7fd99c5231e1322bc0d04d864736f6c634300080f0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e3660046100c3565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610192565b6020810151905173ffffffffffffffffffffffffffffffffffffffff1631109392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156100d557600080fd5b813567ffffffffffffffff808211156100ed57600080fd5b818401915084601f83011261010157600080fd5b81358181111561011357610113610094565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561015957610159610094565b8160405282815287602084870101111561017257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000604082840312156101a457600080fd5b6040516040810181811067ffffffffffffffff821117156101c7576101c7610094565b604052825173ffffffffffffffffffffffffffffffffffffffff811681146101ee57600080fd5b8152602092830151928101929092525091905056fea2646970667358221220f1fe79edf6cb1b21a2c196070aaf9fd8aa207004c7fd99c5231e1322bc0d04d864736f6c634300080f0033", - "devdoc": { - "kind": "dev", - "methods": {}, - "title": "CheckBalanceLow", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "notice": "DripCheck for checking if an account's balance is below a given threshold.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/CheckGelatoLow.json b/packages/contracts-bedrock/deployments/optimism-goerli/CheckGelatoLow.json deleted file mode 100644 index 4107cb9ea6b7..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/CheckGelatoLow.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "address": "0xF9c8a4Cb4021f57F9f6d69799cA9BefF64524862", - "abi": [ - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "treasury", - "type": "address" - }, - { - "internalType": "uint256", - "name": "threshold", - "type": "uint256" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "indexed": false, - "internalType": "struct CheckGelatoLow.Params", - "name": "params", - "type": "tuple" - } - ], - "name": "_EventToExposeStructInABI__Params", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_params", - "type": "bytes" - } - ], - "name": "check", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0xa2c3892e5b792fdb814d5d148fd3b1ff19b06878fe245fb93ad179f403d05b01", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "222032", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xefeb7750cbbb732133ef4060beacd5f4b07c1f1b7a2c41270b1f43a98dd95c77", - "transactionHash": "0xa2c3892e5b792fdb814d5d148fd3b1ff19b06878fe245fb93ad179f403d05b01", - "logs": [], - "blockNumber": 380292, - "cumulativeGasUsed": "222032", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "cb12280dddcf446d7c90129cbaba29bb", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"treasury\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct CheckGelatoLow.Params\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"_EventToExposeStructInABI__Params\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_params\",\"type\":\"bytes\"}],\"name\":\"check\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"title\":\"CheckGelatoLow\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"DripCheck for checking if an account's Gelato ETH balance is below some threshold.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/dripchecks/CheckGelatoLow.sol\":\"CheckGelatoLow\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xbf1b9be6bbcbbbd2268023a169382c9a62a58a343420e4bc4494a9f463f86042\",\"license\":\"MIT\"},\"contracts/universal/drippie/dripchecks/CheckGelatoLow.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { IDripCheck } from \\\"../IDripCheck.sol\\\";\\n\\ninterface IGelatoTreasury {\\n function userTokenBalance(address _user, address _token) external view returns (uint256);\\n}\\n\\n/**\\n * @title CheckGelatoLow\\n * @notice DripCheck for checking if an account's Gelato ETH balance is below some threshold.\\n */\\ncontract CheckGelatoLow is IDripCheck {\\n event _EventToExposeStructInABI__Params(Params params);\\n struct Params {\\n address treasury;\\n uint256 threshold;\\n address recipient;\\n }\\n\\n function check(bytes memory _params) external view returns (bool) {\\n Params memory params = abi.decode(_params, (Params));\\n\\n // Check GelatoTreasury ETH balance is below threshold.\\n return\\n IGelatoTreasury(params.treasury).userTokenBalance(\\n params.recipient,\\n // Gelato represents ETH as 0xeeeee....eeeee\\n 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\\n ) < params.threshold;\\n }\\n}\\n\",\"keccak256\":\"0x527fc26a3f52e97f22d88859cac0511fc57c8a0f46b0dd9549aa98b248086a9f\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061030c806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e366004610160565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610258565b6020810151815160408084015190517fb47064c800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6024820152939450919291169063b47064c890604401602060405180830381865afa158015610105573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061012991906102bd565b109392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561017257600080fd5b813567ffffffffffffffff8082111561018a57600080fd5b818401915084601f83011261019e57600080fd5b8135818111156101b0576101b0610131565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101f6576101f6610131565b8160405282815287602084870101111561020f57600080fd5b826020860160208301376000928101602001929092525095945050505050565b805173ffffffffffffffffffffffffffffffffffffffff8116811461025357600080fd5b919050565b60006060828403121561026a57600080fd5b6040516060810181811067ffffffffffffffff8211171561028d5761028d610131565b6040526102998361022f565b8152602083015160208201526102b16040840161022f565b60408201529392505050565b6000602082840312156102cf57600080fd5b505191905056fea2646970667358221220ad6ea11246f072b25bce3394368ffae4870bfffefe4fe262371ac084c9baaca264736f6c634300080f0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004361003e366004610160565b610057565b604051901515815260200160405180910390f35b6000808280602001905181019061006e9190610258565b6020810151815160408084015190517fb47064c800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6024820152939450919291169063b47064c890604401602060405180830381865afa158015610105573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061012991906102bd565b109392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561017257600080fd5b813567ffffffffffffffff8082111561018a57600080fd5b818401915084601f83011261019e57600080fd5b8135818111156101b0576101b0610131565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101f6576101f6610131565b8160405282815287602084870101111561020f57600080fd5b826020860160208301376000928101602001929092525095945050505050565b805173ffffffffffffffffffffffffffffffffffffffff8116811461025357600080fd5b919050565b60006060828403121561026a57600080fd5b6040516060810181811067ffffffffffffffff8211171561028d5761028d610131565b6040526102998361022f565b8152602083015160208201526102b16040840161022f565b60408201529392505050565b6000602082840312156102cf57600080fd5b505191905056fea2646970667358221220ad6ea11246f072b25bce3394368ffae4870bfffefe4fe262371ac084c9baaca264736f6c634300080f0033", - "devdoc": { - "kind": "dev", - "methods": {}, - "title": "CheckGelatoLow", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "notice": "DripCheck for checking if an account's Gelato ETH balance is below some threshold.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/CheckTrue.json b/packages/contracts-bedrock/deployments/optimism-goerli/CheckTrue.json deleted file mode 100644 index 4977fff035bb..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/CheckTrue.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "address": "0x47443D0C184e022F19BD1578F5bca6B8a9F58E32", - "abi": [ - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "check", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - } - ], - "transactionHash": "0x24cd6437a28b245c14e11cdb849a1c7fa5a4f4e7f7ccb9ddb72c837479167cce", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xc37f6a6c4AB335E20d10F034B90386E2fb70bbF5", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "139230", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe7bb26ce3802e753a1fde9a8180fd7c56625e649b03571535ef847f74b86e103", - "transactionHash": "0x24cd6437a28b245c14e11cdb849a1c7fa5a4f4e7f7ccb9ddb72c837479167cce", - "logs": [], - "blockNumber": 379170, - "cumulativeGasUsed": "139230", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "cb12280dddcf446d7c90129cbaba29bb", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"check\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"title\":\"CheckTrue\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"DripCheck that always returns true.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/dripchecks/CheckTrue.sol\":\"CheckTrue\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xbf1b9be6bbcbbbd2268023a169382c9a62a58a343420e4bc4494a9f463f86042\",\"license\":\"MIT\"},\"contracts/universal/drippie/dripchecks/CheckTrue.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { IDripCheck } from \\\"../IDripCheck.sol\\\";\\n\\n/**\\n * @title CheckTrue\\n * @notice DripCheck that always returns true.\\n */\\ncontract CheckTrue is IDripCheck {\\n function check(bytes memory) external pure returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x0f3110b218bd0a2fda2dcd6d366d40682a7624e001204b2bda3fcaa043396027\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5061018c806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004461003e366004610087565b50600190565b604051901515815260200160405180910390f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561009957600080fd5b813567ffffffffffffffff808211156100b157600080fd5b818401915084601f8301126100c557600080fd5b8135818111156100d7576100d7610058565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561011d5761011d610058565b8160405282815287602084870101111561013657600080fd5b82602086016020830137600092810160200192909252509594505050505056fea2646970667358221220e75519244b9d5ac4ed30ca10eb8a4940711a06bf13b8a7953e0a550561861e0164736f6c634300080f0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c64b3bb514610030575b600080fd5b61004461003e366004610087565b50600190565b604051901515815260200160405180910390f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561009957600080fd5b813567ffffffffffffffff808211156100b157600080fd5b818401915084601f8301126100c557600080fd5b8135818111156100d7576100d7610058565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561011d5761011d610058565b8160405282815287602084870101111561013657600080fd5b82602086016020830137600092810160200192909252509594505050505056fea2646970667358221220e75519244b9d5ac4ed30ca10eb8a4940711a06bf13b8a7953e0a550561861e0164736f6c634300080f0033", - "devdoc": { - "kind": "dev", - "methods": {}, - "title": "CheckTrue", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "notice": "DripCheck that always returns true.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/Drippie.json b/packages/contracts-bedrock/deployments/optimism-goerli/Drippie.json deleted file mode 100644 index a4af421c552d..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/Drippie.json +++ /dev/null @@ -1,1038 +0,0 @@ -{ - "address": "0x8D8d533C16D23847EB04EEB0925be8900Dd3af86", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "nameref", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "interval", - "type": "uint256" - }, - { - "internalType": "contract IDripCheck", - "name": "dripcheck", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkparams", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address payable", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct Drippie.DripAction[]", - "name": "actions", - "type": "tuple[]" - } - ], - "indexed": false, - "internalType": "struct Drippie.DripConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "DripCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "nameref", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "address", - "name": "executor", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - } - ], - "name": "DripExecuted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "nameref", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "enum Drippie.DripStatus", - "name": "status", - "type": "uint8" - } - ], - "name": "DripStatusUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ReceivedETH", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrewERC20", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "WithdrewERC721", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrewETH", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_gas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "CALL", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_gas", - "type": "uint256" - } - ], - "name": "DELEGATECALL", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "interval", - "type": "uint256" - }, - { - "internalType": "contract IDripCheck", - "name": "dripcheck", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkparams", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address payable", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct Drippie.DripAction[]", - "name": "actions", - "type": "tuple[]" - } - ], - "internalType": "struct Drippie.DripConfig", - "name": "_config", - "type": "tuple" - } - ], - "name": "create", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - } - ], - "name": "drip", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "drips", - "outputs": [ - { - "internalType": "enum Drippie.DripStatus", - "name": "status", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "interval", - "type": "uint256" - }, - { - "internalType": "contract IDripCheck", - "name": "dripcheck", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkparams", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address payable", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct Drippie.DripAction[]", - "name": "actions", - "type": "tuple[]" - } - ], - "internalType": "struct Drippie.DripConfig", - "name": "config", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "last", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "count", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - } - ], - "name": "executable", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "setOwner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "enum Drippie.DripStatus", - "name": "_status", - "type": "uint8" - } - ], - "name": "status", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC20", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC20", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC721", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "withdrawERC721", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdrawETH", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - } - ], - "name": "withdrawETH", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0xce71abe3a40dce0243fa31e639995deba791fa6d05de5a0ae33ef3d3b8752764", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xc37f6a6c4AB335E20d10F034B90386E2fb70bbF5", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "2132643", - "logsBloom": "0x00000000000000000001000000000000000000000000000000000000000000000000100000000000000000000000080000000000000000000000000000000004000080010000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000020000000000000000000000000000000000000000000000", - "blockHash": "0xc752d29e4717f908630803175a62ede18360241f05892f83e2c570e5b6c2fbb2", - "transactionHash": "0xce71abe3a40dce0243fa31e639995deba791fa6d05de5a0ae33ef3d3b8752764", - "logs": [ - { - "transactionIndex": 0, - "blockNumber": 379101, - "transactionHash": "0xce71abe3a40dce0243fa31e639995deba791fa6d05de5a0ae33ef3d3b8752764", - "address": "0x8D8d533C16D23847EB04EEB0925be8900Dd3af86", - "topics": [ - "0x8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58" - ], - "data": "0x", - "logIndex": 0, - "blockHash": "0xc752d29e4717f908630803175a62ede18360241f05892f83e2c570e5b6c2fbb2" - } - ], - "blockNumber": 379101, - "cumulativeGasUsed": "2132643", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "cb12280dddcf446d7c90129cbaba29bb", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"nameref\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"interval\",\"type\":\"uint256\"},{\"internalType\":\"contract IDripCheck\",\"name\":\"dripcheck\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkparams\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address payable\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"struct Drippie.DripAction[]\",\"name\":\"actions\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"struct Drippie.DripConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DripCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"nameref\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"executor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"DripExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"string\",\"name\":\"nameref\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"enum Drippie.DripStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"name\":\"DripStatusUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ReceivedETH\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrewERC20\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"WithdrewERC721\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrewETH\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_gas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"CALL\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_gas\",\"type\":\"uint256\"}],\"name\":\"DELEGATECALL\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"interval\",\"type\":\"uint256\"},{\"internalType\":\"contract IDripCheck\",\"name\":\"dripcheck\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkparams\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address payable\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"struct Drippie.DripAction[]\",\"name\":\"actions\",\"type\":\"tuple[]\"}],\"internalType\":\"struct Drippie.DripConfig\",\"name\":\"_config\",\"type\":\"tuple\"}],\"name\":\"create\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"drip\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"drips\",\"outputs\":[{\"internalType\":\"enum Drippie.DripStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"interval\",\"type\":\"uint256\"},{\"internalType\":\"contract IDripCheck\",\"name\":\"dripcheck\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkparams\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address payable\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"internalType\":\"struct Drippie.DripAction[]\",\"name\":\"actions\",\"type\":\"tuple[]\"}],\"internalType\":\"struct Drippie.DripConfig\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"last\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"executable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"enum Drippie.DripStatus\",\"name\":\"_status\",\"type\":\"uint8\"}],\"name\":\"status\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"withdrawERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC721\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"withdrawERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"withdrawETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"events\":{\"DripCreated(string,string,(uint256,address,bytes,(address,bytes,uint256)[]))\":{\"params\":{\"config\":\"Config for the created drip.\",\"name\":\"Unindexed name parameter (unhashed).\",\"nameref\":\"Indexed name parameter (hashed).\"}},\"DripExecuted(string,string,address,uint256)\":{\"params\":{\"executor\":\"Address that executed the drip.\",\"name\":\"Unindexed name parameter (unhashed).\",\"nameref\":\"Indexed name parameter (hashed).\",\"timestamp\":\"Time when the drip was executed.\"}},\"DripStatusUpdated(string,string,uint8)\":{\"params\":{\"name\":\"Unindexed name parameter (unhashed).\",\"nameref\":\"Indexed name parameter (hashed).\",\"status\":\"New drip status.\"}}},\"kind\":\"dev\",\"methods\":{\"CALL(address,bytes,uint256,uint256)\":{\"params\":{\"_data\":\"Data to send with the call.\",\"_gas\":\"Amount of gas to send with the call.\",\"_target\":\"Address to call.\",\"_value\":\"ETH value to send with the call.\"},\"returns\":{\"_0\":\"Boolean success value.\",\"_1\":\"Bytes data returned by the call.\"}},\"DELEGATECALL(address,bytes,uint256)\":{\"params\":{\"_data\":\"Data to send with the call.\",\"_gas\":\"Amount of gas to send with the call.\",\"_target\":\"Address to call.\"},\"returns\":{\"_0\":\"Boolean success value.\",\"_1\":\"Bytes data returned by the call.\"}},\"constructor\":{\"params\":{\"_owner\":\"Initial contract owner.\"}},\"create(string,(uint256,address,bytes,(address,bytes,uint256)[]))\":{\"params\":{\"_config\":\"Configuration for the drip.\",\"_name\":\"Name of the drip.\"}},\"drip(string)\":{\"params\":{\"_name\":\"Name of the drip to trigger.\"}},\"executable(string)\":{\"params\":{\"_name\":\"Drip to check.\"},\"returns\":{\"_0\":\"True if the drip is executable, false otherwise.\"}},\"status(string,uint8)\":{\"params\":{\"_name\":\"Name of the drip to update.\",\"_status\":\"New drip status.\"}},\"withdrawERC20(address,address)\":{\"params\":{\"_asset\":\"ERC20 token to withdraw.\",\"_to\":\"Address to receive the ERC20 balance.\"}},\"withdrawERC20(address,address,uint256)\":{\"params\":{\"_amount\":\"Amount of ERC20 to withdraw.\",\"_asset\":\"ERC20 token to withdraw.\",\"_to\":\"Address to receive the ERC20 balance.\"}},\"withdrawERC721(address,address,uint256)\":{\"params\":{\"_asset\":\"ERC721 token to withdraw.\",\"_id\":\"Token ID of the ERC721 token to withdraw.\",\"_to\":\"Address to receive the ERC721 token.\"}},\"withdrawETH(address)\":{\"params\":{\"_to\":\"Address to receive the ETH balance.\"}},\"withdrawETH(address,uint256)\":{\"params\":{\"_amount\":\"Amount of ETH to withdraw.\",\"_to\":\"Address to receive the ETH balance.\"}}},\"title\":\"Drippie\",\"version\":1},\"userdoc\":{\"events\":{\"DripCreated(string,string,(uint256,address,bytes,(address,bytes,uint256)[]))\":{\"notice\":\"Emitted when a new drip is created.\"},\"DripExecuted(string,string,address,uint256)\":{\"notice\":\"Emitted when a drip is executed.\"},\"DripStatusUpdated(string,string,uint8)\":{\"notice\":\"Emitted when a drip status is updated.\"},\"ReceivedETH(address,uint256)\":{\"notice\":\"Emitted when ETH is received by this address.\"},\"WithdrewERC20(address,address,address,uint256)\":{\"notice\":\"Emitted when ERC20 tokens are withdrawn from this address.\"},\"WithdrewERC721(address,address,address,uint256)\":{\"notice\":\"Emitted when ERC20 tokens are withdrawn from this address.\"},\"WithdrewETH(address,address,uint256)\":{\"notice\":\"Emitted when ETH is withdrawn from this address.\"}},\"kind\":\"user\",\"methods\":{\"CALL(address,bytes,uint256,uint256)\":{\"notice\":\"Sends a CALL to a target address.\"},\"DELEGATECALL(address,bytes,uint256)\":{\"notice\":\"Sends a DELEGATECALL to a target address.\"},\"create(string,(uint256,address,bytes,(address,bytes,uint256)[]))\":{\"notice\":\"Creates a new drip with the given name and configuration. Once created, drips cannot be modified in any way (this is a security measure). If you want to update a drip, simply pause (and potentially archive) the existing drip and create a new one.\"},\"drip(string)\":{\"notice\":\"Triggers a drip. This function is deliberately left as a public function because the assumption being made here is that setting the drip to ACTIVE is an affirmative signal that the drip should be executable according to the drip parameters, drip check, and drip interval. Note that drip parameters are read entirely from the state and are not supplied as user input, so there should not be any way for a non-authorized user to influence the behavior of the drip.\"},\"drips(string)\":{\"notice\":\"Maps from drip names to drip states.\"},\"executable(string)\":{\"notice\":\"Checks if a given drip is executable.\"},\"status(string,uint8)\":{\"notice\":\"Sets the status for a given drip. The behavior of this function depends on the status that the user is trying to set. A drip can always move between ACTIVE and PAUSED, but it can never move back to NONE and once ARCHIVED, it can never move back to ACTIVE or PAUSED.\"},\"withdrawERC20(address,address)\":{\"notice\":\"Withdraws full ERC20 balance to the recipient.\"},\"withdrawERC20(address,address,uint256)\":{\"notice\":\"Withdraws partial ERC20 balance to the recipient.\"},\"withdrawERC721(address,address,uint256)\":{\"notice\":\"Withdraws ERC721 token to the recipient.\"},\"withdrawETH(address)\":{\"notice\":\"Withdraws full ETH balance to the recipient.\"},\"withdrawETH(address,uint256)\":{\"notice\":\"Withdraws partial ETH balance to the recipient.\"}},\"notice\":\"Drippie is a system for managing automated contract interactions. A specific interaction is called a \\\"drip\\\" and can be executed according to some condition (called a dripcheck) and an execution interval. Drips cannot be executed faster than the execution interval. Drips can trigger arbitrary contract calls where the calling contract is this contract address. Drips can also send ETH value, which makes them ideal for keeping addresses sufficiently funded with ETH. Drippie is designed to be connected with smart contract automation services so that drips can be executed automatically. However, Drippie is specifically designed to be separated from these services so that trust assumptions are better compartmentalized.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/drippie/Drippie.sol\":\"Drippie\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x7e91c80b0dd1a14a19cb9e661b99924043adab6d9d893bbfcf3a6a3dc23a6743\",\"license\":\"AGPL-3.0-only\"},\"@rari-capital/solmate/src/tokens/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\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\",\"keccak256\":\"0x0240f7703cff32a61ee3e9fbb339e09a944260432a9ef37debf3692b1a6c8049\",\"license\":\"AGPL-3.0-only\"},\"@rari-capital/solmate/src/tokens/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\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 require(\\n to.code.length == 0 ||\\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 require(\\n to.code.length == 0 ||\\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 require(\\n to.code.length == 0 ||\\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 require(\\n to.code.length == 0 ||\\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\",\"keccak256\":\"0xb59c7c25eca386f39da4819a9f70f89b73b7583d5f5127a83ffe5339800b1183\",\"license\":\"AGPL-3.0-only\"},\"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 */\\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 _to.transfer(_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\",\"keccak256\":\"0x3330abf055d317df2b99fdb0f51e1105d27d6f2a2819ebec5e0a1a1638203d21\",\"license\":\"MIT\"},\"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 _gas Amount of gas 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 _gas,\\n uint256 _value\\n ) external payable onlyOwner returns (bool, bytes memory) {\\n return _target.call{ gas: _gas, 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 * @param _gas Amount of gas to send with the call.\\n *\\n * @return Boolean success value.\\n * @return Bytes data returned by the call.\\n */\\n function DELEGATECALL(\\n address _target,\\n bytes memory _data,\\n uint256 _gas\\n ) external payable onlyOwner returns (bool, bytes memory) {\\n // slither-disable-next-line controlled-delegatecall\\n return _target.delegatecall{ gas: _gas }(_data);\\n }\\n}\\n\",\"keccak256\":\"0x6f11c33999f7f3183a9c69057040141170218a44ce0e589766a327e44c8f43f1\",\"license\":\"MIT\"},\"contracts/universal/drippie/Drippie.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { AssetReceiver } from \\\"../AssetReceiver.sol\\\";\\nimport { IDripCheck } from \\\"./IDripCheck.sol\\\";\\n\\n/**\\n * @title Drippie\\n * @notice Drippie is a system for managing automated contract interactions. A specific interaction\\n * is called a \\\"drip\\\" and can be executed according to some condition (called a dripcheck)\\n * and an execution interval. Drips cannot be executed faster than the execution interval.\\n * Drips can trigger arbitrary contract calls where the calling contract is this contract\\n * address. Drips can also send ETH value, which makes them ideal for keeping addresses\\n * sufficiently funded with ETH. Drippie is designed to be connected with smart contract\\n * automation services so that drips can be executed automatically. However, Drippie is\\n * specifically designed to be separated from these services so that trust assumptions are\\n * better compartmentalized.\\n */\\ncontract Drippie is AssetReceiver {\\n /**\\n * @notice Enum representing different status options for a given drip.\\n *\\n * @custom:value NONE Drip does not exist.\\n * @custom:value ACTIVE Drip is active and can be executed.\\n * @custom:value PAUSED Drip is paused and cannot be executed until reactivated.\\n * @custom:value ARCHIVED Drip is archived and can no longer be executed or reactivated.\\n */\\n enum DripStatus {\\n NONE,\\n ACTIVE,\\n PAUSED,\\n ARCHIVED\\n }\\n\\n /**\\n * @notice Represents a drip action.\\n */\\n struct DripAction {\\n address payable target;\\n bytes data;\\n uint256 value;\\n }\\n\\n /**\\n * @notice Represents the configuration for a given drip.\\n */\\n struct DripConfig {\\n uint256 interval;\\n IDripCheck dripcheck;\\n bytes checkparams;\\n DripAction[] actions;\\n }\\n\\n /**\\n * @notice Represents the state of an active drip.\\n */\\n struct DripState {\\n DripStatus status;\\n DripConfig config;\\n uint256 last;\\n uint256 count;\\n }\\n\\n /**\\n * @notice Emitted when a new drip is created.\\n *\\n * @param nameref Indexed name parameter (hashed).\\n * @param name Unindexed name parameter (unhashed).\\n * @param config Config for the created drip.\\n */\\n event DripCreated(\\n // Emit name twice because indexed version is hashed.\\n string indexed nameref,\\n string name,\\n DripConfig config\\n );\\n\\n /**\\n * @notice Emitted when a drip status is updated.\\n *\\n * @param nameref Indexed name parameter (hashed).\\n * @param name Unindexed name parameter (unhashed).\\n * @param status New drip status.\\n */\\n event DripStatusUpdated(\\n // Emit name twice because indexed version is hashed.\\n string indexed nameref,\\n string name,\\n DripStatus status\\n );\\n\\n /**\\n * @notice Emitted when a drip is executed.\\n *\\n * @param nameref Indexed name parameter (hashed).\\n * @param name Unindexed name parameter (unhashed).\\n * @param executor Address that executed the drip.\\n * @param timestamp Time when the drip was executed.\\n */\\n event DripExecuted(\\n // Emit name twice because indexed version is hashed.\\n string indexed nameref,\\n string name,\\n address executor,\\n uint256 timestamp\\n );\\n\\n /**\\n * @notice Maps from drip names to drip states.\\n */\\n mapping(string => DripState) public drips;\\n\\n /**\\n * @param _owner Initial contract owner.\\n */\\n constructor(address _owner) AssetReceiver(_owner) {}\\n\\n /**\\n * @notice Creates a new drip with the given name and configuration. Once created, drips cannot\\n * be modified in any way (this is a security measure). If you want to update a drip,\\n * simply pause (and potentially archive) the existing drip and create a new one.\\n *\\n * @param _name Name of the drip.\\n * @param _config Configuration for the drip.\\n */\\n function create(string memory _name, DripConfig memory _config) external onlyOwner {\\n // Make sure this drip doesn't already exist. We *must* guarantee that no other function\\n // will ever set the status of a drip back to NONE after it's been created. This is why\\n // archival is a separate status.\\n require(\\n drips[_name].status == DripStatus.NONE,\\n \\\"Drippie: drip with that name already exists\\\"\\n );\\n\\n // We initialize this way because Solidity won't let us copy arrays into storage yet.\\n DripState storage state = drips[_name];\\n state.status = DripStatus.PAUSED;\\n state.config.interval = _config.interval;\\n state.config.dripcheck = _config.dripcheck;\\n state.config.checkparams = _config.checkparams;\\n\\n // Solidity doesn't let us copy arrays into storage, so we push each array one by one.\\n for (uint256 i = 0; i < _config.actions.length; i++) {\\n state.config.actions.push(_config.actions[i]);\\n }\\n\\n // Tell the world!\\n emit DripCreated(_name, _name, _config);\\n }\\n\\n /**\\n * @notice Sets the status for a given drip. The behavior of this function depends on the\\n * status that the user is trying to set. A drip can always move between ACTIVE and\\n * PAUSED, but it can never move back to NONE and once ARCHIVED, it can never move back\\n * to ACTIVE or PAUSED.\\n *\\n * @param _name Name of the drip to update.\\n * @param _status New drip status.\\n */\\n function status(string memory _name, DripStatus _status) external onlyOwner {\\n // Make sure we can never set drip status back to NONE. A simple security measure to\\n // prevent accidental overwrites if this code is ever updated down the line.\\n require(\\n _status != DripStatus.NONE,\\n \\\"Drippie: drip status can never be set back to NONE after creation\\\"\\n );\\n\\n // Make sure the drip in question actually exists. Not strictly necessary but there doesn't\\n // seem to be any clear reason why you would want to do this, and it may save some gas in\\n // the case of a front-end bug.\\n require(\\n drips[_name].status != DripStatus.NONE,\\n \\\"Drippie: drip with that name does not exist\\\"\\n );\\n\\n // Once a drip has been archived, it cannot be un-archived. This is, after all, the entire\\n // point of archiving a drip.\\n require(\\n drips[_name].status != DripStatus.ARCHIVED,\\n \\\"Drippie: drip with that name has been archived\\\"\\n );\\n\\n // Although not strictly necessary, we make sure that the status here is actually changing.\\n // This may save the client some gas if there's a front-end bug and the user accidentally\\n // tries to \\\"change\\\" the status to the same value as before.\\n require(\\n drips[_name].status != _status,\\n \\\"Drippie: cannot set drip status to same status as before\\\"\\n );\\n\\n // If the user is trying to archive this drip, make sure the drip has been paused. We do\\n // not allow users to archive active drips so that the effects of this action are more\\n // abundantly clear.\\n if (_status == DripStatus.ARCHIVED) {\\n require(\\n drips[_name].status == DripStatus.PAUSED,\\n \\\"Drippie: drip must be paused to be archived\\\"\\n );\\n }\\n\\n // If we made it here then we can safely update the status.\\n drips[_name].status = _status;\\n emit DripStatusUpdated(_name, _name, drips[_name].status);\\n }\\n\\n /**\\n * @notice Checks if a given drip is executable.\\n *\\n * @param _name Drip to check.\\n *\\n * @return True if the drip is executable, false otherwise.\\n */\\n function executable(string memory _name) public view returns (bool) {\\n DripState storage state = drips[_name];\\n\\n // Only allow active drips to be executed, an obvious security measure.\\n require(\\n state.status == DripStatus.ACTIVE,\\n \\\"Drippie: selected drip does not exist or is not currently active\\\"\\n );\\n\\n // Don't drip if the drip interval has not yet elapsed since the last time we dripped. This\\n // is a safety measure that prevents a malicious recipient from, e.g., spending all of\\n // their funds and repeatedly requesting new drips. Limits the potential impact of a\\n // compromised recipient to just a single drip interval, after which the drip can be paused\\n // by the owner address.\\n require(\\n state.last + state.config.interval <= block.timestamp,\\n \\\"Drippie: drip interval has not elapsed since last drip\\\"\\n );\\n\\n // Make sure we're allowed to execute this drip.\\n require(\\n state.config.dripcheck.check(state.config.checkparams),\\n \\\"Drippie: dripcheck failed so drip is not yet ready to be triggered\\\"\\n );\\n\\n // Alright, we're good to execute.\\n return true;\\n }\\n\\n /**\\n * @notice Triggers a drip. This function is deliberately left as a public function because the\\n * assumption being made here is that setting the drip to ACTIVE is an affirmative\\n * signal that the drip should be executable according to the drip parameters, drip\\n * check, and drip interval. Note that drip parameters are read entirely from the state\\n * and are not supplied as user input, so there should not be any way for a\\n * non-authorized user to influence the behavior of the drip.\\n *\\n * @param _name Name of the drip to trigger.\\n */\\n function drip(string memory _name) external {\\n DripState storage state = drips[_name];\\n\\n // Make sure the drip can be executed.\\n require(\\n executable(_name) == true,\\n \\\"Drippie: drip cannot be executed at this time, try again later\\\"\\n );\\n\\n // Update the last execution time for this drip before the call. Note that it's entirely\\n // possible for a drip to be executed multiple times per block or even multiple times\\n // within the same transaction (via re-entrancy) if the drip interval is set to zero. Users\\n // should set a drip interval of 1 if they'd like the drip to be executed only once per\\n // block (since this will then prevent re-entrancy).\\n state.last = block.timestamp;\\n\\n // Execute each action in the drip. We allow drips to have multiple actions because there\\n // are scenarios in which a contract must do multiple things atomically. For example, the\\n // contract may need to withdraw ETH from one account and then deposit that ETH into\\n // another account within the same transaction.\\n uint256 len = state.config.actions.length;\\n for (uint256 i = 0; i < len; i++) {\\n // Must be marked as \\\"storage\\\" because copying structs into memory is not yet supported\\n // by Solidity. Won't significantly reduce gas costs but at least makes it easier to\\n // read what the rest of this section is doing.\\n DripAction storage action = state.config.actions[i];\\n\\n // Actually execute the action. We could use ExcessivelySafeCall here but not strictly\\n // necessary (worst case, a drip gets bricked IFF the target is malicious, doubt this\\n // will ever happen in practice). Could save a marginal amount of gas to ignore the\\n // returndata.\\n // slither-disable-next-line calls-loop\\n (bool success, ) = action.target.call{ value: action.value }(action.data);\\n\\n // Generally should not happen, but could if there's a misconfiguration (e.g., passing\\n // the wrong data to the target contract), the recipient is not payable, or\\n // insufficient gas was supplied to this transaction. We revert so the drip can be\\n // fixed and triggered again later. Means we cannot emit an event to alert of the\\n // failure, but can reasonably be detected by off-chain services even without an event.\\n // Note that this forces the drip executor to supply sufficient gas to the call\\n // (assuming there is some sufficient gas limit that exists, otherwise the drip will\\n // not execute).\\n require(\\n success,\\n \\\"Drippie: drip was unsuccessful, please check your configuration for mistakes\\\"\\n );\\n }\\n\\n state.count++;\\n emit DripExecuted(_name, _name, msg.sender, block.timestamp);\\n }\\n}\\n\",\"keccak256\":\"0x6696749e45d49c5724b4d04c59fa32bfae9b2bb687ba9e78fe4cf2a148198cfc\",\"license\":\"MIT\"},\"contracts/universal/drippie/IDripCheck.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IDripCheck {\\n // DripCheck contracts that want to take parameters as inputs MUST expose a struct called\\n // Params and an event _EventForExposingParamsStructInABI(Params params). This makes it\\n // possible to easily encode parameters on the client side. Solidity does not support generics\\n // so it's not possible to do this with explicit typing.\\n\\n function check(bytes memory _params) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xbf1b9be6bbcbbbd2268023a169382c9a62a58a343420e4bc4494a9f463f86042\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b50604051620026003803806200260083398101604081905262000034916200008c565b600080546001600160a01b0319166001600160a01b03831690811782556040518392839283929091907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a350505050620000be565b6000602082840312156200009f57600080fd5b81516001600160a01b0381168114620000b757600080fd5b9392505050565b61253280620000ce6000396000f3fe6080604052600436106100e15760003560e01c8063690d83201161007f5780639456fbcc116100595780639456fbcc146102b05780639bc94d01146102d05780639e73dbea146102f0578063fc3e3eba1461030357600080fd5b8063690d83201461021e5780636f0488131461023e5780638da5cb5b1461025e57600080fd5b80634782f779116100bb5780634782f779146101845780634d7fba6e146101a45780635cef8b4a146101dd57806367148cd2146101fe57600080fd5b806313af4035146101225780634025feb21461014457806344004cc11461016457600080fd5b3661011d5760405134815233907f4103257eaac983ca79a70d28f90dfc4fa16b619bb0c17ee7cab0d4034c2796249060200160405180910390a2005b600080fd5b34801561012e57600080fd5b5061014261013d3660046119e8565b610333565b005b34801561015057600080fd5b5061014261015f366004611a0c565b61040f565b34801561017057600080fd5b5061014261017f366004611a0c565b610587565b34801561019057600080fd5b5061014261019f366004611a4d565b6106fe565b3480156101b057600080fd5b506101c46101bf366004611b95565b6107fa565b6040516101d49493929190611d60565b60405180910390f35b6101f06101eb366004611d93565b610a18565b6040516101d4929190611dec565b34801561020a57600080fd5b50610142610219366004611b95565b610af7565b34801561022a57600080fd5b506101426102393660046119e8565b610d6e565b34801561024a57600080fd5b50610142610259366004611e07565b610de2565b34801561026a57600080fd5b5060005461028b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d4565b3480156102bc57600080fd5b506101426102cb366004611fad565b6110b9565b3480156102dc57600080fd5b506101426102eb366004611fe6565b6111ba565b6101f06102fe366004612031565b61166c565b34801561030f57600080fd5b5061032361031e366004611b95565b61174f565b60405190151581526020016101d4565b60005473ffffffffffffffffffffffffffffffffffffffff16331461039f5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104765760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b1580156104ec57600080fd5b505af1158015610500573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f30b478a5e196e55886228aa87ba74a7dfeba655e0a4d7ba275eabfc22aabb7a88460405161057a91815260200190565b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105ee5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb906044016020604051808303816000875af1158015610663573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106879190612091565b508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f6b00f1c7883f053ba83e907fd1965b22fffe3c4111383e725f04638a566cdbfa8460405161057a91815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107655760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b60405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f193505050501580156107a8573d6000803e3d6000fd5b5060405181815273ffffffffffffffffffffffffffffffffffffffff83169033907f1f12aa8b6d492dd9b98e2b00b0b20830c2a7ded65afac13b60d169a034ae90bc9060200160405180910390a35050565b805160208183018101805160018083529383019483019490942093905282546040805160808101825293850180548552600286015473ffffffffffffffffffffffffffffffffffffffff169385019390935260038501805460ff9093169594939291840191610868906120b3565b80601f0160208091040260200160405190810160405280929190818152602001828054610894906120b3565b80156108e15780601f106108b6576101008083540402835291602001916108e1565b820191906000526020600020905b8154815290600101906020018083116108c457829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b82821015610a00576000848152602090819020604080516060810190915260038502909101805473ffffffffffffffffffffffffffffffffffffffff1682526001810180549293919291840191610965906120b3565b80601f0160208091040260200160405190810160405280929190818152602001828054610991906120b3565b80156109de5780601f106109b3576101008083540402835291602001916109de565b820191906000526020600020905b8154815290600101906020018083116109c157829003601f168201915b505050505081526020016002820154815250508152602001906001019061090f565b50505091525050600582015460069092015490919084565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610a835760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b8473ffffffffffffffffffffffffffffffffffffffff168385604051610aa99190612106565b6000604051808303818686f4925050503d8060008114610ae5576040519150601f19603f3d011682016040523d82523d6000602084013e610aea565b606091505b5091509150935093915050565b6000600182604051610b099190612106565b90815260200160405180910390209050610b228261174f565b1515600114610b995760405162461bcd60e51b815260206004820152603e60248201527f447269707069653a20647269702063616e6e6f7420626520657865637574656460448201527f20617420746869732074696d652c2074727920616761696e206c6174657200006064820152608401610396565b426005820155600481015460005b81811015610d00576000836001016003018281548110610bc957610bc9612122565b6000918252602082206003909102018054600282015460405192945073ffffffffffffffffffffffffffffffffffffffff90911691610c0c906001860190612151565b60006040518083038185875af1925050503d8060008114610c49576040519150601f19603f3d011682016040523d82523d6000602084013e610c4e565b606091505b5050905080610ceb5760405162461bcd60e51b815260206004820152604c60248201527f447269707069653a20647269702077617320756e7375636365737366756c2c2060448201527f706c6561736520636865636b20796f757220636f6e66696775726174696f6e2060648201527f666f72206d697374616b65730000000000000000000000000000000000000000608482015260a401610396565b50508080610cf890612214565b915050610ba7565b50600682018054906000610d1383612214565b919050555082604051610d269190612106565b60405180910390207fea21435419aad9c54a9d90e2522b6f60bd566401f36fcef661f5f5a28cc0d2c6843342604051610d619392919061224c565b60405180910390a2505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610dd55760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b610ddf81476106fe565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e495760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6000600183604051610e5b9190612106565b9081526040519081900360200190205460ff166003811115610e7f57610e7f611bd2565b14610ef25760405162461bcd60e51b815260206004820152602b60248201527f447269707069653a206472697020776974682074686174206e616d6520616c7260448201527f65616479206578697374730000000000000000000000000000000000000000006064820152608401610396565b6000600183604051610f049190612106565b908152604080516020928190038301902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600290811782558551600183015592850151928101805473ffffffffffffffffffffffffffffffffffffffff9094167fffffffffffffffffffffffff0000000000000000000000000000000000000000909416939093179092558301519091506003820190610fa890826122d6565b5060005b826060015151811015611071578160010160030183606001518281518110610fd657610fd6612122565b602090810291909101810151825460018082018555600094855293839020825160039092020180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117815591810151909282019061105190826122d6565b50604082015181600201555050808061106990612214565b915050610fac565b50826040516110809190612106565b60405180910390207f49c9c8da28762ffee6f3f2f37f8f4ebcd85afcb02e1bb496dc95cf47c96380368484604051610d619291906123d2565b60005473ffffffffffffffffffffffffffffffffffffffff1633146111205760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526111b6908390839073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611192573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061017f9190612400565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146112215760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b600081600381111561123557611235611bd2565b036112ce5760405162461bcd60e51b815260206004820152604160248201527f447269707069653a2064726970207374617475732063616e206e65766572206260448201527f6520736574206261636b20746f204e4f4e45206166746572206372656174696f60648201527f6e00000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b60006001836040516112e09190612106565b9081526040519081900360200190205460ff16600381111561130457611304611bd2565b036113775760405162461bcd60e51b815260206004820152602b60248201527f447269707069653a206472697020776974682074686174206e616d6520646f6560448201527f73206e6f742065786973740000000000000000000000000000000000000000006064820152608401610396565b60036001836040516113899190612106565b9081526040519081900360200190205460ff1660038111156113ad576113ad611bd2565b036114205760405162461bcd60e51b815260206004820152602e60248201527f447269707069653a206472697020776974682074686174206e616d652068617360448201527f206265656e2061726368697665640000000000000000000000000000000000006064820152608401610396565b80600381111561143257611432611bd2565b6001836040516114429190612106565b9081526040519081900360200190205460ff16600381111561146657611466611bd2565b036114d95760405162461bcd60e51b815260206004820152603860248201527f447269707069653a2063616e6e6f74207365742064726970207374617475732060448201527f746f2073616d6520737461747573206173206265666f726500000000000000006064820152608401610396565b60038160038111156114ed576114ed611bd2565b0361159b5760026001836040516115049190612106565b9081526040519081900360200190205460ff16600381111561152857611528611bd2565b1461159b5760405162461bcd60e51b815260206004820152602b60248201527f447269707069653a2064726970206d7573742062652070617573656420746f2060448201527f62652061726368697665640000000000000000000000000000000000000000006064820152608401610396565b806001836040516115ac9190612106565b90815260405190819003602001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360038111156115f3576115f3611bd2565b0217905550816040516116069190612106565b60405180910390207f407cb3ad05e60ec498fb39417c7a4f6b82d5ba80f82fe512a37b02c93181a2a1836001856040516116409190612106565b90815260405190819003602001812054611660929160ff90911690612419565b60405180910390a25050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff1633146116d75760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b8573ffffffffffffffffffffffffffffffffffffffff168484876040516116fe9190612106565b600060405180830381858888f193505050503d806000811461173c576040519150601f19603f3d011682016040523d82523d6000602084013e611741565b606091505b509150915094509492505050565b6000806001836040516117629190612106565b90815260405190819003602001902090506001815460ff16600381111561178b5761178b611bd2565b14611800576040805162461bcd60e51b81526020600482015260248101919091527f447269707069653a2073656c6563746564206472697020646f6573206e6f742060448201527f6578697374206f72206973206e6f742063757272656e746c79206163746976656064820152608401610396565b6001810154600582015442916118159161243b565b11156118895760405162461bcd60e51b815260206004820152603660248201527f447269707069653a206472697020696e74657276616c20686173206e6f74206560448201527f6c61707365642073696e6365206c6173742064726970000000000000000000006064820152608401610396565b60028101546040517fc64b3bb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063c64b3bb5906118e4906003850190600401612453565b602060405180830381865afa158015611901573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119259190612091565b6119bd5760405162461bcd60e51b815260206004820152604260248201527f447269707069653a2064726970636865636b206661696c656420736f2064726960448201527f70206973206e6f742079657420726561647920746f206265207472696767657260648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b50600192915050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ddf57600080fd5b6000602082840312156119fa57600080fd5b8135611a05816119c6565b9392505050565b600080600060608486031215611a2157600080fd5b8335611a2c816119c6565b92506020840135611a3c816119c6565b929592945050506040919091013590565b60008060408385031215611a6057600080fd5b8235611a6b816119c6565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715611acb57611acb611a79565b60405290565b6040516060810167ffffffffffffffff81118282101715611acb57611acb611a79565b604051601f8201601f1916810167ffffffffffffffff81118282101715611b1d57611b1d611a79565b604052919050565b600082601f830112611b3657600080fd5b813567ffffffffffffffff811115611b5057611b50611a79565b611b636020601f19601f84011601611af4565b818152846020838601011115611b7857600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215611ba757600080fd5b813567ffffffffffffffff811115611bbe57600080fd5b611bca84828501611b25565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110611c38577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b60005b83811015611c57578181015183820152602001611c3f565b83811115611c66576000848401525b50505050565b60008151808452611c84816020860160208601611c3c565b601f01601f19169290920160200192915050565b80518252600060208083015173ffffffffffffffffffffffffffffffffffffffff808216838701526040915081850151608083880152611cdb6080880182611c6c565b9050606080870151888303828a01528281518085528785019150878160051b860101888401935060005b82811015611d5057601f1987830301845284518881511683528a810151878c850152611d3388850182611c6c565b918b0151938b0193909352948a0194938a01939150600101611d05565b509b9a5050505050505050505050565b611d6a8186611c01565b608060208201526000611d806080830186611c98565b6040830194909452506060015292915050565b600080600060608486031215611da857600080fd5b8335611db3816119c6565b9250602084013567ffffffffffffffff811115611dcf57600080fd5b611ddb86828701611b25565b925050604084013590509250925092565b8215158152604060208201526000611bca6040830184611c6c565b60008060408385031215611e1a57600080fd5b823567ffffffffffffffff80821115611e3257600080fd5b611e3e86838701611b25565b9350602091508185013581811115611e5557600080fd5b850160808188031215611e6757600080fd5b611e6f611aa8565b8135815283820135611e80816119c6565b81850152604082013583811115611e9657600080fd5b611ea289828501611b25565b604083015250606082013583811115611eba57600080fd5b80830192505087601f830112611ecf57600080fd5b813583811115611ee157611ee1611a79565b8060051b611ef0868201611af4565b918252838101860191868101908b841115611f0a57600080fd5b87860192505b83831015611f9757823587811115611f285760008081fd5b86016060818e03601f19011215611f3f5760008081fd5b611f47611ad1565b89820135611f54816119c6565b8152604082013589811115611f695760008081fd5b611f778f8c83860101611b25565b828c01525060609190910135604082015282529187019190870190611f10565b6060850152509699919850909650505050505050565b60008060408385031215611fc057600080fd5b8235611fcb816119c6565b91506020830135611fdb816119c6565b809150509250929050565b60008060408385031215611ff957600080fd5b823567ffffffffffffffff81111561201057600080fd5b61201c85828601611b25565b925050602083013560048110611fdb57600080fd5b6000806000806080858703121561204757600080fd5b8435612052816119c6565b9350602085013567ffffffffffffffff81111561206e57600080fd5b61207a87828801611b25565b949794965050505060408301359260600135919050565b6000602082840312156120a357600080fd5b81518015158114611a0557600080fd5b600181811c908216806120c757607f821691505b602082108103612100577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008251612118818460208701611c3c565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080835461215f816120b3565b6001828116801561217757600181146121aa576121d9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841687528215158302870194506121d9565b8760005260208060002060005b858110156121d05781548a8201529084019082016121b7565b50505082870194505b50929695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612245576122456121e5565b5060010190565b60608152600061225f6060830186611c6c565b73ffffffffffffffffffffffffffffffffffffffff9490941660208301525060400152919050565b601f8211156122d157600081815260208120601f850160051c810160208610156122ae5750805b601f850160051c820191505b818110156122cd578281556001016122ba565b5050505b505050565b815167ffffffffffffffff8111156122f0576122f0611a79565b612304816122fe84546120b3565b84612287565b602080601f83116001811461235757600084156123215750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556122cd565b600085815260208120601f198616915b8281101561238657888601518255948401946001909101908401612367565b50858210156123c257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b6040815260006123e56040830185611c6c565b82810360208401526123f78185611c98565b95945050505050565b60006020828403121561241257600080fd5b5051919050565b60408152600061242c6040830185611c6c565b9050611a056020830184611c01565b6000821982111561244e5761244e6121e5565b500190565b6000602080835260008454612467816120b3565b8084870152604060018084166000811461248857600181146124c0576124ee565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506124ee565b896000528660002060005b858110156124e65781548b82018601529083019088016124cb565b8a0184019650505b50939897505050505050505056fea26469706673582212209e2c642d826f29e188c7d7b6e9595445cf633c5a5dd84422c15db472d859adff64736f6c634300080f0033", - "deployedBytecode": "0x6080604052600436106100e15760003560e01c8063690d83201161007f5780639456fbcc116100595780639456fbcc146102b05780639bc94d01146102d05780639e73dbea146102f0578063fc3e3eba1461030357600080fd5b8063690d83201461021e5780636f0488131461023e5780638da5cb5b1461025e57600080fd5b80634782f779116100bb5780634782f779146101845780634d7fba6e146101a45780635cef8b4a146101dd57806367148cd2146101fe57600080fd5b806313af4035146101225780634025feb21461014457806344004cc11461016457600080fd5b3661011d5760405134815233907f4103257eaac983ca79a70d28f90dfc4fa16b619bb0c17ee7cab0d4034c2796249060200160405180910390a2005b600080fd5b34801561012e57600080fd5b5061014261013d3660046119e8565b610333565b005b34801561015057600080fd5b5061014261015f366004611a0c565b61040f565b34801561017057600080fd5b5061014261017f366004611a0c565b610587565b34801561019057600080fd5b5061014261019f366004611a4d565b6106fe565b3480156101b057600080fd5b506101c46101bf366004611b95565b6107fa565b6040516101d49493929190611d60565b60405180910390f35b6101f06101eb366004611d93565b610a18565b6040516101d4929190611dec565b34801561020a57600080fd5b50610142610219366004611b95565b610af7565b34801561022a57600080fd5b506101426102393660046119e8565b610d6e565b34801561024a57600080fd5b50610142610259366004611e07565b610de2565b34801561026a57600080fd5b5060005461028b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d4565b3480156102bc57600080fd5b506101426102cb366004611fad565b6110b9565b3480156102dc57600080fd5b506101426102eb366004611fe6565b6111ba565b6101f06102fe366004612031565b61166c565b34801561030f57600080fd5b5061032361031e366004611b95565b61174f565b60405190151581526020016101d4565b60005473ffffffffffffffffffffffffffffffffffffffff16331461039f5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104765760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b1580156104ec57600080fd5b505af1158015610500573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f30b478a5e196e55886228aa87ba74a7dfeba655e0a4d7ba275eabfc22aabb7a88460405161057a91815260200190565b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105ee5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb906044016020604051808303816000875af1158015610663573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106879190612091565b508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f6b00f1c7883f053ba83e907fd1965b22fffe3c4111383e725f04638a566cdbfa8460405161057a91815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107655760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b60405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f193505050501580156107a8573d6000803e3d6000fd5b5060405181815273ffffffffffffffffffffffffffffffffffffffff83169033907f1f12aa8b6d492dd9b98e2b00b0b20830c2a7ded65afac13b60d169a034ae90bc9060200160405180910390a35050565b805160208183018101805160018083529383019483019490942093905282546040805160808101825293850180548552600286015473ffffffffffffffffffffffffffffffffffffffff169385019390935260038501805460ff9093169594939291840191610868906120b3565b80601f0160208091040260200160405190810160405280929190818152602001828054610894906120b3565b80156108e15780601f106108b6576101008083540402835291602001916108e1565b820191906000526020600020905b8154815290600101906020018083116108c457829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b82821015610a00576000848152602090819020604080516060810190915260038502909101805473ffffffffffffffffffffffffffffffffffffffff1682526001810180549293919291840191610965906120b3565b80601f0160208091040260200160405190810160405280929190818152602001828054610991906120b3565b80156109de5780601f106109b3576101008083540402835291602001916109de565b820191906000526020600020905b8154815290600101906020018083116109c157829003601f168201915b505050505081526020016002820154815250508152602001906001019061090f565b50505091525050600582015460069092015490919084565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610a835760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b8473ffffffffffffffffffffffffffffffffffffffff168385604051610aa99190612106565b6000604051808303818686f4925050503d8060008114610ae5576040519150601f19603f3d011682016040523d82523d6000602084013e610aea565b606091505b5091509150935093915050565b6000600182604051610b099190612106565b90815260200160405180910390209050610b228261174f565b1515600114610b995760405162461bcd60e51b815260206004820152603e60248201527f447269707069653a20647269702063616e6e6f7420626520657865637574656460448201527f20617420746869732074696d652c2074727920616761696e206c6174657200006064820152608401610396565b426005820155600481015460005b81811015610d00576000836001016003018281548110610bc957610bc9612122565b6000918252602082206003909102018054600282015460405192945073ffffffffffffffffffffffffffffffffffffffff90911691610c0c906001860190612151565b60006040518083038185875af1925050503d8060008114610c49576040519150601f19603f3d011682016040523d82523d6000602084013e610c4e565b606091505b5050905080610ceb5760405162461bcd60e51b815260206004820152604c60248201527f447269707069653a20647269702077617320756e7375636365737366756c2c2060448201527f706c6561736520636865636b20796f757220636f6e66696775726174696f6e2060648201527f666f72206d697374616b65730000000000000000000000000000000000000000608482015260a401610396565b50508080610cf890612214565b915050610ba7565b50600682018054906000610d1383612214565b919050555082604051610d269190612106565b60405180910390207fea21435419aad9c54a9d90e2522b6f60bd566401f36fcef661f5f5a28cc0d2c6843342604051610d619392919061224c565b60405180910390a2505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610dd55760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b610ddf81476106fe565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e495760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6000600183604051610e5b9190612106565b9081526040519081900360200190205460ff166003811115610e7f57610e7f611bd2565b14610ef25760405162461bcd60e51b815260206004820152602b60248201527f447269707069653a206472697020776974682074686174206e616d6520616c7260448201527f65616479206578697374730000000000000000000000000000000000000000006064820152608401610396565b6000600183604051610f049190612106565b908152604080516020928190038301902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600290811782558551600183015592850151928101805473ffffffffffffffffffffffffffffffffffffffff9094167fffffffffffffffffffffffff0000000000000000000000000000000000000000909416939093179092558301519091506003820190610fa890826122d6565b5060005b826060015151811015611071578160010160030183606001518281518110610fd657610fd6612122565b602090810291909101810151825460018082018555600094855293839020825160039092020180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117815591810151909282019061105190826122d6565b50604082015181600201555050808061106990612214565b915050610fac565b50826040516110809190612106565b60405180910390207f49c9c8da28762ffee6f3f2f37f8f4ebcd85afcb02e1bb496dc95cf47c96380368484604051610d619291906123d2565b60005473ffffffffffffffffffffffffffffffffffffffff1633146111205760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526111b6908390839073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611192573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061017f9190612400565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146112215760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b600081600381111561123557611235611bd2565b036112ce5760405162461bcd60e51b815260206004820152604160248201527f447269707069653a2064726970207374617475732063616e206e65766572206260448201527f6520736574206261636b20746f204e4f4e45206166746572206372656174696f60648201527f6e00000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b60006001836040516112e09190612106565b9081526040519081900360200190205460ff16600381111561130457611304611bd2565b036113775760405162461bcd60e51b815260206004820152602b60248201527f447269707069653a206472697020776974682074686174206e616d6520646f6560448201527f73206e6f742065786973740000000000000000000000000000000000000000006064820152608401610396565b60036001836040516113899190612106565b9081526040519081900360200190205460ff1660038111156113ad576113ad611bd2565b036114205760405162461bcd60e51b815260206004820152602e60248201527f447269707069653a206472697020776974682074686174206e616d652068617360448201527f206265656e2061726368697665640000000000000000000000000000000000006064820152608401610396565b80600381111561143257611432611bd2565b6001836040516114429190612106565b9081526040519081900360200190205460ff16600381111561146657611466611bd2565b036114d95760405162461bcd60e51b815260206004820152603860248201527f447269707069653a2063616e6e6f74207365742064726970207374617475732060448201527f746f2073616d6520737461747573206173206265666f726500000000000000006064820152608401610396565b60038160038111156114ed576114ed611bd2565b0361159b5760026001836040516115049190612106565b9081526040519081900360200190205460ff16600381111561152857611528611bd2565b1461159b5760405162461bcd60e51b815260206004820152602b60248201527f447269707069653a2064726970206d7573742062652070617573656420746f2060448201527f62652061726368697665640000000000000000000000000000000000000000006064820152608401610396565b806001836040516115ac9190612106565b90815260405190819003602001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360038111156115f3576115f3611bd2565b0217905550816040516116069190612106565b60405180910390207f407cb3ad05e60ec498fb39417c7a4f6b82d5ba80f82fe512a37b02c93181a2a1836001856040516116409190612106565b90815260405190819003602001812054611660929160ff90911690612419565b60405180910390a25050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff1633146116d75760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610396565b8573ffffffffffffffffffffffffffffffffffffffff168484876040516116fe9190612106565b600060405180830381858888f193505050503d806000811461173c576040519150601f19603f3d011682016040523d82523d6000602084013e611741565b606091505b509150915094509492505050565b6000806001836040516117629190612106565b90815260405190819003602001902090506001815460ff16600381111561178b5761178b611bd2565b14611800576040805162461bcd60e51b81526020600482015260248101919091527f447269707069653a2073656c6563746564206472697020646f6573206e6f742060448201527f6578697374206f72206973206e6f742063757272656e746c79206163746976656064820152608401610396565b6001810154600582015442916118159161243b565b11156118895760405162461bcd60e51b815260206004820152603660248201527f447269707069653a206472697020696e74657276616c20686173206e6f74206560448201527f6c61707365642073696e6365206c6173742064726970000000000000000000006064820152608401610396565b60028101546040517fc64b3bb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063c64b3bb5906118e4906003850190600401612453565b602060405180830381865afa158015611901573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119259190612091565b6119bd5760405162461bcd60e51b815260206004820152604260248201527f447269707069653a2064726970636865636b206661696c656420736f2064726960448201527f70206973206e6f742079657420726561647920746f206265207472696767657260648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a401610396565b50600192915050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ddf57600080fd5b6000602082840312156119fa57600080fd5b8135611a05816119c6565b9392505050565b600080600060608486031215611a2157600080fd5b8335611a2c816119c6565b92506020840135611a3c816119c6565b929592945050506040919091013590565b60008060408385031215611a6057600080fd5b8235611a6b816119c6565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715611acb57611acb611a79565b60405290565b6040516060810167ffffffffffffffff81118282101715611acb57611acb611a79565b604051601f8201601f1916810167ffffffffffffffff81118282101715611b1d57611b1d611a79565b604052919050565b600082601f830112611b3657600080fd5b813567ffffffffffffffff811115611b5057611b50611a79565b611b636020601f19601f84011601611af4565b818152846020838601011115611b7857600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215611ba757600080fd5b813567ffffffffffffffff811115611bbe57600080fd5b611bca84828501611b25565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60048110611c38577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b60005b83811015611c57578181015183820152602001611c3f565b83811115611c66576000848401525b50505050565b60008151808452611c84816020860160208601611c3c565b601f01601f19169290920160200192915050565b80518252600060208083015173ffffffffffffffffffffffffffffffffffffffff808216838701526040915081850151608083880152611cdb6080880182611c6c565b9050606080870151888303828a01528281518085528785019150878160051b860101888401935060005b82811015611d5057601f1987830301845284518881511683528a810151878c850152611d3388850182611c6c565b918b0151938b0193909352948a0194938a01939150600101611d05565b509b9a5050505050505050505050565b611d6a8186611c01565b608060208201526000611d806080830186611c98565b6040830194909452506060015292915050565b600080600060608486031215611da857600080fd5b8335611db3816119c6565b9250602084013567ffffffffffffffff811115611dcf57600080fd5b611ddb86828701611b25565b925050604084013590509250925092565b8215158152604060208201526000611bca6040830184611c6c565b60008060408385031215611e1a57600080fd5b823567ffffffffffffffff80821115611e3257600080fd5b611e3e86838701611b25565b9350602091508185013581811115611e5557600080fd5b850160808188031215611e6757600080fd5b611e6f611aa8565b8135815283820135611e80816119c6565b81850152604082013583811115611e9657600080fd5b611ea289828501611b25565b604083015250606082013583811115611eba57600080fd5b80830192505087601f830112611ecf57600080fd5b813583811115611ee157611ee1611a79565b8060051b611ef0868201611af4565b918252838101860191868101908b841115611f0a57600080fd5b87860192505b83831015611f9757823587811115611f285760008081fd5b86016060818e03601f19011215611f3f5760008081fd5b611f47611ad1565b89820135611f54816119c6565b8152604082013589811115611f695760008081fd5b611f778f8c83860101611b25565b828c01525060609190910135604082015282529187019190870190611f10565b6060850152509699919850909650505050505050565b60008060408385031215611fc057600080fd5b8235611fcb816119c6565b91506020830135611fdb816119c6565b809150509250929050565b60008060408385031215611ff957600080fd5b823567ffffffffffffffff81111561201057600080fd5b61201c85828601611b25565b925050602083013560048110611fdb57600080fd5b6000806000806080858703121561204757600080fd5b8435612052816119c6565b9350602085013567ffffffffffffffff81111561206e57600080fd5b61207a87828801611b25565b949794965050505060408301359260600135919050565b6000602082840312156120a357600080fd5b81518015158114611a0557600080fd5b600181811c908216806120c757607f821691505b602082108103612100577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60008251612118818460208701611c3c565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080835461215f816120b3565b6001828116801561217757600181146121aa576121d9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841687528215158302870194506121d9565b8760005260208060002060005b858110156121d05781548a8201529084019082016121b7565b50505082870194505b50929695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612245576122456121e5565b5060010190565b60608152600061225f6060830186611c6c565b73ffffffffffffffffffffffffffffffffffffffff9490941660208301525060400152919050565b601f8211156122d157600081815260208120601f850160051c810160208610156122ae5750805b601f850160051c820191505b818110156122cd578281556001016122ba565b5050505b505050565b815167ffffffffffffffff8111156122f0576122f0611a79565b612304816122fe84546120b3565b84612287565b602080601f83116001811461235757600084156123215750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556122cd565b600085815260208120601f198616915b8281101561238657888601518255948401946001909101908401612367565b50858210156123c257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b6040815260006123e56040830185611c6c565b82810360208401526123f78185611c98565b95945050505050565b60006020828403121561241257600080fd5b5051919050565b60408152600061242c6040830185611c6c565b9050611a056020830184611c01565b6000821982111561244e5761244e6121e5565b500190565b6000602080835260008454612467816120b3565b8084870152604060018084166000811461248857600181146124c0576124ee565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506124ee565b896000528660002060005b858110156124e65781548b82018601529083019088016124cb565b8a0184019650505b50939897505050505050505056fea26469706673582212209e2c642d826f29e188c7d7b6e9595445cf633c5a5dd84422c15db472d859adff64736f6c634300080f0033", - "devdoc": { - "events": { - "DripCreated(string,string,(uint256,address,bytes,(address,bytes,uint256)[]))": { - "params": { - "config": "Config for the created drip.", - "name": "Unindexed name parameter (unhashed).", - "nameref": "Indexed name parameter (hashed)." - } - }, - "DripExecuted(string,string,address,uint256)": { - "params": { - "executor": "Address that executed the drip.", - "name": "Unindexed name parameter (unhashed).", - "nameref": "Indexed name parameter (hashed).", - "timestamp": "Time when the drip was executed." - } - }, - "DripStatusUpdated(string,string,uint8)": { - "params": { - "name": "Unindexed name parameter (unhashed).", - "nameref": "Indexed name parameter (hashed).", - "status": "New drip status." - } - } - }, - "kind": "dev", - "methods": { - "CALL(address,bytes,uint256,uint256)": { - "params": { - "_data": "Data to send with the call.", - "_gas": "Amount of gas to send with the call.", - "_target": "Address to call.", - "_value": "ETH value to send with the call." - }, - "returns": { - "_0": "Boolean success value.", - "_1": "Bytes data returned by the call." - } - }, - "DELEGATECALL(address,bytes,uint256)": { - "params": { - "_data": "Data to send with the call.", - "_gas": "Amount of gas to send with the call.", - "_target": "Address to call." - }, - "returns": { - "_0": "Boolean success value.", - "_1": "Bytes data returned by the call." - } - }, - "constructor": { - "params": { - "_owner": "Initial contract owner." - } - }, - "create(string,(uint256,address,bytes,(address,bytes,uint256)[]))": { - "params": { - "_config": "Configuration for the drip.", - "_name": "Name of the drip." - } - }, - "drip(string)": { - "params": { - "_name": "Name of the drip to trigger." - } - }, - "executable(string)": { - "params": { - "_name": "Drip to check." - }, - "returns": { - "_0": "True if the drip is executable, false otherwise." - } - }, - "status(string,uint8)": { - "params": { - "_name": "Name of the drip to update.", - "_status": "New drip status." - } - }, - "withdrawERC20(address,address)": { - "params": { - "_asset": "ERC20 token to withdraw.", - "_to": "Address to receive the ERC20 balance." - } - }, - "withdrawERC20(address,address,uint256)": { - "params": { - "_amount": "Amount of ERC20 to withdraw.", - "_asset": "ERC20 token to withdraw.", - "_to": "Address to receive the ERC20 balance." - } - }, - "withdrawERC721(address,address,uint256)": { - "params": { - "_asset": "ERC721 token to withdraw.", - "_id": "Token ID of the ERC721 token to withdraw.", - "_to": "Address to receive the ERC721 token." - } - }, - "withdrawETH(address)": { - "params": { - "_to": "Address to receive the ETH balance." - } - }, - "withdrawETH(address,uint256)": { - "params": { - "_amount": "Amount of ETH to withdraw.", - "_to": "Address to receive the ETH balance." - } - } - }, - "title": "Drippie", - "version": 1 - }, - "userdoc": { - "events": { - "DripCreated(string,string,(uint256,address,bytes,(address,bytes,uint256)[]))": { - "notice": "Emitted when a new drip is created." - }, - "DripExecuted(string,string,address,uint256)": { - "notice": "Emitted when a drip is executed." - }, - "DripStatusUpdated(string,string,uint8)": { - "notice": "Emitted when a drip status is updated." - }, - "ReceivedETH(address,uint256)": { - "notice": "Emitted when ETH is received by this address." - }, - "WithdrewERC20(address,address,address,uint256)": { - "notice": "Emitted when ERC20 tokens are withdrawn from this address." - }, - "WithdrewERC721(address,address,address,uint256)": { - "notice": "Emitted when ERC20 tokens are withdrawn from this address." - }, - "WithdrewETH(address,address,uint256)": { - "notice": "Emitted when ETH is withdrawn from this address." - } - }, - "kind": "user", - "methods": { - "CALL(address,bytes,uint256,uint256)": { - "notice": "Sends a CALL to a target address." - }, - "DELEGATECALL(address,bytes,uint256)": { - "notice": "Sends a DELEGATECALL to a target address." - }, - "create(string,(uint256,address,bytes,(address,bytes,uint256)[]))": { - "notice": "Creates a new drip with the given name and configuration. Once created, drips cannot be modified in any way (this is a security measure). If you want to update a drip, simply pause (and potentially archive) the existing drip and create a new one." - }, - "drip(string)": { - "notice": "Triggers a drip. This function is deliberately left as a public function because the assumption being made here is that setting the drip to ACTIVE is an affirmative signal that the drip should be executable according to the drip parameters, drip check, and drip interval. Note that drip parameters are read entirely from the state and are not supplied as user input, so there should not be any way for a non-authorized user to influence the behavior of the drip." - }, - "drips(string)": { - "notice": "Maps from drip names to drip states." - }, - "executable(string)": { - "notice": "Checks if a given drip is executable." - }, - "status(string,uint8)": { - "notice": "Sets the status for a given drip. The behavior of this function depends on the status that the user is trying to set. A drip can always move between ACTIVE and PAUSED, but it can never move back to NONE and once ARCHIVED, it can never move back to ACTIVE or PAUSED." - }, - "withdrawERC20(address,address)": { - "notice": "Withdraws full ERC20 balance to the recipient." - }, - "withdrawERC20(address,address,uint256)": { - "notice": "Withdraws partial ERC20 balance to the recipient." - }, - "withdrawERC721(address,address,uint256)": { - "notice": "Withdraws ERC721 token to the recipient." - }, - "withdrawETH(address)": { - "notice": "Withdraws full ETH balance to the recipient." - }, - "withdrawETH(address,uint256)": { - "notice": "Withdraws partial ETH balance to the recipient." - } - }, - "notice": "Drippie is a system for managing automated contract interactions. A specific interaction is called a \"drip\" and can be executed according to some condition (called a dripcheck) and an execution interval. Drips cannot be executed faster than the execution interval. Drips can trigger arbitrary contract calls where the calling contract is this contract address. Drips can also send ETH value, which makes them ideal for keeping addresses sufficiently funded with ETH. Drippie is designed to be connected with smart contract automation services so that drips can be executed automatically. However, Drippie is specifically designed to be separated from these services so that trust assumptions are better compartmentalized.", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 4096, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "owner", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 6733, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "drips", - "offset": 0, - "slot": "1", - "type": "t_mapping(t_string_memory_ptr,t_struct(DripState)6696_storage)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_address_payable": { - "encoding": "inplace", - "label": "address payable", - "numberOfBytes": "20" - }, - "t_array(t_struct(DripAction)6673_storage)dyn_storage": { - "base": "t_struct(DripAction)6673_storage", - "encoding": "dynamic_array", - "label": "struct Drippie.DripAction[]", - "numberOfBytes": "32" - }, - "t_bytes_storage": { - "encoding": "bytes", - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(IDripCheck)7077": { - "encoding": "inplace", - "label": "contract IDripCheck", - "numberOfBytes": "20" - }, - "t_enum(DripStatus)6666": { - "encoding": "inplace", - "label": "enum Drippie.DripStatus", - "numberOfBytes": "1" - }, - "t_mapping(t_string_memory_ptr,t_struct(DripState)6696_storage)": { - "encoding": "mapping", - "key": "t_string_memory_ptr", - "label": "mapping(string => struct Drippie.DripState)", - "numberOfBytes": "32", - "value": "t_struct(DripState)6696_storage" - }, - "t_string_memory_ptr": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_struct(DripAction)6673_storage": { - "encoding": "inplace", - "label": "struct Drippie.DripAction", - "members": [ - { - "astId": 6668, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "target", - "offset": 0, - "slot": "0", - "type": "t_address_payable" - }, - { - "astId": 6670, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "data", - "offset": 0, - "slot": "1", - "type": "t_bytes_storage" - }, - { - "astId": 6672, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "value", - "offset": 0, - "slot": "2", - "type": "t_uint256" - } - ], - "numberOfBytes": "96" - }, - "t_struct(DripConfig)6685_storage": { - "encoding": "inplace", - "label": "struct Drippie.DripConfig", - "members": [ - { - "astId": 6675, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "interval", - "offset": 0, - "slot": "0", - "type": "t_uint256" - }, - { - "astId": 6678, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "dripcheck", - "offset": 0, - "slot": "1", - "type": "t_contract(IDripCheck)7077" - }, - { - "astId": 6680, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "checkparams", - "offset": 0, - "slot": "2", - "type": "t_bytes_storage" - }, - { - "astId": 6684, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "actions", - "offset": 0, - "slot": "3", - "type": "t_array(t_struct(DripAction)6673_storage)dyn_storage" - } - ], - "numberOfBytes": "128" - }, - "t_struct(DripState)6696_storage": { - "encoding": "inplace", - "label": "struct Drippie.DripState", - "members": [ - { - "astId": 6688, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "status", - "offset": 0, - "slot": "0", - "type": "t_enum(DripStatus)6666" - }, - { - "astId": 6691, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "config", - "offset": 0, - "slot": "1", - "type": "t_struct(DripConfig)6685_storage" - }, - { - "astId": 6693, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "last", - "offset": 0, - "slot": "5", - "type": "t_uint256" - }, - { - "astId": 6695, - "contract": "contracts/universal/drippie/Drippie.sol:Drippie", - "label": "count", - "offset": 0, - "slot": "6", - "type": "t_uint256" - } - ], - "numberOfBytes": "224" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/EAS.json b/packages/contracts-bedrock/deployments/optimism-goerli/EAS.json deleted file mode 100644 index a43fa6be5380..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/EAS.json +++ /dev/null @@ -1,1483 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AccessDenied", - "type": "error" - }, - { - "inputs": [], - "name": "AlreadyRevoked", - "type": "error" - }, - { - "inputs": [], - "name": "AlreadyRevokedOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "AlreadyTimestamped", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientValue", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidAttestation", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidAttestations", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidExpirationTime", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidOffset", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRegistry", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRevocation", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRevocations", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSchema", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSignature", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidVerifier", - "type": "error" - }, - { - "inputs": [], - "name": "Irrevocable", - "type": "error" - }, - { - "inputs": [], - "name": "NotFound", - "type": "error" - }, - { - "inputs": [], - "name": "NotPayable", - "type": "error" - }, - { - "inputs": [], - "name": "WrongSchema", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "attester", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - } - ], - "name": "Attested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "attester", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - } - ], - "name": "Revoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "revoker", - "type": "address" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - } - ], - "name": "RevokedOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - } - ], - "name": "Timestamped", - "type": "event" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint64", - "name": "expirationTime", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "refUID", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct AttestationRequestData", - "name": "data", - "type": "tuple" - } - ], - "internalType": "struct AttestationRequest", - "name": "request", - "type": "tuple" - } - ], - "name": "attest", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint64", - "name": "expirationTime", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "refUID", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct AttestationRequestData", - "name": "data", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "internalType": "struct EIP712Signature", - "name": "signature", - "type": "tuple" - }, - { - "internalType": "address", - "name": "attester", - "type": "address" - } - ], - "internalType": "struct DelegatedAttestationRequest", - "name": "delegatedRequest", - "type": "tuple" - } - ], - "name": "attestByDelegation", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "getAttestTypeHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - } - ], - "name": "getAttestation", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "time", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "expirationTime", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revocationTime", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "refUID", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "attester", - "type": "address" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Attestation", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getDomainSeparator", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getName", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "getNonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "revoker", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - } - ], - "name": "getRevokeOffchain", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRevokeTypeHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getSchemaRegistry", - "outputs": [ - { - "internalType": "contract ISchemaRegistry", - "name": "", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - } - ], - "name": "getTimestamp", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - } - ], - "name": "isAttestationValid", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint64", - "name": "expirationTime", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "refUID", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct AttestationRequestData[]", - "name": "data", - "type": "tuple[]" - } - ], - "internalType": "struct MultiAttestationRequest[]", - "name": "multiRequests", - "type": "tuple[]" - } - ], - "name": "multiAttest", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint64", - "name": "expirationTime", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "refUID", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct AttestationRequestData[]", - "name": "data", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "internalType": "struct EIP712Signature[]", - "name": "signatures", - "type": "tuple[]" - }, - { - "internalType": "address", - "name": "attester", - "type": "address" - } - ], - "internalType": "struct MultiDelegatedAttestationRequest[]", - "name": "multiDelegatedRequests", - "type": "tuple[]" - } - ], - "name": "multiAttestByDelegation", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct RevocationRequestData[]", - "name": "data", - "type": "tuple[]" - } - ], - "internalType": "struct MultiRevocationRequest[]", - "name": "multiRequests", - "type": "tuple[]" - } - ], - "name": "multiRevoke", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct RevocationRequestData[]", - "name": "data", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "internalType": "struct EIP712Signature[]", - "name": "signatures", - "type": "tuple[]" - }, - { - "internalType": "address", - "name": "revoker", - "type": "address" - } - ], - "internalType": "struct MultiDelegatedRevocationRequest[]", - "name": "multiDelegatedRequests", - "type": "tuple[]" - } - ], - "name": "multiRevokeByDelegation", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "data", - "type": "bytes32[]" - } - ], - "name": "multiRevokeOffchain", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "data", - "type": "bytes32[]" - } - ], - "name": "multiTimestamp", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct RevocationRequestData", - "name": "data", - "type": "tuple" - } - ], - "internalType": "struct RevocationRequest", - "name": "request", - "type": "tuple" - } - ], - "name": "revoke", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct RevocationRequestData", - "name": "data", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "internalType": "struct EIP712Signature", - "name": "signature", - "type": "tuple" - }, - { - "internalType": "address", - "name": "revoker", - "type": "address" - } - ], - "internalType": "struct DelegatedRevocationRequest", - "name": "delegatedRequest", - "type": "tuple" - } - ], - "name": "revokeByDelegation", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - } - ], - "name": "revokeOffchain", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - } - ], - "name": "timestamp", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "address": "0x5A633F1cc84B03F7588486CF2F386c102061E6e1", - "args": [], - "bytecode": "0x6101c06040523480156200001257600080fd5b50604080518082018252600381526245415360e81b6020808301918252835180850190945260058452640312e302e360dc1b9084019081526001608052600060a081905260c052825190912083519091206101408290526101608190524661010052919291839183917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ec8184846040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b60e0523061012052610180525050505060208201516101a052506200010e9050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516144df6200018a60003960006105410152600061265b015260006126aa01526000612685015260006125de0152600061260801526000612632015260006108730152600061084a0152600061082101526144df6000f3fe6080604052600436106101805760003560e01c8063b469318d116100d6578063e45d03f91161007f578063ed24911d11610059578063ed24911d1461049e578063f10b5cc8146104b3578063f17325e7146104e257600080fd5b8063e45d03f914610458578063e57a6b1b1461046b578063e71ff3651461047e57600080fd5b8063d45c4435116100b0578063d45c4435146103cf578063e13458fc14610406578063e30bb5631461041957600080fd5b8063b469318d14610322578063b83010d31461037c578063cf190f34146103af57600080fd5b8063469262671161013857806354fd4d501161011257806354fd4d50146102cd578063831e05a1146102e2578063a3112a64146102f557600080fd5b806346926267146102855780634cb7e9e51461029a5780634d003070146102ad57600080fd5b806317d7de7c1161016957806317d7de7c146102005780632d0335ab1461022257806344adc90e1461026557600080fd5b806312b11a171461018557806313893f61146101c7575b600080fd5b34801561019157600080fd5b507fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de615b6040519081526020015b60405180910390f35b3480156101d357600080fd5b506101e76101e23660046133ee565b6104f5565b60405167ffffffffffffffff90911681526020016101be565b34801561020c57600080fd5b5061021561053a565b6040516101be919061349e565b34801561022e57600080fd5b506101b461023d3660046134ea565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6102786102733660046133ee565b61056a565b6040516101be9190613507565b61029861029336600461354b565b6106a1565b005b6102986102a83660046133ee565b610725565b3480156102b957600080fd5b506101e76102c8366004613563565b61080d565b3480156102d957600080fd5b5061021561081a565b6102786102f03660046133ee565b6108bd565b34801561030157600080fd5b50610315610310366004613563565b610b0e565b6040516101be9190613663565b34801561032e57600080fd5b506101e761033d366004613676565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152603460209081526040808320938352929052205467ffffffffffffffff1690565b34801561038857600080fd5b507fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a996506101b4565b3480156103bb57600080fd5b506101e76103ca366004613563565b610cd1565b3480156103db57600080fd5b506101e76103ea366004613563565b60009081526033602052604090205467ffffffffffffffff1690565b6101b46104143660046136a2565b610cdf565b34801561042557600080fd5b50610448610434366004613563565b600090815260326020526040902054151590565b60405190151581526020016101be565b6102986104663660046133ee565b610de2565b6102986104793660046136dd565b610f5d565b34801561048a57600080fd5b506101e76104993660046133ee565b611002565b3480156104aa57600080fd5b506101b461103a565b3480156104bf57600080fd5b5060405173420000000000000000000000000000000000002081526020016101be565b6101b46104f03660046136ef565b611044565b60004282825b8181101561052e57610526338787848181106105195761051961372a565b9050602002013585611102565b6001016104fb565b50909150505b92915050565b60606105657f0000000000000000000000000000000000000000000000000000000000000000611201565b905090565b606060008267ffffffffffffffff81111561058757610587613759565b6040519080825280602002602001820160405280156105ba57816020015b60608152602001906001900390816105a55790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86018114368888848181106106025761060261372a565b90506020028101906106149190613788565b9050600061063b823561062a60208501856137c6565b61063391613a3f565b33888761138f565b805190915061064a9086613ae2565b945080602001518785815181106106635761066361372a565b6020026020010181905250806020015151860195505050506106858160010190565b90506105c2565b506106978383611aa1565b9695505050505050565b604080516001808252818301909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816106b85790505090506106f336839003830160208401613b44565b816000815181106107065761070661372a565b602090810291909101015261072082358233346001611b6e565b505050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83018114368585848181106107695761076961372a565b905060200281019061077b9190613788565b90506107e8813561078f6020840184613b60565b808060200260200160405190810160405280939291908181526020016000905b828210156107db576107cc60408302860136819003810190613b44565b815260200190600101906107af565b5050505050338786611b6e565b6107f29085613ae2565b935050506108008160010190565b9050610729565b50505050565b60004261053483826121a8565b60606108457f000000000000000000000000000000000000000000000000000000000000000061226a565b61086e7f000000000000000000000000000000000000000000000000000000000000000061226a565b6108977f000000000000000000000000000000000000000000000000000000000000000061226a565b6040516020016108a993929190613bc8565b604051602081830303815290604052905090565b606060008267ffffffffffffffff8111156108da576108da613759565b60405190808252806020026020018201604052801561090d57816020015b60608152602001906001900390816108f85790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86018114368888848181106109555761095561372a565b90506020028101906109679190613c3e565b905036600061097960208401846137c6565b909250905080158061099957506109936040840184613c72565b82141590505b156109d0576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a9257610a8a604051806080016040528086600001358152602001858585818110610a0557610a0561372a565b9050602002810190610a179190613cd9565b610a2090613d0d565b8152602001610a326040880188613c72565b85818110610a4257610a4261372a565b905060600201803603810190610a589190613d84565b8152602001610a6d60808801606089016134ea565b73ffffffffffffffffffffffffffffffffffffffff1690526123a7565b6001016109d3565b506000610abb8435610aa48486613a3f565b610ab460808801606089016134ea565b8a8961138f565b8051909150610aca9088613ae2565b96508060200151898781518110610ae357610ae361372a565b6020026020010181905250806020015151880197505050505050610b078160010190565b9050610915565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082019290925261012081019190915260008281526032602090815260409182902082516101408101845281548152600182015492810192909252600281015467ffffffffffffffff808216948401949094526801000000000000000081048416606084015270010000000000000000000000000000000090049092166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff16151561010082015260068201805491929161012084019190610c4890613da0565b80601f0160208091040260200160405190810160405280929190818152602001828054610c7490613da0565b8015610cc15780601f10610c9657610100808354040283529160200191610cc1565b820191906000526020600020905b815481529060010190602001808311610ca457829003601f168201915b5050505050815250509050919050565b600042610534338483611102565b6000610cf2610ced83613ded565b6123a7565b604080516001808252818301909252600091816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610d09579050509050610d776020840184613cd9565b610d8090613d0d565b81600081518110610d9357610d9361372a565b6020908102919091010152610dbc833582610db460c0870160a088016134ea565b34600161138f565b60200151600081518110610dd257610dd261372a565b6020026020010151915050919050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830181146000858584818110610e2757610e2761372a565b9050602002810190610e399190613c3e565b610e4290613ed2565b60208101518051919250901580610e5f5750816040015151815114155b15610e96576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8151811015610f2757610f1f604051806080016040528085600001518152602001848481518110610ecc57610ecc61372a565b6020026020010151815260200185604001518481518110610eef57610eef61372a565b60200260200101518152602001856060015173ffffffffffffffffffffffffffffffffffffffff16815250612536565b600101610e99565b50610f3d82600001518284606001518887611b6e565b610f479086613ae2565b9450505050610f568160010190565b9050610de6565b610f74610f6f36839003830183613fb1565b612536565b604080516001808252818301909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081610f8b579050509050610fc636839003830160208401613b44565b81600081518110610fd957610fd961372a565b6020908102919091010152610720823582610ffa60e0860160c087016134ea565b346001611b6e565b60004282825b8181101561052e576110328686838181106110255761102561372a565b90506020020135846121a8565b600101611008565b60006105656125c4565b604080516001808252818301909252600091829190816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161105e5790505090506110cc6020840184613cd9565b6110d590613d0d565b816000815181106110e8576110e861372a565b6020908102919091010152610dbc8335823334600161138f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152603460209081526040808320858452918290529091205467ffffffffffffffff1615611176576040517fec9d6eeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526020829052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff861690811790915590519091859173ffffffffffffffffffffffffffffffffffffffff8816917f92a1f7a41a7c585a8b09e25b195e225b1d43248daca46b0faf9e0792777a222991a450505050565b604080516020808252818301909252606091600091906020820181803683370190505090506000805b60208110156112cc5760008582602081106112475761124761372a565b1a60f81b90507fff00000000000000000000000000000000000000000000000000000000000000811660000361127d57506112cc565b808484815181106112905761129061372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350506001918201910161122a565b5060008167ffffffffffffffff8111156112e8576112e8613759565b6040519080825280601f01601f191660200182016040528015611312576020820181803683370190505b50905060005b82811015611386578381815181106113325761133261372a565b602001015160f81c60f81b82828151811061134f5761134f61372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101611318565b50949350505050565b60408051808201909152600081526060602082015284516040805180820190915260008152606060208201528167ffffffffffffffff8111156113d4576113d4613759565b6040519080825280602002602001820160405280156113fd578160200160208202803683370190505b5060208201526040517fa2ea7c6e000000000000000000000000000000000000000000000000000000008152600481018990526000907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa15801561146f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114b5919081019061400d565b80519091506114f0576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008367ffffffffffffffff81111561150b5761150b613759565b6040519080825280602002602001820160405280156115aa57816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816115295790505b50905060008467ffffffffffffffff8111156115c8576115c8613759565b6040519080825280602002602001820160405280156115f1578160200160208202803683370190505b50905060005b85811015611a805760008b82815181106116135761161361372a565b60200260200101519050600067ffffffffffffffff16816020015167ffffffffffffffff161415801561165e57504267ffffffffffffffff16816020015167ffffffffffffffff1611155b15611695576040517f08e8b93700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84604001511580156116a8575080604001515b156116df576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052806000801b81526020018f81526020016117034290565b67ffffffffffffffff168152602001836020015167ffffffffffffffff168152602001600067ffffffffffffffff16815260200183606001518152602001836000015173ffffffffffffffffffffffffffffffffffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815260200183604001511515815260200183608001518152509050600080600090505b6117a583826126f8565b600081815260326020526040902054909250156117c45760010161179b565b81835260008281526032602090815260409182902085518155908501516001820155908401516002820180546060870151608088015167ffffffffffffffff908116700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff92821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169190951617919091171691909117905560a0840151600382015560c084015160048201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560e0850151600583018054610100880151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff000000000000000000000000000000000000000000909116929093169190911791909117905561012084015184919060068201906119449082614133565b50505060608401511561199b57606084015160009081526032602052604090205461199b576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828786815181106119ae576119ae61372a565b60200260200101819052508360a001518686815181106119d0576119d061372a565b60200260200101818152505081896020015186815181106119f3576119f361372a565b6020026020010181815250508f8e73ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff167f8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b3585604051611a6391815260200190565b60405180910390a450505050611a798160010190565b90506115f7565b50611a9083838360008c8c612757565b845250919998505050505050505050565b606060008267ffffffffffffffff811115611abe57611abe613759565b604051908082528060200260200182016040528015611ae7578160200160208202803683370190505b5090506000805b855181101561052e576000868281518110611b0b57611b0b61372a565b6020026020010151905060005b8151811015611b6457818181518110611b3357611b3361372a565b6020026020010151858581518110611b4d57611b4d61372a565b602090810291909101015260019384019301611b18565b5050600101611aee565b6040517fa2ea7c6e0000000000000000000000000000000000000000000000000000000081526004810186905260009081907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa158015611bdc573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611c22919081019061400d565b8051909150611c5d576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855160008167ffffffffffffffff811115611c7a57611c7a613759565b604051908082528060200260200182016040528015611d1957816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611c985790505b50905060008267ffffffffffffffff811115611d3757611d37613759565b604051908082528060200260200182016040528015611d60578160200160208202803683370190505b50905060005b8381101561218a5760008a8281518110611d8257611d8261372a565b6020908102919091018101518051600090815260329092526040909120805491925090611ddb576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8c816001015414611e18576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015473ffffffffffffffffffffffffffffffffffffffff8c8116911614611e6e576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015474010000000000000000000000000000000000000000900460ff16611ec4576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002810154700100000000000000000000000000000000900467ffffffffffffffff1615611f1e576040517f905e710700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b426002820180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff811670010000000000000000000000000000000067ffffffffffffffff948516810291821793849055604080516101408101825287548152600188015460208201529386169286169290921791830191909152680100000000000000008304841660608301529091049091166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff161515610100820152600682018054839161012084019161202a90613da0565b80601f016020809104026020016040519081016040528092919081815260200182805461205690613da0565b80156120a35780601f10612078576101008083540402835291602001916120a3565b820191906000526020600020905b81548152906001019060200180831161208657829003601f168201915b5050505050815250508584815181106120be576120be61372a565b602002602001018190525081602001518484815181106120e0576120e061372a565b60200260200101818152505080600101548b73ffffffffffffffffffffffffffffffffffffffff168260040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167ff930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f615856000015160405161217891815260200190565b60405180910390a45050600101611d66565b5061219a84838360018b8b612757565b9a9950505050505050505050565b60008281526033602052604090205467ffffffffffffffff16156121f8576040517f2e26794600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526033602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051909184917f5aafceeb1c7ad58e4a84898bdee37c02c0fc46e7d24e6b60e8209449f183459f9190a35050565b6060816000036122ad57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156122d757806122c18161424d565b91506122d09050600a836142b4565b91506122b1565b60008167ffffffffffffffff8111156122f2576122f2613759565b6040519080825280601f01601f19166020018201604052801561231c576020820181803683370190505b5090505b841561239f57612331600183613ae2565b915061233e600a866142c8565b6123499060306142dc565b60f81b81838151811061235e5761235e61372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612398600a866142b4565b9450612320565b949350505050565b60208082015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865187890151878901519589015160808a01518051908c01209851999a9799949895976124ad97612492977fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de619791939290918c9101978852602088019690965273ffffffffffffffffffffffffffffffffffffffff94909416604087015267ffffffffffffffff9290921660608601521515608085015260a084015260c083015260e08201526101000190565b60405160208183030381529060405280519060200120612b31565b9050846060015173ffffffffffffffffffffffffffffffffffffffff166124e282856000015186602001518760400151612b44565b73ffffffffffffffffffffffffffffffffffffffff161461252f576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b60208181015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865186517fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a99650998101999099529588015291860193909352608085018190529293909291906124ad9060a001612492565b60003073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561262a57507f000000000000000000000000000000000000000000000000000000000000000046145b1561265457507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60208083015160c084015160e0850151604080870151606088015161010089015160a08a01516101208b0151945160009961273999989796918c91016142ef565b60405160208183030381529060405280519060200120905092915050565b845160009060018190036127af576127a7888860008151811061277c5761277c61372a565b6020026020010151886000815181106127975761279761372a565b6020026020010151888888612b6c565b915050610697565b602088015173ffffffffffffffffffffffffffffffffffffffff81166128415760005b82811015612835578781815181106127ec576127ec61372a565b602002602001015160001461282d576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016127d2565b50600092505050610697565b6000805b8381101561296b5760008982815181106128615761286161372a565b60200260200101519050806000141580156128e857508373ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e691906143cd565b155b1561291f576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87811115612959576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b96879003969190910190600101612845565b508615612a46576040517f88e5b2d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906388e5b2d99083906129c8908d908d906004016143ea565b60206040518083038185885af11580156129e6573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612a0b91906143cd565b612a41576040517fbf2f3a8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b15565b6040517f91db0b7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906391db0b7e908390612a9c908d908d906004016143ea565b60206040518083038185885af1158015612aba573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612adf91906143cd565b612b15576040517fe8bee83900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415612b2457612b2486612e82565b9998505050505050505050565b6000610534612b3e6125c4565b83612e95565b6000806000612b5587878787612ed7565b91509150612b6281612fef565b5095945050505050565b602086015160009073ffffffffffffffffffffffffffffffffffffffff8116612bd1578515612bc7576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000915050610697565b8515801590612c4c57508073ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c4a91906143cd565b155b15612c83576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83861115612cbd576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85840393508415612d9a576040517fe49617e100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e49617e1908890612d1c908b90600401613663565b60206040518083038185885af1158015612d3a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612d5f91906143cd565b612d95576040517fccf3bb2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e67565b6040517fe60c350500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e60c3505908890612dee908b90600401613663565b60206040518083038185885af1158015612e0c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612e3191906143cd565b612e67576040517fbd8ba84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215612e7657612e7684612e82565b50939695505050505050565b8015612e9257612e923382613248565b50565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526022810183905260428101829052600090606201612739565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612f0e5750600090506003612fe6565b8460ff16601b14158015612f2657508460ff16601c14155b15612f375750600090506004612fe6565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612f8b573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612fdf57600060019250925050612fe6565b9150600090505b94509492505050565b6000816004811115613003576130036144a3565b0361300b5750565b600181600481111561301f5761301f6144a3565b0361308b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064015b60405180910390fd5b600281600481111561309f5761309f6144a3565b03613106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401613082565b600381600481111561311a5761311a6144a3565b036131a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401613082565b60048160048111156131bb576131bb6144a3565b03612e92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401613082565b804710156132b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401613082565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461330c576040519150601f19603f3d011682016040523d82523d6000602084013e613311565b606091505b5050905080610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401613082565b60008083601f8401126133b457600080fd5b50813567ffffffffffffffff8111156133cc57600080fd5b6020830191508360208260051b85010111156133e757600080fd5b9250929050565b6000806020838503121561340157600080fd5b823567ffffffffffffffff81111561341857600080fd5b613424858286016133a2565b90969095509350505050565b60005b8381101561344b578181015183820152602001613433565b50506000910152565b6000815180845261346c816020860160208601613430565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006134b16020830184613454565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114612e9257600080fd5b80356134e5816134b8565b919050565b6000602082840312156134fc57600080fd5b81356134b1816134b8565b6020808252825182820181905260009190848201906040850190845b8181101561353f57835183529284019291840191600101613523565b50909695505050505050565b60006060828403121561355d57600080fd5b50919050565b60006020828403121561357557600080fd5b5035919050565b6000610140825184526020830151602085015260408301516135aa604086018267ffffffffffffffff169052565b5060608301516135c6606086018267ffffffffffffffff169052565b5060808301516135e2608086018267ffffffffffffffff169052565b5060a083015160a085015260c083015161361460c086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e083015161363c60e086018273ffffffffffffffffffffffffffffffffffffffff169052565b50610100838101511515908501526101208084015181860183905261069783870182613454565b6020815260006134b1602083018461357c565b6000806040838503121561368957600080fd5b8235613694816134b8565b946020939093013593505050565b6000602082840312156136b457600080fd5b813567ffffffffffffffff8111156136cb57600080fd5b820160c081850312156134b157600080fd5b600060e0828403121561355d57600080fd5b60006020828403121561370157600080fd5b813567ffffffffffffffff81111561371857600080fd5b8201604081850312156134b157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126137bc57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126137fb57600080fd5b83018035915067ffffffffffffffff82111561381657600080fd5b6020019150600581901b36038213156133e757600080fd5b60405160c0810167ffffffffffffffff8111828210171561385157613851613759565b60405290565b6040516080810167ffffffffffffffff8111828210171561385157613851613759565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138c1576138c1613759565b604052919050565b600067ffffffffffffffff8211156138e3576138e3613759565b5060051b60200190565b8015158114612e9257600080fd5b80356134e5816138ed565b600067ffffffffffffffff82111561392057613920613759565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261395d57600080fd5b813561397061396b82613906565b61387a565b81815284602083860101111561398557600080fd5b816020850160208301376000918101602001919091529392505050565b600060c082840312156139b457600080fd5b6139bc61382e565b905081356139c9816134b8565b8152602082013567ffffffffffffffff80821682146139e757600080fd5b8160208401526139f9604085016138fb565b6040840152606084013560608401526080840135915080821115613a1c57600080fd5b50613a298482850161394c565b60808301525060a082013560a082015292915050565b6000613a4d61396b846138c9565b80848252602080830192508560051b850136811115613a6b57600080fd5b855b81811015613aa757803567ffffffffffffffff811115613a8d5760008081fd5b613a9936828a016139a2565b865250938201938201613a6d565b50919695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561053457610534613ab3565b600060408284031215613b0757600080fd5b6040516040810181811067ffffffffffffffff82111715613b2a57613b2a613759565b604052823581526020928301359281019290925250919050565b600060408284031215613b5657600080fd5b6134b18383613af5565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613b9557600080fd5b83018035915067ffffffffffffffff821115613bb057600080fd5b6020019150600681901b36038213156133e757600080fd5b60008451613bda818460208901613430565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551613c16816001850160208a01613430565b60019201918201528351613c31816002840160208801613430565b0160020195945050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818336030181126137bc57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613ca757600080fd5b83018035915067ffffffffffffffff821115613cc257600080fd5b60200191506060810236038213156133e757600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff418336030181126137bc57600080fd5b600061053436836139a2565b600060608284031215613d2b57600080fd5b6040516060810181811067ffffffffffffffff82111715613d4e57613d4e613759565b604052905080823560ff81168114613d6557600080fd5b8082525060208301356020820152604083013560408201525092915050565b600060608284031215613d9657600080fd5b6134b18383613d19565b600181811c90821680613db457607f821691505b60208210810361355d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060c08236031215613dff57600080fd5b613e07613857565b82358152602083013567ffffffffffffffff811115613e2557600080fd5b613e31368286016139a2565b602083015250613e443660408501613d19565b604082015260a0830135613e57816134b8565b606082015292915050565b600082601f830112613e7357600080fd5b81356020613e8361396b836138c9565b82815260609283028501820192828201919087851115613ea257600080fd5b8387015b85811015613ec557613eb88982613d19565b8452928401928101613ea6565b5090979650505050505050565b600060808236031215613ee457600080fd5b613eec613857565b8235815260208084013567ffffffffffffffff80821115613f0c57600080fd5b9085019036601f830112613f1f57600080fd5b8135613f2d61396b826138c9565b81815260069190911b83018401908481019036831115613f4c57600080fd5b938501935b82851015613f7557613f633686613af5565b82528582019150604085019450613f51565b80868801525050506040860135925080831115613f9157600080fd5b5050613f9f36828601613e62565b604083015250613e57606084016134da565b600060e08284031215613fc357600080fd5b613fcb613857565b82358152613fdc8460208501613af5565b6020820152613fee8460608501613d19565b604082015260c0830135614001816134b8565b60608201529392505050565b6000602080838503121561402057600080fd5b825167ffffffffffffffff8082111561403857600080fd5b908401906080828703121561404c57600080fd5b614054613857565b8251815283830151614065816134b8565b818501526040830151614077816138ed565b604082015260608301518281111561408e57600080fd5b80840193505086601f8401126140a357600080fd5b825191506140b361396b83613906565b82815287858486010111156140c757600080fd5b6140d683868301878701613430565b60608201529695505050505050565b601f82111561072057600081815260208120601f850160051c8101602086101561410c5750805b601f850160051c820191505b8181101561412b57828155600101614118565b505050505050565b815167ffffffffffffffff81111561414d5761414d613759565b6141618161415b8454613da0565b846140e5565b602080601f8311600181146141b4576000841561417e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561412b565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614201578886015182559484019460019091019084016141e2565b508582101561423d57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361427e5761427e613ab3565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826142c3576142c3614285565b500490565b6000826142d7576142d7614285565b500690565b8082018082111561053457610534613ab3565b89815260007fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808b60601b166020840152808a60601b166034840152507fffffffffffffffff000000000000000000000000000000000000000000000000808960c01b166048840152808860c01b1660508401525085151560f81b60588301528460598301528351614388816079850160208801613430565b80830190507fffffffff000000000000000000000000000000000000000000000000000000008460e01b166079820152607d81019150509a9950505050505050505050565b6000602082840312156143df57600080fd5b81516134b1816138ed565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b8381101561445f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa088870301855261444d86835161357c565b95509382019390820190600101614413565b50508584038187015286518085528782019482019350915060005b828110156144965784518452938101939281019260010161447a565b5091979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c6343000813000a", - "deployedBytecode": "0x6080604052600436106101805760003560e01c8063b469318d116100d6578063e45d03f91161007f578063ed24911d11610059578063ed24911d1461049e578063f10b5cc8146104b3578063f17325e7146104e257600080fd5b8063e45d03f914610458578063e57a6b1b1461046b578063e71ff3651461047e57600080fd5b8063d45c4435116100b0578063d45c4435146103cf578063e13458fc14610406578063e30bb5631461041957600080fd5b8063b469318d14610322578063b83010d31461037c578063cf190f34146103af57600080fd5b8063469262671161013857806354fd4d501161011257806354fd4d50146102cd578063831e05a1146102e2578063a3112a64146102f557600080fd5b806346926267146102855780634cb7e9e51461029a5780634d003070146102ad57600080fd5b806317d7de7c1161016957806317d7de7c146102005780632d0335ab1461022257806344adc90e1461026557600080fd5b806312b11a171461018557806313893f61146101c7575b600080fd5b34801561019157600080fd5b507fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de615b6040519081526020015b60405180910390f35b3480156101d357600080fd5b506101e76101e23660046133ee565b6104f5565b60405167ffffffffffffffff90911681526020016101be565b34801561020c57600080fd5b5061021561053a565b6040516101be919061349e565b34801561022e57600080fd5b506101b461023d3660046134ea565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6102786102733660046133ee565b61056a565b6040516101be9190613507565b61029861029336600461354b565b6106a1565b005b6102986102a83660046133ee565b610725565b3480156102b957600080fd5b506101e76102c8366004613563565b61080d565b3480156102d957600080fd5b5061021561081a565b6102786102f03660046133ee565b6108bd565b34801561030157600080fd5b50610315610310366004613563565b610b0e565b6040516101be9190613663565b34801561032e57600080fd5b506101e761033d366004613676565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152603460209081526040808320938352929052205467ffffffffffffffff1690565b34801561038857600080fd5b507fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a996506101b4565b3480156103bb57600080fd5b506101e76103ca366004613563565b610cd1565b3480156103db57600080fd5b506101e76103ea366004613563565b60009081526033602052604090205467ffffffffffffffff1690565b6101b46104143660046136a2565b610cdf565b34801561042557600080fd5b50610448610434366004613563565b600090815260326020526040902054151590565b60405190151581526020016101be565b6102986104663660046133ee565b610de2565b6102986104793660046136dd565b610f5d565b34801561048a57600080fd5b506101e76104993660046133ee565b611002565b3480156104aa57600080fd5b506101b461103a565b3480156104bf57600080fd5b5060405173420000000000000000000000000000000000002081526020016101be565b6101b46104f03660046136ef565b611044565b60004282825b8181101561052e57610526338787848181106105195761051961372a565b9050602002013585611102565b6001016104fb565b50909150505b92915050565b60606105657f0000000000000000000000000000000000000000000000000000000000000000611201565b905090565b606060008267ffffffffffffffff81111561058757610587613759565b6040519080825280602002602001820160405280156105ba57816020015b60608152602001906001900390816105a55790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86018114368888848181106106025761060261372a565b90506020028101906106149190613788565b9050600061063b823561062a60208501856137c6565b61063391613a3f565b33888761138f565b805190915061064a9086613ae2565b945080602001518785815181106106635761066361372a565b6020026020010181905250806020015151860195505050506106858160010190565b90506105c2565b506106978383611aa1565b9695505050505050565b604080516001808252818301909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816106b85790505090506106f336839003830160208401613b44565b816000815181106107065761070661372a565b602090810291909101015261072082358233346001611b6e565b505050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83018114368585848181106107695761076961372a565b905060200281019061077b9190613788565b90506107e8813561078f6020840184613b60565b808060200260200160405190810160405280939291908181526020016000905b828210156107db576107cc60408302860136819003810190613b44565b815260200190600101906107af565b5050505050338786611b6e565b6107f29085613ae2565b935050506108008160010190565b9050610729565b50505050565b60004261053483826121a8565b60606108457f000000000000000000000000000000000000000000000000000000000000000061226a565b61086e7f000000000000000000000000000000000000000000000000000000000000000061226a565b6108977f000000000000000000000000000000000000000000000000000000000000000061226a565b6040516020016108a993929190613bc8565b604051602081830303815290604052905090565b606060008267ffffffffffffffff8111156108da576108da613759565b60405190808252806020026020018201604052801561090d57816020015b60608152602001906001900390816108f85790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86018114368888848181106109555761095561372a565b90506020028101906109679190613c3e565b905036600061097960208401846137c6565b909250905080158061099957506109936040840184613c72565b82141590505b156109d0576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a9257610a8a604051806080016040528086600001358152602001858585818110610a0557610a0561372a565b9050602002810190610a179190613cd9565b610a2090613d0d565b8152602001610a326040880188613c72565b85818110610a4257610a4261372a565b905060600201803603810190610a589190613d84565b8152602001610a6d60808801606089016134ea565b73ffffffffffffffffffffffffffffffffffffffff1690526123a7565b6001016109d3565b506000610abb8435610aa48486613a3f565b610ab460808801606089016134ea565b8a8961138f565b8051909150610aca9088613ae2565b96508060200151898781518110610ae357610ae361372a565b6020026020010181905250806020015151880197505050505050610b078160010190565b9050610915565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082019290925261012081019190915260008281526032602090815260409182902082516101408101845281548152600182015492810192909252600281015467ffffffffffffffff808216948401949094526801000000000000000081048416606084015270010000000000000000000000000000000090049092166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff16151561010082015260068201805491929161012084019190610c4890613da0565b80601f0160208091040260200160405190810160405280929190818152602001828054610c7490613da0565b8015610cc15780601f10610c9657610100808354040283529160200191610cc1565b820191906000526020600020905b815481529060010190602001808311610ca457829003601f168201915b5050505050815250509050919050565b600042610534338483611102565b6000610cf2610ced83613ded565b6123a7565b604080516001808252818301909252600091816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610d09579050509050610d776020840184613cd9565b610d8090613d0d565b81600081518110610d9357610d9361372a565b6020908102919091010152610dbc833582610db460c0870160a088016134ea565b34600161138f565b60200151600081518110610dd257610dd261372a565b6020026020010151915050919050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830181146000858584818110610e2757610e2761372a565b9050602002810190610e399190613c3e565b610e4290613ed2565b60208101518051919250901580610e5f5750816040015151815114155b15610e96576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8151811015610f2757610f1f604051806080016040528085600001518152602001848481518110610ecc57610ecc61372a565b6020026020010151815260200185604001518481518110610eef57610eef61372a565b60200260200101518152602001856060015173ffffffffffffffffffffffffffffffffffffffff16815250612536565b600101610e99565b50610f3d82600001518284606001518887611b6e565b610f479086613ae2565b9450505050610f568160010190565b9050610de6565b610f74610f6f36839003830183613fb1565b612536565b604080516001808252818301909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081610f8b579050509050610fc636839003830160208401613b44565b81600081518110610fd957610fd961372a565b6020908102919091010152610720823582610ffa60e0860160c087016134ea565b346001611b6e565b60004282825b8181101561052e576110328686838181106110255761102561372a565b90506020020135846121a8565b600101611008565b60006105656125c4565b604080516001808252818301909252600091829190816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161105e5790505090506110cc6020840184613cd9565b6110d590613d0d565b816000815181106110e8576110e861372a565b6020908102919091010152610dbc8335823334600161138f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152603460209081526040808320858452918290529091205467ffffffffffffffff1615611176576040517fec9d6eeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526020829052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff861690811790915590519091859173ffffffffffffffffffffffffffffffffffffffff8816917f92a1f7a41a7c585a8b09e25b195e225b1d43248daca46b0faf9e0792777a222991a450505050565b604080516020808252818301909252606091600091906020820181803683370190505090506000805b60208110156112cc5760008582602081106112475761124761372a565b1a60f81b90507fff00000000000000000000000000000000000000000000000000000000000000811660000361127d57506112cc565b808484815181106112905761129061372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350506001918201910161122a565b5060008167ffffffffffffffff8111156112e8576112e8613759565b6040519080825280601f01601f191660200182016040528015611312576020820181803683370190505b50905060005b82811015611386578381815181106113325761133261372a565b602001015160f81c60f81b82828151811061134f5761134f61372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101611318565b50949350505050565b60408051808201909152600081526060602082015284516040805180820190915260008152606060208201528167ffffffffffffffff8111156113d4576113d4613759565b6040519080825280602002602001820160405280156113fd578160200160208202803683370190505b5060208201526040517fa2ea7c6e000000000000000000000000000000000000000000000000000000008152600481018990526000907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa15801561146f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114b5919081019061400d565b80519091506114f0576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008367ffffffffffffffff81111561150b5761150b613759565b6040519080825280602002602001820160405280156115aa57816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816115295790505b50905060008467ffffffffffffffff8111156115c8576115c8613759565b6040519080825280602002602001820160405280156115f1578160200160208202803683370190505b50905060005b85811015611a805760008b82815181106116135761161361372a565b60200260200101519050600067ffffffffffffffff16816020015167ffffffffffffffff161415801561165e57504267ffffffffffffffff16816020015167ffffffffffffffff1611155b15611695576040517f08e8b93700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84604001511580156116a8575080604001515b156116df576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052806000801b81526020018f81526020016117034290565b67ffffffffffffffff168152602001836020015167ffffffffffffffff168152602001600067ffffffffffffffff16815260200183606001518152602001836000015173ffffffffffffffffffffffffffffffffffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815260200183604001511515815260200183608001518152509050600080600090505b6117a583826126f8565b600081815260326020526040902054909250156117c45760010161179b565b81835260008281526032602090815260409182902085518155908501516001820155908401516002820180546060870151608088015167ffffffffffffffff908116700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff92821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169190951617919091171691909117905560a0840151600382015560c084015160048201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560e0850151600583018054610100880151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff000000000000000000000000000000000000000000909116929093169190911791909117905561012084015184919060068201906119449082614133565b50505060608401511561199b57606084015160009081526032602052604090205461199b576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828786815181106119ae576119ae61372a565b60200260200101819052508360a001518686815181106119d0576119d061372a565b60200260200101818152505081896020015186815181106119f3576119f361372a565b6020026020010181815250508f8e73ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff167f8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b3585604051611a6391815260200190565b60405180910390a450505050611a798160010190565b90506115f7565b50611a9083838360008c8c612757565b845250919998505050505050505050565b606060008267ffffffffffffffff811115611abe57611abe613759565b604051908082528060200260200182016040528015611ae7578160200160208202803683370190505b5090506000805b855181101561052e576000868281518110611b0b57611b0b61372a565b6020026020010151905060005b8151811015611b6457818181518110611b3357611b3361372a565b6020026020010151858581518110611b4d57611b4d61372a565b602090810291909101015260019384019301611b18565b5050600101611aee565b6040517fa2ea7c6e0000000000000000000000000000000000000000000000000000000081526004810186905260009081907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa158015611bdc573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611c22919081019061400d565b8051909150611c5d576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855160008167ffffffffffffffff811115611c7a57611c7a613759565b604051908082528060200260200182016040528015611d1957816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611c985790505b50905060008267ffffffffffffffff811115611d3757611d37613759565b604051908082528060200260200182016040528015611d60578160200160208202803683370190505b50905060005b8381101561218a5760008a8281518110611d8257611d8261372a565b6020908102919091018101518051600090815260329092526040909120805491925090611ddb576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8c816001015414611e18576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015473ffffffffffffffffffffffffffffffffffffffff8c8116911614611e6e576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015474010000000000000000000000000000000000000000900460ff16611ec4576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002810154700100000000000000000000000000000000900467ffffffffffffffff1615611f1e576040517f905e710700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b426002820180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff811670010000000000000000000000000000000067ffffffffffffffff948516810291821793849055604080516101408101825287548152600188015460208201529386169286169290921791830191909152680100000000000000008304841660608301529091049091166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff161515610100820152600682018054839161012084019161202a90613da0565b80601f016020809104026020016040519081016040528092919081815260200182805461205690613da0565b80156120a35780601f10612078576101008083540402835291602001916120a3565b820191906000526020600020905b81548152906001019060200180831161208657829003601f168201915b5050505050815250508584815181106120be576120be61372a565b602002602001018190525081602001518484815181106120e0576120e061372a565b60200260200101818152505080600101548b73ffffffffffffffffffffffffffffffffffffffff168260040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167ff930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f615856000015160405161217891815260200190565b60405180910390a45050600101611d66565b5061219a84838360018b8b612757565b9a9950505050505050505050565b60008281526033602052604090205467ffffffffffffffff16156121f8576040517f2e26794600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526033602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051909184917f5aafceeb1c7ad58e4a84898bdee37c02c0fc46e7d24e6b60e8209449f183459f9190a35050565b6060816000036122ad57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156122d757806122c18161424d565b91506122d09050600a836142b4565b91506122b1565b60008167ffffffffffffffff8111156122f2576122f2613759565b6040519080825280601f01601f19166020018201604052801561231c576020820181803683370190505b5090505b841561239f57612331600183613ae2565b915061233e600a866142c8565b6123499060306142dc565b60f81b81838151811061235e5761235e61372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612398600a866142b4565b9450612320565b949350505050565b60208082015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865187890151878901519589015160808a01518051908c01209851999a9799949895976124ad97612492977fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de619791939290918c9101978852602088019690965273ffffffffffffffffffffffffffffffffffffffff94909416604087015267ffffffffffffffff9290921660608601521515608085015260a084015260c083015260e08201526101000190565b60405160208183030381529060405280519060200120612b31565b9050846060015173ffffffffffffffffffffffffffffffffffffffff166124e282856000015186602001518760400151612b44565b73ffffffffffffffffffffffffffffffffffffffff161461252f576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b60208181015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865186517fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a99650998101999099529588015291860193909352608085018190529293909291906124ad9060a001612492565b60003073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561262a57507f000000000000000000000000000000000000000000000000000000000000000046145b1561265457507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60208083015160c084015160e0850151604080870151606088015161010089015160a08a01516101208b0151945160009961273999989796918c91016142ef565b60405160208183030381529060405280519060200120905092915050565b845160009060018190036127af576127a7888860008151811061277c5761277c61372a565b6020026020010151886000815181106127975761279761372a565b6020026020010151888888612b6c565b915050610697565b602088015173ffffffffffffffffffffffffffffffffffffffff81166128415760005b82811015612835578781815181106127ec576127ec61372a565b602002602001015160001461282d576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016127d2565b50600092505050610697565b6000805b8381101561296b5760008982815181106128615761286161372a565b60200260200101519050806000141580156128e857508373ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e691906143cd565b155b1561291f576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87811115612959576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b96879003969190910190600101612845565b508615612a46576040517f88e5b2d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906388e5b2d99083906129c8908d908d906004016143ea565b60206040518083038185885af11580156129e6573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612a0b91906143cd565b612a41576040517fbf2f3a8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b15565b6040517f91db0b7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906391db0b7e908390612a9c908d908d906004016143ea565b60206040518083038185885af1158015612aba573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612adf91906143cd565b612b15576040517fe8bee83900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415612b2457612b2486612e82565b9998505050505050505050565b6000610534612b3e6125c4565b83612e95565b6000806000612b5587878787612ed7565b91509150612b6281612fef565b5095945050505050565b602086015160009073ffffffffffffffffffffffffffffffffffffffff8116612bd1578515612bc7576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000915050610697565b8515801590612c4c57508073ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c4a91906143cd565b155b15612c83576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83861115612cbd576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85840393508415612d9a576040517fe49617e100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e49617e1908890612d1c908b90600401613663565b60206040518083038185885af1158015612d3a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612d5f91906143cd565b612d95576040517fccf3bb2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e67565b6040517fe60c350500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e60c3505908890612dee908b90600401613663565b60206040518083038185885af1158015612e0c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612e3191906143cd565b612e67576040517fbd8ba84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215612e7657612e7684612e82565b50939695505050505050565b8015612e9257612e923382613248565b50565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526022810183905260428101829052600090606201612739565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612f0e5750600090506003612fe6565b8460ff16601b14158015612f2657508460ff16601c14155b15612f375750600090506004612fe6565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612f8b573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612fdf57600060019250925050612fe6565b9150600090505b94509492505050565b6000816004811115613003576130036144a3565b0361300b5750565b600181600481111561301f5761301f6144a3565b0361308b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064015b60405180910390fd5b600281600481111561309f5761309f6144a3565b03613106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401613082565b600381600481111561311a5761311a6144a3565b036131a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401613082565b60048160048111156131bb576131bb6144a3565b03612e92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401613082565b804710156132b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401613082565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461330c576040519150601f19603f3d011682016040523d82523d6000602084013e613311565b606091505b5050905080610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401613082565b60008083601f8401126133b457600080fd5b50813567ffffffffffffffff8111156133cc57600080fd5b6020830191508360208260051b85010111156133e757600080fd5b9250929050565b6000806020838503121561340157600080fd5b823567ffffffffffffffff81111561341857600080fd5b613424858286016133a2565b90969095509350505050565b60005b8381101561344b578181015183820152602001613433565b50506000910152565b6000815180845261346c816020860160208601613430565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006134b16020830184613454565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114612e9257600080fd5b80356134e5816134b8565b919050565b6000602082840312156134fc57600080fd5b81356134b1816134b8565b6020808252825182820181905260009190848201906040850190845b8181101561353f57835183529284019291840191600101613523565b50909695505050505050565b60006060828403121561355d57600080fd5b50919050565b60006020828403121561357557600080fd5b5035919050565b6000610140825184526020830151602085015260408301516135aa604086018267ffffffffffffffff169052565b5060608301516135c6606086018267ffffffffffffffff169052565b5060808301516135e2608086018267ffffffffffffffff169052565b5060a083015160a085015260c083015161361460c086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e083015161363c60e086018273ffffffffffffffffffffffffffffffffffffffff169052565b50610100838101511515908501526101208084015181860183905261069783870182613454565b6020815260006134b1602083018461357c565b6000806040838503121561368957600080fd5b8235613694816134b8565b946020939093013593505050565b6000602082840312156136b457600080fd5b813567ffffffffffffffff8111156136cb57600080fd5b820160c081850312156134b157600080fd5b600060e0828403121561355d57600080fd5b60006020828403121561370157600080fd5b813567ffffffffffffffff81111561371857600080fd5b8201604081850312156134b157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126137bc57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126137fb57600080fd5b83018035915067ffffffffffffffff82111561381657600080fd5b6020019150600581901b36038213156133e757600080fd5b60405160c0810167ffffffffffffffff8111828210171561385157613851613759565b60405290565b6040516080810167ffffffffffffffff8111828210171561385157613851613759565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138c1576138c1613759565b604052919050565b600067ffffffffffffffff8211156138e3576138e3613759565b5060051b60200190565b8015158114612e9257600080fd5b80356134e5816138ed565b600067ffffffffffffffff82111561392057613920613759565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261395d57600080fd5b813561397061396b82613906565b61387a565b81815284602083860101111561398557600080fd5b816020850160208301376000918101602001919091529392505050565b600060c082840312156139b457600080fd5b6139bc61382e565b905081356139c9816134b8565b8152602082013567ffffffffffffffff80821682146139e757600080fd5b8160208401526139f9604085016138fb565b6040840152606084013560608401526080840135915080821115613a1c57600080fd5b50613a298482850161394c565b60808301525060a082013560a082015292915050565b6000613a4d61396b846138c9565b80848252602080830192508560051b850136811115613a6b57600080fd5b855b81811015613aa757803567ffffffffffffffff811115613a8d5760008081fd5b613a9936828a016139a2565b865250938201938201613a6d565b50919695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561053457610534613ab3565b600060408284031215613b0757600080fd5b6040516040810181811067ffffffffffffffff82111715613b2a57613b2a613759565b604052823581526020928301359281019290925250919050565b600060408284031215613b5657600080fd5b6134b18383613af5565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613b9557600080fd5b83018035915067ffffffffffffffff821115613bb057600080fd5b6020019150600681901b36038213156133e757600080fd5b60008451613bda818460208901613430565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551613c16816001850160208a01613430565b60019201918201528351613c31816002840160208801613430565b0160020195945050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818336030181126137bc57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613ca757600080fd5b83018035915067ffffffffffffffff821115613cc257600080fd5b60200191506060810236038213156133e757600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff418336030181126137bc57600080fd5b600061053436836139a2565b600060608284031215613d2b57600080fd5b6040516060810181811067ffffffffffffffff82111715613d4e57613d4e613759565b604052905080823560ff81168114613d6557600080fd5b8082525060208301356020820152604083013560408201525092915050565b600060608284031215613d9657600080fd5b6134b18383613d19565b600181811c90821680613db457607f821691505b60208210810361355d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060c08236031215613dff57600080fd5b613e07613857565b82358152602083013567ffffffffffffffff811115613e2557600080fd5b613e31368286016139a2565b602083015250613e443660408501613d19565b604082015260a0830135613e57816134b8565b606082015292915050565b600082601f830112613e7357600080fd5b81356020613e8361396b836138c9565b82815260609283028501820192828201919087851115613ea257600080fd5b8387015b85811015613ec557613eb88982613d19565b8452928401928101613ea6565b5090979650505050505050565b600060808236031215613ee457600080fd5b613eec613857565b8235815260208084013567ffffffffffffffff80821115613f0c57600080fd5b9085019036601f830112613f1f57600080fd5b8135613f2d61396b826138c9565b81815260069190911b83018401908481019036831115613f4c57600080fd5b938501935b82851015613f7557613f633686613af5565b82528582019150604085019450613f51565b80868801525050506040860135925080831115613f9157600080fd5b5050613f9f36828601613e62565b604083015250613e57606084016134da565b600060e08284031215613fc357600080fd5b613fcb613857565b82358152613fdc8460208501613af5565b6020820152613fee8460608501613d19565b604082015260c0830135614001816134b8565b60608201529392505050565b6000602080838503121561402057600080fd5b825167ffffffffffffffff8082111561403857600080fd5b908401906080828703121561404c57600080fd5b614054613857565b8251815283830151614065816134b8565b818501526040830151614077816138ed565b604082015260608301518281111561408e57600080fd5b80840193505086601f8401126140a357600080fd5b825191506140b361396b83613906565b82815287858486010111156140c757600080fd5b6140d683868301878701613430565b60608201529695505050505050565b601f82111561072057600081815260208120601f850160051c8101602086101561410c5750805b601f850160051c820191505b8181101561412b57828155600101614118565b505050505050565b815167ffffffffffffffff81111561414d5761414d613759565b6141618161415b8454613da0565b846140e5565b602080601f8311600181146141b4576000841561417e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561412b565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614201578886015182559484019460019091019084016141e2565b508582101561423d57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361427e5761427e613ab3565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826142c3576142c3614285565b500490565b6000826142d7576142d7614285565b500690565b8082018082111561053457610534613ab3565b89815260007fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808b60601b166020840152808a60601b166034840152507fffffffffffffffff000000000000000000000000000000000000000000000000808960c01b166048840152808860c01b1660508401525085151560f81b60588301528460598301528351614388816079850160208801613430565b80830190507fffffffff000000000000000000000000000000000000000000000000000000008460e01b166079820152607d81019150509a9950505050505050505050565b6000602082840312156143df57600080fd5b81516134b1816138ed565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b8381101561445f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa088870301855261444d86835161357c565b95509382019390820190600101614413565b50508584038187015286518085528782019482019350915060005b828110156144965784518452938101939281019260010161447a565b5091979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c6343000813000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "attest((bytes32,(address,uint64,bool,bytes32,bytes,uint256)))": { - "details": "Attests to a specific schema.", - "params": { - "request": "The arguments of the attestation request. Example: attest({ schema: \"0facc36681cbe2456019c1b0d1e7bedd6d1d40f6f324bf3dd3a4cef2999200a0\", data: { recipient: \"0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf\", expirationTime: 0, revocable: true, refUID: \"0x0000000000000000000000000000000000000000000000000000000000000000\", data: \"0xF00D\", value: 0 } })" - }, - "returns": { - "_0": "The UID of the new attestation." - } - }, - "attestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256),(uint8,bytes32,bytes32),address))": { - "details": "Attests to a specific schema via the provided EIP712 signature.", - "params": { - "delegatedRequest": "The arguments of the delegated attestation request. Example: attestByDelegation({ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: { recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', expirationTime: 1673891048, revocable: true, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x1234', value: 0 }, signature: { v: 28, r: '0x148c...b25b', s: '0x5a72...be22' }, attester: '0xc5E8740aD971409492b1A63Db8d83025e0Fc427e' })" - }, - "returns": { - "_0": "The UID of the new attestation." - } - }, - "constructor": { - "details": "Creates a new EAS instance." - }, - "getAttestation(bytes32)": { - "details": "Returns an existing attestation by UID.", - "params": { - "uid": "The UID of the attestation to retrieve." - }, - "returns": { - "_0": "The attestation data members." - } - }, - "getDomainSeparator()": { - "details": "Returns the domain separator used in the encoding of the signatures for attest, and revoke." - }, - "getNonce(address)": { - "details": "Returns the current nonce per-account.", - "params": { - "account": "The requested account." - }, - "returns": { - "_0": "The current nonce." - } - }, - "getRevokeOffchain(address,bytes32)": { - "details": "Returns the timestamp that the specified data was timestamped with.", - "params": { - "data": "The data to query." - }, - "returns": { - "_0": "The timestamp the data was timestamped with." - } - }, - "getSchemaRegistry()": { - "details": "Returns the address of the global schema registry.", - "returns": { - "_0": "The address of the global schema registry." - } - }, - "getTimestamp(bytes32)": { - "details": "Returns the timestamp that the specified data was timestamped with.", - "params": { - "data": "The data to query." - }, - "returns": { - "_0": "The timestamp the data was timestamped with." - } - }, - "isAttestationValid(bytes32)": { - "details": "Checks whether an attestation exists.", - "params": { - "uid": "The UID of the attestation to retrieve." - }, - "returns": { - "_0": "Whether an attestation exists." - } - }, - "multiAttest((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[])[])": { - "details": "Attests to multiple schemas.", - "params": { - "multiRequests": "The arguments of the multi attestation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization. Example: multiAttest([{ schema: '0x33e9094830a5cba5554d1954310e4fbed2ef5f859ec1404619adea4207f391fd', data: [{ recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf', expirationTime: 1673891048, revocable: true, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x1234', value: 1000 }, { recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', expirationTime: 0, revocable: false, refUID: '0x480df4a039efc31b11bfdf491b383ca138b6bde160988222a2a3509c02cee174', data: '0x00', value: 0 }], }, { schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425', data: [{ recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf', expirationTime: 0, revocable: true, refUID: '0x75bf2ed8dca25a8190c50c52db136664de25b2449535839008ccfdab469b214f', data: '0x12345678', value: 0 }, }])" - }, - "returns": { - "_0": "The UIDs of the new attestations." - } - }, - "multiAttestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[],(uint8,bytes32,bytes32)[],address)[])": { - "details": "Attests to multiple schemas using via provided EIP712 signatures.", - "params": { - "multiDelegatedRequests": "The arguments of the delegated multi attestation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization. Example: multiAttestByDelegation([{ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: [{ recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', expirationTime: 1673891048, revocable: true, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x1234', value: 0 }, { recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf', expirationTime: 0, revocable: false, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x00', value: 0 }], signatures: [{ v: 28, r: '0x148c...b25b', s: '0x5a72...be22' }, { v: 28, r: '0x487s...67bb', s: '0x12ad...2366' }], attester: '0x1D86495b2A7B524D747d2839b3C645Bed32e8CF4' }])" - }, - "returns": { - "_0": "The UIDs of the new attestations." - } - }, - "multiRevoke((bytes32,(bytes32,uint256)[])[])": { - "details": "Revokes existing attestations to multiple schemas.", - "params": { - "multiRequests": "The arguments of the multi revocation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization. Example: multiRevoke([{ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: [{ uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25', value: 1000 }, { uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade', value: 0 }], }, { schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425', data: [{ uid: '0x053d42abce1fd7c8fcddfae21845ad34dae287b2c326220b03ba241bc5a8f019', value: 0 }, }])" - } - }, - "multiRevokeByDelegation((bytes32,(bytes32,uint256)[],(uint8,bytes32,bytes32)[],address)[])": { - "details": "Revokes existing attestations to multiple schemas via provided EIP712 signatures.", - "params": { - "multiDelegatedRequests": "The arguments of the delegated multi revocation attestation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization. Example: multiRevokeByDelegation([{ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: [{ uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25', value: 1000 }, { uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade', value: 0 }], signatures: [{ v: 28, r: '0x148c...b25b', s: '0x5a72...be22' }, { v: 28, r: '0x487s...67bb', s: '0x12ad...2366' }], revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992' }])" - } - }, - "multiRevokeOffchain(bytes32[])": { - "details": "Revokes the specified multiple bytes32 data.", - "params": { - "data": "The data to timestamp." - }, - "returns": { - "_0": "The timestamp the data was revoked with." - } - }, - "multiTimestamp(bytes32[])": { - "details": "Timestamps the specified multiple bytes32 data.", - "params": { - "data": "The data to timestamp." - }, - "returns": { - "_0": "The timestamp the data was timestamped with." - } - }, - "revoke((bytes32,(bytes32,uint256)))": { - "details": "Revokes an existing attestation to a specific schema. Example: revoke({ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: { uid: '0x101032e487642ee04ee17049f99a70590c735b8614079fc9275f9dd57c00966d', value: 0 } })", - "params": { - "request": "The arguments of the revocation request." - } - }, - "revokeByDelegation((bytes32,(bytes32,uint256),(uint8,bytes32,bytes32),address))": { - "details": "Revokes an existing attestation to a specific schema via the provided EIP712 signature. Example: revokeByDelegation({ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: { uid: '0xcbbc12102578c642a0f7b34fe7111e41afa25683b6cd7b5a14caf90fa14d24ba', value: 0 }, signature: { v: 27, r: '0xb593...7142', s: '0x0f5b...2cce' }, revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992' })", - "params": { - "delegatedRequest": "The arguments of the delegated revocation request." - } - }, - "revokeOffchain(bytes32)": { - "details": "Revokes the specified bytes32 data.", - "params": { - "data": "The data to timestamp." - }, - "returns": { - "_0": "The timestamp the data was revoked with." - } - }, - "timestamp(bytes32)": { - "details": "Timestamps the specified bytes32 data.", - "params": { - "data": "The data to timestamp." - }, - "returns": { - "_0": "The timestamp the data was timestamped with." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "events": { - "Attested(address,address,bytes32,bytes32)": { - "details": "Emitted when an attestation has been made.", - "params": { - "attester": "The attesting account.", - "recipient": "The recipient of the attestation.", - "schema": "The UID of the schema.", - "uid": "The UID the revoked attestation." - } - }, - "Revoked(address,address,bytes32,bytes32)": { - "details": "Emitted when an attestation has been revoked.", - "params": { - "attester": "The attesting account.", - "recipient": "The recipient of the attestation.", - "schema": "The UID of the schema.", - "uid": "The UID the revoked attestation." - } - }, - "RevokedOffchain(address,bytes32,uint64)": { - "details": "Emitted when a data has been revoked.", - "params": { - "data": "The data.", - "revoker": "The address of the revoker.", - "timestamp": "The timestamp." - } - }, - "Timestamped(bytes32,uint64)": { - "details": "Emitted when a data has been timestamped.", - "params": { - "data": "The data.", - "timestamp": "The timestamp." - } - } - }, - "title": "EAS" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"AccessDenied\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"AlreadyRevoked\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"AlreadyRevokedOffchain\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"AlreadyTimestamped\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InsufficientValue\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidAttestation\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidAttestations\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidExpirationTime\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidLength\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidOffset\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidRegistry\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidRevocation\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidRevocations\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidSchema\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidSignature\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidVerifier\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"Irrevocable\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"NotFound\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"NotPayable\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"WrongSchema\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\",\"indexed\":false},{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Attested\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\",\"indexed\":false},{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Revoked\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\",\"indexed\":true}],\"type\":\"event\",\"name\":\"RevokedOffchain\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Timestamped\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"struct AttestationRequest\",\"name\":\"request\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct AttestationRequestData\",\"name\":\"data\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"attest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[{\"internalType\":\"struct DelegatedAttestationRequest\",\"name\":\"delegatedRequest\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct AttestationRequestData\",\"name\":\"data\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]},{\"internalType\":\"struct EIP712Signature\",\"name\":\"signature\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}]},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"attestByDelegation\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"getAttestTypeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getAttestation\",\"outputs\":[{\"internalType\":\"struct Attestation\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"time\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revocationTime\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}]}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getDomainSeparator\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getName\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getRevokeOffchain\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"getRevokeTypeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"getSchemaRegistry\",\"outputs\":[{\"internalType\":\"contract ISchemaRegistry\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getTimestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"isAttestationValid\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"struct MultiAttestationRequest[]\",\"name\":\"multiRequests\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct AttestationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"multiAttest\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}]},{\"inputs\":[{\"internalType\":\"struct MultiDelegatedAttestationRequest[]\",\"name\":\"multiDelegatedRequests\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct AttestationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]},{\"internalType\":\"struct EIP712Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}]},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"multiAttestByDelegation\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}]},{\"inputs\":[{\"internalType\":\"struct MultiRevocationRequest[]\",\"name\":\"multiRequests\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct RevocationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"multiRevoke\"},{\"inputs\":[{\"internalType\":\"struct MultiDelegatedRevocationRequest[]\",\"name\":\"multiDelegatedRequests\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct RevocationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]},{\"internalType\":\"struct EIP712Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}]},{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"multiRevokeByDelegation\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"data\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"multiRevokeOffchain\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"data\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"multiTimestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"struct RevocationRequest\",\"name\":\"request\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct RevocationRequestData\",\"name\":\"data\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"revoke\"},{\"inputs\":[{\"internalType\":\"struct DelegatedRevocationRequest\",\"name\":\"delegatedRequest\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct RevocationRequestData\",\"name\":\"data\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]},{\"internalType\":\"struct EIP712Signature\",\"name\":\"signature\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}]},{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"revokeByDelegation\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"revokeOffchain\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"attest((bytes32,(address,uint64,bool,bytes32,bytes,uint256)))\":{\"details\":\"Attests to a specific schema.\",\"params\":{\"request\":\"The arguments of the attestation request. Example: attest({ schema: \\\"0facc36681cbe2456019c1b0d1e7bedd6d1d40f6f324bf3dd3a4cef2999200a0\\\", data: { recipient: \\\"0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf\\\", expirationTime: 0, revocable: true, refUID: \\\"0x0000000000000000000000000000000000000000000000000000000000000000\\\", data: \\\"0xF00D\\\", value: 0 } })\"},\"returns\":{\"_0\":\"The UID of the new attestation.\"}},\"attestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256),(uint8,bytes32,bytes32),address))\":{\"details\":\"Attests to a specific schema via the provided EIP712 signature.\",\"params\":{\"delegatedRequest\":\"The arguments of the delegated attestation request. Example: attestByDelegation({ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: { recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', expirationTime: 1673891048, revocable: true, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x1234', value: 0 }, signature: { v: 28, r: '0x148c...b25b', s: '0x5a72...be22' }, attester: '0xc5E8740aD971409492b1A63Db8d83025e0Fc427e' })\"},\"returns\":{\"_0\":\"The UID of the new attestation.\"}},\"constructor\":{\"details\":\"Creates a new EAS instance.\"},\"getAttestation(bytes32)\":{\"details\":\"Returns an existing attestation by UID.\",\"params\":{\"uid\":\"The UID of the attestation to retrieve.\"},\"returns\":{\"_0\":\"The attestation data members.\"}},\"getDomainSeparator()\":{\"details\":\"Returns the domain separator used in the encoding of the signatures for attest, and revoke.\"},\"getNonce(address)\":{\"details\":\"Returns the current nonce per-account.\",\"params\":{\"account\":\"The requested account.\"},\"returns\":{\"_0\":\"The current nonce.\"}},\"getRevokeOffchain(address,bytes32)\":{\"details\":\"Returns the timestamp that the specified data was timestamped with.\",\"params\":{\"data\":\"The data to query.\"},\"returns\":{\"_0\":\"The timestamp the data was timestamped with.\"}},\"getSchemaRegistry()\":{\"details\":\"Returns the address of the global schema registry.\",\"returns\":{\"_0\":\"The address of the global schema registry.\"}},\"getTimestamp(bytes32)\":{\"details\":\"Returns the timestamp that the specified data was timestamped with.\",\"params\":{\"data\":\"The data to query.\"},\"returns\":{\"_0\":\"The timestamp the data was timestamped with.\"}},\"isAttestationValid(bytes32)\":{\"details\":\"Checks whether an attestation exists.\",\"params\":{\"uid\":\"The UID of the attestation to retrieve.\"},\"returns\":{\"_0\":\"Whether an attestation exists.\"}},\"multiAttest((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[])[])\":{\"details\":\"Attests to multiple schemas.\",\"params\":{\"multiRequests\":\"The arguments of the multi attestation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization. Example: multiAttest([{ schema: '0x33e9094830a5cba5554d1954310e4fbed2ef5f859ec1404619adea4207f391fd', data: [{ recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf', expirationTime: 1673891048, revocable: true, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x1234', value: 1000 }, { recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', expirationTime: 0, revocable: false, refUID: '0x480df4a039efc31b11bfdf491b383ca138b6bde160988222a2a3509c02cee174', data: '0x00', value: 0 }], }, { schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425', data: [{ recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf', expirationTime: 0, revocable: true, refUID: '0x75bf2ed8dca25a8190c50c52db136664de25b2449535839008ccfdab469b214f', data: '0x12345678', value: 0 }, }])\"},\"returns\":{\"_0\":\"The UIDs of the new attestations.\"}},\"multiAttestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[],(uint8,bytes32,bytes32)[],address)[])\":{\"details\":\"Attests to multiple schemas using via provided EIP712 signatures.\",\"params\":{\"multiDelegatedRequests\":\"The arguments of the delegated multi attestation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization. Example: multiAttestByDelegation([{ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: [{ recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', expirationTime: 1673891048, revocable: true, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x1234', value: 0 }, { recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf', expirationTime: 0, revocable: false, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x00', value: 0 }], signatures: [{ v: 28, r: '0x148c...b25b', s: '0x5a72...be22' }, { v: 28, r: '0x487s...67bb', s: '0x12ad...2366' }], attester: '0x1D86495b2A7B524D747d2839b3C645Bed32e8CF4' }])\"},\"returns\":{\"_0\":\"The UIDs of the new attestations.\"}},\"multiRevoke((bytes32,(bytes32,uint256)[])[])\":{\"details\":\"Revokes existing attestations to multiple schemas.\",\"params\":{\"multiRequests\":\"The arguments of the multi revocation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization. Example: multiRevoke([{ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: [{ uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25', value: 1000 }, { uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade', value: 0 }], }, { schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425', data: [{ uid: '0x053d42abce1fd7c8fcddfae21845ad34dae287b2c326220b03ba241bc5a8f019', value: 0 }, }])\"}},\"multiRevokeByDelegation((bytes32,(bytes32,uint256)[],(uint8,bytes32,bytes32)[],address)[])\":{\"details\":\"Revokes existing attestations to multiple schemas via provided EIP712 signatures.\",\"params\":{\"multiDelegatedRequests\":\"The arguments of the delegated multi revocation attestation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization. Example: multiRevokeByDelegation([{ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: [{ uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25', value: 1000 }, { uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade', value: 0 }], signatures: [{ v: 28, r: '0x148c...b25b', s: '0x5a72...be22' }, { v: 28, r: '0x487s...67bb', s: '0x12ad...2366' }], revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992' }])\"}},\"multiRevokeOffchain(bytes32[])\":{\"details\":\"Revokes the specified multiple bytes32 data.\",\"params\":{\"data\":\"The data to timestamp.\"},\"returns\":{\"_0\":\"The timestamp the data was revoked with.\"}},\"multiTimestamp(bytes32[])\":{\"details\":\"Timestamps the specified multiple bytes32 data.\",\"params\":{\"data\":\"The data to timestamp.\"},\"returns\":{\"_0\":\"The timestamp the data was timestamped with.\"}},\"revoke((bytes32,(bytes32,uint256)))\":{\"details\":\"Revokes an existing attestation to a specific schema. Example: revoke({ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: { uid: '0x101032e487642ee04ee17049f99a70590c735b8614079fc9275f9dd57c00966d', value: 0 } })\",\"params\":{\"request\":\"The arguments of the revocation request.\"}},\"revokeByDelegation((bytes32,(bytes32,uint256),(uint8,bytes32,bytes32),address))\":{\"details\":\"Revokes an existing attestation to a specific schema via the provided EIP712 signature. Example: revokeByDelegation({ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: { uid: '0xcbbc12102578c642a0f7b34fe7111e41afa25683b6cd7b5a14caf90fa14d24ba', value: 0 }, signature: { v: 27, r: '0xb593...7142', s: '0x0f5b...2cce' }, revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992' })\",\"params\":{\"delegatedRequest\":\"The arguments of the delegated revocation request.\"}},\"revokeOffchain(bytes32)\":{\"details\":\"Revokes the specified bytes32 data.\",\"params\":{\"data\":\"The data to timestamp.\"},\"returns\":{\"_0\":\"The timestamp the data was revoked with.\"}},\"timestamp(bytes32)\":{\"details\":\"Timestamps the specified bytes32 data.\",\"params\":{\"data\":\"The data to timestamp.\"},\"returns\":{\"_0\":\"The timestamp the data was timestamped with.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getAttestTypeHash()\":{\"notice\":\"Returns the EIP712 type hash for the attest function.\"},\"getName()\":{\"notice\":\"Returns the EIP712 name.\"},\"getRevokeTypeHash()\":{\"notice\":\"Returns the EIP712 type hash for the revoke function.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=node_modules/clones-with-immutable-args/src/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":clones-with-immutable-args/=node_modules/clones-with-immutable-args/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"contracts/EAS/EAS.sol\":\"EAS\"},\"libraries\":{}},\"sources\":{\"contracts/EAS/Common.sol\":{\"keccak256\":\"0x922fda236f56fa813171ac1ae04d70d58763142ed084e36d29b369160f99acef\",\"urls\":[\"bzz-raw://82c6eb5ce50a0cfa28ad70fcd33fcd7f7704d538666127dc7aca32960423851b\",\"dweb:/ipfs/QmVQXmi9d7R4iks3rKNQKsq9HeuHZwpCg68jFbYGTw3VUs\"],\"license\":\"MIT\"},\"contracts/EAS/EAS.sol\":{\"keccak256\":\"0xc93349cf7bee9e8fe70dceb66dde09b9ad8dc10fe58626b27b17e385a35e454f\",\"urls\":[\"bzz-raw://350da593f44fda2c73b2d41728b40187cb1ae975a88f7f6ea3b7396542ef8ee6\",\"dweb:/ipfs/QmRr5oJa7YSQ2VCdWkwERWWy2oq8jcmVJ51kGmeQjBxgxQ\"],\"license\":\"MIT\"},\"contracts/EAS/IEAS.sol\":{\"keccak256\":\"0x4b8a0893a5184ef6f5025af10362deb802e59a95082b928eeaed6774b44a84c3\",\"urls\":[\"bzz-raw://0470b6ea4e572b0f43167a2d797a9470c5bc11fd95408f2a1c85962f6d83bf8c\",\"dweb:/ipfs/QmWM2nnP6hqXoorx85jsL5oFUaNbyN918F5dqd3kdhf6MD\"],\"license\":\"MIT\"},\"contracts/EAS/ISchemaRegistry.sol\":{\"keccak256\":\"0x456637ee808bb949d3941cd8b11581a7e7e0a92f304dbbf06fba320f27f57664\",\"urls\":[\"bzz-raw://372bc7f2fc72460daa5273200ac0d6b81427a23a65c8f5152a0f0fe2a47567d7\",\"dweb:/ipfs/QmSDDuVvp5nXaNDPzZbDMH1YE2nN4nrK8hEDctWds4wRah\"],\"license\":\"MIT\"},\"contracts/EAS/eip712/EIP712Verifier.sol\":{\"keccak256\":\"0x003d42b51615b5289e4cb3fcb57619be2e658187702ef2a190fb00129a3dfa72\",\"urls\":[\"bzz-raw://3ea08f8aeaf7b0ba98951e6c3815a0fd6cefaee06a521fd52125e1d43fad50fb\",\"dweb:/ipfs/Qmccb3grHDFkavAWkoyPdyTfSXHPcx51Rhoni3DhfQH76S\"],\"license\":\"MIT\"},\"contracts/EAS/resolver/ISchemaResolver.sol\":{\"keccak256\":\"0x222f41e52e73c3edf2adcddd65c1c6911287b701b07413959a2f720778136135\",\"urls\":[\"bzz-raw://5b3fc66b38c358c3aa704aa3c22bfe7d48063f18529dbc6b61666d0609ffd658\",\"dweb:/ipfs/QmcHBVQzH4mTV1afqQrYw83kgknNETQ1brgWryBwN6u3mf\"],\"license\":\"MIT\"},\"contracts/libraries/Predeploys.sol\":{\"keccak256\":\"0xe46f53d83bbc978cebc11cb702e6b9f046cfbafdcbb79bba2837edf28515cbe4\",\"urls\":[\"bzz-raw://c80c47543cad25cc10ddd7ec2a2399ef1dac50bd5c90d8042211ded0692416a8\",\"dweb:/ipfs/QmeKCGE85eJpJzEXSLmQmhWT9aniSqvwNc8XDcSVedh9F8\"],\"license\":\"MIT\"},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0xc455c84bb1f17e994dea0451fd363f81f83965bfa86e81ac6c8b3a327b9a0ff0\",\"urls\":[\"bzz-raw://fab499f3c0d7df8eb763b50621848d5d2147fb9c42a8eb9b65a11093090bb482\",\"dweb:/ipfs/QmUKsG4ztwtUZFjuRYAxgUFTgH5YxWSGF1BFFaB7vdM2K3\"],\"license\":\"MIT\"},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"],\"license\":\"MIT\"},\"node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"keccak256\":\"0xdb7f5c28fc61cda0bd8ab60ce288e206b791643bcd3ba464a70cbec18895a2f5\",\"urls\":[\"bzz-raw://bf52bdf22a33263f5ca6227a35faeac3b81e7d2c692fbcc6a079d488710c5900\",\"dweb:/ipfs/QmcmsjkP4yq3UhiJbvyzwufaY2EKh1zhHaRK8ATag2cpD2\"],\"license\":\"MIT\"},\"node_modules/@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol\":{\"keccak256\":\"0x6688fad58b9ec0286d40fa957152e575d5d8bd4c3aa80985efdb11b44f776ae7\",\"urls\":[\"bzz-raw://8bc00ab7f133cdaafd212a5cc6a16c8d37319721105d130c8e5af0c4e8f170ba\",\"dweb:/ipfs/QmVmf6LVMfFiEkvKYLzSv3bGHzymEW93AcUuFrNUdY3NtT\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 1, - "receipt": { - "transactionHash": "0xbb2fc2851a8ecca324ffff4e3918d242feee63421798c0939ee1989c4c74a374", - "transactionIndex": "0x1", - "blockHash": "0x7a30ec8bc826b69ce2cf50106457dc27621dbda6f656856cffd37eb0530a3c16", - "blockNumber": "0xbaad12", - "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", - "to": null, - "cumulativeGasUsed": "0x3b5b40", - "gasUsed": "0x3aa40b", - "contractAddress": "0x5A633F1cc84B03F7588486CF2F386c102061E6e1", - "logs": [], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "type": "0x2", - "effectiveGasPrice": "0xb2d05e32" - }, - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 27260, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "_nonces", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 27266, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 24954, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "_db", - "offset": 0, - "slot": "50", - "type": "t_mapping(t_bytes32,t_struct(Attestation)24729_storage)" - }, - { - "astId": 24958, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "_timestamps", - "offset": 0, - "slot": "51", - "type": "t_mapping(t_bytes32,t_uint64)" - }, - { - "astId": 24964, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "_revocationsOffchain", - "offset": 0, - "slot": "52", - "type": "t_mapping(t_address,t_mapping(t_bytes32,t_uint64))" - }, - { - "astId": 24970, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "__gap", - "offset": 0, - "slot": "53", - "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", - "base": "t_uint256" - }, - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_bytes_storage": { - "encoding": "bytes", - "label": "bytes", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_bytes32,t_uint64))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(bytes32 => uint64))", - "numberOfBytes": "32", - "value": "t_mapping(t_bytes32,t_uint64)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_mapping(t_bytes32,t_struct(Attestation)24729_storage)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => struct Attestation)", - "numberOfBytes": "32", - "value": "t_struct(Attestation)24729_storage" - }, - "t_mapping(t_bytes32,t_uint64)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => uint64)", - "numberOfBytes": "32", - "value": "t_uint64" - }, - "t_struct(Attestation)24729_storage": { - "encoding": "inplace", - "label": "struct Attestation", - "numberOfBytes": "224", - "members": [ - { - "astId": 24710, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "uid", - "offset": 0, - "slot": "0", - "type": "t_bytes32" - }, - { - "astId": 24712, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "schema", - "offset": 0, - "slot": "1", - "type": "t_bytes32" - }, - { - "astId": 24714, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "time", - "offset": 0, - "slot": "2", - "type": "t_uint64" - }, - { - "astId": 24716, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "expirationTime", - "offset": 8, - "slot": "2", - "type": "t_uint64" - }, - { - "astId": 24718, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "revocationTime", - "offset": 16, - "slot": "2", - "type": "t_uint64" - }, - { - "astId": 24720, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "refUID", - "offset": 0, - "slot": "3", - "type": "t_bytes32" - }, - { - "astId": 24722, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "recipient", - "offset": 0, - "slot": "4", - "type": "t_address" - }, - { - "astId": 24724, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "attester", - "offset": 0, - "slot": "5", - "type": "t_address" - }, - { - "astId": 24726, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "revocable", - "offset": 20, - "slot": "5", - "type": "t_bool" - }, - { - "astId": 24728, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "data", - "offset": 0, - "slot": "6", - "type": "t_bytes_storage" - } - ] - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint64": { - "encoding": "inplace", - "label": "uint64", - "numberOfBytes": "8" - } - } - }, - "transactionHash": "0xbb2fc2851a8ecca324ffff4e3918d242feee63421798c0939ee1989c4c74a374", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "getAttestTypeHash()": { - "notice": "Returns the EIP712 type hash for the attest function." - }, - "getName()": { - "notice": "Returns the EIP712 name." - }, - "getRevokeTypeHash()": { - "notice": "Returns the EIP712 type hash for the revoke function." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "The Ethereum Attestation Service protocol." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/GasPriceOracle.json b/packages/contracts-bedrock/deployments/optimism-goerli/GasPriceOracle.json deleted file mode 100644 index 5dc77e21e5b6..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/GasPriceOracle.json +++ /dev/null @@ -1,267 +0,0 @@ -{ - "address": "0xb43C412454f5D1e58Fe895B1a832B6700ADB5FA7", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "DECIMALS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "baseFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "gasPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "getL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "getL1GasUsed", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1BaseFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "overhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "scalar", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x8c489a43a92cc7afceee05a095642087bea53073b1505b269503e0319e666948", - "receipt": { - "to": null, - "from": "0xf80267194936da1E98dB10bcE06F3147D580a62e", - "contractAddress": "0xb43C412454f5D1e58Fe895B1a832B6700ADB5FA7", - "transactionIndex": 1, - "gasUsed": "610049", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfb9046eb324ab0aa228b408fcde63bc29ec696fca1bb90e7f0391402b799f518", - "transactionHash": "0x8c489a43a92cc7afceee05a095642087bea53073b1505b269503e0319e666948", - "logs": [], - "blockNumber": 8579685, - "cumulativeGasUsed": "656962", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "2d538e296d12ca6101a896ac2e894043", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gasPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"getL1Fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"getL1GasUsed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1BaseFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"overhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"scalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"custom:proxied\":\"@custom:predeploy 0x420000000000000000000000000000000000000F\",\"kind\":\"dev\",\"methods\":{\"baseFee()\":{\"returns\":{\"_0\":\"Current L2 base fee.\"}},\"constructor\":{\"custom:semver\":\"1.0.0\"},\"decimals()\":{\"custom:legacy\":\"@notice Retrieves the number of decimals used in the scalar.\",\"returns\":{\"_0\":\"Number of decimals used in the scalar.\"}},\"gasPrice()\":{\"returns\":{\"_0\":\"Current L2 gas price (base fee).\"}},\"getL1Fee(bytes)\":{\"params\":{\"_data\":\"Unsigned fully RLP-encoded transaction to get the L1 fee for.\"},\"returns\":{\"_0\":\"L1 fee that should be paid for the tx\"}},\"getL1GasUsed(bytes)\":{\"params\":{\"_data\":\"Unsigned fully RLP-encoded transaction to get the L1 gas for.\"},\"returns\":{\"_0\":\"Amount of L1 gas used to publish the transaction.\"}},\"l1BaseFee()\":{\"returns\":{\"_0\":\"Latest known L1 base fee.\"}},\"overhead()\":{\"returns\":{\"_0\":\"Current fee overhead.\"}},\"scalar()\":{\"returns\":{\"_0\":\"Current fee scalar.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"GasPriceOracle\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DECIMALS()\":{\"notice\":\"Number of decimals used in the scalar.\"},\"baseFee()\":{\"notice\":\"Retrieves the current base fee.\"},\"gasPrice()\":{\"notice\":\"Retrieves the current gas price (base fee).\"},\"getL1Fee(bytes)\":{\"notice\":\"Computes the L1 portion of the fee based on the size of the rlp encoded input transaction, the current L1 base fee, and the various dynamic parameters.\"},\"getL1GasUsed(bytes)\":{\"notice\":\"Computes the amount of L1 gas used for a transaction. Adds the overhead which represents the per-transaction gas overhead of posting the transaction and state roots to L1. Adds 68 bytes of padding to account for the fact that the input does not have a signature.\"},\"l1BaseFee()\":{\"notice\":\"Retrieves the latest known L1 base fee.\"},\"overhead()\":{\"notice\":\"Retrieves the current fee overhead.\"},\"scalar()\":{\"notice\":\"Retrieves the current fee scalar.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"This contract maintains the variables responsible for computing the L1 portion of the total fee charged on L2. Before Bedrock, this contract held variables in state that were read during the state transition function to compute the L1 portion of the transaction fee. After Bedrock, this contract now simply proxies the L1Block contract, which has the values used to compute the L1 portion of the fee in its state. The contract exposes an API that is useful for knowing how large the L1 portion of the transaction fee will be. The following events were deprecated with Bedrock: - event OverheadUpdated(uint256 overhead); - event ScalarUpdated(uint256 scalar); - event DecimalsUpdated(uint256 decimals);\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2/GasPriceOracle.sol\":\"GasPriceOracle\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/L2/GasPriceOracle.sol\":{\"keccak256\":\"0x9b3061d2d5b7841f21ed2ab58096bccbda37ab7416d853c3f83e27bbdbe3ec7c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c86ff50dfd33d81fa9e63ede7e80b3dc57fbe6e53da9cfabae938e6d684dad9d\",\"dweb:/ipfs/Qme2AtXBiNJCmtS2c1BXeaGXUMvvptTD3i2GUncW2EbZ77\"]},\"contracts/L2/L1Block.sol\":{\"keccak256\":\"0xbd2284eeedcdfbb44aeb010c37e109a28a202b6cee62b7091c9a9afb1f461836\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e8afce8fb5023f16e56f9458b3e9ce998740073ef7668d6aade1c0de0512f870\",\"dweb:/ipfs/QmWQ1FNhqJWraS14qq6wYsPngYv6NghHUwgtmvt9PVzhLo\"]},\"contracts/libraries/Predeploys.sol\":{\"keccak256\":\"0xfc30fb239b5f00284f4b8f578a62f0882597e939335c91ea9bc4aab3070ddc43\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fa132267b3a9d98568b4e02cbb68fe2d2c0ca630826242c1b2293a8fa35bd302\",\"dweb:/ipfs/QmdYvcGbaykP6wyBu5T2obXrWK56xGnfWqbYeeWpTChq3w\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9baf7797439c0ae6512f4639dfc6a1934dbd4e4d7cbb8e63e99264ff47682c9e\",\"dweb:/ipfs/QmawAuhppPyeoZH3rC1uh87xDELa9Lyfw5pYsBqE8myE1m\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]}},\"version\":1}", - "bytecode": "0x60e060405234801561001057600080fd5b5060016080819052600060a081905260c081905280610a2361004a823960006102e3015260006102ba015260006102910152610a236000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c806354fd4d5011610076578063de26c4a11161005b578063de26c4a114610123578063f45e65d814610136578063fe173b971461011d57600080fd5b806354fd4d50146101085780636ef25c3a1461011d57600080fd5b8063313ce567116100a7578063313ce567146100e657806349948e0e146100ed578063519b4bd31461010057600080fd5b80630c18c162146100c35780632e0f2625146100de575b600080fd5b6100cb61013e565b6040519081526020015b60405180910390f35b6100cb600681565b60066100cb565b6100cb6100fb3660046105a9565b6101c8565b6100cb610229565b61011061028a565b6040516100d591906106a8565b486100cb565b6100cb6101313660046105a9565b61032d565b6100cb6103dc565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa15801561019f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c391906106f9565b905090565b6000806101d48361032d565b905060006101e0610229565b6101ea9083610741565b905060006101fa6006600a6108a0565b905060006102066103dc565b6102109084610741565b9050600061021e83836108e2565b979650505050505050565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16635cf249696040518163ffffffff1660e01b8152600401602060405180830381865afa15801561019f573d6000803e3d6000fd5b60606102b57f000000000000000000000000000000000000000000000000000000000000000061043d565b6102de7f000000000000000000000000000000000000000000000000000000000000000061043d565b6103077f000000000000000000000000000000000000000000000000000000000000000061043d565b604051602001610319939291906108f6565b604051602081830303815290604052905090565b80516000908190815b818110156103b0578481815181106103505761035061096c565b01602001517fff00000000000000000000000000000000000000000000000000000000000000166000036103905761038960048461099b565b925061039e565b61039b60108461099b565b92505b806103a8816109b3565b915050610336565b5060006103bb61013e565b6103c5908461099b565b90506103d38161044061099b565b95945050505050565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa15801561019f573d6000803e3d6000fd5b60608160000361048057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104aa5780610494816109b3565b91506104a39050600a836108e2565b9150610484565b60008167ffffffffffffffff8111156104c5576104c561057a565b6040519080825280601f01601f1916602001820160405280156104ef576020820181803683370190505b5090505b8415610572576105046001836109eb565b9150610511600a86610a02565b61051c90603061099b565b60f81b8183815181106105315761053161096c565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061056b600a866108e2565b94506104f3565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156105bb57600080fd5b813567ffffffffffffffff808211156105d357600080fd5b818401915084601f8301126105e757600080fd5b8135818111156105f9576105f961057a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561063f5761063f61057a565b8160405282815287602084870101111561065857600080fd5b826020860160208301376000928101602001929092525095945050505050565b60005b8381101561069357818101518382015260200161067b565b838111156106a2576000848401525b50505050565b60208152600082518060208401526106c7816040850160208701610678565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561070b57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561077957610779610712565b500290565b600181815b808511156107d757817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156107bd576107bd610712565b808516156107ca57918102915b93841c9390800290610783565b509250929050565b6000826107ee5750600161089a565b816107fb5750600061089a565b8160018114610811576002811461081b57610837565b600191505061089a565b60ff84111561082c5761082c610712565b50506001821b61089a565b5060208310610133831016604e8410600b841016171561085a575081810a61089a565b610864838361077e565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561089657610896610712565b0290505b92915050565b60006108ac83836107df565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826108f1576108f16108b3565b500490565b60008451610908818460208901610678565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610944816001850160208a01610678565b6001920191820152835161095f816002840160208801610678565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156109ae576109ae610712565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109e4576109e4610712565b5060010190565b6000828210156109fd576109fd610712565b500390565b600082610a1157610a116108b3565b50069056fea164736f6c634300080f000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100be5760003560e01c806354fd4d5011610076578063de26c4a11161005b578063de26c4a114610123578063f45e65d814610136578063fe173b971461011d57600080fd5b806354fd4d50146101085780636ef25c3a1461011d57600080fd5b8063313ce567116100a7578063313ce567146100e657806349948e0e146100ed578063519b4bd31461010057600080fd5b80630c18c162146100c35780632e0f2625146100de575b600080fd5b6100cb61013e565b6040519081526020015b60405180910390f35b6100cb600681565b60066100cb565b6100cb6100fb3660046105a9565b6101c8565b6100cb610229565b61011061028a565b6040516100d591906106a8565b486100cb565b6100cb6101313660046105a9565b61032d565b6100cb6103dc565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa15801561019f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c391906106f9565b905090565b6000806101d48361032d565b905060006101e0610229565b6101ea9083610741565b905060006101fa6006600a6108a0565b905060006102066103dc565b6102109084610741565b9050600061021e83836108e2565b979650505050505050565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16635cf249696040518163ffffffff1660e01b8152600401602060405180830381865afa15801561019f573d6000803e3d6000fd5b60606102b57f000000000000000000000000000000000000000000000000000000000000000061043d565b6102de7f000000000000000000000000000000000000000000000000000000000000000061043d565b6103077f000000000000000000000000000000000000000000000000000000000000000061043d565b604051602001610319939291906108f6565b604051602081830303815290604052905090565b80516000908190815b818110156103b0578481815181106103505761035061096c565b01602001517fff00000000000000000000000000000000000000000000000000000000000000166000036103905761038960048461099b565b925061039e565b61039b60108461099b565b92505b806103a8816109b3565b915050610336565b5060006103bb61013e565b6103c5908461099b565b90506103d38161044061099b565b95945050505050565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa15801561019f573d6000803e3d6000fd5b60608160000361048057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104aa5780610494816109b3565b91506104a39050600a836108e2565b9150610484565b60008167ffffffffffffffff8111156104c5576104c561057a565b6040519080825280601f01601f1916602001820160405280156104ef576020820181803683370190505b5090505b8415610572576105046001836109eb565b9150610511600a86610a02565b61051c90603061099b565b60f81b8183815181106105315761053161096c565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061056b600a866108e2565b94506104f3565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156105bb57600080fd5b813567ffffffffffffffff808211156105d357600080fd5b818401915084601f8301126105e757600080fd5b8135818111156105f9576105f961057a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561063f5761063f61057a565b8160405282815287602084870101111561065857600080fd5b826020860160208301376000928101602001929092525095945050505050565b60005b8381101561069357818101518382015260200161067b565b838111156106a2576000848401525b50505050565b60208152600082518060208401526106c7816040850160208701610678565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561070b57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561077957610779610712565b500290565b600181815b808511156107d757817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156107bd576107bd610712565b808516156107ca57918102915b93841c9390800290610783565b509250929050565b6000826107ee5750600161089a565b816107fb5750600061089a565b8160018114610811576002811461081b57610837565b600191505061089a565b60ff84111561082c5761082c610712565b50506001821b61089a565b5060208310610133831016604e8410600b841016171561085a575081810a61089a565b610864838361077e565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561089657610896610712565b0290505b92915050565b60006108ac83836107df565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826108f1576108f16108b3565b500490565b60008451610908818460208901610678565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610944816001850160208a01610678565b6001920191820152835161095f816002840160208801610678565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156109ae576109ae610712565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109e4576109e4610712565b5060010190565b6000828210156109fd576109fd610712565b500390565b600082610a1157610a116108b3565b50069056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "baseFee()": { - "returns": { - "_0": "Current L2 base fee." - } - }, - "constructor": {}, - "decimals()": { - "returns": { - "_0": "Number of decimals used in the scalar." - } - }, - "gasPrice()": { - "returns": { - "_0": "Current L2 gas price (base fee)." - } - }, - "getL1Fee(bytes)": { - "params": { - "_data": "Unsigned fully RLP-encoded transaction to get the L1 fee for." - }, - "returns": { - "_0": "L1 fee that should be paid for the tx" - } - }, - "getL1GasUsed(bytes)": { - "params": { - "_data": "Unsigned fully RLP-encoded transaction to get the L1 gas for." - }, - "returns": { - "_0": "Amount of L1 gas used to publish the transaction." - } - }, - "l1BaseFee()": { - "returns": { - "_0": "Latest known L1 base fee." - } - }, - "overhead()": { - "returns": { - "_0": "Current fee overhead." - } - }, - "scalar()": { - "returns": { - "_0": "Current fee scalar." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "title": "GasPriceOracle" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "DECIMALS()": { - "notice": "Number of decimals used in the scalar." - }, - "baseFee()": { - "notice": "Retrieves the current base fee." - }, - "gasPrice()": { - "notice": "Retrieves the current gas price (base fee)." - }, - "getL1Fee(bytes)": { - "notice": "Computes the L1 portion of the fee based on the size of the rlp encoded input transaction, the current L1 base fee, and the various dynamic parameters." - }, - "getL1GasUsed(bytes)": { - "notice": "Computes the amount of L1 gas used for a transaction. Adds the overhead which represents the per-transaction gas overhead of posting the transaction and state roots to L1. Adds 68 bytes of padding to account for the fact that the input does not have a signature." - }, - "l1BaseFee()": { - "notice": "Retrieves the latest known L1 base fee." - }, - "overhead()": { - "notice": "Retrieves the current fee overhead." - }, - "scalar()": { - "notice": "Retrieves the current fee scalar." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "This contract maintains the variables responsible for computing the L1 portion of the total fee charged on L2. Before Bedrock, this contract held variables in state that were read during the state transition function to compute the L1 portion of the transaction fee. After Bedrock, this contract now simply proxies the L1Block contract, which has the values used to compute the L1 portion of the fee in its state. The contract exposes an API that is useful for knowing how large the L1 portion of the transaction fee will be. The following events were deprecated with Bedrock: - event OverheadUpdated(uint256 overhead); - event ScalarUpdated(uint256 scalar); - event DecimalsUpdated(uint256 decimals);" - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/L1Block.json b/packages/contracts-bedrock/deployments/optimism-goerli/L1Block.json deleted file mode 100644 index 6e98dea1b0ac..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/L1Block.json +++ /dev/null @@ -1,360 +0,0 @@ -{ - "address": "0x6dF83A19647A398d48e77a6835F4A28EB7e2f7c0", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "DEPOSITOR_ACCOUNT", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "basefee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "batcherHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1FeeOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1FeeScalar", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "number", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "sequenceNumber", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "_timestamp", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "_basefee", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_hash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "_sequenceNumber", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "_batcherHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_l1FeeOverhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_l1FeeScalar", - "type": "uint256" - } - ], - "name": "setL1BlockValues", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "timestamp", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0xea5f379f7e5b1a3e548af70d4f7d0cb8c7fcaa9106fd86403f4617150950f650", - "receipt": { - "to": null, - "from": "0xf80267194936da1E98dB10bcE06F3147D580a62e", - "contractAddress": "0x6dF83A19647A398d48e77a6835F4A28EB7e2f7c0", - "transactionIndex": 2, - "gasUsed": "483065", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x7ca13a929e32f81a61c5f8b2291bb65331e1224341e40521abfb38ca94387b54", - "transactionHash": "0xea5f379f7e5b1a3e548af70d4f7d0cb8c7fcaa9106fd86403f4617150950f650", - "logs": [], - "blockNumber": 8579658, - "cumulativeGasUsed": "572079", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "2d538e296d12ca6101a896ac2e894043", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DEPOSITOR_ACCOUNT\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"basefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batcherHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1FeeOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1FeeScalar\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"number\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"_timestamp\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"_basefee\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_hash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"_sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"_batcherHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_l1FeeOverhead\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_l1FeeScalar\",\"type\":\"uint256\"}],\"name\":\"setL1BlockValues\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"custom:proxied\":\"@custom:predeploy 0x4200000000000000000000000000000000000015\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:semver\":\"1.0.0\"},\"setL1BlockValues(uint64,uint64,uint256,bytes32,uint64,bytes32,uint256,uint256)\":{\"params\":{\"_basefee\":\"L1 basefee.\",\"_batcherHash\":\"Versioned hash to authenticate batcher by.\",\"_hash\":\"L1 blockhash.\",\"_l1FeeOverhead\":\"L1 fee overhead.\",\"_l1FeeScalar\":\"L1 fee scalar.\",\"_number\":\"L1 blocknumber.\",\"_sequenceNumber\":\"Number of L2 blocks since epoch start.\",\"_timestamp\":\"L1 timestamp.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"L1Block\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"DEPOSITOR_ACCOUNT()\":{\"notice\":\"Address of the special depositor account.\"},\"basefee()\":{\"notice\":\"The latest L1 basefee.\"},\"batcherHash()\":{\"notice\":\"The versioned hash to authenticate the batcher by.\"},\"hash()\":{\"notice\":\"The latest L1 blockhash.\"},\"l1FeeOverhead()\":{\"notice\":\"The overhead value applied to the L1 portion of the transaction fee.\"},\"l1FeeScalar()\":{\"notice\":\"The scalar value applied to the L1 portion of the transaction fee.\"},\"number()\":{\"notice\":\"The latest L1 block number known by the L2 system.\"},\"sequenceNumber()\":{\"notice\":\"The number of L2 blocks in the same epoch.\"},\"setL1BlockValues(uint64,uint64,uint256,bytes32,uint64,bytes32,uint256,uint256)\":{\"notice\":\"Updates the L1 block values.\"},\"timestamp()\":{\"notice\":\"The latest L1 timestamp known by the L2 system.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"The L1Block predeploy gives users access to information about the last known L1 block. Values within this contract are updated once per epoch (every L1 block) and can only be set by the \\\"depositor\\\" account, a special system address. Depositor account transactions are created by the protocol whenever we move to a new epoch.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2/L1Block.sol\":\"L1Block\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/L2/L1Block.sol\":{\"keccak256\":\"0xbd2284eeedcdfbb44aeb010c37e109a28a202b6cee62b7091c9a9afb1f461836\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e8afce8fb5023f16e56f9458b3e9ce998740073ef7668d6aade1c0de0512f870\",\"dweb:/ipfs/QmWQ1FNhqJWraS14qq6wYsPngYv6NghHUwgtmvt9PVzhLo\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9baf7797439c0ae6512f4639dfc6a1934dbd4e4d7cbb8e63e99264ff47682c9e\",\"dweb:/ipfs/QmawAuhppPyeoZH3rC1uh87xDELa9Lyfw5pYsBqE8myE1m\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]}},\"version\":1}", - "bytecode": "0x60e060405234801561001057600080fd5b5060016080819052600060a081905260c0819052806107d661004a82396000610371015260006103480152600061031f01526107d66000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638381f58a11610081578063b80777ea1161005b578063b80777ea14610170578063e591b28214610190578063e81b2c6d146101d057600080fd5b80638381f58a1461014a5780638b239f731461015e5780639e8c49661461016757600080fd5b806354fd4d50116100b257806354fd4d50146100ff5780635cf249691461011457806364ca23ef1461011d57600080fd5b8063015d8eb9146100ce57806309bd5a60146100e3575b600080fd5b6100e16100dc366004610515565b6101d9565b005b6100ec60025481565b6040519081526020015b60405180910390f35b610107610318565b6040516100f691906105b7565b6100ec60015481565b6003546101319067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100f6565b6000546101319067ffffffffffffffff1681565b6100ec60055481565b6100ec60065481565b6000546101319068010000000000000000900467ffffffffffffffff1681565b6101ab73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f6565b6100ec60045481565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4c31426c6f636b3a206f6e6c7920746865206465706f7369746f72206163636f60448201527f756e742063616e20736574204c3120626c6f636b2076616c7565730000000000606482015260840160405180910390fd5b6000805467ffffffffffffffff98891668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116998916999099179890981790975560019490945560029290925560038054919094167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009190911617909255600491909155600555600655565b60606103437f00000000000000000000000000000000000000000000000000000000000000006103bb565b61036c7f00000000000000000000000000000000000000000000000000000000000000006103bb565b6103957f00000000000000000000000000000000000000000000000000000000000000006103bb565b6040516020016103a793929190610608565b604051602081830303815290604052905090565b6060816000036103fe57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104285780610412816106ad565b91506104219050600a83610714565b9150610402565b60008167ffffffffffffffff81111561044357610443610728565b6040519080825280601f01601f19166020018201604052801561046d576020820181803683370190505b5090505b84156104f057610482600183610757565b915061048f600a8661076e565b61049a906030610782565b60f81b8183815181106104af576104af61079a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506104e9600a86610714565b9450610471565b949350505050565b803567ffffffffffffffff8116811461051057600080fd5b919050565b600080600080600080600080610100898b03121561053257600080fd5b61053b896104f8565b975061054960208a016104f8565b9650604089013595506060890135945061056560808a016104f8565b979a969950949793969560a0850135955060c08501359460e001359350915050565b60005b838110156105a257818101518382015260200161058a565b838111156105b1576000848401525b50505050565b60208152600082518060208401526105d6816040850160208701610587565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000845161061a818460208901610587565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610656816001850160208a01610587565b60019201918201528351610671816002840160208801610587565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036106de576106de61067e565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610723576107236106e5565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107695761076961067e565b500390565b60008261077d5761077d6106e5565b500690565b600082198211156107955761079561067e565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100c95760003560e01c80638381f58a11610081578063b80777ea1161005b578063b80777ea14610170578063e591b28214610190578063e81b2c6d146101d057600080fd5b80638381f58a1461014a5780638b239f731461015e5780639e8c49661461016757600080fd5b806354fd4d50116100b257806354fd4d50146100ff5780635cf249691461011457806364ca23ef1461011d57600080fd5b8063015d8eb9146100ce57806309bd5a60146100e3575b600080fd5b6100e16100dc366004610515565b6101d9565b005b6100ec60025481565b6040519081526020015b60405180910390f35b610107610318565b6040516100f691906105b7565b6100ec60015481565b6003546101319067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100f6565b6000546101319067ffffffffffffffff1681565b6100ec60055481565b6100ec60065481565b6000546101319068010000000000000000900467ffffffffffffffff1681565b6101ab73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f6565b6100ec60045481565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4c31426c6f636b3a206f6e6c7920746865206465706f7369746f72206163636f60448201527f756e742063616e20736574204c3120626c6f636b2076616c7565730000000000606482015260840160405180910390fd5b6000805467ffffffffffffffff98891668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116998916999099179890981790975560019490945560029290925560038054919094167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009190911617909255600491909155600555600655565b60606103437f00000000000000000000000000000000000000000000000000000000000000006103bb565b61036c7f00000000000000000000000000000000000000000000000000000000000000006103bb565b6103957f00000000000000000000000000000000000000000000000000000000000000006103bb565b6040516020016103a793929190610608565b604051602081830303815290604052905090565b6060816000036103fe57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104285780610412816106ad565b91506104219050600a83610714565b9150610402565b60008167ffffffffffffffff81111561044357610443610728565b6040519080825280601f01601f19166020018201604052801561046d576020820181803683370190505b5090505b84156104f057610482600183610757565b915061048f600a8661076e565b61049a906030610782565b60f81b8183815181106104af576104af61079a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506104e9600a86610714565b9450610471565b949350505050565b803567ffffffffffffffff8116811461051057600080fd5b919050565b600080600080600080600080610100898b03121561053257600080fd5b61053b896104f8565b975061054960208a016104f8565b9650604089013595506060890135945061056560808a016104f8565b979a969950949793969560a0850135955060c08501359460e001359350915050565b60005b838110156105a257818101518382015260200161058a565b838111156105b1576000848401525b50505050565b60208152600082518060208401526105d6816040850160208701610587565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000845161061a818460208901610587565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610656816001850160208a01610587565b60019201918201528351610671816002840160208801610587565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036106de576106de61067e565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610723576107236106e5565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107695761076961067e565b500390565b60008261077d5761077d6106e5565b500690565b600082198211156107955761079561067e565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "constructor": {}, - "setL1BlockValues(uint64,uint64,uint256,bytes32,uint64,bytes32,uint256,uint256)": { - "params": { - "_basefee": "L1 basefee.", - "_batcherHash": "Versioned hash to authenticate batcher by.", - "_hash": "L1 blockhash.", - "_l1FeeOverhead": "L1 fee overhead.", - "_l1FeeScalar": "L1 fee scalar.", - "_number": "L1 blocknumber.", - "_sequenceNumber": "Number of L2 blocks since epoch start.", - "_timestamp": "L1 timestamp." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "title": "L1Block" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "DEPOSITOR_ACCOUNT()": { - "notice": "Address of the special depositor account." - }, - "basefee()": { - "notice": "The latest L1 basefee." - }, - "batcherHash()": { - "notice": "The versioned hash to authenticate the batcher by." - }, - "hash()": { - "notice": "The latest L1 blockhash." - }, - "l1FeeOverhead()": { - "notice": "The overhead value applied to the L1 portion of the transaction fee." - }, - "l1FeeScalar()": { - "notice": "The scalar value applied to the L1 portion of the transaction fee." - }, - "number()": { - "notice": "The latest L1 block number known by the L2 system." - }, - "sequenceNumber()": { - "notice": "The number of L2 blocks in the same epoch." - }, - "setL1BlockValues(uint64,uint64,uint256,bytes32,uint64,bytes32,uint256,uint256)": { - "notice": "Updates the L1 block values." - }, - "timestamp()": { - "notice": "The latest L1 timestamp known by the L2 system." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "The L1Block predeploy gives users access to information about the last known L1 block. Values within this contract are updated once per epoch (every L1 block) and can only be set by the \"depositor\" account, a special system address. Depositor account transactions are created by the protocol whenever we move to a new epoch." - }, - "storageLayout": { - "storage": [ - { - "astId": 3102, - "contract": "contracts/L2/L1Block.sol:L1Block", - "label": "number", - "offset": 0, - "slot": "0", - "type": "t_uint64" - }, - { - "astId": 3105, - "contract": "contracts/L2/L1Block.sol:L1Block", - "label": "timestamp", - "offset": 8, - "slot": "0", - "type": "t_uint64" - }, - { - "astId": 3108, - "contract": "contracts/L2/L1Block.sol:L1Block", - "label": "basefee", - "offset": 0, - "slot": "1", - "type": "t_uint256" - }, - { - "astId": 3111, - "contract": "contracts/L2/L1Block.sol:L1Block", - "label": "hash", - "offset": 0, - "slot": "2", - "type": "t_bytes32" - }, - { - "astId": 3114, - "contract": "contracts/L2/L1Block.sol:L1Block", - "label": "sequenceNumber", - "offset": 0, - "slot": "3", - "type": "t_uint64" - }, - { - "astId": 3117, - "contract": "contracts/L2/L1Block.sol:L1Block", - "label": "batcherHash", - "offset": 0, - "slot": "4", - "type": "t_bytes32" - }, - { - "astId": 3120, - "contract": "contracts/L2/L1Block.sol:L1Block", - "label": "l1FeeOverhead", - "offset": 0, - "slot": "5", - "type": "t_uint256" - }, - { - "astId": 3123, - "contract": "contracts/L2/L1Block.sol:L1Block", - "label": "l1FeeScalar", - "offset": 0, - "slot": "6", - "type": "t_uint256" - } - ], - "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" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/L1FeeVault.json b/packages/contracts-bedrock/deployments/optimism-goerli/L1FeeVault.json deleted file mode 100644 index 6a406bb49f71..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/L1FeeVault.json +++ /dev/null @@ -1,191 +0,0 @@ -{ - "address": "0xC7d3389726374B8BFF53116585e20A483415f6f6", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "inputs": [], - "name": "MIN_WITHDRAWAL_AMOUNT", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RECIPIENT", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalProcessed", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0x59e591102ee7eb6d0c483d0906df373df211a052397c17f949756c814a138332", - "receipt": { - "to": null, - "from": "0xf80267194936da1E98dB10bcE06F3147D580a62e", - "contractAddress": "0xC7d3389726374B8BFF53116585e20A483415f6f6", - "transactionIndex": 1, - "gasUsed": "492913", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x3e293acdeeed6687747feb770b99293b7411057574722d2bcf180856fa1f49a8", - "transactionHash": "0x59e591102ee7eb6d0c483d0906df373df211a052397c17f949756c814a138332", - "logs": [], - "blockNumber": 8579702, - "cumulativeGasUsed": "539814", - "status": 1, - "byzantium": true - }, - "args": [ - "0xBc1233d0C3e6B5d53Ab455cF65A6623F6dCd7e4f" - ], - "numDeployments": 1, - "solcInputHash": "2d538e296d12ca6101a896ac2e894043", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MIN_WITHDRAWAL_AMOUNT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RECIPIENT\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalProcessed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"custom:proxied\":\"@custom:predeploy 0x420000000000000000000000000000000000001A\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:semver\":\"1.1.0\",\"params\":{\"_recipient\":\"Address that will receive the accumulated fees.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"L1FeeVault\",\"version\":1},\"userdoc\":{\"events\":{\"Withdrawal(uint256,address,address)\":{\"notice\":\"Emits each time that a withdrawal occurs.\"}},\"kind\":\"user\",\"methods\":{\"MIN_WITHDRAWAL_AMOUNT()\":{\"notice\":\"Minimum balance before a withdrawal can be triggered.\"},\"RECIPIENT()\":{\"notice\":\"Wallet that will receive the fees on L1.\"},\"totalProcessed()\":{\"notice\":\"Total amount of wei processed by the contract.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"},\"withdraw()\":{\"notice\":\"Triggers a withdrawal of funds to the L1 fee wallet.\"}},\"notice\":\"The L1FeeVault accumulates the L1 portion of the transaction fees.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2/L1FeeVault.sol\":\"L1FeeVault\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/L1/ResourceMetering.sol\":{\"keccak256\":\"0xbd7b9532a70d8c842bfce0ea971be50d02fbbf0227c9ad55c71ac68d438010f4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4969f478dd54e89392cda2ea0c5edcf1be55a5dee43a0e410527b6e3bcb85c88\",\"dweb:/ipfs/QmU2crAojw8DRDsz7PAPrereazjFsKh9wtfTpTDVh6NLfW\"]},\"contracts/L2/L1FeeVault.sol\":{\"keccak256\":\"0x3788c153f2c907f8af0072e9a2d4aa3ec345c91e4c3d0e7bfff002ba518f34c2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c55d8e30118fa0d9c153973931ae24315b9acb168330a6771217c9663fb879e8\",\"dweb:/ipfs/Qmb7JctebXrSVsRAgbEsJd972dVTPSvg9q6taLoZ3DbUBW\"]},\"contracts/L2/L2StandardBridge.sol\":{\"keccak256\":\"0xd77e04c57f33cd32c32f326cd06e213d8a27a9fd372cfc4269953a49243c8c41\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f59627bf4c08c85886e819b29b8565b48fa7e9c230732fedfbb0b9c9a0ee04c5\",\"dweb:/ipfs/Qmao1VbQ57h6gdCZTYfipa8LB1wBwAthop5tPd9TgDXES2\"]},\"contracts/libraries/Arithmetic.sol\":{\"keccak256\":\"0xc8858039f87e48e6f18c1af8bc0b03e57cfef564acddfd06e4d91e3db7ac5ed6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2fc79af1e844aa6dc1c68067bfe1d359df8d4e9a3e8881afb3bcfcbf68071714\",\"dweb:/ipfs/QmcNC4k8zmvwj4kZizSenTiWbx2DJQPbwqXXLF4iMbkRVD\"]},\"contracts/libraries/Burn.sol\":{\"keccak256\":\"0x54233b226ba6919dc46d438bc790108d8f855001002a1b9c3c37aed7a83e5f3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4051a4baca357a9191a6c9e3aa1593a17b69dd7915966e23e4cb269e9c1d9ed4\",\"dweb:/ipfs/QmadKjGKvxm53abVHQdsxrXBc8e9jXywu6vvhkAgjsx59J\"]},\"contracts/libraries/Constants.sol\":{\"keccak256\":\"0x8c7be28a175eb732995a7f704560163c30261f9f70d377f865c5060882509f5d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f72aba26553b10ca88708e05461691b36b0d2ec7a87f718022fe119ca9c70852\",\"dweb:/ipfs/QmQtDEB1F3D8RsgG63KSJ9t7ZyFLaXc2Av81vKD9y2TMn7\"]},\"contracts/libraries/Encoding.sol\":{\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f18156216c1f9457c2e032a812ad70f2babbc5b89997554ff014d64c483fb2ff\",\"dweb:/ipfs/Qmc5rjMaBFn3jV7XqDrEvRbmatQvJxeVJYA5B5rdcKPkcJ\"]},\"contracts/libraries/Hashing.sol\":{\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6746ed0d26d603568818cc52a29d0209effd69f7e55bd0017a6b91bd6cf319fe\",\"dweb:/ipfs/QmPebCmCELMBRtDDxt5ziEPfRXUh6tfm2qJdwz3iyrDdWN\"]},\"contracts/libraries/Predeploys.sol\":{\"keccak256\":\"0xfc30fb239b5f00284f4b8f578a62f0882597e939335c91ea9bc4aab3070ddc43\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fa132267b3a9d98568b4e02cbb68fe2d2c0ca630826242c1b2293a8fa35bd302\",\"dweb:/ipfs/QmdYvcGbaykP6wyBu5T2obXrWK56xGnfWqbYeeWpTChq3w\"]},\"contracts/libraries/SafeCall.sol\":{\"keccak256\":\"0x6e815b62528d452a4f63040d75ff7a08db8ba8096050a53355fc49abaebdf245\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e27e542a11165c82cbb6961f4d8c2a58527fba1ab915afeeded50e96ce929777\",\"dweb:/ipfs/QmRPXdmUAbL1WHZBvENKWkFuHb9bQyrbiJWwDvzEQBLVi8\"]},\"contracts/libraries/Types.sol\":{\"keccak256\":\"0x4fe8ec920798661a828430bd30dc2715eeb40534ec01c0a7bf41cb4ab422e134\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://74c8471869900bd459358cd990bda1c8d234c06b788804c7049cf465ae1e299f\",\"dweb:/ipfs/QmakcfP6NmbVUQsKqH7rEyJsbiqckigLahw9g74oencEJ7\"]},\"contracts/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://921c44e6a0982b9a4011900fda1bda2c06b7a85894967de98b407a83fe9f90c0\",\"dweb:/ipfs/QmSsHLKDUQ82kpKdqB6VntVGKuPDb4W9VdotsubuqWBzio\"]},\"contracts/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x3c99b1e768cc4c1e064ccc137b1b4d5961bf4edf071be84cc216c5b20f1c00da\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e36b2a6325c2f804d769271575669b62ab2da2df3c81921ac7487399fe02af07\",\"dweb:/ipfs/QmTCmcEKwvD8Xvjyev268Bkz27FC7TJpUbw1nADcsThnUr\"]},\"contracts/universal/FeeVault.sol\":{\"keccak256\":\"0x73eb2c835495ec308c69783db55c6cc315ed2a55ee6811ccda4e7dbbde04b2c8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b5e46201184138d60e339c98276e3b265717a12795270a1d0ef03157e452e9a0\",\"dweb:/ipfs/QmWGLhTcPuF9ZZfrjGj4QGCzEuDwiyRAMpnQvxd2oLFX75\"]},\"contracts/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x2fea0ee05071c9c6b06a34a8e805801e247e861359b376a8918106e1d6f77ebe\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://198c91bda2edf864ddad1f8ab6168155d13d6ba5487418e5531ff040ff250686\",\"dweb:/ipfs/QmQzxfHY4P7zdVFRh2DTdGt1KeMHaGKNRf3KPZ1mRTYEGB\"]},\"contracts/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x302094342a45ebdf7f46f4fb48821960d2a4134f66fd7f458f73fc4ddf34d219\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8b0e2b496e966ca6037e1c9be1d44417c0180fda2a27f68114e93b899defb783\",\"dweb:/ipfs/QmXP76ivMLxYxscC7B9E9qtW3u6HJ2MNaRVeo3x24VEAQH\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9baf7797439c0ae6512f4639dfc6a1934dbd4e4d7cbb8e63e99264ff47682c9e\",\"dweb:/ipfs/QmawAuhppPyeoZH3rC1uh87xDELa9Lyfw5pYsBqE8myE1m\"]},\"contracts/universal/StandardBridge.sol\":{\"keccak256\":\"0xaa45044774fa70ed322983c3c0138b21d26d75f4b7e8f5324d53c3eef91adec4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c65c95d0cb71f2e32f5ffdea92151a9a46bbd538ba110389a134963fd16a33e9\",\"dweb:/ipfs/QmaPNZokt4j5SCXaWwVtw6qxu5GXWFa3SWBgaSWPPA9KUG\"]},\"node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"]},\"node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"]},\"node_modules/@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b2717fd2bdac99daa960a6de500754ea1b932093c946388c381da48658234b95\",\"dweb:/ipfs/QmP6QVMn6UeA3ByahyJbYQr5M6coHKBKsf3ySZSfbyA8R7\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x032807210d1d7d218963d7355d62e021a84bf1b3339f4f50be2f63b53cccaf29\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://11756f42121f6541a35a8339ea899ee7514cfaa2e6d740625fcc844419296aa6\",\"dweb:/ipfs/QmekMuk6BY4DAjzeXr4MSbKdgoqqsZnA8JPtuyWc6CwXHf\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"]},\"node_modules/@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"]},\"node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"]},\"node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"]}},\"version\":1}", - "bytecode": "0x61012060405234801561001157600080fd5b506040516108e53803806108e58339810160408190526100309161005d565b678ac7230489e800006080526001600160a01b031660a052600160c081905260e05260006101005261008d565b60006020828403121561006f57600080fd5b81516001600160a01b038116811461008657600080fd5b9392505050565b60805160a05160c05160e051610100516108006100e560003960006103d3015260006103aa01526000610381015260008181607c015281816102570152610319015260008181610137015261015b01526108006000f3fe60806040526004361061005e5760003560e01c806354fd4d501161004357806354fd4d50146100df57806384411d6514610101578063d3e5792b1461012557600080fd5b80630d9019e11461006a5780633ccfd60b146100c857600080fd5b3661006557005b600080fd5b34801561007657600080fd5b5061009e7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100d457600080fd5b506100dd610159565b005b3480156100eb57600080fd5b506100f461037a565b6040516100bf91906105d4565b34801561010d57600080fd5b5061011760005481565b6040519081526020016100bf565b34801561013157600080fd5b506101177f000000000000000000000000000000000000000000000000000000000000000081565b7f0000000000000000000000000000000000000000000000000000000000000000471015610233576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a40160405180910390fd5b600047905080600080828254610249919061061d565b9091555050604080518281527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020820152338183015290517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a1604080516020810182526000815290517fe11013dd0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109163e11013dd918491610345917f0000000000000000000000000000000000000000000000000000000000000000916188b891600401610635565b6000604051808303818588803b15801561035e57600080fd5b505af1158015610372573d6000803e3d6000fd5b505050505050565b60606103a57f000000000000000000000000000000000000000000000000000000000000000061041d565b6103ce7f000000000000000000000000000000000000000000000000000000000000000061041d565b6103f77f000000000000000000000000000000000000000000000000000000000000000061041d565b60405160200161040993929190610679565b604051602081830303815290604052905090565b60608160000361046057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561048a5780610474816106ef565b91506104839050600a83610756565b9150610464565b60008167ffffffffffffffff8111156104a5576104a561076a565b6040519080825280601f01601f1916602001820160405280156104cf576020820181803683370190505b5090505b8415610552576104e4600183610799565b91506104f1600a866107b0565b6104fc90603061061d565b60f81b818381518110610511576105116107c4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061054b600a86610756565b94506104d3565b949350505050565b60005b8381101561057557818101518382015260200161055d565b83811115610584576000848401525b50505050565b600081518084526105a281602086016020860161055a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006105e7602083018461058a565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610630576106306105ee565b500190565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff83166020820152606060408201526000610670606083018461058a565b95945050505050565b6000845161068b81846020890161055a565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516106c7816001850160208a0161055a565b600192019182015283516106e281600284016020880161055a565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610720576107206105ee565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261076557610765610727565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107ab576107ab6105ee565b500390565b6000826107bf576107bf610727565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c806354fd4d501161004357806354fd4d50146100df57806384411d6514610101578063d3e5792b1461012557600080fd5b80630d9019e11461006a5780633ccfd60b146100c857600080fd5b3661006557005b600080fd5b34801561007657600080fd5b5061009e7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100d457600080fd5b506100dd610159565b005b3480156100eb57600080fd5b506100f461037a565b6040516100bf91906105d4565b34801561010d57600080fd5b5061011760005481565b6040519081526020016100bf565b34801561013157600080fd5b506101177f000000000000000000000000000000000000000000000000000000000000000081565b7f0000000000000000000000000000000000000000000000000000000000000000471015610233576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a40160405180910390fd5b600047905080600080828254610249919061061d565b9091555050604080518281527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020820152338183015290517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a1604080516020810182526000815290517fe11013dd0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109163e11013dd918491610345917f0000000000000000000000000000000000000000000000000000000000000000916188b891600401610635565b6000604051808303818588803b15801561035e57600080fd5b505af1158015610372573d6000803e3d6000fd5b505050505050565b60606103a57f000000000000000000000000000000000000000000000000000000000000000061041d565b6103ce7f000000000000000000000000000000000000000000000000000000000000000061041d565b6103f77f000000000000000000000000000000000000000000000000000000000000000061041d565b60405160200161040993929190610679565b604051602081830303815290604052905090565b60608160000361046057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561048a5780610474816106ef565b91506104839050600a83610756565b9150610464565b60008167ffffffffffffffff8111156104a5576104a561076a565b6040519080825280601f01601f1916602001820160405280156104cf576020820181803683370190505b5090505b8415610552576104e4600183610799565b91506104f1600a866107b0565b6104fc90603061061d565b60f81b818381518110610511576105116107c4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061054b600a86610756565b94506104d3565b949350505050565b60005b8381101561057557818101518382015260200161055d565b83811115610584576000848401525b50505050565b600081518084526105a281602086016020860161055a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006105e7602083018461058a565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610630576106306105ee565b500190565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff83166020820152606060408201526000610670606083018461058a565b95945050505050565b6000845161068b81846020890161055a565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516106c7816001850160208a0161055a565b600192019182015283516106e281600284016020880161055a565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610720576107206105ee565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261076557610765610727565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107ab576107ab6105ee565b500390565b6000826107bf576107bf610727565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_recipient": "Address that will receive the accumulated fees." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "title": "L1FeeVault" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MIN_WITHDRAWAL_AMOUNT()": { - "notice": "Minimum balance before a withdrawal can be triggered." - }, - "RECIPIENT()": { - "notice": "Wallet that will receive the fees on L1." - }, - "totalProcessed()": { - "notice": "Total amount of wei processed by the contract." - }, - "version()": { - "notice": "Returns the full semver contract version." - }, - "withdraw()": { - "notice": "Triggers a withdrawal of funds to the L1 fee wallet." - } - }, - "events": { - "Withdrawal(uint256,address,address)": { - "notice": "Emits each time that a withdrawal occurs." - } - }, - "notice": "The L1FeeVault accumulates the L1 portion of the transaction fees." - }, - "storageLayout": { - "storage": [ - { - "astId": 46671, - "contract": "contracts/L2/L1FeeVault.sol:L1FeeVault", - "label": "totalProcessed", - "offset": 0, - "slot": "0", - "type": "t_uint256" - } - ], - "types": { - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/L2CrossDomainMessenger.json b/packages/contracts-bedrock/deployments/optimism-goerli/L2CrossDomainMessenger.json deleted file mode 100644 index 5afa1423ff73..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/L2CrossDomainMessenger.json +++ /dev/null @@ -1,777 +0,0 @@ -{ - "address": "0x3305a8110469eB7168870126b26BDAD56067C679", - "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": "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" - }, - { - "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_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": [], - "name": "OTHER_MESSENGER", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAY_CALL_OVERHEAD", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAY_CONSTANT_OVERHEAD", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAY_GAS_CHECK_BUFFER", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RELAY_RESERVED_GAS", - "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": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "failedMessages", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "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": [ - { - "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": [ - { - "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": [], - "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" - } - ], - "transactionHash": "0x106e27edc8fcd438852dfc61d5f0a2ab57a692c34867b840ce82b484c5e5b8c1", - "receipt": { - "to": null, - "from": "0xf80267194936da1E98dB10bcE06F3147D580a62e", - "contractAddress": "0x3305a8110469eB7168870126b26BDAD56067C679", - "transactionIndex": 1, - "gasUsed": "1797186", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000400000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000001000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc137484cb3fcca86142309e8f0531010de5150858f2f2cec6cb0d656b136f75e", - "transactionHash": "0x106e27edc8fcd438852dfc61d5f0a2ab57a692c34867b840ce82b484c5e5b8c1", - "logs": [ - { - "transactionIndex": 1, - "blockNumber": 8579664, - "transactionHash": "0x106e27edc8fcd438852dfc61d5f0a2ab57a692c34867b840ce82b484c5e5b8c1", - "address": "0x3305a8110469eB7168870126b26BDAD56067C679", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 0, - "blockHash": "0xc137484cb3fcca86142309e8f0531010de5150858f2f2cec6cb0d656b136f75e" - } - ], - "blockNumber": 8579664, - "cumulativeGasUsed": "1861199", - "status": 1, - "byzantium": true - }, - "args": [ - "0x5086d1eEF304eb5284A0f6720f79403b4e9bE294" - ], - "numDeployments": 1, - "solcInputHash": "2d538e296d12ca6101a896ac2e894043", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"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\":\"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\"},{\"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_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\":[],\"name\":\"OTHER_MESSENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAY_CALL_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAY_CONSTANT_OVERHEAD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAY_GAS_CHECK_BUFFER\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RELAY_RESERVED_GAS\",\"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\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"failedMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"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\":[{\"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\":[{\"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\":[],\"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\"}],\"devdoc\":{\"custom:proxied\":\"@custom:predeploy 0x4200000000000000000000000000000000000007\",\"kind\":\"dev\",\"methods\":{\"baseGas(bytes,uint32)\":{\"params\":{\"_message\":\"Message to compute the amount of required gas for.\",\"_minGasLimit\":\"Minimum desired gas limit when message goes to target.\"},\"returns\":{\"_0\":\"Amount of gas required to guarantee message receipt.\"}},\"constructor\":{\"custom:semver\":\"1.4.0\",\"params\":{\"_l1CrossDomainMessenger\":\"Address of the L1CrossDomainMessenger contract.\"}},\"l1CrossDomainMessenger()\":{\"custom:legacy\":\"@notice Legacy getter for the remote messenger. Use otherMessenger going forward.\",\"returns\":{\"_0\":\"Address of the L1CrossDomainMessenger contract.\"}},\"messageNonce()\":{\"returns\":{\"_0\":\"Nonce of the next message to be sent, with added message version.\"}},\"relayMessage(uint256,address,address,uint256,uint256,bytes)\":{\"params\":{\"_message\":\"Message to send to the target.\",\"_minGasLimit\":\"Minimum amount of gas that the message can be executed with.\",\"_nonce\":\"Nonce of the message being relayed.\",\"_sender\":\"Address of the user who sent the message.\",\"_target\":\"Address that the message is targeted at.\",\"_value\":\"ETH value to send with the message.\"}},\"sendMessage(address,bytes,uint32)\":{\"params\":{\"_message\":\"Message to trigger the target address with.\",\"_minGasLimit\":\"Minimum gas limit that the message can be executed with.\",\"_target\":\"Target contract or wallet address.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}},\"xDomainMessageSender()\":{\"returns\":{\"_0\":\"Address of the sender of the currently executing message on the other chain.\"}}},\"title\":\"L2CrossDomainMessenger\",\"version\":1},\"userdoc\":{\"events\":{\"FailedRelayedMessage(bytes32)\":{\"notice\":\"Emitted whenever a message fails to be relayed on this chain.\"},\"RelayedMessage(bytes32)\":{\"notice\":\"Emitted whenever a message is successfully relayed on this chain.\"},\"SentMessage(address,address,bytes,uint256,uint256)\":{\"notice\":\"Emitted whenever a message is sent to the other chain.\"},\"SentMessageExtension1(address,uint256)\":{\"notice\":\"Additional event data to emit, required as of Bedrock. Cannot be merged with the SentMessage event without breaking the ABI of this contract, this is good enough.\"}},\"kind\":\"user\",\"methods\":{\"MESSAGE_VERSION()\":{\"notice\":\"Current message version identifier.\"},\"MIN_GAS_CALLDATA_OVERHEAD()\":{\"notice\":\"Extra gas added to base gas for each byte of calldata in a message.\"},\"MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR()\":{\"notice\":\"Denominator for dynamic overhead added to the base gas for a message.\"},\"MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR()\":{\"notice\":\"Numerator for dynamic overhead added to the base gas for a message.\"},\"OTHER_MESSENGER()\":{\"notice\":\"Address of the paired CrossDomainMessenger contract on the other chain.\"},\"RELAY_CALL_OVERHEAD()\":{\"notice\":\"Gas reserved for performing the external call in `relayMessage`.\"},\"RELAY_CONSTANT_OVERHEAD()\":{\"notice\":\"Constant overhead added to the base gas for a message.\"},\"RELAY_GAS_CHECK_BUFFER()\":{\"notice\":\"Gas reserved for the execution between the `hasMinGas` check and the external call in `relayMessage`.\"},\"RELAY_RESERVED_GAS()\":{\"notice\":\"Gas reserved for finalizing the execution of `relayMessage` after the safe call.\"},\"baseGas(bytes,uint32)\":{\"notice\":\"Computes the amount of gas required to guarantee that a given message will be received on the other chain without running out of gas. Guaranteeing that a message will not run out of gas is important because this ensures that a message can always be replayed on the other chain if it fails to execute completely.\"},\"failedMessages(bytes32)\":{\"notice\":\"Mapping of message hashes to a boolean if and only if the message has failed to be executed at least once. A message will not be present in this mapping if it successfully executed on the first attempt.\"},\"initialize()\":{\"notice\":\"Initializer.\"},\"messageNonce()\":{\"notice\":\"Retrieves the next message nonce. Message version will be added to the upper two bytes of the message nonce. Message version allows us to treat messages as having different structures.\"},\"relayMessage(uint256,address,address,uint256,uint256,bytes)\":{\"notice\":\"Relays a message that was sent by the other CrossDomainMessenger contract. Can only be executed via cross-chain call from the other messenger OR if the message was already received once and is currently being replayed.\"},\"sendMessage(address,bytes,uint32)\":{\"notice\":\"Sends a message to some target address on the other chain. Note that if the call always reverts, then the message will be unrelayable, and any ETH sent will be permanently locked. The same will occur if the target on the other chain is considered unsafe (see the _isUnsafeTarget() function).\"},\"successfulMessages(bytes32)\":{\"notice\":\"Mapping of message hashes to boolean receipt values. Note that a message will only be present in this mapping if it has successfully been relayed on this chain, and can therefore not be relayed again.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"},\"xDomainMessageSender()\":{\"notice\":\"Retrieves the address of the contract or wallet that initiated the currently executing message on the other chain. Will throw an error if there is no message currently being executed. Allows the recipient of a call to see who triggered it.\"}},\"notice\":\"The L2CrossDomainMessenger is a high-level interface for message passing between L1 and L2 on the L2 side. Users are generally encouraged to use this contract instead of lower level message passing contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2/L2CrossDomainMessenger.sol\":\"L2CrossDomainMessenger\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/L1/ResourceMetering.sol\":{\"keccak256\":\"0xbd7b9532a70d8c842bfce0ea971be50d02fbbf0227c9ad55c71ac68d438010f4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4969f478dd54e89392cda2ea0c5edcf1be55a5dee43a0e410527b6e3bcb85c88\",\"dweb:/ipfs/QmU2crAojw8DRDsz7PAPrereazjFsKh9wtfTpTDVh6NLfW\"]},\"contracts/L2/L2CrossDomainMessenger.sol\":{\"keccak256\":\"0x51c28c22a49e926293de7f06989b656bc2f534ee37a727ee1f67efd557c00826\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c3728945b1f4915e78bb5ecffc58f5e15f5c38f8bccdc646b1773b79346aa2b2\",\"dweb:/ipfs/QmYUgjmX61tJ8oUrZjN2sTYr5YYfGTUQY245v17tyBfU9D\"]},\"contracts/L2/L2ToL1MessagePasser.sol\":{\"keccak256\":\"0xa385bda91d75c44f6d8b0bc5a61e1904ed455d98c07b308910ac1265e6536df1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dcbaab318b084e163992187aa87f9250782982c10d69be9e11959090e02cc912\",\"dweb:/ipfs/QmY81HgBPp4vcMigSbWQ8mDizXCQFvjN52BF7nGPc6f9Fm\"]},\"contracts/libraries/Arithmetic.sol\":{\"keccak256\":\"0xc8858039f87e48e6f18c1af8bc0b03e57cfef564acddfd06e4d91e3db7ac5ed6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2fc79af1e844aa6dc1c68067bfe1d359df8d4e9a3e8881afb3bcfcbf68071714\",\"dweb:/ipfs/QmcNC4k8zmvwj4kZizSenTiWbx2DJQPbwqXXLF4iMbkRVD\"]},\"contracts/libraries/Burn.sol\":{\"keccak256\":\"0x54233b226ba6919dc46d438bc790108d8f855001002a1b9c3c37aed7a83e5f3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4051a4baca357a9191a6c9e3aa1593a17b69dd7915966e23e4cb269e9c1d9ed4\",\"dweb:/ipfs/QmadKjGKvxm53abVHQdsxrXBc8e9jXywu6vvhkAgjsx59J\"]},\"contracts/libraries/Constants.sol\":{\"keccak256\":\"0x8c7be28a175eb732995a7f704560163c30261f9f70d377f865c5060882509f5d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f72aba26553b10ca88708e05461691b36b0d2ec7a87f718022fe119ca9c70852\",\"dweb:/ipfs/QmQtDEB1F3D8RsgG63KSJ9t7ZyFLaXc2Av81vKD9y2TMn7\"]},\"contracts/libraries/Encoding.sol\":{\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f18156216c1f9457c2e032a812ad70f2babbc5b89997554ff014d64c483fb2ff\",\"dweb:/ipfs/Qmc5rjMaBFn3jV7XqDrEvRbmatQvJxeVJYA5B5rdcKPkcJ\"]},\"contracts/libraries/Hashing.sol\":{\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6746ed0d26d603568818cc52a29d0209effd69f7e55bd0017a6b91bd6cf319fe\",\"dweb:/ipfs/QmPebCmCELMBRtDDxt5ziEPfRXUh6tfm2qJdwz3iyrDdWN\"]},\"contracts/libraries/Predeploys.sol\":{\"keccak256\":\"0xfc30fb239b5f00284f4b8f578a62f0882597e939335c91ea9bc4aab3070ddc43\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fa132267b3a9d98568b4e02cbb68fe2d2c0ca630826242c1b2293a8fa35bd302\",\"dweb:/ipfs/QmdYvcGbaykP6wyBu5T2obXrWK56xGnfWqbYeeWpTChq3w\"]},\"contracts/libraries/SafeCall.sol\":{\"keccak256\":\"0x6e815b62528d452a4f63040d75ff7a08db8ba8096050a53355fc49abaebdf245\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e27e542a11165c82cbb6961f4d8c2a58527fba1ab915afeeded50e96ce929777\",\"dweb:/ipfs/QmRPXdmUAbL1WHZBvENKWkFuHb9bQyrbiJWwDvzEQBLVi8\"]},\"contracts/libraries/Types.sol\":{\"keccak256\":\"0x4fe8ec920798661a828430bd30dc2715eeb40534ec01c0a7bf41cb4ab422e134\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://74c8471869900bd459358cd990bda1c8d234c06b788804c7049cf465ae1e299f\",\"dweb:/ipfs/QmakcfP6NmbVUQsKqH7rEyJsbiqckigLahw9g74oencEJ7\"]},\"contracts/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://921c44e6a0982b9a4011900fda1bda2c06b7a85894967de98b407a83fe9f90c0\",\"dweb:/ipfs/QmSsHLKDUQ82kpKdqB6VntVGKuPDb4W9VdotsubuqWBzio\"]},\"contracts/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x3c99b1e768cc4c1e064ccc137b1b4d5961bf4edf071be84cc216c5b20f1c00da\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e36b2a6325c2f804d769271575669b62ab2da2df3c81921ac7487399fe02af07\",\"dweb:/ipfs/QmTCmcEKwvD8Xvjyev268Bkz27FC7TJpUbw1nADcsThnUr\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9baf7797439c0ae6512f4639dfc6a1934dbd4e4d7cbb8e63e99264ff47682c9e\",\"dweb:/ipfs/QmawAuhppPyeoZH3rC1uh87xDELa9Lyfw5pYsBqE8myE1m\"]},\"contracts/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"]},\"node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"]},\"node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"]},\"node_modules/@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]},\"node_modules/@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"]},\"node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"]},\"node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"]}},\"version\":1}", - "bytecode": "0x6101006040523480156200001257600080fd5b506040516200219138038062002191833981016040819052620000359162000243565b6001600160a01b038116608052600160a052600460c052600060e0526200005b62000062565b5062000275565b600054600160a81b900460ff16158080156200008b57506000546001600160a01b90910460ff16105b80620000c25750620000a830620001af60201b620013411760201c565b158015620000c25750600054600160a01b900460ff166001145b6200012b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b179055801562000159576000805460ff60a81b1916600160a81b1790555b62000163620001be565b8015620001ac576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6001600160a01b03163b151590565b600054600160a81b900460ff166200022d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000122565b60cc80546001600160a01b03191661dead179055565b6000602082840312156200025657600080fd5b81516001600160a01b03811681146200026e57600080fd5b9392505050565b60805160a05160c05160e051611ecd620002c460003960006106c30152600061069a015260006106710152600081816102a90152818161031a0152818161040b0152610c980152611ecd6000f3fe6080604052600436106101445760003560e01c80638129fc1c116100c0578063a711986911610074578063b28ade2511610059578063b28ade251461036e578063d764ad0b1461038e578063ecc70428146103a157600080fd5b8063a71198691461030b578063b1b1b2091461033e57600080fd5b80638cbeeef2116100a55780638cbeeef2146101e35780639fce812c14610297578063a4e7f8bd146102cb57600080fd5b80638129fc1c1461026b57806383a740741461028057600080fd5b80633f827a5a1161011757806354fd4d50116100fc57806354fd4d50146101f95780635644cfdf1461021b5780636e296e451461023157600080fd5b80633f827a5a146101bb5780634c1d6a69146101e357600080fd5b8063028f85f7146101495780630c5684981461017c5780632828d7e8146101915780633dbb202b146101a6575b600080fd5b34801561015557600080fd5b5061015e601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061015e603f81565b34801561019d57600080fd5b5061015e604081565b6101b96101b4366004611886565b610406565b005b3480156101c757600080fd5b506101d0600181565b60405161ffff9091168152602001610173565b3480156101ef57600080fd5b5061015e619c4081565b34801561020557600080fd5b5061020e61066a565b6040516101739190611965565b34801561022757600080fd5b5061015e61138881565b34801561023d57600080fd5b5061024661070d565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610173565b34801561027757600080fd5b506101b96107f9565b34801561028c57600080fd5b5061015e62030d4081565b3480156102a357600080fd5b506102467f000000000000000000000000000000000000000000000000000000000000000081565b3480156102d757600080fd5b506102fb6102e636600461197f565b60ce6020526000908152604090205460ff1681565b6040519015158152602001610173565b34801561031757600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610246565b34801561034a57600080fd5b506102fb61035936600461197f565b60cb6020526000908152604090205460ff1681565b34801561037a57600080fd5b5061015e610389366004611998565b6109f6565b6101b961039c3660046119ec565b610a64565b3480156103ad57600080fd5b506103f860cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b604051908152602001610173565b61053f7f00000000000000000000000000000000000000000000000000000000000000006104358585856109f6565b347fd764ad0b000000000000000000000000000000000000000000000000000000006104a160cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016104bd9796959493929190611ab7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261135d565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856105c460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516105d6959493929190611b16565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60606106957f00000000000000000000000000000000000000000000000000000000000000006113eb565b6106be7f00000000000000000000000000000000000000000000000000000000000000006113eb565b6106e77f00000000000000000000000000000000000000000000000000000000000000006113eb565b6040516020016106f993929190611b64565b604051602081830303815290604052905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016107dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000547501000000000000000000000000000000000000000000900460ff1615808015610844575060005460017401000000000000000000000000000000000000000090910460ff16105b806108765750303b158015610876575060005474010000000000000000000000000000000000000000900460ff166001145b610902576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107d3565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055801561098857600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b610990611520565b80156109f357600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6000611388619c4080603f610a12604063ffffffff8816611c09565b610a1c9190611c68565b610a27601088611c09565b610a349062030d40611c8f565b610a3e9190611c8f565b610a489190611c8f565b610a529190611c8f565b610a5c9190611c8f565b949350505050565b60f087901c60028110610b1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016107d3565b8061ffff16600003610c14576000610b70878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506115f9915050565b600081815260cb602052604090205490915060ff1615610c12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016107d3565b505b6000610c5a898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061161892505050565b905073ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffeeeeffffffffffffffffffffffffffffffffeeef330181167f000000000000000000000000000000000000000000000000000000000000000090911603610cf257853414610cce57610cce611cbb565b600081815260ce602052604090205460ff1615610ced57610ced611cbb565b610e44565b3415610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016107d3565b600081815260ce602052604090205460ff16610e44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016107d3565b610e4d8761163b565b15610f00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016107d3565b600081815260cb602052604090205460ff1615610f9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016107d3565b610fc085610fb1611388619c40611c8f565b67ffffffffffffffff16611690565b1580610fe6575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b156110ff57600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016110f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016107d3565b5050611338565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a16179055600061119088619c405a6111539190611cea565b8988888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506116ae92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561122757600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a2611334565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3201611334576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016107d3565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fc2b3e5ac0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000169063c2b3e5ac9084906113b390889088908790600401611d01565b6000604051808303818588803b1580156113cc57600080fd5b505af11580156113e0573d6000803e3d6000fd5b505050505050505050565b60608160000361142e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611458578061144281611d49565b91506114519050600a83611d81565b9150611432565b60008167ffffffffffffffff81111561147357611473611d95565b6040519080825280601f01601f19166020018201604052801561149d576020820181803683370190505b5090505b8415610a5c576114b2600183611cea565b91506114bf600a86611dc4565b6114ca906030611dd8565b60f81b8183815181106114df576114df611df0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611519600a86611d81565b94506114a1565b6000547501000000000000000000000000000000000000000000900460ff166115cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107d3565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b6000611607858585856116c8565b805190602001209050949350505050565b6000611628878787878787611761565b8051906020012090509695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff821630148061168a575073ffffffffffffffffffffffffffffffffffffffff8216734200000000000000000000000000000000000016145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b6060848484846040516024016116e19493929190611e1f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b606086868686868660405160240161177e96959493929190611e69565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461182457600080fd5b919050565b60008083601f84011261183b57600080fd5b50813567ffffffffffffffff81111561185357600080fd5b60208301915083602082850101111561186b57600080fd5b9250929050565b803563ffffffff8116811461182457600080fd5b6000806000806060858703121561189c57600080fd5b6118a585611800565b9350602085013567ffffffffffffffff8111156118c157600080fd5b6118cd87828801611829565b90945092506118e0905060408601611872565b905092959194509250565b60005b838110156119065781810151838201526020016118ee565b83811115611915576000848401525b50505050565b600081518084526119338160208601602086016118eb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611978602083018461191b565b9392505050565b60006020828403121561199157600080fd5b5035919050565b6000806000604084860312156119ad57600080fd5b833567ffffffffffffffff8111156119c457600080fd5b6119d086828701611829565b90945092506119e3905060208501611872565b90509250925092565b600080600080600080600060c0888a031215611a0757600080fd5b87359650611a1760208901611800565b9550611a2560408901611800565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611a4f57600080fd5b611a5b8a828b01611829565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611b0960c083018486611a6e565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611b46608083018688611a6e565b905083604083015263ffffffff831660608301529695505050505050565b60008451611b768184602089016118eb565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611bb2816001850160208a016118eb565b60019201918201528351611bcd8160028401602088016118eb565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611c3057611c30611bda565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680611c8357611c83611c39565b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611cb257611cb2611bda565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611cfc57611cfc611bda565b500390565b73ffffffffffffffffffffffffffffffffffffffff8416815267ffffffffffffffff83166020820152606060408201526000611d40606083018461191b565b95945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611d7a57611d7a611bda565b5060010190565b600082611d9057611d90611c39565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082611dd357611dd3611c39565b500690565b60008219821115611deb57611deb611bda565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611e58608083018561191b565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611eb460c083018461191b565b9897505050505050505056fea164736f6c634300080f000a", - "deployedBytecode": "0x6080604052600436106101445760003560e01c80638129fc1c116100c0578063a711986911610074578063b28ade2511610059578063b28ade251461036e578063d764ad0b1461038e578063ecc70428146103a157600080fd5b8063a71198691461030b578063b1b1b2091461033e57600080fd5b80638cbeeef2116100a55780638cbeeef2146101e35780639fce812c14610297578063a4e7f8bd146102cb57600080fd5b80638129fc1c1461026b57806383a740741461028057600080fd5b80633f827a5a1161011757806354fd4d50116100fc57806354fd4d50146101f95780635644cfdf1461021b5780636e296e451461023157600080fd5b80633f827a5a146101bb5780634c1d6a69146101e357600080fd5b8063028f85f7146101495780630c5684981461017c5780632828d7e8146101915780633dbb202b146101a6575b600080fd5b34801561015557600080fd5b5061015e601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061015e603f81565b34801561019d57600080fd5b5061015e604081565b6101b96101b4366004611886565b610406565b005b3480156101c757600080fd5b506101d0600181565b60405161ffff9091168152602001610173565b3480156101ef57600080fd5b5061015e619c4081565b34801561020557600080fd5b5061020e61066a565b6040516101739190611965565b34801561022757600080fd5b5061015e61138881565b34801561023d57600080fd5b5061024661070d565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610173565b34801561027757600080fd5b506101b96107f9565b34801561028c57600080fd5b5061015e62030d4081565b3480156102a357600080fd5b506102467f000000000000000000000000000000000000000000000000000000000000000081565b3480156102d757600080fd5b506102fb6102e636600461197f565b60ce6020526000908152604090205460ff1681565b6040519015158152602001610173565b34801561031757600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610246565b34801561034a57600080fd5b506102fb61035936600461197f565b60cb6020526000908152604090205460ff1681565b34801561037a57600080fd5b5061015e610389366004611998565b6109f6565b6101b961039c3660046119ec565b610a64565b3480156103ad57600080fd5b506103f860cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b604051908152602001610173565b61053f7f00000000000000000000000000000000000000000000000000000000000000006104358585856109f6565b347fd764ad0b000000000000000000000000000000000000000000000000000000006104a160cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016104bd9796959493929190611ab7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261135d565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856105c460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516105d6959493929190611b16565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60606106957f00000000000000000000000000000000000000000000000000000000000000006113eb565b6106be7f00000000000000000000000000000000000000000000000000000000000000006113eb565b6106e77f00000000000000000000000000000000000000000000000000000000000000006113eb565b6040516020016106f993929190611b64565b604051602081830303815290604052905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016107dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084015b60405180910390fd5b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000547501000000000000000000000000000000000000000000900460ff1615808015610844575060005460017401000000000000000000000000000000000000000090910460ff16105b806108765750303b158015610876575060005474010000000000000000000000000000000000000000900460ff166001145b610902576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107d3565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055801561098857600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b610990611520565b80156109f357600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6000611388619c4080603f610a12604063ffffffff8816611c09565b610a1c9190611c68565b610a27601088611c09565b610a349062030d40611c8f565b610a3e9190611c8f565b610a489190611c8f565b610a529190611c8f565b610a5c9190611c8f565b949350505050565b60f087901c60028110610b1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016107d3565b8061ffff16600003610c14576000610b70878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506115f9915050565b600081815260cb602052604090205490915060ff1615610c12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016107d3565b505b6000610c5a898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061161892505050565b905073ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffeeeeffffffffffffffffffffffffffffffffeeef330181167f000000000000000000000000000000000000000000000000000000000000000090911603610cf257853414610cce57610cce611cbb565b600081815260ce602052604090205460ff1615610ced57610ced611cbb565b610e44565b3415610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016107d3565b600081815260ce602052604090205460ff16610e44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016107d3565b610e4d8761163b565b15610f00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016107d3565b600081815260cb602052604090205460ff1615610f9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016107d3565b610fc085610fb1611388619c40611c8f565b67ffffffffffffffff16611690565b1580610fe6575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b156110ff57600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016110f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016107d3565b5050611338565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a16179055600061119088619c405a6111539190611cea565b8988888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506116ae92505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561122757600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a2611334565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3201611334576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016107d3565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6040517fc2b3e5ac0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000169063c2b3e5ac9084906113b390889088908790600401611d01565b6000604051808303818588803b1580156113cc57600080fd5b505af11580156113e0573d6000803e3d6000fd5b505050505050505050565b60608160000361142e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611458578061144281611d49565b91506114519050600a83611d81565b9150611432565b60008167ffffffffffffffff81111561147357611473611d95565b6040519080825280601f01601f19166020018201604052801561149d576020820181803683370190505b5090505b8415610a5c576114b2600183611cea565b91506114bf600a86611dc4565b6114ca906030611dd8565b60f81b8183815181106114df576114df611df0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611519600a86611d81565b94506114a1565b6000547501000000000000000000000000000000000000000000900460ff166115cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107d3565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055565b6000611607858585856116c8565b805190602001209050949350505050565b6000611628878787878787611761565b8051906020012090509695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff821630148061168a575073ffffffffffffffffffffffffffffffffffffffff8216734200000000000000000000000000000000000016145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b6060848484846040516024016116e19493929190611e1f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b606086868686868660405160240161177e96959493929190611e69565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461182457600080fd5b919050565b60008083601f84011261183b57600080fd5b50813567ffffffffffffffff81111561185357600080fd5b60208301915083602082850101111561186b57600080fd5b9250929050565b803563ffffffff8116811461182457600080fd5b6000806000806060858703121561189c57600080fd5b6118a585611800565b9350602085013567ffffffffffffffff8111156118c157600080fd5b6118cd87828801611829565b90945092506118e0905060408601611872565b905092959194509250565b60005b838110156119065781810151838201526020016118ee565b83811115611915576000848401525b50505050565b600081518084526119338160208601602086016118eb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611978602083018461191b565b9392505050565b60006020828403121561199157600080fd5b5035919050565b6000806000604084860312156119ad57600080fd5b833567ffffffffffffffff8111156119c457600080fd5b6119d086828701611829565b90945092506119e3905060208501611872565b90509250925092565b600080600080600080600060c0888a031215611a0757600080fd5b87359650611a1760208901611800565b9550611a2560408901611800565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611a4f57600080fd5b611a5b8a828b01611829565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611b0960c083018486611a6e565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611b46608083018688611a6e565b905083604083015263ffffffff831660608301529695505050505050565b60008451611b768184602089016118eb565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611bb2816001850160208a016118eb565b60019201918201528351611bcd8160028401602088016118eb565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611c3057611c30611bda565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680611c8357611c83611c39565b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611cb257611cb2611bda565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611cfc57611cfc611bda565b500390565b73ffffffffffffffffffffffffffffffffffffffff8416815267ffffffffffffffff83166020820152606060408201526000611d40606083018461191b565b95945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611d7a57611d7a611bda565b5060010190565b600082611d9057611d90611c39565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082611dd357611dd3611c39565b500690565b60008219821115611deb57611deb611bda565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611e58608083018561191b565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611eb460c083018461191b565b9897505050505050505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "baseGas(bytes,uint32)": { - "params": { - "_message": "Message to compute the amount of required gas for.", - "_minGasLimit": "Minimum desired gas limit when message goes to target." - }, - "returns": { - "_0": "Amount of gas required to guarantee message receipt." - } - }, - "constructor": { - "params": { - "_l1CrossDomainMessenger": "Address of the L1CrossDomainMessenger contract." - } - }, - "l1CrossDomainMessenger()": { - "returns": { - "_0": "Address of the L1CrossDomainMessenger contract." - } - }, - "messageNonce()": { - "returns": { - "_0": "Nonce of the next message to be sent, with added message version." - } - }, - "relayMessage(uint256,address,address,uint256,uint256,bytes)": { - "params": { - "_message": "Message to send to the target.", - "_minGasLimit": "Minimum amount of gas that the message can be executed with.", - "_nonce": "Nonce of the message being relayed.", - "_sender": "Address of the user who sent the message.", - "_target": "Address that the message is targeted at.", - "_value": "ETH value to send with the message." - } - }, - "sendMessage(address,bytes,uint32)": { - "params": { - "_message": "Message to trigger the target address with.", - "_minGasLimit": "Minimum gas limit that the message can be executed with.", - "_target": "Target contract or wallet address." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - }, - "xDomainMessageSender()": { - "returns": { - "_0": "Address of the sender of the currently executing message on the other chain." - } - } - }, - "title": "L2CrossDomainMessenger" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MESSAGE_VERSION()": { - "notice": "Current message version identifier." - }, - "MIN_GAS_CALLDATA_OVERHEAD()": { - "notice": "Extra gas added to base gas for each byte of calldata in a message." - }, - "MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR()": { - "notice": "Denominator for dynamic overhead added to the base gas for a message." - }, - "MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR()": { - "notice": "Numerator for dynamic overhead added to the base gas for a message." - }, - "OTHER_MESSENGER()": { - "notice": "Address of the paired CrossDomainMessenger contract on the other chain." - }, - "RELAY_CALL_OVERHEAD()": { - "notice": "Gas reserved for performing the external call in `relayMessage`." - }, - "RELAY_CONSTANT_OVERHEAD()": { - "notice": "Constant overhead added to the base gas for a message." - }, - "RELAY_GAS_CHECK_BUFFER()": { - "notice": "Gas reserved for the execution between the `hasMinGas` check and the external call in `relayMessage`." - }, - "RELAY_RESERVED_GAS()": { - "notice": "Gas reserved for finalizing the execution of `relayMessage` after the safe call." - }, - "baseGas(bytes,uint32)": { - "notice": "Computes the amount of gas required to guarantee that a given message will be received on the other chain without running out of gas. Guaranteeing that a message will not run out of gas is important because this ensures that a message can always be replayed on the other chain if it fails to execute completely." - }, - "failedMessages(bytes32)": { - "notice": "Mapping of message hashes to a boolean if and only if the message has failed to be executed at least once. A message will not be present in this mapping if it successfully executed on the first attempt." - }, - "initialize()": { - "notice": "Initializer." - }, - "messageNonce()": { - "notice": "Retrieves the next message nonce. Message version will be added to the upper two bytes of the message nonce. Message version allows us to treat messages as having different structures." - }, - "relayMessage(uint256,address,address,uint256,uint256,bytes)": { - "notice": "Relays a message that was sent by the other CrossDomainMessenger contract. Can only be executed via cross-chain call from the other messenger OR if the message was already received once and is currently being replayed." - }, - "sendMessage(address,bytes,uint32)": { - "notice": "Sends a message to some target address on the other chain. Note that if the call always reverts, then the message will be unrelayable, and any ETH sent will be permanently locked. The same will occur if the target on the other chain is considered unsafe (see the _isUnsafeTarget() function)." - }, - "successfulMessages(bytes32)": { - "notice": "Mapping of message hashes to boolean receipt values. Note that a message will only be present in this mapping if it has successfully been relayed on this chain, and can therefore not be relayed again." - }, - "version()": { - "notice": "Returns the full semver contract version." - }, - "xDomainMessageSender()": { - "notice": "Retrieves the address of the contract or wallet that initiated the currently executing message on the other chain. Will throw an error if there is no message currently being executed. Allows the recipient of a call to see who triggered it." - } - }, - "events": { - "FailedRelayedMessage(bytes32)": { - "notice": "Emitted whenever a message fails to be relayed on this chain." - }, - "RelayedMessage(bytes32)": { - "notice": "Emitted whenever a message is successfully relayed on this chain." - }, - "SentMessage(address,address,bytes,uint256,uint256)": { - "notice": "Emitted whenever a message is sent to the other chain." - }, - "SentMessageExtension1(address,uint256)": { - "notice": "Additional event data to emit, required as of Bedrock. Cannot be merged with the SentMessage event without breaking the ABI of this contract, this is good enough." - } - }, - "notice": "The L2CrossDomainMessenger is a high-level interface for message passing between L1 and L2 on the L2 side. Users are generally encouraged to use this contract instead of lower level message passing contracts." - }, - "storageLayout": { - "storage": [ - { - "astId": 45898, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "spacer_0_0_20", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 49236, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "_initialized", - "offset": 20, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 49239, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "_initializing", - "offset": 21, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 45905, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "spacer_1_0_1600", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 45908, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "spacer_51_0_20", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 45913, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "spacer_52_0_1568", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 45916, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "spacer_101_0_1", - "offset": 0, - "slot": "101", - "type": "t_bool" - }, - { - "astId": 45921, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "spacer_102_0_1568", - "offset": 0, - "slot": "102", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 45924, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "spacer_151_0_32", - "offset": 0, - "slot": "151", - "type": "t_uint256" - }, - { - "astId": 45929, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "spacer_152_0_1568", - "offset": 0, - "slot": "152", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 45934, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "spacer_201_0_32", - "offset": 0, - "slot": "201", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 45939, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "spacer_202_0_32", - "offset": 0, - "slot": "202", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 45987, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "successfulMessages", - "offset": 0, - "slot": "203", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 45990, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "xDomainMsgSender", - "offset": 0, - "slot": "204", - "type": "t_address" - }, - { - "astId": 45993, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "msgNonce", - "offset": 0, - "slot": "205", - "type": "t_uint240" - }, - { - "astId": 45998, - "contract": "contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger", - "label": "failedMessages", - "offset": 0, - "slot": "206", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 46003, - "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", - "base": "t_uint256" - }, - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_array(t_uint256)50_storage": { - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes32,t_bool)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_uint240": { - "encoding": "inplace", - "label": "uint240", - "numberOfBytes": "30" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/L2ERC721Bridge.json b/packages/contracts-bedrock/deployments/optimism-goerli/L2ERC721Bridge.json deleted file mode 100644 index 3d734d3beb81..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/L2ERC721Bridge.json +++ /dev/null @@ -1,421 +0,0 @@ -{ - "address": "0x5Eb0EE8d7f29856F50b5c97F9CF1225491404bF1", - "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": [], - "name": "MESSENGER", - "outputs": [ - { - "internalType": "contract CrossDomainMessenger", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OTHER_BRIDGE", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "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": [], - "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": "0xb1558531b8c3a4d2d271b768d63583b8bb189dc945c0881fed0548142fc4927f", - "receipt": { - "to": null, - "from": "0xf80267194936da1E98dB10bcE06F3147D580a62e", - "contractAddress": "0x5Eb0EE8d7f29856F50b5c97F9CF1225491404bF1", - "transactionIndex": 3, - "gasUsed": "1318890", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xa1e924a48dcf7d9bb30b05a140979191dad27527c6f0a7bbd34e4109132a13e1", - "transactionHash": "0xb1558531b8c3a4d2d271b768d63583b8bb189dc945c0881fed0548142fc4927f", - "logs": [], - "blockNumber": 8579680, - "cumulativeGasUsed": "1875901", - "status": 1, - "byzantium": true - }, - "args": [ - "0x4200000000000000000000000000000000000007", - "0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9" - ], - "numDeployments": 1, - "solcInputHash": "2d538e296d12ca6101a896ac2e894043", - "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\":[],\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":[],\"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.1.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.\"}},\"messenger()\":{\"custom:legacy\":\"@notice Legacy getter for messenger contract.\",\"returns\":{\"_0\":\"Messenger contract on this domain.\"}},\"otherBridge()\":{\"custom:legacy\":\"@notice Legacy getter for other bridge address.\",\"returns\":{\"_0\":\"Address of the bridge on the other network.\"}},\"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\":{\"MESSENGER()\":{\"notice\":\"Messenger contract on this domain.\"},\"OTHER_BRIDGE()\":{\"notice\":\"Address of the bridge on the other network.\"},\"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.\"},\"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\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/L1/L1ERC721Bridge.sol\":{\"keccak256\":\"0xf66d53c1bc80c9a204ce8752f26a6fdaa247f6fd80438020b889e0f1c8079b75\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://eab9be6161db4e3e0e598cdaf5e8f9143b4f4bfdbc65e335c5d948b00dc4a1cb\",\"dweb:/ipfs/QmaaLcDguxg1XyCNmbtKMkuTi4ngK8qCUFb1NkurJZGAhZ\"]},\"contracts/L1/ResourceMetering.sol\":{\"keccak256\":\"0xbd7b9532a70d8c842bfce0ea971be50d02fbbf0227c9ad55c71ac68d438010f4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4969f478dd54e89392cda2ea0c5edcf1be55a5dee43a0e410527b6e3bcb85c88\",\"dweb:/ipfs/QmU2crAojw8DRDsz7PAPrereazjFsKh9wtfTpTDVh6NLfW\"]},\"contracts/L2/L2ERC721Bridge.sol\":{\"keccak256\":\"0x94d240acff616f7ec4281bb3c2d3cace1c398bfca754fb3ca7bc795c875b4f10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7613d2506fc31214e3e36c8cd9b0845c9bcaaf063be6fc611ce8efe3fce71584\",\"dweb:/ipfs/QmX8eBBgEWvUPXgpQsPQN3ZhZbwMawFQRuqyTF8Rcv1u1S\"]},\"contracts/libraries/Arithmetic.sol\":{\"keccak256\":\"0xc8858039f87e48e6f18c1af8bc0b03e57cfef564acddfd06e4d91e3db7ac5ed6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2fc79af1e844aa6dc1c68067bfe1d359df8d4e9a3e8881afb3bcfcbf68071714\",\"dweb:/ipfs/QmcNC4k8zmvwj4kZizSenTiWbx2DJQPbwqXXLF4iMbkRVD\"]},\"contracts/libraries/Burn.sol\":{\"keccak256\":\"0x54233b226ba6919dc46d438bc790108d8f855001002a1b9c3c37aed7a83e5f3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4051a4baca357a9191a6c9e3aa1593a17b69dd7915966e23e4cb269e9c1d9ed4\",\"dweb:/ipfs/QmadKjGKvxm53abVHQdsxrXBc8e9jXywu6vvhkAgjsx59J\"]},\"contracts/libraries/Constants.sol\":{\"keccak256\":\"0x8c7be28a175eb732995a7f704560163c30261f9f70d377f865c5060882509f5d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f72aba26553b10ca88708e05461691b36b0d2ec7a87f718022fe119ca9c70852\",\"dweb:/ipfs/QmQtDEB1F3D8RsgG63KSJ9t7ZyFLaXc2Av81vKD9y2TMn7\"]},\"contracts/libraries/Encoding.sol\":{\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f18156216c1f9457c2e032a812ad70f2babbc5b89997554ff014d64c483fb2ff\",\"dweb:/ipfs/Qmc5rjMaBFn3jV7XqDrEvRbmatQvJxeVJYA5B5rdcKPkcJ\"]},\"contracts/libraries/Hashing.sol\":{\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6746ed0d26d603568818cc52a29d0209effd69f7e55bd0017a6b91bd6cf319fe\",\"dweb:/ipfs/QmPebCmCELMBRtDDxt5ziEPfRXUh6tfm2qJdwz3iyrDdWN\"]},\"contracts/libraries/SafeCall.sol\":{\"keccak256\":\"0x6e815b62528d452a4f63040d75ff7a08db8ba8096050a53355fc49abaebdf245\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e27e542a11165c82cbb6961f4d8c2a58527fba1ab915afeeded50e96ce929777\",\"dweb:/ipfs/QmRPXdmUAbL1WHZBvENKWkFuHb9bQyrbiJWwDvzEQBLVi8\"]},\"contracts/libraries/Types.sol\":{\"keccak256\":\"0x4fe8ec920798661a828430bd30dc2715eeb40534ec01c0a7bf41cb4ab422e134\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://74c8471869900bd459358cd990bda1c8d234c06b788804c7049cf465ae1e299f\",\"dweb:/ipfs/QmakcfP6NmbVUQsKqH7rEyJsbiqckigLahw9g74oencEJ7\"]},\"contracts/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://921c44e6a0982b9a4011900fda1bda2c06b7a85894967de98b407a83fe9f90c0\",\"dweb:/ipfs/QmSsHLKDUQ82kpKdqB6VntVGKuPDb4W9VdotsubuqWBzio\"]},\"contracts/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x3c99b1e768cc4c1e064ccc137b1b4d5961bf4edf071be84cc216c5b20f1c00da\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e36b2a6325c2f804d769271575669b62ab2da2df3c81921ac7487399fe02af07\",\"dweb:/ipfs/QmTCmcEKwvD8Xvjyev268Bkz27FC7TJpUbw1nADcsThnUr\"]},\"contracts/universal/ERC721Bridge.sol\":{\"keccak256\":\"0xb47389fbec63e85b2d04fce538fe1b8e048278d631729458b70e32a31971c092\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7133f38e3d8d1911738057b1d4523989abd7cd029797b1d3b59cda29d42e9704\",\"dweb:/ipfs/QmUN31CLssESHrBwWA3WYP5L2xESo9Q4aq2Exua1e8UtUW\"]},\"contracts/universal/IOptimismMintableERC721.sol\":{\"keccak256\":\"0xf1a3dd4452df8882a65a31c5e2e8de7872b08cf078be7a5a7da51e6f75c53ad3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b09a2560cae35ca4789fe1ff5edb2bae9fa7dcda115a55f7ccdcc974a2e37526\",\"dweb:/ipfs/QmPQeTvrJ4SJpng5VGZNMf1u85NWxrdus4gGn8xYkHddKM\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9baf7797439c0ae6512f4639dfc6a1934dbd4e4d7cbb8e63e99264ff47682c9e\",\"dweb:/ipfs/QmawAuhppPyeoZH3rC1uh87xDELa9Lyfw5pYsBqE8myE1m\"]},\"node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"]},\"node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"]},\"node_modules/@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"keccak256\":\"0xed6a749c5373af398105ce6ee3ac4763aa450ea7285d268c85d9eeca809cdb1f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://20a97f891d06f0fe91560ea1a142aaa26fdd22bed1b51606b7d48f670deeb50f\",\"dweb:/ipfs/QmTbCtZKChpaX5H2iRiTDMcSz29GSLCpTCDgJpcMR4wg8x\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://26fef835622b46a5ba08b3ef6b46a22e94b5f285d0f0fb66b703bd30217d2c34\",\"dweb:/ipfs/QmZ548qdwfL1qF7aXz3xh1GCdTiST81kGGuKRqVUfYmPZR\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"]},\"node_modules/@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"]},\"node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"]},\"node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"]}},\"version\":1}", - "bytecode": "0x6101206040523480156200001257600080fd5b506040516200190c3803806200190c833981016040819052620000359162000162565b600180600084846001600160a01b038216620000ad5760405162461bcd60e51b815260206004820152602c60248201527f4552433732314272696467653a206d657373656e6765722063616e6e6f74206260448201526b65206164647265737328302960a01b60648201526084015b60405180910390fd5b6001600160a01b0381166200011d5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314272696467653a206f74686572206272696467652063616e6e6f60448201526e74206265206164647265737328302960881b6064820152608401620000a4565b6001600160a01b039182166080521660a05260c09290925260e05261010052506200019a9050565b80516001600160a01b03811681146200015d57600080fd5b919050565b600080604083850312156200017657600080fd5b620001818362000145565b9150620001916020840162000145565b90509250929050565b60805160a05160c05160e051610100516116fd6200020f60003960006102a2015260006102790152600061025001526000818161011b015281816101790152818161032e0152610dc101526000818160a40152818161014201528181610304015281816103650152610d9401526116fd6000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80637f46ddb21161005b5780637f46ddb214610116578063927ede2d1461013d578063aa55745214610164578063c89701a21461017757600080fd5b80633687011a1461008d5780633cb747bf146100a257806354fd4d50146100ee578063761f449314610103575b600080fd5b6100a061009b3660046111c8565b61019d565b005b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f6610249565b6040516100e591906112c5565b6100a06101113660046112d8565b6102ec565b6100c47f000000000000000000000000000000000000000000000000000000000000000081565b6100c47f000000000000000000000000000000000000000000000000000000000000000081565b6100a0610172366004611370565b610853565b7f00000000000000000000000000000000000000000000000000000000000000006100c4565b333b15610231576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b610241868633338888888861090f565b505050505050565b60606102747f0000000000000000000000000000000000000000000000000000000000000000610ead565b61029d7f0000000000000000000000000000000000000000000000000000000000000000610ead565b6102c67f0000000000000000000000000000000000000000000000000000000000000000610ead565b6040516020016102d8939291906113e7565b604051602081830303815290604052905090565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561040a57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103f2919061145d565b73ffffffffffffffffffffffffffffffffffffffff16145b610496576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f7468657220627269646765006064820152608401610228565b3073ffffffffffffffffffffffffffffffffffffffff88160361053b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c66000000000000000000000000000000000000000000006064820152608401610228565b610565877f74259ebf00000000000000000000000000000000000000000000000000000000610fea565b6105f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e20696e746560448201527f7266616365206973206e6f7420636f6d706c69616e74000000000000000000006064820152608401610228565b8673ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561063c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610660919061145d565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610740576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4c324552433732314272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433732312060648201527f6c6f63616c20746f6b656e000000000000000000000000000000000000000000608482015260a401610228565b6040517fa144819400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526024820185905288169063a144819490604401600060405180830381600087803b1580156107b057600080fd5b505af11580156107c4573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac8787878760405161084294939291906114c3565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff85166108f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f742062652061646472657373283029000000000000000000000000000000006064820152608401610228565b610906878733888888888861090f565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff87166109b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f7420626520616464726573732830290000000000000000000000000000006064820152608401610228565b6040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff891690636352211e90602401602060405180830381865afa158015610a1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a41919061145d565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324552433732314272696467653a205769746864726177616c206973206e6f60448201527f74206265696e6720696e69746961746564206279204e4654206f776e657200006064820152608401610228565b60008873ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6c919061145d565b90508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610c29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e20646f6560448201527f73206e6f74206d6174636820676976656e2076616c75650000000000000000006064820152608401610228565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152602482018790528a1690639dc29fac90604401600060405180830381600087803b158015610c9957600080fd5b505af1158015610cad573d6000803e3d6000fd5b50505050600063761f449360e01b828b8a8a8a8989604051602401610cd89796959493929190611503565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f3dbb202b00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690633dbb202b90610ded907f00000000000000000000000000000000000000000000000000000000000000009085908a90600401611560565b600060405180830381600087803b158015610e0757600080fd5b505af1158015610e1b573d6000803e3d6000fd5b505050508773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a58a8a8989604051610e9994939291906114c3565b60405180910390a450505050505050505050565b606081600003610ef057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610f1a5780610f04816115d4565b9150610f139050600a8361163b565b9150610ef4565b60008167ffffffffffffffff811115610f3557610f3561164f565b6040519080825280601f01601f191660200182016040528015610f5f576020820181803683370190505b5090505b8415610fe257610f7460018361167e565b9150610f81600a86611695565b610f8c9060306116a9565b60f81b818381518110610fa157610fa16116c1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610fdb600a8661163b565b9450610f63565b949350505050565b6000610ff58361100d565b801561100657506110068383611072565b9392505050565b6000611039827f01ffc9a700000000000000000000000000000000000000000000000000000000611072565b801561106c575061106a827fffffffff00000000000000000000000000000000000000000000000000000000611072565b155b92915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d9150600051905082801561112a575060208210155b80156111365750600081115b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461116357600080fd5b50565b803563ffffffff8116811461117a57600080fd5b919050565b60008083601f84011261119157600080fd5b50813567ffffffffffffffff8111156111a957600080fd5b6020830191508360208285010111156111c157600080fd5b9250929050565b60008060008060008060a087890312156111e157600080fd5b86356111ec81611141565b955060208701356111fc81611141565b94506040870135935061121160608801611166565b9250608087013567ffffffffffffffff81111561122d57600080fd5b61123989828a0161117f565b979a9699509497509295939492505050565b60005b8381101561126657818101518382015260200161124e565b83811115611275576000848401525b50505050565b6000815180845261129381602086016020860161124b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611006602083018461127b565b600080600080600080600060c0888a0312156112f357600080fd5b87356112fe81611141565b9650602088013561130e81611141565b9550604088013561131e81611141565b9450606088013561132e81611141565b93506080880135925060a088013567ffffffffffffffff81111561135157600080fd5b61135d8a828b0161117f565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561138b57600080fd5b873561139681611141565b965060208801356113a681611141565b955060408801356113b681611141565b9450606088013593506113cb60808901611166565b925060a088013567ffffffffffffffff81111561135157600080fd5b600084516113f981846020890161124b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611435816001850160208a0161124b565b6001920191820152835161145081600284016020880161124b565b0160020195945050505050565b60006020828403121561146f57600080fd5b815161100681611141565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006114f960608301848661147a565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261155360c08301848661147a565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061158f606083018561127b565b905063ffffffff83166040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611605576116056115a5565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261164a5761164a61160c565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015611690576116906115a5565b500390565b6000826116a4576116a461160c565b500690565b600082198211156116bc576116bc6115a5565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c80637f46ddb21161005b5780637f46ddb214610116578063927ede2d1461013d578063aa55745214610164578063c89701a21461017757600080fd5b80633687011a1461008d5780633cb747bf146100a257806354fd4d50146100ee578063761f449314610103575b600080fd5b6100a061009b3660046111c8565b61019d565b005b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f6610249565b6040516100e591906112c5565b6100a06101113660046112d8565b6102ec565b6100c47f000000000000000000000000000000000000000000000000000000000000000081565b6100c47f000000000000000000000000000000000000000000000000000000000000000081565b6100a0610172366004611370565b610853565b7f00000000000000000000000000000000000000000000000000000000000000006100c4565b333b15610231576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b610241868633338888888861090f565b505050505050565b60606102747f0000000000000000000000000000000000000000000000000000000000000000610ead565b61029d7f0000000000000000000000000000000000000000000000000000000000000000610ead565b6102c67f0000000000000000000000000000000000000000000000000000000000000000610ead565b6040516020016102d8939291906113e7565b604051602081830303815290604052905090565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561040a57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103f2919061145d565b73ffffffffffffffffffffffffffffffffffffffff16145b610496576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f7468657220627269646765006064820152608401610228565b3073ffffffffffffffffffffffffffffffffffffffff88160361053b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c66000000000000000000000000000000000000000000006064820152608401610228565b610565877f74259ebf00000000000000000000000000000000000000000000000000000000610fea565b6105f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e20696e746560448201527f7266616365206973206e6f7420636f6d706c69616e74000000000000000000006064820152608401610228565b8673ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561063c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610660919061145d565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610740576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4c324552433732314272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433732312060648201527f6c6f63616c20746f6b656e000000000000000000000000000000000000000000608482015260a401610228565b6040517fa144819400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526024820185905288169063a144819490604401600060405180830381600087803b1580156107b057600080fd5b505af11580156107c4573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac8787878760405161084294939291906114c3565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff85166108f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f742062652061646472657373283029000000000000000000000000000000006064820152608401610228565b610906878733888888888861090f565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff87166109b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f7420626520616464726573732830290000000000000000000000000000006064820152608401610228565b6040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff891690636352211e90602401602060405180830381865afa158015610a1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a41919061145d565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324552433732314272696467653a205769746864726177616c206973206e6f60448201527f74206265696e6720696e69746961746564206279204e4654206f776e657200006064820152608401610228565b60008873ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6c919061145d565b90508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610c29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e20646f6560448201527f73206e6f74206d6174636820676976656e2076616c75650000000000000000006064820152608401610228565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152602482018790528a1690639dc29fac90604401600060405180830381600087803b158015610c9957600080fd5b505af1158015610cad573d6000803e3d6000fd5b50505050600063761f449360e01b828b8a8a8a8989604051602401610cd89796959493929190611503565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f3dbb202b00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690633dbb202b90610ded907f00000000000000000000000000000000000000000000000000000000000000009085908a90600401611560565b600060405180830381600087803b158015610e0757600080fd5b505af1158015610e1b573d6000803e3d6000fd5b505050508773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a58a8a8989604051610e9994939291906114c3565b60405180910390a450505050505050505050565b606081600003610ef057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610f1a5780610f04816115d4565b9150610f139050600a8361163b565b9150610ef4565b60008167ffffffffffffffff811115610f3557610f3561164f565b6040519080825280601f01601f191660200182016040528015610f5f576020820181803683370190505b5090505b8415610fe257610f7460018361167e565b9150610f81600a86611695565b610f8c9060306116a9565b60f81b818381518110610fa157610fa16116c1565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610fdb600a8661163b565b9450610f63565b949350505050565b6000610ff58361100d565b801561100657506110068383611072565b9392505050565b6000611039827f01ffc9a700000000000000000000000000000000000000000000000000000000611072565b801561106c575061106a827fffffffff00000000000000000000000000000000000000000000000000000000611072565b155b92915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d9150600051905082801561112a575060208210155b80156111365750600081115b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461116357600080fd5b50565b803563ffffffff8116811461117a57600080fd5b919050565b60008083601f84011261119157600080fd5b50813567ffffffffffffffff8111156111a957600080fd5b6020830191508360208285010111156111c157600080fd5b9250929050565b60008060008060008060a087890312156111e157600080fd5b86356111ec81611141565b955060208701356111fc81611141565b94506040870135935061121160608801611166565b9250608087013567ffffffffffffffff81111561122d57600080fd5b61123989828a0161117f565b979a9699509497509295939492505050565b60005b8381101561126657818101518382015260200161124e565b83811115611275576000848401525b50505050565b6000815180845261129381602086016020860161124b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611006602083018461127b565b600080600080600080600060c0888a0312156112f357600080fd5b87356112fe81611141565b9650602088013561130e81611141565b9550604088013561131e81611141565b9450606088013561132e81611141565b93506080880135925060a088013567ffffffffffffffff81111561135157600080fd5b61135d8a828b0161117f565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561138b57600080fd5b873561139681611141565b965060208801356113a681611141565b955060408801356113b681611141565b9450606088013593506113cb60808901611166565b925060a088013567ffffffffffffffff81111561135157600080fd5b600084516113f981846020890161124b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611435816001850160208a0161124b565b6001920191820152835161145081600284016020880161124b565b0160020195945050505050565b60006020828403121561146f57600080fd5b815161100681611141565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006114f960608301848661147a565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261155360c08301848661147a565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061158f606083018561127b565b905063ffffffff83166040830152949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611605576116056115a5565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261164a5761164a61160c565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015611690576116906115a5565b500390565b6000826116a4576116a461160c565b500690565b600082198211156116bc576116bc6115a5565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "bridgeERC721(address,address,uint256,uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.", - "_localToken": "Address of the ERC721 on this domain.", - "_minGasLimit": "Minimum gas limit for the bridge message on the other domain.", - "_remoteToken": "Address of the ERC721 on the remote domain.", - "_tokenId": "Token ID to bridge." - } - }, - "bridgeERC721To(address,address,address,uint256,uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.", - "_localToken": "Address of the ERC721 on this domain.", - "_minGasLimit": "Minimum gas limit for the bridge message on the other domain.", - "_remoteToken": "Address of the ERC721 on the remote domain.", - "_to": "Address to receive the token on the other domain.", - "_tokenId": "Token ID to bridge." - } - }, - "constructor": { - "params": { - "_messenger": "Address of the CrossDomainMessenger on this network.", - "_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." - } - }, - "messenger()": { - "returns": { - "_0": "Messenger contract on this domain." - } - }, - "otherBridge()": { - "returns": { - "_0": "Address of the bridge on the other network." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "title": "L2ERC721Bridge" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MESSENGER()": { - "notice": "Messenger contract on this domain." - }, - "OTHER_BRIDGE()": { - "notice": "Address of the bridge on the other network." - }, - "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." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "events": { - "ERC721BridgeFinalized(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC721 bridge from the other network is finalized." - }, - "ERC721BridgeInitiated(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC721 bridge to the other network is initiated." - } - }, - "notice": "The 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." - }, - "storageLayout": { - "storage": [ - { - "astId": 46438, - "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": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/L2ERC721BridgeProxy.json b/packages/contracts-bedrock/deployments/optimism-goerli/L2ERC721BridgeProxy.json deleted file mode 100644 index 7b340b91992b..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/L2ERC721BridgeProxy.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "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-bedrock/deployments/optimism-goerli/L2StandardBridge.json b/packages/contracts-bedrock/deployments/optimism-goerli/L2StandardBridge.json deleted file mode 100644 index 3053c165c6a4..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/L2StandardBridge.json +++ /dev/null @@ -1,889 +0,0 @@ -{ - "address": "0x26A77636eD9A97BBDE9740bed362bFCE5CaB8e10", - "abi": [ - { - "inputs": [ - { - "internalType": "address payable", - "name": "_otherBridge", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l1Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "DepositFinalized", - "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": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20BridgeFinalized", - "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": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20BridgeInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHBridgeFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHBridgeInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l1Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "WithdrawalInitiated", - "type": "event" - }, - { - "inputs": [], - "name": "MESSENGER", - "outputs": [ - { - "internalType": "contract CrossDomainMessenger", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OTHER_BRIDGE", - "outputs": [ - { - "internalType": "contract StandardBridge", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_localToken", - "type": "address" - }, - { - "internalType": "address", - "name": "_remoteToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeERC20", - "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": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeERC20To", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeETH", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeETHTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "deposits", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "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": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeBridgeERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeBridgeETH", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeDeposit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "l1TokenBridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "messenger", - "outputs": [ - { - "internalType": "contract CrossDomainMessenger", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "withdrawTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0x7aa83de19846f2e702d3ff6a51ac9aa273497c3abc49c414c170c43434239265", - "receipt": { - "to": null, - "from": "0xf80267194936da1E98dB10bcE06F3147D580a62e", - "contractAddress": "0x26A77636eD9A97BBDE9740bed362bFCE5CaB8e10", - "transactionIndex": 1, - "gasUsed": "2401526", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x169e42b58c89087b3b3ab20e52edc28b06e93bc3cd21a9ab044a95149e35d140", - "transactionHash": "0x7aa83de19846f2e702d3ff6a51ac9aa273497c3abc49c414c170c43434239265", - "logs": [], - "blockNumber": 8579669, - "cumulativeGasUsed": "2452027", - "status": 1, - "byzantium": true - }, - "args": [ - "0x636Af16bf2f682dD3109e60102b8E1A089FedAa8" - ], - "numDeployments": 1, - "solcInputHash": "2d538e296d12ca6101a896ac2e894043", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_otherBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"DepositFinalized\",\"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\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC20BridgeFinalized\",\"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\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ERC20BridgeInitiated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ETHBridgeFinalized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ETHBridgeInitiated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"WithdrawalInitiated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"contract StandardBridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"bridgeERC20\",\"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\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"bridgeERC20To\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"bridgeETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"bridgeETHTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"finalizeBridgeERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"finalizeBridgeETH\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"finalizeDeposit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1TokenBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"custom:proxied\":\"@custom:predeploy 0x4200000000000000000000000000000000000010\",\"events\":{\"DepositFinalized(address,address,address,address,uint256,bytes)\":{\"custom:legacy\":\"@notice Emitted whenever an ERC20 deposit is finalized.\",\"params\":{\"amount\":\"Amount of the ERC20 deposited.\",\"extraData\":\"Extra data attached to the deposit.\",\"from\":\"Address of the depositor.\",\"l1Token\":\"Address of the token on L1.\",\"l2Token\":\"Address of the corresponding token on L2.\",\"to\":\"Address of the recipient on L2.\"}},\"WithdrawalInitiated(address,address,address,address,uint256,bytes)\":{\"custom:legacy\":\"@notice Emitted whenever a withdrawal from L2 to L1 is initiated.\",\"params\":{\"amount\":\"Amount of the ERC20 withdrawn.\",\"extraData\":\"Extra data attached to the withdrawal.\",\"from\":\"Address of the withdrawer.\",\"l1Token\":\"Address of the token on L1.\",\"l2Token\":\"Address of the corresponding token on L2.\",\"to\":\"Address of the recipient on L1.\"}}},\"kind\":\"dev\",\"methods\":{\"bridgeERC20(address,address,uint256,uint32,bytes)\":{\"params\":{\"_amount\":\"Amount of local tokens to deposit.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\"}},\"bridgeERC20To(address,address,address,uint256,uint32,bytes)\":{\"params\":{\"_amount\":\"Amount of local tokens to deposit.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\",\"_to\":\"Address of the receiver.\"}},\"bridgeETH(uint32,bytes)\":{\"params\":{\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\"}},\"bridgeETHTo(address,uint32,bytes)\":{\"params\":{\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_to\":\"Address of the receiver.\"}},\"constructor\":{\"custom:semver\":\"1.1.0\",\"params\":{\"_otherBridge\":\"Address of the L1StandardBridge.\"}},\"finalizeBridgeERC20(address,address,address,address,uint256,bytes)\":{\"params\":{\"_amount\":\"Amount of the ERC20 being bridged.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_from\":\"Address of the sender.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\",\"_to\":\"Address of the receiver.\"}},\"finalizeBridgeETH(address,address,uint256,bytes)\":{\"params\":{\"_amount\":\"Amount of ETH being bridged.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_from\":\"Address of the sender.\",\"_to\":\"Address of the receiver.\"}},\"finalizeDeposit(address,address,address,address,uint256,bytes)\":{\"custom:legacy\":\"@notice Finalizes a deposit from L1 to L2. To finalize a deposit of ether, use address(0) and the l1Token and the Legacy ERC20 ether predeploy address as the l2Token.\",\"params\":{\"_amount\":\"Amount of the tokens being deposited.\",\"_extraData\":\"Extra data attached to the deposit.\",\"_from\":\"Address of the depositor.\",\"_l1Token\":\"Address of the L1 token to deposit.\",\"_l2Token\":\"Address of the corresponding L2 token.\",\"_to\":\"Address of the recipient.\"}},\"l1TokenBridge()\":{\"custom:legacy\":\"@notice Retrieves the access of the corresponding L1 bridge contract.\",\"returns\":{\"_0\":\"Address of the corresponding L1 bridge contract.\"}},\"messenger()\":{\"custom:legacy\":\"@notice Legacy getter for messenger contract.\",\"returns\":{\"_0\":\"Messenger contract on this domain.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}},\"withdraw(address,uint256,uint32,bytes)\":{\"custom:legacy\":\"@notice Initiates a withdrawal from L2 to L1. This function only works with OptimismMintableERC20 tokens or ether. Use the `bridgeERC20` function to bridge native L2 tokens to L1.\",\"params\":{\"_amount\":\"Amount of the L2 token to withdraw.\",\"_extraData\":\"Extra data attached to the withdrawal.\",\"_l2Token\":\"Address of the L2 token to withdraw.\",\"_minGasLimit\":\"Minimum gas limit to use for the transaction.\"}},\"withdrawTo(address,address,uint256,uint32,bytes)\":{\"custom:legacy\":\"@notice Initiates a withdrawal from L2 to L1 to a target account on L1. Note that if ETH is sent to a contract on L1 and the call fails, then that ETH will be locked in the L1StandardBridge. ETH may be recoverable if the call can be successfully replayed by increasing the amount of gas supplied to the call. If the call will fail for any amount of gas, then the ETH will be locked permanently. This function only works with OptimismMintableERC20 tokens or ether. Use the `bridgeERC20To` function to bridge native L2 tokens to L1.\",\"params\":{\"_amount\":\"Amount of the L2 token to withdraw.\",\"_extraData\":\"Extra data attached to the withdrawal.\",\"_l2Token\":\"Address of the L2 token to withdraw.\",\"_minGasLimit\":\"Minimum gas limit to use for the transaction.\",\"_to\":\"Recipient account on L1.\"}}},\"title\":\"L2StandardBridge\",\"version\":1},\"userdoc\":{\"events\":{\"ERC20BridgeFinalized(address,address,address,address,uint256,bytes)\":{\"notice\":\"Emitted when an ERC20 bridge is finalized on this chain.\"},\"ERC20BridgeInitiated(address,address,address,address,uint256,bytes)\":{\"notice\":\"Emitted when an ERC20 bridge is initiated to the other chain.\"},\"ETHBridgeFinalized(address,address,uint256,bytes)\":{\"notice\":\"Emitted when an ETH bridge is finalized on this chain.\"},\"ETHBridgeInitiated(address,address,uint256,bytes)\":{\"notice\":\"Emitted when an ETH bridge is initiated to the other chain.\"}},\"kind\":\"user\",\"methods\":{\"MESSENGER()\":{\"notice\":\"Messenger contract on this domain.\"},\"OTHER_BRIDGE()\":{\"notice\":\"Corresponding bridge on the other domain.\"},\"bridgeERC20(address,address,uint256,uint32,bytes)\":{\"notice\":\"Sends ERC20 tokens to the sender's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain.\"},\"bridgeERC20To(address,address,address,uint256,uint32,bytes)\":{\"notice\":\"Sends ERC20 tokens to a receiver's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain.\"},\"bridgeETH(uint32,bytes)\":{\"notice\":\"Sends ETH to the sender's address on the other chain.\"},\"bridgeETHTo(address,uint32,bytes)\":{\"notice\":\"Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a smart contract and the call fails, the ETH will be temporarily locked in the StandardBridge on the other chain until the call is replayed. If the call cannot be replayed with any amount of gas (call always reverts), then the ETH will be permanently locked in the StandardBridge on the other chain. ETH will also be locked if the receiver is the other bridge, because finalizeBridgeETH will revert in that case.\"},\"deposits(address,address)\":{\"notice\":\"Mapping that stores deposits for a given pair of local and remote tokens.\"},\"finalizeBridgeERC20(address,address,address,address,uint256,bytes)\":{\"notice\":\"Finalizes an ERC20 bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain.\"},\"finalizeBridgeETH(address,address,uint256,bytes)\":{\"notice\":\"Finalizes an ETH bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"The L2StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and L2. In the case that an ERC20 token is native to L2, it will be escrowed within this contract. If the ERC20 token is native to L1, it will be burnt. NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples of some token types that may not be properly supported by this contract include, but are not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2/L2StandardBridge.sol\":\"L2StandardBridge\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/L1/ResourceMetering.sol\":{\"keccak256\":\"0xbd7b9532a70d8c842bfce0ea971be50d02fbbf0227c9ad55c71ac68d438010f4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4969f478dd54e89392cda2ea0c5edcf1be55a5dee43a0e410527b6e3bcb85c88\",\"dweb:/ipfs/QmU2crAojw8DRDsz7PAPrereazjFsKh9wtfTpTDVh6NLfW\"]},\"contracts/L2/L2StandardBridge.sol\":{\"keccak256\":\"0xd77e04c57f33cd32c32f326cd06e213d8a27a9fd372cfc4269953a49243c8c41\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f59627bf4c08c85886e819b29b8565b48fa7e9c230732fedfbb0b9c9a0ee04c5\",\"dweb:/ipfs/Qmao1VbQ57h6gdCZTYfipa8LB1wBwAthop5tPd9TgDXES2\"]},\"contracts/libraries/Arithmetic.sol\":{\"keccak256\":\"0xc8858039f87e48e6f18c1af8bc0b03e57cfef564acddfd06e4d91e3db7ac5ed6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2fc79af1e844aa6dc1c68067bfe1d359df8d4e9a3e8881afb3bcfcbf68071714\",\"dweb:/ipfs/QmcNC4k8zmvwj4kZizSenTiWbx2DJQPbwqXXLF4iMbkRVD\"]},\"contracts/libraries/Burn.sol\":{\"keccak256\":\"0x54233b226ba6919dc46d438bc790108d8f855001002a1b9c3c37aed7a83e5f3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4051a4baca357a9191a6c9e3aa1593a17b69dd7915966e23e4cb269e9c1d9ed4\",\"dweb:/ipfs/QmadKjGKvxm53abVHQdsxrXBc8e9jXywu6vvhkAgjsx59J\"]},\"contracts/libraries/Constants.sol\":{\"keccak256\":\"0x8c7be28a175eb732995a7f704560163c30261f9f70d377f865c5060882509f5d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f72aba26553b10ca88708e05461691b36b0d2ec7a87f718022fe119ca9c70852\",\"dweb:/ipfs/QmQtDEB1F3D8RsgG63KSJ9t7ZyFLaXc2Av81vKD9y2TMn7\"]},\"contracts/libraries/Encoding.sol\":{\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f18156216c1f9457c2e032a812ad70f2babbc5b89997554ff014d64c483fb2ff\",\"dweb:/ipfs/Qmc5rjMaBFn3jV7XqDrEvRbmatQvJxeVJYA5B5rdcKPkcJ\"]},\"contracts/libraries/Hashing.sol\":{\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6746ed0d26d603568818cc52a29d0209effd69f7e55bd0017a6b91bd6cf319fe\",\"dweb:/ipfs/QmPebCmCELMBRtDDxt5ziEPfRXUh6tfm2qJdwz3iyrDdWN\"]},\"contracts/libraries/Predeploys.sol\":{\"keccak256\":\"0xfc30fb239b5f00284f4b8f578a62f0882597e939335c91ea9bc4aab3070ddc43\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fa132267b3a9d98568b4e02cbb68fe2d2c0ca630826242c1b2293a8fa35bd302\",\"dweb:/ipfs/QmdYvcGbaykP6wyBu5T2obXrWK56xGnfWqbYeeWpTChq3w\"]},\"contracts/libraries/SafeCall.sol\":{\"keccak256\":\"0x6e815b62528d452a4f63040d75ff7a08db8ba8096050a53355fc49abaebdf245\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e27e542a11165c82cbb6961f4d8c2a58527fba1ab915afeeded50e96ce929777\",\"dweb:/ipfs/QmRPXdmUAbL1WHZBvENKWkFuHb9bQyrbiJWwDvzEQBLVi8\"]},\"contracts/libraries/Types.sol\":{\"keccak256\":\"0x4fe8ec920798661a828430bd30dc2715eeb40534ec01c0a7bf41cb4ab422e134\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://74c8471869900bd459358cd990bda1c8d234c06b788804c7049cf465ae1e299f\",\"dweb:/ipfs/QmakcfP6NmbVUQsKqH7rEyJsbiqckigLahw9g74oencEJ7\"]},\"contracts/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://921c44e6a0982b9a4011900fda1bda2c06b7a85894967de98b407a83fe9f90c0\",\"dweb:/ipfs/QmSsHLKDUQ82kpKdqB6VntVGKuPDb4W9VdotsubuqWBzio\"]},\"contracts/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x3c99b1e768cc4c1e064ccc137b1b4d5961bf4edf071be84cc216c5b20f1c00da\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e36b2a6325c2f804d769271575669b62ab2da2df3c81921ac7487399fe02af07\",\"dweb:/ipfs/QmTCmcEKwvD8Xvjyev268Bkz27FC7TJpUbw1nADcsThnUr\"]},\"contracts/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x2fea0ee05071c9c6b06a34a8e805801e247e861359b376a8918106e1d6f77ebe\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://198c91bda2edf864ddad1f8ab6168155d13d6ba5487418e5531ff040ff250686\",\"dweb:/ipfs/QmQzxfHY4P7zdVFRh2DTdGt1KeMHaGKNRf3KPZ1mRTYEGB\"]},\"contracts/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x302094342a45ebdf7f46f4fb48821960d2a4134f66fd7f458f73fc4ddf34d219\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8b0e2b496e966ca6037e1c9be1d44417c0180fda2a27f68114e93b899defb783\",\"dweb:/ipfs/QmXP76ivMLxYxscC7B9E9qtW3u6HJ2MNaRVeo3x24VEAQH\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9baf7797439c0ae6512f4639dfc6a1934dbd4e4d7cbb8e63e99264ff47682c9e\",\"dweb:/ipfs/QmawAuhppPyeoZH3rC1uh87xDELa9Lyfw5pYsBqE8myE1m\"]},\"contracts/universal/StandardBridge.sol\":{\"keccak256\":\"0xaa45044774fa70ed322983c3c0138b21d26d75f4b7e8f5324d53c3eef91adec4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c65c95d0cb71f2e32f5ffdea92151a9a46bbd538ba110389a134963fd16a33e9\",\"dweb:/ipfs/QmaPNZokt4j5SCXaWwVtw6qxu5GXWFa3SWBgaSWPPA9KUG\"]},\"node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"]},\"node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"]},\"node_modules/@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b2717fd2bdac99daa960a6de500754ea1b932093c946388c381da48658234b95\",\"dweb:/ipfs/QmP6QVMn6UeA3ByahyJbYQr5M6coHKBKsf3ySZSfbyA8R7\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x032807210d1d7d218963d7355d62e021a84bf1b3339f4f50be2f63b53cccaf29\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://11756f42121f6541a35a8339ea899ee7514cfaa2e6d740625fcc844419296aa6\",\"dweb:/ipfs/QmekMuk6BY4DAjzeXr4MSbKdgoqqsZnA8JPtuyWc6CwXHf\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"]},\"node_modules/@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"]},\"node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"]},\"node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"]}},\"version\":1}", - "bytecode": "0x6101206040523480156200001257600080fd5b5060405162002c0638038062002c0683398101604081905262000035916200006f565b7342000000000000000000000000000000000000076080526001600160a01b031660a052600160c081905260e052600061010052620000a1565b6000602082840312156200008257600080fd5b81516001600160a01b03811681146200009a57600080fd5b9392505050565b60805160a05160c05160e05161010051612ac5620001416000396000610fd201526000610fa901526000610f800152600081816102280152818161030c0152818161050b015281816109cf015281816112ca015261160b015260008181610281015281816103a6015281816104e101528181610542015281816109a501528181610a0601528181610c930152818161128d01526115cf0152612ac56000f3fe6080604052600436106100ec5760003560e01c806354fd4d501161008a5780638f601f66116100595780638f601f661461034e578063927ede2d14610394578063a3a79548146103c8578063e11013dd146103db57600080fd5b806354fd4d50146102c5578063662a633a146102e75780637f46ddb2146102fa578063870876231461032e57600080fd5b806332b7006d116100c657806332b7006d1461020657806336c717c1146102195780633cb747bf14610272578063540abf73146102a557600080fd5b80630166a07a146101c057806309fc8843146101e05780631635f5fd146101f357600080fd5b366101bb57333b15610185576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101b973deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d40604051806020016040528060008152506103ee565b005b600080fd5b3480156101cc57600080fd5b506101b96101db366004612372565b6104c9565b6101b96101ee366004612423565b6108b6565b6101b9610201366004612476565b61098d565b6101b96102143660046124e9565b610e5a565b34801561022557600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561027e57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610248565b3480156102b157600080fd5b506101b96102c036600461253d565b610f34565b3480156102d157600080fd5b506102da610f79565b604051610269919061262a565b6101b96102f5366004612372565b61101c565b34801561030657600080fd5b506102487f000000000000000000000000000000000000000000000000000000000000000081565b34801561033a57600080fd5b506101b961034936600461263d565b61108f565b34801561035a57600080fd5b506103866103693660046126c0565b600260209081526000928352604080842090915290825290205481565b604051908152602001610269565b3480156103a057600080fd5b506102487f000000000000000000000000000000000000000000000000000000000000000081565b6101b96103d636600461263d565b611163565b6101b96103e93660046126f9565b6111a7565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff87160161043d5761043885858585856111f0565b6104c1565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa15801561048a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ae919061275c565b90506104bf878288888888886113d4565b505b505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156105e757507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cf919061275c565b73ffffffffffffffffffffffffffffffffffffffff16145b610699576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a40161017c565b6106a28761171b565b156107f0576106b1878761177d565b610763576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a40161017c565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156107d357600080fd5b505af11580156107e7573d6000803e3d6000fd5b50505050610872565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461082e9084906127a8565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c168352939052919091209190915561087290858561189d565b6104bf878787878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197192505050565b333b15610945576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f41000000000000000000606482015260840161017c565b6109883333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506111f092505050565b505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015610aab57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a93919061275c565b73ffffffffffffffffffffffffffffffffffffffff16145b610b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a40161017c565b823414610bec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e74207265717569726564000000000000606482015260840161017c565b3073ffffffffffffffffffffffffffffffffffffffff851603610c91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c660000000000000000000000000000000000000000000000000000000000606482015260840161017c565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610d6c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e676572000000000000000000000000000000000000000000000000606482015260840161017c565b610dae85858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506119ff92505050565b6000610dcb855a8660405180602001604052806000815250611aa0565b9050806104c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c65640000000000000000000000000000000000000000000000000000000000606482015260840161017c565b333b15610ee9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f41000000000000000000606482015260840161017c565b610f2d853333878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103ee92505050565b5050505050565b6104bf87873388888888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506113d492505050565b6060610fa47f0000000000000000000000000000000000000000000000000000000000000000611aba565b610fcd7f0000000000000000000000000000000000000000000000000000000000000000611aba565b610ff67f0000000000000000000000000000000000000000000000000000000000000000611aba565b604051602001611008939291906127bf565b604051602081830303815290604052905090565b73ffffffffffffffffffffffffffffffffffffffff8716158015611069575073ffffffffffffffffffffffffffffffffffffffff861673deaddeaddeaddeaddeaddeaddeaddeaddead0000145b156110805761107b858585858561098d565b6104bf565b6104bf868887878787876104c9565b333b1561111e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f41000000000000000000606482015260840161017c565b6104c186863333888888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506113d492505050565b6104c1863387878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103ee92505050565b6111ea3385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506111f092505050565b50505050565b82341461127f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c75650000606482015260840161017c565b61128b85858584611bf7565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b847f0000000000000000000000000000000000000000000000000000000000000000631635f5fd60e01b898989886040516024016113089493929190612835565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261139b9291889060040161287e565b6000604051808303818588803b1580156113b457600080fd5b505af11580156113c8573d6000803e3d6000fd5b50505050505050505050565b6113dd8761171b565b1561152b576113ec878761177d565b61149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a40161017c565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b15801561150e57600080fd5b505af1158015611522573d6000803e3d6000fd5b505050506115bf565b61154d73ffffffffffffffffffffffffffffffffffffffff8816863086611c98565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461158b9084906128c3565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b6115cd878787878786611cf6565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b7f0000000000000000000000000000000000000000000000000000000000000000630166a07a60e01b898b8a8a8a8960405160240161164d969594939291906128db565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b90921682526116e09291879060040161287e565b600060405180830381600087803b1580156116fa57600080fd5b505af115801561170e573d6000803e3d6000fd5b5050505050505050505050565b6000611747827f1d1d8b6300000000000000000000000000000000000000000000000000000000611d84565b806117775750611777827fec4fc8e300000000000000000000000000000000000000000000000000000000611d84565b92915050565b60006117a9837f1d1d8b6300000000000000000000000000000000000000000000000000000000611d84565b15611852578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181d919061275c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611777565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117f9573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109889084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611da7565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd898686866040516119e993929190612936565b60405180910390a46104c1868686868686611eb3565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611a8c93929190612936565b60405180910390a46111ea84848484611f3b565b600080600080845160208601878a8af19695505050505050565b606081600003611afd57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611b275780611b1181612974565b9150611b209050600a836129db565b9150611b01565b60008167ffffffffffffffff811115611b4257611b426129ef565b6040519080825280601f01601f191660200182016040528015611b6c576020820181803683370190505b5090505b8415611bef57611b816001836127a8565b9150611b8e600a86612a1e565b611b999060306128c3565b60f81b818381518110611bae57611bae612a32565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611be8600a866129db565b9450611b70565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e868686604051611c8493929190612936565b60405180910390a46111ea84848484611fa8565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526111ea9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016118ef565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e868686604051611d6e93929190612936565b60405180910390a46104c1868686868686612007565b6000611d8f8361207f565b8015611da05750611da083836120e3565b9392505050565b6000611e09826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166121b29092919063ffffffff16565b8051909150156109885780806020019051810190611e279190612a61565b610988576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161017c565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd868686604051611f2b93929190612936565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051611f9a929190612a83565b60405180910390a350505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051611f9a929190612a83565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf868686604051611f2b93929190612936565b60006120ab827f01ffc9a7000000000000000000000000000000000000000000000000000000006120e3565b801561177757506120dc827fffffffff000000000000000000000000000000000000000000000000000000006120e3565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d9150600051905082801561219b575060208210155b80156121a75750600081115b979650505050505050565b6060611bef84846000858573ffffffffffffffffffffffffffffffffffffffff85163b61223b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161017c565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516122649190612a9c565b60006040518083038185875af1925050503d80600081146122a1576040519150601f19603f3d011682016040523d82523d6000602084013e6122a6565b606091505b50915091506121a7828286606083156122c0575081611da0565b8251156122d05782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017c919061262a565b73ffffffffffffffffffffffffffffffffffffffff8116811461232657600080fd5b50565b60008083601f84011261233b57600080fd5b50813567ffffffffffffffff81111561235357600080fd5b60208301915083602082850101111561236b57600080fd5b9250929050565b600080600080600080600060c0888a03121561238d57600080fd5b873561239881612304565b965060208801356123a881612304565b955060408801356123b881612304565b945060608801356123c881612304565b93506080880135925060a088013567ffffffffffffffff8111156123eb57600080fd5b6123f78a828b01612329565b989b979a50959850939692959293505050565b803563ffffffff8116811461241e57600080fd5b919050565b60008060006040848603121561243857600080fd5b6124418461240a565b9250602084013567ffffffffffffffff81111561245d57600080fd5b61246986828701612329565b9497909650939450505050565b60008060008060006080868803121561248e57600080fd5b853561249981612304565b945060208601356124a981612304565b935060408601359250606086013567ffffffffffffffff8111156124cc57600080fd5b6124d888828901612329565b969995985093965092949392505050565b60008060008060006080868803121561250157600080fd5b853561250c81612304565b9450602086013593506125216040870161240a565b9250606086013567ffffffffffffffff8111156124cc57600080fd5b600080600080600080600060c0888a03121561255857600080fd5b873561256381612304565b9650602088013561257381612304565b9550604088013561258381612304565b9450606088013593506125986080890161240a565b925060a088013567ffffffffffffffff8111156123eb57600080fd5b60005b838110156125cf5781810151838201526020016125b7565b838111156111ea5750506000910152565b600081518084526125f88160208601602086016125b4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611da060208301846125e0565b60008060008060008060a0878903121561265657600080fd5b863561266181612304565b9550602087013561267181612304565b9450604087013593506126866060880161240a565b9250608087013567ffffffffffffffff8111156126a257600080fd5b6126ae89828a01612329565b979a9699509497509295939492505050565b600080604083850312156126d357600080fd5b82356126de81612304565b915060208301356126ee81612304565b809150509250929050565b6000806000806060858703121561270f57600080fd5b843561271a81612304565b93506127286020860161240a565b9250604085013567ffffffffffffffff81111561274457600080fd5b61275087828801612329565b95989497509550505050565b60006020828403121561276e57600080fd5b8151611da081612304565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156127ba576127ba612779565b500390565b600084516127d18184602089016125b4565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161280d816001850160208a016125b4565b600192019182015283516128288160028401602088016125b4565b0160020195945050505050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152508360408301526080606083015261287460808301846125e0565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006128ad60608301856125e0565b905063ffffffff83166040830152949350505050565b600082198211156128d6576128d6612779565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a083015261292a60c08301846125e0565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061296b60608301846125e0565b95945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036129a5576129a5612779565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826129ea576129ea6129ac565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082612a2d57612a2d6129ac565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612a7357600080fd5b81518015158114611da057600080fd5b828152604060208201526000611bef60408301846125e0565b60008251612aae8184602087016125b4565b919091019291505056fea164736f6c634300080f000a", - "deployedBytecode": "0x6080604052600436106100ec5760003560e01c806354fd4d501161008a5780638f601f66116100595780638f601f661461034e578063927ede2d14610394578063a3a79548146103c8578063e11013dd146103db57600080fd5b806354fd4d50146102c5578063662a633a146102e75780637f46ddb2146102fa578063870876231461032e57600080fd5b806332b7006d116100c657806332b7006d1461020657806336c717c1146102195780633cb747bf14610272578063540abf73146102a557600080fd5b80630166a07a146101c057806309fc8843146101e05780631635f5fd146101f357600080fd5b366101bb57333b15610185576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101b973deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d40604051806020016040528060008152506103ee565b005b600080fd5b3480156101cc57600080fd5b506101b96101db366004612372565b6104c9565b6101b96101ee366004612423565b6108b6565b6101b9610201366004612476565b61098d565b6101b96102143660046124e9565b610e5a565b34801561022557600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561027e57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610248565b3480156102b157600080fd5b506101b96102c036600461253d565b610f34565b3480156102d157600080fd5b506102da610f79565b604051610269919061262a565b6101b96102f5366004612372565b61101c565b34801561030657600080fd5b506102487f000000000000000000000000000000000000000000000000000000000000000081565b34801561033a57600080fd5b506101b961034936600461263d565b61108f565b34801561035a57600080fd5b506103866103693660046126c0565b600260209081526000928352604080842090915290825290205481565b604051908152602001610269565b3480156103a057600080fd5b506102487f000000000000000000000000000000000000000000000000000000000000000081565b6101b96103d636600461263d565b611163565b6101b96103e93660046126f9565b6111a7565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff87160161043d5761043885858585856111f0565b6104c1565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa15801561048a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ae919061275c565b90506104bf878288888888886113d4565b505b505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156105e757507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cf919061275c565b73ffffffffffffffffffffffffffffffffffffffff16145b610699576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a40161017c565b6106a28761171b565b156107f0576106b1878761177d565b610763576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a40161017c565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156107d357600080fd5b505af11580156107e7573d6000803e3d6000fd5b50505050610872565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461082e9084906127a8565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c168352939052919091209190915561087290858561189d565b6104bf878787878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197192505050565b333b15610945576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f41000000000000000000606482015260840161017c565b6109883333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506111f092505050565b505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015610aab57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a93919061275c565b73ffffffffffffffffffffffffffffffffffffffff16145b610b5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a40161017c565b823414610bec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e74207265717569726564000000000000606482015260840161017c565b3073ffffffffffffffffffffffffffffffffffffffff851603610c91576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c660000000000000000000000000000000000000000000000000000000000606482015260840161017c565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610d6c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e676572000000000000000000000000000000000000000000000000606482015260840161017c565b610dae85858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506119ff92505050565b6000610dcb855a8660405180602001604052806000815250611aa0565b9050806104c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c65640000000000000000000000000000000000000000000000000000000000606482015260840161017c565b333b15610ee9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f41000000000000000000606482015260840161017c565b610f2d853333878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103ee92505050565b5050505050565b6104bf87873388888888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506113d492505050565b6060610fa47f0000000000000000000000000000000000000000000000000000000000000000611aba565b610fcd7f0000000000000000000000000000000000000000000000000000000000000000611aba565b610ff67f0000000000000000000000000000000000000000000000000000000000000000611aba565b604051602001611008939291906127bf565b604051602081830303815290604052905090565b73ffffffffffffffffffffffffffffffffffffffff8716158015611069575073ffffffffffffffffffffffffffffffffffffffff861673deaddeaddeaddeaddeaddeaddeaddeaddead0000145b156110805761107b858585858561098d565b6104bf565b6104bf868887878787876104c9565b333b1561111e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f41000000000000000000606482015260840161017c565b6104c186863333888888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506113d492505050565b6104c1863387878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506103ee92505050565b6111ea3385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506111f092505050565b50505050565b82341461127f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c75650000606482015260840161017c565b61128b85858584611bf7565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b847f0000000000000000000000000000000000000000000000000000000000000000631635f5fd60e01b898989886040516024016113089493929190612835565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261139b9291889060040161287e565b6000604051808303818588803b1580156113b457600080fd5b505af11580156113c8573d6000803e3d6000fd5b50505050505050505050565b6113dd8761171b565b1561152b576113ec878761177d565b61149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a40161017c565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b15801561150e57600080fd5b505af1158015611522573d6000803e3d6000fd5b505050506115bf565b61154d73ffffffffffffffffffffffffffffffffffffffff8816863086611c98565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461158b9084906128c3565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b6115cd878787878786611cf6565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b7f0000000000000000000000000000000000000000000000000000000000000000630166a07a60e01b898b8a8a8a8960405160240161164d969594939291906128db565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b90921682526116e09291879060040161287e565b600060405180830381600087803b1580156116fa57600080fd5b505af115801561170e573d6000803e3d6000fd5b5050505050505050505050565b6000611747827f1d1d8b6300000000000000000000000000000000000000000000000000000000611d84565b806117775750611777827fec4fc8e300000000000000000000000000000000000000000000000000000000611d84565b92915050565b60006117a9837f1d1d8b6300000000000000000000000000000000000000000000000000000000611d84565b15611852578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181d919061275c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611777565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117f9573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109889084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611da7565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd898686866040516119e993929190612936565b60405180910390a46104c1868686868686611eb3565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611a8c93929190612936565b60405180910390a46111ea84848484611f3b565b600080600080845160208601878a8af19695505050505050565b606081600003611afd57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611b275780611b1181612974565b9150611b209050600a836129db565b9150611b01565b60008167ffffffffffffffff811115611b4257611b426129ef565b6040519080825280601f01601f191660200182016040528015611b6c576020820181803683370190505b5090505b8415611bef57611b816001836127a8565b9150611b8e600a86612a1e565b611b999060306128c3565b60f81b818381518110611bae57611bae612a32565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611be8600a866129db565b9450611b70565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e868686604051611c8493929190612936565b60405180910390a46111ea84848484611fa8565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526111ea9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016118ef565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e868686604051611d6e93929190612936565b60405180910390a46104c1868686868686612007565b6000611d8f8361207f565b8015611da05750611da083836120e3565b9392505050565b6000611e09826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166121b29092919063ffffffff16565b8051909150156109885780806020019051810190611e279190612a61565b610988576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161017c565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd868686604051611f2b93929190612936565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051611f9a929190612a83565b60405180910390a350505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051611f9a929190612a83565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf868686604051611f2b93929190612936565b60006120ab827f01ffc9a7000000000000000000000000000000000000000000000000000000006120e3565b801561177757506120dc827fffffffff000000000000000000000000000000000000000000000000000000006120e3565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d9150600051905082801561219b575060208210155b80156121a75750600081115b979650505050505050565b6060611bef84846000858573ffffffffffffffffffffffffffffffffffffffff85163b61223b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161017c565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516122649190612a9c565b60006040518083038185875af1925050503d80600081146122a1576040519150601f19603f3d011682016040523d82523d6000602084013e6122a6565b606091505b50915091506121a7828286606083156122c0575081611da0565b8251156122d05782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017c919061262a565b73ffffffffffffffffffffffffffffffffffffffff8116811461232657600080fd5b50565b60008083601f84011261233b57600080fd5b50813567ffffffffffffffff81111561235357600080fd5b60208301915083602082850101111561236b57600080fd5b9250929050565b600080600080600080600060c0888a03121561238d57600080fd5b873561239881612304565b965060208801356123a881612304565b955060408801356123b881612304565b945060608801356123c881612304565b93506080880135925060a088013567ffffffffffffffff8111156123eb57600080fd5b6123f78a828b01612329565b989b979a50959850939692959293505050565b803563ffffffff8116811461241e57600080fd5b919050565b60008060006040848603121561243857600080fd5b6124418461240a565b9250602084013567ffffffffffffffff81111561245d57600080fd5b61246986828701612329565b9497909650939450505050565b60008060008060006080868803121561248e57600080fd5b853561249981612304565b945060208601356124a981612304565b935060408601359250606086013567ffffffffffffffff8111156124cc57600080fd5b6124d888828901612329565b969995985093965092949392505050565b60008060008060006080868803121561250157600080fd5b853561250c81612304565b9450602086013593506125216040870161240a565b9250606086013567ffffffffffffffff8111156124cc57600080fd5b600080600080600080600060c0888a03121561255857600080fd5b873561256381612304565b9650602088013561257381612304565b9550604088013561258381612304565b9450606088013593506125986080890161240a565b925060a088013567ffffffffffffffff8111156123eb57600080fd5b60005b838110156125cf5781810151838201526020016125b7565b838111156111ea5750506000910152565b600081518084526125f88160208601602086016125b4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611da060208301846125e0565b60008060008060008060a0878903121561265657600080fd5b863561266181612304565b9550602087013561267181612304565b9450604087013593506126866060880161240a565b9250608087013567ffffffffffffffff8111156126a257600080fd5b6126ae89828a01612329565b979a9699509497509295939492505050565b600080604083850312156126d357600080fd5b82356126de81612304565b915060208301356126ee81612304565b809150509250929050565b6000806000806060858703121561270f57600080fd5b843561271a81612304565b93506127286020860161240a565b9250604085013567ffffffffffffffff81111561274457600080fd5b61275087828801612329565b95989497509550505050565b60006020828403121561276e57600080fd5b8151611da081612304565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156127ba576127ba612779565b500390565b600084516127d18184602089016125b4565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161280d816001850160208a016125b4565b600192019182015283516128288160028401602088016125b4565b0160020195945050505050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152508360408301526080606083015261287460808301846125e0565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006128ad60608301856125e0565b905063ffffffff83166040830152949350505050565b600082198211156128d6576128d6612779565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a083015261292a60c08301846125e0565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061296b60608301846125e0565b95945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036129a5576129a5612779565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826129ea576129ea6129ac565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082612a2d57612a2d6129ac565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612a7357600080fd5b81518015158114611da057600080fd5b828152604060208201526000611bef60408301846125e0565b60008251612aae8184602087016125b4565b919091019291505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "bridgeERC20(address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of local tokens to deposit.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_localToken": "Address of the ERC20 on this chain.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", - "_remoteToken": "Address of the corresponding token on the remote chain." - } - }, - "bridgeERC20To(address,address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of local tokens to deposit.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_localToken": "Address of the ERC20 on this chain.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", - "_remoteToken": "Address of the corresponding token on the remote chain.", - "_to": "Address of the receiver." - } - }, - "bridgeETH(uint32,bytes)": { - "params": { - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with." - } - }, - "bridgeETHTo(address,uint32,bytes)": { - "params": { - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", - "_to": "Address of the receiver." - } - }, - "constructor": { - "params": { - "_otherBridge": "Address of the L1StandardBridge." - } - }, - "finalizeBridgeERC20(address,address,address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of the ERC20 being bridged.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_from": "Address of the sender.", - "_localToken": "Address of the ERC20 on this chain.", - "_remoteToken": "Address of the corresponding token on the remote chain.", - "_to": "Address of the receiver." - } - }, - "finalizeBridgeETH(address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of ETH being bridged.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_from": "Address of the sender.", - "_to": "Address of the receiver." - } - }, - "finalizeDeposit(address,address,address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of the tokens being deposited.", - "_extraData": "Extra data attached to the deposit.", - "_from": "Address of the depositor.", - "_l1Token": "Address of the L1 token to deposit.", - "_l2Token": "Address of the corresponding L2 token.", - "_to": "Address of the recipient." - } - }, - "l1TokenBridge()": { - "returns": { - "_0": "Address of the corresponding L1 bridge contract." - } - }, - "messenger()": { - "returns": { - "_0": "Messenger contract on this domain." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - }, - "withdraw(address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of the L2 token to withdraw.", - "_extraData": "Extra data attached to the withdrawal.", - "_l2Token": "Address of the L2 token to withdraw.", - "_minGasLimit": "Minimum gas limit to use for the transaction." - } - }, - "withdrawTo(address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of the L2 token to withdraw.", - "_extraData": "Extra data attached to the withdrawal.", - "_l2Token": "Address of the L2 token to withdraw.", - "_minGasLimit": "Minimum gas limit to use for the transaction.", - "_to": "Recipient account on L1." - } - } - }, - "events": { - "DepositFinalized(address,address,address,address,uint256,bytes)": { - "params": { - "amount": "Amount of the ERC20 deposited.", - "extraData": "Extra data attached to the deposit.", - "from": "Address of the depositor.", - "l1Token": "Address of the token on L1.", - "l2Token": "Address of the corresponding token on L2.", - "to": "Address of the recipient on L2." - } - }, - "WithdrawalInitiated(address,address,address,address,uint256,bytes)": { - "params": { - "amount": "Amount of the ERC20 withdrawn.", - "extraData": "Extra data attached to the withdrawal.", - "from": "Address of the withdrawer.", - "l1Token": "Address of the token on L1.", - "l2Token": "Address of the corresponding token on L2.", - "to": "Address of the recipient on L1." - } - } - }, - "title": "L2StandardBridge" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MESSENGER()": { - "notice": "Messenger contract on this domain." - }, - "OTHER_BRIDGE()": { - "notice": "Corresponding bridge on the other domain." - }, - "bridgeERC20(address,address,uint256,uint32,bytes)": { - "notice": "Sends ERC20 tokens to the sender's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain." - }, - "bridgeERC20To(address,address,address,uint256,uint32,bytes)": { - "notice": "Sends ERC20 tokens to a receiver's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain." - }, - "bridgeETH(uint32,bytes)": { - "notice": "Sends ETH to the sender's address on the other chain." - }, - "bridgeETHTo(address,uint32,bytes)": { - "notice": "Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a smart contract and the call fails, the ETH will be temporarily locked in the StandardBridge on the other chain until the call is replayed. If the call cannot be replayed with any amount of gas (call always reverts), then the ETH will be permanently locked in the StandardBridge on the other chain. ETH will also be locked if the receiver is the other bridge, because finalizeBridgeETH will revert in that case." - }, - "deposits(address,address)": { - "notice": "Mapping that stores deposits for a given pair of local and remote tokens." - }, - "finalizeBridgeERC20(address,address,address,address,uint256,bytes)": { - "notice": "Finalizes an ERC20 bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain." - }, - "finalizeBridgeETH(address,address,uint256,bytes)": { - "notice": "Finalizes an ETH bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "events": { - "ERC20BridgeFinalized(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC20 bridge is finalized on this chain." - }, - "ERC20BridgeInitiated(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC20 bridge is initiated to the other chain." - }, - "ETHBridgeFinalized(address,address,uint256,bytes)": { - "notice": "Emitted when an ETH bridge is finalized on this chain." - }, - "ETHBridgeInitiated(address,address,uint256,bytes)": { - "notice": "Emitted when an ETH bridge is initiated to the other chain." - } - }, - "notice": "The L2StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and L2. In the case that an ERC20 token is native to L2, it will be escrowed within this contract. If the ERC20 token is native to L1, it will be burnt. NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples of some token types that may not be properly supported by this contract include, but are not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists." - }, - "storageLayout": { - "storage": [ - { - "astId": 48356, - "contract": "contracts/L2/L2StandardBridge.sol:L2StandardBridge", - "label": "spacer_0_0_20", - "offset": 0, - "slot": "0", - "type": "t_address" - }, - { - "astId": 48359, - "contract": "contracts/L2/L2StandardBridge.sol:L2StandardBridge", - "label": "spacer_1_0_20", - "offset": 0, - "slot": "1", - "type": "t_address" - }, - { - "astId": 48366, - "contract": "contracts/L2/L2StandardBridge.sol:L2StandardBridge", - "label": "deposits", - "offset": 0, - "slot": "2", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" - }, - { - "astId": 48371, - "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", - "base": "t_uint256" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/L2ToL1MessagePasser.json b/packages/contracts-bedrock/deployments/optimism-goerli/L2ToL1MessagePasser.json deleted file mode 100644 index 5c7c0c2004aa..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/L2ToL1MessagePasser.json +++ /dev/null @@ -1,306 +0,0 @@ -{ - "address": "0x50CcA47c1e06084459dc83c9E964F4a158cB28Ae", - "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" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "withdrawalHash", - "type": "bytes32" - } - ], - "name": "MessagePassed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrawerBalanceBurnt", - "type": "event" - }, - { - "inputs": [], - "name": "MESSAGE_VERSION", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "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": "messageNonce", - "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" - } - ], - "transactionHash": "0x34eb684cb1a7cd53dcbbeac926c389066708b55023662726da724f527151c50a", - "receipt": { - "to": null, - "from": "0xf80267194936da1E98dB10bcE06F3147D580a62e", - "contractAddress": "0x50CcA47c1e06084459dc83c9E964F4a158cB28Ae", - "transactionIndex": 2, - "gasUsed": "609034", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfc90bb4a325d363720404e9c49e0d3f1354028f8f6efe8af49b2b4b4cee1028f", - "transactionHash": "0x34eb684cb1a7cd53dcbbeac926c389066708b55023662726da724f527151c50a", - "logs": [], - "blockNumber": 8579675, - "cumulativeGasUsed": "877476", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "2d538e296d12ca6101a896ac2e894043", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"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\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\"}],\"name\":\"MessagePassed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrawerBalanceBurnt\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MESSAGE_VERSION\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\":\"messageNonce\",\"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\"}],\"devdoc\":{\"custom:proxied\":\"@custom:predeploy 0x4200000000000000000000000000000000000016\",\"events\":{\"MessagePassed(uint256,address,address,uint256,uint256,bytes,bytes32)\":{\"params\":{\"data\":\"The data to be forwarded to the target on L1.\",\"gasLimit\":\"The minimum amount of gas that must be provided when withdrawing.\",\"nonce\":\"Unique value corresponding to each withdrawal.\",\"sender\":\"The L2 account address which initiated the withdrawal.\",\"target\":\"The L1 account address the call will be send to.\",\"value\":\"The ETH value submitted for withdrawal, to be forwarded to the target.\",\"withdrawalHash\":\"The hash of the withdrawal.\"}},\"WithdrawerBalanceBurnt(uint256)\":{\"params\":{\"amount\":\"Amount of ETh that was burned.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:semver\":\"1.0.0\"},\"initiateWithdrawal(address,uint256,bytes)\":{\"params\":{\"_data\":\"Data to forward to L1 target.\",\"_gasLimit\":\"Minimum gas limit for executing the message on L1.\",\"_target\":\"Address to call on L1 execution.\"}},\"messageNonce()\":{\"returns\":{\"_0\":\"Nonce of the next message to be sent, with added message version.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"L2ToL1MessagePasser\",\"version\":1},\"userdoc\":{\"events\":{\"MessagePassed(uint256,address,address,uint256,uint256,bytes,bytes32)\":{\"notice\":\"Emitted any time a withdrawal is initiated.\"},\"WithdrawerBalanceBurnt(uint256)\":{\"notice\":\"Emitted when the balance of this contract is burned.\"}},\"kind\":\"user\",\"methods\":{\"MESSAGE_VERSION()\":{\"notice\":\"Current message version identifier.\"},\"burn()\":{\"notice\":\"Removes all ETH held by this contract from the state. Used to prevent the amount of ETH on L2 inflating when ETH is withdrawn. Currently only way to do this is to create a contract and self-destruct it to itself. Anyone can call this function. Not incentivized since this function is very cheap.\"},\"initiateWithdrawal(address,uint256,bytes)\":{\"notice\":\"Sends a message from L2 to L1.\"},\"messageNonce()\":{\"notice\":\"Retrieves the next message nonce. Message version will be added to the upper two bytes of the message nonce. Message version allows us to treat messages as having different structures.\"},\"sentMessages(bytes32)\":{\"notice\":\"Includes the message hashes for all withdrawals\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"The L2ToL1MessagePasser is a dedicated contract where messages that are being sent from L2 to L1 can be stored. The storage root of this contract is pulled up to the top level of the L2 output to reduce the cost of proving the existence of sent messages.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2/L2ToL1MessagePasser.sol\":\"L2ToL1MessagePasser\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/L2/L2ToL1MessagePasser.sol\":{\"keccak256\":\"0xa385bda91d75c44f6d8b0bc5a61e1904ed455d98c07b308910ac1265e6536df1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dcbaab318b084e163992187aa87f9250782982c10d69be9e11959090e02cc912\",\"dweb:/ipfs/QmY81HgBPp4vcMigSbWQ8mDizXCQFvjN52BF7nGPc6f9Fm\"]},\"contracts/libraries/Burn.sol\":{\"keccak256\":\"0x54233b226ba6919dc46d438bc790108d8f855001002a1b9c3c37aed7a83e5f3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4051a4baca357a9191a6c9e3aa1593a17b69dd7915966e23e4cb269e9c1d9ed4\",\"dweb:/ipfs/QmadKjGKvxm53abVHQdsxrXBc8e9jXywu6vvhkAgjsx59J\"]},\"contracts/libraries/Encoding.sol\":{\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f18156216c1f9457c2e032a812ad70f2babbc5b89997554ff014d64c483fb2ff\",\"dweb:/ipfs/Qmc5rjMaBFn3jV7XqDrEvRbmatQvJxeVJYA5B5rdcKPkcJ\"]},\"contracts/libraries/Hashing.sol\":{\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6746ed0d26d603568818cc52a29d0209effd69f7e55bd0017a6b91bd6cf319fe\",\"dweb:/ipfs/QmPebCmCELMBRtDDxt5ziEPfRXUh6tfm2qJdwz3iyrDdWN\"]},\"contracts/libraries/Types.sol\":{\"keccak256\":\"0x4fe8ec920798661a828430bd30dc2715eeb40534ec01c0a7bf41cb4ab422e134\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://74c8471869900bd459358cd990bda1c8d234c06b788804c7049cf465ae1e299f\",\"dweb:/ipfs/QmakcfP6NmbVUQsKqH7rEyJsbiqckigLahw9g74oencEJ7\"]},\"contracts/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://921c44e6a0982b9a4011900fda1bda2c06b7a85894967de98b407a83fe9f90c0\",\"dweb:/ipfs/QmSsHLKDUQ82kpKdqB6VntVGKuPDb4W9VdotsubuqWBzio\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9baf7797439c0ae6512f4639dfc6a1934dbd4e4d7cbb8e63e99264ff47682c9e\",\"dweb:/ipfs/QmawAuhppPyeoZH3rC1uh87xDELa9Lyfw5pYsBqE8myE1m\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]}},\"version\":1}", - "bytecode": "0x60e060405234801561001057600080fd5b5060016080819052600060a081905260c081905280610a2061004a82396000610403015260006103da015260006103b10152610a206000f3fe6080604052600436106100695760003560e01c806382e3702d1161004357806382e3702d146100f6578063c2b3e5ac14610136578063ecc704281461014957600080fd5b80633f827a5a1461009257806344df8e70146100bf57806354fd4d50146100d457600080fd5b3661008d5761008b33620186a0604051806020016040528060008152506101ae565b005b600080fd5b34801561009e57600080fd5b506100a7600181565b60405161ffff90911681526020015b60405180910390f35b3480156100cb57600080fd5b5061008b610372565b3480156100e057600080fd5b506100e96103aa565b6040516100b6919061068c565b34801561010257600080fd5b506101266101113660046106a6565b60006020819052908152604090205460ff1681565b60405190151581526020016100b6565b61008b6101443660046106ee565b6101ae565b34801561015557600080fd5b506101a06001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016100b6565b60006102446040518060c001604052806102086001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b815233602082015273ffffffffffffffffffffffffffffffffffffffff871660408201523460608201526080810186905260a00184905261044d565b600081815260208190526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055905073ffffffffffffffffffffffffffffffffffffffff8416336102df6001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b7f02a52367d10742d8032712c1bb8e0144ff1ec5ffda1ed7d70bb05a27449550543487878760405161031494939291906107f2565b60405180910390a45050600180547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8082168301167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b4761037c8161049a565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b60606103d57f00000000000000000000000000000000000000000000000000000000000000006104c9565b6103fe7f00000000000000000000000000000000000000000000000000000000000000006104c9565b6104277f00000000000000000000000000000000000000000000000000000000000000006104c9565b60405160200161043993929190610822565b604051602081830303815290604052905090565b80516020808301516040808501516060860151608087015160a0880151935160009761047d979096959101610898565b604051602081830303815290604052805190602001209050919050565b806040516104a790610606565b6040518091039082f09050801580156104c4573d6000803e3d6000fd5b505050565b60608160000361050c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561053657806105208161091e565b915061052f9050600a83610985565b9150610510565b60008167ffffffffffffffff811115610551576105516106bf565b6040519080825280601f01601f19166020018201604052801561057b576020820181803683370190505b5090505b84156105fe57610590600183610999565b915061059d600a866109b0565b6105a89060306109c4565b60f81b8183815181106105bd576105bd6109dc565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506105f7600a86610985565b945061057f565b949350505050565b600880610a0c83390190565b60005b8381101561062d578181015183820152602001610615565b8381111561063c576000848401525b50505050565b6000815180845261065a816020860160208601610612565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061069f6020830184610642565b9392505050565b6000602082840312156106b857600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060006060848603121561070357600080fd5b833573ffffffffffffffffffffffffffffffffffffffff8116811461072757600080fd5b925060208401359150604084013567ffffffffffffffff8082111561074b57600080fd5b818601915086601f83011261075f57600080fd5b813581811115610771576107716106bf565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156107b7576107b76106bf565b816040528281528960208487010111156107d057600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b8481528360208201526080604082015260006108116080830185610642565b905082606083015295945050505050565b60008451610834818460208901610612565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610870816001850160208a01610612565b6001920191820152835161088b816002840160208801610612565b0160020195945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526108e360c0830184610642565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361094f5761094f6108ef565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261099457610994610956565b500490565b6000828210156109ab576109ab6108ef565b500390565b6000826109bf576109bf610956565b500690565b600082198211156109d7576109d76108ef565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe608060405230fffea164736f6c634300080f000a", - "deployedBytecode": "0x6080604052600436106100695760003560e01c806382e3702d1161004357806382e3702d146100f6578063c2b3e5ac14610136578063ecc704281461014957600080fd5b80633f827a5a1461009257806344df8e70146100bf57806354fd4d50146100d457600080fd5b3661008d5761008b33620186a0604051806020016040528060008152506101ae565b005b600080fd5b34801561009e57600080fd5b506100a7600181565b60405161ffff90911681526020015b60405180910390f35b3480156100cb57600080fd5b5061008b610372565b3480156100e057600080fd5b506100e96103aa565b6040516100b6919061068c565b34801561010257600080fd5b506101266101113660046106a6565b60006020819052908152604090205460ff1681565b60405190151581526020016100b6565b61008b6101443660046106ee565b6101ae565b34801561015557600080fd5b506101a06001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016100b6565b60006102446040518060c001604052806102086001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b815233602082015273ffffffffffffffffffffffffffffffffffffffff871660408201523460608201526080810186905260a00184905261044d565b600081815260208190526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055905073ffffffffffffffffffffffffffffffffffffffff8416336102df6001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b7f02a52367d10742d8032712c1bb8e0144ff1ec5ffda1ed7d70bb05a27449550543487878760405161031494939291906107f2565b60405180910390a45050600180547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8082168301167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b4761037c8161049a565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b60606103d57f00000000000000000000000000000000000000000000000000000000000000006104c9565b6103fe7f00000000000000000000000000000000000000000000000000000000000000006104c9565b6104277f00000000000000000000000000000000000000000000000000000000000000006104c9565b60405160200161043993929190610822565b604051602081830303815290604052905090565b80516020808301516040808501516060860151608087015160a0880151935160009761047d979096959101610898565b604051602081830303815290604052805190602001209050919050565b806040516104a790610606565b6040518091039082f09050801580156104c4573d6000803e3d6000fd5b505050565b60608160000361050c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561053657806105208161091e565b915061052f9050600a83610985565b9150610510565b60008167ffffffffffffffff811115610551576105516106bf565b6040519080825280601f01601f19166020018201604052801561057b576020820181803683370190505b5090505b84156105fe57610590600183610999565b915061059d600a866109b0565b6105a89060306109c4565b60f81b8183815181106105bd576105bd6109dc565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506105f7600a86610985565b945061057f565b949350505050565b600880610a0c83390190565b60005b8381101561062d578181015183820152602001610615565b8381111561063c576000848401525b50505050565b6000815180845261065a816020860160208601610612565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061069f6020830184610642565b9392505050565b6000602082840312156106b857600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060006060848603121561070357600080fd5b833573ffffffffffffffffffffffffffffffffffffffff8116811461072757600080fd5b925060208401359150604084013567ffffffffffffffff8082111561074b57600080fd5b818601915086601f83011261075f57600080fd5b813581811115610771576107716106bf565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156107b7576107b76106bf565b816040528281528960208487010111156107d057600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b8481528360208201526080604082015260006108116080830185610642565b905082606083015295945050505050565b60008451610834818460208901610612565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610870816001850160208a01610612565b6001920191820152835161088b816002840160208801610612565b0160020195945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526108e360c0830184610642565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361094f5761094f6108ef565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261099457610994610956565b500490565b6000828210156109ab576109ab6108ef565b500390565b6000826109bf576109bf610956565b500690565b600082198211156109d7576109d76108ef565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe608060405230fffea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "constructor": {}, - "initiateWithdrawal(address,uint256,bytes)": { - "params": { - "_data": "Data to forward to L1 target.", - "_gasLimit": "Minimum gas limit for executing the message on L1.", - "_target": "Address to call on L1 execution." - } - }, - "messageNonce()": { - "returns": { - "_0": "Nonce of the next message to be sent, with added message version." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "events": { - "MessagePassed(uint256,address,address,uint256,uint256,bytes,bytes32)": { - "params": { - "data": "The data to be forwarded to the target on L1.", - "gasLimit": "The minimum amount of gas that must be provided when withdrawing.", - "nonce": "Unique value corresponding to each withdrawal.", - "sender": "The L2 account address which initiated the withdrawal.", - "target": "The L1 account address the call will be send to.", - "value": "The ETH value submitted for withdrawal, to be forwarded to the target.", - "withdrawalHash": "The hash of the withdrawal." - } - }, - "WithdrawerBalanceBurnt(uint256)": { - "params": { - "amount": "Amount of ETh that was burned." - } - } - }, - "title": "L2ToL1MessagePasser" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MESSAGE_VERSION()": { - "notice": "Current message version identifier." - }, - "burn()": { - "notice": "Removes all ETH held by this contract from the state. Used to prevent the amount of ETH on L2 inflating when ETH is withdrawn. Currently only way to do this is to create a contract and self-destruct it to itself. Anyone can call this function. Not incentivized since this function is very cheap." - }, - "initiateWithdrawal(address,uint256,bytes)": { - "notice": "Sends a message from L2 to L1." - }, - "messageNonce()": { - "notice": "Retrieves the next message nonce. Message version will be added to the upper two bytes of the message nonce. Message version allows us to treat messages as having different structures." - }, - "sentMessages(bytes32)": { - "notice": "Includes the message hashes for all withdrawals" - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "events": { - "MessagePassed(uint256,address,address,uint256,uint256,bytes,bytes32)": { - "notice": "Emitted any time a withdrawal is initiated." - }, - "WithdrawerBalanceBurnt(uint256)": { - "notice": "Emitted when the balance of this contract is burned." - } - }, - "notice": "The L2ToL1MessagePasser is a dedicated contract where messages that are being sent from L2 to L1 can be stored. The storage root of this contract is pulled up to the top level of the L2 output to reduce the cost of proving the existence of sent messages." - }, - "storageLayout": { - "storage": [ - { - "astId": 3976, - "contract": "contracts/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser", - "label": "sentMessages", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 3979, - "contract": "contracts/L2/L2ToL1MessagePasser.sol:L2ToL1MessagePasser", - "label": "msgNonce", - "offset": 0, - "slot": "1", - "type": "t_uint240" - } - ], - "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", - "key": "t_bytes32", - "label": "mapping(bytes32 => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_uint240": { - "encoding": "inplace", - "label": "uint240", - "numberOfBytes": "30" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/MintManager.json b/packages/contracts-bedrock/deployments/optimism-goerli/MintManager.json deleted file mode 100644 index d0dccf28d1aa..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/MintManager.json +++ /dev/null @@ -1,316 +0,0 @@ -{ - "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-bedrock/deployments/optimism-goerli/OptimismMintableERC20Factory.json b/packages/contracts-bedrock/deployments/optimism-goerli/OptimismMintableERC20Factory.json deleted file mode 100644 index 8238c4251e6e..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/OptimismMintableERC20Factory.json +++ /dev/null @@ -1,244 +0,0 @@ -{ - "address": "0x3F94732CFd48eE3597d7cEDfb853cfB2De31219c", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_bridge", - "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": false, - "internalType": "address", - "name": "deployer", - "type": "address" - } - ], - "name": "OptimismMintableERC20Created", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "localToken", - "type": "address" - } - ], - "name": "StandardL2TokenCreated", - "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": "createOptimismMintableERC20", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_remoteToken", - "type": "address" - }, - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - } - ], - "name": "createStandardL2Token", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0xa03da13fa2f6f9ea224e2e19b5fb19c644203263f97e9de2f62d0be3796faa7a", - "receipt": { - "to": null, - "from": "0xf80267194936da1E98dB10bcE06F3147D580a62e", - "contractAddress": "0x3F94732CFd48eE3597d7cEDfb853cfB2De31219c", - "transactionIndex": 1, - "gasUsed": "1995465", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x3763c5bec563a3cecde263b31267f532357d5ac67be40a557705dfe4254c6af6", - "transactionHash": "0xa03da13fa2f6f9ea224e2e19b5fb19c644203263f97e9de2f62d0be3796faa7a", - "logs": [], - "blockNumber": 8579707, - "cumulativeGasUsed": "2042366", - "status": 1, - "byzantium": true - }, - "args": [ - "0x4200000000000000000000000000000000000010" - ], - "numDeployments": 1, - "solcInputHash": "2d538e296d12ca6101a896ac2e894043", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bridge\",\"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\":false,\"internalType\":\"address\",\"name\":\"deployer\",\"type\":\"address\"}],\"name\":\"OptimismMintableERC20Created\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"StandardL2TokenCreated\",\"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\":\"createOptimismMintableERC20\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"createStandardL2Token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"custom:proxied\":\"@custom:predeployed 0x4200000000000000000000000000000000000012\",\"events\":{\"OptimismMintableERC20Created(address,address,address)\":{\"params\":{\"deployer\":\"Address of the account that deployed the token.\",\"localToken\":\"Address of the created token on the local chain.\",\"remoteToken\":\"Address of the corresponding token on the remote chain.\"}},\"StandardL2TokenCreated(address,address)\":{\"custom:legacy\":\"@notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer OptimismMintableERC20Created event. We recommend relying on that event instead.\",\"params\":{\"localToken\":\"Address of the created token on the local chain.\",\"remoteToken\":\"Address of the token on the remote chain.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:semver\":\"1.1.0\",\"params\":{\"_bridge\":\"Address of the StandardBridge on this chain.\"}},\"createOptimismMintableERC20(address,string,string)\":{\"params\":{\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}},\"createStandardL2Token(address,string,string)\":{\"custom:legacy\":\"@notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the newer createOptimismMintableERC20 function, which has a more intuitive name.\",\"params\":{\"_name\":\"ERC20 name.\",\"_remoteToken\":\"Address of the token on the remote chain.\",\"_symbol\":\"ERC20 symbol.\"},\"returns\":{\"_0\":\"Address of the newly created token.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"OptimismMintableERC20Factory\",\"version\":1},\"userdoc\":{\"events\":{\"OptimismMintableERC20Created(address,address,address)\":{\"notice\":\"Emitted whenever a new OptimismMintableERC20 is created.\"}},\"kind\":\"user\",\"methods\":{\"BRIDGE()\":{\"notice\":\"Address of the StandardBridge on this chain.\"},\"constructor\":{\"notice\":\"The semver MUST be bumped any time that there is a change in the OptimismMintableERC20 token contract since this contract is responsible for deploying OptimismMintableERC20 contracts.\"},\"createOptimismMintableERC20(address,string,string)\":{\"notice\":\"Creates an instance of the OptimismMintableERC20 contract.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20 contracts on the network it's deployed to. Simplifies the deployment process for users who may be less familiar with deploying smart contracts. Designed to be backwards compatible with the older StandardL2ERC20Factory contract.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/OptimismMintableERC20Factory.sol\":\"OptimismMintableERC20Factory\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x2fea0ee05071c9c6b06a34a8e805801e247e861359b376a8918106e1d6f77ebe\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://198c91bda2edf864ddad1f8ab6168155d13d6ba5487418e5531ff040ff250686\",\"dweb:/ipfs/QmQzxfHY4P7zdVFRh2DTdGt1KeMHaGKNRf3KPZ1mRTYEGB\"]},\"contracts/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x302094342a45ebdf7f46f4fb48821960d2a4134f66fd7f458f73fc4ddf34d219\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8b0e2b496e966ca6037e1c9be1d44417c0180fda2a27f68114e93b899defb783\",\"dweb:/ipfs/QmXP76ivMLxYxscC7B9E9qtW3u6HJ2MNaRVeo3x24VEAQH\"]},\"contracts/universal/OptimismMintableERC20Factory.sol\":{\"keccak256\":\"0x87fde59e9b0d43c415cb26d0cb13d7b1aab1f725750291dd257276efdf83774b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e76b70b637fd5d4daf121ba201dd3c85e5ca9763adf65f032c49753057d2c9af\",\"dweb:/ipfs/Qmf5SWFCS2TB1VM5BfGfb8EG84H8mdVwXe9A5jipgf4Lgr\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9baf7797439c0ae6512f4639dfc6a1934dbd4e4d7cbb8e63e99264ff47682c9e\",\"dweb:/ipfs/QmawAuhppPyeoZH3rC1uh87xDELa9Lyfw5pYsBqE8myE1m\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"]}},\"version\":1}", - "bytecode": "0x61010060405234801561001157600080fd5b5060405161243538038061243583398101604081905261003091610050565b6001608081905260a052600060c0526001600160a01b031660e052610080565b60006020828403121561006257600080fd5b81516001600160a01b038116811461007957600080fd5b9392505050565b60805160a05160c05160e0516123776100be6000396000818160d3015261026501526000610153015260006101280152600060fd01526123776000f3fe60806040523480156200001157600080fd5b5060043610620000525760003560e01c806354fd4d501462000057578063896f93d11462000079578063ce5ac90f14620000b6578063ee9a31a214620000cd575b600080fd5b62000061620000f5565b60405162000070919062000550565b60405180910390f35b620000906200008a3660046200064e565b620001a0565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200162000070565b62000090620000c73660046200064e565b620001b7565b620000907f000000000000000000000000000000000000000000000000000000000000000081565b6060620001227f000000000000000000000000000000000000000000000000000000000000000062000376565b6200014d7f000000000000000000000000000000000000000000000000000000000000000062000376565b620001787f000000000000000000000000000000000000000000000000000000000000000062000376565b6040516020016200018c93929190620006e5565b604051602081830303815290604052905090565b6000620001af848484620001b7565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff841662000261576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e206164647265737300606482015260840160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000008585856040516200029590620004c3565b620002a4949392919062000761565b604051809103906000f080158015620002c1573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80871691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a3949350505050565b606081600003620003ba57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115620003ea5780620003d181620007ea565b9150620003e29050600a8362000854565b9150620003be565b60008167ffffffffffffffff8111156200040857620004086200056c565b6040519080825280601f01601f19166020018201604052801562000433576020820181803683370190505b5090505b8415620001af576200044b6001836200086b565b91506200045a600a8662000885565b620004679060306200089c565b60f81b8183815181106200047f576200047f620008b7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350620004bb600a8662000854565b945062000437565b611a8480620008e783390190565b60005b83811015620004ee578181015183820152602001620004d4565b83811115620004fe576000848401525b50505050565b600081518084526200051e816020860160208601620004d1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000565602083018462000504565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112620005ad57600080fd5b813567ffffffffffffffff80821115620005cb57620005cb6200056c565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156200061457620006146200056c565b816040528381528660208588010111156200062e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200066457600080fd5b833573ffffffffffffffffffffffffffffffffffffffff811681146200068957600080fd5b9250602084013567ffffffffffffffff80821115620006a757600080fd5b620006b5878388016200059b565b93506040860135915080821115620006cc57600080fd5b50620006db868287016200059b565b9150509250925092565b60008451620006f9818460208901620004d1565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855162000737816001850160208a01620004d1565b6001920191820152835162000754816002840160208801620004d1565b0160020195945050505050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250608060408301526200079c608083018562000504565b8281036060840152620007b0818562000504565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036200081e576200081e620007bb565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008262000866576200086662000825565b500490565b600082821015620008805762000880620007bb565b500390565b60008262000897576200089762000825565b500690565b60008219821115620008b257620008b2620007bb565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe6101206040523480156200001257600080fd5b5060405162001a8438038062001a8483398101604081905262000035916200016d565b6001600080848460036200004a83826200028c565b5060046200005982826200028c565b50505060809290925260a05260c05250506001600160a01b0390811660e052166101005262000358565b80516001600160a01b03811681146200009b57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000c857600080fd5b81516001600160401b0380821115620000e557620000e5620000a0565b604051601f8301601f19908116603f01168101908282118183101715620001105762000110620000a0565b816040528381526020925086838588010111156200012d57600080fd5b600091505b8382101562000151578582018301518183018401529082019062000132565b83821115620001635760008385830101525b9695505050505050565b600080600080608085870312156200018457600080fd5b6200018f8562000083565b93506200019f6020860162000083565b60408601519093506001600160401b0380821115620001bd57600080fd5b620001cb88838901620000b6565b93506060870151915080821115620001e257600080fd5b50620001f187828801620000b6565b91505092959194509250565b600181811c908216806200021257607f821691505b6020821081036200023357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200028757600081815260208120601f850160051c81016020861015620002625750805b601f850160051c820191505b8181101562000283578281556001016200026e565b5050505b505050565b81516001600160401b03811115620002a857620002a8620000a0565b620002c081620002b98454620001fd565b8462000239565b602080601f831160018114620002f85760008415620002df5750858301515b600019600386901b1c1916600185901b17855562000283565b600085815260208120601f198616915b82811015620003295788860151825594840194600190910190840162000308565b5085821015620003485787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051610100516116cb620003b9600039600081816102f50152818161038a015281816105cf01526107a90152600081816101a9015261031b015260006107380152600061070f015260006106e601526116cb6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e1461033f578063e78cea92146102f3578063ee9a31a21461038557600080fd5b8063ae1f6aaf146102f3578063c01e1bd614610319578063d6c0b2c41461031957600080fd5b80639dc29fac116100bd5780639dc29fac146102ba578063a457c2d7146102cd578063a9059cbb146102e057600080fd5b806370a082311461027c57806395d89b41146102b257600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461024c57806340c10f191461025f57806354fd4d501461027457600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611307565b6103ac565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f861049d565b60405161019b919061137c565b61018f6102133660046113f6565b61052f565b6002545b60405190815260200161019b565b61018f610238366004611420565b610547565b6040516012815260200161019b565b61018f61025a3660046113f6565b61056b565b61027261026d3660046113f6565b6105b7565b005b6101f86106df565b61021c61028a36600461145c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610782565b6102726102c83660046113f6565b610791565b61018f6102db3660046113f6565b6108a8565b61018f6102ee3660046113f6565b610979565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61034d366004611477565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061046557507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b8061049457507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ac906114aa565b80601f01602080910402602001604051908101604052809291908181526020018280546104d8906114aa565b80156105255780601f106104fa57610100808354040283529160200191610525565b820191906000526020600020905b81548152906001019060200180831161050857829003601f168201915b5050505050905090565b60003361053d818585610987565b5060019392505050565b600033610555858285610b3b565b610560858585610c12565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061053d90829086906105b290879061152c565b610987565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610681576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b61068b8282610ec5565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106d391815260200190565b60405180910390a25050565b606061070a7f0000000000000000000000000000000000000000000000000000000000000000610fe5565b6107337f0000000000000000000000000000000000000000000000000000000000000000610fe5565b61075c7f0000000000000000000000000000000000000000000000000000000000000000610fe5565b60405160200161076e93929190611544565b604051602081830303815290604052905090565b6060600480546104ac906114aa565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e0000000000000000000000006064820152608401610678565b6108608282611122565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106d391815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561096c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610678565b6105608286868403610987565b60003361053d818585610c12565b73ffffffffffffffffffffffffffffffffffffffff8316610a29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff8216610acc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c0c5781811015610bff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610678565b610c0c8484848403610987565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff8216610d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e5290849061152c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eb891815260200190565b60405180910390a3610c0c565b73ffffffffffffffffffffffffffffffffffffffff8216610f42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610678565b8060026000828254610f54919061152c565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f8e90849061152c565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361102857505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611052578061103c816115ba565b915061104b9050600a83611621565b915061102c565b60008167ffffffffffffffff81111561106d5761106d611635565b6040519080825280601f01601f191660200182016040528015611097576020820181803683370190505b5090505b841561111a576110ac600183611664565b91506110b9600a8661167b565b6110c490603061152c565b60f81b8183815181106110d9576110d961168f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611113600a86611621565b945061109b565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561127b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112b7908490611664565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b2e565b60006020828403121561131957600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461134957600080fd5b9392505050565b60005b8381101561136b578181015183820152602001611353565b83811115610c0c5750506000910152565b602081526000825180602084015261139b816040850160208701611350565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146113f157600080fd5b919050565b6000806040838503121561140957600080fd5b611412836113cd565b946020939093013593505050565b60008060006060848603121561143557600080fd5b61143e846113cd565b925061144c602085016113cd565b9150604084013590509250925092565b60006020828403121561146e57600080fd5b611349826113cd565b6000806040838503121561148a57600080fd5b611493836113cd565b91506114a1602084016113cd565b90509250929050565b600181811c908216806114be57607f821691505b6020821081036114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561153f5761153f6114fd565b500190565b60008451611556818460208901611350565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611592816001850160208a01611350565b600192019182015283516115ad816002840160208801611350565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036115eb576115eb6114fd565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611630576116306115f2565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015611676576116766114fd565b500390565b60008261168a5761168a6115f2565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a", - "deployedBytecode": "0x60806040523480156200001157600080fd5b5060043610620000525760003560e01c806354fd4d501462000057578063896f93d11462000079578063ce5ac90f14620000b6578063ee9a31a214620000cd575b600080fd5b62000061620000f5565b60405162000070919062000550565b60405180910390f35b620000906200008a3660046200064e565b620001a0565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200162000070565b62000090620000c73660046200064e565b620001b7565b620000907f000000000000000000000000000000000000000000000000000000000000000081565b6060620001227f000000000000000000000000000000000000000000000000000000000000000062000376565b6200014d7f000000000000000000000000000000000000000000000000000000000000000062000376565b620001787f000000000000000000000000000000000000000000000000000000000000000062000376565b6040516020016200018c93929190620006e5565b604051602081830303815290604052905090565b6000620001af848484620001b7565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff841662000261576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e206164647265737300606482015260840160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000008585856040516200029590620004c3565b620002a4949392919062000761565b604051809103906000f080158015620002c1573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf60405160405180910390a360405133815273ffffffffffffffffffffffffffffffffffffffff80871691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a3949350505050565b606081600003620003ba57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115620003ea5780620003d181620007ea565b9150620003e29050600a8362000854565b9150620003be565b60008167ffffffffffffffff8111156200040857620004086200056c565b6040519080825280601f01601f19166020018201604052801562000433576020820181803683370190505b5090505b8415620001af576200044b6001836200086b565b91506200045a600a8662000885565b620004679060306200089c565b60f81b8183815181106200047f576200047f620008b7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350620004bb600a8662000854565b945062000437565b611a8480620008e783390190565b60005b83811015620004ee578181015183820152602001620004d4565b83811115620004fe576000848401525b50505050565b600081518084526200051e816020860160208601620004d1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000565602083018462000504565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112620005ad57600080fd5b813567ffffffffffffffff80821115620005cb57620005cb6200056c565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156200061457620006146200056c565b816040528381528660208588010111156200062e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200066457600080fd5b833573ffffffffffffffffffffffffffffffffffffffff811681146200068957600080fd5b9250602084013567ffffffffffffffff80821115620006a757600080fd5b620006b5878388016200059b565b93506040860135915080821115620006cc57600080fd5b50620006db868287016200059b565b9150509250925092565b60008451620006f9818460208901620004d1565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855162000737816001850160208a01620004d1565b6001920191820152835162000754816002840160208801620004d1565b0160020195945050505050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250608060408301526200079c608083018562000504565b8281036060840152620007b0818562000504565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036200081e576200081e620007bb565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008262000866576200086662000825565b500490565b600082821015620008805762000880620007bb565b500390565b60008262000897576200089762000825565b500690565b60008219821115620008b257620008b2620007bb565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe6101206040523480156200001257600080fd5b5060405162001a8438038062001a8483398101604081905262000035916200016d565b6001600080848460036200004a83826200028c565b5060046200005982826200028c565b50505060809290925260a05260c05250506001600160a01b0390811660e052166101005262000358565b80516001600160a01b03811681146200009b57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000c857600080fd5b81516001600160401b0380821115620000e557620000e5620000a0565b604051601f8301601f19908116603f01168101908282118183101715620001105762000110620000a0565b816040528381526020925086838588010111156200012d57600080fd5b600091505b8382101562000151578582018301518183018401529082019062000132565b83821115620001635760008385830101525b9695505050505050565b600080600080608085870312156200018457600080fd5b6200018f8562000083565b93506200019f6020860162000083565b60408601519093506001600160401b0380821115620001bd57600080fd5b620001cb88838901620000b6565b93506060870151915080821115620001e257600080fd5b50620001f187828801620000b6565b91505092959194509250565b600181811c908216806200021257607f821691505b6020821081036200023357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200028757600081815260208120601f850160051c81016020861015620002625750805b601f850160051c820191505b8181101562000283578281556001016200026e565b5050505b505050565b81516001600160401b03811115620002a857620002a8620000a0565b620002c081620002b98454620001fd565b8462000239565b602080601f831160018114620002f85760008415620002df5750858301515b600019600386901b1c1916600185901b17855562000283565b600085815260208120601f198616915b82811015620003295788860151825594840194600190910190840162000308565b5085821015620003485787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051610100516116cb620003b9600039600081816102f50152818161038a015281816105cf01526107a90152600081816101a9015261031b015260006107380152600061070f015260006106e601526116cb6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e1461033f578063e78cea92146102f3578063ee9a31a21461038557600080fd5b8063ae1f6aaf146102f3578063c01e1bd614610319578063d6c0b2c41461031957600080fd5b80639dc29fac116100bd5780639dc29fac146102ba578063a457c2d7146102cd578063a9059cbb146102e057600080fd5b806370a082311461027c57806395d89b41146102b257600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461024c57806340c10f191461025f57806354fd4d501461027457600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a366004611307565b6103ac565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f861049d565b60405161019b919061137c565b61018f6102133660046113f6565b61052f565b6002545b60405190815260200161019b565b61018f610238366004611420565b610547565b6040516012815260200161019b565b61018f61025a3660046113f6565b61056b565b61027261026d3660046113f6565b6105b7565b005b6101f86106df565b61021c61028a36600461145c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610782565b6102726102c83660046113f6565b610791565b61018f6102db3660046113f6565b6108a8565b61018f6102ee3660046113f6565b610979565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c61034d366004611477565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061046557507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b8061049457507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b6060600380546104ac906114aa565b80601f01602080910402602001604051908101604052809291908181526020018280546104d8906114aa565b80156105255780601f106104fa57610100808354040283529160200191610525565b820191906000526020600020905b81548152906001019060200180831161050857829003601f168201915b5050505050905090565b60003361053d818585610987565b5060019392505050565b600033610555858285610b3b565b610560858585610c12565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061053d90829086906105b290879061152c565b610987565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610681576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b61068b8282610ec5565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516106d391815260200190565b60405180910390a25050565b606061070a7f0000000000000000000000000000000000000000000000000000000000000000610fe5565b6107337f0000000000000000000000000000000000000000000000000000000000000000610fe5565b61075c7f0000000000000000000000000000000000000000000000000000000000000000610fe5565b60405160200161076e93929190611544565b604051602081830303815290604052905090565b6060600480546104ac906114aa565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e0000000000000000000000006064820152608401610678565b6108608282611122565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516106d391815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561096c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610678565b6105608286868403610987565b60003361053d818585610c12565b73ffffffffffffffffffffffffffffffffffffffff8316610a29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff8216610acc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610c0c5781811015610bff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610678565b610c0c8484848403610987565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610cb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff8216610d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610e0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e5290849061152c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610eb891815260200190565b60405180910390a3610c0c565b73ffffffffffffffffffffffffffffffffffffffff8216610f42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610678565b8060026000828254610f54919061152c565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f8e90849061152c565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60608160000361102857505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611052578061103c816115ba565b915061104b9050600a83611621565b915061102c565b60008167ffffffffffffffff81111561106d5761106d611635565b6040519080825280601f01601f191660200182016040528015611097576020820181803683370190505b5090505b841561111a576110ac600183611664565b91506110b9600a8661167b565b6110c490603061152c565b60f81b8183815181106110d9576110d961168f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611113600a86611621565b945061109b565b949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166111c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff82166000908152602081905260409020548181101561127b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610678565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906112b7908490611664565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610b2e565b60006020828403121561131957600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461134957600080fd5b9392505050565b60005b8381101561136b578181015183820152602001611353565b83811115610c0c5750506000910152565b602081526000825180602084015261139b816040850160208701611350565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146113f157600080fd5b919050565b6000806040838503121561140957600080fd5b611412836113cd565b946020939093013593505050565b60008060006060848603121561143557600080fd5b61143e846113cd565b925061144c602085016113cd565b9150604084013590509250925092565b60006020828403121561146e57600080fd5b611349826113cd565b6000806040838503121561148a57600080fd5b611493836113cd565b91506114a1602084016113cd565b90509250929050565b600181811c908216806114be57607f821691505b6020821081036114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561153f5761153f6114fd565b500190565b60008451611556818460208901611350565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611592816001850160208a01611350565b600192019182015283516115ad816002840160208801611350565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036115eb576115eb6114fd565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611630576116306115f2565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015611676576116766114fd565b500390565b60008261168a5761168a6115f2565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_bridge": "Address of the StandardBridge on this chain." - } - }, - "createOptimismMintableERC20(address,string,string)": { - "params": { - "_name": "ERC20 name.", - "_remoteToken": "Address of the token on the remote chain.", - "_symbol": "ERC20 symbol." - }, - "returns": { - "_0": "Address of the newly created token." - } - }, - "createStandardL2Token(address,string,string)": { - "params": { - "_name": "ERC20 name.", - "_remoteToken": "Address of the token on the remote chain.", - "_symbol": "ERC20 symbol." - }, - "returns": { - "_0": "Address of the newly created token." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "events": { - "OptimismMintableERC20Created(address,address,address)": { - "params": { - "deployer": "Address of the account that deployed the token.", - "localToken": "Address of the created token on the local chain.", - "remoteToken": "Address of the corresponding token on the remote chain." - } - }, - "StandardL2TokenCreated(address,address)": { - "params": { - "localToken": "Address of the created token on the local chain.", - "remoteToken": "Address of the token on the remote chain." - } - } - }, - "title": "OptimismMintableERC20Factory" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "BRIDGE()": { - "notice": "Address of the StandardBridge on this chain." - }, - "constructor": { - "notice": "The semver MUST be bumped any time that there is a change in the OptimismMintableERC20 token contract since this contract is responsible for deploying OptimismMintableERC20 contracts." - }, - "createOptimismMintableERC20(address,string,string)": { - "notice": "Creates an instance of the OptimismMintableERC20 contract." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "events": { - "OptimismMintableERC20Created(address,address,address)": { - "notice": "Emitted whenever a new OptimismMintableERC20 is created." - } - }, - "notice": "OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20 contracts on the network it's deployed to. Simplifies the deployment process for users who may be less familiar with deploying smart contracts. Designed to be backwards compatible with the older StandardL2ERC20Factory contract." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/OptimismMintableERC721Factory.json b/packages/contracts-bedrock/deployments/optimism-goerli/OptimismMintableERC721Factory.json deleted file mode 100644 index db548aa72994..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/OptimismMintableERC721Factory.json +++ /dev/null @@ -1,253 +0,0 @@ -{ - "address": "0x13DcfC403eCEF3E8Eab66C00dC64e793dc40Be1d", - "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": [], - "name": "REMOTE_CHAIN_ID", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "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": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x66bd3795a6bef6b6ab0942e832c304d3bea5663d2ede9b5af06bffdc033619a3", - "receipt": { - "to": null, - "from": "0xf80267194936da1E98dB10bcE06F3147D580a62e", - "contractAddress": "0x13DcfC403eCEF3E8Eab66C00dC64e793dc40Be1d", - "transactionIndex": 1, - "gasUsed": "3372345", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x1d0825f07a8ddff70a90349d805448866f966283135060195e3dc0baed203f49", - "transactionHash": "0x66bd3795a6bef6b6ab0942e832c304d3bea5663d2ede9b5af06bffdc033619a3", - "logs": [], - "blockNumber": 8579713, - "cumulativeGasUsed": "3419258", - "status": 1, - "byzantium": true - }, - "args": [ - "0x4200000000000000000000000000000000000010", - "5" - ], - "numDeployments": 1, - "solcInputHash": "2d538e296d12ca6101a896ac2e894043", - "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\":[],\"name\":\"REMOTE_CHAIN_ID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"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.2.0\",\"params\":{\"_bridge\":\"Address of the ERC721 bridge on this network.\",\"_remoteChainId\":\"Chain ID for the remote 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.\"},\"REMOTE_CHAIN_ID()\":{\"notice\":\"Chain ID for the remote network.\"},\"constructor\":{\"notice\":\"The semver MUST be bumped any time that there is a change in the OptimismMintableERC721 token contract since this contract is responsible for deploying OptimismMintableERC721 contracts.\"},\"createOptimismMintableERC721(address,string,string)\":{\"notice\":\"Creates an instance of the standard ERC721.\"},\"isOptimismMintableERC721(address)\":{\"notice\":\"Tracks addresses created by this factory.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"Factory contract for creating OptimismMintableERC721 contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/OptimismMintableERC721Factory.sol\":\"OptimismMintableERC721Factory\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/universal/IOptimismMintableERC721.sol\":{\"keccak256\":\"0xf1a3dd4452df8882a65a31c5e2e8de7872b08cf078be7a5a7da51e6f75c53ad3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b09a2560cae35ca4789fe1ff5edb2bae9fa7dcda115a55f7ccdcc974a2e37526\",\"dweb:/ipfs/QmPQeTvrJ4SJpng5VGZNMf1u85NWxrdus4gGn8xYkHddKM\"]},\"contracts/universal/OptimismMintableERC721.sol\":{\"keccak256\":\"0xfafd77f2c45ef4295478335243b930fd19fffdc820ed424805f37f197915f03e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://05be10c5e73ec56376e90b73dc55a6a5f491a275a8e941a87db5671b40685665\",\"dweb:/ipfs/QmPnc4aFuRCJLVm3GuRfzxMyXxjBnoeRyzMsCz6nxQxrrB\"]},\"contracts/universal/OptimismMintableERC721Factory.sol\":{\"keccak256\":\"0x5dab871aef66fc09336f2f2c6bd0dbea17036bfa6ece27f10cb4a6241f95f561\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f230320a93cc2769fb0f738e367ed4d7b0eb9385d37eb783137e1a56d927ce08\",\"dweb:/ipfs/QmdaVF27BNxV7SFrE1QeVbFJd25tvVdHUVnUAreFoR4E8K\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9baf7797439c0ae6512f4639dfc6a1934dbd4e4d7cbb8e63e99264ff47682c9e\",\"dweb:/ipfs/QmawAuhppPyeoZH3rC1uh87xDELa9Lyfw5pYsBqE8myE1m\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol\":{\"keccak256\":\"0x0b606994df12f0ce35f6d2f6dcdde7e55e6899cdef7e00f180980caa81e3844e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4c827c981a552d1c76c96060e92f56b52bc20c6f9b4dbf911fe99ddbfb41f2ea\",\"dweb:/ipfs/QmW8xvJdzHrr8Ry34C7viBsgG2b8T1mL4BQWJ5CdfD9JLB\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"keccak256\":\"0xed6a749c5373af398105ce6ee3ac4763aa450ea7285d268c85d9eeca809cdb1f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://20a97f891d06f0fe91560ea1a142aaa26fdd22bed1b51606b7d48f670deeb50f\",\"dweb:/ipfs/QmTbCtZKChpaX5H2iRiTDMcSz29GSLCpTCDgJpcMR4wg8x\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6e75cf83beb757b8855791088546b8337e9d4684e169400c20d44a515353b708\",\"dweb:/ipfs/QmYvPafLfoquiDMEj7CKHtvbgHu7TJNPSVPSCjrtjV8HjV\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\":{\"keccak256\":\"0x0a79511df8151b10b0a0004d6a76ad956582d32824af4c0f4886bdbdfe5746e5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://afbedcf17f31db719e6fdc56caa8f458799c5fa2eb94cb1e94ef18f89af85768\",\"dweb:/ipfs/QmVmqRdBfbgYThpZSoAJ5o9mnAMjx8mCHHjv3Rh8cQAAg3\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://26fef835622b46a5ba08b3ef6b46a22e94b5f285d0f0fb66b703bd30217d2c34\",\"dweb:/ipfs/QmZ548qdwfL1qF7aXz3xh1GCdTiST81kGGuKRqVUfYmPZR\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a0a107160525724f9e1bbbab031defc2f298296dd9e331f16a6f7130cec32146\",\"dweb:/ipfs/QmemujxSd7gX8A9M8UwmNbz4Ms3U9FG9QfudUgxwvTmPWf\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fb0048dee081f6fffa5f74afc3fb328483c2a30504e94a0ddd2a5114d731ec4d\",\"dweb:/ipfs/QmZptt1nmYoA5SgjwnSgWqgUSDgm4q52Yos3xhnMv3MV43\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"]}},\"version\":1}", - "bytecode": "0x61012060405234801561001157600080fd5b50604051613d6c380380613d6c83398101604081905261003091610056565b6001608052600260a052600060c0526001600160a01b0390911660e05261010052610090565b6000806040838503121561006957600080fd5b82516001600160a01b038116811461008057600080fd5b6020939093015192949293505050565b60805160a05160c05160e05161010051613c8b6100e16000396000818160d3015261030a01526000818161014701526102e9015260006101c70152600061019c015260006101710152613c8b6000f3fe60806040523480156200001157600080fd5b50600436106200006f5760003560e01c80637d1d0c5b11620000565780637d1d0c5b14620000cd578063d97df6521462000104578063ee9a31a2146200014157600080fd5b806354fd4d5014620000745780635572acae1462000096575b600080fd5b6200007e62000169565b6040516200008d9190620005dc565b60405180910390f35b620000bc620000a736600462000622565b60006020819052908152604090205460ff1681565b60405190151581526020016200008d565b620000f57f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016200008d565b6200011b6200011536600462000722565b62000214565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016200008d565b6200011b7f000000000000000000000000000000000000000000000000000000000000000081565b6060620001967f0000000000000000000000000000000000000000000000000000000000000000620003fa565b620001c17f0000000000000000000000000000000000000000000000000000000000000000620003fa565b620001ec7f0000000000000000000000000000000000000000000000000000000000000000620003fa565b60405160200162000200939291906200079f565b604051602081830303815290604052905090565b600073ffffffffffffffffffffffffffffffffffffffff8416620002e5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a204c908201527f3120746f6b656e20616464726573732063616e6e6f742062652061646472657360648201527f7328302900000000000000000000000000000000000000000000000000000000608482015260a40160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008686866040516200033a906200054f565b6200034a9594939291906200081b565b604051809103906000f08015801562000367573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff8181166000818152602081815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590513381529394509188169290917fe72783bb8e0ca31286b85278da59684dd814df9762a52f0837f89edd1483b299910160405180910390a3949350505050565b6060816000036200043e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156200046e57806200045581620008ab565b9150620004669050600a8362000915565b915062000442565b60008167ffffffffffffffff8111156200048c576200048c62000640565b6040519080825280601f01601f191660200182016040528015620004b7576020820181803683370190505b5090505b84156200054757620004cf6001836200092c565b9150620004de600a8662000946565b620004eb9060306200095d565b60f81b81838151811062000503576200050362000978565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506200053f600a8662000915565b9450620004bb565b949350505050565b6132d780620009a883390190565b60005b838110156200057a57818101518382015260200162000560565b838111156200058a576000848401525b50505050565b60008151808452620005aa8160208601602086016200055d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005f1602083018462000590565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061d57600080fd5b919050565b6000602082840312156200063557600080fd5b620005f182620005f8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200068157600080fd5b813567ffffffffffffffff808211156200069f576200069f62000640565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006e857620006e862000640565b816040528381528660208588010111156200070257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200073857600080fd5b6200074384620005f8565b9250602084013567ffffffffffffffff808211156200076157600080fd5b6200076f878388016200066f565b935060408601359150808211156200078657600080fd5b5062000795868287016200066f565b9150509250925092565b60008451620007b38184602089016200055d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551620007f1816001850160208a016200055d565b600192019182015283516200080e8160028401602088016200055d565b0160020195945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835286602084015280861660408401525060a060608301526200085c60a083018562000590565b828103608084015262000870818562000590565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620008df57620008df6200087c565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082620009275762000927620008e6565b500490565b6000828210156200094157620009416200087c565b500390565b600082620009585762000958620008e6565b500690565b600082198211156200097357620009736200087c565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe6101406040523480156200001257600080fd5b50604051620032d7380380620032d7833981016040819052620000359162000640565b600180600084848262000049838262000769565b50600162000058828262000769565b50505060809290925260a05260c0526001600160a01b038516620000e95760405162461bcd60e51b815260206004820152603360248201527f4f7074696d69736d4d696e7461626c654552433732313a20627269646765206360448201527f616e6e6f7420626520616464726573732830290000000000000000000000000060648201526084015b60405180910390fd5b83600003620001615760405162461bcd60e51b815260206004820152603660248201527f4f7074696d69736d4d696e7461626c654552433732313a2072656d6f7465206360448201527f6861696e2069642063616e6e6f74206265207a65726f000000000000000000006064820152608401620000e0565b6001600160a01b038316620001df5760405162461bcd60e51b815260206004820152603960248201527f4f7074696d69736d4d696e7461626c654552433732313a2072656d6f7465207460448201527f6f6b656e2063616e6e6f742062652061646472657373283029000000000000006064820152608401620000e0565b60e08490526001600160a01b03838116610100819052908616610120526200021590601462000269602090811b62000f5c17901c565b6200022b856200042960201b6200119f1760201c565b6040516020016200023e92919062000835565b604051602081830303815290604052600a90816200025d919062000769565b505050505050620009a6565b606060006200027a836002620008bf565b62000287906002620008e1565b6001600160401b03811115620002a157620002a162000566565b6040519080825280601f01601f191660200182016040528015620002cc576020820181803683370190505b509050600360fc1b81600081518110620002ea57620002ea620008fc565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106200031c576200031c620008fc565b60200101906001600160f81b031916908160001a905350600062000342846002620008bf565b6200034f906001620008e1565b90505b6001811115620003d1576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110620003875762000387620008fc565b1a60f81b828281518110620003a057620003a0620008fc565b60200101906001600160f81b031916908160001a90535060049490941c93620003c98162000912565b905062000352565b508315620004225760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401620000e0565b9392505050565b606081600003620004515750506040805180820190915260018152600360fc1b602082015290565b8160005b811562000481578062000468816200092c565b9150620004799050600a836200095e565b915062000455565b6000816001600160401b038111156200049e576200049e62000566565b6040519080825280601f01601f191660200182016040528015620004c9576020820181803683370190505b5090505b84156200054157620004e160018362000975565b9150620004f0600a866200098f565b620004fd906030620008e1565b60f81b818381518110620005155762000515620008fc565b60200101906001600160f81b031916908160001a90535062000539600a866200095e565b9450620004cd565b949350505050565b80516001600160a01b03811681146200056157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620005995781810151838201526020016200057f565b83811115620005a9576000848401525b50505050565b600082601f830112620005c157600080fd5b81516001600160401b0380821115620005de57620005de62000566565b604051601f8301601f19908116603f0116810190828211818310171562000609576200060962000566565b816040528381528660208588010111156200062357600080fd5b620006368460208301602089016200057c565b9695505050505050565b600080600080600060a086880312156200065957600080fd5b620006648662000549565b9450602086015193506200067b6040870162000549565b60608701519093506001600160401b03808211156200069957600080fd5b620006a789838a01620005af565b93506080880151915080821115620006be57600080fd5b50620006cd88828901620005af565b9150509295509295909350565b600181811c90821680620006ef57607f821691505b6020821081036200071057634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200076457600081815260208120601f850160051c810160208610156200073f5750805b601f850160051c820191505b8181101562000760578281556001016200074b565b5050505b505050565b81516001600160401b0381111562000785576200078562000566565b6200079d81620007968454620006da565b8462000716565b602080601f831160018114620007d55760008415620007bc5750858301515b600019600386901b1c1916600185901b17855562000760565b600085815260208120601f198616915b828110156200080657888601518255948401946001909101908401620007e5565b5085821015620008255787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6832ba3432b932bab69d60b91b8152600083516200085b8160098501602088016200057c565b600160fe1b60099184019182015283516200087e81600a8401602088016200057c565b712f746f6b656e5552493f75696e743235363d60701b600a9290910191820152601c01949350505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620008dc57620008dc620008a9565b500290565b60008219821115620008f757620008f7620008a9565b500190565b634e487b7160e01b600052603260045260246000fd5b600081620009245762000924620008a9565b506000190190565b600060018201620009415762000941620008a9565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008262000970576200097062000948565b500490565b6000828210156200098a576200098a620008a9565b500390565b600082620009a157620009a162000948565b500690565b60805160a05160c05160e05161010051610120516128be62000a19600039600081816103ae0152818161044601528181610b900152610cb20152600081816101e001526103880152600081816102f501526103d4015260006109bf015260006109960152600061096d01526128be6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80637d1d0c5b116100ee578063c87b56dd11610097578063e78cea9211610071578063e78cea92146103ac578063e9518196146103d2578063e985e9c5146103f8578063ee9a31a21461044157600080fd5b8063c87b56dd1461036b578063d547cfb71461037e578063d6c0b2c41461038657600080fd5b8063a1448194116100c8578063a144819414610332578063a22cb46514610345578063b88d4fde1461035857600080fd5b80637d1d0c5b146102f057806395d89b41146103175780639dc29fac1461031f57600080fd5b806323b872dd1161015b5780634f6ccce7116101355780634f6ccce7146102af57806354fd4d50146102c25780636352211e146102ca57806370a08231146102dd57600080fd5b806323b872dd146102765780632f745c591461028957806342842e0e1461029c57600080fd5b8063081812fc1161018c578063081812fc1461023c578063095ea7b31461024f57806318160ddd1461026457600080fd5b806301ffc9a7146101b3578063033964be146101db57806306fdde0314610227575b600080fd5b6101c66101c1366004612295565b610468565b60405190151581526020015b60405180910390f35b6102027f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d2565b61022f6104c6565b6040516101d29190612328565b61020261024a36600461233b565b610558565b61026261025d36600461237d565b61058c565b005b6008545b6040519081526020016101d2565b6102626102843660046123a7565b61071d565b61026861029736600461237d565b6107be565b6102626102aa3660046123a7565b61088d565b6102686102bd36600461233b565b6108a8565b61022f610966565b6102026102d836600461233b565b610a09565b6102686102eb3660046123e3565b610a9b565b6102687f000000000000000000000000000000000000000000000000000000000000000081565b61022f610b69565b61026261032d36600461237d565b610b78565b61026261034036600461237d565b610c9a565b6102626103533660046123fe565b610db1565b610262610366366004612469565b610dc0565b61022f61037936600461233b565b610e68565b61022f610ece565b7f0000000000000000000000000000000000000000000000000000000000000000610202565b7f0000000000000000000000000000000000000000000000000000000000000000610202565b7f0000000000000000000000000000000000000000000000000000000000000000610268565b6101c6610406366004612563565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260056020908152604080832093909416825291909152205460ff1690565b6102027f000000000000000000000000000000000000000000000000000000000000000081565b60007f74259ebf000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083168114806104bf57506104bf836112dc565b9392505050565b6060600080546104d590612596565b80601f016020809104026020016040519081016040528092919081815260200182805461050190612596565b801561054e5780601f106105235761010080835404028352916020019161054e565b820191906000526020600020905b81548152906001019060200180831161053157829003601f168201915b5050505050905090565b600061056382611332565b5060009081526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b600061059782610a09565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610659576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f720000000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff8216148061068257506106828133610406565b61070e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c00006064820152608401610650565b61071883836113c0565b505050565b6107273382611460565b6107b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610650565b61071883838361151f565b60006107c983610a9b565b8210610857576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e64730000000000000000000000000000000000000000006064820152608401610650565b5073ffffffffffffffffffffffffffffffffffffffff919091166000908152600660209081526040808320938352929052205490565b61071883838360405180602001604052806000815250610dc0565b60006108b360085490565b8210610941576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e647300000000000000000000000000000000000000006064820152608401610650565b60088281548110610954576109546125e9565b90600052602060002001549050919050565b60606109917f000000000000000000000000000000000000000000000000000000000000000061119f565b6109ba7f000000000000000000000000000000000000000000000000000000000000000061119f565b6109e37f000000000000000000000000000000000000000000000000000000000000000061119f565b6040516020016109f593929190612618565b604051602081830303815290604052905090565b60008181526002602052604081205473ffffffffffffffffffffffffffffffffffffffff1680610a95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610650565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff8216610b40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f74206120766160448201527f6c6964206f776e657200000000000000000000000000000000000000000000006064820152608401610650565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205490565b6060600180546104d590612596565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610c3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e0000000000006064820152608401610650565b610c4681611791565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca582604051610c8e91815260200190565b60405180910390a25050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e0000000000006064820152608401610650565b610d69828261186a565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688582604051610c8e91815260200190565b610dbc338383611884565b5050565b610dca3383611460565b610e56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610650565b610e62848484846119b1565b50505050565b6060610e7382611332565b6000610e7d611a54565b90506000815111610e9d57604051806020016040528060008152506104bf565b80610ea78461119f565b604051602001610eb892919061268e565b6040516020818303038152906040529392505050565b600a8054610edb90612596565b80601f0160208091040260200160405190810160405280929190818152602001828054610f0790612596565b8015610f545780601f10610f2957610100808354040283529160200191610f54565b820191906000526020600020905b815481529060010190602001808311610f3757829003601f168201915b505050505081565b60606000610f6b8360026126ec565b610f76906002612729565b67ffffffffffffffff811115610f8e57610f8e61243a565b6040519080825280601f01601f191660200182016040528015610fb8576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110610fef57610fef6125e9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611052576110526125e9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061108e8460026126ec565b611099906001612729565b90505b6001811115611136577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106110da576110da6125e9565b1a60f81b8282815181106110f0576110f06125e9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361112f81612741565b905061109c565b5083156104bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610650565b6060816000036111e257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561120c57806111f681612776565b91506112059050600a836127dd565b91506111e6565b60008167ffffffffffffffff8111156112275761122761243a565b6040519080825280601f01601f191660200182016040528015611251576020820181803683370190505b5090505b84156112d4576112666001836127f1565b9150611273600a86612808565b61127e906030612729565b60f81b818381518110611293576112936125e9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506112cd600a866127dd565b9450611255565b949350505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d63000000000000000000000000000000000000000000000000000000001480610a955750610a9582611a63565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff166113bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610650565b50565b600081815260046020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155819061141a82610a09565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008061146c83610a09565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806114da575073ffffffffffffffffffffffffffffffffffffffff80821660009081526005602090815260408083209388168352929052205460ff165b806112d457508373ffffffffffffffffffffffffffffffffffffffff1661150084610558565b73ffffffffffffffffffffffffffffffffffffffff1614949350505050565b8273ffffffffffffffffffffffffffffffffffffffff1661153f82610a09565b73ffffffffffffffffffffffffffffffffffffffff16146115e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610650565b73ffffffffffffffffffffffffffffffffffffffff8216611684576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610650565b61168f838383611b46565b61169a6000826113c0565b73ffffffffffffffffffffffffffffffffffffffff831660009081526003602052604081208054600192906116d09084906127f1565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600090815260036020526040812080546001929061170b908490612729565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061179c82610a09565b90506117aa81600084611b46565b6117b56000836113c0565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054600192906117eb9084906127f1565b909155505060008281526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555183919073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b610dbc828260405180602001604052806000815250611c4c565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611919576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610650565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526005602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6119bc84848461151f565b6119c884848484611cef565b610e62576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610650565b6060600a80546104d590612596565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd000000000000000000000000000000000000000000000000000000001480611af657507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b80610a9557507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610a95565b73ffffffffffffffffffffffffffffffffffffffff8316611bae57611ba981600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b611beb565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614611beb57611beb8382611ee2565b73ffffffffffffffffffffffffffffffffffffffff8216611c0f5761071881611f99565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610718576107188282612048565b611c568383612099565b611c636000848484611cef565b610718576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610650565b600073ffffffffffffffffffffffffffffffffffffffff84163b15611ed7576040517f150b7a0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063150b7a0290611d6690339089908890889060040161281c565b6020604051808303816000875af1925050508015611dbf575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611dbc91810190612865565b60015b611e8c573d808015611ded576040519150601f19603f3d011682016040523d82523d6000602084013e611df2565b606091505b508051600003611e84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610650565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001490506112d4565b506001949350505050565b60006001611eef84610a9b565b611ef991906127f1565b600083815260076020526040902054909150808214611f595773ffffffffffffffffffffffffffffffffffffffff841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b50600091825260076020908152604080842084905573ffffffffffffffffffffffffffffffffffffffff9094168352600681528383209183525290812055565b600854600090611fab906001906127f1565b60008381526009602052604081205460088054939450909284908110611fd357611fd36125e9565b906000526020600020015490508060088381548110611ff457611ff46125e9565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061202c5761202c612882565b6001900381819060005260206000200160009055905550505050565b600061205383610a9b565b73ffffffffffffffffffffffffffffffffffffffff9093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b73ffffffffffffffffffffffffffffffffffffffff8216612116576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610650565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16156121a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610650565b6121ae60008383611b46565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081208054600192906121e4908490612729565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff00000000000000000000000000000000000000000000000000000000811681146113bd57600080fd5b6000602082840312156122a757600080fd5b81356104bf81612267565b60005b838110156122cd5781810151838201526020016122b5565b83811115610e625750506000910152565b600081518084526122f68160208601602086016122b2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104bf60208301846122de565b60006020828403121561234d57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461237857600080fd5b919050565b6000806040838503121561239057600080fd5b61239983612354565b946020939093013593505050565b6000806000606084860312156123bc57600080fd5b6123c584612354565b92506123d360208501612354565b9150604084013590509250925092565b6000602082840312156123f557600080fd5b6104bf82612354565b6000806040838503121561241157600080fd5b61241a83612354565b91506020830135801515811461242f57600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000806080858703121561247f57600080fd5b61248885612354565b935061249660208601612354565b925060408501359150606085013567ffffffffffffffff808211156124ba57600080fd5b818701915087601f8301126124ce57600080fd5b8135818111156124e0576124e061243a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156125265761252661243a565b816040528281528a602084870101111561253f57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561257657600080fd5b61257f83612354565b915061258d60208401612354565b90509250929050565b600181811c908216806125aa57607f821691505b6020821081036125e3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000845161262a8184602089016122b2565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612666816001850160208a016122b2565b600192019182015283516126818160028401602088016122b2565b0160020195945050505050565b600083516126a08184602088016122b2565b8351908301906126b48183602088016122b2565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612724576127246126bd565b500290565b6000821982111561273c5761273c6126bd565b500190565b600081612750576127506126bd565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036127a7576127a76126bd565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826127ec576127ec6127ae565b500490565b600082821015612803576128036126bd565b500390565b600082612817576128176127ae565b500690565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152508360408301526080606083015261285b60808301846122de565b9695505050505050565b60006020828403121561287757600080fd5b81516104bf81612267565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a", - "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200006f5760003560e01c80637d1d0c5b11620000565780637d1d0c5b14620000cd578063d97df6521462000104578063ee9a31a2146200014157600080fd5b806354fd4d5014620000745780635572acae1462000096575b600080fd5b6200007e62000169565b6040516200008d9190620005dc565b60405180910390f35b620000bc620000a736600462000622565b60006020819052908152604090205460ff1681565b60405190151581526020016200008d565b620000f57f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016200008d565b6200011b6200011536600462000722565b62000214565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016200008d565b6200011b7f000000000000000000000000000000000000000000000000000000000000000081565b6060620001967f0000000000000000000000000000000000000000000000000000000000000000620003fa565b620001c17f0000000000000000000000000000000000000000000000000000000000000000620003fa565b620001ec7f0000000000000000000000000000000000000000000000000000000000000000620003fa565b60405160200162000200939291906200079f565b604051602081830303815290604052905090565b600073ffffffffffffffffffffffffffffffffffffffff8416620002e5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4f7074696d69736d4d696e7461626c65455243373231466163746f72793a204c908201527f3120746f6b656e20616464726573732063616e6e6f742062652061646472657360648201527f7328302900000000000000000000000000000000000000000000000000000000608482015260a40160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008686866040516200033a906200054f565b6200034a9594939291906200081b565b604051809103906000f08015801562000367573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff8181166000818152602081815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590513381529394509188169290917fe72783bb8e0ca31286b85278da59684dd814df9762a52f0837f89edd1483b299910160405180910390a3949350505050565b6060816000036200043e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156200046e57806200045581620008ab565b9150620004669050600a8362000915565b915062000442565b60008167ffffffffffffffff8111156200048c576200048c62000640565b6040519080825280601f01601f191660200182016040528015620004b7576020820181803683370190505b5090505b84156200054757620004cf6001836200092c565b9150620004de600a8662000946565b620004eb9060306200095d565b60f81b81838151811062000503576200050362000978565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506200053f600a8662000915565b9450620004bb565b949350505050565b6132d780620009a883390190565b60005b838110156200057a57818101518382015260200162000560565b838111156200058a576000848401525b50505050565b60008151808452620005aa8160208601602086016200055d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000620005f1602083018462000590565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146200061d57600080fd5b919050565b6000602082840312156200063557600080fd5b620005f182620005f8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200068157600080fd5b813567ffffffffffffffff808211156200069f576200069f62000640565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620006e857620006e862000640565b816040528381528660208588010111156200070257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156200073857600080fd5b6200074384620005f8565b9250602084013567ffffffffffffffff808211156200076157600080fd5b6200076f878388016200066f565b935060408601359150808211156200078657600080fd5b5062000795868287016200066f565b9150509250925092565b60008451620007b38184602089016200055d565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551620007f1816001850160208a016200055d565b600192019182015283516200080e8160028401602088016200055d565b0160020195945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835286602084015280861660408401525060a060608301526200085c60a083018562000590565b828103608084015262000870818562000590565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620008df57620008df6200087c565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082620009275762000927620008e6565b500490565b6000828210156200094157620009416200087c565b500390565b600082620009585762000958620008e6565b500690565b600082198211156200097357620009736200087c565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe6101406040523480156200001257600080fd5b50604051620032d7380380620032d7833981016040819052620000359162000640565b600180600084848262000049838262000769565b50600162000058828262000769565b50505060809290925260a05260c0526001600160a01b038516620000e95760405162461bcd60e51b815260206004820152603360248201527f4f7074696d69736d4d696e7461626c654552433732313a20627269646765206360448201527f616e6e6f7420626520616464726573732830290000000000000000000000000060648201526084015b60405180910390fd5b83600003620001615760405162461bcd60e51b815260206004820152603660248201527f4f7074696d69736d4d696e7461626c654552433732313a2072656d6f7465206360448201527f6861696e2069642063616e6e6f74206265207a65726f000000000000000000006064820152608401620000e0565b6001600160a01b038316620001df5760405162461bcd60e51b815260206004820152603960248201527f4f7074696d69736d4d696e7461626c654552433732313a2072656d6f7465207460448201527f6f6b656e2063616e6e6f742062652061646472657373283029000000000000006064820152608401620000e0565b60e08490526001600160a01b03838116610100819052908616610120526200021590601462000269602090811b62000f5c17901c565b6200022b856200042960201b6200119f1760201c565b6040516020016200023e92919062000835565b604051602081830303815290604052600a90816200025d919062000769565b505050505050620009a6565b606060006200027a836002620008bf565b62000287906002620008e1565b6001600160401b03811115620002a157620002a162000566565b6040519080825280601f01601f191660200182016040528015620002cc576020820181803683370190505b509050600360fc1b81600081518110620002ea57620002ea620008fc565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106200031c576200031c620008fc565b60200101906001600160f81b031916908160001a905350600062000342846002620008bf565b6200034f906001620008e1565b90505b6001811115620003d1576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110620003875762000387620008fc565b1a60f81b828281518110620003a057620003a0620008fc565b60200101906001600160f81b031916908160001a90535060049490941c93620003c98162000912565b905062000352565b508315620004225760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401620000e0565b9392505050565b606081600003620004515750506040805180820190915260018152600360fc1b602082015290565b8160005b811562000481578062000468816200092c565b9150620004799050600a836200095e565b915062000455565b6000816001600160401b038111156200049e576200049e62000566565b6040519080825280601f01601f191660200182016040528015620004c9576020820181803683370190505b5090505b84156200054157620004e160018362000975565b9150620004f0600a866200098f565b620004fd906030620008e1565b60f81b818381518110620005155762000515620008fc565b60200101906001600160f81b031916908160001a90535062000539600a866200095e565b9450620004cd565b949350505050565b80516001600160a01b03811681146200056157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620005995781810151838201526020016200057f565b83811115620005a9576000848401525b50505050565b600082601f830112620005c157600080fd5b81516001600160401b0380821115620005de57620005de62000566565b604051601f8301601f19908116603f0116810190828211818310171562000609576200060962000566565b816040528381528660208588010111156200062357600080fd5b620006368460208301602089016200057c565b9695505050505050565b600080600080600060a086880312156200065957600080fd5b620006648662000549565b9450602086015193506200067b6040870162000549565b60608701519093506001600160401b03808211156200069957600080fd5b620006a789838a01620005af565b93506080880151915080821115620006be57600080fd5b50620006cd88828901620005af565b9150509295509295909350565b600181811c90821680620006ef57607f821691505b6020821081036200071057634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200076457600081815260208120601f850160051c810160208610156200073f5750805b601f850160051c820191505b8181101562000760578281556001016200074b565b5050505b505050565b81516001600160401b0381111562000785576200078562000566565b6200079d81620007968454620006da565b8462000716565b602080601f831160018114620007d55760008415620007bc5750858301515b600019600386901b1c1916600185901b17855562000760565b600085815260208120601f198616915b828110156200080657888601518255948401946001909101908401620007e5565b5085821015620008255787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6832ba3432b932bab69d60b91b8152600083516200085b8160098501602088016200057c565b600160fe1b60099184019182015283516200087e81600a8401602088016200057c565b712f746f6b656e5552493f75696e743235363d60701b600a9290910191820152601c01949350505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620008dc57620008dc620008a9565b500290565b60008219821115620008f757620008f7620008a9565b500190565b634e487b7160e01b600052603260045260246000fd5b600081620009245762000924620008a9565b506000190190565b600060018201620009415762000941620008a9565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008262000970576200097062000948565b500490565b6000828210156200098a576200098a620008a9565b500390565b600082620009a157620009a162000948565b500690565b60805160a05160c05160e05161010051610120516128be62000a19600039600081816103ae0152818161044601528181610b900152610cb20152600081816101e001526103880152600081816102f501526103d4015260006109bf015260006109960152600061096d01526128be6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80637d1d0c5b116100ee578063c87b56dd11610097578063e78cea9211610071578063e78cea92146103ac578063e9518196146103d2578063e985e9c5146103f8578063ee9a31a21461044157600080fd5b8063c87b56dd1461036b578063d547cfb71461037e578063d6c0b2c41461038657600080fd5b8063a1448194116100c8578063a144819414610332578063a22cb46514610345578063b88d4fde1461035857600080fd5b80637d1d0c5b146102f057806395d89b41146103175780639dc29fac1461031f57600080fd5b806323b872dd1161015b5780634f6ccce7116101355780634f6ccce7146102af57806354fd4d50146102c25780636352211e146102ca57806370a08231146102dd57600080fd5b806323b872dd146102765780632f745c591461028957806342842e0e1461029c57600080fd5b8063081812fc1161018c578063081812fc1461023c578063095ea7b31461024f57806318160ddd1461026457600080fd5b806301ffc9a7146101b3578063033964be146101db57806306fdde0314610227575b600080fd5b6101c66101c1366004612295565b610468565b60405190151581526020015b60405180910390f35b6102027f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d2565b61022f6104c6565b6040516101d29190612328565b61020261024a36600461233b565b610558565b61026261025d36600461237d565b61058c565b005b6008545b6040519081526020016101d2565b6102626102843660046123a7565b61071d565b61026861029736600461237d565b6107be565b6102626102aa3660046123a7565b61088d565b6102686102bd36600461233b565b6108a8565b61022f610966565b6102026102d836600461233b565b610a09565b6102686102eb3660046123e3565b610a9b565b6102687f000000000000000000000000000000000000000000000000000000000000000081565b61022f610b69565b61026261032d36600461237d565b610b78565b61026261034036600461237d565b610c9a565b6102626103533660046123fe565b610db1565b610262610366366004612469565b610dc0565b61022f61037936600461233b565b610e68565b61022f610ece565b7f0000000000000000000000000000000000000000000000000000000000000000610202565b7f0000000000000000000000000000000000000000000000000000000000000000610202565b7f0000000000000000000000000000000000000000000000000000000000000000610268565b6101c6610406366004612563565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260056020908152604080832093909416825291909152205460ff1690565b6102027f000000000000000000000000000000000000000000000000000000000000000081565b60007f74259ebf000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083168114806104bf57506104bf836112dc565b9392505050565b6060600080546104d590612596565b80601f016020809104026020016040519081016040528092919081815260200182805461050190612596565b801561054e5780601f106105235761010080835404028352916020019161054e565b820191906000526020600020905b81548152906001019060200180831161053157829003601f168201915b5050505050905090565b600061056382611332565b5060009081526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b600061059782610a09565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610659576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f720000000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff8216148061068257506106828133610406565b61070e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c00006064820152608401610650565b61071883836113c0565b505050565b6107273382611460565b6107b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610650565b61071883838361151f565b60006107c983610a9b565b8210610857576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e64730000000000000000000000000000000000000000006064820152608401610650565b5073ffffffffffffffffffffffffffffffffffffffff919091166000908152600660209081526040808320938352929052205490565b61071883838360405180602001604052806000815250610dc0565b60006108b360085490565b8210610941576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e647300000000000000000000000000000000000000006064820152608401610650565b60088281548110610954576109546125e9565b90600052602060002001549050919050565b60606109917f000000000000000000000000000000000000000000000000000000000000000061119f565b6109ba7f000000000000000000000000000000000000000000000000000000000000000061119f565b6109e37f000000000000000000000000000000000000000000000000000000000000000061119f565b6040516020016109f593929190612618565b604051602081830303815290604052905090565b60008181526002602052604081205473ffffffffffffffffffffffffffffffffffffffff1680610a95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610650565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff8216610b40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f74206120766160448201527f6c6964206f776e657200000000000000000000000000000000000000000000006064820152608401610650565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205490565b6060600180546104d590612596565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610c3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e0000000000006064820152608401610650565b610c4681611791565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca582604051610c8e91815260200190565b60405180910390a25050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4f7074696d69736d4d696e7461626c654552433732313a206f6e6c792062726960448201527f6467652063616e2063616c6c20746869732066756e6374696f6e0000000000006064820152608401610650565b610d69828261186a565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d412139688582604051610c8e91815260200190565b610dbc338383611884565b5050565b610dca3383611460565b610e56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610650565b610e62848484846119b1565b50505050565b6060610e7382611332565b6000610e7d611a54565b90506000815111610e9d57604051806020016040528060008152506104bf565b80610ea78461119f565b604051602001610eb892919061268e565b6040516020818303038152906040529392505050565b600a8054610edb90612596565b80601f0160208091040260200160405190810160405280929190818152602001828054610f0790612596565b8015610f545780601f10610f2957610100808354040283529160200191610f54565b820191906000526020600020905b815481529060010190602001808311610f3757829003601f168201915b505050505081565b60606000610f6b8360026126ec565b610f76906002612729565b67ffffffffffffffff811115610f8e57610f8e61243a565b6040519080825280601f01601f191660200182016040528015610fb8576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110610fef57610fef6125e9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611052576110526125e9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061108e8460026126ec565b611099906001612729565b90505b6001811115611136577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106110da576110da6125e9565b1a60f81b8282815181106110f0576110f06125e9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361112f81612741565b905061109c565b5083156104bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610650565b6060816000036111e257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561120c57806111f681612776565b91506112059050600a836127dd565b91506111e6565b60008167ffffffffffffffff8111156112275761122761243a565b6040519080825280601f01601f191660200182016040528015611251576020820181803683370190505b5090505b84156112d4576112666001836127f1565b9150611273600a86612808565b61127e906030612729565b60f81b818381518110611293576112936125e9565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506112cd600a866127dd565b9450611255565b949350505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d63000000000000000000000000000000000000000000000000000000001480610a955750610a9582611a63565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff166113bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610650565b50565b600081815260046020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155819061141a82610a09565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008061146c83610a09565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806114da575073ffffffffffffffffffffffffffffffffffffffff80821660009081526005602090815260408083209388168352929052205460ff165b806112d457508373ffffffffffffffffffffffffffffffffffffffff1661150084610558565b73ffffffffffffffffffffffffffffffffffffffff1614949350505050565b8273ffffffffffffffffffffffffffffffffffffffff1661153f82610a09565b73ffffffffffffffffffffffffffffffffffffffff16146115e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610650565b73ffffffffffffffffffffffffffffffffffffffff8216611684576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610650565b61168f838383611b46565b61169a6000826113c0565b73ffffffffffffffffffffffffffffffffffffffff831660009081526003602052604081208054600192906116d09084906127f1565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600090815260036020526040812080546001929061170b908490612729565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061179c82610a09565b90506117aa81600084611b46565b6117b56000836113c0565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054600192906117eb9084906127f1565b909155505060008281526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555183919073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b610dbc828260405180602001604052806000815250611c4c565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611919576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610650565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526005602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6119bc84848461151f565b6119c884848484611cef565b610e62576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610650565b6060600a80546104d590612596565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd000000000000000000000000000000000000000000000000000000001480611af657507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b80610a9557507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610a95565b73ffffffffffffffffffffffffffffffffffffffff8316611bae57611ba981600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b611beb565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614611beb57611beb8382611ee2565b73ffffffffffffffffffffffffffffffffffffffff8216611c0f5761071881611f99565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614610718576107188282612048565b611c568383612099565b611c636000848484611cef565b610718576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610650565b600073ffffffffffffffffffffffffffffffffffffffff84163b15611ed7576040517f150b7a0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063150b7a0290611d6690339089908890889060040161281c565b6020604051808303816000875af1925050508015611dbf575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611dbc91810190612865565b60015b611e8c573d808015611ded576040519150601f19603f3d011682016040523d82523d6000602084013e611df2565b606091505b508051600003611e84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610650565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001490506112d4565b506001949350505050565b60006001611eef84610a9b565b611ef991906127f1565b600083815260076020526040902054909150808214611f595773ffffffffffffffffffffffffffffffffffffffff841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b50600091825260076020908152604080842084905573ffffffffffffffffffffffffffffffffffffffff9094168352600681528383209183525290812055565b600854600090611fab906001906127f1565b60008381526009602052604081205460088054939450909284908110611fd357611fd36125e9565b906000526020600020015490508060088381548110611ff457611ff46125e9565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061202c5761202c612882565b6001900381819060005260206000200160009055905550505050565b600061205383610a9b565b73ffffffffffffffffffffffffffffffffffffffff9093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b73ffffffffffffffffffffffffffffffffffffffff8216612116576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610650565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16156121a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610650565b6121ae60008383611b46565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081208054600192906121e4908490612729565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff00000000000000000000000000000000000000000000000000000000811681146113bd57600080fd5b6000602082840312156122a757600080fd5b81356104bf81612267565b60005b838110156122cd5781810151838201526020016122b5565b83811115610e625750506000910152565b600081518084526122f68160208601602086016122b2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104bf60208301846122de565b60006020828403121561234d57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461237857600080fd5b919050565b6000806040838503121561239057600080fd5b61239983612354565b946020939093013593505050565b6000806000606084860312156123bc57600080fd5b6123c584612354565b92506123d360208501612354565b9150604084013590509250925092565b6000602082840312156123f557600080fd5b6104bf82612354565b6000806040838503121561241157600080fd5b61241a83612354565b91506020830135801515811461242f57600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000806080858703121561247f57600080fd5b61248885612354565b935061249660208601612354565b925060408501359150606085013567ffffffffffffffff808211156124ba57600080fd5b818701915087601f8301126124ce57600080fd5b8135818111156124e0576124e061243a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156125265761252661243a565b816040528281528a602084870101111561253f57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561257657600080fd5b61257f83612354565b915061258d60208401612354565b90509250929050565b600181811c908216806125aa57607f821691505b6020821081036125e3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000845161262a8184602089016122b2565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612666816001850160208a016122b2565b600192019182015283516126818160028401602088016122b2565b0160020195945050505050565b600083516126a08184602088016122b2565b8351908301906126b48183602088016122b2565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612724576127246126bd565b500290565b6000821982111561273c5761273c6126bd565b500190565b600081612750576127506126bd565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036127a7576127a76126bd565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826127ec576127ec6127ae565b500490565b600082821015612803576128036126bd565b500390565b600082612817576128176127ae565b500690565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152508360408301526080606083015261285b60808301846122de565b9695505050505050565b60006020828403121561287757600080fd5b81516104bf81612267565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c634300080f000aa164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_bridge": "Address of the ERC721 bridge on this network.", - "_remoteChainId": "Chain ID for the remote 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." - } - } - }, - "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." - } - } - }, - "title": "OptimismMintableERC721Factory" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "BRIDGE()": { - "notice": "Address of the ERC721 bridge on this network." - }, - "REMOTE_CHAIN_ID()": { - "notice": "Chain ID for the remote network." - }, - "constructor": { - "notice": "The semver MUST be bumped any time that there is a change in the OptimismMintableERC721 token contract since this contract is responsible for deploying OptimismMintableERC721 contracts." - }, - "createOptimismMintableERC721(address,string,string)": { - "notice": "Creates an instance of the standard ERC721." - }, - "isOptimismMintableERC721(address)": { - "notice": "Tracks addresses created by this factory." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "events": { - "OptimismMintableERC721Created(address,address,address)": { - "notice": "Emitted whenever a new OptimismMintableERC721 contract is created." - } - }, - "notice": "Factory contract for creating OptimismMintableERC721 contracts." - }, - "storageLayout": { - "storage": [ - { - "astId": 47461, - "contract": "contracts/universal/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-bedrock/deployments/optimism-goerli/OptimismMintableERC721FactoryProxy.json b/packages/contracts-bedrock/deployments/optimism-goerli/OptimismMintableERC721FactoryProxy.json deleted file mode 100644 index 69482dda23fb..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/OptimismMintableERC721FactoryProxy.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "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-bedrock/deployments/optimism-goerli/Optimist.json b/packages/contracts-bedrock/deployments/optimism-goerli/Optimist.json deleted file mode 100644 index 9bea8e63c0b3..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/Optimist.json +++ /dev/null @@ -1,883 +0,0 @@ -{ - "address": "0x2044D9830067B78c65F9702506798D6035f58745", - "abi": [ - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - }, - { - "internalType": "address", - "name": "_baseURIAttestor", - "type": "address" - }, - { - "internalType": "contract AttestationStation", - "name": "_attestationStation", - "type": "address" - }, - { - "internalType": "contract OptimistAllowlist", - "name": "_optimistAllowlist", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "approved", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "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": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [], - "name": "ATTESTATION_STATION", - "outputs": [ - { - "internalType": "contract AttestationStation", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "BASE_URI_ATTESTATION_KEY", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "BASE_URI_ATTESTOR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMIST_ALLOWLIST", - "outputs": [ - { - "internalType": "contract OptimistAllowlist", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "baseURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "name": "isOnAllowList", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "tokenIdOfAddress", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x43857c8d09ffe81885d69ae0f72d1103e06a81fe2bfe027b170f08de36f26845", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 1, - "gasUsed": "2242451", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000002000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x19b116883b0dc13479692c084cfeaa28a77ef49da9d85cba16eae1a1ec98d064", - "transactionHash": "0x43857c8d09ffe81885d69ae0f72d1103e06a81fe2bfe027b170f08de36f26845", - "logs": [ - { - "transactionIndex": 1, - "blockNumber": 7691711, - "transactionHash": "0x43857c8d09ffe81885d69ae0f72d1103e06a81fe2bfe027b170f08de36f26845", - "address": "0x2044D9830067B78c65F9702506798D6035f58745", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 0, - "blockHash": "0x19b116883b0dc13479692c084cfeaa28a77ef49da9d85cba16eae1a1ec98d064" - } - ], - "blockNumber": 7691711, - "cumulativeGasUsed": "2289352", - "status": 1, - "byzantium": true - }, - "args": [ - "Optimist", - "OPTIMIST", - "0x8F0EBDaA1cF7106bE861753B0f9F5c0250fE0819", - "0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77", - "0x482b1945D58f2E9Db0CEbe13c7fcFc6876b41180" - ], - "numDeployments": 2, - "solcInputHash": "d7155764d4bdb814f10e1bb45296292b", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_baseURIAttestor\",\"type\":\"address\"},{\"internalType\":\"contract AttestationStation\",\"name\":\"_attestationStation\",\"type\":\"address\"},{\"internalType\":\"contract OptimistAllowlist\",\"name\":\"_optimistAllowlist\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"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\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ATTESTATION_STATION\",\"outputs\":[{\"internalType\":\"contract AttestationStation\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"BASE_URI_ATTESTATION_KEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"BASE_URI_ATTESTOR\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OPTIMIST_ALLOWLIST\",\"outputs\":[{\"internalType\":\"contract OptimistAllowlist\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"isOnAllowList\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"tokenIdOfAddress\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Optimism CollectiveGitcoin\",\"kind\":\"dev\",\"methods\":{\"balanceOf(address)\":{\"details\":\"See {IERC721-balanceOf}.\"},\"baseURI()\":{\"returns\":{\"_0\":\"BaseURI for all tokens.\"}},\"burn(uint256)\":{\"details\":\"Burns `tokenId`. See {ERC721-_burn}. Requirements: - The caller must own `tokenId` or be an approved operator.\"},\"constructor\":{\"custom:semver\":\"2.0.0\",\"params\":{\"_attestationStation\":\"Address of the AttestationStation contract.\",\"_baseURIAttestor\":\"Address of the baseURI attestor.\",\"_name\":\"Token name.\",\"_optimistAllowlist\":\"Address of the OptimistAllowlist contract\",\"_symbol\":\"Token symbol.\"}},\"getApproved(uint256)\":{\"details\":\"See {IERC721-getApproved}.\"},\"initialize(string,string)\":{\"params\":{\"_name\":\"Token name.\",\"_symbol\":\"Token symbol.\"}},\"isApprovedForAll(address,address)\":{\"details\":\"See {IERC721-isApprovedForAll}.\"},\"isOnAllowList(address)\":{\"returns\":{\"_0\":\"Whether or not the address is allowed to mint yet.\"}},\"mint(address)\":{\"params\":{\"_recipient\":\"Address of the token recipient.\"}},\"name()\":{\"details\":\"See {IERC721Metadata-name}.\"},\"ownerOf(uint256)\":{\"details\":\"See {IERC721-ownerOf}.\"},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"See {IERC721-safeTransferFrom}.\"},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"See {IERC721-safeTransferFrom}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"symbol()\":{\"details\":\"See {IERC721Metadata-symbol}.\"},\"tokenIdOfAddress(address)\":{\"returns\":{\"_0\":\"Token ID for the token owned by the given address.\"}},\"tokenURI(uint256)\":{\"params\":{\"_tokenId\":\"Token ID to query.\"},\"returns\":{\"_0\":\"Token URI for the given token by ID.\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC721-transferFrom}.\"},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"Optimist\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"ATTESTATION_STATION()\":{\"notice\":\"Address of the AttestationStation contract.\"},\"BASE_URI_ATTESTATION_KEY()\":{\"notice\":\"Attestation key used by the attestor to attest the baseURI.\"},\"BASE_URI_ATTESTOR()\":{\"notice\":\"Attestor who attests to baseURI.\"},\"OPTIMIST_ALLOWLIST()\":{\"notice\":\"Address of the OptimistAllowlist contract.\"},\"approve(address,uint256)\":{\"notice\":\"Disabled for the Optimist NFT (Soul Bound Token).\"},\"baseURI()\":{\"notice\":\"Returns the baseURI for all tokens.\"},\"initialize(string,string)\":{\"notice\":\"Initializes the Optimist contract.\"},\"isOnAllowList(address)\":{\"notice\":\"Checks OptimistAllowlist to determine whether a given address is allowed to mint the Optimist NFT. Since the Optimist NFT will also be used as part of the Citizens House, mints are currently restricted. Eventually anyone will be able to mint.\"},\"mint(address)\":{\"notice\":\"Allows an address to mint an Optimist NFT. Token ID is the uint256 representation of the recipient's address. Recipients must be permitted to mint, eventually anyone will be able to mint. One token per address.\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"Disabled for the Optimist NFT (Soul Bound Token).\"},\"tokenIdOfAddress(address)\":{\"notice\":\"Returns the token ID for the token owned by a given address. This is the uint256 representation of the given address.\"},\"tokenURI(uint256)\":{\"notice\":\"Returns the token URI for a given token by ID\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"A Soul Bound Token for real humans only(tm).\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/op-nft/Optimist.sol\":\"Optimist\"},\"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.0;\\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 uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\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\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"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/token/ERC721/ERC721Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\nimport \\\"./IERC721ReceiverUpgradeable.sol\\\";\\nimport \\\"./extensions/IERC721MetadataUpgradeable.sol\\\";\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../../utils/StringsUpgradeable.sol\\\";\\nimport \\\"../../utils/introspection/ERC165Upgradeable.sol\\\";\\nimport \\\"../../proxy/utils/Initializable.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 ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable {\\n using AddressUpgradeable for address;\\n using StringsUpgradeable 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 function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing {\\n __ERC721_init_unchained(name_, symbol_);\\n }\\n\\n function __ERC721_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {\\n return\\n interfaceId == type(IERC721Upgradeable).interfaceId ||\\n interfaceId == type(IERC721MetadataUpgradeable).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: address zero is not a valid owner\\\");\\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: invalid token ID\\\");\\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 _requireMinted(tokenId);\\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 = ERC721Upgradeable.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 token 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 _requireMinted(tokenId);\\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: caller is not token 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: caller is not token 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 address owner = ERC721Upgradeable.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 = ERC721Upgradeable.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(ERC721Upgradeable.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 an {Approval} event.\\n */\\n function _approve(address to, uint256 tokenId) internal virtual {\\n _tokenApprovals[tokenId] = to;\\n emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits an {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 Reverts if the `tokenId` has not been minted yet.\\n */\\n function _requireMinted(uint256 tokenId) internal view virtual {\\n require(_exists(tokenId), \\\"ERC721: invalid token ID\\\");\\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 IERC721ReceiverUpgradeable(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\\n return retval == IERC721ReceiverUpgradeable.onERC721Received.selector;\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert(\\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n } else {\\n /// @solidity memory-safe-assembly\\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 /**\\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[44] private __gap;\\n}\\n\",\"keccak256\":\"0x5331c8909221d9f9f3851cfadd5959d0873413a2c27e30e0f2fa234158c1c6cf\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.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 IERC721ReceiverUpgradeable {\\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\":\"0xbb2ed8106d94aeae6858e2551a1e7174df73994b77b13ebd120ccaaef80155f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165Upgradeable.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721Upgradeable is IERC165Upgradeable {\\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 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\":\"0x016298e66a5810253c6c905e61966bb31c8775c3f3517bf946ff56ee31d6c005\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/extensions/ERC721Burnable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC721Upgradeable.sol\\\";\\nimport \\\"../../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../../../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @title ERC721 Burnable Token\\n * @dev ERC721 Token that can be burned (destroyed).\\n */\\nabstract contract ERC721BurnableUpgradeable is Initializable, ContextUpgradeable, ERC721Upgradeable {\\n function __ERC721Burnable_init() internal onlyInitializing {\\n }\\n\\n function __ERC721Burnable_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev Burns `tokenId`. See {ERC721-_burn}.\\n *\\n * Requirements:\\n *\\n * - The caller must own `tokenId` or be an approved operator.\\n */\\n function burn(uint256 tokenId) public virtual {\\n //solhint-disable-next-line max-line-length\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner nor approved\\\");\\n _burn(tokenId);\\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\":\"0xa7dbff7171ac06a023a5ca52c2138ac711037b2146b9197a52e5de4f9183e04d\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.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 \\\"../IERC721Upgradeable.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 IERC721MetadataUpgradeable is IERC721Upgradeable {\\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\":\"0x95a471796eb5f030fdc438660bebec121ad5d063763e64d92376ffb4b5ce8b70\",\"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-upgradeable/utils/StringsUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary StringsUpgradeable {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\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 /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xea5339a7fff0ed42b45be56a88efdd0b2ddde9fa480dc99fef9a6a4c5b776863\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165Upgradeable.sol\\\";\\nimport \\\"../../proxy/utils/Initializable.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 ERC165Upgradeable is Initializable, IERC165Upgradeable {\\n function __ERC165_init() internal onlyInitializing {\\n }\\n\\n function __ERC165_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165Upgradeable).interfaceId;\\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\":\"0x9a3b990bd56d139df3e454a9edf1c64668530b5a77fc32eb063bc206f958274a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.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 IERC165Upgradeable {\\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\":\"0xc6cef87559d0aeffdf0a99803de655938a7779ec0a3cd5d4383483ad85565a09\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\\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 /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/universal/op-nft/AttestationStation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title AttestationStation\\n * @author Optimism Collective\\n * @author Gitcoin\\n * @notice Where attestations live.\\n */\\ncontract AttestationStation is Semver {\\n /**\\n * @notice Struct representing data that is being attested.\\n *\\n * @custom:field about Address for which the attestation is about.\\n * @custom:field key A bytes32 key for the attestation.\\n * @custom:field val The attestation as arbitrary bytes.\\n */\\n struct AttestationData {\\n address about;\\n bytes32 key;\\n bytes val;\\n }\\n\\n /**\\n * @notice Maps addresses to attestations. Creator => About => Key => Value.\\n */\\n mapping(address => mapping(address => mapping(bytes32 => bytes))) public attestations;\\n\\n /**\\n * @notice Emitted when Attestation is created.\\n *\\n * @param creator Address that made the attestation.\\n * @param about Address attestation is about.\\n * @param key Key of the attestation.\\n * @param val Value of the attestation.\\n */\\n event AttestationCreated(\\n address indexed creator,\\n address indexed about,\\n bytes32 indexed key,\\n bytes val\\n );\\n\\n /**\\n * @custom:semver 1.1.0\\n */\\n constructor() Semver(1, 1, 0) {}\\n\\n /**\\n * @notice Allows anyone to create an attestation.\\n *\\n * @param _about Address that the attestation is about.\\n * @param _key A key used to namespace the attestation.\\n * @param _val An arbitrary value stored as part of the attestation.\\n */\\n function attest(\\n address _about,\\n bytes32 _key,\\n bytes memory _val\\n ) public {\\n attestations[msg.sender][_about][_key] = _val;\\n\\n emit AttestationCreated(msg.sender, _about, _key, _val);\\n }\\n\\n /**\\n * @notice Allows anyone to create attestations.\\n *\\n * @param _attestations An array of AttestationData structs.\\n */\\n function attest(AttestationData[] calldata _attestations) external {\\n uint256 length = _attestations.length;\\n for (uint256 i = 0; i < length; ) {\\n AttestationData memory attestation = _attestations[i];\\n\\n attest(attestation.about, attestation.key, attestation.val);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x421923e04df145353db12cd0352ccf516d9c29ab64b138733b4f7a6a450ce2be\",\"license\":\"MIT\"},\"contracts/universal/op-nft/Optimist.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\nimport {\\n ERC721BurnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol\\\";\\nimport { AttestationStation } from \\\"./AttestationStation.sol\\\";\\nimport { OptimistAllowlist } from \\\"./OptimistAllowlist.sol\\\";\\nimport { Strings } from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\n\\n/**\\n * @author Optimism Collective\\n * @author Gitcoin\\n * @title Optimist\\n * @notice A Soul Bound Token for real humans only(tm).\\n */\\ncontract Optimist is ERC721BurnableUpgradeable, Semver {\\n /**\\n * @notice Attestation key used by the attestor to attest the baseURI.\\n */\\n bytes32 public constant BASE_URI_ATTESTATION_KEY = bytes32(\\\"optimist.base-uri\\\");\\n\\n /**\\n * @notice Attestor who attests to baseURI.\\n */\\n address public immutable BASE_URI_ATTESTOR;\\n\\n /**\\n * @notice Address of the AttestationStation contract.\\n */\\n AttestationStation public immutable ATTESTATION_STATION;\\n\\n /**\\n * @notice Address of the OptimistAllowlist contract.\\n */\\n OptimistAllowlist public immutable OPTIMIST_ALLOWLIST;\\n\\n /**\\n * @custom:semver 2.0.0\\n * @param _name Token name.\\n * @param _symbol Token symbol.\\n * @param _baseURIAttestor Address of the baseURI attestor.\\n * @param _attestationStation Address of the AttestationStation contract.\\n * @param _optimistAllowlist Address of the OptimistAllowlist contract\\n */\\n constructor(\\n string memory _name,\\n string memory _symbol,\\n address _baseURIAttestor,\\n AttestationStation _attestationStation,\\n OptimistAllowlist _optimistAllowlist\\n ) Semver(2, 0, 0) {\\n BASE_URI_ATTESTOR = _baseURIAttestor;\\n ATTESTATION_STATION = _attestationStation;\\n OPTIMIST_ALLOWLIST = _optimistAllowlist;\\n initialize(_name, _symbol);\\n }\\n\\n /**\\n * @notice Initializes the Optimist contract.\\n *\\n * @param _name Token name.\\n * @param _symbol Token symbol.\\n */\\n function initialize(string memory _name, string memory _symbol) public initializer {\\n __ERC721_init(_name, _symbol);\\n __ERC721Burnable_init();\\n }\\n\\n /**\\n * @notice Allows an address to mint an Optimist NFT. Token ID is the uint256 representation\\n * of the recipient's address. Recipients must be permitted to mint, eventually anyone\\n * will be able to mint. One token per address.\\n *\\n * @param _recipient Address of the token recipient.\\n */\\n function mint(address _recipient) public {\\n require(isOnAllowList(_recipient), \\\"Optimist: address is not on allowList\\\");\\n _safeMint(_recipient, tokenIdOfAddress(_recipient));\\n }\\n\\n /**\\n * @notice Returns the baseURI for all tokens.\\n *\\n * @return BaseURI for all tokens.\\n */\\n function baseURI() public view returns (string memory) {\\n return\\n string(\\n abi.encodePacked(\\n ATTESTATION_STATION.attestations(\\n BASE_URI_ATTESTOR,\\n address(this),\\n bytes32(\\\"optimist.base-uri\\\")\\n )\\n )\\n );\\n }\\n\\n /**\\n * @notice Returns the token URI for a given token by ID\\n *\\n * @param _tokenId Token ID to query.\\n\\n * @return Token URI for the given token by ID.\\n */\\n function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) {\\n return\\n string(\\n abi.encodePacked(\\n baseURI(),\\n \\\"/\\\",\\n // Properly format the token ID as a 20 byte hex string (address).\\n Strings.toHexString(_tokenId, 20),\\n \\\".json\\\"\\n )\\n );\\n }\\n\\n /**\\n * @notice Checks OptimistAllowlist to determine whether a given address is allowed to mint\\n * the Optimist NFT. Since the Optimist NFT will also be used as part of the\\n * Citizens House, mints are currently restricted. Eventually anyone will be able\\n * to mint.\\n *\\n * @return Whether or not the address is allowed to mint yet.\\n */\\n function isOnAllowList(address _recipient) public view returns (bool) {\\n return OPTIMIST_ALLOWLIST.isAllowedToMint(_recipient);\\n }\\n\\n /**\\n * @notice Returns the token ID for the token owned by a given address. This is the uint256\\n * representation of the given address.\\n *\\n * @return Token ID for the token owned by the given address.\\n */\\n function tokenIdOfAddress(address _owner) public pure returns (uint256) {\\n return uint256(uint160(_owner));\\n }\\n\\n /**\\n * @notice Disabled for the Optimist NFT (Soul Bound Token).\\n */\\n function approve(address, uint256) public pure override {\\n revert(\\\"Optimist: soul bound token\\\");\\n }\\n\\n /**\\n * @notice Disabled for the Optimist NFT (Soul Bound Token).\\n */\\n function setApprovalForAll(address, bool) public virtual override {\\n revert(\\\"Optimist: soul bound token\\\");\\n }\\n\\n /**\\n * @notice Prevents transfers of the Optimist NFT (Soul Bound Token).\\n *\\n * @param _from Address of the token sender.\\n * @param _to Address of the token recipient.\\n */\\n function _beforeTokenTransfer(\\n address _from,\\n address _to,\\n uint256\\n ) internal virtual override {\\n require(_from == address(0) || _to == address(0), \\\"Optimist: soul bound token\\\");\\n }\\n}\\n\",\"keccak256\":\"0xf9c7973102666d1dc1b8a1918d6df82fa8fb470e1774aea840b300afb9699cac\",\"license\":\"MIT\"},\"contracts/universal/op-nft/OptimistAllowlist.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\nimport { AttestationStation } from \\\"./AttestationStation.sol\\\";\\nimport { OptimistConstants } from \\\"./libraries/OptimistConstants.sol\\\";\\n\\n/**\\n * @title OptimistAllowlist\\n * @notice Source of truth for whether an address is able to mint an Optimist NFT.\\n isAllowedToMint function checks various signals to return boolean value for whether an\\n address is eligible or not.\\n */\\ncontract OptimistAllowlist is Semver {\\n /**\\n * @notice Attestation key used by the AllowlistAttestor to manually add addresses to the\\n * allowlist.\\n */\\n bytes32 public constant OPTIMIST_CAN_MINT_ATTESTATION_KEY = bytes32(\\\"optimist.can-mint\\\");\\n\\n /**\\n * @notice Attestation key used by Coinbase to issue attestations for Quest participants.\\n */\\n bytes32 public constant COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY =\\n bytes32(\\\"coinbase.quest-eligible\\\");\\n\\n /**\\n * @notice Address of the AttestationStation contract.\\n */\\n AttestationStation public immutable ATTESTATION_STATION;\\n\\n /**\\n * @notice Attestor that issues 'optimist.can-mint' attestations.\\n */\\n address public immutable ALLOWLIST_ATTESTOR;\\n\\n /**\\n * @notice Attestor that issues 'coinbase.quest-eligible' attestations.\\n */\\n address public immutable COINBASE_QUEST_ATTESTOR;\\n\\n /**\\n * @notice Address of OptimistInviter contract that issues 'optimist.can-mint-from-invite'\\n * attestations.\\n */\\n address public immutable OPTIMIST_INVITER;\\n\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _attestationStation Address of the AttestationStation contract.\\n * @param _allowlistAttestor Address of the allowlist attestor.\\n * @param _coinbaseQuestAttestor Address of the Coinbase Quest attestor.\\n * @param _optimistInviter Address of the OptimistInviter contract.\\n */\\n constructor(\\n AttestationStation _attestationStation,\\n address _allowlistAttestor,\\n address _coinbaseQuestAttestor,\\n address _optimistInviter\\n ) Semver(1, 0, 0) {\\n ATTESTATION_STATION = _attestationStation;\\n ALLOWLIST_ATTESTOR = _allowlistAttestor;\\n COINBASE_QUEST_ATTESTOR = _coinbaseQuestAttestor;\\n OPTIMIST_INVITER = _optimistInviter;\\n }\\n\\n /**\\n * @notice Checks whether a given address is allowed to mint the Optimist NFT yet. Since the\\n * Optimist NFT will also be used as part of the Citizens House, mints are currently\\n * restricted. Eventually anyone will be able to mint.\\n *\\n * Currently, address is allowed to mint if it satisfies any of the following:\\n * 1) Has a valid 'optimist.can-mint' attestation from the allowlist attestor.\\n * 2) Has a valid 'coinbase.quest-eligible' attestation from Coinbase Quest attestor\\n * 3) Has a valid 'optimist.can-mint-from-invite' attestation from the OptimistInviter\\n * contract.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address is allowed to mint yet.\\n */\\n function isAllowedToMint(address _claimer) public view returns (bool) {\\n return\\n _hasAttestationFromAllowlistAttestor(_claimer) ||\\n _hasAttestationFromCoinbaseQuestAttestor(_claimer) ||\\n _hasAttestationFromOptimistInviter(_claimer);\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid 'optimist.can-mint' attestation from the\\n * allowlist attestor.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address has a valid attestation.\\n */\\n function _hasAttestationFromAllowlistAttestor(address _claimer) internal view returns (bool) {\\n // Expected attestation value is bytes32(\\\"true\\\")\\n return\\n _hasValidAttestation(ALLOWLIST_ATTESTOR, _claimer, OPTIMIST_CAN_MINT_ATTESTATION_KEY);\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid attestation from the Coinbase attestor.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address has a valid attestation.\\n */\\n function _hasAttestationFromCoinbaseQuestAttestor(address _claimer)\\n internal\\n view\\n returns (bool)\\n {\\n // Expected attestation value is bytes32(\\\"true\\\")\\n return\\n _hasValidAttestation(\\n COINBASE_QUEST_ATTESTOR,\\n _claimer,\\n COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY\\n );\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid attestation from the OptimistInviter contract.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address has a valid attestation.\\n */\\n function _hasAttestationFromOptimistInviter(address _claimer) internal view returns (bool) {\\n // Expected attestation value is the inviter's address\\n return\\n _hasValidAttestation(\\n OPTIMIST_INVITER,\\n _claimer,\\n OptimistConstants.OPTIMIST_CAN_MINT_FROM_INVITE_ATTESTATION_KEY\\n );\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid truthy attestation.\\n * Any attestation val other than bytes32(\\\"\\\") is considered truthy.\\n *\\n * @param _creator Address that made the attestation.\\n * @param _about Address attestation is about.\\n * @param _key Key of the attestation.\\n *\\n * @return Whether or not the address has a valid truthy attestation.\\n */\\n function _hasValidAttestation(\\n address _creator,\\n address _about,\\n bytes32 _key\\n ) internal view returns (bool) {\\n return ATTESTATION_STATION.attestations(_creator, _about, _key).length > 0;\\n }\\n}\\n\",\"keccak256\":\"0xd36a677571450d2d9be832beb80e5c37481fcdfc355e6a9b929ac9c8d4966ca0\",\"license\":\"MIT\"},\"contracts/universal/op-nft/libraries/OptimistConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title OptimistConstants\\n * @notice Library for storing Optimist related constants that are shared in multiple contracts.\\n */\\n\\nlibrary OptimistConstants {\\n /**\\n * @notice Attestation key issued by OptimistInviter allowing the attested account to mint.\\n */\\n bytes32 internal constant OPTIMIST_CAN_MINT_FROM_INVITE_ATTESTATION_KEY =\\n bytes32(\\\"optimist.can-mint-from-invite\\\");\\n}\\n\",\"keccak256\":\"0x6eebe1db87f8a5de79bf8af9120e5b0cc6a9b51d8d86e6461cdb6bc52a1dde21\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x6101406040523480156200001257600080fd5b5060405162002c7f38038062002c7f8339810160408190526200003591620003ee565b6002608052600060a081905260c0526001600160a01b0380841660e052828116610100528116610120526200006b858562000076565b5050505050620005f4565b600054610100900460ff1615808015620000975750600054600160ff909116105b80620000c75750620000b430620001b660201b62000dd61760201c565b158015620000c7575060005460ff166001145b620001305760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000154576000805461ff0019166101001790555b620001608383620001c5565b6200016a62000231565b8015620001b1576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b600054610100900460ff16620002215760405162461bcd60e51b815260206004820152602b602482015260008051602062002c5f83398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000127565b6200022d82826200028f565b5050565b600054610100900460ff166200028d5760405162461bcd60e51b815260206004820152602b602482015260008051602062002c5f83398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000127565b565b600054610100900460ff16620002eb5760405162461bcd60e51b815260206004820152602b602482015260008051602062002c5f83398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000127565b6065620002f9838262000528565b506066620001b1828262000528565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200033057600080fd5b81516001600160401b03808211156200034d576200034d62000308565b604051601f8301601f19908116603f0116810190828211818310171562000378576200037862000308565b816040528381526020925086838588010111156200039557600080fd5b600091505b83821015620003b957858201830151818301840152908201906200039a565b83821115620003cb5760008385830101525b9695505050505050565b6001600160a01b0381168114620003eb57600080fd5b50565b600080600080600060a086880312156200040757600080fd5b85516001600160401b03808211156200041f57600080fd5b6200042d89838a016200031e565b965060208801519150808211156200044457600080fd5b5062000453888289016200031e565b94505060408601516200046681620003d5565b60608701519093506200047981620003d5565b60808701519092506200048c81620003d5565b809150509295509295909350565b600181811c90821680620004af57607f821691505b602082108103620004d057634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001b157600081815260208120601f850160051c81016020861015620004ff5750805b601f850160051c820191505b8181101562000520578281556001016200050b565b505050505050565b81516001600160401b0381111562000544576200054462000308565b6200055c816200055584546200049a565b84620004d6565b602080601f8311600181146200059457600084156200057b5750858301515b600019600386901b1c1916600185901b17855562000520565b600085815260208120601f198616915b82811015620005c557888601518255948401946001909101908401620005a4565b5085821015620005e45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051610100516101205161260662000659600039600081816103930152610c900152600081816103ba0152610b1301526000818161022c0152610abc01526000610928015260006108ff015260006108d601526126066000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c80636a627842116100e3578063a22cb4651161008c578063ce5dd1b511610066578063ce5dd1b51461038e578063db083d71146103b5578063e985e9c5146103dc57600080fd5b8063a22cb4651461035a578063b88d4fde14610368578063c87b56dd1461037b57600080fd5b80637c08652f116100bd5780637c08652f146103185780638f328a1f1461033f57806395d89b411461035257600080fd5b80636a627842146102ea5780636c0360eb146102fd57806370a082311461030557600080fd5b806323b872dd116101455780634cd88b761161011f5780634cd88b76146102bc57806354fd4d50146102cf5780636352211e146102d757600080fd5b806323b872dd1461028357806342842e0e1461029657806342966c68146102a957600080fd5b8063095ea7b311610176578063095ea7b31461021257806319f463f21461022757806321d3d5cf1461024e57600080fd5b806301ffc9a71461019d57806306fdde03146101c5578063081812fc146101da575b600080fd5b6101b06101ab366004611d0e565b610425565b60405190151581526020015b60405180910390f35b6101cd61050a565b6040516101bc9190611d83565b6101ed6101e8366004611d96565b61059c565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b610225610220366004611dd8565b6105d0565b005b6101ed7f000000000000000000000000000000000000000000000000000000000000000081565b6102757f6f7074696d6973742e626173652d75726900000000000000000000000000000081565b6040519081526020016101bc565b610225610291366004611e02565b61061d565b6102256102a4366004611e02565b6106aa565b6102256102b7366004611d96565b6106c5565b6102256102ca366004611f24565b61074c565b6101cd6108cf565b6101ed6102e5366004611d96565b610972565b6102256102f8366004611f88565b6109e4565b6101cd610a7f565b610275610313366004611f88565b610b94565b610275610326366004611f88565b73ffffffffffffffffffffffffffffffffffffffff1690565b6101b061034d366004611f88565b610c48565b6101cd610cfd565b610225610220366004611fb1565b610225610376366004611fe8565b610d0c565b6101cd610389366004611d96565b610d9a565b6101ed7f000000000000000000000000000000000000000000000000000000000000000081565b6101ed7f000000000000000000000000000000000000000000000000000000000000000081565b6101b06103ea366004612064565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152606a6020908152604080832093909416825291909152205460ff1690565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd0000000000000000000000000000000000000000000000000000000014806104b857507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061050457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60606065805461051990612097565b80601f016020809104026020016040519081016040528092919081815260200182805461054590612097565b80156105925780601f1061056757610100808354040283529160200191610592565b820191906000526020600020905b81548152906001019060200180831161057557829003601f168201915b5050505050905090565b60006105a782610df2565b5060009081526069602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b60405162461bcd60e51b815260206004820152601a60248201527f4f7074696d6973743a20736f756c20626f756e6420746f6b656e00000000000060448201526064015b60405180910390fd5b610628335b82610e63565b61069a5760405162461bcd60e51b815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610614565b6106a5838383610f23565b505050565b6106a583838360405180602001604052806000815250610d0c565b6106ce33610622565b6107405760405162461bcd60e51b815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610614565b61074981611161565b50565b600054610100900460ff161580801561076c5750600054600160ff909116105b806107865750303b158015610786575060005460ff166001145b6107f85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610614565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561085657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610860838361123b565b6108686112c2565b80156106a557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b60606108fa7f0000000000000000000000000000000000000000000000000000000000000000611341565b6109237f0000000000000000000000000000000000000000000000000000000000000000611341565b61094c7f0000000000000000000000000000000000000000000000000000000000000000611341565b60405160200161095e939291906120ea565b604051602081830303815290604052905090565b60008181526067602052604081205473ffffffffffffffffffffffffffffffffffffffff16806105045760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610614565b6109ed81610c48565b610a5f5760405162461bcd60e51b815260206004820152602560248201527f4f7074696d6973743a2061646472657373206973206e6f74206f6e20616c6c6f60448201527f774c6973740000000000000000000000000000000000000000000000000000006064820152608401610614565b6107498173ffffffffffffffffffffffffffffffffffffffff8116611476565b6040517f29b42cb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301523060248301527f6f7074696d6973742e626173652d75726900000000000000000000000000000060448301526060917f0000000000000000000000000000000000000000000000000000000000000000909116906329b42cb590606401600060405180830381865afa158015610b5c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b849190810190612160565b60405160200161095e91906121d7565b600073ffffffffffffffffffffffffffffffffffffffff8216610c1f5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f74206120766160448201527f6c6964206f776e657200000000000000000000000000000000000000000000006064820152608401610614565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526068602052604090205490565b6040517f4813d8a600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690634813d8a690602401602060405180830381865afa158015610cd9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050491906121f3565b60606066805461051990612097565b610d163383610e63565b610d885760405162461bcd60e51b815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610614565b610d9484848484611490565b50505050565b6060610da4610a7f565b610daf836014611519565b604051602001610dc0929190612210565b6040516020818303038152906040529050919050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60008181526067602052604090205473ffffffffffffffffffffffffffffffffffffffff166107495760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610614565b600080610e6f83610972565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610edd575073ffffffffffffffffffffffffffffffffffffffff8082166000908152606a602090815260408083209388168352929052205460ff165b80610f1b57508373ffffffffffffffffffffffffffffffffffffffff16610f038461059c565b73ffffffffffffffffffffffffffffffffffffffff16145b949350505050565b8273ffffffffffffffffffffffffffffffffffffffff16610f4382610972565b73ffffffffffffffffffffffffffffffffffffffff1614610fcc5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610614565b73ffffffffffffffffffffffffffffffffffffffff82166110545760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610614565b61105f838383611749565b61106a6000826117cc565b73ffffffffffffffffffffffffffffffffffffffff831660009081526068602052604081208054600192906110a09084906122c1565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526068602052604081208054600192906110db9084906122d8565b909155505060008181526067602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061116c82610972565b905061117a81600084611749565b6111856000836117cc565b73ffffffffffffffffffffffffffffffffffffffff811660009081526068602052604081208054600192906111bb9084906122c1565b909155505060008281526067602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555183919073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45b5050565b600054610100900460ff166112b85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610614565b611237828261186c565b600054610100900460ff1661133f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610614565b565b60608160000361138457505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156113ae5780611398816122f0565b91506113a79050600a83612357565b9150611388565b60008167ffffffffffffffff8111156113c9576113c9611e3e565b6040519080825280601f01601f1916602001820160405280156113f3576020820181803683370190505b5090505b8415610f1b576114086001836122c1565b9150611415600a8661236b565b6114209060306122d8565b60f81b8183815181106114355761143561237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061146f600a86612357565b94506113f7565b611237828260405180602001604052806000815250611902565b61149b848484610f23565b6114a78484848461198b565b610d945760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610614565b606060006115288360026123ae565b6115339060026122d8565b67ffffffffffffffff81111561154b5761154b611e3e565b6040519080825280601f01601f191660200182016040528015611575576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106115ac576115ac61237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061160f5761160f61237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061164b8460026123ae565b6116569060016122d8565b90505b60018111156116f3577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106116975761169761237f565b1a60f81b8282815181106116ad576116ad61237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936116ec816123eb565b9050611659565b5083156117425760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610614565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff83161580611780575073ffffffffffffffffffffffffffffffffffffffff8216155b6106a55760405162461bcd60e51b815260206004820152601a60248201527f4f7074696d6973743a20736f756c20626f756e6420746f6b656e0000000000006044820152606401610614565b600081815260696020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155819061182682610972565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600054610100900460ff166118e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610614565b60656118f5838261246e565b5060666106a5828261246e565b61190c8383611b46565b611919600084848461198b565b6106a55760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610614565b600073ffffffffffffffffffffffffffffffffffffffff84163b15611b3b576040517f150b7a0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063150b7a0290611a0290339089908890889060040161256a565b6020604051808303816000875af1925050508015611a3d575060408051601f3d908101601f19168201909252611a3a918101906125b3565b60015b611af0573d808015611a6b576040519150601f19603f3d011682016040523d82523d6000602084013e611a70565b606091505b508051600003611ae85760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610614565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149050610f1b565b506001949350505050565b73ffffffffffffffffffffffffffffffffffffffff8216611ba95760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610614565b60008181526067602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611c1b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610614565b611c2760008383611749565b73ffffffffffffffffffffffffffffffffffffffff82166000908152606860205260408120805460019290611c5d9084906122d8565b909155505060008181526067602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461074957600080fd5b600060208284031215611d2057600080fd5b813561174281611ce0565b60005b83811015611d46578181015183820152602001611d2e565b83811115610d945750506000910152565b60008151808452611d6f816020860160208601611d2b565b601f01601f19169290920160200192915050565b6020815260006117426020830184611d57565b600060208284031215611da857600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611dd357600080fd5b919050565b60008060408385031215611deb57600080fd5b611df483611daf565b946020939093013593505050565b600080600060608486031215611e1757600080fd5b611e2084611daf565b9250611e2e60208501611daf565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611e9657611e96611e3e565b604052919050565b600067ffffffffffffffff821115611eb857611eb8611e3e565b50601f01601f191660200190565b6000611ed9611ed484611e9e565b611e6d565b9050828152838383011115611eed57600080fd5b828260208301376000602084830101529392505050565b600082601f830112611f1557600080fd5b61174283833560208501611ec6565b60008060408385031215611f3757600080fd5b823567ffffffffffffffff80821115611f4f57600080fd5b611f5b86838701611f04565b93506020850135915080821115611f7157600080fd5b50611f7e85828601611f04565b9150509250929050565b600060208284031215611f9a57600080fd5b61174282611daf565b801515811461074957600080fd5b60008060408385031215611fc457600080fd5b611fcd83611daf565b91506020830135611fdd81611fa3565b809150509250929050565b60008060008060808587031215611ffe57600080fd5b61200785611daf565b935061201560208601611daf565b925060408501359150606085013567ffffffffffffffff81111561203857600080fd5b8501601f8101871361204957600080fd5b61205887823560208401611ec6565b91505092959194509250565b6000806040838503121561207757600080fd5b61208083611daf565b915061208e60208401611daf565b90509250929050565b600181811c908216806120ab57607f821691505b6020821081036120e4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600084516120fc818460208901611d2b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612138816001850160208a01611d2b565b60019201918201528351612153816002840160208801611d2b565b0160020195945050505050565b60006020828403121561217257600080fd5b815167ffffffffffffffff81111561218957600080fd5b8201601f8101841361219a57600080fd5b80516121a8611ed482611e9e565b8181528560208385010111156121bd57600080fd5b6121ce826020830160208601611d2b565b95945050505050565b600082516121e9818460208701611d2b565b9190910192915050565b60006020828403121561220557600080fd5b815161174281611fa3565b60008351612222818460208801611d2b565b7f2f00000000000000000000000000000000000000000000000000000000000000908301908152835161225c816001840160208801611d2b565b7f2e6a736f6e00000000000000000000000000000000000000000000000000000060019290910191820152600601949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156122d3576122d3612292565b500390565b600082198211156122eb576122eb612292565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361232157612321612292565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261236657612366612328565b500490565b60008261237a5761237a612328565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156123e6576123e6612292565b500290565b6000816123fa576123fa612292565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b601f8211156106a557600081815260208120601f850160051c810160208610156124475750805b601f850160051c820191505b8181101561246657828155600101612453565b505050505050565b815167ffffffffffffffff81111561248857612488611e3e565b61249c816124968454612097565b84612420565b602080601f8311600181146124ef57600084156124b95750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612466565b600085815260208120601f198616915b8281101561251e578886015182559484019460019091019084016124ff565b508582101561255a57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526125a96080830184611d57565b9695505050505050565b6000602082840312156125c557600080fd5b815161174281611ce056fea264697066735822122068519f9cbd8d80e9e293c6c977994da4f38aba3722422b6bfce53b68916efab964736f6c634300080f0033496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101985760003560e01c80636a627842116100e3578063a22cb4651161008c578063ce5dd1b511610066578063ce5dd1b51461038e578063db083d71146103b5578063e985e9c5146103dc57600080fd5b8063a22cb4651461035a578063b88d4fde14610368578063c87b56dd1461037b57600080fd5b80637c08652f116100bd5780637c08652f146103185780638f328a1f1461033f57806395d89b411461035257600080fd5b80636a627842146102ea5780636c0360eb146102fd57806370a082311461030557600080fd5b806323b872dd116101455780634cd88b761161011f5780634cd88b76146102bc57806354fd4d50146102cf5780636352211e146102d757600080fd5b806323b872dd1461028357806342842e0e1461029657806342966c68146102a957600080fd5b8063095ea7b311610176578063095ea7b31461021257806319f463f21461022757806321d3d5cf1461024e57600080fd5b806301ffc9a71461019d57806306fdde03146101c5578063081812fc146101da575b600080fd5b6101b06101ab366004611d0e565b610425565b60405190151581526020015b60405180910390f35b6101cd61050a565b6040516101bc9190611d83565b6101ed6101e8366004611d96565b61059c565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b610225610220366004611dd8565b6105d0565b005b6101ed7f000000000000000000000000000000000000000000000000000000000000000081565b6102757f6f7074696d6973742e626173652d75726900000000000000000000000000000081565b6040519081526020016101bc565b610225610291366004611e02565b61061d565b6102256102a4366004611e02565b6106aa565b6102256102b7366004611d96565b6106c5565b6102256102ca366004611f24565b61074c565b6101cd6108cf565b6101ed6102e5366004611d96565b610972565b6102256102f8366004611f88565b6109e4565b6101cd610a7f565b610275610313366004611f88565b610b94565b610275610326366004611f88565b73ffffffffffffffffffffffffffffffffffffffff1690565b6101b061034d366004611f88565b610c48565b6101cd610cfd565b610225610220366004611fb1565b610225610376366004611fe8565b610d0c565b6101cd610389366004611d96565b610d9a565b6101ed7f000000000000000000000000000000000000000000000000000000000000000081565b6101ed7f000000000000000000000000000000000000000000000000000000000000000081565b6101b06103ea366004612064565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152606a6020908152604080832093909416825291909152205460ff1690565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd0000000000000000000000000000000000000000000000000000000014806104b857507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061050457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60606065805461051990612097565b80601f016020809104026020016040519081016040528092919081815260200182805461054590612097565b80156105925780601f1061056757610100808354040283529160200191610592565b820191906000526020600020905b81548152906001019060200180831161057557829003601f168201915b5050505050905090565b60006105a782610df2565b5060009081526069602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b60405162461bcd60e51b815260206004820152601a60248201527f4f7074696d6973743a20736f756c20626f756e6420746f6b656e00000000000060448201526064015b60405180910390fd5b610628335b82610e63565b61069a5760405162461bcd60e51b815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610614565b6106a5838383610f23565b505050565b6106a583838360405180602001604052806000815250610d0c565b6106ce33610622565b6107405760405162461bcd60e51b815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610614565b61074981611161565b50565b600054610100900460ff161580801561076c5750600054600160ff909116105b806107865750303b158015610786575060005460ff166001145b6107f85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610614565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561085657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610860838361123b565b6108686112c2565b80156106a557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b60606108fa7f0000000000000000000000000000000000000000000000000000000000000000611341565b6109237f0000000000000000000000000000000000000000000000000000000000000000611341565b61094c7f0000000000000000000000000000000000000000000000000000000000000000611341565b60405160200161095e939291906120ea565b604051602081830303815290604052905090565b60008181526067602052604081205473ffffffffffffffffffffffffffffffffffffffff16806105045760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610614565b6109ed81610c48565b610a5f5760405162461bcd60e51b815260206004820152602560248201527f4f7074696d6973743a2061646472657373206973206e6f74206f6e20616c6c6f60448201527f774c6973740000000000000000000000000000000000000000000000000000006064820152608401610614565b6107498173ffffffffffffffffffffffffffffffffffffffff8116611476565b6040517f29b42cb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301523060248301527f6f7074696d6973742e626173652d75726900000000000000000000000000000060448301526060917f0000000000000000000000000000000000000000000000000000000000000000909116906329b42cb590606401600060405180830381865afa158015610b5c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b849190810190612160565b60405160200161095e91906121d7565b600073ffffffffffffffffffffffffffffffffffffffff8216610c1f5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f74206120766160448201527f6c6964206f776e657200000000000000000000000000000000000000000000006064820152608401610614565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526068602052604090205490565b6040517f4813d8a600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690634813d8a690602401602060405180830381865afa158015610cd9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050491906121f3565b60606066805461051990612097565b610d163383610e63565b610d885760405162461bcd60e51b815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610614565b610d9484848484611490565b50505050565b6060610da4610a7f565b610daf836014611519565b604051602001610dc0929190612210565b6040516020818303038152906040529050919050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60008181526067602052604090205473ffffffffffffffffffffffffffffffffffffffff166107495760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610614565b600080610e6f83610972565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610edd575073ffffffffffffffffffffffffffffffffffffffff8082166000908152606a602090815260408083209388168352929052205460ff165b80610f1b57508373ffffffffffffffffffffffffffffffffffffffff16610f038461059c565b73ffffffffffffffffffffffffffffffffffffffff16145b949350505050565b8273ffffffffffffffffffffffffffffffffffffffff16610f4382610972565b73ffffffffffffffffffffffffffffffffffffffff1614610fcc5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610614565b73ffffffffffffffffffffffffffffffffffffffff82166110545760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610614565b61105f838383611749565b61106a6000826117cc565b73ffffffffffffffffffffffffffffffffffffffff831660009081526068602052604081208054600192906110a09084906122c1565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526068602052604081208054600192906110db9084906122d8565b909155505060008181526067602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061116c82610972565b905061117a81600084611749565b6111856000836117cc565b73ffffffffffffffffffffffffffffffffffffffff811660009081526068602052604081208054600192906111bb9084906122c1565b909155505060008281526067602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555183919073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45b5050565b600054610100900460ff166112b85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610614565b611237828261186c565b600054610100900460ff1661133f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610614565b565b60608160000361138457505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156113ae5780611398816122f0565b91506113a79050600a83612357565b9150611388565b60008167ffffffffffffffff8111156113c9576113c9611e3e565b6040519080825280601f01601f1916602001820160405280156113f3576020820181803683370190505b5090505b8415610f1b576114086001836122c1565b9150611415600a8661236b565b6114209060306122d8565b60f81b8183815181106114355761143561237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061146f600a86612357565b94506113f7565b611237828260405180602001604052806000815250611902565b61149b848484610f23565b6114a78484848461198b565b610d945760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610614565b606060006115288360026123ae565b6115339060026122d8565b67ffffffffffffffff81111561154b5761154b611e3e565b6040519080825280601f01601f191660200182016040528015611575576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106115ac576115ac61237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061160f5761160f61237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061164b8460026123ae565b6116569060016122d8565b90505b60018111156116f3577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106116975761169761237f565b1a60f81b8282815181106116ad576116ad61237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936116ec816123eb565b9050611659565b5083156117425760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610614565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff83161580611780575073ffffffffffffffffffffffffffffffffffffffff8216155b6106a55760405162461bcd60e51b815260206004820152601a60248201527f4f7074696d6973743a20736f756c20626f756e6420746f6b656e0000000000006044820152606401610614565b600081815260696020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155819061182682610972565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600054610100900460ff166118e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610614565b60656118f5838261246e565b5060666106a5828261246e565b61190c8383611b46565b611919600084848461198b565b6106a55760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610614565b600073ffffffffffffffffffffffffffffffffffffffff84163b15611b3b576040517f150b7a0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063150b7a0290611a0290339089908890889060040161256a565b6020604051808303816000875af1925050508015611a3d575060408051601f3d908101601f19168201909252611a3a918101906125b3565b60015b611af0573d808015611a6b576040519150601f19603f3d011682016040523d82523d6000602084013e611a70565b606091505b508051600003611ae85760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610614565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149050610f1b565b506001949350505050565b73ffffffffffffffffffffffffffffffffffffffff8216611ba95760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610614565b60008181526067602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611c1b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610614565b611c2760008383611749565b73ffffffffffffffffffffffffffffffffffffffff82166000908152606860205260408120805460019290611c5d9084906122d8565b909155505060008181526067602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461074957600080fd5b600060208284031215611d2057600080fd5b813561174281611ce0565b60005b83811015611d46578181015183820152602001611d2e565b83811115610d945750506000910152565b60008151808452611d6f816020860160208601611d2b565b601f01601f19169290920160200192915050565b6020815260006117426020830184611d57565b600060208284031215611da857600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611dd357600080fd5b919050565b60008060408385031215611deb57600080fd5b611df483611daf565b946020939093013593505050565b600080600060608486031215611e1757600080fd5b611e2084611daf565b9250611e2e60208501611daf565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611e9657611e96611e3e565b604052919050565b600067ffffffffffffffff821115611eb857611eb8611e3e565b50601f01601f191660200190565b6000611ed9611ed484611e9e565b611e6d565b9050828152838383011115611eed57600080fd5b828260208301376000602084830101529392505050565b600082601f830112611f1557600080fd5b61174283833560208501611ec6565b60008060408385031215611f3757600080fd5b823567ffffffffffffffff80821115611f4f57600080fd5b611f5b86838701611f04565b93506020850135915080821115611f7157600080fd5b50611f7e85828601611f04565b9150509250929050565b600060208284031215611f9a57600080fd5b61174282611daf565b801515811461074957600080fd5b60008060408385031215611fc457600080fd5b611fcd83611daf565b91506020830135611fdd81611fa3565b809150509250929050565b60008060008060808587031215611ffe57600080fd5b61200785611daf565b935061201560208601611daf565b925060408501359150606085013567ffffffffffffffff81111561203857600080fd5b8501601f8101871361204957600080fd5b61205887823560208401611ec6565b91505092959194509250565b6000806040838503121561207757600080fd5b61208083611daf565b915061208e60208401611daf565b90509250929050565b600181811c908216806120ab57607f821691505b6020821081036120e4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600084516120fc818460208901611d2b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612138816001850160208a01611d2b565b60019201918201528351612153816002840160208801611d2b565b0160020195945050505050565b60006020828403121561217257600080fd5b815167ffffffffffffffff81111561218957600080fd5b8201601f8101841361219a57600080fd5b80516121a8611ed482611e9e565b8181528560208385010111156121bd57600080fd5b6121ce826020830160208601611d2b565b95945050505050565b600082516121e9818460208701611d2b565b9190910192915050565b60006020828403121561220557600080fd5b815161174281611fa3565b60008351612222818460208801611d2b565b7f2f00000000000000000000000000000000000000000000000000000000000000908301908152835161225c816001840160208801611d2b565b7f2e6a736f6e00000000000000000000000000000000000000000000000000000060019290910191820152600601949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156122d3576122d3612292565b500390565b600082198211156122eb576122eb612292565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361232157612321612292565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261236657612366612328565b500490565b60008261237a5761237a612328565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156123e6576123e6612292565b500290565b6000816123fa576123fa612292565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b601f8211156106a557600081815260208120601f850160051c810160208610156124475750805b601f850160051c820191505b8181101561246657828155600101612453565b505050505050565b815167ffffffffffffffff81111561248857612488611e3e565b61249c816124968454612097565b84612420565b602080601f8311600181146124ef57600084156124b95750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612466565b600085815260208120601f198616915b8281101561251e578886015182559484019460019091019084016124ff565b508582101561255a57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526125a96080830184611d57565b9695505050505050565b6000602082840312156125c557600080fd5b815161174281611ce056fea264697066735822122068519f9cbd8d80e9e293c6c977994da4f38aba3722422b6bfce53b68916efab964736f6c634300080f0033", - "devdoc": { - "author": "Optimism CollectiveGitcoin", - "kind": "dev", - "methods": { - "balanceOf(address)": { - "details": "See {IERC721-balanceOf}." - }, - "baseURI()": { - "returns": { - "_0": "BaseURI for all tokens." - } - }, - "burn(uint256)": { - "details": "Burns `tokenId`. See {ERC721-_burn}. Requirements: - The caller must own `tokenId` or be an approved operator." - }, - "constructor": { - "custom:semver": "2.0.0", - "params": { - "_attestationStation": "Address of the AttestationStation contract.", - "_baseURIAttestor": "Address of the baseURI attestor.", - "_name": "Token name.", - "_optimistAllowlist": "Address of the OptimistAllowlist contract", - "_symbol": "Token symbol." - } - }, - "getApproved(uint256)": { - "details": "See {IERC721-getApproved}." - }, - "initialize(string,string)": { - "params": { - "_name": "Token name.", - "_symbol": "Token symbol." - } - }, - "isApprovedForAll(address,address)": { - "details": "See {IERC721-isApprovedForAll}." - }, - "isOnAllowList(address)": { - "returns": { - "_0": "Whether or not the address is allowed to mint yet." - } - }, - "mint(address)": { - "params": { - "_recipient": "Address of the token recipient." - } - }, - "name()": { - "details": "See {IERC721Metadata-name}." - }, - "ownerOf(uint256)": { - "details": "See {IERC721-ownerOf}." - }, - "safeTransferFrom(address,address,uint256)": { - "details": "See {IERC721-safeTransferFrom}." - }, - "safeTransferFrom(address,address,uint256,bytes)": { - "details": "See {IERC721-safeTransferFrom}." - }, - "supportsInterface(bytes4)": { - "details": "See {IERC165-supportsInterface}." - }, - "symbol()": { - "details": "See {IERC721Metadata-symbol}." - }, - "tokenIdOfAddress(address)": { - "returns": { - "_0": "Token ID for the token owned by the given address." - } - }, - "tokenURI(uint256)": { - "params": { - "_tokenId": "Token ID to query." - }, - "returns": { - "_0": "Token URI for the given token by ID." - } - }, - "transferFrom(address,address,uint256)": { - "details": "See {IERC721-transferFrom}." - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "title": "Optimist", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "ATTESTATION_STATION()": { - "notice": "Address of the AttestationStation contract." - }, - "BASE_URI_ATTESTATION_KEY()": { - "notice": "Attestation key used by the attestor to attest the baseURI." - }, - "BASE_URI_ATTESTOR()": { - "notice": "Attestor who attests to baseURI." - }, - "OPTIMIST_ALLOWLIST()": { - "notice": "Address of the OptimistAllowlist contract." - }, - "approve(address,uint256)": { - "notice": "Disabled for the Optimist NFT (Soul Bound Token)." - }, - "baseURI()": { - "notice": "Returns the baseURI for all tokens." - }, - "initialize(string,string)": { - "notice": "Initializes the Optimist contract." - }, - "isOnAllowList(address)": { - "notice": "Checks OptimistAllowlist to determine whether a given address is allowed to mint the Optimist NFT. Since the Optimist NFT will also be used as part of the Citizens House, mints are currently restricted. Eventually anyone will be able to mint." - }, - "mint(address)": { - "notice": "Allows an address to mint an Optimist NFT. Token ID is the uint256 representation of the recipient's address. Recipients must be permitted to mint, eventually anyone will be able to mint. One token per address." - }, - "setApprovalForAll(address,bool)": { - "notice": "Disabled for the Optimist NFT (Soul Bound Token)." - }, - "tokenIdOfAddress(address)": { - "notice": "Returns the token ID for the token owned by a given address. This is the uint256 representation of the given address." - }, - "tokenURI(uint256)": { - "notice": "Returns the token URI for a given token by ID" - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "A Soul Bound Token for real humans only(tm).", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 1166, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 1169, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 2697, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 3505, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "__gap", - "offset": 0, - "slot": "51", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 1339, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_name", - "offset": 0, - "slot": "101", - "type": "t_string_storage" - }, - { - "astId": 1341, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_symbol", - "offset": 0, - "slot": "102", - "type": "t_string_storage" - }, - { - "astId": 1345, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_owners", - "offset": 0, - "slot": "103", - "type": "t_mapping(t_uint256,t_address)" - }, - { - "astId": 1349, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_balances", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 1353, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_tokenApprovals", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_uint256,t_address)" - }, - { - "astId": 1359, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_operatorApprovals", - "offset": 0, - "slot": "106", - "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" - }, - { - "astId": 2201, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "__gap", - "offset": 0, - "slot": "107", - "type": "t_array(t_uint256)44_storage" - }, - { - "astId": 2385, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "__gap", - "offset": 0, - "slot": "151", - "type": "t_array(t_uint256)50_storage" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)44_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[44]", - "numberOfBytes": "1408" - }, - "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_mapping(t_address,t_mapping(t_address,t_bool))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => bool))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_bool)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_mapping(t_uint256,t_address)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => address)", - "numberOfBytes": "32", - "value": "t_address" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "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-bedrock/deployments/optimism-goerli/OptimistAllowlist.json b/packages/contracts-bedrock/deployments/optimism-goerli/OptimistAllowlist.json deleted file mode 100644 index 20736b2dfdd4..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/OptimistAllowlist.json +++ /dev/null @@ -1,232 +0,0 @@ -{ - "address": "0x1EC6A94aee0Ff4BB21d4852da2D07b8Fd25914a0", - "abi": [ - { - "inputs": [ - { - "internalType": "contract AttestationStation", - "name": "_attestationStation", - "type": "address" - }, - { - "internalType": "address", - "name": "_allowlistAttestor", - "type": "address" - }, - { - "internalType": "address", - "name": "_coinbaseQuestAttestor", - "type": "address" - }, - { - "internalType": "address", - "name": "_optimistInviter", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ALLOWLIST_ATTESTOR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ATTESTATION_STATION", - "outputs": [ - { - "internalType": "contract AttestationStation", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "COINBASE_QUEST_ATTESTOR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMIST_CAN_MINT_ATTESTATION_KEY", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMIST_INVITER", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_claimer", - "type": "address" - } - ], - "name": "isAllowedToMint", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x5673e56b5a4f86f06bac8ed41f0f67ab12d1aaee313770d23d173f3736493be0", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x8F0EBDaA1cF7106bE861753B0f9F5c0250fE0819", - "contractAddress": null, - "transactionIndex": 3, - "gasUsed": "568770", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x6badea5d408ed78fae97b6620d71146646ab68889ad2a3cac3813af7cc9e6280", - "transactionHash": "0x5673e56b5a4f86f06bac8ed41f0f67ab12d1aaee313770d23d173f3736493be0", - "logs": [], - "blockNumber": 8253248, - "cumulativeGasUsed": "878505", - "status": 1, - "byzantium": true - }, - "args": [ - "0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77", - "0x8F0EBDaA1cF7106bE861753B0f9F5c0250fE0819", - "0x9A75024c09b48B78205dfCf9D9FC5E026CD9A416", - "0x073031A1E1b8F5458Ed41Ce56331F5fd7e1de929" - ], - "numDeployments": 2, - "solcInputHash": "d7155764d4bdb814f10e1bb45296292b", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract AttestationStation\",\"name\":\"_attestationStation\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_allowlistAttestor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_coinbaseQuestAttestor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_optimistInviter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ALLOWLIST_ATTESTOR\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ATTESTATION_STATION\",\"outputs\":[{\"internalType\":\"contract AttestationStation\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COINBASE_QUEST_ATTESTOR\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OPTIMIST_CAN_MINT_ATTESTATION_KEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OPTIMIST_INVITER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_claimer\",\"type\":\"address\"}],\"name\":\"isAllowedToMint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:semver\":\"1.0.0\",\"params\":{\"_allowlistAttestor\":\"Address of the allowlist attestor.\",\"_attestationStation\":\"Address of the AttestationStation contract.\",\"_coinbaseQuestAttestor\":\"Address of the Coinbase Quest attestor.\",\"_optimistInviter\":\"Address of the OptimistInviter contract.\"}},\"isAllowedToMint(address)\":{\"params\":{\"_claimer\":\"Address to check.\"},\"returns\":{\"_0\":\"Whether or not the address is allowed to mint yet.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"OptimistAllowlist\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"ALLOWLIST_ATTESTOR()\":{\"notice\":\"Attestor that issues 'optimist.can-mint' attestations.\"},\"ATTESTATION_STATION()\":{\"notice\":\"Address of the AttestationStation contract.\"},\"COINBASE_QUEST_ATTESTOR()\":{\"notice\":\"Attestor that issues 'coinbase.quest-eligible' attestations.\"},\"COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY()\":{\"notice\":\"Attestation key used by Coinbase to issue attestations for Quest participants.\"},\"OPTIMIST_CAN_MINT_ATTESTATION_KEY()\":{\"notice\":\"Attestation key used by the AllowlistAttestor to manually add addresses to the allowlist.\"},\"OPTIMIST_INVITER()\":{\"notice\":\"Address of OptimistInviter contract that issues 'optimist.can-mint-from-invite' attestations.\"},\"isAllowedToMint(address)\":{\"notice\":\"Checks whether a given address is allowed to mint the Optimist NFT yet. Since the Optimist NFT will also be used as part of the Citizens House, mints are currently restricted. Eventually anyone will be able to mint. Currently, address is allowed to mint if it satisfies any of the following: 1) Has a valid 'optimist.can-mint' attestation from the allowlist attestor. 2) Has a valid 'coinbase.quest-eligible' attestation from Coinbase Quest attestor 3) Has a valid 'optimist.can-mint-from-invite' attestation from the OptimistInviter contract.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"Source of truth for whether an address is able to mint an Optimist NFT. isAllowedToMint function checks various signals to return boolean value for whether an address is eligible or not.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/op-nft/OptimistAllowlist.sol\":\"OptimistAllowlist\"},\"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.0;\\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 uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\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\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\\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 /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/universal/op-nft/AttestationStation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title AttestationStation\\n * @author Optimism Collective\\n * @author Gitcoin\\n * @notice Where attestations live.\\n */\\ncontract AttestationStation is Semver {\\n /**\\n * @notice Struct representing data that is being attested.\\n *\\n * @custom:field about Address for which the attestation is about.\\n * @custom:field key A bytes32 key for the attestation.\\n * @custom:field val The attestation as arbitrary bytes.\\n */\\n struct AttestationData {\\n address about;\\n bytes32 key;\\n bytes val;\\n }\\n\\n /**\\n * @notice Maps addresses to attestations. Creator => About => Key => Value.\\n */\\n mapping(address => mapping(address => mapping(bytes32 => bytes))) public attestations;\\n\\n /**\\n * @notice Emitted when Attestation is created.\\n *\\n * @param creator Address that made the attestation.\\n * @param about Address attestation is about.\\n * @param key Key of the attestation.\\n * @param val Value of the attestation.\\n */\\n event AttestationCreated(\\n address indexed creator,\\n address indexed about,\\n bytes32 indexed key,\\n bytes val\\n );\\n\\n /**\\n * @custom:semver 1.1.0\\n */\\n constructor() Semver(1, 1, 0) {}\\n\\n /**\\n * @notice Allows anyone to create an attestation.\\n *\\n * @param _about Address that the attestation is about.\\n * @param _key A key used to namespace the attestation.\\n * @param _val An arbitrary value stored as part of the attestation.\\n */\\n function attest(\\n address _about,\\n bytes32 _key,\\n bytes memory _val\\n ) public {\\n attestations[msg.sender][_about][_key] = _val;\\n\\n emit AttestationCreated(msg.sender, _about, _key, _val);\\n }\\n\\n /**\\n * @notice Allows anyone to create attestations.\\n *\\n * @param _attestations An array of AttestationData structs.\\n */\\n function attest(AttestationData[] calldata _attestations) external {\\n uint256 length = _attestations.length;\\n for (uint256 i = 0; i < length; ) {\\n AttestationData memory attestation = _attestations[i];\\n\\n attest(attestation.about, attestation.key, attestation.val);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x421923e04df145353db12cd0352ccf516d9c29ab64b138733b4f7a6a450ce2be\",\"license\":\"MIT\"},\"contracts/universal/op-nft/OptimistAllowlist.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\nimport { AttestationStation } from \\\"./AttestationStation.sol\\\";\\nimport { OptimistConstants } from \\\"./libraries/OptimistConstants.sol\\\";\\n\\n/**\\n * @title OptimistAllowlist\\n * @notice Source of truth for whether an address is able to mint an Optimist NFT.\\n isAllowedToMint function checks various signals to return boolean value for whether an\\n address is eligible or not.\\n */\\ncontract OptimistAllowlist is Semver {\\n /**\\n * @notice Attestation key used by the AllowlistAttestor to manually add addresses to the\\n * allowlist.\\n */\\n bytes32 public constant OPTIMIST_CAN_MINT_ATTESTATION_KEY = bytes32(\\\"optimist.can-mint\\\");\\n\\n /**\\n * @notice Attestation key used by Coinbase to issue attestations for Quest participants.\\n */\\n bytes32 public constant COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY =\\n bytes32(\\\"coinbase.quest-eligible\\\");\\n\\n /**\\n * @notice Address of the AttestationStation contract.\\n */\\n AttestationStation public immutable ATTESTATION_STATION;\\n\\n /**\\n * @notice Attestor that issues 'optimist.can-mint' attestations.\\n */\\n address public immutable ALLOWLIST_ATTESTOR;\\n\\n /**\\n * @notice Attestor that issues 'coinbase.quest-eligible' attestations.\\n */\\n address public immutable COINBASE_QUEST_ATTESTOR;\\n\\n /**\\n * @notice Address of OptimistInviter contract that issues 'optimist.can-mint-from-invite'\\n * attestations.\\n */\\n address public immutable OPTIMIST_INVITER;\\n\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _attestationStation Address of the AttestationStation contract.\\n * @param _allowlistAttestor Address of the allowlist attestor.\\n * @param _coinbaseQuestAttestor Address of the Coinbase Quest attestor.\\n * @param _optimistInviter Address of the OptimistInviter contract.\\n */\\n constructor(\\n AttestationStation _attestationStation,\\n address _allowlistAttestor,\\n address _coinbaseQuestAttestor,\\n address _optimistInviter\\n ) Semver(1, 0, 0) {\\n ATTESTATION_STATION = _attestationStation;\\n ALLOWLIST_ATTESTOR = _allowlistAttestor;\\n COINBASE_QUEST_ATTESTOR = _coinbaseQuestAttestor;\\n OPTIMIST_INVITER = _optimistInviter;\\n }\\n\\n /**\\n * @notice Checks whether a given address is allowed to mint the Optimist NFT yet. Since the\\n * Optimist NFT will also be used as part of the Citizens House, mints are currently\\n * restricted. Eventually anyone will be able to mint.\\n *\\n * Currently, address is allowed to mint if it satisfies any of the following:\\n * 1) Has a valid 'optimist.can-mint' attestation from the allowlist attestor.\\n * 2) Has a valid 'coinbase.quest-eligible' attestation from Coinbase Quest attestor\\n * 3) Has a valid 'optimist.can-mint-from-invite' attestation from the OptimistInviter\\n * contract.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address is allowed to mint yet.\\n */\\n function isAllowedToMint(address _claimer) public view returns (bool) {\\n return\\n _hasAttestationFromAllowlistAttestor(_claimer) ||\\n _hasAttestationFromCoinbaseQuestAttestor(_claimer) ||\\n _hasAttestationFromOptimistInviter(_claimer);\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid 'optimist.can-mint' attestation from the\\n * allowlist attestor.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address has a valid attestation.\\n */\\n function _hasAttestationFromAllowlistAttestor(address _claimer) internal view returns (bool) {\\n // Expected attestation value is bytes32(\\\"true\\\")\\n return\\n _hasValidAttestation(ALLOWLIST_ATTESTOR, _claimer, OPTIMIST_CAN_MINT_ATTESTATION_KEY);\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid attestation from the Coinbase attestor.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address has a valid attestation.\\n */\\n function _hasAttestationFromCoinbaseQuestAttestor(address _claimer)\\n internal\\n view\\n returns (bool)\\n {\\n // Expected attestation value is bytes32(\\\"true\\\")\\n return\\n _hasValidAttestation(\\n COINBASE_QUEST_ATTESTOR,\\n _claimer,\\n COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY\\n );\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid attestation from the OptimistInviter contract.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address has a valid attestation.\\n */\\n function _hasAttestationFromOptimistInviter(address _claimer) internal view returns (bool) {\\n // Expected attestation value is the inviter's address\\n return\\n _hasValidAttestation(\\n OPTIMIST_INVITER,\\n _claimer,\\n OptimistConstants.OPTIMIST_CAN_MINT_FROM_INVITE_ATTESTATION_KEY\\n );\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid truthy attestation.\\n * Any attestation val other than bytes32(\\\"\\\") is considered truthy.\\n *\\n * @param _creator Address that made the attestation.\\n * @param _about Address attestation is about.\\n * @param _key Key of the attestation.\\n *\\n * @return Whether or not the address has a valid truthy attestation.\\n */\\n function _hasValidAttestation(\\n address _creator,\\n address _about,\\n bytes32 _key\\n ) internal view returns (bool) {\\n return ATTESTATION_STATION.attestations(_creator, _about, _key).length > 0;\\n }\\n}\\n\",\"keccak256\":\"0xd36a677571450d2d9be832beb80e5c37481fcdfc355e6a9b929ac9c8d4966ca0\",\"license\":\"MIT\"},\"contracts/universal/op-nft/libraries/OptimistConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title OptimistConstants\\n * @notice Library for storing Optimist related constants that are shared in multiple contracts.\\n */\\n\\nlibrary OptimistConstants {\\n /**\\n * @notice Attestation key issued by OptimistInviter allowing the attested account to mint.\\n */\\n bytes32 internal constant OPTIMIST_CAN_MINT_FROM_INVITE_ATTESTATION_KEY =\\n bytes32(\\\"optimist.can-mint-from-invite\\\");\\n}\\n\",\"keccak256\":\"0x6eebe1db87f8a5de79bf8af9120e5b0cc6a9b51d8d86e6461cdb6bc52a1dde21\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x61016060405234801561001157600080fd5b50604051610a9d380380610a9d8339810160408190526100309161007c565b6001608052600060a081905260c0526001600160a01b0393841660e0529183166101005282166101205216610140526100db565b6001600160a01b038116811461007957600080fd5b50565b6000806000806080858703121561009257600080fd5b845161009d81610064565b60208601519094506100ae81610064565b60408601519093506100bf81610064565b60608601519092506100d081610064565b939692955090935050565b60805160a05160c05160e05161010051610120516101405161094d6101506000396000818161011b015261035a0152600081816092015261030d01526000818161019e01526102c001526000818161017701526105360152600061026f015260006102460152600061021d015261094d6000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063819f7e841161005b578063819f7e841461013d578063db083d7114610172578063db3c316314610199578063e7bd804e146101c057600080fd5b80633ac52df71461008d5780634813d8a6146100de57806354fd4d50146101015780635e4f489a14610116575b600080fd5b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f16100ec3660046105cd565b6101e7565b60405190151581526020016100d5565b610109610216565b6040516100d5919061063a565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6101647f636f696e626173652e71756573742d656c696769626c6500000000000000000081565b6040519081526020016100d5565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6101647f6f7074696d6973742e63616e2d6d696e7400000000000000000000000000000081565b60006101f2826102b9565b80610201575061020182610306565b80610210575061021082610353565b92915050565b60606102417f00000000000000000000000000000000000000000000000000000000000000006103a0565b61026a7f00000000000000000000000000000000000000000000000000000000000000006103a0565b6102937f00000000000000000000000000000000000000000000000000000000000000006103a0565b6040516020016102a59392919061068b565b604051602081830303815290604052905090565b60006102107f0000000000000000000000000000000000000000000000000000000000000000837f6f7074696d6973742e63616e2d6d696e740000000000000000000000000000006104dd565b60006102107f0000000000000000000000000000000000000000000000000000000000000000837f636f696e626173652e71756573742d656c696769626c650000000000000000006104dd565b60006102107f0000000000000000000000000000000000000000000000000000000000000000837f6f7074696d6973742e63616e2d6d696e742d66726f6d2d696e766974650000006104dd565b6060816000036103e357505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561040d57806103f781610730565b91506104069050600a83610797565b91506103e7565b60008167ffffffffffffffff811115610428576104286107ab565b6040519080825280601f01601f191660200182016040528015610452576020820181803683370190505b5090505b84156104d5576104676001836107da565b9150610474600a866107f1565b61047f906030610805565b60f81b8183815181106104945761049461081d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506104ce600a86610797565b9450610456565b949350505050565b6040517f29b42cb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283811660248301526044820183905260009182917f000000000000000000000000000000000000000000000000000000000000000016906329b42cb590606401600060405180830381865afa15801561057d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105c3919081019061084c565b5111949350505050565b6000602082840312156105df57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461060357600080fd5b9392505050565b60005b8381101561062557818101518382015260200161060d565b83811115610634576000848401525b50505050565b602081526000825180602084015261065981604085016020870161060a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000845161069d81846020890161060a565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516106d9816001850160208a0161060a565b600192019182015283516106f481600284016020880161060a565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361076157610761610701565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826107a6576107a6610768565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107ec576107ec610701565b500390565b60008261080057610800610768565b500690565b6000821982111561081857610818610701565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561085e57600080fd5b815167ffffffffffffffff8082111561087657600080fd5b818401915084601f83011261088a57600080fd5b81518181111561089c5761089c6107ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e2576108e26107ab565b816040528281528760208487010111156108fb57600080fd5b61090c83602083016020880161060a565b97965050505050505056fea2646970667358221220f7c9eee125b4662acd39871c7f71fd0d6635d58d3d0d2d059a8c8bb16ba6d74564736f6c634300080f0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063819f7e841161005b578063819f7e841461013d578063db083d7114610172578063db3c316314610199578063e7bd804e146101c057600080fd5b80633ac52df71461008d5780634813d8a6146100de57806354fd4d50146101015780635e4f489a14610116575b600080fd5b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f16100ec3660046105cd565b6101e7565b60405190151581526020016100d5565b610109610216565b6040516100d5919061063a565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6101647f636f696e626173652e71756573742d656c696769626c6500000000000000000081565b6040519081526020016100d5565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6101647f6f7074696d6973742e63616e2d6d696e7400000000000000000000000000000081565b60006101f2826102b9565b80610201575061020182610306565b80610210575061021082610353565b92915050565b60606102417f00000000000000000000000000000000000000000000000000000000000000006103a0565b61026a7f00000000000000000000000000000000000000000000000000000000000000006103a0565b6102937f00000000000000000000000000000000000000000000000000000000000000006103a0565b6040516020016102a59392919061068b565b604051602081830303815290604052905090565b60006102107f0000000000000000000000000000000000000000000000000000000000000000837f6f7074696d6973742e63616e2d6d696e740000000000000000000000000000006104dd565b60006102107f0000000000000000000000000000000000000000000000000000000000000000837f636f696e626173652e71756573742d656c696769626c650000000000000000006104dd565b60006102107f0000000000000000000000000000000000000000000000000000000000000000837f6f7074696d6973742e63616e2d6d696e742d66726f6d2d696e766974650000006104dd565b6060816000036103e357505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561040d57806103f781610730565b91506104069050600a83610797565b91506103e7565b60008167ffffffffffffffff811115610428576104286107ab565b6040519080825280601f01601f191660200182016040528015610452576020820181803683370190505b5090505b84156104d5576104676001836107da565b9150610474600a866107f1565b61047f906030610805565b60f81b8183815181106104945761049461081d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506104ce600a86610797565b9450610456565b949350505050565b6040517f29b42cb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283811660248301526044820183905260009182917f000000000000000000000000000000000000000000000000000000000000000016906329b42cb590606401600060405180830381865afa15801561057d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105c3919081019061084c565b5111949350505050565b6000602082840312156105df57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461060357600080fd5b9392505050565b60005b8381101561062557818101518382015260200161060d565b83811115610634576000848401525b50505050565b602081526000825180602084015261065981604085016020870161060a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000845161069d81846020890161060a565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516106d9816001850160208a0161060a565b600192019182015283516106f481600284016020880161060a565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361076157610761610701565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826107a6576107a6610768565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107ec576107ec610701565b500390565b60008261080057610800610768565b500690565b6000821982111561081857610818610701565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561085e57600080fd5b815167ffffffffffffffff8082111561087657600080fd5b818401915084601f83011261088a57600080fd5b81518181111561089c5761089c6107ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e2576108e26107ab565b816040528281528760208487010111156108fb57600080fd5b61090c83602083016020880161060a565b97965050505050505056fea2646970667358221220f7c9eee125b4662acd39871c7f71fd0d6635d58d3d0d2d059a8c8bb16ba6d74564736f6c634300080f0033", - "devdoc": { - "kind": "dev", - "methods": { - "constructor": { - "custom:semver": "1.0.0", - "params": { - "_allowlistAttestor": "Address of the allowlist attestor.", - "_attestationStation": "Address of the AttestationStation contract.", - "_coinbaseQuestAttestor": "Address of the Coinbase Quest attestor.", - "_optimistInviter": "Address of the OptimistInviter contract." - } - }, - "isAllowedToMint(address)": { - "params": { - "_claimer": "Address to check." - }, - "returns": { - "_0": "Whether or not the address is allowed to mint yet." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "title": "OptimistAllowlist", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "ALLOWLIST_ATTESTOR()": { - "notice": "Attestor that issues 'optimist.can-mint' attestations." - }, - "ATTESTATION_STATION()": { - "notice": "Address of the AttestationStation contract." - }, - "COINBASE_QUEST_ATTESTOR()": { - "notice": "Attestor that issues 'coinbase.quest-eligible' attestations." - }, - "COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY()": { - "notice": "Attestation key used by Coinbase to issue attestations for Quest participants." - }, - "OPTIMIST_CAN_MINT_ATTESTATION_KEY()": { - "notice": "Attestation key used by the AllowlistAttestor to manually add addresses to the allowlist." - }, - "OPTIMIST_INVITER()": { - "notice": "Address of OptimistInviter contract that issues 'optimist.can-mint-from-invite' attestations." - }, - "isAllowedToMint(address)": { - "notice": "Checks whether a given address is allowed to mint the Optimist NFT yet. Since the Optimist NFT will also be used as part of the Citizens House, mints are currently restricted. Eventually anyone will be able to mint. Currently, address is allowed to mint if it satisfies any of the following: 1) Has a valid 'optimist.can-mint' attestation from the allowlist attestor. 2) Has a valid 'coinbase.quest-eligible' attestation from Coinbase Quest attestor 3) Has a valid 'optimist.can-mint-from-invite' attestation from the OptimistInviter contract." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "Source of truth for whether an address is able to mint an Optimist NFT. isAllowedToMint function checks various signals to return boolean value for whether an address is eligible or not.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/OptimistAllowlistProxy.json b/packages/contracts-bedrock/deployments/optimism-goerli/OptimistAllowlistProxy.json deleted file mode 100644 index 4e821b79b1a8..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/OptimistAllowlistProxy.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "address": "0x482b1945D58f2E9Db0CEbe13c7fcFc6876b41180", - "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": "0x1ad6d371fc1567fe96ef97bf4d1b0446a0df8bca5b4bbe36391a8b8039982f21", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 1, - "gasUsed": "534190", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000400000000000000000000000000000000000000000000", - "blockHash": "0x76d8f7991f381ae9eabc900e5684fbb8e1d29b4b22e539ec5369d3f15ae4372d", - "transactionHash": "0x1ad6d371fc1567fe96ef97bf4d1b0446a0df8bca5b4bbe36391a8b8039982f21", - "logs": [ - { - "transactionIndex": 1, - "blockNumber": 7691644, - "transactionHash": "0x1ad6d371fc1567fe96ef97bf4d1b0446a0df8bca5b4bbe36391a8b8039982f21", - "address": "0x482b1945D58f2E9Db0CEbe13c7fcFc6876b41180", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58", - "logIndex": 0, - "blockHash": "0x76d8f7991f381ae9eabc900e5684fbb8e1d29b4b22e539ec5369d3f15ae4372d" - } - ], - "blockNumber": 7691644, - "cumulativeGasUsed": "598191", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "d7155764d4bdb814f10e1bb45296292b", - "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) public virtual 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 public\\n payable\\n virtual\\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) public virtual 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() public virtual proxyCallIfNotAdmin returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function implementation() public virtual 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\":\"0x64d67f1936d97c87a2e42317eb162744ad5cefdc9bc8b1138ee4afe2886eb885\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161094138038061094183398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206109218339815191525490565b600080516020610921833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610830806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea26469706673582212200496188e743eb5556ea8662e234845601d39477882517acc1cf9061fcc51284c64736f6c634300080f0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea26469706673582212200496188e743eb5556ea8662e234845601d39477882517acc1cf9061fcc51284c64736f6c634300080f0033", - "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-bedrock/deployments/optimism-goerli/OptimistInviter.json b/packages/contracts-bedrock/deployments/optimism-goerli/OptimistInviter.json deleted file mode 100644 index 899002bc91c1..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/OptimistInviter.json +++ /dev/null @@ -1,543 +0,0 @@ -{ - "address": "0xe256605bE52B0758fd70E07953dD36fABF9beFd2", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_inviteGranter", - "type": "address" - }, - { - "internalType": "contract AttestationStation", - "name": "_attestationStation", - "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": "address", - "name": "issuer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "claimer", - "type": "address" - } - ], - "name": "InviteClaimed", - "type": "event" - }, - { - "inputs": [], - "name": "ATTESTATION_STATION", - "outputs": [ - { - "internalType": "contract AttestationStation", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "CAN_INVITE_ATTESTATION_KEY", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "CLAIMABLE_INVITE_TYPEHASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "EIP712_VERSION", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INVITE_GRANTER", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MIN_COMMITMENT_PERIOD", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_claimer", - "type": "address" - }, - { - "components": [ - { - "internalType": "address", - "name": "issuer", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "nonce", - "type": "bytes32" - } - ], - "internalType": "struct OptimistInviter.ClaimableInvite", - "name": "_claimableInvite", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "_signature", - "type": "bytes" - } - ], - "name": "claimInvite", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_commitment", - "type": "bytes32" - } - ], - "name": "commitInvite", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "commitmentTimestamps", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "inviteCounts", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "_accounts", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "_inviteCount", - "type": "uint256" - } - ], - "name": "setInviteCounts", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "usedNonces", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x142dcc7b21e97d2199e3c086e0dd94e3293549aea1373c3a856fdf1065a27101", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 3, - "gasUsed": "1650064", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x1f493311ad79e9a938942359c85bf059eac56d3b52289012b283a4c9ebb5ec61", - "transactionHash": "0x142dcc7b21e97d2199e3c086e0dd94e3293549aea1373c3a856fdf1065a27101", - "logs": [], - "blockNumber": 7690225, - "cumulativeGasUsed": "2093837", - "status": 1, - "byzantium": true - }, - "args": [ - "0x8F0EBDaA1cF7106bE861753B0f9F5c0250fE0819", - "0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77" - ], - "numDeployments": 1, - "solcInputHash": "d7155764d4bdb814f10e1bb45296292b", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_inviteGranter\",\"type\":\"address\"},{\"internalType\":\"contract AttestationStation\",\"name\":\"_attestationStation\",\"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\":\"address\",\"name\":\"issuer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"}],\"name\":\"InviteClaimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ATTESTATION_STATION\",\"outputs\":[{\"internalType\":\"contract AttestationStation\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"CAN_INVITE_ATTESTATION_KEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"CLAIMABLE_INVITE_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EIP712_VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INVITE_GRANTER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_COMMITMENT_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_claimer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"issuer\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"nonce\",\"type\":\"bytes32\"}],\"internalType\":\"struct OptimistInviter.ClaimableInvite\",\"name\":\"_claimableInvite\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"claimInvite\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_commitment\",\"type\":\"bytes32\"}],\"name\":\"commitInvite\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"commitmentTimestamps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"inviteCounts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256\",\"name\":\"_inviteCount\",\"type\":\"uint256\"}],\"name\":\"setInviteCounts\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"usedNonces\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"custom:upgradeable\":\"@title OptimistInviter\",\"events\":{\"InviteClaimed(address,address)\":{\"params\":{\"claimer\":\"Address that claimed the invite.\",\"issuer\":\"Address that issued the signature.\"}}},\"kind\":\"dev\",\"methods\":{\"claimInvite(address,(address,bytes32),bytes)\":{\"params\":{\"_claimableInvite\":\"ClaimableInvite struct containing the issuer and nonce.\",\"_claimer\":\"Address that will be granted the invite.\",\"_signature\":\"Signature signed over the claimable invite.\"}},\"commitInvite(bytes32)\":{\"params\":{\"_commitment\":\"A hash of the claimer and signature concatenated. keccak256(abi.encode(_claimer, _signature))\"}},\"constructor\":{\"custom:semver\":\"1.0.0\",\"params\":{\"_attestationStation\":\"Address of the AttestationStation contract.\",\"_inviteGranter\":\"Address of the invite granter.\"}},\"initialize(string)\":{\"params\":{\"_name\":\"Contract name.\"}},\"setInviteCounts(address[],uint256)\":{\"params\":{\"_accounts\":\"An array of accounts to update the invite counts of.\",\"_inviteCount\":\"Number of invites to set to.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"version\":1},\"userdoc\":{\"events\":{\"InviteClaimed(address,address)\":{\"notice\":\"Emitted when an invite is claimed.\"}},\"kind\":\"user\",\"methods\":{\"ATTESTATION_STATION()\":{\"notice\":\"Address of the AttestationStation contract.\"},\"CAN_INVITE_ATTESTATION_KEY()\":{\"notice\":\"Attestation key for that signals that an account was allowed to issue invites\"},\"CLAIMABLE_INVITE_TYPEHASH()\":{\"notice\":\"EIP712 typehash for the ClaimableInvite type.\"},\"EIP712_VERSION()\":{\"notice\":\"Version used for the EIP712 domain separator. This version is separated from the contract semver because the EIP712 domain separator is used to sign messages, and changing the domain separator invalidates all existing signatures. We should only bump this version if we make a major change to the signature scheme.\"},\"INVITE_GRANTER()\":{\"notice\":\"Granter who can set accounts' invite counts.\"},\"MIN_COMMITMENT_PERIOD()\":{\"notice\":\"Minimum age of a commitment (in seconds) before it can be revealed using claimInvite. Currently set to 60 seconds. Prevents an attacker from front-running a commitment by taking the signature in the claimInvite call and quickly committing and claiming it before the the claimer's transaction succeeds. With this, frontrunning a commitment requires that an attacker be able to prevent the honest claimer's claimInvite transaction from being included for this long.\"},\"claimInvite(address,(address,bytes32),bytes)\":{\"notice\":\"Allows anyone to reveal a commitment and claim an invite. The hash, keccak256(abi.encode(_claimer, _signature)), should have been already committed using commitInvite. Before issuing the \\\"optimist.can-mint-from-invite\\\" attestation, this function checks that 1) the hash corresponding to the _claimer and the _signature was committed 2) MIN_COMMITMENT_PERIOD has passed since the commitment was made. 3) the _signature is signed correctly by the issuer 4) the _signature hasn't already been used to claim an invite before 5) the _signature issuer has not used up all of their invites This function doesn't require that the _claimer is calling this function.\"},\"commitInvite(bytes32)\":{\"notice\":\"Allows anyone (but likely the claimer) to commit a received signature along with the address to claim to. Before calling this function, the claimer should have received a signature from the issuer off-chain. The claimer then calls this function with the hash of the claimer's address and the received signature. This is necessary to prevent front-running when the invitee is claiming the invite. Without a commit and reveal scheme, anyone who is watching the mempool can take the signature being submitted and front run the transaction to claim the invite to their own address. The same commitment can only be made once, and the function reverts if the commitment has already been made. This prevents griefing where a malicious party can prevent the original claimer from being able to claimInvite.\"},\"commitmentTimestamps(bytes32)\":{\"notice\":\"Maps from hashes to the timestamp when they were committed.\"},\"initialize(string)\":{\"notice\":\"Initializes this contract, setting the EIP712 context. Only update the EIP712_VERSION when there is a change to the signature scheme. After the EIP712 version is changed, any signatures issued off-chain but not claimed yet will no longer be accepted by the claimInvite function. Please make sure to notify the issuers that they must re-issue their invite signatures.\"},\"inviteCounts(address)\":{\"notice\":\"Maps from addresses to number of invites they have.\"},\"setInviteCounts(address[],uint256)\":{\"notice\":\"Allows invite granter to set the number of invites an address has.\"},\"usedNonces(address,bytes32)\":{\"notice\":\"Maps from addresses to nonces to whether or not they have been used.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"OptimistInviter issues \\\"optimist.can-invite\\\" and \\\"optimist.can-mint-from-invite\\\" attestations. Accounts that have invites can issue signatures that allow other accounts to claim an invite. The invitee uses a claim and reveal flow to claim the invite to an address of their choosing. Parties involved: 1) INVITE_GRANTER: trusted account that can allow accounts to issue invites 2) issuer: account that is allowed to issue invites 3) claimer: account that receives the invites Flow: 1) INVITE_GRANTER calls _setInviteCount to allow an issuer to issue a certain number of invites, and also creates a \\\"optimist.can-invite\\\" attestation for the issuer 2) Off-chain, the issuer signs (EIP-712) a ClaimableInvite to produce a signature 3) Off-chain, invite issuer sends the plaintext ClaimableInvite and the signature to the recipient 4) claimer chooses an address they want to receive the invite on 5) claimer commits the hash of the address they want to receive the invite on and the received signature keccak256(abi.encode(addressToReceiveTo, receivedSignature)) using the commitInvite function 6) claimer waits for the MIN_COMMITMENT_PERIOD to pass. 7) claimer reveals the plaintext ClaimableInvite and the signature using the claimInvite function, receiving the \\\"optimist.can-mint-from-invite\\\" attestation\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/op-nft/OptimistInviter.sol\":\"OptimistInviter\"},\"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.0;\\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 uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\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\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"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/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/StringsUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary StringsUpgradeable {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\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 /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xea5339a7fff0ed42b45be56a88efdd0b2ddde9fa480dc99fef9a6a4c5b776863\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../StringsUpgradeable.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 ECDSAUpgradeable {\\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 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 /// @solidity memory-safe-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 {\\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\\\", StringsUpgradeable.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\":\"0xbf5daf926894541a40a64b43c3746aa1940c5a1b3b8d14a06465eea72a9b90cc\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.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 \\\"./ECDSAUpgradeable.sol\\\";\\nimport \\\"../../proxy/utils/Initializable.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 *\\n * @custom:storage-size 52\\n */\\nabstract contract EIP712Upgradeable is Initializable {\\n /* solhint-disable var-name-mixedcase */\\n bytes32 private _HASHED_NAME;\\n bytes32 private _HASHED_VERSION;\\n bytes32 private constant _TYPE_HASH = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\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 function __EIP712_init(string memory name, string memory version) internal onlyInitializing {\\n __EIP712_init_unchained(name, version);\\n }\\n\\n function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\\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 ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n\\n /**\\n * @dev The hash of the name parameter for the EIP712 domain.\\n *\\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\\n * are a concern.\\n */\\n function _EIP712NameHash() internal virtual view returns (bytes32) {\\n return _HASHED_NAME;\\n }\\n\\n /**\\n * @dev The hash of the version parameter for the EIP712 domain.\\n *\\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\\n * are a concern.\\n */\\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\\n return _HASHED_VERSION;\\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\":\"0xaf5a96100f421d61693605349511e43221d3c2e47d4b3efa87af2b936e2567fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/interfaces/IERC1271.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC1271 standard signature validation method for\\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC1271 {\\n /**\\n * @dev Should return whether the signature provided is valid for the provided data\\n * @param hash Hash of the data to be signed\\n * @param signature Signature byte array associated with _data\\n */\\n function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);\\n}\\n\",\"keccak256\":\"0x0705a4b1b86d7b0bd8432118f226ba139c44b9dcaba0a6eafba2dd7d0639c544\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.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 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 /// @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\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\\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 /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.3) (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 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 /// @solidity memory-safe-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 {\\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\":\"0xdb7f5c28fc61cda0bd8ab60ce288e206b791643bcd3ba464a70cbec18895a2f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.1) (utils/cryptography/SignatureChecker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\nimport \\\"../Address.sol\\\";\\nimport \\\"../../interfaces/IERC1271.sol\\\";\\n\\n/**\\n * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA\\n * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like\\n * Argent and Gnosis Safe.\\n *\\n * _Available since v4.1._\\n */\\nlibrary SignatureChecker {\\n /**\\n * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the\\n * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.\\n *\\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\\n */\\n function isValidSignatureNow(\\n address signer,\\n bytes32 hash,\\n bytes memory signature\\n ) internal view returns (bool) {\\n (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);\\n if (error == ECDSA.RecoverError.NoError && recovered == signer) {\\n return true;\\n }\\n\\n (bool success, bytes memory result) = signer.staticcall(\\n abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)\\n );\\n return (success &&\\n result.length == 32 &&\\n abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));\\n }\\n}\\n\",\"keccak256\":\"0xbb5c92a62f2a917ec08667ebc024d5f4172ae3594cd5f4eaa997485ed0440d81\",\"license\":\"MIT\"},\"contracts/universal/op-nft/AttestationStation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title AttestationStation\\n * @author Optimism Collective\\n * @author Gitcoin\\n * @notice Where attestations live.\\n */\\ncontract AttestationStation is Semver {\\n /**\\n * @notice Struct representing data that is being attested.\\n *\\n * @custom:field about Address for which the attestation is about.\\n * @custom:field key A bytes32 key for the attestation.\\n * @custom:field val The attestation as arbitrary bytes.\\n */\\n struct AttestationData {\\n address about;\\n bytes32 key;\\n bytes val;\\n }\\n\\n /**\\n * @notice Maps addresses to attestations. Creator => About => Key => Value.\\n */\\n mapping(address => mapping(address => mapping(bytes32 => bytes))) public attestations;\\n\\n /**\\n * @notice Emitted when Attestation is created.\\n *\\n * @param creator Address that made the attestation.\\n * @param about Address attestation is about.\\n * @param key Key of the attestation.\\n * @param val Value of the attestation.\\n */\\n event AttestationCreated(\\n address indexed creator,\\n address indexed about,\\n bytes32 indexed key,\\n bytes val\\n );\\n\\n /**\\n * @custom:semver 1.1.0\\n */\\n constructor() Semver(1, 1, 0) {}\\n\\n /**\\n * @notice Allows anyone to create an attestation.\\n *\\n * @param _about Address that the attestation is about.\\n * @param _key A key used to namespace the attestation.\\n * @param _val An arbitrary value stored as part of the attestation.\\n */\\n function attest(\\n address _about,\\n bytes32 _key,\\n bytes memory _val\\n ) public {\\n attestations[msg.sender][_about][_key] = _val;\\n\\n emit AttestationCreated(msg.sender, _about, _key, _val);\\n }\\n\\n /**\\n * @notice Allows anyone to create attestations.\\n *\\n * @param _attestations An array of AttestationData structs.\\n */\\n function attest(AttestationData[] calldata _attestations) external {\\n uint256 length = _attestations.length;\\n for (uint256 i = 0; i < length; ) {\\n AttestationData memory attestation = _attestations[i];\\n\\n attest(attestation.about, attestation.key, attestation.val);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x421923e04df145353db12cd0352ccf516d9c29ab64b138733b4f7a6a450ce2be\",\"license\":\"MIT\"},\"contracts/universal/op-nft/OptimistInviter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { OptimistConstants } from \\\"./libraries/OptimistConstants.sol\\\";\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\nimport { AttestationStation } from \\\"./AttestationStation.sol\\\";\\nimport { SignatureChecker } from \\\"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\\\";\\nimport {\\n EIP712Upgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol\\\";\\n\\n/**\\n * @custom:upgradeable\\n * @title OptimistInviter\\n * @notice OptimistInviter issues \\\"optimist.can-invite\\\" and \\\"optimist.can-mint-from-invite\\\"\\n * attestations. Accounts that have invites can issue signatures that allow other\\n * accounts to claim an invite. The invitee uses a claim and reveal flow to claim the\\n * invite to an address of their choosing.\\n *\\n * Parties involved:\\n * 1) INVITE_GRANTER: trusted account that can allow accounts to issue invites\\n * 2) issuer: account that is allowed to issue invites\\n * 3) claimer: account that receives the invites\\n *\\n * Flow:\\n * 1) INVITE_GRANTER calls _setInviteCount to allow an issuer to issue a certain number\\n * of invites, and also creates a \\\"optimist.can-invite\\\" attestation for the issuer\\n * 2) Off-chain, the issuer signs (EIP-712) a ClaimableInvite to produce a signature\\n * 3) Off-chain, invite issuer sends the plaintext ClaimableInvite and the signature\\n * to the recipient\\n * 4) claimer chooses an address they want to receive the invite on\\n * 5) claimer commits the hash of the address they want to receive the invite on and the\\n * received signature keccak256(abi.encode(addressToReceiveTo, receivedSignature))\\n * using the commitInvite function\\n * 6) claimer waits for the MIN_COMMITMENT_PERIOD to pass.\\n * 7) claimer reveals the plaintext ClaimableInvite and the signature using the\\n * claimInvite function, receiving the \\\"optimist.can-mint-from-invite\\\" attestation\\n */\\ncontract OptimistInviter is Semver, EIP712Upgradeable {\\n /**\\n * @notice Emitted when an invite is claimed.\\n *\\n * @param issuer Address that issued the signature.\\n * @param claimer Address that claimed the invite.\\n */\\n event InviteClaimed(address indexed issuer, address indexed claimer);\\n\\n /**\\n * @notice Version used for the EIP712 domain separator. This version is separated from the\\n * contract semver because the EIP712 domain separator is used to sign messages, and\\n * changing the domain separator invalidates all existing signatures. We should only\\n * bump this version if we make a major change to the signature scheme.\\n */\\n string public constant EIP712_VERSION = \\\"1.0.0\\\";\\n\\n /**\\n * @notice EIP712 typehash for the ClaimableInvite type.\\n */\\n bytes32 public constant CLAIMABLE_INVITE_TYPEHASH =\\n keccak256(\\\"ClaimableInvite(address issuer,bytes32 nonce)\\\");\\n\\n /**\\n * @notice Attestation key for that signals that an account was allowed to issue invites\\n */\\n bytes32 public constant CAN_INVITE_ATTESTATION_KEY = bytes32(\\\"optimist.can-invite\\\");\\n\\n /**\\n * @notice Granter who can set accounts' invite counts.\\n */\\n address public immutable INVITE_GRANTER;\\n\\n /**\\n * @notice Address of the AttestationStation contract.\\n */\\n AttestationStation public immutable ATTESTATION_STATION;\\n\\n /**\\n * @notice Minimum age of a commitment (in seconds) before it can be revealed using claimInvite.\\n * Currently set to 60 seconds.\\n *\\n * Prevents an attacker from front-running a commitment by taking the signature in the\\n * claimInvite call and quickly committing and claiming it before the the claimer's\\n * transaction succeeds. With this, frontrunning a commitment requires that an attacker\\n * be able to prevent the honest claimer's claimInvite transaction from being included\\n * for this long.\\n */\\n uint256 public constant MIN_COMMITMENT_PERIOD = 60;\\n\\n /**\\n * @notice Struct that represents a claimable invite that will be signed by the issuer.\\n *\\n * @custom:field issuer Address that issued the signature. Reason this is explicitly included,\\n * and not implicitly assumed to be the recovered address from the\\n * signature is that the issuer may be using a ERC-1271 compatible\\n * contract wallet, where the recovered address is not the same as the\\n * issuer, or the signature is not an ECDSA signature at all.\\n * @custom:field nonce Pseudorandom nonce to prevent replay attacks.\\n */\\n struct ClaimableInvite {\\n address issuer;\\n bytes32 nonce;\\n }\\n\\n /**\\n * @notice Maps from hashes to the timestamp when they were committed.\\n */\\n mapping(bytes32 => uint256) public commitmentTimestamps;\\n\\n /**\\n * @notice Maps from addresses to nonces to whether or not they have been used.\\n */\\n mapping(address => mapping(bytes32 => bool)) public usedNonces;\\n\\n /**\\n * @notice Maps from addresses to number of invites they have.\\n */\\n mapping(address => uint256) public inviteCounts;\\n\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _inviteGranter Address of the invite granter.\\n * @param _attestationStation Address of the AttestationStation contract.\\n */\\n constructor(address _inviteGranter, AttestationStation _attestationStation) Semver(1, 0, 0) {\\n INVITE_GRANTER = _inviteGranter;\\n ATTESTATION_STATION = _attestationStation;\\n }\\n\\n /**\\n * @notice Initializes this contract, setting the EIP712 context.\\n *\\n * Only update the EIP712_VERSION when there is a change to the signature scheme.\\n * After the EIP712 version is changed, any signatures issued off-chain but not\\n * claimed yet will no longer be accepted by the claimInvite function. Please make\\n * sure to notify the issuers that they must re-issue their invite signatures.\\n *\\n * @param _name Contract name.\\n */\\n function initialize(string memory _name) public initializer {\\n __EIP712_init(_name, EIP712_VERSION);\\n }\\n\\n /**\\n * @notice Allows invite granter to set the number of invites an address has.\\n *\\n * @param _accounts An array of accounts to update the invite counts of.\\n * @param _inviteCount Number of invites to set to.\\n */\\n function setInviteCounts(address[] calldata _accounts, uint256 _inviteCount) public {\\n // Only invite granter can grant invites\\n require(\\n msg.sender == INVITE_GRANTER,\\n \\\"OptimistInviter: only invite granter can grant invites\\\"\\n );\\n\\n uint256 length = _accounts.length;\\n\\n AttestationStation.AttestationData[]\\n memory attestations = new AttestationStation.AttestationData[](length);\\n\\n for (uint256 i; i < length; ) {\\n // Set invite count for account to _inviteCount\\n inviteCounts[_accounts[i]] = _inviteCount;\\n\\n // Create an attestation for posterity that the account is allowed to create invites\\n attestations[i] = AttestationStation.AttestationData({\\n about: _accounts[i],\\n key: CAN_INVITE_ATTESTATION_KEY,\\n val: bytes(\\\"true\\\")\\n });\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n ATTESTATION_STATION.attest(attestations);\\n }\\n\\n /**\\n * @notice Allows anyone (but likely the claimer) to commit a received signature along with the\\n * address to claim to.\\n *\\n * Before calling this function, the claimer should have received a signature from the\\n * issuer off-chain. The claimer then calls this function with the hash of the\\n * claimer's address and the received signature. This is necessary to prevent\\n * front-running when the invitee is claiming the invite. Without a commit and reveal\\n * scheme, anyone who is watching the mempool can take the signature being submitted\\n * and front run the transaction to claim the invite to their own address.\\n *\\n * The same commitment can only be made once, and the function reverts if the\\n * commitment has already been made. This prevents griefing where a malicious party can\\n * prevent the original claimer from being able to claimInvite.\\n *\\n *\\n * @param _commitment A hash of the claimer and signature concatenated.\\n * keccak256(abi.encode(_claimer, _signature))\\n */\\n function commitInvite(bytes32 _commitment) public {\\n // Check that the commitment hasn't already been made. This prevents griefing where\\n // a malicious party continuously re-submits the same commitment, preventing the original\\n // claimer from claiming their invite by resetting the minimum commitment period.\\n require(commitmentTimestamps[_commitment] == 0, \\\"OptimistInviter: commitment already made\\\");\\n\\n commitmentTimestamps[_commitment] = block.timestamp;\\n }\\n\\n /**\\n * @notice Allows anyone to reveal a commitment and claim an invite.\\n *\\n * The hash, keccak256(abi.encode(_claimer, _signature)), should have been already\\n * committed using commitInvite. Before issuing the \\\"optimist.can-mint-from-invite\\\"\\n * attestation, this function checks that\\n * 1) the hash corresponding to the _claimer and the _signature was committed\\n * 2) MIN_COMMITMENT_PERIOD has passed since the commitment was made.\\n * 3) the _signature is signed correctly by the issuer\\n * 4) the _signature hasn't already been used to claim an invite before\\n * 5) the _signature issuer has not used up all of their invites\\n * This function doesn't require that the _claimer is calling this function.\\n *\\n * @param _claimer Address that will be granted the invite.\\n * @param _claimableInvite ClaimableInvite struct containing the issuer and nonce.\\n * @param _signature Signature signed over the claimable invite.\\n */\\n function claimInvite(\\n address _claimer,\\n ClaimableInvite calldata _claimableInvite,\\n bytes memory _signature\\n ) public {\\n uint256 commitmentTimestamp = commitmentTimestamps[\\n keccak256(abi.encode(_claimer, _signature))\\n ];\\n\\n // Make sure the claimer and signature have been committed.\\n require(\\n commitmentTimestamp > 0,\\n \\\"OptimistInviter: claimer and signature have not been committed yet\\\"\\n );\\n\\n // Check that MIN_COMMITMENT_PERIOD has passed since the commitment was made.\\n require(\\n commitmentTimestamp + MIN_COMMITMENT_PERIOD <= block.timestamp,\\n \\\"OptimistInviter: minimum commitment period has not elapsed yet\\\"\\n );\\n\\n // Generate a EIP712 typed data hash to compare against the signature.\\n bytes32 digest = _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n CLAIMABLE_INVITE_TYPEHASH,\\n _claimableInvite.issuer,\\n _claimableInvite.nonce\\n )\\n )\\n );\\n\\n // Uses SignatureChecker, which supports both regular ECDSA signatures from EOAs as well as\\n // ERC-1271 signatures from contract wallets or multi-sigs. This means that if the issuer\\n // wants to revoke a signature, they can use a smart contract wallet to issue the signature,\\n // then invalidate the signature after issuing it.\\n require(\\n SignatureChecker.isValidSignatureNow(_claimableInvite.issuer, digest, _signature),\\n \\\"OptimistInviter: invalid signature\\\"\\n );\\n\\n // The issuer's signature commits to a nonce to prevent replay attacks.\\n // This checks that the nonce has not been used for this issuer before. The nonces are\\n // scoped to the issuer address, so the same nonce can be used by different issuers without\\n // clashing.\\n require(\\n usedNonces[_claimableInvite.issuer][_claimableInvite.nonce] == false,\\n \\\"OptimistInviter: nonce has already been used\\\"\\n );\\n\\n // Set the nonce as used for the issuer so that it cannot be replayed.\\n usedNonces[_claimableInvite.issuer][_claimableInvite.nonce] = true;\\n\\n // Failing this check means that the issuer has used up all of their existing invites.\\n require(\\n inviteCounts[_claimableInvite.issuer] > 0,\\n \\\"OptimistInviter: issuer has no invites\\\"\\n );\\n\\n // Reduce the issuer's invite count by 1. Can be unchecked because we check above that\\n // count is > 0.\\n unchecked {\\n --inviteCounts[_claimableInvite.issuer];\\n }\\n\\n // Create the attestation that the claimer can mint from the issuer's invite.\\n // The invite issuer is included in the data of the attestation.\\n ATTESTATION_STATION.attest(\\n _claimer,\\n OptimistConstants.OPTIMIST_CAN_MINT_FROM_INVITE_ATTESTATION_KEY,\\n abi.encode(_claimableInvite.issuer)\\n );\\n\\n emit InviteClaimed(_claimableInvite.issuer, _claimer);\\n }\\n}\\n\",\"keccak256\":\"0xd7b006570c7e0c66ed0a8001c7e57848062913639e65f5bb6f4d8120e2a00c32\",\"license\":\"MIT\"},\"contracts/universal/op-nft/libraries/OptimistConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title OptimistConstants\\n * @notice Library for storing Optimist related constants that are shared in multiple contracts.\\n */\\n\\nlibrary OptimistConstants {\\n /**\\n * @notice Attestation key issued by OptimistInviter allowing the attested account to mint.\\n */\\n bytes32 internal constant OPTIMIST_CAN_MINT_FROM_INVITE_ATTESTATION_KEY =\\n bytes32(\\\"optimist.can-mint-from-invite\\\");\\n}\\n\",\"keccak256\":\"0x6eebe1db87f8a5de79bf8af9120e5b0cc6a9b51d8d86e6461cdb6bc52a1dde21\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x6101206040523480156200001257600080fd5b5060405162001e0938038062001e09833981016040819052620000359162000076565b6001608052600060a081905260c0526001600160a01b0391821660e0521661010052620000b5565b6001600160a01b03811681146200007357600080fd5b50565b600080604083850312156200008a57600080fd5b825162000097816200005d565b6020840151909250620000aa816200005d565b809150509250929050565b60805160a05160c05160e05161010051611cfb6200010e60003960008181610257015281816106510152610c0201526000818160f401526103b401526000610da101526000610d7801526000610d4f0152611cfb6000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063916db22f1161008c578063db083d7111610066578063db083d7114610252578063de2dd22114610279578063eccec5a814610299578063f62d1888146102d557600080fd5b8063916db22f146101e4578063b4245d731461020b578063c4fc453d1461022b57600080fd5b806350b414e6116100c857806350b414e61461016857806350eedbc21461017e57806354fd4d50146101915780635fda04c7146101a657600080fd5b806314b47241146100ef578063187e3cd11461014057806325b27a3d14610155575b600080fd5b6101167f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61015361014e36600461165f565b6102e8565b005b610153610163366004611678565b61039c565b610170603c81565b604051908152602001610137565b61015361018c3660046117df565b6106bf565b610199610d48565b60405161013791906118f5565b6101d46101b4366004611908565b603660209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610137565b6101707f6f7074696d6973742e63616e2d696e766974650000000000000000000000000081565b61017061021936600461165f565b60356020526000908152604090205481565b6101707f6529fd129351e725d7bcbc468b0b0b4675477e56b58514e69ab7e66ddfd20fce81565b6101167f000000000000000000000000000000000000000000000000000000000000000081565b610170610287366004611932565b60376020526000908152604090205481565b6101996040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6101536102e336600461194d565b610deb565b60008181526035602052604090205415610389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4f7074696d697374496e76697465723a20636f6d6d69746d656e7420616c726560448201527f616479206d61646500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000908152603560205260409020429055565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610461576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4f7074696d697374496e76697465723a206f6e6c7920696e766974652067726160448201527f6e7465722063616e206772616e7420696e7669746573000000000000000000006064820152608401610380565b8160008167ffffffffffffffff81111561047d5761047d61171c565b6040519080825280602002602001820160405280156104ca57816020015b6040805160608082018352600080835260208301529181019190915281526020019060019003908161049b5790505b50905060005b828110156106135783603760008888858181106104ef576104ef611996565b90506020020160208101906105049190611932565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550604051806060016040528087878481811061055f5761055f611996565b90506020020160208101906105749190611932565b73ffffffffffffffffffffffffffffffffffffffff1681526020017f6f7074696d6973742e63616e2d696e766974650000000000000000000000000081526020016040518060400160405280600481526020017f747275650000000000000000000000000000000000000000000000000000000081525081525082828151811061060057610600611996565b60209081029190910101526001016104d0565b506040517f5eb5ea1000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690635eb5ea10906106869084906004016119c5565b600060405180830381600087803b1580156106a057600080fd5b505af11580156106b4573d6000803e3d6000fd5b505050505050505050565b60006035600085846040516020016106d8929190611a78565b604051602081830303815290604052805190602001208152602001908152602001600020549050600081116107b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f4f7074696d697374496e76697465723a20636c61696d657220616e642073696760448201527f6e61747572652068617665206e6f74206265656e20636f6d6d6974746564207960648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a401610380565b426107c1603c83611ad6565b111561084f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4f7074696d697374496e76697465723a206d696e696d756d20636f6d6d69746d60448201527f656e7420706572696f6420686173206e6f7420656c61707365642079657400006064820152608401610380565b60006108d27f6529fd129351e725d7bcbc468b0b0b4675477e56b58514e69ab7e66ddfd20fce6108826020870187611932565b6040805160208181019490945273ffffffffffffffffffffffffffffffffffffffff9092169082015290860135606082015260800160405160208183030381529060405280519060200120610fb5565b90506108eb6108e46020860186611932565b8285611024565b610977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4f7074696d697374496e76697465723a20696e76616c6964207369676e61747560448201527f72650000000000000000000000000000000000000000000000000000000000006064820152608401610380565b603660006109886020870187611932565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040908101600090812087840135825290925290205460ff1615610a4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4f7074696d697374496e76697465723a206e6f6e63652068617320616c72656160448201527f6479206265656e207573656400000000000000000000000000000000000000006064820152608401610380565b600160366000610a626020880188611932565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040908101600090812088840180358352935290812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016931515939093179092556037908290610ad69088611932565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411610b9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f7074696d697374496e76697465723a2069737375657220686173206e6f206960448201527f6e766974657300000000000000000000000000000000000000000000000000006064820152608401610380565b60376000610baf6020870187611932565b73ffffffffffffffffffffffffffffffffffffffff9081168252602080830193909352604090910160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190557f0000000000000000000000000000000000000000000000000000000000000000169063702b9dee9087907f6f7074696d6973742e63616e2d6d696e742d66726f6d2d696e7669746500000090610c5990890189611932565b6040805173ffffffffffffffffffffffffffffffffffffffff9092166020830152016040516020818303038152906040526040518463ffffffff1660e01b8152600401610ca893929190611aee565b600060405180830381600087803b158015610cc257600080fd5b505af1158015610cd6573d6000803e3d6000fd5b50505073ffffffffffffffffffffffffffffffffffffffff86169050610cff6020860186611932565b73ffffffffffffffffffffffffffffffffffffffff167f745d3c5bc92ab40b418069bf8f8e2030807effceb88bbaa07ee01574f16be47560405160405180910390a35050505050565b6060610d737f00000000000000000000000000000000000000000000000000000000000000006111f3565b610d9c7f00000000000000000000000000000000000000000000000000000000000000006111f3565b610dc57f00000000000000000000000000000000000000000000000000000000000000006111f3565b604051602001610dd793929190611b2c565b604051602081830303815290604052905090565b600054610100900460ff1615808015610e0b5750600054600160ff909116105b80610e255750303b158015610e25575060005460ff166001145b610eb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610380565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610f0f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610f4e826040518060400160405280600581526020017f312e302e30000000000000000000000000000000000000000000000000000000815250611330565b8015610fb157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600061101e610fc26113d1565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b92915050565b60008060006110338585611451565b9092509050600081600481111561104c5761104c611ba2565b14801561108457508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b15611094576001925050506111ec565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b88886040516024016110c9929190611bd1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516111529190611bea565b600060405180830381855afa9150503d806000811461118d576040519150601f19603f3d011682016040523d82523d6000602084013e611192565b606091505b50915091508180156111a5575080516020145b80156111e5575080517f1626ba7e00000000000000000000000000000000000000000000000000000000906111e39083016020908101908401611c06565b145b9450505050505b9392505050565b60608160000361123657505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611260578061124a81611c1f565b91506112599050600a83611c86565b915061123a565b60008167ffffffffffffffff81111561127b5761127b61171c565b6040519080825280601f01601f1916602001820160405280156112a5576020820181803683370190505b5090505b8415611328576112ba600183611c9a565b91506112c7600a86611cb1565b6112d2906030611ad6565b60f81b8183815181106112e7576112e7611996565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611321600a86611c86565b94506112a9565b949350505050565b600054610100900460ff166113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610380565b610fb18282611496565b600061144c7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61140060015490565b6002546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b905090565b60008082516041036114875760208301516040840151606085015160001a61147b87828585611547565b9450945050505061148f565b506000905060025b9250929050565b600054610100900460ff1661152d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610380565b815160209283012081519190920120600191909155600255565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561157e5750600090506003611656565b8460ff16601b1415801561159657508460ff16601c14155b156115a75750600090506004611656565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156115fb573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661164f57600060019250925050611656565b9150600090505b94509492505050565b60006020828403121561167157600080fd5b5035919050565b60008060006040848603121561168d57600080fd5b833567ffffffffffffffff808211156116a557600080fd5b818601915086601f8301126116b957600080fd5b8135818111156116c857600080fd5b8760208260051b85010111156116dd57600080fd5b6020928301989097509590910135949350505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461171757600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600067ffffffffffffffff808411156117665761176661171c565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156117ac576117ac61171c565b816040528093508581528686860111156117c557600080fd5b858560208301376000602087830101525050509392505050565b600080600083850360808112156117f557600080fd5b6117fe856116f3565b935060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201121561183057600080fd5b50602084019150606084013567ffffffffffffffff81111561185157600080fd5b8401601f8101861361186257600080fd5b6118718682356020840161174b565b9150509250925092565b60005b8381101561189657818101518382015260200161187e565b838111156118a5576000848401525b50505050565b600081518084526118c381602086016020860161187b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006111ec60208301846118ab565b6000806040838503121561191b57600080fd5b611924836116f3565b946020939093013593505050565b60006020828403121561194457600080fd5b6111ec826116f3565b60006020828403121561195f57600080fd5b813567ffffffffffffffff81111561197657600080fd5b8201601f8101841361198757600080fd5b6113288482356020840161174b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611a6a578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805173ffffffffffffffffffffffffffffffffffffffff16845287810151888501528601516060878501819052611a56818601836118ab565b9689019694505050908601906001016119ec565b509098975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061132860408301846118ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115611ae957611ae9611aa7565b500190565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000611b2360608301846118ab565b95945050505050565b60008451611b3e81846020890161187b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611b7a816001850160208a0161187b565b60019201918201528351611b9581600284016020880161187b565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061132860408301846118ab565b60008251611bfc81846020870161187b565b9190910192915050565b600060208284031215611c1857600080fd5b5051919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611c5057611c50611aa7565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611c9557611c95611c57565b500490565b600082821015611cac57611cac611aa7565b500390565b600082611cc057611cc0611c57565b50069056fea264697066735822122097f93936c2ea57902b86c424cff790fa55dccd81b007b045479cd5575c81c5d564736f6c634300080f0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063916db22f1161008c578063db083d7111610066578063db083d7114610252578063de2dd22114610279578063eccec5a814610299578063f62d1888146102d557600080fd5b8063916db22f146101e4578063b4245d731461020b578063c4fc453d1461022b57600080fd5b806350b414e6116100c857806350b414e61461016857806350eedbc21461017e57806354fd4d50146101915780635fda04c7146101a657600080fd5b806314b47241146100ef578063187e3cd11461014057806325b27a3d14610155575b600080fd5b6101167f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61015361014e36600461165f565b6102e8565b005b610153610163366004611678565b61039c565b610170603c81565b604051908152602001610137565b61015361018c3660046117df565b6106bf565b610199610d48565b60405161013791906118f5565b6101d46101b4366004611908565b603660209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610137565b6101707f6f7074696d6973742e63616e2d696e766974650000000000000000000000000081565b61017061021936600461165f565b60356020526000908152604090205481565b6101707f6529fd129351e725d7bcbc468b0b0b4675477e56b58514e69ab7e66ddfd20fce81565b6101167f000000000000000000000000000000000000000000000000000000000000000081565b610170610287366004611932565b60376020526000908152604090205481565b6101996040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6101536102e336600461194d565b610deb565b60008181526035602052604090205415610389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4f7074696d697374496e76697465723a20636f6d6d69746d656e7420616c726560448201527f616479206d61646500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000908152603560205260409020429055565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610461576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4f7074696d697374496e76697465723a206f6e6c7920696e766974652067726160448201527f6e7465722063616e206772616e7420696e7669746573000000000000000000006064820152608401610380565b8160008167ffffffffffffffff81111561047d5761047d61171c565b6040519080825280602002602001820160405280156104ca57816020015b6040805160608082018352600080835260208301529181019190915281526020019060019003908161049b5790505b50905060005b828110156106135783603760008888858181106104ef576104ef611996565b90506020020160208101906105049190611932565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550604051806060016040528087878481811061055f5761055f611996565b90506020020160208101906105749190611932565b73ffffffffffffffffffffffffffffffffffffffff1681526020017f6f7074696d6973742e63616e2d696e766974650000000000000000000000000081526020016040518060400160405280600481526020017f747275650000000000000000000000000000000000000000000000000000000081525081525082828151811061060057610600611996565b60209081029190910101526001016104d0565b506040517f5eb5ea1000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690635eb5ea10906106869084906004016119c5565b600060405180830381600087803b1580156106a057600080fd5b505af11580156106b4573d6000803e3d6000fd5b505050505050505050565b60006035600085846040516020016106d8929190611a78565b604051602081830303815290604052805190602001208152602001908152602001600020549050600081116107b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f4f7074696d697374496e76697465723a20636c61696d657220616e642073696760448201527f6e61747572652068617665206e6f74206265656e20636f6d6d6974746564207960648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a401610380565b426107c1603c83611ad6565b111561084f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4f7074696d697374496e76697465723a206d696e696d756d20636f6d6d69746d60448201527f656e7420706572696f6420686173206e6f7420656c61707365642079657400006064820152608401610380565b60006108d27f6529fd129351e725d7bcbc468b0b0b4675477e56b58514e69ab7e66ddfd20fce6108826020870187611932565b6040805160208181019490945273ffffffffffffffffffffffffffffffffffffffff9092169082015290860135606082015260800160405160208183030381529060405280519060200120610fb5565b90506108eb6108e46020860186611932565b8285611024565b610977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4f7074696d697374496e76697465723a20696e76616c6964207369676e61747560448201527f72650000000000000000000000000000000000000000000000000000000000006064820152608401610380565b603660006109886020870187611932565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040908101600090812087840135825290925290205460ff1615610a4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4f7074696d697374496e76697465723a206e6f6e63652068617320616c72656160448201527f6479206265656e207573656400000000000000000000000000000000000000006064820152608401610380565b600160366000610a626020880188611932565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040908101600090812088840180358352935290812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016931515939093179092556037908290610ad69088611932565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411610b9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f7074696d697374496e76697465723a2069737375657220686173206e6f206960448201527f6e766974657300000000000000000000000000000000000000000000000000006064820152608401610380565b60376000610baf6020870187611932565b73ffffffffffffffffffffffffffffffffffffffff9081168252602080830193909352604090910160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190557f0000000000000000000000000000000000000000000000000000000000000000169063702b9dee9087907f6f7074696d6973742e63616e2d6d696e742d66726f6d2d696e7669746500000090610c5990890189611932565b6040805173ffffffffffffffffffffffffffffffffffffffff9092166020830152016040516020818303038152906040526040518463ffffffff1660e01b8152600401610ca893929190611aee565b600060405180830381600087803b158015610cc257600080fd5b505af1158015610cd6573d6000803e3d6000fd5b50505073ffffffffffffffffffffffffffffffffffffffff86169050610cff6020860186611932565b73ffffffffffffffffffffffffffffffffffffffff167f745d3c5bc92ab40b418069bf8f8e2030807effceb88bbaa07ee01574f16be47560405160405180910390a35050505050565b6060610d737f00000000000000000000000000000000000000000000000000000000000000006111f3565b610d9c7f00000000000000000000000000000000000000000000000000000000000000006111f3565b610dc57f00000000000000000000000000000000000000000000000000000000000000006111f3565b604051602001610dd793929190611b2c565b604051602081830303815290604052905090565b600054610100900460ff1615808015610e0b5750600054600160ff909116105b80610e255750303b158015610e25575060005460ff166001145b610eb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610380565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610f0f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610f4e826040518060400160405280600581526020017f312e302e30000000000000000000000000000000000000000000000000000000815250611330565b8015610fb157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600061101e610fc26113d1565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b92915050565b60008060006110338585611451565b9092509050600081600481111561104c5761104c611ba2565b14801561108457508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b15611094576001925050506111ec565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b88886040516024016110c9929190611bd1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516111529190611bea565b600060405180830381855afa9150503d806000811461118d576040519150601f19603f3d011682016040523d82523d6000602084013e611192565b606091505b50915091508180156111a5575080516020145b80156111e5575080517f1626ba7e00000000000000000000000000000000000000000000000000000000906111e39083016020908101908401611c06565b145b9450505050505b9392505050565b60608160000361123657505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611260578061124a81611c1f565b91506112599050600a83611c86565b915061123a565b60008167ffffffffffffffff81111561127b5761127b61171c565b6040519080825280601f01601f1916602001820160405280156112a5576020820181803683370190505b5090505b8415611328576112ba600183611c9a565b91506112c7600a86611cb1565b6112d2906030611ad6565b60f81b8183815181106112e7576112e7611996565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611321600a86611c86565b94506112a9565b949350505050565b600054610100900460ff166113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610380565b610fb18282611496565b600061144c7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61140060015490565b6002546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b905090565b60008082516041036114875760208301516040840151606085015160001a61147b87828585611547565b9450945050505061148f565b506000905060025b9250929050565b600054610100900460ff1661152d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610380565b815160209283012081519190920120600191909155600255565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561157e5750600090506003611656565b8460ff16601b1415801561159657508460ff16601c14155b156115a75750600090506004611656565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156115fb573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661164f57600060019250925050611656565b9150600090505b94509492505050565b60006020828403121561167157600080fd5b5035919050565b60008060006040848603121561168d57600080fd5b833567ffffffffffffffff808211156116a557600080fd5b818601915086601f8301126116b957600080fd5b8135818111156116c857600080fd5b8760208260051b85010111156116dd57600080fd5b6020928301989097509590910135949350505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461171757600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600067ffffffffffffffff808411156117665761176661171c565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156117ac576117ac61171c565b816040528093508581528686860111156117c557600080fd5b858560208301376000602087830101525050509392505050565b600080600083850360808112156117f557600080fd5b6117fe856116f3565b935060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201121561183057600080fd5b50602084019150606084013567ffffffffffffffff81111561185157600080fd5b8401601f8101861361186257600080fd5b6118718682356020840161174b565b9150509250925092565b60005b8381101561189657818101518382015260200161187e565b838111156118a5576000848401525b50505050565b600081518084526118c381602086016020860161187b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006111ec60208301846118ab565b6000806040838503121561191b57600080fd5b611924836116f3565b946020939093013593505050565b60006020828403121561194457600080fd5b6111ec826116f3565b60006020828403121561195f57600080fd5b813567ffffffffffffffff81111561197657600080fd5b8201601f8101841361198757600080fd5b6113288482356020840161174b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611a6a578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805173ffffffffffffffffffffffffffffffffffffffff16845287810151888501528601516060878501819052611a56818601836118ab565b9689019694505050908601906001016119ec565b509098975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061132860408301846118ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115611ae957611ae9611aa7565b500190565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000611b2360608301846118ab565b95945050505050565b60008451611b3e81846020890161187b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611b7a816001850160208a0161187b565b60019201918201528351611b9581600284016020880161187b565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061132860408301846118ab565b60008251611bfc81846020870161187b565b9190910192915050565b600060208284031215611c1857600080fd5b5051919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611c5057611c50611aa7565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611c9557611c95611c57565b500490565b600082821015611cac57611cac611aa7565b500390565b600082611cc057611cc0611c57565b50069056fea264697066735822122097f93936c2ea57902b86c424cff790fa55dccd81b007b045479cd5575c81c5d564736f6c634300080f0033", - "devdoc": { - "custom:upgradeable": "@title OptimistInviter", - "events": { - "InviteClaimed(address,address)": { - "params": { - "claimer": "Address that claimed the invite.", - "issuer": "Address that issued the signature." - } - } - }, - "kind": "dev", - "methods": { - "claimInvite(address,(address,bytes32),bytes)": { - "params": { - "_claimableInvite": "ClaimableInvite struct containing the issuer and nonce.", - "_claimer": "Address that will be granted the invite.", - "_signature": "Signature signed over the claimable invite." - } - }, - "commitInvite(bytes32)": { - "params": { - "_commitment": "A hash of the claimer and signature concatenated. keccak256(abi.encode(_claimer, _signature))" - } - }, - "constructor": { - "custom:semver": "1.0.0", - "params": { - "_attestationStation": "Address of the AttestationStation contract.", - "_inviteGranter": "Address of the invite granter." - } - }, - "initialize(string)": { - "params": { - "_name": "Contract name." - } - }, - "setInviteCounts(address[],uint256)": { - "params": { - "_accounts": "An array of accounts to update the invite counts of.", - "_inviteCount": "Number of invites to set to." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "version": 1 - }, - "userdoc": { - "events": { - "InviteClaimed(address,address)": { - "notice": "Emitted when an invite is claimed." - } - }, - "kind": "user", - "methods": { - "ATTESTATION_STATION()": { - "notice": "Address of the AttestationStation contract." - }, - "CAN_INVITE_ATTESTATION_KEY()": { - "notice": "Attestation key for that signals that an account was allowed to issue invites" - }, - "CLAIMABLE_INVITE_TYPEHASH()": { - "notice": "EIP712 typehash for the ClaimableInvite type." - }, - "EIP712_VERSION()": { - "notice": "Version used for the EIP712 domain separator. This version is separated from the contract semver because the EIP712 domain separator is used to sign messages, and changing the domain separator invalidates all existing signatures. We should only bump this version if we make a major change to the signature scheme." - }, - "INVITE_GRANTER()": { - "notice": "Granter who can set accounts' invite counts." - }, - "MIN_COMMITMENT_PERIOD()": { - "notice": "Minimum age of a commitment (in seconds) before it can be revealed using claimInvite. Currently set to 60 seconds. Prevents an attacker from front-running a commitment by taking the signature in the claimInvite call and quickly committing and claiming it before the the claimer's transaction succeeds. With this, frontrunning a commitment requires that an attacker be able to prevent the honest claimer's claimInvite transaction from being included for this long." - }, - "claimInvite(address,(address,bytes32),bytes)": { - "notice": "Allows anyone to reveal a commitment and claim an invite. The hash, keccak256(abi.encode(_claimer, _signature)), should have been already committed using commitInvite. Before issuing the \"optimist.can-mint-from-invite\" attestation, this function checks that 1) the hash corresponding to the _claimer and the _signature was committed 2) MIN_COMMITMENT_PERIOD has passed since the commitment was made. 3) the _signature is signed correctly by the issuer 4) the _signature hasn't already been used to claim an invite before 5) the _signature issuer has not used up all of their invites This function doesn't require that the _claimer is calling this function." - }, - "commitInvite(bytes32)": { - "notice": "Allows anyone (but likely the claimer) to commit a received signature along with the address to claim to. Before calling this function, the claimer should have received a signature from the issuer off-chain. The claimer then calls this function with the hash of the claimer's address and the received signature. This is necessary to prevent front-running when the invitee is claiming the invite. Without a commit and reveal scheme, anyone who is watching the mempool can take the signature being submitted and front run the transaction to claim the invite to their own address. The same commitment can only be made once, and the function reverts if the commitment has already been made. This prevents griefing where a malicious party can prevent the original claimer from being able to claimInvite." - }, - "commitmentTimestamps(bytes32)": { - "notice": "Maps from hashes to the timestamp when they were committed." - }, - "initialize(string)": { - "notice": "Initializes this contract, setting the EIP712 context. Only update the EIP712_VERSION when there is a change to the signature scheme. After the EIP712 version is changed, any signatures issued off-chain but not claimed yet will no longer be accepted by the claimInvite function. Please make sure to notify the issuers that they must re-issue their invite signatures." - }, - "inviteCounts(address)": { - "notice": "Maps from addresses to number of invites they have." - }, - "setInviteCounts(address[],uint256)": { - "notice": "Allows invite granter to set the number of invites an address has." - }, - "usedNonces(address,bytes32)": { - "notice": "Maps from addresses to nonces to whether or not they have been used." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "OptimistInviter issues \"optimist.can-invite\" and \"optimist.can-mint-from-invite\" attestations. Accounts that have invites can issue signatures that allow other accounts to claim an invite. The invitee uses a claim and reveal flow to claim the invite to an address of their choosing. Parties involved: 1) INVITE_GRANTER: trusted account that can allow accounts to issue invites 2) issuer: account that is allowed to issue invites 3) claimer: account that receives the invites Flow: 1) INVITE_GRANTER calls _setInviteCount to allow an issuer to issue a certain number of invites, and also creates a \"optimist.can-invite\" attestation for the issuer 2) Off-chain, the issuer signs (EIP-712) a ClaimableInvite to produce a signature 3) Off-chain, invite issuer sends the plaintext ClaimableInvite and the signature to the recipient 4) claimer chooses an address they want to receive the invite on 5) claimer commits the hash of the address they want to receive the invite on and the received signature keccak256(abi.encode(addressToReceiveTo, receivedSignature)) using the commitInvite function 6) claimer waits for the MIN_COMMITMENT_PERIOD to pass. 7) claimer reveals the plaintext ClaimableInvite and the signature using the claimInvite function, receiving the \"optimist.can-mint-from-invite\" attestation", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 1166, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 1169, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 3321, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "_HASHED_NAME", - "offset": 0, - "slot": "1", - "type": "t_bytes32" - }, - { - "astId": 3323, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "_HASHED_VERSION", - "offset": 0, - "slot": "2", - "type": "t_bytes32" - }, - { - "astId": 3461, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "__gap", - "offset": 0, - "slot": "3", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 5494, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "commitmentTimestamps", - "offset": 0, - "slot": "53", - "type": "t_mapping(t_bytes32,t_uint256)" - }, - { - "astId": 5501, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "usedNonces", - "offset": 0, - "slot": "54", - "type": "t_mapping(t_address,t_mapping(t_bytes32,t_bool))" - }, - { - "astId": 5506, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "inviteCounts", - "offset": 0, - "slot": "55", - "type": "t_mapping(t_address,t_uint256)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "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_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_bytes32,t_bool))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(bytes32 => bool))", - "numberOfBytes": "32", - "value": "t_mapping(t_bytes32,t_bool)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_mapping(t_bytes32,t_bool)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_mapping(t_bytes32,t_uint256)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "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-bedrock/deployments/optimism-goerli/OptimistInviterProxy.json b/packages/contracts-bedrock/deployments/optimism-goerli/OptimistInviterProxy.json deleted file mode 100644 index cd73860c7799..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/OptimistInviterProxy.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "address": "0x073031A1E1b8F5458Ed41Ce56331F5fd7e1de929", - "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": "0x49b84cb498f5e256c0bcc616fd1c1d262c5cd01b67339f8eb9c9cd4ff26f5b90", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 1, - "gasUsed": "534190", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080010000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x711ca7182301afd7a0be34c2ba3e6d693b22723d4609944a77dca738911aa336", - "transactionHash": "0x49b84cb498f5e256c0bcc616fd1c1d262c5cd01b67339f8eb9c9cd4ff26f5b90", - "logs": [ - { - "transactionIndex": 1, - "blockNumber": 7690255, - "transactionHash": "0x49b84cb498f5e256c0bcc616fd1c1d262c5cd01b67339f8eb9c9cd4ff26f5b90", - "address": "0x073031A1E1b8F5458Ed41Ce56331F5fd7e1de929", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58", - "logIndex": 0, - "blockHash": "0x711ca7182301afd7a0be34c2ba3e6d693b22723d4609944a77dca738911aa336" - } - ], - "blockNumber": 7690255, - "cumulativeGasUsed": "581103", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "d7155764d4bdb814f10e1bb45296292b", - "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) public virtual 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 public\\n payable\\n virtual\\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) public virtual 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() public virtual proxyCallIfNotAdmin returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function implementation() public virtual 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\":\"0x64d67f1936d97c87a2e42317eb162744ad5cefdc9bc8b1138ee4afe2886eb885\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161094138038061094183398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206109218339815191525490565b600080516020610921833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610830806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea26469706673582212200496188e743eb5556ea8662e234845601d39477882517acc1cf9061fcc51284c64736f6c634300080f0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea26469706673582212200496188e743eb5556ea8662e234845601d39477882517acc1cf9061fcc51284c64736f6c634300080f0033", - "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-bedrock/deployments/optimism-goerli/OptimistProxy.json b/packages/contracts-bedrock/deployments/optimism-goerli/OptimistProxy.json deleted file mode 100644 index 099c6d45c790..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/OptimistProxy.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "address": "0x2335022c740d17c2837f9C884Bfe4fFdbf0A95D5", - "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": "0x890d2852461118f7847e5d9d1d5cf04714dc2aba8e279a5a06fd32e6415c3d1c", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "534190", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x82b49133e92eddff1adca6bd3d902c0a54ccc681bf917ed8116c03133b1c32e7", - "transactionHash": "0x890d2852461118f7847e5d9d1d5cf04714dc2aba8e279a5a06fd32e6415c3d1c", - "logs": [ - { - "transactionIndex": 0, - "blockNumber": 3451420, - "transactionHash": "0x890d2852461118f7847e5d9d1d5cf04714dc2aba8e279a5a06fd32e6415c3d1c", - "address": "0x2335022c740d17c2837f9C884Bfe4fFdbf0A95D5", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58", - "logIndex": 0, - "blockHash": "0x82b49133e92eddff1adca6bd3d902c0a54ccc681bf917ed8116c03133b1c32e7" - } - ], - "blockNumber": 3451420, - "cumulativeGasUsed": "534190", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "45837d34ff24b9cb2ae34232b60ea874", - "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-bedrock/deployments/optimism-goerli/SchemaRegistry.json b/packages/contracts-bedrock/deployments/optimism-goerli/SchemaRegistry.json deleted file mode 100644 index 24af8ddc658c..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/SchemaRegistry.json +++ /dev/null @@ -1,293 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AlreadyExists", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "registerer", - "type": "address" - } - ], - "name": "Registered", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - } - ], - "name": "getSchema", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "internalType": "contract ISchemaResolver", - "name": "resolver", - "type": "address" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - }, - { - "internalType": "string", - "name": "schema", - "type": "string" - } - ], - "internalType": "struct SchemaRecord", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "schema", - "type": "string" - }, - { - "internalType": "contract ISchemaResolver", - "name": "resolver", - "type": "address" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - } - ], - "name": "register", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "address": "0x2545fa928d5d278cA75Fd47306e4a89096ff6403", - "args": [], - "bytecode": "0x60e060405234801561001057600080fd5b5060016080819052600060a081905260c081905280610b166100478239600060fe0152600060d50152600060ac0152610b166000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806360d7a27814610064578063a2ea7c6e14610085575b600080fd5b61004e6100a5565b60405161005b9190610604565b60405180910390f35b61007761007236600461061e565b610148565b60405190815260200161005b565b6100986100933660046106d0565b6102f1565b60405161005b91906106e9565b60606100d07f0000000000000000000000000000000000000000000000000000000000000000610419565b6100f97f0000000000000000000000000000000000000000000000000000000000000000610419565b6101227f0000000000000000000000000000000000000000000000000000000000000000610419565b6040516020016101349392919061073a565b604051602081830303815290604052905090565b60008060405180608001604052806000801b81526020018573ffffffffffffffffffffffffffffffffffffffff168152602001841515815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525092935091506101ca905082610556565b60008181526020819052604090205490915015610213576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80825260008181526020818152604091829020845181559084015160018201805493860151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090941673ffffffffffffffffffffffffffffffffffffffff9092169190911792909217909155606083015183919060028201906102af9082610881565b50506040513381528291507f7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c9060200160405180910390a29695505050505050565b604080516080810182526000808252602082018190529181019190915260608082015260008281526020818152604091829020825160808101845281548152600182015473ffffffffffffffffffffffffffffffffffffffff8116938201939093527401000000000000000000000000000000000000000090920460ff16151592820192909252600282018054919291606084019190610390906107df565b80601f01602080910402602001604051908101604052809291908181526020018280546103bc906107df565b80156104095780601f106103de57610100808354040283529160200191610409565b820191906000526020600020905b8154815290600101906020018083116103ec57829003601f168201915b5050505050815250509050919050565b60608160000361045c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104865780610470816109ca565b915061047f9050600a83610a31565b9150610460565b60008167ffffffffffffffff8111156104a1576104a16107b0565b6040519080825280601f01601f1916602001820160405280156104cb576020820181803683370190505b5090505b841561054e576104e0600183610a45565b91506104ed600a86610a5e565b6104f8906030610a72565b60f81b81838151811061050d5761050d610a85565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610547600a86610a31565b94506104cf565b949350505050565b600081606001518260200151836040015160405160200161057993929190610ab4565b604051602081830303815290604052805190602001209050919050565b60005b838110156105b1578181015183820152602001610599565b50506000910152565b600081518084526105d2816020860160208601610596565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061061760208301846105ba565b9392505050565b6000806000806060858703121561063457600080fd5b843567ffffffffffffffff8082111561064c57600080fd5b818701915087601f83011261066057600080fd5b81358181111561066f57600080fd5b88602082850101111561068157600080fd5b6020928301965094505085013573ffffffffffffffffffffffffffffffffffffffff811681146106b057600080fd5b9150604085013580151581146106c557600080fd5b939692955090935050565b6000602082840312156106e257600080fd5b5035919050565b602081528151602082015273ffffffffffffffffffffffffffffffffffffffff60208301511660408201526040820151151560608201526000606083015160808084015261054e60a08401826105ba565b6000845161074c818460208901610596565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610788816001850160208a01610596565b600192019182015283516107a3816002840160208801610596565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c908216806107f357607f821691505b60208210810361082c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561087c57600081815260208120601f850160051c810160208610156108595750805b601f850160051c820191505b8181101561087857828155600101610865565b5050505b505050565b815167ffffffffffffffff81111561089b5761089b6107b0565b6108af816108a984546107df565b84610832565b602080601f83116001811461090257600084156108cc5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610878565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561094f57888601518255948401946001909101908401610930565b508582101561098b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109fb576109fb61099b565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a4057610a40610a02565b500490565b81810381811115610a5857610a5861099b565b92915050565b600082610a6d57610a6d610a02565b500690565b80820180821115610a5857610a5861099b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008451610ac6818460208901610596565b60609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190930190815290151560f81b60148201526015019291505056fea164736f6c6343000813000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806360d7a27814610064578063a2ea7c6e14610085575b600080fd5b61004e6100a5565b60405161005b9190610604565b60405180910390f35b61007761007236600461061e565b610148565b60405190815260200161005b565b6100986100933660046106d0565b6102f1565b60405161005b91906106e9565b60606100d07f0000000000000000000000000000000000000000000000000000000000000000610419565b6100f97f0000000000000000000000000000000000000000000000000000000000000000610419565b6101227f0000000000000000000000000000000000000000000000000000000000000000610419565b6040516020016101349392919061073a565b604051602081830303815290604052905090565b60008060405180608001604052806000801b81526020018573ffffffffffffffffffffffffffffffffffffffff168152602001841515815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525092935091506101ca905082610556565b60008181526020819052604090205490915015610213576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80825260008181526020818152604091829020845181559084015160018201805493860151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090941673ffffffffffffffffffffffffffffffffffffffff9092169190911792909217909155606083015183919060028201906102af9082610881565b50506040513381528291507f7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c9060200160405180910390a29695505050505050565b604080516080810182526000808252602082018190529181019190915260608082015260008281526020818152604091829020825160808101845281548152600182015473ffffffffffffffffffffffffffffffffffffffff8116938201939093527401000000000000000000000000000000000000000090920460ff16151592820192909252600282018054919291606084019190610390906107df565b80601f01602080910402602001604051908101604052809291908181526020018280546103bc906107df565b80156104095780601f106103de57610100808354040283529160200191610409565b820191906000526020600020905b8154815290600101906020018083116103ec57829003601f168201915b5050505050815250509050919050565b60608160000361045c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104865780610470816109ca565b915061047f9050600a83610a31565b9150610460565b60008167ffffffffffffffff8111156104a1576104a16107b0565b6040519080825280601f01601f1916602001820160405280156104cb576020820181803683370190505b5090505b841561054e576104e0600183610a45565b91506104ed600a86610a5e565b6104f8906030610a72565b60f81b81838151811061050d5761050d610a85565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610547600a86610a31565b94506104cf565b949350505050565b600081606001518260200151836040015160405160200161057993929190610ab4565b604051602081830303815290604052805190602001209050919050565b60005b838110156105b1578181015183820152602001610599565b50506000910152565b600081518084526105d2816020860160208601610596565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061061760208301846105ba565b9392505050565b6000806000806060858703121561063457600080fd5b843567ffffffffffffffff8082111561064c57600080fd5b818701915087601f83011261066057600080fd5b81358181111561066f57600080fd5b88602082850101111561068157600080fd5b6020928301965094505085013573ffffffffffffffffffffffffffffffffffffffff811681146106b057600080fd5b9150604085013580151581146106c557600080fd5b939692955090935050565b6000602082840312156106e257600080fd5b5035919050565b602081528151602082015273ffffffffffffffffffffffffffffffffffffffff60208301511660408201526040820151151560608201526000606083015160808084015261054e60a08401826105ba565b6000845161074c818460208901610596565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610788816001850160208a01610596565b600192019182015283516107a3816002840160208801610596565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c908216806107f357607f821691505b60208210810361082c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561087c57600081815260208120601f850160051c810160208610156108595750805b601f850160051c820191505b8181101561087857828155600101610865565b5050505b505050565b815167ffffffffffffffff81111561089b5761089b6107b0565b6108af816108a984546107df565b84610832565b602080601f83116001811461090257600084156108cc5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610878565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561094f57888601518255948401946001909101908401610930565b508582101561098b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109fb576109fb61099b565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a4057610a40610a02565b500490565b81810381811115610a5857610a5861099b565b92915050565b600082610a6d57610a6d610a02565b500690565b80820180821115610a5857610a5861099b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008451610ac6818460208901610596565b60609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190930190815290151560f81b60148201526015019291505056fea164736f6c6343000813000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "constructor": { - "details": "Creates a new SchemaRegistry instance." - }, - "getSchema(bytes32)": { - "details": "Returns an existing schema by UID", - "params": { - "uid": "The UID of the schema to retrieve." - }, - "returns": { - "_0": "The schema data members." - } - }, - "register(string,address,bool)": { - "details": "Submits and reserves a new schema", - "params": { - "resolver": "An optional schema resolver.", - "revocable": "Whether the schema allows revocations explicitly.", - "schema": "The schema data schema." - }, - "returns": { - "_0": "The UID of the new schema." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "events": { - "Registered(bytes32,address)": { - "details": "Emitted when a new schema has been registered", - "params": { - "registerer": "The address of the account used to register the schema.", - "uid": "The schema UID." - } - } - }, - "title": "SchemaRegistry" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"AlreadyExists\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"registerer\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Registered\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getSchema\",\"outputs\":[{\"internalType\":\"struct SchemaRecord\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"contract ISchemaResolver\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"schema\",\"type\":\"string\"}]}]},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"schema\",\"type\":\"string\"},{\"internalType\":\"contract ISchemaResolver\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"register\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Creates a new SchemaRegistry instance.\"},\"getSchema(bytes32)\":{\"details\":\"Returns an existing schema by UID\",\"params\":{\"uid\":\"The UID of the schema to retrieve.\"},\"returns\":{\"_0\":\"The schema data members.\"}},\"register(string,address,bool)\":{\"details\":\"Submits and reserves a new schema\",\"params\":{\"resolver\":\"An optional schema resolver.\",\"revocable\":\"Whether the schema allows revocations explicitly.\",\"schema\":\"The schema data schema.\"},\"returns\":{\"_0\":\"The UID of the new schema.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=node_modules/clones-with-immutable-args/src/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":clones-with-immutable-args/=node_modules/clones-with-immutable-args/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"contracts/EAS/SchemaRegistry.sol\":\"SchemaRegistry\"},\"libraries\":{}},\"sources\":{\"contracts/EAS/Common.sol\":{\"keccak256\":\"0x922fda236f56fa813171ac1ae04d70d58763142ed084e36d29b369160f99acef\",\"urls\":[\"bzz-raw://82c6eb5ce50a0cfa28ad70fcd33fcd7f7704d538666127dc7aca32960423851b\",\"dweb:/ipfs/QmVQXmi9d7R4iks3rKNQKsq9HeuHZwpCg68jFbYGTw3VUs\"],\"license\":\"MIT\"},\"contracts/EAS/ISchemaRegistry.sol\":{\"keccak256\":\"0x456637ee808bb949d3941cd8b11581a7e7e0a92f304dbbf06fba320f27f57664\",\"urls\":[\"bzz-raw://372bc7f2fc72460daa5273200ac0d6b81427a23a65c8f5152a0f0fe2a47567d7\",\"dweb:/ipfs/QmSDDuVvp5nXaNDPzZbDMH1YE2nN4nrK8hEDctWds4wRah\"],\"license\":\"MIT\"},\"contracts/EAS/SchemaRegistry.sol\":{\"keccak256\":\"0x0cba1207d8986681585b65863a7cefd5cfc23e9e414d02baef027fca5cc8113d\",\"urls\":[\"bzz-raw://a5f62f15f3e977d1416af1cc4742e312d6f7c75a5ab533180695e02eb603d172\",\"dweb:/ipfs/QmPsyWTzKet3v4bfM7H8Eyz2uRRafz25Jxeqg9c6rKUDPH\"],\"license\":\"MIT\"},\"contracts/EAS/resolver/ISchemaResolver.sol\":{\"keccak256\":\"0x222f41e52e73c3edf2adcddd65c1c6911287b701b07413959a2f720778136135\",\"urls\":[\"bzz-raw://5b3fc66b38c358c3aa704aa3c22bfe7d48063f18529dbc6b61666d0609ffd658\",\"dweb:/ipfs/QmcHBVQzH4mTV1afqQrYw83kgknNETQ1brgWryBwN6u3mf\"],\"license\":\"MIT\"},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0xc455c84bb1f17e994dea0451fd363f81f83965bfa86e81ac6c8b3a327b9a0ff0\",\"urls\":[\"bzz-raw://fab499f3c0d7df8eb763b50621848d5d2147fb9c42a8eb9b65a11093090bb482\",\"dweb:/ipfs/QmUKsG4ztwtUZFjuRYAxgUFTgH5YxWSGF1BFFaB7vdM2K3\"],\"license\":\"MIT\"},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 1, - "receipt": { - "transactionHash": "0xfcee65e070a73f09d30aeae275abb7ff11f0e6d7a950c6032b0fb7e0950a382c", - "transactionIndex": "0x1", - "blockHash": "0x9c59cce84fd9fdd418fa3b99cc22fc52b775eed30b3671ab644dbec7630ce162", - "blockNumber": "0xbaabdb", - "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", - "to": null, - "cumulativeGasUsed": "0xad18a", - "gasUsed": "0xa1a55", - "contractAddress": "0x2545fa928d5d278cA75Fd47306e4a89096ff6403", - "logs": [], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "type": "0x2", - "effectiveGasPrice": "0xb2d05e32" - }, - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 27112, - "contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry", - "label": "_registry", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_bytes32,t_struct(SchemaRecord)27057_storage)" - }, - { - "astId": 27118, - "contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)49_storage" - } - ], - "types": { - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(ISchemaResolver)27536": { - "encoding": "inplace", - "label": "contract ISchemaResolver", - "numberOfBytes": "20" - }, - "t_mapping(t_bytes32,t_struct(SchemaRecord)27057_storage)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => struct SchemaRecord)", - "numberOfBytes": "32", - "value": "t_struct(SchemaRecord)27057_storage" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_struct(SchemaRecord)27057_storage": { - "encoding": "inplace", - "label": "struct SchemaRecord", - "numberOfBytes": "96", - "members": [ - { - "astId": 27049, - "contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry", - "label": "uid", - "offset": 0, - "slot": "0", - "type": "t_bytes32" - }, - { - "astId": 27052, - "contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry", - "label": "resolver", - "offset": 0, - "slot": "1", - "type": "t_contract(ISchemaResolver)27536" - }, - { - "astId": 27054, - "contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry", - "label": "revocable", - "offset": 20, - "slot": "1", - "type": "t_bool" - }, - { - "astId": 27056, - "contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry", - "label": "schema", - "offset": 0, - "slot": "2", - "type": "t_string_storage" - } - ] - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - }, - "transactionHash": "0xfcee65e070a73f09d30aeae275abb7ff11f0e6d7a950c6032b0fb7e0950a382c", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "The global attestation schemas for the Ethereum Attestation Service protocol." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/SequencerFeeVault.json b/packages/contracts-bedrock/deployments/optimism-goerli/SequencerFeeVault.json deleted file mode 100644 index 51b16c18c3fc..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/SequencerFeeVault.json +++ /dev/null @@ -1,209 +0,0 @@ -{ - "address": "0x9eE472aB07Aa92bAe20a9d3E2d29beD3248b9075", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "inputs": [], - "name": "MIN_WITHDRAWAL_AMOUNT", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RECIPIENT", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1FeeWallet", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalProcessed", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0xe48c7bbac5aae994f898f87b9bf8e0bb466d84d8bd454f81990dcfbe9838caac", - "receipt": { - "to": null, - "from": "0xf80267194936da1E98dB10bcE06F3147D580a62e", - "contractAddress": "0x9eE472aB07Aa92bAe20a9d3E2d29beD3248b9075", - "transactionIndex": 2, - "gasUsed": "506060", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x52f53f362a23142d90f2abdffb2addca84a67c854a4fc67274d671f3265432d2", - "transactionHash": "0xe48c7bbac5aae994f898f87b9bf8e0bb466d84d8bd454f81990dcfbe9838caac", - "logs": [], - "blockNumber": 8579691, - "cumulativeGasUsed": "987372", - "status": 1, - "byzantium": true - }, - "args": [ - "0xBc1233d0C3e6B5d53Ab455cF65A6623F6dCd7e4f" - ], - "numDeployments": 1, - "solcInputHash": "2d538e296d12ca6101a896ac2e894043", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MIN_WITHDRAWAL_AMOUNT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RECIPIENT\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1FeeWallet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalProcessed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"custom:proxied\":\"@custom:predeploy 0x4200000000000000000000000000000000000011\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:semver\":\"1.1.0\",\"params\":{\"_recipient\":\"Address that will receive the accumulated fees.\"}},\"l1FeeWallet()\":{\"custom:legacy\":\"@notice Legacy getter for the recipient address.\",\"returns\":{\"_0\":\"The recipient address.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"SequencerFeeVault\",\"version\":1},\"userdoc\":{\"events\":{\"Withdrawal(uint256,address,address)\":{\"notice\":\"Emits each time that a withdrawal occurs.\"}},\"kind\":\"user\",\"methods\":{\"MIN_WITHDRAWAL_AMOUNT()\":{\"notice\":\"Minimum balance before a withdrawal can be triggered.\"},\"RECIPIENT()\":{\"notice\":\"Wallet that will receive the fees on L1.\"},\"totalProcessed()\":{\"notice\":\"Total amount of wei processed by the contract.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"},\"withdraw()\":{\"notice\":\"Triggers a withdrawal of funds to the L1 fee wallet.\"}},\"notice\":\"The SequencerFeeVault is the contract that holds any fees paid to the Sequencer during transaction processing and block production.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2/SequencerFeeVault.sol\":\"SequencerFeeVault\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"]},\"sources\":{\"contracts/L1/ResourceMetering.sol\":{\"keccak256\":\"0xbd7b9532a70d8c842bfce0ea971be50d02fbbf0227c9ad55c71ac68d438010f4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4969f478dd54e89392cda2ea0c5edcf1be55a5dee43a0e410527b6e3bcb85c88\",\"dweb:/ipfs/QmU2crAojw8DRDsz7PAPrereazjFsKh9wtfTpTDVh6NLfW\"]},\"contracts/L2/L2StandardBridge.sol\":{\"keccak256\":\"0xd77e04c57f33cd32c32f326cd06e213d8a27a9fd372cfc4269953a49243c8c41\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f59627bf4c08c85886e819b29b8565b48fa7e9c230732fedfbb0b9c9a0ee04c5\",\"dweb:/ipfs/Qmao1VbQ57h6gdCZTYfipa8LB1wBwAthop5tPd9TgDXES2\"]},\"contracts/L2/SequencerFeeVault.sol\":{\"keccak256\":\"0xf4b01c9026a2208866ab0099f0ebd3df6f8a8c7f995fef99688243558c30e212\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f6ec0c7f5fa9b75d4686cf18224bdb43b344420c37585eda565c1ff74a1bd71\",\"dweb:/ipfs/QmX3dDrAkZ6ahf9F4Md1PN7LUBRyAV61rL17on6KAV15Fm\"]},\"contracts/libraries/Arithmetic.sol\":{\"keccak256\":\"0xc8858039f87e48e6f18c1af8bc0b03e57cfef564acddfd06e4d91e3db7ac5ed6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2fc79af1e844aa6dc1c68067bfe1d359df8d4e9a3e8881afb3bcfcbf68071714\",\"dweb:/ipfs/QmcNC4k8zmvwj4kZizSenTiWbx2DJQPbwqXXLF4iMbkRVD\"]},\"contracts/libraries/Burn.sol\":{\"keccak256\":\"0x54233b226ba6919dc46d438bc790108d8f855001002a1b9c3c37aed7a83e5f3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4051a4baca357a9191a6c9e3aa1593a17b69dd7915966e23e4cb269e9c1d9ed4\",\"dweb:/ipfs/QmadKjGKvxm53abVHQdsxrXBc8e9jXywu6vvhkAgjsx59J\"]},\"contracts/libraries/Constants.sol\":{\"keccak256\":\"0x8c7be28a175eb732995a7f704560163c30261f9f70d377f865c5060882509f5d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f72aba26553b10ca88708e05461691b36b0d2ec7a87f718022fe119ca9c70852\",\"dweb:/ipfs/QmQtDEB1F3D8RsgG63KSJ9t7ZyFLaXc2Av81vKD9y2TMn7\"]},\"contracts/libraries/Encoding.sol\":{\"keccak256\":\"0x170cd0821cec37976a6391da20f1dcdcb1ea9ffada96ccd3c57ff2e357589418\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f18156216c1f9457c2e032a812ad70f2babbc5b89997554ff014d64c483fb2ff\",\"dweb:/ipfs/Qmc5rjMaBFn3jV7XqDrEvRbmatQvJxeVJYA5B5rdcKPkcJ\"]},\"contracts/libraries/Hashing.sol\":{\"keccak256\":\"0x5d4988987899306d2785b3de068194a39f8e829a7864762a07a0016db5189f5e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6746ed0d26d603568818cc52a29d0209effd69f7e55bd0017a6b91bd6cf319fe\",\"dweb:/ipfs/QmPebCmCELMBRtDDxt5ziEPfRXUh6tfm2qJdwz3iyrDdWN\"]},\"contracts/libraries/Predeploys.sol\":{\"keccak256\":\"0xfc30fb239b5f00284f4b8f578a62f0882597e939335c91ea9bc4aab3070ddc43\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fa132267b3a9d98568b4e02cbb68fe2d2c0ca630826242c1b2293a8fa35bd302\",\"dweb:/ipfs/QmdYvcGbaykP6wyBu5T2obXrWK56xGnfWqbYeeWpTChq3w\"]},\"contracts/libraries/SafeCall.sol\":{\"keccak256\":\"0x6e815b62528d452a4f63040d75ff7a08db8ba8096050a53355fc49abaebdf245\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e27e542a11165c82cbb6961f4d8c2a58527fba1ab915afeeded50e96ce929777\",\"dweb:/ipfs/QmRPXdmUAbL1WHZBvENKWkFuHb9bQyrbiJWwDvzEQBLVi8\"]},\"contracts/libraries/Types.sol\":{\"keccak256\":\"0x4fe8ec920798661a828430bd30dc2715eeb40534ec01c0a7bf41cb4ab422e134\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://74c8471869900bd459358cd990bda1c8d234c06b788804c7049cf465ae1e299f\",\"dweb:/ipfs/QmakcfP6NmbVUQsKqH7rEyJsbiqckigLahw9g74oencEJ7\"]},\"contracts/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x5aa9d21c5b41c9786f23153f819d561ae809a1d55c7b0d423dfeafdfbacedc78\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://921c44e6a0982b9a4011900fda1bda2c06b7a85894967de98b407a83fe9f90c0\",\"dweb:/ipfs/QmSsHLKDUQ82kpKdqB6VntVGKuPDb4W9VdotsubuqWBzio\"]},\"contracts/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x3c99b1e768cc4c1e064ccc137b1b4d5961bf4edf071be84cc216c5b20f1c00da\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e36b2a6325c2f804d769271575669b62ab2da2df3c81921ac7487399fe02af07\",\"dweb:/ipfs/QmTCmcEKwvD8Xvjyev268Bkz27FC7TJpUbw1nADcsThnUr\"]},\"contracts/universal/FeeVault.sol\":{\"keccak256\":\"0x73eb2c835495ec308c69783db55c6cc315ed2a55ee6811ccda4e7dbbde04b2c8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b5e46201184138d60e339c98276e3b265717a12795270a1d0ef03157e452e9a0\",\"dweb:/ipfs/QmWGLhTcPuF9ZZfrjGj4QGCzEuDwiyRAMpnQvxd2oLFX75\"]},\"contracts/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x2fea0ee05071c9c6b06a34a8e805801e247e861359b376a8918106e1d6f77ebe\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://198c91bda2edf864ddad1f8ab6168155d13d6ba5487418e5531ff040ff250686\",\"dweb:/ipfs/QmQzxfHY4P7zdVFRh2DTdGt1KeMHaGKNRf3KPZ1mRTYEGB\"]},\"contracts/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x302094342a45ebdf7f46f4fb48821960d2a4134f66fd7f458f73fc4ddf34d219\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8b0e2b496e966ca6037e1c9be1d44417c0180fda2a27f68114e93b899defb783\",\"dweb:/ipfs/QmXP76ivMLxYxscC7B9E9qtW3u6HJ2MNaRVeo3x24VEAQH\"]},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9baf7797439c0ae6512f4639dfc6a1934dbd4e4d7cbb8e63e99264ff47682c9e\",\"dweb:/ipfs/QmawAuhppPyeoZH3rC1uh87xDELa9Lyfw5pYsBqE8myE1m\"]},\"contracts/universal/StandardBridge.sol\":{\"keccak256\":\"0xaa45044774fa70ed322983c3c0138b21d26d75f4b7e8f5324d53c3eef91adec4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c65c95d0cb71f2e32f5ffdea92151a9a46bbd538ba110389a134963fd16a33e9\",\"dweb:/ipfs/QmaPNZokt4j5SCXaWwVtw6qxu5GXWFa3SWBgaSWPPA9KUG\"]},\"node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"]},\"node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"]},\"node_modules/@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b2717fd2bdac99daa960a6de500754ea1b932093c946388c381da48658234b95\",\"dweb:/ipfs/QmP6QVMn6UeA3ByahyJbYQr5M6coHKBKsf3ySZSfbyA8R7\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x032807210d1d7d218963d7355d62e021a84bf1b3339f4f50be2f63b53cccaf29\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://11756f42121f6541a35a8339ea899ee7514cfaa2e6d740625fcc844419296aa6\",\"dweb:/ipfs/QmekMuk6BY4DAjzeXr4MSbKdgoqqsZnA8JPtuyWc6CwXHf\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"]},\"node_modules/@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"]},\"node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"]},\"node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"]}},\"version\":1}", - "bytecode": "0x61012060405234801561001157600080fd5b5060405161092a38038061092a8339810160408190526100309161005d565b678ac7230489e800006080526001600160a01b031660a052600160c081905260e05260006101005261008d565b60006020828403121561006f57600080fd5b81516001600160a01b038116811461008657600080fd5b9392505050565b60805160a05160c05160e0516101005161083e6100ec6000396000610411015260006103e8015260006103bf0152600081816087015281816101730152818161029501526103570152600081816101420152610199015261083e6000f3fe6080604052600436106100695760003560e01c806384411d651161004357806384411d651461010c578063d3e5792b14610130578063d4ff92181461016457600080fd5b80630d9019e1146100755780633ccfd60b146100d357806354fd4d50146100ea57600080fd5b3661007057005b600080fd5b34801561008157600080fd5b506100a97f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100df57600080fd5b506100e8610197565b005b3480156100f657600080fd5b506100ff6103b8565b6040516100ca9190610612565b34801561011857600080fd5b5061012260005481565b6040519081526020016100ca565b34801561013c57600080fd5b506101227f000000000000000000000000000000000000000000000000000000000000000081565b34801561017057600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006100a9565b7f0000000000000000000000000000000000000000000000000000000000000000471015610271576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a40160405180910390fd5b600047905080600080828254610287919061065b565b9091555050604080518281527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020820152338183015290517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a1604080516020810182526000815290517fe11013dd0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109163e11013dd918491610383917f0000000000000000000000000000000000000000000000000000000000000000916188b891600401610673565b6000604051808303818588803b15801561039c57600080fd5b505af11580156103b0573d6000803e3d6000fd5b505050505050565b60606103e37f000000000000000000000000000000000000000000000000000000000000000061045b565b61040c7f000000000000000000000000000000000000000000000000000000000000000061045b565b6104357f000000000000000000000000000000000000000000000000000000000000000061045b565b604051602001610447939291906106b7565b604051602081830303815290604052905090565b60608160000361049e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104c857806104b28161072d565b91506104c19050600a83610794565b91506104a2565b60008167ffffffffffffffff8111156104e3576104e36107a8565b6040519080825280601f01601f19166020018201604052801561050d576020820181803683370190505b5090505b8415610590576105226001836107d7565b915061052f600a866107ee565b61053a90603061065b565b60f81b81838151811061054f5761054f610802565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610589600a86610794565b9450610511565b949350505050565b60005b838110156105b357818101518382015260200161059b565b838111156105c2576000848401525b50505050565b600081518084526105e0816020860160208601610598565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061062560208301846105c8565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561066e5761066e61062c565b500190565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff831660208201526060604082015260006106ae60608301846105c8565b95945050505050565b600084516106c9818460208901610598565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610705816001850160208a01610598565b60019201918201528351610720816002840160208801610598565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361075e5761075e61062c565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826107a3576107a3610765565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107e9576107e961062c565b500390565b6000826107fd576107fd610765565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", - "deployedBytecode": "0x6080604052600436106100695760003560e01c806384411d651161004357806384411d651461010c578063d3e5792b14610130578063d4ff92181461016457600080fd5b80630d9019e1146100755780633ccfd60b146100d357806354fd4d50146100ea57600080fd5b3661007057005b600080fd5b34801561008157600080fd5b506100a97f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100df57600080fd5b506100e8610197565b005b3480156100f657600080fd5b506100ff6103b8565b6040516100ca9190610612565b34801561011857600080fd5b5061012260005481565b6040519081526020016100ca565b34801561013c57600080fd5b506101227f000000000000000000000000000000000000000000000000000000000000000081565b34801561017057600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006100a9565b7f0000000000000000000000000000000000000000000000000000000000000000471015610271576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a40160405180910390fd5b600047905080600080828254610287919061065b565b9091555050604080518281527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020820152338183015290517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a1604080516020810182526000815290517fe11013dd0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109163e11013dd918491610383917f0000000000000000000000000000000000000000000000000000000000000000916188b891600401610673565b6000604051808303818588803b15801561039c57600080fd5b505af11580156103b0573d6000803e3d6000fd5b505050505050565b60606103e37f000000000000000000000000000000000000000000000000000000000000000061045b565b61040c7f000000000000000000000000000000000000000000000000000000000000000061045b565b6104357f000000000000000000000000000000000000000000000000000000000000000061045b565b604051602001610447939291906106b7565b604051602081830303815290604052905090565b60608160000361049e57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104c857806104b28161072d565b91506104c19050600a83610794565b91506104a2565b60008167ffffffffffffffff8111156104e3576104e36107a8565b6040519080825280601f01601f19166020018201604052801561050d576020820181803683370190505b5090505b8415610590576105226001836107d7565b915061052f600a866107ee565b61053a90603061065b565b60f81b81838151811061054f5761054f610802565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610589600a86610794565b9450610511565b949350505050565b60005b838110156105b357818101518382015260200161059b565b838111156105c2576000848401525b50505050565b600081518084526105e0816020860160208601610598565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061062560208301846105c8565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561066e5761066e61062c565b500190565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff831660208201526060604082015260006106ae60608301846105c8565b95945050505050565b600084516106c9818460208901610598565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610705816001850160208a01610598565b60019201918201528351610720816002840160208801610598565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361075e5761075e61062c565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826107a3576107a3610765565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107e9576107e961062c565b500390565b6000826107fd576107fd610765565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "constructor": { - "params": { - "_recipient": "Address that will receive the accumulated fees." - } - }, - "l1FeeWallet()": { - "returns": { - "_0": "The recipient address." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "title": "SequencerFeeVault" - }, - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MIN_WITHDRAWAL_AMOUNT()": { - "notice": "Minimum balance before a withdrawal can be triggered." - }, - "RECIPIENT()": { - "notice": "Wallet that will receive the fees on L1." - }, - "totalProcessed()": { - "notice": "Total amount of wei processed by the contract." - }, - "version()": { - "notice": "Returns the full semver contract version." - }, - "withdraw()": { - "notice": "Triggers a withdrawal of funds to the L1 fee wallet." - } - }, - "events": { - "Withdrawal(uint256,address,address)": { - "notice": "Emits each time that a withdrawal occurs." - } - }, - "notice": "The SequencerFeeVault is the contract that holds any fees paid to the Sequencer during transaction processing and block production." - }, - "storageLayout": { - "storage": [ - { - "astId": 46671, - "contract": "contracts/L2/SequencerFeeVault.sol:SequencerFeeVault", - "label": "totalProcessed", - "offset": 0, - "slot": "0", - "type": "t_uint256" - } - ], - "types": { - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/solcInputs/2d538e296d12ca6101a896ac2e894043.json b/packages/contracts-bedrock/deployments/optimism-goerli/solcInputs/2d538e296d12ca6101a896ac2e894043.json deleted file mode 100644 index 89915af4d92c..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/solcInputs/2d538e296d12ca6101a896ac2e894043.json +++ /dev/null @@ -1,552 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/L1/L1CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismPortal } from \"./OptimismPortal.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1CrossDomainMessenger\n * @notice The L1CrossDomainMessenger is a message passing interface between L1 and L2 responsible\n * for sending and receiving data on the L1 side. Users are encouraged to use this\n * interface instead of interacting with lower-level contracts directly.\n */\ncontract L1CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @notice Address of the OptimismPortal.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @custom:semver 1.4.0\n *\n * @param _portal Address of the OptimismPortal contract on this network.\n */\n constructor(OptimismPortal _portal)\n Semver(1, 4, 0)\n CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER)\n {\n PORTAL = _portal;\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n PORTAL.depositTransaction{ value: _value }(_to, _value, _gasLimit, false, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return msg.sender == address(PORTAL) && PORTAL.l2Sender() == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(PORTAL);\n }\n}\n" - }, - "contracts/L1/L1ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { L2ERC721Bridge } from \"../L2/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 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, 1, 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 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), \"L1ERC721Bridge: 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(OTHER_BRIDGE, message, _minGasLimit);\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L1/L1StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1StandardBridge\n * @notice The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L1, it will be escrowed within this\n * contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was\n * stored within this contract. After Bedrock, ETH is instead stored inside the\n * OptimismPortal contract.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L1StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a deposit of ETH from L1 into L2 is initiated.\n *\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of ETH deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ETHDepositInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal of ETH from L2 to L1 is finalized.\n *\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of ETH withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 withdrawal is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _messenger Address of the L1CrossDomainMessenger.\n */\n constructor(address payable _messenger)\n Semver(1, 1, 0)\n StandardBridge(_messenger, payable(Predeploys.L2_STANDARD_BRIDGE))\n {}\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n */\n receive() external payable override onlyEOA {\n _initiateETHDeposit(msg.sender, msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into the sender's account on L2.\n *\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETH(uint32 _minGasLimit, bytes calldata _extraData) external payable onlyEOA {\n _initiateETHDeposit(msg.sender, msg.sender, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into a target account on L2.\n * Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will\n * be locked in the L2StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n *\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable {\n _initiateETHDeposit(msg.sender, _to, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into the sender's account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20(\n address _l1Token,\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual onlyEOA {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into a target account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20To(\n address _l1Token,\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ETH from L2.\n *\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of ETH to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeETHWithdrawal(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable {\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ERC20 tokens from L2.\n *\n * @param _l1Token Address of the token on L1.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of the ERC20 to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeERC20Withdrawal(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external {\n finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L2 bridge contract.\n *\n * @return Address of the corresponding L2 bridge contract.\n */\n function l2TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @notice Internal function for initiating an ETH deposit.\n *\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateETHDeposit(\n address _from,\n address _to,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n _initiateBridgeETH(_from, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Internal function for initiating an ERC20 deposit.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateERC20Deposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n _initiateBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Emits the legacy ETHDepositInitiated event followed by the ETHBridgeInitiated event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ETHDepositInitiated(_from, _to, _amount, _extraData);\n super._emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ETHWithdrawalFinalized event followed by the ETHBridgeFinalized\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ETHWithdrawalFinalized(_from, _to, _amount, _extraData);\n super._emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ERC20DepositInitiated event followed by the ERC20BridgeInitiated\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ERC20DepositInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ERC20WithdrawalFinalized event followed by the ERC20BridgeFinalized\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ERC20WithdrawalFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/L1/L2OutputOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\n/**\n * @custom:proxied\n * @title L2OutputOracle\n * @notice The L2OutputOracle contains an array of L2 state outputs, where each output is a\n * commitment to the state of the L2 chain. Other contracts like the OptimismPortal use\n * these outputs to verify information about the state of L2.\n */\ncontract L2OutputOracle is Initializable, Semver {\n /**\n * @notice The interval in L2 blocks at which checkpoints must be submitted. Although this is\n * immutable, it can safely be modified by upgrading the implementation contract.\n */\n uint256 public immutable SUBMISSION_INTERVAL;\n\n /**\n * @notice The time between L2 blocks in seconds. Once set, this value MUST NOT be modified.\n */\n uint256 public immutable L2_BLOCK_TIME;\n\n /**\n * @notice The address of the challenger. Can be updated via upgrade.\n */\n address public immutable CHALLENGER;\n\n /**\n * @notice The address of the proposer. Can be updated via upgrade.\n */\n address public immutable PROPOSER;\n\n /**\n * @notice Minimum time (in seconds) that must elapse before a withdrawal can be finalized.\n */\n uint256 public immutable FINALIZATION_PERIOD_SECONDS;\n\n /**\n * @notice The number of the first L2 block recorded in this contract.\n */\n uint256 public startingBlockNumber;\n\n /**\n * @notice The timestamp of the first L2 block recorded in this contract.\n */\n uint256 public startingTimestamp;\n\n /**\n * @notice Array of L2 output proposals.\n */\n Types.OutputProposal[] internal l2Outputs;\n\n /**\n * @notice Emitted when an output is proposed.\n *\n * @param outputRoot The output root.\n * @param l2OutputIndex The index of the output in the l2Outputs array.\n * @param l2BlockNumber The L2 block number of the output root.\n * @param l1Timestamp The L1 timestamp when proposed.\n */\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n /**\n * @notice Emitted when outputs are deleted.\n *\n * @param prevNextOutputIndex Next L2 output index before the deletion.\n * @param newNextOutputIndex Next L2 output index after the deletion.\n */\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n /**\n * @custom:semver 1.3.0\n *\n * @param _submissionInterval Interval in blocks at which checkpoints must be submitted.\n * @param _l2BlockTime The time per L2 block, in seconds.\n * @param _startingBlockNumber The number of the first L2 block.\n * @param _startingTimestamp The timestamp of the first L2 block.\n * @param _proposer The address of the proposer.\n * @param _challenger The address of the challenger.\n */\n constructor(\n uint256 _submissionInterval,\n uint256 _l2BlockTime,\n uint256 _startingBlockNumber,\n uint256 _startingTimestamp,\n address _proposer,\n address _challenger,\n uint256 _finalizationPeriodSeconds\n ) Semver(1, 3, 0) {\n require(_l2BlockTime > 0, \"L2OutputOracle: L2 block time must be greater than 0\");\n require(\n _submissionInterval > 0,\n \"L2OutputOracle: submission interval must be greater than 0\"\n );\n\n SUBMISSION_INTERVAL = _submissionInterval;\n L2_BLOCK_TIME = _l2BlockTime;\n PROPOSER = _proposer;\n CHALLENGER = _challenger;\n FINALIZATION_PERIOD_SECONDS = _finalizationPeriodSeconds;\n\n initialize(_startingBlockNumber, _startingTimestamp);\n }\n\n /**\n * @notice Initializer.\n *\n * @param _startingBlockNumber Block number for the first recoded L2 block.\n * @param _startingTimestamp Timestamp for the first recoded L2 block.\n */\n function initialize(uint256 _startingBlockNumber, uint256 _startingTimestamp)\n public\n initializer\n {\n require(\n _startingTimestamp <= block.timestamp,\n \"L2OutputOracle: starting L2 timestamp must be less than current time\"\n );\n\n startingTimestamp = _startingTimestamp;\n startingBlockNumber = _startingBlockNumber;\n }\n\n /**\n * @notice Deletes all output proposals after and including the proposal that corresponds to\n * the given output index. Only the challenger address can delete outputs.\n *\n * @param _l2OutputIndex Index of the first L2 output to be deleted. All outputs after this\n * output will also be deleted.\n */\n // solhint-disable-next-line ordering\n function deleteL2Outputs(uint256 _l2OutputIndex) external {\n require(\n msg.sender == CHALLENGER,\n \"L2OutputOracle: only the challenger address can delete outputs\"\n );\n\n // Make sure we're not *increasing* the length of the array.\n require(\n _l2OutputIndex < l2Outputs.length,\n \"L2OutputOracle: cannot delete outputs after the latest output index\"\n );\n\n // Do not allow deleting any outputs that have already been finalized.\n require(\n block.timestamp - l2Outputs[_l2OutputIndex].timestamp < FINALIZATION_PERIOD_SECONDS,\n \"L2OutputOracle: cannot delete outputs that have already been finalized\"\n );\n\n uint256 prevNextL2OutputIndex = nextOutputIndex();\n\n // Use assembly to delete the array elements because Solidity doesn't allow it.\n assembly {\n sstore(l2Outputs.slot, _l2OutputIndex)\n }\n\n emit OutputsDeleted(prevNextL2OutputIndex, _l2OutputIndex);\n }\n\n /**\n * @notice Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp\n * must be equal to the current value returned by `nextTimestamp()` in order to be\n * accepted. This function may only be called by the Proposer.\n *\n * @param _outputRoot The L2 output of the checkpoint block.\n * @param _l2BlockNumber The L2 block number that resulted in _outputRoot.\n * @param _l1BlockHash A block hash which must be included in the current chain.\n * @param _l1BlockNumber The block number with the specified block hash.\n */\n function proposeL2Output(\n bytes32 _outputRoot,\n uint256 _l2BlockNumber,\n bytes32 _l1BlockHash,\n uint256 _l1BlockNumber\n ) external payable {\n require(\n msg.sender == PROPOSER,\n \"L2OutputOracle: only the proposer address can propose new outputs\"\n );\n\n require(\n _l2BlockNumber == nextBlockNumber(),\n \"L2OutputOracle: block number must be equal to next expected block number\"\n );\n\n require(\n computeL2Timestamp(_l2BlockNumber) < block.timestamp,\n \"L2OutputOracle: cannot propose L2 output in the future\"\n );\n\n require(\n _outputRoot != bytes32(0),\n \"L2OutputOracle: L2 output proposal cannot be the zero hash\"\n );\n\n if (_l1BlockHash != bytes32(0)) {\n // This check allows the proposer to propose an output based on a given L1 block,\n // without fear that it will be reorged out.\n // It will also revert if the blockheight provided is more than 256 blocks behind the\n // chain tip (as the hash will return as zero). This does open the door to a griefing\n // attack in which the proposer's submission is censored until the block is no longer\n // retrievable, if the proposer is experiencing this attack it can simply leave out the\n // blockhash value, and delay submission until it is confident that the L1 block is\n // finalized.\n require(\n blockhash(_l1BlockNumber) == _l1BlockHash,\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n }\n\n emit OutputProposed(_outputRoot, nextOutputIndex(), _l2BlockNumber, block.timestamp);\n\n l2Outputs.push(\n Types.OutputProposal({\n outputRoot: _outputRoot,\n timestamp: uint128(block.timestamp),\n l2BlockNumber: uint128(_l2BlockNumber)\n })\n );\n }\n\n /**\n * @notice Returns an output by index. Exists because Solidity's array access will return a\n * tuple instead of a struct.\n *\n * @param _l2OutputIndex Index of the output to return.\n *\n * @return The output at the given index.\n */\n function getL2Output(uint256 _l2OutputIndex)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[_l2OutputIndex];\n }\n\n /**\n * @notice Returns the index of the L2 output that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return Index of the first checkpoint that commits to the given L2 block number.\n */\n function getL2OutputIndexAfter(uint256 _l2BlockNumber) public view returns (uint256) {\n // Make sure an output for this block number has actually been proposed.\n require(\n _l2BlockNumber <= latestBlockNumber(),\n \"L2OutputOracle: cannot get output for a block that has not been proposed\"\n );\n\n // Make sure there's at least one output proposed.\n require(\n l2Outputs.length > 0,\n \"L2OutputOracle: cannot get output as no outputs have been proposed yet\"\n );\n\n // Find the output via binary search, guaranteed to exist.\n uint256 lo = 0;\n uint256 hi = l2Outputs.length;\n while (lo < hi) {\n uint256 mid = (lo + hi) / 2;\n if (l2Outputs[mid].l2BlockNumber < _l2BlockNumber) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n return lo;\n }\n\n /**\n * @notice Returns the L2 output proposal that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return First checkpoint that commits to the given L2 block number.\n */\n function getL2OutputAfter(uint256 _l2BlockNumber)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[getL2OutputIndexAfter(_l2BlockNumber)];\n }\n\n /**\n * @notice Returns the number of outputs that have been proposed. Will revert if no outputs\n * have been proposed yet.\n *\n * @return The number of outputs that have been proposed.\n */\n function latestOutputIndex() external view returns (uint256) {\n return l2Outputs.length - 1;\n }\n\n /**\n * @notice Returns the index of the next output to be proposed.\n *\n * @return The index of the next output to be proposed.\n */\n function nextOutputIndex() public view returns (uint256) {\n return l2Outputs.length;\n }\n\n /**\n * @notice Returns the block number of the latest submitted L2 output proposal. If no proposals\n * been submitted yet then this function will return the starting block number.\n *\n * @return Latest submitted L2 block number.\n */\n function latestBlockNumber() public view returns (uint256) {\n return\n l2Outputs.length == 0\n ? startingBlockNumber\n : l2Outputs[l2Outputs.length - 1].l2BlockNumber;\n }\n\n /**\n * @notice Computes the block number of the next L2 block that needs to be checkpointed.\n *\n * @return Next L2 block number.\n */\n function nextBlockNumber() public view returns (uint256) {\n return latestBlockNumber() + SUBMISSION_INTERVAL;\n }\n\n /**\n * @notice Returns the L2 timestamp corresponding to a given L2 block number.\n *\n * @param _l2BlockNumber The L2 block number of the target block.\n *\n * @return L2 timestamp of the given block.\n */\n function computeL2Timestamp(uint256 _l2BlockNumber) public view returns (uint256) {\n return startingTimestamp + ((_l2BlockNumber - startingBlockNumber) * L2_BLOCK_TIME);\n }\n}\n" - }, - "contracts/L1/OptimismPortal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { L2OutputOracle } from \"./L2OutputOracle.sol\";\nimport { SystemConfig } from \"./SystemConfig.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { SecureMerkleTrie } from \"../libraries/trie/SecureMerkleTrie.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ResourceMetering } from \"./ResourceMetering.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title OptimismPortal\n * @notice The OptimismPortal is a low-level contract responsible for passing messages between L1\n * and L2. Messages sent directly to the OptimismPortal have no form of replayability.\n * Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface.\n */\ncontract OptimismPortal is Initializable, ResourceMetering, Semver {\n /**\n * @notice Represents a proven withdrawal.\n *\n * @custom:field outputRoot Root of the L2 output this was proven against.\n * @custom:field timestamp Timestamp at whcih the withdrawal was proven.\n * @custom:field l2OutputIndex Index of the output this was proven against.\n */\n struct ProvenWithdrawal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2OutputIndex;\n }\n\n /**\n * @notice Version of the deposit event.\n */\n uint256 internal constant DEPOSIT_VERSION = 0;\n\n /**\n * @notice The L2 gas limit set when eth is deposited using the receive() function.\n */\n uint64 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Address of the L2OutputOracle contract.\n */\n L2OutputOracle public immutable L2_ORACLE;\n\n /**\n * @notice Address of the SystemConfig contract.\n */\n SystemConfig public immutable SYSTEM_CONFIG;\n\n /**\n * @notice Address that has the ability to pause and unpause withdrawals.\n */\n address public immutable GUARDIAN;\n\n /**\n * @notice Address of the L2 account which initiated a withdrawal in this transaction. If the\n * of this variable is the default L2 sender address, then we are NOT inside of a call\n * to finalizeWithdrawalTransaction.\n */\n address public l2Sender;\n\n /**\n * @notice A list of withdrawal hashes which have been successfully finalized.\n */\n mapping(bytes32 => bool) public finalizedWithdrawals;\n\n /**\n * @notice A mapping of withdrawal hashes to `ProvenWithdrawal` data.\n */\n mapping(bytes32 => ProvenWithdrawal) public provenWithdrawals;\n\n /**\n * @notice Determines if cross domain messaging is paused. When set to true,\n * withdrawals are paused. This may be removed in the future.\n */\n bool public paused;\n\n /**\n * @notice Emitted when a transaction is deposited from L1 to L2. The parameters of this event\n * are read by the rollup node and used to derive deposit transactions on L2.\n *\n * @param from Address that triggered the deposit transaction.\n * @param to Address that the deposit transaction is directed to.\n * @param version Version of this deposit transaction event.\n * @param opaqueData ABI encoded deposit data to be parsed off-chain.\n */\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is proven.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n */\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is finalized.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n * @param success Whether the withdrawal transaction was successful.\n */\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n\n /**\n * @notice Emitted when the pause is triggered.\n *\n * @param account Address of the account triggering the pause.\n */\n event Paused(address account);\n\n /**\n * @notice Emitted when the pause is lifted.\n *\n * @param account Address of the account triggering the unpause.\n */\n event Unpaused(address account);\n\n /**\n * @notice Reverts when paused.\n */\n modifier whenNotPaused() {\n require(paused == false, \"OptimismPortal: paused\");\n _;\n }\n\n /**\n * @custom:semver 1.6.0\n *\n * @param _l2Oracle Address of the L2OutputOracle contract.\n * @param _guardian Address that can pause deposits and withdrawals.\n * @param _paused Sets the contract's pausability state.\n * @param _config Address of the SystemConfig contract.\n */\n constructor(\n L2OutputOracle _l2Oracle,\n address _guardian,\n bool _paused,\n SystemConfig _config\n ) Semver(1, 6, 0) {\n L2_ORACLE = _l2Oracle;\n GUARDIAN = _guardian;\n SYSTEM_CONFIG = _config;\n initialize(_paused);\n }\n\n /**\n * @notice Initializer.\n */\n function initialize(bool _paused) public initializer {\n l2Sender = Constants.DEFAULT_L2_SENDER;\n paused = _paused;\n __ResourceMetering_init();\n }\n\n /**\n * @notice Pause deposits and withdrawals.\n */\n function pause() external {\n require(msg.sender == GUARDIAN, \"OptimismPortal: only guardian can pause\");\n paused = true;\n emit Paused(msg.sender);\n }\n\n /**\n * @notice Unpause deposits and withdrawals.\n */\n function unpause() external {\n require(msg.sender == GUARDIAN, \"OptimismPortal: only guardian can unpause\");\n paused = false;\n emit Unpaused(msg.sender);\n }\n\n /**\n * @notice Computes the minimum gas limit for a deposit. The minimum gas limit\n * linearly increases based on the size of the calldata. This is to prevent\n * users from creating L2 resource usage without paying for it. This function\n * can be used when interacting with the portal to ensure forwards compatibility.\n *\n */\n function minimumGasLimit(uint64 _byteCount) public pure returns (uint64) {\n return _byteCount * 16 + 21000;\n }\n\n /**\n * @notice Accepts value so that users can send ETH directly to this contract and have the\n * funds be deposited to their address on L2. This is intended as a convenience\n * function for EOAs. Contracts should call the depositTransaction() function directly\n * otherwise any deposited funds will be lost due to address aliasing.\n */\n // solhint-disable-next-line ordering\n receive() external payable {\n depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes(\"\"));\n }\n\n /**\n * @notice Accepts ETH value without triggering a deposit to L2. This function mainly exists\n * for the sake of the migration between the legacy Optimism system and Bedrock.\n */\n function donateETH() external payable {\n // Intentionally empty.\n }\n\n /**\n * @notice Getter for the resource config. Used internally by the ResourceMetering\n * contract. The SystemConfig is the source of truth for the resource config.\n *\n * @return ResourceMetering.ResourceConfig\n */\n function _resourceConfig()\n internal\n view\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return SYSTEM_CONFIG.resourceConfig();\n }\n\n /**\n * @notice Proves a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n * @param _l2OutputIndex L2 output index to prove against.\n * @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root.\n * @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract.\n */\n function proveWithdrawalTransaction(\n Types.WithdrawalTransaction memory _tx,\n uint256 _l2OutputIndex,\n Types.OutputRootProof calldata _outputRootProof,\n bytes[] calldata _withdrawalProof\n ) external whenNotPaused {\n // Prevent users from creating a deposit transaction where this address is the message\n // sender on L2. Because this is checked here, we do not need to check again in\n // `finalizeWithdrawalTransaction`.\n require(\n _tx.target != address(this),\n \"OptimismPortal: you cannot send messages to the portal contract\"\n );\n\n // Get the output root and load onto the stack to prevent multiple mloads. This will\n // revert if there is no output root for the given block number.\n bytes32 outputRoot = L2_ORACLE.getL2Output(_l2OutputIndex).outputRoot;\n\n // Verify that the output root can be generated with the elements in the proof.\n require(\n outputRoot == Hashing.hashOutputRootProof(_outputRootProof),\n \"OptimismPortal: invalid output root proof\"\n );\n\n // Load the ProvenWithdrawal into memory, using the withdrawal hash as a unique identifier.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // We generally want to prevent users from proving the same withdrawal multiple times\n // because each successive proof will update the timestamp. A malicious user can take\n // advantage of this to prevent other users from finalizing their withdrawal. However,\n // since withdrawals are proven before an output root is finalized, we need to allow users\n // to re-prove their withdrawal only in the case that the output root for their specified\n // output index has been updated.\n require(\n provenWithdrawal.timestamp == 0 ||\n L2_ORACLE.getL2Output(provenWithdrawal.l2OutputIndex).outputRoot !=\n provenWithdrawal.outputRoot,\n \"OptimismPortal: withdrawal hash has already been proven\"\n );\n\n // Compute the storage slot of the withdrawal hash in the L2ToL1MessagePasser contract.\n // Refer to the Solidity documentation for more information on how storage layouts are\n // computed for mappings.\n bytes32 storageKey = keccak256(\n abi.encode(\n withdrawalHash,\n uint256(0) // The withdrawals mapping is at the first slot in the layout.\n )\n );\n\n // Verify that the hash of this withdrawal was stored in the L2toL1MessagePasser contract\n // on L2. If this is true, under the assumption that the SecureMerkleTrie does not have\n // bugs, then we know that this withdrawal was actually triggered on L2 and can therefore\n // be relayed on L1.\n require(\n SecureMerkleTrie.verifyInclusionProof(\n abi.encode(storageKey),\n hex\"01\",\n _withdrawalProof,\n _outputRootProof.messagePasserStorageRoot\n ),\n \"OptimismPortal: invalid withdrawal inclusion proof\"\n );\n\n // Designate the withdrawalHash as proven by storing the `outputRoot`, `timestamp`, and\n // `l2BlockNumber` in the `provenWithdrawals` mapping. A `withdrawalHash` can only be\n // proven once unless it is submitted again with a different outputRoot.\n provenWithdrawals[withdrawalHash] = ProvenWithdrawal({\n outputRoot: outputRoot,\n timestamp: uint128(block.timestamp),\n l2OutputIndex: uint128(_l2OutputIndex)\n });\n\n // Emit a `WithdrawalProven` event.\n emit WithdrawalProven(withdrawalHash, _tx.sender, _tx.target);\n }\n\n /**\n * @notice Finalizes a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n */\n function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx)\n external\n whenNotPaused\n {\n // Make sure that the l2Sender has not yet been set. The l2Sender is set to a value other\n // than the default value when a withdrawal transaction is being finalized. This check is\n // a defacto reentrancy guard.\n require(\n l2Sender == Constants.DEFAULT_L2_SENDER,\n \"OptimismPortal: can only trigger one withdrawal per transaction\"\n );\n\n // Grab the proven withdrawal from the `provenWithdrawals` map.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // A withdrawal can only be finalized if it has been proven. We know that a withdrawal has\n // been proven at least once when its timestamp is non-zero. Unproven withdrawals will have\n // a timestamp of zero.\n require(\n provenWithdrawal.timestamp != 0,\n \"OptimismPortal: withdrawal has not been proven yet\"\n );\n\n // As a sanity check, we make sure that the proven withdrawal's timestamp is greater than\n // starting timestamp inside the L2OutputOracle. Not strictly necessary but extra layer of\n // safety against weird bugs in the proving step.\n require(\n provenWithdrawal.timestamp >= L2_ORACLE.startingTimestamp(),\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n\n // A proven withdrawal must wait at least the finalization period before it can be\n // finalized. This waiting period can elapse in parallel with the waiting period for the\n // output the withdrawal was proven against. In effect, this means that the minimum\n // withdrawal time is proposal submission time + finalization period.\n require(\n _isFinalizationPeriodElapsed(provenWithdrawal.timestamp),\n \"OptimismPortal: proven withdrawal finalization period has not elapsed\"\n );\n\n // Grab the OutputProposal from the L2OutputOracle, will revert if the output that\n // corresponds to the given index has not been proposed yet.\n Types.OutputProposal memory proposal = L2_ORACLE.getL2Output(\n provenWithdrawal.l2OutputIndex\n );\n\n // Check that the output root that was used to prove the withdrawal is the same as the\n // current output root for the given output index. An output root may change if it is\n // deleted by the challenger address and then re-proposed.\n require(\n proposal.outputRoot == provenWithdrawal.outputRoot,\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n\n // Check that the output proposal has also been finalized.\n require(\n _isFinalizationPeriodElapsed(proposal.timestamp),\n \"OptimismPortal: output proposal finalization period has not elapsed\"\n );\n\n // Check that this withdrawal has not already been finalized, this is replay protection.\n require(\n finalizedWithdrawals[withdrawalHash] == false,\n \"OptimismPortal: withdrawal has already been finalized\"\n );\n\n // Mark the withdrawal as finalized so it can't be replayed.\n finalizedWithdrawals[withdrawalHash] = true;\n\n // Set the l2Sender so contracts know who triggered this withdrawal on L2.\n l2Sender = _tx.sender;\n\n // Trigger the call to the target contract. We use a custom low level method\n // SafeCall.callWithMinGas to ensure two key properties\n // 1. Target contracts cannot force this call to run out of gas by returning a very large\n // amount of data (and this is OK because we don't care about the returndata here).\n // 2. The amount of gas provided to the execution context of the target is at least the\n // gas limit specified by the user. If there is not enough gas in the current context\n // to accomplish this, `callWithMinGas` will revert.\n bool success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, _tx.value, _tx.data);\n\n // Reset the l2Sender back to the default value.\n l2Sender = Constants.DEFAULT_L2_SENDER;\n\n // All withdrawals are immediately finalized. Replayability can\n // be achieved through contracts built on top of this contract\n emit WithdrawalFinalized(withdrawalHash, success);\n\n // Reverting here is useful for determining the exact gas cost to successfully execute the\n // sub call to the target contract if the minimum gas limit specified by the user would not\n // be sufficient to execute the sub call.\n if (success == false && tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"OptimismPortal: withdrawal failed\");\n }\n }\n\n /**\n * @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in\n * deriving deposit transactions. Note that if a deposit is made by a contract, its\n * address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider\n * using the CrossDomainMessenger contracts for a simpler developer experience.\n *\n * @param _to Target address on L2.\n * @param _value ETH value to send to the recipient.\n * @param _gasLimit Minimum L2 gas limit (can be greater than or equal to this value).\n * @param _isCreation Whether or not the transaction is a contract creation.\n * @param _data Data to trigger the recipient with.\n */\n function depositTransaction(\n address _to,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable metered(_gasLimit) {\n // Just to be safe, make sure that people specify address(0) as the target when doing\n // contract creations.\n if (_isCreation) {\n require(\n _to == address(0),\n \"OptimismPortal: must send to address(0) when creating a contract\"\n );\n }\n\n // Prevent depositing transactions that have too small of a gas limit. Users should pay\n // more for more resource usage.\n require(\n _gasLimit >= minimumGasLimit(uint64(_data.length)),\n \"OptimismPortal: gas limit too small\"\n );\n\n // Prevent the creation of deposit transactions that have too much calldata. This gives an\n // upper limit on the size of unsafe blocks over the p2p network. 120kb is chosen to ensure\n // that the transaction can fit into the p2p network policy of 128kb even though deposit\n // transactions are not gossipped over the p2p network.\n require(_data.length <= 120_000, \"OptimismPortal: data too large\");\n\n // Transform the from-address to its alias if the caller is a contract.\n address from = msg.sender;\n if (msg.sender != tx.origin) {\n from = AddressAliasHelper.applyL1ToL2Alias(msg.sender);\n }\n\n // Compute the opaque data that will be emitted as part of the TransactionDeposited event.\n // We use opaque data so that we can update the TransactionDeposited event in the future\n // without breaking the current interface.\n bytes memory opaqueData = abi.encodePacked(\n msg.value,\n _value,\n _gasLimit,\n _isCreation,\n _data\n );\n\n // Emit a TransactionDeposited event so that the rollup node can derive a deposit\n // transaction for this deposit.\n emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData);\n }\n\n /**\n * @notice Determine if a given output is finalized. Reverts if the call to\n * L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.\n *\n * @param _l2OutputIndex Index of the L2 output to check.\n *\n * @return Whether or not the output is finalized.\n */\n function isOutputFinalized(uint256 _l2OutputIndex) external view returns (bool) {\n return _isFinalizationPeriodElapsed(L2_ORACLE.getL2Output(_l2OutputIndex).timestamp);\n }\n\n /**\n * @notice Determines whether the finalization period has elapsed w/r/t a given timestamp.\n *\n * @param _timestamp Timestamp to check.\n *\n * @return Whether or not the finalization period has elapsed.\n */\n function _isFinalizationPeriodElapsed(uint256 _timestamp) internal view returns (bool) {\n return block.timestamp > _timestamp + L2_ORACLE.FINALIZATION_PERIOD_SECONDS();\n }\n}\n" - }, - "contracts/L1/ResourceMetering.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\n\n/**\n * @custom:upgradeable\n * @title ResourceMetering\n * @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing\n * updates automatically based on current demand.\n */\nabstract contract ResourceMetering is Initializable {\n /**\n * @notice Represents the various parameters that control the way in which resources are\n * metered. Corresponds to the EIP-1559 resource metering system.\n *\n * @custom:field prevBaseFee Base fee from the previous block(s).\n * @custom:field prevBoughtGas Amount of gas bought so far in the current block.\n * @custom:field prevBlockNum Last block number that the base fee was updated.\n */\n struct ResourceParams {\n uint128 prevBaseFee;\n uint64 prevBoughtGas;\n uint64 prevBlockNum;\n }\n\n /**\n * @notice Represents the configuration for the EIP-1559 based curve for the deposit gas\n * market. These values should be set with care as it is possible to set them in\n * a way that breaks the deposit gas market. The target resource limit is defined as\n * maxResourceLimit / elasticityMultiplier. This struct was designed to fit within a\n * single word. There is additional space for additions in the future.\n *\n * @custom:field maxResourceLimit Represents the maximum amount of deposit gas that\n * can be purchased per block.\n * @custom:field elasticityMultiplier Determines the target resource limit along with\n * the resource limit.\n * @custom:field baseFeeMaxChangeDenominator Determines max change on fee per block.\n * @custom:field minimumBaseFee The min deposit base fee, it is clamped to this\n * value.\n * @custom:field systemTxMaxGas The amount of gas supplied to the system\n * transaction. This should be set to the same number\n * that the op-node sets as the gas limit for the\n * system transaction.\n * @custom:field maximumBaseFee The max deposit base fee, it is clamped to this\n * value.\n */\n struct ResourceConfig {\n uint32 maxResourceLimit;\n uint8 elasticityMultiplier;\n uint8 baseFeeMaxChangeDenominator;\n uint32 minimumBaseFee;\n uint32 systemTxMaxGas;\n uint128 maximumBaseFee;\n }\n\n /**\n * @notice EIP-1559 style gas parameters.\n */\n ResourceParams public params;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n */\n uint256[48] private __gap;\n\n /**\n * @notice Meters access to a function based an amount of a requested resource.\n *\n * @param _amount Amount of the resource requested.\n */\n modifier metered(uint64 _amount) {\n // Record initial gas amount so we can refund for it later.\n uint256 initialGas = gasleft();\n\n // Run the underlying function.\n _;\n\n // Run the metering function.\n _metered(_amount, initialGas);\n }\n\n /**\n * @notice An internal function that holds all of the logic for metering a resource.\n *\n * @param _amount Amount of the resource requested.\n * @param _initialGas The amount of gas before any modifier execution.\n */\n function _metered(uint64 _amount, uint256 _initialGas) internal {\n // Update block number and base fee if necessary.\n uint256 blockDiff = block.number - params.prevBlockNum;\n\n ResourceConfig memory config = _resourceConfig();\n int256 targetResourceLimit = int256(uint256(config.maxResourceLimit)) /\n int256(uint256(config.elasticityMultiplier));\n\n if (blockDiff > 0) {\n // Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate\n // at which deposits can be created and therefore limit the potential for deposits to\n // spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes.\n int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - targetResourceLimit;\n int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) /\n (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator)));\n\n // Update base fee by adding the base fee delta and clamp the resulting value between\n // min and max.\n int256 newBaseFee = Arithmetic.clamp({\n _value: int256(uint256(params.prevBaseFee)) + baseFeeDelta,\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n\n // If we skipped more than one block, we also need to account for every empty block.\n // Empty block means there was no demand for deposits in that block, so we should\n // reflect this lack of demand in the fee.\n if (blockDiff > 1) {\n // Update the base fee by repeatedly applying the exponent 1-(1/change_denominator)\n // blockDiff - 1 times. Simulates multiple empty blocks. Clamp the resulting value\n // between min and max.\n newBaseFee = Arithmetic.clamp({\n _value: Arithmetic.cdexp({\n _coefficient: newBaseFee,\n _denominator: int256(uint256(config.baseFeeMaxChangeDenominator)),\n _exponent: int256(blockDiff - 1)\n }),\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n }\n\n // Update new base fee, reset bought gas, and update block number.\n params.prevBaseFee = uint128(uint256(newBaseFee));\n params.prevBoughtGas = 0;\n params.prevBlockNum = uint64(block.number);\n }\n\n // Make sure we can actually buy the resource amount requested by the user.\n params.prevBoughtGas += _amount;\n require(\n int256(uint256(params.prevBoughtGas)) <= int256(uint256(config.maxResourceLimit)),\n \"ResourceMetering: cannot buy more gas than available gas limit\"\n );\n\n // Determine the amount of ETH to be paid.\n uint256 resourceCost = uint256(_amount) * uint256(params.prevBaseFee);\n\n // We currently charge for this ETH amount as an L1 gas burn, so we convert the ETH amount\n // into gas by dividing by the L1 base fee. We assume a minimum base fee of 1 gwei to avoid\n // division by zero for L1s that don't support 1559 or to avoid excessive gas burns during\n // periods of extremely low L1 demand. One-day average gas fee hasn't dipped below 1 gwei\n // during any 1 day period in the last 5 years, so should be fine.\n uint256 gasCost = resourceCost / Math.max(block.basefee, 1 gwei);\n\n // Give the user a refund based on the amount of gas they used to do all of the work up to\n // this point. Since we're at the end of the modifier, this should be pretty accurate. Acts\n // effectively like a dynamic stipend (with a minimum value).\n uint256 usedGas = _initialGas - gasleft();\n if (gasCost > usedGas) {\n Burn.gas(gasCost - usedGas);\n }\n }\n\n /**\n * @notice Virtual function that returns the resource config. Contracts that inherit this\n * contract must implement this function.\n *\n * @return ResourceConfig\n */\n function _resourceConfig() internal virtual returns (ResourceConfig memory);\n\n /**\n * @notice Sets initial resource parameter values. This function must either be called by the\n * initializer function of an upgradeable child contract.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __ResourceMetering_init() internal onlyInitializing {\n params = ResourceParams({\n prevBaseFee: 1 gwei,\n prevBoughtGas: 0,\n prevBlockNum: uint64(block.number)\n });\n }\n}\n" - }, - "contracts/L1/SystemConfig.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { ResourceMetering } from \"./ResourceMetering.sol\";\n\n/**\n * @title SystemConfig\n * @notice The SystemConfig contract is used to manage configuration of an Optimism network. All\n * configuration is stored on L1 and picked up by L2 as part of the derviation of the L2\n * chain.\n */\ncontract SystemConfig is OwnableUpgradeable, Semver {\n /**\n * @notice Enum representing different types of updates.\n *\n * @custom:value BATCHER Represents an update to the batcher hash.\n * @custom:value GAS_CONFIG Represents an update to txn fee config on L2.\n * @custom:value GAS_LIMIT Represents an update to gas limit on L2.\n * @custom:value UNSAFE_BLOCK_SIGNER Represents an update to the signer key for unsafe\n * block distrubution.\n */\n enum UpdateType {\n BATCHER,\n GAS_CONFIG,\n GAS_LIMIT,\n UNSAFE_BLOCK_SIGNER\n }\n\n /**\n * @notice Version identifier, used for upgrades.\n */\n uint256 public constant VERSION = 0;\n\n /**\n * @notice Storage slot that the unsafe block signer is stored at. Storing it at this\n * deterministic storage slot allows for decoupling the storage layout from the way\n * that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value.\n */\n bytes32 public constant UNSAFE_BLOCK_SIGNER_SLOT = keccak256(\"systemconfig.unsafeblocksigner\");\n\n /**\n * @notice Fixed L2 gas overhead. Used as part of the L2 fee calculation.\n */\n uint256 public overhead;\n\n /**\n * @notice Dynamic L2 gas overhead. Used as part of the L2 fee calculation.\n */\n uint256 public scalar;\n\n /**\n * @notice Identifier for the batcher. For version 1 of this configuration, this is represented\n * as an address left-padded with zeros to 32 bytes.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice L2 block gas limit.\n */\n uint64 public gasLimit;\n\n /**\n * @notice The configuration for the deposit fee market. Used by the OptimismPortal\n * to meter the cost of buying L2 gas on L1. Set as internal and wrapped with a getter\n * so that the struct is returned instead of a tuple.\n */\n ResourceMetering.ResourceConfig internal _resourceConfig;\n\n /**\n * @notice Emitted when configuration is updated\n *\n * @param version SystemConfig version.\n * @param updateType Type of update.\n * @param data Encoded update data.\n */\n event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);\n\n /**\n * @custom:semver 1.3.0\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n * @param _unsafeBlockSigner Initial unsafe block signer address.\n * @param _config Initial resource config.\n */\n constructor(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner,\n ResourceMetering.ResourceConfig memory _config\n ) Semver(1, 3, 0) {\n initialize({\n _owner: _owner,\n _overhead: _overhead,\n _scalar: _scalar,\n _batcherHash: _batcherHash,\n _gasLimit: _gasLimit,\n _unsafeBlockSigner: _unsafeBlockSigner,\n _config: _config\n });\n }\n\n /**\n * @notice Initializer. The resource config must be set before the\n * require check.\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n * @param _unsafeBlockSigner Initial unsafe block signer address.\n * @param _config Initial ResourceConfig.\n */\n function initialize(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner,\n ResourceMetering.ResourceConfig memory _config\n ) public initializer {\n __Ownable_init();\n transferOwnership(_owner);\n overhead = _overhead;\n scalar = _scalar;\n batcherHash = _batcherHash;\n gasLimit = _gasLimit;\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n _setResourceConfig(_config);\n require(_gasLimit >= minimumGasLimit(), \"SystemConfig: gas limit too low\");\n }\n\n /**\n * @notice Returns the minimum L2 gas limit that can be safely set for the system to\n * operate. The L2 gas limit must be larger than or equal to the amount of\n * gas that is allocated for deposits per block plus the amount of gas that\n * is allocated for the system transaction.\n * This function is used to determine if changes to parameters are safe.\n *\n * @return uint64\n */\n function minimumGasLimit() public view returns (uint64) {\n return uint64(_resourceConfig.maxResourceLimit) + uint64(_resourceConfig.systemTxMaxGas);\n }\n\n /**\n * @notice High level getter for the unsafe block signer address. Unsafe blocks can be\n * propagated across the p2p network if they are signed by the key corresponding to\n * this address.\n *\n * @return Address of the unsafe block signer.\n */\n // solhint-disable-next-line ordering\n function unsafeBlockSigner() external view returns (address) {\n address addr;\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n addr := sload(slot)\n }\n return addr;\n }\n\n /**\n * @notice Updates the unsafe block signer address.\n *\n * @param _unsafeBlockSigner New unsafe block signer address.\n */\n function setUnsafeBlockSigner(address _unsafeBlockSigner) external onlyOwner {\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n\n bytes memory data = abi.encode(_unsafeBlockSigner);\n emit ConfigUpdate(VERSION, UpdateType.UNSAFE_BLOCK_SIGNER, data);\n }\n\n /**\n * @notice Updates the batcher hash.\n *\n * @param _batcherHash New batcher hash.\n */\n function setBatcherHash(bytes32 _batcherHash) external onlyOwner {\n batcherHash = _batcherHash;\n\n bytes memory data = abi.encode(_batcherHash);\n emit ConfigUpdate(VERSION, UpdateType.BATCHER, data);\n }\n\n /**\n * @notice Updates gas config.\n *\n * @param _overhead New overhead value.\n * @param _scalar New scalar value.\n */\n function setGasConfig(uint256 _overhead, uint256 _scalar) external onlyOwner {\n overhead = _overhead;\n scalar = _scalar;\n\n bytes memory data = abi.encode(_overhead, _scalar);\n emit ConfigUpdate(VERSION, UpdateType.GAS_CONFIG, data);\n }\n\n /**\n * @notice Updates the L2 gas limit.\n *\n * @param _gasLimit New gas limit.\n */\n function setGasLimit(uint64 _gasLimit) external onlyOwner {\n require(_gasLimit >= minimumGasLimit(), \"SystemConfig: gas limit too low\");\n gasLimit = _gasLimit;\n\n bytes memory data = abi.encode(_gasLimit);\n emit ConfigUpdate(VERSION, UpdateType.GAS_LIMIT, data);\n }\n\n /**\n * @notice Low level setter for the unsafe block signer address. This function exists to\n * deduplicate code around storing the unsafeBlockSigner address in storage.\n *\n * @param _unsafeBlockSigner New unsafeBlockSigner value.\n */\n function _setUnsafeBlockSigner(address _unsafeBlockSigner) internal {\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n sstore(slot, _unsafeBlockSigner)\n }\n }\n\n /**\n * @notice A getter for the resource config. Ensures that the struct is\n * returned instead of a tuple.\n *\n * @return ResourceConfig\n */\n function resourceConfig() external view returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig;\n }\n\n /**\n * @notice An external setter for the resource config. In the future, this\n * method may emit an event that the `op-node` picks up for when the\n * resource config is changed.\n *\n * @param _config The new resource config values.\n */\n function setResourceConfig(ResourceMetering.ResourceConfig memory _config) external onlyOwner {\n _setResourceConfig(_config);\n }\n\n /**\n * @notice An internal setter for the resource config. Ensures that the\n * config is sane before storing it by checking for invariants.\n *\n * @param _config The new resource config.\n */\n function _setResourceConfig(ResourceMetering.ResourceConfig memory _config) internal {\n // Min base fee must be less than or equal to max base fee.\n require(\n _config.minimumBaseFee <= _config.maximumBaseFee,\n \"SystemConfig: min base fee must be less than max base\"\n );\n // Base fee change denominator must be greater than 1.\n require(\n _config.baseFeeMaxChangeDenominator > 1,\n \"SystemConfig: denominator must be larger than 1\"\n );\n // Max resource limit plus system tx gas must be less than or equal to the L2 gas limit.\n // The gas limit must be increased before these values can be increased.\n require(\n _config.maxResourceLimit + _config.systemTxMaxGas <= gasLimit,\n \"SystemConfig: gas limit too low\"\n );\n // Elasticity multiplier must be greater than 0.\n require(\n _config.elasticityMultiplier > 0,\n \"SystemConfig: elasticity multiplier cannot be 0\"\n );\n // No precision loss when computing target resource limit.\n require(\n ((_config.maxResourceLimit / _config.elasticityMultiplier) *\n _config.elasticityMultiplier) == _config.maxResourceLimit,\n \"SystemConfig: precision loss with target resource limit\"\n );\n\n _resourceConfig = _config;\n }\n}\n" - }, - "contracts/L2/BaseFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000019\n * @title BaseFeeVault\n * @notice The BaseFeeVault accumulates the base fee that is paid by transactions.\n */\ncontract BaseFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}\n}\n" - }, - "contracts/L2/CrossDomainOwnable.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\n/**\n * @title CrossDomainOwnable\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is only safe to be used if the\n * CrossDomainMessenger system is bypassed and the caller on L1 is calling the\n * OptimismPortal directly.\n */\nabstract contract CrossDomainOwnable is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `msg.sender` is the owner of the contract.\n */\n function _checkOwner() internal view override {\n require(\n owner() == AddressAliasHelper.undoL1ToL2Alias(msg.sender),\n \"CrossDomainOwnable: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/CrossDomainOwnable2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L2CrossDomainMessenger } from \"./L2CrossDomainMessenger.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title CrossDomainOwnable2\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is meant to be used with systems that use\n * the CrossDomainMessenger system. It will not work if the OptimismPortal is used\n * directly.\n */\nabstract contract CrossDomainOwnable2 is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `xDomainMessageSender` is the owner of the contract. This value is set to the caller\n * of the L1CrossDomainMessenger.\n */\n function _checkOwner() internal view override {\n L2CrossDomainMessenger messenger = L2CrossDomainMessenger(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER\n );\n\n require(\n msg.sender == address(messenger),\n \"CrossDomainOwnable2: caller is not the messenger\"\n );\n\n require(\n owner() == messenger.xDomainMessageSender(),\n \"CrossDomainOwnable2: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/CrossDomainOwnable3.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L2CrossDomainMessenger } from \"./L2CrossDomainMessenger.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title CrossDomainOwnable3\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on either L1 or L2. Note that this contract is meant to be used with systems\n * that use the CrossDomainMessenger system. It will not work if the OptimismPortal is\n * used directly.\n */\nabstract contract CrossDomainOwnable3 is Ownable {\n /**\n * @notice If true, the contract uses the cross domain _checkOwner function override. If false\n * it uses the standard Ownable _checkOwner function.\n */\n bool public isLocal = true;\n\n /**\n * @notice Emits when ownership of the contract is transferred. Includes the\n * isLocal field in addition to the standard `Ownable` OwnershipTransferred event.\n */\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner,\n bool isLocal\n );\n\n /**\n * @notice Allows for ownership to be transferred with specifying the locality.\n * @param _owner The new owner of the contract.\n * @param _isLocal Configures the locality of the ownership.\n */\n function transferOwnership(address _owner, bool _isLocal) external onlyOwner {\n require(_owner != address(0), \"CrossDomainOwnable3: new owner is the zero address\");\n\n address oldOwner = owner();\n _transferOwnership(_owner);\n isLocal = _isLocal;\n\n emit OwnershipTransferred(oldOwner, _owner, _isLocal);\n }\n\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `xDomainMessageSender` is the owner of the contract. This value is set to the caller\n * of the L1CrossDomainMessenger.\n */\n function _checkOwner() internal view override {\n if (isLocal) {\n require(owner() == msg.sender, \"CrossDomainOwnable3: caller is not the owner\");\n } else {\n L2CrossDomainMessenger messenger = L2CrossDomainMessenger(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER\n );\n\n require(\n msg.sender == address(messenger),\n \"CrossDomainOwnable3: caller is not the messenger\"\n );\n\n require(\n owner() == messenger.xDomainMessageSender(),\n \"CrossDomainOwnable3: caller is not the owner\"\n );\n }\n }\n}\n" - }, - "contracts/L2/GasPriceOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000000F\n * @title GasPriceOracle\n * @notice This contract maintains the variables responsible for computing the L1 portion of the\n * total fee charged on L2. Before Bedrock, this contract held variables in state that were\n * read during the state transition function to compute the L1 portion of the transaction\n * fee. After Bedrock, this contract now simply proxies the L1Block contract, which has\n * the values used to compute the L1 portion of the fee in its state.\n *\n * The contract exposes an API that is useful for knowing how large the L1 portion of the\n * transaction fee will be. The following events were deprecated with Bedrock:\n * - event OverheadUpdated(uint256 overhead);\n * - event ScalarUpdated(uint256 scalar);\n * - event DecimalsUpdated(uint256 decimals);\n */\ncontract GasPriceOracle is Semver {\n /**\n * @notice Number of decimals used in the scalar.\n */\n uint256 public constant DECIMALS = 6;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Computes the L1 portion of the fee based on the size of the rlp encoded input\n * transaction, the current L1 base fee, and the various dynamic parameters.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for.\n *\n * @return L1 fee that should be paid for the tx\n */\n function getL1Fee(bytes memory _data) external view returns (uint256) {\n uint256 l1GasUsed = getL1GasUsed(_data);\n uint256 l1Fee = l1GasUsed * l1BaseFee();\n uint256 divisor = 10**DECIMALS;\n uint256 unscaled = l1Fee * scalar();\n uint256 scaled = unscaled / divisor;\n return scaled;\n }\n\n /**\n * @notice Retrieves the current gas price (base fee).\n *\n * @return Current L2 gas price (base fee).\n */\n function gasPrice() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current base fee.\n *\n * @return Current L2 base fee.\n */\n function baseFee() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current fee overhead.\n *\n * @return Current fee overhead.\n */\n function overhead() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead();\n }\n\n /**\n * @notice Retrieves the current fee scalar.\n *\n * @return Current fee scalar.\n */\n function scalar() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar();\n }\n\n /**\n * @notice Retrieves the latest known L1 base fee.\n *\n * @return Latest known L1 base fee.\n */\n function l1BaseFee() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee();\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the number of decimals used in the scalar.\n *\n * @return Number of decimals used in the scalar.\n */\n function decimals() public pure returns (uint256) {\n return DECIMALS;\n }\n\n /**\n * @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which\n * represents the per-transaction gas overhead of posting the transaction and state\n * roots to L1. Adds 68 bytes of padding to account for the fact that the input does\n * not have a signature.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for.\n *\n * @return Amount of L1 gas used to publish the transaction.\n */\n function getL1GasUsed(bytes memory _data) public view returns (uint256) {\n uint256 total = 0;\n uint256 length = _data.length;\n for (uint256 i = 0; i < length; i++) {\n if (_data[i] == 0) {\n total += 4;\n } else {\n total += 16;\n }\n }\n uint256 unsigned = total + overhead();\n return unsigned + (68 * 16);\n }\n}\n" - }, - "contracts/L2/L1Block.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000015\n * @title L1Block\n * @notice The L1Block predeploy gives users access to information about the last known L1 block.\n * Values within this contract are updated once per epoch (every L1 block) and can only be\n * set by the \"depositor\" account, a special system address. Depositor account transactions\n * are created by the protocol whenever we move to a new epoch.\n */\ncontract L1Block is Semver {\n /**\n * @notice Address of the special depositor account.\n */\n address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001;\n\n /**\n * @notice The latest L1 block number known by the L2 system.\n */\n uint64 public number;\n\n /**\n * @notice The latest L1 timestamp known by the L2 system.\n */\n uint64 public timestamp;\n\n /**\n * @notice The latest L1 basefee.\n */\n uint256 public basefee;\n\n /**\n * @notice The latest L1 blockhash.\n */\n bytes32 public hash;\n\n /**\n * @notice The number of L2 blocks in the same epoch.\n */\n uint64 public sequenceNumber;\n\n /**\n * @notice The versioned hash to authenticate the batcher by.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice The overhead value applied to the L1 portion of the transaction\n * fee.\n */\n uint256 public l1FeeOverhead;\n\n /**\n * @notice The scalar value applied to the L1 portion of the transaction fee.\n */\n uint256 public l1FeeScalar;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Updates the L1 block values.\n *\n * @param _number L1 blocknumber.\n * @param _timestamp L1 timestamp.\n * @param _basefee L1 basefee.\n * @param _hash L1 blockhash.\n * @param _sequenceNumber Number of L2 blocks since epoch start.\n * @param _batcherHash Versioned hash to authenticate batcher by.\n * @param _l1FeeOverhead L1 fee overhead.\n * @param _l1FeeScalar L1 fee scalar.\n */\n function setL1BlockValues(\n uint64 _number,\n uint64 _timestamp,\n uint256 _basefee,\n bytes32 _hash,\n uint64 _sequenceNumber,\n bytes32 _batcherHash,\n uint256 _l1FeeOverhead,\n uint256 _l1FeeScalar\n ) external {\n require(\n msg.sender == DEPOSITOR_ACCOUNT,\n \"L1Block: only the depositor account can set L1 block values\"\n );\n\n number = _number;\n timestamp = _timestamp;\n basefee = _basefee;\n hash = _hash;\n sequenceNumber = _sequenceNumber;\n batcherHash = _batcherHash;\n l1FeeOverhead = _l1FeeOverhead;\n l1FeeScalar = _l1FeeScalar;\n }\n}\n" - }, - "contracts/L2/L1FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000001A\n * @title L1FeeVault\n * @notice The L1FeeVault accumulates the L1 portion of the transaction fees.\n */\ncontract L1FeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}\n}\n" - }, - "contracts/L2/L2CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { L2ToL1MessagePasser } from \"./L2ToL1MessagePasser.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000007\n * @title L2CrossDomainMessenger\n * @notice The L2CrossDomainMessenger is a high-level interface for message passing between L1 and\n * L2 on the L2 side. Users are generally encouraged to use this contract instead of lower\n * level message passing contracts.\n */\ncontract L2CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @custom:semver 1.4.0\n *\n * @param _l1CrossDomainMessenger Address of the L1CrossDomainMessenger contract.\n */\n constructor(address _l1CrossDomainMessenger)\n Semver(1, 4, 0)\n CrossDomainMessenger(_l1CrossDomainMessenger)\n {\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote messenger. Use otherMessenger going forward.\n *\n * @return Address of the L1CrossDomainMessenger contract.\n */\n function l1CrossDomainMessenger() public view returns (address) {\n return OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)).initiateWithdrawal{\n value: _value\n }(_to, _gasLimit, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(Predeploys.L2_TO_L1_MESSAGE_PASSER);\n }\n}\n" - }, - "contracts/L2/L2ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../universal/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 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.1.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, 1, 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), \"L2ERC721Bridge: 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 \"L2ERC721Bridge: 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(OTHER_BRIDGE, message, _minGasLimit);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L2/L2StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000010\n * @title L2StandardBridge\n * @notice The L2StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L2, it will be escrowed within this\n * contract. If the ERC20 token is native to L1, it will be burnt.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L2StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal from L2 to L1 is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _otherBridge Address of the L1StandardBridge.\n */\n constructor(address payable _otherBridge)\n Semver(1, 1, 0)\n StandardBridge(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER), _otherBridge)\n {}\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n */\n receive() external payable override onlyEOA {\n _initiateWithdrawal(\n Predeploys.LEGACY_ERC20_ETH,\n msg.sender,\n msg.sender,\n msg.value,\n RECEIVE_DEFAULT_GAS_LIMIT,\n bytes(\"\")\n );\n }\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1.\n * This function only works with OptimismMintableERC20 tokens or ether. Use the\n * `bridgeERC20` function to bridge native L2 tokens to L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdraw(\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual onlyEOA {\n _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1 to a target account on L1.\n * Note that if ETH is sent to a contract on L1 and the call fails, then that ETH will\n * be locked in the L1StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n * This function only works with OptimismMintableERC20 tokens or ether. Use the\n * `bridgeERC20To` function to bridge native L2 tokens to L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdrawTo(\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual {\n _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a deposit from L1 to L2. To finalize a deposit of ether, use address(0)\n * and the l1Token and the Legacy ERC20 ether predeploy address as the l2Token.\n *\n * @param _l1Token Address of the L1 token to deposit.\n * @param _l2Token Address of the corresponding L2 token.\n * @param _from Address of the depositor.\n * @param _to Address of the recipient.\n * @param _amount Amount of the tokens being deposited.\n * @param _extraData Extra data attached to the deposit.\n */\n function finalizeDeposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable virtual {\n if (_l1Token == address(0) && _l2Token == Predeploys.LEGACY_ERC20_ETH) {\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n } else {\n finalizeBridgeERC20(_l2Token, _l1Token, _from, _to, _amount, _extraData);\n }\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L1 bridge contract.\n *\n * @return Address of the corresponding L1 bridge contract.\n */\n function l1TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @custom:legacy\n * @notice Internal function to a withdrawal from L2 to L1 to a target account on L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _from Address of the withdrawer.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function _initiateWithdrawal(\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n if (_l2Token == Predeploys.LEGACY_ERC20_ETH) {\n _initiateBridgeETH(_from, _to, _amount, _minGasLimit, _extraData);\n } else {\n address l1Token = OptimismMintableERC20(_l2Token).l1Token();\n _initiateBridgeERC20(_l2Token, l1Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n }\n\n /**\n * @notice Emits the legacy WithdrawalInitiated event followed by the ETHBridgeInitiated event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit WithdrawalInitiated(\n address(0),\n Predeploys.LEGACY_ERC20_ETH,\n _from,\n _to,\n _amount,\n _extraData\n );\n super._emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy DepositFinalized event followed by the ETHBridgeFinalized event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit DepositFinalized(\n address(0),\n Predeploys.LEGACY_ERC20_ETH,\n _from,\n _to,\n _amount,\n _extraData\n );\n super._emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy WithdrawalInitiated event followed by the ERC20BridgeInitiated\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit WithdrawalInitiated(_remoteToken, _localToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy DepositFinalized event followed by the ERC20BridgeFinalized event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit DepositFinalized(_remoteToken, _localToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/L2/L2ToL1MessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000016\n * @title L2ToL1MessagePasser\n * @notice The L2ToL1MessagePasser is a dedicated contract where messages that are being sent from\n * L2 to L1 can be stored. The storage root of this contract is pulled up to the top level\n * of the L2 output to reduce the cost of proving the existence of sent messages.\n */\ncontract L2ToL1MessagePasser is Semver {\n /**\n * @notice The L1 gas limit set when eth is withdrawn using the receive() function.\n */\n uint256 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Current message version identifier.\n */\n uint16 public constant MESSAGE_VERSION = 1;\n\n /**\n * @notice Includes the message hashes for all withdrawals\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @notice A unique value hashed with each withdrawal.\n */\n uint240 internal msgNonce;\n\n /**\n * @notice Emitted any time a withdrawal is initiated.\n *\n * @param nonce Unique value corresponding to each withdrawal.\n * @param sender The L2 account address which initiated the withdrawal.\n * @param target The L1 account address the call will be send to.\n * @param value The ETH value submitted for withdrawal, to be forwarded to the target.\n * @param gasLimit The minimum amount of gas that must be provided when withdrawing.\n * @param data The data to be forwarded to the target on L1.\n * @param withdrawalHash The hash of the withdrawal.\n */\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n /**\n * @notice Emitted when the balance of this contract is burned.\n *\n * @param amount Amount of ETh that was burned.\n */\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Allows users to withdraw ETH by sending directly to this contract.\n */\n receive() external payable {\n initiateWithdrawal(msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @notice Removes all ETH held by this contract from the state. Used to prevent the amount of\n * ETH on L2 inflating when ETH is withdrawn. Currently only way to do this is to\n * create a contract and self-destruct it to itself. Anyone can call this function. Not\n * incentivized since this function is very cheap.\n */\n function burn() external {\n uint256 balance = address(this).balance;\n Burn.eth(balance);\n emit WithdrawerBalanceBurnt(balance);\n }\n\n /**\n * @notice Sends a message from L2 to L1.\n *\n * @param _target Address to call on L1 execution.\n * @param _gasLimit Minimum gas limit for executing the message on L1.\n * @param _data Data to forward to L1 target.\n */\n function initiateWithdrawal(\n address _target,\n uint256 _gasLimit,\n bytes memory _data\n ) public payable {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messageNonce(),\n sender: msg.sender,\n target: _target,\n value: msg.value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n sentMessages[withdrawalHash] = true;\n\n emit MessagePassed(\n messageNonce(),\n msg.sender,\n _target,\n msg.value,\n _gasLimit,\n _data,\n withdrawalHash\n );\n\n unchecked {\n ++msgNonce;\n }\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" - }, - "contracts/L2/SequencerFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000011\n * @title SequencerFeeVault\n * @notice The SequencerFeeVault is the contract that holds any fees paid to the Sequencer during\n * transaction processing and block production.\n */\ncontract SequencerFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the recipient address.\n *\n * @return The recipient address.\n */\n function l1FeeWallet() public view returns (address) {\n return RECIPIENT;\n }\n}\n" - }, - "contracts/deployment/PortalSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/**\n * @title PortalSender\n * @notice The PortalSender is a simple intermediate contract that will transfer the balance of the\n * L1StandardBridge to the OptimismPortal during the Bedrock migration.\n */\ncontract PortalSender {\n /**\n * @notice Address of the OptimismPortal contract.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @param _portal Address of the OptimismPortal contract.\n */\n constructor(OptimismPortal _portal) {\n PORTAL = _portal;\n }\n\n /**\n * @notice Sends balance of this contract to the OptimismPortal.\n */\n function donate() public {\n PORTAL.donateETH{ value: address(this).balance }();\n }\n}\n" - }, - "contracts/deployment/SystemDictator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { PortalSender } from \"./PortalSender.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\n/**\n * @title SystemDictator\n * @notice The SystemDictator is responsible for coordinating the deployment of a full Bedrock\n * system. The SystemDictator is designed to support both fresh network deployments and\n * upgrades to existing pre-Bedrock systems.\n */\ncontract SystemDictator is OwnableUpgradeable {\n /**\n * @notice Basic system configuration.\n */\n struct GlobalConfig {\n AddressManager addressManager;\n ProxyAdmin proxyAdmin;\n address controller;\n address finalOwner;\n }\n\n /**\n * @notice Set of proxy addresses.\n */\n struct ProxyAddressConfig {\n address l2OutputOracleProxy;\n address optimismPortalProxy;\n address l1CrossDomainMessengerProxy;\n address l1StandardBridgeProxy;\n address optimismMintableERC20FactoryProxy;\n address l1ERC721BridgeProxy;\n address systemConfigProxy;\n }\n\n /**\n * @notice Set of implementation addresses.\n */\n struct ImplementationAddressConfig {\n L2OutputOracle l2OutputOracleImpl;\n OptimismPortal optimismPortalImpl;\n L1CrossDomainMessenger l1CrossDomainMessengerImpl;\n L1StandardBridge l1StandardBridgeImpl;\n OptimismMintableERC20Factory optimismMintableERC20FactoryImpl;\n L1ERC721Bridge l1ERC721BridgeImpl;\n PortalSender portalSenderImpl;\n SystemConfig systemConfigImpl;\n }\n\n /**\n * @notice Dynamic L2OutputOracle config.\n */\n struct L2OutputOracleDynamicConfig {\n uint256 l2OutputOracleStartingBlockNumber;\n uint256 l2OutputOracleStartingTimestamp;\n }\n\n /**\n * @notice Values for the system config contract.\n */\n struct SystemConfigConfig {\n address owner;\n uint256 overhead;\n uint256 scalar;\n bytes32 batcherHash;\n uint64 gasLimit;\n address unsafeBlockSigner;\n ResourceMetering.ResourceConfig resourceConfig;\n }\n\n /**\n * @notice Combined system configuration.\n */\n struct DeployConfig {\n GlobalConfig globalConfig;\n ProxyAddressConfig proxyAddressConfig;\n ImplementationAddressConfig implementationAddressConfig;\n SystemConfigConfig systemConfigConfig;\n }\n\n /**\n * @notice Step after which exit 1 can no longer be used.\n */\n uint8 public constant EXIT_1_NO_RETURN_STEP = 3;\n\n /**\n * @notice Step where proxy ownership is transferred.\n */\n uint8 public constant PROXY_TRANSFER_STEP = 4;\n\n /**\n * @notice System configuration.\n */\n DeployConfig public config;\n\n /**\n * @notice Dynamic configuration for the L2OutputOracle.\n */\n L2OutputOracleDynamicConfig public l2OutputOracleDynamicConfig;\n\n /**\n * @notice Dynamic configuration for the OptimismPortal. Determines\n * if the system should be paused when initialized.\n */\n bool public optimismPortalDynamicConfig;\n\n /**\n * @notice Current step;\n */\n uint8 public currentStep;\n\n /**\n * @notice Whether or not dynamic config has been set.\n */\n bool public dynamicConfigSet;\n\n /**\n * @notice Whether or not the deployment is finalized.\n */\n bool public finalized;\n\n /**\n * @notice Whether or not the deployment has been exited.\n */\n bool public exited;\n\n /**\n * @notice Address of the old L1CrossDomainMessenger implementation.\n */\n address public oldL1CrossDomainMessenger;\n\n /**\n * @notice Checks that the current step is the expected step, then bumps the current step.\n *\n * @param _step Current step.\n */\n modifier step(uint8 _step) {\n require(!finalized, \"SystemDictator: already finalized\");\n require(!exited, \"SystemDictator: already exited\");\n require(currentStep == _step, \"SystemDictator: incorrect step\");\n _;\n currentStep++;\n }\n\n /**\n * @notice Constructor required to ensure that the implementation of the SystemDictator is\n * initialized upon deployment.\n */\n constructor() {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n // Using this shorter variable as an alias for address(0) just prevents us from having to\n // to use a new line for every single parameter.\n address zero = address(0);\n initialize(\n DeployConfig(\n GlobalConfig(AddressManager(zero), ProxyAdmin(zero), zero, zero),\n ProxyAddressConfig(zero, zero, zero, zero, zero, zero, zero),\n ImplementationAddressConfig(\n L2OutputOracle(zero),\n OptimismPortal(payable(zero)),\n L1CrossDomainMessenger(zero),\n L1StandardBridge(payable(zero)),\n OptimismMintableERC20Factory(zero),\n L1ERC721Bridge(zero),\n PortalSender(zero),\n SystemConfig(zero)\n ),\n SystemConfigConfig(zero, 0, 0, bytes32(0), 0, zero, rcfg)\n )\n );\n }\n\n /**\n * @param _config System configuration.\n */\n function initialize(DeployConfig memory _config) public initializer {\n config = _config;\n currentStep = 1;\n __Ownable_init();\n _transferOwnership(config.globalConfig.controller);\n }\n\n /**\n * @notice Allows the owner to update dynamic config.\n *\n * @param _l2OutputOracleDynamicConfig Dynamic L2OutputOracle config.\n * @param _optimismPortalDynamicConfig Dynamic OptimismPortal config.\n */\n function updateDynamicConfig(\n L2OutputOracleDynamicConfig memory _l2OutputOracleDynamicConfig,\n bool _optimismPortalDynamicConfig\n ) external onlyOwner {\n l2OutputOracleDynamicConfig = _l2OutputOracleDynamicConfig;\n optimismPortalDynamicConfig = _optimismPortalDynamicConfig;\n dynamicConfigSet = true;\n }\n\n /**\n * @notice Configures the ProxyAdmin contract.\n */\n function step1() public onlyOwner step(1) {\n // Set the AddressManager in the ProxyAdmin.\n config.globalConfig.proxyAdmin.setAddressManager(config.globalConfig.addressManager);\n\n // Set the L1CrossDomainMessenger to the RESOLVED proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n ProxyAdmin.ProxyType.RESOLVED\n );\n\n // Set the implementation name for the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.setImplementationName(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Set the L1StandardBridge to the CHUGSPLASH proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1StandardBridgeProxy,\n ProxyAdmin.ProxyType.CHUGSPLASH\n );\n\n // Upgrade and initialize the SystemConfig so the Sequencer can start up.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.systemConfigProxy),\n address(config.implementationAddressConfig.systemConfigImpl),\n abi.encodeCall(\n SystemConfig.initialize,\n (\n config.systemConfigConfig.owner,\n config.systemConfigConfig.overhead,\n config.systemConfigConfig.scalar,\n config.systemConfigConfig.batcherHash,\n config.systemConfigConfig.gasLimit,\n config.systemConfigConfig.unsafeBlockSigner,\n config.systemConfigConfig.resourceConfig\n )\n )\n );\n }\n\n /**\n * @notice Pauses the system by shutting down the L1CrossDomainMessenger and setting the\n * deposit halt flag to tell the Sequencer's DTL to stop accepting deposits.\n */\n function step2() public onlyOwner step(2) {\n // Store the address of the old L1CrossDomainMessenger implementation. We will need this\n // address in the case that we have to exit early.\n oldL1CrossDomainMessenger = config.globalConfig.addressManager.getAddress(\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Temporarily brick the L1CrossDomainMessenger by setting its implementation address to\n // address(0) which will cause the ResolvedDelegateProxy to revert. Better than pausing\n // the L1CrossDomainMessenger via pause() because it can be easily reverted.\n config.globalConfig.addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(0));\n\n // Set the DTL shutoff block, which will tell the DTL to stop syncing new deposits from the\n // CanonicalTransactionChain. We do this by setting an address in the AddressManager\n // because the DTL already has a reference to the AddressManager and this way we don't also\n // need to give it a reference to the SystemDictator.\n config.globalConfig.addressManager.setAddress(\n \"DTL_SHUTOFF_BLOCK\",\n address(uint160(block.number))\n );\n }\n\n /**\n * @notice Removes deprecated addresses from the AddressManager.\n */\n function step3() external onlyOwner step(EXIT_1_NO_RETURN_STEP) {\n // Remove all deprecated addresses from the AddressManager\n string[17] memory deprecated = [\n \"OVM_CanonicalTransactionChain\",\n \"OVM_L2CrossDomainMessenger\",\n \"OVM_DecompressionPrecompileAddress\",\n \"OVM_Sequencer\",\n \"OVM_Proposer\",\n \"OVM_ChainStorageContainer-CTC-batches\",\n \"OVM_ChainStorageContainer-CTC-queue\",\n \"OVM_CanonicalTransactionChain\",\n \"OVM_StateCommitmentChain\",\n \"OVM_BondManager\",\n \"OVM_ExecutionManager\",\n \"OVM_FraudVerifier\",\n \"OVM_StateManagerFactory\",\n \"OVM_StateTransitionerFactory\",\n \"OVM_SafetyChecker\",\n \"OVM_L1MultiMessageRelayer\",\n \"BondManager\"\n ];\n\n for (uint256 i = 0; i < deprecated.length; i++) {\n config.globalConfig.addressManager.setAddress(deprecated[i], address(0));\n }\n }\n\n /**\n * @notice Transfers system ownership to the ProxyAdmin.\n */\n function step4() external onlyOwner step(PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the ProxyAdmin.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1StandardBridge to the ProxyAdmin.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the ProxyAdmin.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.proxyAdmin)\n );\n }\n\n /**\n * @notice Upgrades and initializes proxy contracts.\n */\n function step5() external onlyOwner step(5) {\n // Dynamic config must be set before we can initialize the L2OutputOracle.\n require(dynamicConfigSet, \"SystemDictator: dynamic oracle config is not yet initialized\");\n\n // Upgrade and initialize the L2OutputOracle.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l2OutputOracleProxy),\n address(config.implementationAddressConfig.l2OutputOracleImpl),\n abi.encodeCall(\n L2OutputOracle.initialize,\n (\n l2OutputOracleDynamicConfig.l2OutputOracleStartingBlockNumber,\n l2OutputOracleDynamicConfig.l2OutputOracleStartingTimestamp\n )\n )\n );\n\n // Upgrade and initialize the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.optimismPortalProxy),\n address(config.implementationAddressConfig.optimismPortalImpl),\n abi.encodeCall(OptimismPortal.initialize, (optimismPortalDynamicConfig))\n );\n\n // Upgrade the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1CrossDomainMessengerProxy),\n address(config.implementationAddressConfig.l1CrossDomainMessengerImpl)\n );\n\n // Try to initialize the L1CrossDomainMessenger, only fail if it's already been initialized.\n try\n L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy)\n .initialize()\n {\n // L1CrossDomainMessenger is the one annoying edge case difference between existing\n // networks and fresh networks because in existing networks it'll already be\n // initialized but in fresh networks it won't be. Try/catch is the easiest and most\n // consistent way to handle this because initialized() is not exposed publicly.\n } catch Error(string memory reason) {\n require(\n keccak256(abi.encodePacked(reason)) ==\n keccak256(\"Initializable: contract is already initialized\"),\n string.concat(\"SystemDictator: unexpected error initializing L1XDM: \", reason)\n );\n } catch {\n revert(\"SystemDictator: unexpected error initializing L1XDM (no reason)\");\n }\n\n // Transfer ETH from the L1StandardBridge to the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.portalSenderImpl),\n abi.encodeCall(PortalSender.donate, ())\n );\n\n // Upgrade the L1StandardBridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.l1StandardBridgeImpl)\n );\n\n // Upgrade the OptimismMintableERC20Factory (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.optimismMintableERC20FactoryProxy),\n address(config.implementationAddressConfig.optimismMintableERC20FactoryImpl)\n );\n\n // Upgrade the L1ERC721Bridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1ERC721BridgeProxy),\n address(config.implementationAddressConfig.l1ERC721BridgeImpl)\n );\n }\n\n /**\n * @notice Calls the first 2 steps of the migration process.\n */\n function phase1() external onlyOwner {\n step1();\n step2();\n }\n\n /**\n * @notice Tranfers admin ownership to the final owner.\n */\n function finalize() external onlyOwner {\n // Transfer ownership of the ProxyAdmin to the final owner.\n config.globalConfig.proxyAdmin.transferOwnership(config.globalConfig.finalOwner);\n\n // Optionally also transfer AddressManager and L1StandardBridge if we still own it. Might\n // happen if we're exiting early.\n if (currentStep <= PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the final owner.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1StandardBridge to the final owner.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the final owner.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.finalOwner)\n );\n }\n\n // Mark the deployment as finalized.\n finalized = true;\n }\n\n /**\n * @notice First exit point, can only be called before step 3 is executed.\n */\n function exit1() external onlyOwner {\n require(\n currentStep == EXIT_1_NO_RETURN_STEP,\n \"SystemDictator: can only exit1 before step 3 is executed\"\n );\n\n // Reset the L1CrossDomainMessenger to the old implementation.\n config.globalConfig.addressManager.setAddress(\n \"OVM_L1CrossDomainMessenger\",\n oldL1CrossDomainMessenger\n );\n\n // Unset the DTL shutoff block which will allow the DTL to sync again.\n config.globalConfig.addressManager.setAddress(\"DTL_SHUTOFF_BLOCK\", address(0));\n\n // Mark the deployment as exited.\n exited = true;\n }\n}\n" - }, - "contracts/echidna/FuzzAddressAliasing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract EchidnaFuzzAddressAliasing {\n bool internal failedRoundtrip;\n\n /**\n * @notice Takes an address to be aliased with AddressAliasHelper and then unaliased\n * and updates the test contract's state indicating if the round trip encoding\n * failed.\n */\n function testRoundTrip(address addr) public {\n // Alias our address\n address aliasedAddr = AddressAliasHelper.applyL1ToL2Alias(addr);\n\n // Unalias our address\n address undoneAliasAddr = AddressAliasHelper.undoL1ToL2Alias(aliasedAddr);\n\n // If our round trip aliasing did not return the original result, set our state.\n if (addr != undoneAliasAddr) {\n failedRoundtrip = true;\n }\n }\n\n /**\n * @custom:invariant Address aliases are always able to be undone.\n *\n * Asserts that an address that has been aliased with `applyL1ToL2Alias` can always\n * be unaliased with `undoL1ToL2Alias`.\n */\n function echidna_round_trip_aliasing() public view returns (bool) {\n // ASSERTION: The round trip aliasing done in testRoundTrip(...) should never fail.\n return !failedRoundtrip;\n }\n}\n" - }, - "contracts/echidna/FuzzBurn.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\n\ncontract EchidnaFuzzBurnEth is StdUtils {\n bool internal failedEthBurn;\n\n /**\n * @notice Takes an integer amount of eth to burn through the Burn library and\n * updates the contract state if an incorrect amount of eth moved from the contract\n */\n function testBurn(uint256 _value) public {\n // cache the contract's eth balance\n uint256 preBurnBalance = address(this).balance;\n uint256 value = bound(_value, 0, preBurnBalance);\n\n // execute a burn of _value eth\n Burn.eth(value);\n\n // check that exactly value eth was transfered from the contract\n unchecked {\n if (address(this).balance != preBurnBalance - value) {\n failedEthBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `eth(uint256)` always burns the exact amount of eth passed.\n *\n * Asserts that when `Burn.eth(uint256)` is called, it always burns the exact amount\n * of ETH passed to the function.\n */\n function echidna_burn_eth() public view returns (bool) {\n // ASSERTION: The amount burned should always match the amount passed exactly\n return !failedEthBurn;\n }\n}\n\ncontract EchidnaFuzzBurnGas is StdUtils {\n bool internal failedGasBurn;\n\n /**\n * @notice Takes an integer amount of gas to burn through the Burn library and\n * updates the contract state if at least that amount of gas was not burned\n * by the library\n */\n function testGas(uint256 _value) public {\n // cap the value to the max resource limit\n uint256 MAX_RESOURCE_LIMIT = 8_000_000;\n uint256 value = bound(_value, 0, MAX_RESOURCE_LIMIT);\n\n // cache the contract's current remaining gas\n uint256 preBurnGas = gasleft();\n\n // execute the gas burn\n Burn.gas(value);\n\n // cache the remaining gas post burn\n uint256 postBurnGas = gasleft();\n\n // check that at least value gas was burnt (and that there was no underflow)\n unchecked {\n if (postBurnGas - preBurnGas > value || preBurnGas - value > preBurnGas) {\n failedGasBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `gas(uint256)` always burns at least the amount of gas passed.\n *\n * Asserts that when `Burn.gas(uint256)` is called, it always burns at least the amount\n * of gas passed to the function.\n */\n function echidna_burn_gas() public view returns (bool) {\n // ASSERTION: The amount of gas burned should be strictly greater than the\n // the amount passed as _value (minimum _value + whatever minor overhead to\n // the value after the call)\n return !failedGasBurn;\n }\n}\n" - }, - "contracts/echidna/FuzzEncoding.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzEncoding {\n bool internal failedRoundtripAToB;\n bool internal failedRoundtripBToA;\n\n /**\n * @notice Takes a pair of integers to be encoded into a versioned nonce with the\n * Encoding library and then decoded and updates the test contract's state\n * indicating if the round trip encoding failed.\n */\n function testRoundTripAToB(uint240 _nonce, uint16 _version) public {\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(encodedVersionedNonce);\n\n // If our round trip encoding did not return the original result, set our state.\n if ((decodedNonce != _nonce) || (decodedVersion != _version)) {\n failedRoundtripAToB = true;\n }\n }\n\n /**\n * @notice Takes an integer representing a packed version and nonce and attempts\n * to decode them using the Encoding library before re-encoding and updates\n * the test contract's state indicating if the round trip encoding failed.\n */\n function testRoundTripBToA(uint256 _versionedNonce) public {\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(_versionedNonce);\n\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(decodedNonce, decodedVersion);\n\n // If our round trip encoding did not return the original result, set our state.\n if (encodedVersionedNonce != _versionedNonce) {\n failedRoundtripBToA = true;\n }\n }\n\n /**\n * @custom:invariant `testRoundTripAToB` never fails.\n *\n * Asserts that a raw versioned nonce can be encoded / decoded to reach the same raw value.\n */\n function echidna_round_trip_encoding_AToB() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripAToB(...)\n return !failedRoundtripAToB;\n }\n\n /**\n * @custom:invariant `testRoundTripBToA` never fails.\n *\n * Asserts that an encoded versioned nonce can always be decoded / re-encoded to reach\n * the same encoded value.\n */\n function echidna_round_trip_encoding_BToA() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripBToA should never\n // fail.\n return !failedRoundtripBToA;\n }\n}\n" - }, - "contracts/echidna/FuzzHashing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzHashing {\n bool internal failedCrossDomainHashHighVersion;\n bool internal failedCrossDomainHashV0;\n bool internal failedCrossDomainHashV1;\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash with a randomly\n * generated version. Only schema versions 0 and 1 are supported and all others should revert.\n */\n function testHashCrossDomainMessageHighVersion(\n uint16 _version,\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // hash the cross domain message. we don't need to store the result since the function\n // validates and should revert if an invalid version (>1) is encoded\n Hashing.hashCrossDomainMessage(encodedNonce, _sender, _target, _value, _gasLimit, _data);\n\n // check that execution never makes it this far for an invalid version\n if (_version > 1) {\n failedCrossDomainHashHighVersion = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v0 schema\n * and compares the output of a call to the unversioned function to the v0 function directly\n */\n function testHashCrossDomainMessageV0(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 0\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 0);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV0(\n _target,\n _sender,\n _data,\n encodedNonce\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV0 = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v1 schema\n * and compares the output of a call to the unversioned function to the v1 function directly\n */\n function testHashCrossDomainMessageV1(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 1\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 1);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV1(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV1 = true;\n }\n }\n\n /**\n * @custom:invariant `hashCrossDomainMessage` reverts if `version` is > `1`.\n *\n * The `hashCrossDomainMessage` function should always revert if the `version` passed is > `1`.\n */\n function echidna_hash_xdomain_msg_high_version() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage will never succeed for a version > 1\n return !failedCrossDomainHashHighVersion;\n }\n\n /**\n * @custom:invariant `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0`\n * are equivalent.\n *\n * If the version passed is 0, `hashCrossDomainMessage` and `hashCrossDomainMessageV0` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_0() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV0\n // should always match when the version passed is 0\n return !failedCrossDomainHashV0;\n }\n\n /**\n * @custom:invariant `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1`\n * are equivalent.\n *\n * If the version passed is 1, `hashCrossDomainMessage` and `hashCrossDomainMessageV1` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_1() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV1\n // should always match when the version passed is 1\n return !failedCrossDomainHashV1;\n }\n}\n" - }, - "contracts/echidna/FuzzOptimismPortal.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract EchidnaFuzzOptimismPortal {\n OptimismPortal internal portal;\n bool internal failedToComplete;\n\n constructor() {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n SystemConfig systemConfig = new SystemConfig({\n _owner: address(1),\n _overhead: 0,\n _scalar: 10000,\n _batcherHash: bytes32(0),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(0),\n _config: rcfg\n });\n\n portal = new OptimismPortal({\n _l2Oracle: L2OutputOracle(address(0)),\n _guardian: address(0),\n _paused: false,\n _config: systemConfig\n });\n }\n\n // A test intended to identify any unexpected halting conditions\n function testDepositTransactionCompletes(\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable {\n failedToComplete = true;\n require(!_isCreation || _to == address(0), \"EchidnaFuzzOptimismPortal: invalid test case.\");\n portal.depositTransaction{ value: _mint }(_to, _value, _gasLimit, _isCreation, _data);\n failedToComplete = false;\n }\n\n /**\n * @custom:invariant Deposits of any value should always succeed unless\n * `_to` = `address(0)` or `_isCreation` = `true`.\n *\n * All deposits, barring creation transactions and transactions sent to `address(0)`,\n * should always succeed.\n */\n function echidna_deposit_completes() public view returns (bool) {\n return !failedToComplete;\n }\n}\n" - }, - "contracts/echidna/FuzzResourceMetering.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {\n bool internal failedMaxGasPerBlock;\n bool internal failedRaiseBaseFee;\n bool internal failedLowerBaseFee;\n bool internal failedNeverBelowMinBaseFee;\n bool internal failedMaxRaiseBaseFeePerBlock;\n bool internal failedMaxLowerBaseFeePerBlock;\n\n // Used as a special flag for the purpose of identifying unchecked math errors specifically\n // in the test contracts, not the target contracts themselves.\n bool internal underflow;\n\n constructor() {\n initialize();\n }\n\n function initialize() internal initializer {\n __ResourceMetering_init();\n }\n\n function resourceConfig() public pure returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig();\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n return rcfg;\n }\n\n /**\n * @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test\n * the underlying resource metering/gas market logic\n */\n function testBurn(uint256 _gasToBurn, bool _raiseBaseFee) public {\n // Part 1: we cache the current param values and do some basic checks on them.\n uint256 cachedPrevBaseFee = uint256(params.prevBaseFee);\n uint256 cachedPrevBoughtGas = uint256(params.prevBoughtGas);\n uint256 cachedPrevBlockNum = uint256(params.prevBlockNum);\n\n ResourceMetering.ResourceConfig memory rcfg = resourceConfig();\n uint256 targetResourceLimit = uint256(rcfg.maxResourceLimit) /\n uint256(rcfg.elasticityMultiplier);\n\n // check that the last block's base fee hasn't dropped below the minimum\n if (cachedPrevBaseFee < uint256(rcfg.minimumBaseFee)) {\n failedNeverBelowMinBaseFee = true;\n }\n // check that the last block didn't consume more than the max amount of gas\n if (cachedPrevBoughtGas > uint256(rcfg.maxResourceLimit)) {\n failedMaxGasPerBlock = true;\n }\n\n // Part2: we perform the gas burn\n\n // force the gasToBurn into the correct range based on whether we intend to\n // raise or lower the baseFee after this block, respectively\n uint256 gasToBurn;\n if (_raiseBaseFee) {\n gasToBurn = bound(\n _gasToBurn,\n uint256(targetResourceLimit),\n uint256(rcfg.maxResourceLimit)\n );\n } else {\n gasToBurn = bound(_gasToBurn, 0, targetResourceLimit);\n }\n\n _burnInternal(uint64(gasToBurn));\n\n // Part 3: we run checks and modify our invariant flags based on the updated params values\n\n // Calculate the maximum allowed baseFee change (per block)\n uint256 maxBaseFeeChange = cachedPrevBaseFee / uint256(rcfg.baseFeeMaxChangeDenominator);\n\n // If the last block used more than the target amount of gas (and there were no\n // empty blocks in between), ensure this block's baseFee increased, but not by\n // more than the max amount per block\n if (\n (cachedPrevBoughtGas > uint256(targetResourceLimit)) &&\n (uint256(params.prevBlockNum) - cachedPrevBlockNum == 1)\n ) {\n failedRaiseBaseFee = failedRaiseBaseFee || (params.prevBaseFee <= cachedPrevBaseFee);\n failedMaxRaiseBaseFeePerBlock =\n failedMaxRaiseBaseFeePerBlock ||\n ((uint256(params.prevBaseFee) - cachedPrevBaseFee) < maxBaseFeeChange);\n }\n\n // If the last block used less than the target amount of gas, (or was empty),\n // ensure that: this block's baseFee was decreased, but not by more than the max amount\n if (\n (cachedPrevBoughtGas < uint256(targetResourceLimit)) ||\n (uint256(params.prevBlockNum) - cachedPrevBlockNum > 1)\n ) {\n // Invariant: baseFee should decrease\n failedLowerBaseFee =\n failedLowerBaseFee ||\n (uint256(params.prevBaseFee) > cachedPrevBaseFee);\n\n if (params.prevBlockNum - cachedPrevBlockNum == 1) {\n // No empty blocks\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n } else if (params.prevBlockNum - cachedPrevBlockNum > 1) {\n // We have at least one empty block\n // Update the maxBaseFeeChange to account for multiple blocks having passed\n unchecked {\n maxBaseFeeChange = uint256(\n int256(cachedPrevBaseFee) -\n Arithmetic.clamp(\n Arithmetic.cdexp(\n int256(cachedPrevBaseFee),\n int256(uint256(rcfg.baseFeeMaxChangeDenominator)),\n int256(uint256(params.prevBlockNum) - cachedPrevBlockNum)\n ),\n int256(uint256(rcfg.minimumBaseFee)),\n int256(uint256(rcfg.maximumBaseFee))\n )\n );\n }\n\n // Detect an underflow in the previous calculation.\n // Without using unchecked above, and detecting the underflow here, echidna would\n // otherwise ignore the revert.\n underflow = underflow || maxBaseFeeChange > cachedPrevBaseFee;\n\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n }\n }\n }\n\n function _burnInternal(uint64 _gasToBurn) private metered(_gasToBurn) {}\n\n /**\n * @custom:invariant The base fee should increase if the last block used more\n * than the target amount of gas\n *\n * If the last block used more than the target amount of gas (and there were no\n * empty blocks in between), ensure this block's baseFee increased, but not by\n * more than the max amount per block.\n */\n function echidna_high_usage_raise_baseFee() public view returns (bool) {\n return !failedRaiseBaseFee;\n }\n\n /**\n * @custom:invariant The base fee should decrease if the last block used less\n * than the target amount of gas\n *\n * If the previous block used less than the target amount of gas, the base fee should decrease,\n * but not more than the max amount.\n */\n function echidna_low_usage_lower_baseFee() public view returns (bool) {\n return !failedLowerBaseFee;\n }\n\n /**\n * @custom:invariant A block's base fee should never be below `MINIMUM_BASE_FEE`\n *\n * This test asserts that a block's base fee can never drop below the\n * `MINIMUM_BASE_FEE` threshold.\n */\n function echidna_never_below_min_baseFee() public view returns (bool) {\n return !failedNeverBelowMinBaseFee;\n }\n\n /**\n * @custom:invariant A block can never consume more than `MAX_RESOURCE_LIMIT` gas.\n *\n * This test asserts that a block can never consume more than the `MAX_RESOURCE_LIMIT`\n * gas threshold.\n */\n function echidna_never_above_max_gas_limit() public view returns (bool) {\n return !failedMaxGasPerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be raised more than the max base fee change.\n *\n * After a block consumes more gas than the target gas, the base fee cannot be raised\n * more than the maximum amount allowed. The max base fee change (per-block) is derived\n * as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_increase() public view returns (bool) {\n return !failedMaxRaiseBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be lowered more than the max base fee change.\n *\n * After a block consumes less than the target gas, the base fee cannot be lowered more\n * than the maximum amount allowed. The max base fee change (per-block) is derived as\n *follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_decrease() public view returns (bool) {\n return !failedMaxLowerBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The `maxBaseFeeChange` calculation over multiple blocks can never\n * underflow.\n *\n * When calculating the `maxBaseFeeChange` after multiple empty blocks, the calculation\n * should never be allowed to underflow.\n */\n function echidna_underflow() public view returns (bool) {\n return !underflow;\n }\n}\n" - }, - "contracts/governance/GovernanceToken.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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 * @custom:predeploy 0x4200000000000000000000000000000000000042\n * @title GovernanceToken\n * @notice The Optimism token used in governance and supporting voting and delegation. Implements\n * EIP 2612 allowing signed approvals. Contract is \"owned\" by a `MintManager` instance with\n * permission to the `mint` function only, for the purposes of enforcing the token inflation\n * schedule.\n */\ncontract GovernanceToken is ERC20Burnable, ERC20Votes, Ownable {\n constructor() ERC20(\"Optimism\", \"OP\") ERC20Permit(\"Optimism\") {}\n\n /**\n * @notice Allows the owner to mint tokens.\n *\n * @param _account The account receiving minted tokens.\n * @param _amount The amount of tokens to mint.\n */\n function mint(address _account, uint256 _amount) public onlyOwner {\n _mint(_account, _amount);\n }\n\n /**\n * @notice Callback called after a token transfer.\n *\n * @param from The account sending tokens.\n * @param to The account receiving tokens.\n * @param amount The amount of tokens being transfered.\n */\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 /**\n * @notice Internal mint function.\n *\n * @param to The account receiving minted tokens.\n * @param amount The amount of tokens to mint.\n */\n function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._mint(to, amount);\n }\n\n /**\n * @notice Internal burn function.\n *\n * @param account The account that tokens will be burned from.\n * @param amount The amount of tokens that will be burned.\n */\n function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._burn(account, amount);\n }\n}\n" - }, - "contracts/governance/MintManager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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(\n mintPermittedAfter <= block.timestamp,\n \"MintManager: minting not permitted yet\"\n );\n\n require(\n _amount <= (governanceToken.totalSupply() * MINT_CAP) / DENOMINATOR,\n \"MintManager: mint amount exceeds cap\"\n );\n }\n\n mintPermittedAfter = block.timestamp + MINT_PERIOD;\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(\n _newMintManager != address(0),\n \"MintManager: mint manager cannot be the zero address\"\n );\n\n governanceToken.transferOwnership(_newMintManager);\n }\n}\n" - }, - "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" - }, - "contracts/legacy/DeployerWhitelist.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000002\n * @title DeployerWhitelist\n * @notice DeployerWhitelist is a legacy contract that was originally used to act as a whitelist of\n * addresses allowed to the Optimism network. The DeployerWhitelist has since been\n * disabled, but the code is kept in state for the sake of full backwards compatibility.\n * As of the Bedrock upgrade, the DeployerWhitelist is completely unused by the Optimism\n * system and could, in theory, be removed entirely.\n */\ncontract DeployerWhitelist is Semver {\n /**\n * @notice Address of the owner of this contract. Note that when this address is set to\n * address(0), the whitelist is disabled.\n */\n address public owner;\n\n /**\n * @notice Mapping of deployer addresses to boolean whitelist status.\n */\n mapping(address => bool) public whitelist;\n\n /**\n * @notice Emitted when the owner of this contract changes.\n *\n * @param oldOwner Address of the previous owner.\n * @param newOwner Address of the new owner.\n */\n event OwnerChanged(address oldOwner, address newOwner);\n\n /**\n * @notice Emitted when the whitelist status of a deployer changes.\n *\n * @param deployer Address of the deployer.\n * @param whitelisted Boolean indicating whether the deployer is whitelisted.\n */\n event WhitelistStatusChanged(address deployer, bool whitelisted);\n\n /**\n * @notice Emitted when the whitelist is disabled.\n *\n * @param oldOwner Address of the final owner of the whitelist.\n */\n event WhitelistDisabled(address oldOwner);\n\n /**\n * @notice Blocks functions to anyone except the contract owner.\n */\n modifier onlyOwner() {\n require(\n msg.sender == owner,\n \"DeployerWhitelist: function can only be called by the owner of this contract\"\n );\n _;\n }\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Adds or removes an address from the deployment whitelist.\n *\n * @param _deployer Address to update permissions for.\n * @param _isWhitelisted Whether or not the address is whitelisted.\n */\n function setWhitelistedDeployer(address _deployer, bool _isWhitelisted) external onlyOwner {\n whitelist[_deployer] = _isWhitelisted;\n emit WhitelistStatusChanged(_deployer, _isWhitelisted);\n }\n\n /**\n * @notice Updates the owner of this contract.\n *\n * @param _owner Address of the new owner.\n */\n function setOwner(address _owner) external onlyOwner {\n // Prevent users from setting the whitelist owner to address(0) except via\n // enableArbitraryContractDeployment. If you want to burn the whitelist owner, send it to\n // any other address that doesn't have a corresponding knowable private key.\n require(\n _owner != address(0),\n \"DeployerWhitelist: can only be disabled via enableArbitraryContractDeployment\"\n );\n\n emit OwnerChanged(owner, _owner);\n owner = _owner;\n }\n\n /**\n * @notice Permanently enables arbitrary contract deployment and deletes the owner.\n */\n function enableArbitraryContractDeployment() external onlyOwner {\n emit WhitelistDisabled(owner);\n owner = address(0);\n }\n\n /**\n * @notice Checks whether an address is allowed to deploy contracts.\n *\n * @param _deployer Address to check.\n *\n * @return Whether or not the address can deploy contracts.\n */\n function isDeployerAllowed(address _deployer) external view returns (bool) {\n return (owner == address(0) || whitelist[_deployer]);\n }\n}\n" - }, - "contracts/legacy/L1BlockNumber.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000013\n * @title L1BlockNumber\n * @notice L1BlockNumber is a legacy contract that fills the roll of the OVM_L1BlockNumber contract\n * in the old version of the Optimism system. Only necessary for backwards compatibility.\n * If you want to access the L1 block number going forward, you should use the L1Block\n * contract instead.\n */\ncontract L1BlockNumber is Semver {\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Returns the L1 block number.\n */\n receive() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Returns the L1 block number.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Retrieves the latest L1 block number.\n *\n * @return Latest L1 block number.\n */\n function getL1BlockNumber() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).number();\n }\n}\n" - }, - "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/legacy/LegacyERC20ETH.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000\n * @title LegacyERC20ETH\n * @notice LegacyERC20ETH is a legacy contract that held ETH balances before the Bedrock upgrade.\n * All ETH balances held within this contract were migrated to the state trie as part of\n * the Bedrock upgrade. Functions within this contract that mutate state were already\n * disabled as part of the EVM equivalence upgrade.\n */\ncontract LegacyERC20ETH is OptimismMintableERC20 {\n /**\n * @notice Initializes the contract as an Optimism Mintable ERC20.\n */\n constructor()\n OptimismMintableERC20(Predeploys.L2_STANDARD_BRIDGE, address(0), \"Ether\", \"ETH\")\n {}\n\n /**\n * @notice Returns the ETH balance of the target account. Overrides the base behavior of the\n * contract to preserve the invariant that the balance within this contract always\n * matches the balance in the state trie.\n *\n * @param _who Address of the account to query.\n *\n * @return The ETH balance of the target account.\n */\n function balanceOf(address _who) public view virtual override returns (uint256) {\n return address(_who).balance;\n }\n\n /**\n * @custom:blocked\n * @notice Mints some amount of ETH.\n */\n function mint(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: mint is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Burns some amount of ETH.\n */\n function burn(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: burn is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers some amount of ETH.\n */\n function transfer(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transfer is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Approves a spender to spend some amount of ETH.\n */\n function approve(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: approve is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers funds from some sender account.\n */\n function transferFrom(\n address,\n address,\n uint256\n ) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transferFrom is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Increases the allowance of a spender.\n */\n function increaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Decreases the allowance of a spender.\n */\n function decreaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n }\n}\n" - }, - "contracts/legacy/LegacyMessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000000\n * @title LegacyMessagePasser\n * @notice The LegacyMessagePasser was the low-level mechanism used to send messages from L2 to L1\n * before the Bedrock upgrade. It is now deprecated in favor of the new MessagePasser.\n */\ncontract LegacyMessagePasser is Semver {\n /**\n * @notice Mapping of sent message hashes to boolean status.\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Passes a message to L1.\n *\n * @param _message Message to pass to L1.\n */\n function passMessageToL1(bytes memory _message) external {\n sentMessages[keccak256(abi.encodePacked(_message, msg.sender))] = true;\n }\n}\n" - }, - "contracts/legacy/LegacyMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { ILegacyMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @title LegacyMintableERC20\n * @notice The legacy implementation of the OptimismMintableERC20. This\n * contract is deprecated and should no longer be used.\n */\ncontract LegacyMintableERC20 is ILegacyMintableERC20, ERC20 {\n /**\n * @notice Emitted when the token is minted by the bridge.\n */\n event Mint(address indexed _account, uint256 _amount);\n\n /**\n * @notice Emitted when a token is burned by the bridge.\n */\n event Burn(address indexed _account, uint256 _amount);\n\n /**\n * @notice The token on the remote domain.\n */\n address public l1Token;\n\n /**\n * @notice The local bridge.\n */\n address public l2Bridge;\n\n /**\n * @param _l2Bridge Address of the L2 standard bridge.\n * @param _l1Token Address of the corresponding L1 token.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n */\n constructor(\n address _l2Bridge,\n address _l1Token,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) {\n l1Token = _l1Token;\n l2Bridge = _l2Bridge;\n }\n\n /**\n * @notice Modifier that requires the contract was called by the bridge.\n */\n modifier onlyL2Bridge() {\n require(msg.sender == l2Bridge, \"Only L2 Bridge can mint and burn\");\n _;\n }\n\n /**\n * @notice EIP165 implementation.\n */\n function supportsInterface(bytes4 _interfaceId) public pure returns (bool) {\n bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^\n ILegacyMintableERC20.mint.selector ^\n ILegacyMintableERC20.burn.selector;\n return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n }\n\n /**\n * @notice Only the bridge can mint tokens.\n * @param _to The account receiving tokens.\n * @param _amount The amount of tokens to receive.\n */\n function mint(address _to, uint256 _amount) public virtual onlyL2Bridge {\n _mint(_to, _amount);\n\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Only the bridge can burn tokens.\n * @param _from The account having tokens burnt.\n * @param _amount The amount of tokens being burnt.\n */\n function burn(address _from, uint256 _amount) public virtual onlyL2Bridge {\n _burn(_from, _amount);\n\n emit Burn(_from, _amount);\n }\n}\n" - }, - "contracts/legacy/ResolvedDelegateProxy.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressManager } from \"./AddressManager.sol\";\n\n/**\n * @custom:legacy\n * @title ResolvedDelegateProxy\n * @notice ResolvedDelegateProxy is a legacy proxy contract that makes use of the AddressManager to\n * resolve the implementation address. We're maintaining this contract for backwards\n * compatibility so we can manage all legacy proxies where necessary.\n */\ncontract ResolvedDelegateProxy {\n /**\n * @notice Mapping used to store the implementation name that corresponds to this contract. A\n * mapping was originally used as a way to bypass the same issue normally solved by\n * storing the implementation address in a specific storage slot that does not conflict\n * with any other storage slot. Generally NOT a safe solution but works as long as the\n * implementation does not also keep a mapping in the first storage slot.\n */\n mapping(address => string) private implementationName;\n\n /**\n * @notice Mapping used to store the address of the AddressManager contract where the\n * implementation address will be resolved from. Same concept here as with the above\n * mapping. Also generally unsafe but fine if the implementation doesn't keep a mapping\n * in the second storage slot.\n */\n mapping(address => AddressManager) private addressManager;\n\n /**\n * @param _addressManager Address of the AddressManager.\n * @param _implementationName implementationName of the contract to proxy to.\n */\n constructor(AddressManager _addressManager, string memory _implementationName) {\n addressManager[address(this)] = _addressManager;\n implementationName[address(this)] = _implementationName;\n }\n\n /**\n * @notice Fallback, performs a delegatecall to the resolved implementation address.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n address target = addressManager[address(this)].getAddress(\n (implementationName[address(this)])\n );\n\n require(target != address(0), \"ResolvedDelegateProxy: target address must be initialized\");\n\n // slither-disable-next-line controlled-delegatecall\n (bool success, bytes memory returndata) = target.delegatecall(msg.data);\n\n if (success == true) {\n assembly {\n return(add(returndata, 0x20), mload(returndata))\n }\n } else {\n assembly {\n revert(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n" - }, - "contracts/libraries/Arithmetic.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { SignedMath } from \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\nimport { FixedPointMathLib } from \"@rari-capital/solmate/src/utils/FixedPointMathLib.sol\";\n\n/**\n * @title Arithmetic\n * @notice Even more math than before.\n */\nlibrary Arithmetic {\n /**\n * @notice Clamps a value between a minimum and maximum.\n *\n * @param _value The value to clamp.\n * @param _min The minimum value.\n * @param _max The maximum value.\n *\n * @return The clamped value.\n */\n function clamp(\n int256 _value,\n int256 _min,\n int256 _max\n ) internal pure returns (int256) {\n return SignedMath.min(SignedMath.max(_value, _min), _max);\n }\n\n /**\n * @notice (c)oefficient (d)enominator (exp)onentiation function.\n * Returns the result of: c * (1 - 1/d)^exp.\n *\n * @param _coefficient Coefficient of the function.\n * @param _denominator Fractional denominator.\n * @param _exponent Power function exponent.\n *\n * @return Result of c * (1 - 1/d)^exp.\n */\n function cdexp(\n int256 _coefficient,\n int256 _denominator,\n int256 _exponent\n ) internal pure returns (int256) {\n return\n (_coefficient *\n (FixedPointMathLib.powWad(1e18 - (1e18 / _denominator), _exponent * 1e18))) / 1e18;\n }\n}\n" - }, - "contracts/libraries/Burn.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Burn\n * @notice Utilities for burning stuff.\n */\nlibrary Burn {\n /**\n * Burns a given amount of ETH.\n *\n * @param _amount Amount of ETH to burn.\n */\n function eth(uint256 _amount) internal {\n new Burner{ value: _amount }();\n }\n\n /**\n * Burns a given amount of gas.\n *\n * @param _amount Amount of gas to burn.\n */\n function gas(uint256 _amount) internal view {\n uint256 i = 0;\n uint256 initialGas = gasleft();\n while (initialGas - gasleft() < _amount) {\n ++i;\n }\n }\n}\n\n/**\n * @title Burner\n * @notice Burner self-destructs on creation and sends all ETH to itself, removing all ETH given to\n * the contract from the circulating supply. Self-destructing is the only way to remove ETH\n * from the circulating supply.\n */\ncontract Burner {\n constructor() payable {\n selfdestruct(payable(address(this)));\n }\n}\n" - }, - "contracts/libraries/Bytes.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Bytes\n * @notice Bytes is a library for manipulating byte arrays.\n */\nlibrary Bytes {\n /**\n * @custom:attribution https://github.com/GNSPS/solidity-bytes-utils\n * @notice Slices a byte array with a given starting index and length. Returns a new byte array\n * as opposed to a pointer to the original array. Will throw if trying to slice more\n * bytes than exist in the array.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n * @param _length Length of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n unchecked {\n require(_length + 31 >= _length, \"slice_overflow\");\n require(_start + _length >= _start, \"slice_overflow\");\n require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n }\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n /**\n * @notice Slices a byte array with a given starting index up to the end of the original byte\n * array. Returns a new array rathern than a pointer to the original.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {\n if (_start >= _bytes.length) {\n return bytes(\"\");\n }\n return slice(_bytes, _start, _bytes.length - _start);\n }\n\n /**\n * @notice Converts a byte array into a nibble array by splitting each byte into two nibbles.\n * Resulting nibble array will be exactly twice as long as the input byte array.\n *\n * @param _bytes Input byte array to convert.\n *\n * @return Resulting nibble array.\n */\n function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n uint256 bytesLength = _bytes.length;\n bytes memory nibbles = new bytes(bytesLength * 2);\n bytes1 b;\n\n for (uint256 i = 0; i < bytesLength; ) {\n b = _bytes[i];\n nibbles[i * 2] = b >> 4;\n nibbles[i * 2 + 1] = b & 0x0f;\n unchecked {\n ++i;\n }\n }\n\n return nibbles;\n }\n\n /**\n * @notice Compares two byte arrays by comparing their keccak256 hashes.\n *\n * @param _bytes First byte array to compare.\n * @param _other Second byte array to compare.\n *\n * @return True if the two byte arrays are equal, false otherwise.\n */\n function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {\n return keccak256(_bytes) == keccak256(_other);\n }\n}\n" - }, - "contracts/libraries/Constants.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\n/**\n * @title Constants\n * @notice Constants is a library for storing constants. Simple! Don't put everything in here, just\n * the stuff used in multiple contracts. Constants that only apply to a single contract\n * should be defined in that contract instead.\n */\nlibrary Constants {\n /**\n * @notice Special address to be used as the tx origin for gas estimation calls in the\n * OptimismPortal and CrossDomainMessenger calls. You only need to use this address if\n * the minimum gas limit specified by the user is not actually enough to execute the\n * given message and you're attempting to estimate the actual necessary gas limit. We\n * use address(1) because it's the ecrecover precompile and therefore guaranteed to\n * never have any code on any EVM chain.\n */\n address internal constant ESTIMATION_ADDRESS = address(1);\n\n /**\n * @notice Value used for the L2 sender storage slot in both the OptimismPortal and the\n * CrossDomainMessenger contracts before an actual sender is set. This value is\n * non-zero to reduce the gas cost of message passing transactions.\n */\n address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD;\n\n /**\n * @notice Returns the default values for the ResourceConfig. These are the recommended values\n * for a production network.\n */\n function DEFAULT_RESOURCE_CONFIG()\n internal\n pure\n returns (ResourceMetering.ResourceConfig memory)\n {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n return config;\n }\n}\n" - }, - "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" - }, - "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" - }, - "contracts/libraries/LegacyCrossDomainUtils.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n// Importing from the legacy contracts package causes issues with the build of the contract bindings\n// so we just copy the library here from\n// /packages/contracts/contracts/libraries/bridge/Lib_CrossDomainUtils.sol at commit\n// 7866168c\n/**\n * @title LegacyCrossDomainUtils\n */\nlibrary LegacyCrossDomainUtils {\n /**\n * Generates the correct cross domain calldata for a message.\n * @param _target Target contract address.\n * @param _sender Message sender address.\n * @param _message Message to send to the target.\n * @param _messageNonce Nonce for the provided message.\n * @return ABI encoded cross domain calldata.\n */\n function encodeXDomainCalldata(\n address _target,\n address _sender,\n bytes memory _message,\n uint256 _messageNonce\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(address,address,bytes,uint256)\",\n _target,\n _sender,\n _message,\n _messageNonce\n );\n }\n}\n" - }, - "contracts/libraries/Predeploys.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Predeploys\n * @notice Contains constant addresses for contracts that are pre-deployed to the L2 system.\n */\nlibrary Predeploys {\n /**\n * @notice Address of the L2ToL1MessagePasser predeploy.\n */\n address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016;\n\n /**\n * @notice Address of the L2CrossDomainMessenger predeploy.\n */\n address internal constant L2_CROSS_DOMAIN_MESSENGER =\n 0x4200000000000000000000000000000000000007;\n\n /**\n * @notice Address of the L2StandardBridge predeploy.\n */\n address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;\n\n /**\n * @notice Address of the L2ERC721Bridge predeploy.\n */\n address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014;\n\n /**\n * @notice Address of the SequencerFeeWallet predeploy.\n */\n address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;\n\n /**\n * @notice Address of the OptimismMintableERC20Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY =\n 0x4200000000000000000000000000000000000012;\n\n /**\n * @notice Address of the OptimismMintableERC721Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY =\n 0x4200000000000000000000000000000000000017;\n\n /**\n * @notice Address of the L1Block predeploy.\n */\n address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015;\n\n /**\n * @notice Address of the GasPriceOracle predeploy. Includes fee information\n * and helpers for computing the L1 portion of the transaction fee.\n */\n address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F;\n\n /**\n * @custom:legacy\n * @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger\n * or access tx.origin (or msg.sender) in a L1 to L2 transaction instead.\n */\n address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;\n\n /**\n * @custom:legacy\n * @notice Address of the DeployerWhitelist predeploy. No longer active.\n */\n address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the\n * state trie as of the Bedrock upgrade. Contract has been locked and write functions\n * can no longer be accessed.\n */\n address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;\n\n /**\n * @custom:legacy\n * @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy\n * instead, which exposes more information about the L1 state.\n */\n address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated\n * L2ToL1MessagePasser contract instead.\n */\n address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;\n\n /**\n * @notice Address of the ProxyAdmin predeploy.\n */\n address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018;\n\n /**\n * @notice Address of the BaseFeeVault predeploy.\n */\n address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019;\n\n /**\n * @notice Address of the L1FeeVault predeploy.\n */\n address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A;\n\n /**\n * @notice Address of the GovernanceToken predeploy.\n */\n address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042;\n}\n" - }, - "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, 32), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n\n /**\n * @notice Helper function to determine if there is sufficient gas remaining within the context\n * to guarantee that the minimum gas requirement for a call will be met as well as\n * optionally reserving a specified amount of gas for after the call has concluded.\n * @param _minGas The minimum amount of gas that may be passed to the target context.\n * @param _reservedGas Optional amount of gas to reserve for the caller after the execution\n * of the target context.\n * @return `true` if there is enough gas remaining to safely supply `_minGas` to the target\n * context as well as reserve `_reservedGas` for the caller after the execution of\n * the target context.\n * @dev !!!!! FOOTGUN ALERT !!!!!\n * 1.) The 40_000 base buffer is to account for the worst case of the dynamic cost of the\n * `CALL` opcode's `address_access_cost`, `positive_value_cost`, and\n * `value_to_empty_account_cost` factors with an added buffer of 5,700 gas. It is\n * still possible to self-rekt by initiating a withdrawal with a minimum gas limit\n * that does not account for the `memory_expansion_cost` & `code_execution_cost`\n * factors of the dynamic cost of the `CALL` opcode.\n * 2.) This function should *directly* precede the external call if possible. There is an\n * added buffer to account for gas consumed between this check and the call, but it\n * is only 5,700 gas.\n * 3.) Because EIP-150 ensures that a maximum of 63/64ths of the remaining gas in the call\n * frame may be passed to a subcontext, we need to ensure that the gas will not be\n * truncated.\n * 4.) Use wisely. This function is not a silver bullet.\n */\n function hasMinGas(uint256 _minGas, uint256 _reservedGas) internal view returns (bool) {\n bool _hasMinGas;\n assembly {\n // Equation: gas × 63 ≥ minGas × 64 + 63(40_000 + reservedGas)\n _hasMinGas := iszero(\n lt(mul(gas(), 63), add(mul(_minGas, 64), mul(add(40000, _reservedGas), 63)))\n )\n }\n return _hasMinGas;\n }\n\n /**\n * @notice Perform a low level call without copying any returndata. This function\n * will revert if the call cannot be performed with the specified minimum\n * gas.\n *\n * @param _target Address to call\n * @param _minGas The minimum amount of gas that may be passed 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 callWithMinGas(\n address _target,\n uint256 _minGas,\n uint256 _value,\n bytes memory _calldata\n ) internal returns (bool) {\n bool _success;\n bool _hasMinGas = hasMinGas(_minGas, 0);\n assembly {\n // Assertion: gasleft() >= (_minGas * 64) / 63 + 40_000\n if iszero(_hasMinGas) {\n // Store the \"Error(string)\" selector in scratch space.\n mstore(0, 0x08c379a0)\n // Store the pointer to the string length in scratch space.\n mstore(32, 32)\n // Store the string.\n //\n // SAFETY:\n // - We pad the beginning of the string with two zero bytes as well as the\n // length (24) to ensure that we override the free memory pointer at offset\n // 0x40. This is necessary because the free memory pointer is likely to\n // be greater than 1 byte when this function is called, but it is incredibly\n // unlikely that it will be greater than 3 bytes. As for the data within\n // 0x60, it is ensured that it is 0 due to 0x60 being the zero offset.\n // - It's fine to clobber the free memory pointer, we're reverting.\n mstore(88, 0x0000185361666543616c6c3a204e6f7420656e6f75676820676173)\n\n // Revert with 'Error(\"SafeCall: Not enough gas\")'\n revert(28, 100)\n }\n\n // The call will be supplied at least ((_minGas * 64) / 63) gas due to the\n // above assertion. This ensures that, in all circumstances (except for when the\n // `_minGas` does not account for the `memory_expansion_cost` and `code_execution_cost`\n // factors of the dynamic cost of the `CALL` opcode), the call will receive at least\n // the minimum amount of gas specified.\n _success := call(\n gas(), // gas\n _target, // recipient\n _value, // ether value\n add(_calldata, 32), // inloc\n mload(_calldata), // inlen\n 0x00, // outloc\n 0x00 // outlen\n )\n }\n return _success;\n }\n}\n" - }, - "contracts/libraries/Types.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 * @custom:field outputRoot Hash of the L2 output.\n * @custom:field timestamp Timestamp of the L1 block that the output root was submitted in.\n * @custom:field l2BlockNumber L2 block number that the output corresponds to.\n */\n struct OutputProposal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2BlockNumber;\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 * @custom:field version Version of the output root.\n * @custom:field stateRoot Root of the state trie at the block of this output.\n * @custom:field messagePasserStorageRoot Root of the message passer storage trie.\n * @custom:field latestBlockhash Hash of the block this output was generated from.\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 * @custom:field from Address of the sender of the transaction.\n * @custom:field to Address of the recipient of the transaction.\n * @custom:field isCreation True if the transaction is a contract creation.\n * @custom:field value Value to send to the recipient.\n * @custom:field mint Amount of ETH to mint.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the transaction.\n * @custom:field l1BlockHash Hash of the block the transaction was submitted in.\n * @custom:field logIndex Index of the log in the block the transaction was submitted in.\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 * @custom:field nonce Nonce of the withdrawal transaction\n * @custom:field sender Address of the sender of the transaction.\n * @custom:field target Address of the recipient of the transaction.\n * @custom:field value Value to send to the recipient.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the 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" - }, - "contracts/libraries/rlp/RLPReader.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\n/**\n * @custom:attribution https://github.com/hamdiallam/Solidity-RLP\n * @title RLPReader\n * @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted\n * from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with\n * various tweaks to improve readability.\n */\nlibrary RLPReader {\n /**\n * Custom pointer type to avoid confusion between pointers and uint256s.\n */\n type MemoryPointer is uint256;\n\n /**\n * @notice RLP item types.\n *\n * @custom:value DATA_ITEM Represents an RLP data item (NOT a list).\n * @custom:value LIST_ITEM Represents an RLP list item.\n */\n enum RLPItemType {\n DATA_ITEM,\n LIST_ITEM\n }\n\n /**\n * @notice Struct representing an RLP item.\n *\n * @custom:field length Length of the RLP item.\n * @custom:field ptr Pointer to the RLP item in memory.\n */\n struct RLPItem {\n uint256 length;\n MemoryPointer ptr;\n }\n\n /**\n * @notice Max list length that this library will accept.\n */\n uint256 internal constant MAX_LIST_LENGTH = 32;\n\n /**\n * @notice Converts bytes to a reference to memory position and length.\n *\n * @param _in Input bytes to convert.\n *\n * @return Output memory reference.\n */\n function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) {\n // Empty arrays are not RLP items.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr;\n assembly {\n ptr := add(_in, 32)\n }\n\n return RLPItem({ length: _in.length, ptr: ptr });\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) {\n (uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.LIST_ITEM,\n \"RLPReader: decoded item type for list is not a list item\"\n );\n\n require(\n listOffset + listLength == _in.length,\n \"RLPReader: list item has an invalid data remainder\"\n );\n\n // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by\n // writing to the length. Since we can't know the number of RLP items without looping over\n // the entire input, we'd have to loop twice to accurately size this array. It's easier to\n // simply set a reasonable maximum list length and decrease the size before we finish.\n RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH);\n\n uint256 itemCount = 0;\n uint256 offset = listOffset;\n while (offset < _in.length) {\n (uint256 itemOffset, uint256 itemLength, ) = _decodeLength(\n RLPItem({\n length: _in.length - offset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n })\n );\n\n // We don't need to check itemCount < out.length explicitly because Solidity already\n // handles this check on our behalf, we'd just be wasting gas.\n out[itemCount] = RLPItem({\n length: itemLength + itemOffset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n });\n\n itemCount += 1;\n offset += itemOffset + itemLength;\n }\n\n // Decrease the array size to match the actual item count.\n assembly {\n mstore(out, itemCount)\n }\n\n return out;\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(bytes memory _in) internal pure returns (RLPItem[] memory) {\n return readList(toRLPItem(_in));\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.DATA_ITEM,\n \"RLPReader: decoded item type for bytes is not a data item\"\n );\n\n require(\n _in.length == itemOffset + itemLength,\n \"RLPReader: bytes value contains an invalid remainder\"\n );\n\n return _copy(_in.ptr, itemOffset, itemLength);\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(bytes memory _in) internal pure returns (bytes memory) {\n return readBytes(toRLPItem(_in));\n }\n\n /**\n * @notice Reads the raw bytes of an RLP item.\n *\n * @param _in RLP item to read.\n *\n * @return Raw RLP bytes.\n */\n function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n return _copy(_in.ptr, 0, _in.length);\n }\n\n /**\n * @notice Decodes the length of an RLP item.\n *\n * @param _in RLP item to decode.\n *\n * @return Offset of the encoded data.\n * @return Length of the encoded data.\n * @return RLP item type (LIST_ITEM or DATA_ITEM).\n */\n function _decodeLength(RLPItem memory _in)\n private\n pure\n returns (\n uint256,\n uint256,\n RLPItemType\n )\n {\n // Short-circuit if there's nothing to decode, note that we perform this check when\n // the user creates an RLP item via toRLPItem, but it's always possible for them to bypass\n // that function and create an RLP item directly. So we need to check this anyway.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr = _in.ptr;\n uint256 prefix;\n assembly {\n prefix := byte(0, mload(ptr))\n }\n\n if (prefix <= 0x7f) {\n // Single byte.\n return (0, 1, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xb7) {\n // Short string.\n\n // slither-disable-next-line variable-scope\n uint256 strLen = prefix - 0x80;\n\n require(\n _in.length > strLen,\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n strLen != 1 || firstByteOfContent >= 0x80,\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n\n return (1, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xbf) {\n // Long string.\n uint256 lenOfStrLen = prefix - 0xb7;\n\n require(\n _in.length > lenOfStrLen,\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n\n uint256 strLen;\n assembly {\n strLen := shr(sub(256, mul(8, lenOfStrLen)), mload(add(ptr, 1)))\n }\n\n require(\n strLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long string)\"\n );\n\n require(\n _in.length > lenOfStrLen + strLen,\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n\n return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xf7) {\n // Short list.\n // slither-disable-next-line variable-scope\n uint256 listLen = prefix - 0xc0;\n\n require(\n _in.length > listLen,\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n\n return (1, listLen, RLPItemType.LIST_ITEM);\n } else {\n // Long list.\n uint256 lenOfListLen = prefix - 0xf7;\n\n require(\n _in.length > lenOfListLen,\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long list)\"\n );\n\n uint256 listLen;\n assembly {\n listLen := shr(sub(256, mul(8, lenOfListLen)), mload(add(ptr, 1)))\n }\n\n require(\n listLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long list)\"\n );\n\n require(\n _in.length > lenOfListLen + listLen,\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n\n return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);\n }\n }\n\n /**\n * @notice Copies the bytes from a memory location.\n *\n * @param _src Pointer to the location to read from.\n * @param _offset Offset to start reading from.\n * @param _length Number of bytes to read.\n *\n * @return Copied bytes.\n */\n function _copy(\n MemoryPointer _src,\n uint256 _offset,\n uint256 _length\n ) private pure returns (bytes memory) {\n bytes memory out = new bytes(_length);\n if (_length == 0) {\n return out;\n }\n\n // Mostly based on Solidity's copy_memory_to_memory:\n // solhint-disable max-line-length\n // https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114\n uint256 src = MemoryPointer.unwrap(_src) + _offset;\n assembly {\n let dest := add(out, 32)\n let i := 0\n for {\n\n } lt(i, _length) {\n i := add(i, 32)\n } {\n mstore(add(dest, i), mload(add(src, i)))\n }\n\n if gt(i, _length) {\n mstore(add(dest, _length), 0)\n }\n }\n\n return out;\n }\n}\n" - }, - "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" - }, - "contracts/libraries/trie/MerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Bytes } from \"../Bytes.sol\";\nimport { RLPReader } from \"../rlp/RLPReader.sol\";\n\n/**\n * @title MerkleTrie\n * @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie\n * inclusion proofs. By default, this library assumes a hexary trie. One can change the\n * trie radix constant to support other trie radixes.\n */\nlibrary MerkleTrie {\n /**\n * @notice Struct representing a node in the trie.\n *\n * @custom:field encoded The RLP-encoded node.\n * @custom:field decoded The RLP-decoded node.\n */\n struct TrieNode {\n bytes encoded;\n RLPReader.RLPItem[] decoded;\n }\n\n /**\n * @notice Determines the number of elements per branch node.\n */\n uint256 internal constant TREE_RADIX = 16;\n\n /**\n * @notice Branch nodes have TREE_RADIX elements and one value element.\n */\n uint256 internal constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;\n\n /**\n * @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.\n */\n uint256 internal constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;\n\n /**\n * @notice Prefix for even-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_EVEN = 0;\n\n /**\n * @notice Prefix for odd-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_ODD = 1;\n\n /**\n * @notice Prefix for even-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_EVEN = 2;\n\n /**\n * @notice Prefix for odd-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_ODD = 3;\n\n /**\n * @notice Verifies a proof that a given key/value pair is present in the trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n return Bytes.equal(_value, get(_key, _proof, _root));\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n require(_key.length > 0, \"MerkleTrie: empty key\");\n\n TrieNode[] memory proof = _parseProof(_proof);\n bytes memory key = Bytes.toNibbles(_key);\n bytes memory currentNodeID = abi.encodePacked(_root);\n uint256 currentKeyIndex = 0;\n\n // Proof is top-down, so we start at the first element (root).\n for (uint256 i = 0; i < proof.length; i++) {\n TrieNode memory currentNode = proof[i];\n\n // Key index should never exceed total key length or we'll be out of bounds.\n require(\n currentKeyIndex <= key.length,\n \"MerkleTrie: key index exceeds total key length\"\n );\n\n if (currentKeyIndex == 0) {\n // First proof element is always the root node.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid root hash\"\n );\n } else if (currentNode.encoded.length >= 32) {\n // Nodes 32 bytes or larger are hashed inside branch nodes.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid large internal hash\"\n );\n } else {\n // Nodes smaller than 32 bytes aren't hashed.\n require(\n Bytes.equal(currentNode.encoded, currentNodeID),\n \"MerkleTrie: invalid internal node hash\"\n );\n }\n\n if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {\n if (currentKeyIndex == key.length) {\n // Value is the last element of the decoded list (for branch nodes). There's\n // some ambiguity in the Merkle trie specification because bytes(0) is a\n // valid value to place into the trie, but for branch nodes bytes(0) can exist\n // even when the value wasn't explicitly placed there. Geth treats a value of\n // bytes(0) as \"key does not exist\" and so we do the same.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[TREE_RADIX]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (branch)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (branch)\"\n );\n\n return value;\n } else {\n // We're not at the end of the key yet.\n // Figure out what the next node ID should be and continue.\n uint8 branchKey = uint8(key[currentKeyIndex]);\n RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];\n currentNodeID = _getNodeID(nextNode);\n currentKeyIndex += 1;\n }\n } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {\n bytes memory path = _getNodePath(currentNode);\n uint8 prefix = uint8(path[0]);\n uint8 offset = 2 - (prefix % 2);\n bytes memory pathRemainder = Bytes.slice(path, offset);\n bytes memory keyRemainder = Bytes.slice(key, currentKeyIndex);\n uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);\n\n // Whether this is a leaf node or an extension node, the path remainder MUST be a\n // prefix of the key remainder (or be equal to the key remainder) or the proof is\n // considered invalid.\n require(\n pathRemainder.length == sharedNibbleLength,\n \"MerkleTrie: path remainder must share all nibbles with key\"\n );\n\n if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {\n // Prefix of 2 or 3 means this is a leaf node. For the leaf node to be valid,\n // the key remainder must be exactly equal to the path remainder. We already\n // did the necessary byte comparison, so it's more efficient here to check that\n // the key remainder length equals the shared nibble length, which implies\n // equality with the path remainder (since we already did the same check with\n // the path remainder and the shared nibble length).\n require(\n keyRemainder.length == sharedNibbleLength,\n \"MerkleTrie: key remainder must be identical to path remainder\"\n );\n\n // Our Merkle Trie is designed specifically for the purposes of the Ethereum\n // state trie. Empty values are not allowed in the state trie, so we can safely\n // say that if the value is empty, the key should not exist and the proof is\n // invalid.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[1]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (leaf)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (leaf)\"\n );\n\n return value;\n } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {\n // Prefix of 0 or 1 means this is an extension node. We move onto the next node\n // in the proof and increment the key index by the length of the path remainder\n // which is equal to the shared nibble length.\n currentNodeID = _getNodeID(currentNode.decoded[1]);\n currentKeyIndex += sharedNibbleLength;\n } else {\n revert(\"MerkleTrie: received a node with an unknown prefix\");\n }\n } else {\n revert(\"MerkleTrie: received an unparseable node\");\n }\n }\n\n revert(\"MerkleTrie: ran out of proof elements\");\n }\n\n /**\n * @notice Parses an array of proof elements into a new array that contains both the original\n * encoded element and the RLP-decoded element.\n *\n * @param _proof Array of proof elements to parse.\n *\n * @return Proof parsed into easily accessible structs.\n */\n function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory) {\n uint256 length = _proof.length;\n TrieNode[] memory proof = new TrieNode[](length);\n for (uint256 i = 0; i < length; ) {\n proof[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) });\n unchecked {\n ++i;\n }\n }\n return proof;\n }\n\n /**\n * @notice Picks out the ID for a node. Node ID is referred to as the \"hash\" within the\n * specification, but nodes < 32 bytes are not actually hashed.\n *\n * @param _node Node to pull an ID for.\n *\n * @return ID for the node, depending on the size of its contents.\n */\n function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes memory) {\n return _node.length < 32 ? RLPReader.readRawBytes(_node) : RLPReader.readBytes(_node);\n }\n\n /**\n * @notice Gets the path for a leaf or extension node.\n *\n * @param _node Node to get a path for.\n *\n * @return Node path, converted to an array of nibbles.\n */\n function _getNodePath(TrieNode memory _node) private pure returns (bytes memory) {\n return Bytes.toNibbles(RLPReader.readBytes(_node.decoded[0]));\n }\n\n /**\n * @notice Utility; determines the number of nibbles shared between two nibble arrays.\n *\n * @param _a First nibble array.\n * @param _b Second nibble array.\n *\n * @return Number of shared nibbles.\n */\n function _getSharedNibbleLength(bytes memory _a, bytes memory _b)\n private\n pure\n returns (uint256)\n {\n uint256 shared;\n uint256 max = (_a.length < _b.length) ? _a.length : _b.length;\n for (; shared < max && _a[shared] == _b[shared]; ) {\n unchecked {\n ++shared;\n }\n }\n return shared;\n }\n}\n" - }, - "contracts/libraries/trie/SecureMerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* Library Imports */\nimport { MerkleTrie } from \"./MerkleTrie.sol\";\n\n/**\n * @title SecureMerkleTrie\n * @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input\n * keys. Ethereum's state trie hashes input keys before storing them.\n */\nlibrary SecureMerkleTrie {\n /**\n * @notice Verifies a proof that a given key/value pair is present in the Merkle trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.get(key, _proof, _root);\n }\n\n /**\n * @notice Computes the hashed version of the input key.\n *\n * @param _key Key to hash.\n *\n * @return Hashed version of the key.\n */\n function _getSecureKey(bytes memory _key) private pure returns (bytes memory) {\n return abi.encodePacked(keccak256(_key));\n }\n}\n" - }, - "contracts/periphery/TransferOnion.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ReentrancyGuard } from \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @title TransferOnion\n * @notice TransferOnion is a hash onion for distributing tokens. The shell commits\n * to an ordered list of the token transfers and can be permissionlessly\n * unwrapped in order. The SENDER must `approve` this contract as\n * `transferFrom` is used to move the token balances.\n */\ncontract TransferOnion is ReentrancyGuard {\n using SafeERC20 for ERC20;\n\n /**\n * @notice Struct representing a layer of the onion.\n */\n struct Layer {\n address recipient;\n uint256 amount;\n bytes32 shell;\n }\n\n /**\n * @notice Address of the token to distribute.\n */\n ERC20 public immutable TOKEN;\n\n /**\n * @notice Address of the account to distribute tokens from.\n */\n address public immutable SENDER;\n\n /**\n * @notice Current shell hash.\n */\n bytes32 public shell;\n\n /**\n * @param _token Address of the token to distribute.\n * @param _sender Address of the sender to distribute from.\n * @param _shell Initial shell of the onion.\n */\n constructor(\n ERC20 _token,\n address _sender,\n bytes32 _shell\n ) {\n TOKEN = _token;\n SENDER = _sender;\n shell = _shell;\n }\n\n /**\n * @notice Peels layers from the onion and distributes tokens.\n *\n * @param _layers Array of onion layers to peel.\n */\n function peel(Layer[] memory _layers) public nonReentrant {\n bytes32 tempShell = shell;\n uint256 length = _layers.length;\n for (uint256 i = 0; i < length; ) {\n Layer memory layer = _layers[i];\n\n // Confirm that the onion layer is correct.\n require(\n keccak256(abi.encode(layer.recipient, layer.amount, layer.shell)) == tempShell,\n \"TransferOnion: what are you doing in my swamp?\"\n );\n\n // Update the onion layer.\n tempShell = layer.shell;\n\n // Transfer the tokens.\n TOKEN.safeTransferFrom(SENDER, layer.recipient, layer.amount);\n\n // Unchecked increment to save some gas.\n unchecked {\n ++i;\n }\n }\n\n shell = tempShell;\n }\n}\n" - }, - "contracts/test/AddressAliasHelper.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract AddressAliasHelper_applyAndUndo_Test is Test {\n /**\n * @notice Tests that applying and then undoing an alias results in the original address.\n */\n function testFuzz_applyAndUndo_succeeds(address _address) external {\n address aliased = AddressAliasHelper.applyL1ToL2Alias(_address);\n address unaliased = AddressAliasHelper.undoL1ToL2Alias(aliased);\n assertEq(_address, unaliased);\n }\n}\n" - }, - "contracts/test/BenchmarkTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test } from \"forge-std/Test.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport \"./CommonTest.t.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\n// Free function for setting the prevBaseFee param in the OptimismPortal.\nfunction setPrevBaseFee(\n Vm _vm,\n address _op,\n uint128 _prevBaseFee\n) {\n _vm.store(address(_op), bytes32(uint256(1)), bytes32((block.number << 192) | _prevBaseFee));\n}\n\ncontract SetPrevBaseFee_Test is Portal_Initializer {\n function test_setPrevBaseFee_succeeds() external {\n setPrevBaseFee(vm, address(op), 100 gwei);\n (uint128 prevBaseFee, , uint64 prevBlockNum) = op.params();\n assertEq(uint256(prevBaseFee), 100 gwei);\n assertEq(uint256(prevBlockNum), block.number);\n }\n}\n\n// Tests for obtaining pure gas cost estimates for commonly used functions.\n// The objective with these benchmarks is to strip down the actual test functions\n// so that they are nothing more than the call we want measure the gas cost of.\n// In order to achieve this we make no assertions, and handle everything else in the setUp()\n// function.\ncontract GasBenchMark_OptimismPortal is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n bytes32 _outputRoot;\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n\n // Get withdrawal proof data we can use for testing.\n bytes32 _storageRoot;\n bytes32 _stateRoot;\n (_stateRoot, _storageRoot, _outputRoot, , _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public virtual override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n function test_depositTransaction_benchmark() external {\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_depositTransaction_benchmark_1() external {\n setPrevBaseFee(vm, address(op), 1 gwei);\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_proveWithdrawalTransaction_benchmark() external {\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n}\n\ncontract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer {\n function test_sendMessage_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n vm.resumeGasMetering();\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n\n function test_sendMessage_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n vm.resumeGasMetering();\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), alice, 100000, true);\n vm.startPrank(alice, alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n }\n\n function test_depositETH_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n vm.resumeGasMetering();\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositETH_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n vm.resumeGasMetering();\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositERC20_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n vm.resumeGasMetering();\n L1Bridge.bridgeERC20({\n _localToken: address(L1Token),\n _remoteToken: address(L2Token),\n _amount: 100,\n _minGasLimit: 100_000,\n _extraData: hex\"\"\n });\n }\n\n function test_depositERC20_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n vm.resumeGasMetering();\n L1Bridge.bridgeERC20({\n _localToken: address(L1Token),\n _remoteToken: address(L2Token),\n _amount: 100,\n _minGasLimit: 100_000,\n _extraData: hex\"\"\n });\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Finalize is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), address(L1Bridge), 100, true);\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.startPrank(address(L1Bridge.messenger()));\n vm.deal(address(L1Bridge.messenger()), 100);\n }\n\n function test_finalizeETHWithdrawal_benchmark() external {\n // TODO: Make this more accurate. It is underestimating the cost because it pranks\n // the call coming from the messenger, which bypasses the portal\n // and oracle.\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n\ncontract GasBenchMark_L2OutputOracle is L2OutputOracle_Initializer {\n uint256 nextBlockNumber;\n\n function setUp() public override {\n super.setUp();\n nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.startPrank(proposer);\n }\n\n function test_proposeL2Output_benchmark() external {\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n}\n" - }, - "contracts/test/Bytes.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Bytes } from \"../libraries/Bytes.sol\";\n\ncontract Bytes_slice_Test is Test {\n /**\n * @notice Tests that the `slice` function works as expected when starting from index 0.\n */\n function test_slice_fromZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check if all possible slices starting from index 0 are correct.\n assertEq(Bytes.slice(input, 0, 0), hex\"\");\n assertEq(Bytes.slice(input, 0, 1), hex\"11\");\n assertEq(Bytes.slice(input, 0, 2), hex\"1122\");\n assertEq(Bytes.slice(input, 0, 3), hex\"112233\");\n assertEq(Bytes.slice(input, 0, 4), hex\"11223344\");\n assertEq(Bytes.slice(input, 0, 5), hex\"1122334455\");\n assertEq(Bytes.slice(input, 0, 6), hex\"112233445566\");\n assertEq(Bytes.slice(input, 0, 7), hex\"11223344556677\");\n assertEq(Bytes.slice(input, 0, 8), hex\"1122334455667788\");\n assertEq(Bytes.slice(input, 0, 9), hex\"112233445566778899\");\n assertEq(Bytes.slice(input, 0, 10), hex\"11223344556677889900\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when starting from indices [1, 9]\n * with lengths [1, 9], in reverse order.\n */\n function test_slice_fromNonZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check correctness of slices starting from indexes [1, 9]\n // and spanning [1, 9] bytes, in reverse order\n assertEq(Bytes.slice(input, 9, 1), hex\"00\");\n assertEq(Bytes.slice(input, 8, 2), hex\"9900\");\n assertEq(Bytes.slice(input, 7, 3), hex\"889900\");\n assertEq(Bytes.slice(input, 6, 4), hex\"77889900\");\n assertEq(Bytes.slice(input, 5, 5), hex\"6677889900\");\n assertEq(Bytes.slice(input, 4, 6), hex\"556677889900\");\n assertEq(Bytes.slice(input, 3, 7), hex\"44556677889900\");\n assertEq(Bytes.slice(input, 2, 8), hex\"3344556677889900\");\n assertEq(Bytes.slice(input, 1, 9), hex\"223344556677889900\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when slicing between multiple words\n * in memory. In this case, we test that a 2 byte slice between the 32nd byte of the\n * first word and the 1st byte of the second word is correct.\n */\n function test_slice_acrossWords_works() public {\n bytes\n memory input = hex\"00000000000000000000000000000000000000000000000000000000000000112200000000000000000000000000000000000000000000000000000000000000\";\n\n assertEq(Bytes.slice(input, 31, 2), hex\"1122\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when slicing between multiple\n * words in memory. In this case, we test that a 34 byte slice between 3 separate words\n * returns the correct result.\n */\n function test_slice_acrossMultipleWords_works() public {\n bytes\n memory input = hex\"000000000000000000000000000000000000000000000000000000000000001122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1100000000000000000000000000000000000000000000000000000000000000\";\n bytes\n memory expected = hex\"1122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11\";\n\n assertEq(Bytes.slice(input, 31, 34), expected);\n }\n\n /**\n * @notice Tests that, when given an input bytes array of length `n`, the `slice` function will\n * always revert if `_start + _length > n`.\n */\n function testFuzz_slice_outOfBounds_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // We want a valid start index and a length that will not overflow.\n vm.assume(_start < _input.length && _length < type(uint256).max - 31);\n // But, we want an invalid slice length.\n vm.assume(_start + _length > _input.length);\n\n vm.expectRevert(\"slice_outOfBounds\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that, when given a length `n` that is greater than `type(uint256).max - 31`,\n * the `slice` function reverts.\n */\n function testFuzz_slice_lengthOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that the `_length` will overflow if a number >= 31 is added to it.\n vm.assume(_length > type(uint256).max - 31);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that, when given a start index `n` that is greater than\n * `type(uint256).max - n`, the `slice` function reverts.\n */\n function testFuzz_slice_rangeOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that `_length` is a realistic length of a slice. This is to make sure\n // we revert on the correct require statement.\n vm.assume(_length < _input.length);\n // Ensure that `_start` will overflow if `_length` is added to it.\n vm.assume(_start > type(uint256).max - _length);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that the `slice` function correctly updates the free memory pointer depending\n * on the length of the slice.\n */\n function testFuzz_slice_memorySafety_succeeds(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // The start should never be more than the length of the input bytes array - 1\n vm.assume(_start < _input.length);\n // The length should never be more than the length of the input bytes array - the starting\n // slice index.\n vm.assume(_length <= _input.length - _start);\n\n // Grab the free memory pointer before the slice operation\n uint64 initPtr;\n assembly {\n initPtr := mload(0x40)\n }\n uint64 expectedPtr = uint64(initPtr + 0x20 + ((_length + 0x1f) & ~uint256(0x1f)));\n\n // Ensure that all memory outside of the expected range is safe.\n vm.expectSafeMemory(initPtr, expectedPtr);\n\n // Slice the input bytes array from `_start` to `_start + _length`\n bytes memory slice = Bytes.slice(_input, _start, _length);\n\n // Grab the free memory pointer after the slice operation\n uint64 finalPtr;\n assembly {\n finalPtr := mload(0x40)\n }\n\n // The free memory pointer should have been updated properly\n if (_length == 0) {\n // If the slice length is zero, only 32 bytes of memory should have been allocated.\n assertEq(finalPtr, initPtr + 0x20);\n } else {\n // If the slice length is greater than zero, the memory allocated should be the\n // length of the slice rounded up to the next 32 byte word + 32 bytes for the\n // length of the byte array.\n //\n // Note that we use a slightly less efficient, but equivalent method of rounding\n // up `_length` to the next multiple of 32 than is used in the `slice` function.\n // This is to diff test the method used in `slice`.\n uint64 _expectedPtr = uint64(initPtr + 0x20 + (((_length + 0x1F) >> 5) << 5));\n assertEq(finalPtr, _expectedPtr);\n\n // Sanity check for equivalence of the rounding methods.\n assertEq(_expectedPtr, expectedPtr);\n }\n\n // The slice length should be equal to `_length`\n assertEq(slice.length, _length);\n }\n}\n\ncontract Bytes_toNibbles_Test is Test {\n /**\n * @notice Diffs the test Solidity version of `toNibbles` against the Yul version.\n *\n * @param _bytes The `bytes` array to convert to nibbles.\n *\n * @return Yul version of `toNibbles` applied to `_bytes`.\n */\n function _toNibblesYul(bytes memory _bytes) internal pure returns (bytes memory) {\n // Allocate memory for the `nibbles` array.\n bytes memory nibbles = new bytes(_bytes.length << 1);\n\n assembly {\n // Load the length of the passed bytes array from memory\n let bytesLength := mload(_bytes)\n\n // Store the memory offset of the _bytes array's contents on the stack\n let bytesStart := add(_bytes, 0x20)\n\n // Store the memory offset of the nibbles array's contents on the stack\n let nibblesStart := add(nibbles, 0x20)\n\n // Loop through each byte in the input array\n for {\n let i := 0x00\n } lt(i, bytesLength) {\n i := add(i, 0x01)\n } {\n // Get the starting offset of the next 2 bytes in the nibbles array\n let offset := add(nibblesStart, shl(0x01, i))\n\n // Load the byte at the current index within the `_bytes` array\n let b := byte(0x00, mload(add(bytesStart, i)))\n\n // Pull out the first nibble and store it in the new array\n mstore8(offset, shr(0x04, b))\n // Pull out the second nibble and store it in the new array\n mstore8(add(offset, 0x01), and(b, 0x0F))\n }\n }\n\n return nibbles;\n }\n\n /**\n * @notice Tests that, given an input of 5 bytes, the `toNibbles` function returns an array of\n * 10 nibbles corresponding to the input data.\n */\n function test_toNibbles_expectedResult5Bytes_works() public {\n bytes memory input = hex\"1234567890\";\n bytes memory expected = hex\"01020304050607080900\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Tests that, given an input of 128 bytes, the `toNibbles` function returns an array\n * of 256 nibbles corresponding to the input data. This test exists to ensure that,\n * given a large input, the `toNibbles` function works as expected.\n */\n function test_toNibbles_expectedResult128Bytes_works() public {\n bytes\n memory input = hex\"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f\";\n bytes\n memory expected = hex\"0000000100020003000400050006000700080009000a000b000c000d000e000f0100010101020103010401050106010701080109010a010b010c010d010e010f0200020102020203020402050206020702080209020a020b020c020d020e020f0300030103020303030403050306030703080309030a030b030c030d030e030f0400040104020403040404050406040704080409040a040b040c040d040e040f0500050105020503050405050506050705080509050a050b050c050d050e050f0600060106020603060406050606060706080609060a060b060c060d060e060f0700070107020703070407050706070707080709070a070b070c070d070e070f\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Tests that, given an input of 0 bytes, the `toNibbles` function returns a zero\n * length array.\n */\n function test_toNibbles_zeroLengthInput_works() public {\n bytes memory input = hex\"\";\n bytes memory expected = hex\"\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length, 0);\n assertEq(expected.length, 0);\n assertEq(actual.length, 0);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Test that the `toNibbles` function in the `Bytes` library is equivalent to the Yul\n * implementation.\n */\n function testDiff_toNibbles_succeeds(bytes memory _input) public {\n assertEq(Bytes.toNibbles(_input), _toNibblesYul(_input));\n }\n}\n\ncontract Bytes_equal_Test is Test {\n /**\n * @notice Manually checks equality of two dynamic `bytes` arrays in memory.\n *\n * @param _a The first `bytes` array to compare.\n * @param _b The second `bytes` array to compare.\n *\n * @return True if the two `bytes` arrays are equal in memory.\n */\n function manualEq(bytes memory _a, bytes memory _b) internal pure returns (bool) {\n bool _eq;\n assembly {\n _eq := and(\n // Check if the contents of the two bytes arrays are equal in memory.\n eq(keccak256(add(0x20, _a), mload(_a)), keccak256(add(0x20, _b), mload(_b))),\n // Check if the length of the two bytes arrays are equal in memory.\n // This is redundant given the above check, but included for completeness.\n eq(mload(_a), mload(_b))\n )\n }\n return _eq;\n }\n\n /**\n * @notice Tests that the `equal` function in the `Bytes` library returns `false` if given two\n * non-equal byte arrays.\n */\n function testFuzz_equal_notEqual_works(bytes memory _a, bytes memory _b) public {\n vm.assume(!manualEq(_a, _b));\n assertFalse(Bytes.equal(_a, _b));\n }\n\n /**\n * @notice Test whether or not the `equal` function in the `Bytes` library is equivalent to\n * manually checking equality of the two dynamic `bytes` arrays in memory.\n */\n function testDiff_equal_works(bytes memory _a, bytes memory _b) public {\n assertEq(Bytes.equal(_a, _b), manualEq(_a, _b));\n }\n}\n" - }, - "contracts/test/CommonTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test, StdUtils } from \"forge-std/Test.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { IL1ChugSplashDeployer } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { LegacyMintableERC20 } from \"../legacy/LegacyMintableERC20.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract CommonTest is Test {\n address alice = address(128);\n address bob = address(256);\n address multisig = address(512);\n\n address immutable ZERO_ADDRESS = address(0);\n address immutable NON_ZERO_ADDRESS = address(1);\n uint256 immutable NON_ZERO_VALUE = 100;\n uint256 immutable ZERO_VALUE = 0;\n uint64 immutable NON_ZERO_GASLIMIT = 50000;\n bytes32 nonZeroHash = keccak256(abi.encode(\"NON_ZERO\"));\n bytes NON_ZERO_DATA = hex\"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000\";\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n FFIInterface ffi;\n\n function setUp() public virtual {\n // Give alice and bob some ETH\n vm.deal(alice, 1 << 16);\n vm.deal(bob, 1 << 16);\n vm.deal(multisig, 1 << 16);\n\n vm.label(alice, \"alice\");\n vm.label(bob, \"bob\");\n vm.label(multisig, \"multisig\");\n\n // Make sure we have a non-zero base fee\n vm.fee(1000000000);\n\n ffi = new FFIInterface();\n }\n\n function emitTransactionDeposited(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) internal {\n emit TransactionDeposited(\n _from,\n _to,\n 0,\n abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data)\n );\n }\n}\n\ncontract L2OutputOracle_Initializer is CommonTest {\n // Test target\n L2OutputOracle oracle;\n L2OutputOracle oracleImpl;\n\n L2ToL1MessagePasser messagePasser =\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER));\n\n // Constructor arguments\n address internal proposer = 0x000000000000000000000000000000000000AbBa;\n address internal owner = 0x000000000000000000000000000000000000ACDC;\n uint256 internal submissionInterval = 1800;\n uint256 internal l2BlockTime = 2;\n uint256 internal startingBlockNumber = 200;\n uint256 internal startingTimestamp = 1000;\n address guardian;\n\n // Test data\n uint256 initL1Time;\n\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n // Advance the evm's time to meet the L2OutputOracle's requirements for proposeL2Output\n function warpToProposeTime(uint256 _nextBlockNumber) public {\n vm.warp(oracle.computeL2Timestamp(_nextBlockNumber) + 1);\n }\n\n function setUp() public virtual override {\n super.setUp();\n guardian = makeAddr(\"guardian\");\n\n // By default the first block has timestamp and number zero, which will cause underflows in the\n // tests, so we'll move forward to these block values.\n initL1Time = startingTimestamp + 1;\n vm.warp(initL1Time);\n vm.roll(startingBlockNumber);\n // Deploy the L2OutputOracle and transfer owernship to the proposer\n oracleImpl = new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: startingTimestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(oracleImpl),\n abi.encodeCall(L2OutputOracle.initialize, (startingBlockNumber, startingTimestamp))\n );\n oracle = L2OutputOracle(address(proxy));\n vm.label(address(oracle), \"L2OutputOracle\");\n\n // Set the L2ToL1MessagePasser at the correct address\n vm.etch(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(new L2ToL1MessagePasser()).code);\n\n vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, \"L2ToL1MessagePasser\");\n }\n}\n\ncontract Portal_Initializer is L2OutputOracle_Initializer {\n // Test target\n OptimismPortal internal opImpl;\n OptimismPortal internal op;\n SystemConfig systemConfig;\n\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n function setUp() public virtual override {\n super.setUp();\n\n ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();\n\n systemConfig = new SystemConfig({\n _owner: address(1),\n _overhead: 0,\n _scalar: 10000,\n _batcherHash: bytes32(0),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(0),\n _config: config\n });\n\n opImpl = new OptimismPortal({\n _l2Oracle: oracle,\n _guardian: guardian,\n _paused: true,\n _config: systemConfig\n });\n\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(opImpl),\n abi.encodeWithSelector(OptimismPortal.initialize.selector, false)\n );\n op = OptimismPortal(payable(address(proxy)));\n vm.label(address(op), \"OptimismPortal\");\n }\n}\n\ncontract Messenger_Initializer is Portal_Initializer {\n AddressManager internal addressManager;\n L1CrossDomainMessenger internal L1Messenger;\n L2CrossDomainMessenger internal L2Messenger =\n L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER);\n\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n\n event SentMessageExtension1(address indexed sender, uint256 value);\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event RelayedMessage(bytes32 indexed msgHash);\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 mint,\n uint256 value,\n uint64 gasLimit,\n bool isCreation,\n bytes data\n );\n\n event WhatHappened(bool success, bytes returndata);\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the address manager\n vm.prank(multisig);\n addressManager = new AddressManager();\n\n // Setup implementation\n L1CrossDomainMessenger L1MessengerImpl = new L1CrossDomainMessenger(op);\n\n // Setup the address manager and proxy\n vm.prank(multisig);\n addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(L1MessengerImpl));\n ResolvedDelegateProxy proxy = new ResolvedDelegateProxy(\n addressManager,\n \"OVM_L1CrossDomainMessenger\"\n );\n L1Messenger = L1CrossDomainMessenger(address(proxy));\n L1Messenger.initialize();\n\n vm.etch(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n address(new L2CrossDomainMessenger(address(L1Messenger))).code\n );\n\n L2Messenger.initialize();\n\n // Label addresses\n vm.label(address(addressManager), \"AddressManager\");\n vm.label(address(L1MessengerImpl), \"L1CrossDomainMessenger_Impl\");\n vm.label(address(L1Messenger), \"L1CrossDomainMessenger_Proxy\");\n vm.label(Predeploys.LEGACY_ERC20_ETH, \"LegacyERC20ETH\");\n vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, \"L2CrossDomainMessenger\");\n\n vm.label(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n \"L1CrossDomainMessenger_aliased\"\n );\n }\n}\n\ncontract Bridge_Initializer is Messenger_Initializer {\n L1StandardBridge L1Bridge;\n L2StandardBridge L2Bridge;\n OptimismMintableERC20Factory L2TokenFactory;\n OptimismMintableERC20Factory L1TokenFactory;\n ERC20 L1Token;\n ERC20 BadL1Token;\n OptimismMintableERC20 L2Token;\n LegacyMintableERC20 LegacyL2Token;\n ERC20 NativeL2Token;\n ERC20 BadL2Token;\n OptimismMintableERC20 RemoteL1Token;\n\n event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes data\n );\n\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFailed(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ETHBridgeInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n function setUp() public virtual override {\n super.setUp();\n\n vm.label(Predeploys.L2_STANDARD_BRIDGE, \"L2StandardBridge\");\n vm.label(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, \"OptimismMintableERC20Factory\");\n\n // Deploy the L1 bridge and initialize it with the address of the\n // L1CrossDomainMessenger\n L1ChugSplashProxy proxy = new L1ChugSplashProxy(multisig);\n vm.mockCall(\n multisig,\n abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector),\n abi.encode(true)\n );\n vm.startPrank(multisig);\n proxy.setCode(address(new L1StandardBridge(payable(address(L1Messenger)))).code);\n vm.clearMockedCalls();\n address L1Bridge_Impl = proxy.getImplementation();\n vm.stopPrank();\n\n L1Bridge = L1StandardBridge(payable(address(proxy)));\n\n vm.label(address(proxy), \"L1StandardBridge_Proxy\");\n vm.label(address(L1Bridge_Impl), \"L1StandardBridge_Impl\");\n\n // Deploy the L2StandardBridge, move it to the correct predeploy\n // address and then initialize it\n L2StandardBridge l2B = new L2StandardBridge(payable(proxy));\n vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(l2B).code);\n L2Bridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE));\n\n // Set up the L2 mintable token factory\n OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory(\n Predeploys.L2_STANDARD_BRIDGE\n );\n vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(factory).code);\n L2TokenFactory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY);\n\n vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code);\n\n L1Token = new ERC20(\"Native L1 Token\", \"L1T\");\n\n LegacyL2Token = new LegacyMintableERC20({\n _l2Bridge: address(L2Bridge),\n _l1Token: address(L1Token),\n _name: string.concat(\"LegacyL2-\", L1Token.name()),\n _symbol: string.concat(\"LegacyL2-\", L1Token.symbol())\n });\n vm.label(address(LegacyL2Token), \"LegacyMintableERC20\");\n\n // Deploy the L2 ERC20 now\n L2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(L1Token),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n BadL2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n NativeL2Token = new ERC20(\"Native L2 Token\", \"L2T\");\n L1TokenFactory = new OptimismMintableERC20Factory(address(L1Bridge));\n\n RemoteL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(NativeL2Token),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n\n BadL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n }\n}\n\ncontract ERC721Bridge_Initializer is Messenger_Initializer {\n L1ERC721Bridge L1Bridge;\n L2ERC721Bridge L2Bridge;\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the L1ERC721Bridge.\n L1Bridge = new L1ERC721Bridge(address(L1Messenger), Predeploys.L2_ERC721_BRIDGE);\n\n // Deploy the implementation for the L2ERC721Bridge and etch it into the predeploy address.\n vm.etch(\n Predeploys.L2_ERC721_BRIDGE,\n address(new L2ERC721Bridge(Predeploys.L2_CROSS_DOMAIN_MESSENGER, address(L1Bridge)))\n .code\n );\n\n // Set up a reference to the L2ERC721Bridge.\n L2Bridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE);\n\n // Label the L1 and L2 bridges.\n vm.label(address(L1Bridge), \"L1ERC721Bridge\");\n vm.label(address(L2Bridge), \"L2ERC721Bridge\");\n }\n}\n\ncontract FFIInterface is Test {\n function getProveWithdrawalTransactionInputs(Types.WithdrawalTransaction memory _tx)\n external\n returns (\n bytes32,\n bytes32,\n bytes32,\n bytes32,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"getProveWithdrawalTransactionInputs\";\n cmds[2] = vm.toString(_tx.nonce);\n cmds[3] = vm.toString(_tx.sender);\n cmds[4] = vm.toString(_tx.target);\n cmds[5] = vm.toString(_tx.value);\n cmds[6] = vm.toString(_tx.gasLimit);\n cmds[7] = vm.toString(_tx.data);\n\n bytes memory result = vm.ffi(cmds);\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = abi.decode(result, (bytes32, bytes32, bytes32, bytes32, bytes[]));\n\n return (stateRoot, storageRoot, outputRoot, withdrawalHash, withdrawalProof);\n }\n\n function hashCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashCrossDomainMessage\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashWithdrawal(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashWithdrawal\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashOutputRootProof(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external returns (bytes32) {\n string[] memory cmds = new string[](6);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashOutputRootProof\";\n cmds[2] = Strings.toHexString(uint256(_version));\n cmds[3] = Strings.toHexString(uint256(_stateRoot));\n cmds[4] = Strings.toHexString(uint256(_messagePasserStorageRoot));\n cmds[5] = Strings.toHexString(uint256(_latestBlockhash));\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashDepositTransaction(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint64 _logIndex\n ) external returns (bytes32) {\n string[] memory cmds = new string[](10);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashDepositTransaction\";\n cmds[2] = \"0x0000000000000000000000000000000000000000000000000000000000000000\";\n cmds[3] = vm.toString(_logIndex);\n cmds[4] = vm.toString(_from);\n cmds[5] = vm.toString(_to);\n cmds[6] = vm.toString(_mint);\n cmds[7] = vm.toString(_value);\n cmds[8] = vm.toString(_gas);\n cmds[9] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function encodeDepositTransaction(Types.UserDepositTransaction calldata txn)\n external\n returns (bytes memory)\n {\n string[] memory cmds = new string[](11);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"encodeDepositTransaction\";\n cmds[2] = vm.toString(txn.from);\n cmds[3] = vm.toString(txn.to);\n cmds[4] = vm.toString(txn.value);\n cmds[5] = vm.toString(txn.mint);\n cmds[6] = vm.toString(txn.gasLimit);\n cmds[7] = vm.toString(txn.isCreation);\n cmds[8] = vm.toString(txn.data);\n cmds[9] = vm.toString(txn.l1BlockHash);\n cmds[10] = vm.toString(txn.logIndex);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function encodeCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes memory) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"encodeCrossDomainMessage\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function decodeVersionedNonce(uint256 nonce) external returns (uint256, uint256) {\n string[] memory cmds = new string[](3);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"decodeVersionedNonce\";\n cmds[2] = vm.toString(nonce);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (uint256, uint256));\n }\n\n function getMerkleTrieFuzzCase(string memory variant)\n external\n returns (\n bytes32,\n bytes memory,\n bytes memory,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](5);\n cmds[0] = \"./test-case-generator/fuzz\";\n cmds[1] = \"-m\";\n cmds[2] = \"trie\";\n cmds[3] = \"-v\";\n cmds[4] = variant;\n\n return abi.decode(vm.ffi(cmds), (bytes32, bytes, bytes, bytes[]));\n }\n}\n\n// Used for testing a future upgrade beyond the current implementations.\n// We include some variables so that we can sanity check accessing storage values after an upgrade.\ncontract NextImpl is Initializable {\n // Initializable occupies the zero-th slot.\n bytes32 slot1;\n bytes32[19] __gap;\n bytes32 slot21;\n bytes32 public constant slot21Init = bytes32(hex\"1337\");\n\n function initialize() public reinitializer(2) {\n // Slot21 is unused by an of our upgradeable contracts.\n // This is used to verify that we can access this value after an upgrade.\n slot21 = slot21Init;\n }\n}\n\ncontract Reverter {\n fallback() external {\n revert();\n }\n}\n\n// Useful for testing reentrancy guards\ncontract CallerCaller {\n event WhatHappened(bool success, bytes returndata);\n\n fallback() external {\n (bool success, bytes memory returndata) = msg.sender.call(msg.data);\n emit WhatHappened(success, returndata);\n assembly {\n switch success\n case 0 {\n revert(add(returndata, 0x20), mload(returndata))\n }\n default {\n return(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n\n// Used for testing the `CrossDomainMessenger`'s per-message reentrancy guard.\ncontract ConfigurableCaller {\n bool doRevert = true;\n address target;\n bytes payload;\n\n event WhatHappened(bool success, bytes returndata);\n\n /**\n * @notice Call the configured target with the configured payload OR revert.\n */\n function call() external {\n if (doRevert) {\n revert(\"ConfigurableCaller: revert\");\n } else {\n (bool success, bytes memory returndata) = address(target).call(payload);\n emit WhatHappened(success, returndata);\n assembly {\n switch success\n case 0 {\n revert(add(returndata, 0x20), mload(returndata))\n }\n default {\n return(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n }\n\n /**\n * @notice Set whether or not to have `call` revert.\n */\n function setDoRevert(bool _doRevert) external {\n doRevert = _doRevert;\n }\n\n /**\n * @notice Set the target for the call made in `call`.\n */\n function setTarget(address _target) external {\n target = _target;\n }\n\n /**\n * @notice Set the payload for the call made in `call`.\n */\n function setPayload(bytes calldata _payload) external {\n payload = _payload;\n }\n\n /**\n * @notice Fallback function that reverts if `doRevert` is true.\n * Otherwise, it does nothing.\n */\n fallback() external {\n if (doRevert) {\n revert(\"ConfigurableCaller: revert\");\n }\n }\n}\n" - }, - "contracts/test/CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, CallerCaller, CommonTest } from \"./CommonTest.t.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\n\n// Libraries\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n// CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2\n// CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract.\ncontract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {\n // Ensure that baseGas passes for the max value of _minGasLimit,\n // this is about 4 Billion.\n function test_baseGas_succeeds() external view {\n L1Messenger.baseGas(hex\"ff\", type(uint32).max);\n }\n\n // Fuzz for other values which might cause a revert in baseGas.\n function testFuzz_baseGas_succeeds(uint32 _minGasLimit) external view {\n L1Messenger.baseGas(hex\"ff\", _minGasLimit);\n }\n\n /**\n * @notice The baseGas function should always return a value greater than\n * or equal to the minimum gas limit value on the OptimismPortal.\n * This guarantees that the messengers will always pass sufficient\n * gas to the OptimismPortal.\n */\n function testFuzz_baseGas_portalMinGasLimit_succeeds(bytes memory _data, uint32 _minGasLimit)\n external\n {\n vm.assume(_data.length <= type(uint64).max);\n uint64 baseGas = L1Messenger.baseGas(_data, _minGasLimit);\n uint64 minGasLimit = op.minimumGasLimit(uint64(_data.length));\n assertTrue(baseGas >= minGasLimit);\n }\n}\n\n/**\n * @title ExternalRelay\n * @notice A mock external contract called via the SafeCall inside\n * the CrossDomainMessenger's `relayMessage` function.\n */\ncontract ExternalRelay is CommonTest {\n address internal op;\n address internal fuzzedSender;\n L1CrossDomainMessenger internal L1Messenger;\n\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n constructor(L1CrossDomainMessenger _l1Messenger, address _op) {\n L1Messenger = _l1Messenger;\n op = _op;\n }\n\n /**\n * @notice Internal helper function to relay a message and perform assertions.\n */\n function _internalRelay(address _innerSender) internal {\n address initialSender = L1Messenger.xDomainMessageSender();\n\n bytes memory callMessage = getCallData();\n\n bytes32 hash = Hashing.hashCrossDomainMessage({\n _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n _sender: _innerSender,\n _target: address(this),\n _value: 0,\n _gasLimit: 0,\n _data: callMessage\n });\n\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n vm.prank(address(op));\n L1Messenger.relayMessage({\n _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n _sender: _innerSender,\n _target: address(this),\n _value: 0,\n _minGasLimit: 0,\n _message: callMessage\n });\n\n assertTrue(L1Messenger.failedMessages(hash));\n assertFalse(L1Messenger.successfulMessages(hash));\n assertEq(initialSender, L1Messenger.xDomainMessageSender());\n }\n\n /**\n * @notice externalCallWithMinGas is called by the CrossDomainMessenger.\n */\n function externalCallWithMinGas() external payable {\n for (uint256 i = 0; i < 10; i++) {\n address _innerSender;\n unchecked {\n _innerSender = address(uint160(uint256(uint160(fuzzedSender)) + i));\n }\n _internalRelay(_innerSender);\n }\n }\n\n /**\n * @notice Helper function to get the callData for an `externalCallWithMinGas\n */\n function getCallData() public pure returns (bytes memory) {\n return abi.encodeWithSelector(ExternalRelay.externalCallWithMinGas.selector);\n }\n\n /**\n * @notice Helper function to set the fuzzed sender\n */\n function setFuzzedSender(address _fuzzedSender) public {\n fuzzedSender = _fuzzedSender;\n }\n}\n\n/**\n * @title CrossDomainMessenger_RelayMessage_Test\n * @notice Fuzz tests re-entrancy into the CrossDomainMessenger relayMessage function.\n */\ncontract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n ExternalRelay public er;\n\n function setUp() public override {\n super.setUp();\n er = new ExternalRelay(L1Messenger, address(op));\n }\n\n /**\n * @dev This test mocks an OptimismPortal call to the L1CrossDomainMessenger via\n * the relayMessage function. The relayMessage function will then use SafeCall's\n * callWithMinGas to call the target with call data packed in the callMessage.\n * For this test, the callWithMinGas will call the mock ExternalRelay test contract\n * defined above, executing the externalCallWithMinGas function which will try to\n * re-enter the CrossDomainMessenger's relayMessage function, resulting in that message\n * being recorded as failed.\n */\n function testFuzz_relayMessageReenter_succeeds(address _sender, uint256 _gasLimit) external {\n vm.assume(_sender != Predeploys.L2_CROSS_DOMAIN_MESSENGER);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n er.setFuzzedSender(_sender);\n address target = address(er);\n bytes memory callMessage = er.getCallData();\n\n vm.expectCall(target, callMessage);\n\n uint64 gasLimit = uint64(bound(_gasLimit, 0, 30_000_000));\n\n bytes32 hash = Hashing.hashCrossDomainMessage({\n _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n _sender: sender,\n _target: target,\n _value: 0,\n _gasLimit: gasLimit,\n _data: callMessage\n });\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n L1Messenger.relayMessage({\n _nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n _sender: sender,\n _target: target,\n _value: 0,\n _minGasLimit: gasLimit,\n _message: callMessage\n });\n\n assertTrue(L1Messenger.successfulMessages(hash));\n assertEq(L1Messenger.failedMessages(hash), false);\n\n // Ensures that the `xDomainMsgSender` is set back to `Predeploys.L2_CROSS_DOMAIN_MESSENGER`\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest, Portal_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable } from \"../L2/CrossDomainOwnable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Vm, VmSafe } from \"forge-std/Vm.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract XDomainSetter is CrossDomainOwnable {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable_Test is CommonTest {\n XDomainSetter setter;\n\n function setUp() public override {\n super.setUp();\n setter = new XDomainSetter();\n }\n\n // Check that the revert message is correct\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable: caller is not the owner\");\n setter.set(1);\n }\n\n // Check that making a call can set the value properly\n function test_onlyOwner_succeeds() external {\n assertEq(setter.value(), 0);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(setter.owner()));\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n\ncontract CrossDomainOwnableThroughPortal_Test is Portal_Initializer {\n XDomainSetter setter;\n\n function setUp() public override {\n super.setUp();\n\n vm.prank(alice);\n setter = new XDomainSetter();\n }\n\n function test_depositTransaction_crossDomainOwner_succeeds() external {\n vm.recordLogs();\n\n vm.prank(alice);\n op.depositTransaction({\n _to: address(setter),\n _value: 0,\n _gasLimit: 30_000,\n _isCreation: false,\n _data: abi.encodeWithSelector(XDomainSetter.set.selector, 1)\n });\n\n // Simulate the operation of the `op-node` by parsing data\n // from logs\n VmSafe.Log[] memory logs = vm.getRecordedLogs();\n // Only 1 log emitted\n assertEq(logs.length, 1);\n\n VmSafe.Log memory log = logs[0];\n\n // It is the expected topic\n bytes32 topic = log.topics[0];\n assertEq(topic, keccak256(\"TransactionDeposited(address,address,uint256,bytes)\"));\n\n // from is indexed and the first argument to the event.\n bytes32 _from = log.topics[1];\n address from = Bytes32AddressLib.fromLast20Bytes(_from);\n\n assertEq(AddressAliasHelper.undoL1ToL2Alias(from), alice);\n\n // Make a call from the \"from\" value received from the log.\n // In theory the opaque data could be parsed from the log\n // and passed to a low level call to \"to\", but calling set\n // directly on the setter is good enough.\n vm.prank(from);\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable2.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\nimport { CommonTest, Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable2 } from \"../L2/CrossDomainOwnable2.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract XDomainSetter2 is CrossDomainOwnable2 {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable2_Test is Messenger_Initializer {\n XDomainSetter2 setter;\n\n function setUp() public override {\n super.setUp();\n vm.prank(alice);\n setter = new XDomainSetter2();\n }\n\n function test_onlyOwner_notMessenger_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the messenger\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n // set the xDomainMsgSender storage slot\n bytes32 key = bytes32(uint256(204));\n bytes32 value = Bytes32AddressLib.fillLast12Bytes(address(alice));\n vm.store(address(L2Messenger), key, value);\n\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the owner\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner2_reverts() external {\n uint240 nonce = 0;\n address sender = bob;\n address target = address(setter);\n uint256 value = 0;\n uint256 minGasLimit = 0;\n bytes memory message = abi.encodeWithSelector(XDomainSetter2.set.selector, 1);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n // It should be a failed message. The revert is caught,\n // so we cannot expectRevert here.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n assertEq(setter.value(), 0);\n }\n\n function test_onlyOwner_succeeds() external {\n address owner = setter.owner();\n\n // Simulate the L2 execution where the call is coming from\n // the L1CrossDomainMessenger\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(1, 1),\n owner,\n address(setter),\n 0,\n 0,\n abi.encodeWithSelector(XDomainSetter2.set.selector, 2)\n );\n\n assertEq(setter.value(), 2);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable3.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\nimport { CommonTest, Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable3 } from \"../L2/CrossDomainOwnable3.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract XDomainSetter3 is CrossDomainOwnable3 {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable3_Test is Messenger_Initializer {\n XDomainSetter3 setter;\n\n /**\n * @notice OpenZeppelin Ownable.sol transferOwnership event\n */\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @notice CrossDomainOwnable3.sol transferOwnership event\n */\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner,\n bool isLocal\n );\n\n function setUp() public override {\n super.setUp();\n vm.prank(alice);\n setter = new XDomainSetter3();\n }\n\n function test_constructor_succeeds() public {\n assertEq(setter.owner(), alice);\n assertEq(setter.isLocal(), true);\n }\n\n function test_localOnlyOwner_notOwner_reverts() public {\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.set(1);\n }\n\n function test_transferOwnership_notOwner_reverts() public {\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.transferOwnership({ _owner: bob, _isLocal: true });\n }\n\n function test_crossDomainOnlyOwner_notOwner_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n // set the xDomainMsgSender storage slot\n bytes32 key = bytes32(uint256(204));\n bytes32 value = Bytes32AddressLib.fillLast12Bytes(bob);\n vm.store(address(L2Messenger), key, value);\n\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.set(1);\n }\n\n function test_crossDomainOnlyOwner_notOwner2_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n assertEq(setter.isLocal(), false);\n\n uint240 nonce = 0;\n address sender = bob;\n address target = address(setter);\n uint256 value = 0;\n uint256 minGasLimit = 0;\n bytes memory message = abi.encodeWithSelector(XDomainSetter3.set.selector, 1);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n // It should be a failed message. The revert is caught,\n // so we cannot expectRevert here.\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit FailedRelayedMessage(hash);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n assertEq(setter.value(), 0);\n }\n\n function test_crossDomainOnlyOwner_notMessenger_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the messenger\");\n setter.set(1);\n }\n\n function test_transferOwnership_zeroAddress_reverts() public {\n vm.prank(setter.owner());\n vm.expectRevert(\"CrossDomainOwnable3: new owner is the zero address\");\n setter.transferOwnership({ _owner: address(0), _isLocal: true });\n }\n\n function test_transferOwnership_noLocalZeroAddress_reverts() public {\n vm.prank(setter.owner());\n vm.expectRevert(\"Ownable: new owner is the zero address\");\n setter.transferOwnership(address(0));\n }\n\n function test_localOnlyOwner_succeeds() public {\n assertEq(setter.isLocal(), true);\n vm.prank(setter.owner());\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n\n function test_localTransferOwnership_succeeds() public {\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n emit OwnershipTransferred(alice, bob, true);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: bob, _isLocal: true });\n\n assertEq(setter.isLocal(), true);\n\n vm.prank(bob);\n setter.set(2);\n assertEq(setter.value(), 2);\n }\n\n /**\n * @notice The existing transferOwnership(address) method\n * still exists on the contract\n */\n function test_transferOwnershipNoLocal_succeeds() public {\n bool isLocal = setter.isLocal();\n\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n\n vm.prank(setter.owner());\n setter.transferOwnership(bob);\n\n // isLocal has not changed\n assertEq(setter.isLocal(), isLocal);\n\n vm.prank(bob);\n setter.set(2);\n assertEq(setter.value(), 2);\n }\n\n function test_crossDomainTransferOwnership_succeeds() public {\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n emit OwnershipTransferred(alice, bob, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: bob, _isLocal: false });\n\n assertEq(setter.isLocal(), false);\n\n // Simulate the L2 execution where the call is coming from\n // the L1CrossDomainMessenger\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(1, 1),\n bob,\n address(setter),\n 0,\n 0,\n abi.encodeWithSelector(XDomainSetter3.set.selector, 2)\n );\n\n assertEq(setter.value(), 2);\n }\n}\n" - }, - "contracts/test/DeployerWhitelist.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { DeployerWhitelist } from \"../legacy/DeployerWhitelist.sol\";\n\ncontract DeployerWhitelist_Test is CommonTest {\n DeployerWhitelist list;\n\n function setUp() public virtual override {\n list = new DeployerWhitelist();\n }\n\n // The owner should be address(0)\n function test_owner_succeeds() external {\n assertEq(list.owner(), address(0));\n }\n\n // The storage slot for the owner must be the same\n function test_storageSlots_succeeds() external {\n vm.prank(list.owner());\n list.setOwner(address(1));\n\n assertEq(bytes32(uint256(1)), vm.load(address(list), bytes32(uint256(0))));\n }\n}\n" - }, - "contracts/test/Encoding.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { LegacyCrossDomainUtils } from \"../libraries/LegacyCrossDomainUtils.sol\";\n\ncontract Encoding_Test is CommonTest {\n function testFuzz_nonceVersioning_succeeds(uint240 _nonce, uint16 _version) external {\n (uint240 nonce, uint16 version) = Encoding.decodeVersionedNonce(\n Encoding.encodeVersionedNonce(_nonce, _version)\n );\n assertEq(version, _version);\n assertEq(nonce, _nonce);\n }\n\n function testDiff_decodeVersionedNonce_succeeds(uint240 _nonce, uint16 _version) external {\n uint256 nonce = uint256(Encoding.encodeVersionedNonce(_nonce, _version));\n (uint256 decodedNonce, uint256 decodedVersion) = ffi.decodeVersionedNonce(nonce);\n\n assertEq(_version, uint16(decodedVersion));\n\n assertEq(_nonce, uint240(decodedNonce));\n }\n\n function testDiff_encodeCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint8 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint8 version = _version % 2;\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes memory encoding = Encoding.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n bytes memory _encoding = ffi.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n assertEq(encoding, _encoding);\n }\n\n function testFuzz_encodeCrossDomainMessageV0_matchesLegacy_succeeds(\n uint240 _nonce,\n address _sender,\n address _target,\n bytes memory _data\n ) external {\n uint8 version = 0;\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes memory legacyEncoding = LegacyCrossDomainUtils.encodeXDomainCalldata(\n _target,\n _sender,\n _data,\n nonce\n );\n\n bytes memory bedrockEncoding = Encoding.encodeCrossDomainMessageV0(\n _target,\n _sender,\n _data,\n nonce\n );\n\n assertEq(legacyEncoding, bedrockEncoding);\n }\n\n function testDiff_encodeDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bool isCreate,\n bytes memory _data,\n uint64 _logIndex\n ) external {\n Types.UserDepositTransaction memory t = Types.UserDepositTransaction(\n _from,\n _to,\n isCreate,\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n );\n\n bytes memory txn = Encoding.encodeDepositTransaction(t);\n bytes memory _txn = ffi.encodeDepositTransaction(t);\n\n assertEq(txn, _txn);\n }\n}\n" - }, - "contracts/test/FeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { L1FeeVault } from \"../L2/L1FeeVault.sol\";\nimport { BaseFeeVault } from \"../L2/BaseFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n// Test the implementations of the FeeVault\ncontract FeeVault_Test is Bridge_Initializer {\n BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT));\n L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT));\n\n address constant recipient = address(0x10000);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.BASE_FEE_VAULT, address(new BaseFeeVault(recipient)).code);\n vm.etch(Predeploys.L1_FEE_VAULT, address(new L1FeeVault(recipient)).code);\n\n vm.label(Predeploys.BASE_FEE_VAULT, \"BaseFeeVault\");\n vm.label(Predeploys.L1_FEE_VAULT, \"L1FeeVault\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(baseFeeVault.RECIPIENT(), recipient);\n assertEq(l1FeeVault.RECIPIENT(), recipient);\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n}\n" - }, - "contracts/test/GasPriceOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GasPriceOracle } from \"../L2/GasPriceOracle.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract GasPriceOracle_Test is CommonTest {\n event OverheadUpdated(uint256);\n event ScalarUpdated(uint256);\n event DecimalsUpdated(uint256);\n\n GasPriceOracle gasOracle;\n L1Block l1Block;\n address depositor;\n\n // set the initial L1 context values\n uint64 constant number = 10;\n uint64 constant timestamp = 11;\n uint256 constant basefee = 100;\n bytes32 constant hash = bytes32(uint256(64));\n uint64 constant sequenceNumber = 0;\n bytes32 constant batcherHash = bytes32(uint256(777));\n uint256 constant l1FeeOverhead = 310;\n uint256 constant l1FeeScalar = 10;\n\n function setUp() public virtual override {\n super.setUp();\n // place the L1Block contract at the predeploy address\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n\n l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n depositor = l1Block.DEPOSITOR_ACCOUNT();\n\n // We are not setting the gas oracle at its predeploy\n // address for simplicity purposes. Nothing in this test\n // requires it to be at a particular address\n gasOracle = new GasPriceOracle();\n\n vm.prank(depositor);\n l1Block.setL1BlockValues({\n _number: number,\n _timestamp: timestamp,\n _basefee: basefee,\n _hash: hash,\n _sequenceNumber: sequenceNumber,\n _batcherHash: batcherHash,\n _l1FeeOverhead: l1FeeOverhead,\n _l1FeeScalar: l1FeeScalar\n });\n }\n\n function test_l1BaseFee_succeeds() external {\n assertEq(gasOracle.l1BaseFee(), basefee);\n }\n\n function test_gasPrice_succeeds() external {\n vm.fee(100);\n uint256 gasPrice = gasOracle.gasPrice();\n assertEq(gasPrice, 100);\n }\n\n function test_baseFee_succeeds() external {\n vm.fee(64);\n uint256 gasPrice = gasOracle.baseFee();\n assertEq(gasPrice, 64);\n }\n\n function test_scalar_succeeds() external {\n assertEq(gasOracle.scalar(), l1FeeScalar);\n }\n\n function test_overhead_succeeds() external {\n assertEq(gasOracle.overhead(), l1FeeOverhead);\n }\n\n function test_decimals_succeeds() external {\n assertEq(gasOracle.decimals(), 6);\n assertEq(gasOracle.DECIMALS(), 6);\n }\n\n // Removed in bedrock\n function test_setGasPrice_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setGasPrice(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n\n // Removed in bedrock\n function test_setL1BaseFee_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setL1BaseFee(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n}\n" - }, - "contracts/test/GovernanceToken.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract GovernanceToken_Test is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n\n function setUp() public virtual override {\n super.setUp();\n vm.prank(owner);\n gov = new GovernanceToken();\n }\n\n function test_constructor_succeeds() external {\n assertEq(gov.owner(), owner);\n assertEq(gov.name(), \"Optimism\");\n assertEq(gov.symbol(), \"OP\");\n assertEq(gov.decimals(), 18);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_mint_fromOwner_succeeds() external {\n // Mint 100 tokens.\n vm.prank(owner);\n gov.mint(owner, 100);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 100);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_mint_fromNotOwner_reverts() external {\n // Mint 100 tokens as rando.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n gov.mint(owner, 100);\n\n // Balance does not update.\n assertEq(gov.balanceOf(owner), 0);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_burn_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando burns their tokens.\n vm.prank(rando);\n gov.burn(50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_burnFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to burn 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner burns 50 tokens from rando.\n vm.prank(owner);\n gov.burnFrom(rando, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_transfer_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando transfers 50 tokens to owner.\n vm.prank(rando);\n gov.transfer(owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_approve_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n\n function test_transferFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner transfers 50 tokens from rando to owner.\n vm.prank(owner);\n gov.transferFrom(rando, owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_increaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Rando increases allowance by 50 tokens.\n vm.prank(rando);\n gov.increaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 100);\n }\n\n function test_decreaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 100 tokens.\n vm.prank(rando);\n gov.approve(owner, 100);\n\n // Rando decreases allowance by 50 tokens.\n vm.prank(rando);\n gov.decreaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n}\n" - }, - "contracts/test/Hashing.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { LegacyCrossDomainUtils } from \"../libraries/LegacyCrossDomainUtils.sol\";\n\ncontract Hashing_hashDepositSource_Test is CommonTest {\n /**\n * @notice Tests that hashDepositSource returns the correct hash in a simple case.\n */\n function test_hashDepositSource_succeeds() external {\n assertEq(\n Hashing.hashDepositSource(\n 0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959,\n 0x1\n ),\n 0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc\n );\n }\n}\n\ncontract Hashing_hashCrossDomainMessage_Test is CommonTest {\n /**\n * @notice Tests that hashCrossDomainMessage returns the correct hash in a simple case.\n */\n function testDiff_hashCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint16 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n // Ensure the version is valid.\n uint16 version = uint16(bound(uint256(_version), 0, 1));\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n assertEq(\n Hashing.hashCrossDomainMessage(nonce, _sender, _target, _value, _gasLimit, _data),\n ffi.hashCrossDomainMessage(nonce, _sender, _target, _value, _gasLimit, _data)\n );\n }\n\n /**\n * @notice Tests that hashCrossDomainMessageV0 matches the hash of the legacy encoding.\n */\n function testFuzz_hashCrossDomainMessageV0_matchesLegacy_succeeds(\n address _target,\n address _sender,\n bytes memory _message,\n uint256 _messageNonce\n ) external {\n assertEq(\n keccak256(\n LegacyCrossDomainUtils.encodeXDomainCalldata(\n _target,\n _sender,\n _message,\n _messageNonce\n )\n ),\n Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _messageNonce)\n );\n }\n}\n\ncontract Hashing_hashWithdrawal_Test is CommonTest {\n /**\n * @notice Tests that hashWithdrawal returns the correct hash in a simple case.\n */\n function testDiff_hashWithdrawal_succeeds(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n assertEq(\n Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(_nonce, _sender, _target, _value, _gasLimit, _data)\n ),\n ffi.hashWithdrawal(_nonce, _sender, _target, _value, _gasLimit, _data)\n );\n }\n}\n\ncontract Hashing_hashOutputRootProof_Test is CommonTest {\n /**\n * @notice Tests that hashOutputRootProof returns the correct hash in a simple case.\n */\n function testDiff_hashOutputRootProof_succeeds(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external {\n assertEq(\n Hashing.hashOutputRootProof(\n Types.OutputRootProof({\n version: _version,\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _messagePasserStorageRoot,\n latestBlockhash: _latestBlockhash\n })\n ),\n ffi.hashOutputRootProof(\n _version,\n _stateRoot,\n _messagePasserStorageRoot,\n _latestBlockhash\n )\n );\n }\n}\n\ncontract Hashing_hashDepositTransaction_Test is CommonTest {\n /**\n * @notice Tests that hashDepositTransaction returns the correct hash in a simple case.\n */\n function testDiff_hashDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint64 _logIndex\n ) external {\n assertEq(\n Hashing.hashDepositTransaction(\n Types.UserDepositTransaction(\n _from,\n _to,\n false, // isCreate\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n )\n ),\n ffi.hashDepositTransaction(_from, _to, _mint, _value, _gas, _data, _logIndex)\n );\n }\n}\n" - }, - "contracts/test/L1Block.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\ncontract L1BlockTest is CommonTest {\n L1Block lb;\n address depositor;\n bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1));\n\n function setUp() public virtual override {\n super.setUp();\n lb = new L1Block();\n depositor = lb.DEPOSITOR_ACCOUNT();\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: uint64(1),\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: NON_ZERO_HASH,\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(0),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function testFuzz_updatesValues_succeeds(\n uint64 n,\n uint64 t,\n uint256 b,\n bytes32 h,\n uint64 s,\n bytes32 bt,\n uint256 fo,\n uint256 fs\n ) external {\n vm.prank(depositor);\n lb.setL1BlockValues(n, t, b, h, s, bt, fo, fs);\n assertEq(lb.number(), n);\n assertEq(lb.timestamp(), t);\n assertEq(lb.basefee(), b);\n assertEq(lb.hash(), h);\n assertEq(lb.sequenceNumber(), s);\n assertEq(lb.batcherHash(), bt);\n assertEq(lb.l1FeeOverhead(), fo);\n assertEq(lb.l1FeeScalar(), fs);\n }\n\n function test_number_succeeds() external {\n assertEq(lb.number(), uint64(1));\n }\n\n function test_timestamp_succeeds() external {\n assertEq(lb.timestamp(), uint64(2));\n }\n\n function test_basefee_succeeds() external {\n assertEq(lb.basefee(), 3);\n }\n\n function test_hash_succeeds() external {\n assertEq(lb.hash(), NON_ZERO_HASH);\n }\n\n function test_sequenceNumber_succeeds() external {\n assertEq(lb.sequenceNumber(), uint64(4));\n }\n\n function test_updateValues_succeeds() external {\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: type(uint64).max,\n _timestamp: type(uint64).max,\n _basefee: type(uint256).max,\n _hash: keccak256(abi.encode(1)),\n _sequenceNumber: type(uint64).max,\n _batcherHash: bytes32(type(uint256).max),\n _l1FeeOverhead: type(uint256).max,\n _l1FeeScalar: type(uint256).max\n });\n }\n}\n" - }, - "contracts/test/L1BlockNumber.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { L1BlockNumber } from \"../legacy/L1BlockNumber.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract L1BlockNumberTest is Test {\n L1Block lb;\n L1BlockNumber bn;\n\n uint64 constant number = 99;\n\n function setUp() external {\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n lb = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n bn = new L1BlockNumber();\n vm.prank(lb.DEPOSITOR_ACCOUNT());\n\n lb.setL1BlockValues({\n _number: number,\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: bytes32(uint256(10)),\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(uint256(0)),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function test_getL1BlockNumber_succeeds() external {\n assertEq(bn.getL1BlockNumber(), number);\n }\n\n function test_fallback_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n\n function test_receive_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call{ value: 1 }(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n}\n" - }, - "contracts/test/L1CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Messenger_Initializer, Reverter, ConfigurableCaller } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle_Initializer } from \"./L2OutputOracle.t.sol\";\n\n/* Libraries */\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n/* Target contract dependencies */\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/* Target contract */\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\n\ncontract L1CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n // the version is encoded in the nonce\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L1Messenger.messageNonce());\n assertEq(version, L1Messenger.MESSAGE_VERSION());\n }\n\n // sendMessage: should be able to send a single message\n // TODO: this same test needs to be done with the legacy message type\n // by setting the message version to 0\n function test_sendMessage_succeeds() external {\n // deposit transaction on the optimism portal should be called\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n )\n );\n\n // TransactionDeposited event\n vm.expectEmit(true, true, true, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n );\n\n // SentMessage event\n vm.expectEmit(true, true, true, true);\n emit SentMessage(recipient, alice, hex\"ff\", L1Messenger.messageNonce(), 100);\n\n // SentMessageExtension1 event\n vm.expectEmit(true, true, true, true);\n emit SentMessageExtension1(alice, 0);\n\n vm.prank(alice);\n L1Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n // sendMessage: should be able to send the same message twice\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L1Messenger.messageNonce());\n }\n\n function test_xDomainSender_notSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(address(op));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 2 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n // relayMessage: should send a successful call to the target contract\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.expectCall(target, hex\"1111\");\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L1Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n // set the target to be the OptimismPortal\n address target = address(op);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.prank(address(op));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n\n vm.store(address(op), 0, bytes32(abi.encode(sender)));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: should revert if eth is sent from a contract other than the standard bridge\n function test_replayMessage_withValue_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.expectRevert(\n \"CrossDomainMessenger: value must be zero unless message is from a system address\"\n );\n L1Messenger.relayMessage{ value: 100 }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n vm.expectCall(target, hex\"1111\");\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n function test_relayMessage_legacy_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyOldReplay_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Mark legacy message as already relayed.\n uint256 successfulMessagesSlot = 203;\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(target, sender, hex\"1111\", 0);\n bytes32 slot = keccak256(abi.encode(oldHash, successfulMessagesSlot));\n vm.store(address(L1Messenger), slot, bytes32(uint256(1)));\n\n // Expect revert.\n vm.expectRevert(\"CrossDomainMessenger: legacy withdrawal already relayed\");\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was not relayed.\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyRetryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect FailedRelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n function test_relayMessage_legacyRetryAfterSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message has already been relayed\");\n\n // Retry the message again.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n}\n" - }, - "contracts/test/L1ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.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\ncontract L1ERC721Bridge_Test is Messenger_Initializer {\n TestERC721 internal localToken;\n TestERC721 internal remoteToken;\n L1ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L1ERC721Bridge(address(L1Messenger), otherBridge);\n localToken = new TestERC721();\n remoteToken = new TestERC721();\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L1ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L1Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L1Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L1ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L1ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notEscrowed_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n" - }, - "contracts/test/L1StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\n\ncontract L1StandardBridge_Getter_Test is Bridge_Initializer {\n function test_getters_succeeds() external {\n assert(L1Bridge.l2TokenBridge() == address(L2Bridge));\n assert(L1Bridge.OTHER_BRIDGE() == L2Bridge);\n assert(L1Bridge.messenger() == L1Messenger);\n assert(L1Bridge.MESSENGER() == L1Messenger);\n assertEq(L1Bridge.version(), \"1.1.0\");\n }\n}\n\ncontract L1StandardBridge_Initialize_Test is Bridge_Initializer {\n function test_initialize_succeeds() external {\n assertEq(address(L1Bridge.messenger()), address(L1Messenger));\n\n assertEq(address(L1Bridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE);\n\n assertEq(address(L2Bridge), Predeploys.L2_STANDARD_BRIDGE);\n }\n}\n\ncontract L1StandardBridge_Initialize_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_Receive_Test is Bridge_Initializer {\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(op).balance, 0);\n\n // The legacy event must be emitted for backwards compatibility\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 100,\n hex\"\"\n ),\n 200_000\n )\n );\n\n vm.prank(alice, alice);\n (bool success, ) = address(L1Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(op).balance, 100);\n }\n}\n\ncontract L1StandardBridge_Receive_TestFail {}\n\ncontract PreBridgeETH is Bridge_Initializer {\n function _preBridgeETH(bool isLegacy) internal {\n assertEq(address(op).balance, 0);\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 500,\n hex\"dead\"\n );\n\n if (isLegacy) {\n vm.expectCall(\n address(L1Bridge),\n 500,\n abi.encodeWithSelector(L1Bridge.depositETH.selector, 50000, hex\"dead\")\n );\n } else {\n vm.expectCall(\n address(L1Bridge),\n 500,\n abi.encodeWithSelector(L1Bridge.bridgeETH.selector, 50000, hex\"dead\")\n );\n }\n vm.expectCall(\n address(L1Messenger),\n 500,\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 50000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 500,\n 50000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 50000);\n vm.expectCall(\n address(op),\n 500,\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 500,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(500),\n uint256(500),\n baseGas,\n false,\n innerMessage\n );\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, alice, 500, hex\"dead\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, alice, 500, hex\"dead\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 50000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 500);\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L1StandardBridge_DepositETH_Test is PreBridgeETH {\n // depositETH\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_depositETH_succeeds() external {\n _preBridgeETH({ isLegacy: true });\n L1Bridge.depositETH{ value: 500 }(50000, hex\"dead\");\n assertEq(address(op).balance, 500);\n }\n}\n\ncontract L1StandardBridge_BridgeETH_Test is PreBridgeETH {\n // BridgeETH\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_bridgeETH_succeeds() external {\n _preBridgeETH({ isLegacy: false });\n L1Bridge.bridgeETH{ value: 500 }(50000, hex\"dead\");\n assertEq(address(op).balance, 500);\n }\n}\n\ncontract L1StandardBridge_DepositETH_TestFail is Bridge_Initializer {\n function test_depositETH_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, address(L1Token).code);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice);\n L1Bridge.depositETH{ value: 1 }(300, hex\"\");\n }\n}\n\ncontract PreBridgeETHTo is Bridge_Initializer {\n function _preBridgeETHTo(bool isLegacy) internal {\n assertEq(address(op).balance, 0);\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n if (isLegacy) {\n vm.expectCall(\n address(L1Bridge),\n 600,\n abi.encodeWithSelector(L1Bridge.depositETHTo.selector, bob, 60000, hex\"dead\")\n );\n } else {\n vm.expectCall(\n address(L1Bridge),\n 600,\n abi.encodeWithSelector(L1Bridge.bridgeETHTo.selector, bob, 60000, hex\"dead\")\n );\n }\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n bob,\n 600,\n hex\"dead\"\n );\n\n // the L1 bridge should call\n // L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 60000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 600,\n 60000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 60000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 600,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(600),\n uint256(600),\n baseGas,\n false,\n innerMessage\n );\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, bob, 600, hex\"dead\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, bob, 600, hex\"dead\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 60000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 600);\n\n // deposit eth to bob\n vm.prank(alice, alice);\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_Test is PreBridgeETHTo {\n // depositETHTo\n // - emits ETHDepositInitiated\n // - calls optimismPortal.depositTransaction\n // - EOA or contract can call\n // - ETH ends up in the optimismPortal\n function test_depositETHTo_succeeds() external {\n _preBridgeETHTo({ isLegacy: true });\n L1Bridge.depositETHTo{ value: 600 }(bob, 60000, hex\"dead\");\n assertEq(address(op).balance, 600);\n }\n}\n\ncontract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo {\n // BridgeETHTo\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_bridgeETHTo_succeeds() external {\n _preBridgeETHTo({ isLegacy: false });\n L1Bridge.bridgeETHTo{ value: 600 }(bob, 60000, hex\"dead\");\n assertEq(address(op).balance, 600);\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_DepositERC20_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // depositERC20\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - only callable by EOA\n function test_depositERC20_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n // Deal Alice's ERC20 State\n deal(address(L1Token), alice, 100000, true);\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n // The L1Bridge should transfer alice's tokens to itself\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 100)\n );\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L2Token),\n address(L1Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n // the L1 bridge should call L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 10000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 0,\n 10000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 10000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 0,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(0),\n uint256(0),\n baseGas,\n false,\n innerMessage\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 0);\n\n vm.prank(alice);\n L1Bridge.depositERC20(address(L1Token), address(L2Token), 100, 10000, hex\"\");\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n }\n}\n\ncontract L1StandardBridge_DepositERC20_TestFail is Bridge_Initializer {\n function test_depositERC20_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, hex\"ffff\");\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice, alice);\n L1Bridge.depositERC20(address(0), address(0), 100, 100, hex\"\");\n }\n}\n\ncontract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer {\n // depositERC20To\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - callable by a contract\n function test_depositERC20To_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L2Token),\n address(L1Token),\n alice,\n bob,\n 1000,\n hex\"\"\n );\n\n // the L1 bridge should call L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 10000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 0,\n 10000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 10000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 0,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(0),\n uint256(0),\n baseGas,\n false,\n innerMessage\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex\"\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 0);\n\n deal(address(L1Token), alice, 100000, true);\n\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 1000)\n );\n\n vm.prank(alice);\n L1Bridge.depositERC20To(address(L1Token), address(L2Token), bob, 1000, 10000, hex\"\");\n\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 1000);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeETHWithdrawal\n // - emits ETHWithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeETHWithdrawal_succeeds() external {\n uint256 aliceBalance = alice.balance;\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHWithdrawalFinalized(alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n vm.expectCall(alice, hex\"\");\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n // ensure that the messenger has ETH to call with\n vm.deal(address(L1Bridge.messenger()), 100);\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n\n assertEq(address(L1Bridge.messenger()).balance, 0);\n assertEq(aliceBalance + 100, alice.balance);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeERC20Withdrawal\n // - updates bridge.deposits\n // - emits ERC20WithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeERC20Withdrawal_succeeds() external {\n deal(address(L1Token), address(L1Bridge), 100, true);\n\n uint256 slot = stdstore\n .target(address(L1Bridge))\n .sig(\"deposits(address,address)\")\n .with_key(address(L1Token))\n .with_key(address(L2Token))\n .find();\n\n // Give the L1 bridge some ERC20 tokens\n vm.store(address(L1Bridge), bytes32(slot), bytes32(uint256(100)));\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20WithdrawalFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transfer.selector, alice, 100)\n );\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n assertEq(L1Token.balanceOf(address(L1Bridge)), 0);\n assertEq(L1Token.balanceOf(address(alice)), 100);\n }\n}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer {\n function test_finalizeERC20Withdrawal_notMessenger_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(28));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n\n function test_finalizeERC20Withdrawal_notOtherBridge_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(address(0)))\n );\n vm.prank(address(L1Bridge.messenger()));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n}\n\ncontract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {\n function test_finalizeBridgeETH_succeeds() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n\ncontract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer {\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L1Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L1Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, ConfigurableCaller } from \"./CommonTest.t.sol\";\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L2Messenger.messageNonce());\n assertEq(version, L2Messenger.MESSAGE_VERSION());\n }\n\n function test_sendMessage_succeeds() external {\n bytes memory xDomainCallData = Encoding.encodeCrossDomainMessage(\n L2Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n );\n vm.expectCall(\n address(messagePasser),\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData\n )\n );\n\n // MessagePassed event\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(L2Messenger),\n address(L1Messenger),\n 0,\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData,\n Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messagePasser.messageNonce(),\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: L2Messenger.baseGas(hex\"ff\", 100),\n data: xDomainCallData\n })\n )\n );\n\n vm.prank(alice);\n L2Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L2Messenger.messageNonce();\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L2Messenger.messageNonce());\n }\n\n function test_xDomainSender_senderNotSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 2), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n vm.expectCall(target, hex\"1111\");\n\n vm.prank(caller);\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L2Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L2Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n address target = address(messagePasser);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n bytes memory message = hex\"1111\";\n\n vm.prank(caller);\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retry_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n uint256 value = 100;\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(caller), value);\n vm.prank(caller);\n L2Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L2Messenger.successfulMessages(hash), false);\n assertEq(L2Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L2Messenger.successfulMessages(hash), true);\n assertEq(L2Messenger.failedMessages(hash), true);\n }\n}\n" - }, - "contracts/test/L2ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.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\ncontract TestMintableERC721 is OptimismMintableERC721 {\n constructor(address _bridge, address _remoteToken)\n OptimismMintableERC721(_bridge, 1, _remoteToken, \"Test\", \"TST\")\n {}\n\n function mint(address to, uint256 tokenId) public {\n _mint(to, tokenId);\n }\n}\n\ncontract L2ERC721Bridge_Test is Messenger_Initializer {\n TestMintableERC721 internal localToken;\n TestERC721 internal remoteToken;\n L2ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L2ERC721Bridge(address(L2Messenger), otherBridge);\n remoteToken = new TestERC721();\n localToken = new TestMintableERC721(address(bridge), address(remoteToken));\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L2ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L2Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L2Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L2ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"L2ERC721Bridge: Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L1ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L2ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"L2ERC721Bridge: Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_interfaceNotCompliant_reverts() external {\n // Create a non-compliant token\n NonCompliantERC721 nonCompliantToken = new NonCompliantERC721(alice);\n\n // Bridge the non-compliant token.\n vm.prank(alice);\n bridge.bridgeERC721(address(nonCompliantToken), address(0x01), tokenId, 1234, hex\"5678\");\n\n // Attempt to finalize the withdrawal. Should revert because the token does not claim\n // to be compliant with the `IOptimismMintableERC721` interface.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"L2ERC721Bridge: local token interface is not compliant\");\n bridge.finalizeBridgeERC721(\n address(address(nonCompliantToken)),\n address(address(0x01)),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"L2ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_alreadyExists_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721: token already minted\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n\n/**\n * @dev A non-compliant ERC721 token that does not implement the full ERC721 interface.\n *\n * This is used to test that the bridge will revert if the token does not claim to support\n * the ERC721 interface.\n */\ncontract NonCompliantERC721 {\n address internal immutable owner;\n\n constructor(address _owner) {\n owner = _owner;\n }\n\n function ownerOf(uint256) external view returns (address) {\n return owner;\n }\n\n function remoteToken() external pure returns (address) {\n return address(0x01);\n }\n\n function burn(address, uint256) external {\n // Do nothing.\n }\n\n function supportsInterface(bytes4) external pure returns (bool) {\n return false;\n }\n}\n" - }, - "contracts/test/L2OutputOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { L2OutputOracle_Initializer, NextImpl } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2OutputOracleTest is L2OutputOracle_Initializer {\n bytes32 proposedOutput1 = keccak256(abi.encode(1));\n\n function test_constructor_succeeds() external {\n assertEq(oracle.PROPOSER(), proposer);\n assertEq(oracle.CHALLENGER(), owner);\n assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval);\n assertEq(oracle.latestBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingTimestamp(), startingTimestamp);\n }\n\n function test_constructor_badTimestamp_reverts() external {\n vm.expectRevert(\"L2OutputOracle: starting L2 timestamp must be less than current time\");\n\n // startingTimestamp is in the future\n new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp + 1,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n function test_constructor_l2BlockTimeZero_reverts() external {\n vm.expectRevert(\"L2OutputOracle: L2 block time must be greater than 0\");\n new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: 0,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n function test_constructor_submissionInterval_reverts() external {\n vm.expectRevert(\"L2OutputOracle: submission interval must be greater than 0\");\n new L2OutputOracle({\n _submissionInterval: 0,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n /****************\n * Getter Tests *\n ****************/\n\n // Test: latestBlockNumber() should return the correct value\n function test_latestBlockNumber_succeeds() external {\n uint256 proposedNumber = oracle.nextBlockNumber();\n\n // Roll to after the block number we'll propose\n warpToProposeTime(proposedNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, proposedNumber, 0, 0);\n assertEq(oracle.latestBlockNumber(), proposedNumber);\n }\n\n // Test: getL2Output() should return the correct value\n function test_getL2Output_succeeds() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0);\n\n Types.OutputProposal memory proposal = oracle.getL2Output(nextOutputIndex);\n assertEq(proposal.outputRoot, proposedOutput1);\n assertEq(proposal.timestamp, block.timestamp);\n\n // The block number is larger than the latest proposed output:\n vm.expectRevert(stdError.indexOOBError);\n oracle.getL2Output(nextOutputIndex + 1);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is exact block\n function test_getL2OutputIndexAfter_sameBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with exact same block as proposed returns the proposal.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is previous block\n function test_getL2OutputIndexAfter_previousBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with previous block returns the proposal too.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 - 1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value during binary search\n function test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n bytes32 output2 = keccak256(abi.encode(2));\n uint256 nextBlockNumber2 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber2);\n vm.prank(proposer);\n oracle.proposeL2Output(output2, nextBlockNumber2, 0, 0);\n\n bytes32 output3 = keccak256(abi.encode(3));\n uint256 nextBlockNumber3 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber3);\n vm.prank(proposer);\n oracle.proposeL2Output(output3, nextBlockNumber3, 0, 0);\n\n bytes32 output4 = keccak256(abi.encode(4));\n uint256 nextBlockNumber4 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber4);\n vm.prank(proposer);\n oracle.proposeL2Output(output4, nextBlockNumber4, 0, 0);\n\n // Querying with a block number between the first and second proposal\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 + 1);\n assertEq(index1, 1);\n\n // Querying with a block number between the second and third proposal\n uint256 index2 = oracle.getL2OutputIndexAfter(nextBlockNumber2 + 1);\n assertEq(index2, 2);\n\n // Querying with a block number between the third and fourth proposal\n uint256 index3 = oracle.getL2OutputIndexAfter(nextBlockNumber3 + 1);\n assertEq(index3, 3);\n }\n\n // Test: getL2OutputIndexAfter() reverts when no output exists yet\n function test_getL2OutputIndexAfter_noOutputsExis_reverts() external {\n vm.expectRevert(\"L2OutputOracle: cannot get output as no outputs have been proposed yet\");\n oracle.getL2OutputIndexAfter(0);\n }\n\n // Test: nextBlockNumber() should return the correct value\n function test_nextBlockNumber_succeeds() external {\n assertEq(\n oracle.nextBlockNumber(),\n // The return value should match this arithmetic\n oracle.latestBlockNumber() + oracle.SUBMISSION_INTERVAL()\n );\n }\n\n function test_computeL2Timestamp_succeeds() external {\n // reverts if timestamp is too low\n vm.expectRevert(stdError.arithmeticError);\n oracle.computeL2Timestamp(startingBlockNumber - 1);\n\n // returns the correct value...\n // ... for the very first block\n assertEq(oracle.computeL2Timestamp(startingBlockNumber), startingTimestamp);\n\n // ... for the first block after the starting block\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 1),\n startingTimestamp + l2BlockTime\n );\n\n // ... for some other block number\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 96024),\n startingTimestamp + l2BlockTime * 96024\n );\n }\n\n /*****************************\n * Propose Tests - Happy Path *\n *****************************/\n\n // Test: proposeL2Output succeeds when given valid input, and no block hash and number are\n // specified.\n function test_proposeL2Output_proposeAnotherOutput_succeeds() public {\n bytes32 proposedOutput2 = keccak256(abi.encode());\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n uint256 proposedNumber = oracle.latestBlockNumber();\n\n // Ensure the submissionInterval is enforced\n assertEq(nextBlockNumber, proposedNumber + submissionInterval);\n\n vm.roll(nextBlockNumber + 1);\n\n vm.expectEmit(true, true, true, true);\n emit OutputProposed(proposedOutput2, nextOutputIndex, nextBlockNumber, block.timestamp);\n\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output succeeds when given valid input, and when a block hash and number are\n // specified for reorg protection.\n function test_proposeWithBlockhashAndHeight_succeeds() external {\n // Get the number and hash of a previous block in the chain\n uint256 prevL1BlockNumber = block.number - 1;\n bytes32 prevL1BlockHash = blockhash(prevL1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber);\n }\n\n /***************************\n * Propose Tests - Sad Path *\n ***************************/\n\n // Test: proposeL2Output fails if called by a party that is not the proposer.\n function test_proposeL2Output_notProposer_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n\n vm.prank(address(128));\n vm.expectRevert(\"L2OutputOracle: only the proposer address can propose new outputs\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails given a zero blockhash.\n function test_proposeL2Output_emptyOutput_reverts() external {\n bytes32 outputToPropose = bytes32(0);\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: L2 output proposal cannot be the zero hash\");\n oracle.proposeL2Output(outputToPropose, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if the block number doesn't match the next expected number.\n function test_proposeL2Output_unexpectedBlockNumber_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: block number must be equal to next expected block number\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0);\n }\n\n // Test: proposeL2Output fails if it would have a timestamp in the future.\n function test_proposeL2Output_futureTimetamp_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextTimestamp = oracle.computeL2Timestamp(nextBlockNumber);\n vm.warp(nextTimestamp);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: cannot propose L2 output in the future\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if a non-existent L1 block hash and number are provided for reorg\n // protection.\n function test_proposeL2Output_wrongFork_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(\n nonZeroHash,\n nextBlockNumber,\n bytes32(uint256(0x01)),\n block.number - 1\n );\n }\n\n // Test: proposeL2Output fails when given valid input, but the block hash and number do not\n // match.\n function test_proposeL2Output_unmatchedBlockhash_reverts() external {\n // Move ahead to block 100 so that we can reference historical blocks\n vm.roll(100);\n\n // Get the number and hash of a previous block in the chain\n uint256 l1BlockNumber = block.number - 1;\n bytes32 l1BlockHash = blockhash(l1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n\n // This will fail when foundry no longer returns zerod block hashes\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1);\n }\n\n /*****************************\n * Delete Tests - Happy Path *\n *****************************/\n\n function test_deleteOutputs_singleOutput_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 1);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex);\n oracle.deleteL2Outputs(latestOutputIndex);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n function test_deleteOutputs_multipleOutputs_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 3);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex - 2);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval * 3, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n /***************************\n * Delete Tests - Sad Path *\n ***************************/\n\n function test_deleteL2Outputs_ifNotChallenger_reverts() external {\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.expectRevert(\"L2OutputOracle: only the challenger address can delete outputs\");\n oracle.deleteL2Outputs(latestBlockNumber);\n }\n\n function test_deleteL2Outputs_nonExistent_reverts() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestBlockNumber + 1);\n }\n\n function test_deleteL2Outputs_afterLatest_reverts() external {\n // Start by proposing three outputs\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n // Delete the latest two outputs\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n vm.prank(owner);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // Now try to delete the same output again\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n }\n\n function test_deleteL2Outputs_finalized_reverts() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n // Warp past the finalization period + 1 second\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n\n // Try to delete a finalized output\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs that have already been finalized\");\n oracle.deleteL2Outputs(latestOutputIndex);\n }\n}\n\ncontract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {\n Proxy internal proxy;\n\n function setUp() public override {\n super.setUp();\n proxy = Proxy(payable(address(oracle)));\n }\n\n function test_initValuesOnProxy_succeeds() external {\n assertEq(submissionInterval, oracleImpl.SUBMISSION_INTERVAL());\n assertEq(l2BlockTime, oracleImpl.L2_BLOCK_TIME());\n assertEq(startingBlockNumber, oracleImpl.startingBlockNumber());\n assertEq(startingTimestamp, oracleImpl.startingTimestamp());\n\n assertEq(proposer, oracleImpl.PROPOSER());\n assertEq(owner, oracleImpl.CHALLENGER());\n }\n\n function test_initializeProxy_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(payable(proxy)).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_initializeImpl_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(oracleImpl).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(oracle), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(oracle), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(oracle)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n" - }, - "contracts/test/L2StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { console } from \"forge-std/console.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\ncontract L2StandardBridge_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n function test_initialize_succeeds() external {\n assertEq(address(L2Bridge.messenger()), address(L2Messenger));\n assertEq(L1Bridge.l2TokenBridge(), address(L2Bridge));\n assertEq(address(L2Bridge.OTHER_BRIDGE()), address(L1Bridge));\n }\n\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(messagePasser).balance, 0);\n uint256 nonce = L2Messenger.messageNonce();\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 200_000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 100,\n 200_000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 100,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalInitiated(address(0), Predeploys.LEGACY_ERC20_ETH, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n // L2ToL1MessagePasser will emit a MessagePassed event\n vm.expectEmit(true, true, true, true, address(messagePasser));\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 100,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 200_000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessageExtension1(address(L2Bridge), 100);\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 200_000 // StandardBridge's RECEIVE_DEFAULT_GAS_LIMIT\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n vm.prank(alice, alice);\n (bool success, ) = address(L2Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(messagePasser).balance, 100);\n }\n\n // withrdraw\n // - requires amount == msg.value\n function test_withdraw_insufficientValue_reverts() external {\n assertEq(address(messagePasser).balance, 0);\n\n vm.expectRevert(\"StandardBridge: bridging ETH must include sufficient ETH value\");\n vm.prank(alice, alice);\n L2Bridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 100, 1000, hex\"\");\n }\n\n /**\n * @notice Use the legacy `withdraw` interface on the L2StandardBridge to\n * withdraw ether from L2 to L1.\n */\n function test_withdraw_ether_succeeds() external {\n assertTrue(alice.balance >= 100);\n assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 0);\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit WithdrawalInitiated({\n l1Token: address(0),\n l2Token: Predeploys.LEGACY_ERC20_ETH,\n from: alice,\n to: alice,\n amount: 100,\n data: hex\"\"\n });\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ETHBridgeInitiated({ from: alice, to: alice, amount: 100, data: hex\"\" });\n\n vm.prank(alice, alice);\n L2Bridge.withdraw{ value: 100 }({\n _l2Token: Predeploys.LEGACY_ERC20_ETH,\n _amount: 100,\n _minGasLimit: 1000,\n _extraData: hex\"\"\n });\n\n assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 100);\n }\n}\n\ncontract PreBridgeERC20 is Bridge_Initializer {\n // withdraw and BridgeERC20 should behave the same when transferring ERC20 tokens\n // so they should share the same setup and expectEmit calls\n function _preBridgeERC20(bool _isLegacy, address _l2Token) internal {\n // Alice has 100 L2Token\n deal(_l2Token, alice, 100, true);\n assertEq(ERC20(_l2Token).balanceOf(alice), 100);\n uint256 nonce = L2Messenger.messageNonce();\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L1Token),\n _l2Token,\n alice,\n alice,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 1000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 0,\n 1000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n if (_isLegacy) {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(L2Bridge.withdraw.selector, _l2Token, 100, 1000, hex\"\")\n );\n } else {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.bridgeERC20.selector,\n _l2Token,\n address(L1Token),\n 100,\n 1000,\n hex\"\"\n )\n );\n }\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 1000\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n // The L2Bridge should burn the tokens\n vm.expectCall(\n _l2Token,\n abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalInitiated(address(L1Token), _l2Token, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 0,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true);\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true);\n emit SentMessageExtension1(address(L2Bridge), 0);\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {\n // withdraw\n // - token is burned\n // - emits WithdrawalInitiated\n // - calls Withdrawer.initiateWithdrawal\n function test_withdraw_withdrawingERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: true, _l2Token: address(L2Token) });\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n // BridgeERC20\n // - token is burned\n // - emits WithdrawalInitiated\n // - calls Withdrawer.initiateWithdrawal\n function test_bridgeERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: false, _l2Token: address(L2Token) });\n L2Bridge.bridgeERC20(address(L2Token), address(L1Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_withdrawLegacyERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: true, _l2Token: address(LegacyL2Token) });\n L2Bridge.withdraw(address(LegacyL2Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_bridgeLegacyERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: false, _l2Token: address(LegacyL2Token) });\n L2Bridge.bridgeERC20(address(LegacyL2Token), address(L1Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_withdraw_notEOA_reverts() external {\n // This contract has 100 L2Token\n deal(address(L2Token), address(this), 100, true);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n }\n}\n\ncontract PreBridgeERC20To is Bridge_Initializer {\n // withdrawTo and BridgeERC20To should behave the same when transferring ERC20 tokens\n // so they should share the same setup and expectEmit calls\n function _preBridgeERC20To(bool _isLegacy, address _l2Token) internal {\n deal(_l2Token, alice, 100, true);\n assertEq(ERC20(L2Token).balanceOf(alice), 100);\n uint256 nonce = L2Messenger.messageNonce();\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L1Token),\n _l2Token,\n alice,\n bob,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 1000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 0,\n 1000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit WithdrawalInitiated(address(L1Token), _l2Token, alice, bob, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, bob, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(messagePasser));\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 0,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessageExtension1(address(L2Bridge), 0);\n\n if (_isLegacy) {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.withdrawTo.selector,\n _l2Token,\n bob,\n 100,\n 1000,\n hex\"\"\n )\n );\n } else {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.bridgeERC20To.selector,\n _l2Token,\n address(L1Token),\n bob,\n 100,\n 1000,\n hex\"\"\n )\n );\n }\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 1000\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n // The L2Bridge should burn the tokens\n vm.expectCall(\n address(L2Token),\n abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)\n );\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To {\n // withdrawTo\n // - token is burned\n // - emits WithdrawalInitiated w/ correct recipient\n // - calls Withdrawer.initiateWithdrawal\n function test_withdrawTo_withdrawingERC20_succeeds() external {\n _preBridgeERC20To({ _isLegacy: true, _l2Token: address(L2Token) });\n L2Bridge.withdrawTo(address(L2Token), bob, 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n // bridgeERC20To\n // - token is burned\n // - emits WithdrawalInitiated w/ correct recipient\n // - calls Withdrawer.initiateWithdrawal\n function test_bridgeERC20To_succeeds() external {\n _preBridgeERC20To({ _isLegacy: false, _l2Token: address(L2Token) });\n L2Bridge.bridgeERC20To(address(L2Token), address(L1Token), bob, 100, 1000, hex\"\");\n assertEq(L2Token.balanceOf(alice), 0);\n }\n}\n\ncontract L2StandardBridge_Bridge_Test is Bridge_Initializer {\n // finalizeDeposit\n // - only callable by l1TokenBridge\n // - supported token pair emits DepositFinalized\n // - invalid deposit calls Withdrawer.initiateWithdrawal\n function test_finalizeDeposit_depositingERC20_succeeds() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n\n vm.expectCall(\n address(L2Token),\n abi.encodeWithSelector(OptimismMintableERC20.mint.selector, alice, 100)\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeFinalized(address(L2Token), address(L1Token), alice, alice, 100, hex\"\");\n\n vm.prank(address(L2Messenger));\n L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n }\n\n function test_finalizeDeposit_depositingETH_succeeds() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeFinalized(\n address(L2Token), // localToken\n address(L1Token), // remoteToken\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n vm.prank(address(L2Messenger));\n L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L2Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Messenger), 100, hex\"\");\n }\n}\n\ncontract L2StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {\n function test_finalizeBridgeETH_succeeds() external {\n address messenger = address(L2Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n\n vm.expectEmit(true, true, true, true);\n emit DepositFinalized(address(0), Predeploys.LEGACY_ERC20_ETH, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2ToL1MessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\n\ncontract L2ToL1MessagePasserTest is CommonTest {\n L2ToL1MessagePasser messagePasser;\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n function setUp() public virtual override {\n super.setUp();\n messagePasser = new L2ToL1MessagePasser();\n }\n\n function testFuzz_initiateWithdrawal_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint256 nonce = messagePasser.messageNonce();\n\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: _value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, _sender, _target, _value, _gasLimit, _data, withdrawalHash);\n\n vm.deal(_sender, _value);\n vm.prank(_sender);\n messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);\n\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n\n bytes32 slot = keccak256(bytes.concat(withdrawalHash, bytes32(0)));\n\n assertEq(vm.load(address(messagePasser), slot), bytes32(uint256(1)));\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by a contract\n function test_initiateWithdrawal_fromContract_succeeds() external {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\"\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\",\n withdrawalHash\n );\n\n vm.deal(address(this), 2**64);\n messagePasser.initiateWithdrawal{ value: 100 }(address(4), 64000, hex\"\");\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by an EOA\n function test_initiateWithdrawal_fromEOA_succeeds() external {\n uint256 gasLimit = 64000;\n address target = address(4);\n uint256 value = 100;\n bytes memory data = hex\"ff\";\n uint256 nonce = messagePasser.messageNonce();\n\n // EOA emulation\n vm.prank(alice, alice);\n vm.deal(alice, 2**64);\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(nonce, alice, target, value, gasLimit, data)\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, alice, target, value, gasLimit, data, withdrawalHash);\n\n messagePasser.initiateWithdrawal{ value: value }(target, gasLimit, data);\n\n // the sent messages mapping is filled\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n // the nonce increments\n assertEq(nonce + 1, messagePasser.messageNonce());\n }\n\n // Test: burn should destroy the ETH held in the contract\n function test_burn_succeeds() external {\n messagePasser.initiateWithdrawal{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n NON_ZERO_GASLIMIT,\n NON_ZERO_DATA\n );\n\n assertEq(address(messagePasser).balance, NON_ZERO_VALUE);\n vm.expectEmit(true, false, false, false);\n emit WithdrawerBalanceBurnt(NON_ZERO_VALUE);\n messagePasser.burn();\n\n // The Withdrawer should have no balance\n assertEq(address(messagePasser).balance, 0);\n }\n}\n" - }, - "contracts/test/LegacyERC20ETH.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyERC20ETH_Test is CommonTest {\n LegacyERC20ETH eth;\n\n function setUp() public virtual override {\n super.setUp();\n eth = new LegacyERC20ETH();\n }\n\n function test_metadata_succeeds() external {\n assertEq(eth.name(), \"Ether\");\n assertEq(eth.symbol(), \"ETH\");\n assertEq(eth.decimals(), 18);\n }\n\n function test_crossDomain_succeeds() external {\n assertEq(eth.l2Bridge(), Predeploys.L2_STANDARD_BRIDGE);\n assertEq(eth.l1Token(), address(0));\n }\n\n function test_transfer_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transfer is disabled\");\n eth.transfer(alice, 100);\n }\n\n function test_approve_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: approve is disabled\");\n eth.approve(alice, 100);\n }\n\n function test_transferFrom_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transferFrom is disabled\");\n eth.transferFrom(bob, alice, 100);\n }\n\n function test_increaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n eth.increaseAllowance(alice, 100);\n }\n\n function test_decreaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n eth.decreaseAllowance(alice, 100);\n }\n\n function test_mint_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: mint is disabled\");\n eth.mint(alice, 100);\n }\n\n function test_burn_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: burn is disabled\");\n eth.burn(alice, 100);\n }\n}\n" - }, - "contracts/test/LegacyMessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyMessagePasser } from \"../legacy/LegacyMessagePasser.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyMessagePasser_Test is CommonTest {\n LegacyMessagePasser messagePasser;\n\n function setUp() public virtual override {\n super.setUp();\n messagePasser = new LegacyMessagePasser();\n }\n\n function test_passMessageToL1_succeeds() external {\n vm.prank(alice);\n messagePasser.passMessageToL1(hex\"ff\");\n assert(messagePasser.sentMessages(keccak256(abi.encodePacked(hex\"ff\", alice))));\n }\n}\n" - }, - "contracts/test/MerkleTrie.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MerkleTrie } from \"../libraries/trie/MerkleTrie.sol\";\n\ncontract MerkleTrie_get_Test is CommonTest {\n function test_get_validProof1_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579326262\";\n bytes memory val = hex\"6176616c32\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof2_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[\n 2\n ] = hex\"ef83206161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof3_succeeds() external {\n bytes32 root = 0xf838216fa749aefa91e0b672a9c06d3e6e983f913d7107b5dab4af60b5f5abed;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"f387206b6579316161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof4_succeeds() external {\n bytes32 root = 0x37956bab6bba472308146808d5311ac19cb4a7daae5df7efcc0f32badc97f55e;\n bytes memory key = hex\"6b6579316161\";\n bytes memory val = hex\"3031323334\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"ce87206b6579316161853031323334\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof5_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657931\";\n bytes\n memory val = hex\"30313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f862808080808080a057895fdbd71e2c67c2f9274a56811ff5cf458720a7fa713a135e3890f8cafcf8808080808080808080b130313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof6_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657932\";\n bytes memory val = hex\"73686f7274\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[2] = hex\"df808080808080c9823262856176616c338080808080808080808573686f7274\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof7_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657933\";\n bytes memory val = hex\"31323334353637383930313233343536373839303132333435363738393031\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f839808080808080c9823363856176616c338080808080808080809f31323334353637383930313233343536373839303132333435363738393031\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof8_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"61\";\n bytes memory val = hex\"61\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22061\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof9_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"62\";\n bytes memory val = hex\"62\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22062\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof10_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"63\";\n bytes memory val = hex\"63\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22063\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_nonexistentKey1_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b657932\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_nonexistentKey2_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"616e7972616e646f6d6b6579\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_wrongKeyProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579316161\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e216a04892c039d654f1be9af20e88ae53e9ab5fa5520190e0fb2f805823e45ebad22f\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[2] = hex\"d687206e6f746865728d33343938683472697568677765\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_corruptedProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579326262\";\n bytes[] memory proof = new bytes[](5);\n proof[0] = hex\"2fd2ba5ee42358802ffbe0900152a55fabe953ae880ef29abef154d639c09248a016e2\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[\n 2\n ] = hex\"e583165793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 3\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[4] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidDataRemainder_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa000000000000000000000000000000\";\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidInternalNodeHash_reverts() external {\n bytes32 root = 0xa827dff1a657bb9bb9a1c3abe9db173e2f1359f15eb06f1647ea21ac7c95d8fa;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa09862c6b113008c4204c13755693cbb868acc25ebaa98db11df8c89a0c0dd3157\";\n proof[\n 1\n ] = hex\"f380808080808080808080a0de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f00c220118080808080\";\n proof[2] = hex\"de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroBranchValueLength_reverts() external {\n bytes32 root = 0xe04b3589eef96b237cd49ccb5dcf6e654a47682bfa0961d563ab843f7ad1e035;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](2);\n proof[0] = hex\"dd8200aad98080808080808080808080c43b82aabbc43c82aacc80808080\";\n proof[1] = hex\"d98080808080808080808080c43b82aabbc43c82aacc80808080\";\n\n vm.expectRevert(\"MerkleTrie: value length must be greater than zero (branch)\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroLengthKey_reverts() external {\n bytes32 root = 0x54157fd62cdf2f474e7bfec2d3cd581e807bee38488c9590cb887add98936b73;\n bytes memory key = hex\"\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"c78320f00082b443\";\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey1_reverts() external {\n bytes32 root = 0xa513ba530659356fb7588a2c831944e80fd8aedaa5a4dc36f918152be2be0605;\n bytes memory key = hex\"01\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"db10d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[1] = hex\"d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[2] = hex\"c582202381aa\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey2_reverts() external {\n bytes32 root = 0xa06abffaec4ebe8ccde595f4547b864b4421b21c1fc699973f94710c9bc17979;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa07ea462226a3dc0a46afb4ded39306d7a84d311ada3557dfc75a909fd25530905\";\n proof[\n 1\n ] = hex\"f380808080808080808080a027f11bd3af96d137b9287632f44dd00fea1ca1bd70386c30985ede8cc287476e808080c220338080\";\n proof[2] = hex\"e48200bba0a6911545ed01c2d3f4e15b8b27c7bfba97738bd5e6dd674dd07033428a4c53af\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_extraProofElements_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](4);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa\";\n proof[3] = hex\"c32081aa\";\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_validProofs_succeeds(bytes4) external {\n // Generate a test case with a valid proof of inclusion for the k/v pair in the trie.\n (bytes32 root, bytes memory key, bytes memory val, bytes[] memory proof) = ffi\n .getMerkleTrieFuzzCase(\"valid\");\n\n // Assert that our expected value is equal to our actual value.\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidRoot_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"valid\"\n );\n\n bytes32 rootHash = keccak256(abi.encodePacked(root));\n vm.expectRevert(\"MerkleTrie: invalid root hash\");\n MerkleTrie.get(key, proof, rootHash);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_extraProofElements_reverts(bytes4) external {\n // Generate an invalid test case with an extra proof element attached to an otherwise\n // valid proof of inclusion for the passed k/v.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"extra_proof_elems\"\n );\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidLargeInternalHash_reverts(bytes4) external {\n // Generate an invalid test case where a long proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_large_internal_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid large internal hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidInternalNodeHash_reverts(bytes4) external {\n // Generate an invalid test case where a small proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_internal_node_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_corruptedProof_reverts(bytes4) external {\n // Generate an invalid test case where the proof is malformed.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"corrupted_proof\"\n );\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidDataRemainder_reverts(bytes4) external {\n // Generate an invalid test case where a random element of the proof has more bytes than the\n // length designates within the RLP list encoding.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_data_remainder\"\n );\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_prefixedValidKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and a valid key that is prefixed\n // with random bytes\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"prefixed_valid_key\"\n );\n\n // Ambiguous revert check- all that we care is that it *does* fail. This case may\n // fail within different branches.\n vm.expectRevert();\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_emptyKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and an empty key\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"empty_key\"\n );\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_partialProof_reverts(bytes4) external {\n // Get a random test case with a valid trie / partially correct proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"partial_proof\"\n );\n\n vm.expectRevert(\"MerkleTrie: ran out of proof elements\");\n MerkleTrie.get(key, proof, root);\n }\n}\n" - }, - "contracts/test/MintManager.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MintManager } from \"../governance/MintManager.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract MintManager_Initializer is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n MintManager internal manager;\n\n function setUp() public virtual override {\n super.setUp();\n\n vm.prank(owner);\n gov = new GovernanceToken();\n\n vm.prank(owner);\n manager = new MintManager(owner, address(gov));\n\n vm.prank(owner);\n gov.transferOwnership(address(manager));\n }\n}\n\ncontract MintManager_constructor_Test is MintManager_Initializer {\n /**\n * @notice Tests that the constructor properly configures the contract.\n */\n function test_constructor_succeeds() external {\n assertEq(manager.owner(), owner);\n assertEq(address(manager.governanceToken()), address(gov));\n }\n}\n\ncontract MintManager_mint_Test is MintManager_Initializer {\n /**\n * @notice Tests that the mint function properly mints tokens when called by the owner.\n */\n function test_mint_fromOwner_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n /**\n * @notice Tests that the mint function reverts when called by a non-owner.\n */\n function test_mint_fromNotOwner_reverts() external {\n // Mint from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.mint(owner, 100);\n }\n\n /**\n * @notice Tests that the mint function properly mints tokens when called by the owner a second\n * time after the mint period has elapsed.\n */\n function test_mint_afterPeriodElapsed_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again after period elapsed (2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n manager.mint(owner, 2);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 102);\n }\n\n /**\n * @notice Tests that the mint function always reverts when called before the mint period has\n * elapsed, even if the caller is the owner.\n */\n function test_mint_beforePeriodElapsed_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: minting not permitted yet\");\n manager.mint(owner, 100);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n /**\n * @notice Tests that the owner cannot mint more than the mint cap.\n */\n function test_mint_moreThanCap_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again (greater than 2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint amount exceeds cap\");\n manager.mint(owner, 3);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n}\n\ncontract MintManager_upgrade_Test is MintManager_Initializer {\n /**\n * @notice Tests that the owner can upgrade the mint manager.\n */\n function test_upgrade_fromOwner_succeeds() external {\n // Upgrade to new manager.\n vm.prank(owner);\n manager.upgrade(rando);\n\n // New manager is rando.\n assertEq(gov.owner(), rando);\n }\n\n /**\n * @notice Tests that the upgrade function reverts when called by a non-owner.\n */\n function test_upgrade_fromNotOwner_reverts() external {\n // Upgrade from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.upgrade(rando);\n }\n\n /**\n * @notice Tests that the upgrade function reverts when attempting to update to the zero\n * address, even if the caller is the owner.\n */\n function test_upgrade_toZeroAddress_reverts() external {\n // Upgrade to zero address fails.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint manager cannot be the zero address\");\n manager.upgrade(address(0));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport {\n ILegacyMintableERC20,\n IOptimismMintableERC20\n} from \"../universal/IOptimismMintableERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ncontract OptimismMintableERC20_Test is Bridge_Initializer {\n event Mint(address indexed account, uint256 amount);\n event Burn(address indexed account, uint256 amount);\n\n function test_semver_succeeds() external {\n assertEq(L2Token.version(), \"1.0.0\");\n }\n\n function test_remoteToken_succeeds() external {\n assertEq(L2Token.remoteToken(), address(L1Token));\n }\n\n function test_bridge_succeeds() external {\n assertEq(L2Token.bridge(), address(L2Bridge));\n }\n\n function test_l1Token_succeeds() external {\n assertEq(L2Token.l1Token(), address(L1Token));\n }\n\n function test_l2Bridge_succeeds() external {\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_legacy_succeeds() external {\n // Getters for the remote token\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.l1Token(), address(L1Token));\n // Getters for the bridge\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_mint_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 100);\n }\n\n function test_mint_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.mint(alice, 100);\n }\n\n function test_burn_succeeds() external {\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_burn_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.burn(alice, 100);\n }\n\n function test_erc165_supportsInterface_succeeds() external {\n // The assertEq calls in this test are comparing the manual calculation of the iface,\n // with what is returned by the solidity's type().interfaceId, just to be safe.\n bytes4 iface1 = bytes4(keccak256(\"supportsInterface(bytes4)\"));\n assertEq(iface1, type(IERC165).interfaceId);\n assert(L2Token.supportsInterface(iface1));\n\n bytes4 iface2 = L2Token.l1Token.selector ^ L2Token.mint.selector ^ L2Token.burn.selector;\n assertEq(iface2, type(ILegacyMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface2));\n\n bytes4 iface3 = L2Token.remoteToken.selector ^\n L2Token.bridge.selector ^\n L2Token.mint.selector ^\n L2Token.burn.selector;\n assertEq(iface3, type(IOptimismMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface3));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\n\ncontract OptimismMintableTokenFactory_Test is Bridge_Initializer {\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n }\n\n function test_bridge_succeeds() external {\n assertEq(address(L2TokenFactory.BRIDGE()), address(L2Bridge));\n }\n\n function test_createStandardL2Token_succeeds() external {\n address remote = address(4);\n address local = LibRLP.computeAddress(address(L2TokenFactory), 2);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_sameTwice_succeeds() external {\n address remote = address(4);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n\n address local = LibRLP.computeAddress(address(L2TokenFactory), 3);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_remoteIsZero_succeeds() external {\n address remote = address(0);\n vm.expectRevert(\"OptimismMintableERC20Factory: must provide remote token address\");\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721, IERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport {\n IERC721Enumerable\n} from \"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport {\n OptimismMintableERC721,\n IOptimismMintableERC721\n} from \"../universal/OptimismMintableERC721.sol\";\n\ncontract OptimismMintableERC721_Test is ERC721Bridge_Initializer {\n ERC721 internal L1Token;\n OptimismMintableERC721 internal L2Token;\n\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n event Mint(address indexed account, uint256 tokenId);\n\n event Burn(address indexed account, uint256 tokenId);\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n L1Token = new ERC721(\"L1Token\", \"L1T\");\n L2Token = new OptimismMintableERC721(\n address(L2Bridge),\n 1,\n address(L1Token),\n \"L2Token\",\n \"L2T\"\n );\n\n // Label the addresses for nice traces.\n vm.label(address(L1Token), \"L1ERC721Token\");\n vm.label(address(L2Token), \"L2ERC721Token\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(L2Token.name(), \"L2Token\");\n assertEq(L2Token.symbol(), \"L2T\");\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.remoteChainId(), 1);\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.REMOTE_CHAIN_ID(), 1);\n assertEq(L2Token.version(), \"1.1.0\");\n }\n\n /**\n * @notice Ensure that the contract supports the expected interfaces.\n */\n function test_supportsInterfaces_succeeds() external {\n // Checks if the contract supports the IOptimismMintableERC721 interface.\n assertTrue(L2Token.supportsInterface(type(IOptimismMintableERC721).interfaceId));\n // Checks if the contract supports the IERC721Enumerable interface.\n assertTrue(L2Token.supportsInterface(type(IERC721Enumerable).interfaceId));\n // Checks if the contract supports the IERC721 interface.\n assertTrue(L2Token.supportsInterface(type(IERC721).interfaceId));\n // Checks if the contract supports the IERC165 interface.\n assertTrue(L2Token.supportsInterface(type(IERC165).interfaceId));\n }\n\n function test_safeMint_succeeds() external {\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(address(0), alice, 1);\n\n // Expect a mint event.\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 1);\n\n // Mint the token.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token should be owned by alice.\n assertEq(L2Token.ownerOf(1), alice);\n }\n\n function test_safeMint_notBridge_reverts() external {\n // Try to mint the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.safeMint(alice, 1);\n }\n\n function test_burn_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(alice, address(0), 1);\n\n // Expect a burn event.\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 1);\n\n // Burn the token.\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 1);\n\n // Token should be owned by address(0).\n vm.expectRevert(\"ERC721: invalid token ID\");\n L2Token.ownerOf(1);\n }\n\n function test_burn_notBridge_reverts() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Try to burn the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.burn(alice, 1);\n }\n\n function test_tokenURI_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token URI should be correct.\n assertEq(\n L2Token.tokenURI(1),\n string(\n abi.encodePacked(\n \"ethereum:\",\n Strings.toHexString(uint160(address(L1Token)), 20),\n \"@\",\n Strings.toString(1),\n \"/tokenURI?uint256=\",\n Strings.toString(1)\n )\n )\n );\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\n\ncontract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer {\n OptimismMintableERC721Factory internal factory;\n\n event OptimismMintableERC721Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n factory = new OptimismMintableERC721Factory(address(L2Bridge), 1);\n\n // Label the addresses for nice traces.\n vm.label(address(factory), \"OptimismMintableERC721Factory\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(factory.BRIDGE(), address(L2Bridge));\n assertEq(factory.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_succeeds() external {\n // Predict the address based on the factory address and nonce.\n address predicted = LibRLP.computeAddress(address(factory), 1);\n\n // Expect a token creation event.\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC721Created(predicted, address(1234), alice);\n\n // Create the token.\n vm.prank(alice);\n OptimismMintableERC721 created = OptimismMintableERC721(\n factory.createOptimismMintableERC721(address(1234), \"L2Token\", \"L2T\")\n );\n\n // Token address should be correct.\n assertEq(address(created), predicted);\n\n // Should be marked as created by the factory.\n assertEq(factory.isOptimismMintableERC721(address(created)), true);\n\n // Token should've been constructed correctly.\n assertEq(created.name(), \"L2Token\");\n assertEq(created.symbol(), \"L2T\");\n assertEq(created.REMOTE_TOKEN(), address(1234));\n assertEq(created.BRIDGE(), address(L2Bridge));\n assertEq(created.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_zeroRemoteToken_reverts() external {\n // Try to create a token with a zero remote token address.\n vm.expectRevert(\"OptimismMintableERC721Factory: L1 token address cannot be address(0)\");\n factory.createOptimismMintableERC721(address(0), \"L2Token\", \"L2T\");\n }\n}\n" - }, - "contracts/test/OptimismPortal.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { Portal_Initializer, CommonTest, NextImpl } from \"./CommonTest.t.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\ncontract OptimismPortal_Test is Portal_Initializer {\n event Paused(address);\n event Unpaused(address);\n\n function test_constructor_succeeds() external {\n assertEq(address(op.L2_ORACLE()), address(oracle));\n assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD);\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal can be paused by the GUARDIAN\n */\n function test_pause_succeeds() external {\n address guardian = op.GUARDIAN();\n\n assertEq(op.paused(), false);\n\n vm.expectEmit(true, true, true, true, address(op));\n emit Paused(guardian);\n\n vm.prank(guardian);\n op.pause();\n\n assertEq(op.paused(), true);\n }\n\n /**\n * @notice The OptimismPortal reverts when an account that is not the\n * GUARDIAN calls `pause()`\n */\n function test_pause_onlyGuardian_reverts() external {\n assertEq(op.paused(), false);\n\n assertTrue(op.GUARDIAN() != alice);\n vm.expectRevert(\"OptimismPortal: only guardian can pause\");\n vm.prank(alice);\n op.pause();\n\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal can be unpaused by the GUARDIAN\n */\n function test_unpause_succeeds() external {\n address guardian = op.GUARDIAN();\n\n vm.prank(guardian);\n op.pause();\n assertEq(op.paused(), true);\n\n vm.expectEmit(true, true, true, true, address(op));\n emit Unpaused(guardian);\n vm.prank(guardian);\n op.unpause();\n\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal reverts when an account that is not\n * the GUARDIAN calls `unpause()`\n */\n function test_unpause_onlyGuardian_reverts() external {\n address guardian = op.GUARDIAN();\n\n vm.prank(guardian);\n op.pause();\n assertEq(op.paused(), true);\n\n assertTrue(op.GUARDIAN() != alice);\n vm.expectRevert(\"OptimismPortal: only guardian can unpause\");\n vm.prank(alice);\n op.unpause();\n\n assertEq(op.paused(), true);\n }\n\n function test_receive_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(alice, alice, 100, 100, 100_000, false, hex\"\");\n\n // give alice money and send as an eoa\n vm.deal(alice, 2**64);\n vm.prank(alice, alice);\n (bool s, ) = address(op).call{ value: 100 }(hex\"\");\n\n assert(s);\n assertEq(address(op).balance, 100);\n }\n\n // Test: depositTransaction fails when contract creation has a non-zero destination address\n function test_depositTransaction_contractCreation_reverts() external {\n // contract creation must have a target of address(0)\n vm.expectRevert(\"OptimismPortal: must send to address(0) when creating a contract\");\n op.depositTransaction(address(1), 1, 0, true, hex\"\");\n }\n\n /**\n * @notice Prevent deposits from being too large to have a sane upper bound\n * on unsafe blocks sent over the p2p network.\n */\n function test_depositTransaction_largeData_reverts() external {\n uint256 size = 120_001;\n uint64 gasLimit = op.minimumGasLimit(uint64(size));\n vm.expectRevert(\"OptimismPortal: data too large\");\n op.depositTransaction({\n _to: address(0),\n _value: 0,\n _gasLimit: gasLimit,\n _isCreation: false,\n _data: new bytes(size)\n });\n }\n\n /**\n * @notice Prevent gasless deposits from being force processed in L2 by\n * ensuring that they have a large enough gas limit set.\n */\n function test_depositTransaction_smallGasLimit_reverts() external {\n vm.expectRevert(\"OptimismPortal: gas limit too small\");\n op.depositTransaction({\n _to: address(1),\n _value: 0,\n _gasLimit: 0,\n _isCreation: false,\n _data: hex\"\"\n });\n }\n\n /**\n * @notice Fuzz for too small of gas limits\n */\n function testFuzz_depositTransaction_smallGasLimit_succeeds(\n bytes memory _data,\n bool _shouldFail\n ) external {\n vm.assume(_data.length <= type(uint64).max);\n\n uint64 gasLimit = op.minimumGasLimit(uint64(_data.length));\n if (_shouldFail) {\n gasLimit = uint64(bound(gasLimit, 0, gasLimit - 1));\n vm.expectRevert(\"OptimismPortal: gas limit too small\");\n }\n\n op.depositTransaction({\n _to: address(0x40),\n _value: 0,\n _gasLimit: gasLimit,\n _isCreation: false,\n _data: _data\n });\n }\n\n /**\n * @notice Ensure that the 0 calldata case is covered and there is a linearly\n * increasing gas limit for larger calldata sizes.\n */\n function test_minimumGasLimit_succeeds() external {\n assertEq(op.minimumGasLimit(0), 21_000);\n assertTrue(op.minimumGasLimit(2) > op.minimumGasLimit(1));\n assertTrue(op.minimumGasLimit(3) > op.minimumGasLimit(2));\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value\n function test_depositTransaction_noValueEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value\n function test_depositTransaction_noValueContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndContractContractCreation_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n function test_simple_isOutputFinalized_succeeds() external {\n uint256 ts = block.timestamp;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(bytes32(uint256(1)), uint128(ts), uint128(startingBlockNumber))\n )\n );\n\n // warp to the finalization period\n vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS());\n assertEq(op.isOutputFinalized(0), false);\n\n // warp past the finalization period\n vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n assertEq(op.isOutputFinalized(0), true);\n }\n\n function test_isOutputFinalized_succeeds() external {\n uint256 checkpoint = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n vm.roll(checkpoint);\n vm.warp(oracle.computeL2Timestamp(checkpoint) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(keccak256(abi.encode(2)), checkpoint, 0, 0);\n\n // warp to the final second of the finalization period\n uint256 finalizationHorizon = block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS();\n vm.warp(finalizationHorizon);\n // The checkpointed block should not be finalized until 1 second from now.\n assertEq(op.isOutputFinalized(nextOutputIndex), false);\n // Nor should a block after it\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n\n // warp past the finalization period\n vm.warp(finalizationHorizon + 1);\n // It should now be finalized.\n assertEq(op.isOutputFinalized(nextOutputIndex), true);\n // But not the block after it.\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n }\n}\n\ncontract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n // Utility function used in the subsequent test. This is necessary to assert that the\n // reentrant call will revert.\n function callPortalAndExpectRevert() external payable {\n vm.expectRevert(\"OptimismPortal: can only trigger one withdrawal per transaction\");\n // Arguments here don't matter, as the require check is the first thing that happens.\n // We assume that this has already been proven.\n op.finalizeWithdrawalTransaction(_defaultTx);\n // Assert that the withdrawal was not finalized.\n assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx)));\n }\n\n /**\n * @notice Proving withdrawal transactions should revert when paused\n */\n function test_proveWithdrawalTransaction_paused_reverts() external {\n vm.prank(op.GUARDIAN());\n op.pause();\n\n vm.expectRevert(\"OptimismPortal: paused\");\n op.proveWithdrawalTransaction({\n _tx: _defaultTx,\n _l2OutputIndex: _proposedOutputIndex,\n _outputRootProof: _outputRootProof,\n _withdrawalProof: _withdrawalProof\n });\n }\n\n // Test: proveWithdrawalTransaction cannot prove a withdrawal with itself (the OptimismPortal) as the target.\n function test_proveWithdrawalTransaction_onSelfCall_reverts() external {\n _defaultTx.target = address(op);\n vm.expectRevert(\"OptimismPortal: you cannot send messages to the portal contract\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the outputRootProof does not match the output root\n function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external {\n // Modify the version to invalidate the withdrawal proof.\n _outputRootProof.version = bytes32(uint256(1));\n vm.expectRevert(\"OptimismPortal: invalid output root proof\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the proof is invalid due to non-existence of\n // the withdrawal.\n function test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() external {\n // modify the default test values to invalidate the proof.\n _defaultTx.data = hex\"abcd\";\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the passed transaction's withdrawalHash has\n // already been proven.\n function test_proveWithdrawalTransaction_replayProve_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: withdrawal hash has already been proven\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has\n // already been proven AND the output root has changed AND the l2BlockNumber stays the same.\n function test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`\n // inside of the `provenWithdrawal`s mapping.\n bytes32 slot;\n assembly {\n mstore(0x00, sload(_withdrawalHash.slot))\n mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in the OptimismPortal\n slot := keccak256(0x00, 0x40)\n }\n\n // Store a different output root within the `provenWithdrawals` mapping without\n // touching the l2BlockNumber or timestamp.\n vm.store(address(op), slot, bytes32(0));\n\n // Warp ahead 1 second\n vm.warp(block.timestamp + 1);\n\n // Even though we have already proven this withdrawalHash, we should be allowed to re-submit\n // our proof with a changed outputRoot\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Ensure that the withdrawal was updated within the mapping\n (, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);\n assertEq(timestamp, block.timestamp);\n }\n\n // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has\n // already been proven AND the output root + output index + l2BlockNumber changes.\n function test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds()\n external\n {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`\n // inside of the `provenWithdrawal`s mapping.\n bytes32 slot;\n assembly {\n mstore(0x00, sload(_withdrawalHash.slot))\n mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in OptimismPortal\n slot := keccak256(0x00, 0x40)\n }\n\n // Store a dummy output root within the `provenWithdrawals` mapping without touching the\n // l2BlockNumber or timestamp.\n vm.store(address(op), slot, bytes32(0));\n\n // Fetch the output proposal at `_proposedOutputIndex` from the L2OutputOracle\n Types.OutputProposal memory proposal = op.L2_ORACLE().getL2Output(_proposedOutputIndex);\n\n // Propose the same output root again, creating the same output at a different index + l2BlockNumber.\n vm.startPrank(op.L2_ORACLE().PROPOSER());\n op.L2_ORACLE().proposeL2Output(\n proposal.outputRoot,\n op.L2_ORACLE().nextBlockNumber(),\n blockhash(block.number),\n block.number\n );\n vm.stopPrank();\n\n // Warp ahead 1 second\n vm.warp(block.timestamp + 1);\n\n // Even though we have already proven this withdrawalHash, we should be allowed to re-submit\n // our proof with a changed outputRoot + a different output index\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex + 1,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Ensure that the withdrawal was updated within the mapping\n (, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);\n assertEq(timestamp, block.timestamp);\n }\n\n // Test: proveWithdrawalTransaction succeeds and emits the WithdrawalProven event.\n function test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: finalizeWithdrawalTransaction succeeds and emits the WithdrawalFinalized event.\n function test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, false, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore + 100);\n }\n\n /**\n * @notice Finalizing withdrawal transactions should revert when paused\n */\n function test_finalizeWithdrawalTransaction_paused_reverts() external {\n vm.prank(op.GUARDIAN());\n op.pause();\n\n vm.expectRevert(\"OptimismPortal: paused\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has not been proven.\n function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectRevert(\"OptimismPortal: withdrawal has not been proven yet\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if withdrawal not proven long enough ago.\n function test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Mock a call where the resulting output root is anything but the original output root. In\n // this case we just use bytes32(uint256(1)).\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(bytes32(uint256(1)), _proposedBlockNumber)\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the provenWithdrawal's timestamp is less\n // than the L2 output oracle's starting timestamp\n function test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a startingTimestamp change on the L2 Oracle\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSignature(\"startingTimestamp()\"),\n abi.encode(block.timestamp + 1)\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output root proven is not the same as the\n // output root at the time of finalization.\n function test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock an outputRoot change on the output proposal before attempting\n // to finalize the withdrawal.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n bytes32(uint256(0)),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output proposal's timestamp has\n // not passed the finalization period.\n function test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a timestamp change on the output proposal that has not passed the\n // finalization period.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(block.timestamp + 1),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\"OptimismPortal: output proposal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction fails because the target reverts,\n // and emits the WithdrawalFinalized event with success=false.\n function test_finalizeWithdrawalTransaction_targetFails_fails() external {\n uint256 bobBalanceBefore = address(bob).balance;\n vm.etch(bob, hex\"fe\"); // Contract with just the invalid opcode.\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, false);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the finalization period has not yet passed.\n function test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() external {\n // Setup the Oracle to return an output with a recent timestamp\n uint256 recentTimestamp = block.timestamp - 1000;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(recentTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has already been finalized.\n function test_finalizeWithdrawalTransaction_onReplay_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if insufficient gas is supplied.\n function test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() external {\n // This number was identified through trial and error.\n uint256 gasLimit = 150_000;\n Types.WithdrawalTransaction memory insufficientGasTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: gasLimit,\n data: hex\"\"\n });\n\n // Get updated proof inputs.\n (bytes32 stateRoot, bytes32 storageRoot, , , bytes[] memory withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(insufficientGasTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n Hashing.hashOutputRootProof(outputRootProof),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n insufficientGasTx,\n _proposedOutputIndex,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectRevert(\"SafeCall: Not enough gas\");\n op.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if a sub-call attempts to finalize another\n // withdrawal.\n function test_finalizeWithdrawalTransaction_onReentrancy_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Copy and modify the default test values to attempt a reentrant call by first calling to\n // this contract's callPortalAndExpectRevert() function above.\n Types.WithdrawalTransaction memory _testTx = _defaultTx;\n _testTx.target = address(this);\n _testTx.data = abi.encodeWithSelector(this.callPortalAndExpectRevert.selector);\n\n // Get modified proof inputs.\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_testTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n // Setup the Oracle to return the outputRoot we want as well as a finalized timestamp.\n uint256 finalizedTimestamp = block.timestamp - oracle.FINALIZATION_PERIOD_SECONDS() - 1;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n outputRoot,\n uint128(finalizedTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(withdrawalHash, alice, address(this));\n op.proveWithdrawalTransaction(\n _testTx,\n _proposedBlockNumber,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectCall(address(this), _testTx.data);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_testTx);\n\n // Ensure that bob's balance was not changed by the reentrant call.\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n function testDiff_finalizeWithdrawalTransaction_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n vm.assume(\n _target != address(op) && // Cannot call the optimism portal or a contract\n _target.code.length == 0 && // No accounts with code\n _target != CONSOLE && // The console has no code but behaves like a contract\n uint160(_target) > 9 // No precompiles (or zero address)\n );\n\n // Total ETH supply is currently about 120M ETH.\n uint256 value = bound(_value, 0, 200_000_000 ether);\n vm.deal(address(op), value);\n\n uint256 gasLimit = bound(_gasLimit, 0, 50_000_000);\n uint256 nonce = messagePasser.messageNonce();\n\n // Get a withdrawal transaction and mock proof from the differential testing script.\n Types.WithdrawalTransaction memory _tx = Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: value,\n gasLimit: gasLimit,\n data: _data\n });\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_tx);\n\n // Create the output root proof\n Types.OutputRootProof memory proof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n\n // Ensure the values returned from ffi are correct\n assertEq(outputRoot, Hashing.hashOutputRootProof(proof));\n assertEq(withdrawalHash, Hashing.hashWithdrawal(_tx));\n\n // Setup the Oracle to return the outputRoot\n vm.mockCall(\n address(oracle),\n abi.encodeWithSelector(oracle.getL2Output.selector),\n abi.encode(outputRoot, block.timestamp, 100)\n );\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _tx,\n 100, // l2BlockNumber\n proof,\n withdrawalProof\n );\n (bytes32 _root, , ) = op.provenWithdrawals(withdrawalHash);\n assertTrue(_root != bytes32(0));\n\n // Warp past the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Finalize the withdrawal transaction\n vm.expectCallMinGas(_tx.target, _tx.value, uint64(_tx.gasLimit), _tx.data);\n op.finalizeWithdrawalTransaction(_tx);\n assertTrue(op.finalizedWithdrawals(withdrawalHash));\n }\n}\n\ncontract OptimismPortalUpgradeable_Test is Portal_Initializer {\n Proxy internal proxy;\n uint64 initialBlockNum;\n\n function setUp() public override {\n super.setUp();\n initialBlockNum = uint64(block.number);\n proxy = Proxy(payable(address(op)));\n }\n\n function test_params_initValuesOnProxy_succeeds() external {\n OptimismPortal p = OptimismPortal(payable(address(proxy)));\n\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = p.params();\n\n ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig();\n assertEq(prevBaseFee, rcfg.minimumBaseFee);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_initialize_cannotInitProxy_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(payable(proxy)).initialize(false);\n }\n\n function test_initialize_cannotInitImpl_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(opImpl).initialize(false);\n }\n\n function test_upgradeToAndCall_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(op), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(op), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(op)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n\n/**\n * @title OptimismPortalResourceFuzz_Test\n * @dev Test various values of the resource metering config to ensure that deposits cannot be\n * broken by changing the config.\n */\ncontract OptimismPortalResourceFuzz_Test is Portal_Initializer {\n /**\n * @dev The max gas limit observed throughout this test. Setting this too high can cause\n * the test to take too long to run.\n */\n uint256 constant MAX_GAS_LIMIT = 30_000_000;\n\n /**\n * @dev Test that various values of the resource metering config will not break deposits.\n */\n function testFuzz_systemConfigDeposit_succeeds(\n uint32 _maxResourceLimit,\n uint8 _elasticityMultiplier,\n uint8 _baseFeeMaxChangeDenominator,\n uint32 _minimumBaseFee,\n uint32 _systemTxMaxGas,\n uint128 _maximumBaseFee,\n uint64 _gasLimit,\n uint64 _prevBoughtGas,\n uint128 _prevBaseFee,\n uint8 _blockDiff\n ) external {\n // Get the set system gas limit\n uint64 gasLimit = systemConfig.gasLimit();\n // Bound resource config\n _maxResourceLimit = uint32(bound(_maxResourceLimit, 21000, MAX_GAS_LIMIT / 8));\n _gasLimit = uint64(bound(_gasLimit, 21000, _maxResourceLimit));\n _prevBaseFee = uint128(bound(_prevBaseFee, 0, 3 gwei));\n // Prevent values that would cause reverts\n vm.assume(gasLimit >= _gasLimit);\n vm.assume(_minimumBaseFee < _maximumBaseFee);\n vm.assume(_baseFeeMaxChangeDenominator > 1);\n vm.assume(uint256(_maxResourceLimit) + uint256(_systemTxMaxGas) <= gasLimit);\n vm.assume(_elasticityMultiplier > 0);\n vm.assume(\n ((_maxResourceLimit / _elasticityMultiplier) * _elasticityMultiplier) ==\n _maxResourceLimit\n );\n _prevBoughtGas = uint64(bound(_prevBoughtGas, 0, _maxResourceLimit - _gasLimit));\n _blockDiff = uint8(bound(_blockDiff, 0, 3));\n\n // Create a resource config to mock the call to the system config with\n ResourceMetering.ResourceConfig memory rcfg = ResourceMetering.ResourceConfig({\n maxResourceLimit: _maxResourceLimit,\n elasticityMultiplier: _elasticityMultiplier,\n baseFeeMaxChangeDenominator: _baseFeeMaxChangeDenominator,\n minimumBaseFee: _minimumBaseFee,\n systemTxMaxGas: _systemTxMaxGas,\n maximumBaseFee: _maximumBaseFee\n });\n vm.mockCall(\n address(systemConfig),\n abi.encodeWithSelector(systemConfig.resourceConfig.selector),\n abi.encode(rcfg)\n );\n\n // Set the resource params\n uint256 _prevBlockNum = block.number - _blockDiff;\n vm.store(\n address(op),\n bytes32(uint256(1)),\n bytes32((_prevBlockNum << 192) | (uint256(_prevBoughtGas) << 128) | _prevBaseFee)\n );\n // Ensure that the storage setting is correct\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = op.params();\n assertEq(prevBaseFee, _prevBaseFee);\n assertEq(prevBoughtGas, _prevBoughtGas);\n assertEq(prevBlockNum, _prevBlockNum);\n\n // Do a deposit, should not revert\n op.depositTransaction{ gas: MAX_GAS_LIMIT }({\n _to: address(0x20),\n _value: 0x40,\n _gasLimit: _gasLimit,\n _isCreation: false,\n _data: hex\"\"\n });\n }\n}\n" - }, - "contracts/test/Proxy.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract SimpleStorage {\n mapping(uint256 => uint256) internal store;\n\n function get(uint256 key) external payable returns (uint256) {\n return store[key];\n }\n\n function set(uint256 key, uint256 value) external payable {\n store[key] = value;\n }\n}\n\ncontract Clasher {\n function upgradeTo(address) external pure {\n revert(\"upgradeTo\");\n }\n}\n\ncontract Proxy_Test is Test {\n event Upgraded(address indexed implementation);\n event AdminChanged(address previousAdmin, address newAdmin);\n\n address alice = address(64);\n\n bytes32 internal constant IMPLEMENTATION_KEY =\n bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1);\n\n bytes32 internal constant OWNER_KEY = bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1);\n\n Proxy proxy;\n SimpleStorage simpleStorage;\n\n function setUp() external {\n // Deploy a proxy and simple storage contract as\n // the implementation\n proxy = new Proxy(alice);\n simpleStorage = new SimpleStorage();\n\n vm.prank(alice);\n proxy.upgradeTo(address(simpleStorage));\n }\n\n function test_implementationKey_succeeds() external {\n // The hardcoded implementation key should be correct\n vm.prank(alice);\n proxy.upgradeTo(address(6));\n\n bytes32 key = vm.load(address(proxy), IMPLEMENTATION_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(6));\n }\n\n function test_ownerKey_succeeds() external {\n // The hardcoded owner key should be correct\n vm.prank(alice);\n proxy.changeAdmin(address(6));\n\n bytes32 key = vm.load(address(proxy), OWNER_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(address(6));\n address owner = proxy.admin();\n assertEq(owner, address(6));\n }\n\n function test_proxyCallToImp_notAdmin_succeeds() external {\n // The implementation does not have a `upgradeTo`\n // method, calling `upgradeTo` not as the owner\n // should revert.\n vm.expectRevert();\n proxy.upgradeTo(address(64));\n\n // Call `upgradeTo` as the owner, it should succeed\n // and emit the `Upgraded` event.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(64));\n vm.prank(alice);\n proxy.upgradeTo(address(64));\n\n // Get the implementation as the owner\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(64));\n }\n\n function test_ownerProxyCall_notAdmin_succeeds() external {\n // Calling `changeAdmin` not as the owner should revert\n // as the implementation does not have a `changeAdmin` method.\n vm.expectRevert();\n proxy.changeAdmin(address(1));\n\n // Call `changeAdmin` as the owner, it should succeed\n // and emit the `AdminChanged` event.\n vm.expectEmit(true, true, true, true);\n emit AdminChanged(alice, address(1));\n vm.prank(alice);\n proxy.changeAdmin(address(1));\n\n // Calling `admin` not as the owner should\n // revert as the implementation does not have\n // a `admin` method.\n vm.expectRevert();\n proxy.admin();\n\n // Calling `admin` as the owner should work.\n vm.prank(address(1));\n address owner = proxy.admin();\n assertEq(owner, address(1));\n }\n\n function test_delegatesToImpl_succeeds() external {\n // Call the storage setter on the proxy\n SimpleStorage(address(proxy)).set(1, 1);\n\n // The key should not be set in the implementation\n uint256 result = simpleStorage.get(1);\n assertEq(result, 0);\n {\n // The key should be set in the proxy\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n\n {\n // The owner should be able to call through the proxy\n // when there is not a function selector crash\n vm.prank(alice);\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n }\n\n function test_upgradeToAndCall_succeeds() external {\n {\n // There should be nothing in the current proxy storage\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 0);\n }\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(simpleStorage));\n vm.prank(alice);\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The call should have impacted the state\n uint256 result = SimpleStorage(address(proxy)).get(1);\n assertEq(result, 1);\n }\n\n function test_upgradeToAndCall_functionDoesNotExist_reverts() external {\n // Get the current implementation address\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call. This reverts because the calldata doesn't\n // match a function on the implementation.\n vm.expectRevert(\"Proxy: delegatecall to new implementation contract failed\");\n vm.prank(alice);\n proxy.upgradeToAndCall(address(simpleStorage), hex\"\");\n\n // The implementation address should have not\n // updated because the call to `upgradeToAndCall`\n // reverted.\n vm.prank(alice);\n address postImpl = proxy.implementation();\n assertEq(impl, postImpl);\n\n // The attempt to `upgradeToAndCall`\n // should revert when it is not called by the owner.\n vm.expectRevert();\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n }\n\n function test_upgradeToAndCall_isPayable_succeeds() external {\n // Give alice some funds\n vm.deal(alice, 1 ether);\n // Set the implementation and call and send\n // value.\n vm.prank(alice);\n proxy.upgradeToAndCall{ value: 1 ether }(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The implementation address should be correct\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // The proxy should have a balance\n assertEq(address(proxy).balance, 1 ether);\n }\n\n function test_upgradeTo_clashingFunctionSignatures_succeeds() external {\n // Clasher has a clashing function with the proxy.\n Clasher clasher = new Clasher();\n\n // Set the clasher as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(clasher));\n\n {\n // Assert that the implementation was set properly.\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(clasher));\n }\n\n // Call the clashing function on the proxy\n // not as the owner so that the call passes through.\n // The implementation will revert so we can be\n // sure that the call passed through.\n vm.expectRevert(bytes(\"upgradeTo\"));\n proxy.upgradeTo(address(0));\n\n {\n // Now call the clashing function as the owner\n // and be sure that it doesn't pass through to\n // the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(0));\n }\n }\n\n // Allow for `eth_call` to call proxy methods\n // by setting \"from\" to `address(0)`.\n function test_implementation_zeroAddressCaller_succeeds() external {\n vm.prank(address(0));\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n }\n\n function test_implementation_isZeroAddress_reverts() external {\n // Set `address(0)` as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n\n (bool success, bytes memory returndata) = address(proxy).call(hex\"\");\n assertEq(success, false);\n\n bytes memory err = abi.encodeWithSignature(\n \"Error(string)\",\n \"Proxy: implementation not initialized\"\n );\n\n assertEq(returndata, err);\n }\n}\n" - }, - "contracts/test/ProxyAdmin.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { SimpleStorage } from \"./Proxy.t.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\n\ncontract ProxyAdmin_Test is Test {\n address alice = address(64);\n\n Proxy proxy;\n L1ChugSplashProxy chugsplash;\n ResolvedDelegateProxy resolved;\n\n AddressManager addressManager;\n\n ProxyAdmin admin;\n\n SimpleStorage implementation;\n\n function setUp() external {\n // Deploy the proxy admin\n admin = new ProxyAdmin(alice);\n // Deploy the standard proxy\n proxy = new Proxy(address(admin));\n\n // Deploy the legacy L1ChugSplashProxy with the admin as the owner\n chugsplash = new L1ChugSplashProxy(address(admin));\n\n // Deploy the legacy AddressManager\n addressManager = new AddressManager();\n // The proxy admin must be the new owner of the address manager\n addressManager.transferOwnership(address(admin));\n // Deploy a legacy ResolvedDelegateProxy with the name `a`.\n // Whatever `a` is set to in AddressManager will be the address\n // that is used for the implementation.\n resolved = new ResolvedDelegateProxy(addressManager, \"a\");\n\n // Impersonate alice for setting up the admin.\n vm.startPrank(alice);\n // Set the address of the address manager in the admin so that it\n // can resolve the implementation address of legacy\n // ResolvedDelegateProxy based proxies.\n admin.setAddressManager(addressManager);\n // Set the reverse lookup of the ResolvedDelegateProxy\n // proxy\n admin.setImplementationName(address(resolved), \"a\");\n\n // Set the proxy types\n admin.setProxyType(address(proxy), ProxyAdmin.ProxyType.ERC1967);\n admin.setProxyType(address(chugsplash), ProxyAdmin.ProxyType.CHUGSPLASH);\n admin.setProxyType(address(resolved), ProxyAdmin.ProxyType.RESOLVED);\n vm.stopPrank();\n\n implementation = new SimpleStorage();\n }\n\n function test_setImplementationName_succeeds() external {\n vm.prank(alice);\n admin.setImplementationName(address(1), \"foo\");\n assertEq(admin.implementationName(address(1)), \"foo\");\n }\n\n function test_setAddressManager_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setAddressManager(AddressManager((address(0))));\n }\n\n function test_setImplementationName_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setImplementationName(address(0), \"foo\");\n }\n\n function test_setProxyType_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setProxyType(address(0), ProxyAdmin.ProxyType.CHUGSPLASH);\n }\n\n function test_owner_succeeds() external {\n assertEq(admin.owner(), alice);\n }\n\n function test_proxyType_succeeds() external {\n assertEq(uint256(admin.proxyType(address(proxy))), uint256(ProxyAdmin.ProxyType.ERC1967));\n assertEq(\n uint256(admin.proxyType(address(chugsplash))),\n uint256(ProxyAdmin.ProxyType.CHUGSPLASH)\n );\n assertEq(\n uint256(admin.proxyType(address(resolved))),\n uint256(ProxyAdmin.ProxyType.RESOLVED)\n );\n }\n\n function test_erc1967GetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(proxy));\n }\n\n function test_chugsplashGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(resolved));\n }\n\n function getProxyImplementation(address payable _proxy) internal {\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(0));\n }\n\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n }\n\n function test_erc1967GetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(resolved));\n }\n\n function getProxyAdmin(address payable _proxy) internal {\n address owner = admin.getProxyAdmin(_proxy);\n assertEq(owner, address(admin));\n }\n\n function test_erc1967ChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(resolved));\n }\n\n function changeProxyAdmin(address payable _proxy) internal {\n ProxyAdmin.ProxyType proxyType = admin.proxyType(address(_proxy));\n\n vm.prank(alice);\n admin.changeProxyAdmin(_proxy, address(128));\n\n // The proxy is no longer the admin and can\n // no longer call the proxy interface except for\n // the ResolvedDelegate type on which anybody can\n // call the admin interface.\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n vm.expectRevert(\"Proxy: implementation not initialized\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n vm.expectRevert(\"L1ChugSplashProxy: implementation is not set yet\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n // Just an empty block to show that all cases are covered\n } else {\n vm.expectRevert(\"ProxyAdmin: unknown proxy type\");\n }\n\n // Call the proxy contract directly to get the admin.\n // Different proxy types have different interfaces.\n vm.prank(address(128));\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n assertEq(Proxy(payable(_proxy)).admin(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n assertEq(L1ChugSplashProxy(payable(_proxy)).getOwner(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n assertEq(addressManager.owner(), address(128));\n } else {\n assert(false);\n }\n }\n\n function test_erc1967Upgrade_succeeds() external {\n upgrade(payable(proxy));\n }\n\n function test_chugsplashUpgrade_succeeds() external {\n upgrade(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgrade_succeeds() external {\n upgrade(payable(resolved));\n }\n\n function upgrade(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n\n function test_erc1967UpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(proxy));\n }\n\n function test_chugsplashUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(resolved));\n }\n\n function upgradeAndCall(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgradeAndCall(\n _proxy,\n address(implementation),\n abi.encodeWithSelector(SimpleStorage.set.selector, 1, 1)\n );\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n\n uint256 got = SimpleStorage(address(_proxy)).get(1);\n assertEq(got, 1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.changeProxyAdmin(payable(proxy), address(0));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgrade(payable(proxy), address(implementation));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgradeAndCall(payable(proxy), address(implementation), hex\"\");\n }\n\n function test_isUpgrading_succeeds() external {\n assertEq(false, admin.isUpgrading());\n\n vm.prank(alice);\n admin.setUpgrading(true);\n assertEq(true, admin.isUpgrading());\n }\n}\n" - }, - "contracts/test/RLP.t.sol": { - "content": "// SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\n/**\n * @title LibRLP\n * @notice Via https://github.com/Rari-Capital/solmate/issues/207.\n */\nlibrary LibRLP {\n using Bytes32AddressLib for bytes32;\n\n function computeAddress(address deployer, uint256 nonce) internal pure returns (address) {\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80)))\n .fromLast20Bytes();\n if (nonce <= 0x7f)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce)))\n .fromLast20Bytes();\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= type(uint8).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd7),\n bytes1(0x94),\n deployer,\n bytes1(0x81),\n uint8(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint16).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd8),\n bytes1(0x94),\n deployer,\n bytes1(0x82),\n uint16(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint24).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd9),\n bytes1(0x94),\n deployer,\n bytes1(0x83),\n uint24(nonce)\n )\n ).fromLast20Bytes();\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return\n keccak256(\n abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))\n ).fromLast20Bytes();\n }\n}\n" - }, - "contracts/test/RLPReader.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { RLPReader } from \"../libraries/rlp/RLPReader.sol\";\n\ncontract RLPReader_readBytes_Test is CommonTest {\n function test_readBytes_bytestring00_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"00\"), hex\"00\");\n }\n\n function test_readBytes_bytestring01_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"01\"), hex\"01\");\n }\n\n function test_readBytes_bytestring7f_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"7f\"), hex\"7f\");\n }\n\n function test_readBytes_revertListItem_reverts() external {\n vm.expectRevert(\"RLPReader: decoded item type for bytes is not a data item\");\n RLPReader.readBytes(hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_readBytes_invalidStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n RLPReader.readBytes(hex\"b9\");\n }\n\n function test_readBytes_invalidListLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n RLPReader.readBytes(hex\"ff\");\n }\n\n function test_readBytes_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: bytes value contains an invalid remainder\");\n RLPReader.readBytes(hex\"800a\");\n }\n\n function test_readBytes_invalidPrefix_reverts() external {\n vm.expectRevert(\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n RLPReader.readBytes(hex\"810a\");\n }\n}\n\ncontract RLPReader_readList_Test is CommonTest {\n function test_readList_empty_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c0\");\n assertEq(list.length, 0);\n }\n\n function test_readList_multiList_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c6827a77c10401\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"827a77\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c104\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"01\");\n }\n\n function test_readList_shortListMax1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n\n assertEq(list.length, 11);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[4]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[5]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[6]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[7]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[8]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[9]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[10]), hex\"8471776572\");\n }\n\n function test_readList_longList1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n\n assertEq(list.length, 4);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"cf84617364668471776572847a786376\");\n }\n\n function test_readList_longList2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n assertEq(list.length, 32);\n\n for (uint256 i = 0; i < 32; i++) {\n assertEq(RLPReader.readRawBytes(list[i]), hex\"cf84617364668471776572847a786376\");\n }\n }\n\n function test_readList_listLongerThan32Elements_reverts() external {\n vm.expectRevert(stdError.indexOOBError);\n RLPReader.readList(\n hex\"e1454545454545454545454545454545454545454545454545454545454545454545\"\n );\n }\n\n function test_readList_listOfLists_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c4c2c0c0c0\");\n assertEq(list.length, 2);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c2c0c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c0\");\n }\n\n function test_readList_listOfLists2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c7c0c1c0c3c0c1c0\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c1c0\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"c3c0c1c0\");\n }\n\n function test_readList_dictTest1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n assertEq(list.length, 4);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"ca846b6579318476616c31\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"ca846b6579328476616c32\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"ca846b6579338476616c33\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"ca846b6579348476616c34\");\n }\n\n function test_readList_invalidShortList_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efdebd\");\n }\n\n function test_readList_longStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efb83600\");\n }\n\n function test_readList_notLongEnough_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(\n hex\"efdebdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n );\n }\n\n function test_readList_int32Overflow_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"bf0f000000000000021111\");\n }\n\n function test_readList_int32Overflow2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ff0f000000000000021111\");\n }\n\n function test_readList_incorrectLengthInArray_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b9002100dc2b275d0f74e8a53e6f4ec61b27f24278820be3f82ea2110e582081b0565df0\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b90040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(hex\"b800\");\n }\n\n function test_readList_leadingZerosInLongLengthList1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must not have any leading zeros (long list)\");\n RLPReader.readList(\n hex\"fb00000040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_nonOptimalLongLengthArray1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b81000112233445566778899aabbccddeeff\");\n }\n\n function test_readList_nonOptimalLongLengthArray2_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b801ff\");\n }\n\n function test_readList_invalidValue_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n RLPReader.readList(hex\"91\");\n }\n\n function test_readList_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n RLPReader.readList(hex\"c000\");\n }\n\n function test_readList_notEnoughContentForString1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"ba010000aabbccddeeff\");\n }\n\n function test_readList_notEnoughContentForString2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"b840ffeeddccbbaa99887766554433221100\");\n }\n\n function test_readList_notEnoughContentForList1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"f90180\");\n }\n\n function test_readList_notEnoughContentForList2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ffffffffffffffffff0001020304050607\");\n }\n\n function test_readList_longStringLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b80100\");\n }\n\n function test_readList_longListLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long list)\");\n RLPReader.readList(hex\"f80100\");\n }\n}\n" - }, - "contracts/test/RLPWriter.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { RLPWriter } from \"../libraries/rlp/RLPWriter.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\n\ncontract RLPWriter_writeString_Test is CommonTest {\n function test_writeString_empty_succeeds() external {\n assertEq(RLPWriter.writeString(\"\"), hex\"80\");\n }\n\n function test_writeString_bytestring00_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0000\"), hex\"00\");\n }\n\n function test_writeString_bytestring01_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0001\"), hex\"01\");\n }\n\n function test_writeString_bytestring7f_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u007F\"), hex\"7f\");\n }\n\n function test_writeString_shortstring_succeeds() external {\n assertEq(RLPWriter.writeString(\"dog\"), hex\"83646f67\");\n }\n\n function test_writeString_shortstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing eli\"),\n hex\"b74c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c69\"\n );\n }\n\n function test_writeString_longstring_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing elit\"),\n hex\"b8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974\"\n );\n }\n\n function test_writeString_longstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\n \"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\"\n ),\n hex\"b904004c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20437572616269747572206d6175726973206d61676e612c20737573636970697420736564207665686963756c61206e6f6e2c20696163756c697320666175636962757320746f72746f722e2050726f696e20737573636970697420756c74726963696573206d616c6573756164612e204475697320746f72746f7220656c69742c2064696374756d2071756973207472697374697175652065752c20756c7472696365732061742072697375732e204d6f72626920612065737420696d70657264696574206d6920756c6c616d636f7270657220616c6971756574207375736369706974206e6563206c6f72656d2e2041656e65616e2071756973206c656f206d6f6c6c69732c2076756c70757461746520656c6974207661726975732c20636f6e73657175617420656e696d2e204e756c6c6120756c74726963657320747572706973206a7573746f2c20657420706f73756572652075726e6120636f6e7365637465747572206e65632e2050726f696e206e6f6e20636f6e76616c6c6973206d657475732e20446f6e65632074656d706f7220697073756d20696e206d617572697320636f6e67756520736f6c6c696369747564696e2e20566573746962756c756d20616e746520697073756d207072696d697320696e206661756369627573206f726369206c756374757320657420756c74726963657320706f737565726520637562696c69612043757261653b2053757370656e646973736520636f6e76616c6c69732073656d2076656c206d617373612066617563696275732c2065676574206c6163696e6961206c616375732074656d706f722e204e756c6c61207175697320756c747269636965732070757275732e2050726f696e20617563746f722072686f6e637573206e69626820636f6e64696d656e74756d206d6f6c6c69732e20416c697175616d20636f6e73657175617420656e696d206174206d65747573206c75637475732c206120656c656966656e6420707572757320656765737461732e20437572616269747572206174206e696268206d657475732e204e616d20626962656e64756d2c206e6571756520617420617563746f72207472697374697175652c206c6f72656d206c696265726f20616c697175657420617263752c206e6f6e20696e74657264756d2074656c6c7573206c65637475732073697420616d65742065726f732e20437261732072686f6e6375732c206d65747573206163206f726e617265206375727375732c20646f6c6f72206a7573746f20756c747269636573206d657475732c20617420756c6c616d636f7270657220766f6c7574706174\"\n );\n }\n}\n\ncontract RLPWriter_writeUint_Test is CommonTest {\n function test_writeUint_zero_succeeds() external {\n assertEq(RLPWriter.writeUint(0x0), hex\"80\");\n }\n\n function test_writeUint_smallint_succeeds() external {\n assertEq(RLPWriter.writeUint(1), hex\"01\");\n }\n\n function test_writeUint_smallint2_succeeds() external {\n assertEq(RLPWriter.writeUint(16), hex\"10\");\n }\n\n function test_writeUint_smallint3_succeeds() external {\n assertEq(RLPWriter.writeUint(79), hex\"4f\");\n }\n\n function test_writeUint_smallint4_succeeds() external {\n assertEq(RLPWriter.writeUint(127), hex\"7f\");\n }\n\n function test_writeUint_mediumint_succeeds() external {\n assertEq(RLPWriter.writeUint(128), hex\"8180\");\n }\n\n function test_writeUint_mediumint2_succeeds() external {\n assertEq(RLPWriter.writeUint(1000), hex\"8203e8\");\n }\n\n function test_writeUint_mediumint3_succeeds() external {\n assertEq(RLPWriter.writeUint(100000), hex\"830186a0\");\n }\n}\n\ncontract RLPWriter_writeList_Test is CommonTest {\n function test_writeList_empty_succeeds() external {\n assertEq(RLPWriter.writeList(new bytes[](0)), hex\"c0\");\n }\n\n function test_writeList_stringList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeString(\"dog\");\n list[1] = RLPWriter.writeString(\"god\");\n list[2] = RLPWriter.writeString(\"cat\");\n\n assertEq(RLPWriter.writeList(list), hex\"cc83646f6783676f6483636174\");\n }\n\n function test_writeList_multiList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeUint(4);\n\n list[0] = RLPWriter.writeString(\"zw\");\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeUint(1);\n\n assertEq(RLPWriter.writeList(list), hex\"c6827a77c10401\");\n }\n\n function test_writeList_shortListMax1_succeeds() external {\n bytes[] memory list = new bytes[](11);\n list[0] = RLPWriter.writeString(\"asdf\");\n list[1] = RLPWriter.writeString(\"qwer\");\n list[2] = RLPWriter.writeString(\"zxcv\");\n list[3] = RLPWriter.writeString(\"asdf\");\n list[4] = RLPWriter.writeString(\"qwer\");\n list[5] = RLPWriter.writeString(\"zxcv\");\n list[6] = RLPWriter.writeString(\"asdf\");\n list[7] = RLPWriter.writeString(\"qwer\");\n list[8] = RLPWriter.writeString(\"zxcv\");\n list[9] = RLPWriter.writeString(\"asdf\");\n list[10] = RLPWriter.writeString(\"qwer\");\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n }\n\n function test_writeList_longlist1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list2);\n list[3] = RLPWriter.writeList(list2);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_longlist2_succeeds() external {\n bytes[] memory list = new bytes[](32);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n for (uint256 i = 0; i < 32; i++) {\n list[i] = RLPWriter.writeList(list2);\n }\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_listoflists_succeeds() external {\n // [ [ [], [] ], [] ]\n bytes[] memory list = new bytes[](2);\n bytes[] memory list2 = new bytes[](2);\n\n list2[0] = RLPWriter.writeList(new bytes[](0));\n list2[1] = RLPWriter.writeList(new bytes[](0));\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(new bytes[](0));\n\n assertEq(RLPWriter.writeList(list), hex\"c4c2c0c0c0\");\n }\n\n function test_writeList_listoflists2_succeeds() external {\n // [ [], [[]], [ [], [[]] ] ]\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeList(new bytes[](0));\n\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeList(new bytes[](0));\n\n list[1] = RLPWriter.writeList(list2);\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeList(new bytes[](0));\n list3[1] = RLPWriter.writeList(list2);\n\n list[2] = RLPWriter.writeList(list3);\n\n assertEq(RLPWriter.writeList(list), hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_writeList_dictTest1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n\n bytes[] memory list1 = new bytes[](2);\n list1[0] = RLPWriter.writeString(\"key1\");\n list1[1] = RLPWriter.writeString(\"val1\");\n\n bytes[] memory list2 = new bytes[](2);\n list2[0] = RLPWriter.writeString(\"key2\");\n list2[1] = RLPWriter.writeString(\"val2\");\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeString(\"key3\");\n list3[1] = RLPWriter.writeString(\"val3\");\n\n bytes[] memory list4 = new bytes[](2);\n list4[0] = RLPWriter.writeString(\"key4\");\n list4[1] = RLPWriter.writeString(\"val4\");\n\n list[0] = RLPWriter.writeList(list1);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list3);\n list[3] = RLPWriter.writeList(list4);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n }\n}\n" - }, - "contracts/test/ResolvedDelegateProxy.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\n\ncontract ResolvedDelegateProxy_Test is Test {\n AddressManager internal addressManager;\n SimpleImplementation internal impl;\n SimpleImplementation internal proxy;\n\n function setUp() public {\n // Set up the address manager.\n addressManager = new AddressManager();\n impl = new SimpleImplementation();\n addressManager.setAddress(\"SimpleImplementation\", address(impl));\n\n // Set up the proxy.\n proxy = SimpleImplementation(\n address(new ResolvedDelegateProxy(addressManager, \"SimpleImplementation\"))\n );\n }\n\n // Tests that the proxy properly bubbles up returndata when the delegatecall succeeds.\n function testFuzz_fallback_delegateCallFoo_succeeds(uint256 x) public {\n vm.expectCall(address(impl), abi.encodeWithSelector(impl.foo.selector, x));\n assertEq(proxy.foo(x), x);\n }\n\n // Tests that the proxy properly bubbles up returndata when the delegatecall reverts.\n function test_fallback_delegateCallBar_reverts() public {\n vm.expectRevert(\"SimpleImplementation: revert\");\n vm.expectCall(address(impl), abi.encodeWithSelector(impl.bar.selector));\n proxy.bar();\n }\n\n // Tests that the proxy fallback reverts as expected if the implementation within the\n // address manager is not set.\n function test_fallback_addressManagerNotSet_reverts() public {\n AddressManager am = new AddressManager();\n SimpleImplementation p = SimpleImplementation(\n address(new ResolvedDelegateProxy(am, \"SimpleImplementation\"))\n );\n\n vm.expectRevert(\"ResolvedDelegateProxy: target address must be initialized\");\n p.foo(0);\n }\n}\n\ncontract SimpleImplementation {\n function foo(uint256 _x) public pure returns (uint256) {\n return _x;\n }\n\n function bar() public pure {\n revert(\"SimpleImplementation: revert\");\n }\n}\n" - }, - "contracts/test/ResourceMetering.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract MeterUser is ResourceMetering {\n ResourceMetering.ResourceConfig public innerConfig;\n\n constructor() {\n initialize();\n innerConfig = Constants.DEFAULT_RESOURCE_CONFIG();\n }\n\n function initialize() public initializer {\n __ResourceMetering_init();\n }\n\n function resourceConfig() public view returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig();\n }\n\n function _resourceConfig()\n internal\n view\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return innerConfig;\n }\n\n function use(uint64 _amount) public metered(_amount) {}\n\n function set(\n uint128 _prevBaseFee,\n uint64 _prevBoughtGas,\n uint64 _prevBlockNum\n ) public {\n params = ResourceMetering.ResourceParams({\n prevBaseFee: _prevBaseFee,\n prevBoughtGas: _prevBoughtGas,\n prevBlockNum: _prevBlockNum\n });\n }\n\n function setParams(ResourceMetering.ResourceConfig memory newConfig) public {\n innerConfig = newConfig;\n }\n}\n\n/**\n * @title ResourceConfig\n * @notice The tests are based on the default config values. It is expected that\n * the config values used in these tests are ran in production.\n */\ncontract ResourceMetering_Test is Test {\n MeterUser internal meter;\n uint64 initialBlockNum;\n\n function setUp() public {\n meter = new MeterUser();\n initialBlockNum = uint64(block.number);\n }\n\n function test_meter_initialResourceParams_succeeds() external {\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n\n assertEq(prevBaseFee, rcfg.minimumBaseFee);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_updateParamsNoChange_succeeds() external {\n meter.use(0); // equivalent to just updating the base fee and block number\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n meter.use(0);\n (uint128 postBaseFee, uint64 postBoughtGas, uint64 postBlockNum) = meter.params();\n\n assertEq(postBaseFee, prevBaseFee);\n assertEq(postBoughtGas, prevBoughtGas);\n assertEq(postBlockNum, prevBlockNum);\n }\n\n function test_meter_updateOneEmptyBlock_succeeds() external {\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 1);\n }\n\n function test_meter_updateTwoEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 2);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 2);\n }\n\n function test_meter_updateTenEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 10);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 10);\n }\n\n function test_meter_updateNoGasDelta_succeeds() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint256 target = uint256(rcfg.maxResourceLimit) / uint256(rcfg.elasticityMultiplier);\n meter.use(uint64(target));\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1000000000);\n assertEq(prevBoughtGas, target);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_useMax_succeeds() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n meter.use(target * elasticityMultiplier);\n\n (, uint64 prevBoughtGas, ) = meter.params();\n assertEq(prevBoughtGas, target * elasticityMultiplier);\n\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 postBaseFee, , ) = meter.params();\n assertEq(postBaseFee, 2125000000);\n }\n\n /**\n * @notice This tests that the metered modifier reverts if\n * the ResourceConfig baseFeeMaxChangeDenominator\n * is set to 1.\n * Since the metered modifier internally calls\n * solmate's powWad function, it will revert\n * with the error string \"UNDEFINED\" since the\n * first parameter will be computed as 0.\n */\n function test_meter_denominatorEq1_reverts() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n rcfg.baseFeeMaxChangeDenominator = 1;\n meter.setParams(rcfg);\n meter.use(target * elasticityMultiplier);\n\n (, uint64 prevBoughtGas, ) = meter.params();\n assertEq(prevBoughtGas, target * elasticityMultiplier);\n\n vm.roll(initialBlockNum + 2);\n\n vm.expectRevert(\"UNDEFINED\");\n meter.use(0);\n }\n\n function test_meter_useMoreThanMax_reverts() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n vm.expectRevert(\"ResourceMetering: cannot buy more gas than available gas limit\");\n meter.use(target * elasticityMultiplier + 1);\n }\n\n // Demonstrates that the resource metering arithmetic can tolerate very large gaps between\n // deposits.\n function testFuzz_meter_largeBlockDiff_succeeds(uint64 _amount, uint256 _blockDiff) external {\n // This test fails if the following line is commented out.\n // At 12 seconds per block, this number is effectively unreachable.\n vm.assume(_blockDiff < 433576281058164217753225238677900874458691);\n\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n vm.assume(_amount < target * elasticityMultiplier);\n vm.roll(initialBlockNum + _blockDiff);\n meter.use(_amount);\n }\n}\n\n/**\n * @title CustomMeterUser\n * @notice A simple wrapper around `ResourceMetering` that allows the initial\n * params to be set in the constructor.\n */\ncontract CustomMeterUser is ResourceMetering {\n uint256 public startGas;\n uint256 public endGas;\n\n constructor(\n uint128 _prevBaseFee,\n uint64 _prevBoughtGas,\n uint64 _prevBlockNum\n ) {\n params = ResourceMetering.ResourceParams({\n prevBaseFee: _prevBaseFee,\n prevBoughtGas: _prevBoughtGas,\n prevBlockNum: _prevBlockNum\n });\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return Constants.DEFAULT_RESOURCE_CONFIG();\n }\n\n function use(uint64 _amount) public returns (uint256) {\n uint256 initialGas = gasleft();\n _metered(_amount, initialGas);\n return initialGas - gasleft();\n }\n}\n\n/**\n * @title ArtifactResourceMetering_Test\n * @notice A table test that sets the state of the ResourceParams and then requests\n * various amounts of gas. This test ensures that a wide range of values\n * can safely be used with the `ResourceMetering` contract.\n * It also writes a CSV file to disk that includes useful information\n * about how much gas is used and how expensive it is in USD terms to\n * purchase the deposit gas.\n */\ncontract ArtifactResourceMetering_Test is Test {\n uint128 internal minimumBaseFee;\n uint128 internal maximumBaseFee;\n uint64 internal maxResourceLimit;\n uint64 internal targetResourceLimit;\n\n string internal outfile;\n\n // keccak256(abi.encodeWithSignature(\"Error(string)\", \"ResourceMetering: cannot buy more gas than available gas limit\"))\n bytes32 internal cannotBuyMoreGas =\n 0x84edc668cfd5e050b8999f43ff87a1faaa93e5f935b20bc1dd4d3ff157ccf429;\n // keccak256(abi.encodeWithSignature(\"Panic(uint256)\", 0x11))\n bytes32 internal overflowErr =\n 0x1ca389f2c8264faa4377de9ce8e14d6263ef29c68044a9272d405761bab2db27;\n // keccak256(hex\"\")\n bytes32 internal emptyReturnData =\n 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n\n /**\n * @notice Sets up the tests by getting constants from the ResourceMetering\n * contract.\n */\n function setUp() public {\n vm.roll(1_000_000);\n\n MeterUser base = new MeterUser();\n ResourceMetering.ResourceConfig memory rcfg = base.resourceConfig();\n minimumBaseFee = uint128(rcfg.minimumBaseFee);\n maximumBaseFee = rcfg.maximumBaseFee;\n maxResourceLimit = uint64(rcfg.maxResourceLimit);\n targetResourceLimit = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n\n outfile = string.concat(vm.projectRoot(), \"/.resource-metering.csv\");\n try vm.removeFile(outfile) {} catch {}\n }\n\n /**\n * @notice Generate a CSV file. The call to `meter` should be called with at\n * most the L1 block gas limit. Without specifying the amount of\n * gas, it can take very long to execute.\n */\n function test_meter_generateArtifact_succeeds() external {\n vm.writeLine(\n outfile,\n \"prevBaseFee,prevBoughtGas,prevBlockNumDiff,l1BaseFee,requestedGas,gasConsumed,ethPrice,usdCost,success\"\n );\n\n // prevBaseFee value in ResourceParams\n uint128[] memory prevBaseFees = new uint128[](5);\n prevBaseFees[0] = minimumBaseFee;\n prevBaseFees[1] = maximumBaseFee;\n prevBaseFees[2] = uint128(50 gwei);\n prevBaseFees[3] = uint128(100 gwei);\n prevBaseFees[4] = uint128(200 gwei);\n\n // prevBoughtGas value in ResourceParams\n uint64[] memory prevBoughtGases = new uint64[](1);\n prevBoughtGases[0] = uint64(0);\n\n // prevBlockNum diff, simulates blocks with no deposits when non zero\n uint64[] memory prevBlockNumDiffs = new uint64[](2);\n prevBlockNumDiffs[0] = 0;\n prevBlockNumDiffs[1] = 1;\n\n // The amount of L2 gas that a user requests\n uint64[] memory requestedGases = new uint64[](3);\n requestedGases[0] = maxResourceLimit;\n requestedGases[1] = targetResourceLimit;\n requestedGases[2] = uint64(100_000);\n\n // The L1 base fee\n uint256[] memory l1BaseFees = new uint256[](4);\n l1BaseFees[0] = 1 gwei;\n l1BaseFees[1] = 50 gwei;\n l1BaseFees[2] = 75 gwei;\n l1BaseFees[3] = 100 gwei;\n\n // USD price of 1 ether\n uint256[] memory ethPrices = new uint256[](2);\n ethPrices[0] = 1600;\n ethPrices[1] = 3200;\n\n // Iterate over all of the test values and run a test\n for (uint256 i; i < prevBaseFees.length; i++) {\n for (uint256 j; j < prevBoughtGases.length; j++) {\n for (uint256 k; k < prevBlockNumDiffs.length; k++) {\n for (uint256 l; l < requestedGases.length; l++) {\n for (uint256 m; m < l1BaseFees.length; m++) {\n for (uint256 n; n < ethPrices.length; n++) {\n uint256 snapshotId = vm.snapshot();\n\n uint128 prevBaseFee = prevBaseFees[i];\n uint64 prevBoughtGas = prevBoughtGases[j];\n uint64 prevBlockNumDiff = prevBlockNumDiffs[k];\n uint64 requestedGas = requestedGases[l];\n uint256 l1BaseFee = l1BaseFees[m];\n uint256 ethPrice = ethPrices[n];\n string memory result = \"success\";\n\n vm.fee(l1BaseFee);\n\n CustomMeterUser meter = new CustomMeterUser({\n _prevBaseFee: prevBaseFee,\n _prevBoughtGas: prevBoughtGas,\n _prevBlockNum: uint64(block.number)\n });\n\n vm.roll(block.number + prevBlockNumDiff);\n\n // Call the metering code and catch the various\n // types of errors.\n uint256 gasConsumed = 0;\n try meter.use{ gas: 30_000_000 }(requestedGas) returns (\n uint256 _gasConsumed\n ) {\n gasConsumed = _gasConsumed;\n } catch (bytes memory err) {\n bytes32 hash = keccak256(err);\n if (hash == cannotBuyMoreGas) {\n result = \"ResourceMetering: cannot buy more gas than available gas limit\";\n } else if (hash == overflowErr) {\n result = \"arithmetic overflow/underflow\";\n } else if (hash == emptyReturnData) {\n result = \"out of gas\";\n } else {\n result = \"UNKNOWN ERROR\";\n }\n }\n\n // Compute the USD cost of the gas used\n uint256 usdCost = (gasConsumed * l1BaseFee * ethPrice) / 1 ether;\n\n vm.writeLine(\n outfile,\n string.concat(\n vm.toString(prevBaseFee),\n \",\",\n vm.toString(prevBoughtGas),\n \",\",\n vm.toString(prevBlockNumDiff),\n \",\",\n vm.toString(l1BaseFee),\n \",\",\n vm.toString(requestedGas),\n \",\",\n vm.toString(gasConsumed),\n \",\",\n \"$\",\n vm.toString(ethPrice),\n \",\",\n \"$\",\n vm.toString(usdCost),\n \",\",\n result\n )\n );\n\n assertTrue(vm.revertTo(snapshotId));\n }\n }\n }\n }\n }\n }\n }\n}\n" - }, - "contracts/test/SafeCall.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\n\ncontract SafeCall_Test is CommonTest {\n function testFuzz_call_succeeds(\n address from,\n address to,\n uint256 gas,\n uint64 value,\n bytes memory data\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles (mainnet)\n assumeNoPrecompiles(to, 1);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n // don't call the ffi interface\n vm.assume(to != address(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f));\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n uint256[2] memory balancesBefore = [from.balance, to.balance];\n\n vm.expectCall(to, value, data);\n vm.prank(from);\n bool success = SafeCall.call(to, gas, value, data);\n\n assertTrue(success, \"call not successful\");\n if (from == to) {\n assertEq(from.balance, balancesBefore[0], \"Self-send did not change balance\");\n } else {\n assertEq(from.balance, balancesBefore[0] - value, \"from balance not drained\");\n assertEq(to.balance, balancesBefore[1] + value, \"to balance received\");\n }\n }\n\n function testFuzz_callWithMinGas_hasEnough_succeeds(\n address from,\n address to,\n uint64 minGas,\n uint64 value,\n bytes memory data\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles (mainnet)\n assumeNoPrecompiles(to, 1);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n // don't call the FFIInterface\n vm.assume(to != address(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f));\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n // Bound minGas to [0, l1_block_gas_limit]\n minGas = uint64(bound(minGas, 0, 30_000_000));\n\n uint256[2] memory balancesBefore = [from.balance, to.balance];\n\n vm.expectCallMinGas(to, value, minGas, data);\n vm.prank(from);\n bool success = SafeCall.callWithMinGas(to, minGas, value, data);\n\n assertTrue(success, \"call not successful\");\n if (from == to) {\n assertEq(from.balance, balancesBefore[0], \"Self-send did not change balance\");\n } else {\n assertEq(from.balance, balancesBefore[0] - value, \"from balance not drained\");\n assertEq(to.balance, balancesBefore[1] + value, \"to balance received\");\n }\n }\n\n function test_callWithMinGas_noLeakageLow_succeeds() external {\n SimpleSafeCaller caller = new SimpleSafeCaller();\n\n for (uint64 i = 40_000; i < 100_000; i++) {\n uint256 snapshot = vm.snapshot();\n\n // 65_907 is the exact amount of gas required to make the safe call\n // successfully.\n if (i < 65_907) {\n assertFalse(caller.makeSafeCall(i, 25_000));\n } else {\n vm.expectCallMinGas(\n address(caller),\n 0,\n 25_000,\n abi.encodeWithSelector(caller.setA.selector, 1)\n );\n assertTrue(caller.makeSafeCall(i, 25_000));\n }\n\n assertTrue(vm.revertTo(snapshot));\n }\n }\n\n function test_callWithMinGas_noLeakageHigh_succeeds() external {\n SimpleSafeCaller caller = new SimpleSafeCaller();\n\n for (uint64 i = 15_200_000; i < 15_300_000; i++) {\n uint256 snapshot = vm.snapshot();\n\n // 15_278_606 is the exact amount of gas required to make the safe call\n // successfully.\n if (i < 15_278_606) {\n assertFalse(caller.makeSafeCall(i, 15_000_000));\n } else {\n vm.expectCallMinGas(\n address(caller),\n 0,\n 15_000_000,\n abi.encodeWithSelector(caller.setA.selector, 1)\n );\n assertTrue(caller.makeSafeCall(i, 15_000_000));\n }\n\n assertTrue(vm.revertTo(snapshot));\n }\n }\n}\n\ncontract SimpleSafeCaller {\n uint256 public a;\n\n function makeSafeCall(uint64 gas, uint64 minGas) external returns (bool) {\n return\n SafeCall.call(\n address(this),\n gas,\n 0,\n abi.encodeWithSelector(this.makeSafeCallMinGas.selector, minGas)\n );\n }\n\n function makeSafeCallMinGas(uint64 minGas) external returns (bool) {\n return\n SafeCall.callWithMinGas(\n address(this),\n minGas,\n 0,\n abi.encodeWithSelector(this.setA.selector, 1)\n );\n }\n\n function setA(uint256 _a) external {\n a = _a;\n }\n}\n" - }, - "contracts/test/Semver.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\n\n/**\n * @notice Test the Semver contract that is used for semantic versioning\n * of various contracts.\n */\ncontract Semver_Test is CommonTest {\n /**\n * @notice Global semver contract deployed in setUp. This is used in\n * the test cases.\n */\n Semver semver;\n\n /**\n * @notice Deploy a Semver contract\n */\n function setUp() public virtual override {\n semver = new Semver(7, 8, 0);\n }\n\n /**\n * @notice Test the version getter\n */\n function test_version_succeeds() external {\n assertEq(semver.version(), \"7.8.0\");\n }\n\n /**\n * @notice Since the versions are all immutable, they should\n * be able to be accessed from behind a proxy without needing\n * to initialize the contract.\n */\n function test_behindProxy_succeeds() external {\n Proxy proxy = new Proxy(alice);\n vm.prank(alice);\n proxy.upgradeTo(address(semver));\n\n assertEq(Semver(address(proxy)).version(), \"7.8.0\");\n }\n}\n" - }, - "contracts/test/SequencerFeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { SequencerFeeVault } from \"../L2/SequencerFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract SequencerFeeVault_Test is Bridge_Initializer {\n SequencerFeeVault vault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET));\n address constant recipient = address(256);\n\n event Withdrawal(uint256 value, address to, address from);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.SEQUENCER_FEE_WALLET, address(new SequencerFeeVault(recipient)).code);\n vm.label(Predeploys.SEQUENCER_FEE_WALLET, \"SequencerFeeVault\");\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(vault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n\n function test_constructor_succeeds() external {\n assertEq(vault.l1FeeWallet(), recipient);\n }\n\n function test_receive_succeeds() external {\n uint256 balance = address(vault).balance;\n\n vm.prank(alice);\n (bool success, ) = address(vault).call{ value: 100 }(hex\"\");\n\n assertEq(success, true);\n assertEq(address(vault).balance, balance + 100);\n }\n\n function test_withdraw_notEnough_reverts() external {\n assert(address(vault).balance < vault.MIN_WITHDRAWAL_AMOUNT());\n\n vm.expectRevert(\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n vault.withdraw();\n }\n\n function test_withdraw_succeeds() external {\n uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1;\n vm.deal(address(vault), amount);\n\n // No ether has been withdrawn yet\n assertEq(vault.totalProcessed(), 0);\n\n vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));\n emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this));\n\n // The entire vault's balance is withdrawn\n vm.expectCall(\n Predeploys.L2_STANDARD_BRIDGE,\n address(vault).balance,\n abi.encodeWithSelector(\n StandardBridge.bridgeETHTo.selector,\n vault.l1FeeWallet(),\n 35_000,\n bytes(\"\")\n )\n );\n\n vault.withdraw();\n\n // The withdrawal was successful\n assertEq(vault.totalProcessed(), amount);\n }\n}\n" - }, - "contracts/test/StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport {\n OptimismMintableERC20,\n ILegacyMintableERC20\n} from \"../universal/OptimismMintableERC20.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/**\n * @title StandardBridgeTester\n * @notice Simple wrapper around the StandardBridge contract that exposes\n * internal functions so they can be more easily tested directly.\n */\ncontract StandardBridgeTester is StandardBridge {\n constructor(address payable _messenger, address payable _otherBridge)\n StandardBridge(_messenger, _otherBridge)\n {}\n\n function isOptimismMintableERC20(address _token) external view returns (bool) {\n return _isOptimismMintableERC20(_token);\n }\n\n function isCorrectTokenPair(address _mintableToken, address _otherToken)\n external\n view\n returns (bool)\n {\n return _isCorrectTokenPair(_mintableToken, _otherToken);\n }\n\n receive() external payable override {}\n}\n\n/**\n * @title LegacyMintable\n * @notice Simple implementation of the legacy OptimismMintableERC20.\n */\ncontract LegacyMintable is ERC20, ILegacyMintableERC20 {\n constructor(string memory _name, string memory _ticker) ERC20(_name, _ticker) {}\n\n function l1Token() external pure returns (address) {\n return address(0);\n }\n\n function mint(address _to, uint256 _amount) external pure {}\n\n function burn(address _from, uint256 _amount) external pure {}\n\n /**\n * @notice Implements ERC165. This implementation should not be changed as\n * it is how the actual legacy optimism mintable token does the\n * check. Allows for testing against code that is has been deployed,\n * assuming different compiler version is no problem.\n */\n function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {\n bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^\n ILegacyMintableERC20.mint.selector ^\n ILegacyMintableERC20.burn.selector;\n return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n }\n}\n\n/**\n * @title StandardBridge_Stateless_Test\n * @notice Tests internal functions that require no existing state or contract\n * interactions with the messenger.\n */\ncontract StandardBridge_Stateless_Test is CommonTest {\n StandardBridgeTester internal bridge;\n OptimismMintableERC20 internal mintable;\n ERC20 internal erc20;\n LegacyMintable internal legacy;\n\n function setUp() public override {\n super.setUp();\n\n bridge = new StandardBridgeTester({\n _messenger: payable(address(0)),\n _otherBridge: payable(address(0))\n });\n\n mintable = new OptimismMintableERC20({\n _bridge: address(0),\n _remoteToken: address(0),\n _name: \"Stonks\",\n _symbol: \"STONK\"\n });\n\n erc20 = new ERC20(\"Altcoin\", \"ALT\");\n legacy = new LegacyMintable(\"Legacy\", \"LEG\");\n }\n\n /**\n * @notice Test coverage for identifying OptimismMintableERC20 tokens.\n * This function should return true for both modern and legacy\n * OptimismMintableERC20 tokens and false for any accounts that\n * do not implement the interface.\n */\n function test_isOptimismMintableERC20_succeeds() external {\n // Both the modern and legacy mintable tokens should return true\n assertTrue(bridge.isOptimismMintableERC20(address(mintable)));\n assertTrue(bridge.isOptimismMintableERC20(address(legacy)));\n // A regular ERC20 should return false\n assertFalse(bridge.isOptimismMintableERC20(address(erc20)));\n // Non existent contracts should return false and not revert\n assertEq(address(0x20).code.length, 0);\n assertFalse(bridge.isOptimismMintableERC20(address(0x20)));\n }\n\n /**\n * @notice Test coverage of isCorrectTokenPair under different types of\n * tokens.\n */\n function test_isCorrectTokenPair_succeeds() external {\n // Modern + known to be correct remote token\n assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.remoteToken()));\n // Modern + known to be correct l1Token (legacy interface)\n assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.l1Token()));\n // Modern + known to be incorrect remote token\n assertTrue(mintable.remoteToken() != address(0x20));\n assertFalse(bridge.isCorrectTokenPair(address(mintable), address(0x20)));\n // Legacy + known to be correct l1Token\n assertTrue(bridge.isCorrectTokenPair(address(legacy), legacy.l1Token()));\n // Legacy + known to be incorrect l1Token\n assertTrue(legacy.l1Token() != address(0x20));\n assertFalse(bridge.isCorrectTokenPair(address(legacy), address(0x20)));\n // A token that doesn't support either modern or legacy interface\n // will revert\n vm.expectRevert();\n bridge.isCorrectTokenPair(address(erc20), address(1));\n }\n}\n" - }, - "contracts/test/SystemConfig.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract SystemConfig_Init is CommonTest {\n SystemConfig sysConf;\n\n function setUp() public virtual override {\n super.setUp();\n\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n\n sysConf = new SystemConfig({\n _owner: alice,\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(1),\n _config: config\n });\n }\n}\n\ncontract SystemConfig_Initialize_TestFail is SystemConfig_Init {\n function test_initialize_lowGasLimit_reverts() external {\n uint64 minimumGasLimit = sysConf.minimumGasLimit();\n\n ResourceMetering.ResourceConfig memory cfg = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n\n vm.expectRevert(\"SystemConfig: gas limit too low\");\n new SystemConfig({\n _owner: alice,\n _overhead: 0,\n _scalar: 0,\n _batcherHash: bytes32(hex\"\"),\n _gasLimit: minimumGasLimit - 1,\n _unsafeBlockSigner: address(1),\n _config: cfg\n });\n }\n}\n\ncontract SystemConfig_Setters_TestFail is SystemConfig_Init {\n function test_setBatcherHash_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setBatcherHash(bytes32(hex\"\"));\n }\n\n function test_setGasConfig_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasConfig(0, 0);\n }\n\n function test_setGasLimit_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasLimit(0);\n }\n\n function test_setUnsafeBlockSigner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setUnsafeBlockSigner(address(0x20));\n }\n\n function test_setResourceConfig_notOwner_reverts() external {\n ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_badMinMax_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 2 gwei,\n maximumBaseFee: 1 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: min base fee must be less than max base\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_zeroDenominator_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 0,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: denominator must be larger than 1\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_lowGasLimit_reverts() external {\n uint64 gasLimit = sysConf.gasLimit();\n\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: uint32(gasLimit),\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: uint32(gasLimit),\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: gas limit too low\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_badPrecision_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 11,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: precision loss with target resource limit\");\n sysConf.setResourceConfig(config);\n }\n}\n\ncontract SystemConfig_Setters_Test is SystemConfig_Init {\n event ConfigUpdate(\n uint256 indexed version,\n SystemConfig.UpdateType indexed updateType,\n bytes data\n );\n\n function testFuzz_setBatcherHash_succeeds(bytes32 newBatcherHash) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash));\n\n vm.prank(sysConf.owner());\n sysConf.setBatcherHash(newBatcherHash);\n assertEq(sysConf.batcherHash(), newBatcherHash);\n }\n\n function testFuzz_setGasConfig_succeeds(uint256 newOverhead, uint256 newScalar) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.GAS_CONFIG,\n abi.encode(newOverhead, newScalar)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setGasConfig(newOverhead, newScalar);\n assertEq(sysConf.overhead(), newOverhead);\n assertEq(sysConf.scalar(), newScalar);\n }\n\n function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external {\n uint64 minimumGasLimit = sysConf.minimumGasLimit();\n newGasLimit = uint64(\n bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(type(uint64).max))\n );\n\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit));\n\n vm.prank(sysConf.owner());\n sysConf.setGasLimit(newGasLimit);\n assertEq(sysConf.gasLimit(), newGasLimit);\n }\n\n function testFuzz_setUnsafeBlockSigner_succeeds(address newUnsafeSigner) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER,\n abi.encode(newUnsafeSigner)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setUnsafeBlockSigner(newUnsafeSigner);\n assertEq(sysConf.unsafeBlockSigner(), newUnsafeSigner);\n }\n}\n" - }, - "contracts/test/TransferOnion.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { TransferOnion } from \"../periphery/TransferOnion.sol\";\n\n/**\n * @title TransferOnionTest\n * @notice Test coverage of TransferOnion\n */\ncontract TransferOnionTest is Test {\n /**\n * @notice TransferOnion\n */\n TransferOnion internal onion;\n\n /**\n * @notice token constructor arg\n */\n address internal _token;\n\n /**\n * @notice sender constructor arg\n */\n address internal _sender;\n\n /**\n * @notice Sets up addresses, deploys contracts and funds the owner.\n */\n function setUp() public {\n ERC20 token = new ERC20(\"Token\", \"TKN\");\n _token = address(token);\n _sender = makeAddr(\"sender\");\n }\n\n /**\n * @notice Deploy the TransferOnion with a dummy shell\n */\n function _deploy() public {\n _deploy(bytes32(0));\n }\n\n /**\n * @notice Deploy the TransferOnion with a specific shell\n */\n function _deploy(bytes32 _shell) public {\n onion = new TransferOnion({ _token: ERC20(_token), _sender: _sender, _shell: _shell });\n }\n\n /**\n * @notice Build the onion data\n */\n function _onionize(TransferOnion.Layer[] memory _layers)\n public\n pure\n returns (bytes32, TransferOnion.Layer[] memory)\n {\n uint256 length = _layers.length;\n bytes32 hash = bytes32(0);\n for (uint256 i; i < length; i++) {\n TransferOnion.Layer memory layer = _layers[i];\n _layers[i].shell = hash;\n hash = keccak256(abi.encode(layer.recipient, layer.amount, hash));\n }\n return (hash, _layers);\n }\n\n /**\n * @notice The constructor sets the variables as expected\n */\n function test_constructor_succeeds() external {\n _deploy();\n\n assertEq(address(onion.TOKEN()), _token);\n assertEq(onion.SENDER(), _sender);\n assertEq(onion.shell(), bytes32(0));\n }\n\n /**\n * @notice unwrap\n */\n function test_unwrap_succeeds() external {\n // Commit to transferring tiny amounts of tokens\n TransferOnion.Layer[] memory _layers = new TransferOnion.Layer[](2);\n _layers[0] = TransferOnion.Layer(address(1), 1, bytes32(0));\n _layers[1] = TransferOnion.Layer(address(2), 2, bytes32(0));\n\n // Build the onion shell\n (bytes32 shell, TransferOnion.Layer[] memory layers) = _onionize(_layers);\n _deploy(shell);\n\n assertEq(onion.shell(), shell);\n\n address token = address(onion.TOKEN());\n address sender = onion.SENDER();\n\n // give 3 units of token to sender\n deal(token, onion.SENDER(), 3);\n vm.prank(sender);\n ERC20(token).approve(address(onion), 3);\n\n // To build the inputs, to `peel`, need to reverse the list\n TransferOnion.Layer[] memory inputs = new TransferOnion.Layer[](2);\n int256 length = int256(layers.length);\n for (int256 i = length - 1; i >= 0; i--) {\n uint256 ui = uint256(i);\n uint256 revidx = uint256(length) - ui - 1;\n TransferOnion.Layer memory layer = layers[ui];\n inputs[revidx] = layer;\n }\n\n // The accounts have no balance\n assertEq(ERC20(_token).balanceOf(address(1)), 0);\n assertEq(ERC20(_token).balanceOf(address(2)), 0);\n\n onion.peel(inputs);\n\n // Now the accounts have the expected balance\n assertEq(ERC20(_token).balanceOf(address(1)), 1);\n assertEq(ERC20(_token).balanceOf(address(2)), 2);\n }\n}\n" - }, - "contracts/test/invariants/CrossDomainMessenger.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { StdUtils } from \"forge-std/StdUtils.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport { OptimismPortal } from \"../../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../../L1/L1CrossDomainMessenger.sol\";\nimport { Messenger_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\nimport { Predeploys } from \"../../libraries/Predeploys.sol\";\nimport { Constants } from \"../../libraries/Constants.sol\";\nimport { Encoding } from \"../../libraries/Encoding.sol\";\nimport { Hashing } from \"../../libraries/Hashing.sol\";\n\ncontract RelayActor is StdUtils {\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n uint256 public numHashes;\n bytes32[] public hashes;\n bool public reverted = false;\n\n OptimismPortal op;\n L1CrossDomainMessenger xdm;\n Vm vm;\n bool doFail;\n\n constructor(\n OptimismPortal _op,\n L1CrossDomainMessenger _xdm,\n Vm _vm,\n bool _doFail\n ) {\n op = _op;\n xdm = _xdm;\n vm = _vm;\n doFail = _doFail;\n }\n\n /**\n * Relays a message to the `L1CrossDomainMessenger` with a random `version`, and `_message`.\n */\n function relay(\n uint8 _version,\n uint8 _value,\n bytes memory _message\n ) external {\n address target = address(0x04); // ID precompile\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Set the minimum gas limit to the cost of the identity precompile's execution for\n // the given message.\n // ID Precompile cost can be determined by calculating: 15 + 3 * data_word_length\n uint32 minGasLimit = uint32(15 + 3 * ((_message.length + 31) / 32));\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Restrict version to the range of [0, 1]\n _version = _version % 2;\n\n // Restrict the value to the range of [0, 1]\n // This is just so we get variance of calls with and without value. The ID precompile\n // will not reject value being sent to it.\n _value = _value % 2;\n\n // If the message should succeed, supply it `baseGas`. If not, supply it an amount of\n // gas that is too low to complete the call.\n uint256 gas = doFail\n ? bound(minGasLimit, 60_000, 80_000)\n : xdm.baseGas(_message, minGasLimit);\n\n // Compute the cross domain message hash and store it in `hashes`.\n // The `relayMessage` function will always encode the message as a version 1\n // message after checking that the V0 hash has not already been relayed.\n bytes32 _hash = Hashing.hashCrossDomainMessageV1(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n _value,\n minGasLimit,\n _message\n );\n hashes.push(_hash);\n numHashes += 1;\n\n // Make sure we've got a fresh message.\n vm.assume(xdm.successfulMessages(_hash) == false && xdm.failedMessages(_hash) == false);\n\n // Act as the optimism portal and call `relayMessage` on the `L1CrossDomainMessenger` with\n // the outer min gas limit.\n vm.startPrank(address(op));\n if (!doFail) {\n vm.expectCallMinGas(address(0x04), _value, minGasLimit, _message);\n }\n try\n xdm.relayMessage{ gas: gas, value: _value }(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n _value,\n minGasLimit,\n _message\n )\n {} catch {\n // If any of these calls revert, set `reverted` to true to fail the invariant test.\n // NOTE: This is to get around forge's invariant fuzzer ignoring reverted calls\n // to this function.\n reverted = true;\n }\n vm.stopPrank();\n }\n}\n\ncontract XDM_MinGasLimits is Messenger_Initializer {\n RelayActor actor;\n\n function init(bool doFail) public virtual {\n // Set up the `L1CrossDomainMessenger` and `OptimismPortal` contracts.\n super.setUp();\n\n // Deploy a relay actor\n actor = new RelayActor(op, L1Messenger, vm, doFail);\n\n // Give the portal some ether to send to `relayMessage`\n vm.deal(address(op), type(uint128).max);\n\n // Target the `RelayActor` contract\n targetContract(address(actor));\n\n // Don't allow the estimation address to be the sender\n excludeSender(Constants.ESTIMATION_ADDRESS);\n\n // Target the actor's `relay` function\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = actor.relay.selector;\n targetSelector(FuzzSelector({ addr: address(actor), selectors: selectors }));\n }\n}\n\ncontract XDM_MinGasLimits_Succeeds is XDM_MinGasLimits {\n function setUp() public override {\n // Don't fail\n super.init(false);\n }\n\n /**\n * @custom:invariant A call to `relayMessage` should succeed if at least the minimum gas limit\n * can be supplied to the target context, there is enough gas to complete\n * execution of `relayMessage` after the target context's execution is\n * finished, and the target context did not revert.\n *\n * There are two minimum gas limits here:\n *\n * - The outer min gas limit is for the call from the `OptimismPortal` to the\n * `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function\n * with the `message` and inner limit.\n *\n * - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target\n * contract.\n */\n function invariant_minGasLimits() external {\n uint256 length = actor.numHashes();\n for (uint256 i = 0; i < length; ++i) {\n bytes32 hash = actor.hashes(i);\n // The message hash is set in the successfulMessages mapping\n assertTrue(L1Messenger.successfulMessages(hash));\n // The message hash is not set in the failedMessages mapping\n assertFalse(L1Messenger.failedMessages(hash));\n }\n assertFalse(actor.reverted());\n }\n}\n\ncontract XDM_MinGasLimits_Reverts is XDM_MinGasLimits {\n function setUp() public override {\n // Do fail\n super.init(true);\n }\n\n /**\n * @custom:invariant A call to `relayMessage` should assign the message hash to the\n * `failedMessages` mapping if not enough gas is supplied to forward\n * `minGasLimit` to the target context or if there is not enough gas to\n * complete execution of `relayMessage` after the target context's execution\n * is finished.\n *\n * There are two minimum gas limits here:\n *\n * - The outer min gas limit is for the call from the `OptimismPortal` to the\n * `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function\n * with the `message` and inner limit.\n *\n * - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target\n * contract.\n */\n function invariant_minGasLimits() external {\n uint256 length = actor.numHashes();\n for (uint256 i = 0; i < length; ++i) {\n bytes32 hash = actor.hashes(i);\n // The message hash is not set in the successfulMessages mapping\n assertFalse(L1Messenger.successfulMessages(hash));\n // The message hash is set in the failedMessages mapping\n assertTrue(L1Messenger.failedMessages(hash));\n }\n assertFalse(actor.reverted());\n }\n}\n" - }, - "contracts/test/invariants/L2OutputOracle.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { L2OutputOracle_Initializer } from \"../CommonTest.t.sol\";\nimport { L2OutputOracle } from \"../../L1/L2OutputOracle.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\n\ncontract L2OutputOracle_Proposer {\n L2OutputOracle internal oracle;\n Vm internal vm;\n\n constructor(L2OutputOracle _oracle, Vm _vm) {\n oracle = _oracle;\n vm = _vm;\n }\n\n /**\n * @dev Allows the actor to propose an L2 output to the `L2OutputOracle`\n */\n function proposeL2Output(\n bytes32 _outputRoot,\n uint256 _l2BlockNumber,\n bytes32 _l1BlockHash,\n uint256 _l1BlockNumber\n ) external {\n // Act as the proposer and propose a new output.\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _l2BlockNumber, _l1BlockHash, _l1BlockNumber);\n }\n}\n\ncontract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_Initializer {\n L2OutputOracle_Proposer internal actor;\n\n function setUp() public override {\n super.setUp();\n\n // Create a proposer actor.\n actor = new L2OutputOracle_Proposer(oracle, vm);\n\n // Set the target contract to the proposer actor.\n targetContract(address(actor));\n\n // Set the target selector for `proposeL2Output`\n // `proposeL2Output` is the only function we care about, as it is the only function\n // that can modify the `l2Outputs` array in the oracle.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = actor.proposeL2Output.selector;\n FuzzSelector memory selector = FuzzSelector({ addr: address(actor), selectors: selectors });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The block number of the output root proposals should monotonically\n * increase.\n *\n * When a new output is submitted, it should never be allowed to correspond to a block\n * number that is less than the current output.\n */\n function invariant_monotonicBlockNumIncrease() external {\n // Assert that the block number of proposals must monotonically increase.\n assertTrue(oracle.nextBlockNumber() >= oracle.latestBlockNumber());\n }\n}\n" - }, - "contracts/test/invariants/OptimismPortal.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Portal_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\n\ncontract OptimismPortal_Invariant_Harness is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n function setUp() public virtual override {\n super.setUp();\n\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n}\n\ncontract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the finalization\n * period has not elapsed.\n *\n * A withdrawal that has been proven should not be able to be finalized until after\n * the finalization period has elapsed.\n */\n function invariant_cannotFinalizeBeforePeriodHasPassed() external {\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Finalize the withdrawal transaction.\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal\n * has already been finalized.\n *\n * Ensures that there is no chain of calls that can be made that allows a withdrawal\n * to be finalized twice.\n */\n function invariant_cannotFinalizeTwice() external {\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant A withdrawal should **always** be able to be finalized\n * `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.\n *\n * This invariant asserts that there is no chain of calls that can be made that\n * will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS`\n * after it was successfully proven.\n */\n function invariant_canAlwaysFinalize() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assertEq(address(bob).balance, bobBalanceBefore + _defaultTx.value);\n }\n}\n" - }, - "contracts/test/invariants/SafeCall.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { StdUtils } from \"forge-std/StdUtils.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport { SafeCall } from \"../../libraries/SafeCall.sol\";\n\ncontract SafeCall_Succeeds_Invariants is Test {\n SafeCaller_Actor actor;\n\n function setUp() public {\n // Create a new safe caller actor.\n actor = new SafeCaller_Actor(vm, false);\n\n // Set the caller to this contract\n targetSender(address(this));\n\n // Target the safe caller actor.\n targetContract(address(actor));\n\n // Give the actor some ETH to work with\n vm.deal(address(actor), type(uint128).max);\n }\n\n /**\n * @custom:invariant If `callWithMinGas` performs a call, then it must always\n * provide at least the specified minimum gas limit to the subcontext.\n *\n * If the check for remaining gas in `SafeCall.callWithMinGas` passes, the\n * subcontext of the call below it must be provided at least `minGas` gas.\n */\n function invariant_callWithMinGas_alwaysForwardsMinGas_succeeds() public {\n assertEq(actor.numCalls(), 0, \"no failed calls allowed\");\n }\n\n function performSafeCallMinGas(address to, uint64 minGas) external payable {\n SafeCall.callWithMinGas(to, minGas, msg.value, hex\"\");\n }\n}\n\ncontract SafeCall_Fails_Invariants is Test {\n SafeCaller_Actor actor;\n\n function setUp() public {\n // Create a new safe caller actor.\n actor = new SafeCaller_Actor(vm, true);\n\n // Set the caller to this contract\n targetSender(address(this));\n\n // Target the safe caller actor.\n targetContract(address(actor));\n\n // Give the actor some ETH to work with\n vm.deal(address(actor), type(uint128).max);\n }\n\n /**\n * @custom:invariant `callWithMinGas` reverts if there is not enough gas to pass\n * to the subcontext.\n *\n * If there is not enough gas in the callframe to ensure that `callWithMinGas`\n * can provide the specified minimum gas limit to the subcontext of the call,\n * then `callWithMinGas` must revert.\n */\n function invariant_callWithMinGas_neverForwardsMinGas_reverts() public {\n assertEq(actor.numCalls(), 0, \"no successful calls allowed\");\n }\n\n function performSafeCallMinGas(address to, uint64 minGas) external payable {\n SafeCall.callWithMinGas(to, minGas, msg.value, hex\"\");\n }\n}\n\ncontract SafeCaller_Actor is StdUtils {\n bool internal immutable FAILS;\n\n Vm internal vm;\n uint256 public numCalls;\n\n constructor(Vm _vm, bool _fails) {\n vm = _vm;\n FAILS = _fails;\n }\n\n function performSafeCallMinGas(\n uint64 gas,\n uint64 minGas,\n address to,\n uint8 value\n ) external {\n // Only send to EOAs - we exclude the console as it has no code but reverts when called\n // with a selector that doesn't exist due to the foundry hook.\n vm.assume(to.code.length == 0 && to != 0x000000000000000000636F6e736F6c652e6c6f67);\n\n // Bound the minimum gas amount to [2500, type(uint48).max]\n minGas = uint64(bound(minGas, 2500, type(uint48).max));\n if (FAILS) {\n // Bound the gas passed to [minGas, ((minGas * 64) / 63)]\n gas = uint64(bound(gas, minGas, (minGas * 64) / 63));\n } else {\n // Bound the gas passed to\n // [((minGas * 64) / 63) + 40_000 + 1000, type(uint64).max]\n // The extra 1000 gas is to account for the gas used by the `SafeCall.call` call\n // itself.\n gas = uint64(bound(gas, ((minGas * 64) / 63) + 40_000 + 1000, type(uint64).max));\n }\n\n vm.expectCallMinGas(to, value, minGas, hex\"\");\n bool success = SafeCall.call(\n msg.sender,\n gas,\n value,\n abi.encodeWithSelector(\n SafeCall_Succeeds_Invariants.performSafeCallMinGas.selector,\n to,\n minGas\n )\n );\n\n if (success && FAILS) numCalls++;\n if (!FAILS && !success) numCalls++;\n }\n}\n" - }, - "contracts/test/invariants/SystemConfig.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { SystemConfig } from \"../../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../../L1/ResourceMetering.sol\";\nimport { Constants } from \"../../libraries/Constants.sol\";\n\ncontract SystemConfig_GasLimitLowerBound_Invariant is Test {\n SystemConfig public config;\n\n function setUp() public {\n ResourceMetering.ResourceConfig memory cfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n config = new SystemConfig({\n _owner: address(0xbeef),\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(1),\n _config: cfg\n });\n\n // Set the target contract to the `config`\n targetContract(address(config));\n // Set the target sender to the `config`'s owner (0xbeef)\n targetSender(address(0xbeef));\n // Set the target selector for `setGasLimit`\n // `setGasLimit` is the only function we care about, as it is the only function\n // that can modify the gas limit within the SystemConfig.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = config.setGasLimit.selector;\n FuzzSelector memory selector = FuzzSelector({\n addr: address(config),\n selectors: selectors\n });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The gas limit of the `SystemConfig` contract can never be lower\n * than the hard-coded lower bound.\n */\n function invariant_gasLimitLowerBound() external {\n assertTrue(config.gasLimit() >= config.minimumGasLimit());\n }\n}\n" - }, - "contracts/universal/CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\n/**\n * @custom:legacy\n * @title CrossDomainMessengerLegacySpacer0\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 CrossDomainMessengerLegacySpacer0 {\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:legacy\n * @title CrossDomainMessengerLegacySpacer1\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\n * PausableUpgradable and OwnableUpgradeable variables used to exist. Must be\n * the third contract in the inheritance tree of the CrossDomainMessenger.\n */\ncontract CrossDomainMessengerLegacySpacer1 {\n /**\n * @custom:legacy\n * @custom:spacer ContextUpgradable's __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * ContextUpgradable.\n *\n */\n uint256[50] private spacer_1_0_1600;\n\n /**\n * @custom:legacy\n * @custom:spacer OwnableUpgradeable's _owner\n * @notice Spacer for backwards compatibility.\n * Come from OpenZeppelin OwnableUpgradeable.\n */\n address private spacer_51_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer OwnableUpgradeable's __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * OwnableUpgradeable.\n */\n uint256[49] private spacer_52_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer PausableUpgradable's _paused\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n bool private spacer_101_0_1;\n\n /**\n * @custom:legacy\n * @custom:spacer PausableUpgradable's __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n uint256[49] private spacer_102_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer ReentrancyGuardUpgradeable's `_status` field.\n * @notice Spacer for backwards compatibility.\n */\n uint256 private spacer_151_0_32;\n\n /**\n * @custom:legacy\n * @custom:spacer ReentrancyGuardUpgradeable's __gap\n * @notice Spacer for backwards compatibility.\n */\n uint256[49] private spacer_152_0_1568;\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/**\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 *\n * Any changes to this contract MUST result in a semver bump for contracts that inherit it.\n */\nabstract contract CrossDomainMessenger is\n CrossDomainMessengerLegacySpacer0,\n Initializable,\n CrossDomainMessengerLegacySpacer1\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 uint64 public constant RELAY_CONSTANT_OVERHEAD = 200_000;\n\n /**\n * @notice Numerator for dynamic overhead added to the base gas for a message.\n */\n uint64 public constant MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR = 64;\n\n /**\n * @notice Denominator for dynamic overhead added to the base gas for a message.\n */\n uint64 public constant MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR = 63;\n\n /**\n * @notice Extra gas added to base gas for each byte of calldata in a message.\n */\n uint64 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\n\n /**\n * @notice Gas reserved for performing the external call in `relayMessage`.\n */\n uint64 public constant RELAY_CALL_OVERHEAD = 40_000;\n\n /**\n * @notice Gas reserved for finalizing the execution of `relayMessage` after the safe call.\n */\n uint64 public constant RELAY_RESERVED_GAS = 40_000;\n\n /**\n * @notice Gas reserved for the execution between the `hasMinGas` check and the external\n * call in `relayMessage`.\n */\n uint64 public constant RELAY_GAS_CHECK_BUFFER = 5_000;\n\n /**\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\n */\n address public immutable OTHER_MESSENGER;\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 a boolean if and only if the message has failed to be\n * executed at least once. A message will not be present in this mapping if it\n * successfully executed on the first attempt.\n */\n mapping(bytes32 => bool) public failedMessages;\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 OTHER_MESSENGER = _otherMessenger;\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 OTHER_MESSENGER,\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 {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n require(\n version < 2,\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // If the message is version 0, then it's a migrated legacy withdrawal. We therefore need\n // to check that the legacy version of the message has not already been relayed.\n if (version == 0) {\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _nonce);\n require(\n successfulMessages[oldHash] == false,\n \"CrossDomainMessenger: legacy withdrawal already relayed\"\n );\n }\n\n // We use the v1 message hash as the unique identifier for the message because it commits\n // to the value and minimum gas limit of the message.\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _minGasLimit,\n _message\n );\n\n if (_isOtherMessenger()) {\n // These properties should always hold when the message is first submitted (as\n // opposed to being replayed).\n assert(msg.value == _value);\n assert(!failedMessages[versionedHash]);\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 failedMessages[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 // If there is not enough gas left to perform the external call and finish the execution,\n // return early and assign the message to the failedMessages mapping.\n // We are asserting that we have enough gas to:\n // 1. Call the target contract (_minGasLimit + RELAY_CALL_OVERHEAD + RELAY_GAS_CHECK_BUFFER)\n // 1.a. The RELAY_CALL_OVERHEAD is included in `hasMinGas`.\n // 2. Finish the execution after the external call (RELAY_RESERVED_GAS).\n //\n // If `xDomainMsgSender` is not the default L2 sender, this function\n // is being re-entered. This marks the message as failed to allow it to be replayed.\n if (\n !SafeCall.hasMinGas(_minGasLimit, RELAY_RESERVED_GAS + RELAY_GAS_CHECK_BUFFER) ||\n xDomainMsgSender != Constants.DEFAULT_L2_SENDER\n ) {\n failedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n\n // Revert in this case if the transaction was triggered by the estimation address. This\n // should only be possible during gas estimation or we have bigger problems. Reverting\n // here will make the behavior of gas estimation change such that the gas limit\n // computed will be the amount required to relay the message, even if that amount is\n // greater than the minimum gas limit specified by the user.\n if (tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"CrossDomainMessenger: failed to relay message\");\n }\n\n return;\n }\n\n xDomainMsgSender = _sender;\n bool success = SafeCall.call(_target, gasleft() - RELAY_RESERVED_GAS, _value, _message);\n xDomainMsgSender = Constants.DEFAULT_L2_SENDER;\n\n if (success) {\n successfulMessages[versionedHash] = true;\n emit RelayedMessage(versionedHash);\n } else {\n failedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n\n // Revert in this case if the transaction was triggered by the estimation address. This\n // should only be possible during gas estimation or we have bigger problems. Reverting\n // here will make the behavior of gas estimation change such that the gas limit\n // computed will be the amount required to relay the message, even if that amount is\n // greater than the minimum gas limit specified by the user.\n if (tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"CrossDomainMessenger: failed to relay message\");\n }\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 != Constants.DEFAULT_L2_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 (uint64) {\n return\n // Constant overhead\n RELAY_CONSTANT_OVERHEAD +\n // Calldata overhead\n (uint64(_message.length) * MIN_GAS_CALLDATA_OVERHEAD) +\n // Dynamic overhead (EIP-150)\n ((_minGasLimit * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n // Gas reserved for the worst-case cost of 3/5 of the `CALL` opcode's dynamic gas\n // factors. (Conservative)\n RELAY_CALL_OVERHEAD +\n // Relay reserved gas (to ensure execution of `relayMessage` completes after the\n // subcontext finishes executing) (Conservative)\n RELAY_RESERVED_GAS +\n // Gas reserved for the execution between the `hasMinGas` check and the `CALL`\n // opcode. (Conservative)\n RELAY_GAS_CHECK_BUFFER;\n }\n\n /**\n * @notice Intializer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __CrossDomainMessenger_init() internal onlyInitializing {\n xDomainMsgSender = Constants.DEFAULT_L2_SENDER;\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" - }, - "contracts/universal/ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CrossDomainMessenger } from \"./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 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 OTHER_BRIDGE;\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 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 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() == OTHER_BRIDGE,\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 OTHER_BRIDGE = _otherBridge;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for other bridge address.\n *\n * @return Address of the bridge on the other network.\n */\n function otherBridge() external view returns (address) {\n return OTHER_BRIDGE;\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" - }, - "contracts/universal/FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n/**\n * @title FeeVault\n * @notice The FeeVault contract contains the basic logic for the various different vault contracts\n * used to hold fee revenue generated by the L2 system.\n */\nabstract contract FeeVault {\n /**\n * @notice Emits each time that a withdrawal occurs.\n *\n * @param value Amount that was withdrawn (in wei).\n * @param to Address that the funds were sent to.\n * @param from Address that triggered the withdrawal.\n */\n event Withdrawal(uint256 value, address to, address from);\n\n /**\n * @notice Minimum balance before a withdrawal can be triggered.\n */\n uint256 public immutable MIN_WITHDRAWAL_AMOUNT;\n\n /**\n * @notice Wallet that will receive the fees on L1.\n */\n address public immutable RECIPIENT;\n\n /**\n * @notice The minimum gas limit for the FeeVault withdrawal transaction.\n */\n uint32 internal constant WITHDRAWAL_MIN_GAS = 35_000;\n\n /**\n * @notice Total amount of wei processed by the contract.\n */\n uint256 public totalProcessed;\n\n /**\n * @param _recipient Wallet that will receive the fees on L1.\n * @param _minWithdrawalAmount Minimum balance before a withdrawal can be triggered.\n */\n constructor(address _recipient, uint256 _minWithdrawalAmount) {\n MIN_WITHDRAWAL_AMOUNT = _minWithdrawalAmount;\n RECIPIENT = _recipient;\n }\n\n /**\n * @notice Allow the contract to receive ETH.\n */\n receive() external payable {}\n\n /**\n * @notice Triggers a withdrawal of funds to the L1 fee wallet.\n */\n function withdraw() external {\n require(\n address(this).balance >= MIN_WITHDRAWAL_AMOUNT,\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n\n uint256 value = address(this).balance;\n totalProcessed += value;\n\n emit Withdrawal(value, RECIPIENT, msg.sender);\n\n L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)).bridgeETHTo{ value: value }(\n RECIPIENT,\n WITHDRAWAL_MIN_GAS,\n bytes(\"\")\n );\n }\n}\n" - }, - "contracts/universal/IOptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\n/**\n * @title IOptimismMintableERC20\n * @notice This interface is available on the OptimismMintableERC20 contract. We declare it as a\n * separate interface so that it can be used in custom implementations of\n * OptimismMintableERC20.\n */\ninterface IOptimismMintableERC20 is IERC165 {\n function remoteToken() external view returns (address);\n\n function bridge() external returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n\n/**\n * @custom:legacy\n * @title ILegacyMintableERC20\n * @notice This interface was available on the legacy L2StandardERC20 contract. It remains available\n * on the OptimismMintableERC20 contract for backwards compatibility.\n */\ninterface ILegacyMintableERC20 is IERC165 {\n function l1Token() external view returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n" - }, - "contracts/universal/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 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 /**\n * @notice Chain ID of the chain where the remote token is deployed.\n */\n function REMOTE_CHAIN_ID() external view returns (uint256);\n\n /**\n * @notice Address of the token on the remote domain.\n */\n function REMOTE_TOKEN() 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 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" - }, - "contracts/universal/OptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { ILegacyMintableERC20, IOptimismMintableERC20 } from \"./IOptimismMintableERC20.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @title OptimismMintableERC20\n * @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed\n * to allow the StandardBridge contracts to mint and burn tokens. This makes it possible to\n * use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa.\n * Designed to be backwards compatible with the older StandardL2ERC20 token which was only\n * meant for use on L2.\n */\ncontract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, Semver {\n /**\n * @notice Address of the corresponding version of this token on the remote chain.\n */\n address public immutable REMOTE_TOKEN;\n\n /**\n * @notice Address of the StandardBridge on this network.\n */\n address public immutable BRIDGE;\n\n /**\n * @notice Emitted whenever tokens are minted for an account.\n *\n * @param account Address of the account tokens are being minted for.\n * @param amount Amount of tokens minted.\n */\n event Mint(address indexed account, uint256 amount);\n\n /**\n * @notice Emitted whenever tokens are burned from an account.\n *\n * @param account Address of the account tokens are being burned from.\n * @param amount Amount of tokens burned.\n */\n event Burn(address indexed account, uint256 amount);\n\n /**\n * @notice A modifier that only allows the bridge to call\n */\n modifier onlyBridge() {\n require(msg.sender == BRIDGE, \"OptimismMintableERC20: only bridge can mint and burn\");\n _;\n }\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _bridge Address of the L2 standard bridge.\n * @param _remoteToken Address of the corresponding L1 token.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n */\n constructor(\n address _bridge,\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) Semver(1, 0, 0) {\n REMOTE_TOKEN = _remoteToken;\n BRIDGE = _bridge;\n }\n\n /**\n * @notice Allows the StandardBridge on this network to mint tokens.\n *\n * @param _to Address to mint tokens to.\n * @param _amount Amount of tokens to mint.\n */\n function mint(address _to, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _mint(_to, _amount);\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Allows the StandardBridge on this network to burn tokens.\n *\n * @param _from Address to burn tokens from.\n * @param _amount Amount of tokens to burn.\n */\n function burn(address _from, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _burn(_from, _amount);\n emit Burn(_from, _amount);\n }\n\n /**\n * @notice ERC165 interface check function.\n *\n * @param _interfaceId Interface ID to check.\n *\n * @return Whether or not the interface is supported by this contract.\n */\n function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {\n bytes4 iface1 = type(IERC165).interfaceId;\n // Interface corresponding to the legacy L2StandardERC20.\n bytes4 iface2 = type(ILegacyMintableERC20).interfaceId;\n // Interface corresponding to the updated OptimismMintableERC20 (this contract).\n bytes4 iface3 = type(IOptimismMintableERC20).interfaceId;\n return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward.\n */\n function l1Token() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the bridge. Use BRIDGE going forward.\n */\n function l2Bridge() public view returns (address) {\n return BRIDGE;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for REMOTE_TOKEN.\n */\n function remoteToken() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for BRIDGE.\n */\n function bridge() public view returns (address) {\n return BRIDGE;\n }\n}\n" - }, - "contracts/universal/OptimismMintableERC20Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Contract Imports */\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { Semver } from \"./Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000012\n * @title OptimismMintableERC20Factory\n * @notice OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20\n * contracts on the network it's deployed to. Simplifies the deployment process for users\n * who may be less familiar with deploying smart contracts. Designed to be backwards\n * compatible with the older StandardL2ERC20Factory contract.\n */\ncontract OptimismMintableERC20Factory is Semver {\n /**\n * @notice Address of the StandardBridge on this chain.\n */\n address public immutable BRIDGE;\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer\n * OptimismMintableERC20Created event. We recommend relying on that event instead.\n *\n * @param remoteToken Address of the token on the remote chain.\n * @param localToken Address of the created token on the local chain.\n */\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n\n /**\n * @notice Emitted whenever a new OptimismMintableERC20 is created.\n *\n * @param localToken Address of the created token on the local chain.\n * @param remoteToken Address of the corresponding token on the remote chain.\n * @param deployer Address of the account that deployed the token.\n */\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @notice The semver MUST be bumped any time that there is a change in\n * the OptimismMintableERC20 token contract since this contract\n * is responsible for deploying OptimismMintableERC20 contracts.\n *\n * @param _bridge Address of the StandardBridge on this chain.\n */\n constructor(address _bridge) Semver(1, 1, 0) {\n BRIDGE = _bridge;\n }\n\n /**\n * @custom:legacy\n * @notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the\n * newer createOptimismMintableERC20 function, which has a more intuitive name.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createStandardL2Token(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) external returns (address) {\n return createOptimismMintableERC20(_remoteToken, _name, _symbol);\n }\n\n /**\n * @notice Creates an instance of the OptimismMintableERC20 contract.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createOptimismMintableERC20(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) public returns (address) {\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC20Factory: must provide remote token address\"\n );\n\n address localToken = address(\n new OptimismMintableERC20(BRIDGE, _remoteToken, _name, _symbol)\n );\n\n // Emit the old event too for legacy support.\n emit StandardL2TokenCreated(_remoteToken, localToken);\n\n // Emit the updated event. The arguments here differ from the legacy event, but\n // are consistent with the ordering used in StandardBridge events.\n emit OptimismMintableERC20Created(localToken, _remoteToken, msg.sender);\n\n return localToken;\n }\n}\n" - }, - "contracts/universal/OptimismMintableERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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\";\nimport { Semver } from \"../universal/Semver.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, Semver {\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n uint256 public immutable REMOTE_CHAIN_ID;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable REMOTE_TOKEN;\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 * @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 * @custom:semver 1.1.0\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) Semver(1, 1, 0) {\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 REMOTE_CHAIN_ID = _remoteChainId;\n REMOTE_TOKEN = _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 * @inheritdoc IOptimismMintableERC721\n */\n function remoteChainId() external view returns (uint256) {\n return REMOTE_CHAIN_ID;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function remoteToken() external view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function bridge() external view returns (address) {\n return BRIDGE;\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 iface = type(IOptimismMintableERC721).interfaceId;\n return _interfaceId == iface || 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" - }, - "contracts/universal/OptimismMintableERC721Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\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 {\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 REMOTE_CHAIN_ID;\n\n /**\n * @notice Tracks addresses created by this factory.\n */\n mapping(address => bool) public isOptimismMintableERC721;\n\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 * @custom:semver 1.2.0\n * @notice The semver MUST be bumped any time that there is a change in\n * the OptimismMintableERC721 token contract since this contract\n * is responsible for deploying OptimismMintableERC721 contracts.\n *\n * @param _bridge Address of the ERC721 bridge on this network.\n * @param _remoteChainId Chain ID for the remote network.\n */\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 2, 0) {\n BRIDGE = _bridge;\n REMOTE_CHAIN_ID = _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, REMOTE_CHAIN_ID, _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/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) public virtual 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 public\n payable\n virtual\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) public virtual 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() public virtual proxyCallIfNotAdmin returns (address) {\n return _getAdmin();\n }\n\n /**\n * @notice Queries the implementation address.\n *\n * @return Implementation address.\n */\n function implementation() public virtual 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" - }, - "contracts/universal/ProxyAdmin.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.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 Ownable {\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 * @notice A mapping of proxy types, used for backwards compatibility.\n */\n mapping(address => ProxyType) public proxyType;\n\n /**\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 * @notice The address of the address manager, this is required to manage the\n * ResolvedDelegateProxy type.\n */\n AddressManager public addressManager;\n\n /**\n * @notice A legacy upgrading indicator used by the old Chugsplash Proxy.\n */\n bool internal upgrading;\n\n /**\n * @param _owner Address of the initial owner of this contract.\n */\n constructor(address _owner) Ownable() {\n _transferOwnership(_owner);\n }\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 * @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 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.\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 /**\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" - }, - "contracts/universal/Semver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 uint256 private immutable MAJOR_VERSION;\n\n /**\n * @notice Contract version number (minor).\n */\n uint256 private immutable MINOR_VERSION;\n\n /**\n * @notice Contract version number (patch).\n */\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" - }, - "contracts/universal/StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { IOptimismMintableERC20, ILegacyMintableERC20 } from \"./IOptimismMintableERC20.sol\";\nimport { CrossDomainMessenger } from \"./CrossDomainMessenger.sol\";\nimport { OptimismMintableERC20 } from \"./OptimismMintableERC20.sol\";\n\n/**\n * @custom:upgradeable\n * @title StandardBridge\n * @notice StandardBridge is a base contract for the L1 and L2 standard ERC20 bridges. It handles\n * the core bridging logic, including escrowing tokens that are native to the local chain\n * and minting/burning tokens that are native to the remote chain.\n */\nabstract contract StandardBridge {\n using SafeERC20 for IERC20;\n\n /**\n * @notice The L2 gas limit set when eth is depoisited using the receive() function.\n */\n uint32 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 200_000;\n\n /**\n * @notice Messenger contract on this domain.\n */\n CrossDomainMessenger public immutable MESSENGER;\n\n /**\n * @notice Corresponding bridge on the other domain.\n */\n StandardBridge public immutable OTHER_BRIDGE;\n\n /**\n * @custom:legacy\n * @custom:spacer messenger\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_0_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer l2TokenBridge\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_1_0_20;\n\n /**\n * @notice Mapping that stores deposits for a given pair of local and remote tokens.\n */\n mapping(address => mapping(address => uint256)) public deposits;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n * A gap size of 47 was chosen here, so that the first slot used in a child contract\n * would be a multiple of 50.\n */\n uint256[47] private __gap;\n\n /**\n * @notice Emitted when an ETH bridge is initiated to the other chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ETH bridge is finalized on this chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is initiated to the other chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is finalized on this chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Only allow EOAs to call the functions. Note that this is not safe against contracts\n * calling code within their constructors, but also doesn't really matter since we're\n * just trying to prevent users accidentally depositing with smart contract wallets.\n */\n modifier onlyEOA() {\n require(\n !Address.isContract(msg.sender),\n \"StandardBridge: function can only be called from an EOA\"\n );\n _;\n }\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) &&\n MESSENGER.xDomainMessageSender() == address(OTHER_BRIDGE),\n \"StandardBridge: function can only be called from the other bridge\"\n );\n _;\n }\n\n /**\n * @param _messenger Address of CrossDomainMessenger on this network.\n * @param _otherBridge Address of the other StandardBridge contract.\n */\n constructor(address payable _messenger, address payable _otherBridge) {\n MESSENGER = CrossDomainMessenger(_messenger);\n OTHER_BRIDGE = StandardBridge(_otherBridge);\n }\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n * Must be implemented by contracts that inherit.\n */\n receive() external payable virtual;\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @notice Sends ETH to the sender's address on the other chain.\n *\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETH(uint32 _minGasLimit, bytes calldata _extraData) public payable onlyEOA {\n _initiateBridgeETH(msg.sender, msg.sender, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a\n * smart contract and the call fails, the ETH will be temporarily locked in the\n * StandardBridge on the other chain until the call is replayed. If the call cannot be\n * replayed with any amount of gas (call always reverts), then the ETH will be\n * permanently locked in the StandardBridge on the other chain. ETH will also\n * be locked if the receiver is the other bridge, because finalizeBridgeETH will revert\n * in that case.\n *\n * @param _to Address of the receiver.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public payable {\n _initiateBridgeETH(msg.sender, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ERC20 tokens to the sender's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20(\n address _localToken,\n address _remoteToken,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual onlyEOA {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Finalizes an ETH bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public payable onlyOtherBridge {\n require(msg.value == _amount, \"StandardBridge: amount sent does not match amount required\");\n require(_to != address(this), \"StandardBridge: cannot send to self\");\n require(_to != address(MESSENGER), \"StandardBridge: cannot send to messenger\");\n\n // Emit the correct events. By default this will be _amount, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n\n bool success = SafeCall.call(_to, gasleft(), _amount, hex\"\");\n require(success, \"StandardBridge: ETH transfer failed\");\n }\n\n /**\n * @notice Finalizes an ERC20 bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public onlyOtherBridge {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).mint(_to, _amount);\n } else {\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] - _amount;\n IERC20(_localToken).safeTransfer(_to, _amount);\n }\n\n // Emit the correct events. By default this will be ERC20BridgeFinalized, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Initiates a bridge of ETH through the CrossDomainMessenger.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n require(\n msg.value == _amount,\n \"StandardBridge: bridging ETH must include sufficient ETH value\"\n );\n\n // Emit the correct events. By default this will be _amount, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage{ value: _amount }(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeETH.selector,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).burn(_from, _amount);\n } else {\n IERC20(_localToken).safeTransferFrom(_from, address(this), _amount);\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount;\n }\n\n // Emit the correct events. By default this will be ERC20BridgeInitiated, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeERC20.selector,\n // Because this call will be executed on the remote chain, we reverse the order of\n // the remote and local token addresses relative to their order in the\n // finalizeBridgeERC20 function.\n _remoteToken,\n _localToken,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Checks if a given address is an OptimismMintableERC20. Not perfect, but good enough.\n * Just the way we like it.\n *\n * @param _token Address of the token to check.\n *\n * @return True if the token is an OptimismMintableERC20.\n */\n function _isOptimismMintableERC20(address _token) internal view returns (bool) {\n return\n ERC165Checker.supportsInterface(_token, type(ILegacyMintableERC20).interfaceId) ||\n ERC165Checker.supportsInterface(_token, type(IOptimismMintableERC20).interfaceId);\n }\n\n /**\n * @notice Checks if the \"other token\" is the correct pair token for the OptimismMintableERC20.\n * Calls can be saved in the future by combining this logic with\n * `_isOptimismMintableERC20`.\n *\n * @param _mintableToken OptimismMintableERC20 to check against.\n * @param _otherToken Pair token to check.\n *\n * @return True if the other token is the correct pair token for the OptimismMintableERC20.\n */\n function _isCorrectTokenPair(address _mintableToken, address _otherToken)\n internal\n view\n returns (bool)\n {\n if (\n ERC165Checker.supportsInterface(_mintableToken, type(ILegacyMintableERC20).interfaceId)\n ) {\n return _otherToken == ILegacyMintableERC20(_mintableToken).l1Token();\n } else {\n return _otherToken == IOptimismMintableERC20(_mintableToken).remoteToken();\n }\n }\n\n /** @notice Emits the ETHBridgeInitiated event and if necessary the appropriate legacy event\n * when an ETH bridge is finalized on this chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ETHBridgeFinalized and if necessary the appropriate legacy event when an\n * ETH bridge is finalized on this chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ERC20BridgeInitiated event and if necessary the appropriate legacy\n * event when an ERC20 bridge is initiated to the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the ERC20 on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ERC20BridgeFinalized event and if necessary the appropriate legacy\n * event when an ERC20 bridge is initiated to the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the ERC20 on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/vendor/AddressAliasHelper.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npragma solidity ^0.8.0;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n unchecked {\n l2Address = address(uint160(l1Address) + offset);\n }\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n unchecked {\n l1Address = address(uint160(l2Address) - offset);\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/access/Ownable.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/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 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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/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/Address.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) || (!Address.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" - }, - "node_modules/@openzeppelin/contracts/security/ReentrancyGuard.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\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 ReentrancyGuard {\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 constructor() {\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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, allowance(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 = allowance(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 `from` to `to`.\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 Updates `owner` s allowance for `spender` based on spent `amount`.\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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 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 /**\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (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 constant _PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n /**\n * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\n * However, to ensure consistency with the upgradeable transpiler, we will continue\n * to reserve a slot.\n * @custom:oz-renamed-from _PERMIT_TYPEHASH\n */\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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: address zero is not a valid owner\");\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: invalid token ID\");\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 _requireMinted(tokenId);\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 token 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 _requireMinted(tokenId);\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: caller is not token 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: caller is not token 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 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 an {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 an {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 Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\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 /// @solidity memory-safe-assembly\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Address.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 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 /// @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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\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 /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.3) (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 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 /// @solidity memory-safe-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 {\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.2) (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 // prepare call\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n\n // perform static call\n bool success;\n uint256 returnSize;\n uint256 returnValue;\n assembly {\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\n returnSize := returndatasize()\n returnValue := mload(0x00)\n }\n\n return success && returnSize >= 0x20 && returnValue > 0;\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\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 == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`.\n // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.\n // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.\n // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a\n // good first aproximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1;\n uint256 x = a;\n if (x >> 128 > 0) {\n x >>= 128;\n result <<= 64;\n }\n if (x >> 64 > 0) {\n x >>= 64;\n result <<= 32;\n }\n if (x >> 32 > 0) {\n x >>= 32;\n result <<= 16;\n }\n if (x >> 16 > 0) {\n x >>= 16;\n result <<= 8;\n }\n if (x >> 8 > 0) {\n x >>= 8;\n result <<= 4;\n }\n if (x >> 4 > 0) {\n x >>= 4;\n result <<= 2;\n }\n if (x >> 2 > 0) {\n result <<= 1;\n }\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n uint256 result = sqrt(a);\n if (rounding == Rounding.Up && result * result < a) {\n result += 1;\n }\n return result;\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\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 * _Available since v4.2._\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 uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(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 * _Available since v2.5._\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 uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(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 * _Available since v4.2._\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 uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(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 * _Available since v2.5._\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 uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(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 * _Available since v2.5._\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 uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(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 * _Available since v2.5._\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 * _Available since v2.5._\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 * _Available since v3.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 int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248) {\n require(value >= type(int248).min && value <= type(int248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return int248(value);\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240) {\n require(value >= type(int240).min && value <= type(int240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return int240(value);\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232) {\n require(value >= type(int232).min && value <= type(int232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return int232(value);\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224) {\n require(value >= type(int224).min && value <= type(int224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return int224(value);\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216) {\n require(value >= type(int216).min && value <= type(int216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return int216(value);\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208) {\n require(value >= type(int208).min && value <= type(int208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return int208(value);\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200) {\n require(value >= type(int200).min && value <= type(int200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return int200(value);\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192) {\n require(value >= type(int192).min && value <= type(int192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return int192(value);\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184) {\n require(value >= type(int184).min && value <= type(int184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return int184(value);\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176) {\n require(value >= type(int176).min && value <= type(int176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return int176(value);\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168) {\n require(value >= type(int168).min && value <= type(int168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return int168(value);\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160) {\n require(value >= type(int160).min && value <= type(int160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return int160(value);\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152) {\n require(value >= type(int152).min && value <= type(int152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return int152(value);\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144) {\n require(value >= type(int144).min && value <= type(int144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return int144(value);\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136) {\n require(value >= type(int136).min && value <= type(int136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return int136(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 int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120) {\n require(value >= type(int120).min && value <= type(int120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return int120(value);\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112) {\n require(value >= type(int112).min && value <= type(int112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return int112(value);\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104) {\n require(value >= type(int104).min && value <= type(int104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return int104(value);\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96) {\n require(value >= type(int96).min && value <= type(int96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return int96(value);\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88) {\n require(value >= type(int88).min && value <= type(int88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return int88(value);\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80) {\n require(value >= type(int80).min && value <= type(int80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return int80(value);\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72) {\n require(value >= type(int72).min && value <= type(int72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return int72(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 int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56) {\n require(value >= type(int56).min && value <= type(int56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return int56(value);\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48) {\n require(value >= type(int48).min && value <= type(int48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return int48(value);\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40) {\n require(value >= type(int40).min && value <= type(int40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return int40(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 int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24) {\n require(value >= type(int24).min && value <= type(int24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return int24(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 * _Available since v3.0._\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" - }, - "node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@rari-capital/solmate/src/utils/Bytes32AddressLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Library for converting between addresses and bytes32 values.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/Bytes32AddressLib.sol)\nlibrary Bytes32AddressLib {\n function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n function fillLast12Bytes(address addressValue) internal pure returns (bytes32) {\n return bytes32(bytes20(addressValue));\n }\n}\n" - }, - "node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)\nlibrary FixedPointMathLib {\n /*//////////////////////////////////////////////////////////////\n SIMPLIFIED FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n }\n\n function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n }\n\n function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n }\n\n function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n }\n\n function powWad(int256 x, int256 y) internal pure returns (int256) {\n // Equivalent to x to the power of y because x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)\n return expWad((lnWad(x) * y) / int256(WAD)); // Using ln(x) means x must be greater than 0.\n }\n\n function expWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n // When the result is < 0.5 we return zero. This happens when\n // x <= floor(log(0.5e18) * 1e18) ~ -42e18\n if (x <= -42139678854452767551) return 0;\n\n // When the result is > (2**255 - 1) / 1e18 we can not represent it as an\n // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.\n if (x >= 135305999368893231589) revert(\"EXP_OVERFLOW\");\n\n // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96\n // for more intermediate precision and a binary basis. This base conversion\n // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.\n x = (x << 78) / 5**18;\n\n // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers\n // of two such that exp(x) = exp(x') * 2**k, where k is an integer.\n // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).\n int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96;\n x = x - k * 54916777467707473351141471128;\n\n // k is in the range [-61, 195].\n\n // Evaluate using a (6, 7)-term rational approximation.\n // p is made monic, we'll multiply by a scale factor later.\n int256 y = x + 1346386616545796478920950773328;\n y = ((y * x) >> 96) + 57155421227552351082224309758442;\n int256 p = y + x - 94201549194550492254356042504812;\n p = ((p * y) >> 96) + 28719021644029726153956944680412240;\n p = p * x + (4385272521454847904659076985693276 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n int256 q = x - 2855989394907223263936484059900;\n q = ((q * x) >> 96) + 50020603652535783019961831881945;\n q = ((q * x) >> 96) - 533845033583426703283633433725380;\n q = ((q * x) >> 96) + 3604857256930695427073651918091429;\n q = ((q * x) >> 96) - 14423608567350463180887372962807573;\n q = ((q * x) >> 96) + 26449188498355588339934803723976023;\n\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial won't have zeros in the domain as all its roots are complex.\n // No scaling is necessary because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r should be in the range (0.09, 0.25) * 2**96.\n\n // We now need to multiply r by:\n // * the scale factor s = ~6.031367120.\n // * the 2**k factor from the range reduction.\n // * the 1e18 / 2**96 factor for base conversion.\n // We do this all at once, with an intermediate result in 2**213\n // basis, so the final right shift is always by a positive amount.\n r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k));\n }\n }\n\n function lnWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n require(x > 0, \"UNDEFINED\");\n\n // We want to convert x from 10**18 fixed point to 2**96 fixed point.\n // We do this by multiplying by 2**96 / 10**18. But since\n // ln(x * C) = ln(x) + ln(C), we can simply do nothing here\n // and add ln(2**96 / 10**18) at the end.\n\n // Reduce range of x to (1, 2) * 2**96\n // ln(2^k * x) = k * ln(2) + ln(x)\n int256 k = int256(log2(uint256(x))) - 96;\n x <<= uint256(159 - k);\n x = int256(uint256(x) >> 159);\n\n // Evaluate using a (8, 8)-term rational approximation.\n // p is made monic, we will multiply by a scale factor later.\n int256 p = x + 3273285459638523848632254066296;\n p = ((p * x) >> 96) + 24828157081833163892658089445524;\n p = ((p * x) >> 96) + 43456485725739037958740375743393;\n p = ((p * x) >> 96) - 11111509109440967052023855526967;\n p = ((p * x) >> 96) - 45023709667254063763336534515857;\n p = ((p * x) >> 96) - 14706773417378608786704636184526;\n p = p * x - (795164235651350426258249787498 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n // q is monic by convention.\n int256 q = x + 5573035233440673466300451813936;\n q = ((q * x) >> 96) + 71694874799317883764090561454958;\n q = ((q * x) >> 96) + 283447036172924575727196451306956;\n q = ((q * x) >> 96) + 401686690394027663651624208769553;\n q = ((q * x) >> 96) + 204048457590392012362485061816622;\n q = ((q * x) >> 96) + 31853899698501571402653359427138;\n q = ((q * x) >> 96) + 909429971244387300277376558375;\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial is known not to have zeros in the domain.\n // No scaling required because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r is in the range (0, 0.125) * 2**96\n\n // Finalization, we need to:\n // * multiply by the scale factor s = 5.549…\n // * add ln(2**96 / 10**18)\n // * add k * ln(2)\n // * multiply by 10**18 / 2**96 = 5**18 >> 78\n\n // mul s * 5e18 * 2**96, base is now 5**18 * 2**192\n r *= 1677202110996718588342820967067443963516166;\n // add ln(2) * k * 5e18 * 2**192\n r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;\n // add ln(2**96 / 10**18) * 5e18 * 2**192\n r += 600920179829731861736702779321621459595472258049074101567377883020018308;\n // base conversion: mul 2**18 / 2**192\n r >>= 174;\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n LOW LEVEL FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function mulDivDown(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // Divide z by the denominator.\n z := div(z, denominator)\n }\n }\n\n function mulDivUp(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // First, divide z - 1 by the denominator and add 1.\n // We allow z - 1 to underflow if z is 0, because we multiply the\n // end result by 0 if z is zero, ensuring we return 0 if z is zero.\n z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))\n }\n }\n\n function rpow(\n uint256 x,\n uint256 n,\n uint256 scalar\n ) internal pure returns (uint256 z) {\n assembly {\n switch x\n case 0 {\n switch n\n case 0 {\n // 0 ** 0 = 1\n z := scalar\n }\n default {\n // 0 ** n = 0\n z := 0\n }\n }\n default {\n switch mod(n, 2)\n case 0 {\n // If n is even, store scalar in z for now.\n z := scalar\n }\n default {\n // If n is odd, store x in z for now.\n z := x\n }\n\n // Shifting right by 1 is like dividing by 2.\n let half := shr(1, scalar)\n\n for {\n // Shift n right by 1 before looping to halve it.\n n := shr(1, n)\n } n {\n // Shift n right by 1 each iteration to halve it.\n n := shr(1, n)\n } {\n // Revert immediately if x ** 2 would overflow.\n // Equivalent to iszero(eq(div(xx, x), x)) here.\n if shr(128, x) {\n revert(0, 0)\n }\n\n // Store x squared.\n let xx := mul(x, x)\n\n // Round to the nearest number.\n let xxRound := add(xx, half)\n\n // Revert if xx + half overflowed.\n if lt(xxRound, xx) {\n revert(0, 0)\n }\n\n // Set x to scaled xxRound.\n x := div(xxRound, scalar)\n\n // If n is even:\n if mod(n, 2) {\n // Compute z * x.\n let zx := mul(z, x)\n\n // If z * x overflowed:\n if iszero(eq(div(zx, x), z)) {\n // Revert if x is non-zero.\n if iszero(iszero(x)) {\n revert(0, 0)\n }\n }\n\n // Round to the nearest number.\n let zxRound := add(zx, half)\n\n // Revert if zx + half overflowed.\n if lt(zxRound, zx) {\n revert(0, 0)\n }\n\n // Return properly scaled zxRound.\n z := div(zxRound, scalar)\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n GENERAL NUMBER UTILITIES\n //////////////////////////////////////////////////////////////*/\n\n function sqrt(uint256 x) internal pure returns (uint256 z) {\n assembly {\n let y := x // We start y at x, which will help us make our initial estimate.\n\n z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n // We check y >= 2^(k + 8) but shift right by k bits\n // each branch to ensure that if x >= 256, then y >= 256.\n if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n y := shr(128, y)\n z := shl(64, z)\n }\n if iszero(lt(y, 0x1000000000000000000)) {\n y := shr(64, y)\n z := shl(32, z)\n }\n if iszero(lt(y, 0x10000000000)) {\n y := shr(32, y)\n z := shl(16, z)\n }\n if iszero(lt(y, 0x1000000)) {\n y := shr(16, y)\n z := shl(8, z)\n }\n\n // Goal was to get z*z*y within a small factor of x. More iterations could\n // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n // There is no overflow risk here since y < 2^136 after the first branch above.\n z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n\n // If x+1 is a perfect square, the Babylonian method cycles between\n // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n z := sub(z, lt(div(x, z), z))\n }\n }\n\n function log2(uint256 x) internal pure returns (uint256 r) {\n require(x > 0, \"UNDEFINED\");\n\n assembly {\n r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n r := or(r, shl(4, lt(0xffff, shr(r, x))))\n r := or(r, shl(3, lt(0xff, shr(r, x))))\n r := or(r, shl(2, lt(0xf, shr(r, x))))\n r := or(r, shl(1, lt(0x3, shr(r, x))))\n r := or(r, lt(0x1, shr(r, x)))\n }\n }\n}\n" - }, - "node_modules/ds-test/src/test.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see .\n\npragma solidity >=0.5.0;\n\ncontract DSTest {\n event log (string);\n event logs (bytes);\n\n event log_address (address);\n event log_bytes32 (bytes32);\n event log_int (int);\n event log_uint (uint);\n event log_bytes (bytes);\n event log_string (string);\n\n event log_named_address (string key, address val);\n event log_named_bytes32 (string key, bytes32 val);\n event log_named_decimal_int (string key, int val, uint decimals);\n event log_named_decimal_uint (string key, uint val, uint decimals);\n event log_named_int (string key, int val);\n event log_named_uint (string key, uint val);\n event log_named_bytes (string key, bytes val);\n event log_named_string (string key, string val);\n\n bool public IS_TEST = true;\n bool private _failed;\n\n address constant HEVM_ADDRESS =\n address(bytes20(uint160(uint256(keccak256('hevm cheat code')))));\n\n modifier mayRevert() { _; }\n modifier testopts(string memory) { _; }\n\n function failed() public returns (bool) {\n if (_failed) {\n return _failed;\n } else {\n bool globalFailed = false;\n if (hasHEVMContext()) {\n (, bytes memory retdata) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"load(address,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"))\n )\n );\n globalFailed = abi.decode(retdata, (bool));\n }\n return globalFailed;\n }\n } \n\n function fail() internal {\n if (hasHEVMContext()) {\n (bool status, ) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"store(address,bytes32,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"), bytes32(uint256(0x01)))\n )\n );\n status; // Silence compiler warnings\n }\n _failed = true;\n }\n\n function hasHEVMContext() internal view returns (bool) {\n uint256 hevmCodeSize = 0;\n assembly {\n hevmCodeSize := extcodesize(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D)\n }\n return hevmCodeSize > 0;\n }\n\n modifier logs_gas() {\n uint startGas = gasleft();\n _;\n uint endGas = gasleft();\n emit log_named_uint(\"gas\", startGas - endGas);\n }\n\n function assertTrue(bool condition) internal {\n if (!condition) {\n emit log(\"Error: Assertion Failed\");\n fail();\n }\n }\n\n function assertTrue(bool condition, string memory err) internal {\n if (!condition) {\n emit log_named_string(\"Error\", err);\n assertTrue(condition);\n }\n }\n\n function assertEq(address a, address b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [address]\");\n emit log_named_address(\" Expected\", b);\n emit log_named_address(\" Actual\", a);\n fail();\n }\n }\n function assertEq(address a, address b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes32 a, bytes32 b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bytes32]\");\n emit log_named_bytes32(\" Expected\", b);\n emit log_named_bytes32(\" Actual\", a);\n fail();\n }\n }\n function assertEq(bytes32 a, bytes32 b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq32(bytes32 a, bytes32 b) internal {\n assertEq(a, b);\n }\n function assertEq32(bytes32 a, bytes32 b, string memory err) internal {\n assertEq(a, b, err);\n }\n\n function assertEq(int a, int b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [int]\");\n emit log_named_int(\" Expected\", b);\n emit log_named_int(\" Actual\", a);\n fail();\n }\n }\n function assertEq(int a, int b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq(uint a, uint b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [uint]\");\n emit log_named_uint(\" Expected\", b);\n emit log_named_uint(\" Actual\", a);\n fail();\n }\n }\n function assertEq(uint a, uint b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEqDecimal(int a, int b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Expected\", b, decimals);\n emit log_named_decimal_int(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Expected\", b, decimals);\n emit log_named_decimal_uint(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n\n function assertGt(uint a, uint b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGt(uint a, uint b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGt(int a, int b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGt(int a, int b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGtDecimal(int a, int b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n\n function assertGe(uint a, uint b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGe(uint a, uint b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGe(int a, int b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGe(int a, int b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGeDecimal(int a, int b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertLt(uint a, uint b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLt(uint a, uint b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLt(int a, int b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLt(int a, int b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLtDecimal(int a, int b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n\n function assertLe(uint a, uint b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLe(uint a, uint b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLe(int a, int b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLe(int a, int b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLeDecimal(int a, int b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLeDecimal(a, b, decimals);\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertEq(string memory a, string memory b) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log(\"Error: a == b not satisfied [string]\");\n emit log_named_string(\" Expected\", b);\n emit log_named_string(\" Actual\", a);\n fail();\n }\n }\n function assertEq(string memory a, string memory b, string memory err) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function checkEq0(bytes memory a, bytes memory b) internal pure returns (bool ok) {\n ok = true;\n if (a.length == b.length) {\n for (uint i = 0; i < a.length; i++) {\n if (a[i] != b[i]) {\n ok = false;\n }\n }\n } else {\n ok = false;\n }\n }\n function assertEq0(bytes memory a, bytes memory b) internal {\n if (!checkEq0(a, b)) {\n emit log(\"Error: a == b not satisfied [bytes]\");\n emit log_named_bytes(\" Expected\", b);\n emit log_named_bytes(\" Actual\", a);\n fail();\n }\n }\n function assertEq0(bytes memory a, bytes memory b, string memory err) internal {\n if (!checkEq0(a, b)) {\n emit log_named_string(\"Error\", err);\n assertEq0(a, b);\n }\n }\n}\n" - }, - "node_modules/forge-std/src/Base.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {StdStorage} from \"./StdStorage.sol\";\nimport {Vm, VmSafe} from \"./Vm.sol\";\n\nabstract contract CommonBase {\n // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.\n address internal constant VM_ADDRESS = address(uint160(uint256(keccak256(\"hevm cheat code\"))));\n // console.sol and console2.sol work by executing a staticcall to this address.\n address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;\n // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38.\n address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256(\"foundry default caller\"))));\n // Address of the test contract, deployed by the DEFAULT_SENDER.\n address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;\n // Deterministic deployment address of the Multicall3 contract.\n address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11;\n\n uint256 internal constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n Vm internal constant vm = Vm(VM_ADDRESS);\n StdStorage internal stdstore;\n}\n\nabstract contract TestBase is CommonBase {}\n\nabstract contract ScriptBase is CommonBase {\n // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.\n address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;\n\n VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);\n}\n" - }, - "node_modules/forge-std/src/StdAssertions.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {DSTest} from \"ds-test/test.sol\";\nimport {stdMath} from \"./StdMath.sol\";\n\nabstract contract StdAssertions is DSTest {\n event log_array(uint256[] val);\n event log_array(int256[] val);\n event log_array(address[] val);\n event log_named_array(string key, uint256[] val);\n event log_named_array(string key, int256[] val);\n event log_named_array(string key, address[] val);\n\n function fail(string memory err) internal virtual {\n emit log_named_string(\"Error\", err);\n fail();\n }\n\n function assertFalse(bool data) internal virtual {\n assertTrue(!data);\n }\n\n function assertFalse(bool data, string memory err) internal virtual {\n assertTrue(!data, err);\n }\n\n function assertEq(bool a, bool b) internal virtual {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bool]\");\n emit log_named_string(\" Left\", a ? \"true\" : \"false\");\n emit log_named_string(\" Right\", b ? \"true\" : \"false\");\n fail();\n }\n }\n\n function assertEq(bool a, bool b, string memory err) internal virtual {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes memory a, bytes memory b) internal virtual {\n assertEq0(a, b);\n }\n\n function assertEq(bytes memory a, bytes memory b, string memory err) internal virtual {\n assertEq0(a, b, err);\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [uint[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [int[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(address[] memory a, address[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [address[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(address[] memory a, address[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n // Legacy helper\n function assertEqUint(uint256 a, uint256 b) internal virtual {\n assertEq(uint256(a), uint256(b));\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Left\", a);\n emit log_named_uint(\" Right\", b);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_decimal_uint(\" Left\", a, decimals);\n emit log_named_decimal_uint(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max Delta\", maxDelta, decimals);\n emit log_named_decimal_uint(\" Delta\", delta, decimals);\n fail();\n }\n }\n\n function assertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbsDecimal(a, b, maxDelta, decimals);\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Left\", a);\n emit log_named_int(\" Right\", b);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_decimal_int(\" Left\", a, decimals);\n emit log_named_decimal_int(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max Delta\", maxDelta, decimals);\n emit log_named_decimal_uint(\" Delta\", delta, decimals);\n fail();\n }\n }\n\n function assertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbsDecimal(a, b, maxDelta, decimals);\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%\n ) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Left\", a);\n emit log_named_uint(\" Right\", b);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n string memory err\n ) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n\n function assertApproxEqRelDecimal(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n uint256 decimals\n ) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_decimal_uint(\" Left\", a, decimals);\n emit log_named_decimal_uint(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRelDecimal(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n uint256 decimals,\n string memory err\n ) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Left\", a);\n emit log_named_int(\" Right\", b);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta, string memory err) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n\n function assertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_decimal_int(\" Left\", a, decimals);\n emit log_named_decimal_int(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);\n }\n }\n\n function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual {\n assertEqCall(target, callDataA, target, callDataB, true);\n }\n\n function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB)\n internal\n virtual\n {\n assertEqCall(targetA, callDataA, targetB, callDataB, true);\n }\n\n function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData)\n internal\n virtual\n {\n assertEqCall(target, callDataA, target, callDataB, strictRevertData);\n }\n\n function assertEqCall(\n address targetA,\n bytes memory callDataA,\n address targetB,\n bytes memory callDataB,\n bool strictRevertData\n ) internal virtual {\n (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA);\n (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB);\n\n if (successA && successB) {\n assertEq(returnDataA, returnDataB, \"Call return data does not match\");\n }\n\n if (!successA && !successB && strictRevertData) {\n assertEq(returnDataA, returnDataB, \"Call revert data does not match\");\n }\n\n if (!successA && successB) {\n emit log(\"Error: Calls were not equal\");\n emit log_named_bytes(\" Left call revert data\", returnDataA);\n emit log_named_bytes(\" Right call return data\", returnDataB);\n fail();\n }\n\n if (successA && !successB) {\n emit log(\"Error: Calls were not equal\");\n emit log_named_bytes(\" Left call return data\", returnDataA);\n emit log_named_bytes(\" Right call revert data\", returnDataB);\n fail();\n }\n }\n}\n" - }, - "node_modules/forge-std/src/StdChains.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n/**\n * StdChains provides information about EVM compatible chains that can be used in scripts/tests.\n * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are\n * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of\n * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the\n * alias used in this contract, which can be found as the first argument to the\n * `setChainWithDefaultRpcUrl` call in the `initialize` function.\n *\n * There are two main ways to use this contract:\n * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or\n * `setChain(string memory chainAlias, Chain memory chain)`\n * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.\n *\n * The first time either of those are used, chains are initialized with the default set of RPC URLs.\n * This is done in `initialize`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in\n * `defaultRpcUrls`.\n *\n * The `setChain` function is straightforward, and it simply saves off the given chain data.\n *\n * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say\n * we want to retrieve `mainnet`'s RPC URL:\n * - If you haven't set any mainnet chain info with `setChain`, you haven't specified that\n * chain in `foundry.toml` and no env var is set, the default data and RPC URL will be returned.\n * - If you have set a mainnet RPC URL in `foundry.toml` it will return that, if valid (e.g. if\n * a URL is given or if an environment variable is given and that environment variable exists).\n * Otherwise, the default data is returned.\n * - If you specified data with `setChain` it will return that.\n *\n * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults.\n */\nabstract contract StdChains {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private initialized;\n\n struct ChainData {\n string name;\n uint256 chainId;\n string rpcUrl;\n }\n\n struct Chain {\n // The chain name.\n string name;\n // The chain's Chain ID.\n uint256 chainId;\n // The chain's alias. (i.e. what gets specified in `foundry.toml`).\n string chainAlias;\n // A default RPC endpoint for this chain.\n // NOTE: This default RPC URL is included for convenience to facilitate quick tests and\n // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy\n // usage as you will be throttled and this is a disservice to others who need this endpoint.\n string rpcUrl;\n }\n\n // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.\n mapping(string => Chain) private chains;\n // Maps from the chain's alias to it's default RPC URL.\n mapping(string => string) private defaultRpcUrls;\n // Maps from a chain ID to it's alias.\n mapping(uint256 => string) private idToAlias;\n\n bool private fallbackToDefaultRpcUrls = true;\n\n // The RPC URL will be fetched from config or defaultRpcUrls if possible.\n function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {\n require(bytes(chainAlias).length != 0, \"StdChains getChain(string): Chain alias cannot be the empty string.\");\n\n initialize();\n chain = chains[chainAlias];\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(string): Chain with alias \\\"\", chainAlias, \"\\\" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {\n require(chainId != 0, \"StdChains getChain(uint256): Chain ID cannot be 0.\");\n initialize();\n string memory chainAlias = idToAlias[chainId];\n\n chain = chains[chainAlias];\n\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(uint256): Chain with ID \", vm.toString(chainId), \" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n // set chain info, with priority to argument's rpcUrl field.\n function setChain(string memory chainAlias, ChainData memory chain) internal virtual {\n require(\n bytes(chainAlias).length != 0,\n \"StdChains setChain(string,ChainData): Chain alias cannot be the empty string.\"\n );\n\n require(chain.chainId != 0, \"StdChains setChain(string,ChainData): Chain ID cannot be 0.\");\n\n initialize();\n string memory foundAlias = idToAlias[chain.chainId];\n\n require(\n bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)),\n string(\n abi.encodePacked(\n \"StdChains setChain(string,ChainData): Chain ID \",\n vm.toString(chain.chainId),\n \" already used by \\\"\",\n foundAlias,\n \"\\\".\"\n )\n )\n );\n\n uint256 oldChainId = chains[chainAlias].chainId;\n delete idToAlias[oldChainId];\n\n chains[chainAlias] =\n Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});\n idToAlias[chain.chainId] = chainAlias;\n }\n\n // set chain info, with priority to argument's rpcUrl field.\n function setChain(string memory chainAlias, Chain memory chain) internal virtual {\n setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));\n }\n\n function _toUpper(string memory str) private pure returns (string memory) {\n bytes memory strb = bytes(str);\n bytes memory copy = new bytes(strb.length);\n for (uint256 i = 0; i < strb.length; i++) {\n bytes1 b = strb[i];\n if (b >= 0x61 && b <= 0x7A) {\n copy[i] = bytes1(uint8(b) - 32);\n } else {\n copy[i] = b;\n }\n }\n return string(copy);\n }\n\n // lookup rpcUrl, in descending order of priority:\n // current -> config (foundry.toml) -> environment variable -> default\n function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) private returns (Chain memory) {\n if (bytes(chain.rpcUrl).length == 0) {\n try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {\n chain.rpcUrl = configRpcUrl;\n } catch (bytes memory err) {\n string memory envName = string(abi.encodePacked(_toUpper(chainAlias), \"_RPC_URL\"));\n if (fallbackToDefaultRpcUrls) {\n chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]);\n } else {\n chain.rpcUrl = vm.envString(envName);\n }\n // distinguish 'not found' from 'cannot read'\n bytes memory notFoundError =\n abi.encodeWithSignature(\"CheatCodeError\", string(abi.encodePacked(\"invalid rpc url \", chainAlias)));\n if (keccak256(notFoundError) != keccak256(err) || bytes(chain.rpcUrl).length == 0) {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, err), mload(err))\n }\n }\n }\n }\n return chain;\n }\n\n function setFallbackToDefaultRpcUrls(bool useDefault) internal {\n fallbackToDefaultRpcUrls = useDefault;\n }\n\n function initialize() private {\n if (initialized) return;\n\n initialized = true;\n\n // If adding an RPC here, make sure to test the default RPC URL in `testRpcs`\n setChainWithDefaultRpcUrl(\"anvil\", ChainData(\"Anvil\", 31337, \"http://127.0.0.1:8545\"));\n setChainWithDefaultRpcUrl(\n \"mainnet\", ChainData(\"Mainnet\", 1, \"https://mainnet.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\n \"goerli\", ChainData(\"Goerli\", 5, \"https://goerli.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\n \"sepolia\", ChainData(\"Sepolia\", 11155111, \"https://sepolia.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\"optimism\", ChainData(\"Optimism\", 10, \"https://mainnet.optimism.io\"));\n setChainWithDefaultRpcUrl(\"optimism_goerli\", ChainData(\"Optimism Goerli\", 420, \"https://goerli.optimism.io\"));\n setChainWithDefaultRpcUrl(\"arbitrum_one\", ChainData(\"Arbitrum One\", 42161, \"https://arb1.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\n \"arbitrum_one_goerli\", ChainData(\"Arbitrum One Goerli\", 421613, \"https://goerli-rollup.arbitrum.io/rpc\")\n );\n setChainWithDefaultRpcUrl(\"arbitrum_nova\", ChainData(\"Arbitrum Nova\", 42170, \"https://nova.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\"polygon\", ChainData(\"Polygon\", 137, \"https://polygon-rpc.com\"));\n setChainWithDefaultRpcUrl(\n \"polygon_mumbai\", ChainData(\"Polygon Mumbai\", 80001, \"https://rpc-mumbai.maticvigil.com\")\n );\n setChainWithDefaultRpcUrl(\"avalanche\", ChainData(\"Avalanche\", 43114, \"https://api.avax.network/ext/bc/C/rpc\"));\n setChainWithDefaultRpcUrl(\n \"avalanche_fuji\", ChainData(\"Avalanche Fuji\", 43113, \"https://api.avax-test.network/ext/bc/C/rpc\")\n );\n setChainWithDefaultRpcUrl(\n \"bnb_smart_chain\", ChainData(\"BNB Smart Chain\", 56, \"https://bsc-dataseed1.binance.org\")\n );\n setChainWithDefaultRpcUrl(\n \"bnb_smart_chain_testnet\",\n ChainData(\"BNB Smart Chain Testnet\", 97, \"https://rpc.ankr.com/bsc_testnet_chapel\")\n );\n setChainWithDefaultRpcUrl(\"gnosis_chain\", ChainData(\"Gnosis Chain\", 100, \"https://rpc.gnosischain.com\"));\n }\n\n // set chain info, with priority to chainAlias' rpc url in foundry.toml\n function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {\n string memory rpcUrl = chain.rpcUrl;\n defaultRpcUrls[chainAlias] = rpcUrl;\n chain.rpcUrl = \"\";\n setChain(chainAlias, chain);\n chain.rpcUrl = rpcUrl; // restore argument\n }\n}\n" - }, - "node_modules/forge-std/src/StdCheats.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {Vm} from \"./Vm.sol\";\n\nabstract contract StdCheatsSafe {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private gasMeteringOff;\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawTx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n // json value name = function\n string functionSig;\n bytes32 hash;\n // json value name = tx\n RawTx1559Detail txDetail;\n // json value name = type\n string opcode;\n }\n\n struct RawTx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n bytes gas;\n bytes nonce;\n address to;\n bytes txType;\n bytes value;\n }\n\n struct Tx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n bytes32 hash;\n Tx1559Detail txDetail;\n string opcode;\n }\n\n struct Tx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n uint256 gas;\n uint256 nonce;\n address to;\n uint256 txType;\n uint256 value;\n }\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct TxLegacy {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n string hash;\n string opcode;\n TxDetailLegacy transaction;\n }\n\n struct TxDetailLegacy {\n AccessList[] accessList;\n uint256 chainId;\n bytes data;\n address from;\n uint256 gas;\n uint256 gasPrice;\n bytes32 hash;\n uint256 nonce;\n bytes1 opcode;\n bytes32 r;\n bytes32 s;\n uint256 txType;\n address to;\n uint8 v;\n uint256 value;\n }\n\n struct AccessList {\n address accessAddress;\n bytes32[] storageKeys;\n }\n\n // Data structures to parse Receipt objects from the broadcast artifact.\n // The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawReceipt {\n bytes32 blockHash;\n bytes blockNumber;\n address contractAddress;\n bytes cumulativeGasUsed;\n bytes effectiveGasPrice;\n address from;\n bytes gasUsed;\n RawReceiptLog[] logs;\n bytes logsBloom;\n bytes status;\n address to;\n bytes32 transactionHash;\n bytes transactionIndex;\n }\n\n struct Receipt {\n bytes32 blockHash;\n uint256 blockNumber;\n address contractAddress;\n uint256 cumulativeGasUsed;\n uint256 effectiveGasPrice;\n address from;\n uint256 gasUsed;\n ReceiptLog[] logs;\n bytes logsBloom;\n uint256 status;\n address to;\n bytes32 transactionHash;\n uint256 transactionIndex;\n }\n\n // Data structures to parse the entire broadcast artifact, assuming the\n // transactions conform to EIP1559.\n\n struct EIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n Receipt[] receipts;\n uint256 timestamp;\n Tx1559[] transactions;\n TxReturn[] txReturns;\n }\n\n struct RawEIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n RawReceipt[] receipts;\n TxReturn[] txReturns;\n uint256 timestamp;\n RawTx1559[] transactions;\n }\n\n struct RawReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n bytes blockNumber;\n bytes data;\n bytes logIndex;\n bool removed;\n bytes32[] topics;\n bytes32 transactionHash;\n bytes transactionIndex;\n bytes transactionLogIndex;\n }\n\n struct ReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n uint256 blockNumber;\n bytes data;\n uint256 logIndex;\n bytes32[] topics;\n uint256 transactionIndex;\n uint256 transactionLogIndex;\n bool removed;\n }\n\n struct TxReturn {\n string internalType;\n string value;\n }\n\n function assumeNoPrecompiles(address addr) internal virtual {\n // Assembly required since `block.chainid` was introduced in 0.8.0.\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n assumeNoPrecompiles(addr, chainId);\n }\n\n function assumeNoPrecompiles(address addr, uint256 chainId) internal pure virtual {\n // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific\n // address), but the same rationale for excluding them applies so we include those too.\n\n // These should be present on all EVM-compatible chains.\n vm.assume(addr < address(0x1) || addr > address(0x9));\n\n // forgefmt: disable-start\n if (chainId == 10 || chainId == 420) {\n // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21\n vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));\n } else if (chainId == 42161 || chainId == 421613) {\n // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains\n vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));\n } else if (chainId == 43114 || chainId == 43113) {\n // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59\n vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));\n vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));\n vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));\n }\n // forgefmt: disable-end\n }\n\n function readEIP1559ScriptArtifact(string memory path)\n internal\n view\n virtual\n returns (EIP1559ScriptArtifact memory)\n {\n string memory data = vm.readFile(path);\n bytes memory parsedData = vm.parseJson(data);\n RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));\n EIP1559ScriptArtifact memory artifact;\n artifact.libraries = rawArtifact.libraries;\n artifact.path = rawArtifact.path;\n artifact.timestamp = rawArtifact.timestamp;\n artifact.pending = rawArtifact.pending;\n artifact.txReturns = rawArtifact.txReturns;\n artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);\n artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);\n return artifact;\n }\n\n function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {\n Tx1559[] memory txs = new Tx1559[](rawTxs.length);\n for (uint256 i; i < rawTxs.length; i++) {\n txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);\n }\n return txs;\n }\n\n function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {\n Tx1559 memory transaction;\n transaction.arguments = rawTx.arguments;\n transaction.contractName = rawTx.contractName;\n transaction.functionSig = rawTx.functionSig;\n transaction.hash = rawTx.hash;\n transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);\n transaction.opcode = rawTx.opcode;\n return transaction;\n }\n\n function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)\n internal\n pure\n virtual\n returns (Tx1559Detail memory)\n {\n Tx1559Detail memory txDetail;\n txDetail.data = rawDetail.data;\n txDetail.from = rawDetail.from;\n txDetail.to = rawDetail.to;\n txDetail.nonce = _bytesToUint(rawDetail.nonce);\n txDetail.txType = _bytesToUint(rawDetail.txType);\n txDetail.value = _bytesToUint(rawDetail.value);\n txDetail.gas = _bytesToUint(rawDetail.gas);\n txDetail.accessList = rawDetail.accessList;\n return txDetail;\n }\n\n function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".transactions\");\n RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));\n return rawToConvertedEIPTx1559s(rawTxs);\n }\n\n function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".transactions[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));\n return rawToConvertedEIPTx1559(rawTx);\n }\n\n // Analogous to readTransactions, but for receipts.\n function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".receipts\");\n RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));\n return rawToConvertedReceipts(rawReceipts);\n }\n\n function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".receipts[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));\n return rawToConvertedReceipt(rawReceipt);\n }\n\n function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {\n Receipt[] memory receipts = new Receipt[](rawReceipts.length);\n for (uint256 i; i < rawReceipts.length; i++) {\n receipts[i] = rawToConvertedReceipt(rawReceipts[i]);\n }\n return receipts;\n }\n\n function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {\n Receipt memory receipt;\n receipt.blockHash = rawReceipt.blockHash;\n receipt.to = rawReceipt.to;\n receipt.from = rawReceipt.from;\n receipt.contractAddress = rawReceipt.contractAddress;\n receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);\n receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);\n receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);\n receipt.status = _bytesToUint(rawReceipt.status);\n receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);\n receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);\n receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);\n receipt.logsBloom = rawReceipt.logsBloom;\n receipt.transactionHash = rawReceipt.transactionHash;\n return receipt;\n }\n\n function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)\n internal\n pure\n virtual\n returns (ReceiptLog[] memory)\n {\n ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);\n for (uint256 i; i < rawLogs.length; i++) {\n logs[i].logAddress = rawLogs[i].logAddress;\n logs[i].blockHash = rawLogs[i].blockHash;\n logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);\n logs[i].data = rawLogs[i].data;\n logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);\n logs[i].topics = rawLogs[i].topics;\n logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);\n logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);\n logs[i].removed = rawLogs[i].removed;\n }\n return logs;\n }\n\n // Deploy a contract by fetching the contract bytecode from\n // the artifacts directory\n // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`\n function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes): Deployment failed.\");\n }\n\n function deployCode(string memory what) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string): Deployment failed.\");\n }\n\n /// @dev deploy contract with value on construction\n function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes,uint256): Deployment failed.\");\n }\n\n function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,uint256): Deployment failed.\");\n }\n\n // creates a labeled address and the corresponding private key\n function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {\n privateKey = uint256(keccak256(abi.encodePacked(name)));\n addr = vm.addr(privateKey);\n vm.label(addr, name);\n }\n\n // creates a labeled address\n function makeAddr(string memory name) internal virtual returns (address addr) {\n (addr,) = makeAddrAndKey(name);\n }\n\n function deriveRememberKey(string memory mnemonic, uint32 index)\n internal\n virtual\n returns (address who, uint256 privateKey)\n {\n privateKey = vm.deriveKey(mnemonic, index);\n who = vm.rememberKey(privateKey);\n }\n\n function _bytesToUint(bytes memory b) private pure returns (uint256) {\n require(b.length <= 32, \"StdCheats _bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n function isFork() internal view virtual returns (bool status) {\n try vm.activeFork() {\n status = true;\n } catch (bytes memory) {}\n }\n\n modifier skipWhenForking() {\n if (!isFork()) {\n _;\n }\n }\n\n modifier skipWhenNotForking() {\n if (isFork()) {\n _;\n }\n }\n\n modifier noGasMetering() {\n vm.pauseGasMetering();\n // To prevent turning gas monitoring back on with nested functions that use this modifier,\n // we check if gasMetering started in the off position. If it did, we don't want to turn\n // it back on until we exit the top level function that used the modifier\n //\n // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.\n // funcA will have `gasStartedOff` as false, funcB will have it as true,\n // so we only turn metering back on at the end of the funcA\n bool gasStartedOff = gasMeteringOff;\n gasMeteringOff = true;\n\n _;\n\n // if gas metering was on when this modifier was called, turn it back on at the end\n if (!gasStartedOff) {\n gasMeteringOff = false;\n vm.resumeGasMetering();\n }\n }\n\n // a cheat for fuzzing addresses that are payable only\n // see https://github.com/foundry-rs/foundry/issues/3631\n function assumePayable(address addr) internal virtual {\n (bool success,) = payable(addr).call{value: 0}(\"\");\n vm.assume(success);\n }\n}\n\n// Wrappers around cheatcodes to avoid footguns\nabstract contract StdCheats is StdCheatsSafe {\n using stdStorage for StdStorage;\n\n StdStorage private stdstore;\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n // Skip forward or rewind time by the specified number of seconds\n function skip(uint256 time) internal virtual {\n vm.warp(block.timestamp + time);\n }\n\n function rewind(uint256 time) internal virtual {\n vm.warp(block.timestamp - time);\n }\n\n // Setup a prank from an address that has some ether\n function hoax(address msgSender) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.prank(msgSender);\n }\n\n function hoax(address msgSender, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.prank(msgSender);\n }\n\n function hoax(address msgSender, address origin) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.prank(msgSender, origin);\n }\n\n function hoax(address msgSender, address origin, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.prank(msgSender, origin);\n }\n\n // Start perpetual prank from an address that has some ether\n function startHoax(address msgSender) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.startPrank(msgSender);\n }\n\n function startHoax(address msgSender, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.startPrank(msgSender);\n }\n\n // Start perpetual prank from an address that has some ether\n // tx.origin is set to the origin parameter\n function startHoax(address msgSender, address origin) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.startPrank(msgSender, origin);\n }\n\n function startHoax(address msgSender, address origin, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.startPrank(msgSender, origin);\n }\n\n function changePrank(address msgSender) internal virtual {\n vm.stopPrank();\n vm.startPrank(msgSender);\n }\n\n function changePrank(address msgSender, address txOrigin) internal virtual {\n vm.stopPrank();\n vm.startPrank(msgSender, txOrigin);\n }\n\n // The same as Vm's `deal`\n // Use the alternative signature for ERC20 tokens\n function deal(address to, uint256 give) internal virtual {\n vm.deal(to, give);\n }\n\n // Set the balance of an account for any ERC20 token\n // Use the alternative signature to update `totalSupply`\n function deal(address token, address to, uint256 give) internal virtual {\n deal(token, to, give, false);\n }\n\n // Set the balance of an account for any ERC1155 token\n // Use the alternative signature to update `totalSupply`\n function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {\n dealERC1155(token, to, id, give, false);\n }\n\n function deal(address token, address to, uint256 give, bool adjust) internal virtual {\n // get current balance\n (, bytes memory balData) = token.call(abi.encodeWithSelector(0x70a08231, to));\n uint256 prevBal = abi.decode(balData, (uint256));\n\n // update balance\n stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);\n\n // update total supply\n if (adjust) {\n (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0x18160ddd));\n uint256 totSup = abi.decode(totSupData, (uint256));\n if (give < prevBal) {\n totSup -= (prevBal - give);\n } else {\n totSup += (give - prevBal);\n }\n stdstore.target(token).sig(0x18160ddd).checked_write(totSup);\n }\n }\n\n function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {\n // get current balance\n (, bytes memory balData) = token.call(abi.encodeWithSelector(0x00fdd58e, to, id));\n uint256 prevBal = abi.decode(balData, (uint256));\n\n // update balance\n stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);\n\n // update total supply\n if (adjust) {\n (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0xbd85b039, id));\n require(\n totSupData.length != 0,\n \"StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply.\"\n );\n uint256 totSup = abi.decode(totSupData, (uint256));\n if (give < prevBal) {\n totSup -= (prevBal - give);\n } else {\n totSup += (give - prevBal);\n }\n stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);\n }\n }\n\n function dealERC721(address token, address to, uint256 id) internal virtual {\n // check if token id is already minted and the actual owner.\n (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));\n require(successMinted, \"StdCheats deal(address,address,uint,bool): id not minted.\");\n\n // get owner current balance\n (, bytes memory fromBalData) = token.call(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));\n uint256 fromPrevBal = abi.decode(fromBalData, (uint256));\n\n // get new user current balance\n (, bytes memory toBalData) = token.call(abi.encodeWithSelector(0x70a08231, to));\n uint256 toPrevBal = abi.decode(toBalData, (uint256));\n\n // update balances\n stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);\n stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);\n\n // update owner\n stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);\n }\n}\n" - }, - "node_modules/forge-std/src/StdError.sol": { - "content": "// SPDX-License-Identifier: MIT\n// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdError {\n bytes public constant assertionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x01);\n bytes public constant arithmeticError = abi.encodeWithSignature(\"Panic(uint256)\", 0x11);\n bytes public constant divisionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x12);\n bytes public constant enumConversionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x21);\n bytes public constant encodeStorageError = abi.encodeWithSignature(\"Panic(uint256)\", 0x22);\n bytes public constant popError = abi.encodeWithSignature(\"Panic(uint256)\", 0x31);\n bytes public constant indexOOBError = abi.encodeWithSignature(\"Panic(uint256)\", 0x32);\n bytes public constant memOverflowError = abi.encodeWithSignature(\"Panic(uint256)\", 0x41);\n bytes public constant zeroVarError = abi.encodeWithSignature(\"Panic(uint256)\", 0x51);\n}\n" - }, - "node_modules/forge-std/src/StdInvariant.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\ncontract StdInvariant {\n struct FuzzSelector {\n address addr;\n bytes4[] selectors;\n }\n\n address[] private _excludedContracts;\n address[] private _excludedSenders;\n address[] private _targetedContracts;\n address[] private _targetedSenders;\n\n string[] private _excludedArtifacts;\n string[] private _targetedArtifacts;\n\n FuzzSelector[] private _targetedArtifactSelectors;\n FuzzSelector[] private _targetedSelectors;\n\n // Functions for users:\n // These are intended to be called in tests.\n\n function excludeContract(address newExcludedContract_) internal {\n _excludedContracts.push(newExcludedContract_);\n }\n\n function excludeSender(address newExcludedSender_) internal {\n _excludedSenders.push(newExcludedSender_);\n }\n\n function excludeArtifact(string memory newExcludedArtifact_) internal {\n _excludedArtifacts.push(newExcludedArtifact_);\n }\n\n function targetArtifact(string memory newTargetedArtifact_) internal {\n _targetedArtifacts.push(newTargetedArtifact_);\n }\n\n function targetArtifactSelector(FuzzSelector memory newTargetedArtifactSelector_) internal {\n _targetedArtifactSelectors.push(newTargetedArtifactSelector_);\n }\n\n function targetContract(address newTargetedContract_) internal {\n _targetedContracts.push(newTargetedContract_);\n }\n\n function targetSelector(FuzzSelector memory newTargetedSelector_) internal {\n _targetedSelectors.push(newTargetedSelector_);\n }\n\n function targetSender(address newTargetedSender_) internal {\n _targetedSenders.push(newTargetedSender_);\n }\n\n // Functions for forge:\n // These are called by forge to run invariant tests and don't need to be called in tests.\n\n function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) {\n excludedArtifacts_ = _excludedArtifacts;\n }\n\n function excludeContracts() public view returns (address[] memory excludedContracts_) {\n excludedContracts_ = _excludedContracts;\n }\n\n function excludeSenders() public view returns (address[] memory excludedSenders_) {\n excludedSenders_ = _excludedSenders;\n }\n\n function targetArtifacts() public view returns (string[] memory targetedArtifacts_) {\n targetedArtifacts_ = _targetedArtifacts;\n }\n\n function targetArtifactSelectors() public view returns (FuzzSelector[] memory targetedArtifactSelectors_) {\n targetedArtifactSelectors_ = _targetedArtifactSelectors;\n }\n\n function targetContracts() public view returns (address[] memory targetedContracts_) {\n targetedContracts_ = _targetedContracts;\n }\n\n function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) {\n targetedSelectors_ = _targetedSelectors;\n }\n\n function targetSenders() public view returns (address[] memory targetedSenders_) {\n targetedSenders_ = _targetedSenders;\n }\n}\n" - }, - "node_modules/forge-std/src/StdJson.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n// Helpers for parsing and writing JSON files\n// To parse:\n// ```\n// using stdJson for string;\n// string memory json = vm.readFile(\"some_peth\");\n// json.parseUint(\"\");\n// ```\n// To write:\n// ```\n// using stdJson for string;\n// string memory json = \"deploymentArtifact\";\n// Contract contract = new Contract();\n// json.serialize(\"contractAddress\", address(contract));\n// json = json.serialize(\"deploymentTimes\", uint(1));\n// // store the stringified JSON to the 'json' variable we have been using as a key\n// // as we won't need it any longer\n// string memory json2 = \"finalArtifact\";\n// string memory final = json2.serialize(\"depArtifact\", json);\n// final.write(\"\");\n// ```\n\nlibrary stdJson {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {\n return vm.parseJson(json, key);\n }\n\n function readUint(string memory json, string memory key) internal returns (uint256) {\n return vm.parseJsonUint(json, key);\n }\n\n function readUintArray(string memory json, string memory key) internal returns (uint256[] memory) {\n return vm.parseJsonUintArray(json, key);\n }\n\n function readInt(string memory json, string memory key) internal returns (int256) {\n return vm.parseJsonInt(json, key);\n }\n\n function readIntArray(string memory json, string memory key) internal returns (int256[] memory) {\n return vm.parseJsonIntArray(json, key);\n }\n\n function readBytes32(string memory json, string memory key) internal returns (bytes32) {\n return vm.parseJsonBytes32(json, key);\n }\n\n function readBytes32Array(string memory json, string memory key) internal returns (bytes32[] memory) {\n return vm.parseJsonBytes32Array(json, key);\n }\n\n function readString(string memory json, string memory key) internal returns (string memory) {\n return vm.parseJsonString(json, key);\n }\n\n function readStringArray(string memory json, string memory key) internal returns (string[] memory) {\n return vm.parseJsonStringArray(json, key);\n }\n\n function readAddress(string memory json, string memory key) internal returns (address) {\n return vm.parseJsonAddress(json, key);\n }\n\n function readAddressArray(string memory json, string memory key) internal returns (address[] memory) {\n return vm.parseJsonAddressArray(json, key);\n }\n\n function readBool(string memory json, string memory key) internal returns (bool) {\n return vm.parseJsonBool(json, key);\n }\n\n function readBoolArray(string memory json, string memory key) internal returns (bool[] memory) {\n return vm.parseJsonBoolArray(json, key);\n }\n\n function readBytes(string memory json, string memory key) internal returns (bytes memory) {\n return vm.parseJsonBytes(json, key);\n }\n\n function readBytesArray(string memory json, string memory key) internal returns (bytes[] memory) {\n return vm.parseJsonBytesArray(json, key);\n }\n\n function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bool[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function write(string memory jsonKey, string memory path) internal {\n vm.writeJson(jsonKey, path);\n }\n\n function write(string memory jsonKey, string memory path, string memory valueKey) internal {\n vm.writeJson(jsonKey, path, valueKey);\n }\n}\n" - }, - "node_modules/forge-std/src/StdMath.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdMath {\n int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;\n\n function abs(int256 a) internal pure returns (uint256) {\n // Required or it will fail when `a = type(int256).min`\n if (a == INT256_MIN) {\n return 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n }\n\n return uint256(a > 0 ? a : -a);\n }\n\n function delta(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a - b : b - a;\n }\n\n function delta(int256 a, int256 b) internal pure returns (uint256) {\n // a and b are of the same sign\n // this works thanks to two's complement, the left-most bit is the sign bit\n if ((a ^ b) > -1) {\n return delta(abs(a), abs(b));\n }\n\n // a and b are of opposite signs\n return abs(a) + abs(b);\n }\n\n function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n\n return absDelta * 1e18 / b;\n }\n\n function percentDelta(int256 a, int256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n uint256 absB = abs(b);\n\n return absDelta * 1e18 / absB;\n }\n}\n" - }, - "node_modules/forge-std/src/StdStorage.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {Vm} from \"./Vm.sol\";\n\nstruct StdStorage {\n mapping(address => mapping(bytes4 => mapping(bytes32 => uint256))) slots;\n mapping(address => mapping(bytes4 => mapping(bytes32 => bool))) finds;\n bytes32[] _keys;\n bytes4 _sig;\n uint256 _depth;\n address _target;\n bytes32 _set;\n}\n\nlibrary stdStorageSafe {\n event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);\n event WARNING_UninitedSlot(address who, uint256 slot);\n\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return bytes4(keccak256(bytes(sigStr)));\n }\n\n /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against\n // slot complexity:\n // if flat, will be bytes32(uint256(uint));\n // if map, will be keccak256(abi.encode(key, uint(slot)));\n // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));\n // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);\n function find(StdStorage storage self) internal returns (uint256) {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n // calldata to test against\n if (self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n vm.record();\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n (bytes32[] memory reads,) = vm.accesses(address(who));\n if (reads.length == 1) {\n bytes32 curr = vm.load(who, reads[0]);\n if (curr == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[0]));\n }\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[0]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[0]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n } else if (reads.length > 1) {\n for (uint256 i = 0; i < reads.length; i++) {\n bytes32 prev = vm.load(who, reads[i]);\n if (prev == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[i]));\n }\n // store\n vm.store(who, reads[i], bytes32(hex\"1337\"));\n bool success;\n bytes memory rdat;\n {\n (success, rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n if (success && fdat == bytes32(hex\"1337\")) {\n // we found which of the slots is the actual one\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[i]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[i]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n vm.store(who, reads[i], prev);\n break;\n }\n vm.store(who, reads[i], prev);\n }\n } else {\n revert(\"stdStorage find(StdStorage): No storage use detected for target.\");\n }\n\n require(\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))],\n \"stdStorage find(StdStorage): Slot(s) not found.\"\n );\n\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n self._target = _target;\n return self;\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n self._sig = _sig;\n return self;\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n self._sig = sigs(_sig);\n return self;\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n self._keys.push(bytes32(uint256(uint160(who))));\n return self;\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n self._keys.push(bytes32(amt));\n return self;\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n self._keys.push(key);\n return self;\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n self._depth = _depth;\n return self;\n }\n\n function read(StdStorage storage self) private returns (bytes memory) {\n address t = self._target;\n uint256 s = find(self);\n return abi.encode(vm.load(t, bytes32(s)));\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return abi.decode(read(self), (bytes32));\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n int256 v = read_int(self);\n if (v == 0) return false;\n if (v == 1) return true;\n revert(\"stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.\");\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return abi.decode(read(self), (address));\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return abi.decode(read(self), (uint256));\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return abi.decode(read(self), (int256));\n }\n\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n\nlibrary stdStorage {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return stdStorageSafe.sigs(sigStr);\n }\n\n function find(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.find(self);\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n return stdStorageSafe.target(self, _target);\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, who);\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, amt);\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, key);\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n return stdStorageSafe.depth(self, _depth);\n }\n\n function checked_write(StdStorage storage self, address who) internal {\n checked_write(self, bytes32(uint256(uint160(who))));\n }\n\n function checked_write(StdStorage storage self, uint256 amt) internal {\n checked_write(self, bytes32(amt));\n }\n\n function checked_write(StdStorage storage self, bool write) internal {\n bytes32 t;\n /// @solidity memory-safe-assembly\n assembly {\n t := write\n }\n checked_write(self, t);\n }\n\n function checked_write(StdStorage storage self, bytes32 set) internal {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n if (!self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n find(self);\n }\n bytes32 slot = bytes32(self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]);\n\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n bytes32 curr = vm.load(who, slot);\n\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n vm.store(who, slot, set);\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return stdStorageSafe.read_bytes32(self);\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n return stdStorageSafe.read_bool(self);\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return stdStorageSafe.read_address(self);\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.read_uint(self);\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return stdStorageSafe.read_int(self);\n }\n\n // Private function so needs to be copied over\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n // Private function so needs to be copied over\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n" - }, - "node_modules/forge-std/src/StdStyle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nimport {Vm} from \"./Vm.sol\";\n\nlibrary StdStyle {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n string constant RED = \"\\u001b[91m\";\n string constant GREEN = \"\\u001b[92m\";\n string constant YELLOW = \"\\u001b[93m\";\n string constant BLUE = \"\\u001b[94m\";\n string constant MAGENTA = \"\\u001b[95m\";\n string constant CYAN = \"\\u001b[96m\";\n string constant BOLD = \"\\u001b[1m\";\n string constant DIM = \"\\u001b[2m\";\n string constant ITALIC = \"\\u001b[3m\";\n string constant UNDERLINE = \"\\u001b[4m\";\n string constant INVERSE = \"\\u001b[7m\";\n string constant RESET = \"\\u001b[0m\";\n\n function styleConcat(string memory style, string memory self) private pure returns (string memory) {\n return string(abi.encodePacked(style, self, RESET));\n }\n\n function red(string memory self) internal pure returns (string memory) {\n return styleConcat(RED, self);\n }\n\n function red(uint256 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(int256 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(address self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(bool self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function redBytes(bytes memory self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function redBytes32(bytes32 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function green(string memory self) internal pure returns (string memory) {\n return styleConcat(GREEN, self);\n }\n\n function green(uint256 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(int256 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(address self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(bool self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function greenBytes(bytes memory self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function greenBytes32(bytes32 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function yellow(string memory self) internal pure returns (string memory) {\n return styleConcat(YELLOW, self);\n }\n\n function yellow(uint256 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(int256 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(address self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(bool self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellowBytes(bytes memory self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellowBytes32(bytes32 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function blue(string memory self) internal pure returns (string memory) {\n return styleConcat(BLUE, self);\n }\n\n function blue(uint256 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(int256 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(address self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(bool self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blueBytes(bytes memory self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blueBytes32(bytes32 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function magenta(string memory self) internal pure returns (string memory) {\n return styleConcat(MAGENTA, self);\n }\n\n function magenta(uint256 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(int256 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(address self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(bool self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magentaBytes(bytes memory self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magentaBytes32(bytes32 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function cyan(string memory self) internal pure returns (string memory) {\n return styleConcat(CYAN, self);\n }\n\n function cyan(uint256 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(int256 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(address self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(bool self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyanBytes(bytes memory self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyanBytes32(bytes32 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function bold(string memory self) internal pure returns (string memory) {\n return styleConcat(BOLD, self);\n }\n\n function bold(uint256 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(int256 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(address self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(bool self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function boldBytes(bytes memory self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function boldBytes32(bytes32 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function dim(string memory self) internal pure returns (string memory) {\n return styleConcat(DIM, self);\n }\n\n function dim(uint256 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(int256 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(address self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(bool self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dimBytes(bytes memory self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dimBytes32(bytes32 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function italic(string memory self) internal pure returns (string memory) {\n return styleConcat(ITALIC, self);\n }\n\n function italic(uint256 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(int256 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(address self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(bool self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italicBytes(bytes memory self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italicBytes32(bytes32 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function underline(string memory self) internal pure returns (string memory) {\n return styleConcat(UNDERLINE, self);\n }\n\n function underline(uint256 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(int256 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(address self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(bool self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underlineBytes(bytes memory self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underlineBytes32(bytes32 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function inverse(string memory self) internal pure returns (string memory) {\n return styleConcat(INVERSE, self);\n }\n\n function inverse(uint256 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(int256 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(address self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(bool self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverseBytes(bytes memory self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverseBytes32(bytes32 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n}\n" - }, - "node_modules/forge-std/src/StdUtils.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {IMulticall3} from \"./interfaces/IMulticall3.sol\";\n// TODO Remove import.\nimport {VmSafe} from \"./Vm.sol\";\n\nabstract contract StdUtils {\n /*//////////////////////////////////////////////////////////////////////////\n CONSTANTS\n //////////////////////////////////////////////////////////////////////////*/\n\n IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;\n uint256 private constant INT256_MIN_ABS =\n 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n uint256 private constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.\n address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;\n\n /*//////////////////////////////////////////////////////////////////////////\n INTERNAL FUNCTIONS\n //////////////////////////////////////////////////////////////////////////*/\n\n function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {\n require(min <= max, \"StdUtils bound(uint256,uint256,uint256): Max is less than min.\");\n // If x is between min and max, return x directly. This is to ensure that dictionary values\n // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188\n if (x >= min && x <= max) return x;\n\n uint256 size = max - min + 1;\n\n // If the value is 0, 1, 2, 3, warp that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.\n // This helps ensure coverage of the min/max values.\n if (x <= 3 && size > x) return min + x;\n if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);\n\n // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.\n if (x > max) {\n uint256 diff = x - max;\n uint256 rem = diff % size;\n if (rem == 0) return max;\n result = min + rem - 1;\n } else if (x < min) {\n uint256 diff = min - x;\n uint256 rem = diff % size;\n if (rem == 0) return min;\n result = max - rem + 1;\n }\n }\n\n function bound(uint256 x, uint256 min, uint256 max) internal view virtual returns (uint256 result) {\n result = _bound(x, min, max);\n console2_log(\"Bound Result\", result);\n }\n\n function bound(int256 x, int256 min, int256 max) internal view virtual returns (int256 result) {\n require(min <= max, \"StdUtils bound(int256,int256,int256): Max is less than min.\");\n\n // Shifting all int256 values to uint256 to use _bound function. The range of two types are:\n // int256 : -(2**255) ~ (2**255 - 1)\n // uint256: 0 ~ (2**256 - 1)\n // So, add 2**255, INT256_MIN_ABS to the integer values.\n //\n // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.\n // So, use `~uint256(x) + 1` instead.\n uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);\n uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);\n uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);\n\n uint256 y = _bound(_x, _min, _max);\n\n // To move it back to int256 value, subtract INT256_MIN_ABS at here.\n result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);\n console2_log(\"Bound result\", vm.toString(result));\n }\n\n function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {\n require(b.length <= 32, \"StdUtils bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce\n /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)\n function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {\n // forgefmt: disable-start\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))));\n if (nonce <= 0x7f) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))));\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= 2**8 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce))));\n if (nonce <= 2**16 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce))));\n if (nonce <= 2**24 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce))));\n // forgefmt: disable-end\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return addressFromLast20Bytes(\n keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce)))\n );\n }\n\n function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)\n internal\n pure\n virtual\n returns (address)\n {\n return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, initcodeHash)));\n }\n\n /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer\n function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {\n return computeCreate2Address(salt, initCodeHash, CREATE2_FACTORY);\n }\n\n /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments\n /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode\n function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {\n return hashInitCode(creationCode, \"\");\n }\n\n /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2\n /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode\n /// @param args the ABI-encoded arguments to the constructor of C\n function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(creationCode, args));\n }\n\n // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.\n function getTokenBalances(address token, address[] memory addresses)\n internal\n virtual\n returns (uint256[] memory balances)\n {\n uint256 tokenCodeSize;\n assembly {\n tokenCodeSize := extcodesize(token)\n }\n require(tokenCodeSize > 0, \"StdUtils getTokenBalances(address,address[]): Token address is not a contract.\");\n\n // ABI encode the aggregate call to Multicall3.\n uint256 length = addresses.length;\n IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);\n for (uint256 i = 0; i < length; ++i) {\n // 0x70a08231 = bytes4(\"balanceOf(address)\"))\n calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});\n }\n\n // Make the aggregate call.\n (, bytes[] memory returnData) = multicall.aggregate(calls);\n\n // ABI decode the return data and return the balances.\n balances = new uint256[](length);\n for (uint256 i = 0; i < length; ++i) {\n balances[i] = abi.decode(returnData[i], (uint256));\n }\n }\n\n /*//////////////////////////////////////////////////////////////////////////\n PRIVATE FUNCTIONS\n //////////////////////////////////////////////////////////////////////////*/\n\n function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.\n\n function console2_log(string memory p0, uint256 p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n status;\n }\n\n function console2_log(string memory p0, string memory p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n status;\n }\n}\n" - }, - "node_modules/forge-std/src/Test.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\n// 💬 ABOUT\n// Standard Library's default Test\n\n// 🧩 MODULES\nimport {console} from \"./console.sol\";\nimport {console2} from \"./console2.sol\";\nimport {StdAssertions} from \"./StdAssertions.sol\";\nimport {StdChains} from \"./StdChains.sol\";\nimport {StdCheats} from \"./StdCheats.sol\";\nimport {stdError} from \"./StdError.sol\";\nimport {StdInvariant} from \"./StdInvariant.sol\";\nimport {stdJson} from \"./StdJson.sol\";\nimport {stdMath} from \"./StdMath.sol\";\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {StdUtils} from \"./StdUtils.sol\";\nimport {Vm} from \"./Vm.sol\";\nimport {StdStyle} from \"./StdStyle.sol\";\n\n// 📦 BOILERPLATE\nimport {TestBase} from \"./Base.sol\";\nimport {DSTest} from \"ds-test/test.sol\";\n\n// ⭐️ TEST\nabstract contract Test is DSTest, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils, TestBase {\n// Note: IS_TEST() must return true.\n// Note: Must have failure system, https://github.com/dapphub/ds-test/blob/cd98eff28324bfac652e63a239a60632a761790b/src/test.sol#L39-L76.\n}\n" - }, - "node_modules/forge-std/src/Vm.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\n// Cheatcodes are marked as view/pure/none using the following rules:\n// 0. A call's observable behaviour includes its return value, logs, reverts and state writes,\n// 1. If you can influence a later call's observable behaviour, you're neither `view` nor `pure (you are modifying some state be it the EVM, interpreter, filesystem, etc),\n// 2. Otherwise if you can be influenced by an earlier call, or if reading some state, you're `view`,\n// 3. Otherwise you're `pure`.\n\ninterface VmSafe {\n struct Log {\n bytes32[] topics;\n bytes data;\n address emitter;\n }\n\n struct Rpc {\n string key;\n string url;\n }\n\n struct FsMetadata {\n bool isDir;\n bool isSymlink;\n uint256 length;\n bool readOnly;\n uint256 modified;\n uint256 accessed;\n uint256 created;\n }\n\n // Loads a storage slot from an address\n function load(address target, bytes32 slot) external view returns (bytes32 data);\n // Signs data\n function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);\n // Gets the address for a given private key\n function addr(uint256 privateKey) external pure returns (address keyAddr);\n // Gets the nonce of an account\n function getNonce(address account) external view returns (uint64 nonce);\n // Performs a foreign function call via the terminal\n function ffi(string[] calldata commandInput) external returns (bytes memory result);\n // Sets environment variables\n function setEnv(string calldata name, string calldata value) external;\n // Reads environment variables, (name) => (value)\n function envBool(string calldata name) external view returns (bool value);\n function envUint(string calldata name) external view returns (uint256 value);\n function envInt(string calldata name) external view returns (int256 value);\n function envAddress(string calldata name) external view returns (address value);\n function envBytes32(string calldata name) external view returns (bytes32 value);\n function envString(string calldata name) external view returns (string memory value);\n function envBytes(string calldata name) external view returns (bytes memory value);\n // Reads environment variables as arrays\n function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);\n function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);\n function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);\n function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);\n function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);\n function envString(string calldata name, string calldata delim) external view returns (string[] memory value);\n function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);\n // Read environment variables with default value\n function envOr(string calldata name, bool defaultValue) external returns (bool value);\n function envOr(string calldata name, uint256 defaultValue) external returns (uint256 value);\n function envOr(string calldata name, int256 defaultValue) external returns (int256 value);\n function envOr(string calldata name, address defaultValue) external returns (address value);\n function envOr(string calldata name, bytes32 defaultValue) external returns (bytes32 value);\n function envOr(string calldata name, string calldata defaultValue) external returns (string memory value);\n function envOr(string calldata name, bytes calldata defaultValue) external returns (bytes memory value);\n // Read environment variables as arrays with default value\n function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)\n external\n returns (bool[] memory value);\n function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)\n external\n returns (uint256[] memory value);\n function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)\n external\n returns (int256[] memory value);\n function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)\n external\n returns (address[] memory value);\n function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)\n external\n returns (bytes32[] memory value);\n function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)\n external\n returns (string[] memory value);\n function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)\n external\n returns (bytes[] memory value);\n // Records all storage reads and writes\n function record() external;\n // Gets all accessed reads and write slot from a recording session, for a given address\n function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);\n // Gets the _creation_ bytecode from an artifact file. Takes in the relative path to the json file\n function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);\n // Gets the _deployed_ bytecode from an artifact file. Takes in the relative path to the json file\n function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);\n // Labels an address in call traces\n function label(address account, string calldata newLabel) external;\n // Using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain\n function broadcast() external;\n // Has the next call (at this call depth only) create a transaction with the address provided as the sender that can later be signed and sent onchain\n function broadcast(address signer) external;\n // Has the next call (at this call depth only) create a transaction with the private key provided as the sender that can later be signed and sent onchain\n function broadcast(uint256 privateKey) external;\n // Using the address that calls the test contract, has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain\n function startBroadcast() external;\n // Has all subsequent calls (at this call depth only) create transactions with the address provided that can later be signed and sent onchain\n function startBroadcast(address signer) external;\n // Has all subsequent calls (at this call depth only) create transactions with the private key provided that can later be signed and sent onchain\n function startBroadcast(uint256 privateKey) external;\n // Stops collecting onchain transactions\n function stopBroadcast() external;\n // Reads the entire content of file to string\n function readFile(string calldata path) external view returns (string memory data);\n // Reads the entire content of file as binary. Path is relative to the project root.\n function readFileBinary(string calldata path) external view returns (bytes memory data);\n // Get the path of the current project root\n function projectRoot() external view returns (string memory path);\n // Get the metadata for a file/directory\n function fsMetadata(string calldata fileOrDir) external returns (FsMetadata memory metadata);\n // Reads next line of file to string\n function readLine(string calldata path) external view returns (string memory line);\n // Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.\n function writeFile(string calldata path, string calldata data) external;\n // Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.\n // Path is relative to the project root.\n function writeFileBinary(string calldata path, bytes calldata data) external;\n // Writes line to file, creating a file if it does not exist.\n function writeLine(string calldata path, string calldata data) external;\n // Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.\n function closeFile(string calldata path) external;\n // Removes file. This cheatcode will revert in the following situations, but is not limited to just these cases:\n // - Path points to a directory.\n // - The file doesn't exist.\n // - The user lacks permissions to remove the file.\n function removeFile(string calldata path) external;\n // Convert values to a string\n function toString(address value) external pure returns (string memory stringifiedValue);\n function toString(bytes calldata value) external pure returns (string memory stringifiedValue);\n function toString(bytes32 value) external pure returns (string memory stringifiedValue);\n function toString(bool value) external pure returns (string memory stringifiedValue);\n function toString(uint256 value) external pure returns (string memory stringifiedValue);\n function toString(int256 value) external pure returns (string memory stringifiedValue);\n // Convert values from a string\n function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);\n function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);\n function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);\n function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);\n function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);\n function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);\n // Record all the transaction logs\n function recordLogs() external;\n // Gets all the recorded logs\n function getRecordedLogs() external returns (Log[] memory logs);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path m/44'/60'/0'/0/{index}\n function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at {derivationPath}{index}\n function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)\n external\n pure\n returns (uint256 privateKey);\n // Adds a private key to the local forge wallet and returns the address\n function rememberKey(uint256 privateKey) external returns (address keyAddr);\n //\n // parseJson\n //\n // ----\n // In case the returned value is a JSON object, it's encoded as a ABI-encoded tuple. As JSON objects\n // don't have the notion of ordered, but tuples do, they JSON object is encoded with it's fields ordered in\n // ALPHABETICAL order. That means that in order to successfully decode the tuple, we need to define a tuple that\n // encodes the fields in the same order, which is alphabetical. In the case of Solidity structs, they are encoded\n // as tuples, with the attributes in the order in which they are defined.\n // For example: json = { 'a': 1, 'b': 0xa4tb......3xs}\n // a: uint256\n // b: address\n // To decode that json, we need to define a struct or a tuple as follows:\n // struct json = { uint256 a; address b; }\n // If we defined a json struct with the opposite order, meaning placing the address b first, it would try to\n // decode the tuple in that order, and thus fail.\n // ----\n // Given a string of JSON, return it as ABI-encoded\n function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);\n function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);\n\n // The following parseJson cheatcodes will do type coercion, for the type that they indicate.\n // For example, parseJsonUint will coerce all values to a uint256. That includes stringified numbers '12'\n // and hex numbers '0xEF'.\n // Type coercion works ONLY for discrete values or arrays. That means that the key must return a value or array, not\n // a JSON object.\n function parseJsonUint(string calldata, string calldata) external returns (uint256);\n function parseJsonUintArray(string calldata, string calldata) external returns (uint256[] memory);\n function parseJsonInt(string calldata, string calldata) external returns (int256);\n function parseJsonIntArray(string calldata, string calldata) external returns (int256[] memory);\n function parseJsonBool(string calldata, string calldata) external returns (bool);\n function parseJsonBoolArray(string calldata, string calldata) external returns (bool[] memory);\n function parseJsonAddress(string calldata, string calldata) external returns (address);\n function parseJsonAddressArray(string calldata, string calldata) external returns (address[] memory);\n function parseJsonString(string calldata, string calldata) external returns (string memory);\n function parseJsonStringArray(string calldata, string calldata) external returns (string[] memory);\n function parseJsonBytes(string calldata, string calldata) external returns (bytes memory);\n function parseJsonBytesArray(string calldata, string calldata) external returns (bytes[] memory);\n function parseJsonBytes32(string calldata, string calldata) external returns (bytes32);\n function parseJsonBytes32Array(string calldata, string calldata) external returns (bytes32[] memory);\n\n // Serialize a key and value to a JSON object stored in-memory that can be later written to a file\n // It returns the stringified version of the specific JSON file up to that moment.\n function serializeBool(string calldata objectKey, string calldata valueKey, bool value)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address value)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)\n external\n returns (string memory json);\n\n function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)\n external\n returns (string memory json);\n\n //\n // writeJson\n //\n // ----\n // Write a serialized JSON object to a file. If the file exists, it will be overwritten.\n // Let's assume we want to write the following JSON to a file:\n //\n // { \"boolean\": true, \"number\": 342, \"object\": { \"title\": \"finally json serialization\" } }\n //\n // ```\n // string memory json1 = \"some key\";\n // vm.serializeBool(json1, \"boolean\", true);\n // vm.serializeBool(json1, \"number\", uint256(342));\n // json2 = \"some other key\";\n // string memory output = vm.serializeString(json2, \"title\", \"finally json serialization\");\n // string memory finalJson = vm.serialize(json1, \"object\", output);\n // vm.writeJson(finalJson, \"./output/example.json\");\n // ```\n // The critical insight is that every invocation of serialization will return the stringified version of the JSON\n // up to that point. That means we can construct arbitrary JSON objects and then use the return stringified version\n // to serialize them as values to another JSON object.\n //\n // json1 and json2 are simply keys used by the backend to keep track of the objects. So vm.serializeJson(json1,..)\n // will find the object in-memory that is keyed by \"some key\".\n function writeJson(string calldata json, string calldata path) external;\n // Write a serialized JSON object to an **existing** JSON file, replacing a value with key = \n // This is useful to replace a specific value of a JSON file, without having to parse the entire thing\n function writeJson(string calldata json, string calldata path, string calldata valueKey) external;\n // Returns the RPC url for the given alias\n function rpcUrl(string calldata rpcAlias) external view returns (string memory json);\n // Returns all rpc urls and their aliases `[alias, url][]`\n function rpcUrls() external view returns (string[2][] memory urls);\n // Returns all rpc urls and their aliases as structs.\n function rpcUrlStructs() external view returns (Rpc[] memory urls);\n // If the condition is false, discard this run's fuzz inputs and generate new ones.\n function assume(bool condition) external pure;\n // Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.\n function pauseGasMetering() external;\n // Resumes gas metering (i.e. gas usage is counted again). Noop if already on.\n function resumeGasMetering() external;\n}\n\ninterface Vm is VmSafe {\n // Sets block.timestamp\n function warp(uint256 newTimestamp) external;\n // Sets block.height\n function roll(uint256 newHeight) external;\n // Sets block.basefee\n function fee(uint256 newBasefee) external;\n // Sets block.difficulty\n function difficulty(uint256 newDifficulty) external;\n // Sets block.chainid\n function chainId(uint256 newChainId) external;\n // Stores a value to an address' storage slot.\n function store(address target, bytes32 slot, bytes32 value) external;\n // Sets the nonce of an account; must be higher than the current nonce of the account\n function setNonce(address account, uint64 newNonce) external;\n // Sets the *next* call's msg.sender to be the input address\n function prank(address msgSender) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called\n function startPrank(address msgSender) external;\n // Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input\n function prank(address msgSender, address txOrigin) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input\n function startPrank(address msgSender, address txOrigin) external;\n // Resets subsequent calls' msg.sender to be `address(this)`\n function stopPrank() external;\n // Sets an address' balance\n function deal(address account, uint256 newBalance) external;\n // Sets an address' code\n function etch(address target, bytes calldata newRuntimeBytecode) external;\n // Expects an error on next call\n function expectRevert(bytes calldata revertData) external;\n function expectRevert(bytes4 revertData) external;\n function expectRevert() external;\n\n // Prepare an expected log with all four checks enabled.\n // Call this function, then emit an event, then call a function. Internally after the call, we check if\n // logs were emitted in the expected order with the expected topics and data.\n // Second form also checks supplied address against emitting contract.\n function expectEmit() external;\n function expectEmit(address emitter) external;\n\n // Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData).\n // Call this function, then emit an event, then call a function. Internally after the call, we check if\n // logs were emitted in the expected order with the expected topics and data (as specified by the booleans).\n // Second form also checks supplied address against emitting contract.\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)\n external;\n\n // Mocks a call to an address, returning specified data.\n // Calldata can either be strict or a partial match, e.g. if you only\n // pass a Solidity selector to the expected calldata, then the entire Solidity\n // function will be mocked.\n function mockCall(address callee, bytes calldata data, bytes calldata returnData) external;\n // Mocks a call to an address with a specific msg.value, returning specified data.\n // Calldata match takes precedence over msg.value in case of ambiguity.\n function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external;\n // Clears all mocked calls\n function clearMockedCalls() external;\n // Expects a call to an address with the specified calldata.\n // Calldata can either be a strict or a partial match\n function expectCall(address callee, bytes calldata data) external;\n // Expects a call to an address with the specified msg.value and calldata\n function expectCall(address callee, uint256 msgValue, bytes calldata data) external;\n // Expect a call to an address with the specified msg.value, gas, and calldata.\n function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external;\n // Expect a call to an address with the specified msg.value and calldata, and a *minimum* amount of gas.\n function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external;\n // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other\n // memory is written to, the test will fail. Can be called multiple times to add more ranges to the set.\n function expectSafeMemory(uint64 min, uint64 max) external;\n // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext.\n // If any other memory is written to, the test will fail. Can be called multiple times to add more ranges\n // to the set.\n function expectSafeMemoryCall(uint64 min, uint64 max) external;\n // Sets block.coinbase\n function coinbase(address newCoinbase) external;\n // Snapshot the current state of the evm.\n // Returns the id of the snapshot that was created.\n // To revert a snapshot use `revertTo`\n function snapshot() external returns (uint256 snapshotId);\n // Revert the state of the EVM to a previous snapshot\n // Takes the snapshot id to revert to.\n // This deletes the snapshot and all snapshots taken after the given snapshot id.\n function revertTo(uint256 snapshotId) external returns (bool success);\n // Creates a new fork with the given endpoint and block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before the transaction,\n // and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates _and_ also selects new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before\n // the transaction, returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.\n function selectFork(uint256 forkId) external;\n /// Returns the identifier of the currently active fork. Reverts if no fork is currently active.\n function activeFork() external view returns (uint256 forkId);\n // Updates the currently active fork to given block number\n // This is similar to `roll` but for the currently active fork\n function rollFork(uint256 blockNumber) external;\n // Updates the currently active fork to given transaction\n // this will `rollFork` with the number of the block the transaction was mined in and replays all transaction mined before it in the block\n function rollFork(bytes32 txHash) external;\n // Updates the given fork to given block number\n function rollFork(uint256 forkId, uint256 blockNumber) external;\n // Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block\n function rollFork(uint256 forkId, bytes32 txHash) external;\n // Marks that the account(s) should use persistent storage across fork swaps in a multifork setup\n // Meaning, changes made to the state of this account will be kept when switching forks\n function makePersistent(address account) external;\n function makePersistent(address account0, address account1) external;\n function makePersistent(address account0, address account1, address account2) external;\n function makePersistent(address[] calldata accounts) external;\n // Revokes persistent status from the address, previously added via `makePersistent`\n function revokePersistent(address account) external;\n function revokePersistent(address[] calldata accounts) external;\n // Returns true if the account is marked as persistent\n function isPersistent(address account) external view returns (bool persistent);\n // In forking mode, explicitly grant the given address cheatcode access\n function allowCheatcodes(address account) external;\n // Fetches the given transaction from the active fork and executes it on the current state\n function transact(bytes32 txHash) external;\n // Fetches the given transaction from the given fork and executes it on the current state\n function transact(uint256 forkId, bytes32 txHash) external;\n}\n" - }, - "node_modules/forge-std/src/console.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nlibrary console {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int)\", p0));\n }\n\n function logUint(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint)\", p0, p1));\n }\n\n function log(uint p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string)\", p0, p1));\n }\n\n function log(uint p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool)\", p0, p1));\n }\n\n function log(uint p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address)\", p0, p1));\n }\n\n function log(string memory p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - }, - "node_modules/forge-std/src/console2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\n/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should\n/// use `int256` and `uint256`. This modified version fixes that. This version is recommended\n/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in\n/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.\n/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178\nlibrary console2 {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function logUint(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function log(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint256 p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256)\", p0, p1));\n }\n\n function log(uint256 p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string)\", p0, p1));\n }\n\n function log(uint256 p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool)\", p0, p1));\n }\n\n function log(uint256 p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address)\", p0, p1));\n }\n\n function log(string memory p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n }\n\n function log(string memory p0, int256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,int256)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - }, - "node_modules/forge-std/src/interfaces/IMulticall3.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\ninterface IMulticall3 {\n struct Call {\n address target;\n bytes callData;\n }\n\n struct Call3 {\n address target;\n bool allowFailure;\n bytes callData;\n }\n\n struct Call3Value {\n address target;\n bool allowFailure;\n uint256 value;\n bytes callData;\n }\n\n struct Result {\n bool success;\n bytes returnData;\n }\n\n function aggregate(Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes[] memory returnData);\n\n function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData);\n\n function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData);\n\n function blockAndAggregate(Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);\n\n function getBasefee() external view returns (uint256 basefee);\n\n function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash);\n\n function getBlockNumber() external view returns (uint256 blockNumber);\n\n function getChainId() external view returns (uint256 chainid);\n\n function getCurrentBlockCoinbase() external view returns (address coinbase);\n\n function getCurrentBlockDifficulty() external view returns (uint256 difficulty);\n\n function getCurrentBlockGasLimit() external view returns (uint256 gaslimit);\n\n function getCurrentBlockTimestamp() external view returns (uint256 timestamp);\n\n function getEthBalance(address addr) external view returns (uint256 balance);\n\n function getLastBlockHash() external view returns (bytes32 blockHash);\n\n function tryAggregate(bool requireSuccess, Call[] calldata calls)\n external\n payable\n returns (Result[] memory returnData);\n\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);\n}\n" - } - }, - "settings": { - "remappings": [ - "@openzeppelin/=node_modules/@openzeppelin/", - "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", - "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", - "@rari-capital/=node_modules/@rari-capital/", - "@rari-capital/solmate/=node_modules/@rari-capital/solmate/", - "ds-test/=node_modules/ds-test/src/", - "forge-std/=node_modules/forge-std/src/" - ], - "optimizer": { - "enabled": true, - "runs": 999999 - }, - "metadata": { - "bytecodeHash": "none" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "storageLayout", - "devdoc", - "userdoc" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/solcInputs/4eff12bc9de58190fbafded200df8851.json b/packages/contracts-bedrock/deployments/optimism-goerli/solcInputs/4eff12bc9de58190fbafded200df8851.json deleted file mode 100644 index fd16bdebc2a1..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/solcInputs/4eff12bc9de58190fbafded200df8851.json +++ /dev/null @@ -1,554 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/L1/L1CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismPortal } from \"./OptimismPortal.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1CrossDomainMessenger\n * @notice The L1CrossDomainMessenger is a message passing interface between L1 and L2 responsible\n * for sending and receiving data on the L1 side. Users are encouraged to use this\n * interface instead of interacting with lower-level contracts directly.\n */\ncontract L1CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @notice Address of the OptimismPortal.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _portal Address of the OptimismPortal contract on this network.\n */\n constructor(OptimismPortal _portal)\n Semver(1, 1, 0)\n CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER)\n {\n PORTAL = _portal;\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n PORTAL.depositTransaction{ value: _value }(_to, _value, _gasLimit, false, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return msg.sender == address(PORTAL) && PORTAL.l2Sender() == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(PORTAL);\n }\n}\n" - }, - "contracts/L1/L1ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { IERC721 } from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport { L2ERC721Bridge } from \"../L2/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 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, 1, 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 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), \"L1ERC721Bridge: 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(OTHER_BRIDGE, message, _minGasLimit);\n emit ERC721BridgeInitiated(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L1/L1StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title L1StandardBridge\n * @notice The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L1, it will be escrowed within this\n * contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was\n * stored within this contract. After Bedrock, ETH is instead stored inside the\n * OptimismPortal contract.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L1StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a deposit of ETH from L1 into L2 is initiated.\n *\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of ETH deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ETHDepositInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal of ETH from L2 to L1 is finalized.\n *\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of ETH withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 withdrawal is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _messenger Address of the L1CrossDomainMessenger.\n */\n constructor(address payable _messenger)\n Semver(1, 1, 0)\n StandardBridge(_messenger, payable(Predeploys.L2_STANDARD_BRIDGE))\n {}\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n */\n receive() external payable override onlyEOA {\n _initiateETHDeposit(msg.sender, msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into the sender's account on L2.\n *\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETH(uint32 _minGasLimit, bytes calldata _extraData) external payable onlyEOA {\n _initiateETHDeposit(msg.sender, msg.sender, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ETH into a target account on L2.\n * Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will\n * be locked in the L2StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n *\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable {\n _initiateETHDeposit(msg.sender, _to, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into the sender's account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20(\n address _l1Token,\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual onlyEOA {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Deposits some amount of ERC20 tokens into a target account on L2.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\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 depositERC20To(\n address _l1Token,\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external virtual {\n _initiateERC20Deposit(\n _l1Token,\n _l2Token,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ETH from L2.\n *\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of ETH to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeETHWithdrawal(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable {\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a withdrawal of ERC20 tokens from L2.\n *\n * @param _l1Token Address of the token on L1.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the withdrawer on L2.\n * @param _to Address of the recipient on L1.\n * @param _amount Amount of the ERC20 to withdraw.\n * @param _extraData Optional data forwarded from L2.\n */\n function finalizeERC20Withdrawal(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external {\n finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L2 bridge contract.\n *\n * @return Address of the corresponding L2 bridge contract.\n */\n function l2TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @notice Internal function for initiating an ETH deposit.\n *\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateETHDeposit(\n address _from,\n address _to,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n _initiateBridgeETH(_from, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Internal function for initiating an ERC20 deposit.\n *\n * @param _l1Token Address of the L1 token being deposited.\n * @param _l2Token Address of the corresponding token on L2.\n * @param _from Address of the sender on L1.\n * @param _to Address of the recipient on L2.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _minGasLimit Minimum gas limit for the deposit message on L2.\n * @param _extraData Optional data to forward to L2.\n */\n function _initiateERC20Deposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n _initiateBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Emits the legacy ETHDepositInitiated event followed by the ETHBridgeInitiated event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ETHDepositInitiated(_from, _to, _amount, _extraData);\n super._emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ETHWithdrawalFinalized event followed by the ETHBridgeFinalized\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ETHWithdrawalFinalized(_from, _to, _amount, _extraData);\n super._emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ERC20DepositInitiated event followed by the ERC20BridgeInitiated\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ERC20DepositInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy ERC20WithdrawalFinalized event followed by the ERC20BridgeFinalized\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit ERC20WithdrawalFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/L1/L2OutputOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\n/**\n * @custom:proxied\n * @title L2OutputOracle\n * @notice The L2OutputOracle contains an array of L2 state outputs, where each output is a\n * commitment to the state of the L2 chain. Other contracts like the OptimismPortal use\n * these outputs to verify information about the state of L2.\n */\ncontract L2OutputOracle is Initializable, Semver {\n /**\n * @notice The interval in L2 blocks at which checkpoints must be submitted. Although this is\n * immutable, it can safely be modified by upgrading the implementation contract.\n */\n uint256 public immutable SUBMISSION_INTERVAL;\n\n /**\n * @notice The time between L2 blocks in seconds. Once set, this value MUST NOT be modified.\n */\n uint256 public immutable L2_BLOCK_TIME;\n\n /**\n * @notice The address of the challenger. Can be updated via upgrade.\n */\n address public immutable CHALLENGER;\n\n /**\n * @notice The address of the proposer. Can be updated via upgrade.\n */\n address public immutable PROPOSER;\n\n /**\n * @notice Minimum time (in seconds) that must elapse before a withdrawal can be finalized.\n */\n uint256 public immutable FINALIZATION_PERIOD_SECONDS;\n\n /**\n * @notice The number of the first L2 block recorded in this contract.\n */\n uint256 public startingBlockNumber;\n\n /**\n * @notice The timestamp of the first L2 block recorded in this contract.\n */\n uint256 public startingTimestamp;\n\n /**\n * @notice Array of L2 output proposals.\n */\n Types.OutputProposal[] internal l2Outputs;\n\n /**\n * @notice Emitted when an output is proposed.\n *\n * @param outputRoot The output root.\n * @param l2OutputIndex The index of the output in the l2Outputs array.\n * @param l2BlockNumber The L2 block number of the output root.\n * @param l1Timestamp The L1 timestamp when proposed.\n */\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n /**\n * @notice Emitted when outputs are deleted.\n *\n * @param prevNextOutputIndex Next L2 output index before the deletion.\n * @param newNextOutputIndex Next L2 output index after the deletion.\n */\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n /**\n * @custom:semver 1.2.0\n *\n * @param _submissionInterval Interval in blocks at which checkpoints must be submitted.\n * @param _l2BlockTime The time per L2 block, in seconds.\n * @param _startingBlockNumber The number of the first L2 block.\n * @param _startingTimestamp The timestamp of the first L2 block.\n * @param _proposer The address of the proposer.\n * @param _challenger The address of the challenger.\n */\n constructor(\n uint256 _submissionInterval,\n uint256 _l2BlockTime,\n uint256 _startingBlockNumber,\n uint256 _startingTimestamp,\n address _proposer,\n address _challenger,\n uint256 _finalizationPeriodSeconds\n ) Semver(1, 2, 0) {\n require(_l2BlockTime > 0, \"L2OutputOracle: L2 block time must be greater than 0\");\n require(\n _submissionInterval > _l2BlockTime,\n \"L2OutputOracle: submission interval must be greater than L2 block time\"\n );\n\n SUBMISSION_INTERVAL = _submissionInterval;\n L2_BLOCK_TIME = _l2BlockTime;\n PROPOSER = _proposer;\n CHALLENGER = _challenger;\n FINALIZATION_PERIOD_SECONDS = _finalizationPeriodSeconds;\n\n initialize(_startingBlockNumber, _startingTimestamp);\n }\n\n /**\n * @notice Initializer.\n *\n * @param _startingBlockNumber Block number for the first recoded L2 block.\n * @param _startingTimestamp Timestamp for the first recoded L2 block.\n */\n function initialize(uint256 _startingBlockNumber, uint256 _startingTimestamp)\n public\n initializer\n {\n require(\n _startingTimestamp <= block.timestamp,\n \"L2OutputOracle: starting L2 timestamp must be less than current time\"\n );\n\n startingTimestamp = _startingTimestamp;\n startingBlockNumber = _startingBlockNumber;\n }\n\n /**\n * @notice Deletes all output proposals after and including the proposal that corresponds to\n * the given output index. Only the challenger address can delete outputs.\n *\n * @param _l2OutputIndex Index of the first L2 output to be deleted. All outputs after this\n * output will also be deleted.\n */\n // solhint-disable-next-line ordering\n function deleteL2Outputs(uint256 _l2OutputIndex) external {\n require(\n msg.sender == CHALLENGER,\n \"L2OutputOracle: only the challenger address can delete outputs\"\n );\n\n // Make sure we're not *increasing* the length of the array.\n require(\n _l2OutputIndex < l2Outputs.length,\n \"L2OutputOracle: cannot delete outputs after the latest output index\"\n );\n\n // Do not allow deleting any outputs that have already been finalized.\n require(\n block.timestamp - l2Outputs[_l2OutputIndex].timestamp < FINALIZATION_PERIOD_SECONDS,\n \"L2OutputOracle: cannot delete outputs that have already been finalized\"\n );\n\n uint256 prevNextL2OutputIndex = nextOutputIndex();\n\n // Use assembly to delete the array elements because Solidity doesn't allow it.\n assembly {\n sstore(l2Outputs.slot, _l2OutputIndex)\n }\n\n emit OutputsDeleted(prevNextL2OutputIndex, _l2OutputIndex);\n }\n\n /**\n * @notice Accepts an outputRoot and the timestamp of the corresponding L2 block. The timestamp\n * must be equal to the current value returned by `nextTimestamp()` in order to be\n * accepted. This function may only be called by the Proposer.\n *\n * @param _outputRoot The L2 output of the checkpoint block.\n * @param _l2BlockNumber The L2 block number that resulted in _outputRoot.\n * @param _l1BlockHash A block hash which must be included in the current chain.\n * @param _l1BlockNumber The block number with the specified block hash.\n */\n function proposeL2Output(\n bytes32 _outputRoot,\n uint256 _l2BlockNumber,\n bytes32 _l1BlockHash,\n uint256 _l1BlockNumber\n ) external payable {\n require(\n msg.sender == PROPOSER,\n \"L2OutputOracle: only the proposer address can propose new outputs\"\n );\n\n require(\n _l2BlockNumber == nextBlockNumber(),\n \"L2OutputOracle: block number must be equal to next expected block number\"\n );\n\n require(\n computeL2Timestamp(_l2BlockNumber) < block.timestamp,\n \"L2OutputOracle: cannot propose L2 output in the future\"\n );\n\n require(\n _outputRoot != bytes32(0),\n \"L2OutputOracle: L2 output proposal cannot be the zero hash\"\n );\n\n if (_l1BlockHash != bytes32(0)) {\n // This check allows the proposer to propose an output based on a given L1 block,\n // without fear that it will be reorged out.\n // It will also revert if the blockheight provided is more than 256 blocks behind the\n // chain tip (as the hash will return as zero). This does open the door to a griefing\n // attack in which the proposer's submission is censored until the block is no longer\n // retrievable, if the proposer is experiencing this attack it can simply leave out the\n // blockhash value, and delay submission until it is confident that the L1 block is\n // finalized.\n require(\n blockhash(_l1BlockNumber) == _l1BlockHash,\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n }\n\n emit OutputProposed(_outputRoot, nextOutputIndex(), _l2BlockNumber, block.timestamp);\n\n l2Outputs.push(\n Types.OutputProposal({\n outputRoot: _outputRoot,\n timestamp: uint128(block.timestamp),\n l2BlockNumber: uint128(_l2BlockNumber)\n })\n );\n }\n\n /**\n * @notice Returns an output by index. Exists because Solidity's array access will return a\n * tuple instead of a struct.\n *\n * @param _l2OutputIndex Index of the output to return.\n *\n * @return The output at the given index.\n */\n function getL2Output(uint256 _l2OutputIndex)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[_l2OutputIndex];\n }\n\n /**\n * @notice Returns the index of the L2 output that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return Index of the first checkpoint that commits to the given L2 block number.\n */\n function getL2OutputIndexAfter(uint256 _l2BlockNumber) public view returns (uint256) {\n // Make sure an output for this block number has actually been proposed.\n require(\n _l2BlockNumber <= latestBlockNumber(),\n \"L2OutputOracle: cannot get output for a block that has not been proposed\"\n );\n\n // Make sure there's at least one output proposed.\n require(\n l2Outputs.length > 0,\n \"L2OutputOracle: cannot get output as no outputs have been proposed yet\"\n );\n\n // Find the output via binary search, guaranteed to exist.\n uint256 lo = 0;\n uint256 hi = l2Outputs.length;\n while (lo < hi) {\n uint256 mid = (lo + hi) / 2;\n if (l2Outputs[mid].l2BlockNumber < _l2BlockNumber) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n return lo;\n }\n\n /**\n * @notice Returns the L2 output proposal that checkpoints a given L2 block number. Uses a\n * binary search to find the first output greater than or equal to the given block.\n *\n * @param _l2BlockNumber L2 block number to find a checkpoint for.\n *\n * @return First checkpoint that commits to the given L2 block number.\n */\n function getL2OutputAfter(uint256 _l2BlockNumber)\n external\n view\n returns (Types.OutputProposal memory)\n {\n return l2Outputs[getL2OutputIndexAfter(_l2BlockNumber)];\n }\n\n /**\n * @notice Returns the number of outputs that have been proposed. Will revert if no outputs\n * have been proposed yet.\n *\n * @return The number of outputs that have been proposed.\n */\n function latestOutputIndex() external view returns (uint256) {\n return l2Outputs.length - 1;\n }\n\n /**\n * @notice Returns the index of the next output to be proposed.\n *\n * @return The index of the next output to be proposed.\n */\n function nextOutputIndex() public view returns (uint256) {\n return l2Outputs.length;\n }\n\n /**\n * @notice Returns the block number of the latest submitted L2 output proposal. If no proposals\n * been submitted yet then this function will return the starting block number.\n *\n * @return Latest submitted L2 block number.\n */\n function latestBlockNumber() public view returns (uint256) {\n return\n l2Outputs.length == 0\n ? startingBlockNumber\n : l2Outputs[l2Outputs.length - 1].l2BlockNumber;\n }\n\n /**\n * @notice Computes the block number of the next L2 block that needs to be checkpointed.\n *\n * @return Next L2 block number.\n */\n function nextBlockNumber() public view returns (uint256) {\n return latestBlockNumber() + SUBMISSION_INTERVAL;\n }\n\n /**\n * @notice Returns the L2 timestamp corresponding to a given L2 block number.\n *\n * @param _l2BlockNumber The L2 block number of the target block.\n *\n * @return L2 timestamp of the given block.\n */\n function computeL2Timestamp(uint256 _l2BlockNumber) public view returns (uint256) {\n return startingTimestamp + ((_l2BlockNumber - startingBlockNumber) * L2_BLOCK_TIME);\n }\n}\n" - }, - "contracts/L1/OptimismPortal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { L2OutputOracle } from \"./L2OutputOracle.sol\";\nimport { SystemConfig } from \"./SystemConfig.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { SecureMerkleTrie } from \"../libraries/trie/SecureMerkleTrie.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ResourceMetering } from \"./ResourceMetering.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @title OptimismPortal\n * @notice The OptimismPortal is a low-level contract responsible for passing messages between L1\n * and L2. Messages sent directly to the OptimismPortal have no form of replayability.\n * Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface.\n */\ncontract OptimismPortal is Initializable, ResourceMetering, Semver {\n /**\n * @notice Represents a proven withdrawal.\n *\n * @custom:field outputRoot Root of the L2 output this was proven against.\n * @custom:field timestamp Timestamp at whcih the withdrawal was proven.\n * @custom:field l2OutputIndex Index of the output this was proven against.\n */\n struct ProvenWithdrawal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2OutputIndex;\n }\n\n /**\n * @notice Version of the deposit event.\n */\n uint256 internal constant DEPOSIT_VERSION = 0;\n\n /**\n * @notice The L2 gas limit set when eth is deposited using the receive() function.\n */\n uint64 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Address of the L2OutputOracle contract.\n */\n L2OutputOracle public immutable L2_ORACLE;\n\n /**\n * @notice Address of the SystemConfig contract.\n */\n SystemConfig public immutable SYSTEM_CONFIG;\n\n /**\n * @notice Address that has the ability to pause and unpause withdrawals.\n */\n address public immutable GUARDIAN;\n\n /**\n * @notice Address of the L2 account which initiated a withdrawal in this transaction. If the\n * of this variable is the default L2 sender address, then we are NOT inside of a call\n * to finalizeWithdrawalTransaction.\n */\n address public l2Sender;\n\n /**\n * @notice A list of withdrawal hashes which have been successfully finalized.\n */\n mapping(bytes32 => bool) public finalizedWithdrawals;\n\n /**\n * @notice A mapping of withdrawal hashes to `ProvenWithdrawal` data.\n */\n mapping(bytes32 => ProvenWithdrawal) public provenWithdrawals;\n\n /**\n * @notice Determines if cross domain messaging is paused. When set to true,\n * deposits and withdrawals are paused. This may be removed in the\n * future.\n */\n bool public paused;\n\n /**\n * @notice Emitted when a transaction is deposited from L1 to L2. The parameters of this event\n * are read by the rollup node and used to derive deposit transactions on L2.\n *\n * @param from Address that triggered the deposit transaction.\n * @param to Address that the deposit transaction is directed to.\n * @param version Version of this deposit transaction event.\n * @param opaqueData ABI encoded deposit data to be parsed off-chain.\n */\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is proven.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n */\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n /**\n * @notice Emitted when a withdrawal transaction is finalized.\n *\n * @param withdrawalHash Hash of the withdrawal transaction.\n * @param success Whether the withdrawal transaction was successful.\n */\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n\n /**\n * @notice Emitted when the pause is triggered.\n *\n * @param account Address of the account triggering the pause.\n */\n event Paused(address account);\n\n /**\n * @notice Emitted when the pause is lifted.\n *\n * @param account Address of the account triggering the unpause.\n */\n event Unpaused(address account);\n\n /**\n * @notice Reverts when paused.\n */\n modifier whenNotPaused() {\n require(paused == false, \"OptimismPortal: paused\");\n _;\n }\n\n /**\n * @custom:semver 1.3.0\n *\n * @param _l2Oracle Address of the L2OutputOracle contract.\n * @param _guardian Address that can pause deposits and withdrawals.\n * @param _paused Sets the contract's pausability state.\n * @param _config Address of the SystemConfig contract.\n */\n constructor(\n L2OutputOracle _l2Oracle,\n address _guardian,\n bool _paused,\n SystemConfig _config\n ) Semver(1, 3, 0) {\n L2_ORACLE = _l2Oracle;\n GUARDIAN = _guardian;\n SYSTEM_CONFIG = _config;\n initialize(_paused);\n }\n\n /**\n * @notice Initializer.\n */\n function initialize(bool _paused) public initializer {\n l2Sender = Constants.DEFAULT_L2_SENDER;\n paused = _paused;\n __ResourceMetering_init();\n }\n\n /**\n * @notice Pause deposits and withdrawals.\n */\n function pause() external {\n require(msg.sender == GUARDIAN, \"OptimismPortal: only guardian can pause\");\n paused = true;\n emit Paused(msg.sender);\n }\n\n /**\n * @notice Unpause deposits and withdrawals.\n */\n function unpause() external {\n require(msg.sender == GUARDIAN, \"OptimismPortal: only guardian can unpause\");\n paused = false;\n emit Unpaused(msg.sender);\n }\n\n /**\n * @notice Accepts value so that users can send ETH directly to this contract and have the\n * funds be deposited to their address on L2. This is intended as a convenience\n * function for EOAs. Contracts should call the depositTransaction() function directly\n * otherwise any deposited funds will be lost due to address aliasing.\n */\n // solhint-disable-next-line ordering\n receive() external payable {\n depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes(\"\"));\n }\n\n /**\n * @notice Accepts ETH value without triggering a deposit to L2. This function mainly exists\n * for the sake of the migration between the legacy Optimism system and Bedrock.\n */\n function donateETH() external payable {\n // Intentionally empty.\n }\n\n /**\n * @notice Getter for the resource config. Used internally by the ResourceMetering\n * contract. The SystemConfig is the source of truth for the resource config.\n *\n * @return ResourceMetering.ResourceConfig\n */\n function _resourceConfig()\n internal\n view\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return SYSTEM_CONFIG.resourceConfig();\n }\n\n /**\n * @notice Proves a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n * @param _l2OutputIndex L2 output index to prove against.\n * @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root.\n * @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract.\n */\n function proveWithdrawalTransaction(\n Types.WithdrawalTransaction memory _tx,\n uint256 _l2OutputIndex,\n Types.OutputRootProof calldata _outputRootProof,\n bytes[] calldata _withdrawalProof\n ) external whenNotPaused {\n // Prevent users from creating a deposit transaction where this address is the message\n // sender on L2. Because this is checked here, we do not need to check again in\n // `finalizeWithdrawalTransaction`.\n require(\n _tx.target != address(this),\n \"OptimismPortal: you cannot send messages to the portal contract\"\n );\n\n // Get the output root and load onto the stack to prevent multiple mloads. This will\n // revert if there is no output root for the given block number.\n bytes32 outputRoot = L2_ORACLE.getL2Output(_l2OutputIndex).outputRoot;\n\n // Verify that the output root can be generated with the elements in the proof.\n require(\n outputRoot == Hashing.hashOutputRootProof(_outputRootProof),\n \"OptimismPortal: invalid output root proof\"\n );\n\n // Load the ProvenWithdrawal into memory, using the withdrawal hash as a unique identifier.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // We generally want to prevent users from proving the same withdrawal multiple times\n // because each successive proof will update the timestamp. A malicious user can take\n // advantage of this to prevent other users from finalizing their withdrawal. However,\n // since withdrawals are proven before an output root is finalized, we need to allow users\n // to re-prove their withdrawal only in the case that the output root for their specified\n // output index has been updated.\n require(\n provenWithdrawal.timestamp == 0 ||\n L2_ORACLE.getL2Output(provenWithdrawal.l2OutputIndex).outputRoot !=\n provenWithdrawal.outputRoot,\n \"OptimismPortal: withdrawal hash has already been proven\"\n );\n\n // Compute the storage slot of the withdrawal hash in the L2ToL1MessagePasser contract.\n // Refer to the Solidity documentation for more information on how storage layouts are\n // computed for mappings.\n bytes32 storageKey = keccak256(\n abi.encode(\n withdrawalHash,\n uint256(0) // The withdrawals mapping is at the first slot in the layout.\n )\n );\n\n // Verify that the hash of this withdrawal was stored in the L2toL1MessagePasser contract\n // on L2. If this is true, under the assumption that the SecureMerkleTrie does not have\n // bugs, then we know that this withdrawal was actually triggered on L2 and can therefore\n // be relayed on L1.\n require(\n SecureMerkleTrie.verifyInclusionProof(\n abi.encode(storageKey),\n hex\"01\",\n _withdrawalProof,\n _outputRootProof.messagePasserStorageRoot\n ),\n \"OptimismPortal: invalid withdrawal inclusion proof\"\n );\n\n // Designate the withdrawalHash as proven by storing the `outputRoot`, `timestamp`, and\n // `l2BlockNumber` in the `provenWithdrawals` mapping. A `withdrawalHash` can only be\n // proven once unless it is submitted again with a different outputRoot.\n provenWithdrawals[withdrawalHash] = ProvenWithdrawal({\n outputRoot: outputRoot,\n timestamp: uint128(block.timestamp),\n l2OutputIndex: uint128(_l2OutputIndex)\n });\n\n // Emit a `WithdrawalProven` event.\n emit WithdrawalProven(withdrawalHash, _tx.sender, _tx.target);\n }\n\n /**\n * @notice Finalizes a withdrawal transaction.\n *\n * @param _tx Withdrawal transaction to finalize.\n */\n function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx)\n external\n whenNotPaused\n {\n // Make sure that the l2Sender has not yet been set. The l2Sender is set to a value other\n // than the default value when a withdrawal transaction is being finalized. This check is\n // a defacto reentrancy guard.\n require(\n l2Sender == Constants.DEFAULT_L2_SENDER,\n \"OptimismPortal: can only trigger one withdrawal per transaction\"\n );\n\n // Grab the proven withdrawal from the `provenWithdrawals` map.\n bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);\n ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];\n\n // A withdrawal can only be finalized if it has been proven. We know that a withdrawal has\n // been proven at least once when its timestamp is non-zero. Unproven withdrawals will have\n // a timestamp of zero.\n require(\n provenWithdrawal.timestamp != 0,\n \"OptimismPortal: withdrawal has not been proven yet\"\n );\n\n // As a sanity check, we make sure that the proven withdrawal's timestamp is greater than\n // starting timestamp inside the L2OutputOracle. Not strictly necessary but extra layer of\n // safety against weird bugs in the proving step.\n require(\n provenWithdrawal.timestamp >= L2_ORACLE.startingTimestamp(),\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n\n // A proven withdrawal must wait at least the finalization period before it can be\n // finalized. This waiting period can elapse in parallel with the waiting period for the\n // output the withdrawal was proven against. In effect, this means that the minimum\n // withdrawal time is proposal submission time + finalization period.\n require(\n _isFinalizationPeriodElapsed(provenWithdrawal.timestamp),\n \"OptimismPortal: proven withdrawal finalization period has not elapsed\"\n );\n\n // Grab the OutputProposal from the L2OutputOracle, will revert if the output that\n // corresponds to the given index has not been proposed yet.\n Types.OutputProposal memory proposal = L2_ORACLE.getL2Output(\n provenWithdrawal.l2OutputIndex\n );\n\n // Check that the output root that was used to prove the withdrawal is the same as the\n // current output root for the given output index. An output root may change if it is\n // deleted by the challenger address and then re-proposed.\n require(\n proposal.outputRoot == provenWithdrawal.outputRoot,\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n\n // Check that the output proposal has also been finalized.\n require(\n _isFinalizationPeriodElapsed(proposal.timestamp),\n \"OptimismPortal: output proposal finalization period has not elapsed\"\n );\n\n // Check that this withdrawal has not already been finalized, this is replay protection.\n require(\n finalizedWithdrawals[withdrawalHash] == false,\n \"OptimismPortal: withdrawal has already been finalized\"\n );\n\n // Mark the withdrawal as finalized so it can't be replayed.\n finalizedWithdrawals[withdrawalHash] = true;\n\n // Set the l2Sender so contracts know who triggered this withdrawal on L2.\n l2Sender = _tx.sender;\n\n // Trigger the call to the target contract. We use a custom low level method\n // SafeCall.callWithMinGas to ensure two key properties\n // 1. Target contracts cannot force this call to run out of gas by returning a very large\n // amount of data (and this is OK because we don't care about the returndata here).\n // 2. The amount of gas provided to the call to the target contract is at least the gas\n // limit specified by the user. If there is not enough gas in the callframe to\n // accomplish this, `callWithMinGas` will revert.\n // Additionally, if there is not enough gas remaining to complete the execution after the\n // call returns, this function will revert.\n bool success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, _tx.value, _tx.data);\n\n // Reset the l2Sender back to the default value.\n l2Sender = Constants.DEFAULT_L2_SENDER;\n\n // All withdrawals are immediately finalized. Replayability can\n // be achieved through contracts built on top of this contract\n emit WithdrawalFinalized(withdrawalHash, success);\n\n // Reverting here is useful for determining the exact gas cost to successfully execute the\n // sub call to the target contract if the minimum gas limit specified by the user would not\n // be sufficient to execute the sub call.\n if (success == false && tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"OptimismPortal: withdrawal failed\");\n }\n }\n\n /**\n * @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in\n * deriving deposit transactions. Note that if a deposit is made by a contract, its\n * address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider\n * using the CrossDomainMessenger contracts for a simpler developer experience.\n *\n * @param _to Target address on L2.\n * @param _value ETH value to send to the recipient.\n * @param _gasLimit Minimum L2 gas limit (can be greater than or equal to this value).\n * @param _isCreation Whether or not the transaction is a contract creation.\n * @param _data Data to trigger the recipient with.\n */\n function depositTransaction(\n address _to,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable metered(_gasLimit) {\n // Just to be safe, make sure that people specify address(0) as the target when doing\n // contract creations.\n if (_isCreation) {\n require(\n _to == address(0),\n \"OptimismPortal: must send to address(0) when creating a contract\"\n );\n }\n\n // Prevent depositing transactions that have too small of a gas limit.\n require(_gasLimit >= 21_000, \"OptimismPortal: gas limit must cover instrinsic gas cost\");\n\n // Transform the from-address to its alias if the caller is a contract.\n address from = msg.sender;\n if (msg.sender != tx.origin) {\n from = AddressAliasHelper.applyL1ToL2Alias(msg.sender);\n }\n\n // Compute the opaque data that will be emitted as part of the TransactionDeposited event.\n // We use opaque data so that we can update the TransactionDeposited event in the future\n // without breaking the current interface.\n bytes memory opaqueData = abi.encodePacked(\n msg.value,\n _value,\n _gasLimit,\n _isCreation,\n _data\n );\n\n // Emit a TransactionDeposited event so that the rollup node can derive a deposit\n // transaction for this deposit.\n emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData);\n }\n\n /**\n * @notice Determine if a given output is finalized. Reverts if the call to\n * L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.\n *\n * @param _l2OutputIndex Index of the L2 output to check.\n *\n * @return Whether or not the output is finalized.\n */\n function isOutputFinalized(uint256 _l2OutputIndex) external view returns (bool) {\n return _isFinalizationPeriodElapsed(L2_ORACLE.getL2Output(_l2OutputIndex).timestamp);\n }\n\n /**\n * @notice Determines whether the finalization period has elapsed w/r/t a given timestamp.\n *\n * @param _timestamp Timestamp to check.\n *\n * @return Whether or not the finalization period has elapsed.\n */\n function _isFinalizationPeriodElapsed(uint256 _timestamp) internal view returns (bool) {\n return block.timestamp > _timestamp + L2_ORACLE.FINALIZATION_PERIOD_SECONDS();\n }\n}\n" - }, - "contracts/L1/ResourceMetering.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\n\n/**\n * @custom:upgradeable\n * @title ResourceMetering\n * @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing\n * updates automatically based on current demand.\n */\nabstract contract ResourceMetering is Initializable {\n /**\n * @notice Represents the various parameters that control the way in which resources are\n * metered. Corresponds to the EIP-1559 resource metering system.\n *\n * @custom:field prevBaseFee Base fee from the previous block(s).\n * @custom:field prevBoughtGas Amount of gas bought so far in the current block.\n * @custom:field prevBlockNum Last block number that the base fee was updated.\n */\n struct ResourceParams {\n uint128 prevBaseFee;\n uint64 prevBoughtGas;\n uint64 prevBlockNum;\n }\n\n /**\n * @notice Represents the configuration for the EIP-1559 based curve for the deposit gas\n * market. These values should be set with care as it is possible to set them in\n * a way that breaks the deposit gas market. The target resource limit is defined as\n * maxResourceLimit / elasticityMultiplier. This struct was designed to fit within a\n * single word. There is additional space for additions in the future.\n *\n * @custom:field maxResourceLimit Represents the maximum amount of deposit gas that\n * can be purchased per block.\n * @custom:field elasticityMultiplier Determines the target resource limit along with\n * the resource limit.\n * @custom:field baseFeeMaxChangeDenominator Determines max change on fee per block.\n * @custom:field minimumBaseFee The min deposit base fee, it is clamped to this\n * value.\n * @custom:field systemTxMaxGas The amount of gas supplied to the system\n * transaction. This should be set to the same number\n * that the op-node sets as the gas limit for the\n * system transaction.\n * @custom:field maximumBaseFee The max deposit base fee, it is clamped to this\n * value.\n */\n struct ResourceConfig {\n uint32 maxResourceLimit;\n uint8 elasticityMultiplier;\n uint8 baseFeeMaxChangeDenominator;\n uint32 minimumBaseFee;\n uint32 systemTxMaxGas;\n uint128 maximumBaseFee;\n }\n\n /**\n * @notice EIP-1559 style gas parameters.\n */\n ResourceParams public params;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n */\n uint256[48] private __gap;\n\n /**\n * @notice Meters access to a function based an amount of a requested resource.\n *\n * @param _amount Amount of the resource requested.\n */\n modifier metered(uint64 _amount) {\n // Record initial gas amount so we can refund for it later.\n uint256 initialGas = gasleft();\n\n // Run the underlying function.\n _;\n\n // Run the metering function.\n _metered(_amount, initialGas);\n }\n\n /**\n * @notice An internal function that holds all of the logic for metering a resource.\n *\n * @param _amount Amount of the resource requested.\n * @param _initialGas The amount of gas before any modifier execution.\n */\n function _metered(uint64 _amount, uint256 _initialGas) internal {\n // Update block number and base fee if necessary.\n uint256 blockDiff = block.number - params.prevBlockNum;\n\n ResourceConfig memory config = _resourceConfig();\n int256 targetResourceLimit = int256(uint256(config.maxResourceLimit)) /\n int256(uint256(config.elasticityMultiplier));\n\n if (blockDiff > 0) {\n // Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate\n // at which deposits can be created and therefore limit the potential for deposits to\n // spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes.\n int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - targetResourceLimit;\n int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) /\n (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator)));\n\n // Update base fee by adding the base fee delta and clamp the resulting value between\n // min and max.\n int256 newBaseFee = Arithmetic.clamp({\n _value: int256(uint256(params.prevBaseFee)) + baseFeeDelta,\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n\n // If we skipped more than one block, we also need to account for every empty block.\n // Empty block means there was no demand for deposits in that block, so we should\n // reflect this lack of demand in the fee.\n if (blockDiff > 1) {\n // Update the base fee by repeatedly applying the exponent 1-(1/change_denominator)\n // blockDiff - 1 times. Simulates multiple empty blocks. Clamp the resulting value\n // between min and max.\n newBaseFee = Arithmetic.clamp({\n _value: Arithmetic.cdexp({\n _coefficient: newBaseFee,\n _denominator: int256(uint256(config.baseFeeMaxChangeDenominator)),\n _exponent: int256(blockDiff - 1)\n }),\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n }\n\n // Update new base fee, reset bought gas, and update block number.\n params.prevBaseFee = uint128(uint256(newBaseFee));\n params.prevBoughtGas = 0;\n params.prevBlockNum = uint64(block.number);\n }\n\n // Make sure we can actually buy the resource amount requested by the user.\n params.prevBoughtGas += _amount;\n require(\n int256(uint256(params.prevBoughtGas)) <= int256(uint256(config.maxResourceLimit)),\n \"ResourceMetering: cannot buy more gas than available gas limit\"\n );\n\n // Determine the amount of ETH to be paid.\n uint256 resourceCost = uint256(_amount) * uint256(params.prevBaseFee);\n\n // We currently charge for this ETH amount as an L1 gas burn, so we convert the ETH amount\n // into gas by dividing by the L1 base fee. We assume a minimum base fee of 1 gwei to avoid\n // division by zero for L1s that don't support 1559 or to avoid excessive gas burns during\n // periods of extremely low L1 demand. One-day average gas fee hasn't dipped below 1 gwei\n // during any 1 day period in the last 5 years, so should be fine.\n uint256 gasCost = resourceCost / Math.max(block.basefee, 1 gwei);\n\n // Give the user a refund based on the amount of gas they used to do all of the work up to\n // this point. Since we're at the end of the modifier, this should be pretty accurate. Acts\n // effectively like a dynamic stipend (with a minimum value).\n uint256 usedGas = _initialGas - gasleft();\n if (gasCost > usedGas) {\n Burn.gas(gasCost - usedGas);\n }\n }\n\n /**\n * @notice Virtual function that returns the resource config. Contracts that inherit this\n * contract must implement this function.\n *\n * @return ResourceConfig\n */\n function _resourceConfig() internal virtual returns (ResourceConfig memory);\n\n /**\n * @notice Sets initial resource parameter values. This function must either be called by the\n * initializer function of an upgradeable child contract.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __ResourceMetering_init() internal onlyInitializing {\n params = ResourceParams({\n prevBaseFee: 1 gwei,\n prevBoughtGas: 0,\n prevBlockNum: uint64(block.number)\n });\n }\n}\n" - }, - "contracts/L1/SystemConfig.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { ResourceMetering } from \"./ResourceMetering.sol\";\n\n/**\n * @title SystemConfig\n * @notice The SystemConfig contract is used to manage configuration of an Optimism network. All\n * configuration is stored on L1 and picked up by L2 as part of the derviation of the L2\n * chain.\n */\ncontract SystemConfig is OwnableUpgradeable, Semver {\n /**\n * @notice Enum representing different types of updates.\n *\n * @custom:value BATCHER Represents an update to the batcher hash.\n * @custom:value GAS_CONFIG Represents an update to txn fee config on L2.\n * @custom:value GAS_LIMIT Represents an update to gas limit on L2.\n * @custom:value UNSAFE_BLOCK_SIGNER Represents an update to the signer key for unsafe\n * block distrubution.\n */\n enum UpdateType {\n BATCHER,\n GAS_CONFIG,\n GAS_LIMIT,\n UNSAFE_BLOCK_SIGNER\n }\n\n /**\n * @notice Version identifier, used for upgrades.\n */\n uint256 public constant VERSION = 0;\n\n /**\n * @notice Storage slot that the unsafe block signer is stored at. Storing it at this\n * deterministic storage slot allows for decoupling the storage layout from the way\n * that `solc` lays out storage. The `op-node` uses a storage proof to fetch this value.\n */\n bytes32 public constant UNSAFE_BLOCK_SIGNER_SLOT = keccak256(\"systemconfig.unsafeblocksigner\");\n\n /**\n * @notice Fixed L2 gas overhead. Used as part of the L2 fee calculation.\n */\n uint256 public overhead;\n\n /**\n * @notice Dynamic L2 gas overhead. Used as part of the L2 fee calculation.\n */\n uint256 public scalar;\n\n /**\n * @notice Identifier for the batcher. For version 1 of this configuration, this is represented\n * as an address left-padded with zeros to 32 bytes.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice L2 block gas limit.\n */\n uint64 public gasLimit;\n\n /**\n * @notice The configuration for the deposit fee market. Used by the OptimismPortal\n * to meter the cost of buying L2 gas on L1. Set as internal and wrapped with a getter\n * so that the struct is returned instead of a tuple.\n */\n ResourceMetering.ResourceConfig internal _resourceConfig;\n\n /**\n * @notice Emitted when configuration is updated\n *\n * @param version SystemConfig version.\n * @param updateType Type of update.\n * @param data Encoded update data.\n */\n event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);\n\n /**\n * @custom:semver 1.2.0\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n * @param _unsafeBlockSigner Initial unsafe block signer address.\n * @param _config Initial resource config.\n */\n constructor(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner,\n ResourceMetering.ResourceConfig memory _config\n ) Semver(1, 2, 0) {\n initialize({\n _owner: _owner,\n _overhead: _overhead,\n _scalar: _scalar,\n _batcherHash: _batcherHash,\n _gasLimit: _gasLimit,\n _unsafeBlockSigner: _unsafeBlockSigner,\n _config: _config\n });\n }\n\n /**\n * @notice Initializer. The resource config must be set before the\n * require check.\n *\n * @param _owner Initial owner of the contract.\n * @param _overhead Initial overhead value.\n * @param _scalar Initial scalar value.\n * @param _batcherHash Initial batcher hash.\n * @param _gasLimit Initial gas limit.\n * @param _unsafeBlockSigner Initial unsafe block signer address.\n * @param _config Initial ResourceConfig.\n */\n function initialize(\n address _owner,\n uint256 _overhead,\n uint256 _scalar,\n bytes32 _batcherHash,\n uint64 _gasLimit,\n address _unsafeBlockSigner,\n ResourceMetering.ResourceConfig memory _config\n ) public initializer {\n __Ownable_init();\n transferOwnership(_owner);\n overhead = _overhead;\n scalar = _scalar;\n batcherHash = _batcherHash;\n gasLimit = _gasLimit;\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n _setResourceConfig(_config);\n require(_gasLimit >= minimumGasLimit(), \"SystemConfig: gas limit too low\");\n }\n\n /**\n * @notice Returns the minimum L2 gas limit that can be safely set for the system to\n * operate. The L2 gas limit must be larger than or equal to the amount of\n * gas that is allocated for deposits per block plus the amount of gas that\n * is allocated for the system transaction.\n * This function is used to determine if changes to parameters are safe.\n *\n * @return uint64\n */\n function minimumGasLimit() public view returns (uint64) {\n return uint64(_resourceConfig.maxResourceLimit) + uint64(_resourceConfig.systemTxMaxGas);\n }\n\n /**\n * @notice High level getter for the unsafe block signer address. Unsafe blocks can be\n * propagated across the p2p network if they are signed by the key corresponding to\n * this address.\n *\n * @return Address of the unsafe block signer.\n */\n // solhint-disable-next-line ordering\n function unsafeBlockSigner() external view returns (address) {\n address addr;\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n addr := sload(slot)\n }\n return addr;\n }\n\n /**\n * @notice Updates the unsafe block signer address.\n *\n * @param _unsafeBlockSigner New unsafe block signer address.\n */\n function setUnsafeBlockSigner(address _unsafeBlockSigner) external onlyOwner {\n _setUnsafeBlockSigner(_unsafeBlockSigner);\n\n bytes memory data = abi.encode(_unsafeBlockSigner);\n emit ConfigUpdate(VERSION, UpdateType.UNSAFE_BLOCK_SIGNER, data);\n }\n\n /**\n * @notice Updates the batcher hash.\n *\n * @param _batcherHash New batcher hash.\n */\n function setBatcherHash(bytes32 _batcherHash) external onlyOwner {\n batcherHash = _batcherHash;\n\n bytes memory data = abi.encode(_batcherHash);\n emit ConfigUpdate(VERSION, UpdateType.BATCHER, data);\n }\n\n /**\n * @notice Updates gas config.\n *\n * @param _overhead New overhead value.\n * @param _scalar New scalar value.\n */\n function setGasConfig(uint256 _overhead, uint256 _scalar) external onlyOwner {\n overhead = _overhead;\n scalar = _scalar;\n\n bytes memory data = abi.encode(_overhead, _scalar);\n emit ConfigUpdate(VERSION, UpdateType.GAS_CONFIG, data);\n }\n\n /**\n * @notice Updates the L2 gas limit.\n *\n * @param _gasLimit New gas limit.\n */\n function setGasLimit(uint64 _gasLimit) external onlyOwner {\n require(_gasLimit >= minimumGasLimit(), \"SystemConfig: gas limit too low\");\n gasLimit = _gasLimit;\n\n bytes memory data = abi.encode(_gasLimit);\n emit ConfigUpdate(VERSION, UpdateType.GAS_LIMIT, data);\n }\n\n /**\n * @notice Low level setter for the unsafe block signer address. This function exists to\n * deduplicate code around storing the unsafeBlockSigner address in storage.\n *\n * @param _unsafeBlockSigner New unsafeBlockSigner value.\n */\n function _setUnsafeBlockSigner(address _unsafeBlockSigner) internal {\n bytes32 slot = UNSAFE_BLOCK_SIGNER_SLOT;\n assembly {\n sstore(slot, _unsafeBlockSigner)\n }\n }\n\n /**\n * @notice A getter for the resource config. Ensures that the struct is\n * returned instead of a tuple.\n *\n * @return ResourceConfig\n */\n function resourceConfig() external view returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig;\n }\n\n /**\n * @notice An external setter for the resource config. In the future, this\n * method may emit an event that the `op-node` picks up for when the\n * resource config is changed.\n *\n * @param _config The new resource config values.\n */\n function setResourceConfig(ResourceMetering.ResourceConfig memory _config) external onlyOwner {\n _setResourceConfig(_config);\n }\n\n /**\n * @notice An internal setter for the resource config. Ensures that the\n * config is sane before storing it by checking for invariants.\n *\n * @param _config The new resource config.\n */\n function _setResourceConfig(ResourceMetering.ResourceConfig memory _config) internal {\n // Min base fee must be less than or equal to max base fee.\n require(\n _config.minimumBaseFee <= _config.maximumBaseFee,\n \"SystemConfig: min base fee must be less than max base\"\n );\n // Base fee change denominator must be greater than 0.\n require(_config.baseFeeMaxChangeDenominator > 0, \"SystemConfig: denominator cannot be 0\");\n // Max resource limit plus system tx gas must be less than or equal to the L2 gas limit.\n // The gas limit must be increased before these values can be increased.\n require(\n _config.maxResourceLimit + _config.systemTxMaxGas <= gasLimit,\n \"SystemConfig: gas limit too low\"\n );\n // Elasticity multiplier must be greater than 0.\n require(\n _config.elasticityMultiplier > 0,\n \"SystemConfig: elasticity multiplier cannot be 0\"\n );\n // No precision loss when computing target resource limit.\n require(\n ((_config.maxResourceLimit / _config.elasticityMultiplier) *\n _config.elasticityMultiplier) == _config.maxResourceLimit,\n \"SystemConfig: precision loss with target resource limit\"\n );\n\n _resourceConfig = _config;\n }\n}\n" - }, - "contracts/L2/BaseFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000019\n * @title BaseFeeVault\n * @notice The BaseFeeVault accumulates the base fee that is paid by transactions.\n */\ncontract BaseFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}\n}\n" - }, - "contracts/L2/CrossDomainOwnable.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\n/**\n * @title CrossDomainOwnable\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is only safe to be used if the\n * CrossDomainMessenger system is bypassed and the caller on L1 is calling the\n * OptimismPortal directly.\n */\nabstract contract CrossDomainOwnable is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `msg.sender` is the owner of the contract.\n */\n function _checkOwner() internal view override {\n require(\n owner() == AddressAliasHelper.undoL1ToL2Alias(msg.sender),\n \"CrossDomainOwnable: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/CrossDomainOwnable2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L2CrossDomainMessenger } from \"./L2CrossDomainMessenger.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title CrossDomainOwnable2\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on L1. Note that this contract is meant to be used with systems that use\n * the CrossDomainMessenger system. It will not work if the OptimismPortal is used\n * directly.\n */\nabstract contract CrossDomainOwnable2 is Ownable {\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `xDomainMessageSender` is the owner of the contract. This value is set to the caller\n * of the L1CrossDomainMessenger.\n */\n function _checkOwner() internal view override {\n L2CrossDomainMessenger messenger = L2CrossDomainMessenger(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER\n );\n\n require(\n msg.sender == address(messenger),\n \"CrossDomainOwnable2: caller is not the messenger\"\n );\n\n require(\n owner() == messenger.xDomainMessageSender(),\n \"CrossDomainOwnable2: caller is not the owner\"\n );\n }\n}\n" - }, - "contracts/L2/CrossDomainOwnable3.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L2CrossDomainMessenger } from \"./L2CrossDomainMessenger.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title CrossDomainOwnable3\n * @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned\n * by contracts on either L1 or L2. Note that this contract is meant to be used with systems\n * that use the CrossDomainMessenger system. It will not work if the OptimismPortal is\n * used directly.\n */\nabstract contract CrossDomainOwnable3 is Ownable {\n /**\n * @notice If true, the contract uses the cross domain _checkOwner function override. If false\n * it uses the standard Ownable _checkOwner function.\n */\n bool public isLocal = true;\n\n /**\n * @notice Emits when ownership of the contract is transferred. Includes the\n * isLocal field in addition to the standard `Ownable` OwnershipTransferred event.\n */\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner,\n bool isLocal\n );\n\n /**\n * @notice Allows for ownership to be transferred with specifying the locality.\n * @param _owner The new owner of the contract.\n * @param _isLocal Configures the locality of the ownership.\n */\n function transferOwnership(address _owner, bool _isLocal) external onlyOwner {\n require(_owner != address(0), \"CrossDomainOwnable3: new owner is the zero address\");\n\n address oldOwner = owner();\n _transferOwnership(_owner);\n isLocal = _isLocal;\n\n emit OwnershipTransferred(oldOwner, _owner, _isLocal);\n }\n\n /**\n * @notice Overrides the implementation of the `onlyOwner` modifier to check that the unaliased\n * `xDomainMessageSender` is the owner of the contract. This value is set to the caller\n * of the L1CrossDomainMessenger.\n */\n function _checkOwner() internal view override {\n if (isLocal) {\n require(owner() == msg.sender, \"CrossDomainOwnable3: caller is not the owner\");\n } else {\n L2CrossDomainMessenger messenger = L2CrossDomainMessenger(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER\n );\n\n require(\n msg.sender == address(messenger),\n \"CrossDomainOwnable3: caller is not the messenger\"\n );\n\n require(\n owner() == messenger.xDomainMessageSender(),\n \"CrossDomainOwnable3: caller is not the owner\"\n );\n }\n }\n}\n" - }, - "contracts/L2/GasPriceOracle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000000F\n * @title GasPriceOracle\n * @notice This contract maintains the variables responsible for computing the L1 portion of the\n * total fee charged on L2. Before Bedrock, this contract held variables in state that were\n * read during the state transition function to compute the L1 portion of the transaction\n * fee. After Bedrock, this contract now simply proxies the L1Block contract, which has\n * the values used to compute the L1 portion of the fee in its state.\n *\n * The contract exposes an API that is useful for knowing how large the L1 portion of the\n * transaction fee will be. The following events were deprecated with Bedrock:\n * - event OverheadUpdated(uint256 overhead);\n * - event ScalarUpdated(uint256 scalar);\n * - event DecimalsUpdated(uint256 decimals);\n */\ncontract GasPriceOracle is Semver {\n /**\n * @notice Number of decimals used in the scalar.\n */\n uint256 public constant DECIMALS = 6;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Computes the L1 portion of the fee based on the size of the rlp encoded input\n * transaction, the current L1 base fee, and the various dynamic parameters.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for.\n *\n * @return L1 fee that should be paid for the tx\n */\n function getL1Fee(bytes memory _data) external view returns (uint256) {\n uint256 l1GasUsed = getL1GasUsed(_data);\n uint256 l1Fee = l1GasUsed * l1BaseFee();\n uint256 divisor = 10**DECIMALS;\n uint256 unscaled = l1Fee * scalar();\n uint256 scaled = unscaled / divisor;\n return scaled;\n }\n\n /**\n * @notice Retrieves the current gas price (base fee).\n *\n * @return Current L2 gas price (base fee).\n */\n function gasPrice() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current base fee.\n *\n * @return Current L2 base fee.\n */\n function baseFee() public view returns (uint256) {\n return block.basefee;\n }\n\n /**\n * @notice Retrieves the current fee overhead.\n *\n * @return Current fee overhead.\n */\n function overhead() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead();\n }\n\n /**\n * @notice Retrieves the current fee scalar.\n *\n * @return Current fee scalar.\n */\n function scalar() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar();\n }\n\n /**\n * @notice Retrieves the latest known L1 base fee.\n *\n * @return Latest known L1 base fee.\n */\n function l1BaseFee() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee();\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the number of decimals used in the scalar.\n *\n * @return Number of decimals used in the scalar.\n */\n function decimals() public pure returns (uint256) {\n return DECIMALS;\n }\n\n /**\n * @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which\n * represents the per-transaction gas overhead of posting the transaction and state\n * roots to L1. Adds 68 bytes of padding to account for the fact that the input does\n * not have a signature.\n *\n * @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for.\n *\n * @return Amount of L1 gas used to publish the transaction.\n */\n function getL1GasUsed(bytes memory _data) public view returns (uint256) {\n uint256 total = 0;\n uint256 length = _data.length;\n for (uint256 i = 0; i < length; i++) {\n if (_data[i] == 0) {\n total += 4;\n } else {\n total += 16;\n }\n }\n uint256 unsigned = total + overhead();\n return unsigned + (68 * 16);\n }\n}\n" - }, - "contracts/L2/L1Block.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000015\n * @title L1Block\n * @notice The L1Block predeploy gives users access to information about the last known L1 block.\n * Values within this contract are updated once per epoch (every L1 block) and can only be\n * set by the \"depositor\" account, a special system address. Depositor account transactions\n * are created by the protocol whenever we move to a new epoch.\n */\ncontract L1Block is Semver {\n /**\n * @notice Address of the special depositor account.\n */\n address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001;\n\n /**\n * @notice The latest L1 block number known by the L2 system.\n */\n uint64 public number;\n\n /**\n * @notice The latest L1 timestamp known by the L2 system.\n */\n uint64 public timestamp;\n\n /**\n * @notice The latest L1 basefee.\n */\n uint256 public basefee;\n\n /**\n * @notice The latest L1 blockhash.\n */\n bytes32 public hash;\n\n /**\n * @notice The number of L2 blocks in the same epoch.\n */\n uint64 public sequenceNumber;\n\n /**\n * @notice The versioned hash to authenticate the batcher by.\n */\n bytes32 public batcherHash;\n\n /**\n * @notice The overhead value applied to the L1 portion of the transaction\n * fee.\n */\n uint256 public l1FeeOverhead;\n\n /**\n * @notice The scalar value applied to the L1 portion of the transaction fee.\n */\n uint256 public l1FeeScalar;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Updates the L1 block values.\n *\n * @param _number L1 blocknumber.\n * @param _timestamp L1 timestamp.\n * @param _basefee L1 basefee.\n * @param _hash L1 blockhash.\n * @param _sequenceNumber Number of L2 blocks since epoch start.\n * @param _batcherHash Versioned hash to authenticate batcher by.\n * @param _l1FeeOverhead L1 fee overhead.\n * @param _l1FeeScalar L1 fee scalar.\n */\n function setL1BlockValues(\n uint64 _number,\n uint64 _timestamp,\n uint256 _basefee,\n bytes32 _hash,\n uint64 _sequenceNumber,\n bytes32 _batcherHash,\n uint256 _l1FeeOverhead,\n uint256 _l1FeeScalar\n ) external {\n require(\n msg.sender == DEPOSITOR_ACCOUNT,\n \"L1Block: only the depositor account can set L1 block values\"\n );\n\n number = _number;\n timestamp = _timestamp;\n basefee = _basefee;\n hash = _hash;\n sequenceNumber = _sequenceNumber;\n batcherHash = _batcherHash;\n l1FeeOverhead = _l1FeeOverhead;\n l1FeeScalar = _l1FeeScalar;\n }\n}\n" - }, - "contracts/L2/L1FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x420000000000000000000000000000000000001A\n * @title L1FeeVault\n * @notice The L1FeeVault accumulates the L1 portion of the transaction fees.\n */\ncontract L1FeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.0.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}\n}\n" - }, - "contracts/L2/L2CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { L2ToL1MessagePasser } from \"./L2ToL1MessagePasser.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000007\n * @title L2CrossDomainMessenger\n * @notice The L2CrossDomainMessenger is a high-level interface for message passing between L1 and\n * L2 on the L2 side. Users are generally encouraged to use this contract instead of lower\n * level message passing contracts.\n */\ncontract L2CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _l1CrossDomainMessenger Address of the L1CrossDomainMessenger contract.\n */\n constructor(address _l1CrossDomainMessenger)\n Semver(1, 1, 0)\n CrossDomainMessenger(_l1CrossDomainMessenger)\n {\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote messenger. Use otherMessenger going forward.\n *\n * @return Address of the L1CrossDomainMessenger contract.\n */\n function l1CrossDomainMessenger() public view returns (address) {\n return OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)).initiateWithdrawal{\n value: _value\n }(_to, _gasLimit, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(Predeploys.L2_TO_L1_MESSAGE_PASSER);\n }\n}\n" - }, - "contracts/L2/L2ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721Bridge } from \"../universal/ERC721Bridge.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { IOptimismMintableERC721 } from \"../universal/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 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.1.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, 1, 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), \"L2ERC721Bridge: 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 \"L2ERC721Bridge: 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(OTHER_BRIDGE, message, _minGasLimit);\n\n // slither-disable-next-line reentrancy-events\n emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);\n }\n}\n" - }, - "contracts/L2/L2StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000010\n * @title L2StandardBridge\n * @notice The L2StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and\n * L2. In the case that an ERC20 token is native to L2, it will be escrowed within this\n * contract. If the ERC20 token is native to L1, it will be burnt.\n * NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples\n * of some token types that may not be properly supported by this contract include, but are\n * not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists.\n */\ncontract L2StandardBridge is StandardBridge, Semver {\n /**\n * @custom:legacy\n * @notice Emitted whenever a withdrawal from L2 to L1 is initiated.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the withdrawer.\n * @param to Address of the recipient on L1.\n * @param amount Amount of the ERC20 withdrawn.\n * @param extraData Extra data attached to the withdrawal.\n */\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:legacy\n * @notice Emitted whenever an ERC20 deposit is finalized.\n *\n * @param l1Token Address of the token on L1.\n * @param l2Token Address of the corresponding token on L2.\n * @param from Address of the depositor.\n * @param to Address of the recipient on L2.\n * @param amount Amount of the ERC20 deposited.\n * @param extraData Extra data attached to the deposit.\n */\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @param _otherBridge Address of the L1StandardBridge.\n */\n constructor(address payable _otherBridge)\n Semver(1, 1, 0)\n StandardBridge(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER), _otherBridge)\n {}\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n */\n receive() external payable override onlyEOA {\n _initiateWithdrawal(\n Predeploys.LEGACY_ERC20_ETH,\n msg.sender,\n msg.sender,\n msg.value,\n RECEIVE_DEFAULT_GAS_LIMIT,\n bytes(\"\")\n );\n }\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1.\n * This function only works with OptimismMintableERC20 tokens or ether. Use the\n * `bridgeERC20` function to bridge native L2 tokens to L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdraw(\n address _l2Token,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual onlyEOA {\n _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Initiates a withdrawal from L2 to L1 to a target account on L1.\n * Note that if ETH is sent to a contract on L1 and the call fails, then that ETH will\n * be locked in the L1StandardBridge. ETH may be recoverable if the call can be\n * successfully replayed by increasing the amount of gas supplied to the call. If the\n * call will fail for any amount of gas, then the ETH will be locked permanently.\n * This function only works with OptimismMintableERC20 tokens or ether. Use the\n * `bridgeERC20To` function to bridge native L2 tokens to L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function withdrawTo(\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable virtual {\n _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _minGasLimit, _extraData);\n }\n\n /**\n * @custom:legacy\n * @notice Finalizes a deposit from L1 to L2. To finalize a deposit of ether, use address(0)\n * and the l1Token and the Legacy ERC20 ether predeploy address as the l2Token.\n *\n * @param _l1Token Address of the L1 token to deposit.\n * @param _l2Token Address of the corresponding L2 token.\n * @param _from Address of the depositor.\n * @param _to Address of the recipient.\n * @param _amount Amount of the tokens being deposited.\n * @param _extraData Extra data attached to the deposit.\n */\n function finalizeDeposit(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) external payable virtual {\n if (_l1Token == address(0) && _l2Token == Predeploys.LEGACY_ERC20_ETH) {\n finalizeBridgeETH(_from, _to, _amount, _extraData);\n } else {\n finalizeBridgeERC20(_l2Token, _l1Token, _from, _to, _amount, _extraData);\n }\n }\n\n /**\n * @custom:legacy\n * @notice Retrieves the access of the corresponding L1 bridge contract.\n *\n * @return Address of the corresponding L1 bridge contract.\n */\n function l1TokenBridge() external view returns (address) {\n return address(OTHER_BRIDGE);\n }\n\n /**\n * @custom:legacy\n * @notice Internal function to a withdrawal from L2 to L1 to a target account on L1.\n *\n * @param _l2Token Address of the L2 token to withdraw.\n * @param _from Address of the withdrawer.\n * @param _to Recipient account on L1.\n * @param _amount Amount of the L2 token to withdraw.\n * @param _minGasLimit Minimum gas limit to use for the transaction.\n * @param _extraData Extra data attached to the withdrawal.\n */\n function _initiateWithdrawal(\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n if (_l2Token == Predeploys.LEGACY_ERC20_ETH) {\n _initiateBridgeETH(_from, _to, _amount, _minGasLimit, _extraData);\n } else {\n address l1Token = OptimismMintableERC20(_l2Token).l1Token();\n _initiateBridgeERC20(_l2Token, l1Token, _from, _to, _amount, _minGasLimit, _extraData);\n }\n }\n\n /**\n * @notice Emits the legacy WithdrawalInitiated event followed by the ETHBridgeInitiated event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit WithdrawalInitiated(\n address(0),\n Predeploys.LEGACY_ERC20_ETH,\n _from,\n _to,\n _amount,\n _extraData\n );\n super._emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy DepositFinalized event followed by the ETHBridgeFinalized event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit DepositFinalized(\n address(0),\n Predeploys.LEGACY_ERC20_ETH,\n _from,\n _to,\n _amount,\n _extraData\n );\n super._emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy WithdrawalInitiated event followed by the ERC20BridgeInitiated\n * event. This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit WithdrawalInitiated(_remoteToken, _localToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the legacy DepositFinalized event followed by the ERC20BridgeFinalized event.\n * This is necessary for backwards compatibility with the legacy bridge.\n *\n * @inheritdoc StandardBridge\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal override {\n emit DepositFinalized(_remoteToken, _localToken, _from, _to, _amount, _extraData);\n super._emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/L2/L2ToL1MessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000016\n * @title L2ToL1MessagePasser\n * @notice The L2ToL1MessagePasser is a dedicated contract where messages that are being sent from\n * L2 to L1 can be stored. The storage root of this contract is pulled up to the top level\n * of the L2 output to reduce the cost of proving the existence of sent messages.\n */\ncontract L2ToL1MessagePasser is Semver {\n /**\n * @notice The L1 gas limit set when eth is withdrawn using the receive() function.\n */\n uint256 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Current message version identifier.\n */\n uint16 public constant MESSAGE_VERSION = 1;\n\n /**\n * @notice Includes the message hashes for all withdrawals\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @notice A unique value hashed with each withdrawal.\n */\n uint240 internal msgNonce;\n\n /**\n * @notice Emitted any time a withdrawal is initiated.\n *\n * @param nonce Unique value corresponding to each withdrawal.\n * @param sender The L2 account address which initiated the withdrawal.\n * @param target The L1 account address the call will be send to.\n * @param value The ETH value submitted for withdrawal, to be forwarded to the target.\n * @param gasLimit The minimum amount of gas that must be provided when withdrawing.\n * @param data The data to be forwarded to the target on L1.\n * @param withdrawalHash The hash of the withdrawal.\n */\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n /**\n * @notice Emitted when the balance of this contract is burned.\n *\n * @param amount Amount of ETh that was burned.\n */\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Allows users to withdraw ETH by sending directly to this contract.\n */\n receive() external payable {\n initiateWithdrawal(msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @notice Removes all ETH held by this contract from the state. Used to prevent the amount of\n * ETH on L2 inflating when ETH is withdrawn. Currently only way to do this is to\n * create a contract and self-destruct it to itself. Anyone can call this function. Not\n * incentivized since this function is very cheap.\n */\n function burn() external {\n uint256 balance = address(this).balance;\n Burn.eth(balance);\n emit WithdrawerBalanceBurnt(balance);\n }\n\n /**\n * @notice Sends a message from L2 to L1.\n *\n * @param _target Address to call on L1 execution.\n * @param _gasLimit Minimum gas limit for executing the message on L1.\n * @param _data Data to forward to L1 target.\n */\n function initiateWithdrawal(\n address _target,\n uint256 _gasLimit,\n bytes memory _data\n ) public payable {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messageNonce(),\n sender: msg.sender,\n target: _target,\n value: msg.value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n sentMessages[withdrawalHash] = true;\n\n emit MessagePassed(\n messageNonce(),\n msg.sender,\n _target,\n msg.value,\n _gasLimit,\n _data,\n withdrawalHash\n );\n\n unchecked {\n ++msgNonce;\n }\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" - }, - "contracts/L2/SequencerFeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\nimport { FeeVault } from \"../universal/FeeVault.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000011\n * @title SequencerFeeVault\n * @notice The SequencerFeeVault is the contract that holds any fees paid to the Sequencer during\n * transaction processing and block production.\n */\ncontract SequencerFeeVault is FeeVault, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _recipient Address that will receive the accumulated fees.\n */\n constructor(address _recipient) FeeVault(_recipient, 10 ether) Semver(1, 1, 0) {}\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the recipient address.\n *\n * @return The recipient address.\n */\n function l1FeeWallet() public view returns (address) {\n return RECIPIENT;\n }\n}\n" - }, - "contracts/deployment/PortalSender.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/**\n * @title PortalSender\n * @notice The PortalSender is a simple intermediate contract that will transfer the balance of the\n * L1StandardBridge to the OptimismPortal during the Bedrock migration.\n */\ncontract PortalSender {\n /**\n * @notice Address of the OptimismPortal contract.\n */\n OptimismPortal public immutable PORTAL;\n\n /**\n * @param _portal Address of the OptimismPortal contract.\n */\n constructor(OptimismPortal _portal) {\n PORTAL = _portal;\n }\n\n /**\n * @notice Sends balance of this contract to the OptimismPortal.\n */\n function donate() public {\n PORTAL.donateETH{ value: address(this).balance }();\n }\n}\n" - }, - "contracts/deployment/SystemDictator.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { PortalSender } from \"./PortalSender.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\n/**\n * @title SystemDictator\n * @notice The SystemDictator is responsible for coordinating the deployment of a full Bedrock\n * system. The SystemDictator is designed to support both fresh network deployments and\n * upgrades to existing pre-Bedrock systems.\n */\ncontract SystemDictator is OwnableUpgradeable {\n /**\n * @notice Basic system configuration.\n */\n struct GlobalConfig {\n AddressManager addressManager;\n ProxyAdmin proxyAdmin;\n address controller;\n address finalOwner;\n }\n\n /**\n * @notice Set of proxy addresses.\n */\n struct ProxyAddressConfig {\n address l2OutputOracleProxy;\n address optimismPortalProxy;\n address l1CrossDomainMessengerProxy;\n address l1StandardBridgeProxy;\n address optimismMintableERC20FactoryProxy;\n address l1ERC721BridgeProxy;\n address systemConfigProxy;\n }\n\n /**\n * @notice Set of implementation addresses.\n */\n struct ImplementationAddressConfig {\n L2OutputOracle l2OutputOracleImpl;\n OptimismPortal optimismPortalImpl;\n L1CrossDomainMessenger l1CrossDomainMessengerImpl;\n L1StandardBridge l1StandardBridgeImpl;\n OptimismMintableERC20Factory optimismMintableERC20FactoryImpl;\n L1ERC721Bridge l1ERC721BridgeImpl;\n PortalSender portalSenderImpl;\n SystemConfig systemConfigImpl;\n }\n\n /**\n * @notice Dynamic L2OutputOracle config.\n */\n struct L2OutputOracleDynamicConfig {\n uint256 l2OutputOracleStartingBlockNumber;\n uint256 l2OutputOracleStartingTimestamp;\n }\n\n /**\n * @notice Values for the system config contract.\n */\n struct SystemConfigConfig {\n address owner;\n uint256 overhead;\n uint256 scalar;\n bytes32 batcherHash;\n uint64 gasLimit;\n address unsafeBlockSigner;\n ResourceMetering.ResourceConfig resourceConfig;\n }\n\n /**\n * @notice Combined system configuration.\n */\n struct DeployConfig {\n GlobalConfig globalConfig;\n ProxyAddressConfig proxyAddressConfig;\n ImplementationAddressConfig implementationAddressConfig;\n SystemConfigConfig systemConfigConfig;\n }\n\n /**\n * @notice Step after which exit 1 can no longer be used.\n */\n uint8 public constant EXIT_1_NO_RETURN_STEP = 3;\n\n /**\n * @notice Step where proxy ownership is transferred.\n */\n uint8 public constant PROXY_TRANSFER_STEP = 4;\n\n /**\n * @notice System configuration.\n */\n DeployConfig public config;\n\n /**\n * @notice Dynamic configuration for the L2OutputOracle.\n */\n L2OutputOracleDynamicConfig public l2OutputOracleDynamicConfig;\n\n /**\n * @notice Dynamic configuration for the OptimismPortal. Determines\n * if the system should be paused when initialized.\n */\n bool public optimismPortalDynamicConfig;\n\n /**\n * @notice Current step;\n */\n uint8 public currentStep;\n\n /**\n * @notice Whether or not dynamic config has been set.\n */\n bool public dynamicConfigSet;\n\n /**\n * @notice Whether or not the deployment is finalized.\n */\n bool public finalized;\n\n /**\n * @notice Whether or not the deployment has been exited.\n */\n bool public exited;\n\n /**\n * @notice Address of the old L1CrossDomainMessenger implementation.\n */\n address public oldL1CrossDomainMessenger;\n\n /**\n * @notice Checks that the current step is the expected step, then bumps the current step.\n *\n * @param _step Current step.\n */\n modifier step(uint8 _step) {\n require(!finalized, \"SystemDictator: already finalized\");\n require(!exited, \"SystemDictator: already exited\");\n require(currentStep == _step, \"SystemDictator: incorrect step\");\n _;\n currentStep++;\n }\n\n /**\n * @notice Constructor required to ensure that the implementation of the SystemDictator is\n * initialized upon deployment.\n */\n constructor() {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n // Using this shorter variable as an alias for address(0) just prevents us from having to\n // to use a new line for every single parameter.\n address zero = address(0);\n initialize(\n DeployConfig(\n GlobalConfig(AddressManager(zero), ProxyAdmin(zero), zero, zero),\n ProxyAddressConfig(zero, zero, zero, zero, zero, zero, zero),\n ImplementationAddressConfig(\n L2OutputOracle(zero),\n OptimismPortal(payable(zero)),\n L1CrossDomainMessenger(zero),\n L1StandardBridge(payable(zero)),\n OptimismMintableERC20Factory(zero),\n L1ERC721Bridge(zero),\n PortalSender(zero),\n SystemConfig(zero)\n ),\n SystemConfigConfig(zero, 0, 0, bytes32(0), 0, zero, rcfg)\n )\n );\n }\n\n /**\n * @param _config System configuration.\n */\n function initialize(DeployConfig memory _config) public initializer {\n config = _config;\n currentStep = 1;\n __Ownable_init();\n _transferOwnership(config.globalConfig.controller);\n }\n\n /**\n * @notice Allows the owner to update dynamic config.\n *\n * @param _l2OutputOracleDynamicConfig Dynamic L2OutputOracle config.\n * @param _optimismPortalDynamicConfig Dynamic OptimismPortal config.\n */\n function updateDynamicConfig(\n L2OutputOracleDynamicConfig memory _l2OutputOracleDynamicConfig,\n bool _optimismPortalDynamicConfig\n ) external onlyOwner {\n l2OutputOracleDynamicConfig = _l2OutputOracleDynamicConfig;\n optimismPortalDynamicConfig = _optimismPortalDynamicConfig;\n dynamicConfigSet = true;\n }\n\n /**\n * @notice Configures the ProxyAdmin contract.\n */\n function step1() external onlyOwner step(1) {\n // Set the AddressManager in the ProxyAdmin.\n config.globalConfig.proxyAdmin.setAddressManager(config.globalConfig.addressManager);\n\n // Set the L1CrossDomainMessenger to the RESOLVED proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n ProxyAdmin.ProxyType.RESOLVED\n );\n\n // Set the implementation name for the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.setImplementationName(\n config.proxyAddressConfig.l1CrossDomainMessengerProxy,\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Set the L1StandardBridge to the CHUGSPLASH proxy type.\n config.globalConfig.proxyAdmin.setProxyType(\n config.proxyAddressConfig.l1StandardBridgeProxy,\n ProxyAdmin.ProxyType.CHUGSPLASH\n );\n\n // Upgrade and initialize the SystemConfig so the Sequencer can start up.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.systemConfigProxy),\n address(config.implementationAddressConfig.systemConfigImpl),\n abi.encodeCall(\n SystemConfig.initialize,\n (\n config.systemConfigConfig.owner,\n config.systemConfigConfig.overhead,\n config.systemConfigConfig.scalar,\n config.systemConfigConfig.batcherHash,\n config.systemConfigConfig.gasLimit,\n config.systemConfigConfig.unsafeBlockSigner,\n config.systemConfigConfig.resourceConfig\n )\n )\n );\n }\n\n /**\n * @notice Pauses the system by shutting down the L1CrossDomainMessenger and setting the\n * deposit halt flag to tell the Sequencer's DTL to stop accepting deposits.\n */\n function step2() external onlyOwner step(2) {\n // Store the address of the old L1CrossDomainMessenger implementation. We will need this\n // address in the case that we have to exit early.\n oldL1CrossDomainMessenger = config.globalConfig.addressManager.getAddress(\n \"OVM_L1CrossDomainMessenger\"\n );\n\n // Temporarily brick the L1CrossDomainMessenger by setting its implementation address to\n // address(0) which will cause the ResolvedDelegateProxy to revert. Better than pausing\n // the L1CrossDomainMessenger via pause() because it can be easily reverted.\n config.globalConfig.addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(0));\n\n // Set the DTL shutoff block, which will tell the DTL to stop syncing new deposits from the\n // CanonicalTransactionChain. We do this by setting an address in the AddressManager\n // because the DTL already has a reference to the AddressManager and this way we don't also\n // need to give it a reference to the SystemDictator.\n config.globalConfig.addressManager.setAddress(\n \"DTL_SHUTOFF_BLOCK\",\n address(uint160(block.number))\n );\n }\n\n /**\n * @notice Removes deprecated addresses from the AddressManager.\n */\n function step3() external onlyOwner step(EXIT_1_NO_RETURN_STEP) {\n // Remove all deprecated addresses from the AddressManager\n string[17] memory deprecated = [\n \"OVM_CanonicalTransactionChain\",\n \"OVM_L2CrossDomainMessenger\",\n \"OVM_DecompressionPrecompileAddress\",\n \"OVM_Sequencer\",\n \"OVM_Proposer\",\n \"OVM_ChainStorageContainer-CTC-batches\",\n \"OVM_ChainStorageContainer-CTC-queue\",\n \"OVM_CanonicalTransactionChain\",\n \"OVM_StateCommitmentChain\",\n \"OVM_BondManager\",\n \"OVM_ExecutionManager\",\n \"OVM_FraudVerifier\",\n \"OVM_StateManagerFactory\",\n \"OVM_StateTransitionerFactory\",\n \"OVM_SafetyChecker\",\n \"OVM_L1MultiMessageRelayer\",\n \"BondManager\"\n ];\n\n for (uint256 i = 0; i < deprecated.length; i++) {\n config.globalConfig.addressManager.setAddress(deprecated[i], address(0));\n }\n }\n\n /**\n * @notice Transfers system ownership to the ProxyAdmin.\n */\n function step4() external onlyOwner step(PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the ProxyAdmin.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1StandardBridge to the ProxyAdmin.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.proxyAdmin)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the ProxyAdmin.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.proxyAdmin)\n );\n }\n\n /**\n * @notice Upgrades and initializes proxy contracts.\n */\n function step5() external onlyOwner step(5) {\n // Dynamic config must be set before we can initialize the L2OutputOracle.\n require(dynamicConfigSet, \"SystemDictator: dynamic oracle config is not yet initialized\");\n\n // Upgrade and initialize the L2OutputOracle.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l2OutputOracleProxy),\n address(config.implementationAddressConfig.l2OutputOracleImpl),\n abi.encodeCall(\n L2OutputOracle.initialize,\n (\n l2OutputOracleDynamicConfig.l2OutputOracleStartingBlockNumber,\n l2OutputOracleDynamicConfig.l2OutputOracleStartingTimestamp\n )\n )\n );\n\n // Upgrade and initialize the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.optimismPortalProxy),\n address(config.implementationAddressConfig.optimismPortalImpl),\n abi.encodeCall(OptimismPortal.initialize, (optimismPortalDynamicConfig))\n );\n\n // Upgrade the L1CrossDomainMessenger.\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1CrossDomainMessengerProxy),\n address(config.implementationAddressConfig.l1CrossDomainMessengerImpl)\n );\n\n // Try to initialize the L1CrossDomainMessenger, only fail if it's already been initialized.\n try\n L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy)\n .initialize()\n {\n // L1CrossDomainMessenger is the one annoying edge case difference between existing\n // networks and fresh networks because in existing networks it'll already be\n // initialized but in fresh networks it won't be. Try/catch is the easiest and most\n // consistent way to handle this because initialized() is not exposed publicly.\n } catch Error(string memory reason) {\n require(\n keccak256(abi.encodePacked(reason)) ==\n keccak256(\"Initializable: contract is already initialized\"),\n string.concat(\"SystemDictator: unexpected error initializing L1XDM: \", reason)\n );\n } catch {\n revert(\"SystemDictator: unexpected error initializing L1XDM (no reason)\");\n }\n\n // Transfer ETH from the L1StandardBridge to the OptimismPortal.\n config.globalConfig.proxyAdmin.upgradeAndCall(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.portalSenderImpl),\n abi.encodeCall(PortalSender.donate, ())\n );\n\n // Upgrade the L1StandardBridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1StandardBridgeProxy),\n address(config.implementationAddressConfig.l1StandardBridgeImpl)\n );\n\n // Upgrade the OptimismMintableERC20Factory (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.optimismMintableERC20FactoryProxy),\n address(config.implementationAddressConfig.optimismMintableERC20FactoryImpl)\n );\n\n // Upgrade the L1ERC721Bridge (no initializer).\n config.globalConfig.proxyAdmin.upgrade(\n payable(config.proxyAddressConfig.l1ERC721BridgeProxy),\n address(config.implementationAddressConfig.l1ERC721BridgeImpl)\n );\n }\n\n /**\n * @notice Tranfers admin ownership to the final owner.\n */\n function finalize() external onlyOwner {\n // Transfer ownership of the ProxyAdmin to the final owner.\n config.globalConfig.proxyAdmin.transferOwnership(config.globalConfig.finalOwner);\n\n // Optionally also transfer AddressManager and L1StandardBridge if we still own it. Might\n // happen if we're exiting early.\n if (currentStep <= PROXY_TRANSFER_STEP) {\n // Transfer ownership of the AddressManager to the final owner.\n config.globalConfig.addressManager.transferOwnership(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1StandardBridge to the final owner.\n L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(\n address(config.globalConfig.finalOwner)\n );\n\n // Transfer ownership of the L1ERC721Bridge to the final owner.\n Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(\n address(config.globalConfig.finalOwner)\n );\n }\n\n // Mark the deployment as finalized.\n finalized = true;\n }\n\n /**\n * @notice First exit point, can only be called before step 3 is executed.\n */\n function exit1() external onlyOwner {\n require(\n currentStep == EXIT_1_NO_RETURN_STEP,\n \"SystemDictator: can only exit1 before step 3 is executed\"\n );\n\n // Reset the L1CrossDomainMessenger to the old implementation.\n config.globalConfig.addressManager.setAddress(\n \"OVM_L1CrossDomainMessenger\",\n oldL1CrossDomainMessenger\n );\n\n // Unset the DTL shutoff block which will allow the DTL to sync again.\n config.globalConfig.addressManager.setAddress(\"DTL_SHUTOFF_BLOCK\", address(0));\n\n // Mark the deployment as exited.\n exited = true;\n }\n}\n" - }, - "contracts/echidna/FuzzAddressAliasing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract EchidnaFuzzAddressAliasing {\n bool internal failedRoundtrip;\n\n /**\n * @notice Takes an address to be aliased with AddressAliasHelper and then unaliased\n * and updates the test contract's state indicating if the round trip encoding\n * failed.\n */\n function testRoundTrip(address addr) public {\n // Alias our address\n address aliasedAddr = AddressAliasHelper.applyL1ToL2Alias(addr);\n\n // Unalias our address\n address undoneAliasAddr = AddressAliasHelper.undoL1ToL2Alias(aliasedAddr);\n\n // If our round trip aliasing did not return the original result, set our state.\n if (addr != undoneAliasAddr) {\n failedRoundtrip = true;\n }\n }\n\n /**\n * @custom:invariant Address aliases are always able to be undone.\n *\n * Asserts that an address that has been aliased with `applyL1ToL2Alias` can always\n * be unaliased with `undoL1ToL2Alias`.\n */\n function echidna_round_trip_aliasing() public view returns (bool) {\n // ASSERTION: The round trip aliasing done in testRoundTrip(...) should never fail.\n return !failedRoundtrip;\n }\n}\n" - }, - "contracts/echidna/FuzzBurn.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\n\ncontract EchidnaFuzzBurnEth is StdUtils {\n bool internal failedEthBurn;\n\n /**\n * @notice Takes an integer amount of eth to burn through the Burn library and\n * updates the contract state if an incorrect amount of eth moved from the contract\n */\n function testBurn(uint256 _value) public {\n // cache the contract's eth balance\n uint256 preBurnBalance = address(this).balance;\n uint256 value = bound(_value, 0, preBurnBalance);\n\n // execute a burn of _value eth\n Burn.eth(value);\n\n // check that exactly value eth was transfered from the contract\n unchecked {\n if (address(this).balance != preBurnBalance - value) {\n failedEthBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `eth(uint256)` always burns the exact amount of eth passed.\n *\n * Asserts that when `Burn.eth(uint256)` is called, it always burns the exact amount\n * of ETH passed to the function.\n */\n function echidna_burn_eth() public view returns (bool) {\n // ASSERTION: The amount burned should always match the amount passed exactly\n return !failedEthBurn;\n }\n}\n\ncontract EchidnaFuzzBurnGas is StdUtils {\n bool internal failedGasBurn;\n\n /**\n * @notice Takes an integer amount of gas to burn through the Burn library and\n * updates the contract state if at least that amount of gas was not burned\n * by the library\n */\n function testGas(uint256 _value) public {\n // cap the value to the max resource limit\n uint256 MAX_RESOURCE_LIMIT = 8_000_000;\n uint256 value = bound(_value, 0, MAX_RESOURCE_LIMIT);\n\n // cache the contract's current remaining gas\n uint256 preBurnGas = gasleft();\n\n // execute the gas burn\n Burn.gas(value);\n\n // cache the remaining gas post burn\n uint256 postBurnGas = gasleft();\n\n // check that at least value gas was burnt (and that there was no underflow)\n unchecked {\n if (postBurnGas - preBurnGas > value || preBurnGas - value > preBurnGas) {\n failedGasBurn = true;\n }\n }\n }\n\n /**\n * @custom:invariant `gas(uint256)` always burns at least the amount of gas passed.\n *\n * Asserts that when `Burn.gas(uint256)` is called, it always burns at least the amount\n * of gas passed to the function.\n */\n function echidna_burn_gas() public view returns (bool) {\n // ASSERTION: The amount of gas burned should be strictly greater than the\n // the amount passed as _value (minimum _value + whatever minor overhead to\n // the value after the call)\n return !failedGasBurn;\n }\n}\n" - }, - "contracts/echidna/FuzzEncoding.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzEncoding {\n bool internal failedRoundtripAToB;\n bool internal failedRoundtripBToA;\n\n /**\n * @notice Takes a pair of integers to be encoded into a versioned nonce with the\n * Encoding library and then decoded and updates the test contract's state\n * indicating if the round trip encoding failed.\n */\n function testRoundTripAToB(uint240 _nonce, uint16 _version) public {\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(encodedVersionedNonce);\n\n // If our round trip encoding did not return the original result, set our state.\n if ((decodedNonce != _nonce) || (decodedVersion != _version)) {\n failedRoundtripAToB = true;\n }\n }\n\n /**\n * @notice Takes an integer representing a packed version and nonce and attempts\n * to decode them using the Encoding library before re-encoding and updates\n * the test contract's state indicating if the round trip encoding failed.\n */\n function testRoundTripBToA(uint256 _versionedNonce) public {\n // Decode the nonce and version\n uint240 decodedNonce;\n uint16 decodedVersion;\n\n (decodedNonce, decodedVersion) = Encoding.decodeVersionedNonce(_versionedNonce);\n\n // Encode the nonce and version\n uint256 encodedVersionedNonce = Encoding.encodeVersionedNonce(decodedNonce, decodedVersion);\n\n // If our round trip encoding did not return the original result, set our state.\n if (encodedVersionedNonce != _versionedNonce) {\n failedRoundtripBToA = true;\n }\n }\n\n /**\n * @custom:invariant `testRoundTripAToB` never fails.\n *\n * Asserts that a raw versioned nonce can be encoded / decoded to reach the same raw value.\n */\n function echidna_round_trip_encoding_AToB() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripAToB(...)\n return !failedRoundtripAToB;\n }\n\n /**\n * @custom:invariant `testRoundTripBToA` never fails.\n *\n * Asserts that an encoded versioned nonce can always be decoded / re-encoded to reach\n * the same encoded value.\n */\n function echidna_round_trip_encoding_BToA() public view returns (bool) {\n // ASSERTION: The round trip encoding done in testRoundTripBToA should never\n // fail.\n return !failedRoundtripBToA;\n }\n}\n" - }, - "contracts/echidna/FuzzHashing.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract EchidnaFuzzHashing {\n bool internal failedCrossDomainHashHighVersion;\n bool internal failedCrossDomainHashV0;\n bool internal failedCrossDomainHashV1;\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash with a randomly\n * generated version. Only schema versions 0 and 1 are supported and all others should revert.\n */\n function testHashCrossDomainMessageHighVersion(\n uint16 _version,\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, _version);\n\n // hash the cross domain message. we don't need to store the result since the function\n // validates and should revert if an invalid version (>1) is encoded\n Hashing.hashCrossDomainMessage(encodedNonce, _sender, _target, _value, _gasLimit, _data);\n\n // check that execution never makes it this far for an invalid version\n if (_version > 1) {\n failedCrossDomainHashHighVersion = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v0 schema\n * and compares the output of a call to the unversioned function to the v0 function directly\n */\n function testHashCrossDomainMessageV0(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 0\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 0);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV0(\n _target,\n _sender,\n _data,\n encodedNonce\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV0 = true;\n }\n }\n\n /**\n * @notice Takes the necessary parameters to perform a cross domain hash using the v1 schema\n * and compares the output of a call to the unversioned function to the v1 function directly\n */\n function testHashCrossDomainMessageV1(\n uint240 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) public {\n // generate the versioned nonce with the version set to 1\n uint256 encodedNonce = Encoding.encodeVersionedNonce(_nonce, 1);\n\n // hash the cross domain message using the unversioned and versioned functions for\n // comparison\n bytes32 sampleHash1 = Hashing.hashCrossDomainMessage(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n bytes32 sampleHash2 = Hashing.hashCrossDomainMessageV1(\n encodedNonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n // check that the output of both functions matches\n if (sampleHash1 != sampleHash2) {\n failedCrossDomainHashV1 = true;\n }\n }\n\n /**\n * @custom:invariant `hashCrossDomainMessage` reverts if `version` is > `1`.\n *\n * The `hashCrossDomainMessage` function should always revert if the `version` passed is > `1`.\n */\n function echidna_hash_xdomain_msg_high_version() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage will never succeed for a version > 1\n return !failedCrossDomainHashHighVersion;\n }\n\n /**\n * @custom:invariant `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0`\n * are equivalent.\n *\n * If the version passed is 0, `hashCrossDomainMessage` and `hashCrossDomainMessageV0` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_0() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV0\n // should always match when the version passed is 0\n return !failedCrossDomainHashV0;\n }\n\n /**\n * @custom:invariant `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1`\n * are equivalent.\n *\n * If the version passed is 1, `hashCrossDomainMessage` and `hashCrossDomainMessageV1` should be\n * equivalent.\n */\n function echidna_hash_xdomain_msg_1() public view returns (bool) {\n // ASSERTION: A call to hashCrossDomainMessage and hashCrossDomainMessageV1\n // should always match when the version passed is 1\n return !failedCrossDomainHashV1;\n }\n}\n" - }, - "contracts/echidna/FuzzOptimismPortal.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract EchidnaFuzzOptimismPortal {\n OptimismPortal internal portal;\n bool internal failedToComplete;\n\n constructor() {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n SystemConfig systemConfig = new SystemConfig({\n _owner: address(1),\n _overhead: 0,\n _scalar: 10000,\n _batcherHash: bytes32(0),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(0),\n _config: rcfg\n });\n\n portal = new OptimismPortal({\n _l2Oracle: L2OutputOracle(address(0)),\n _guardian: address(0),\n _paused: false,\n _config: systemConfig\n });\n }\n\n // A test intended to identify any unexpected halting conditions\n function testDepositTransactionCompletes(\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) public payable {\n failedToComplete = true;\n require(!_isCreation || _to == address(0), \"EchidnaFuzzOptimismPortal: invalid test case.\");\n portal.depositTransaction{ value: _mint }(_to, _value, _gasLimit, _isCreation, _data);\n failedToComplete = false;\n }\n\n /**\n * @custom:invariant Deposits of any value should always succeed unless\n * `_to` = `address(0)` or `_isCreation` = `true`.\n *\n * All deposits, barring creation transactions and transactions sent to `address(0)`,\n * should always succeed.\n */\n function echidna_deposit_completes() public view returns (bool) {\n return !failedToComplete;\n }\n}\n" - }, - "contracts/echidna/FuzzResourceMetering.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\nimport { StdUtils } from \"forge-std/Test.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {\n bool internal failedMaxGasPerBlock;\n bool internal failedRaiseBaseFee;\n bool internal failedLowerBaseFee;\n bool internal failedNeverBelowMinBaseFee;\n bool internal failedMaxRaiseBaseFeePerBlock;\n bool internal failedMaxLowerBaseFeePerBlock;\n\n // Used as a special flag for the purpose of identifying unchecked math errors specifically\n // in the test contracts, not the target contracts themselves.\n bool internal underflow;\n\n constructor() {\n initialize();\n }\n\n function initialize() internal initializer {\n __ResourceMetering_init();\n }\n\n function resourceConfig() public pure returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig();\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG();\n return rcfg;\n }\n\n /**\n * @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test\n * the underlying resource metering/gas market logic\n */\n function testBurn(uint256 _gasToBurn, bool _raiseBaseFee) public {\n // Part 1: we cache the current param values and do some basic checks on them.\n uint256 cachedPrevBaseFee = uint256(params.prevBaseFee);\n uint256 cachedPrevBoughtGas = uint256(params.prevBoughtGas);\n uint256 cachedPrevBlockNum = uint256(params.prevBlockNum);\n\n ResourceMetering.ResourceConfig memory rcfg = resourceConfig();\n uint256 targetResourceLimit = uint256(rcfg.maxResourceLimit) /\n uint256(rcfg.elasticityMultiplier);\n\n // check that the last block's base fee hasn't dropped below the minimum\n if (cachedPrevBaseFee < uint256(rcfg.minimumBaseFee)) {\n failedNeverBelowMinBaseFee = true;\n }\n // check that the last block didn't consume more than the max amount of gas\n if (cachedPrevBoughtGas > uint256(rcfg.maxResourceLimit)) {\n failedMaxGasPerBlock = true;\n }\n\n // Part2: we perform the gas burn\n\n // force the gasToBurn into the correct range based on whether we intend to\n // raise or lower the baseFee after this block, respectively\n uint256 gasToBurn;\n if (_raiseBaseFee) {\n gasToBurn = bound(\n _gasToBurn,\n uint256(targetResourceLimit),\n uint256(rcfg.maxResourceLimit)\n );\n } else {\n gasToBurn = bound(_gasToBurn, 0, targetResourceLimit);\n }\n\n _burnInternal(uint64(gasToBurn));\n\n // Part 3: we run checks and modify our invariant flags based on the updated params values\n\n // Calculate the maximum allowed baseFee change (per block)\n uint256 maxBaseFeeChange = cachedPrevBaseFee / uint256(rcfg.baseFeeMaxChangeDenominator);\n\n // If the last block used more than the target amount of gas (and there were no\n // empty blocks in between), ensure this block's baseFee increased, but not by\n // more than the max amount per block\n if (\n (cachedPrevBoughtGas > uint256(targetResourceLimit)) &&\n (uint256(params.prevBlockNum) - cachedPrevBlockNum == 1)\n ) {\n failedRaiseBaseFee = failedRaiseBaseFee || (params.prevBaseFee <= cachedPrevBaseFee);\n failedMaxRaiseBaseFeePerBlock =\n failedMaxRaiseBaseFeePerBlock ||\n ((uint256(params.prevBaseFee) - cachedPrevBaseFee) < maxBaseFeeChange);\n }\n\n // If the last block used less than the target amount of gas, (or was empty),\n // ensure that: this block's baseFee was decreased, but not by more than the max amount\n if (\n (cachedPrevBoughtGas < uint256(targetResourceLimit)) ||\n (uint256(params.prevBlockNum) - cachedPrevBlockNum > 1)\n ) {\n // Invariant: baseFee should decrease\n failedLowerBaseFee =\n failedLowerBaseFee ||\n (uint256(params.prevBaseFee) > cachedPrevBaseFee);\n\n if (params.prevBlockNum - cachedPrevBlockNum == 1) {\n // No empty blocks\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n } else if (params.prevBlockNum - cachedPrevBlockNum > 1) {\n // We have at least one empty block\n // Update the maxBaseFeeChange to account for multiple blocks having passed\n unchecked {\n maxBaseFeeChange = uint256(\n int256(cachedPrevBaseFee) -\n Arithmetic.clamp(\n Arithmetic.cdexp(\n int256(cachedPrevBaseFee),\n int256(uint256(rcfg.baseFeeMaxChangeDenominator)),\n int256(uint256(params.prevBlockNum) - cachedPrevBlockNum)\n ),\n int256(uint256(rcfg.minimumBaseFee)),\n int256(uint256(rcfg.maximumBaseFee))\n )\n );\n }\n\n // Detect an underflow in the previous calculation.\n // Without using unchecked above, and detecting the underflow here, echidna would\n // otherwise ignore the revert.\n underflow = underflow || maxBaseFeeChange > cachedPrevBaseFee;\n\n // Invariant: baseFee should not have decreased by more than the maximum amount\n failedMaxLowerBaseFeePerBlock =\n failedMaxLowerBaseFeePerBlock ||\n ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);\n }\n }\n }\n\n function _burnInternal(uint64 _gasToBurn) private metered(_gasToBurn) {}\n\n /**\n * @custom:invariant The base fee should increase if the last block used more\n * than the target amount of gas\n *\n * If the last block used more than the target amount of gas (and there were no\n * empty blocks in between), ensure this block's baseFee increased, but not by\n * more than the max amount per block.\n */\n function echidna_high_usage_raise_baseFee() public view returns (bool) {\n return !failedRaiseBaseFee;\n }\n\n /**\n * @custom:invariant The base fee should decrease if the last block used less\n * than the target amount of gas\n *\n * If the previous block used less than the target amount of gas, the base fee should decrease,\n * but not more than the max amount.\n */\n function echidna_low_usage_lower_baseFee() public view returns (bool) {\n return !failedLowerBaseFee;\n }\n\n /**\n * @custom:invariant A block's base fee should never be below `MINIMUM_BASE_FEE`\n *\n * This test asserts that a block's base fee can never drop below the\n * `MINIMUM_BASE_FEE` threshold.\n */\n function echidna_never_below_min_baseFee() public view returns (bool) {\n return !failedNeverBelowMinBaseFee;\n }\n\n /**\n * @custom:invariant A block can never consume more than `MAX_RESOURCE_LIMIT` gas.\n *\n * This test asserts that a block can never consume more than the `MAX_RESOURCE_LIMIT`\n * gas threshold.\n */\n function echidna_never_above_max_gas_limit() public view returns (bool) {\n return !failedMaxGasPerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be raised more than the max base fee change.\n *\n * After a block consumes more gas than the target gas, the base fee cannot be raised\n * more than the maximum amount allowed. The max base fee change (per-block) is derived\n * as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_increase() public view returns (bool) {\n return !failedMaxRaiseBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The base fee can never be lowered more than the max base fee change.\n *\n * After a block consumes less than the target gas, the base fee cannot be lowered more\n * than the maximum amount allowed. The max base fee change (per-block) is derived as\n *follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR`\n */\n function echidna_never_exceed_max_decrease() public view returns (bool) {\n return !failedMaxLowerBaseFeePerBlock;\n }\n\n /**\n * @custom:invariant The `maxBaseFeeChange` calculation over multiple blocks can never\n * underflow.\n *\n * When calculating the `maxBaseFeeChange` after multiple empty blocks, the calculation\n * should never be allowed to underflow.\n */\n function echidna_underflow() public view returns (bool) {\n return !underflow;\n }\n}\n" - }, - "contracts/governance/GovernanceToken.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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 * @custom:predeploy 0x4200000000000000000000000000000000000042\n * @title GovernanceToken\n * @notice The Optimism token used in governance and supporting voting and delegation. Implements\n * EIP 2612 allowing signed approvals. Contract is \"owned\" by a `MintManager` instance with\n * permission to the `mint` function only, for the purposes of enforcing the token inflation\n * schedule.\n */\ncontract GovernanceToken is ERC20Burnable, ERC20Votes, Ownable {\n constructor() ERC20(\"Optimism\", \"OP\") ERC20Permit(\"Optimism\") {}\n\n /**\n * @notice Allows the owner to mint tokens.\n *\n * @param _account The account receiving minted tokens.\n * @param _amount The amount of tokens to mint.\n */\n function mint(address _account, uint256 _amount) public onlyOwner {\n _mint(_account, _amount);\n }\n\n /**\n * @notice Callback called after a token transfer.\n *\n * @param from The account sending tokens.\n * @param to The account receiving tokens.\n * @param amount The amount of tokens being transfered.\n */\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 /**\n * @notice Internal mint function.\n *\n * @param to The account receiving minted tokens.\n * @param amount The amount of tokens to mint.\n */\n function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._mint(to, amount);\n }\n\n /**\n * @notice Internal burn function.\n *\n * @param account The account that tokens will be burned from.\n * @param amount The amount of tokens that will be burned.\n */\n function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) {\n super._burn(account, amount);\n }\n}\n" - }, - "contracts/governance/MintManager.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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(\n mintPermittedAfter <= block.timestamp,\n \"MintManager: minting not permitted yet\"\n );\n\n require(\n _amount <= (governanceToken.totalSupply() * MINT_CAP) / DENOMINATOR,\n \"MintManager: mint amount exceeds cap\"\n );\n }\n\n mintPermittedAfter = block.timestamp + MINT_PERIOD;\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(\n _newMintManager != address(0),\n \"MintManager: mint manager cannot be the zero address\"\n );\n\n governanceToken.transferOwnership(_newMintManager);\n }\n}\n" - }, - "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" - }, - "contracts/legacy/DeployerWhitelist.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000002\n * @title DeployerWhitelist\n * @notice DeployerWhitelist is a legacy contract that was originally used to act as a whitelist of\n * addresses allowed to the Optimism network. The DeployerWhitelist has since been\n * disabled, but the code is kept in state for the sake of full backwards compatibility.\n * As of the Bedrock upgrade, the DeployerWhitelist is completely unused by the Optimism\n * system and could, in theory, be removed entirely.\n */\ncontract DeployerWhitelist is Semver {\n /**\n * @notice Address of the owner of this contract. Note that when this address is set to\n * address(0), the whitelist is disabled.\n */\n address public owner;\n\n /**\n * @notice Mapping of deployer addresses to boolean whitelist status.\n */\n mapping(address => bool) public whitelist;\n\n /**\n * @notice Emitted when the owner of this contract changes.\n *\n * @param oldOwner Address of the previous owner.\n * @param newOwner Address of the new owner.\n */\n event OwnerChanged(address oldOwner, address newOwner);\n\n /**\n * @notice Emitted when the whitelist status of a deployer changes.\n *\n * @param deployer Address of the deployer.\n * @param whitelisted Boolean indicating whether the deployer is whitelisted.\n */\n event WhitelistStatusChanged(address deployer, bool whitelisted);\n\n /**\n * @notice Emitted when the whitelist is disabled.\n *\n * @param oldOwner Address of the final owner of the whitelist.\n */\n event WhitelistDisabled(address oldOwner);\n\n /**\n * @notice Blocks functions to anyone except the contract owner.\n */\n modifier onlyOwner() {\n require(\n msg.sender == owner,\n \"DeployerWhitelist: function can only be called by the owner of this contract\"\n );\n _;\n }\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Adds or removes an address from the deployment whitelist.\n *\n * @param _deployer Address to update permissions for.\n * @param _isWhitelisted Whether or not the address is whitelisted.\n */\n function setWhitelistedDeployer(address _deployer, bool _isWhitelisted) external onlyOwner {\n whitelist[_deployer] = _isWhitelisted;\n emit WhitelistStatusChanged(_deployer, _isWhitelisted);\n }\n\n /**\n * @notice Updates the owner of this contract.\n *\n * @param _owner Address of the new owner.\n */\n function setOwner(address _owner) external onlyOwner {\n // Prevent users from setting the whitelist owner to address(0) except via\n // enableArbitraryContractDeployment. If you want to burn the whitelist owner, send it to\n // any other address that doesn't have a corresponding knowable private key.\n require(\n _owner != address(0),\n \"DeployerWhitelist: can only be disabled via enableArbitraryContractDeployment\"\n );\n\n emit OwnerChanged(owner, _owner);\n owner = _owner;\n }\n\n /**\n * @notice Permanently enables arbitrary contract deployment and deletes the owner.\n */\n function enableArbitraryContractDeployment() external onlyOwner {\n emit WhitelistDisabled(owner);\n owner = address(0);\n }\n\n /**\n * @notice Checks whether an address is allowed to deploy contracts.\n *\n * @param _deployer Address to check.\n *\n * @return Whether or not the address can deploy contracts.\n */\n function isDeployerAllowed(address _deployer) external view returns (bool) {\n return (owner == address(0) || whitelist[_deployer]);\n }\n}\n" - }, - "contracts/legacy/L1BlockNumber.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000013\n * @title L1BlockNumber\n * @notice L1BlockNumber is a legacy contract that fills the roll of the OVM_L1BlockNumber contract\n * in the old version of the Optimism system. Only necessary for backwards compatibility.\n * If you want to access the L1 block number going forward, you should use the L1Block\n * contract instead.\n */\ncontract L1BlockNumber is Semver {\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Returns the L1 block number.\n */\n receive() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Returns the L1 block number.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n uint256 l1BlockNumber = getL1BlockNumber();\n assembly {\n mstore(0, l1BlockNumber)\n return(0, 32)\n }\n }\n\n /**\n * @notice Retrieves the latest L1 block number.\n *\n * @return Latest L1 block number.\n */\n function getL1BlockNumber() public view returns (uint256) {\n return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).number();\n }\n}\n" - }, - "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/legacy/LegacyERC20ETH.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000\n * @title LegacyERC20ETH\n * @notice LegacyERC20ETH is a legacy contract that held ETH balances before the Bedrock upgrade.\n * All ETH balances held within this contract were migrated to the state trie as part of\n * the Bedrock upgrade. Functions within this contract that mutate state were already\n * disabled as part of the EVM equivalence upgrade.\n */\ncontract LegacyERC20ETH is OptimismMintableERC20 {\n /**\n * @notice Initializes the contract as an Optimism Mintable ERC20.\n */\n constructor()\n OptimismMintableERC20(Predeploys.L2_STANDARD_BRIDGE, address(0), \"Ether\", \"ETH\")\n {}\n\n /**\n * @notice Returns the ETH balance of the target account. Overrides the base behavior of the\n * contract to preserve the invariant that the balance within this contract always\n * matches the balance in the state trie.\n *\n * @param _who Address of the account to query.\n *\n * @return The ETH balance of the target account.\n */\n function balanceOf(address _who) public view virtual override returns (uint256) {\n return address(_who).balance;\n }\n\n /**\n * @custom:blocked\n * @notice Mints some amount of ETH.\n */\n function mint(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: mint is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Burns some amount of ETH.\n */\n function burn(address, uint256) public virtual override {\n revert(\"LegacyERC20ETH: burn is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers some amount of ETH.\n */\n function transfer(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transfer is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Approves a spender to spend some amount of ETH.\n */\n function approve(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: approve is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Transfers funds from some sender account.\n */\n function transferFrom(\n address,\n address,\n uint256\n ) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: transferFrom is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Increases the allowance of a spender.\n */\n function increaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n }\n\n /**\n * @custom:blocked\n * @notice Decreases the allowance of a spender.\n */\n function decreaseAllowance(address, uint256) public virtual override returns (bool) {\n revert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n }\n}\n" - }, - "contracts/legacy/LegacyMessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:legacy\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000000\n * @title LegacyMessagePasser\n * @notice The LegacyMessagePasser was the low-level mechanism used to send messages from L2 to L1\n * before the Bedrock upgrade. It is now deprecated in favor of the new MessagePasser.\n */\ncontract LegacyMessagePasser is Semver {\n /**\n * @notice Mapping of sent message hashes to boolean status.\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Passes a message to L1.\n *\n * @param _message Message to pass to L1.\n */\n function passMessageToL1(bytes memory _message) external {\n sentMessages[keccak256(abi.encodePacked(_message, msg.sender))] = true;\n }\n}\n" - }, - "contracts/legacy/LegacyMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { ILegacyMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\n/**\n * @title LegacyMintableERC20\n * @notice The legacy implementation of the OptimismMintableERC20. This\n * contract is deprecated and should no longer be used.\n */\ncontract LegacyMintableERC20 is ILegacyMintableERC20, ERC20 {\n /**\n * @notice Emitted when the token is minted by the bridge.\n */\n event Mint(address indexed _account, uint256 _amount);\n\n /**\n * @notice Emitted when a token is burned by the bridge.\n */\n event Burn(address indexed _account, uint256 _amount);\n\n /**\n * @notice The token on the remote domain.\n */\n address public l1Token;\n\n /**\n * @notice The local bridge.\n */\n address public l2Bridge;\n\n /**\n * @param _l2Bridge Address of the L2 standard bridge.\n * @param _l1Token Address of the corresponding L1 token.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n */\n constructor(\n address _l2Bridge,\n address _l1Token,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) {\n l1Token = _l1Token;\n l2Bridge = _l2Bridge;\n }\n\n /**\n * @notice Modifier that requires the contract was called by the bridge.\n */\n modifier onlyL2Bridge() {\n require(msg.sender == l2Bridge, \"Only L2 Bridge can mint and burn\");\n _;\n }\n\n /**\n * @notice EIP165 implementation.\n */\n function supportsInterface(bytes4 _interfaceId) public pure returns (bool) {\n bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^\n ILegacyMintableERC20.mint.selector ^\n ILegacyMintableERC20.burn.selector;\n return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n }\n\n /**\n * @notice Only the bridge can mint tokens.\n * @param _to The account receiving tokens.\n * @param _amount The amount of tokens to receive.\n */\n function mint(address _to, uint256 _amount) public virtual onlyL2Bridge {\n _mint(_to, _amount);\n\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Only the bridge can burn tokens.\n * @param _from The account having tokens burnt.\n * @param _amount The amount of tokens being burnt.\n */\n function burn(address _from, uint256 _amount) public virtual onlyL2Bridge {\n _burn(_from, _amount);\n\n emit Burn(_from, _amount);\n }\n}\n" - }, - "contracts/legacy/ResolvedDelegateProxy.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressManager } from \"./AddressManager.sol\";\n\n/**\n * @custom:legacy\n * @title ResolvedDelegateProxy\n * @notice ResolvedDelegateProxy is a legacy proxy contract that makes use of the AddressManager to\n * resolve the implementation address. We're maintaining this contract for backwards\n * compatibility so we can manage all legacy proxies where necessary.\n */\ncontract ResolvedDelegateProxy {\n /**\n * @notice Mapping used to store the implementation name that corresponds to this contract. A\n * mapping was originally used as a way to bypass the same issue normally solved by\n * storing the implementation address in a specific storage slot that does not conflict\n * with any other storage slot. Generally NOT a safe solution but works as long as the\n * implementation does not also keep a mapping in the first storage slot.\n */\n mapping(address => string) private implementationName;\n\n /**\n * @notice Mapping used to store the address of the AddressManager contract where the\n * implementation address will be resolved from. Same concept here as with the above\n * mapping. Also generally unsafe but fine if the implementation doesn't keep a mapping\n * in the second storage slot.\n */\n mapping(address => AddressManager) private addressManager;\n\n /**\n * @param _addressManager Address of the AddressManager.\n * @param _implementationName implementationName of the contract to proxy to.\n */\n constructor(AddressManager _addressManager, string memory _implementationName) {\n addressManager[address(this)] = _addressManager;\n implementationName[address(this)] = _implementationName;\n }\n\n /**\n * @notice Fallback, performs a delegatecall to the resolved implementation address.\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n address target = addressManager[address(this)].getAddress(\n (implementationName[address(this)])\n );\n\n require(target != address(0), \"ResolvedDelegateProxy: target address must be initialized\");\n\n // slither-disable-next-line controlled-delegatecall\n (bool success, bytes memory returndata) = target.delegatecall(msg.data);\n\n if (success == true) {\n assembly {\n return(add(returndata, 0x20), mload(returndata))\n }\n } else {\n assembly {\n revert(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n" - }, - "contracts/libraries/Arithmetic.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { SignedMath } from \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\nimport { FixedPointMathLib } from \"@rari-capital/solmate/src/utils/FixedPointMathLib.sol\";\n\n/**\n * @title Arithmetic\n * @notice Even more math than before.\n */\nlibrary Arithmetic {\n /**\n * @notice Clamps a value between a minimum and maximum.\n *\n * @param _value The value to clamp.\n * @param _min The minimum value.\n * @param _max The maximum value.\n *\n * @return The clamped value.\n */\n function clamp(\n int256 _value,\n int256 _min,\n int256 _max\n ) internal pure returns (int256) {\n return SignedMath.min(SignedMath.max(_value, _min), _max);\n }\n\n /**\n * @notice (c)oefficient (d)enominator (exp)onentiation function.\n * Returns the result of: c * (1 - 1/d)^exp.\n *\n * @param _coefficient Coefficient of the function.\n * @param _denominator Fractional denominator.\n * @param _exponent Power function exponent.\n *\n * @return Result of c * (1 - 1/d)^exp.\n */\n function cdexp(\n int256 _coefficient,\n int256 _denominator,\n int256 _exponent\n ) internal pure returns (int256) {\n return\n (_coefficient *\n (FixedPointMathLib.powWad(1e18 - (1e18 / _denominator), _exponent * 1e18))) / 1e18;\n }\n}\n" - }, - "contracts/libraries/Burn.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Burn\n * @notice Utilities for burning stuff.\n */\nlibrary Burn {\n /**\n * Burns a given amount of ETH.\n *\n * @param _amount Amount of ETH to burn.\n */\n function eth(uint256 _amount) internal {\n new Burner{ value: _amount }();\n }\n\n /**\n * Burns a given amount of gas.\n *\n * @param _amount Amount of gas to burn.\n */\n function gas(uint256 _amount) internal view {\n uint256 i = 0;\n uint256 initialGas = gasleft();\n while (initialGas - gasleft() < _amount) {\n ++i;\n }\n }\n}\n\n/**\n * @title Burner\n * @notice Burner self-destructs on creation and sends all ETH to itself, removing all ETH given to\n * the contract from the circulating supply. Self-destructing is the only way to remove ETH\n * from the circulating supply.\n */\ncontract Burner {\n constructor() payable {\n selfdestruct(payable(address(this)));\n }\n}\n" - }, - "contracts/libraries/Bytes.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Bytes\n * @notice Bytes is a library for manipulating byte arrays.\n */\nlibrary Bytes {\n /**\n * @custom:attribution https://github.com/GNSPS/solidity-bytes-utils\n * @notice Slices a byte array with a given starting index and length. Returns a new byte array\n * as opposed to a pointer to the original array. Will throw if trying to slice more\n * bytes than exist in the array.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n * @param _length Length of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n unchecked {\n require(_length + 31 >= _length, \"slice_overflow\");\n require(_start + _length >= _start, \"slice_overflow\");\n require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n }\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n /**\n * @notice Slices a byte array with a given starting index up to the end of the original byte\n * array. Returns a new array rathern than a pointer to the original.\n *\n * @param _bytes Byte array to slice.\n * @param _start Starting index of the slice.\n *\n * @return Slice of the input byte array.\n */\n function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) {\n if (_start >= _bytes.length) {\n return bytes(\"\");\n }\n return slice(_bytes, _start, _bytes.length - _start);\n }\n\n /**\n * @notice Converts a byte array into a nibble array by splitting each byte into two nibbles.\n * Resulting nibble array will be exactly twice as long as the input byte array.\n *\n * @param _bytes Input byte array to convert.\n *\n * @return Resulting nibble array.\n */\n function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) {\n uint256 bytesLength = _bytes.length;\n bytes memory nibbles = new bytes(bytesLength * 2);\n bytes1 b;\n\n for (uint256 i = 0; i < bytesLength; ) {\n b = _bytes[i];\n nibbles[i * 2] = b >> 4;\n nibbles[i * 2 + 1] = b & 0x0f;\n unchecked {\n ++i;\n }\n }\n\n return nibbles;\n }\n\n /**\n * @notice Compares two byte arrays by comparing their keccak256 hashes.\n *\n * @param _bytes First byte array to compare.\n * @param _other Second byte array to compare.\n *\n * @return True if the two byte arrays are equal, false otherwise.\n */\n function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) {\n return keccak256(_bytes) == keccak256(_other);\n }\n}\n" - }, - "contracts/libraries/Constants.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\n/**\n * @title Constants\n * @notice Constants is a library for storing constants. Simple! Don't put everything in here, just\n * the stuff used in multiple contracts. Constants that only apply to a single contract\n * should be defined in that contract instead.\n */\nlibrary Constants {\n /**\n * @notice Special address to be used as the tx origin for gas estimation calls in the\n * OptimismPortal and CrossDomainMessenger calls. You only need to use this address if\n * the minimum gas limit specified by the user is not actually enough to execute the\n * given message and you're attempting to estimate the actual necessary gas limit. We\n * use address(1) because it's the ecrecover precompile and therefore guaranteed to\n * never have any code on any EVM chain.\n */\n address internal constant ESTIMATION_ADDRESS = address(1);\n\n /**\n * @notice Value used for the L2 sender storage slot in both the OptimismPortal and the\n * CrossDomainMessenger contracts before an actual sender is set. This value is\n * non-zero to reduce the gas cost of message passing transactions.\n */\n address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD;\n\n /**\n * @notice Returns the default values for the ResourceConfig. These are the recommended values\n * for a production network.\n */\n function DEFAULT_RESOURCE_CONFIG()\n internal\n pure\n returns (ResourceMetering.ResourceConfig memory)\n {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n return config;\n }\n}\n" - }, - "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" - }, - "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" - }, - "contracts/libraries/LegacyCrossDomainUtils.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n// Importing from the legacy contracts package causes issues with the build of the contract bindings\n// so we just copy the library here from\n// /packages/contracts/contracts/libraries/bridge/Lib_CrossDomainUtils.sol at commit\n// 7866168c\n/**\n * @title LegacyCrossDomainUtils\n */\nlibrary LegacyCrossDomainUtils {\n /**\n * Generates the correct cross domain calldata for a message.\n * @param _target Target contract address.\n * @param _sender Message sender address.\n * @param _message Message to send to the target.\n * @param _messageNonce Nonce for the provided message.\n * @return ABI encoded cross domain calldata.\n */\n function encodeXDomainCalldata(\n address _target,\n address _sender,\n bytes memory _message,\n uint256 _messageNonce\n ) internal pure returns (bytes memory) {\n return\n abi.encodeWithSignature(\n \"relayMessage(address,address,bytes,uint256)\",\n _target,\n _sender,\n _message,\n _messageNonce\n );\n }\n}\n" - }, - "contracts/libraries/Predeploys.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Predeploys\n * @notice Contains constant addresses for contracts that are pre-deployed to the L2 system.\n */\nlibrary Predeploys {\n /**\n * @notice Address of the L2ToL1MessagePasser predeploy.\n */\n address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016;\n\n /**\n * @notice Address of the L2CrossDomainMessenger predeploy.\n */\n address internal constant L2_CROSS_DOMAIN_MESSENGER =\n 0x4200000000000000000000000000000000000007;\n\n /**\n * @notice Address of the L2StandardBridge predeploy.\n */\n address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;\n\n /**\n * @notice Address of the L2ERC721Bridge predeploy.\n */\n address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014;\n\n /**\n * @notice Address of the SequencerFeeWallet predeploy.\n */\n address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;\n\n /**\n * @notice Address of the OptimismMintableERC20Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY =\n 0x4200000000000000000000000000000000000012;\n\n /**\n * @notice Address of the OptimismMintableERC721Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY =\n 0x4200000000000000000000000000000000000017;\n\n /**\n * @notice Address of the L1Block predeploy.\n */\n address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015;\n\n /**\n * @notice Address of the GasPriceOracle predeploy. Includes fee information\n * and helpers for computing the L1 portion of the transaction fee.\n */\n address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F;\n\n /**\n * @custom:legacy\n * @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger\n * or access tx.origin (or msg.sender) in a L1 to L2 transaction instead.\n */\n address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;\n\n /**\n * @custom:legacy\n * @notice Address of the DeployerWhitelist predeploy. No longer active.\n */\n address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the\n * state trie as of the Bedrock upgrade. Contract has been locked and write functions\n * can no longer be accessed.\n */\n address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;\n\n /**\n * @custom:legacy\n * @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy\n * instead, which exposes more information about the L1 state.\n */\n address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated\n * L2ToL1MessagePasser contract instead.\n */\n address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;\n\n /**\n * @notice Address of the ProxyAdmin predeploy.\n */\n address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018;\n\n /**\n * @notice Address of the BaseFeeVault predeploy.\n */\n address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019;\n\n /**\n * @notice Address of the L1FeeVault predeploy.\n */\n address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A;\n\n /**\n * @notice Address of the GovernanceToken predeploy.\n */\n address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042;\n}\n" - }, - "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, 32), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n\n /**\n * @notice Perform a low level call without copying any returndata. This function\n * will revert if the call cannot be performed with the specified minimum\n * gas.\n *\n * @param _target Address to call\n * @param _minGas The minimum amount of gas that may be passed 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 callWithMinGas(\n address _target,\n uint256 _minGas,\n uint256 _value,\n bytes memory _calldata\n ) internal returns (bool) {\n bool _success;\n assembly {\n // Assertion: gasleft() >= ((_minGas + 200) * 64) / 63\n //\n // Because EIP-150 ensures that, a maximum of 63/64ths of the remaining gas in the call\n // frame may be passed to a subcontext, we need to ensure that the gas will not be\n // truncated to hold this function's invariant: \"If a call is performed by\n // `callWithMinGas`, it must receive at least the specified minimum gas limit.\" In\n // addition, exactly 51 gas is consumed between the below `GAS` opcode and the `CALL`\n // opcode, so it is factored in with some extra room for error.\n if lt(gas(), div(mul(64, add(_minGas, 200)), 63)) {\n // Store the \"Error(string)\" selector in scratch space.\n mstore(0, 0x08c379a0)\n // Store the pointer to the string length in scratch space.\n mstore(32, 32)\n // Store the string.\n //\n // SAFETY:\n // - We pad the beginning of the string with two zero bytes as well as the\n // length (24) to ensure that we override the free memory pointer at offset\n // 0x40. This is necessary because the free memory pointer is likely to\n // be greater than 1 byte when this function is called, but it is incredibly\n // unlikely that it will be greater than 3 bytes. As for the data within\n // 0x60, it is ensured that it is 0 due to 0x60 being the zero offset.\n // - It's fine to clobber the free memory pointer, we're reverting.\n mstore(88, 0x0000185361666543616c6c3a204e6f7420656e6f75676820676173)\n\n // Revert with 'Error(\"SafeCall: Not enough gas\")'\n revert(28, 100)\n }\n\n // The call will be supplied at least (((_minGas + 200) * 64) / 63) - 49 gas due to the\n // above assertion. This ensures that, in all circumstances, the call will\n // receive at least the minimum amount of gas specified.\n // We can prove this property by solving the inequalities:\n // ((((_minGas + 200) * 64) / 63) - 49) >= _minGas\n // ((((_minGas + 200) * 64) / 63) - 51) * (63 / 64) >= _minGas\n // Both inequalities hold true for all possible values of `_minGas`.\n _success := call(\n gas(), // gas\n _target, // recipient\n _value, // ether value\n add(_calldata, 32), // inloc\n mload(_calldata), // inlen\n 0x00, // outloc\n 0x00 // outlen\n )\n }\n return _success;\n }\n}\n" - }, - "contracts/libraries/Types.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 * @custom:field outputRoot Hash of the L2 output.\n * @custom:field timestamp Timestamp of the L1 block that the output root was submitted in.\n * @custom:field l2BlockNumber L2 block number that the output corresponds to.\n */\n struct OutputProposal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2BlockNumber;\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 * @custom:field version Version of the output root.\n * @custom:field stateRoot Root of the state trie at the block of this output.\n * @custom:field messagePasserStorageRoot Root of the message passer storage trie.\n * @custom:field latestBlockhash Hash of the block this output was generated from.\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 * @custom:field from Address of the sender of the transaction.\n * @custom:field to Address of the recipient of the transaction.\n * @custom:field isCreation True if the transaction is a contract creation.\n * @custom:field value Value to send to the recipient.\n * @custom:field mint Amount of ETH to mint.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the transaction.\n * @custom:field l1BlockHash Hash of the block the transaction was submitted in.\n * @custom:field logIndex Index of the log in the block the transaction was submitted in.\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 * @custom:field nonce Nonce of the withdrawal transaction\n * @custom:field sender Address of the sender of the transaction.\n * @custom:field target Address of the recipient of the transaction.\n * @custom:field value Value to send to the recipient.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the 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" - }, - "contracts/libraries/rlp/RLPReader.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.8;\n\n/**\n * @custom:attribution https://github.com/hamdiallam/Solidity-RLP\n * @title RLPReader\n * @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted\n * from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with\n * various tweaks to improve readability.\n */\nlibrary RLPReader {\n /**\n * Custom pointer type to avoid confusion between pointers and uint256s.\n */\n type MemoryPointer is uint256;\n\n /**\n * @notice RLP item types.\n *\n * @custom:value DATA_ITEM Represents an RLP data item (NOT a list).\n * @custom:value LIST_ITEM Represents an RLP list item.\n */\n enum RLPItemType {\n DATA_ITEM,\n LIST_ITEM\n }\n\n /**\n * @notice Struct representing an RLP item.\n *\n * @custom:field length Length of the RLP item.\n * @custom:field ptr Pointer to the RLP item in memory.\n */\n struct RLPItem {\n uint256 length;\n MemoryPointer ptr;\n }\n\n /**\n * @notice Max list length that this library will accept.\n */\n uint256 internal constant MAX_LIST_LENGTH = 32;\n\n /**\n * @notice Converts bytes to a reference to memory position and length.\n *\n * @param _in Input bytes to convert.\n *\n * @return Output memory reference.\n */\n function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) {\n // Empty arrays are not RLP items.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr;\n assembly {\n ptr := add(_in, 32)\n }\n\n return RLPItem({ length: _in.length, ptr: ptr });\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) {\n (uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.LIST_ITEM,\n \"RLPReader: decoded item type for list is not a list item\"\n );\n\n require(\n listOffset + listLength == _in.length,\n \"RLPReader: list item has an invalid data remainder\"\n );\n\n // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by\n // writing to the length. Since we can't know the number of RLP items without looping over\n // the entire input, we'd have to loop twice to accurately size this array. It's easier to\n // simply set a reasonable maximum list length and decrease the size before we finish.\n RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH);\n\n uint256 itemCount = 0;\n uint256 offset = listOffset;\n while (offset < _in.length) {\n (uint256 itemOffset, uint256 itemLength, ) = _decodeLength(\n RLPItem({\n length: _in.length - offset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n })\n );\n\n // We don't need to check itemCount < out.length explicitly because Solidity already\n // handles this check on our behalf, we'd just be wasting gas.\n out[itemCount] = RLPItem({\n length: itemLength + itemOffset,\n ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)\n });\n\n itemCount += 1;\n offset += itemOffset + itemLength;\n }\n\n // Decrease the array size to match the actual item count.\n assembly {\n mstore(out, itemCount)\n }\n\n return out;\n }\n\n /**\n * @notice Reads an RLP list value into a list of RLP items.\n *\n * @param _in RLP list value.\n *\n * @return Decoded RLP list items.\n */\n function readList(bytes memory _in) internal pure returns (RLPItem[] memory) {\n return readList(toRLPItem(_in));\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);\n\n require(\n itemType == RLPItemType.DATA_ITEM,\n \"RLPReader: decoded item type for bytes is not a data item\"\n );\n\n require(\n _in.length == itemOffset + itemLength,\n \"RLPReader: bytes value contains an invalid remainder\"\n );\n\n return _copy(_in.ptr, itemOffset, itemLength);\n }\n\n /**\n * @notice Reads an RLP bytes value into bytes.\n *\n * @param _in RLP bytes value.\n *\n * @return Decoded bytes.\n */\n function readBytes(bytes memory _in) internal pure returns (bytes memory) {\n return readBytes(toRLPItem(_in));\n }\n\n /**\n * @notice Reads the raw bytes of an RLP item.\n *\n * @param _in RLP item to read.\n *\n * @return Raw RLP bytes.\n */\n function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) {\n return _copy(_in.ptr, 0, _in.length);\n }\n\n /**\n * @notice Decodes the length of an RLP item.\n *\n * @param _in RLP item to decode.\n *\n * @return Offset of the encoded data.\n * @return Length of the encoded data.\n * @return RLP item type (LIST_ITEM or DATA_ITEM).\n */\n function _decodeLength(RLPItem memory _in)\n private\n pure\n returns (\n uint256,\n uint256,\n RLPItemType\n )\n {\n // Short-circuit if there's nothing to decode, note that we perform this check when\n // the user creates an RLP item via toRLPItem, but it's always possible for them to bypass\n // that function and create an RLP item directly. So we need to check this anyway.\n require(\n _in.length > 0,\n \"RLPReader: length of an RLP item must be greater than zero to be decodable\"\n );\n\n MemoryPointer ptr = _in.ptr;\n uint256 prefix;\n assembly {\n prefix := byte(0, mload(ptr))\n }\n\n if (prefix <= 0x7f) {\n // Single byte.\n return (0, 1, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xb7) {\n // Short string.\n\n // slither-disable-next-line variable-scope\n uint256 strLen = prefix - 0x80;\n\n require(\n _in.length > strLen,\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n strLen != 1 || firstByteOfContent >= 0x80,\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n\n return (1, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xbf) {\n // Long string.\n uint256 lenOfStrLen = prefix - 0xb7;\n\n require(\n _in.length > lenOfStrLen,\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n\n uint256 strLen;\n assembly {\n strLen := shr(sub(256, mul(8, lenOfStrLen)), mload(add(ptr, 1)))\n }\n\n require(\n strLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long string)\"\n );\n\n require(\n _in.length > lenOfStrLen + strLen,\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n\n return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM);\n } else if (prefix <= 0xf7) {\n // Short list.\n // slither-disable-next-line variable-scope\n uint256 listLen = prefix - 0xc0;\n\n require(\n _in.length > listLen,\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n\n return (1, listLen, RLPItemType.LIST_ITEM);\n } else {\n // Long list.\n uint256 lenOfListLen = prefix - 0xf7;\n\n require(\n _in.length > lenOfListLen,\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n\n bytes1 firstByteOfContent;\n assembly {\n firstByteOfContent := and(mload(add(ptr, 1)), shl(248, 0xff))\n }\n\n require(\n firstByteOfContent != 0x00,\n \"RLPReader: length of content must not have any leading zeros (long list)\"\n );\n\n uint256 listLen;\n assembly {\n listLen := shr(sub(256, mul(8, lenOfListLen)), mload(add(ptr, 1)))\n }\n\n require(\n listLen > 55,\n \"RLPReader: length of content must be greater than 55 bytes (long list)\"\n );\n\n require(\n _in.length > lenOfListLen + listLen,\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n\n return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM);\n }\n }\n\n /**\n * @notice Copies the bytes from a memory location.\n *\n * @param _src Pointer to the location to read from.\n * @param _offset Offset to start reading from.\n * @param _length Number of bytes to read.\n *\n * @return Copied bytes.\n */\n function _copy(\n MemoryPointer _src,\n uint256 _offset,\n uint256 _length\n ) private pure returns (bytes memory) {\n bytes memory out = new bytes(_length);\n if (_length == 0) {\n return out;\n }\n\n // Mostly based on Solidity's copy_memory_to_memory:\n // solhint-disable max-line-length\n // https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114\n uint256 src = MemoryPointer.unwrap(_src) + _offset;\n assembly {\n let dest := add(out, 32)\n let i := 0\n for {\n\n } lt(i, _length) {\n i := add(i, 32)\n } {\n mstore(add(dest, i), mload(add(src, i)))\n }\n\n if gt(i, _length) {\n mstore(add(dest, _length), 0)\n }\n }\n\n return out;\n }\n}\n" - }, - "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" - }, - "contracts/libraries/trie/MerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Bytes } from \"../Bytes.sol\";\nimport { RLPReader } from \"../rlp/RLPReader.sol\";\n\n/**\n * @title MerkleTrie\n * @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie\n * inclusion proofs. By default, this library assumes a hexary trie. One can change the\n * trie radix constant to support other trie radixes.\n */\nlibrary MerkleTrie {\n /**\n * @notice Struct representing a node in the trie.\n *\n * @custom:field encoded The RLP-encoded node.\n * @custom:field decoded The RLP-decoded node.\n */\n struct TrieNode {\n bytes encoded;\n RLPReader.RLPItem[] decoded;\n }\n\n /**\n * @notice Determines the number of elements per branch node.\n */\n uint256 internal constant TREE_RADIX = 16;\n\n /**\n * @notice Branch nodes have TREE_RADIX elements and one value element.\n */\n uint256 internal constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;\n\n /**\n * @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.\n */\n uint256 internal constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;\n\n /**\n * @notice Prefix for even-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_EVEN = 0;\n\n /**\n * @notice Prefix for odd-nibbled extension node paths.\n */\n uint8 internal constant PREFIX_EXTENSION_ODD = 1;\n\n /**\n * @notice Prefix for even-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_EVEN = 2;\n\n /**\n * @notice Prefix for odd-nibbled leaf node paths.\n */\n uint8 internal constant PREFIX_LEAF_ODD = 3;\n\n /**\n * @notice Verifies a proof that a given key/value pair is present in the trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n return Bytes.equal(_value, get(_key, _proof, _root));\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n require(_key.length > 0, \"MerkleTrie: empty key\");\n\n TrieNode[] memory proof = _parseProof(_proof);\n bytes memory key = Bytes.toNibbles(_key);\n bytes memory currentNodeID = abi.encodePacked(_root);\n uint256 currentKeyIndex = 0;\n\n // Proof is top-down, so we start at the first element (root).\n for (uint256 i = 0; i < proof.length; i++) {\n TrieNode memory currentNode = proof[i];\n\n // Key index should never exceed total key length or we'll be out of bounds.\n require(\n currentKeyIndex <= key.length,\n \"MerkleTrie: key index exceeds total key length\"\n );\n\n if (currentKeyIndex == 0) {\n // First proof element is always the root node.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid root hash\"\n );\n } else if (currentNode.encoded.length >= 32) {\n // Nodes 32 bytes or larger are hashed inside branch nodes.\n require(\n Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID),\n \"MerkleTrie: invalid large internal hash\"\n );\n } else {\n // Nodes smaller than 32 bytes aren't hashed.\n require(\n Bytes.equal(currentNode.encoded, currentNodeID),\n \"MerkleTrie: invalid internal node hash\"\n );\n }\n\n if (currentNode.decoded.length == BRANCH_NODE_LENGTH) {\n if (currentKeyIndex == key.length) {\n // Value is the last element of the decoded list (for branch nodes). There's\n // some ambiguity in the Merkle trie specification because bytes(0) is a\n // valid value to place into the trie, but for branch nodes bytes(0) can exist\n // even when the value wasn't explicitly placed there. Geth treats a value of\n // bytes(0) as \"key does not exist\" and so we do the same.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[TREE_RADIX]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (branch)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (branch)\"\n );\n\n return value;\n } else {\n // We're not at the end of the key yet.\n // Figure out what the next node ID should be and continue.\n uint8 branchKey = uint8(key[currentKeyIndex]);\n RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];\n currentNodeID = _getNodeID(nextNode);\n currentKeyIndex += 1;\n }\n } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) {\n bytes memory path = _getNodePath(currentNode);\n uint8 prefix = uint8(path[0]);\n uint8 offset = 2 - (prefix % 2);\n bytes memory pathRemainder = Bytes.slice(path, offset);\n bytes memory keyRemainder = Bytes.slice(key, currentKeyIndex);\n uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder);\n\n // Whether this is a leaf node or an extension node, the path remainder MUST be a\n // prefix of the key remainder (or be equal to the key remainder) or the proof is\n // considered invalid.\n require(\n pathRemainder.length == sharedNibbleLength,\n \"MerkleTrie: path remainder must share all nibbles with key\"\n );\n\n if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) {\n // Prefix of 2 or 3 means this is a leaf node. For the leaf node to be valid,\n // the key remainder must be exactly equal to the path remainder. We already\n // did the necessary byte comparison, so it's more efficient here to check that\n // the key remainder length equals the shared nibble length, which implies\n // equality with the path remainder (since we already did the same check with\n // the path remainder and the shared nibble length).\n require(\n keyRemainder.length == sharedNibbleLength,\n \"MerkleTrie: key remainder must be identical to path remainder\"\n );\n\n // Our Merkle Trie is designed specifically for the purposes of the Ethereum\n // state trie. Empty values are not allowed in the state trie, so we can safely\n // say that if the value is empty, the key should not exist and the proof is\n // invalid.\n bytes memory value = RLPReader.readBytes(currentNode.decoded[1]);\n require(\n value.length > 0,\n \"MerkleTrie: value length must be greater than zero (leaf)\"\n );\n\n // Extra proof elements are not allowed.\n require(\n i == proof.length - 1,\n \"MerkleTrie: value node must be last node in proof (leaf)\"\n );\n\n return value;\n } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) {\n // Prefix of 0 or 1 means this is an extension node. We move onto the next node\n // in the proof and increment the key index by the length of the path remainder\n // which is equal to the shared nibble length.\n currentNodeID = _getNodeID(currentNode.decoded[1]);\n currentKeyIndex += sharedNibbleLength;\n } else {\n revert(\"MerkleTrie: received a node with an unknown prefix\");\n }\n } else {\n revert(\"MerkleTrie: received an unparseable node\");\n }\n }\n\n revert(\"MerkleTrie: ran out of proof elements\");\n }\n\n /**\n * @notice Parses an array of proof elements into a new array that contains both the original\n * encoded element and the RLP-decoded element.\n *\n * @param _proof Array of proof elements to parse.\n *\n * @return Proof parsed into easily accessible structs.\n */\n function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory) {\n uint256 length = _proof.length;\n TrieNode[] memory proof = new TrieNode[](length);\n for (uint256 i = 0; i < length; ) {\n proof[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) });\n unchecked {\n ++i;\n }\n }\n return proof;\n }\n\n /**\n * @notice Picks out the ID for a node. Node ID is referred to as the \"hash\" within the\n * specification, but nodes < 32 bytes are not actually hashed.\n *\n * @param _node Node to pull an ID for.\n *\n * @return ID for the node, depending on the size of its contents.\n */\n function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes memory) {\n return _node.length < 32 ? RLPReader.readRawBytes(_node) : RLPReader.readBytes(_node);\n }\n\n /**\n * @notice Gets the path for a leaf or extension node.\n *\n * @param _node Node to get a path for.\n *\n * @return Node path, converted to an array of nibbles.\n */\n function _getNodePath(TrieNode memory _node) private pure returns (bytes memory) {\n return Bytes.toNibbles(RLPReader.readBytes(_node.decoded[0]));\n }\n\n /**\n * @notice Utility; determines the number of nibbles shared between two nibble arrays.\n *\n * @param _a First nibble array.\n * @param _b Second nibble array.\n *\n * @return Number of shared nibbles.\n */\n function _getSharedNibbleLength(bytes memory _a, bytes memory _b)\n private\n pure\n returns (uint256)\n {\n uint256 shared;\n uint256 max = (_a.length < _b.length) ? _a.length : _b.length;\n for (; shared < max && _a[shared] == _b[shared]; ) {\n unchecked {\n ++shared;\n }\n }\n return shared;\n }\n}\n" - }, - "contracts/libraries/trie/SecureMerkleTrie.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* Library Imports */\nimport { MerkleTrie } from \"./MerkleTrie.sol\";\n\n/**\n * @title SecureMerkleTrie\n * @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input\n * keys. Ethereum's state trie hashes input keys before storing them.\n */\nlibrary SecureMerkleTrie {\n /**\n * @notice Verifies a proof that a given key/value pair is present in the Merkle trie.\n *\n * @param _key Key of the node to search for, as a hex string.\n * @param _value Value of the node to search for, as a hex string.\n * @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle\n * trees, this proof is executed top-down and consists of a list of RLP-encoded\n * nodes that make a path down to the target node.\n * @param _root Known root of the Merkle trie. Used to verify that the included proof is\n * correctly constructed.\n *\n * @return Whether or not the proof is valid.\n */\n function verifyInclusionProof(\n bytes memory _key,\n bytes memory _value,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bool) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);\n }\n\n /**\n * @notice Retrieves the value associated with a given key.\n *\n * @param _key Key to search for, as hex bytes.\n * @param _proof Merkle trie inclusion proof for the key.\n * @param _root Known root of the Merkle trie.\n *\n * @return Value of the key if it exists.\n */\n function get(\n bytes memory _key,\n bytes[] memory _proof,\n bytes32 _root\n ) internal pure returns (bytes memory) {\n bytes memory key = _getSecureKey(_key);\n return MerkleTrie.get(key, _proof, _root);\n }\n\n /**\n * @notice Computes the hashed version of the input key.\n *\n * @param _key Key to hash.\n *\n * @return Hashed version of the key.\n */\n function _getSecureKey(bytes memory _key) private pure returns (bytes memory) {\n return abi.encodePacked(keccak256(_key));\n }\n}\n" - }, - "contracts/periphery/TransferOnion.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ReentrancyGuard } from \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @title TransferOnion\n * @notice TransferOnion is a hash onion for distributing tokens. The shell commits\n * to an ordered list of the token transfers and can be permissionlessly\n * unwrapped in order. The SENDER must `approve` this contract as\n * `transferFrom` is used to move the token balances.\n */\ncontract TransferOnion is ReentrancyGuard {\n using SafeERC20 for ERC20;\n\n /**\n * @notice Struct representing a layer of the onion.\n */\n struct Layer {\n address recipient;\n uint256 amount;\n bytes32 shell;\n }\n\n /**\n * @notice Address of the token to distribute.\n */\n ERC20 public immutable TOKEN;\n\n /**\n * @notice Address of the account to distribute tokens from.\n */\n address public immutable SENDER;\n\n /**\n * @notice Current shell hash.\n */\n bytes32 public shell;\n\n /**\n * @param _token Address of the token to distribute.\n * @param _sender Address of the sender to distribute from.\n * @param _shell Initial shell of the onion.\n */\n constructor(\n ERC20 _token,\n address _sender,\n bytes32 _shell\n ) {\n TOKEN = _token;\n SENDER = _sender;\n shell = _shell;\n }\n\n /**\n * @notice Peels layers from the onion and distributes tokens.\n *\n * @param _layers Array of onion layers to peel.\n */\n function peel(Layer[] memory _layers) public nonReentrant {\n bytes32 tempShell = shell;\n uint256 length = _layers.length;\n for (uint256 i = 0; i < length; ) {\n Layer memory layer = _layers[i];\n\n // Confirm that the onion layer is correct.\n require(\n keccak256(abi.encode(layer.recipient, layer.amount, layer.shell)) == tempShell,\n \"TransferOnion: what are you doing in my swamp?\"\n );\n\n // Update the onion layer.\n tempShell = layer.shell;\n\n // Transfer the tokens.\n TOKEN.safeTransferFrom(SENDER, layer.recipient, layer.amount);\n\n // Unchecked increment to save some gas.\n unchecked {\n ++i;\n }\n }\n\n shell = tempShell;\n }\n}\n" - }, - "contracts/test/AddressAliasHelper.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\n\ncontract AddressAliasHelper_applyAndUndo_Test is Test {\n /**\n * @notice Tests that applying and then undoing an alias results in the original address.\n */\n function testFuzz_applyAndUndo_succeeds(address _address) external {\n address aliased = AddressAliasHelper.applyL1ToL2Alias(_address);\n address unaliased = AddressAliasHelper.undoL1ToL2Alias(aliased);\n assertEq(_address, unaliased);\n }\n}\n" - }, - "contracts/test/BenchmarkTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test } from \"forge-std/Test.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport \"./CommonTest.t.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\n// Free function for setting the prevBaseFee param in the OptimismPortal.\nfunction setPrevBaseFee(\n Vm _vm,\n address _op,\n uint128 _prevBaseFee\n) {\n _vm.store(address(_op), bytes32(uint256(1)), bytes32((block.number << 192) | _prevBaseFee));\n}\n\ncontract SetPrevBaseFee_Test is Portal_Initializer {\n function test_setPrevBaseFee_succeeds() external {\n setPrevBaseFee(vm, address(op), 100 gwei);\n (uint128 prevBaseFee, , uint64 prevBlockNum) = op.params();\n assertEq(uint256(prevBaseFee), 100 gwei);\n assertEq(uint256(prevBlockNum), block.number);\n }\n}\n\n// Tests for obtaining pure gas cost estimates for commonly used functions.\n// The objective with these benchmarks is to strip down the actual test functions\n// so that they are nothing more than the call we want measure the gas cost of.\n// In order to achieve this we make no assertions, and handle everything else in the setUp()\n// function.\ncontract GasBenchMark_OptimismPortal is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n bytes32 _outputRoot;\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n\n // Get withdrawal proof data we can use for testing.\n bytes32 _storageRoot;\n bytes32 _stateRoot;\n (_stateRoot, _storageRoot, _outputRoot, , _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public virtual override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n function test_depositTransaction_benchmark() external {\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_depositTransaction_benchmark_1() external {\n setPrevBaseFee(vm, address(op), 1 gwei);\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n function test_proveWithdrawalTransaction_benchmark() external {\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n}\n\ncontract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer {\n function test_sendMessage_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n vm.resumeGasMetering();\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n\n function test_sendMessage_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n // The amount of data typically sent during a bridge deposit.\n bytes\n memory data = hex\"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\";\n vm.resumeGasMetering();\n L1Messenger.sendMessage(bob, data, uint32(100));\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), alice, 100000, true);\n vm.startPrank(alice, alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n }\n\n function test_depositETH_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n vm.resumeGasMetering();\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositETH_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n vm.resumeGasMetering();\n L1Bridge.depositETH{ value: 500 }(50000, hex\"\");\n }\n\n function test_depositERC20_benchmark_0() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 1 gwei);\n vm.resumeGasMetering();\n L1Bridge.bridgeERC20({\n _localToken: address(L1Token),\n _remoteToken: address(L2Token),\n _amount: 100,\n _minGasLimit: 100_000,\n _extraData: hex\"\"\n });\n }\n\n function test_depositERC20_benchmark_1() external {\n vm.pauseGasMetering();\n setPrevBaseFee(vm, address(op), 10 gwei);\n vm.resumeGasMetering();\n L1Bridge.bridgeERC20({\n _localToken: address(L1Token),\n _remoteToken: address(L2Token),\n _amount: 100,\n _minGasLimit: 100_000,\n _extraData: hex\"\"\n });\n }\n}\n\ncontract GasBenchMark_L1StandardBridge_Finalize is Bridge_Initializer {\n function setUp() public virtual override {\n super.setUp();\n deal(address(L1Token), address(L1Bridge), 100, true);\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.startPrank(address(L1Bridge.messenger()));\n vm.deal(address(L1Bridge.messenger()), 100);\n }\n\n function test_finalizeETHWithdrawal_benchmark() external {\n // TODO: Make this more accurate. It is underestimating the cost because it pranks\n // the call coming from the messenger, which bypasses the portal\n // and oracle.\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n\ncontract GasBenchMark_L2OutputOracle is L2OutputOracle_Initializer {\n uint256 nextBlockNumber;\n\n function setUp() public override {\n super.setUp();\n nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.startPrank(proposer);\n }\n\n function test_proposeL2Output_benchmark() external {\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n}\n" - }, - "contracts/test/Bytes.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Bytes } from \"../libraries/Bytes.sol\";\n\ncontract Bytes_slice_Test is Test {\n /**\n * @notice Tests that the `slice` function works as expected when starting from index 0.\n */\n function test_slice_fromZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check if all possible slices starting from index 0 are correct.\n assertEq(Bytes.slice(input, 0, 0), hex\"\");\n assertEq(Bytes.slice(input, 0, 1), hex\"11\");\n assertEq(Bytes.slice(input, 0, 2), hex\"1122\");\n assertEq(Bytes.slice(input, 0, 3), hex\"112233\");\n assertEq(Bytes.slice(input, 0, 4), hex\"11223344\");\n assertEq(Bytes.slice(input, 0, 5), hex\"1122334455\");\n assertEq(Bytes.slice(input, 0, 6), hex\"112233445566\");\n assertEq(Bytes.slice(input, 0, 7), hex\"11223344556677\");\n assertEq(Bytes.slice(input, 0, 8), hex\"1122334455667788\");\n assertEq(Bytes.slice(input, 0, 9), hex\"112233445566778899\");\n assertEq(Bytes.slice(input, 0, 10), hex\"11223344556677889900\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when starting from indices [1, 9]\n * with lengths [1, 9], in reverse order.\n */\n function test_slice_fromNonZeroIdx_works() public {\n bytes memory input = hex\"11223344556677889900\";\n\n // Exhaustively check correctness of slices starting from indexes [1, 9]\n // and spanning [1, 9] bytes, in reverse order\n assertEq(Bytes.slice(input, 9, 1), hex\"00\");\n assertEq(Bytes.slice(input, 8, 2), hex\"9900\");\n assertEq(Bytes.slice(input, 7, 3), hex\"889900\");\n assertEq(Bytes.slice(input, 6, 4), hex\"77889900\");\n assertEq(Bytes.slice(input, 5, 5), hex\"6677889900\");\n assertEq(Bytes.slice(input, 4, 6), hex\"556677889900\");\n assertEq(Bytes.slice(input, 3, 7), hex\"44556677889900\");\n assertEq(Bytes.slice(input, 2, 8), hex\"3344556677889900\");\n assertEq(Bytes.slice(input, 1, 9), hex\"223344556677889900\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when slicing between multiple words\n * in memory. In this case, we test that a 2 byte slice between the 32nd byte of the\n * first word and the 1st byte of the second word is correct.\n */\n function test_slice_acrossWords_works() public {\n bytes\n memory input = hex\"00000000000000000000000000000000000000000000000000000000000000112200000000000000000000000000000000000000000000000000000000000000\";\n\n assertEq(Bytes.slice(input, 31, 2), hex\"1122\");\n }\n\n /**\n * @notice Tests that the `slice` function works as expected when slicing between multiple\n * words in memory. In this case, we test that a 34 byte slice between 3 separate words\n * returns the correct result.\n */\n function test_slice_acrossMultipleWords_works() public {\n bytes\n memory input = hex\"000000000000000000000000000000000000000000000000000000000000001122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1100000000000000000000000000000000000000000000000000000000000000\";\n bytes\n memory expected = hex\"1122FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11\";\n\n assertEq(Bytes.slice(input, 31, 34), expected);\n }\n\n /**\n * @notice Tests that, when given an input bytes array of length `n`, the `slice` function will\n * always revert if `_start + _length > n`.\n */\n function testFuzz_slice_outOfBounds_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // We want a valid start index and a length that will not overflow.\n vm.assume(_start < _input.length && _length < type(uint256).max - 31);\n // But, we want an invalid slice length.\n vm.assume(_start + _length > _input.length);\n\n vm.expectRevert(\"slice_outOfBounds\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that, when given a length `n` that is greater than `type(uint256).max - 31`,\n * the `slice` function reverts.\n */\n function testFuzz_slice_lengthOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that the `_length` will overflow if a number >= 31 is added to it.\n vm.assume(_length > type(uint256).max - 31);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that, when given a start index `n` that is greater than\n * `type(uint256).max - n`, the `slice` function reverts.\n */\n function testFuzz_slice_rangeOverflows_reverts(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // Ensure that `_length` is a realistic length of a slice. This is to make sure\n // we revert on the correct require statement.\n vm.assume(_length < _input.length);\n // Ensure that `_start` will overflow if `_length` is added to it.\n vm.assume(_start > type(uint256).max - _length);\n\n vm.expectRevert(\"slice_overflow\");\n Bytes.slice(_input, _start, _length);\n }\n\n /**\n * @notice Tests that the `slice` function correctly updates the free memory pointer depending\n * on the length of the slice.\n */\n function testFuzz_slice_memorySafety_succeeds(\n bytes memory _input,\n uint256 _start,\n uint256 _length\n ) public {\n // The start should never be more than the length of the input bytes array - 1\n vm.assume(_start < _input.length);\n // The length should never be more than the length of the input bytes array - the starting\n // slice index.\n vm.assume(_length <= _input.length - _start);\n\n // Grab the free memory pointer before the slice operation\n uint64 initPtr;\n assembly {\n initPtr := mload(0x40)\n }\n uint64 expectedPtr = uint64(initPtr + 0x20 + ((_length + 0x1f) & ~uint256(0x1f)));\n\n // Ensure that all memory outside of the expected range is safe.\n vm.expectSafeMemory(initPtr, expectedPtr);\n\n // Slice the input bytes array from `_start` to `_start + _length`\n bytes memory slice = Bytes.slice(_input, _start, _length);\n\n // Grab the free memory pointer after the slice operation\n uint64 finalPtr;\n assembly {\n finalPtr := mload(0x40)\n }\n\n // The free memory pointer should have been updated properly\n if (_length == 0) {\n // If the slice length is zero, only 32 bytes of memory should have been allocated.\n assertEq(finalPtr, initPtr + 0x20);\n } else {\n // If the slice length is greater than zero, the memory allocated should be the\n // length of the slice rounded up to the next 32 byte word + 32 bytes for the\n // length of the byte array.\n //\n // Note that we use a slightly less efficient, but equivalent method of rounding\n // up `_length` to the next multiple of 32 than is used in the `slice` function.\n // This is to diff test the method used in `slice`.\n uint64 _expectedPtr = uint64(initPtr + 0x20 + (((_length + 0x1F) >> 5) << 5));\n assertEq(finalPtr, _expectedPtr);\n\n // Sanity check for equivalence of the rounding methods.\n assertEq(_expectedPtr, expectedPtr);\n }\n\n // The slice length should be equal to `_length`\n assertEq(slice.length, _length);\n }\n}\n\ncontract Bytes_toNibbles_Test is Test {\n /**\n * @notice Diffs the test Solidity version of `toNibbles` against the Yul version.\n *\n * @param _bytes The `bytes` array to convert to nibbles.\n *\n * @return Yul version of `toNibbles` applied to `_bytes`.\n */\n function _toNibblesYul(bytes memory _bytes) internal pure returns (bytes memory) {\n // Allocate memory for the `nibbles` array.\n bytes memory nibbles = new bytes(_bytes.length << 1);\n\n assembly {\n // Load the length of the passed bytes array from memory\n let bytesLength := mload(_bytes)\n\n // Store the memory offset of the _bytes array's contents on the stack\n let bytesStart := add(_bytes, 0x20)\n\n // Store the memory offset of the nibbles array's contents on the stack\n let nibblesStart := add(nibbles, 0x20)\n\n // Loop through each byte in the input array\n for {\n let i := 0x00\n } lt(i, bytesLength) {\n i := add(i, 0x01)\n } {\n // Get the starting offset of the next 2 bytes in the nibbles array\n let offset := add(nibblesStart, shl(0x01, i))\n\n // Load the byte at the current index within the `_bytes` array\n let b := byte(0x00, mload(add(bytesStart, i)))\n\n // Pull out the first nibble and store it in the new array\n mstore8(offset, shr(0x04, b))\n // Pull out the second nibble and store it in the new array\n mstore8(add(offset, 0x01), and(b, 0x0F))\n }\n }\n\n return nibbles;\n }\n\n /**\n * @notice Tests that, given an input of 5 bytes, the `toNibbles` function returns an array of\n * 10 nibbles corresponding to the input data.\n */\n function test_toNibbles_expectedResult5Bytes_works() public {\n bytes memory input = hex\"1234567890\";\n bytes memory expected = hex\"01020304050607080900\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Tests that, given an input of 128 bytes, the `toNibbles` function returns an array\n * of 256 nibbles corresponding to the input data. This test exists to ensure that,\n * given a large input, the `toNibbles` function works as expected.\n */\n function test_toNibbles_expectedResult128Bytes_works() public {\n bytes\n memory input = hex\"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f\";\n bytes\n memory expected = hex\"0000000100020003000400050006000700080009000a000b000c000d000e000f0100010101020103010401050106010701080109010a010b010c010d010e010f0200020102020203020402050206020702080209020a020b020c020d020e020f0300030103020303030403050306030703080309030a030b030c030d030e030f0400040104020403040404050406040704080409040a040b040c040d040e040f0500050105020503050405050506050705080509050a050b050c050d050e050f0600060106020603060406050606060706080609060a060b060c060d060e060f0700070107020703070407050706070707080709070a070b070c070d070e070f\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length * 2, actual.length);\n assertEq(expected.length, actual.length);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Tests that, given an input of 0 bytes, the `toNibbles` function returns a zero\n * length array.\n */\n function test_toNibbles_zeroLengthInput_works() public {\n bytes memory input = hex\"\";\n bytes memory expected = hex\"\";\n bytes memory actual = Bytes.toNibbles(input);\n\n assertEq(input.length, 0);\n assertEq(expected.length, 0);\n assertEq(actual.length, 0);\n assertEq(actual, expected);\n }\n\n /**\n * @notice Test that the `toNibbles` function in the `Bytes` library is equivalent to the Yul\n * implementation.\n */\n function testDiff_toNibbles_succeeds(bytes memory _input) public {\n assertEq(Bytes.toNibbles(_input), _toNibblesYul(_input));\n }\n}\n\ncontract Bytes_equal_Test is Test {\n /**\n * @notice Manually checks equality of two dynamic `bytes` arrays in memory.\n *\n * @param _a The first `bytes` array to compare.\n * @param _b The second `bytes` array to compare.\n *\n * @return True if the two `bytes` arrays are equal in memory.\n */\n function manualEq(bytes memory _a, bytes memory _b) internal pure returns (bool) {\n bool _eq;\n assembly {\n _eq := and(\n // Check if the contents of the two bytes arrays are equal in memory.\n eq(keccak256(add(0x20, _a), mload(_a)), keccak256(add(0x20, _b), mload(_b))),\n // Check if the length of the two bytes arrays are equal in memory.\n // This is redundant given the above check, but included for completeness.\n eq(mload(_a), mload(_b))\n )\n }\n return _eq;\n }\n\n /**\n * @notice Tests that the `equal` function in the `Bytes` library returns `false` if given two\n * non-equal byte arrays.\n */\n function testFuzz_equal_notEqual_works(bytes memory _a, bytes memory _b) public {\n vm.assume(!manualEq(_a, _b));\n assertFalse(Bytes.equal(_a, _b));\n }\n\n /**\n * @notice Test whether or not the `equal` function in the `Bytes` library is equivalent to\n * manually checking equality of the two dynamic `bytes` arrays in memory.\n */\n function testDiff_equal_works(bytes memory _a, bytes memory _b) public {\n assertEq(Bytes.equal(_a, _b), manualEq(_a, _b));\n }\n}\n" - }, - "contracts/test/CommonTest.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Test, StdUtils } from \"forge-std/Test.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L1StandardBridge } from \"../L1/L1StandardBridge.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC20Factory } from \"../universal/OptimismMintableERC20Factory.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { IL1ChugSplashDeployer } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { Strings } from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport { LegacyMintableERC20 } from \"../legacy/LegacyMintableERC20.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract CommonTest is Test {\n address alice = address(128);\n address bob = address(256);\n address multisig = address(512);\n\n address immutable ZERO_ADDRESS = address(0);\n address immutable NON_ZERO_ADDRESS = address(1);\n uint256 immutable NON_ZERO_VALUE = 100;\n uint256 immutable ZERO_VALUE = 0;\n uint64 immutable NON_ZERO_GASLIMIT = 50000;\n bytes32 nonZeroHash = keccak256(abi.encode(\"NON_ZERO\"));\n bytes NON_ZERO_DATA = hex\"0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000\";\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 indexed version,\n bytes opaqueData\n );\n\n FFIInterface ffi;\n\n function setUp() public virtual {\n // Give alice and bob some ETH\n vm.deal(alice, 1 << 16);\n vm.deal(bob, 1 << 16);\n vm.deal(multisig, 1 << 16);\n\n vm.label(alice, \"alice\");\n vm.label(bob, \"bob\");\n vm.label(multisig, \"multisig\");\n\n // Make sure we have a non-zero base fee\n vm.fee(1000000000);\n\n ffi = new FFIInterface();\n }\n\n function emitTransactionDeposited(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gasLimit,\n bool _isCreation,\n bytes memory _data\n ) internal {\n emit TransactionDeposited(\n _from,\n _to,\n 0,\n abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data)\n );\n }\n}\n\ncontract L2OutputOracle_Initializer is CommonTest {\n // Test target\n L2OutputOracle oracle;\n L2OutputOracle oracleImpl;\n\n L2ToL1MessagePasser messagePasser =\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER));\n\n // Constructor arguments\n address internal proposer = 0x000000000000000000000000000000000000AbBa;\n address internal owner = 0x000000000000000000000000000000000000ACDC;\n uint256 internal submissionInterval = 1800;\n uint256 internal l2BlockTime = 2;\n uint256 internal startingBlockNumber = 200;\n uint256 internal startingTimestamp = 1000;\n address guardian;\n\n // Test data\n uint256 initL1Time;\n\n event OutputProposed(\n bytes32 indexed outputRoot,\n uint256 indexed l2OutputIndex,\n uint256 indexed l2BlockNumber,\n uint256 l1Timestamp\n );\n\n event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex);\n\n // Advance the evm's time to meet the L2OutputOracle's requirements for proposeL2Output\n function warpToProposeTime(uint256 _nextBlockNumber) public {\n vm.warp(oracle.computeL2Timestamp(_nextBlockNumber) + 1);\n }\n\n function setUp() public virtual override {\n super.setUp();\n guardian = makeAddr(\"guardian\");\n\n // By default the first block has timestamp and number zero, which will cause underflows in the\n // tests, so we'll move forward to these block values.\n initL1Time = startingTimestamp + 1;\n vm.warp(initL1Time);\n vm.roll(startingBlockNumber);\n // Deploy the L2OutputOracle and transfer owernship to the proposer\n oracleImpl = new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: startingTimestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(oracleImpl),\n abi.encodeCall(L2OutputOracle.initialize, (startingBlockNumber, startingTimestamp))\n );\n oracle = L2OutputOracle(address(proxy));\n vm.label(address(oracle), \"L2OutputOracle\");\n\n // Set the L2ToL1MessagePasser at the correct address\n vm.etch(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(new L2ToL1MessagePasser()).code);\n\n vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, \"L2ToL1MessagePasser\");\n }\n}\n\ncontract Portal_Initializer is L2OutputOracle_Initializer {\n // Test target\n OptimismPortal internal opImpl;\n OptimismPortal internal op;\n SystemConfig systemConfig;\n\n event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);\n event WithdrawalProven(\n bytes32 indexed withdrawalHash,\n address indexed from,\n address indexed to\n );\n\n function setUp() public virtual override {\n super.setUp();\n\n ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();\n\n systemConfig = new SystemConfig({\n _owner: address(1),\n _overhead: 0,\n _scalar: 10000,\n _batcherHash: bytes32(0),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(0),\n _config: config\n });\n\n opImpl = new OptimismPortal({\n _l2Oracle: oracle,\n _guardian: guardian,\n _paused: true,\n _config: systemConfig\n });\n\n Proxy proxy = new Proxy(multisig);\n vm.prank(multisig);\n proxy.upgradeToAndCall(\n address(opImpl),\n abi.encodeWithSelector(OptimismPortal.initialize.selector, false)\n );\n op = OptimismPortal(payable(address(proxy)));\n vm.label(address(op), \"OptimismPortal\");\n }\n}\n\ncontract Messenger_Initializer is Portal_Initializer {\n AddressManager internal addressManager;\n L1CrossDomainMessenger internal L1Messenger;\n L2CrossDomainMessenger internal L2Messenger =\n L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER);\n\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n\n event SentMessageExtension1(address indexed sender, uint256 value);\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event RelayedMessage(bytes32 indexed msgHash);\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n event TransactionDeposited(\n address indexed from,\n address indexed to,\n uint256 mint,\n uint256 value,\n uint64 gasLimit,\n bool isCreation,\n bytes data\n );\n\n event WhatHappened(bool success, bytes returndata);\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the address manager\n vm.prank(multisig);\n addressManager = new AddressManager();\n\n // Setup implementation\n L1CrossDomainMessenger L1MessengerImpl = new L1CrossDomainMessenger(op);\n\n // Setup the address manager and proxy\n vm.prank(multisig);\n addressManager.setAddress(\"OVM_L1CrossDomainMessenger\", address(L1MessengerImpl));\n ResolvedDelegateProxy proxy = new ResolvedDelegateProxy(\n addressManager,\n \"OVM_L1CrossDomainMessenger\"\n );\n L1Messenger = L1CrossDomainMessenger(address(proxy));\n L1Messenger.initialize();\n\n vm.etch(\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n address(new L2CrossDomainMessenger(address(L1Messenger))).code\n );\n\n L2Messenger.initialize();\n\n // Label addresses\n vm.label(address(addressManager), \"AddressManager\");\n vm.label(address(L1MessengerImpl), \"L1CrossDomainMessenger_Impl\");\n vm.label(address(L1Messenger), \"L1CrossDomainMessenger_Proxy\");\n vm.label(Predeploys.LEGACY_ERC20_ETH, \"LegacyERC20ETH\");\n vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, \"L2CrossDomainMessenger\");\n\n vm.label(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n \"L1CrossDomainMessenger_aliased\"\n );\n }\n}\n\ncontract Bridge_Initializer is Messenger_Initializer {\n L1StandardBridge L1Bridge;\n L2StandardBridge L2Bridge;\n OptimismMintableERC20Factory L2TokenFactory;\n OptimismMintableERC20Factory L1TokenFactory;\n ERC20 L1Token;\n ERC20 BadL1Token;\n OptimismMintableERC20 L2Token;\n LegacyMintableERC20 LegacyL2Token;\n ERC20 NativeL2Token;\n ERC20 BadL2Token;\n OptimismMintableERC20 RemoteL1Token;\n\n event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHWithdrawalFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes data\n );\n\n event ERC20DepositInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20WithdrawalFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event WithdrawalInitiated(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFinalized(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event DepositFailed(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ETHBridgeInitiated(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes data);\n\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n function setUp() public virtual override {\n super.setUp();\n\n vm.label(Predeploys.L2_STANDARD_BRIDGE, \"L2StandardBridge\");\n vm.label(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, \"OptimismMintableERC20Factory\");\n\n // Deploy the L1 bridge and initialize it with the address of the\n // L1CrossDomainMessenger\n L1ChugSplashProxy proxy = new L1ChugSplashProxy(multisig);\n vm.mockCall(\n multisig,\n abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector),\n abi.encode(true)\n );\n vm.startPrank(multisig);\n proxy.setCode(address(new L1StandardBridge(payable(address(L1Messenger)))).code);\n vm.clearMockedCalls();\n address L1Bridge_Impl = proxy.getImplementation();\n vm.stopPrank();\n\n L1Bridge = L1StandardBridge(payable(address(proxy)));\n\n vm.label(address(proxy), \"L1StandardBridge_Proxy\");\n vm.label(address(L1Bridge_Impl), \"L1StandardBridge_Impl\");\n\n // Deploy the L2StandardBridge, move it to the correct predeploy\n // address and then initialize it\n L2StandardBridge l2B = new L2StandardBridge(payable(proxy));\n vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(l2B).code);\n L2Bridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE));\n\n // Set up the L2 mintable token factory\n OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory(\n Predeploys.L2_STANDARD_BRIDGE\n );\n vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(factory).code);\n L2TokenFactory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY);\n\n vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code);\n\n L1Token = new ERC20(\"Native L1 Token\", \"L1T\");\n\n LegacyL2Token = new LegacyMintableERC20({\n _l2Bridge: address(L2Bridge),\n _l1Token: address(L1Token),\n _name: string.concat(\"LegacyL2-\", L1Token.name()),\n _symbol: string.concat(\"LegacyL2-\", L1Token.symbol())\n });\n vm.label(address(LegacyL2Token), \"LegacyMintableERC20\");\n\n // Deploy the L2 ERC20 now\n L2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(L1Token),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n BadL2Token = OptimismMintableERC20(\n L2TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L2-\", L1Token.name())),\n string(abi.encodePacked(\"L2-\", L1Token.symbol()))\n )\n );\n\n NativeL2Token = new ERC20(\"Native L2 Token\", \"L2T\");\n L1TokenFactory = new OptimismMintableERC20Factory(address(L1Bridge));\n\n RemoteL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(NativeL2Token),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n\n BadL1Token = OptimismMintableERC20(\n L1TokenFactory.createStandardL2Token(\n address(1),\n string(abi.encodePacked(\"L1-\", NativeL2Token.name())),\n string(abi.encodePacked(\"L1-\", NativeL2Token.symbol()))\n )\n );\n }\n}\n\ncontract ERC721Bridge_Initializer is Messenger_Initializer {\n L1ERC721Bridge L1Bridge;\n L2ERC721Bridge L2Bridge;\n\n function setUp() public virtual override {\n super.setUp();\n\n // Deploy the L1ERC721Bridge.\n L1Bridge = new L1ERC721Bridge(address(L1Messenger), Predeploys.L2_ERC721_BRIDGE);\n\n // Deploy the implementation for the L2ERC721Bridge and etch it into the predeploy address.\n vm.etch(\n Predeploys.L2_ERC721_BRIDGE,\n address(new L2ERC721Bridge(Predeploys.L2_CROSS_DOMAIN_MESSENGER, address(L1Bridge)))\n .code\n );\n\n // Set up a reference to the L2ERC721Bridge.\n L2Bridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE);\n\n // Label the L1 and L2 bridges.\n vm.label(address(L1Bridge), \"L1ERC721Bridge\");\n vm.label(address(L2Bridge), \"L2ERC721Bridge\");\n }\n}\n\ncontract FFIInterface is Test {\n function getProveWithdrawalTransactionInputs(Types.WithdrawalTransaction memory _tx)\n external\n returns (\n bytes32,\n bytes32,\n bytes32,\n bytes32,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"getProveWithdrawalTransactionInputs\";\n cmds[2] = vm.toString(_tx.nonce);\n cmds[3] = vm.toString(_tx.sender);\n cmds[4] = vm.toString(_tx.target);\n cmds[5] = vm.toString(_tx.value);\n cmds[6] = vm.toString(_tx.gasLimit);\n cmds[7] = vm.toString(_tx.data);\n\n bytes memory result = vm.ffi(cmds);\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = abi.decode(result, (bytes32, bytes32, bytes32, bytes32, bytes[]));\n\n return (stateRoot, storageRoot, outputRoot, withdrawalHash, withdrawalProof);\n }\n\n function hashCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashCrossDomainMessage\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashWithdrawal(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes32) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashWithdrawal\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashOutputRootProof(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external returns (bytes32) {\n string[] memory cmds = new string[](6);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashOutputRootProof\";\n cmds[2] = Strings.toHexString(uint256(_version));\n cmds[3] = Strings.toHexString(uint256(_stateRoot));\n cmds[4] = Strings.toHexString(uint256(_messagePasserStorageRoot));\n cmds[5] = Strings.toHexString(uint256(_latestBlockhash));\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function hashDepositTransaction(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint64 _logIndex\n ) external returns (bytes32) {\n string[] memory cmds = new string[](10);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"hashDepositTransaction\";\n cmds[2] = \"0x0000000000000000000000000000000000000000000000000000000000000000\";\n cmds[3] = vm.toString(_logIndex);\n cmds[4] = vm.toString(_from);\n cmds[5] = vm.toString(_to);\n cmds[6] = vm.toString(_mint);\n cmds[7] = vm.toString(_value);\n cmds[8] = vm.toString(_gas);\n cmds[9] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes32));\n }\n\n function encodeDepositTransaction(Types.UserDepositTransaction calldata txn)\n external\n returns (bytes memory)\n {\n string[] memory cmds = new string[](11);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"encodeDepositTransaction\";\n cmds[2] = vm.toString(txn.from);\n cmds[3] = vm.toString(txn.to);\n cmds[4] = vm.toString(txn.value);\n cmds[5] = vm.toString(txn.mint);\n cmds[6] = vm.toString(txn.gasLimit);\n cmds[7] = vm.toString(txn.isCreation);\n cmds[8] = vm.toString(txn.data);\n cmds[9] = vm.toString(txn.l1BlockHash);\n cmds[10] = vm.toString(txn.logIndex);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function encodeCrossDomainMessage(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external returns (bytes memory) {\n string[] memory cmds = new string[](8);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"encodeCrossDomainMessage\";\n cmds[2] = vm.toString(_nonce);\n cmds[3] = vm.toString(_sender);\n cmds[4] = vm.toString(_target);\n cmds[5] = vm.toString(_value);\n cmds[6] = vm.toString(_gasLimit);\n cmds[7] = vm.toString(_data);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (bytes));\n }\n\n function decodeVersionedNonce(uint256 nonce) external returns (uint256, uint256) {\n string[] memory cmds = new string[](3);\n cmds[0] = \"scripts/differential-testing/differential-testing\";\n cmds[1] = \"decodeVersionedNonce\";\n cmds[2] = vm.toString(nonce);\n\n bytes memory result = vm.ffi(cmds);\n return abi.decode(result, (uint256, uint256));\n }\n\n function getMerkleTrieFuzzCase(string memory variant)\n external\n returns (\n bytes32,\n bytes memory,\n bytes memory,\n bytes[] memory\n )\n {\n string[] memory cmds = new string[](5);\n cmds[0] = \"./test-case-generator/fuzz\";\n cmds[1] = \"-m\";\n cmds[2] = \"trie\";\n cmds[3] = \"-v\";\n cmds[4] = variant;\n\n return abi.decode(vm.ffi(cmds), (bytes32, bytes, bytes, bytes[]));\n }\n}\n\n// Used for testing a future upgrade beyond the current implementations.\n// We include some variables so that we can sanity check accessing storage values after an upgrade.\ncontract NextImpl is Initializable {\n // Initializable occupies the zero-th slot.\n bytes32 slot1;\n bytes32[19] __gap;\n bytes32 slot21;\n bytes32 public constant slot21Init = bytes32(hex\"1337\");\n\n function initialize() public reinitializer(2) {\n // Slot21 is unused by an of our upgradeable contracts.\n // This is used to verify that we can access this value after an upgrade.\n slot21 = slot21Init;\n }\n}\n\ncontract Reverter {\n fallback() external {\n revert();\n }\n}\n\n// Useful for testing reentrancy guards\ncontract CallerCaller {\n event WhatHappened(bool success, bytes returndata);\n\n fallback() external {\n (bool success, bytes memory returndata) = msg.sender.call(msg.data);\n emit WhatHappened(success, returndata);\n assembly {\n switch success\n case 0 {\n revert(add(returndata, 0x20), mload(returndata))\n }\n default {\n return(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n}\n\n// Used for testing the `CrossDomainMessenger`'s per-message reentrancy guard.\ncontract ConfigurableCaller {\n bool doRevert = true;\n address target;\n bytes payload;\n\n event WhatHappened(bool success, bytes returndata);\n\n /**\n * @notice Call the configured target with the configured payload OR revert.\n */\n function call() external {\n if (doRevert) {\n revert(\"ConfigurableCaller: revert\");\n } else {\n (bool success, bytes memory returndata) = address(target).call(payload);\n emit WhatHappened(success, returndata);\n assembly {\n switch success\n case 0 {\n revert(add(returndata, 0x20), mload(returndata))\n }\n default {\n return(add(returndata, 0x20), mload(returndata))\n }\n }\n }\n }\n\n /**\n * @notice Set whether or not to have `call` revert.\n */\n function setDoRevert(bool _doRevert) external {\n doRevert = _doRevert;\n }\n\n /**\n * @notice Set the target for the call made in `call`.\n */\n function setTarget(address _target) external {\n target = _target;\n }\n\n /**\n * @notice Set the payload for the call made in `call`.\n */\n function setPayload(bytes calldata _payload) external {\n payload = _payload;\n }\n\n /**\n * @notice Fallback function that reverts if `doRevert` is true.\n * Otherwise, it does nothing.\n */\n fallback() external {\n if (doRevert) {\n revert(\"ConfigurableCaller: revert\");\n }\n }\n}\n" - }, - "contracts/test/CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, CallerCaller } from \"./CommonTest.t.sol\";\n\n// CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2\n// CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract.\ncontract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {\n // Ensure that baseGas passes for the max value of _minGasLimit,\n // this is about 4 Billion.\n function test_baseGas_succeeds() external view {\n L1Messenger.baseGas(hex\"ff\", type(uint32).max);\n }\n\n // Fuzz for other values which might cause a revert in baseGas.\n function testFuzz_baseGas_succeeds(uint32 _minGasLimit) external view {\n L1Messenger.baseGas(hex\"ff\", _minGasLimit);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest, Portal_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable } from \"../L2/CrossDomainOwnable.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Vm, VmSafe } from \"forge-std/Vm.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract XDomainSetter is CrossDomainOwnable {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable_Test is CommonTest {\n XDomainSetter setter;\n\n function setUp() public override {\n super.setUp();\n setter = new XDomainSetter();\n }\n\n // Check that the revert message is correct\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable: caller is not the owner\");\n setter.set(1);\n }\n\n // Check that making a call can set the value properly\n function test_onlyOwner_succeeds() external {\n assertEq(setter.value(), 0);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(setter.owner()));\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n\ncontract CrossDomainOwnableThroughPortal_Test is Portal_Initializer {\n XDomainSetter setter;\n\n function setUp() public override {\n super.setUp();\n\n vm.prank(alice);\n setter = new XDomainSetter();\n }\n\n function test_depositTransaction_crossDomainOwner_succeeds() external {\n vm.recordLogs();\n\n vm.prank(alice);\n op.depositTransaction({\n _to: address(setter),\n _value: 0,\n _gasLimit: 21_000,\n _isCreation: false,\n _data: abi.encodeWithSelector(XDomainSetter.set.selector, 1)\n });\n\n // Simulate the operation of the `op-node` by parsing data\n // from logs\n VmSafe.Log[] memory logs = vm.getRecordedLogs();\n // Only 1 log emitted\n assertEq(logs.length, 1);\n\n VmSafe.Log memory log = logs[0];\n\n // It is the expected topic\n bytes32 topic = log.topics[0];\n assertEq(topic, keccak256(\"TransactionDeposited(address,address,uint256,bytes)\"));\n\n // from is indexed and the first argument to the event.\n bytes32 _from = log.topics[1];\n address from = Bytes32AddressLib.fromLast20Bytes(_from);\n\n assertEq(AddressAliasHelper.undoL1ToL2Alias(from), alice);\n\n // Make a call from the \"from\" value received from the log.\n // In theory the opaque data could be parsed from the log\n // and passed to a low level call to \"to\", but calling set\n // directly on the setter is good enough.\n vm.prank(from);\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable2.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\nimport { CommonTest, Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable2 } from \"../L2/CrossDomainOwnable2.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract XDomainSetter2 is CrossDomainOwnable2 {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable2_Test is Messenger_Initializer {\n XDomainSetter2 setter;\n\n function setUp() public override {\n super.setUp();\n vm.prank(alice);\n setter = new XDomainSetter2();\n }\n\n function test_onlyOwner_notMessenger_reverts() external {\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the messenger\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n // set the xDomainMsgSender storage slot\n bytes32 key = bytes32(uint256(204));\n bytes32 value = Bytes32AddressLib.fillLast12Bytes(address(alice));\n vm.store(address(L2Messenger), key, value);\n\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"CrossDomainOwnable2: caller is not the owner\");\n setter.set(1);\n }\n\n function test_onlyOwner_notOwner2_reverts() external {\n uint240 nonce = 0;\n address sender = bob;\n address target = address(setter);\n uint256 value = 0;\n uint256 minGasLimit = 0;\n bytes memory message = abi.encodeWithSelector(XDomainSetter2.set.selector, 1);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n // It should be a failed message. The revert is caught,\n // so we cannot expectRevert here.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n assertEq(setter.value(), 0);\n }\n\n function test_onlyOwner_succeeds() external {\n address owner = setter.owner();\n\n // Simulate the L2 execution where the call is coming from\n // the L1CrossDomainMessenger\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(1, 1),\n owner,\n address(setter),\n 0,\n 0,\n abi.encodeWithSelector(XDomainSetter2.set.selector, 2)\n );\n\n assertEq(setter.value(), 2);\n }\n}\n" - }, - "contracts/test/CrossDomainOwnable3.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\nimport { CommonTest, Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { CrossDomainOwnable3 } from \"../L2/CrossDomainOwnable3.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\ncontract XDomainSetter3 is CrossDomainOwnable3 {\n uint256 public value;\n\n function set(uint256 _value) external onlyOwner {\n value = _value;\n }\n}\n\ncontract CrossDomainOwnable3_Test is Messenger_Initializer {\n XDomainSetter3 setter;\n\n /**\n * @notice OpenZeppelin Ownable.sol transferOwnership event\n */\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @notice CrossDomainOwnable3.sol transferOwnership event\n */\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner,\n bool isLocal\n );\n\n function setUp() public override {\n super.setUp();\n vm.prank(alice);\n setter = new XDomainSetter3();\n }\n\n function test_constructor_succeeds() public {\n assertEq(setter.owner(), alice);\n assertEq(setter.isLocal(), true);\n }\n\n function test_localOnlyOwner_notOwner_reverts() public {\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.set(1);\n }\n\n function test_transferOwnership_notOwner_reverts() public {\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.transferOwnership({ _owner: bob, _isLocal: true });\n }\n\n function test_crossDomainOnlyOwner_notOwner_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n // set the xDomainMsgSender storage slot\n bytes32 key = bytes32(uint256(204));\n bytes32 value = Bytes32AddressLib.fillLast12Bytes(bob);\n vm.store(address(L2Messenger), key, value);\n\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the owner\");\n setter.set(1);\n }\n\n function test_crossDomainOnlyOwner_notOwner2_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n assertEq(setter.isLocal(), false);\n\n uint240 nonce = 0;\n address sender = bob;\n address target = address(setter);\n uint256 value = 0;\n uint256 minGasLimit = 0;\n bytes memory message = abi.encodeWithSelector(XDomainSetter3.set.selector, 1);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n // It should be a failed message. The revert is caught,\n // so we cannot expectRevert here.\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit FailedRelayedMessage(hash);\n\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(nonce, 1),\n sender,\n target,\n value,\n minGasLimit,\n message\n );\n\n assertEq(setter.value(), 0);\n }\n\n function test_crossDomainOnlyOwner_notMessenger_reverts() public {\n vm.expectEmit(true, true, true, true);\n\n // OpenZeppelin Ownable.sol transferOwnership event\n emit OwnershipTransferred(alice, alice);\n\n // CrossDomainOwnable3.sol transferOwnership event\n emit OwnershipTransferred(alice, alice, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: alice, _isLocal: false });\n\n vm.prank(bob);\n vm.expectRevert(\"CrossDomainOwnable3: caller is not the messenger\");\n setter.set(1);\n }\n\n function test_transferOwnership_zeroAddress_reverts() public {\n vm.prank(setter.owner());\n vm.expectRevert(\"CrossDomainOwnable3: new owner is the zero address\");\n setter.transferOwnership({ _owner: address(0), _isLocal: true });\n }\n\n function test_transferOwnership_noLocalZeroAddress_reverts() public {\n vm.prank(setter.owner());\n vm.expectRevert(\"Ownable: new owner is the zero address\");\n setter.transferOwnership(address(0));\n }\n\n function test_localOnlyOwner_succeeds() public {\n assertEq(setter.isLocal(), true);\n vm.prank(setter.owner());\n setter.set(1);\n assertEq(setter.value(), 1);\n }\n\n function test_localTransferOwnership_succeeds() public {\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n emit OwnershipTransferred(alice, bob, true);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: bob, _isLocal: true });\n\n assertEq(setter.isLocal(), true);\n\n vm.prank(bob);\n setter.set(2);\n assertEq(setter.value(), 2);\n }\n\n /**\n * @notice The existing transferOwnership(address) method\n * still exists on the contract\n */\n function test_transferOwnershipNoLocal_succeeds() public {\n bool isLocal = setter.isLocal();\n\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n\n vm.prank(setter.owner());\n setter.transferOwnership(bob);\n\n // isLocal has not changed\n assertEq(setter.isLocal(), isLocal);\n\n vm.prank(bob);\n setter.set(2);\n assertEq(setter.value(), 2);\n }\n\n function test_crossDomainTransferOwnership_succeeds() public {\n vm.expectEmit(true, true, true, true, address(setter));\n emit OwnershipTransferred(alice, bob);\n emit OwnershipTransferred(alice, bob, false);\n\n vm.prank(setter.owner());\n setter.transferOwnership({ _owner: bob, _isLocal: false });\n\n assertEq(setter.isLocal(), false);\n\n // Simulate the L2 execution where the call is coming from\n // the L1CrossDomainMessenger\n vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(1, 1),\n bob,\n address(setter),\n 0,\n 0,\n abi.encodeWithSelector(XDomainSetter3.set.selector, 2)\n );\n\n assertEq(setter.value(), 2);\n }\n}\n" - }, - "contracts/test/DeployerWhitelist.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { DeployerWhitelist } from \"../legacy/DeployerWhitelist.sol\";\n\ncontract DeployerWhitelist_Test is CommonTest {\n DeployerWhitelist list;\n\n function setUp() public virtual override {\n list = new DeployerWhitelist();\n }\n\n // The owner should be address(0)\n function test_owner_succeeds() external {\n assertEq(list.owner(), address(0));\n }\n\n // The storage slot for the owner must be the same\n function test_storageSlots_succeeds() external {\n vm.prank(list.owner());\n list.setOwner(address(1));\n\n assertEq(bytes32(uint256(1)), vm.load(address(list), bytes32(uint256(0))));\n }\n}\n" - }, - "contracts/test/Encoding.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { LegacyCrossDomainUtils } from \"../libraries/LegacyCrossDomainUtils.sol\";\n\ncontract Encoding_Test is CommonTest {\n function testFuzz_nonceVersioning_succeeds(uint240 _nonce, uint16 _version) external {\n (uint240 nonce, uint16 version) = Encoding.decodeVersionedNonce(\n Encoding.encodeVersionedNonce(_nonce, _version)\n );\n assertEq(version, _version);\n assertEq(nonce, _nonce);\n }\n\n function testDiff_decodeVersionedNonce_succeeds(uint240 _nonce, uint16 _version) external {\n uint256 nonce = uint256(Encoding.encodeVersionedNonce(_nonce, _version));\n (uint256 decodedNonce, uint256 decodedVersion) = ffi.decodeVersionedNonce(nonce);\n\n assertEq(_version, uint16(decodedVersion));\n\n assertEq(_nonce, uint240(decodedNonce));\n }\n\n function testDiff_encodeCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint8 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint8 version = _version % 2;\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes memory encoding = Encoding.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n bytes memory _encoding = ffi.encodeCrossDomainMessage(\n nonce,\n _sender,\n _target,\n _value,\n _gasLimit,\n _data\n );\n\n assertEq(encoding, _encoding);\n }\n\n function testFuzz_encodeCrossDomainMessageV0_matchesLegacy_succeeds(\n uint240 _nonce,\n address _sender,\n address _target,\n bytes memory _data\n ) external {\n uint8 version = 0;\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n bytes memory legacyEncoding = LegacyCrossDomainUtils.encodeXDomainCalldata(\n _target,\n _sender,\n _data,\n nonce\n );\n\n bytes memory bedrockEncoding = Encoding.encodeCrossDomainMessageV0(\n _target,\n _sender,\n _data,\n nonce\n );\n\n assertEq(legacyEncoding, bedrockEncoding);\n }\n\n function testDiff_encodeDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bool isCreate,\n bytes memory _data,\n uint64 _logIndex\n ) external {\n Types.UserDepositTransaction memory t = Types.UserDepositTransaction(\n _from,\n _to,\n isCreate,\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n );\n\n bytes memory txn = Encoding.encodeDepositTransaction(t);\n bytes memory _txn = ffi.encodeDepositTransaction(t);\n\n assertEq(txn, _txn);\n }\n}\n" - }, - "contracts/test/FeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { L1FeeVault } from \"../L2/L1FeeVault.sol\";\nimport { BaseFeeVault } from \"../L2/BaseFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n// Test the implementations of the FeeVault\ncontract FeeVault_Test is Bridge_Initializer {\n BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT));\n L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT));\n\n address constant recipient = address(0x10000);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.BASE_FEE_VAULT, address(new BaseFeeVault(recipient)).code);\n vm.etch(Predeploys.L1_FEE_VAULT, address(new L1FeeVault(recipient)).code);\n\n vm.label(Predeploys.BASE_FEE_VAULT, \"BaseFeeVault\");\n vm.label(Predeploys.L1_FEE_VAULT, \"L1FeeVault\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(baseFeeVault.RECIPIENT(), recipient);\n assertEq(l1FeeVault.RECIPIENT(), recipient);\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n}\n" - }, - "contracts/test/GasPriceOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GasPriceOracle } from \"../L2/GasPriceOracle.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract GasPriceOracle_Test is CommonTest {\n event OverheadUpdated(uint256);\n event ScalarUpdated(uint256);\n event DecimalsUpdated(uint256);\n\n GasPriceOracle gasOracle;\n L1Block l1Block;\n address depositor;\n\n // set the initial L1 context values\n uint64 constant number = 10;\n uint64 constant timestamp = 11;\n uint256 constant basefee = 100;\n bytes32 constant hash = bytes32(uint256(64));\n uint64 constant sequenceNumber = 0;\n bytes32 constant batcherHash = bytes32(uint256(777));\n uint256 constant l1FeeOverhead = 310;\n uint256 constant l1FeeScalar = 10;\n\n function setUp() public virtual override {\n super.setUp();\n // place the L1Block contract at the predeploy address\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n\n l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n depositor = l1Block.DEPOSITOR_ACCOUNT();\n\n // We are not setting the gas oracle at its predeploy\n // address for simplicity purposes. Nothing in this test\n // requires it to be at a particular address\n gasOracle = new GasPriceOracle();\n\n vm.prank(depositor);\n l1Block.setL1BlockValues({\n _number: number,\n _timestamp: timestamp,\n _basefee: basefee,\n _hash: hash,\n _sequenceNumber: sequenceNumber,\n _batcherHash: batcherHash,\n _l1FeeOverhead: l1FeeOverhead,\n _l1FeeScalar: l1FeeScalar\n });\n }\n\n function test_l1BaseFee_succeeds() external {\n assertEq(gasOracle.l1BaseFee(), basefee);\n }\n\n function test_gasPrice_succeeds() external {\n vm.fee(100);\n uint256 gasPrice = gasOracle.gasPrice();\n assertEq(gasPrice, 100);\n }\n\n function test_baseFee_succeeds() external {\n vm.fee(64);\n uint256 gasPrice = gasOracle.baseFee();\n assertEq(gasPrice, 64);\n }\n\n function test_scalar_succeeds() external {\n assertEq(gasOracle.scalar(), l1FeeScalar);\n }\n\n function test_overhead_succeeds() external {\n assertEq(gasOracle.overhead(), l1FeeOverhead);\n }\n\n function test_decimals_succeeds() external {\n assertEq(gasOracle.decimals(), 6);\n assertEq(gasOracle.DECIMALS(), 6);\n }\n\n // Removed in bedrock\n function test_setGasPrice_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setGasPrice(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n\n // Removed in bedrock\n function test_setL1BaseFee_doesNotExist_reverts() external {\n (bool success, bytes memory returndata) = address(gasOracle).call(\n abi.encodeWithSignature(\"setL1BaseFee(uint256)\", 1)\n );\n\n assertEq(success, false);\n assertEq(returndata, hex\"\");\n }\n}\n" - }, - "contracts/test/GovernanceToken.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract GovernanceToken_Test is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n\n function setUp() public virtual override {\n super.setUp();\n vm.prank(owner);\n gov = new GovernanceToken();\n }\n\n function test_constructor_succeeds() external {\n assertEq(gov.owner(), owner);\n assertEq(gov.name(), \"Optimism\");\n assertEq(gov.symbol(), \"OP\");\n assertEq(gov.decimals(), 18);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_mint_fromOwner_succeeds() external {\n // Mint 100 tokens.\n vm.prank(owner);\n gov.mint(owner, 100);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 100);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_mint_fromNotOwner_reverts() external {\n // Mint 100 tokens as rando.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n gov.mint(owner, 100);\n\n // Balance does not update.\n assertEq(gov.balanceOf(owner), 0);\n assertEq(gov.totalSupply(), 0);\n }\n\n function test_burn_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando burns their tokens.\n vm.prank(rando);\n gov.burn(50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_burnFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to burn 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner burns 50 tokens from rando.\n vm.prank(owner);\n gov.burnFrom(rando, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 50);\n }\n\n function test_transfer_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando transfers 50 tokens to owner.\n vm.prank(rando);\n gov.transfer(owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_approve_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n\n function test_transferFrom_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Owner transfers 50 tokens from rando to owner.\n vm.prank(owner);\n gov.transferFrom(rando, owner, 50);\n\n // Balances have updated correctly.\n assertEq(gov.balanceOf(owner), 50);\n assertEq(gov.balanceOf(rando), 50);\n assertEq(gov.totalSupply(), 100);\n }\n\n function test_increaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 50 tokens.\n vm.prank(rando);\n gov.approve(owner, 50);\n\n // Rando increases allowance by 50 tokens.\n vm.prank(rando);\n gov.increaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 100);\n }\n\n function test_decreaseAllowance_succeeds() external {\n // Mint 100 tokens to rando.\n vm.prank(owner);\n gov.mint(rando, 100);\n\n // Rando approves owner to spend 100 tokens.\n vm.prank(rando);\n gov.approve(owner, 100);\n\n // Rando decreases allowance by 50 tokens.\n vm.prank(rando);\n gov.decreaseAllowance(owner, 50);\n\n // Allowances have updated.\n assertEq(gov.allowance(rando, owner), 50);\n }\n}\n" - }, - "contracts/test/Hashing.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { LegacyCrossDomainUtils } from \"../libraries/LegacyCrossDomainUtils.sol\";\n\ncontract Hashing_hashDepositSource_Test is CommonTest {\n /**\n * @notice Tests that hashDepositSource returns the correct hash in a simple case.\n */\n function test_hashDepositSource_succeeds() external {\n assertEq(\n Hashing.hashDepositSource(\n 0xd25df7858efc1778118fb133ac561b138845361626dfb976699c5287ed0f4959,\n 0x1\n ),\n 0xf923fb07134d7d287cb52c770cc619e17e82606c21a875c92f4c63b65280a5cc\n );\n }\n}\n\ncontract Hashing_hashCrossDomainMessage_Test is CommonTest {\n /**\n * @notice Tests that hashCrossDomainMessage returns the correct hash in a simple case.\n */\n function testDiff_hashCrossDomainMessage_succeeds(\n uint240 _nonce,\n uint16 _version,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n // Ensure the version is valid.\n uint16 version = uint16(bound(uint256(_version), 0, 1));\n uint256 nonce = Encoding.encodeVersionedNonce(_nonce, version);\n\n assertEq(\n Hashing.hashCrossDomainMessage(nonce, _sender, _target, _value, _gasLimit, _data),\n ffi.hashCrossDomainMessage(nonce, _sender, _target, _value, _gasLimit, _data)\n );\n }\n\n /**\n * @notice Tests that hashCrossDomainMessageV0 matches the hash of the legacy encoding.\n */\n function testFuzz_hashCrossDomainMessageV0_matchesLegacy_succeeds(\n address _target,\n address _sender,\n bytes memory _message,\n uint256 _messageNonce\n ) external {\n assertEq(\n keccak256(\n LegacyCrossDomainUtils.encodeXDomainCalldata(\n _target,\n _sender,\n _message,\n _messageNonce\n )\n ),\n Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _messageNonce)\n );\n }\n}\n\ncontract Hashing_hashWithdrawal_Test is CommonTest {\n /**\n * @notice Tests that hashWithdrawal returns the correct hash in a simple case.\n */\n function testDiff_hashWithdrawal_succeeds(\n uint256 _nonce,\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n assertEq(\n Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(_nonce, _sender, _target, _value, _gasLimit, _data)\n ),\n ffi.hashWithdrawal(_nonce, _sender, _target, _value, _gasLimit, _data)\n );\n }\n}\n\ncontract Hashing_hashOutputRootProof_Test is CommonTest {\n /**\n * @notice Tests that hashOutputRootProof returns the correct hash in a simple case.\n */\n function testDiff_hashOutputRootProof_succeeds(\n bytes32 _version,\n bytes32 _stateRoot,\n bytes32 _messagePasserStorageRoot,\n bytes32 _latestBlockhash\n ) external {\n assertEq(\n Hashing.hashOutputRootProof(\n Types.OutputRootProof({\n version: _version,\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _messagePasserStorageRoot,\n latestBlockhash: _latestBlockhash\n })\n ),\n ffi.hashOutputRootProof(\n _version,\n _stateRoot,\n _messagePasserStorageRoot,\n _latestBlockhash\n )\n );\n }\n}\n\ncontract Hashing_hashDepositTransaction_Test is CommonTest {\n /**\n * @notice Tests that hashDepositTransaction returns the correct hash in a simple case.\n */\n function testDiff_hashDepositTransaction_succeeds(\n address _from,\n address _to,\n uint256 _mint,\n uint256 _value,\n uint64 _gas,\n bytes memory _data,\n uint64 _logIndex\n ) external {\n assertEq(\n Hashing.hashDepositTransaction(\n Types.UserDepositTransaction(\n _from,\n _to,\n false, // isCreate\n _value,\n _mint,\n _gas,\n _data,\n bytes32(uint256(0)),\n _logIndex\n )\n ),\n ffi.hashDepositTransaction(_from, _to, _mint, _value, _gas, _data, _logIndex)\n );\n }\n}\n" - }, - "contracts/test/L1Block.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\n\ncontract L1BlockTest is CommonTest {\n L1Block lb;\n address depositor;\n bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1));\n\n function setUp() public virtual override {\n super.setUp();\n lb = new L1Block();\n depositor = lb.DEPOSITOR_ACCOUNT();\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: uint64(1),\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: NON_ZERO_HASH,\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(0),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function testFuzz_updatesValues_succeeds(\n uint64 n,\n uint64 t,\n uint256 b,\n bytes32 h,\n uint64 s,\n bytes32 bt,\n uint256 fo,\n uint256 fs\n ) external {\n vm.prank(depositor);\n lb.setL1BlockValues(n, t, b, h, s, bt, fo, fs);\n assertEq(lb.number(), n);\n assertEq(lb.timestamp(), t);\n assertEq(lb.basefee(), b);\n assertEq(lb.hash(), h);\n assertEq(lb.sequenceNumber(), s);\n assertEq(lb.batcherHash(), bt);\n assertEq(lb.l1FeeOverhead(), fo);\n assertEq(lb.l1FeeScalar(), fs);\n }\n\n function test_number_succeeds() external {\n assertEq(lb.number(), uint64(1));\n }\n\n function test_timestamp_succeeds() external {\n assertEq(lb.timestamp(), uint64(2));\n }\n\n function test_basefee_succeeds() external {\n assertEq(lb.basefee(), 3);\n }\n\n function test_hash_succeeds() external {\n assertEq(lb.hash(), NON_ZERO_HASH);\n }\n\n function test_sequenceNumber_succeeds() external {\n assertEq(lb.sequenceNumber(), uint64(4));\n }\n\n function test_updateValues_succeeds() external {\n vm.prank(depositor);\n lb.setL1BlockValues({\n _number: type(uint64).max,\n _timestamp: type(uint64).max,\n _basefee: type(uint256).max,\n _hash: keccak256(abi.encode(1)),\n _sequenceNumber: type(uint64).max,\n _batcherHash: bytes32(type(uint256).max),\n _l1FeeOverhead: type(uint256).max,\n _l1FeeScalar: type(uint256).max\n });\n }\n}\n" - }, - "contracts/test/L1BlockNumber.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { L1Block } from \"../L2/L1Block.sol\";\nimport { L1BlockNumber } from \"../legacy/L1BlockNumber.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract L1BlockNumberTest is Test {\n L1Block lb;\n L1BlockNumber bn;\n\n uint64 constant number = 99;\n\n function setUp() external {\n vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);\n lb = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);\n bn = new L1BlockNumber();\n vm.prank(lb.DEPOSITOR_ACCOUNT());\n\n lb.setL1BlockValues({\n _number: number,\n _timestamp: uint64(2),\n _basefee: 3,\n _hash: bytes32(uint256(10)),\n _sequenceNumber: uint64(4),\n _batcherHash: bytes32(uint256(0)),\n _l1FeeOverhead: 2,\n _l1FeeScalar: 3\n });\n }\n\n function test_getL1BlockNumber_succeeds() external {\n assertEq(bn.getL1BlockNumber(), number);\n }\n\n function test_fallback_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n\n function test_receive_succeeds() external {\n (bool success, bytes memory ret) = address(bn).call{ value: 1 }(hex\"\");\n assertEq(success, true);\n assertEq(ret, abi.encode(number));\n }\n}\n" - }, - "contracts/test/L1CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Testing utilities */\nimport { Messenger_Initializer, Reverter, ConfigurableCaller } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle_Initializer } from \"./L2OutputOracle.t.sol\";\n\n/* Libraries */\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\n\n/* Target contract dependencies */\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\n\n/* Target contract */\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\n\ncontract L1CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n // the version is encoded in the nonce\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L1Messenger.messageNonce());\n assertEq(version, L1Messenger.MESSAGE_VERSION());\n }\n\n // sendMessage: should be able to send a single message\n // TODO: this same test needs to be done with the legacy message type\n // by setting the message version to 0\n function test_sendMessage_succeeds() external {\n // deposit transaction on the optimism portal should be called\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n )\n );\n\n // TransactionDeposited event\n vm.expectEmit(true, true, true, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)),\n Predeploys.L2_CROSS_DOMAIN_MESSENGER,\n 0,\n 0,\n L1Messenger.baseGas(hex\"ff\", 100),\n false,\n Encoding.encodeCrossDomainMessage(\n L1Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n )\n );\n\n // SentMessage event\n vm.expectEmit(true, true, true, true);\n emit SentMessage(recipient, alice, hex\"ff\", L1Messenger.messageNonce(), 100);\n\n // SentMessageExtension1 event\n vm.expectEmit(true, true, true, true);\n emit SentMessageExtension1(alice, 0);\n\n vm.prank(alice);\n L1Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n // sendMessage: should be able to send the same message twice\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L1Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L1Messenger.messageNonce());\n }\n\n function test_xDomainSender_notSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n // xDomainMessageSender: should return the xDomainMsgSender address\n // TODO: might need a test contract\n // function test_xDomainSenderSetCorrectly() external {}\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(address(op));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 2 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n // relayMessage: should send a successful call to the target contract\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.expectCall(target, hex\"1111\");\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L1Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n // set the target to be the OptimismPortal\n address target = address(op);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.prank(address(op));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n\n vm.store(address(op), 0, bytes32(abi.encode(sender)));\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: should revert if eth is sent from a contract other than the standard bridge\n function test_replayMessage_withValue_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory message = hex\"1111\";\n\n vm.expectRevert(\n \"CrossDomainMessenger: value must be zero unless message is from a system address\"\n );\n L1Messenger.relayMessage{ value: 100 }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L1Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n vm.expectCall(target, hex\"1111\");\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n // relayMessage: Should revert if the recipient is trying to reenter with the\n // same message.\n function test_relayMessage_reentrancySameMessage_reverts() external {\n ConfigurableCaller caller = new ConfigurableCaller();\n address target = address(caller);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory callMessage = abi.encodeWithSelector(caller.call.selector);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Set the portal's `l2Sender` to the `sender`.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(uint256(uint160(sender))));\n\n // Act as the portal and call the `relayMessage` function with the `innerMessage`.\n vm.prank(address(op));\n vm.expectCall(target, callMessage);\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Assert that the message failed to be relayed\n assertFalse(L1Messenger.successfulMessages(hash));\n assertTrue(L1Messenger.failedMessages(hash));\n\n // Set the configurable caller's target to `L1Messenger` and set the payload to `relayMessage(...)`.\n caller.setDoRevert(false);\n caller.setTarget(address(L1Messenger));\n caller.setPayload(\n abi.encodeWithSelector(\n L1Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n callMessage\n )\n );\n\n // Attempt to replay the failed message, which will *not* immediately revert this time around,\n // but attempt to reenter `relayMessage` with the same message hash. The reentrancy attempt should\n // revert.\n vm.expectEmit(true, true, true, true, target);\n emit WhatHappened(\n false,\n abi.encodeWithSignature(\"Error(string)\", \"ReentrancyGuard: reentrant call\")\n );\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Assert that the message still failed to be relayed.\n assertFalse(L1Messenger.successfulMessages(hash));\n assertTrue(L1Messenger.failedMessages(hash));\n }\n\n // relayMessage: should not revert if the recipient reenters `relayMessage` with a different\n // message hash.\n function test_relayMessage_reentrancyDiffMessage_succeeds() external {\n ConfigurableCaller caller = new ConfigurableCaller();\n address target = address(caller);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n bytes memory messageA = abi.encodeWithSelector(caller.call.selector);\n bytes memory messageB = hex\"\";\n\n bytes32 hashA = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n bytes32 hashB = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageB\n );\n\n // Set the portal's `l2Sender` to the `sender`.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(uint256(uint160(sender))));\n\n // Act as the portal and call the `relayMessage` function with both `messageA` and `messageB`.\n vm.startPrank(address(op));\n\n vm.expectCall(target, messageA);\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n vm.expectCall(target, messageB);\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageB\n );\n\n // Stop acting as the portal\n vm.stopPrank();\n\n // Assert that both messages failed to be relayed\n assertFalse(L1Messenger.successfulMessages(hashA));\n assertFalse(L1Messenger.successfulMessages(hashB));\n assertTrue(L1Messenger.failedMessages(hashA));\n assertTrue(L1Messenger.failedMessages(hashB));\n\n // Set the configurable caller's target to `L1Messenger` and set the payload to `relayMessage(...)`.\n caller.setDoRevert(false);\n caller.setTarget(address(L1Messenger));\n caller.setPayload(\n abi.encodeWithSelector(\n L1Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageB\n )\n );\n\n // Attempt to replay the failed message, which will *not* immediately revert this time around,\n // but attempt to reenter `relayMessage` with messageB. The reentrancy attempt should succeed\n // because the message hashes are different.\n vm.expectEmit(true, true, true, true, target);\n emit WhatHappened(true, hex\"\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n\n // Assert that both messages are now in the `successfulMessages` mapping.\n assertTrue(L1Messenger.successfulMessages(hashA));\n assertTrue(L1Messenger.successfulMessages(hashB));\n }\n\n function test_relayMessage_legacy_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyOldReplay_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Mark legacy message as already relayed.\n uint256 successfulMessagesSlot = 203;\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(target, sender, hex\"1111\", 0);\n bytes32 slot = keccak256(abi.encode(oldHash, successfulMessagesSlot));\n vm.store(address(L1Messenger), slot, bytes32(uint256(1)));\n\n // Expect revert.\n vm.expectRevert(\"CrossDomainMessenger: legacy withdrawal already relayed\");\n\n // Relay the message.\n vm.prank(address(op));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // Message was not relayed.\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), false);\n }\n\n function test_relayMessage_legacyRetryAfterFailure_succeeds() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect FailedRelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit FailedRelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n }\n\n function test_relayMessage_legacyRetryAfterSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), false);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n\n // Retry the message.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() external {\n address target = address(0xabcd);\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n uint256 value = 100;\n\n // Compute the message hash.\n bytes32 hash = Hashing.hashCrossDomainMessageV1(\n // Using a legacy nonce with version 0.\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Turn the target into a Reverter.\n vm.etch(target, address(new Reverter()).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Relay the message.\n vm.deal(address(op), value);\n vm.prank(address(op));\n L1Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message failed.\n assertEq(address(L1Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L1Messenger.successfulMessages(hash), false);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Make the target not revert anymore.\n vm.etch(target, address(0).code);\n\n // Target should be called with expected data.\n vm.expectCall(target, hex\"1111\");\n\n // Expect RelayedMessage event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit RelayedMessage(hash);\n\n // Retry the message\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n // Message was successfully relayed.\n assertEq(address(L1Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L1Messenger.successfulMessages(hash), true);\n assertEq(L1Messenger.failedMessages(hash), true);\n\n // Expect a revert.\n vm.expectRevert(\"CrossDomainMessenger: message has already been relayed\");\n\n // Retry the message again.\n vm.prank(address(sender));\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce({ _nonce: 0, _version: 0 }), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n }\n}\n" - }, - "contracts/test/L1ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.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\ncontract L1ERC721Bridge_Test is Messenger_Initializer {\n TestERC721 internal localToken;\n TestERC721 internal remoteToken;\n L1ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L1ERC721Bridge(address(L1Messenger), otherBridge);\n localToken = new TestERC721();\n remoteToken = new TestERC721();\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L1ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L1Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L1Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L1ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L1Messenger),\n abi.encodeCall(\n L1Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), true);\n assertEq(localToken.ownerOf(tokenId), address(bridge));\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L1ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"ERC721: transfer from incorrect owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(bridge.deposits(address(localToken), address(remoteToken), tokenId), false);\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notEscrowed_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L1Messenger),\n abi.encodeWithSelector(L1Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L1Messenger));\n vm.expectRevert(\"L1ERC721Bridge: Token ID is not escrowed in the L1 Bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n" - }, - "contracts/test/L1StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\n\ncontract L1StandardBridge_Getter_Test is Bridge_Initializer {\n function test_getters_succeeds() external {\n assert(L1Bridge.l2TokenBridge() == address(L2Bridge));\n assert(L1Bridge.OTHER_BRIDGE() == L2Bridge);\n assert(L1Bridge.messenger() == L1Messenger);\n assert(L1Bridge.MESSENGER() == L1Messenger);\n assertEq(L1Bridge.version(), \"1.1.0\");\n }\n}\n\ncontract L1StandardBridge_Initialize_Test is Bridge_Initializer {\n function test_initialize_succeeds() external {\n assertEq(address(L1Bridge.messenger()), address(L1Messenger));\n\n assertEq(address(L1Bridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE);\n\n assertEq(address(L2Bridge), Predeploys.L2_STANDARD_BRIDGE);\n }\n}\n\ncontract L1StandardBridge_Initialize_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_Receive_Test is Bridge_Initializer {\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(op).balance, 0);\n\n // The legacy event must be emitted for backwards compatibility\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 100,\n hex\"\"\n ),\n 200_000\n )\n );\n\n vm.prank(alice, alice);\n (bool success, ) = address(L1Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(op).balance, 100);\n }\n}\n\ncontract L1StandardBridge_Receive_TestFail {}\n\ncontract PreBridgeETH is Bridge_Initializer {\n function _preBridgeETH(bool isLegacy) internal {\n assertEq(address(op).balance, 0);\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 500,\n hex\"dead\"\n );\n\n if (isLegacy) {\n vm.expectCall(\n address(L1Bridge),\n 500,\n abi.encodeWithSelector(L1Bridge.depositETH.selector, 50000, hex\"dead\")\n );\n } else {\n vm.expectCall(\n address(L1Bridge),\n 500,\n abi.encodeWithSelector(L1Bridge.bridgeETH.selector, 50000, hex\"dead\")\n );\n }\n vm.expectCall(\n address(L1Messenger),\n 500,\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 50000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 500,\n 50000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 50000);\n vm.expectCall(\n address(op),\n 500,\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 500,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(500),\n uint256(500),\n baseGas,\n false,\n innerMessage\n );\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, alice, 500, hex\"dead\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, alice, 500, hex\"dead\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 50000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 500);\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L1StandardBridge_DepositETH_Test is PreBridgeETH {\n // depositETH\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_depositETH_succeeds() external {\n _preBridgeETH({ isLegacy: true });\n L1Bridge.depositETH{ value: 500 }(50000, hex\"dead\");\n assertEq(address(op).balance, 500);\n }\n}\n\ncontract L1StandardBridge_BridgeETH_Test is PreBridgeETH {\n // BridgeETH\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_bridgeETH_succeeds() external {\n _preBridgeETH({ isLegacy: false });\n L1Bridge.bridgeETH{ value: 500 }(50000, hex\"dead\");\n assertEq(address(op).balance, 500);\n }\n}\n\ncontract L1StandardBridge_DepositETH_TestFail is Bridge_Initializer {\n function test_depositETH_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, address(L1Token).code);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice);\n L1Bridge.depositETH{ value: 1 }(300, hex\"\");\n }\n}\n\ncontract PreBridgeETHTo is Bridge_Initializer {\n function _preBridgeETHTo(bool isLegacy) internal {\n assertEq(address(op).balance, 0);\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n if (isLegacy) {\n vm.expectCall(\n address(L1Bridge),\n 600,\n abi.encodeWithSelector(L1Bridge.depositETHTo.selector, bob, 60000, hex\"dead\")\n );\n } else {\n vm.expectCall(\n address(L1Bridge),\n 600,\n abi.encodeWithSelector(L1Bridge.bridgeETHTo.selector, bob, 60000, hex\"dead\")\n );\n }\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n bob,\n 600,\n hex\"dead\"\n );\n\n // the L1 bridge should call\n // L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 60000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 600,\n 60000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 60000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 600,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(600),\n uint256(600),\n baseGas,\n false,\n innerMessage\n );\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHDepositInitiated(alice, bob, 600, hex\"dead\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeInitiated(alice, bob, 600, hex\"dead\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 60000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 600);\n\n // deposit eth to bob\n vm.prank(alice, alice);\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_Test is PreBridgeETHTo {\n // depositETHTo\n // - emits ETHDepositInitiated\n // - calls optimismPortal.depositTransaction\n // - EOA or contract can call\n // - ETH ends up in the optimismPortal\n function test_depositETHTo_succeeds() external {\n _preBridgeETHTo({ isLegacy: true });\n L1Bridge.depositETHTo{ value: 600 }(bob, 60000, hex\"dead\");\n assertEq(address(op).balance, 600);\n }\n}\n\ncontract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo {\n // BridgeETHTo\n // - emits ETHDepositInitiated\n // - emits ETHBridgeInitiated\n // - calls optimismPortal.depositTransaction\n // - only EOA\n // - ETH ends up in the optimismPortal\n function test_bridgeETHTo_succeeds() external {\n _preBridgeETHTo({ isLegacy: false });\n L1Bridge.bridgeETHTo{ value: 600 }(bob, 60000, hex\"dead\");\n assertEq(address(op).balance, 600);\n }\n}\n\ncontract L1StandardBridge_DepositETHTo_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_DepositERC20_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // depositERC20\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - only callable by EOA\n function test_depositERC20_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n // Deal Alice's ERC20 State\n deal(address(L1Token), alice, 100000, true);\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n // The L1Bridge should transfer alice's tokens to itself\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 100)\n );\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L2Token),\n address(L1Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n // the L1 bridge should call L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 10000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 0,\n 10000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 10000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 0,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(0),\n uint256(0),\n baseGas,\n false,\n innerMessage\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 0);\n\n vm.prank(alice);\n L1Bridge.depositERC20(address(L1Token), address(L2Token), 100, 10000, hex\"\");\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n }\n}\n\ncontract L1StandardBridge_DepositERC20_TestFail is Bridge_Initializer {\n function test_depositERC20_notEoa_reverts() external {\n // turn alice into a contract\n vm.etch(alice, hex\"ffff\");\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n vm.prank(alice, alice);\n L1Bridge.depositERC20(address(0), address(0), 100, 100, hex\"\");\n }\n}\n\ncontract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer {\n // depositERC20To\n // - updates bridge.deposits\n // - emits ERC20DepositInitiated\n // - calls optimismPortal.depositTransaction\n // - callable by a contract\n function test_depositERC20To_succeeds() external {\n uint256 nonce = L1Messenger.messageNonce();\n uint256 version = 0; // Internal constant in the OptimismPortal: DEPOSIT_VERSION\n address l1MessengerAliased = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L2Token),\n address(L1Token),\n alice,\n bob,\n 1000,\n hex\"\"\n );\n\n // the L1 bridge should call L1CrossDomainMessenger.sendMessage\n vm.expectCall(\n address(L1Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L2Bridge),\n message,\n 10000\n )\n );\n\n bytes memory innerMessage = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L1Bridge),\n address(L2Bridge),\n 0,\n 10000,\n message\n );\n\n uint64 baseGas = L1Messenger.baseGas(message, 10000);\n vm.expectCall(\n address(op),\n abi.encodeWithSelector(\n OptimismPortal.depositTransaction.selector,\n address(L2Messenger),\n 0,\n baseGas,\n false,\n innerMessage\n )\n );\n\n bytes memory opaqueData = abi.encodePacked(\n uint256(0),\n uint256(0),\n baseGas,\n false,\n innerMessage\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20DepositInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeInitiated(address(L1Token), address(L2Token), alice, bob, 1000, hex\"\");\n\n // OptimismPortal emits a TransactionDeposited event on `depositTransaction` call\n vm.expectEmit(true, true, true, true, address(op));\n emit TransactionDeposited(l1MessengerAliased, address(L2Messenger), version, opaqueData);\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessage(address(L2Bridge), address(L1Bridge), message, nonce, 10000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L1Messenger));\n emit SentMessageExtension1(address(L1Bridge), 0);\n\n deal(address(L1Token), alice, 100000, true);\n\n vm.prank(alice);\n L1Token.approve(address(L1Bridge), type(uint256).max);\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transferFrom.selector, alice, address(L1Bridge), 1000)\n );\n\n vm.prank(alice);\n L1Bridge.depositERC20To(address(L1Token), address(L2Token), bob, 1000, 10000, hex\"\");\n\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 1000);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeETHWithdrawal\n // - emits ETHWithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeETHWithdrawal_succeeds() external {\n uint256 aliceBalance = alice.balance;\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHWithdrawalFinalized(alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n vm.expectCall(alice, hex\"\");\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n // ensure that the messenger has ETH to call with\n vm.deal(address(L1Bridge.messenger()), 100);\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeETHWithdrawal{ value: 100 }(alice, alice, 100, hex\"\");\n\n assertEq(address(L1Bridge.messenger()).balance, 0);\n assertEq(aliceBalance + 100, alice.balance);\n }\n}\n\ncontract L1StandardBridge_FinalizeETHWithdrawal_TestFail is Bridge_Initializer {}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n // finalizeERC20Withdrawal\n // - updates bridge.deposits\n // - emits ERC20WithdrawalFinalized\n // - only callable by L2 bridge\n function test_finalizeERC20Withdrawal_succeeds() external {\n deal(address(L1Token), address(L1Bridge), 100, true);\n\n uint256 slot = stdstore\n .target(address(L1Bridge))\n .sig(\"deposits(address,address)\")\n .with_key(address(L1Token))\n .with_key(address(L2Token))\n .find();\n\n // Give the L1 bridge some ERC20 tokens\n vm.store(address(L1Bridge), bytes32(slot), bytes32(uint256(100)));\n assertEq(L1Bridge.deposits(address(L1Token), address(L2Token)), 100);\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20WithdrawalFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ERC20BridgeFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectCall(\n address(L1Token),\n abi.encodeWithSelector(ERC20.transfer.selector, alice, 100)\n );\n\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(L1Bridge.messenger()));\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n assertEq(L1Token.balanceOf(address(L1Bridge)), 0);\n assertEq(L1Token.balanceOf(address(alice)), 100);\n }\n}\n\ncontract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer {\n function test_finalizeERC20Withdrawal_notMessenger_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.prank(address(28));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n\n function test_finalizeERC20Withdrawal_notOtherBridge_reverts() external {\n vm.mockCall(\n address(L1Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(address(0)))\n );\n vm.prank(address(L1Bridge.messenger()));\n vm.expectRevert(\"StandardBridge: function can only be called from the other bridge\");\n L1Bridge.finalizeERC20Withdrawal(\n address(L1Token),\n address(L2Token),\n alice,\n alice,\n 100,\n hex\"\"\n );\n }\n}\n\ncontract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {\n function test_finalizeBridgeETH_succeeds() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n\n vm.expectEmit(true, true, true, true, address(L1Bridge));\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n\ncontract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer {\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L1Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L1Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n address messenger = address(L1Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L1Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L1Bridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2CrossDomainMessenger.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Messenger_Initializer, Reverter, ConfigurableCaller } from \"./CommonTest.t.sol\";\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { L2CrossDomainMessenger } from \"../L2/L2CrossDomainMessenger.sol\";\nimport { L1CrossDomainMessenger } from \"../L1/L1CrossDomainMessenger.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2CrossDomainMessenger_Test is Messenger_Initializer {\n // Receiver address for testing\n address recipient = address(0xabbaacdc);\n\n function test_messageVersion_succeeds() external {\n (, uint16 version) = Encoding.decodeVersionedNonce(L2Messenger.messageNonce());\n assertEq(version, L2Messenger.MESSAGE_VERSION());\n }\n\n function test_sendMessage_succeeds() external {\n bytes memory xDomainCallData = Encoding.encodeCrossDomainMessage(\n L2Messenger.messageNonce(),\n alice,\n recipient,\n 0,\n 100,\n hex\"ff\"\n );\n vm.expectCall(\n address(messagePasser),\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData\n )\n );\n\n // MessagePassed event\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(L2Messenger),\n address(L1Messenger),\n 0,\n L2Messenger.baseGas(hex\"ff\", 100),\n xDomainCallData,\n Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messagePasser.messageNonce(),\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: L2Messenger.baseGas(hex\"ff\", 100),\n data: xDomainCallData\n })\n )\n );\n\n vm.prank(alice);\n L2Messenger.sendMessage(recipient, hex\"ff\", uint32(100));\n }\n\n function test_sendMessage_twice_succeeds() external {\n uint256 nonce = L2Messenger.messageNonce();\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n L2Messenger.sendMessage(recipient, hex\"aa\", uint32(500_000));\n // the nonce increments for each message sent\n assertEq(nonce + 2, L2Messenger.messageNonce());\n }\n\n function test_xDomainSender_senderNotSet_reverts() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n function test_relayMessage_v2_reverts() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n // Expect a revert.\n vm.expectRevert(\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // Try to relay a v2 message.\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 2), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n }\n\n function test_relayMessage_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n vm.expectCall(target, hex\"1111\");\n\n vm.prank(caller);\n\n vm.expectEmit(true, true, true, true);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n hex\"1111\"\n );\n\n emit RelayedMessage(hash);\n\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n 0, // value\n 0,\n hex\"1111\"\n );\n\n // the message hash is in the successfulMessages mapping\n assert(L2Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertEq(L2Messenger.failedMessages(hash), false);\n }\n\n // relayMessage: should revert if attempting to relay a message sent to an L1 system contract\n function test_relayMessage_toSystemContract_reverts() external {\n address target = address(messagePasser);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n bytes memory message = hex\"1111\";\n\n vm.prank(caller);\n vm.expectRevert(\"CrossDomainMessenger: message cannot be replayed\");\n L1Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n message\n );\n }\n\n // relayMessage: the xDomainMessageSender is reset to the original value\n function test_xDomainMessageSender_reset_succeeds() external {\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n vm.prank(caller);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n address(0),\n address(0),\n 0,\n 0,\n hex\"\"\n );\n\n vm.expectRevert(\"CrossDomainMessenger: xDomainMessageSender is not set\");\n L2Messenger.xDomainMessageSender();\n }\n\n // relayMessage: should send a successful call to the target contract after the first message\n // fails and ETH gets stuck, but the second message succeeds\n function test_relayMessage_retry_succeeds() external {\n address target = address(0xabcd);\n address sender = address(L1Messenger);\n address caller = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n uint256 value = 100;\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n vm.etch(target, address(new Reverter()).code);\n vm.deal(address(caller), value);\n vm.prank(caller);\n L2Messenger.relayMessage{ value: value }(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, value);\n assertEq(address(target).balance, 0);\n assertEq(L2Messenger.successfulMessages(hash), false);\n assertEq(L2Messenger.failedMessages(hash), true);\n\n vm.expectEmit(true, true, true, true);\n\n emit RelayedMessage(hash);\n\n vm.etch(target, address(0).code);\n vm.prank(address(sender));\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1), // nonce\n sender,\n target,\n value,\n 0,\n hex\"1111\"\n );\n\n assertEq(address(L2Messenger).balance, 0);\n assertEq(address(target).balance, value);\n assertEq(L2Messenger.successfulMessages(hash), true);\n assertEq(L2Messenger.failedMessages(hash), true);\n }\n\n // relayMessage: Should revert if the recipient is trying to reenter with the\n // same message.\n function test_relayMessage_reentrancySameMessage_reverts() external {\n ConfigurableCaller caller = new ConfigurableCaller();\n address target = address(caller);\n address sender = address(L1Messenger);\n address l1XDMAlias = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n bytes memory callMessage = abi.encodeWithSelector(caller.call.selector);\n\n bytes32 hash = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Act as the L1XDM and call the `relayMessage` function with the `innerMessage`.\n vm.prank(l1XDMAlias);\n vm.expectCall(target, callMessage);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Assert that the message failed to be relayed\n assertFalse(L2Messenger.successfulMessages(hash));\n assertTrue(L2Messenger.failedMessages(hash));\n\n // Set the configurable caller's target to `L2Messenger` and set the payload to `relayMessage(...)`.\n caller.setDoRevert(false);\n caller.setTarget(address(L2Messenger));\n caller.setPayload(\n abi.encodeWithSelector(\n L2Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n callMessage\n )\n );\n\n // Attempt to replay the failed message, which will *not* immediately revert this time around,\n // but attempt to reenter `relayMessage` with the same message hash. The reentrancy attempt should\n // revert.\n vm.expectEmit(true, true, true, true, target);\n emit WhatHappened(\n false,\n abi.encodeWithSignature(\"Error(string)\", \"ReentrancyGuard: reentrant call\")\n );\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n callMessage\n );\n\n // Assert that the message still failed to be relayed.\n assertFalse(L2Messenger.successfulMessages(hash));\n assertTrue(L2Messenger.failedMessages(hash));\n }\n\n // relayMessage: should not revert if the recipient reenters `relayMessage` with a different\n // message hash.\n function test_relayMessage_reentrancyDiffMessage_succeeds() external {\n ConfigurableCaller caller = new ConfigurableCaller();\n address target = address(caller);\n address sender = address(L1Messenger);\n address l1XDMAlias = AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger));\n\n bytes memory messageA = abi.encodeWithSelector(caller.call.selector);\n bytes memory messageB = hex\"\";\n\n bytes32 hashA = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n bytes32 hashB = Hashing.hashCrossDomainMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageB\n );\n\n // Act as the L1XDM and call the `relayMessage` function with both `messageA` and `messageB`.\n vm.startPrank(l1XDMAlias);\n\n vm.expectCall(target, messageA);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n vm.expectCall(target, messageB);\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageB\n );\n\n // Stop acting as the L1XDM\n vm.stopPrank();\n\n // Assert that both messages failed to be relayed\n assertFalse(L2Messenger.successfulMessages(hashA));\n assertFalse(L2Messenger.successfulMessages(hashB));\n assertTrue(L2Messenger.failedMessages(hashA));\n assertTrue(L2Messenger.failedMessages(hashB));\n\n // Set the configurable caller's target to `L2Messenger` and set the payload to `relayMessage(...)`.\n caller.setDoRevert(false);\n caller.setTarget(address(L2Messenger));\n caller.setPayload(\n abi.encodeWithSelector(\n L2Messenger.relayMessage.selector,\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageB\n )\n );\n\n // Attempt to replay the failed message, which will *not* immediately revert this time around,\n // but attempt to reenter `relayMessage` with messageB. The reentrancy attempt should succeed\n // because the message hashes are different.\n vm.expectEmit(true, true, true, true, target);\n emit WhatHappened(true, hex\"\");\n L2Messenger.relayMessage(\n Encoding.encodeVersionedNonce(0, 1),\n sender,\n target,\n 0,\n 0,\n messageA\n );\n\n // Assert that both messages are now in the `successfulMessages` mapping.\n assertTrue(L2Messenger.successfulMessages(hashA));\n assertTrue(L2Messenger.successfulMessages(hashB));\n }\n}\n" - }, - "contracts/test/L2ERC721Bridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { Messenger_Initializer } from \"./CommonTest.t.sol\";\nimport { L1ERC721Bridge } from \"../L1/L1ERC721Bridge.sol\";\nimport { L2ERC721Bridge } from \"../L2/L2ERC721Bridge.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.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\ncontract TestMintableERC721 is OptimismMintableERC721 {\n constructor(address _bridge, address _remoteToken)\n OptimismMintableERC721(_bridge, 1, _remoteToken, \"Test\", \"TST\")\n {}\n\n function mint(address to, uint256 tokenId) public {\n _mint(to, tokenId);\n }\n}\n\ncontract L2ERC721Bridge_Test is Messenger_Initializer {\n TestMintableERC721 internal localToken;\n TestERC721 internal remoteToken;\n L2ERC721Bridge internal bridge;\n address internal constant otherBridge = address(0x3456);\n uint256 internal constant tokenId = 1;\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 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 function setUp() public override {\n super.setUp();\n\n // Create necessary contracts.\n bridge = new L2ERC721Bridge(address(L2Messenger), otherBridge);\n remoteToken = new TestERC721();\n localToken = new TestMintableERC721(address(bridge), address(remoteToken));\n\n // Label the bridge so we get nice traces.\n vm.label(address(bridge), \"L2ERC721Bridge\");\n\n // Mint alice a token.\n localToken.mint(alice, tokenId);\n\n // Approve the bridge to transfer the token.\n vm.prank(alice);\n localToken.approve(address(bridge), tokenId);\n }\n\n function test_constructor_succeeds() public {\n assertEq(address(bridge.MESSENGER()), address(L2Messenger));\n assertEq(address(bridge.OTHER_BRIDGE()), otherBridge);\n assertEq(address(bridge.messenger()), address(L2Messenger));\n assertEq(address(bridge.otherBridge()), otherBridge);\n }\n\n function test_bridgeERC721_succeeds() public {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L2ERC721Bridge.finalizeBridgeERC721,\n (\n address(remoteToken),\n address(localToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n )\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721_fromContract_reverts() external {\n // Bridge the token.\n vm.etch(alice, hex\"01\");\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: account is not externally owned\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L2ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721(address(localToken), address(0), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"L2ERC721Bridge: Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_succeeds() external {\n // Expect a call to the messenger.\n vm.expectCall(\n address(L2Messenger),\n abi.encodeCall(\n L2Messenger.sendMessage,\n (\n address(otherBridge),\n abi.encodeCall(\n L1ERC721Bridge.finalizeBridgeERC721,\n (address(remoteToken), address(localToken), alice, bob, tokenId, hex\"5678\")\n ),\n 1234\n )\n )\n );\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeInitiated(\n address(localToken),\n address(remoteToken),\n alice,\n bob,\n tokenId,\n hex\"5678\"\n );\n\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is burned.\n vm.expectRevert(\"ERC721: invalid token ID\");\n localToken.ownerOf(tokenId);\n }\n\n function test_bridgeERC721To_localTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert();\n bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_remoteTokenZeroAddress_reverts() external {\n // Bridge the token.\n vm.prank(alice);\n vm.expectRevert(\"L2ERC721Bridge: remote token cannot be address(0)\");\n bridge.bridgeERC721To(address(localToken), address(0), bob, tokenId, 1234, hex\"5678\");\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_bridgeERC721To_wrongOwner_reverts() external {\n // Bridge the token.\n vm.prank(bob);\n vm.expectRevert(\"L2ERC721Bridge: Withdrawal is not being initiated by NFT owner\");\n bridge.bridgeERC721To(\n address(localToken),\n address(remoteToken),\n bob,\n tokenId,\n 1234,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_succeeds() external {\n // Bridge the token.\n vm.prank(alice);\n bridge.bridgeERC721(address(localToken), address(remoteToken), tokenId, 1234, hex\"5678\");\n\n // Expect an event to be emitted.\n vm.expectEmit(true, true, true, true);\n emit ERC721BridgeFinalized(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n\n // Token is not locked in the bridge.\n assertEq(localToken.ownerOf(tokenId), alice);\n }\n\n function test_finalizeBridgeERC721_interfaceNotCompliant_reverts() external {\n // Create a non-compliant token\n NonCompliantERC721 nonCompliantToken = new NonCompliantERC721(alice);\n\n // Bridge the non-compliant token.\n vm.prank(alice);\n bridge.bridgeERC721(address(nonCompliantToken), address(0x01), tokenId, 1234, hex\"5678\");\n\n // Attempt to finalize the withdrawal. Should revert because the token does not claim\n // to be compliant with the `IOptimismMintableERC721` interface.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"L2ERC721Bridge: local token interface is not compliant\");\n bridge.finalizeBridgeERC721(\n address(address(nonCompliantToken)),\n address(address(0x01)),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notViaLocalMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.prank(alice);\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(alice)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721Bridge: function can only be called from the other bridge\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_selfToken_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"L2ERC721Bridge: local token cannot be self\");\n bridge.finalizeBridgeERC721(\n address(bridge),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n\n function test_finalizeBridgeERC721_alreadyExists_reverts() external {\n // Finalize a withdrawal.\n vm.mockCall(\n address(L2Messenger),\n abi.encodeWithSelector(L2Messenger.xDomainMessageSender.selector),\n abi.encode(otherBridge)\n );\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"ERC721: token already minted\");\n bridge.finalizeBridgeERC721(\n address(localToken),\n address(remoteToken),\n alice,\n alice,\n tokenId,\n hex\"5678\"\n );\n }\n}\n\n/**\n * @dev A non-compliant ERC721 token that does not implement the full ERC721 interface.\n *\n * This is used to test that the bridge will revert if the token does not claim to support\n * the ERC721 interface.\n */\ncontract NonCompliantERC721 {\n address internal immutable owner;\n\n constructor(address _owner) {\n owner = _owner;\n }\n\n function ownerOf(uint256) external view returns (address) {\n return owner;\n }\n\n function remoteToken() external pure returns (address) {\n return address(0x01);\n }\n\n function burn(address, uint256) external {\n // Do nothing.\n }\n\n function supportsInterface(bytes4) external pure returns (bool) {\n return false;\n }\n}\n" - }, - "contracts/test/L2OutputOracle.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { L2OutputOracle_Initializer, NextImpl } from \"./CommonTest.t.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Types } from \"../libraries/Types.sol\";\n\ncontract L2OutputOracleTest is L2OutputOracle_Initializer {\n bytes32 proposedOutput1 = keccak256(abi.encode(1));\n\n function test_constructor_succeeds() external {\n assertEq(oracle.PROPOSER(), proposer);\n assertEq(oracle.CHALLENGER(), owner);\n assertEq(oracle.SUBMISSION_INTERVAL(), submissionInterval);\n assertEq(oracle.latestBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingBlockNumber(), startingBlockNumber);\n assertEq(oracle.startingTimestamp(), startingTimestamp);\n }\n\n function test_constructor_badTimestamp_reverts() external {\n vm.expectRevert(\"L2OutputOracle: starting L2 timestamp must be less than current time\");\n\n // startingTimestamp is in the future\n new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp + 1,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n function test_constructor_l2BlockTimeZero_reverts() external {\n vm.expectRevert(\"L2OutputOracle: L2 block time must be greater than 0\");\n new L2OutputOracle({\n _submissionInterval: submissionInterval,\n _l2BlockTime: 0,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n function testFuzz_constructor_submissionIntervalLteL2BlockTime_reverts(\n uint256 _submissionInterval,\n uint256 _l2BlockTime\n ) external {\n // Bound the _l2blockTime to be in the range of [1, type(uint256).max]\n _l2BlockTime = bound(_l2BlockTime, 1, type(uint256).max);\n // Roll the block number to _l2blockTime (the starting L2 timestamp must be less than or equal to the current time)\n vm.roll(_l2BlockTime);\n // Bound _submissionInterval to be less than or equal to _l2BlockTime\n _submissionInterval = bound(_submissionInterval, 0, _l2BlockTime);\n\n vm.expectRevert(\"L2OutputOracle: submission interval must be greater than L2 block time\");\n new L2OutputOracle({\n _submissionInterval: _submissionInterval,\n _l2BlockTime: _l2BlockTime,\n _startingBlockNumber: startingBlockNumber,\n _startingTimestamp: block.timestamp,\n _proposer: proposer,\n _challenger: owner,\n _finalizationPeriodSeconds: 7 days\n });\n }\n\n /****************\n * Getter Tests *\n ****************/\n\n // Test: latestBlockNumber() should return the correct value\n function test_latestBlockNumber_succeeds() external {\n uint256 proposedNumber = oracle.nextBlockNumber();\n\n // Roll to after the block number we'll propose\n warpToProposeTime(proposedNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, proposedNumber, 0, 0);\n assertEq(oracle.latestBlockNumber(), proposedNumber);\n }\n\n // Test: getL2Output() should return the correct value\n function test_getL2Output_succeeds() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput1, nextBlockNumber, 0, 0);\n\n Types.OutputProposal memory proposal = oracle.getL2Output(nextOutputIndex);\n assertEq(proposal.outputRoot, proposedOutput1);\n assertEq(proposal.timestamp, block.timestamp);\n\n // The block number is larger than the latest proposed output:\n vm.expectRevert(stdError.indexOOBError);\n oracle.getL2Output(nextOutputIndex + 1);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is exact block\n function test_getL2OutputIndexAfter_sameBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with exact same block as proposed returns the proposal.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value when input is previous block\n function test_getL2OutputIndexAfter_previousBlock_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n // Querying with previous block returns the proposal too.\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 - 1);\n assertEq(index1, 0);\n }\n\n // Test: getL2OutputIndexAfter() returns correct value during binary search\n function test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() external {\n bytes32 output1 = keccak256(abi.encode(1));\n uint256 nextBlockNumber1 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber1);\n vm.prank(proposer);\n oracle.proposeL2Output(output1, nextBlockNumber1, 0, 0);\n\n bytes32 output2 = keccak256(abi.encode(2));\n uint256 nextBlockNumber2 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber2);\n vm.prank(proposer);\n oracle.proposeL2Output(output2, nextBlockNumber2, 0, 0);\n\n bytes32 output3 = keccak256(abi.encode(3));\n uint256 nextBlockNumber3 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber3);\n vm.prank(proposer);\n oracle.proposeL2Output(output3, nextBlockNumber3, 0, 0);\n\n bytes32 output4 = keccak256(abi.encode(4));\n uint256 nextBlockNumber4 = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber4);\n vm.prank(proposer);\n oracle.proposeL2Output(output4, nextBlockNumber4, 0, 0);\n\n // Querying with a block number between the first and second proposal\n uint256 index1 = oracle.getL2OutputIndexAfter(nextBlockNumber1 + 1);\n assertEq(index1, 1);\n\n // Querying with a block number between the second and third proposal\n uint256 index2 = oracle.getL2OutputIndexAfter(nextBlockNumber2 + 1);\n assertEq(index2, 2);\n\n // Querying with a block number between the third and fourth proposal\n uint256 index3 = oracle.getL2OutputIndexAfter(nextBlockNumber3 + 1);\n assertEq(index3, 3);\n }\n\n // Test: getL2OutputIndexAfter() reverts when no output exists yet\n function test_getL2OutputIndexAfter_noOutputsExis_reverts() external {\n vm.expectRevert(\"L2OutputOracle: cannot get output as no outputs have been proposed yet\");\n oracle.getL2OutputIndexAfter(0);\n }\n\n // Test: nextBlockNumber() should return the correct value\n function test_nextBlockNumber_succeeds() external {\n assertEq(\n oracle.nextBlockNumber(),\n // The return value should match this arithmetic\n oracle.latestBlockNumber() + oracle.SUBMISSION_INTERVAL()\n );\n }\n\n function test_computeL2Timestamp_succeeds() external {\n // reverts if timestamp is too low\n vm.expectRevert(stdError.arithmeticError);\n oracle.computeL2Timestamp(startingBlockNumber - 1);\n\n // returns the correct value...\n // ... for the very first block\n assertEq(oracle.computeL2Timestamp(startingBlockNumber), startingTimestamp);\n\n // ... for the first block after the starting block\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 1),\n startingTimestamp + l2BlockTime\n );\n\n // ... for some other block number\n assertEq(\n oracle.computeL2Timestamp(startingBlockNumber + 96024),\n startingTimestamp + l2BlockTime * 96024\n );\n }\n\n /*****************************\n * Propose Tests - Happy Path *\n *****************************/\n\n // Test: proposeL2Output succeeds when given valid input, and no block hash and number are\n // specified.\n function test_proposeL2Output_proposeAnotherOutput_succeeds() public {\n bytes32 proposedOutput2 = keccak256(abi.encode());\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n warpToProposeTime(nextBlockNumber);\n uint256 proposedNumber = oracle.latestBlockNumber();\n\n // Ensure the submissionInterval is enforced\n assertEq(nextBlockNumber, proposedNumber + submissionInterval);\n\n vm.roll(nextBlockNumber + 1);\n\n vm.expectEmit(true, true, true, true);\n emit OutputProposed(proposedOutput2, nextOutputIndex, nextBlockNumber, block.timestamp);\n\n vm.prank(proposer);\n oracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output succeeds when given valid input, and when a block hash and number are\n // specified for reorg protection.\n function test_proposeWithBlockhashAndHeight_succeeds() external {\n // Get the number and hash of a previous block in the chain\n uint256 prevL1BlockNumber = block.number - 1;\n bytes32 prevL1BlockHash = blockhash(prevL1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, prevL1BlockHash, prevL1BlockNumber);\n }\n\n /***************************\n * Propose Tests - Sad Path *\n ***************************/\n\n // Test: proposeL2Output fails if called by a party that is not the proposer.\n function test_proposeL2Output_notProposer_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n\n vm.prank(address(128));\n vm.expectRevert(\"L2OutputOracle: only the proposer address can propose new outputs\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails given a zero blockhash.\n function test_proposeL2Output_emptyOutput_reverts() external {\n bytes32 outputToPropose = bytes32(0);\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: L2 output proposal cannot be the zero hash\");\n oracle.proposeL2Output(outputToPropose, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if the block number doesn't match the next expected number.\n function test_proposeL2Output_unexpectedBlockNumber_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: block number must be equal to next expected block number\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber - 1, 0, 0);\n }\n\n // Test: proposeL2Output fails if it would have a timestamp in the future.\n function test_proposeL2Output_futureTimetamp_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n uint256 nextTimestamp = oracle.computeL2Timestamp(nextBlockNumber);\n vm.warp(nextTimestamp);\n vm.prank(proposer);\n vm.expectRevert(\"L2OutputOracle: cannot propose L2 output in the future\");\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0);\n }\n\n // Test: proposeL2Output fails if a non-existent L1 block hash and number are provided for reorg\n // protection.\n function test_proposeL2Output_wrongFork_reverts() external {\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(\n nonZeroHash,\n nextBlockNumber,\n bytes32(uint256(0x01)),\n block.number - 1\n );\n }\n\n // Test: proposeL2Output fails when given valid input, but the block hash and number do not\n // match.\n function test_proposeL2Output_unmatchedBlockhash_reverts() external {\n // Move ahead to block 100 so that we can reference historical blocks\n vm.roll(100);\n\n // Get the number and hash of a previous block in the chain\n uint256 l1BlockNumber = block.number - 1;\n bytes32 l1BlockHash = blockhash(l1BlockNumber);\n\n uint256 nextBlockNumber = oracle.nextBlockNumber();\n warpToProposeTime(nextBlockNumber);\n vm.prank(proposer);\n\n // This will fail when foundry no longer returns zerod block hashes\n vm.expectRevert(\n \"L2OutputOracle: block hash does not match the hash at the expected height\"\n );\n oracle.proposeL2Output(nonZeroHash, nextBlockNumber, l1BlockHash, l1BlockNumber - 1);\n }\n\n /*****************************\n * Delete Tests - Happy Path *\n *****************************/\n\n function test_deleteOutputs_singleOutput_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 1);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex);\n oracle.deleteL2Outputs(latestOutputIndex);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n function test_deleteOutputs_multipleOutputs_succeeds() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n Types.OutputProposal memory newLatestOutput = oracle.getL2Output(latestOutputIndex - 3);\n\n vm.prank(owner);\n vm.expectEmit(true, true, false, false);\n emit OutputsDeleted(latestOutputIndex + 1, latestOutputIndex - 2);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // validate latestBlockNumber has been reduced\n uint256 latestBlockNumberAfter = oracle.latestBlockNumber();\n uint256 latestOutputIndexAfter = oracle.latestOutputIndex();\n assertEq(latestBlockNumber - submissionInterval * 3, latestBlockNumberAfter);\n\n // validate that the new latest output is as expected.\n Types.OutputProposal memory proposal = oracle.getL2Output(latestOutputIndexAfter);\n assertEq(newLatestOutput.outputRoot, proposal.outputRoot);\n assertEq(newLatestOutput.timestamp, proposal.timestamp);\n }\n\n /***************************\n * Delete Tests - Sad Path *\n ***************************/\n\n function test_deleteL2Outputs_ifNotChallenger_reverts() external {\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.expectRevert(\"L2OutputOracle: only the challenger address can delete outputs\");\n oracle.deleteL2Outputs(latestBlockNumber);\n }\n\n function test_deleteL2Outputs_nonExistent_reverts() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n uint256 latestBlockNumber = oracle.latestBlockNumber();\n\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestBlockNumber + 1);\n }\n\n function test_deleteL2Outputs_afterLatest_reverts() external {\n // Start by proposing three outputs\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n // Delete the latest two outputs\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n vm.prank(owner);\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n\n // Now try to delete the same output again\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs after the latest output index\");\n oracle.deleteL2Outputs(latestOutputIndex - 2);\n }\n\n function test_deleteL2Outputs_finalized_reverts() external {\n test_proposeL2Output_proposeAnotherOutput_succeeds();\n\n // Warp past the finalization period + 1 second\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n uint256 latestOutputIndex = oracle.latestOutputIndex();\n\n // Try to delete a finalized output\n vm.prank(owner);\n vm.expectRevert(\"L2OutputOracle: cannot delete outputs that have already been finalized\");\n oracle.deleteL2Outputs(latestOutputIndex);\n }\n}\n\ncontract L2OutputOracleUpgradeable_Test is L2OutputOracle_Initializer {\n Proxy internal proxy;\n\n function setUp() public override {\n super.setUp();\n proxy = Proxy(payable(address(oracle)));\n }\n\n function test_initValuesOnProxy_succeeds() external {\n assertEq(submissionInterval, oracleImpl.SUBMISSION_INTERVAL());\n assertEq(l2BlockTime, oracleImpl.L2_BLOCK_TIME());\n assertEq(startingBlockNumber, oracleImpl.startingBlockNumber());\n assertEq(startingTimestamp, oracleImpl.startingTimestamp());\n\n assertEq(proposer, oracleImpl.PROPOSER());\n assertEq(owner, oracleImpl.CHALLENGER());\n }\n\n function test_initializeProxy_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(payable(proxy)).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_initializeImpl_alreadyInitialized_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n L2OutputOracle(oracleImpl).initialize(startingBlockNumber, startingTimestamp);\n }\n\n function test_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(oracle), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(oracle), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(oracle)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n" - }, - "contracts/test/L2StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { stdStorage, StdStorage } from \"forge-std/Test.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { console } from \"forge-std/console.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\n\ncontract L2StandardBridge_Test is Bridge_Initializer {\n using stdStorage for StdStorage;\n\n function test_initialize_succeeds() external {\n assertEq(address(L2Bridge.messenger()), address(L2Messenger));\n assertEq(L1Bridge.l2TokenBridge(), address(L2Bridge));\n assertEq(address(L2Bridge.OTHER_BRIDGE()), address(L1Bridge));\n }\n\n // receive\n // - can accept ETH\n function test_receive_succeeds() external {\n assertEq(address(messagePasser).balance, 0);\n uint256 nonce = L2Messenger.messageNonce();\n\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeETH.selector,\n alice,\n alice,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 200_000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 100,\n 200_000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 100,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalInitiated(address(0), Predeploys.LEGACY_ERC20_ETH, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeInitiated(alice, alice, 100, hex\"\");\n\n // L2ToL1MessagePasser will emit a MessagePassed event\n vm.expectEmit(true, true, true, true, address(messagePasser));\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 100,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 200_000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessageExtension1(address(L2Bridge), 100);\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 200_000 // StandardBridge's RECEIVE_DEFAULT_GAS_LIMIT\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n vm.prank(alice, alice);\n (bool success, ) = address(L2Bridge).call{ value: 100 }(hex\"\");\n assertEq(success, true);\n assertEq(address(messagePasser).balance, 100);\n }\n\n // withrdraw\n // - requires amount == msg.value\n function test_withdraw_insufficientValue_reverts() external {\n assertEq(address(messagePasser).balance, 0);\n\n vm.expectRevert(\"StandardBridge: bridging ETH must include sufficient ETH value\");\n vm.prank(alice, alice);\n L2Bridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 100, 1000, hex\"\");\n }\n\n /**\n * @notice Use the legacy `withdraw` interface on the L2StandardBridge to\n * withdraw ether from L2 to L1.\n */\n function test_withdraw_ether_succeeds() external {\n assertTrue(alice.balance >= 100);\n assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 0);\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit WithdrawalInitiated({\n l1Token: address(0),\n l2Token: Predeploys.LEGACY_ERC20_ETH,\n from: alice,\n to: alice,\n amount: 100,\n data: hex\"\"\n });\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ETHBridgeInitiated({ from: alice, to: alice, amount: 100, data: hex\"\" });\n\n vm.prank(alice, alice);\n L2Bridge.withdraw{ value: 100 }({\n _l2Token: Predeploys.LEGACY_ERC20_ETH,\n _amount: 100,\n _minGasLimit: 1000,\n _extraData: hex\"\"\n });\n\n assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 100);\n }\n}\n\ncontract PreBridgeERC20 is Bridge_Initializer {\n // withdraw and BridgeERC20 should behave the same when transferring ERC20 tokens\n // so they should share the same setup and expectEmit calls\n function _preBridgeERC20(bool _isLegacy, address _l2Token) internal {\n // Alice has 100 L2Token\n deal(_l2Token, alice, 100, true);\n assertEq(ERC20(_l2Token).balanceOf(alice), 100);\n uint256 nonce = L2Messenger.messageNonce();\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L1Token),\n _l2Token,\n alice,\n alice,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 1000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 0,\n 1000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n if (_isLegacy) {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(L2Bridge.withdraw.selector, _l2Token, 100, 1000, hex\"\")\n );\n } else {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.bridgeERC20.selector,\n _l2Token,\n address(L1Token),\n 100,\n 1000,\n hex\"\"\n )\n );\n }\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 1000\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n // The L2Bridge should burn the tokens\n vm.expectCall(\n _l2Token,\n abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalInitiated(address(L1Token), _l2Token, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 0,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true);\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true);\n emit SentMessageExtension1(address(L2Bridge), 0);\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L2StandardBridge_BridgeERC20_Test is PreBridgeERC20 {\n // withdraw\n // - token is burned\n // - emits WithdrawalInitiated\n // - calls Withdrawer.initiateWithdrawal\n function test_withdraw_withdrawingERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: true, _l2Token: address(L2Token) });\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n // BridgeERC20\n // - token is burned\n // - emits WithdrawalInitiated\n // - calls Withdrawer.initiateWithdrawal\n function test_bridgeERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: false, _l2Token: address(L2Token) });\n L2Bridge.bridgeERC20(address(L2Token), address(L1Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_withdrawLegacyERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: true, _l2Token: address(LegacyL2Token) });\n L2Bridge.withdraw(address(LegacyL2Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_bridgeLegacyERC20_succeeds() external {\n _preBridgeERC20({ _isLegacy: false, _l2Token: address(LegacyL2Token) });\n L2Bridge.bridgeERC20(address(LegacyL2Token), address(L1Token), 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_withdraw_notEOA_reverts() external {\n // This contract has 100 L2Token\n deal(address(L2Token), address(this), 100, true);\n\n vm.expectRevert(\"StandardBridge: function can only be called from an EOA\");\n L2Bridge.withdraw(address(L2Token), 100, 1000, hex\"\");\n }\n}\n\ncontract PreBridgeERC20To is Bridge_Initializer {\n // withdrawTo and BridgeERC20To should behave the same when transferring ERC20 tokens\n // so they should share the same setup and expectEmit calls\n function _preBridgeERC20To(bool _isLegacy, address _l2Token) internal {\n deal(_l2Token, alice, 100, true);\n assertEq(ERC20(L2Token).balanceOf(alice), 100);\n uint256 nonce = L2Messenger.messageNonce();\n bytes memory message = abi.encodeWithSelector(\n StandardBridge.finalizeBridgeERC20.selector,\n address(L1Token),\n _l2Token,\n alice,\n bob,\n 100,\n hex\"\"\n );\n uint64 baseGas = L2Messenger.baseGas(message, 1000);\n bytes memory withdrawalData = abi.encodeWithSelector(\n CrossDomainMessenger.relayMessage.selector,\n nonce,\n address(L2Bridge),\n address(L1Bridge),\n 0,\n 1000,\n message\n );\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: address(L2Messenger),\n target: address(L1Messenger),\n value: 0,\n gasLimit: baseGas,\n data: withdrawalData\n })\n );\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit WithdrawalInitiated(address(L1Token), _l2Token, alice, bob, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeInitiated(_l2Token, address(L1Token), alice, bob, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(messagePasser));\n emit MessagePassed(\n nonce,\n address(L2Messenger),\n address(L1Messenger),\n 0,\n baseGas,\n withdrawalData,\n withdrawalHash\n );\n\n // SentMessage event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessage(address(L1Bridge), address(L2Bridge), message, nonce, 1000);\n\n // SentMessageExtension1 event emitted by the CrossDomainMessenger\n vm.expectEmit(true, true, true, true, address(L2Messenger));\n emit SentMessageExtension1(address(L2Bridge), 0);\n\n if (_isLegacy) {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.withdrawTo.selector,\n _l2Token,\n bob,\n 100,\n 1000,\n hex\"\"\n )\n );\n } else {\n vm.expectCall(\n address(L2Bridge),\n abi.encodeWithSelector(\n L2Bridge.bridgeERC20To.selector,\n _l2Token,\n address(L1Token),\n bob,\n 100,\n 1000,\n hex\"\"\n )\n );\n }\n\n vm.expectCall(\n address(L2Messenger),\n abi.encodeWithSelector(\n CrossDomainMessenger.sendMessage.selector,\n address(L1Bridge),\n message,\n 1000\n )\n );\n\n vm.expectCall(\n Predeploys.L2_TO_L1_MESSAGE_PASSER,\n abi.encodeWithSelector(\n L2ToL1MessagePasser.initiateWithdrawal.selector,\n address(L1Messenger),\n baseGas,\n withdrawalData\n )\n );\n\n // The L2Bridge should burn the tokens\n vm.expectCall(\n address(L2Token),\n abi.encodeWithSelector(OptimismMintableERC20.burn.selector, alice, 100)\n );\n\n vm.prank(alice, alice);\n }\n}\n\ncontract L2StandardBridge_BridgeERC20To_Test is PreBridgeERC20To {\n // withdrawTo\n // - token is burned\n // - emits WithdrawalInitiated w/ correct recipient\n // - calls Withdrawer.initiateWithdrawal\n function test_withdrawTo_withdrawingERC20_succeeds() external {\n _preBridgeERC20To({ _isLegacy: true, _l2Token: address(L2Token) });\n L2Bridge.withdrawTo(address(L2Token), bob, 100, 1000, hex\"\");\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n // bridgeERC20To\n // - token is burned\n // - emits WithdrawalInitiated w/ correct recipient\n // - calls Withdrawer.initiateWithdrawal\n function test_bridgeERC20To_succeeds() external {\n _preBridgeERC20To({ _isLegacy: false, _l2Token: address(L2Token) });\n L2Bridge.bridgeERC20To(address(L2Token), address(L1Token), bob, 100, 1000, hex\"\");\n assertEq(L2Token.balanceOf(alice), 0);\n }\n}\n\ncontract L2StandardBridge_Bridge_Test is Bridge_Initializer {\n // finalizeDeposit\n // - only callable by l1TokenBridge\n // - supported token pair emits DepositFinalized\n // - invalid deposit calls Withdrawer.initiateWithdrawal\n function test_finalizeDeposit_depositingERC20_succeeds() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n\n vm.expectCall(\n address(L2Token),\n abi.encodeWithSelector(OptimismMintableERC20.mint.selector, alice, 100)\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeFinalized(address(L2Token), address(L1Token), alice, alice, 100, hex\"\");\n\n vm.prank(address(L2Messenger));\n L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n }\n\n function test_finalizeDeposit_depositingETH_succeeds() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n\n // Should emit both the bedrock and legacy events\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit DepositFinalized(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true, address(L2Bridge));\n emit ERC20BridgeFinalized(\n address(L2Token), // localToken\n address(L1Token), // remoteToken\n alice,\n alice,\n 100,\n hex\"\"\n );\n\n vm.prank(address(L2Messenger));\n L2Bridge.finalizeDeposit(address(L1Token), address(L2Token), alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_incorrectValue_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: amount sent does not match amount required\");\n L2Bridge.finalizeBridgeETH{ value: 50 }(alice, alice, 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToSelf_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to self\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Bridge), 100, hex\"\");\n }\n\n function test_finalizeBridgeETH_sendToMessenger_reverts() external {\n vm.mockCall(\n address(L2Bridge.messenger()),\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(address(L2Messenger), 100);\n vm.prank(address(L2Messenger));\n vm.expectRevert(\"StandardBridge: cannot send to messenger\");\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, address(L2Messenger), 100, hex\"\");\n }\n}\n\ncontract L2StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer {\n function test_finalizeBridgeETH_succeeds() external {\n address messenger = address(L2Bridge.messenger());\n vm.mockCall(\n messenger,\n abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),\n abi.encode(address(L2Bridge.OTHER_BRIDGE()))\n );\n vm.deal(messenger, 100);\n vm.prank(messenger);\n\n vm.expectEmit(true, true, true, true);\n emit DepositFinalized(address(0), Predeploys.LEGACY_ERC20_ETH, alice, alice, 100, hex\"\");\n\n vm.expectEmit(true, true, true, true);\n emit ETHBridgeFinalized(alice, alice, 100, hex\"\");\n\n L2Bridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex\"\");\n }\n}\n" - }, - "contracts/test/L2ToL1MessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { L2ToL1MessagePasser } from \"../L2/L2ToL1MessagePasser.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\n\ncontract L2ToL1MessagePasserTest is CommonTest {\n L2ToL1MessagePasser messagePasser;\n\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n function setUp() public virtual override {\n super.setUp();\n messagePasser = new L2ToL1MessagePasser();\n }\n\n function testFuzz_initiateWithdrawal_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n uint256 nonce = messagePasser.messageNonce();\n\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: _value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, _sender, _target, _value, _gasLimit, _data, withdrawalHash);\n\n vm.deal(_sender, _value);\n vm.prank(_sender);\n messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);\n\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n\n bytes32 slot = keccak256(bytes.concat(withdrawalHash, bytes32(0)));\n\n assertEq(vm.load(address(messagePasser), slot), bytes32(uint256(1)));\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by a contract\n function test_initiateWithdrawal_fromContract_succeeds() external {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\"\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(\n messagePasser.messageNonce(),\n address(this),\n address(4),\n 100,\n 64000,\n hex\"\",\n withdrawalHash\n );\n\n vm.deal(address(this), 2**64);\n messagePasser.initiateWithdrawal{ value: 100 }(address(4), 64000, hex\"\");\n }\n\n // Test: initiateWithdrawal should emit the correct log when called by an EOA\n function test_initiateWithdrawal_fromEOA_succeeds() external {\n uint256 gasLimit = 64000;\n address target = address(4);\n uint256 value = 100;\n bytes memory data = hex\"ff\";\n uint256 nonce = messagePasser.messageNonce();\n\n // EOA emulation\n vm.prank(alice, alice);\n vm.deal(alice, 2**64);\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction(nonce, alice, target, value, gasLimit, data)\n );\n\n vm.expectEmit(true, true, true, true);\n emit MessagePassed(nonce, alice, target, value, gasLimit, data, withdrawalHash);\n\n messagePasser.initiateWithdrawal{ value: value }(target, gasLimit, data);\n\n // the sent messages mapping is filled\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n // the nonce increments\n assertEq(nonce + 1, messagePasser.messageNonce());\n }\n\n // Test: burn should destroy the ETH held in the contract\n function test_burn_succeeds() external {\n messagePasser.initiateWithdrawal{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n NON_ZERO_GASLIMIT,\n NON_ZERO_DATA\n );\n\n assertEq(address(messagePasser).balance, NON_ZERO_VALUE);\n vm.expectEmit(true, false, false, false);\n emit WithdrawerBalanceBurnt(NON_ZERO_VALUE);\n messagePasser.burn();\n\n // The Withdrawer should have no balance\n assertEq(address(messagePasser).balance, 0);\n }\n}\n" - }, - "contracts/test/LegacyERC20ETH.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyERC20ETH } from \"../legacy/LegacyERC20ETH.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyERC20ETH_Test is CommonTest {\n LegacyERC20ETH eth;\n\n function setUp() public virtual override {\n super.setUp();\n eth = new LegacyERC20ETH();\n }\n\n function test_metadata_succeeds() external {\n assertEq(eth.name(), \"Ether\");\n assertEq(eth.symbol(), \"ETH\");\n assertEq(eth.decimals(), 18);\n }\n\n function test_crossDomain_succeeds() external {\n assertEq(eth.l2Bridge(), Predeploys.L2_STANDARD_BRIDGE);\n assertEq(eth.l1Token(), address(0));\n }\n\n function test_transfer_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transfer is disabled\");\n eth.transfer(alice, 100);\n }\n\n function test_approve_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: approve is disabled\");\n eth.approve(alice, 100);\n }\n\n function test_transferFrom_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: transferFrom is disabled\");\n eth.transferFrom(bob, alice, 100);\n }\n\n function test_increaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: increaseAllowance is disabled\");\n eth.increaseAllowance(alice, 100);\n }\n\n function test_decreaseAllowance_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: decreaseAllowance is disabled\");\n eth.decreaseAllowance(alice, 100);\n }\n\n function test_mint_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: mint is disabled\");\n eth.mint(alice, 100);\n }\n\n function test_burn_doesNotExist_reverts() external {\n vm.expectRevert(\"LegacyERC20ETH: burn is disabled\");\n eth.burn(alice, 100);\n }\n}\n" - }, - "contracts/test/LegacyMessagePasser.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { LegacyMessagePasser } from \"../legacy/LegacyMessagePasser.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract LegacyMessagePasser_Test is CommonTest {\n LegacyMessagePasser messagePasser;\n\n function setUp() public virtual override {\n super.setUp();\n messagePasser = new LegacyMessagePasser();\n }\n\n function test_passMessageToL1_succeeds() external {\n vm.prank(alice);\n messagePasser.passMessageToL1(hex\"ff\");\n assert(messagePasser.sentMessages(keccak256(abi.encodePacked(hex\"ff\", alice))));\n }\n}\n" - }, - "contracts/test/MerkleTrie.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MerkleTrie } from \"../libraries/trie/MerkleTrie.sol\";\n\ncontract MerkleTrie_get_Test is CommonTest {\n function test_get_validProof1_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579326262\";\n bytes memory val = hex\"6176616c32\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof2_succeeds() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[\n 2\n ] = hex\"ef83206161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof3_succeeds() external {\n bytes32 root = 0xf838216fa749aefa91e0b672a9c06d3e6e983f913d7107b5dab4af60b5f5abed;\n bytes memory key = hex\"6b6579316161\";\n bytes\n memory val = hex\"303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"f387206b6579316161aa303132333435363738393031323334353637383930313233343536373839303132333435363738397878\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof4_succeeds() external {\n bytes32 root = 0x37956bab6bba472308146808d5311ac19cb4a7daae5df7efcc0f32badc97f55e;\n bytes memory key = hex\"6b6579316161\";\n bytes memory val = hex\"3031323334\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"ce87206b6579316161853031323334\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof5_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657931\";\n bytes\n memory val = hex\"30313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f862808080808080a057895fdbd71e2c67c2f9274a56811ff5cf458720a7fa713a135e3890f8cafcf8808080808080808080b130313233343536373839303132333435363738393031323334353637383930313233343536373839566572795f4c6f6e67\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof6_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657932\";\n bytes memory val = hex\"73686f7274\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[2] = hex\"df808080808080c9823262856176616c338080808080808080808573686f7274\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof7_succeeds() external {\n bytes32 root = 0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89;\n bytes memory key = hex\"6b657933\";\n bytes memory val = hex\"31323334353637383930313233343536373839303132333435363738393031\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779\";\n proof[\n 1\n ] = hex\"f87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080\";\n proof[\n 2\n ] = hex\"f839808080808080c9823363856176616c338080808080808080809f31323334353637383930313233343536373839303132333435363738393031\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof8_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"61\";\n bytes memory val = hex\"61\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22061\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof9_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"62\";\n bytes memory val = hex\"62\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22062\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_validProof10_succeeds() external {\n bytes32 root = 0x72e6c01ad0c9a7b517d4bc68a5b323287fe80f0e68f5415b4b95ecbc8ad83978;\n bytes memory key = hex\"63\";\n bytes memory val = hex\"63\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d916d780c22061c22062c2206380808080808080808080808080\";\n proof[1] = hex\"d780c22061c22062c2206380808080808080808080808080\";\n proof[2] = hex\"c22063\";\n\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n function test_get_nonexistentKey1_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"6b657932\";\n bytes[] memory proof = new bytes[](3);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 1\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[2] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_nonexistentKey2_reverts() external {\n bytes32 root = 0xd582f99275e227a1cf4284899e5ff06ee56da8859be71b553397c69151bc942f;\n bytes memory key = hex\"616e7972616e646f6d6b6579\";\n bytes[] memory proof = new bytes[](1);\n proof[\n 0\n ] = hex\"e68416b65793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_wrongKeyProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579316161\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e216a04892c039d654f1be9af20e88ae53e9ab5fa5520190e0fb2f805823e45ebad22f\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[2] = hex\"d687206e6f746865728d33343938683472697568677765\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_corruptedProof_reverts() external {\n bytes32 root = 0x2858eebfa9d96c8a9e6a0cae9d86ec9189127110f132d63f07d3544c2a75a696;\n bytes memory key = hex\"6b6579326262\";\n bytes[] memory proof = new bytes[](5);\n proof[0] = hex\"2fd2ba5ee42358802ffbe0900152a55fabe953ae880ef29abef154d639c09248a016e2\";\n proof[\n 1\n ] = hex\"f84780d687206e6f746865728d33343938683472697568677765808080808080808080a0854405b57aa6dc458bc41899a761cbbb1f66a4998af6dd0e8601c1b845395ae38080808080\";\n proof[\n 2\n ] = hex\"e583165793a03101b4447781f1e6c51ce76c709274fc80bd064f3a58ff981b6015348a826386\";\n proof[\n 3\n ] = hex\"f84580a0582eed8dd051b823d13f8648cdcd08aa2d8dac239f458863c4620e8c4d605debca83206262856176616c32ca83206363856176616c3380808080808080808080808080\";\n proof[4] = hex\"ca83206262856176616c32\";\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidDataRemainder_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa000000000000000000000000000000\";\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_invalidInternalNodeHash_reverts() external {\n bytes32 root = 0xa827dff1a657bb9bb9a1c3abe9db173e2f1359f15eb06f1647ea21ac7c95d8fa;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa09862c6b113008c4204c13755693cbb868acc25ebaa98db11df8c89a0c0dd3157\";\n proof[\n 1\n ] = hex\"f380808080808080808080a0de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f00c220118080808080\";\n proof[2] = hex\"de2a9c6a46b6ea71ab9e881c8420570cf19e833c85df6026b04f085016e78f\";\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroBranchValueLength_reverts() external {\n bytes32 root = 0xe04b3589eef96b237cd49ccb5dcf6e654a47682bfa0961d563ab843f7ad1e035;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](2);\n proof[0] = hex\"dd8200aad98080808080808080808080c43b82aabbc43c82aacc80808080\";\n proof[1] = hex\"d98080808080808080808080c43b82aabbc43c82aacc80808080\";\n\n vm.expectRevert(\"MerkleTrie: value length must be greater than zero (branch)\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_zeroLengthKey_reverts() external {\n bytes32 root = 0x54157fd62cdf2f474e7bfec2d3cd581e807bee38488c9590cb887add98936b73;\n bytes memory key = hex\"\";\n bytes[] memory proof = new bytes[](1);\n proof[0] = hex\"c78320f00082b443\";\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey1_reverts() external {\n bytes32 root = 0xa513ba530659356fb7588a2c831944e80fd8aedaa5a4dc36f918152be2be0605;\n bytes memory key = hex\"01\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"db10d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[1] = hex\"d9c32081bbc582202381aa808080808080808080808080808080\";\n proof[2] = hex\"c582202381aa\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_smallerPathThanKey2_reverts() external {\n bytes32 root = 0xa06abffaec4ebe8ccde595f4547b864b4421b21c1fc699973f94710c9bc17979;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](3);\n proof[0] = hex\"e21aa07ea462226a3dc0a46afb4ded39306d7a84d311ada3557dfc75a909fd25530905\";\n proof[\n 1\n ] = hex\"f380808080808080808080a027f11bd3af96d137b9287632f44dd00fea1ca1bd70386c30985ede8cc287476e808080c220338080\";\n proof[2] = hex\"e48200bba0a6911545ed01c2d3f4e15b8b27c7bfba97738bd5e6dd674dd07033428a4c53af\";\n\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n MerkleTrie.get(key, proof, root);\n }\n\n function test_get_extraProofElements_reverts() external {\n bytes32 root = 0x278c88eb59beba4f8b94f940c41614bb0dd80c305859ebffcd6ce07c93ca3749;\n bytes memory key = hex\"aa\";\n bytes[] memory proof = new bytes[](4);\n proof[0] = hex\"d91ad780808080808080808080c32081aac32081ab8080808080\";\n proof[1] = hex\"d780808080808080808080c32081aac32081ab8080808080\";\n proof[2] = hex\"c32081aa\";\n proof[3] = hex\"c32081aa\";\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_validProofs_succeeds(bytes4) external {\n // Generate a test case with a valid proof of inclusion for the k/v pair in the trie.\n (bytes32 root, bytes memory key, bytes memory val, bytes[] memory proof) = ffi\n .getMerkleTrieFuzzCase(\"valid\");\n\n // Assert that our expected value is equal to our actual value.\n assertEq(val, MerkleTrie.get(key, proof, root));\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidRoot_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"valid\"\n );\n\n bytes32 rootHash = keccak256(abi.encodePacked(root));\n vm.expectRevert(\"MerkleTrie: invalid root hash\");\n MerkleTrie.get(key, proof, rootHash);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_extraProofElements_reverts(bytes4) external {\n // Generate an invalid test case with an extra proof element attached to an otherwise\n // valid proof of inclusion for the passed k/v.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"extra_proof_elems\"\n );\n\n vm.expectRevert(\"MerkleTrie: value node must be last node in proof (leaf)\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidLargeInternalHash_reverts(bytes4) external {\n // Generate an invalid test case where a long proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_large_internal_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid large internal hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidInternalNodeHash_reverts(bytes4) external {\n // Generate an invalid test case where a small proof element is incorrect for the root.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_internal_node_hash\"\n );\n\n vm.expectRevert(\"MerkleTrie: invalid internal node hash\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_corruptedProof_reverts(bytes4) external {\n // Generate an invalid test case where the proof is malformed.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"corrupted_proof\"\n );\n\n vm.expectRevert(\"RLPReader: decoded item type for list is not a list item\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_invalidDataRemainder_reverts(bytes4) external {\n // Generate an invalid test case where a random element of the proof has more bytes than the\n // length designates within the RLP list encoding.\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"invalid_data_remainder\"\n );\n\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_prefixedValidKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and a valid key that is prefixed\n // with random bytes\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"prefixed_valid_key\"\n );\n\n // Ambiguous revert check- all that we care is that it *does* fail. This case may\n // fail within different branches.\n vm.expectRevert();\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_emptyKey_reverts(bytes4) external {\n // Get a random test case with a valid trie / proof and an empty key\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"empty_key\"\n );\n\n vm.expectRevert(\"MerkleTrie: empty key\");\n MerkleTrie.get(key, proof, root);\n }\n\n /// @notice The `bytes4` parameter is to enable parallel fuzz runs; it is ignored.\n function testFuzz_get_partialProof_reverts(bytes4) external {\n // Get a random test case with a valid trie / partially correct proof\n (bytes32 root, bytes memory key, , bytes[] memory proof) = ffi.getMerkleTrieFuzzCase(\n \"partial_proof\"\n );\n\n vm.expectRevert(\"MerkleTrie: ran out of proof elements\");\n MerkleTrie.get(key, proof, root);\n }\n}\n" - }, - "contracts/test/MintManager.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { MintManager } from \"../governance/MintManager.sol\";\nimport { GovernanceToken } from \"../governance/GovernanceToken.sol\";\n\ncontract MintManager_Initializer is CommonTest {\n address constant owner = address(0x1234);\n address constant rando = address(0x5678);\n GovernanceToken internal gov;\n MintManager internal manager;\n\n function setUp() public virtual override {\n super.setUp();\n\n vm.prank(owner);\n gov = new GovernanceToken();\n\n vm.prank(owner);\n manager = new MintManager(owner, address(gov));\n\n vm.prank(owner);\n gov.transferOwnership(address(manager));\n }\n}\n\ncontract MintManager_constructor_Test is MintManager_Initializer {\n /**\n * @notice Tests that the constructor properly configures the contract.\n */\n function test_constructor_succeeds() external {\n assertEq(manager.owner(), owner);\n assertEq(address(manager.governanceToken()), address(gov));\n }\n}\n\ncontract MintManager_mint_Test is MintManager_Initializer {\n /**\n * @notice Tests that the mint function properly mints tokens when called by the owner.\n */\n function test_mint_fromOwner_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n /**\n * @notice Tests that the mint function reverts when called by a non-owner.\n */\n function test_mint_fromNotOwner_reverts() external {\n // Mint from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.mint(owner, 100);\n }\n\n /**\n * @notice Tests that the mint function properly mints tokens when called by the owner a second\n * time after the mint period has elapsed.\n */\n function test_mint_afterPeriodElapsed_succeeds() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again after period elapsed (2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n manager.mint(owner, 2);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 102);\n }\n\n /**\n * @notice Tests that the mint function always reverts when called before the mint period has\n * elapsed, even if the caller is the owner.\n */\n function test_mint_beforePeriodElapsed_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: minting not permitted yet\");\n manager.mint(owner, 100);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n\n /**\n * @notice Tests that the owner cannot mint more than the mint cap.\n */\n function test_mint_moreThanCap_reverts() external {\n // Mint once.\n vm.prank(owner);\n manager.mint(owner, 100);\n\n // Token balance increases.\n assertEq(gov.balanceOf(owner), 100);\n\n // Mint again (greater than 2% max).\n vm.warp(block.timestamp + manager.MINT_PERIOD() + 1);\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint amount exceeds cap\");\n manager.mint(owner, 3);\n\n // Token balance does not increase.\n assertEq(gov.balanceOf(owner), 100);\n }\n}\n\ncontract MintManager_upgrade_Test is MintManager_Initializer {\n /**\n * @notice Tests that the owner can upgrade the mint manager.\n */\n function test_upgrade_fromOwner_succeeds() external {\n // Upgrade to new manager.\n vm.prank(owner);\n manager.upgrade(rando);\n\n // New manager is rando.\n assertEq(gov.owner(), rando);\n }\n\n /**\n * @notice Tests that the upgrade function reverts when called by a non-owner.\n */\n function test_upgrade_fromNotOwner_reverts() external {\n // Upgrade from rando fails.\n vm.prank(rando);\n vm.expectRevert(\"Ownable: caller is not the owner\");\n manager.upgrade(rando);\n }\n\n /**\n * @notice Tests that the upgrade function reverts when attempting to update to the zero\n * address, even if the caller is the owner.\n */\n function test_upgrade_toZeroAddress_reverts() external {\n // Upgrade to zero address fails.\n vm.prank(owner);\n vm.expectRevert(\"MintManager: mint manager cannot be the zero address\");\n manager.upgrade(address(0));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport {\n ILegacyMintableERC20,\n IOptimismMintableERC20\n} from \"../universal/IOptimismMintableERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ncontract OptimismMintableERC20_Test is Bridge_Initializer {\n event Mint(address indexed account, uint256 amount);\n event Burn(address indexed account, uint256 amount);\n\n function test_semver_succeeds() external {\n assertEq(L2Token.version(), \"1.0.0\");\n }\n\n function test_remoteToken_succeeds() external {\n assertEq(L2Token.remoteToken(), address(L1Token));\n }\n\n function test_bridge_succeeds() external {\n assertEq(L2Token.bridge(), address(L2Bridge));\n }\n\n function test_l1Token_succeeds() external {\n assertEq(L2Token.l1Token(), address(L1Token));\n }\n\n function test_l2Bridge_succeeds() external {\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_legacy_succeeds() external {\n // Getters for the remote token\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.l1Token(), address(L1Token));\n // Getters for the bridge\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.l2Bridge(), address(L2Bridge));\n }\n\n function test_mint_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 100);\n }\n\n function test_mint_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.mint(alice, 100);\n }\n\n function test_burn_succeeds() external {\n vm.prank(address(L2Bridge));\n L2Token.mint(alice, 100);\n\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 100);\n\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 100);\n\n assertEq(L2Token.balanceOf(alice), 0);\n }\n\n function test_burn_notBridge_reverts() external {\n // NOT the bridge\n vm.expectRevert(\"OptimismMintableERC20: only bridge can mint and burn\");\n vm.prank(address(alice));\n L2Token.burn(alice, 100);\n }\n\n function test_erc165_supportsInterface_succeeds() external {\n // The assertEq calls in this test are comparing the manual calculation of the iface,\n // with what is returned by the solidity's type().interfaceId, just to be safe.\n bytes4 iface1 = bytes4(keccak256(\"supportsInterface(bytes4)\"));\n assertEq(iface1, type(IERC165).interfaceId);\n assert(L2Token.supportsInterface(iface1));\n\n bytes4 iface2 = L2Token.l1Token.selector ^ L2Token.mint.selector ^ L2Token.burn.selector;\n assertEq(iface2, type(ILegacyMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface2));\n\n bytes4 iface3 = L2Token.remoteToken.selector ^\n L2Token.bridge.selector ^\n L2Token.mint.selector ^\n L2Token.burn.selector;\n assertEq(iface3, type(IOptimismMintableERC20).interfaceId);\n assert(L2Token.supportsInterface(iface3));\n }\n}\n" - }, - "contracts/test/OptimismMintableERC20Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\n\ncontract OptimismMintableTokenFactory_Test is Bridge_Initializer {\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n }\n\n function test_bridge_succeeds() external {\n assertEq(address(L2TokenFactory.BRIDGE()), address(L2Bridge));\n }\n\n function test_createStandardL2Token_succeeds() external {\n address remote = address(4);\n address local = LibRLP.computeAddress(address(L2TokenFactory), 2);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_sameTwice_succeeds() external {\n address remote = address(4);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n\n address local = LibRLP.computeAddress(address(L2TokenFactory), 3);\n\n vm.expectEmit(true, true, true, true);\n emit StandardL2TokenCreated(remote, local);\n\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC20Created(local, remote, alice);\n\n vm.prank(alice);\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n\n function test_createStandardL2Token_remoteIsZero_succeeds() external {\n address remote = address(0);\n vm.expectRevert(\"OptimismMintableERC20Factory: must provide remote token address\");\n L2TokenFactory.createStandardL2Token(remote, \"Beep\", \"BOOP\");\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\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 { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.sol\";\n\ncontract OptimismMintableERC721_Test is ERC721Bridge_Initializer {\n ERC721 internal L1Token;\n OptimismMintableERC721 internal L2Token;\n\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n event Mint(address indexed account, uint256 tokenId);\n\n event Burn(address indexed account, uint256 tokenId);\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n L1Token = new ERC721(\"L1Token\", \"L1T\");\n L2Token = new OptimismMintableERC721(\n address(L2Bridge),\n 1,\n address(L1Token),\n \"L2Token\",\n \"L2T\"\n );\n\n // Label the addresses for nice traces.\n vm.label(address(L1Token), \"L1ERC721Token\");\n vm.label(address(L2Token), \"L2ERC721Token\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(L2Token.name(), \"L2Token\");\n assertEq(L2Token.symbol(), \"L2T\");\n assertEq(L2Token.remoteToken(), address(L1Token));\n assertEq(L2Token.bridge(), address(L2Bridge));\n assertEq(L2Token.remoteChainId(), 1);\n assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));\n assertEq(L2Token.BRIDGE(), address(L2Bridge));\n assertEq(L2Token.REMOTE_CHAIN_ID(), 1);\n assertEq(L2Token.version(), \"1.0.0\");\n }\n\n function test_safeMint_succeeds() external {\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(address(0), alice, 1);\n\n // Expect a mint event.\n vm.expectEmit(true, true, true, true);\n emit Mint(alice, 1);\n\n // Mint the token.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token should be owned by alice.\n assertEq(L2Token.ownerOf(1), alice);\n }\n\n function test_safeMint_notBridge_reverts() external {\n // Try to mint the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.safeMint(alice, 1);\n }\n\n function test_burn_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Expect a transfer event.\n vm.expectEmit(true, true, true, true);\n emit Transfer(alice, address(0), 1);\n\n // Expect a burn event.\n vm.expectEmit(true, true, true, true);\n emit Burn(alice, 1);\n\n // Burn the token.\n vm.prank(address(L2Bridge));\n L2Token.burn(alice, 1);\n\n // Token should be owned by address(0).\n vm.expectRevert(\"ERC721: invalid token ID\");\n L2Token.ownerOf(1);\n }\n\n function test_burn_notBridge_reverts() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Try to burn the token.\n vm.expectRevert(\"OptimismMintableERC721: only bridge can call this function\");\n vm.prank(address(alice));\n L2Token.burn(alice, 1);\n }\n\n function test_tokenURI_succeeds() external {\n // Mint the token first.\n vm.prank(address(L2Bridge));\n L2Token.safeMint(alice, 1);\n\n // Token URI should be correct.\n assertEq(\n L2Token.tokenURI(1),\n string(\n abi.encodePacked(\n \"ethereum:\",\n Strings.toHexString(uint160(address(L1Token)), 20),\n \"@\",\n Strings.toString(1),\n \"/tokenURI?uint256=\",\n Strings.toString(1)\n )\n )\n );\n }\n}\n" - }, - "contracts/test/OptimismMintableERC721Factory.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC721 } from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport { ERC721Bridge_Initializer } from \"./CommonTest.t.sol\";\nimport { LibRLP } from \"./RLP.t.sol\";\nimport { OptimismMintableERC721 } from \"../universal/OptimismMintableERC721.sol\";\nimport { OptimismMintableERC721Factory } from \"../universal/OptimismMintableERC721Factory.sol\";\n\ncontract OptimismMintableERC721Factory_Test is ERC721Bridge_Initializer {\n OptimismMintableERC721Factory internal factory;\n\n event OptimismMintableERC721Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n function setUp() public override {\n super.setUp();\n\n // Set up the token pair.\n factory = new OptimismMintableERC721Factory(address(L2Bridge), 1);\n\n // Label the addresses for nice traces.\n vm.label(address(factory), \"OptimismMintableERC721Factory\");\n }\n\n function test_constructor_succeeds() external {\n assertEq(factory.BRIDGE(), address(L2Bridge));\n assertEq(factory.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_succeeds() external {\n // Predict the address based on the factory address and nonce.\n address predicted = LibRLP.computeAddress(address(factory), 1);\n\n // Expect a token creation event.\n vm.expectEmit(true, true, true, true);\n emit OptimismMintableERC721Created(predicted, address(1234), alice);\n\n // Create the token.\n vm.prank(alice);\n OptimismMintableERC721 created = OptimismMintableERC721(\n factory.createOptimismMintableERC721(address(1234), \"L2Token\", \"L2T\")\n );\n\n // Token address should be correct.\n assertEq(address(created), predicted);\n\n // Should be marked as created by the factory.\n assertEq(factory.isOptimismMintableERC721(address(created)), true);\n\n // Token should've been constructed correctly.\n assertEq(created.name(), \"L2Token\");\n assertEq(created.symbol(), \"L2T\");\n assertEq(created.REMOTE_TOKEN(), address(1234));\n assertEq(created.BRIDGE(), address(L2Bridge));\n assertEq(created.REMOTE_CHAIN_ID(), 1);\n }\n\n function test_createOptimismMintableERC721_zeroRemoteToken_reverts() external {\n // Try to create a token with a zero remote token address.\n vm.expectRevert(\"OptimismMintableERC721Factory: L1 token address cannot be address(0)\");\n factory.createOptimismMintableERC721(address(0), \"L2Token\", \"L2T\");\n }\n}\n" - }, - "contracts/test/OptimismPortal.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { Portal_Initializer, CommonTest, NextImpl } from \"./CommonTest.t.sol\";\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { L2OutputOracle } from \"../L1/L2OutputOracle.sol\";\nimport { OptimismPortal } from \"../L1/OptimismPortal.sol\";\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\ncontract OptimismPortal_Test is Portal_Initializer {\n event Paused(address);\n event Unpaused(address);\n\n function test_constructor_succeeds() external {\n assertEq(address(op.L2_ORACLE()), address(oracle));\n assertEq(op.l2Sender(), 0x000000000000000000000000000000000000dEaD);\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal can be paused by the GUARDIAN\n */\n function test_pause_succeeds() external {\n address guardian = op.GUARDIAN();\n\n assertEq(op.paused(), false);\n\n vm.expectEmit(true, true, true, true, address(op));\n emit Paused(guardian);\n\n vm.prank(guardian);\n op.pause();\n\n assertEq(op.paused(), true);\n }\n\n /**\n * @notice The OptimismPortal reverts when an account that is not the\n * GUARDIAN calls `pause()`\n */\n function test_pause_onlyGuardian_reverts() external {\n assertEq(op.paused(), false);\n\n assertTrue(op.GUARDIAN() != alice);\n vm.expectRevert(\"OptimismPortal: only guardian can pause\");\n vm.prank(alice);\n op.pause();\n\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal can be unpaused by the GUARDIAN\n */\n function test_unpause_succeeds() external {\n address guardian = op.GUARDIAN();\n\n vm.prank(guardian);\n op.pause();\n assertEq(op.paused(), true);\n\n vm.expectEmit(true, true, true, true, address(op));\n emit Unpaused(guardian);\n vm.prank(guardian);\n op.unpause();\n\n assertEq(op.paused(), false);\n }\n\n /**\n * @notice The OptimismPortal reverts when an account that is not\n * the GUARDIAN calls `unpause()`\n */\n function test_unpause_onlyGuardian_reverts() external {\n address guardian = op.GUARDIAN();\n\n vm.prank(guardian);\n op.pause();\n assertEq(op.paused(), true);\n\n assertTrue(op.GUARDIAN() != alice);\n vm.expectRevert(\"OptimismPortal: only guardian can unpause\");\n vm.prank(alice);\n op.unpause();\n\n assertEq(op.paused(), true);\n }\n\n function test_receive_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(alice, alice, 100, 100, 100_000, false, hex\"\");\n\n // give alice money and send as an eoa\n vm.deal(alice, 2**64);\n vm.prank(alice, alice);\n (bool s, ) = address(op).call{ value: 100 }(hex\"\");\n\n assert(s);\n assertEq(address(op).balance, 100);\n }\n\n // Test: depositTransaction fails when contract creation has a non-zero destination address\n function test_depositTransaction_contractCreation_reverts() external {\n // contract creation must have a target of address(0)\n vm.expectRevert(\"OptimismPortal: must send to address(0) when creating a contract\");\n op.depositTransaction(address(1), 1, 0, true, hex\"\");\n }\n\n /**\n * @notice Prevent gasless deposits from being force processed in L2 by\n * ensuring that they have a large enough gas limit set.\n */\n function test_depositTransaction_smallGasLimit_reverts() external {\n vm.expectRevert(\"OptimismPortal: gas limit must cover instrinsic gas cost\");\n op.depositTransaction({\n _to: address(1),\n _value: 0,\n _gasLimit: 0,\n _isCreation: false,\n _data: hex\"\"\n });\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a tx with 0 value\n function test_depositTransaction_noValueEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a tx with 0 value\n function test_depositTransaction_noValueContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should emit the correct log when an EOA deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should emit the correct log when a contract deposits a contract creation with 0 value\n function test_depositTransaction_createWithZeroValueForContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction(ZERO_ADDRESS, ZERO_VALUE, NON_ZERO_GASLIMIT, true, NON_ZERO_DATA);\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromEOA_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a transaction with ETH\n function test_depositTransaction_withEthValueFromContract_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n NON_ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n NON_ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n false,\n NON_ZERO_DATA\n );\n }\n\n // Test: depositTransaction should increase its eth balance when an EOA deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndEOAContractCreation_succeeds() external {\n // EOA emulation\n vm.prank(address(this), address(this));\n\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n address(this),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n hex\"\"\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n // Test: depositTransaction should increase its eth balance when a contract deposits a contract creation with ETH\n function test_depositTransaction_withEthValueAndContractContractCreation_succeeds() external {\n vm.expectEmit(true, true, false, true);\n emitTransactionDeposited(\n AddressAliasHelper.applyL1ToL2Alias(address(this)),\n ZERO_ADDRESS,\n NON_ZERO_VALUE,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n\n op.depositTransaction{ value: NON_ZERO_VALUE }(\n ZERO_ADDRESS,\n ZERO_VALUE,\n NON_ZERO_GASLIMIT,\n true,\n NON_ZERO_DATA\n );\n assertEq(address(op).balance, NON_ZERO_VALUE);\n }\n\n function test_simple_isOutputFinalized_succeeds() external {\n uint256 ts = block.timestamp;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(bytes32(uint256(1)), uint128(ts), uint128(startingBlockNumber))\n )\n );\n\n // warp to the finalization period\n vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS());\n assertEq(op.isOutputFinalized(0), false);\n\n // warp past the finalization period\n vm.warp(ts + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n assertEq(op.isOutputFinalized(0), true);\n }\n\n function test_isOutputFinalized_succeeds() external {\n uint256 checkpoint = oracle.nextBlockNumber();\n uint256 nextOutputIndex = oracle.nextOutputIndex();\n vm.roll(checkpoint);\n vm.warp(oracle.computeL2Timestamp(checkpoint) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(keccak256(abi.encode(2)), checkpoint, 0, 0);\n\n // warp to the final second of the finalization period\n uint256 finalizationHorizon = block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS();\n vm.warp(finalizationHorizon);\n // The checkpointed block should not be finalized until 1 second from now.\n assertEq(op.isOutputFinalized(nextOutputIndex), false);\n // Nor should a block after it\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n\n // warp past the finalization period\n vm.warp(finalizationHorizon + 1);\n // It should now be finalized.\n assertEq(op.isOutputFinalized(nextOutputIndex), true);\n // But not the block after it.\n vm.expectRevert(stdError.indexOOBError);\n assertEq(op.isOutputFinalized(nextOutputIndex + 1), false);\n }\n}\n\ncontract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls.\n constructor() {\n super.setUp();\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n }\n\n // Get the system into a nice ready-to-use state.\n function setUp() public override {\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n\n // Utility function used in the subsequent test. This is necessary to assert that the\n // reentrant call will revert.\n function callPortalAndExpectRevert() external payable {\n vm.expectRevert(\"OptimismPortal: can only trigger one withdrawal per transaction\");\n // Arguments here don't matter, as the require check is the first thing that happens.\n // We assume that this has already been proven.\n op.finalizeWithdrawalTransaction(_defaultTx);\n // Assert that the withdrawal was not finalized.\n assertFalse(op.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx)));\n }\n\n /**\n * @notice Proving withdrawal transactions should revert when paused\n */\n function test_proveWithdrawalTransaction_paused_reverts() external {\n vm.prank(op.GUARDIAN());\n op.pause();\n\n vm.expectRevert(\"OptimismPortal: paused\");\n op.proveWithdrawalTransaction({\n _tx: _defaultTx,\n _l2OutputIndex: _proposedOutputIndex,\n _outputRootProof: _outputRootProof,\n _withdrawalProof: _withdrawalProof\n });\n }\n\n // Test: proveWithdrawalTransaction cannot prove a withdrawal with itself (the OptimismPortal) as the target.\n function test_proveWithdrawalTransaction_onSelfCall_reverts() external {\n _defaultTx.target = address(op);\n vm.expectRevert(\"OptimismPortal: you cannot send messages to the portal contract\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the outputRootProof does not match the output root\n function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external {\n // Modify the version to invalidate the withdrawal proof.\n _outputRootProof.version = bytes32(uint256(1));\n vm.expectRevert(\"OptimismPortal: invalid output root proof\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the proof is invalid due to non-existence of\n // the withdrawal.\n function test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() external {\n // modify the default test values to invalidate the proof.\n _defaultTx.data = hex\"abcd\";\n vm.expectRevert(\"MerkleTrie: path remainder must share all nibbles with key\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction reverts if the passed transaction's withdrawalHash has\n // already been proven.\n function test_proveWithdrawalTransaction_replayProve_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: withdrawal hash has already been proven\");\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has\n // already been proven AND the output root has changed AND the l2BlockNumber stays the same.\n function test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`\n // inside of the `provenWithdrawal`s mapping.\n bytes32 slot;\n assembly {\n mstore(0x00, sload(_withdrawalHash.slot))\n mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in the OptimismPortal\n slot := keccak256(0x00, 0x40)\n }\n\n // Store a different output root within the `provenWithdrawals` mapping without\n // touching the l2BlockNumber or timestamp.\n vm.store(address(op), slot, bytes32(0));\n\n // Warp ahead 1 second\n vm.warp(block.timestamp + 1);\n\n // Even though we have already proven this withdrawalHash, we should be allowed to re-submit\n // our proof with a changed outputRoot\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Ensure that the withdrawal was updated within the mapping\n (, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);\n assertEq(timestamp, block.timestamp);\n }\n\n // Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has\n // already been proven AND the output root + output index + l2BlockNumber changes.\n function test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds()\n external\n {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`\n // inside of the `provenWithdrawal`s mapping.\n bytes32 slot;\n assembly {\n mstore(0x00, sload(_withdrawalHash.slot))\n mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in OptimismPortal\n slot := keccak256(0x00, 0x40)\n }\n\n // Store a dummy output root within the `provenWithdrawals` mapping without touching the\n // l2BlockNumber or timestamp.\n vm.store(address(op), slot, bytes32(0));\n\n // Fetch the output proposal at `_proposedOutputIndex` from the L2OutputOracle\n Types.OutputProposal memory proposal = op.L2_ORACLE().getL2Output(_proposedOutputIndex);\n\n // Propose the same output root again, creating the same output at a different index + l2BlockNumber.\n vm.startPrank(op.L2_ORACLE().PROPOSER());\n op.L2_ORACLE().proposeL2Output(\n proposal.outputRoot,\n op.L2_ORACLE().nextBlockNumber(),\n blockhash(block.number),\n block.number\n );\n vm.stopPrank();\n\n // Warp ahead 1 second\n vm.warp(block.timestamp + 1);\n\n // Even though we have already proven this withdrawalHash, we should be allowed to re-submit\n // our proof with a changed outputRoot + a different output index\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex + 1,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Ensure that the withdrawal was updated within the mapping\n (, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);\n assertEq(timestamp, block.timestamp);\n }\n\n // Test: proveWithdrawalTransaction succeeds and emits the WithdrawalProven event.\n function test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n }\n\n // Test: finalizeWithdrawalTransaction succeeds and emits the WithdrawalFinalized event.\n function test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, false, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore + 100);\n }\n\n /**\n * @notice Finalizing withdrawal transactions should revert when paused\n */\n function test_finalizeWithdrawalTransaction_paused_reverts() external {\n vm.prank(op.GUARDIAN());\n op.pause();\n\n vm.expectRevert(\"OptimismPortal: paused\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has not been proven.\n function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectRevert(\"OptimismPortal: withdrawal has not been proven yet\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if withdrawal not proven long enough ago.\n function test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Mock a call where the resulting output root is anything but the original output root. In\n // this case we just use bytes32(uint256(1)).\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(bytes32(uint256(1)), _proposedBlockNumber)\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the provenWithdrawal's timestamp is less\n // than the L2 output oracle's starting timestamp\n function test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a startingTimestamp change on the L2 Oracle\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSignature(\"startingTimestamp()\"),\n abi.encode(block.timestamp + 1)\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output root proven is not the same as the\n // output root at the time of finalization.\n function test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock an outputRoot change on the output proposal before attempting\n // to finalize the withdrawal.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n bytes32(uint256(0)),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\n \"OptimismPortal: output root proven is not the same as current output root\"\n );\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the output proposal's timestamp has\n // not passed the finalization period.\n function test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Prove our withdrawal\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp to after the finalization period\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Mock a timestamp change on the output proposal that has not passed the\n // finalization period.\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(block.timestamp + 1),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n // Attempt to finalize the withdrawal\n vm.expectRevert(\"OptimismPortal: output proposal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Ensure that bob's balance has remained the same\n assertEq(bobBalanceBefore, address(bob).balance);\n }\n\n // Test: finalizeWithdrawalTransaction fails because the target reverts,\n // and emits the WithdrawalFinalized event with success=false.\n function test_finalizeWithdrawalTransaction_targetFails_fails() external {\n uint256 bobBalanceBefore = address(bob).balance;\n vm.etch(bob, hex\"fe\"); // Contract with just the invalid opcode.\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, false);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the finalization period has not yet passed.\n function test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() external {\n // Setup the Oracle to return an output with a recent timestamp\n uint256 recentTimestamp = block.timestamp - 1000;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n _outputRoot,\n uint128(recentTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if the withdrawal has already been finalized.\n function test_finalizeWithdrawalTransaction_onReplay_reverts() external {\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(_withdrawalHash, alice, bob);\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(_withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if insufficient gas is supplied.\n function test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() external {\n // This number was identified through trial and error.\n uint256 gasLimit = 150_000;\n Types.WithdrawalTransaction memory insufficientGasTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: gasLimit,\n data: hex\"\"\n });\n\n // Get updated proof inputs.\n (bytes32 stateRoot, bytes32 storageRoot, , , bytes[] memory withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(insufficientGasTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n Hashing.hashOutputRootProof(outputRootProof),\n uint128(block.timestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n op.proveWithdrawalTransaction(\n insufficientGasTx,\n _proposedOutputIndex,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectRevert(\"SafeCall: Not enough gas\");\n op.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx);\n }\n\n // Test: finalizeWithdrawalTransaction reverts if a sub-call attempts to finalize another\n // withdrawal.\n function test_finalizeWithdrawalTransaction_onReentrancy_reverts() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n // Copy and modify the default test values to attempt a reentrant call by first calling to\n // this contract's callPortalAndExpectRevert() function above.\n Types.WithdrawalTransaction memory _testTx = _defaultTx;\n _testTx.target = address(this);\n _testTx.data = abi.encodeWithSelector(this.callPortalAndExpectRevert.selector);\n\n // Get modified proof inputs.\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_testTx);\n Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({\n version: bytes32(0),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(0)\n });\n\n // Setup the Oracle to return the outputRoot we want as well as a finalized timestamp.\n uint256 finalizedTimestamp = block.timestamp - oracle.FINALIZATION_PERIOD_SECONDS() - 1;\n vm.mockCall(\n address(op.L2_ORACLE()),\n abi.encodeWithSelector(L2OutputOracle.getL2Output.selector),\n abi.encode(\n Types.OutputProposal(\n outputRoot,\n uint128(finalizedTimestamp),\n uint128(_proposedBlockNumber)\n )\n )\n );\n\n vm.expectEmit(true, true, true, true);\n emit WithdrawalProven(withdrawalHash, alice, address(this));\n op.proveWithdrawalTransaction(\n _testTx,\n _proposedBlockNumber,\n outputRootProof,\n withdrawalProof\n );\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n vm.expectCall(address(this), _testTx.data);\n vm.expectEmit(true, true, true, true);\n emit WithdrawalFinalized(withdrawalHash, true);\n op.finalizeWithdrawalTransaction(_testTx);\n\n // Ensure that bob's balance was not changed by the reentrant call.\n assert(address(bob).balance == bobBalanceBefore);\n }\n\n function testDiff_finalizeWithdrawalTransaction_succeeds(\n address _sender,\n address _target,\n uint256 _value,\n uint256 _gasLimit,\n bytes memory _data\n ) external {\n // Cannot call the optimism portal\n vm.assume(_target != address(op));\n // Total ETH supply is currently about 120M ETH.\n uint256 value = bound(_value, 0, 200_000_000 ether);\n uint256 gasLimit = bound(_gasLimit, 0, 50_000_000);\n uint256 nonce = messagePasser.messageNonce();\n Types.WithdrawalTransaction memory _tx = Types.WithdrawalTransaction({\n nonce: nonce,\n sender: _sender,\n target: _target,\n value: value,\n gasLimit: gasLimit,\n data: _data\n });\n (\n bytes32 stateRoot,\n bytes32 storageRoot,\n bytes32 outputRoot,\n bytes32 withdrawalHash,\n bytes[] memory withdrawalProof\n ) = ffi.getProveWithdrawalTransactionInputs(_tx);\n\n Types.OutputRootProof memory proof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: stateRoot,\n messagePasserStorageRoot: storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n\n // Ensure the values returned from ffi are correct\n assertEq(outputRoot, Hashing.hashOutputRootProof(proof));\n assertEq(withdrawalHash, Hashing.hashWithdrawal(_tx));\n\n // Mock the call to the oracle\n vm.mockCall(\n address(oracle),\n abi.encodeWithSelector(oracle.getL2Output.selector),\n abi.encode(outputRoot, 0)\n );\n\n // Start the withdrawal, it must be initiated by the _sender and the\n // correct value must be passed along\n vm.deal(_tx.sender, _tx.value);\n vm.prank(_tx.sender);\n messagePasser.initiateWithdrawal{ value: _tx.value }(_tx.target, _tx.gasLimit, _tx.data);\n\n // Ensure that the sentMessages is correct\n assertEq(messagePasser.sentMessages(withdrawalHash), true);\n\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n op.proveWithdrawalTransaction(\n _tx,\n 100, // l2BlockNumber\n proof,\n withdrawalProof\n );\n }\n}\n\ncontract OptimismPortalUpgradeable_Test is Portal_Initializer {\n Proxy internal proxy;\n uint64 initialBlockNum;\n\n function setUp() public override {\n super.setUp();\n initialBlockNum = uint64(block.number);\n proxy = Proxy(payable(address(op)));\n }\n\n function test_params_initValuesOnProxy_succeeds() external {\n OptimismPortal p = OptimismPortal(payable(address(proxy)));\n\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = p.params();\n\n ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig();\n assertEq(prevBaseFee, rcfg.minimumBaseFee);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_initialize_cannotInitProxy_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(payable(proxy)).initialize(false);\n }\n\n function test_initialize_cannotInitImpl_reverts() external {\n vm.expectRevert(\"Initializable: contract is already initialized\");\n OptimismPortal(opImpl).initialize(false);\n }\n\n function test_upgradeToAndCall_upgrading_succeeds() external {\n // Check an unused slot before upgrading.\n bytes32 slot21Before = vm.load(address(op), bytes32(uint256(21)));\n assertEq(bytes32(0), slot21Before);\n\n NextImpl nextImpl = new NextImpl();\n vm.startPrank(multisig);\n proxy.upgradeToAndCall(\n address(nextImpl),\n abi.encodeWithSelector(NextImpl.initialize.selector)\n );\n assertEq(proxy.implementation(), address(nextImpl));\n\n // Verify that the NextImpl contract initialized its values according as expected\n bytes32 slot21After = vm.load(address(op), bytes32(uint256(21)));\n bytes32 slot21Expected = NextImpl(address(op)).slot21Init();\n assertEq(slot21Expected, slot21After);\n }\n}\n" - }, - "contracts/test/Proxy.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\ncontract SimpleStorage {\n mapping(uint256 => uint256) internal store;\n\n function get(uint256 key) external payable returns (uint256) {\n return store[key];\n }\n\n function set(uint256 key, uint256 value) external payable {\n store[key] = value;\n }\n}\n\ncontract Clasher {\n function upgradeTo(address) external pure {\n revert(\"upgradeTo\");\n }\n}\n\ncontract Proxy_Test is Test {\n event Upgraded(address indexed implementation);\n event AdminChanged(address previousAdmin, address newAdmin);\n\n address alice = address(64);\n\n bytes32 internal constant IMPLEMENTATION_KEY =\n bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1);\n\n bytes32 internal constant OWNER_KEY = bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1);\n\n Proxy proxy;\n SimpleStorage simpleStorage;\n\n function setUp() external {\n // Deploy a proxy and simple storage contract as\n // the implementation\n proxy = new Proxy(alice);\n simpleStorage = new SimpleStorage();\n\n vm.prank(alice);\n proxy.upgradeTo(address(simpleStorage));\n }\n\n function test_implementationKey_succeeds() external {\n // The hardcoded implementation key should be correct\n vm.prank(alice);\n proxy.upgradeTo(address(6));\n\n bytes32 key = vm.load(address(proxy), IMPLEMENTATION_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(6));\n }\n\n function test_ownerKey_succeeds() external {\n // The hardcoded owner key should be correct\n vm.prank(alice);\n proxy.changeAdmin(address(6));\n\n bytes32 key = vm.load(address(proxy), OWNER_KEY);\n assertEq(address(6), Bytes32AddressLib.fromLast20Bytes(key));\n\n vm.prank(address(6));\n address owner = proxy.admin();\n assertEq(owner, address(6));\n }\n\n function test_proxyCallToImp_notAdmin_succeeds() external {\n // The implementation does not have a `upgradeTo`\n // method, calling `upgradeTo` not as the owner\n // should revert.\n vm.expectRevert();\n proxy.upgradeTo(address(64));\n\n // Call `upgradeTo` as the owner, it should succeed\n // and emit the `Upgraded` event.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(64));\n vm.prank(alice);\n proxy.upgradeTo(address(64));\n\n // Get the implementation as the owner\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(64));\n }\n\n function test_ownerProxyCall_notAdmin_succeeds() external {\n // Calling `changeAdmin` not as the owner should revert\n // as the implementation does not have a `changeAdmin` method.\n vm.expectRevert();\n proxy.changeAdmin(address(1));\n\n // Call `changeAdmin` as the owner, it should succeed\n // and emit the `AdminChanged` event.\n vm.expectEmit(true, true, true, true);\n emit AdminChanged(alice, address(1));\n vm.prank(alice);\n proxy.changeAdmin(address(1));\n\n // Calling `admin` not as the owner should\n // revert as the implementation does not have\n // a `admin` method.\n vm.expectRevert();\n proxy.admin();\n\n // Calling `admin` as the owner should work.\n vm.prank(address(1));\n address owner = proxy.admin();\n assertEq(owner, address(1));\n }\n\n function test_delegatesToImpl_succeeds() external {\n // Call the storage setter on the proxy\n SimpleStorage(address(proxy)).set(1, 1);\n\n // The key should not be set in the implementation\n uint256 result = simpleStorage.get(1);\n assertEq(result, 0);\n {\n // The key should be set in the proxy\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n\n {\n // The owner should be able to call through the proxy\n // when there is not a function selector crash\n vm.prank(alice);\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 1);\n }\n }\n\n function test_upgradeToAndCall_succeeds() external {\n {\n // There should be nothing in the current proxy storage\n uint256 expect = SimpleStorage(address(proxy)).get(1);\n assertEq(expect, 0);\n }\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call.\n vm.expectEmit(true, true, true, true);\n emit Upgraded(address(simpleStorage));\n vm.prank(alice);\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The call should have impacted the state\n uint256 result = SimpleStorage(address(proxy)).get(1);\n assertEq(result, 1);\n }\n\n function test_upgradeToAndCall_functionDoesNotExist_reverts() external {\n // Get the current implementation address\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // Deploy a new SimpleStorage\n simpleStorage = new SimpleStorage();\n\n // Set the new SimpleStorage as the implementation\n // and call. This reverts because the calldata doesn't\n // match a function on the implementation.\n vm.expectRevert(\"Proxy: delegatecall to new implementation contract failed\");\n vm.prank(alice);\n proxy.upgradeToAndCall(address(simpleStorage), hex\"\");\n\n // The implementation address should have not\n // updated because the call to `upgradeToAndCall`\n // reverted.\n vm.prank(alice);\n address postImpl = proxy.implementation();\n assertEq(impl, postImpl);\n\n // The attempt to `upgradeToAndCall`\n // should revert when it is not called by the owner.\n vm.expectRevert();\n proxy.upgradeToAndCall(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n }\n\n function test_upgradeToAndCall_isPayable_succeeds() external {\n // Give alice some funds\n vm.deal(alice, 1 ether);\n // Set the implementation and call and send\n // value.\n vm.prank(alice);\n proxy.upgradeToAndCall{ value: 1 ether }(\n address(simpleStorage),\n abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)\n );\n\n // The implementation address should be correct\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n\n // The proxy should have a balance\n assertEq(address(proxy).balance, 1 ether);\n }\n\n function test_upgradeTo_clashingFunctionSignatures_succeeds() external {\n // Clasher has a clashing function with the proxy.\n Clasher clasher = new Clasher();\n\n // Set the clasher as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(clasher));\n\n {\n // Assert that the implementation was set properly.\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(clasher));\n }\n\n // Call the clashing function on the proxy\n // not as the owner so that the call passes through.\n // The implementation will revert so we can be\n // sure that the call passed through.\n vm.expectRevert(bytes(\"upgradeTo\"));\n proxy.upgradeTo(address(0));\n\n {\n // Now call the clashing function as the owner\n // and be sure that it doesn't pass through to\n // the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n vm.prank(alice);\n address impl = proxy.implementation();\n assertEq(impl, address(0));\n }\n }\n\n // Allow for `eth_call` to call proxy methods\n // by setting \"from\" to `address(0)`.\n function test_implementation_zeroAddressCaller_succeeds() external {\n vm.prank(address(0));\n address impl = proxy.implementation();\n assertEq(impl, address(simpleStorage));\n }\n\n function test_implementation_isZeroAddress_reverts() external {\n // Set `address(0)` as the implementation.\n vm.prank(alice);\n proxy.upgradeTo(address(0));\n\n (bool success, bytes memory returndata) = address(proxy).call(hex\"\");\n assertEq(success, false);\n\n bytes memory err = abi.encodeWithSignature(\n \"Error(string)\",\n \"Proxy: implementation not initialized\"\n );\n\n assertEq(returndata, err);\n }\n}\n" - }, - "contracts/test/ProxyAdmin.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { ProxyAdmin } from \"../universal/ProxyAdmin.sol\";\nimport { SimpleStorage } from \"./Proxy.t.sol\";\nimport { L1ChugSplashProxy } from \"../legacy/L1ChugSplashProxy.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\n\ncontract ProxyAdmin_Test is Test {\n address alice = address(64);\n\n Proxy proxy;\n L1ChugSplashProxy chugsplash;\n ResolvedDelegateProxy resolved;\n\n AddressManager addressManager;\n\n ProxyAdmin admin;\n\n SimpleStorage implementation;\n\n function setUp() external {\n // Deploy the proxy admin\n admin = new ProxyAdmin(alice);\n // Deploy the standard proxy\n proxy = new Proxy(address(admin));\n\n // Deploy the legacy L1ChugSplashProxy with the admin as the owner\n chugsplash = new L1ChugSplashProxy(address(admin));\n\n // Deploy the legacy AddressManager\n addressManager = new AddressManager();\n // The proxy admin must be the new owner of the address manager\n addressManager.transferOwnership(address(admin));\n // Deploy a legacy ResolvedDelegateProxy with the name `a`.\n // Whatever `a` is set to in AddressManager will be the address\n // that is used for the implementation.\n resolved = new ResolvedDelegateProxy(addressManager, \"a\");\n\n // Impersonate alice for setting up the admin.\n vm.startPrank(alice);\n // Set the address of the address manager in the admin so that it\n // can resolve the implementation address of legacy\n // ResolvedDelegateProxy based proxies.\n admin.setAddressManager(addressManager);\n // Set the reverse lookup of the ResolvedDelegateProxy\n // proxy\n admin.setImplementationName(address(resolved), \"a\");\n\n // Set the proxy types\n admin.setProxyType(address(proxy), ProxyAdmin.ProxyType.ERC1967);\n admin.setProxyType(address(chugsplash), ProxyAdmin.ProxyType.CHUGSPLASH);\n admin.setProxyType(address(resolved), ProxyAdmin.ProxyType.RESOLVED);\n vm.stopPrank();\n\n implementation = new SimpleStorage();\n }\n\n function test_setImplementationName_succeeds() external {\n vm.prank(alice);\n admin.setImplementationName(address(1), \"foo\");\n assertEq(admin.implementationName(address(1)), \"foo\");\n }\n\n function test_setAddressManager_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setAddressManager(AddressManager((address(0))));\n }\n\n function test_setImplementationName_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setImplementationName(address(0), \"foo\");\n }\n\n function test_setProxyType_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.setProxyType(address(0), ProxyAdmin.ProxyType.CHUGSPLASH);\n }\n\n function test_owner_succeeds() external {\n assertEq(admin.owner(), alice);\n }\n\n function test_proxyType_succeeds() external {\n assertEq(uint256(admin.proxyType(address(proxy))), uint256(ProxyAdmin.ProxyType.ERC1967));\n assertEq(\n uint256(admin.proxyType(address(chugsplash))),\n uint256(ProxyAdmin.ProxyType.CHUGSPLASH)\n );\n assertEq(\n uint256(admin.proxyType(address(resolved))),\n uint256(ProxyAdmin.ProxyType.RESOLVED)\n );\n }\n\n function test_erc1967GetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(proxy));\n }\n\n function test_chugsplashGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyImplementation_succeeds() external {\n getProxyImplementation(payable(resolved));\n }\n\n function getProxyImplementation(address payable _proxy) internal {\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(0));\n }\n\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n {\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n }\n\n function test_erc1967GetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedGetProxyAdmin_succeeds() external {\n getProxyAdmin(payable(resolved));\n }\n\n function getProxyAdmin(address payable _proxy) internal {\n address owner = admin.getProxyAdmin(_proxy);\n assertEq(owner, address(admin));\n }\n\n function test_erc1967ChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(proxy));\n }\n\n function test_chugsplashChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(chugsplash));\n }\n\n function test_delegateResolvedChangeProxyAdmin_succeeds() external {\n changeProxyAdmin(payable(resolved));\n }\n\n function changeProxyAdmin(address payable _proxy) internal {\n ProxyAdmin.ProxyType proxyType = admin.proxyType(address(_proxy));\n\n vm.prank(alice);\n admin.changeProxyAdmin(_proxy, address(128));\n\n // The proxy is no longer the admin and can\n // no longer call the proxy interface except for\n // the ResolvedDelegate type on which anybody can\n // call the admin interface.\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n vm.expectRevert(\"Proxy: implementation not initialized\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n vm.expectRevert(\"L1ChugSplashProxy: implementation is not set yet\");\n admin.getProxyAdmin(_proxy);\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n // Just an empty block to show that all cases are covered\n } else {\n vm.expectRevert(\"ProxyAdmin: unknown proxy type\");\n }\n\n // Call the proxy contract directly to get the admin.\n // Different proxy types have different interfaces.\n vm.prank(address(128));\n if (proxyType == ProxyAdmin.ProxyType.ERC1967) {\n assertEq(Proxy(payable(_proxy)).admin(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.CHUGSPLASH) {\n assertEq(L1ChugSplashProxy(payable(_proxy)).getOwner(), address(128));\n } else if (proxyType == ProxyAdmin.ProxyType.RESOLVED) {\n assertEq(addressManager.owner(), address(128));\n } else {\n assert(false);\n }\n }\n\n function test_erc1967Upgrade_succeeds() external {\n upgrade(payable(proxy));\n }\n\n function test_chugsplashUpgrade_succeeds() external {\n upgrade(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgrade_succeeds() external {\n upgrade(payable(resolved));\n }\n\n function upgrade(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgrade(_proxy, address(implementation));\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n }\n\n function test_erc1967UpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(proxy));\n }\n\n function test_chugsplashUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(chugsplash));\n }\n\n function test_delegateResolvedUpgradeAndCall_succeeds() external {\n upgradeAndCall(payable(resolved));\n }\n\n function upgradeAndCall(address payable _proxy) internal {\n vm.prank(alice);\n admin.upgradeAndCall(\n _proxy,\n address(implementation),\n abi.encodeWithSelector(SimpleStorage.set.selector, 1, 1)\n );\n\n address impl = admin.getProxyImplementation(_proxy);\n assertEq(impl, address(implementation));\n\n uint256 got = SimpleStorage(address(_proxy)).get(1);\n assertEq(got, 1);\n }\n\n function test_onlyOwner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.changeProxyAdmin(payable(proxy), address(0));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgrade(payable(proxy), address(implementation));\n\n vm.expectRevert(\"Ownable: caller is not the owner\");\n admin.upgradeAndCall(payable(proxy), address(implementation), hex\"\");\n }\n\n function test_isUpgrading_succeeds() external {\n assertEq(false, admin.isUpgrading());\n\n vm.prank(alice);\n admin.setUpgrading(true);\n assertEq(true, admin.isUpgrading());\n }\n}\n" - }, - "contracts/test/RLP.t.sol": { - "content": "// SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport { Bytes32AddressLib } from \"@rari-capital/solmate/src/utils/Bytes32AddressLib.sol\";\n\n/**\n * @title LibRLP\n * @notice Via https://github.com/Rari-Capital/solmate/issues/207.\n */\nlibrary LibRLP {\n using Bytes32AddressLib for bytes32;\n\n function computeAddress(address deployer, uint256 nonce) internal pure returns (address) {\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80)))\n .fromLast20Bytes();\n if (nonce <= 0x7f)\n return\n keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce)))\n .fromLast20Bytes();\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= type(uint8).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd7),\n bytes1(0x94),\n deployer,\n bytes1(0x81),\n uint8(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint16).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd8),\n bytes1(0x94),\n deployer,\n bytes1(0x82),\n uint16(nonce)\n )\n ).fromLast20Bytes();\n if (nonce <= type(uint24).max)\n return\n keccak256(\n abi.encodePacked(\n bytes1(0xd9),\n bytes1(0x94),\n deployer,\n bytes1(0x83),\n uint24(nonce)\n )\n ).fromLast20Bytes();\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return\n keccak256(\n abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce))\n ).fromLast20Bytes();\n }\n}\n" - }, - "contracts/test/RLPReader.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { stdError } from \"forge-std/Test.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { RLPReader } from \"../libraries/rlp/RLPReader.sol\";\n\ncontract RLPReader_readBytes_Test is CommonTest {\n function test_readBytes_bytestring00_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"00\"), hex\"00\");\n }\n\n function test_readBytes_bytestring01_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"01\"), hex\"01\");\n }\n\n function test_readBytes_bytestring7f_succeeds() external {\n assertEq(RLPReader.readBytes(hex\"7f\"), hex\"7f\");\n }\n\n function test_readBytes_revertListItem_reverts() external {\n vm.expectRevert(\"RLPReader: decoded item type for bytes is not a data item\");\n RLPReader.readBytes(hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_readBytes_invalidStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of string length (long string)\"\n );\n RLPReader.readBytes(hex\"b9\");\n }\n\n function test_readBytes_invalidListLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be > than length of list length (long list)\"\n );\n RLPReader.readBytes(hex\"ff\");\n }\n\n function test_readBytes_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: bytes value contains an invalid remainder\");\n RLPReader.readBytes(hex\"800a\");\n }\n\n function test_readBytes_invalidPrefix_reverts() external {\n vm.expectRevert(\n \"RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)\"\n );\n RLPReader.readBytes(hex\"810a\");\n }\n}\n\ncontract RLPReader_readList_Test is CommonTest {\n function test_readList_empty_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c0\");\n assertEq(list.length, 0);\n }\n\n function test_readList_multiList_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c6827a77c10401\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"827a77\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c104\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"01\");\n }\n\n function test_readList_shortListMax1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n\n assertEq(list.length, 11);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[4]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[5]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[6]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[7]), hex\"8471776572\");\n assertEq(RLPReader.readRawBytes(list[8]), hex\"847a786376\");\n assertEq(RLPReader.readRawBytes(list[9]), hex\"8461736466\");\n assertEq(RLPReader.readRawBytes(list[10]), hex\"8471776572\");\n }\n\n function test_readList_longList1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n\n assertEq(list.length, 4);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"cf84617364668471776572847a786376\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"cf84617364668471776572847a786376\");\n }\n\n function test_readList_longList2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n assertEq(list.length, 32);\n\n for (uint256 i = 0; i < 32; i++) {\n assertEq(RLPReader.readRawBytes(list[i]), hex\"cf84617364668471776572847a786376\");\n }\n }\n\n function test_readList_listLongerThan32Elements_reverts() external {\n vm.expectRevert(stdError.indexOOBError);\n RLPReader.readList(\n hex\"e1454545454545454545454545454545454545454545454545454545454545454545\"\n );\n }\n\n function test_readList_listOfLists_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c4c2c0c0c0\");\n assertEq(list.length, 2);\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c2c0c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c0\");\n }\n\n function test_readList_listOfLists2_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(hex\"c7c0c1c0c3c0c1c0\");\n assertEq(list.length, 3);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"c0\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"c1c0\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"c3c0c1c0\");\n }\n\n function test_readList_dictTest1_succeeds() external {\n RLPReader.RLPItem[] memory list = RLPReader.readList(\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n assertEq(list.length, 4);\n\n assertEq(RLPReader.readRawBytes(list[0]), hex\"ca846b6579318476616c31\");\n assertEq(RLPReader.readRawBytes(list[1]), hex\"ca846b6579328476616c32\");\n assertEq(RLPReader.readRawBytes(list[2]), hex\"ca846b6579338476616c33\");\n assertEq(RLPReader.readRawBytes(list[3]), hex\"ca846b6579348476616c34\");\n }\n\n function test_readList_invalidShortList_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efdebd\");\n }\n\n function test_readList_longStringLength_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(hex\"efb83600\");\n }\n\n function test_readList_notLongEnough_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than list length (short list)\"\n );\n RLPReader.readList(\n hex\"efdebdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n );\n }\n\n function test_readList_int32Overflow_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"bf0f000000000000021111\");\n }\n\n function test_readList_int32Overflow2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ff0f000000000000021111\");\n }\n\n function test_readList_incorrectLengthInArray_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b9002100dc2b275d0f74e8a53e6f4ec61b27f24278820be3f82ea2110e582081b0565df0\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(\n hex\"b90040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_leadingZerosInLongLengthArray2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must not have any leading zeros (long string)\"\n );\n RLPReader.readList(hex\"b800\");\n }\n\n function test_readList_leadingZerosInLongLengthList1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must not have any leading zeros (long list)\");\n RLPReader.readList(\n hex\"fb00000040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f\"\n );\n }\n\n function test_readList_nonOptimalLongLengthArray1_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b81000112233445566778899aabbccddeeff\");\n }\n\n function test_readList_nonOptimalLongLengthArray2_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b801ff\");\n }\n\n function test_readList_invalidValue_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than string length (short string)\"\n );\n RLPReader.readList(hex\"91\");\n }\n\n function test_readList_invalidRemainder_reverts() external {\n vm.expectRevert(\"RLPReader: list item has an invalid data remainder\");\n RLPReader.readList(hex\"c000\");\n }\n\n function test_readList_notEnoughContentForString1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"ba010000aabbccddeeff\");\n }\n\n function test_readList_notEnoughContentForString2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long string)\"\n );\n RLPReader.readList(hex\"b840ffeeddccbbaa99887766554433221100\");\n }\n\n function test_readList_notEnoughContentForList1_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"f90180\");\n }\n\n function test_readList_notEnoughContentForList2_reverts() external {\n vm.expectRevert(\n \"RLPReader: length of content must be greater than total length (long list)\"\n );\n RLPReader.readList(hex\"ffffffffffffffffff0001020304050607\");\n }\n\n function test_readList_longStringLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long string)\");\n RLPReader.readList(hex\"b80100\");\n }\n\n function test_readList_longListLessThan56Bytes_reverts() external {\n vm.expectRevert(\"RLPReader: length of content must be greater than 55 bytes (long list)\");\n RLPReader.readList(hex\"f80100\");\n }\n}\n" - }, - "contracts/test/RLPWriter.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { RLPWriter } from \"../libraries/rlp/RLPWriter.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\n\ncontract RLPWriter_writeString_Test is CommonTest {\n function test_writeString_empty_succeeds() external {\n assertEq(RLPWriter.writeString(\"\"), hex\"80\");\n }\n\n function test_writeString_bytestring00_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0000\"), hex\"00\");\n }\n\n function test_writeString_bytestring01_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u0001\"), hex\"01\");\n }\n\n function test_writeString_bytestring7f_succeeds() external {\n assertEq(RLPWriter.writeString(\"\\u007F\"), hex\"7f\");\n }\n\n function test_writeString_shortstring_succeeds() external {\n assertEq(RLPWriter.writeString(\"dog\"), hex\"83646f67\");\n }\n\n function test_writeString_shortstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing eli\"),\n hex\"b74c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c69\"\n );\n }\n\n function test_writeString_longstring_succeeds() external {\n assertEq(\n RLPWriter.writeString(\"Lorem ipsum dolor sit amet, consectetur adipisicing elit\"),\n hex\"b8384c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c6974\"\n );\n }\n\n function test_writeString_longstring2_succeeds() external {\n assertEq(\n RLPWriter.writeString(\n \"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\"\n ),\n hex\"b904004c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e6720656c69742e20437572616269747572206d6175726973206d61676e612c20737573636970697420736564207665686963756c61206e6f6e2c20696163756c697320666175636962757320746f72746f722e2050726f696e20737573636970697420756c74726963696573206d616c6573756164612e204475697320746f72746f7220656c69742c2064696374756d2071756973207472697374697175652065752c20756c7472696365732061742072697375732e204d6f72626920612065737420696d70657264696574206d6920756c6c616d636f7270657220616c6971756574207375736369706974206e6563206c6f72656d2e2041656e65616e2071756973206c656f206d6f6c6c69732c2076756c70757461746520656c6974207661726975732c20636f6e73657175617420656e696d2e204e756c6c6120756c74726963657320747572706973206a7573746f2c20657420706f73756572652075726e6120636f6e7365637465747572206e65632e2050726f696e206e6f6e20636f6e76616c6c6973206d657475732e20446f6e65632074656d706f7220697073756d20696e206d617572697320636f6e67756520736f6c6c696369747564696e2e20566573746962756c756d20616e746520697073756d207072696d697320696e206661756369627573206f726369206c756374757320657420756c74726963657320706f737565726520637562696c69612043757261653b2053757370656e646973736520636f6e76616c6c69732073656d2076656c206d617373612066617563696275732c2065676574206c6163696e6961206c616375732074656d706f722e204e756c6c61207175697320756c747269636965732070757275732e2050726f696e20617563746f722072686f6e637573206e69626820636f6e64696d656e74756d206d6f6c6c69732e20416c697175616d20636f6e73657175617420656e696d206174206d65747573206c75637475732c206120656c656966656e6420707572757320656765737461732e20437572616269747572206174206e696268206d657475732e204e616d20626962656e64756d2c206e6571756520617420617563746f72207472697374697175652c206c6f72656d206c696265726f20616c697175657420617263752c206e6f6e20696e74657264756d2074656c6c7573206c65637475732073697420616d65742065726f732e20437261732072686f6e6375732c206d65747573206163206f726e617265206375727375732c20646f6c6f72206a7573746f20756c747269636573206d657475732c20617420756c6c616d636f7270657220766f6c7574706174\"\n );\n }\n}\n\ncontract RLPWriter_writeUint_Test is CommonTest {\n function test_writeUint_zero_succeeds() external {\n assertEq(RLPWriter.writeUint(0x0), hex\"80\");\n }\n\n function test_writeUint_smallint_succeeds() external {\n assertEq(RLPWriter.writeUint(1), hex\"01\");\n }\n\n function test_writeUint_smallint2_succeeds() external {\n assertEq(RLPWriter.writeUint(16), hex\"10\");\n }\n\n function test_writeUint_smallint3_succeeds() external {\n assertEq(RLPWriter.writeUint(79), hex\"4f\");\n }\n\n function test_writeUint_smallint4_succeeds() external {\n assertEq(RLPWriter.writeUint(127), hex\"7f\");\n }\n\n function test_writeUint_mediumint_succeeds() external {\n assertEq(RLPWriter.writeUint(128), hex\"8180\");\n }\n\n function test_writeUint_mediumint2_succeeds() external {\n assertEq(RLPWriter.writeUint(1000), hex\"8203e8\");\n }\n\n function test_writeUint_mediumint3_succeeds() external {\n assertEq(RLPWriter.writeUint(100000), hex\"830186a0\");\n }\n}\n\ncontract RLPWriter_writeList_Test is CommonTest {\n function test_writeList_empty_succeeds() external {\n assertEq(RLPWriter.writeList(new bytes[](0)), hex\"c0\");\n }\n\n function test_writeList_stringList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeString(\"dog\");\n list[1] = RLPWriter.writeString(\"god\");\n list[2] = RLPWriter.writeString(\"cat\");\n\n assertEq(RLPWriter.writeList(list), hex\"cc83646f6783676f6483636174\");\n }\n\n function test_writeList_multiList_succeeds() external {\n bytes[] memory list = new bytes[](3);\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeUint(4);\n\n list[0] = RLPWriter.writeString(\"zw\");\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeUint(1);\n\n assertEq(RLPWriter.writeList(list), hex\"c6827a77c10401\");\n }\n\n function test_writeList_shortListMax1_succeeds() external {\n bytes[] memory list = new bytes[](11);\n list[0] = RLPWriter.writeString(\"asdf\");\n list[1] = RLPWriter.writeString(\"qwer\");\n list[2] = RLPWriter.writeString(\"zxcv\");\n list[3] = RLPWriter.writeString(\"asdf\");\n list[4] = RLPWriter.writeString(\"qwer\");\n list[5] = RLPWriter.writeString(\"zxcv\");\n list[6] = RLPWriter.writeString(\"asdf\");\n list[7] = RLPWriter.writeString(\"qwer\");\n list[8] = RLPWriter.writeString(\"zxcv\");\n list[9] = RLPWriter.writeString(\"asdf\");\n list[10] = RLPWriter.writeString(\"qwer\");\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f784617364668471776572847a78637684617364668471776572847a78637684617364668471776572847a78637684617364668471776572\"\n );\n }\n\n function test_writeList_longlist1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list2);\n list[3] = RLPWriter.writeList(list2);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f840cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_longlist2_succeeds() external {\n bytes[] memory list = new bytes[](32);\n bytes[] memory list2 = new bytes[](3);\n\n list2[0] = RLPWriter.writeString(\"asdf\");\n list2[1] = RLPWriter.writeString(\"qwer\");\n list2[2] = RLPWriter.writeString(\"zxcv\");\n\n for (uint256 i = 0; i < 32; i++) {\n list[i] = RLPWriter.writeList(list2);\n }\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"f90200cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376cf84617364668471776572847a786376\"\n );\n }\n\n function test_writeList_listoflists_succeeds() external {\n // [ [ [], [] ], [] ]\n bytes[] memory list = new bytes[](2);\n bytes[] memory list2 = new bytes[](2);\n\n list2[0] = RLPWriter.writeList(new bytes[](0));\n list2[1] = RLPWriter.writeList(new bytes[](0));\n\n list[0] = RLPWriter.writeList(list2);\n list[1] = RLPWriter.writeList(new bytes[](0));\n\n assertEq(RLPWriter.writeList(list), hex\"c4c2c0c0c0\");\n }\n\n function test_writeList_listoflists2_succeeds() external {\n // [ [], [[]], [ [], [[]] ] ]\n bytes[] memory list = new bytes[](3);\n list[0] = RLPWriter.writeList(new bytes[](0));\n\n bytes[] memory list2 = new bytes[](1);\n list2[0] = RLPWriter.writeList(new bytes[](0));\n\n list[1] = RLPWriter.writeList(list2);\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeList(new bytes[](0));\n list3[1] = RLPWriter.writeList(list2);\n\n list[2] = RLPWriter.writeList(list3);\n\n assertEq(RLPWriter.writeList(list), hex\"c7c0c1c0c3c0c1c0\");\n }\n\n function test_writeList_dictTest1_succeeds() external {\n bytes[] memory list = new bytes[](4);\n\n bytes[] memory list1 = new bytes[](2);\n list1[0] = RLPWriter.writeString(\"key1\");\n list1[1] = RLPWriter.writeString(\"val1\");\n\n bytes[] memory list2 = new bytes[](2);\n list2[0] = RLPWriter.writeString(\"key2\");\n list2[1] = RLPWriter.writeString(\"val2\");\n\n bytes[] memory list3 = new bytes[](2);\n list3[0] = RLPWriter.writeString(\"key3\");\n list3[1] = RLPWriter.writeString(\"val3\");\n\n bytes[] memory list4 = new bytes[](2);\n list4[0] = RLPWriter.writeString(\"key4\");\n list4[1] = RLPWriter.writeString(\"val4\");\n\n list[0] = RLPWriter.writeList(list1);\n list[1] = RLPWriter.writeList(list2);\n list[2] = RLPWriter.writeList(list3);\n list[3] = RLPWriter.writeList(list4);\n\n assertEq(\n RLPWriter.writeList(list),\n hex\"ecca846b6579318476616c31ca846b6579328476616c32ca846b6579338476616c33ca846b6579348476616c34\"\n );\n }\n}\n" - }, - "contracts/test/ResolvedDelegateProxy.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { AddressManager } from \"../legacy/AddressManager.sol\";\nimport { ResolvedDelegateProxy } from \"../legacy/ResolvedDelegateProxy.sol\";\n\ncontract ResolvedDelegateProxy_Test is Test {\n AddressManager internal addressManager;\n SimpleImplementation internal impl;\n SimpleImplementation internal proxy;\n\n function setUp() public {\n // Set up the address manager.\n addressManager = new AddressManager();\n impl = new SimpleImplementation();\n addressManager.setAddress(\"SimpleImplementation\", address(impl));\n\n // Set up the proxy.\n proxy = SimpleImplementation(\n address(new ResolvedDelegateProxy(addressManager, \"SimpleImplementation\"))\n );\n }\n\n // Tests that the proxy properly bubbles up returndata when the delegatecall succeeds.\n function testFuzz_fallback_delegateCallFoo_succeeds(uint256 x) public {\n vm.expectCall(address(impl), abi.encodeWithSelector(impl.foo.selector, x));\n assertEq(proxy.foo(x), x);\n }\n\n // Tests that the proxy properly bubbles up returndata when the delegatecall reverts.\n function test_fallback_delegateCallBar_reverts() public {\n vm.expectRevert(\"SimpleImplementation: revert\");\n vm.expectCall(address(impl), abi.encodeWithSelector(impl.bar.selector));\n proxy.bar();\n }\n\n // Tests that the proxy fallback reverts as expected if the implementation within the\n // address manager is not set.\n function test_fallback_addressManagerNotSet_reverts() public {\n AddressManager am = new AddressManager();\n SimpleImplementation p = SimpleImplementation(\n address(new ResolvedDelegateProxy(am, \"SimpleImplementation\"))\n );\n\n vm.expectRevert(\"ResolvedDelegateProxy: target address must be initialized\");\n p.foo(0);\n }\n}\n\ncontract SimpleImplementation {\n function foo(uint256 _x) public pure returns (uint256) {\n return _x;\n }\n\n function bar() public pure {\n revert(\"SimpleImplementation: revert\");\n }\n}\n" - }, - "contracts/test/ResourceMetering.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract MeterUser is ResourceMetering {\n constructor() {\n initialize();\n }\n\n function initialize() public initializer {\n __ResourceMetering_init();\n }\n\n function resourceConfig() public pure returns (ResourceMetering.ResourceConfig memory) {\n return _resourceConfig();\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return Constants.DEFAULT_RESOURCE_CONFIG();\n }\n\n function use(uint64 _amount) public metered(_amount) {}\n\n function set(\n uint128 _prevBaseFee,\n uint64 _prevBoughtGas,\n uint64 _prevBlockNum\n ) public {\n params = ResourceMetering.ResourceParams({\n prevBaseFee: _prevBaseFee,\n prevBoughtGas: _prevBoughtGas,\n prevBlockNum: _prevBlockNum\n });\n }\n}\n\n/**\n * @title ResourceConfig\n * @notice The tests are based on the default config values. It is expected that\n * the config values used in these tests are ran in production.\n */\ncontract ResourceMetering_Test is Test {\n MeterUser internal meter;\n uint64 initialBlockNum;\n\n function setUp() public {\n meter = new MeterUser();\n initialBlockNum = uint64(block.number);\n }\n\n function test_meter_initialResourceParams_succeeds() external {\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n\n assertEq(prevBaseFee, rcfg.minimumBaseFee);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_updateParamsNoChange_succeeds() external {\n meter.use(0); // equivalent to just updating the base fee and block number\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n meter.use(0);\n (uint128 postBaseFee, uint64 postBoughtGas, uint64 postBlockNum) = meter.params();\n\n assertEq(postBaseFee, prevBaseFee);\n assertEq(postBoughtGas, prevBoughtGas);\n assertEq(postBlockNum, prevBlockNum);\n }\n\n function test_meter_updateOneEmptyBlock_succeeds() external {\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 1);\n }\n\n function test_meter_updateTwoEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 2);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 2);\n }\n\n function test_meter_updateTenEmptyBlocks_succeeds() external {\n vm.roll(initialBlockNum + 10);\n meter.use(0);\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1 gwei);\n assertEq(prevBoughtGas, 0);\n assertEq(prevBlockNum, initialBlockNum + 10);\n }\n\n function test_meter_updateNoGasDelta_succeeds() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint256 target = uint256(rcfg.maxResourceLimit) / uint256(rcfg.elasticityMultiplier);\n meter.use(uint64(target));\n (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();\n\n assertEq(prevBaseFee, 1000000000);\n assertEq(prevBoughtGas, target);\n assertEq(prevBlockNum, initialBlockNum);\n }\n\n function test_meter_useMax_succeeds() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n meter.use(target * elasticityMultiplier);\n\n (, uint64 prevBoughtGas, ) = meter.params();\n assertEq(prevBoughtGas, target * elasticityMultiplier);\n\n vm.roll(initialBlockNum + 1);\n meter.use(0);\n (uint128 postBaseFee, , ) = meter.params();\n assertEq(postBaseFee, 2125000000);\n }\n\n function test_meter_useMoreThanMax_reverts() external {\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n vm.expectRevert(\"ResourceMetering: cannot buy more gas than available gas limit\");\n meter.use(target * elasticityMultiplier + 1);\n }\n\n // Demonstrates that the resource metering arithmetic can tolerate very large gaps between\n // deposits.\n function testFuzz_meter_largeBlockDiff_succeeds(uint64 _amount, uint256 _blockDiff) external {\n // This test fails if the following line is commented out.\n // At 12 seconds per block, this number is effectively unreachable.\n vm.assume(_blockDiff < 433576281058164217753225238677900874458691);\n\n ResourceMetering.ResourceConfig memory rcfg = meter.resourceConfig();\n uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);\n\n vm.assume(_amount < target * elasticityMultiplier);\n vm.roll(initialBlockNum + _blockDiff);\n meter.use(_amount);\n }\n}\n\n/**\n * @title CustomMeterUser\n * @notice A simple wrapper around `ResourceMetering` that allows the initial\n * params to be set in the constructor.\n */\ncontract CustomMeterUser is ResourceMetering {\n uint256 public startGas;\n uint256 public endGas;\n\n constructor(\n uint128 _prevBaseFee,\n uint64 _prevBoughtGas,\n uint64 _prevBlockNum\n ) {\n params = ResourceMetering.ResourceParams({\n prevBaseFee: _prevBaseFee,\n prevBoughtGas: _prevBoughtGas,\n prevBlockNum: _prevBlockNum\n });\n }\n\n function _resourceConfig()\n internal\n pure\n override\n returns (ResourceMetering.ResourceConfig memory)\n {\n return Constants.DEFAULT_RESOURCE_CONFIG();\n }\n\n function use(uint64 _amount) public returns (uint256) {\n uint256 initialGas = gasleft();\n _metered(_amount, initialGas);\n return initialGas - gasleft();\n }\n}\n\n/**\n * @title ArtifactResourceMetering_Test\n * @notice A table test that sets the state of the ResourceParams and then requests\n * various amounts of gas. This test ensures that a wide range of values\n * can safely be used with the `ResourceMetering` contract.\n * It also writes a CSV file to disk that includes useful information\n * about how much gas is used and how expensive it is in USD terms to\n * purchase the deposit gas.\n */\ncontract ArtifactResourceMetering_Test is Test {\n uint128 internal minimumBaseFee;\n uint128 internal maximumBaseFee;\n uint64 internal maxResourceLimit;\n uint64 internal targetResourceLimit;\n\n string internal outfile;\n\n // keccak256(abi.encodeWithSignature(\"Error(string)\", \"ResourceMetering: cannot buy more gas than available gas limit\"))\n bytes32 internal cannotBuyMoreGas =\n 0x84edc668cfd5e050b8999f43ff87a1faaa93e5f935b20bc1dd4d3ff157ccf429;\n // keccak256(abi.encodeWithSignature(\"Panic(uint256)\", 0x11))\n bytes32 internal overflowErr =\n 0x1ca389f2c8264faa4377de9ce8e14d6263ef29c68044a9272d405761bab2db27;\n // keccak256(hex\"\")\n bytes32 internal emptyReturnData =\n 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n\n /**\n * @notice Sets up the tests by getting constants from the ResourceMetering\n * contract.\n */\n function setUp() public {\n vm.roll(1_000_000);\n\n MeterUser base = new MeterUser();\n ResourceMetering.ResourceConfig memory rcfg = base.resourceConfig();\n minimumBaseFee = uint128(rcfg.minimumBaseFee);\n maximumBaseFee = rcfg.maximumBaseFee;\n maxResourceLimit = uint64(rcfg.maxResourceLimit);\n targetResourceLimit = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);\n\n outfile = string.concat(vm.projectRoot(), \"/.resource-metering.csv\");\n try vm.removeFile(outfile) {} catch {}\n }\n\n /**\n * @notice Generate a CSV file. The call to `meter` should be called with at\n * most the L1 block gas limit. Without specifying the amount of\n * gas, it can take very long to execute.\n */\n function test_meter_generateArtifact_succeeds() external {\n vm.writeLine(\n outfile,\n \"prevBaseFee,prevBoughtGas,prevBlockNumDiff,l1BaseFee,requestedGas,gasConsumed,ethPrice,usdCost,success\"\n );\n\n // prevBaseFee value in ResourceParams\n uint128[] memory prevBaseFees = new uint128[](5);\n prevBaseFees[0] = minimumBaseFee;\n prevBaseFees[1] = maximumBaseFee;\n prevBaseFees[2] = uint128(50 gwei);\n prevBaseFees[3] = uint128(100 gwei);\n prevBaseFees[4] = uint128(200 gwei);\n\n // prevBoughtGas value in ResourceParams\n uint64[] memory prevBoughtGases = new uint64[](1);\n prevBoughtGases[0] = uint64(0);\n\n // prevBlockNum diff, simulates blocks with no deposits when non zero\n uint64[] memory prevBlockNumDiffs = new uint64[](2);\n prevBlockNumDiffs[0] = 0;\n prevBlockNumDiffs[1] = 1;\n\n // The amount of L2 gas that a user requests\n uint64[] memory requestedGases = new uint64[](3);\n requestedGases[0] = maxResourceLimit;\n requestedGases[1] = targetResourceLimit;\n requestedGases[2] = uint64(100_000);\n\n // The L1 base fee\n uint256[] memory l1BaseFees = new uint256[](4);\n l1BaseFees[0] = 1 gwei;\n l1BaseFees[1] = 50 gwei;\n l1BaseFees[2] = 75 gwei;\n l1BaseFees[3] = 100 gwei;\n\n // USD price of 1 ether\n uint256[] memory ethPrices = new uint256[](2);\n ethPrices[0] = 1600;\n ethPrices[1] = 3200;\n\n // Iterate over all of the test values and run a test\n for (uint256 i; i < prevBaseFees.length; i++) {\n for (uint256 j; j < prevBoughtGases.length; j++) {\n for (uint256 k; k < prevBlockNumDiffs.length; k++) {\n for (uint256 l; l < requestedGases.length; l++) {\n for (uint256 m; m < l1BaseFees.length; m++) {\n for (uint256 n; n < ethPrices.length; n++) {\n uint256 snapshotId = vm.snapshot();\n\n uint128 prevBaseFee = prevBaseFees[i];\n uint64 prevBoughtGas = prevBoughtGases[j];\n uint64 prevBlockNumDiff = prevBlockNumDiffs[k];\n uint64 requestedGas = requestedGases[l];\n uint256 l1BaseFee = l1BaseFees[m];\n uint256 ethPrice = ethPrices[n];\n string memory result = \"success\";\n\n vm.fee(l1BaseFee);\n\n CustomMeterUser meter = new CustomMeterUser({\n _prevBaseFee: prevBaseFee,\n _prevBoughtGas: prevBoughtGas,\n _prevBlockNum: uint64(block.number)\n });\n\n vm.roll(block.number + prevBlockNumDiff);\n\n // Call the metering code and catch the various\n // types of errors.\n uint256 gasConsumed = 0;\n try meter.use{ gas: 30_000_000 }(requestedGas) returns (\n uint256 _gasConsumed\n ) {\n gasConsumed = _gasConsumed;\n } catch (bytes memory err) {\n bytes32 hash = keccak256(err);\n if (hash == cannotBuyMoreGas) {\n result = \"ResourceMetering: cannot buy more gas than available gas limit\";\n } else if (hash == overflowErr) {\n result = \"arithmetic overflow/underflow\";\n } else if (hash == emptyReturnData) {\n result = \"out of gas\";\n } else {\n result = \"UNKNOWN ERROR\";\n }\n }\n\n // Compute the USD cost of the gas used\n uint256 usdCost = (gasConsumed * l1BaseFee * ethPrice) / 1 ether;\n\n vm.writeLine(\n outfile,\n string.concat(\n vm.toString(prevBaseFee),\n \",\",\n vm.toString(prevBoughtGas),\n \",\",\n vm.toString(prevBlockNumDiff),\n \",\",\n vm.toString(l1BaseFee),\n \",\",\n vm.toString(requestedGas),\n \",\",\n vm.toString(gasConsumed),\n \",\",\n \"$\",\n vm.toString(ethPrice),\n \",\",\n \"$\",\n vm.toString(usdCost),\n \",\",\n result\n )\n );\n\n assertTrue(vm.revertTo(snapshotId));\n }\n }\n }\n }\n }\n }\n }\n}\n" - }, - "contracts/test/SafeCall.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\n\ncontract SafeCall_call_Test is CommonTest {\n function testFuzz_call_succeeds(\n address from,\n address to,\n uint256 gas,\n uint64 value,\n bytes memory data\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles (mainnet)\n assumeNoPrecompiles(to, 1);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n uint256[2] memory balancesBefore = [from.balance, to.balance];\n\n vm.expectCall(to, value, data);\n vm.prank(from);\n bool success = SafeCall.call(to, gas, value, data);\n\n assertTrue(success, \"call not successful\");\n if (from == to) {\n assertEq(from.balance, balancesBefore[0], \"Self-send did not change balance\");\n } else {\n assertEq(from.balance, balancesBefore[0] - value, \"from balance not drained\");\n assertEq(to.balance, balancesBefore[1] + value, \"to balance received\");\n }\n }\n\n function testFuzz_callWithMinGas_hasEnough_succeeds(\n address from,\n address to,\n uint64 minGas,\n uint64 value,\n bytes memory data\n ) external {\n vm.assume(from.balance == 0);\n vm.assume(to.balance == 0);\n // no precompiles (mainnet)\n assumeNoPrecompiles(to, 1);\n // don't call the vm\n vm.assume(to != address(vm));\n vm.assume(from != address(vm));\n // don't call the console\n vm.assume(to != address(0x000000000000000000636F6e736F6c652e6c6f67));\n // don't call the create2 deployer\n vm.assume(to != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));\n\n assertEq(from.balance, 0, \"from balance is 0\");\n vm.deal(from, value);\n assertEq(from.balance, value, \"from balance not dealt\");\n\n // Bound minGas to [0, l1_block_gas_limit]\n minGas = uint64(bound(minGas, 0, 30_000_000));\n\n uint256[2] memory balancesBefore = [from.balance, to.balance];\n\n vm.expectCallMinGas(to, value, minGas, data);\n vm.prank(from);\n bool success = SafeCall.callWithMinGas(to, minGas, value, data);\n\n assertTrue(success, \"call not successful\");\n if (from == to) {\n assertEq(from.balance, balancesBefore[0], \"Self-send did not change balance\");\n } else {\n assertEq(from.balance, balancesBefore[0] - value, \"from balance not drained\");\n assertEq(to.balance, balancesBefore[1] + value, \"to balance received\");\n }\n }\n\n function test_callWithMinGas_noLeakageLow_succeeds() external {\n SimpleSafeCaller caller = new SimpleSafeCaller();\n\n for (uint64 i = 5000; i < 50_000; i++) {\n uint256 snapshot = vm.snapshot();\n\n // 26,071 is the exact amount of gas required to make the safe call\n // successfully.\n if (i < 26_071) {\n assertFalse(caller.makeSafeCall(i, 25_000));\n } else {\n vm.expectCallMinGas(\n address(caller),\n 0,\n 25_000,\n abi.encodeWithSelector(caller.setA.selector, 1)\n );\n assertTrue(caller.makeSafeCall(i, 25_000));\n }\n\n assertTrue(vm.revertTo(snapshot));\n }\n }\n\n function test_callWithMinGas_noLeakageHigh_succeeds() external {\n SimpleSafeCaller caller = new SimpleSafeCaller();\n\n for (uint64 i = 15_200_000; i < 15_300_000; i++) {\n uint256 snapshot = vm.snapshot();\n\n // 15,238,769 is the exact amount of gas required to make the safe call\n // successfully.\n if (i < 15_238_769) {\n assertFalse(caller.makeSafeCall(i, 15_000_000));\n } else {\n vm.expectCallMinGas(\n address(caller),\n 0,\n 15_000_000,\n abi.encodeWithSelector(caller.setA.selector, 1)\n );\n assertTrue(caller.makeSafeCall(i, 15_000_000));\n }\n\n assertTrue(vm.revertTo(snapshot));\n }\n }\n}\n\ncontract SimpleSafeCaller {\n uint256 public a;\n\n function makeSafeCall(uint64 gas, uint64 minGas) external returns (bool) {\n return\n SafeCall.call(\n address(this),\n gas,\n 0,\n abi.encodeWithSelector(this.makeSafeCallMinGas.selector, minGas)\n );\n }\n\n function makeSafeCallMinGas(uint64 minGas) external returns (bool) {\n return\n SafeCall.callWithMinGas(\n address(this),\n minGas,\n 0,\n abi.encodeWithSelector(this.setA.selector, 1)\n );\n }\n\n function setA(uint256 _a) external {\n a = _a;\n }\n}\n" - }, - "contracts/test/Semver.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { Proxy } from \"../universal/Proxy.sol\";\n\n/**\n * @notice Test the Semver contract that is used for semantic versioning\n * of various contracts.\n */\ncontract Semver_Test is CommonTest {\n /**\n * @notice Global semver contract deployed in setUp. This is used in\n * the test cases.\n */\n Semver semver;\n\n /**\n * @notice Deploy a Semver contract\n */\n function setUp() public virtual override {\n semver = new Semver(7, 8, 0);\n }\n\n /**\n * @notice Test the version getter\n */\n function test_version_succeeds() external {\n assertEq(semver.version(), \"7.8.0\");\n }\n\n /**\n * @notice Since the versions are all immutable, they should\n * be able to be accessed from behind a proxy without needing\n * to initialize the contract.\n */\n function test_behindProxy_succeeds() external {\n Proxy proxy = new Proxy(alice);\n vm.prank(alice);\n proxy.upgradeTo(address(semver));\n\n assertEq(Semver(address(proxy)).version(), \"7.8.0\");\n }\n}\n" - }, - "contracts/test/SequencerFeeVault.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Bridge_Initializer } from \"./CommonTest.t.sol\";\n\nimport { SequencerFeeVault } from \"../L2/SequencerFeeVault.sol\";\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\ncontract SequencerFeeVault_Test is Bridge_Initializer {\n SequencerFeeVault vault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET));\n address constant recipient = address(256);\n\n event Withdrawal(uint256 value, address to, address from);\n\n function setUp() public override {\n super.setUp();\n vm.etch(Predeploys.SEQUENCER_FEE_WALLET, address(new SequencerFeeVault(recipient)).code);\n vm.label(Predeploys.SEQUENCER_FEE_WALLET, \"SequencerFeeVault\");\n }\n\n function test_minWithdrawalAmount_succeeds() external {\n assertEq(vault.MIN_WITHDRAWAL_AMOUNT(), 10 ether);\n }\n\n function test_constructor_succeeds() external {\n assertEq(vault.l1FeeWallet(), recipient);\n }\n\n function test_receive_succeeds() external {\n uint256 balance = address(vault).balance;\n\n vm.prank(alice);\n (bool success, ) = address(vault).call{ value: 100 }(hex\"\");\n\n assertEq(success, true);\n assertEq(address(vault).balance, balance + 100);\n }\n\n function test_withdraw_notEnough_reverts() external {\n assert(address(vault).balance < vault.MIN_WITHDRAWAL_AMOUNT());\n\n vm.expectRevert(\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n vault.withdraw();\n }\n\n function test_withdraw_succeeds() external {\n uint256 amount = vault.MIN_WITHDRAWAL_AMOUNT() + 1;\n vm.deal(address(vault), amount);\n\n // No ether has been withdrawn yet\n assertEq(vault.totalProcessed(), 0);\n\n vm.expectEmit(true, true, true, true, address(Predeploys.SEQUENCER_FEE_WALLET));\n emit Withdrawal(address(vault).balance, vault.RECIPIENT(), address(this));\n\n // The entire vault's balance is withdrawn\n vm.expectCall(\n Predeploys.L2_STANDARD_BRIDGE,\n address(vault).balance,\n abi.encodeWithSelector(\n StandardBridge.bridgeETHTo.selector,\n vault.l1FeeWallet(),\n 35_000,\n bytes(\"\")\n )\n );\n\n vault.withdraw();\n\n // The withdrawal was successful\n assertEq(vault.totalProcessed(), amount);\n }\n}\n" - }, - "contracts/test/StandardBridge.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { StandardBridge } from \"../universal/StandardBridge.sol\";\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport {\n OptimismMintableERC20,\n ILegacyMintableERC20\n} from \"../universal/OptimismMintableERC20.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/**\n * @title StandardBridgeTester\n * @notice Simple wrapper around the StandardBridge contract that exposes\n * internal functions so they can be more easily tested directly.\n */\ncontract StandardBridgeTester is StandardBridge {\n constructor(address payable _messenger, address payable _otherBridge)\n StandardBridge(_messenger, _otherBridge)\n {}\n\n function isOptimismMintableERC20(address _token) external view returns (bool) {\n return _isOptimismMintableERC20(_token);\n }\n\n function isCorrectTokenPair(address _mintableToken, address _otherToken)\n external\n view\n returns (bool)\n {\n return _isCorrectTokenPair(_mintableToken, _otherToken);\n }\n\n receive() external payable override {}\n}\n\n/**\n * @title LegacyMintable\n * @notice Simple implementation of the legacy OptimismMintableERC20.\n */\ncontract LegacyMintable is ERC20, ILegacyMintableERC20 {\n constructor(string memory _name, string memory _ticker) ERC20(_name, _ticker) {}\n\n function l1Token() external pure returns (address) {\n return address(0);\n }\n\n function mint(address _to, uint256 _amount) external pure {}\n\n function burn(address _from, uint256 _amount) external pure {}\n\n /**\n * @notice Implements ERC165. This implementation should not be changed as\n * it is how the actual legacy optimism mintable token does the\n * check. Allows for testing against code that is has been deployed,\n * assuming different compiler version is no problem.\n */\n function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {\n bytes4 firstSupportedInterface = bytes4(keccak256(\"supportsInterface(bytes4)\")); // ERC165\n bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^\n ILegacyMintableERC20.mint.selector ^\n ILegacyMintableERC20.burn.selector;\n return _interfaceId == firstSupportedInterface || _interfaceId == secondSupportedInterface;\n }\n}\n\n/**\n * @title StandardBridge_Stateless_Test\n * @notice Tests internal functions that require no existing state or contract\n * interactions with the messenger.\n */\ncontract StandardBridge_Stateless_Test is CommonTest {\n StandardBridgeTester internal bridge;\n OptimismMintableERC20 internal mintable;\n ERC20 internal erc20;\n LegacyMintable internal legacy;\n\n function setUp() public override {\n super.setUp();\n\n bridge = new StandardBridgeTester({\n _messenger: payable(address(0)),\n _otherBridge: payable(address(0))\n });\n\n mintable = new OptimismMintableERC20({\n _bridge: address(0),\n _remoteToken: address(0),\n _name: \"Stonks\",\n _symbol: \"STONK\"\n });\n\n erc20 = new ERC20(\"Altcoin\", \"ALT\");\n legacy = new LegacyMintable(\"Legacy\", \"LEG\");\n }\n\n /**\n * @notice Test coverage for identifying OptimismMintableERC20 tokens.\n * This function should return true for both modern and legacy\n * OptimismMintableERC20 tokens and false for any accounts that\n * do not implement the interface.\n */\n function test_isOptimismMintableERC20_succeeds() external {\n // Both the modern and legacy mintable tokens should return true\n assertTrue(bridge.isOptimismMintableERC20(address(mintable)));\n assertTrue(bridge.isOptimismMintableERC20(address(legacy)));\n // A regular ERC20 should return false\n assertFalse(bridge.isOptimismMintableERC20(address(erc20)));\n // Non existent contracts should return false and not revert\n assertEq(address(0x20).code.length, 0);\n assertFalse(bridge.isOptimismMintableERC20(address(0x20)));\n }\n\n /**\n * @notice Test coverage of isCorrectTokenPair under different types of\n * tokens.\n */\n function test_isCorrectTokenPair_succeeds() external {\n // Modern + known to be correct remote token\n assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.remoteToken()));\n // Modern + known to be correct l1Token (legacy interface)\n assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.l1Token()));\n // Modern + known to be incorrect remote token\n assertTrue(mintable.remoteToken() != address(0x20));\n assertFalse(bridge.isCorrectTokenPair(address(mintable), address(0x20)));\n // Legacy + known to be correct l1Token\n assertTrue(bridge.isCorrectTokenPair(address(legacy), legacy.l1Token()));\n // Legacy + known to be incorrect l1Token\n assertTrue(legacy.l1Token() != address(0x20));\n assertFalse(bridge.isCorrectTokenPair(address(legacy), address(0x20)));\n // A token that doesn't support either modern or legacy interface\n // will revert\n vm.expectRevert();\n bridge.isCorrectTokenPair(address(erc20), address(1));\n }\n}\n" - }, - "contracts/test/SystemConfig.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CommonTest } from \"./CommonTest.t.sol\";\nimport { SystemConfig } from \"../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\ncontract SystemConfig_Init is CommonTest {\n SystemConfig sysConf;\n\n function setUp() public virtual override {\n super.setUp();\n\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n\n sysConf = new SystemConfig({\n _owner: alice,\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(1),\n _config: config\n });\n }\n}\n\ncontract SystemConfig_Initialize_TestFail is SystemConfig_Init {\n function test_initialize_lowGasLimit_reverts() external {\n uint64 minimumGasLimit = sysConf.minimumGasLimit();\n\n ResourceMetering.ResourceConfig memory cfg = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n\n vm.expectRevert(\"SystemConfig: gas limit too low\");\n new SystemConfig({\n _owner: alice,\n _overhead: 0,\n _scalar: 0,\n _batcherHash: bytes32(hex\"\"),\n _gasLimit: minimumGasLimit - 1,\n _unsafeBlockSigner: address(1),\n _config: cfg\n });\n }\n}\n\ncontract SystemConfig_Setters_TestFail is SystemConfig_Init {\n function test_setBatcherHash_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setBatcherHash(bytes32(hex\"\"));\n }\n\n function test_setGasConfig_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasConfig(0, 0);\n }\n\n function test_setGasLimit_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setGasLimit(0);\n }\n\n function test_setUnsafeBlockSigner_notOwner_reverts() external {\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setUnsafeBlockSigner(address(0x20));\n }\n\n function test_setResourceConfig_notOwner_reverts() external {\n ResourceMetering.ResourceConfig memory config = Constants.DEFAULT_RESOURCE_CONFIG();\n vm.expectRevert(\"Ownable: caller is not the owner\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_badMinMax_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 2 gwei,\n maximumBaseFee: 1 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: min base fee must be less than max base\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_zeroDenominator_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 0,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: denominator cannot be 0\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_lowGasLimit_reverts() external {\n uint64 gasLimit = sysConf.gasLimit();\n\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: uint32(gasLimit),\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: uint32(gasLimit),\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: gas limit too low\");\n sysConf.setResourceConfig(config);\n }\n\n function test_setResourceConfig_badPrecision_reverts() external {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 11,\n baseFeeMaxChangeDenominator: 8,\n systemTxMaxGas: 1_000_000,\n minimumBaseFee: 1 gwei,\n maximumBaseFee: 2 gwei\n });\n vm.prank(sysConf.owner());\n vm.expectRevert(\"SystemConfig: precision loss with target resource limit\");\n sysConf.setResourceConfig(config);\n }\n}\n\ncontract SystemConfig_Setters_Test is SystemConfig_Init {\n event ConfigUpdate(\n uint256 indexed version,\n SystemConfig.UpdateType indexed updateType,\n bytes data\n );\n\n function testFuzz_setBatcherHash_succeeds(bytes32 newBatcherHash) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash));\n\n vm.prank(sysConf.owner());\n sysConf.setBatcherHash(newBatcherHash);\n assertEq(sysConf.batcherHash(), newBatcherHash);\n }\n\n function testFuzz_setGasConfig_succeeds(uint256 newOverhead, uint256 newScalar) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.GAS_CONFIG,\n abi.encode(newOverhead, newScalar)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setGasConfig(newOverhead, newScalar);\n assertEq(sysConf.overhead(), newOverhead);\n assertEq(sysConf.scalar(), newScalar);\n }\n\n function testFuzz_setGasLimit_succeeds(uint64 newGasLimit) external {\n uint64 minimumGasLimit = sysConf.minimumGasLimit();\n newGasLimit = uint64(\n bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(type(uint64).max))\n );\n\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit));\n\n vm.prank(sysConf.owner());\n sysConf.setGasLimit(newGasLimit);\n assertEq(sysConf.gasLimit(), newGasLimit);\n }\n\n function testFuzz_setUnsafeBlockSigner_succeeds(address newUnsafeSigner) external {\n vm.expectEmit(true, true, true, true);\n emit ConfigUpdate(\n 0,\n SystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER,\n abi.encode(newUnsafeSigner)\n );\n\n vm.prank(sysConf.owner());\n sysConf.setUnsafeBlockSigner(newUnsafeSigner);\n assertEq(sysConf.unsafeBlockSigner(), newUnsafeSigner);\n }\n}\n" - }, - "contracts/test/TransferOnion.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { TransferOnion } from \"../periphery/TransferOnion.sol\";\n\n/**\n * @title TransferOnionTest\n * @notice Test coverage of TransferOnion\n */\ncontract TransferOnionTest is Test {\n /**\n * @notice TransferOnion\n */\n TransferOnion internal onion;\n\n /**\n * @notice token constructor arg\n */\n address internal _token;\n\n /**\n * @notice sender constructor arg\n */\n address internal _sender;\n\n /**\n * @notice Sets up addresses, deploys contracts and funds the owner.\n */\n function setUp() public {\n ERC20 token = new ERC20(\"Token\", \"TKN\");\n _token = address(token);\n _sender = makeAddr(\"sender\");\n }\n\n /**\n * @notice Deploy the TransferOnion with a dummy shell\n */\n function _deploy() public {\n _deploy(bytes32(0));\n }\n\n /**\n * @notice Deploy the TransferOnion with a specific shell\n */\n function _deploy(bytes32 _shell) public {\n onion = new TransferOnion({ _token: ERC20(_token), _sender: _sender, _shell: _shell });\n }\n\n /**\n * @notice Build the onion data\n */\n function _onionize(TransferOnion.Layer[] memory _layers)\n public\n pure\n returns (bytes32, TransferOnion.Layer[] memory)\n {\n uint256 length = _layers.length;\n bytes32 hash = bytes32(0);\n for (uint256 i; i < length; i++) {\n TransferOnion.Layer memory layer = _layers[i];\n _layers[i].shell = hash;\n hash = keccak256(abi.encode(layer.recipient, layer.amount, hash));\n }\n return (hash, _layers);\n }\n\n /**\n * @notice The constructor sets the variables as expected\n */\n function test_constructor_succeeds() external {\n _deploy();\n\n assertEq(address(onion.TOKEN()), _token);\n assertEq(onion.SENDER(), _sender);\n assertEq(onion.shell(), bytes32(0));\n }\n\n /**\n * @notice unwrap\n */\n function test_unwrap_succeeds() external {\n // Commit to transferring tiny amounts of tokens\n TransferOnion.Layer[] memory _layers = new TransferOnion.Layer[](2);\n _layers[0] = TransferOnion.Layer(address(1), 1, bytes32(0));\n _layers[1] = TransferOnion.Layer(address(2), 2, bytes32(0));\n\n // Build the onion shell\n (bytes32 shell, TransferOnion.Layer[] memory layers) = _onionize(_layers);\n _deploy(shell);\n\n assertEq(onion.shell(), shell);\n\n address token = address(onion.TOKEN());\n address sender = onion.SENDER();\n\n // give 3 units of token to sender\n deal(token, onion.SENDER(), 3);\n vm.prank(sender);\n ERC20(token).approve(address(onion), 3);\n\n // To build the inputs, to `peel`, need to reverse the list\n TransferOnion.Layer[] memory inputs = new TransferOnion.Layer[](2);\n int256 length = int256(layers.length);\n for (int256 i = length - 1; i >= 0; i--) {\n uint256 ui = uint256(i);\n uint256 revidx = uint256(length) - ui - 1;\n TransferOnion.Layer memory layer = layers[ui];\n inputs[revidx] = layer;\n }\n\n // The accounts have no balance\n assertEq(ERC20(_token).balanceOf(address(1)), 0);\n assertEq(ERC20(_token).balanceOf(address(2)), 0);\n\n onion.peel(inputs);\n\n // Now the accounts have the expected balance\n assertEq(ERC20(_token).balanceOf(address(1)), 1);\n assertEq(ERC20(_token).balanceOf(address(2)), 2);\n }\n}\n" - }, - "contracts/test/invariants/CrossDomainMessenger.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { StdUtils } from \"forge-std/StdUtils.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport { OptimismPortal } from \"../../L1/OptimismPortal.sol\";\nimport { L1CrossDomainMessenger } from \"../../L1/L1CrossDomainMessenger.sol\";\nimport { Messenger_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\nimport { Predeploys } from \"../../libraries/Predeploys.sol\";\nimport { Encoding } from \"../../libraries/Encoding.sol\";\nimport { Hashing } from \"../../libraries/Hashing.sol\";\n\ncontract RelayActor is StdUtils {\n // Storage slot of the l2Sender\n uint256 constant senderSlotIndex = 50;\n\n uint256 public numHashes;\n bytes32[] public hashes;\n bool public reverted = false;\n\n OptimismPortal op;\n L1CrossDomainMessenger xdm;\n Vm vm;\n\n constructor(\n OptimismPortal _op,\n L1CrossDomainMessenger _xdm,\n Vm _vm\n ) {\n op = _op;\n xdm = _xdm;\n vm = _vm;\n }\n\n /**\n * Relays a message to the `L1CrossDomainMessenger` with a random `version`, `_minGasLimit`\n * and `_message`.\n */\n function relay(\n uint16 _version,\n uint32 _minGasLimit,\n bytes memory _message\n ) external {\n address target = address(0x04); // ID precompile\n address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;\n\n // set the value of op.l2Sender() to be the L2 Cross Domain Messenger.\n vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));\n\n // Restrict `_minGasLimit` to a number in the range of the block gas limit.\n _minGasLimit = uint32(bound(_minGasLimit, 0, block.gaslimit));\n\n // Restrict version to the range of [0, 1]\n _version = _version % 2;\n\n // Compute the cross domain message hash and store it in `hashes`.\n // The `relayMessage` function will always encode the message as a version 1\n // message after checking that the V0 hash has not already been relayed.\n bytes32 _hash = Hashing.hashCrossDomainMessageV1(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n 0, // value\n _minGasLimit,\n _message\n );\n\n // Act as the optimism portal and call `relayMessage` on the `L1CrossDomainMessenger` with\n // the outer min gas limit.\n vm.startPrank(address(op));\n vm.expectCall(target, _message);\n try\n xdm.relayMessage{ gas: xdm.baseGas(_message, _minGasLimit) }(\n Encoding.encodeVersionedNonce(0, _version),\n sender,\n target,\n 0, // value\n _minGasLimit,\n _message\n )\n {} catch {\n // If any of these calls revert, set `reverted` to true to fail the invariant test.\n // NOTE: This is to get around forge's invariant fuzzer ignoring reverted calls\n // to this function.\n reverted = true;\n }\n vm.stopPrank();\n\n hashes.push(_hash);\n numHashes += 1;\n }\n}\n\ncontract XDM_MinGasLimits is Messenger_Initializer {\n RelayActor actor;\n\n function setUp() public virtual override {\n // Set up the `L1CrossDomainMessenger` and `OptimismPortal` contracts.\n super.setUp();\n\n // Deploy a relay actor\n actor = new RelayActor(op, L1Messenger, vm);\n\n // Target the `RelayActor` contract\n targetContract(address(actor));\n\n // Target the actor's `relay` function\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = actor.relay.selector;\n targetSelector(FuzzSelector({ addr: address(actor), selectors: selectors }));\n }\n\n /**\n * @custom:invariant A call to `relayMessage` should never revert if at least the proper minimum\n * gas limits are supplied.\n *\n * There are two minimum gas limits here:\n *\n * - The outer min gas limit is for the call from the `OptimismPortal` to the\n * `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function\n * with the `message` and inner limit.\n *\n * - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target\n * contract.\n */\n function invariant_minGasLimits() public {\n uint256 length = actor.numHashes();\n for (uint256 i = 0; i < length; ++i) {\n bytes32 hash = actor.hashes(i);\n // the message hash is in the successfulMessages mapping\n assertTrue(L1Messenger.successfulMessages(hash));\n // it is not in the received messages mapping\n assertFalse(L1Messenger.failedMessages(hash));\n }\n assertFalse(actor.reverted());\n }\n}\n" - }, - "contracts/test/invariants/L2OutputOracle.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { L2OutputOracle_Initializer } from \"../CommonTest.t.sol\";\nimport { L2OutputOracle } from \"../../L1/L2OutputOracle.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\n\ncontract L2OutputOracle_Proposer {\n L2OutputOracle internal oracle;\n Vm internal vm;\n\n constructor(L2OutputOracle _oracle, Vm _vm) {\n oracle = _oracle;\n vm = _vm;\n }\n\n /**\n * @dev Allows the actor to propose an L2 output to the `L2OutputOracle`\n */\n function proposeL2Output(\n bytes32 _outputRoot,\n uint256 _l2BlockNumber,\n bytes32 _l1BlockHash,\n uint256 _l1BlockNumber\n ) external {\n // Act as the proposer and propose a new output.\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _l2BlockNumber, _l1BlockHash, _l1BlockNumber);\n }\n}\n\ncontract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is L2OutputOracle_Initializer {\n L2OutputOracle_Proposer internal actor;\n\n function setUp() public override {\n super.setUp();\n\n // Create a proposer actor.\n actor = new L2OutputOracle_Proposer(oracle, vm);\n\n // Set the target contract to the proposer actor.\n targetContract(address(actor));\n\n // Set the target selector for `proposeL2Output`\n // `proposeL2Output` is the only function we care about, as it is the only function\n // that can modify the `l2Outputs` array in the oracle.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = actor.proposeL2Output.selector;\n FuzzSelector memory selector = FuzzSelector({ addr: address(actor), selectors: selectors });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The block number of the output root proposals should monotonically\n * increase.\n *\n * When a new output is submitted, it should never be allowed to correspond to a block\n * number that is less than the current output.\n */\n function invariant_monotonicBlockNumIncrease() external {\n // Assert that the block number of proposals must monotonically increase.\n assertTrue(oracle.nextBlockNumber() >= oracle.latestBlockNumber());\n }\n}\n" - }, - "contracts/test/invariants/OptimismPortal.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Portal_Initializer } from \"../CommonTest.t.sol\";\nimport { Types } from \"../../libraries/Types.sol\";\n\ncontract OptimismPortal_Invariant_Harness is Portal_Initializer {\n // Reusable default values for a test withdrawal\n Types.WithdrawalTransaction _defaultTx;\n\n uint256 _proposedOutputIndex;\n uint256 _proposedBlockNumber;\n bytes32 _stateRoot;\n bytes32 _storageRoot;\n bytes32 _outputRoot;\n bytes32 _withdrawalHash;\n bytes[] _withdrawalProof;\n Types.OutputRootProof internal _outputRootProof;\n\n function setUp() public virtual override {\n super.setUp();\n\n _defaultTx = Types.WithdrawalTransaction({\n nonce: 0,\n sender: alice,\n target: bob,\n value: 100,\n gasLimit: 100_000,\n data: hex\"\"\n });\n // Get withdrawal proof data we can use for testing.\n (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = ffi\n .getProveWithdrawalTransactionInputs(_defaultTx);\n\n // Setup a dummy output root proof for reuse.\n _outputRootProof = Types.OutputRootProof({\n version: bytes32(uint256(0)),\n stateRoot: _stateRoot,\n messagePasserStorageRoot: _storageRoot,\n latestBlockhash: bytes32(uint256(0))\n });\n _proposedBlockNumber = oracle.nextBlockNumber();\n _proposedOutputIndex = oracle.nextOutputIndex();\n\n // Configure the oracle to return the output root we've prepared.\n vm.warp(oracle.computeL2Timestamp(_proposedBlockNumber) + 1);\n vm.prank(oracle.PROPOSER());\n oracle.proposeL2Output(_outputRoot, _proposedBlockNumber, 0, 0);\n\n // Warp beyond the finalization period for the block we've proposed.\n vm.warp(\n oracle.getL2Output(_proposedOutputIndex).timestamp +\n oracle.FINALIZATION_PERIOD_SECONDS() +\n 1\n );\n // Fund the portal so that we can withdraw ETH.\n vm.deal(address(op), 0xFFFFFFFF);\n }\n}\n\ncontract OptimismPortal_CannotTimeTravel is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the finalization\n * period has not elapsed.\n *\n * A withdrawal that has been proven should not be able to be finalized until after\n * the finalization period has elapsed.\n */\n function invariant_cannotFinalizeBeforePeriodHasPassed() external {\n vm.expectRevert(\"OptimismPortal: proven withdrawal finalization period has not elapsed\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CannotFinalizeTwice is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Finalize the withdrawal transaction.\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal\n * has already been finalized.\n *\n * Ensures that there is no chain of calls that can be made that allows a withdrawal\n * to be finalized twice.\n */\n function invariant_cannotFinalizeTwice() external {\n vm.expectRevert(\"OptimismPortal: withdrawal has already been finalized\");\n op.finalizeWithdrawalTransaction(_defaultTx);\n }\n}\n\ncontract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal_Invariant_Harness {\n function setUp() public override {\n super.setUp();\n\n // Prove the withdrawal transaction\n op.proveWithdrawalTransaction(\n _defaultTx,\n _proposedOutputIndex,\n _outputRootProof,\n _withdrawalProof\n );\n\n // Warp past the finalization period.\n vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS() + 1);\n\n // Set the target contract to the portal proxy\n targetContract(address(op));\n // Exclude the proxy multisig from the senders so that the proxy cannot be upgraded\n excludeSender(address(multisig));\n }\n\n /**\n * @custom:invariant A withdrawal should **always** be able to be finalized\n * `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.\n *\n * This invariant asserts that there is no chain of calls that can be made that\n * will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS`\n * after it was successfully proven.\n */\n function invariant_canAlwaysFinalize() external {\n uint256 bobBalanceBefore = address(bob).balance;\n\n op.finalizeWithdrawalTransaction(_defaultTx);\n\n assertEq(address(bob).balance, bobBalanceBefore + _defaultTx.value);\n }\n}\n" - }, - "contracts/test/invariants/SafeCall.t.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { StdUtils } from \"forge-std/StdUtils.sol\";\nimport { Vm } from \"forge-std/Vm.sol\";\nimport { SafeCall } from \"../../libraries/SafeCall.sol\";\n\ncontract SafeCall_Succeeds_Invariants is Test {\n SafeCaller_Actor actor;\n\n function setUp() public {\n // Create a new safe caller actor.\n actor = new SafeCaller_Actor(vm, false);\n\n // Set the caller to this contract\n targetSender(address(this));\n\n // Target the safe caller actor.\n targetContract(address(actor));\n }\n\n /**\n * @custom:invariant If `callWithMinGas` performs a call, then it must always\n * provide at least the specified minimum gas limit to the subcontext.\n *\n * If the check for remaining gas in `SafeCall.callWithMinGas` passes, the\n * subcontext of the call below it must be provided at least `minGas` gas.\n */\n function invariant_callWithMinGas_alwaysForwardsMinGas_succeeds() public {\n assertEq(actor.numCalls(), 0, \"no failed calls allowed\");\n }\n\n function performSafeCallMinGas(uint64 minGas) external {\n SafeCall.callWithMinGas(address(0), minGas, 0, hex\"\");\n }\n}\n\ncontract SafeCall_Fails_Invariants is Test {\n SafeCaller_Actor actor;\n\n function setUp() public {\n // Create a new safe caller actor.\n actor = new SafeCaller_Actor(vm, true);\n\n // Set the caller to this contract\n targetSender(address(this));\n\n // Target the safe caller actor.\n targetContract(address(actor));\n }\n\n /**\n * @custom:invariant `callWithMinGas` reverts if there is not enough gas to pass\n * to the subcontext.\n *\n * If there is not enough gas in the callframe to ensure that `callWithMinGas`\n * can provide the specified minimum gas limit to the subcontext of the call,\n * then `callWithMinGas` must revert.\n */\n function invariant_callWithMinGas_neverForwardsMinGas_reverts() public {\n assertEq(actor.numCalls(), 0, \"no successful calls allowed\");\n }\n\n function performSafeCallMinGas(uint64 minGas) external {\n SafeCall.callWithMinGas(address(0), minGas, 0, hex\"\");\n }\n}\n\ncontract SafeCaller_Actor is StdUtils {\n bool internal immutable FAILS;\n\n Vm internal vm;\n uint256 public numCalls;\n\n constructor(Vm _vm, bool _fails) {\n vm = _vm;\n FAILS = _fails;\n }\n\n function performSafeCallMinGas(uint64 gas, uint64 minGas) external {\n if (FAILS) {\n // Bound the minimum gas amount to [2500, type(uint48).max]\n minGas = uint64(bound(minGas, 2500, type(uint48).max));\n // Bound the gas passed to [minGas, (((minGas + 200) * 64) / 63)]\n gas = uint64(bound(gas, minGas, (((minGas + 200) * 64) / 63)));\n } else {\n // Bound the minimum gas amount to [2500, type(uint48).max]\n minGas = uint64(bound(minGas, 2500, type(uint48).max));\n // Bound the gas passed to [(((minGas + 200) * 64) / 63) + 500, type(uint64).max]\n gas = uint64(bound(gas, (((minGas + 200) * 64) / 63) + 500, type(uint64).max));\n }\n\n vm.expectCallMinGas(address(0x00), 0, minGas, hex\"\");\n bool success = SafeCall.call(\n msg.sender,\n gas,\n 0,\n abi.encodeWithSelector(0x2ae57a41, minGas)\n );\n\n if (success && FAILS) numCalls++;\n if (!FAILS && !success) numCalls++;\n }\n}\n" - }, - "contracts/test/invariants/SystemConfig.t.sol": { - "content": "pragma solidity 0.8.15;\n\nimport { Test } from \"forge-std/Test.sol\";\nimport { SystemConfig } from \"../../L1/SystemConfig.sol\";\nimport { ResourceMetering } from \"../../L1/ResourceMetering.sol\";\nimport { Constants } from \"../../libraries/Constants.sol\";\n\ncontract SystemConfig_GasLimitLowerBound_Invariant is Test {\n SystemConfig public config;\n\n function setUp() public {\n ResourceMetering.ResourceConfig memory cfg = Constants.DEFAULT_RESOURCE_CONFIG();\n\n config = new SystemConfig({\n _owner: address(0xbeef),\n _overhead: 2100,\n _scalar: 1000000,\n _batcherHash: bytes32(hex\"abcd\"),\n _gasLimit: 30_000_000,\n _unsafeBlockSigner: address(1),\n _config: cfg\n });\n\n // Set the target contract to the `config`\n targetContract(address(config));\n // Set the target sender to the `config`'s owner (0xbeef)\n targetSender(address(0xbeef));\n // Set the target selector for `setGasLimit`\n // `setGasLimit` is the only function we care about, as it is the only function\n // that can modify the gas limit within the SystemConfig.\n bytes4[] memory selectors = new bytes4[](1);\n selectors[0] = config.setGasLimit.selector;\n FuzzSelector memory selector = FuzzSelector({\n addr: address(config),\n selectors: selectors\n });\n targetSelector(selector);\n }\n\n /**\n * @custom:invariant The gas limit of the `SystemConfig` contract can never be lower\n * than the hard-coded lower bound.\n */\n function invariant_gasLimitLowerBound() external {\n assertTrue(config.gasLimit() >= config.minimumGasLimit());\n }\n}\n" - }, - "contracts/universal/CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\n/**\n * @custom:legacy\n * @title CrossDomainMessengerLegacySpacer0\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 CrossDomainMessengerLegacySpacer0 {\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:legacy\n * @title CrossDomainMessengerLegacySpacer1\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\n * PausableUpgradable and OwnableUpgradeable variables used to exist. Must be\n * the third contract in the inheritance tree of the CrossDomainMessenger.\n */\ncontract CrossDomainMessengerLegacySpacer1 {\n /**\n * @custom:legacy\n * @custom:spacer __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * ContextUpgradable via OwnableUpgradeable.\n *\n */\n uint256[50] private spacer_1_0_1600;\n\n /**\n * @custom:legacy\n * @custom:spacer _owner\n * @notice Spacer for backwards compatibility.\n * Come from OpenZeppelin OwnableUpgradeable.\n */\n address private spacer_51_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * ContextUpgradable via PausableUpgradable.\n */\n uint256[49] private spacer_52_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer _paused\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n bool private spacer_101_0_1;\n\n /**\n * @custom:legacy\n * @custom:spacer __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n uint256[49] private spacer_102_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer ReentrancyGuardUpgradeable's `_status` field.\n * @notice Spacer for backwards compatibility\n */\n uint256 private spacer_151_0_32;\n\n /**\n * @custom:spacer ReentrancyGuardUpgradeable\n * @notice Spacer for backwards compatibility\n */\n uint256[49] private __gap_reentrancy_guard;\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/**\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 *\n * Any changes to this contract MUST result in a semver bump for contracts that inherit it.\n */\nabstract contract CrossDomainMessenger is\n CrossDomainMessengerLegacySpacer0,\n Initializable,\n CrossDomainMessengerLegacySpacer1\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 uint64 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 uint64 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 uint64 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 uint64 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\n\n /**\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\n */\n address public immutable OTHER_MESSENGER;\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 a boolean if and only if the message has failed to be\n * executed at least once. A message will not be present in this mapping if it\n * successfully executed on the first attempt.\n */\n mapping(bytes32 => bool) public failedMessages;\n\n /**\n * @notice A mapping of hashes to reentrancy locks.\n */\n mapping(bytes32 => bool) internal reentrancyLocks;\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[41] 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 OTHER_MESSENGER = _otherMessenger;\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 OTHER_MESSENGER,\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 {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n require(\n version < 2,\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // If the message is version 0, then it's a migrated legacy withdrawal. We therefore need\n // to check that the legacy version of the message has not already been relayed.\n if (version == 0) {\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _nonce);\n require(\n successfulMessages[oldHash] == false,\n \"CrossDomainMessenger: legacy withdrawal already relayed\"\n );\n }\n\n // We use the v1 message hash as the unique identifier for the message because it commits\n // to the value and minimum gas limit of the message.\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _minGasLimit,\n _message\n );\n\n // Check if the reentrancy lock for the `versionedHash` is already set.\n if (reentrancyLocks[versionedHash]) {\n revert(\"ReentrancyGuard: reentrant call\");\n }\n // Trigger the reentrancy lock for `versionedHash`\n reentrancyLocks[versionedHash] = true;\n\n if (_isOtherMessenger()) {\n // These properties should always hold when the message is first submitted (as\n // opposed to being replayed).\n assert(msg.value == _value);\n assert(!failedMessages[versionedHash]);\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 failedMessages[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 xDomainMsgSender = _sender;\n bool success = SafeCall.callWithMinGas(_target, _minGasLimit, _value, _message);\n xDomainMsgSender = Constants.DEFAULT_L2_SENDER;\n\n if (success) {\n successfulMessages[versionedHash] = true;\n emit RelayedMessage(versionedHash);\n } else {\n failedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n\n // Revert in this case if the transaction was triggered by the estimation address. This\n // should only be possible during gas estimation or we have bigger problems. Reverting\n // here will make the behavior of gas estimation change such that the gas limit\n // computed will be the amount required to relay the message, even if that amount is\n // greater than the minimum gas limit specified by the user.\n if (tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"CrossDomainMessenger: failed to relay message\");\n }\n }\n\n // Clear the reentrancy lock for `versionedHash`\n reentrancyLocks[versionedHash] = false;\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 != Constants.DEFAULT_L2_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 (uint64) {\n // We peform the following math on uint64s to avoid overflow errors. Multiplying the\n // by MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR would otherwise limit the _minGasLimit to\n // type(uint32).max / MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR ~= 4.2m.\n return\n // Dynamic overhead\n ((uint64(_minGasLimit) * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n // Calldata overhead\n (uint64(_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 = Constants.DEFAULT_L2_SENDER;\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" - }, - "contracts/universal/ERC721Bridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { CrossDomainMessenger } from \"./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 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 OTHER_BRIDGE;\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 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 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() == OTHER_BRIDGE,\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 OTHER_BRIDGE = _otherBridge;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for other bridge address.\n *\n * @return Address of the bridge on the other network.\n */\n function otherBridge() external view returns (address) {\n return OTHER_BRIDGE;\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" - }, - "contracts/universal/FeeVault.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { L2StandardBridge } from \"../L2/L2StandardBridge.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\n\n/**\n * @title FeeVault\n * @notice The FeeVault contract contains the basic logic for the various different vault contracts\n * used to hold fee revenue generated by the L2 system.\n */\nabstract contract FeeVault {\n /**\n * @notice Emits each time that a withdrawal occurs.\n *\n * @param value Amount that was withdrawn (in wei).\n * @param to Address that the funds were sent to.\n * @param from Address that triggered the withdrawal.\n */\n event Withdrawal(uint256 value, address to, address from);\n\n /**\n * @notice Minimum balance before a withdrawal can be triggered.\n */\n uint256 public immutable MIN_WITHDRAWAL_AMOUNT;\n\n /**\n * @notice Wallet that will receive the fees on L1.\n */\n address public immutable RECIPIENT;\n\n /**\n * @notice The minimum gas limit for the FeeVault withdrawal transaction.\n */\n uint32 internal constant WITHDRAWAL_MIN_GAS = 35_000;\n\n /**\n * @notice Total amount of wei processed by the contract.\n */\n uint256 public totalProcessed;\n\n /**\n * @param _recipient Wallet that will receive the fees on L1.\n * @param _minWithdrawalAmount Minimum balance before a withdrawal can be triggered.\n */\n constructor(address _recipient, uint256 _minWithdrawalAmount) {\n MIN_WITHDRAWAL_AMOUNT = _minWithdrawalAmount;\n RECIPIENT = _recipient;\n }\n\n /**\n * @notice Allow the contract to receive ETH.\n */\n receive() external payable {}\n\n /**\n * @notice Triggers a withdrawal of funds to the L1 fee wallet.\n */\n function withdraw() external {\n require(\n address(this).balance >= MIN_WITHDRAWAL_AMOUNT,\n \"FeeVault: withdrawal amount must be greater than minimum withdrawal amount\"\n );\n\n uint256 value = address(this).balance;\n totalProcessed += value;\n\n emit Withdrawal(value, RECIPIENT, msg.sender);\n\n L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)).bridgeETHTo{ value: value }(\n RECIPIENT,\n WITHDRAWAL_MIN_GAS,\n bytes(\"\")\n );\n }\n}\n" - }, - "contracts/universal/IOptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\n/**\n * @title IOptimismMintableERC20\n * @notice This interface is available on the OptimismMintableERC20 contract. We declare it as a\n * separate interface so that it can be used in custom implementations of\n * OptimismMintableERC20.\n */\ninterface IOptimismMintableERC20 is IERC165 {\n function remoteToken() external view returns (address);\n\n function bridge() external returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n\n/**\n * @custom:legacy\n * @title ILegacyMintableERC20\n * @notice This interface was available on the legacy L2StandardERC20 contract. It remains available\n * on the OptimismMintableERC20 contract for backwards compatibility.\n */\ninterface ILegacyMintableERC20 is IERC165 {\n function l1Token() external view returns (address);\n\n function mint(address _to, uint256 _amount) external;\n\n function burn(address _from, uint256 _amount) external;\n}\n" - }, - "contracts/universal/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 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 /**\n * @notice Chain ID of the chain where the remote token is deployed.\n */\n function REMOTE_CHAIN_ID() external view returns (uint256);\n\n /**\n * @notice Address of the token on the remote domain.\n */\n function REMOTE_TOKEN() 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 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" - }, - "contracts/universal/OptimismMintableERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport { ILegacyMintableERC20, IOptimismMintableERC20 } from \"./IOptimismMintableERC20.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @title OptimismMintableERC20\n * @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed\n * to allow the StandardBridge contracts to mint and burn tokens. This makes it possible to\n * use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa.\n * Designed to be backwards compatible with the older StandardL2ERC20 token which was only\n * meant for use on L2.\n */\ncontract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, Semver {\n /**\n * @notice Address of the corresponding version of this token on the remote chain.\n */\n address public immutable REMOTE_TOKEN;\n\n /**\n * @notice Address of the StandardBridge on this network.\n */\n address public immutable BRIDGE;\n\n /**\n * @notice Emitted whenever tokens are minted for an account.\n *\n * @param account Address of the account tokens are being minted for.\n * @param amount Amount of tokens minted.\n */\n event Mint(address indexed account, uint256 amount);\n\n /**\n * @notice Emitted whenever tokens are burned from an account.\n *\n * @param account Address of the account tokens are being burned from.\n * @param amount Amount of tokens burned.\n */\n event Burn(address indexed account, uint256 amount);\n\n /**\n * @notice A modifier that only allows the bridge to call\n */\n modifier onlyBridge() {\n require(msg.sender == BRIDGE, \"OptimismMintableERC20: only bridge can mint and burn\");\n _;\n }\n\n /**\n * @custom:semver 1.0.0\n *\n * @param _bridge Address of the L2 standard bridge.\n * @param _remoteToken Address of the corresponding L1 token.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n */\n constructor(\n address _bridge,\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) ERC20(_name, _symbol) Semver(1, 0, 0) {\n REMOTE_TOKEN = _remoteToken;\n BRIDGE = _bridge;\n }\n\n /**\n * @notice Allows the StandardBridge on this network to mint tokens.\n *\n * @param _to Address to mint tokens to.\n * @param _amount Amount of tokens to mint.\n */\n function mint(address _to, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _mint(_to, _amount);\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Allows the StandardBridge on this network to burn tokens.\n *\n * @param _from Address to burn tokens from.\n * @param _amount Amount of tokens to burn.\n */\n function burn(address _from, uint256 _amount)\n external\n virtual\n override(IOptimismMintableERC20, ILegacyMintableERC20)\n onlyBridge\n {\n _burn(_from, _amount);\n emit Burn(_from, _amount);\n }\n\n /**\n * @notice ERC165 interface check function.\n *\n * @param _interfaceId Interface ID to check.\n *\n * @return Whether or not the interface is supported by this contract.\n */\n function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {\n bytes4 iface1 = type(IERC165).interfaceId;\n // Interface corresponding to the legacy L2StandardERC20.\n bytes4 iface2 = type(ILegacyMintableERC20).interfaceId;\n // Interface corresponding to the updated OptimismMintableERC20 (this contract).\n bytes4 iface3 = type(IOptimismMintableERC20).interfaceId;\n return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward.\n */\n function l1Token() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the bridge. Use BRIDGE going forward.\n */\n function l2Bridge() public view returns (address) {\n return BRIDGE;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for REMOTE_TOKEN.\n */\n function remoteToken() public view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for BRIDGE.\n */\n function bridge() public view returns (address) {\n return BRIDGE;\n }\n}\n" - }, - "contracts/universal/OptimismMintableERC20Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/* Contract Imports */\nimport { OptimismMintableERC20 } from \"../universal/OptimismMintableERC20.sol\";\nimport { Semver } from \"./Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeployed 0x4200000000000000000000000000000000000012\n * @title OptimismMintableERC20Factory\n * @notice OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20\n * contracts on the network it's deployed to. Simplifies the deployment process for users\n * who may be less familiar with deploying smart contracts. Designed to be backwards\n * compatible with the older StandardL2ERC20Factory contract.\n */\ncontract OptimismMintableERC20Factory is Semver {\n /**\n * @notice Address of the StandardBridge on this chain.\n */\n address public immutable BRIDGE;\n\n /**\n * @custom:legacy\n * @notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer\n * OptimismMintableERC20Created event. We recommend relying on that event instead.\n *\n * @param remoteToken Address of the token on the remote chain.\n * @param localToken Address of the created token on the local chain.\n */\n event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);\n\n /**\n * @notice Emitted whenever a new OptimismMintableERC20 is created.\n *\n * @param localToken Address of the created token on the local chain.\n * @param remoteToken Address of the corresponding token on the remote chain.\n * @param deployer Address of the account that deployed the token.\n */\n event OptimismMintableERC20Created(\n address indexed localToken,\n address indexed remoteToken,\n address deployer\n );\n\n /**\n * @custom:semver 1.1.0\n *\n * @notice The semver MUST be bumped any time that there is a change in\n * the OptimismMintableERC20 token contract since this contract\n * is responsible for deploying OptimismMintableERC20 contracts.\n *\n * @param _bridge Address of the StandardBridge on this chain.\n */\n constructor(address _bridge) Semver(1, 1, 0) {\n BRIDGE = _bridge;\n }\n\n /**\n * @custom:legacy\n * @notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the\n * newer createOptimismMintableERC20 function, which has a more intuitive name.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createStandardL2Token(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) external returns (address) {\n return createOptimismMintableERC20(_remoteToken, _name, _symbol);\n }\n\n /**\n * @notice Creates an instance of the OptimismMintableERC20 contract.\n *\n * @param _remoteToken Address of the token on the remote chain.\n * @param _name ERC20 name.\n * @param _symbol ERC20 symbol.\n *\n * @return Address of the newly created token.\n */\n function createOptimismMintableERC20(\n address _remoteToken,\n string memory _name,\n string memory _symbol\n ) public returns (address) {\n require(\n _remoteToken != address(0),\n \"OptimismMintableERC20Factory: must provide remote token address\"\n );\n\n address localToken = address(\n new OptimismMintableERC20(BRIDGE, _remoteToken, _name, _symbol)\n );\n\n // Emit the old event too for legacy support.\n emit StandardL2TokenCreated(_remoteToken, localToken);\n\n // Emit the updated event. The arguments here differ from the legacy event, but\n // are consistent with the ordering used in StandardBridge events.\n emit OptimismMintableERC20Created(localToken, _remoteToken, msg.sender);\n\n return localToken;\n }\n}\n" - }, - "contracts/universal/OptimismMintableERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\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\";\nimport { Semver } from \"../universal/Semver.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, Semver {\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n uint256 public immutable REMOTE_CHAIN_ID;\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n address public immutable REMOTE_TOKEN;\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 * @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 * @custom:semver 1.0.0\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) Semver(1, 0, 0) {\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 REMOTE_CHAIN_ID = _remoteChainId;\n REMOTE_TOKEN = _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 * @inheritdoc IOptimismMintableERC721\n */\n function remoteChainId() external view returns (uint256) {\n return REMOTE_CHAIN_ID;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function remoteToken() external view returns (address) {\n return REMOTE_TOKEN;\n }\n\n /**\n * @inheritdoc IOptimismMintableERC721\n */\n function bridge() external view returns (address) {\n return BRIDGE;\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" - }, - "contracts/universal/OptimismMintableERC721Factory.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\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 {\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 REMOTE_CHAIN_ID;\n\n /**\n * @notice Tracks addresses created by this factory.\n */\n mapping(address => bool) public isOptimismMintableERC721;\n\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 * @custom:semver 1.1.0\n * @notice The semver MUST be bumped any time that there is a change in\n * the OptimismMintableERC721 token contract since this contract\n * is responsible for deploying OptimismMintableERC721 contracts.\n *\n * @param _bridge Address of the ERC721 bridge on this network.\n * @param _remoteChainId Chain ID for the remote network.\n */\n constructor(address _bridge, uint256 _remoteChainId) Semver(1, 1, 0) {\n BRIDGE = _bridge;\n REMOTE_CHAIN_ID = _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, REMOTE_CHAIN_ID, _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/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" - }, - "contracts/universal/ProxyAdmin.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.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 Ownable {\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 * @notice A mapping of proxy types, used for backwards compatibility.\n */\n mapping(address => ProxyType) public proxyType;\n\n /**\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 * @notice The address of the address manager, this is required to manage the\n * ResolvedDelegateProxy type.\n */\n AddressManager public addressManager;\n\n /**\n * @notice A legacy upgrading indicator used by the old Chugsplash Proxy.\n */\n bool internal upgrading;\n\n /**\n * @param _owner Address of the initial owner of this contract.\n */\n constructor(address _owner) Ownable() {\n _transferOwnership(_owner);\n }\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 * @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 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.\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 /**\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" - }, - "contracts/universal/Semver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 uint256 private immutable MAJOR_VERSION;\n\n /**\n * @notice Contract version number (minor).\n */\n uint256 private immutable MINOR_VERSION;\n\n /**\n * @notice Contract version number (patch).\n */\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" - }, - "contracts/universal/StandardBridge.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { ERC165Checker } from \"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { IOptimismMintableERC20, ILegacyMintableERC20 } from \"./IOptimismMintableERC20.sol\";\nimport { CrossDomainMessenger } from \"./CrossDomainMessenger.sol\";\nimport { OptimismMintableERC20 } from \"./OptimismMintableERC20.sol\";\n\n/**\n * @custom:upgradeable\n * @title StandardBridge\n * @notice StandardBridge is a base contract for the L1 and L2 standard ERC20 bridges. It handles\n * the core bridging logic, including escrowing tokens that are native to the local chain\n * and minting/burning tokens that are native to the remote chain.\n */\nabstract contract StandardBridge {\n using SafeERC20 for IERC20;\n\n /**\n * @notice The L2 gas limit set when eth is depoisited using the receive() function.\n */\n uint32 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 200_000;\n\n /**\n * @notice Messenger contract on this domain.\n */\n CrossDomainMessenger public immutable MESSENGER;\n\n /**\n * @notice Corresponding bridge on the other domain.\n */\n StandardBridge public immutable OTHER_BRIDGE;\n\n /**\n * @custom:legacy\n * @custom:spacer messenger\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_0_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer l2TokenBridge\n * @notice Spacer for backwards compatibility.\n */\n address private spacer_1_0_20;\n\n /**\n * @notice Mapping that stores deposits for a given pair of local and remote tokens.\n */\n mapping(address => mapping(address => uint256)) public deposits;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n * A gap size of 47 was chosen here, so that the first slot used in a child contract\n * would be a multiple of 50.\n */\n uint256[47] private __gap;\n\n /**\n * @notice Emitted when an ETH bridge is initiated to the other chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeInitiated(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ETH bridge is finalized on this chain.\n *\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of ETH sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ETHBridgeFinalized(\n address indexed from,\n address indexed to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is initiated to the other chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeInitiated(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Emitted when an ERC20 bridge is finalized on this chain.\n *\n * @param localToken Address of the ERC20 on this chain.\n * @param remoteToken Address of the ERC20 on the remote chain.\n * @param from Address of the sender.\n * @param to Address of the receiver.\n * @param amount Amount of the ERC20 sent.\n * @param extraData Extra data sent with the transaction.\n */\n event ERC20BridgeFinalized(\n address indexed localToken,\n address indexed remoteToken,\n address indexed from,\n address to,\n uint256 amount,\n bytes extraData\n );\n\n /**\n * @notice Only allow EOAs to call the functions. Note that this is not safe against contracts\n * calling code within their constructors, but also doesn't really matter since we're\n * just trying to prevent users accidentally depositing with smart contract wallets.\n */\n modifier onlyEOA() {\n require(\n !Address.isContract(msg.sender),\n \"StandardBridge: function can only be called from an EOA\"\n );\n _;\n }\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) &&\n MESSENGER.xDomainMessageSender() == address(OTHER_BRIDGE),\n \"StandardBridge: function can only be called from the other bridge\"\n );\n _;\n }\n\n /**\n * @param _messenger Address of CrossDomainMessenger on this network.\n * @param _otherBridge Address of the other StandardBridge contract.\n */\n constructor(address payable _messenger, address payable _otherBridge) {\n MESSENGER = CrossDomainMessenger(_messenger);\n OTHER_BRIDGE = StandardBridge(_otherBridge);\n }\n\n /**\n * @notice Allows EOAs to bridge ETH by sending directly to the bridge.\n * Must be implemented by contracts that inherit.\n */\n receive() external payable virtual;\n\n /**\n * @custom:legacy\n * @notice Legacy getter for messenger contract.\n *\n * @return Messenger contract on this domain.\n */\n function messenger() external view returns (CrossDomainMessenger) {\n return MESSENGER;\n }\n\n /**\n * @notice Sends ETH to the sender's address on the other chain.\n *\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETH(uint32 _minGasLimit, bytes calldata _extraData) public payable onlyEOA {\n _initiateBridgeETH(msg.sender, msg.sender, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a\n * smart contract and the call fails, the ETH will be temporarily locked in the\n * StandardBridge on the other chain until the call is replayed. If the call cannot be\n * replayed with any amount of gas (call always reverts), then the ETH will be\n * permanently locked in the StandardBridge on the other chain. ETH will also\n * be locked if the receiver is the other bridge, because finalizeBridgeETH will revert\n * in that case.\n *\n * @param _to Address of the receiver.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeETHTo(\n address _to,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public payable {\n _initiateBridgeETH(msg.sender, _to, msg.value, _minGasLimit, _extraData);\n }\n\n /**\n * @notice Sends ERC20 tokens to the sender's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20(\n address _localToken,\n address _remoteToken,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual onlyEOA {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n msg.sender,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain. Note that if the\n * ERC20 token on the other chain does not recognize the local token as the correct\n * pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n * this chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function bridgeERC20To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) public virtual {\n _initiateBridgeERC20(\n _localToken,\n _remoteToken,\n msg.sender,\n _to,\n _amount,\n _minGasLimit,\n _extraData\n );\n }\n\n /**\n * @notice Finalizes an ETH bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public payable onlyOtherBridge {\n require(msg.value == _amount, \"StandardBridge: amount sent does not match amount required\");\n require(_to != address(this), \"StandardBridge: cannot send to self\");\n require(_to != address(MESSENGER), \"StandardBridge: cannot send to messenger\");\n\n // Emit the correct events. By default this will be _amount, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitETHBridgeFinalized(_from, _to, _amount, _extraData);\n\n bool success = SafeCall.call(_to, gasleft(), _amount, hex\"\");\n require(success, \"StandardBridge: ETH transfer failed\");\n }\n\n /**\n * @notice Finalizes an ERC20 bridge on this chain. Can only be triggered by the other\n * StandardBridge contract on the remote chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 being bridged.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function finalizeBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _extraData\n ) public onlyOtherBridge {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).mint(_to, _amount);\n } else {\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] - _amount;\n IERC20(_localToken).safeTransfer(_to, _amount);\n }\n\n // Emit the correct events. By default this will be ERC20BridgeFinalized, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Initiates a bridge of ETH through the CrossDomainMessenger.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH being bridged.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeETH(\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n require(\n msg.value == _amount,\n \"StandardBridge: bridging ETH must include sufficient ETH value\"\n );\n\n // Emit the correct events. By default this will be _amount, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitETHBridgeInitiated(_from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage{ value: _amount }(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeETH.selector,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Sends ERC20 tokens to a receiver's address on the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the corresponding token on the remote chain.\n * @param _to Address of the receiver.\n * @param _amount Amount of local tokens to deposit.\n * @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n * @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n * not be triggered with this data, but it will be emitted and can be used\n * to identify the transaction.\n */\n function _initiateBridgeERC20(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes memory _extraData\n ) internal {\n if (_isOptimismMintableERC20(_localToken)) {\n require(\n _isCorrectTokenPair(_localToken, _remoteToken),\n \"StandardBridge: wrong remote token for Optimism Mintable ERC20 local token\"\n );\n\n OptimismMintableERC20(_localToken).burn(_from, _amount);\n } else {\n IERC20(_localToken).safeTransferFrom(_from, address(this), _amount);\n deposits[_localToken][_remoteToken] = deposits[_localToken][_remoteToken] + _amount;\n }\n\n // Emit the correct events. By default this will be ERC20BridgeInitiated, but child\n // contracts may override this function in order to emit legacy events as well.\n _emitERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n\n MESSENGER.sendMessage(\n address(OTHER_BRIDGE),\n abi.encodeWithSelector(\n this.finalizeBridgeERC20.selector,\n // Because this call will be executed on the remote chain, we reverse the order of\n // the remote and local token addresses relative to their order in the\n // finalizeBridgeERC20 function.\n _remoteToken,\n _localToken,\n _from,\n _to,\n _amount,\n _extraData\n ),\n _minGasLimit\n );\n }\n\n /**\n * @notice Checks if a given address is an OptimismMintableERC20. Not perfect, but good enough.\n * Just the way we like it.\n *\n * @param _token Address of the token to check.\n *\n * @return True if the token is an OptimismMintableERC20.\n */\n function _isOptimismMintableERC20(address _token) internal view returns (bool) {\n return\n ERC165Checker.supportsInterface(_token, type(ILegacyMintableERC20).interfaceId) ||\n ERC165Checker.supportsInterface(_token, type(IOptimismMintableERC20).interfaceId);\n }\n\n /**\n * @notice Checks if the \"other token\" is the correct pair token for the OptimismMintableERC20.\n * Calls can be saved in the future by combining this logic with\n * `_isOptimismMintableERC20`.\n *\n * @param _mintableToken OptimismMintableERC20 to check against.\n * @param _otherToken Pair token to check.\n *\n * @return True if the other token is the correct pair token for the OptimismMintableERC20.\n */\n function _isCorrectTokenPair(address _mintableToken, address _otherToken)\n internal\n view\n returns (bool)\n {\n if (\n ERC165Checker.supportsInterface(_mintableToken, type(ILegacyMintableERC20).interfaceId)\n ) {\n return _otherToken == ILegacyMintableERC20(_mintableToken).l1Token();\n } else {\n return _otherToken == IOptimismMintableERC20(_mintableToken).remoteToken();\n }\n }\n\n /** @notice Emits the ETHBridgeInitiated event and if necessary the appropriate legacy event\n * when an ETH bridge is finalized on this chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitETHBridgeInitiated(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ETHBridgeInitiated(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ETHBridgeFinalized and if necessary the appropriate legacy event when an\n * ETH bridge is finalized on this chain.\n *\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of ETH sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitETHBridgeFinalized(\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ETHBridgeFinalized(_from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ERC20BridgeInitiated event and if necessary the appropriate legacy\n * event when an ERC20 bridge is initiated to the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the ERC20 on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitERC20BridgeInitiated(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ERC20BridgeInitiated(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n\n /**\n * @notice Emits the ERC20BridgeFinalized event and if necessary the appropriate legacy\n * event when an ERC20 bridge is initiated to the other chain.\n *\n * @param _localToken Address of the ERC20 on this chain.\n * @param _remoteToken Address of the ERC20 on the remote chain.\n * @param _from Address of the sender.\n * @param _to Address of the receiver.\n * @param _amount Amount of the ERC20 sent.\n * @param _extraData Extra data sent with the transaction.\n */\n function _emitERC20BridgeFinalized(\n address _localToken,\n address _remoteToken,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _extraData\n ) internal virtual {\n emit ERC20BridgeFinalized(_localToken, _remoteToken, _from, _to, _amount, _extraData);\n }\n}\n" - }, - "contracts/vendor/AddressAliasHelper.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npragma solidity ^0.8.0;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n unchecked {\n l2Address = address(uint160(l1Address) + offset);\n }\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n unchecked {\n l1Address = address(uint160(l2Address) - offset);\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/access/Ownable.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/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 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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/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/Address.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) || (!Address.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" - }, - "node_modules/@openzeppelin/contracts/security/ReentrancyGuard.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\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 ReentrancyGuard {\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 constructor() {\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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, allowance(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 = allowance(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 `from` to `to`.\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 Updates `owner` s allowance for `spender` based on spent `amount`.\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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 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 /**\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (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 constant _PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n /**\n * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\n * However, to ensure consistency with the upgradeable transpiler, we will continue\n * to reserve a slot.\n * @custom:oz-renamed-from _PERMIT_TYPEHASH\n */\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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: address zero is not a valid owner\");\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: invalid token ID\");\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 _requireMinted(tokenId);\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 token 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 _requireMinted(tokenId);\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: caller is not token 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: caller is not token 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 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 an {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 an {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 Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\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 /// @solidity memory-safe-assembly\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" - }, - "node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Address.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 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 /// @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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\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 /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.3) (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 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 /// @solidity memory-safe-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 {\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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.2) (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 // prepare call\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n\n // perform static call\n bool success;\n uint256 returnSize;\n uint256 returnValue;\n assembly {\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\n returnSize := returndatasize()\n returnValue := mload(0x00)\n }\n\n return success && returnSize >= 0x20 && returnValue > 0;\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@openzeppelin/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\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 == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`.\n // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.\n // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.\n // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a\n // good first aproximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1;\n uint256 x = a;\n if (x >> 128 > 0) {\n x >>= 128;\n result <<= 64;\n }\n if (x >> 64 > 0) {\n x >>= 64;\n result <<= 32;\n }\n if (x >> 32 > 0) {\n x >>= 32;\n result <<= 16;\n }\n if (x >> 16 > 0) {\n x >>= 16;\n result <<= 8;\n }\n if (x >> 8 > 0) {\n x >>= 8;\n result <<= 4;\n }\n if (x >> 4 > 0) {\n x >>= 4;\n result <<= 2;\n }\n if (x >> 2 > 0) {\n result <<= 1;\n }\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n uint256 result = sqrt(a);\n if (rounding == Rounding.Up && result * result < a) {\n result += 1;\n }\n return result;\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\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 * _Available since v4.2._\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 uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(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 * _Available since v2.5._\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 uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(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 * _Available since v4.2._\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 uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(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 * _Available since v2.5._\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 uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(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 * _Available since v2.5._\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 uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(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 * _Available since v2.5._\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 * _Available since v2.5._\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 * _Available since v3.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 int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248) {\n require(value >= type(int248).min && value <= type(int248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return int248(value);\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240) {\n require(value >= type(int240).min && value <= type(int240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return int240(value);\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232) {\n require(value >= type(int232).min && value <= type(int232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return int232(value);\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224) {\n require(value >= type(int224).min && value <= type(int224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return int224(value);\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216) {\n require(value >= type(int216).min && value <= type(int216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return int216(value);\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208) {\n require(value >= type(int208).min && value <= type(int208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return int208(value);\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200) {\n require(value >= type(int200).min && value <= type(int200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return int200(value);\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192) {\n require(value >= type(int192).min && value <= type(int192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return int192(value);\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184) {\n require(value >= type(int184).min && value <= type(int184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return int184(value);\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176) {\n require(value >= type(int176).min && value <= type(int176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return int176(value);\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168) {\n require(value >= type(int168).min && value <= type(int168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return int168(value);\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160) {\n require(value >= type(int160).min && value <= type(int160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return int160(value);\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152) {\n require(value >= type(int152).min && value <= type(int152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return int152(value);\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144) {\n require(value >= type(int144).min && value <= type(int144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return int144(value);\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136) {\n require(value >= type(int136).min && value <= type(int136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return int136(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 int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120) {\n require(value >= type(int120).min && value <= type(int120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return int120(value);\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112) {\n require(value >= type(int112).min && value <= type(int112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return int112(value);\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104) {\n require(value >= type(int104).min && value <= type(int104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return int104(value);\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96) {\n require(value >= type(int96).min && value <= type(int96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return int96(value);\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88) {\n require(value >= type(int88).min && value <= type(int88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return int88(value);\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80) {\n require(value >= type(int80).min && value <= type(int80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return int80(value);\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72) {\n require(value >= type(int72).min && value <= type(int72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return int72(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 int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56) {\n require(value >= type(int56).min && value <= type(int56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return int56(value);\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48) {\n require(value >= type(int48).min && value <= type(int48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return int48(value);\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40) {\n require(value >= type(int40).min && value <= type(int40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return int40(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 int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24) {\n require(value >= type(int24).min && value <= type(int24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return int24(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 * _Available since v3.0._\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" - }, - "node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@rari-capital/solmate/src/utils/Bytes32AddressLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Library for converting between addresses and bytes32 values.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/Bytes32AddressLib.sol)\nlibrary Bytes32AddressLib {\n function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n function fillLast12Bytes(address addressValue) internal pure returns (bytes32) {\n return bytes32(bytes20(addressValue));\n }\n}\n" - }, - "node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)\nlibrary FixedPointMathLib {\n /*//////////////////////////////////////////////////////////////\n SIMPLIFIED FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n }\n\n function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n }\n\n function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n }\n\n function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n }\n\n function powWad(int256 x, int256 y) internal pure returns (int256) {\n // Equivalent to x to the power of y because x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)\n return expWad((lnWad(x) * y) / int256(WAD)); // Using ln(x) means x must be greater than 0.\n }\n\n function expWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n // When the result is < 0.5 we return zero. This happens when\n // x <= floor(log(0.5e18) * 1e18) ~ -42e18\n if (x <= -42139678854452767551) return 0;\n\n // When the result is > (2**255 - 1) / 1e18 we can not represent it as an\n // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.\n if (x >= 135305999368893231589) revert(\"EXP_OVERFLOW\");\n\n // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96\n // for more intermediate precision and a binary basis. This base conversion\n // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.\n x = (x << 78) / 5**18;\n\n // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers\n // of two such that exp(x) = exp(x') * 2**k, where k is an integer.\n // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).\n int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96;\n x = x - k * 54916777467707473351141471128;\n\n // k is in the range [-61, 195].\n\n // Evaluate using a (6, 7)-term rational approximation.\n // p is made monic, we'll multiply by a scale factor later.\n int256 y = x + 1346386616545796478920950773328;\n y = ((y * x) >> 96) + 57155421227552351082224309758442;\n int256 p = y + x - 94201549194550492254356042504812;\n p = ((p * y) >> 96) + 28719021644029726153956944680412240;\n p = p * x + (4385272521454847904659076985693276 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n int256 q = x - 2855989394907223263936484059900;\n q = ((q * x) >> 96) + 50020603652535783019961831881945;\n q = ((q * x) >> 96) - 533845033583426703283633433725380;\n q = ((q * x) >> 96) + 3604857256930695427073651918091429;\n q = ((q * x) >> 96) - 14423608567350463180887372962807573;\n q = ((q * x) >> 96) + 26449188498355588339934803723976023;\n\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial won't have zeros in the domain as all its roots are complex.\n // No scaling is necessary because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r should be in the range (0.09, 0.25) * 2**96.\n\n // We now need to multiply r by:\n // * the scale factor s = ~6.031367120.\n // * the 2**k factor from the range reduction.\n // * the 1e18 / 2**96 factor for base conversion.\n // We do this all at once, with an intermediate result in 2**213\n // basis, so the final right shift is always by a positive amount.\n r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k));\n }\n }\n\n function lnWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n require(x > 0, \"UNDEFINED\");\n\n // We want to convert x from 10**18 fixed point to 2**96 fixed point.\n // We do this by multiplying by 2**96 / 10**18. But since\n // ln(x * C) = ln(x) + ln(C), we can simply do nothing here\n // and add ln(2**96 / 10**18) at the end.\n\n // Reduce range of x to (1, 2) * 2**96\n // ln(2^k * x) = k * ln(2) + ln(x)\n int256 k = int256(log2(uint256(x))) - 96;\n x <<= uint256(159 - k);\n x = int256(uint256(x) >> 159);\n\n // Evaluate using a (8, 8)-term rational approximation.\n // p is made monic, we will multiply by a scale factor later.\n int256 p = x + 3273285459638523848632254066296;\n p = ((p * x) >> 96) + 24828157081833163892658089445524;\n p = ((p * x) >> 96) + 43456485725739037958740375743393;\n p = ((p * x) >> 96) - 11111509109440967052023855526967;\n p = ((p * x) >> 96) - 45023709667254063763336534515857;\n p = ((p * x) >> 96) - 14706773417378608786704636184526;\n p = p * x - (795164235651350426258249787498 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n // q is monic by convention.\n int256 q = x + 5573035233440673466300451813936;\n q = ((q * x) >> 96) + 71694874799317883764090561454958;\n q = ((q * x) >> 96) + 283447036172924575727196451306956;\n q = ((q * x) >> 96) + 401686690394027663651624208769553;\n q = ((q * x) >> 96) + 204048457590392012362485061816622;\n q = ((q * x) >> 96) + 31853899698501571402653359427138;\n q = ((q * x) >> 96) + 909429971244387300277376558375;\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial is known not to have zeros in the domain.\n // No scaling required because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r is in the range (0, 0.125) * 2**96\n\n // Finalization, we need to:\n // * multiply by the scale factor s = 5.549…\n // * add ln(2**96 / 10**18)\n // * add k * ln(2)\n // * multiply by 10**18 / 2**96 = 5**18 >> 78\n\n // mul s * 5e18 * 2**96, base is now 5**18 * 2**192\n r *= 1677202110996718588342820967067443963516166;\n // add ln(2) * k * 5e18 * 2**192\n r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;\n // add ln(2**96 / 10**18) * 5e18 * 2**192\n r += 600920179829731861736702779321621459595472258049074101567377883020018308;\n // base conversion: mul 2**18 / 2**192\n r >>= 174;\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n LOW LEVEL FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function mulDivDown(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // Divide z by the denominator.\n z := div(z, denominator)\n }\n }\n\n function mulDivUp(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // First, divide z - 1 by the denominator and add 1.\n // We allow z - 1 to underflow if z is 0, because we multiply the\n // end result by 0 if z is zero, ensuring we return 0 if z is zero.\n z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))\n }\n }\n\n function rpow(\n uint256 x,\n uint256 n,\n uint256 scalar\n ) internal pure returns (uint256 z) {\n assembly {\n switch x\n case 0 {\n switch n\n case 0 {\n // 0 ** 0 = 1\n z := scalar\n }\n default {\n // 0 ** n = 0\n z := 0\n }\n }\n default {\n switch mod(n, 2)\n case 0 {\n // If n is even, store scalar in z for now.\n z := scalar\n }\n default {\n // If n is odd, store x in z for now.\n z := x\n }\n\n // Shifting right by 1 is like dividing by 2.\n let half := shr(1, scalar)\n\n for {\n // Shift n right by 1 before looping to halve it.\n n := shr(1, n)\n } n {\n // Shift n right by 1 each iteration to halve it.\n n := shr(1, n)\n } {\n // Revert immediately if x ** 2 would overflow.\n // Equivalent to iszero(eq(div(xx, x), x)) here.\n if shr(128, x) {\n revert(0, 0)\n }\n\n // Store x squared.\n let xx := mul(x, x)\n\n // Round to the nearest number.\n let xxRound := add(xx, half)\n\n // Revert if xx + half overflowed.\n if lt(xxRound, xx) {\n revert(0, 0)\n }\n\n // Set x to scaled xxRound.\n x := div(xxRound, scalar)\n\n // If n is even:\n if mod(n, 2) {\n // Compute z * x.\n let zx := mul(z, x)\n\n // If z * x overflowed:\n if iszero(eq(div(zx, x), z)) {\n // Revert if x is non-zero.\n if iszero(iszero(x)) {\n revert(0, 0)\n }\n }\n\n // Round to the nearest number.\n let zxRound := add(zx, half)\n\n // Revert if zx + half overflowed.\n if lt(zxRound, zx) {\n revert(0, 0)\n }\n\n // Return properly scaled zxRound.\n z := div(zxRound, scalar)\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n GENERAL NUMBER UTILITIES\n //////////////////////////////////////////////////////////////*/\n\n function sqrt(uint256 x) internal pure returns (uint256 z) {\n assembly {\n let y := x // We start y at x, which will help us make our initial estimate.\n\n z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n // We check y >= 2^(k + 8) but shift right by k bits\n // each branch to ensure that if x >= 256, then y >= 256.\n if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n y := shr(128, y)\n z := shl(64, z)\n }\n if iszero(lt(y, 0x1000000000000000000)) {\n y := shr(64, y)\n z := shl(32, z)\n }\n if iszero(lt(y, 0x10000000000)) {\n y := shr(32, y)\n z := shl(16, z)\n }\n if iszero(lt(y, 0x1000000)) {\n y := shr(16, y)\n z := shl(8, z)\n }\n\n // Goal was to get z*z*y within a small factor of x. More iterations could\n // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n // There is no overflow risk here since y < 2^136 after the first branch above.\n z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n\n // If x+1 is a perfect square, the Babylonian method cycles between\n // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n z := sub(z, lt(div(x, z), z))\n }\n }\n\n function log2(uint256 x) internal pure returns (uint256 r) {\n require(x > 0, \"UNDEFINED\");\n\n assembly {\n r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n r := or(r, shl(4, lt(0xffff, shr(r, x))))\n r := or(r, shl(3, lt(0xff, shr(r, x))))\n r := or(r, shl(2, lt(0xf, shr(r, x))))\n r := or(r, shl(1, lt(0x3, shr(r, x))))\n r := or(r, lt(0x1, shr(r, x)))\n }\n }\n}\n" - }, - "node_modules/ds-test/src/test.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see .\n\npragma solidity >=0.5.0;\n\ncontract DSTest {\n event log (string);\n event logs (bytes);\n\n event log_address (address);\n event log_bytes32 (bytes32);\n event log_int (int);\n event log_uint (uint);\n event log_bytes (bytes);\n event log_string (string);\n\n event log_named_address (string key, address val);\n event log_named_bytes32 (string key, bytes32 val);\n event log_named_decimal_int (string key, int val, uint decimals);\n event log_named_decimal_uint (string key, uint val, uint decimals);\n event log_named_int (string key, int val);\n event log_named_uint (string key, uint val);\n event log_named_bytes (string key, bytes val);\n event log_named_string (string key, string val);\n\n bool public IS_TEST = true;\n bool private _failed;\n\n address constant HEVM_ADDRESS =\n address(bytes20(uint160(uint256(keccak256('hevm cheat code')))));\n\n modifier mayRevert() { _; }\n modifier testopts(string memory) { _; }\n\n function failed() public returns (bool) {\n if (_failed) {\n return _failed;\n } else {\n bool globalFailed = false;\n if (hasHEVMContext()) {\n (, bytes memory retdata) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"load(address,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"))\n )\n );\n globalFailed = abi.decode(retdata, (bool));\n }\n return globalFailed;\n }\n } \n\n function fail() internal {\n if (hasHEVMContext()) {\n (bool status, ) = HEVM_ADDRESS.call(\n abi.encodePacked(\n bytes4(keccak256(\"store(address,bytes32,bytes32)\")),\n abi.encode(HEVM_ADDRESS, bytes32(\"failed\"), bytes32(uint256(0x01)))\n )\n );\n status; // Silence compiler warnings\n }\n _failed = true;\n }\n\n function hasHEVMContext() internal view returns (bool) {\n uint256 hevmCodeSize = 0;\n assembly {\n hevmCodeSize := extcodesize(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D)\n }\n return hevmCodeSize > 0;\n }\n\n modifier logs_gas() {\n uint startGas = gasleft();\n _;\n uint endGas = gasleft();\n emit log_named_uint(\"gas\", startGas - endGas);\n }\n\n function assertTrue(bool condition) internal {\n if (!condition) {\n emit log(\"Error: Assertion Failed\");\n fail();\n }\n }\n\n function assertTrue(bool condition, string memory err) internal {\n if (!condition) {\n emit log_named_string(\"Error\", err);\n assertTrue(condition);\n }\n }\n\n function assertEq(address a, address b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [address]\");\n emit log_named_address(\" Expected\", b);\n emit log_named_address(\" Actual\", a);\n fail();\n }\n }\n function assertEq(address a, address b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes32 a, bytes32 b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bytes32]\");\n emit log_named_bytes32(\" Expected\", b);\n emit log_named_bytes32(\" Actual\", a);\n fail();\n }\n }\n function assertEq(bytes32 a, bytes32 b, string memory err) internal {\n if (a != b) {\n emit log_named_string (\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq32(bytes32 a, bytes32 b) internal {\n assertEq(a, b);\n }\n function assertEq32(bytes32 a, bytes32 b, string memory err) internal {\n assertEq(a, b, err);\n }\n\n function assertEq(int a, int b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [int]\");\n emit log_named_int(\" Expected\", b);\n emit log_named_int(\" Actual\", a);\n fail();\n }\n }\n function assertEq(int a, int b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEq(uint a, uint b) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [uint]\");\n emit log_named_uint(\" Expected\", b);\n emit log_named_uint(\" Actual\", a);\n fail();\n }\n }\n function assertEq(uint a, uint b, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n function assertEqDecimal(int a, int b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Expected\", b, decimals);\n emit log_named_decimal_int(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals) internal {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Expected\", b, decimals);\n emit log_named_decimal_uint(\" Actual\", a, decimals);\n fail();\n }\n }\n function assertEqDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEqDecimal(a, b, decimals);\n }\n }\n\n function assertGt(uint a, uint b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGt(uint a, uint b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGt(int a, int b) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGt(int a, int b, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGt(a, b);\n }\n }\n function assertGtDecimal(int a, int b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals) internal {\n if (a <= b) {\n emit log(\"Error: a > b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a <= b) {\n emit log_named_string(\"Error\", err);\n assertGtDecimal(a, b, decimals);\n }\n }\n\n function assertGe(uint a, uint b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertGe(uint a, uint b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGe(int a, int b) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertGe(int a, int b, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGe(a, b);\n }\n }\n function assertGeDecimal(int a, int b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals) internal {\n if (a < b) {\n emit log(\"Error: a >= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertGeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a < b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertLt(uint a, uint b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLt(uint a, uint b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLt(int a, int b) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLt(int a, int b, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLt(a, b);\n }\n }\n function assertLtDecimal(int a, int b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals) internal {\n if (a >= b) {\n emit log(\"Error: a < b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLtDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a >= b) {\n emit log_named_string(\"Error\", err);\n assertLtDecimal(a, b, decimals);\n }\n }\n\n function assertLe(uint a, uint b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [uint]\");\n emit log_named_uint(\" Value a\", a);\n emit log_named_uint(\" Value b\", b);\n fail();\n }\n }\n function assertLe(uint a, uint b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLe(int a, int b) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [int]\");\n emit log_named_int(\" Value a\", a);\n emit log_named_int(\" Value b\", b);\n fail();\n }\n }\n function assertLe(int a, int b, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLe(a, b);\n }\n }\n function assertLeDecimal(int a, int b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal int]\");\n emit log_named_decimal_int(\" Value a\", a, decimals);\n emit log_named_decimal_int(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(int a, int b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertLeDecimal(a, b, decimals);\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals) internal {\n if (a > b) {\n emit log(\"Error: a <= b not satisfied [decimal uint]\");\n emit log_named_decimal_uint(\" Value a\", a, decimals);\n emit log_named_decimal_uint(\" Value b\", b, decimals);\n fail();\n }\n }\n function assertLeDecimal(uint a, uint b, uint decimals, string memory err) internal {\n if (a > b) {\n emit log_named_string(\"Error\", err);\n assertGeDecimal(a, b, decimals);\n }\n }\n\n function assertEq(string memory a, string memory b) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log(\"Error: a == b not satisfied [string]\");\n emit log_named_string(\" Expected\", b);\n emit log_named_string(\" Actual\", a);\n fail();\n }\n }\n function assertEq(string memory a, string memory b, string memory err) internal {\n if (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function checkEq0(bytes memory a, bytes memory b) internal pure returns (bool ok) {\n ok = true;\n if (a.length == b.length) {\n for (uint i = 0; i < a.length; i++) {\n if (a[i] != b[i]) {\n ok = false;\n }\n }\n } else {\n ok = false;\n }\n }\n function assertEq0(bytes memory a, bytes memory b) internal {\n if (!checkEq0(a, b)) {\n emit log(\"Error: a == b not satisfied [bytes]\");\n emit log_named_bytes(\" Expected\", b);\n emit log_named_bytes(\" Actual\", a);\n fail();\n }\n }\n function assertEq0(bytes memory a, bytes memory b, string memory err) internal {\n if (!checkEq0(a, b)) {\n emit log_named_string(\"Error\", err);\n assertEq0(a, b);\n }\n }\n}\n" - }, - "node_modules/forge-std/src/Base.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {StdStorage} from \"./StdStorage.sol\";\nimport {Vm, VmSafe} from \"./Vm.sol\";\n\nabstract contract CommonBase {\n // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.\n address internal constant VM_ADDRESS = address(uint160(uint256(keccak256(\"hevm cheat code\"))));\n // console.sol and console2.sol work by executing a staticcall to this address.\n address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;\n // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38.\n address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256(\"foundry default caller\"))));\n // Address of the test contract, deployed by the DEFAULT_SENDER.\n address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;\n // Deterministic deployment address of the Multicall3 contract.\n address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11;\n\n uint256 internal constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n Vm internal constant vm = Vm(VM_ADDRESS);\n StdStorage internal stdstore;\n}\n\nabstract contract TestBase is CommonBase {}\n\nabstract contract ScriptBase is CommonBase {\n // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.\n address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;\n\n VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);\n}\n" - }, - "node_modules/forge-std/src/StdAssertions.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {DSTest} from \"ds-test/test.sol\";\nimport {stdMath} from \"./StdMath.sol\";\n\nabstract contract StdAssertions is DSTest {\n event log_array(uint256[] val);\n event log_array(int256[] val);\n event log_array(address[] val);\n event log_named_array(string key, uint256[] val);\n event log_named_array(string key, int256[] val);\n event log_named_array(string key, address[] val);\n\n function fail(string memory err) internal virtual {\n emit log_named_string(\"Error\", err);\n fail();\n }\n\n function assertFalse(bool data) internal virtual {\n assertTrue(!data);\n }\n\n function assertFalse(bool data, string memory err) internal virtual {\n assertTrue(!data, err);\n }\n\n function assertEq(bool a, bool b) internal virtual {\n if (a != b) {\n emit log(\"Error: a == b not satisfied [bool]\");\n emit log_named_string(\" Left\", a ? \"true\" : \"false\");\n emit log_named_string(\" Right\", b ? \"true\" : \"false\");\n fail();\n }\n }\n\n function assertEq(bool a, bool b, string memory err) internal virtual {\n if (a != b) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(bytes memory a, bytes memory b) internal virtual {\n assertEq0(a, b);\n }\n\n function assertEq(bytes memory a, bytes memory b, string memory err) internal virtual {\n assertEq0(a, b, err);\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [uint[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [int[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(address[] memory a, address[] memory b) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log(\"Error: a == b not satisfied [address[]]\");\n emit log_named_array(\" Left\", a);\n emit log_named_array(\" Right\", b);\n fail();\n }\n }\n\n function assertEq(uint256[] memory a, uint256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(int256[] memory a, int256[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n function assertEq(address[] memory a, address[] memory b, string memory err) internal virtual {\n if (keccak256(abi.encode(a)) != keccak256(abi.encode(b))) {\n emit log_named_string(\"Error\", err);\n assertEq(a, b);\n }\n }\n\n // Legacy helper\n function assertEqUint(uint256 a, uint256 b) internal virtual {\n assertEq(uint256(a), uint256(b));\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Left\", a);\n emit log_named_uint(\" Right\", b);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_decimal_uint(\" Left\", a, decimals);\n emit log_named_decimal_uint(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max Delta\", maxDelta, decimals);\n emit log_named_decimal_uint(\" Delta\", delta, decimals);\n fail();\n }\n }\n\n function assertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbsDecimal(a, b, maxDelta, decimals);\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Left\", a);\n emit log_named_int(\" Right\", b);\n emit log_named_uint(\" Max Delta\", maxDelta);\n emit log_named_uint(\" Delta\", delta);\n fail();\n }\n }\n\n function assertApproxEqAbs(int256 a, int256 b, uint256 maxDelta, string memory err) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbs(a, b, maxDelta);\n }\n }\n\n function assertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals) internal virtual {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_decimal_int(\" Left\", a, decimals);\n emit log_named_decimal_int(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max Delta\", maxDelta, decimals);\n emit log_named_decimal_uint(\" Delta\", delta, decimals);\n fail();\n }\n }\n\n function assertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n uint256 delta = stdMath.delta(a, b);\n\n if (delta > maxDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqAbsDecimal(a, b, maxDelta, decimals);\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%\n ) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_uint(\" Left\", a);\n emit log_named_uint(\" Right\", b);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n string memory err\n ) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n\n function assertApproxEqRelDecimal(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n uint256 decimals\n ) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [uint]\");\n emit log_named_decimal_uint(\" Left\", a, decimals);\n emit log_named_decimal_uint(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRelDecimal(\n uint256 a,\n uint256 b,\n uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%\n uint256 decimals,\n string memory err\n ) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_int(\" Left\", a);\n emit log_named_int(\" Right\", b);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta, string memory err) internal virtual {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRel(a, b, maxPercentDelta);\n }\n }\n\n function assertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals) internal virtual {\n if (b == 0) return assertEq(a, b); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log(\"Error: a ~= b not satisfied [int]\");\n emit log_named_decimal_int(\" Left\", a, decimals);\n emit log_named_decimal_int(\" Right\", b, decimals);\n emit log_named_decimal_uint(\" Max % Delta\", maxPercentDelta, 18);\n emit log_named_decimal_uint(\" % Delta\", percentDelta, 18);\n fail();\n }\n }\n\n function assertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals, string memory err)\n internal\n virtual\n {\n if (b == 0) return assertEq(a, b, err); // If the left is 0, right must be too.\n\n uint256 percentDelta = stdMath.percentDelta(a, b);\n\n if (percentDelta > maxPercentDelta) {\n emit log_named_string(\"Error\", err);\n assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);\n }\n }\n\n function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual {\n assertEqCall(target, callDataA, target, callDataB, true);\n }\n\n function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB)\n internal\n virtual\n {\n assertEqCall(targetA, callDataA, targetB, callDataB, true);\n }\n\n function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData)\n internal\n virtual\n {\n assertEqCall(target, callDataA, target, callDataB, strictRevertData);\n }\n\n function assertEqCall(\n address targetA,\n bytes memory callDataA,\n address targetB,\n bytes memory callDataB,\n bool strictRevertData\n ) internal virtual {\n (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA);\n (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB);\n\n if (successA && successB) {\n assertEq(returnDataA, returnDataB, \"Call return data does not match\");\n }\n\n if (!successA && !successB && strictRevertData) {\n assertEq(returnDataA, returnDataB, \"Call revert data does not match\");\n }\n\n if (!successA && successB) {\n emit log(\"Error: Calls were not equal\");\n emit log_named_bytes(\" Left call revert data\", returnDataA);\n emit log_named_bytes(\" Right call return data\", returnDataB);\n fail();\n }\n\n if (successA && !successB) {\n emit log(\"Error: Calls were not equal\");\n emit log_named_bytes(\" Left call return data\", returnDataA);\n emit log_named_bytes(\" Right call revert data\", returnDataB);\n fail();\n }\n }\n}\n" - }, - "node_modules/forge-std/src/StdChains.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n/**\n * StdChains provides information about EVM compatible chains that can be used in scripts/tests.\n * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are\n * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of\n * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the\n * alias used in this contract, which can be found as the first argument to the\n * `setChainWithDefaultRpcUrl` call in the `initialize` function.\n *\n * There are two main ways to use this contract:\n * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or\n * `setChain(string memory chainAlias, Chain memory chain)`\n * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.\n *\n * The first time either of those are used, chains are initialized with the default set of RPC URLs.\n * This is done in `initialize`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in\n * `defaultRpcUrls`.\n *\n * The `setChain` function is straightforward, and it simply saves off the given chain data.\n *\n * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say\n * we want to retrieve `mainnet`'s RPC URL:\n * - If you haven't set any mainnet chain info with `setChain`, you haven't specified that\n * chain in `foundry.toml` and no env var is set, the default data and RPC URL will be returned.\n * - If you have set a mainnet RPC URL in `foundry.toml` it will return that, if valid (e.g. if\n * a URL is given or if an environment variable is given and that environment variable exists).\n * Otherwise, the default data is returned.\n * - If you specified data with `setChain` it will return that.\n *\n * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults.\n */\nabstract contract StdChains {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private initialized;\n\n struct ChainData {\n string name;\n uint256 chainId;\n string rpcUrl;\n }\n\n struct Chain {\n // The chain name.\n string name;\n // The chain's Chain ID.\n uint256 chainId;\n // The chain's alias. (i.e. what gets specified in `foundry.toml`).\n string chainAlias;\n // A default RPC endpoint for this chain.\n // NOTE: This default RPC URL is included for convenience to facilitate quick tests and\n // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy\n // usage as you will be throttled and this is a disservice to others who need this endpoint.\n string rpcUrl;\n }\n\n // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.\n mapping(string => Chain) private chains;\n // Maps from the chain's alias to it's default RPC URL.\n mapping(string => string) private defaultRpcUrls;\n // Maps from a chain ID to it's alias.\n mapping(uint256 => string) private idToAlias;\n\n bool private fallbackToDefaultRpcUrls = true;\n\n // The RPC URL will be fetched from config or defaultRpcUrls if possible.\n function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {\n require(bytes(chainAlias).length != 0, \"StdChains getChain(string): Chain alias cannot be the empty string.\");\n\n initialize();\n chain = chains[chainAlias];\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(string): Chain with alias \\\"\", chainAlias, \"\\\" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {\n require(chainId != 0, \"StdChains getChain(uint256): Chain ID cannot be 0.\");\n initialize();\n string memory chainAlias = idToAlias[chainId];\n\n chain = chains[chainAlias];\n\n require(\n chain.chainId != 0,\n string(abi.encodePacked(\"StdChains getChain(uint256): Chain with ID \", vm.toString(chainId), \" not found.\"))\n );\n\n chain = getChainWithUpdatedRpcUrl(chainAlias, chain);\n }\n\n // set chain info, with priority to argument's rpcUrl field.\n function setChain(string memory chainAlias, ChainData memory chain) internal virtual {\n require(\n bytes(chainAlias).length != 0,\n \"StdChains setChain(string,ChainData): Chain alias cannot be the empty string.\"\n );\n\n require(chain.chainId != 0, \"StdChains setChain(string,ChainData): Chain ID cannot be 0.\");\n\n initialize();\n string memory foundAlias = idToAlias[chain.chainId];\n\n require(\n bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)),\n string(\n abi.encodePacked(\n \"StdChains setChain(string,ChainData): Chain ID \",\n vm.toString(chain.chainId),\n \" already used by \\\"\",\n foundAlias,\n \"\\\".\"\n )\n )\n );\n\n uint256 oldChainId = chains[chainAlias].chainId;\n delete idToAlias[oldChainId];\n\n chains[chainAlias] =\n Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});\n idToAlias[chain.chainId] = chainAlias;\n }\n\n // set chain info, with priority to argument's rpcUrl field.\n function setChain(string memory chainAlias, Chain memory chain) internal virtual {\n setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));\n }\n\n function _toUpper(string memory str) private pure returns (string memory) {\n bytes memory strb = bytes(str);\n bytes memory copy = new bytes(strb.length);\n for (uint256 i = 0; i < strb.length; i++) {\n bytes1 b = strb[i];\n if (b >= 0x61 && b <= 0x7A) {\n copy[i] = bytes1(uint8(b) - 32);\n } else {\n copy[i] = b;\n }\n }\n return string(copy);\n }\n\n // lookup rpcUrl, in descending order of priority:\n // current -> config (foundry.toml) -> environment variable -> default\n function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) private returns (Chain memory) {\n if (bytes(chain.rpcUrl).length == 0) {\n try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {\n chain.rpcUrl = configRpcUrl;\n } catch (bytes memory err) {\n string memory envName = string(abi.encodePacked(_toUpper(chainAlias), \"_RPC_URL\"));\n if (fallbackToDefaultRpcUrls) {\n chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]);\n } else {\n chain.rpcUrl = vm.envString(envName);\n }\n // distinguish 'not found' from 'cannot read'\n bytes memory notFoundError =\n abi.encodeWithSignature(\"CheatCodeError\", string(abi.encodePacked(\"invalid rpc url \", chainAlias)));\n if (keccak256(notFoundError) != keccak256(err) || bytes(chain.rpcUrl).length == 0) {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, err), mload(err))\n }\n }\n }\n }\n return chain;\n }\n\n function setFallbackToDefaultRpcUrls(bool useDefault) internal {\n fallbackToDefaultRpcUrls = useDefault;\n }\n\n function initialize() private {\n if (initialized) return;\n\n initialized = true;\n\n // If adding an RPC here, make sure to test the default RPC URL in `testRpcs`\n setChainWithDefaultRpcUrl(\"anvil\", ChainData(\"Anvil\", 31337, \"http://127.0.0.1:8545\"));\n setChainWithDefaultRpcUrl(\n \"mainnet\", ChainData(\"Mainnet\", 1, \"https://mainnet.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\n \"goerli\", ChainData(\"Goerli\", 5, \"https://goerli.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\n \"sepolia\", ChainData(\"Sepolia\", 11155111, \"https://sepolia.infura.io/v3/f4a0bdad42674adab5fc0ac077ffab2b\")\n );\n setChainWithDefaultRpcUrl(\"optimism\", ChainData(\"Optimism\", 10, \"https://mainnet.optimism.io\"));\n setChainWithDefaultRpcUrl(\"optimism_goerli\", ChainData(\"Optimism Goerli\", 420, \"https://goerli.optimism.io\"));\n setChainWithDefaultRpcUrl(\"arbitrum_one\", ChainData(\"Arbitrum One\", 42161, \"https://arb1.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\n \"arbitrum_one_goerli\", ChainData(\"Arbitrum One Goerli\", 421613, \"https://goerli-rollup.arbitrum.io/rpc\")\n );\n setChainWithDefaultRpcUrl(\"arbitrum_nova\", ChainData(\"Arbitrum Nova\", 42170, \"https://nova.arbitrum.io/rpc\"));\n setChainWithDefaultRpcUrl(\"polygon\", ChainData(\"Polygon\", 137, \"https://polygon-rpc.com\"));\n setChainWithDefaultRpcUrl(\n \"polygon_mumbai\", ChainData(\"Polygon Mumbai\", 80001, \"https://rpc-mumbai.maticvigil.com\")\n );\n setChainWithDefaultRpcUrl(\"avalanche\", ChainData(\"Avalanche\", 43114, \"https://api.avax.network/ext/bc/C/rpc\"));\n setChainWithDefaultRpcUrl(\n \"avalanche_fuji\", ChainData(\"Avalanche Fuji\", 43113, \"https://api.avax-test.network/ext/bc/C/rpc\")\n );\n setChainWithDefaultRpcUrl(\n \"bnb_smart_chain\", ChainData(\"BNB Smart Chain\", 56, \"https://bsc-dataseed1.binance.org\")\n );\n setChainWithDefaultRpcUrl(\n \"bnb_smart_chain_testnet\",\n ChainData(\"BNB Smart Chain Testnet\", 97, \"https://rpc.ankr.com/bsc_testnet_chapel\")\n );\n setChainWithDefaultRpcUrl(\"gnosis_chain\", ChainData(\"Gnosis Chain\", 100, \"https://rpc.gnosischain.com\"));\n }\n\n // set chain info, with priority to chainAlias' rpc url in foundry.toml\n function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {\n string memory rpcUrl = chain.rpcUrl;\n defaultRpcUrls[chainAlias] = rpcUrl;\n chain.rpcUrl = \"\";\n setChain(chainAlias, chain);\n chain.rpcUrl = rpcUrl; // restore argument\n }\n}\n" - }, - "node_modules/forge-std/src/StdCheats.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {Vm} from \"./Vm.sol\";\n\nabstract contract StdCheatsSafe {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n bool private gasMeteringOff;\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawTx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n // json value name = function\n string functionSig;\n bytes32 hash;\n // json value name = tx\n RawTx1559Detail txDetail;\n // json value name = type\n string opcode;\n }\n\n struct RawTx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n bytes gas;\n bytes nonce;\n address to;\n bytes txType;\n bytes value;\n }\n\n struct Tx1559 {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n bytes32 hash;\n Tx1559Detail txDetail;\n string opcode;\n }\n\n struct Tx1559Detail {\n AccessList[] accessList;\n bytes data;\n address from;\n uint256 gas;\n uint256 nonce;\n address to;\n uint256 txType;\n uint256 value;\n }\n\n // Data structures to parse Transaction objects from the broadcast artifact\n // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct TxLegacy {\n string[] arguments;\n address contractAddress;\n string contractName;\n string functionSig;\n string hash;\n string opcode;\n TxDetailLegacy transaction;\n }\n\n struct TxDetailLegacy {\n AccessList[] accessList;\n uint256 chainId;\n bytes data;\n address from;\n uint256 gas;\n uint256 gasPrice;\n bytes32 hash;\n uint256 nonce;\n bytes1 opcode;\n bytes32 r;\n bytes32 s;\n uint256 txType;\n address to;\n uint8 v;\n uint256 value;\n }\n\n struct AccessList {\n address accessAddress;\n bytes32[] storageKeys;\n }\n\n // Data structures to parse Receipt objects from the broadcast artifact.\n // The Raw structs is what is parsed from the JSON\n // and then converted to the one that is used by the user for better UX.\n\n struct RawReceipt {\n bytes32 blockHash;\n bytes blockNumber;\n address contractAddress;\n bytes cumulativeGasUsed;\n bytes effectiveGasPrice;\n address from;\n bytes gasUsed;\n RawReceiptLog[] logs;\n bytes logsBloom;\n bytes status;\n address to;\n bytes32 transactionHash;\n bytes transactionIndex;\n }\n\n struct Receipt {\n bytes32 blockHash;\n uint256 blockNumber;\n address contractAddress;\n uint256 cumulativeGasUsed;\n uint256 effectiveGasPrice;\n address from;\n uint256 gasUsed;\n ReceiptLog[] logs;\n bytes logsBloom;\n uint256 status;\n address to;\n bytes32 transactionHash;\n uint256 transactionIndex;\n }\n\n // Data structures to parse the entire broadcast artifact, assuming the\n // transactions conform to EIP1559.\n\n struct EIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n Receipt[] receipts;\n uint256 timestamp;\n Tx1559[] transactions;\n TxReturn[] txReturns;\n }\n\n struct RawEIP1559ScriptArtifact {\n string[] libraries;\n string path;\n string[] pending;\n RawReceipt[] receipts;\n TxReturn[] txReturns;\n uint256 timestamp;\n RawTx1559[] transactions;\n }\n\n struct RawReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n bytes blockNumber;\n bytes data;\n bytes logIndex;\n bool removed;\n bytes32[] topics;\n bytes32 transactionHash;\n bytes transactionIndex;\n bytes transactionLogIndex;\n }\n\n struct ReceiptLog {\n // json value = address\n address logAddress;\n bytes32 blockHash;\n uint256 blockNumber;\n bytes data;\n uint256 logIndex;\n bytes32[] topics;\n uint256 transactionIndex;\n uint256 transactionLogIndex;\n bool removed;\n }\n\n struct TxReturn {\n string internalType;\n string value;\n }\n\n function assumeNoPrecompiles(address addr) internal virtual {\n // Assembly required since `block.chainid` was introduced in 0.8.0.\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n assumeNoPrecompiles(addr, chainId);\n }\n\n function assumeNoPrecompiles(address addr, uint256 chainId) internal pure virtual {\n // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific\n // address), but the same rationale for excluding them applies so we include those too.\n\n // These should be present on all EVM-compatible chains.\n vm.assume(addr < address(0x1) || addr > address(0x9));\n\n // forgefmt: disable-start\n if (chainId == 10 || chainId == 420) {\n // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21\n vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));\n } else if (chainId == 42161 || chainId == 421613) {\n // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains\n vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));\n } else if (chainId == 43114 || chainId == 43113) {\n // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59\n vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));\n vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));\n vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));\n }\n // forgefmt: disable-end\n }\n\n function readEIP1559ScriptArtifact(string memory path)\n internal\n view\n virtual\n returns (EIP1559ScriptArtifact memory)\n {\n string memory data = vm.readFile(path);\n bytes memory parsedData = vm.parseJson(data);\n RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));\n EIP1559ScriptArtifact memory artifact;\n artifact.libraries = rawArtifact.libraries;\n artifact.path = rawArtifact.path;\n artifact.timestamp = rawArtifact.timestamp;\n artifact.pending = rawArtifact.pending;\n artifact.txReturns = rawArtifact.txReturns;\n artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);\n artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);\n return artifact;\n }\n\n function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {\n Tx1559[] memory txs = new Tx1559[](rawTxs.length);\n for (uint256 i; i < rawTxs.length; i++) {\n txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);\n }\n return txs;\n }\n\n function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {\n Tx1559 memory transaction;\n transaction.arguments = rawTx.arguments;\n transaction.contractName = rawTx.contractName;\n transaction.functionSig = rawTx.functionSig;\n transaction.hash = rawTx.hash;\n transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);\n transaction.opcode = rawTx.opcode;\n return transaction;\n }\n\n function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)\n internal\n pure\n virtual\n returns (Tx1559Detail memory)\n {\n Tx1559Detail memory txDetail;\n txDetail.data = rawDetail.data;\n txDetail.from = rawDetail.from;\n txDetail.to = rawDetail.to;\n txDetail.nonce = _bytesToUint(rawDetail.nonce);\n txDetail.txType = _bytesToUint(rawDetail.txType);\n txDetail.value = _bytesToUint(rawDetail.value);\n txDetail.gas = _bytesToUint(rawDetail.gas);\n txDetail.accessList = rawDetail.accessList;\n return txDetail;\n }\n\n function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".transactions\");\n RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));\n return rawToConvertedEIPTx1559s(rawTxs);\n }\n\n function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".transactions[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));\n return rawToConvertedEIPTx1559(rawTx);\n }\n\n // Analogous to readTransactions, but for receipts.\n function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {\n string memory deployData = vm.readFile(path);\n bytes memory parsedDeployData = vm.parseJson(deployData, \".receipts\");\n RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));\n return rawToConvertedReceipts(rawReceipts);\n }\n\n function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {\n string memory deployData = vm.readFile(path);\n string memory key = string(abi.encodePacked(\".receipts[\", vm.toString(index), \"]\"));\n bytes memory parsedDeployData = vm.parseJson(deployData, key);\n RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));\n return rawToConvertedReceipt(rawReceipt);\n }\n\n function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {\n Receipt[] memory receipts = new Receipt[](rawReceipts.length);\n for (uint256 i; i < rawReceipts.length; i++) {\n receipts[i] = rawToConvertedReceipt(rawReceipts[i]);\n }\n return receipts;\n }\n\n function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {\n Receipt memory receipt;\n receipt.blockHash = rawReceipt.blockHash;\n receipt.to = rawReceipt.to;\n receipt.from = rawReceipt.from;\n receipt.contractAddress = rawReceipt.contractAddress;\n receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);\n receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);\n receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);\n receipt.status = _bytesToUint(rawReceipt.status);\n receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);\n receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);\n receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);\n receipt.logsBloom = rawReceipt.logsBloom;\n receipt.transactionHash = rawReceipt.transactionHash;\n return receipt;\n }\n\n function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)\n internal\n pure\n virtual\n returns (ReceiptLog[] memory)\n {\n ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);\n for (uint256 i; i < rawLogs.length; i++) {\n logs[i].logAddress = rawLogs[i].logAddress;\n logs[i].blockHash = rawLogs[i].blockHash;\n logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);\n logs[i].data = rawLogs[i].data;\n logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);\n logs[i].topics = rawLogs[i].topics;\n logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);\n logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);\n logs[i].removed = rawLogs[i].removed;\n }\n return logs;\n }\n\n // Deploy a contract by fetching the contract bytecode from\n // the artifacts directory\n // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`\n function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes): Deployment failed.\");\n }\n\n function deployCode(string memory what) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(0, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string): Deployment failed.\");\n }\n\n /// @dev deploy contract with value on construction\n function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,bytes,uint256): Deployment failed.\");\n }\n\n function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {\n bytes memory bytecode = vm.getCode(what);\n /// @solidity memory-safe-assembly\n assembly {\n addr := create(val, add(bytecode, 0x20), mload(bytecode))\n }\n\n require(addr != address(0), \"StdCheats deployCode(string,uint256): Deployment failed.\");\n }\n\n // creates a labeled address and the corresponding private key\n function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {\n privateKey = uint256(keccak256(abi.encodePacked(name)));\n addr = vm.addr(privateKey);\n vm.label(addr, name);\n }\n\n // creates a labeled address\n function makeAddr(string memory name) internal virtual returns (address addr) {\n (addr,) = makeAddrAndKey(name);\n }\n\n function deriveRememberKey(string memory mnemonic, uint32 index)\n internal\n virtual\n returns (address who, uint256 privateKey)\n {\n privateKey = vm.deriveKey(mnemonic, index);\n who = vm.rememberKey(privateKey);\n }\n\n function _bytesToUint(bytes memory b) private pure returns (uint256) {\n require(b.length <= 32, \"StdCheats _bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n function isFork() internal view virtual returns (bool status) {\n try vm.activeFork() {\n status = true;\n } catch (bytes memory) {}\n }\n\n modifier skipWhenForking() {\n if (!isFork()) {\n _;\n }\n }\n\n modifier skipWhenNotForking() {\n if (isFork()) {\n _;\n }\n }\n\n modifier noGasMetering() {\n vm.pauseGasMetering();\n // To prevent turning gas monitoring back on with nested functions that use this modifier,\n // we check if gasMetering started in the off position. If it did, we don't want to turn\n // it back on until we exit the top level function that used the modifier\n //\n // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.\n // funcA will have `gasStartedOff` as false, funcB will have it as true,\n // so we only turn metering back on at the end of the funcA\n bool gasStartedOff = gasMeteringOff;\n gasMeteringOff = true;\n\n _;\n\n // if gas metering was on when this modifier was called, turn it back on at the end\n if (!gasStartedOff) {\n gasMeteringOff = false;\n vm.resumeGasMetering();\n }\n }\n\n // a cheat for fuzzing addresses that are payable only\n // see https://github.com/foundry-rs/foundry/issues/3631\n function assumePayable(address addr) internal virtual {\n (bool success,) = payable(addr).call{value: 0}(\"\");\n vm.assume(success);\n }\n}\n\n// Wrappers around cheatcodes to avoid footguns\nabstract contract StdCheats is StdCheatsSafe {\n using stdStorage for StdStorage;\n\n StdStorage private stdstore;\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n // Skip forward or rewind time by the specified number of seconds\n function skip(uint256 time) internal virtual {\n vm.warp(block.timestamp + time);\n }\n\n function rewind(uint256 time) internal virtual {\n vm.warp(block.timestamp - time);\n }\n\n // Setup a prank from an address that has some ether\n function hoax(address msgSender) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.prank(msgSender);\n }\n\n function hoax(address msgSender, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.prank(msgSender);\n }\n\n function hoax(address msgSender, address origin) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.prank(msgSender, origin);\n }\n\n function hoax(address msgSender, address origin, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.prank(msgSender, origin);\n }\n\n // Start perpetual prank from an address that has some ether\n function startHoax(address msgSender) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.startPrank(msgSender);\n }\n\n function startHoax(address msgSender, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.startPrank(msgSender);\n }\n\n // Start perpetual prank from an address that has some ether\n // tx.origin is set to the origin parameter\n function startHoax(address msgSender, address origin) internal virtual {\n vm.deal(msgSender, 1 << 128);\n vm.startPrank(msgSender, origin);\n }\n\n function startHoax(address msgSender, address origin, uint256 give) internal virtual {\n vm.deal(msgSender, give);\n vm.startPrank(msgSender, origin);\n }\n\n function changePrank(address msgSender) internal virtual {\n vm.stopPrank();\n vm.startPrank(msgSender);\n }\n\n function changePrank(address msgSender, address txOrigin) internal virtual {\n vm.stopPrank();\n vm.startPrank(msgSender, txOrigin);\n }\n\n // The same as Vm's `deal`\n // Use the alternative signature for ERC20 tokens\n function deal(address to, uint256 give) internal virtual {\n vm.deal(to, give);\n }\n\n // Set the balance of an account for any ERC20 token\n // Use the alternative signature to update `totalSupply`\n function deal(address token, address to, uint256 give) internal virtual {\n deal(token, to, give, false);\n }\n\n // Set the balance of an account for any ERC1155 token\n // Use the alternative signature to update `totalSupply`\n function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {\n dealERC1155(token, to, id, give, false);\n }\n\n function deal(address token, address to, uint256 give, bool adjust) internal virtual {\n // get current balance\n (, bytes memory balData) = token.call(abi.encodeWithSelector(0x70a08231, to));\n uint256 prevBal = abi.decode(balData, (uint256));\n\n // update balance\n stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);\n\n // update total supply\n if (adjust) {\n (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0x18160ddd));\n uint256 totSup = abi.decode(totSupData, (uint256));\n if (give < prevBal) {\n totSup -= (prevBal - give);\n } else {\n totSup += (give - prevBal);\n }\n stdstore.target(token).sig(0x18160ddd).checked_write(totSup);\n }\n }\n\n function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {\n // get current balance\n (, bytes memory balData) = token.call(abi.encodeWithSelector(0x00fdd58e, to, id));\n uint256 prevBal = abi.decode(balData, (uint256));\n\n // update balance\n stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);\n\n // update total supply\n if (adjust) {\n (, bytes memory totSupData) = token.call(abi.encodeWithSelector(0xbd85b039, id));\n require(\n totSupData.length != 0,\n \"StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply.\"\n );\n uint256 totSup = abi.decode(totSupData, (uint256));\n if (give < prevBal) {\n totSup -= (prevBal - give);\n } else {\n totSup += (give - prevBal);\n }\n stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);\n }\n }\n\n function dealERC721(address token, address to, uint256 id) internal virtual {\n // check if token id is already minted and the actual owner.\n (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));\n require(successMinted, \"StdCheats deal(address,address,uint,bool): id not minted.\");\n\n // get owner current balance\n (, bytes memory fromBalData) = token.call(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));\n uint256 fromPrevBal = abi.decode(fromBalData, (uint256));\n\n // get new user current balance\n (, bytes memory toBalData) = token.call(abi.encodeWithSelector(0x70a08231, to));\n uint256 toPrevBal = abi.decode(toBalData, (uint256));\n\n // update balances\n stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);\n stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);\n\n // update owner\n stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);\n }\n}\n" - }, - "node_modules/forge-std/src/StdError.sol": { - "content": "// SPDX-License-Identifier: MIT\n// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdError {\n bytes public constant assertionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x01);\n bytes public constant arithmeticError = abi.encodeWithSignature(\"Panic(uint256)\", 0x11);\n bytes public constant divisionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x12);\n bytes public constant enumConversionError = abi.encodeWithSignature(\"Panic(uint256)\", 0x21);\n bytes public constant encodeStorageError = abi.encodeWithSignature(\"Panic(uint256)\", 0x22);\n bytes public constant popError = abi.encodeWithSignature(\"Panic(uint256)\", 0x31);\n bytes public constant indexOOBError = abi.encodeWithSignature(\"Panic(uint256)\", 0x32);\n bytes public constant memOverflowError = abi.encodeWithSignature(\"Panic(uint256)\", 0x41);\n bytes public constant zeroVarError = abi.encodeWithSignature(\"Panic(uint256)\", 0x51);\n}\n" - }, - "node_modules/forge-std/src/StdInvariant.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\ncontract StdInvariant {\n struct FuzzSelector {\n address addr;\n bytes4[] selectors;\n }\n\n address[] private _excludedContracts;\n address[] private _excludedSenders;\n address[] private _targetedContracts;\n address[] private _targetedSenders;\n\n string[] private _excludedArtifacts;\n string[] private _targetedArtifacts;\n\n FuzzSelector[] private _targetedArtifactSelectors;\n FuzzSelector[] private _targetedSelectors;\n\n // Functions for users:\n // These are intended to be called in tests.\n\n function excludeContract(address newExcludedContract_) internal {\n _excludedContracts.push(newExcludedContract_);\n }\n\n function excludeSender(address newExcludedSender_) internal {\n _excludedSenders.push(newExcludedSender_);\n }\n\n function excludeArtifact(string memory newExcludedArtifact_) internal {\n _excludedArtifacts.push(newExcludedArtifact_);\n }\n\n function targetArtifact(string memory newTargetedArtifact_) internal {\n _targetedArtifacts.push(newTargetedArtifact_);\n }\n\n function targetArtifactSelector(FuzzSelector memory newTargetedArtifactSelector_) internal {\n _targetedArtifactSelectors.push(newTargetedArtifactSelector_);\n }\n\n function targetContract(address newTargetedContract_) internal {\n _targetedContracts.push(newTargetedContract_);\n }\n\n function targetSelector(FuzzSelector memory newTargetedSelector_) internal {\n _targetedSelectors.push(newTargetedSelector_);\n }\n\n function targetSender(address newTargetedSender_) internal {\n _targetedSenders.push(newTargetedSender_);\n }\n\n // Functions for forge:\n // These are called by forge to run invariant tests and don't need to be called in tests.\n\n function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) {\n excludedArtifacts_ = _excludedArtifacts;\n }\n\n function excludeContracts() public view returns (address[] memory excludedContracts_) {\n excludedContracts_ = _excludedContracts;\n }\n\n function excludeSenders() public view returns (address[] memory excludedSenders_) {\n excludedSenders_ = _excludedSenders;\n }\n\n function targetArtifacts() public view returns (string[] memory targetedArtifacts_) {\n targetedArtifacts_ = _targetedArtifacts;\n }\n\n function targetArtifactSelectors() public view returns (FuzzSelector[] memory targetedArtifactSelectors_) {\n targetedArtifactSelectors_ = _targetedArtifactSelectors;\n }\n\n function targetContracts() public view returns (address[] memory targetedContracts_) {\n targetedContracts_ = _targetedContracts;\n }\n\n function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) {\n targetedSelectors_ = _targetedSelectors;\n }\n\n function targetSenders() public view returns (address[] memory targetedSenders_) {\n targetedSenders_ = _targetedSenders;\n }\n}\n" - }, - "node_modules/forge-std/src/StdJson.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {VmSafe} from \"./Vm.sol\";\n\n// Helpers for parsing and writing JSON files\n// To parse:\n// ```\n// using stdJson for string;\n// string memory json = vm.readFile(\"some_peth\");\n// json.parseUint(\"\");\n// ```\n// To write:\n// ```\n// using stdJson for string;\n// string memory json = \"deploymentArtifact\";\n// Contract contract = new Contract();\n// json.serialize(\"contractAddress\", address(contract));\n// json = json.serialize(\"deploymentTimes\", uint(1));\n// // store the stringified JSON to the 'json' variable we have been using as a key\n// // as we won't need it any longer\n// string memory json2 = \"finalArtifact\";\n// string memory final = json2.serialize(\"depArtifact\", json);\n// final.write(\"\");\n// ```\n\nlibrary stdJson {\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {\n return vm.parseJson(json, key);\n }\n\n function readUint(string memory json, string memory key) internal returns (uint256) {\n return vm.parseJsonUint(json, key);\n }\n\n function readUintArray(string memory json, string memory key) internal returns (uint256[] memory) {\n return vm.parseJsonUintArray(json, key);\n }\n\n function readInt(string memory json, string memory key) internal returns (int256) {\n return vm.parseJsonInt(json, key);\n }\n\n function readIntArray(string memory json, string memory key) internal returns (int256[] memory) {\n return vm.parseJsonIntArray(json, key);\n }\n\n function readBytes32(string memory json, string memory key) internal returns (bytes32) {\n return vm.parseJsonBytes32(json, key);\n }\n\n function readBytes32Array(string memory json, string memory key) internal returns (bytes32[] memory) {\n return vm.parseJsonBytes32Array(json, key);\n }\n\n function readString(string memory json, string memory key) internal returns (string memory) {\n return vm.parseJsonString(json, key);\n }\n\n function readStringArray(string memory json, string memory key) internal returns (string[] memory) {\n return vm.parseJsonStringArray(json, key);\n }\n\n function readAddress(string memory json, string memory key) internal returns (address) {\n return vm.parseJsonAddress(json, key);\n }\n\n function readAddressArray(string memory json, string memory key) internal returns (address[] memory) {\n return vm.parseJsonAddressArray(json, key);\n }\n\n function readBool(string memory json, string memory key) internal returns (bool) {\n return vm.parseJsonBool(json, key);\n }\n\n function readBoolArray(string memory json, string memory key) internal returns (bool[] memory) {\n return vm.parseJsonBoolArray(json, key);\n }\n\n function readBytes(string memory json, string memory key) internal returns (bytes memory) {\n return vm.parseJsonBytes(json, key);\n }\n\n function readBytesArray(string memory json, string memory key) internal returns (bytes[] memory) {\n return vm.parseJsonBytesArray(json, key);\n }\n\n function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bool[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBool(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, uint256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeUint(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, int256[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeInt(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, address[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeAddress(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes32[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes32(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, bytes[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeBytes(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function serialize(string memory jsonKey, string memory key, string[] memory value)\n internal\n returns (string memory)\n {\n return vm.serializeString(jsonKey, key, value);\n }\n\n function write(string memory jsonKey, string memory path) internal {\n vm.writeJson(jsonKey, path);\n }\n\n function write(string memory jsonKey, string memory path, string memory valueKey) internal {\n vm.writeJson(jsonKey, path, valueKey);\n }\n}\n" - }, - "node_modules/forge-std/src/StdMath.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nlibrary stdMath {\n int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;\n\n function abs(int256 a) internal pure returns (uint256) {\n // Required or it will fail when `a = type(int256).min`\n if (a == INT256_MIN) {\n return 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n }\n\n return uint256(a > 0 ? a : -a);\n }\n\n function delta(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a - b : b - a;\n }\n\n function delta(int256 a, int256 b) internal pure returns (uint256) {\n // a and b are of the same sign\n // this works thanks to two's complement, the left-most bit is the sign bit\n if ((a ^ b) > -1) {\n return delta(abs(a), abs(b));\n }\n\n // a and b are of opposite signs\n return abs(a) + abs(b);\n }\n\n function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n\n return absDelta * 1e18 / b;\n }\n\n function percentDelta(int256 a, int256 b) internal pure returns (uint256) {\n uint256 absDelta = delta(a, b);\n uint256 absB = abs(b);\n\n return absDelta * 1e18 / absB;\n }\n}\n" - }, - "node_modules/forge-std/src/StdStorage.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\nimport {Vm} from \"./Vm.sol\";\n\nstruct StdStorage {\n mapping(address => mapping(bytes4 => mapping(bytes32 => uint256))) slots;\n mapping(address => mapping(bytes4 => mapping(bytes32 => bool))) finds;\n bytes32[] _keys;\n bytes4 _sig;\n uint256 _depth;\n address _target;\n bytes32 _set;\n}\n\nlibrary stdStorageSafe {\n event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);\n event WARNING_UninitedSlot(address who, uint256 slot);\n\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return bytes4(keccak256(bytes(sigStr)));\n }\n\n /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against\n // slot complexity:\n // if flat, will be bytes32(uint256(uint));\n // if map, will be keccak256(abi.encode(key, uint(slot)));\n // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));\n // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);\n function find(StdStorage storage self) internal returns (uint256) {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n // calldata to test against\n if (self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n vm.record();\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n (bytes32[] memory reads,) = vm.accesses(address(who));\n if (reads.length == 1) {\n bytes32 curr = vm.load(who, reads[0]);\n if (curr == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[0]));\n }\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[0]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[0]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n } else if (reads.length > 1) {\n for (uint256 i = 0; i < reads.length; i++) {\n bytes32 prev = vm.load(who, reads[i]);\n if (prev == bytes32(0)) {\n emit WARNING_UninitedSlot(who, uint256(reads[i]));\n }\n // store\n vm.store(who, reads[i], bytes32(hex\"1337\"));\n bool success;\n bytes memory rdat;\n {\n (success, rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n\n if (success && fdat == bytes32(hex\"1337\")) {\n // we found which of the slots is the actual one\n emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[i]));\n self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = uint256(reads[i]);\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] = true;\n vm.store(who, reads[i], prev);\n break;\n }\n vm.store(who, reads[i], prev);\n }\n } else {\n revert(\"stdStorage find(StdStorage): No storage use detected for target.\");\n }\n\n require(\n self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))],\n \"stdStorage find(StdStorage): Slot(s) not found.\"\n );\n\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n\n return self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n self._target = _target;\n return self;\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n self._sig = _sig;\n return self;\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n self._sig = sigs(_sig);\n return self;\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n self._keys.push(bytes32(uint256(uint160(who))));\n return self;\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n self._keys.push(bytes32(amt));\n return self;\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n self._keys.push(key);\n return self;\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n self._depth = _depth;\n return self;\n }\n\n function read(StdStorage storage self) private returns (bytes memory) {\n address t = self._target;\n uint256 s = find(self);\n return abi.encode(vm.load(t, bytes32(s)));\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return abi.decode(read(self), (bytes32));\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n int256 v = read_int(self);\n if (v == 0) return false;\n if (v == 1) return true;\n revert(\"stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.\");\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return abi.decode(read(self), (address));\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return abi.decode(read(self), (uint256));\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return abi.decode(read(self), (int256));\n }\n\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n\nlibrary stdStorage {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n function sigs(string memory sigStr) internal pure returns (bytes4) {\n return stdStorageSafe.sigs(sigStr);\n }\n\n function find(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.find(self);\n }\n\n function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {\n return stdStorageSafe.target(self, _target);\n }\n\n function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {\n return stdStorageSafe.sig(self, _sig);\n }\n\n function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, who);\n }\n\n function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, amt);\n }\n\n function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {\n return stdStorageSafe.with_key(self, key);\n }\n\n function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {\n return stdStorageSafe.depth(self, _depth);\n }\n\n function checked_write(StdStorage storage self, address who) internal {\n checked_write(self, bytes32(uint256(uint160(who))));\n }\n\n function checked_write(StdStorage storage self, uint256 amt) internal {\n checked_write(self, bytes32(amt));\n }\n\n function checked_write(StdStorage storage self, bool write) internal {\n bytes32 t;\n /// @solidity memory-safe-assembly\n assembly {\n t := write\n }\n checked_write(self, t);\n }\n\n function checked_write(StdStorage storage self, bytes32 set) internal {\n address who = self._target;\n bytes4 fsig = self._sig;\n uint256 field_depth = self._depth;\n bytes32[] memory ins = self._keys;\n\n bytes memory cald = abi.encodePacked(fsig, flatten(ins));\n if (!self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {\n find(self);\n }\n bytes32 slot = bytes32(self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]);\n\n bytes32 fdat;\n {\n (, bytes memory rdat) = who.staticcall(cald);\n fdat = bytesToBytes32(rdat, 32 * field_depth);\n }\n bytes32 curr = vm.load(who, slot);\n\n if (fdat != curr) {\n require(\n false,\n \"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported.\"\n );\n }\n vm.store(who, slot, set);\n delete self._target;\n delete self._sig;\n delete self._keys;\n delete self._depth;\n }\n\n function read_bytes32(StdStorage storage self) internal returns (bytes32) {\n return stdStorageSafe.read_bytes32(self);\n }\n\n function read_bool(StdStorage storage self) internal returns (bool) {\n return stdStorageSafe.read_bool(self);\n }\n\n function read_address(StdStorage storage self) internal returns (address) {\n return stdStorageSafe.read_address(self);\n }\n\n function read_uint(StdStorage storage self) internal returns (uint256) {\n return stdStorageSafe.read_uint(self);\n }\n\n function read_int(StdStorage storage self) internal returns (int256) {\n return stdStorageSafe.read_int(self);\n }\n\n // Private function so needs to be copied over\n function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {\n bytes32 out;\n\n uint256 max = b.length > 32 ? 32 : b.length;\n for (uint256 i = 0; i < max; i++) {\n out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);\n }\n return out;\n }\n\n // Private function so needs to be copied over\n function flatten(bytes32[] memory b) private pure returns (bytes memory) {\n bytes memory result = new bytes(b.length * 32);\n for (uint256 i = 0; i < b.length; i++) {\n bytes32 k = b[i];\n /// @solidity memory-safe-assembly\n assembly {\n mstore(add(result, add(32, mul(32, i))), k)\n }\n }\n\n return result;\n }\n}\n" - }, - "node_modules/forge-std/src/StdStyle.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nimport {Vm} from \"./Vm.sol\";\n\nlibrary StdStyle {\n Vm private constant vm = Vm(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n\n string constant RED = \"\\u001b[91m\";\n string constant GREEN = \"\\u001b[92m\";\n string constant YELLOW = \"\\u001b[93m\";\n string constant BLUE = \"\\u001b[94m\";\n string constant MAGENTA = \"\\u001b[95m\";\n string constant CYAN = \"\\u001b[96m\";\n string constant BOLD = \"\\u001b[1m\";\n string constant DIM = \"\\u001b[2m\";\n string constant ITALIC = \"\\u001b[3m\";\n string constant UNDERLINE = \"\\u001b[4m\";\n string constant INVERSE = \"\\u001b[7m\";\n string constant RESET = \"\\u001b[0m\";\n\n function styleConcat(string memory style, string memory self) private pure returns (string memory) {\n return string(abi.encodePacked(style, self, RESET));\n }\n\n function red(string memory self) internal pure returns (string memory) {\n return styleConcat(RED, self);\n }\n\n function red(uint256 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(int256 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(address self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function red(bool self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function redBytes(bytes memory self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function redBytes32(bytes32 self) internal pure returns (string memory) {\n return red(vm.toString(self));\n }\n\n function green(string memory self) internal pure returns (string memory) {\n return styleConcat(GREEN, self);\n }\n\n function green(uint256 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(int256 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(address self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function green(bool self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function greenBytes(bytes memory self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function greenBytes32(bytes32 self) internal pure returns (string memory) {\n return green(vm.toString(self));\n }\n\n function yellow(string memory self) internal pure returns (string memory) {\n return styleConcat(YELLOW, self);\n }\n\n function yellow(uint256 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(int256 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(address self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellow(bool self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellowBytes(bytes memory self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function yellowBytes32(bytes32 self) internal pure returns (string memory) {\n return yellow(vm.toString(self));\n }\n\n function blue(string memory self) internal pure returns (string memory) {\n return styleConcat(BLUE, self);\n }\n\n function blue(uint256 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(int256 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(address self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blue(bool self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blueBytes(bytes memory self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function blueBytes32(bytes32 self) internal pure returns (string memory) {\n return blue(vm.toString(self));\n }\n\n function magenta(string memory self) internal pure returns (string memory) {\n return styleConcat(MAGENTA, self);\n }\n\n function magenta(uint256 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(int256 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(address self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magenta(bool self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magentaBytes(bytes memory self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function magentaBytes32(bytes32 self) internal pure returns (string memory) {\n return magenta(vm.toString(self));\n }\n\n function cyan(string memory self) internal pure returns (string memory) {\n return styleConcat(CYAN, self);\n }\n\n function cyan(uint256 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(int256 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(address self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyan(bool self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyanBytes(bytes memory self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function cyanBytes32(bytes32 self) internal pure returns (string memory) {\n return cyan(vm.toString(self));\n }\n\n function bold(string memory self) internal pure returns (string memory) {\n return styleConcat(BOLD, self);\n }\n\n function bold(uint256 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(int256 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(address self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function bold(bool self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function boldBytes(bytes memory self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function boldBytes32(bytes32 self) internal pure returns (string memory) {\n return bold(vm.toString(self));\n }\n\n function dim(string memory self) internal pure returns (string memory) {\n return styleConcat(DIM, self);\n }\n\n function dim(uint256 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(int256 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(address self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dim(bool self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dimBytes(bytes memory self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function dimBytes32(bytes32 self) internal pure returns (string memory) {\n return dim(vm.toString(self));\n }\n\n function italic(string memory self) internal pure returns (string memory) {\n return styleConcat(ITALIC, self);\n }\n\n function italic(uint256 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(int256 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(address self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italic(bool self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italicBytes(bytes memory self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function italicBytes32(bytes32 self) internal pure returns (string memory) {\n return italic(vm.toString(self));\n }\n\n function underline(string memory self) internal pure returns (string memory) {\n return styleConcat(UNDERLINE, self);\n }\n\n function underline(uint256 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(int256 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(address self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underline(bool self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underlineBytes(bytes memory self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function underlineBytes32(bytes32 self) internal pure returns (string memory) {\n return underline(vm.toString(self));\n }\n\n function inverse(string memory self) internal pure returns (string memory) {\n return styleConcat(INVERSE, self);\n }\n\n function inverse(uint256 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(int256 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(address self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverse(bool self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverseBytes(bytes memory self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n\n function inverseBytes32(bytes32 self) internal pure returns (string memory) {\n return inverse(vm.toString(self));\n }\n}\n" - }, - "node_modules/forge-std/src/StdUtils.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport {IMulticall3} from \"./interfaces/IMulticall3.sol\";\n// TODO Remove import.\nimport {VmSafe} from \"./Vm.sol\";\n\nabstract contract StdUtils {\n /*//////////////////////////////////////////////////////////////////////////\n CONSTANTS\n //////////////////////////////////////////////////////////////////////////*/\n\n IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);\n VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256(\"hevm cheat code\")))));\n address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;\n uint256 private constant INT256_MIN_ABS =\n 57896044618658097711785492504343953926634992332820282019728792003956564819968;\n uint256 private constant UINT256_MAX =\n 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n\n // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.\n address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;\n\n /*//////////////////////////////////////////////////////////////////////////\n INTERNAL FUNCTIONS\n //////////////////////////////////////////////////////////////////////////*/\n\n function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {\n require(min <= max, \"StdUtils bound(uint256,uint256,uint256): Max is less than min.\");\n // If x is between min and max, return x directly. This is to ensure that dictionary values\n // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188\n if (x >= min && x <= max) return x;\n\n uint256 size = max - min + 1;\n\n // If the value is 0, 1, 2, 3, warp that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.\n // This helps ensure coverage of the min/max values.\n if (x <= 3 && size > x) return min + x;\n if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);\n\n // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.\n if (x > max) {\n uint256 diff = x - max;\n uint256 rem = diff % size;\n if (rem == 0) return max;\n result = min + rem - 1;\n } else if (x < min) {\n uint256 diff = min - x;\n uint256 rem = diff % size;\n if (rem == 0) return min;\n result = max - rem + 1;\n }\n }\n\n function bound(uint256 x, uint256 min, uint256 max) internal view virtual returns (uint256 result) {\n result = _bound(x, min, max);\n console2_log(\"Bound Result\", result);\n }\n\n function bound(int256 x, int256 min, int256 max) internal view virtual returns (int256 result) {\n require(min <= max, \"StdUtils bound(int256,int256,int256): Max is less than min.\");\n\n // Shifting all int256 values to uint256 to use _bound function. The range of two types are:\n // int256 : -(2**255) ~ (2**255 - 1)\n // uint256: 0 ~ (2**256 - 1)\n // So, add 2**255, INT256_MIN_ABS to the integer values.\n //\n // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.\n // So, use `~uint256(x) + 1` instead.\n uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);\n uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);\n uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);\n\n uint256 y = _bound(_x, _min, _max);\n\n // To move it back to int256 value, subtract INT256_MIN_ABS at here.\n result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);\n console2_log(\"Bound result\", vm.toString(result));\n }\n\n function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {\n require(b.length <= 32, \"StdUtils bytesToUint(bytes): Bytes length exceeds 32.\");\n return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));\n }\n\n /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce\n /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)\n function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {\n // forgefmt: disable-start\n // 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.\n // A one byte integer uses its own value as its length prefix, there is no additional \"0x80 + length\" prefix that comes before it.\n if (nonce == 0x00) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80))));\n if (nonce <= 0x7f) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce))));\n\n // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length.\n if (nonce <= 2**8 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce))));\n if (nonce <= 2**16 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce))));\n if (nonce <= 2**24 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce))));\n // forgefmt: disable-end\n\n // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp\n // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce)\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex)\n // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex)\n // We assume nobody can have a nonce large enough to require more than 32 bytes.\n return addressFromLast20Bytes(\n keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce)))\n );\n }\n\n function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)\n internal\n pure\n virtual\n returns (address)\n {\n return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, initcodeHash)));\n }\n\n /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer\n function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {\n return computeCreate2Address(salt, initCodeHash, CREATE2_FACTORY);\n }\n\n /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments\n /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode\n function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {\n return hashInitCode(creationCode, \"\");\n }\n\n /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2\n /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode\n /// @param args the ABI-encoded arguments to the constructor of C\n function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(creationCode, args));\n }\n\n // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.\n function getTokenBalances(address token, address[] memory addresses)\n internal\n virtual\n returns (uint256[] memory balances)\n {\n uint256 tokenCodeSize;\n assembly {\n tokenCodeSize := extcodesize(token)\n }\n require(tokenCodeSize > 0, \"StdUtils getTokenBalances(address,address[]): Token address is not a contract.\");\n\n // ABI encode the aggregate call to Multicall3.\n uint256 length = addresses.length;\n IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);\n for (uint256 i = 0; i < length; ++i) {\n // 0x70a08231 = bytes4(\"balanceOf(address)\"))\n calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});\n }\n\n // Make the aggregate call.\n (, bytes[] memory returnData) = multicall.aggregate(calls);\n\n // ABI decode the return data and return the balances.\n balances = new uint256[](length);\n for (uint256 i = 0; i < length; ++i) {\n balances[i] = abi.decode(returnData[i], (uint256));\n }\n }\n\n /*//////////////////////////////////////////////////////////////////////////\n PRIVATE FUNCTIONS\n //////////////////////////////////////////////////////////////////////////*/\n\n function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {\n return address(uint160(uint256(bytesValue)));\n }\n\n // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.\n\n function console2_log(string memory p0, uint256 p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n status;\n }\n\n function console2_log(string memory p0, string memory p1) private view {\n (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n status;\n }\n}\n" - }, - "node_modules/forge-std/src/Test.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\n// 💬 ABOUT\n// Standard Library's default Test\n\n// 🧩 MODULES\nimport {console} from \"./console.sol\";\nimport {console2} from \"./console2.sol\";\nimport {StdAssertions} from \"./StdAssertions.sol\";\nimport {StdChains} from \"./StdChains.sol\";\nimport {StdCheats} from \"./StdCheats.sol\";\nimport {stdError} from \"./StdError.sol\";\nimport {StdInvariant} from \"./StdInvariant.sol\";\nimport {stdJson} from \"./StdJson.sol\";\nimport {stdMath} from \"./StdMath.sol\";\nimport {StdStorage, stdStorage} from \"./StdStorage.sol\";\nimport {StdUtils} from \"./StdUtils.sol\";\nimport {Vm} from \"./Vm.sol\";\nimport {StdStyle} from \"./StdStyle.sol\";\n\n// 📦 BOILERPLATE\nimport {TestBase} from \"./Base.sol\";\nimport {DSTest} from \"ds-test/test.sol\";\n\n// ⭐️ TEST\nabstract contract Test is DSTest, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils, TestBase {\n// Note: IS_TEST() must return true.\n// Note: Must have failure system, https://github.com/dapphub/ds-test/blob/cd98eff28324bfac652e63a239a60632a761790b/src/test.sol#L39-L76.\n}\n" - }, - "node_modules/forge-std/src/Vm.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\n// Cheatcodes are marked as view/pure/none using the following rules:\n// 0. A call's observable behaviour includes its return value, logs, reverts and state writes,\n// 1. If you can influence a later call's observable behaviour, you're neither `view` nor `pure (you are modifying some state be it the EVM, interpreter, filesystem, etc),\n// 2. Otherwise if you can be influenced by an earlier call, or if reading some state, you're `view`,\n// 3. Otherwise you're `pure`.\n\ninterface VmSafe {\n struct Log {\n bytes32[] topics;\n bytes data;\n address emitter;\n }\n\n struct Rpc {\n string key;\n string url;\n }\n\n struct FsMetadata {\n bool isDir;\n bool isSymlink;\n uint256 length;\n bool readOnly;\n uint256 modified;\n uint256 accessed;\n uint256 created;\n }\n\n // Loads a storage slot from an address\n function load(address target, bytes32 slot) external view returns (bytes32 data);\n // Signs data\n function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);\n // Gets the address for a given private key\n function addr(uint256 privateKey) external pure returns (address keyAddr);\n // Gets the nonce of an account\n function getNonce(address account) external view returns (uint64 nonce);\n // Performs a foreign function call via the terminal\n function ffi(string[] calldata commandInput) external returns (bytes memory result);\n // Sets environment variables\n function setEnv(string calldata name, string calldata value) external;\n // Reads environment variables, (name) => (value)\n function envBool(string calldata name) external view returns (bool value);\n function envUint(string calldata name) external view returns (uint256 value);\n function envInt(string calldata name) external view returns (int256 value);\n function envAddress(string calldata name) external view returns (address value);\n function envBytes32(string calldata name) external view returns (bytes32 value);\n function envString(string calldata name) external view returns (string memory value);\n function envBytes(string calldata name) external view returns (bytes memory value);\n // Reads environment variables as arrays\n function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);\n function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);\n function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);\n function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);\n function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);\n function envString(string calldata name, string calldata delim) external view returns (string[] memory value);\n function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);\n // Read environment variables with default value\n function envOr(string calldata name, bool defaultValue) external returns (bool value);\n function envOr(string calldata name, uint256 defaultValue) external returns (uint256 value);\n function envOr(string calldata name, int256 defaultValue) external returns (int256 value);\n function envOr(string calldata name, address defaultValue) external returns (address value);\n function envOr(string calldata name, bytes32 defaultValue) external returns (bytes32 value);\n function envOr(string calldata name, string calldata defaultValue) external returns (string memory value);\n function envOr(string calldata name, bytes calldata defaultValue) external returns (bytes memory value);\n // Read environment variables as arrays with default value\n function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)\n external\n returns (bool[] memory value);\n function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)\n external\n returns (uint256[] memory value);\n function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)\n external\n returns (int256[] memory value);\n function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)\n external\n returns (address[] memory value);\n function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)\n external\n returns (bytes32[] memory value);\n function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)\n external\n returns (string[] memory value);\n function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)\n external\n returns (bytes[] memory value);\n // Records all storage reads and writes\n function record() external;\n // Gets all accessed reads and write slot from a recording session, for a given address\n function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);\n // Gets the _creation_ bytecode from an artifact file. Takes in the relative path to the json file\n function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);\n // Gets the _deployed_ bytecode from an artifact file. Takes in the relative path to the json file\n function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);\n // Labels an address in call traces\n function label(address account, string calldata newLabel) external;\n // Using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain\n function broadcast() external;\n // Has the next call (at this call depth only) create a transaction with the address provided as the sender that can later be signed and sent onchain\n function broadcast(address signer) external;\n // Has the next call (at this call depth only) create a transaction with the private key provided as the sender that can later be signed and sent onchain\n function broadcast(uint256 privateKey) external;\n // Using the address that calls the test contract, has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain\n function startBroadcast() external;\n // Has all subsequent calls (at this call depth only) create transactions with the address provided that can later be signed and sent onchain\n function startBroadcast(address signer) external;\n // Has all subsequent calls (at this call depth only) create transactions with the private key provided that can later be signed and sent onchain\n function startBroadcast(uint256 privateKey) external;\n // Stops collecting onchain transactions\n function stopBroadcast() external;\n // Reads the entire content of file to string\n function readFile(string calldata path) external view returns (string memory data);\n // Reads the entire content of file as binary. Path is relative to the project root.\n function readFileBinary(string calldata path) external view returns (bytes memory data);\n // Get the path of the current project root\n function projectRoot() external view returns (string memory path);\n // Get the metadata for a file/directory\n function fsMetadata(string calldata fileOrDir) external returns (FsMetadata memory metadata);\n // Reads next line of file to string\n function readLine(string calldata path) external view returns (string memory line);\n // Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.\n function writeFile(string calldata path, string calldata data) external;\n // Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.\n // Path is relative to the project root.\n function writeFileBinary(string calldata path, bytes calldata data) external;\n // Writes line to file, creating a file if it does not exist.\n function writeLine(string calldata path, string calldata data) external;\n // Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.\n function closeFile(string calldata path) external;\n // Removes file. This cheatcode will revert in the following situations, but is not limited to just these cases:\n // - Path points to a directory.\n // - The file doesn't exist.\n // - The user lacks permissions to remove the file.\n function removeFile(string calldata path) external;\n // Convert values to a string\n function toString(address value) external pure returns (string memory stringifiedValue);\n function toString(bytes calldata value) external pure returns (string memory stringifiedValue);\n function toString(bytes32 value) external pure returns (string memory stringifiedValue);\n function toString(bool value) external pure returns (string memory stringifiedValue);\n function toString(uint256 value) external pure returns (string memory stringifiedValue);\n function toString(int256 value) external pure returns (string memory stringifiedValue);\n // Convert values from a string\n function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);\n function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);\n function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);\n function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);\n function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);\n function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);\n // Record all the transaction logs\n function recordLogs() external;\n // Gets all the recorded logs\n function getRecordedLogs() external returns (Log[] memory logs);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path m/44'/60'/0'/0/{index}\n function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);\n // Derive a private key from a provided mnenomic string (or mnenomic file path) at {derivationPath}{index}\n function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)\n external\n pure\n returns (uint256 privateKey);\n // Adds a private key to the local forge wallet and returns the address\n function rememberKey(uint256 privateKey) external returns (address keyAddr);\n //\n // parseJson\n //\n // ----\n // In case the returned value is a JSON object, it's encoded as a ABI-encoded tuple. As JSON objects\n // don't have the notion of ordered, but tuples do, they JSON object is encoded with it's fields ordered in\n // ALPHABETICAL order. That means that in order to successfully decode the tuple, we need to define a tuple that\n // encodes the fields in the same order, which is alphabetical. In the case of Solidity structs, they are encoded\n // as tuples, with the attributes in the order in which they are defined.\n // For example: json = { 'a': 1, 'b': 0xa4tb......3xs}\n // a: uint256\n // b: address\n // To decode that json, we need to define a struct or a tuple as follows:\n // struct json = { uint256 a; address b; }\n // If we defined a json struct with the opposite order, meaning placing the address b first, it would try to\n // decode the tuple in that order, and thus fail.\n // ----\n // Given a string of JSON, return it as ABI-encoded\n function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);\n function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);\n\n // The following parseJson cheatcodes will do type coercion, for the type that they indicate.\n // For example, parseJsonUint will coerce all values to a uint256. That includes stringified numbers '12'\n // and hex numbers '0xEF'.\n // Type coercion works ONLY for discrete values or arrays. That means that the key must return a value or array, not\n // a JSON object.\n function parseJsonUint(string calldata, string calldata) external returns (uint256);\n function parseJsonUintArray(string calldata, string calldata) external returns (uint256[] memory);\n function parseJsonInt(string calldata, string calldata) external returns (int256);\n function parseJsonIntArray(string calldata, string calldata) external returns (int256[] memory);\n function parseJsonBool(string calldata, string calldata) external returns (bool);\n function parseJsonBoolArray(string calldata, string calldata) external returns (bool[] memory);\n function parseJsonAddress(string calldata, string calldata) external returns (address);\n function parseJsonAddressArray(string calldata, string calldata) external returns (address[] memory);\n function parseJsonString(string calldata, string calldata) external returns (string memory);\n function parseJsonStringArray(string calldata, string calldata) external returns (string[] memory);\n function parseJsonBytes(string calldata, string calldata) external returns (bytes memory);\n function parseJsonBytesArray(string calldata, string calldata) external returns (bytes[] memory);\n function parseJsonBytes32(string calldata, string calldata) external returns (bytes32);\n function parseJsonBytes32Array(string calldata, string calldata) external returns (bytes32[] memory);\n\n // Serialize a key and value to a JSON object stored in-memory that can be later written to a file\n // It returns the stringified version of the specific JSON file up to that moment.\n function serializeBool(string calldata objectKey, string calldata valueKey, bool value)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address value)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)\n external\n returns (string memory json);\n\n function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)\n external\n returns (string memory json);\n function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)\n external\n returns (string memory json);\n function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)\n external\n returns (string memory json);\n function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)\n external\n returns (string memory json);\n function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)\n external\n returns (string memory json);\n function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)\n external\n returns (string memory json);\n function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)\n external\n returns (string memory json);\n\n //\n // writeJson\n //\n // ----\n // Write a serialized JSON object to a file. If the file exists, it will be overwritten.\n // Let's assume we want to write the following JSON to a file:\n //\n // { \"boolean\": true, \"number\": 342, \"object\": { \"title\": \"finally json serialization\" } }\n //\n // ```\n // string memory json1 = \"some key\";\n // vm.serializeBool(json1, \"boolean\", true);\n // vm.serializeBool(json1, \"number\", uint256(342));\n // json2 = \"some other key\";\n // string memory output = vm.serializeString(json2, \"title\", \"finally json serialization\");\n // string memory finalJson = vm.serialize(json1, \"object\", output);\n // vm.writeJson(finalJson, \"./output/example.json\");\n // ```\n // The critical insight is that every invocation of serialization will return the stringified version of the JSON\n // up to that point. That means we can construct arbitrary JSON objects and then use the return stringified version\n // to serialize them as values to another JSON object.\n //\n // json1 and json2 are simply keys used by the backend to keep track of the objects. So vm.serializeJson(json1,..)\n // will find the object in-memory that is keyed by \"some key\".\n function writeJson(string calldata json, string calldata path) external;\n // Write a serialized JSON object to an **existing** JSON file, replacing a value with key = \n // This is useful to replace a specific value of a JSON file, without having to parse the entire thing\n function writeJson(string calldata json, string calldata path, string calldata valueKey) external;\n // Returns the RPC url for the given alias\n function rpcUrl(string calldata rpcAlias) external view returns (string memory json);\n // Returns all rpc urls and their aliases `[alias, url][]`\n function rpcUrls() external view returns (string[2][] memory urls);\n // Returns all rpc urls and their aliases as structs.\n function rpcUrlStructs() external view returns (Rpc[] memory urls);\n // If the condition is false, discard this run's fuzz inputs and generate new ones.\n function assume(bool condition) external pure;\n // Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.\n function pauseGasMetering() external;\n // Resumes gas metering (i.e. gas usage is counted again). Noop if already on.\n function resumeGasMetering() external;\n}\n\ninterface Vm is VmSafe {\n // Sets block.timestamp\n function warp(uint256 newTimestamp) external;\n // Sets block.height\n function roll(uint256 newHeight) external;\n // Sets block.basefee\n function fee(uint256 newBasefee) external;\n // Sets block.difficulty\n function difficulty(uint256 newDifficulty) external;\n // Sets block.chainid\n function chainId(uint256 newChainId) external;\n // Stores a value to an address' storage slot.\n function store(address target, bytes32 slot, bytes32 value) external;\n // Sets the nonce of an account; must be higher than the current nonce of the account\n function setNonce(address account, uint64 newNonce) external;\n // Sets the *next* call's msg.sender to be the input address\n function prank(address msgSender) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called\n function startPrank(address msgSender) external;\n // Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input\n function prank(address msgSender, address txOrigin) external;\n // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input\n function startPrank(address msgSender, address txOrigin) external;\n // Resets subsequent calls' msg.sender to be `address(this)`\n function stopPrank() external;\n // Sets an address' balance\n function deal(address account, uint256 newBalance) external;\n // Sets an address' code\n function etch(address target, bytes calldata newRuntimeBytecode) external;\n // Expects an error on next call\n function expectRevert(bytes calldata revertData) external;\n function expectRevert(bytes4 revertData) external;\n function expectRevert() external;\n\n // Prepare an expected log with all four checks enabled.\n // Call this function, then emit an event, then call a function. Internally after the call, we check if\n // logs were emitted in the expected order with the expected topics and data.\n // Second form also checks supplied address against emitting contract.\n function expectEmit() external;\n function expectEmit(address emitter) external;\n\n // Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData).\n // Call this function, then emit an event, then call a function. Internally after the call, we check if\n // logs were emitted in the expected order with the expected topics and data (as specified by the booleans).\n // Second form also checks supplied address against emitting contract.\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;\n function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)\n external;\n\n // Mocks a call to an address, returning specified data.\n // Calldata can either be strict or a partial match, e.g. if you only\n // pass a Solidity selector to the expected calldata, then the entire Solidity\n // function will be mocked.\n function mockCall(address callee, bytes calldata data, bytes calldata returnData) external;\n // Mocks a call to an address with a specific msg.value, returning specified data.\n // Calldata match takes precedence over msg.value in case of ambiguity.\n function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external;\n // Clears all mocked calls\n function clearMockedCalls() external;\n // Expects a call to an address with the specified calldata.\n // Calldata can either be a strict or a partial match\n function expectCall(address callee, bytes calldata data) external;\n // Expects a call to an address with the specified msg.value and calldata\n function expectCall(address callee, uint256 msgValue, bytes calldata data) external;\n // Expect a call to an address with the specified msg.value, gas, and calldata.\n function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external;\n // Expect a call to an address with the specified msg.value and calldata, and a *minimum* amount of gas.\n function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external;\n // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other\n // memory is written to, the test will fail. Can be called multiple times to add more ranges to the set.\n function expectSafeMemory(uint64 min, uint64 max) external;\n // Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext.\n // If any other memory is written to, the test will fail. Can be called multiple times to add more ranges\n // to the set.\n function expectSafeMemoryCall(uint64 min, uint64 max) external;\n // Sets block.coinbase\n function coinbase(address newCoinbase) external;\n // Snapshot the current state of the evm.\n // Returns the id of the snapshot that was created.\n // To revert a snapshot use `revertTo`\n function snapshot() external returns (uint256 snapshotId);\n // Revert the state of the EVM to a previous snapshot\n // Takes the snapshot id to revert to.\n // This deletes the snapshot and all snapshots taken after the given snapshot id.\n function revertTo(uint256 snapshotId) external returns (bool success);\n // Creates a new fork with the given endpoint and block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork\n function createFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Creates a new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before the transaction,\n // and returns the identifier of the fork\n function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);\n // Creates _and_ also selects new fork with the given endpoint and at the block the given transaction was mined in, replays all transaction mined in the block before\n // the transaction, returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);\n // Creates _and_ also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork\n function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);\n // Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.\n function selectFork(uint256 forkId) external;\n /// Returns the identifier of the currently active fork. Reverts if no fork is currently active.\n function activeFork() external view returns (uint256 forkId);\n // Updates the currently active fork to given block number\n // This is similar to `roll` but for the currently active fork\n function rollFork(uint256 blockNumber) external;\n // Updates the currently active fork to given transaction\n // this will `rollFork` with the number of the block the transaction was mined in and replays all transaction mined before it in the block\n function rollFork(bytes32 txHash) external;\n // Updates the given fork to given block number\n function rollFork(uint256 forkId, uint256 blockNumber) external;\n // Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block\n function rollFork(uint256 forkId, bytes32 txHash) external;\n // Marks that the account(s) should use persistent storage across fork swaps in a multifork setup\n // Meaning, changes made to the state of this account will be kept when switching forks\n function makePersistent(address account) external;\n function makePersistent(address account0, address account1) external;\n function makePersistent(address account0, address account1, address account2) external;\n function makePersistent(address[] calldata accounts) external;\n // Revokes persistent status from the address, previously added via `makePersistent`\n function revokePersistent(address account) external;\n function revokePersistent(address[] calldata accounts) external;\n // Returns true if the account is marked as persistent\n function isPersistent(address account) external view returns (bool persistent);\n // In forking mode, explicitly grant the given address cheatcode access\n function allowCheatcodes(address account) external;\n // Fetches the given transaction from the active fork and executes it on the current state\n function transact(bytes32 txHash) external;\n // Fetches the given transaction from the given fork and executes it on the current state\n function transact(uint256 forkId, bytes32 txHash) external;\n}\n" - }, - "node_modules/forge-std/src/console.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\nlibrary console {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int)\", p0));\n }\n\n function logUint(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint)\", p0, p1));\n }\n\n function log(uint p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string)\", p0, p1));\n }\n\n function log(uint p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool)\", p0, p1));\n }\n\n function log(uint p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address)\", p0, p1));\n }\n\n function log(string memory p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool)\", p0, p1, p2));\n }\n\n function log(uint p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - }, - "node_modules/forge-std/src/console2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\n/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should\n/// use `int256` and `uint256`. This modified version fixes that. This version is recommended\n/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in\n/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.\n/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178\nlibrary console2 {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _sendLogPayload(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function logUint(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function logString(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function log(int256 p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function log(string memory p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint256 p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256)\", p0, p1));\n }\n\n function log(uint256 p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string)\", p0, p1));\n }\n\n function log(uint256 p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool)\", p0, p1));\n }\n\n function log(uint256 p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address)\", p0, p1));\n }\n\n function log(string memory p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n }\n\n function log(string memory p0, int256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,int256)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint256 p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint256 p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint256 p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal view {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" - }, - "node_modules/forge-std/src/interfaces/IMulticall3.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\npragma experimental ABIEncoderV2;\n\ninterface IMulticall3 {\n struct Call {\n address target;\n bytes callData;\n }\n\n struct Call3 {\n address target;\n bool allowFailure;\n bytes callData;\n }\n\n struct Call3Value {\n address target;\n bool allowFailure;\n uint256 value;\n bytes callData;\n }\n\n struct Result {\n bool success;\n bytes returnData;\n }\n\n function aggregate(Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes[] memory returnData);\n\n function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData);\n\n function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData);\n\n function blockAndAggregate(Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);\n\n function getBasefee() external view returns (uint256 basefee);\n\n function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash);\n\n function getBlockNumber() external view returns (uint256 blockNumber);\n\n function getChainId() external view returns (uint256 chainid);\n\n function getCurrentBlockCoinbase() external view returns (address coinbase);\n\n function getCurrentBlockDifficulty() external view returns (uint256 difficulty);\n\n function getCurrentBlockGasLimit() external view returns (uint256 gaslimit);\n\n function getCurrentBlockTimestamp() external view returns (uint256 timestamp);\n\n function getEthBalance(address addr) external view returns (uint256 balance);\n\n function getLastBlockHash() external view returns (bytes32 blockHash);\n\n function tryAggregate(bool requireSuccess, Call[] calldata calls)\n external\n payable\n returns (Result[] memory returnData);\n\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)\n external\n payable\n returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);\n}\n" - } - }, - "settings": { - "remappings": [ - "@openzeppelin/=node_modules/@openzeppelin/", - "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", - "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", - "@rari-capital/=node_modules/@rari-capital/", - "@rari-capital/solmate/=node_modules/@rari-capital/solmate/", - "@safe-global/safe-contracts/=node_modules/@safe-global/safe-contracts/", - "ds-test/=node_modules/ds-test/src/", - "forge-std/=node_modules/forge-std/src/", - "solady/=node_modules/solady/src/" - ], - "optimizer": { - "enabled": true, - "runs": 999999 - }, - "metadata": { - "bytecodeHash": "none" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "storageLayout", - "devdoc", - "userdoc" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-goerli/solcInputs/b1df373a9ed51b3903b61f56faa9a78f.json b/packages/contracts-bedrock/deployments/optimism-goerli/solcInputs/b1df373a9ed51b3903b61f56faa9a78f.json deleted file mode 100644 index b0bf9b8a4dfb..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/solcInputs/b1df373a9ed51b3903b61f56faa9a78f.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "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-bedrock/deployments/optimism-goerli/solcInputs/cf9f12504fd2a3f54e63ce13e7c60cdc.json b/packages/contracts-bedrock/deployments/optimism-goerli/solcInputs/cf9f12504fd2a3f54e63ce13e7c60cdc.json deleted file mode 100644 index cd674e3e437d..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-goerli/solcInputs/cf9f12504fd2a3f54e63ce13e7c60cdc.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "contracts/L1/ResourceMetering.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Arithmetic } from \"../libraries/Arithmetic.sol\";\n\n/**\n * @custom:upgradeable\n * @title ResourceMetering\n * @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing\n * updates automatically based on current demand.\n */\nabstract contract ResourceMetering is Initializable {\n /**\n * @notice Represents the various parameters that control the way in which resources are\n * metered. Corresponds to the EIP-1559 resource metering system.\n *\n * @custom:field prevBaseFee Base fee from the previous block(s).\n * @custom:field prevBoughtGas Amount of gas bought so far in the current block.\n * @custom:field prevBlockNum Last block number that the base fee was updated.\n */\n struct ResourceParams {\n uint128 prevBaseFee;\n uint64 prevBoughtGas;\n uint64 prevBlockNum;\n }\n\n /**\n * @notice Represents the configuration for the EIP-1559 based curve for the deposit gas\n * market. These values should be set with care as it is possible to set them in\n * a way that breaks the deposit gas market. The target resource limit is defined as\n * maxResourceLimit / elasticityMultiplier. This struct was designed to fit within a\n * single word. There is additional space for additions in the future.\n *\n * @custom:field maxResourceLimit Represents the maximum amount of deposit gas that\n * can be purchased per block.\n * @custom:field elasticityMultiplier Determines the target resource limit along with\n * the resource limit.\n * @custom:field baseFeeMaxChangeDenominator Determines max change on fee per block.\n * @custom:field minimumBaseFee The min deposit base fee, it is clamped to this\n * value.\n * @custom:field systemTxMaxGas The amount of gas supplied to the system\n * transaction. This should be set to the same number\n * that the op-node sets as the gas limit for the\n * system transaction.\n * @custom:field maximumBaseFee The max deposit base fee, it is clamped to this\n * value.\n */\n struct ResourceConfig {\n uint32 maxResourceLimit;\n uint8 elasticityMultiplier;\n uint8 baseFeeMaxChangeDenominator;\n uint32 minimumBaseFee;\n uint32 systemTxMaxGas;\n uint128 maximumBaseFee;\n }\n\n /**\n * @notice EIP-1559 style gas parameters.\n */\n ResourceParams public params;\n\n /**\n * @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.\n */\n uint256[48] private __gap;\n\n /**\n * @notice Meters access to a function based an amount of a requested resource.\n *\n * @param _amount Amount of the resource requested.\n */\n modifier metered(uint64 _amount) {\n // Record initial gas amount so we can refund for it later.\n uint256 initialGas = gasleft();\n\n // Run the underlying function.\n _;\n\n // Run the metering function.\n _metered(_amount, initialGas);\n }\n\n /**\n * @notice An internal function that holds all of the logic for metering a resource.\n *\n * @param _amount Amount of the resource requested.\n * @param _initialGas The amount of gas before any modifier execution.\n */\n function _metered(uint64 _amount, uint256 _initialGas) internal {\n // Update block number and base fee if necessary.\n uint256 blockDiff = block.number - params.prevBlockNum;\n\n ResourceConfig memory config = _resourceConfig();\n int256 targetResourceLimit = int256(uint256(config.maxResourceLimit)) /\n int256(uint256(config.elasticityMultiplier));\n\n if (blockDiff > 0) {\n // Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate\n // at which deposits can be created and therefore limit the potential for deposits to\n // spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes.\n int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - targetResourceLimit;\n int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) /\n (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator)));\n\n // Update base fee by adding the base fee delta and clamp the resulting value between\n // min and max.\n int256 newBaseFee = Arithmetic.clamp({\n _value: int256(uint256(params.prevBaseFee)) + baseFeeDelta,\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n\n // If we skipped more than one block, we also need to account for every empty block.\n // Empty block means there was no demand for deposits in that block, so we should\n // reflect this lack of demand in the fee.\n if (blockDiff > 1) {\n // Update the base fee by repeatedly applying the exponent 1-(1/change_denominator)\n // blockDiff - 1 times. Simulates multiple empty blocks. Clamp the resulting value\n // between min and max.\n newBaseFee = Arithmetic.clamp({\n _value: Arithmetic.cdexp({\n _coefficient: newBaseFee,\n _denominator: int256(uint256(config.baseFeeMaxChangeDenominator)),\n _exponent: int256(blockDiff - 1)\n }),\n _min: int256(uint256(config.minimumBaseFee)),\n _max: int256(uint256(config.maximumBaseFee))\n });\n }\n\n // Update new base fee, reset bought gas, and update block number.\n params.prevBaseFee = uint128(uint256(newBaseFee));\n params.prevBoughtGas = 0;\n params.prevBlockNum = uint64(block.number);\n }\n\n // Make sure we can actually buy the resource amount requested by the user.\n params.prevBoughtGas += _amount;\n require(\n int256(uint256(params.prevBoughtGas)) <= int256(uint256(config.maxResourceLimit)),\n \"ResourceMetering: cannot buy more gas than available gas limit\"\n );\n\n // Determine the amount of ETH to be paid.\n uint256 resourceCost = uint256(_amount) * uint256(params.prevBaseFee);\n\n // We currently charge for this ETH amount as an L1 gas burn, so we convert the ETH amount\n // into gas by dividing by the L1 base fee. We assume a minimum base fee of 1 gwei to avoid\n // division by zero for L1s that don't support 1559 or to avoid excessive gas burns during\n // periods of extremely low L1 demand. One-day average gas fee hasn't dipped below 1 gwei\n // during any 1 day period in the last 5 years, so should be fine.\n uint256 gasCost = resourceCost / Math.max(block.basefee, 1 gwei);\n\n // Give the user a refund based on the amount of gas they used to do all of the work up to\n // this point. Since we're at the end of the modifier, this should be pretty accurate. Acts\n // effectively like a dynamic stipend (with a minimum value).\n uint256 usedGas = _initialGas - gasleft();\n if (gasCost > usedGas) {\n Burn.gas(gasCost - usedGas);\n }\n }\n\n /**\n * @notice Virtual function that returns the resource config. Contracts that inherit this\n * contract must implement this function.\n *\n * @return ResourceConfig\n */\n function _resourceConfig() internal virtual returns (ResourceConfig memory);\n\n /**\n * @notice Sets initial resource parameter values. This function must either be called by the\n * initializer function of an upgradeable child contract.\n */\n // solhint-disable-next-line func-name-mixedcase\n function __ResourceMetering_init() internal onlyInitializing {\n params = ResourceParams({\n prevBaseFee: 1 gwei,\n prevBoughtGas: 0,\n prevBlockNum: uint64(block.number)\n });\n }\n}\n" - }, - "contracts/L2/L2CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { AddressAliasHelper } from \"../vendor/AddressAliasHelper.sol\";\nimport { Predeploys } from \"../libraries/Predeploys.sol\";\nimport { CrossDomainMessenger } from \"../universal/CrossDomainMessenger.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\nimport { L2ToL1MessagePasser } from \"./L2ToL1MessagePasser.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000007\n * @title L2CrossDomainMessenger\n * @notice The L2CrossDomainMessenger is a high-level interface for message passing between L1 and\n * L2 on the L2 side. Users are generally encouraged to use this contract instead of lower\n * level message passing contracts.\n */\ncontract L2CrossDomainMessenger is CrossDomainMessenger, Semver {\n /**\n * @custom:semver 1.1.0\n *\n * @param _l1CrossDomainMessenger Address of the L1CrossDomainMessenger contract.\n */\n constructor(address _l1CrossDomainMessenger)\n Semver(1, 1, 0)\n CrossDomainMessenger(_l1CrossDomainMessenger)\n {\n initialize();\n }\n\n /**\n * @notice Initializer.\n */\n function initialize() public initializer {\n __CrossDomainMessenger_init();\n }\n\n /**\n * @custom:legacy\n * @notice Legacy getter for the remote messenger. Use otherMessenger going forward.\n *\n * @return Address of the L1CrossDomainMessenger contract.\n */\n function l1CrossDomainMessenger() public view returns (address) {\n return OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _sendMessage(\n address _to,\n uint64 _gasLimit,\n uint256 _value,\n bytes memory _data\n ) internal override {\n L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)).initiateWithdrawal{\n value: _value\n }(_to, _gasLimit, _data);\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isOtherMessenger() internal view override returns (bool) {\n return AddressAliasHelper.undoL1ToL2Alias(msg.sender) == OTHER_MESSENGER;\n }\n\n /**\n * @inheritdoc CrossDomainMessenger\n */\n function _isUnsafeTarget(address _target) internal view override returns (bool) {\n return _target == address(this) || _target == address(Predeploys.L2_TO_L1_MESSAGE_PASSER);\n }\n}\n" - }, - "contracts/L2/L2ToL1MessagePasser.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Types } from \"../libraries/Types.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Burn } from \"../libraries/Burn.sol\";\nimport { Semver } from \"../universal/Semver.sol\";\n\n/**\n * @custom:proxied\n * @custom:predeploy 0x4200000000000000000000000000000000000016\n * @title L2ToL1MessagePasser\n * @notice The L2ToL1MessagePasser is a dedicated contract where messages that are being sent from\n * L2 to L1 can be stored. The storage root of this contract is pulled up to the top level\n * of the L2 output to reduce the cost of proving the existence of sent messages.\n */\ncontract L2ToL1MessagePasser is Semver {\n /**\n * @notice The L1 gas limit set when eth is withdrawn using the receive() function.\n */\n uint256 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000;\n\n /**\n * @notice Current message version identifier.\n */\n uint16 public constant MESSAGE_VERSION = 1;\n\n /**\n * @notice Includes the message hashes for all withdrawals\n */\n mapping(bytes32 => bool) public sentMessages;\n\n /**\n * @notice A unique value hashed with each withdrawal.\n */\n uint240 internal msgNonce;\n\n /**\n * @notice Emitted any time a withdrawal is initiated.\n *\n * @param nonce Unique value corresponding to each withdrawal.\n * @param sender The L2 account address which initiated the withdrawal.\n * @param target The L1 account address the call will be send to.\n * @param value The ETH value submitted for withdrawal, to be forwarded to the target.\n * @param gasLimit The minimum amount of gas that must be provided when withdrawing.\n * @param data The data to be forwarded to the target on L1.\n * @param withdrawalHash The hash of the withdrawal.\n */\n event MessagePassed(\n uint256 indexed nonce,\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 gasLimit,\n bytes data,\n bytes32 withdrawalHash\n );\n\n /**\n * @notice Emitted when the balance of this contract is burned.\n *\n * @param amount Amount of ETh that was burned.\n */\n event WithdrawerBalanceBurnt(uint256 indexed amount);\n\n /**\n * @custom:semver 1.0.0\n */\n constructor() Semver(1, 0, 0) {}\n\n /**\n * @notice Allows users to withdraw ETH by sending directly to this contract.\n */\n receive() external payable {\n initiateWithdrawal(msg.sender, RECEIVE_DEFAULT_GAS_LIMIT, bytes(\"\"));\n }\n\n /**\n * @notice Removes all ETH held by this contract from the state. Used to prevent the amount of\n * ETH on L2 inflating when ETH is withdrawn. Currently only way to do this is to\n * create a contract and self-destruct it to itself. Anyone can call this function. Not\n * incentivized since this function is very cheap.\n */\n function burn() external {\n uint256 balance = address(this).balance;\n Burn.eth(balance);\n emit WithdrawerBalanceBurnt(balance);\n }\n\n /**\n * @notice Sends a message from L2 to L1.\n *\n * @param _target Address to call on L1 execution.\n * @param _gasLimit Minimum gas limit for executing the message on L1.\n * @param _data Data to forward to L1 target.\n */\n function initiateWithdrawal(\n address _target,\n uint256 _gasLimit,\n bytes memory _data\n ) public payable {\n bytes32 withdrawalHash = Hashing.hashWithdrawal(\n Types.WithdrawalTransaction({\n nonce: messageNonce(),\n sender: msg.sender,\n target: _target,\n value: msg.value,\n gasLimit: _gasLimit,\n data: _data\n })\n );\n\n sentMessages[withdrawalHash] = true;\n\n emit MessagePassed(\n messageNonce(),\n msg.sender,\n _target,\n msg.value,\n _gasLimit,\n _data,\n withdrawalHash\n );\n\n unchecked {\n ++msgNonce;\n }\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" - }, - "contracts/libraries/Arithmetic.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { SignedMath } from \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\nimport { FixedPointMathLib } from \"@rari-capital/solmate/src/utils/FixedPointMathLib.sol\";\n\n/**\n * @title Arithmetic\n * @notice Even more math than before.\n */\nlibrary Arithmetic {\n /**\n * @notice Clamps a value between a minimum and maximum.\n *\n * @param _value The value to clamp.\n * @param _min The minimum value.\n * @param _max The maximum value.\n *\n * @return The clamped value.\n */\n function clamp(\n int256 _value,\n int256 _min,\n int256 _max\n ) internal pure returns (int256) {\n return SignedMath.min(SignedMath.max(_value, _min), _max);\n }\n\n /**\n * @notice (c)oefficient (d)enominator (exp)onentiation function.\n * Returns the result of: c * (1 - 1/d)^exp.\n *\n * @param _coefficient Coefficient of the function.\n * @param _denominator Fractional denominator.\n * @param _exponent Power function exponent.\n *\n * @return Result of c * (1 - 1/d)^exp.\n */\n function cdexp(\n int256 _coefficient,\n int256 _denominator,\n int256 _exponent\n ) internal pure returns (int256) {\n return\n (_coefficient *\n (FixedPointMathLib.powWad(1e18 - (1e18 / _denominator), _exponent * 1e18))) / 1e18;\n }\n}\n" - }, - "contracts/libraries/Burn.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @title Burn\n * @notice Utilities for burning stuff.\n */\nlibrary Burn {\n /**\n * Burns a given amount of ETH.\n *\n * @param _amount Amount of ETH to burn.\n */\n function eth(uint256 _amount) internal {\n new Burner{ value: _amount }();\n }\n\n /**\n * Burns a given amount of gas.\n *\n * @param _amount Amount of gas to burn.\n */\n function gas(uint256 _amount) internal view {\n uint256 i = 0;\n uint256 initialGas = gasleft();\n while (initialGas - gasleft() < _amount) {\n ++i;\n }\n }\n}\n\n/**\n * @title Burner\n * @notice Burner self-destructs on creation and sends all ETH to itself, removing all ETH given to\n * the contract from the circulating supply. Self-destructing is the only way to remove ETH\n * from the circulating supply.\n */\ncontract Burner {\n constructor() payable {\n selfdestruct(payable(address(this)));\n }\n}\n" - }, - "contracts/libraries/Constants.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { ResourceMetering } from \"../L1/ResourceMetering.sol\";\n\n/**\n * @title Constants\n * @notice Constants is a library for storing constants. Simple! Don't put everything in here, just\n * the stuff used in multiple contracts. Constants that only apply to a single contract\n * should be defined in that contract instead.\n */\nlibrary Constants {\n /**\n * @notice Special address to be used as the tx origin for gas estimation calls in the\n * OptimismPortal and CrossDomainMessenger calls. You only need to use this address if\n * the minimum gas limit specified by the user is not actually enough to execute the\n * given message and you're attempting to estimate the actual necessary gas limit. We\n * use address(1) because it's the ecrecover precompile and therefore guaranteed to\n * never have any code on any EVM chain.\n */\n address internal constant ESTIMATION_ADDRESS = address(1);\n\n /**\n * @notice Value used for the L2 sender storage slot in both the OptimismPortal and the\n * CrossDomainMessenger contracts before an actual sender is set. This value is\n * non-zero to reduce the gas cost of message passing transactions.\n */\n address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD;\n\n /**\n * @notice Returns the default values for the ResourceConfig. These are the recommended values\n * for a production network.\n */\n function DEFAULT_RESOURCE_CONFIG()\n internal\n pure\n returns (ResourceMetering.ResourceConfig memory)\n {\n ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({\n maxResourceLimit: 20_000_000,\n elasticityMultiplier: 10,\n baseFeeMaxChangeDenominator: 8,\n minimumBaseFee: 1 gwei,\n systemTxMaxGas: 1_000_000,\n maximumBaseFee: type(uint128).max\n });\n return config;\n }\n}\n" - }, - "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" - }, - "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" - }, - "contracts/libraries/Predeploys.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Predeploys\n * @notice Contains constant addresses for contracts that are pre-deployed to the L2 system.\n */\nlibrary Predeploys {\n /**\n * @notice Address of the L2ToL1MessagePasser predeploy.\n */\n address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016;\n\n /**\n * @notice Address of the L2CrossDomainMessenger predeploy.\n */\n address internal constant L2_CROSS_DOMAIN_MESSENGER =\n 0x4200000000000000000000000000000000000007;\n\n /**\n * @notice Address of the L2StandardBridge predeploy.\n */\n address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;\n\n /**\n * @notice Address of the L2ERC721Bridge predeploy.\n */\n address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014;\n\n /**\n * @notice Address of the SequencerFeeWallet predeploy.\n */\n address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;\n\n /**\n * @notice Address of the OptimismMintableERC20Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY =\n 0x4200000000000000000000000000000000000012;\n\n /**\n * @notice Address of the OptimismMintableERC721Factory predeploy.\n */\n address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY =\n 0x4200000000000000000000000000000000000017;\n\n /**\n * @notice Address of the L1Block predeploy.\n */\n address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015;\n\n /**\n * @notice Address of the GasPriceOracle predeploy. Includes fee information\n * and helpers for computing the L1 portion of the transaction fee.\n */\n address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F;\n\n /**\n * @custom:legacy\n * @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger\n * or access tx.origin (or msg.sender) in a L1 to L2 transaction instead.\n */\n address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;\n\n /**\n * @custom:legacy\n * @notice Address of the DeployerWhitelist predeploy. No longer active.\n */\n address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the\n * state trie as of the Bedrock upgrade. Contract has been locked and write functions\n * can no longer be accessed.\n */\n address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;\n\n /**\n * @custom:legacy\n * @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy\n * instead, which exposes more information about the L1 state.\n */\n address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;\n\n /**\n * @custom:legacy\n * @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated\n * L2ToL1MessagePasser contract instead.\n */\n address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;\n\n /**\n * @notice Address of the ProxyAdmin predeploy.\n */\n address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018;\n\n /**\n * @notice Address of the BaseFeeVault predeploy.\n */\n address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019;\n\n /**\n * @notice Address of the L1FeeVault predeploy.\n */\n address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A;\n\n /**\n * @notice Address of the GovernanceToken predeploy.\n */\n address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042;\n}\n" - }, - "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, 32), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n }\n return _success;\n }\n\n /**\n * @notice Perform a low level call without copying any returndata. This function\n * will revert if the call cannot be performed with the specified minimum\n * gas.\n *\n * @param _target Address to call\n * @param _minGas The minimum amount of gas that may be passed 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 callWithMinGas(\n address _target,\n uint256 _minGas,\n uint256 _value,\n bytes memory _calldata\n ) internal returns (bool) {\n bool _success;\n assembly {\n // Assertion: gasleft() >= ((_minGas + 200) * 64) / 63\n //\n // Because EIP-150 ensures that, a maximum of 63/64ths of the remaining gas in the call\n // frame may be passed to a subcontext, we need to ensure that the gas will not be\n // truncated to hold this function's invariant: \"If a call is performed by\n // `callWithMinGas`, it must receive at least the specified minimum gas limit.\" In\n // addition, exactly 51 gas is consumed between the below `GAS` opcode and the `CALL`\n // opcode, so it is factored in with some extra room for error.\n if lt(gas(), div(mul(64, add(_minGas, 200)), 63)) {\n // Store the \"Error(string)\" selector in scratch space.\n mstore(0, 0x08c379a0)\n // Store the pointer to the string length in scratch space.\n mstore(32, 32)\n // Store the string.\n //\n // SAFETY:\n // - We pad the beginning of the string with two zero bytes as well as the\n // length (24) to ensure that we override the free memory pointer at offset\n // 0x40. This is necessary because the free memory pointer is likely to\n // be greater than 1 byte when this function is called, but it is incredibly\n // unlikely that it will be greater than 3 bytes. As for the data within\n // 0x60, it is ensured that it is 0 due to 0x60 being the zero offset.\n // - It's fine to clobber the free memory pointer, we're reverting.\n mstore(88, 0x0000185361666543616c6c3a204e6f7420656e6f75676820676173)\n\n // Revert with 'Error(\"SafeCall: Not enough gas\")'\n revert(28, 100)\n }\n\n // The call will be supplied at least (((_minGas + 200) * 64) / 63) - 49 gas due to the\n // above assertion. This ensures that, in all circumstances, the call will\n // receive at least the minimum amount of gas specified.\n // We can prove this property by solving the inequalities:\n // ((((_minGas + 200) * 64) / 63) - 49) >= _minGas\n // ((((_minGas + 200) * 64) / 63) - 51) * (63 / 64) >= _minGas\n // Both inequalities hold true for all possible values of `_minGas`.\n _success := call(\n gas(), // gas\n _target, // recipient\n _value, // ether value\n add(_calldata, 32), // inloc\n mload(_calldata), // inlen\n 0x00, // outloc\n 0x00 // outlen\n )\n }\n return _success;\n }\n}\n" - }, - "contracts/libraries/Types.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 * @custom:field outputRoot Hash of the L2 output.\n * @custom:field timestamp Timestamp of the L1 block that the output root was submitted in.\n * @custom:field l2BlockNumber L2 block number that the output corresponds to.\n */\n struct OutputProposal {\n bytes32 outputRoot;\n uint128 timestamp;\n uint128 l2BlockNumber;\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 * @custom:field version Version of the output root.\n * @custom:field stateRoot Root of the state trie at the block of this output.\n * @custom:field messagePasserStorageRoot Root of the message passer storage trie.\n * @custom:field latestBlockhash Hash of the block this output was generated from.\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 * @custom:field from Address of the sender of the transaction.\n * @custom:field to Address of the recipient of the transaction.\n * @custom:field isCreation True if the transaction is a contract creation.\n * @custom:field value Value to send to the recipient.\n * @custom:field mint Amount of ETH to mint.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the transaction.\n * @custom:field l1BlockHash Hash of the block the transaction was submitted in.\n * @custom:field logIndex Index of the log in the block the transaction was submitted in.\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 * @custom:field nonce Nonce of the withdrawal transaction\n * @custom:field sender Address of the sender of the transaction.\n * @custom:field target Address of the recipient of the transaction.\n * @custom:field value Value to send to the recipient.\n * @custom:field gasLimit Gas limit of the transaction.\n * @custom:field data Data of the 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" - }, - "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" - }, - "contracts/universal/CrossDomainMessenger.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { SafeCall } from \"../libraries/SafeCall.sol\";\nimport { Hashing } from \"../libraries/Hashing.sol\";\nimport { Encoding } from \"../libraries/Encoding.sol\";\nimport { Constants } from \"../libraries/Constants.sol\";\n\n/**\n * @custom:legacy\n * @title CrossDomainMessengerLegacySpacer0\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 CrossDomainMessengerLegacySpacer0 {\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:legacy\n * @title CrossDomainMessengerLegacySpacer1\n * @notice Contract only exists to add a spacer to the CrossDomainMessenger where the\n * PausableUpgradable and OwnableUpgradeable variables used to exist. Must be\n * the third contract in the inheritance tree of the CrossDomainMessenger.\n */\ncontract CrossDomainMessengerLegacySpacer1 {\n /**\n * @custom:legacy\n * @custom:spacer __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * ContextUpgradable via OwnableUpgradeable.\n *\n */\n uint256[50] private spacer_1_0_1600;\n\n /**\n * @custom:legacy\n * @custom:spacer _owner\n * @notice Spacer for backwards compatibility.\n * Come from OpenZeppelin OwnableUpgradeable.\n */\n address private spacer_51_0_20;\n\n /**\n * @custom:legacy\n * @custom:spacer __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * ContextUpgradable via PausableUpgradable.\n */\n uint256[49] private spacer_52_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer _paused\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n bool private spacer_101_0_1;\n\n /**\n * @custom:legacy\n * @custom:spacer __gap\n * @notice Spacer for backwards compatibility. Comes from OpenZeppelin\n * PausableUpgradable.\n */\n uint256[49] private spacer_102_0_1568;\n\n /**\n * @custom:legacy\n * @custom:spacer ReentrancyGuardUpgradeable's `_status` field.\n * @notice Spacer for backwards compatibility\n */\n uint256 private spacer_151_0_32;\n\n /**\n * @custom:spacer ReentrancyGuardUpgradeable\n * @notice Spacer for backwards compatibility\n */\n uint256[49] private __gap_reentrancy_guard;\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/**\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 *\n * Any changes to this contract MUST result in a semver bump for contracts that inherit it.\n */\nabstract contract CrossDomainMessenger is\n CrossDomainMessengerLegacySpacer0,\n Initializable,\n CrossDomainMessengerLegacySpacer1\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 uint64 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 uint64 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 uint64 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 uint64 public constant MIN_GAS_CALLDATA_OVERHEAD = 16;\n\n /**\n * @notice Address of the paired CrossDomainMessenger contract on the other chain.\n */\n address public immutable OTHER_MESSENGER;\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 a boolean if and only if the message has failed to be\n * executed at least once. A message will not be present in this mapping if it\n * successfully executed on the first attempt.\n */\n mapping(bytes32 => bool) public failedMessages;\n\n /**\n * @notice A mapping of hashes to reentrancy locks.\n */\n mapping(bytes32 => bool) internal reentrancyLocks;\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[41] 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 OTHER_MESSENGER = _otherMessenger;\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 OTHER_MESSENGER,\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 {\n (, uint16 version) = Encoding.decodeVersionedNonce(_nonce);\n require(\n version < 2,\n \"CrossDomainMessenger: only version 0 or 1 messages are supported at this time\"\n );\n\n // If the message is version 0, then it's a migrated legacy withdrawal. We therefore need\n // to check that the legacy version of the message has not already been relayed.\n if (version == 0) {\n bytes32 oldHash = Hashing.hashCrossDomainMessageV0(_target, _sender, _message, _nonce);\n require(\n successfulMessages[oldHash] == false,\n \"CrossDomainMessenger: legacy withdrawal already relayed\"\n );\n }\n\n // We use the v1 message hash as the unique identifier for the message because it commits\n // to the value and minimum gas limit of the message.\n bytes32 versionedHash = Hashing.hashCrossDomainMessageV1(\n _nonce,\n _sender,\n _target,\n _value,\n _minGasLimit,\n _message\n );\n\n // Check if the reentrancy lock for the `versionedHash` is already set.\n if (reentrancyLocks[versionedHash]) {\n revert(\"ReentrancyGuard: reentrant call\");\n }\n // Trigger the reentrancy lock for `versionedHash`\n reentrancyLocks[versionedHash] = true;\n\n if (_isOtherMessenger()) {\n // These properties should always hold when the message is first submitted (as\n // opposed to being replayed).\n assert(msg.value == _value);\n assert(!failedMessages[versionedHash]);\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 failedMessages[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 xDomainMsgSender = _sender;\n bool success = SafeCall.callWithMinGas(_target, _minGasLimit, _value, _message);\n xDomainMsgSender = Constants.DEFAULT_L2_SENDER;\n\n if (success) {\n successfulMessages[versionedHash] = true;\n emit RelayedMessage(versionedHash);\n } else {\n failedMessages[versionedHash] = true;\n emit FailedRelayedMessage(versionedHash);\n\n // Revert in this case if the transaction was triggered by the estimation address. This\n // should only be possible during gas estimation or we have bigger problems. Reverting\n // here will make the behavior of gas estimation change such that the gas limit\n // computed will be the amount required to relay the message, even if that amount is\n // greater than the minimum gas limit specified by the user.\n if (tx.origin == Constants.ESTIMATION_ADDRESS) {\n revert(\"CrossDomainMessenger: failed to relay message\");\n }\n }\n\n // Clear the reentrancy lock for `versionedHash`\n reentrancyLocks[versionedHash] = false;\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 != Constants.DEFAULT_L2_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 (uint64) {\n // We peform the following math on uint64s to avoid overflow errors. Multiplying the\n // by MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR would otherwise limit the _minGasLimit to\n // type(uint32).max / MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR ~= 4.2m.\n return\n // Dynamic overhead\n ((uint64(_minGasLimit) * MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR) /\n MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR) +\n // Calldata overhead\n (uint64(_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 = Constants.DEFAULT_L2_SENDER;\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" - }, - "contracts/universal/Semver.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\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 uint256 private immutable MAJOR_VERSION;\n\n /**\n * @notice Contract version number (minor).\n */\n uint256 private immutable MINOR_VERSION;\n\n /**\n * @notice Contract version number (patch).\n */\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" - }, - "contracts/vendor/AddressAliasHelper.sol": { - "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npragma solidity ^0.8.0;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n unchecked {\n l2Address = address(uint160(l1Address) + offset);\n }\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n unchecked {\n l1Address = address(uint160(l2Address) - offset);\n }\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/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/Address.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) || (!Address.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" - }, - "node_modules/@openzeppelin/contracts/utils/Address.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 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 /// @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" - }, - "node_modules/@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\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 /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.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 enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\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 == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`.\n // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`.\n // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`.\n // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a\n // good first aproximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1;\n uint256 x = a;\n if (x >> 128 > 0) {\n x >>= 128;\n result <<= 64;\n }\n if (x >> 64 > 0) {\n x >>= 64;\n result <<= 32;\n }\n if (x >> 32 > 0) {\n x >>= 32;\n result <<= 16;\n }\n if (x >> 16 > 0) {\n x >>= 16;\n result <<= 8;\n }\n if (x >> 8 > 0) {\n x >>= 8;\n result <<= 4;\n }\n if (x >> 4 > 0) {\n x >>= 4;\n result <<= 2;\n }\n if (x >> 2 > 0) {\n result <<= 1;\n }\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n uint256 result = sqrt(a);\n if (rounding == Rounding.Up && result * result < a) {\n result += 1;\n }\n return result;\n }\n}\n" - }, - "node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" - }, - "node_modules/@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" - }, - "node_modules/@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" - }, - "node_modules/@rari-capital/solmate/src/utils/FixedPointMathLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol)\nlibrary FixedPointMathLib {\n /*//////////////////////////////////////////////////////////////\n SIMPLIFIED FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.\n\n function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.\n }\n\n function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.\n }\n\n function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.\n }\n\n function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.\n }\n\n function powWad(int256 x, int256 y) internal pure returns (int256) {\n // Equivalent to x to the power of y because x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)\n return expWad((lnWad(x) * y) / int256(WAD)); // Using ln(x) means x must be greater than 0.\n }\n\n function expWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n // When the result is < 0.5 we return zero. This happens when\n // x <= floor(log(0.5e18) * 1e18) ~ -42e18\n if (x <= -42139678854452767551) return 0;\n\n // When the result is > (2**255 - 1) / 1e18 we can not represent it as an\n // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.\n if (x >= 135305999368893231589) revert(\"EXP_OVERFLOW\");\n\n // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96\n // for more intermediate precision and a binary basis. This base conversion\n // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.\n x = (x << 78) / 5**18;\n\n // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers\n // of two such that exp(x) = exp(x') * 2**k, where k is an integer.\n // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).\n int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96;\n x = x - k * 54916777467707473351141471128;\n\n // k is in the range [-61, 195].\n\n // Evaluate using a (6, 7)-term rational approximation.\n // p is made monic, we'll multiply by a scale factor later.\n int256 y = x + 1346386616545796478920950773328;\n y = ((y * x) >> 96) + 57155421227552351082224309758442;\n int256 p = y + x - 94201549194550492254356042504812;\n p = ((p * y) >> 96) + 28719021644029726153956944680412240;\n p = p * x + (4385272521454847904659076985693276 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n int256 q = x - 2855989394907223263936484059900;\n q = ((q * x) >> 96) + 50020603652535783019961831881945;\n q = ((q * x) >> 96) - 533845033583426703283633433725380;\n q = ((q * x) >> 96) + 3604857256930695427073651918091429;\n q = ((q * x) >> 96) - 14423608567350463180887372962807573;\n q = ((q * x) >> 96) + 26449188498355588339934803723976023;\n\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial won't have zeros in the domain as all its roots are complex.\n // No scaling is necessary because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r should be in the range (0.09, 0.25) * 2**96.\n\n // We now need to multiply r by:\n // * the scale factor s = ~6.031367120.\n // * the 2**k factor from the range reduction.\n // * the 1e18 / 2**96 factor for base conversion.\n // We do this all at once, with an intermediate result in 2**213\n // basis, so the final right shift is always by a positive amount.\n r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k));\n }\n }\n\n function lnWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n require(x > 0, \"UNDEFINED\");\n\n // We want to convert x from 10**18 fixed point to 2**96 fixed point.\n // We do this by multiplying by 2**96 / 10**18. But since\n // ln(x * C) = ln(x) + ln(C), we can simply do nothing here\n // and add ln(2**96 / 10**18) at the end.\n\n // Reduce range of x to (1, 2) * 2**96\n // ln(2^k * x) = k * ln(2) + ln(x)\n int256 k = int256(log2(uint256(x))) - 96;\n x <<= uint256(159 - k);\n x = int256(uint256(x) >> 159);\n\n // Evaluate using a (8, 8)-term rational approximation.\n // p is made monic, we will multiply by a scale factor later.\n int256 p = x + 3273285459638523848632254066296;\n p = ((p * x) >> 96) + 24828157081833163892658089445524;\n p = ((p * x) >> 96) + 43456485725739037958740375743393;\n p = ((p * x) >> 96) - 11111509109440967052023855526967;\n p = ((p * x) >> 96) - 45023709667254063763336534515857;\n p = ((p * x) >> 96) - 14706773417378608786704636184526;\n p = p * x - (795164235651350426258249787498 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n // q is monic by convention.\n int256 q = x + 5573035233440673466300451813936;\n q = ((q * x) >> 96) + 71694874799317883764090561454958;\n q = ((q * x) >> 96) + 283447036172924575727196451306956;\n q = ((q * x) >> 96) + 401686690394027663651624208769553;\n q = ((q * x) >> 96) + 204048457590392012362485061816622;\n q = ((q * x) >> 96) + 31853899698501571402653359427138;\n q = ((q * x) >> 96) + 909429971244387300277376558375;\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial is known not to have zeros in the domain.\n // No scaling required because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r is in the range (0, 0.125) * 2**96\n\n // Finalization, we need to:\n // * multiply by the scale factor s = 5.549…\n // * add ln(2**96 / 10**18)\n // * add k * ln(2)\n // * multiply by 10**18 / 2**96 = 5**18 >> 78\n\n // mul s * 5e18 * 2**96, base is now 5**18 * 2**192\n r *= 1677202110996718588342820967067443963516166;\n // add ln(2) * k * 5e18 * 2**192\n r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;\n // add ln(2**96 / 10**18) * 5e18 * 2**192\n r += 600920179829731861736702779321621459595472258049074101567377883020018308;\n // base conversion: mul 2**18 / 2**192\n r >>= 174;\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n LOW LEVEL FIXED POINT OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function mulDivDown(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // Divide z by the denominator.\n z := div(z, denominator)\n }\n }\n\n function mulDivUp(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 z) {\n assembly {\n // Store x * y in z for now.\n z := mul(x, y)\n\n // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))\n if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {\n revert(0, 0)\n }\n\n // First, divide z - 1 by the denominator and add 1.\n // We allow z - 1 to underflow if z is 0, because we multiply the\n // end result by 0 if z is zero, ensuring we return 0 if z is zero.\n z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))\n }\n }\n\n function rpow(\n uint256 x,\n uint256 n,\n uint256 scalar\n ) internal pure returns (uint256 z) {\n assembly {\n switch x\n case 0 {\n switch n\n case 0 {\n // 0 ** 0 = 1\n z := scalar\n }\n default {\n // 0 ** n = 0\n z := 0\n }\n }\n default {\n switch mod(n, 2)\n case 0 {\n // If n is even, store scalar in z for now.\n z := scalar\n }\n default {\n // If n is odd, store x in z for now.\n z := x\n }\n\n // Shifting right by 1 is like dividing by 2.\n let half := shr(1, scalar)\n\n for {\n // Shift n right by 1 before looping to halve it.\n n := shr(1, n)\n } n {\n // Shift n right by 1 each iteration to halve it.\n n := shr(1, n)\n } {\n // Revert immediately if x ** 2 would overflow.\n // Equivalent to iszero(eq(div(xx, x), x)) here.\n if shr(128, x) {\n revert(0, 0)\n }\n\n // Store x squared.\n let xx := mul(x, x)\n\n // Round to the nearest number.\n let xxRound := add(xx, half)\n\n // Revert if xx + half overflowed.\n if lt(xxRound, xx) {\n revert(0, 0)\n }\n\n // Set x to scaled xxRound.\n x := div(xxRound, scalar)\n\n // If n is even:\n if mod(n, 2) {\n // Compute z * x.\n let zx := mul(z, x)\n\n // If z * x overflowed:\n if iszero(eq(div(zx, x), z)) {\n // Revert if x is non-zero.\n if iszero(iszero(x)) {\n revert(0, 0)\n }\n }\n\n // Round to the nearest number.\n let zxRound := add(zx, half)\n\n // Revert if zx + half overflowed.\n if lt(zxRound, zx) {\n revert(0, 0)\n }\n\n // Return properly scaled zxRound.\n z := div(zxRound, scalar)\n }\n }\n }\n }\n }\n\n /*//////////////////////////////////////////////////////////////\n GENERAL NUMBER UTILITIES\n //////////////////////////////////////////////////////////////*/\n\n function sqrt(uint256 x) internal pure returns (uint256 z) {\n assembly {\n let y := x // We start y at x, which will help us make our initial estimate.\n\n z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n // We check y >= 2^(k + 8) but shift right by k bits\n // each branch to ensure that if x >= 256, then y >= 256.\n if iszero(lt(y, 0x10000000000000000000000000000000000)) {\n y := shr(128, y)\n z := shl(64, z)\n }\n if iszero(lt(y, 0x1000000000000000000)) {\n y := shr(64, y)\n z := shl(32, z)\n }\n if iszero(lt(y, 0x10000000000)) {\n y := shr(32, y)\n z := shl(16, z)\n }\n if iszero(lt(y, 0x1000000)) {\n y := shr(16, y)\n z := shl(8, z)\n }\n\n // Goal was to get z*z*y within a small factor of x. More iterations could\n // get y in a tighter range. Currently, we will have y in [256, 256*2^16).\n // We ensured y >= 256 so that the relative difference between y and y+1 is small.\n // That's not possible if x < 256 but we can just verify those cases exhaustively.\n\n // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.\n // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.\n // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.\n\n // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range\n // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.\n\n // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate\n // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.\n\n // There is no overflow risk here since y < 2^136 after the first branch above.\n z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.\n\n // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n\n // If x+1 is a perfect square, the Babylonian method cycles between\n // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.\n // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n z := sub(z, lt(div(x, z), z))\n }\n }\n\n function log2(uint256 x) internal pure returns (uint256 r) {\n require(x > 0, \"UNDEFINED\");\n\n assembly {\n r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n r := or(r, shl(4, lt(0xffff, shr(r, x))))\n r := or(r, shl(3, lt(0xff, shr(r, x))))\n r := or(r, shl(2, lt(0xf, shr(r, x))))\n r := or(r, shl(1, lt(0x3, shr(r, x))))\n r := or(r, lt(0x1, shr(r, x)))\n }\n }\n}\n" - } - }, - "settings": { - "remappings": [ - "@openzeppelin/=node_modules/@openzeppelin/", - "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", - "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", - "@rari-capital/=node_modules/@rari-capital/", - "@rari-capital/solmate/=node_modules/@rari-capital/solmate/", - "@safe-global/safe-contracts/=node_modules/@safe-global/safe-contracts/", - "ds-test/=node_modules/ds-test/src/", - "forge-std/=node_modules/forge-std/src/", - "solady/=node_modules/solady/src/" - ], - "optimizer": { - "enabled": true, - "runs": 999999 - }, - "metadata": { - "bytecodeHash": "none" - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "storageLayout", - "devdoc", - "userdoc" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-mainnet/.chainId b/packages/contracts-bedrock/deployments/optimism-mainnet/.chainId deleted file mode 100644 index 9a037142aa3c..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/.chainId +++ /dev/null @@ -1 +0,0 @@ -10 \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-mainnet/AssetReceiver.json b/packages/contracts-bedrock/deployments/optimism-mainnet/AssetReceiver.json deleted file mode 100644 index 90bda4e9e155..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/AssetReceiver.json +++ /dev/null @@ -1,505 +0,0 @@ -{ - "address": "0x15DdA60616Ffca20371ED1659dBB78E888f65556", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "ReceivedETH", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrewERC20", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "WithdrewERC721", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "withdrawer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrewETH", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_gas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "CALL", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_gas", - "type": "uint256" - } - ], - "name": "DELEGATECALL", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "setOwner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC20", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC20", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ERC721", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - } - ], - "name": "withdrawERC721", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdrawETH", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - } - ], - "name": "withdrawETH", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "transactionHash": "0xc478761265f900cc77738ebe913f9894e4e31f5eb9571521d2c82eedcde263aa", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "887432", - "logsBloom": "0x00100000000000000001000000000000000000000000000000000000000000000000100000000000000000100000080000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000020000000000000000000000000000000000000000000000", - "blockHash": "0xba4660a5466eba797503a88256c703f1c0019eec12d403db1a6f998d285281c5", - "transactionHash": "0xc478761265f900cc77738ebe913f9894e4e31f5eb9571521d2c82eedcde263aa", - "logs": [ - { - "transactionIndex": 0, - "blockNumber": 10573944, - "transactionHash": "0xc478761265f900cc77738ebe913f9894e4e31f5eb9571521d2c82eedcde263aa", - "address": "0x15DdA60616Ffca20371ED1659dBB78E888f65556", - "topics": [ - "0x8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58" - ], - "data": "0x", - "logIndex": 0, - "blockHash": "0xba4660a5466eba797503a88256c703f1c0019eec12d403db1a6f998d285281c5" - } - ], - "blockNumber": 10573944, - "cumulativeGasUsed": "887432", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 2, - "solcInputHash": "66d28de48de020e62747d42ffe3118e7", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ReceivedETH\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrewERC20\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"WithdrewERC721\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WithdrewETH\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_gas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"CALL\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_gas\",\"type\":\"uint256\"}],\"name\":\"DELEGATECALL\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC20\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"withdrawERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ERC721\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_id\",\"type\":\"uint256\"}],\"name\":\"withdrawERC721\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"withdrawETH\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"CALL(address,bytes,uint256,uint256)\":{\"params\":{\"_data\":\"Data to send with the call.\",\"_gas\":\"Amount of gas to send with the call.\",\"_target\":\"Address to call.\",\"_value\":\"ETH value to send with the call.\"},\"returns\":{\"_0\":\"Boolean success value.\",\"_1\":\"Bytes data returned by the call.\"}},\"DELEGATECALL(address,bytes,uint256)\":{\"params\":{\"_data\":\"Data to send with the call.\",\"_gas\":\"Amount of gas to send with the call.\",\"_target\":\"Address to call.\"},\"returns\":{\"_0\":\"Boolean success value.\",\"_1\":\"Bytes data returned by the call.\"}},\"constructor\":{\"params\":{\"_owner\":\"Initial contract owner.\"}},\"withdrawERC20(address,address)\":{\"params\":{\"_asset\":\"ERC20 token to withdraw.\",\"_to\":\"Address to receive the ERC20 balance.\"}},\"withdrawERC20(address,address,uint256)\":{\"params\":{\"_amount\":\"Amount of ERC20 to withdraw.\",\"_asset\":\"ERC20 token to withdraw.\",\"_to\":\"Address to receive the ERC20 balance.\"}},\"withdrawERC721(address,address,uint256)\":{\"params\":{\"_asset\":\"ERC721 token to withdraw.\",\"_id\":\"Token ID of the ERC721 token to withdraw.\",\"_to\":\"Address to receive the ERC721 token.\"}},\"withdrawETH(address)\":{\"params\":{\"_to\":\"Address to receive the ETH balance.\"}},\"withdrawETH(address,uint256)\":{\"params\":{\"_amount\":\"Amount of ETH to withdraw.\",\"_to\":\"Address to receive the ETH balance.\"}}},\"title\":\"AssetReceiver\",\"version\":1},\"userdoc\":{\"events\":{\"ReceivedETH(address,uint256)\":{\"notice\":\"Emitted when ETH is received by this address.\"},\"WithdrewERC20(address,address,address,uint256)\":{\"notice\":\"Emitted when ERC20 tokens are withdrawn from this address.\"},\"WithdrewERC721(address,address,address,uint256)\":{\"notice\":\"Emitted when ERC721 tokens are withdrawn from this address.\"},\"WithdrewETH(address,address,uint256)\":{\"notice\":\"Emitted when ETH is withdrawn from this address.\"}},\"kind\":\"user\",\"methods\":{\"CALL(address,bytes,uint256,uint256)\":{\"notice\":\"Sends a CALL to a target address.\"},\"DELEGATECALL(address,bytes,uint256)\":{\"notice\":\"Sends a DELEGATECALL to a target address.\"},\"withdrawERC20(address,address)\":{\"notice\":\"Withdraws full ERC20 balance to the recipient.\"},\"withdrawERC20(address,address,uint256)\":{\"notice\":\"Withdraws partial ERC20 balance to the recipient.\"},\"withdrawERC721(address,address,uint256)\":{\"notice\":\"Withdraws ERC721 token to the recipient.\"},\"withdrawETH(address)\":{\"notice\":\"Withdraws full ETH balance to the recipient.\"},\"withdrawETH(address,uint256)\":{\"notice\":\"Withdraws partial ETH balance to the recipient.\"}},\"notice\":\"AssetReceiver is a minimal contract for receiving funds assets in the form of either ETH, ERC20 tokens, or ERC721 tokens. Only the contract owner may withdraw the assets.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/AssetReceiver.sol\":\"AssetReceiver\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@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\",\"keccak256\":\"0x7e91c80b0dd1a14a19cb9e661b99924043adab6d9d893bbfcf3a6a3dc23a6743\",\"license\":\"AGPL-3.0-only\"},\"@rari-capital/solmate/src/tokens/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\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\",\"keccak256\":\"0x0240f7703cff32a61ee3e9fbb339e09a944260432a9ef37debf3692b1a6c8049\",\"license\":\"AGPL-3.0-only\"},\"@rari-capital/solmate/src/tokens/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-only\\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 require(\\n to.code.length == 0 ||\\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 require(\\n to.code.length == 0 ||\\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 require(\\n to.code.length == 0 ||\\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 require(\\n to.code.length == 0 ||\\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\",\"keccak256\":\"0xb59c7c25eca386f39da4819a9f70f89b73b7583d5f5127a83ffe5339800b1183\",\"license\":\"AGPL-3.0-only\"},\"contracts/universal/AssetReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\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 * Emitted when ETH is received by this address.\\n */\\n event ReceivedETH(address indexed from, uint256 amount);\\n\\n /**\\n * Emitted when ETH is withdrawn from this address.\\n */\\n event WithdrewETH(address indexed withdrawer, address indexed recipient, uint256 amount);\\n\\n /**\\n * Emitted when ERC20 tokens are withdrawn from this address.\\n */\\n event WithdrewERC20(\\n address indexed withdrawer,\\n address indexed recipient,\\n address indexed asset,\\n uint256 amount\\n );\\n\\n /**\\n * Emitted when ERC721 tokens are withdrawn from this address.\\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 * Make sure we can receive ETH.\\n */\\n receive() external payable {\\n emit ReceivedETH(msg.sender, msg.value);\\n }\\n\\n /**\\n * 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 * 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 _to.transfer(_amount);\\n emit WithdrewETH(msg.sender, _to, _amount);\\n }\\n\\n /**\\n * 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 * 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 * 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\",\"keccak256\":\"0x1f82aff6f4e5a4bebebbfb4a2e0e4378ef9bc5bee8b81f88b27fc0ce73546d5f\",\"license\":\"MIT\"},\"contracts/universal/Transactor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.9;\\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 _gas Amount of gas to send with the call.\\n * @param _value ETH value to send with the call.\\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 _gas,\\n uint256 _value\\n ) external payable onlyOwner returns (bool, bytes memory) {\\n return _target.call{ gas: _gas, 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 * @param _gas Amount of gas to send with the call.\\n * @return Boolean success value.\\n * @return Bytes data returned by the call.\\n */\\n function DELEGATECALL(\\n address _target,\\n bytes memory _data,\\n uint256 _gas\\n ) external payable onlyOwner returns (bool, bytes memory) {\\n // slither-disable-next-line controlled-delegatecall\\n return _target.delegatecall{ gas: _gas }(_data);\\n }\\n}\\n\",\"keccak256\":\"0xfe0d9c05a423d36775047e3285f76b874f8b887444d412a0d680c302c3b06a50\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50604051610f6e380380610f6e83398101604081905261002f91610081565b600080546001600160a01b0319166001600160a01b038316908117825560405183928392917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a35050506100b1565b60006020828403121561009357600080fd5b81516001600160a01b03811681146100aa57600080fd5b9392505050565b610eae806100c06000396000f3fe60806040526004361061009a5760003560e01c80635cef8b4a116100695780638da5cb5b1161004e5780638da5cb5b146101a75780639456fbcc146101f95780639e73dbea1461021957600080fd5b80635cef8b4a1461015d578063690d83201461018757600080fd5b806313af4035146100db5780634025feb2146100fd57806344004cc11461011d5780634782f7791461013d57600080fd5b366100d65760405134815233907f4103257eaac983ca79a70d28f90dfc4fa16b619bb0c17ee7cab0d4034c2796249060200160405180910390a2005b600080fd5b3480156100e757600080fd5b506100fb6100f6366004610b3a565b61022c565b005b34801561010957600080fd5b506100fb610118366004610b5e565b610322565b34801561012957600080fd5b506100fb610138366004610b5e565b6104b4565b34801561014957600080fd5b506100fb610158366004610b9f565b610654565b61017061016b366004610ca5565b61076a565b60405161017e929190610d2e565b60405180910390f35b34801561019357600080fd5b506100fb6101a2366004610b3a565b610863565b3480156101b357600080fd5b506000546101d49073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161017e565b34801561020557600080fd5b506100fb610214366004610d88565b6108f1565b610170610227366004610dc1565b610a1b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b15801561041957600080fd5b505af115801561042d573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f30b478a5e196e55886228aa87ba74a7dfeba655e0a4d7ba275eabfc22aabb7a8846040516104a791815260200190565b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb90604401602060405180830381600087803b1580156105a557600080fd5b505af11580156105b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105dd9190610e21565b508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f6b00f1c7883f053ba83e907fd1965b22fffe3c4111383e725f04638a566cdbfa846040516104a791815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b60405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610718573d6000803e3d6000fd5b5060405181815273ffffffffffffffffffffffffffffffffffffffff83169033907f1f12aa8b6d492dd9b98e2b00b0b20830c2a7ded65afac13b60d169a034ae90bc9060200160405180910390a35050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff1633146107ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b8473ffffffffffffffffffffffffffffffffffffffff1683856040516108159190610e43565b6000604051808303818686f4925050503d8060008114610851576040519150601f19603f3d011682016040523d82523d6000602084013e610856565b606091505b5091509150935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6108ee8147610654565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610a17908390839073ffffffffffffffffffffffffffffffffffffffff8316906370a082319060240160206040518083038186803b1580156109df57600080fd5b505afa1580156109f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101389190610e5f565b5050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610aa0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b8573ffffffffffffffffffffffffffffffffffffffff16848487604051610ac79190610e43565b600060405180830381858888f193505050503d8060008114610b05576040519150601f19603f3d011682016040523d82523d6000602084013e610b0a565b606091505b509150915094509492505050565b73ffffffffffffffffffffffffffffffffffffffff811681146108ee57600080fd5b600060208284031215610b4c57600080fd5b8135610b5781610b18565b9392505050565b600080600060608486031215610b7357600080fd5b8335610b7e81610b18565b92506020840135610b8e81610b18565b929592945050506040919091013590565b60008060408385031215610bb257600080fd5b8235610bbd81610b18565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610c0b57600080fd5b813567ffffffffffffffff80821115610c2657610c26610bcb565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610c6c57610c6c610bcb565b81604052838152866020858801011115610c8557600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215610cba57600080fd5b8335610cc581610b18565b9250602084013567ffffffffffffffff811115610ce157600080fd5b610ced86828701610bfa565b925050604084013590509250925092565b60005b83811015610d19578181015183820152602001610d01565b83811115610d28576000848401525b50505050565b82151581526040602082015260008251806040840152610d55816060850160208701610cfe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b60008060408385031215610d9b57600080fd5b8235610da681610b18565b91506020830135610db681610b18565b809150509250929050565b60008060008060808587031215610dd757600080fd5b8435610de281610b18565b9350602085013567ffffffffffffffff811115610dfe57600080fd5b610e0a87828801610bfa565b949794965050505060408301359260600135919050565b600060208284031215610e3357600080fd5b81518015158114610b5757600080fd5b60008251610e55818460208701610cfe565b9190910192915050565b600060208284031215610e7157600080fd5b505191905056fea2646970667358221220a79fda18860baa011a378f2e4963a1c9eb8fa5184c5fd3130308ce3c35ba96da64736f6c63430008090033", - "deployedBytecode": "0x60806040526004361061009a5760003560e01c80635cef8b4a116100695780638da5cb5b1161004e5780638da5cb5b146101a75780639456fbcc146101f95780639e73dbea1461021957600080fd5b80635cef8b4a1461015d578063690d83201461018757600080fd5b806313af4035146100db5780634025feb2146100fd57806344004cc11461011d5780634782f7791461013d57600080fd5b366100d65760405134815233907f4103257eaac983ca79a70d28f90dfc4fa16b619bb0c17ee7cab0d4034c2796249060200160405180910390a2005b600080fd5b3480156100e757600080fd5b506100fb6100f6366004610b3a565b61022c565b005b34801561010957600080fd5b506100fb610118366004610b5e565b610322565b34801561012957600080fd5b506100fb610138366004610b5e565b6104b4565b34801561014957600080fd5b506100fb610158366004610b9f565b610654565b61017061016b366004610ca5565b61076a565b60405161017e929190610d2e565b60405180910390f35b34801561019357600080fd5b506100fb6101a2366004610b3a565b610863565b3480156101b357600080fd5b506000546101d49073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161017e565b34801561020557600080fd5b506100fb610214366004610d88565b6108f1565b610170610227366004610dc1565b610a1b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146102b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6040517f23b872dd00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152604482018390528416906323b872dd90606401600060405180830381600087803b15801561041957600080fd5b505af115801561042d573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f30b478a5e196e55886228aa87ba74a7dfeba655e0a4d7ba275eabfc22aabb7a8846040516104a791815260200190565b60405180910390a4505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301526024820183905284169063a9059cbb90604401602060405180830381600087803b1580156105a557600080fd5b505af11580156105b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105dd9190610e21565b508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f6b00f1c7883f053ba83e907fd1965b22fffe3c4111383e725f04638a566cdbfa846040516104a791815260200190565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b60405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f19350505050158015610718573d6000803e3d6000fd5b5060405181815273ffffffffffffffffffffffffffffffffffffffff83169033907f1f12aa8b6d492dd9b98e2b00b0b20830c2a7ded65afac13b60d169a034ae90bc9060200160405180910390a35050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff1633146107ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b8473ffffffffffffffffffffffffffffffffffffffff1683856040516108159190610e43565b6000604051808303818686f4925050503d8060008114610851576040519150601f19603f3d011682016040523d82523d6000602084013e610856565b606091505b5091509150935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6108ee8147610654565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610a17908390839073ffffffffffffffffffffffffffffffffffffffff8316906370a082319060240160206040518083038186803b1580156109df57600080fd5b505afa1580156109f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101389190610e5f565b5050565b6000805460609073ffffffffffffffffffffffffffffffffffffffff163314610aa0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a4544000000000000000000000000000000000000000060448201526064016102a9565b8573ffffffffffffffffffffffffffffffffffffffff16848487604051610ac79190610e43565b600060405180830381858888f193505050503d8060008114610b05576040519150601f19603f3d011682016040523d82523d6000602084013e610b0a565b606091505b509150915094509492505050565b73ffffffffffffffffffffffffffffffffffffffff811681146108ee57600080fd5b600060208284031215610b4c57600080fd5b8135610b5781610b18565b9392505050565b600080600060608486031215610b7357600080fd5b8335610b7e81610b18565b92506020840135610b8e81610b18565b929592945050506040919091013590565b60008060408385031215610bb257600080fd5b8235610bbd81610b18565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610c0b57600080fd5b813567ffffffffffffffff80821115610c2657610c26610bcb565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610c6c57610c6c610bcb565b81604052838152866020858801011115610c8557600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215610cba57600080fd5b8335610cc581610b18565b9250602084013567ffffffffffffffff811115610ce157600080fd5b610ced86828701610bfa565b925050604084013590509250925092565b60005b83811015610d19578181015183820152602001610d01565b83811115610d28576000848401525b50505050565b82151581526040602082015260008251806040840152610d55816060850160208701610cfe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b60008060408385031215610d9b57600080fd5b8235610da681610b18565b91506020830135610db681610b18565b809150509250929050565b60008060008060808587031215610dd757600080fd5b8435610de281610b18565b9350602085013567ffffffffffffffff811115610dfe57600080fd5b610e0a87828801610bfa565b949794965050505060408301359260600135919050565b600060208284031215610e3357600080fd5b81518015158114610b5757600080fd5b60008251610e55818460208701610cfe565b9190910192915050565b600060208284031215610e7157600080fd5b505191905056fea2646970667358221220a79fda18860baa011a378f2e4963a1c9eb8fa5184c5fd3130308ce3c35ba96da64736f6c63430008090033", - "devdoc": { - "kind": "dev", - "methods": { - "CALL(address,bytes,uint256,uint256)": { - "params": { - "_data": "Data to send with the call.", - "_gas": "Amount of gas to send with the call.", - "_target": "Address to call.", - "_value": "ETH value to send with the call." - }, - "returns": { - "_0": "Boolean success value.", - "_1": "Bytes data returned by the call." - } - }, - "DELEGATECALL(address,bytes,uint256)": { - "params": { - "_data": "Data to send with the call.", - "_gas": "Amount of gas to send with the call.", - "_target": "Address to call." - }, - "returns": { - "_0": "Boolean success value.", - "_1": "Bytes data returned by the call." - } - }, - "constructor": { - "params": { - "_owner": "Initial contract owner." - } - }, - "withdrawERC20(address,address)": { - "params": { - "_asset": "ERC20 token to withdraw.", - "_to": "Address to receive the ERC20 balance." - } - }, - "withdrawERC20(address,address,uint256)": { - "params": { - "_amount": "Amount of ERC20 to withdraw.", - "_asset": "ERC20 token to withdraw.", - "_to": "Address to receive the ERC20 balance." - } - }, - "withdrawERC721(address,address,uint256)": { - "params": { - "_asset": "ERC721 token to withdraw.", - "_id": "Token ID of the ERC721 token to withdraw.", - "_to": "Address to receive the ERC721 token." - } - }, - "withdrawETH(address)": { - "params": { - "_to": "Address to receive the ETH balance." - } - }, - "withdrawETH(address,uint256)": { - "params": { - "_amount": "Amount of ETH to withdraw.", - "_to": "Address to receive the ETH balance." - } - } - }, - "title": "AssetReceiver", - "version": 1 - }, - "userdoc": { - "events": { - "ReceivedETH(address,uint256)": { - "notice": "Emitted when ETH is received by this address." - }, - "WithdrewERC20(address,address,address,uint256)": { - "notice": "Emitted when ERC20 tokens are withdrawn from this address." - }, - "WithdrewERC721(address,address,address,uint256)": { - "notice": "Emitted when ERC721 tokens are withdrawn from this address." - }, - "WithdrewETH(address,address,uint256)": { - "notice": "Emitted when ETH is withdrawn from this address." - } - }, - "kind": "user", - "methods": { - "CALL(address,bytes,uint256,uint256)": { - "notice": "Sends a CALL to a target address." - }, - "DELEGATECALL(address,bytes,uint256)": { - "notice": "Sends a DELEGATECALL to a target address." - }, - "withdrawERC20(address,address)": { - "notice": "Withdraws full ERC20 balance to the recipient." - }, - "withdrawERC20(address,address,uint256)": { - "notice": "Withdraws partial ERC20 balance to the recipient." - }, - "withdrawERC721(address,address,uint256)": { - "notice": "Withdraws ERC721 token to the recipient." - }, - "withdrawETH(address)": { - "notice": "Withdraws full ETH balance to the recipient." - }, - "withdrawETH(address,uint256)": { - "notice": "Withdraws partial ETH balance to the recipient." - } - }, - "notice": "AssetReceiver is a minimal contract for receiving funds assets in the form of either ETH, ERC20 tokens, or ERC721 tokens. Only the contract owner may withdraw the assets.", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 10, - "contract": "contracts/universal/AssetReceiver.sol:AssetReceiver", - "label": "owner", - "offset": 0, - "slot": "0", - "type": "t_address" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-mainnet/AttestationStation.json b/packages/contracts-bedrock/deployments/optimism-mainnet/AttestationStation.json deleted file mode 100644 index 550f3107c92a..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/AttestationStation.json +++ /dev/null @@ -1,270 +0,0 @@ -{ - "address": "0xbeD744818e96AAD8a51324291a6f6Cb20A0c22be", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "creator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "about", - "type": "address" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "val", - "type": "bytes" - } - ], - "name": "AttestationCreated", - "type": "event" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "about", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "val", - "type": "bytes" - } - ], - "internalType": "struct AttestationStation.AttestationData[]", - "name": "_attestations", - "type": "tuple[]" - } - ], - "name": "attest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_about", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_key", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "_val", - "type": "bytes" - } - ], - "name": "attest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "attestations", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x0272013b1d20b4b8e2b8153867389c1c75cbbd5c50e564ee71a62dbfcc35f062", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x956a5152D0f498dBA0c5966577bb44262F8F7078", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "666309", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x6d539badaadce9732f2f79e1ceaee94499dd0003d42862324ff334bd7e7e6e68", - "transactionHash": "0x0272013b1d20b4b8e2b8153867389c1c75cbbd5c50e564ee71a62dbfcc35f062", - "logs": [], - "blockNumber": 70643992, - "cumulativeGasUsed": "666309", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 2, - "solcInputHash": "3aa2ad7d005d9515a1f12df8da17d178", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"about\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"val\",\"type\":\"bytes\"}],\"name\":\"AttestationCreated\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"about\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"val\",\"type\":\"bytes\"}],\"internalType\":\"struct AttestationStation.AttestationData[]\",\"name\":\"_attestations\",\"type\":\"tuple[]\"}],\"name\":\"attest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_about\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_val\",\"type\":\"bytes\"}],\"name\":\"attest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"attestations\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Optimism CollectiveGitcoin\",\"events\":{\"AttestationCreated(address,address,bytes32,bytes)\":{\"params\":{\"about\":\"Address attestation is about.\",\"creator\":\"Address that made the attestation.\",\"key\":\"Key of the attestation.\",\"val\":\"Value of the attestation.\"}}},\"kind\":\"dev\",\"methods\":{\"attest((address,bytes32,bytes)[])\":{\"params\":{\"_attestations\":\"An array of attestation data.\"}},\"attest(address,bytes32,bytes)\":{\"params\":{\"_about\":\"Address that the attestation is about.\",\"_key\":\"A key used to namespace the attestation.\",\"_val\":\"An arbitrary value stored as part of the attestation.\"}},\"constructor\":{\"custom:semver\":\"1.1.0\"},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"AttestationStation\",\"version\":1},\"userdoc\":{\"events\":{\"AttestationCreated(address,address,bytes32,bytes)\":{\"notice\":\"Emitted when Attestation is created.\"}},\"kind\":\"user\",\"methods\":{\"attest((address,bytes32,bytes)[])\":{\"notice\":\"Allows anyone to create attestations.\"},\"attest(address,bytes32,bytes)\":{\"notice\":\"Allows anyone to create an attestation.\"},\"attestations(address,address,bytes32)\":{\"notice\":\"Maps addresses to attestations. Creator => About => Key => Value.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"Where attestations live.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/op-nft/AttestationStation.sol\":\"AttestationStation\"},\"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 uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\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\":\"0x979b13465de4996a1105850abbf48abe7f71d5e18a8d4af318597ee14c165fdf\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\\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 /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/universal/op-nft/AttestationStation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title AttestationStation\\n * @author Optimism Collective\\n * @author Gitcoin\\n * @notice Where attestations live.\\n */\\ncontract AttestationStation is Semver {\\n /**\\n * @notice Struct representing data that is being attested.\\n *\\n * @custom:field about Address for which the attestation is about.\\n * @custom:field key A bytes32 key for the attestation.\\n * @custom:field val The attestation as arbitrary bytes.\\n */\\n struct AttestationData {\\n address about;\\n bytes32 key;\\n bytes val;\\n }\\n\\n /**\\n * @notice Maps addresses to attestations. Creator => About => Key => Value.\\n */\\n mapping(address => mapping(address => mapping(bytes32 => bytes))) public attestations;\\n\\n /**\\n * @notice Emitted when Attestation is created.\\n *\\n * @param creator Address that made the attestation.\\n * @param about Address attestation is about.\\n * @param key Key of the attestation.\\n * @param val Value of the attestation.\\n */\\n event AttestationCreated(\\n address indexed creator,\\n address indexed about,\\n bytes32 indexed key,\\n bytes val\\n );\\n\\n /**\\n * @custom:semver 1.1.0\\n */\\n constructor() Semver(1, 1, 0) {}\\n\\n /**\\n * @notice Allows anyone to create an attestation.\\n *\\n * @param _about Address that the attestation is about.\\n * @param _key A key used to namespace the attestation.\\n * @param _val An arbitrary value stored as part of the attestation.\\n */\\n function attest(\\n address _about,\\n bytes32 _key,\\n bytes memory _val\\n ) public {\\n attestations[msg.sender][_about][_key] = _val;\\n\\n emit AttestationCreated(msg.sender, _about, _key, _val);\\n }\\n\\n /**\\n * @notice Allows anyone to create attestations.\\n *\\n * @param _attestations An array of attestation data.\\n */\\n function attest(AttestationData[] calldata _attestations) external {\\n uint256 length = _attestations.length;\\n for (uint256 i = 0; i < length; ) {\\n AttestationData memory attestation = _attestations[i];\\n\\n attest(attestation.about, attestation.key, attestation.val);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x80718fdc09061ea8f8b99a0b846eee46c5a2a1372dbb0cbc3d40953cb3af19e0\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60e060405234801561001057600080fd5b506001608081905260a052600060c05260805160a05160c051610b1c61004f60003960006101ad015260006101840152600061015b0152610b1c6000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c806329b42cb51461005157806354fd4d501461007a5780635eb5ea1014610082578063702b9dee14610097575b600080fd5b61006461005f36600461046c565b6100aa565b604051610071919061051e565b60405180910390f35b610064610154565b610095610090366004610538565b6101f7565b005b6100956100a5366004610687565b61025a565b60006020818152938152604080822085529281528281209093528252902080546100d3906106de565b80601f01602080910402602001604051908101604052809291908181526020018280546100ff906106de565b801561014c5780601f106101215761010080835404028352916020019161014c565b820191906000526020600020905b81548152906001019060200180831161012f57829003601f168201915b505050505081565b606061017f7f0000000000000000000000000000000000000000000000000000000000000000610306565b6101a87f0000000000000000000000000000000000000000000000000000000000000000610306565b6101d17f0000000000000000000000000000000000000000000000000000000000000000610306565b6040516020016101e393929190610731565b604051602081830303815290604052905090565b8060005b81811015610254576000848483818110610217576102176107a7565b905060200281019061022991906107d6565b61023290610814565b905061024b81600001518260200151836040015161025a565b506001016101fb565b50505050565b3360009081526020818152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320858452909152902061029a82826108df565b50818373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f28710dfecab43d1e29e02aa56b2e1e610c0bae19135c9cf7a83a1adb6df96d85846040516102f9919061051e565b60405180910390a4505050565b60608160000361034957505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610373578061035d81610a28565b915061036c9050600a83610a8f565b915061034d565b60008167ffffffffffffffff81111561038e5761038e6105ad565b6040519080825280601f01601f1916602001820160405280156103b8576020820181803683370190505b5090505b841561043b576103cd600183610aa3565b91506103da600a86610aba565b6103e5906030610ace565b60f81b8183815181106103fa576103fa6107a7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610434600a86610a8f565b94506103bc565b949350505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461046757600080fd5b919050565b60008060006060848603121561048157600080fd5b61048a84610443565b925061049860208501610443565b9150604084013590509250925092565b60005b838110156104c35781810151838201526020016104ab565b838111156102545750506000910152565b600081518084526104ec8160208601602086016104a8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061053160208301846104d4565b9392505050565b6000806020838503121561054b57600080fd5b823567ffffffffffffffff8082111561056357600080fd5b818501915085601f83011261057757600080fd5b81358181111561058657600080fd5b8660208260051b850101111561059b57600080fd5b60209290920196919550909350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126105ed57600080fd5b813567ffffffffffffffff80821115610608576106086105ad565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561064e5761064e6105ad565b8160405283815286602085880101111561066757600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561069c57600080fd5b6106a584610443565b925060208401359150604084013567ffffffffffffffff8111156106c857600080fd5b6106d4868287016105dc565b9150509250925092565b600181811c908216806106f257607f821691505b60208210810361072b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600084516107438184602089016104a8565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161077f816001850160208a016104a8565b6001920191820152835161079a8160028401602088016104a8565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261080a57600080fd5b9190910192915050565b60006060823603121561082657600080fd5b6040516060810167ffffffffffffffff828210818311171561084a5761084a6105ad565b8160405261085785610443565b835260208501356020840152604085013591508082111561087757600080fd5b50610884368286016105dc565b60408301525092915050565b601f8211156108da57600081815260208120601f850160051c810160208610156108b75750805b601f850160051c820191505b818110156108d6578281556001016108c3565b5050505b505050565b815167ffffffffffffffff8111156108f9576108f96105ad565b61090d8161090784546106de565b84610890565b602080601f831160018114610960576000841561092a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556108d6565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156109ad5788860151825594840194600190910190840161098e565b50858210156109e957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610a5957610a596109f9565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a9e57610a9e610a60565b500490565b600082821015610ab557610ab56109f9565b500390565b600082610ac957610ac9610a60565b500690565b60008219821115610ae157610ae16109f9565b50019056fea2646970667358221220bfd4abacc1c2510682b093eea8745255cdd9f45c5b16c168540522a65ddc1f3264736f6c634300080f0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806329b42cb51461005157806354fd4d501461007a5780635eb5ea1014610082578063702b9dee14610097575b600080fd5b61006461005f36600461046c565b6100aa565b604051610071919061051e565b60405180910390f35b610064610154565b610095610090366004610538565b6101f7565b005b6100956100a5366004610687565b61025a565b60006020818152938152604080822085529281528281209093528252902080546100d3906106de565b80601f01602080910402602001604051908101604052809291908181526020018280546100ff906106de565b801561014c5780601f106101215761010080835404028352916020019161014c565b820191906000526020600020905b81548152906001019060200180831161012f57829003601f168201915b505050505081565b606061017f7f0000000000000000000000000000000000000000000000000000000000000000610306565b6101a87f0000000000000000000000000000000000000000000000000000000000000000610306565b6101d17f0000000000000000000000000000000000000000000000000000000000000000610306565b6040516020016101e393929190610731565b604051602081830303815290604052905090565b8060005b81811015610254576000848483818110610217576102176107a7565b905060200281019061022991906107d6565b61023290610814565b905061024b81600001518260200151836040015161025a565b506001016101fb565b50505050565b3360009081526020818152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320858452909152902061029a82826108df565b50818373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f28710dfecab43d1e29e02aa56b2e1e610c0bae19135c9cf7a83a1adb6df96d85846040516102f9919061051e565b60405180910390a4505050565b60608160000361034957505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610373578061035d81610a28565b915061036c9050600a83610a8f565b915061034d565b60008167ffffffffffffffff81111561038e5761038e6105ad565b6040519080825280601f01601f1916602001820160405280156103b8576020820181803683370190505b5090505b841561043b576103cd600183610aa3565b91506103da600a86610aba565b6103e5906030610ace565b60f81b8183815181106103fa576103fa6107a7565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610434600a86610a8f565b94506103bc565b949350505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461046757600080fd5b919050565b60008060006060848603121561048157600080fd5b61048a84610443565b925061049860208501610443565b9150604084013590509250925092565b60005b838110156104c35781810151838201526020016104ab565b838111156102545750506000910152565b600081518084526104ec8160208601602086016104a8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061053160208301846104d4565b9392505050565b6000806020838503121561054b57600080fd5b823567ffffffffffffffff8082111561056357600080fd5b818501915085601f83011261057757600080fd5b81358181111561058657600080fd5b8660208260051b850101111561059b57600080fd5b60209290920196919550909350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126105ed57600080fd5b813567ffffffffffffffff80821115610608576106086105ad565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561064e5761064e6105ad565b8160405283815286602085880101111561066757600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561069c57600080fd5b6106a584610443565b925060208401359150604084013567ffffffffffffffff8111156106c857600080fd5b6106d4868287016105dc565b9150509250925092565b600181811c908216806106f257607f821691505b60208210810361072b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600084516107438184602089016104a8565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161077f816001850160208a016104a8565b6001920191820152835161079a8160028401602088016104a8565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261080a57600080fd5b9190910192915050565b60006060823603121561082657600080fd5b6040516060810167ffffffffffffffff828210818311171561084a5761084a6105ad565b8160405261085785610443565b835260208501356020840152604085013591508082111561087757600080fd5b50610884368286016105dc565b60408301525092915050565b601f8211156108da57600081815260208120601f850160051c810160208610156108b75750805b601f850160051c820191505b818110156108d6578281556001016108c3565b5050505b505050565b815167ffffffffffffffff8111156108f9576108f96105ad565b61090d8161090784546106de565b84610890565b602080601f831160018114610960576000841561092a5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556108d6565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156109ad5788860151825594840194600190910190840161098e565b50858210156109e957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610a5957610a596109f9565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a9e57610a9e610a60565b500490565b600082821015610ab557610ab56109f9565b500390565b600082610ac957610ac9610a60565b500690565b60008219821115610ae157610ae16109f9565b50019056fea2646970667358221220bfd4abacc1c2510682b093eea8745255cdd9f45c5b16c168540522a65ddc1f3264736f6c634300080f0033", - "devdoc": { - "author": "Optimism CollectiveGitcoin", - "events": { - "AttestationCreated(address,address,bytes32,bytes)": { - "params": { - "about": "Address attestation is about.", - "creator": "Address that made the attestation.", - "key": "Key of the attestation.", - "val": "Value of the attestation." - } - } - }, - "kind": "dev", - "methods": { - "attest((address,bytes32,bytes)[])": { - "params": { - "_attestations": "An array of attestation data." - } - }, - "attest(address,bytes32,bytes)": { - "params": { - "_about": "Address that the attestation is about.", - "_key": "A key used to namespace the attestation.", - "_val": "An arbitrary value stored as part of the attestation." - } - }, - "constructor": { - "custom:semver": "1.1.0" - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "title": "AttestationStation", - "version": 1 - }, - "userdoc": { - "events": { - "AttestationCreated(address,address,bytes32,bytes)": { - "notice": "Emitted when Attestation is created." - } - }, - "kind": "user", - "methods": { - "attest((address,bytes32,bytes)[])": { - "notice": "Allows anyone to create attestations." - }, - "attest(address,bytes32,bytes)": { - "notice": "Allows anyone to create an attestation." - }, - "attestations(address,address,bytes32)": { - "notice": "Maps addresses to attestations. Creator => About => Key => Value." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "Where attestations live.", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 2135, - "contract": "contracts/universal/op-nft/AttestationStation.sol:AttestationStation", - "label": "attestations", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_bytes32,t_bytes_storage)))" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_bytes_storage": { - "encoding": "bytes", - "label": "bytes", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_mapping(t_bytes32,t_bytes_storage)))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => mapping(bytes32 => bytes)))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_mapping(t_bytes32,t_bytes_storage))" - }, - "t_mapping(t_address,t_mapping(t_bytes32,t_bytes_storage))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(bytes32 => bytes))", - "numberOfBytes": "32", - "value": "t_mapping(t_bytes32,t_bytes_storage)" - }, - "t_mapping(t_bytes32,t_bytes_storage)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => bytes)", - "numberOfBytes": "32", - "value": "t_bytes_storage" - } - } - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-mainnet/AttestationStationProxy.json b/packages/contracts-bedrock/deployments/optimism-mainnet/AttestationStationProxy.json deleted file mode 100644 index b9b59ffc2858..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/AttestationStationProxy.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "address": "0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77", - "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": "0xddf8785bc33a64924409c4588a7664b210c469c6a658ae36ef106a4ed6c324ca", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "534190", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000008000000000000000000000000", - "blockHash": "0x59216851b5a511cd84c75a7b796ca0f23331bc52c92085d4a5921061428b82f6", - "transactionHash": "0xddf8785bc33a64924409c4588a7664b210c469c6a658ae36ef106a4ed6c324ca", - "logs": [ - { - "transactionIndex": 0, - "blockNumber": 49669971, - "transactionHash": "0xddf8785bc33a64924409c4588a7664b210c469c6a658ae36ef106a4ed6c324ca", - "address": "0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58", - "logIndex": 0, - "blockHash": "0x59216851b5a511cd84c75a7b796ca0f23331bc52c92085d4a5921061428b82f6" - } - ], - "blockNumber": 49669971, - "cumulativeGasUsed": "534190", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "45837d34ff24b9cb2ae34232b60ea874", - "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-bedrock/deployments/optimism-mainnet/EAS.json b/packages/contracts-bedrock/deployments/optimism-mainnet/EAS.json deleted file mode 100644 index 0964371988a0..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/EAS.json +++ /dev/null @@ -1,1534 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AccessDenied", - "type": "error" - }, - { - "inputs": [], - "name": "AlreadyRevoked", - "type": "error" - }, - { - "inputs": [], - "name": "AlreadyRevokedOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "AlreadyTimestamped", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientValue", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidAttestation", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidAttestations", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidExpirationTime", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidOffset", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRegistry", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRevocation", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRevocations", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSchema", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSignature", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidVerifier", - "type": "error" - }, - { - "inputs": [], - "name": "Irrevocable", - "type": "error" - }, - { - "inputs": [], - "name": "NotFound", - "type": "error" - }, - { - "inputs": [], - "name": "NotPayable", - "type": "error" - }, - { - "inputs": [], - "name": "WrongSchema", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "attester", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - } - ], - "name": "Attested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "attester", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - } - ], - "name": "Revoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "revoker", - "type": "address" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - } - ], - "name": "RevokedOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - } - ], - "name": "Timestamped", - "type": "event" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint64", - "name": "expirationTime", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "refUID", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct AttestationRequestData", - "name": "data", - "type": "tuple" - } - ], - "internalType": "struct AttestationRequest", - "name": "request", - "type": "tuple" - } - ], - "name": "attest", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint64", - "name": "expirationTime", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "refUID", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct AttestationRequestData", - "name": "data", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "internalType": "struct EIP712Signature", - "name": "signature", - "type": "tuple" - }, - { - "internalType": "address", - "name": "attester", - "type": "address" - } - ], - "internalType": "struct DelegatedAttestationRequest", - "name": "delegatedRequest", - "type": "tuple" - } - ], - "name": "attestByDelegation", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "getAttestTypeHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - } - ], - "name": "getAttestation", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "time", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "expirationTime", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "revocationTime", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "refUID", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "address", - "name": "attester", - "type": "address" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Attestation", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getDomainSeparator", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getName", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "getNonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "revoker", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - } - ], - "name": "getRevokeOffchain", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRevokeTypeHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getSchemaRegistry", - "outputs": [ - { - "internalType": "contract ISchemaRegistry", - "name": "", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - } - ], - "name": "getTimestamp", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - } - ], - "name": "isAttestationValid", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint64", - "name": "expirationTime", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "refUID", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct AttestationRequestData[]", - "name": "data", - "type": "tuple[]" - } - ], - "internalType": "struct MultiAttestationRequest[]", - "name": "multiRequests", - "type": "tuple[]" - } - ], - "name": "multiAttest", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint64", - "name": "expirationTime", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "refUID", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct AttestationRequestData[]", - "name": "data", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "internalType": "struct EIP712Signature[]", - "name": "signatures", - "type": "tuple[]" - }, - { - "internalType": "address", - "name": "attester", - "type": "address" - } - ], - "internalType": "struct MultiDelegatedAttestationRequest[]", - "name": "multiDelegatedRequests", - "type": "tuple[]" - } - ], - "name": "multiAttestByDelegation", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct RevocationRequestData[]", - "name": "data", - "type": "tuple[]" - } - ], - "internalType": "struct MultiRevocationRequest[]", - "name": "multiRequests", - "type": "tuple[]" - } - ], - "name": "multiRevoke", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct RevocationRequestData[]", - "name": "data", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "internalType": "struct EIP712Signature[]", - "name": "signatures", - "type": "tuple[]" - }, - { - "internalType": "address", - "name": "revoker", - "type": "address" - } - ], - "internalType": "struct MultiDelegatedRevocationRequest[]", - "name": "multiDelegatedRequests", - "type": "tuple[]" - } - ], - "name": "multiRevokeByDelegation", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "data", - "type": "bytes32[]" - } - ], - "name": "multiRevokeOffchain", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "data", - "type": "bytes32[]" - } - ], - "name": "multiTimestamp", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct RevocationRequestData", - "name": "data", - "type": "tuple" - } - ], - "internalType": "struct RevocationRequest", - "name": "request", - "type": "tuple" - } - ], - "name": "revoke", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "schema", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "internalType": "struct RevocationRequestData", - "name": "data", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "internalType": "struct EIP712Signature", - "name": "signature", - "type": "tuple" - }, - { - "internalType": "address", - "name": "revoker", - "type": "address" - } - ], - "internalType": "struct DelegatedRevocationRequest", - "name": "delegatedRequest", - "type": "tuple" - } - ], - "name": "revokeByDelegation", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - } - ], - "name": "revokeOffchain", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - } - ], - "name": "timestamp", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "address": "0x4E0275Ea5a89e7a3c1B58411379D1a0eDdc5b088", - "args": [], - "bytecode": "0x6101c06040523480156200001257600080fd5b50604080518082018252600381526245415360e81b602080830191825283518085019094526005845264312e302e3160d81b90840190815260016080819052600060a05260c052825190912083519091206101408290526101608190524661010052919291839183917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ec8184846040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b60e0523061012052610180525050505060208201516101a052506200010e9050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516144df6200018a60003960006105410152600061265b015260006126aa01526000612685015260006125de0152600061260801526000612632015260006108730152600061084a0152600061082101526144df6000f3fe6080604052600436106101805760003560e01c8063b469318d116100d6578063e45d03f91161007f578063ed24911d11610059578063ed24911d1461049e578063f10b5cc8146104b3578063f17325e7146104e257600080fd5b8063e45d03f914610458578063e57a6b1b1461046b578063e71ff3651461047e57600080fd5b8063d45c4435116100b0578063d45c4435146103cf578063e13458fc14610406578063e30bb5631461041957600080fd5b8063b469318d14610322578063b83010d31461037c578063cf190f34146103af57600080fd5b8063469262671161013857806354fd4d501161011257806354fd4d50146102cd578063831e05a1146102e2578063a3112a64146102f557600080fd5b806346926267146102855780634cb7e9e51461029a5780634d003070146102ad57600080fd5b806317d7de7c1161016957806317d7de7c146102005780632d0335ab1461022257806344adc90e1461026557600080fd5b806312b11a171461018557806313893f61146101c7575b600080fd5b34801561019157600080fd5b507fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de615b6040519081526020015b60405180910390f35b3480156101d357600080fd5b506101e76101e23660046133ee565b6104f5565b60405167ffffffffffffffff90911681526020016101be565b34801561020c57600080fd5b5061021561053a565b6040516101be919061349e565b34801561022e57600080fd5b506101b461023d3660046134ea565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6102786102733660046133ee565b61056a565b6040516101be9190613507565b61029861029336600461354b565b6106a1565b005b6102986102a83660046133ee565b610725565b3480156102b957600080fd5b506101e76102c8366004613563565b61080d565b3480156102d957600080fd5b5061021561081a565b6102786102f03660046133ee565b6108bd565b34801561030157600080fd5b50610315610310366004613563565b610b0e565b6040516101be9190613663565b34801561032e57600080fd5b506101e761033d366004613676565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152603460209081526040808320938352929052205467ffffffffffffffff1690565b34801561038857600080fd5b507fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a996506101b4565b3480156103bb57600080fd5b506101e76103ca366004613563565b610cd1565b3480156103db57600080fd5b506101e76103ea366004613563565b60009081526033602052604090205467ffffffffffffffff1690565b6101b46104143660046136a2565b610cdf565b34801561042557600080fd5b50610448610434366004613563565b600090815260326020526040902054151590565b60405190151581526020016101be565b6102986104663660046133ee565b610de2565b6102986104793660046136dd565b610f5d565b34801561048a57600080fd5b506101e76104993660046133ee565b611002565b3480156104aa57600080fd5b506101b461103a565b3480156104bf57600080fd5b5060405173420000000000000000000000000000000000002081526020016101be565b6101b46104f03660046136ef565b611044565b60004282825b8181101561052e57610526338787848181106105195761051961372a565b9050602002013585611102565b6001016104fb565b50909150505b92915050565b60606105657f0000000000000000000000000000000000000000000000000000000000000000611201565b905090565b606060008267ffffffffffffffff81111561058757610587613759565b6040519080825280602002602001820160405280156105ba57816020015b60608152602001906001900390816105a55790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86018114368888848181106106025761060261372a565b90506020028101906106149190613788565b9050600061063b823561062a60208501856137c6565b61063391613a3f565b33888761138f565b805190915061064a9086613ae2565b945080602001518785815181106106635761066361372a565b6020026020010181905250806020015151860195505050506106858160010190565b90506105c2565b506106978383611aa1565b9695505050505050565b604080516001808252818301909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816106b85790505090506106f336839003830160208401613b44565b816000815181106107065761070661372a565b602090810291909101015261072082358233346001611b6e565b505050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83018114368585848181106107695761076961372a565b905060200281019061077b9190613788565b90506107e8813561078f6020840184613b60565b808060200260200160405190810160405280939291908181526020016000905b828210156107db576107cc60408302860136819003810190613b44565b815260200190600101906107af565b5050505050338786611b6e565b6107f29085613ae2565b935050506108008160010190565b9050610729565b50505050565b60004261053483826121a8565b60606108457f000000000000000000000000000000000000000000000000000000000000000061226a565b61086e7f000000000000000000000000000000000000000000000000000000000000000061226a565b6108977f000000000000000000000000000000000000000000000000000000000000000061226a565b6040516020016108a993929190613bc8565b604051602081830303815290604052905090565b606060008267ffffffffffffffff8111156108da576108da613759565b60405190808252806020026020018201604052801561090d57816020015b60608152602001906001900390816108f85790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86018114368888848181106109555761095561372a565b90506020028101906109679190613c3e565b905036600061097960208401846137c6565b909250905080158061099957506109936040840184613c72565b82141590505b156109d0576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a9257610a8a604051806080016040528086600001358152602001858585818110610a0557610a0561372a565b9050602002810190610a179190613cd9565b610a2090613d0d565b8152602001610a326040880188613c72565b85818110610a4257610a4261372a565b905060600201803603810190610a589190613d84565b8152602001610a6d60808801606089016134ea565b73ffffffffffffffffffffffffffffffffffffffff1690526123a7565b6001016109d3565b506000610abb8435610aa48486613a3f565b610ab460808801606089016134ea565b8a8961138f565b8051909150610aca9088613ae2565b96508060200151898781518110610ae357610ae361372a565b6020026020010181905250806020015151880197505050505050610b078160010190565b9050610915565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082019290925261012081019190915260008281526032602090815260409182902082516101408101845281548152600182015492810192909252600281015467ffffffffffffffff808216948401949094526801000000000000000081048416606084015270010000000000000000000000000000000090049092166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff16151561010082015260068201805491929161012084019190610c4890613da0565b80601f0160208091040260200160405190810160405280929190818152602001828054610c7490613da0565b8015610cc15780601f10610c9657610100808354040283529160200191610cc1565b820191906000526020600020905b815481529060010190602001808311610ca457829003601f168201915b5050505050815250509050919050565b600042610534338483611102565b6000610cf2610ced83613ded565b6123a7565b604080516001808252818301909252600091816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610d09579050509050610d776020840184613cd9565b610d8090613d0d565b81600081518110610d9357610d9361372a565b6020908102919091010152610dbc833582610db460c0870160a088016134ea565b34600161138f565b60200151600081518110610dd257610dd261372a565b6020026020010151915050919050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830181146000858584818110610e2757610e2761372a565b9050602002810190610e399190613c3e565b610e4290613ed2565b60208101518051919250901580610e5f5750816040015151815114155b15610e96576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8151811015610f2757610f1f604051806080016040528085600001518152602001848481518110610ecc57610ecc61372a565b6020026020010151815260200185604001518481518110610eef57610eef61372a565b60200260200101518152602001856060015173ffffffffffffffffffffffffffffffffffffffff16815250612536565b600101610e99565b50610f3d82600001518284606001518887611b6e565b610f479086613ae2565b9450505050610f568160010190565b9050610de6565b610f74610f6f36839003830183613fb1565b612536565b604080516001808252818301909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081610f8b579050509050610fc636839003830160208401613b44565b81600081518110610fd957610fd961372a565b6020908102919091010152610720823582610ffa60e0860160c087016134ea565b346001611b6e565b60004282825b8181101561052e576110328686838181106110255761102561372a565b90506020020135846121a8565b600101611008565b60006105656125c4565b604080516001808252818301909252600091829190816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161105e5790505090506110cc6020840184613cd9565b6110d590613d0d565b816000815181106110e8576110e861372a565b6020908102919091010152610dbc8335823334600161138f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152603460209081526040808320858452918290529091205467ffffffffffffffff1615611176576040517fec9d6eeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526020829052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff861690811790915590519091859173ffffffffffffffffffffffffffffffffffffffff8816917f92a1f7a41a7c585a8b09e25b195e225b1d43248daca46b0faf9e0792777a222991a450505050565b604080516020808252818301909252606091600091906020820181803683370190505090506000805b60208110156112cc5760008582602081106112475761124761372a565b1a60f81b90507fff00000000000000000000000000000000000000000000000000000000000000811660000361127d57506112cc565b808484815181106112905761129061372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350506001918201910161122a565b5060008167ffffffffffffffff8111156112e8576112e8613759565b6040519080825280601f01601f191660200182016040528015611312576020820181803683370190505b50905060005b82811015611386578381815181106113325761133261372a565b602001015160f81c60f81b82828151811061134f5761134f61372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101611318565b50949350505050565b60408051808201909152600081526060602082015284516040805180820190915260008152606060208201528167ffffffffffffffff8111156113d4576113d4613759565b6040519080825280602002602001820160405280156113fd578160200160208202803683370190505b5060208201526040517fa2ea7c6e000000000000000000000000000000000000000000000000000000008152600481018990526000907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa15801561146f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114b5919081019061400d565b80519091506114f0576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008367ffffffffffffffff81111561150b5761150b613759565b6040519080825280602002602001820160405280156115aa57816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816115295790505b50905060008467ffffffffffffffff8111156115c8576115c8613759565b6040519080825280602002602001820160405280156115f1578160200160208202803683370190505b50905060005b85811015611a805760008b82815181106116135761161361372a565b60200260200101519050600067ffffffffffffffff16816020015167ffffffffffffffff161415801561165e57504267ffffffffffffffff16816020015167ffffffffffffffff1611155b15611695576040517f08e8b93700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84604001511580156116a8575080604001515b156116df576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052806000801b81526020018f81526020016117034290565b67ffffffffffffffff168152602001836020015167ffffffffffffffff168152602001600067ffffffffffffffff16815260200183606001518152602001836000015173ffffffffffffffffffffffffffffffffffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815260200183604001511515815260200183608001518152509050600080600090505b6117a583826126f8565b600081815260326020526040902054909250156117c45760010161179b565b81835260008281526032602090815260409182902085518155908501516001820155908401516002820180546060870151608088015167ffffffffffffffff908116700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff92821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169190951617919091171691909117905560a0840151600382015560c084015160048201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560e0850151600583018054610100880151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff000000000000000000000000000000000000000000909116929093169190911791909117905561012084015184919060068201906119449082614133565b50505060608401511561199b57606084015160009081526032602052604090205461199b576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828786815181106119ae576119ae61372a565b60200260200101819052508360a001518686815181106119d0576119d061372a565b60200260200101818152505081896020015186815181106119f3576119f361372a565b6020026020010181815250508f8e73ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff167f8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b3585604051611a6391815260200190565b60405180910390a450505050611a798160010190565b90506115f7565b50611a9083838360008c8c612757565b845250919998505050505050505050565b606060008267ffffffffffffffff811115611abe57611abe613759565b604051908082528060200260200182016040528015611ae7578160200160208202803683370190505b5090506000805b855181101561052e576000868281518110611b0b57611b0b61372a565b6020026020010151905060005b8151811015611b6457818181518110611b3357611b3361372a565b6020026020010151858581518110611b4d57611b4d61372a565b602090810291909101015260019384019301611b18565b5050600101611aee565b6040517fa2ea7c6e0000000000000000000000000000000000000000000000000000000081526004810186905260009081907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa158015611bdc573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611c22919081019061400d565b8051909150611c5d576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855160008167ffffffffffffffff811115611c7a57611c7a613759565b604051908082528060200260200182016040528015611d1957816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611c985790505b50905060008267ffffffffffffffff811115611d3757611d37613759565b604051908082528060200260200182016040528015611d60578160200160208202803683370190505b50905060005b8381101561218a5760008a8281518110611d8257611d8261372a565b6020908102919091018101518051600090815260329092526040909120805491925090611ddb576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8c816001015414611e18576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015473ffffffffffffffffffffffffffffffffffffffff8c8116911614611e6e576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015474010000000000000000000000000000000000000000900460ff16611ec4576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002810154700100000000000000000000000000000000900467ffffffffffffffff1615611f1e576040517f905e710700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b426002820180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff811670010000000000000000000000000000000067ffffffffffffffff948516810291821793849055604080516101408101825287548152600188015460208201529386169286169290921791830191909152680100000000000000008304841660608301529091049091166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff161515610100820152600682018054839161012084019161202a90613da0565b80601f016020809104026020016040519081016040528092919081815260200182805461205690613da0565b80156120a35780601f10612078576101008083540402835291602001916120a3565b820191906000526020600020905b81548152906001019060200180831161208657829003601f168201915b5050505050815250508584815181106120be576120be61372a565b602002602001018190525081602001518484815181106120e0576120e061372a565b60200260200101818152505080600101548b73ffffffffffffffffffffffffffffffffffffffff168260040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167ff930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f615856000015160405161217891815260200190565b60405180910390a45050600101611d66565b5061219a84838360018b8b612757565b9a9950505050505050505050565b60008281526033602052604090205467ffffffffffffffff16156121f8576040517f2e26794600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526033602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051909184917f5aafceeb1c7ad58e4a84898bdee37c02c0fc46e7d24e6b60e8209449f183459f9190a35050565b6060816000036122ad57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156122d757806122c18161424d565b91506122d09050600a836142b4565b91506122b1565b60008167ffffffffffffffff8111156122f2576122f2613759565b6040519080825280601f01601f19166020018201604052801561231c576020820181803683370190505b5090505b841561239f57612331600183613ae2565b915061233e600a866142c8565b6123499060306142dc565b60f81b81838151811061235e5761235e61372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612398600a866142b4565b9450612320565b949350505050565b60208082015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865187890151878901519589015160808a01518051908c01209851999a9799949895976124ad97612492977fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de619791939290918c9101978852602088019690965273ffffffffffffffffffffffffffffffffffffffff94909416604087015267ffffffffffffffff9290921660608601521515608085015260a084015260c083015260e08201526101000190565b60405160208183030381529060405280519060200120612b31565b9050846060015173ffffffffffffffffffffffffffffffffffffffff166124e282856000015186602001518760400151612b44565b73ffffffffffffffffffffffffffffffffffffffff161461252f576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b60208181015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865186517fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a99650998101999099529588015291860193909352608085018190529293909291906124ad9060a001612492565b60003073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561262a57507f000000000000000000000000000000000000000000000000000000000000000046145b1561265457507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60208083015160c084015160e0850151604080870151606088015161010089015160a08a01516101208b0151945160009961273999989796918c91016142ef565b60405160208183030381529060405280519060200120905092915050565b845160009060018190036127af576127a7888860008151811061277c5761277c61372a565b6020026020010151886000815181106127975761279761372a565b6020026020010151888888612b6c565b915050610697565b602088015173ffffffffffffffffffffffffffffffffffffffff81166128415760005b82811015612835578781815181106127ec576127ec61372a565b602002602001015160001461282d576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016127d2565b50600092505050610697565b6000805b8381101561296b5760008982815181106128615761286161372a565b60200260200101519050806000141580156128e857508373ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e691906143cd565b155b1561291f576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87811115612959576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b96879003969190910190600101612845565b508615612a46576040517f88e5b2d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906388e5b2d99083906129c8908d908d906004016143ea565b60206040518083038185885af11580156129e6573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612a0b91906143cd565b612a41576040517fbf2f3a8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b15565b6040517f91db0b7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906391db0b7e908390612a9c908d908d906004016143ea565b60206040518083038185885af1158015612aba573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612adf91906143cd565b612b15576040517fe8bee83900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415612b2457612b2486612e82565b9998505050505050505050565b6000610534612b3e6125c4565b83612e95565b6000806000612b5587878787612ed7565b91509150612b6281612fef565b5095945050505050565b602086015160009073ffffffffffffffffffffffffffffffffffffffff8116612bd1578515612bc7576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000915050610697565b8515801590612c4c57508073ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c4a91906143cd565b155b15612c83576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83861115612cbd576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85840393508415612d9a576040517fe49617e100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e49617e1908890612d1c908b90600401613663565b60206040518083038185885af1158015612d3a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612d5f91906143cd565b612d95576040517fccf3bb2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e67565b6040517fe60c350500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e60c3505908890612dee908b90600401613663565b60206040518083038185885af1158015612e0c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612e3191906143cd565b612e67576040517fbd8ba84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215612e7657612e7684612e82565b50939695505050505050565b8015612e9257612e923382613248565b50565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526022810183905260428101829052600090606201612739565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612f0e5750600090506003612fe6565b8460ff16601b14158015612f2657508460ff16601c14155b15612f375750600090506004612fe6565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612f8b573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612fdf57600060019250925050612fe6565b9150600090505b94509492505050565b6000816004811115613003576130036144a3565b0361300b5750565b600181600481111561301f5761301f6144a3565b0361308b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064015b60405180910390fd5b600281600481111561309f5761309f6144a3565b03613106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401613082565b600381600481111561311a5761311a6144a3565b036131a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401613082565b60048160048111156131bb576131bb6144a3565b03612e92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401613082565b804710156132b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401613082565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461330c576040519150601f19603f3d011682016040523d82523d6000602084013e613311565b606091505b5050905080610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401613082565b60008083601f8401126133b457600080fd5b50813567ffffffffffffffff8111156133cc57600080fd5b6020830191508360208260051b85010111156133e757600080fd5b9250929050565b6000806020838503121561340157600080fd5b823567ffffffffffffffff81111561341857600080fd5b613424858286016133a2565b90969095509350505050565b60005b8381101561344b578181015183820152602001613433565b50506000910152565b6000815180845261346c816020860160208601613430565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006134b16020830184613454565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114612e9257600080fd5b80356134e5816134b8565b919050565b6000602082840312156134fc57600080fd5b81356134b1816134b8565b6020808252825182820181905260009190848201906040850190845b8181101561353f57835183529284019291840191600101613523565b50909695505050505050565b60006060828403121561355d57600080fd5b50919050565b60006020828403121561357557600080fd5b5035919050565b6000610140825184526020830151602085015260408301516135aa604086018267ffffffffffffffff169052565b5060608301516135c6606086018267ffffffffffffffff169052565b5060808301516135e2608086018267ffffffffffffffff169052565b5060a083015160a085015260c083015161361460c086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e083015161363c60e086018273ffffffffffffffffffffffffffffffffffffffff169052565b50610100838101511515908501526101208084015181860183905261069783870182613454565b6020815260006134b1602083018461357c565b6000806040838503121561368957600080fd5b8235613694816134b8565b946020939093013593505050565b6000602082840312156136b457600080fd5b813567ffffffffffffffff8111156136cb57600080fd5b820160c081850312156134b157600080fd5b600060e0828403121561355d57600080fd5b60006020828403121561370157600080fd5b813567ffffffffffffffff81111561371857600080fd5b8201604081850312156134b157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126137bc57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126137fb57600080fd5b83018035915067ffffffffffffffff82111561381657600080fd5b6020019150600581901b36038213156133e757600080fd5b60405160c0810167ffffffffffffffff8111828210171561385157613851613759565b60405290565b6040516080810167ffffffffffffffff8111828210171561385157613851613759565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138c1576138c1613759565b604052919050565b600067ffffffffffffffff8211156138e3576138e3613759565b5060051b60200190565b8015158114612e9257600080fd5b80356134e5816138ed565b600067ffffffffffffffff82111561392057613920613759565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261395d57600080fd5b813561397061396b82613906565b61387a565b81815284602083860101111561398557600080fd5b816020850160208301376000918101602001919091529392505050565b600060c082840312156139b457600080fd5b6139bc61382e565b905081356139c9816134b8565b8152602082013567ffffffffffffffff80821682146139e757600080fd5b8160208401526139f9604085016138fb565b6040840152606084013560608401526080840135915080821115613a1c57600080fd5b50613a298482850161394c565b60808301525060a082013560a082015292915050565b6000613a4d61396b846138c9565b80848252602080830192508560051b850136811115613a6b57600080fd5b855b81811015613aa757803567ffffffffffffffff811115613a8d5760008081fd5b613a9936828a016139a2565b865250938201938201613a6d565b50919695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561053457610534613ab3565b600060408284031215613b0757600080fd5b6040516040810181811067ffffffffffffffff82111715613b2a57613b2a613759565b604052823581526020928301359281019290925250919050565b600060408284031215613b5657600080fd5b6134b18383613af5565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613b9557600080fd5b83018035915067ffffffffffffffff821115613bb057600080fd5b6020019150600681901b36038213156133e757600080fd5b60008451613bda818460208901613430565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551613c16816001850160208a01613430565b60019201918201528351613c31816002840160208801613430565b0160020195945050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818336030181126137bc57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613ca757600080fd5b83018035915067ffffffffffffffff821115613cc257600080fd5b60200191506060810236038213156133e757600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff418336030181126137bc57600080fd5b600061053436836139a2565b600060608284031215613d2b57600080fd5b6040516060810181811067ffffffffffffffff82111715613d4e57613d4e613759565b604052905080823560ff81168114613d6557600080fd5b8082525060208301356020820152604083013560408201525092915050565b600060608284031215613d9657600080fd5b6134b18383613d19565b600181811c90821680613db457607f821691505b60208210810361355d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060c08236031215613dff57600080fd5b613e07613857565b82358152602083013567ffffffffffffffff811115613e2557600080fd5b613e31368286016139a2565b602083015250613e443660408501613d19565b604082015260a0830135613e57816134b8565b606082015292915050565b600082601f830112613e7357600080fd5b81356020613e8361396b836138c9565b82815260609283028501820192828201919087851115613ea257600080fd5b8387015b85811015613ec557613eb88982613d19565b8452928401928101613ea6565b5090979650505050505050565b600060808236031215613ee457600080fd5b613eec613857565b8235815260208084013567ffffffffffffffff80821115613f0c57600080fd5b9085019036601f830112613f1f57600080fd5b8135613f2d61396b826138c9565b81815260069190911b83018401908481019036831115613f4c57600080fd5b938501935b82851015613f7557613f633686613af5565b82528582019150604085019450613f51565b80868801525050506040860135925080831115613f9157600080fd5b5050613f9f36828601613e62565b604083015250613e57606084016134da565b600060e08284031215613fc357600080fd5b613fcb613857565b82358152613fdc8460208501613af5565b6020820152613fee8460608501613d19565b604082015260c0830135614001816134b8565b60608201529392505050565b6000602080838503121561402057600080fd5b825167ffffffffffffffff8082111561403857600080fd5b908401906080828703121561404c57600080fd5b614054613857565b8251815283830151614065816134b8565b818501526040830151614077816138ed565b604082015260608301518281111561408e57600080fd5b80840193505086601f8401126140a357600080fd5b825191506140b361396b83613906565b82815287858486010111156140c757600080fd5b6140d683868301878701613430565b60608201529695505050505050565b601f82111561072057600081815260208120601f850160051c8101602086101561410c5750805b601f850160051c820191505b8181101561412b57828155600101614118565b505050505050565b815167ffffffffffffffff81111561414d5761414d613759565b6141618161415b8454613da0565b846140e5565b602080601f8311600181146141b4576000841561417e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561412b565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614201578886015182559484019460019091019084016141e2565b508582101561423d57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361427e5761427e613ab3565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826142c3576142c3614285565b500490565b6000826142d7576142d7614285565b500690565b8082018082111561053457610534613ab3565b89815260007fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808b60601b166020840152808a60601b166034840152507fffffffffffffffff000000000000000000000000000000000000000000000000808960c01b166048840152808860c01b1660508401525085151560f81b60588301528460598301528351614388816079850160208801613430565b80830190507fffffffff000000000000000000000000000000000000000000000000000000008460e01b166079820152607d81019150509a9950505050505050505050565b6000602082840312156143df57600080fd5b81516134b1816138ed565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b8381101561445f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa088870301855261444d86835161357c565b95509382019390820190600101614413565b50508584038187015286518085528782019482019350915060005b828110156144965784518452938101939281019260010161447a565b5091979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c6343000813000a", - "deployedBytecode": "0x6080604052600436106101805760003560e01c8063b469318d116100d6578063e45d03f91161007f578063ed24911d11610059578063ed24911d1461049e578063f10b5cc8146104b3578063f17325e7146104e257600080fd5b8063e45d03f914610458578063e57a6b1b1461046b578063e71ff3651461047e57600080fd5b8063d45c4435116100b0578063d45c4435146103cf578063e13458fc14610406578063e30bb5631461041957600080fd5b8063b469318d14610322578063b83010d31461037c578063cf190f34146103af57600080fd5b8063469262671161013857806354fd4d501161011257806354fd4d50146102cd578063831e05a1146102e2578063a3112a64146102f557600080fd5b806346926267146102855780634cb7e9e51461029a5780634d003070146102ad57600080fd5b806317d7de7c1161016957806317d7de7c146102005780632d0335ab1461022257806344adc90e1461026557600080fd5b806312b11a171461018557806313893f61146101c7575b600080fd5b34801561019157600080fd5b507fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de615b6040519081526020015b60405180910390f35b3480156101d357600080fd5b506101e76101e23660046133ee565b6104f5565b60405167ffffffffffffffff90911681526020016101be565b34801561020c57600080fd5b5061021561053a565b6040516101be919061349e565b34801561022e57600080fd5b506101b461023d3660046134ea565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6102786102733660046133ee565b61056a565b6040516101be9190613507565b61029861029336600461354b565b6106a1565b005b6102986102a83660046133ee565b610725565b3480156102b957600080fd5b506101e76102c8366004613563565b61080d565b3480156102d957600080fd5b5061021561081a565b6102786102f03660046133ee565b6108bd565b34801561030157600080fd5b50610315610310366004613563565b610b0e565b6040516101be9190613663565b34801561032e57600080fd5b506101e761033d366004613676565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152603460209081526040808320938352929052205467ffffffffffffffff1690565b34801561038857600080fd5b507fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a996506101b4565b3480156103bb57600080fd5b506101e76103ca366004613563565b610cd1565b3480156103db57600080fd5b506101e76103ea366004613563565b60009081526033602052604090205467ffffffffffffffff1690565b6101b46104143660046136a2565b610cdf565b34801561042557600080fd5b50610448610434366004613563565b600090815260326020526040902054151590565b60405190151581526020016101be565b6102986104663660046133ee565b610de2565b6102986104793660046136dd565b610f5d565b34801561048a57600080fd5b506101e76104993660046133ee565b611002565b3480156104aa57600080fd5b506101b461103a565b3480156104bf57600080fd5b5060405173420000000000000000000000000000000000002081526020016101be565b6101b46104f03660046136ef565b611044565b60004282825b8181101561052e57610526338787848181106105195761051961372a565b9050602002013585611102565b6001016104fb565b50909150505b92915050565b60606105657f0000000000000000000000000000000000000000000000000000000000000000611201565b905090565b606060008267ffffffffffffffff81111561058757610587613759565b6040519080825280602002602001820160405280156105ba57816020015b60608152602001906001900390816105a55790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86018114368888848181106106025761060261372a565b90506020028101906106149190613788565b9050600061063b823561062a60208501856137c6565b61063391613a3f565b33888761138f565b805190915061064a9086613ae2565b945080602001518785815181106106635761066361372a565b6020026020010181905250806020015151860195505050506106858160010190565b90506105c2565b506106978383611aa1565b9695505050505050565b604080516001808252818301909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816106b85790505090506106f336839003830160208401613b44565b816000815181106107065761070661372a565b602090810291909101015261072082358233346001611b6e565b505050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83018114368585848181106107695761076961372a565b905060200281019061077b9190613788565b90506107e8813561078f6020840184613b60565b808060200260200160405190810160405280939291908181526020016000905b828210156107db576107cc60408302860136819003810190613b44565b815260200190600101906107af565b5050505050338786611b6e565b6107f29085613ae2565b935050506108008160010190565b9050610729565b50505050565b60004261053483826121a8565b60606108457f000000000000000000000000000000000000000000000000000000000000000061226a565b61086e7f000000000000000000000000000000000000000000000000000000000000000061226a565b6108977f000000000000000000000000000000000000000000000000000000000000000061226a565b6040516020016108a993929190613bc8565b604051602081830303815290604052905090565b606060008267ffffffffffffffff8111156108da576108da613759565b60405190808252806020026020018201604052801561090d57816020015b60608152602001906001900390816108f85790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86018114368888848181106109555761095561372a565b90506020028101906109679190613c3e565b905036600061097960208401846137c6565b909250905080158061099957506109936040840184613c72565b82141590505b156109d0576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a9257610a8a604051806080016040528086600001358152602001858585818110610a0557610a0561372a565b9050602002810190610a179190613cd9565b610a2090613d0d565b8152602001610a326040880188613c72565b85818110610a4257610a4261372a565b905060600201803603810190610a589190613d84565b8152602001610a6d60808801606089016134ea565b73ffffffffffffffffffffffffffffffffffffffff1690526123a7565b6001016109d3565b506000610abb8435610aa48486613a3f565b610ab460808801606089016134ea565b8a8961138f565b8051909150610aca9088613ae2565b96508060200151898781518110610ae357610ae361372a565b6020026020010181905250806020015151880197505050505050610b078160010190565b9050610915565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082019290925261012081019190915260008281526032602090815260409182902082516101408101845281548152600182015492810192909252600281015467ffffffffffffffff808216948401949094526801000000000000000081048416606084015270010000000000000000000000000000000090049092166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff16151561010082015260068201805491929161012084019190610c4890613da0565b80601f0160208091040260200160405190810160405280929190818152602001828054610c7490613da0565b8015610cc15780601f10610c9657610100808354040283529160200191610cc1565b820191906000526020600020905b815481529060010190602001808311610ca457829003601f168201915b5050505050815250509050919050565b600042610534338483611102565b6000610cf2610ced83613ded565b6123a7565b604080516001808252818301909252600091816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610d09579050509050610d776020840184613cd9565b610d8090613d0d565b81600081518110610d9357610d9361372a565b6020908102919091010152610dbc833582610db460c0870160a088016134ea565b34600161138f565b60200151600081518110610dd257610dd261372a565b6020026020010151915050919050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830181146000858584818110610e2757610e2761372a565b9050602002810190610e399190613c3e565b610e4290613ed2565b60208101518051919250901580610e5f5750816040015151815114155b15610e96576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8151811015610f2757610f1f604051806080016040528085600001518152602001848481518110610ecc57610ecc61372a565b6020026020010151815260200185604001518481518110610eef57610eef61372a565b60200260200101518152602001856060015173ffffffffffffffffffffffffffffffffffffffff16815250612536565b600101610e99565b50610f3d82600001518284606001518887611b6e565b610f479086613ae2565b9450505050610f568160010190565b9050610de6565b610f74610f6f36839003830183613fb1565b612536565b604080516001808252818301909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081610f8b579050509050610fc636839003830160208401613b44565b81600081518110610fd957610fd961372a565b6020908102919091010152610720823582610ffa60e0860160c087016134ea565b346001611b6e565b60004282825b8181101561052e576110328686838181106110255761102561372a565b90506020020135846121a8565b600101611008565b60006105656125c4565b604080516001808252818301909252600091829190816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161105e5790505090506110cc6020840184613cd9565b6110d590613d0d565b816000815181106110e8576110e861372a565b6020908102919091010152610dbc8335823334600161138f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152603460209081526040808320858452918290529091205467ffffffffffffffff1615611176576040517fec9d6eeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526020829052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff861690811790915590519091859173ffffffffffffffffffffffffffffffffffffffff8816917f92a1f7a41a7c585a8b09e25b195e225b1d43248daca46b0faf9e0792777a222991a450505050565b604080516020808252818301909252606091600091906020820181803683370190505090506000805b60208110156112cc5760008582602081106112475761124761372a565b1a60f81b90507fff00000000000000000000000000000000000000000000000000000000000000811660000361127d57506112cc565b808484815181106112905761129061372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350506001918201910161122a565b5060008167ffffffffffffffff8111156112e8576112e8613759565b6040519080825280601f01601f191660200182016040528015611312576020820181803683370190505b50905060005b82811015611386578381815181106113325761133261372a565b602001015160f81c60f81b82828151811061134f5761134f61372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101611318565b50949350505050565b60408051808201909152600081526060602082015284516040805180820190915260008152606060208201528167ffffffffffffffff8111156113d4576113d4613759565b6040519080825280602002602001820160405280156113fd578160200160208202803683370190505b5060208201526040517fa2ea7c6e000000000000000000000000000000000000000000000000000000008152600481018990526000907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa15801561146f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114b5919081019061400d565b80519091506114f0576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008367ffffffffffffffff81111561150b5761150b613759565b6040519080825280602002602001820160405280156115aa57816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816115295790505b50905060008467ffffffffffffffff8111156115c8576115c8613759565b6040519080825280602002602001820160405280156115f1578160200160208202803683370190505b50905060005b85811015611a805760008b82815181106116135761161361372a565b60200260200101519050600067ffffffffffffffff16816020015167ffffffffffffffff161415801561165e57504267ffffffffffffffff16816020015167ffffffffffffffff1611155b15611695576040517f08e8b93700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84604001511580156116a8575080604001515b156116df576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052806000801b81526020018f81526020016117034290565b67ffffffffffffffff168152602001836020015167ffffffffffffffff168152602001600067ffffffffffffffff16815260200183606001518152602001836000015173ffffffffffffffffffffffffffffffffffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815260200183604001511515815260200183608001518152509050600080600090505b6117a583826126f8565b600081815260326020526040902054909250156117c45760010161179b565b81835260008281526032602090815260409182902085518155908501516001820155908401516002820180546060870151608088015167ffffffffffffffff908116700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff92821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169190951617919091171691909117905560a0840151600382015560c084015160048201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560e0850151600583018054610100880151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff000000000000000000000000000000000000000000909116929093169190911791909117905561012084015184919060068201906119449082614133565b50505060608401511561199b57606084015160009081526032602052604090205461199b576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828786815181106119ae576119ae61372a565b60200260200101819052508360a001518686815181106119d0576119d061372a565b60200260200101818152505081896020015186815181106119f3576119f361372a565b6020026020010181815250508f8e73ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff167f8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b3585604051611a6391815260200190565b60405180910390a450505050611a798160010190565b90506115f7565b50611a9083838360008c8c612757565b845250919998505050505050505050565b606060008267ffffffffffffffff811115611abe57611abe613759565b604051908082528060200260200182016040528015611ae7578160200160208202803683370190505b5090506000805b855181101561052e576000868281518110611b0b57611b0b61372a565b6020026020010151905060005b8151811015611b6457818181518110611b3357611b3361372a565b6020026020010151858581518110611b4d57611b4d61372a565b602090810291909101015260019384019301611b18565b5050600101611aee565b6040517fa2ea7c6e0000000000000000000000000000000000000000000000000000000081526004810186905260009081907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa158015611bdc573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611c22919081019061400d565b8051909150611c5d576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855160008167ffffffffffffffff811115611c7a57611c7a613759565b604051908082528060200260200182016040528015611d1957816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611c985790505b50905060008267ffffffffffffffff811115611d3757611d37613759565b604051908082528060200260200182016040528015611d60578160200160208202803683370190505b50905060005b8381101561218a5760008a8281518110611d8257611d8261372a565b6020908102919091018101518051600090815260329092526040909120805491925090611ddb576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8c816001015414611e18576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015473ffffffffffffffffffffffffffffffffffffffff8c8116911614611e6e576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015474010000000000000000000000000000000000000000900460ff16611ec4576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002810154700100000000000000000000000000000000900467ffffffffffffffff1615611f1e576040517f905e710700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b426002820180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff811670010000000000000000000000000000000067ffffffffffffffff948516810291821793849055604080516101408101825287548152600188015460208201529386169286169290921791830191909152680100000000000000008304841660608301529091049091166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff161515610100820152600682018054839161012084019161202a90613da0565b80601f016020809104026020016040519081016040528092919081815260200182805461205690613da0565b80156120a35780601f10612078576101008083540402835291602001916120a3565b820191906000526020600020905b81548152906001019060200180831161208657829003601f168201915b5050505050815250508584815181106120be576120be61372a565b602002602001018190525081602001518484815181106120e0576120e061372a565b60200260200101818152505080600101548b73ffffffffffffffffffffffffffffffffffffffff168260040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167ff930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f615856000015160405161217891815260200190565b60405180910390a45050600101611d66565b5061219a84838360018b8b612757565b9a9950505050505050505050565b60008281526033602052604090205467ffffffffffffffff16156121f8576040517f2e26794600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526033602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051909184917f5aafceeb1c7ad58e4a84898bdee37c02c0fc46e7d24e6b60e8209449f183459f9190a35050565b6060816000036122ad57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156122d757806122c18161424d565b91506122d09050600a836142b4565b91506122b1565b60008167ffffffffffffffff8111156122f2576122f2613759565b6040519080825280601f01601f19166020018201604052801561231c576020820181803683370190505b5090505b841561239f57612331600183613ae2565b915061233e600a866142c8565b6123499060306142dc565b60f81b81838151811061235e5761235e61372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612398600a866142b4565b9450612320565b949350505050565b60208082015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865187890151878901519589015160808a01518051908c01209851999a9799949895976124ad97612492977fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de619791939290918c9101978852602088019690965273ffffffffffffffffffffffffffffffffffffffff94909416604087015267ffffffffffffffff9290921660608601521515608085015260a084015260c083015260e08201526101000190565b60405160208183030381529060405280519060200120612b31565b9050846060015173ffffffffffffffffffffffffffffffffffffffff166124e282856000015186602001518760400151612b44565b73ffffffffffffffffffffffffffffffffffffffff161461252f576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b60208181015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865186517fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a99650998101999099529588015291860193909352608085018190529293909291906124ad9060a001612492565b60003073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561262a57507f000000000000000000000000000000000000000000000000000000000000000046145b1561265457507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60208083015160c084015160e0850151604080870151606088015161010089015160a08a01516101208b0151945160009961273999989796918c91016142ef565b60405160208183030381529060405280519060200120905092915050565b845160009060018190036127af576127a7888860008151811061277c5761277c61372a565b6020026020010151886000815181106127975761279761372a565b6020026020010151888888612b6c565b915050610697565b602088015173ffffffffffffffffffffffffffffffffffffffff81166128415760005b82811015612835578781815181106127ec576127ec61372a565b602002602001015160001461282d576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016127d2565b50600092505050610697565b6000805b8381101561296b5760008982815181106128615761286161372a565b60200260200101519050806000141580156128e857508373ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e691906143cd565b155b1561291f576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87811115612959576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b96879003969190910190600101612845565b508615612a46576040517f88e5b2d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906388e5b2d99083906129c8908d908d906004016143ea565b60206040518083038185885af11580156129e6573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612a0b91906143cd565b612a41576040517fbf2f3a8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b15565b6040517f91db0b7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906391db0b7e908390612a9c908d908d906004016143ea565b60206040518083038185885af1158015612aba573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612adf91906143cd565b612b15576040517fe8bee83900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415612b2457612b2486612e82565b9998505050505050505050565b6000610534612b3e6125c4565b83612e95565b6000806000612b5587878787612ed7565b91509150612b6281612fef565b5095945050505050565b602086015160009073ffffffffffffffffffffffffffffffffffffffff8116612bd1578515612bc7576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000915050610697565b8515801590612c4c57508073ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c4a91906143cd565b155b15612c83576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83861115612cbd576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85840393508415612d9a576040517fe49617e100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e49617e1908890612d1c908b90600401613663565b60206040518083038185885af1158015612d3a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612d5f91906143cd565b612d95576040517fccf3bb2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e67565b6040517fe60c350500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e60c3505908890612dee908b90600401613663565b60206040518083038185885af1158015612e0c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612e3191906143cd565b612e67576040517fbd8ba84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215612e7657612e7684612e82565b50939695505050505050565b8015612e9257612e923382613248565b50565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526022810183905260428101829052600090606201612739565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612f0e5750600090506003612fe6565b8460ff16601b14158015612f2657508460ff16601c14155b15612f375750600090506004612fe6565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612f8b573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612fdf57600060019250925050612fe6565b9150600090505b94509492505050565b6000816004811115613003576130036144a3565b0361300b5750565b600181600481111561301f5761301f6144a3565b0361308b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064015b60405180910390fd5b600281600481111561309f5761309f6144a3565b03613106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401613082565b600381600481111561311a5761311a6144a3565b036131a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401613082565b60048160048111156131bb576131bb6144a3565b03612e92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401613082565b804710156132b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401613082565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461330c576040519150601f19603f3d011682016040523d82523d6000602084013e613311565b606091505b5050905080610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401613082565b60008083601f8401126133b457600080fd5b50813567ffffffffffffffff8111156133cc57600080fd5b6020830191508360208260051b85010111156133e757600080fd5b9250929050565b6000806020838503121561340157600080fd5b823567ffffffffffffffff81111561341857600080fd5b613424858286016133a2565b90969095509350505050565b60005b8381101561344b578181015183820152602001613433565b50506000910152565b6000815180845261346c816020860160208601613430565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006134b16020830184613454565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114612e9257600080fd5b80356134e5816134b8565b919050565b6000602082840312156134fc57600080fd5b81356134b1816134b8565b6020808252825182820181905260009190848201906040850190845b8181101561353f57835183529284019291840191600101613523565b50909695505050505050565b60006060828403121561355d57600080fd5b50919050565b60006020828403121561357557600080fd5b5035919050565b6000610140825184526020830151602085015260408301516135aa604086018267ffffffffffffffff169052565b5060608301516135c6606086018267ffffffffffffffff169052565b5060808301516135e2608086018267ffffffffffffffff169052565b5060a083015160a085015260c083015161361460c086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e083015161363c60e086018273ffffffffffffffffffffffffffffffffffffffff169052565b50610100838101511515908501526101208084015181860183905261069783870182613454565b6020815260006134b1602083018461357c565b6000806040838503121561368957600080fd5b8235613694816134b8565b946020939093013593505050565b6000602082840312156136b457600080fd5b813567ffffffffffffffff8111156136cb57600080fd5b820160c081850312156134b157600080fd5b600060e0828403121561355d57600080fd5b60006020828403121561370157600080fd5b813567ffffffffffffffff81111561371857600080fd5b8201604081850312156134b157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126137bc57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126137fb57600080fd5b83018035915067ffffffffffffffff82111561381657600080fd5b6020019150600581901b36038213156133e757600080fd5b60405160c0810167ffffffffffffffff8111828210171561385157613851613759565b60405290565b6040516080810167ffffffffffffffff8111828210171561385157613851613759565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138c1576138c1613759565b604052919050565b600067ffffffffffffffff8211156138e3576138e3613759565b5060051b60200190565b8015158114612e9257600080fd5b80356134e5816138ed565b600067ffffffffffffffff82111561392057613920613759565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261395d57600080fd5b813561397061396b82613906565b61387a565b81815284602083860101111561398557600080fd5b816020850160208301376000918101602001919091529392505050565b600060c082840312156139b457600080fd5b6139bc61382e565b905081356139c9816134b8565b8152602082013567ffffffffffffffff80821682146139e757600080fd5b8160208401526139f9604085016138fb565b6040840152606084013560608401526080840135915080821115613a1c57600080fd5b50613a298482850161394c565b60808301525060a082013560a082015292915050565b6000613a4d61396b846138c9565b80848252602080830192508560051b850136811115613a6b57600080fd5b855b81811015613aa757803567ffffffffffffffff811115613a8d5760008081fd5b613a9936828a016139a2565b865250938201938201613a6d565b50919695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561053457610534613ab3565b600060408284031215613b0757600080fd5b6040516040810181811067ffffffffffffffff82111715613b2a57613b2a613759565b604052823581526020928301359281019290925250919050565b600060408284031215613b5657600080fd5b6134b18383613af5565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613b9557600080fd5b83018035915067ffffffffffffffff821115613bb057600080fd5b6020019150600681901b36038213156133e757600080fd5b60008451613bda818460208901613430565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551613c16816001850160208a01613430565b60019201918201528351613c31816002840160208801613430565b0160020195945050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818336030181126137bc57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613ca757600080fd5b83018035915067ffffffffffffffff821115613cc257600080fd5b60200191506060810236038213156133e757600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff418336030181126137bc57600080fd5b600061053436836139a2565b600060608284031215613d2b57600080fd5b6040516060810181811067ffffffffffffffff82111715613d4e57613d4e613759565b604052905080823560ff81168114613d6557600080fd5b8082525060208301356020820152604083013560408201525092915050565b600060608284031215613d9657600080fd5b6134b18383613d19565b600181811c90821680613db457607f821691505b60208210810361355d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060c08236031215613dff57600080fd5b613e07613857565b82358152602083013567ffffffffffffffff811115613e2557600080fd5b613e31368286016139a2565b602083015250613e443660408501613d19565b604082015260a0830135613e57816134b8565b606082015292915050565b600082601f830112613e7357600080fd5b81356020613e8361396b836138c9565b82815260609283028501820192828201919087851115613ea257600080fd5b8387015b85811015613ec557613eb88982613d19565b8452928401928101613ea6565b5090979650505050505050565b600060808236031215613ee457600080fd5b613eec613857565b8235815260208084013567ffffffffffffffff80821115613f0c57600080fd5b9085019036601f830112613f1f57600080fd5b8135613f2d61396b826138c9565b81815260069190911b83018401908481019036831115613f4c57600080fd5b938501935b82851015613f7557613f633686613af5565b82528582019150604085019450613f51565b80868801525050506040860135925080831115613f9157600080fd5b5050613f9f36828601613e62565b604083015250613e57606084016134da565b600060e08284031215613fc357600080fd5b613fcb613857565b82358152613fdc8460208501613af5565b6020820152613fee8460608501613d19565b604082015260c0830135614001816134b8565b60608201529392505050565b6000602080838503121561402057600080fd5b825167ffffffffffffffff8082111561403857600080fd5b908401906080828703121561404c57600080fd5b614054613857565b8251815283830151614065816134b8565b818501526040830151614077816138ed565b604082015260608301518281111561408e57600080fd5b80840193505086601f8401126140a357600080fd5b825191506140b361396b83613906565b82815287858486010111156140c757600080fd5b6140d683868301878701613430565b60608201529695505050505050565b601f82111561072057600081815260208120601f850160051c8101602086101561410c5750805b601f850160051c820191505b8181101561412b57828155600101614118565b505050505050565b815167ffffffffffffffff81111561414d5761414d613759565b6141618161415b8454613da0565b846140e5565b602080601f8311600181146141b4576000841561417e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561412b565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614201578886015182559484019460019091019084016141e2565b508582101561423d57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361427e5761427e613ab3565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826142c3576142c3614285565b500490565b6000826142d7576142d7614285565b500690565b8082018082111561053457610534613ab3565b89815260007fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808b60601b166020840152808a60601b166034840152507fffffffffffffffff000000000000000000000000000000000000000000000000808960c01b166048840152808860c01b1660508401525085151560f81b60588301528460598301528351614388816079850160208801613430565b80830190507fffffffff000000000000000000000000000000000000000000000000000000008460e01b166079820152607d81019150509a9950505050505050505050565b6000602082840312156143df57600080fd5b81516134b1816138ed565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b8381101561445f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa088870301855261444d86835161357c565b95509382019390820190600101614413565b50508584038187015286518085528782019482019350915060005b828110156144965784518452938101939281019260010161447a565b5091979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c6343000813000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "attest((bytes32,(address,uint64,bool,bytes32,bytes,uint256)))": { - "params": { - "request": "The arguments of the attestation request." - }, - "returns": { - "_0": "The UID of the new attestation." - } - }, - "attestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256),(uint8,bytes32,bytes32),address))": { - "params": { - "delegatedRequest": "The arguments of the delegated attestation request." - }, - "returns": { - "_0": "The UID of the new attestation." - } - }, - "constructor": { - "details": "Creates a new EAS instance." - }, - "getAttestTypeHash()": { - "returns": { - "_0": "The EIP712 attest function type hash." - } - }, - "getAttestation(bytes32)": { - "params": { - "uid": "The UID of the attestation to retrieve." - }, - "returns": { - "_0": "The attestation data members." - } - }, - "getName()": { - "returns": { - "_0": "The EIP712 name." - } - }, - "getNonce(address)": { - "params": { - "account": "The requested account." - }, - "returns": { - "_0": "The current nonce." - } - }, - "getRevokeOffchain(address,bytes32)": { - "params": { - "data": "The data to query." - }, - "returns": { - "_0": "The timestamp the data was timestamped with." - } - }, - "getRevokeTypeHash()": { - "returns": { - "_0": "hash_ The EIP712 revoke function type hash." - } - }, - "getSchemaRegistry()": { - "returns": { - "_0": "The address of the global schema registry." - } - }, - "getTimestamp(bytes32)": { - "params": { - "data": "The data to query." - }, - "returns": { - "_0": "The timestamp the data was timestamped with." - } - }, - "isAttestationValid(bytes32)": { - "params": { - "uid": "The UID of the attestation to retrieve." - }, - "returns": { - "_0": "Whether an attestation exists." - } - }, - "multiAttest((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[])[])": { - "params": { - "multiRequests": "The arguments of the multi attestation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization." - }, - "returns": { - "_0": "The UIDs of the new attestations." - } - }, - "multiAttestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[],(uint8,bytes32,bytes32)[],address)[])": { - "params": { - "multiDelegatedRequests": "The arguments of the delegated multi attestation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization." - }, - "returns": { - "_0": "The UIDs of the new attestations." - } - }, - "multiRevoke((bytes32,(bytes32,uint256)[])[])": { - "params": { - "multiRequests": "The arguments of the multi revocation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization." - } - }, - "multiRevokeByDelegation((bytes32,(bytes32,uint256)[],(uint8,bytes32,bytes32)[],address)[])": { - "params": { - "multiDelegatedRequests": "The arguments of the delegated multi revocation attestation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization." - } - }, - "multiRevokeOffchain(bytes32[])": { - "params": { - "data": "The data to timestamp." - }, - "returns": { - "_0": "The timestamp the data was revoked with." - } - }, - "multiTimestamp(bytes32[])": { - "params": { - "data": "The data to timestamp." - }, - "returns": { - "_0": "The timestamp the data was timestamped with." - } - }, - "revoke((bytes32,(bytes32,uint256)))": { - "params": { - "request": "The arguments of the revocation request." - } - }, - "revokeByDelegation((bytes32,(bytes32,uint256),(uint8,bytes32,bytes32),address))": { - "params": { - "delegatedRequest": "The arguments of the delegated revocation request." - } - }, - "revokeOffchain(bytes32)": { - "params": { - "data": "The data to timestamp." - }, - "returns": { - "_0": "The timestamp the data was revoked with." - } - }, - "timestamp(bytes32)": { - "params": { - "data": "The data to timestamp." - }, - "returns": { - "_0": "The timestamp the data was timestamped with." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "events": { - "Attested(address,address,bytes32,bytes32)": { - "details": "Emitted when an attestation has been made.", - "params": { - "attester": "The attesting account.", - "recipient": "The recipient of the attestation.", - "schema": "The UID of the schema.", - "uid": "The UID the revoked attestation." - } - }, - "Revoked(address,address,bytes32,bytes32)": { - "details": "Emitted when an attestation has been revoked.", - "params": { - "attester": "The attesting account.", - "recipient": "The recipient of the attestation.", - "schema": "The UID of the schema.", - "uid": "The UID the revoked attestation." - } - }, - "RevokedOffchain(address,bytes32,uint64)": { - "details": "Emitted when a data has been revoked.", - "params": { - "data": "The data.", - "revoker": "The address of the revoker.", - "timestamp": "The timestamp." - } - }, - "Timestamped(bytes32,uint64)": { - "details": "Emitted when a data has been timestamped.", - "params": { - "data": "The data.", - "timestamp": "The timestamp." - } - } - }, - "title": "EAS" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"AccessDenied\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"AlreadyRevoked\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"AlreadyRevokedOffchain\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"AlreadyTimestamped\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InsufficientValue\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidAttestation\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidAttestations\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidExpirationTime\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidLength\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidOffset\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidRegistry\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidRevocation\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidRevocations\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidSchema\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidSignature\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"InvalidVerifier\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"Irrevocable\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"NotFound\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"NotPayable\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"WrongSchema\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\",\"indexed\":false},{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Attested\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\",\"indexed\":false},{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Revoked\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\",\"indexed\":true}],\"type\":\"event\",\"name\":\"RevokedOffchain\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"uint64\",\"name\":\"timestamp\",\"type\":\"uint64\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Timestamped\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"struct AttestationRequest\",\"name\":\"request\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct AttestationRequestData\",\"name\":\"data\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"attest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[{\"internalType\":\"struct DelegatedAttestationRequest\",\"name\":\"delegatedRequest\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct AttestationRequestData\",\"name\":\"data\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]},{\"internalType\":\"struct EIP712Signature\",\"name\":\"signature\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}]},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"attestByDelegation\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"getAttestTypeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getAttestation\",\"outputs\":[{\"internalType\":\"struct Attestation\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"time\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"revocationTime\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}]}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getDomainSeparator\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getName\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getRevokeOffchain\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"getRevokeTypeHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"getSchemaRegistry\",\"outputs\":[{\"internalType\":\"contract ISchemaRegistry\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getTimestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"isAttestationValid\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"struct MultiAttestationRequest[]\",\"name\":\"multiRequests\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct AttestationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"multiAttest\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}]},{\"inputs\":[{\"internalType\":\"struct MultiDelegatedAttestationRequest[]\",\"name\":\"multiDelegatedRequests\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct AttestationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"expirationTime\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"refUID\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]},{\"internalType\":\"struct EIP712Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}]},{\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"multiAttestByDelegation\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}]},{\"inputs\":[{\"internalType\":\"struct MultiRevocationRequest[]\",\"name\":\"multiRequests\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct RevocationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"multiRevoke\"},{\"inputs\":[{\"internalType\":\"struct MultiDelegatedRevocationRequest[]\",\"name\":\"multiDelegatedRequests\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct RevocationRequestData[]\",\"name\":\"data\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]},{\"internalType\":\"struct EIP712Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\",\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}]},{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"multiRevokeByDelegation\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"data\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"multiRevokeOffchain\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"data\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"multiTimestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"struct RevocationRequest\",\"name\":\"request\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct RevocationRequestData\",\"name\":\"data\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"revoke\"},{\"inputs\":[{\"internalType\":\"struct DelegatedRevocationRequest\",\"name\":\"delegatedRequest\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"schema\",\"type\":\"bytes32\"},{\"internalType\":\"struct RevocationRequestData\",\"name\":\"data\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}]},{\"internalType\":\"struct EIP712Signature\",\"name\":\"signature\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}]},{\"internalType\":\"address\",\"name\":\"revoker\",\"type\":\"address\"}]}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"revokeByDelegation\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"revokeOffchain\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"data\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"timestamp\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"attest((bytes32,(address,uint64,bool,bytes32,bytes,uint256)))\":{\"params\":{\"request\":\"The arguments of the attestation request.\"},\"returns\":{\"_0\":\"The UID of the new attestation.\"}},\"attestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256),(uint8,bytes32,bytes32),address))\":{\"params\":{\"delegatedRequest\":\"The arguments of the delegated attestation request.\"},\"returns\":{\"_0\":\"The UID of the new attestation.\"}},\"constructor\":{\"details\":\"Creates a new EAS instance.\"},\"getAttestTypeHash()\":{\"returns\":{\"_0\":\"The EIP712 attest function type hash.\"}},\"getAttestation(bytes32)\":{\"params\":{\"uid\":\"The UID of the attestation to retrieve.\"},\"returns\":{\"_0\":\"The attestation data members.\"}},\"getName()\":{\"returns\":{\"_0\":\"The EIP712 name.\"}},\"getNonce(address)\":{\"params\":{\"account\":\"The requested account.\"},\"returns\":{\"_0\":\"The current nonce.\"}},\"getRevokeOffchain(address,bytes32)\":{\"params\":{\"data\":\"The data to query.\"},\"returns\":{\"_0\":\"The timestamp the data was timestamped with.\"}},\"getRevokeTypeHash()\":{\"returns\":{\"_0\":\"hash_ The EIP712 revoke function type hash.\"}},\"getSchemaRegistry()\":{\"returns\":{\"_0\":\"The address of the global schema registry.\"}},\"getTimestamp(bytes32)\":{\"params\":{\"data\":\"The data to query.\"},\"returns\":{\"_0\":\"The timestamp the data was timestamped with.\"}},\"isAttestationValid(bytes32)\":{\"params\":{\"uid\":\"The UID of the attestation to retrieve.\"},\"returns\":{\"_0\":\"Whether an attestation exists.\"}},\"multiAttest((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[])[])\":{\"params\":{\"multiRequests\":\"The arguments of the multi attestation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization.\"},\"returns\":{\"_0\":\"The UIDs of the new attestations.\"}},\"multiAttestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[],(uint8,bytes32,bytes32)[],address)[])\":{\"params\":{\"multiDelegatedRequests\":\"The arguments of the delegated multi attestation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization.\"},\"returns\":{\"_0\":\"The UIDs of the new attestations.\"}},\"multiRevoke((bytes32,(bytes32,uint256)[])[])\":{\"params\":{\"multiRequests\":\"The arguments of the multi revocation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization.\"}},\"multiRevokeByDelegation((bytes32,(bytes32,uint256)[],(uint8,bytes32,bytes32)[],address)[])\":{\"params\":{\"multiDelegatedRequests\":\"The arguments of the delegated multi revocation attestation requests. The requests should be grouped by distinct schema ids to benefit from the best batching optimization.\"}},\"multiRevokeOffchain(bytes32[])\":{\"params\":{\"data\":\"The data to timestamp.\"},\"returns\":{\"_0\":\"The timestamp the data was revoked with.\"}},\"multiTimestamp(bytes32[])\":{\"params\":{\"data\":\"The data to timestamp.\"},\"returns\":{\"_0\":\"The timestamp the data was timestamped with.\"}},\"revoke((bytes32,(bytes32,uint256)))\":{\"params\":{\"request\":\"The arguments of the revocation request.\"}},\"revokeByDelegation((bytes32,(bytes32,uint256),(uint8,bytes32,bytes32),address))\":{\"params\":{\"delegatedRequest\":\"The arguments of the delegated revocation request.\"}},\"revokeOffchain(bytes32)\":{\"params\":{\"data\":\"The data to timestamp.\"},\"returns\":{\"_0\":\"The timestamp the data was revoked with.\"}},\"timestamp(bytes32)\":{\"params\":{\"data\":\"The data to timestamp.\"},\"returns\":{\"_0\":\"The timestamp the data was timestamped with.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"attest((bytes32,(address,uint64,bool,bytes32,bytes,uint256)))\":{\"notice\":\"Attests to a specific schema. Example: attest({ schema: \\\"0facc36681cbe2456019c1b0d1e7bedd6d1d40f6f324bf3dd3a4cef2999200a0\\\", data: { recipient: \\\"0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf\\\", expirationTime: 0, revocable: true, refUID: \\\"0x0000000000000000000000000000000000000000000000000000000000000000\\\", data: \\\"0xF00D\\\", value: 0 } })\"},\"attestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256),(uint8,bytes32,bytes32),address))\":{\"notice\":\"Attests to a specific schema via the provided EIP712 signature. Example: attestByDelegation({ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: { recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', expirationTime: 1673891048, revocable: true, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x1234', value: 0 }, signature: { v: 28, r: '0x148c...b25b', s: '0x5a72...be22' }, attester: '0xc5E8740aD971409492b1A63Db8d83025e0Fc427e' })\"},\"getAttestTypeHash()\":{\"notice\":\"Returns the EIP712 type hash for the attest function.\"},\"getAttestation(bytes32)\":{\"notice\":\"Returns an existing attestation by UID.\"},\"getDomainSeparator()\":{\"notice\":\"Returns the domain separator used in the encoding of the signatures for attest, and revoke.\"},\"getName()\":{\"notice\":\"Returns the EIP712 name.\"},\"getNonce(address)\":{\"notice\":\"Returns the current nonce per-account.\"},\"getRevokeOffchain(address,bytes32)\":{\"notice\":\"Returns the timestamp that the specified data was timestamped with.\"},\"getRevokeTypeHash()\":{\"notice\":\"Returns the EIP712 type hash for the revoke function.\"},\"getSchemaRegistry()\":{\"notice\":\"Returns the address of the global schema registry.\"},\"getTimestamp(bytes32)\":{\"notice\":\"Returns the timestamp that the specified data was timestamped with.\"},\"isAttestationValid(bytes32)\":{\"notice\":\"Checks whether an attestation exists.\"},\"multiAttest((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[])[])\":{\"notice\":\"Attests to multiple schemas. Example: multiAttest([{ schema: '0x33e9094830a5cba5554d1954310e4fbed2ef5f859ec1404619adea4207f391fd', data: [{ recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf', expirationTime: 1673891048, revocable: true, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x1234', value: 1000 }, { recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', expirationTime: 0, revocable: false, refUID: '0x480df4a039efc31b11bfdf491b383ca138b6bde160988222a2a3509c02cee174', data: '0x00', value: 0 }], }, { schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425', data: [{ recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf', expirationTime: 0, revocable: true, refUID: '0x75bf2ed8dca25a8190c50c52db136664de25b2449535839008ccfdab469b214f', data: '0x12345678', value: 0 }, }])\"},\"multiAttestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[],(uint8,bytes32,bytes32)[],address)[])\":{\"notice\":\"Attests to multiple schemas using via provided EIP712 signatures. Example: multiAttestByDelegation([{ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: [{ recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', expirationTime: 1673891048, revocable: true, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x1234', value: 0 }, { recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf', expirationTime: 0, revocable: false, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x00', value: 0 }], signatures: [{ v: 28, r: '0x148c...b25b', s: '0x5a72...be22' }, { v: 28, r: '0x487s...67bb', s: '0x12ad...2366' }], attester: '0x1D86495b2A7B524D747d2839b3C645Bed32e8CF4' }])\"},\"multiRevoke((bytes32,(bytes32,uint256)[])[])\":{\"notice\":\"Revokes existing attestations to multiple schemas. Example: multiRevoke([{ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: [{ uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25', value: 1000 }, { uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade', value: 0 }], }, { schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425', data: [{ uid: '0x053d42abce1fd7c8fcddfae21845ad34dae287b2c326220b03ba241bc5a8f019', value: 0 }, }])\"},\"multiRevokeByDelegation((bytes32,(bytes32,uint256)[],(uint8,bytes32,bytes32)[],address)[])\":{\"notice\":\"Revokes existing attestations to multiple schemas via provided EIP712 signatures. Example: multiRevokeByDelegation([{ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: [{ uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25', value: 1000 }, { uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade', value: 0 }], signatures: [{ v: 28, r: '0x148c...b25b', s: '0x5a72...be22' }, { v: 28, r: '0x487s...67bb', s: '0x12ad...2366' }], revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992' }])\"},\"multiRevokeOffchain(bytes32[])\":{\"notice\":\"Revokes the specified multiple bytes32 data.\"},\"multiTimestamp(bytes32[])\":{\"notice\":\"Timestamps the specified multiple bytes32 data.\"},\"revoke((bytes32,(bytes32,uint256)))\":{\"notice\":\"Revokes an existing attestation to a specific schema. Example: revoke({ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: { uid: '0x101032e487642ee04ee17049f99a70590c735b8614079fc9275f9dd57c00966d', value: 0 } })\"},\"revokeByDelegation((bytes32,(bytes32,uint256),(uint8,bytes32,bytes32),address))\":{\"notice\":\"Revokes an existing attestation to a specific schema via the provided EIP712 signature. Example: revokeByDelegation({ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: { uid: '0xcbbc12102578c642a0f7b34fe7111e41afa25683b6cd7b5a14caf90fa14d24ba', value: 0 }, signature: { v: 27, r: '0xb593...7142', s: '0x0f5b...2cce' }, revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992' })\"},\"revokeOffchain(bytes32)\":{\"notice\":\"Revokes the specified bytes32 data.\"},\"timestamp(bytes32)\":{\"notice\":\"Timestamps the specified bytes32 data.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":@cwia/=node_modules/clones-with-immutable-args/src/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":clones-with-immutable-args/=node_modules/clones-with-immutable-args/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"contracts/EAS/EAS.sol\":\"EAS\"},\"libraries\":{}},\"sources\":{\"contracts/EAS/Common.sol\":{\"keccak256\":\"0x880e8262ee6682eeca6140e5a0b71f98e0c4024720c777da161e05a7715ed09a\",\"urls\":[\"bzz-raw://56ed7dc6b538070a66b851275a6a9721275da9e5e83631d94e93620cd679c3f6\",\"dweb:/ipfs/QmVjKgNr3jbnYerjDyFGLky8wXCUR8SuzxrsypBVVSW3tk\"],\"license\":\"MIT\"},\"contracts/EAS/EAS.sol\":{\"keccak256\":\"0x6b2cb86e523e76ab186c84ec7e9ee3451e993ddeea97c0c775d7e716b3379423\",\"urls\":[\"bzz-raw://3d05621ec6e9f83b4b6a77cf934d042d06bf6edb16e200245d9ac6620fabf7c0\",\"dweb:/ipfs/QmZWSECRBQMg4fduaYCrUhgmbmxK5cqaPSUAYHGWp4az5g\"],\"license\":\"MIT\"},\"contracts/EAS/IEAS.sol\":{\"keccak256\":\"0x8370442f2f2a19eef31653d46860ddcaa1c10bd5ec70113ce93fc43e672378c6\",\"urls\":[\"bzz-raw://37968de66d77a84bf03876d2ec6363f155dfccf87f00df9876d154ac8a6a87d6\",\"dweb:/ipfs/Qmb82nUieu66cfTLVdRcGwGGs2yYqmut4hDJ5vUVqtnXFe\"],\"license\":\"MIT\"},\"contracts/EAS/ISchemaRegistry.sol\":{\"keccak256\":\"0x4e988bea43a70e8ed156c7ee74dd3667872a68f65fa10dc4f07ddd4d89b929f1\",\"urls\":[\"bzz-raw://046977484b8089aad16f2064099b3f7604bcbddd61334e046838c3c448b5ebb5\",\"dweb:/ipfs/QmXdorYunKEbiosCGL4teYCd1W2njCqujvMWQjYonAxU6w\"],\"license\":\"MIT\"},\"contracts/EAS/eip712/EIP712Verifier.sol\":{\"keccak256\":\"0x048e65ebd0d8a0e3195affa57e7f7b904b3195fe28b160169244fc89c0eb55f2\",\"urls\":[\"bzz-raw://7c8760a59d43cf81c43f2945283f0f0e5f6f205136064d4e48ee2abe67fe687b\",\"dweb:/ipfs/QmaGXYY8g17CTMYyVCZK42P8MM3ntcQye1KK1ytc6sbbVb\"],\"license\":\"MIT\"},\"contracts/EAS/resolver/ISchemaResolver.sol\":{\"keccak256\":\"0xe537341e3d8d9c8e0eada21b4278beef510781fb1745892312c286a3c8287c2d\",\"urls\":[\"bzz-raw://5ab80b1fd7b6ad0ca94ff14358c5ba942614e25632d8a07c8e364d3f45c08453\",\"dweb:/ipfs/QmY6WToUtVo1HpDq7z7Tb17othZnJwpz4m26GuzKAsGTeM\"],\"license\":\"MIT\"},\"contracts/libraries/Predeploys.sol\":{\"keccak256\":\"0xe46f53d83bbc978cebc11cb702e6b9f046cfbafdcbb79bba2837edf28515cbe4\",\"urls\":[\"bzz-raw://c80c47543cad25cc10ddd7ec2a2399ef1dac50bd5c90d8042211ded0692416a8\",\"dweb:/ipfs/QmeKCGE85eJpJzEXSLmQmhWT9aniSqvwNc8XDcSVedh9F8\"],\"license\":\"MIT\"},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0xc455c84bb1f17e994dea0451fd363f81f83965bfa86e81ac6c8b3a327b9a0ff0\",\"urls\":[\"bzz-raw://fab499f3c0d7df8eb763b50621848d5d2147fb9c42a8eb9b65a11093090bb482\",\"dweb:/ipfs/QmUKsG4ztwtUZFjuRYAxgUFTgH5YxWSGF1BFFaB7vdM2K3\"],\"license\":\"MIT\"},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"],\"license\":\"MIT\"},\"node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"keccak256\":\"0xdb7f5c28fc61cda0bd8ab60ce288e206b791643bcd3ba464a70cbec18895a2f5\",\"urls\":[\"bzz-raw://bf52bdf22a33263f5ca6227a35faeac3b81e7d2c692fbcc6a079d488710c5900\",\"dweb:/ipfs/QmcmsjkP4yq3UhiJbvyzwufaY2EKh1zhHaRK8ATag2cpD2\"],\"license\":\"MIT\"},\"node_modules/@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol\":{\"keccak256\":\"0x6688fad58b9ec0286d40fa957152e575d5d8bd4c3aa80985efdb11b44f776ae7\",\"urls\":[\"bzz-raw://8bc00ab7f133cdaafd212a5cc6a16c8d37319721105d130c8e5af0c4e8f170ba\",\"dweb:/ipfs/QmVmf6LVMfFiEkvKYLzSv3bGHzymEW93AcUuFrNUdY3NtT\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 1, - "receipt": { - "transactionHash": "0xb17f2eb6e221002683f7427bd2481ce78b0f82094c4eeb0e701442cba4904db5", - "transactionIndex": "0x2", - "blockHash": "0xfcbb8967e5e2d9c6547cd7ae13b0f7973cc2bbd01fbf506e64ef0959ae345f19", - "blockNumber": "0x6645706", - "from": "0x9bbFB9919062C29a5eE15aCD93c9D7c3b14d31aa", - "to": null, - "cumulativeGasUsed": "0x3bf2b8", - "gasUsed": "0x3aa40b", - "contractAddress": "0x4E0275Ea5a89e7a3c1B58411379D1a0eDdc5b088", - "logs": [], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "type": "0x2", - "effectiveGasPrice": "0xb2d05e44" - }, - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 27260, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "_nonces", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 27266, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)49_storage" - }, - { - "astId": 24954, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "_db", - "offset": 0, - "slot": "50", - "type": "t_mapping(t_bytes32,t_struct(Attestation)24729_storage)" - }, - { - "astId": 24958, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "_timestamps", - "offset": 0, - "slot": "51", - "type": "t_mapping(t_bytes32,t_uint64)" - }, - { - "astId": 24964, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "_revocationsOffchain", - "offset": 0, - "slot": "52", - "type": "t_mapping(t_address,t_mapping(t_bytes32,t_uint64))" - }, - { - "astId": 24970, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "__gap", - "offset": 0, - "slot": "53", - "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", - "base": "t_uint256" - }, - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_bytes_storage": { - "encoding": "bytes", - "label": "bytes", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_bytes32,t_uint64))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(bytes32 => uint64))", - "numberOfBytes": "32", - "value": "t_mapping(t_bytes32,t_uint64)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_mapping(t_bytes32,t_struct(Attestation)24729_storage)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => struct Attestation)", - "numberOfBytes": "32", - "value": "t_struct(Attestation)24729_storage" - }, - "t_mapping(t_bytes32,t_uint64)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => uint64)", - "numberOfBytes": "32", - "value": "t_uint64" - }, - "t_struct(Attestation)24729_storage": { - "encoding": "inplace", - "label": "struct Attestation", - "numberOfBytes": "224", - "members": [ - { - "astId": 24710, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "uid", - "offset": 0, - "slot": "0", - "type": "t_bytes32" - }, - { - "astId": 24712, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "schema", - "offset": 0, - "slot": "1", - "type": "t_bytes32" - }, - { - "astId": 24714, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "time", - "offset": 0, - "slot": "2", - "type": "t_uint64" - }, - { - "astId": 24716, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "expirationTime", - "offset": 8, - "slot": "2", - "type": "t_uint64" - }, - { - "astId": 24718, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "revocationTime", - "offset": 16, - "slot": "2", - "type": "t_uint64" - }, - { - "astId": 24720, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "refUID", - "offset": 0, - "slot": "3", - "type": "t_bytes32" - }, - { - "astId": 24722, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "recipient", - "offset": 0, - "slot": "4", - "type": "t_address" - }, - { - "astId": 24724, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "attester", - "offset": 0, - "slot": "5", - "type": "t_address" - }, - { - "astId": 24726, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "revocable", - "offset": 20, - "slot": "5", - "type": "t_bool" - }, - { - "astId": 24728, - "contract": "contracts/EAS/EAS.sol:EAS", - "label": "data", - "offset": 0, - "slot": "6", - "type": "t_bytes_storage" - } - ] - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint64": { - "encoding": "inplace", - "label": "uint64", - "numberOfBytes": "8" - } - } - }, - "transactionHash": "0xb17f2eb6e221002683f7427bd2481ce78b0f82094c4eeb0e701442cba4904db5", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "attest((bytes32,(address,uint64,bool,bytes32,bytes,uint256)))": { - "notice": "Attests to a specific schema. Example: attest({ schema: \"0facc36681cbe2456019c1b0d1e7bedd6d1d40f6f324bf3dd3a4cef2999200a0\", data: { recipient: \"0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf\", expirationTime: 0, revocable: true, refUID: \"0x0000000000000000000000000000000000000000000000000000000000000000\", data: \"0xF00D\", value: 0 } })" - }, - "attestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256),(uint8,bytes32,bytes32),address))": { - "notice": "Attests to a specific schema via the provided EIP712 signature. Example: attestByDelegation({ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: { recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', expirationTime: 1673891048, revocable: true, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x1234', value: 0 }, signature: { v: 28, r: '0x148c...b25b', s: '0x5a72...be22' }, attester: '0xc5E8740aD971409492b1A63Db8d83025e0Fc427e' })" - }, - "getAttestTypeHash()": { - "notice": "Returns the EIP712 type hash for the attest function." - }, - "getAttestation(bytes32)": { - "notice": "Returns an existing attestation by UID." - }, - "getDomainSeparator()": { - "notice": "Returns the domain separator used in the encoding of the signatures for attest, and revoke." - }, - "getName()": { - "notice": "Returns the EIP712 name." - }, - "getNonce(address)": { - "notice": "Returns the current nonce per-account." - }, - "getRevokeOffchain(address,bytes32)": { - "notice": "Returns the timestamp that the specified data was timestamped with." - }, - "getRevokeTypeHash()": { - "notice": "Returns the EIP712 type hash for the revoke function." - }, - "getSchemaRegistry()": { - "notice": "Returns the address of the global schema registry." - }, - "getTimestamp(bytes32)": { - "notice": "Returns the timestamp that the specified data was timestamped with." - }, - "isAttestationValid(bytes32)": { - "notice": "Checks whether an attestation exists." - }, - "multiAttest((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[])[])": { - "notice": "Attests to multiple schemas. Example: multiAttest([{ schema: '0x33e9094830a5cba5554d1954310e4fbed2ef5f859ec1404619adea4207f391fd', data: [{ recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf', expirationTime: 1673891048, revocable: true, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x1234', value: 1000 }, { recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', expirationTime: 0, revocable: false, refUID: '0x480df4a039efc31b11bfdf491b383ca138b6bde160988222a2a3509c02cee174', data: '0x00', value: 0 }], }, { schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425', data: [{ recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf', expirationTime: 0, revocable: true, refUID: '0x75bf2ed8dca25a8190c50c52db136664de25b2449535839008ccfdab469b214f', data: '0x12345678', value: 0 }, }])" - }, - "multiAttestByDelegation((bytes32,(address,uint64,bool,bytes32,bytes,uint256)[],(uint8,bytes32,bytes32)[],address)[])": { - "notice": "Attests to multiple schemas using via provided EIP712 signatures. Example: multiAttestByDelegation([{ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: [{ recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', expirationTime: 1673891048, revocable: true, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x1234', value: 0 }, { recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf', expirationTime: 0, revocable: false, refUID: '0x0000000000000000000000000000000000000000000000000000000000000000', data: '0x00', value: 0 }], signatures: [{ v: 28, r: '0x148c...b25b', s: '0x5a72...be22' }, { v: 28, r: '0x487s...67bb', s: '0x12ad...2366' }], attester: '0x1D86495b2A7B524D747d2839b3C645Bed32e8CF4' }])" - }, - "multiRevoke((bytes32,(bytes32,uint256)[])[])": { - "notice": "Revokes existing attestations to multiple schemas. Example: multiRevoke([{ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: [{ uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25', value: 1000 }, { uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade', value: 0 }], }, { schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425', data: [{ uid: '0x053d42abce1fd7c8fcddfae21845ad34dae287b2c326220b03ba241bc5a8f019', value: 0 }, }])" - }, - "multiRevokeByDelegation((bytes32,(bytes32,uint256)[],(uint8,bytes32,bytes32)[],address)[])": { - "notice": "Revokes existing attestations to multiple schemas via provided EIP712 signatures. Example: multiRevokeByDelegation([{ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: [{ uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25', value: 1000 }, { uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade', value: 0 }], signatures: [{ v: 28, r: '0x148c...b25b', s: '0x5a72...be22' }, { v: 28, r: '0x487s...67bb', s: '0x12ad...2366' }], revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992' }])" - }, - "multiRevokeOffchain(bytes32[])": { - "notice": "Revokes the specified multiple bytes32 data." - }, - "multiTimestamp(bytes32[])": { - "notice": "Timestamps the specified multiple bytes32 data." - }, - "revoke((bytes32,(bytes32,uint256)))": { - "notice": "Revokes an existing attestation to a specific schema. Example: revoke({ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: { uid: '0x101032e487642ee04ee17049f99a70590c735b8614079fc9275f9dd57c00966d', value: 0 } })" - }, - "revokeByDelegation((bytes32,(bytes32,uint256),(uint8,bytes32,bytes32),address))": { - "notice": "Revokes an existing attestation to a specific schema via the provided EIP712 signature. Example: revokeByDelegation({ schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc', data: { uid: '0xcbbc12102578c642a0f7b34fe7111e41afa25683b6cd7b5a14caf90fa14d24ba', value: 0 }, signature: { v: 27, r: '0xb593...7142', s: '0x0f5b...2cce' }, revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992' })" - }, - "revokeOffchain(bytes32)": { - "notice": "Revokes the specified bytes32 data." - }, - "timestamp(bytes32)": { - "notice": "Timestamps the specified bytes32 data." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "The Ethereum Attestation Service protocol." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-mainnet/L2ERC721Bridge.json b/packages/contracts-bedrock/deployments/optimism-mainnet/L2ERC721Bridge.json deleted file mode 100644 index fe0939d45919..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/L2ERC721Bridge.json +++ /dev/null @@ -1,386 +0,0 @@ -{ - "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-bedrock/deployments/optimism-mainnet/MintManager.json b/packages/contracts-bedrock/deployments/optimism-mainnet/MintManager.json deleted file mode 100644 index f71c767af618..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/MintManager.json +++ /dev/null @@ -1,316 +0,0 @@ -{ - "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-bedrock/deployments/optimism-mainnet/OptimismMintableERC721Factory.json b/packages/contracts-bedrock/deployments/optimism-mainnet/OptimismMintableERC721Factory.json deleted file mode 100644 index 0052dac91020..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/OptimismMintableERC721Factory.json +++ /dev/null @@ -1,250 +0,0 @@ -{ - "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-bedrock/deployments/optimism-mainnet/OptimismMintableERC721FactoryProxy.json b/packages/contracts-bedrock/deployments/optimism-mainnet/OptimismMintableERC721FactoryProxy.json deleted file mode 100644 index 4c0e4160aa01..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/OptimismMintableERC721FactoryProxy.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "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-bedrock/deployments/optimism-mainnet/Optimist.json b/packages/contracts-bedrock/deployments/optimism-mainnet/Optimist.json deleted file mode 100644 index abc6e6a12a1a..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/Optimist.json +++ /dev/null @@ -1,883 +0,0 @@ -{ - "address": "0x7c3B29661317a18Ea2bFfc8b5081dBFf60404E52", - "abi": [ - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - }, - { - "internalType": "address", - "name": "_baseURIAttestor", - "type": "address" - }, - { - "internalType": "contract AttestationStation", - "name": "_attestationStation", - "type": "address" - }, - { - "internalType": "contract OptimistAllowlist", - "name": "_optimistAllowlist", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "approved", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "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": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [], - "name": "ATTESTATION_STATION", - "outputs": [ - { - "internalType": "contract AttestationStation", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "BASE_URI_ATTESTATION_KEY", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "BASE_URI_ATTESTOR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMIST_ALLOWLIST", - "outputs": [ - { - "internalType": "contract OptimistAllowlist", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "baseURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "name": "isOnAllowList", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "name": "tokenIdOfAddress", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x3dc847b45e050bf6f3732330d8ac94bf736a1a6fd8a143b6c0dbe0e850009dbb", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "2242451", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000080000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x5c2528f97cb45423c2ae91620b75cdf554e3c866e8616bd2b8b47fabbe2b99d3", - "transactionHash": "0x3dc847b45e050bf6f3732330d8ac94bf736a1a6fd8a143b6c0dbe0e850009dbb", - "logs": [ - { - "transactionIndex": 0, - "blockNumber": 87032414, - "transactionHash": "0x3dc847b45e050bf6f3732330d8ac94bf736a1a6fd8a143b6c0dbe0e850009dbb", - "address": "0x7c3B29661317a18Ea2bFfc8b5081dBFf60404E52", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 0, - "blockHash": "0x5c2528f97cb45423c2ae91620b75cdf554e3c866e8616bd2b8b47fabbe2b99d3" - } - ], - "blockNumber": 87032414, - "cumulativeGasUsed": "2242451", - "status": 1, - "byzantium": true - }, - "args": [ - "Optimist", - "OPTIMIST", - "0x60c5C9c98bcBd0b0F2fD89B24c16e533BaA8CdA3", - "0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77", - "0x482b1945D58f2E9Db0CEbe13c7fcFc6876b41180" - ], - "numDeployments": 1, - "solcInputHash": "d7155764d4bdb814f10e1bb45296292b", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_baseURIAttestor\",\"type\":\"address\"},{\"internalType\":\"contract AttestationStation\",\"name\":\"_attestationStation\",\"type\":\"address\"},{\"internalType\":\"contract OptimistAllowlist\",\"name\":\"_optimistAllowlist\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"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\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ATTESTATION_STATION\",\"outputs\":[{\"internalType\":\"contract AttestationStation\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"BASE_URI_ATTESTATION_KEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"BASE_URI_ATTESTOR\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OPTIMIST_ALLOWLIST\",\"outputs\":[{\"internalType\":\"contract OptimistAllowlist\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"isOnAllowList\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"tokenIdOfAddress\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Optimism CollectiveGitcoin\",\"kind\":\"dev\",\"methods\":{\"balanceOf(address)\":{\"details\":\"See {IERC721-balanceOf}.\"},\"baseURI()\":{\"returns\":{\"_0\":\"BaseURI for all tokens.\"}},\"burn(uint256)\":{\"details\":\"Burns `tokenId`. See {ERC721-_burn}. Requirements: - The caller must own `tokenId` or be an approved operator.\"},\"constructor\":{\"custom:semver\":\"2.0.0\",\"params\":{\"_attestationStation\":\"Address of the AttestationStation contract.\",\"_baseURIAttestor\":\"Address of the baseURI attestor.\",\"_name\":\"Token name.\",\"_optimistAllowlist\":\"Address of the OptimistAllowlist contract\",\"_symbol\":\"Token symbol.\"}},\"getApproved(uint256)\":{\"details\":\"See {IERC721-getApproved}.\"},\"initialize(string,string)\":{\"params\":{\"_name\":\"Token name.\",\"_symbol\":\"Token symbol.\"}},\"isApprovedForAll(address,address)\":{\"details\":\"See {IERC721-isApprovedForAll}.\"},\"isOnAllowList(address)\":{\"returns\":{\"_0\":\"Whether or not the address is allowed to mint yet.\"}},\"mint(address)\":{\"params\":{\"_recipient\":\"Address of the token recipient.\"}},\"name()\":{\"details\":\"See {IERC721Metadata-name}.\"},\"ownerOf(uint256)\":{\"details\":\"See {IERC721-ownerOf}.\"},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"See {IERC721-safeTransferFrom}.\"},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"See {IERC721-safeTransferFrom}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"symbol()\":{\"details\":\"See {IERC721Metadata-symbol}.\"},\"tokenIdOfAddress(address)\":{\"returns\":{\"_0\":\"Token ID for the token owned by the given address.\"}},\"tokenURI(uint256)\":{\"params\":{\"_tokenId\":\"Token ID to query.\"},\"returns\":{\"_0\":\"Token URI for the given token by ID.\"}},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC721-transferFrom}.\"},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"Optimist\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"ATTESTATION_STATION()\":{\"notice\":\"Address of the AttestationStation contract.\"},\"BASE_URI_ATTESTATION_KEY()\":{\"notice\":\"Attestation key used by the attestor to attest the baseURI.\"},\"BASE_URI_ATTESTOR()\":{\"notice\":\"Attestor who attests to baseURI.\"},\"OPTIMIST_ALLOWLIST()\":{\"notice\":\"Address of the OptimistAllowlist contract.\"},\"approve(address,uint256)\":{\"notice\":\"Disabled for the Optimist NFT (Soul Bound Token).\"},\"baseURI()\":{\"notice\":\"Returns the baseURI for all tokens.\"},\"initialize(string,string)\":{\"notice\":\"Initializes the Optimist contract.\"},\"isOnAllowList(address)\":{\"notice\":\"Checks OptimistAllowlist to determine whether a given address is allowed to mint the Optimist NFT. Since the Optimist NFT will also be used as part of the Citizens House, mints are currently restricted. Eventually anyone will be able to mint.\"},\"mint(address)\":{\"notice\":\"Allows an address to mint an Optimist NFT. Token ID is the uint256 representation of the recipient's address. Recipients must be permitted to mint, eventually anyone will be able to mint. One token per address.\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"Disabled for the Optimist NFT (Soul Bound Token).\"},\"tokenIdOfAddress(address)\":{\"notice\":\"Returns the token ID for the token owned by a given address. This is the uint256 representation of the given address.\"},\"tokenURI(uint256)\":{\"notice\":\"Returns the token URI for a given token by ID\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"A Soul Bound Token for real humans only(tm).\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/op-nft/Optimist.sol\":\"Optimist\"},\"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.0;\\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 uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\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\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"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/token/ERC721/ERC721Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC721Upgradeable.sol\\\";\\nimport \\\"./IERC721ReceiverUpgradeable.sol\\\";\\nimport \\\"./extensions/IERC721MetadataUpgradeable.sol\\\";\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\nimport \\\"../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../../utils/StringsUpgradeable.sol\\\";\\nimport \\\"../../utils/introspection/ERC165Upgradeable.sol\\\";\\nimport \\\"../../proxy/utils/Initializable.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 ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable {\\n using AddressUpgradeable for address;\\n using StringsUpgradeable 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 function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing {\\n __ERC721_init_unchained(name_, symbol_);\\n }\\n\\n function __ERC721_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {\\n return\\n interfaceId == type(IERC721Upgradeable).interfaceId ||\\n interfaceId == type(IERC721MetadataUpgradeable).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: address zero is not a valid owner\\\");\\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: invalid token ID\\\");\\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 _requireMinted(tokenId);\\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 = ERC721Upgradeable.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 token 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 _requireMinted(tokenId);\\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: caller is not token 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: caller is not token 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 address owner = ERC721Upgradeable.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 = ERC721Upgradeable.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(ERC721Upgradeable.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 an {Approval} event.\\n */\\n function _approve(address to, uint256 tokenId) internal virtual {\\n _tokenApprovals[tokenId] = to;\\n emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits an {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 Reverts if the `tokenId` has not been minted yet.\\n */\\n function _requireMinted(uint256 tokenId) internal view virtual {\\n require(_exists(tokenId), \\\"ERC721: invalid token ID\\\");\\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 IERC721ReceiverUpgradeable(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\\n return retval == IERC721ReceiverUpgradeable.onERC721Received.selector;\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert(\\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n } else {\\n /// @solidity memory-safe-assembly\\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 /**\\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[44] private __gap;\\n}\\n\",\"keccak256\":\"0x5331c8909221d9f9f3851cfadd5959d0873413a2c27e30e0f2fa234158c1c6cf\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.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 IERC721ReceiverUpgradeable {\\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\":\"0xbb2ed8106d94aeae6858e2551a1e7174df73994b77b13ebd120ccaaef80155f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165Upgradeable.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721Upgradeable is IERC165Upgradeable {\\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 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\":\"0x016298e66a5810253c6c905e61966bb31c8775c3f3517bf946ff56ee31d6c005\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/extensions/ERC721Burnable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC721Upgradeable.sol\\\";\\nimport \\\"../../../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../../../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @title ERC721 Burnable Token\\n * @dev ERC721 Token that can be burned (destroyed).\\n */\\nabstract contract ERC721BurnableUpgradeable is Initializable, ContextUpgradeable, ERC721Upgradeable {\\n function __ERC721Burnable_init() internal onlyInitializing {\\n }\\n\\n function __ERC721Burnable_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev Burns `tokenId`. See {ERC721-_burn}.\\n *\\n * Requirements:\\n *\\n * - The caller must own `tokenId` or be an approved operator.\\n */\\n function burn(uint256 tokenId) public virtual {\\n //solhint-disable-next-line max-line-length\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner nor approved\\\");\\n _burn(tokenId);\\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\":\"0xa7dbff7171ac06a023a5ca52c2138ac711037b2146b9197a52e5de4f9183e04d\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.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 \\\"../IERC721Upgradeable.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 IERC721MetadataUpgradeable is IERC721Upgradeable {\\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\":\"0x95a471796eb5f030fdc438660bebec121ad5d063763e64d92376ffb4b5ce8b70\",\"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-upgradeable/utils/StringsUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary StringsUpgradeable {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\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 /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xea5339a7fff0ed42b45be56a88efdd0b2ddde9fa480dc99fef9a6a4c5b776863\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165Upgradeable.sol\\\";\\nimport \\\"../../proxy/utils/Initializable.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 ERC165Upgradeable is Initializable, IERC165Upgradeable {\\n function __ERC165_init() internal onlyInitializing {\\n }\\n\\n function __ERC165_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165Upgradeable).interfaceId;\\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\":\"0x9a3b990bd56d139df3e454a9edf1c64668530b5a77fc32eb063bc206f958274a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.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 IERC165Upgradeable {\\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\":\"0xc6cef87559d0aeffdf0a99803de655938a7779ec0a3cd5d4383483ad85565a09\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\\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 /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/universal/op-nft/AttestationStation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title AttestationStation\\n * @author Optimism Collective\\n * @author Gitcoin\\n * @notice Where attestations live.\\n */\\ncontract AttestationStation is Semver {\\n /**\\n * @notice Struct representing data that is being attested.\\n *\\n * @custom:field about Address for which the attestation is about.\\n * @custom:field key A bytes32 key for the attestation.\\n * @custom:field val The attestation as arbitrary bytes.\\n */\\n struct AttestationData {\\n address about;\\n bytes32 key;\\n bytes val;\\n }\\n\\n /**\\n * @notice Maps addresses to attestations. Creator => About => Key => Value.\\n */\\n mapping(address => mapping(address => mapping(bytes32 => bytes))) public attestations;\\n\\n /**\\n * @notice Emitted when Attestation is created.\\n *\\n * @param creator Address that made the attestation.\\n * @param about Address attestation is about.\\n * @param key Key of the attestation.\\n * @param val Value of the attestation.\\n */\\n event AttestationCreated(\\n address indexed creator,\\n address indexed about,\\n bytes32 indexed key,\\n bytes val\\n );\\n\\n /**\\n * @custom:semver 1.1.0\\n */\\n constructor() Semver(1, 1, 0) {}\\n\\n /**\\n * @notice Allows anyone to create an attestation.\\n *\\n * @param _about Address that the attestation is about.\\n * @param _key A key used to namespace the attestation.\\n * @param _val An arbitrary value stored as part of the attestation.\\n */\\n function attest(\\n address _about,\\n bytes32 _key,\\n bytes memory _val\\n ) public {\\n attestations[msg.sender][_about][_key] = _val;\\n\\n emit AttestationCreated(msg.sender, _about, _key, _val);\\n }\\n\\n /**\\n * @notice Allows anyone to create attestations.\\n *\\n * @param _attestations An array of AttestationData structs.\\n */\\n function attest(AttestationData[] calldata _attestations) external {\\n uint256 length = _attestations.length;\\n for (uint256 i = 0; i < length; ) {\\n AttestationData memory attestation = _attestations[i];\\n\\n attest(attestation.about, attestation.key, attestation.val);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x421923e04df145353db12cd0352ccf516d9c29ab64b138733b4f7a6a450ce2be\",\"license\":\"MIT\"},\"contracts/universal/op-nft/Optimist.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\nimport {\\n ERC721BurnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol\\\";\\nimport { AttestationStation } from \\\"./AttestationStation.sol\\\";\\nimport { OptimistAllowlist } from \\\"./OptimistAllowlist.sol\\\";\\nimport { Strings } from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\n\\n/**\\n * @author Optimism Collective\\n * @author Gitcoin\\n * @title Optimist\\n * @notice A Soul Bound Token for real humans only(tm).\\n */\\ncontract Optimist is ERC721BurnableUpgradeable, Semver {\\n /**\\n * @notice Attestation key used by the attestor to attest the baseURI.\\n */\\n bytes32 public constant BASE_URI_ATTESTATION_KEY = bytes32(\\\"optimist.base-uri\\\");\\n\\n /**\\n * @notice Attestor who attests to baseURI.\\n */\\n address public immutable BASE_URI_ATTESTOR;\\n\\n /**\\n * @notice Address of the AttestationStation contract.\\n */\\n AttestationStation public immutable ATTESTATION_STATION;\\n\\n /**\\n * @notice Address of the OptimistAllowlist contract.\\n */\\n OptimistAllowlist public immutable OPTIMIST_ALLOWLIST;\\n\\n /**\\n * @custom:semver 2.0.0\\n * @param _name Token name.\\n * @param _symbol Token symbol.\\n * @param _baseURIAttestor Address of the baseURI attestor.\\n * @param _attestationStation Address of the AttestationStation contract.\\n * @param _optimistAllowlist Address of the OptimistAllowlist contract\\n */\\n constructor(\\n string memory _name,\\n string memory _symbol,\\n address _baseURIAttestor,\\n AttestationStation _attestationStation,\\n OptimistAllowlist _optimistAllowlist\\n ) Semver(2, 0, 0) {\\n BASE_URI_ATTESTOR = _baseURIAttestor;\\n ATTESTATION_STATION = _attestationStation;\\n OPTIMIST_ALLOWLIST = _optimistAllowlist;\\n initialize(_name, _symbol);\\n }\\n\\n /**\\n * @notice Initializes the Optimist contract.\\n *\\n * @param _name Token name.\\n * @param _symbol Token symbol.\\n */\\n function initialize(string memory _name, string memory _symbol) public initializer {\\n __ERC721_init(_name, _symbol);\\n __ERC721Burnable_init();\\n }\\n\\n /**\\n * @notice Allows an address to mint an Optimist NFT. Token ID is the uint256 representation\\n * of the recipient's address. Recipients must be permitted to mint, eventually anyone\\n * will be able to mint. One token per address.\\n *\\n * @param _recipient Address of the token recipient.\\n */\\n function mint(address _recipient) public {\\n require(isOnAllowList(_recipient), \\\"Optimist: address is not on allowList\\\");\\n _safeMint(_recipient, tokenIdOfAddress(_recipient));\\n }\\n\\n /**\\n * @notice Returns the baseURI for all tokens.\\n *\\n * @return BaseURI for all tokens.\\n */\\n function baseURI() public view returns (string memory) {\\n return\\n string(\\n abi.encodePacked(\\n ATTESTATION_STATION.attestations(\\n BASE_URI_ATTESTOR,\\n address(this),\\n bytes32(\\\"optimist.base-uri\\\")\\n )\\n )\\n );\\n }\\n\\n /**\\n * @notice Returns the token URI for a given token by ID\\n *\\n * @param _tokenId Token ID to query.\\n\\n * @return Token URI for the given token by ID.\\n */\\n function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) {\\n return\\n string(\\n abi.encodePacked(\\n baseURI(),\\n \\\"/\\\",\\n // Properly format the token ID as a 20 byte hex string (address).\\n Strings.toHexString(_tokenId, 20),\\n \\\".json\\\"\\n )\\n );\\n }\\n\\n /**\\n * @notice Checks OptimistAllowlist to determine whether a given address is allowed to mint\\n * the Optimist NFT. Since the Optimist NFT will also be used as part of the\\n * Citizens House, mints are currently restricted. Eventually anyone will be able\\n * to mint.\\n *\\n * @return Whether or not the address is allowed to mint yet.\\n */\\n function isOnAllowList(address _recipient) public view returns (bool) {\\n return OPTIMIST_ALLOWLIST.isAllowedToMint(_recipient);\\n }\\n\\n /**\\n * @notice Returns the token ID for the token owned by a given address. This is the uint256\\n * representation of the given address.\\n *\\n * @return Token ID for the token owned by the given address.\\n */\\n function tokenIdOfAddress(address _owner) public pure returns (uint256) {\\n return uint256(uint160(_owner));\\n }\\n\\n /**\\n * @notice Disabled for the Optimist NFT (Soul Bound Token).\\n */\\n function approve(address, uint256) public pure override {\\n revert(\\\"Optimist: soul bound token\\\");\\n }\\n\\n /**\\n * @notice Disabled for the Optimist NFT (Soul Bound Token).\\n */\\n function setApprovalForAll(address, bool) public virtual override {\\n revert(\\\"Optimist: soul bound token\\\");\\n }\\n\\n /**\\n * @notice Prevents transfers of the Optimist NFT (Soul Bound Token).\\n *\\n * @param _from Address of the token sender.\\n * @param _to Address of the token recipient.\\n */\\n function _beforeTokenTransfer(\\n address _from,\\n address _to,\\n uint256\\n ) internal virtual override {\\n require(_from == address(0) || _to == address(0), \\\"Optimist: soul bound token\\\");\\n }\\n}\\n\",\"keccak256\":\"0xf9c7973102666d1dc1b8a1918d6df82fa8fb470e1774aea840b300afb9699cac\",\"license\":\"MIT\"},\"contracts/universal/op-nft/OptimistAllowlist.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\nimport { AttestationStation } from \\\"./AttestationStation.sol\\\";\\nimport { OptimistConstants } from \\\"./libraries/OptimistConstants.sol\\\";\\n\\n/**\\n * @title OptimistAllowlist\\n * @notice Source of truth for whether an address is able to mint an Optimist NFT.\\n isAllowedToMint function checks various signals to return boolean value for whether an\\n address is eligible or not.\\n */\\ncontract OptimistAllowlist is Semver {\\n /**\\n * @notice Attestation key used by the AllowlistAttestor to manually add addresses to the\\n * allowlist.\\n */\\n bytes32 public constant OPTIMIST_CAN_MINT_ATTESTATION_KEY = bytes32(\\\"optimist.can-mint\\\");\\n\\n /**\\n * @notice Attestation key used by Coinbase to issue attestations for Quest participants.\\n */\\n bytes32 public constant COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY =\\n bytes32(\\\"coinbase.quest-eligible\\\");\\n\\n /**\\n * @notice Address of the AttestationStation contract.\\n */\\n AttestationStation public immutable ATTESTATION_STATION;\\n\\n /**\\n * @notice Attestor that issues 'optimist.can-mint' attestations.\\n */\\n address public immutable ALLOWLIST_ATTESTOR;\\n\\n /**\\n * @notice Attestor that issues 'coinbase.quest-eligible' attestations.\\n */\\n address public immutable COINBASE_QUEST_ATTESTOR;\\n\\n /**\\n * @notice Address of OptimistInviter contract that issues 'optimist.can-mint-from-invite'\\n * attestations.\\n */\\n address public immutable OPTIMIST_INVITER;\\n\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _attestationStation Address of the AttestationStation contract.\\n * @param _allowlistAttestor Address of the allowlist attestor.\\n * @param _coinbaseQuestAttestor Address of the Coinbase Quest attestor.\\n * @param _optimistInviter Address of the OptimistInviter contract.\\n */\\n constructor(\\n AttestationStation _attestationStation,\\n address _allowlistAttestor,\\n address _coinbaseQuestAttestor,\\n address _optimistInviter\\n ) Semver(1, 0, 0) {\\n ATTESTATION_STATION = _attestationStation;\\n ALLOWLIST_ATTESTOR = _allowlistAttestor;\\n COINBASE_QUEST_ATTESTOR = _coinbaseQuestAttestor;\\n OPTIMIST_INVITER = _optimistInviter;\\n }\\n\\n /**\\n * @notice Checks whether a given address is allowed to mint the Optimist NFT yet. Since the\\n * Optimist NFT will also be used as part of the Citizens House, mints are currently\\n * restricted. Eventually anyone will be able to mint.\\n *\\n * Currently, address is allowed to mint if it satisfies any of the following:\\n * 1) Has a valid 'optimist.can-mint' attestation from the allowlist attestor.\\n * 2) Has a valid 'coinbase.quest-eligible' attestation from Coinbase Quest attestor\\n * 3) Has a valid 'optimist.can-mint-from-invite' attestation from the OptimistInviter\\n * contract.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address is allowed to mint yet.\\n */\\n function isAllowedToMint(address _claimer) public view returns (bool) {\\n return\\n _hasAttestationFromAllowlistAttestor(_claimer) ||\\n _hasAttestationFromCoinbaseQuestAttestor(_claimer) ||\\n _hasAttestationFromOptimistInviter(_claimer);\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid 'optimist.can-mint' attestation from the\\n * allowlist attestor.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address has a valid attestation.\\n */\\n function _hasAttestationFromAllowlistAttestor(address _claimer) internal view returns (bool) {\\n // Expected attestation value is bytes32(\\\"true\\\")\\n return\\n _hasValidAttestation(ALLOWLIST_ATTESTOR, _claimer, OPTIMIST_CAN_MINT_ATTESTATION_KEY);\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid attestation from the Coinbase attestor.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address has a valid attestation.\\n */\\n function _hasAttestationFromCoinbaseQuestAttestor(address _claimer)\\n internal\\n view\\n returns (bool)\\n {\\n // Expected attestation value is bytes32(\\\"true\\\")\\n return\\n _hasValidAttestation(\\n COINBASE_QUEST_ATTESTOR,\\n _claimer,\\n COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY\\n );\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid attestation from the OptimistInviter contract.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address has a valid attestation.\\n */\\n function _hasAttestationFromOptimistInviter(address _claimer) internal view returns (bool) {\\n // Expected attestation value is the inviter's address\\n return\\n _hasValidAttestation(\\n OPTIMIST_INVITER,\\n _claimer,\\n OptimistConstants.OPTIMIST_CAN_MINT_FROM_INVITE_ATTESTATION_KEY\\n );\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid truthy attestation.\\n * Any attestation val other than bytes32(\\\"\\\") is considered truthy.\\n *\\n * @param _creator Address that made the attestation.\\n * @param _about Address attestation is about.\\n * @param _key Key of the attestation.\\n *\\n * @return Whether or not the address has a valid truthy attestation.\\n */\\n function _hasValidAttestation(\\n address _creator,\\n address _about,\\n bytes32 _key\\n ) internal view returns (bool) {\\n return ATTESTATION_STATION.attestations(_creator, _about, _key).length > 0;\\n }\\n}\\n\",\"keccak256\":\"0xd36a677571450d2d9be832beb80e5c37481fcdfc355e6a9b929ac9c8d4966ca0\",\"license\":\"MIT\"},\"contracts/universal/op-nft/libraries/OptimistConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title OptimistConstants\\n * @notice Library for storing Optimist related constants that are shared in multiple contracts.\\n */\\n\\nlibrary OptimistConstants {\\n /**\\n * @notice Attestation key issued by OptimistInviter allowing the attested account to mint.\\n */\\n bytes32 internal constant OPTIMIST_CAN_MINT_FROM_INVITE_ATTESTATION_KEY =\\n bytes32(\\\"optimist.can-mint-from-invite\\\");\\n}\\n\",\"keccak256\":\"0x6eebe1db87f8a5de79bf8af9120e5b0cc6a9b51d8d86e6461cdb6bc52a1dde21\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x6101406040523480156200001257600080fd5b5060405162002c7f38038062002c7f8339810160408190526200003591620003ee565b6002608052600060a081905260c0526001600160a01b0380841660e052828116610100528116610120526200006b858562000076565b5050505050620005f4565b600054610100900460ff1615808015620000975750600054600160ff909116105b80620000c75750620000b430620001b660201b62000dd61760201c565b158015620000c7575060005460ff166001145b620001305760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000154576000805461ff0019166101001790555b620001608383620001c5565b6200016a62000231565b8015620001b1576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b600054610100900460ff16620002215760405162461bcd60e51b815260206004820152602b602482015260008051602062002c5f83398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000127565b6200022d82826200028f565b5050565b600054610100900460ff166200028d5760405162461bcd60e51b815260206004820152602b602482015260008051602062002c5f83398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000127565b565b600054610100900460ff16620002eb5760405162461bcd60e51b815260206004820152602b602482015260008051602062002c5f83398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000127565b6065620002f9838262000528565b506066620001b1828262000528565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200033057600080fd5b81516001600160401b03808211156200034d576200034d62000308565b604051601f8301601f19908116603f0116810190828211818310171562000378576200037862000308565b816040528381526020925086838588010111156200039557600080fd5b600091505b83821015620003b957858201830151818301840152908201906200039a565b83821115620003cb5760008385830101525b9695505050505050565b6001600160a01b0381168114620003eb57600080fd5b50565b600080600080600060a086880312156200040757600080fd5b85516001600160401b03808211156200041f57600080fd5b6200042d89838a016200031e565b965060208801519150808211156200044457600080fd5b5062000453888289016200031e565b94505060408601516200046681620003d5565b60608701519093506200047981620003d5565b60808701519092506200048c81620003d5565b809150509295509295909350565b600181811c90821680620004af57607f821691505b602082108103620004d057634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001b157600081815260208120601f850160051c81016020861015620004ff5750805b601f850160051c820191505b8181101562000520578281556001016200050b565b505050505050565b81516001600160401b0381111562000544576200054462000308565b6200055c816200055584546200049a565b84620004d6565b602080601f8311600181146200059457600084156200057b5750858301515b600019600386901b1c1916600185901b17855562000520565b600085815260208120601f198616915b82811015620005c557888601518255948401946001909101908401620005a4565b5085821015620005e45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051610100516101205161260662000659600039600081816103930152610c900152600081816103ba0152610b1301526000818161022c0152610abc01526000610928015260006108ff015260006108d601526126066000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c80636a627842116100e3578063a22cb4651161008c578063ce5dd1b511610066578063ce5dd1b51461038e578063db083d71146103b5578063e985e9c5146103dc57600080fd5b8063a22cb4651461035a578063b88d4fde14610368578063c87b56dd1461037b57600080fd5b80637c08652f116100bd5780637c08652f146103185780638f328a1f1461033f57806395d89b411461035257600080fd5b80636a627842146102ea5780636c0360eb146102fd57806370a082311461030557600080fd5b806323b872dd116101455780634cd88b761161011f5780634cd88b76146102bc57806354fd4d50146102cf5780636352211e146102d757600080fd5b806323b872dd1461028357806342842e0e1461029657806342966c68146102a957600080fd5b8063095ea7b311610176578063095ea7b31461021257806319f463f21461022757806321d3d5cf1461024e57600080fd5b806301ffc9a71461019d57806306fdde03146101c5578063081812fc146101da575b600080fd5b6101b06101ab366004611d0e565b610425565b60405190151581526020015b60405180910390f35b6101cd61050a565b6040516101bc9190611d83565b6101ed6101e8366004611d96565b61059c565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b610225610220366004611dd8565b6105d0565b005b6101ed7f000000000000000000000000000000000000000000000000000000000000000081565b6102757f6f7074696d6973742e626173652d75726900000000000000000000000000000081565b6040519081526020016101bc565b610225610291366004611e02565b61061d565b6102256102a4366004611e02565b6106aa565b6102256102b7366004611d96565b6106c5565b6102256102ca366004611f24565b61074c565b6101cd6108cf565b6101ed6102e5366004611d96565b610972565b6102256102f8366004611f88565b6109e4565b6101cd610a7f565b610275610313366004611f88565b610b94565b610275610326366004611f88565b73ffffffffffffffffffffffffffffffffffffffff1690565b6101b061034d366004611f88565b610c48565b6101cd610cfd565b610225610220366004611fb1565b610225610376366004611fe8565b610d0c565b6101cd610389366004611d96565b610d9a565b6101ed7f000000000000000000000000000000000000000000000000000000000000000081565b6101ed7f000000000000000000000000000000000000000000000000000000000000000081565b6101b06103ea366004612064565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152606a6020908152604080832093909416825291909152205460ff1690565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd0000000000000000000000000000000000000000000000000000000014806104b857507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061050457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60606065805461051990612097565b80601f016020809104026020016040519081016040528092919081815260200182805461054590612097565b80156105925780601f1061056757610100808354040283529160200191610592565b820191906000526020600020905b81548152906001019060200180831161057557829003601f168201915b5050505050905090565b60006105a782610df2565b5060009081526069602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b60405162461bcd60e51b815260206004820152601a60248201527f4f7074696d6973743a20736f756c20626f756e6420746f6b656e00000000000060448201526064015b60405180910390fd5b610628335b82610e63565b61069a5760405162461bcd60e51b815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610614565b6106a5838383610f23565b505050565b6106a583838360405180602001604052806000815250610d0c565b6106ce33610622565b6107405760405162461bcd60e51b815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610614565b61074981611161565b50565b600054610100900460ff161580801561076c5750600054600160ff909116105b806107865750303b158015610786575060005460ff166001145b6107f85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610614565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561085657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610860838361123b565b6108686112c2565b80156106a557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b60606108fa7f0000000000000000000000000000000000000000000000000000000000000000611341565b6109237f0000000000000000000000000000000000000000000000000000000000000000611341565b61094c7f0000000000000000000000000000000000000000000000000000000000000000611341565b60405160200161095e939291906120ea565b604051602081830303815290604052905090565b60008181526067602052604081205473ffffffffffffffffffffffffffffffffffffffff16806105045760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610614565b6109ed81610c48565b610a5f5760405162461bcd60e51b815260206004820152602560248201527f4f7074696d6973743a2061646472657373206973206e6f74206f6e20616c6c6f60448201527f774c6973740000000000000000000000000000000000000000000000000000006064820152608401610614565b6107498173ffffffffffffffffffffffffffffffffffffffff8116611476565b6040517f29b42cb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301523060248301527f6f7074696d6973742e626173652d75726900000000000000000000000000000060448301526060917f0000000000000000000000000000000000000000000000000000000000000000909116906329b42cb590606401600060405180830381865afa158015610b5c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b849190810190612160565b60405160200161095e91906121d7565b600073ffffffffffffffffffffffffffffffffffffffff8216610c1f5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f74206120766160448201527f6c6964206f776e657200000000000000000000000000000000000000000000006064820152608401610614565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526068602052604090205490565b6040517f4813d8a600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690634813d8a690602401602060405180830381865afa158015610cd9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050491906121f3565b60606066805461051990612097565b610d163383610e63565b610d885760405162461bcd60e51b815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610614565b610d9484848484611490565b50505050565b6060610da4610a7f565b610daf836014611519565b604051602001610dc0929190612210565b6040516020818303038152906040529050919050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60008181526067602052604090205473ffffffffffffffffffffffffffffffffffffffff166107495760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610614565b600080610e6f83610972565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610edd575073ffffffffffffffffffffffffffffffffffffffff8082166000908152606a602090815260408083209388168352929052205460ff165b80610f1b57508373ffffffffffffffffffffffffffffffffffffffff16610f038461059c565b73ffffffffffffffffffffffffffffffffffffffff16145b949350505050565b8273ffffffffffffffffffffffffffffffffffffffff16610f4382610972565b73ffffffffffffffffffffffffffffffffffffffff1614610fcc5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610614565b73ffffffffffffffffffffffffffffffffffffffff82166110545760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610614565b61105f838383611749565b61106a6000826117cc565b73ffffffffffffffffffffffffffffffffffffffff831660009081526068602052604081208054600192906110a09084906122c1565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526068602052604081208054600192906110db9084906122d8565b909155505060008181526067602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061116c82610972565b905061117a81600084611749565b6111856000836117cc565b73ffffffffffffffffffffffffffffffffffffffff811660009081526068602052604081208054600192906111bb9084906122c1565b909155505060008281526067602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555183919073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45b5050565b600054610100900460ff166112b85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610614565b611237828261186c565b600054610100900460ff1661133f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610614565b565b60608160000361138457505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156113ae5780611398816122f0565b91506113a79050600a83612357565b9150611388565b60008167ffffffffffffffff8111156113c9576113c9611e3e565b6040519080825280601f01601f1916602001820160405280156113f3576020820181803683370190505b5090505b8415610f1b576114086001836122c1565b9150611415600a8661236b565b6114209060306122d8565b60f81b8183815181106114355761143561237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061146f600a86612357565b94506113f7565b611237828260405180602001604052806000815250611902565b61149b848484610f23565b6114a78484848461198b565b610d945760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610614565b606060006115288360026123ae565b6115339060026122d8565b67ffffffffffffffff81111561154b5761154b611e3e565b6040519080825280601f01601f191660200182016040528015611575576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106115ac576115ac61237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061160f5761160f61237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061164b8460026123ae565b6116569060016122d8565b90505b60018111156116f3577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106116975761169761237f565b1a60f81b8282815181106116ad576116ad61237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936116ec816123eb565b9050611659565b5083156117425760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610614565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff83161580611780575073ffffffffffffffffffffffffffffffffffffffff8216155b6106a55760405162461bcd60e51b815260206004820152601a60248201527f4f7074696d6973743a20736f756c20626f756e6420746f6b656e0000000000006044820152606401610614565b600081815260696020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155819061182682610972565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600054610100900460ff166118e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610614565b60656118f5838261246e565b5060666106a5828261246e565b61190c8383611b46565b611919600084848461198b565b6106a55760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610614565b600073ffffffffffffffffffffffffffffffffffffffff84163b15611b3b576040517f150b7a0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063150b7a0290611a0290339089908890889060040161256a565b6020604051808303816000875af1925050508015611a3d575060408051601f3d908101601f19168201909252611a3a918101906125b3565b60015b611af0573d808015611a6b576040519150601f19603f3d011682016040523d82523d6000602084013e611a70565b606091505b508051600003611ae85760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610614565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149050610f1b565b506001949350505050565b73ffffffffffffffffffffffffffffffffffffffff8216611ba95760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610614565b60008181526067602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611c1b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610614565b611c2760008383611749565b73ffffffffffffffffffffffffffffffffffffffff82166000908152606860205260408120805460019290611c5d9084906122d8565b909155505060008181526067602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461074957600080fd5b600060208284031215611d2057600080fd5b813561174281611ce0565b60005b83811015611d46578181015183820152602001611d2e565b83811115610d945750506000910152565b60008151808452611d6f816020860160208601611d2b565b601f01601f19169290920160200192915050565b6020815260006117426020830184611d57565b600060208284031215611da857600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611dd357600080fd5b919050565b60008060408385031215611deb57600080fd5b611df483611daf565b946020939093013593505050565b600080600060608486031215611e1757600080fd5b611e2084611daf565b9250611e2e60208501611daf565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611e9657611e96611e3e565b604052919050565b600067ffffffffffffffff821115611eb857611eb8611e3e565b50601f01601f191660200190565b6000611ed9611ed484611e9e565b611e6d565b9050828152838383011115611eed57600080fd5b828260208301376000602084830101529392505050565b600082601f830112611f1557600080fd5b61174283833560208501611ec6565b60008060408385031215611f3757600080fd5b823567ffffffffffffffff80821115611f4f57600080fd5b611f5b86838701611f04565b93506020850135915080821115611f7157600080fd5b50611f7e85828601611f04565b9150509250929050565b600060208284031215611f9a57600080fd5b61174282611daf565b801515811461074957600080fd5b60008060408385031215611fc457600080fd5b611fcd83611daf565b91506020830135611fdd81611fa3565b809150509250929050565b60008060008060808587031215611ffe57600080fd5b61200785611daf565b935061201560208601611daf565b925060408501359150606085013567ffffffffffffffff81111561203857600080fd5b8501601f8101871361204957600080fd5b61205887823560208401611ec6565b91505092959194509250565b6000806040838503121561207757600080fd5b61208083611daf565b915061208e60208401611daf565b90509250929050565b600181811c908216806120ab57607f821691505b6020821081036120e4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600084516120fc818460208901611d2b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612138816001850160208a01611d2b565b60019201918201528351612153816002840160208801611d2b565b0160020195945050505050565b60006020828403121561217257600080fd5b815167ffffffffffffffff81111561218957600080fd5b8201601f8101841361219a57600080fd5b80516121a8611ed482611e9e565b8181528560208385010111156121bd57600080fd5b6121ce826020830160208601611d2b565b95945050505050565b600082516121e9818460208701611d2b565b9190910192915050565b60006020828403121561220557600080fd5b815161174281611fa3565b60008351612222818460208801611d2b565b7f2f00000000000000000000000000000000000000000000000000000000000000908301908152835161225c816001840160208801611d2b565b7f2e6a736f6e00000000000000000000000000000000000000000000000000000060019290910191820152600601949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156122d3576122d3612292565b500390565b600082198211156122eb576122eb612292565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361232157612321612292565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261236657612366612328565b500490565b60008261237a5761237a612328565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156123e6576123e6612292565b500290565b6000816123fa576123fa612292565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b601f8211156106a557600081815260208120601f850160051c810160208610156124475750805b601f850160051c820191505b8181101561246657828155600101612453565b505050505050565b815167ffffffffffffffff81111561248857612488611e3e565b61249c816124968454612097565b84612420565b602080601f8311600181146124ef57600084156124b95750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612466565b600085815260208120601f198616915b8281101561251e578886015182559484019460019091019084016124ff565b508582101561255a57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526125a96080830184611d57565b9695505050505050565b6000602082840312156125c557600080fd5b815161174281611ce056fea264697066735822122068519f9cbd8d80e9e293c6c977994da4f38aba3722422b6bfce53b68916efab964736f6c634300080f0033496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101985760003560e01c80636a627842116100e3578063a22cb4651161008c578063ce5dd1b511610066578063ce5dd1b51461038e578063db083d71146103b5578063e985e9c5146103dc57600080fd5b8063a22cb4651461035a578063b88d4fde14610368578063c87b56dd1461037b57600080fd5b80637c08652f116100bd5780637c08652f146103185780638f328a1f1461033f57806395d89b411461035257600080fd5b80636a627842146102ea5780636c0360eb146102fd57806370a082311461030557600080fd5b806323b872dd116101455780634cd88b761161011f5780634cd88b76146102bc57806354fd4d50146102cf5780636352211e146102d757600080fd5b806323b872dd1461028357806342842e0e1461029657806342966c68146102a957600080fd5b8063095ea7b311610176578063095ea7b31461021257806319f463f21461022757806321d3d5cf1461024e57600080fd5b806301ffc9a71461019d57806306fdde03146101c5578063081812fc146101da575b600080fd5b6101b06101ab366004611d0e565b610425565b60405190151581526020015b60405180910390f35b6101cd61050a565b6040516101bc9190611d83565b6101ed6101e8366004611d96565b61059c565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b610225610220366004611dd8565b6105d0565b005b6101ed7f000000000000000000000000000000000000000000000000000000000000000081565b6102757f6f7074696d6973742e626173652d75726900000000000000000000000000000081565b6040519081526020016101bc565b610225610291366004611e02565b61061d565b6102256102a4366004611e02565b6106aa565b6102256102b7366004611d96565b6106c5565b6102256102ca366004611f24565b61074c565b6101cd6108cf565b6101ed6102e5366004611d96565b610972565b6102256102f8366004611f88565b6109e4565b6101cd610a7f565b610275610313366004611f88565b610b94565b610275610326366004611f88565b73ffffffffffffffffffffffffffffffffffffffff1690565b6101b061034d366004611f88565b610c48565b6101cd610cfd565b610225610220366004611fb1565b610225610376366004611fe8565b610d0c565b6101cd610389366004611d96565b610d9a565b6101ed7f000000000000000000000000000000000000000000000000000000000000000081565b6101ed7f000000000000000000000000000000000000000000000000000000000000000081565b6101b06103ea366004612064565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152606a6020908152604080832093909416825291909152205460ff1690565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd0000000000000000000000000000000000000000000000000000000014806104b857507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061050457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60606065805461051990612097565b80601f016020809104026020016040519081016040528092919081815260200182805461054590612097565b80156105925780601f1061056757610100808354040283529160200191610592565b820191906000526020600020905b81548152906001019060200180831161057557829003601f168201915b5050505050905090565b60006105a782610df2565b5060009081526069602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b60405162461bcd60e51b815260206004820152601a60248201527f4f7074696d6973743a20736f756c20626f756e6420746f6b656e00000000000060448201526064015b60405180910390fd5b610628335b82610e63565b61069a5760405162461bcd60e51b815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610614565b6106a5838383610f23565b505050565b6106a583838360405180602001604052806000815250610d0c565b6106ce33610622565b6107405760405162461bcd60e51b815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610614565b61074981611161565b50565b600054610100900460ff161580801561076c5750600054600160ff909116105b806107865750303b158015610786575060005460ff166001145b6107f85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610614565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561085657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610860838361123b565b6108686112c2565b80156106a557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b60606108fa7f0000000000000000000000000000000000000000000000000000000000000000611341565b6109237f0000000000000000000000000000000000000000000000000000000000000000611341565b61094c7f0000000000000000000000000000000000000000000000000000000000000000611341565b60405160200161095e939291906120ea565b604051602081830303815290604052905090565b60008181526067602052604081205473ffffffffffffffffffffffffffffffffffffffff16806105045760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610614565b6109ed81610c48565b610a5f5760405162461bcd60e51b815260206004820152602560248201527f4f7074696d6973743a2061646472657373206973206e6f74206f6e20616c6c6f60448201527f774c6973740000000000000000000000000000000000000000000000000000006064820152608401610614565b6107498173ffffffffffffffffffffffffffffffffffffffff8116611476565b6040517f29b42cb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301523060248301527f6f7074696d6973742e626173652d75726900000000000000000000000000000060448301526060917f0000000000000000000000000000000000000000000000000000000000000000909116906329b42cb590606401600060405180830381865afa158015610b5c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b849190810190612160565b60405160200161095e91906121d7565b600073ffffffffffffffffffffffffffffffffffffffff8216610c1f5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f74206120766160448201527f6c6964206f776e657200000000000000000000000000000000000000000000006064820152608401610614565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526068602052604090205490565b6040517f4813d8a600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690634813d8a690602401602060405180830381865afa158015610cd9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050491906121f3565b60606066805461051990612097565b610d163383610e63565b610d885760405162461bcd60e51b815260206004820152602e60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201527f72206e6f7220617070726f7665640000000000000000000000000000000000006064820152608401610614565b610d9484848484611490565b50505050565b6060610da4610a7f565b610daf836014611519565b604051602001610dc0929190612210565b6040516020818303038152906040529050919050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60008181526067602052604090205473ffffffffffffffffffffffffffffffffffffffff166107495760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610614565b600080610e6f83610972565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610edd575073ffffffffffffffffffffffffffffffffffffffff8082166000908152606a602090815260408083209388168352929052205460ff165b80610f1b57508373ffffffffffffffffffffffffffffffffffffffff16610f038461059c565b73ffffffffffffffffffffffffffffffffffffffff16145b949350505050565b8273ffffffffffffffffffffffffffffffffffffffff16610f4382610972565b73ffffffffffffffffffffffffffffffffffffffff1614610fcc5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610614565b73ffffffffffffffffffffffffffffffffffffffff82166110545760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610614565b61105f838383611749565b61106a6000826117cc565b73ffffffffffffffffffffffffffffffffffffffff831660009081526068602052604081208054600192906110a09084906122c1565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526068602052604081208054600192906110db9084906122d8565b909155505060008181526067602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061116c82610972565b905061117a81600084611749565b6111856000836117cc565b73ffffffffffffffffffffffffffffffffffffffff811660009081526068602052604081208054600192906111bb9084906122c1565b909155505060008281526067602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555183919073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45b5050565b600054610100900460ff166112b85760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610614565b611237828261186c565b600054610100900460ff1661133f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610614565b565b60608160000361138457505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156113ae5780611398816122f0565b91506113a79050600a83612357565b9150611388565b60008167ffffffffffffffff8111156113c9576113c9611e3e565b6040519080825280601f01601f1916602001820160405280156113f3576020820181803683370190505b5090505b8415610f1b576114086001836122c1565b9150611415600a8661236b565b6114209060306122d8565b60f81b8183815181106114355761143561237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061146f600a86612357565b94506113f7565b611237828260405180602001604052806000815250611902565b61149b848484610f23565b6114a78484848461198b565b610d945760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610614565b606060006115288360026123ae565b6115339060026122d8565b67ffffffffffffffff81111561154b5761154b611e3e565b6040519080825280601f01601f191660200182016040528015611575576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106115ac576115ac61237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061160f5761160f61237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061164b8460026123ae565b6116569060016122d8565b90505b60018111156116f3577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106116975761169761237f565b1a60f81b8282815181106116ad576116ad61237f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c936116ec816123eb565b9050611659565b5083156117425760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610614565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff83161580611780575073ffffffffffffffffffffffffffffffffffffffff8216155b6106a55760405162461bcd60e51b815260206004820152601a60248201527f4f7074696d6973743a20736f756c20626f756e6420746f6b656e0000000000006044820152606401610614565b600081815260696020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416908117909155819061182682610972565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600054610100900460ff166118e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610614565b60656118f5838261246e565b5060666106a5828261246e565b61190c8383611b46565b611919600084848461198b565b6106a55760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610614565b600073ffffffffffffffffffffffffffffffffffffffff84163b15611b3b576040517f150b7a0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063150b7a0290611a0290339089908890889060040161256a565b6020604051808303816000875af1925050508015611a3d575060408051601f3d908101601f19168201909252611a3a918101906125b3565b60015b611af0573d808015611a6b576040519150601f19603f3d011682016040523d82523d6000602084013e611a70565b606091505b508051600003611ae85760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610614565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149050610f1b565b506001949350505050565b73ffffffffffffffffffffffffffffffffffffffff8216611ba95760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610614565b60008181526067602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611c1b5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610614565b611c2760008383611749565b73ffffffffffffffffffffffffffffffffffffffff82166000908152606860205260408120805460019290611c5d9084906122d8565b909155505060008181526067602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461074957600080fd5b600060208284031215611d2057600080fd5b813561174281611ce0565b60005b83811015611d46578181015183820152602001611d2e565b83811115610d945750506000910152565b60008151808452611d6f816020860160208601611d2b565b601f01601f19169290920160200192915050565b6020815260006117426020830184611d57565b600060208284031215611da857600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611dd357600080fd5b919050565b60008060408385031215611deb57600080fd5b611df483611daf565b946020939093013593505050565b600080600060608486031215611e1757600080fd5b611e2084611daf565b9250611e2e60208501611daf565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611e9657611e96611e3e565b604052919050565b600067ffffffffffffffff821115611eb857611eb8611e3e565b50601f01601f191660200190565b6000611ed9611ed484611e9e565b611e6d565b9050828152838383011115611eed57600080fd5b828260208301376000602084830101529392505050565b600082601f830112611f1557600080fd5b61174283833560208501611ec6565b60008060408385031215611f3757600080fd5b823567ffffffffffffffff80821115611f4f57600080fd5b611f5b86838701611f04565b93506020850135915080821115611f7157600080fd5b50611f7e85828601611f04565b9150509250929050565b600060208284031215611f9a57600080fd5b61174282611daf565b801515811461074957600080fd5b60008060408385031215611fc457600080fd5b611fcd83611daf565b91506020830135611fdd81611fa3565b809150509250929050565b60008060008060808587031215611ffe57600080fd5b61200785611daf565b935061201560208601611daf565b925060408501359150606085013567ffffffffffffffff81111561203857600080fd5b8501601f8101871361204957600080fd5b61205887823560208401611ec6565b91505092959194509250565b6000806040838503121561207757600080fd5b61208083611daf565b915061208e60208401611daf565b90509250929050565b600181811c908216806120ab57607f821691505b6020821081036120e4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600084516120fc818460208901611d2b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612138816001850160208a01611d2b565b60019201918201528351612153816002840160208801611d2b565b0160020195945050505050565b60006020828403121561217257600080fd5b815167ffffffffffffffff81111561218957600080fd5b8201601f8101841361219a57600080fd5b80516121a8611ed482611e9e565b8181528560208385010111156121bd57600080fd5b6121ce826020830160208601611d2b565b95945050505050565b600082516121e9818460208701611d2b565b9190910192915050565b60006020828403121561220557600080fd5b815161174281611fa3565b60008351612222818460208801611d2b565b7f2f00000000000000000000000000000000000000000000000000000000000000908301908152835161225c816001840160208801611d2b565b7f2e6a736f6e00000000000000000000000000000000000000000000000000000060019290910191820152600601949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156122d3576122d3612292565b500390565b600082198211156122eb576122eb612292565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361232157612321612292565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261236657612366612328565b500490565b60008261237a5761237a612328565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156123e6576123e6612292565b500290565b6000816123fa576123fa612292565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b601f8211156106a557600081815260208120601f850160051c810160208610156124475750805b601f850160051c820191505b8181101561246657828155600101612453565b505050505050565b815167ffffffffffffffff81111561248857612488611e3e565b61249c816124968454612097565b84612420565b602080601f8311600181146124ef57600084156124b95750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612466565b600085815260208120601f198616915b8281101561251e578886015182559484019460019091019084016124ff565b508582101561255a57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526125a96080830184611d57565b9695505050505050565b6000602082840312156125c557600080fd5b815161174281611ce056fea264697066735822122068519f9cbd8d80e9e293c6c977994da4f38aba3722422b6bfce53b68916efab964736f6c634300080f0033", - "devdoc": { - "author": "Optimism CollectiveGitcoin", - "kind": "dev", - "methods": { - "balanceOf(address)": { - "details": "See {IERC721-balanceOf}." - }, - "baseURI()": { - "returns": { - "_0": "BaseURI for all tokens." - } - }, - "burn(uint256)": { - "details": "Burns `tokenId`. See {ERC721-_burn}. Requirements: - The caller must own `tokenId` or be an approved operator." - }, - "constructor": { - "custom:semver": "2.0.0", - "params": { - "_attestationStation": "Address of the AttestationStation contract.", - "_baseURIAttestor": "Address of the baseURI attestor.", - "_name": "Token name.", - "_optimistAllowlist": "Address of the OptimistAllowlist contract", - "_symbol": "Token symbol." - } - }, - "getApproved(uint256)": { - "details": "See {IERC721-getApproved}." - }, - "initialize(string,string)": { - "params": { - "_name": "Token name.", - "_symbol": "Token symbol." - } - }, - "isApprovedForAll(address,address)": { - "details": "See {IERC721-isApprovedForAll}." - }, - "isOnAllowList(address)": { - "returns": { - "_0": "Whether or not the address is allowed to mint yet." - } - }, - "mint(address)": { - "params": { - "_recipient": "Address of the token recipient." - } - }, - "name()": { - "details": "See {IERC721Metadata-name}." - }, - "ownerOf(uint256)": { - "details": "See {IERC721-ownerOf}." - }, - "safeTransferFrom(address,address,uint256)": { - "details": "See {IERC721-safeTransferFrom}." - }, - "safeTransferFrom(address,address,uint256,bytes)": { - "details": "See {IERC721-safeTransferFrom}." - }, - "supportsInterface(bytes4)": { - "details": "See {IERC165-supportsInterface}." - }, - "symbol()": { - "details": "See {IERC721Metadata-symbol}." - }, - "tokenIdOfAddress(address)": { - "returns": { - "_0": "Token ID for the token owned by the given address." - } - }, - "tokenURI(uint256)": { - "params": { - "_tokenId": "Token ID to query." - }, - "returns": { - "_0": "Token URI for the given token by ID." - } - }, - "transferFrom(address,address,uint256)": { - "details": "See {IERC721-transferFrom}." - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "title": "Optimist", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "ATTESTATION_STATION()": { - "notice": "Address of the AttestationStation contract." - }, - "BASE_URI_ATTESTATION_KEY()": { - "notice": "Attestation key used by the attestor to attest the baseURI." - }, - "BASE_URI_ATTESTOR()": { - "notice": "Attestor who attests to baseURI." - }, - "OPTIMIST_ALLOWLIST()": { - "notice": "Address of the OptimistAllowlist contract." - }, - "approve(address,uint256)": { - "notice": "Disabled for the Optimist NFT (Soul Bound Token)." - }, - "baseURI()": { - "notice": "Returns the baseURI for all tokens." - }, - "initialize(string,string)": { - "notice": "Initializes the Optimist contract." - }, - "isOnAllowList(address)": { - "notice": "Checks OptimistAllowlist to determine whether a given address is allowed to mint the Optimist NFT. Since the Optimist NFT will also be used as part of the Citizens House, mints are currently restricted. Eventually anyone will be able to mint." - }, - "mint(address)": { - "notice": "Allows an address to mint an Optimist NFT. Token ID is the uint256 representation of the recipient's address. Recipients must be permitted to mint, eventually anyone will be able to mint. One token per address." - }, - "setApprovalForAll(address,bool)": { - "notice": "Disabled for the Optimist NFT (Soul Bound Token)." - }, - "tokenIdOfAddress(address)": { - "notice": "Returns the token ID for the token owned by a given address. This is the uint256 representation of the given address." - }, - "tokenURI(uint256)": { - "notice": "Returns the token URI for a given token by ID" - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "A Soul Bound Token for real humans only(tm).", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 1166, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 1169, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 2697, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 3505, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "__gap", - "offset": 0, - "slot": "51", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 1339, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_name", - "offset": 0, - "slot": "101", - "type": "t_string_storage" - }, - { - "astId": 1341, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_symbol", - "offset": 0, - "slot": "102", - "type": "t_string_storage" - }, - { - "astId": 1345, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_owners", - "offset": 0, - "slot": "103", - "type": "t_mapping(t_uint256,t_address)" - }, - { - "astId": 1349, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_balances", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_uint256)" - }, - { - "astId": 1353, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_tokenApprovals", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_uint256,t_address)" - }, - { - "astId": 1359, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "_operatorApprovals", - "offset": 0, - "slot": "106", - "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" - }, - { - "astId": 2201, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "__gap", - "offset": 0, - "slot": "107", - "type": "t_array(t_uint256)44_storage" - }, - { - "astId": 2385, - "contract": "contracts/universal/op-nft/Optimist.sol:Optimist", - "label": "__gap", - "offset": 0, - "slot": "151", - "type": "t_array(t_uint256)50_storage" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)44_storage": { - "base": "t_uint256", - "encoding": "inplace", - "label": "uint256[44]", - "numberOfBytes": "1408" - }, - "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_mapping(t_address,t_mapping(t_address,t_bool))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => bool))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_bool)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_mapping(t_uint256,t_address)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => address)", - "numberOfBytes": "32", - "value": "t_address" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "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-bedrock/deployments/optimism-mainnet/OptimistAllowlist.json b/packages/contracts-bedrock/deployments/optimism-mainnet/OptimistAllowlist.json deleted file mode 100644 index 295667f8c81e..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/OptimistAllowlist.json +++ /dev/null @@ -1,232 +0,0 @@ -{ - "address": "0x7688895Ad581637e0e50605189AC15c3B1CF0014", - "abi": [ - { - "inputs": [ - { - "internalType": "contract AttestationStation", - "name": "_attestationStation", - "type": "address" - }, - { - "internalType": "address", - "name": "_allowlistAttestor", - "type": "address" - }, - { - "internalType": "address", - "name": "_coinbaseQuestAttestor", - "type": "address" - }, - { - "internalType": "address", - "name": "_optimistInviter", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ALLOWLIST_ATTESTOR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ATTESTATION_STATION", - "outputs": [ - { - "internalType": "contract AttestationStation", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "COINBASE_QUEST_ATTESTOR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMIST_CAN_MINT_ATTESTATION_KEY", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMIST_INVITER", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_claimer", - "type": "address" - } - ], - "name": "isAllowedToMint", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0xa4fdbc20288ff71bcf2ae03124cfdb99231db7643509e5e09de7e637e17e925a", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "568758", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xb669a73c250c84f232a25032e1da2a777b0fc5a39d0d8ee38742decff4873794", - "transactionHash": "0xa4fdbc20288ff71bcf2ae03124cfdb99231db7643509e5e09de7e637e17e925a", - "logs": [], - "blockNumber": 87031619, - "cumulativeGasUsed": "568758", - "status": 1, - "byzantium": true - }, - "args": [ - "0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77", - "0x60c5C9c98bcBd0b0F2fD89B24c16e533BaA8CdA3", - "0x661B7Acca8ebd93AFd349a088e9a9A00053DB1BF", - "0x073031A1E1b8F5458Ed41Ce56331F5fd7e1de929" - ], - "numDeployments": 1, - "solcInputHash": "d7155764d4bdb814f10e1bb45296292b", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract AttestationStation\",\"name\":\"_attestationStation\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_allowlistAttestor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_coinbaseQuestAttestor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_optimistInviter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ALLOWLIST_ATTESTOR\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ATTESTATION_STATION\",\"outputs\":[{\"internalType\":\"contract AttestationStation\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COINBASE_QUEST_ATTESTOR\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OPTIMIST_CAN_MINT_ATTESTATION_KEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OPTIMIST_INVITER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_claimer\",\"type\":\"address\"}],\"name\":\"isAllowedToMint\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:semver\":\"1.0.0\",\"params\":{\"_allowlistAttestor\":\"Address of the allowlist attestor.\",\"_attestationStation\":\"Address of the AttestationStation contract.\",\"_coinbaseQuestAttestor\":\"Address of the Coinbase Quest attestor.\",\"_optimistInviter\":\"Address of the OptimistInviter contract.\"}},\"isAllowedToMint(address)\":{\"params\":{\"_claimer\":\"Address to check.\"},\"returns\":{\"_0\":\"Whether or not the address is allowed to mint yet.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"title\":\"OptimistAllowlist\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"ALLOWLIST_ATTESTOR()\":{\"notice\":\"Attestor that issues 'optimist.can-mint' attestations.\"},\"ATTESTATION_STATION()\":{\"notice\":\"Address of the AttestationStation contract.\"},\"COINBASE_QUEST_ATTESTOR()\":{\"notice\":\"Attestor that issues 'coinbase.quest-eligible' attestations.\"},\"COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY()\":{\"notice\":\"Attestation key used by Coinbase to issue attestations for Quest participants.\"},\"OPTIMIST_CAN_MINT_ATTESTATION_KEY()\":{\"notice\":\"Attestation key used by the AllowlistAttestor to manually add addresses to the allowlist.\"},\"OPTIMIST_INVITER()\":{\"notice\":\"Address of OptimistInviter contract that issues 'optimist.can-mint-from-invite' attestations.\"},\"isAllowedToMint(address)\":{\"notice\":\"Checks whether a given address is allowed to mint the Optimist NFT yet. Since the Optimist NFT will also be used as part of the Citizens House, mints are currently restricted. Eventually anyone will be able to mint. Currently, address is allowed to mint if it satisfies any of the following: 1) Has a valid 'optimist.can-mint' attestation from the allowlist attestor. 2) Has a valid 'coinbase.quest-eligible' attestation from Coinbase Quest attestor 3) Has a valid 'optimist.can-mint-from-invite' attestation from the OptimistInviter contract.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"Source of truth for whether an address is able to mint an Optimist NFT. isAllowedToMint function checks various signals to return boolean value for whether an address is eligible or not.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/op-nft/OptimistAllowlist.sol\":\"OptimistAllowlist\"},\"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.0;\\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 uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\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\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\\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 /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/universal/op-nft/AttestationStation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title AttestationStation\\n * @author Optimism Collective\\n * @author Gitcoin\\n * @notice Where attestations live.\\n */\\ncontract AttestationStation is Semver {\\n /**\\n * @notice Struct representing data that is being attested.\\n *\\n * @custom:field about Address for which the attestation is about.\\n * @custom:field key A bytes32 key for the attestation.\\n * @custom:field val The attestation as arbitrary bytes.\\n */\\n struct AttestationData {\\n address about;\\n bytes32 key;\\n bytes val;\\n }\\n\\n /**\\n * @notice Maps addresses to attestations. Creator => About => Key => Value.\\n */\\n mapping(address => mapping(address => mapping(bytes32 => bytes))) public attestations;\\n\\n /**\\n * @notice Emitted when Attestation is created.\\n *\\n * @param creator Address that made the attestation.\\n * @param about Address attestation is about.\\n * @param key Key of the attestation.\\n * @param val Value of the attestation.\\n */\\n event AttestationCreated(\\n address indexed creator,\\n address indexed about,\\n bytes32 indexed key,\\n bytes val\\n );\\n\\n /**\\n * @custom:semver 1.1.0\\n */\\n constructor() Semver(1, 1, 0) {}\\n\\n /**\\n * @notice Allows anyone to create an attestation.\\n *\\n * @param _about Address that the attestation is about.\\n * @param _key A key used to namespace the attestation.\\n * @param _val An arbitrary value stored as part of the attestation.\\n */\\n function attest(\\n address _about,\\n bytes32 _key,\\n bytes memory _val\\n ) public {\\n attestations[msg.sender][_about][_key] = _val;\\n\\n emit AttestationCreated(msg.sender, _about, _key, _val);\\n }\\n\\n /**\\n * @notice Allows anyone to create attestations.\\n *\\n * @param _attestations An array of AttestationData structs.\\n */\\n function attest(AttestationData[] calldata _attestations) external {\\n uint256 length = _attestations.length;\\n for (uint256 i = 0; i < length; ) {\\n AttestationData memory attestation = _attestations[i];\\n\\n attest(attestation.about, attestation.key, attestation.val);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x421923e04df145353db12cd0352ccf516d9c29ab64b138733b4f7a6a450ce2be\",\"license\":\"MIT\"},\"contracts/universal/op-nft/OptimistAllowlist.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\nimport { AttestationStation } from \\\"./AttestationStation.sol\\\";\\nimport { OptimistConstants } from \\\"./libraries/OptimistConstants.sol\\\";\\n\\n/**\\n * @title OptimistAllowlist\\n * @notice Source of truth for whether an address is able to mint an Optimist NFT.\\n isAllowedToMint function checks various signals to return boolean value for whether an\\n address is eligible or not.\\n */\\ncontract OptimistAllowlist is Semver {\\n /**\\n * @notice Attestation key used by the AllowlistAttestor to manually add addresses to the\\n * allowlist.\\n */\\n bytes32 public constant OPTIMIST_CAN_MINT_ATTESTATION_KEY = bytes32(\\\"optimist.can-mint\\\");\\n\\n /**\\n * @notice Attestation key used by Coinbase to issue attestations for Quest participants.\\n */\\n bytes32 public constant COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY =\\n bytes32(\\\"coinbase.quest-eligible\\\");\\n\\n /**\\n * @notice Address of the AttestationStation contract.\\n */\\n AttestationStation public immutable ATTESTATION_STATION;\\n\\n /**\\n * @notice Attestor that issues 'optimist.can-mint' attestations.\\n */\\n address public immutable ALLOWLIST_ATTESTOR;\\n\\n /**\\n * @notice Attestor that issues 'coinbase.quest-eligible' attestations.\\n */\\n address public immutable COINBASE_QUEST_ATTESTOR;\\n\\n /**\\n * @notice Address of OptimistInviter contract that issues 'optimist.can-mint-from-invite'\\n * attestations.\\n */\\n address public immutable OPTIMIST_INVITER;\\n\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _attestationStation Address of the AttestationStation contract.\\n * @param _allowlistAttestor Address of the allowlist attestor.\\n * @param _coinbaseQuestAttestor Address of the Coinbase Quest attestor.\\n * @param _optimistInviter Address of the OptimistInviter contract.\\n */\\n constructor(\\n AttestationStation _attestationStation,\\n address _allowlistAttestor,\\n address _coinbaseQuestAttestor,\\n address _optimistInviter\\n ) Semver(1, 0, 0) {\\n ATTESTATION_STATION = _attestationStation;\\n ALLOWLIST_ATTESTOR = _allowlistAttestor;\\n COINBASE_QUEST_ATTESTOR = _coinbaseQuestAttestor;\\n OPTIMIST_INVITER = _optimistInviter;\\n }\\n\\n /**\\n * @notice Checks whether a given address is allowed to mint the Optimist NFT yet. Since the\\n * Optimist NFT will also be used as part of the Citizens House, mints are currently\\n * restricted. Eventually anyone will be able to mint.\\n *\\n * Currently, address is allowed to mint if it satisfies any of the following:\\n * 1) Has a valid 'optimist.can-mint' attestation from the allowlist attestor.\\n * 2) Has a valid 'coinbase.quest-eligible' attestation from Coinbase Quest attestor\\n * 3) Has a valid 'optimist.can-mint-from-invite' attestation from the OptimistInviter\\n * contract.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address is allowed to mint yet.\\n */\\n function isAllowedToMint(address _claimer) public view returns (bool) {\\n return\\n _hasAttestationFromAllowlistAttestor(_claimer) ||\\n _hasAttestationFromCoinbaseQuestAttestor(_claimer) ||\\n _hasAttestationFromOptimistInviter(_claimer);\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid 'optimist.can-mint' attestation from the\\n * allowlist attestor.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address has a valid attestation.\\n */\\n function _hasAttestationFromAllowlistAttestor(address _claimer) internal view returns (bool) {\\n // Expected attestation value is bytes32(\\\"true\\\")\\n return\\n _hasValidAttestation(ALLOWLIST_ATTESTOR, _claimer, OPTIMIST_CAN_MINT_ATTESTATION_KEY);\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid attestation from the Coinbase attestor.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address has a valid attestation.\\n */\\n function _hasAttestationFromCoinbaseQuestAttestor(address _claimer)\\n internal\\n view\\n returns (bool)\\n {\\n // Expected attestation value is bytes32(\\\"true\\\")\\n return\\n _hasValidAttestation(\\n COINBASE_QUEST_ATTESTOR,\\n _claimer,\\n COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY\\n );\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid attestation from the OptimistInviter contract.\\n *\\n * @param _claimer Address to check.\\n *\\n * @return Whether or not the address has a valid attestation.\\n */\\n function _hasAttestationFromOptimistInviter(address _claimer) internal view returns (bool) {\\n // Expected attestation value is the inviter's address\\n return\\n _hasValidAttestation(\\n OPTIMIST_INVITER,\\n _claimer,\\n OptimistConstants.OPTIMIST_CAN_MINT_FROM_INVITE_ATTESTATION_KEY\\n );\\n }\\n\\n /**\\n * @notice Checks whether an address has a valid truthy attestation.\\n * Any attestation val other than bytes32(\\\"\\\") is considered truthy.\\n *\\n * @param _creator Address that made the attestation.\\n * @param _about Address attestation is about.\\n * @param _key Key of the attestation.\\n *\\n * @return Whether or not the address has a valid truthy attestation.\\n */\\n function _hasValidAttestation(\\n address _creator,\\n address _about,\\n bytes32 _key\\n ) internal view returns (bool) {\\n return ATTESTATION_STATION.attestations(_creator, _about, _key).length > 0;\\n }\\n}\\n\",\"keccak256\":\"0xd36a677571450d2d9be832beb80e5c37481fcdfc355e6a9b929ac9c8d4966ca0\",\"license\":\"MIT\"},\"contracts/universal/op-nft/libraries/OptimistConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title OptimistConstants\\n * @notice Library for storing Optimist related constants that are shared in multiple contracts.\\n */\\n\\nlibrary OptimistConstants {\\n /**\\n * @notice Attestation key issued by OptimistInviter allowing the attested account to mint.\\n */\\n bytes32 internal constant OPTIMIST_CAN_MINT_FROM_INVITE_ATTESTATION_KEY =\\n bytes32(\\\"optimist.can-mint-from-invite\\\");\\n}\\n\",\"keccak256\":\"0x6eebe1db87f8a5de79bf8af9120e5b0cc6a9b51d8d86e6461cdb6bc52a1dde21\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x61016060405234801561001157600080fd5b50604051610a9d380380610a9d8339810160408190526100309161007c565b6001608052600060a081905260c0526001600160a01b0393841660e0529183166101005282166101205216610140526100db565b6001600160a01b038116811461007957600080fd5b50565b6000806000806080858703121561009257600080fd5b845161009d81610064565b60208601519094506100ae81610064565b60408601519093506100bf81610064565b60608601519092506100d081610064565b939692955090935050565b60805160a05160c05160e05161010051610120516101405161094d6101506000396000818161011b015261035a0152600081816092015261030d01526000818161019e01526102c001526000818161017701526105360152600061026f015260006102460152600061021d015261094d6000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063819f7e841161005b578063819f7e841461013d578063db083d7114610172578063db3c316314610199578063e7bd804e146101c057600080fd5b80633ac52df71461008d5780634813d8a6146100de57806354fd4d50146101015780635e4f489a14610116575b600080fd5b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f16100ec3660046105cd565b6101e7565b60405190151581526020016100d5565b610109610216565b6040516100d5919061063a565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6101647f636f696e626173652e71756573742d656c696769626c6500000000000000000081565b6040519081526020016100d5565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6101647f6f7074696d6973742e63616e2d6d696e7400000000000000000000000000000081565b60006101f2826102b9565b80610201575061020182610306565b80610210575061021082610353565b92915050565b60606102417f00000000000000000000000000000000000000000000000000000000000000006103a0565b61026a7f00000000000000000000000000000000000000000000000000000000000000006103a0565b6102937f00000000000000000000000000000000000000000000000000000000000000006103a0565b6040516020016102a59392919061068b565b604051602081830303815290604052905090565b60006102107f0000000000000000000000000000000000000000000000000000000000000000837f6f7074696d6973742e63616e2d6d696e740000000000000000000000000000006104dd565b60006102107f0000000000000000000000000000000000000000000000000000000000000000837f636f696e626173652e71756573742d656c696769626c650000000000000000006104dd565b60006102107f0000000000000000000000000000000000000000000000000000000000000000837f6f7074696d6973742e63616e2d6d696e742d66726f6d2d696e766974650000006104dd565b6060816000036103e357505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561040d57806103f781610730565b91506104069050600a83610797565b91506103e7565b60008167ffffffffffffffff811115610428576104286107ab565b6040519080825280601f01601f191660200182016040528015610452576020820181803683370190505b5090505b84156104d5576104676001836107da565b9150610474600a866107f1565b61047f906030610805565b60f81b8183815181106104945761049461081d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506104ce600a86610797565b9450610456565b949350505050565b6040517f29b42cb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283811660248301526044820183905260009182917f000000000000000000000000000000000000000000000000000000000000000016906329b42cb590606401600060405180830381865afa15801561057d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105c3919081019061084c565b5111949350505050565b6000602082840312156105df57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461060357600080fd5b9392505050565b60005b8381101561062557818101518382015260200161060d565b83811115610634576000848401525b50505050565b602081526000825180602084015261065981604085016020870161060a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000845161069d81846020890161060a565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516106d9816001850160208a0161060a565b600192019182015283516106f481600284016020880161060a565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361076157610761610701565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826107a6576107a6610768565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107ec576107ec610701565b500390565b60008261080057610800610768565b500690565b6000821982111561081857610818610701565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561085e57600080fd5b815167ffffffffffffffff8082111561087657600080fd5b818401915084601f83011261088a57600080fd5b81518181111561089c5761089c6107ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e2576108e26107ab565b816040528281528760208487010111156108fb57600080fd5b61090c83602083016020880161060a565b97965050505050505056fea2646970667358221220f7c9eee125b4662acd39871c7f71fd0d6635d58d3d0d2d059a8c8bb16ba6d74564736f6c634300080f0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063819f7e841161005b578063819f7e841461013d578063db083d7114610172578063db3c316314610199578063e7bd804e146101c057600080fd5b80633ac52df71461008d5780634813d8a6146100de57806354fd4d50146101015780635e4f489a14610116575b600080fd5b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f16100ec3660046105cd565b6101e7565b60405190151581526020016100d5565b610109610216565b6040516100d5919061063a565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6101647f636f696e626173652e71756573742d656c696769626c6500000000000000000081565b6040519081526020016100d5565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6100b47f000000000000000000000000000000000000000000000000000000000000000081565b6101647f6f7074696d6973742e63616e2d6d696e7400000000000000000000000000000081565b60006101f2826102b9565b80610201575061020182610306565b80610210575061021082610353565b92915050565b60606102417f00000000000000000000000000000000000000000000000000000000000000006103a0565b61026a7f00000000000000000000000000000000000000000000000000000000000000006103a0565b6102937f00000000000000000000000000000000000000000000000000000000000000006103a0565b6040516020016102a59392919061068b565b604051602081830303815290604052905090565b60006102107f0000000000000000000000000000000000000000000000000000000000000000837f6f7074696d6973742e63616e2d6d696e740000000000000000000000000000006104dd565b60006102107f0000000000000000000000000000000000000000000000000000000000000000837f636f696e626173652e71756573742d656c696769626c650000000000000000006104dd565b60006102107f0000000000000000000000000000000000000000000000000000000000000000837f6f7074696d6973742e63616e2d6d696e742d66726f6d2d696e766974650000006104dd565b6060816000036103e357505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561040d57806103f781610730565b91506104069050600a83610797565b91506103e7565b60008167ffffffffffffffff811115610428576104286107ab565b6040519080825280601f01601f191660200182016040528015610452576020820181803683370190505b5090505b84156104d5576104676001836107da565b9150610474600a866107f1565b61047f906030610805565b60f81b8183815181106104945761049461081d565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506104ce600a86610797565b9450610456565b949350505050565b6040517f29b42cb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283811660248301526044820183905260009182917f000000000000000000000000000000000000000000000000000000000000000016906329b42cb590606401600060405180830381865afa15801561057d573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105c3919081019061084c565b5111949350505050565b6000602082840312156105df57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461060357600080fd5b9392505050565b60005b8381101561062557818101518382015260200161060d565b83811115610634576000848401525b50505050565b602081526000825180602084015261065981604085016020870161060a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000845161069d81846020890161060a565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516106d9816001850160208a0161060a565b600192019182015283516106f481600284016020880161060a565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361076157610761610701565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826107a6576107a6610768565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107ec576107ec610701565b500390565b60008261080057610800610768565b500690565b6000821982111561081857610818610701565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561085e57600080fd5b815167ffffffffffffffff8082111561087657600080fd5b818401915084601f83011261088a57600080fd5b81518181111561089c5761089c6107ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e2576108e26107ab565b816040528281528760208487010111156108fb57600080fd5b61090c83602083016020880161060a565b97965050505050505056fea2646970667358221220f7c9eee125b4662acd39871c7f71fd0d6635d58d3d0d2d059a8c8bb16ba6d74564736f6c634300080f0033", - "devdoc": { - "kind": "dev", - "methods": { - "constructor": { - "custom:semver": "1.0.0", - "params": { - "_allowlistAttestor": "Address of the allowlist attestor.", - "_attestationStation": "Address of the AttestationStation contract.", - "_coinbaseQuestAttestor": "Address of the Coinbase Quest attestor.", - "_optimistInviter": "Address of the OptimistInviter contract." - } - }, - "isAllowedToMint(address)": { - "params": { - "_claimer": "Address to check." - }, - "returns": { - "_0": "Whether or not the address is allowed to mint yet." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "title": "OptimistAllowlist", - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": { - "ALLOWLIST_ATTESTOR()": { - "notice": "Attestor that issues 'optimist.can-mint' attestations." - }, - "ATTESTATION_STATION()": { - "notice": "Address of the AttestationStation contract." - }, - "COINBASE_QUEST_ATTESTOR()": { - "notice": "Attestor that issues 'coinbase.quest-eligible' attestations." - }, - "COINBASE_QUEST_ELIGIBLE_ATTESTATION_KEY()": { - "notice": "Attestation key used by Coinbase to issue attestations for Quest participants." - }, - "OPTIMIST_CAN_MINT_ATTESTATION_KEY()": { - "notice": "Attestation key used by the AllowlistAttestor to manually add addresses to the allowlist." - }, - "OPTIMIST_INVITER()": { - "notice": "Address of OptimistInviter contract that issues 'optimist.can-mint-from-invite' attestations." - }, - "isAllowedToMint(address)": { - "notice": "Checks whether a given address is allowed to mint the Optimist NFT yet. Since the Optimist NFT will also be used as part of the Citizens House, mints are currently restricted. Eventually anyone will be able to mint. Currently, address is allowed to mint if it satisfies any of the following: 1) Has a valid 'optimist.can-mint' attestation from the allowlist attestor. 2) Has a valid 'coinbase.quest-eligible' attestation from Coinbase Quest attestor 3) Has a valid 'optimist.can-mint-from-invite' attestation from the OptimistInviter contract." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "Source of truth for whether an address is able to mint an Optimist NFT. isAllowedToMint function checks various signals to return boolean value for whether an address is eligible or not.", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-mainnet/OptimistAllowlistProxy.json b/packages/contracts-bedrock/deployments/optimism-mainnet/OptimistAllowlistProxy.json deleted file mode 100644 index d26cc3cb23fa..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/OptimistAllowlistProxy.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "address": "0x482b1945D58f2E9Db0CEbe13c7fcFc6876b41180", - "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": "0x8a5be8c67f602b334fedc18faaa58de68861d619be084d90310f93015c2c0b7c", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "534190", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000400000000000000000000000000000000000000000000", - "blockHash": "0x54e0ce11f60f1f0c01aad2bf677a4550669f7ca408a4ee7c5bddf0b25fe11e85", - "transactionHash": "0x8a5be8c67f602b334fedc18faaa58de68861d619be084d90310f93015c2c0b7c", - "logs": [ - { - "transactionIndex": 0, - "blockNumber": 87031806, - "transactionHash": "0x8a5be8c67f602b334fedc18faaa58de68861d619be084d90310f93015c2c0b7c", - "address": "0x482b1945D58f2E9Db0CEbe13c7fcFc6876b41180", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58", - "logIndex": 0, - "blockHash": "0x54e0ce11f60f1f0c01aad2bf677a4550669f7ca408a4ee7c5bddf0b25fe11e85" - } - ], - "blockNumber": 87031806, - "cumulativeGasUsed": "534190", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "d7155764d4bdb814f10e1bb45296292b", - "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) public virtual 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 public\\n payable\\n virtual\\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) public virtual 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() public virtual proxyCallIfNotAdmin returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function implementation() public virtual 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\":\"0x64d67f1936d97c87a2e42317eb162744ad5cefdc9bc8b1138ee4afe2886eb885\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161094138038061094183398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206109218339815191525490565b600080516020610921833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610830806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea26469706673582212200496188e743eb5556ea8662e234845601d39477882517acc1cf9061fcc51284c64736f6c634300080f0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea26469706673582212200496188e743eb5556ea8662e234845601d39477882517acc1cf9061fcc51284c64736f6c634300080f0033", - "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-bedrock/deployments/optimism-mainnet/OptimistInviter.json b/packages/contracts-bedrock/deployments/optimism-mainnet/OptimistInviter.json deleted file mode 100644 index b7059136a651..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/OptimistInviter.json +++ /dev/null @@ -1,543 +0,0 @@ -{ - "address": "0xD1A342EB71F5e032770dc0Fb11dE3F75a23C7ca9", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_inviteGranter", - "type": "address" - }, - { - "internalType": "contract AttestationStation", - "name": "_attestationStation", - "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": "address", - "name": "issuer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "claimer", - "type": "address" - } - ], - "name": "InviteClaimed", - "type": "event" - }, - { - "inputs": [], - "name": "ATTESTATION_STATION", - "outputs": [ - { - "internalType": "contract AttestationStation", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "CAN_INVITE_ATTESTATION_KEY", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "CLAIMABLE_INVITE_TYPEHASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "EIP712_VERSION", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INVITE_GRANTER", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MIN_COMMITMENT_PERIOD", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_claimer", - "type": "address" - }, - { - "components": [ - { - "internalType": "address", - "name": "issuer", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "nonce", - "type": "bytes32" - } - ], - "internalType": "struct OptimistInviter.ClaimableInvite", - "name": "_claimableInvite", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "_signature", - "type": "bytes" - } - ], - "name": "claimInvite", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_commitment", - "type": "bytes32" - } - ], - "name": "commitInvite", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "commitmentTimestamps", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "inviteCounts", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "_accounts", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "_inviteCount", - "type": "uint256" - } - ], - "name": "setInviteCounts", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "usedNonces", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0xe8b8a4c7cb6f074690f00e79e0a13d16f3ed16e4afb56d02afe74825a86f0d00", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "1650064", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xbc41ee7fc08d560ed6791a304433afbb424415cfa189376192b63eb6a85d8a55", - "transactionHash": "0xe8b8a4c7cb6f074690f00e79e0a13d16f3ed16e4afb56d02afe74825a86f0d00", - "logs": [], - "blockNumber": 87030949, - "cumulativeGasUsed": "1650064", - "status": 1, - "byzantium": true - }, - "args": [ - "0x60c5C9c98bcBd0b0F2fD89B24c16e533BaA8CdA3", - "0xEE36eaaD94d1Cc1d0eccaDb55C38bFfB6Be06C77" - ], - "numDeployments": 1, - "solcInputHash": "d7155764d4bdb814f10e1bb45296292b", - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_inviteGranter\",\"type\":\"address\"},{\"internalType\":\"contract AttestationStation\",\"name\":\"_attestationStation\",\"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\":\"address\",\"name\":\"issuer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"}],\"name\":\"InviteClaimed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ATTESTATION_STATION\",\"outputs\":[{\"internalType\":\"contract AttestationStation\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"CAN_INVITE_ATTESTATION_KEY\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"CLAIMABLE_INVITE_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EIP712_VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INVITE_GRANTER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_COMMITMENT_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_claimer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"issuer\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"nonce\",\"type\":\"bytes32\"}],\"internalType\":\"struct OptimistInviter.ClaimableInvite\",\"name\":\"_claimableInvite\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_signature\",\"type\":\"bytes\"}],\"name\":\"claimInvite\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_commitment\",\"type\":\"bytes32\"}],\"name\":\"commitInvite\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"commitmentTimestamps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"inviteCounts\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256\",\"name\":\"_inviteCount\",\"type\":\"uint256\"}],\"name\":\"setInviteCounts\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"usedNonces\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"custom:upgradeable\":\"@title OptimistInviter\",\"events\":{\"InviteClaimed(address,address)\":{\"params\":{\"claimer\":\"Address that claimed the invite.\",\"issuer\":\"Address that issued the signature.\"}}},\"kind\":\"dev\",\"methods\":{\"claimInvite(address,(address,bytes32),bytes)\":{\"params\":{\"_claimableInvite\":\"ClaimableInvite struct containing the issuer and nonce.\",\"_claimer\":\"Address that will be granted the invite.\",\"_signature\":\"Signature signed over the claimable invite.\"}},\"commitInvite(bytes32)\":{\"params\":{\"_commitment\":\"A hash of the claimer and signature concatenated. keccak256(abi.encode(_claimer, _signature))\"}},\"constructor\":{\"custom:semver\":\"1.0.0\",\"params\":{\"_attestationStation\":\"Address of the AttestationStation contract.\",\"_inviteGranter\":\"Address of the invite granter.\"}},\"initialize(string)\":{\"params\":{\"_name\":\"Contract name.\"}},\"setInviteCounts(address[],uint256)\":{\"params\":{\"_accounts\":\"An array of accounts to update the invite counts of.\",\"_inviteCount\":\"Number of invites to set to.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"version\":1},\"userdoc\":{\"events\":{\"InviteClaimed(address,address)\":{\"notice\":\"Emitted when an invite is claimed.\"}},\"kind\":\"user\",\"methods\":{\"ATTESTATION_STATION()\":{\"notice\":\"Address of the AttestationStation contract.\"},\"CAN_INVITE_ATTESTATION_KEY()\":{\"notice\":\"Attestation key for that signals that an account was allowed to issue invites\"},\"CLAIMABLE_INVITE_TYPEHASH()\":{\"notice\":\"EIP712 typehash for the ClaimableInvite type.\"},\"EIP712_VERSION()\":{\"notice\":\"Version used for the EIP712 domain separator. This version is separated from the contract semver because the EIP712 domain separator is used to sign messages, and changing the domain separator invalidates all existing signatures. We should only bump this version if we make a major change to the signature scheme.\"},\"INVITE_GRANTER()\":{\"notice\":\"Granter who can set accounts' invite counts.\"},\"MIN_COMMITMENT_PERIOD()\":{\"notice\":\"Minimum age of a commitment (in seconds) before it can be revealed using claimInvite. Currently set to 60 seconds. Prevents an attacker from front-running a commitment by taking the signature in the claimInvite call and quickly committing and claiming it before the the claimer's transaction succeeds. With this, frontrunning a commitment requires that an attacker be able to prevent the honest claimer's claimInvite transaction from being included for this long.\"},\"claimInvite(address,(address,bytes32),bytes)\":{\"notice\":\"Allows anyone to reveal a commitment and claim an invite. The hash, keccak256(abi.encode(_claimer, _signature)), should have been already committed using commitInvite. Before issuing the \\\"optimist.can-mint-from-invite\\\" attestation, this function checks that 1) the hash corresponding to the _claimer and the _signature was committed 2) MIN_COMMITMENT_PERIOD has passed since the commitment was made. 3) the _signature is signed correctly by the issuer 4) the _signature hasn't already been used to claim an invite before 5) the _signature issuer has not used up all of their invites This function doesn't require that the _claimer is calling this function.\"},\"commitInvite(bytes32)\":{\"notice\":\"Allows anyone (but likely the claimer) to commit a received signature along with the address to claim to. Before calling this function, the claimer should have received a signature from the issuer off-chain. The claimer then calls this function with the hash of the claimer's address and the received signature. This is necessary to prevent front-running when the invitee is claiming the invite. Without a commit and reveal scheme, anyone who is watching the mempool can take the signature being submitted and front run the transaction to claim the invite to their own address. The same commitment can only be made once, and the function reverts if the commitment has already been made. This prevents griefing where a malicious party can prevent the original claimer from being able to claimInvite.\"},\"commitmentTimestamps(bytes32)\":{\"notice\":\"Maps from hashes to the timestamp when they were committed.\"},\"initialize(string)\":{\"notice\":\"Initializes this contract, setting the EIP712 context. Only update the EIP712_VERSION when there is a change to the signature scheme. After the EIP712 version is changed, any signatures issued off-chain but not claimed yet will no longer be accepted by the claimInvite function. Please make sure to notify the issuers that they must re-issue their invite signatures.\"},\"inviteCounts(address)\":{\"notice\":\"Maps from addresses to number of invites they have.\"},\"setInviteCounts(address[],uint256)\":{\"notice\":\"Allows invite granter to set the number of invites an address has.\"},\"usedNonces(address,bytes32)\":{\"notice\":\"Maps from addresses to nonces to whether or not they have been used.\"},\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"notice\":\"OptimistInviter issues \\\"optimist.can-invite\\\" and \\\"optimist.can-mint-from-invite\\\" attestations. Accounts that have invites can issue signatures that allow other accounts to claim an invite. The invitee uses a claim and reveal flow to claim the invite to an address of their choosing. Parties involved: 1) INVITE_GRANTER: trusted account that can allow accounts to issue invites 2) issuer: account that is allowed to issue invites 3) claimer: account that receives the invites Flow: 1) INVITE_GRANTER calls _setInviteCount to allow an issuer to issue a certain number of invites, and also creates a \\\"optimist.can-invite\\\" attestation for the issuer 2) Off-chain, the issuer signs (EIP-712) a ClaimableInvite to produce a signature 3) Off-chain, invite issuer sends the plaintext ClaimableInvite and the signature to the recipient 4) claimer chooses an address they want to receive the invite on 5) claimer commits the hash of the address they want to receive the invite on and the received signature keccak256(abi.encode(addressToReceiveTo, receivedSignature)) using the commitInvite function 6) claimer waits for the MIN_COMMITMENT_PERIOD to pass. 7) claimer reveals the plaintext ClaimableInvite and the signature using the claimInvite function, receiving the \\\"optimist.can-mint-from-invite\\\" attestation\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/universal/op-nft/OptimistInviter.sol\":\"OptimistInviter\"},\"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.0;\\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 uint256 private immutable MAJOR_VERSION;\\n\\n /**\\n * @notice Contract version number (minor).\\n */\\n uint256 private immutable MINOR_VERSION;\\n\\n /**\\n * @notice Contract version number (patch).\\n */\\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\":\"0x400059d3edb9efc9c23e6fbc18de6710f9235a4ffba4ab23bdb9f825273f093b\",\"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/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/StringsUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary StringsUpgradeable {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\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 /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xea5339a7fff0ed42b45be56a88efdd0b2ddde9fa480dc99fef9a6a4c5b776863\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../StringsUpgradeable.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 ECDSAUpgradeable {\\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 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 /// @solidity memory-safe-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 {\\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\\\", StringsUpgradeable.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\":\"0xbf5daf926894541a40a64b43c3746aa1940c5a1b3b8d14a06465eea72a9b90cc\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.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 \\\"./ECDSAUpgradeable.sol\\\";\\nimport \\\"../../proxy/utils/Initializable.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 *\\n * @custom:storage-size 52\\n */\\nabstract contract EIP712Upgradeable is Initializable {\\n /* solhint-disable var-name-mixedcase */\\n bytes32 private _HASHED_NAME;\\n bytes32 private _HASHED_VERSION;\\n bytes32 private constant _TYPE_HASH = keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\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 function __EIP712_init(string memory name, string memory version) internal onlyInitializing {\\n __EIP712_init_unchained(name, version);\\n }\\n\\n function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {\\n bytes32 hashedName = keccak256(bytes(name));\\n bytes32 hashedVersion = keccak256(bytes(version));\\n _HASHED_NAME = hashedName;\\n _HASHED_VERSION = hashedVersion;\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\\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 ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n\\n /**\\n * @dev The hash of the name parameter for the EIP712 domain.\\n *\\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\\n * are a concern.\\n */\\n function _EIP712NameHash() internal virtual view returns (bytes32) {\\n return _HASHED_NAME;\\n }\\n\\n /**\\n * @dev The hash of the version parameter for the EIP712 domain.\\n *\\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\\n * are a concern.\\n */\\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\\n return _HASHED_VERSION;\\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\":\"0xaf5a96100f421d61693605349511e43221d3c2e47d4b3efa87af2b936e2567fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/interfaces/IERC1271.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC1271 standard signature validation method for\\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC1271 {\\n /**\\n * @dev Should return whether the signature provided is valid for the provided data\\n * @param hash Hash of the data to be signed\\n * @param signature Signature byte array associated with _data\\n */\\n function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);\\n}\\n\",\"keccak256\":\"0x0705a4b1b86d7b0bd8432118f226ba139c44b9dcaba0a6eafba2dd7d0639c544\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.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 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 /// @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\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (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 uint8 private constant _ADDRESS_LENGTH = 20;\\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 /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.3) (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 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 /// @solidity memory-safe-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 {\\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\":\"0xdb7f5c28fc61cda0bd8ab60ce288e206b791643bcd3ba464a70cbec18895a2f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.1) (utils/cryptography/SignatureChecker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\nimport \\\"../Address.sol\\\";\\nimport \\\"../../interfaces/IERC1271.sol\\\";\\n\\n/**\\n * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA\\n * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like\\n * Argent and Gnosis Safe.\\n *\\n * _Available since v4.1._\\n */\\nlibrary SignatureChecker {\\n /**\\n * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the\\n * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.\\n *\\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\\n */\\n function isValidSignatureNow(\\n address signer,\\n bytes32 hash,\\n bytes memory signature\\n ) internal view returns (bool) {\\n (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);\\n if (error == ECDSA.RecoverError.NoError && recovered == signer) {\\n return true;\\n }\\n\\n (bool success, bytes memory result) = signer.staticcall(\\n abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)\\n );\\n return (success &&\\n result.length == 32 &&\\n abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));\\n }\\n}\\n\",\"keccak256\":\"0xbb5c92a62f2a917ec08667ebc024d5f4172ae3594cd5f4eaa997485ed0440d81\",\"license\":\"MIT\"},\"contracts/universal/op-nft/AttestationStation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\n\\n/**\\n * @title AttestationStation\\n * @author Optimism Collective\\n * @author Gitcoin\\n * @notice Where attestations live.\\n */\\ncontract AttestationStation is Semver {\\n /**\\n * @notice Struct representing data that is being attested.\\n *\\n * @custom:field about Address for which the attestation is about.\\n * @custom:field key A bytes32 key for the attestation.\\n * @custom:field val The attestation as arbitrary bytes.\\n */\\n struct AttestationData {\\n address about;\\n bytes32 key;\\n bytes val;\\n }\\n\\n /**\\n * @notice Maps addresses to attestations. Creator => About => Key => Value.\\n */\\n mapping(address => mapping(address => mapping(bytes32 => bytes))) public attestations;\\n\\n /**\\n * @notice Emitted when Attestation is created.\\n *\\n * @param creator Address that made the attestation.\\n * @param about Address attestation is about.\\n * @param key Key of the attestation.\\n * @param val Value of the attestation.\\n */\\n event AttestationCreated(\\n address indexed creator,\\n address indexed about,\\n bytes32 indexed key,\\n bytes val\\n );\\n\\n /**\\n * @custom:semver 1.1.0\\n */\\n constructor() Semver(1, 1, 0) {}\\n\\n /**\\n * @notice Allows anyone to create an attestation.\\n *\\n * @param _about Address that the attestation is about.\\n * @param _key A key used to namespace the attestation.\\n * @param _val An arbitrary value stored as part of the attestation.\\n */\\n function attest(\\n address _about,\\n bytes32 _key,\\n bytes memory _val\\n ) public {\\n attestations[msg.sender][_about][_key] = _val;\\n\\n emit AttestationCreated(msg.sender, _about, _key, _val);\\n }\\n\\n /**\\n * @notice Allows anyone to create attestations.\\n *\\n * @param _attestations An array of AttestationData structs.\\n */\\n function attest(AttestationData[] calldata _attestations) external {\\n uint256 length = _attestations.length;\\n for (uint256 i = 0; i < length; ) {\\n AttestationData memory attestation = _attestations[i];\\n\\n attest(attestation.about, attestation.key, attestation.val);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x421923e04df145353db12cd0352ccf516d9c29ab64b138733b4f7a6a450ce2be\",\"license\":\"MIT\"},\"contracts/universal/op-nft/OptimistInviter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\nimport { OptimistConstants } from \\\"./libraries/OptimistConstants.sol\\\";\\nimport { Semver } from \\\"@eth-optimism/contracts-bedrock/contracts/universal/Semver.sol\\\";\\nimport { AttestationStation } from \\\"./AttestationStation.sol\\\";\\nimport { SignatureChecker } from \\\"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\\\";\\nimport {\\n EIP712Upgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol\\\";\\n\\n/**\\n * @custom:upgradeable\\n * @title OptimistInviter\\n * @notice OptimistInviter issues \\\"optimist.can-invite\\\" and \\\"optimist.can-mint-from-invite\\\"\\n * attestations. Accounts that have invites can issue signatures that allow other\\n * accounts to claim an invite. The invitee uses a claim and reveal flow to claim the\\n * invite to an address of their choosing.\\n *\\n * Parties involved:\\n * 1) INVITE_GRANTER: trusted account that can allow accounts to issue invites\\n * 2) issuer: account that is allowed to issue invites\\n * 3) claimer: account that receives the invites\\n *\\n * Flow:\\n * 1) INVITE_GRANTER calls _setInviteCount to allow an issuer to issue a certain number\\n * of invites, and also creates a \\\"optimist.can-invite\\\" attestation for the issuer\\n * 2) Off-chain, the issuer signs (EIP-712) a ClaimableInvite to produce a signature\\n * 3) Off-chain, invite issuer sends the plaintext ClaimableInvite and the signature\\n * to the recipient\\n * 4) claimer chooses an address they want to receive the invite on\\n * 5) claimer commits the hash of the address they want to receive the invite on and the\\n * received signature keccak256(abi.encode(addressToReceiveTo, receivedSignature))\\n * using the commitInvite function\\n * 6) claimer waits for the MIN_COMMITMENT_PERIOD to pass.\\n * 7) claimer reveals the plaintext ClaimableInvite and the signature using the\\n * claimInvite function, receiving the \\\"optimist.can-mint-from-invite\\\" attestation\\n */\\ncontract OptimistInviter is Semver, EIP712Upgradeable {\\n /**\\n * @notice Emitted when an invite is claimed.\\n *\\n * @param issuer Address that issued the signature.\\n * @param claimer Address that claimed the invite.\\n */\\n event InviteClaimed(address indexed issuer, address indexed claimer);\\n\\n /**\\n * @notice Version used for the EIP712 domain separator. This version is separated from the\\n * contract semver because the EIP712 domain separator is used to sign messages, and\\n * changing the domain separator invalidates all existing signatures. We should only\\n * bump this version if we make a major change to the signature scheme.\\n */\\n string public constant EIP712_VERSION = \\\"1.0.0\\\";\\n\\n /**\\n * @notice EIP712 typehash for the ClaimableInvite type.\\n */\\n bytes32 public constant CLAIMABLE_INVITE_TYPEHASH =\\n keccak256(\\\"ClaimableInvite(address issuer,bytes32 nonce)\\\");\\n\\n /**\\n * @notice Attestation key for that signals that an account was allowed to issue invites\\n */\\n bytes32 public constant CAN_INVITE_ATTESTATION_KEY = bytes32(\\\"optimist.can-invite\\\");\\n\\n /**\\n * @notice Granter who can set accounts' invite counts.\\n */\\n address public immutable INVITE_GRANTER;\\n\\n /**\\n * @notice Address of the AttestationStation contract.\\n */\\n AttestationStation public immutable ATTESTATION_STATION;\\n\\n /**\\n * @notice Minimum age of a commitment (in seconds) before it can be revealed using claimInvite.\\n * Currently set to 60 seconds.\\n *\\n * Prevents an attacker from front-running a commitment by taking the signature in the\\n * claimInvite call and quickly committing and claiming it before the the claimer's\\n * transaction succeeds. With this, frontrunning a commitment requires that an attacker\\n * be able to prevent the honest claimer's claimInvite transaction from being included\\n * for this long.\\n */\\n uint256 public constant MIN_COMMITMENT_PERIOD = 60;\\n\\n /**\\n * @notice Struct that represents a claimable invite that will be signed by the issuer.\\n *\\n * @custom:field issuer Address that issued the signature. Reason this is explicitly included,\\n * and not implicitly assumed to be the recovered address from the\\n * signature is that the issuer may be using a ERC-1271 compatible\\n * contract wallet, where the recovered address is not the same as the\\n * issuer, or the signature is not an ECDSA signature at all.\\n * @custom:field nonce Pseudorandom nonce to prevent replay attacks.\\n */\\n struct ClaimableInvite {\\n address issuer;\\n bytes32 nonce;\\n }\\n\\n /**\\n * @notice Maps from hashes to the timestamp when they were committed.\\n */\\n mapping(bytes32 => uint256) public commitmentTimestamps;\\n\\n /**\\n * @notice Maps from addresses to nonces to whether or not they have been used.\\n */\\n mapping(address => mapping(bytes32 => bool)) public usedNonces;\\n\\n /**\\n * @notice Maps from addresses to number of invites they have.\\n */\\n mapping(address => uint256) public inviteCounts;\\n\\n /**\\n * @custom:semver 1.0.0\\n *\\n * @param _inviteGranter Address of the invite granter.\\n * @param _attestationStation Address of the AttestationStation contract.\\n */\\n constructor(address _inviteGranter, AttestationStation _attestationStation) Semver(1, 0, 0) {\\n INVITE_GRANTER = _inviteGranter;\\n ATTESTATION_STATION = _attestationStation;\\n }\\n\\n /**\\n * @notice Initializes this contract, setting the EIP712 context.\\n *\\n * Only update the EIP712_VERSION when there is a change to the signature scheme.\\n * After the EIP712 version is changed, any signatures issued off-chain but not\\n * claimed yet will no longer be accepted by the claimInvite function. Please make\\n * sure to notify the issuers that they must re-issue their invite signatures.\\n *\\n * @param _name Contract name.\\n */\\n function initialize(string memory _name) public initializer {\\n __EIP712_init(_name, EIP712_VERSION);\\n }\\n\\n /**\\n * @notice Allows invite granter to set the number of invites an address has.\\n *\\n * @param _accounts An array of accounts to update the invite counts of.\\n * @param _inviteCount Number of invites to set to.\\n */\\n function setInviteCounts(address[] calldata _accounts, uint256 _inviteCount) public {\\n // Only invite granter can grant invites\\n require(\\n msg.sender == INVITE_GRANTER,\\n \\\"OptimistInviter: only invite granter can grant invites\\\"\\n );\\n\\n uint256 length = _accounts.length;\\n\\n AttestationStation.AttestationData[]\\n memory attestations = new AttestationStation.AttestationData[](length);\\n\\n for (uint256 i; i < length; ) {\\n // Set invite count for account to _inviteCount\\n inviteCounts[_accounts[i]] = _inviteCount;\\n\\n // Create an attestation for posterity that the account is allowed to create invites\\n attestations[i] = AttestationStation.AttestationData({\\n about: _accounts[i],\\n key: CAN_INVITE_ATTESTATION_KEY,\\n val: bytes(\\\"true\\\")\\n });\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n ATTESTATION_STATION.attest(attestations);\\n }\\n\\n /**\\n * @notice Allows anyone (but likely the claimer) to commit a received signature along with the\\n * address to claim to.\\n *\\n * Before calling this function, the claimer should have received a signature from the\\n * issuer off-chain. The claimer then calls this function with the hash of the\\n * claimer's address and the received signature. This is necessary to prevent\\n * front-running when the invitee is claiming the invite. Without a commit and reveal\\n * scheme, anyone who is watching the mempool can take the signature being submitted\\n * and front run the transaction to claim the invite to their own address.\\n *\\n * The same commitment can only be made once, and the function reverts if the\\n * commitment has already been made. This prevents griefing where a malicious party can\\n * prevent the original claimer from being able to claimInvite.\\n *\\n *\\n * @param _commitment A hash of the claimer and signature concatenated.\\n * keccak256(abi.encode(_claimer, _signature))\\n */\\n function commitInvite(bytes32 _commitment) public {\\n // Check that the commitment hasn't already been made. This prevents griefing where\\n // a malicious party continuously re-submits the same commitment, preventing the original\\n // claimer from claiming their invite by resetting the minimum commitment period.\\n require(commitmentTimestamps[_commitment] == 0, \\\"OptimistInviter: commitment already made\\\");\\n\\n commitmentTimestamps[_commitment] = block.timestamp;\\n }\\n\\n /**\\n * @notice Allows anyone to reveal a commitment and claim an invite.\\n *\\n * The hash, keccak256(abi.encode(_claimer, _signature)), should have been already\\n * committed using commitInvite. Before issuing the \\\"optimist.can-mint-from-invite\\\"\\n * attestation, this function checks that\\n * 1) the hash corresponding to the _claimer and the _signature was committed\\n * 2) MIN_COMMITMENT_PERIOD has passed since the commitment was made.\\n * 3) the _signature is signed correctly by the issuer\\n * 4) the _signature hasn't already been used to claim an invite before\\n * 5) the _signature issuer has not used up all of their invites\\n * This function doesn't require that the _claimer is calling this function.\\n *\\n * @param _claimer Address that will be granted the invite.\\n * @param _claimableInvite ClaimableInvite struct containing the issuer and nonce.\\n * @param _signature Signature signed over the claimable invite.\\n */\\n function claimInvite(\\n address _claimer,\\n ClaimableInvite calldata _claimableInvite,\\n bytes memory _signature\\n ) public {\\n uint256 commitmentTimestamp = commitmentTimestamps[\\n keccak256(abi.encode(_claimer, _signature))\\n ];\\n\\n // Make sure the claimer and signature have been committed.\\n require(\\n commitmentTimestamp > 0,\\n \\\"OptimistInviter: claimer and signature have not been committed yet\\\"\\n );\\n\\n // Check that MIN_COMMITMENT_PERIOD has passed since the commitment was made.\\n require(\\n commitmentTimestamp + MIN_COMMITMENT_PERIOD <= block.timestamp,\\n \\\"OptimistInviter: minimum commitment period has not elapsed yet\\\"\\n );\\n\\n // Generate a EIP712 typed data hash to compare against the signature.\\n bytes32 digest = _hashTypedDataV4(\\n keccak256(\\n abi.encode(\\n CLAIMABLE_INVITE_TYPEHASH,\\n _claimableInvite.issuer,\\n _claimableInvite.nonce\\n )\\n )\\n );\\n\\n // Uses SignatureChecker, which supports both regular ECDSA signatures from EOAs as well as\\n // ERC-1271 signatures from contract wallets or multi-sigs. This means that if the issuer\\n // wants to revoke a signature, they can use a smart contract wallet to issue the signature,\\n // then invalidate the signature after issuing it.\\n require(\\n SignatureChecker.isValidSignatureNow(_claimableInvite.issuer, digest, _signature),\\n \\\"OptimistInviter: invalid signature\\\"\\n );\\n\\n // The issuer's signature commits to a nonce to prevent replay attacks.\\n // This checks that the nonce has not been used for this issuer before. The nonces are\\n // scoped to the issuer address, so the same nonce can be used by different issuers without\\n // clashing.\\n require(\\n usedNonces[_claimableInvite.issuer][_claimableInvite.nonce] == false,\\n \\\"OptimistInviter: nonce has already been used\\\"\\n );\\n\\n // Set the nonce as used for the issuer so that it cannot be replayed.\\n usedNonces[_claimableInvite.issuer][_claimableInvite.nonce] = true;\\n\\n // Failing this check means that the issuer has used up all of their existing invites.\\n require(\\n inviteCounts[_claimableInvite.issuer] > 0,\\n \\\"OptimistInviter: issuer has no invites\\\"\\n );\\n\\n // Reduce the issuer's invite count by 1. Can be unchecked because we check above that\\n // count is > 0.\\n unchecked {\\n --inviteCounts[_claimableInvite.issuer];\\n }\\n\\n // Create the attestation that the claimer can mint from the issuer's invite.\\n // The invite issuer is included in the data of the attestation.\\n ATTESTATION_STATION.attest(\\n _claimer,\\n OptimistConstants.OPTIMIST_CAN_MINT_FROM_INVITE_ATTESTATION_KEY,\\n abi.encode(_claimableInvite.issuer)\\n );\\n\\n emit InviteClaimed(_claimableInvite.issuer, _claimer);\\n }\\n}\\n\",\"keccak256\":\"0xd7b006570c7e0c66ed0a8001c7e57848062913639e65f5bb6f4d8120e2a00c32\",\"license\":\"MIT\"},\"contracts/universal/op-nft/libraries/OptimistConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.15;\\n\\n/**\\n * @title OptimistConstants\\n * @notice Library for storing Optimist related constants that are shared in multiple contracts.\\n */\\n\\nlibrary OptimistConstants {\\n /**\\n * @notice Attestation key issued by OptimistInviter allowing the attested account to mint.\\n */\\n bytes32 internal constant OPTIMIST_CAN_MINT_FROM_INVITE_ATTESTATION_KEY =\\n bytes32(\\\"optimist.can-mint-from-invite\\\");\\n}\\n\",\"keccak256\":\"0x6eebe1db87f8a5de79bf8af9120e5b0cc6a9b51d8d86e6461cdb6bc52a1dde21\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x6101206040523480156200001257600080fd5b5060405162001e0938038062001e09833981016040819052620000359162000076565b6001608052600060a081905260c0526001600160a01b0391821660e0521661010052620000b5565b6001600160a01b03811681146200007357600080fd5b50565b600080604083850312156200008a57600080fd5b825162000097816200005d565b6020840151909250620000aa816200005d565b809150509250929050565b60805160a05160c05160e05161010051611cfb6200010e60003960008181610257015281816106510152610c0201526000818160f401526103b401526000610da101526000610d7801526000610d4f0152611cfb6000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063916db22f1161008c578063db083d7111610066578063db083d7114610252578063de2dd22114610279578063eccec5a814610299578063f62d1888146102d557600080fd5b8063916db22f146101e4578063b4245d731461020b578063c4fc453d1461022b57600080fd5b806350b414e6116100c857806350b414e61461016857806350eedbc21461017e57806354fd4d50146101915780635fda04c7146101a657600080fd5b806314b47241146100ef578063187e3cd11461014057806325b27a3d14610155575b600080fd5b6101167f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61015361014e36600461165f565b6102e8565b005b610153610163366004611678565b61039c565b610170603c81565b604051908152602001610137565b61015361018c3660046117df565b6106bf565b610199610d48565b60405161013791906118f5565b6101d46101b4366004611908565b603660209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610137565b6101707f6f7074696d6973742e63616e2d696e766974650000000000000000000000000081565b61017061021936600461165f565b60356020526000908152604090205481565b6101707f6529fd129351e725d7bcbc468b0b0b4675477e56b58514e69ab7e66ddfd20fce81565b6101167f000000000000000000000000000000000000000000000000000000000000000081565b610170610287366004611932565b60376020526000908152604090205481565b6101996040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6101536102e336600461194d565b610deb565b60008181526035602052604090205415610389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4f7074696d697374496e76697465723a20636f6d6d69746d656e7420616c726560448201527f616479206d61646500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000908152603560205260409020429055565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610461576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4f7074696d697374496e76697465723a206f6e6c7920696e766974652067726160448201527f6e7465722063616e206772616e7420696e7669746573000000000000000000006064820152608401610380565b8160008167ffffffffffffffff81111561047d5761047d61171c565b6040519080825280602002602001820160405280156104ca57816020015b6040805160608082018352600080835260208301529181019190915281526020019060019003908161049b5790505b50905060005b828110156106135783603760008888858181106104ef576104ef611996565b90506020020160208101906105049190611932565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550604051806060016040528087878481811061055f5761055f611996565b90506020020160208101906105749190611932565b73ffffffffffffffffffffffffffffffffffffffff1681526020017f6f7074696d6973742e63616e2d696e766974650000000000000000000000000081526020016040518060400160405280600481526020017f747275650000000000000000000000000000000000000000000000000000000081525081525082828151811061060057610600611996565b60209081029190910101526001016104d0565b506040517f5eb5ea1000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690635eb5ea10906106869084906004016119c5565b600060405180830381600087803b1580156106a057600080fd5b505af11580156106b4573d6000803e3d6000fd5b505050505050505050565b60006035600085846040516020016106d8929190611a78565b604051602081830303815290604052805190602001208152602001908152602001600020549050600081116107b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f4f7074696d697374496e76697465723a20636c61696d657220616e642073696760448201527f6e61747572652068617665206e6f74206265656e20636f6d6d6974746564207960648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a401610380565b426107c1603c83611ad6565b111561084f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4f7074696d697374496e76697465723a206d696e696d756d20636f6d6d69746d60448201527f656e7420706572696f6420686173206e6f7420656c61707365642079657400006064820152608401610380565b60006108d27f6529fd129351e725d7bcbc468b0b0b4675477e56b58514e69ab7e66ddfd20fce6108826020870187611932565b6040805160208181019490945273ffffffffffffffffffffffffffffffffffffffff9092169082015290860135606082015260800160405160208183030381529060405280519060200120610fb5565b90506108eb6108e46020860186611932565b8285611024565b610977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4f7074696d697374496e76697465723a20696e76616c6964207369676e61747560448201527f72650000000000000000000000000000000000000000000000000000000000006064820152608401610380565b603660006109886020870187611932565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040908101600090812087840135825290925290205460ff1615610a4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4f7074696d697374496e76697465723a206e6f6e63652068617320616c72656160448201527f6479206265656e207573656400000000000000000000000000000000000000006064820152608401610380565b600160366000610a626020880188611932565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040908101600090812088840180358352935290812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016931515939093179092556037908290610ad69088611932565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411610b9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f7074696d697374496e76697465723a2069737375657220686173206e6f206960448201527f6e766974657300000000000000000000000000000000000000000000000000006064820152608401610380565b60376000610baf6020870187611932565b73ffffffffffffffffffffffffffffffffffffffff9081168252602080830193909352604090910160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190557f0000000000000000000000000000000000000000000000000000000000000000169063702b9dee9087907f6f7074696d6973742e63616e2d6d696e742d66726f6d2d696e7669746500000090610c5990890189611932565b6040805173ffffffffffffffffffffffffffffffffffffffff9092166020830152016040516020818303038152906040526040518463ffffffff1660e01b8152600401610ca893929190611aee565b600060405180830381600087803b158015610cc257600080fd5b505af1158015610cd6573d6000803e3d6000fd5b50505073ffffffffffffffffffffffffffffffffffffffff86169050610cff6020860186611932565b73ffffffffffffffffffffffffffffffffffffffff167f745d3c5bc92ab40b418069bf8f8e2030807effceb88bbaa07ee01574f16be47560405160405180910390a35050505050565b6060610d737f00000000000000000000000000000000000000000000000000000000000000006111f3565b610d9c7f00000000000000000000000000000000000000000000000000000000000000006111f3565b610dc57f00000000000000000000000000000000000000000000000000000000000000006111f3565b604051602001610dd793929190611b2c565b604051602081830303815290604052905090565b600054610100900460ff1615808015610e0b5750600054600160ff909116105b80610e255750303b158015610e25575060005460ff166001145b610eb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610380565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610f0f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610f4e826040518060400160405280600581526020017f312e302e30000000000000000000000000000000000000000000000000000000815250611330565b8015610fb157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600061101e610fc26113d1565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b92915050565b60008060006110338585611451565b9092509050600081600481111561104c5761104c611ba2565b14801561108457508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b15611094576001925050506111ec565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b88886040516024016110c9929190611bd1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516111529190611bea565b600060405180830381855afa9150503d806000811461118d576040519150601f19603f3d011682016040523d82523d6000602084013e611192565b606091505b50915091508180156111a5575080516020145b80156111e5575080517f1626ba7e00000000000000000000000000000000000000000000000000000000906111e39083016020908101908401611c06565b145b9450505050505b9392505050565b60608160000361123657505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611260578061124a81611c1f565b91506112599050600a83611c86565b915061123a565b60008167ffffffffffffffff81111561127b5761127b61171c565b6040519080825280601f01601f1916602001820160405280156112a5576020820181803683370190505b5090505b8415611328576112ba600183611c9a565b91506112c7600a86611cb1565b6112d2906030611ad6565b60f81b8183815181106112e7576112e7611996565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611321600a86611c86565b94506112a9565b949350505050565b600054610100900460ff166113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610380565b610fb18282611496565b600061144c7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61140060015490565b6002546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b905090565b60008082516041036114875760208301516040840151606085015160001a61147b87828585611547565b9450945050505061148f565b506000905060025b9250929050565b600054610100900460ff1661152d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610380565b815160209283012081519190920120600191909155600255565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561157e5750600090506003611656565b8460ff16601b1415801561159657508460ff16601c14155b156115a75750600090506004611656565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156115fb573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661164f57600060019250925050611656565b9150600090505b94509492505050565b60006020828403121561167157600080fd5b5035919050565b60008060006040848603121561168d57600080fd5b833567ffffffffffffffff808211156116a557600080fd5b818601915086601f8301126116b957600080fd5b8135818111156116c857600080fd5b8760208260051b85010111156116dd57600080fd5b6020928301989097509590910135949350505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461171757600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600067ffffffffffffffff808411156117665761176661171c565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156117ac576117ac61171c565b816040528093508581528686860111156117c557600080fd5b858560208301376000602087830101525050509392505050565b600080600083850360808112156117f557600080fd5b6117fe856116f3565b935060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201121561183057600080fd5b50602084019150606084013567ffffffffffffffff81111561185157600080fd5b8401601f8101861361186257600080fd5b6118718682356020840161174b565b9150509250925092565b60005b8381101561189657818101518382015260200161187e565b838111156118a5576000848401525b50505050565b600081518084526118c381602086016020860161187b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006111ec60208301846118ab565b6000806040838503121561191b57600080fd5b611924836116f3565b946020939093013593505050565b60006020828403121561194457600080fd5b6111ec826116f3565b60006020828403121561195f57600080fd5b813567ffffffffffffffff81111561197657600080fd5b8201601f8101841361198757600080fd5b6113288482356020840161174b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611a6a578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805173ffffffffffffffffffffffffffffffffffffffff16845287810151888501528601516060878501819052611a56818601836118ab565b9689019694505050908601906001016119ec565b509098975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061132860408301846118ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115611ae957611ae9611aa7565b500190565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000611b2360608301846118ab565b95945050505050565b60008451611b3e81846020890161187b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611b7a816001850160208a0161187b565b60019201918201528351611b9581600284016020880161187b565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061132860408301846118ab565b60008251611bfc81846020870161187b565b9190910192915050565b600060208284031215611c1857600080fd5b5051919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611c5057611c50611aa7565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611c9557611c95611c57565b500490565b600082821015611cac57611cac611aa7565b500390565b600082611cc057611cc0611c57565b50069056fea264697066735822122097f93936c2ea57902b86c424cff790fa55dccd81b007b045479cd5575c81c5d564736f6c634300080f0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063916db22f1161008c578063db083d7111610066578063db083d7114610252578063de2dd22114610279578063eccec5a814610299578063f62d1888146102d557600080fd5b8063916db22f146101e4578063b4245d731461020b578063c4fc453d1461022b57600080fd5b806350b414e6116100c857806350b414e61461016857806350eedbc21461017e57806354fd4d50146101915780635fda04c7146101a657600080fd5b806314b47241146100ef578063187e3cd11461014057806325b27a3d14610155575b600080fd5b6101167f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61015361014e36600461165f565b6102e8565b005b610153610163366004611678565b61039c565b610170603c81565b604051908152602001610137565b61015361018c3660046117df565b6106bf565b610199610d48565b60405161013791906118f5565b6101d46101b4366004611908565b603660209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610137565b6101707f6f7074696d6973742e63616e2d696e766974650000000000000000000000000081565b61017061021936600461165f565b60356020526000908152604090205481565b6101707f6529fd129351e725d7bcbc468b0b0b4675477e56b58514e69ab7e66ddfd20fce81565b6101167f000000000000000000000000000000000000000000000000000000000000000081565b610170610287366004611932565b60376020526000908152604090205481565b6101996040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6101536102e336600461194d565b610deb565b60008181526035602052604090205415610389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4f7074696d697374496e76697465723a20636f6d6d69746d656e7420616c726560448201527f616479206d61646500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000908152603560205260409020429055565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610461576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4f7074696d697374496e76697465723a206f6e6c7920696e766974652067726160448201527f6e7465722063616e206772616e7420696e7669746573000000000000000000006064820152608401610380565b8160008167ffffffffffffffff81111561047d5761047d61171c565b6040519080825280602002602001820160405280156104ca57816020015b6040805160608082018352600080835260208301529181019190915281526020019060019003908161049b5790505b50905060005b828110156106135783603760008888858181106104ef576104ef611996565b90506020020160208101906105049190611932565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550604051806060016040528087878481811061055f5761055f611996565b90506020020160208101906105749190611932565b73ffffffffffffffffffffffffffffffffffffffff1681526020017f6f7074696d6973742e63616e2d696e766974650000000000000000000000000081526020016040518060400160405280600481526020017f747275650000000000000000000000000000000000000000000000000000000081525081525082828151811061060057610600611996565b60209081029190910101526001016104d0565b506040517f5eb5ea1000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690635eb5ea10906106869084906004016119c5565b600060405180830381600087803b1580156106a057600080fd5b505af11580156106b4573d6000803e3d6000fd5b505050505050505050565b60006035600085846040516020016106d8929190611a78565b604051602081830303815290604052805190602001208152602001908152602001600020549050600081116107b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f4f7074696d697374496e76697465723a20636c61696d657220616e642073696760448201527f6e61747572652068617665206e6f74206265656e20636f6d6d6974746564207960648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a401610380565b426107c1603c83611ad6565b111561084f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4f7074696d697374496e76697465723a206d696e696d756d20636f6d6d69746d60448201527f656e7420706572696f6420686173206e6f7420656c61707365642079657400006064820152608401610380565b60006108d27f6529fd129351e725d7bcbc468b0b0b4675477e56b58514e69ab7e66ddfd20fce6108826020870187611932565b6040805160208181019490945273ffffffffffffffffffffffffffffffffffffffff9092169082015290860135606082015260800160405160208183030381529060405280519060200120610fb5565b90506108eb6108e46020860186611932565b8285611024565b610977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f4f7074696d697374496e76697465723a20696e76616c6964207369676e61747560448201527f72650000000000000000000000000000000000000000000000000000000000006064820152608401610380565b603660006109886020870187611932565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040908101600090812087840135825290925290205460ff1615610a4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4f7074696d697374496e76697465723a206e6f6e63652068617320616c72656160448201527f6479206265656e207573656400000000000000000000000000000000000000006064820152608401610380565b600160366000610a626020880188611932565b73ffffffffffffffffffffffffffffffffffffffff1681526020808201929092526040908101600090812088840180358352935290812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016931515939093179092556037908290610ad69088611932565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411610b9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f7074696d697374496e76697465723a2069737375657220686173206e6f206960448201527f6e766974657300000000000000000000000000000000000000000000000000006064820152608401610380565b60376000610baf6020870187611932565b73ffffffffffffffffffffffffffffffffffffffff9081168252602080830193909352604090910160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190557f0000000000000000000000000000000000000000000000000000000000000000169063702b9dee9087907f6f7074696d6973742e63616e2d6d696e742d66726f6d2d696e7669746500000090610c5990890189611932565b6040805173ffffffffffffffffffffffffffffffffffffffff9092166020830152016040516020818303038152906040526040518463ffffffff1660e01b8152600401610ca893929190611aee565b600060405180830381600087803b158015610cc257600080fd5b505af1158015610cd6573d6000803e3d6000fd5b50505073ffffffffffffffffffffffffffffffffffffffff86169050610cff6020860186611932565b73ffffffffffffffffffffffffffffffffffffffff167f745d3c5bc92ab40b418069bf8f8e2030807effceb88bbaa07ee01574f16be47560405160405180910390a35050505050565b6060610d737f00000000000000000000000000000000000000000000000000000000000000006111f3565b610d9c7f00000000000000000000000000000000000000000000000000000000000000006111f3565b610dc57f00000000000000000000000000000000000000000000000000000000000000006111f3565b604051602001610dd793929190611b2c565b604051602081830303815290604052905090565b600054610100900460ff1615808015610e0b5750600054600160ff909116105b80610e255750303b158015610e25575060005460ff166001145b610eb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610380565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610f0f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610f4e826040518060400160405280600581526020017f312e302e30000000000000000000000000000000000000000000000000000000815250611330565b8015610fb157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b600061101e610fc26113d1565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b92915050565b60008060006110338585611451565b9092509050600081600481111561104c5761104c611ba2565b14801561108457508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b15611094576001925050506111ec565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b88886040516024016110c9929190611bd1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516111529190611bea565b600060405180830381855afa9150503d806000811461118d576040519150601f19603f3d011682016040523d82523d6000602084013e611192565b606091505b50915091508180156111a5575080516020145b80156111e5575080517f1626ba7e00000000000000000000000000000000000000000000000000000000906111e39083016020908101908401611c06565b145b9450505050505b9392505050565b60608160000361123657505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611260578061124a81611c1f565b91506112599050600a83611c86565b915061123a565b60008167ffffffffffffffff81111561127b5761127b61171c565b6040519080825280601f01601f1916602001820160405280156112a5576020820181803683370190505b5090505b8415611328576112ba600183611c9a565b91506112c7600a86611cb1565b6112d2906030611ad6565b60f81b8183815181106112e7576112e7611996565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611321600a86611c86565b94506112a9565b949350505050565b600054610100900460ff166113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610380565b610fb18282611496565b600061144c7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61140060015490565b6002546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b905090565b60008082516041036114875760208301516040840151606085015160001a61147b87828585611547565b9450945050505061148f565b506000905060025b9250929050565b600054610100900460ff1661152d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610380565b815160209283012081519190920120600191909155600255565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561157e5750600090506003611656565b8460ff16601b1415801561159657508460ff16601c14155b156115a75750600090506004611656565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156115fb573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661164f57600060019250925050611656565b9150600090505b94509492505050565b60006020828403121561167157600080fd5b5035919050565b60008060006040848603121561168d57600080fd5b833567ffffffffffffffff808211156116a557600080fd5b818601915086601f8301126116b957600080fd5b8135818111156116c857600080fd5b8760208260051b85010111156116dd57600080fd5b6020928301989097509590910135949350505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461171757600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600067ffffffffffffffff808411156117665761176661171c565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156117ac576117ac61171c565b816040528093508581528686860111156117c557600080fd5b858560208301376000602087830101525050509392505050565b600080600083850360808112156117f557600080fd5b6117fe856116f3565b935060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201121561183057600080fd5b50602084019150606084013567ffffffffffffffff81111561185157600080fd5b8401601f8101861361186257600080fd5b6118718682356020840161174b565b9150509250925092565b60005b8381101561189657818101518382015260200161187e565b838111156118a5576000848401525b50505050565b600081518084526118c381602086016020860161187b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006111ec60208301846118ab565b6000806040838503121561191b57600080fd5b611924836116f3565b946020939093013593505050565b60006020828403121561194457600080fd5b6111ec826116f3565b60006020828403121561195f57600080fd5b813567ffffffffffffffff81111561197657600080fd5b8201601f8101841361198757600080fd5b6113288482356020840161174b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611a6a578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805173ffffffffffffffffffffffffffffffffffffffff16845287810151888501528601516060878501819052611a56818601836118ab565b9689019694505050908601906001016119ec565b509098975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061132860408301846118ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115611ae957611ae9611aa7565b500190565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000611b2360608301846118ab565b95945050505050565b60008451611b3e81846020890161187b565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551611b7a816001850160208a0161187b565b60019201918201528351611b9581600284016020880161187b565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b82815260406020820152600061132860408301846118ab565b60008251611bfc81846020870161187b565b9190910192915050565b600060208284031215611c1857600080fd5b5051919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611c5057611c50611aa7565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611c9557611c95611c57565b500490565b600082821015611cac57611cac611aa7565b500390565b600082611cc057611cc0611c57565b50069056fea264697066735822122097f93936c2ea57902b86c424cff790fa55dccd81b007b045479cd5575c81c5d564736f6c634300080f0033", - "devdoc": { - "custom:upgradeable": "@title OptimistInviter", - "events": { - "InviteClaimed(address,address)": { - "params": { - "claimer": "Address that claimed the invite.", - "issuer": "Address that issued the signature." - } - } - }, - "kind": "dev", - "methods": { - "claimInvite(address,(address,bytes32),bytes)": { - "params": { - "_claimableInvite": "ClaimableInvite struct containing the issuer and nonce.", - "_claimer": "Address that will be granted the invite.", - "_signature": "Signature signed over the claimable invite." - } - }, - "commitInvite(bytes32)": { - "params": { - "_commitment": "A hash of the claimer and signature concatenated. keccak256(abi.encode(_claimer, _signature))" - } - }, - "constructor": { - "custom:semver": "1.0.0", - "params": { - "_attestationStation": "Address of the AttestationStation contract.", - "_inviteGranter": "Address of the invite granter." - } - }, - "initialize(string)": { - "params": { - "_name": "Contract name." - } - }, - "setInviteCounts(address[],uint256)": { - "params": { - "_accounts": "An array of accounts to update the invite counts of.", - "_inviteCount": "Number of invites to set to." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "version": 1 - }, - "userdoc": { - "events": { - "InviteClaimed(address,address)": { - "notice": "Emitted when an invite is claimed." - } - }, - "kind": "user", - "methods": { - "ATTESTATION_STATION()": { - "notice": "Address of the AttestationStation contract." - }, - "CAN_INVITE_ATTESTATION_KEY()": { - "notice": "Attestation key for that signals that an account was allowed to issue invites" - }, - "CLAIMABLE_INVITE_TYPEHASH()": { - "notice": "EIP712 typehash for the ClaimableInvite type." - }, - "EIP712_VERSION()": { - "notice": "Version used for the EIP712 domain separator. This version is separated from the contract semver because the EIP712 domain separator is used to sign messages, and changing the domain separator invalidates all existing signatures. We should only bump this version if we make a major change to the signature scheme." - }, - "INVITE_GRANTER()": { - "notice": "Granter who can set accounts' invite counts." - }, - "MIN_COMMITMENT_PERIOD()": { - "notice": "Minimum age of a commitment (in seconds) before it can be revealed using claimInvite. Currently set to 60 seconds. Prevents an attacker from front-running a commitment by taking the signature in the claimInvite call and quickly committing and claiming it before the the claimer's transaction succeeds. With this, frontrunning a commitment requires that an attacker be able to prevent the honest claimer's claimInvite transaction from being included for this long." - }, - "claimInvite(address,(address,bytes32),bytes)": { - "notice": "Allows anyone to reveal a commitment and claim an invite. The hash, keccak256(abi.encode(_claimer, _signature)), should have been already committed using commitInvite. Before issuing the \"optimist.can-mint-from-invite\" attestation, this function checks that 1) the hash corresponding to the _claimer and the _signature was committed 2) MIN_COMMITMENT_PERIOD has passed since the commitment was made. 3) the _signature is signed correctly by the issuer 4) the _signature hasn't already been used to claim an invite before 5) the _signature issuer has not used up all of their invites This function doesn't require that the _claimer is calling this function." - }, - "commitInvite(bytes32)": { - "notice": "Allows anyone (but likely the claimer) to commit a received signature along with the address to claim to. Before calling this function, the claimer should have received a signature from the issuer off-chain. The claimer then calls this function with the hash of the claimer's address and the received signature. This is necessary to prevent front-running when the invitee is claiming the invite. Without a commit and reveal scheme, anyone who is watching the mempool can take the signature being submitted and front run the transaction to claim the invite to their own address. The same commitment can only be made once, and the function reverts if the commitment has already been made. This prevents griefing where a malicious party can prevent the original claimer from being able to claimInvite." - }, - "commitmentTimestamps(bytes32)": { - "notice": "Maps from hashes to the timestamp when they were committed." - }, - "initialize(string)": { - "notice": "Initializes this contract, setting the EIP712 context. Only update the EIP712_VERSION when there is a change to the signature scheme. After the EIP712 version is changed, any signatures issued off-chain but not claimed yet will no longer be accepted by the claimInvite function. Please make sure to notify the issuers that they must re-issue their invite signatures." - }, - "inviteCounts(address)": { - "notice": "Maps from addresses to number of invites they have." - }, - "setInviteCounts(address[],uint256)": { - "notice": "Allows invite granter to set the number of invites an address has." - }, - "usedNonces(address,bytes32)": { - "notice": "Maps from addresses to nonces to whether or not they have been used." - }, - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "OptimistInviter issues \"optimist.can-invite\" and \"optimist.can-mint-from-invite\" attestations. Accounts that have invites can issue signatures that allow other accounts to claim an invite. The invitee uses a claim and reveal flow to claim the invite to an address of their choosing. Parties involved: 1) INVITE_GRANTER: trusted account that can allow accounts to issue invites 2) issuer: account that is allowed to issue invites 3) claimer: account that receives the invites Flow: 1) INVITE_GRANTER calls _setInviteCount to allow an issuer to issue a certain number of invites, and also creates a \"optimist.can-invite\" attestation for the issuer 2) Off-chain, the issuer signs (EIP-712) a ClaimableInvite to produce a signature 3) Off-chain, invite issuer sends the plaintext ClaimableInvite and the signature to the recipient 4) claimer chooses an address they want to receive the invite on 5) claimer commits the hash of the address they want to receive the invite on and the received signature keccak256(abi.encode(addressToReceiveTo, receivedSignature)) using the commitInvite function 6) claimer waits for the MIN_COMMITMENT_PERIOD to pass. 7) claimer reveals the plaintext ClaimableInvite and the signature using the claimInvite function, receiving the \"optimist.can-mint-from-invite\" attestation", - "version": 1 - }, - "storageLayout": { - "storage": [ - { - "astId": 1166, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 1169, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 3321, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "_HASHED_NAME", - "offset": 0, - "slot": "1", - "type": "t_bytes32" - }, - { - "astId": 3323, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "_HASHED_VERSION", - "offset": 0, - "slot": "2", - "type": "t_bytes32" - }, - { - "astId": 3461, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "__gap", - "offset": 0, - "slot": "3", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 5494, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "commitmentTimestamps", - "offset": 0, - "slot": "53", - "type": "t_mapping(t_bytes32,t_uint256)" - }, - { - "astId": 5501, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "usedNonces", - "offset": 0, - "slot": "54", - "type": "t_mapping(t_address,t_mapping(t_bytes32,t_bool))" - }, - { - "astId": 5506, - "contract": "contracts/universal/op-nft/OptimistInviter.sol:OptimistInviter", - "label": "inviteCounts", - "offset": 0, - "slot": "55", - "type": "t_mapping(t_address,t_uint256)" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "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_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_bytes32,t_bool))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(bytes32 => bool))", - "numberOfBytes": "32", - "value": "t_mapping(t_bytes32,t_bool)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_mapping(t_bytes32,t_bool)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_mapping(t_bytes32,t_uint256)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "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-bedrock/deployments/optimism-mainnet/OptimistInviterProxy.json b/packages/contracts-bedrock/deployments/optimism-mainnet/OptimistInviterProxy.json deleted file mode 100644 index 24a4368dad49..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/OptimistInviterProxy.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "address": "0x073031A1E1b8F5458Ed41Ce56331F5fd7e1de929", - "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": "0x0103162552bf1ea529a5b39fa6b29efe7439475be4bed49cda640f2a3b91b3e3", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "534190", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080010000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xde6a4af6b6df5b8bcc01857505fbab84445c5441f2a76c2f62e3c1a942f2265b", - "transactionHash": "0x0103162552bf1ea529a5b39fa6b29efe7439475be4bed49cda640f2a3b91b3e3", - "logs": [ - { - "transactionIndex": 0, - "blockNumber": 87031037, - "transactionHash": "0x0103162552bf1ea529a5b39fa6b29efe7439475be4bed49cda640f2a3b91b3e3", - "address": "0x073031A1E1b8F5458Ed41Ce56331F5fd7e1de929", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58", - "logIndex": 0, - "blockHash": "0xde6a4af6b6df5b8bcc01857505fbab84445c5441f2a76c2f62e3c1a942f2265b" - } - ], - "blockNumber": 87031037, - "cumulativeGasUsed": "534190", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "d7155764d4bdb814f10e1bb45296292b", - "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) public virtual 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 public\\n payable\\n virtual\\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) public virtual 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() public virtual proxyCallIfNotAdmin returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @notice Queries the implementation address.\\n *\\n * @return Implementation address.\\n */\\n function implementation() public virtual 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\":\"0x64d67f1936d97c87a2e42317eb162744ad5cefdc9bc8b1138ee4afe2886eb885\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b5060405161094138038061094183398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206109218339815191525490565b600080516020610921833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610830806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea26469706673582212200496188e743eb5556ea8662e234845601d39477882517acc1cf9061fcc51284c64736f6c634300080f0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea26469706673582212200496188e743eb5556ea8662e234845601d39477882517acc1cf9061fcc51284c64736f6c634300080f0033", - "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-bedrock/deployments/optimism-mainnet/OptimistProxy.json b/packages/contracts-bedrock/deployments/optimism-mainnet/OptimistProxy.json deleted file mode 100644 index 904016e921b2..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/OptimistProxy.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "address": "0x2335022c740d17c2837f9C884Bfe4fFdbf0A95D5", - "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": "0x3a663cc47f695bade6e93cbd5803bdd8e3419a689fd4682a2e12a37f9a6dd3ef", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0x9C6373dE60c2D3297b18A8f964618ac46E011B58", - "contractAddress": null, - "transactionIndex": 0, - "gasUsed": "534190", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x8edb9af706a1eaa6dcff60412414c56e2b55528e997bd9f079d9eca72aa745fc", - "transactionHash": "0x3a663cc47f695bade6e93cbd5803bdd8e3419a689fd4682a2e12a37f9a6dd3ef", - "logs": [ - { - "transactionIndex": 0, - "blockNumber": 49670714, - "transactionHash": "0x3a663cc47f695bade6e93cbd5803bdd8e3419a689fd4682a2e12a37f9a6dd3ef", - "address": "0x2335022c740d17c2837f9C884Bfe4fFdbf0A95D5", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000009c6373de60c2d3297b18a8f964618ac46e011b58", - "logIndex": 0, - "blockHash": "0x8edb9af706a1eaa6dcff60412414c56e2b55528e997bd9f079d9eca72aa745fc" - } - ], - "blockNumber": 49670714, - "cumulativeGasUsed": "534190", - "status": 1, - "byzantium": true - }, - "args": [ - "0x9C6373dE60c2D3297b18A8f964618ac46E011B58" - ], - "numDeployments": 1, - "solcInputHash": "45837d34ff24b9cb2ae34232b60ea874", - "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-bedrock/deployments/optimism-mainnet/SchemaRegistry.json b/packages/contracts-bedrock/deployments/optimism-mainnet/SchemaRegistry.json deleted file mode 100644 index 458dd59f0d96..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/SchemaRegistry.json +++ /dev/null @@ -1,293 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AlreadyExists", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "registerer", - "type": "address" - } - ], - "name": "Registered", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - } - ], - "name": "getSchema", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "uid", - "type": "bytes32" - }, - { - "internalType": "contract ISchemaResolver", - "name": "resolver", - "type": "address" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - }, - { - "internalType": "string", - "name": "schema", - "type": "string" - } - ], - "internalType": "struct SchemaRecord", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "schema", - "type": "string" - }, - { - "internalType": "contract ISchemaResolver", - "name": "resolver", - "type": "address" - }, - { - "internalType": "bool", - "name": "revocable", - "type": "bool" - } - ], - "name": "register", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "address": "0x6232208d66bAc2305b46b4Cb6BCB3857B298DF13", - "args": [], - "bytecode": "0x60e060405234801561001057600080fd5b5060016080819052600060a081905260c082905281610b166100478339600060fe0152600060d50152600060ac0152610b166000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806360d7a27814610064578063a2ea7c6e14610085575b600080fd5b61004e6100a5565b60405161005b9190610604565b60405180910390f35b61007761007236600461061e565b610148565b60405190815260200161005b565b6100986100933660046106d0565b6102f1565b60405161005b91906106e9565b60606100d07f0000000000000000000000000000000000000000000000000000000000000000610419565b6100f97f0000000000000000000000000000000000000000000000000000000000000000610419565b6101227f0000000000000000000000000000000000000000000000000000000000000000610419565b6040516020016101349392919061073a565b604051602081830303815290604052905090565b60008060405180608001604052806000801b81526020018573ffffffffffffffffffffffffffffffffffffffff168152602001841515815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525092935091506101ca905082610556565b60008181526020819052604090205490915015610213576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80825260008181526020818152604091829020845181559084015160018201805493860151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090941673ffffffffffffffffffffffffffffffffffffffff9092169190911792909217909155606083015183919060028201906102af9082610881565b50506040513381528291507f7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c9060200160405180910390a29695505050505050565b604080516080810182526000808252602082018190529181019190915260608082015260008281526020818152604091829020825160808101845281548152600182015473ffffffffffffffffffffffffffffffffffffffff8116938201939093527401000000000000000000000000000000000000000090920460ff16151592820192909252600282018054919291606084019190610390906107df565b80601f01602080910402602001604051908101604052809291908181526020018280546103bc906107df565b80156104095780601f106103de57610100808354040283529160200191610409565b820191906000526020600020905b8154815290600101906020018083116103ec57829003601f168201915b5050505050815250509050919050565b60608160000361045c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104865780610470816109ca565b915061047f9050600a83610a31565b9150610460565b60008167ffffffffffffffff8111156104a1576104a16107b0565b6040519080825280601f01601f1916602001820160405280156104cb576020820181803683370190505b5090505b841561054e576104e0600183610a45565b91506104ed600a86610a5e565b6104f8906030610a72565b60f81b81838151811061050d5761050d610a85565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610547600a86610a31565b94506104cf565b949350505050565b600081606001518260200151836040015160405160200161057993929190610ab4565b604051602081830303815290604052805190602001209050919050565b60005b838110156105b1578181015183820152602001610599565b50506000910152565b600081518084526105d2816020860160208601610596565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061061760208301846105ba565b9392505050565b6000806000806060858703121561063457600080fd5b843567ffffffffffffffff8082111561064c57600080fd5b818701915087601f83011261066057600080fd5b81358181111561066f57600080fd5b88602082850101111561068157600080fd5b6020928301965094505085013573ffffffffffffffffffffffffffffffffffffffff811681146106b057600080fd5b9150604085013580151581146106c557600080fd5b939692955090935050565b6000602082840312156106e257600080fd5b5035919050565b602081528151602082015273ffffffffffffffffffffffffffffffffffffffff60208301511660408201526040820151151560608201526000606083015160808084015261054e60a08401826105ba565b6000845161074c818460208901610596565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610788816001850160208a01610596565b600192019182015283516107a3816002840160208801610596565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c908216806107f357607f821691505b60208210810361082c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561087c57600081815260208120601f850160051c810160208610156108595750805b601f850160051c820191505b8181101561087857828155600101610865565b5050505b505050565b815167ffffffffffffffff81111561089b5761089b6107b0565b6108af816108a984546107df565b84610832565b602080601f83116001811461090257600084156108cc5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610878565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561094f57888601518255948401946001909101908401610930565b508582101561098b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109fb576109fb61099b565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a4057610a40610a02565b500490565b81810381811115610a5857610a5861099b565b92915050565b600082610a6d57610a6d610a02565b500690565b80820180821115610a5857610a5861099b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008451610ac6818460208901610596565b60609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190930190815290151560f81b60148201526015019291505056fea164736f6c6343000813000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806360d7a27814610064578063a2ea7c6e14610085575b600080fd5b61004e6100a5565b60405161005b9190610604565b60405180910390f35b61007761007236600461061e565b610148565b60405190815260200161005b565b6100986100933660046106d0565b6102f1565b60405161005b91906106e9565b60606100d07f0000000000000000000000000000000000000000000000000000000000000000610419565b6100f97f0000000000000000000000000000000000000000000000000000000000000000610419565b6101227f0000000000000000000000000000000000000000000000000000000000000000610419565b6040516020016101349392919061073a565b604051602081830303815290604052905090565b60008060405180608001604052806000801b81526020018573ffffffffffffffffffffffffffffffffffffffff168152602001841515815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525092935091506101ca905082610556565b60008181526020819052604090205490915015610213576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80825260008181526020818152604091829020845181559084015160018201805493860151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090941673ffffffffffffffffffffffffffffffffffffffff9092169190911792909217909155606083015183919060028201906102af9082610881565b50506040513381528291507f7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c9060200160405180910390a29695505050505050565b604080516080810182526000808252602082018190529181019190915260608082015260008281526020818152604091829020825160808101845281548152600182015473ffffffffffffffffffffffffffffffffffffffff8116938201939093527401000000000000000000000000000000000000000090920460ff16151592820192909252600282018054919291606084019190610390906107df565b80601f01602080910402602001604051908101604052809291908181526020018280546103bc906107df565b80156104095780601f106103de57610100808354040283529160200191610409565b820191906000526020600020905b8154815290600101906020018083116103ec57829003601f168201915b5050505050815250509050919050565b60608160000361045c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104865780610470816109ca565b915061047f9050600a83610a31565b9150610460565b60008167ffffffffffffffff8111156104a1576104a16107b0565b6040519080825280601f01601f1916602001820160405280156104cb576020820181803683370190505b5090505b841561054e576104e0600183610a45565b91506104ed600a86610a5e565b6104f8906030610a72565b60f81b81838151811061050d5761050d610a85565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610547600a86610a31565b94506104cf565b949350505050565b600081606001518260200151836040015160405160200161057993929190610ab4565b604051602081830303815290604052805190602001209050919050565b60005b838110156105b1578181015183820152602001610599565b50506000910152565b600081518084526105d2816020860160208601610596565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061061760208301846105ba565b9392505050565b6000806000806060858703121561063457600080fd5b843567ffffffffffffffff8082111561064c57600080fd5b818701915087601f83011261066057600080fd5b81358181111561066f57600080fd5b88602082850101111561068157600080fd5b6020928301965094505085013573ffffffffffffffffffffffffffffffffffffffff811681146106b057600080fd5b9150604085013580151581146106c557600080fd5b939692955090935050565b6000602082840312156106e257600080fd5b5035919050565b602081528151602082015273ffffffffffffffffffffffffffffffffffffffff60208301511660408201526040820151151560608201526000606083015160808084015261054e60a08401826105ba565b6000845161074c818460208901610596565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610788816001850160208a01610596565b600192019182015283516107a3816002840160208801610596565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c908216806107f357607f821691505b60208210810361082c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561087c57600081815260208120601f850160051c810160208610156108595750805b601f850160051c820191505b8181101561087857828155600101610865565b5050505b505050565b815167ffffffffffffffff81111561089b5761089b6107b0565b6108af816108a984546107df565b84610832565b602080601f83116001811461090257600084156108cc5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610878565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561094f57888601518255948401946001909101908401610930565b508582101561098b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109fb576109fb61099b565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a4057610a40610a02565b500490565b81810381811115610a5857610a5861099b565b92915050565b600082610a6d57610a6d610a02565b500690565b80820180821115610a5857610a5861099b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008451610ac6818460208901610596565b60609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190930190815290151560f81b60148201526015019291505056fea164736f6c6343000813000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "constructor": { - "details": "Creates a new SchemaRegistry instance." - }, - "getSchema(bytes32)": { - "details": "Returns an existing schema by UID", - "params": { - "uid": "The UID of the schema to retrieve." - }, - "returns": { - "_0": "The schema data members." - } - }, - "register(string,address,bool)": { - "details": "Submits and reserves a new schema", - "params": { - "resolver": "An optional schema resolver.", - "revocable": "Whether the schema allows revocations explicitly.", - "schema": "The schema data schema." - }, - "returns": { - "_0": "The UID of the new schema." - } - }, - "version()": { - "returns": { - "_0": "Semver contract version as a string." - } - } - }, - "events": { - "Registered(bytes32,address)": { - "details": "Emitted when a new schema has been registered", - "params": { - "registerer": "The address of the account used to register the schema.", - "uid": "The schema UID." - } - } - }, - "title": "SchemaRegistry" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"AlreadyExists\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"registerer\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Registered\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getSchema\",\"outputs\":[{\"internalType\":\"struct SchemaRecord\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"contract ISchemaResolver\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"schema\",\"type\":\"string\"}]}]},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"schema\",\"type\":\"string\"},{\"internalType\":\"contract ISchemaResolver\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"register\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Creates a new SchemaRegistry instance.\"},\"getSchema(bytes32)\":{\"details\":\"Returns an existing schema by UID\",\"params\":{\"uid\":\"The UID of the schema to retrieve.\"},\"returns\":{\"_0\":\"The schema data members.\"}},\"register(string,address,bool)\":{\"details\":\"Submits and reserves a new schema\",\"params\":{\"resolver\":\"An optional schema resolver.\",\"revocable\":\"Whether the schema allows revocations explicitly.\",\"schema\":\"The schema data schema.\"},\"returns\":{\"_0\":\"The UID of the new schema.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":@cwia/=node_modules/clones-with-immutable-args/src/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":clones-with-immutable-args/=node_modules/clones-with-immutable-args/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"contracts/EAS/SchemaRegistry.sol\":\"SchemaRegistry\"},\"libraries\":{}},\"sources\":{\"contracts/EAS/Common.sol\":{\"keccak256\":\"0x880e8262ee6682eeca6140e5a0b71f98e0c4024720c777da161e05a7715ed09a\",\"urls\":[\"bzz-raw://56ed7dc6b538070a66b851275a6a9721275da9e5e83631d94e93620cd679c3f6\",\"dweb:/ipfs/QmVjKgNr3jbnYerjDyFGLky8wXCUR8SuzxrsypBVVSW3tk\"],\"license\":\"MIT\"},\"contracts/EAS/ISchemaRegistry.sol\":{\"keccak256\":\"0x4e988bea43a70e8ed156c7ee74dd3667872a68f65fa10dc4f07ddd4d89b929f1\",\"urls\":[\"bzz-raw://046977484b8089aad16f2064099b3f7604bcbddd61334e046838c3c448b5ebb5\",\"dweb:/ipfs/QmXdorYunKEbiosCGL4teYCd1W2njCqujvMWQjYonAxU6w\"],\"license\":\"MIT\"},\"contracts/EAS/SchemaRegistry.sol\":{\"keccak256\":\"0x41f61bef4ebc0c20d0ed6bbab7623f26e0ff13f68e969211a8882a9610f935b6\",\"urls\":[\"bzz-raw://cccadbdd3bf6546ed9d7280119b6d0c7d4de6f92de9469cbab62c01d59b84c8b\",\"dweb:/ipfs/Qmf7vycRfckwYCUYN7e6bce4QuMj35hjR1AqqtoYm4gNxu\"],\"license\":\"MIT\"},\"contracts/EAS/resolver/ISchemaResolver.sol\":{\"keccak256\":\"0xe537341e3d8d9c8e0eada21b4278beef510781fb1745892312c286a3c8287c2d\",\"urls\":[\"bzz-raw://5ab80b1fd7b6ad0ca94ff14358c5ba942614e25632d8a07c8e364d3f45c08453\",\"dweb:/ipfs/QmY6WToUtVo1HpDq7z7Tb17othZnJwpz4m26GuzKAsGTeM\"],\"license\":\"MIT\"},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0xc455c84bb1f17e994dea0451fd363f81f83965bfa86e81ac6c8b3a327b9a0ff0\",\"urls\":[\"bzz-raw://fab499f3c0d7df8eb763b50621848d5d2147fb9c42a8eb9b65a11093090bb482\",\"dweb:/ipfs/QmUKsG4ztwtUZFjuRYAxgUFTgH5YxWSGF1BFFaB7vdM2K3\"],\"license\":\"MIT\"},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 1, - "receipt": { - "transactionHash": "0xef2a1eb6082e0ce53a239b80272f9ac5e0734901f0e2b7dc851d6f4d3ab04e8e", - "transactionIndex": "0x1", - "blockHash": "0x3d832e9dc651b4667640a6a685b55f4548663e0e936adf45c2336dc44f029b68", - "blockNumber": "0x6645730", - "from": "0x9bbFB9919062C29a5eE15aCD93c9D7c3b14d31aa", - "to": null, - "cumulativeGasUsed": "0xadf9a", - "gasUsed": "0xa1a55", - "contractAddress": "0x6232208d66bAc2305b46b4Cb6BCB3857B298DF13", - "logs": [], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "type": "0x2", - "effectiveGasPrice": "0xb2d05e40" - }, - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 27112, - "contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry", - "label": "_registry", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_bytes32,t_struct(SchemaRecord)27057_storage)" - }, - { - "astId": 27118, - "contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)49_storage" - } - ], - "types": { - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(ISchemaResolver)27536": { - "encoding": "inplace", - "label": "contract ISchemaResolver", - "numberOfBytes": "20" - }, - "t_mapping(t_bytes32,t_struct(SchemaRecord)27057_storage)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => struct SchemaRecord)", - "numberOfBytes": "32", - "value": "t_struct(SchemaRecord)27057_storage" - }, - "t_string_storage": { - "encoding": "bytes", - "label": "string", - "numberOfBytes": "32" - }, - "t_struct(SchemaRecord)27057_storage": { - "encoding": "inplace", - "label": "struct SchemaRecord", - "numberOfBytes": "96", - "members": [ - { - "astId": 27049, - "contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry", - "label": "uid", - "offset": 0, - "slot": "0", - "type": "t_bytes32" - }, - { - "astId": 27052, - "contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry", - "label": "resolver", - "offset": 0, - "slot": "1", - "type": "t_contract(ISchemaResolver)27536" - }, - { - "astId": 27054, - "contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry", - "label": "revocable", - "offset": 20, - "slot": "1", - "type": "t_bool" - }, - { - "astId": 27056, - "contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry", - "label": "schema", - "offset": 0, - "slot": "2", - "type": "t_string_storage" - } - ] - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - } - } - }, - "transactionHash": "0xef2a1eb6082e0ce53a239b80272f9ac5e0734901f0e2b7dc851d6f4d3ab04e8e", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "version()": { - "notice": "Returns the full semver contract version." - } - }, - "notice": "The global attestation schemas for the Ethereum Attestation Service protocol." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/optimism-mainnet/solcInputs/b1df373a9ed51b3903b61f56faa9a78f.json b/packages/contracts-bedrock/deployments/optimism-mainnet/solcInputs/b1df373a9ed51b3903b61f56faa9a78f.json deleted file mode 100644 index b0bf9b8a4dfb..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-mainnet/solcInputs/b1df373a9ed51b3903b61f56faa9a78f.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "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-bedrock/deployments/optimism-sepolia/.chainId b/packages/contracts-bedrock/deployments/optimism-sepolia/.chainId deleted file mode 100644 index 03f37de82513..000000000000 --- a/packages/contracts-bedrock/deployments/optimism-sepolia/.chainId +++ /dev/null @@ -1 +0,0 @@ -11155420 \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/sepolia/.chainId b/packages/contracts-bedrock/deployments/sepolia/.chainId deleted file mode 100644 index bd8d1cd44c96..000000000000 --- a/packages/contracts-bedrock/deployments/sepolia/.chainId +++ /dev/null @@ -1 +0,0 @@ -11155111 \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/sepolia/L1ERC721Bridge.json b/packages/contracts-bedrock/deployments/sepolia/L1ERC721Bridge.json deleted file mode 100644 index 81626f30f9c4..000000000000 --- a/packages/contracts-bedrock/deployments/sepolia/L1ERC721Bridge.json +++ /dev/null @@ -1,580 +0,0 @@ -{ - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_messenger", - "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" - }, - { - "inputs": [], - "name": "MESSENGER", - "outputs": [ - { - "internalType": "contract CrossDomainMessenger", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OTHER_BRIDGE", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "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": "contract SuperchainConfig", - "name": "_superchainConfig", - "type": "address" - } - ], - "name": "initialize", - "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": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "superchainConfig", - "outputs": [ - { - "internalType": "contract SuperchainConfig", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "address": "0x532Cad52e1f812EEB9c9A9571E07Fef55993FEfA", - "args": [ - "0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef" - ], - "bytecode": "0x60c06040523480156200001157600080fd5b506040516200168a3803806200168a83398101604081905262000034916200029f565b807342000000000000000000000000000000000000146001600160a01b038216620000bb5760405162461bcd60e51b815260206004820152602c60248201527f4552433732314272696467653a206d657373656e6765722063616e6e6f74206260448201526b65206164647265737328302960a01b60648201526084015b60405180910390fd5b6001600160a01b0381166200012b5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314272696467653a206f74686572206272696467652063616e6e6f60448201526e74206265206164647265737328302960881b6064820152608401620000b2565b6001600160a01b039182166080521660a05262000149600062000150565b50620002d1565b600054610100900460ff1615808015620001715750600054600160ff909116105b80620001a157506200018e306200029060201b62000b5c1760201c565b158015620001a1575060005460ff166001145b620002065760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000b2565b6000805460ff1916600117905580156200022a576000805461ff0019166101001790555b603280546001600160a01b0319166001600160a01b03841617905580156200028c576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600060208284031215620002b257600080fd5b81516001600160a01b0381168114620002ca57600080fd5b9392505050565b60805160a051611362620003286000396000818161020b0152818161027c015281816104270152610e0401526000818161013a01528181610232015281816103fd0152818161045e0152610dd501526113626000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c8063761f449311610081578063aa5574521161005b578063aa55745214610254578063c4d66de814610267578063c89701a21461027a57600080fd5b8063761f4493146101f35780637f46ddb214610206578063927ede2d1461022d57600080fd5b806354fd4d50116100b257806354fd4d501461015e5780635c975abb146101a75780635d93a3fc146101bf57600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610f76565b6102a0565b005b7f00000000000000000000000000000000000000000000000000000000000000006100f9565b61019a6040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161011a9190611064565b6101af61034c565b604051901515815260200161011a565b6101af6101cd36600461107e565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b6101366102013660046110bf565b6103e5565b6100f97f000000000000000000000000000000000000000000000000000000000000000081565b6100f97f000000000000000000000000000000000000000000000000000000000000000081565b610136610262366004611157565b6108d5565b6101366102753660046111ce565b610991565b7f00000000000000000000000000000000000000000000000000000000000000006100f9565b333b15610334576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103448686333388888888610b78565b505050505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156103bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e091906111eb565b905090565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561050357507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104eb919061120d565b73ffffffffffffffffffffffffffffffffffffffff16145b61058f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161032b565b61059761034c565b156105fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161032b565b3073ffffffffffffffffffffffffffffffffffffffff8816036106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161032b565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff161515600114610772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161032b565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b15801561083257600080fd5b505af1158015610846573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516108c49493929190611273565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610978576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161032b565b6109888787338888888888610b78565b50505050505050565b600054610100900460ff16158080156109b15750600054600160ff909116105b806109cb5750303b1580156109cb575060005460ff166001145b610a57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161032b565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610ab557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015610b5857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610c1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161032b565b600063761f449360e01b888a8989898888604051602401610c4297969594939291906112b3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d8257600080fd5b505af1158015610d96573d6000803e3d6000fd5b50506040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169250633dbb202b9150610e30907f00000000000000000000000000000000000000000000000000000000000000009085908990600401611310565b600060405180830381600087803b158015610e4a57600080fd5b505af1158015610e5e573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610edc9493929190611273565b60405180910390a4505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f1157600080fd5b50565b803563ffffffff81168114610f2857600080fd5b919050565b60008083601f840112610f3f57600080fd5b50813567ffffffffffffffff811115610f5757600080fd5b602083019150836020828501011115610f6f57600080fd5b9250929050565b60008060008060008060a08789031215610f8f57600080fd5b8635610f9a81610eef565b95506020870135610faa81610eef565b945060408701359350610fbf60608801610f14565b9250608087013567ffffffffffffffff811115610fdb57600080fd5b610fe789828a01610f2d565b979a9699509497509295939492505050565b6000815180845260005b8181101561101f57602081850181015186830182015201611003565b81811115611031576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006110776020830184610ff9565b9392505050565b60008060006060848603121561109357600080fd5b833561109e81610eef565b925060208401356110ae81610eef565b929592945050506040919091013590565b600080600080600080600060c0888a0312156110da57600080fd5b87356110e581610eef565b965060208801356110f581610eef565b9550604088013561110581610eef565b9450606088013561111581610eef565b93506080880135925060a088013567ffffffffffffffff81111561113857600080fd5b6111448a828b01610f2d565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561117257600080fd5b873561117d81610eef565b9650602088013561118d81610eef565b9550604088013561119d81610eef565b9450606088013593506111b260808901610f14565b925060a088013567ffffffffffffffff81111561113857600080fd5b6000602082840312156111e057600080fd5b813561107781610eef565b6000602082840312156111fd57600080fd5b8151801515811461107757600080fd5b60006020828403121561121f57600080fd5b815161107781610eef565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006112a960608301848661122a565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261130360c08301848661122a565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061133f6060830185610ff9565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100d45760003560e01c8063761f449311610081578063aa5574521161005b578063aa55745214610254578063c4d66de814610267578063c89701a21461027a57600080fd5b8063761f4493146101f35780637f46ddb214610206578063927ede2d1461022d57600080fd5b806354fd4d50116100b257806354fd4d501461015e5780635c975abb146101a75780635d93a3fc146101bf57600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610f76565b6102a0565b005b7f00000000000000000000000000000000000000000000000000000000000000006100f9565b61019a6040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161011a9190611064565b6101af61034c565b604051901515815260200161011a565b6101af6101cd36600461107e565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b6101366102013660046110bf565b6103e5565b6100f97f000000000000000000000000000000000000000000000000000000000000000081565b6100f97f000000000000000000000000000000000000000000000000000000000000000081565b610136610262366004611157565b6108d5565b6101366102753660046111ce565b610991565b7f00000000000000000000000000000000000000000000000000000000000000006100f9565b333b15610334576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103448686333388888888610b78565b505050505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156103bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e091906111eb565b905090565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561050357507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104eb919061120d565b73ffffffffffffffffffffffffffffffffffffffff16145b61058f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161032b565b61059761034c565b156105fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161032b565b3073ffffffffffffffffffffffffffffffffffffffff8816036106a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161032b565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff161515600114610772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161032b565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b15801561083257600080fd5b505af1158015610846573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516108c49493929190611273565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610978576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161032b565b6109888787338888888888610b78565b50505050505050565b600054610100900460ff16158080156109b15750600054600160ff909116105b806109cb5750303b1580156109cb575060005460ff166001145b610a57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161032b565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610ab557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015610b5857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610c1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161032b565b600063761f449360e01b888a8989898888604051602401610c4297969594939291906112b3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d8257600080fd5b505af1158015610d96573d6000803e3d6000fd5b50506040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169250633dbb202b9150610e30907f00000000000000000000000000000000000000000000000000000000000000009085908990600401611310565b600060405180830381600087803b158015610e4a57600080fd5b505af1158015610e5e573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610edc9493929190611273565b60405180910390a4505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f1157600080fd5b50565b803563ffffffff81168114610f2857600080fd5b919050565b60008083601f840112610f3f57600080fd5b50813567ffffffffffffffff811115610f5757600080fd5b602083019150836020828501011115610f6f57600080fd5b9250929050565b60008060008060008060a08789031215610f8f57600080fd5b8635610f9a81610eef565b95506020870135610faa81610eef565b945060408701359350610fbf60608801610f14565b9250608087013567ffffffffffffffff811115610fdb57600080fd5b610fe789828a01610f2d565b979a9699509497509295939492505050565b6000815180845260005b8181101561101f57602081850181015186830182015201611003565b81811115611031576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006110776020830184610ff9565b9392505050565b60008060006060848603121561109357600080fd5b833561109e81610eef565b925060208401356110ae81610eef565b929592945050506040919091013590565b600080600080600080600060c0888a0312156110da57600080fd5b87356110e581610eef565b965060208801356110f581610eef565b9550604088013561110581610eef565b9450606088013561111581610eef565b93506080880135925060a088013567ffffffffffffffff81111561113857600080fd5b6111448a828b01610f2d565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561117257600080fd5b873561117d81610eef565b9650602088013561118d81610eef565b9550604088013561119d81610eef565b9450606088013593506111b260808901610f14565b925060a088013567ffffffffffffffff81111561113857600080fd5b6000602082840312156111e057600080fd5b813561107781610eef565b6000602082840312156111fd57600080fd5b8151801515811461107757600080fd5b60006020828403121561121f57600080fd5b815161107781610eef565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006112a960608301848661122a565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261130360c08301848661122a565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600061133f6060830185610ff9565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "bridgeERC721(address,address,uint256,uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.", - "_localToken": "Address of the ERC721 on this domain.", - "_minGasLimit": "Minimum gas limit for the bridge message on the other domain.", - "_remoteToken": "Address of the ERC721 on the remote domain.", - "_tokenId": "Token ID to bridge." - } - }, - "bridgeERC721To(address,address,address,uint256,uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.", - "_localToken": "Address of the ERC721 on this domain.", - "_minGasLimit": "Minimum gas limit for the bridge message on the other domain.", - "_remoteToken": "Address of the ERC721 on the remote domain.", - "_to": "Address to receive the token on the other domain.", - "_tokenId": "Token ID to bridge." - } - }, - "constructor": { - "params": { - "_messenger": "Address of the CrossDomainMessenger on this network." - } - }, - "finalizeBridgeERC721(address,address,address,address,uint256,bytes)": { - "params": { - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_from": "Address that triggered the bridge on the other domain.", - "_localToken": "Address of the ERC721 token on this domain.", - "_remoteToken": "Address of the ERC721 token on the other domain.", - "_to": "Address to receive the token on this domain.", - "_tokenId": "ID of the token being deposited." - } - }, - "initialize(address)": { - "params": { - "_superchainConfig": "Address of the SuperchainConfig contract on this network." - } - }, - "messenger()": { - "returns": { - "_0": "Messenger contract on this domain." - } - }, - "otherBridge()": { - "returns": { - "_0": "Address of the bridge on the other network." - } - }, - "paused()": { - "returns": { - "_0": "Whether or not the contract is paused." - } - } - }, - "title": "L1ERC721Bridge" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_messenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC721BridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC721BridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC721\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC721To\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeBridgeERC721\"},{\"inputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"_superchainConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"superchainConfig\",\"outputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bridgeERC721(address,address,uint256,uint32,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.\",\"_localToken\":\"Address of the ERC721 on this domain.\",\"_minGasLimit\":\"Minimum gas limit for the bridge message on the other domain.\",\"_remoteToken\":\"Address of the ERC721 on the remote domain.\",\"_tokenId\":\"Token ID to bridge.\"}},\"bridgeERC721To(address,address,address,uint256,uint32,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to the other chain. Data supplied here will not be used to execute any code on the other chain and is only emitted as extra data for the convenience of off-chain tooling.\",\"_localToken\":\"Address of the ERC721 on this domain.\",\"_minGasLimit\":\"Minimum gas limit for the bridge message on the other domain.\",\"_remoteToken\":\"Address of the ERC721 on the remote domain.\",\"_to\":\"Address to receive the token on the other domain.\",\"_tokenId\":\"Token ID to bridge.\"}},\"constructor\":{\"params\":{\"_messenger\":\"Address of the CrossDomainMessenger on this network.\"}},\"finalizeBridgeERC721(address,address,address,address,uint256,bytes)\":{\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_from\":\"Address that triggered the bridge on the other domain.\",\"_localToken\":\"Address of the ERC721 token on this domain.\",\"_remoteToken\":\"Address of the ERC721 token on the other domain.\",\"_to\":\"Address to receive the token on this domain.\",\"_tokenId\":\"ID of the token being deposited.\"}},\"initialize(address)\":{\"params\":{\"_superchainConfig\":\"Address of the SuperchainConfig contract on this network.\"}},\"messenger()\":{\"returns\":{\"_0\":\"Messenger contract on this domain.\"}},\"otherBridge()\":{\"returns\":{\"_0\":\"Address of the bridge on the other network.\"}},\"paused()\":{\"returns\":{\"_0\":\"Whether or not the contract is paused.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSENGER()\":{\"notice\":\"Messenger contract on this domain. This will be removed in the future, use `messenger` instead.\"},\"OTHER_BRIDGE()\":{\"notice\":\"Address of the bridge on the other network. This will be removed in the future, use `otherBridge` instead.\"},\"bridgeERC721(address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to the caller's account on the other chain. Note that this function can only be called by EOAs. Smart contract wallets should use the `bridgeERC721To` function after ensuring that the recipient address on the remote chain exists. Also note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2.\"},\"bridgeERC721To(address,address,address,uint256,uint32,bytes)\":{\"notice\":\"Initiates a bridge of an NFT to some recipient's account on the other chain. Note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2.\"},\"constructor\":{\"notice\":\"Constructs the L1ERC721Bridge contract.\"},\"deposits(address,address,uint256)\":{\"notice\":\"Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token by ID was deposited for a given L2 token.\"},\"finalizeBridgeERC721(address,address,address,address,uint256,bytes)\":{\"notice\":\"Completes an ERC721 bridge from the other domain and sends the ERC721 token to the recipient on this domain.\"},\"initialize(address)\":{\"notice\":\"Initializes the contract.\"},\"messenger()\":{\"notice\":\"Legacy getter for messenger contract.\"},\"otherBridge()\":{\"notice\":\"Legacy getter for other bridge address.\"},\"paused()\":{\"notice\":\"This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op.\"},\"superchainConfig()\":{\"notice\":\"Address of the SuperchainConfig contract.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1ERC721Bridge.sol\":\"L1ERC721Bridge\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol\":{\"keccak256\":\"0xed6a749c5373af398105ce6ee3ac4763aa450ea7285d268c85d9eeca809cdb1f\",\"urls\":[\"bzz-raw://20a97f891d06f0fe91560ea1a142aaa26fdd22bed1b51606b7d48f670deeb50f\",\"dweb:/ipfs/QmTbCtZKChpaX5H2iRiTDMcSz29GSLCpTCDgJpcMR4wg8x\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Enumerable.sol\":{\"keccak256\":\"0xd1556954440b31c97a142c6ba07d5cade45f96fafd52091d33a14ebe365aecbf\",\"urls\":[\"bzz-raw://26fef835622b46a5ba08b3ef6b46a22e94b5f285d0f0fb66b703bd30217d2c34\",\"dweb:/ipfs/QmZ548qdwfL1qF7aXz3xh1GCdTiST81kGGuKRqVUfYmPZR\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1ERC721Bridge.sol\":{\"keccak256\":\"0x533c336296674ded2bde8d3ca4a8b75d535732bbca50d065f8687246170a9c37\",\"urls\":[\"bzz-raw://281df98c7080584720850c67449d3a97736320ff41ba6151d919e963e8a7ac00\",\"dweb:/ipfs/QmVqBHoLygqn7PWcEq3taTH9WHnsr1pPWi2ferwrf7dPHz\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0x4a03e4a42900cecb4e923b92a7a10edb367347260bf38a937ce31826f1644330\",\"urls\":[\"bzz-raw://29dbfb9f323dfb9c4ce23c27a876dd7caddda6a3a5d483429cda433021d9f145\",\"dweb:/ipfs/QmZff2htQcExkwLdoGZ6e81zCFeGZV8oXgn4BhpW8Sccq7\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x3dd454d7ec9e2a90a6daf4b0c2f9ba371eae564b6e535aa88884e50de7df340a\",\"urls\":[\"bzz-raw://710bcccf6a1071171c45c2594e896ef5a26080a00dd3586e9ce80148a731d55b\",\"dweb:/ipfs/QmRSSYggh5woP8Xd9SHhuNt6tF7hMaSUMMk8W5zWk34NeL\"],\"license\":\"MIT\"},\"src/L2/L2ERC721Bridge.sol\":{\"keccak256\":\"0x55561c9ff8fa5c2436c03c7da90dfb9c46523b77c7992481bc7487415bcbfb46\",\"urls\":[\"bzz-raw://5c1fb7b3e06cca1555ecca7a523d7fd9f7482114f680e663387925b05616ab64\",\"dweb:/ipfs/QmRXVR1jfYWfBAXWrr8aMS9mMaLtrmckR2agJkrq32TVkV\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x75408c79fd51bd6f53ab1ad1719ec09264d1e6965cd5604c8346fbee76039fc3\",\"urls\":[\"bzz-raw://100be0dc2c772b569820b3c0828fac21fb241773c586eb8e789b4ddbca89f4f8\",\"dweb:/ipfs/QmW8NrsSeu1kYkga5cdjuzQ853dZZKFY22ZaycoHwiStbw\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x7ce27a05552aa69afa6b2ab6684dfe99f27366cf8ef2046baeb1fb62fff0022f\",\"urls\":[\"bzz-raw://a6a24f3ed56681720707a5ab0372fd67fcb1a4f6fb072c7140cda28bdb70f269\",\"dweb:/ipfs/QmW9uTpUULV4xmP7A7MoBDeDhVfQgmJG5qVUFGtXxWpWWK\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x62e11a169b3fa987af2427bf5117612e2770d4cca51565e6bbfe255ff7ffc4bb\",\"urls\":[\"bzz-raw://c852c8c0571bb22d9f28d577620a71de5ee60eb0c7ab8c68645da9a7295d24a0\",\"dweb:/ipfs/QmdixJ2dpsz8N8CgZz8z1MkZNVjw6ZkRM6bS7mchPYX6Yi\"],\"license\":\"MIT\"},\"src/universal/ERC721Bridge.sol\":{\"keccak256\":\"0x70aacc49b94ab1f43a5737046ee0b95b8774a3756d0f2d2fcfdedc541ae9344a\",\"urls\":[\"bzz-raw://cbc8abe6b65c32cfec535a7bb080ad20963ffd91682718477cb5be3990bf4e06\",\"dweb:/ipfs/QmeBZRzZrSYVN1jiS9ohEMaNM9WgL9FuivC6tcvipZ9rv7\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC721.sol\":{\"keccak256\":\"0xb3a65b067e67a9e1fa0493401c8d247970377c6725eba4e7b02ce8099c4f4f52\",\"urls\":[\"bzz-raw://86bb6864027560ade2f4ced6a6e34213cbff8002977dc365377e5a0b473cf17b\",\"dweb:/ipfs/QmQvjtodTK27as1g1PzsYk9NyJJ3X6a6251o1vrBwx7DPT\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 7, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 45409, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 45412, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 89957, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)48_storage" - }, - { - "astId": 72366, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "deposits", - "offset": 0, - "slot": "49", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))" - }, - { - "astId": 72370, - "contract": "src/L1/L1ERC721Bridge.sol:L1ERC721Bridge", - "label": "superchainConfig", - "offset": 0, - "slot": "50", - "type": "t_contract(SuperchainConfig)75085" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)48_storage": { - "encoding": "inplace", - "label": "uint256[48]", - "numberOfBytes": "1536", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(SuperchainConfig)75085": { - "encoding": "inplace", - "label": "contract SuperchainConfig", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => mapping(uint256 => bool)))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_bool))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(uint256 => bool))", - "numberOfBytes": "32", - "value": "t_mapping(t_uint256,t_bool)" - }, - "t_mapping(t_uint256,t_bool)": { - "encoding": "mapping", - "key": "t_uint256", - "label": "mapping(uint256 => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x7296f0a3d2b5890b4b05f0b445bc7dd4e8873c99d5574e27a37da7969218f0ab", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MESSENGER()": { - "notice": "Messenger contract on this domain. This will be removed in the future, use `messenger` instead." - }, - "OTHER_BRIDGE()": { - "notice": "Address of the bridge on the other network. This will be removed in the future, use `otherBridge` instead." - }, - "bridgeERC721(address,address,uint256,uint32,bytes)": { - "notice": "Initiates a bridge of an NFT to the caller's account on the other chain. Note that this function can only be called by EOAs. Smart contract wallets should use the `bridgeERC721To` function after ensuring that the recipient address on the remote chain exists. Also note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2." - }, - "bridgeERC721To(address,address,address,uint256,uint32,bytes)": { - "notice": "Initiates a bridge of an NFT to some recipient's account on the other chain. Note that the current owner of the token on this chain must approve this contract to operate the NFT before it can be bridged. **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This bridge only supports ERC721s originally deployed on Ethereum. Users will need to wait for the one-week challenge period to elapse before their Optimism-native NFT can be refunded on L2." - }, - "constructor": { - "notice": "Constructs the L1ERC721Bridge contract." - }, - "deposits(address,address,uint256)": { - "notice": "Mapping of L1 token to L2 token to ID to boolean, indicating if the given L1 token by ID was deposited for a given L2 token." - }, - "finalizeBridgeERC721(address,address,address,address,uint256,bytes)": { - "notice": "Completes an ERC721 bridge from the other domain and sends the ERC721 token to the recipient on this domain." - }, - "initialize(address)": { - "notice": "Initializes the contract." - }, - "messenger()": { - "notice": "Legacy getter for messenger contract." - }, - "otherBridge()": { - "notice": "Legacy getter for other bridge address." - }, - "paused()": { - "notice": "This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op." - }, - "superchainConfig()": { - "notice": "Address of the SuperchainConfig contract." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "ERC721BridgeFinalized(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC721 bridge from the other network is finalized." - }, - "ERC721BridgeInitiated(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC721 bridge to the other network is initiated." - } - }, - "notice": "The L1 ERC721 bridge is a contract which works together with the L2 ERC721 bridge to make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract acts as an escrow for ERC721 tokens deposited into L2." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/sepolia/L1StandardBridge.json b/packages/contracts-bedrock/deployments/sepolia/L1StandardBridge.json deleted file mode 100644 index a3cc48288b1a..000000000000 --- a/packages/contracts-bedrock/deployments/sepolia/L1StandardBridge.json +++ /dev/null @@ -1,1215 +0,0 @@ -{ - "abi": [ - { - "inputs": [ - { - "internalType": "address payable", - "name": "_messenger", - "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": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20BridgeFinalized", - "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": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20BridgeInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l1Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20DepositInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l1Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20WithdrawalFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHBridgeFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHBridgeInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHDepositInitiated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ETHWithdrawalFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "inputs": [], - "name": "MESSENGER", - "outputs": [ - { - "internalType": "contract CrossDomainMessenger", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OTHER_BRIDGE", - "outputs": [ - { - "internalType": "contract StandardBridge", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_localToken", - "type": "address" - }, - { - "internalType": "address", - "name": "_remoteToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeERC20", - "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": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeERC20To", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeETH", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "bridgeETHTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "depositERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "depositERC20To", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "depositETH", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "depositETHTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "deposits", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "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": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeBridgeERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeBridgeETH", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeERC20Withdrawal", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeETHWithdrawal", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract SuperchainConfig", - "name": "_superchainConfig", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l2TokenBridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "messenger", - "outputs": [ - { - "internalType": "contract CrossDomainMessenger", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "otherBridge", - "outputs": [ - { - "internalType": "contract StandardBridge", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "superchainConfig", - "outputs": [ - { - "internalType": "contract SuperchainConfig", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "address": "0xE19C7a2C0Bb32287731Ea75dA9B1C836815964F1", - "args": [ - "0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef" - ], - "bytecode": "0x60c06040523480156200001157600080fd5b5060405162002eed38038062002eed8339810160408190526200003491620001be565b6001600160a01b03811660805273420000000000000000000000000000000000001060a0526200006560006200006c565b50620001f0565b600054610100900460ff16158080156200008d5750600054600160ff909116105b80620000bd5750620000aa30620001af60201b6200056f1760201c565b158015620000bd575060005460ff166001145b620001255760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff19166001179055801562000149576000805461ff0019166101001790555b603280546001600160a01b0319166001600160a01b0384161790558015620001ab576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600060208284031215620001d157600080fd5b81516001600160a01b0381168114620001e957600080fd5b9392505050565b60805160a051612c7c62000271600039600081816103e70152818161049e015281816105e001528181610b30015281816117070152611db90152600081816102f6015281816104d4015281816105b60152818161061701528181610b0601528181610b6701528181610e63015281816116ca0152611d7d0152612c7c6000f3fe6080604052600436106101795760003560e01c8063838b2520116100cb5780639a2ac6d51161007f578063c4d66de811610059578063c4d66de81461053c578063c89701a21461048f578063e11013dd1461055c57600080fd5b80639a2ac6d5146104f6578063a9f9e67514610509578063b1a1a8821461052957600080fd5b80638f601f66116100b05780638f601f661461044957806391c49bf81461048f578063927ede2d146104c257600080fd5b8063838b252014610409578063870876231461042957600080fd5b80633cb747bf1161012d57806358a997f61161010757806358a997f6146103905780635c975abb146103b05780637f46ddb2146103d557600080fd5b80633cb747bf146102e7578063540abf731461031a57806354fd4d501461033a57600080fd5b80631532ec341161015e5780631532ec341461026a5780631635f5fd1461027d57806335e80ab31461029057600080fd5b80630166a07a1461023757806309fc88431461025757600080fd5b3661023257333b15610212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b610230333362030d406040518060200160405280600081525061058b565b005b600080fd5b34801561024357600080fd5b506102306102523660046126c3565b61059e565b610230610265366004612774565b610a03565b6102306102783660046127c7565b610ada565b61023061028b3660046127c7565b610aee565b34801561029c57600080fd5b506032546102bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102f357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102bd565b34801561032657600080fd5b5061023061033536600461283a565b611032565b34801561034657600080fd5b506103836040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516102de9190612927565b34801561039c57600080fd5b506102306103ab36600461293a565b611077565b3480156103bc57600080fd5b506103c561114b565b60405190151581526020016102de565b3480156103e157600080fd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561041557600080fd5b5061023061042436600461283a565b6111e4565b34801561043557600080fd5b5061023061044436600461293a565b611229565b34801561045557600080fd5b506104816104643660046129bd565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102de565b34801561049b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102bd565b3480156104ce57600080fd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b6102306105043660046129f6565b6112fd565b34801561051557600080fd5b506102306105243660046126c3565b61133f565b610230610537366004612774565b61134e565b34801561054857600080fd5b50610230610557366004612a59565b61141f565b61023061056a3660046129f6565b6115ea565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b610598848434858561162d565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156106bc57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a49190612a76565b73ffffffffffffffffffffffffffffffffffffffff16145b61076e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b61077661114b565b156107dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b6107e687611811565b15610934576107f58787611873565b6108a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561091757600080fd5b505af115801561092b573d6000803e3d6000fd5b505050506109b6565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610972908490612ac2565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556109b6908585611993565b6109fa878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a6792505050565b50505050505050565b333b15610a92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610ad53333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162d92505050565b505050565b610ae78585858585610aee565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015610c0c57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190612a76565b73ffffffffffffffffffffffffffffffffffffffff16145b610cbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b610cc661114b565b15610d2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b823414610dbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610209565b3073ffffffffffffffffffffffffffffffffffffffff851603610e61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610209565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610f3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610209565b610f7e85858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611af592505050565b6000610f9b855a8660405180602001604052806000815250611b68565b90508061102a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610209565b505050505050565b6109fa87873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8292505050565b333b15611106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b61102a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ec992505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111df9190612ad9565b905090565b6109fa87873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ec992505050565b333b156112b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b61102a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8292505050565b61059833858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058b92505050565b6109fa8787878787878761059e565b333b156113dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610ad533338585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058b92505050565b600054610100900460ff161580801561143f5750600054600160ff909116105b806114595750303b158015611459575060005460ff166001145b6114e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610209565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561154357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156115e657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6105983385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162d92505050565b8234146116bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610209565b6116c885858584611ed8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b847f0000000000000000000000000000000000000000000000000000000000000000631635f5fd60e01b898989886040516024016117459493929190612afb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526117d892918890600401612b44565b6000604051808303818588803b1580156117f157600080fd5b505af1158015611805573d6000803e3d6000fd5b50505050505050505050565b600061183d827f1d1d8b6300000000000000000000000000000000000000000000000000000000611f4b565b8061186d575061186d827fec4fc8e300000000000000000000000000000000000000000000000000000000611f4b565b92915050565b600061189f837f1d1d8b6300000000000000000000000000000000000000000000000000000000611f4b565b15611948578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119139190612a76565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905061186d565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610ad59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611f6e565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611adf93929190612b89565b60405180910390a461102a86868686868661207a565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611b54929190612bc7565b60405180910390a361059884848484612102565b600080600080845160208601878a8af19695505050505050565b611b8b87611811565b15611cd957611b9a8787611873565b611c4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611cbc57600080fd5b505af1158015611cd0573d6000803e3d6000fd5b50505050611d6d565b611cfb73ffffffffffffffffffffffffffffffffffffffff881686308661216f565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611d39908490612be0565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611d7b8787878787866121cd565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b7f0000000000000000000000000000000000000000000000000000000000000000630166a07a60e01b898b8a8a8a89604051602401611dfb96959493929190612bf8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611e8e92918790600401612b44565b600060405180830381600087803b158015611ea857600080fd5b505af1158015611ebc573d6000803e3d6000fd5b5050505050505050505050565b6109fa87878787878787611b82565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611f37929190612bc7565b60405180910390a36105988484848461225b565b6000611f56836122ba565b8015611f675750611f67838361231e565b9392505050565b6000611fd0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123ed9092919063ffffffff16565b805190915015610ad55780806020019051810190611fee9190612ad9565b610ad5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610209565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd8686866040516120f293929190612b89565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051612161929190612bc7565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105989085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016119e5565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161224593929190612b89565b60405180910390a461102a868686868686612404565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051612161929190612bc7565b60006122e6827f01ffc9a70000000000000000000000000000000000000000000000000000000061231e565b801561186d5750612317827fffffffff0000000000000000000000000000000000000000000000000000000061231e565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156123d6575060208210155b80156123e25750600081115b979650505050505050565b60606123fc848460008561247c565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf8686866040516120f293929190612b89565b60608247101561250e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610209565b73ffffffffffffffffffffffffffffffffffffffff85163b61258c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610209565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125b59190612c53565b60006040518083038185875af1925050503d80600081146125f2576040519150601f19603f3d011682016040523d82523d6000602084013e6125f7565b606091505b50915091506123e282828660608315612611575081611f67565b8251156126215782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102099190612927565b73ffffffffffffffffffffffffffffffffffffffff8116811461267757600080fd5b50565b60008083601f84011261268c57600080fd5b50813567ffffffffffffffff8111156126a457600080fd5b6020830191508360208285010111156126bc57600080fd5b9250929050565b600080600080600080600060c0888a0312156126de57600080fd5b87356126e981612655565b965060208801356126f981612655565b9550604088013561270981612655565b9450606088013561271981612655565b93506080880135925060a088013567ffffffffffffffff81111561273c57600080fd5b6127488a828b0161267a565b989b979a50959850939692959293505050565b803563ffffffff8116811461276f57600080fd5b919050565b60008060006040848603121561278957600080fd5b6127928461275b565b9250602084013567ffffffffffffffff8111156127ae57600080fd5b6127ba8682870161267a565b9497909650939450505050565b6000806000806000608086880312156127df57600080fd5b85356127ea81612655565b945060208601356127fa81612655565b935060408601359250606086013567ffffffffffffffff81111561281d57600080fd5b6128298882890161267a565b969995985093965092949392505050565b600080600080600080600060c0888a03121561285557600080fd5b873561286081612655565b9650602088013561287081612655565b9550604088013561288081612655565b9450606088013593506128956080890161275b565b925060a088013567ffffffffffffffff81111561273c57600080fd5b60005b838110156128cc5781810151838201526020016128b4565b838111156105985750506000910152565b600081518084526128f58160208601602086016128b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f6760208301846128dd565b60008060008060008060a0878903121561295357600080fd5b863561295e81612655565b9550602087013561296e81612655565b9450604087013593506129836060880161275b565b9250608087013567ffffffffffffffff81111561299f57600080fd5b6129ab89828a0161267a565b979a9699509497509295939492505050565b600080604083850312156129d057600080fd5b82356129db81612655565b915060208301356129eb81612655565b809150509250929050565b60008060008060608587031215612a0c57600080fd5b8435612a1781612655565b9350612a256020860161275b565b9250604085013567ffffffffffffffff811115612a4157600080fd5b612a4d8782880161267a565b95989497509550505050565b600060208284031215612a6b57600080fd5b8135611f6781612655565b600060208284031215612a8857600080fd5b8151611f6781612655565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612ad457612ad4612a93565b500390565b600060208284031215612aeb57600080fd5b81518015158114611f6757600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612b3a60808301846128dd565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612b7360608301856128dd565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612bbe60608301846128dd565b95945050505050565b8281526040602082015260006123fc60408301846128dd565b60008219821115612bf357612bf3612a93565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612c4760c08301846128dd565b98975050505050505050565b60008251612c658184602087016128b1565b919091019291505056fea164736f6c634300080f000a", - "deployedBytecode": "0x6080604052600436106101795760003560e01c8063838b2520116100cb5780639a2ac6d51161007f578063c4d66de811610059578063c4d66de81461053c578063c89701a21461048f578063e11013dd1461055c57600080fd5b80639a2ac6d5146104f6578063a9f9e67514610509578063b1a1a8821461052957600080fd5b80638f601f66116100b05780638f601f661461044957806391c49bf81461048f578063927ede2d146104c257600080fd5b8063838b252014610409578063870876231461042957600080fd5b80633cb747bf1161012d57806358a997f61161010757806358a997f6146103905780635c975abb146103b05780637f46ddb2146103d557600080fd5b80633cb747bf146102e7578063540abf731461031a57806354fd4d501461033a57600080fd5b80631532ec341161015e5780631532ec341461026a5780631635f5fd1461027d57806335e80ab31461029057600080fd5b80630166a07a1461023757806309fc88431461025757600080fd5b3661023257333b15610212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b610230333362030d406040518060200160405280600081525061058b565b005b600080fd5b34801561024357600080fd5b506102306102523660046126c3565b61059e565b610230610265366004612774565b610a03565b6102306102783660046127c7565b610ada565b61023061028b3660046127c7565b610aee565b34801561029c57600080fd5b506032546102bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102f357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102bd565b34801561032657600080fd5b5061023061033536600461283a565b611032565b34801561034657600080fd5b506103836040518060400160405280600581526020017f322e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516102de9190612927565b34801561039c57600080fd5b506102306103ab36600461293a565b611077565b3480156103bc57600080fd5b506103c561114b565b60405190151581526020016102de565b3480156103e157600080fd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561041557600080fd5b5061023061042436600461283a565b6111e4565b34801561043557600080fd5b5061023061044436600461293a565b611229565b34801561045557600080fd5b506104816104643660046129bd565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102de565b34801561049b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102bd565b3480156104ce57600080fd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b6102306105043660046129f6565b6112fd565b34801561051557600080fd5b506102306105243660046126c3565b61133f565b610230610537366004612774565b61134e565b34801561054857600080fd5b50610230610557366004612a59565b61141f565b61023061056a3660046129f6565b6115ea565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b610598848434858561162d565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156106bc57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610680573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a49190612a76565b73ffffffffffffffffffffffffffffffffffffffff16145b61076e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b61077661114b565b156107dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b6107e687611811565b15610934576107f58787611873565b6108a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561091757600080fd5b505af115801561092b573d6000803e3d6000fd5b505050506109b6565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610972908490612ac2565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556109b6908585611993565b6109fa878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a6792505050565b50505050505050565b333b15610a92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610ad53333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162d92505050565b505050565b610ae78585858585610aee565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015610c0c57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190612a76565b73ffffffffffffffffffffffffffffffffffffffff16145b610cbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b610cc661114b565b15610d2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b823414610dbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610209565b3073ffffffffffffffffffffffffffffffffffffffff851603610e61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610209565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610f3c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610209565b610f7e85858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611af592505050565b6000610f9b855a8660405180602001604052806000815250611b68565b90508061102a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610209565b505050505050565b6109fa87873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8292505050565b333b15611106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b61102a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ec992505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111df9190612ad9565b905090565b6109fa87873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ec992505050565b333b156112b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b61102a86863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8292505050565b61059833858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058b92505050565b6109fa8787878787878761059e565b333b156113dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610ad533338585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058b92505050565b600054610100900460ff161580801561143f5750600054600160ff909116105b806114595750303b158015611459575060005460ff166001145b6114e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610209565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561154357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156115e657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6105983385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061162d92505050565b8234146116bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610209565b6116c885858584611ed8565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b847f0000000000000000000000000000000000000000000000000000000000000000631635f5fd60e01b898989886040516024016117459493929190612afb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526117d892918890600401612b44565b6000604051808303818588803b1580156117f157600080fd5b505af1158015611805573d6000803e3d6000fd5b50505050505050505050565b600061183d827f1d1d8b6300000000000000000000000000000000000000000000000000000000611f4b565b8061186d575061186d827fec4fc8e300000000000000000000000000000000000000000000000000000000611f4b565b92915050565b600061189f837f1d1d8b6300000000000000000000000000000000000000000000000000000000611f4b565b15611948578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119139190612a76565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905061186d565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610ad59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611f6e565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611adf93929190612b89565b60405180910390a461102a86868686868661207a565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611b54929190612bc7565b60405180910390a361059884848484612102565b600080600080845160208601878a8af19695505050505050565b611b8b87611811565b15611cd957611b9a8787611873565b611c4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611cbc57600080fd5b505af1158015611cd0573d6000803e3d6000fd5b50505050611d6d565b611cfb73ffffffffffffffffffffffffffffffffffffffff881686308661216f565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611d39908490612be0565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611d7b8787878787866121cd565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633dbb202b7f0000000000000000000000000000000000000000000000000000000000000000630166a07a60e01b898b8a8a8a89604051602401611dfb96959493929190612bf8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611e8e92918790600401612b44565b600060405180830381600087803b158015611ea857600080fd5b505af1158015611ebc573d6000803e3d6000fd5b5050505050505050505050565b6109fa87878787878787611b82565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611f37929190612bc7565b60405180910390a36105988484848461225b565b6000611f56836122ba565b8015611f675750611f67838361231e565b9392505050565b6000611fd0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123ed9092919063ffffffff16565b805190915015610ad55780806020019051810190611fee9190612ad9565b610ad5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610209565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd8686866040516120f293929190612b89565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d8484604051612161929190612bc7565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105989085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016119e5565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161224593929190612b89565b60405180910390a461102a868686868686612404565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af58484604051612161929190612bc7565b60006122e6827f01ffc9a70000000000000000000000000000000000000000000000000000000061231e565b801561186d5750612317827fffffffff0000000000000000000000000000000000000000000000000000000061231e565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156123d6575060208210155b80156123e25750600081115b979650505050505050565b60606123fc848460008561247c565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf8686866040516120f293929190612b89565b60608247101561250e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610209565b73ffffffffffffffffffffffffffffffffffffffff85163b61258c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610209565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125b59190612c53565b60006040518083038185875af1925050503d80600081146125f2576040519150601f19603f3d011682016040523d82523d6000602084013e6125f7565b606091505b50915091506123e282828660608315612611575081611f67565b8251156126215782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102099190612927565b73ffffffffffffffffffffffffffffffffffffffff8116811461267757600080fd5b50565b60008083601f84011261268c57600080fd5b50813567ffffffffffffffff8111156126a457600080fd5b6020830191508360208285010111156126bc57600080fd5b9250929050565b600080600080600080600060c0888a0312156126de57600080fd5b87356126e981612655565b965060208801356126f981612655565b9550604088013561270981612655565b9450606088013561271981612655565b93506080880135925060a088013567ffffffffffffffff81111561273c57600080fd5b6127488a828b0161267a565b989b979a50959850939692959293505050565b803563ffffffff8116811461276f57600080fd5b919050565b60008060006040848603121561278957600080fd5b6127928461275b565b9250602084013567ffffffffffffffff8111156127ae57600080fd5b6127ba8682870161267a565b9497909650939450505050565b6000806000806000608086880312156127df57600080fd5b85356127ea81612655565b945060208601356127fa81612655565b935060408601359250606086013567ffffffffffffffff81111561281d57600080fd5b6128298882890161267a565b969995985093965092949392505050565b600080600080600080600060c0888a03121561285557600080fd5b873561286081612655565b9650602088013561287081612655565b9550604088013561288081612655565b9450606088013593506128956080890161275b565b925060a088013567ffffffffffffffff81111561273c57600080fd5b60005b838110156128cc5781810151838201526020016128b4565b838111156105985750506000910152565b600081518084526128f58160208601602086016128b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f6760208301846128dd565b60008060008060008060a0878903121561295357600080fd5b863561295e81612655565b9550602087013561296e81612655565b9450604087013593506129836060880161275b565b9250608087013567ffffffffffffffff81111561299f57600080fd5b6129ab89828a0161267a565b979a9699509497509295939492505050565b600080604083850312156129d057600080fd5b82356129db81612655565b915060208301356129eb81612655565b809150509250929050565b60008060008060608587031215612a0c57600080fd5b8435612a1781612655565b9350612a256020860161275b565b9250604085013567ffffffffffffffff811115612a4157600080fd5b612a4d8782880161267a565b95989497509550505050565b600060208284031215612a6b57600080fd5b8135611f6781612655565b600060208284031215612a8857600080fd5b8151611f6781612655565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612ad457612ad4612a93565b500390565b600060208284031215612aeb57600080fd5b81518015158114611f6757600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612b3a60808301846128dd565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612b7360608301856128dd565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612bbe60608301846128dd565b95945050505050565b8281526040602082015260006123fc60408301846128dd565b60008219821115612bf357612bf3612a93565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612c4760c08301846128dd565b98975050505050505050565b60008251612c658184602087016128b1565b919091019291505056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "bridgeERC20(address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of local tokens to deposit.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_localToken": "Address of the ERC20 on this chain.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", - "_remoteToken": "Address of the corresponding token on the remote chain." - } - }, - "bridgeERC20To(address,address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of local tokens to deposit.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_localToken": "Address of the ERC20 on this chain.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", - "_remoteToken": "Address of the corresponding token on the remote chain.", - "_to": "Address of the receiver." - } - }, - "bridgeETH(uint32,bytes)": { - "params": { - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with." - } - }, - "bridgeETHTo(address,uint32,bytes)": { - "params": { - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_minGasLimit": "Minimum amount of gas that the bridge can be relayed with.", - "_to": "Address of the receiver." - } - }, - "constructor": { - "params": { - "_messenger": "Address of the L1CrossDomainMessenger." - } - }, - "depositERC20(address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of the ERC20 to deposit.", - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_l1Token": "Address of the L1 token being deposited.", - "_l2Token": "Address of the corresponding token on L2.", - "_minGasLimit": "Minimum gas limit for the deposit message on L2." - } - }, - "depositERC20To(address,address,address,uint256,uint32,bytes)": { - "params": { - "_amount": "Amount of the ERC20 to deposit.", - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_l1Token": "Address of the L1 token being deposited.", - "_l2Token": "Address of the corresponding token on L2.", - "_minGasLimit": "Minimum gas limit for the deposit message on L2.", - "_to": "Address of the recipient on L2." - } - }, - "depositETH(uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_minGasLimit": "Minimum gas limit for the deposit message on L2." - } - }, - "depositETHTo(address,uint32,bytes)": { - "params": { - "_extraData": "Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.", - "_minGasLimit": "Minimum gas limit for the deposit message on L2.", - "_to": "Address of the recipient on L2." - } - }, - "finalizeBridgeERC20(address,address,address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of the ERC20 being bridged.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_from": "Address of the sender.", - "_localToken": "Address of the ERC20 on this chain.", - "_remoteToken": "Address of the corresponding token on the remote chain.", - "_to": "Address of the receiver." - } - }, - "finalizeBridgeETH(address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of ETH being bridged.", - "_extraData": "Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.", - "_from": "Address of the sender.", - "_to": "Address of the receiver." - } - }, - "finalizeERC20Withdrawal(address,address,address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of the ERC20 to withdraw.", - "_extraData": "Optional data forwarded from L2.", - "_from": "Address of the withdrawer on L2.", - "_l1Token": "Address of the token on L1.", - "_l2Token": "Address of the corresponding token on L2.", - "_to": "Address of the recipient on L1." - } - }, - "finalizeETHWithdrawal(address,address,uint256,bytes)": { - "params": { - "_amount": "Amount of ETH to withdraw.", - "_extraData": "Optional data forwarded from L2.", - "_from": "Address of the withdrawer on L2.", - "_to": "Address of the recipient on L1." - } - }, - "initialize(address)": { - "params": { - "_superchainConfig": "Address of the SuperchainConfig contract on this network." - } - }, - "l2TokenBridge()": { - "returns": { - "_0": "Address of the corresponding L2 bridge contract." - } - }, - "messenger()": { - "returns": { - "_0": "Messenger contract on this domain." - } - }, - "otherBridge()": { - "returns": { - "_0": "The bridge contract on the other network." - } - }, - "paused()": { - "returns": { - "_0": "Whether or not the contract is paused." - } - } - }, - "events": { - "ERC20DepositInitiated(address,address,address,address,uint256,bytes)": { - "params": { - "amount": "Amount of the ERC20 deposited.", - "extraData": "Extra data attached to the deposit.", - "from": "Address of the depositor.", - "l1Token": "Address of the token on L1.", - "l2Token": "Address of the corresponding token on L2.", - "to": "Address of the recipient on L2." - } - }, - "ERC20WithdrawalFinalized(address,address,address,address,uint256,bytes)": { - "params": { - "amount": "Amount of the ERC20 withdrawn.", - "extraData": "Extra data attached to the withdrawal.", - "from": "Address of the withdrawer.", - "l1Token": "Address of the token on L1.", - "l2Token": "Address of the corresponding token on L2.", - "to": "Address of the recipient on L1." - } - }, - "ETHDepositInitiated(address,address,uint256,bytes)": { - "params": { - "amount": "Amount of ETH deposited.", - "extraData": "Extra data attached to the deposit.", - "from": "Address of the depositor.", - "to": "Address of the recipient on L2." - } - }, - "ETHWithdrawalFinalized(address,address,uint256,bytes)": { - "params": { - "amount": "Amount of ETH withdrawn.", - "extraData": "Extra data attached to the withdrawal.", - "from": "Address of the withdrawer.", - "to": "Address of the recipient on L1." - } - } - } - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_messenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20BridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20BridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20DepositInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ERC20WithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHBridgeFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHBridgeInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHDepositInitiated\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ETHWithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"OTHER_BRIDGE\",\"outputs\":[{\"internalType\":\"contract StandardBridge\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"bridgeERC20To\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"bridgeETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"bridgeETHTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"depositERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"depositERC20To\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_minGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositETHTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeBridgeERC20\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"finalizeBridgeETH\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeERC20Withdrawal\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"finalizeETHWithdrawal\"},{\"inputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"_superchainConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2TokenBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"messenger\",\"outputs\":[{\"internalType\":\"contract CrossDomainMessenger\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"otherBridge\",\"outputs\":[{\"internalType\":\"contract StandardBridge\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"superchainConfig\",\"outputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"bridgeERC20(address,address,uint256,uint32,bytes)\":{\"params\":{\"_amount\":\"Amount of local tokens to deposit.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\"}},\"bridgeERC20To(address,address,address,uint256,uint32,bytes)\":{\"params\":{\"_amount\":\"Amount of local tokens to deposit.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\",\"_to\":\"Address of the receiver.\"}},\"bridgeETH(uint32,bytes)\":{\"params\":{\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\"}},\"bridgeETHTo(address,uint32,bytes)\":{\"params\":{\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_minGasLimit\":\"Minimum amount of gas that the bridge can be relayed with.\",\"_to\":\"Address of the receiver.\"}},\"constructor\":{\"params\":{\"_messenger\":\"Address of the L1CrossDomainMessenger.\"}},\"depositERC20(address,address,uint256,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ERC20 tokens into the sender's account on L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to deposit.\",\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_l1Token\":\"Address of the L1 token being deposited.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\"}},\"depositERC20To(address,address,address,uint256,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ERC20 tokens into a target account on L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to deposit.\",\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_l1Token\":\"Address of the L1 token being deposited.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\",\"_to\":\"Address of the recipient on L2.\"}},\"depositETH(uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ETH into the sender's account on L2.\",\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\"}},\"depositETHTo(address,uint32,bytes)\":{\"custom:legacy\":\"@notice Deposits some amount of ETH into a target account on L2. Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will be locked in the L2StandardBridge. ETH may be recoverable if the call can be successfully replayed by increasing the amount of gas supplied to the call. If the call will fail for any amount of gas, then the ETH will be locked permanently.\",\"params\":{\"_extraData\":\"Optional data to forward to L2. Data supplied here will not be used to execute any code on L2 and is only emitted as extra data for the convenience of off-chain tooling.\",\"_minGasLimit\":\"Minimum gas limit for the deposit message on L2.\",\"_to\":\"Address of the recipient on L2.\"}},\"finalizeBridgeERC20(address,address,address,address,uint256,bytes)\":{\"params\":{\"_amount\":\"Amount of the ERC20 being bridged.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_from\":\"Address of the sender.\",\"_localToken\":\"Address of the ERC20 on this chain.\",\"_remoteToken\":\"Address of the corresponding token on the remote chain.\",\"_to\":\"Address of the receiver.\"}},\"finalizeBridgeETH(address,address,uint256,bytes)\":{\"params\":{\"_amount\":\"Amount of ETH being bridged.\",\"_extraData\":\"Extra data to be sent with the transaction. Note that the recipient will not be triggered with this data, but it will be emitted and can be used to identify the transaction.\",\"_from\":\"Address of the sender.\",\"_to\":\"Address of the receiver.\"}},\"finalizeERC20Withdrawal(address,address,address,address,uint256,bytes)\":{\"custom:legacy\":\"@notice Finalizes a withdrawal of ERC20 tokens from L2.\",\"params\":{\"_amount\":\"Amount of the ERC20 to withdraw.\",\"_extraData\":\"Optional data forwarded from L2.\",\"_from\":\"Address of the withdrawer on L2.\",\"_l1Token\":\"Address of the token on L1.\",\"_l2Token\":\"Address of the corresponding token on L2.\",\"_to\":\"Address of the recipient on L1.\"}},\"finalizeETHWithdrawal(address,address,uint256,bytes)\":{\"custom:legacy\":\"@notice Finalizes a withdrawal of ETH from L2.\",\"params\":{\"_amount\":\"Amount of ETH to withdraw.\",\"_extraData\":\"Optional data forwarded from L2.\",\"_from\":\"Address of the withdrawer on L2.\",\"_to\":\"Address of the recipient on L1.\"}},\"initialize(address)\":{\"params\":{\"_superchainConfig\":\"Address of the SuperchainConfig contract on this network.\"}},\"l2TokenBridge()\":{\"custom:legacy\":\"@notice Retrieves the access of the corresponding L2 bridge contract.\",\"returns\":{\"_0\":\"Address of the corresponding L2 bridge contract.\"}},\"messenger()\":{\"returns\":{\"_0\":\"Messenger contract on this domain.\"}},\"otherBridge()\":{\"returns\":{\"_0\":\"The bridge contract on the other network.\"}},\"paused()\":{\"returns\":{\"_0\":\"Whether or not the contract is paused.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MESSENGER()\":{\"notice\":\"Messenger contract on this domain.\"},\"OTHER_BRIDGE()\":{\"notice\":\"Corresponding bridge on the other domain.\"},\"bridgeERC20(address,address,uint256,uint32,bytes)\":{\"notice\":\"Sends ERC20 tokens to the sender's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain.\"},\"bridgeERC20To(address,address,address,uint256,uint32,bytes)\":{\"notice\":\"Sends ERC20 tokens to a receiver's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain.\"},\"bridgeETH(uint32,bytes)\":{\"notice\":\"Sends ETH to the sender's address on the other chain.\"},\"bridgeETHTo(address,uint32,bytes)\":{\"notice\":\"Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a smart contract and the call fails, the ETH will be temporarily locked in the StandardBridge on the other chain until the call is replayed. If the call cannot be replayed with any amount of gas (call always reverts), then the ETH will be permanently locked in the StandardBridge on the other chain. ETH will also be locked if the receiver is the other bridge, because finalizeBridgeETH will revert in that case.\"},\"constructor\":{\"notice\":\"Constructs the L1StandardBridge contract.\"},\"deposits(address,address)\":{\"notice\":\"Mapping that stores deposits for a given pair of local and remote tokens.\"},\"finalizeBridgeERC20(address,address,address,address,uint256,bytes)\":{\"notice\":\"Finalizes an ERC20 bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain.\"},\"finalizeBridgeETH(address,address,uint256,bytes)\":{\"notice\":\"Finalizes an ETH bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain.\"},\"initialize(address)\":{\"notice\":\"Initializes the contract.\"},\"messenger()\":{\"notice\":\"Getter for messenger contract.\"},\"otherBridge()\":{\"notice\":\"Getter for the other bridge.\"},\"paused()\":{\"notice\":\"This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op.\"},\"superchainConfig()\":{\"notice\":\"Address of the SuperchainConfig contract.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/L1StandardBridge.sol\":\"L1StandardBridge\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"keccak256\":\"0x24b04b8aacaaf1a4a0719117b29c9c3647b1f479c5ac2a60f5ff1bb6d839c238\",\"urls\":[\"bzz-raw://43e46da9d9f49741ecd876a269e71bc7494058d7a8e9478429998adb5bc3eaa0\",\"dweb:/ipfs/QmUtp4cqzf22C5rJ76AabKADquGWcjsc33yjYXxXC4sDvy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"urls\":[\"bzz-raw://b2717fd2bdac99daa960a6de500754ea1b932093c946388c381da48658234b95\",\"dweb:/ipfs/QmP6QVMn6UeA3ByahyJbYQr5M6coHKBKsf3ySZSfbyA8R7\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x032807210d1d7d218963d7355d62e021a84bf1b3339f4f50be2f63b53cccaf29\",\"urls\":[\"bzz-raw://11756f42121f6541a35a8339ea899ee7514cfaa2e6d740625fcc844419296aa6\",\"dweb:/ipfs/QmekMuk6BY4DAjzeXr4MSbKdgoqqsZnA8JPtuyWc6CwXHf\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0xc65c83c1039508fa7a42a09a3c6a32babd1c438ba4dbb23581255e784b5d5eed\",\"urls\":[\"bzz-raw://a1b3b38db0f76429db899909025e534c366415e9ea8b5ddc4c8901e6a7fc1461\",\"dweb:/ipfs/QmYv1KxyHjLEky9JWNSsSfpGJbiCxFyzVFgTwQKpiqYGUg\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L1StandardBridge.sol\":{\"keccak256\":\"0x2564decacc35545e2de52ea7793ceaa561ec4bc86fdd9d56b41c199cd6bca7ef\",\"urls\":[\"bzz-raw://6231b05c0c581b04536ac968ce053a99312d24e35defcd64b4f2cb8540ffe268\",\"dweb:/ipfs/QmRrq2Sguo4CyMyy8KPyXsGe4ULQr8Tm3919eRsvs3yPte\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0x4a03e4a42900cecb4e923b92a7a10edb367347260bf38a937ce31826f1644330\",\"urls\":[\"bzz-raw://29dbfb9f323dfb9c4ce23c27a876dd7caddda6a3a5d483429cda433021d9f145\",\"dweb:/ipfs/QmZff2htQcExkwLdoGZ6e81zCFeGZV8oXgn4BhpW8Sccq7\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x3dd454d7ec9e2a90a6daf4b0c2f9ba371eae564b6e535aa88884e50de7df340a\",\"urls\":[\"bzz-raw://710bcccf6a1071171c45c2594e896ef5a26080a00dd3586e9ce80148a731d55b\",\"dweb:/ipfs/QmRSSYggh5woP8Xd9SHhuNt6tF7hMaSUMMk8W5zWk34NeL\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/Predeploys.sol\":{\"keccak256\":\"0x75408c79fd51bd6f53ab1ad1719ec09264d1e6965cd5604c8346fbee76039fc3\",\"urls\":[\"bzz-raw://100be0dc2c772b569820b3c0828fac21fb241773c586eb8e789b4ddbca89f4f8\",\"dweb:/ipfs/QmW8NrsSeu1kYkga5cdjuzQ853dZZKFY22ZaycoHwiStbw\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x7ce27a05552aa69afa6b2ab6684dfe99f27366cf8ef2046baeb1fb62fff0022f\",\"urls\":[\"bzz-raw://a6a24f3ed56681720707a5ab0372fd67fcb1a4f6fb072c7140cda28bdb70f269\",\"dweb:/ipfs/QmW9uTpUULV4xmP7A7MoBDeDhVfQgmJG5qVUFGtXxWpWWK\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/universal/CrossDomainMessenger.sol\":{\"keccak256\":\"0x62e11a169b3fa987af2427bf5117612e2770d4cca51565e6bbfe255ff7ffc4bb\",\"urls\":[\"bzz-raw://c852c8c0571bb22d9f28d577620a71de5ee60eb0c7ab8c68645da9a7295d24a0\",\"dweb:/ipfs/QmdixJ2dpsz8N8CgZz8z1MkZNVjw6ZkRM6bS7mchPYX6Yi\"],\"license\":\"MIT\"},\"src/universal/IOptimismMintableERC20.sol\":{\"keccak256\":\"0x6f8133b39efcbcbd5088f195dfacf1bedc3146508429c3865443909af735a04c\",\"urls\":[\"bzz-raw://adc36971e2e120458769f050428d9d2b0504516660345020c2521ee46e6d8abf\",\"dweb:/ipfs/QmPbFusQkZgGKpU8Fv5JoqL4oVeJtM3yqnhRGLY9eZT5zZ\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/universal/OptimismMintableERC20.sol\":{\"keccak256\":\"0x18721f41a831ec39d47002e73ecc2aa3e6624f8d1ab7b9f25b53348e8b0765df\",\"urls\":[\"bzz-raw://2162fa7529a77b199a07f37fca26c778542f6c8805f0365f1ceef90c5cd3a3a7\",\"dweb:/ipfs/QmaMmHJS52Bp95AGnrjh1zV7fLLqV3uAbFzkVLziMnPJYa\"],\"license\":\"MIT\"},\"src/universal/StandardBridge.sol\":{\"keccak256\":\"0x84b8925a791503b39861a9bf692e45d149053922b1339abe4d13b633121f0493\",\"urls\":[\"bzz-raw://b71e4723358644d72b35442530abdbdfcb425d807c675ba0bf94c2b95632bff2\",\"dweb:/ipfs/QmaKMD4wkAdiGGBhG49AN62jzD5F5PLWcNKjMasLwyN2WE\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 7, - "receipt": { - "transactionHash": "0x5eca3b218f8833a01189c622ed0cbdfae939b84b5bc47dd51915d8b8083f72e6", - "transactionIndex": "0x14", - "blockHash": "0xa4cd57459cf08f021f24a1fbc15da572b6cd3e74932b3e69c54e4d2630e2e3d2", - "blockNumber": "0x49d1ed", - "from": "0x354F3f4ECdcA5E0A7acE08d71348cdC1Dab48960", - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "cumulativeGasUsed": "0x3fce7f", - "gasUsed": "0x26a66d", - "contractAddress": "0xE19C7a2C0Bb32287731Ea75dA9B1C836815964F1", - "logs": [ - { - "address": "0xE19C7a2C0Bb32287731Ea75dA9B1C836815964F1", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "blockHash": "0xa4cd57459cf08f021f24a1fbc15da572b6cd3e74932b3e69c54e4d2630e2e3d2", - "blockNumber": "0x49d1ed", - "transactionHash": "0x5eca3b218f8833a01189c622ed0cbdfae939b84b5bc47dd51915d8b8083f72e6", - "transactionIndex": "0x14", - "logIndex": "0x2", - "removed": false - } - ], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000", - "type": "0x2", - "effectiveGasPrice": "0xb98e4e7e" - }, - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 45409, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 45412, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 91978, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "spacer_0_2_20", - "offset": 2, - "slot": "0", - "type": "t_address" - }, - { - "astId": 91981, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "spacer_1_0_20", - "offset": 0, - "slot": "1", - "type": "t_address" - }, - { - "astId": 91988, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "deposits", - "offset": 0, - "slot": "2", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" - }, - { - "astId": 91993, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "__gap", - "offset": 0, - "slot": "3", - "type": "t_array(t_uint256)47_storage" - }, - { - "astId": 72666, - "contract": "src/L1/L1StandardBridge.sol:L1StandardBridge", - "label": "superchainConfig", - "offset": 0, - "slot": "50", - "type": "t_contract(SuperchainConfig)75085" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)47_storage": { - "encoding": "inplace", - "label": "uint256[47]", - "numberOfBytes": "1504", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(SuperchainConfig)75085": { - "encoding": "inplace", - "label": "contract SuperchainConfig", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32", - "value": "t_mapping(t_address,t_uint256)" - }, - "t_mapping(t_address,t_uint256)": { - "encoding": "mapping", - "key": "t_address", - "label": "mapping(address => uint256)", - "numberOfBytes": "32", - "value": "t_uint256" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x5eca3b218f8833a01189c622ed0cbdfae939b84b5bc47dd51915d8b8083f72e6", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "MESSENGER()": { - "notice": "Messenger contract on this domain." - }, - "OTHER_BRIDGE()": { - "notice": "Corresponding bridge on the other domain." - }, - "bridgeERC20(address,address,uint256,uint32,bytes)": { - "notice": "Sends ERC20 tokens to the sender's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain." - }, - "bridgeERC20To(address,address,address,uint256,uint32,bytes)": { - "notice": "Sends ERC20 tokens to a receiver's address on the other chain. Note that if the ERC20 token on the other chain does not recognize the local token as the correct pair token, the ERC20 bridge will fail and the tokens will be returned to sender on this chain." - }, - "bridgeETH(uint32,bytes)": { - "notice": "Sends ETH to the sender's address on the other chain." - }, - "bridgeETHTo(address,uint32,bytes)": { - "notice": "Sends ETH to a receiver's address on the other chain. Note that if ETH is sent to a smart contract and the call fails, the ETH will be temporarily locked in the StandardBridge on the other chain until the call is replayed. If the call cannot be replayed with any amount of gas (call always reverts), then the ETH will be permanently locked in the StandardBridge on the other chain. ETH will also be locked if the receiver is the other bridge, because finalizeBridgeETH will revert in that case." - }, - "constructor": { - "notice": "Constructs the L1StandardBridge contract." - }, - "deposits(address,address)": { - "notice": "Mapping that stores deposits for a given pair of local and remote tokens." - }, - "finalizeBridgeERC20(address,address,address,address,uint256,bytes)": { - "notice": "Finalizes an ERC20 bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain." - }, - "finalizeBridgeETH(address,address,uint256,bytes)": { - "notice": "Finalizes an ETH bridge on this chain. Can only be triggered by the other StandardBridge contract on the remote chain." - }, - "initialize(address)": { - "notice": "Initializes the contract." - }, - "messenger()": { - "notice": "Getter for messenger contract." - }, - "otherBridge()": { - "notice": "Getter for the other bridge." - }, - "paused()": { - "notice": "This function should return true if the contract is paused. On L1 this function will check the SuperchainConfig for its paused status. On L2 this function should be a no-op." - }, - "superchainConfig()": { - "notice": "Address of the SuperchainConfig contract." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "ERC20BridgeFinalized(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC20 bridge is finalized on this chain." - }, - "ERC20BridgeInitiated(address,address,address,address,uint256,bytes)": { - "notice": "Emitted when an ERC20 bridge is initiated to the other chain." - }, - "ETHBridgeFinalized(address,address,uint256,bytes)": { - "notice": "Emitted when an ETH bridge is finalized on this chain." - }, - "ETHBridgeInitiated(address,address,uint256,bytes)": { - "notice": "Emitted when an ETH bridge is initiated to the other chain." - } - }, - "notice": "The L1StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and L2. In the case that an ERC20 token is native to L1, it will be escrowed within this contract. If the ERC20 token is native to L2, it will be burnt. Before Bedrock, ETH was stored within this contract. After Bedrock, ETH is instead stored inside the OptimismPortal contract. NOTE: this contract is not intended to support all variations of ERC20 tokens. Examples of some token types that may not be properly supported by this contract include, but are not limited to: tokens with transfer fees, rebasing tokens, and tokens with blocklists." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/sepolia/L2OutputOracleProxy.json b/packages/contracts-bedrock/deployments/sepolia/L2OutputOracleProxy.json deleted file mode 100644 index 3e73e4375384..000000000000 --- a/packages/contracts-bedrock/deployments/sepolia/L2OutputOracleProxy.json +++ /dev/null @@ -1,256 +0,0 @@ -{ - "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" - } - ], - "address": "0x90E9c4f8a994a250F6aEfd61CAFb4F2e895D458F", - "args": [ - "0x189aBAAaa82DfC015A588A7dbaD6F13b1D3485Bc" - ], - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "admin()": { - "returns": { - "_0": "Owner address." - } - }, - "changeAdmin(address)": { - "params": { - "_admin": "New owner of the proxy contract." - } - }, - "constructor": { - "params": { - "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "Address of the implementation contract." - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "Calldata to delegatecall the new implementation with.", - "_implementation": "Address of the implementation contract." - } - } - }, - "events": { - "AdminChanged(address,address)": { - "params": { - "newAdmin": "The new owner of the contract", - "previousAdmin": "The previous owner of the contract" - } - }, - "Upgraded(address)": { - "params": { - "implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"src/universal/Proxy.sol\":{\"keccak256\":\"0x783aed9ff90b38a9898be5fb18699b3b249f012bc2c33f6537e1ab9f6444478f\",\"urls\":[\"bzz-raw://b119b1b68874f4d92a89cc05a4f0d25da73a959747a81e26739739a52895b844\",\"dweb:/ipfs/QmbKZqMd6CsM7annE7bCXcCi72syJAX3qtuFNPEGMCp13W\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 4, - "receipt": { - "transactionHash": "0x5c4860af998f0dca2420d76b161bd5f0e051b1f78c2bce5a42fbfb3a755350a6", - "transactionIndex": "0x6", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", - "to": null, - "cumulativeGasUsed": "0x4992f0", - "gasUsed": "0x7feb8", - "contractAddress": "0x90E9c4f8a994a250F6aEfd61CAFb4F2e895D458F", - "logs": [ - { - "address": "0x90E9c4f8a994a250F6aEfd61CAFb4F2e895D458F", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000189abaaaa82dfc015a588a7dbad6f13b1d3485bc", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "transactionHash": "0x5c4860af998f0dca2420d76b161bd5f0e051b1f78c2bce5a42fbfb3a755350a6", - "transactionIndex": "0x6", - "logIndex": "0x6", - "removed": false - } - ], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "type": "0x2", - "effectiveGasPrice": "0xbec78df7" - }, - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [], - "types": {} - }, - "transactionHash": "0x5c4860af998f0dca2420d76b161bd5f0e051b1f78c2bce5a42fbfb3a755350a6", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "admin()": { - "notice": "Gets the owner of the proxy contract." - }, - "changeAdmin(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "constructor": { - "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." - }, - "upgradeTo(address)": { - "notice": "Set the implementation contract address. The code at the given address will execute when this contract is called." - }, - "upgradeToAndCall(address,bytes)": { - "notice": "Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades." - } - }, - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." - } - }, - "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/sepolia/OptimismMintableERC20FactoryProxy.json b/packages/contracts-bedrock/deployments/sepolia/OptimismMintableERC20FactoryProxy.json deleted file mode 100644 index e9218419ef2f..000000000000 --- a/packages/contracts-bedrock/deployments/sepolia/OptimismMintableERC20FactoryProxy.json +++ /dev/null @@ -1,256 +0,0 @@ -{ - "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" - } - ], - "address": "0x868D59fF9710159C2B330Cc0fBDF57144dD7A13b", - "args": [ - "0x189aBAAaa82DfC015A588A7dbaD6F13b1D3485Bc" - ], - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "admin()": { - "returns": { - "_0": "Owner address." - } - }, - "changeAdmin(address)": { - "params": { - "_admin": "New owner of the proxy contract." - } - }, - "constructor": { - "params": { - "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "Address of the implementation contract." - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "Calldata to delegatecall the new implementation with.", - "_implementation": "Address of the implementation contract." - } - } - }, - "events": { - "AdminChanged(address,address)": { - "params": { - "newAdmin": "The new owner of the contract", - "previousAdmin": "The previous owner of the contract" - } - }, - "Upgraded(address)": { - "params": { - "implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"src/universal/Proxy.sol\":{\"keccak256\":\"0x783aed9ff90b38a9898be5fb18699b3b249f012bc2c33f6537e1ab9f6444478f\",\"urls\":[\"bzz-raw://b119b1b68874f4d92a89cc05a4f0d25da73a959747a81e26739739a52895b844\",\"dweb:/ipfs/QmbKZqMd6CsM7annE7bCXcCi72syJAX3qtuFNPEGMCp13W\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 4, - "receipt": { - "transactionHash": "0xb5cf29ab2fd0d1831f27e7be89ed597111a4662cf6c4a0ca86462e304f38c431", - "transactionIndex": "0xb", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", - "to": null, - "cumulativeGasUsed": "0x67ebcd", - "gasUsed": "0x7feb8", - "contractAddress": "0x868D59fF9710159C2B330Cc0fBDF57144dD7A13b", - "logs": [ - { - "address": "0x868D59fF9710159C2B330Cc0fBDF57144dD7A13b", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000189abaaaa82dfc015a588a7dbad6f13b1d3485bc", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "transactionHash": "0xb5cf29ab2fd0d1831f27e7be89ed597111a4662cf6c4a0ca86462e304f38c431", - "transactionIndex": "0xb", - "logIndex": "0x9", - "removed": false - } - ], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400800000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "type": "0x2", - "effectiveGasPrice": "0xbec78df7" - }, - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [], - "types": {} - }, - "transactionHash": "0xb5cf29ab2fd0d1831f27e7be89ed597111a4662cf6c4a0ca86462e304f38c431", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "admin()": { - "notice": "Gets the owner of the proxy contract." - }, - "changeAdmin(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "constructor": { - "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." - }, - "upgradeTo(address)": { - "notice": "Set the implementation contract address. The code at the given address will execute when this contract is called." - }, - "upgradeToAndCall(address,bytes)": { - "notice": "Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades." - } - }, - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." - } - }, - "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/sepolia/OptimismPortal.json b/packages/contracts-bedrock/deployments/sepolia/OptimismPortal.json deleted file mode 100644 index d36fa638cf94..000000000000 --- a/packages/contracts-bedrock/deployments/sepolia/OptimismPortal.json +++ /dev/null @@ -1,904 +0,0 @@ -{ - "abi": [ - { - "inputs": [ - { - "internalType": "contract L2OutputOracle", - "name": "_l2Oracle", - "type": "address" - }, - { - "internalType": "contract SystemConfig", - "name": "_systemConfig", - "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": "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" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "withdrawalHash", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "WithdrawalProven", - "type": "event" - }, - { - "inputs": [], - "name": "GUARDIAN", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L2_ORACLE", - "outputs": [ - { - "internalType": "contract L2OutputOracle", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SYSTEM_CONFIG", - "outputs": [ - { - "internalType": "contract SystemConfig", - "name": "", - "type": "address" - } - ], - "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": [], - "name": "donateETH", - "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": "struct Types.WithdrawalTransaction", - "name": "_tx", - "type": "tuple" - } - ], - "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": "guardian", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract SuperchainConfig", - "name": "_superchainConfig", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2OutputIndex", - "type": "uint256" - } - ], - "name": "isOutputFinalized", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l2Oracle", - "outputs": [ - { - "internalType": "contract L2OutputOracle", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l2Sender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_byteCount", - "type": "uint64" - } - ], - "name": "minimumGasLimit", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "pure", - "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": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "paused_", - "type": "bool" - } - ], - "stateMutability": "view", - "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": "struct Types.WithdrawalTransaction", - "name": "_tx", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "_l2OutputIndex", - "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": "struct Types.OutputRootProof", - "name": "_outputRootProof", - "type": "tuple" - }, - { - "internalType": "bytes[]", - "name": "_withdrawalProof", - "type": "bytes[]" - } - ], - "name": "proveWithdrawalTransaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "provenWithdrawals", - "outputs": [ - { - "internalType": "bytes32", - "name": "outputRoot", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "timestamp", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "l2OutputIndex", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "superchainConfig", - "outputs": [ - { - "internalType": "contract SuperchainConfig", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "systemConfig", - "outputs": [ - { - "internalType": "contract SystemConfig", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "address": "0x592B7D3255a8037307d23C16cC8c13a9563c8Ab1", - "args": [ - "0x90E9c4f8a994a250F6aEfd61CAFb4F2e895D458F", - "0x034edD2A225f7f429A63E0f1D2084B9E0A93b538" - ], - "bytecode": "0x60c06040523480156200001157600080fd5b506040516200575a3803806200575a8339810160408190526200003491620002ab565b6001600160a01b03808316608052811660a0526200005360006200005b565b5050620002ea565b600054610100900460ff16158080156200007c5750600054600160ff909116105b80620000ac57506200009930620001c460201b62001bbf1760201c565b158015620000ac575060005460ff166001145b620001155760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000139576000805461ff0019166101001790555b603280546001600160a01b03191661dead179055603580546001600160a01b03841661010002610100600160a81b031990911617905562000179620001d3565b8015620001c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620002405760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200010c565b600154600160c01b90046001600160401b0316600003620002905760408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b02176001555b565b6001600160a01b0381168114620002a857600080fd5b50565b60008060408385031215620002bf57600080fd5b8251620002cc8162000292565b6020840151909250620002df8162000292565b809150509250929050565b60805160a05161540b6200034f600039600081816101fb0152818161059101526122000152600081816101a00152818161036501528181610a4601528181610c270152818161102c015281816112d4015281816115460152611fbc015261540b6000f3fe6080604052600436106101625760003560e01c80638c3152e9116100c0578063c4d66de811610074578063e965084c11610059578063e965084c146104e0578063e9e05c421461056c578063f04987501461057f57600080fd5b8063c4d66de81461041f578063cff0ab961461043f57600080fd5b80639bf62d82116100a55780639bf62d8214610389578063a14238e7146103b6578063a35d99df146103e657600080fd5b80638c3152e9146103365780639b5f694a1461035657600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb7814610301578063724c184c146103215780638b4c40b01461018757600080fd5b806354fd4d50146102865780635c975abb146102dc57600080fd5b806335e80ab31161014857806335e80ab31461021f578063452a9320146102515780634870496f1461026657600080fd5b80621c2ff61461018e57806333d7e2bd146101ec57600080fd5b36610189576101873334620186a06000604051806020016040528060008152506105b3565b005b600080fd5b34801561019a57600080fd5b506101c27f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101f857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c2565b34801561022b57600080fd5b506035546101c290610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561025d57600080fd5b506101c261084e565b34801561027257600080fd5b506101876102813660046149fc565b6108e6565b34801561029257600080fd5b506102cf6040518060400160405280600581526020017f322e332e3000000000000000000000000000000000000000000000000000000081525081565b6040516101e39190614b52565b3480156102e857600080fd5b506102f1610f4e565b60405190151581526020016101e3565b34801561030d57600080fd5b506102f161031c366004614b65565b610fe1565b34801561032d57600080fd5b506101c26110b8565b34801561034257600080fd5b50610187610351366004614b7e565b6110c4565b34801561036257600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c2565b34801561039557600080fd5b506032546101c29073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103c257600080fd5b506102f16103d1366004614b65565b60336020526000908152604090205460ff1681565b3480156103f257600080fd5b50610406610401366004614bd8565b6119a1565b60405167ffffffffffffffff90911681526020016101e3565b34801561042b57600080fd5b5061018761043a366004614bf3565b6119ba565b34801561044b57600080fd5b506001546104a7906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101e3565b3480156104ec57600080fd5b5061053e6104fb366004614b65565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101e3565b61018761057a366004614c1e565b6105b3565b34801561058b57600080fd5b506101c27f000000000000000000000000000000000000000000000000000000000000000081565b8260005a9050831561066a5773ffffffffffffffffffffffffffffffffffffffff87161561066a57604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b61067483516119a1565b67ffffffffffffffff168567ffffffffffffffff161015610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c00000000000000000000000000000000000000000000000000000000006064820152608401610661565b6201d4c083511115610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c6172676500006044820152606401610661565b333281146107a6575033731111000000000000000000000000000000001111015b600034888888886040516020016107c1959493929190614c9b565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516108319190614b52565b60405180910390a450506108458282611bdb565b50505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190614d00565b905090565b6108ee610f4e565b15610955576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610661565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610a14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610661565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610aa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac69190614d3d565b519050610ae0610adb36869003860186614da2565b611f08565b8114610b6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610661565b6000610b7987611f64565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610cab5750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190614d3d565b5114155b610d37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610661565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610e009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610df6888a614e08565b8a60400135611f94565b610e8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610661565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fbd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190614e8c565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018290526000906110b29073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa158015611073573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110979190614d3d565b602001516fffffffffffffffffffffffffffffffff16611fb8565b92915050565b60006108e161084e565b565b6110cc610f4e565b15611133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610661565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead146111dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610661565b60006111e782611f64565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036112d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610661565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa15801561133d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113619190614ea9565b81602001516fffffffffffffffffffffffffffffffff16101561142c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610661565b61144b81602001516fffffffffffffffffffffffffffffffff16611fb8565b6114fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610661565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c69190614d3d565b8251815191925014611680576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610661565b61169f81602001516fffffffffffffffffffffffffffffffff16611fb8565b611751576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610661565b60008381526033602052604090205460ff16156117f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610661565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a08801516118929392919061205b565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906118f790841515815260200190565b60405180910390a28015801561190d5750326001145b1561199a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610661565b5050505050565b60006119ae826010614ef1565b6110b290615208614f21565b600054610100900460ff16158080156119da5750600054600160ff909116105b806119f45750303b1580156119f4575060005460ff166001145b611a80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610661565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611ade57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556035805473ffffffffffffffffffffffffffffffffffffffff8416610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909116179055611b586120b9565b8015611bbb57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611c11907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643614f4d565b90506000611c1d6121cc565b90506000816020015160ff16826000015163ffffffff16611c3e9190614f93565b90508215611d7557600154600090611c75908390700100000000000000000000000000000000900467ffffffffffffffff16614ffb565b90506000836040015160ff1683611c8c919061506f565b600154611cac9084906fffffffffffffffffffffffffffffffff1661506f565b611cb69190614f93565b600154909150600090611d0790611ce09084906fffffffffffffffffffffffffffffffff1661512b565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff1661228d565b90506001861115611d3657611d33611ce082876040015160ff1660018a611d2e9190614f4d565b6122ac565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611da8908490700100000000000000000000000000000000900467ffffffffffffffff16614f21565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611e8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d697400006064820152608401610661565b600154600090611eb7906fffffffffffffffffffffffffffffffff1667ffffffffffffffff881661519f565b90506000611ec948633b9aca00612301565b611ed390836151dc565b905060005a611ee29088614f4d565b905080821115611efe57611efe611ef98284614f4d565b612318565b5050505050505050565b60008160000151826020015183604001518460600151604051602001611f47949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097611f479790969591016151f0565b600080611fa086612346565b9050611fae81868686612378565b9695505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa158015612025573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120499190614ea9565b6120539083615247565b421192915050565b600080600061206b8660006123a8565b9050806120a1576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff16612150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610661565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036110c25760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663cc731b026040518163ffffffff1660e01b815260040160c060405180830381865afa158015612269573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190615284565b60006122a261229c85856123c6565b836123d6565b90505b9392505050565b6000670de0b6b3a76400006122ed6122c48583614f93565b6122d690670de0b6b3a7640000614ffb565b6122e885670de0b6b3a764000061506f565b6123e5565b6122f7908661506f565b6122a29190614f93565b60008183101561231157816122a5565b5090919050565b6000805a90505b825a61232b9083614f4d565b10156123415761233a82615323565b915061231f565b505050565b6060818051906020012060405160200161236291815260200190565b6040516020818303038152906040529050919050565b600061239f84612389878686612416565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b60008183121561231157816122a5565b600081831261231157816122a5565b60006122a5670de0b6b3a7640000836123fd86612e94565b612407919061506f565b6124119190614f93565b6130d8565b60606000845111612483576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610661565b600061248e84613317565b9050600061249b86613403565b90506000846040516020016124b291815260200190565b60405160208183030381529060405290506000805b8451811015612e0b5760008582815181106124e4576124e461535b565b60200260200101519050845183111561257f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610661565b8260000361263857805180516020918201206040516125cd926125a792910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612633576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610661565b61278f565b8051516020116126ee5780518051602091820120604051612662926125a792910190815260200190565b612633576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610661565b80518451602080870191909120825191909201201461278f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610661565b61279b60106001615247565b81602001515103612977578451830361290f576127d581602001516010815181106127c8576127c861535b565b6020026020010151613466565b96506000875111612868576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610661565b600186516128769190614f4d565b8214612904576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610661565b5050505050506122a5565b60008584815181106129235761292361535b565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061294e5761294e61535b565b60200260200101519050612961816135c6565b955061296e600186615247565b94505050612df8565b600281602001515103612d7057600061298f826135eb565b90506000816000815181106129a6576129a661535b565b016020015160f81c905060006129bd60028361538a565b6129c89060026153ac565b905060006129d9848360ff1661360f565b905060006129e78a8961360f565b905060006129f58383613645565b905080835114612a87576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610661565b60ff851660021480612a9c575060ff85166003145b15612c8b5780825114612b31576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610661565b612b4b87602001516001815181106127c8576127c861535b565b9c5060008d5111612bde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610661565b60018c51612bec9190614f4d565b8814612c7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610661565b5050505050505050505050506122a5565b60ff85161580612c9e575060ff85166001145b15612cdd57612cca8760200151600181518110612cbd57612cbd61535b565b60200260200101516135c6565b9950612cd6818a615247565b9850612d65565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610661565b505050505050612df8565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610661565b5080612e0381615323565b9150506124c7565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610661565b6000808213612eff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610661565b60006060612f0c846136f9565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361310957506000919050565b680755bf798b4a1bf1e5821261317b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610661565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff8111156133355761333561481c565b60405190808252806020026020018201604052801561337a57816020015b60408051808201909152606080825260208201528152602001906001900390816133535790505b50915060005b818110156133fc5760405180604001604052808583815181106133a5576133a561535b565b602002602001015181526020016133d48684815181106133c7576133c761535b565b60200260200101516137cf565b8152508382815181106133e9576133e961535b565b6020908102919091010152600101613380565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b8381101561345b578060011b82018184015160001a8060041c8253600f81166001830153505060010161342d565b509295945050505050565b60606000806000613476856137e2565b919450925090506000816001811115613491576134916153cf565b1461351e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d000000000000006064820152608401610661565b6135288284615247565b8551146135b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e6465720000000000000000000000006064820152608401610661565b61239f8560200151848461424f565b606060208260000151106135e2576135dd82613466565b6110b2565b6110b2826142e3565b60606110b261360a83602001516000815181106127c8576127c861535b565b613403565b60608251821061362e57506040805160208101909152600081526110b2565b6122a583838486516136409190614f4d565b6142f9565b600080825184511061365857825161365b565b83515b90505b80821080156136e2575082828151811061367a5761367a61535b565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106136b9576136b961535b565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156136f25781600101915061365e565b5092915050565b6000808211613764576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610661565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60606110b26137dd836144d1565b6145ba565b6000806000808460000151116138a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610661565b6020840151805160001a607f81116138c5576000600160009450945094505050614248565b60b78111613ad35760006138da608083614f4d565b905080876000015111613995576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a401610661565b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082141580613a0e57507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613ac0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a401610661565b5060019550935060009250614248915050565b60bf8111613e21576000613ae860b783614f4d565b905080876000015111613ba3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a401610661565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613c81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a401610661565b600184015160088302610100031c60378111613d45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a401610661565b613d4f8184615247565b895111613e04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a401610661565b613e0f836001615247565b97509550600094506142489350505050565b60f78111613f02576000613e3660c083614f4d565b905080876000015111613ef1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a401610661565b600195509350849250614248915050565b6000613f0f60f783614f4d565b905080876000015111613fca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a401610661565b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036140a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a401610661565b600184015160088302610100031c6037811161416c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a401610661565b6141768184615247565b89511161422b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a401610661565b614236836001615247565b97509550600194506142489350505050565b9193909250565b60608167ffffffffffffffff81111561426a5761426a61481c565b6040519080825280601f01601f191660200182016040528015614294576020820181803683370190505b50905081156122a55760006142a98486615247565b90506020820160005b848110156142ca5782810151828201526020016142b2565b848111156142d9576000858301525b5050509392505050565b60606110b282602001516000846000015161424f565b60608182601f011015614368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610661565b8282840110156143d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610661565b81830184511015614441576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610661565b60608215801561446057604051915060008252602082016040526144c8565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614499578051835260209283019201614481565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6040805180820190915260008082526020820152600082511161459c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610661565b50604080518082019091528151815260209182019181019190915290565b606060008060006145ca856137e2565b9194509250905060018160018111156145e5576145e56153cf565b14614672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d00000000000000006064820152608401610661565b845161467e8385615247565b1461470b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e64657200000000000000000000000000006064820152608401610661565b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816147225790505093506000835b8651811015614810576000806147956040518060400160405280858c600001516147799190614f4d565b8152602001858c6020015161478e9190615247565b90526137e2565b5091509150604051806040016040528083836147b19190615247565b8152602001848b602001516147c69190615247565b8152508885815181106147db576147db61535b565b60209081029190910101526147f1600185615247565b93506147fd8183615247565b6148079084615247565b9250505061474f565b50845250919392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156148925761489261481c565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff811681146148bc57600080fd5b50565b600082601f8301126148d057600080fd5b813567ffffffffffffffff8111156148ea576148ea61481c565b61491b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161484b565b81815284602083860101111561493057600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561495f57600080fd5b60405160c0810167ffffffffffffffff82821081831117156149835761498361481c565b81604052829350843583526020850135915061499e8261489a565b816020840152604085013591506149b48261489a565b816040840152606085013560608401526080850135608084015260a08501359150808211156149e257600080fd5b506149ef858286016148bf565b60a0830152505092915050565b600080600080600085870360e0811215614a1557600080fd5b863567ffffffffffffffff80821115614a2d57600080fd5b614a398a838b0161494d565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614a7257600080fd5b60408901955060c0890135925080831115614a8c57600080fd5b828901925089601f840112614aa057600080fd5b8235915080821115614ab157600080fd5b508860208260051b8401011115614ac757600080fd5b959894975092955050506020019190565b60005b83811015614af3578181015183820152602001614adb565b83811115614b02576000848401525b50505050565b60008151808452614b20816020860160208601614ad8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122a56020830184614b08565b600060208284031215614b7757600080fd5b5035919050565b600060208284031215614b9057600080fd5b813567ffffffffffffffff811115614ba757600080fd5b614bb38482850161494d565b949350505050565b803567ffffffffffffffff81168114614bd357600080fd5b919050565b600060208284031215614bea57600080fd5b6122a582614bbb565b600060208284031215614c0557600080fd5b81356122a58161489a565b80151581146148bc57600080fd5b600080600080600060a08688031215614c3657600080fd5b8535614c418161489a565b945060208601359350614c5660408701614bbb565b92506060860135614c6681614c10565b9150608086013567ffffffffffffffff811115614c8257600080fd5b614c8e888289016148bf565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614cef816049850160208701614ad8565b919091016049019695505050505050565b600060208284031215614d1257600080fd5b81516122a58161489a565b80516fffffffffffffffffffffffffffffffff81168114614bd357600080fd5b600060608284031215614d4f57600080fd5b6040516060810181811067ffffffffffffffff82111715614d7257614d7261481c565b60405282518152614d8560208401614d1d565b6020820152614d9660408401614d1d565b60408201529392505050565b600060808284031215614db457600080fd5b6040516080810181811067ffffffffffffffff82111715614dd757614dd761481c565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614e2357614e2361481c565b8360051b6020614e3481830161484b565b868152918501918181019036841115614e4c57600080fd5b865b84811015614e8057803586811115614e665760008081fd5b614e7236828b016148bf565b845250918301918301614e4e565b50979650505050505050565b600060208284031215614e9e57600080fd5b81516122a581614c10565b600060208284031215614ebb57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615614f1857614f18614ec2565b02949350505050565b600067ffffffffffffffff808316818516808303821115614f4457614f44614ec2565b01949350505050565b600082821015614f5f57614f5f614ec2565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614fa257614fa2614f64565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615614ff657614ff6614ec2565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561503557615035614ec2565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561506957615069614ec2565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156150b0576150b0614ec2565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156150eb576150eb614ec2565b6000871292508782058712848416161561510757615107614ec2565b8785058712818416161561511d5761511d614ec2565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561516557615165614ec2565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561519957615199614ec2565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156151d7576151d7614ec2565b500290565b6000826151eb576151eb614f64565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261523b60c0830184614b08565b98975050505050505050565b6000821982111561525a5761525a614ec2565b500190565b805163ffffffff81168114614bd357600080fd5b805160ff81168114614bd357600080fd5b600060c0828403121561529657600080fd5b60405160c0810181811067ffffffffffffffff821117156152b9576152b961481c565b6040526152c58361525f565b81526152d360208401615273565b60208201526152e460408401615273565b60408201526152f56060840161525f565b60608201526153066080840161525f565b608082015261531760a08401614d1d565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361535457615354614ec2565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff83168061539d5761539d614f64565b8060ff84160691505092915050565b600060ff821660ff8416808210156153c6576153c6614ec2565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", - "deployedBytecode": "0x6080604052600436106101625760003560e01c80638c3152e9116100c0578063c4d66de811610074578063e965084c11610059578063e965084c146104e0578063e9e05c421461056c578063f04987501461057f57600080fd5b8063c4d66de81461041f578063cff0ab961461043f57600080fd5b80639bf62d82116100a55780639bf62d8214610389578063a14238e7146103b6578063a35d99df146103e657600080fd5b80638c3152e9146103365780639b5f694a1461035657600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb7814610301578063724c184c146103215780638b4c40b01461018757600080fd5b806354fd4d50146102865780635c975abb146102dc57600080fd5b806335e80ab31161014857806335e80ab31461021f578063452a9320146102515780634870496f1461026657600080fd5b80621c2ff61461018e57806333d7e2bd146101ec57600080fd5b36610189576101873334620186a06000604051806020016040528060008152506105b3565b005b600080fd5b34801561019a57600080fd5b506101c27f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101f857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c2565b34801561022b57600080fd5b506035546101c290610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561025d57600080fd5b506101c261084e565b34801561027257600080fd5b506101876102813660046149fc565b6108e6565b34801561029257600080fd5b506102cf6040518060400160405280600581526020017f322e332e3000000000000000000000000000000000000000000000000000000081525081565b6040516101e39190614b52565b3480156102e857600080fd5b506102f1610f4e565b60405190151581526020016101e3565b34801561030d57600080fd5b506102f161031c366004614b65565b610fe1565b34801561032d57600080fd5b506101c26110b8565b34801561034257600080fd5b50610187610351366004614b7e565b6110c4565b34801561036257600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c2565b34801561039557600080fd5b506032546101c29073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103c257600080fd5b506102f16103d1366004614b65565b60336020526000908152604090205460ff1681565b3480156103f257600080fd5b50610406610401366004614bd8565b6119a1565b60405167ffffffffffffffff90911681526020016101e3565b34801561042b57600080fd5b5061018761043a366004614bf3565b6119ba565b34801561044b57600080fd5b506001546104a7906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101e3565b3480156104ec57600080fd5b5061053e6104fb366004614b65565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101e3565b61018761057a366004614c1e565b6105b3565b34801561058b57600080fd5b506101c27f000000000000000000000000000000000000000000000000000000000000000081565b8260005a9050831561066a5773ffffffffffffffffffffffffffffffffffffffff87161561066a57604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b61067483516119a1565b67ffffffffffffffff168567ffffffffffffffff161015610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c00000000000000000000000000000000000000000000000000000000006064820152608401610661565b6201d4c083511115610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c6172676500006044820152606401610661565b333281146107a6575033731111000000000000000000000000000000001111015b600034888888886040516020016107c1959493929190614c9b565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516108319190614b52565b60405180910390a450506108458282611bdb565b50505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190614d00565b905090565b6108ee610f4e565b15610955576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610661565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610a14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610661565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610aa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac69190614d3d565b519050610ae0610adb36869003860186614da2565b611f08565b8114610b6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610661565b6000610b7987611f64565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610cab5750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190614d3d565b5114155b610d37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610661565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610e009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610df6888a614e08565b8a60400135611f94565b610e8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610661565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fbd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190614e8c565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018290526000906110b29073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa158015611073573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110979190614d3d565b602001516fffffffffffffffffffffffffffffffff16611fb8565b92915050565b60006108e161084e565b565b6110cc610f4e565b15611133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610661565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead146111dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610661565b60006111e782611f64565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036112d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610661565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa15801561133d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113619190614ea9565b81602001516fffffffffffffffffffffffffffffffff16101561142c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610661565b61144b81602001516fffffffffffffffffffffffffffffffff16611fb8565b6114fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610661565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c69190614d3d565b8251815191925014611680576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610661565b61169f81602001516fffffffffffffffffffffffffffffffff16611fb8565b611751576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610661565b60008381526033602052604090205460ff16156117f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610661565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a08801516118929392919061205b565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906118f790841515815260200190565b60405180910390a28015801561190d5750326001145b1561199a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610661565b5050505050565b60006119ae826010614ef1565b6110b290615208614f21565b600054610100900460ff16158080156119da5750600054600160ff909116105b806119f45750303b1580156119f4575060005460ff166001145b611a80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610661565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611ade57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790556035805473ffffffffffffffffffffffffffffffffffffffff8416610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909116179055611b586120b9565b8015611bbb57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611c11907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643614f4d565b90506000611c1d6121cc565b90506000816020015160ff16826000015163ffffffff16611c3e9190614f93565b90508215611d7557600154600090611c75908390700100000000000000000000000000000000900467ffffffffffffffff16614ffb565b90506000836040015160ff1683611c8c919061506f565b600154611cac9084906fffffffffffffffffffffffffffffffff1661506f565b611cb69190614f93565b600154909150600090611d0790611ce09084906fffffffffffffffffffffffffffffffff1661512b565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff1661228d565b90506001861115611d3657611d33611ce082876040015160ff1660018a611d2e9190614f4d565b6122ac565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611da8908490700100000000000000000000000000000000900467ffffffffffffffff16614f21565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611e8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d697400006064820152608401610661565b600154600090611eb7906fffffffffffffffffffffffffffffffff1667ffffffffffffffff881661519f565b90506000611ec948633b9aca00612301565b611ed390836151dc565b905060005a611ee29088614f4d565b905080821115611efe57611efe611ef98284614f4d565b612318565b5050505050505050565b60008160000151826020015183604001518460600151604051602001611f47949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097611f479790969591016151f0565b600080611fa086612346565b9050611fae81868686612378565b9695505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa158015612025573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120499190614ea9565b6120539083615247565b421192915050565b600080600061206b8660006123a8565b9050806120a1576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff16612150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610661565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036110c25760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663cc731b026040518163ffffffff1660e01b815260040160c060405180830381865afa158015612269573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190615284565b60006122a261229c85856123c6565b836123d6565b90505b9392505050565b6000670de0b6b3a76400006122ed6122c48583614f93565b6122d690670de0b6b3a7640000614ffb565b6122e885670de0b6b3a764000061506f565b6123e5565b6122f7908661506f565b6122a29190614f93565b60008183101561231157816122a5565b5090919050565b6000805a90505b825a61232b9083614f4d565b10156123415761233a82615323565b915061231f565b505050565b6060818051906020012060405160200161236291815260200190565b6040516020818303038152906040529050919050565b600061239f84612389878686612416565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b60008183121561231157816122a5565b600081831261231157816122a5565b60006122a5670de0b6b3a7640000836123fd86612e94565b612407919061506f565b6124119190614f93565b6130d8565b60606000845111612483576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610661565b600061248e84613317565b9050600061249b86613403565b90506000846040516020016124b291815260200190565b60405160208183030381529060405290506000805b8451811015612e0b5760008582815181106124e4576124e461535b565b60200260200101519050845183111561257f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610661565b8260000361263857805180516020918201206040516125cd926125a792910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612633576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610661565b61278f565b8051516020116126ee5780518051602091820120604051612662926125a792910190815260200190565b612633576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610661565b80518451602080870191909120825191909201201461278f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610661565b61279b60106001615247565b81602001515103612977578451830361290f576127d581602001516010815181106127c8576127c861535b565b6020026020010151613466565b96506000875111612868576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610661565b600186516128769190614f4d565b8214612904576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610661565b5050505050506122a5565b60008584815181106129235761292361535b565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061294e5761294e61535b565b60200260200101519050612961816135c6565b955061296e600186615247565b94505050612df8565b600281602001515103612d7057600061298f826135eb565b90506000816000815181106129a6576129a661535b565b016020015160f81c905060006129bd60028361538a565b6129c89060026153ac565b905060006129d9848360ff1661360f565b905060006129e78a8961360f565b905060006129f58383613645565b905080835114612a87576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610661565b60ff851660021480612a9c575060ff85166003145b15612c8b5780825114612b31576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610661565b612b4b87602001516001815181106127c8576127c861535b565b9c5060008d5111612bde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610661565b60018c51612bec9190614f4d565b8814612c7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610661565b5050505050505050505050506122a5565b60ff85161580612c9e575060ff85166001145b15612cdd57612cca8760200151600181518110612cbd57612cbd61535b565b60200260200101516135c6565b9950612cd6818a615247565b9850612d65565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610661565b505050505050612df8565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610661565b5080612e0381615323565b9150506124c7565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610661565b6000808213612eff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610661565b60006060612f0c846136f9565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361310957506000919050565b680755bf798b4a1bf1e5821261317b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610661565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff8111156133355761333561481c565b60405190808252806020026020018201604052801561337a57816020015b60408051808201909152606080825260208201528152602001906001900390816133535790505b50915060005b818110156133fc5760405180604001604052808583815181106133a5576133a561535b565b602002602001015181526020016133d48684815181106133c7576133c761535b565b60200260200101516137cf565b8152508382815181106133e9576133e961535b565b6020908102919091010152600101613380565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b8381101561345b578060011b82018184015160001a8060041c8253600f81166001830153505060010161342d565b509295945050505050565b60606000806000613476856137e2565b919450925090506000816001811115613491576134916153cf565b1461351e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d000000000000006064820152608401610661565b6135288284615247565b8551146135b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e6465720000000000000000000000006064820152608401610661565b61239f8560200151848461424f565b606060208260000151106135e2576135dd82613466565b6110b2565b6110b2826142e3565b60606110b261360a83602001516000815181106127c8576127c861535b565b613403565b60608251821061362e57506040805160208101909152600081526110b2565b6122a583838486516136409190614f4d565b6142f9565b600080825184511061365857825161365b565b83515b90505b80821080156136e2575082828151811061367a5761367a61535b565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106136b9576136b961535b565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156136f25781600101915061365e565b5092915050565b6000808211613764576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610661565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60606110b26137dd836144d1565b6145ba565b6000806000808460000151116138a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610661565b6020840151805160001a607f81116138c5576000600160009450945094505050614248565b60b78111613ad35760006138da608083614f4d565b905080876000015111613995576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a401610661565b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082141580613a0e57507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613ac0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a401610661565b5060019550935060009250614248915050565b60bf8111613e21576000613ae860b783614f4d565b905080876000015111613ba3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a401610661565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613c81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a401610661565b600184015160088302610100031c60378111613d45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a401610661565b613d4f8184615247565b895111613e04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a401610661565b613e0f836001615247565b97509550600094506142489350505050565b60f78111613f02576000613e3660c083614f4d565b905080876000015111613ef1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a401610661565b600195509350849250614248915050565b6000613f0f60f783614f4d565b905080876000015111613fca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a401610661565b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036140a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a401610661565b600184015160088302610100031c6037811161416c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a401610661565b6141768184615247565b89511161422b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a401610661565b614236836001615247565b97509550600194506142489350505050565b9193909250565b60608167ffffffffffffffff81111561426a5761426a61481c565b6040519080825280601f01601f191660200182016040528015614294576020820181803683370190505b50905081156122a55760006142a98486615247565b90506020820160005b848110156142ca5782810151828201526020016142b2565b848111156142d9576000858301525b5050509392505050565b60606110b282602001516000846000015161424f565b60608182601f011015614368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610661565b8282840110156143d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610661565b81830184511015614441576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610661565b60608215801561446057604051915060008252602082016040526144c8565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614499578051835260209283019201614481565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b6040805180820190915260008082526020820152600082511161459c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610661565b50604080518082019091528151815260209182019181019190915290565b606060008060006145ca856137e2565b9194509250905060018160018111156145e5576145e56153cf565b14614672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d00000000000000006064820152608401610661565b845161467e8385615247565b1461470b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e64657200000000000000000000000000006064820152608401610661565b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816147225790505093506000835b8651811015614810576000806147956040518060400160405280858c600001516147799190614f4d565b8152602001858c6020015161478e9190615247565b90526137e2565b5091509150604051806040016040528083836147b19190615247565b8152602001848b602001516147c69190615247565b8152508885815181106147db576147db61535b565b60209081029190910101526147f1600185615247565b93506147fd8183615247565b6148079084615247565b9250505061474f565b50845250919392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156148925761489261481c565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff811681146148bc57600080fd5b50565b600082601f8301126148d057600080fd5b813567ffffffffffffffff8111156148ea576148ea61481c565b61491b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161484b565b81815284602083860101111561493057600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561495f57600080fd5b60405160c0810167ffffffffffffffff82821081831117156149835761498361481c565b81604052829350843583526020850135915061499e8261489a565b816020840152604085013591506149b48261489a565b816040840152606085013560608401526080850135608084015260a08501359150808211156149e257600080fd5b506149ef858286016148bf565b60a0830152505092915050565b600080600080600085870360e0811215614a1557600080fd5b863567ffffffffffffffff80821115614a2d57600080fd5b614a398a838b0161494d565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614a7257600080fd5b60408901955060c0890135925080831115614a8c57600080fd5b828901925089601f840112614aa057600080fd5b8235915080821115614ab157600080fd5b508860208260051b8401011115614ac757600080fd5b959894975092955050506020019190565b60005b83811015614af3578181015183820152602001614adb565b83811115614b02576000848401525b50505050565b60008151808452614b20816020860160208601614ad8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122a56020830184614b08565b600060208284031215614b7757600080fd5b5035919050565b600060208284031215614b9057600080fd5b813567ffffffffffffffff811115614ba757600080fd5b614bb38482850161494d565b949350505050565b803567ffffffffffffffff81168114614bd357600080fd5b919050565b600060208284031215614bea57600080fd5b6122a582614bbb565b600060208284031215614c0557600080fd5b81356122a58161489a565b80151581146148bc57600080fd5b600080600080600060a08688031215614c3657600080fd5b8535614c418161489a565b945060208601359350614c5660408701614bbb565b92506060860135614c6681614c10565b9150608086013567ffffffffffffffff811115614c8257600080fd5b614c8e888289016148bf565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614cef816049850160208701614ad8565b919091016049019695505050505050565b600060208284031215614d1257600080fd5b81516122a58161489a565b80516fffffffffffffffffffffffffffffffff81168114614bd357600080fd5b600060608284031215614d4f57600080fd5b6040516060810181811067ffffffffffffffff82111715614d7257614d7261481c565b60405282518152614d8560208401614d1d565b6020820152614d9660408401614d1d565b60408201529392505050565b600060808284031215614db457600080fd5b6040516080810181811067ffffffffffffffff82111715614dd757614dd761481c565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614e2357614e2361481c565b8360051b6020614e3481830161484b565b868152918501918181019036841115614e4c57600080fd5b865b84811015614e8057803586811115614e665760008081fd5b614e7236828b016148bf565b845250918301918301614e4e565b50979650505050505050565b600060208284031215614e9e57600080fd5b81516122a581614c10565b600060208284031215614ebb57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615614f1857614f18614ec2565b02949350505050565b600067ffffffffffffffff808316818516808303821115614f4457614f44614ec2565b01949350505050565b600082821015614f5f57614f5f614ec2565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614fa257614fa2614f64565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615614ff657614ff6614ec2565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561503557615035614ec2565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561506957615069614ec2565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156150b0576150b0614ec2565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156150eb576150eb614ec2565b6000871292508782058712848416161561510757615107614ec2565b8785058712818416161561511d5761511d614ec2565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561516557615165614ec2565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561519957615199614ec2565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156151d7576151d7614ec2565b500290565b6000826151eb576151eb614f64565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261523b60c0830184614b08565b98975050505050505050565b6000821982111561525a5761525a614ec2565b500190565b805163ffffffff81168114614bd357600080fd5b805160ff81168114614bd357600080fd5b600060c0828403121561529657600080fd5b60405160c0810181811067ffffffffffffffff821117156152b9576152b961481c565b6040526152c58361525f565b81526152d360208401615273565b60208201526152e460408401615273565b60408201526152f56060840161525f565b60608201526153066080840161525f565b608082015261531760a08401614d1d565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361535457615354614ec2565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff83168061539d5761539d614f64565b8060ff84160691505092915050565b600060ff821660ff8416808210156153c6576153c6614ec2565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "GUARDIAN()": {}, - "constructor": { - "params": { - "_l2Oracle": "Address of the L2OutputOracle contract.", - "_systemConfig": "Address of the SystemConfig contract." - } - }, - "depositTransaction(address,uint256,uint64,bool,bytes)": { - "params": { - "_data": "Data to trigger the recipient with.", - "_gasLimit": "Amount of L2 gas to purchase by burning gas on L1.", - "_isCreation": "Whether or not the transaction is a contract creation.", - "_to": "Target address on L2.", - "_value": "ETH value to send to the recipient." - } - }, - "finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))": { - "params": { - "_tx": "Withdrawal transaction to finalize." - } - }, - "guardian()": {}, - "initialize(address)": { - "params": { - "_superchainConfig": "Address of the SuperchainConfig contract." - } - }, - "isOutputFinalized(uint256)": { - "params": { - "_l2OutputIndex": "Index of the L2 output to check." - }, - "returns": { - "_0": "Whether or not the output is finalized." - } - }, - "minimumGasLimit(uint64)": { - "params": { - "_byteCount": "Number of bytes in the calldata." - }, - "returns": { - "_0": "The minimum gas limit for a deposit." - } - }, - "proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])": { - "params": { - "_l2OutputIndex": "L2 output index to prove against.", - "_outputRootProof": "Inclusion proof of the L2ToL1MessagePasser contract's storage root.", - "_tx": "Withdrawal transaction to finalize.", - "_withdrawalProof": "Inclusion proof of the withdrawal in L2ToL1MessagePasser contract." - } - } - }, - "events": { - "TransactionDeposited(address,address,uint256,bytes)": { - "params": { - "from": "Address that triggered the deposit transaction.", - "opaqueData": "ABI encoded deposit data to be parsed off-chain.", - "to": "Address that the deposit transaction is directed to.", - "version": "Version of this deposit transaction event." - } - }, - "WithdrawalFinalized(bytes32,bool)": { - "params": { - "success": "Whether the withdrawal transaction was successful.", - "withdrawalHash": "Hash of the withdrawal transaction." - } - }, - "WithdrawalProven(bytes32,address,address)": { - "params": { - "from": "Address that triggered the withdrawal transaction.", - "to": "Address that the withdrawal transaction is directed to.", - "withdrawalHash": "Hash of the withdrawal transaction." - } - } - } - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"_l2Oracle\",\"type\":\"address\"},{\"internalType\":\"contract SystemConfig\",\"name\":\"_systemConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"opaqueData\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"TransactionDeposited\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\",\"indexed\":false}],\"type\":\"event\",\"name\":\"WithdrawalFinalized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"withdrawalHash\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"WithdrawalProven\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"GUARDIAN\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"L2_ORACLE\",\"outputs\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"SYSTEM_CONFIG\",\"outputs\":[{\"internalType\":\"contract SystemConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"_gasLimit\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"_isCreation\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"depositTransaction\"},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"donateETH\"},{\"inputs\":[{\"internalType\":\"struct Types.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}]}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"finalizeWithdrawalTransaction\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"finalizedWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"guardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"_superchainConfig\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"isOutputFinalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2Oracle\",\"outputs\":[{\"internalType\":\"contract L2OutputOracle\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"l2Sender\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_byteCount\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\",\"name\":\"minimumGasLimit\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"params\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"prevBaseFee\",\"type\":\"uint128\"},{\"internalType\":\"uint64\",\"name\":\"prevBoughtGas\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"prevBlockNum\",\"type\":\"uint64\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}]},{\"inputs\":[{\"internalType\":\"struct Types.WithdrawalTransaction\",\"name\":\"_tx\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}]},{\"internalType\":\"uint256\",\"name\":\"_l2OutputIndex\",\"type\":\"uint256\"},{\"internalType\":\"struct Types.OutputRootProof\",\"name\":\"_outputRootProof\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messagePasserStorageRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"latestBlockhash\",\"type\":\"bytes32\"}]},{\"internalType\":\"bytes[]\",\"name\":\"_withdrawalProof\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"proveWithdrawalTransaction\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"provenWithdrawals\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"outputRoot\",\"type\":\"bytes32\"},{\"internalType\":\"uint128\",\"name\":\"timestamp\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2OutputIndex\",\"type\":\"uint128\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"superchainConfig\",\"outputs\":[{\"internalType\":\"contract SuperchainConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"systemConfig\",\"outputs\":[{\"internalType\":\"contract SystemConfig\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"GUARDIAN()\":{\"custom:legacy\":\"\"},\"constructor\":{\"params\":{\"_l2Oracle\":\"Address of the L2OutputOracle contract.\",\"_systemConfig\":\"Address of the SystemConfig contract.\"}},\"depositTransaction(address,uint256,uint64,bool,bytes)\":{\"params\":{\"_data\":\"Data to trigger the recipient with.\",\"_gasLimit\":\"Amount of L2 gas to purchase by burning gas on L1.\",\"_isCreation\":\"Whether or not the transaction is a contract creation.\",\"_to\":\"Target address on L2.\",\"_value\":\"ETH value to send to the recipient.\"}},\"finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))\":{\"params\":{\"_tx\":\"Withdrawal transaction to finalize.\"}},\"guardian()\":{\"custom:legacy\":\"\"},\"initialize(address)\":{\"params\":{\"_superchainConfig\":\"Address of the SuperchainConfig contract.\"}},\"isOutputFinalized(uint256)\":{\"params\":{\"_l2OutputIndex\":\"Index of the L2 output to check.\"},\"returns\":{\"_0\":\"Whether or not the output is finalized.\"}},\"minimumGasLimit(uint64)\":{\"params\":{\"_byteCount\":\"Number of bytes in the calldata.\"},\"returns\":{\"_0\":\"The minimum gas limit for a deposit.\"}},\"proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])\":{\"params\":{\"_l2OutputIndex\":\"L2 output index to prove against.\",\"_outputRootProof\":\"Inclusion proof of the L2ToL1MessagePasser contract's storage root.\",\"_tx\":\"Withdrawal transaction to finalize.\",\"_withdrawalProof\":\"Inclusion proof of the withdrawal in L2ToL1MessagePasser contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"GUARDIAN()\":{\"notice\":\"Getter function for the address of the guardian. This will be removed in the future, use `SuperchainConfig.guardian()` instead.Address of the guardian.\"},\"L2_ORACLE()\":{\"notice\":\"Address of the L2OutputOracle contract. This will be removed in the future, use `l2Oracle` instead.\"},\"SYSTEM_CONFIG()\":{\"notice\":\"Address of the SystemConfig contract. This will be removed in the future, use `systemConfig` instead.\"},\"constructor\":{\"notice\":\"Constructs the OptimismPortal contract.\"},\"depositTransaction(address,uint256,uint64,bool,bytes)\":{\"notice\":\"Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in deriving deposit transactions. Note that if a deposit is made by a contract, its address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider using the CrossDomainMessenger contracts for a simpler developer experience.\"},\"donateETH()\":{\"notice\":\"Accepts ETH value without triggering a deposit to L2. This function mainly exists for the sake of the migration between the legacy Optimism system and Bedrock.\"},\"finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))\":{\"notice\":\"Finalizes a withdrawal transaction.\"},\"finalizedWithdrawals(bytes32)\":{\"notice\":\"A list of withdrawal hashes which have been successfully finalized.\"},\"guardian()\":{\"notice\":\"Getter function for the address of the guardian. This will be removed in the future, use `SuperchainConfig.guardian()` instead.Address of the guardian.\"},\"initialize(address)\":{\"notice\":\"Initializer.\"},\"isOutputFinalized(uint256)\":{\"notice\":\"Determine if a given output is finalized. Reverts if the call to L2_ORACLE.getL2Output reverts. Returns a boolean otherwise.\"},\"l2Oracle()\":{\"notice\":\"Getter function for the address of the L2OutputOracle on this chain.Address of the L2OutputOracle on this chain.\"},\"l2Sender()\":{\"notice\":\"Address of the L2 account which initiated a withdrawal in this transaction. If the of this variable is the default L2 sender address, then we are NOT inside of a call to finalizeWithdrawalTransaction.\"},\"minimumGasLimit(uint64)\":{\"notice\":\"Computes the minimum gas limit for a deposit. The minimum gas limit linearly increases based on the size of the calldata. This is to prevent users from creating L2 resource usage without paying for it. This function can be used when interacting with the portal to ensure forwards compatibility.\"},\"params()\":{\"notice\":\"EIP-1559 style gas parameters.\"},\"paused()\":{\"notice\":\"Getter for the current paused status.\"},\"proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])\":{\"notice\":\"Proves a withdrawal transaction.\"},\"provenWithdrawals(bytes32)\":{\"notice\":\"A mapping of withdrawal hashes to `ProvenWithdrawal` data.\"},\"superchainConfig()\":{\"notice\":\"The address of the Superchain Config contract.\"},\"systemConfig()\":{\"notice\":\"Getter function for the address of the SystemConfig on this chain.Address of the SystemConfig on this chain.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/OptimismPortal.sol\":\"OptimismPortal\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/L2OutputOracle.sol\":{\"keccak256\":\"0xecd3b0cd61ec0d1246ea19cc5095508b84ad0d586988f781b4de9233b3c2821d\",\"urls\":[\"bzz-raw://b4d5e6a842dd999ff09c6db97c8a5e44aaa5f84652a6eb1aa3c170094e9c9591\",\"dweb:/ipfs/QmfUaT1pX9rQBZm48zdwzaSQ7miW8Ek7kBwys1UhMFSYJR\"],\"license\":\"MIT\"},\"src/L1/OptimismPortal.sol\":{\"keccak256\":\"0xf128f38f10196f54f108f9ab1036db85b0e7b631b1c728b21a410c747963c193\",\"urls\":[\"bzz-raw://149a852fdf45ad58a6df9fa8503dbc8a8bdd40fe730010c83d1f57d698c15cb1\",\"dweb:/ipfs/QmYEhvArJ3Tud1kfyx2LwyAg9RMLb9hp8r3VLnFjR19Pyy\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0x4a03e4a42900cecb4e923b92a7a10edb367347260bf38a937ce31826f1644330\",\"urls\":[\"bzz-raw://29dbfb9f323dfb9c4ce23c27a876dd7caddda6a3a5d483429cda433021d9f145\",\"dweb:/ipfs/QmZff2htQcExkwLdoGZ6e81zCFeGZV8oXgn4BhpW8Sccq7\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x3dd454d7ec9e2a90a6daf4b0c2f9ba371eae564b6e535aa88884e50de7df340a\",\"urls\":[\"bzz-raw://710bcccf6a1071171c45c2594e896ef5a26080a00dd3586e9ce80148a731d55b\",\"dweb:/ipfs/QmRSSYggh5woP8Xd9SHhuNt6tF7hMaSUMMk8W5zWk34NeL\"],\"license\":\"MIT\"},\"src/L1/SystemConfig.sol\":{\"keccak256\":\"0x5c6346060b3e8d3bf4289b20fd869a66fbad8f69dc0b095845f990066b6c4d2b\",\"urls\":[\"bzz-raw://161277a9935cc567d76096a9a3ffc54632fda2020e02b4c5dc5541bfad3d166f\",\"dweb:/ipfs/QmXiDP2A4MPsN9VDNf9YbqbQQTU2J5tffWbJHg45f9LJyN\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Bytes.sol\":{\"keccak256\":\"0x827f47d123b0fdf3b08816d5b33831811704dbf4e554e53f2269354f6bba8859\",\"urls\":[\"bzz-raw://3137ac7204d30a245a8b0d67aa6da5286f1bd8c90379daab561f84963b6db782\",\"dweb:/ipfs/QmWRhisw3axJK833gUScs23ETh2MLFbVzzqzYVMKSDN3S9\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0x8fcbc468fa4924f81538d4a6674031e12b62b61a88e869fdf099158a0d0c6a19\",\"urls\":[\"bzz-raw://fc7b9bca6c12fdd38e556650ec1eda3cccb0de4d474d2e97904cbd483b147359\",\"dweb:/ipfs/QmW4oKjDtHJj4cNfMhMLDteQEHSUuZtwrrFUJRnZCbQTJd\"],\"license\":\"MIT\"},\"src/libraries/Encoding.sol\":{\"keccak256\":\"0xd5bbcb7da113e69562498d9543765e03912558ad66348682c2049c31e19f9d9b\",\"urls\":[\"bzz-raw://afc6656ea10062c0c9d0817bb8683636caebf9222c9c102f29ea54fff74a2f93\",\"dweb:/ipfs/QmTNWtMgrTRHM6XtdUmA8bMZcuFpXoFCXgXR5vRihZWLuW\"],\"license\":\"MIT\"},\"src/libraries/Hashing.sol\":{\"keccak256\":\"0x44e2b2dcfffc39c0fc95ccd3c2118c7e7585fadf3dca327877d5756c7d4b21c3\",\"urls\":[\"bzz-raw://6c89e0d9cfcb08a0d3c46c85367a32bbd9703468ba4c0c5bb6e124c1d173b26b\",\"dweb:/ipfs/QmaY3nQHBBhHK1wrurVXiEeNL8hfZ1pRmhpqW44tFDJnDf\"],\"license\":\"MIT\"},\"src/libraries/SafeCall.sol\":{\"keccak256\":\"0x0636a7abb242bb5d6f5606967c8929e6aa7e63468c1e2ce40ad4780d4c4bf94f\",\"urls\":[\"bzz-raw://a4daec2ac8f9907bbf84ef0a1c48f03bae8657619bc6f42b3a672f25c516f17a\",\"dweb:/ipfs/Qmf8gfRxBv8gEmCkP8YMPb2GGfj9QUnoNUyKE7UR2SWGnq\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x7ce27a05552aa69afa6b2ab6684dfe99f27366cf8ef2046baeb1fb62fff0022f\",\"urls\":[\"bzz-raw://a6a24f3ed56681720707a5ab0372fd67fcb1a4f6fb072c7140cda28bdb70f269\",\"dweb:/ipfs/QmW9uTpUULV4xmP7A7MoBDeDhVfQgmJG5qVUFGtXxWpWWK\"],\"license\":\"MIT\"},\"src/libraries/Types.sol\":{\"keccak256\":\"0x75900d651301940d24c00d14f0b3b6cbd6dcf379173ceaa31d9bf5be934a9aa4\",\"urls\":[\"bzz-raw://99c2632c5bf4fa3982391c32110eec9fa07917b483b2442cbaf18bdde5bdb24e\",\"dweb:/ipfs/QmSUs6Amkeootf5gKGbKi4mJpvhN2U8i1ED6ef2dskV5xc\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPReader.sol\":{\"keccak256\":\"0x9ba74a3b0a11693e622380807d213d5d1250d974e18b2cd768da9cbe719a6778\",\"urls\":[\"bzz-raw://0808d721ed9e05707526ee134faa051d707a95ee6b8bd6e0b1972275da8e5723\",\"dweb:/ipfs/QmcTTPu9xgckfWdbFUAcr2RAgk3J6vzyR4FpV798TjFMeN\"],\"license\":\"MIT\"},\"src/libraries/rlp/RLPWriter.sol\":{\"keccak256\":\"0x60ac401490f321c9c55e996a2c65151cd5e60de5f8f297e7c94d541c29820bb6\",\"urls\":[\"bzz-raw://070f5814db07e4a89173d44a36d90e4261ce530f7336034c01635347f2c2d88b\",\"dweb:/ipfs/QmXqr9yW5Kc8MYgr5wSehU5AiqS9pZ4FKxv7vwiwpZCcyV\"],\"license\":\"MIT\"},\"src/libraries/trie/MerkleTrie.sol\":{\"keccak256\":\"0xf8ba770ee6666e73ae43184c700e9c704b2c4ace71f9e3c2227ddc11a8148b4c\",\"urls\":[\"bzz-raw://4702ccee1fe44aea3ee01d59e6152eb755da083f786f00947fec4437c064fe74\",\"dweb:/ipfs/QmQjFj5J7hrEM1dxJjFszzW2Cs7g7eMhYNBXonF2DXBstE\"],\"license\":\"MIT\"},\"src/libraries/trie/SecureMerkleTrie.sol\":{\"keccak256\":\"0xeaff8315cfd21197bc6bc859c2decf5d4f4838c9c357c502cdf2b1eac863d288\",\"urls\":[\"bzz-raw://79dcdcaa560aea51d138da4f5dc553a1808b6de090b2dc1629f18375edbff681\",\"dweb:/ipfs/QmbE4pUPhf5fLKW4W6cEjhQs55gEDvHmbmoBqkW1yz3bnw\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"},\"src/vendor/AddressAliasHelper.sol\":{\"keccak256\":\"0x6ecb83b4ec80fbe49c22f4f95d90482de64660ef5d422a19f4d4b04df31c1237\",\"urls\":[\"bzz-raw://1d0885be6e473962f9a0622176a22300165ac0cc1a1d7f2e22b11c3d656ace88\",\"dweb:/ipfs/QmPRa3KmRpXW5P9ykveKRDgYN5zYo4cYLAYSnoqHX3KnXR\"],\"license\":\"Apache-2.0\"}},\"version\":1}", - "numDeployments": 7, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 45409, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 45412, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 74555, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "params", - "offset": 0, - "slot": "1", - "type": "t_struct(ResourceParams)74538_storage" - }, - { - "astId": 74560, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "__gap", - "offset": 0, - "slot": "2", - "type": "t_array(t_uint256)48_storage" - }, - { - "astId": 73646, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "l2Sender", - "offset": 0, - "slot": "50", - "type": "t_address" - }, - { - "astId": 73651, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "finalizedWithdrawals", - "offset": 0, - "slot": "51", - "type": "t_mapping(t_bytes32,t_bool)" - }, - { - "astId": 73657, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "provenWithdrawals", - "offset": 0, - "slot": "52", - "type": "t_mapping(t_bytes32,t_struct(ProvenWithdrawal)73627_storage)" - }, - { - "astId": 73660, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "spacer_53_0_1", - "offset": 0, - "slot": "53", - "type": "t_bool" - }, - { - "astId": 73664, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "superchainConfig", - "offset": 1, - "slot": "53", - "type": "t_contract(SuperchainConfig)75085" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)48_storage": { - "encoding": "inplace", - "label": "uint256[48]", - "numberOfBytes": "1536", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "encoding": "inplace", - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(SuperchainConfig)75085": { - "encoding": "inplace", - "label": "contract SuperchainConfig", - "numberOfBytes": "20" - }, - "t_mapping(t_bytes32,t_bool)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => bool)", - "numberOfBytes": "32", - "value": "t_bool" - }, - "t_mapping(t_bytes32,t_struct(ProvenWithdrawal)73627_storage)": { - "encoding": "mapping", - "key": "t_bytes32", - "label": "mapping(bytes32 => struct OptimismPortal.ProvenWithdrawal)", - "numberOfBytes": "32", - "value": "t_struct(ProvenWithdrawal)73627_storage" - }, - "t_struct(ProvenWithdrawal)73627_storage": { - "encoding": "inplace", - "label": "struct OptimismPortal.ProvenWithdrawal", - "numberOfBytes": "64", - "members": [ - { - "astId": 73622, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "outputRoot", - "offset": 0, - "slot": "0", - "type": "t_bytes32" - }, - { - "astId": 73624, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "timestamp", - "offset": 0, - "slot": "1", - "type": "t_uint128" - }, - { - "astId": 73626, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "l2OutputIndex", - "offset": 16, - "slot": "1", - "type": "t_uint128" - } - ] - }, - "t_struct(ResourceParams)74538_storage": { - "encoding": "inplace", - "label": "struct ResourceMetering.ResourceParams", - "numberOfBytes": "32", - "members": [ - { - "astId": 74533, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "prevBaseFee", - "offset": 0, - "slot": "0", - "type": "t_uint128" - }, - { - "astId": 74535, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "prevBoughtGas", - "offset": 16, - "slot": "0", - "type": "t_uint64" - }, - { - "astId": 74537, - "contract": "src/L1/OptimismPortal.sol:OptimismPortal", - "label": "prevBlockNum", - "offset": 24, - "slot": "0", - "type": "t_uint64" - } - ] - }, - "t_uint128": { - "encoding": "inplace", - "label": "uint128", - "numberOfBytes": "16" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint64": { - "encoding": "inplace", - "label": "uint64", - "numberOfBytes": "8" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x2a888e2fbb01160013245a373a978b839a15bde2756fa4d3ff2dcb90b83c1f2a", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "GUARDIAN()": { - "notice": "Getter function for the address of the guardian. This will be removed in the future, use `SuperchainConfig.guardian()` instead.Address of the guardian." - }, - "L2_ORACLE()": { - "notice": "Address of the L2OutputOracle contract. This will be removed in the future, use `l2Oracle` instead." - }, - "SYSTEM_CONFIG()": { - "notice": "Address of the SystemConfig contract. This will be removed in the future, use `systemConfig` instead." - }, - "constructor": { - "notice": "Constructs the OptimismPortal contract." - }, - "depositTransaction(address,uint256,uint64,bool,bytes)": { - "notice": "Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in deriving deposit transactions. Note that if a deposit is made by a contract, its address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider using the CrossDomainMessenger contracts for a simpler developer experience." - }, - "donateETH()": { - "notice": "Accepts ETH value without triggering a deposit to L2. This function mainly exists for the sake of the migration between the legacy Optimism system and Bedrock." - }, - "finalizeWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes))": { - "notice": "Finalizes a withdrawal transaction." - }, - "finalizedWithdrawals(bytes32)": { - "notice": "A list of withdrawal hashes which have been successfully finalized." - }, - "guardian()": { - "notice": "Getter function for the address of the guardian. This will be removed in the future, use `SuperchainConfig.guardian()` instead.Address of the guardian." - }, - "initialize(address)": { - "notice": "Initializer." - }, - "isOutputFinalized(uint256)": { - "notice": "Determine if a given output is finalized. Reverts if the call to L2_ORACLE.getL2Output reverts. Returns a boolean otherwise." - }, - "l2Oracle()": { - "notice": "Getter function for the address of the L2OutputOracle on this chain.Address of the L2OutputOracle on this chain." - }, - "l2Sender()": { - "notice": "Address of the L2 account which initiated a withdrawal in this transaction. If the of this variable is the default L2 sender address, then we are NOT inside of a call to finalizeWithdrawalTransaction." - }, - "minimumGasLimit(uint64)": { - "notice": "Computes the minimum gas limit for a deposit. The minimum gas limit linearly increases based on the size of the calldata. This is to prevent users from creating L2 resource usage without paying for it. This function can be used when interacting with the portal to ensure forwards compatibility." - }, - "params()": { - "notice": "EIP-1559 style gas parameters." - }, - "paused()": { - "notice": "Getter for the current paused status." - }, - "proveWithdrawalTransaction((uint256,address,address,uint256,uint256,bytes),uint256,(bytes32,bytes32,bytes32,bytes32),bytes[])": { - "notice": "Proves a withdrawal transaction." - }, - "provenWithdrawals(bytes32)": { - "notice": "A mapping of withdrawal hashes to `ProvenWithdrawal` data." - }, - "superchainConfig()": { - "notice": "The address of the Superchain Config contract." - }, - "systemConfig()": { - "notice": "Getter function for the address of the SystemConfig on this chain.Address of the SystemConfig on this chain." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "TransactionDeposited(address,address,uint256,bytes)": { - "notice": "Emitted when a transaction is deposited from L1 to L2. The parameters of this event are read by the rollup node and used to derive deposit transactions on L2." - }, - "WithdrawalFinalized(bytes32,bool)": { - "notice": "Emitted when a withdrawal transaction is finalized." - }, - "WithdrawalProven(bytes32,address,address)": { - "notice": "Emitted when a withdrawal transaction is proven." - } - }, - "notice": "The OptimismPortal is a low-level contract responsible for passing messages between L1 and L2. Messages sent directly to the OptimismPortal have no form of replayability. Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/sepolia/OptimismPortalProxy.json b/packages/contracts-bedrock/deployments/sepolia/OptimismPortalProxy.json deleted file mode 100644 index 745066c478fe..000000000000 --- a/packages/contracts-bedrock/deployments/sepolia/OptimismPortalProxy.json +++ /dev/null @@ -1,256 +0,0 @@ -{ - "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" - } - ], - "address": "0x16Fc5058F25648194471939df75CF27A2fdC48BC", - "args": [ - "0x189aBAAaa82DfC015A588A7dbaD6F13b1D3485Bc" - ], - "bytecode": "0x608060405234801561001057600080fd5b5060405161091838038061091883398101604081905261002f916100b2565b6100388161003e565b506100e2565b60006100566000805160206108f88339815191525490565b6000805160206108f8833981519152839055604080516001600160a01b038084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b6000602082840312156100c457600080fd5b81516001600160a01b03811681146100db57600080fd5b9392505050565b610807806100f16000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103", - "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106d9565b610224565b6100a86100a33660046106f4565b610296565b6040516100b59190610777565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106d9565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ea565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060b565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81905560405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60006106357fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038390556040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201529192507f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a15050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d457600080fd5b919050565b6000602082840312156106eb57600080fd5b610412826106b0565b60008060006040848603121561070957600080fd5b610712846106b0565b9250602084013567ffffffffffffffff8082111561072f57600080fd5b818601915086601f83011261074357600080fd5b81358181111561075257600080fd5b87602082850101111561076457600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a457858101830151858201604001528201610788565b818111156107b6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "admin()": { - "returns": { - "_0": "Owner address." - } - }, - "changeAdmin(address)": { - "params": { - "_admin": "New owner of the proxy contract." - } - }, - "constructor": { - "params": { - "_admin": "Address of the initial contract admin. Admin as the ability to access the transparent proxy interface." - } - }, - "implementation()": { - "returns": { - "_0": "Implementation address." - } - }, - "upgradeTo(address)": { - "params": { - "_implementation": "Address of the implementation contract." - } - }, - "upgradeToAndCall(address,bytes)": { - "params": { - "_data": "Calldata to delegatecall the new implementation with.", - "_implementation": "Address of the implementation contract." - } - } - }, - "events": { - "AdminChanged(address,address)": { - "params": { - "newAdmin": "The new owner of the contract", - "previousAdmin": "The previous owner of the contract" - } - }, - "Upgraded(address)": { - "params": { - "implementation": "The address of the implementation contract" - } - } - }, - "title": "Proxy" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\",\"indexed\":false},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"AdminChanged\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"Upgraded\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"changeAdmin\"},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"upgradeTo\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\",\"name\":\"upgradeToAndCall\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}]},{\"inputs\":[],\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"Owner address.\"}},\"changeAdmin(address)\":{\"params\":{\"_admin\":\"New owner of the proxy contract.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the initial contract admin. Admin as the ability to access the transparent proxy interface.\"}},\"implementation()\":{\"returns\":{\"_0\":\"Implementation address.\"}},\"upgradeTo(address)\":{\"params\":{\"_implementation\":\"Address of the implementation contract.\"}},\"upgradeToAndCall(address,bytes)\":{\"params\":{\"_data\":\"Calldata to delegatecall the new implementation with.\",\"_implementation\":\"Address of the implementation contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Gets the owner of the proxy contract.\"},\"changeAdmin(address)\":{\"notice\":\"Changes the owner of the proxy contract. Only callable by the owner.\"},\"constructor\":{\"notice\":\"Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible.\"},\"upgradeTo(address)\":{\"notice\":\"Set the implementation contract address. The code at the given address will execute when this contract is called.\"},\"upgradeToAndCall(address,bytes)\":{\"notice\":\"Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/universal/Proxy.sol\":\"Proxy\"},\"libraries\":{}},\"sources\":{\"src/universal/Proxy.sol\":{\"keccak256\":\"0x783aed9ff90b38a9898be5fb18699b3b249f012bc2c33f6537e1ab9f6444478f\",\"urls\":[\"bzz-raw://b119b1b68874f4d92a89cc05a4f0d25da73a959747a81e26739739a52895b844\",\"dweb:/ipfs/QmbKZqMd6CsM7annE7bCXcCi72syJAX3qtuFNPEGMCp13W\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 4, - "receipt": { - "transactionHash": "0xbc4e72f21589ed2f7b018fd442dff1804ba03d678731700e3d14bfea95179ddd", - "transactionIndex": "0x5", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", - "to": null, - "cumulativeGasUsed": "0x419438", - "gasUsed": "0x7feb8", - "contractAddress": "0x16Fc5058F25648194471939df75CF27A2fdC48BC", - "logs": [ - { - "address": "0x16Fc5058F25648194471939df75CF27A2fdC48BC", - "topics": [ - "0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000189abaaaa82dfc015a588a7dbad6f13b1d3485bc", - "blockHash": "0xa6d331f0f1bd46d1aa2c3575c353e2b981d69bb858e6c58c4d24d75115986a68", - "blockNumber": "0x3e1f50", - "transactionHash": "0xbc4e72f21589ed2f7b018fd442dff1804ba03d678731700e3d14bfea95179ddd", - "transactionIndex": "0x5", - "logIndex": "0x5", - "removed": false - } - ], - "status": "0x1", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000800000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000010000000000000000000000000000000000000000000000000000000", - "type": "0x2", - "effectiveGasPrice": "0xbec78df7" - }, - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [], - "types": {} - }, - "transactionHash": "0xbc4e72f21589ed2f7b018fd442dff1804ba03d678731700e3d14bfea95179ddd", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "admin()": { - "notice": "Gets the owner of the proxy contract." - }, - "changeAdmin(address)": { - "notice": "Changes the owner of the proxy contract. Only callable by the owner." - }, - "constructor": { - "notice": "Sets the initial admin during contract deployment. Admin address is stored at the EIP-1967 admin storage slot so that accidental storage collision with the implementation is not possible." - }, - "upgradeTo(address)": { - "notice": "Set the implementation contract address. The code at the given address will execute when this contract is called." - }, - "upgradeToAndCall(address,bytes)": { - "notice": "Set the implementation and call a function in a single transaction. Useful to ensure atomic execution of initialization-based upgrades." - } - }, - "events": { - "AdminChanged(address,address)": { - "notice": "An event that is emitted each time the owner is upgraded. This event is part of the EIP-1967 specification." - }, - "Upgraded(address)": { - "notice": "An event that is emitted each time the implementation is changed. This event is part of the EIP-1967 specification." - } - }, - "notice": "Proxy is a transparent proxy that passes through the call if the caller is the owner or if the caller is address(0), meaning that the call originated from an off-chain simulation." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/sepolia/ProtocolVersions.json b/packages/contracts-bedrock/deployments/sepolia/ProtocolVersions.json deleted file mode 100644 index b34ca4bc7b31..000000000000 --- a/packages/contracts-bedrock/deployments/sepolia/ProtocolVersions.json +++ /dev/null @@ -1,496 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "version", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "enum ProtocolVersions.UpdateType", - "name": "updateType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "ConfigUpdate", - "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": "RECOMMENDED_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REQUIRED_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "VERSION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - }, - { - "internalType": "ProtocolVersion", - "name": "_required", - "type": "uint256" - }, - { - "internalType": "ProtocolVersion", - "name": "_recommended", - "type": "uint256" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "recommended", - "outputs": [ - { - "internalType": "ProtocolVersion", - "name": "out_", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "required", - "outputs": [ - { - "internalType": "ProtocolVersion", - "name": "out_", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "ProtocolVersion", - "name": "_recommended", - "type": "uint256" - } - ], - "name": "setRecommended", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "ProtocolVersion", - "name": "_required", - "type": "uint256" - } - ], - "name": "setRequired", - "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" - } - ], - "address": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "args": [], - "bytecode": "0x60806040523480156200001157600080fd5b506200002261dead60008062000028565b620004c9565b600054600390610100900460ff161580156200004b575060005460ff8083169116105b620000b45760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805461ffff191660ff831617610100179055620000d26200013a565b620000dd84620001a2565b620000e88362000221565b620000f382620002d1565b6000805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b600054610100900460ff16620001965760405162461bcd60e51b815260206004820152602b602482015260008051602062000e9683398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000ab565b620001a062000332565b565b620001ac62000399565b6001600160a01b038116620002135760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620000ab565b6200021e81620003f5565b50565b620002676200025260017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16200044b565b60001b826200044760201b620004f51760201c565b6000816040516020016200027d91815260200190565b60408051601f19818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051620002c5919062000471565b60405180910390a35050565b620003026200025260017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6200044b565b6000816040516020016200031891815260200190565b60408051601f198184030181529190529050600162000292565b600054610100900460ff166200038e5760405162461bcd60e51b815260206004820152602b602482015260008051602062000e9683398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000ab565b620001a033620003f5565b6033546001600160a01b03163314620001a05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620000ab565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b9055565b6000828210156200046c57634e487b7160e01b600052601160045260246000fd5b500390565b600060208083528351808285015260005b81811015620004a05785810183015185820160400152820162000482565b81811115620004b3576000604083870101525b50601f01601f1916929092016040019392505050565b6109bd80620004d96000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e736600461085d565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161010091906108e1565b6100ec61016036600461085d565b61021d565b6100ec61022e565b6100ec61017b366004610924565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103ad565b6100f66103e6565b6100ec6101c6366004610957565b610416565b6100f66104ca565b6100f6600081565b6101e36104f9565b6101ec8161057a565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b81565b6102256104f9565b6101ec81610632565b6102366104f9565b61024060006106ac565b565b600054600390610100900460ff16158015610264575060005460ff8083169116105b6102f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905561032e610723565b61033784610416565b6103408361057a565b61034982610632565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b60006103e16103dd60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b5490565b905090565b60006103e16103dd60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b61041e6104f9565b73ffffffffffffffffffffffffffffffffffffffff81166104c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102ec565b6101ec816106ac565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102ec565b6105ad6105a860017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b829055565b6000816040516020016105c291815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161062691906108e1565b60405180910390a35050565b6106606105a860017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b60008160405160200161067591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060016105f5565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166107ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ec565b610240600054610100900460ff16610854576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ec565b610240336106ac565b60006020828403121561086f57600080fd5b5035919050565b6000815180845260005b8181101561089c57602081850181015186830182015201610880565b818111156108ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006108f46020830184610876565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091f57600080fd5b919050565b60008060006060848603121561093957600080fd5b610942846108fb565b95602085013595506040909401359392505050565b60006020828403121561096957600080fd5b6108f4826108fb565b6000828210156109ab577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e736600461085d565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161010091906108e1565b6100ec61016036600461085d565b61021d565b6100ec61022e565b6100ec61017b366004610924565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103ad565b6100f66103e6565b6100ec6101c6366004610957565b610416565b6100f66104ca565b6100f6600081565b6101e36104f9565b6101ec8161057a565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b81565b6102256104f9565b6101ec81610632565b6102366104f9565b61024060006106ac565b565b600054600390610100900460ff16158015610264575060005460ff8083169116105b6102f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905561032e610723565b61033784610416565b6103408361057a565b61034982610632565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b60006103e16103dd60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b5490565b905090565b60006103e16103dd60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b61041e6104f9565b73ffffffffffffffffffffffffffffffffffffffff81166104c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102ec565b6101ec816106ac565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102ec565b6105ad6105a860017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace1610972565b829055565b6000816040516020016105c291815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161062691906108e1565b60405180910390a35050565b6106606105a860017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b610972565b60008160405160200161067591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060016105f5565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff166107ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ec565b610240600054610100900460ff16610854576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016102ec565b610240336106ac565b60006020828403121561086f57600080fd5b5035919050565b6000815180845260005b8181101561089c57602081850181015186830182015201610880565b818111156108ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006108f46020830184610876565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091f57600080fd5b919050565b60008060006060848603121561093957600080fd5b610942846108fb565b95602085013595506040909401359392505050565b60006020828403121561096957600080fd5b6108f4826108fb565b6000828210156109ab577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "initialize(address,uint256,uint256)": { - "params": { - "_owner": "Initial owner of the contract.", - "_recommended": "Recommended protocol version to operate on thi chain.", - "_required": "Required protocol version to operate on this chain." - } - }, - "owner()": { - "details": "Returns the address of the current owner." - }, - "recommended()": { - "returns": { - "out_": "Recommended protocol version to sync to the head of the chain." - } - }, - "renounceOwnership()": { - "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." - }, - "required()": { - "returns": { - "out_": "Required protocol version to sync to the head of the chain." - } - }, - "setRecommended(uint256)": { - "params": { - "_recommended": "New recommended protocol version." - } - }, - "setRequired(uint256)": { - "params": { - "_required": "New required protocol version." - } - }, - "transferOwnership(address)": { - "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." - } - }, - "events": { - "ConfigUpdate(uint256,uint8,bytes)": { - "params": { - "data": "Encoded update data.", - "updateType": "Type of update.", - "version": "ProtocolVersion version." - } - } - }, - "title": "ProtocolVersions" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\",\"indexed\":true},{\"internalType\":\"enum ProtocolVersions.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ConfigUpdate\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true}],\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"RECOMMENDED_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"REQUIRED_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"ProtocolVersion\",\"name\":\"_required\",\"type\":\"uint256\"},{\"internalType\":\"ProtocolVersion\",\"name\":\"_recommended\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"recommended\",\"outputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"out_\",\"type\":\"uint256\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"renounceOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"required\",\"outputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"out_\",\"type\":\"uint256\"}]},{\"inputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"_recommended\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setRecommended\"},{\"inputs\":[{\"internalType\":\"ProtocolVersion\",\"name\":\"_required\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"setRequired\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"transferOwnership\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"initialize(address,uint256,uint256)\":{\"params\":{\"_owner\":\"Initial owner of the contract.\",\"_recommended\":\"Recommended protocol version to operate on thi chain.\",\"_required\":\"Required protocol version to operate on this chain.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"recommended()\":{\"returns\":{\"out_\":\"Recommended protocol version to sync to the head of the chain.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"required()\":{\"returns\":{\"out_\":\"Required protocol version to sync to the head of the chain.\"}},\"setRecommended(uint256)\":{\"params\":{\"_recommended\":\"New recommended protocol version.\"}},\"setRequired(uint256)\":{\"params\":{\"_required\":\"New required protocol version.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"RECOMMENDED_SLOT()\":{\"notice\":\"Storage slot that the recommended protocol version is stored at.\"},\"REQUIRED_SLOT()\":{\"notice\":\"Storage slot that the required protocol version is stored at.\"},\"VERSION()\":{\"notice\":\"Version identifier, used for upgrades.\"},\"constructor\":{\"notice\":\"Constructs the ProtocolVersion contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)` A zero version is considered empty and is ignored by nodes.\"},\"initialize(address,uint256,uint256)\":{\"notice\":\"Initializer.\"},\"recommended()\":{\"notice\":\"High level getter for the recommended protocol version.\"},\"required()\":{\"notice\":\"High level getter for the required protocol version.\"},\"setRecommended(uint256)\":{\"notice\":\"Updates the recommended protocol version. Can only be called by the owner.\"},\"setRequired(uint256)\":{\"notice\":\"Updates the required protocol version. Can only be called by the owner.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=lib/clones-with-immutable-args/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@rari-capital/solmate/=lib/solmate/\",\":clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\":ds-test/=lib/forge-std/lib/ds-test/src/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":safe-contracts/=lib/safe-contracts/contracts/\",\":solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/ProtocolVersions.sol\":\"ProtocolVersions\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xd15c3e400531f00203839159b2b8e7209c5158b35618f570c695b7e47f12e9f0\",\"urls\":[\"bzz-raw://b600b852e0597aa69989cc263111f02097e2827edc1bdc70306303e3af5e9929\",\"dweb:/ipfs/QmU4WfM28A1nDqghuuGeFmN3CnVrk6opWtiF65K4vhFPeC\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xb3ebde1c8d27576db912d87c3560dab14adfb9cd001be95890ec4ba035e652e7\",\"urls\":[\"bzz-raw://a709421c4f5d4677db8216055d2d4dac96a613efdb08178a9f7041f0c5cef689\",\"dweb:/ipfs/QmYs2rStvVLDnSJs8HgaMD1ABwoKKWdiVbQyNfLfFWTjTy\"],\"license\":\"MIT\"},\"lib/solmate/src/utils/FixedPointMathLib.sol\":{\"keccak256\":\"0x622fcd8a49e132df5ec7651cc6ae3aaf0cf59bdcd67a9a804a1b9e2485113b7d\",\"urls\":[\"bzz-raw://af77088eb606427d4c55e578984a615779c86bc30646a20f7bb27299ba390f7c\",\"dweb:/ipfs/QmZGQdhdQDtHc7gZXWrKXgA3govc74X8U63BiWhPQK3mK8\"],\"license\":\"MIT\"},\"src/L1/ProtocolVersions.sol\":{\"keccak256\":\"0xa283721c36e2ba3ea1c61faebc364a8884bf3a276f80374cc8017d0e23ea1dfc\",\"urls\":[\"bzz-raw://4ee23cbc9772213c637c767747e5fb1db7c3f0f17d6a1ff576b638f25c6799e8\",\"dweb:/ipfs/QmfKZfFC6fyhQdLk2YrjVBL6eRX1d9CTrPHj7fNPUNXmEq\"],\"license\":\"MIT\"},\"src/L1/ResourceMetering.sol\":{\"keccak256\":\"0xa4d524f2a5e91a0b63a62603e712001c51c77e8371b93cbb576bcb7d074b7588\",\"urls\":[\"bzz-raw://d6d8141b6c6dc72d2e684c1ae388c005fd78c9ca7fc9c15dddebd227ca4fd730\",\"dweb:/ipfs/QmPfJrR4qssu769TDWJnxdTozqKtZUxiY8fs95bhfECTvG\"],\"license\":\"MIT\"},\"src/libraries/Arithmetic.sol\":{\"keccak256\":\"0x06a5a8b00527843f0cfc1bb3c0661316966a6cc432f88be31f23cde78cd07560\",\"urls\":[\"bzz-raw://d5209e78e5415c0bf8b350362a825cc56152811abd6fcf2df3d4fa47766d3dee\",\"dweb:/ipfs/Qmf43xyc4Um32NmccayDfhm8kSnS2mhHXpPZnwABJS7cWm\"],\"license\":\"MIT\"},\"src/libraries/Burn.sol\":{\"keccak256\":\"0x90a795bcea3ef06d6d5011256c4bd63d1a4271f519246dbf1ee3e8f1c0e21010\",\"urls\":[\"bzz-raw://9f60c3aa77cf0c484ddda4754157cff4dc0e2eace4bea67990daff4c0612ab5f\",\"dweb:/ipfs/QmSYGanMFve9uBC17X7hFneSFnwnJxz86Jgh6MX9BRMweb\"],\"license\":\"MIT\"},\"src/libraries/Constants.sol\":{\"keccak256\":\"0xe12e392f05f80d3837c9392d016471181ae1ee6b84ea91b4e125e6523e5f18a2\",\"urls\":[\"bzz-raw://a3509231c228b7a4352573cd422cf0260dcbb94cfd915e5b664643db5475a5b7\",\"dweb:/ipfs/QmU2QERY4mHxqWFqSE5Exsy6Ftc5MTjTtYHC11fahLJWDC\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x902a0a815272a5b76c647d9e82101aca765e9835a6624d0857088b9da0f58afd\",\"urls\":[\"bzz-raw://9c39a697aacb0a2eac0bf1fbd7790d835a685c61006f6d3464e19cbc96a24480\",\"dweb:/ipfs/QmV3T8ZTRWPB5CNuZjxwWQNoENd7W4SoBMnFG6Y6g6xYV4\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 2, - "receipt": { - "transactionHash": "0x3e058627192fd891a3d6660f21a874e78bac77643013ef46505962d9c7e68477", - "transactionIndex": "0x7", - "blockHash": "0x1757e9d553875bd033f03f68b1e4494db5258e626f0853156717dd64b6cdb98a", - "blockNumber": "0x438a06", - "from": "0x18394B52d3Cb931dfA76F63251919D051953413d", - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "cumulativeGasUsed": "0x49734a", - "gasUsed": "0xa3523", - "contractAddress": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "logs": [ - { - "address": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c" - ], - "data": "0x", - "blockHash": "0x1757e9d553875bd033f03f68b1e4494db5258e626f0853156717dd64b6cdb98a", - "blockNumber": "0x438a06", - "transactionHash": "0x3e058627192fd891a3d6660f21a874e78bac77643013ef46505962d9c7e68477", - "transactionIndex": "0x7", - "logIndex": "0x1c", - "removed": false - }, - { - "address": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "topics": [ - "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", - "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "0x000000000000000000000000000000000000000000000000000000000000dead" - ], - "data": "0x", - "blockHash": "0x1757e9d553875bd033f03f68b1e4494db5258e626f0853156717dd64b6cdb98a", - "blockNumber": "0x438a06", - "transactionHash": "0x3e058627192fd891a3d6660f21a874e78bac77643013ef46505962d9c7e68477", - "transactionIndex": "0x7", - "logIndex": "0x1d", - "removed": false - }, - { - "address": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "topics": [ - "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x1757e9d553875bd033f03f68b1e4494db5258e626f0853156717dd64b6cdb98a", - "blockNumber": "0x438a06", - "transactionHash": "0x3e058627192fd891a3d6660f21a874e78bac77643013ef46505962d9c7e68477", - "transactionIndex": "0x7", - "logIndex": "0x1e", - "removed": false - }, - { - "address": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "topics": [ - "0x1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001" - ], - "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x1757e9d553875bd033f03f68b1e4494db5258e626f0853156717dd64b6cdb98a", - "blockNumber": "0x438a06", - "transactionHash": "0x3e058627192fd891a3d6660f21a874e78bac77643013ef46505962d9c7e68477", - "transactionIndex": "0x7", - "logIndex": "0x1f", - "removed": false - }, - { - "address": "0x42F0bD8313ad456A38061308857b2383fe2c72a0", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000003", - "blockHash": "0x1757e9d553875bd033f03f68b1e4494db5258e626f0853156717dd64b6cdb98a", - "blockNumber": "0x438a06", - "transactionHash": "0x3e058627192fd891a3d6660f21a874e78bac77643013ef46505962d9c7e68477", - "transactionIndex": "0x7", - "logIndex": "0x20", - "removed": false - } - ], - "status": "0x1", - "logsBloom": "0x00000000000010000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000008000001000000040000000000000000000000000000000000000001000000040000000000000000000000000000020000000000000000000800000000000000000000000800000000400000000000000000000004040000000000000000001080000000000000000000000000000001000000000080000400000000000000000000000000000000000000000400000000000000000000040000000000000000000000000000000060000000000000000000000000000000000080000000000000000000008000000000", - "type": "0x2", - "effectiveGasPrice": "0xb3abbc06" - }, - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 29536, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 29539, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - }, - { - "astId": 31067, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage" - }, - { - "astId": 29408, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address" - }, - { - "astId": 29528, - "contract": "src/L1/ProtocolVersions.sol:ProtocolVersions", - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage" - } - ], - "types": { - "t_address": { - "encoding": "inplace", - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "encoding": "inplace", - "label": "uint256[49]", - "numberOfBytes": "1568", - "base": "t_uint256" - }, - "t_array(t_uint256)50_storage": { - "encoding": "inplace", - "label": "uint256[50]", - "numberOfBytes": "1600", - "base": "t_uint256" - }, - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_uint256": { - "encoding": "inplace", - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x3e058627192fd891a3d6660f21a874e78bac77643013ef46505962d9c7e68477", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "RECOMMENDED_SLOT()": { - "notice": "Storage slot that the recommended protocol version is stored at." - }, - "REQUIRED_SLOT()": { - "notice": "Storage slot that the required protocol version is stored at." - }, - "VERSION()": { - "notice": "Version identifier, used for upgrades." - }, - "constructor": { - "notice": "Constructs the ProtocolVersion contract. Cannot set the owner to `address(0)` due to the Ownable contract's implementation, so set it to `address(0xdEaD)` A zero version is considered empty and is ignored by nodes." - }, - "initialize(address,uint256,uint256)": { - "notice": "Initializer." - }, - "recommended()": { - "notice": "High level getter for the recommended protocol version." - }, - "required()": { - "notice": "High level getter for the required protocol version." - }, - "setRecommended(uint256)": { - "notice": "Updates the recommended protocol version. Can only be called by the owner." - }, - "setRequired(uint256)": { - "notice": "Updates the required protocol version. Can only be called by the owner." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "ConfigUpdate(uint256,uint8,bytes)": { - "notice": "Emitted when configuration is updated." - } - }, - "notice": "The ProtocolVersions contract is used to manage superchain protocol version information." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/deployments/sepolia/SuperchainConfig.json b/packages/contracts-bedrock/deployments/sepolia/SuperchainConfig.json deleted file mode 100644 index 94a6aae1f7e4..000000000000 --- a/packages/contracts-bedrock/deployments/sepolia/SuperchainConfig.json +++ /dev/null @@ -1,280 +0,0 @@ -{ - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "enum SuperchainConfig.UpdateType", - "name": "updateType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "ConfigUpdate", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "identifier", - "type": "string" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "GUARDIAN_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PAUSED_SLOT", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "guardian", - "outputs": [ - { - "internalType": "address", - "name": "guardian_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_guardian", - "type": "address" - }, - { - "internalType": "bool", - "name": "_paused", - "type": "bool" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_identifier", - "type": "string" - } - ], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "paused_", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "address": "0x44674AF65D36b9d4AC6ba4717369AF794c75d9BA", - "args": [], - "bytecode": "0x60806040523480156200001157600080fd5b506200001f60008062000025565b62000361565b600054610100900460ff1615808015620000465750600054600160ff909116105b8062000076575062000063306200019460201b620005fd1760201c565b15801562000076575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b6200010d83620001a3565b81156200014857604080518082019091526012815271125b9a5d1a585b1a5e995c881c185d5cd95960721b6020820152620001489062000248565b80156200018f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b620001e9620001d460017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69620002cf565b60001b82620002cb60201b620006191760201c565b6000604080516001600160a01b03841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb910160408051601f19818403018152908290526200023d9162000345565b60405180910390a250565b6200028f6200027960017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7620002cf565b60001b6001620002cb60201b620006191760201c565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea2838181604051620002c0919062000345565b60405180910390a150565b9055565b600082821015620002f057634e487b7160e01b600052601160045260246000fd5b500390565b6000815180845260005b818110156200031d57602081850181015186830182015201620002ff565b8181111562000330576000602083870101525b50601f01601f19169290920160200192915050565b6020815260006200035a6020830184620002f5565b9392505050565b61096b80620003716000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", - "devdoc": { - "version": 1, - "kind": "dev", - "methods": { - "initialize(address,bool)": { - "params": { - "_guardian": "Address of the guardian, can pause the OptimismPortal.", - "_paused": "Initial paused status." - } - }, - "pause(string)": { - "params": { - "_identifier": "(Optional) A string to identify provenance of the pause transaction." - } - } - }, - "events": { - "ConfigUpdate(uint8,bytes)": { - "params": { - "data": "Encoded update data.", - "updateType": "Type of update." - } - }, - "Paused(string)": { - "params": { - "identifier": "A string helping to identify provenance of the pause transaction." - } - } - }, - "title": "SuperchainConfig" - }, - "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"enum SuperchainConfig.UpdateType\",\"name\":\"updateType\",\"type\":\"uint8\",\"indexed\":true},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false}],\"type\":\"event\",\"name\":\"ConfigUpdate\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Initialized\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"identifier\",\"type\":\"string\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Paused\",\"anonymous\":false},{\"inputs\":[],\"type\":\"event\",\"name\":\"Unpaused\",\"anonymous\":false},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"GUARDIAN_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"PAUSED_SLOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"guardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"guardian_\",\"type\":\"address\"}]},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_guardian\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_paused\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"initialize\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_identifier\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"pause\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}]},{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"unpause\"},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"initialize(address,bool)\":{\"params\":{\"_guardian\":\"Address of the guardian, can pause the OptimismPortal.\",\"_paused\":\"Initial paused status.\"}},\"pause(string)\":{\"params\":{\"_identifier\":\"(Optional) A string to identify provenance of the pause transaction.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"GUARDIAN_SLOT()\":{\"notice\":\"The address of the guardian, which can pause withdrawals from the System. It can only be modified by an upgrade.\"},\"PAUSED_SLOT()\":{\"notice\":\"Whether or not the Superchain is paused.\"},\"constructor\":{\"notice\":\"Constructs the SuperchainConfig contract.\"},\"guardian()\":{\"notice\":\"Getter for the guardian address.\"},\"initialize(address,bool)\":{\"notice\":\"Initializer.\"},\"pause(string)\":{\"notice\":\"Pauses withdrawals.\"},\"paused()\":{\"notice\":\"Getter for the current paused status.\"},\"unpause()\":{\"notice\":\"Unpauses withdrawals.\"},\"version()\":{\"notice\":\"Semantic version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\"@cwia/=lib/clones-with-immutable-args/src/\",\"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\"@rari-capital/solmate/=lib/solmate/\",\"clones-with-immutable-args/=lib/clones-with-immutable-args/src/\",\"ds-test/=lib/forge-std/lib/ds-test/src/\",\"forge-std/=lib/forge-std/src/\",\"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\"safe-contracts/=lib/safe-contracts/contracts/\",\"solmate/=lib/solmate/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"src/L1/SuperchainConfig.sol\":\"SuperchainConfig\"},\"libraries\":{}},\"sources\":{\"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x2a21b14ff90012878752f230d3ffd5c3405e5938d06c97a7d89c0a64561d0d66\",\"urls\":[\"bzz-raw://3313a8f9bb1f9476857c9050067b31982bf2140b83d84f3bc0cec1f62bbe947f\",\"dweb:/ipfs/Qma17Pk8NRe7aB4UD3jjVxk7nSFaov3eQyv86hcyqkwJRV\"],\"license\":\"MIT\"},\"lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"],\"license\":\"MIT\"},\"src/L1/SuperchainConfig.sol\":{\"keccak256\":\"0x3dd454d7ec9e2a90a6daf4b0c2f9ba371eae564b6e535aa88884e50de7df340a\",\"urls\":[\"bzz-raw://710bcccf6a1071171c45c2594e896ef5a26080a00dd3586e9ce80148a731d55b\",\"dweb:/ipfs/QmRSSYggh5woP8Xd9SHhuNt6tF7hMaSUMMk8W5zWk34NeL\"],\"license\":\"MIT\"},\"src/libraries/Storage.sol\":{\"keccak256\":\"0x7ce27a05552aa69afa6b2ab6684dfe99f27366cf8ef2046baeb1fb62fff0022f\",\"urls\":[\"bzz-raw://a6a24f3ed56681720707a5ab0372fd67fcb1a4f6fb072c7140cda28bdb70f269\",\"dweb:/ipfs/QmW9uTpUULV4xmP7A7MoBDeDhVfQgmJG5qVUFGtXxWpWWK\"],\"license\":\"MIT\"},\"src/universal/ISemver.sol\":{\"keccak256\":\"0xba34562a8026f59886d2e07d1d58d90b9691d00e0788c6263cef6c22740cab44\",\"urls\":[\"bzz-raw://0826f998632f83c103c3085bf2e872db79a69022b6d2e0444c83a64ca5283c2a\",\"dweb:/ipfs/QmcJ7PNqkAfKqbjFGRordtAg1v9DvcBSKvdTkVvciLyvQR\"],\"license\":\"MIT\"}},\"version\":1}", - "numDeployments": 2, - "receipt": "", - "solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "storageLayout": { - "storage": [ - { - "astId": 45395, - "contract": "src/L1/SuperchainConfig.sol:SuperchainConfig", - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8" - }, - { - "astId": 45398, - "contract": "src/L1/SuperchainConfig.sol:SuperchainConfig", - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool" - } - ], - "types": { - "t_bool": { - "encoding": "inplace", - "label": "bool", - "numberOfBytes": "1" - }, - "t_uint8": { - "encoding": "inplace", - "label": "uint8", - "numberOfBytes": "1" - } - } - }, - "transactionHash": "0x4653e1ddaa6faf70024e01ef4ddbb20e4becd28cc3864f22d06cb0f0a2ce5820", - "userdoc": { - "version": 1, - "kind": "user", - "methods": { - "GUARDIAN_SLOT()": { - "notice": "The address of the guardian, which can pause withdrawals from the System. It can only be modified by an upgrade." - }, - "PAUSED_SLOT()": { - "notice": "Whether or not the Superchain is paused." - }, - "constructor": { - "notice": "Constructs the SuperchainConfig contract." - }, - "guardian()": { - "notice": "Getter for the guardian address." - }, - "initialize(address,bool)": { - "notice": "Initializer." - }, - "pause(string)": { - "notice": "Pauses withdrawals." - }, - "paused()": { - "notice": "Getter for the current paused status." - }, - "unpause()": { - "notice": "Unpauses withdrawals." - }, - "version()": { - "notice": "Semantic version." - } - }, - "events": { - "ConfigUpdate(uint8,bytes)": { - "notice": "Emitted when configuration is updated." - }, - "Paused(string)": { - "notice": "Emitted when the pause is triggered." - }, - "Unpaused()": { - "notice": "Emitted when the pause is lifted." - } - }, - "notice": "The SuperchainConfig contract is used to manage configuration of global superchain values." - } -} \ No newline at end of file diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 1e32d279feee..51f9db270ffe 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -86,4 +86,5 @@ script = 'scripts-kontrol' src = 'test/kontrol/proofs' out = 'kout-proofs' test = 'test/kontrol/proofs' -script = 'scripts-kontrol' +script = 'test/kontrol/proofs' +ast = true diff --git a/packages/contracts-bedrock/invariant-docs/AddressAliasHelper.md b/packages/contracts-bedrock/invariant-docs/AddressAliasHelper.md index 36251fcfad0c..f7787a436122 100644 --- a/packages/contracts-bedrock/invariant-docs/AddressAliasHelper.md +++ b/packages/contracts-bedrock/invariant-docs/AddressAliasHelper.md @@ -1,6 +1,6 @@ # `AddressAliasHelper` Invariants ## Address aliases are always able to be undone. -**Test:** [`AddressAliasHelper.t.sol#L46`](../test/invariants/AddressAliasHelper.t.sol#L46) +**Test:** [`AddressAliasHelper.t.sol#L48`](../test/invariants/AddressAliasHelper.t.sol#L48) Asserts that an address that has been aliased with `applyL1ToL2Alias` can always be unaliased with `undoL1ToL2Alias`. \ No newline at end of file diff --git a/packages/contracts-bedrock/invariant-docs/Burn.Eth.md b/packages/contracts-bedrock/invariant-docs/Burn.Eth.md index b19d3de5475a..eb11cba92315 100644 --- a/packages/contracts-bedrock/invariant-docs/Burn.Eth.md +++ b/packages/contracts-bedrock/invariant-docs/Burn.Eth.md @@ -1,6 +1,6 @@ # `Burn.Eth` Invariants ## `eth(uint256)` always burns the exact amount of eth passed. -**Test:** [`Burn.Eth.t.sol#L64`](../test/invariants/Burn.Eth.t.sol#L64) +**Test:** [`Burn.Eth.t.sol#L66`](../test/invariants/Burn.Eth.t.sol#L66) Asserts that when `Burn.eth(uint256)` is called, it always burns the exact amount of ETH passed to the function. \ No newline at end of file diff --git a/packages/contracts-bedrock/invariant-docs/Burn.Gas.md b/packages/contracts-bedrock/invariant-docs/Burn.Gas.md index 24f6a0f2df5e..5c343bca23fd 100644 --- a/packages/contracts-bedrock/invariant-docs/Burn.Gas.md +++ b/packages/contracts-bedrock/invariant-docs/Burn.Gas.md @@ -1,6 +1,6 @@ # `Burn.Gas` Invariants ## `gas(uint256)` always burns at least the amount of gas passed. -**Test:** [`Burn.Gas.t.sol#L64`](../test/invariants/Burn.Gas.t.sol#L64) +**Test:** [`Burn.Gas.t.sol#L66`](../test/invariants/Burn.Gas.t.sol#L66) Asserts that when `Burn.gas(uint256)` is called, it always burns at least the amount of gas passed to the function. \ No newline at end of file diff --git a/packages/contracts-bedrock/invariant-docs/CrossDomainMessenger.md b/packages/contracts-bedrock/invariant-docs/CrossDomainMessenger.md index aae30cf5c6c4..4329859f24a3 100644 --- a/packages/contracts-bedrock/invariant-docs/CrossDomainMessenger.md +++ b/packages/contracts-bedrock/invariant-docs/CrossDomainMessenger.md @@ -1,14 +1,14 @@ # `CrossDomainMessenger` Invariants ## A call to `relayMessage` should succeed if at least the minimum gas limit can be supplied to the target context, there is enough gas to complete execution of `relayMessage` after the target context's execution is finished, and the target context did not revert. -**Test:** [`CrossDomainMessenger.t.sol#L144`](../test/invariants/CrossDomainMessenger.t.sol#L144) +**Test:** [`CrossDomainMessenger.t.sol#L143`](../test/invariants/CrossDomainMessenger.t.sol#L143) There are two minimum gas limits here: - The outer min gas limit is for the call from the `OptimismPortal` to the `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function with the `message` and inner limit. - The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target contract. ## A call to `relayMessage` should assign the message hash to the `failedMessages` mapping if not enough gas is supplied to forward `minGasLimit` to the target context or if there is not enough gas to complete execution of `relayMessage` after the target context's execution is finished. -**Test:** [`CrossDomainMessenger.t.sol#L177`](../test/invariants/CrossDomainMessenger.t.sol#L177) +**Test:** [`CrossDomainMessenger.t.sol#L176`](../test/invariants/CrossDomainMessenger.t.sol#L176) There are two minimum gas limits here: - The outer min gas limit is for the call from the `OptimismPortal` to the `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function with the `message` and inner limit. diff --git a/packages/contracts-bedrock/invariant-docs/Encoding.md b/packages/contracts-bedrock/invariant-docs/Encoding.md index ab67a91160e1..460eff43df77 100644 --- a/packages/contracts-bedrock/invariant-docs/Encoding.md +++ b/packages/contracts-bedrock/invariant-docs/Encoding.md @@ -1,11 +1,11 @@ # `Encoding` Invariants ## `convertRoundTripAToB` never fails. -**Test:** [`Encoding.t.sol#L71`](../test/invariants/Encoding.t.sol#L71) +**Test:** [`Encoding.t.sol#L73`](../test/invariants/Encoding.t.sol#L73) Asserts that a raw versioned nonce can be encoded / decoded to reach the same raw value. ## `convertRoundTripBToA` never fails. -**Test:** [`Encoding.t.sol#L80`](../test/invariants/Encoding.t.sol#L80) +**Test:** [`Encoding.t.sol#L82`](../test/invariants/Encoding.t.sol#L82) Asserts that an encoded versioned nonce can always be decoded / re-encoded to reach the same encoded value. \ No newline at end of file diff --git a/packages/contracts-bedrock/invariant-docs/FaultDisputeGame.md b/packages/contracts-bedrock/invariant-docs/FaultDisputeGame.md index 2b2888701575..c54eb974cff7 100644 --- a/packages/contracts-bedrock/invariant-docs/FaultDisputeGame.md +++ b/packages/contracts-bedrock/invariant-docs/FaultDisputeGame.md @@ -1,6 +1,6 @@ # `FaultDisputeGame` Invariants ## FaultDisputeGame always returns all ETH on total resolution -**Test:** [`FaultDisputeGame.t.sol#L38`](../test/invariants/FaultDisputeGame.t.sol#L38) +**Test:** [`FaultDisputeGame.t.sol#L33`](../test/invariants/FaultDisputeGame.t.sol#L33) The FaultDisputeGame contract should always return all ETH in the contract to the correct recipients upon resolution of all outstanding claims. There may never be any ETH left in the contract after a full resolution. \ No newline at end of file diff --git a/packages/contracts-bedrock/invariant-docs/Hashing.md b/packages/contracts-bedrock/invariant-docs/Hashing.md index 0501ed342d25..acf407876d3c 100644 --- a/packages/contracts-bedrock/invariant-docs/Hashing.md +++ b/packages/contracts-bedrock/invariant-docs/Hashing.md @@ -1,16 +1,16 @@ # `Hashing` Invariants ## `hashCrossDomainMessage` reverts if `version` is > `1`. -**Test:** [`Hashing.t.sol#L117`](../test/invariants/Hashing.t.sol#L117) +**Test:** [`Hashing.t.sol#L119`](../test/invariants/Hashing.t.sol#L119) The `hashCrossDomainMessage` function should always revert if the `version` passed is > `1`. ## `version` = `0`: `hashCrossDomainMessage` and `hashCrossDomainMessageV0` are equivalent. -**Test:** [`Hashing.t.sol#L127`](../test/invariants/Hashing.t.sol#L127) +**Test:** [`Hashing.t.sol#L129`](../test/invariants/Hashing.t.sol#L129) If the version passed is 0, `hashCrossDomainMessage` and `hashCrossDomainMessageV0` should be equivalent. ## `version` = `1`: `hashCrossDomainMessage` and `hashCrossDomainMessageV1` are equivalent. -**Test:** [`Hashing.t.sol#L138`](../test/invariants/Hashing.t.sol#L138) +**Test:** [`Hashing.t.sol#L140`](../test/invariants/Hashing.t.sol#L140) If the version passed is 1, `hashCrossDomainMessage` and `hashCrossDomainMessageV1` should be equivalent. \ No newline at end of file diff --git a/packages/contracts-bedrock/invariant-docs/InvariantTest.sol.md b/packages/contracts-bedrock/invariant-docs/InvariantTest.sol.md new file mode 100644 index 000000000000..bd27f490f563 --- /dev/null +++ b/packages/contracts-bedrock/invariant-docs/InvariantTest.sol.md @@ -0,0 +1,2 @@ +# `InvariantTest.sol` Invariants + diff --git a/packages/contracts-bedrock/invariant-docs/OptimismPortal.md b/packages/contracts-bedrock/invariant-docs/OptimismPortal.md index b1b2c38cb278..07347e58bd77 100644 --- a/packages/contracts-bedrock/invariant-docs/OptimismPortal.md +++ b/packages/contracts-bedrock/invariant-docs/OptimismPortal.md @@ -1,21 +1,21 @@ # `OptimismPortal` Invariants ## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`. -**Test:** [`OptimismPortal.t.sol#L151`](../test/invariants/OptimismPortal.t.sol#L151) +**Test:** [`OptimismPortal.t.sol#L149`](../test/invariants/OptimismPortal.t.sol#L149) All deposits, barring creation transactions and transactions sent to `address(0)`, should always succeed. ## `finalizeWithdrawalTransaction` should revert if the finalization period has not elapsed. -**Test:** [`OptimismPortal.t.sol#L174`](../test/invariants/OptimismPortal.t.sol#L174) +**Test:** [`OptimismPortal.t.sol#L172`](../test/invariants/OptimismPortal.t.sol#L172) A withdrawal that has been proven should not be able to be finalized until after the finalization period has elapsed. ## `finalizeWithdrawalTransaction` should revert if the withdrawal has already been finalized. -**Test:** [`OptimismPortal.t.sol#L204`](../test/invariants/OptimismPortal.t.sol#L204) +**Test:** [`OptimismPortal.t.sol#L202`](../test/invariants/OptimismPortal.t.sol#L202) Ensures that there is no chain of calls that can be made that allows a withdrawal to be finalized twice. ## A withdrawal should **always** be able to be finalized `FINALIZATION_PERIOD_SECONDS` after it was successfully proven. -**Test:** [`OptimismPortal.t.sol#L233`](../test/invariants/OptimismPortal.t.sol#L233) +**Test:** [`OptimismPortal.t.sol#L231`](../test/invariants/OptimismPortal.t.sol#L231) This invariant asserts that there is no chain of calls that can be made that will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS` after it was successfully proven. \ No newline at end of file diff --git a/packages/contracts-bedrock/invariant-docs/OptimismPortal2.md b/packages/contracts-bedrock/invariant-docs/OptimismPortal2.md new file mode 100644 index 000000000000..03630c5cd9a0 --- /dev/null +++ b/packages/contracts-bedrock/invariant-docs/OptimismPortal2.md @@ -0,0 +1,21 @@ +# `OptimismPortal2` Invariants + +## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`. +**Test:** [`OptimismPortal2.t.sol#L160`](../test/invariants/OptimismPortal2.t.sol#L160) + +All deposits, barring creation transactions and transactions sent to `address(0)`, should always succeed. + +## `finalizeWithdrawalTransaction` should revert if the proof maturity period has not elapsed. +**Test:** [`OptimismPortal2.t.sol#L182`](../test/invariants/OptimismPortal2.t.sol#L182) + +A withdrawal that has been proven should not be able to be finalized until after the proof maturity period has elapsed. + +## `finalizeWithdrawalTransaction` should revert if the withdrawal has already been finalized. +**Test:** [`OptimismPortal2.t.sol#L211`](../test/invariants/OptimismPortal2.t.sol#L211) + +Ensures that there is no chain of calls that can be made that allows a withdrawal to be finalized twice. + +## A withdrawal should **always** be able to be finalized `PROOF_MATURITY_DELAY_SECONDS` after it was successfully proven, if the game has resolved and passed the air-gap. +**Test:** [`OptimismPortal2.t.sol#L239`](../test/invariants/OptimismPortal2.t.sol#L239) + +This invariant asserts that there is no chain of calls that can be made that will prevent a withdrawal from being finalized exactly `PROOF_MATURITY_DELAY_SECONDS` after it was successfully proven and the game has resolved and passed the air-gap. \ No newline at end of file diff --git a/packages/contracts-bedrock/invariant-docs/README.md b/packages/contracts-bedrock/invariant-docs/README.md index e890036ea3b7..eae292a89cc2 100644 --- a/packages/contracts-bedrock/invariant-docs/README.md +++ b/packages/contracts-bedrock/invariant-docs/README.md @@ -13,8 +13,10 @@ This directory contains documentation for all defined invariant tests within `co - [Encoding](./Encoding.md) - [FaultDisputeGame](./FaultDisputeGame.md) - [Hashing](./Hashing.md) +- [InvariantTest.sol](./InvariantTest.sol.md) - [L2OutputOracle](./L2OutputOracle.md) - [OptimismPortal](./OptimismPortal.md) +- [OptimismPortal2](./OptimismPortal2.md) - [ResourceMetering](./ResourceMetering.md) - [SafeCall](./SafeCall.md) - [SystemConfig](./SystemConfig.md) @@ -26,7 +28,7 @@ To auto-generate documentation for invariant tests, run `pnpm autogen:invariant- ## Documentation Standard -In order for an invariant test file to be picked up by the [docgen script](../scripts/invariant-doc-gen.ts), it must +In order for an invariant test file to be picked up by the [docgen script](../scripts/autogen/generate-invariant-docs.ts), it must adhere to the following conventions: ### Forge Invariants diff --git a/packages/contracts-bedrock/invariant-docs/ResourceMetering.md b/packages/contracts-bedrock/invariant-docs/ResourceMetering.md index 5330108400b8..967c24bf886f 100644 --- a/packages/contracts-bedrock/invariant-docs/ResourceMetering.md +++ b/packages/contracts-bedrock/invariant-docs/ResourceMetering.md @@ -1,36 +1,36 @@ # `ResourceMetering` Invariants ## The base fee should increase if the last block used more than the target amount of gas. -**Test:** [`ResourceMetering.t.sol#L162`](../test/invariants/ResourceMetering.t.sol#L162) +**Test:** [`ResourceMetering.t.sol#L163`](../test/invariants/ResourceMetering.t.sol#L163) If the last block used more than the target amount of gas (and there were no empty blocks in between), ensure this block's baseFee increased, but not by more than the max amount per block. ## The base fee should decrease if the last block used less than the target amount of gas. -**Test:** [`ResourceMetering.t.sol#L171`](../test/invariants/ResourceMetering.t.sol#L171) +**Test:** [`ResourceMetering.t.sol#L172`](../test/invariants/ResourceMetering.t.sol#L172) If the previous block used less than the target amount of gas, the base fee should decrease, but not more than the max amount. ## A block's base fee should never be below `MINIMUM_BASE_FEE`. -**Test:** [`ResourceMetering.t.sol#L179`](../test/invariants/ResourceMetering.t.sol#L179) +**Test:** [`ResourceMetering.t.sol#L180`](../test/invariants/ResourceMetering.t.sol#L180) This test asserts that a block's base fee can never drop below the `MINIMUM_BASE_FEE` threshold. ## A block can never consume more than `MAX_RESOURCE_LIMIT` gas. -**Test:** [`ResourceMetering.t.sol#L187`](../test/invariants/ResourceMetering.t.sol#L187) +**Test:** [`ResourceMetering.t.sol#L188`](../test/invariants/ResourceMetering.t.sol#L188) This test asserts that a block can never consume more than the `MAX_RESOURCE_LIMIT` gas threshold. ## The base fee can never be raised more than the max base fee change. -**Test:** [`ResourceMetering.t.sol#L197`](../test/invariants/ResourceMetering.t.sol#L197) +**Test:** [`ResourceMetering.t.sol#L198`](../test/invariants/ResourceMetering.t.sol#L198) After a block consumes more gas than the target gas, the base fee cannot be raised more than the maximum amount allowed. The max base fee change (per-block) is derived as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR` ## The base fee can never be lowered more than the max base fee change. -**Test:** [`ResourceMetering.t.sol#L207`](../test/invariants/ResourceMetering.t.sol#L207) +**Test:** [`ResourceMetering.t.sol#L208`](../test/invariants/ResourceMetering.t.sol#L208) After a block consumes less than the target gas, the base fee cannot be lowered more than the maximum amount allowed. The max base fee change (per-block) is derived as follows: `prevBaseFee / BASE_FEE_MAX_CHANGE_DENOMINATOR` ## The `maxBaseFeeChange` calculation over multiple blocks can never underflow. -**Test:** [`ResourceMetering.t.sol#L216`](../test/invariants/ResourceMetering.t.sol#L216) +**Test:** [`ResourceMetering.t.sol#L217`](../test/invariants/ResourceMetering.t.sol#L217) When calculating the `maxBaseFeeChange` after multiple empty blocks, the calculation should never be allowed to underflow. \ No newline at end of file diff --git a/packages/contracts-bedrock/invariant-docs/SafeCall.md b/packages/contracts-bedrock/invariant-docs/SafeCall.md index 5f0563810a22..19ac6d851030 100644 --- a/packages/contracts-bedrock/invariant-docs/SafeCall.md +++ b/packages/contracts-bedrock/invariant-docs/SafeCall.md @@ -1,11 +1,11 @@ # `SafeCall` Invariants ## If `callWithMinGas` performs a call, then it must always provide at least the specified minimum gas limit to the subcontext. -**Test:** [`SafeCall.t.sol#L31`](../test/invariants/SafeCall.t.sol#L31) +**Test:** [`SafeCall.t.sol#L33`](../test/invariants/SafeCall.t.sol#L33) If the check for remaining gas in `SafeCall.callWithMinGas` passes, the subcontext of the call below it must be provided at least `minGas` gas. ## `callWithMinGas` reverts if there is not enough gas to pass to the subcontext. -**Test:** [`SafeCall.t.sol#L63`](../test/invariants/SafeCall.t.sol#L63) +**Test:** [`SafeCall.t.sol#L66`](../test/invariants/SafeCall.t.sol#L66) If there is not enough gas in the callframe to ensure that `callWithMinGas` can provide the specified minimum gas limit to the subcontext of the call, then `callWithMinGas` must revert. \ No newline at end of file diff --git a/packages/contracts-bedrock/invariant-docs/SystemConfig.md b/packages/contracts-bedrock/invariant-docs/SystemConfig.md index 757a0e25b097..382bb3d539df 100644 --- a/packages/contracts-bedrock/invariant-docs/SystemConfig.md +++ b/packages/contracts-bedrock/invariant-docs/SystemConfig.md @@ -1,5 +1,5 @@ # `SystemConfig` Invariants ## The gas limit of the `SystemConfig` contract can never be lower than the hard-coded lower bound. -**Test:** [`SystemConfig.t.sol#L69`](../test/invariants/SystemConfig.t.sol#L69) +**Test:** [`SystemConfig.t.sol#L68`](../test/invariants/SystemConfig.t.sol#L68) diff --git a/packages/contracts-bedrock/lib/lib-keccak b/packages/contracts-bedrock/lib/lib-keccak index 59dcbd7b0de1..0115edbbc60b 160000 --- a/packages/contracts-bedrock/lib/lib-keccak +++ b/packages/contracts-bedrock/lib/lib-keccak @@ -1 +1 @@ -Subproject commit 59dcbd7b0de1fd00b44f4ce41e99a7f990564d11 +Subproject commit 0115edbbc60b5f702392caafc3a142061e6142fa diff --git a/packages/contracts-bedrock/package.json b/packages/contracts-bedrock/package.json index 8aeed85d3793..9004a872e7cd 100644 --- a/packages/contracts-bedrock/package.json +++ b/packages/contracts-bedrock/package.json @@ -1,6 +1,6 @@ { "name": "@eth-optimism/contracts-bedrock", - "version": "0.16.2", + "version": "0.17.1", "description": "Contracts for Optimism Specs", "license": "MIT", "files": [ @@ -14,12 +14,12 @@ "bindings:ts": "nx generate @eth-optimism/contracts-ts", "bindings:go:no-build": "cd ../../op-bindings && make bindings-build", "bindings:go": "pnpm clean && pnpm build && pnpm bindings:go:no-build", - "prebuild": "./scripts/verify-foundry-install.sh", + "prebuild": "./scripts/checks/check-foundry-install.sh", "build": "forge build", "build:go-ffi": "(cd scripts/go-ffi && go build)", - "autogen:invariant-docs": "npx tsx scripts/invariant-doc-gen.ts", + "autogen:invariant-docs": "npx tsx scripts/autogen/generate-invariant-docs.ts", "test": "pnpm build:go-ffi && forge test", - "test:kontrol": "./test/kontrol/scripts/run-kontrol.sh", + "test:kontrol": "./test/kontrol/scripts/run-kontrol.sh script", "genesis": "./scripts/generate-l2-genesis.sh", "coverage": "pnpm build:go-ffi && forge coverage", "coverage:lcov": "pnpm build:go-ffi && forge coverage --report lcov", @@ -27,22 +27,18 @@ "gas-snapshot:no-build": "forge snapshot --match-contract GasBenchMark", "statediff": "./scripts/statediff.sh && git diff --exit-code", "gas-snapshot": "pnpm build:go-ffi && pnpm gas-snapshot:no-build", - "snapshots": "npx tsx scripts/generate-snapshots.ts", - "snapshots:check": "./scripts/check-snapshots.sh", - "slither": "./scripts/slither.sh", - "slither:check": "pnpm slither && git diff --exit-code", - "slither:triage": "TRIAGE_MODE=1 ./scripts/slither.sh", + "snapshots": "npx tsx scripts/autogen/generate-snapshots.ts && ./test/kontrol/scripts/make-summary-deployment.sh", + "snapshots:check": "./scripts/checks/check-snapshots.sh", "semver-lock": "forge script scripts/SemverLock.s.sol", - "validate-deploy-configs": "./scripts/check-deploy-configs.sh", - "validate-spacers:no-build": "npx tsx scripts/validate-spacers.ts", + "validate-deploy-configs": "./scripts/checks/check-deploy-configs.sh", + "validate-spacers:no-build": "npx tsx scripts/checks/check-spacers.ts", "validate-spacers": "pnpm build && pnpm validate-spacers:no-build", "clean": "rm -rf ./artifacts ./forge-artifacts ./cache ./tsconfig.tsbuildinfo ./tsconfig.build.tsbuildinfo ./scripts/go-ffi/go-ffi ./.testdata ./deployments/hardhat/*", - "preinstall": "npx only-allow pnpm", "pre-pr:no-build": "pnpm gas-snapshot:no-build && pnpm snapshots && pnpm semver-lock && pnpm autogen:invariant-docs && pnpm lint && pnpm bindings:go:no-build", "pre-pr": "pnpm clean && pnpm build:go-ffi && pnpm build && pnpm pre-pr:no-build", - "pre-pr:full": "pnpm test && pnpm slither && pnpm validate-deploy-configs && pnpm validate-spacers && pnpm pre-pr", + "pre-pr:full": "pnpm test && pnpm validate-deploy-configs && pnpm validate-spacers && pnpm pre-pr", "lint:ts:check": "eslint . --max-warnings=0", - "lint:forge-tests:check": "npx tsx scripts/forge-test-names.ts", + "lint:forge-tests:check": "npx tsx scripts/checks/check-test-names.ts", "lint:contracts:check": "pnpm lint:fix && git diff --exit-code", "lint:check": "pnpm lint:contracts:check && pnpm lint:ts:check", "lint:ts:fix": "eslint --fix .", @@ -51,8 +47,8 @@ "lint": "pnpm lint:fix && pnpm lint:check" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^6.19.1", - "@typescript-eslint/parser": "^6.19.1", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", "tsx": "^4.7.0", "typescript": "^5.3.3" } diff --git a/packages/contracts-bedrock/periphery-deploy-config/4202.json b/packages/contracts-bedrock/periphery-deploy-config/4202.json new file mode 100644 index 000000000000..2e298c7f0585 --- /dev/null +++ b/packages/contracts-bedrock/periphery-deploy-config/4202.json @@ -0,0 +1,42 @@ +{ + "faucetAdmin": "0x212E789D4523D4BAF464f8Fb2A9B9dff2B36e5A6", + "faucetDrippieOwner": "0x10ab157483dd308f8B38aCF2ad823dfD255F56b5", + "faucetDripV1Value": 20000000000000000000, + "faucetDripV1Interval": 3600, + "faucetDripV1Threshold": 100000000000000000000, + "faucetDripV2Interval": 604800, + "faucetDripV2Threshold": 20000000000000000000, + "faucetDripV2Value": 500000000000000000000, + "faucetAdminDripV1Interval": 86400, + "faucetAdminDripV1Threshold": 100000000000000000, + "faucetAdminDripV1Value": 1000000000000000000, + "faucetGelatoTreasury": "0x644CB00854EDC55FE8CCC9c1967BABb22F08Ad2f", + "faucetGelatoRecipient": "0x0E9b4649eB0760A4F01646636E032D68cFDe58FF", + "faucetGelatoBalanceV1DripInterval": 86400, + "faucetGelatoBalanceV1Value": 1000000000000000000, + "faucetGelatoThreshold": 100000000000000000, + "faucetOnchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOnchainAuthModuleTtl": 86400, + "faucetOnchainAuthModuleAmount": 1000000000000000000, + "faucetOffchainAuthModuleAdmin": "0xFe44Ae787A632c45ACea658492dDBebE39f002aC", + "faucetOffchainAuthModuleTtl": 86400, + "faucetOffchainAuthModuleAmount": 50000000000000000, + "opL1BridgeAddress": "0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1", + "baseL1BridgeAddress": "0xfd0Bf71F60660E2f608ed56e1659C450eB113120", + "pgnL1BridgeAddress": "0xFaE6abCAF30D23e233AC7faF747F2fC3a5a6Bfa3", + "zoraL1BridgeAddress": "0x5376f1D543dcbB5BD416c56C189e4cB7399fCcCB", + "orderlyL1BridgeAddress": "0x1Af0494040d6904A9F3EE21921de4b359C736333", + "modeL1BridgeAddress": "0xbC5C679879B2965296756CD959C3C739769995E2", + "lyraL1BridgeAddress": "0x915f179A77FB2e1AeA8b56Ebc0D75A7e1A8a7A17", + "liskL1BridgeAddress": "0x1Fb30e446eA791cd1f011675E5F3f5311b70faF5", + "installOpChainFaucetsDrips": false, + "archivePreviousOpChainFaucetsDrips": false, + "dripVersion": 3, + "previousDripVersion": 2, + "smallOpChainFaucetDripValue": 34000000000000000000, + "smallOpChainFaucetDripInterval": 86400, + "largeOpChainFaucetDripValue": 34000000000000000000, + "largeOpChainFaucetDripInterval": 86400, + "opChainAdminWalletDripValue": 1000000000000000000, + "opChainAdminWalletDripInterval": 2592000 +} diff --git a/packages/contracts-bedrock/periphery-deploy-config/4460.json b/packages/contracts-bedrock/periphery-deploy-config/4460.json index baa776ddd80a..5e86522dbe56 100644 --- a/packages/contracts-bedrock/periphery-deploy-config/4460.json +++ b/packages/contracts-bedrock/periphery-deploy-config/4460.json @@ -28,6 +28,7 @@ "orderlyL1BridgeAddress": "0x1Af0494040d6904A9F3EE21921de4b359C736333", "modeL1BridgeAddress": "0xbC5C679879B2965296756CD959C3C739769995E2", "lyraL1BridgeAddress": "0x915f179A77FB2e1AeA8b56Ebc0D75A7e1A8a7A17", + "liskL1BridgeAddress": "0x1Fb30e446eA791cd1f011675E5F3f5311b70faF5", "installOpChainFaucetsDrips": false, "archivePreviousOpChainFaucetsDrips": false, "dripVersion": 1, diff --git a/packages/contracts-bedrock/periphery-deploy-config/58008.json b/packages/contracts-bedrock/periphery-deploy-config/58008.json index baa776ddd80a..5e86522dbe56 100644 --- a/packages/contracts-bedrock/periphery-deploy-config/58008.json +++ b/packages/contracts-bedrock/periphery-deploy-config/58008.json @@ -28,6 +28,7 @@ "orderlyL1BridgeAddress": "0x1Af0494040d6904A9F3EE21921de4b359C736333", "modeL1BridgeAddress": "0xbC5C679879B2965296756CD959C3C739769995E2", "lyraL1BridgeAddress": "0x915f179A77FB2e1AeA8b56Ebc0D75A7e1A8a7A17", + "liskL1BridgeAddress": "0x1Fb30e446eA791cd1f011675E5F3f5311b70faF5", "installOpChainFaucetsDrips": false, "archivePreviousOpChainFaucetsDrips": false, "dripVersion": 1, diff --git a/packages/contracts-bedrock/periphery-deploy-config/84532.json b/packages/contracts-bedrock/periphery-deploy-config/84532.json index baa776ddd80a..5e86522dbe56 100644 --- a/packages/contracts-bedrock/periphery-deploy-config/84532.json +++ b/packages/contracts-bedrock/periphery-deploy-config/84532.json @@ -28,6 +28,7 @@ "orderlyL1BridgeAddress": "0x1Af0494040d6904A9F3EE21921de4b359C736333", "modeL1BridgeAddress": "0xbC5C679879B2965296756CD959C3C739769995E2", "lyraL1BridgeAddress": "0x915f179A77FB2e1AeA8b56Ebc0D75A7e1A8a7A17", + "liskL1BridgeAddress": "0x1Fb30e446eA791cd1f011675E5F3f5311b70faF5", "installOpChainFaucetsDrips": false, "archivePreviousOpChainFaucetsDrips": false, "dripVersion": 1, diff --git a/packages/contracts-bedrock/periphery-deploy-config/901.json b/packages/contracts-bedrock/periphery-deploy-config/901.json index baa776ddd80a..5e86522dbe56 100644 --- a/packages/contracts-bedrock/periphery-deploy-config/901.json +++ b/packages/contracts-bedrock/periphery-deploy-config/901.json @@ -28,6 +28,7 @@ "orderlyL1BridgeAddress": "0x1Af0494040d6904A9F3EE21921de4b359C736333", "modeL1BridgeAddress": "0xbC5C679879B2965296756CD959C3C739769995E2", "lyraL1BridgeAddress": "0x915f179A77FB2e1AeA8b56Ebc0D75A7e1A8a7A17", + "liskL1BridgeAddress": "0x1Fb30e446eA791cd1f011675E5F3f5311b70faF5", "installOpChainFaucetsDrips": false, "archivePreviousOpChainFaucetsDrips": false, "dripVersion": 1, diff --git a/packages/contracts-bedrock/periphery-deploy-config/919.json b/packages/contracts-bedrock/periphery-deploy-config/919.json index baa776ddd80a..5e86522dbe56 100644 --- a/packages/contracts-bedrock/periphery-deploy-config/919.json +++ b/packages/contracts-bedrock/periphery-deploy-config/919.json @@ -28,6 +28,7 @@ "orderlyL1BridgeAddress": "0x1Af0494040d6904A9F3EE21921de4b359C736333", "modeL1BridgeAddress": "0xbC5C679879B2965296756CD959C3C739769995E2", "lyraL1BridgeAddress": "0x915f179A77FB2e1AeA8b56Ebc0D75A7e1A8a7A17", + "liskL1BridgeAddress": "0x1Fb30e446eA791cd1f011675E5F3f5311b70faF5", "installOpChainFaucetsDrips": false, "archivePreviousOpChainFaucetsDrips": false, "dripVersion": 1, diff --git a/packages/contracts-bedrock/periphery-deploy-config/999999999.json b/packages/contracts-bedrock/periphery-deploy-config/999999999.json index baa776ddd80a..5e86522dbe56 100644 --- a/packages/contracts-bedrock/periphery-deploy-config/999999999.json +++ b/packages/contracts-bedrock/periphery-deploy-config/999999999.json @@ -28,6 +28,7 @@ "orderlyL1BridgeAddress": "0x1Af0494040d6904A9F3EE21921de4b359C736333", "modeL1BridgeAddress": "0xbC5C679879B2965296756CD959C3C739769995E2", "lyraL1BridgeAddress": "0x915f179A77FB2e1AeA8b56Ebc0D75A7e1A8a7A17", + "liskL1BridgeAddress": "0x1Fb30e446eA791cd1f011675E5F3f5311b70faF5", "installOpChainFaucetsDrips": false, "archivePreviousOpChainFaucetsDrips": false, "dripVersion": 1, diff --git a/packages/contracts-bedrock/periphery-deploy-config/optimism-goerli.json b/packages/contracts-bedrock/periphery-deploy-config/optimism-goerli.json index 4ba3a39a8d13..0a9e4f938c8f 100644 --- a/packages/contracts-bedrock/periphery-deploy-config/optimism-goerli.json +++ b/packages/contracts-bedrock/periphery-deploy-config/optimism-goerli.json @@ -28,6 +28,7 @@ "orderlyL1BridgeAddress": "0x1Af0494040d6904A9F3EE21921de4b359C736333", "modeL1BridgeAddress": "0xbC5C679879B2965296756CD959C3C739769995E2", "lyraL1BridgeAddress": "0x915f179A77FB2e1AeA8b56Ebc0D75A7e1A8a7A17", + "liskL1BridgeAddress": "0x1Fb30e446eA791cd1f011675E5F3f5311b70faF5", "installOpChainFaucetsDrips": false, "archivePreviousOpChainFaucetsDrips": false, "dripVersion": 1, diff --git a/packages/contracts-bedrock/periphery-deploy-config/optimism-sepolia.json b/packages/contracts-bedrock/periphery-deploy-config/optimism-sepolia.json index baa776ddd80a..5e86522dbe56 100644 --- a/packages/contracts-bedrock/periphery-deploy-config/optimism-sepolia.json +++ b/packages/contracts-bedrock/periphery-deploy-config/optimism-sepolia.json @@ -28,6 +28,7 @@ "orderlyL1BridgeAddress": "0x1Af0494040d6904A9F3EE21921de4b359C736333", "modeL1BridgeAddress": "0xbC5C679879B2965296756CD959C3C739769995E2", "lyraL1BridgeAddress": "0x915f179A77FB2e1AeA8b56Ebc0D75A7e1A8a7A17", + "liskL1BridgeAddress": "0x1Fb30e446eA791cd1f011675E5F3f5311b70faF5", "installOpChainFaucetsDrips": false, "archivePreviousOpChainFaucetsDrips": false, "dripVersion": 1, diff --git a/packages/contracts-bedrock/periphery-deploy-config/sepolia.json b/packages/contracts-bedrock/periphery-deploy-config/sepolia.json index 4d2835ff478a..c6f7945deeb0 100644 --- a/packages/contracts-bedrock/periphery-deploy-config/sepolia.json +++ b/packages/contracts-bedrock/periphery-deploy-config/sepolia.json @@ -28,6 +28,7 @@ "orderlyL1BridgeAddress": "0x1Af0494040d6904A9F3EE21921de4b359C736333", "modeL1BridgeAddress": "0xbC5C679879B2965296756CD959C3C739769995E2", "lyraL1BridgeAddress": "0x915f179A77FB2e1AeA8b56Ebc0D75A7e1A8a7A17", + "liskL1BridgeAddress": "0x1Fb30e446eA791cd1f011675E5F3f5311b70faF5", "installOpChainFaucetsDrips": true, "archivePreviousOpChainFaucetsDrips": false, "dripVersion": 3, diff --git a/packages/contracts-bedrock/scripts/Artifacts.s.sol b/packages/contracts-bedrock/scripts/Artifacts.s.sol index 7bd36c421d42..4042c72043eb 100644 --- a/packages/contracts-bedrock/scripts/Artifacts.s.sol +++ b/packages/contracts-bedrock/scripts/Artifacts.s.sol @@ -6,7 +6,12 @@ import { stdJson } from "forge-std/StdJson.sol"; import { Vm } from "forge-std/Vm.sol"; import { Executables } from "scripts/Executables.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { Chains } from "scripts/Chains.sol"; +import { Config } from "scripts/Config.sol"; +import { StorageSlot } from "scripts/ForgeArtifacts.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; +import { LibString } from "solady/utils/LibString.sol"; +import { ForgeArtifacts } from "scripts/ForgeArtifacts.sol"; +import { IAddressManager } from "scripts/interfaces/IAddressManager.sol"; /// @notice Represents a deployment. Is serialized to JSON as a key/value /// pair. Can be accessed from within scripts. @@ -17,6 +22,8 @@ struct Deployment { /// @title Artifacts /// @notice Useful for accessing deployment artifacts from within scripts. +/// When a contract is deployed, call the `save` function to write its name and +/// contract address to disk. Inspired by `forge-deploy`. abstract contract Artifacts { /// @notice Foundry cheatcode VM. Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); @@ -32,49 +39,23 @@ abstract contract Artifacts { Deployment[] internal _newDeployments; /// @notice Path to the directory containing the hh deploy style artifacts string internal deploymentsDir; - /// @notice The path to the temp deployments file - string internal tempDeploymentsPath; + /// @notice The path to the deployment artifact that is being written to. + string internal deploymentOutfile; /// @notice The namespace for the deployment. Can be set with the env var DEPLOYMENT_CONTEXT. string internal deploymentContext; /// @notice Setup function. The arguments here function setUp() public virtual { - string memory root = vm.projectRoot(); + deploymentOutfile = Config.deploymentOutfile(); + console.log("Writing artifact to %s", deploymentOutfile); + ForgeArtifacts.ensurePath(deploymentOutfile); - // The `deploymentContext` should match the name of the deploy-config file. - deploymentContext = _getDeploymentContext(); - deploymentsDir = string.concat(root, "/deployments/", deploymentContext); - - if (!vm.isDir(deploymentsDir)) { - vm.createDir(deploymentsDir, true); - } - - tempDeploymentsPath = vm.envOr("DEPLOYMENT_OUTFILE", string.concat(deploymentsDir, "/.deploy")); - try vm.readFile(tempDeploymentsPath) returns (string memory) { } - catch { - vm.writeJson("{}", tempDeploymentsPath); - } - console.log("Storing temp deployment data in %s", tempDeploymentsPath); - - try vm.createDir(deploymentsDir, true) { } catch (bytes memory) { } - - uint256 chainId = vm.envOr("CHAIN_ID", block.chainid); - string memory chainIdPath = string.concat(deploymentsDir, string("/.chainId")); - try vm.readFile(chainIdPath) returns (string memory localChainId) { - if (vm.envOr("STRICT_DEPLOYMENT", true)) { - require( - vm.parseUint(localChainId) == chainId, - string.concat("Misconfigured networks: ", localChainId, " != ", vm.toString(chainId)) - ); - } - } catch { - vm.writeFile(chainIdPath, vm.toString(chainId)); - } + uint256 chainId = Config.chainID(); console.log("Connected to network with chainid %s", chainId); // Load addresses from a JSON file if the CONTRACT_ADDRESSES_PATH environment variable // is set. Great for loading addresses from `superchain-registry`. - string memory addresses = vm.envOr("CONTRACT_ADDRESSES_PATH", string("")); + string memory addresses = Config.contractAddressesPath(); if (bytes(addresses).length > 0) { console.log("Loading addresses from %s", addresses); _loadAddresses(addresses); @@ -83,7 +64,7 @@ abstract contract Artifacts { /// @notice Populates the addresses to be used in a script based on a JSON file. /// The format of the JSON file is the same that it output by this script - /// as well as the JSON files that contain addresses in the `superchain-ops` + /// as well as the JSON files that contain addresses in the `superchain-registry` /// repo. The JSON key is the name of the contract and the value is an address. function _loadAddresses(string memory _path) internal { string[] memory commands = new string[](3); @@ -109,10 +90,7 @@ abstract contract Artifacts { /// @return Whether the deployment exists or not. function has(string memory _name) public view returns (bool) { Deployment memory existing = _namedDeployments[_name]; - if (existing.addr != address(0)) { - return bytes(existing.name).length > 0; - } - return _getExistingDeploymentAddress(_name) != address(0); + return bytes(existing.name).length > 0; } /// @notice Returns the address of a deployment. Also handles the predeploys. @@ -127,8 +105,6 @@ abstract contract Artifacts { } return existing.addr; } - address addr = _getExistingDeploymentAddress(_name); - if (addr != address(0)) return payable(addr); bytes32 digest = keccak256(bytes(_name)); if (digest == keccak256(bytes("L2CrossDomainMessenger"))) { @@ -192,16 +168,10 @@ abstract contract Artifacts { /// @param _name The name of the deployment. /// @return The deployment. function get(string memory _name) public view returns (Deployment memory) { - Deployment memory deployment = _namedDeployments[_name]; - if (deployment.addr != address(0)) { - return deployment; - } else { - return _getExistingDeployment(_name); - } + return _namedDeployments[_name]; } - /// @notice Writes a deployment to disk as a temp deployment so that the - /// hardhat deploy artifact can be generated afterwards. + /// @notice Appends a deployment to disk as a JSON deploy artifact. /// @param _name The name of the deployment. /// @param _deployed The address of the deployment. function save(string memory _name, address _deployed) public { @@ -212,17 +182,18 @@ abstract contract Artifacts { revert InvalidDeployment("AlreadyExists"); } + console.log("Saving %s: %s", _name, _deployed); Deployment memory deployment = Deployment({ name: _name, addr: payable(_deployed) }); _namedDeployments[_name] = deployment; _newDeployments.push(deployment); - _writeTemp(_name, _deployed); + _appendDeployment(_name, _deployed); } - /// @notice Reads the temp deployments from disk that were generated + /// @notice Reads the deployment artifact from disk that were generated /// by the deploy script. /// @return An array of deployments. - function _getTempDeployments() internal returns (Deployment[] memory) { - string memory json = vm.readFile(tempDeploymentsPath); + function _getDeployments() internal returns (Deployment[] memory) { + string memory json = vm.readFile(deploymentOutfile); string[] memory cmd = new string[](3); cmd[0] = Executables.bash; cmd[1] = "-c"; @@ -240,28 +211,8 @@ abstract contract Artifacts { } /// @notice Adds a deployment to the temp deployments file - function _writeTemp(string memory _name, address _deployed) internal { - vm.writeJson({ json: stdJson.serialize("", _name, _deployed), path: tempDeploymentsPath }); - } - - /// @notice Reads the artifact from the filesystem by name and returns the address. - /// @param _name The name of the artifact to read. - /// @return The address of the artifact. - function _getExistingDeploymentAddress(string memory _name) internal view returns (address payable) { - return _getExistingDeployment(_name).addr; - } - - /// @notice Reads the artifact from the filesystem by name and returns the Deployment. - /// @param _name The name of the artifact to read. - /// @return The deployment corresponding to the name. - function _getExistingDeployment(string memory _name) internal view returns (Deployment memory) { - string memory path = string.concat(deploymentsDir, "/", _name, ".json"); - try vm.readFile(path) returns (string memory json) { - bytes memory addr = stdJson.parseRaw(json, "$.address"); - return Deployment({ addr: abi.decode(addr, (address)), name: _name }); - } catch { - return Deployment({ addr: payable(address(0)), name: "" }); - } + function _appendDeployment(string memory _name, address _deployed) internal { + vm.writeJson({ json: stdJson.serialize("", _name, _deployed), path: deploymentOutfile }); } /// @notice Stubs a deployment retrieved through `get`. @@ -276,34 +227,24 @@ abstract contract Artifacts { _namedDeployments[_name] = deployment; } - /// @notice The context of the deployment is used to namespace the artifacts. - /// An unknown context will use the chainid as the context name. - /// This is legacy code and should be removed in the future. - function _getDeploymentContext() private view returns (string memory) { - string memory context = vm.envOr("DEPLOYMENT_CONTEXT", string("")); - if (bytes(context).length > 0) { - return context; - } - - uint256 chainid = vm.envOr("CHAIN_ID", block.chainid); - if (chainid == Chains.Mainnet) { - return "mainnet"; - } else if (chainid == Chains.Goerli) { - return "goerli"; - } else if (chainid == Chains.OPGoerli) { - return "optimism-goerli"; - } else if (chainid == Chains.OPMainnet) { - return "optimism-mainnet"; - } else if (chainid == Chains.LocalDevnet || chainid == Chains.GethDevnet) { - return "devnetL1"; - } else if (chainid == Chains.Hardhat) { - return "hardhat"; - } else if (chainid == Chains.Sepolia) { - return "sepolia"; - } else if (chainid == Chains.OPSepolia) { - return "optimism-sepolia"; + /// @notice Returns the value of the internal `_initialized` storage slot for a given contract. + function loadInitializedSlot(string memory _contractName) public returns (uint8 initialized_) { + address contractAddress; + // Check if the contract name ends with `Proxy` and, if so, get the implementation address + if (LibString.endsWith(_contractName, "Proxy")) { + contractAddress = EIP1967Helper.getImplementation(getAddress(_contractName)); + _contractName = LibString.slice(_contractName, 0, bytes(_contractName).length - 5); + // If the EIP1967 implementation address is 0, we try to get the implementation address from legacy + // AddressManager, which would work if the proxy is ResolvedDelegateProxy like L1CrossDomainMessengerProxy. + if (contractAddress == address(0)) { + contractAddress = + IAddressManager(mustGetAddress("AddressManager")).getAddress(string.concat("OVM_", _contractName)); + } } else { - return vm.toString(chainid); + contractAddress = mustGetAddress(_contractName); } + StorageSlot memory slot = ForgeArtifacts.getInitializedSlot(_contractName); + bytes32 slotVal = vm.load(contractAddress, bytes32(vm.parseUint(slot.slot))); + initialized_ = uint8((uint256(slotVal) >> (slot.offset * 8)) & 0xFF); } } diff --git a/packages/contracts-bedrock/scripts/ChainAssertions.sol b/packages/contracts-bedrock/scripts/ChainAssertions.sol index 3b2653a64d5b..7afdceb62cb3 100644 --- a/packages/contracts-bedrock/scripts/ChainAssertions.sol +++ b/packages/contracts-bedrock/scripts/ChainAssertions.sol @@ -9,9 +9,12 @@ import { SystemConfig } from "src/L1/SystemConfig.sol"; import { Constants } from "src/libraries/Constants.sol"; import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; +import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; +import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol"; import { ProtocolVersion, ProtocolVersions } from "src/L1/ProtocolVersions.sol"; import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; import { OptimismPortal } from "src/L1/OptimismPortal.sol"; +import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; @@ -22,6 +25,8 @@ import { ISystemConfigV0 } from "scripts/interfaces/ISystemConfigV0.sol"; import { console2 as console } from "forge-std/console2.sol"; library ChainAssertions { + Vm internal constant vm = Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); + /// @notice Asserts the correctness of an L1 deployment. This function expects that all contracts /// within the `prox` ContractSet are proxies that have been setup and initialized. function postDeployAssertions( @@ -50,6 +55,7 @@ library ChainAssertions { checkOptimismMintableERC20Factory({ _contracts: _prox, _isProxy: true }); checkL1ERC721Bridge({ _contracts: _prox, _isProxy: true }); checkOptimismPortal({ _contracts: _prox, _cfg: _cfg, _isProxy: true }); + checkOptimismPortal2({ _contracts: _prox, _cfg: _cfg, _isProxy: true }); checkProtocolVersions({ _contracts: _prox, _cfg: _cfg, _isProxy: true }); } @@ -58,6 +64,9 @@ library ChainAssertions { console.log("Running chain assertions on the SystemConfig"); SystemConfig config = SystemConfig(_contracts.SystemConfig); + // Check that the contract is initialized + assertSlotValueIsOne({ _contractAddress: address(config), _slot: 0, _offset: 0 }); + ResourceMetering.ResourceConfig memory resourceConfig = config.resourceConfig(); if (_isProxy) { @@ -117,6 +126,9 @@ library ChainAssertions { console.log("Running chain assertions on the L1CrossDomainMessenger"); L1CrossDomainMessenger messenger = L1CrossDomainMessenger(_contracts.L1CrossDomainMessenger); + // Check that the contract is initialized + assertSlotValueIsOne({ _contractAddress: address(messenger), _slot: 0, _offset: 20 }); + require(address(messenger.OTHER_MESSENGER()) == Predeploys.L2_CROSS_DOMAIN_MESSENGER); require(address(messenger.otherMessenger()) == Predeploys.L2_CROSS_DOMAIN_MESSENGER); @@ -138,6 +150,9 @@ library ChainAssertions { console.log("Running chain assertions on the L1StandardBridge"); L1StandardBridge bridge = L1StandardBridge(payable(_contracts.L1StandardBridge)); + // Check that the contract is initialized + assertSlotValueIsOne({ _contractAddress: address(bridge), _slot: 0, _offset: 0 }); + if (_isProxy) { require(address(bridge.MESSENGER()) == _contracts.L1CrossDomainMessenger); require(address(bridge.messenger()) == _contracts.L1CrossDomainMessenger); @@ -153,6 +168,43 @@ library ChainAssertions { } } + /// @notice Asserts that the DisputeGameFactory is setup correctly + function checkDisputeGameFactory(Types.ContractSet memory _contracts, address _expectedOwner) internal view { + console.log("Running chain assertions on the DisputeGameFactory"); + DisputeGameFactory factory = DisputeGameFactory(_contracts.DisputeGameFactory); + + // Check that the contract is initialized + assertSlotValueIsOne({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); + + require(factory.owner() == _expectedOwner); + } + + /// @notice Asserts that the DelayedWETH is setup correctly + function checkDelayedWETH( + Types.ContractSet memory _contracts, + DeployConfig _cfg, + bool _isProxy, + address _expectedOwner + ) + internal + view + { + console.log("Running chain assertions on the DelayedWETH"); + DelayedWETH weth = DelayedWETH(payable(_contracts.DelayedWETH)); + + // Check that the contract is initialized + assertSlotValueIsOne({ _contractAddress: address(weth), _slot: 0, _offset: 0 }); + + if (_isProxy) { + require(weth.owner() == _expectedOwner); + require(weth.delay() == _cfg.faultGameWithdrawalDelay()); + require(weth.config() == SuperchainConfig(_contracts.SuperchainConfig)); + } else { + require(weth.owner() == _expectedOwner); + require(weth.delay() == _cfg.faultGameWithdrawalDelay()); + } + } + /// @notice Asserts that the L2OutputOracle is setup correctly function checkL2OutputOracle( Types.ContractSet memory _contracts, @@ -166,6 +218,9 @@ library ChainAssertions { console.log("Running chain assertions on the L2OutputOracle"); L2OutputOracle oracle = L2OutputOracle(_contracts.L2OutputOracle); + // Check that the contract is initialized + assertSlotValueIsOne({ _contractAddress: address(oracle), _slot: 0, _offset: 0 }); + if (_isProxy) { require(oracle.SUBMISSION_INTERVAL() == _cfg.l2OutputOracleSubmissionInterval()); require(oracle.submissionInterval() == _cfg.l2OutputOracleSubmissionInterval()); @@ -200,6 +255,9 @@ library ChainAssertions { console.log("Running chain assertions on the OptimismMintableERC20Factory"); OptimismMintableERC20Factory factory = OptimismMintableERC20Factory(_contracts.OptimismMintableERC20Factory); + // Check that the contract is initialized + assertSlotValueIsOne({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); + if (_isProxy) { require(factory.BRIDGE() == _contracts.L1StandardBridge); require(factory.bridge() == _contracts.L1StandardBridge); @@ -214,6 +272,9 @@ library ChainAssertions { console.log("Running chain assertions on the L1ERC721Bridge"); L1ERC721Bridge bridge = L1ERC721Bridge(_contracts.L1ERC721Bridge); + // Check that the contract is initialized + assertSlotValueIsOne({ _contractAddress: address(bridge), _slot: 0, _offset: 0 }); + require(address(bridge.OTHER_BRIDGE()) == Predeploys.L2_ERC721_BRIDGE); require(address(bridge.otherBridge()) == Predeploys.L2_ERC721_BRIDGE); @@ -234,6 +295,9 @@ library ChainAssertions { OptimismPortal portal = OptimismPortal(payable(_contracts.OptimismPortal)); + // Check that the contract is initialized + assertSlotValueIsOne({ _contractAddress: address(portal), _slot: 0, _offset: 0 }); + address guardian = _cfg.superchainConfigGuardian(); if (guardian.code.length == 0) { console.log("Guardian has no code: %s", guardian); @@ -259,6 +323,45 @@ library ChainAssertions { } } + /// @notice Asserts the OptimismPortal2 is setup correctly + function checkOptimismPortal2( + Types.ContractSet memory _contracts, + DeployConfig _cfg, + bool _isProxy + ) + internal + view + { + console.log("Running chain assertions on the OptimismPortal2"); + + OptimismPortal2 portal = OptimismPortal2(payable(_contracts.OptimismPortal2)); + + // Check that the contract is initialized + assertSlotValueIsOne({ _contractAddress: address(portal), _slot: 0, _offset: 0 }); + + address guardian = _cfg.superchainConfigGuardian(); + if (guardian.code.length == 0) { + console.log("Guardian has no code: %s", guardian); + } + + if (_isProxy) { + require(address(portal.disputeGameFactory()) == _contracts.DisputeGameFactory); + require(address(portal.SYSTEM_CONFIG()) == _contracts.SystemConfig); + require(address(portal.systemConfig()) == _contracts.SystemConfig); + require(portal.GUARDIAN() == guardian); + require(portal.guardian() == guardian); + require(address(portal.superchainConfig()) == address(_contracts.SuperchainConfig)); + require(portal.paused() == SuperchainConfig(_contracts.SuperchainConfig).paused()); + require(portal.l2Sender() == Constants.DEFAULT_L2_SENDER); + } else { + require(address(portal.disputeGameFactory()) == address(0)); + require(address(portal.SYSTEM_CONFIG()) == address(0)); + require(address(portal.systemConfig()) == address(0)); + require(address(portal.superchainConfig()) == address(0)); + require(portal.l2Sender() == Constants.DEFAULT_L2_SENDER); + } + } + /// @notice Asserts that the ProtocolVersions is setup correctly function checkProtocolVersions( Types.ContractSet memory _contracts, @@ -270,6 +373,10 @@ library ChainAssertions { { console.log("Running chain assertions on the ProtocolVersions"); ProtocolVersions versions = ProtocolVersions(_contracts.ProtocolVersions); + + // Check that the contract is initialized + assertSlotValueIsOne({ _contractAddress: address(versions), _slot: 0, _offset: 0 }); + if (_isProxy) { require(versions.owner() == _cfg.finalSystemOwner()); require(ProtocolVersion.unwrap(versions.required()) == _cfg.requiredProtocolVersion()); @@ -292,7 +399,20 @@ library ChainAssertions { { console.log("Running chain assertions on the SuperchainConfig"); SuperchainConfig superchainConfig = SuperchainConfig(_contracts.SuperchainConfig); + + // Check that the contract is initialized + assertSlotValueIsOne({ _contractAddress: address(superchainConfig), _slot: 0, _offset: 0 }); + require(superchainConfig.guardian() == _cfg.superchainConfigGuardian()); require(superchainConfig.paused() == _isPaused); } + + /// @dev Asserts that for a given contract the value of a storage slot at an offset is 1. + function assertSlotValueIsOne(address _contractAddress, uint256 _slot, uint256 _offset) internal view { + bytes32 slotVal = vm.load(_contractAddress, bytes32(_slot)); + require( + uint8((uint256(slotVal) >> (_offset * 8)) & 0xFF) == uint8(1), + "Storage value is not 1 at the given slot and offset" + ); + } } diff --git a/packages/contracts-bedrock/scripts/Config.sol b/packages/contracts-bedrock/scripts/Config.sol new file mode 100644 index 000000000000..eafb8bfe983b --- /dev/null +++ b/packages/contracts-bedrock/scripts/Config.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Vm } from "forge-std/Vm.sol"; +import { Chains } from "scripts/Chains.sol"; + +/// @title Config +/// @notice Contains all env var based config. Add any new env var parsing to this file +/// to ensure that all config is in a single place. +library Config { + /// @notice Foundry cheatcode VM. + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + /// @notice Returns the path on the local filesystem where the deployment artifact is + /// written to disk after doing a deployment. + function deploymentOutfile() internal view returns (string memory _env) { + _env = vm.envOr( + "DEPLOYMENT_OUTFILE", string.concat(vm.projectRoot(), "/deployments/", _getDeploymentContext(), "/.deploy") + ); + } + + /// @notice Returns the path on the local filesystem where the deploy config is + function deployConfigPath() internal view returns (string memory _env) { + _env = vm.envOr( + "DEPLOY_CONFIG_PATH", string.concat(vm.projectRoot(), "/deploy-config/", _getDeploymentContext(), ".json") + ); + } + + /// @notice Returns the chainid from the EVM context or the value of the CHAIN_ID env var as + /// an override. + function chainID() internal view returns (uint256 _env) { + _env = vm.envOr("CHAIN_ID", block.chainid); + } + + /// @notice Returns the value of the env var CONTRACT_ADDRESSES_PATH which is a JSON key/value + /// pair of contract names and their addresses. Each key/value pair is passed to `save` + /// which then backs the `getAddress` function. + function contractAddressesPath() internal view returns (string memory _env) { + _env = vm.envOr("CONTRACT_ADDRESSES_PATH", string("")); + } + + /// @notice Returns the deployment context which was only useful in the hardhat deploy style + /// of deployments. It is now DEPRECATED and will be removed in the future. + function deploymentContext() internal view returns (string memory _env) { + _env = vm.envOr("DEPLOYMENT_CONTEXT", string("")); + } + + /// @notice The CREATE2 salt to be used when deploying the implementations. + function implSalt() internal view returns (string memory _env) { + _env = vm.envOr("IMPL_SALT", string("ethers phoenix")); + } + + /// @notice Returns the path that the state dump file should be written to or read from + /// on the local filesystem. + function stateDumpPath(string memory _name) internal view returns (string memory _env) { + _env = vm.envOr( + "STATE_DUMP_PATH", string.concat(vm.projectRoot(), "/", _name, "-", vm.toString(block.chainid), ".json") + ); + } + + /// @notice Returns the sig of the entrypoint to the deploy script. By default, it is `run`. + /// This was useful for creating hardhat deploy style artifacts and will be removed in a future release. + function sig() internal view returns (string memory _env) { + _env = vm.envOr("SIG", string("run")); + } + + /// @notice Returns the name of the file that the forge deployment artifact is written to on the local + /// filesystem. By default, it is the name of the deploy script with the suffix `-latest.json`. + /// This was useful for creating hardhat deploy style artifacts and will be removed in a future release. + function deployFile(string memory _sig) internal view returns (string memory _env) { + _env = vm.envOr("DEPLOY_FILE", string.concat(_sig, "-latest.json")); + } + + /// @notice Returns the private key that is used to configure drippie. + function drippieOwnerPrivateKey() internal view returns (uint256 _env) { + _env = vm.envUint("DRIPPIE_OWNER_PRIVATE_KEY"); + } + + /// @notice The context of the deployment is used to namespace the artifacts. + /// An unknown context will use the chainid as the context name. + /// This is legacy code and should be removed in the future. + function _getDeploymentContext() private view returns (string memory) { + string memory context = deploymentContext(); + if (bytes(context).length > 0) { + return context; + } + + uint256 chainid = Config.chainID(); + if (chainid == Chains.Mainnet) { + return "mainnet"; + } else if (chainid == Chains.Goerli) { + return "goerli"; + } else if (chainid == Chains.OPGoerli) { + return "optimism-goerli"; + } else if (chainid == Chains.OPMainnet) { + return "optimism-mainnet"; + } else if (chainid == Chains.LocalDevnet || chainid == Chains.GethDevnet) { + return "devnetL1"; + } else if (chainid == Chains.Hardhat) { + return "hardhat"; + } else if (chainid == Chains.Sepolia) { + return "sepolia"; + } else if (chainid == Chains.OPSepolia) { + return "optimism-sepolia"; + } else { + return vm.toString(chainid); + } + } +} diff --git a/packages/contracts-bedrock/scripts/Deploy.s.sol b/packages/contracts-bedrock/scripts/Deploy.s.sol index f551371ab2a6..2b5eb671fb75 100644 --- a/packages/contracts-bedrock/scripts/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/Deploy.s.sol @@ -12,7 +12,6 @@ import { SafeProxyFactory } from "safe-contracts/proxies/SafeProxyFactory.sol"; import { Enum as SafeOps } from "safe-contracts/common/Enum.sol"; import { Deployer } from "scripts/Deployer.sol"; -import { DeployConfig } from "scripts/DeployConfig.s.sol"; import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { AddressManager } from "src/legacy/AddressManager.sol"; @@ -20,6 +19,7 @@ import { Proxy } from "src/universal/Proxy.sol"; import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; import { StandardBridge } from "src/universal/StandardBridge.sol"; import { OptimismPortal } from "src/L1/OptimismPortal.sol"; +import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; import { L1ChugSplashProxy } from "src/legacy/L1ChugSplashProxy.sol"; import { ResolvedDelegateProxy } from "src/legacy/ResolvedDelegateProxy.sol"; import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; @@ -28,9 +28,13 @@ import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC2 import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +import { DataAvailabilityChallenge } from "src/L1/DataAvailabilityChallenge.sol"; import { Constants } from "src/libraries/Constants.sol"; import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; +import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol"; +import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol"; +import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; import { PreimageOracle } from "src/cannon/PreimageOracle.sol"; import { MIPS } from "src/cannon/MIPS.sol"; import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; @@ -38,6 +42,7 @@ import { ProtocolVersions, ProtocolVersion } from "src/L1/ProtocolVersions.sol"; import { StorageSetter } from "src/universal/StorageSetter.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { Chains } from "scripts/Chains.sol"; +import { Config } from "scripts/Config.sol"; import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; @@ -47,6 +52,7 @@ import { ChainAssertions } from "scripts/ChainAssertions.sol"; import { Types } from "scripts/Types.sol"; import { LibStateDiff } from "scripts/libraries/LibStateDiff.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; +import { ForgeArtifacts } from "scripts/ForgeArtifacts.sol"; /// @title Deploy /// @notice Script used to deploy a bedrock system. The entire system is deployed within the `run` function. @@ -57,11 +63,21 @@ import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; /// contract name to address pairs. That enables this script to be much more flexible in the way it is used. /// This contract must not have constructor logic because it is set into state using `etch`. contract Deploy is Deployer { - DeployConfig public constant cfg = - DeployConfig(address(uint160(uint256(keccak256(abi.encode("optimism.deployconfig")))))); - using stdJson for string; + /// @notice FaultDisputeGameParams is a struct that contains the parameters necessary to call + /// the function _setFaultGameImplementation. This struct exists because the EVM needs + /// to finally adopt PUSHN and get rid of stack too deep once and for all. + /// Someday we will look back and laugh about stack too deep, today is not that day. + struct FaultDisputeGameParams { + AnchorStateRegistry anchorStateRegistry; + DelayedWETH weth; + GameType gameType; + Claim absolutePrestate; + IBigStepper faultVm; + uint256 maxGameDepth; + } + //////////////////////////////////////////////////////////////// // Modifiers // //////////////////////////////////////////////////////////////// @@ -119,17 +135,21 @@ contract Deploy is Deployer { /// Using this helps to reduce config across networks as the implementation /// addresses will be the same across networks when deployed with create2. function _implSalt() internal view returns (bytes32) { - return keccak256(bytes(vm.envOr("IMPL_SALT", string("ethers phoenix")))); + return keccak256(bytes(Config.implSalt())); } /// @notice Returns the proxy addresses. If a proxy is not found, it will have address(0). - function _proxies() private view returns (Types.ContractSet memory proxies_) { + function _proxies() internal view returns (Types.ContractSet memory proxies_) { proxies_ = Types.ContractSet({ L1CrossDomainMessenger: mustGetAddress("L1CrossDomainMessengerProxy"), L1StandardBridge: mustGetAddress("L1StandardBridgeProxy"), L2OutputOracle: mustGetAddress("L2OutputOracleProxy"), + DisputeGameFactory: mustGetAddress("DisputeGameFactoryProxy"), + DelayedWETH: mustGetAddress("DelayedWETHProxy"), + AnchorStateRegistry: mustGetAddress("AnchorStateRegistryProxy"), OptimismMintableERC20Factory: mustGetAddress("OptimismMintableERC20FactoryProxy"), OptimismPortal: mustGetAddress("OptimismPortalProxy"), + OptimismPortal2: mustGetAddress("OptimismPortalProxy"), SystemConfig: mustGetAddress("SystemConfigProxy"), L1ERC721Bridge: mustGetAddress("L1ERC721BridgeProxy"), ProtocolVersions: mustGetAddress("ProtocolVersionsProxy"), @@ -138,13 +158,17 @@ contract Deploy is Deployer { } /// @notice Returns the proxy addresses, not reverting if any are unset. - function _proxiesUnstrict() private view returns (Types.ContractSet memory proxies_) { + function _proxiesUnstrict() internal view returns (Types.ContractSet memory proxies_) { proxies_ = Types.ContractSet({ L1CrossDomainMessenger: getAddress("L1CrossDomainMessengerProxy"), L1StandardBridge: getAddress("L1StandardBridgeProxy"), L2OutputOracle: getAddress("L2OutputOracleProxy"), + DisputeGameFactory: getAddress("DisputeGameFactoryProxy"), + DelayedWETH: getAddress("DelayedWETHProxy"), + AnchorStateRegistry: getAddress("AnchorStateRegistryProxy"), OptimismMintableERC20Factory: getAddress("OptimismMintableERC20FactoryProxy"), OptimismPortal: getAddress("OptimismPortalProxy"), + OptimismPortal2: getAddress("OptimismPortalProxy"), SystemConfig: getAddress("SystemConfigProxy"), L1ERC721Bridge: getAddress("L1ERC721BridgeProxy"), ProtocolVersions: getAddress("ProtocolVersionsProxy"), @@ -158,7 +182,7 @@ contract Deploy is Deployer { /// @notice Gets the address of the SafeProxyFactory and Safe singleton for use in deploying a new GnosisSafe. function _getSafeFactory() internal returns (SafeProxyFactory safeProxyFactory_, Safe safeSingleton_) { - // These are they standard create2 deployed contracts. First we'll check if they are deployed, + // These are the standard create2 deployed contracts. First we'll check if they are deployed, // if not we'll deploy new ones, though not at these addresses. address safeProxyFactory = 0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2; address safeSingleton = 0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552; @@ -230,25 +254,18 @@ contract Deploy is Deployer { // SetUp and Run // //////////////////////////////////////////////////////////////// - function setUp() public virtual override { - super.setUp(); - - string memory path = string.concat(vm.projectRoot(), "/deploy-config/", deploymentContext, ".json"); - vm.etch(address(cfg), vm.getDeployedCode("DeployConfig.s.sol:DeployConfig")); - vm.label(address(cfg), "DeployConfig"); - vm.allowCheatcodes(address(cfg)); - cfg.read(path); - - console.log("Deploying from %s", deployScript); - console.log("Deployment context: %s", deploymentContext); - } - /// @notice Deploy all of the L1 contracts necessary for a full Superchain with a single Op Chain. function run() public { console.log("Deploying a fresh OP Stack including SuperchainConfig"); _run(); } + function runWithStateDump() public { + _run(); + + vm.dumpState(Config.stateDumpPath(name())); + } + /// @notice Deploy all L1 contracts and write the state diff to a file. function runWithStateDiff() public stateDiff { _run(); @@ -258,6 +275,9 @@ contract Deploy is Deployer { function _run() internal { deploySafe(); setupSuperchain(); + if (cfg.usePlasma()) { + setupOpPlasma(); + } setupOpChain(); } @@ -306,8 +326,10 @@ contract Deploy is Deployer { setAlphabetFaultGameImplementation({ _allowUpgrade: false }); setCannonFaultGameImplementation({ _allowUpgrade: false }); + setPermissionedCannonFaultGameImplementation({ _allowUpgrade: false }); transferDisputeGameFactoryOwnership(); + transferDelayedWETHOwnership(); } /// @notice Deploy all of the proxies @@ -315,13 +337,19 @@ contract Deploy is Deployer { console.log("Deploying proxies"); deployERC1967Proxy("OptimismPortalProxy"); - deployERC1967Proxy("L2OutputOracleProxy"); deployERC1967Proxy("SystemConfigProxy"); deployL1StandardBridgeProxy(); deployL1CrossDomainMessengerProxy(); deployERC1967Proxy("OptimismMintableERC20FactoryProxy"); deployERC1967Proxy("L1ERC721BridgeProxy"); + + // Both the DisputeGameFactory and L2OutputOracle proxies are deployed regardles of whether FPAC is enabled + // to prevent a nastier refactor to the deploy scripts. In the future, the L2OutputOracle will be removed. If + // fault proofs are not enabled, the DisputeGameFactory proxy will be unused. deployERC1967Proxy("DisputeGameFactoryProxy"); + deployERC1967Proxy("L2OutputOracleProxy"); + deployERC1967Proxy("DelayedWETHProxy"); + deployERC1967Proxy("AnchorStateRegistryProxy"); transferAddressManagerOwnership(); // to the ProxyAdmin } @@ -329,29 +357,53 @@ contract Deploy is Deployer { /// @notice Deploy all of the implementations function deployImplementations() public { console.log("Deploying implementations"); - deployOptimismPortal(); deployL1CrossDomainMessenger(); - deployL2OutputOracle(); deployOptimismMintableERC20Factory(); deploySystemConfig(); deployL1StandardBridge(); deployL1ERC721Bridge(); + deployOptimismPortal(); + deployL2OutputOracle(); + + // Fault proofs + deployOptimismPortal2(); deployDisputeGameFactory(); + deployDelayedWETH(); deployPreimageOracle(); deployMips(); + deployAnchorStateRegistry(); } /// @notice Initialize all of the implementations function initializeImplementations() public { console.log("Initializing implementations"); - initializeDisputeGameFactory(); initializeSystemConfig(); initializeL1StandardBridge(); initializeL1ERC721Bridge(); initializeOptimismMintableERC20Factory(); initializeL1CrossDomainMessenger(); initializeL2OutputOracle(); - initializeOptimismPortal(); + initializeDisputeGameFactory(); + initializeDelayedWETH(); + initializeAnchorStateRegistry(); + + // Selectively initialize either the original OptimismPortal or the new OptimismPortal2. Since this will upgrade + // the proxy, we cannot initialize both. FPAC warning can be removed once we're done with the old OptimismPortal + // contract. + if (cfg.useFaultProofs()) { + console.log("WARNING: FPAC is enabled. Initializing the OptimismPortal proxy with the OptimismPortal2."); + initializeOptimismPortal2(); + } else { + initializeOptimismPortal(); + } + } + + /// @notice Add Plasma setup to the OP chain + function setupOpPlasma() public { + console.log("Deploying OP Plasma"); + deployDataAvailabilityChallengeProxy(); + deployDataAvailabilityChallenge(); + initializeDataAvailabilityChallenge(); } //////////////////////////////////////////////////////////////// @@ -473,6 +525,20 @@ contract Deploy is Deployer { addr_ = address(proxy); } + /// @notice Deploy the DataAvailabilityChallengeProxy + function deployDataAvailabilityChallengeProxy() public broadcast returns (address addr_) { + console.log("Deploying proxy for DataAvailabilityChallenge"); + address proxyAdmin = mustGetAddress("ProxyAdmin"); + Proxy proxy = new Proxy({ _admin: proxyAdmin }); + + require(EIP1967Helper.getAdmin(address(proxy)) == proxyAdmin); + + save("DataAvailabilityChallengeProxy", address(proxy)); + console.log("DataAvailabilityChallengeProxy deployed at %s", address(proxy)); + + addr_ = address(proxy); + } + //////////////////////////////////////////////////////////////// // Implementation Deployment Functions // //////////////////////////////////////////////////////////////// @@ -504,8 +570,6 @@ contract Deploy is Deployer { contracts.L1CrossDomainMessenger = address(messenger); ChainAssertions.checkL1CrossDomainMessenger({ _contracts: contracts, _vm: vm, _isProxy: false }); - require(loadInitializedSlot("L1CrossDomainMessenger") == 1, "L1CrossDomainMessenger is not initialized"); - addr_ = address(messenger); } @@ -525,7 +589,33 @@ contract Deploy is Deployer { contracts.OptimismPortal = address(portal); ChainAssertions.checkOptimismPortal({ _contracts: contracts, _cfg: cfg, _isProxy: false }); - require(loadInitializedSlot("OptimismPortal") == 1, "OptimismPortal is not initialized"); + addr_ = address(portal); + } + + /// @notice Deploy the OptimismPortal2 + function deployOptimismPortal2() public broadcast returns (address addr_) { + console.log("Deploying OptimismPortal2 implementation"); + + // Could also verify this inside DeployConfig but doing it here is a bit more reliable. + require( + uint32(cfg.respectedGameType()) == cfg.respectedGameType(), "Deploy: respectedGameType must fit into uint32" + ); + + OptimismPortal2 portal = new OptimismPortal2{ salt: _implSalt() }({ + _proofMaturityDelaySeconds: cfg.proofMaturityDelaySeconds(), + _disputeGameFinalityDelaySeconds: cfg.disputeGameFinalityDelaySeconds(), + _initialRespectedGameType: GameType.wrap(uint32(cfg.respectedGameType())) + }); + + save("OptimismPortal2", address(portal)); + console.log("OptimismPortal2 deployed at %s", address(portal)); + + // Override the `OptimismPortal2` contract to the deployed implementation. This is necessary + // to check the `OptimismPortal2` implementation alongside dependent contracts, which + // are always proxies. + Types.ContractSet memory contracts = _proxiesUnstrict(); + contracts.OptimismPortal2 = address(portal); + ChainAssertions.checkOptimismPortal2({ _contracts: contracts, _cfg: cfg, _isProxy: false }); addr_ = address(portal); } @@ -550,8 +640,6 @@ contract Deploy is Deployer { _isProxy: false }); - require(loadInitializedSlot("L2OutputOracle") == 1, "L2OutputOracle is not initialized"); - addr_ = address(oracle); } @@ -574,15 +662,42 @@ contract Deploy is Deployer { } /// @notice Deploy the DisputeGameFactory - function deployDisputeGameFactory() public onlyTestnetOrDevnet broadcast returns (address addr_) { + function deployDisputeGameFactory() public broadcast returns (address addr_) { console.log("Deploying DisputeGameFactory implementation"); DisputeGameFactory factory = new DisputeGameFactory{ salt: _implSalt() }(); save("DisputeGameFactory", address(factory)); console.log("DisputeGameFactory deployed at %s", address(factory)); + // Override the `DisputeGameFactory` contract to the deployed implementation. This is necessary to check the + // `DisputeGameFactory` implementation alongside dependent contracts, which are always proxies. + Types.ContractSet memory contracts = _proxiesUnstrict(); + contracts.DisputeGameFactory = address(factory); + ChainAssertions.checkDisputeGameFactory({ _contracts: contracts, _expectedOwner: address(0) }); + addr_ = address(factory); } + function deployDelayedWETH() public broadcast returns (address addr_) { + console.log("Deploying DelayedWETH implementation"); + DelayedWETH weth = new DelayedWETH{ salt: _implSalt() }(cfg.faultGameWithdrawalDelay()); + save("DelayedWETH", address(weth)); + console.log("DelayedWETH deployed at %s", address(weth)); + + // Override the `DelayedWETH` contract to the deployed implementation. This is necessary + // to check the `DelayedWETH` implementation alongside dependent contracts, which are + // always proxies. + Types.ContractSet memory contracts = _proxiesUnstrict(); + contracts.DelayedWETH = address(weth); + ChainAssertions.checkDelayedWETH({ + _contracts: contracts, + _cfg: cfg, + _isProxy: false, + _expectedOwner: address(0) + }); + + addr_ = address(weth); + } + /// @notice Deploy the ProtocolVersions function deployProtocolVersions() public broadcast returns (address addr_) { console.log("Deploying ProtocolVersions implementation"); @@ -597,13 +712,11 @@ contract Deploy is Deployer { contracts.ProtocolVersions = address(versions); ChainAssertions.checkProtocolVersions({ _contracts: contracts, _cfg: cfg, _isProxy: false }); - require(loadInitializedSlot("ProtocolVersions") == 1, "ProtocolVersions is not initialized"); - addr_ = address(versions); } /// @notice Deploy the PreimageOracle - function deployPreimageOracle() public onlyTestnetOrDevnet broadcast returns (address addr_) { + function deployPreimageOracle() public broadcast returns (address addr_) { console.log("Deploying PreimageOracle implementation"); PreimageOracle preimageOracle = new PreimageOracle{ salt: _implSalt() }({ _minProposalSize: cfg.preimageOracleMinProposalSize(), @@ -616,7 +729,7 @@ contract Deploy is Deployer { } /// @notice Deploy Mips - function deployMips() public onlyTestnetOrDevnet broadcast returns (address addr_) { + function deployMips() public broadcast returns (address addr_) { console.log("Deploying Mips implementation"); MIPS mips = new MIPS{ salt: _implSalt() }(IPreimageOracle(mustGetAddress("PreimageOracle"))); save("Mips", address(mips)); @@ -625,6 +738,17 @@ contract Deploy is Deployer { addr_ = address(mips); } + /// @notice Deploy the AnchorStateRegistry + function deployAnchorStateRegistry() public broadcast returns (address addr_) { + console.log("Deploying AnchorStateRegistry implementation"); + AnchorStateRegistry anchorStateRegistry = + new AnchorStateRegistry{ salt: _implSalt() }(DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"))); + save("AnchorStateRegistry", address(anchorStateRegistry)); + console.log("AnchorStateRegistry deployed at %s", address(anchorStateRegistry)); + + addr_ = address(anchorStateRegistry); + } + /// @notice Deploy the SystemConfig function deploySystemConfig() public broadcast returns (address addr_) { console.log("Deploying SystemConfig implementation"); @@ -640,8 +764,6 @@ contract Deploy is Deployer { contracts.SystemConfig = address(config); ChainAssertions.checkSystemConfig({ _contracts: contracts, _cfg: cfg, _isProxy: false }); - require(loadInitializedSlot("SystemConfig") == 1, "SystemConfig is not initialized"); - addr_ = address(config); } @@ -697,6 +819,16 @@ contract Deploy is Deployer { require(addressManager.owner() == proxyAdmin); } + /// @notice Deploy the DataAvailabilityChallenge + function deployDataAvailabilityChallenge() public broadcast returns (address addr_) { + console.log("Deploying DataAvailabilityChallenge implementation"); + DataAvailabilityChallenge dac = new DataAvailabilityChallenge(); + save("DataAvailabilityChallenge", address(dac)); + console.log("DataAvailabilityChallenge deployed at %s", address(dac)); + + addr_ = address(dac); + } + //////////////////////////////////////////////////////////////// // Initialize Functions // //////////////////////////////////////////////////////////////// @@ -715,7 +847,7 @@ contract Deploy is Deployer { } /// @notice Initialize the DisputeGameFactory - function initializeDisputeGameFactory() public onlyTestnetOrDevnet broadcast { + function initializeDisputeGameFactory() public broadcast { console.log("Upgrading and initializing DisputeGameFactory proxy"); address disputeGameFactoryProxy = mustGetAddress("DisputeGameFactoryProxy"); address disputeGameFactory = mustGetAddress("DisputeGameFactory"); @@ -728,6 +860,69 @@ contract Deploy is Deployer { string memory version = DisputeGameFactory(disputeGameFactoryProxy).version(); console.log("DisputeGameFactory version: %s", version); + + ChainAssertions.checkDisputeGameFactory({ _contracts: _proxiesUnstrict(), _expectedOwner: msg.sender }); + } + + function initializeDelayedWETH() public broadcast { + console.log("Upgrading and initializing DelayedWETH proxy"); + address delayedWETHProxy = mustGetAddress("DelayedWETHProxy"); + address delayedWETH = mustGetAddress("DelayedWETH"); + address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy"); + + _upgradeAndCallViaSafe({ + _proxy: payable(delayedWETHProxy), + _implementation: delayedWETH, + _innerCallData: abi.encodeCall(DelayedWETH.initialize, (msg.sender, SuperchainConfig(superchainConfigProxy))) + }); + + string memory version = DelayedWETH(payable(delayedWETHProxy)).version(); + console.log("DelayedWETH version: %s", version); + + ChainAssertions.checkDelayedWETH({ + _contracts: _proxiesUnstrict(), + _cfg: cfg, + _isProxy: true, + _expectedOwner: msg.sender + }); + } + + function initializeAnchorStateRegistry() public broadcast { + console.log("Upgrading and initializing AnchorStateRegistry proxy"); + address anchorStateRegistryProxy = mustGetAddress("AnchorStateRegistryProxy"); + address anchorStateRegistry = mustGetAddress("AnchorStateRegistry"); + + AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](3); + roots[0] = AnchorStateRegistry.StartingAnchorRoot({ + gameType: GameTypes.CANNON, + outputRoot: OutputRoot({ + root: Hash.wrap(cfg.faultGameGenesisOutputRoot()), + l2BlockNumber: cfg.faultGameGenesisBlock() + }) + }); + roots[1] = AnchorStateRegistry.StartingAnchorRoot({ + gameType: GameTypes.PERMISSIONED_CANNON, + outputRoot: OutputRoot({ + root: Hash.wrap(cfg.faultGameGenesisOutputRoot()), + l2BlockNumber: cfg.faultGameGenesisBlock() + }) + }); + roots[2] = AnchorStateRegistry.StartingAnchorRoot({ + gameType: GameTypes.ALPHABET, + outputRoot: OutputRoot({ + root: Hash.wrap(cfg.faultGameGenesisOutputRoot()), + l2BlockNumber: cfg.faultGameGenesisBlock() + }) + }); + + _upgradeAndCallViaSafe({ + _proxy: payable(anchorStateRegistryProxy), + _implementation: anchorStateRegistry, + _innerCallData: abi.encodeCall(AnchorStateRegistry.initialize, (roots)) + }); + + string memory version = AnchorStateRegistry(payable(anchorStateRegistryProxy)).version(); + console.log("AnchorStateRegistry version: %s", version); } /// @notice Initialize the SystemConfig @@ -769,8 +964,6 @@ contract Deploy is Deployer { console.log("SystemConfig version: %s", version); ChainAssertions.checkSystemConfig({ _contracts: _proxies(), _cfg: cfg, _isProxy: true }); - - require(loadInitializedSlot("SystemConfigProxy") == 1, "SystemConfigProxy is not initialized"); } /// @notice Initialize the L1StandardBridge @@ -895,10 +1088,6 @@ contract Deploy is Deployer { console.log("L1CrossDomainMessenger version: %s", version); ChainAssertions.checkL1CrossDomainMessenger({ _contracts: _proxies(), _vm: vm, _isProxy: true }); - - require( - loadInitializedSlot("L1CrossDomainMessengerProxy") == 1, "L1CrossDomainMessengerProxy is not initialized" - ); } /// @notice Initialize the L2OutputOracle @@ -934,8 +1123,6 @@ contract Deploy is Deployer { _l2OutputOracleStartingTimestamp: cfg.l2OutputOracleStartingTimestamp(), _isProxy: true }); - - require(loadInitializedSlot("L2OutputOracleProxy") == 1, "L2OutputOracleProxy is not initialized"); } /// @notice Initialize the OptimismPortal @@ -965,8 +1152,35 @@ contract Deploy is Deployer { console.log("OptimismPortal version: %s", version); ChainAssertions.checkOptimismPortal({ _contracts: _proxies(), _cfg: cfg, _isProxy: true }); + } + + /// @notice Initialize the OptimismPortal2 + function initializeOptimismPortal2() public broadcast { + console.log("Upgrading and initializing OptimismPortal2 proxy"); + address optimismPortalProxy = mustGetAddress("OptimismPortalProxy"); + address optimismPortal2 = mustGetAddress("OptimismPortal2"); + address disputeGameFactoryProxy = mustGetAddress("DisputeGameFactoryProxy"); + address systemConfigProxy = mustGetAddress("SystemConfigProxy"); + address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy"); + + _upgradeAndCallViaSafe({ + _proxy: payable(optimismPortalProxy), + _implementation: optimismPortal2, + _innerCallData: abi.encodeCall( + OptimismPortal2.initialize, + ( + DisputeGameFactory(disputeGameFactoryProxy), + SystemConfig(systemConfigProxy), + SuperchainConfig(superchainConfigProxy) + ) + ) + }); - require(loadInitializedSlot("OptimismPortalProxy") == 1, "OptimismPortalProxy is not initialized"); + OptimismPortal2 portal = OptimismPortal2(payable(optimismPortalProxy)); + string memory version = portal.version(); + console.log("OptimismPortal2 version: %s", version); + + ChainAssertions.checkOptimismPortal2({ _contracts: _proxies(), _cfg: cfg, _isProxy: true }); } function initializeProtocolVersions() public broadcast { @@ -996,12 +1210,10 @@ contract Deploy is Deployer { console.log("ProtocolVersions version: %s", version); ChainAssertions.checkProtocolVersions({ _contracts: _proxiesUnstrict(), _cfg: cfg, _isProxy: true }); - - require(loadInitializedSlot("ProtocolVersionsProxy") == 1, "ProtocolVersionsProxy is not initialized"); } /// @notice Transfer ownership of the DisputeGameFactory contract to the final system owner - function transferDisputeGameFactoryOwnership() public onlyTestnetOrDevnet broadcast { + function transferDisputeGameFactoryOwnership() public broadcast { console.log("Transferring DisputeGameFactory ownership to Safe"); DisputeGameFactory disputeGameFactory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); address owner = disputeGameFactory.owner(); @@ -1011,6 +1223,21 @@ contract Deploy is Deployer { disputeGameFactory.transferOwnership(safe); console.log("DisputeGameFactory ownership transferred to Safe at: %s", safe); } + ChainAssertions.checkDisputeGameFactory({ _contracts: _proxies(), _expectedOwner: safe }); + } + + /// @notice Transfer ownership of the DelayedWETH contract to the final system owner + function transferDelayedWETHOwnership() public broadcast { + console.log("Transferring DelayedWETH ownership to Safe"); + DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy")); + address owner = weth.owner(); + + address safe = mustGetAddress("SystemOwnerSafe"); + if (owner != safe) { + weth.transferOwnership(safe); + console.log("DelayedWETH ownership transferred to Safe at: %s", safe); + } + ChainAssertions.checkDelayedWETH({ _contracts: _proxies(), _cfg: cfg, _isProxy: true, _expectedOwner: safe }); } /// @notice Loads the mips absolute prestate from the prestate-proof for devnets otherwise @@ -1040,19 +1267,45 @@ contract Deploy is Deployer { } } - /// @notice Sets the implementation for the `FAULT` game type in the `DisputeGameFactory` - function setCannonFaultGameImplementation(bool _allowUpgrade) public onlyTestnetOrDevnet broadcast { + /// @notice Sets the implementation for the `CANNON` game type in the `DisputeGameFactory` + function setCannonFaultGameImplementation(bool _allowUpgrade) public broadcast { console.log("Setting Cannon FaultDisputeGame implementation"); DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); + DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy")); + + // Set the Cannon FaultDisputeGame implementation in the factory. + _setFaultGameImplementation({ + _factory: factory, + _allowUpgrade: _allowUpgrade, + _params: FaultDisputeGameParams({ + anchorStateRegistry: AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), + weth: weth, + gameType: GameTypes.CANNON, + absolutePrestate: loadMipsAbsolutePrestate(), + faultVm: IBigStepper(mustGetAddress("Mips")), + maxGameDepth: cfg.faultGameMaxDepth() + }) + }); + } + + /// @notice Sets the implementation for the `PERMISSIONED_CANNON` game type in the `DisputeGameFactory` + function setPermissionedCannonFaultGameImplementation(bool _allowUpgrade) public broadcast { + console.log("Setting Cannon PermissionedDisputeGame implementation"); + DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); + DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy")); // Set the Cannon FaultDisputeGame implementation in the factory. _setFaultGameImplementation({ _factory: factory, - _gameType: GameTypes.CANNON, - _absolutePrestate: loadMipsAbsolutePrestate(), - _faultVm: IBigStepper(mustGetAddress("Mips")), - _maxGameDepth: cfg.faultGameMaxDepth(), - _allowUpgrade: _allowUpgrade + _allowUpgrade: _allowUpgrade, + _params: FaultDisputeGameParams({ + anchorStateRegistry: AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), + weth: weth, + gameType: GameTypes.PERMISSIONED_CANNON, + absolutePrestate: loadMipsAbsolutePrestate(), + faultVm: IBigStepper(mustGetAddress("Mips")), + maxGameDepth: cfg.faultGameMaxDepth() + }) }); } @@ -1060,57 +1313,81 @@ contract Deploy is Deployer { function setAlphabetFaultGameImplementation(bool _allowUpgrade) public onlyDevnet broadcast { console.log("Setting Alphabet FaultDisputeGame implementation"); DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); + DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy")); Claim outputAbsolutePrestate = Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate())); _setFaultGameImplementation({ _factory: factory, - _gameType: GameTypes.ALPHABET, - _absolutePrestate: outputAbsolutePrestate, - _faultVm: IBigStepper(new AlphabetVM(outputAbsolutePrestate)), - // The max depth for the alphabet trace is always 3. Add 1 because split depth is fully inclusive. - _maxGameDepth: cfg.faultGameSplitDepth() + 3 + 1, - _allowUpgrade: _allowUpgrade + _allowUpgrade: _allowUpgrade, + _params: FaultDisputeGameParams({ + anchorStateRegistry: AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), + weth: weth, + gameType: GameTypes.ALPHABET, + absolutePrestate: outputAbsolutePrestate, + faultVm: IBigStepper(new AlphabetVM(outputAbsolutePrestate, PreimageOracle(mustGetAddress("PreimageOracle")))), + // The max depth for the alphabet trace is always 3. Add 1 because split depth is fully inclusive. + maxGameDepth: cfg.faultGameSplitDepth() + 3 + 1 + }) }); } /// @notice Sets the implementation for the given fault game type in the `DisputeGameFactory`. function _setFaultGameImplementation( DisputeGameFactory _factory, - GameType _gameType, - Claim _absolutePrestate, - IBigStepper _faultVm, - uint256 _maxGameDepth, - bool _allowUpgrade + bool _allowUpgrade, + FaultDisputeGameParams memory _params ) internal { - if (address(_factory.gameImpls(_gameType)) != address(0) && !_allowUpgrade) { + if (address(_factory.gameImpls(_params.gameType)) != address(0) && !_allowUpgrade) { console.log( "[WARN] DisputeGameFactoryProxy: `FaultDisputeGame` implementation already set for game type: %s", - vm.toString(GameType.unwrap(_gameType)) + vm.toString(GameType.unwrap(_params.gameType)) ); return; } - _factory.setImplementation( - _gameType, - new FaultDisputeGame({ - _gameType: _gameType, - _absolutePrestate: _absolutePrestate, - _genesisBlockNumber: cfg.faultGameGenesisBlock(), - _genesisOutputRoot: Hash.wrap(cfg.faultGameGenesisOutputRoot()), - _maxGameDepth: _maxGameDepth, - _splitDepth: cfg.faultGameSplitDepth(), - _gameDuration: Duration.wrap(uint64(cfg.faultGameMaxDuration())), - _vm: _faultVm - }) - ); + uint32 rawGameType = GameType.unwrap(_params.gameType); + if (rawGameType != GameTypes.PERMISSIONED_CANNON.raw()) { + _factory.setImplementation( + _params.gameType, + new FaultDisputeGame({ + _gameType: _params.gameType, + _absolutePrestate: _params.absolutePrestate, + _maxGameDepth: _params.maxGameDepth, + _splitDepth: cfg.faultGameSplitDepth(), + _gameDuration: Duration.wrap(uint64(cfg.faultGameMaxDuration())), + _vm: _params.faultVm, + _weth: _params.weth, + _anchorStateRegistry: _params.anchorStateRegistry, + _l2ChainId: cfg.l2ChainID() + }) + ); + } else { + _factory.setImplementation( + _params.gameType, + new PermissionedDisputeGame({ + _gameType: _params.gameType, + _absolutePrestate: _params.absolutePrestate, + _maxGameDepth: _params.maxGameDepth, + _splitDepth: cfg.faultGameSplitDepth(), + _gameDuration: Duration.wrap(uint64(cfg.faultGameMaxDuration())), + _vm: _params.faultVm, + _weth: _params.weth, + _anchorStateRegistry: _params.anchorStateRegistry, + _l2ChainId: cfg.l2ChainID(), + _proposer: cfg.l2OutputOracleProposer(), + _challenger: cfg.l2OutputOracleChallenger() + }) + ); + } - uint8 rawGameType = GameType.unwrap(_gameType); string memory gameTypeString; - if (rawGameType == GameType.unwrap(GameTypes.CANNON)) { + if (rawGameType == GameTypes.CANNON.raw()) { gameTypeString = "Cannon"; - } else if (rawGameType == GameType.unwrap(GameTypes.ALPHABET)) { + } else if (rawGameType == GameTypes.PERMISSIONED_CANNON.raw()) { + gameTypeString = "PermissionedCannon"; + } else if (rawGameType == GameTypes.ALPHABET.raw()) { gameTypeString = "Alphabet"; } else { gameTypeString = "Unknown"; @@ -1122,4 +1399,36 @@ contract Deploy is Deployer { vm.toString(rawGameType) ); } + + /// @notice Initialize the DataAvailabilityChallenge + function initializeDataAvailabilityChallenge() public broadcast { + console.log("Upgrading and initializing DataAvailabilityChallenge proxy"); + address dataAvailabilityChallengeProxy = mustGetAddress("DataAvailabilityChallengeProxy"); + address dataAvailabilityChallenge = mustGetAddress("DataAvailabilityChallenge"); + + address finalSystemOwner = cfg.finalSystemOwner(); + uint256 daChallengeWindow = cfg.daChallengeWindow(); + uint256 daResolveWindow = cfg.daResolveWindow(); + uint256 daBondSize = cfg.daBondSize(); + uint256 daResolverRefundPercentage = cfg.daResolverRefundPercentage(); + + _upgradeAndCallViaSafe({ + _proxy: payable(dataAvailabilityChallengeProxy), + _implementation: dataAvailabilityChallenge, + _innerCallData: abi.encodeCall( + DataAvailabilityChallenge.initialize, + (finalSystemOwner, daChallengeWindow, daResolveWindow, daBondSize, daResolverRefundPercentage) + ) + }); + + DataAvailabilityChallenge dac = DataAvailabilityChallenge(payable(dataAvailabilityChallengeProxy)); + string memory version = dac.version(); + console.log("DataAvailabilityChallenge version: %s", version); + + require(dac.owner() == finalSystemOwner); + require(dac.challengeWindow() == daChallengeWindow); + require(dac.resolveWindow() == daResolveWindow); + require(dac.bondSize() == daBondSize); + require(dac.resolverRefundPercentage() == daResolverRefundPercentage); + } } diff --git a/packages/contracts-bedrock/scripts/DeployConfig.s.sol b/packages/contracts-bedrock/scripts/DeployConfig.s.sol index e0f48cfbc482..097ffbf4b9e4 100644 --- a/packages/contracts-bedrock/scripts/DeployConfig.s.sol +++ b/packages/contracts-bedrock/scripts/DeployConfig.s.sol @@ -7,6 +7,10 @@ import { stdJson } from "forge-std/StdJson.sol"; import { Executables } from "scripts/Executables.sol"; import { Chains } from "scripts/Chains.sol"; +// Global constant for the `useFaultProofs` slot in the DeployConfig contract, which can be overridden in the testing +// environment. +bytes32 constant USE_FAULT_PROOFS_SLOT = bytes32(uint256(63)); + /// @title DeployConfig /// @notice Represents the configuration required to deploy the system. It is expected /// to read the file from JSON. A future improvement would be to have fallback @@ -31,6 +35,7 @@ contract DeployConfig is Script { address public l2OutputOracleProposer; address public l2OutputOracleChallenger; uint256 public finalizationPeriodSeconds; + bool public fundDevAccounts; address public proxyAdminOwner; address public baseFeeVaultRecipient; uint256 public baseFeeVaultMinimumWithdrawalAmount; @@ -38,6 +43,7 @@ contract DeployConfig is Script { uint256 public l1FeeVaultMinimumWithdrawalAmount; address public sequencerFeeVaultRecipient; uint256 public sequencerFeeVaultMinimumWithdrawalAmount; + uint256 public sequencerFeeVaultWithdrawalNetwork; string public governanceTokenName; string public governanceTokenSymbol; address public governanceTokenOwner; @@ -45,6 +51,7 @@ contract DeployConfig is Script { uint256 public l2GenesisBlockBaseFeePerGas; uint256 public gasPriceOracleOverhead; uint256 public gasPriceOracleScalar; + bool public enableGovernance; uint256 public eip1559Denominator; uint256 public eip1559Elasticity; uint256 public faultGameAbsolutePrestate; @@ -53,19 +60,28 @@ contract DeployConfig is Script { uint256 public faultGameMaxDepth; uint256 public faultGameSplitDepth; uint256 public faultGameMaxDuration; + uint256 public faultGameWithdrawalDelay; uint256 public preimageOracleMinProposalSize; uint256 public preimageOracleChallengePeriod; uint256 public systemConfigStartBlock; uint256 public requiredProtocolVersion; uint256 public recommendedProtocolVersion; + uint256 public proofMaturityDelaySeconds; + uint256 public disputeGameFinalityDelaySeconds; + uint256 public respectedGameType; + bool public useFaultProofs; + bool public usePlasma; + uint256 public daChallengeWindow; + uint256 public daResolveWindow; + uint256 public daBondSize; + uint256 public daResolverRefundPercentage; function read(string memory _path) public { console.log("DeployConfig: reading file %s", _path); try vm.readFile(_path) returns (string memory data) { _json = data; } catch { - console.log("Warning: unable to read config. Do not deploy unless you are not using config."); - return; + require(false, string.concat("Cannot find deploy config file at ", _path)); } finalSystemOwner = stdJson.readAddress(_json, "$.finalSystemOwner"); @@ -85,6 +101,7 @@ contract DeployConfig is Script { l2OutputOracleProposer = stdJson.readAddress(_json, "$.l2OutputOracleProposer"); l2OutputOracleChallenger = stdJson.readAddress(_json, "$.l2OutputOracleChallenger"); finalizationPeriodSeconds = stdJson.readUint(_json, "$.finalizationPeriodSeconds"); + fundDevAccounts = stdJson.readBool(_json, "$.fundDevAccounts"); proxyAdminOwner = stdJson.readAddress(_json, "$.proxyAdminOwner"); baseFeeVaultRecipient = stdJson.readAddress(_json, "$.baseFeeVaultRecipient"); baseFeeVaultMinimumWithdrawalAmount = stdJson.readUint(_json, "$.baseFeeVaultMinimumWithdrawalAmount"); @@ -92,6 +109,7 @@ contract DeployConfig is Script { l1FeeVaultMinimumWithdrawalAmount = stdJson.readUint(_json, "$.l1FeeVaultMinimumWithdrawalAmount"); sequencerFeeVaultRecipient = stdJson.readAddress(_json, "$.sequencerFeeVaultRecipient"); sequencerFeeVaultMinimumWithdrawalAmount = stdJson.readUint(_json, "$.sequencerFeeVaultMinimumWithdrawalAmount"); + sequencerFeeVaultWithdrawalNetwork = stdJson.readUint(_json, "$.sequencerFeeVaultWithdrawalNetwork"); governanceTokenName = stdJson.readString(_json, "$.governanceTokenName"); governanceTokenSymbol = stdJson.readString(_json, "$.governanceTokenSymbol"); governanceTokenOwner = stdJson.readAddress(_json, "$.governanceTokenOwner"); @@ -99,26 +117,34 @@ contract DeployConfig is Script { l2GenesisBlockBaseFeePerGas = stdJson.readUint(_json, "$.l2GenesisBlockBaseFeePerGas"); gasPriceOracleOverhead = stdJson.readUint(_json, "$.gasPriceOracleOverhead"); gasPriceOracleScalar = stdJson.readUint(_json, "$.gasPriceOracleScalar"); + enableGovernance = stdJson.readBool(_json, "$.enableGovernance"); eip1559Denominator = stdJson.readUint(_json, "$.eip1559Denominator"); eip1559Elasticity = stdJson.readUint(_json, "$.eip1559Elasticity"); systemConfigStartBlock = stdJson.readUint(_json, "$.systemConfigStartBlock"); requiredProtocolVersion = stdJson.readUint(_json, "$.requiredProtocolVersion"); recommendedProtocolVersion = stdJson.readUint(_json, "$.recommendedProtocolVersion"); - if ( - block.chainid == Chains.LocalDevnet || block.chainid == Chains.GethDevnet || block.chainid == Chains.Sepolia - || block.chainid == Chains.Goerli - ) { - faultGameAbsolutePrestate = stdJson.readUint(_json, "$.faultGameAbsolutePrestate"); - faultGameMaxDepth = stdJson.readUint(_json, "$.faultGameMaxDepth"); - faultGameSplitDepth = stdJson.readUint(_json, "$.faultGameSplitDepth"); - faultGameMaxDuration = stdJson.readUint(_json, "$.faultGameMaxDuration"); - faultGameGenesisBlock = stdJson.readUint(_json, "$.faultGameGenesisBlock"); - faultGameGenesisOutputRoot = stdJson.readBytes32(_json, "$.faultGameGenesisOutputRoot"); - - preimageOracleMinProposalSize = stdJson.readUint(_json, "$.preimageOracleMinProposalSize"); - preimageOracleChallengePeriod = stdJson.readUint(_json, "$.preimageOracleChallengePeriod"); - } + useFaultProofs = stdJson.readBool(_json, "$.useFaultProofs"); + proofMaturityDelaySeconds = stdJson.readUint(_json, "$.proofMaturityDelaySeconds"); + disputeGameFinalityDelaySeconds = stdJson.readUint(_json, "$.disputeGameFinalityDelaySeconds"); + respectedGameType = stdJson.readUint(_json, "$.respectedGameType"); + + faultGameAbsolutePrestate = stdJson.readUint(_json, "$.faultGameAbsolutePrestate"); + faultGameMaxDepth = stdJson.readUint(_json, "$.faultGameMaxDepth"); + faultGameSplitDepth = stdJson.readUint(_json, "$.faultGameSplitDepth"); + faultGameMaxDuration = stdJson.readUint(_json, "$.faultGameMaxDuration"); + faultGameGenesisBlock = stdJson.readUint(_json, "$.faultGameGenesisBlock"); + faultGameGenesisOutputRoot = stdJson.readBytes32(_json, "$.faultGameGenesisOutputRoot"); + faultGameWithdrawalDelay = stdJson.readUint(_json, "$.faultGameWithdrawalDelay"); + + preimageOracleMinProposalSize = stdJson.readUint(_json, "$.preimageOracleMinProposalSize"); + preimageOracleChallengePeriod = stdJson.readUint(_json, "$.preimageOracleChallengePeriod"); + + usePlasma = _readOr(_json, "$.usePlasma", false); + daChallengeWindow = _readOr(_json, "$.daChallengeWindow", 1000); + daResolveWindow = _readOr(_json, "$.daResolveWindow", 1000); + daBondSize = _readOr(_json, "$.daBondSize", 1000000000); + daResolverRefundPercentage = _readOr(_json, "$.daResolverRefundPercentage", 0); } function l1StartingBlockTag() public returns (bytes32) { @@ -149,6 +175,11 @@ contract DeployConfig is Script { return uint256(_l2OutputOracleStartingTimestamp); } + /// @notice Allow the `usePlasma` config to be overridden in testing environments + function setUsePlasma(bool _usePlasma) public { + usePlasma = _usePlasma; + } + function _getBlockByTag(string memory _tag) internal returns (bytes32) { string[] memory cmd = new string[](3); cmd[0] = Executables.bash; @@ -157,4 +188,12 @@ contract DeployConfig is Script { bytes memory res = vm.ffi(cmd); return abi.decode(res, (bytes32)); } + + function _readOr(string memory json, string memory key, bool defaultValue) internal view returns (bool) { + return vm.keyExists(json, key) ? stdJson.readBool(json, key) : defaultValue; + } + + function _readOr(string memory json, string memory key, uint256 defaultValue) internal view returns (uint256) { + return vm.keyExists(json, key) ? stdJson.readUint(json, key) : defaultValue; + } } diff --git a/packages/contracts-bedrock/scripts/DeployPeriphery.s.sol b/packages/contracts-bedrock/scripts/DeployPeriphery.s.sol index e6b6ca714111..8efb11228334 100644 --- a/packages/contracts-bedrock/scripts/DeployPeriphery.s.sol +++ b/packages/contracts-bedrock/scripts/DeployPeriphery.s.sol @@ -3,8 +3,9 @@ pragma solidity ^0.8.0; import { console2 as console } from "forge-std/console2.sol"; -import { Deployer } from "./Deployer.sol"; -import { PeripheryDeployConfig } from "./PeripheryDeployConfig.s.sol"; +import { Script } from "forge-std/Script.sol"; +import { Artifacts } from "scripts/Artifacts.s.sol"; +import { PeripheryDeployConfig } from "scripts/PeripheryDeployConfig.s.sol"; import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { Proxy } from "src/universal/Proxy.sol"; @@ -16,25 +17,25 @@ import { CheckBalanceLow } from "src/periphery/drippie/dripchecks/CheckBalanceLo import { CheckTrue } from "src/periphery/drippie/dripchecks/CheckTrue.sol"; import { AdminFaucetAuthModule } from "src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; +import { Config } from "scripts/Config.sol"; /// @title DeployPeriphery /// @notice Script used to deploy periphery contracts. -contract DeployPeriphery is Deployer { +contract DeployPeriphery is Script, Artifacts { PeripheryDeployConfig cfg; /// @notice The name of the script, used to ensure the right deploy artifacts /// are used. - function name() public pure override returns (string memory) { - return "DeployPeriphery"; + function name() public pure returns (string memory name_) { + name_ = "DeployPeriphery"; } function setUp() public override { - super.setUp(); + Artifacts.setUp(); string memory path = string.concat(vm.projectRoot(), "/periphery-deploy-config/", deploymentContext, ".json"); cfg = new PeripheryDeployConfig(path); - console.log("Deploying from %s", deployScript); console.log("Deployment context: %s", deploymentContext); } @@ -250,7 +251,7 @@ contract DeployPeriphery is Deployer { /// @notice installs drip configs that deposit funds to all OP Chain faucets. This function /// should only be called on an L1 testnet. function installOpChainFaucetsDrippieConfigs() public { - uint256 drippieOwnerPrivateKey = vm.envUint("DRIPPIE_OWNER_PRIVATE_KEY"); + uint256 drippieOwnerPrivateKey = Config.drippieOwnerPrivateKey(); vm.startBroadcast(drippieOwnerPrivateKey); Drippie drippie = Drippie(mustGetAddress("FaucetDrippie")); @@ -267,7 +268,7 @@ contract DeployPeriphery is Deployer { /// @notice archives the previous OP Chain drip configs. function archivePreviousOpChainFaucetsDrippieConfigs() public { - uint256 drippieOwnerPrivateKey = vm.envUint("DRIPPIE_OWNER_PRIVATE_KEY"); + uint256 drippieOwnerPrivateKey = Config.drippieOwnerPrivateKey(); vm.startBroadcast(drippieOwnerPrivateKey); Drippie drippie = Drippie(mustGetAddress("FaucetDrippie")); diff --git a/packages/contracts-bedrock/scripts/Deployer.sol b/packages/contracts-bedrock/scripts/Deployer.sol index ac431950bebe..6ab4fa8c19a9 100644 --- a/packages/contracts-bedrock/scripts/Deployer.sol +++ b/packages/contracts-bedrock/scripts/Deployer.sol @@ -2,56 +2,34 @@ pragma solidity ^0.8.0; import { Script } from "forge-std/Script.sol"; -import { stdJson } from "forge-std/StdJson.sol"; -import { console2 as console } from "forge-std/console2.sol"; -import { Executables } from "scripts/Executables.sol"; -import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; -import { IAddressManager } from "scripts/interfaces/IAddressManager.sol"; -import { LibString } from "solady/utils/LibString.sol"; -import { Artifacts, Deployment } from "scripts/Artifacts.s.sol"; - -/// @notice Contains information about a storage slot. Mirrors the layout of the storage -/// slot object in Forge artifacts so that we can deserialize JSON into this struct. -struct StorageSlot { - uint256 astId; - string _contract; - string label; - uint256 offset; - string slot; - string _type; -} +import { Artifacts } from "scripts/Artifacts.s.sol"; +import { Config } from "scripts/Config.sol"; +import { DeployConfig } from "scripts/DeployConfig.s.sol"; +import { USE_FAULT_PROOFS_SLOT } from "scripts/DeployConfig.s.sol"; /// @title Deployer /// @author tynes /// @notice A contract that can make deploying and interacting with deployments easy. -/// When a contract is deployed, call the `save` function to write its name and -/// contract address to disk. Inspired by `forge-deploy`. abstract contract Deployer is Script, Artifacts { - /// @notice Path to the deploy artifact generated by foundry - string internal deployPath; + DeployConfig public constant cfg = + DeployConfig(address(uint160(uint256(keccak256(abi.encode("optimism.deployconfig")))))); - /// @notice The name of the deploy script that sends the transactions. - /// Can be modified with the env var DEPLOY_SCRIPT - string internal deployScript; - - /// @notice Create the global variables and set up the filesystem. - /// Forge script will create a file where the prefix is the - /// name of the function that runs with the suffix `-latest.json`. - /// By default, `run()` is called. Allow the user to use the SIG - /// env var to specify what function signature was called so that - /// the `sync()` method can be used to create hardhat deploy style - /// artifacts. + /// @notice Sets up the artifacts contract. function setUp() public virtual override { Artifacts.setUp(); - deployScript = vm.envOr("DEPLOY_SCRIPT", name()); + // Load the `useFaultProofs` slot value prior to etching the DeployConfig's bytecode and reading the deploy + // config file. If this slot has already been set, it will override the preference in the deploy config. + bytes32 useFaultProofsOverride = vm.load(address(cfg), USE_FAULT_PROOFS_SLOT); + + vm.etch(address(cfg), vm.getDeployedCode("DeployConfig.s.sol:DeployConfig")); + vm.label(address(cfg), "DeployConfig"); + vm.allowCheatcodes(address(cfg)); + cfg.read(Config.deployConfigPath()); - string memory sig = vm.envOr("SIG", string("run")); - string memory deployFile = vm.envOr("DEPLOY_FILE", string.concat(sig, "-latest.json")); - uint256 chainId = vm.envOr("CHAIN_ID", block.chainid); - deployPath = string.concat( - vm.projectRoot(), "/broadcast/", deployScript, ".s.sol/", vm.toString(chainId), "/", deployFile - ); + if (useFaultProofsOverride != 0) { + vm.store(address(cfg), USE_FAULT_PROOFS_SLOT, useFaultProofsOverride); + } } /// @notice Returns the name of the deployment script. Children contracts @@ -59,134 +37,4 @@ abstract contract Deployer is Script, Artifacts { /// This should be the same as the name of the script and is used as the file /// name inside of the `broadcast` directory when looking up deployment artifacts. function name() public pure virtual returns (string memory); - - /// @notice Removes the semantic versioning from a contract name. The semver will exist if the contract is compiled - /// more than once with different versions of the compiler. - function _stripSemver(string memory _name) internal returns (string memory) { - string[] memory cmd = new string[](3); - cmd[0] = Executables.bash; - cmd[1] = "-c"; - cmd[2] = string.concat( - Executables.echo, " ", _name, " | ", Executables.sed, " -E 's/[.][0-9]+\\.[0-9]+\\.[0-9]+//g'" - ); - bytes memory res = vm.ffi(cmd); - return string(res); - } - - /// @notice Builds the fully qualified name of a contract. Assumes that the - /// file name is the same as the contract name but strips semver for the file name. - function _getFullyQualifiedName(string memory _name) internal returns (string memory) { - string memory sanitized = _stripSemver(_name); - return string.concat(sanitized, ".sol:", _name); - } - - /// @notice Returns the storage layout for a deployed contract. - function getStorageLayout(string memory _name) public returns (string memory layout_) { - string[] memory cmd = new string[](3); - cmd[0] = Executables.bash; - cmd[1] = "-c"; - cmd[2] = string.concat(Executables.jq, " -r '.storageLayout' < ", _getForgeArtifactPath(_name)); - bytes memory res = vm.ffi(cmd); - layout_ = string(res); - } - - /// @notice Returns the abi from a the forge artifact - function getAbi(string memory _name) public returns (string memory abi_) { - string[] memory cmd = new string[](3); - cmd[0] = Executables.bash; - cmd[1] = "-c"; - cmd[2] = string.concat(Executables.jq, " -r '.abi' < ", _getForgeArtifactPath(_name)); - bytes memory res = vm.ffi(cmd); - abi_ = string(res); - } - - /// @notice Returns the methodIdentifiers from the forge artifact - function getMethodIdentifiers(string memory _name) public returns (string[] memory ids_) { - string[] memory cmd = new string[](3); - cmd[0] = Executables.bash; - cmd[1] = "-c"; - cmd[2] = string.concat(Executables.jq, " '.methodIdentifiers | keys' < ", _getForgeArtifactPath(_name)); - bytes memory res = vm.ffi(cmd); - ids_ = stdJson.readStringArray(string(res), ""); - } - - function _getForgeArtifactDirectory(string memory _name) internal returns (string memory dir_) { - string[] memory cmd = new string[](3); - cmd[0] = Executables.bash; - cmd[1] = "-c"; - cmd[2] = string.concat(Executables.forge, " config --json | ", Executables.jq, " -r .out"); - bytes memory res = vm.ffi(cmd); - string memory contractName = _stripSemver(_name); - dir_ = string.concat(vm.projectRoot(), "/", string(res), "/", contractName, ".sol"); - } - - /// @notice Returns the filesystem path to the artifact path. If the contract was compiled - /// with multiple solidity versions then return the first one based on the result of `ls`. - function _getForgeArtifactPath(string memory _name) internal returns (string memory) { - string memory directory = _getForgeArtifactDirectory(_name); - string memory path = string.concat(directory, "/", _name, ".json"); - if (vm.exists(path)) return path; - - string[] memory cmd = new string[](3); - cmd[0] = Executables.bash; - cmd[1] = "-c"; - cmd[2] = string.concat( - Executables.ls, - " -1 --color=never ", - directory, - " | ", - Executables.jq, - " -R -s -c 'split(\"\n\") | map(select(length > 0))'" - ); - bytes memory res = vm.ffi(cmd); - string[] memory files = stdJson.readStringArray(string(res), ""); - return string.concat(directory, "/", files[0]); - } - - /// @notice Returns the forge artifact given a contract name. - function _getForgeArtifact(string memory _name) internal returns (string memory) { - string memory forgeArtifactPath = _getForgeArtifactPath(_name); - return vm.readFile(forgeArtifactPath); - } - - /// @dev Pulls the `_initialized` storage slot information from the Forge artifacts for a given contract. - function getInitializedSlot(string memory _contractName) internal returns (StorageSlot memory slot_) { - string memory storageLayout = getStorageLayout(_contractName); - - string[] memory command = new string[](3); - command[0] = Executables.bash; - command[1] = "-c"; - command[2] = string.concat( - Executables.echo, - " '", - storageLayout, - "'", - " | ", - Executables.jq, - " '.storage[] | select(.label == \"_initialized\" and .type == \"t_uint8\")'" - ); - bytes memory rawSlot = vm.parseJson(string(vm.ffi(command))); - slot_ = abi.decode(rawSlot, (StorageSlot)); - } - - /// @dev Returns the value of the internal `_initialized` storage slot for a given contract. - function loadInitializedSlot(string memory _contractName) public returns (uint8 initialized_) { - address contractAddress; - // Check if the contract name ends with `Proxy` and, if so, get the implementation address - if (LibString.endsWith(_contractName, "Proxy")) { - contractAddress = EIP1967Helper.getImplementation(getAddress(_contractName)); - _contractName = LibString.slice(_contractName, 0, bytes(_contractName).length - 5); - // If the EIP1967 implementation address is 0, we try to get the implementation address from legacy - // AddressManager, which would work if the proxy is ResolvedDelegateProxy like L1CrossDomainMessengerProxy. - if (contractAddress == address(0)) { - contractAddress = - IAddressManager(mustGetAddress("AddressManager")).getAddress(string.concat("OVM_", _contractName)); - } - } else { - contractAddress = mustGetAddress(_contractName); - } - StorageSlot memory slot = getInitializedSlot(_contractName); - bytes32 slotVal = vm.load(contractAddress, bytes32(vm.parseUint(slot.slot))); - initialized_ = uint8((uint256(slotVal) >> (slot.offset * 8)) & 0xFF); - } } diff --git a/packages/contracts-bedrock/scripts/FaultDisputeGameViz.s.sol b/packages/contracts-bedrock/scripts/FaultDisputeGameViz.s.sol index 19f4b5606130..1d9ba743a56b 100644 --- a/packages/contracts-bedrock/scripts/FaultDisputeGameViz.s.sol +++ b/packages/contracts-bedrock/scripts/FaultDisputeGameViz.s.sol @@ -25,13 +25,7 @@ contract FaultDisputeGameViz is Script, FaultDisputeGame_Init { function setUp() public override { super.setUp(); - super.init({ - rootClaim: ROOT_CLAIM, - absolutePrestate: ABSOLUTE_PRESTATE, - l2BlockNumber: 0x10, - genesisBlockNumber: 0, - genesisOutputRoot: Hash.wrap(bytes32(0)) - }); + super.init({ rootClaim: ROOT_CLAIM, absolutePrestate: ABSOLUTE_PRESTATE, l2BlockNumber: 0x10 }); } /** @@ -49,7 +43,7 @@ contract FaultDisputeGameViz is Script, FaultDisputeGame_Init { * @dev Entry point */ function remote(address _addr) public { - gameProxy = FaultDisputeGame(_addr); + gameProxy = FaultDisputeGame(payable(_addr)); buildGraph(); console.log("Saved graph to `./dispute_game.svg"); } diff --git a/packages/contracts-bedrock/scripts/ForgeArtifacts.sol b/packages/contracts-bedrock/scripts/ForgeArtifacts.sol new file mode 100644 index 000000000000..c95254c8e044 --- /dev/null +++ b/packages/contracts-bedrock/scripts/ForgeArtifacts.sol @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Vm } from "forge-std/Vm.sol"; +import { Executables } from "scripts/Executables.sol"; +import { stdJson } from "forge-std/StdJson.sol"; + +/// @notice Contains information about a storage slot. Mirrors the layout of the storage +/// slot object in Forge artifacts so that we can deserialize JSON into this struct. +struct StorageSlot { + uint256 astId; + string _contract; + string label; + uint256 offset; + string slot; + string _type; +} + +/// @title ForgeArtifacts +/// @notice Library for interacting with the forge artifacts. +library ForgeArtifacts { + /// @notice Foundry cheatcode VM. + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + /// @notice Removes the semantic versioning from a contract name. The semver will exist if the contract is compiled + /// more than once with different versions of the compiler. + function _stripSemver(string memory _name) internal returns (string memory out_) { + string[] memory cmd = new string[](3); + cmd[0] = Executables.bash; + cmd[1] = "-c"; + cmd[2] = string.concat( + Executables.echo, " ", _name, " | ", Executables.sed, " -E 's/[.][0-9]+\\.[0-9]+\\.[0-9]+//g'" + ); + bytes memory res = vm.ffi(cmd); + out_ = string(res); + } + + /// @notice Builds the fully qualified name of a contract. Assumes that the + /// file name is the same as the contract name but strips semver for the file name. + function _getFullyQualifiedName(string memory _name) internal returns (string memory out_) { + string memory sanitized = _stripSemver(_name); + out_ = string.concat(sanitized, ".sol:", _name); + } + + /// @notice Returns the storage layout for a deployed contract. + function getStorageLayout(string memory _name) public returns (string memory layout_) { + string[] memory cmd = new string[](3); + cmd[0] = Executables.bash; + cmd[1] = "-c"; + cmd[2] = string.concat(Executables.jq, " -r '.storageLayout' < ", _getForgeArtifactPath(_name)); + bytes memory res = vm.ffi(cmd); + layout_ = string(res); + } + + /// @notice Returns the abi from a the forge artifact + function getAbi(string memory _name) public returns (string memory abi_) { + string[] memory cmd = new string[](3); + cmd[0] = Executables.bash; + cmd[1] = "-c"; + cmd[2] = string.concat(Executables.jq, " -r '.abi' < ", _getForgeArtifactPath(_name)); + bytes memory res = vm.ffi(cmd); + abi_ = string(res); + } + + /// @notice Returns the methodIdentifiers from the forge artifact + function getMethodIdentifiers(string memory _name) internal returns (string[] memory ids_) { + string[] memory cmd = new string[](3); + cmd[0] = Executables.bash; + cmd[1] = "-c"; + cmd[2] = string.concat(Executables.jq, " '.methodIdentifiers | keys' < ", _getForgeArtifactPath(_name)); + bytes memory res = vm.ffi(cmd); + ids_ = stdJson.readStringArray(string(res), ""); + } + + function _getForgeArtifactDirectory(string memory _name) internal returns (string memory dir_) { + string[] memory cmd = new string[](3); + cmd[0] = Executables.bash; + cmd[1] = "-c"; + cmd[2] = string.concat(Executables.forge, " config --json | ", Executables.jq, " -r .out"); + bytes memory res = vm.ffi(cmd); + string memory contractName = _stripSemver(_name); + dir_ = string.concat(vm.projectRoot(), "/", string(res), "/", contractName, ".sol"); + } + + /// @notice Returns the filesystem path to the artifact path. If the contract was compiled + /// with multiple solidity versions then return the first one based on the result of `ls`. + function _getForgeArtifactPath(string memory _name) internal returns (string memory out_) { + string memory directory = _getForgeArtifactDirectory(_name); + string memory path = string.concat(directory, "/", _name, ".json"); + if (vm.exists(path)) { + return path; + } + + string[] memory cmd = new string[](3); + cmd[0] = Executables.bash; + cmd[1] = "-c"; + cmd[2] = string.concat( + Executables.ls, + " -1 --color=never ", + directory, + " | ", + Executables.jq, + " -R -s -c 'split(\"\n\") | map(select(length > 0))'" + ); + bytes memory res = vm.ffi(cmd); + string[] memory files = stdJson.readStringArray(string(res), ""); + out_ = string.concat(directory, "/", files[0]); + } + + /// @notice Returns the forge artifact given a contract name. + function _getForgeArtifact(string memory _name) internal returns (string memory out_) { + string memory forgeArtifactPath = _getForgeArtifactPath(_name); + out_ = vm.readFile(forgeArtifactPath); + } + + /// @notice Pulls the `_initialized` storage slot information from the Forge artifacts for a given contract. + function getInitializedSlot(string memory _contractName) internal returns (StorageSlot memory slot_) { + string memory storageLayout = getStorageLayout(_contractName); + + string[] memory command = new string[](3); + command[0] = Executables.bash; + command[1] = "-c"; + command[2] = string.concat( + Executables.echo, + " '", + storageLayout, + "'", + " | ", + Executables.jq, + " '.storage[] | select(.label == \"_initialized\" and .type == \"t_uint8\")'" + ); + bytes memory rawSlot = vm.parseJson(string(vm.ffi(command))); + slot_ = abi.decode(rawSlot, (StorageSlot)); + } + + /// @notice Accepts a filepath and then ensures that the directory + /// exists for the file to live in. + function ensurePath(string memory _path) internal { + (, bytes memory returndata) = + address(vm).call(abi.encodeWithSignature("split(string,string)", _path, string("/"))); + string[] memory outputs = abi.decode(returndata, (string[])); + + string memory path = ""; + for (uint256 i = 0; i < outputs.length - 1; i++) { + path = string.concat(path, outputs[i], "/"); + } + vm.createDir(path, true); + } +} diff --git a/packages/contracts-bedrock/scripts/L2Genesis.s.sol b/packages/contracts-bedrock/scripts/L2Genesis.s.sol new file mode 100644 index 000000000000..5f5f8a198bb9 --- /dev/null +++ b/packages/contracts-bedrock/scripts/L2Genesis.s.sol @@ -0,0 +1,429 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Script } from "forge-std/Script.sol"; +import { console2 as console } from "forge-std/console2.sol"; + +import { Artifacts } from "scripts/Artifacts.s.sol"; +import { DeployConfig } from "scripts/DeployConfig.s.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; +import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; +import { L2StandardBridge } from "src/L2/L2StandardBridge.sol"; +import { L2CrossDomainMessenger } from "src/L2/L2CrossDomainMessenger.sol"; +import { SequencerFeeVault } from "src/L2/SequencerFeeVault.sol"; +import { FeeVault } from "src/universal/FeeVault.sol"; +import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; +import { L1Block } from "src/L2/L1Block.sol"; +import { GovernanceToken } from "src/governance/GovernanceToken.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; + +interface IInitializable { + function initialize(address _addr) external; +} + +/// @dev The general flow of adding a predeploy is: +/// 1. _setPredeployProxies uses vm.etch to set the Proxy.sol deployed bytecode for proxy address `0x420...000` to +/// `0x420...000 + PROXY_COUNT - 1`. +/// Additionally, the PROXY_ADMIN_ADDRESS and PROXY_IMPLEMENTATION_ADDRESS storage slots are set for the proxy +/// address. +/// 2. `vm.etch` sets the deployed bytecode for each predeploy at the implementation address (i.e. `0xc0d3` +/// namespace). +/// 3. The `initialize` method is called at the implementation address with zero/dummy vaules if the method exists. +/// 4. The `initialize` method is called at the proxy address with actual vaules if the method exists. +/// 5. A `require` check to verify the expected implementation address is set for the proxy. +/// @notice The following safety invariants are used when setting state: +/// 1. `vm.getDeployedBytecode` can only be used with `vm.etch` when there are no side +/// effects in the constructor and no immutables in the bytecode. +/// 2. A contract must be deployed using the `new` syntax if there are immutables in the code. +/// Any other side effects from the init code besides setting the immutables must be cleaned up afterwards. +/// 3. A contract is deployed using the `new` syntax, however it's not proxied and is still expected to exist at +/// a +/// specific implementation address (i.e. `0xc0d3` namespace). In this case we deploy an instance of the +/// contract +/// using `new` syntax, use `contract.code` to retrieve it's deployed bytecode, `vm.etch` the bytecode at the +/// expected implementation address, and `vm.store` to set any storage slots that are +/// expected to be set after a new deployment. Lastly, we reset the account code and storage slots the contract +/// was initially deployed to so it's not included in the `vm.dumpState`. +contract L2Genesis is Script, Artifacts { + uint256 constant PROXY_COUNT = 2048; + uint256 constant PRECOMPILE_COUNT = 256; + DeployConfig public constant cfg = + DeployConfig(address(uint160(uint256(keccak256(abi.encode("optimism.deployconfig")))))); + + /// @notice The storage slot that holds the address of a proxy implementation. + /// @dev `bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)` + bytes32 internal constant PROXY_IMPLEMENTATION_ADDRESS = + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + + /// @notice The storage slot that holds the address of the owner. + /// @dev `bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)` + bytes32 internal constant PROXY_ADMIN_ADDRESS = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; + uint80 internal constant DEV_ACCOUNT_FUND_AMT = 10_000 ether; + /// @notice Default Anvil dev accounts. Only funded if `cfg.fundDevAccounts == true`. + address[10] internal devAccounts = [ + 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, + 0x70997970C51812dc3A010C7d01b50e0d17dc79C8, + 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC, + 0x90F79bf6EB2c4f870365E785982E1f101E93b906, + 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65, + 0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc, + 0x976EA74026E726554dB657fA54763abd0C3a0aa9, + 0x14dC79964da2C08b23698B3D3cc7Ca32193d9955, + 0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f, + 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 + ]; + + string internal outfile; + + /// @dev Reads the deploy config, sets `outfile` which is where the `vm.dumpState` will be saved to, and + /// loads in the addresses for the L1 contract deployments. + function setUp() public override { + Artifacts.setUp(); + + string memory path = string.concat(vm.projectRoot(), "/deploy-config/", deploymentContext, ".json"); + vm.etch(address(cfg), vm.getDeployedCode("DeployConfig.s.sol:DeployConfig")); + vm.label(address(cfg), "DeployConfig"); + vm.allowCheatcodes(address(cfg)); + cfg.read(path); + + outfile = string.concat(vm.projectRoot(), "/deployments/", deploymentContext, "/genesis-l2.json"); + + _loadAddresses(string.concat(vm.projectRoot(), "/deployments/", deploymentContext, "/.deploy")); + } + + /// @dev Sets the precompiles, proxies, and the implementation accounts to be `vm.dumpState` + /// to generate a L2 genesis alloc. + /// @notice The alloc object is sorted numerically by address. + function run() public { + _dealEthToPrecompiles(); + _setPredeployProxies(); + _setPredeployImplementations(); + + if (cfg.fundDevAccounts()) { + _fundDevAccounts(); + } + + /// Reset so its not included state dump + vm.etch(address(cfg), ""); + + vm.dumpState(outfile); + _sortJsonByKeys(outfile); + } + + /// @notice Give all of the precompiles 1 wei so that they are + /// not considered empty accounts. + function _dealEthToPrecompiles() internal { + for (uint256 i; i < PRECOMPILE_COUNT; i++) { + vm.deal(address(uint160(i)), 1); + } + } + + /// @dev Set up the accounts that correspond to the predeploys. + /// The Proxy bytecode should be set. All proxied predeploys should have + /// the 1967 admin slot set to the ProxyAdmin predeploy. All defined predeploys + /// should have their implementations set. + function _setPredeployProxies() internal { + bytes memory code = vm.getDeployedCode("Proxy.sol:Proxy"); + uint160 prefix = uint160(0x420) << 148; + + console.log( + "Setting proxy deployed bytecode for addresses in range %s through %s", + address(prefix | uint160(0)), + address(prefix | uint160(PROXY_COUNT - 1)) + ); + for (uint256 i = 0; i < PROXY_COUNT; i++) { + address addr = address(prefix | uint160(i)); + if (_notProxied(addr)) { + continue; + } + + vm.etch(addr, code); + vm.store(addr, PROXY_ADMIN_ADDRESS, bytes32(uint256(uint160(Predeploys.PROXY_ADMIN)))); + + if (_isDefinedPredeploy(addr)) { + address implementation = _predeployToCodeNamespace(addr); + console.log("Setting proxy %s implementation: %s", addr, implementation); + vm.store(addr, PROXY_IMPLEMENTATION_ADDRESS, bytes32(uint256(uint160(implementation)))); + } + } + } + + /// @notice LEGACY_ERC20_ETH is not being predeployed since it's been deprecated. + /// @dev Sets all the implementations for the predeploy proxies. For contracts without proxies, + /// sets the deployed bytecode at their expected predeploy address. + function _setPredeployImplementations() internal { + _setLegacyMessagePasser(); + _setDeployerWhitelist(); + _setWETH9(); + _setL2StandardBridge(); + _setL2CrossDomainMessenger(); + _setSequencerFeeVault(); + _setOptimismMintableERC20Factory(); + _setL1BlockNumber(); + _setGasPriceOracle(); + _setGovernanceToken(); + _setL1Block(); + } + + /// @notice This predeploy is following the saftey invariant #1. + function _setLegacyMessagePasser() internal { + _setImplementationCode(Predeploys.LEGACY_MESSAGE_PASSER, "LegacyMessagePasser"); + } + + /// @notice This predeploy is following the saftey invariant #1. + function _setDeployerWhitelist() internal { + _setImplementationCode(Predeploys.DEPLOYER_WHITELIST, "DeployerWhitelist"); + } + + /// @notice This predeploy is following the saftey invariant #1. + /// Contract metadata hash appended to deployed bytecode will differ + /// from previous L2 genesis output. + /// This contract is NOT proxied. + /// @dev We're manually setting storage slots because we need to deployment to be at + /// the address `Predeploys.WETH9`, so we can't just deploy a new instance of `WETH9`. + function _setWETH9() internal { + console.log("Setting %s implementation at: %s", "WETH9", Predeploys.WETH9); + vm.etch(Predeploys.WETH9, vm.getDeployedCode("WETH9.sol:WETH9")); + + vm.store( + Predeploys.WETH9, + /// string public name + hex"0000000000000000000000000000000000000000000000000000000000000000", + /// "Wrapped Ether" + hex"577261707065642045746865720000000000000000000000000000000000001a" + ); + vm.store( + Predeploys.WETH9, + /// string public symbol + hex"0000000000000000000000000000000000000000000000000000000000000001", + /// "WETH" + hex"5745544800000000000000000000000000000000000000000000000000000008" + ); + vm.store( + Predeploys.WETH9, + // uint8 public decimals + hex"0000000000000000000000000000000000000000000000000000000000000002", + /// 18 + hex"0000000000000000000000000000000000000000000000000000000000000012" + ); + } + + /// @notice This predeploy is following the saftey invariant #1. + /// We're initializing the implementation with `address(0)` so + /// it's not left uninitialized. After `initialize` is called on the + /// proxy to set the storage slot with the expected value. + function _setL2StandardBridge() internal { + address impl = _setImplementationCode(Predeploys.L2_STANDARD_BRIDGE, "L2StandardBridge"); + + L2StandardBridge(payable(impl)).initialize(L1StandardBridge(payable(address(0)))); + + L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)).initialize( + L1StandardBridge(mustGetAddress("L1StandardBridgeProxy")) + ); + + _checkL2StandardBridge(impl); + } + + /// @notice This predeploy is following the saftey invariant #1. + /// We're initializing the implementation with `address(0)` so + /// it's not left uninitialized. After `initialize` is called on the + /// proxy to set the storage slot with the expected value. + function _setL2CrossDomainMessenger() internal { + address impl = _setImplementationCode(Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L2CrossDomainMessenger"); + + L2CrossDomainMessenger(impl).initialize(L1CrossDomainMessenger(address(0))); + + L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER).initialize( + L1CrossDomainMessenger(mustGetAddress("L1CrossDomainMessengerProxy")) + ); + + _checkL2CrossDomainMessenger(impl); + } + + /// @notice This predeploy is following the saftey invariant #2, + /// because the constructor args are non-static L1 contract + /// addresses that are being read from the deploy config + /// that are set as immutables. + /// @dev Because the constructor args are stored as immutables, + /// we don't have to worry about setting storage slots. + function _setSequencerFeeVault() internal { + SequencerFeeVault vault = new SequencerFeeVault({ + _recipient: cfg.sequencerFeeVaultRecipient(), + _minWithdrawalAmount: cfg.sequencerFeeVaultMinimumWithdrawalAmount(), + _withdrawalNetwork: FeeVault.WithdrawalNetwork(cfg.sequencerFeeVaultWithdrawalNetwork()) + }); + + address impl = _predeployToCodeNamespace(Predeploys.SEQUENCER_FEE_WALLET); + console.log("Setting %s implementation at: %s", "SequencerFeeVault", impl); + vm.etch(impl, address(vault).code); + + /// Reset so its not included state dump + vm.etch(address(vault), ""); + vm.resetNonce(address(vault)); + + _checkSequencerFeeVault(impl); + } + + /// @notice This predeploy is following the saftey invariant #1. + /// We're initializing the implementation with `address(0)` so + /// it's not left uninitialized. After `initialize` is called on the + /// proxy to set the storage slot with the expected value. + function _setOptimismMintableERC20Factory() internal { + address impl = + _setImplementationCode(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, "OptimismMintableERC20Factory"); + + OptimismMintableERC20Factory(impl).initialize(address(0)); + + OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY).initialize( + Predeploys.L2_STANDARD_BRIDGE + ); + + _checkOptimismMintableERC20Factory(impl); + } + + /// @notice This predeploy is following the saftey invariant #1. + /// This contract has no initializer. + function _setL1BlockNumber() internal { + _setImplementationCode(Predeploys.L1_BLOCK_NUMBER, "L1BlockNumber"); + } + + /// @notice This predeploy is following the saftey invariant #1. + /// This contract has no initializer. + function _setGasPriceOracle() internal { + _setImplementationCode(Predeploys.GAS_PRICE_ORACLE, "GasPriceOracle"); + } + + /// @notice This predeploy is following the saftey invariant #3. + function _setGovernanceToken() internal { + if (!cfg.enableGovernance()) { + console.log("Governance not enabled, skipping setting governanace token"); + return; + } + + GovernanceToken token = new GovernanceToken(); + console.log("Setting %s implementation at: %s", "GovernanceToken", Predeploys.GOVERNANCE_TOKEN); + vm.etch(Predeploys.GOVERNANCE_TOKEN, address(token).code); + + bytes32 _nameSlot = hex"0000000000000000000000000000000000000000000000000000000000000003"; + bytes32 _symbolSlot = hex"0000000000000000000000000000000000000000000000000000000000000004"; + bytes32 _ownerSlot = hex"000000000000000000000000000000000000000000000000000000000000000a"; + + vm.store(Predeploys.GOVERNANCE_TOKEN, _nameSlot, vm.load(address(token), _nameSlot)); + vm.store(Predeploys.GOVERNANCE_TOKEN, _symbolSlot, vm.load(address(token), _symbolSlot)); + vm.store(Predeploys.GOVERNANCE_TOKEN, _ownerSlot, bytes32(uint256(uint160(cfg.governanceTokenOwner())))); + + /// Reset so its not included state dump + vm.etch(address(token), ""); + vm.resetNonce(address(token)); + } + + /// @notice This predeploy is following the saftey invariant #1. + /// This contract has no initializer. + /// @dev Previously the initial L1 attributes was set at genesis, to simplify, + /// they no longer are so the resulting storage slots are no longer set. + function _setL1Block() internal { + _setImplementationCode(Predeploys.L1_BLOCK_ATTRIBUTES, "L1Block"); + } + + /// @dev Returns true if the address is not proxied. + function _notProxied(address _addr) internal pure returns (bool) { + return _addr == Predeploys.GOVERNANCE_TOKEN || _addr == Predeploys.WETH9; + } + + /// @dev Returns true if the address is a predeploy. + function _isDefinedPredeploy(address _addr) internal pure returns (bool) { + return _addr == Predeploys.L2_TO_L1_MESSAGE_PASSER || _addr == Predeploys.L2_CROSS_DOMAIN_MESSENGER + || _addr == Predeploys.L2_STANDARD_BRIDGE || _addr == Predeploys.L2_ERC721_BRIDGE + || _addr == Predeploys.SEQUENCER_FEE_WALLET || _addr == Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY + || _addr == Predeploys.OPTIMISM_MINTABLE_ERC721_FACTORY || _addr == Predeploys.L1_BLOCK_ATTRIBUTES + || _addr == Predeploys.GAS_PRICE_ORACLE || _addr == Predeploys.DEPLOYER_WHITELIST || _addr == Predeploys.WETH9 + || _addr == Predeploys.L1_BLOCK_NUMBER || _addr == Predeploys.LEGACY_MESSAGE_PASSER + || _addr == Predeploys.PROXY_ADMIN || _addr == Predeploys.BASE_FEE_VAULT || _addr == Predeploys.L1_FEE_VAULT + || _addr == Predeploys.GOVERNANCE_TOKEN || _addr == Predeploys.SCHEMA_REGISTRY || _addr == Predeploys.EAS; + } + + /// @dev Function to compute the expected address of the predeploy implementation + /// in the genesis state. + function _predeployToCodeNamespace(address _addr) internal pure returns (address) { + return address( + uint160(uint256(uint160(_addr)) & 0xffff | uint256(uint160(0xc0D3C0d3C0d3C0D3c0d3C0d3c0D3C0d3c0d30000))) + ); + } + + function _setImplementationCode(address _addr, string memory _name) internal returns (address) { + address impl = _predeployToCodeNamespace(_addr); + console.log("Setting %s implementation at: %s", _name, impl); + vm.etch(impl, vm.getDeployedCode(string.concat(_name, ".sol:", _name))); + + _verifyProxyImplementationAddress(_addr, impl); + + return impl; + } + + /// @dev Function to verify the expected implementation address is set for the respective proxy. + function _verifyProxyImplementationAddress(address _proxy, address _impl) internal view { + require( + EIP1967Helper.getImplementation(_proxy) == _impl, + "Expected different address at Proxys PROXY_IMPLEMENTATION_ADDRESS storage slot" + ); + } + + /// @dev Function to verify that a contract was initialized, and can't be reinitialized. + /// @notice There isn't a good way to know if the resulting revering is due to abi mismatch + /// or because it's already been initialized + function _verifyCantReinitialize(address _contract, address _arg) internal { + vm.expectRevert("Initializable: contract is already initialized"); + IInitializable(_contract).initialize(_arg); + } + + /// @dev Helper function to sort the genesis alloc numerically by address. + function _sortJsonByKeys(string memory _path) internal { + string[] memory commands = new string[](3); + commands[0] = "bash"; + commands[1] = "-c"; + commands[2] = string.concat("cat <<< $(jq -S '.' ", _path, ") > ", _path); + vm.ffi(commands); + } + + function _fundDevAccounts() internal { + for (uint256 i; i < devAccounts.length; i++) { + console.log("Funding dev account %s with %s ETH", devAccounts[i], DEV_ACCOUNT_FUND_AMT / 1e18); + vm.deal(devAccounts[i], DEV_ACCOUNT_FUND_AMT); + } + + _checkDevAccountsFunded(); + } + + ////////////////////////////////////////////////////// + /// Post Checks + ////////////////////////////////////////////////////// + function _checkL2StandardBridge(address _impl) internal { + _verifyCantReinitialize(_impl, address(0)); + _verifyCantReinitialize(Predeploys.L2_STANDARD_BRIDGE, mustGetAddress("L1StandardBridgeProxy")); + } + + function _checkL2CrossDomainMessenger(address _impl) internal { + _verifyCantReinitialize(_impl, address(0)); + _verifyCantReinitialize(Predeploys.L2_CROSS_DOMAIN_MESSENGER, mustGetAddress("L1CrossDomainMessengerProxy")); + } + + function _checkSequencerFeeVault(address _impl) internal view { + _verifyProxyImplementationAddress(Predeploys.SEQUENCER_FEE_WALLET, _impl); + } + + function _checkOptimismMintableERC20Factory(address _impl) internal { + _verifyCantReinitialize(_impl, address(0)); + _verifyCantReinitialize(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, Predeploys.L2_STANDARD_BRIDGE); + } + + function _checkDevAccountsFunded() internal view { + for (uint256 i; i < devAccounts.length; i++) { + if (devAccounts[i].balance != DEV_ACCOUNT_FUND_AMT) { + revert( + string.concat("Dev account not funded with expected amount of ETH: ", vm.toString(devAccounts[i])) + ); + } + } + } +} diff --git a/packages/contracts-bedrock/scripts/PeripheryDeployConfig.s.sol b/packages/contracts-bedrock/scripts/PeripheryDeployConfig.s.sol index 9da41818b385..adf2e88fe3ae 100644 --- a/packages/contracts-bedrock/scripts/PeripheryDeployConfig.s.sol +++ b/packages/contracts-bedrock/scripts/PeripheryDeployConfig.s.sol @@ -49,7 +49,8 @@ contract PeripheryDeployConfig is Script { address public orderlyL1BridgeAddress; address public modeL1BridgeAddress; address public lyraL1BridgeAddress; - address[5] public smallFaucetsL1BridgeAddresses; + address public liskL1BridgeAddress; + address[6] public smallFaucetsL1BridgeAddresses; address[2] public largeFaucetsL1BridgeAddresses; uint256 public dripVersion; uint256 public previousDripVersion; @@ -92,6 +93,7 @@ contract PeripheryDeployConfig is Script { zoraL1BridgeAddress = stdJson.readAddress(_json, "$.zoraL1BridgeAddress"); pgnL1BridgeAddress = stdJson.readAddress(_json, "$.pgnL1BridgeAddress"); orderlyL1BridgeAddress = stdJson.readAddress(_json, "$.orderlyL1BridgeAddress"); + liskL1BridgeAddress = stdJson.readAddress(_json, "$.liskL1BridgeAddress"); modeL1BridgeAddress = stdJson.readAddress(_json, "$.modeL1BridgeAddress"); lyraL1BridgeAddress = stdJson.readAddress(_json, "$.lyraL1BridgeAddress"); dripVersion = stdJson.readUint(_json, "$.dripVersion"); @@ -109,6 +111,7 @@ contract PeripheryDeployConfig is Script { smallFaucetsL1BridgeAddresses[2] = orderlyL1BridgeAddress; smallFaucetsL1BridgeAddresses[3] = modeL1BridgeAddress; smallFaucetsL1BridgeAddresses[4] = lyraL1BridgeAddress; + smallFaucetsL1BridgeAddresses[5] = liskL1BridgeAddress; } function getSmallFaucetsL1BridgeAddressesCount() public view returns (uint256 count) { diff --git a/packages/contracts-bedrock/scripts/Types.sol b/packages/contracts-bedrock/scripts/Types.sol index 12b8a41cb46c..c8b48dc1e704 100644 --- a/packages/contracts-bedrock/scripts/Types.sol +++ b/packages/contracts-bedrock/scripts/Types.sol @@ -7,8 +7,12 @@ library Types { address L1CrossDomainMessenger; address L1StandardBridge; address L2OutputOracle; + address DisputeGameFactory; + address DelayedWETH; + address AnchorStateRegistry; address OptimismMintableERC20Factory; address OptimismPortal; + address OptimismPortal2; address SystemConfig; address L1ERC721Bridge; address ProtocolVersions; diff --git a/packages/contracts-bedrock/scripts/invariant-doc-gen.ts b/packages/contracts-bedrock/scripts/autogen/generate-invariant-docs.ts similarity index 96% rename from packages/contracts-bedrock/scripts/invariant-doc-gen.ts rename to packages/contracts-bedrock/scripts/autogen/generate-invariant-docs.ts index a4ec3e7c295a..2c01e2617ef4 100644 --- a/packages/contracts-bedrock/scripts/invariant-doc-gen.ts +++ b/packages/contracts-bedrock/scripts/autogen/generate-invariant-docs.ts @@ -1,8 +1,9 @@ import fs from 'fs' import path from 'path' -const BASE_INVARIANTS_DIR = path.join(__dirname, '..', 'test', 'invariants') -const BASE_DOCS_DIR = path.join(__dirname, '..', 'invariant-docs') +const ROOT_DIR = path.join(__dirname, '..', '..') +const BASE_INVARIANTS_DIR = path.join(ROOT_DIR, 'test', 'invariants') +const BASE_DOCS_DIR = path.join(ROOT_DIR, 'invariant-docs') const BASE_INVARIANT_GH_URL = '../test/invariants/' const NATSPEC_INV = '@custom:invariant' diff --git a/packages/contracts-bedrock/scripts/generate-snapshots.ts b/packages/contracts-bedrock/scripts/autogen/generate-snapshots.ts similarity index 95% rename from packages/contracts-bedrock/scripts/generate-snapshots.ts rename to packages/contracts-bedrock/scripts/autogen/generate-snapshots.ts index a1fe705b2a21..19c5e18740a9 100644 --- a/packages/contracts-bedrock/scripts/generate-snapshots.ts +++ b/packages/contracts-bedrock/scripts/autogen/generate-snapshots.ts @@ -1,8 +1,9 @@ import fs from 'fs' import path from 'path' -const outdir = process.argv[2] || path.join(__dirname, '..', 'snapshots') -const forgeArtifactsDir = path.join(__dirname, '..', 'forge-artifacts') +const root = path.join(__dirname, '..', '..') +const outdir = process.argv[2] || path.join(root, 'snapshots') +const forgeArtifactsDir = path.join(root, 'forge-artifacts') const getAllContractsSources = (): Array => { const paths = [] @@ -20,7 +21,7 @@ const getAllContractsSources = (): Array => { } } } - readFilesRecursively(path.join(__dirname, '..', 'src')) + readFilesRecursively(path.join(root, 'src')) return paths .filter((x) => x.endsWith('.sol')) diff --git a/packages/contracts-bedrock/scripts/check-deploy-configs.sh b/packages/contracts-bedrock/scripts/checks/check-deploy-configs.sh similarity index 91% rename from packages/contracts-bedrock/scripts/check-deploy-configs.sh rename to packages/contracts-bedrock/scripts/checks/check-deploy-configs.sh index 1ad81e908a2f..0c6071fcaca9 100755 --- a/packages/contracts-bedrock/scripts/check-deploy-configs.sh +++ b/packages/contracts-bedrock/scripts/checks/check-deploy-configs.sh @@ -7,7 +7,7 @@ code=0 SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -CONTRACTS_BASE=$(dirname "$SCRIPT_DIR") +CONTRACTS_BASE=$(dirname "$(dirname "$SCRIPT_DIR")") MONOREPO_BASE=$(dirname "$(dirname "$CONTRACTS_BASE")") for config in "$CONTRACTS_BASE"/deploy-config/*.json; do diff --git a/packages/contracts-bedrock/scripts/checks/check-foundry-install.sh b/packages/contracts-bedrock/scripts/checks/check-foundry-install.sh new file mode 100755 index 000000000000..e7edc7db270e --- /dev/null +++ b/packages/contracts-bedrock/scripts/checks/check-foundry-install.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +CONTRACTS_BASE=$(dirname "$(dirname "$SCRIPT_DIR")") +MONOREPO_BASE=$(dirname "$(dirname "$CONTRACTS_BASE")") +VERSIONS_FILE="${MONOREPO_BASE}/versions.json" + +if ! command -v forge &> /dev/null +then + # shellcheck disable=SC2006 + echo "Is Foundry not installed? Consider installing via pnpm install:foundry" >&2 + exit 1 +fi + +# Check VERSIONS_FILE has expected foundry property +if ! jq -e '.foundry' "$VERSIONS_FILE" &> /dev/null; then + echo "'foundry' is missing from $VERSIONS_FILE" >&2 + exit 1 +fi + +# Extract the expected foundry version from versions.json +EXPECTED_VERSION=$(jq -r '.foundry' "$VERSIONS_FILE" | cut -c 1-7) +if [ -z "$EXPECTED_VERSION" ]; then + echo "Unable to extract Foundry version from $VERSIONS_FILE" >&2 + exit 1 +fi + +# Extract the installed forge version +INSTALLED_VERSION=$(forge --version | grep -o '[a-f0-9]\{7\}' | head -n 1) + +# Compare the installed timestamp with the expected timestamp +if [ "$INSTALLED_VERSION" = "$EXPECTED_VERSION" ]; then + echo "Foundry version matches the expected version." +else + echo "Mismatch between installed Foundry version ($INSTALLED_VERSION) and expected version ($EXPECTED_VERSION)." + echo "Your version of Foundry may either not be up to date, or it could be a later version." + echo "Running pnpm update:foundry will install the expected version." +fi diff --git a/packages/contracts-bedrock/scripts/check-snapshots.sh b/packages/contracts-bedrock/scripts/checks/check-snapshots.sh similarity index 100% rename from packages/contracts-bedrock/scripts/check-snapshots.sh rename to packages/contracts-bedrock/scripts/checks/check-snapshots.sh diff --git a/packages/contracts-bedrock/scripts/validate-spacers.ts b/packages/contracts-bedrock/scripts/checks/check-spacers.ts similarity index 98% rename from packages/contracts-bedrock/scripts/validate-spacers.ts rename to packages/contracts-bedrock/scripts/checks/check-spacers.ts index 5e645867604f..8967618131d3 100644 --- a/packages/contracts-bedrock/scripts/validate-spacers.ts +++ b/packages/contracts-bedrock/scripts/checks/check-spacers.ts @@ -7,7 +7,7 @@ import path from 'path' * defaults to the forge-artifacts directory. */ const directoryPath = - process.argv[2] || path.join(__dirname, '..', 'forge-artifacts') + process.argv[2] || path.join(__dirname, '..', '..', 'forge-artifacts') /** * Returns true if the contract should be skipped when inspecting its storage layout. diff --git a/packages/contracts-bedrock/scripts/forge-test-names.ts b/packages/contracts-bedrock/scripts/checks/check-test-names.ts similarity index 100% rename from packages/contracts-bedrock/scripts/forge-test-names.ts rename to packages/contracts-bedrock/scripts/checks/check-test-names.ts diff --git a/packages/contracts-bedrock/scripts/fpac/FPACOPS.s.sol b/packages/contracts-bedrock/scripts/fpac/FPACOPS.s.sol new file mode 100644 index 000000000000..8911c7de1ae0 --- /dev/null +++ b/packages/contracts-bedrock/scripts/fpac/FPACOPS.s.sol @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Proxy } from "src/universal/Proxy.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; +import { AnchorStateRegistry, IAnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; +import { StdAssertions } from "forge-std/StdAssertions.sol"; +import "src/libraries/DisputeTypes.sol"; +import "scripts/Deploy.s.sol"; + +/// @notice Deploys the Fault Proof Alpha Chad contracts. +contract FPACOPS is Deploy, StdAssertions { + //////////////////////////////////////////////////////////////// + // ENTRYPOINTS // + //////////////////////////////////////////////////////////////// + + function deployFPAC(address _proxyAdmin, address _systemOwnerSafe, address _superchainConfigProxy) public { + console.log("Deploying a fresh FPAC system and OptimismPortal2 implementation."); + + prankDeployment("ProxyAdmin", msg.sender); + prankDeployment("SystemOwnerSafe", msg.sender); + prankDeployment("SuperchainConfigProxy", _superchainConfigProxy); + + // Deploy the proxies. + deployERC1967Proxy("DisputeGameFactoryProxy"); + deployERC1967Proxy("DelayedWETHProxy"); + deployERC1967Proxy("AnchorStateRegistryProxy"); + + // Deploy implementations. + deployDisputeGameFactory(); + deployDelayedWETH(); + deployAnchorStateRegistry(); + deployPreimageOracle(); + deployMips(); + + // Deploy the new `OptimismPortal` implementation. + deployOptimismPortal2(); + + // Initialize the proxies. + initializeDisputeGameFactoryProxy(); + initializeDelayedWETHProxy(); + initializeAnchorStateRegistryProxy(); + + // Deploy the Cannon Fault game implementation and set it as game ID = 0. + setCannonFaultGameImplementation({ _allowUpgrade: false }); + // Deploy the Permissioned Cannon Fault game implementation and set it as game ID = 1. + setPermissionedCannonFaultGameImplementation({ _allowUpgrade: false }); + + // Transfer ownership of the DisputeGameFactory to the SystemOwnerSafe, and transfer the administrative rights + // of the DisputeGameFactoryProxy to the ProxyAdmin. + transferDGFOwnershipFinal({ _proxyAdmin: _proxyAdmin, _systemOwnerSafe: _systemOwnerSafe }); + transferWethOwnershipFinal({ _proxyAdmin: _proxyAdmin, _systemOwnerSafe: _systemOwnerSafe }); + transferAnchorStateOwnershipFinal({ _proxyAdmin: _proxyAdmin }); + + // Run post-deployment assertions. + postDeployAssertions({ _proxyAdmin: _proxyAdmin, _systemOwnerSafe: _systemOwnerSafe }); + + // Print overview + printConfigReview(); + } + + //////////////////////////////////////////////////////////////// + // HELPERS // + //////////////////////////////////////////////////////////////// + + /// @notice Initializes the DisputeGameFactoryProxy with the DisputeGameFactory. + function initializeDisputeGameFactoryProxy() internal broadcast { + console.log("Initializing DisputeGameFactoryProxy with DisputeGameFactory."); + + address dgfProxy = mustGetAddress("DisputeGameFactoryProxy"); + Proxy(payable(dgfProxy)).upgradeToAndCall( + mustGetAddress("DisputeGameFactory"), abi.encodeCall(DisputeGameFactory.initialize, msg.sender) + ); + + // Set the initialization bonds for the FaultDisputeGame and PermissionedDisputeGame. + DisputeGameFactory dgf = DisputeGameFactory(dgfProxy); + dgf.setInitBond(GameTypes.CANNON, 0.08 ether); + dgf.setInitBond(GameTypes.PERMISSIONED_CANNON, 0.08 ether); + } + + function initializeDelayedWETHProxy() internal broadcast { + console.log("Initializing DelayedWETHProxy with DelayedWETH."); + + address wethProxy = mustGetAddress("DelayedWETHProxy"); + address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy"); + Proxy(payable(wethProxy)).upgradeToAndCall( + mustGetAddress("DelayedWETH"), + abi.encodeCall(DelayedWETH.initialize, (msg.sender, SuperchainConfig(superchainConfigProxy))) + ); + } + + function initializeAnchorStateRegistryProxy() internal broadcast { + console.log("Initializing AnchorStateRegistryProxy with AnchorStateRegistry."); + + AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](2); + roots[0] = AnchorStateRegistry.StartingAnchorRoot({ + gameType: GameTypes.CANNON, + outputRoot: OutputRoot({ + root: Hash.wrap(cfg.faultGameGenesisOutputRoot()), + l2BlockNumber: cfg.faultGameGenesisBlock() + }) + }); + roots[1] = AnchorStateRegistry.StartingAnchorRoot({ + gameType: GameTypes.PERMISSIONED_CANNON, + outputRoot: OutputRoot({ + root: Hash.wrap(cfg.faultGameGenesisOutputRoot()), + l2BlockNumber: cfg.faultGameGenesisBlock() + }) + }); + + address asrProxy = mustGetAddress("AnchorStateRegistryProxy"); + Proxy(payable(asrProxy)).upgradeToAndCall( + mustGetAddress("AnchorStateRegistry"), abi.encodeCall(AnchorStateRegistry.initialize, (roots)) + ); + } + + /// @notice Transfers admin rights of the `DisputeGameFactoryProxy` to the `ProxyAdmin` and sets the + /// `DisputeGameFactory` owner to the `SystemOwnerSafe`. + function transferDGFOwnershipFinal(address _proxyAdmin, address _systemOwnerSafe) internal broadcast { + DisputeGameFactory dgf = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); + + // Transfer the ownership of the DisputeGameFactory to the SystemOwnerSafe. + dgf.transferOwnership(_systemOwnerSafe); + + // Transfer the admin rights of the DisputeGameFactoryProxy to the ProxyAdmin. + Proxy prox = Proxy(payable(address(dgf))); + prox.changeAdmin(_proxyAdmin); + } + + /// @notice Transfers admin rights of the `DelayedWETHProxy` to the `ProxyAdmin` and sets the + /// `DelayedWETH` owner to the `SystemOwnerSafe`. + function transferWethOwnershipFinal(address _proxyAdmin, address _systemOwnerSafe) internal broadcast { + DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy")); + + // Transfer the ownership of the DelayedWETH to the SystemOwnerSafe. + weth.transferOwnership(_systemOwnerSafe); + + // Transfer the admin rights of the DelayedWETHProxy to the ProxyAdmin. + Proxy prox = Proxy(payable(address(weth))); + prox.changeAdmin(_proxyAdmin); + } + + /// @notice Transfers admin rights of the `AnchorStateRegistryProxy` to the `ProxyAdmin`. + function transferAnchorStateOwnershipFinal(address _proxyAdmin) internal broadcast { + AnchorStateRegistry asr = AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")); + + // Transfer the admin rights of the AnchorStateRegistryProxy to the ProxyAdmin. + Proxy prox = Proxy(payable(address(asr))); + prox.changeAdmin(_proxyAdmin); + } + + /// @notice Checks that the deployed system is configured correctly. + function postDeployAssertions(address _proxyAdmin, address _systemOwnerSafe) internal { + Types.ContractSet memory contracts = _proxiesUnstrict(); + contracts.OptimismPortal2 = mustGetAddress("OptimismPortal2"); + + // Ensure that `useFaultProofs` is set to `true`. + assertTrue(cfg.useFaultProofs()); + + // Ensure the contracts are owned by the correct entities. + address dgfProxyAddr = mustGetAddress("DisputeGameFactoryProxy"); + DisputeGameFactory dgfProxy = DisputeGameFactory(dgfProxyAddr); + assertEq(address(uint160(uint256(vm.load(dgfProxyAddr, Constants.PROXY_OWNER_ADDRESS)))), _proxyAdmin); + ChainAssertions.checkDisputeGameFactory(contracts, _systemOwnerSafe); + address wethProxyAddr = mustGetAddress("DelayedWETHProxy"); + assertEq(address(uint160(uint256(vm.load(wethProxyAddr, Constants.PROXY_OWNER_ADDRESS)))), _proxyAdmin); + ChainAssertions.checkDelayedWETH(contracts, cfg, true, _systemOwnerSafe); + + // Check the config elements in the deployed contracts. + ChainAssertions.checkOptimismPortal2(contracts, cfg, false); + + PreimageOracle oracle = PreimageOracle(mustGetAddress("PreimageOracle")); + assertEq(oracle.minProposalSize(), cfg.preimageOracleMinProposalSize()); + assertEq(oracle.challengePeriod(), cfg.preimageOracleChallengePeriod()); + + MIPS mips = MIPS(mustGetAddress("Mips")); + assertEq(address(mips.oracle()), address(oracle)); + + // Check the FaultDisputeGame configuration. + FaultDisputeGame gameImpl = FaultDisputeGame(payable(address(dgfProxy.gameImpls(GameTypes.CANNON)))); + assertEq(gameImpl.maxGameDepth(), cfg.faultGameMaxDepth()); + assertEq(gameImpl.splitDepth(), cfg.faultGameSplitDepth()); + assertEq(gameImpl.gameDuration().raw(), cfg.faultGameMaxDuration()); + assertEq(gameImpl.absolutePrestate().raw(), bytes32(cfg.faultGameAbsolutePrestate())); + + // Check the security override yoke configuration. + PermissionedDisputeGame soyGameImpl = + PermissionedDisputeGame(payable(address(dgfProxy.gameImpls(GameTypes.PERMISSIONED_CANNON)))); + assertEq(soyGameImpl.maxGameDepth(), cfg.faultGameMaxDepth()); + assertEq(soyGameImpl.splitDepth(), cfg.faultGameSplitDepth()); + assertEq(soyGameImpl.gameDuration().raw(), cfg.faultGameMaxDuration()); + assertEq(soyGameImpl.absolutePrestate().raw(), bytes32(cfg.faultGameAbsolutePrestate())); + + // Check the AnchorStateRegistry configuration. + AnchorStateRegistry asr = AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")); + (Hash root1, uint256 l2BlockNumber1) = asr.anchors(GameTypes.CANNON); + (Hash root2, uint256 l2BlockNumber2) = asr.anchors(GameTypes.PERMISSIONED_CANNON); + assertEq(root1.raw(), cfg.faultGameGenesisOutputRoot()); + assertEq(root2.raw(), cfg.faultGameGenesisOutputRoot()); + assertEq(l2BlockNumber1, cfg.faultGameGenesisBlock()); + assertEq(l2BlockNumber2, cfg.faultGameGenesisBlock()); + } + + /// @notice Prints a review of the fault proof configuration section of the deploy config. + function printConfigReview() internal view { + console.log(unicode"📖 FaultDisputeGame Config Overview (chainid: %d)", block.chainid); + console.log(" 0. Use Fault Proofs: %s", cfg.useFaultProofs() ? "true" : "false"); + console.log(" 1. Absolute Prestate: %x", cfg.faultGameAbsolutePrestate()); + console.log(" 2. Max Depth: %d", cfg.faultGameMaxDepth()); + console.log(" 3. Output / Execution split Depth: %d", cfg.faultGameSplitDepth()); + console.log(" 4. Game Duration (seconds): %d", cfg.faultGameMaxDuration()); + console.log(" 5. L2 Genesis block number: %d", cfg.faultGameGenesisBlock()); + console.log(" 6. L2 Genesis output root: %x", uint256(cfg.faultGameGenesisOutputRoot())); + console.log(" 7. Proof Maturity Delay (seconds): ", cfg.proofMaturityDelaySeconds()); + console.log(" 8. Dispute Game Finality Delay (seconds): ", cfg.disputeGameFinalityDelaySeconds()); + console.log(" 9. Respected Game Type: ", cfg.respectedGameType()); + console.log(" 10. Preimage Oracle Min Proposal Size (bytes): ", cfg.preimageOracleMinProposalSize()); + console.log(" 11. Preimage Oracle Challenge Period (seconds): ", cfg.preimageOracleChallengePeriod()); + } +} diff --git a/packages/contracts-bedrock/scripts/fpac/FPACOPS.sol b/packages/contracts-bedrock/scripts/fpac/FPACOPS.sol deleted file mode 100644 index e86344e49ef0..000000000000 --- a/packages/contracts-bedrock/scripts/fpac/FPACOPS.sol +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -import { Proxy } from "src/universal/Proxy.sol"; -import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; -import { StdAssertions } from "forge-std/StdAssertions.sol"; -import "scripts/Deploy.s.sol"; - -/// @notice Deploys the Fault Proof Alpha Chad contracts. These contracts are currently in-development, and the system -/// is independent of the live protocol. Once the contracts are integrated with the live protocol, this script -/// should be deleted. -contract FPACOPS is Deploy, StdAssertions { - //////////////////////////////////////////////////////////////// - // ENTRYPOINTS // - //////////////////////////////////////////////////////////////// - - function deployFPAC() public { - console.log("Deploying a fresh FPAC system"); - - // Mock the proxy admin & system owner safe so that the DisputeGameFactory & proxy are governed by the deployer. - prankDeployment("ProxyAdmin", msg.sender); - prankDeployment("SystemOwnerSafe", msg.sender); - - // Deploy the DisputeGameFactoryProxy. - deployERC1967Proxy("DisputeGameFactoryProxy"); - - // Deploy implementations. - deployDisputeGameFactory(); - deployPreimageOracle(); - deployMips(); - - // Initialize the DisputeGameFactoryProxy. - initializeDisputeGameFactoryProxy(); - - // Deploy the Cannon Fault game implementation and set it as game ID = 0. - setCannonFaultGameImplementation({ _allowUpgrade: false }); - - // Ensure `msg.sender` owns the system. - postDeployAssertions(); - - // Print overview - printConfigReview(); - } - - function upgradeGameImpl(address _dgf, address _mips) public { - prankDeployment("DisputeGameFactoryProxy", _dgf); - prankDeployment("Mips", _mips); - - setCannonFaultGameImplementation({ _allowUpgrade: true }); - } - - function updateInitBond(address _dgf, GameType _gameType, uint256 _newBond) public { - vm.startBroadcast(msg.sender); - DisputeGameFactory dgfProxy = DisputeGameFactory(_dgf); - dgfProxy.setInitBond(_gameType, _newBond); - vm.stopBroadcast(); - } - - //////////////////////////////////////////////////////////////// - // HELPERS // - //////////////////////////////////////////////////////////////// - - /// @notice Initializes the DisputeGameFactoryProxy with the DisputeGameFactory. - function initializeDisputeGameFactoryProxy() internal onlyTestnetOrDevnet broadcast { - address dgfProxy = mustGetAddress("DisputeGameFactoryProxy"); - Proxy(payable(dgfProxy)).upgradeToAndCall( - mustGetAddress("DisputeGameFactory"), abi.encodeWithSignature("initialize(address)", msg.sender) - ); - } - - /// @notice Checks that the deployed system is configured correctly. - function postDeployAssertions() internal { - // Ensure `msg.sender` owns the deployed system. - address proxyAdmin = mustGetAddress("ProxyAdmin"); - address dgfProxyAddr = mustGetAddress("DisputeGameFactoryProxy"); - DisputeGameFactory dgfProxy = DisputeGameFactory(dgfProxyAddr); - assertEq(dgfProxy.owner(), proxyAdmin); - assertEq(address(uint160(uint256(vm.load(dgfProxyAddr, Constants.PROXY_OWNER_ADDRESS)))), proxyAdmin); - - // Check the config elements. - FaultDisputeGame gameImpl = FaultDisputeGame(address(dgfProxy.gameImpls(GameTypes.CANNON))); - assertEq(gameImpl.maxGameDepth(), cfg.faultGameMaxDepth()); - assertEq(gameImpl.splitDepth(), cfg.faultGameSplitDepth()); - assertEq(gameImpl.gameDuration().raw(), cfg.faultGameMaxDuration()); - assertEq(gameImpl.absolutePrestate().raw(), bytes32(cfg.faultGameAbsolutePrestate())); - assertEq(gameImpl.genesisBlockNumber(), cfg.faultGameGenesisBlock()); - assertEq(gameImpl.genesisOutputRoot().raw(), cfg.faultGameGenesisOutputRoot()); - } - - /// @notice Prints a review of the fault proof configuration section of the deploy config. - function printConfigReview() internal view { - console.log(unicode"📖 FaultDisputeGame Config Overview (chainid: %d)", block.chainid); - console.log(" 1. Absolute Prestate: %x", cfg.faultGameAbsolutePrestate()); - console.log(" 2. Max Depth: %d", cfg.faultGameMaxDepth()); - console.log(" 3. Output / Execution split Depth: %d", cfg.faultGameSplitDepth()); - console.log(" 4. Game Duration (seconds): %d", cfg.faultGameMaxDuration()); - console.log(" 5. L2 Genesis block number: %d", cfg.faultGameGenesisBlock()); - console.log(" 6. L2 Genesis output root: %x", uint256(cfg.faultGameGenesisOutputRoot())); - } -} diff --git a/packages/contracts-bedrock/scripts/fpac/Makefile b/packages/contracts-bedrock/scripts/fpac/Makefile index 6a684a2305ea..64db2979b943 100644 --- a/packages/contracts-bedrock/scripts/fpac/Makefile +++ b/packages/contracts-bedrock/scripts/fpac/Makefile @@ -10,7 +10,7 @@ help: # Show help for each of the Makefile recipes. .PHONY: cannon-prestate cannon-prestate: # Generate the cannon prestate, and tar the `op-program` + `cannon` binaries + prestate data used to generate it. - cd $(monorepo_root) && make cannon-prestate + cd $(monorepo_root) && make reproducible-prestate @mkdir -p prestate-artifacts @cp -r $(monorepo_root)/cannon/bin/** prestate-artifacts/ @cp -r $(monorepo_root)/op-program/bin/** prestate-artifacts/ @@ -22,13 +22,5 @@ cannon-prestate: # Generate the cannon prestate, and tar the `op-program` + `can @rm -rf prestate-artifacts .PHONY: deploy-fresh -deploy-fresh: # Deploy a fresh version of the FPAC contracts. Pass `--broadcast` to send to the network. - forge script FPACOPS.sol --sig "deployFPAC()" --chain $(chain) -vvv $(args) - -.PHONY: upgrade-game-impl -upgrade-game-impl: # Upgrades a dispute game implementation in the deployed `DisputeGameFactory` contract for the configured chain. Pass `--broadcast` to send to the network. - forge script FPACOPS.sol --sig "upgradeGameImpl(address,address)" --chain $(chain) -vvv $(dgf) $(vm) $(args) - -.PHONY: update-init-bond -update-init-bond: # Upgrades a dispute game's init bond in the deployed `DisputeGameFactory` contract for the configured chain. Pass `--broadcast` to send to the network. - forge script FPACOPS.sol --sig "updateInitBond(address,uint8,uint256)" --chain $(chain) -vvv $(dgf) $(game-type) $(new-init-bond) $(args) +deploy-fresh: cannon-prestate # Deploy a fresh version of the FPAC contracts. Pass `--broadcast` to send to the network. + forge script FPACOPS.sol --sig "deployFPAC(address,address)" $(proxy-admin) $(system-owner-safe) --chain $(chain) -vvv $(args) diff --git a/packages/contracts-bedrock/scripts/fpac/README.md b/packages/contracts-bedrock/scripts/fpac/README.md index f77aca662778..f03b755e0fbc 100644 --- a/packages/contracts-bedrock/scripts/fpac/README.md +++ b/packages/contracts-bedrock/scripts/fpac/README.md @@ -6,7 +6,7 @@ Chain-ops scripts for the Fault Proof Alpha Chad contracts. ### Generating the Cannon prestate and artifacts -*Description*: Generates the cannon prestate, tars the relavent artifacts, and sets the absolute prestate field in the network's deploy config. +_Description_: Generates the cannon prestate, tars the relavent artifacts, and sets the absolute prestate field in the network's deploy config. ```sh make cannon-prestate chain= @@ -14,24 +14,8 @@ make cannon-prestate chain= ### Deploying a fresh system -*Description*: Deploys a fully fresh FPAC system to the passed chain. All args after the `chain-name` are forwarded to `forge script`. +_Description_: Deploys a fully fresh FPAC system to the passed chain. All args after the `args=` are forwarded to `forge script`. ```sh -make deploy-fresh chain= [args=] -``` - -### Upgrading the Game Implementation - -*Description*: Upgrades the `CANNON` game type's implementation in the `DisputeGameFactory` that was deployed for the passed `chain-name`. All args after the `chain-name` are forwarded to `forge script`. - -```sh -make upgrade-game-impl chain= dgf= vm= [args=] -``` - -### Updating Init Bonds - -*Description*: Updates the initialization bond for a given game type in the `DisputeGameFactory` that was deployed for the passed `chain-name`. All args after the `chain-name` are forwarded to `forge script`. - -```sh -make update-init-bond chain= dgf= game-type= new-init-bond= [args=] +make deploy-fresh chain= proxy-admin= system-owner-safe= [args=] ``` diff --git a/packages/contracts-bedrock/scripts/fpac/lpp-estimation.sh b/packages/contracts-bedrock/scripts/fpac/lpp-estimation.sh index 1bf0b4f87d2b..a120cccf3dee 100755 --- a/packages/contracts-bedrock/scripts/fpac/lpp-estimation.sh +++ b/packages/contracts-bedrock/scripts/fpac/lpp-estimation.sh @@ -16,7 +16,9 @@ anvil --base-fee $BASE_FEE & ANVIL_PID=$! # Deploy the `PreimageOracle` contract to anvil. -PO_ADDR=$(forge create PreimageOracle --private-key $PRIVATE_KEY --rpc-url $ETH_RPC_URL --json | jq -r '.deployedTo') +PO_MIN_PROPOSAL_SIZE=10000 +PO_CHALLENGE_PERIOD=120 +PO_ADDR=$(forge create PreimageOracle --private-key $PRIVATE_KEY --rpc-url $ETH_RPC_URL --json --constructor-args "${PO_MIN_PROPOSAL_SIZE}" "${PO_CHALLENGE_PERIOD}" 0 | jq -r '.deployedTo') # Capture the balance of the submitter prior to submitting all leaves. BALANCE_BEFORE=$(cast balance --rpc-url http://localhost:8545 "$PUB_KEY") diff --git a/packages/contracts-bedrock/scripts/generate-l2-genesis.sh b/packages/contracts-bedrock/scripts/generate-l2-genesis.sh index 7186e5503d6c..39d162b9151b 100755 --- a/packages/contracts-bedrock/scripts/generate-l2-genesis.sh +++ b/packages/contracts-bedrock/scripts/generate-l2-genesis.sh @@ -63,12 +63,16 @@ if mkdir -- "$LOCKDIR" > /dev/null 2>&1; then fi if [ ! -f "$OUTFILE_L2" ]; then - go run "$OP_NODE" genesis l2 \ + tempfile=$(mktemp) + if ! go run "$OP_NODE" genesis l2 \ --deploy-config "$CONTRACTS_DIR/deploy-config/hardhat.json" \ --l1-deployments "$DEPLOY_ARTIFACT" \ --l1-starting-block "$L1_STARTING_BLOCK_PATH" \ --outfile.l2 "$OUTFILE_L2" \ - --outfile.rollup "$OUTFILE_ROLLUP" > /dev/null 2>&1 + --outfile.rollup "$OUTFILE_ROLLUP" 2>"$tempfile"; then + cat "$tempfile" >&2 + fi + rm "$tempfile" fi else # Wait up to 5 minutes for the lock to be released diff --git a/packages/contracts-bedrock/scripts/getting-started/config.sh b/packages/contracts-bedrock/scripts/getting-started/config.sh index 14cc5b182fdc..95ab527d603d 100755 --- a/packages/contracts-bedrock/scripts/getting-started/config.sh +++ b/packages/contracts-bedrock/scripts/getting-started/config.sh @@ -6,10 +6,10 @@ # invalid JSON file when not filled in, which is annoying. reqenv() { - if [ -z "${!1}" ]; then - echo "Error: environment variable '$1' is undefined" - exit 1 - fi + if [ -z "${!1}" ]; then + echo "Error: environment variable '$1' is undefined" + exit 1 + fi } # Check required environment variables @@ -97,7 +97,7 @@ config=$(cat << EOL "faultGameSplitDepth": 14, "preimageOracleMinProposalSize": 1800000, - "preimageOracleChallengePeriod": 86400 + "preimageOracleChallengePeriod": 86400, } EOL ) diff --git a/packages/contracts-bedrock/scripts/getting-started/versions.sh b/packages/contracts-bedrock/scripts/getting-started/versions.sh index ef8bfaf6a2ef..79dc55a7e9c5 100755 --- a/packages/contracts-bedrock/scripts/getting-started/versions.sh +++ b/packages/contracts-bedrock/scripts/getting-started/versions.sh @@ -14,23 +14,37 @@ version() { fi } +versionFoundry() { + local string="$1" + local version_regex='forge ([0-9]+\.[0-9]+\.[0-9]+)' + local commit_hash_regex='\(([a-fA-F0-9]+)' + local full_regex="${version_regex} ${commit_hash_regex}" + + if [[ $string =~ $full_regex ]]; then + echo "${BASH_REMATCH[1]} (${BASH_REMATCH[2]})" + else + echo "No version, commit hash, and timestamp found." + fi +} + + # Grab versions ver_git=$(version "$(git --version)") ver_go=$(version "$(go version)") ver_node=$(version "$(node --version)") ver_pnpm=$(version "$(pnpm --version)") -ver_foundry=$(version "$(forge --version)") +ver_foundry=$(versionFoundry "$(forge --version)") ver_make=$(version "$(make --version)") ver_jq=$(version "$(jq --version)") ver_direnv=$(version "$(direnv --version)") # Print versions -echo "Dependency | Minimum | Actual" -echo "git 2 $ver_git" -echo "go 1.21 $ver_go" -echo "node 20 $ver_node" -echo "pnpm 8 $ver_pnpm" -echo "foundry 0.2.0 $ver_foundry" -echo "make 3 $ver_make" -echo "jq 1.6 $ver_jq" -echo "direnv 2 $ver_direnv" +echo "Dependency | Minimum | Actual" +echo "git 2 $ver_git" +echo "go 1.21 $ver_go" +echo "node 20 $ver_node" +echo "pnpm 8 $ver_pnpm" +echo "foundry 0.2.0 (a5efe4f) $ver_foundry" +echo "make 3 $ver_make" +echo "jq 1.6 $ver_jq" +echo "direnv 2 $ver_direnv" diff --git a/packages/contracts-bedrock/scripts/go-ffi/bin.go b/packages/contracts-bedrock/scripts/go-ffi/bin.go index da7475392623..3610b7a140b1 100644 --- a/packages/contracts-bedrock/scripts/go-ffi/bin.go +++ b/packages/contracts-bedrock/scripts/go-ffi/bin.go @@ -11,6 +11,8 @@ func main() { DiffTestUtils() case "trie": FuzzTrie() + case "merkle": + DiffMerkle() default: log.Fatal("Must pass a subcommand") } diff --git a/packages/contracts-bedrock/scripts/go-ffi/merkle.go b/packages/contracts-bedrock/scripts/go-ffi/merkle.go new file mode 100644 index 000000000000..3fdad8ca734c --- /dev/null +++ b/packages/contracts-bedrock/scripts/go-ffi/merkle.go @@ -0,0 +1,98 @@ +package main + +import ( + "fmt" + "log" + "os" + "strconv" + + "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/merkle" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" +) + +// VerifyMerkleProof verifies a merkle proof against the root hash and the leaf hash. +// Reference: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#is_valid_merkle_branch +func VerifyMerkleProof(root, leaf common.Hash, index uint64, proof [merkle.BinaryMerkleTreeDepth]common.Hash) bool { + value := leaf + for i := 0; i < merkle.BinaryMerkleTreeDepth; i++ { + if ((index >> i) & 1) == 1 { + value = crypto.Keccak256Hash(proof[i][:], value[:]) + } else { + value = crypto.Keccak256Hash(value[:], proof[i][:]) + } + } + return value == root +} + +const ( + // GenProof generates a merkle proof for a given leaf index by reconstructing the merkle tree from the passed + // leaves. + genProof = "gen_proof" +) + +var ( + rootAndProof, _ = abi.NewType("tuple", "", []abi.ArgumentMarshaling{ + {Name: "root", Type: "bytes32"}, + {Name: "proof", Type: "bytes32[]"}, + }) + + merkleEncoder = abi.Arguments{ + {Type: rootAndProof}, + } +) + +// DiffMerkle generates an abi-encoded `merkleTestCase` of a specified variant. +func DiffMerkle() { + variant := os.Args[2] + if len(variant) == 0 { + log.Fatal("Must pass a variant to the merkle diff tester!") + } + + switch variant { + case genProof: + if len(os.Args) < 5 { + log.Fatal("Invalid arguments to `gen_proof` variant.") + } + + rawLeaves, err := hexutil.Decode(os.Args[3]) + if err != nil { + log.Fatal("Failed to decode leaves: ", err) + } + index, err := strconv.ParseInt(os.Args[4], 10, 64) + if err != nil { + log.Fatal("Failed to parse leaf index: ", err) + } + merkleTree := merkle.NewBinaryMerkleTree() + + // Append all leaves to the merkle tree. + for i := 0; i < len(rawLeaves)/32; i++ { + leaf := common.BytesToHash(rawLeaves[i<<5 : (i+1)<<5]) + merkleTree.AddLeaf(leaf) + } + + // Generate the proof for the given index. + proof := merkleTree.ProofAtIndex(uint64(index)) + + // Generate the merkle root. + root := merkleTree.RootHash() + + // Return "abi.encode(root, proof)" + packed, err := merkleEncoder.Pack(struct { + Root common.Hash + Proof [merkle.BinaryMerkleTreeDepth]common.Hash + }{ + Root: root, + Proof: proof, + }) + if err != nil { + log.Fatal("Failed to ABI encode root and proof: ", err) + } + fmt.Print(hexutil.Encode(packed[32:])) + default: + log.Fatal("Invalid variant passed to merkle diff tester!") + } +} diff --git a/packages/contracts-bedrock/scripts/print-addresses.sh b/packages/contracts-bedrock/scripts/print-addresses.sh index 5ff387fade0c..7a4a7465a862 100755 --- a/packages/contracts-bedrock/scripts/print-addresses.sh +++ b/packages/contracts-bedrock/scripts/print-addresses.sh @@ -42,6 +42,7 @@ for file in "$DIR"/*.json; do filename=$(basename "$file" .json) # If SDK mode is on and the filename is not in the list, skip it + # shellcheck disable=SC2199,SC2076 if $SDK_MODE && [[ ! " ${SDK_FILES[@]} " =~ " ${filename} " ]]; then continue fi diff --git a/packages/contracts-bedrock/scripts/slither.sh b/packages/contracts-bedrock/scripts/slither.sh deleted file mode 100755 index 792c2720cc85..000000000000 --- a/packages/contracts-bedrock/scripts/slither.sh +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env bash - -set -e - -SLITHER_REPORT="slither-report.json" -SLITHER_REPORT_BACKUP="slither-report.json.temp" -SLITHER_TRIAGE_REPORT="slither.db.json" - -# Get the absolute path of the parent directory of this script -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd .. && pwd )" -echo "Running slither in $DIR" -cd "$DIR" - -# Clean up any previous artifacts. -# We do not check if pnpm is installed since it is used across the monorepo -# and must be installed as a prerequisite. -pnpm clean - -# Check if slither is installed -# If not, provide instructions to install with `pip3 install slither-analyzer` and exit -if ! command -v slither &> /dev/null -then - echo "Slither could not be found. Please install slither by running:" - echo "pip3 install slither-analyzer" - exit -fi - - -# Check if jq is installed and exit otherwise -if ! command -v jq &> /dev/null -then - echo "jq could not be found. Please install jq." - echo "On Mac: brew install jq" - echo "On Ubuntu: sudo apt-get install jq" - echo "For other platforms: https://stedolan.github.io/jq/download/" - exit -fi - -# Print the slither version -echo "Slither version: $(slither --version)" - -# Copy the slither report if it exists to a temp file -if [ -e "$SLITHER_REPORT" ]; then - mv $SLITHER_REPORT $SLITHER_REPORT_BACKUP - echo "Created backup of previous slither report at $SLITHER_REPORT_BACKUP" -fi - -# Slither normal mode will run slither and put all findings in the slither-report.json file. -# See slither.config.json for slither settings and to disable specific detectors. -if [[ -z "$TRIAGE_MODE" ]]; then - echo "Running slither in normal mode" - SLITHER_OUTPUT=$(slither . 2>&1 || true) -fi - -# Slither's triage mode will run an 'interview' in the terminal. -# This allows you to review each finding, and specify which to ignore in future runs. -# Findings to keep are output to the slither-report.json output file. -# Checking in a json file is cleaner than adding slither-disable comments throughout the codebase. -# See slither.config.json for slither settings and to disable specific detectors. -if [[ -n "$TRIAGE_MODE" ]]; then - echo "Running slither in triage mode" - SLITHER_OUTPUT=$(slither . --triage-mode --json $SLITHER_REPORT || true) - - # If the slither report was generated successfully, and the slither triage exists, clean up the triaged output. - if [ -f "$SLITHER_REPORT" ] && [ -f "$SLITHER_TRIAGE_REPORT" ]; then - # The following jq command selects a subset of fields in each of the slither triage report description and element objects. - # This significantly slims down the output json, on the order of 100 magnitudes smaller. - updated_json=$(cat $SLITHER_TRIAGE_REPORT | jq -r '[.[] | .id as $id | .description as $description | .check as $check | .impact as $impact | .confidence as $confidence | (.elements[] | .type as $type | .name as $name | (.source_mapping | { "id": $id, "impact": $impact, "confidence": $confidence, "check": $check, "description": $description, "type": $type, "name": $name, start, length, filename_relative } ))]') - echo "$updated_json" > $SLITHER_TRIAGE_REPORT - echo "Slither traige report updated at $DIR/$SLITHER_TRIAGE_REPORT" - fi -fi - -# If slither failed to generate a report, exit with an error. -if [ ! -f "$SLITHER_REPORT" ]; then - echo "Slither output:" - echo "$SLITHER_OUTPUT" - echo "Slither failed to generate a report." - if [ -e "$SLITHER_REPORT_BACKUP" ]; then - mv $SLITHER_REPORT_BACKUP $SLITHER_REPORT - echo "Restored previous slither report from $SLITHER_REPORT_BACKUP" - fi - echo "Exiting with error." - exit 1 -fi - -# If slither successfully generated a report, clean up the report. -# The following jq command selects a subset of fields in each of the slither triage report description and element objects. -# This significantly slims down the output json, on the order of 100 magnitudes smaller. -echo "Slither ran successfully, generating minimzed report..." -updated_json=$(cat $SLITHER_REPORT | jq -r '[.results.detectors[] | .id as $id | .description as $description | .check as $check | .impact as $impact | .confidence as $confidence | (.elements[] | .type as $type | .name as $name | (.source_mapping | { "id": $id, "impact": $impact, "confidence": $confidence, "check": $check, "description": $description, "type": $type, "name": $name, start, length, filename_relative } ))]') -echo "$updated_json" > $SLITHER_REPORT -echo "Slither report stored at $DIR/$SLITHER_REPORT" - -# Remove any items in the slither report that are also in the slither triage report. -# This prevents the same finding from being reported twice. -# Iterate over the slither-report.json file and remove any items that are in the slither.db.json file -# by matching on the id field. -if [ -f "$SLITHER_TRIAGE_REPORT" ]; then - echo "Removing triaged items from slither report..." - jq -s '.[0] as $slither_report | .[1] as $slither_triage_report | $slither_report - ($slither_report - $slither_triage_report)' $SLITHER_REPORT $SLITHER_TRIAGE_REPORT > $SLITHER_REPORT.temp - mv $SLITHER_REPORT.temp $SLITHER_REPORT - echo "Slither report stored at $DIR/$SLITHER_REPORT" -fi - -# Delete the backup of the previous slither report if it exists -if [ -e "$SLITHER_REPORT_BACKUP" ]; then - rm $SLITHER_REPORT_BACKUP - echo "Deleted backup of previous slither report at $SLITHER_REPORT_BACKUP" -fi diff --git a/packages/contracts-bedrock/scripts/verify-foundry-install.sh b/packages/contracts-bedrock/scripts/verify-foundry-install.sh deleted file mode 100755 index 4df76e926c79..000000000000 --- a/packages/contracts-bedrock/scripts/verify-foundry-install.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -if ! command -v forge &> /dev/null -then - # shellcheck disable=SC2006 - echo "Is Foundry not installed? Consider installing via `curl -L https://foundry.paradigm.xyz | bash` and then running `foundryup` on a new terminal. For more context, check the installation instructions in the book: https://book.getfoundry.sh/getting-started/installation.html." - exit 1 -fi - -VERSION=$(forge --version) -echo "Using foundry version: $VERSION" diff --git a/op-challenger/scripts/visualize.sh b/packages/contracts-bedrock/scripts/visualize.sh old mode 100755 new mode 100644 similarity index 78% rename from op-challenger/scripts/visualize.sh rename to packages/contracts-bedrock/scripts/visualize.sh index fb0f979a6b5c..4fb3078ebe70 --- a/op-challenger/scripts/visualize.sh +++ b/packages/contracts-bedrock/scripts/visualize.sh @@ -1,16 +1,13 @@ #!/usr/bin/env bash - set -euo pipefail RPC="${1:?Must specify RPC address}" FAULT_GAME_ADDRESS="${2:?Must specify game address}" DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -DIR="${DIR%/*/*}" -cd "$DIR"/packages/contracts-bedrock +DIR="${DIR%/*}" +cd "$DIR" forge script scripts/FaultDisputeGameViz.s.sol \ --sig "remote(address)" "$FAULT_GAME_ADDRESS" \ --fork-url "$RPC" - -mv dispute_game.svg "$DIR" diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index deade4695d0d..1b5507af099b 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -7,9 +7,13 @@ "initCodeHash": "0xf4c3155413be4a4ebaaba66b9f9daaf12db7b090afdea739dfb8a543df357289", "sourceCodeHash": "0x2ed7a2d6d66839fb3d207952f44b001bce349334adc40ce66d0503ce64e48548" }, + "src/L1/DataAvailabilityChallenge.sol": { + "initCodeHash": "0x39d938938b13abb2455959960c2ee96d48149fd16a7fb69f1f6699460d5019be", + "sourceCodeHash": "0xf6c72a2cca24cfa7c9274d720e93b05d665a2751cca3d747105e6c511ccffc73" + }, "src/L1/DelayedVetoable.sol": { - "initCodeHash": "0xd33130a4cf4db0cbfe07ed20cf910a619562c7560e575e45d20e3db88bb9ccfd", - "sourceCodeHash": "0x0c2f8fdc6130397f84d5867000110ef5ee864946cbc159f9b78665c29333b4f7" + "initCodeHash": "0x84f78e56211500a768b2c5bbafde8e7b411bd64c237297370d7d22326b68357c", + "sourceCodeHash": "0xc59b8574531162e016d7342aeb6e79d05574e90dbea6c0e5ede35b65010ad894" }, "src/L1/L1CrossDomainMessenger.sol": { "initCodeHash": "0xb0b3273999191e4ff616509e3a368a9d89f7967c20ba73c1bc5bd72bd13acb16", @@ -25,11 +29,15 @@ }, "src/L1/L2OutputOracle.sol": { "initCodeHash": "0x14c3a582ca46ef2a6abad5590323f4de26ff4de54415c927c62e131ccbf8d9ba", - "sourceCodeHash": "0xad40d88dad5e371af8cd52673c1bec59c02012cc5627cfd60db32a05b3dcb029" + "sourceCodeHash": "0xf5fcf570721e25459fadbb37e02f9efe349e1c8afcbf1e3b5fdb09c9f612cdc0" }, "src/L1/OptimismPortal.sol": { "initCodeHash": "0x54658799b54481f56acb6481db4f37ad830a8238a8fd592c96e8b1a2b60e0627", - "sourceCodeHash": "0xdc27421279afb6c3b26fc8c589c5d213695f666c74d2c2c41cb7df719d172f37" + "sourceCodeHash": "0xf549ae16033b63e7cb3e032898a6495e1a13090dc8dd1422f7f650076ae973f8" + }, + "src/L1/OptimismPortal2.sol": { + "initCodeHash": "0xd2947b6ce4c5976d550c84d72f14ead2c92f27449edc98ca8ef92b3e9c02b367", + "sourceCodeHash": "0x477df849308119f516e21e3c44e72422c1afa919fad5351be5046d3ec9f0e11f" }, "src/L1/ProtocolVersions.sol": { "initCodeHash": "0x72cd467e8bcf019c02675d72ab762e088bcc9cc0f1a4e9f587fa4589f7fdd1b8", @@ -41,7 +49,7 @@ }, "src/L1/SystemConfig.sol": { "initCodeHash": "0xa14bfe090e923acbacb361d9aa60e0d56fc1dff158ddbd1dc221a5380679f37f", - "sourceCodeHash": "0x1ad56af089f740b63d7a21f2d98b2844860f40b06b692eafb6d0f65aa61ef398" + "sourceCodeHash": "0x58d078f2f352ccb9001afe8245f4655b47ed0227189ede9ef56523b2193059bd" }, "src/L2/BaseFeeVault.sol": { "initCodeHash": "0x2744d34573be83206d1b75d049d18a7bb37f9058e68c0803e5008c46b0dc2474", @@ -87,13 +95,29 @@ "initCodeHash": "0x0da844fb4dd22f252ff631524f01f45edf43bca7558fe45f71d711b79af01742", "sourceCodeHash": "0x1afb1d392e8f6a58ff86ea7f648e0d1756d4ba8d0d964279d58a390deaa53b7e" }, + "src/cannon/MIPS.sol": { + "initCodeHash": "0xaf2ac814f64ccf12e9c6738db7cef865f51f9e39f39105adef9fba11465f6ee1", + "sourceCodeHash": "0x6ab593a4b87007c000c254b2c4ff0507683600f48b60e453148e44bee30030f6" + }, + "src/cannon/PreimageOracle.sol": { + "initCodeHash": "0x9e0d25588d96934044c6f20b62b21444d734c85fe86b305efd8d226024e92725", + "sourceCodeHash": "0xa2d7d5a1de4159a41ff99c2f05d33b9b472c2d00ea62f817b372988f56650153" + }, + "src/dispute/AnchorStateRegistry.sol": { + "initCodeHash": "0x2f8c56069e43e306b0e40fba43109188b29328e83569560021a68aa5d9f2486b", + "sourceCodeHash": "0xba941ad1f941f5a4a066182d50634fa9b190085ed82779decef71c019ba963c5" + }, "src/dispute/DisputeGameFactory.sol": { - "initCodeHash": "0xf6ab546550f8d3d85e9bde748eeea21f7fb16db3d63b8312c04598ca64c1be16", - "sourceCodeHash": "0x01c757935c87dcf2faa7f16bcf29cfb29b90c671a874f983067614670147b11d" + "initCodeHash": "0x80d749a56c1776930fe0deb5c3c646217716e5875ace99c4d036af0452236476", + "sourceCodeHash": "0xf897c1a845a16cb8b217135a1c7819cdb20b315567066282f5860251e48d3611" }, "src/dispute/FaultDisputeGame.sol": { - "initCodeHash": "0x2f30aa96d5c4d126d93dfe15bbfc90e1bbd6bc6208bcc4a49e250790c2a0918d", - "sourceCodeHash": "0x315508f5b100dcb6b81077fb8d6999de425b47f0dfd0330ac1973ee4df166f4a" + "initCodeHash": "0x9dcd4df1dd3e7a09dab46bfe1ebd9376f533cc533f9edce2f01aa754301e25aa", + "sourceCodeHash": "0xbe89df391f9cd4165389a7f6f65af752db13d0e508a1ec8430737aba5b7174dc" + }, + "src/dispute/weth/DelayedWETH.sol": { + "initCodeHash": "0xf179e4249be6eda22b24ae2b32717f154f35edeb9dee0332aefa6fad3ace4dbe", + "sourceCodeHash": "0x1a37c92242f612588f60256554107ee675678687b49b1f41087411dfcd6aabd3" }, "src/legacy/DeployerWhitelist.sol": { "initCodeHash": "0x8de80fb23b26dd9d849f6328e56ea7c173cd9e9ce1f05c9beea559d1720deb3d", @@ -101,7 +125,7 @@ }, "src/legacy/L1BlockNumber.sol": { "initCodeHash": "0xd586c4f93caf1753e53fcdc05eb547c1f3a69afda2904ae9f9d851b73e1c9c1d", - "sourceCodeHash": "0x2a42b124a918a987da60934d9059a72d4fe13dba2609b9f80146f9c8a3fc8293" + "sourceCodeHash": "0xed7d0d1695f28bf967626ee58debcf235204ecc5e814f53da369c94a9ed7cf0d" }, "src/legacy/LegacyMessagePasser.sol": { "initCodeHash": "0x024ff54be1762f8946c6dc1796517bd5e622349a26a908f78a31872969f10369", diff --git a/packages/contracts-bedrock/slither-report.json b/packages/contracts-bedrock/slither-report.json deleted file mode 100644 index 3160d4a30107..000000000000 --- a/packages/contracts-bedrock/slither-report.json +++ /dev/null @@ -1,1190 +0,0 @@ -[ - { - "id": "0b6d0d6699a3fa3c78250e527327e43538895feecaa6cfd8a1793dfcc1d20c72", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.setOwner(address) (src/legacy/L1ChugSplashProxy.sol#138-140) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "function", - "name": "setOwner", - "start": 6890, - "length": 97, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "0b6d0d6699a3fa3c78250e527327e43538895feecaa6cfd8a1793dfcc1d20c72", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.setOwner(address) (src/legacy/L1ChugSplashProxy.sol#138-140) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "function", - "name": "proxyCallIfNotOwner", - "start": 3867, - "length": 237, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "0b6d0d6699a3fa3c78250e527327e43538895feecaa6cfd8a1793dfcc1d20c72", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.setOwner(address) (src/legacy/L1ChugSplashProxy.sol#138-140) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "node", - "name": "return(uint256,uint256)(0x0,returndatasize()())", - "start": 9403, - "length": 29, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "0d4915766a9a2117c655d6bc36e42594e95bbba8293384ec5b2c4904ff7a131f", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.target() (src/L1/DelayedVetoable.sol#108-110) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "target", - "start": 4421, - "length": 99, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "0d4915766a9a2117c655d6bc36e42594e95bbba8293384ec5b2c4904ff7a131f", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.target() (src/L1/DelayedVetoable.sol#108-110) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "readOrHandle", - "start": 2953, - "length": 200, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "0d4915766a9a2117c655d6bc36e42594e95bbba8293384ec5b2c4904ff7a131f", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.target() (src/L1/DelayedVetoable.sol#108-110) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "node", - "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", - "start": 7723, - "length": 48, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "11c5e51d3a0080a2b8f208ae6ec1a4c5617c6df83441ac96c67f322294f73f2b", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.getImplementation() (src/legacy/L1ChugSplashProxy.sol#152-154) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "function", - "name": "getImplementation", - "start": 7519, - "length": 120, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "11c5e51d3a0080a2b8f208ae6ec1a4c5617c6df83441ac96c67f322294f73f2b", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.getImplementation() (src/legacy/L1ChugSplashProxy.sol#152-154) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "function", - "name": "proxyCallIfNotOwner", - "start": 3867, - "length": 237, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "11c5e51d3a0080a2b8f208ae6ec1a4c5617c6df83441ac96c67f322294f73f2b", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.getImplementation() (src/legacy/L1ChugSplashProxy.sol#152-154) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "node", - "name": "return(uint256,uint256)(0x0,returndatasize()())", - "start": 9403, - "length": 29, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "1e96b3f3be5c5b827284291533d15f8b70c3f8bc774e863359baa95195e8a79c", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.implementation() (src/universal/Proxy.sol#97-99) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "function", - "name": "implementation", - "start": 3967, - "length": 123, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "1e96b3f3be5c5b827284291533d15f8b70c3f8bc774e863359baa95195e8a79c", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.implementation() (src/universal/Proxy.sol#97-99) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "function", - "name": "proxyCallIfNotAdmin", - "start": 1295, - "length": 237, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "1e96b3f3be5c5b827284291533d15f8b70c3f8bc774e863359baa95195e8a79c", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.implementation() (src/universal/Proxy.sol#97-99) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "node", - "name": "return(uint256,uint256)(0x0,returndatasize()())", - "start": 5922, - "length": 29, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "2792614492719714cdcff9f7f8e1c602931befa4b0b2d9e0845a2fbf3964f949", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.upgradeToAndCall(address,bytes) (src/universal/Proxy.sol#67-81) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "function", - "name": "upgradeToAndCall", - "start": 2959, - "length": 458, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "2792614492719714cdcff9f7f8e1c602931befa4b0b2d9e0845a2fbf3964f949", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.upgradeToAndCall(address,bytes) (src/universal/Proxy.sol#67-81) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "function", - "name": "proxyCallIfNotAdmin", - "start": 1295, - "length": 237, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "2792614492719714cdcff9f7f8e1c602931befa4b0b2d9e0845a2fbf3964f949", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.upgradeToAndCall(address,bytes) (src/universal/Proxy.sol#67-81) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "node", - "name": "return(uint256,uint256)(0x0,returndatasize()())", - "start": 5922, - "length": 29, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "35ba264224a7ea48dc7cd248e60c07e4aae32401690ae90b217f017e3a1b8112", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.vetoer() (src/L1/DelayedVetoable.sol#102-104) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "vetoer", - "start": 4223, - "length": 107, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "35ba264224a7ea48dc7cd248e60c07e4aae32401690ae90b217f017e3a1b8112", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.vetoer() (src/L1/DelayedVetoable.sol#102-104) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "readOrHandle", - "start": 2953, - "length": 200, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "35ba264224a7ea48dc7cd248e60c07e4aae32401690ae90b217f017e3a1b8112", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.vetoer() (src/L1/DelayedVetoable.sol#102-104) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "node", - "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", - "start": 7723, - "length": 48, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "38dac452acbdd7762ba9aa67e268c249835dad01e219ff2f50d93e4533aa7c52", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) calls DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "readOrHandle", - "start": 2953, - "length": 200, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "38dac452acbdd7762ba9aa67e268c249835dad01e219ff2f50d93e4533aa7c52", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) calls DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "_handleCall", - "start": 5365, - "length": 2009, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "38dac452acbdd7762ba9aa67e268c249835dad01e219ff2f50d93e4533aa7c52", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) calls DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "node", - "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", - "start": 7723, - "length": 48, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "39745c2ba61544fe128a7627287a023e043a087ee32100d6e0bfe5b404209670", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.initiator() (src/L1/DelayedVetoable.sol#96-98) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "initiator", - "start": 4013, - "length": 119, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "39745c2ba61544fe128a7627287a023e043a087ee32100d6e0bfe5b404209670", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.initiator() (src/L1/DelayedVetoable.sol#96-98) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "readOrHandle", - "start": 2953, - "length": 200, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "39745c2ba61544fe128a7627287a023e043a087ee32100d6e0bfe5b404209670", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.initiator() (src/L1/DelayedVetoable.sol#96-98) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "node", - "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", - "start": 7723, - "length": 48, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "3f56bbd28cbf0b716ac3b0a61479a74ece176d3e2f2a53dd16994daa375a5468", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181) calls DelayedVetoable._forwardAndHalt(bytes32) (src/L1/DelayedVetoable.sol#184-197) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "_handleCall", - "start": 5365, - "length": 2009, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "3f56bbd28cbf0b716ac3b0a61479a74ece176d3e2f2a53dd16994daa375a5468", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181) calls DelayedVetoable._forwardAndHalt(bytes32) (src/L1/DelayedVetoable.sol#184-197) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "_forwardAndHalt", - "start": 7454, - "length": 466, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "3f56bbd28cbf0b716ac3b0a61479a74ece176d3e2f2a53dd16994daa375a5468", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181) calls DelayedVetoable._forwardAndHalt(bytes32) (src/L1/DelayedVetoable.sol#184-197) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "node", - "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", - "start": 7723, - "length": 48, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "40da9d5df6ace4d9b107bfd175846739fa74c9a29d3b6d94d1b8ce9dfa13aa05", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.queuedAt(bytes32) (src/L1/DelayedVetoable.sol#121-123) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "queuedAt", - "start": 4865, - "length": 134, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "40da9d5df6ace4d9b107bfd175846739fa74c9a29d3b6d94d1b8ce9dfa13aa05", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.queuedAt(bytes32) (src/L1/DelayedVetoable.sol#121-123) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "readOrHandle", - "start": 2953, - "length": 200, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "40da9d5df6ace4d9b107bfd175846739fa74c9a29d3b6d94d1b8ce9dfa13aa05", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.queuedAt(bytes32) (src/L1/DelayedVetoable.sol#121-123) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "node", - "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", - "start": 7723, - "length": 48, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "4ea64b8e0080de740c9c25e7841217213a680d8680654c8c9f744be145a1431a", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.setCode(bytes) (src/legacy/L1ChugSplashProxy.sol#96-124) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "function", - "name": "setCode", - "start": 5022, - "length": 1285, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "4ea64b8e0080de740c9c25e7841217213a680d8680654c8c9f744be145a1431a", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.setCode(bytes) (src/legacy/L1ChugSplashProxy.sol#96-124) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "function", - "name": "proxyCallIfNotOwner", - "start": 3867, - "length": 237, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "4ea64b8e0080de740c9c25e7841217213a680d8680654c8c9f744be145a1431a", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.setCode(bytes) (src/legacy/L1ChugSplashProxy.sol#96-124) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "node", - "name": "return(uint256,uint256)(0x0,returndatasize()())", - "start": 9403, - "length": 29, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "5dbecee956931b503b0ed4fbb7be62ba5f9f64bab10ac87b3c5ba4dab3694bec", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.upgradeTo(address) (src/universal/Proxy.sol#59-61) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "function", - "name": "upgradeTo", - "start": 2498, - "length": 131, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "5dbecee956931b503b0ed4fbb7be62ba5f9f64bab10ac87b3c5ba4dab3694bec", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.upgradeTo(address) (src/universal/Proxy.sol#59-61) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "function", - "name": "proxyCallIfNotAdmin", - "start": 1295, - "length": 237, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "5dbecee956931b503b0ed4fbb7be62ba5f9f64bab10ac87b3c5ba4dab3694bec", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.upgradeTo(address) (src/universal/Proxy.sol#59-61) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "node", - "name": "return(uint256,uint256)(0x0,returndatasize()())", - "start": 5922, - "length": 29, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "5f00d9ac316494d702da33c92ba3267b0b2a5ab498b5c720e942923a75fd0f50", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.changeAdmin(address) (src/universal/Proxy.sol#85-87) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "function", - "name": "changeAdmin", - "start": 3563, - "length": 109, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "5f00d9ac316494d702da33c92ba3267b0b2a5ab498b5c720e942923a75fd0f50", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.changeAdmin(address) (src/universal/Proxy.sol#85-87) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "function", - "name": "proxyCallIfNotAdmin", - "start": 1295, - "length": 237, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "5f00d9ac316494d702da33c92ba3267b0b2a5ab498b5c720e942923a75fd0f50", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.changeAdmin(address) (src/universal/Proxy.sol#85-87) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "node", - "name": "return(uint256,uint256)(0x0,returndatasize()())", - "start": 5922, - "length": 29, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "61c6823d9d96abad705c3e29c3768a5d2ade61e6f226c9241e6f3278063ab469", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.admin() (src/universal/Proxy.sol#91-93) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "function", - "name": "admin", - "start": 3763, - "length": 105, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "61c6823d9d96abad705c3e29c3768a5d2ade61e6f226c9241e6f3278063ab469", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.admin() (src/universal/Proxy.sol#91-93) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "function", - "name": "proxyCallIfNotAdmin", - "start": 1295, - "length": 237, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "61c6823d9d96abad705c3e29c3768a5d2ade61e6f226c9241e6f3278063ab469", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.admin() (src/universal/Proxy.sol#91-93) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "node", - "name": "return(uint256,uint256)(0x0,returndatasize()())", - "start": 5922, - "length": 29, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "648de83c485a902ab3df50445e187c6390720ae77705d14edbcc112e4fd8fe1a", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) calls L1ChugSplashProxy._doProxyCall() (src/legacy/L1ChugSplashProxy.sol#175-198) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "function", - "name": "proxyCallIfNotOwner", - "start": 3867, - "length": 237, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "648de83c485a902ab3df50445e187c6390720ae77705d14edbcc112e4fd8fe1a", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) calls L1ChugSplashProxy._doProxyCall() (src/legacy/L1ChugSplashProxy.sol#175-198) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "function", - "name": "_doProxyCall", - "start": 8349, - "length": 1099, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "648de83c485a902ab3df50445e187c6390720ae77705d14edbcc112e4fd8fe1a", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) calls L1ChugSplashProxy._doProxyCall() (src/legacy/L1ChugSplashProxy.sol#175-198) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "node", - "name": "return(uint256,uint256)(0x0,returndatasize()())", - "start": 9403, - "length": 29, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "6cf6408cd8c7aedc182552abc25970ede8e033409292304b75b62006b0ad9491", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.delay() (src/L1/DelayedVetoable.sol#114-116) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "delay", - "start": 4595, - "length": 96, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "6cf6408cd8c7aedc182552abc25970ede8e033409292304b75b62006b0ad9491", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.delay() (src/L1/DelayedVetoable.sol#114-116) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "function", - "name": "readOrHandle", - "start": 2953, - "length": 200, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "6cf6408cd8c7aedc182552abc25970ede8e033409292304b75b62006b0ad9491", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "DelayedVetoable.delay() (src/L1/DelayedVetoable.sol#114-116) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#67-74) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#190)\n", - "type": "node", - "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", - "start": 7723, - "length": 48, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "98821b545d4849522091839fbd87144e6fcc256a73b9dd1817676bd127be6d8c", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.getOwner() (src/legacy/L1ChugSplashProxy.sol#145-147) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "function", - "name": "getOwner", - "start": 7200, - "length": 102, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "98821b545d4849522091839fbd87144e6fcc256a73b9dd1817676bd127be6d8c", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.getOwner() (src/legacy/L1ChugSplashProxy.sol#145-147) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "function", - "name": "proxyCallIfNotOwner", - "start": 3867, - "length": 237, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "98821b545d4849522091839fbd87144e6fcc256a73b9dd1817676bd127be6d8c", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.getOwner() (src/legacy/L1ChugSplashProxy.sol#145-147) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "node", - "name": "return(uint256,uint256)(0x0,returndatasize()())", - "start": 9403, - "length": 29, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "c116aac23f49ec7d5d6574972abfbf02d56d0521ea2285dc09d239a829e7d2af", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.setStorage(bytes32,bytes32) (src/legacy/L1ChugSplashProxy.sol#130-134) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "function", - "name": "setStorage", - "start": 6596, - "length": 148, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "c116aac23f49ec7d5d6574972abfbf02d56d0521ea2285dc09d239a829e7d2af", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.setStorage(bytes32,bytes32) (src/legacy/L1ChugSplashProxy.sol#130-134) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "function", - "name": "proxyCallIfNotOwner", - "start": 3867, - "length": 237, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "c116aac23f49ec7d5d6574972abfbf02d56d0521ea2285dc09d239a829e7d2af", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "L1ChugSplashProxy.setStorage(bytes32,bytes32) (src/legacy/L1ChugSplashProxy.sol#130-134) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", - "type": "node", - "name": "return(uint256,uint256)(0x0,returndatasize()())", - "start": 9403, - "length": 29, - "filename_relative": "src/legacy/L1ChugSplashProxy.sol" - }, - { - "id": "d14996b9cc4486d4926155fb1f3d0c1ffc8be9b4af43a61074039356721c7e45", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) calls Proxy._doProxyCall() (src/universal/Proxy.sol#123-145) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "function", - "name": "proxyCallIfNotAdmin", - "start": 1295, - "length": 237, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "d14996b9cc4486d4926155fb1f3d0c1ffc8be9b4af43a61074039356721c7e45", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) calls Proxy._doProxyCall() (src/universal/Proxy.sol#123-145) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "function", - "name": "_doProxyCall", - "start": 4928, - "length": 1039, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "d14996b9cc4486d4926155fb1f3d0c1ffc8be9b4af43a61074039356721c7e45", - "impact": "High", - "confidence": "Medium", - "check": "incorrect-return", - "description": "Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) calls Proxy._doProxyCall() (src/universal/Proxy.sol#123-145) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", - "type": "node", - "name": "return(uint256,uint256)(0x0,returndatasize()())", - "start": 5922, - "length": 29, - "filename_relative": "src/universal/Proxy.sol" - }, - { - "id": "fa673f7f315b9ee7fea38da72b4b0b0eb94babc8d0938536b00ce803ecc07fa2", - "impact": "High", - "confidence": "High", - "check": "uninitialized-state", - "description": "L1Block.blobBaseFee (src/L2/L1Block.sol#50) is never initialized. It is used in:\n\t- L1Block.setL1BlockValuesEcotone() (src/L2/L1Block.sol#101-118)\n", - "type": "variable", - "name": "blobBaseFee", - "start": 1899, - "length": 26, - "filename_relative": "src/L2/L1Block.sol" - }, - { - "id": "fa673f7f315b9ee7fea38da72b4b0b0eb94babc8d0938536b00ce803ecc07fa2", - "impact": "High", - "confidence": "High", - "check": "uninitialized-state", - "description": "L1Block.blobBaseFee (src/L2/L1Block.sol#50) is never initialized. It is used in:\n\t- L1Block.setL1BlockValuesEcotone() (src/L2/L1Block.sol#101-118)\n", - "type": "function", - "name": "setL1BlockValuesEcotone", - "start": 3886, - "length": 956, - "filename_relative": "src/L2/L1Block.sol" - }, - { - "id": "89460308ae3bd86a612657eb7bfe28221ced6a7a7fe723ec2a19149bfc819cb5", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract L2OutputOracle (src/L1/L2OutputOracle.sol#14-317) has payable functions:\n\t - L2OutputOracle.proposeL2Output(bytes32,uint256,bytes32,uint256) (src/L1/L2OutputOracle.sol#189-236)\n\tBut does not have a function to withdraw the ether\n", - "type": "contract", - "name": "L2OutputOracle", - "start": 611, - "length": 13467, - "filename_relative": "src/L1/L2OutputOracle.sol" - }, - { - "id": "89460308ae3bd86a612657eb7bfe28221ced6a7a7fe723ec2a19149bfc819cb5", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract L2OutputOracle (src/L1/L2OutputOracle.sol#14-317) has payable functions:\n\t - L2OutputOracle.proposeL2Output(bytes32,uint256,bytes32,uint256) (src/L1/L2OutputOracle.sol#189-236)\n\tBut does not have a function to withdraw the ether\n", - "type": "function", - "name": "proposeL2Output", - "start": 8300, - "length": 1981, - "filename_relative": "src/L1/L2OutputOracle.sol" - }, - { - "id": "c0920fe4b6b04a2b81f69b85402d465719d06978441052f49a6582415934a1bf", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract L1BlockNumber (src/legacy/L1BlockNumber.sol#16-45) has payable functions:\n\t - L1BlockNumber.receive() (src/legacy/L1BlockNumber.sol#22-28)\n\t - L1BlockNumber.fallback() (src/legacy/L1BlockNumber.sol#32-38)\n\tBut does not have a function to withdraw the ether\n", - "type": "contract", - "name": "L1BlockNumber", - "start": 668, - "length": 888, - "filename_relative": "src/legacy/L1BlockNumber.sol" - }, - { - "id": "c0920fe4b6b04a2b81f69b85402d465719d06978441052f49a6582415934a1bf", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract L1BlockNumber (src/legacy/L1BlockNumber.sol#16-45) has payable functions:\n\t - L1BlockNumber.receive() (src/legacy/L1BlockNumber.sol#22-28)\n\t - L1BlockNumber.fallback() (src/legacy/L1BlockNumber.sol#32-38)\n\tBut does not have a function to withdraw the ether\n", - "type": "function", - "name": "receive", - "start": 863, - "length": 178, - "filename_relative": "src/legacy/L1BlockNumber.sol" - }, - { - "id": "c0920fe4b6b04a2b81f69b85402d465719d06978441052f49a6582415934a1bf", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract L1BlockNumber (src/legacy/L1BlockNumber.sol#16-45) has payable functions:\n\t - L1BlockNumber.receive() (src/legacy/L1BlockNumber.sol#22-28)\n\t - L1BlockNumber.fallback() (src/legacy/L1BlockNumber.sol#32-38)\n\tBut does not have a function to withdraw the ether\n", - "type": "function", - "name": "fallback", - "start": 1145, - "length": 179, - "filename_relative": "src/legacy/L1BlockNumber.sol" - }, - { - "id": "3e52f3459d6607e6494e893c33e98bfaee52639c20f8e8366a39b97d30efeb9d", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract SchemaResolver (src/EAS/resolver/SchemaResolver.sol#11-165) has payable functions:\n\t - ISchemaResolver.attest(Attestation) (src/EAS/resolver/ISchemaResolver.sol#16)\n\t - ISchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#22-28)\n\t - ISchemaResolver.revoke(Attestation) (src/EAS/resolver/ISchemaResolver.sol#33)\n\t - ISchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#39-45)\n\t - SchemaResolver.receive() (src/EAS/resolver/SchemaResolver.sol#41-45)\n\t - SchemaResolver.attest(Attestation) (src/EAS/resolver/SchemaResolver.sol#48-50)\n\t - SchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#53-92)\n\t - SchemaResolver.revoke(Attestation) (src/EAS/resolver/SchemaResolver.sol#95-97)\n\t - SchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#100-139)\n\tBut does not have a function to withdraw the ether\n", - "type": "contract", - "name": "SchemaResolver", - "start": 350, - "length": 5868, - "filename_relative": "src/EAS/resolver/SchemaResolver.sol" - }, - { - "id": "3e52f3459d6607e6494e893c33e98bfaee52639c20f8e8366a39b97d30efeb9d", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract SchemaResolver (src/EAS/resolver/SchemaResolver.sol#11-165) has payable functions:\n\t - ISchemaResolver.attest(Attestation) (src/EAS/resolver/ISchemaResolver.sol#16)\n\t - ISchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#22-28)\n\t - ISchemaResolver.revoke(Attestation) (src/EAS/resolver/ISchemaResolver.sol#33)\n\t - ISchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#39-45)\n\t - SchemaResolver.receive() (src/EAS/resolver/SchemaResolver.sol#41-45)\n\t - SchemaResolver.attest(Attestation) (src/EAS/resolver/SchemaResolver.sol#48-50)\n\t - SchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#53-92)\n\t - SchemaResolver.revoke(Attestation) (src/EAS/resolver/SchemaResolver.sol#95-97)\n\t - SchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#100-139)\n\tBut does not have a function to withdraw the ether\n", - "type": "function", - "name": "attest", - "start": 565, - "length": 82, - "filename_relative": "src/EAS/resolver/ISchemaResolver.sol" - }, - { - "id": "3e52f3459d6607e6494e893c33e98bfaee52639c20f8e8366a39b97d30efeb9d", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract SchemaResolver (src/EAS/resolver/SchemaResolver.sol#11-165) has payable functions:\n\t - ISchemaResolver.attest(Attestation) (src/EAS/resolver/ISchemaResolver.sol#16)\n\t - ISchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#22-28)\n\t - ISchemaResolver.revoke(Attestation) (src/EAS/resolver/ISchemaResolver.sol#33)\n\t - ISchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#39-45)\n\t - SchemaResolver.receive() (src/EAS/resolver/SchemaResolver.sol#41-45)\n\t - SchemaResolver.attest(Attestation) (src/EAS/resolver/SchemaResolver.sol#48-50)\n\t - SchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#53-92)\n\t - SchemaResolver.revoke(Attestation) (src/EAS/resolver/SchemaResolver.sol#95-97)\n\t - SchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#100-139)\n\tBut does not have a function to withdraw the ether\n", - "type": "function", - "name": "multiAttest", - "start": 926, - "length": 163, - "filename_relative": "src/EAS/resolver/ISchemaResolver.sol" - }, - { - "id": "3e52f3459d6607e6494e893c33e98bfaee52639c20f8e8366a39b97d30efeb9d", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract SchemaResolver (src/EAS/resolver/SchemaResolver.sol#11-165) has payable functions:\n\t - ISchemaResolver.attest(Attestation) (src/EAS/resolver/ISchemaResolver.sol#16)\n\t - ISchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#22-28)\n\t - ISchemaResolver.revoke(Attestation) (src/EAS/resolver/ISchemaResolver.sol#33)\n\t - ISchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#39-45)\n\t - SchemaResolver.receive() (src/EAS/resolver/SchemaResolver.sol#41-45)\n\t - SchemaResolver.attest(Attestation) (src/EAS/resolver/SchemaResolver.sol#48-50)\n\t - SchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#53-92)\n\t - SchemaResolver.revoke(Attestation) (src/EAS/resolver/SchemaResolver.sol#95-97)\n\t - SchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#100-139)\n\tBut does not have a function to withdraw the ether\n", - "type": "function", - "name": "revoke", - "start": 1305, - "length": 82, - "filename_relative": "src/EAS/resolver/ISchemaResolver.sol" - }, - { - "id": "3e52f3459d6607e6494e893c33e98bfaee52639c20f8e8366a39b97d30efeb9d", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract SchemaResolver (src/EAS/resolver/SchemaResolver.sol#11-165) has payable functions:\n\t - ISchemaResolver.attest(Attestation) (src/EAS/resolver/ISchemaResolver.sol#16)\n\t - ISchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#22-28)\n\t - ISchemaResolver.revoke(Attestation) (src/EAS/resolver/ISchemaResolver.sol#33)\n\t - ISchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#39-45)\n\t - SchemaResolver.receive() (src/EAS/resolver/SchemaResolver.sol#41-45)\n\t - SchemaResolver.attest(Attestation) (src/EAS/resolver/SchemaResolver.sol#48-50)\n\t - SchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#53-92)\n\t - SchemaResolver.revoke(Attestation) (src/EAS/resolver/SchemaResolver.sol#95-97)\n\t - SchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#100-139)\n\tBut does not have a function to withdraw the ether\n", - "type": "function", - "name": "multiRevoke", - "start": 1695, - "length": 163, - "filename_relative": "src/EAS/resolver/ISchemaResolver.sol" - }, - { - "id": "3e52f3459d6607e6494e893c33e98bfaee52639c20f8e8366a39b97d30efeb9d", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract SchemaResolver (src/EAS/resolver/SchemaResolver.sol#11-165) has payable functions:\n\t - ISchemaResolver.attest(Attestation) (src/EAS/resolver/ISchemaResolver.sol#16)\n\t - ISchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#22-28)\n\t - ISchemaResolver.revoke(Attestation) (src/EAS/resolver/ISchemaResolver.sol#33)\n\t - ISchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#39-45)\n\t - SchemaResolver.receive() (src/EAS/resolver/SchemaResolver.sol#41-45)\n\t - SchemaResolver.attest(Attestation) (src/EAS/resolver/SchemaResolver.sol#48-50)\n\t - SchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#53-92)\n\t - SchemaResolver.revoke(Attestation) (src/EAS/resolver/SchemaResolver.sol#95-97)\n\t - SchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#100-139)\n\tBut does not have a function to withdraw the ether\n", - "type": "function", - "name": "receive", - "start": 1054, - "length": 113, - "filename_relative": "src/EAS/resolver/SchemaResolver.sol" - }, - { - "id": "3e52f3459d6607e6494e893c33e98bfaee52639c20f8e8366a39b97d30efeb9d", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract SchemaResolver (src/EAS/resolver/SchemaResolver.sol#11-165) has payable functions:\n\t - ISchemaResolver.attest(Attestation) (src/EAS/resolver/ISchemaResolver.sol#16)\n\t - ISchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#22-28)\n\t - ISchemaResolver.revoke(Attestation) (src/EAS/resolver/ISchemaResolver.sol#33)\n\t - ISchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#39-45)\n\t - SchemaResolver.receive() (src/EAS/resolver/SchemaResolver.sol#41-45)\n\t - SchemaResolver.attest(Attestation) (src/EAS/resolver/SchemaResolver.sol#48-50)\n\t - SchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#53-92)\n\t - SchemaResolver.revoke(Attestation) (src/EAS/resolver/SchemaResolver.sol#95-97)\n\t - SchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#100-139)\n\tBut does not have a function to withdraw the ether\n", - "type": "function", - "name": "attest", - "start": 1209, - "length": 146, - "filename_relative": "src/EAS/resolver/SchemaResolver.sol" - }, - { - "id": "3e52f3459d6607e6494e893c33e98bfaee52639c20f8e8366a39b97d30efeb9d", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract SchemaResolver (src/EAS/resolver/SchemaResolver.sol#11-165) has payable functions:\n\t - ISchemaResolver.attest(Attestation) (src/EAS/resolver/ISchemaResolver.sol#16)\n\t - ISchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#22-28)\n\t - ISchemaResolver.revoke(Attestation) (src/EAS/resolver/ISchemaResolver.sol#33)\n\t - ISchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#39-45)\n\t - SchemaResolver.receive() (src/EAS/resolver/SchemaResolver.sol#41-45)\n\t - SchemaResolver.attest(Attestation) (src/EAS/resolver/SchemaResolver.sol#48-50)\n\t - SchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#53-92)\n\t - SchemaResolver.revoke(Attestation) (src/EAS/resolver/SchemaResolver.sol#95-97)\n\t - SchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#100-139)\n\tBut does not have a function to withdraw the ether\n", - "type": "function", - "name": "multiAttest", - "start": 1397, - "length": 1497, - "filename_relative": "src/EAS/resolver/SchemaResolver.sol" - }, - { - "id": "3e52f3459d6607e6494e893c33e98bfaee52639c20f8e8366a39b97d30efeb9d", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract SchemaResolver (src/EAS/resolver/SchemaResolver.sol#11-165) has payable functions:\n\t - ISchemaResolver.attest(Attestation) (src/EAS/resolver/ISchemaResolver.sol#16)\n\t - ISchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#22-28)\n\t - ISchemaResolver.revoke(Attestation) (src/EAS/resolver/ISchemaResolver.sol#33)\n\t - ISchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#39-45)\n\t - SchemaResolver.receive() (src/EAS/resolver/SchemaResolver.sol#41-45)\n\t - SchemaResolver.attest(Attestation) (src/EAS/resolver/SchemaResolver.sol#48-50)\n\t - SchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#53-92)\n\t - SchemaResolver.revoke(Attestation) (src/EAS/resolver/SchemaResolver.sol#95-97)\n\t - SchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#100-139)\n\tBut does not have a function to withdraw the ether\n", - "type": "function", - "name": "revoke", - "start": 2936, - "length": 146, - "filename_relative": "src/EAS/resolver/SchemaResolver.sol" - }, - { - "id": "3e52f3459d6607e6494e893c33e98bfaee52639c20f8e8366a39b97d30efeb9d", - "impact": "Medium", - "confidence": "High", - "check": "locked-ether", - "description": "Contract locking ether found:\n\tContract SchemaResolver (src/EAS/resolver/SchemaResolver.sol#11-165) has payable functions:\n\t - ISchemaResolver.attest(Attestation) (src/EAS/resolver/ISchemaResolver.sol#16)\n\t - ISchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#22-28)\n\t - ISchemaResolver.revoke(Attestation) (src/EAS/resolver/ISchemaResolver.sol#33)\n\t - ISchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#39-45)\n\t - SchemaResolver.receive() (src/EAS/resolver/SchemaResolver.sol#41-45)\n\t - SchemaResolver.attest(Attestation) (src/EAS/resolver/SchemaResolver.sol#48-50)\n\t - SchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#53-92)\n\t - SchemaResolver.revoke(Attestation) (src/EAS/resolver/SchemaResolver.sol#95-97)\n\t - SchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#100-139)\n\tBut does not have a function to withdraw the ether\n", - "type": "function", - "name": "multiRevoke", - "start": 3124, - "length": 1496, - "filename_relative": "src/EAS/resolver/SchemaResolver.sol" - }, - { - "id": "1349b68c3b08ecdf27782bd74d9fecadf1739eef738171cbbba403c77a29f424", - "impact": "Medium", - "confidence": "Medium", - "check": "reentrancy-no-eth", - "description": "Reentrancy in TransferOnion.peel(TransferOnion.Layer[]) (src/periphery/TransferOnion.sol#44-70):\n\tExternal calls:\n\t- TOKEN.safeTransferFrom(SENDER,layer.recipient,layer.amount) (src/periphery/TransferOnion.sol#61)\n\tState variables written after the call(s):\n\t- shell = tempShell (src/periphery/TransferOnion.sol#69)\n\tTransferOnion.shell (src/periphery/TransferOnion.sol#30) can be used in cross function reentrancies:\n\t- TransferOnion.constructor(ERC20,address,bytes32) (src/periphery/TransferOnion.sol#36-40)\n\t- TransferOnion.shell (src/periphery/TransferOnion.sol#30)\n", - "type": "function", - "name": "peel", - "start": 1616, - "length": 885, - "filename_relative": "src/periphery/TransferOnion.sol" - }, - { - "id": "1349b68c3b08ecdf27782bd74d9fecadf1739eef738171cbbba403c77a29f424", - "impact": "Medium", - "confidence": "Medium", - "check": "reentrancy-no-eth", - "description": "Reentrancy in TransferOnion.peel(TransferOnion.Layer[]) (src/periphery/TransferOnion.sol#44-70):\n\tExternal calls:\n\t- TOKEN.safeTransferFrom(SENDER,layer.recipient,layer.amount) (src/periphery/TransferOnion.sol#61)\n\tState variables written after the call(s):\n\t- shell = tempShell (src/periphery/TransferOnion.sol#69)\n\tTransferOnion.shell (src/periphery/TransferOnion.sol#30) can be used in cross function reentrancies:\n\t- TransferOnion.constructor(ERC20,address,bytes32) (src/periphery/TransferOnion.sol#36-40)\n\t- TransferOnion.shell (src/periphery/TransferOnion.sol#30)\n", - "type": "node", - "name": "TOKEN.safeTransferFrom(SENDER,layer.recipient,layer.amount)", - "start": 2282, - "length": 61, - "filename_relative": "src/periphery/TransferOnion.sol" - }, - { - "id": "1349b68c3b08ecdf27782bd74d9fecadf1739eef738171cbbba403c77a29f424", - "impact": "Medium", - "confidence": "Medium", - "check": "reentrancy-no-eth", - "description": "Reentrancy in TransferOnion.peel(TransferOnion.Layer[]) (src/periphery/TransferOnion.sol#44-70):\n\tExternal calls:\n\t- TOKEN.safeTransferFrom(SENDER,layer.recipient,layer.amount) (src/periphery/TransferOnion.sol#61)\n\tState variables written after the call(s):\n\t- shell = tempShell (src/periphery/TransferOnion.sol#69)\n\tTransferOnion.shell (src/periphery/TransferOnion.sol#30) can be used in cross function reentrancies:\n\t- TransferOnion.constructor(ERC20,address,bytes32) (src/periphery/TransferOnion.sol#36-40)\n\t- TransferOnion.shell (src/periphery/TransferOnion.sol#30)\n", - "type": "node", - "name": "shell = tempShell", - "start": 2477, - "length": 17, - "filename_relative": "src/periphery/TransferOnion.sol" - }, - { - "id": "14134bc23d372275d187f91848cac770b21d8451fa7b979380dc2ac94588945b", - "impact": "Medium", - "confidence": "Medium", - "check": "reentrancy-no-eth", - "description": "Reentrancy in DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181):\n\tExternal calls:\n\t- _forwardAndHalt(callHash) (src/L1/DelayedVetoable.sol#150)\n\t\t- (success,returndata) = TARGET.call(msg.data) (src/L1/DelayedVetoable.sol#187)\n\tState variables written after the call(s):\n\t- _queuedAt[callHash] = block.timestamp (src/L1/DelayedVetoable.sol#152)\n\tDelayedVetoable._queuedAt (src/L1/DelayedVetoable.sol#61) can be used in cross function reentrancies:\n\t- DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181)\n\t- DelayedVetoable.queuedAt(bytes32) (src/L1/DelayedVetoable.sol#121-123)\n", - "type": "function", - "name": "_handleCall", - "start": 5365, - "length": 2009, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "14134bc23d372275d187f91848cac770b21d8451fa7b979380dc2ac94588945b", - "impact": "Medium", - "confidence": "Medium", - "check": "reentrancy-no-eth", - "description": "Reentrancy in DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181):\n\tExternal calls:\n\t- _forwardAndHalt(callHash) (src/L1/DelayedVetoable.sol#150)\n\t\t- (success,returndata) = TARGET.call(msg.data) (src/L1/DelayedVetoable.sol#187)\n\tState variables written after the call(s):\n\t- _queuedAt[callHash] = block.timestamp (src/L1/DelayedVetoable.sol#152)\n\tDelayedVetoable._queuedAt (src/L1/DelayedVetoable.sol#61) can be used in cross function reentrancies:\n\t- DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181)\n\t- DelayedVetoable.queuedAt(bytes32) (src/L1/DelayedVetoable.sol#121-123)\n", - "type": "node", - "name": "_forwardAndHalt(callHash)", - "start": 6102, - "length": 25, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "14134bc23d372275d187f91848cac770b21d8451fa7b979380dc2ac94588945b", - "impact": "Medium", - "confidence": "Medium", - "check": "reentrancy-no-eth", - "description": "Reentrancy in DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181):\n\tExternal calls:\n\t- _forwardAndHalt(callHash) (src/L1/DelayedVetoable.sol#150)\n\t\t- (success,returndata) = TARGET.call(msg.data) (src/L1/DelayedVetoable.sol#187)\n\tState variables written after the call(s):\n\t- _queuedAt[callHash] = block.timestamp (src/L1/DelayedVetoable.sol#152)\n\tDelayedVetoable._queuedAt (src/L1/DelayedVetoable.sol#61) can be used in cross function reentrancies:\n\t- DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181)\n\t- DelayedVetoable.queuedAt(bytes32) (src/L1/DelayedVetoable.sol#121-123)\n", - "type": "node", - "name": "(success,returndata) = TARGET.call(msg.data)", - "start": 7588, - "length": 63, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "14134bc23d372275d187f91848cac770b21d8451fa7b979380dc2ac94588945b", - "impact": "Medium", - "confidence": "Medium", - "check": "reentrancy-no-eth", - "description": "Reentrancy in DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181):\n\tExternal calls:\n\t- _forwardAndHalt(callHash) (src/L1/DelayedVetoable.sol#150)\n\t\t- (success,returndata) = TARGET.call(msg.data) (src/L1/DelayedVetoable.sol#187)\n\tState variables written after the call(s):\n\t- _queuedAt[callHash] = block.timestamp (src/L1/DelayedVetoable.sol#152)\n\tDelayedVetoable._queuedAt (src/L1/DelayedVetoable.sol#61) can be used in cross function reentrancies:\n\t- DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#133-181)\n\t- DelayedVetoable.queuedAt(bytes32) (src/L1/DelayedVetoable.sol#121-123)\n", - "type": "node", - "name": "_queuedAt[callHash] = block.timestamp", - "start": 6155, - "length": 37, - "filename_relative": "src/L1/DelayedVetoable.sol" - }, - { - "id": "a31cc22ac44058d56b0a89d6a2ab1dbe6791d75f6d06397eebf72a6d932e82c2", - "impact": "Medium", - "confidence": "Medium", - "check": "reentrancy-no-eth", - "description": "Reentrancy in FaultDisputeGame.step(uint256,bool,bytes,bytes) (src/dispute/FaultDisputeGame.sol#124-191):\n\tExternal calls:\n\t- validStep = VM.step(_stateData,_proof,uuid.raw()) == postState.claim.raw() (src/dispute/FaultDisputeGame.sol#184)\n\tState variables written after the call(s):\n\t- parent.counteredBy = msg.sender (src/dispute/FaultDisputeGame.sol#190)\n\tFaultDisputeGame.claimData (src/dispute/FaultDisputeGame.sol#66) can be used in cross function reentrancies:\n\t- FaultDisputeGame._findStartingAndDisputedOutputs(uint256) (src/dispute/FaultDisputeGame.sol#662-721)\n\t- FaultDisputeGame._findTraceAncestor(Position,uint256,bool) (src/dispute/FaultDisputeGame.sol#635-653)\n\t- FaultDisputeGame.claimData (src/dispute/FaultDisputeGame.sol#66)\n\t- FaultDisputeGame.claimDataLen() (src/dispute/FaultDisputeGame.sol#510-512)\n\t- FaultDisputeGame.initialize() (src/dispute/FaultDisputeGame.sol#454-507)\n\t- FaultDisputeGame.move(uint256,Claim,bool) (src/dispute/FaultDisputeGame.sol#197-288)\n\t- FaultDisputeGame.resolve() (src/dispute/FaultDisputeGame.sol#353-365)\n\t- FaultDisputeGame.resolveClaim(uint256) (src/dispute/FaultDisputeGame.sol#368-428)\n\t- FaultDisputeGame.step(uint256,bool,bytes,bytes) (src/dispute/FaultDisputeGame.sol#124-191)\n", - "type": "function", - "name": "step", - "start": 4981, - "length": 4228, - "filename_relative": "src/dispute/FaultDisputeGame.sol" - }, - { - "id": "a31cc22ac44058d56b0a89d6a2ab1dbe6791d75f6d06397eebf72a6d932e82c2", - "impact": "Medium", - "confidence": "Medium", - "check": "reentrancy-no-eth", - "description": "Reentrancy in FaultDisputeGame.step(uint256,bool,bytes,bytes) (src/dispute/FaultDisputeGame.sol#124-191):\n\tExternal calls:\n\t- validStep = VM.step(_stateData,_proof,uuid.raw()) == postState.claim.raw() (src/dispute/FaultDisputeGame.sol#184)\n\tState variables written after the call(s):\n\t- parent.counteredBy = msg.sender (src/dispute/FaultDisputeGame.sol#190)\n\tFaultDisputeGame.claimData (src/dispute/FaultDisputeGame.sol#66) can be used in cross function reentrancies:\n\t- FaultDisputeGame._findStartingAndDisputedOutputs(uint256) (src/dispute/FaultDisputeGame.sol#662-721)\n\t- FaultDisputeGame._findTraceAncestor(Position,uint256,bool) (src/dispute/FaultDisputeGame.sol#635-653)\n\t- FaultDisputeGame.claimData (src/dispute/FaultDisputeGame.sol#66)\n\t- FaultDisputeGame.claimDataLen() (src/dispute/FaultDisputeGame.sol#510-512)\n\t- FaultDisputeGame.initialize() (src/dispute/FaultDisputeGame.sol#454-507)\n\t- FaultDisputeGame.move(uint256,Claim,bool) (src/dispute/FaultDisputeGame.sol#197-288)\n\t- FaultDisputeGame.resolve() (src/dispute/FaultDisputeGame.sol#353-365)\n\t- FaultDisputeGame.resolveClaim(uint256) (src/dispute/FaultDisputeGame.sol#368-428)\n\t- FaultDisputeGame.step(uint256,bool,bytes,bytes) (src/dispute/FaultDisputeGame.sol#124-191)\n", - "type": "node", - "name": "validStep = VM.step(_stateData,_proof,uuid.raw()) == postState.claim.raw()", - "start": 8761, - "length": 81, - "filename_relative": "src/dispute/FaultDisputeGame.sol" - }, - { - "id": "a31cc22ac44058d56b0a89d6a2ab1dbe6791d75f6d06397eebf72a6d932e82c2", - "impact": "Medium", - "confidence": "Medium", - "check": "reentrancy-no-eth", - "description": "Reentrancy in FaultDisputeGame.step(uint256,bool,bytes,bytes) (src/dispute/FaultDisputeGame.sol#124-191):\n\tExternal calls:\n\t- validStep = VM.step(_stateData,_proof,uuid.raw()) == postState.claim.raw() (src/dispute/FaultDisputeGame.sol#184)\n\tState variables written after the call(s):\n\t- parent.counteredBy = msg.sender (src/dispute/FaultDisputeGame.sol#190)\n\tFaultDisputeGame.claimData (src/dispute/FaultDisputeGame.sol#66) can be used in cross function reentrancies:\n\t- FaultDisputeGame._findStartingAndDisputedOutputs(uint256) (src/dispute/FaultDisputeGame.sol#662-721)\n\t- FaultDisputeGame._findTraceAncestor(Position,uint256,bool) (src/dispute/FaultDisputeGame.sol#635-653)\n\t- FaultDisputeGame.claimData (src/dispute/FaultDisputeGame.sol#66)\n\t- FaultDisputeGame.claimDataLen() (src/dispute/FaultDisputeGame.sol#510-512)\n\t- FaultDisputeGame.initialize() (src/dispute/FaultDisputeGame.sol#454-507)\n\t- FaultDisputeGame.move(uint256,Claim,bool) (src/dispute/FaultDisputeGame.sol#197-288)\n\t- FaultDisputeGame.resolve() (src/dispute/FaultDisputeGame.sol#353-365)\n\t- FaultDisputeGame.resolveClaim(uint256) (src/dispute/FaultDisputeGame.sol#368-428)\n\t- FaultDisputeGame.step(uint256,bool,bytes,bytes) (src/dispute/FaultDisputeGame.sol#124-191)\n", - "type": "node", - "name": "parent.counteredBy = msg.sender", - "start": 9171, - "length": 31, - "filename_relative": "src/dispute/FaultDisputeGame.sol" - }, - { - "id": "3702aae0a8031af92233fa312a75b60518153a9f80ad2e6157debb825eec5ba1", - "impact": "Medium", - "confidence": "Medium", - "check": "tx-origin", - "description": "CrossDomainMessenger.relayMessage(uint256,address,address,uint256,uint256,bytes) (src/universal/CrossDomainMessenger.sol#207-305) uses tx.origin for authorization: tx.origin == Constants.ESTIMATION_ADDRESS (src/universal/CrossDomainMessenger.sol#301)\n", - "type": "function", - "name": "relayMessage", - "start": 10315, - "length": 5066, - "filename_relative": "src/universal/CrossDomainMessenger.sol" - }, - { - "id": "3702aae0a8031af92233fa312a75b60518153a9f80ad2e6157debb825eec5ba1", - "impact": "Medium", - "confidence": "Medium", - "check": "tx-origin", - "description": "CrossDomainMessenger.relayMessage(uint256,address,address,uint256,uint256,bytes) (src/universal/CrossDomainMessenger.sol#207-305) uses tx.origin for authorization: tx.origin == Constants.ESTIMATION_ADDRESS (src/universal/CrossDomainMessenger.sol#301)\n", - "type": "node", - "name": "tx.origin == Constants.ESTIMATION_ADDRESS", - "start": 15234, - "length": 41, - "filename_relative": "src/universal/CrossDomainMessenger.sol" - }, - { - "id": "b507540468fdf3f9972d33e723efb8c120f8d824ffe54842e1e998244944abaf", - "impact": "Medium", - "confidence": "Medium", - "check": "tx-origin", - "description": "OptimismPortal.finalizeWithdrawalTransaction(Types.WithdrawalTransaction) (src/L1/OptimismPortal.sol#280-363) uses tx.origin for authorization: success == false && tx.origin == Constants.ESTIMATION_ADDRESS (src/L1/OptimismPortal.sol#360)\n", - "type": "function", - "name": "finalizeWithdrawalTransaction", - "start": 13252, - "length": 4839, - "filename_relative": "src/L1/OptimismPortal.sol" - }, - { - "id": "b507540468fdf3f9972d33e723efb8c120f8d824ffe54842e1e998244944abaf", - "impact": "Medium", - "confidence": "Medium", - "check": "tx-origin", - "description": "OptimismPortal.finalizeWithdrawalTransaction(Types.WithdrawalTransaction) (src/L1/OptimismPortal.sol#280-363) uses tx.origin for authorization: success == false && tx.origin == Constants.ESTIMATION_ADDRESS (src/L1/OptimismPortal.sol#360)\n", - "type": "node", - "name": "success == false && tx.origin == Constants.ESTIMATION_ADDRESS", - "start": 17954, - "length": 61, - "filename_relative": "src/L1/OptimismPortal.sol" - }, - { - "id": "baf2bfa9777021d9e36870b76a1020c950de67bbf00d486f604cc72d36c47839", - "impact": "Medium", - "confidence": "Medium", - "check": "tx-origin", - "description": "CrossDomainMessenger.relayMessage(uint256,address,address,uint256,uint256,bytes) (src/universal/CrossDomainMessenger.sol#207-305) uses tx.origin for authorization: tx.origin == Constants.ESTIMATION_ADDRESS (src/universal/CrossDomainMessenger.sol#275)\n", - "type": "function", - "name": "relayMessage", - "start": 10315, - "length": 5066, - "filename_relative": "src/universal/CrossDomainMessenger.sol" - }, - { - "id": "baf2bfa9777021d9e36870b76a1020c950de67bbf00d486f604cc72d36c47839", - "impact": "Medium", - "confidence": "Medium", - "check": "tx-origin", - "description": "CrossDomainMessenger.relayMessage(uint256,address,address,uint256,uint256,bytes) (src/universal/CrossDomainMessenger.sol#207-305) uses tx.origin for authorization: tx.origin == Constants.ESTIMATION_ADDRESS (src/universal/CrossDomainMessenger.sol#275)\n", - "type": "node", - "name": "tx.origin == Constants.ESTIMATION_ADDRESS", - "start": 13912, - "length": 41, - "filename_relative": "src/universal/CrossDomainMessenger.sol" - }, - { - "id": "0369380fef18a61639eac6a12773df792e9969e7bb20eddde54ccf3a263a0987", - "impact": "Medium", - "confidence": "Medium", - "check": "uninitialized-local", - "description": "FaultDisputeGame.move(uint256,Claim,bool).grandparentClock (src/dispute/FaultDisputeGame.sol#235) is a local variable never initialized\n", - "type": "variable", - "name": "grandparentClock", - "start": 11863, - "length": 22, - "filename_relative": "src/dispute/FaultDisputeGame.sol" - }, - { - "id": "037c6a008887de2859c40f66cb99806d2e25ea8d4b0658d3fdc448e77c20439b", - "impact": "Medium", - "confidence": "Medium", - "check": "uninitialized-local", - "description": "PreimageOracle.challengeFirstLPP(address,uint256,PreimageOracle.Leaf,bytes32[]).stateMatrix (src/cannon/PreimageOracle.sol#444) is a local variable never initialized\n", - "type": "variable", - "name": "stateMatrix", - "start": 20524, - "length": 40, - "filename_relative": "src/cannon/PreimageOracle.sol" - }, - { - "id": "8c229f5475784b2e9526e30d55b066e479489bca4b07c4f062b42b5b70100794", - "impact": "Medium", - "confidence": "Medium", - "check": "uninitialized-local", - "description": "FaultDisputeGame._findStartingAndDisputedOutputs(uint256).currentDepth (src/dispute/FaultDisputeGame.sol#680) is a local variable never initialized\n", - "type": "variable", - "name": "currentDepth", - "start": 32115, - "length": 20, - "filename_relative": "src/dispute/FaultDisputeGame.sol" - }, - { - "id": "858b95108475bbb08343b6f5701b03c0762d00b73cec53751173e93c3ec10c1a", - "impact": "Medium", - "confidence": "High", - "check": "write-after-write", - "description": "CrossDomainMessenger.xDomainMsgSender (src/universal/CrossDomainMessenger.sol#126) is written in both\n\txDomainMsgSender = _sender (src/universal/CrossDomainMessenger.sol#282)\n\txDomainMsgSender = Constants.DEFAULT_L2_SENDER (src/universal/CrossDomainMessenger.sol#284)\n", - "type": "variable", - "name": "xDomainMsgSender", - "start": 5649, - "length": 33, - "filename_relative": "src/universal/CrossDomainMessenger.sol" - }, - { - "id": "858b95108475bbb08343b6f5701b03c0762d00b73cec53751173e93c3ec10c1a", - "impact": "Medium", - "confidence": "High", - "check": "write-after-write", - "description": "CrossDomainMessenger.xDomainMsgSender (src/universal/CrossDomainMessenger.sol#126) is written in both\n\txDomainMsgSender = _sender (src/universal/CrossDomainMessenger.sol#282)\n\txDomainMsgSender = Constants.DEFAULT_L2_SENDER (src/universal/CrossDomainMessenger.sol#284)\n", - "type": "node", - "name": "xDomainMsgSender = _sender", - "start": 14084, - "length": 26, - "filename_relative": "src/universal/CrossDomainMessenger.sol" - }, - { - "id": "858b95108475bbb08343b6f5701b03c0762d00b73cec53751173e93c3ec10c1a", - "impact": "Medium", - "confidence": "High", - "check": "write-after-write", - "description": "CrossDomainMessenger.xDomainMsgSender (src/universal/CrossDomainMessenger.sol#126) is written in both\n\txDomainMsgSender = _sender (src/universal/CrossDomainMessenger.sol#282)\n\txDomainMsgSender = Constants.DEFAULT_L2_SENDER (src/universal/CrossDomainMessenger.sol#284)\n", - "type": "node", - "name": "xDomainMsgSender = Constants.DEFAULT_L2_SENDER", - "start": 14217, - "length": 46, - "filename_relative": "src/universal/CrossDomainMessenger.sol" - }, - { - "id": "a43b8cff6d6b33609e8c7e3e89af17a0bc9ec73eb9a1a1b796e69c36ce8bcf71", - "impact": "Medium", - "confidence": "High", - "check": "write-after-write", - "description": "OptimismPortal.l2Sender (src/L1/OptimismPortal.sol#43) is written in both\n\tl2Sender = _tx.sender (src/L1/OptimismPortal.sol#339)\n\tl2Sender = Constants.DEFAULT_L2_SENDER (src/L1/OptimismPortal.sol#351)\n", - "type": "variable", - "name": "l2Sender", - "start": 2193, - "length": 23, - "filename_relative": "src/L1/OptimismPortal.sol" - }, - { - "id": "a43b8cff6d6b33609e8c7e3e89af17a0bc9ec73eb9a1a1b796e69c36ce8bcf71", - "impact": "Medium", - "confidence": "High", - "check": "write-after-write", - "description": "OptimismPortal.l2Sender (src/L1/OptimismPortal.sol#43) is written in both\n\tl2Sender = _tx.sender (src/L1/OptimismPortal.sol#339)\n\tl2Sender = Constants.DEFAULT_L2_SENDER (src/L1/OptimismPortal.sol#351)\n", - "type": "node", - "name": "l2Sender = _tx.sender", - "start": 16655, - "length": 21, - "filename_relative": "src/L1/OptimismPortal.sol" - }, - { - "id": "a43b8cff6d6b33609e8c7e3e89af17a0bc9ec73eb9a1a1b796e69c36ce8bcf71", - "impact": "Medium", - "confidence": "High", - "check": "write-after-write", - "description": "OptimismPortal.l2Sender (src/L1/OptimismPortal.sol#43) is written in both\n\tl2Sender = _tx.sender (src/L1/OptimismPortal.sol#339)\n\tl2Sender = Constants.DEFAULT_L2_SENDER (src/L1/OptimismPortal.sol#351)\n", - "type": "node", - "name": "l2Sender = Constants.DEFAULT_L2_SENDER", - "start": 17449, - "length": 38, - "filename_relative": "src/L1/OptimismPortal.sol" - } -] diff --git a/packages/contracts-bedrock/slither.config.json b/packages/contracts-bedrock/slither.config.json index 8a844be3b828..7b1af2283925 100644 --- a/packages/contracts-bedrock/slither.config.json +++ b/packages/contracts-bedrock/slither.config.json @@ -1,15 +1,10 @@ { - "detectors_to_exclude": "incorrect-shift-in-assembly,assembly,timestamp,solc-version,missing-zero-check,immutable-states,arbitrary-send-eth,too-many-digits,divide-before-multiply,conformance-to-solidity-naming-conventions,low-level-calls,reentrancy-events,cache-array-length,unused-return,cyclomatic-complexity,calls-loop,reentrancy-unlimited-gas,reentrancy-eth,reentrancy-benign,costly-loop,events-maths,incorrect-equality", - "exclude_informational": true, - "exclude_optimization": true, - "exclude_low": true, - "json": "slither-report.json", - "exclude_medium": false, - "exclude_high": false, - "solc_disable_warnings": false, - "disable_color": false, - "exclude_dependencies": true, - "filter_paths": "(lib/|src/vendor|src/cannon/MIPS.sol|src/EAS/EAS.sol)", - "legacy_ast": false, - "foundry_out_directory": "artifacts" + "detectors_to_exclude": "arbitrary-send-eth,incorrect-equality,naming-convention,solc-version", + "exclude_dependencies": true, + "exclude_informational": true, + "exclude_low": true, + "exclude_optimization": true, + "fail_on": "none", + "filter_paths": "(src/vendor|src/cannon/MIPS.sol|src/EAS/EAS.sol)", + "foundry_out_directory": "artifacts" } diff --git a/packages/contracts-bedrock/slither.db.json b/packages/contracts-bedrock/slither.db.json new file mode 100644 index 000000000000..f998749201d8 --- /dev/null +++ b/packages/contracts-bedrock/slither.db.json @@ -0,0 +1 @@ +[{"elements": [{"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 14716, "length": 2329, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353], "starting_column": 13, "ending_column": 52}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480], "starting_column": 1, "ending_column": 11}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}, {"type": "node", "name": "! success && tx.origin == Constants.ESTIMATION_ADDRESS", "source_mapping": {"start": 16916, "length": 53, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [351, 352], "starting_column": 88, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 14716, "length": 2329, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353], "starting_column": 13, "ending_column": 52}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480], "starting_column": 1, "ending_column": 11}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}}}], "description": "OptimismPortal2.finalizeWithdrawalTransaction(Types.WithdrawalTransaction) (src/L1/OptimismPortal2.sol#310-353) uses tx.origin for authorization: ! success && tx.origin == Constants.ESTIMATION_ADDRESS (src/L1/OptimismPortal2.sol#351-352)\n", "markdown": "[OptimismPortal2.finalizeWithdrawalTransaction(Types.WithdrawalTransaction)](src/L1/OptimismPortal2.sol#L310-L353) uses tx.origin for authorization: [! success && tx.origin == Constants.ESTIMATION_ADDRESS](src/L1/OptimismPortal2.sol#L351-L352)\n", "first_markdown_element": "src/L1/OptimismPortal2.sol#L310-L353", "id": "d48d1e372e3b9eedcc9cd7898b5c06c3d9a034fd7b2fe74f33030a43b17ace68", "check": "tx-origin", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 15460, "length": 2329, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 23826, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498], "starting_column": 1, "ending_column": 2}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}, {"type": "node", "name": "! success && tx.origin == Constants.ESTIMATION_ADDRESS", "source_mapping": {"start": 17660, "length": 53, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [365], "starting_column": 13, "ending_column": 66}, "type_specific_fields": {"parent": {"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 15460, "length": 2329, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 23826, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498], "starting_column": 1, "ending_column": 2}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}}}], "description": "OptimismPortal2.finalizeWithdrawalTransaction(Types.WithdrawalTransaction) (src/L1/OptimismPortal2.sol#326-368) uses tx.origin for authorization: ! success && tx.origin == Constants.ESTIMATION_ADDRESS (src/L1/OptimismPortal2.sol#365)\n", "markdown": "[OptimismPortal2.finalizeWithdrawalTransaction(Types.WithdrawalTransaction)](src/L1/OptimismPortal2.sol#L326-L368) uses tx.origin for authorization: [! success && tx.origin == Constants.ESTIMATION_ADDRESS](src/L1/OptimismPortal2.sol#L365)\n", "first_markdown_element": "src/L1/OptimismPortal2.sol#L326-L368", "id": "1ff38a1a3765ac0e84f926b9fc8a4c45324bb734bbf2aab3c9f62e58a99a6859", "check": "tx-origin", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "proveWithdrawalTransaction", "source_mapping": {"start": 10692, "length": 3911, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309], "starting_column": 74, "ending_column": 9}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480], "starting_column": 1, "ending_column": 11}}, "signature": "proveWithdrawalTransaction(Types.WithdrawalTransaction,uint256,Types.OutputRootProof,bytes[])"}}, {"type": "node", "name": "(gameType,gameProxy) = disputeGameFactory.gameAtIndex(_disputeGameIndex)", "source_mapping": {"start": 11391, "length": 96, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [250, 251, 252], "starting_column": 34, "ending_column": 47}, "type_specific_fields": {"parent": {"type": "function", "name": "proveWithdrawalTransaction", "source_mapping": {"start": 10692, "length": 3911, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309], "starting_column": 74, "ending_column": 9}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480], "starting_column": 1, "ending_column": 11}}, "signature": "proveWithdrawalTransaction(Types.WithdrawalTransaction,uint256,Types.OutputRootProof,bytes[])"}}}}], "description": "OptimismPortal2.proveWithdrawalTransaction(Types.WithdrawalTransaction,uint256,Types.OutputRootProof,bytes[]) (src/L1/OptimismPortal2.sol#238-309) ignores return value by (gameType,gameProxy) = disputeGameFactory.gameAtIndex(_disputeGameIndex) (src/L1/OptimismPortal2.sol#250-252)\n", "markdown": "[OptimismPortal2.proveWithdrawalTransaction(Types.WithdrawalTransaction,uint256,Types.OutputRootProof,bytes[])](src/L1/OptimismPortal2.sol#L238-L309) ignores return value by [(gameType,gameProxy) = disputeGameFactory.gameAtIndex(_disputeGameIndex)](src/L1/OptimismPortal2.sol#L250-L252)\n", "first_markdown_element": "src/L1/OptimismPortal2.sol#L238-L309", "id": "988135f1cdbc085e5427f69ba7b5c4ad2b9e4332b9f3e009e1df32e8b056deb1", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "proveWithdrawalTransaction", "source_mapping": {"start": 11321, "length": 4026, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 23826, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498], "starting_column": 1, "ending_column": 2}}, "signature": "proveWithdrawalTransaction(Types.WithdrawalTransaction,uint256,Types.OutputRootProof,bytes[])"}}, {"type": "node", "name": "(gameType,gameProxy) = disputeGameFactory.gameAtIndex(_disputeGameIndex)", "source_mapping": {"start": 12020, "length": 96, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [264], "starting_column": 9, "ending_column": 105}, "type_specific_fields": {"parent": {"type": "function", "name": "proveWithdrawalTransaction", "source_mapping": {"start": 11321, "length": 4026, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 23826, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498], "starting_column": 1, "ending_column": 2}}, "signature": "proveWithdrawalTransaction(Types.WithdrawalTransaction,uint256,Types.OutputRootProof,bytes[])"}}}}], "description": "OptimismPortal2.proveWithdrawalTransaction(Types.WithdrawalTransaction,uint256,Types.OutputRootProof,bytes[]) (src/L1/OptimismPortal2.sol#249-322) ignores return value by (gameType,gameProxy) = disputeGameFactory.gameAtIndex(_disputeGameIndex) (src/L1/OptimismPortal2.sol#264)\n", "markdown": "[OptimismPortal2.proveWithdrawalTransaction(Types.WithdrawalTransaction,uint256,Types.OutputRootProof,bytes[])](src/L1/OptimismPortal2.sol#L249-L322) ignores return value by [(gameType,gameProxy) = disputeGameFactory.gameAtIndex(_disputeGameIndex)](src/L1/OptimismPortal2.sol#L264)\n", "first_markdown_element": "src/L1/OptimismPortal2.sol#L249-L322", "id": "a456300035f2d7bf357556a28b682d2e5e736e7dd889515683935f960874a7b0", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "l2Sender", "source_mapping": {"start": 2796, "length": 23, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [54], "starting_column": 5, "ending_column": 28}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480], "starting_column": 1, "ending_column": 11}}}}, {"type": "node", "name": "l2Sender = _tx.sender", "source_mapping": {"start": 15617, "length": 21, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [327], "starting_column": 54, "ending_column": 75}, "type_specific_fields": {"parent": {"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 14716, "length": 2329, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353], "starting_column": 13, "ending_column": 52}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480], "starting_column": 1, "ending_column": 11}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}}}, {"type": "node", "name": "l2Sender = Constants.DEFAULT_L2_SENDER", "source_mapping": {"start": 16411, "length": 38, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [346], "starting_column": 27, "ending_column": 65}, "type_specific_fields": {"parent": {"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 14716, "length": 2329, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353], "starting_column": 13, "ending_column": 52}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480], "starting_column": 1, "ending_column": 11}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}}}], "description": "OptimismPortal2.l2Sender (src/L1/OptimismPortal2.sol#54) is written in both\n\tl2Sender = _tx.sender (src/L1/OptimismPortal2.sol#327)\n\tl2Sender = Constants.DEFAULT_L2_SENDER (src/L1/OptimismPortal2.sol#346)\n", "markdown": "[OptimismPortal2.l2Sender](src/L1/OptimismPortal2.sol#L54) is written in both\n\t[l2Sender = _tx.sender](src/L1/OptimismPortal2.sol#L327)\n\t[l2Sender = Constants.DEFAULT_L2_SENDER](src/L1/OptimismPortal2.sol#L346)\n", "first_markdown_element": "src/L1/OptimismPortal2.sol#L54", "id": "ec66682a9884e1f71956f493ab54d04460e4827acbde3d42678a3a0a56e2ce43", "check": "write-after-write", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "variable", "name": "l2Sender", "source_mapping": {"start": 2796, "length": 23, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [54], "starting_column": 5, "ending_column": 28}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 23826, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498], "starting_column": 1, "ending_column": 2}}}}, {"type": "node", "name": "l2Sender = _tx.sender", "source_mapping": {"start": 16361, "length": 21, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [344], "starting_column": 9, "ending_column": 30}, "type_specific_fields": {"parent": {"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 15460, "length": 2329, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 23826, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498], "starting_column": 1, "ending_column": 2}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}}}, {"type": "node", "name": "l2Sender = Constants.DEFAULT_L2_SENDER", "source_mapping": {"start": 17155, "length": 38, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [356], "starting_column": 9, "ending_column": 47}, "type_specific_fields": {"parent": {"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 15460, "length": 2329, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 23826, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498], "starting_column": 1, "ending_column": 2}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}}}], "description": "OptimismPortal2.l2Sender (src/L1/OptimismPortal2.sol#54) is written in both\n\tl2Sender = _tx.sender (src/L1/OptimismPortal2.sol#344)\n\tl2Sender = Constants.DEFAULT_L2_SENDER (src/L1/OptimismPortal2.sol#356)\n", "markdown": "[OptimismPortal2.l2Sender](src/L1/OptimismPortal2.sol#L54) is written in both\n\t[l2Sender = _tx.sender](src/L1/OptimismPortal2.sol#L344)\n\t[l2Sender = Constants.DEFAULT_L2_SENDER](src/L1/OptimismPortal2.sol#L356)\n", "first_markdown_element": "src/L1/OptimismPortal2.sol#L54", "id": "294dba726d30e30cbad67ac423aff3fb10ccffb8f37fe69888eb06cd2e7faad9", "check": "write-after-write", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "initiator", "source_mapping": {"start": 3840, "length": 119, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [90, 91, 92], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "initiator()"}}, {"type": "function", "name": "readOrHandle", "source_mapping": {"start": 2780, "length": 200, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "readOrHandle()"}}, {"type": "node", "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", "source_mapping": {"start": 7550, "length": 48, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [184], "starting_column": 17, "ending_column": 65}, "type_specific_fields": {"parent": {"type": "function", "name": "_forwardAndHalt", "source_mapping": {"start": 7281, "length": 466, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_forwardAndHalt(bytes32)"}}}}], "description": "DelayedVetoable.initiator() (src/L1/DelayedVetoable.sol#90-92) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#61-68) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#184)\n", "markdown": "[DelayedVetoable.initiator()](src/L1/DelayedVetoable.sol#L90-L92) calls [DelayedVetoable.readOrHandle()](src/L1/DelayedVetoable.sol#L61-L68) which halt the execution [return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))](src/L1/DelayedVetoable.sol#L184)\n", "first_markdown_element": "src/L1/DelayedVetoable.sol#L90-L92", "id": "2f0ff440c452994f93eeb59d1118c67b60d90509cd44640ed4bcda175849d617", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "vetoer", "source_mapping": {"start": 4050, "length": 107, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [96, 97, 98], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "vetoer()"}}, {"type": "function", "name": "readOrHandle", "source_mapping": {"start": 2780, "length": 200, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "readOrHandle()"}}, {"type": "node", "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", "source_mapping": {"start": 7550, "length": 48, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [184], "starting_column": 17, "ending_column": 65}, "type_specific_fields": {"parent": {"type": "function", "name": "_forwardAndHalt", "source_mapping": {"start": 7281, "length": 466, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_forwardAndHalt(bytes32)"}}}}], "description": "DelayedVetoable.vetoer() (src/L1/DelayedVetoable.sol#96-98) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#61-68) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#184)\n", "markdown": "[DelayedVetoable.vetoer()](src/L1/DelayedVetoable.sol#L96-L98) calls [DelayedVetoable.readOrHandle()](src/L1/DelayedVetoable.sol#L61-L68) which halt the execution [return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))](src/L1/DelayedVetoable.sol#L184)\n", "first_markdown_element": "src/L1/DelayedVetoable.sol#L96-L98", "id": "c5d34a7c09aed9f0e9eda0a08d720363d155a5c2f8a51262699cd9cda8f6e081", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "target", "source_mapping": {"start": 4248, "length": 99, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [102, 103, 104], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "target()"}}, {"type": "function", "name": "readOrHandle", "source_mapping": {"start": 2780, "length": 200, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "readOrHandle()"}}, {"type": "node", "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", "source_mapping": {"start": 7550, "length": 48, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [184], "starting_column": 17, "ending_column": 65}, "type_specific_fields": {"parent": {"type": "function", "name": "_forwardAndHalt", "source_mapping": {"start": 7281, "length": 466, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_forwardAndHalt(bytes32)"}}}}], "description": "DelayedVetoable.target() (src/L1/DelayedVetoable.sol#102-104) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#61-68) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#184)\n", "markdown": "[DelayedVetoable.target()](src/L1/DelayedVetoable.sol#L102-L104) calls [DelayedVetoable.readOrHandle()](src/L1/DelayedVetoable.sol#L61-L68) which halt the execution [return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))](src/L1/DelayedVetoable.sol#L184)\n", "first_markdown_element": "src/L1/DelayedVetoable.sol#L102-L104", "id": "40b59d20ec40f1b518e51f0b99ea46375013ec50b66df052612434f826263ed1", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "delay", "source_mapping": {"start": 4422, "length": 96, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [108, 109, 110], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "delay()"}}, {"type": "function", "name": "readOrHandle", "source_mapping": {"start": 2780, "length": 200, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "readOrHandle()"}}, {"type": "node", "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", "source_mapping": {"start": 7550, "length": 48, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [184], "starting_column": 17, "ending_column": 65}, "type_specific_fields": {"parent": {"type": "function", "name": "_forwardAndHalt", "source_mapping": {"start": 7281, "length": 466, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_forwardAndHalt(bytes32)"}}}}], "description": "DelayedVetoable.delay() (src/L1/DelayedVetoable.sol#108-110) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#61-68) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#184)\n", "markdown": "[DelayedVetoable.delay()](src/L1/DelayedVetoable.sol#L108-L110) calls [DelayedVetoable.readOrHandle()](src/L1/DelayedVetoable.sol#L61-L68) which halt the execution [return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))](src/L1/DelayedVetoable.sol#L184)\n", "first_markdown_element": "src/L1/DelayedVetoable.sol#L108-L110", "id": "f3b27aa640fa9135b6551282605b609c44ebb060ab15e1b568c919a1900278e6", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "queuedAt", "source_mapping": {"start": 4692, "length": 134, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [115, 116, 117], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "queuedAt(bytes32)"}}, {"type": "function", "name": "readOrHandle", "source_mapping": {"start": 2780, "length": 200, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "readOrHandle()"}}, {"type": "node", "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", "source_mapping": {"start": 7550, "length": 48, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [184], "starting_column": 17, "ending_column": 65}, "type_specific_fields": {"parent": {"type": "function", "name": "_forwardAndHalt", "source_mapping": {"start": 7281, "length": 466, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_forwardAndHalt(bytes32)"}}}}], "description": "DelayedVetoable.queuedAt(bytes32) (src/L1/DelayedVetoable.sol#115-117) calls DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#61-68) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#184)\n", "markdown": "[DelayedVetoable.queuedAt(bytes32)](src/L1/DelayedVetoable.sol#L115-L117) calls [DelayedVetoable.readOrHandle()](src/L1/DelayedVetoable.sol#L61-L68) which halt the execution [return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))](src/L1/DelayedVetoable.sol#L184)\n", "first_markdown_element": "src/L1/DelayedVetoable.sol#L115-L117", "id": "60e2d0b2123f864b56411897c63b8a4d35b8c0fa967e80cddc8f466b40e977f9", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "_handleCall", "source_mapping": {"start": 5192, "length": 2009, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_handleCall()"}}, {"type": "function", "name": "_forwardAndHalt", "source_mapping": {"start": 7281, "length": 466, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_forwardAndHalt(bytes32)"}}, {"type": "node", "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", "source_mapping": {"start": 7550, "length": 48, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [184], "starting_column": 17, "ending_column": 65}, "type_specific_fields": {"parent": {"type": "function", "name": "_forwardAndHalt", "source_mapping": {"start": 7281, "length": 466, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_forwardAndHalt(bytes32)"}}}}], "description": "DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#127-175) calls DelayedVetoable._forwardAndHalt(bytes32) (src/L1/DelayedVetoable.sol#178-191) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#184)\n", "markdown": "[DelayedVetoable._handleCall()](src/L1/DelayedVetoable.sol#L127-L175) calls [DelayedVetoable._forwardAndHalt(bytes32)](src/L1/DelayedVetoable.sol#L178-L191) which halt the execution [return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))](src/L1/DelayedVetoable.sol#L184)\n", "first_markdown_element": "src/L1/DelayedVetoable.sol#L127-L175", "id": "7de03eb5bb5d87de6cb2002aff77b9a53a4101ff3b1e1d794f3aba799c6452a6", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "readOrHandle", "source_mapping": {"start": 2780, "length": 200, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [61, 62, 63, 64, 65, 66, 67, 68], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "readOrHandle()"}}, {"type": "function", "name": "_handleCall", "source_mapping": {"start": 5192, "length": 2009, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_handleCall()"}}, {"type": "node", "name": "return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))", "source_mapping": {"start": 7550, "length": 48, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [184], "starting_column": 17, "ending_column": 65}, "type_specific_fields": {"parent": {"type": "function", "name": "_forwardAndHalt", "source_mapping": {"start": 7281, "length": 466, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_forwardAndHalt(bytes32)"}}}}], "description": "DelayedVetoable.readOrHandle() (src/L1/DelayedVetoable.sol#61-68) calls DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#127-175) which halt the execution return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata)) (src/L1/DelayedVetoable.sol#184)\n", "markdown": "[DelayedVetoable.readOrHandle()](src/L1/DelayedVetoable.sol#L61-L68) calls [DelayedVetoable._handleCall()](src/L1/DelayedVetoable.sol#L127-L175) which halt the execution [return(uint256,uint256)(returndata + 0x20,mload(uint256)(returndata))](src/L1/DelayedVetoable.sol#L184)\n", "first_markdown_element": "src/L1/DelayedVetoable.sol#L61-L68", "id": "12541821582e8769db5cb6534423a56e3cbae828c5a9e26da1db6d6f8c10634a", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "setCode", "source_mapping": {"start": 5022, "length": 1285, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "setCode(bytes)"}}, {"type": "function", "name": "proxyCallIfNotOwner", "source_mapping": {"start": 3867, "length": 237, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [64, 65, 66, 67, 68, 69, 70, 71], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "proxyCallIfNotOwner()"}}, {"type": "node", "name": "return(uint256,uint256)(0x0,returndatasize()())", "source_mapping": {"start": 9403, "length": 29, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [196], "starting_column": 13, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 8349, "length": 1099, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}}}], "description": "L1ChugSplashProxy.setCode(bytes) (src/legacy/L1ChugSplashProxy.sol#96-124) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", "markdown": "[L1ChugSplashProxy.setCode(bytes)](src/legacy/L1ChugSplashProxy.sol#L96-L124) calls [L1ChugSplashProxy.proxyCallIfNotOwner()](src/legacy/L1ChugSplashProxy.sol#L64-L71) which halt the execution [return(uint256,uint256)(0x0,returndatasize()())](src/legacy/L1ChugSplashProxy.sol#L196)\n", "first_markdown_element": "src/legacy/L1ChugSplashProxy.sol#L96-L124", "id": "4ea64b8e0080de740c9c25e7841217213a680d8680654c8c9f744be145a1431a", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "setStorage", "source_mapping": {"start": 6596, "length": 148, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [130, 131, 132, 133, 134], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "setStorage(bytes32,bytes32)"}}, {"type": "function", "name": "proxyCallIfNotOwner", "source_mapping": {"start": 3867, "length": 237, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [64, 65, 66, 67, 68, 69, 70, 71], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "proxyCallIfNotOwner()"}}, {"type": "node", "name": "return(uint256,uint256)(0x0,returndatasize()())", "source_mapping": {"start": 9403, "length": 29, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [196], "starting_column": 13, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 8349, "length": 1099, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}}}], "description": "L1ChugSplashProxy.setStorage(bytes32,bytes32) (src/legacy/L1ChugSplashProxy.sol#130-134) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", "markdown": "[L1ChugSplashProxy.setStorage(bytes32,bytes32)](src/legacy/L1ChugSplashProxy.sol#L130-L134) calls [L1ChugSplashProxy.proxyCallIfNotOwner()](src/legacy/L1ChugSplashProxy.sol#L64-L71) which halt the execution [return(uint256,uint256)(0x0,returndatasize()())](src/legacy/L1ChugSplashProxy.sol#L196)\n", "first_markdown_element": "src/legacy/L1ChugSplashProxy.sol#L130-L134", "id": "c116aac23f49ec7d5d6574972abfbf02d56d0521ea2285dc09d239a829e7d2af", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "setOwner", "source_mapping": {"start": 6890, "length": 97, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [138, 139, 140], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "setOwner(address)"}}, {"type": "function", "name": "proxyCallIfNotOwner", "source_mapping": {"start": 3867, "length": 237, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [64, 65, 66, 67, 68, 69, 70, 71], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "proxyCallIfNotOwner()"}}, {"type": "node", "name": "return(uint256,uint256)(0x0,returndatasize()())", "source_mapping": {"start": 9403, "length": 29, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [196], "starting_column": 13, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 8349, "length": 1099, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}}}], "description": "L1ChugSplashProxy.setOwner(address) (src/legacy/L1ChugSplashProxy.sol#138-140) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", "markdown": "[L1ChugSplashProxy.setOwner(address)](src/legacy/L1ChugSplashProxy.sol#L138-L140) calls [L1ChugSplashProxy.proxyCallIfNotOwner()](src/legacy/L1ChugSplashProxy.sol#L64-L71) which halt the execution [return(uint256,uint256)(0x0,returndatasize()())](src/legacy/L1ChugSplashProxy.sol#L196)\n", "first_markdown_element": "src/legacy/L1ChugSplashProxy.sol#L138-L140", "id": "0b6d0d6699a3fa3c78250e527327e43538895feecaa6cfd8a1793dfcc1d20c72", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "getOwner", "source_mapping": {"start": 7200, "length": 102, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [145, 146, 147], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "getOwner()"}}, {"type": "function", "name": "proxyCallIfNotOwner", "source_mapping": {"start": 3867, "length": 237, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [64, 65, 66, 67, 68, 69, 70, 71], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "proxyCallIfNotOwner()"}}, {"type": "node", "name": "return(uint256,uint256)(0x0,returndatasize()())", "source_mapping": {"start": 9403, "length": 29, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [196], "starting_column": 13, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 8349, "length": 1099, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}}}], "description": "L1ChugSplashProxy.getOwner() (src/legacy/L1ChugSplashProxy.sol#145-147) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", "markdown": "[L1ChugSplashProxy.getOwner()](src/legacy/L1ChugSplashProxy.sol#L145-L147) calls [L1ChugSplashProxy.proxyCallIfNotOwner()](src/legacy/L1ChugSplashProxy.sol#L64-L71) which halt the execution [return(uint256,uint256)(0x0,returndatasize()())](src/legacy/L1ChugSplashProxy.sol#L196)\n", "first_markdown_element": "src/legacy/L1ChugSplashProxy.sol#L145-L147", "id": "98821b545d4849522091839fbd87144e6fcc256a73b9dd1817676bd127be6d8c", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "getImplementation", "source_mapping": {"start": 7519, "length": 120, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [152, 153, 154], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "getImplementation()"}}, {"type": "function", "name": "proxyCallIfNotOwner", "source_mapping": {"start": 3867, "length": 237, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [64, 65, 66, 67, 68, 69, 70, 71], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "proxyCallIfNotOwner()"}}, {"type": "node", "name": "return(uint256,uint256)(0x0,returndatasize()())", "source_mapping": {"start": 9403, "length": 29, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [196], "starting_column": 13, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 8349, "length": 1099, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}}}], "description": "L1ChugSplashProxy.getImplementation() (src/legacy/L1ChugSplashProxy.sol#152-154) calls L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", "markdown": "[L1ChugSplashProxy.getImplementation()](src/legacy/L1ChugSplashProxy.sol#L152-L154) calls [L1ChugSplashProxy.proxyCallIfNotOwner()](src/legacy/L1ChugSplashProxy.sol#L64-L71) which halt the execution [return(uint256,uint256)(0x0,returndatasize()())](src/legacy/L1ChugSplashProxy.sol#L196)\n", "first_markdown_element": "src/legacy/L1ChugSplashProxy.sol#L152-L154", "id": "11c5e51d3a0080a2b8f208ae6ec1a4c5617c6df83441ac96c67f322294f73f2b", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "proxyCallIfNotOwner", "source_mapping": {"start": 3867, "length": 237, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [64, 65, 66, 67, 68, 69, 70, 71], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "proxyCallIfNotOwner()"}}, {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 8349, "length": 1099, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}, {"type": "node", "name": "return(uint256,uint256)(0x0,returndatasize()())", "source_mapping": {"start": 9403, "length": 29, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [196], "starting_column": 13, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 8349, "length": 1099, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1ChugSplashProxy", "source_mapping": {"start": 1025, "length": 9534, "filename_relative": "src/legacy/L1ChugSplashProxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol", "filename_short": "src/legacy/L1ChugSplashProxy.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}}}], "description": "L1ChugSplashProxy.proxyCallIfNotOwner() (src/legacy/L1ChugSplashProxy.sol#64-71) calls L1ChugSplashProxy._doProxyCall() (src/legacy/L1ChugSplashProxy.sol#175-198) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/legacy/L1ChugSplashProxy.sol#196)\n", "markdown": "[L1ChugSplashProxy.proxyCallIfNotOwner()](src/legacy/L1ChugSplashProxy.sol#L64-L71) calls [L1ChugSplashProxy._doProxyCall()](src/legacy/L1ChugSplashProxy.sol#L175-L198) which halt the execution [return(uint256,uint256)(0x0,returndatasize()())](src/legacy/L1ChugSplashProxy.sol#L196)\n", "first_markdown_element": "src/legacy/L1ChugSplashProxy.sol#L64-L71", "id": "648de83c485a902ab3df50445e187c6390720ae77705d14edbcc112e4fd8fe1a", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "upgradeTo", "source_mapping": {"start": 2498, "length": 131, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [59, 60, 61], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "upgradeTo(address)"}}, {"type": "function", "name": "proxyCallIfNotAdmin", "source_mapping": {"start": 1295, "length": 237, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "proxyCallIfNotAdmin()"}}, {"type": "node", "name": "return(uint256,uint256)(0x0,returndatasize()())", "source_mapping": {"start": 5922, "length": 29, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [143], "starting_column": 13, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 4928, "length": 1039, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}}}], "description": "Proxy.upgradeTo(address) (src/universal/Proxy.sol#59-61) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", "markdown": "[Proxy.upgradeTo(address)](src/universal/Proxy.sol#L59-L61) calls [Proxy.proxyCallIfNotAdmin()](src/universal/Proxy.sol#L26-L33) which halt the execution [return(uint256,uint256)(0x0,returndatasize()())](src/universal/Proxy.sol#L143)\n", "first_markdown_element": "src/universal/Proxy.sol#L59-L61", "id": "5dbecee956931b503b0ed4fbb7be62ba5f9f64bab10ac87b3c5ba4dab3694bec", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "upgradeToAndCall", "source_mapping": {"start": 2959, "length": 458, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "upgradeToAndCall(address,bytes)"}}, {"type": "function", "name": "proxyCallIfNotAdmin", "source_mapping": {"start": 1295, "length": 237, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "proxyCallIfNotAdmin()"}}, {"type": "node", "name": "return(uint256,uint256)(0x0,returndatasize()())", "source_mapping": {"start": 5922, "length": 29, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [143], "starting_column": 13, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 4928, "length": 1039, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}}}], "description": "Proxy.upgradeToAndCall(address,bytes) (src/universal/Proxy.sol#67-81) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", "markdown": "[Proxy.upgradeToAndCall(address,bytes)](src/universal/Proxy.sol#L67-L81) calls [Proxy.proxyCallIfNotAdmin()](src/universal/Proxy.sol#L26-L33) which halt the execution [return(uint256,uint256)(0x0,returndatasize()())](src/universal/Proxy.sol#L143)\n", "first_markdown_element": "src/universal/Proxy.sol#L67-L81", "id": "2792614492719714cdcff9f7f8e1c602931befa4b0b2d9e0845a2fbf3964f949", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "changeAdmin", "source_mapping": {"start": 3563, "length": 109, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [85, 86, 87], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "changeAdmin(address)"}}, {"type": "function", "name": "proxyCallIfNotAdmin", "source_mapping": {"start": 1295, "length": 237, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "proxyCallIfNotAdmin()"}}, {"type": "node", "name": "return(uint256,uint256)(0x0,returndatasize()())", "source_mapping": {"start": 5922, "length": 29, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [143], "starting_column": 13, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 4928, "length": 1039, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}}}], "description": "Proxy.changeAdmin(address) (src/universal/Proxy.sol#85-87) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", "markdown": "[Proxy.changeAdmin(address)](src/universal/Proxy.sol#L85-L87) calls [Proxy.proxyCallIfNotAdmin()](src/universal/Proxy.sol#L26-L33) which halt the execution [return(uint256,uint256)(0x0,returndatasize()())](src/universal/Proxy.sol#L143)\n", "first_markdown_element": "src/universal/Proxy.sol#L85-L87", "id": "5f00d9ac316494d702da33c92ba3267b0b2a5ab498b5c720e942923a75fd0f50", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "admin", "source_mapping": {"start": 3763, "length": 105, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [91, 92, 93], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "admin()"}}, {"type": "function", "name": "proxyCallIfNotAdmin", "source_mapping": {"start": 1295, "length": 237, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "proxyCallIfNotAdmin()"}}, {"type": "node", "name": "return(uint256,uint256)(0x0,returndatasize()())", "source_mapping": {"start": 5922, "length": 29, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [143], "starting_column": 13, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 4928, "length": 1039, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}}}], "description": "Proxy.admin() (src/universal/Proxy.sol#91-93) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", "markdown": "[Proxy.admin()](src/universal/Proxy.sol#L91-L93) calls [Proxy.proxyCallIfNotAdmin()](src/universal/Proxy.sol#L26-L33) which halt the execution [return(uint256,uint256)(0x0,returndatasize()())](src/universal/Proxy.sol#L143)\n", "first_markdown_element": "src/universal/Proxy.sol#L91-L93", "id": "61c6823d9d96abad705c3e29c3768a5d2ade61e6f226c9241e6f3278063ab469", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "implementation", "source_mapping": {"start": 3967, "length": 123, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [97, 98, 99], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "implementation()"}}, {"type": "function", "name": "proxyCallIfNotAdmin", "source_mapping": {"start": 1295, "length": 237, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "proxyCallIfNotAdmin()"}}, {"type": "node", "name": "return(uint256,uint256)(0x0,returndatasize()())", "source_mapping": {"start": 5922, "length": 29, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [143], "starting_column": 13, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 4928, "length": 1039, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}}}], "description": "Proxy.implementation() (src/universal/Proxy.sol#97-99) calls Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", "markdown": "[Proxy.implementation()](src/universal/Proxy.sol#L97-L99) calls [Proxy.proxyCallIfNotAdmin()](src/universal/Proxy.sol#L26-L33) which halt the execution [return(uint256,uint256)(0x0,returndatasize()())](src/universal/Proxy.sol#L143)\n", "first_markdown_element": "src/universal/Proxy.sol#L97-L99", "id": "1e96b3f3be5c5b827284291533d15f8b70c3f8bc774e863359baa95195e8a79c", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "proxyCallIfNotAdmin", "source_mapping": {"start": 1295, "length": 237, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [26, 27, 28, 29, 30, 31, 32, 33], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "proxyCallIfNotAdmin()"}}, {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 4928, "length": 1039, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}, {"type": "node", "name": "return(uint256,uint256)(0x0,returndatasize()())", "source_mapping": {"start": 5922, "length": 29, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [143], "starting_column": 13, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "_doProxyCall", "source_mapping": {"start": 4928, "length": 1039, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Proxy", "source_mapping": {"start": 348, "length": 6312, "filename_relative": "src/universal/Proxy.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/Proxy.sol", "filename_short": "src/universal/Proxy.sol", "is_dependency": false, "lines": [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168], "starting_column": 1, "ending_column": 2}}, "signature": "_doProxyCall()"}}}}], "description": "Proxy.proxyCallIfNotAdmin() (src/universal/Proxy.sol#26-33) calls Proxy._doProxyCall() (src/universal/Proxy.sol#123-145) which halt the execution return(uint256,uint256)(0x0,returndatasize()()) (src/universal/Proxy.sol#143)\n", "markdown": "[Proxy.proxyCallIfNotAdmin()](src/universal/Proxy.sol#L26-L33) calls [Proxy._doProxyCall()](src/universal/Proxy.sol#L123-L145) which halt the execution [return(uint256,uint256)(0x0,returndatasize()())](src/universal/Proxy.sol#L143)\n", "first_markdown_element": "src/universal/Proxy.sol#L26-L33", "id": "d14996b9cc4486d4926155fb1f3d0c1ffc8be9b4af43a61074039356721c7e45", "check": "incorrect-return", "impact": "High", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "blobBaseFee", "source_mapping": {"start": 1899, "length": 26, "filename_relative": "src/L2/L1Block.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L2/L1Block.sol", "filename_short": "src/L2/L1Block.sol", "is_dependency": false, "lines": [50], "starting_column": 5, "ending_column": 31}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1Block", "source_mapping": {"start": 588, "length": 4256, "filename_relative": "src/L2/L1Block.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L2/L1Block.sol", "filename_short": "src/L2/L1Block.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119], "starting_column": 1, "ending_column": 2}}}}, {"type": "function", "name": "setL1BlockValuesEcotone", "source_mapping": {"start": 3886, "length": 956, "filename_relative": "src/L2/L1Block.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L2/L1Block.sol", "filename_short": "src/L2/L1Block.sol", "is_dependency": false, "lines": [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1Block", "source_mapping": {"start": 588, "length": 4256, "filename_relative": "src/L2/L1Block.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L2/L1Block.sol", "filename_short": "src/L2/L1Block.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119], "starting_column": 1, "ending_column": 2}}, "signature": "setL1BlockValuesEcotone()"}}], "description": "L1Block.blobBaseFee (src/L2/L1Block.sol#50) is never initialized. It is used in:\n\t- L1Block.setL1BlockValuesEcotone() (src/L2/L1Block.sol#101-118)\n", "markdown": "[L1Block.blobBaseFee](src/L2/L1Block.sol#L50) is never initialized. It is used in:\n\t- [L1Block.setL1BlockValuesEcotone()](src/L2/L1Block.sol#L101-L118)\n", "first_markdown_element": "src/L2/L1Block.sol#L50", "id": "fa673f7f315b9ee7fea38da72b4b0b0eb94babc8d0938536b00ce803ecc07fa2", "check": "uninitialized-state", "impact": "High", "confidence": "High"}, {"elements": [{"type": "function", "name": "_metered", "source_mapping": {"start": 3817, "length": 4037, "filename_relative": "src/L1/ResourceMetering.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/ResourceMetering.sol", "filename_short": "src/L1/ResourceMetering.sol", "is_dependency": false, "lines": [74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "ResourceMetering", "source_mapping": {"start": 527, "length": 8071, "filename_relative": "src/L1/ResourceMetering.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/ResourceMetering.sol", "filename_short": "src/L1/ResourceMetering.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162], "starting_column": 1, "ending_column": 2}}, "signature": "_metered(uint64,uint256)"}}, {"type": "node", "name": "targetResourceLimit = int256(uint256(config.maxResourceLimit)) / int256(uint256(config.elasticityMultiplier))", "source_mapping": {"start": 4072, "length": 128, "filename_relative": "src/L1/ResourceMetering.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/ResourceMetering.sol", "filename_short": "src/L1/ResourceMetering.sol", "is_dependency": false, "lines": [79, 80], "starting_column": 9, "ending_column": 100}, "type_specific_fields": {"parent": {"type": "function", "name": "_metered", "source_mapping": {"start": 3817, "length": 4037, "filename_relative": "src/L1/ResourceMetering.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/ResourceMetering.sol", "filename_short": "src/L1/ResourceMetering.sol", "is_dependency": false, "lines": [74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "ResourceMetering", "source_mapping": {"start": 527, "length": 8071, "filename_relative": "src/L1/ResourceMetering.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/ResourceMetering.sol", "filename_short": "src/L1/ResourceMetering.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162], "starting_column": 1, "ending_column": 2}}, "signature": "_metered(uint64,uint256)"}}}}, {"type": "node", "name": "baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) / (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator)))", "source_mapping": {"start": 4630, "length": 168, "filename_relative": "src/L1/ResourceMetering.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/ResourceMetering.sol", "filename_short": "src/L1/ResourceMetering.sol", "is_dependency": false, "lines": [87, 88], "starting_column": 13, "ending_column": 94}, "type_specific_fields": {"parent": {"type": "function", "name": "_metered", "source_mapping": {"start": 3817, "length": 4037, "filename_relative": "src/L1/ResourceMetering.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/ResourceMetering.sol", "filename_short": "src/L1/ResourceMetering.sol", "is_dependency": false, "lines": [74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "ResourceMetering", "source_mapping": {"start": 527, "length": 8071, "filename_relative": "src/L1/ResourceMetering.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/ResourceMetering.sol", "filename_short": "src/L1/ResourceMetering.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162], "starting_column": 1, "ending_column": 2}}, "signature": "_metered(uint64,uint256)"}}}}], "description": "ResourceMetering._metered(uint64,uint256) (src/L1/ResourceMetering.sol#74-146) performs a multiplication on the result of a division:\n\t- targetResourceLimit = int256(uint256(config.maxResourceLimit)) / int256(uint256(config.elasticityMultiplier)) (src/L1/ResourceMetering.sol#79-80)\n\t- baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) / (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator))) (src/L1/ResourceMetering.sol#87-88)\n", "markdown": "[ResourceMetering._metered(uint64,uint256)](src/L1/ResourceMetering.sol#L74-L146) performs a multiplication on the result of a division:\n\t- [targetResourceLimit = int256(uint256(config.maxResourceLimit)) / int256(uint256(config.elasticityMultiplier))](src/L1/ResourceMetering.sol#L79-L80)\n\t- [baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) / (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator)))](src/L1/ResourceMetering.sol#L87-L88)\n", "first_markdown_element": "src/L1/ResourceMetering.sol#L74-L146", "id": "595a94c37aa9f252f126879331b7f976f816b1f68c91143e14e849044bc177c0", "check": "divide-before-multiply", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "contract", "name": "L1BlockNumber", "source_mapping": {"start": 668, "length": 888, "filename_relative": "src/legacy/L1BlockNumber.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1BlockNumber.sol", "filename_short": "src/legacy/L1BlockNumber.sol", "is_dependency": false, "lines": [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45], "starting_column": 1, "ending_column": 2}}, {"type": "function", "name": "receive", "source_mapping": {"start": 863, "length": 178, "filename_relative": "src/legacy/L1BlockNumber.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1BlockNumber.sol", "filename_short": "src/legacy/L1BlockNumber.sol", "is_dependency": false, "lines": [22, 23, 24, 25, 26, 27, 28], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1BlockNumber", "source_mapping": {"start": 668, "length": 888, "filename_relative": "src/legacy/L1BlockNumber.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1BlockNumber.sol", "filename_short": "src/legacy/L1BlockNumber.sol", "is_dependency": false, "lines": [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45], "starting_column": 1, "ending_column": 2}}, "signature": "receive()"}}, {"type": "function", "name": "fallback", "source_mapping": {"start": 1145, "length": 179, "filename_relative": "src/legacy/L1BlockNumber.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1BlockNumber.sol", "filename_short": "src/legacy/L1BlockNumber.sol", "is_dependency": false, "lines": [32, 33, 34, 35, 36, 37, 38], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "L1BlockNumber", "source_mapping": {"start": 668, "length": 888, "filename_relative": "src/legacy/L1BlockNumber.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/legacy/L1BlockNumber.sol", "filename_short": "src/legacy/L1BlockNumber.sol", "is_dependency": false, "lines": [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45], "starting_column": 1, "ending_column": 2}}, "signature": "fallback()"}}], "description": "Contract locking ether found:\n\tContract L1BlockNumber (src/legacy/L1BlockNumber.sol#16-45) has payable functions:\n\t - L1BlockNumber.receive() (src/legacy/L1BlockNumber.sol#22-28)\n\t - L1BlockNumber.fallback() (src/legacy/L1BlockNumber.sol#32-38)\n\tBut does not have a function to withdraw the ether\n", "markdown": "Contract locking ether found:\n\tContract [L1BlockNumber](src/legacy/L1BlockNumber.sol#L16-L45) has payable functions:\n\t - [L1BlockNumber.receive()](src/legacy/L1BlockNumber.sol#L22-L28)\n\t - [L1BlockNumber.fallback()](src/legacy/L1BlockNumber.sol#L32-L38)\n\tBut does not have a function to withdraw the ether\n", "first_markdown_element": "src/legacy/L1BlockNumber.sol#L16-L45", "id": "c0920fe4b6b04a2b81f69b85402d465719d06978441052f49a6582415934a1bf", "check": "locked-ether", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "contract", "name": "SchemaResolver", "source_mapping": {"start": 350, "length": 5868, "filename_relative": "src/EAS/resolver/SchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol", "filename_short": "src/EAS/resolver/SchemaResolver.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165], "starting_column": 1, "ending_column": 2}}, {"type": "function", "name": "attest", "source_mapping": {"start": 565, "length": 82, "filename_relative": "src/EAS/resolver/ISchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/ISchemaResolver.sol", "filename_short": "src/EAS/resolver/ISchemaResolver.sol", "is_dependency": false, "lines": [16], "starting_column": 5, "ending_column": 87}, "type_specific_fields": {"parent": {"type": "contract", "name": "ISchemaResolver", "source_mapping": {"start": 188, "length": 1672, "filename_relative": "src/EAS/resolver/ISchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/ISchemaResolver.sol", "filename_short": "src/EAS/resolver/ISchemaResolver.sol", "is_dependency": false, "lines": [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46], "starting_column": 1, "ending_column": 2}}, "signature": "attest(Attestation)"}}, {"type": "function", "name": "multiAttest", "source_mapping": {"start": 926, "length": 163, "filename_relative": "src/EAS/resolver/ISchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/ISchemaResolver.sol", "filename_short": "src/EAS/resolver/ISchemaResolver.sol", "is_dependency": false, "lines": [22, 23, 24, 25, 26, 27, 28], "starting_column": 5, "ending_column": 24}, "type_specific_fields": {"parent": {"type": "contract", "name": "ISchemaResolver", "source_mapping": {"start": 188, "length": 1672, "filename_relative": "src/EAS/resolver/ISchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/ISchemaResolver.sol", "filename_short": "src/EAS/resolver/ISchemaResolver.sol", "is_dependency": false, "lines": [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46], "starting_column": 1, "ending_column": 2}}, "signature": "multiAttest(Attestation[],uint256[])"}}, {"type": "function", "name": "revoke", "source_mapping": {"start": 1305, "length": 82, "filename_relative": "src/EAS/resolver/ISchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/ISchemaResolver.sol", "filename_short": "src/EAS/resolver/ISchemaResolver.sol", "is_dependency": false, "lines": [33], "starting_column": 5, "ending_column": 87}, "type_specific_fields": {"parent": {"type": "contract", "name": "ISchemaResolver", "source_mapping": {"start": 188, "length": 1672, "filename_relative": "src/EAS/resolver/ISchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/ISchemaResolver.sol", "filename_short": "src/EAS/resolver/ISchemaResolver.sol", "is_dependency": false, "lines": [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46], "starting_column": 1, "ending_column": 2}}, "signature": "revoke(Attestation)"}}, {"type": "function", "name": "multiRevoke", "source_mapping": {"start": 1695, "length": 163, "filename_relative": "src/EAS/resolver/ISchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/ISchemaResolver.sol", "filename_short": "src/EAS/resolver/ISchemaResolver.sol", "is_dependency": false, "lines": [39, 40, 41, 42, 43, 44, 45], "starting_column": 5, "ending_column": 24}, "type_specific_fields": {"parent": {"type": "contract", "name": "ISchemaResolver", "source_mapping": {"start": 188, "length": 1672, "filename_relative": "src/EAS/resolver/ISchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/ISchemaResolver.sol", "filename_short": "src/EAS/resolver/ISchemaResolver.sol", "is_dependency": false, "lines": [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46], "starting_column": 1, "ending_column": 2}}, "signature": "multiRevoke(Attestation[],uint256[])"}}, {"type": "function", "name": "receive", "source_mapping": {"start": 1054, "length": 113, "filename_relative": "src/EAS/resolver/SchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol", "filename_short": "src/EAS/resolver/SchemaResolver.sol", "is_dependency": false, "lines": [41, 42, 43, 44, 45], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "SchemaResolver", "source_mapping": {"start": 350, "length": 5868, "filename_relative": "src/EAS/resolver/SchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol", "filename_short": "src/EAS/resolver/SchemaResolver.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165], "starting_column": 1, "ending_column": 2}}, "signature": "receive()"}}, {"type": "function", "name": "attest", "source_mapping": {"start": 1209, "length": 146, "filename_relative": "src/EAS/resolver/SchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol", "filename_short": "src/EAS/resolver/SchemaResolver.sol", "is_dependency": false, "lines": [48, 49, 50], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "SchemaResolver", "source_mapping": {"start": 350, "length": 5868, "filename_relative": "src/EAS/resolver/SchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol", "filename_short": "src/EAS/resolver/SchemaResolver.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165], "starting_column": 1, "ending_column": 2}}, "signature": "attest(Attestation)"}}, {"type": "function", "name": "multiAttest", "source_mapping": {"start": 1397, "length": 1497, "filename_relative": "src/EAS/resolver/SchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol", "filename_short": "src/EAS/resolver/SchemaResolver.sol", "is_dependency": false, "lines": [53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "SchemaResolver", "source_mapping": {"start": 350, "length": 5868, "filename_relative": "src/EAS/resolver/SchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol", "filename_short": "src/EAS/resolver/SchemaResolver.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165], "starting_column": 1, "ending_column": 2}}, "signature": "multiAttest(Attestation[],uint256[])"}}, {"type": "function", "name": "revoke", "source_mapping": {"start": 2936, "length": 146, "filename_relative": "src/EAS/resolver/SchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol", "filename_short": "src/EAS/resolver/SchemaResolver.sol", "is_dependency": false, "lines": [95, 96, 97], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "SchemaResolver", "source_mapping": {"start": 350, "length": 5868, "filename_relative": "src/EAS/resolver/SchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol", "filename_short": "src/EAS/resolver/SchemaResolver.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165], "starting_column": 1, "ending_column": 2}}, "signature": "revoke(Attestation)"}}, {"type": "function", "name": "multiRevoke", "source_mapping": {"start": 3124, "length": 1496, "filename_relative": "src/EAS/resolver/SchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol", "filename_short": "src/EAS/resolver/SchemaResolver.sol", "is_dependency": false, "lines": [100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "SchemaResolver", "source_mapping": {"start": 350, "length": 5868, "filename_relative": "src/EAS/resolver/SchemaResolver.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/EAS/resolver/SchemaResolver.sol", "filename_short": "src/EAS/resolver/SchemaResolver.sol", "is_dependency": false, "lines": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165], "starting_column": 1, "ending_column": 2}}, "signature": "multiRevoke(Attestation[],uint256[])"}}], "description": "Contract locking ether found:\n\tContract SchemaResolver (src/EAS/resolver/SchemaResolver.sol#11-165) has payable functions:\n\t - ISchemaResolver.attest(Attestation) (src/EAS/resolver/ISchemaResolver.sol#16)\n\t - ISchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#22-28)\n\t - ISchemaResolver.revoke(Attestation) (src/EAS/resolver/ISchemaResolver.sol#33)\n\t - ISchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/ISchemaResolver.sol#39-45)\n\t - SchemaResolver.receive() (src/EAS/resolver/SchemaResolver.sol#41-45)\n\t - SchemaResolver.attest(Attestation) (src/EAS/resolver/SchemaResolver.sol#48-50)\n\t - SchemaResolver.multiAttest(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#53-92)\n\t - SchemaResolver.revoke(Attestation) (src/EAS/resolver/SchemaResolver.sol#95-97)\n\t - SchemaResolver.multiRevoke(Attestation[],uint256[]) (src/EAS/resolver/SchemaResolver.sol#100-139)\n\tBut does not have a function to withdraw the ether\n", "markdown": "Contract locking ether found:\n\tContract [SchemaResolver](src/EAS/resolver/SchemaResolver.sol#L11-L165) has payable functions:\n\t - [ISchemaResolver.attest(Attestation)](src/EAS/resolver/ISchemaResolver.sol#L16)\n\t - [ISchemaResolver.multiAttest(Attestation[],uint256[])](src/EAS/resolver/ISchemaResolver.sol#L22-L28)\n\t - [ISchemaResolver.revoke(Attestation)](src/EAS/resolver/ISchemaResolver.sol#L33)\n\t - [ISchemaResolver.multiRevoke(Attestation[],uint256[])](src/EAS/resolver/ISchemaResolver.sol#L39-L45)\n\t - [SchemaResolver.receive()](src/EAS/resolver/SchemaResolver.sol#L41-L45)\n\t - [SchemaResolver.attest(Attestation)](src/EAS/resolver/SchemaResolver.sol#L48-L50)\n\t - [SchemaResolver.multiAttest(Attestation[],uint256[])](src/EAS/resolver/SchemaResolver.sol#L53-L92)\n\t - [SchemaResolver.revoke(Attestation)](src/EAS/resolver/SchemaResolver.sol#L95-L97)\n\t - [SchemaResolver.multiRevoke(Attestation[],uint256[])](src/EAS/resolver/SchemaResolver.sol#L100-L139)\n\tBut does not have a function to withdraw the ether\n", "first_markdown_element": "src/EAS/resolver/SchemaResolver.sol#L11-L165", "id": "3e52f3459d6607e6494e893c33e98bfaee52639c20f8e8366a39b97d30efeb9d", "check": "locked-ether", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "function", "name": "_handleCall", "source_mapping": {"start": 5192, "length": 2009, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_handleCall()"}}, {"type": "node", "name": "_forwardAndHalt(callHash)", "source_mapping": {"start": 5929, "length": 25, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [144], "starting_column": 17, "ending_column": 42}, "type_specific_fields": {"parent": {"type": "function", "name": "_handleCall", "source_mapping": {"start": 5192, "length": 2009, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_handleCall()"}}}, "additional_fields": {"underlying_type": "external_calls"}}, {"type": "node", "name": "(success,returndata) = TARGET.call(msg.data)", "source_mapping": {"start": 7415, "length": 63, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [181], "starting_column": 9, "ending_column": 72}, "type_specific_fields": {"parent": {"type": "function", "name": "_forwardAndHalt", "source_mapping": {"start": 7281, "length": 466, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_forwardAndHalt(bytes32)"}}}, "additional_fields": {"underlying_type": "external_calls_sending_eth"}}, {"type": "node", "name": "_queuedAt[callHash] = block.timestamp", "source_mapping": {"start": 5982, "length": 37, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [146], "starting_column": 13, "ending_column": 50}, "type_specific_fields": {"parent": {"type": "function", "name": "_handleCall", "source_mapping": {"start": 5192, "length": 2009, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DelayedVetoable", "source_mapping": {"start": 695, "length": 7054, "filename_relative": "src/L1/DelayedVetoable.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/DelayedVetoable.sol", "filename_short": "src/L1/DelayedVetoable.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192], "starting_column": 1, "ending_column": 2}}, "signature": "_handleCall()"}}}, "additional_fields": {"underlying_type": "variables_written", "variable_name": "_queuedAt"}}], "description": "Reentrancy in DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#127-175):\n\tExternal calls:\n\t- _forwardAndHalt(callHash) (src/L1/DelayedVetoable.sol#144)\n\t\t- (success,returndata) = TARGET.call(msg.data) (src/L1/DelayedVetoable.sol#181)\n\tState variables written after the call(s):\n\t- _queuedAt[callHash] = block.timestamp (src/L1/DelayedVetoable.sol#146)\n\tDelayedVetoable._queuedAt (src/L1/DelayedVetoable.sol#55) can be used in cross function reentrancies:\n\t- DelayedVetoable._handleCall() (src/L1/DelayedVetoable.sol#127-175)\n\t- DelayedVetoable.queuedAt(bytes32) (src/L1/DelayedVetoable.sol#115-117)\n", "markdown": "Reentrancy in [DelayedVetoable._handleCall()](src/L1/DelayedVetoable.sol#L127-L175):\n\tExternal calls:\n\t- [_forwardAndHalt(callHash)](src/L1/DelayedVetoable.sol#L144)\n\t\t- [(success,returndata) = TARGET.call(msg.data)](src/L1/DelayedVetoable.sol#L181)\n\tState variables written after the call(s):\n\t- [_queuedAt[callHash] = block.timestamp](src/L1/DelayedVetoable.sol#L146)\n\t[DelayedVetoable._queuedAt](src/L1/DelayedVetoable.sol#L55) can be used in cross function reentrancies:\n\t- [DelayedVetoable._handleCall()](src/L1/DelayedVetoable.sol#L127-L175)\n\t- [DelayedVetoable.queuedAt(bytes32)](src/L1/DelayedVetoable.sol#L115-L117)\n", "first_markdown_element": "src/L1/DelayedVetoable.sol#L127-L175", "id": "791771351f6ef5490cbea5fbd5fe374336617a83ad32ebe163690cdee25b4208", "check": "reentrancy-no-eth", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "peel", "source_mapping": {"start": 1616, "length": 885, "filename_relative": "src/periphery/TransferOnion.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/periphery/TransferOnion.sol", "filename_short": "src/periphery/TransferOnion.sol", "is_dependency": false, "lines": [44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "TransferOnion", "source_mapping": {"start": 633, "length": 1870, "filename_relative": "src/periphery/TransferOnion.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/periphery/TransferOnion.sol", "filename_short": "src/periphery/TransferOnion.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71], "starting_column": 1, "ending_column": 2}}, "signature": "peel(TransferOnion.Layer[])"}}, {"type": "node", "name": "TOKEN.safeTransferFrom(SENDER,layer.recipient,layer.amount)", "source_mapping": {"start": 2282, "length": 61, "filename_relative": "src/periphery/TransferOnion.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/periphery/TransferOnion.sol", "filename_short": "src/periphery/TransferOnion.sol", "is_dependency": false, "lines": [61], "starting_column": 13, "ending_column": 74}, "type_specific_fields": {"parent": {"type": "function", "name": "peel", "source_mapping": {"start": 1616, "length": 885, "filename_relative": "src/periphery/TransferOnion.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/periphery/TransferOnion.sol", "filename_short": "src/periphery/TransferOnion.sol", "is_dependency": false, "lines": [44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "TransferOnion", "source_mapping": {"start": 633, "length": 1870, "filename_relative": "src/periphery/TransferOnion.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/periphery/TransferOnion.sol", "filename_short": "src/periphery/TransferOnion.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71], "starting_column": 1, "ending_column": 2}}, "signature": "peel(TransferOnion.Layer[])"}}}, "additional_fields": {"underlying_type": "external_calls"}}, {"type": "node", "name": "shell = tempShell", "source_mapping": {"start": 2477, "length": 17, "filename_relative": "src/periphery/TransferOnion.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/periphery/TransferOnion.sol", "filename_short": "src/periphery/TransferOnion.sol", "is_dependency": false, "lines": [69], "starting_column": 9, "ending_column": 26}, "type_specific_fields": {"parent": {"type": "function", "name": "peel", "source_mapping": {"start": 1616, "length": 885, "filename_relative": "src/periphery/TransferOnion.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/periphery/TransferOnion.sol", "filename_short": "src/periphery/TransferOnion.sol", "is_dependency": false, "lines": [44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "TransferOnion", "source_mapping": {"start": 633, "length": 1870, "filename_relative": "src/periphery/TransferOnion.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/periphery/TransferOnion.sol", "filename_short": "src/periphery/TransferOnion.sol", "is_dependency": false, "lines": [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71], "starting_column": 1, "ending_column": 2}}, "signature": "peel(TransferOnion.Layer[])"}}}, "additional_fields": {"underlying_type": "variables_written", "variable_name": "shell"}}], "description": "Reentrancy in TransferOnion.peel(TransferOnion.Layer[]) (src/periphery/TransferOnion.sol#44-70):\n\tExternal calls:\n\t- TOKEN.safeTransferFrom(SENDER,layer.recipient,layer.amount) (src/periphery/TransferOnion.sol#61)\n\tState variables written after the call(s):\n\t- shell = tempShell (src/periphery/TransferOnion.sol#69)\n\tTransferOnion.shell (src/periphery/TransferOnion.sol#30) can be used in cross function reentrancies:\n\t- TransferOnion.constructor(ERC20,address,bytes32) (src/periphery/TransferOnion.sol#36-40)\n\t- TransferOnion.shell (src/periphery/TransferOnion.sol#30)\n", "markdown": "Reentrancy in [TransferOnion.peel(TransferOnion.Layer[])](src/periphery/TransferOnion.sol#L44-L70):\n\tExternal calls:\n\t- [TOKEN.safeTransferFrom(SENDER,layer.recipient,layer.amount)](src/periphery/TransferOnion.sol#L61)\n\tState variables written after the call(s):\n\t- [shell = tempShell](src/periphery/TransferOnion.sol#L69)\n\t[TransferOnion.shell](src/periphery/TransferOnion.sol#L30) can be used in cross function reentrancies:\n\t- [TransferOnion.constructor(ERC20,address,bytes32)](src/periphery/TransferOnion.sol#L36-L40)\n\t- [TransferOnion.shell](src/periphery/TransferOnion.sol#L30)\n", "first_markdown_element": "src/periphery/TransferOnion.sol#L44-L70", "id": "1349b68c3b08ecdf27782bd74d9fecadf1739eef738171cbbba403c77a29f424", "check": "reentrancy-no-eth", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "step", "source_mapping": {"start": 4978, "length": 4228, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "step(uint256,bool,bytes,bytes)"}}, {"type": "node", "name": "validStep = VM.step(_stateData,_proof,uuid.raw()) == postState.claim.raw()", "source_mapping": {"start": 8758, "length": 81, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [184], "starting_column": 9, "ending_column": 90}, "type_specific_fields": {"parent": {"type": "function", "name": "step", "source_mapping": {"start": 4978, "length": 4228, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "step(uint256,bool,bytes,bytes)"}}}, "additional_fields": {"underlying_type": "external_calls"}}, {"type": "node", "name": "parent.counteredBy = msg.sender", "source_mapping": {"start": 9168, "length": 31, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [190], "starting_column": 9, "ending_column": 40}, "type_specific_fields": {"parent": {"type": "function", "name": "step", "source_mapping": {"start": 4978, "length": 4228, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "step(uint256,bool,bytes,bytes)"}}}, "additional_fields": {"underlying_type": "variables_written", "variable_name": "claimData"}}], "description": "Reentrancy in FaultDisputeGame.step(uint256,bool,bytes,bytes) (src/dispute/FaultDisputeGame.sol#124-191):\n\tExternal calls:\n\t- validStep = VM.step(_stateData,_proof,uuid.raw()) == postState.claim.raw() (src/dispute/FaultDisputeGame.sol#184)\n\tState variables written after the call(s):\n\t- parent.counteredBy = msg.sender (src/dispute/FaultDisputeGame.sol#190)\n\tFaultDisputeGame.claimData (src/dispute/FaultDisputeGame.sol#66) can be used in cross function reentrancies:\n\t- FaultDisputeGame._findStartingAndDisputedOutputs(uint256) (src/dispute/FaultDisputeGame.sol#672-731)\n\t- FaultDisputeGame._findTraceAncestor(Position,uint256,bool) (src/dispute/FaultDisputeGame.sol#645-663)\n\t- FaultDisputeGame.claimData (src/dispute/FaultDisputeGame.sol#66)\n\t- FaultDisputeGame.claimDataLen() (src/dispute/FaultDisputeGame.sol#520-522)\n\t- FaultDisputeGame.initialize() (src/dispute/FaultDisputeGame.sol#464-517)\n\t- FaultDisputeGame.move(uint256,Claim,bool) (src/dispute/FaultDisputeGame.sol#197-286)\n\t- FaultDisputeGame.resolve() (src/dispute/FaultDisputeGame.sol#351-363)\n\t- FaultDisputeGame.resolveClaim(uint256) (src/dispute/FaultDisputeGame.sol#366-438)\n\t- FaultDisputeGame.step(uint256,bool,bytes,bytes) (src/dispute/FaultDisputeGame.sol#124-191)\n", "markdown": "Reentrancy in [FaultDisputeGame.step(uint256,bool,bytes,bytes)](src/dispute/FaultDisputeGame.sol#L124-L191):\n\tExternal calls:\n\t- [validStep = VM.step(_stateData,_proof,uuid.raw()) == postState.claim.raw()](src/dispute/FaultDisputeGame.sol#L184)\n\tState variables written after the call(s):\n\t- [parent.counteredBy = msg.sender](src/dispute/FaultDisputeGame.sol#L190)\n\t[FaultDisputeGame.claimData](src/dispute/FaultDisputeGame.sol#L66) can be used in cross function reentrancies:\n\t- [FaultDisputeGame._findStartingAndDisputedOutputs(uint256)](src/dispute/FaultDisputeGame.sol#L672-L731)\n\t- [FaultDisputeGame._findTraceAncestor(Position,uint256,bool)](src/dispute/FaultDisputeGame.sol#L645-L663)\n\t- [FaultDisputeGame.claimData](src/dispute/FaultDisputeGame.sol#L66)\n\t- [FaultDisputeGame.claimDataLen()](src/dispute/FaultDisputeGame.sol#L520-L522)\n\t- [FaultDisputeGame.initialize()](src/dispute/FaultDisputeGame.sol#L464-L517)\n\t- [FaultDisputeGame.move(uint256,Claim,bool)](src/dispute/FaultDisputeGame.sol#L197-L286)\n\t- [FaultDisputeGame.resolve()](src/dispute/FaultDisputeGame.sol#L351-L363)\n\t- [FaultDisputeGame.resolveClaim(uint256)](src/dispute/FaultDisputeGame.sol#L366-L438)\n\t- [FaultDisputeGame.step(uint256,bool,bytes,bytes)](src/dispute/FaultDisputeGame.sol#L124-L191)\n", "first_markdown_element": "src/dispute/FaultDisputeGame.sol#L124-L191", "id": "a31cc22ac44058d56b0a89d6a2ab1dbe6791d75f6d06397eebf72a6d932e82c2", "check": "reentrancy-no-eth", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "relayMessage", "source_mapping": {"start": 10315, "length": 5066, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "CrossDomainMessenger", "source_mapping": {"start": 3683, "length": 17490, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406], "starting_column": 1, "ending_column": 2}}, "signature": "relayMessage(uint256,address,address,uint256,uint256,bytes)"}}, {"type": "node", "name": "tx.origin == Constants.ESTIMATION_ADDRESS", "source_mapping": {"start": 13912, "length": 41, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [275], "starting_column": 17, "ending_column": 58}, "type_specific_fields": {"parent": {"type": "function", "name": "relayMessage", "source_mapping": {"start": 10315, "length": 5066, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "CrossDomainMessenger", "source_mapping": {"start": 3683, "length": 17490, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406], "starting_column": 1, "ending_column": 2}}, "signature": "relayMessage(uint256,address,address,uint256,uint256,bytes)"}}}}], "description": "CrossDomainMessenger.relayMessage(uint256,address,address,uint256,uint256,bytes) (src/universal/CrossDomainMessenger.sol#207-305) uses tx.origin for authorization: tx.origin == Constants.ESTIMATION_ADDRESS (src/universal/CrossDomainMessenger.sol#275)\n", "markdown": "[CrossDomainMessenger.relayMessage(uint256,address,address,uint256,uint256,bytes)](src/universal/CrossDomainMessenger.sol#L207-L305) uses tx.origin for authorization: [tx.origin == Constants.ESTIMATION_ADDRESS](src/universal/CrossDomainMessenger.sol#L275)\n", "first_markdown_element": "src/universal/CrossDomainMessenger.sol#L207-L305", "id": "baf2bfa9777021d9e36870b76a1020c950de67bbf00d486f604cc72d36c47839", "check": "tx-origin", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "relayMessage", "source_mapping": {"start": 10315, "length": 5066, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "CrossDomainMessenger", "source_mapping": {"start": 3683, "length": 17490, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406], "starting_column": 1, "ending_column": 2}}, "signature": "relayMessage(uint256,address,address,uint256,uint256,bytes)"}}, {"type": "node", "name": "tx.origin == Constants.ESTIMATION_ADDRESS", "source_mapping": {"start": 15234, "length": 41, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [301], "starting_column": 17, "ending_column": 58}, "type_specific_fields": {"parent": {"type": "function", "name": "relayMessage", "source_mapping": {"start": 10315, "length": 5066, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "CrossDomainMessenger", "source_mapping": {"start": 3683, "length": 17490, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406], "starting_column": 1, "ending_column": 2}}, "signature": "relayMessage(uint256,address,address,uint256,uint256,bytes)"}}}}], "description": "CrossDomainMessenger.relayMessage(uint256,address,address,uint256,uint256,bytes) (src/universal/CrossDomainMessenger.sol#207-305) uses tx.origin for authorization: tx.origin == Constants.ESTIMATION_ADDRESS (src/universal/CrossDomainMessenger.sol#301)\n", "markdown": "[CrossDomainMessenger.relayMessage(uint256,address,address,uint256,uint256,bytes)](src/universal/CrossDomainMessenger.sol#L207-L305) uses tx.origin for authorization: [tx.origin == Constants.ESTIMATION_ADDRESS](src/universal/CrossDomainMessenger.sol#L301)\n", "first_markdown_element": "src/universal/CrossDomainMessenger.sol#L207-L305", "id": "3702aae0a8031af92233fa312a75b60518153a9f80ad2e6157debb825eec5ba1", "check": "tx-origin", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 13252, "length": 4839, "filename_relative": "src/L1/OptimismPortal.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal.sol", "filename_short": "src/L1/OptimismPortal.sol", "is_dependency": false, "lines": [280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal", "source_mapping": {"start": 1199, "length": 20505, "filename_relative": "src/L1/OptimismPortal.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal.sol", "filename_short": "src/L1/OptimismPortal.sol", "is_dependency": false, "lines": [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433], "starting_column": 1, "ending_column": 2}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}, {"type": "node", "name": "success == false && tx.origin == Constants.ESTIMATION_ADDRESS", "source_mapping": {"start": 17954, "length": 61, "filename_relative": "src/L1/OptimismPortal.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal.sol", "filename_short": "src/L1/OptimismPortal.sol", "is_dependency": false, "lines": [360], "starting_column": 13, "ending_column": 74}, "type_specific_fields": {"parent": {"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 13252, "length": 4839, "filename_relative": "src/L1/OptimismPortal.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal.sol", "filename_short": "src/L1/OptimismPortal.sol", "is_dependency": false, "lines": [280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal", "source_mapping": {"start": 1199, "length": 20505, "filename_relative": "src/L1/OptimismPortal.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal.sol", "filename_short": "src/L1/OptimismPortal.sol", "is_dependency": false, "lines": [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433], "starting_column": 1, "ending_column": 2}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}}}], "description": "OptimismPortal.finalizeWithdrawalTransaction(Types.WithdrawalTransaction) (src/L1/OptimismPortal.sol#280-363) uses tx.origin for authorization: success == false && tx.origin == Constants.ESTIMATION_ADDRESS (src/L1/OptimismPortal.sol#360)\n", "markdown": "[OptimismPortal.finalizeWithdrawalTransaction(Types.WithdrawalTransaction)](src/L1/OptimismPortal.sol#L280-L363) uses tx.origin for authorization: [success == false && tx.origin == Constants.ESTIMATION_ADDRESS](src/L1/OptimismPortal.sol#L360)\n", "first_markdown_element": "src/L1/OptimismPortal.sol#L280-L363", "id": "b507540468fdf3f9972d33e723efb8c120f8d824ffe54842e1e998244944abaf", "check": "tx-origin", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 14716, "length": 2329, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476], "starting_column": 1, "ending_column": 2}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}, {"type": "node", "name": "! success && tx.origin == Constants.ESTIMATION_ADDRESS", "source_mapping": {"start": 16916, "length": 53, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [347], "starting_column": 13, "ending_column": 66}, "type_specific_fields": {"parent": {"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 14716, "length": 2329, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476], "starting_column": 1, "ending_column": 2}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}}}], "description": "OptimismPortal2.finalizeWithdrawalTransaction(Types.WithdrawalTransaction) (src/L1/OptimismPortal2.sol#308-350) uses tx.origin for authorization: ! success && tx.origin == Constants.ESTIMATION_ADDRESS (src/L1/OptimismPortal2.sol#347)\n", "markdown": "[OptimismPortal2.finalizeWithdrawalTransaction(Types.WithdrawalTransaction)](src/L1/OptimismPortal2.sol#L308-L350) uses tx.origin for authorization: [! success && tx.origin == Constants.ESTIMATION_ADDRESS](src/L1/OptimismPortal2.sol#L347)\n", "first_markdown_element": "src/L1/OptimismPortal2.sol#L308-L350", "id": "7f4e534ab54f269b764a28db827d0820f938651b430bf72145e81408c8d77ef3", "check": "tx-origin", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "grandparentClock", "source_mapping": {"start": 11860, "length": 22, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [235], "starting_column": 9, "ending_column": 31}, "type_specific_fields": {"parent": {"type": "function", "name": "move", "source_mapping": {"start": 9517, "length": 4693, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "move(uint256,Claim,bool)"}}}}], "description": "FaultDisputeGame.move(uint256,Claim,bool).grandparentClock (src/dispute/FaultDisputeGame.sol#235) is a local variable never initialized\n", "markdown": "[FaultDisputeGame.move(uint256,Claim,bool).grandparentClock](src/dispute/FaultDisputeGame.sol#L235) is a local variable never initialized\n", "first_markdown_element": "src/dispute/FaultDisputeGame.sol#L235", "id": "0369380fef18a61639eac6a12773df792e9969e7bb20eddde54ccf3a263a0987", "check": "uninitialized-local", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "currentDepth", "source_mapping": {"start": 33339, "length": 20, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [690], "starting_column": 9, "ending_column": 29}, "type_specific_fields": {"parent": {"type": "function", "name": "_findStartingAndDisputedOutputs", "source_mapping": {"start": 32477, "length": 3446, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "_findStartingAndDisputedOutputs(uint256)"}}}}], "description": "FaultDisputeGame._findStartingAndDisputedOutputs(uint256).currentDepth (src/dispute/FaultDisputeGame.sol#690) is a local variable never initialized\n", "markdown": "[FaultDisputeGame._findStartingAndDisputedOutputs(uint256).currentDepth](src/dispute/FaultDisputeGame.sol#L690) is a local variable never initialized\n", "first_markdown_element": "src/dispute/FaultDisputeGame.sol#L690", "id": "8c229f5475784b2e9526e30d55b066e479489bca4b07c4f062b42b5b70100794", "check": "uninitialized-local", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "relayMessage", "source_mapping": {"start": 10315, "length": 5066, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "CrossDomainMessenger", "source_mapping": {"start": 3683, "length": 17490, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406], "starting_column": 1, "ending_column": 2}}, "signature": "relayMessage(uint256,address,address,uint256,uint256,bytes)"}}, {"type": "node", "name": "(version) = Encoding.decodeVersionedNonce(_nonce)", "source_mapping": {"start": 10787, "length": 58, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [222], "starting_column": 9, "ending_column": 67}, "type_specific_fields": {"parent": {"type": "function", "name": "relayMessage", "source_mapping": {"start": 10315, "length": 5066, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "CrossDomainMessenger", "source_mapping": {"start": 3683, "length": 17490, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406], "starting_column": 1, "ending_column": 2}}, "signature": "relayMessage(uint256,address,address,uint256,uint256,bytes)"}}}}], "description": "CrossDomainMessenger.relayMessage(uint256,address,address,uint256,uint256,bytes) (src/universal/CrossDomainMessenger.sol#207-305) ignores return value by (version) = Encoding.decodeVersionedNonce(_nonce) (src/universal/CrossDomainMessenger.sol#222)\n", "markdown": "[CrossDomainMessenger.relayMessage(uint256,address,address,uint256,uint256,bytes)](src/universal/CrossDomainMessenger.sol#L207-L305) ignores return value by [(version) = Encoding.decodeVersionedNonce(_nonce)](src/universal/CrossDomainMessenger.sol#L222)\n", "first_markdown_element": "src/universal/CrossDomainMessenger.sol#L207-L305", "id": "44386f359246ae057885fdfb55bd224c93990000eb00c0f8a95364098f76f95e", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "proveWithdrawalTransaction", "source_mapping": {"start": 10692, "length": 3911, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476], "starting_column": 1, "ending_column": 2}}, "signature": "proveWithdrawalTransaction(Types.WithdrawalTransaction,uint256,Types.OutputRootProof,bytes[])"}}, {"type": "node", "name": "(gameType,gameProxy) = disputeGameFactory.gameAtIndex(_disputeGameIndex)", "source_mapping": {"start": 11391, "length": 96, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [247], "starting_column": 9, "ending_column": 105}, "type_specific_fields": {"parent": {"type": "function", "name": "proveWithdrawalTransaction", "source_mapping": {"start": 10692, "length": 3911, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476], "starting_column": 1, "ending_column": 2}}, "signature": "proveWithdrawalTransaction(Types.WithdrawalTransaction,uint256,Types.OutputRootProof,bytes[])"}}}}], "description": "OptimismPortal2.proveWithdrawalTransaction(Types.WithdrawalTransaction,uint256,Types.OutputRootProof,bytes[]) (src/L1/OptimismPortal2.sol#232-304) ignores return value by (gameType,gameProxy) = disputeGameFactory.gameAtIndex(_disputeGameIndex) (src/L1/OptimismPortal2.sol#247)\n", "markdown": "[OptimismPortal2.proveWithdrawalTransaction(Types.WithdrawalTransaction,uint256,Types.OutputRootProof,bytes[])](src/L1/OptimismPortal2.sol#L232-L304) ignores return value by [(gameType,gameProxy) = disputeGameFactory.gameAtIndex(_disputeGameIndex)](src/L1/OptimismPortal2.sol#L247)\n", "first_markdown_element": "src/L1/OptimismPortal2.sol#L232-L304", "id": "8830f3dfb5472dfaf7954fb2e77efcce01faa75aece2e030343e61548e8935e0", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "checkTransaction", "source_mapping": {"start": 3201, "length": 1635, "filename_relative": "src/Safe/LivenessGuard.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/Safe/LivenessGuard.sol", "filename_short": "src/Safe/LivenessGuard.sol", "is_dependency": false, "lines": [69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "LivenessGuard", "source_mapping": {"start": 1239, "length": 5732, "filename_relative": "src/Safe/LivenessGuard.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/Safe/LivenessGuard.sol", "filename_short": "src/Safe/LivenessGuard.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159], "starting_column": 1, "ending_column": 2}}, "signature": "checkTransaction(address,uint256,bytes,Enum.Operation,uint256,uint256,uint256,address,address,bytes,address)"}}, {"type": "node", "name": "ownersBefore.add(owners[i])", "source_mapping": {"start": 3884, "length": 27, "filename_relative": "src/Safe/LivenessGuard.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/Safe/LivenessGuard.sol", "filename_short": "src/Safe/LivenessGuard.sol", "is_dependency": false, "lines": [91], "starting_column": 13, "ending_column": 40}, "type_specific_fields": {"parent": {"type": "function", "name": "checkTransaction", "source_mapping": {"start": 3201, "length": 1635, "filename_relative": "src/Safe/LivenessGuard.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/Safe/LivenessGuard.sol", "filename_short": "src/Safe/LivenessGuard.sol", "is_dependency": false, "lines": [69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "LivenessGuard", "source_mapping": {"start": 1239, "length": 5732, "filename_relative": "src/Safe/LivenessGuard.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/Safe/LivenessGuard.sol", "filename_short": "src/Safe/LivenessGuard.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159], "starting_column": 1, "ending_column": 2}}, "signature": "checkTransaction(address,uint256,bytes,Enum.Operation,uint256,uint256,uint256,address,address,bytes,address)"}}}}], "description": "LivenessGuard.checkTransaction(address,uint256,bytes,Enum.Operation,uint256,uint256,uint256,address,address,bytes,address) (src/Safe/LivenessGuard.sol#69-117) ignores return value by ownersBefore.add(owners[i]) (src/Safe/LivenessGuard.sol#91)\n", "markdown": "[LivenessGuard.checkTransaction(address,uint256,bytes,Enum.Operation,uint256,uint256,uint256,address,address,bytes,address)](src/Safe/LivenessGuard.sol#L69-L117) ignores return value by [ownersBefore.add(owners[i])](src/Safe/LivenessGuard.sol#L91)\n", "first_markdown_element": "src/Safe/LivenessGuard.sol#L69-L117", "id": "e7db51bed73ec8725649e136aa53c89b47fb78f106a38ba5583f5f449c3df44c", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "checkAfterExecution", "source_mapping": {"start": 5290, "length": 1252, "filename_relative": "src/Safe/LivenessGuard.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/Safe/LivenessGuard.sol", "filename_short": "src/Safe/LivenessGuard.sol", "is_dependency": false, "lines": [125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "LivenessGuard", "source_mapping": {"start": 1239, "length": 5732, "filename_relative": "src/Safe/LivenessGuard.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/Safe/LivenessGuard.sol", "filename_short": "src/Safe/LivenessGuard.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159], "starting_column": 1, "ending_column": 2}}, "signature": "checkAfterExecution(bytes32,bool)"}}, {"type": "node", "name": "ownersBefore.remove(ownerBefore)", "source_mapping": {"start": 6493, "length": 32, "filename_relative": "src/Safe/LivenessGuard.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/Safe/LivenessGuard.sol", "filename_short": "src/Safe/LivenessGuard.sol", "is_dependency": false, "lines": [147], "starting_column": 13, "ending_column": 45}, "type_specific_fields": {"parent": {"type": "function", "name": "checkAfterExecution", "source_mapping": {"start": 5290, "length": 1252, "filename_relative": "src/Safe/LivenessGuard.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/Safe/LivenessGuard.sol", "filename_short": "src/Safe/LivenessGuard.sol", "is_dependency": false, "lines": [125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "LivenessGuard", "source_mapping": {"start": 1239, "length": 5732, "filename_relative": "src/Safe/LivenessGuard.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/Safe/LivenessGuard.sol", "filename_short": "src/Safe/LivenessGuard.sol", "is_dependency": false, "lines": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159], "starting_column": 1, "ending_column": 2}}, "signature": "checkAfterExecution(bytes32,bool)"}}}}], "description": "LivenessGuard.checkAfterExecution(bytes32,bool) (src/Safe/LivenessGuard.sol#125-149) ignores return value by ownersBefore.remove(ownerBefore) (src/Safe/LivenessGuard.sol#147)\n", "markdown": "[LivenessGuard.checkAfterExecution(bytes32,bool)](src/Safe/LivenessGuard.sol#L125-L149) ignores return value by [ownersBefore.remove(ownerBefore)](src/Safe/LivenessGuard.sol#L147)\n", "first_markdown_element": "src/Safe/LivenessGuard.sol#L125-L149", "id": "a6b6c14f97b8f53fd719fe31b201e7e3ecd9e1e96588f3169f9b04eb60d2877d", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "games", "source_mapping": {"start": 2565, "length": 342, "filename_relative": "src/dispute/DisputeGameFactory.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol", "filename_short": "src/dispute/DisputeGameFactory.sol", "is_dependency": false, "lines": [64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DisputeGameFactory", "source_mapping": {"start": 1032, "length": 6436, "filename_relative": "src/dispute/DisputeGameFactory.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol", "filename_short": "src/dispute/DisputeGameFactory.sol", "is_dependency": false, "lines": [22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198], "starting_column": 1, "ending_column": 2}}, "signature": "games(GameType,Claim,bytes)"}}, {"type": "node", "name": "(None,timestamp_,proxy_) = _disputeGames[uuid].unpack()", "source_mapping": {"start": 2847, "length": 53, "filename_relative": "src/dispute/DisputeGameFactory.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol", "filename_short": "src/dispute/DisputeGameFactory.sol", "is_dependency": false, "lines": [74], "starting_column": 9, "ending_column": 62}, "type_specific_fields": {"parent": {"type": "function", "name": "games", "source_mapping": {"start": 2565, "length": 342, "filename_relative": "src/dispute/DisputeGameFactory.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol", "filename_short": "src/dispute/DisputeGameFactory.sol", "is_dependency": false, "lines": [64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "DisputeGameFactory", "source_mapping": {"start": 1032, "length": 6436, "filename_relative": "src/dispute/DisputeGameFactory.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol", "filename_short": "src/dispute/DisputeGameFactory.sol", "is_dependency": false, "lines": [22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198], "starting_column": 1, "ending_column": 2}}, "signature": "games(GameType,Claim,bytes)"}}}}], "description": "DisputeGameFactory.games(GameType,Claim,bytes) (src/dispute/DisputeGameFactory.sol#64-75) ignores return value by (None,timestamp_,proxy_) = _disputeGames[uuid].unpack() (src/dispute/DisputeGameFactory.sol#74)\n", "markdown": "[DisputeGameFactory.games(GameType,Claim,bytes)](src/dispute/DisputeGameFactory.sol#L64-L75) ignores return value by [(None,timestamp_,proxy_) = _disputeGames[uuid].unpack()](src/dispute/DisputeGameFactory.sol#L74)\n", "first_markdown_element": "src/dispute/DisputeGameFactory.sol#L64-L75", "id": "004aeb9cde0c34281efe12ecba9cf191a562c14d4840e4037cdfc3de62ace754", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "addLocalData", "source_mapping": {"start": 14579, "length": 2158, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "addLocalData(uint256,uint256,uint256)"}}, {"type": "node", "name": "oracle.loadLocalData(_ident,uuid.raw(),l1Head.raw(),32,_partOffset)", "source_mapping": {"start": 15220, "length": 71, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [310], "starting_column": 13, "ending_column": 84}, "type_specific_fields": {"parent": {"type": "function", "name": "addLocalData", "source_mapping": {"start": 14579, "length": 2158, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "addLocalData(uint256,uint256,uint256)"}}}}], "description": "FaultDisputeGame.addLocalData(uint256,uint256,uint256) (src/dispute/FaultDisputeGame.sol#299-334) ignores return value by oracle.loadLocalData(_ident,uuid.raw(),l1Head.raw(),32,_partOffset) (src/dispute/FaultDisputeGame.sol#310)\n", "markdown": "[FaultDisputeGame.addLocalData(uint256,uint256,uint256)](src/dispute/FaultDisputeGame.sol#L299-L334) ignores return value by [oracle.loadLocalData(_ident,uuid.raw(),l1Head.raw(),32,_partOffset)](src/dispute/FaultDisputeGame.sol#L310)\n", "first_markdown_element": "src/dispute/FaultDisputeGame.sol#L299-L334", "id": "763bb639fb65a7cbbf328c3f8ca871f83d4fec7f6158eac30b24a2930427b3a8", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "addLocalData", "source_mapping": {"start": 14579, "length": 2158, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "addLocalData(uint256,uint256,uint256)"}}, {"type": "node", "name": "oracle.loadLocalData(_ident,uuid.raw(),starting.raw(),32,_partOffset)", "source_mapping": {"start": 15432, "length": 73, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [313], "starting_column": 13, "ending_column": 86}, "type_specific_fields": {"parent": {"type": "function", "name": "addLocalData", "source_mapping": {"start": 14579, "length": 2158, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "addLocalData(uint256,uint256,uint256)"}}}}], "description": "FaultDisputeGame.addLocalData(uint256,uint256,uint256) (src/dispute/FaultDisputeGame.sol#299-334) ignores return value by oracle.loadLocalData(_ident,uuid.raw(),starting.raw(),32,_partOffset) (src/dispute/FaultDisputeGame.sol#313)\n", "markdown": "[FaultDisputeGame.addLocalData(uint256,uint256,uint256)](src/dispute/FaultDisputeGame.sol#L299-L334) ignores return value by [oracle.loadLocalData(_ident,uuid.raw(),starting.raw(),32,_partOffset)](src/dispute/FaultDisputeGame.sol#L313)\n", "first_markdown_element": "src/dispute/FaultDisputeGame.sol#L299-L334", "id": "db2c2eb34d10413c40fe2188f165de643843dd37f48449b9a8619c35c22f0279", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "addLocalData", "source_mapping": {"start": 14579, "length": 2158, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "addLocalData(uint256,uint256,uint256)"}}, {"type": "node", "name": "oracle.loadLocalData(_ident,uuid.raw(),disputed.raw(),32,_partOffset)", "source_mapping": {"start": 15645, "length": 73, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [316], "starting_column": 13, "ending_column": 86}, "type_specific_fields": {"parent": {"type": "function", "name": "addLocalData", "source_mapping": {"start": 14579, "length": 2158, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "addLocalData(uint256,uint256,uint256)"}}}}], "description": "FaultDisputeGame.addLocalData(uint256,uint256,uint256) (src/dispute/FaultDisputeGame.sol#299-334) ignores return value by oracle.loadLocalData(_ident,uuid.raw(),disputed.raw(),32,_partOffset) (src/dispute/FaultDisputeGame.sol#316)\n", "markdown": "[FaultDisputeGame.addLocalData(uint256,uint256,uint256)](src/dispute/FaultDisputeGame.sol#L299-L334) ignores return value by [oracle.loadLocalData(_ident,uuid.raw(),disputed.raw(),32,_partOffset)](src/dispute/FaultDisputeGame.sol#L316)\n", "first_markdown_element": "src/dispute/FaultDisputeGame.sol#L299-L334", "id": "9702aa60c8832889631f0b6de7d749a701854dfdcf73ceef0bace811c65aba71", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "addLocalData", "source_mapping": {"start": 14579, "length": 2158, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "addLocalData(uint256,uint256,uint256)"}}, {"type": "node", "name": "oracle.loadLocalData(_ident,uuid.raw(),bytes32(l2Number << 0xC0),8,_partOffset)", "source_mapping": {"start": 16325, "length": 83, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [327], "starting_column": 13, "ending_column": 96}, "type_specific_fields": {"parent": {"type": "function", "name": "addLocalData", "source_mapping": {"start": 14579, "length": 2158, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "addLocalData(uint256,uint256,uint256)"}}}}], "description": "FaultDisputeGame.addLocalData(uint256,uint256,uint256) (src/dispute/FaultDisputeGame.sol#299-334) ignores return value by oracle.loadLocalData(_ident,uuid.raw(),bytes32(l2Number << 0xC0),8,_partOffset) (src/dispute/FaultDisputeGame.sol#327)\n", "markdown": "[FaultDisputeGame.addLocalData(uint256,uint256,uint256)](src/dispute/FaultDisputeGame.sol#L299-L334) ignores return value by [oracle.loadLocalData(_ident,uuid.raw(),bytes32(l2Number << 0xC0),8,_partOffset)](src/dispute/FaultDisputeGame.sol#L327)\n", "first_markdown_element": "src/dispute/FaultDisputeGame.sol#L299-L334", "id": "ee245b77a502d8e82346325fe49d61108d0bd0ec1604ddcce2fe98109e008cbb", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "addLocalData", "source_mapping": {"start": 14579, "length": 2158, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "addLocalData(uint256,uint256,uint256)"}}, {"type": "node", "name": "oracle.loadLocalData(_ident,uuid.raw(),bytes32(block.chainid << 0xC0),8,_partOffset)", "source_mapping": {"start": 16575, "length": 88, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [330], "starting_column": 13, "ending_column": 101}, "type_specific_fields": {"parent": {"type": "function", "name": "addLocalData", "source_mapping": {"start": 14579, "length": 2158, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "FaultDisputeGame", "source_mapping": {"start": 762, "length": 36758, "filename_relative": "src/dispute/FaultDisputeGame.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol", "filename_short": "src/dispute/FaultDisputeGame.sol", "is_dependency": false, "lines": [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766], "starting_column": 1, "ending_column": 2}}, "signature": "addLocalData(uint256,uint256,uint256)"}}}}], "description": "FaultDisputeGame.addLocalData(uint256,uint256,uint256) (src/dispute/FaultDisputeGame.sol#299-334) ignores return value by oracle.loadLocalData(_ident,uuid.raw(),bytes32(block.chainid << 0xC0),8,_partOffset) (src/dispute/FaultDisputeGame.sol#330)\n", "markdown": "[FaultDisputeGame.addLocalData(uint256,uint256,uint256)](src/dispute/FaultDisputeGame.sol#L299-L334) ignores return value by [oracle.loadLocalData(_ident,uuid.raw(),bytes32(block.chainid << 0xC0),8,_partOffset)](src/dispute/FaultDisputeGame.sol#L330)\n", "first_markdown_element": "src/dispute/FaultDisputeGame.sol#L299-L334", "id": "73fe3972601cc6ea4ff24d94e8df972b992343d997e305b892512f0fe2853f5e", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "hashCrossDomainMessage", "source_mapping": {"start": 2094, "length": 660, "filename_relative": "src/libraries/Hashing.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/libraries/Hashing.sol", "filename_short": "src/libraries/Hashing.sol", "is_dependency": false, "lines": [39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Hashing", "source_mapping": {"start": 255, "length": 5092, "filename_relative": "src/libraries/Hashing.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/libraries/Hashing.sol", "filename_short": "src/libraries/Hashing.sol", "is_dependency": false, "lines": [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124], "starting_column": 1, "ending_column": 2}}, "signature": "hashCrossDomainMessage(uint256,address,address,uint256,uint256,bytes)"}}, {"type": "node", "name": "(version) = Encoding.decodeVersionedNonce(_nonce)", "source_mapping": {"start": 2355, "length": 58, "filename_relative": "src/libraries/Hashing.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/libraries/Hashing.sol", "filename_short": "src/libraries/Hashing.sol", "is_dependency": false, "lines": [51], "starting_column": 9, "ending_column": 67}, "type_specific_fields": {"parent": {"type": "function", "name": "hashCrossDomainMessage", "source_mapping": {"start": 2094, "length": 660, "filename_relative": "src/libraries/Hashing.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/libraries/Hashing.sol", "filename_short": "src/libraries/Hashing.sol", "is_dependency": false, "lines": [39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "Hashing", "source_mapping": {"start": 255, "length": 5092, "filename_relative": "src/libraries/Hashing.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/libraries/Hashing.sol", "filename_short": "src/libraries/Hashing.sol", "is_dependency": false, "lines": [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124], "starting_column": 1, "ending_column": 2}}, "signature": "hashCrossDomainMessage(uint256,address,address,uint256,uint256,bytes)"}}}}], "description": "Hashing.hashCrossDomainMessage(uint256,address,address,uint256,uint256,bytes) (src/libraries/Hashing.sol#39-59) ignores return value by (version) = Encoding.decodeVersionedNonce(_nonce) (src/libraries/Hashing.sol#51)\n", "markdown": "[Hashing.hashCrossDomainMessage(uint256,address,address,uint256,uint256,bytes)](src/libraries/Hashing.sol#L39-L59) ignores return value by [(version) = Encoding.decodeVersionedNonce(_nonce)](src/libraries/Hashing.sol#L51)\n", "first_markdown_element": "src/libraries/Hashing.sol#L39-L59", "id": "1c9189427ab6b52bbec781d0432aed1a62fbec3ef51df7b307691cc1281675ef", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "function", "name": "upgradeAndCall", "source_mapping": {"start": 8644, "length": 631, "filename_relative": "src/universal/ProxyAdmin.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/ProxyAdmin.sol", "filename_short": "src/universal/ProxyAdmin.sol", "is_dependency": false, "lines": [184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "ProxyAdmin", "source_mapping": {"start": 1241, "length": 8036, "filename_relative": "src/universal/ProxyAdmin.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/ProxyAdmin.sol", "filename_short": "src/universal/ProxyAdmin.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203], "starting_column": 1, "ending_column": 2}}, "signature": "upgradeAndCall(address,address,bytes)"}}, {"type": "node", "name": "Proxy(_proxy).upgradeToAndCall{value: msg.value}(_implementation,_data)", "source_mapping": {"start": 8923, "length": 74, "filename_relative": "src/universal/ProxyAdmin.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/ProxyAdmin.sol", "filename_short": "src/universal/ProxyAdmin.sol", "is_dependency": false, "lines": [195], "starting_column": 13, "ending_column": 87}, "type_specific_fields": {"parent": {"type": "function", "name": "upgradeAndCall", "source_mapping": {"start": 8644, "length": 631, "filename_relative": "src/universal/ProxyAdmin.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/ProxyAdmin.sol", "filename_short": "src/universal/ProxyAdmin.sol", "is_dependency": false, "lines": [184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "ProxyAdmin", "source_mapping": {"start": 1241, "length": 8036, "filename_relative": "src/universal/ProxyAdmin.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/ProxyAdmin.sol", "filename_short": "src/universal/ProxyAdmin.sol", "is_dependency": false, "lines": [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203], "starting_column": 1, "ending_column": 2}}, "signature": "upgradeAndCall(address,address,bytes)"}}}}], "description": "ProxyAdmin.upgradeAndCall(address,address,bytes) (src/universal/ProxyAdmin.sol#184-202) ignores return value by Proxy(_proxy).upgradeToAndCall{value: msg.value}(_implementation,_data) (src/universal/ProxyAdmin.sol#195)\n", "markdown": "[ProxyAdmin.upgradeAndCall(address,address,bytes)](src/universal/ProxyAdmin.sol#L184-L202) ignores return value by [Proxy(_proxy).upgradeToAndCall{value: msg.value}(_implementation,_data)](src/universal/ProxyAdmin.sol#L195)\n", "first_markdown_element": "src/universal/ProxyAdmin.sol#L184-L202", "id": "81d1f7dc411a9897d1685d2a83e4ef7d0913f0beeec0756a1e90039e750ef319", "check": "unused-return", "impact": "Medium", "confidence": "Medium"}, {"elements": [{"type": "variable", "name": "xDomainMsgSender", "source_mapping": {"start": 5649, "length": 33, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [126], "starting_column": 5, "ending_column": 38}, "type_specific_fields": {"parent": {"type": "contract", "name": "CrossDomainMessenger", "source_mapping": {"start": 3683, "length": 17490, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406], "starting_column": 1, "ending_column": 2}}}}, {"type": "node", "name": "xDomainMsgSender = _sender", "source_mapping": {"start": 14084, "length": 26, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [282], "starting_column": 9, "ending_column": 35}, "type_specific_fields": {"parent": {"type": "function", "name": "relayMessage", "source_mapping": {"start": 10315, "length": 5066, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "CrossDomainMessenger", "source_mapping": {"start": 3683, "length": 17490, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406], "starting_column": 1, "ending_column": 2}}, "signature": "relayMessage(uint256,address,address,uint256,uint256,bytes)"}}}}, {"type": "node", "name": "xDomainMsgSender = Constants.DEFAULT_L2_SENDER", "source_mapping": {"start": 14217, "length": 46, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [284], "starting_column": 9, "ending_column": 55}, "type_specific_fields": {"parent": {"type": "function", "name": "relayMessage", "source_mapping": {"start": 10315, "length": 5066, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "CrossDomainMessenger", "source_mapping": {"start": 3683, "length": 17490, "filename_relative": "src/universal/CrossDomainMessenger.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol", "filename_short": "src/universal/CrossDomainMessenger.sol", "is_dependency": false, "lines": [87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406], "starting_column": 1, "ending_column": 2}}, "signature": "relayMessage(uint256,address,address,uint256,uint256,bytes)"}}}}], "description": "CrossDomainMessenger.xDomainMsgSender (src/universal/CrossDomainMessenger.sol#126) is written in both\n\txDomainMsgSender = _sender (src/universal/CrossDomainMessenger.sol#282)\n\txDomainMsgSender = Constants.DEFAULT_L2_SENDER (src/universal/CrossDomainMessenger.sol#284)\n", "markdown": "[CrossDomainMessenger.xDomainMsgSender](src/universal/CrossDomainMessenger.sol#L126) is written in both\n\t[xDomainMsgSender = _sender](src/universal/CrossDomainMessenger.sol#L282)\n\t[xDomainMsgSender = Constants.DEFAULT_L2_SENDER](src/universal/CrossDomainMessenger.sol#L284)\n", "first_markdown_element": "src/universal/CrossDomainMessenger.sol#L126", "id": "858b95108475bbb08343b6f5701b03c0762d00b73cec53751173e93c3ec10c1a", "check": "write-after-write", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "variable", "name": "l2Sender", "source_mapping": {"start": 2193, "length": 23, "filename_relative": "src/L1/OptimismPortal.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal.sol", "filename_short": "src/L1/OptimismPortal.sol", "is_dependency": false, "lines": [43], "starting_column": 5, "ending_column": 28}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal", "source_mapping": {"start": 1199, "length": 20505, "filename_relative": "src/L1/OptimismPortal.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal.sol", "filename_short": "src/L1/OptimismPortal.sol", "is_dependency": false, "lines": [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433], "starting_column": 1, "ending_column": 2}}}}, {"type": "node", "name": "l2Sender = _tx.sender", "source_mapping": {"start": 16655, "length": 21, "filename_relative": "src/L1/OptimismPortal.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal.sol", "filename_short": "src/L1/OptimismPortal.sol", "is_dependency": false, "lines": [339], "starting_column": 9, "ending_column": 30}, "type_specific_fields": {"parent": {"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 13252, "length": 4839, "filename_relative": "src/L1/OptimismPortal.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal.sol", "filename_short": "src/L1/OptimismPortal.sol", "is_dependency": false, "lines": [280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal", "source_mapping": {"start": 1199, "length": 20505, "filename_relative": "src/L1/OptimismPortal.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal.sol", "filename_short": "src/L1/OptimismPortal.sol", "is_dependency": false, "lines": [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433], "starting_column": 1, "ending_column": 2}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}}}, {"type": "node", "name": "l2Sender = Constants.DEFAULT_L2_SENDER", "source_mapping": {"start": 17449, "length": 38, "filename_relative": "src/L1/OptimismPortal.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal.sol", "filename_short": "src/L1/OptimismPortal.sol", "is_dependency": false, "lines": [351], "starting_column": 9, "ending_column": 47}, "type_specific_fields": {"parent": {"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 13252, "length": 4839, "filename_relative": "src/L1/OptimismPortal.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal.sol", "filename_short": "src/L1/OptimismPortal.sol", "is_dependency": false, "lines": [280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal", "source_mapping": {"start": 1199, "length": 20505, "filename_relative": "src/L1/OptimismPortal.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal.sol", "filename_short": "src/L1/OptimismPortal.sol", "is_dependency": false, "lines": [23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433], "starting_column": 1, "ending_column": 2}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}}}], "description": "OptimismPortal.l2Sender (src/L1/OptimismPortal.sol#43) is written in both\n\tl2Sender = _tx.sender (src/L1/OptimismPortal.sol#339)\n\tl2Sender = Constants.DEFAULT_L2_SENDER (src/L1/OptimismPortal.sol#351)\n", "markdown": "[OptimismPortal.l2Sender](src/L1/OptimismPortal.sol#L43) is written in both\n\t[l2Sender = _tx.sender](src/L1/OptimismPortal.sol#L339)\n\t[l2Sender = Constants.DEFAULT_L2_SENDER](src/L1/OptimismPortal.sol#L351)\n", "first_markdown_element": "src/L1/OptimismPortal.sol#L43", "id": "a43b8cff6d6b33609e8c7e3e89af17a0bc9ec73eb9a1a1b796e69c36ce8bcf71", "check": "write-after-write", "impact": "Medium", "confidence": "High"}, {"elements": [{"type": "variable", "name": "l2Sender", "source_mapping": {"start": 2796, "length": 23, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [54], "starting_column": 5, "ending_column": 28}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476], "starting_column": 1, "ending_column": 2}}}}, {"type": "node", "name": "l2Sender = _tx.sender", "source_mapping": {"start": 15617, "length": 21, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [326], "starting_column": 9, "ending_column": 30}, "type_specific_fields": {"parent": {"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 14716, "length": 2329, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476], "starting_column": 1, "ending_column": 2}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}}}, {"type": "node", "name": "l2Sender = Constants.DEFAULT_L2_SENDER", "source_mapping": {"start": 16411, "length": 38, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [338], "starting_column": 9, "ending_column": 47}, "type_specific_fields": {"parent": {"type": "function", "name": "finalizeWithdrawalTransaction", "source_mapping": {"start": 14716, "length": 2329, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350], "starting_column": 5, "ending_column": 6}, "type_specific_fields": {"parent": {"type": "contract", "name": "OptimismPortal2", "source_mapping": {"start": 1269, "length": 22759, "filename_relative": "src/L1/OptimismPortal2.sol", "filename_absolute": "/Users/mds/Documents/projects/ethereum-optimism/optimism/packages/contracts-bedrock/src/L1/OptimismPortal2.sol", "filename_short": "src/L1/OptimismPortal2.sol", "is_dependency": false, "lines": [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476], "starting_column": 1, "ending_column": 2}}, "signature": "finalizeWithdrawalTransaction(Types.WithdrawalTransaction)"}}}}], "description": "OptimismPortal2.l2Sender (src/L1/OptimismPortal2.sol#54) is written in both\n\tl2Sender = _tx.sender (src/L1/OptimismPortal2.sol#326)\n\tl2Sender = Constants.DEFAULT_L2_SENDER (src/L1/OptimismPortal2.sol#338)\n", "markdown": "[OptimismPortal2.l2Sender](src/L1/OptimismPortal2.sol#L54) is written in both\n\t[l2Sender = _tx.sender](src/L1/OptimismPortal2.sol#L326)\n\t[l2Sender = Constants.DEFAULT_L2_SENDER](src/L1/OptimismPortal2.sol#L338)\n", "first_markdown_element": "src/L1/OptimismPortal2.sol#L54", "id": "39a1b02450892eee126102ad84facb2bd801987bf64fb0d092e7b428629fd203", "check": "write-after-write", "impact": "Medium", "confidence": "High"}] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/AnchorStateRegistry.json b/packages/contracts-bedrock/snapshots/abi/AnchorStateRegistry.json new file mode 100644 index 000000000000..37ddc45a0ae2 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/AnchorStateRegistry.json @@ -0,0 +1,120 @@ +[ + { + "inputs": [ + { + "internalType": "contract IDisputeGameFactory", + "name": "_disputeGameFactory", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "GameType", + "name": "", + "type": "uint32" + } + ], + "name": "anchors", + "outputs": [ + { + "internalType": "Hash", + "name": "root", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "l2BlockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disputeGameFactory", + "outputs": [ + { + "internalType": "contract IDisputeGameFactory", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "GameType", + "name": "gameType", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "Hash", + "name": "root", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "l2BlockNumber", + "type": "uint256" + } + ], + "internalType": "struct OutputRoot", + "name": "outputRoot", + "type": "tuple" + } + ], + "internalType": "struct AnchorStateRegistry.StartingAnchorRoot[]", + "name": "_startingAnchorRoots", + "type": "tuple[]" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "tryUpdateAnchorState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/DataAvailabilityChallenge.json b/packages/contracts-bedrock/snapshots/abi/DataAvailabilityChallenge.json new file mode 100644 index 000000000000..fdf59e1a0026 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/DataAvailabilityChallenge.json @@ -0,0 +1,584 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balances", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bondSize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "challengedBlockNumber", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "challengedCommitment", + "type": "bytes" + } + ], + "name": "challenge", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "challengeWindow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "fixedResolutionCost", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "challengedBlockNumber", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "challengedCommitment", + "type": "bytes" + } + ], + "name": "getChallenge", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "challenger", + "type": "address" + }, + { + "internalType": "uint256", + "name": "lockedBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resolvedBlock", + "type": "uint256" + } + ], + "internalType": "struct Challenge", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "challengedBlockNumber", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "challengedCommitment", + "type": "bytes" + } + ], + "name": "getChallengeStatus", + "outputs": [ + { + "internalType": "enum ChallengeStatus", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_challengeWindow", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_resolveWindow", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_bondSize", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_resolverRefundPercentage", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "challengedBlockNumber", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "challengedCommitment", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "resolveData", + "type": "bytes" + } + ], + "name": "resolve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resolveWindow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "resolverRefundPercentage", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_bondSize", + "type": "uint256" + } + ], + "name": "setBondSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_resolverRefundPercentage", + "type": "uint256" + } + ], + "name": "setResolverRefundPercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "challengedBlockNumber", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "challengedCommitment", + "type": "bytes" + } + ], + "name": "unlockBond", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "commitment", + "type": "bytes" + } + ], + "name": "validateCommitment", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "variableResolutionCost", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "variableResolutionCostPrecision", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "name": "BalanceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "challengedBlockNumber", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "challengedCommitment", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "enum ChallengeStatus", + "name": "status", + "type": "uint8" + } + ], + "name": "ChallengeStatusChanged", + "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": "uint256", + "name": "challengeWindow", + "type": "uint256" + } + ], + "name": "RequiredBondSizeChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "resolverRefundPercentage", + "type": "uint256" + } + ], + "name": "ResolverRefundPercentageChanged", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "required", + "type": "uint256" + } + ], + "name": "BondTooLow", + "type": "error" + }, + { + "inputs": [], + "name": "ChallengeExists", + "type": "error" + }, + { + "inputs": [], + "name": "ChallengeNotActive", + "type": "error" + }, + { + "inputs": [], + "name": "ChallengeNotExpired", + "type": "error" + }, + { + "inputs": [], + "name": "ChallengeWindowNotOpen", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "commitmentType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "expectedLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actualLength", + "type": "uint256" + } + ], + "name": "InvalidCommitmentLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "providedDataCommitment", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "expectedCommitment", + "type": "bytes" + } + ], + "name": "InvalidInputData", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "invalidResolverRefundPercentage", + "type": "uint256" + } + ], + "name": "InvalidResolverRefundPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "commitmentType", + "type": "uint8" + } + ], + "name": "UnknownCommitmentType", + "type": "error" + }, + { + "inputs": [], + "name": "WithdrawalFailed", + "type": "error" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/DelayedVetoable.json b/packages/contracts-bedrock/snapshots/abi/DelayedVetoable.json index 3744ab134c1a..fad9861a1374 100644 --- a/packages/contracts-bedrock/snapshots/abi/DelayedVetoable.json +++ b/packages/contracts-bedrock/snapshots/abi/DelayedVetoable.json @@ -183,21 +183,11 @@ "name": "Vetoed", "type": "event" }, - { - "inputs": [], - "name": "AlreadyDelayed", - "type": "error" - }, { "inputs": [], "name": "ForwardingEarly", "type": "error" }, - { - "inputs": [], - "name": "TargetUnitialized", - "type": "error" - }, { "inputs": [ { diff --git a/packages/contracts-bedrock/snapshots/abi/DelayedWETH.json b/packages/contracts-bedrock/snapshots/abi/DelayedWETH.json new file mode 100644 index 000000000000..ef58fc35f123 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/DelayedWETH.json @@ -0,0 +1,534 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_delay", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "guy", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "config", + "outputs": [ + { + "internalType": "contract SuperchainConfig", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "delay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_guy", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_wad", + "type": "uint256" + } + ], + "name": "hold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "contract SuperchainConfig", + "name": "_config", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_wad", + "type": "uint256" + } + ], + "name": "recover", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_guy", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_wad", + "type": "uint256" + } + ], + "name": "unlock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_wad", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_guy", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_wad", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "withdrawals", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "guy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Deposit", + "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": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Unwrap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Withdrawal", + "type": "event" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/DisputeGameFactory.json b/packages/contracts-bedrock/snapshots/abi/DisputeGameFactory.json index 58285e7bca6b..01de0ce1b0a1 100644 --- a/packages/contracts-bedrock/snapshots/abi/DisputeGameFactory.json +++ b/packages/contracts-bedrock/snapshots/abi/DisputeGameFactory.json @@ -9,7 +9,7 @@ { "internalType": "GameType", "name": "_gameType", - "type": "uint8" + "type": "uint32" }, { "internalType": "Claim", @@ -33,6 +33,62 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { + "internalType": "GameType", + "name": "_gameType", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_n", + "type": "uint256" + } + ], + "name": "findLatestGames", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "GameId", + "name": "metadata", + "type": "bytes32" + }, + { + "internalType": "Timestamp", + "name": "timestamp", + "type": "uint64" + }, + { + "internalType": "Claim", + "name": "rootClaim", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "internalType": "struct IDisputeGameFactory.GameSearchResult[]", + "name": "games_", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -46,7 +102,7 @@ { "internalType": "GameType", "name": "gameType_", - "type": "uint8" + "type": "uint32" }, { "internalType": "Timestamp", @@ -80,7 +136,7 @@ { "internalType": "GameType", "name": "", - "type": "uint8" + "type": "uint32" } ], "name": "gameImpls", @@ -99,7 +155,7 @@ { "internalType": "GameType", "name": "_gameType", - "type": "uint8" + "type": "uint32" }, { "internalType": "Claim", @@ -133,7 +189,7 @@ { "internalType": "GameType", "name": "_gameType", - "type": "uint8" + "type": "uint32" }, { "internalType": "Claim", @@ -162,7 +218,7 @@ { "internalType": "GameType", "name": "", - "type": "uint8" + "type": "uint32" } ], "name": "initBonds", @@ -214,7 +270,7 @@ { "internalType": "GameType", "name": "_gameType", - "type": "uint8" + "type": "uint32" }, { "internalType": "contract IDisputeGame", @@ -232,7 +288,7 @@ { "internalType": "GameType", "name": "_gameType", - "type": "uint8" + "type": "uint32" }, { "internalType": "uint256", @@ -284,7 +340,7 @@ "indexed": true, "internalType": "GameType", "name": "gameType", - "type": "uint8" + "type": "uint32" }, { "indexed": true, @@ -309,7 +365,7 @@ "indexed": true, "internalType": "GameType", "name": "gameType", - "type": "uint8" + "type": "uint32" } ], "name": "ImplementationSet", @@ -322,7 +378,7 @@ "indexed": true, "internalType": "GameType", "name": "gameType", - "type": "uint8" + "type": "uint32" }, { "indexed": true, @@ -387,7 +443,7 @@ { "internalType": "GameType", "name": "gameType", - "type": "uint8" + "type": "uint32" } ], "name": "NoImplementation", diff --git a/packages/contracts-bedrock/snapshots/abi/FaultDisputeGame.json b/packages/contracts-bedrock/snapshots/abi/FaultDisputeGame.json index 16986dc781d1..cd9ddfee2cb1 100644 --- a/packages/contracts-bedrock/snapshots/abi/FaultDisputeGame.json +++ b/packages/contracts-bedrock/snapshots/abi/FaultDisputeGame.json @@ -4,23 +4,13 @@ { "internalType": "GameType", "name": "_gameType", - "type": "uint8" + "type": "uint32" }, { "internalType": "Claim", "name": "_absolutePrestate", "type": "bytes32" }, - { - "internalType": "uint256", - "name": "_genesisBlockNumber", - "type": "uint256" - }, - { - "internalType": "Hash", - "name": "_genesisOutputRoot", - "type": "bytes32" - }, { "internalType": "uint256", "name": "_maxGameDepth", @@ -40,11 +30,34 @@ "internalType": "contract IBigStepper", "name": "_vm", "type": "address" + }, + { + "internalType": "contract IDelayedWETH", + "name": "_weth", + "type": "address" + }, + { + "internalType": "contract IAnchorStateRegistry", + "name": "_anchorStateRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_l2ChainId", + "type": "uint256" } ], "stateMutability": "nonpayable", "type": "constructor" }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + }, { "inputs": [], "name": "absolutePrestate", @@ -174,6 +187,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "claimedBondFlag", + "outputs": [ + { + "internalType": "uint128", + "name": "claimedBondFlag_", + "type": "uint128" + } + ], + "stateMutability": "pure", + "type": "function" + }, { "inputs": [], "name": "createdAt", @@ -244,7 +270,7 @@ { "internalType": "GameType", "name": "gameType_", - "type": "uint8" + "type": "uint32" }, { "internalType": "Claim", @@ -280,33 +306,7 @@ { "internalType": "GameType", "name": "gameType_", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "genesisBlockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "genesisBlockNumber_", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "genesisOutputRoot", - "outputs": [ - { - "internalType": "Hash", - "name": "genesisOutputRoot_", - "type": "bytes32" + "type": "uint32" } ], "stateMutability": "view", @@ -328,7 +328,7 @@ "type": "uint256" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" }, { @@ -344,11 +344,11 @@ "outputs": [ { "internalType": "Hash", - "name": "", + "name": "l1Head_", "type": "bytes32" } ], - "stateMutability": "view", + "stateMutability": "pure", "type": "function" }, { @@ -364,6 +364,19 @@ "stateMutability": "pure", "type": "function" }, + { + "inputs": [], + "name": "l2ChainId", + "outputs": [ + { + "internalType": "uint256", + "name": "l2ChainId_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "maxGameDepth", @@ -465,6 +478,50 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "startingBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "startingBlockNumber_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startingOutputRoot", + "outputs": [ + { + "internalType": "Hash", + "name": "root", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "l2BlockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startingRootHash", + "outputs": [ + { + "internalType": "Hash", + "name": "startingRootHash_", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "status", @@ -532,6 +589,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "weth", + "outputs": [ + { + "internalType": "contract IDelayedWETH", + "name": "weth_", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "anonymous": false, "inputs": [ @@ -575,6 +645,11 @@ "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [], + "name": "AnchorRootNotFound", + "type": "error" + }, { "inputs": [], "name": "BondTransferFailed", @@ -610,6 +685,11 @@ "name": "ClockTimeExceeded", "type": "error" }, + { + "inputs": [], + "name": "DuplicateStep", + "type": "error" + }, { "inputs": [], "name": "GameDepthExceeded", @@ -645,6 +725,11 @@ "name": "InvalidSplitDepth", "type": "error" }, + { + "inputs": [], + "name": "NoCreditToClaim", + "type": "error" + }, { "inputs": [], "name": "OutOfOrderResolution", diff --git a/packages/contracts-bedrock/snapshots/abi/MIPS.json b/packages/contracts-bedrock/snapshots/abi/MIPS.json index ae195813b9ae..e4760d16fc5a 100644 --- a/packages/contracts-bedrock/snapshots/abi/MIPS.json +++ b/packages/contracts-bedrock/snapshots/abi/MIPS.json @@ -64,5 +64,18 @@ ], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json b/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json new file mode 100644 index 000000000000..4f3c67ebd4a1 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json @@ -0,0 +1,617 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_proofMaturityDelaySeconds", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_disputeGameFinalityDelaySeconds", + "type": "uint256" + }, + { + "internalType": "GameType", + "name": "_initialRespectedGameType", + "type": "uint32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "GUARDIAN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_CONFIG", + "outputs": [ + { + "internalType": "contract SystemConfig", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IDisputeGame", + "name": "_disputeGame", + "type": "address" + } + ], + "name": "blacklistDisputeGame", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_withdrawalHash", + "type": "bytes32" + } + ], + "name": "checkWithdrawal", + "outputs": [], + "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": [ + { + "internalType": "contract IDisputeGame", + "name": "", + "type": "address" + } + ], + "name": "disputeGameBlacklist", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disputeGameFactory", + "outputs": [ + { + "internalType": "contract DisputeGameFactory", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disputeGameFinalityDelaySeconds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "donateETH", + "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": "struct Types.WithdrawalTransaction", + "name": "_tx", + "type": "tuple" + } + ], + "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": "guardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract DisputeGameFactory", + "name": "_disputeGameFactory", + "type": "address" + }, + { + "internalType": "contract SystemConfig", + "name": "_systemConfig", + "type": "address" + }, + { + "internalType": "contract SuperchainConfig", + "name": "_superchainConfig", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l2Sender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_byteCount", + "type": "uint64" + } + ], + "name": "minimumGasLimit", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "pure", + "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": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proofMaturityDelaySeconds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "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": "struct Types.WithdrawalTransaction", + "name": "_tx", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "_disputeGameIndex", + "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": "struct Types.OutputRootProof", + "name": "_outputRootProof", + "type": "tuple" + }, + { + "internalType": "bytes[]", + "name": "_withdrawalProof", + "type": "bytes[]" + } + ], + "name": "proveWithdrawalTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "provenWithdrawals", + "outputs": [ + { + "internalType": "contract IDisputeGame", + "name": "disputeGameProxy", + "type": "address" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "respectedGameType", + "outputs": [ + { + "internalType": "GameType", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "respectedGameTypeUpdatedAt", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "GameType", + "name": "_gameType", + "type": "uint32" + } + ], + "name": "setRespectedGameType", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "superchainConfig", + "outputs": [ + { + "internalType": "contract SuperchainConfig", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "systemConfig", + "outputs": [ + { + "internalType": "contract SystemConfig", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "withdrawalHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "WithdrawalProven", + "type": "event" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json b/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json new file mode 100644 index 000000000000..5f804d69ca77 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/PermissionedDisputeGame.json @@ -0,0 +1,769 @@ +[ + { + "inputs": [ + { + "internalType": "GameType", + "name": "_gameType", + "type": "uint32" + }, + { + "internalType": "Claim", + "name": "_absolutePrestate", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_maxGameDepth", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_splitDepth", + "type": "uint256" + }, + { + "internalType": "Duration", + "name": "_gameDuration", + "type": "uint64" + }, + { + "internalType": "contract IBigStepper", + "name": "_vm", + "type": "address" + }, + { + "internalType": "contract IDelayedWETH", + "name": "_weth", + "type": "address" + }, + { + "internalType": "contract IAnchorStateRegistry", + "name": "_anchorStateRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_l2ChainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_proposer", + "type": "address" + }, + { + "internalType": "address", + "name": "_challenger", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "absolutePrestate", + "outputs": [ + { + "internalType": "Claim", + "name": "absolutePrestate_", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_ident", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_execLeafIdx", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_partOffset", + "type": "uint256" + } + ], + "name": "addLocalData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_parentIndex", + "type": "uint256" + }, + { + "internalType": "Claim", + "name": "_claim", + "type": "bytes32" + } + ], + "name": "attack", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "claimCredit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "claimData", + "outputs": [ + { + "internalType": "uint32", + "name": "parentIndex", + "type": "uint32" + }, + { + "internalType": "address", + "name": "counteredBy", + "type": "address" + }, + { + "internalType": "address", + "name": "claimant", + "type": "address" + }, + { + "internalType": "uint128", + "name": "bond", + "type": "uint128" + }, + { + "internalType": "Claim", + "name": "claim", + "type": "bytes32" + }, + { + "internalType": "Position", + "name": "position", + "type": "uint128" + }, + { + "internalType": "Clock", + "name": "clock", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "claimDataLen", + "outputs": [ + { + "internalType": "uint256", + "name": "len_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "claimedBondFlag", + "outputs": [ + { + "internalType": "uint128", + "name": "claimedBondFlag_", + "type": "uint128" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "createdAt", + "outputs": [ + { + "internalType": "Timestamp", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "credit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_parentIndex", + "type": "uint256" + }, + { + "internalType": "Claim", + "name": "_claim", + "type": "bytes32" + } + ], + "name": "defend", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "extraData", + "outputs": [ + { + "internalType": "bytes", + "name": "extraData_", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "gameData", + "outputs": [ + { + "internalType": "GameType", + "name": "gameType_", + "type": "uint32" + }, + { + "internalType": "Claim", + "name": "rootClaim_", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "extraData_", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gameDuration", + "outputs": [ + { + "internalType": "Duration", + "name": "gameDuration_", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gameType", + "outputs": [ + { + "internalType": "GameType", + "name": "gameType_", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Position", + "name": "_position", + "type": "uint128" + } + ], + "name": "getRequiredBond", + "outputs": [ + { + "internalType": "uint256", + "name": "requiredBond_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Head", + "outputs": [ + { + "internalType": "Hash", + "name": "l1Head_", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "l2BlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "l2BlockNumber_", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "l2ChainId", + "outputs": [ + { + "internalType": "uint256", + "name": "l2ChainId_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxGameDepth", + "outputs": [ + { + "internalType": "uint256", + "name": "maxGameDepth_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_challengeIndex", + "type": "uint256" + }, + { + "internalType": "Claim", + "name": "_claim", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "_isAttack", + "type": "bool" + } + ], + "name": "move", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "resolve", + "outputs": [ + { + "internalType": "enum GameStatus", + "name": "status_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_claimIndex", + "type": "uint256" + } + ], + "name": "resolveClaim", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "resolvedAt", + "outputs": [ + { + "internalType": "Timestamp", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rootClaim", + "outputs": [ + { + "internalType": "Claim", + "name": "rootClaim_", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "splitDepth", + "outputs": [ + { + "internalType": "uint256", + "name": "splitDepth_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startingBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "startingBlockNumber_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startingOutputRoot", + "outputs": [ + { + "internalType": "Hash", + "name": "root", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "l2BlockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startingRootHash", + "outputs": [ + { + "internalType": "Hash", + "name": "startingRootHash_", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "status", + "outputs": [ + { + "internalType": "enum GameStatus", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_claimIndex", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "_isAttack", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "_stateData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_proof", + "type": "bytes" + } + ], + "name": "step", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vm", + "outputs": [ + { + "internalType": "contract IBigStepper", + "name": "vm_", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "weth", + "outputs": [ + { + "internalType": "contract IDelayedWETH", + "name": "weth_", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "parentIndex", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "Claim", + "name": "claim", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "claimant", + "type": "address" + } + ], + "name": "Move", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "enum GameStatus", + "name": "status", + "type": "uint8" + } + ], + "name": "Resolved", + "type": "event" + }, + { + "inputs": [], + "name": "AlreadyInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "AnchorRootNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "BadAuth", + "type": "error" + }, + { + "inputs": [], + "name": "BondTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "CannotDefendRootClaim", + "type": "error" + }, + { + "inputs": [], + "name": "ClaimAboveSplit", + "type": "error" + }, + { + "inputs": [], + "name": "ClaimAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "ClaimAlreadyResolved", + "type": "error" + }, + { + "inputs": [], + "name": "ClockNotExpired", + "type": "error" + }, + { + "inputs": [], + "name": "ClockTimeExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateStep", + "type": "error" + }, + { + "inputs": [], + "name": "GameDepthExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "GameNotInProgress", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBond", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLocalIdent", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidParent", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPrestate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSplitDepth", + "type": "error" + }, + { + "inputs": [], + "name": "NoCreditToClaim", + "type": "error" + }, + { + "inputs": [], + "name": "OutOfOrderResolution", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "Claim", + "name": "rootClaim", + "type": "bytes32" + } + ], + "name": "UnexpectedRootClaim", + "type": "error" + }, + { + "inputs": [], + "name": "ValidStep", + "type": "error" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/PreimageOracle.json b/packages/contracts-bedrock/snapshots/abi/PreimageOracle.json index c80d311aa12a..5ba83bc0b514 100644 --- a/packages/contracts-bedrock/snapshots/abi/PreimageOracle.json +++ b/packages/contracts-bedrock/snapshots/abi/PreimageOracle.json @@ -41,6 +41,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "MIN_BOND_SIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -260,6 +273,39 @@ ], "name": "initLPP", "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_z", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_y", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_commitment", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "_proof", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_partOffset", + "type": "uint256" + } + ], + "name": "loadBlobPreimagePart", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -320,6 +366,29 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_partOffset", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_precompile", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_input", + "type": "bytes" + } + ], + "name": "loadPrecompilePreimagePart", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -471,6 +540,30 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proposalBonds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -698,6 +791,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -732,6 +838,16 @@ "name": "BadProposal", "type": "error" }, + { + "inputs": [], + "name": "BondTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBond", + "type": "error" + }, { "inputs": [], "name": "InvalidInputSize", diff --git a/packages/contracts-bedrock/snapshots/abi/WETH98.json b/packages/contracts-bedrock/snapshots/abi/WETH98.json new file mode 100644 index 000000000000..f5380edb3e52 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/WETH98.json @@ -0,0 +1,286 @@ +[ + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "guy", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "guy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Withdrawal", + "type": "event" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/state-diff/Kontrol-Deploy.json b/packages/contracts-bedrock/snapshots/state-diff/Kontrol-Deploy.json index 7eea311e7f51..1185fce2f370 100644 --- a/packages/contracts-bedrock/snapshots/state-diff/Kontrol-Deploy.json +++ b/packages/contracts-bedrock/snapshots/state-diff/Kontrol-Deploy.json @@ -1,3 +1,12035 @@ { - "accountAccesses": [{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":false,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x34A1D3fff3958843C43aD80F30b94c510645C316","chainInfo":{"chainId":31337,"forkId":0},"data":"0x608060405234801561001057600080fd5b50610913806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806353e5d9351161005057806353e5d935146100b7578063d18af54d146100cc578063ec9e80bb146100df57600080fd5b80631688f0b91461006c5780633408e470146100a9575b600080fd5b61007f61007a3660046105d2565b6100f2565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6040514681526020016100a0565b6100bf610194565b6040516100a091906106a5565b61007f6100da3660046106bf565b6101dc565b61007f6100ed3660046105d2565b6102f8565b600080838051906020012083604051602001610118929190918252602082015260400190565b60405160208183030381529060405280519060200120905061013b85858361032a565b60405173ffffffffffffffffffffffffffffffffffffffff8781168252919350908316907f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e2359060200160405180910390a2509392505050565b6060604051806020016101a6906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604052919050565b600080838360405160200161022092919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b6040516020818303038152906040528051906020012060001c90506102468686836100f2565b915073ffffffffffffffffffffffffffffffffffffffff8316156102ef576040517f1e52b51800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690631e52b518906102bc9085908a908a908a9060040161072b565b600060405180830381600087803b1580156102d657600080fd5b505af11580156102ea573d6000803e3d6000fd5b505050505b50949350505050565b60008083805190602001208361030b4690565b6040805160208101949094528301919091526060820152608001610118565b6000833b610399576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53696e676c65746f6e20636f6e7472616374206e6f74206465706c6f7965640060448201526064015b60405180910390fd5b6000604051806020016103ab906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052610403919073ffffffffffffffffffffffffffffffffffffffff881690602001610775565b6040516020818303038152906040529050828151826020016000f5915073ffffffffffffffffffffffffffffffffffffffff821661049d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f437265617465322063616c6c206661696c6564000000000000000000000000006044820152606401610390565b8351156104be5760008060008651602088016000875af1036104be57600080fd5b509392505050565b61016f8061079883390190565b73ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261053857600080fd5b813567ffffffffffffffff80821115610553576105536104f8565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610599576105996104f8565b816040528381528660208588010111156105b257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156105e757600080fd5b83356105f2816104d3565b9250602084013567ffffffffffffffff81111561060e57600080fd5b61061a86828701610527565b925050604084013590509250925092565b60005b8381101561064657818101518382015260200161062e565b83811115610655576000848401525b50505050565b6000815180845261067381602086016020860161062b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006106b8602083018461065b565b9392505050565b600080600080608085870312156106d557600080fd5b84356106e0816104d3565b9350602085013567ffffffffffffffff8111156106fc57600080fd5b61070887828801610527565b935050604085013591506060850135610720816104d3565b939692955090935050565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152610764608083018561065b565b905082606083015295945050505050565b6000835161078781846020880161062b565b919091019182525060200191905056fe608060405234801561001057600080fd5b5060405161016f38038061016f83398101604081905261002f916100b9565b6001600160a01b0381166100945760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642073696e676c65746f6e20616464726573732070726f766964604482015261195960f21b606482015260840160405180910390fd5b600080546001600160a01b0319166001600160a01b03929092169190911790556100e9565b6000602082840312156100cb57600080fd5b81516001600160a01b03811681146100e257600080fd5b9392505050565b6078806100f76000396000f3fe6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000aa164736f6c634300080f000a","deployedCode":"0x608060405234801561001057600080fd5b50600436106100675760003560e01c806353e5d9351161005057806353e5d935146100b7578063d18af54d146100cc578063ec9e80bb146100df57600080fd5b80631688f0b91461006c5780633408e470146100a9575b600080fd5b61007f61007a3660046105d2565b6100f2565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6040514681526020016100a0565b6100bf610194565b6040516100a091906106a5565b61007f6100da3660046106bf565b6101dc565b61007f6100ed3660046105d2565b6102f8565b600080838051906020012083604051602001610118929190918252602082015260400190565b60405160208183030381529060405280519060200120905061013b85858361032a565b60405173ffffffffffffffffffffffffffffffffffffffff8781168252919350908316907f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e2359060200160405180910390a2509392505050565b6060604051806020016101a6906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604052919050565b600080838360405160200161022092919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b6040516020818303038152906040528051906020012060001c90506102468686836100f2565b915073ffffffffffffffffffffffffffffffffffffffff8316156102ef576040517f1e52b51800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690631e52b518906102bc9085908a908a908a9060040161072b565b600060405180830381600087803b1580156102d657600080fd5b505af11580156102ea573d6000803e3d6000fd5b505050505b50949350505050565b60008083805190602001208361030b4690565b6040805160208101949094528301919091526060820152608001610118565b6000833b610399576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53696e676c65746f6e20636f6e7472616374206e6f74206465706c6f7965640060448201526064015b60405180910390fd5b6000604051806020016103ab906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052610403919073ffffffffffffffffffffffffffffffffffffffff881690602001610775565b6040516020818303038152906040529050828151826020016000f5915073ffffffffffffffffffffffffffffffffffffffff821661049d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f437265617465322063616c6c206661696c6564000000000000000000000000006044820152606401610390565b8351156104be5760008060008651602088016000875af1036104be57600080fd5b509392505050565b61016f8061079883390190565b73ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261053857600080fd5b813567ffffffffffffffff80821115610553576105536104f8565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610599576105996104f8565b816040528381528660208588010111156105b257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156105e757600080fd5b83356105f2816104d3565b9250602084013567ffffffffffffffff81111561060e57600080fd5b61061a86828701610527565b925050604084013590509250925092565b60005b8381101561064657818101518382015260200161062e565b83811115610655576000848401525b50505050565b6000815180845261067381602086016020860161062b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006106b8602083018461065b565b9392505050565b600080600080608085870312156106d557600080fd5b84356106e0816104d3565b9350602085013567ffffffffffffffff8111156106fc57600080fd5b61070887828801610527565b935050604085013591506060850135610720816104d3565b939692955090935050565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152610764608083018561065b565b905082606083015295945050505050565b6000835161078781846020880161062b565b919091019182525060200191905056fe608060405234801561001057600080fd5b5060405161016f38038061016f83398101604081905261002f916100b9565b6001600160a01b0381166100945760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642073696e676c65746f6e20616464726573732070726f766964604482015261195960f21b606482015260840160405180910390fd5b600080546001600160a01b0319166001600160a01b03929092169190911790556100e9565b6000602082840312156100cb57600080fd5b81516001600160a01b03811681146100e257600080fd5b9392505050565b6078806100f76000396000f3fe6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000aa164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":false,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x90193C961A926261B756D1E5bb255e67ff9498A1","chainInfo":{"chainId":31337,"forkId":0},"data":"0x608060405234801561001057600080fd5b506001600455614201806100256000396000f3fe6080604052600436106101d15760003560e01c8063affed0e0116100f7578063e19a9dd911610095578063f08a032311610064578063f08a0323146105f5578063f698da2514610615578063f8dc5dd91461067c578063ffa1ad741461069c5761020d565b8063e19a9dd914610580578063e318b52b146105a0578063e75235b8146105c0578063e86637db146105d55761020d565b8063cc2f8452116100d1578063cc2f8452146104f2578063d4d9bdcd14610520578063d8d11f7814610540578063e009cfde146105605761020d565b8063affed0e01461049c578063b4faba09146104b2578063b63e800d146104d25761020d565b80635624b25b1161016f5780636a7612021161013e5780636a7612021461040f5780637d83297414610422578063934f3a111461045a578063a0e67e2b1461047a5761020d565b80635624b25b146103755780635ae6bd37146103a2578063610b5925146103cf578063694e80c3146103ef5761020d565b80632f54bf6e116101ab5780632f54bf6e146102ea5780633408e4701461030a578063468721a7146103275780635229073f146103475761020d565b80630d582f131461027357806312fb68e0146102955780632d9ad53d146102b55761020d565b3661020d5760405134815233907f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d9060200160405180910390a2005b34801561021957600080fd5b507f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d580548061024457005b36600080373360601b365260008060143601600080855af190503d6000803e8061026d573d6000fd5b503d6000f35b34801561027f57600080fd5b5061029361028e366004613568565b6106e5565b005b3480156102a157600080fd5b506102936102b036600461366e565b610933565b3480156102c157600080fd5b506102d56102d03660046136e3565b610ff7565b60405190151581526020015b60405180910390f35b3480156102f657600080fd5b506102d56103053660046136e3565b61104c565b34801561031657600080fd5b50465b6040519081526020016102e1565b34801561033357600080fd5b506102d561034236600461370f565b61109e565b34801561035357600080fd5b5061036761036236600461370f565b6111d4565b6040516102e19291906137e4565b34801561038157600080fd5b506103956103903660046137ff565b61120a565b6040516102e19190613821565b3480156103ae57600080fd5b506103196103bd366004613834565b60076020526000908152604090205481565b3480156103db57600080fd5b506102936103ea3660046136e3565b611290565b3480156103fb57600080fd5b5061029361040a366004613834565b611479565b6102d561041d366004613896565b611593565b34801561042e57600080fd5b5061031961043d366004613568565b600860209081526000928352604080842090915290825290205481565b34801561046657600080fd5b5061029361047536600461396f565b61198f565b34801561048657600080fd5b5061048f611a0b565b6040516102e19190613a2d565b3480156104a857600080fd5b5061031960055481565b3480156104be57600080fd5b506102936104cd366004613a40565b611b23565b3480156104de57600080fd5b506102936104ed366004613a90565b611b46565b3480156104fe57600080fd5b5061051261050d366004613568565b611c62565b6040516102e1929190613b85565b34801561052c57600080fd5b5061029361053b366004613834565b611ed0565b34801561054c57600080fd5b5061031961055b366004613bbd565b611fa4565b34801561056c57600080fd5b5061029361057b366004613c7e565b611fd1565b34801561058c57600080fd5b5061029361059b3660046136e3565b6121a3565b3480156105ac57600080fd5b506102936105bb366004613cb7565b612344565b3480156105cc57600080fd5b50600454610319565b3480156105e157600080fd5b506103956105f0366004613bbd565b6126bc565b34801561060157600080fd5b506102936106103660046136e3565b612855565b34801561062157600080fd5b5061031960007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b34801561068857600080fd5b50610293610697366004613d02565b6128aa565b3480156106a857600080fd5b506103956040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b6106ed612b34565b73ffffffffffffffffffffffffffffffffffffffff821615801590610729575073ffffffffffffffffffffffffffffffffffffffff8216600114155b801561074b575073ffffffffffffffffffffffffffffffffffffffff82163014155b6107b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600260205260409020541615610845576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b60026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0805473ffffffffffffffffffffffffffffffffffffffff8481166000818152604081208054939094167fffffffffffffffffffffffff0000000000000000000000000000000000000000938416179093556001835283549091161790915560038054916108d783613d72565b909155505060405173ffffffffffffffffffffffffffffffffffffffff8316907f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2690600090a2806004541461092f5761092f81611479565b5050565b61093e816041612b9f565b825110156109a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6000808060008060005b86811015610feb576041818102890160208101516040820151919092015160ff16955090935091506000849003610cf857885160208a01208a14610a52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323700000000000000000000000000000000000000000000000000000060448201526064016107ad565b9193508391610a62876041612b9f565b821015610acb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323100000000000000000000000000000000000000000000000000000060448201526064016107ad565b8751610ad8836020612bdb565b1115610b40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323200000000000000000000000000000000000000000000000000000060448201526064016107ad565b602082890181015189519091610b63908390610b5d908790612bdb565b90612bdb565b1115610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323300000000000000000000000000000000000000000000000000000060448201526064016107ad565b6040517f20c13b0b000000000000000000000000000000000000000000000000000000008082528a85016020019173ffffffffffffffffffffffffffffffffffffffff8916906320c13b0b90610c27908f908690600401613daa565b602060405180830381865afa158015610c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c689190613dcf565b7fffffffff000000000000000000000000000000000000000000000000000000001614610cf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323400000000000000000000000000000000000000000000000000000060448201526064016107ad565b5050610eeb565b8360ff16600103610dc65791935083913373ffffffffffffffffffffffffffffffffffffffff84161480610d5b575073ffffffffffffffffffffffffffffffffffffffff851660009081526008602090815260408083208d845290915290205415155b610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323500000000000000000000000000000000000000000000000000000060448201526064016107ad565b610eeb565b601e8460ff161115610e8b576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018b9052600190605c0160405160208183030381529060405280519060200120600486610e2b9190613e11565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610e7a573d6000803e3d6000fd5b505050602060405103519450610eeb565b6040805160008152602081018083528c905260ff861691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa158015610ede573d6000803e3d6000fd5b5050506020604051035194505b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16118015610f4c575073ffffffffffffffffffffffffffffffffffffffff8581166000908152600260205260409020541615155b8015610f6f575073ffffffffffffffffffffffffffffffffffffffff8516600114155b610fd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323600000000000000000000000000000000000000000000000000000060448201526064016107ad565b8495508080610fe390613d72565b9150506109b2565b50505050505050505050565b6000600173ffffffffffffffffffffffffffffffffffffffff831614801590611046575073ffffffffffffffffffffffffffffffffffffffff8281166000908152600160205260409020541615155b92915050565b600073ffffffffffffffffffffffffffffffffffffffff821660011480159061104657505073ffffffffffffffffffffffffffffffffffffffff90811660009081526002602052604090205416151590565b6000336001148015906110d557503360009081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff1615155b61113b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b611168858585857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612bf7565b905080156111a05760405133907f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb890600090a26111cc565b60405133907facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37590600090a25b949350505050565b600060606111e48686868661109e565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b60606000611219836020613e34565b67ffffffffffffffff81111561123157611231613594565b6040519080825280601f01601f19166020018201604052801561125b576020820181803683370190505b50905060005b8381101561128857848101546020808302840101528061128081613d72565b915050611261565b509392505050565b611298612b34565b73ffffffffffffffffffffffffffffffffffffffff8116158015906112d4575073ffffffffffffffffffffffffffffffffffffffff8116600114155b61133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff81811660009081526001602052604090205416156113c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b600160208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f805473ffffffffffffffffffffffffffffffffffffffff848116600081815260408082208054949095167fffffffffffffffffffffffff000000000000000000000000000000000000000094851617909455948552835490911681179092555190917fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844091a250565b611481612b34565b6003548111156114ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001811015611558576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b60048190556040518181527f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c939060200160405180910390a150565b60008060006115ad8e8e8e8e8e8e8e8e8e8e6005546126bc565b6005805491925060006115bf83613d72565b90915550508051602082012091506115d882828661198f565b5060006116037f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c85490565b905073ffffffffffffffffffffffffffffffffffffffff8116156116a3578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b81526004016116709c9b9a99989796959493929190613edb565b600060405180830381600087803b15801561168a57600080fd5b505af115801561169e573d6000803e3d6000fd5b505050505b6116cf6116b28a6109c4613ff1565b603f6116bf8c6040613e34565b6116c99190614009565b90612c3e565b6116db906101f4613ff1565b5a1015611744576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313000000000000000000000000000000000000000000000000000000060448201526064016107ad565b60005a90506117b58f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8c6000146117a2578e612bf7565b6109c45a6117b09190614044565b612bf7565b93506117c25a8290612c55565b905083806117cf57508915155b806117d957508715155b61183f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313300000000000000000000000000000000000000000000000000000060448201526064016107ad565b6000881561185757611854828b8b8b8b612c70565b90505b841561189c57837f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e8260405161188f91815260200190565b60405180910390a26118d7565b837f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23826040516118ce91815260200190565b60405180910390a25b505073ffffffffffffffffffffffffffffffffffffffff81161561197e576040517f9327136800000000000000000000000000000000000000000000000000000000815260048101839052831515602482015273ffffffffffffffffffffffffffffffffffffffff821690639327136890604401600060405180830381600087803b15801561196557600080fd5b505af1158015611979573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b600454806119f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b611a0584848484610933565b50505050565b6060600060035467ffffffffffffffff811115611a2a57611a2a613594565b604051908082528060200260200182016040528015611a53578160200160208202803683370190505b506001600090815260026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0549192509073ffffffffffffffffffffffffffffffffffffffff165b73ffffffffffffffffffffffffffffffffffffffff8116600114611b1b5780838381518110611ace57611ace61405b565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152918116600090815260029092526040909120541681611b1381613d72565b925050611a9d565b509092915050565b600080825160208401855af480600052503d6020523d600060403e60403d016000fd5b611b848a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9250612e01915050565b73ffffffffffffffffffffffffffffffffffffffff841615611ba957611ba9846131ce565b611be98787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061327192505050565b8115611c0057611bfe82600060018685612c70565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b89604051611c4e95949392919061408a565b60405180910390a250505050505050505050565b6060600073ffffffffffffffffffffffffffffffffffffffff841660011480611c8f5750611c8f84610ff7565b611cf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b60008311611d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303600000000000000000000000000000000000000000000000000000060448201526064016107ad565b8267ffffffffffffffff811115611d7857611d78613594565b604051908082528060200260200182016040528015611da1578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff808616600090815260016020526040812054929450911691505b73ffffffffffffffffffffffffffffffffffffffff821615801590611e0d575073ffffffffffffffffffffffffffffffffffffffff8216600114155b8015611e1857508381105b15611e805781838281518110611e3057611e3061405b565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152928116600090815260019093526040909220549091169080611e7881613d72565b915050611dd1565b73ffffffffffffffffffffffffffffffffffffffff8216600114611ec55782611eaa600183614044565b81518110611eba57611eba61405b565b602002602001015191505b808352509250929050565b3360009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16611f5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333000000000000000000000000000000000000000000000000000000060448201526064016107ad565b336000818152600860209081526040808320858452909152808220600190555183917ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c91a350565b6000611fb98c8c8c8c8c8c8c8c8c8c8c6126bc565b8051906020012090509b9a5050505050505050505050565b611fd9612b34565b73ffffffffffffffffffffffffffffffffffffffff811615801590612015575073ffffffffffffffffffffffffffffffffffffffff8116600114155b61207b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526001602052604090205481169082161461210e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff818116600081815260016020526040808220805487861684528284208054919096167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179095558383528054909416909355915190917faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427691a25050565b6121ab612b34565b73ffffffffffffffffffffffffffffffffffffffff8116156122db576040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527fe6d7a83a00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015612251573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122759190614110565b6122db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475333303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c881815560405173ffffffffffffffffffffffffffffffffffffffff8316907f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa290600090a25050565b61234c612b34565b73ffffffffffffffffffffffffffffffffffffffff811615801590612388575073ffffffffffffffffffffffffffffffffffffffff8116600114155b80156123aa575073ffffffffffffffffffffffffffffffffffffffff81163014155b612410576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff818116600090815260026020526040902054161561249f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8216158015906124db575073ffffffffffffffffffffffffffffffffffffffff8216600114155b612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600260205260409020548116908316146125d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805486861680855283852080549288167fffffffffffffffffffffffff00000000000000000000000000000000000000009384161790559589168452828420805482169096179095558383528054909416909355915190917ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf91a260405173ffffffffffffffffffffffffffffffffffffffff8216907f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2690600090a2505050565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d6040516126f6929190614132565b60405190819003812061271c949392918e908e908e908e908e908e908e90602001614142565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012090507f19000000000000000000000000000000000000000000000000000000000000007f01000000000000000000000000000000000000000000000000000000000000006127f060007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b6040517fff0000000000000000000000000000000000000000000000000000000000000093841660208201529290911660218301526022820152604281018290526062016040516020818303038152906040529150509b9a5050505050505050505050565b61285d612b34565b612866816131ce565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b090600090a250565b6128b2612b34565b8060016003546128c29190614044565b101561292a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff821615801590612966575073ffffffffffffffffffffffffffffffffffffffff8216600114155b6129cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff838116600090815260026020526040902054811690831614612a5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805488861684529183208054929095167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790945591815282549091169091556003805491612ad7836141bf565b909155505060405173ffffffffffffffffffffffffffffffffffffffff8316907ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf90600090a28060045414612b2f57612b2f81611479565b505050565b333014612b9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333100000000000000000000000000000000000000000000000000000060448201526064016107ad565b565b600082600003612bb157506000611046565b6000612bbd8385613e34565b905082612bca8583614009565b14612bd457600080fd5b9392505050565b600080612be88385613ff1565b905083811015612bd457600080fd5b60006001836001811115612c0d57612c0d613e71565b03612c25576000808551602087018986f49050612c35565b600080855160208701888a87f190505b95945050505050565b600081831015612c4e5781612bd4565b5090919050565b600082821115612c6457600080fd5b60006111cc8385614044565b60008073ffffffffffffffffffffffffffffffffffffffff831615612c955782612c97565b325b905073ffffffffffffffffffffffffffffffffffffffff8416612d7657612cd63a8610612cc4573a612cc6565b855b612cd08989612bdb565b90612b9f565b60405190925073ffffffffffffffffffffffffffffffffffffffff82169083156108fc029084906000818181858888f19350505050612d71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313100000000000000000000000000000000000000000000000000000060448201526064016107ad565b612df7565b612d8485612cd08989612bdb565b9150612d91848284613469565b612df7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313200000000000000000000000000000000000000000000000000000060448201526064016107ad565b5095945050505050565b60045415612e6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b8151811115612ed6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001811015612f41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b600160005b8351811015613176576000848281518110612f6357612f6361405b565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015612fc1575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015612fe3575073ffffffffffffffffffffffffffffffffffffffff81163014155b801561301b57508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b613081576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600260205260409020541615613110576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff928316600090815260026020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016938216939093179092558061316e81613d72565b915050612f46565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260026020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790559051600355600455565b3073ffffffffffffffffffffffffffffffffffffffff82160361324d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475334303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b7f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d555565b600160008190526020527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f5473ffffffffffffffffffffffffffffffffffffffff161561331a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001600081905260208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f80547fffffffffffffffffffffffff000000000000000000000000000000000000000016909117905573ffffffffffffffffffffffffffffffffffffffff82161561092f57813b6133f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b6134038260008360015a612bf7565b61092f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6040805173ffffffffffffffffffffffffffffffffffffffff841660248201526044808201849052825180830390910181526064909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781528251600093929184919082896127105a03f13d8015613516576020811461351e5760009350613529565b819350613529565b600051158215171593505b5050509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461355557600080fd5b50565b803561356381613533565b919050565b6000806040838503121561357b57600080fd5b823561358681613533565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126135d457600080fd5b813567ffffffffffffffff808211156135ef576135ef613594565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561363557613635613594565b8160405283815286602085880101111561364e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561368457600080fd5b84359350602085013567ffffffffffffffff808211156136a357600080fd5b6136af888389016135c3565b945060408701359150808211156136c557600080fd5b506136d2878288016135c3565b949793965093946060013593505050565b6000602082840312156136f557600080fd5b8135612bd481613533565b80356002811061356357600080fd5b6000806000806080858703121561372557600080fd5b843561373081613533565b935060208501359250604085013567ffffffffffffffff81111561375357600080fd5b61375f878288016135c3565b92505061376e60608601613700565b905092959194509250565b6000815180845260005b8181101561379f57602081850181015186830182015201613783565b818111156137b1576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b82151581526040602082015260006111cc6040830184613779565b6000806040838503121561381257600080fd5b50508035926020909101359150565b602081526000612bd46020830184613779565b60006020828403121561384657600080fd5b5035919050565b60008083601f84011261385f57600080fd5b50813567ffffffffffffffff81111561387757600080fd5b60208301915083602082850101111561388f57600080fd5b9250929050565b60008060008060008060008060008060006101408c8e0312156138b857600080fd5b6138c18c613558565b9a5060208c0135995067ffffffffffffffff8060408e013511156138e457600080fd5b6138f48e60408f01358f0161384d565b909a50985061390560608e01613700565b975060808d0135965060a08d0135955060c08d0135945061392860e08e01613558565b93506139376101008e01613558565b9250806101208e0135111561394b57600080fd5b5061395d8d6101208e01358e016135c3565b90509295989b509295989b9093969950565b60008060006060848603121561398457600080fd5b83359250602084013567ffffffffffffffff808211156139a357600080fd5b6139af878388016135c3565b935060408601359150808211156139c557600080fd5b506139d2868287016135c3565b9150509250925092565b600081518084526020808501945080840160005b83811015613a2257815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016139f0565b509495945050505050565b602081526000612bd460208301846139dc565b60008060408385031215613a5357600080fd5b8235613a5e81613533565b9150602083013567ffffffffffffffff811115613a7a57600080fd5b613a86858286016135c3565b9150509250929050565b6000806000806000806000806000806101008b8d031215613ab057600080fd5b8a3567ffffffffffffffff80821115613ac857600080fd5b818d0191508d601f830112613adc57600080fd5b813581811115613aeb57600080fd5b8e60208260051b8501011115613b0057600080fd5b60208381019d50909b508d01359950613b1b60408e01613558565b985060608d0135915080821115613b3157600080fd5b50613b3e8d828e0161384d565b9097509550613b51905060808c01613558565b9350613b5f60a08c01613558565b925060c08b01359150613b7460e08c01613558565b90509295989b9194979a5092959850565b604081526000613b9860408301856139dc565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b60008060008060008060008060008060006101408c8e031215613bdf57600080fd5b8b35613bea81613533565b9a5060208c0135995060408c013567ffffffffffffffff811115613c0d57600080fd5b613c198e828f0161384d565b909a509850613c2c905060608d01613700565b965060808c0135955060a08c0135945060c08c0135935060e08c0135613c5181613533565b92506101008c0135613c6281613533565b809250506101208c013590509295989b509295989b9093969950565b60008060408385031215613c9157600080fd5b8235613c9c81613533565b91506020830135613cac81613533565b809150509250929050565b600080600060608486031215613ccc57600080fd5b8335613cd781613533565b92506020840135613ce781613533565b91506040840135613cf781613533565b809150509250925092565b600080600060608486031215613d1757600080fd5b8335613d2281613533565b92506020840135613d3281613533565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613da357613da3613d43565b5060010190565b604081526000613dbd6040830185613779565b8281036020840152612c358185613779565b600060208284031215613de157600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114612bd457600080fd5b600060ff821660ff841680821015613e2b57613e2b613d43565b90039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613e6c57613e6c613d43565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110613ed7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b600061016073ffffffffffffffffffffffffffffffffffffffff8f1683528d60208401528060408401528b81840152506101808b8d828501376000818d850101527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8d01168301613f51606085018d613ea0565b8a60808501528960a08501528860c0850152613f8560e085018973ffffffffffffffffffffffffffffffffffffffff169052565b73ffffffffffffffffffffffffffffffffffffffff87166101008501528184820301610120850152613fb982820187613779565b92505050613fe061014083018473ffffffffffffffffffffffffffffffffffffffff169052565b9d9c50505050505050505050505050565b6000821982111561400457614004613d43565b500190565b60008261403f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008282101561405657614056613d43565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6080808252810185905260008660a08301825b888110156140da5782356140b081613533565b73ffffffffffffffffffffffffffffffffffffffff1682526020928301929091019060010161409d565b506020840196909652505073ffffffffffffffffffffffffffffffffffffffff9283166040820152911660609091015292915050565b60006020828403121561412257600080fd5b81518015158114612bd457600080fd5b8183823760009101908152919050565b6000610160820190508c825273ffffffffffffffffffffffffffffffffffffffff808d1660208401528b60408401528a6060840152614184608084018b613ea0565b60a083019890985260c082019690965260e0810194909452918516610100840152909316610120820152610140019190915295945050505050565b6000816141ce576141ce613d43565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea164736f6c634300080f000a","deployedCode":"0x6080604052600436106101d15760003560e01c8063affed0e0116100f7578063e19a9dd911610095578063f08a032311610064578063f08a0323146105f5578063f698da2514610615578063f8dc5dd91461067c578063ffa1ad741461069c5761020d565b8063e19a9dd914610580578063e318b52b146105a0578063e75235b8146105c0578063e86637db146105d55761020d565b8063cc2f8452116100d1578063cc2f8452146104f2578063d4d9bdcd14610520578063d8d11f7814610540578063e009cfde146105605761020d565b8063affed0e01461049c578063b4faba09146104b2578063b63e800d146104d25761020d565b80635624b25b1161016f5780636a7612021161013e5780636a7612021461040f5780637d83297414610422578063934f3a111461045a578063a0e67e2b1461047a5761020d565b80635624b25b146103755780635ae6bd37146103a2578063610b5925146103cf578063694e80c3146103ef5761020d565b80632f54bf6e116101ab5780632f54bf6e146102ea5780633408e4701461030a578063468721a7146103275780635229073f146103475761020d565b80630d582f131461027357806312fb68e0146102955780632d9ad53d146102b55761020d565b3661020d5760405134815233907f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d9060200160405180910390a2005b34801561021957600080fd5b507f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d580548061024457005b36600080373360601b365260008060143601600080855af190503d6000803e8061026d573d6000fd5b503d6000f35b34801561027f57600080fd5b5061029361028e366004613568565b6106e5565b005b3480156102a157600080fd5b506102936102b036600461366e565b610933565b3480156102c157600080fd5b506102d56102d03660046136e3565b610ff7565b60405190151581526020015b60405180910390f35b3480156102f657600080fd5b506102d56103053660046136e3565b61104c565b34801561031657600080fd5b50465b6040519081526020016102e1565b34801561033357600080fd5b506102d561034236600461370f565b61109e565b34801561035357600080fd5b5061036761036236600461370f565b6111d4565b6040516102e19291906137e4565b34801561038157600080fd5b506103956103903660046137ff565b61120a565b6040516102e19190613821565b3480156103ae57600080fd5b506103196103bd366004613834565b60076020526000908152604090205481565b3480156103db57600080fd5b506102936103ea3660046136e3565b611290565b3480156103fb57600080fd5b5061029361040a366004613834565b611479565b6102d561041d366004613896565b611593565b34801561042e57600080fd5b5061031961043d366004613568565b600860209081526000928352604080842090915290825290205481565b34801561046657600080fd5b5061029361047536600461396f565b61198f565b34801561048657600080fd5b5061048f611a0b565b6040516102e19190613a2d565b3480156104a857600080fd5b5061031960055481565b3480156104be57600080fd5b506102936104cd366004613a40565b611b23565b3480156104de57600080fd5b506102936104ed366004613a90565b611b46565b3480156104fe57600080fd5b5061051261050d366004613568565b611c62565b6040516102e1929190613b85565b34801561052c57600080fd5b5061029361053b366004613834565b611ed0565b34801561054c57600080fd5b5061031961055b366004613bbd565b611fa4565b34801561056c57600080fd5b5061029361057b366004613c7e565b611fd1565b34801561058c57600080fd5b5061029361059b3660046136e3565b6121a3565b3480156105ac57600080fd5b506102936105bb366004613cb7565b612344565b3480156105cc57600080fd5b50600454610319565b3480156105e157600080fd5b506103956105f0366004613bbd565b6126bc565b34801561060157600080fd5b506102936106103660046136e3565b612855565b34801561062157600080fd5b5061031960007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b34801561068857600080fd5b50610293610697366004613d02565b6128aa565b3480156106a857600080fd5b506103956040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b6106ed612b34565b73ffffffffffffffffffffffffffffffffffffffff821615801590610729575073ffffffffffffffffffffffffffffffffffffffff8216600114155b801561074b575073ffffffffffffffffffffffffffffffffffffffff82163014155b6107b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600260205260409020541615610845576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b60026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0805473ffffffffffffffffffffffffffffffffffffffff8481166000818152604081208054939094167fffffffffffffffffffffffff0000000000000000000000000000000000000000938416179093556001835283549091161790915560038054916108d783613d72565b909155505060405173ffffffffffffffffffffffffffffffffffffffff8316907f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2690600090a2806004541461092f5761092f81611479565b5050565b61093e816041612b9f565b825110156109a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6000808060008060005b86811015610feb576041818102890160208101516040820151919092015160ff16955090935091506000849003610cf857885160208a01208a14610a52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323700000000000000000000000000000000000000000000000000000060448201526064016107ad565b9193508391610a62876041612b9f565b821015610acb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323100000000000000000000000000000000000000000000000000000060448201526064016107ad565b8751610ad8836020612bdb565b1115610b40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323200000000000000000000000000000000000000000000000000000060448201526064016107ad565b602082890181015189519091610b63908390610b5d908790612bdb565b90612bdb565b1115610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323300000000000000000000000000000000000000000000000000000060448201526064016107ad565b6040517f20c13b0b000000000000000000000000000000000000000000000000000000008082528a85016020019173ffffffffffffffffffffffffffffffffffffffff8916906320c13b0b90610c27908f908690600401613daa565b602060405180830381865afa158015610c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c689190613dcf565b7fffffffff000000000000000000000000000000000000000000000000000000001614610cf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323400000000000000000000000000000000000000000000000000000060448201526064016107ad565b5050610eeb565b8360ff16600103610dc65791935083913373ffffffffffffffffffffffffffffffffffffffff84161480610d5b575073ffffffffffffffffffffffffffffffffffffffff851660009081526008602090815260408083208d845290915290205415155b610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323500000000000000000000000000000000000000000000000000000060448201526064016107ad565b610eeb565b601e8460ff161115610e8b576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018b9052600190605c0160405160208183030381529060405280519060200120600486610e2b9190613e11565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610e7a573d6000803e3d6000fd5b505050602060405103519450610eeb565b6040805160008152602081018083528c905260ff861691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa158015610ede573d6000803e3d6000fd5b5050506020604051035194505b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16118015610f4c575073ffffffffffffffffffffffffffffffffffffffff8581166000908152600260205260409020541615155b8015610f6f575073ffffffffffffffffffffffffffffffffffffffff8516600114155b610fd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323600000000000000000000000000000000000000000000000000000060448201526064016107ad565b8495508080610fe390613d72565b9150506109b2565b50505050505050505050565b6000600173ffffffffffffffffffffffffffffffffffffffff831614801590611046575073ffffffffffffffffffffffffffffffffffffffff8281166000908152600160205260409020541615155b92915050565b600073ffffffffffffffffffffffffffffffffffffffff821660011480159061104657505073ffffffffffffffffffffffffffffffffffffffff90811660009081526002602052604090205416151590565b6000336001148015906110d557503360009081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff1615155b61113b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b611168858585857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612bf7565b905080156111a05760405133907f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb890600090a26111cc565b60405133907facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37590600090a25b949350505050565b600060606111e48686868661109e565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b60606000611219836020613e34565b67ffffffffffffffff81111561123157611231613594565b6040519080825280601f01601f19166020018201604052801561125b576020820181803683370190505b50905060005b8381101561128857848101546020808302840101528061128081613d72565b915050611261565b509392505050565b611298612b34565b73ffffffffffffffffffffffffffffffffffffffff8116158015906112d4575073ffffffffffffffffffffffffffffffffffffffff8116600114155b61133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff81811660009081526001602052604090205416156113c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b600160208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f805473ffffffffffffffffffffffffffffffffffffffff848116600081815260408082208054949095167fffffffffffffffffffffffff000000000000000000000000000000000000000094851617909455948552835490911681179092555190917fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844091a250565b611481612b34565b6003548111156114ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001811015611558576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b60048190556040518181527f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c939060200160405180910390a150565b60008060006115ad8e8e8e8e8e8e8e8e8e8e6005546126bc565b6005805491925060006115bf83613d72565b90915550508051602082012091506115d882828661198f565b5060006116037f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c85490565b905073ffffffffffffffffffffffffffffffffffffffff8116156116a3578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b81526004016116709c9b9a99989796959493929190613edb565b600060405180830381600087803b15801561168a57600080fd5b505af115801561169e573d6000803e3d6000fd5b505050505b6116cf6116b28a6109c4613ff1565b603f6116bf8c6040613e34565b6116c99190614009565b90612c3e565b6116db906101f4613ff1565b5a1015611744576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313000000000000000000000000000000000000000000000000000000060448201526064016107ad565b60005a90506117b58f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8c6000146117a2578e612bf7565b6109c45a6117b09190614044565b612bf7565b93506117c25a8290612c55565b905083806117cf57508915155b806117d957508715155b61183f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313300000000000000000000000000000000000000000000000000000060448201526064016107ad565b6000881561185757611854828b8b8b8b612c70565b90505b841561189c57837f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e8260405161188f91815260200190565b60405180910390a26118d7565b837f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23826040516118ce91815260200190565b60405180910390a25b505073ffffffffffffffffffffffffffffffffffffffff81161561197e576040517f9327136800000000000000000000000000000000000000000000000000000000815260048101839052831515602482015273ffffffffffffffffffffffffffffffffffffffff821690639327136890604401600060405180830381600087803b15801561196557600080fd5b505af1158015611979573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b600454806119f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b611a0584848484610933565b50505050565b6060600060035467ffffffffffffffff811115611a2a57611a2a613594565b604051908082528060200260200182016040528015611a53578160200160208202803683370190505b506001600090815260026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0549192509073ffffffffffffffffffffffffffffffffffffffff165b73ffffffffffffffffffffffffffffffffffffffff8116600114611b1b5780838381518110611ace57611ace61405b565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152918116600090815260029092526040909120541681611b1381613d72565b925050611a9d565b509092915050565b600080825160208401855af480600052503d6020523d600060403e60403d016000fd5b611b848a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9250612e01915050565b73ffffffffffffffffffffffffffffffffffffffff841615611ba957611ba9846131ce565b611be98787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061327192505050565b8115611c0057611bfe82600060018685612c70565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b89604051611c4e95949392919061408a565b60405180910390a250505050505050505050565b6060600073ffffffffffffffffffffffffffffffffffffffff841660011480611c8f5750611c8f84610ff7565b611cf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b60008311611d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303600000000000000000000000000000000000000000000000000000060448201526064016107ad565b8267ffffffffffffffff811115611d7857611d78613594565b604051908082528060200260200182016040528015611da1578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff808616600090815260016020526040812054929450911691505b73ffffffffffffffffffffffffffffffffffffffff821615801590611e0d575073ffffffffffffffffffffffffffffffffffffffff8216600114155b8015611e1857508381105b15611e805781838281518110611e3057611e3061405b565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152928116600090815260019093526040909220549091169080611e7881613d72565b915050611dd1565b73ffffffffffffffffffffffffffffffffffffffff8216600114611ec55782611eaa600183614044565b81518110611eba57611eba61405b565b602002602001015191505b808352509250929050565b3360009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16611f5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333000000000000000000000000000000000000000000000000000000060448201526064016107ad565b336000818152600860209081526040808320858452909152808220600190555183917ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c91a350565b6000611fb98c8c8c8c8c8c8c8c8c8c8c6126bc565b8051906020012090509b9a5050505050505050505050565b611fd9612b34565b73ffffffffffffffffffffffffffffffffffffffff811615801590612015575073ffffffffffffffffffffffffffffffffffffffff8116600114155b61207b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526001602052604090205481169082161461210e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff818116600081815260016020526040808220805487861684528284208054919096167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179095558383528054909416909355915190917faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427691a25050565b6121ab612b34565b73ffffffffffffffffffffffffffffffffffffffff8116156122db576040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527fe6d7a83a00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015612251573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122759190614110565b6122db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475333303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c881815560405173ffffffffffffffffffffffffffffffffffffffff8316907f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa290600090a25050565b61234c612b34565b73ffffffffffffffffffffffffffffffffffffffff811615801590612388575073ffffffffffffffffffffffffffffffffffffffff8116600114155b80156123aa575073ffffffffffffffffffffffffffffffffffffffff81163014155b612410576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff818116600090815260026020526040902054161561249f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8216158015906124db575073ffffffffffffffffffffffffffffffffffffffff8216600114155b612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600260205260409020548116908316146125d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805486861680855283852080549288167fffffffffffffffffffffffff00000000000000000000000000000000000000009384161790559589168452828420805482169096179095558383528054909416909355915190917ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf91a260405173ffffffffffffffffffffffffffffffffffffffff8216907f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2690600090a2505050565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d6040516126f6929190614132565b60405190819003812061271c949392918e908e908e908e908e908e908e90602001614142565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012090507f19000000000000000000000000000000000000000000000000000000000000007f01000000000000000000000000000000000000000000000000000000000000006127f060007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b6040517fff0000000000000000000000000000000000000000000000000000000000000093841660208201529290911660218301526022820152604281018290526062016040516020818303038152906040529150509b9a5050505050505050505050565b61285d612b34565b612866816131ce565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b090600090a250565b6128b2612b34565b8060016003546128c29190614044565b101561292a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff821615801590612966575073ffffffffffffffffffffffffffffffffffffffff8216600114155b6129cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff838116600090815260026020526040902054811690831614612a5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805488861684529183208054929095167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790945591815282549091169091556003805491612ad7836141bf565b909155505060405173ffffffffffffffffffffffffffffffffffffffff8316907ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf90600090a28060045414612b2f57612b2f81611479565b505050565b333014612b9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333100000000000000000000000000000000000000000000000000000060448201526064016107ad565b565b600082600003612bb157506000611046565b6000612bbd8385613e34565b905082612bca8583614009565b14612bd457600080fd5b9392505050565b600080612be88385613ff1565b905083811015612bd457600080fd5b60006001836001811115612c0d57612c0d613e71565b03612c25576000808551602087018986f49050612c35565b600080855160208701888a87f190505b95945050505050565b600081831015612c4e5781612bd4565b5090919050565b600082821115612c6457600080fd5b60006111cc8385614044565b60008073ffffffffffffffffffffffffffffffffffffffff831615612c955782612c97565b325b905073ffffffffffffffffffffffffffffffffffffffff8416612d7657612cd63a8610612cc4573a612cc6565b855b612cd08989612bdb565b90612b9f565b60405190925073ffffffffffffffffffffffffffffffffffffffff82169083156108fc029084906000818181858888f19350505050612d71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313100000000000000000000000000000000000000000000000000000060448201526064016107ad565b612df7565b612d8485612cd08989612bdb565b9150612d91848284613469565b612df7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313200000000000000000000000000000000000000000000000000000060448201526064016107ad565b5095945050505050565b60045415612e6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b8151811115612ed6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001811015612f41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b600160005b8351811015613176576000848281518110612f6357612f6361405b565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015612fc1575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015612fe3575073ffffffffffffffffffffffffffffffffffffffff81163014155b801561301b57508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b613081576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600260205260409020541615613110576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff928316600090815260026020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016938216939093179092558061316e81613d72565b915050612f46565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260026020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790559051600355600455565b3073ffffffffffffffffffffffffffffffffffffffff82160361324d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475334303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b7f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d555565b600160008190526020527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f5473ffffffffffffffffffffffffffffffffffffffff161561331a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001600081905260208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f80547fffffffffffffffffffffffff000000000000000000000000000000000000000016909117905573ffffffffffffffffffffffffffffffffffffffff82161561092f57813b6133f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b6134038260008360015a612bf7565b61092f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6040805173ffffffffffffffffffffffffffffffffffffffff841660248201526044808201849052825180830390910181526064909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781528251600093929184919082896127105a03f13d8015613516576020811461351e5760009350613529565b819350613529565b600051158215171593505b5050509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461355557600080fd5b50565b803561356381613533565b919050565b6000806040838503121561357b57600080fd5b823561358681613533565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126135d457600080fd5b813567ffffffffffffffff808211156135ef576135ef613594565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561363557613635613594565b8160405283815286602085880101111561364e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561368457600080fd5b84359350602085013567ffffffffffffffff808211156136a357600080fd5b6136af888389016135c3565b945060408701359150808211156136c557600080fd5b506136d2878288016135c3565b949793965093946060013593505050565b6000602082840312156136f557600080fd5b8135612bd481613533565b80356002811061356357600080fd5b6000806000806080858703121561372557600080fd5b843561373081613533565b935060208501359250604085013567ffffffffffffffff81111561375357600080fd5b61375f878288016135c3565b92505061376e60608601613700565b905092959194509250565b6000815180845260005b8181101561379f57602081850181015186830182015201613783565b818111156137b1576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b82151581526040602082015260006111cc6040830184613779565b6000806040838503121561381257600080fd5b50508035926020909101359150565b602081526000612bd46020830184613779565b60006020828403121561384657600080fd5b5035919050565b60008083601f84011261385f57600080fd5b50813567ffffffffffffffff81111561387757600080fd5b60208301915083602082850101111561388f57600080fd5b9250929050565b60008060008060008060008060008060006101408c8e0312156138b857600080fd5b6138c18c613558565b9a5060208c0135995067ffffffffffffffff8060408e013511156138e457600080fd5b6138f48e60408f01358f0161384d565b909a50985061390560608e01613700565b975060808d0135965060a08d0135955060c08d0135945061392860e08e01613558565b93506139376101008e01613558565b9250806101208e0135111561394b57600080fd5b5061395d8d6101208e01358e016135c3565b90509295989b509295989b9093969950565b60008060006060848603121561398457600080fd5b83359250602084013567ffffffffffffffff808211156139a357600080fd5b6139af878388016135c3565b935060408601359150808211156139c557600080fd5b506139d2868287016135c3565b9150509250925092565b600081518084526020808501945080840160005b83811015613a2257815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016139f0565b509495945050505050565b602081526000612bd460208301846139dc565b60008060408385031215613a5357600080fd5b8235613a5e81613533565b9150602083013567ffffffffffffffff811115613a7a57600080fd5b613a86858286016135c3565b9150509250929050565b6000806000806000806000806000806101008b8d031215613ab057600080fd5b8a3567ffffffffffffffff80821115613ac857600080fd5b818d0191508d601f830112613adc57600080fd5b813581811115613aeb57600080fd5b8e60208260051b8501011115613b0057600080fd5b60208381019d50909b508d01359950613b1b60408e01613558565b985060608d0135915080821115613b3157600080fd5b50613b3e8d828e0161384d565b9097509550613b51905060808c01613558565b9350613b5f60a08c01613558565b925060c08b01359150613b7460e08c01613558565b90509295989b9194979a5092959850565b604081526000613b9860408301856139dc565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b60008060008060008060008060008060006101408c8e031215613bdf57600080fd5b8b35613bea81613533565b9a5060208c0135995060408c013567ffffffffffffffff811115613c0d57600080fd5b613c198e828f0161384d565b909a509850613c2c905060608d01613700565b965060808c0135955060a08c0135945060c08c0135935060e08c0135613c5181613533565b92506101008c0135613c6281613533565b809250506101208c013590509295989b509295989b9093969950565b60008060408385031215613c9157600080fd5b8235613c9c81613533565b91506020830135613cac81613533565b809150509250929050565b600080600060608486031215613ccc57600080fd5b8335613cd781613533565b92506020840135613ce781613533565b91506040840135613cf781613533565b809150509250925092565b600080600060608486031215613d1757600080fd5b8335613d2281613533565b92506020840135613d3281613533565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613da357613da3613d43565b5060010190565b604081526000613dbd6040830185613779565b8281036020840152612c358185613779565b600060208284031215613de157600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114612bd457600080fd5b600060ff821660ff841680821015613e2b57613e2b613d43565b90039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613e6c57613e6c613d43565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110613ed7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b600061016073ffffffffffffffffffffffffffffffffffffffff8f1683528d60208401528060408401528b81840152506101808b8d828501376000818d850101527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8d01168301613f51606085018d613ea0565b8a60808501528960a08501528860c0850152613f8560e085018973ffffffffffffffffffffffffffffffffffffffff169052565b73ffffffffffffffffffffffffffffffffffffffff87166101008501528184820301610120850152613fb982820187613779565b92505050613fe061014083018473ffffffffffffffffffffffffffffffffffffffff169052565b9d9c50505050505050505050505050565b6000821982111561400457614004613d43565b500190565b60008261403f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008282101561405657614056613d43565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6080808252810185905260008660a08301825b888110156140da5782356140b081613533565b73ffffffffffffffffffffffffffffffffffffffff1682526020928301929091019060010161409d565b506020840196909652505073ffffffffffffffffffffffffffffffffffffffff9283166040820152911660609091015292915050565b60006020828403121561412257600080fd5b81518015158114612bd457600080fd5b8183823760009101908152919050565b6000610160820190508c825273ffffffffffffffffffffffffffffffffffffffff808d1660208401528b60408401528a6060840152614184608084018b613ea0565b60a083019890985260c082019690965260e0810194909452918516610100840152909316610120820152610140019190915295945050505050565b6000816141ce576141ce613d43565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x90193C961A926261B756D1E5bb255e67ff9498A1","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000004"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x34A1D3fff3958843C43aD80F30b94c510645C316","chainInfo":{"chainId":31337,"forkId":0},"data":"0x1688f0b900000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000164b63e800d0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x34A1D3fff3958843C43aD80F30b94c510645C316","account":"0x90193C961A926261B756D1E5bb255e67ff9498A1","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x34A1D3fff3958843C43aD80F30b94c510645C316","account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0x608060405234801561001057600080fd5b5060405161016f38038061016f83398101604081905261002f916100b9565b6001600160a01b0381166100945760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642073696e676c65746f6e20616464726573732070726f766964604482015261195960f21b606482015260840160405180910390fd5b600080546001600160a01b0319166001600160a01b03929092169190911790556100e9565b6000602082840312156100cb57600080fd5b81516001600160a01b03811681146100e257600080fd5b9392505050565b6078806100f76000396000f3fe6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000a00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1","deployedCode":"0x6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":true,"newValue":"0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x34A1D3fff3958843C43aD80F30b94c510645C316","account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0xb63e800d0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1","previousValue":"0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x34A1D3fff3958843C43aD80F30b94c510645C316","account":"0x90193C961A926261B756D1E5bb255e67ff9498A1","chainInfo":{"chainId":31337,"forkId":0},"data":"0xb63e800d0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000004"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":true,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000003"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000004"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","chainInfo":{"chainId":31337,"forkId":0},"data":"0x608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6105ef8061007e6000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80639b2ea4bd116100505780639b2ea4bd146100b9578063bf40fac1146100cc578063f2fde38b146100df57600080fd5b8063715018a61461006c5780638da5cb5b14610076575b600080fd5b6100746100f2565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100746100c73660046104fa565b610106565b6100906100da366004610548565b6101d9565b6100746100ed366004610585565b610215565b6100fa6102d1565b6101046000610352565b565b61010e6102d1565b6000610119836103c7565b60008181526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff8681167fffffffffffffffffffffffff00000000000000000000000000000000000000008316179092559151929350169061017c9085906105a7565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b6000600160006101e8846103c7565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1692915050565b61021d6102d1565b73ffffffffffffffffffffffffffffffffffffffff81166102c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102ce81610352565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610104576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102bc565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816040516020016103da91906105a7565b604051602081830303815290604052805190602001209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261043757600080fd5b813567ffffffffffffffff80821115610452576104526103f7565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610498576104986103f7565b816040528381528660208588010111156104b157600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b919050565b6000806040838503121561050d57600080fd5b823567ffffffffffffffff81111561052457600080fd5b61053085828601610426565b92505061053f602084016104d1565b90509250929050565b60006020828403121561055a57600080fd5b813567ffffffffffffffff81111561057157600080fd5b61057d84828501610426565b949350505050565b60006020828403121561059757600080fd5b6105a0826104d1565b9392505050565b6000825160005b818110156105c857602081860181015185830152016105ae565b818111156105d7576000828501525b50919091019291505056fea164736f6c634300080f000a","deployedCode":"0x608060405234801561001057600080fd5b50600436106100675760003560e01c80639b2ea4bd116100505780639b2ea4bd146100b9578063bf40fac1146100cc578063f2fde38b146100df57600080fd5b8063715018a61461006c5780638da5cb5b14610076575b600080fd5b6100746100f2565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100746100c73660046104fa565b610106565b6100906100da366004610548565b6101d9565b6100746100ed366004610585565b610215565b6100fa6102d1565b6101046000610352565b565b61010e6102d1565b6000610119836103c7565b60008181526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff8681167fffffffffffffffffffffffff00000000000000000000000000000000000000008316179092559151929350169061017c9085906105a7565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b6000600160006101e8846103c7565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1692915050565b61021d6102d1565b73ffffffffffffffffffffffffffffffffffffffff81166102c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102ce81610352565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610104576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102bc565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816040516020016103da91906105a7565b604051602081830303815290604052805190602001209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261043757600080fd5b813567ffffffffffffffff80821115610452576104526103f7565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610498576104986103f7565b816040528381528660208588010111156104b157600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b919050565b6000806040838503121561050d57600080fd5b823567ffffffffffffffff81111561052457600080fd5b61053085828601610426565b92505061053f602084016104d1565b90509250929050565b60006020828403121561055a57600080fd5b813567ffffffffffffffff81111561057157600080fd5b61057d84828501610426565b949350505050565b60006020828403121561059757600080fd5b6105a0826104d1565b9392505050565b6000825160005b818110156105c857602081860181015185830152016105ae565b818111156105d7576000828501525b50919091019291505056fea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","isWrite":true,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","chainInfo":{"chainId":31337,"forkId":0},"data":"0x8da5cb5b","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","isWrite":false,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","chainInfo":{"chainId":31337,"forkId":0},"data":"0x60806040523480156200001157600080fd5b5060405162001a5f38038062001a5f8339810160408190526200003491620000a1565b6200003f3362000051565b6200004a8162000051565b50620000d3565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215620000b457600080fd5b81516001600160a01b0381168114620000cc57600080fd5b9392505050565b61197c80620000e36000396000f3fe60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","deployedCode":"0x60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":true,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":true,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","chainInfo":{"chainId":31337,"forkId":0},"data":"0x8da5cb5b","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","chainInfo":{"chainId":31337,"forkId":0},"data":"0x3ab76e9f","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000003"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","chainInfo":{"chainId":31337,"forkId":0},"data":"0x0652b57a000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000003"},{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":true,"newValue":"0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000003"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","chainInfo":{"chainId":31337,"forkId":0},"data":"0x3ab76e9f","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3","previousValue":"0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000003"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","chainInfo":{"chainId":31337,"forkId":0},"data":"0x8da5cb5b","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","chainInfo":{"chainId":31337,"forkId":0},"data":"0xf2fde38b0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":true,"newValue":"0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","chainInfo":{"chainId":31337,"forkId":0},"data":"0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","deployedCode":"0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"},{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":true,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x4e59b44847b379578588920cA78FbF26c0B4956C","account":"0x068E44eB31e111028c41598E4535be7468674D0A","chainInfo":{"chainId":31337,"forkId":0},"data":"0x60806040523480156200001157600080fd5b506200001f60008062000025565b62000361565b600054610100900460ff1615808015620000465750600054600160ff909116105b8062000076575062000063306200019460201b620005fd1760201c565b15801562000076575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b6200010d83620001a3565b81156200014857604080518082019091526012815271125b9a5d1a585b1a5e995c881c185d5cd95960721b6020820152620001489062000248565b80156200018f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b620001e9620001d460017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69620002cf565b60001b82620002cb60201b620006191760201c565b6000604080516001600160a01b03841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb910160408051601f19818403018152908290526200023d9162000345565b60405180910390a250565b6200028f6200027960017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7620002cf565b60001b6001620002cb60201b620006191760201c565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea2838181604051620002c0919062000345565b60405180910390a150565b9055565b600082821015620002f057634e487b7160e01b600052601160045260246000fd5b500390565b6000815180845260005b818110156200031d57602081850181015186830182015201620002ff565b8181111562000330576000602083870101525b50601f01601f19169290920160200192915050565b6020815260006200035a6020830184620002f5565b9392505050565b61096b80620003716000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a","deployedCode":"0x608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x068E44eB31e111028c41598E4535be7468674D0A","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x068E44eB31e111028c41598E4535be7468674D0A","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x068E44eB31e111028c41598E4535be7468674D0A","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x068E44eB31e111028c41598E4535be7468674D0A","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x068E44eB31e111028c41598E4535be7468674D0A","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x068E44eB31e111028c41598E4535be7468674D0A","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x068E44eB31e111028c41598E4535be7468674D0A","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68"},{"account":"0x068E44eB31e111028c41598E4535be7468674D0A","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x068E44eB31e111028c41598E4535be7468674D0A","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x068E44eB31e111028c41598E4535be7468674D0A","chainInfo":{"chainId":31337,"forkId":0},"data":"0x452a9320","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x068E44eB31e111028c41598E4535be7468674D0A","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xfa60f9b2","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000000e"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1","previousValue":"0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x90193C961A926261B756D1E5bb255e67ff9498A1","chainInfo":{"chainId":31337,"forkId":0},"data":"0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000005"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000005"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000005"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000004"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8"}],"value":0},{"accessor":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","chainInfo":{"chainId":31337,"forkId":0},"data":"0x9623609d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f","previousValue":"0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x070dca21862da24de5bcba7acd697f207bda1c8caae3812d68f0baee0dd32f38"}],"value":0},{"accessor":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","chainInfo":{"chainId":31337,"forkId":0},"data":"0x4f1ef286000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"},{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":true,"newValue":"0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","account":"0x068E44eB31e111028c41598E4535be7468674D0A","chainInfo":{"chainId":31337,"forkId":0},"data":"0x400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":true,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68"},{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xfa60f9b2","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000000e"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","chainInfo":{"chainId":31337,"forkId":0},"data":"0x452a9320","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a","previousValue":"0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x068E44eB31e111028c41598E4535be7468674D0A","chainInfo":{"chainId":31337,"forkId":0},"data":"0x452a9320","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","chainInfo":{"chainId":31337,"forkId":0},"data":"0x5c975abb","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a","previousValue":"0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x068E44eB31e111028c41598E4535be7468674D0A","chainInfo":{"chainId":31337,"forkId":0},"data":"0x5c975abb","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b6"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","chainInfo":{"chainId":31337,"forkId":0},"data":"0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","deployedCode":"0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":true,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x4e59b44847b379578588920cA78FbF26c0B4956C","account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0x60806040523480156200001157600080fd5b506200002261dead60008062000028565b6200051c565b600054610100900460ff1615808015620000495750600054600160ff909116105b8062000079575062000066306200017e60201b6200053f1760201c565b15801562000079575060005460ff166001145b620000e25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000106576000805461ff0019166101001790555b620001106200018d565b6200011b84620001f5565b620001268362000274565b620001318262000324565b801562000178576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b602482015260008051602062000f4f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d9565b620001f362000385565b565b620001ff620003ec565b6001600160a01b038116620002665760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620000d9565b620002718162000448565b50565b620002ba620002a560017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16200049e565b60001b826200049a60201b6200055b1760201c565b600081604051602001620002d091815260200190565b60408051601f19818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051620003189190620004c4565b60405180910390a35050565b62000355620002a560017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6200049e565b6000816040516020016200036b91815260200190565b60408051601f1981840301815291905290506001620002e5565b600054610100900460ff16620003e15760405162461bcd60e51b815260206004820152602b602482015260008051602062000f4f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d9565b620001f33362000448565b6033546001600160a01b03163314620001f35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620000d9565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b9055565b600082821015620004bf57634e487b7160e01b600052601160045260246000fd5b500390565b600060208083528351808285015260005b81811015620004f357858101830151858201604001528201620004d5565b8181111562000506576000604083870101525b50601f01601f1916929092016040019392505050565b610a23806200052c6000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069","deployedCode":"0x608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":true,"newValue":"0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":false,"newValue":"0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c","previousValue":"0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":false,"newValue":"0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c","previousValue":"0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":true,"newValue":"0x000000000000000000000000000000000000000000000000000000000000dead","previousValue":"0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace0"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1a"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0x8da5cb5b","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":false,"newValue":"0x000000000000000000000000000000000000000000000000000000000000dead","previousValue":"0x000000000000000000000000000000000000000000000000000000000000dead","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0xdc8452cd","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace0"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0xd798b1ac","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1a"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xd2354f20","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000000d"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x38c27159","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000035"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x67cef446","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000036"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d000000000000000000000000416c42991d05b31e9a6dc209e91ad22b79d87ae6000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000647a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1","previousValue":"0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x90193C961A926261B756D1E5bb255e67ff9498A1","chainInfo":{"chainId":31337,"forkId":0},"data":"0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d000000000000000000000000416c42991d05b31e9a6dc209e91ad22b79d87ae6000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000647a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000005"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000005"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000002","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000005"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000004"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8"}],"value":0},{"accessor":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","chainInfo":{"chainId":31337,"forkId":0},"data":"0x9623609d000000000000000000000000416c42991d05b31e9a6dc209e91ad22b79d87ae6000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000647a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f","previousValue":"0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x9d54a4eb6e745ee152f323ba7a05534bbe68629624a74c9623b7903663b002cf"}],"value":0},{"accessor":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","chainInfo":{"chainId":31337,"forkId":0},"data":"0x4f1ef286000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000647a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":true,"newValue":"0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0x7a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":true,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":true,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace0"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1a"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","chainInfo":{"chainId":31337,"forkId":0},"data":"0x54fd4d50","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f","previousValue":"0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0x54fd4d50","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xd2354f20","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000000d"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","chainInfo":{"chainId":31337,"forkId":0},"data":"0x8da5cb5b","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f","previousValue":"0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0x8da5cb5b","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x38c27159","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000035"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","chainInfo":{"chainId":31337,"forkId":0},"data":"0xdc8452cd","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f","previousValue":"0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0xdc8452cd","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace0"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x67cef446","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000036"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","chainInfo":{"chainId":31337,"forkId":0},"data":"0xd798b1ac","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f","previousValue":"0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0xd798b1ac","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1a"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x978e3286EB805934215a88694d80b09aDed68D90","chainInfo":{"chainId":31337,"forkId":0},"data":"0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","deployedCode":"0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":true,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x8B71b41D4dBEb2b6821d44692d3fACAAf77480Bb","chainInfo":{"chainId":31337,"forkId":0},"data":"0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","deployedCode":"0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x8B71b41D4dBEb2b6821d44692d3fACAAf77480Bb","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"},{"account":"0x8B71b41D4dBEb2b6821d44692d3fACAAf77480Bb","isWrite":true,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","chainInfo":{"chainId":31337,"forkId":0},"data":"0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","deployedCode":"0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":true,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","chainInfo":{"chainId":31337,"forkId":0},"data":"0x8da5cb5b","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","isWrite":false,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","chainInfo":{"chainId":31337,"forkId":0},"data":"0xf2fde38b000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","isWrite":false,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","isWrite":false,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","isWrite":true,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","chainInfo":{"chainId":31337,"forkId":0},"data":"0x8da5cb5b","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3","isWrite":false,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x4e59b44847b379578588920cA78FbF26c0B4956C","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0x60c06040523480156200001157600080fd5b5060405162005777380380620057778339810160408190526200003491620002ba565b6001600160a01b03808316608052811660a0526200005360006200005b565b5050620002f9565b600054610100900460ff16158080156200007c5750600054600160ff909116105b80620000ac57506200009930620001d360201b62001bcd1760201c565b158015620000ac575060005460ff166001145b620001155760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000139576000805461ff0019166101001790555b603580546001600160a01b0380851661010002610100600160a81b031990921691909117909155603254166200017e57603280546001600160a01b03191661dead1790555b62000188620001e2565b8015620001cf576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff166200024f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200010c565b600154600160c01b90046001600160401b03166000036200029f5760408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b02176001555b565b6001600160a01b0381168114620002b757600080fd5b50565b60008060408385031215620002ce57600080fd5b8251620002db81620002a1565b6020840151909250620002ee81620002a1565b809150509250929050565b60805160a0516154196200035e600039600081816101fb01528181610591015261220e0152600081816101a00152818161036501528181610a4601528181610c270152818161102c015281816112d4015281816115460152611fca01526154196000f3fe6080604052600436106101625760003560e01c80638c3152e9116100c0578063c4d66de811610074578063e965084c11610059578063e965084c146104e0578063e9e05c421461056c578063f04987501461057f57600080fd5b8063c4d66de81461041f578063cff0ab961461043f57600080fd5b80639bf62d82116100a55780639bf62d8214610389578063a14238e7146103b6578063a35d99df146103e657600080fd5b80638c3152e9146103365780639b5f694a1461035657600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb7814610301578063724c184c146103215780638b4c40b01461018757600080fd5b806354fd4d50146102865780635c975abb146102dc57600080fd5b806335e80ab31161014857806335e80ab31461021f578063452a9320146102515780634870496f1461026657600080fd5b80621c2ff61461018e57806333d7e2bd146101ec57600080fd5b36610189576101873334620186a06000604051806020016040528060008152506105b3565b005b600080fd5b34801561019a57600080fd5b506101c27f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101f857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c2565b34801561022b57600080fd5b506035546101c290610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561025d57600080fd5b506101c261084e565b34801561027257600080fd5b50610187610281366004614a0a565b6108e6565b34801561029257600080fd5b506102cf6040518060400160405280600581526020017f322e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516101e39190614b60565b3480156102e857600080fd5b506102f1610f4e565b60405190151581526020016101e3565b34801561030d57600080fd5b506102f161031c366004614b73565b610fe1565b34801561032d57600080fd5b506101c26110b8565b34801561034257600080fd5b50610187610351366004614b8c565b6110c4565b34801561036257600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c2565b34801561039557600080fd5b506032546101c29073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103c257600080fd5b506102f16103d1366004614b73565b60336020526000908152604090205460ff1681565b3480156103f257600080fd5b50610406610401366004614be6565b6119a1565b60405167ffffffffffffffff90911681526020016101e3565b34801561042b57600080fd5b5061018761043a366004614c01565b6119ba565b34801561044b57600080fd5b506001546104a7906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101e3565b3480156104ec57600080fd5b5061053e6104fb366004614b73565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101e3565b61018761057a366004614c2c565b6105b3565b34801561058b57600080fd5b506101c27f000000000000000000000000000000000000000000000000000000000000000081565b8260005a9050831561066a5773ffffffffffffffffffffffffffffffffffffffff87161561066a57604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b61067483516119a1565b67ffffffffffffffff168567ffffffffffffffff161015610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c00000000000000000000000000000000000000000000000000000000006064820152608401610661565b6201d4c083511115610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c6172676500006044820152606401610661565b333281146107a6575033731111000000000000000000000000000000001111015b600034888888886040516020016107c1959493929190614ca9565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516108319190614b60565b60405180910390a450506108458282611be9565b50505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190614d0e565b905090565b6108ee610f4e565b15610955576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610661565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610a14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610661565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610aa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac69190614d4b565b519050610ae0610adb36869003860186614db0565b611f16565b8114610b6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610661565b6000610b7987611f72565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610cab5750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190614d4b565b5114155b610d37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610661565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610e009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610df6888a614e16565b8a60400135611fa2565b610e8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610661565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fbd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190614e9a565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018290526000906110b29073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa158015611073573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110979190614d4b565b602001516fffffffffffffffffffffffffffffffff16611fc6565b92915050565b60006108e161084e565b565b6110cc610f4e565b15611133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610661565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead146111dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610661565b60006111e782611f72565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036112d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610661565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa15801561133d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113619190614eb7565b81602001516fffffffffffffffffffffffffffffffff16101561142c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610661565b61144b81602001516fffffffffffffffffffffffffffffffff16611fc6565b6114fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610661565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c69190614d4b565b8251815191925014611680576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610661565b61169f81602001516fffffffffffffffffffffffffffffffff16611fc6565b611751576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610661565b60008381526033602052604090205460ff16156117f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610661565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a088015161189293929190612069565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906118f790841515815260200190565b60405180910390a28015801561190d5750326001145b1561199a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610661565b5050505050565b60006119ae826010614eff565b6110b290615208614f2f565b600054610100900460ff16158080156119da5750600054600160ff909116105b806119f45750303b1580156119f4575060005460ff166001145b611a80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610661565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611ade57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6035805473ffffffffffffffffffffffffffffffffffffffff808516610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff9092169190911790915560325416611b5e57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611b666120c7565b8015611bc957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611c1f907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643614f5b565b90506000611c2b6121da565b90506000816020015160ff16826000015163ffffffff16611c4c9190614fa1565b90508215611d8357600154600090611c83908390700100000000000000000000000000000000900467ffffffffffffffff16615009565b90506000836040015160ff1683611c9a919061507d565b600154611cba9084906fffffffffffffffffffffffffffffffff1661507d565b611cc49190614fa1565b600154909150600090611d1590611cee9084906fffffffffffffffffffffffffffffffff16615139565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff1661229b565b90506001861115611d4457611d41611cee82876040015160ff1660018a611d3c9190614f5b565b6122ba565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611db6908490700100000000000000000000000000000000900467ffffffffffffffff16614f2f565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611e99576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d697400006064820152608401610661565b600154600090611ec5906fffffffffffffffffffffffffffffffff1667ffffffffffffffff88166151ad565b90506000611ed748633b9aca0061230f565b611ee190836151ea565b905060005a611ef09088614f5b565b905080821115611f0c57611f0c611f078284614f5b565b612326565b5050505050505050565b60008160000151826020015183604001518460600151604051602001611f55949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097611f559790969591016151fe565b600080611fae86612354565b9050611fbc81868686612386565b9695505050505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa158015612033573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120579190614eb7565b6120619083615255565b421192915050565b60008060006120798660006123b6565b9050806120af576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff1661215e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610661565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036110c25760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663cc731b026040518163ffffffff1660e01b815260040160c060405180830381865afa158015612277573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190615292565b60006122b06122aa85856123d4565b836123e4565b90505b9392505050565b6000670de0b6b3a76400006122fb6122d28583614fa1565b6122e490670de0b6b3a7640000615009565b6122f685670de0b6b3a764000061507d565b6123f3565b612305908661507d565b6122b09190614fa1565b60008183101561231f57816122b3565b5090919050565b6000805a90505b825a6123399083614f5b565b101561234f5761234882615331565b915061232d565b505050565b6060818051906020012060405160200161237091815260200190565b6040516020818303038152906040529050919050565b60006123ad84612397878686612424565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b60008183121561231f57816122b3565b600081831261231f57816122b3565b60006122b3670de0b6b3a76400008361240b86612ea2565b612415919061507d565b61241f9190614fa1565b6130e6565b60606000845111612491576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610661565b600061249c84613325565b905060006124a986613411565b90506000846040516020016124c091815260200190565b60405160208183030381529060405290506000805b8451811015612e195760008582815181106124f2576124f2615369565b60200260200101519050845183111561258d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610661565b8260000361264657805180516020918201206040516125db926125b592910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612641576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610661565b61279d565b8051516020116126fc5780518051602091820120604051612670926125b592910190815260200190565b612641576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610661565b80518451602080870191909120825191909201201461279d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610661565b6127a960106001615255565b81602001515103612985578451830361291d576127e381602001516010815181106127d6576127d6615369565b6020026020010151613474565b96506000875111612876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610661565b600186516128849190614f5b565b8214612912576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610661565b5050505050506122b3565b600085848151811061293157612931615369565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061295c5761295c615369565b6020026020010151905061296f816135d4565b955061297c600186615255565b94505050612e06565b600281602001515103612d7e57600061299d826135f9565b90506000816000815181106129b4576129b4615369565b016020015160f81c905060006129cb600283615398565b6129d69060026153ba565b905060006129e7848360ff1661361d565b905060006129f58a8961361d565b90506000612a038383613653565b905080835114612a95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610661565b60ff851660021480612aaa575060ff85166003145b15612c995780825114612b3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610661565b612b5987602001516001815181106127d6576127d6615369565b9c5060008d5111612bec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610661565b60018c51612bfa9190614f5b565b8814612c88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610661565b5050505050505050505050506122b3565b60ff85161580612cac575060ff85166001145b15612ceb57612cd88760200151600181518110612ccb57612ccb615369565b60200260200101516135d4565b9950612ce4818a615255565b9850612d73565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610661565b505050505050612e06565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610661565b5080612e1181615331565b9150506124d5565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610661565b6000808213612f0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610661565b60006060612f1a84613707565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361311757506000919050565b680755bf798b4a1bf1e58212613189576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610661565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff8111156133435761334361482a565b60405190808252806020026020018201604052801561338857816020015b60408051808201909152606080825260208201528152602001906001900390816133615790505b50915060005b8181101561340a5760405180604001604052808583815181106133b3576133b3615369565b602002602001015181526020016133e28684815181106133d5576133d5615369565b60200260200101516137dd565b8152508382815181106133f7576133f7615369565b602090810291909101015260010161338e565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613469578060011b82018184015160001a8060041c8253600f81166001830153505060010161343b565b509295945050505050565b60606000806000613484856137f0565b91945092509050600081600181111561349f5761349f6153dd565b1461352c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d000000000000006064820152608401610661565b6135368284615255565b8551146135c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e6465720000000000000000000000006064820152608401610661565b6123ad8560200151848461425d565b606060208260000151106135f0576135eb82613474565b6110b2565b6110b2826142f1565b60606110b261361883602001516000815181106127d6576127d6615369565b613411565b60608251821061363c57506040805160208101909152600081526110b2565b6122b3838384865161364e9190614f5b565b614307565b6000808251845110613666578251613669565b83515b90505b80821080156136f0575082828151811061368857613688615369565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106136c7576136c7615369565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156137005781600101915061366c565b5092915050565b6000808211613772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610661565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60606110b26137eb836144df565b6145c8565b6000806000808460000151116138ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610661565b6020840151805160001a607f81116138d3576000600160009450945094505050614256565b60b78111613ae15760006138e8608083614f5b565b9050808760000151116139a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a401610661565b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082141580613a1c57507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613ace576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a401610661565b5060019550935060009250614256915050565b60bf8111613e2f576000613af660b783614f5b565b905080876000015111613bb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a401610661565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613c8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a401610661565b600184015160088302610100031c60378111613d53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a401610661565b613d5d8184615255565b895111613e12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a401610661565b613e1d836001615255565b97509550600094506142569350505050565b60f78111613f10576000613e4460c083614f5b565b905080876000015111613eff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a401610661565b600195509350849250614256915050565b6000613f1d60f783614f5b565b905080876000015111613fd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a401610661565b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036140b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a401610661565b600184015160088302610100031c6037811161417a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a401610661565b6141848184615255565b895111614239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a401610661565b614244836001615255565b97509550600194506142569350505050565b9193909250565b60608167ffffffffffffffff8111156142785761427861482a565b6040519080825280601f01601f1916602001820160405280156142a2576020820181803683370190505b50905081156122b35760006142b78486615255565b90506020820160005b848110156142d85782810151828201526020016142c0565b848111156142e7576000858301525b5050509392505050565b60606110b282602001516000846000015161425d565b60608182601f011015614376576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610661565b8282840110156143e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610661565b8183018451101561444f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610661565b60608215801561446e57604051915060008252602082016040526144d6565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156144a757805183526020928301920161448f565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b604080518082019091526000808252602082015260008251116145aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610661565b50604080518082019091528151815260209182019181019190915290565b606060008060006145d8856137f0565b9194509250905060018160018111156145f3576145f36153dd565b14614680576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d00000000000000006064820152608401610661565b845161468c8385615255565b14614719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e64657200000000000000000000000000006064820152608401610661565b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816147305790505093506000835b865181101561481e576000806147a36040518060400160405280858c600001516147879190614f5b565b8152602001858c6020015161479c9190615255565b90526137f0565b5091509150604051806040016040528083836147bf9190615255565b8152602001848b602001516147d49190615255565b8152508885815181106147e9576147e9615369565b60209081029190910101526147ff600185615255565b935061480b8183615255565b6148159084615255565b9250505061475d565b50845250919392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156148a0576148a061482a565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff811681146148ca57600080fd5b50565b600082601f8301126148de57600080fd5b813567ffffffffffffffff8111156148f8576148f861482a565b61492960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614859565b81815284602083860101111561493e57600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561496d57600080fd5b60405160c0810167ffffffffffffffff82821081831117156149915761499161482a565b8160405282935084358352602085013591506149ac826148a8565b816020840152604085013591506149c2826148a8565b816040840152606085013560608401526080850135608084015260a08501359150808211156149f057600080fd5b506149fd858286016148cd565b60a0830152505092915050565b600080600080600085870360e0811215614a2357600080fd5b863567ffffffffffffffff80821115614a3b57600080fd5b614a478a838b0161495b565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614a8057600080fd5b60408901955060c0890135925080831115614a9a57600080fd5b828901925089601f840112614aae57600080fd5b8235915080821115614abf57600080fd5b508860208260051b8401011115614ad557600080fd5b959894975092955050506020019190565b60005b83811015614b01578181015183820152602001614ae9565b83811115614b10576000848401525b50505050565b60008151808452614b2e816020860160208601614ae6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122b36020830184614b16565b600060208284031215614b8557600080fd5b5035919050565b600060208284031215614b9e57600080fd5b813567ffffffffffffffff811115614bb557600080fd5b614bc18482850161495b565b949350505050565b803567ffffffffffffffff81168114614be157600080fd5b919050565b600060208284031215614bf857600080fd5b6122b382614bc9565b600060208284031215614c1357600080fd5b81356122b3816148a8565b80151581146148ca57600080fd5b600080600080600060a08688031215614c4457600080fd5b8535614c4f816148a8565b945060208601359350614c6460408701614bc9565b92506060860135614c7481614c1e565b9150608086013567ffffffffffffffff811115614c9057600080fd5b614c9c888289016148cd565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614cfd816049850160208701614ae6565b919091016049019695505050505050565b600060208284031215614d2057600080fd5b81516122b3816148a8565b80516fffffffffffffffffffffffffffffffff81168114614be157600080fd5b600060608284031215614d5d57600080fd5b6040516060810181811067ffffffffffffffff82111715614d8057614d8061482a565b60405282518152614d9360208401614d2b565b6020820152614da460408401614d2b565b60408201529392505050565b600060808284031215614dc257600080fd5b6040516080810181811067ffffffffffffffff82111715614de557614de561482a565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614e3157614e3161482a565b8360051b6020614e42818301614859565b868152918501918181019036841115614e5a57600080fd5b865b84811015614e8e57803586811115614e745760008081fd5b614e8036828b016148cd565b845250918301918301614e5c565b50979650505050505050565b600060208284031215614eac57600080fd5b81516122b381614c1e565b600060208284031215614ec957600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615614f2657614f26614ed0565b02949350505050565b600067ffffffffffffffff808316818516808303821115614f5257614f52614ed0565b01949350505050565b600082821015614f6d57614f6d614ed0565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614fb057614fb0614f72565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561500457615004614ed0565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561504357615043614ed0565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561507757615077614ed0565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156150be576150be614ed0565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156150f9576150f9614ed0565b6000871292508782058712848416161561511557615115614ed0565b8785058712818416161561512b5761512b614ed0565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561517357615173614ed0565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156151a7576151a7614ed0565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156151e5576151e5614ed0565b500290565b6000826151f9576151f9614f72565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261524960c0830184614b16565b98975050505050505050565b6000821982111561526857615268614ed0565b500190565b805163ffffffff81168114614be157600080fd5b805160ff81168114614be157600080fd5b600060c082840312156152a457600080fd5b60405160c0810181811067ffffffffffffffff821117156152c7576152c761482a565b6040526152d38361526d565b81526152e160208401615281565b60208201526152f260408401615281565b60408201526153036060840161526d565b60608201526153146080840161526d565b608082015261532560a08401614d2b565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361536257615362614ed0565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff8316806153ab576153ab614f72565b8060ff84160691505092915050565b600060ff821660ff8416808210156153d4576153d4614ed0565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4","deployedCode":"0x6080604052600436106101625760003560e01c80638c3152e9116100c0578063c4d66de811610074578063e965084c11610059578063e965084c146104e0578063e9e05c421461056c578063f04987501461057f57600080fd5b8063c4d66de81461041f578063cff0ab961461043f57600080fd5b80639bf62d82116100a55780639bf62d8214610389578063a14238e7146103b6578063a35d99df146103e657600080fd5b80638c3152e9146103365780639b5f694a1461035657600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb7814610301578063724c184c146103215780638b4c40b01461018757600080fd5b806354fd4d50146102865780635c975abb146102dc57600080fd5b806335e80ab31161014857806335e80ab31461021f578063452a9320146102515780634870496f1461026657600080fd5b80621c2ff61461018e57806333d7e2bd146101ec57600080fd5b36610189576101873334620186a06000604051806020016040528060008152506105b3565b005b600080fd5b34801561019a57600080fd5b506101c27f0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb81565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101f857600080fd5b507f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e46101c2565b34801561022b57600080fd5b506035546101c290610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561025d57600080fd5b506101c261084e565b34801561027257600080fd5b50610187610281366004614a0a565b6108e6565b34801561029257600080fd5b506102cf6040518060400160405280600581526020017f322e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516101e39190614b60565b3480156102e857600080fd5b506102f1610f4e565b60405190151581526020016101e3565b34801561030d57600080fd5b506102f161031c366004614b73565b610fe1565b34801561032d57600080fd5b506101c26110b8565b34801561034257600080fd5b50610187610351366004614b8c565b6110c4565b34801561036257600080fd5b507f0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb6101c2565b34801561039557600080fd5b506032546101c29073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103c257600080fd5b506102f16103d1366004614b73565b60336020526000908152604090205460ff1681565b3480156103f257600080fd5b50610406610401366004614be6565b6119a1565b60405167ffffffffffffffff90911681526020016101e3565b34801561042b57600080fd5b5061018761043a366004614c01565b6119ba565b34801561044b57600080fd5b506001546104a7906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101e3565b3480156104ec57600080fd5b5061053e6104fb366004614b73565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101e3565b61018761057a366004614c2c565b6105b3565b34801561058b57600080fd5b506101c27f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e481565b8260005a9050831561066a5773ffffffffffffffffffffffffffffffffffffffff87161561066a57604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b61067483516119a1565b67ffffffffffffffff168567ffffffffffffffff161015610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c00000000000000000000000000000000000000000000000000000000006064820152608401610661565b6201d4c083511115610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c6172676500006044820152606401610661565b333281146107a6575033731111000000000000000000000000000000001111015b600034888888886040516020016107c1959493929190614ca9565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516108319190614b60565b60405180910390a450506108458282611be9565b50505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190614d0e565b905090565b6108ee610f4e565b15610955576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610661565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610a14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e7472616374006064820152608401610661565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018590526000907f0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb73ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610aa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac69190614d4b565b519050610ae0610adb36869003860186614db0565b611f16565b8114610b6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f6600000000000000000000000000000000000000000000006064820152608401610661565b6000610b7987611f72565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610cab5750805160408083015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201527f0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb73ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190614d4b565b5114155b610d37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610661565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610e009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610df6888a614e16565b8a60400135611fa2565b610e8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610661565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fbd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190614e9a565b6040517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018290526000906110b29073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb169063a25ae55790602401606060405180830381865afa158015611073573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110979190614d4b565b602001516fffffffffffffffffffffffffffffffff16611fc6565b92915050565b60006108e161084e565b565b6110cc610f4e565b15611133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a20706175736564000000000000000000006044820152606401610661565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead146111dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e006064820152608401610661565b60006111e782611f72565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff808216948301859052700100000000000000000000000000000000909104169181019190915292935090036112d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610661565b7f0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb73ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa15801561133d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113619190614eb7565b81602001516fffffffffffffffffffffffffffffffff16101561142c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610661565b61144b81602001516fffffffffffffffffffffffffffffffff16611fc6565b6114fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610661565b60408181015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff90911660048201526000907f0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb73ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c69190614d4b565b8251815191925014611680576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610661565b61169f81602001516fffffffffffffffffffffffffffffffff16611fc6565b611751576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610661565b60008381526033602052604090205460ff16156117f0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610661565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a088015161189293929190612069565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b906118f790841515815260200190565b60405180910390a28015801561190d5750326001145b1561199a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610661565b5050505050565b60006119ae826010614eff565b6110b290615208614f2f565b600054610100900460ff16158080156119da5750600054600160ff909116105b806119f45750303b1580156119f4575060005460ff166001145b611a80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610661565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611ade57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6035805473ffffffffffffffffffffffffffffffffffffffff808516610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff9092169190911790915560325416611b5e57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611b666120c7565b8015611bc957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611c1f907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643614f5b565b90506000611c2b6121da565b90506000816020015160ff16826000015163ffffffff16611c4c9190614fa1565b90508215611d8357600154600090611c83908390700100000000000000000000000000000000900467ffffffffffffffff16615009565b90506000836040015160ff1683611c9a919061507d565b600154611cba9084906fffffffffffffffffffffffffffffffff1661507d565b611cc49190614fa1565b600154909150600090611d1590611cee9084906fffffffffffffffffffffffffffffffff16615139565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff1661229b565b90506001861115611d4457611d41611cee82876040015160ff1660018a611d3c9190614f5b565b6122ba565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611db6908490700100000000000000000000000000000000900467ffffffffffffffff16614f2f565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611e99576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d697400006064820152608401610661565b600154600090611ec5906fffffffffffffffffffffffffffffffff1667ffffffffffffffff88166151ad565b90506000611ed748633b9aca0061230f565b611ee190836151ea565b905060005a611ef09088614f5b565b905080821115611f0c57611f0c611f078284614f5b565b612326565b5050505050505050565b60008160000151826020015183604001518460600151604051602001611f55949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097611f559790969591016151fe565b600080611fae86612354565b9050611fbc81868686612386565b9695505050505050565b60007f0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb73ffffffffffffffffffffffffffffffffffffffff1663f4daa2916040518163ffffffff1660e01b8152600401602060405180830381865afa158015612033573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120579190614eb7565b6120619083615255565b421192915050565b60008060006120798660006123b6565b9050806120af576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff1661215e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610661565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036110c25760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091527f0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e473ffffffffffffffffffffffffffffffffffffffff1663cc731b026040518163ffffffff1660e01b815260040160c060405180830381865afa158015612277573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e19190615292565b60006122b06122aa85856123d4565b836123e4565b90505b9392505050565b6000670de0b6b3a76400006122fb6122d28583614fa1565b6122e490670de0b6b3a7640000615009565b6122f685670de0b6b3a764000061507d565b6123f3565b612305908661507d565b6122b09190614fa1565b60008183101561231f57816122b3565b5090919050565b6000805a90505b825a6123399083614f5b565b101561234f5761234882615331565b915061232d565b505050565b6060818051906020012060405160200161237091815260200190565b6040516020818303038152906040529050919050565b60006123ad84612397878686612424565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b60008183121561231f57816122b3565b600081831261231f57816122b3565b60006122b3670de0b6b3a76400008361240b86612ea2565b612415919061507d565b61241f9190614fa1565b6130e6565b60606000845111612491576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610661565b600061249c84613325565b905060006124a986613411565b90506000846040516020016124c091815260200190565b60405160208183030381529060405290506000805b8451811015612e195760008582815181106124f2576124f2615369565b60200260200101519050845183111561258d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610661565b8260000361264657805180516020918201206040516125db926125b592910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612641576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610661565b61279d565b8051516020116126fc5780518051602091820120604051612670926125b592910190815260200190565b612641576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610661565b80518451602080870191909120825191909201201461279d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610661565b6127a960106001615255565b81602001515103612985578451830361291d576127e381602001516010815181106127d6576127d6615369565b6020026020010151613474565b96506000875111612876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610661565b600186516128849190614f5b565b8214612912576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610661565b5050505050506122b3565b600085848151811061293157612931615369565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061295c5761295c615369565b6020026020010151905061296f816135d4565b955061297c600186615255565b94505050612e06565b600281602001515103612d7e57600061299d826135f9565b90506000816000815181106129b4576129b4615369565b016020015160f81c905060006129cb600283615398565b6129d69060026153ba565b905060006129e7848360ff1661361d565b905060006129f58a8961361d565b90506000612a038383613653565b905080835114612a95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610661565b60ff851660021480612aaa575060ff85166003145b15612c995780825114612b3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610661565b612b5987602001516001815181106127d6576127d6615369565b9c5060008d5111612bec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610661565b60018c51612bfa9190614f5b565b8814612c88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610661565b5050505050505050505050506122b3565b60ff85161580612cac575060ff85166001145b15612ceb57612cd88760200151600181518110612ccb57612ccb615369565b60200260200101516135d4565b9950612ce4818a615255565b9850612d73565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610661565b505050505050612e06565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610661565b5080612e1181615331565b9150506124d5565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610661565b6000808213612f0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610661565b60006060612f1a84613707565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361311757506000919050565b680755bf798b4a1bf1e58212613189576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610661565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff8111156133435761334361482a565b60405190808252806020026020018201604052801561338857816020015b60408051808201909152606080825260208201528152602001906001900390816133615790505b50915060005b8181101561340a5760405180604001604052808583815181106133b3576133b3615369565b602002602001015181526020016133e28684815181106133d5576133d5615369565b60200260200101516137dd565b8152508382815181106133f7576133f7615369565b602090810291909101015260010161338e565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613469578060011b82018184015160001a8060041c8253600f81166001830153505060010161343b565b509295945050505050565b60606000806000613484856137f0565b91945092509050600081600181111561349f5761349f6153dd565b1461352c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d000000000000006064820152608401610661565b6135368284615255565b8551146135c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e6465720000000000000000000000006064820152608401610661565b6123ad8560200151848461425d565b606060208260000151106135f0576135eb82613474565b6110b2565b6110b2826142f1565b60606110b261361883602001516000815181106127d6576127d6615369565b613411565b60608251821061363c57506040805160208101909152600081526110b2565b6122b3838384865161364e9190614f5b565b614307565b6000808251845110613666578251613669565b83515b90505b80821080156136f0575082828151811061368857613688615369565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106136c7576136c7615369565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156137005781600101915061366c565b5092915050565b6000808211613772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610661565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b60606110b26137eb836144df565b6145c8565b6000806000808460000151116138ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610661565b6020840151805160001a607f81116138d3576000600160009450945094505050614256565b60b78111613ae15760006138e8608083614f5b565b9050808760000151116139a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a401610661565b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082141580613a1c57507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613ace576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a401610661565b5060019550935060009250614256915050565b60bf8111613e2f576000613af660b783614f5b565b905080876000015111613bb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a401610661565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613c8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a401610661565b600184015160088302610100031c60378111613d53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a401610661565b613d5d8184615255565b895111613e12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a401610661565b613e1d836001615255565b97509550600094506142569350505050565b60f78111613f10576000613e4460c083614f5b565b905080876000015111613eff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a401610661565b600195509350849250614256915050565b6000613f1d60f783614f5b565b905080876000015111613fd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a401610661565b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036140b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a401610661565b600184015160088302610100031c6037811161417a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a401610661565b6141848184615255565b895111614239576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a401610661565b614244836001615255565b97509550600194506142569350505050565b9193909250565b60608167ffffffffffffffff8111156142785761427861482a565b6040519080825280601f01601f1916602001820160405280156142a2576020820181803683370190505b50905081156122b35760006142b78486615255565b90506020820160005b848110156142d85782810151828201526020016142c0565b848111156142e7576000858301525b5050509392505050565b60606110b282602001516000846000015161425d565b60608182601f011015614376576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610661565b8282840110156143e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610661565b8183018451101561444f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610661565b60608215801561446e57604051915060008252602082016040526144d6565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156144a757805183526020928301920161448f565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b604080518082019091526000808252602082015260008251116145aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a401610661565b50604080518082019091528151815260209182019181019190915290565b606060008060006145d8856137f0565b9194509250905060018160018111156145f3576145f36153dd565b14614680576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d00000000000000006064820152608401610661565b845161468c8385615255565b14614719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e64657200000000000000000000000000006064820152608401610661565b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816147305790505093506000835b865181101561481e576000806147a36040518060400160405280858c600001516147879190614f5b565b8152602001858c6020015161479c9190615255565b90526137f0565b5091509150604051806040016040528083836147bf9190615255565b8152602001848b602001516147d49190615255565b8152508885815181106147e9576147e9615369565b60209081029190910101526147ff600185615255565b935061480b8183615255565b6148159084615255565b9250505061475d565b50845250919392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156148a0576148a061482a565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff811681146148ca57600080fd5b50565b600082601f8301126148de57600080fd5b813567ffffffffffffffff8111156148f8576148f861482a565b61492960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614859565b81815284602083860101111561493e57600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561496d57600080fd5b60405160c0810167ffffffffffffffff82821081831117156149915761499161482a565b8160405282935084358352602085013591506149ac826148a8565b816020840152604085013591506149c2826148a8565b816040840152606085013560608401526080850135608084015260a08501359150808211156149f057600080fd5b506149fd858286016148cd565b60a0830152505092915050565b600080600080600085870360e0811215614a2357600080fd5b863567ffffffffffffffff80821115614a3b57600080fd5b614a478a838b0161495b565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614a8057600080fd5b60408901955060c0890135925080831115614a9a57600080fd5b828901925089601f840112614aae57600080fd5b8235915080821115614abf57600080fd5b508860208260051b8401011115614ad557600080fd5b959894975092955050506020019190565b60005b83811015614b01578181015183820152602001614ae9565b83811115614b10576000848401525b50505050565b60008151808452614b2e816020860160208601614ae6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122b36020830184614b16565b600060208284031215614b8557600080fd5b5035919050565b600060208284031215614b9e57600080fd5b813567ffffffffffffffff811115614bb557600080fd5b614bc18482850161495b565b949350505050565b803567ffffffffffffffff81168114614be157600080fd5b919050565b600060208284031215614bf857600080fd5b6122b382614bc9565b600060208284031215614c1357600080fd5b81356122b3816148a8565b80151581146148ca57600080fd5b600080600080600060a08688031215614c4457600080fd5b8535614c4f816148a8565b945060208601359350614c6460408701614bc9565b92506060860135614c7481614c1e565b9150608086013567ffffffffffffffff811115614c9057600080fd5b614c9c888289016148cd565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614cfd816049850160208701614ae6565b919091016049019695505050505050565b600060208284031215614d2057600080fd5b81516122b3816148a8565b80516fffffffffffffffffffffffffffffffff81168114614be157600080fd5b600060608284031215614d5d57600080fd5b6040516060810181811067ffffffffffffffff82111715614d8057614d8061482a565b60405282518152614d9360208401614d2b565b6020820152614da460408401614d2b565b60408201529392505050565b600060808284031215614dc257600080fd5b6040516080810181811067ffffffffffffffff82111715614de557614de561482a565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614e3157614e3161482a565b8360051b6020614e42818301614859565b868152918501918181019036841115614e5a57600080fd5b865b84811015614e8e57803586811115614e745760008081fd5b614e8036828b016148cd565b845250918301918301614e5c565b50979650505050505050565b600060208284031215614eac57600080fd5b81516122b381614c1e565b600060208284031215614ec957600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615614f2657614f26614ed0565b02949350505050565b600067ffffffffffffffff808316818516808303821115614f5257614f52614ed0565b01949350505050565b600082821015614f6d57614f6d614ed0565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614fb057614fb0614f72565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561500457615004614ed0565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561504357615043614ed0565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561507757615077614ed0565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156150be576150be614ed0565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156150f9576150f9614ed0565b6000871292508782058712848416161561511557615115614ed0565b8785058712818416161561512b5761512b614ed0565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561517357615173614ed0565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156151a7576151a7614ed0565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156151e5576151e5614ed0565b500290565b6000826151f9576151f9614f72565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261524960c0830184614b16565b98975050505050505050565b6000821982111561526857615268614ed0565b500190565b805163ffffffff81168114614be157600080fd5b805160ff81168114614be157600080fd5b600060c082840312156152a457600080fd5b60405160c0810181811067ffffffffffffffff821117156152c7576152c761482a565b6040526152d38361526d565b81526152e160208401615281565b60208201526152f260408401615281565b60408201526153036060840161526d565b60608201526153146080840161526d565b608082015261532560a08401614d2b565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361536257615362614ed0565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff8316806153ab576153ab614f72565b8060ff84160691505092915050565b600060ff821660ff8416808210156153d4576153d4614ed0565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000035"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000035"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000032"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000032"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":true,"newValue":"0x000000000000000000000000000000000000000000000000000000000000dead","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000032"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000001"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":true,"newValue":"0x000000000000000100000000000000000000000000000000000000003b9aca00","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000001"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xfa60f9b2","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000000e"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":false,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0x001c2ff6","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0x9b5f694a","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0xf0498750","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0x33d7e2bd","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x276b657a","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000006","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000006","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000018"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x93991af3","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000002","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000002","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000011"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x241e2d7e","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8","previousValue":"0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000001b"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x08cb822d","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63","previousValue":"0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000001c"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xce5db8d6","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000024","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000024","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000001d"}],"value":0},{"accessor":"0x4e59b44847b379578588920cA78FbF26c0B4956C","account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","chainInfo":{"chainId":31337,"forkId":0},"data":"0x6101206040523480156200001257600080fd5b506040516200198438038062001984833981016040819052620000359162000347565b60008611620000b15760405162461bcd60e51b815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e203000000000000000000000000060648201526084015b60405180910390fd5b60008711620001295760405162461bcd60e51b815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e20300000000000006064820152608401620000a8565b608087905260a08690526001600160a01b0380841660e052821660c05261010081905262000158858562000165565b50505050505050620003af565b600054610100900460ff1615808015620001865750600054600160ff909116105b80620001b65750620001a3306200031b60201b6200133c1760201c565b158015620001b6575060005460ff166001145b6200021b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000a8565b6000805460ff1916600117905580156200023f576000805461ff0019166101001790555b42821115620002c55760405162461bcd60e51b8152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201526374696d6560e01b608482015260a401620000a8565b60028290556001839055801562000316576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b80516001600160a01b03811681146200034257600080fd5b919050565b600080600080600080600060e0888a0312156200036357600080fd5b875196506020880151955060408801519450606088015193506200038a608089016200032a565b92506200039a60a089016200032a565b915060c0880151905092959891949750929550565b60805160a05160c05160e0516101005161154a6200043a600039600081816104ad0152818161058b01526109c90152600081816104460152818161047c0152610b3901526000818161022e0152818161030501526108630152600081816101a1015281816103a401526110700152600081816101fd0152818161053501526110be015261154a6000f3fe60806040526004361061018a5760003560e01c806393991af3116100d6578063cf8e5cf01161007f578063e1a41bcf11610059578063e1a41bcf14610526578063e4a3011614610559578063f4daa2911461057957600080fd5b8063cf8e5cf0146104d1578063d1de856c146104f1578063dcec33481461051157600080fd5b8063a8e4fb90116100b0578063a8e4fb9014610437578063bffa7f0f1461046a578063ce5db8d61461049e57600080fd5b806393991af3146103955780639aaab648146103c8578063a25ae557146103db57600080fd5b80636abcf563116101385780637f006420116101125780637f0064201461033d578063887862721461035d57806389c44cbb1461037357600080fd5b80636abcf563146102de5780636b4d98dd146102f357806370872aa51461032757600080fd5b8063534db0e211610169578063534db0e21461021f57806354fd4d501461027357806369f16eec146102c957600080fd5b80622134cc1461018f5780634599c788146101d6578063529933df146101eb575b600080fd5b34801561019b57600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b3480156101e257600080fd5b506101c36105ad565b3480156101f757600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b34801561022b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101cd565b34801561027f57600080fd5b506102bc6040518060400160405280600581526020017f312e372e3000000000000000000000000000000000000000000000000000000081525081565b6040516101cd9190611358565b3480156102d557600080fd5b506101c3610620565b3480156102ea57600080fd5b506003546101c3565b3480156102ff57600080fd5b5061024e7f000000000000000000000000000000000000000000000000000000000000000081565b34801561033357600080fd5b506101c360015481565b34801561034957600080fd5b506101c36103583660046113cb565b610632565b34801561036957600080fd5b506101c360025481565b34801561037f57600080fd5b5061039361038e3660046113cb565b61084b565b005b3480156103a157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b6103936103d63660046113e4565b610b21565b3480156103e757600080fd5b506103fb6103f63660046113cb565b610fa0565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101cd565b34801561044357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061024e565b34801561047657600080fd5b5061024e7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104aa57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b3480156104dd57600080fd5b506103fb6104ec3660046113cb565b611034565b3480156104fd57600080fd5b506101c361050c3660046113cb565b61106c565b34801561051d57600080fd5b506101c36110ba565b34801561053257600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101c3565b34801561056557600080fd5b50610393610574366004611416565b6110ef565b34801561058557600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000081565b6003546000901561061757600380546105c890600190611467565b815481106105d8576105d861147e565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b60035460009061061b90600190611467565b600061063c6105ad565b8211156106f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6003546107ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a4016106ed565b6003546000905b8082101561084457600060026107c883856114ad565b6107d291906114c5565b905084600382815481106107e8576107e861147e565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16101561083a576108338160016114ad565b925061083e565b8091505b506107b2565b5092915050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610910576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f757470757473000060648201526084016106ed565b60035481106109c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b7f0000000000000000000000000000000000000000000000000000000000000000600382815481106109fb576109fb61147e565b6000918252602090912060016002909202010154610a2b906fffffffffffffffffffffffffffffffff1642611467565b10610ade576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a4016106ed565b6000610ae960035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610c0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b610c146110ba565b8314610cc8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a4016106ed565b42610cd28461106c565b10610d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e20746865206675747572650000000000000000000060648201526084016106ed565b83610dec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f206861736800000000000060648201526084016106ed565b8115610ea85781814014610ea8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a4016106ed565b82610eb260035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e242604051610ee491815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b604080516060810182526000808252602082018190529181019190915260038281548110610fd057610fd061147e565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b6040805160608101825260008082526020820181905291810191909152600361105c83610632565b81548110610fd057610fd061147e565b60007f00000000000000000000000000000000000000000000000000000000000000006001548361109d9190611467565b6110a79190611500565b6002546110b491906114ad565b92915050565b60007f00000000000000000000000000000000000000000000000000000000000000006110e56105ad565b61061b91906114ad565b600054610100900460ff161580801561110f5750600054600160ff909116105b806111295750303b158015611129575060005460ff166001145b6111b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106ed565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561121357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b428211156112ca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b60028290556001839055801561133757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208083528351808285015260005b8181101561138557858101830151858201604001528201611369565b81811115611397576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000602082840312156113dd57600080fd5b5035919050565b600080600080608085870312156113fa57600080fd5b5050823594602084013594506040840135936060013592509050565b6000806040838503121561142957600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561147957611479611438565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156114c0576114c0611438565b500190565b6000826114fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561153857611538611438565b50029056fea164736f6c634300080f000a000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b630000000000000000000000000000000000000000000000000000000000000024","deployedCode":"0x60806040526004361061018a5760003560e01c806393991af3116100d6578063cf8e5cf01161007f578063e1a41bcf11610059578063e1a41bcf14610526578063e4a3011614610559578063f4daa2911461057957600080fd5b8063cf8e5cf0146104d1578063d1de856c146104f1578063dcec33481461051157600080fd5b8063a8e4fb90116100b0578063a8e4fb9014610437578063bffa7f0f1461046a578063ce5db8d61461049e57600080fd5b806393991af3146103955780639aaab648146103c8578063a25ae557146103db57600080fd5b80636abcf563116101385780637f006420116101125780637f0064201461033d578063887862721461035d57806389c44cbb1461037357600080fd5b80636abcf563146102de5780636b4d98dd146102f357806370872aa51461032757600080fd5b8063534db0e211610169578063534db0e21461021f57806354fd4d501461027357806369f16eec146102c957600080fd5b80622134cc1461018f5780634599c788146101d6578063529933df146101eb575b600080fd5b34801561019b57600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000281565b6040519081526020015b60405180910390f35b3480156101e257600080fd5b506101c36105ad565b3480156101f757600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000000681565b34801561022b57600080fd5b507f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b635b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101cd565b34801561027f57600080fd5b506102bc6040518060400160405280600581526020017f312e372e3000000000000000000000000000000000000000000000000000000081525081565b6040516101cd9190611358565b3480156102d557600080fd5b506101c3610620565b3480156102ea57600080fd5b506003546101c3565b3480156102ff57600080fd5b5061024e7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6381565b34801561033357600080fd5b506101c360015481565b34801561034957600080fd5b506101c36103583660046113cb565b610632565b34801561036957600080fd5b506101c360025481565b34801561037f57600080fd5b5061039361038e3660046113cb565b61084b565b005b3480156103a157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000026101c3565b6103936103d63660046113e4565b610b21565b3480156103e757600080fd5b506103fb6103f63660046113cb565b610fa0565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101cd565b34801561044357600080fd5b507f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c861024e565b34801561047657600080fd5b5061024e7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c881565b3480156104aa57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000246101c3565b3480156104dd57600080fd5b506103fb6104ec3660046113cb565b611034565b3480156104fd57600080fd5b506101c361050c3660046113cb565b61106c565b34801561051d57600080fd5b506101c36110ba565b34801561053257600080fd5b507f00000000000000000000000000000000000000000000000000000000000000066101c3565b34801561056557600080fd5b50610393610574366004611416565b6110ef565b34801561058557600080fd5b506101c37f000000000000000000000000000000000000000000000000000000000000002481565b6003546000901561061757600380546105c890600190611467565b815481106105d8576105d861147e565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b60035460009061061b90600190611467565b600061063c6105ad565b8211156106f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6003546107ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a4016106ed565b6003546000905b8082101561084457600060026107c883856114ad565b6107d291906114c5565b905084600382815481106107e8576107e861147e565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16101561083a576108338160016114ad565b925061083e565b8091505b506107b2565b5092915050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b631614610910576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f757470757473000060648201526084016106ed565b60035481106109c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b7f0000000000000000000000000000000000000000000000000000000000000024600382815481106109fb576109fb61147e565b6000918252602090912060016002909202010154610a2b906fffffffffffffffffffffffffffffffff1642611467565b10610ade576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a4016106ed565b6000610ae960035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614610c0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b610c146110ba565b8314610cc8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a4016106ed565b42610cd28461106c565b10610d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e20746865206675747572650000000000000000000060648201526084016106ed565b83610dec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f206861736800000000000060648201526084016106ed565b8115610ea85781814014610ea8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a4016106ed565b82610eb260035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e242604051610ee491815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b604080516060810182526000808252602082018190529181019190915260038281548110610fd057610fd061147e565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b6040805160608101825260008082526020820181905291810191909152600361105c83610632565b81548110610fd057610fd061147e565b60007f00000000000000000000000000000000000000000000000000000000000000026001548361109d9190611467565b6110a79190611500565b6002546110b491906114ad565b92915050565b60007f00000000000000000000000000000000000000000000000000000000000000066110e56105ad565b61061b91906114ad565b600054610100900460ff161580801561110f5750600054600160ff909116105b806111295750303b158015611129575060005460ff166001145b6111b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106ed565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561121357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b428211156112ca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a4016106ed565b60028290556001839055801561133757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208083528351808285015260005b8181101561138557858101830151858201604001528201611369565b81811115611397576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000602082840312156113dd57600080fd5b5035919050565b600080600080608085870312156113fa57600080fd5b5050823594602084013594506040840135936060013592509050565b6000806040838503121561142957600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561147957611479611438565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156114c0576114c0611438565b500190565b6000826114fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561153857611538611438565b50029056fea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000002"},{"account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000001"},{"account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x276b657a","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000006","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000006","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000018"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","chainInfo":{"chainId":31337,"forkId":0},"data":"0x529933df","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x276b657a","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000006","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000006","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000018"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","chainInfo":{"chainId":31337,"forkId":0},"data":"0xe1a41bcf","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x93991af3","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000002","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000002","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000011"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","chainInfo":{"chainId":31337,"forkId":0},"data":"0x002134cc","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x93991af3","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000002","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000002","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000011"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","chainInfo":{"chainId":31337,"forkId":0},"data":"0x93991af3","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x241e2d7e","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8","previousValue":"0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000001b"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","chainInfo":{"chainId":31337,"forkId":0},"data":"0xbffa7f0f","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x241e2d7e","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8","previousValue":"0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000001b"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","chainInfo":{"chainId":31337,"forkId":0},"data":"0xa8e4fb90","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x08cb822d","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63","previousValue":"0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000001c"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","chainInfo":{"chainId":31337,"forkId":0},"data":"0x6b4d98dd","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x08cb822d","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63","previousValue":"0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000001c"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","chainInfo":{"chainId":31337,"forkId":0},"data":"0x534db0e2","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xce5db8d6","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000024","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000024","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000001d"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","chainInfo":{"chainId":31337,"forkId":0},"data":"0xf4daa291","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xce5db8d6","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000024","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000024","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000001d"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","chainInfo":{"chainId":31337,"forkId":0},"data":"0xce5db8d6","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","chainInfo":{"chainId":31337,"forkId":0},"data":"0x70872aa5","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000001"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","chainInfo":{"chainId":31337,"forkId":0},"data":"0x88786272","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1B9F0e648A0A4780120A6Cd07B952F76560c8F8b","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000002"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0x60806040523480156200001157600080fd5b5060405162002187380380620021878339810160408190526200003491620009c1565b620000458787878787878762000052565b5050505050505062000c19565b600054610100900460ff1615808015620000735750600054600160ff909116105b80620000a3575062000090306200022a60201b620008131760201c565b158015620000a3575060005460ff166001145b6200010c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000130576000805461ff0019166101001790555b6200013a62000239565b6200014588620002a1565b620001508562000320565b6200015c878762000372565b6200016784620003d6565b620001728362000473565b6200017d82620004db565b620001876200081f565b6001600160401b0316846001600160401b03161015620001d95760405162461bcd60e51b815260206004820152601f602482015260008051602062002127833981519152604482015260640162000103565b801562000220576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6001600160a01b03163b151590565b600054610100900460ff16620002955760405162461bcd60e51b815260206004820152602b60248201526000805160206200216783398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000103565b6200029f6200084c565b565b620002ab620008b3565b6001600160a01b038116620003125760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000103565b6200031d816200090f565b50565b60678190556040805160208082018490528251808303909101815290820190915260005b6000600080516020620021478339815191528360405162000366919062000afa565b60405180910390a35050565b60658290556066819055604080516020810184905290810182905260009060600160408051601f198184030181529190529050600160006000805160206200214783398151915283604051620003c9919062000afa565b60405180910390a3505050565b620003e06200081f565b6001600160401b0316816001600160401b03161015620004325760405162461bcd60e51b815260206004820152601f602482015260008051602062002127833981519152604482015260640162000103565b606880546001600160401b0319166001600160401b038316908117909155604080516020808201939093528151808203909301835281019052600262000344565b620004aa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08826200096160201b6200082f1760201c565b604080516001600160a01b03831660208201526000910160408051601f198184030181529190529050600362000344565b8060a001516001600160801b0316816060015163ffffffff1611156200056a5760405162461bcd60e51b815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d617820626173650000000000000000000000606482015260840162000103565b6001816040015160ff1611620005db5760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201526e65206c6172676572207468616e203160881b606482015260840162000103565b606854608082015182516001600160401b0390921691620005fd919062000b68565b63ffffffff161115620006425760405162461bcd60e51b815260206004820152601f602482015260008051602062002127833981519152604482015260640162000103565b6000816020015160ff1611620006b35760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201526e06965722063616e6e6f74206265203608c1b606482015260840162000103565b8051602082015163ffffffff82169160ff90911690620006d590829062000b93565b620006e1919062000bc5565b63ffffffff16146200075c5760405162461bcd60e51b815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d6974000000000000000000606482015260840162000103565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff96871664ffffffffff199095169490941764010000000060ff948516021764ffffffffff60281b191665010000000000939092169290920263ffffffff60301b19161766010000000000009185169190910217600160501b600160f01b0319166a01000000000000000000009390941692909202600160701b600160f01b03191692909217600160701b6001600160801b0390921691909102179055565b606954600090620008479063ffffffff6a010000000000000000000082048116911662000bf4565b905090565b600054610100900460ff16620008a85760405162461bcd60e51b815260206004820152602b60248201526000805160206200216783398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000103565b6200029f336200090f565b6033546001600160a01b031633146200029f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000103565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b9055565b80516001600160a01b03811681146200097d57600080fd5b919050565b805163ffffffff811681146200097d57600080fd5b805160ff811681146200097d57600080fd5b80516001600160801b03811681146200097d57600080fd5b6000806000806000806000878903610180811215620009df57600080fd5b620009ea8962000965565b60208a015160408b015160608c015160808d0151939b50919950975095506001600160401b03808216821462000a1f57600080fd5b81955062000a3060a08c0162000965565b945060c060bf198401121562000a4557600080fd5b604051925060c083019150828210818311171562000a7357634e487b7160e01b600052604160045260246000fd5b5060405262000a8560c08a0162000982565b815262000a9560e08a0162000997565b602082015262000aa96101008a0162000997565b604082015262000abd6101208a0162000982565b606082015262000ad16101408a0162000982565b608082015262000ae56101608a01620009a9565b60a08201528091505092959891949750929550565b600060208083528351808285015260005b8181101562000b295785810183015185820160400152820162000b0b565b8181111562000b3c576000604083870101525b50601f01601f1916929092016040019392505050565b634e487b7160e01b600052601160045260246000fd5b600063ffffffff80831681851680830382111562000b8a5762000b8a62000b52565b01949350505050565b600063ffffffff8084168062000bb957634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b600063ffffffff8083168185168183048111821515161562000beb5762000beb62000b52565b02949350505050565b60006001600160401b0382811684821680830382111562000b8a5762000b8a62000b52565b6114fe8062000c296000396000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c8063b40a817c116100cd578063f2fde38b11610081578063f68016b711610066578063f68016b714610410578063f975e92514610424578063ffa1ad741461043757600080fd5b8063f2fde38b146103f4578063f45e65d81461040757600080fd5b8063c9b26f61116100b2578063c9b26f61146102a4578063cc731b02146102b7578063e81b2c6d146103eb57600080fd5b8063b40a817c1461027e578063c71973f61461029157600080fd5b80634f16540b11610124578063715018a611610109578063715018a6146102455780638da5cb5b1461024d578063935f029e1461026b57600080fd5b80634f16540b146101d557806354fd4d50146101fc57600080fd5b80630c18c1621461015657806318d13918146101725780631fd19ee1146101875780634add321d146101b4575b600080fd5b61015f60655481565b6040519081526020015b60405180910390f35b610185610180366004611156565b61043f565b005b61018f610453565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610169565b6101bc610482565b60405167ffffffffffffffff9091168152602001610169565b61015f7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b6102386040518060400160405280600681526020017f312e31312e30000000000000000000000000000000000000000000000000000081525081565b60405161016991906111e3565b6101856104a8565b60335473ffffffffffffffffffffffffffffffffffffffff1661018f565b6101856102793660046111f6565b6104bc565b61018561028c366004611230565b6104d2565b61018561029f366004611359565b6104e3565b6101856102b2366004611375565b6104f4565b61037b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516101699190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61015f60675481565b610185610402366004611156565b610505565b61015f60665481565b6068546101bc9067ffffffffffffffff1681565b61018561043236600461138e565b6105be565b61015f600081565b610447610833565b610450816108b4565b50565b600061047d7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b905090565b60695460009061047d9063ffffffff6a0100000000000000000000820481169116611430565b6104b0610833565b6104ba6000610971565b565b6104c4610833565b6104ce82826109e8565b5050565b6104da610833565b61045081610a79565b6104eb610833565b61045081610b57565b6104fc610833565b61045081610fcb565b61050d610833565b73ffffffffffffffffffffffffffffffffffffffff81166105b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61045081610971565b600054610100900460ff16158080156105de5750600054600160ff909116105b806105f85750303b1580156105f8575060005460ff166001145b610684576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105ac565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156106e257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6106ea610ff3565b6106f388610505565b6106fc85610fcb565b61070687876109e8565b61070f84610a79565b610718836108b4565b61072182610b57565b610729610482565b67ffffffffffffffff168467ffffffffffffffff1610156107a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016105ac565b801561080957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff1633146104ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105ac565b6108dd7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161096591906111e3565b60405180910390a35050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610a6c91906111e3565b60405180910390a3505050565b610a81610482565b67ffffffffffffffff168167ffffffffffffffff161015610afe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016105ac565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610934565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115610c07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d61782062617365000000000000000000000060648201526084016105ac565b6001816040015160ff1611610c9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e2031000000000000000000000000000000000060648201526084016105ac565b6068546080820151825167ffffffffffffffff90921691610cbf919061145c565b63ffffffff161115610d2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016105ac565b6000816020015160ff1611610dc4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f742062652030000000000000000000000000000000000060648201526084016105ac565b8051602082015163ffffffff82169160ff90911690610de490829061147b565b610dee91906114c5565b63ffffffff1614610e81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d697400000000000000000060648201526084016105ac565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b6067819055604080516020808201849052825180830390910181529082019091526000610934565b600054610100900460ff1661108a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105ac565b6104ba600054610100900460ff16611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105ac565b6104ba33610971565b803573ffffffffffffffffffffffffffffffffffffffff8116811461115157600080fd5b919050565b60006020828403121561116857600080fd5b6111718261112d565b9392505050565b6000815180845260005b8181101561119e57602081850181015186830182015201611182565b818111156111b0576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006111716020830184611178565b6000806040838503121561120957600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461115157600080fd5b60006020828403121561124257600080fd5b61117182611218565b803563ffffffff8116811461115157600080fd5b803560ff8116811461115157600080fd5b80356fffffffffffffffffffffffffffffffff8116811461115157600080fd5b600060c082840312156112a257600080fd5b60405160c0810181811067ffffffffffffffff821117156112ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806112fb8361124b565b81526113096020840161125f565b602082015261131a6040840161125f565b604082015261132b6060840161124b565b606082015261133c6080840161124b565b608082015261134d60a08401611270565b60a08201525092915050565b600060c0828403121561136b57600080fd5b6111718383611290565b60006020828403121561138757600080fd5b5035919050565b6000806000806000806000610180888a0312156113aa57600080fd5b6113b38861112d565b96506020880135955060408801359450606088013593506113d660808901611218565b92506113e460a0890161112d565b91506113f38960c08a01611290565b905092959891949750929550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851680830382111561145357611453611401565b01949350505050565b600063ffffffff80831681851680830382111561145357611453611401565b600063ffffffff808416806114b9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156114e8576114e8611401565b0294935050505056fea164736f6c634300080f000a53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77001d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069000000000000000000000000000000000000000000000000000000000000dead0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001406f4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff","deployedCode":"0x608060405234801561001057600080fd5b50600436106101515760003560e01c8063b40a817c116100cd578063f2fde38b11610081578063f68016b711610066578063f68016b714610410578063f975e92514610424578063ffa1ad741461043757600080fd5b8063f2fde38b146103f4578063f45e65d81461040757600080fd5b8063c9b26f61116100b2578063c9b26f61146102a4578063cc731b02146102b7578063e81b2c6d146103eb57600080fd5b8063b40a817c1461027e578063c71973f61461029157600080fd5b80634f16540b11610124578063715018a611610109578063715018a6146102455780638da5cb5b1461024d578063935f029e1461026b57600080fd5b80634f16540b146101d557806354fd4d50146101fc57600080fd5b80630c18c1621461015657806318d13918146101725780631fd19ee1146101875780634add321d146101b4575b600080fd5b61015f60655481565b6040519081526020015b60405180910390f35b610185610180366004611156565b61043f565b005b61018f610453565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610169565b6101bc610482565b60405167ffffffffffffffff9091168152602001610169565b61015f7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b6102386040518060400160405280600681526020017f312e31312e30000000000000000000000000000000000000000000000000000081525081565b60405161016991906111e3565b6101856104a8565b60335473ffffffffffffffffffffffffffffffffffffffff1661018f565b6101856102793660046111f6565b6104bc565b61018561028c366004611230565b6104d2565b61018561029f366004611359565b6104e3565b6101856102b2366004611375565b6104f4565b61037b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516101699190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61015f60675481565b610185610402366004611156565b610505565b61015f60665481565b6068546101bc9067ffffffffffffffff1681565b61018561043236600461138e565b6105be565b61015f600081565b610447610833565b610450816108b4565b50565b600061047d7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b905090565b60695460009061047d9063ffffffff6a0100000000000000000000820481169116611430565b6104b0610833565b6104ba6000610971565b565b6104c4610833565b6104ce82826109e8565b5050565b6104da610833565b61045081610a79565b6104eb610833565b61045081610b57565b6104fc610833565b61045081610fcb565b61050d610833565b73ffffffffffffffffffffffffffffffffffffffff81166105b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61045081610971565b600054610100900460ff16158080156105de5750600054600160ff909116105b806105f85750303b1580156105f8575060005460ff166001145b610684576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105ac565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156106e257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6106ea610ff3565b6106f388610505565b6106fc85610fcb565b61070687876109e8565b61070f84610a79565b610718836108b4565b61072182610b57565b610729610482565b67ffffffffffffffff168467ffffffffffffffff1610156107a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016105ac565b801561080957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff1633146104ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105ac565b6108dd7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161096591906111e3565b60405180910390a35050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610a6c91906111e3565b60405180910390a3505050565b610a81610482565b67ffffffffffffffff168167ffffffffffffffff161015610afe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016105ac565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610934565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115610c07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d61782062617365000000000000000000000060648201526084016105ac565b6001816040015160ff1611610c9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e2031000000000000000000000000000000000060648201526084016105ac565b6068546080820151825167ffffffffffffffff90921691610cbf919061145c565b63ffffffff161115610d2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f770060448201526064016105ac565b6000816020015160ff1611610dc4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f742062652030000000000000000000000000000000000060648201526084016105ac565b8051602082015163ffffffff82169160ff90911690610de490829061147b565b610dee91906114c5565b63ffffffff1614610e81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d697400000000000000000060648201526084016105ac565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b6067819055604080516020808201849052825180830390910181529082019091526000610934565b600054610100900460ff1661108a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105ac565b6104ba600054610100900460ff16611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105ac565b6104ba33610971565b803573ffffffffffffffffffffffffffffffffffffffff8116811461115157600080fd5b919050565b60006020828403121561116857600080fd5b6111718261112d565b9392505050565b6000815180845260005b8181101561119e57602081850181015186830182015201611182565b818111156111b0576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006111716020830184611178565b6000806040838503121561120957600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461115157600080fd5b60006020828403121561124257600080fd5b61117182611218565b803563ffffffff8116811461115157600080fd5b803560ff8116811461115157600080fd5b80356fffffffffffffffffffffffffffffffff8116811461115157600080fd5b600060c082840312156112a257600080fd5b60405160c0810181811067ffffffffffffffff821117156112ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806112fb8361124b565b81526113096020840161125f565b602082015261131a6040840161125f565b604082015261132b6060840161124b565b606082015261133c6080840161124b565b608082015261134d60a08401611270565b60a08201525092915050565b600060c0828403121561136b57600080fd5b6111718383611290565b60006020828403121561138757600080fd5b5035919050565b6000806000806000806000610180888a0312156113aa57600080fd5b6113b38861112d565b96506020880135955060408801359450606088013593506113d660808901611218565b92506113e460a0890161112d565b91506113f38960c08a01611290565b905092959891949750929550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851680830382111561145357611453611401565b01949350505050565b600063ffffffff80831681851680830382111561145357611453611401565b600063ffffffff808416806114b9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156114e8576114e8611401565b0294935050505056fea164736f6c634300080f000a","initialized":true,"kind":"Create","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":true,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":true,"newValue":"0x000000000000000000000000000000000000000000000000000000000000dead","previousValue":"0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000067"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000065"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000066"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000069"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000068"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000001406f40","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000068"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000001406f40","previousValue":"0x0000000000000000000000000000000000000000000000000000000001406f40","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000068"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000069"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":true,"newValue":"0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000069"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00","previousValue":"0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000069"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0x8da5cb5b","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x000000000000000000000000000000000000000000000000000000000000dead","previousValue":"0x000000000000000000000000000000000000000000000000000000000000dead","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0x0c18c162","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000065"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0xf45e65d8","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000066"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0xe81b2c6d","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000067"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0x1fd19ee1","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0xcc731b02","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","isWrite":false,"newValue":"0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00","previousValue":"0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000069"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x68ea2a43","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc","previousValue":"0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000017"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xd2354f20","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000000d"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x81143a59","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000834","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000834","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000002a"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x0ac77bb5","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x00000000000000000000000000000000000000000000000000000000000f4240","previousValue":"0x00000000000000000000000000000000000000000000000000000000000f4240","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000002b"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x2dde36f5","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x00000000000000000000000000000000000000000000000000000000017d7840","previousValue":"0x00000000000000000000000000000000000000000000000000000000017d7840","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000028"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xe7d6cd42","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000015"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002249623609d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184f975e9250000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f42400000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1","previousValue":"0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x90193C961A926261B756D1E5bb255e67ff9498A1","chainInfo":{"chainId":31337,"forkId":0},"data":"0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000002249623609d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184f975e9250000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f42400000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000002","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000002","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000005"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000002","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000002","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000005"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000003","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000002","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000005"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000004"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8"}],"value":0},{"accessor":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","chainInfo":{"chainId":31337,"forkId":0},"data":"0x9623609d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000184f975e9250000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f42400000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f","previousValue":"0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x727598a658f6983be3a9f29beef55aaee89ef8a176baeeacbe7edf5ff94a781b"}],"value":0},{"accessor":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","chainInfo":{"chainId":31337,"forkId":0},"data":"0x4f1ef286000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000184f975e9250000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f42400000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":true,"newValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0xf975e9250000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f42400000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":true,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":true,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":true,"newValue":"0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000067"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000834","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000065"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":true,"newValue":"0x00000000000000000000000000000000000000000000000000000000000f4240","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000066"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000069"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000068"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":true,"newValue":"0x00000000000000000000000000000000000000000000000000000000017d7840","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000068"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":true,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x00000000000000000000000000000000000000000000000000000000017d7840","previousValue":"0x00000000000000000000000000000000000000000000000000000000017d7840","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000068"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000069"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":true,"newValue":"0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000069"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00","previousValue":"0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000069"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","chainInfo":{"chainId":31337,"forkId":0},"data":"0x54fd4d50","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","previousValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0x54fd4d50","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xd2354f20","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000000d"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","chainInfo":{"chainId":31337,"forkId":0},"data":"0x8da5cb5b","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","previousValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0x8da5cb5b","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000033"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x81143a59","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000834","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000834","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000002a"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","chainInfo":{"chainId":31337,"forkId":0},"data":"0x0c18c162","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","previousValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0x0c18c162","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000834","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000834","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000065"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x0ac77bb5","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x00000000000000000000000000000000000000000000000000000000000f4240","previousValue":"0x00000000000000000000000000000000000000000000000000000000000f4240","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000002b"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","chainInfo":{"chainId":31337,"forkId":0},"data":"0xf45e65d8","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","previousValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0xf45e65d8","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x00000000000000000000000000000000000000000000000000000000000f4240","previousValue":"0x00000000000000000000000000000000000000000000000000000000000f4240","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000066"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0x68ea2a43","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc","previousValue":"0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000017"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","chainInfo":{"chainId":31337,"forkId":0},"data":"0xe81b2c6d","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","previousValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0xe81b2c6d","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc","previousValue":"0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000067"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xe7d6cd42","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000015"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","chainInfo":{"chainId":31337,"forkId":0},"data":"0x1fd19ee1","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","previousValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0x1fd19ee1","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","chainInfo":{"chainId":31337,"forkId":0},"data":"0xcc731b02","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","previousValue":"0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xc7B87b2b892EA5C3CfF47168881FE168C00377FB","chainInfo":{"chainId":31337,"forkId":0},"data":"0xcc731b02","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4","isWrite":false,"newValue":"0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00","previousValue":"0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000069"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","chainInfo":{"chainId":31337,"forkId":0},"data":"0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000c49623609d000000000000000000000000978e3286eb805934215a88694d80b09aded68d9000000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce4400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1","previousValue":"0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x90193C961A926261B756D1E5bb255e67ff9498A1","chainInfo":{"chainId":31337,"forkId":0},"data":"0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000c49623609d000000000000000000000000978e3286eb805934215a88694d80b09aded68d9000000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce4400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000003","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000003","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000005"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000003","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000003","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000005"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000004","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000003","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000005"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000004"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32"},{"account":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8"}],"value":0},{"accessor":"0x2601573C28B77dea6C8B73385c25024A28a00C3F","account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","chainInfo":{"chainId":31337,"forkId":0},"data":"0x9623609d000000000000000000000000978e3286eb805934215a88694d80b09aded68d9000000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce4400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f","previousValue":"0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x9302c2c5f397028777ab180924fb28ceaf3af9b6a91b43410c4c0afe36476877"}],"value":0},{"accessor":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","account":"0x978e3286EB805934215a88694d80b09aDed68D90","chainInfo":{"chainId":31337,"forkId":0},"data":"0x4f1ef28600000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce4400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900000000000000000000000000000000000000000000000000000000","deployedCode":"0x","initialized":true,"kind":"Call","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","previousValue":"0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76","reverted":false,"slot":"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":true,"newValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0xc4d66de8000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000001","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000035"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":true,"newValue":"0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000035"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000032"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000032"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":true,"newValue":"0x000000000000000000000000000000000000000000000000000000000000dead","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000032"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000001"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":true,"newValue":"0x000000000000000100000000000000000000000000000000000000003b9aca00","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000001"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000101","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":true,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000001","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000101","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x978e3286EB805934215a88694d80b09aDed68D90","chainInfo":{"chainId":31337,"forkId":0},"data":"0x54fd4d50","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","previousValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0x54fd4d50","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xfa60f9b2","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000000e"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":false,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x978e3286EB805934215a88694d80b09aDed68D90","chainInfo":{"chainId":31337,"forkId":0},"data":"0x001c2ff6","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","previousValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0x001c2ff6","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x978e3286EB805934215a88694d80b09aDed68D90","chainInfo":{"chainId":31337,"forkId":0},"data":"0x9b5f694a","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","previousValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0x9b5f694a","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x978e3286EB805934215a88694d80b09aDed68D90","chainInfo":{"chainId":31337,"forkId":0},"data":"0xf0498750","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","previousValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0xf0498750","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x978e3286EB805934215a88694d80b09aDed68D90","chainInfo":{"chainId":31337,"forkId":0},"data":"0x33d7e2bd","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","previousValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0x33d7e2bd","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xfa60f9b2","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000000e"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x978e3286EB805934215a88694d80b09aDed68D90","chainInfo":{"chainId":31337,"forkId":0},"data":"0x724c184c","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","previousValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0x724c184c","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900","previousValue":"0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000035"}],"value":0},{"accessor":"0x978e3286EB805934215a88694d80b09aDed68D90","account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","chainInfo":{"chainId":31337,"forkId":0},"data":"0x452a9320","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a","previousValue":"0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x978e3286EB805934215a88694d80b09aDed68D90","account":"0x068E44eB31e111028c41598E4535be7468674D0A","chainInfo":{"chainId":31337,"forkId":0},"data":"0x452a9320","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","chainInfo":{"chainId":31337,"forkId":0},"data":"0xfa60f9b2","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0x000000000000000000000000000000000000000000000000000000000000000e"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x978e3286EB805934215a88694d80b09aDed68D90","chainInfo":{"chainId":31337,"forkId":0},"data":"0x452a9320","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","previousValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0x452a9320","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900","previousValue":"0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000035"}],"value":0},{"accessor":"0x978e3286EB805934215a88694d80b09aDed68D90","account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","chainInfo":{"chainId":31337,"forkId":0},"data":"0x452a9320","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a","previousValue":"0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x978e3286EB805934215a88694d80b09aDed68D90","account":"0x068E44eB31e111028c41598E4535be7468674D0A","chainInfo":{"chainId":31337,"forkId":0},"data":"0x452a9320","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","previousValue":"0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc","reverted":false,"slot":"0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x978e3286EB805934215a88694d80b09aDed68D90","chainInfo":{"chainId":31337,"forkId":0},"data":"0x35e80ab3","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","previousValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0x35e80ab3","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900","previousValue":"0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000035"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","chainInfo":{"chainId":31337,"forkId":0},"data":"0x5c975abb","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a","previousValue":"0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x068E44eB31e111028c41598E4535be7468674D0A","chainInfo":{"chainId":31337,"forkId":0},"data":"0x5c975abb","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b6"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x978e3286EB805934215a88694d80b09aDed68D90","chainInfo":{"chainId":31337,"forkId":0},"data":"0x5c975abb","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","previousValue":"0x00000000000000000000000094ea1235778adc02fd93c242e6a23ef5c8c3ce44","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38","account":"0x94eA1235778aDc02FD93c242e6A23Ef5C8c3CE44","chainInfo":{"chainId":31337,"forkId":0},"data":"0x5c975abb","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0x978e3286EB805934215a88694d80b09aDed68D90","isWrite":false,"newValue":"0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900","previousValue":"0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900","reverted":false,"slot":"0x0000000000000000000000000000000000000000000000000000000000000035"}],"value":0},{"accessor":"0x978e3286EB805934215a88694d80b09aDed68D90","account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","chainInfo":{"chainId":31337,"forkId":0},"data":"0x5c975abb","deployedCode":"0x","initialized":true,"kind":"StaticCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a","previousValue":"0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a","reverted":false,"slot":"0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"}],"value":0},{"accessor":"0x978e3286EB805934215a88694d80b09aDed68D90","account":"0x068E44eB31e111028c41598E4535be7468674D0A","chainInfo":{"chainId":31337,"forkId":0},"data":"0x5c975abb","deployedCode":"0x","initialized":true,"kind":"DelegateCall","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[{"account":"0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809","isWrite":false,"newValue":"0x0000000000000000000000000000000000000000000000000000000000000000","previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","reverted":false,"slot":"0x54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b6"}],"value":0},{"accessor":"0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496","account":"0x7109709ECfa91a80626fF3989D68f67F5b1DD12D","chainInfo":{"chainId":31337,"forkId":0},"data":"0x","deployedCode":"0x","initialized":true,"kind":"Resume","newBalance":0,"oldBalance":0,"reverted":false,"storageAccesses":[],"value":0}] -} \ No newline at end of file + "accountAccesses": [ + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": false, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x34A1D3fff3958843C43aD80F30b94c510645C316", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x608060405234801561001057600080fd5b50610913806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806353e5d9351161005057806353e5d935146100b7578063d18af54d146100cc578063ec9e80bb146100df57600080fd5b80631688f0b91461006c5780633408e470146100a9575b600080fd5b61007f61007a3660046105d2565b6100f2565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6040514681526020016100a0565b6100bf610194565b6040516100a091906106a5565b61007f6100da3660046106bf565b6101dc565b61007f6100ed3660046105d2565b6102f8565b600080838051906020012083604051602001610118929190918252602082015260400190565b60405160208183030381529060405280519060200120905061013b85858361032a565b60405173ffffffffffffffffffffffffffffffffffffffff8781168252919350908316907f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e2359060200160405180910390a2509392505050565b6060604051806020016101a6906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604052919050565b600080838360405160200161022092919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b6040516020818303038152906040528051906020012060001c90506102468686836100f2565b915073ffffffffffffffffffffffffffffffffffffffff8316156102ef576040517f1e52b51800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690631e52b518906102bc9085908a908a908a9060040161072b565b600060405180830381600087803b1580156102d657600080fd5b505af11580156102ea573d6000803e3d6000fd5b505050505b50949350505050565b60008083805190602001208361030b4690565b6040805160208101949094528301919091526060820152608001610118565b6000833b610399576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53696e676c65746f6e20636f6e7472616374206e6f74206465706c6f7965640060448201526064015b60405180910390fd5b6000604051806020016103ab906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052610403919073ffffffffffffffffffffffffffffffffffffffff881690602001610775565b6040516020818303038152906040529050828151826020016000f5915073ffffffffffffffffffffffffffffffffffffffff821661049d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f437265617465322063616c6c206661696c6564000000000000000000000000006044820152606401610390565b8351156104be5760008060008651602088016000875af1036104be57600080fd5b509392505050565b61016f8061079883390190565b73ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261053857600080fd5b813567ffffffffffffffff80821115610553576105536104f8565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610599576105996104f8565b816040528381528660208588010111156105b257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156105e757600080fd5b83356105f2816104d3565b9250602084013567ffffffffffffffff81111561060e57600080fd5b61061a86828701610527565b925050604084013590509250925092565b60005b8381101561064657818101518382015260200161062e565b83811115610655576000848401525b50505050565b6000815180845261067381602086016020860161062b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006106b8602083018461065b565b9392505050565b600080600080608085870312156106d557600080fd5b84356106e0816104d3565b9350602085013567ffffffffffffffff8111156106fc57600080fd5b61070887828801610527565b935050604085013591506060850135610720816104d3565b939692955090935050565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152610764608083018561065b565b905082606083015295945050505050565b6000835161078781846020880161062b565b919091019182525060200191905056fe608060405234801561001057600080fd5b5060405161016f38038061016f83398101604081905261002f916100b9565b6001600160a01b0381166100945760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642073696e676c65746f6e20616464726573732070726f766964604482015261195960f21b606482015260840160405180910390fd5b600080546001600160a01b0319166001600160a01b03929092169190911790556100e9565b6000602082840312156100cb57600080fd5b81516001600160a01b03811681146100e257600080fd5b9392505050565b6078806100f76000396000f3fe6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000aa164736f6c634300080f000a", + "deployedCode": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c806353e5d9351161005057806353e5d935146100b7578063d18af54d146100cc578063ec9e80bb146100df57600080fd5b80631688f0b91461006c5780633408e470146100a9575b600080fd5b61007f61007a3660046105d2565b6100f2565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6040514681526020016100a0565b6100bf610194565b6040516100a091906106a5565b61007f6100da3660046106bf565b6101dc565b61007f6100ed3660046105d2565b6102f8565b600080838051906020012083604051602001610118929190918252602082015260400190565b60405160208183030381529060405280519060200120905061013b85858361032a565b60405173ffffffffffffffffffffffffffffffffffffffff8781168252919350908316907f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e2359060200160405180910390a2509392505050565b6060604051806020016101a6906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604052919050565b600080838360405160200161022092919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b6040516020818303038152906040528051906020012060001c90506102468686836100f2565b915073ffffffffffffffffffffffffffffffffffffffff8316156102ef576040517f1e52b51800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690631e52b518906102bc9085908a908a908a9060040161072b565b600060405180830381600087803b1580156102d657600080fd5b505af11580156102ea573d6000803e3d6000fd5b505050505b50949350505050565b60008083805190602001208361030b4690565b6040805160208101949094528301919091526060820152608001610118565b6000833b610399576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53696e676c65746f6e20636f6e7472616374206e6f74206465706c6f7965640060448201526064015b60405180910390fd5b6000604051806020016103ab906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052610403919073ffffffffffffffffffffffffffffffffffffffff881690602001610775565b6040516020818303038152906040529050828151826020016000f5915073ffffffffffffffffffffffffffffffffffffffff821661049d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f437265617465322063616c6c206661696c6564000000000000000000000000006044820152606401610390565b8351156104be5760008060008651602088016000875af1036104be57600080fd5b509392505050565b61016f8061079883390190565b73ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261053857600080fd5b813567ffffffffffffffff80821115610553576105536104f8565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610599576105996104f8565b816040528381528660208588010111156105b257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156105e757600080fd5b83356105f2816104d3565b9250602084013567ffffffffffffffff81111561060e57600080fd5b61061a86828701610527565b925050604084013590509250925092565b60005b8381101561064657818101518382015260200161062e565b83811115610655576000848401525b50505050565b6000815180845261067381602086016020860161062b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006106b8602083018461065b565b9392505050565b600080600080608085870312156106d557600080fd5b84356106e0816104d3565b9350602085013567ffffffffffffffff8111156106fc57600080fd5b61070887828801610527565b935050604085013591506060850135610720816104d3565b939692955090935050565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152610764608083018561065b565b905082606083015295945050505050565b6000835161078781846020880161062b565b919091019182525060200191905056fe608060405234801561001057600080fd5b5060405161016f38038061016f83398101604081905261002f916100b9565b6001600160a01b0381166100945760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642073696e676c65746f6e20616464726573732070726f766964604482015261195960f21b606482015260840160405180910390fd5b600080546001600160a01b0319166001600160a01b03929092169190911790556100e9565b6000602082840312156100cb57600080fd5b81516001600160a01b03811681146100e257600080fd5b9392505050565b6078806100f76000396000f3fe6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000aa164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": false, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x608060405234801561001057600080fd5b506001600455614201806100256000396000f3fe6080604052600436106101d15760003560e01c8063affed0e0116100f7578063e19a9dd911610095578063f08a032311610064578063f08a0323146105f5578063f698da2514610615578063f8dc5dd91461067c578063ffa1ad741461069c5761020d565b8063e19a9dd914610580578063e318b52b146105a0578063e75235b8146105c0578063e86637db146105d55761020d565b8063cc2f8452116100d1578063cc2f8452146104f2578063d4d9bdcd14610520578063d8d11f7814610540578063e009cfde146105605761020d565b8063affed0e01461049c578063b4faba09146104b2578063b63e800d146104d25761020d565b80635624b25b1161016f5780636a7612021161013e5780636a7612021461040f5780637d83297414610422578063934f3a111461045a578063a0e67e2b1461047a5761020d565b80635624b25b146103755780635ae6bd37146103a2578063610b5925146103cf578063694e80c3146103ef5761020d565b80632f54bf6e116101ab5780632f54bf6e146102ea5780633408e4701461030a578063468721a7146103275780635229073f146103475761020d565b80630d582f131461027357806312fb68e0146102955780632d9ad53d146102b55761020d565b3661020d5760405134815233907f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d9060200160405180910390a2005b34801561021957600080fd5b507f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d580548061024457005b36600080373360601b365260008060143601600080855af190503d6000803e8061026d573d6000fd5b503d6000f35b34801561027f57600080fd5b5061029361028e366004613568565b6106e5565b005b3480156102a157600080fd5b506102936102b036600461366e565b610933565b3480156102c157600080fd5b506102d56102d03660046136e3565b610ff7565b60405190151581526020015b60405180910390f35b3480156102f657600080fd5b506102d56103053660046136e3565b61104c565b34801561031657600080fd5b50465b6040519081526020016102e1565b34801561033357600080fd5b506102d561034236600461370f565b61109e565b34801561035357600080fd5b5061036761036236600461370f565b6111d4565b6040516102e19291906137e4565b34801561038157600080fd5b506103956103903660046137ff565b61120a565b6040516102e19190613821565b3480156103ae57600080fd5b506103196103bd366004613834565b60076020526000908152604090205481565b3480156103db57600080fd5b506102936103ea3660046136e3565b611290565b3480156103fb57600080fd5b5061029361040a366004613834565b611479565b6102d561041d366004613896565b611593565b34801561042e57600080fd5b5061031961043d366004613568565b600860209081526000928352604080842090915290825290205481565b34801561046657600080fd5b5061029361047536600461396f565b61198f565b34801561048657600080fd5b5061048f611a0b565b6040516102e19190613a2d565b3480156104a857600080fd5b5061031960055481565b3480156104be57600080fd5b506102936104cd366004613a40565b611b23565b3480156104de57600080fd5b506102936104ed366004613a90565b611b46565b3480156104fe57600080fd5b5061051261050d366004613568565b611c62565b6040516102e1929190613b85565b34801561052c57600080fd5b5061029361053b366004613834565b611ed0565b34801561054c57600080fd5b5061031961055b366004613bbd565b611fa4565b34801561056c57600080fd5b5061029361057b366004613c7e565b611fd1565b34801561058c57600080fd5b5061029361059b3660046136e3565b6121a3565b3480156105ac57600080fd5b506102936105bb366004613cb7565b612344565b3480156105cc57600080fd5b50600454610319565b3480156105e157600080fd5b506103956105f0366004613bbd565b6126bc565b34801561060157600080fd5b506102936106103660046136e3565b612855565b34801561062157600080fd5b5061031960007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b34801561068857600080fd5b50610293610697366004613d02565b6128aa565b3480156106a857600080fd5b506103956040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b6106ed612b34565b73ffffffffffffffffffffffffffffffffffffffff821615801590610729575073ffffffffffffffffffffffffffffffffffffffff8216600114155b801561074b575073ffffffffffffffffffffffffffffffffffffffff82163014155b6107b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600260205260409020541615610845576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b60026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0805473ffffffffffffffffffffffffffffffffffffffff8481166000818152604081208054939094167fffffffffffffffffffffffff0000000000000000000000000000000000000000938416179093556001835283549091161790915560038054916108d783613d72565b909155505060405173ffffffffffffffffffffffffffffffffffffffff8316907f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2690600090a2806004541461092f5761092f81611479565b5050565b61093e816041612b9f565b825110156109a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6000808060008060005b86811015610feb576041818102890160208101516040820151919092015160ff16955090935091506000849003610cf857885160208a01208a14610a52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323700000000000000000000000000000000000000000000000000000060448201526064016107ad565b9193508391610a62876041612b9f565b821015610acb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323100000000000000000000000000000000000000000000000000000060448201526064016107ad565b8751610ad8836020612bdb565b1115610b40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323200000000000000000000000000000000000000000000000000000060448201526064016107ad565b602082890181015189519091610b63908390610b5d908790612bdb565b90612bdb565b1115610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323300000000000000000000000000000000000000000000000000000060448201526064016107ad565b6040517f20c13b0b000000000000000000000000000000000000000000000000000000008082528a85016020019173ffffffffffffffffffffffffffffffffffffffff8916906320c13b0b90610c27908f908690600401613daa565b602060405180830381865afa158015610c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c689190613dcf565b7fffffffff000000000000000000000000000000000000000000000000000000001614610cf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323400000000000000000000000000000000000000000000000000000060448201526064016107ad565b5050610eeb565b8360ff16600103610dc65791935083913373ffffffffffffffffffffffffffffffffffffffff84161480610d5b575073ffffffffffffffffffffffffffffffffffffffff851660009081526008602090815260408083208d845290915290205415155b610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323500000000000000000000000000000000000000000000000000000060448201526064016107ad565b610eeb565b601e8460ff161115610e8b576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018b9052600190605c0160405160208183030381529060405280519060200120600486610e2b9190613e11565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610e7a573d6000803e3d6000fd5b505050602060405103519450610eeb565b6040805160008152602081018083528c905260ff861691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa158015610ede573d6000803e3d6000fd5b5050506020604051035194505b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16118015610f4c575073ffffffffffffffffffffffffffffffffffffffff8581166000908152600260205260409020541615155b8015610f6f575073ffffffffffffffffffffffffffffffffffffffff8516600114155b610fd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323600000000000000000000000000000000000000000000000000000060448201526064016107ad565b8495508080610fe390613d72565b9150506109b2565b50505050505050505050565b6000600173ffffffffffffffffffffffffffffffffffffffff831614801590611046575073ffffffffffffffffffffffffffffffffffffffff8281166000908152600160205260409020541615155b92915050565b600073ffffffffffffffffffffffffffffffffffffffff821660011480159061104657505073ffffffffffffffffffffffffffffffffffffffff90811660009081526002602052604090205416151590565b6000336001148015906110d557503360009081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff1615155b61113b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b611168858585857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612bf7565b905080156111a05760405133907f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb890600090a26111cc565b60405133907facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37590600090a25b949350505050565b600060606111e48686868661109e565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b60606000611219836020613e34565b67ffffffffffffffff81111561123157611231613594565b6040519080825280601f01601f19166020018201604052801561125b576020820181803683370190505b50905060005b8381101561128857848101546020808302840101528061128081613d72565b915050611261565b509392505050565b611298612b34565b73ffffffffffffffffffffffffffffffffffffffff8116158015906112d4575073ffffffffffffffffffffffffffffffffffffffff8116600114155b61133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff81811660009081526001602052604090205416156113c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b600160208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f805473ffffffffffffffffffffffffffffffffffffffff848116600081815260408082208054949095167fffffffffffffffffffffffff000000000000000000000000000000000000000094851617909455948552835490911681179092555190917fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844091a250565b611481612b34565b6003548111156114ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001811015611558576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b60048190556040518181527f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c939060200160405180910390a150565b60008060006115ad8e8e8e8e8e8e8e8e8e8e6005546126bc565b6005805491925060006115bf83613d72565b90915550508051602082012091506115d882828661198f565b5060006116037f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c85490565b905073ffffffffffffffffffffffffffffffffffffffff8116156116a3578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b81526004016116709c9b9a99989796959493929190613edb565b600060405180830381600087803b15801561168a57600080fd5b505af115801561169e573d6000803e3d6000fd5b505050505b6116cf6116b28a6109c4613ff1565b603f6116bf8c6040613e34565b6116c99190614009565b90612c3e565b6116db906101f4613ff1565b5a1015611744576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313000000000000000000000000000000000000000000000000000000060448201526064016107ad565b60005a90506117b58f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8c6000146117a2578e612bf7565b6109c45a6117b09190614044565b612bf7565b93506117c25a8290612c55565b905083806117cf57508915155b806117d957508715155b61183f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313300000000000000000000000000000000000000000000000000000060448201526064016107ad565b6000881561185757611854828b8b8b8b612c70565b90505b841561189c57837f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e8260405161188f91815260200190565b60405180910390a26118d7565b837f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23826040516118ce91815260200190565b60405180910390a25b505073ffffffffffffffffffffffffffffffffffffffff81161561197e576040517f9327136800000000000000000000000000000000000000000000000000000000815260048101839052831515602482015273ffffffffffffffffffffffffffffffffffffffff821690639327136890604401600060405180830381600087803b15801561196557600080fd5b505af1158015611979573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b600454806119f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b611a0584848484610933565b50505050565b6060600060035467ffffffffffffffff811115611a2a57611a2a613594565b604051908082528060200260200182016040528015611a53578160200160208202803683370190505b506001600090815260026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0549192509073ffffffffffffffffffffffffffffffffffffffff165b73ffffffffffffffffffffffffffffffffffffffff8116600114611b1b5780838381518110611ace57611ace61405b565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152918116600090815260029092526040909120541681611b1381613d72565b925050611a9d565b509092915050565b600080825160208401855af480600052503d6020523d600060403e60403d016000fd5b611b848a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9250612e01915050565b73ffffffffffffffffffffffffffffffffffffffff841615611ba957611ba9846131ce565b611be98787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061327192505050565b8115611c0057611bfe82600060018685612c70565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b89604051611c4e95949392919061408a565b60405180910390a250505050505050505050565b6060600073ffffffffffffffffffffffffffffffffffffffff841660011480611c8f5750611c8f84610ff7565b611cf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b60008311611d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303600000000000000000000000000000000000000000000000000000060448201526064016107ad565b8267ffffffffffffffff811115611d7857611d78613594565b604051908082528060200260200182016040528015611da1578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff808616600090815260016020526040812054929450911691505b73ffffffffffffffffffffffffffffffffffffffff821615801590611e0d575073ffffffffffffffffffffffffffffffffffffffff8216600114155b8015611e1857508381105b15611e805781838281518110611e3057611e3061405b565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152928116600090815260019093526040909220549091169080611e7881613d72565b915050611dd1565b73ffffffffffffffffffffffffffffffffffffffff8216600114611ec55782611eaa600183614044565b81518110611eba57611eba61405b565b602002602001015191505b808352509250929050565b3360009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16611f5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333000000000000000000000000000000000000000000000000000000060448201526064016107ad565b336000818152600860209081526040808320858452909152808220600190555183917ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c91a350565b6000611fb98c8c8c8c8c8c8c8c8c8c8c6126bc565b8051906020012090509b9a5050505050505050505050565b611fd9612b34565b73ffffffffffffffffffffffffffffffffffffffff811615801590612015575073ffffffffffffffffffffffffffffffffffffffff8116600114155b61207b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526001602052604090205481169082161461210e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff818116600081815260016020526040808220805487861684528284208054919096167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179095558383528054909416909355915190917faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427691a25050565b6121ab612b34565b73ffffffffffffffffffffffffffffffffffffffff8116156122db576040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527fe6d7a83a00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015612251573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122759190614110565b6122db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475333303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c881815560405173ffffffffffffffffffffffffffffffffffffffff8316907f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa290600090a25050565b61234c612b34565b73ffffffffffffffffffffffffffffffffffffffff811615801590612388575073ffffffffffffffffffffffffffffffffffffffff8116600114155b80156123aa575073ffffffffffffffffffffffffffffffffffffffff81163014155b612410576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff818116600090815260026020526040902054161561249f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8216158015906124db575073ffffffffffffffffffffffffffffffffffffffff8216600114155b612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600260205260409020548116908316146125d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805486861680855283852080549288167fffffffffffffffffffffffff00000000000000000000000000000000000000009384161790559589168452828420805482169096179095558383528054909416909355915190917ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf91a260405173ffffffffffffffffffffffffffffffffffffffff8216907f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2690600090a2505050565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d6040516126f6929190614132565b60405190819003812061271c949392918e908e908e908e908e908e908e90602001614142565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012090507f19000000000000000000000000000000000000000000000000000000000000007f01000000000000000000000000000000000000000000000000000000000000006127f060007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b6040517fff0000000000000000000000000000000000000000000000000000000000000093841660208201529290911660218301526022820152604281018290526062016040516020818303038152906040529150509b9a5050505050505050505050565b61285d612b34565b612866816131ce565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b090600090a250565b6128b2612b34565b8060016003546128c29190614044565b101561292a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff821615801590612966575073ffffffffffffffffffffffffffffffffffffffff8216600114155b6129cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff838116600090815260026020526040902054811690831614612a5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805488861684529183208054929095167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790945591815282549091169091556003805491612ad7836141bf565b909155505060405173ffffffffffffffffffffffffffffffffffffffff8316907ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf90600090a28060045414612b2f57612b2f81611479565b505050565b333014612b9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333100000000000000000000000000000000000000000000000000000060448201526064016107ad565b565b600082600003612bb157506000611046565b6000612bbd8385613e34565b905082612bca8583614009565b14612bd457600080fd5b9392505050565b600080612be88385613ff1565b905083811015612bd457600080fd5b60006001836001811115612c0d57612c0d613e71565b03612c25576000808551602087018986f49050612c35565b600080855160208701888a87f190505b95945050505050565b600081831015612c4e5781612bd4565b5090919050565b600082821115612c6457600080fd5b60006111cc8385614044565b60008073ffffffffffffffffffffffffffffffffffffffff831615612c955782612c97565b325b905073ffffffffffffffffffffffffffffffffffffffff8416612d7657612cd63a8610612cc4573a612cc6565b855b612cd08989612bdb565b90612b9f565b60405190925073ffffffffffffffffffffffffffffffffffffffff82169083156108fc029084906000818181858888f19350505050612d71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313100000000000000000000000000000000000000000000000000000060448201526064016107ad565b612df7565b612d8485612cd08989612bdb565b9150612d91848284613469565b612df7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313200000000000000000000000000000000000000000000000000000060448201526064016107ad565b5095945050505050565b60045415612e6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b8151811115612ed6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001811015612f41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b600160005b8351811015613176576000848281518110612f6357612f6361405b565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015612fc1575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015612fe3575073ffffffffffffffffffffffffffffffffffffffff81163014155b801561301b57508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b613081576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600260205260409020541615613110576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff928316600090815260026020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016938216939093179092558061316e81613d72565b915050612f46565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260026020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790559051600355600455565b3073ffffffffffffffffffffffffffffffffffffffff82160361324d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475334303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b7f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d555565b600160008190526020527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f5473ffffffffffffffffffffffffffffffffffffffff161561331a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001600081905260208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f80547fffffffffffffffffffffffff000000000000000000000000000000000000000016909117905573ffffffffffffffffffffffffffffffffffffffff82161561092f57813b6133f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b6134038260008360015a612bf7565b61092f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6040805173ffffffffffffffffffffffffffffffffffffffff841660248201526044808201849052825180830390910181526064909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781528251600093929184919082896127105a03f13d8015613516576020811461351e5760009350613529565b819350613529565b600051158215171593505b5050509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461355557600080fd5b50565b803561356381613533565b919050565b6000806040838503121561357b57600080fd5b823561358681613533565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126135d457600080fd5b813567ffffffffffffffff808211156135ef576135ef613594565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561363557613635613594565b8160405283815286602085880101111561364e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561368457600080fd5b84359350602085013567ffffffffffffffff808211156136a357600080fd5b6136af888389016135c3565b945060408701359150808211156136c557600080fd5b506136d2878288016135c3565b949793965093946060013593505050565b6000602082840312156136f557600080fd5b8135612bd481613533565b80356002811061356357600080fd5b6000806000806080858703121561372557600080fd5b843561373081613533565b935060208501359250604085013567ffffffffffffffff81111561375357600080fd5b61375f878288016135c3565b92505061376e60608601613700565b905092959194509250565b6000815180845260005b8181101561379f57602081850181015186830182015201613783565b818111156137b1576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b82151581526040602082015260006111cc6040830184613779565b6000806040838503121561381257600080fd5b50508035926020909101359150565b602081526000612bd46020830184613779565b60006020828403121561384657600080fd5b5035919050565b60008083601f84011261385f57600080fd5b50813567ffffffffffffffff81111561387757600080fd5b60208301915083602082850101111561388f57600080fd5b9250929050565b60008060008060008060008060008060006101408c8e0312156138b857600080fd5b6138c18c613558565b9a5060208c0135995067ffffffffffffffff8060408e013511156138e457600080fd5b6138f48e60408f01358f0161384d565b909a50985061390560608e01613700565b975060808d0135965060a08d0135955060c08d0135945061392860e08e01613558565b93506139376101008e01613558565b9250806101208e0135111561394b57600080fd5b5061395d8d6101208e01358e016135c3565b90509295989b509295989b9093969950565b60008060006060848603121561398457600080fd5b83359250602084013567ffffffffffffffff808211156139a357600080fd5b6139af878388016135c3565b935060408601359150808211156139c557600080fd5b506139d2868287016135c3565b9150509250925092565b600081518084526020808501945080840160005b83811015613a2257815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016139f0565b509495945050505050565b602081526000612bd460208301846139dc565b60008060408385031215613a5357600080fd5b8235613a5e81613533565b9150602083013567ffffffffffffffff811115613a7a57600080fd5b613a86858286016135c3565b9150509250929050565b6000806000806000806000806000806101008b8d031215613ab057600080fd5b8a3567ffffffffffffffff80821115613ac857600080fd5b818d0191508d601f830112613adc57600080fd5b813581811115613aeb57600080fd5b8e60208260051b8501011115613b0057600080fd5b60208381019d50909b508d01359950613b1b60408e01613558565b985060608d0135915080821115613b3157600080fd5b50613b3e8d828e0161384d565b9097509550613b51905060808c01613558565b9350613b5f60a08c01613558565b925060c08b01359150613b7460e08c01613558565b90509295989b9194979a5092959850565b604081526000613b9860408301856139dc565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b60008060008060008060008060008060006101408c8e031215613bdf57600080fd5b8b35613bea81613533565b9a5060208c0135995060408c013567ffffffffffffffff811115613c0d57600080fd5b613c198e828f0161384d565b909a509850613c2c905060608d01613700565b965060808c0135955060a08c0135945060c08c0135935060e08c0135613c5181613533565b92506101008c0135613c6281613533565b809250506101208c013590509295989b509295989b9093969950565b60008060408385031215613c9157600080fd5b8235613c9c81613533565b91506020830135613cac81613533565b809150509250929050565b600080600060608486031215613ccc57600080fd5b8335613cd781613533565b92506020840135613ce781613533565b91506040840135613cf781613533565b809150509250925092565b600080600060608486031215613d1757600080fd5b8335613d2281613533565b92506020840135613d3281613533565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613da357613da3613d43565b5060010190565b604081526000613dbd6040830185613779565b8281036020840152612c358185613779565b600060208284031215613de157600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114612bd457600080fd5b600060ff821660ff841680821015613e2b57613e2b613d43565b90039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613e6c57613e6c613d43565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110613ed7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b600061016073ffffffffffffffffffffffffffffffffffffffff8f1683528d60208401528060408401528b81840152506101808b8d828501376000818d850101527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8d01168301613f51606085018d613ea0565b8a60808501528960a08501528860c0850152613f8560e085018973ffffffffffffffffffffffffffffffffffffffff169052565b73ffffffffffffffffffffffffffffffffffffffff87166101008501528184820301610120850152613fb982820187613779565b92505050613fe061014083018473ffffffffffffffffffffffffffffffffffffffff169052565b9d9c50505050505050505050505050565b6000821982111561400457614004613d43565b500190565b60008261403f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008282101561405657614056613d43565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6080808252810185905260008660a08301825b888110156140da5782356140b081613533565b73ffffffffffffffffffffffffffffffffffffffff1682526020928301929091019060010161409d565b506020840196909652505073ffffffffffffffffffffffffffffffffffffffff9283166040820152911660609091015292915050565b60006020828403121561412257600080fd5b81518015158114612bd457600080fd5b8183823760009101908152919050565b6000610160820190508c825273ffffffffffffffffffffffffffffffffffffffff808d1660208401528b60408401528a6060840152614184608084018b613ea0565b60a083019890985260c082019690965260e0810194909452918516610100840152909316610120820152610140019190915295945050505050565b6000816141ce576141ce613d43565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea164736f6c634300080f000a", + "deployedCode": "0x6080604052600436106101d15760003560e01c8063affed0e0116100f7578063e19a9dd911610095578063f08a032311610064578063f08a0323146105f5578063f698da2514610615578063f8dc5dd91461067c578063ffa1ad741461069c5761020d565b8063e19a9dd914610580578063e318b52b146105a0578063e75235b8146105c0578063e86637db146105d55761020d565b8063cc2f8452116100d1578063cc2f8452146104f2578063d4d9bdcd14610520578063d8d11f7814610540578063e009cfde146105605761020d565b8063affed0e01461049c578063b4faba09146104b2578063b63e800d146104d25761020d565b80635624b25b1161016f5780636a7612021161013e5780636a7612021461040f5780637d83297414610422578063934f3a111461045a578063a0e67e2b1461047a5761020d565b80635624b25b146103755780635ae6bd37146103a2578063610b5925146103cf578063694e80c3146103ef5761020d565b80632f54bf6e116101ab5780632f54bf6e146102ea5780633408e4701461030a578063468721a7146103275780635229073f146103475761020d565b80630d582f131461027357806312fb68e0146102955780632d9ad53d146102b55761020d565b3661020d5760405134815233907f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d9060200160405180910390a2005b34801561021957600080fd5b507f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d580548061024457005b36600080373360601b365260008060143601600080855af190503d6000803e8061026d573d6000fd5b503d6000f35b34801561027f57600080fd5b5061029361028e366004613568565b6106e5565b005b3480156102a157600080fd5b506102936102b036600461366e565b610933565b3480156102c157600080fd5b506102d56102d03660046136e3565b610ff7565b60405190151581526020015b60405180910390f35b3480156102f657600080fd5b506102d56103053660046136e3565b61104c565b34801561031657600080fd5b50465b6040519081526020016102e1565b34801561033357600080fd5b506102d561034236600461370f565b61109e565b34801561035357600080fd5b5061036761036236600461370f565b6111d4565b6040516102e19291906137e4565b34801561038157600080fd5b506103956103903660046137ff565b61120a565b6040516102e19190613821565b3480156103ae57600080fd5b506103196103bd366004613834565b60076020526000908152604090205481565b3480156103db57600080fd5b506102936103ea3660046136e3565b611290565b3480156103fb57600080fd5b5061029361040a366004613834565b611479565b6102d561041d366004613896565b611593565b34801561042e57600080fd5b5061031961043d366004613568565b600860209081526000928352604080842090915290825290205481565b34801561046657600080fd5b5061029361047536600461396f565b61198f565b34801561048657600080fd5b5061048f611a0b565b6040516102e19190613a2d565b3480156104a857600080fd5b5061031960055481565b3480156104be57600080fd5b506102936104cd366004613a40565b611b23565b3480156104de57600080fd5b506102936104ed366004613a90565b611b46565b3480156104fe57600080fd5b5061051261050d366004613568565b611c62565b6040516102e1929190613b85565b34801561052c57600080fd5b5061029361053b366004613834565b611ed0565b34801561054c57600080fd5b5061031961055b366004613bbd565b611fa4565b34801561056c57600080fd5b5061029361057b366004613c7e565b611fd1565b34801561058c57600080fd5b5061029361059b3660046136e3565b6121a3565b3480156105ac57600080fd5b506102936105bb366004613cb7565b612344565b3480156105cc57600080fd5b50600454610319565b3480156105e157600080fd5b506103956105f0366004613bbd565b6126bc565b34801561060157600080fd5b506102936106103660046136e3565b612855565b34801561062157600080fd5b5061031960007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b34801561068857600080fd5b50610293610697366004613d02565b6128aa565b3480156106a857600080fd5b506103956040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b6106ed612b34565b73ffffffffffffffffffffffffffffffffffffffff821615801590610729575073ffffffffffffffffffffffffffffffffffffffff8216600114155b801561074b575073ffffffffffffffffffffffffffffffffffffffff82163014155b6107b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600260205260409020541615610845576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b60026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0805473ffffffffffffffffffffffffffffffffffffffff8481166000818152604081208054939094167fffffffffffffffffffffffff0000000000000000000000000000000000000000938416179093556001835283549091161790915560038054916108d783613d72565b909155505060405173ffffffffffffffffffffffffffffffffffffffff8316907f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2690600090a2806004541461092f5761092f81611479565b5050565b61093e816041612b9f565b825110156109a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6000808060008060005b86811015610feb576041818102890160208101516040820151919092015160ff16955090935091506000849003610cf857885160208a01208a14610a52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323700000000000000000000000000000000000000000000000000000060448201526064016107ad565b9193508391610a62876041612b9f565b821015610acb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323100000000000000000000000000000000000000000000000000000060448201526064016107ad565b8751610ad8836020612bdb565b1115610b40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323200000000000000000000000000000000000000000000000000000060448201526064016107ad565b602082890181015189519091610b63908390610b5d908790612bdb565b90612bdb565b1115610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323300000000000000000000000000000000000000000000000000000060448201526064016107ad565b6040517f20c13b0b000000000000000000000000000000000000000000000000000000008082528a85016020019173ffffffffffffffffffffffffffffffffffffffff8916906320c13b0b90610c27908f908690600401613daa565b602060405180830381865afa158015610c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c689190613dcf565b7fffffffff000000000000000000000000000000000000000000000000000000001614610cf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323400000000000000000000000000000000000000000000000000000060448201526064016107ad565b5050610eeb565b8360ff16600103610dc65791935083913373ffffffffffffffffffffffffffffffffffffffff84161480610d5b575073ffffffffffffffffffffffffffffffffffffffff851660009081526008602090815260408083208d845290915290205415155b610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323500000000000000000000000000000000000000000000000000000060448201526064016107ad565b610eeb565b601e8460ff161115610e8b576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018b9052600190605c0160405160208183030381529060405280519060200120600486610e2b9190613e11565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610e7a573d6000803e3d6000fd5b505050602060405103519450610eeb565b6040805160008152602081018083528c905260ff861691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa158015610ede573d6000803e3d6000fd5b5050506020604051035194505b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16118015610f4c575073ffffffffffffffffffffffffffffffffffffffff8581166000908152600260205260409020541615155b8015610f6f575073ffffffffffffffffffffffffffffffffffffffff8516600114155b610fd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323600000000000000000000000000000000000000000000000000000060448201526064016107ad565b8495508080610fe390613d72565b9150506109b2565b50505050505050505050565b6000600173ffffffffffffffffffffffffffffffffffffffff831614801590611046575073ffffffffffffffffffffffffffffffffffffffff8281166000908152600160205260409020541615155b92915050565b600073ffffffffffffffffffffffffffffffffffffffff821660011480159061104657505073ffffffffffffffffffffffffffffffffffffffff90811660009081526002602052604090205416151590565b6000336001148015906110d557503360009081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff1615155b61113b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b611168858585857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612bf7565b905080156111a05760405133907f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb890600090a26111cc565b60405133907facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37590600090a25b949350505050565b600060606111e48686868661109e565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b60606000611219836020613e34565b67ffffffffffffffff81111561123157611231613594565b6040519080825280601f01601f19166020018201604052801561125b576020820181803683370190505b50905060005b8381101561128857848101546020808302840101528061128081613d72565b915050611261565b509392505050565b611298612b34565b73ffffffffffffffffffffffffffffffffffffffff8116158015906112d4575073ffffffffffffffffffffffffffffffffffffffff8116600114155b61133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff81811660009081526001602052604090205416156113c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b600160208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f805473ffffffffffffffffffffffffffffffffffffffff848116600081815260408082208054949095167fffffffffffffffffffffffff000000000000000000000000000000000000000094851617909455948552835490911681179092555190917fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844091a250565b611481612b34565b6003548111156114ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001811015611558576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b60048190556040518181527f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c939060200160405180910390a150565b60008060006115ad8e8e8e8e8e8e8e8e8e8e6005546126bc565b6005805491925060006115bf83613d72565b90915550508051602082012091506115d882828661198f565b5060006116037f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c85490565b905073ffffffffffffffffffffffffffffffffffffffff8116156116a3578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b81526004016116709c9b9a99989796959493929190613edb565b600060405180830381600087803b15801561168a57600080fd5b505af115801561169e573d6000803e3d6000fd5b505050505b6116cf6116b28a6109c4613ff1565b603f6116bf8c6040613e34565b6116c99190614009565b90612c3e565b6116db906101f4613ff1565b5a1015611744576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313000000000000000000000000000000000000000000000000000000060448201526064016107ad565b60005a90506117b58f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8c6000146117a2578e612bf7565b6109c45a6117b09190614044565b612bf7565b93506117c25a8290612c55565b905083806117cf57508915155b806117d957508715155b61183f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313300000000000000000000000000000000000000000000000000000060448201526064016107ad565b6000881561185757611854828b8b8b8b612c70565b90505b841561189c57837f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e8260405161188f91815260200190565b60405180910390a26118d7565b837f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23826040516118ce91815260200190565b60405180910390a25b505073ffffffffffffffffffffffffffffffffffffffff81161561197e576040517f9327136800000000000000000000000000000000000000000000000000000000815260048101839052831515602482015273ffffffffffffffffffffffffffffffffffffffff821690639327136890604401600060405180830381600087803b15801561196557600080fd5b505af1158015611979573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b600454806119f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b611a0584848484610933565b50505050565b6060600060035467ffffffffffffffff811115611a2a57611a2a613594565b604051908082528060200260200182016040528015611a53578160200160208202803683370190505b506001600090815260026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0549192509073ffffffffffffffffffffffffffffffffffffffff165b73ffffffffffffffffffffffffffffffffffffffff8116600114611b1b5780838381518110611ace57611ace61405b565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152918116600090815260029092526040909120541681611b1381613d72565b925050611a9d565b509092915050565b600080825160208401855af480600052503d6020523d600060403e60403d016000fd5b611b848a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9250612e01915050565b73ffffffffffffffffffffffffffffffffffffffff841615611ba957611ba9846131ce565b611be98787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061327192505050565b8115611c0057611bfe82600060018685612c70565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b89604051611c4e95949392919061408a565b60405180910390a250505050505050505050565b6060600073ffffffffffffffffffffffffffffffffffffffff841660011480611c8f5750611c8f84610ff7565b611cf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b60008311611d5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303600000000000000000000000000000000000000000000000000000060448201526064016107ad565b8267ffffffffffffffff811115611d7857611d78613594565b604051908082528060200260200182016040528015611da1578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff808616600090815260016020526040812054929450911691505b73ffffffffffffffffffffffffffffffffffffffff821615801590611e0d575073ffffffffffffffffffffffffffffffffffffffff8216600114155b8015611e1857508381105b15611e805781838281518110611e3057611e3061405b565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152928116600090815260019093526040909220549091169080611e7881613d72565b915050611dd1565b73ffffffffffffffffffffffffffffffffffffffff8216600114611ec55782611eaa600183614044565b81518110611eba57611eba61405b565b602002602001015191505b808352509250929050565b3360009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16611f5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333000000000000000000000000000000000000000000000000000000060448201526064016107ad565b336000818152600860209081526040808320858452909152808220600190555183917ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c91a350565b6000611fb98c8c8c8c8c8c8c8c8c8c8c6126bc565b8051906020012090509b9a5050505050505050505050565b611fd9612b34565b73ffffffffffffffffffffffffffffffffffffffff811615801590612015575073ffffffffffffffffffffffffffffffffffffffff8116600114155b61207b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526001602052604090205481169082161461210e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff818116600081815260016020526040808220805487861684528284208054919096167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179095558383528054909416909355915190917faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427691a25050565b6121ab612b34565b73ffffffffffffffffffffffffffffffffffffffff8116156122db576040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527fe6d7a83a00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015612251573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122759190614110565b6122db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475333303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c881815560405173ffffffffffffffffffffffffffffffffffffffff8316907f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa290600090a25050565b61234c612b34565b73ffffffffffffffffffffffffffffffffffffffff811615801590612388575073ffffffffffffffffffffffffffffffffffffffff8116600114155b80156123aa575073ffffffffffffffffffffffffffffffffffffffff81163014155b612410576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff818116600090815260026020526040902054161561249f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8216158015906124db575073ffffffffffffffffffffffffffffffffffffffff8216600114155b612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600260205260409020548116908316146125d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805486861680855283852080549288167fffffffffffffffffffffffff00000000000000000000000000000000000000009384161790559589168452828420805482169096179095558383528054909416909355915190917ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf91a260405173ffffffffffffffffffffffffffffffffffffffff8216907f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea2690600090a2505050565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d6040516126f6929190614132565b60405190819003812061271c949392918e908e908e908e908e908e908e90602001614142565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012090507f19000000000000000000000000000000000000000000000000000000000000007f01000000000000000000000000000000000000000000000000000000000000006127f060007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b6040517fff0000000000000000000000000000000000000000000000000000000000000093841660208201529290911660218301526022820152604281018290526062016040516020818303038152906040529150509b9a5050505050505050505050565b61285d612b34565b612866816131ce565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b090600090a250565b6128b2612b34565b8060016003546128c29190614044565b101561292a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff821615801590612966575073ffffffffffffffffffffffffffffffffffffffff8216600114155b6129cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff838116600090815260026020526040902054811690831614612a5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805488861684529183208054929095167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790945591815282549091169091556003805491612ad7836141bf565b909155505060405173ffffffffffffffffffffffffffffffffffffffff8316907ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf90600090a28060045414612b2f57612b2f81611479565b505050565b333014612b9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333100000000000000000000000000000000000000000000000000000060448201526064016107ad565b565b600082600003612bb157506000611046565b6000612bbd8385613e34565b905082612bca8583614009565b14612bd457600080fd5b9392505050565b600080612be88385613ff1565b905083811015612bd457600080fd5b60006001836001811115612c0d57612c0d613e71565b03612c25576000808551602087018986f49050612c35565b600080855160208701888a87f190505b95945050505050565b600081831015612c4e5781612bd4565b5090919050565b600082821115612c6457600080fd5b60006111cc8385614044565b60008073ffffffffffffffffffffffffffffffffffffffff831615612c955782612c97565b325b905073ffffffffffffffffffffffffffffffffffffffff8416612d7657612cd63a8610612cc4573a612cc6565b855b612cd08989612bdb565b90612b9f565b60405190925073ffffffffffffffffffffffffffffffffffffffff82169083156108fc029084906000818181858888f19350505050612d71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313100000000000000000000000000000000000000000000000000000060448201526064016107ad565b612df7565b612d8485612cd08989612bdb565b9150612d91848284613469565b612df7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313200000000000000000000000000000000000000000000000000000060448201526064016107ad565b5095945050505050565b60045415612e6b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b8151811115612ed6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001811015612f41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b600160005b8351811015613176576000848281518110612f6357612f6361405b565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015612fc1575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015612fe3575073ffffffffffffffffffffffffffffffffffffffff81163014155b801561301b57508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b613081576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600260205260409020541615613110576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107ad565b73ffffffffffffffffffffffffffffffffffffffff928316600090815260026020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016938216939093179092558061316e81613d72565b915050612f46565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260026020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790559051600355600455565b3073ffffffffffffffffffffffffffffffffffffffff82160361324d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475334303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b7f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d555565b600160008190526020527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f5473ffffffffffffffffffffffffffffffffffffffff161561331a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6001600081905260208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f80547fffffffffffffffffffffffff000000000000000000000000000000000000000016909117905573ffffffffffffffffffffffffffffffffffffffff82161561092f57813b6133f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303200000000000000000000000000000000000000000000000000000060448201526064016107ad565b6134038260008360015a612bf7565b61092f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303000000000000000000000000000000000000000000000000000000060448201526064016107ad565b6040805173ffffffffffffffffffffffffffffffffffffffff841660248201526044808201849052825180830390910181526064909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781528251600093929184919082896127105a03f13d8015613516576020811461351e5760009350613529565b819350613529565b600051158215171593505b5050509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461355557600080fd5b50565b803561356381613533565b919050565b6000806040838503121561357b57600080fd5b823561358681613533565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126135d457600080fd5b813567ffffffffffffffff808211156135ef576135ef613594565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561363557613635613594565b8160405283815286602085880101111561364e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561368457600080fd5b84359350602085013567ffffffffffffffff808211156136a357600080fd5b6136af888389016135c3565b945060408701359150808211156136c557600080fd5b506136d2878288016135c3565b949793965093946060013593505050565b6000602082840312156136f557600080fd5b8135612bd481613533565b80356002811061356357600080fd5b6000806000806080858703121561372557600080fd5b843561373081613533565b935060208501359250604085013567ffffffffffffffff81111561375357600080fd5b61375f878288016135c3565b92505061376e60608601613700565b905092959194509250565b6000815180845260005b8181101561379f57602081850181015186830182015201613783565b818111156137b1576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b82151581526040602082015260006111cc6040830184613779565b6000806040838503121561381257600080fd5b50508035926020909101359150565b602081526000612bd46020830184613779565b60006020828403121561384657600080fd5b5035919050565b60008083601f84011261385f57600080fd5b50813567ffffffffffffffff81111561387757600080fd5b60208301915083602082850101111561388f57600080fd5b9250929050565b60008060008060008060008060008060006101408c8e0312156138b857600080fd5b6138c18c613558565b9a5060208c0135995067ffffffffffffffff8060408e013511156138e457600080fd5b6138f48e60408f01358f0161384d565b909a50985061390560608e01613700565b975060808d0135965060a08d0135955060c08d0135945061392860e08e01613558565b93506139376101008e01613558565b9250806101208e0135111561394b57600080fd5b5061395d8d6101208e01358e016135c3565b90509295989b509295989b9093969950565b60008060006060848603121561398457600080fd5b83359250602084013567ffffffffffffffff808211156139a357600080fd5b6139af878388016135c3565b935060408601359150808211156139c557600080fd5b506139d2868287016135c3565b9150509250925092565b600081518084526020808501945080840160005b83811015613a2257815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016139f0565b509495945050505050565b602081526000612bd460208301846139dc565b60008060408385031215613a5357600080fd5b8235613a5e81613533565b9150602083013567ffffffffffffffff811115613a7a57600080fd5b613a86858286016135c3565b9150509250929050565b6000806000806000806000806000806101008b8d031215613ab057600080fd5b8a3567ffffffffffffffff80821115613ac857600080fd5b818d0191508d601f830112613adc57600080fd5b813581811115613aeb57600080fd5b8e60208260051b8501011115613b0057600080fd5b60208381019d50909b508d01359950613b1b60408e01613558565b985060608d0135915080821115613b3157600080fd5b50613b3e8d828e0161384d565b9097509550613b51905060808c01613558565b9350613b5f60a08c01613558565b925060c08b01359150613b7460e08c01613558565b90509295989b9194979a5092959850565b604081526000613b9860408301856139dc565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b60008060008060008060008060008060006101408c8e031215613bdf57600080fd5b8b35613bea81613533565b9a5060208c0135995060408c013567ffffffffffffffff811115613c0d57600080fd5b613c198e828f0161384d565b909a509850613c2c905060608d01613700565b965060808c0135955060a08c0135945060c08c0135935060e08c0135613c5181613533565b92506101008c0135613c6281613533565b809250506101208c013590509295989b509295989b9093969950565b60008060408385031215613c9157600080fd5b8235613c9c81613533565b91506020830135613cac81613533565b809150509250929050565b600080600060608486031215613ccc57600080fd5b8335613cd781613533565b92506020840135613ce781613533565b91506040840135613cf781613533565b809150509250925092565b600080600060608486031215613d1757600080fd5b8335613d2281613533565b92506020840135613d3281613533565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613da357613da3613d43565b5060010190565b604081526000613dbd6040830185613779565b8281036020840152612c358185613779565b600060208284031215613de157600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114612bd457600080fd5b600060ff821660ff841680821015613e2b57613e2b613d43565b90039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613e6c57613e6c613d43565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110613ed7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b600061016073ffffffffffffffffffffffffffffffffffffffff8f1683528d60208401528060408401528b81840152506101808b8d828501376000818d850101527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8d01168301613f51606085018d613ea0565b8a60808501528960a08501528860c0850152613f8560e085018973ffffffffffffffffffffffffffffffffffffffff169052565b73ffffffffffffffffffffffffffffffffffffffff87166101008501528184820301610120850152613fb982820187613779565b92505050613fe061014083018473ffffffffffffffffffffffffffffffffffffffff169052565b9d9c50505050505050505050505050565b6000821982111561400457614004613d43565b500190565b60008261403f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008282101561405657614056613d43565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6080808252810185905260008660a08301825b888110156140da5782356140b081613533565b73ffffffffffffffffffffffffffffffffffffffff1682526020928301929091019060010161409d565b506020840196909652505073ffffffffffffffffffffffffffffffffffffffff9283166040820152911660609091015292915050565b60006020828403121561412257600080fd5b81518015158114612bd457600080fd5b8183823760009101908152919050565b6000610160820190508c825273ffffffffffffffffffffffffffffffffffffffff808d1660208401528b60408401528a6060840152614184608084018b613ea0565b60a083019890985260c082019690965260e0810194909452918516610100840152909316610120820152610140019190915295945050505050565b6000816141ce576141ce613d43565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x34A1D3fff3958843C43aD80F30b94c510645C316", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x1688f0b900000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000164b63e800d0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x34A1D3fff3958843C43aD80F30b94c510645C316", + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x34A1D3fff3958843C43aD80F30b94c510645C316", + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x608060405234801561001057600080fd5b5060405161016f38038061016f83398101604081905261002f916100b9565b6001600160a01b0381166100945760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642073696e676c65746f6e20616464726573732070726f766964604482015261195960f21b606482015260840160405180910390fd5b600080546001600160a01b0319166001600160a01b03929092169190911790556100e9565b6000602082840312156100cb57600080fd5b81516001600160a01b03811681146100e257600080fd5b9392505050565b6078806100f76000396000f3fe6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000a00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "deployedCode": "0x6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x34A1D3fff3958843C43aD80F30b94c510645C316", + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xb63e800d0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "previousValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x34A1D3fff3958843C43aD80F30b94c510645C316", + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xb63e800d0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6105ef8061007e6000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80639b2ea4bd116100505780639b2ea4bd146100b9578063bf40fac1146100cc578063f2fde38b146100df57600080fd5b8063715018a61461006c5780638da5cb5b14610076575b600080fd5b6100746100f2565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100746100c73660046104fa565b610106565b6100906100da366004610548565b6101d9565b6100746100ed366004610585565b610215565b6100fa6102d1565b6101046000610352565b565b61010e6102d1565b6000610119836103c7565b60008181526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff8681167fffffffffffffffffffffffff00000000000000000000000000000000000000008316179092559151929350169061017c9085906105a7565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b6000600160006101e8846103c7565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1692915050565b61021d6102d1565b73ffffffffffffffffffffffffffffffffffffffff81166102c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102ce81610352565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610104576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102bc565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816040516020016103da91906105a7565b604051602081830303815290604052805190602001209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261043757600080fd5b813567ffffffffffffffff80821115610452576104526103f7565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610498576104986103f7565b816040528381528660208588010111156104b157600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b919050565b6000806040838503121561050d57600080fd5b823567ffffffffffffffff81111561052457600080fd5b61053085828601610426565b92505061053f602084016104d1565b90509250929050565b60006020828403121561055a57600080fd5b813567ffffffffffffffff81111561057157600080fd5b61057d84828501610426565b949350505050565b60006020828403121561059757600080fd5b6105a0826104d1565b9392505050565b6000825160005b818110156105c857602081860181015185830152016105ae565b818111156105d7576000828501525b50919091019291505056fea164736f6c634300080f000a", + "deployedCode": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c80639b2ea4bd116100505780639b2ea4bd146100b9578063bf40fac1146100cc578063f2fde38b146100df57600080fd5b8063715018a61461006c5780638da5cb5b14610076575b600080fd5b6100746100f2565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100746100c73660046104fa565b610106565b6100906100da366004610548565b6101d9565b6100746100ed366004610585565b610215565b6100fa6102d1565b6101046000610352565b565b61010e6102d1565b6000610119836103c7565b60008181526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff8681167fffffffffffffffffffffffff00000000000000000000000000000000000000008316179092559151929350169061017c9085906105a7565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b6000600160006101e8846103c7565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1692915050565b61021d6102d1565b73ffffffffffffffffffffffffffffffffffffffff81166102c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102ce81610352565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610104576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102bc565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816040516020016103da91906105a7565b604051602081830303815290604052805190602001209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261043757600080fd5b813567ffffffffffffffff80821115610452576104526103f7565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610498576104986103f7565b816040528381528660208588010111156104b157600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b919050565b6000806040838503121561050d57600080fd5b823567ffffffffffffffff81111561052457600080fd5b61053085828601610426565b92505061053f602084016104d1565b90509250929050565b60006020828403121561055a57600080fd5b813567ffffffffffffffff81111561057157600080fd5b61057d84828501610426565b949350505050565b60006020828403121561059757600080fd5b6105a0826104d1565b9392505050565b6000825160005b818110156105c857602081860181015185830152016105ae565b818111156105d7576000828501525b50919091019291505056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": true, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x8da5cb5b", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x60806040523480156200001157600080fd5b5060405162001a5f38038062001a5f8339810160408190526200003491620000a1565b6200003f3362000051565b6200004a8162000051565b50620000d3565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215620000b457600080fd5b81516001600160a01b0381168114620000cc57600080fd5b9392505050565b61197c80620000e36000396000f3fe60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "deployedCode": "0x60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": true, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": true, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x8da5cb5b", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x3ab76e9f", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x0652b57a000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": true, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x3ab76e9f", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x8da5cb5b", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf2fde38b0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": true, + "newValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + }, + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": true, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x60806040523480156200001157600080fd5b506200001f60008062000025565b62000361565b600054610100900460ff1615808015620000465750600054600160ff909116105b8062000076575062000063306200019460201b620005fd1760201c565b15801562000076575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b6200010d83620001a3565b81156200014857604080518082019091526012815271125b9a5d1a585b1a5e995c881c185d5cd95960721b6020820152620001489062000248565b80156200018f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b620001e9620001d460017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69620002cf565b60001b82620002cb60201b620006191760201c565b6000604080516001600160a01b03841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb910160408051601f19818403018152908290526200023d9162000345565b60405180910390a250565b6200028f6200027960017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7620002cf565b60001b6001620002cb60201b620006191760201c565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea2838181604051620002c0919062000345565b60405180910390a150565b9055565b600082821015620002f057634e487b7160e01b600052601160045260246000fd5b500390565b6000815180845260005b818110156200031d57602081850181015186830182015201620002ff565b8181111562000330576000602083870101525b50601f01601f19169290920160200192915050565b6020815260006200035a6020830184620002f5565b9392505050565b61096b80620003716000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", + "deployedCode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68" + }, + { + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x452a9320", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xfa60f9b2", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000000e" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "previousValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" + } + ], + "value": 0 + }, + { + "accessor": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9623609d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "previousValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x070dca21862da24de5bcba7acd697f207bda1c8caae3812d68f0baee0dd32f38" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x4f1ef286000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + }, + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": true, + "newValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": true, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68" + }, + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xfa60f9b2", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000000e" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x452a9320", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", + "previousValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x452a9320", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x5c975abb", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", + "previousValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x5c975abb", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b6" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": true, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x60806040523480156200001157600080fd5b506200002261dead60008062000028565b6200051c565b600054610100900460ff1615808015620000495750600054600160ff909116105b8062000079575062000066306200017e60201b6200053f1760201c565b15801562000079575060005460ff166001145b620000e25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000106576000805461ff0019166101001790555b620001106200018d565b6200011b84620001f5565b620001268362000274565b620001318262000324565b801562000178576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b602482015260008051602062000f4f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d9565b620001f362000385565b565b620001ff620003ec565b6001600160a01b038116620002665760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620000d9565b620002718162000448565b50565b620002ba620002a560017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16200049e565b60001b826200049a60201b6200055b1760201c565b600081604051602001620002d091815260200190565b60408051601f19818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051620003189190620004c4565b60405180910390a35050565b62000355620002a560017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6200049e565b6000816040516020016200036b91815260200190565b60408051601f1981840301815291905290506001620002e5565b600054610100900460ff16620003e15760405162461bcd60e51b815260206004820152602b602482015260008051602062000f4f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d9565b620001f33362000448565b6033546001600160a01b03163314620001f35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620000d9565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b9055565b600082821015620004bf57634e487b7160e01b600052601160045260246000fd5b500390565b600060208083528351808285015260005b81811015620004f357858101830151858201604001528201620004d5565b8181111562000506576000604083870101525b50601f01601f1916929092016040019392505050565b610a23806200052c6000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", + "deployedCode": "0x608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", + "previousValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", + "previousValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": true, + "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "previousValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace0" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1a" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x8da5cb5b", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": false, + "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "previousValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xdc8452cd", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace0" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xd798b1ac", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1a" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xd2354f20", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000000d" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x38c27159", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000003a" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x67cef446", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000003b" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d000000000000000000000000416c42991d05b31e9a6dc209e91ad22b79d87ae6000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000647a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "previousValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d000000000000000000000000416c42991d05b31e9a6dc209e91ad22b79d87ae6000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000647a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" + } + ], + "value": 0 + }, + { + "accessor": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9623609d000000000000000000000000416c42991d05b31e9a6dc209e91ad22b79d87ae6000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000647a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "previousValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x9d54a4eb6e745ee152f323ba7a05534bbe68629624a74c9623b7903663b002cf" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x4f1ef286000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000647a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": true, + "newValue": "0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x7a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": true, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": true, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace0" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1a" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x54fd4d50", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f", + "previousValue": "0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x54fd4d50", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xd2354f20", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000000d" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x8da5cb5b", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f", + "previousValue": "0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x8da5cb5b", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x38c27159", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000003a" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xdc8452cd", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f", + "previousValue": "0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xdc8452cd", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace0" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x67cef446", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000003b" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xd798b1ac", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f", + "previousValue": "0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xd798b1ac", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x416C42991d05b31E9A6dC209e91AD22b79D87Ae6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1a" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": true, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8B71b41D4dBEb2b6821d44692d3fACAAf77480Bb", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x8B71b41D4dBEb2b6821d44692d3fACAAf77480Bb", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + }, + { + "account": "0x8B71b41D4dBEb2b6821d44692d3fACAAf77480Bb", + "isWrite": true, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x608060405234801561001057600080fd5b50604051610a44380380610a4483398101604081905261002f9161005d565b610057817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b5061008d565b60006020828403121561006f57600080fd5b81516001600160a01b038116811461008657600080fd5b9392505050565b6109a88061009c6000396000f3fe60806040526004361061005e5760003560e01c8063893d20e811610043578063893d20e8146100b55780639b0b0fda146100f3578063aaf10f42146101135761006d565b806313af4035146100755780636c5d4ad0146100955761006d565b3661006d5761006b610128565b005b61006b610128565b34801561008157600080fd5b5061006b6100903660046107a2565b6103cb565b3480156100a157600080fd5b5061006b6100b036600461080e565b61045c565b3480156100c157600080fd5b506100ca610611565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ff57600080fd5b5061006b61010e3660046108dd565b6106a8565b34801561011f57600080fd5b506100ca610716565b60006101527fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb7947262000000000000000000000000000000000000000000000000000000001790529051919250600091829173ffffffffffffffffffffffffffffffffffffffff8516916101d4919061093a565b600060405180830381855afa9150503d806000811461020f576040519150601f19603f3d011682016040523d82523d6000602084013e610214565b606091505b5091509150818015610227575080516020145b156102d9576000818060200190518101906102429190610946565b905080156102d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c314368756753706c61736850726f78793a2073797374656d2069732063757260448201527f72656e746c79206265696e67207570677261646564000000000000000000000060648201526084015b60405180910390fd5b505b60006103037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166103a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4c314368756753706c61736850726f78793a20696d706c656d656e746174696f60448201527f6e206973206e6f7420736574207965740000000000000000000000000000000060648201526084016102ce565b3660008037600080366000845af43d6000803e806103c5573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610424575033155b1561045457610451817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b50565b610451610128565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104b5575033155b156104545760006104e47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050803f82516020840120036104f8575050565b60405160009061052e907f600d380380600d6000396000f30000000000000000000000000000000000000090859060200161095f565b604051602081830303815290604052905060008151602083016000f084516020860120909150813f146105e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4c314368756753706c61736850726f78793a20636f646520776173206e6f742060448201527f636f72726563746c79206465706c6f796564000000000000000000000000000060648201526084016102ce565b61060b817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b50505050565b600061063b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610672575033155b1561069d57507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6106a5610128565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610701575033155b1561070a579055565b610712610128565b5050565b60006107407fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610777575033155b1561069d57507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000602082840312156107b457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146107d857600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561082057600080fd5b813567ffffffffffffffff8082111561083857600080fd5b818401915084601f83011261084c57600080fd5b81358181111561085e5761085e6107df565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108a4576108a46107df565b816040528281528760208487010111156108bd57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600080604083850312156108f057600080fd5b50508035926020909101359150565b6000815160005b818110156109205760208185018101518683015201610906565b8181111561092f576000828601525b509290920192915050565b60006107d882846108ff565b60006020828403121561095857600080fd5b5051919050565b7fffffffffffffffffffffffffff00000000000000000000000000000000000000831681526000610993600d8301846108ff565b94935050505056fea164736f6c634300080f000a000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "deployedCode": "0x60806040526004361061005e5760003560e01c8063893d20e811610043578063893d20e8146100b55780639b0b0fda146100f3578063aaf10f42146101135761006d565b806313af4035146100755780636c5d4ad0146100955761006d565b3661006d5761006b610128565b005b61006b610128565b34801561008157600080fd5b5061006b6100903660046107a2565b6103cb565b3480156100a157600080fd5b5061006b6100b036600461080e565b61045c565b3480156100c157600080fd5b506100ca610611565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ff57600080fd5b5061006b61010e3660046108dd565b6106a8565b34801561011f57600080fd5b506100ca610716565b60006101527fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb7947262000000000000000000000000000000000000000000000000000000001790529051919250600091829173ffffffffffffffffffffffffffffffffffffffff8516916101d4919061093a565b600060405180830381855afa9150503d806000811461020f576040519150601f19603f3d011682016040523d82523d6000602084013e610214565b606091505b5091509150818015610227575080516020145b156102d9576000818060200190518101906102429190610946565b905080156102d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c314368756753706c61736850726f78793a2073797374656d2069732063757260448201527f72656e746c79206265696e67207570677261646564000000000000000000000060648201526084015b60405180910390fd5b505b60006103037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166103a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4c314368756753706c61736850726f78793a20696d706c656d656e746174696f60448201527f6e206973206e6f7420736574207965740000000000000000000000000000000060648201526084016102ce565b3660008037600080366000845af43d6000803e806103c5573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610424575033155b1561045457610451817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b50565b610451610128565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104b5575033155b156104545760006104e47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050803f82516020840120036104f8575050565b60405160009061052e907f600d380380600d6000396000f30000000000000000000000000000000000000090859060200161095f565b604051602081830303815290604052905060008151602083016000f084516020860120909150813f146105e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4c314368756753706c61736850726f78793a20636f646520776173206e6f742060448201527f636f72726563746c79206465706c6f796564000000000000000000000000000060648201526084016102ce565b61060b817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b50505050565b600061063b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610672575033155b1561069d57507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6106a5610128565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610701575033155b1561070a579055565b610712610128565b5050565b60006107407fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610777575033155b1561069d57507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000602082840312156107b457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146107d857600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561082057600080fd5b813567ffffffffffffffff8082111561083857600080fd5b818401915084601f83011261084c57600080fd5b81358181111561085e5761085e6107df565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108a4576108a46107df565b816040528281528760208487010111156108bd57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600080604083850312156108f057600080fd5b50508035926020909101359150565b6000815160005b818110156109205760208185018101518683015201610906565b8181111561092f576000828601525b509290920192915050565b60006107d882846108ff565b60006020828403121561095857600080fd5b5051919050565b7fffffffffffffffffffffffffff00000000000000000000000000000000000000831681526000610993600d8301846108ff565b94935050505056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": true, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x608060405234801561001057600080fd5b506040516105f03803806105f083398101604081905261002f91610088565b30600090815260016020908152604080832080546001600160a01b0319166001600160a01b03871617905590829052902061006a8282610203565b5050506102c2565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561009b57600080fd5b82516001600160a01b03811681146100b257600080fd5b602084810151919350906001600160401b03808211156100d157600080fd5b818601915086601f8301126100e557600080fd5b8151818111156100f7576100f7610072565b604051601f8201601f19908116603f0116810190838211818310171561011f5761011f610072565b81604052828152898684870101111561013757600080fd5b600093505b82841015610159578484018601518185018701529285019261013c565b8284111561016a5760008684830101525b8096505050505050509250929050565b600181811c9082168061018e57607f821691505b6020821081036101ae57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156101fe57600081815260208120601f850160051c810160208610156101db5750805b601f850160051c820191505b818110156101fa578281556001016101e7565b5050505b505050565b81516001600160401b0381111561021c5761021c610072565b6102308161022a845461017a565b846101b4565b602080601f831160018114610265576000841561024d5750858301515b600019600386901b1c1916600185901b1785556101fa565b600085815260208120601f198616915b8281101561029457888601518255948401946001909101908401610275565b50858210156102b25787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61031f806102d16000396000f3fe608060408181523060009081526001602090815282822054908290529181207fbf40fac1000000000000000000000000000000000000000000000000000000009093529173ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac19061006d9060846101e2565b602060405180830381865afa15801561008a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ae91906102c5565b905073ffffffffffffffffffffffffffffffffffffffff8116610157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f5265736f6c76656444656c656761746550726f78793a2074617267657420616460448201527f6472657373206d75737420626520696e697469616c697a656400000000000000606482015260840160405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff16600036604051610182929190610302565b600060405180830381855af49150503d80600081146101bd576040519150601f19603f3d011682016040523d82523d6000602084013e6101c2565b606091505b5090925090508115156001036101da57805160208201f35b805160208201fd5b600060208083526000845481600182811c91508083168061020457607f831692505b858310810361023a577f4e487b710000000000000000000000000000000000000000000000000000000085526022600452602485fd5b878601838152602001818015610257576001811461028b576102b6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616825284151560051b820196506102b6565b60008b81526020902060005b868110156102b057815484820152908501908901610297565b83019750505b50949998505050505050505050565b6000602082840312156102d757600080fd5b815173ffffffffffffffffffffffffffffffffffffffff811681146102fb57600080fd5b9392505050565b818382376000910190815291905056fea164736f6c634300080f000a000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c30000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", + "deployedCode": "0x608060408181523060009081526001602090815282822054908290529181207fbf40fac1000000000000000000000000000000000000000000000000000000009093529173ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac19061006d9060846101e2565b602060405180830381865afa15801561008a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ae91906102c5565b905073ffffffffffffffffffffffffffffffffffffffff8116610157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f5265736f6c76656444656c656761746550726f78793a2074617267657420616460448201527f6472657373206d75737420626520696e697469616c697a656400000000000000606482015260840160405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff16600036604051610182929190610302565b600060405180830381855af49150503d80600081146101bd576040519150601f19603f3d011682016040523d82523d6000602084013e6101c2565b606091505b5090925090508115156001036101da57805160208201f35b805160208201fd5b600060208083526000845481600182811c91508083168061020457607f831692505b858310810361023a577f4e487b710000000000000000000000000000000000000000000000000000000085526022600452602485fd5b878601838152602001818015610257576001811461028b576102b6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616825284151560051b820196506102b6565b60008b81526020902060005b868110156102b057815484820152908501908901610297565b83019750505b50949998505050505050505050565b6000602082840312156102d757600080fd5b815173ffffffffffffffffffffffffffffffffffffffff811681146102fb57600080fd5b9392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": true, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4505be7acf20898edfef2b5289635349881ad9bf4b57316a74e81e2abec2be52" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": true, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4505be7acf20898edfef2b5289635349881ad9bf4b57316a74e81e2abec2be52" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": true, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x8da5cb5b", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf2fde38b000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": true, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x8da5cb5b", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x60806040523480156200001157600080fd5b50620000206000808062000026565b6200028f565b600054610100900460ff1615808015620000475750600054600160ff909116105b806200007757506200006430620001c160201b62001b741760201c565b15801562000077575060005460ff166001145b620000e05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000104576000805461ff0019166101001790555b603680546001600160a01b03199081166001600160a01b03878116919091179092556037805490911685831617905560358054610100600160a81b03191661010085841602179055603254166200016a57603280546001600160a01b03191661dead1790555b62000174620001d0565b8015620001bb576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054610100900460ff166200023d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d7565b600154600160c01b90046001600160401b03166000036200028d5760408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b02176001555b565b6153ed806200029f6000396000f3fe6080604052600436106101625760003560e01c80638c3152e9116100c0578063c0c53b8b11610074578063e965084c11610059578063e965084c146104c7578063e9e05c4214610553578063f04987501461056657600080fd5b8063c0c53b8b14610406578063cff0ab961461042657600080fd5b80639bf62d82116100a55780639bf62d8214610370578063a14238e71461039d578063a35d99df146103cd57600080fd5b80638c3152e9146103235780639b5f694a1461034357600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102ee578063724c184c1461030e5780638b4c40b01461018757600080fd5b806354fd4d50146102735780635c975abb146102c957600080fd5b806335e80ab31161014857806335e80ab31461020c578063452a93201461023e5780634870496f1461025357600080fd5b80621c2ff61461018e57806333d7e2bd146101df57600080fd5b36610189576101873334620186a0600060405180602001604052806000815250610591565b005b600080fd5b34801561019a57600080fd5b5060365473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101eb57600080fd5b506037546101b59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021857600080fd5b506035546101b590610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024a57600080fd5b506101b561082c565b34801561025f57600080fd5b5061018761026e3660046149b4565b6108c4565b34801561027f57600080fd5b506102bc6040518060400160405280600581526020017f322e352e3000000000000000000000000000000000000000000000000000000081525081565b6040516101d69190614b06565b3480156102d557600080fd5b506102de610ef2565b60405190151581526020016101d6565b3480156102fa57600080fd5b506102de610309366004614b19565b610f85565b34801561031a57600080fd5b506101b5611040565b34801561032f57600080fd5b5061018761033e366004614b32565b61104c565b34801561034f57600080fd5b506036546101b59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037c57600080fd5b506032546101b59073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a957600080fd5b506102de6103b8366004614b19565b60336020526000908152604090205460ff1681565b3480156103d957600080fd5b506103ed6103e8366004614b8c565b61190d565b60405167ffffffffffffffff90911681526020016101d6565b34801561041257600080fd5b50610187610421366004614ba7565b611926565b34801561043257600080fd5b5060015461048e906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101d6565b3480156104d357600080fd5b506105256104e2366004614b19565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101d6565b610187610561366004614c00565b610591565b34801561057257600080fd5b5060375473ffffffffffffffffffffffffffffffffffffffff166101b5565b8260005a905083156106485773ffffffffffffffffffffffffffffffffffffffff87161561064857604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b610652835161190d565b67ffffffffffffffff168567ffffffffffffffff1610156106f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c0000000000000000000000000000000000000000000000000000000000606482015260840161063f565b6201d4c083511115610763576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c617267650000604482015260640161063f565b33328114610784575033731111000000000000000000000000000000001111015b6000348888888860405160200161079f959493929190614c7d565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161080f9190614b06565b60405180910390a450506108238282611b90565b50505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa15801561089b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108bf9190614ce2565b905090565b6108cc610ef2565b15610933576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a2070617573656400000000000000000000604482015260640161063f565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e747261637400606482015260840161063f565b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a869190614d1f565b519050610aa0610a9b36869003860186614d84565b611ebd565b8114610b2e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f660000000000000000000000000000000000000000000000606482015260840161063f565b6000610b3987611f19565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c4f5750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610c27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4b9190614d1f565b5114155b610cdb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e000000000000000000606482015260840161063f565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610da49101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d9a888a614dea565b8a60400135611f49565b610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f660000000000000000000000000000606482015260840161063f565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f61573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108bf9190614e6e565b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810183905260009161103a9173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101f9190614d1f565b602001516fffffffffffffffffffffffffffffffff16611f6d565b92915050565b60006108bf61082c565b565b611054610ef2565b156110bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a2070617573656400000000000000000000604482015260640161063f565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14611164576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e00606482015260840161063f565b600061116f82611f19565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff8082169483018590527001000000000000000000000000000000009091041691810191909152929350900361125a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e207965740000000000000000000000000000606482015260840161063f565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112eb9190614e8b565b81602001516fffffffffffffffffffffffffffffffff1610156113b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a40161063f565b6113d581602001516fffffffffffffffffffffffffffffffff16611f6d565b611487576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a40161063f565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa15801561150e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115329190614d1f565b82518151919250146115ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a40161063f565b61160b81602001516fffffffffffffffffffffffffffffffff16611f6d565b6116bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a40161063f565b60008381526033602052604090205460ff161561175c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a65640000000000000000000000606482015260840161063f565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a08801516117fe93929190612013565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061186390841515815260200190565b60405180910390a2801580156118795750326001145b15611906576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015260840161063f565b5050505050565b600061191a826010614ed3565b61103a90615208614f03565b600054610100900460ff16158080156119465750600054600160ff909116105b806119605750303b158015611960575060005460ff166001145b6119ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161063f565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611a4a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008584160217905560325416611b0357603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611b0b612071565b8015611b6e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611bc6907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643614f2f565b90506000611bd2612184565b90506000816020015160ff16826000015163ffffffff16611bf39190614f75565b90508215611d2a57600154600090611c2a908390700100000000000000000000000000000000900467ffffffffffffffff16614fdd565b90506000836040015160ff1683611c419190615051565b600154611c619084906fffffffffffffffffffffffffffffffff16615051565b611c6b9190614f75565b600154909150600090611cbc90611c959084906fffffffffffffffffffffffffffffffff1661510d565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612245565b90506001861115611ceb57611ce8611c9582876040015160ff1660018a611ce39190614f2f565b612264565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611d5d908490700100000000000000000000000000000000900467ffffffffffffffff16614f03565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611e40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d69740000606482015260840161063f565b600154600090611e6c906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615181565b90506000611e7e48633b9aca006122b9565b611e8890836151be565b905060005a611e979088614f2f565b905080821115611eb357611eb3611eae8284614f2f565b6122d0565b5050505050505050565b60008160000151826020015183604001518460600151604051602001611efc949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097611efc9790969591016151d2565b600080611f55866122fe565b9050611f6381868686612330565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa158015611fdd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120019190614e8b565b61200b9083615229565b421192915050565b6000806000612023866000612360565b905080612059576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff16612108576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161063f565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660000361104a5760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa158015612221573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108bf9190615266565b600061225a612254858561237e565b8361238e565b90505b9392505050565b6000670de0b6b3a76400006122a561227c8583614f75565b61228e90670de0b6b3a7640000614fdd565b6122a085670de0b6b3a7640000615051565b61239d565b6122af9086615051565b61225a9190614f75565b6000818310156122c9578161225d565b5090919050565b6000805a90505b825a6122e39083614f2f565b10156122f9576122f282615305565b91506122d7565b505050565b6060818051906020012060405160200161231a91815260200190565b6040516020818303038152906040529050919050565b6000612357846123418786866123ce565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156122c9578161225d565b60008183126122c9578161225d565b600061225d670de0b6b3a7640000836123b586612e4c565b6123bf9190615051565b6123c99190614f75565b613090565b6060600084511161243b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b65790000000000000000000000604482015260640161063f565b6000612446846132cf565b90506000612453866133bb565b905060008460405160200161246a91815260200190565b60405160208183030381529060405290506000805b8451811015612dc357600085828151811061249c5761249c61533d565b602002602001015190508451831115612537576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e677468000000000000000000000000000000000000606482015260840161063f565b826000036125f057805180516020918201206040516125859261255f92910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b6125eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f742068617368000000604482015260640161063f565b612747565b8051516020116126a6578051805160209182012060405161261a9261255f92910190815260200190565b6125eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c206861736800000000000000000000000000000000000000000000000000606482015260840161063f565b805184516020808701919091208251919092012014612747576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f6520686173680000000000000000000000000000000000000000000000000000606482015260840161063f565b61275360106001615229565b8160200151510361292f57845183036128c75761278d81602001516010815181106127805761278061533d565b602002602001015161341e565b96506000875111612820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e6368290000000000606482015260840161063f565b6001865161282e9190614f2f565b82146128bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e636829000000000000606482015260840161063f565b50505050505061225d565b60008584815181106128db576128db61533d565b602001015160f81c60f81b60f81c9050600082602001518260ff16815181106129065761290661533d565b602002602001015190506129198161357e565b9550612926600186615229565b94505050612db0565b600281602001515103612d28576000612947826135a3565b905060008160008151811061295e5761295e61533d565b016020015160f81c9050600061297560028361536c565b61298090600261538e565b90506000612991848360ff166135c7565b9050600061299f8a896135c7565b905060006129ad83836135fd565b905080835114612a3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b6579000000000000606482015260840161063f565b60ff851660021480612a54575060ff85166003145b15612c435780825114612ae9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e646572000000606482015260840161063f565b612b0387602001516001815181106127805761278061533d565b9c5060008d5111612b96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c6561662900000000000000606482015260840161063f565b60018c51612ba49190614f2f565b8814612c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c656166290000000000000000606482015260840161063f565b50505050505050505050505061225d565b60ff85161580612c56575060ff85166001145b15612c9557612c828760200151600181518110612c7557612c7561533d565b602002602001015161357e565b9950612c8e818a615229565b9850612d1d565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e207072656669780000000000000000000000000000606482015260840161063f565b505050505050612db0565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f6465000000000000000000000000000000000000000000000000606482015260840161063f565b5080612dbb81615305565b91505061247f565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e7473000000000000000000000000000000000000000000000000000000606482015260840161063f565b6000808213612eb7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161063f565b60006060612ec4846136b1565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136130c157506000919050565b680755bf798b4a1bf1e58212613133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f570000000000000000000000000000000000000000604482015260640161063f565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff8111156132ed576132ed6147d4565b60405190808252806020026020018201604052801561333257816020015b604080518082019091526060808252602082015281526020019060019003908161330b5790505b50915060005b818110156133b457604051806040016040528085838151811061335d5761335d61533d565b6020026020010151815260200161338c86848151811061337f5761337f61533d565b6020026020010151613787565b8152508382815181106133a1576133a161533d565b6020908102919091010152600101613338565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613413578060011b82018184015160001a8060041c8253600f8116600183015350506001016133e5565b509295945050505050565b6060600080600061342e8561379a565b919450925090506000816001811115613449576134496153b1565b146134d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d00000000000000606482015260840161063f565b6134e08284615229565b85511461356f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e646572000000000000000000000000606482015260840161063f565b61235785602001518484614207565b6060602082600001511061359a576135958261341e565b61103a565b61103a8261429b565b606061103a6135c283602001516000815181106127805761278061533d565b6133bb565b6060825182106135e6575060408051602081019091526000815261103a565b61225d83838486516135f89190614f2f565b6142b1565b6000808251845110613610578251613613565b83515b90505b808210801561369a57508282815181106136325761363261533d565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106136715761367161533d565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156136aa57816001019150613616565b5092915050565b600080821161371c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161063f565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606061103a61379583614489565b614572565b600080600080846000015111613858576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a40161063f565b6020840151805160001a607f811161387d576000600160009450945094505050614200565b60b78111613a8b576000613892608083614f2f565b90508087600001511161394d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a40161063f565b6001838101517fff000000000000000000000000000000000000000000000000000000000000001690821415806139c657507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613a78576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a40161063f565b5060019550935060009250614200915050565b60bf8111613dd9576000613aa060b783614f2f565b905080876000015111613b5b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a40161063f565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613c39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a40161063f565b600184015160088302610100031c60378111613cfd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a40161063f565b613d078184615229565b895111613dbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a40161063f565b613dc7836001615229565b97509550600094506142009350505050565b60f78111613eba576000613dee60c083614f2f565b905080876000015111613ea9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a40161063f565b600195509350849250614200915050565b6000613ec760f783614f2f565b905080876000015111613f82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a40161063f565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614060576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a40161063f565b600184015160088302610100031c60378111614124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a40161063f565b61412e8184615229565b8951116141e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a40161063f565b6141ee836001615229565b97509550600194506142009350505050565b9193909250565b60608167ffffffffffffffff811115614222576142226147d4565b6040519080825280601f01601f19166020018201604052801561424c576020820181803683370190505b509050811561225d5760006142618486615229565b90506020820160005b8481101561428257828101518282015260200161426a565b84811115614291576000858301525b5050509392505050565b606061103a826020015160008460000151614207565b60608182601f011015614320576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161063f565b82828401101561438c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161063f565b818301845110156143f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015260640161063f565b6060821580156144185760405191506000825260208201604052614480565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614451578051835260209283019201614439565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201526000825111614554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a40161063f565b50604080518082019091528151815260209182019181019190915290565b606060008060006145828561379a565b91945092509050600181600181111561459d5761459d6153b1565b1461462a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d0000000000000000606482015260840161063f565b84516146368385615229565b146146c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e6465720000000000000000000000000000606482015260840161063f565b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816146da5790505093506000835b86518110156147c85760008061474d6040518060400160405280858c600001516147319190614f2f565b8152602001858c602001516147469190615229565b905261379a565b5091509150604051806040016040528083836147699190615229565b8152602001848b6020015161477e9190615229565b8152508885815181106147935761479361533d565b60209081029190910101526147a9600185615229565b93506147b58183615229565b6147bf9084615229565b92505050614707565b50845250919392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561484a5761484a6147d4565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461487457600080fd5b50565b600082601f83011261488857600080fd5b813567ffffffffffffffff8111156148a2576148a26147d4565b6148d360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614803565b8181528460208386010111156148e857600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561491757600080fd5b60405160c0810167ffffffffffffffff828210818311171561493b5761493b6147d4565b81604052829350843583526020850135915061495682614852565b8160208401526040850135915061496c82614852565b816040840152606085013560608401526080850135608084015260a085013591508082111561499a57600080fd5b506149a785828601614877565b60a0830152505092915050565b600080600080600085870360e08112156149cd57600080fd5b863567ffffffffffffffff808211156149e557600080fd5b6149f18a838b01614905565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614a2a57600080fd5b60408901955060c0890135925080831115614a4457600080fd5b828901925089601f840112614a5857600080fd5b8235915080821115614a6957600080fd5b508860208260051b8401011115614a7f57600080fd5b959894975092955050506020019190565b60005b83811015614aab578181015183820152602001614a93565b83811115611b6e5750506000910152565b60008151808452614ad4816020860160208601614a90565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225d6020830184614abc565b600060208284031215614b2b57600080fd5b5035919050565b600060208284031215614b4457600080fd5b813567ffffffffffffffff811115614b5b57600080fd5b614b6784828501614905565b949350505050565b803567ffffffffffffffff81168114614b8757600080fd5b919050565b600060208284031215614b9e57600080fd5b61225d82614b6f565b600080600060608486031215614bbc57600080fd5b8335614bc781614852565b92506020840135614bd781614852565b91506040840135614be781614852565b809150509250925092565b801515811461487457600080fd5b600080600080600060a08688031215614c1857600080fd5b8535614c2381614852565b945060208601359350614c3860408701614b6f565b92506060860135614c4881614bf2565b9150608086013567ffffffffffffffff811115614c6457600080fd5b614c7088828901614877565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614cd1816049850160208701614a90565b919091016049019695505050505050565b600060208284031215614cf457600080fd5b815161225d81614852565b80516fffffffffffffffffffffffffffffffff81168114614b8757600080fd5b600060608284031215614d3157600080fd5b6040516060810181811067ffffffffffffffff82111715614d5457614d546147d4565b60405282518152614d6760208401614cff565b6020820152614d7860408401614cff565b60408201529392505050565b600060808284031215614d9657600080fd5b6040516080810181811067ffffffffffffffff82111715614db957614db96147d4565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614e0557614e056147d4565b8360051b6020614e16818301614803565b868152918501918181019036841115614e2e57600080fd5b865b84811015614e6257803586811115614e485760008081fd5b614e5436828b01614877565b845250918301918301614e30565b50979650505050505050565b600060208284031215614e8057600080fd5b815161225d81614bf2565b600060208284031215614e9d57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615614efa57614efa614ea4565b02949350505050565b600067ffffffffffffffff808316818516808303821115614f2657614f26614ea4565b01949350505050565b600082821015614f4157614f41614ea4565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614f8457614f84614f46565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615614fd857614fd8614ea4565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561501757615017614ea4565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561504b5761504b614ea4565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561509257615092614ea4565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156150cd576150cd614ea4565b600087129250878205871284841616156150e9576150e9614ea4565b878505871281841616156150ff576150ff614ea4565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561514757615147614ea4565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561517b5761517b614ea4565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156151b9576151b9614ea4565b500290565b6000826151cd576151cd614f46565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261521d60c0830184614abc565b98975050505050505050565b6000821982111561523c5761523c614ea4565b500190565b805163ffffffff81168114614b8757600080fd5b805160ff81168114614b8757600080fd5b600060c0828403121561527857600080fd5b60405160c0810181811067ffffffffffffffff8211171561529b5761529b6147d4565b6040526152a783615241565b81526152b560208401615255565b60208201526152c660408401615255565b60408201526152d760608401615241565b60608201526152e860808401615241565b60808201526152f960a08401614cff565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361533657615336614ea4565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff83168061537f5761537f614f46565b8060ff84160691505092915050565b600060ff821660ff8416808210156153a8576153a8614ea4565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", + "deployedCode": "0x6080604052600436106101625760003560e01c80638c3152e9116100c0578063c0c53b8b11610074578063e965084c11610059578063e965084c146104c7578063e9e05c4214610553578063f04987501461056657600080fd5b8063c0c53b8b14610406578063cff0ab961461042657600080fd5b80639bf62d82116100a55780639bf62d8214610370578063a14238e71461039d578063a35d99df146103cd57600080fd5b80638c3152e9146103235780639b5f694a1461034357600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102ee578063724c184c1461030e5780638b4c40b01461018757600080fd5b806354fd4d50146102735780635c975abb146102c957600080fd5b806335e80ab31161014857806335e80ab31461020c578063452a93201461023e5780634870496f1461025357600080fd5b80621c2ff61461018e57806333d7e2bd146101df57600080fd5b36610189576101873334620186a0600060405180602001604052806000815250610591565b005b600080fd5b34801561019a57600080fd5b5060365473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101eb57600080fd5b506037546101b59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561021857600080fd5b506035546101b590610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024a57600080fd5b506101b561082c565b34801561025f57600080fd5b5061018761026e3660046149b4565b6108c4565b34801561027f57600080fd5b506102bc6040518060400160405280600581526020017f322e352e3000000000000000000000000000000000000000000000000000000081525081565b6040516101d69190614b06565b3480156102d557600080fd5b506102de610ef2565b60405190151581526020016101d6565b3480156102fa57600080fd5b506102de610309366004614b19565b610f85565b34801561031a57600080fd5b506101b5611040565b34801561032f57600080fd5b5061018761033e366004614b32565b61104c565b34801561034f57600080fd5b506036546101b59073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037c57600080fd5b506032546101b59073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a957600080fd5b506102de6103b8366004614b19565b60336020526000908152604090205460ff1681565b3480156103d957600080fd5b506103ed6103e8366004614b8c565b61190d565b60405167ffffffffffffffff90911681526020016101d6565b34801561041257600080fd5b50610187610421366004614ba7565b611926565b34801561043257600080fd5b5060015461048e906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101d6565b3480156104d357600080fd5b506105256104e2366004614b19565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101d6565b610187610561366004614c00565b610591565b34801561057257600080fd5b5060375473ffffffffffffffffffffffffffffffffffffffff166101b5565b8260005a905083156106485773ffffffffffffffffffffffffffffffffffffffff87161561064857604080517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260248101919091527f4f7074696d69736d506f7274616c3a206d7573742073656e6420746f2061646460448201527f72657373283029207768656e206372656174696e67206120636f6e747261637460648201526084015b60405180910390fd5b610652835161190d565b67ffffffffffffffff168567ffffffffffffffff1610156106f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4f7074696d69736d506f7274616c3a20676173206c696d697420746f6f20736d60448201527f616c6c0000000000000000000000000000000000000000000000000000000000606482015260840161063f565b6201d4c083511115610763576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f4f7074696d69736d506f7274616c3a206461746120746f6f206c617267650000604482015260640161063f565b33328114610784575033731111000000000000000000000000000000001111015b6000348888888860405160200161079f959493929190614c7d565b604051602081830303815290604052905060008973ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161080f9190614b06565b60405180910390a450506108238282611b90565b50505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa15801561089b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108bf9190614ce2565b905090565b6108cc610ef2565b15610933576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a2070617573656400000000000000000000604482015260640161063f565b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a20796f752063616e6e6f742073656e642060448201527f6d6573736167657320746f2074686520706f7274616c20636f6e747261637400606482015260840161063f565b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a869190614d1f565b519050610aa0610a9b36869003860186614d84565b611ebd565b8114610b2e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f660000000000000000000000000000000000000000000000606482015260840161063f565b6000610b3987611f19565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c4f5750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610c27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4b9190614d1f565b5114155b610cdb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e000000000000000000606482015260840161063f565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610da49101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d9a888a614dea565b8a60400135611f49565b610e30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f660000000000000000000000000000606482015260840161063f565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f61573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108bf9190614e6e565b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810183905260009161103a9173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101f9190614d1f565b602001516fffffffffffffffffffffffffffffffff16611f6d565b92915050565b60006108bf61082c565b565b611054610ef2565b156110bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f7074696d69736d506f7274616c3a2070617573656400000000000000000000604482015260640161063f565b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14611164576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d506f7274616c3a2063616e206f6e6c79207472696767657260448201527f206f6e65207769746864726177616c20706572207472616e73616374696f6e00606482015260840161063f565b600061116f82611f19565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff8082169483018590527001000000000000000000000000000000009091041691810191909152929350900361125a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e207965740000000000000000000000000000606482015260840161063f565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112eb9190614e8b565b81602001516fffffffffffffffffffffffffffffffff1610156113b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a40161063f565b6113d581602001516fffffffffffffffffffffffffffffffff16611f6d565b611487576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a40161063f565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa15801561150e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115329190614d1f565b82518151919250146115ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a40161063f565b61160b81602001516fffffffffffffffffffffffffffffffff16611f6d565b6116bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a40161063f565b60008381526033602052604090205460ff161561175c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a65640000000000000000000000606482015260840161063f565b600083815260336020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055908601516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff00000000000000000000000000000000000000009092169190911790558501516080860151606087015160a08801516117fe93929190612013565b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405190915084907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b9061186390841515815260200190565b60405180910390a2801580156118795750326001145b15611906576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4f7074696d69736d506f7274616c3a207769746864726177616c206661696c6560448201527f6400000000000000000000000000000000000000000000000000000000000000606482015260840161063f565b5050505050565b600061191a826010614ed3565b61103a90615208614f03565b600054610100900460ff16158080156119465750600054600160ff909116105b806119605750303b158015611960575060005460ff166001145b6119ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161063f565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611a4a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008584160217905560325416611b0357603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611b0b612071565b8015611b6e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600154600090611bc6907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643614f2f565b90506000611bd2612184565b90506000816020015160ff16826000015163ffffffff16611bf39190614f75565b90508215611d2a57600154600090611c2a908390700100000000000000000000000000000000900467ffffffffffffffff16614fdd565b90506000836040015160ff1683611c419190615051565b600154611c619084906fffffffffffffffffffffffffffffffff16615051565b611c6b9190614f75565b600154909150600090611cbc90611c959084906fffffffffffffffffffffffffffffffff1661510d565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612245565b90506001861115611ceb57611ce8611c9582876040015160ff1660018a611ce39190614f2f565b612264565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090611d5d908490700100000000000000000000000000000000900467ffffffffffffffff16614f03565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff161315611e40576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5265736f757263654d65746572696e673a2063616e6e6f7420627579206d6f7260448201527f6520676173207468616e20617661696c61626c6520676173206c696d69740000606482015260840161063f565b600154600090611e6c906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615181565b90506000611e7e48633b9aca006122b9565b611e8890836151be565b905060005a611e979088614f2f565b905080821115611eb357611eb3611eae8284614f2f565b6122d0565b5050505050505050565b60008160000151826020015183604001518460600151604051602001611efc949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097611efc9790969591016151d2565b600080611f55866122fe565b9050611f6381868686612330565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa158015611fdd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120019190614e8b565b61200b9083615229565b421192915050565b6000806000612023866000612360565b905080612059576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b600054610100900460ff16612108576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161063f565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660000361104a5760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa158015612221573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108bf9190615266565b600061225a612254858561237e565b8361238e565b90505b9392505050565b6000670de0b6b3a76400006122a561227c8583614f75565b61228e90670de0b6b3a7640000614fdd565b6122a085670de0b6b3a7640000615051565b61239d565b6122af9086615051565b61225a9190614f75565b6000818310156122c9578161225d565b5090919050565b6000805a90505b825a6122e39083614f2f565b10156122f9576122f282615305565b91506122d7565b505050565b6060818051906020012060405160200161231a91815260200190565b6040516020818303038152906040529050919050565b6000612357846123418786866123ce565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156122c9578161225d565b60008183126122c9578161225d565b600061225d670de0b6b3a7640000836123b586612e4c565b6123bf9190615051565b6123c99190614f75565b613090565b6060600084511161243b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b65790000000000000000000000604482015260640161063f565b6000612446846132cf565b90506000612453866133bb565b905060008460405160200161246a91815260200190565b60405160208183030381529060405290506000805b8451811015612dc357600085828151811061249c5761249c61533d565b602002602001015190508451831115612537576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e677468000000000000000000000000000000000000606482015260840161063f565b826000036125f057805180516020918201206040516125859261255f92910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b6125eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f742068617368000000604482015260640161063f565b612747565b8051516020116126a6578051805160209182012060405161261a9261255f92910190815260200190565b6125eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c206861736800000000000000000000000000000000000000000000000000606482015260840161063f565b805184516020808701919091208251919092012014612747576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f6520686173680000000000000000000000000000000000000000000000000000606482015260840161063f565b61275360106001615229565b8160200151510361292f57845183036128c75761278d81602001516010815181106127805761278061533d565b602002602001015161341e565b96506000875111612820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e6368290000000000606482015260840161063f565b6001865161282e9190614f2f565b82146128bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e636829000000000000606482015260840161063f565b50505050505061225d565b60008584815181106128db576128db61533d565b602001015160f81c60f81b60f81c9050600082602001518260ff16815181106129065761290661533d565b602002602001015190506129198161357e565b9550612926600186615229565b94505050612db0565b600281602001515103612d28576000612947826135a3565b905060008160008151811061295e5761295e61533d565b016020015160f81c9050600061297560028361536c565b61298090600261538e565b90506000612991848360ff166135c7565b9050600061299f8a896135c7565b905060006129ad83836135fd565b905080835114612a3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b6579000000000000606482015260840161063f565b60ff851660021480612a54575060ff85166003145b15612c435780825114612ae9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e646572000000606482015260840161063f565b612b0387602001516001815181106127805761278061533d565b9c5060008d5111612b96576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c6561662900000000000000606482015260840161063f565b60018c51612ba49190614f2f565b8814612c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c656166290000000000000000606482015260840161063f565b50505050505050505050505061225d565b60ff85161580612c56575060ff85166001145b15612c9557612c828760200151600181518110612c7557612c7561533d565b602002602001015161357e565b9950612c8e818a615229565b9850612d1d565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e207072656669780000000000000000000000000000606482015260840161063f565b505050505050612db0565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f6465000000000000000000000000000000000000000000000000606482015260840161063f565b5080612dbb81615305565b91505061247f565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e7473000000000000000000000000000000000000000000000000000000606482015260840161063f565b6000808213612eb7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161063f565b60006060612ec4846136b1565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136130c157506000919050565b680755bf798b4a1bf1e58212613133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f570000000000000000000000000000000000000000604482015260640161063f565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b80516060908067ffffffffffffffff8111156132ed576132ed6147d4565b60405190808252806020026020018201604052801561333257816020015b604080518082019091526060808252602082015281526020019060019003908161330b5790505b50915060005b818110156133b457604051806040016040528085838151811061335d5761335d61533d565b6020026020010151815260200161338c86848151811061337f5761337f61533d565b6020026020010151613787565b8152508382815181106133a1576133a161533d565b6020908102919091010152600101613338565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613413578060011b82018184015160001a8060041c8253600f8116600183015350506001016133e5565b509295945050505050565b6060600080600061342e8561379a565b919450925090506000816001811115613449576134496153b1565b146134d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206279746573206973206e6f7420612064617461206974656d00000000000000606482015260840161063f565b6134e08284615229565b85511461356f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f524c505265616465723a2062797465732076616c756520636f6e7461696e732060448201527f616e20696e76616c69642072656d61696e646572000000000000000000000000606482015260840161063f565b61235785602001518484614207565b6060602082600001511061359a576135958261341e565b61103a565b61103a8261429b565b606061103a6135c283602001516000815181106127805761278061533d565b6133bb565b6060825182106135e6575060408051602081019091526000815261103a565b61225d83838486516135f89190614f2f565b6142b1565b6000808251845110613610578251613613565b83515b90505b808210801561369a57508282815181106136325761363261533d565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106136715761367161533d565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156136aa57816001019150613616565b5092915050565b600080821161371c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e45440000000000000000000000000000000000000000000000604482015260640161063f565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606061103a61379583614489565b614572565b600080600080846000015111613858576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a40161063f565b6020840151805160001a607f811161387d576000600160009450945094505050614200565b60b78111613a8b576000613892608083614f2f565b90508087600001511161394d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20737472696e67206c656e6774682060648201527f2873686f727420737472696e6729000000000000000000000000000000000000608482015260a40161063f565b6001838101517fff000000000000000000000000000000000000000000000000000000000000001690821415806139c657507f80000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610155b613a78576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a20696e76616c6964207072656669782c2073696e676c60448201527f652062797465203c203078383020617265206e6f74207072656669786564202860648201527f73686f727420737472696e672900000000000000000000000000000000000000608482015260a40161063f565b5060019550935060009250614200915050565b60bf8111613dd9576000613aa060b783614f2f565b905080876000015111613b5b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605160248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f6620737472696e67206c656e60648201527f67746820286c6f6e6720737472696e6729000000000000000000000000000000608482015260a40161063f565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003613c39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e6720737472696e672900000000000000000000000000000000000000000000608482015260a40161063f565b600184015160088302610100031c60378111613cfd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f20737472696e6729000000000000000000000000000000000000000000000000608482015260a40161063f565b613d078184615229565b895111613dbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e6720737472696e67290000000000000000000000000000000000000000608482015260a40161063f565b613dc7836001615229565b97509550600094506142009350505050565b60f78111613eba576000613dee60c083614f2f565b905080876000015111613ea9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e206c697374206c656e67746820287360648201527f686f7274206c6973742900000000000000000000000000000000000000000000608482015260a40161063f565b600195509350849250614200915050565b6000613ec760f783614f2f565b905080876000015111613f82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206265203e207468616e206c656e677468206f66206c697374206c656e677460648201527f6820286c6f6e67206c6973742900000000000000000000000000000000000000608482015260a40161063f565b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614060576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f74206e6f74206861766520616e79206c656164696e67207a65726f7320286c6f60648201527f6e67206c69737429000000000000000000000000000000000000000000000000608482015260a40161063f565b600184015160088302610100031c60378111614124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20353520627974657320286c6f6e6760648201527f206c697374290000000000000000000000000000000000000000000000000000608482015260a40161063f565b61412e8184615229565b8951116141e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620636f6e74656e74206d757360448201527f742062652067726561746572207468616e20746f74616c206c656e677468202860648201527f6c6f6e67206c6973742900000000000000000000000000000000000000000000608482015260a40161063f565b6141ee836001615229565b97509550600194506142009350505050565b9193909250565b60608167ffffffffffffffff811115614222576142226147d4565b6040519080825280601f01601f19166020018201604052801561424c576020820181803683370190505b509050811561225d5760006142618486615229565b90506020820160005b8481101561428257828101518282015260200161426a565b84811115614291576000858301525b5050509392505050565b606061103a826020015160008460000151614207565b60608182601f011015614320576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161063f565b82828401101561438c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f77000000000000000000000000000000000000604482015260640161063f565b818301845110156143f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e6473000000000000000000000000000000604482015260640161063f565b6060821580156144185760405191506000825260208201604052614480565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614451578051835260209283019201614439565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201526000825111614554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f524c505265616465723a206c656e677468206f6620616e20524c50206974656d60448201527f206d7573742062652067726561746572207468616e207a65726f20746f20626560648201527f206465636f6461626c6500000000000000000000000000000000000000000000608482015260a40161063f565b50604080518082019091528151815260209182019181019190915290565b606060008060006145828561379a565b91945092509050600181600181111561459d5761459d6153b1565b1461462a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f524c505265616465723a206465636f646564206974656d207479706520666f7260448201527f206c697374206973206e6f742061206c697374206974656d0000000000000000606482015260840161063f565b84516146368385615229565b146146c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f524c505265616465723a206c697374206974656d2068617320616e20696e766160448201527f6c696420646174612072656d61696e6465720000000000000000000000000000606482015260840161063f565b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816146da5790505093506000835b86518110156147c85760008061474d6040518060400160405280858c600001516147319190614f2f565b8152602001858c602001516147469190615229565b905261379a565b5091509150604051806040016040528083836147699190615229565b8152602001848b6020015161477e9190615229565b8152508885815181106147935761479361533d565b60209081029190910101526147a9600185615229565b93506147b58183615229565b6147bf9084615229565b92505050614707565b50845250919392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561484a5761484a6147d4565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461487457600080fd5b50565b600082601f83011261488857600080fd5b813567ffffffffffffffff8111156148a2576148a26147d4565b6148d360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614803565b8181528460208386010111156148e857600080fd5b816020850160208301376000918101602001919091529392505050565b600060c0828403121561491757600080fd5b60405160c0810167ffffffffffffffff828210818311171561493b5761493b6147d4565b81604052829350843583526020850135915061495682614852565b8160208401526040850135915061496c82614852565b816040840152606085013560608401526080850135608084015260a085013591508082111561499a57600080fd5b506149a785828601614877565b60a0830152505092915050565b600080600080600085870360e08112156149cd57600080fd5b863567ffffffffffffffff808211156149e557600080fd5b6149f18a838b01614905565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614a2a57600080fd5b60408901955060c0890135925080831115614a4457600080fd5b828901925089601f840112614a5857600080fd5b8235915080821115614a6957600080fd5b508860208260051b8401011115614a7f57600080fd5b959894975092955050506020019190565b60005b83811015614aab578181015183820152602001614a93565b83811115611b6e5750506000910152565b60008151808452614ad4816020860160208601614a90565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225d6020830184614abc565b600060208284031215614b2b57600080fd5b5035919050565b600060208284031215614b4457600080fd5b813567ffffffffffffffff811115614b5b57600080fd5b614b6784828501614905565b949350505050565b803567ffffffffffffffff81168114614b8757600080fd5b919050565b600060208284031215614b9e57600080fd5b61225d82614b6f565b600080600060608486031215614bbc57600080fd5b8335614bc781614852565b92506020840135614bd781614852565b91506040840135614be781614852565b809150509250925092565b801515811461487457600080fd5b600080600080600060a08688031215614c1857600080fd5b8535614c2381614852565b945060208601359350614c3860408701614b6f565b92506060860135614c4881614bf2565b9150608086013567ffffffffffffffff811115614c6457600080fd5b614c7088828901614877565b9150509295509295909350565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251614cd1816049850160208701614a90565b919091016049019695505050505050565b600060208284031215614cf457600080fd5b815161225d81614852565b80516fffffffffffffffffffffffffffffffff81168114614b8757600080fd5b600060608284031215614d3157600080fd5b6040516060810181811067ffffffffffffffff82111715614d5457614d546147d4565b60405282518152614d6760208401614cff565b6020820152614d7860408401614cff565b60408201529392505050565b600060808284031215614d9657600080fd5b6040516080810181811067ffffffffffffffff82111715614db957614db96147d4565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff80841115614e0557614e056147d4565b8360051b6020614e16818301614803565b868152918501918181019036841115614e2e57600080fd5b865b84811015614e6257803586811115614e485760008081fd5b614e5436828b01614877565b845250918301918301614e30565b50979650505050505050565b600060208284031215614e8057600080fd5b815161225d81614bf2565b600060208284031215614e9d57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615614efa57614efa614ea4565b02949350505050565b600067ffffffffffffffff808316818516808303821115614f2657614f26614ea4565b01949350505050565b600082821015614f4157614f41614ea4565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614f8457614f84614f46565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615614fd857614fd8614ea4565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561501757615017614ea4565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561504b5761504b614ea4565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561509257615092614ea4565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156150cd576150cd614ea4565b600087129250878205871284841616156150e9576150e9614ea4565b878505871281841616156150ff576150ff614ea4565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561514757615147614ea4565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561517b5761517b614ea4565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156151b9576151b9614ea4565b500290565b6000826151cd576151cd614f46565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261521d60c0830184614abc565b98975050505050505050565b6000821982111561523c5761523c614ea4565b500190565b805163ffffffff81168114614b8757600080fd5b805160ff81168114614b8757600080fd5b600060c0828403121561527857600080fd5b60405160c0810181811067ffffffffffffffff8211171561529b5761529b6147d4565b6040526152a783615241565b81526152b560208401615255565b60208201526152c660408401615255565b60408201526152d760608401615241565b60608201526152e860808401615241565b60808201526152f960a08401614cff565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361533657615336614ea4565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff83168061537f5761537f614f46565b8060ff84160691505092915050565b600060ff821660ff8416808210156153a8576153a8614ea4565b90039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": true, + "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": true, + "newValue": "0x000000000000000100000000000000000000000000000000000000003b9aca00", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xfa60f9b2", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000000e" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": false, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x001c2ff6", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9b5f694a", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf0498750", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x33d7e2bd", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x35e80ab3", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9bf62d82", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "isWrite": false, + "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "previousValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x60806040523480156200001157600080fd5b506200001f60008062000025565b6200027f565b600054600160a81b900460ff16158080156200004e57506000546001600160a01b90910460ff16105b806200008557506200006b30620001b960201b620014d61760201c565b158015620000855750600054600160a01b900460ff166001145b620000ee5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b17905580156200011c576000805460ff60a81b1916600160a81b1790555b60fb80546001600160a01b038086166001600160a01b03199283161790925560fc8054928516929091169190911790556200016b734200000000000000000000000000000000000007620001c8565b8015620001b4576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b600054600160a81b900460ff16620002375760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000e5565b60cc546001600160a01b03166200025d5760cc80546001600160a01b03191661dead1790555b60cf80546001600160a01b0319166001600160a01b0392909216919091179055565b611f94806200028f6000396000f3fe6080604052600436106101805760003560e01c80635c975abb116100d6578063a4e7f8bd1161007f578063d764ad0b11610059578063d764ad0b14610463578063db505d8014610476578063ecc70428146104a357600080fd5b8063a4e7f8bd146103e3578063b1b1b20914610413578063b28ade251461044357600080fd5b806383a74074116100b057806383a74074146103a15780638cbeeef2146102b85780639fce812c146103b857600080fd5b80635c975abb1461033a5780636425666b1461035f5780636e296e451461038c57600080fd5b80633dbb202b116101385780634c1d6a69116101125780634c1d6a69146102b857806354fd4d50146102ce5780635644cfdf1461032457600080fd5b80633dbb202b1461025b5780633f827a5a14610270578063485cc9551461029857600080fd5b80630ff754ea116101695780630ff754ea146101cd5780632828d7e81461021957806335e80ab31461022e57600080fd5b8063028f85f7146101855780630c568498146101b8575b600080fd5b34801561019157600080fd5b5061019a601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101c457600080fd5b5061019a603f81565b3480156101d957600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101af565b34801561022557600080fd5b5061019a604081565b34801561023a57600080fd5b5060fb546101f49073ffffffffffffffffffffffffffffffffffffffff1681565b61026e610269366004611a22565b610508565b005b34801561027c57600080fd5b50610285600181565b60405161ffff90911681526020016101af565b3480156102a457600080fd5b5061026e6102b3366004611a89565b610765565b3480156102c457600080fd5b5061019a619c4081565b3480156102da57600080fd5b506103176040518060400160405280600581526020017f322e332e3000000000000000000000000000000000000000000000000000000081525081565b6040516101af9190611b2d565b34801561033057600080fd5b5061019a61138881565b34801561034657600080fd5b5061034f6109d3565b60405190151581526020016101af565b34801561036b57600080fd5b5060fc546101f49073ffffffffffffffffffffffffffffffffffffffff1681565b34801561039857600080fd5b506101f4610a6c565b3480156103ad57600080fd5b5061019a62030d4081565b3480156103c457600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101f4565b3480156103ef57600080fd5b5061034f6103fe366004611b47565b60ce6020526000908152604090205460ff1681565b34801561041f57600080fd5b5061034f61042e366004611b47565b60cb6020526000908152604090205460ff1681565b34801561044f57600080fd5b5061019a61045e366004611b60565b610b53565b61026e610471366004611bb4565b610bc1565b34801561048257600080fd5b5060cf546101f49073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104af57600080fd5b506104fa60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101af565b60cf5461063a9073ffffffffffffffffffffffffffffffffffffffff16610530858585610b53565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061059c60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105b89796959493929190611c83565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526114f2565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856106bf60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516106d1959493929190611ce2565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b6000547501000000000000000000000000000000000000000000900460ff16158080156107b0575060005460017401000000000000000000000000000000000000000090910460ff16105b806107e25750303b1580156107e2575060005474010000000000000000000000000000000000000000900460ff166001145b610873576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905580156108f957600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc80549285169290911691909117905561096b73420000000000000000000000000000000000000761158b565b80156109ce57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610a43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a679190611d30565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff215301610b36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f74207365740000000000000000000000606482015260840161086a565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f610b6f604063ffffffff8816611d81565b610b799190611db1565b610b84601088611d81565b610b919062030d40611dff565b610b9b9190611dff565b610ba59190611dff565b610baf9190611dff565b610bb99190611dff565b949350505050565b610bc96109d3565b15610c30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a2070617573656400000000604482015260640161086a565b60f087901c60028110610ceb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a40161086a565b8061ffff16600003610de0576000610d3c878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506116c7915050565b600081815260cb602052604090205490915060ff1615610dde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c61796564000000000000000000606482015260840161086a565b505b6000610e26898989898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506116e692505050565b9050610e30611709565b15610e6857853414610e4457610e44611e2b565b600081815260ce602052604090205460ff1615610e6357610e63611e2b565b610fba565b3415610f1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a40161086a565b600081815260ce602052604090205460ff16610fba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c6179656400000000000000000000000000000000606482015260840161086a565b610fc3876117e5565b15611076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a40161086a565b600081815260cb602052604090205460ff1615611115576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c6179656400000000000000000000606482015260840161086a565b61113685611127611388619c40611dff565b67ffffffffffffffff1661182b565b158061115c575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561127557600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161126e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d65737361676500000000000000000000000000000000000000606482015260840161086a565b50506114cd565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a16179055600061130688619c405a6112c99190611e5a565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061184992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080156113bc57600082815260cb602052604090205460ff161561135957611359611e2b565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26114c9565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016114c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d65737361676500000000000000000000000000000000000000606482015260840161086a565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c42908490611553908890839089906000908990600401611e71565b6000604051808303818588803b15801561156c57600080fd5b505af1158015611580573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611636576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161086a565b60cc5473ffffffffffffffffffffffffffffffffffffffff166116805760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006116d585858585611863565b805190602001209050949350505050565b60006116f68787878787876118fc565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff1633148015610a67575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156117a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c99190611ec9565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611825575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b60608484848460405160240161187c9493929190611ee6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b606086868686868660405160240161191996959493929190611f30565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146119bd57600080fd5b50565b60008083601f8401126119d257600080fd5b50813567ffffffffffffffff8111156119ea57600080fd5b602083019150836020828501011115611a0257600080fd5b9250929050565b803563ffffffff81168114611a1d57600080fd5b919050565b60008060008060608587031215611a3857600080fd5b8435611a438161199b565b9350602085013567ffffffffffffffff811115611a5f57600080fd5b611a6b878288016119c0565b9094509250611a7e905060408601611a09565b905092959194509250565b60008060408385031215611a9c57600080fd5b8235611aa78161199b565b91506020830135611ab78161199b565b809150509250929050565b6000815180845260005b81811015611ae857602081850181015186830182015201611acc565b81811115611afa576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611b406020830184611ac2565b9392505050565b600060208284031215611b5957600080fd5b5035919050565b600080600060408486031215611b7557600080fd5b833567ffffffffffffffff811115611b8c57600080fd5b611b98868287016119c0565b9094509250611bab905060208501611a09565b90509250925092565b600080600080600080600060c0888a031215611bcf57600080fd5b873596506020880135611be18161199b565b95506040880135611bf18161199b565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611c1b57600080fd5b611c278a828b016119c0565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611cd560c083018486611c3a565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611d12608083018688611c3a565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611d4257600080fd5b81518015158114611b4057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611da857611da8611d52565b02949350505050565b600067ffffffffffffffff80841680611df3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611e2257611e22611d52565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611e6c57611e6c611d52565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611ebe60a0830184611ac2565b979650505050505050565b600060208284031215611edb57600080fd5b8151611b408161199b565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611f1f6080830185611ac2565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611f7b60c0830184611ac2565b9897505050505050505056fea164736f6c634300080f000a", + "deployedCode": "0x6080604052600436106101805760003560e01c80635c975abb116100d6578063a4e7f8bd1161007f578063d764ad0b11610059578063d764ad0b14610463578063db505d8014610476578063ecc70428146104a357600080fd5b8063a4e7f8bd146103e3578063b1b1b20914610413578063b28ade251461044357600080fd5b806383a74074116100b057806383a74074146103a15780638cbeeef2146102b85780639fce812c146103b857600080fd5b80635c975abb1461033a5780636425666b1461035f5780636e296e451461038c57600080fd5b80633dbb202b116101385780634c1d6a69116101125780634c1d6a69146102b857806354fd4d50146102ce5780635644cfdf1461032457600080fd5b80633dbb202b1461025b5780633f827a5a14610270578063485cc9551461029857600080fd5b80630ff754ea116101695780630ff754ea146101cd5780632828d7e81461021957806335e80ab31461022e57600080fd5b8063028f85f7146101855780630c568498146101b8575b600080fd5b34801561019157600080fd5b5061019a601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101c457600080fd5b5061019a603f81565b3480156101d957600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101af565b34801561022557600080fd5b5061019a604081565b34801561023a57600080fd5b5060fb546101f49073ffffffffffffffffffffffffffffffffffffffff1681565b61026e610269366004611a22565b610508565b005b34801561027c57600080fd5b50610285600181565b60405161ffff90911681526020016101af565b3480156102a457600080fd5b5061026e6102b3366004611a89565b610765565b3480156102c457600080fd5b5061019a619c4081565b3480156102da57600080fd5b506103176040518060400160405280600581526020017f322e332e3000000000000000000000000000000000000000000000000000000081525081565b6040516101af9190611b2d565b34801561033057600080fd5b5061019a61138881565b34801561034657600080fd5b5061034f6109d3565b60405190151581526020016101af565b34801561036b57600080fd5b5060fc546101f49073ffffffffffffffffffffffffffffffffffffffff1681565b34801561039857600080fd5b506101f4610a6c565b3480156103ad57600080fd5b5061019a62030d4081565b3480156103c457600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101f4565b3480156103ef57600080fd5b5061034f6103fe366004611b47565b60ce6020526000908152604090205460ff1681565b34801561041f57600080fd5b5061034f61042e366004611b47565b60cb6020526000908152604090205460ff1681565b34801561044f57600080fd5b5061019a61045e366004611b60565b610b53565b61026e610471366004611bb4565b610bc1565b34801561048257600080fd5b5060cf546101f49073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104af57600080fd5b506104fa60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101af565b60cf5461063a9073ffffffffffffffffffffffffffffffffffffffff16610530858585610b53565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061059c60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016105b89796959493929190611c83565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526114f2565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3385856106bf60cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516106d1959493929190611ce2565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b6000547501000000000000000000000000000000000000000000900460ff16158080156107b0575060005460017401000000000000000000000000000000000000000090910460ff16105b806107e25750303b1580156107e2575060005474010000000000000000000000000000000000000000900460ff166001145b610873576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905580156108f957600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc80549285169290911691909117905561096b73420000000000000000000000000000000000000761158b565b80156109ce57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610a43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a679190611d30565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff215301610b36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f74207365740000000000000000000000606482015260840161086a565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f610b6f604063ffffffff8816611d81565b610b799190611db1565b610b84601088611d81565b610b919062030d40611dff565b610b9b9190611dff565b610ba59190611dff565b610baf9190611dff565b610bb99190611dff565b949350505050565b610bc96109d3565b15610c30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a2070617573656400000000604482015260640161086a565b60f087901c60028110610ceb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a40161086a565b8061ffff16600003610de0576000610d3c878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506116c7915050565b600081815260cb602052604090205490915060ff1615610dde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c61796564000000000000000000606482015260840161086a565b505b6000610e26898989898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506116e692505050565b9050610e30611709565b15610e6857853414610e4457610e44611e2b565b600081815260ce602052604090205460ff1615610e6357610e63611e2b565b610fba565b3415610f1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a40161086a565b600081815260ce602052604090205460ff16610fba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c6179656400000000000000000000000000000000606482015260840161086a565b610fc3876117e5565b15611076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a40161086a565b600081815260cb602052604090205460ff1615611115576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c6179656400000000000000000000606482015260840161086a565b61113685611127611388619c40611dff565b67ffffffffffffffff1661182b565b158061115c575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561127557600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161126e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d65737361676500000000000000000000000000000000000000606482015260840161086a565b50506114cd565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a16179055600061130688619c405a6112c99190611e5a565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061184992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080156113bc57600082815260cb602052604090205460ff161561135957611359611e2b565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26114c9565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016114c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d65737361676500000000000000000000000000000000000000606482015260840161086a565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c42908490611553908890839089906000908990600401611e71565b6000604051808303818588803b15801561156c57600080fd5b505af1158015611580573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611636576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161086a565b60cc5473ffffffffffffffffffffffffffffffffffffffff166116805760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006116d585858585611863565b805190602001209050949350505050565b60006116f68787878787876118fc565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff1633148015610a67575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156117a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c99190611ec9565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611825575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b600080600080845160208601878a8af19695505050505050565b60608484848460405160240161187c9493929190611ee6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b606086868686868660405160240161191996959493929190611f30565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146119bd57600080fd5b50565b60008083601f8401126119d257600080fd5b50813567ffffffffffffffff8111156119ea57600080fd5b602083019150836020828501011115611a0257600080fd5b9250929050565b803563ffffffff81168114611a1d57600080fd5b919050565b60008060008060608587031215611a3857600080fd5b8435611a438161199b565b9350602085013567ffffffffffffffff811115611a5f57600080fd5b611a6b878288016119c0565b9094509250611a7e905060408601611a09565b905092959194509250565b60008060408385031215611a9c57600080fd5b8235611aa78161199b565b91506020830135611ab78161199b565b809150509250929050565b6000815180845260005b81811015611ae857602081850181015186830182015201611acc565b81811115611afa576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611b406020830184611ac2565b9392505050565b600060208284031215611b5957600080fd5b5035919050565b600080600060408486031215611b7557600080fd5b833567ffffffffffffffff811115611b8c57600080fd5b611b98868287016119c0565b9094509250611bab905060208501611a09565b90509250925092565b600080600080600080600060c0888a031215611bcf57600080fd5b873596506020880135611be18161199b565b95506040880135611bf18161199b565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611c1b57600080fd5b611c278a828b016119c0565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611cd560c083018486611c3a565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611d12608083018688611c3a565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611d4257600080fd5b81518015158114611b4057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611da857611da8611d52565b02949350505050565b600067ffffffffffffffff80841680611df3577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611e2257611e22611d52565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b600082821015611e6c57611e6c611d52565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a060808201526000611ebe60a0830184611ac2565b979650505050505050565b600060208284031215611edb57600080fd5b8151611b408161199b565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152611f1f6080830185611ac2565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152611f7b60c0830184611ac2565b9897505050505050505056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": true, + "newValue": "0x0000000000000000000000010000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000010000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000010000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": true, + "newValue": "0x0000000000000000000001010000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000010000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fb" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fb" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000001010000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000001010000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cc" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cc" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": true, + "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cc" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": true, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000007", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000001010000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000001010000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": true, + "newValue": "0x0000000000000000000000010000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000001010000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9fce812c", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000007", + "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000007", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xdb505d80", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000007", + "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000007", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x0ff754ea", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6425666b", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x35e80ab3", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fb" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x60806040523480156200001157600080fd5b50620000256001806000808080806200002b565b62000328565b600054610100900460ff16158080156200004c5750600054600160ff909116105b806200007c575062000069306200031960201b6200135d1760201c565b1580156200007c575060005460ff166001145b620000e55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000109576000805461ff0019166101001790555b60008811620001815760405162461bcd60e51b815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e20300000000000006064820152608401620000dc565b60008711620001f95760405162461bcd60e51b815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e20300000000000000000000000006064820152608401620000dc565b428511156200027f5760405162461bcd60e51b8152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201526374696d6560e01b608482015260a401620000dc565b6004889055600587905560018690556002859055600780546001600160a01b038087166001600160a01b0319928316179092556006805492861692909116919091179055600882905580156200030f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6001600160a01b03163b151590565b6115d580620003386000396000f3fe60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea164736f6c634300080f000a", + "deployedCode": "0x60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000007" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000007" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000006" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000006" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000008" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x529933df", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xe1a41bcf", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x002134cc", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x93991af3", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xbffa7f0f", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000007" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xa8e4fb90", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000007" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6b4d98dd", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000006" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x534db0e2", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000006" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf4daa291", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000008" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xce5db8d6", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000008" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x70872aa5", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x88786272", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x60806040523480156200001157600080fd5b506200004962000032600160008051602062002a4783398151915262000c39565b60001b600019620000c960201b62000e061760201c565b6040805160c080820183526001808352602080840182905260028486015260006060808601829052608080870183905260a08088018490528851968701895283875293860183905296850182905284018190529483018590528201849052620000c39361dead9390928392839290918391908290620000cd565b62000d5c565b9055565b600054610100900460ff1615808015620000ee5750600054600160ff909116105b806200011e57506200010b30620004df60201b62000e0a1760201c565b1580156200011e575060005460ff166001145b620001875760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015620001ab576000805461ff0019166101001790555b620001b5620004ee565b620001c08a62000556565b620001cb87620005d5565b620001d7898962000627565b620001e2866200068b565b620002197f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0886620000c960201b62000e061760201c565b6200025f6200024a60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59862000c39565b60001b84620000c960201b62000e061760201c565b620002a96200029060017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063762000c39565b60001b8360000151620000c960201b62000e061760201c565b620002f3620002da60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a862000c39565b60001b8360200151620000c960201b62000e061760201c565b6200033d6200032460017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637762000c39565b60001b8360400151620000c960201b62000e061760201c565b620003876200036e60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a687181662000c39565b60001b8360600151620000c960201b62000e061760201c565b620003d1620003b860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad62000c39565b60001b8360800151620000c960201b62000e061760201c565b6200041b6200040260017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d62000c39565b60001b8360a00151620000c960201b62000e061760201c565b6200042562000728565b620004308462000799565b6200043a62000add565b6001600160401b0316866001600160401b031610156200048c5760405162461bcd60e51b815260206004820152601f6024820152600080516020620029e783398151915260448201526064016200017e565b8015620004d3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b6001600160a01b03163b151590565b600054610100900460ff166200054a5760405162461bcd60e51b815260206004820152602b602482015260008051602062002a2783398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200017e565b6200055462000b0a565b565b6200056062000b71565b6001600160a01b038116620005c75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016200017e565b620005d28162000bcd565b50565b60678190556040805160208082018490528251808303909101815290820190915260005b600060008051602062002a07833981519152836040516200061b919062000c53565b60405180910390a35050565b60658290556066819055604080516020810184905290810182905260009060600160408051601f1981840301815291905290506001600060008051602062002a07833981519152836040516200067e919062000c53565b60405180910390a3505050565b6200069562000add565b6001600160401b0316816001600160401b03161015620006e75760405162461bcd60e51b815260206004820152601f6024820152600080516020620029e783398151915260448201526064016200017e565b606880546001600160401b0319166001600160401b0383169081179091556040805160208082019390935281518082039093018352810190526002620005f9565b6200075c62000748600160008051602062002a4783398151915262000c39565b60001b62000c1f60201b62000e261760201c565b60000362000554576200055462000784600160008051602062002a4783398151915262000c39565b60001b43620000c960201b62000e061760201c565b8060a001516001600160801b0316816060015163ffffffff161115620008285760405162461bcd60e51b815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d61782062617365000000000000000000000060648201526084016200017e565b6001816040015160ff1611620008995760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201526e65206c6172676572207468616e203160881b60648201526084016200017e565b606854608082015182516001600160401b0390921691620008bb919062000cab565b63ffffffff161115620009005760405162461bcd60e51b815260206004820152601f6024820152600080516020620029e783398151915260448201526064016200017e565b6000816020015160ff1611620009715760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201526e06965722063616e6e6f74206265203608c1b60648201526084016200017e565b8051602082015163ffffffff82169160ff909116906200099390829062000cd6565b6200099f919062000d08565b63ffffffff161462000a1a5760405162461bcd60e51b815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d697400000000000000000060648201526084016200017e565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff96871664ffffffffff199095169490941764010000000060ff948516021764ffffffffff60281b191665010000000000939092169290920263ffffffff60301b19161766010000000000009185169190910217600160501b600160f01b0319166a01000000000000000000009390941692909202600160701b600160f01b03191692909217600160701b6001600160801b0390921691909102179055565b60695460009062000b059063ffffffff6a010000000000000000000082048116911662000d37565b905090565b600054610100900460ff1662000b665760405162461bcd60e51b815260206004820152602b602482015260008051602062002a2783398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200017e565b620005543362000bcd565b6033546001600160a01b03163314620005545760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016200017e565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b5490565b634e487b7160e01b600052601160045260246000fd5b60008282101562000c4e5762000c4e62000c23565b500390565b600060208083528351808285015260005b8181101562000c825785810183015185820160400152820162000c64565b8181111562000c95576000604083870101525b50601f01601f1916929092016040019392505050565b600063ffffffff80831681851680830382111562000ccd5762000ccd62000c23565b01949350505050565b600063ffffffff8084168062000cfc57634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b600063ffffffff8083168185168183048111821515161562000d2e5762000d2e62000c23565b02949350505050565b60006001600160401b0382811684821680830382111562000ccd5762000ccd62000c23565b611c7b8062000d6c6000396000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c8063935f029e11610145578063dac6e63a116100bd578063f45e65d81161008c578063f8c68de011610071578063f8c68de014610597578063fd32aa0f1461059f578063ffa1ad74146105a757600080fd5b8063f45e65d81461057a578063f68016b71461058357600080fd5b8063dac6e63a1461054e578063e0e2016d14610556578063e81b2c6d1461055e578063f2fde38b1461056757600080fd5b8063bc49ce5f11610114578063c71973f6116100f9578063c71973f6146103f4578063c9b26f6114610407578063cc731b021461041a57600080fd5b8063bc49ce5f146103e4578063c4e8ddfa146103ec57600080fd5b8063935f029e146103ae5780639b7d7f0a146103c1578063a7119869146103c9578063b40a817c146103d157600080fd5b806348cd4cb1116101d857806354fd4d50116101a757806361d157681161018c57806361d1576814610380578063715018a6146103885780638da5cb5b1461039057600080fd5b806354fd4d501461032f5780635d73369c1461037857600080fd5b806348cd4cb1146102d75780634add321d146102df5780634d9f1559146103005780634f16540b1461030857600080fd5b80630c18c162116102145780630c18c162146102ab57806318d13918146102b457806319f5cea8146102c75780631fd19ee1146102cf57600080fd5b806306c9265714610246578063078f29cf146102615780630a49cb031461028e5780630bbb796814610296575b600080fd5b61024e6105af565b6040519081526020015b60405180910390f35b6102696105dd565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610258565b610269610616565b6102a96102a4366004611928565b610646565b005b61024e60655481565b6102a96102c2366004611a55565b610a44565b61024e610a58565b610269610a83565b61024e610aad565b6102e7610add565b60405167ffffffffffffffff9091168152602001610258565b610269610b03565b61024e7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b61036b6040518060400160405280600681526020017f312e31322e30000000000000000000000000000000000000000000000000000081525081565b6040516102589190611ae2565b61024e610b33565b61024e610b5e565b6102a9610b89565b60335473ffffffffffffffffffffffffffffffffffffffff16610269565b6102a96103bc366004611af5565b610b9d565b610269610bb3565b610269610be3565b6102a96103df366004611b17565b610c13565b61024e610c24565b610269610c4f565b6102a9610402366004611b32565b610c7f565b6102a9610415366004611b4e565b610c90565b6104de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102589190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b610269610ca1565b61024e610cd1565b61024e60675481565b6102a9610575366004611a55565b610cfc565b61024e60665481565b6068546102e79067ffffffffffffffff1681565b61024e610db0565b61024e610ddb565b61024e600081565b6105da60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611b96565b81565b600061061161060d60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611b96565b5490565b905090565b600061061161060d60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611b96565b600054610100900460ff16158080156106665750600054600160ff909116105b806106805750303b158015610680575060005460ff166001145b610711576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561076f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610777610e2a565b6107808a610cfc565b61078987610ec9565b6107938989610f2a565b61079c86610fbb565b6107c57f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b6107f86107f360017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611b96565b849055565b61082c61082660017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611b96565b83519055565b61086361085a60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611b96565b60208401519055565b61089a61089160017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611b96565b60408401519055565b6108d16108c860017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611b96565b60608401519055565b6109086108ff60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611b96565b60808401519055565b61093f61093660017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611b96565b60a08401519055565b610947611099565b61095084611101565b610958610add565b67ffffffffffffffff168667ffffffffffffffff1610156109d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610708565b8015610a3857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b610a4c611575565b610a55816115f6565b50565b6105da60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611b96565b60006106117f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b600061061161060d60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b6069546000906106119063ffffffff6a0100000000000000000000820481169116611bad565b600061061161060d60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611b96565b6105da60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611b96565b6105da60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611b96565b610b91611575565b610b9b600061167a565b565b610ba5611575565b610baf8282610f2a565b5050565b600061061161060d60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611b96565b600061061161060d60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611b96565b610c1b611575565b610a5581610fbb565b6105da60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611b96565b600061061161060d60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611b96565b610c87611575565b610a5581611101565b610c98611575565b610a5581610ec9565b600061061161060d60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611b96565b6105da60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b610d04611575565b73ffffffffffffffffffffffffffffffffffffffff8116610da7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610708565b610a558161167a565b6105da60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611b96565b6105da60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611b96565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b5490565b600054610100900460ff16610ec1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610708565b610b9b6116f1565b60678190556040805160208082018490528251808303909101815290820190915260005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610f1e9190611ae2565b60405180910390a35050565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610fae9190611ae2565b60405180910390a3505050565b610fc3610add565b67ffffffffffffffff168167ffffffffffffffff161015611040576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610708565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610eed565b6110c761060d60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b600003610b9b57610b9b6110fc60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b439055565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff1611156111b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610708565b6001816040015160ff1611611248576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610708565b6068546080820151825167ffffffffffffffff909216916112699190611bd9565b63ffffffff1611156112d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610708565b6000816020015160ff161161136e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610708565b8051602082015163ffffffff82169160ff9091169061138e908290611bf8565b6113989190611c42565b63ffffffff161461142b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610708565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610b9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610708565b61161f7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905290506003610eed565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610708565b610b9b3361167a565b803573ffffffffffffffffffffffffffffffffffffffff811681146117b557600080fd5b919050565b803567ffffffffffffffff811681146117b557600080fd5b60405160c0810167ffffffffffffffff8111828210171561181c577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290565b803563ffffffff811681146117b557600080fd5b803560ff811681146117b557600080fd5b600060c0828403121561185957600080fd5b60405160c0810181811067ffffffffffffffff821117156118a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806118b283611822565b81526118c060208401611836565b60208201526118d160408401611836565b60408201526118e260608401611822565b60608201526118f360808401611822565b608082015260a08301356fffffffffffffffffffffffffffffffff8116811461191b57600080fd5b60a0919091015292915050565b6000806000806000806000806000898b0361026081121561194857600080fd5b6119518b611791565b995060208b0135985060408b0135975060608b0135965061197460808c016117ba565b955061198260a08c01611791565b94506119918c60c08d01611847565b93506119a06101808c01611791565b925060c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe60820112156119d257600080fd5b506119db6117d2565b6119e86101a08c01611791565b81526119f76101c08c01611791565b6020820152611a096101e08c01611791565b6040820152611a1b6102008c01611791565b6060820152611a2d6102208c01611791565b6080820152611a3f6102408c01611791565b60a0820152809150509295985092959850929598565b600060208284031215611a6757600080fd5b611a7082611791565b9392505050565b6000815180845260005b81811015611a9d57602081850181015186830182015201611a81565b81811115611aaf576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611a706020830184611a77565b60008060408385031215611b0857600080fd5b50508035926020909101359150565b600060208284031215611b2957600080fd5b611a70826117ba565b600060c08284031215611b4457600080fd5b611a708383611847565b600060208284031215611b6057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611ba857611ba8611b67565b500390565b600067ffffffffffffffff808316818516808303821115611bd057611bd0611b67565b01949350505050565b600063ffffffff808316818516808303821115611bd057611bd0611b67565b600063ffffffff80841680611c36577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff80831681851681830481118215151615611c6557611c65611b67565b0294935050505056fea164736f6c634300080f000a53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77001d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069a11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0", + "deployedCode": "0x608060405234801561001057600080fd5b50600436106102415760003560e01c8063935f029e11610145578063dac6e63a116100bd578063f45e65d81161008c578063f8c68de011610071578063f8c68de014610597578063fd32aa0f1461059f578063ffa1ad74146105a757600080fd5b8063f45e65d81461057a578063f68016b71461058357600080fd5b8063dac6e63a1461054e578063e0e2016d14610556578063e81b2c6d1461055e578063f2fde38b1461056757600080fd5b8063bc49ce5f11610114578063c71973f6116100f9578063c71973f6146103f4578063c9b26f6114610407578063cc731b021461041a57600080fd5b8063bc49ce5f146103e4578063c4e8ddfa146103ec57600080fd5b8063935f029e146103ae5780639b7d7f0a146103c1578063a7119869146103c9578063b40a817c146103d157600080fd5b806348cd4cb1116101d857806354fd4d50116101a757806361d157681161018c57806361d1576814610380578063715018a6146103885780638da5cb5b1461039057600080fd5b806354fd4d501461032f5780635d73369c1461037857600080fd5b806348cd4cb1146102d75780634add321d146102df5780634d9f1559146103005780634f16540b1461030857600080fd5b80630c18c162116102145780630c18c162146102ab57806318d13918146102b457806319f5cea8146102c75780631fd19ee1146102cf57600080fd5b806306c9265714610246578063078f29cf146102615780630a49cb031461028e5780630bbb796814610296575b600080fd5b61024e6105af565b6040519081526020015b60405180910390f35b6102696105dd565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610258565b610269610616565b6102a96102a4366004611928565b610646565b005b61024e60655481565b6102a96102c2366004611a55565b610a44565b61024e610a58565b610269610a83565b61024e610aad565b6102e7610add565b60405167ffffffffffffffff9091168152602001610258565b610269610b03565b61024e7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b61036b6040518060400160405280600681526020017f312e31322e30000000000000000000000000000000000000000000000000000081525081565b6040516102589190611ae2565b61024e610b33565b61024e610b5e565b6102a9610b89565b60335473ffffffffffffffffffffffffffffffffffffffff16610269565b6102a96103bc366004611af5565b610b9d565b610269610bb3565b610269610be3565b6102a96103df366004611b17565b610c13565b61024e610c24565b610269610c4f565b6102a9610402366004611b32565b610c7f565b6102a9610415366004611b4e565b610c90565b6104de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102589190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b610269610ca1565b61024e610cd1565b61024e60675481565b6102a9610575366004611a55565b610cfc565b61024e60665481565b6068546102e79067ffffffffffffffff1681565b61024e610db0565b61024e610ddb565b61024e600081565b6105da60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611b96565b81565b600061061161060d60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611b96565b5490565b905090565b600061061161060d60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611b96565b600054610100900460ff16158080156106665750600054600160ff909116105b806106805750303b158015610680575060005460ff166001145b610711576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561076f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610777610e2a565b6107808a610cfc565b61078987610ec9565b6107938989610f2a565b61079c86610fbb565b6107c57f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b6107f86107f360017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611b96565b849055565b61082c61082660017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611b96565b83519055565b61086361085a60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611b96565b60208401519055565b61089a61089160017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611b96565b60408401519055565b6108d16108c860017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611b96565b60608401519055565b6109086108ff60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611b96565b60808401519055565b61093f61093660017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611b96565b60a08401519055565b610947611099565b61095084611101565b610958610add565b67ffffffffffffffff168667ffffffffffffffff1610156109d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610708565b8015610a3857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b610a4c611575565b610a55816115f6565b50565b6105da60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611b96565b60006106117f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b600061061161060d60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b6069546000906106119063ffffffff6a0100000000000000000000820481169116611bad565b600061061161060d60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611b96565b6105da60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611b96565b6105da60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611b96565b610b91611575565b610b9b600061167a565b565b610ba5611575565b610baf8282610f2a565b5050565b600061061161060d60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611b96565b600061061161060d60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611b96565b610c1b611575565b610a5581610fbb565b6105da60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611b96565b600061061161060d60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611b96565b610c87611575565b610a5581611101565b610c98611575565b610a5581610ec9565b600061061161060d60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611b96565b6105da60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b610d04611575565b73ffffffffffffffffffffffffffffffffffffffff8116610da7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610708565b610a558161167a565b6105da60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611b96565b6105da60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611b96565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b5490565b600054610100900460ff16610ec1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610708565b610b9b6116f1565b60678190556040805160208082018490528251808303909101815290820190915260005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610f1e9190611ae2565b60405180910390a35050565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610fae9190611ae2565b60405180910390a3505050565b610fc3610add565b67ffffffffffffffff168167ffffffffffffffff161015611040576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610708565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610eed565b6110c761060d60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b600003610b9b57610b9b6110fc60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b439055565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff1611156111b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610708565b6001816040015160ff1611611248576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610708565b6068546080820151825167ffffffffffffffff909216916112699190611bd9565b63ffffffff1611156112d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610708565b6000816020015160ff161161136e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610708565b8051602082015163ffffffff82169160ff9091169061138e908290611bf8565b6113989190611c42565b63ffffffff161461142b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610708565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610b9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610708565b61161f7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905290506003610eed565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610708565b610b9b3361167a565b803573ffffffffffffffffffffffffffffffffffffffff811681146117b557600080fd5b919050565b803567ffffffffffffffff811681146117b557600080fd5b60405160c0810167ffffffffffffffff8111828210171561181c577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290565b803563ffffffff811681146117b557600080fd5b803560ff811681146117b557600080fd5b600060c0828403121561185957600080fd5b60405160c0810181811067ffffffffffffffff821117156118a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806118b283611822565b81526118c060208401611836565b60208201526118d160408401611836565b60408201526118e260608401611822565b60608201526118f360808401611822565b608082015260a08301356fffffffffffffffffffffffffffffffff8116811461191b57600080fd5b60a0919091015292915050565b6000806000806000806000806000898b0361026081121561194857600080fd5b6119518b611791565b995060208b0135985060408b0135975060608b0135965061197460808c016117ba565b955061198260a08c01611791565b94506119918c60c08d01611847565b93506119a06101808c01611791565b925060c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe60820112156119d257600080fd5b506119db6117d2565b6119e86101a08c01611791565b81526119f76101c08c01611791565b6020820152611a096101e08c01611791565b6040820152611a1b6102008c01611791565b6060820152611a2d6102208c01611791565b6080820152611a3f6102408c01611791565b60a0820152809150509295985092959850929598565b600060208284031215611a6757600080fd5b611a7082611791565b9392505050565b6000815180845260005b81811015611a9d57602081850181015186830182015201611a81565b81811115611aaf576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611a706020830184611a77565b60008060408385031215611b0857600080fd5b50508035926020909101359150565b600060208284031215611b2957600080fd5b611a70826117ba565b600060c08284031215611b4457600080fd5b611a708383611847565b600060208284031215611b6057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611ba857611ba8611b67565b500390565b600067ffffffffffffffff808316818516808303821115611bd057611bd0611b67565b01949350505050565b600063ffffffff808316818516808303821115611bd057611bd0611b67565b600063ffffffff80841680611c36577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff80831681851681830481118215151615611c6557611c65611b67565b0294935050505056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb19f" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", + "previousValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", + "previousValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "previousValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000067" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000065" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000066" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc597" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580636" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a7" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6376" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871815" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ac" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320c" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "previousValue": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "reverted": false, + "slot": "0xa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb19f" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000020100000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000020100000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000020100000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xcc731b02", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000020100000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000020100000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x8da5cb5b", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "previousValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x0c18c162", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000065" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf45e65d8", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000066" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xe81b2c6d", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000067" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf68016b7", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x1fd19ee1", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x48cd4cb1", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "previousValue": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "reverted": false, + "slot": "0xa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb19f" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xdac6e63a", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc597" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xa7119869", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580636" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xc4e8ddfa", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a7" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x078f29cf", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6376" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x4d9f1559", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871815" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x0a49cb03", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ac" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9b7d7f0a", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320c" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x60806040523480156200001157600080fd5b506200001f60008062000025565b62000234565b600054610100900460ff1615808015620000465750600054600160ff909116105b8062000076575062000063306200018a60201b620005511760201c565b15801562000076575060005460ff166001145b620000df5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000103576000805461ff0019166101001790555b603280546001600160a01b0319166001600160a01b0384161790556200013e8373420000000000000000000000000000000000001062000199565b801562000185576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b600054610100900460ff16620002065760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d6565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b612c4d80620002446000396000f3fe6080604052600436106101795760003560e01c80637f46ddb2116100cb578063927ede2d1161007f578063b1a1a88211610059578063b1a1a882146104fe578063c89701a214610511578063e11013dd1461053e57600080fd5b8063927ede2d146104a05780639a2ac6d5146104cb578063a9f9e675146104de57600080fd5b806387087623116100b0578063870876231461043a5780638f601f661461045a57806391c49bf8146103ef57600080fd5b80637f46ddb2146103ef578063838b25201461041a57600080fd5b80633cb747bf1161012d57806354fd4d501161010757806354fd4d501461035457806358a997f6146103aa5780635c975abb146103ca57600080fd5b80633cb747bf146102e7578063485cc95514610314578063540abf731461033457600080fd5b80631532ec341161015e5780631532ec341461026a5780631635f5fd1461027d57806335e80ab31461029057600080fd5b80630166a07a1461023757806309fc88431461025757600080fd5b3661023257333b15610212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b610230333362030d406040518060200160405280600081525061056d565b005b600080fd5b34801561024357600080fd5b506102306102523660046126b1565b610580565b610230610265366004612762565b61099a565b6102306102783660046127b5565b610a71565b61023061028b3660046127b5565b610a85565b34801561029c57600080fd5b506032546102bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102f357600080fd5b506003546102bd9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032057600080fd5b5061023061032f366004612828565b610f4e565b34801561034057600080fd5b5061023061034f366004612861565b611137565b34801561036057600080fd5b5061039d6040518060400160405280600581526020017f322e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516102de919061294e565b3480156103b657600080fd5b506102306103c5366004612961565b61117c565b3480156103d657600080fd5b506103df611250565b60405190151581526020016102de565b3480156103fb57600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102bd565b34801561042657600080fd5b50610230610435366004612861565b6112e9565b34801561044657600080fd5b50610230610455366004612961565b61132e565b34801561046657600080fd5b50610492610475366004612828565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102de565b3480156104ac57600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102bd565b6102306104d93660046129e4565b611402565b3480156104ea57600080fd5b506102306104f93660046126b1565b611444565b61023061050c366004612762565b611453565b34801561051d57600080fd5b506004546102bd9073ffffffffffffffffffffffffffffffffffffffff1681565b61023061054c3660046129e4565b611524565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61057a8484348585611567565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610653575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610617573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063b9190612a47565b73ffffffffffffffffffffffffffffffffffffffff16145b610705576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b61070d611250565b15610774576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b61077d87611731565b156108cb5761078c8787611793565b61083e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108ae57600080fd5b505af11580156108c2573d6000803e3d6000fd5b5050505061094d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610909908490612a93565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c168352939052919091209190915561094d9085856118b3565b610991878787878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061198792505050565b50505050505050565b333b15610a29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610a6c3333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061156792505050565b505050565b610a7e8585858585610a85565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b58575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b409190612a47565b73ffffffffffffffffffffffffffffffffffffffff16145b610c0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b610c12611250565b15610c79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b823414610d08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610209565b3073ffffffffffffffffffffffffffffffffffffffff851603610dad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610209565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610e58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610209565b610e9a85858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a1592505050565b6000610eb7855a8660405180602001604052806000815250611a88565b905080610f46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610209565b505050505050565b600054610100900460ff1615808015610f6e5750600054600160ff909116105b80610f885750303b158015610f88575060005460ff166001145b611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610209565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561107257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556110d083734200000000000000000000000000000000000010611aa2565b8015610a6c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b61099187873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8c92505050565b333b1561120b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610f4686863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611eb792505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156112c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e49190612aaa565b905090565b61099187873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611eb792505050565b333b156113bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610f4686863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8c92505050565b61057a33858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061056d92505050565b61099187878787878787610580565b333b156114e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610a6c33338585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061056d92505050565b61057a3385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061156792505050565b8234146115f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610209565b61160285858584611ec6565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611665908b908b9086908a90602401612acc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526116f892918890600401612b15565b6000604051808303818588803b15801561171157600080fd5b505af1158015611725573d6000803e3d6000fd5b50505050505050505050565b600061175d827f1d1d8b6300000000000000000000000000000000000000000000000000000000611f39565b8061178d575061178d827fec4fc8e300000000000000000000000000000000000000000000000000000000611f39565b92915050565b60006117bf837f1d1d8b6300000000000000000000000000000000000000000000000000000000611f39565b15611868578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa15801561180f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118339190612a47565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905061178d565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561180f573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610a6c9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611f5c565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b38686866040516119ff93929190612b5a565b60405180910390a4610f46868686868686612068565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611a74929190612b98565b60405180910390a361057a848484846120f0565b600080600080845160208601878a8af19695505050505050565b600054610100900460ff16611b39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610209565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b611b9587611731565b15611ce357611ba48787611793565b611c56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611cc657600080fd5b505af1158015611cda573d6000803e3d6000fd5b50505050611d77565b611d0573ffffffffffffffffffffffffffffffffffffffff881686308661215d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611d43908490612bb1565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611d858787878787866121bb565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611de9908b908d908c908c908c908b90602401612bc9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611e7c92918790600401612b15565b600060405180830381600087803b158015611e9657600080fd5b505af1158015611eaa573d6000803e3d6000fd5b5050505050505050505050565b61099187878787878787611b8c565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611f25929190612b98565b60405180910390a361057a84848484612249565b6000611f44836122a8565b8015611f555750611f55838361230c565b9392505050565b6000611fbe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123db9092919063ffffffff16565b805190915015610a6c5780806020019051810190611fdc9190612aaa565b610a6c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610209565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd8686866040516120e093929190612b5a565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161214f929190612b98565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff8085166024830152831660448201526064810182905261057a9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611905565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161223393929190612b5a565b60405180910390a4610f468686868686866123f2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161214f929190612b98565b60006122d4827f01ffc9a70000000000000000000000000000000000000000000000000000000061230c565b801561178d5750612305827fffffffff0000000000000000000000000000000000000000000000000000000061230c565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156123c4575060208210155b80156123d05750600081115b979650505050505050565b60606123ea848460008561246a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf8686866040516120e093929190612b5a565b6060824710156124fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610209565b73ffffffffffffffffffffffffffffffffffffffff85163b61257a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610209565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125a39190612c24565b60006040518083038185875af1925050503d80600081146125e0576040519150601f19603f3d011682016040523d82523d6000602084013e6125e5565b606091505b50915091506123d0828286606083156125ff575081611f55565b82511561260f5782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610209919061294e565b73ffffffffffffffffffffffffffffffffffffffff8116811461266557600080fd5b50565b60008083601f84011261267a57600080fd5b50813567ffffffffffffffff81111561269257600080fd5b6020830191508360208285010111156126aa57600080fd5b9250929050565b600080600080600080600060c0888a0312156126cc57600080fd5b87356126d781612643565b965060208801356126e781612643565b955060408801356126f781612643565b9450606088013561270781612643565b93506080880135925060a088013567ffffffffffffffff81111561272a57600080fd5b6127368a828b01612668565b989b979a50959850939692959293505050565b803563ffffffff8116811461275d57600080fd5b919050565b60008060006040848603121561277757600080fd5b61278084612749565b9250602084013567ffffffffffffffff81111561279c57600080fd5b6127a886828701612668565b9497909650939450505050565b6000806000806000608086880312156127cd57600080fd5b85356127d881612643565b945060208601356127e881612643565b935060408601359250606086013567ffffffffffffffff81111561280b57600080fd5b61281788828901612668565b969995985093965092949392505050565b6000806040838503121561283b57600080fd5b823561284681612643565b9150602083013561285681612643565b809150509250929050565b600080600080600080600060c0888a03121561287c57600080fd5b873561288781612643565b9650602088013561289781612643565b955060408801356128a781612643565b9450606088013593506128bc60808901612749565b925060a088013567ffffffffffffffff81111561272a57600080fd5b60005b838110156128f35781810151838201526020016128db565b8381111561057a5750506000910152565b6000815180845261291c8160208601602086016128d8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f556020830184612904565b60008060008060008060a0878903121561297a57600080fd5b863561298581612643565b9550602087013561299581612643565b9450604087013593506129aa60608801612749565b9250608087013567ffffffffffffffff8111156129c657600080fd5b6129d289828a01612668565b979a9699509497509295939492505050565b600080600080606085870312156129fa57600080fd5b8435612a0581612643565b9350612a1360208601612749565b9250604085013567ffffffffffffffff811115612a2f57600080fd5b612a3b87828801612668565b95989497509550505050565b600060208284031215612a5957600080fd5b8151611f5581612643565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612aa557612aa5612a64565b500390565b600060208284031215612abc57600080fd5b81518015158114611f5557600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612b0b6080830184612904565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612b446060830185612904565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612b8f6060830184612904565b95945050505050565b8281526040602082015260006123ea6040830184612904565b60008219821115612bc457612bc4612a64565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612c1860c0830184612904565b98975050505050505050565b60008251612c368184602087016128d8565b919091019291505056fea164736f6c634300080f000a", + "deployedCode": "0x6080604052600436106101795760003560e01c80637f46ddb2116100cb578063927ede2d1161007f578063b1a1a88211610059578063b1a1a882146104fe578063c89701a214610511578063e11013dd1461053e57600080fd5b8063927ede2d146104a05780639a2ac6d5146104cb578063a9f9e675146104de57600080fd5b806387087623116100b0578063870876231461043a5780638f601f661461045a57806391c49bf8146103ef57600080fd5b80637f46ddb2146103ef578063838b25201461041a57600080fd5b80633cb747bf1161012d57806354fd4d501161010757806354fd4d501461035457806358a997f6146103aa5780635c975abb146103ca57600080fd5b80633cb747bf146102e7578063485cc95514610314578063540abf731461033457600080fd5b80631532ec341161015e5780631532ec341461026a5780631635f5fd1461027d57806335e80ab31461029057600080fd5b80630166a07a1461023757806309fc88431461025757600080fd5b3661023257333b15610212576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b610230333362030d406040518060200160405280600081525061056d565b005b600080fd5b34801561024357600080fd5b506102306102523660046126b1565b610580565b610230610265366004612762565b61099a565b6102306102783660046127b5565b610a71565b61023061028b3660046127b5565b610a85565b34801561029c57600080fd5b506032546102bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102f357600080fd5b506003546102bd9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032057600080fd5b5061023061032f366004612828565b610f4e565b34801561034057600080fd5b5061023061034f366004612861565b611137565b34801561036057600080fd5b5061039d6040518060400160405280600581526020017f322e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516102de919061294e565b3480156103b657600080fd5b506102306103c5366004612961565b61117c565b3480156103d657600080fd5b506103df611250565b60405190151581526020016102de565b3480156103fb57600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102bd565b34801561042657600080fd5b50610230610435366004612861565b6112e9565b34801561044657600080fd5b50610230610455366004612961565b61132e565b34801561046657600080fd5b50610492610475366004612828565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102de565b3480156104ac57600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102bd565b6102306104d93660046129e4565b611402565b3480156104ea57600080fd5b506102306104f93660046126b1565b611444565b61023061050c366004612762565b611453565b34801561051d57600080fd5b506004546102bd9073ffffffffffffffffffffffffffffffffffffffff1681565b61023061054c3660046129e4565b611524565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61057a8484348585611567565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610653575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610617573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063b9190612a47565b73ffffffffffffffffffffffffffffffffffffffff16145b610705576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b61070d611250565b15610774576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b61077d87611731565b156108cb5761078c8787611793565b61083e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108ae57600080fd5b505af11580156108c2573d6000803e3d6000fd5b5050505061094d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610909908490612a93565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c168352939052919091209190915561094d9085856118b3565b610991878787878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061198792505050565b50505050505050565b333b15610a29576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610a6c3333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061156792505050565b505050565b610a7e8585858585610a85565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b58575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b409190612a47565b73ffffffffffffffffffffffffffffffffffffffff16145b610c0a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610209565b610c12611250565b15610c79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610209565b823414610d08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610209565b3073ffffffffffffffffffffffffffffffffffffffff851603610dad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610209565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610e58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610209565b610e9a85858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a1592505050565b6000610eb7855a8660405180602001604052806000815250611a88565b905080610f46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610209565b505050505050565b600054610100900460ff1615808015610f6e5750600054600160ff909116105b80610f885750303b158015610f88575060005460ff166001145b611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610209565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561107257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556110d083734200000000000000000000000000000000000010611aa2565b8015610a6c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b61099187873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8c92505050565b333b1561120b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610f4686863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611eb792505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156112c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e49190612aaa565b905090565b61099187873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611eb792505050565b333b156113bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610f4686863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b8c92505050565b61057a33858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061056d92505050565b61099187878787878787610580565b333b156114e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610209565b610a6c33338585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061056d92505050565b61057a3385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061156792505050565b8234146115f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610209565b61160285858584611ec6565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611665908b908b9086908a90602401612acc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526116f892918890600401612b15565b6000604051808303818588803b15801561171157600080fd5b505af1158015611725573d6000803e3d6000fd5b50505050505050505050565b600061175d827f1d1d8b6300000000000000000000000000000000000000000000000000000000611f39565b8061178d575061178d827fec4fc8e300000000000000000000000000000000000000000000000000000000611f39565b92915050565b60006117bf837f1d1d8b6300000000000000000000000000000000000000000000000000000000611f39565b15611868578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa15801561180f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118339190612a47565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905061178d565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561180f573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610a6c9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611f5c565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b38686866040516119ff93929190612b5a565b60405180910390a4610f46868686868686612068565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611a74929190612b98565b60405180910390a361057a848484846120f0565b600080600080845160208601878a8af19695505050505050565b600054610100900460ff16611b39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610209565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b611b9587611731565b15611ce357611ba48787611793565b611c56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610209565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611cc657600080fd5b505af1158015611cda573d6000803e3d6000fd5b50505050611d77565b611d0573ffffffffffffffffffffffffffffffffffffffff881686308661215d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611d43908490612bb1565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611d858787878787866121bb565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611de9908b908d908c908c908c908b90602401612bc9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611e7c92918790600401612b15565b600060405180830381600087803b158015611e9657600080fd5b505af1158015611eaa573d6000803e3d6000fd5b5050505050505050505050565b61099187878787878787611b8c565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051611f25929190612b98565b60405180910390a361057a84848484612249565b6000611f44836122a8565b8015611f555750611f55838361230c565b9392505050565b6000611fbe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123db9092919063ffffffff16565b805190915015610a6c5780806020019051810190611fdc9190612aaa565b610a6c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610209565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd8686866040516120e093929190612b5a565b60405180910390a4505050505050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161214f929190612b98565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff8085166024830152831660448201526064810182905261057a9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611905565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161223393929190612b5a565b60405180910390a4610f468686868686866123f2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161214f929190612b98565b60006122d4827f01ffc9a70000000000000000000000000000000000000000000000000000000061230c565b801561178d5750612305827fffffffff0000000000000000000000000000000000000000000000000000000061230c565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156123c4575060208210155b80156123d05750600081115b979650505050505050565b60606123ea848460008561246a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf8686866040516120e093929190612b5a565b6060824710156124fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610209565b73ffffffffffffffffffffffffffffffffffffffff85163b61257a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610209565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125a39190612c24565b60006040518083038185875af1925050503d80600081146125e0576040519150601f19603f3d011682016040523d82523d6000602084013e6125e5565b606091505b50915091506123d0828286606083156125ff575081611f55565b82511561260f5782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610209919061294e565b73ffffffffffffffffffffffffffffffffffffffff8116811461266557600080fd5b50565b60008083601f84011261267a57600080fd5b50813567ffffffffffffffff81111561269257600080fd5b6020830191508360208285010111156126aa57600080fd5b9250929050565b600080600080600080600060c0888a0312156126cc57600080fd5b87356126d781612643565b965060208801356126e781612643565b955060408801356126f781612643565b9450606088013561270781612643565b93506080880135925060a088013567ffffffffffffffff81111561272a57600080fd5b6127368a828b01612668565b989b979a50959850939692959293505050565b803563ffffffff8116811461275d57600080fd5b919050565b60008060006040848603121561277757600080fd5b61278084612749565b9250602084013567ffffffffffffffff81111561279c57600080fd5b6127a886828701612668565b9497909650939450505050565b6000806000806000608086880312156127cd57600080fd5b85356127d881612643565b945060208601356127e881612643565b935060408601359250606086013567ffffffffffffffff81111561280b57600080fd5b61281788828901612668565b969995985093965092949392505050565b6000806040838503121561283b57600080fd5b823561284681612643565b9150602083013561285681612643565b809150509250929050565b600080600080600080600060c0888a03121561287c57600080fd5b873561288781612643565b9650602088013561289781612643565b955060408801356128a781612643565b9450606088013593506128bc60808901612749565b925060a088013567ffffffffffffffff81111561272a57600080fd5b60005b838110156128f35781810151838201526020016128db565b8381111561057a5750506000910152565b6000815180845261291c8160208601602086016128d8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611f556020830184612904565b60008060008060008060a0878903121561297a57600080fd5b863561298581612643565b9550602087013561299581612643565b9450604087013593506129aa60608801612749565b9250608087013567ffffffffffffffff8111156129c657600080fd5b6129d289828a01612668565b979a9699509497509295939492505050565b600080600080606085870312156129fa57600080fd5b8435612a0581612643565b9350612a1360208601612749565b9250604085013567ffffffffffffffff811115612a2f57600080fd5b612a3b87828801612668565b95989497509550505050565b600060208284031215612a5957600080fd5b8151611f5581612643565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612aa557612aa5612a64565b500390565b600060208284031215612abc57600080fd5b81518015158114611f5557600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612b0b6080830184612904565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612b446060830185612904565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612b8f6060830184612904565b95945050505050565b8281526040602082015260006123ea6040830184612904565b60008219821115612bc457612bc4612a64565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612c1860c0830184612904565b98975050505050505050565b60008251612c368184602087016128d8565b919091019291505056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": true, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000010", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x927ede2d", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x3cb747bf", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x7f46ddb2", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000010", + "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000010", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xc89701a2", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000010", + "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000010", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x35e80ab3", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x60806040523480156200001157600080fd5b506200001f60008062000025565b62000234565b600054610100900460ff1615808015620000465750600054600160ff909116105b8062000076575062000063306200018a60201b62000b141760201c565b15801562000076575060005460ff166001145b620000df5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000103576000805461ff0019166101001790555b603280546001600160a01b0319166001600160a01b0384161790556200013e8373420000000000000000000000000000000000001462000199565b801562000185576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b600054610100900460ff16620002065760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d6565b600180546001600160a01b039384166001600160a01b03199182161790915560028054929093169116179055565b6113e980620002446000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600581526020017f322e312e3000000000000000000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", + "deployedCode": "0x608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600581526020017f322e312e3000000000000000000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": true, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000014", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x7f46ddb2", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000014", + "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000014", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xc89701a2", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000014", + "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000014", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x927ede2d", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x3cb747bf", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x35e80ab3", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x68ea2a43", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "previousValue": "0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000017" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xd2354f20", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000000d" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x81143a59", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000834", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000834", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000002b" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x0ac77bb5", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x00000000000000000000000000000000000000000000000000000000000f4240", + "previousValue": "0x00000000000000000000000000000000000000000000000000000000000f4240", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000002c" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x2dde36f5", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x00000000000000000000000000000000000000000000000000000000017d7840", + "previousValue": "0x00000000000000000000000000000000000000000000000000000000017d7840", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000029" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xe7d6cd42", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000015" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9c16360f", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x000000000000000000000000ff00000000000000000000000000000000000000", + "previousValue": "0x000000000000000000000000ff00000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000016" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000003049623609d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002640bbb79680000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f42400000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb000000000000000000000000978e3286eb805934215a88694d80b09aded68d900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "previousValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000003049623609d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002640bbb79680000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f42400000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb000000000000000000000000978e3286eb805934215a88694d80b09aded68d900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000003", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" + } + ], + "value": 0 + }, + { + "accessor": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9623609d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002640bbb79680000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f42400000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb000000000000000000000000978e3286eb805934215a88694d80b09aded68d90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "previousValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x727598a658f6983be3a9f29beef55aaee89ef8a176baeeacbe7edf5ff94a781b" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x4f1ef286000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002640bbb79680000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f42400000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb000000000000000000000000978e3286eb805934215a88694d80b09aded68d90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x0bbb79680000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f42400000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb000000000000000000000000978e3286eb805934215a88694d80b09aded68d900000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000067" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000834", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000065" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x00000000000000000000000000000000000000000000000000000000000f4240", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000066" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x00000000000000000000000000000000000000000000000000000000017d7840", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x000000000000000000000000ff00000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc597" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580636" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a7" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6376" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871815" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x000000000000000000000000978e3286eb805934215a88694d80b09aded68d90", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ac" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320c" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb19f" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb19f" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x00000000000000000000000000000000000000000000000000000000017d7840", + "previousValue": "0x00000000000000000000000000000000000000000000000000000000017d7840", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00", + "previousValue": "0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x54fd4d50", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x54fd4d50", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xcc731b02", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xcc731b02", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00", + "previousValue": "0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xd2354f20", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000000d" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x8da5cb5b", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x8da5cb5b", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x81143a59", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000834", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000834", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000002b" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x0c18c162", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x0c18c162", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000834", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000834", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000065" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x0ac77bb5", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x00000000000000000000000000000000000000000000000000000000000f4240", + "previousValue": "0x00000000000000000000000000000000000000000000000000000000000f4240", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000002c" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf45e65d8", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf45e65d8", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x00000000000000000000000000000000000000000000000000000000000f4240", + "previousValue": "0x00000000000000000000000000000000000000000000000000000000000f4240", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000066" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x68ea2a43", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "previousValue": "0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000017" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xe81b2c6d", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xe81b2c6d", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "previousValue": "0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000067" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x2dde36f5", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x00000000000000000000000000000000000000000000000000000000017d7840", + "previousValue": "0x00000000000000000000000000000000000000000000000000000000017d7840", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000029" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf68016b7", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf68016b7", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x00000000000000000000000000000000000000000000000000000000017d7840", + "previousValue": "0x00000000000000000000000000000000000000000000000000000000017d7840", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xe7d6cd42", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000015" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x1fd19ee1", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x1fd19ee1", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x102c9aa4", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000039" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x48cd4cb1", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x48cd4cb1", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb19f" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9c16360f", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x000000000000000000000000ff00000000000000000000000000000000000000", + "previousValue": "0x000000000000000000000000ff00000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000016" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xdac6e63a", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xdac6e63a", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ff00000000000000000000000000000000000000", + "previousValue": "0x000000000000000000000000ff00000000000000000000000000000000000000", + "reverted": false, + "slot": "0x71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc597" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xa7119869", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xa7119869", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "previousValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "reverted": false, + "slot": "0x383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580636" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xc4e8ddfa", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xc4e8ddfa", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", + "previousValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", + "reverted": false, + "slot": "0x46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a7" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x078f29cf", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x078f29cf", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", + "previousValue": "0x0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", + "reverted": false, + "slot": "0x9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6376" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x4d9f1559", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x4d9f1559", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb", + "previousValue": "0x0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb", + "reverted": false, + "slot": "0xe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871815" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x0a49cb03", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x0a49cb03", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000978e3286eb805934215a88694d80b09aded68d90", + "previousValue": "0x000000000000000000000000978e3286eb805934215a88694d80b09aded68d90", + "reverted": false, + "slot": "0x4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ac" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9b7d7f0a", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "previousValue": "0x000000000000000000000000ffba8944650e26653823658d76a122946f27e2f2", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xffbA8944650e26653823658d76A122946F27e2f2", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9b7d7f0a", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320c" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6bd9f5160000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xa8f0d50211ac8ff1a40793a899dff3ced4762e0466f69b0078ab7b00d037835c" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000448d52d4a00000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "previousValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000448d52d4a00000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000003", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000003", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000003", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000003", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000004", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000003", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" + } + ], + "value": 0 + }, + { + "accessor": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x8d52d4a00000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000000000000000000000000000000000000000000001", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "previousValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xa8f0d50211ac8ff1a40793a899dff3ced4762e0466f69b0078ab7b00d037835c" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xa8f0d50211ac8ff1a40793a899dff3ced4762e0466f69b0078ab7b00d037835c" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6bd9f5160000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xa8f0d50211ac8ff1a40793a899dff3ced4762e0466f69b0078ab7b00d037835c" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc95500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "previousValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc95500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000004", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000004", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000004", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000004", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000005", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000004", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" + } + ], + "value": 0 + }, + { + "accessor": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9623609d0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc95500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "previousValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xa8f0d50211ac8ff1a40793a899dff3ced4762e0466f69b0078ab7b00d037835c" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "previousValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xa8f0d50211ac8ff1a40793a899dff3ced4762e0466f69b0078ab7b00d037835c" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9b0b0fda360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": true, + "newValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x485cc95500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xb7947262", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "previousValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x485cc95500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": true, + "newValue": "0x000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": true, + "newValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": true, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000010", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x54fd4d50", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xb7947262", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "previousValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x54fd4d50", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x927ede2d", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xb7947262", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "previousValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x927ede2d", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "previousValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x3cb747bf", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xb7947262", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "previousValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x3cb747bf", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "previousValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x7f46ddb2", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xb7947262", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "previousValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x7f46ddb2", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000010", + "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000010", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xc89701a2", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xb7947262", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "previousValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xc89701a2", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000010", + "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000010", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x35e80ab3", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + } + ], + "value": 0 + }, + { + "accessor": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xb7947262", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "previousValue": "0x0000000000000000000000000da314776b267d898dee57f6ede357ae28b3b83c", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x0Da314776B267D898dEE57F6Ede357ae28b3b83c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x35e80ab3", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", + "isWrite": false, + "newValue": "0x000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809", + "previousValue": "0x000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd058600000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc95500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "previousValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd058600000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc95500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000005", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000005", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000005", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000005", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000006", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000005", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" + } + ], + "value": 0 + }, + { + "accessor": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9623609d000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd058600000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc95500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "previousValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x4f1ef28600000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd058600000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044485cc95500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": true, + "newValue": "0x00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd0586", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x485cc95500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": true, + "newValue": "0x000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": true, + "newValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": true, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000014", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x54fd4d50", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd0586", + "previousValue": "0x00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd0586", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x54fd4d50", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x7f46ddb2", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd0586", + "previousValue": "0x00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd0586", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x7f46ddb2", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000014", + "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000014", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xc89701a2", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd0586", + "previousValue": "0x00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd0586", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xc89701a2", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000014", + "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000014", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x927ede2d", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd0586", + "previousValue": "0x00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd0586", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x927ede2d", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "previousValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x3cb747bf", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd0586", + "previousValue": "0x00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd0586", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x3cb747bf", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "previousValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x35e80ab3", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd0586", + "previousValue": "0x00000000000000000000000044637a4292e0cd2b17a55d5f6b2f05afcacd0586", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x44637A4292E0CD2B17A55d5F6B2F05AFcAcD0586", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x35e80ab3", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", + "isWrite": false, + "newValue": "0x000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809", + "previousValue": "0x000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6bd9f51600000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000448d52d4a000000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "previousValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000448d52d4a000000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000006", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000006", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000006", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000006", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000007", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000006", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" + } + ], + "value": 0 + }, + { + "accessor": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x8d52d4a000000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d0000000000000000000000000000000000000000000000000000000000000002", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "previousValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6bd9f51600000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x238181ae00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xa84149e805fd07fd65e6292517ce28bc2d9d17991b87a6d9c16e7c7cb921ab16" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xa84149e805fd07fd65e6292517ce28bc2d9d17991b87a6d9c16e7c7cb921ab16" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000084860f7cda00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e6765720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "previousValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000084860f7cda00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e6765720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000007", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000007", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000007", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000007", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000008", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000007", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" + } + ], + "value": 0 + }, + { + "accessor": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x860f7cda00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "previousValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x17eb2365d570ef4d1cc4abe9e522ed8632b11233db9c15f3c2c8aa32407b981b" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": true, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x17eb2365d570ef4d1cc4abe9e522ed8632b11233db9c15f3c2c8aa32407b981b" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x238181ae00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "reverted": false, + "slot": "0x17eb2365d570ef4d1cc4abe9e522ed8632b11233db9c15f3c2c8aa32407b981b" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "reverted": false, + "slot": "0x17eb2365d570ef4d1cc4abe9e522ed8632b11233db9c15f3c2c8aa32407b981b" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "reverted": false, + "slot": "0x17eb2365d570ef4d1cc4abe9e522ed8632b11233db9c15f3c2c8aa32407b981b" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000978e3286eb805934215a88694d80b09aded68d90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "previousValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000978e3286eb805934215a88694d80b09aded68d90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000008", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000008", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000008", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000008", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000009", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000008", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" + } + ], + "value": 0 + }, + { + "accessor": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9623609d00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000978e3286eb805934215a88694d80b09aded68d9000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "previousValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "previousValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "reverted": false, + "slot": "0x17eb2365d570ef4d1cc4abe9e522ed8632b11233db9c15f3c2c8aa32407b981b" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "reverted": false, + "slot": "0x17eb2365d570ef4d1cc4abe9e522ed8632b11233db9c15f3c2c8aa32407b981b" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "reverted": false, + "slot": "0x17eb2365d570ef4d1cc4abe9e522ed8632b11233db9c15f3c2c8aa32407b981b" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9b2ea4bd000000000000000000000000000000000000000000000000000000000000004000000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" + }, + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": true, + "newValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x485cc955000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000978e3286eb805934215a88694d80b09aded68d90", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "reverted": false, + "slot": "0x4505be7acf20898edfef2b5289635349881ad9bf4b57316a74e81e2abec2be52" + } + ], + "value": 0 + }, + { + "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "previousValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "reverted": false, + "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x485cc955000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000978e3286eb805934215a88694d80b09aded68d90", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": true, + "newValue": "0x0000000000000000000000010000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000000010000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000010000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": true, + "newValue": "0x0000000000000000000001010000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000010000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fb" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": true, + "newValue": "0x000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fb" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": true, + "newValue": "0x000000000000000000000000978e3286eb805934215a88694d80b09aded68d90", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000001010000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000001010000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cc" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cc" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": true, + "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cc" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": true, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000007", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000001010000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000001010000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": true, + "newValue": "0x0000000000000000000000010000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000001010000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x54fd4d50", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "reverted": false, + "slot": "0x4505be7acf20898edfef2b5289635349881ad9bf4b57316a74e81e2abec2be52" + } + ], + "value": 0 + }, + { + "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "previousValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "reverted": false, + "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x54fd4d50", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9fce812c", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "reverted": false, + "slot": "0x4505be7acf20898edfef2b5289635349881ad9bf4b57316a74e81e2abec2be52" + } + ], + "value": 0 + }, + { + "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "previousValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "reverted": false, + "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9fce812c", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000007", + "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000007", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xdb505d80", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "reverted": false, + "slot": "0x4505be7acf20898edfef2b5289635349881ad9bf4b57316a74e81e2abec2be52" + } + ], + "value": 0 + }, + { + "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "previousValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "reverted": false, + "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xdb505d80", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x0000000000000000000000004200000000000000000000000000000000000007", + "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000007", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x0ff754ea", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "reverted": false, + "slot": "0x4505be7acf20898edfef2b5289635349881ad9bf4b57316a74e81e2abec2be52" + } + ], + "value": 0 + }, + { + "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "previousValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "reverted": false, + "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x0ff754ea", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x000000000000000000000000978e3286eb805934215a88694d80b09aded68d90", + "previousValue": "0x000000000000000000000000978e3286eb805934215a88694d80b09aded68d90", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6425666b", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "reverted": false, + "slot": "0x4505be7acf20898edfef2b5289635349881ad9bf4b57316a74e81e2abec2be52" + } + ], + "value": 0 + }, + { + "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "previousValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "reverted": false, + "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6425666b", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x000000000000000000000000978e3286eb805934215a88694d80b09aded68d90", + "previousValue": "0x000000000000000000000000978e3286eb805934215a88694d80b09aded68d90", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x35e80ab3", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", + "reverted": false, + "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" + }, + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", + "reverted": false, + "slot": "0x4505be7acf20898edfef2b5289635349881ad9bf4b57316a74e81e2abec2be52" + } + ], + "value": 0 + }, + { + "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", + "isWrite": false, + "newValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "previousValue": "0x00000000000000000000000071fa82ea96672797954c28032b337aa40aafc99f", + "reverted": false, + "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x71fA82Ea96672797954C28032b337aA40AAFC99f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x35e80ab3", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", + "isWrite": false, + "newValue": "0x000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809", + "previousValue": "0x000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809", + "reverted": false, + "slot": "0x00000000000000000000000000000000000000000000000000000000000000fb" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d000000000000000000000000978e3286eb805934215a88694d80b09aded68d900000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "previousValue": "0x00000000000000000000000090193c961a926261b756d1e5bb255e67ff9498a1", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x90193C961A926261B756D1E5bb255e67ff9498A1", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6a761202000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c7600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d000000000000000000000000978e3286eb805934215a88694d80b09aded68d900000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000009", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000009", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000009", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000009", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": true, + "newValue": "0x000000000000000000000000000000000000000000000000000000000000000a", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000009", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" + }, + { + "account": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" + } + ], + "value": 0 + }, + { + "accessor": "0x2601573C28B77dea6C8B73385c25024A28a00C3F", + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9623609d000000000000000000000000978e3286eb805934215a88694d80b09aded68d900000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "previousValue": "0x0000000000000000000000002601573c28b77dea6c8b73385c25024a28a00c3f", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x9302c2c5f397028777ab180924fb28ceaf3af9b6a91b43410c4c0afe36476877" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x4f1ef2860000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "Call", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "previousValue": "0x000000000000000000000000db8cff278adccf9e9b5da745b44e754fc4ee3c76", + "reverted": false, + "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": true, + "newValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0xDB8cFf278adCCF9E9b5da745B44E754fC4EE3C76", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xc0c53b8b0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d70809", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": true, + "newValue": "0x0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": true, + "newValue": "0x0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": true, + "newValue": "0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": true, + "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": true, + "newValue": "0x000000000000000100000000000000000000000000000000000000003b9aca00", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x54fd4d50", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "previousValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x54fd4d50", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xfa60f9b2", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0x000000000000000000000000000000000000000000000000000000000000000e" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": false, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x001c2ff6", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "previousValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x001c2ff6", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb", + "previousValue": "0x0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9b5f694a", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "previousValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9b5f694a", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb", + "previousValue": "0x0000000000000000000000008b71b41d4dbeb2b6821d44692d3facaaf77480bb", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf0498750", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "previousValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf0498750", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4", + "previousValue": "0x0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x33d7e2bd", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "previousValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x33d7e2bd", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4", + "previousValue": "0x0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x724c184c", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "previousValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x724c184c", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900", + "previousValue": "0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" + } + ], + "value": 0 + }, + { + "accessor": "0x978e3286EB805934215a88694d80b09aDed68D90", + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x452a9320", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", + "previousValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x978e3286EB805934215a88694d80b09aDed68D90", + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x452a9320", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x452a9320", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "previousValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x452a9320", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900", + "previousValue": "0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" + } + ], + "value": 0 + }, + { + "accessor": "0x978e3286EB805934215a88694d80b09aDed68D90", + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x452a9320", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", + "previousValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x978e3286EB805934215a88694d80b09aDed68D90", + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x452a9320", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", + "reverted": false, + "slot": "0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x35e80ab3", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "previousValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x35e80ab3", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900", + "previousValue": "0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x5c975abb", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", + "previousValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x5c975abb", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b6" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x5c975abb", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "previousValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x5c975abb", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900", + "previousValue": "0x0000000000000000000000deb1e9a6be7baf84208bb6e10ac9f9bbe1d7080900", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" + } + ], + "value": 0 + }, + { + "accessor": "0x978e3286EB805934215a88694d80b09aDed68D90", + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x5c975abb", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", + "previousValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x978e3286EB805934215a88694d80b09aDed68D90", + "account": "0x068E44eB31e111028c41598E4535be7468674D0A", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x5c975abb", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b6" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9bf62d82", + "deployedCode": "0x", + "initialized": true, + "kind": "StaticCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "previousValue": "0x0000000000000000000000008887e7568e81405c4e0d4caaabdda949e3b9d4e4", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", + "account": "0x8887E7568E81405c4E0D4cAaabdda949e3B9d4E4", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x9bf62d82", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x978e3286EB805934215a88694d80b09aDed68D90", + "isWrite": false, + "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "previousValue": "0x000000000000000000000000000000000000000000000000000000000000dead", + "reverted": false, + "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + } + ] +} diff --git a/packages/contracts-bedrock/snapshots/storageLayout/AnchorStateRegistry.json b/packages/contracts-bedrock/snapshots/storageLayout/AnchorStateRegistry.json new file mode 100644 index 000000000000..5da4030ae426 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/AnchorStateRegistry.json @@ -0,0 +1,23 @@ +[ + { + "bytes": "1", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "uint8" + }, + { + "bytes": "1", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "bool" + }, + { + "bytes": "32", + "label": "anchors", + "offset": 0, + "slot": "1", + "type": "mapping(GameType => struct OutputRoot)" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/DataAvailabilityChallenge.json b/packages/contracts-bedrock/snapshots/storageLayout/DataAvailabilityChallenge.json new file mode 100644 index 000000000000..95c66157adc8 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/DataAvailabilityChallenge.json @@ -0,0 +1,79 @@ +[ + { + "bytes": "1", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "uint8" + }, + { + "bytes": "1", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "bool" + }, + { + "bytes": "1600", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "uint256[50]" + }, + { + "bytes": "20", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "address" + }, + { + "bytes": "1568", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "uint256[49]" + }, + { + "bytes": "32", + "label": "challengeWindow", + "offset": 0, + "slot": "101", + "type": "uint256" + }, + { + "bytes": "32", + "label": "resolveWindow", + "offset": 0, + "slot": "102", + "type": "uint256" + }, + { + "bytes": "32", + "label": "bondSize", + "offset": 0, + "slot": "103", + "type": "uint256" + }, + { + "bytes": "32", + "label": "resolverRefundPercentage", + "offset": 0, + "slot": "104", + "type": "uint256" + }, + { + "bytes": "32", + "label": "balances", + "offset": 0, + "slot": "105", + "type": "mapping(address => uint256)" + }, + { + "bytes": "32", + "label": "challenges", + "offset": 0, + "slot": "106", + "type": "mapping(uint256 => mapping(bytes => struct Challenge))" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/DelayedWETH.json b/packages/contracts-bedrock/snapshots/storageLayout/DelayedWETH.json new file mode 100644 index 000000000000..efc43f45893c --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/DelayedWETH.json @@ -0,0 +1,65 @@ +[ + { + "bytes": "1", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "uint8" + }, + { + "bytes": "1", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "bool" + }, + { + "bytes": "1600", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "uint256[50]" + }, + { + "bytes": "20", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "address" + }, + { + "bytes": "1568", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "uint256[49]" + }, + { + "bytes": "32", + "label": "balanceOf", + "offset": 0, + "slot": "101", + "type": "mapping(address => uint256)" + }, + { + "bytes": "32", + "label": "allowance", + "offset": 0, + "slot": "102", + "type": "mapping(address => mapping(address => uint256))" + }, + { + "bytes": "32", + "label": "withdrawals", + "offset": 0, + "slot": "103", + "type": "mapping(address => mapping(address => struct IDelayedWETH.WithdrawalRequest))" + }, + { + "bytes": "20", + "label": "config", + "offset": 0, + "slot": "104", + "type": "contract SuperchainConfig" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/FaultDisputeGame.json b/packages/contracts-bedrock/snapshots/storageLayout/FaultDisputeGame.json index b3be0a518e5a..67383f2a1c48 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/FaultDisputeGame.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/FaultDisputeGame.json @@ -20,53 +20,53 @@ "slot": "0", "type": "enum GameStatus" }, - { - "bytes": "32", - "label": "l1Head", - "offset": 0, - "slot": "1", - "type": "Hash" - }, { "bytes": "32", "label": "claimData", "offset": 0, - "slot": "2", + "slot": "1", "type": "struct IFaultDisputeGame.ClaimData[]" }, { "bytes": "32", "label": "credit", "offset": 0, - "slot": "3", + "slot": "2", "type": "mapping(address => uint256)" }, { "bytes": "32", "label": "claims", "offset": 0, - "slot": "4", + "slot": "3", "type": "mapping(ClaimHash => bool)" }, { "bytes": "32", "label": "subgames", "offset": 0, - "slot": "5", + "slot": "4", "type": "mapping(uint256 => uint256[])" }, { "bytes": "1", "label": "subgameAtRootResolved", "offset": 0, - "slot": "6", + "slot": "5", "type": "bool" }, { "bytes": "1", "label": "initialized", "offset": 1, - "slot": "6", + "slot": "5", "type": "bool" + }, + { + "bytes": "64", + "label": "startingOutputRoot", + "offset": 0, + "slot": "6", + "type": "struct OutputRoot" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json new file mode 100644 index 000000000000..c18c6eb5cc2b --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json @@ -0,0 +1,114 @@ +[ + { + "bytes": "1", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "uint8" + }, + { + "bytes": "1", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "bool" + }, + { + "bytes": "32", + "label": "params", + "offset": 0, + "slot": "1", + "type": "struct ResourceMetering.ResourceParams" + }, + { + "bytes": "1536", + "label": "__gap", + "offset": 0, + "slot": "2", + "type": "uint256[48]" + }, + { + "bytes": "20", + "label": "l2Sender", + "offset": 0, + "slot": "50", + "type": "address" + }, + { + "bytes": "32", + "label": "finalizedWithdrawals", + "offset": 0, + "slot": "51", + "type": "mapping(bytes32 => bool)" + }, + { + "bytes": "32", + "label": "spacer_52_0_32", + "offset": 0, + "slot": "52", + "type": "bytes32" + }, + { + "bytes": "1", + "label": "spacer_53_0_1", + "offset": 0, + "slot": "53", + "type": "bool" + }, + { + "bytes": "20", + "label": "superchainConfig", + "offset": 1, + "slot": "53", + "type": "contract SuperchainConfig" + }, + { + "bytes": "20", + "label": "spacer_54_0_20", + "offset": 0, + "slot": "54", + "type": "address" + }, + { + "bytes": "20", + "label": "systemConfig", + "offset": 0, + "slot": "55", + "type": "contract SystemConfig" + }, + { + "bytes": "20", + "label": "disputeGameFactory", + "offset": 0, + "slot": "56", + "type": "contract DisputeGameFactory" + }, + { + "bytes": "32", + "label": "provenWithdrawals", + "offset": 0, + "slot": "57", + "type": "mapping(bytes32 => struct OptimismPortal2.ProvenWithdrawal)" + }, + { + "bytes": "32", + "label": "disputeGameBlacklist", + "offset": 0, + "slot": "58", + "type": "mapping(contract IDisputeGame => bool)" + }, + { + "bytes": "4", + "label": "respectedGameType", + "offset": 0, + "slot": "59", + "type": "GameType" + }, + { + "bytes": "8", + "label": "respectedGameTypeUpdatedAt", + "offset": 4, + "slot": "59", + "type": "uint64" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/PermissionedDisputeGame.json b/packages/contracts-bedrock/snapshots/storageLayout/PermissionedDisputeGame.json new file mode 100644 index 000000000000..67383f2a1c48 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/PermissionedDisputeGame.json @@ -0,0 +1,72 @@ +[ + { + "bytes": "8", + "label": "createdAt", + "offset": 0, + "slot": "0", + "type": "Timestamp" + }, + { + "bytes": "8", + "label": "resolvedAt", + "offset": 8, + "slot": "0", + "type": "Timestamp" + }, + { + "bytes": "1", + "label": "status", + "offset": 16, + "slot": "0", + "type": "enum GameStatus" + }, + { + "bytes": "32", + "label": "claimData", + "offset": 0, + "slot": "1", + "type": "struct IFaultDisputeGame.ClaimData[]" + }, + { + "bytes": "32", + "label": "credit", + "offset": 0, + "slot": "2", + "type": "mapping(address => uint256)" + }, + { + "bytes": "32", + "label": "claims", + "offset": 0, + "slot": "3", + "type": "mapping(ClaimHash => bool)" + }, + { + "bytes": "32", + "label": "subgames", + "offset": 0, + "slot": "4", + "type": "mapping(uint256 => uint256[])" + }, + { + "bytes": "1", + "label": "subgameAtRootResolved", + "offset": 0, + "slot": "5", + "type": "bool" + }, + { + "bytes": "1", + "label": "initialized", + "offset": 1, + "slot": "5", + "type": "bool" + }, + { + "bytes": "64", + "label": "startingOutputRoot", + "offset": 0, + "slot": "6", + "type": "struct OutputRoot" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/PreimageOracle.json b/packages/contracts-bedrock/snapshots/storageLayout/PreimageOracle.json index 63319ee1d329..fbbea6e3d656 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/PreimageOracle.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/PreimageOracle.json @@ -50,16 +50,23 @@ }, { "bytes": "32", - "label": "proposalParts", + "label": "proposalBonds", "offset": 0, "slot": "22", + "type": "mapping(address => mapping(uint256 => uint256))" + }, + { + "bytes": "32", + "label": "proposalParts", + "offset": 0, + "slot": "23", "type": "mapping(address => mapping(uint256 => bytes32))" }, { "bytes": "32", "label": "proposalBlocks", "offset": 0, - "slot": "23", + "slot": "24", "type": "mapping(address => mapping(uint256 => uint64[]))" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/WETH98.json b/packages/contracts-bedrock/snapshots/storageLayout/WETH98.json new file mode 100644 index 000000000000..ac5f38a75a04 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/WETH98.json @@ -0,0 +1,16 @@ +[ + { + "bytes": "32", + "label": "balanceOf", + "offset": 0, + "slot": "0", + "type": "mapping(address => uint256)" + }, + { + "bytes": "32", + "label": "allowance", + "offset": 0, + "slot": "1", + "type": "mapping(address => mapping(address => uint256))" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/src/L1/DataAvailabilityChallenge.sol b/packages/contracts-bedrock/src/L1/DataAvailabilityChallenge.sol new file mode 100644 index 000000000000..84ba91b8fa98 --- /dev/null +++ b/packages/contracts-bedrock/src/L1/DataAvailabilityChallenge.sol @@ -0,0 +1,445 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { ISemver } from "src/universal/ISemver.sol"; +import { SafeCall } from "src/libraries/SafeCall.sol"; + +/// @dev An enum representing the status of a DA challenge. +enum ChallengeStatus { + Uninitialized, + Active, + Resolved, + Expired +} + +/// @dev An enum representing known commitment types. +enum CommitmentType { + Keccak256 +} + +/// @dev A struct representing a single DA challenge. +/// @custom:field status The status of the challenge. +/// @custom:field challenger The address that initiated the challenge. +/// @custom:field startBlock The block number at which the challenge was initiated. +struct Challenge { + address challenger; + uint256 lockedBond; + uint256 startBlock; + uint256 resolvedBlock; +} + +/// @title DataAvailabilityChallenge +/// @notice This contract enables data availability of a data commitment at a given block number to be challenged. +/// To challenge a commitment, the challenger must first post a bond (bondSize). +/// Challenging a commitment is only possible within a certain block interval (challengeWindow) after the +/// commitment was made. +/// If the challenge is not resolved within a certain block interval (resolveWindow), the challenge can be +/// expired. +/// If a challenge is expired, the challenger's bond is unlocked and the challenged commitment is added to the +/// chain of expired challenges. +contract DataAvailabilityChallenge is OwnableUpgradeable, ISemver { + /// @notice Error for when the provided resolver refund percentage exceeds 100%. + error InvalidResolverRefundPercentage(uint256 invalidResolverRefundPercentage); + + /// @notice Error for when the challenger's bond is too low. + error BondTooLow(uint256 balance, uint256 required); + + /// @notice Error for when attempting to challenge a commitment that already has a challenge. + error ChallengeExists(); + + /// @notice Error for when attempting to resolve a challenge that is not active. + error ChallengeNotActive(); + + /// @notice Error for when attempting to unlock a bond from a challenge that is not expired. + error ChallengeNotExpired(); + + /// @notice Error for when attempting to challenge a commitment that is not in the challenge window. + error ChallengeWindowNotOpen(); + + /// @notice Error for when the provided input data doesn't match the commitment. + error InvalidInputData(bytes providedDataCommitment, bytes expectedCommitment); + + /// @notice Error for when the call to withdraw a bond failed. + error WithdrawalFailed(); + + /// @notice Error for when a the type of a given commitment is unknown + error UnknownCommitmentType(uint8 commitmentType); + + /// @notice Error for when the commitment length does not match the commitment type + error InvalidCommitmentLength(uint8 commitmentType, uint256 expectedLength, uint256 actualLength); + + /// @notice An event that is emitted when the status of a challenge changes. + /// @param challengedCommitment The commitment that is being challenged. + /// @param challengedBlockNumber The block number at which the commitment was made. + /// @param status The new status of the challenge. + event ChallengeStatusChanged( + uint256 indexed challengedBlockNumber, bytes challengedCommitment, ChallengeStatus status + ); + + /// @notice An event that is emitted when the bond size required to initiate a challenge changes. + event RequiredBondSizeChanged(uint256 challengeWindow); + + /// @notice An event that is emitted when the percentage of the resolving cost to be refunded to the resolver + /// changes. + event ResolverRefundPercentageChanged(uint256 resolverRefundPercentage); + + /// @notice An event that is emitted when a user's bond balance changes. + event BalanceChanged(address account, uint256 balance); + + /// @notice Semantic version. + /// @custom:semver 1.0.0 + string public constant version = "1.0.0"; + + /// @notice The fixed cost of resolving a challenge. + /// @dev The value is estimated by measuring the cost of resolving with `bytes(0)` + uint256 public constant fixedResolutionCost = 72925; + + /// @notice The variable cost of resolving a callenge per byte scaled by the variableResolutionCostPrecision. + /// @dev upper limit; The value is estimated by measuring the cost of resolving with variable size data where each + /// byte is non-zero. + uint256 public constant variableResolutionCost = 16640; + + /// @dev The precision of the variable resolution cost. + uint256 public constant variableResolutionCostPrecision = 1000; + + /// @notice The block interval during which a commitment can be challenged. + uint256 public challengeWindow; + + /// @notice The block interval during which a challenge can be resolved. + uint256 public resolveWindow; + + /// @notice The amount required to post a challenge. + uint256 public bondSize; + + /// @notice The percentage of the resolving cost to be refunded to the resolver. + /// @dev There are no decimals, ie a value of 50 corresponds to 50%. + uint256 public resolverRefundPercentage; + + /// @notice A mapping from addresses to their bond balance in the contract. + mapping(address => uint256) public balances; + + /// @notice A mapping from challenged block numbers to challenged commitments to challenges. + mapping(uint256 => mapping(bytes => Challenge)) internal challenges; + + /// @notice Constructs the DataAvailabilityChallenge contract. Cannot set + /// the owner to `address(0)` due to the Ownable contract's + /// implementation, so set it to `address(0xdEaD)`. + constructor() OwnableUpgradeable() { + initialize({ + _owner: address(0xdEaD), + _challengeWindow: 0, + _resolveWindow: 0, + _bondSize: 0, + _resolverRefundPercentage: 0 + }); + } + + /// @notice Initializes the contract. + /// @param _owner The owner of the contract. + /// @param _challengeWindow The block interval during which a commitment can be challenged. + /// @param _resolveWindow The block interval during which a challenge can be resolved. + /// @param _bondSize The amount required to post a challenge. + function initialize( + address _owner, + uint256 _challengeWindow, + uint256 _resolveWindow, + uint256 _bondSize, + uint256 _resolverRefundPercentage + ) + public + initializer + { + __Ownable_init(); + challengeWindow = _challengeWindow; + resolveWindow = _resolveWindow; + setBondSize(_bondSize); + setResolverRefundPercentage(_resolverRefundPercentage); + _transferOwnership(_owner); + } + + /// @notice Sets the bond size. + /// @param _bondSize The amount required to post a challenge. + function setBondSize(uint256 _bondSize) public onlyOwner { + bondSize = _bondSize; + emit RequiredBondSizeChanged(_bondSize); + } + + /// @notice Sets the percentage of the resolving cost to be refunded to the resolver. + /// @dev The function reverts if the provided percentage is above 100, since the refund logic + /// assumes a value smaller or equal to 100%. + /// @param _resolverRefundPercentage The percentage of the resolving cost to be refunded to the resolver. + function setResolverRefundPercentage(uint256 _resolverRefundPercentage) public onlyOwner { + if (_resolverRefundPercentage > 100) { + revert InvalidResolverRefundPercentage(_resolverRefundPercentage); + } + resolverRefundPercentage = _resolverRefundPercentage; + } + + /// @notice Post a bond as prerequisite for challenging a commitment. + receive() external payable { + deposit(); + } + + /// @notice Post a bond as prerequisite for challenging a commitment. + function deposit() public payable { + balances[msg.sender] += msg.value; + emit BalanceChanged(msg.sender, balances[msg.sender]); + } + + /// @notice Withdraw a user's unlocked bond. + function withdraw() external { + // get caller's balance + uint256 balance = balances[msg.sender]; + + // set caller's balance to 0 + balances[msg.sender] = 0; + emit BalanceChanged(msg.sender, 0); + + // send caller's balance to caller + bool success = SafeCall.send(msg.sender, gasleft(), balance); + if (!success) { + revert WithdrawalFailed(); + } + } + + /// @notice Checks if the current block is within the challenge window for a given challenged block number. + /// @param challengedBlockNumber The block number at which the commitment was made. + /// @return True if the current block is within the challenge window, false otherwise. + function _isInChallengeWindow(uint256 challengedBlockNumber) internal view returns (bool) { + return (block.number >= challengedBlockNumber && block.number <= challengedBlockNumber + challengeWindow); + } + + /// @notice Checks if the current block is within the resolve window for a given challenge start block number. + /// @param challengeStartBlockNumber The block number at which the challenge was initiated. + /// @return True if the current block is within the resolve window, false otherwise. + function _isInResolveWindow(uint256 challengeStartBlockNumber) internal view returns (bool) { + return block.number <= challengeStartBlockNumber + resolveWindow; + } + + /// @notice Returns a challenge for the given block number and commitment. + /// @dev Unlike with a public `challenges` mapping, we can return a Challenge struct instead of tuple. + /// @param challengedBlockNumber The block number at which the commitment was made. + /// @param challengedCommitment The commitment that is being challenged. + /// @return The challenge struct. + function getChallenge( + uint256 challengedBlockNumber, + bytes calldata challengedCommitment + ) + public + view + returns (Challenge memory) + { + return challenges[challengedBlockNumber][challengedCommitment]; + } + + /// @notice Returns the status of a challenge for a given challenged block number and challenged commitment. + /// @param challengedBlockNumber The block number at which the commitment was made. + /// @param challengedCommitment The commitment that is being challenged. + /// @return The status of the challenge. + function getChallengeStatus( + uint256 challengedBlockNumber, + bytes calldata challengedCommitment + ) + public + view + returns (ChallengeStatus) + { + Challenge memory _challenge = challenges[challengedBlockNumber][challengedCommitment]; + // if the address is 0, the challenge is uninitialized + if (_challenge.challenger == address(0)) return ChallengeStatus.Uninitialized; + + // if the challenge has a resolved block, it is resolved + if (_challenge.resolvedBlock != 0) return ChallengeStatus.Resolved; + + // if the challenge's start block is in the resolve window, it is active + if (_isInResolveWindow(_challenge.startBlock)) return ChallengeStatus.Active; + + // if the challenge's start block is not in the resolve window, it is expired + return ChallengeStatus.Expired; + } + + /// @notice Extract the commitment type from a given commitment. + /// @dev The commitment type is located in the first byte of the commitment. + /// @param commitment The commitment from which to extract the commitment type. + /// @return The commitment type of the given commitment. + function _getCommitmentType(bytes calldata commitment) internal pure returns (uint8) { + return uint8(bytes1(commitment)); + } + + /// @notice Validate that a given commitment has a known type and the expected length for this type. + /// @dev The type of a commitment is stored in its first byte. + /// The function reverts with `UnknownCommitmentType` if the type is not known and + /// with `InvalidCommitmentLength` if the commitment has an unexpected length. + /// @param commitment The commitment for which to check the type. + function validateCommitment(bytes calldata commitment) public pure { + uint8 commitmentType = _getCommitmentType(commitment); + if (commitmentType == uint8(CommitmentType.Keccak256)) { + if (commitment.length != 33) { + revert InvalidCommitmentLength(uint8(CommitmentType.Keccak256), 33, commitment.length); + } + return; + } + + revert UnknownCommitmentType(commitmentType); + } + + /// @notice Challenge a commitment at a given block number. + /// @dev The block number parameter is necessary for the contract to verify the challenge window, + /// since the contract cannot access the block number of the commitment. + /// The function reverts if the commitment type (first byte) is unknown, + /// if the caller does not have a bond or if the challenge already exists. + /// @param challengedBlockNumber The block number at which the commitment was made. + /// @param challengedCommitment The commitment that is being challenged. + function challenge(uint256 challengedBlockNumber, bytes calldata challengedCommitment) external payable { + // require the commitment type to be known + validateCommitment(challengedCommitment); + + // deposit value sent with the transaction as bond + deposit(); + + // require the caller to have a bond + if (balances[msg.sender] < bondSize) { + revert BondTooLow(balances[msg.sender], bondSize); + } + + // require the challenge status to be uninitialized + if (getChallengeStatus(challengedBlockNumber, challengedCommitment) != ChallengeStatus.Uninitialized) { + revert ChallengeExists(); + } + + // require the current block to be in the challenge window + if (!_isInChallengeWindow(challengedBlockNumber)) { + revert ChallengeWindowNotOpen(); + } + + // reduce the caller's balance + balances[msg.sender] -= bondSize; + + // store the challenger's address, bond size, and start block of the challenge + challenges[challengedBlockNumber][challengedCommitment] = + Challenge({ challenger: msg.sender, lockedBond: bondSize, startBlock: block.number, resolvedBlock: 0 }); + + // emit an event to notify that the challenge status is now active + emit ChallengeStatusChanged(challengedBlockNumber, challengedCommitment, ChallengeStatus.Active); + } + + /// @notice Resolve a challenge by providing the data corresponding to the challenged commitment. + /// @dev The function computes a commitment from the provided resolveData and verifies that it matches the + /// challenged commitment. + /// It reverts if the commitment type is unknown, if the data doesn't match the commitment, + /// if the challenge is not active or if the resolve window is not open. + /// @param challengedBlockNumber The block number at which the commitment was made. + /// @param challengedCommitment The challenged commitment that is being resolved. + /// @param resolveData The pre-image data corresponding to the challenged commitment. + function resolve( + uint256 challengedBlockNumber, + bytes calldata challengedCommitment, + bytes calldata resolveData + ) + external + { + // require the commitment type to be known + validateCommitment(challengedCommitment); + + // require the challenge to be active (started, not resolved, and resolve window still open) + if (getChallengeStatus(challengedBlockNumber, challengedCommitment) != ChallengeStatus.Active) { + revert ChallengeNotActive(); + } + + // compute the commitment corresponding to the given resolveData + uint8 commitmentType = _getCommitmentType(challengedCommitment); + bytes memory computedCommitment; + if (commitmentType == uint8(CommitmentType.Keccak256)) { + computedCommitment = computeCommitmentKeccak256(resolveData); + } + + // require the provided input data to correspond to the challenged commitment + if (keccak256(computedCommitment) != keccak256(challengedCommitment)) { + revert InvalidInputData(computedCommitment, challengedCommitment); + } + + // store the block number at which the challenge was resolved + Challenge storage activeChallenge = challenges[challengedBlockNumber][challengedCommitment]; + activeChallenge.resolvedBlock = block.number; + + // emit an event to notify that the challenge status is now resolved + emit ChallengeStatusChanged(challengedBlockNumber, challengedCommitment, ChallengeStatus.Resolved); + + // distribute the bond among challenger, resolver and address(0) + _distributeBond(activeChallenge, resolveData.length, msg.sender); + } + + /// @notice Distribute the bond of a resolved challenge among the resolver, challenger and address(0). + /// The challenger is refunded the bond amount exceeding the resolution cost. + /// The resolver is refunded a percentage of the resolution cost based on the `resolverRefundPercentage` + /// state variable. + /// The remaining bond is burned by sending it to address(0). + /// @dev The resolution cost is approximated based on a fixed cost and variable cost depending on the size of the + /// pre-image. + /// The real resolution cost might vary, because calldata is priced differently for zero and non-zero bytes. + /// Computing the exact cost adds too much gas overhead to be worth the tradeoff. + /// @param resolvedChallenge The resolved challenge in storage. + /// @param preImageLength The size of the pre-image used to resolve the challenge. + /// @param resolver The address of the resolver. + function _distributeBond(Challenge storage resolvedChallenge, uint256 preImageLength, address resolver) internal { + uint256 lockedBond = resolvedChallenge.lockedBond; + address challenger = resolvedChallenge.challenger; + + // approximate the cost of resolving a challenge with the provided pre-image size + uint256 resolutionCost = ( + fixedResolutionCost + preImageLength * variableResolutionCost / variableResolutionCostPrecision + ) * block.basefee; + + // refund bond exceeding the resolution cost to the challenger + if (lockedBond > resolutionCost) { + balances[challenger] += lockedBond - resolutionCost; + lockedBond = resolutionCost; + emit BalanceChanged(challenger, balances[challenger]); + } + + // refund a percentage of the resolution cost to the resolver (but not more than the locked bond) + uint256 resolverRefund = resolutionCost * resolverRefundPercentage / 100; + if (resolverRefund > lockedBond) { + resolverRefund = lockedBond; + } + if (resolverRefund > 0) { + balances[resolver] += resolverRefund; + lockedBond -= resolverRefund; + emit BalanceChanged(resolver, balances[resolver]); + } + + // burn the remaining bond + if (lockedBond > 0) { + payable(address(0)).transfer(lockedBond); + } + resolvedChallenge.lockedBond = 0; + } + + /// @notice Unlock the bond associated wth an expired challenge. + /// @dev The function reverts if the challenge is not expired. + /// If the expiration is successful, the challenger's bond is unlocked. + /// @param challengedBlockNumber The block number at which the commitment was made. + /// @param challengedCommitment The commitment that is being challenged. + function unlockBond(uint256 challengedBlockNumber, bytes calldata challengedCommitment) external { + // require the challenge to be active (started, not resolved, and in the resolve window) + if (getChallengeStatus(challengedBlockNumber, challengedCommitment) != ChallengeStatus.Expired) { + revert ChallengeNotExpired(); + } + + // Unlock the bond associated with the challenge + Challenge storage expiredChallenge = challenges[challengedBlockNumber][challengedCommitment]; + balances[expiredChallenge.challenger] += expiredChallenge.lockedBond; + expiredChallenge.lockedBond = 0; + + // Emit balance update event + emit BalanceChanged(expiredChallenge.challenger, balances[expiredChallenge.challenger]); + } +} + +/// @notice Compute the expected commitment for a given blob of data. +/// @param data The blob of data to compute a commitment for. +/// @return The commitment for the given blob of data. +function computeCommitmentKeccak256(bytes memory data) pure returns (bytes memory) { + return bytes.concat(bytes1(uint8(CommitmentType.Keccak256)), keccak256(data)); +} diff --git a/packages/contracts-bedrock/src/L1/DelayedVetoable.sol b/packages/contracts-bedrock/src/L1/DelayedVetoable.sol index 8a1f08cb0ef3..abb40b9ce90f 100644 --- a/packages/contracts-bedrock/src/L1/DelayedVetoable.sol +++ b/packages/contracts-bedrock/src/L1/DelayedVetoable.sol @@ -11,15 +11,9 @@ import { ISemver } from "src/universal/ISemver.sol"; /// of the queuedAt(bytes32) function. This is because of input validation checks which solidity performs at /// runtime on functions which take an argument. contract DelayedVetoable is ISemver { - /// @notice Error for when the delay has already been set. - error AlreadyDelayed(); - /// @notice Error for when attempting to forward too early. error ForwardingEarly(); - /// @notice Error for the target is not set. - error TargetUnitialized(); - /// @notice Error for unauthorized calls. error Unauthorized(address expected, address actual); @@ -170,7 +164,7 @@ contract DelayedVetoable is ISemver { revert Unauthorized(INITIATOR, msg.sender); } - if (_queuedAt[callHash] + _delay < block.timestamp) { + if (_queuedAt[callHash] + _delay > block.timestamp) { // Not enough time has passed, so we'll revert. revert ForwardingEarly(); } diff --git a/packages/contracts-bedrock/src/L1/L2OutputOracle.sol b/packages/contracts-bedrock/src/L1/L2OutputOracle.sol index 105fbb99d1f7..fe2c7dd7c8ef 100644 --- a/packages/contracts-bedrock/src/L1/L2OutputOracle.sol +++ b/packages/contracts-bedrock/src/L1/L2OutputOracle.sol @@ -154,7 +154,6 @@ contract L2OutputOracle is Initializable, ISemver { /// the given output index. Only the challenger address can delete outputs. /// @param _l2OutputIndex Index of the first L2 output to be deleted. /// All outputs after this output will also be deleted. - // solhint-disable-next-line ordering function deleteL2Outputs(uint256 _l2OutputIndex) external { require(msg.sender == challenger, "L2OutputOracle: only the challenger address can delete outputs"); diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal.sol b/packages/contracts-bedrock/src/L1/OptimismPortal.sol index ec5d1348308e..30e6bd471dd6 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortal.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortal.sol @@ -177,7 +177,6 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver { /// funds be deposited to their address on L2. This is intended as a convenience /// function for EOAs. Contracts should call the depositTransaction() function directly /// otherwise any deposited funds will be lost due to address aliasing. - // solhint-disable-next-line ordering receive() external payable { depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes("")); } diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol new file mode 100644 index 000000000000..6604c8d23087 --- /dev/null +++ b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol @@ -0,0 +1,490 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +import { SafeCall } from "src/libraries/SafeCall.sol"; +import { DisputeGameFactory, IDisputeGame } from "src/dispute/DisputeGameFactory.sol"; +import { SystemConfig } from "src/L1/SystemConfig.sol"; +import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { Constants } from "src/libraries/Constants.sol"; +import { Types } from "src/libraries/Types.sol"; +import { Hashing } from "src/libraries/Hashing.sol"; +import { SecureMerkleTrie } from "src/libraries/trie/SecureMerkleTrie.sol"; +import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; +import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +import { ISemver } from "src/universal/ISemver.sol"; +import { Constants } from "src/libraries/Constants.sol"; + +import "src/libraries/DisputeTypes.sol"; + +/// @custom:proxied +/// @title OptimismPortal2 +/// @notice The OptimismPortal is a low-level contract responsible for passing messages between L1 +/// and L2. Messages sent directly to the OptimismPortal have no form of replayability. +/// Users are encouraged to use the L1CrossDomainMessenger for a higher-level interface. +contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { + /// @notice Represents a proven withdrawal. + /// @custom:field disputeGameProxy The address of the dispute game proxy that the withdrawal was proven against. + /// @custom:field timestamp Timestamp at whcih the withdrawal was proven. + struct ProvenWithdrawal { + IDisputeGame disputeGameProxy; + uint64 timestamp; + } + + /// @notice The delay between when a withdrawal transaction is proven and when it may be finalized. + uint256 internal immutable PROOF_MATURITY_DELAY_SECONDS; + + /// @notice The delay between when a dispute game is resolved and when a withdrawal proven against it may be + /// finalized. + uint256 internal immutable DISPUTE_GAME_FINALITY_DELAY_SECONDS; + + /// @notice Version of the deposit event. + uint256 internal constant DEPOSIT_VERSION = 0; + + /// @notice The L2 gas limit set when eth is deposited using the receive() function. + uint64 internal constant RECEIVE_DEFAULT_GAS_LIMIT = 100_000; + + /// @notice Address of the L2 account which initiated a withdrawal in this transaction. + /// If the of this variable is the default L2 sender address, then we are NOT inside of + /// a call to finalizeWithdrawalTransaction. + address public l2Sender; + + /// @notice A list of withdrawal hashes which have been successfully finalized. + mapping(bytes32 => bool) public finalizedWithdrawals; + + /// @custom:legacy + /// @custom:spacer provenWithdrawals + /// @notice Spacer taking up the legacy `provenWithdrawals` mapping slot. + bytes32 private spacer_52_0_32; + + /// @custom:legacy + /// @custom:spacer paused + /// @notice Spacer for backwards compatibility. + bool private spacer_53_0_1; + + /// @notice Contract of the Superchain Config. + SuperchainConfig public superchainConfig; + + /// @custom:legacy + /// @custom:spacer l2Oracle + /// @notice Spacer taking up the legacy `l2Oracle` address slot. + address private spacer_54_0_20; + + /// @notice Contract of the SystemConfig. + /// @custom:network-specific + SystemConfig public systemConfig; + + /// @notice Address of the DisputeGameFactory. + /// @custom:network-specific + DisputeGameFactory public disputeGameFactory; + + /// @notice A mapping of withdrawal hashes to `ProvenWithdrawal` data. + mapping(bytes32 => ProvenWithdrawal) public provenWithdrawals; + + /// @notice A mapping of dispute game addresses to whether or not they are blacklisted. + mapping(IDisputeGame => bool) public disputeGameBlacklist; + + /// @notice The game type that the OptimismPortal consults for output proposals. + GameType public respectedGameType; + + /// @notice The timestamp at which the respected game type was last updated. + uint64 public respectedGameTypeUpdatedAt; + + /// @notice Emitted when a transaction is deposited from L1 to L2. + /// The parameters of this event are read by the rollup node and used to derive deposit + /// transactions on L2. + /// @param from Address that triggered the deposit transaction. + /// @param to Address that the deposit transaction is directed to. + /// @param version Version of this deposit transaction event. + /// @param opaqueData ABI encoded deposit data to be parsed off-chain. + event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); + + /// @notice Emitted when a withdrawal transaction is proven. + /// @param withdrawalHash Hash of the withdrawal transaction. + /// @param from Address that triggered the withdrawal transaction. + /// @param to Address that the withdrawal transaction is directed to. + event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to); + + /// @notice Emitted when a withdrawal transaction is finalized. + /// @param withdrawalHash Hash of the withdrawal transaction. + /// @param success Whether the withdrawal transaction was successful. + event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); + + /// @notice Reverts when paused. + modifier whenNotPaused() { + require(!paused(), "OptimismPortal: paused"); + _; + } + + /// @notice Semantic version. + /// @custom:semver 3.3.0 + string public constant version = "3.3.0"; + + /// @notice Constructs the OptimismPortal contract. + constructor( + uint256 _proofMaturityDelaySeconds, + uint256 _disputeGameFinalityDelaySeconds, + GameType _initialRespectedGameType + ) { + PROOF_MATURITY_DELAY_SECONDS = _proofMaturityDelaySeconds; + DISPUTE_GAME_FINALITY_DELAY_SECONDS = _disputeGameFinalityDelaySeconds; + respectedGameType = _initialRespectedGameType; + + initialize({ + _disputeGameFactory: DisputeGameFactory(address(0)), + _systemConfig: SystemConfig(address(0)), + _superchainConfig: SuperchainConfig(address(0)) + }); + } + + /// @notice Initializer. + /// @param _disputeGameFactory Contract of the DisputeGameFactory. + /// @param _systemConfig Contract of the SystemConfig. + /// @param _superchainConfig Contract of the SuperchainConfig. + function initialize( + DisputeGameFactory _disputeGameFactory, + SystemConfig _systemConfig, + SuperchainConfig _superchainConfig + ) + public + initializer + { + disputeGameFactory = _disputeGameFactory; + systemConfig = _systemConfig; + superchainConfig = _superchainConfig; + if (l2Sender == address(0)) { + l2Sender = Constants.DEFAULT_L2_SENDER; + } + __ResourceMetering_init(); + } + + /// @notice Getter function for the contract of the SystemConfig on this chain. + /// Public getter is legacy and will be removed in the future. Use `systemConfig()` instead. + /// @return Contract of the SystemConfig on this chain. + /// @custom:legacy + function SYSTEM_CONFIG() external view returns (SystemConfig) { + return systemConfig; + } + + /// @notice Getter function for the address of the guardian. + /// Public getter is legacy and will be removed in the future. Use `SuperchainConfig.guardian()` instead. + /// @return Address of the guardian. + /// @custom:legacy + function GUARDIAN() external view returns (address) { + return guardian(); + } + + /// @notice Getter function for the address of the guardian. + /// Public getter is legacy and will be removed in the future. Use `SuperchainConfig.guardian()` instead. + /// @return Address of the guardian. + /// @custom:legacy + function guardian() public view returns (address) { + return superchainConfig.guardian(); + } + + /// @notice Getter for the current paused status. + function paused() public view returns (bool) { + return superchainConfig.paused(); + } + + /// @notice Getter for the proof maturity delay. + function proofMaturityDelaySeconds() public view returns (uint256) { + return PROOF_MATURITY_DELAY_SECONDS; + } + + /// @notice Getter for the dispute game finality delay. + function disputeGameFinalityDelaySeconds() public view returns (uint256) { + return DISPUTE_GAME_FINALITY_DELAY_SECONDS; + } + + /// @notice Computes the minimum gas limit for a deposit. + /// The minimum gas limit linearly increases based on the size of the calldata. + /// This is to prevent users from creating L2 resource usage without paying for it. + /// This function can be used when interacting with the portal to ensure forwards + /// compatibility. + /// @param _byteCount Number of bytes in the calldata. + /// @return The minimum gas limit for a deposit. + function minimumGasLimit(uint64 _byteCount) public pure returns (uint64) { + return _byteCount * 16 + 21000; + } + + /// @notice Accepts value so that users can send ETH directly to this contract and have the + /// funds be deposited to their address on L2. This is intended as a convenience + /// function for EOAs. Contracts should call the depositTransaction() function directly + /// otherwise any deposited funds will be lost due to address aliasing. + receive() external payable { + depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes("")); + } + + /// @notice Accepts ETH value without triggering a deposit to L2. + /// This function mainly exists for the sake of the migration between the legacy + /// Optimism system and Bedrock. + function donateETH() external payable { + // Intentionally empty. + } + + /// @notice Getter for the resource config. + /// Used internally by the ResourceMetering contract. + /// The SystemConfig is the source of truth for the resource config. + /// @return ResourceMetering ResourceConfig + function _resourceConfig() internal view override returns (ResourceMetering.ResourceConfig memory) { + return systemConfig.resourceConfig(); + } + + /// @notice Proves a withdrawal transaction. + /// @param _tx Withdrawal transaction to finalize. + /// @param _disputeGameIndex Index of the dispute game to prove the withdrawal against. + /// @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root. + /// @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract. + function proveWithdrawalTransaction( + Types.WithdrawalTransaction memory _tx, + uint256 _disputeGameIndex, + Types.OutputRootProof calldata _outputRootProof, + bytes[] calldata _withdrawalProof + ) + external + whenNotPaused + { + // Prevent users from creating a deposit transaction where this address is the message + // sender on L2. Because this is checked here, we do not need to check again in + // `finalizeWithdrawalTransaction`. + require(_tx.target != address(this), "OptimismPortal: you cannot send messages to the portal contract"); + + // Fetch the dispute game proxy from the `DisputeGameFactory` contract. + (GameType gameType,, IDisputeGame gameProxy) = disputeGameFactory.gameAtIndex(_disputeGameIndex); + Claim outputRoot = gameProxy.rootClaim(); + + // The game type of the dispute game must be the respected game type. + require(gameType.raw() == respectedGameType.raw(), "OptimismPortal: invalid game type"); + + // Verify that the output root can be generated with the elements in the proof. + require( + outputRoot.raw() == Hashing.hashOutputRootProof(_outputRootProof), + "OptimismPortal: invalid output root proof" + ); + + // Load the ProvenWithdrawal into memory, using the withdrawal hash as a unique identifier. + bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx); + ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash]; + + // We generally want to prevent users from proving the same withdrawal multiple times + // because each successive proof will update the timestamp. A malicious user can take + // advantage of this to prevent other users from finalizing their withdrawal. However, + // in the case that an honest user proves their withdrawal against a dispute game that + // resolves against the root claim, or the dispute game is blacklisted, we allow + // re-proving the withdrawal against a new proposal. + IDisputeGame oldGame = provenWithdrawal.disputeGameProxy; + require( + provenWithdrawal.timestamp == 0 || oldGame.status() == GameStatus.CHALLENGER_WINS + || disputeGameBlacklist[oldGame] || oldGame.gameType().raw() != respectedGameType.raw(), + "OptimismPortal: withdrawal hash has already been proven, and the old dispute game is not invalid" + ); + + // Compute the storage slot of the withdrawal hash in the L2ToL1MessagePasser contract. + // Refer to the Solidity documentation for more information on how storage layouts are + // computed for mappings. + bytes32 storageKey = keccak256( + abi.encode( + withdrawalHash, + uint256(0) // The withdrawals mapping is at the first slot in the layout. + ) + ); + + // Verify that the hash of this withdrawal was stored in the L2toL1MessagePasser contract + // on L2. If this is true, under the assumption that the SecureMerkleTrie does not have + // bugs, then we know that this withdrawal was actually triggered on L2 and can therefore + // be relayed on L1. + require( + SecureMerkleTrie.verifyInclusionProof( + abi.encode(storageKey), hex"01", _withdrawalProof, _outputRootProof.messagePasserStorageRoot + ), + "OptimismPortal: invalid withdrawal inclusion proof" + ); + + // Designate the withdrawalHash as proven by storing the `disputeGameProxy` & `timestamp` in the + // `provenWithdrawals` mapping. A `withdrawalHash` can only be proven once unless the dispute game it proved + // against resolves against the favor of the root claim. + provenWithdrawals[withdrawalHash] = + ProvenWithdrawal({ disputeGameProxy: gameProxy, timestamp: uint64(block.timestamp) }); + + // Emit a `WithdrawalProven` event. + emit WithdrawalProven(withdrawalHash, _tx.sender, _tx.target); + } + + /// @notice Finalizes a withdrawal transaction. + /// @param _tx Withdrawal transaction to finalize. + function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external whenNotPaused { + // Make sure that the l2Sender has not yet been set. The l2Sender is set to a value other + // than the default value when a withdrawal transaction is being finalized. This check is + // a defacto reentrancy guard. + require( + l2Sender == Constants.DEFAULT_L2_SENDER, "OptimismPortal: can only trigger one withdrawal per transaction" + ); + + // Compute the withdrawal hash. + bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx); + + // Check that the withdrawal can be finalized. + checkWithdrawal(withdrawalHash); + + // Mark the withdrawal as finalized so it can't be replayed. + finalizedWithdrawals[withdrawalHash] = true; + + // Set the l2Sender so contracts know who triggered this withdrawal on L2. + l2Sender = _tx.sender; + + // Trigger the call to the target contract. We use a custom low level method + // SafeCall.callWithMinGas to ensure two key properties + // 1. Target contracts cannot force this call to run out of gas by returning a very large + // amount of data (and this is OK because we don't care about the returndata here). + // 2. The amount of gas provided to the execution context of the target is at least the + // gas limit specified by the user. If there is not enough gas in the current context + // to accomplish this, `callWithMinGas` will revert. + bool success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, _tx.value, _tx.data); + + // Reset the l2Sender back to the default value. + l2Sender = Constants.DEFAULT_L2_SENDER; + + // All withdrawals are immediately finalized. Replayability can + // be achieved through contracts built on top of this contract + emit WithdrawalFinalized(withdrawalHash, success); + + // Reverting here is useful for determining the exact gas cost to successfully execute the + // sub call to the target contract if the minimum gas limit specified by the user would not + // be sufficient to execute the sub call. + if (!success && tx.origin == Constants.ESTIMATION_ADDRESS) { + revert("OptimismPortal: withdrawal failed"); + } + } + + /// @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in + /// deriving deposit transactions. Note that if a deposit is made by a contract, its + /// address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider + /// using the CrossDomainMessenger contracts for a simpler developer experience. + /// @param _to Target address on L2. + /// @param _value ETH value to send to the recipient. + /// @param _gasLimit Amount of L2 gas to purchase by burning gas on L1. + /// @param _isCreation Whether or not the transaction is a contract creation. + /// @param _data Data to trigger the recipient with. + function depositTransaction( + address _to, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) + public + payable + metered(_gasLimit) + { + // Just to be safe, make sure that people specify address(0) as the target when doing + // contract creations. + if (_isCreation) { + require(_to == address(0), "OptimismPortal: must send to address(0) when creating a contract"); + } + + // Prevent depositing transactions that have too small of a gas limit. Users should pay + // more for more resource usage. + require(_gasLimit >= minimumGasLimit(uint64(_data.length)), "OptimismPortal: gas limit too small"); + + // Prevent the creation of deposit transactions that have too much calldata. This gives an + // upper limit on the size of unsafe blocks over the p2p network. 120kb is chosen to ensure + // that the transaction can fit into the p2p network policy of 128kb even though deposit + // transactions are not gossipped over the p2p network. + require(_data.length <= 120_000, "OptimismPortal: data too large"); + + // Transform the from-address to its alias if the caller is a contract. + address from = msg.sender; + if (msg.sender != tx.origin) { + from = AddressAliasHelper.applyL1ToL2Alias(msg.sender); + } + + // Compute the opaque data that will be emitted as part of the TransactionDeposited event. + // We use opaque data so that we can update the TransactionDeposited event in the future + // without breaking the current interface. + bytes memory opaqueData = abi.encodePacked(msg.value, _value, _gasLimit, _isCreation, _data); + + // Emit a TransactionDeposited event so that the rollup node can derive a deposit + // transaction for this deposit. + emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData); + } + + /// @notice Blacklists a dispute game. Should only be used in the event that a dispute game resolves incorrectly. + /// @param _disputeGame Dispute game to blacklist. + function blacklistDisputeGame(IDisputeGame _disputeGame) external { + require(msg.sender == guardian(), "OptimismPortal: only the guardian can blacklist dispute games"); + disputeGameBlacklist[_disputeGame] = true; + } + + /// @notice Sets the respected game type. Changing this value can alter the security properties of the system, + /// depending on the new game's behavior. + /// @param _gameType The game type to consult for output proposals. + function setRespectedGameType(GameType _gameType) external { + require(msg.sender == guardian(), "OptimismPortal: only the guardian can set the respected game type"); + respectedGameType = _gameType; + respectedGameTypeUpdatedAt = uint64(block.timestamp); + } + + /// @notice Checks if a withdrawal can be finalized. This function will revert if the withdrawal cannot be + /// finalized, and otherwise has no side-effects. + /// @param _withdrawalHash Hash of the withdrawal to check. + function checkWithdrawal(bytes32 _withdrawalHash) public view { + ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[_withdrawalHash]; + IDisputeGame disputeGameProxy = provenWithdrawal.disputeGameProxy; + + // The dispute game must not be blacklisted. + require(!disputeGameBlacklist[disputeGameProxy], "OptimismPortal: dispute game has been blacklisted"); + + // A withdrawal can only be finalized if it has been proven. We know that a withdrawal has + // been proven at least once when its timestamp is non-zero. Unproven withdrawals will have + // a timestamp of zero. + require(provenWithdrawal.timestamp != 0, "OptimismPortal: withdrawal has not been proven yet"); + + uint64 createdAt = disputeGameProxy.createdAt().raw(); + + // As a sanity check, we make sure that the proven withdrawal's timestamp is greater than + // starting timestamp inside the Dispute Game. Not strictly necessary but extra layer of + // safety against weird bugs in the proving step. + require( + provenWithdrawal.timestamp > createdAt, + "OptimismPortal: withdrawal timestamp less than dispute game creation timestamp" + ); + + // A proven withdrawal must wait at least `PROOF_MATURITY_DELAY_SECONDS` before finalizing. + require( + block.timestamp - provenWithdrawal.timestamp > PROOF_MATURITY_DELAY_SECONDS, + "OptimismPortal: proven withdrawal has not matured yet" + ); + + // A proven withdrawal must wait until the dispute game it was proven against has been + // resolved in favor of the root claim (the output proposal). This is to prevent users + // from finalizing withdrawals proven against non-finalized output roots. + require( + disputeGameProxy.status() == GameStatus.DEFENDER_WINS, + "OptimismPortal: output proposal has not been finalized yet" + ); + + // The game type of the dispute game must be the respected game type. This was also checked in + // `proveWithdrawalTransaction`, but we check it again in case the respected game type has changed since + // the withdrawal was proven. + require(disputeGameProxy.gameType().raw() == respectedGameType.raw(), "OptimismPortal: invalid game type"); + + // The game must have been created after `respectedGameTypeUpdatedAt`. This is to prevent users from creating + // invalid disputes against a deployed game type while the off-chain challenge agents are not watching. + require( + createdAt >= respectedGameTypeUpdatedAt, + "OptimismPortal: dispute game created before respected game type was updated" + ); + + // Before a withdrawal can be finalized, the dispute game it was proven against must have been + // resolved for at least `DISPUTE_GAME_FINALITY_DELAY_SECONDS`. This is to allow for manual + // intervention in the event that a dispute game is resolved incorrectly. + require( + block.timestamp - disputeGameProxy.resolvedAt().raw() > DISPUTE_GAME_FINALITY_DELAY_SECONDS, + "OptimismPortal: output proposal in air-gap" + ); + + // Check that this withdrawal has not already been finalized, this is replay protection. + require(!finalizedWithdrawals[_withdrawalHash], "OptimismPortal: withdrawal has already been finalized"); + } +} diff --git a/packages/contracts-bedrock/src/L1/ResourceMetering.sol b/packages/contracts-bedrock/src/L1/ResourceMetering.sol index 3df7b69d02fe..e66cb6b16e22 100644 --- a/packages/contracts-bedrock/src/L1/ResourceMetering.sol +++ b/packages/contracts-bedrock/src/L1/ResourceMetering.sol @@ -153,7 +153,6 @@ abstract contract ResourceMetering is Initializable { /// @notice Sets initial resource parameter values. /// This function must either be called by the initializer function of an upgradeable /// child contract. - // solhint-disable-next-line func-name-mixedcase function __ResourceMetering_init() internal onlyInitializing { if (params.prevBlockNum == 0) { params = ResourceParams({ prevBaseFee: 1 gwei, prevBoughtGas: 0, prevBlockNum: uint64(block.number) }); diff --git a/packages/contracts-bedrock/src/L1/SystemConfig.sol b/packages/contracts-bedrock/src/L1/SystemConfig.sol index b165ded292cb..5e497e22793a 100644 --- a/packages/contracts-bedrock/src/L1/SystemConfig.sol +++ b/packages/contracts-bedrock/src/L1/SystemConfig.sol @@ -201,7 +201,6 @@ contract SystemConfig is OwnableUpgradeable, ISemver { /// Unsafe blocks can be propagated across the p2p network if they are signed by the /// key corresponding to this address. /// @return addr_ Address of the unsafe block signer. - // solhint-disable-next-line ordering function unsafeBlockSigner() public view returns (address addr_) { addr_ = Storage.getAddress(UNSAFE_BLOCK_SIGNER_SLOT); } diff --git a/packages/contracts-bedrock/src/Safe/SafeSigners.sol b/packages/contracts-bedrock/src/Safe/SafeSigners.sol index 32e65913dda5..18c443582eba 100644 --- a/packages/contracts-bedrock/src/Safe/SafeSigners.sol +++ b/packages/contracts-bedrock/src/Safe/SafeSigners.sol @@ -22,7 +22,6 @@ library SafeSigners { pure returns (uint8 v, bytes32 r, bytes32 s) { - // solhint-disable-next-line no-inline-assembly assembly { let signaturePos := mul(0x41, pos) r := mload(add(signatures, add(signaturePos, 0x20))) diff --git a/packages/contracts-bedrock/src/cannon/MIPS.sol b/packages/contracts-bedrock/src/cannon/MIPS.sol index 1202a9a7a203..09be2d34b499 100644 --- a/packages/contracts-bedrock/src/cannon/MIPS.sol +++ b/packages/contracts-bedrock/src/cannon/MIPS.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +import { ISemver } from "src/universal/ISemver.sol"; import { IPreimageOracle } from "./interfaces/IPreimageOracle.sol"; import { PreimageKeyLib } from "./PreimageKeyLib.sol"; @@ -19,7 +20,7 @@ import { PreimageKeyLib } from "./PreimageKeyLib.sol"; /// @dev https://en.wikibooks.org/wiki/MIPS_Assembly/Instruction_Formats /// @dev https://github.com/golang/go/blob/master/src/syscall/zerrors_linux_mips.go /// MIPS linux kernel errors used by Go runtime -contract MIPS { +contract MIPS is ISemver { /// @notice Stores the VM state. /// Total state size: 32 + 32 + 6 * 4 + 1 + 1 + 8 + 32 * 4 = 226 bytes /// If nextPC != pc + 4, then the VM is executing a branch/jump delay slot. @@ -41,16 +42,20 @@ contract MIPS { /// @notice Start of the data segment. uint32 public constant BRK_START = 0x40000000; - uint32 constant FD_STDIN = 0; - uint32 constant FD_STDOUT = 1; - uint32 constant FD_STDERR = 2; - uint32 constant FD_HINT_READ = 3; - uint32 constant FD_HINT_WRITE = 4; - uint32 constant FD_PREIMAGE_READ = 5; - uint32 constant FD_PREIMAGE_WRITE = 6; + /// @notice The semantic version of the MIPS contract. + /// @custom:semver 0.1.0 + string public constant version = "0.1.0"; - uint32 constant EBADF = 0x9; - uint32 constant EINVAL = 0x16; + uint32 internal constant FD_STDIN = 0; + uint32 internal constant FD_STDOUT = 1; + uint32 internal constant FD_STDERR = 2; + uint32 internal constant FD_HINT_READ = 3; + uint32 internal constant FD_HINT_WRITE = 4; + uint32 internal constant FD_PREIMAGE_READ = 5; + uint32 internal constant FD_PREIMAGE_WRITE = 6; + + uint32 internal constant EBADF = 0x9; + uint32 internal constant EINVAL = 0x16; /// @notice The preimage oracle contract. IPreimageOracle internal immutable ORACLE; diff --git a/packages/contracts-bedrock/src/cannon/PreimageOracle.sol b/packages/contracts-bedrock/src/cannon/PreimageOracle.sol index 396ca8a6e844..dfdeaa7fc5b1 100644 --- a/packages/contracts-bedrock/src/cannon/PreimageOracle.sol +++ b/packages/contracts-bedrock/src/cannon/PreimageOracle.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.15; import { IPreimageOracle } from "./interfaces/IPreimageOracle.sol"; +import { ISemver } from "src/universal/ISemver.sol"; import { PreimageKeyLib } from "./PreimageKeyLib.sol"; import { LibKeccak } from "@lib-keccak/LibKeccak.sol"; import "src/cannon/libraries/CannonErrors.sol"; @@ -11,7 +12,7 @@ import "src/cannon/libraries/CannonTypes.sol"; /// @notice A contract for storing permissioned pre-images. /// @custom:attribution Solady /// @custom:attribution Beacon Deposit Contract <0x00000000219ab540356cbb839cbe05303d7705fa> -contract PreimageOracle is IPreimageOracle { +contract PreimageOracle is IPreimageOracle, ISemver { //////////////////////////////////////////////////////////////// // Constants & Immutables // //////////////////////////////////////////////////////////////// @@ -20,11 +21,17 @@ contract PreimageOracle is IPreimageOracle { uint256 internal immutable CHALLENGE_PERIOD; /// @notice The minimum size of a preimage that can be proposed in the large preimage path. uint256 internal immutable MIN_LPP_SIZE_BYTES; + /// @notice The minimum bond size for large preimage proposals. + uint256 public constant MIN_BOND_SIZE = 0.25 ether; /// @notice The depth of the keccak256 merkle tree. Supports up to 65,536 keccak blocks, or ~8.91MB preimages. uint256 public constant KECCAK_TREE_DEPTH = 16; /// @notice The maximum number of keccak blocks that can fit into the merkle tree. uint256 public constant MAX_LEAF_COUNT = 2 ** KECCAK_TREE_DEPTH - 1; + /// @notice The semantic version of the Preimage Oracle contract. + /// @custom:semver 0.1.0 + string public constant version = "0.1.0"; + //////////////////////////////////////////////////////////////// // Authorized Preimage Parts // //////////////////////////////////////////////////////////////// @@ -68,6 +75,8 @@ contract PreimageOracle is IPreimageOracle { /// @notice Mapping of claimants to proposal UUIDs to the timestamp of creation of the proposal as well as the /// challenged status. mapping(address => mapping(uint256 => LPPMetaData)) public proposalMetadata; + /// @notice Mapping of claimants to proposal UUIDs to bond amounts. + mapping(address => mapping(uint256 => uint256)) public proposalBonds; /// @notice Mapping of claimants to proposal UUIDs to the preimage part picked up during the absorbtion process. mapping(address => mapping(uint256 => bytes32)) public proposalParts; /// @notice Mapping of claimants to proposal UUIDs to blocks which leaves were added to the merkle tree. @@ -159,24 +168,23 @@ contract PreimageOracle is IPreimageOracle { // revert if part offset >= size+8 (i.e. parts must be within bounds) if iszero(lt(_partOffset, add(size, 8))) { // Store "PartOffsetOOB()" - mstore(0, 0xfe254987) + mstore(0x00, 0xfe254987) // Revert with "PartOffsetOOB()" - revert(0x1c, 4) + revert(0x1c, 0x04) } - // we leave solidity slots 0x40 and 0x60 untouched, - // and everything after as scratch-memory. + // we leave solidity slots 0x40 and 0x60 untouched, and everything after as scratch-memory. let ptr := 0x80 // put size as big-endian uint64 at start of pre-image mstore(ptr, shl(192, size)) - ptr := add(ptr, 8) + ptr := add(ptr, 0x08) // copy preimage payload into memory so we can hash and read it. calldatacopy(ptr, _preimage.offset, size) // Note that it includes the 8-byte big-endian uint64 length prefix. // this will be zero-padded at the end, since memory at end is clean. - part := mload(add(sub(ptr, 8), _partOffset)) + part := mload(add(sub(ptr, 0x08), _partOffset)) let h := keccak256(ptr, size) // compute preimage keccak256 hash // mask out prefix byte, replace with type 2 byte - key := or(and(h, not(shl(248, 0xFF))), shl(248, 2)) + key := or(and(h, not(shl(248, 0xFF))), shl(248, 0x02)) } preimagePartOk[key][_partOffset] = true; preimageParts[key][_partOffset] = part; @@ -232,7 +240,153 @@ contract PreimageOracle is IPreimageOracle { preimageLengths[key] = size; } - // TODO 4844 point-evaluation preimage + /// @inheritdoc IPreimageOracle + function loadBlobPreimagePart( + uint256 _z, + uint256 _y, + bytes calldata _commitment, + bytes calldata _proof, + uint256 _partOffset + ) + external + { + bytes32 key; + bytes32 part; + assembly { + // Compute the versioned hash. The SHA2 hash of the 48 byte commitment is masked with the version byte, + // which is currently 1. https://eips.ethereum.org/EIPS/eip-4844#parameters + // SAFETY: We're only reading 48 bytes from `_commitment` into scratch space, so we're not reading into the + // free memory ptr region. Since the exact number of btyes that is copied into scratch space is + // the same size as the hash input, there's no concern of dirty memory being read into the hash + // input. + calldatacopy(0x00, _commitment.offset, 0x30) + let success := staticcall(gas(), 0x02, 0x00, 0x30, 0x00, 0x20) + if iszero(success) { + // Store the "ShaFailed()" error selector. + mstore(0x00, 0xf9112969) + // revert with "ShaFailed()" + revert(0x1C, 0x04) + } + // Set the `VERSIONED_HASH_VERSION_KZG` byte = 1 in the high-order byte of the hash. + let versionedHash := or(and(mload(0x00), not(shl(248, 0xFF))), shl(248, 0x01)) + + // we leave solidity slots 0x40 and 0x60 untouched, and everything after as scratch-memory. + let ptr := 0x80 + + // Load the inputs for the point evaluation precompile into memory. The inputs to the point evaluation + // precompile are packed, and not supposed to be ABI-encoded. + mstore(ptr, versionedHash) + mstore(add(ptr, 0x20), _z) + mstore(add(ptr, 0x40), _y) + calldatacopy(add(ptr, 0x60), _commitment.offset, 0x30) + calldatacopy(add(ptr, 0x90), _proof.offset, 0x30) + + // Verify the KZG proof by calling the point evaluation precompile. If the proof is invalid, the precompile + // will revert. + success := + staticcall( + gas(), // forward all gas + 0x0A, // point evaluation precompile address + ptr, // input ptr + 0xC0, // input size = 192 bytes + 0x00, // output ptr + 0x00 // output size + ) + if iszero(success) { + // Store the "InvalidProof()" error selector. + mstore(0x00, 0x09bde339) + // revert with "InvalidProof()" + revert(0x1C, 0x04) + } + + // revert if part offset >= 32+8 (i.e. parts must be within bounds) + if iszero(lt(_partOffset, 0x28)) { + // Store "PartOffsetOOB()" + mstore(0x00, 0xfe254987) + // Revert with "PartOffsetOOB()" + revert(0x1C, 0x04) + } + // Clean the word at `ptr + 0x28` to ensure that data out of bounds of the preimage is zero, if the part + // offset requires a partial read. + mstore(add(ptr, 0x28), 0x00) + // put size (32) as a big-endian uint64 at start of pre-image + mstore(ptr, shl(192, 0x20)) + // copy preimage payload into memory so we can hash and read it. + mstore(add(ptr, 0x08), _y) + // Note that it includes the 8-byte big-endian uint64 length prefix. This will be zero-padded at the end, + // since memory at end is guaranteed to be clean. + part := mload(add(ptr, _partOffset)) + + // Compute the key: `keccak256(commitment ++ z)`. Since the exact number of btyes that is copied into + // scratch space is the same size as the hash input, there's no concern of dirty memory being read into + // the hash input. + calldatacopy(ptr, _commitment.offset, 0x30) + mstore(add(ptr, 0x30), _z) + let h := keccak256(ptr, 0x50) + // mask out prefix byte, replace with type 5 byte + key := or(and(h, not(shl(248, 0xFF))), shl(248, 0x05)) + } + preimagePartOk[key][_partOffset] = true; + preimageParts[key][_partOffset] = part; + preimageLengths[key] = 32; + } + + /// @inheritdoc IPreimageOracle + function loadPrecompilePreimagePart(uint256 _partOffset, address _precompile, bytes calldata _input) external { + bytes32 res; + bytes32 key; + bytes32 part; + uint256 size; + assembly { + // we leave solidity slots 0x40 and 0x60 untouched, and everything after as scratch-memory. + let ptr := 0x80 + + // copy precompile address and input into memory + // len(sig) + len(_partOffset) + address-offset-in-slot + calldatacopy(ptr, 48, 20) + calldatacopy(add(20, ptr), _input.offset, _input.length) + // compute the hash + let h := keccak256(ptr, add(20, _input.length)) + // mask out prefix byte, replace with type 6 byte + key := or(and(h, not(shl(248, 0xFF))), shl(248, 0x06)) + + // Call the precompile to get the result. + res := + staticcall( + gas(), // forward all gas + _precompile, + add(20, ptr), // input ptr + _input.length, + 0x0, // Unused as we don't copy anything + 0x00 // don't copy anything + ) + + size := add(1, returndatasize()) + // revert if part offset >= size+8 (i.e. parts must be within bounds) + if iszero(lt(_partOffset, add(size, 8))) { + // Store "PartOffsetOOB()" + mstore(0, 0xfe254987) + // Revert with "PartOffsetOOB()" + revert(0x1c, 4) + } + + // Reuse the `ptr` to store the preimage part: + // put size as big-endian uint64 at start of pre-image + mstore(ptr, shl(192, size)) + ptr := add(ptr, 0x08) + + // write precompile result status to the first byte of `ptr` + mstore8(ptr, res) + // write precompile return data to the rest of `ptr` + returndatacopy(add(ptr, 0x01), 0x0, returndatasize()) + + // compute part given ofset + part := mload(add(sub(ptr, 0x08), _partOffset)) + } + preimagePartOk[key][_partOffset] = true; + preimageParts[key][_partOffset] = part; + preimageLengths[key] = size; + } //////////////////////////////////////////////////////////////// // Large Preimage Proposals (External) // @@ -260,8 +414,11 @@ contract PreimageOracle is IPreimageOracle { } /// @notice Initialize a large preimage proposal. Must be called before adding any leaves. - function initLPP(uint256 _uuid, uint32 _partOffset, uint32 _claimedSize) external { - // The caller of `addLeavesLPP` must be an EOA. + function initLPP(uint256 _uuid, uint32 _partOffset, uint32 _claimedSize) external payable { + // The bond provided must be at least `MIN_BOND_SIZE`. + if (msg.value < MIN_BOND_SIZE) revert InsufficientBond(); + + // The caller of `addLeavesLPP` must be an EOA, so that the call inputs are always available in block bodies. if (msg.sender != tx.origin) revert NotEOA(); // The part offset must be within the bounds of the claimed size + 8. @@ -270,9 +427,13 @@ contract PreimageOracle is IPreimageOracle { // The claimed size must be at least `MIN_LPP_SIZE_BYTES`. if (_claimedSize < MIN_LPP_SIZE_BYTES) revert InvalidInputSize(); + // Initialize the proposal metadata. LPPMetaData metaData = proposalMetadata[msg.sender][_uuid]; proposalMetadata[msg.sender][_uuid] = metaData.setPartOffset(_partOffset).setClaimedSize(_claimedSize); proposals.push(LargePreimageProposalKeys(msg.sender, _uuid)); + + // Assign the bond to the proposal. + proposalBonds[msg.sender][_uuid] = msg.value; } /// @notice Adds a contiguous list of keccak state matrices to the merkle tree. @@ -366,7 +527,9 @@ contract PreimageOracle is IPreimageOracle { } } - // Do not allow for posting preimages larger than the merkle tree can support. + // Do not allow for posting preimages larger than the merkle tree can support. The incremental merkle tree + // algorithm only supports 2**height - 1 leaves, the right most leaf must always be kept empty. + // Reference: https://daejunpark.github.io/papers/deposit.pdf - Page 10, Section 5.1. if (blocksProcessed > MAX_LEAF_COUNT) revert TreeSizeOverflow(); // Update the proposal metadata to include the number of blocks processed and total bytes processed. @@ -375,7 +538,12 @@ contract PreimageOracle is IPreimageOracle { ); // If the proposal is being finalized, set the timestamp to the current block timestamp. This begins the // challenge period, which must be waited out before the proposal can be finalized. - if (_finalize) metaData = metaData.setTimestamp(uint64(block.timestamp)); + if (_finalize) { + metaData = metaData.setTimestamp(uint64(block.timestamp)); + + // If the number of bytes processed is not equal to the claimed size, the proposal cannot be finalized. + if (metaData.bytesProcessed() != metaData.claimedSize()) revert InvalidInputSize(); + } // Perist the latest branch to storage. proposalBranches[msg.sender][_uuid] = branch; @@ -422,6 +590,9 @@ contract PreimageOracle is IPreimageOracle { // Mark the keccak claim as countered. proposalMetadata[_claimant][_uuid] = proposalMetadata[_claimant][_uuid].setCountered(true); + + // Pay out the bond to the challenger. + _payoutBond(_claimant, _uuid, msg.sender); } /// @notice Challenge the first keccak256 block that was absorbed. @@ -450,6 +621,9 @@ contract PreimageOracle is IPreimageOracle { // Mark the keccak claim as countered. proposalMetadata[_claimant][_uuid] = proposalMetadata[_claimant][_uuid].setCountered(true); + + // Pay out the bond to the challenger. + _payoutBond(_claimant, _uuid, msg.sender); } /// @notice Finalize a large preimage proposal after the challenge period has passed. @@ -489,21 +663,23 @@ contract PreimageOracle is IPreimageOracle { revert StatesNotContiguous(); } - // The claimed size must match the actual size of the preimage. - uint256 claimedSize = metaData.claimedSize(); - if (metaData.bytesProcessed() != claimedSize) revert InvalidInputSize(); - // Absorb and permute the input bytes. We perform no final verification on the state matrix here, since the // proposal has passed the challenge period and is considered valid. LibKeccak.absorb(_stateMatrix, _postState.input); LibKeccak.permutation(_stateMatrix); bytes32 finalDigest = LibKeccak.squeeze(_stateMatrix); + assembly { + finalDigest := or(and(finalDigest, not(shl(248, 0xFF))), shl(248, 0x02)) + } // Write the preimage part to the authorized preimage parts mapping. uint256 partOffset = metaData.partOffset(); preimagePartOk[finalDigest][partOffset] = true; preimageParts[finalDigest][partOffset] = proposalParts[_claimant][_uuid]; - preimageLengths[finalDigest] = claimedSize; + preimageLengths[finalDigest] = metaData.claimedSize(); + + // Pay out the bond to the claimant. + _payoutBond(_claimant, _uuid, _claimant); } /// @notice Gets the current merkle root of the large preimage proposal tree. @@ -565,7 +741,7 @@ contract PreimageOracle is IPreimageOracle { } } - /// Check if leaf` at `index` verifies against the Merkle `root` and `branch`. + /// @notice Check if leaf` at `index` verifies against the Merkle `root` and `branch`. /// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#is_valid_merkle_branch function _verify( bytes32[] calldata _proof, @@ -598,6 +774,15 @@ contract PreimageOracle is IPreimageOracle { } } + /// @notice Pay out a proposal's bond. Reverts if the transfer fails. + function _payoutBond(address _claimant, uint256 _uuid, address _to) internal { + // Pay out the bond to the claimant. + uint256 bond = proposalBonds[_claimant][_uuid]; + proposalBonds[_claimant][_uuid] = 0; + (bool success,) = _to.call{ value: bond }(""); + if (!success) revert BondTransferFailed(); + } + /// @notice Hashes leaf data for the preimage proposals tree function _hashLeaf(Leaf memory _leaf) internal pure returns (bytes32 leaf_) { leaf_ = keccak256(abi.encodePacked(_leaf.input, _leaf.index, _leaf.stateCommitment)); diff --git a/packages/contracts-bedrock/src/cannon/interfaces/IPreimageOracle.sol b/packages/contracts-bedrock/src/cannon/interfaces/IPreimageOracle.sol index f7380eba4e74..7c4a57b257bd 100644 --- a/packages/contracts-bedrock/src/cannon/interfaces/IPreimageOracle.sol +++ b/packages/contracts-bedrock/src/cannon/interfaces/IPreimageOracle.sol @@ -53,4 +53,28 @@ interface IPreimageOracle { /// @param _partOffset The offset of the preimage to read. /// @param _preimage The preimage data. function loadSha256PreimagePart(uint256 _partOffset, bytes calldata _preimage) external; + + /// @notice Verifies that `p(_z) = _y` given `_commitment` that corresponds to the polynomial `p(x)` and a KZG + // proof. The value `y` is the pre-image, and the preimage key is `5 ++ keccak256(_commitment ++ z)[1:]`. + /// @param _z Big endian point value. Part of the preimage key. + /// @param _y Big endian point value. The preimage for the key. + /// @param _commitment The commitment to the polynomial. 48 bytes, part of the preimage key. + /// @param _proof The KZG proof, part of the preimage key. + /// @param _partOffset The offset of the preimage to store. + function loadBlobPreimagePart( + uint256 _z, + uint256 _y, + bytes calldata _commitment, + bytes calldata _proof, + uint256 _partOffset + ) + external; + + /// @notice Prepares a precompile result to be read by a precompile key for the specified offset. + /// The precompile result data is a concatenation of the precompile call status byte and its return data. + /// The preimage key is `6 ++ keccak256(precompile ++ input)[1:]`. + /// @param _partOffset The offset of the precompile result being loaded. + /// @param _precompile The precompile address + /// @param _input The input to the precompile call. + function loadPrecompilePreimagePart(uint256 _partOffset, address _precompile, bytes calldata _input) external; } diff --git a/packages/contracts-bedrock/src/cannon/libraries/CannonErrors.sol b/packages/contracts-bedrock/src/cannon/libraries/CannonErrors.sol index 862046ce482e..621c0609a879 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/CannonErrors.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/CannonErrors.sol @@ -39,3 +39,9 @@ error NotInitialized(); /// @notice Thrown when the caller of a function is not an EOA. error NotEOA(); + +/// @notice Thrown when an insufficient bond is provided for a large preimage proposal. +error InsufficientBond(); + +/// @notice Thrown when a bond transfer fails. +error BondTransferFailed(); diff --git a/packages/contracts-bedrock/src/dispute/AnchorStateRegistry.sol b/packages/contracts-bedrock/src/dispute/AnchorStateRegistry.sol new file mode 100644 index 000000000000..f9fc42162f33 --- /dev/null +++ b/packages/contracts-bedrock/src/dispute/AnchorStateRegistry.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +import { ISemver } from "src/universal/ISemver.sol"; + +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; +import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; +import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; + +import "src/libraries/DisputeTypes.sol"; + +/// @title AnchorStateRegistry +/// @notice The AnchorStateRegistry is a contract that stores the latest "anchor" state for each available +/// FaultDisputeGame type. The anchor state is the latest state that has been proposed on L1 and was not +/// challenged within the challenge period. By using stored anchor states, new FaultDisputeGame instances can +/// be initialized with a more recent starting state which reduces the amount of required offchain computation. +contract AnchorStateRegistry is Initializable, IAnchorStateRegistry, ISemver { + /// @notice Describes an initial anchor state for a game type. + struct StartingAnchorRoot { + GameType gameType; + OutputRoot outputRoot; + } + + /// @notice Semantic version. + /// @custom:semver 0.1.0 + string public constant version = "0.1.0"; + + /// @notice DisputeGameFactory address. + IDisputeGameFactory internal immutable DISPUTE_GAME_FACTORY; + + /// @inheritdoc IAnchorStateRegistry + mapping(GameType => OutputRoot) public anchors; + + /// @param _disputeGameFactory DisputeGameFactory address. + constructor(IDisputeGameFactory _disputeGameFactory) { + DISPUTE_GAME_FACTORY = _disputeGameFactory; + + // Initialize the implementation with an empty array of starting anchor roots. + initialize(new StartingAnchorRoot[](0)); + } + + /// @notice Initializes the contract. + /// @param _startingAnchorRoots An array of starting anchor roots. + function initialize(StartingAnchorRoot[] memory _startingAnchorRoots) public initializer { + for (uint256 i = 0; i < _startingAnchorRoots.length; i++) { + StartingAnchorRoot memory startingAnchorRoot = _startingAnchorRoots[i]; + anchors[startingAnchorRoot.gameType] = startingAnchorRoot.outputRoot; + } + } + + /// @inheritdoc IAnchorStateRegistry + function disputeGameFactory() external view returns (IDisputeGameFactory) { + return DISPUTE_GAME_FACTORY; + } + + /// @inheritdoc IAnchorStateRegistry + function tryUpdateAnchorState() external { + // Grab the game and game data. + IFaultDisputeGame game = IFaultDisputeGame(msg.sender); + (GameType gameType, Claim rootClaim, bytes memory extraData) = game.gameData(); + + // Grab the verified address of the game based on the game data. + // slither-disable-next-line unused-return + (IDisputeGame factoryRegisteredGame,) = + DISPUTE_GAME_FACTORY.games({ _gameType: gameType, _rootClaim: rootClaim, _extraData: extraData }); + + // Must be a valid game. + require( + address(factoryRegisteredGame) == address(game), + "AnchorStateRegistry: fault dispute game not registered with factory" + ); + + // No need to update anything if the anchor state is already newer. + if (game.l2BlockNumber() <= anchors[gameType].l2BlockNumber) { + return; + } + + // Must be a game that resolved in favor of the state. + if (game.status() != GameStatus.DEFENDER_WINS) { + return; + } + + // Actually update the anchor state. + anchors[gameType] = OutputRoot({ l2BlockNumber: game.l2BlockNumber(), root: Hash.wrap(game.rootClaim().raw()) }); + } +} diff --git a/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol b/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol index 9db6bbebe29f..e3f7d441f84a 100644 --- a/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol +++ b/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; +pragma solidity 0.8.15; import { ClonesWithImmutableArgs } from "@cwia/ClonesWithImmutableArgs.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; @@ -14,18 +14,17 @@ import "src/libraries/DisputeTypes.sol"; import "src/libraries/DisputeErrors.sol"; /// @title DisputeGameFactory -/// @notice A factory contract for creating `IDisputeGame` contracts. All created dispute games -/// are stored in both a mapping and an append only array. The timestamp of the creation -/// time of the dispute game is packed tightly into the storage slot with the address of -/// the dispute game. This is to make offchain discoverability of playable dispute games -/// easier. +/// @notice A factory contract for creating `IDisputeGame` contracts. All created dispute games are stored in both a +/// mapping and an append only array. The timestamp of the creation time of the dispute game is packed tightly +/// into the storage slot with the address of the dispute game to make offchain discoverability of playable +/// dispute games easier. contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver { /// @dev Allows for the creation of clone proxies with immutable arguments. using ClonesWithImmutableArgs for address; /// @notice Semantic version. - /// @custom:semver 0.0.8 - string public constant version = "0.0.8"; + /// @custom:semver 0.2.0 + string public constant version = "0.2.0"; /// @inheritdoc IDisputeGameFactory mapping(GameType => IDisputeGame) public gameImpls; @@ -33,17 +32,15 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver /// @inheritdoc IDisputeGameFactory mapping(GameType => uint256) public initBonds; - /// @notice Mapping of a hash of `gameType || rootClaim || extraData` to - /// the deployed `IDisputeGame` clone. - /// @dev Note: `||` denotes concatenation. + /// @notice Mapping of a hash of `gameType || rootClaim || extraData` to the deployed `IDisputeGame` clone (where + // `||` denotes concatenation). mapping(Hash => GameId) internal _disputeGames; - /// @notice an append-only array of disputeGames that have been created. - /// @dev this accessor is used by offchain game solvers to efficiently - /// track dispute games + /// @notice An append-only array of disputeGames that have been created. Used by offchain game solvers to + /// efficiently track dispute games. GameId[] internal _disputeGameList; - /// @notice constructs a new DisputeGameFactory contract. + /// @notice Constructs a new DisputeGameFactory contract. constructor() OwnableUpgradeable() { initialize(address(0)); } @@ -102,8 +99,11 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver // If the required initialization bond is not met, revert. if (msg.value < initBonds[_gameType]) revert InsufficientBond(); + // Get the hash of the parent block. + bytes32 parentHash = blockhash(block.number - 1); + // Clone the implementation contract and initialize it with the given parameters. - proxy_ = IDisputeGame(address(impl).clone(abi.encodePacked(_rootClaim, _extraData))); + proxy_ = IDisputeGame(address(impl).clone(abi.encodePacked(_rootClaim, parentHash, _extraData))); proxy_.initialize{ value: msg.value }(); // Compute the unique identifier for the dispute game. @@ -112,6 +112,7 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver // If a dispute game with the same UUID already exists, revert. if (GameId.unwrap(_disputeGames[uuid]) != bytes32(0)) revert GameAlreadyExists(uuid); + // Pack the game ID. GameId id = LibGameId.pack(_gameType, Timestamp.wrap(uint64(block.timestamp)), proxy_); // Store the dispute game id in the mapping & emit the `DisputeGameCreated` event. @@ -133,6 +134,57 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver uuid_ = Hash.wrap(keccak256(abi.encode(_gameType, _rootClaim, _extraData))); } + /// @inheritdoc IDisputeGameFactory + function findLatestGames( + GameType _gameType, + uint256 _start, + uint256 _n + ) + external + view + returns (GameSearchResult[] memory games_) + { + // If the `_start` index is greater than or equal to the game array length or `_n == 0`, return an empty array. + if (_start >= _disputeGameList.length || _n == 0) return games_; + + // Allocate enough memory for the full array, but start the array's length at `0`. We may not use all of the + // memory allocated, but we don't know ahead of time the final size of the array. + assembly { + games_ := mload(0x40) + mstore(0x40, add(games_, add(0x20, shl(0x05, _n)))) + } + + // Perform a reverse linear search for the `_n` most recent games of type `_gameType`. + for (uint256 i = _start; i >= 0 && i <= _start;) { + GameId id = _disputeGameList[i]; + (GameType gameType, Timestamp timestamp, IDisputeGame proxy) = id.unpack(); + + if (gameType.raw() == _gameType.raw()) { + // Increase the size of the `games_` array by 1. + // SAFETY: We can safely lazily allocate memory here because we pre-allocated enough memory for the max + // possible size of the array. + assembly { + mstore(games_, add(mload(games_), 0x01)) + } + + bytes memory extraData = proxy.extraData(); + Claim rootClaim = proxy.rootClaim(); + games_[games_.length - 1] = GameSearchResult({ + index: i, + metadata: id, + timestamp: timestamp, + rootClaim: rootClaim, + extraData: extraData + }); + if (games_.length >= _n) break; + } + + unchecked { + i--; + } + } + } + /// @inheritdoc IDisputeGameFactory function setImplementation(GameType _gameType, IDisputeGame _impl) external onlyOwner { gameImpls[_gameType] = _impl; diff --git a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol index 052cc4a968df..3e2df9d7cd7a 100644 --- a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol @@ -1,10 +1,14 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; +pragma solidity 0.8.15; +import { FixedPointMathLib } from "solady/utils/FixedPointMathLib.sol"; + +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; import { IInitializable } from "src/dispute/interfaces/IInitializable.sol"; import { IBigStepper, IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; import { Clone } from "src/libraries/Clone.sol"; import { Types } from "src/libraries/Types.sol"; @@ -38,18 +42,24 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { /// @notice An onchain VM that performs single instruction steps on a fault proof program trace. IBigStepper internal immutable VM; - /// @notice The genesis block number - uint256 internal immutable GENESIS_BLOCK_NUMBER; + /// @notice The game type ID. + GameType internal immutable GAME_TYPE; - /// @notice The genesis output root - Hash internal immutable GENESIS_OUTPUT_ROOT; + /// @notice WETH contract for holding ETH. + IDelayedWETH internal immutable WETH; - /// @notice The game type ID - GameType internal immutable GAME_TYPE; + /// @notice The anchor state registry. + IAnchorStateRegistry internal immutable ANCHOR_STATE_REGISTRY; + + /// @notice The chain ID of the L2 network this contract argues about. + uint256 internal immutable L2_CHAIN_ID; /// @notice The global root claim's position is always at gindex 1. Position internal constant ROOT_POSITION = Position.wrap(1); + /// @notice The flag set in the `bond` field of a `ClaimData` struct to indicate that the bond has been claimed. + uint128 internal constant CLAIMED_BOND_FLAG = type(uint128).max; + /// @notice The starting timestamp of the game Timestamp public createdAt; @@ -59,9 +69,6 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { /// @inheritdoc IDisputeGame GameStatus public status; - /// @inheritdoc IFaultDisputeGame - Hash public l1Head; - /// @notice An append-only array of all claims made during the dispute game. ClaimData[] public claimData; @@ -80,48 +87,67 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { /// @notice Flag for the `initialize` function to prevent re-initialization. bool internal initialized; + /// @notice The latest finalized output root, serving as the anchor for output bisection. + OutputRoot public startingOutputRoot; + /// @notice Semantic version. - /// @custom:semver 0.0.24 - string public constant version = "0.0.24"; + /// @custom:semver 0.8.1 + string public constant version = "0.8.1"; /// @param _gameType The type ID of the game. /// @param _absolutePrestate The absolute prestate of the instruction trace. - /// @param _genesisBlockNumber The block number of the genesis block. - /// @param _genesisOutputRoot The output root of the genesis block. /// @param _maxGameDepth The maximum depth of bisection. /// @param _splitDepth The final depth of the output bisection portion of the game. /// @param _gameDuration The duration of the game. - /// @param _vm An onchain VM that performs single instruction steps on a fault proof program - /// trace. + /// @param _vm An onchain VM that performs single instruction steps on an FPP trace. + /// @param _weth WETH contract for holding ETH. + /// @param _anchorStateRegistry The contract that stores the anchor state for each game type. + /// @param _l2ChainId Chain ID of the L2 network this contract argues about. constructor( GameType _gameType, Claim _absolutePrestate, - uint256 _genesisBlockNumber, - Hash _genesisOutputRoot, uint256 _maxGameDepth, uint256 _splitDepth, Duration _gameDuration, - IBigStepper _vm + IBigStepper _vm, + IDelayedWETH _weth, + IAnchorStateRegistry _anchorStateRegistry, + uint256 _l2ChainId ) { // The split depth cannot be greater than or equal to the max game depth. if (_splitDepth >= _maxGameDepth) revert InvalidSplitDepth(); GAME_TYPE = _gameType; ABSOLUTE_PRESTATE = _absolutePrestate; - GENESIS_BLOCK_NUMBER = _genesisBlockNumber; - GENESIS_OUTPUT_ROOT = _genesisOutputRoot; MAX_GAME_DEPTH = _maxGameDepth; SPLIT_DEPTH = _splitDepth; GAME_DURATION = _gameDuration; VM = _vm; + WETH = _weth; + ANCHOR_STATE_REGISTRY = _anchorStateRegistry; + L2_CHAIN_ID = _l2ChainId; } + /// @notice Receive function to allow the contract to receive ETH. + receive() external payable { } + + /// @notice Fallback function to allow the contract to receive ETH. + fallback() external payable { } + //////////////////////////////////////////////////////////////// // `IFaultDisputeGame` impl // //////////////////////////////////////////////////////////////// /// @inheritdoc IFaultDisputeGame - function step(uint256 _claimIndex, bool _isAttack, bytes calldata _stateData, bytes calldata _proof) external { + function step( + uint256 _claimIndex, + bool _isAttack, + bytes calldata _stateData, + bytes calldata _proof + ) + public + virtual + { // INVARIANT: Steps cannot be made unless the game is currently in progress. if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); @@ -185,6 +211,9 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { bool parentPostAgree = (parentPos.depth() - postState.position.depth()) % 2 == 0; if (parentPostAgree == validStep) revert ValidStep(); + // INVARIANT: A step cannot be made against a claim for a second time. + if (parent.counteredBy != address(0)) revert DuplicateStep(); + // Set the parent claim as countered. We do not need to append a new claim to the game; // instead, we can just set the existing parent as countered. parent.counteredBy = msg.sender; @@ -194,7 +223,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { /// @param _challengeIndex The index of the claim being moved against. /// @param _claim The claim at the next logical position in the game. /// @param _isAttack Whether or not the move is an attack or defense. - function move(uint256 _challengeIndex, Claim _claim, bool _isAttack) public payable { + function move(uint256 _challengeIndex, Claim _claim, bool _isAttack) public payable virtual { // INVARIANT: Moves cannot be made unless the game is currently in progress. if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); @@ -268,6 +297,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { claimData.push( ClaimData({ parentIndex: uint32(_challengeIndex), + // This is updated during subgame resolution counteredBy: address(0), claimant: msg.sender, bond: uint128(msg.value), @@ -277,12 +307,12 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { }) ); - // Set the parent claim as countered. - claimData[_challengeIndex].counteredBy = msg.sender; - // Update the subgame rooted at the parent claim. subgames[_challengeIndex].push(claimData.length - 1); + // Deposit the bond. + WETH.deposit{ value: msg.value }(); + // Emit the appropriate event for the attack or defense. emit Move(_challengeIndex, _claim, msg.sender); } @@ -309,35 +339,38 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { IPreimageOracle oracle = VM.oracle(); if (_ident == LocalPreimageKey.L1_HEAD_HASH) { // Load the L1 head hash - oracle.loadLocalData(_ident, uuid.raw(), l1Head.raw(), 32, _partOffset); + oracle.loadLocalData(_ident, uuid.raw(), l1Head().raw(), 32, _partOffset); } else if (_ident == LocalPreimageKey.STARTING_OUTPUT_ROOT) { // Load the starting proposal's output root. oracle.loadLocalData(_ident, uuid.raw(), starting.raw(), 32, _partOffset); } else if (_ident == LocalPreimageKey.DISPUTED_OUTPUT_ROOT) { // Load the disputed proposal's output root oracle.loadLocalData(_ident, uuid.raw(), disputed.raw(), 32, _partOffset); - } else if (_ident == LocalPreimageKey.STARTING_L2_BLOCK_NUMBER) { - // Load the starting proposal's L2 block number as a big-endian uint64 in the + } else if (_ident == LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER) { + // Load the disputed proposal's L2 block number as a big-endian uint64 in the // high order 8 bytes of the word. - // If the starting position is 0 (invalid), the starting output root is genesis. Otherwise, - // we add the index at depth + 1 to the genesis block number to get the L2 block number. - uint256 l2Number = startingPos.raw() == 0 - ? GENESIS_BLOCK_NUMBER - : GENESIS_BLOCK_NUMBER + startingPos.traceIndex(SPLIT_DEPTH) + 1; + // We add the index at depth + 1 to the starting block number to get the disputed L2 + // block number. + uint256 l2Number = startingOutputRoot.l2BlockNumber + disputedPos.traceIndex(SPLIT_DEPTH) + 1; oracle.loadLocalData(_ident, uuid.raw(), bytes32(l2Number << 0xC0), 8, _partOffset); } else if (_ident == LocalPreimageKey.CHAIN_ID) { // Load the chain ID as a big-endian uint64 in the high order 8 bytes of the word. - oracle.loadLocalData(_ident, uuid.raw(), bytes32(block.chainid << 0xC0), 8, _partOffset); + oracle.loadLocalData(_ident, uuid.raw(), bytes32(L2_CHAIN_ID << 0xC0), 8, _partOffset); } else { revert InvalidLocalIdent(); } } + /// @inheritdoc IFaultDisputeGame + function l1Head() public pure returns (Hash l1Head_) { + l1Head_ = Hash.wrap(_getArgFixedBytes(0x20)); + } + /// @inheritdoc IFaultDisputeGame function l2BlockNumber() public pure returns (uint256 l2BlockNumber_) { - l2BlockNumber_ = _getArgUint256(0x20); + l2BlockNumber_ = _getArgUint256(0x40); } //////////////////////////////////////////////////////////////// @@ -361,7 +394,11 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { status_ = claimData[0].counteredBy == address(0) ? GameStatus.DEFENDER_WINS : GameStatus.CHALLENGER_WINS; resolvedAt = Timestamp.wrap(uint64(block.timestamp)); + // Update the status and emit the resolved event, note that we're performing an assignment here. emit Resolved(status = status_); + + // Try to update the anchor state, this should not revert. + ANCHOR_STATE_REGISTRY.tryUpdateAnchorState(); } /// @inheritdoc IFaultDisputeGame @@ -389,12 +426,19 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { // Uncontested claims are resolved implicitly unless they are the root claim. Pay out the bond to the claimant // and return early. if (challengeIndicesLen == 0 && _claimIndex != 0) { - _distributeBond(parent.claimant, parent); + // In the event that the parent claim is at the max depth, there will always be 0 subgames. If the + // `counteredBy` field is set and there are no subgames, this implies that the parent claim was successfully + // stepped against. In this case, we pay out the bond to the party that stepped against the parent claim. + // Otherwise, the parent claim is uncontested, and the bond is returned to the claimant. + address counteredBy = parent.counteredBy; + address recipient = counteredBy == address(0) ? parent.claimant : counteredBy; + _distributeBond(recipient, parent); return; } // Assume parent is honest until proven otherwise address countered = address(0); + Position leftmostCounter = Position.wrap(type(uint128).max); for (uint256 i = 0; i < challengeIndicesLen; ++i) { uint256 challengeIndex = challengeIndices[i]; @@ -403,10 +447,15 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { ClaimData storage claim = claimData[challengeIndex]; - // Ignore false claims - if (claim.counteredBy == address(0)) { - countered = msg.sender; - break; + // If the child subgame is uncountered and further left than the current left-most counter, + // update the parent subgame's `countered` address and the current `leftmostCounter`. + // The left-most correct counter is preferred in bond payouts in order to discourage attackers + // from countering invalid subgame roots via an invalid defense position. As such positions + // cannot be correctly countered. + // Note that correctly positioned defense, but invalid claimes can still be successfully countered. + if (claim.counteredBy == address(0) && leftmostCounter.raw() > claim.position.raw()) { + countered = claim.claimant; + leftmostCounter = claim.position; } } @@ -436,7 +485,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { function extraData() public pure returns (bytes memory extraData_) { // The extra data starts at the second word within the cwia calldata and // is 32 bytes long. - extraData_ = _getArgDynBytes(0x20, 0x20); + extraData_ = _getArgDynBytes(0x40, 0x20); } /// @inheritdoc IDisputeGame @@ -446,12 +495,22 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { extraData_ = extraData(); } + /// @inheritdoc IFaultDisputeGame + function startingBlockNumber() external view returns (uint256 startingBlockNumber_) { + startingBlockNumber_ = startingOutputRoot.l2BlockNumber; + } + + /// @inheritdoc IFaultDisputeGame + function startingRootHash() external view returns (Hash startingRootHash_) { + startingRootHash_ = startingOutputRoot.root; + } + //////////////////////////////////////////////////////////////// // MISC EXTERNAL // //////////////////////////////////////////////////////////////// /// @inheritdoc IInitializable - function initialize() external payable { + function initialize() public payable virtual { // SAFETY: Any revert in this function will bubble up to the DisputeGameFactory and // prevent the game from being created. // @@ -461,22 +520,31 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { // // Explicit checks: // - The game must not have already been initialized. - // - An output root cannot be proposed at or before the genesis block. + // - An output root cannot be proposed at or before the starting block number. // INVARIANT: The game must not have already been initialized. if (initialized) revert AlreadyInitialized(); + // Grab the latest anchor root. + (Hash root, uint256 rootBlockNumber) = ANCHOR_STATE_REGISTRY.anchors(GAME_TYPE); + + // Should only happen if this is a new game type that hasn't been set up yet. + if (root.raw() == bytes32(0)) revert AnchorRootNotFound(); + + // Set the starting output root. + startingOutputRoot = OutputRoot({ l2BlockNumber: rootBlockNumber, root: root }); + // Do not allow the game to be initialized if the root claim corresponds to a block at or before the - // configured genesis block number. - if (l2BlockNumber() <= GENESIS_BLOCK_NUMBER) revert UnexpectedRootClaim(rootClaim()); + // configured starting block number. + if (l2BlockNumber() <= rootBlockNumber) revert UnexpectedRootClaim(rootClaim()); // Revert if the calldata size is too large, which signals that the `extraData` contains more than expected. // This is to prevent adding extra bytes to the `extraData` that result in a different game UUID in the factory, // but are not used by the game, which would allow for multiple dispute games for the same output proposal to // be created. - // Expected length: 0x46 (0x04 selector + 0x20 root claim + 0x20 extraData + 0x02 CWIA bytes) + // Expected length: 0x66 (0x04 selector + 0x20 root claim + 0x20 l1 head + 0x20 extraData + 0x02 CWIA bytes) assembly { - if gt(calldatasize(), 0x46) { + if gt(calldatasize(), 0x66) { // Store the selector for `ExtraDataTooLong()` & revert mstore(0x00, 0xc407e025) revert(0x1C, 0x04) @@ -496,12 +564,12 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { }) ); + // Deposit the bond. + WETH.deposit{ value: msg.value }(); + // Set the game's starting timestamp createdAt = Timestamp.wrap(uint64(block.timestamp)); - // Persist the blockhash of the parent block. - l1Head = Hash.wrap(blockhash(block.number - 1)); - // Set the game as initialized. initialized = true; } @@ -514,10 +582,47 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { /// @notice Returns the required bond for a given move kind. /// @param _position The position of the bonded interaction. /// @return requiredBond_ The required ETH bond for the given move, in wei. - function getRequiredBond(Position _position) public pure returns (uint256 requiredBond_) { - // TODO - _position; - requiredBond_ = 0; + function getRequiredBond(Position _position) public view returns (uint256 requiredBond_) { + uint256 depth = uint256(_position.depth()); + if (depth > MAX_GAME_DEPTH) revert GameDepthExceeded(); + + // Values taken from Big Bonds v1.5 (TM) spec. + uint256 assumedBaseFee = 200 gwei; + uint256 baseGasCharged = 400_000; + uint256 highGasCharged = 200_000_000; + + // Goal here is to compute the fixed multiplier that will be applied to the base gas + // charged to get the required gas amount for the given depth. We apply this multiplier + // some `n` times where `n` is the depth of the position. We are looking for some number + // that, when multiplied by itself `MAX_GAME_DEPTH` times and then multiplied by the base + // gas charged, will give us the maximum gas that we want to charge. + // We want to solve for (highGasCharged/baseGasCharged) ** (1/MAX_GAME_DEPTH). + // We know that a ** (b/c) is equal to e ** (ln(a) * (b/c)). + // We can compute e ** (ln(a) * (b/c)) quite easily with FixedPointMathLib. + + // Set up a, b, and c. + uint256 a = highGasCharged / baseGasCharged; + uint256 b = FixedPointMathLib.WAD; + uint256 c = MAX_GAME_DEPTH * FixedPointMathLib.WAD; + + // Compute ln(a). + // slither-disable-next-line divide-before-multiply + uint256 lnA = uint256(FixedPointMathLib.lnWad(int256(a * FixedPointMathLib.WAD))); + + // Computes (b / c) with full precision using WAD = 1e18. + uint256 bOverC = FixedPointMathLib.divWad(b, c); + + // Compute e ** (ln(a) * (b/c)) + // sMulWad can be used here since WAD = 1e18 maintains the same precision. + uint256 numerator = FixedPointMathLib.mulWad(lnA, bOverC); + int256 base = FixedPointMathLib.expWad(int256(numerator)); + + // Compute the required gas amount. + int256 rawGas = FixedPointMathLib.powWad(base, int256(depth * FixedPointMathLib.WAD)); + uint256 requiredGas = FixedPointMathLib.mulWad(baseGasCharged, uint256(rawGas)); + + // Compute the required bond. + requiredBond_ = assumedBaseFee * requiredGas; } /// @notice Claim the credit belonging to the recipient address. @@ -527,11 +632,25 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { uint256 recipientCredit = credit[_recipient]; credit[_recipient] = 0; + // Revert if the recipient has no credit to claim. + if (recipientCredit == 0) { + revert NoCreditToClaim(); + } + + // Try to withdraw the WETH amount so it can be used here. + WETH.withdraw(_recipient, recipientCredit); + // Transfer the credit to the recipient. (bool success,) = _recipient.call{ value: recipientCredit }(hex""); if (!success) revert BondTransferFailed(); } + /// @notice Returns the flag set in the `bond` field of a `ClaimData` struct to indicate that the bond has been + /// claimed. + function claimedBondFlag() external pure returns (uint128 claimedBondFlag_) { + claimedBondFlag_ = CLAIMED_BOND_FLAG; + } + //////////////////////////////////////////////////////////////// // IMMUTABLE GETTERS // //////////////////////////////////////////////////////////////// @@ -561,14 +680,14 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { vm_ = VM; } - /// @notice Returns the genesis block number. - function genesisBlockNumber() external view returns (uint256 genesisBlockNumber_) { - genesisBlockNumber_ = GENESIS_BLOCK_NUMBER; + /// @notice Returns the WETH contract for holding ETH. + function weth() external view returns (IDelayedWETH weth_) { + weth_ = WETH; } - /// @notice Returns the genesis output root. - function genesisOutputRoot() external view returns (Hash genesisOutputRoot_) { - genesisOutputRoot_ = GENESIS_OUTPUT_ROOT; + /// @notice Returns the chain ID of the L2 network this contract argues about. + function l2ChainId() external view returns (uint256 l2ChainId_) { + l2ChainId_ = L2_CHAIN_ID; } //////////////////////////////////////////////////////////////// @@ -581,11 +700,14 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { function _distributeBond(address _recipient, ClaimData storage _bonded) internal { // Set all bits in the bond value to indicate that the bond has been paid out. uint256 bond = _bonded.bond; - if (bond == type(uint128).max) revert ClaimAlreadyResolved(); - _bonded.bond = type(uint128).max; + if (bond == CLAIMED_BOND_FLAG) revert ClaimAlreadyResolved(); + _bonded.bond = CLAIMED_BOND_FLAG; // Increase the recipient's credit. credit[_recipient] += bond; + + // Unlock the bond. + WETH.unlock(_recipient, bond); } /// @notice Verifies the integrity of an execution bisection subgame's root claim. Reverts if the claim @@ -703,14 +825,14 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { // 2. If it was a defense, the starting output root is `claim`, and the disputed output root is // elsewhere in the DAG (it must commit to the block # index at depth of `outputPos + 1`). if (wasAttack) { - // If this is an attack on the first output root (the block directly after genesis), the - // starting claim nor position exists in the tree. We leave these as 0, which can be easily - // identified due to 0 being an invalid Gindex. + // If this is an attack on the first output root (the block directly after the starting + // block number), the starting claim nor position exists in the tree. We leave these as + // 0, which can be easily identified due to 0 being an invalid Gindex. if (outputPos.indexAtDepth() > 0) { ClaimData storage starting = _findTraceAncestor(Position.wrap(outputPos.raw() - 1), claimIdx, true); (startingClaim_, startingPos_) = (starting.claim, starting.position); } else { - startingClaim_ = Claim.wrap(GENESIS_OUTPUT_ROOT.raw()); + startingClaim_ = Claim.wrap(startingOutputRoot.root.raw()); } (disputedClaim_, disputedPos_) = (claim.claim, claim.position); } else { diff --git a/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol b/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol new file mode 100644 index 000000000000..6063eb0e5476 --- /dev/null +++ b/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; +import { FaultDisputeGame, IFaultDisputeGame, IBigStepper, IInitializable } from "src/dispute/FaultDisputeGame.sol"; +import "src/libraries/DisputeTypes.sol"; +import "src/libraries/DisputeErrors.sol"; + +/// @title PermissionedDisputeGame +/// @notice PermissionedDisputeGame is a contract that inherits from `FaultDisputeGame`, and contains two roles: +/// - The `challenger` role, which is allowed to challenge a dispute. +/// - The `proposer` role, which is allowed to create proposals and participate in their game. +/// This contract exists as a way for networks to support the fault proof iteration of the OptimismPortal +/// contract without needing to support a fully permissionless system. Permissionless systems can introduce +/// costs that certain networks may not wish to support. This contract can also be used as a fallback mechanism +/// in case of a failure in the permissionless fault proof system in the stage one release. +contract PermissionedDisputeGame is FaultDisputeGame { + /// @notice The proposer role is allowed to create proposals and participate in the dispute game. + address internal immutable PROPOSER; + + /// @notice The challenger role is allowed to participate in the dispute game. + address internal immutable CHALLENGER; + + /// @notice Modifier that gates access to the `challenger` and `proposer` roles. + modifier onlyAuthorized() { + if (!(msg.sender == PROPOSER || msg.sender == CHALLENGER)) { + revert BadAuth(); + } + _; + } + + /// @param _gameType The type ID of the game. + /// @param _absolutePrestate The absolute prestate of the instruction trace. + /// @param _maxGameDepth The maximum depth of bisection. + /// @param _splitDepth The final depth of the output bisection portion of the game. + /// @param _gameDuration The duration of the game. + /// @param _vm An onchain VM that performs single instruction steps on an FPP trace. + /// @param _weth WETH contract for holding ETH. + /// @param _anchorStateRegistry The contract that stores the anchor state for each game type. + /// @param _l2ChainId Chain ID of the L2 network this contract argues about. + /// @param _proposer Address that is allowed to create instances of this contract. + /// @param _challenger Address that is allowed to challenge instances of this contract. + constructor( + GameType _gameType, + Claim _absolutePrestate, + uint256 _maxGameDepth, + uint256 _splitDepth, + Duration _gameDuration, + IBigStepper _vm, + IDelayedWETH _weth, + IAnchorStateRegistry _anchorStateRegistry, + uint256 _l2ChainId, + address _proposer, + address _challenger + ) + FaultDisputeGame( + _gameType, + _absolutePrestate, + _maxGameDepth, + _splitDepth, + _gameDuration, + _vm, + _weth, + _anchorStateRegistry, + _l2ChainId + ) + { + PROPOSER = _proposer; + CHALLENGER = _challenger; + } + + /// @inheritdoc IFaultDisputeGame + function step( + uint256 _claimIndex, + bool _isAttack, + bytes calldata _stateData, + bytes calldata _proof + ) + public + override + onlyAuthorized + { + super.step(_claimIndex, _isAttack, _stateData, _proof); + } + + /// @notice Generic move function, used for both `attack` and `defend` moves. + /// @param _challengeIndex The index of the claim being moved against. + /// @param _claim The claim at the next logical position in the game. + /// @param _isAttack Whether or not the move is an attack or defense. + function move(uint256 _challengeIndex, Claim _claim, bool _isAttack) public payable override onlyAuthorized { + super.move(_challengeIndex, _claim, _isAttack); + } + + /// @inheritdoc IInitializable + function initialize() public payable override { + // The creator of the dispute game must be the proposer EOA. + if (tx.origin != PROPOSER) revert BadAuth(); + + // Fallthrough initialization. + super.initialize(); + } +} diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IAnchorStateRegistry.sol b/packages/contracts-bedrock/src/dispute/interfaces/IAnchorStateRegistry.sol new file mode 100644 index 000000000000..b10a9dc7712e --- /dev/null +++ b/packages/contracts-bedrock/src/dispute/interfaces/IAnchorStateRegistry.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; + +import "src/libraries/DisputeTypes.sol"; + +/// @title IAnchorStateRegistry +/// @notice Describes a contract that stores the anchor state for each game type. +interface IAnchorStateRegistry { + /// @notice Returns the anchor state for the given game type. + /// @param _gameType The game type to get the anchor state for. + /// @return The anchor state for the given game type. + function anchors(GameType _gameType) external view returns (Hash, uint256); + + /// @notice Returns the DisputeGameFactory address. + /// @return DisputeGameFactory address. + function disputeGameFactory() external view returns (IDisputeGameFactory); + + /// @notice Callable by FaultDisputeGame contracts to update the anchor state. Pulls the anchor state directly from + /// the FaultDisputeGame contract and stores it in the registry if the new anchor state is valid and the + /// state is newer than the current anchor state. + function tryUpdateAnchorState() external; +} diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IBigStepper.sol b/packages/contracts-bedrock/src/dispute/interfaces/IBigStepper.sol index 8b32d7c555f6..f38e58f9d9d6 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IBigStepper.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IBigStepper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; +pragma solidity ^0.8.0; import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IDelayedWETH.sol b/packages/contracts-bedrock/src/dispute/interfaces/IDelayedWETH.sol new file mode 100644 index 000000000000..80b90c69b860 --- /dev/null +++ b/packages/contracts-bedrock/src/dispute/interfaces/IDelayedWETH.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IWETH } from "src/dispute/interfaces/IWETH.sol"; + +/// @title IDelayedWETH +/// @notice Interface for the DelayedWETH contract. +interface IDelayedWETH is IWETH { + /// @notice Represents a withdrawal request. + struct WithdrawalRequest { + uint256 amount; + uint256 timestamp; + } + + /// @notice Emitted when an unwrap is started. + /// @param src The address that started the unwrap. + /// @param wad The amount of WETH that was unwrapped. + event Unwrap(address indexed src, uint256 wad); + + /// @notice Returns the withdrawal delay in seconds. + /// @return The withdrawal delay in seconds. + function delay() external view returns (uint256); + + /// @notice Returns a withdrawal request for the given address. + /// @param _owner The address to query the withdrawal request of. + /// @param _guy Sub-account to query the withdrawal request of. + /// @return The withdrawal request for the given address-subaccount pair. + function withdrawals(address _owner, address _guy) external view returns (uint256, uint256); + + /// @notice Unlocks withdrawals for the sender's account, after a time delay. + /// @param _guy Sub-account to unlock. + /// @param _wad The amount of WETH to unlock. + function unlock(address _guy, uint256 _wad) external; + + /// @notice Extension to withdrawal, must provide a sub-account to withdraw from. + /// @param _guy Sub-account to withdraw from. + /// @param _wad The amount of WETH to withdraw. + function withdraw(address _guy, uint256 _wad) external; + + /// @notice Allows the owner to recover from error cases by pulling ETH out of the contract. + /// @param _wad The amount of WETH to recover. + function recover(uint256 _wad) external; + + /// @notice Allows the owner to recover from error cases by pulling ETH from a specific owner. + /// @param _guy The address to recover the WETH from. + /// @param _wad The amount of WETH to recover. + function hold(address _guy, uint256 _wad) external; +} diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGame.sol b/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGame.sol index a692492c894b..c9d18ad96ed4 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGame.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; +pragma solidity ^0.8.0; import { IInitializable } from "src/dispute/interfaces/IInitializable.sol"; @@ -16,6 +16,10 @@ interface IDisputeGame is IInitializable { /// @return createdAt_ The timestamp that the DisputeGame contract was created at. function createdAt() external view returns (Timestamp createdAt_); + /// @notice Returns the timestamp that the DisputeGame contract was resolved at. + /// @return resolvedAt_ The timestamp that the DisputeGame contract was resolved at. + function resolvedAt() external view returns (Timestamp resolvedAt_); + /// @notice Returns the current status of the game. /// @return status_ The current status of the game. function status() external view returns (GameStatus status_); diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGameFactory.sol b/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGameFactory.sol index d468a91f4f6d..e528057e8add 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGameFactory.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGameFactory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; +pragma solidity ^0.8.0; import { IDisputeGame } from "./IDisputeGame.sol"; @@ -24,6 +24,15 @@ interface IDisputeGameFactory { /// @param newBond The new bond (in wei) for initializing the game type. event InitBondUpdated(GameType indexed gameType, uint256 indexed newBond); + /// @notice Information about a dispute game found in a `findLatestGames` search. + struct GameSearchResult { + uint256 index; + GameId metadata; + Timestamp timestamp; + Claim rootClaim; + bytes extraData; + } + /// @notice The total number of dispute games created by this factory. /// @return gameCount_ The total number of dispute games created by this factory. function gameCount() external view returns (uint256 gameCount_); @@ -111,4 +120,18 @@ interface IDisputeGameFactory { external pure returns (Hash uuid_); + + /// @notice Finds the `_n` most recent `GameId`'s of type `_gameType` starting at `_start`. If there are less than + /// `_n` games of type `_gameType` starting at `_start`, then the returned array will be shorter than `_n`. + /// @param _gameType The type of game to find. + /// @param _start The index to start the reverse search from. + /// @param _n The number of games to find. + function findLatestGames( + GameType _gameType, + uint256 _start, + uint256 _n + ) + external + view + returns (GameSearchResult[] memory games_); } diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol b/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol index d53107e3bace..355140ab338b 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; +pragma solidity ^0.8.0; import { IDisputeGame } from "./IDisputeGame.sol"; @@ -67,4 +67,13 @@ interface IFaultDisputeGame is IDisputeGame { /// @notice The l2BlockNumber of the disputed output root in the `L2OutputOracle`. function l2BlockNumber() external view returns (uint256 l2BlockNumber_); + + /// @notice Starting output root and block number of the game. + function startingOutputRoot() external view returns (Hash startingRoot_, uint256 l2BlockNumber_); + + /// @notice Only the starting block number of the game. + function startingBlockNumber() external view returns (uint256 startingBlockNumber_); + + /// @notice Only the starting output root of the game. + function startingRootHash() external view returns (Hash startingRootHash_); } diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IInitializable.sol b/packages/contracts-bedrock/src/dispute/interfaces/IInitializable.sol index c2ca15f0d144..5968b45f9bfb 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IInitializable.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IInitializable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; +pragma solidity ^0.8.0; /// @title IInitializable /// @notice An interface for initializable contracts. diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IWETH.sol b/packages/contracts-bedrock/src/dispute/interfaces/IWETH.sol new file mode 100644 index 000000000000..0d736ecac73a --- /dev/null +++ b/packages/contracts-bedrock/src/dispute/interfaces/IWETH.sol @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title IWETH +/// @notice Interface for WETH9. +interface IWETH { + /// @notice Emitted when an approval is made. + /// @param src The address that approved the transfer. + /// @param guy The address that was approved to transfer. + /// @param wad The amount that was approved to transfer. + event Approval(address indexed src, address indexed guy, uint256 wad); + + /// @notice Emitted when a transfer is made. + /// @param src The address that transferred the WETH. + /// @param dst The address that received the WETH. + /// @param wad The amount of WETH that was transferred. + event Transfer(address indexed src, address indexed dst, uint256 wad); + + /// @notice Emitted when a deposit is made. + /// @param dst The address that deposited the WETH. + /// @param wad The amount of WETH that was deposited. + event Deposit(address indexed dst, uint256 wad); + + /// @notice Emitted when a withdrawal is made. + /// @param src The address that withdrew the WETH. + /// @param wad The amount of WETH that was withdrawn. + event Withdrawal(address indexed src, uint256 wad); + + /// @notice Returns the name of the token. + /// @return The name of the token. + function name() external pure returns (string memory); + + /// @notice Returns the symbol of the token. + /// @return The symbol of the token. + function symbol() external pure returns (string memory); + + /// @notice Returns the number of decimals the token uses. + /// @return The number of decimals the token uses. + function decimals() external pure returns (uint8); + + /// @notice Returns the balance of the given address. + /// @param owner The address to query the balance of. + /// @return The balance of the given address. + function balanceOf(address owner) external view returns (uint256); + + /// @notice Returns the amount of WETH that the spender can transfer on behalf of the owner. + /// @param owner The address that owns the WETH. + /// @param spender The address that is approved to transfer the WETH. + /// @return The amount of WETH that the spender can transfer on behalf of the owner. + function allowance(address owner, address spender) external view returns (uint256); + + /// @notice Allows WETH to be deposited by sending ether to the contract. + function deposit() external payable; + + /// @notice Withdraws an amount of ETH. + /// @param wad The amount of ETH to withdraw. + function withdraw(uint256 wad) external; + + /// @notice Returns the total supply of WETH. + /// @return The total supply of WETH. + function totalSupply() external view returns (uint256); + + /// @notice Approves the given address to transfer the WETH on behalf of the caller. + /// @param guy The address that is approved to transfer the WETH. + /// @param wad The amount that is approved to transfer. + /// @return True if the approval was successful. + function approve(address guy, uint256 wad) external returns (bool); + + /// @notice Transfers the given amount of WETH to the given address. + /// @param dst The address to transfer the WETH to. + /// @param wad The amount of WETH to transfer. + /// @return True if the transfer was successful. + function transfer(address dst, uint256 wad) external returns (bool); + + /// @notice Transfers the given amount of WETH from the given address to the given address. + /// @param src The address to transfer the WETH from. + /// @param dst The address to transfer the WETH to. + /// @param wad The amount of WETH to transfer. + /// @return True if the transfer was successful. + function transferFrom(address src, address dst, uint256 wad) external returns (bool); +} diff --git a/packages/contracts-bedrock/src/dispute/lib/LibGameId.sol b/packages/contracts-bedrock/src/dispute/lib/LibGameId.sol index a96d81e0df73..2a4657b3246e 100644 --- a/packages/contracts-bedrock/src/dispute/lib/LibGameId.sol +++ b/packages/contracts-bedrock/src/dispute/lib/LibGameId.sol @@ -22,7 +22,7 @@ library LibGameId { returns (GameId gameId_) { assembly { - gameId_ := or(or(shl(248, _gameType), shl(184, _timestamp)), _gameProxy) + gameId_ := or(or(shl(224, _gameType), shl(160, _timestamp)), _gameProxy) } } @@ -37,9 +37,9 @@ library LibGameId { returns (GameType gameType_, Timestamp timestamp_, IDisputeGame gameProxy_) { assembly { - gameType_ := shr(248, _gameId) - timestamp_ := shr(184, and(_gameId, not(shl(248, 0xff)))) - gameProxy_ := and(_gameId, 0xffffffffffffffffffffffffffffffffffffffff) + gameType_ := shr(224, _gameId) + timestamp_ := and(shr(160, _gameId), 0xFFFFFFFFFFFFFFFF) + gameProxy_ := and(_gameId, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) } } } diff --git a/packages/contracts-bedrock/src/dispute/lib/LibPosition.sol b/packages/contracts-bedrock/src/dispute/lib/LibPosition.sol index f3b4f2e71ae9..abf79fb51b06 100644 --- a/packages/contracts-bedrock/src/dispute/lib/LibPosition.sol +++ b/packages/contracts-bedrock/src/dispute/lib/LibPosition.sol @@ -166,8 +166,8 @@ library LibPosition { } /// @notice Get the move position of `_position`, which is the left child of: - /// 1. `_position + 1` if `_isAttack` is true. - /// 1. `_position` if `_isAttack` is false. + /// 1. `_position` if `_isAttack` is true. + /// 2. `_position | 1` if `_isAttack` is false. /// @param _position The position to get the relative attack/defense position of. /// @param _isAttack Whether or not the move is an attack move. /// @return move_ The move position relative to `position`. diff --git a/packages/contracts-bedrock/src/dispute/weth/DelayedWETH.sol b/packages/contracts-bedrock/src/dispute/weth/DelayedWETH.sol new file mode 100644 index 000000000000..7a3d5bb6dece --- /dev/null +++ b/packages/contracts-bedrock/src/dispute/weth/DelayedWETH.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { ISemver } from "src/universal/ISemver.sol"; + +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; +import { IWETH } from "src/dispute/interfaces/IWETH.sol"; +import { WETH98 } from "src/dispute/weth/WETH98.sol"; + +import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; + +/// @title DelayedWETH +/// @notice DelayedWETH is an extension to WETH9 that allows for delayed withdrawals. Accounts must trigger an unlock +/// function before they can withdraw WETH. Accounts must trigger unlock by specifying a sub-account and an +/// amount of WETH to unlock. Accounts can trigger the unlock function at any time, but must wait a delay +/// period before they can withdraw after the unlock function is triggered. DelayedWETH is designed to be used +/// by the DisputeGame contracts where unlock will only be triggered after a dispute is resolved. DelayedWETH +/// is meant to sit behind a proxy contract and has an owner address that can pull WETH from any account and +/// can recover ETH from the contract itself. Variable and function naming vaguely follows the vibe of WETH9. +/// Not the prettiest contract in the world, but it gets the job done. +contract DelayedWETH is OwnableUpgradeable, WETH98, IDelayedWETH, ISemver { + /// @notice Semantic version. + /// @custom:semver 0.2.0 + string public constant version = "0.2.0"; + + /// @inheritdoc IDelayedWETH + mapping(address => mapping(address => WithdrawalRequest)) public withdrawals; + + /// @notice Withdrawal delay in seconds. + uint256 internal immutable DELAY_SECONDS; + + /// @notice Address of the SuperchainConfig contract. + SuperchainConfig public config; + + /// @param _delay The delay for withdrawals in seconds. + constructor(uint256 _delay) { + DELAY_SECONDS = _delay; + initialize({ _owner: address(0), _config: SuperchainConfig(address(0)) }); + } + + /// @notice Initializes the contract. + /// @param _owner The address of the owner. + /// @param _config Address of the SuperchainConfig contract. + function initialize(address _owner, SuperchainConfig _config) public initializer { + __Ownable_init(); + _transferOwnership(_owner); + config = _config; + } + + /// @inheritdoc IDelayedWETH + function delay() external view returns (uint256) { + return DELAY_SECONDS; + } + + /// @inheritdoc IDelayedWETH + function unlock(address _guy, uint256 _wad) external { + // Note that the unlock function can be called by any address, but the actual unlocking capability still only + // gives the msg.sender the ability to withdraw from the account. As long as the unlock and withdraw functions + // are called with the proper recipient addresses, this will be safe. Could be made safer by having external + // accounts execute withdrawals themselves but that would have added extra complexity and made DelayedWETH a + // leaky abstraction, so we chose this instead. + WithdrawalRequest storage wd = withdrawals[msg.sender][_guy]; + wd.timestamp = block.timestamp; + wd.amount += _wad; + } + + /// @inheritdoc IWETH + function withdraw(uint256 _wad) public override(WETH98, IWETH) { + withdraw(msg.sender, _wad); + } + + /// @inheritdoc IDelayedWETH + function withdraw(address _guy, uint256 _wad) public { + require(!config.paused(), "DelayedWETH: contract is paused"); + WithdrawalRequest storage wd = withdrawals[msg.sender][_guy]; + require(wd.amount >= _wad, "DelayedWETH: insufficient unlocked withdrawal"); + require(wd.timestamp > 0, "DelayedWETH: withdrawal not unlocked"); + require(wd.timestamp + DELAY_SECONDS <= block.timestamp, "DelayedWETH: withdrawal delay not met"); + wd.amount -= _wad; + super.withdraw(_wad); + } + + /// @inheritdoc IDelayedWETH + function recover(uint256 _wad) external { + require(msg.sender == owner(), "DelayedWETH: not owner"); + uint256 amount = _wad < address(this).balance ? _wad : address(this).balance; + payable(msg.sender).transfer(amount); + } + + /// @inheritdoc IDelayedWETH + function hold(address _guy, uint256 _wad) external { + require(msg.sender == owner(), "DelayedWETH: not owner"); + allowance[_guy][msg.sender] = _wad; + emit Approval(_guy, msg.sender, _wad); + } +} diff --git a/packages/contracts-bedrock/src/dispute/weth/WETH98.sol b/packages/contracts-bedrock/src/dispute/weth/WETH98.sol new file mode 100644 index 000000000000..c52291e0982b --- /dev/null +++ b/packages/contracts-bedrock/src/dispute/weth/WETH98.sol @@ -0,0 +1,85 @@ +// Copyright (C) 2015, 2016, 2017 Dapphub + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// Based on WETH9 by Dapphub. +// Modified by OP Labs. + +pragma solidity 0.8.15; + +import { IWETH } from "src/dispute/interfaces/IWETH.sol"; + +/// @title WETH98 +/// @notice WETH98 is a version of WETH9 upgraded for Solidity 0.8.x. +contract WETH98 is IWETH { + string public constant name = "Wrapped Ether"; + string public constant symbol = "WETH"; + uint8 public constant decimals = 18; + + mapping(address => uint256) public balanceOf; + mapping(address => mapping(address => uint256)) public allowance; + + /// @notice Pipes to deposit. + receive() external payable { + deposit(); + } + + /// @inheritdoc IWETH + function deposit() public payable { + balanceOf[msg.sender] += msg.value; + emit Deposit(msg.sender, msg.value); + } + + /// @inheritdoc IWETH + function withdraw(uint256 wad) public virtual { + require(balanceOf[msg.sender] >= wad); + balanceOf[msg.sender] -= wad; + payable(msg.sender).transfer(wad); + emit Withdrawal(msg.sender, wad); + } + + /// @inheritdoc IWETH + function totalSupply() external view returns (uint256) { + return address(this).balance; + } + + /// @inheritdoc IWETH + function approve(address guy, uint256 wad) external returns (bool) { + allowance[msg.sender][guy] = wad; + emit Approval(msg.sender, guy, wad); + return true; + } + + /// @inheritdoc IWETH + function transfer(address dst, uint256 wad) external returns (bool) { + return transferFrom(msg.sender, dst, wad); + } + + /// @inheritdoc IWETH + function transferFrom(address src, address dst, uint256 wad) public returns (bool) { + require(balanceOf[src] >= wad); + + if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) { + require(allowance[src][msg.sender] >= wad); + allowance[src][msg.sender] -= wad; + } + + balanceOf[src] -= wad; + balanceOf[dst] += wad; + + emit Transfer(src, dst, wad); + + return true; + } +} diff --git a/packages/contracts-bedrock/src/legacy/L1BlockNumber.sol b/packages/contracts-bedrock/src/legacy/L1BlockNumber.sol index a82ddaa5806e..8bd2e2a8f315 100644 --- a/packages/contracts-bedrock/src/legacy/L1BlockNumber.sol +++ b/packages/contracts-bedrock/src/legacy/L1BlockNumber.sol @@ -28,7 +28,6 @@ contract L1BlockNumber is ISemver { } /// @notice Returns the L1 block number. - // solhint-disable-next-line no-complex-fallback fallback() external payable { uint256 l1BlockNumber = getL1BlockNumber(); assembly { diff --git a/packages/contracts-bedrock/src/legacy/LegacyERC20ETH.sol b/packages/contracts-bedrock/src/legacy/LegacyERC20ETH.sol deleted file mode 100644 index 9f6545774d3c..000000000000 --- a/packages/contracts-bedrock/src/legacy/LegacyERC20ETH.sol +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; - -/// @custom:legacy -/// @custom:proxied -/// @custom:predeploy 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000 -/// @title LegacyERC20ETH -/// @notice LegacyERC20ETH is a legacy contract that held ETH balances before the Bedrock upgrade. -/// All ETH balances held within this contract were migrated to the state trie as part of -/// the Bedrock upgrade. Functions within this contract that mutate state were already -/// disabled as part of the EVM equivalence upgrade. -contract LegacyERC20ETH is OptimismMintableERC20 { - /// @notice Initializes the contract as an Optimism Mintable ERC20. - constructor() OptimismMintableERC20(Predeploys.L2_STANDARD_BRIDGE, address(0), "Ether", "ETH", 18) { } - - /// @notice Returns the ETH balance of the target account. Overrides the base behavior of the - /// contract to preserve the invariant that the balance within this contract always - /// matches the balance in the state trie. - /// @param _who Address of the account to query. - /// @return The ETH balance of the target account. - function balanceOf(address _who) public view virtual override returns (uint256) { - return address(_who).balance; - } - - /// @custom:blocked - /// @notice Mints some amount of ETH. - function mint(address, uint256) public virtual override { - revert("LegacyERC20ETH: mint is disabled"); - } - - /// @custom:blocked - /// @notice Burns some amount of ETH. - function burn(address, uint256) public virtual override { - revert("LegacyERC20ETH: burn is disabled"); - } - - /// @custom:blocked - /// @notice Transfers some amount of ETH. - function transfer(address, uint256) public virtual override returns (bool) { - revert("LegacyERC20ETH: transfer is disabled"); - } - - /// @custom:blocked - /// @notice Approves a spender to spend some amount of ETH. - function approve(address, uint256) public virtual override returns (bool) { - revert("LegacyERC20ETH: approve is disabled"); - } - - /// @custom:blocked - /// @notice Transfers funds from some sender account. - function transferFrom(address, address, uint256) public virtual override returns (bool) { - revert("LegacyERC20ETH: transferFrom is disabled"); - } - - /// @custom:blocked - /// @notice Increases the allowance of a spender. - function increaseAllowance(address, uint256) public virtual override returns (bool) { - revert("LegacyERC20ETH: increaseAllowance is disabled"); - } - - /// @custom:blocked - /// @notice Decreases the allowance of a spender. - function decreaseAllowance(address, uint256) public virtual override returns (bool) { - revert("LegacyERC20ETH: decreaseAllowance is disabled"); - } -} diff --git a/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol b/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol index e668c74ffa5e..c735339a6bb8 100644 --- a/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol +++ b/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol @@ -30,7 +30,6 @@ contract ResolvedDelegateProxy { } /// @notice Fallback, performs a delegatecall to the resolved implementation address. - // solhint-disable-next-line no-complex-fallback fallback() external payable { address target = addressManager[address(this)].getAddress((implementationName[address(this)])); diff --git a/packages/contracts-bedrock/src/libraries/DisputeErrors.sol b/packages/contracts-bedrock/src/libraries/DisputeErrors.sol index 1f35729170d2..382c05c43af9 100644 --- a/packages/contracts-bedrock/src/libraries/DisputeErrors.sol +++ b/packages/contracts-bedrock/src/libraries/DisputeErrors.sol @@ -30,6 +30,9 @@ error AlreadyInitialized(); /// @notice Thrown when a supplied bond is too low to cover the cost of the interaction. error InsufficientBond(); +/// @notice Thrown when a credit claim is attempted for a value of 0. +error NoCreditToClaim(); + /// @notice Thrown when the transfer of credit to a recipient account reverts. error BondTransferFailed(); @@ -87,3 +90,17 @@ error ClaimAboveSplit(); /// @notice Thrown on deployment if the split depth is greater than or equal to the max /// depth of the game. error InvalidSplitDepth(); + +/// @notice Thrown when trying to step against a claim for a second time, after it has already been countered with +/// an instruction step. +error DuplicateStep(); + +/// @notice Thrown when an anchor root is not found for a given game type. +error AnchorRootNotFound(); + +//////////////////////////////////////////////////////////////// +// `PermissionedDisputeGame` Errors // +//////////////////////////////////////////////////////////////// + +/// @notice Thrown when an unauthorized address attempts to interact with the game. +error BadAuth(); diff --git a/packages/contracts-bedrock/src/libraries/DisputeTypes.sol b/packages/contracts-bedrock/src/libraries/DisputeTypes.sol index a88819366d36..2480812049c5 100644 --- a/packages/contracts-bedrock/src/libraries/DisputeTypes.sol +++ b/packages/contracts-bedrock/src/libraries/DisputeTypes.sol @@ -74,7 +74,7 @@ type Clock is uint128; type Position is uint128; /// @notice A `GameType` represents the type of game being played. -type GameType is uint8; +type GameType is uint32; /// @notice A `VMStatus` represents the status of a VM execution. type VMStatus is uint8; @@ -89,12 +89,23 @@ enum GameStatus { DEFENDER_WINS } +/// @notice Represents an L2 output root and the L2 block number at which it was generated. +/// @custom:field root The output root. +/// @custom:field l2BlockNumber The L2 block number at which the output root was generated. +struct OutputRoot { + Hash root; + uint256 l2BlockNumber; +} + /// @title GameTypes /// @notice A library that defines the IDs of games that can be played. library GameTypes { /// @dev A dispute game type the uses the cannon vm. GameType internal constant CANNON = GameType.wrap(0); + /// @dev A permissioned dispute game type the uses the cannon vm. + GameType internal constant PERMISSIONED_CANNON = GameType.wrap(1); + /// @notice A dispute game type that uses an alphabet vm. /// Not intended for production use. GameType internal constant ALPHABET = GameType.wrap(255); @@ -128,8 +139,8 @@ library LocalPreimageKey { /// @notice The identifier for the disputed output root. uint256 internal constant DISPUTED_OUTPUT_ROOT = 0x03; - /// @notice The identifier for the starting L2 block number. - uint256 internal constant STARTING_L2_BLOCK_NUMBER = 0x04; + /// @notice The identifier for the disputed L2 block number. + uint256 internal constant DISPUTED_L2_BLOCK_NUMBER = 0x04; /// @notice The identifier for the chain ID. uint256 internal constant CHAIN_ID = 0x05; diff --git a/packages/contracts-bedrock/src/libraries/rlp/RLPReader.sol b/packages/contracts-bedrock/src/libraries/rlp/RLPReader.sol index 34d446f7d5c2..179c8f4c7624 100644 --- a/packages/contracts-bedrock/src/libraries/rlp/RLPReader.sol +++ b/packages/contracts-bedrock/src/libraries/rlp/RLPReader.sol @@ -248,7 +248,6 @@ library RLPReader { } // Mostly based on Solidity's copy_memory_to_memory: - // solhint-disable max-line-length // https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114 uint256 src = MemoryPointer.unwrap(_src) + _offset; assembly { diff --git a/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol b/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol index 7429e23fa4fd..b5048d5c7bcc 100644 --- a/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol @@ -360,7 +360,6 @@ abstract contract CrossDomainMessenger is /// @notice Initializer. /// @param _otherMessenger CrossDomainMessenger contract on the other chain. - // solhint-disable-next-line func-name-mixedcase function __CrossDomainMessenger_init(CrossDomainMessenger _otherMessenger) internal onlyInitializing { // We only want to set the xDomainMsgSender to the default value if it hasn't been initialized yet, // meaning that this is a fresh contract deployment. diff --git a/packages/contracts-bedrock/src/universal/ERC721Bridge.sol b/packages/contracts-bedrock/src/universal/ERC721Bridge.sol index a01dfe7a8212..d62c612fca1a 100644 --- a/packages/contracts-bedrock/src/universal/ERC721Bridge.sol +++ b/packages/contracts-bedrock/src/universal/ERC721Bridge.sol @@ -69,7 +69,6 @@ abstract contract ERC721Bridge is Initializable { /// @notice Initializer. /// @param _messenger Contract of the CrossDomainMessenger on this network. /// @param _otherBridge Contract of the ERC721 bridge on the other network. - // solhint-disable-next-line func-name-mixedcase function __ERC721Bridge_init( CrossDomainMessenger _messenger, StandardBridge _otherBridge diff --git a/packages/contracts-bedrock/src/universal/Proxy.sol b/packages/contracts-bedrock/src/universal/Proxy.sol index 0325a61d3aab..b50b08efca83 100644 --- a/packages/contracts-bedrock/src/universal/Proxy.sol +++ b/packages/contracts-bedrock/src/universal/Proxy.sol @@ -35,7 +35,7 @@ contract Proxy { /// @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. - /// @param _admin Address of the initial contract admin. Admin as the ability to access the + /// @param _admin Address of the initial contract admin. Admin has the ability to access the /// transparent proxy interface. constructor(address _admin) { _changeAdmin(_admin); diff --git a/packages/contracts-bedrock/src/universal/StandardBridge.sol b/packages/contracts-bedrock/src/universal/StandardBridge.sol index 4c2dae829508..2c2c8c241b0b 100644 --- a/packages/contracts-bedrock/src/universal/StandardBridge.sol +++ b/packages/contracts-bedrock/src/universal/StandardBridge.sol @@ -114,7 +114,6 @@ abstract contract StandardBridge is Initializable { /// @notice Initializer. /// @param _messenger Contract for CrossDomainMessenger on this network. /// @param _otherBridge Contract for the other StandardBridge contract. - // solhint-disable-next-line func-name-mixedcase function __StandardBridge_init( CrossDomainMessenger _messenger, StandardBridge _otherBridge diff --git a/packages/contracts-bedrock/test/L1/DataAvailabilityChallenge.t.sol b/packages/contracts-bedrock/test/L1/DataAvailabilityChallenge.t.sol new file mode 100644 index 000000000000..34e98be77bae --- /dev/null +++ b/packages/contracts-bedrock/test/L1/DataAvailabilityChallenge.t.sol @@ -0,0 +1,534 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { + DataAvailabilityChallenge, + ChallengeStatus, + Challenge, + CommitmentType, + computeCommitmentKeccak256 +} from "src/L1/DataAvailabilityChallenge.sol"; +import { Proxy } from "src/universal/Proxy.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; + +contract DataAvailabilityChallengeTest is CommonTest { + function setUp() public virtual override { + super.enablePlasma(); + super.setUp(); + } + + function testDeposit() public { + assertEq(dataAvailabilityChallenge.balances(address(this)), 0); + dataAvailabilityChallenge.deposit{ value: 1000 }(); + assertEq(dataAvailabilityChallenge.balances(address(this)), 1000); + } + + function testReceive() public { + assertEq(dataAvailabilityChallenge.balances(address(this)), 0); + (bool success,) = payable(address(dataAvailabilityChallenge)).call{ value: 1000 }(""); + assertTrue(success); + assertEq(dataAvailabilityChallenge.balances(address(this)), 1000); + } + + function testWithdraw(address sender, uint256 amount) public { + assumePayable(sender); + assumeNotPrecompile(sender); + vm.assume(sender != address(dataAvailabilityChallenge)); + vm.assume(sender.balance == 0); + vm.deal(sender, amount); + + vm.prank(sender); + dataAvailabilityChallenge.deposit{ value: amount }(); + + assertEq(dataAvailabilityChallenge.balances(sender), amount); + assertEq(sender.balance, 0); + + vm.prank(sender); + dataAvailabilityChallenge.withdraw(); + + assertEq(dataAvailabilityChallenge.balances(sender), 0); + assertEq(sender.balance, amount); + } + + function testChallengeSuccess(address challenger, uint256 challengedBlockNumber, bytes calldata preImage) public { + bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); + + // Assume the challenger is not the 0 address + vm.assume(challenger != address(0)); + + // Assume the block number is not close to the max uint256 value + vm.assume( + challengedBlockNumber + < type(uint256).max - dataAvailabilityChallenge.challengeWindow() + - dataAvailabilityChallenge.resolveWindow() + ); + uint256 requiredBond = dataAvailabilityChallenge.bondSize(); + + // Move to a block after the challenged block + vm.roll(challengedBlockNumber + 1); + + // Deposit the required bond + vm.deal(challenger, requiredBond); + vm.prank(challenger); + dataAvailabilityChallenge.deposit{ value: requiredBond }(); + + // Expect the challenge status to be uninitialized + assertEq( + uint8(dataAvailabilityChallenge.getChallengeStatus(challengedBlockNumber, challengedCommitment)), + uint8(ChallengeStatus.Uninitialized) + ); + + // Challenge a (blockNumber,hash) tuple + vm.prank(challenger); + dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); + + // Challenge should have been created + Challenge memory challenge = dataAvailabilityChallenge.getChallenge(challengedBlockNumber, challengedCommitment); + assertEq(challenge.challenger, challenger); + assertEq(challenge.startBlock, block.number); + assertEq(challenge.resolvedBlock, 0); + assertEq(challenge.lockedBond, requiredBond); + assertEq( + uint8(dataAvailabilityChallenge.getChallengeStatus(challengedBlockNumber, challengedCommitment)), + uint8(ChallengeStatus.Active) + ); + + // Challenge should have decreased the challenger's bond size + assertEq(dataAvailabilityChallenge.balances(challenger), 0); + } + + function testChallengeDeposit(address challenger, uint256 challengedBlockNumber, bytes memory preImage) public { + bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); + + // Assume the challenger is not the 0 address + vm.assume(challenger != address(0)); + + // Assume the block number is not close to the max uint256 value + vm.assume( + challengedBlockNumber + < type(uint256).max - dataAvailabilityChallenge.challengeWindow() + - dataAvailabilityChallenge.resolveWindow() + ); + uint256 requiredBond = dataAvailabilityChallenge.bondSize(); + + // Move to a block after the challenged block + vm.roll(challengedBlockNumber + 1); + + // Expect the challenge status to be uninitialized + assertEq( + uint8(dataAvailabilityChallenge.getChallengeStatus(challengedBlockNumber, challengedCommitment)), + uint8(ChallengeStatus.Uninitialized) + ); + + // Deposit the required bond as part of the challenge transaction + vm.deal(challenger, requiredBond); + vm.prank(challenger); + dataAvailabilityChallenge.challenge{ value: requiredBond }(challengedBlockNumber, challengedCommitment); + + // Challenge should have been created + Challenge memory challenge = dataAvailabilityChallenge.getChallenge(challengedBlockNumber, challengedCommitment); + assertEq(challenge.challenger, challenger); + assertEq(challenge.startBlock, block.number); + assertEq(challenge.resolvedBlock, 0); + assertEq(challenge.lockedBond, requiredBond); + assertEq( + uint8(dataAvailabilityChallenge.getChallengeStatus(challengedBlockNumber, challengedCommitment)), + uint8(ChallengeStatus.Active) + ); + + // Challenge should have decreased the challenger's bond size + assertEq(dataAvailabilityChallenge.balances(challenger), 0); + } + + function testChallengeFailBondTooLow() public { + uint256 requiredBond = dataAvailabilityChallenge.bondSize(); + uint256 actualBond = requiredBond - 1; + dataAvailabilityChallenge.deposit{ value: actualBond }(); + + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.BondTooLow.selector, actualBond, requiredBond)); + dataAvailabilityChallenge.challenge(0, computeCommitmentKeccak256("some hash")); + } + + function testChallengeFailChallengeExists() public { + // Move to a block after the hash to challenge + vm.roll(2); + + // First challenge succeeds + bytes memory challengedCommitment = computeCommitmentKeccak256("some data"); + dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); + dataAvailabilityChallenge.challenge(0, challengedCommitment); + + // Second challenge of the same hash/blockNumber fails + dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeExists.selector)); + dataAvailabilityChallenge.challenge(0, challengedCommitment); + + // Challenge succeed if the challenged block number is different + dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); + dataAvailabilityChallenge.challenge(1, challengedCommitment); + + // Challenge succeed if the challenged hash is different + dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); + dataAvailabilityChallenge.challenge(0, computeCommitmentKeccak256("some other hash")); + } + + function testChallengeFailBeforeChallengeWindow() public { + uint256 challengedBlockNumber = 1; + bytes memory challengedCommitment = computeCommitmentKeccak256("some hash"); + + // Move to challenged block + vm.roll(challengedBlockNumber - 1); + + // Challenge fails because the current block number must be after the challenged block + dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeWindowNotOpen.selector)); + dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); + } + + function testChallengeFailAfterChallengeWindow() public { + uint256 challengedBlockNumber = 1; + bytes memory challengedCommitment = computeCommitmentKeccak256("some hash"); + + // Move to block after the challenge window + vm.roll(challengedBlockNumber + dataAvailabilityChallenge.challengeWindow() + 1); + + // Challenge fails because the block number is after the challenge window + dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeWindowNotOpen.selector)); + dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); + } + + function testResolveSuccess( + address challenger, + address resolver, + bytes memory preImage, + uint256 challengedBlockNumber, + uint256 resolverRefundPercentage, + uint128 txGasPrice + ) + public + { + // Assume neither the challenger nor resolver is address(0) and that they're not the same entity + vm.assume(challenger != address(0)); + vm.assume(resolver != address(0)); + vm.assume(challenger != resolver); + + // Bound the resolver refund percentage to 100 + resolverRefundPercentage = bound(resolverRefundPercentage, 0, 100); + + // Set the gas price to a fuzzed value to test bond distribution logic + vm.txGasPrice(txGasPrice); + + // Change the resolver refund percentage + vm.prank(dataAvailabilityChallenge.owner()); + dataAvailabilityChallenge.setResolverRefundPercentage(resolverRefundPercentage); + + // Assume the block number is not close to the max uint256 value + vm.assume( + challengedBlockNumber + < type(uint256).max - dataAvailabilityChallenge.challengeWindow() + - dataAvailabilityChallenge.resolveWindow() + ); + bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); + + // Move to block after challenged block + vm.roll(challengedBlockNumber + 1); + + // Challenge the hash + uint256 bondSize = dataAvailabilityChallenge.bondSize(); + vm.deal(challenger, bondSize); + vm.prank(challenger); + dataAvailabilityChallenge.challenge{ value: bondSize }(challengedBlockNumber, challengedCommitment); + + // Store the address(0) balance before resolving to assert the burned amount later + uint256 zeroAddressBalanceBeforeResolve = address(0).balance; + + // Resolve the challenge + vm.prank(resolver); + dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); + + // Expect the challenge to be resolved + Challenge memory challenge = dataAvailabilityChallenge.getChallenge(challengedBlockNumber, challengedCommitment); + + assertEq(challenge.challenger, challenger); + assertEq(challenge.lockedBond, 0); + assertEq(challenge.startBlock, block.number); + assertEq(challenge.resolvedBlock, block.number); + assertEq( + uint8(dataAvailabilityChallenge.getChallengeStatus(challengedBlockNumber, challengedCommitment)), + uint8(ChallengeStatus.Resolved) + ); + + // Assert challenger balance after bond distribution + uint256 resolutionCost = ( + dataAvailabilityChallenge.fixedResolutionCost() + + preImage.length * dataAvailabilityChallenge.variableResolutionCost() + / dataAvailabilityChallenge.variableResolutionCostPrecision() + ) * block.basefee; + uint256 challengerRefund = bondSize > resolutionCost ? bondSize - resolutionCost : 0; + assertEq(dataAvailabilityChallenge.balances(challenger), challengerRefund, "challenger refund"); + + // Assert resolver balance after bond distribution + uint256 resolverRefund = resolutionCost * dataAvailabilityChallenge.resolverRefundPercentage() / 100; + resolverRefund = resolverRefund > resolutionCost ? resolutionCost : resolverRefund; + resolverRefund = resolverRefund > bondSize ? bondSize : resolverRefund; + assertEq(dataAvailabilityChallenge.balances(resolver), resolverRefund, "resolver refund"); + + // Assert burned amount after bond distribution + uint256 burned = bondSize - challengerRefund - resolverRefund; + assertEq(address(0).balance - zeroAddressBalanceBeforeResolve, burned, "burned bond"); + } + + function testResolveFailNonExistentChallenge() public { + bytes memory preImage = "some preimage"; + uint256 challengedBlockNumber = 1; + + // Move to block after challenged block + vm.roll(challengedBlockNumber + 1); + + // Resolving a non-existent challenge fails + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotActive.selector)); + dataAvailabilityChallenge.resolve(challengedBlockNumber, computeCommitmentKeccak256(preImage), preImage); + } + + function testResolveFailResolved() public { + bytes memory preImage = "some preimage"; + bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); + uint256 challengedBlockNumber = 1; + + // Move to block after challenged block + vm.roll(challengedBlockNumber + 1); + + // Challenge the hash + dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); + dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); + + // Resolve the challenge + dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); + + // Resolving an already resolved challenge fails + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotActive.selector)); + dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); + } + + function testResolveFailExpired() public { + bytes memory preImage = "some preimage"; + bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); + uint256 challengedBlockNumber = 1; + + // Move to block after challenged block + vm.roll(challengedBlockNumber + 1); + + // Challenge the hash + dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); + dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); + + // Move to a block after the resolve window + vm.roll(block.number + dataAvailabilityChallenge.resolveWindow() + 1); + + // Resolving an expired challenge fails + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotActive.selector)); + dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); + } + + function testResolveFailAfterResolveWindow() public { + bytes memory preImage = "some preimage"; + bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); + uint256 challengedBlockNumber = 1; + + // Move to block after challenged block + vm.roll(challengedBlockNumber + 1); + + // Challenge the hash + dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); + dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); + + // Move to block after resolve window + vm.roll(block.number + dataAvailabilityChallenge.resolveWindow() + 1); + + // Resolve the challenge + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotActive.selector)); + dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); + } + + function testUnlockBondSuccess(bytes memory preImage, uint256 challengedBlockNumber) public { + // Assume the block number is not close to the max uint256 value + vm.assume( + challengedBlockNumber + < type(uint256).max - dataAvailabilityChallenge.challengeWindow() + - dataAvailabilityChallenge.resolveWindow() + ); + bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); + + // Move to block after challenged block + vm.roll(challengedBlockNumber + 1); + + // Challenge the hash + dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); + dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); + + // Move to a block after the resolve window + vm.roll(block.number + dataAvailabilityChallenge.resolveWindow() + 1); + + uint256 balanceBeforeUnlock = dataAvailabilityChallenge.balances(address(this)); + + // Unlock the bond associated with the challenge + dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); + + // Expect the balance to be increased by the bond size + uint256 balanceAfterUnlock = dataAvailabilityChallenge.balances(address(this)); + assertEq(balanceAfterUnlock, balanceBeforeUnlock + dataAvailabilityChallenge.bondSize()); + + // Expect the bond to be unlocked + Challenge memory challenge = dataAvailabilityChallenge.getChallenge(challengedBlockNumber, challengedCommitment); + + assertEq(challenge.challenger, address(this)); + assertEq(challenge.lockedBond, 0); + assertEq(challenge.startBlock, challengedBlockNumber + 1); + assertEq(challenge.resolvedBlock, 0); + assertEq( + uint8(dataAvailabilityChallenge.getChallengeStatus(challengedBlockNumber, challengedCommitment)), + uint8(ChallengeStatus.Expired) + ); + + // Unlock the bond again, expect the balance to remain the same + dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); + assertEq(dataAvailabilityChallenge.balances(address(this)), balanceAfterUnlock); + } + + function testUnlockBondFailNonExistentChallenge() public { + bytes memory preImage = "some preimage"; + bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); + uint256 challengedBlockNumber = 1; + + // Move to block after challenged block + vm.roll(challengedBlockNumber + 1); + + // Unlock a bond of a non-existent challenge fails + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotExpired.selector)); + dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); + } + + function testUnlockBondFailResolvedChallenge() public { + bytes memory preImage = "some preimage"; + bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); + uint256 challengedBlockNumber = 1; + + // Move to block after challenged block + vm.roll(challengedBlockNumber + 1); + + // Challenge the hash + dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); + dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); + + // Resolve the challenge + dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); + + // Attempting to unlock a bond of a resolved challenge fails + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotExpired.selector)); + dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); + } + + function testUnlockBondExpiredChallengeTwice() public { + bytes memory preImage = "some preimage"; + bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); + uint256 challengedBlockNumber = 1; + + // Move to block after challenged block + vm.roll(challengedBlockNumber + 1); + + // Challenge the hash + dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); + dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); + + // Move to a block after the challenge window + vm.roll(block.number + dataAvailabilityChallenge.resolveWindow() + 1); + + // Unlock the bond + dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); + + uint256 balanceAfterUnlock = dataAvailabilityChallenge.balances(address(this)); + + // Unlock the bond again doesn't change the balance + dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); + assertEq(dataAvailabilityChallenge.balances(address(this)), balanceAfterUnlock); + } + + function testUnlockFailResolveWindowNotClosed() public { + bytes memory preImage = "some preimage"; + bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); + uint256 challengedBlockNumber = 1; + + // Move to block after challenged block + vm.roll(challengedBlockNumber + 1); + + // Challenge the hash + dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); + dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); + + vm.roll(block.number + dataAvailabilityChallenge.resolveWindow() - 1); + + // Expiring the challenge before the resolve window closes fails + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotExpired.selector)); + dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); + } + + function testSetBondSize() public { + uint256 requiredBond = dataAvailabilityChallenge.bondSize(); + uint256 actualBond = requiredBond - 1; + dataAvailabilityChallenge.deposit{ value: actualBond }(); + + // Expect the challenge to fail because the bond is too low + bytes memory challengedCommitment = computeCommitmentKeccak256("some hash"); + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.BondTooLow.selector, actualBond, requiredBond)); + dataAvailabilityChallenge.challenge(0, challengedCommitment); + + // Reduce the required bond + vm.prank(dataAvailabilityChallenge.owner()); + dataAvailabilityChallenge.setBondSize(actualBond); + + // Expect the challenge to succeed + dataAvailabilityChallenge.challenge(0, challengedCommitment); + } + + function testSetResolverRefundPercentage(uint256 resolverRefundPercentage) public { + resolverRefundPercentage = bound(resolverRefundPercentage, 0, 100); + vm.prank(dataAvailabilityChallenge.owner()); + dataAvailabilityChallenge.setResolverRefundPercentage(resolverRefundPercentage); + assertEq(dataAvailabilityChallenge.resolverRefundPercentage(), resolverRefundPercentage); + } + + function testSetResolverRefundPercentageFail() public { + address owner = dataAvailabilityChallenge.owner(); + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.InvalidResolverRefundPercentage.selector, 101)); + vm.prank(owner); + dataAvailabilityChallenge.setResolverRefundPercentage(101); + } + + function testSetBondSizeFailOnlyOwner(address notOwner, uint256 newBondSize) public { + vm.assume(notOwner != dataAvailabilityChallenge.owner()); + + // Expect setting the bond size to fail because the sender is not the owner + vm.prank(notOwner); + vm.expectRevert("Ownable: caller is not the owner"); + dataAvailabilityChallenge.setBondSize(newBondSize); + } + + function testValidateCommitment() public { + // Should not revert given a valid commitment + bytes memory validCommitment = abi.encodePacked(CommitmentType.Keccak256, keccak256("test")); + dataAvailabilityChallenge.validateCommitment(validCommitment); + + // Should revert if the commitment type is unknown + vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.UnknownCommitmentType.selector, uint8(1))); + bytes memory unknownType = abi.encodePacked(uint8(1), keccak256("test")); + dataAvailabilityChallenge.validateCommitment(unknownType); + + // Should revert if the commitment length does not match + vm.expectRevert( + abi.encodeWithSelector(DataAvailabilityChallenge.InvalidCommitmentLength.selector, uint8(0), 33, 34) + ); + bytes memory invalidLength = abi.encodePacked(CommitmentType.Keccak256, keccak256("test"), "x"); + dataAvailabilityChallenge.validateCommitment(invalidLength); + } +} diff --git a/packages/contracts-bedrock/test/L1/DelayedVetoable.t.sol b/packages/contracts-bedrock/test/L1/DelayedVetoable.t.sol index c21137010f4e..5e67a7ba5cf9 100644 --- a/packages/contracts-bedrock/test/L1/DelayedVetoable.t.sol +++ b/packages/contracts-bedrock/test/L1/DelayedVetoable.t.sol @@ -150,9 +150,9 @@ contract DelayedVetoable_HandleCall_Test is DelayedVetoable_Init { contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init { /// @dev Only the initiator can initiate a call. function test_handleCall_unauthorizedInitiation_reverts() external { - vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this))); - (bool success,) = address(delayedVetoable).call(hex"00001234"); - assertTrue(success); + vm.expectRevert(abi.encodeWithSelector(DelayedVetoable.Unauthorized.selector, initiator, address(this))); + (bool revertsAsExpected,) = address(delayedVetoable).call(hex"00001234"); + assertTrue(revertsAsExpected); } /// @dev The call cannot be forwarded until the delay has passed. @@ -160,10 +160,11 @@ contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init { assumeNoClash(data); vm.prank(initiator); (bool success,) = address(delayedVetoable).call(data); + assertTrue(success); - vm.expectRevert(abi.encodeWithSelector(ForwardingEarly.selector)); - (success,) = address(delayedVetoable).call(data); - success; + vm.expectRevert(DelayedVetoable.ForwardingEarly.selector); + (bool revertsAsExpected,) = address(delayedVetoable).call(data); + assertTrue(revertsAsExpected); } /// @dev The call cannot be forwarded a second time. @@ -184,10 +185,10 @@ contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init { (success,) = address(delayedVetoable).call(data); assertTrue(success); - // Attempt to foward the same call again. - vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this))); - (success,) = address(delayedVetoable).call(data); - assertTrue(success); + // Attempt to forward the same call again. + vm.expectRevert(abi.encodeWithSelector(DelayedVetoable.Unauthorized.selector, initiator, address(this))); + (bool revertsAsExpected,) = address(delayedVetoable).call(data); + assertTrue(revertsAsExpected); } /// @dev If the target reverts, it is bubbled up. @@ -202,7 +203,7 @@ contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init { // Initiate the call vm.prank(initiator); (bool success,) = address(delayedVetoable).call(inData); - success; + assertTrue(success); vm.warp(block.timestamp + operatingDelay); vm.expectEmit(true, false, false, true, address(delayedVetoable)); @@ -212,8 +213,8 @@ contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init { // Forward the call vm.expectRevert(outData); - (bool success2,) = address(delayedVetoable).call(inData); - success2; + (bool revertsAsExpected,) = address(delayedVetoable).call(inData); + assertTrue(revertsAsExpected); } function testFuzz_handleCall_forwardingTargetRetValue_succeeds( @@ -227,7 +228,7 @@ contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init { // Initiate the call vm.prank(initiator); (bool success,) = address(delayedVetoable).call(inData); - success; + assertTrue(success); vm.warp(block.timestamp + operatingDelay); vm.expectEmit(true, false, false, true, address(delayedVetoable)); @@ -242,7 +243,7 @@ contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init { } /// @dev A test documenting the single instance in which the contract is not 'transparent' to the initiator. - function testFuzz_handleCall_queuedAtClash_reverts(bytes memory outData) external { + function testFuzz_handleCall_queuedAtClash_reverts() external { // This will get us calldata with the same function selector as the queuedAt function, but // with the incorrect input data length. bytes memory inData = abi.encodePacked(keccak256("queuedAt(bytes32)")); @@ -251,8 +252,8 @@ contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init { vm.store(address(delayedVetoable), bytes32(uint256(0)), bytes32(uint256(0))); vm.prank(initiator); - vm.expectRevert(outData); - (bool success,) = address(delayedVetoable).call(inData); - success; + vm.expectRevert(bytes("")); + (bool revertsAsExpected,) = address(delayedVetoable).call(inData); + assertTrue(revertsAsExpected); } } diff --git a/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol index ad4aef66e642..1f8054609073 100644 --- a/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol @@ -25,7 +25,9 @@ contract L1CrossDomainMessenger_Test is Bridge_Initializer { uint256 constant senderSlotIndex = 50; /// @dev Tests that the implementation is initialized correctly. - function test_constructor_succeeds() external { + /// @notice Marked virtual to be overridden in + /// test/kontrol/deployment/DeploymentSummary.t.sol + function test_constructor_succeeds() external virtual { L1CrossDomainMessenger impl = L1CrossDomainMessenger(deploy.mustGetAddress("L1CrossDomainMessenger")); assertEq(address(impl.superchainConfig()), address(0)); assertEq(address(impl.PORTAL()), address(0)); @@ -110,7 +112,9 @@ contract L1CrossDomainMessenger_Test is Bridge_Initializer { /// @dev Tests that the relayMessage function reverts when /// the message version is not 0 or 1. - function test_relayMessage_v2_reverts() external { + /// @notice Marked virtual to be overridden in + /// test/kontrol/deployment/DeploymentSummary.t.sol + function test_relayMessage_v2_reverts() external virtual { address target = address(0xabcd); address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; diff --git a/packages/contracts-bedrock/test/L1/L1ERC721Bridge.t.sol b/packages/contracts-bedrock/test/L1/L1ERC721Bridge.t.sol index b8f436e32438..5d2444525bf7 100644 --- a/packages/contracts-bedrock/test/L1/L1ERC721Bridge.t.sol +++ b/packages/contracts-bedrock/test/L1/L1ERC721Bridge.t.sol @@ -47,7 +47,9 @@ contract L1ERC721Bridge_Test is Bridge_Initializer { ); /// @dev Sets up the testing environment. - function setUp() public override { + /// @notice Marked virtual to be overridden in + /// test/kontrol/deployment/DeploymentSummary.t.sol + function setUp() public virtual override { super.setUp(); localToken = new TestERC721(); @@ -62,7 +64,9 @@ contract L1ERC721Bridge_Test is Bridge_Initializer { } /// @dev Tests that the impl is created with the correct values. - function test_constructor_succeeds() public { + /// @notice Marked virtual to be overridden in + /// test/kontrol/deployment/DeploymentSummary.t.sol + function test_constructor_succeeds() public virtual { L1ERC721Bridge impl = L1ERC721Bridge(deploy.mustGetAddress("L1ERC721Bridge")); assertEq(address(impl.MESSENGER()), address(0)); assertEq(address(impl.messenger()), address(0)); @@ -128,7 +132,7 @@ contract L1ERC721Bridge_Test is Bridge_Initializer { function test_bridgeERC721_localTokenZeroAddress_reverts() external { // Bridge the token. vm.prank(alice); - vm.expectRevert(); + vm.expectRevert(bytes("")); l1ERC721Bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678"); // Token is not locked in the bridge. @@ -197,7 +201,7 @@ contract L1ERC721Bridge_Test is Bridge_Initializer { function test_bridgeERC721To_localTokenZeroAddress_reverts() external { // Bridge the token. vm.prank(alice); - vm.expectRevert(); + vm.expectRevert(bytes("")); l1ERC721Bridge.bridgeERC721To(address(0), address(remoteToken), bob, tokenId, 1234, hex"5678"); // Token is not locked in the bridge. diff --git a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol index c96eb197f71f..0d0b7dc8c308 100644 --- a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol @@ -8,7 +8,6 @@ import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; -import { Constants } from "src/libraries/Constants.sol"; // Target contract dependencies import { StandardBridge } from "src/universal/StandardBridge.sol"; @@ -33,7 +32,9 @@ contract L1StandardBridge_Getter_Test is Bridge_Initializer { contract L1StandardBridge_Initialize_Test is Bridge_Initializer { /// @dev Test that the constructor sets the correct values. - function test_constructor_succeeds() external { + /// @notice Marked virtual to be overridden in + /// test/kontrol/deployment/DeploymentSummary.t.sol + function test_constructor_succeeds() external virtual { L1StandardBridge impl = L1StandardBridge(deploy.mustGetAddress("L1StandardBridge")); assertEq(address(impl.superchainConfig()), address(0)); assertEq(address(impl.MESSENGER()), address(0)); diff --git a/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol b/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol index 6192d6ef4526..7f712e8ff8f7 100644 --- a/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol +++ b/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol @@ -51,6 +51,7 @@ contract L2OutputOracle_constructor_Test is CommonTest { assertEq(l2OutputOracle.submissionInterval(), submissionInterval); assertEq(l2OutputOracle.L2_BLOCK_TIME(), l2BlockTime); assertEq(l2OutputOracle.l2BlockTime(), l2BlockTime); + assertEq(l2OutputOracle.latestBlockNumber(), startingBlockNumber); assertEq(l2OutputOracle.startingBlockNumber(), startingBlockNumber); assertEq(l2OutputOracle.startingTimestamp(), startingTimestamp); assertEq(l2OutputOracle.finalizationPeriodSeconds(), finalizationPeriodSeconds); @@ -451,7 +452,7 @@ contract L2OutputOracleUpgradeable_Test is CommonTest { } /// @dev Tests that initialize reverts if the l2BlockTime is invalid. - function test_initalize_l2BlockTimeZero_reverts() external { + function test_initialize_l2BlockTimeZero_reverts() external { // Reset the initialized field in the 0th storage slot // so that initialize can be called again. vm.store(address(l2OutputOracle), bytes32(uint256(0)), bytes32(uint256(0))); diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal.t.sol index 6ac737e3b41a..58679b313ee9 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortal.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortal.t.sol @@ -25,13 +25,17 @@ import { OptimismPortal } from "src/L1/OptimismPortal.sol"; contract OptimismPortal_Test is CommonTest { address depositor; - function setUp() public override { + /// @notice Marked virtual to be overridden in + /// test/kontrol/deployment/DeploymentSummary.t.sol + function setUp() public virtual override { super.setUp(); depositor = makeAddr("depositor"); } /// @dev Tests that the constructor sets the correct values. - function test_constructor_succeeds() external { + /// @notice Marked virtual to be overridden in + /// test/kontrol/deployment/DeploymentSummary.t.sol + function test_constructor_succeeds() external virtual { OptimismPortal opImpl = OptimismPortal(payable(deploy.mustGetAddress("OptimismPortal"))); assertEq(address(opImpl.L2_ORACLE()), address(0)); assertEq(address(opImpl.l2Oracle()), address(0)); @@ -39,10 +43,16 @@ contract OptimismPortal_Test is CommonTest { assertEq(address(opImpl.systemConfig()), address(0)); assertEq(address(opImpl.superchainConfig()), address(0)); assertEq(opImpl.l2Sender(), Constants.DEFAULT_L2_SENDER); + (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = opImpl.params(); + assertEq(prevBaseFee, 1 gwei); + assertEq(prevBoughtGas, 0); + assertEq(prevBlockNum, uint64(block.number)); } /// @dev Tests that the initializer sets the correct values. - function test_initialize_succeeds() external { + /// @notice Marked virtual to be overridden in + /// test/kontrol/deployment/DeploymentSummary.t.sol + function test_initialize_succeeds() external virtual { address guardian = deploy.cfg().superchainConfigGuardian(); assertEq(address(optimismPortal.L2_ORACLE()), address(l2OutputOracle)); assertEq(address(optimismPortal.l2Oracle()), address(l2OutputOracle)); @@ -53,6 +63,10 @@ contract OptimismPortal_Test is CommonTest { assertEq(address(optimismPortal.superchainConfig()), address(superchainConfig)); assertEq(optimismPortal.l2Sender(), Constants.DEFAULT_L2_SENDER); assertEq(optimismPortal.paused(), false); + (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = optimismPortal.params(); + assertEq(prevBaseFee, 1 gwei); + assertEq(prevBoughtGas, 0); + assertEq(prevBlockNum, uint64(block.number)); } /// @dev Tests that `pause` successfully pauses @@ -282,7 +296,9 @@ contract OptimismPortal_Test is CommonTest { } /// @dev Tests that `isOutputFinalized` succeeds for an EOA depositing a tx with ETH and data. - function test_simple_isOutputFinalized_succeeds() external { + /// @notice Marked virtual to be overridden in + /// test/kontrol/deployment/DeploymentSummary.t.sol + function test_simple_isOutputFinalized_succeeds() external virtual { uint256 startingBlockNumber = deploy.cfg().l2OutputOracleStartingBlockNumber(); uint256 ts = block.timestamp; @@ -302,7 +318,9 @@ contract OptimismPortal_Test is CommonTest { } /// @dev Tests `isOutputFinalized` for a finalized output. - function test_isOutputFinalized_succeeds() external { + /// @notice Marked virtual to be overridden in + /// test/kontrol/deployment/DeploymentSummary.t.sol + function test_isOutputFinalized_succeeds() external virtual { uint256 checkpoint = l2OutputOracle.nextBlockNumber(); uint256 nextOutputIndex = l2OutputOracle.nextOutputIndex(); vm.roll(checkpoint); diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol new file mode 100644 index 000000000000..3c7c14625977 --- /dev/null +++ b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol @@ -0,0 +1,1193 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +// Testing utilities +import { stdError } from "forge-std/Test.sol"; + +import { CommonTest } from "test/setup/CommonTest.sol"; +import { NextImpl } from "test/mocks/NextImpl.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; + +// Libraries +import { Types } from "src/libraries/Types.sol"; +import { Hashing } from "src/libraries/Hashing.sol"; +import { Constants } from "src/libraries/Constants.sol"; + +// Target contract dependencies +import { Proxy } from "src/universal/Proxy.sol"; +import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; +import { SystemConfig } from "src/L1/SystemConfig.sol"; +import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; + +import { FaultDisputeGame, IDisputeGame } from "src/dispute/FaultDisputeGame.sol"; +import "src/libraries/DisputeTypes.sol"; + +contract OptimismPortal2_Test is CommonTest { + address depositor; + + function setUp() public override { + super.enableFaultProofs(); + super.setUp(); + + depositor = makeAddr("depositor"); + } + + /// @dev Tests that the constructor sets the correct values. + /// @notice Marked virtual to be overridden in + /// test/kontrol/deployment/DeploymentSummary.t.sol + function test_constructor_succeeds() external virtual { + OptimismPortal2 opImpl = OptimismPortal2(payable(deploy.mustGetAddress("OptimismPortal2"))); + assertEq(address(opImpl.disputeGameFactory()), address(0)); + assertEq(address(opImpl.SYSTEM_CONFIG()), address(0)); + assertEq(address(opImpl.systemConfig()), address(0)); + assertEq(address(opImpl.superchainConfig()), address(0)); + assertEq(opImpl.l2Sender(), Constants.DEFAULT_L2_SENDER); + assertEq(opImpl.respectedGameType().raw(), deploy.cfg().respectedGameType()); + } + + /// @dev Tests that the initializer sets the correct values. + /// @notice Marked virtual to be overridden in + /// test/kontrol/deployment/DeploymentSummary.t.sol + function test_initialize_succeeds() external virtual { + address guardian = deploy.cfg().superchainConfigGuardian(); + assertEq(address(optimismPortal2.disputeGameFactory()), address(disputeGameFactory)); + assertEq(address(optimismPortal2.SYSTEM_CONFIG()), address(systemConfig)); + assertEq(address(optimismPortal2.systemConfig()), address(systemConfig)); + assertEq(optimismPortal2.GUARDIAN(), guardian); + assertEq(optimismPortal2.guardian(), guardian); + assertEq(address(optimismPortal2.superchainConfig()), address(superchainConfig)); + assertEq(optimismPortal2.l2Sender(), Constants.DEFAULT_L2_SENDER); + assertEq(optimismPortal2.paused(), false); + assertEq(optimismPortal2.respectedGameType().raw(), deploy.cfg().respectedGameType()); + } + + /// @dev Tests that `pause` successfully pauses + /// when called by the GUARDIAN. + function test_pause_succeeds() external { + address guardian = optimismPortal2.GUARDIAN(); + + assertEq(optimismPortal2.paused(), false); + + vm.expectEmit(address(superchainConfig)); + emit Paused("identifier"); + + vm.prank(guardian); + superchainConfig.pause("identifier"); + + assertEq(optimismPortal2.paused(), true); + } + + /// @dev Tests that `pause` reverts when called by a non-GUARDIAN. + function test_pause_onlyGuardian_reverts() external { + assertEq(optimismPortal2.paused(), false); + + assertTrue(optimismPortal2.GUARDIAN() != alice); + vm.expectRevert("SuperchainConfig: only guardian can pause"); + vm.prank(alice); + superchainConfig.pause("identifier"); + + assertEq(optimismPortal2.paused(), false); + } + + /// @dev Tests that `unpause` successfully unpauses + /// when called by the GUARDIAN. + function test_unpause_succeeds() external { + address guardian = optimismPortal2.GUARDIAN(); + + vm.prank(guardian); + superchainConfig.pause("identifier"); + assertEq(optimismPortal2.paused(), true); + + vm.expectEmit(address(superchainConfig)); + emit Unpaused(); + vm.prank(guardian); + superchainConfig.unpause(); + + assertEq(optimismPortal2.paused(), false); + } + + /// @dev Tests that `unpause` reverts when called by a non-GUARDIAN. + function test_unpause_onlyGuardian_reverts() external { + address guardian = optimismPortal2.GUARDIAN(); + + vm.prank(guardian); + superchainConfig.pause("identifier"); + assertEq(optimismPortal2.paused(), true); + + assertTrue(optimismPortal2.GUARDIAN() != alice); + vm.expectRevert("SuperchainConfig: only guardian can unpause"); + vm.prank(alice); + superchainConfig.unpause(); + + assertEq(optimismPortal2.paused(), true); + } + + /// @dev Tests that `receive` successdully deposits ETH. + function testFuzz_receive_succeeds(uint256 _value) external { + vm.expectEmit(address(optimismPortal2)); + emitTransactionDeposited({ + _from: alice, + _to: alice, + _value: _value, + _mint: _value, + _gasLimit: 100_000, + _isCreation: false, + _data: hex"" + }); + + // give alice money and send as an eoa + vm.deal(alice, _value); + vm.prank(alice, alice); + (bool s,) = address(optimismPortal2).call{ value: _value }(hex""); + + assertTrue(s); + assertEq(address(optimismPortal2).balance, _value); + } + + /// @dev Tests that `depositTransaction` reverts when the destination address is non-zero + /// for a contract creation deposit. + function test_depositTransaction_contractCreation_reverts() external { + // contract creation must have a target of address(0) + vm.expectRevert("OptimismPortal: must send to address(0) when creating a contract"); + optimismPortal2.depositTransaction(address(1), 1, 0, true, hex""); + } + + /// @dev Tests that `depositTransaction` reverts when the data is too large. + /// This places an upper bound on unsafe blocks sent over p2p. + function test_depositTransaction_largeData_reverts() external { + uint256 size = 120_001; + uint64 gasLimit = optimismPortal2.minimumGasLimit(uint64(size)); + vm.expectRevert("OptimismPortal: data too large"); + optimismPortal2.depositTransaction({ + _to: address(0), + _value: 0, + _gasLimit: gasLimit, + _isCreation: false, + _data: new bytes(size) + }); + } + + /// @dev Tests that `depositTransaction` reverts when the gas limit is too small. + function test_depositTransaction_smallGasLimit_reverts() external { + vm.expectRevert("OptimismPortal: gas limit too small"); + optimismPortal2.depositTransaction({ _to: address(1), _value: 0, _gasLimit: 0, _isCreation: false, _data: hex"" }); + } + + /// @dev Tests that `depositTransaction` succeeds for small, + /// but sufficient, gas limits. + function testFuzz_depositTransaction_smallGasLimit_succeeds(bytes memory _data, bool _shouldFail) external { + uint64 gasLimit = optimismPortal2.minimumGasLimit(uint64(_data.length)); + if (_shouldFail) { + gasLimit = uint64(bound(gasLimit, 0, gasLimit - 1)); + vm.expectRevert("OptimismPortal: gas limit too small"); + } + + optimismPortal2.depositTransaction({ + _to: address(0x40), + _value: 0, + _gasLimit: gasLimit, + _isCreation: false, + _data: _data + }); + } + + /// @dev Tests that `minimumGasLimit` succeeds for small calldata sizes. + /// The gas limit should be 21k for 0 calldata and increase linearly + /// for larger calldata sizes. + function test_minimumGasLimit_succeeds() external { + assertEq(optimismPortal2.minimumGasLimit(0), 21_000); + assertTrue(optimismPortal2.minimumGasLimit(2) > optimismPortal2.minimumGasLimit(1)); + assertTrue(optimismPortal2.minimumGasLimit(3) > optimismPortal2.minimumGasLimit(2)); + } + + /// @dev Tests that `depositTransaction` succeeds for an EOA. + function testFuzz_depositTransaction_eoa_succeeds( + address _to, + uint64 _gasLimit, + uint256 _value, + uint256 _mint, + bool _isCreation, + bytes memory _data + ) + external + { + _gasLimit = uint64( + bound( + _gasLimit, + optimismPortal2.minimumGasLimit(uint64(_data.length)), + systemConfig.resourceConfig().maxResourceLimit + ) + ); + if (_isCreation) _to = address(0); + + // EOA emulation + vm.expectEmit(address(optimismPortal2)); + emitTransactionDeposited({ + _from: depositor, + _to: _to, + _value: _value, + _mint: _mint, + _gasLimit: _gasLimit, + _isCreation: _isCreation, + _data: _data + }); + + vm.deal(depositor, _mint); + vm.prank(depositor, depositor); + optimismPortal2.depositTransaction{ value: _mint }({ + _to: _to, + _value: _value, + _gasLimit: _gasLimit, + _isCreation: _isCreation, + _data: _data + }); + assertEq(address(optimismPortal2).balance, _mint); + } + + /// @dev Tests that `depositTransaction` succeeds for a contract. + function testFuzz_depositTransaction_contract_succeeds( + address _to, + uint64 _gasLimit, + uint256 _value, + uint256 _mint, + bool _isCreation, + bytes memory _data + ) + external + { + _gasLimit = uint64( + bound( + _gasLimit, + optimismPortal2.minimumGasLimit(uint64(_data.length)), + systemConfig.resourceConfig().maxResourceLimit + ) + ); + if (_isCreation) _to = address(0); + + vm.expectEmit(address(optimismPortal2)); + emitTransactionDeposited({ + _from: AddressAliasHelper.applyL1ToL2Alias(address(this)), + _to: _to, + _value: _value, + _mint: _mint, + _gasLimit: _gasLimit, + _isCreation: _isCreation, + _data: _data + }); + + vm.deal(address(this), _mint); + vm.prank(address(this)); + optimismPortal2.depositTransaction{ value: _mint }({ + _to: _to, + _value: _value, + _gasLimit: _gasLimit, + _isCreation: _isCreation, + _data: _data + }); + assertEq(address(optimismPortal2).balance, _mint); + } +} + +contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { + // Reusable default values for a test withdrawal + Types.WithdrawalTransaction _defaultTx; + + FaultDisputeGame game; + uint256 _proposedGameIndex; + uint256 _proposedBlockNumber; + bytes32 _stateRoot; + bytes32 _storageRoot; + bytes32 _outputRoot; + bytes32 _withdrawalHash; + bytes[] _withdrawalProof; + Types.OutputRootProof internal _outputRootProof; + + // Use a constructor to set the storage vars above, so as to minimize the number of ffi calls. + constructor() { + super.enableFaultProofs(); + super.setUp(); + + _defaultTx = Types.WithdrawalTransaction({ + nonce: 0, + sender: alice, + target: bob, + value: 100, + gasLimit: 100_000, + data: hex"" + }); + // Get withdrawal proof data we can use for testing. + (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = + ffi.getProveWithdrawalTransactionInputs(_defaultTx); + + // Setup a dummy output root proof for reuse. + _outputRootProof = Types.OutputRootProof({ + version: bytes32(uint256(0)), + stateRoot: _stateRoot, + messagePasserStorageRoot: _storageRoot, + latestBlockhash: bytes32(uint256(0)) + }); + } + + /// @dev Setup the system for a ready-to-use state. + function setUp() public override { + _proposedBlockNumber = 0xFF; + game = FaultDisputeGame( + payable( + address( + disputeGameFactory.create( + optimismPortal2.respectedGameType(), Claim.wrap(_outputRoot), abi.encode(_proposedBlockNumber) + ) + ) + ) + ); + _proposedGameIndex = disputeGameFactory.gameCount() - 1; + + // Warp beyond the chess clocks and finalize the game. + vm.warp(block.timestamp + game.gameDuration().raw() / 2 + 1 seconds); + + // Fund the portal so that we can withdraw ETH. + vm.deal(address(optimismPortal2), 0xFFFFFFFF); + } + + /// @dev Asserts that the reentrant call will revert. + function callPortalAndExpectRevert() external payable { + vm.expectRevert("OptimismPortal: can only trigger one withdrawal per transaction"); + // Arguments here don't matter, as the require check is the first thing that happens. + // We assume that this has already been proven. + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + // Assert that the withdrawal was not finalized. + assertFalse(optimismPortal2.finalizedWithdrawals(Hashing.hashWithdrawal(_defaultTx))); + } + + /// @dev Tests that `blacklistDisputeGame` reverts when called by a non-guardian. + function testFuzz_blacklist_onlyGuardian_reverts(address _act) external { + vm.assume(_act != address(optimismPortal2.guardian())); + + vm.expectRevert("OptimismPortal: only the guardian can blacklist dispute games"); + optimismPortal2.blacklistDisputeGame(IDisputeGame(address(0xdead))); + } + + /// @dev Tests that the guardian role can blacklist any dispute game. + function testFuzz_blacklist_guardian_succeeds(address _addr) external { + vm.prank(optimismPortal2.guardian()); + optimismPortal2.blacklistDisputeGame(IDisputeGame(_addr)); + + assertTrue(optimismPortal2.disputeGameBlacklist(IDisputeGame(_addr))); + } + + /// @dev Tests that `setRespectedGameType` reverts when called by a non-guardian. + function testFuzz_setRespectedGameType_onlyGuardian_reverts(address _act, GameType _ty) external { + vm.assume(_act != address(optimismPortal2.guardian())); + + vm.prank(_act); + vm.expectRevert("OptimismPortal: only the guardian can set the respected game type"); + optimismPortal2.setRespectedGameType(_ty); + } + + /// @dev Tests that the guardian role can set the respected game type to anything they want. + function testFuzz_setRespectedGameType_guardian_succeeds(GameType _ty) external { + vm.prank(optimismPortal2.guardian()); + optimismPortal2.setRespectedGameType(_ty); + + assertEq(optimismPortal2.respectedGameType().raw(), _ty.raw()); + } + + /// @dev Tests that `proveWithdrawalTransaction` reverts when paused. + function test_proveWithdrawalTransaction_paused_reverts() external { + vm.prank(optimismPortal2.GUARDIAN()); + superchainConfig.pause("identifier"); + + vm.expectRevert("OptimismPortal: paused"); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + + /// @dev Tests that `proveWithdrawalTransaction` reverts when the target is the portal contract. + function test_proveWithdrawalTransaction_onSelfCall_reverts() external { + _defaultTx.target = address(optimismPortal2); + vm.expectRevert("OptimismPortal: you cannot send messages to the portal contract"); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + + /// @dev Tests that `proveWithdrawalTransaction` reverts when the outputRootProof does not match the output root + function test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() external { + // Modify the version to invalidate the withdrawal proof. + _outputRootProof.version = bytes32(uint256(1)); + vm.expectRevert("OptimismPortal: invalid output root proof"); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + + /// @dev Tests that `proveWithdrawalTransaction` reverts when the withdrawal is missing. + function test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() external { + // modify the default test values to invalidate the proof. + _defaultTx.data = hex"abcd"; + vm.expectRevert("MerkleTrie: path remainder must share all nibbles with key"); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + + /// @dev Tests that `proveWithdrawalTransaction` reverts when the withdrawal has already + /// been proven. + function test_proveWithdrawalTransaction_replayProve_reverts() external { + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + vm.expectRevert( + "OptimismPortal: withdrawal hash has already been proven, and the old dispute game is not invalid" + ); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + + /// @dev Tests that `proveWithdrawalTransaction` reverts if the dispute game being proven against is not of the + /// respected game type. + function test_proveWithdrawalTransaction_badGameType_reverts() external { + vm.mockCall( + address(disputeGameFactory), + abi.encodeCall(disputeGameFactory.gameAtIndex, (_proposedGameIndex)), + abi.encode(GameType.wrap(0xFF), Timestamp.wrap(uint64(block.timestamp)), IDisputeGame(address(game))) + ); + + vm.expectRevert("OptimismPortal: invalid game type"); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + + /// @dev Tests that `proveWithdrawalTransaction` can be re-executed if the dispute game proven against has been + /// blacklisted. + function test_proveWithdrawalTransaction_replayProveBlacklisted_suceeds() external { + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + // Blacklist the dispute dispute game. + vm.prank(optimismPortal2.guardian()); + optimismPortal2.blacklistDisputeGame(IDisputeGame(address(game))); + + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + + /// @dev Tests that `proveWithdrawalTransaction` can be re-executed if the dispute game proven against has resolved + /// against the favor of the root claim. + function test_proveWithdrawalTransaction_replayProveBadProposal_suceeds() external { + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + vm.mockCall(address(game), abi.encodeCall(game.status, ()), abi.encode(GameStatus.CHALLENGER_WINS)); + + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + + /// @dev Tests that `proveWithdrawalTransaction` can be re-executed if the dispute game proven against is no longer + /// of the respected game type. + function test_proveWithdrawalTransaction_replayRespectedGameTypeChanged_suceeds() external { + // Prove the withdrawal against a game with the current respected game type. + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + // Update the respected game type to 0xbeef. + vm.prank(optimismPortal2.guardian()); + optimismPortal2.setRespectedGameType(GameType.wrap(0xbeef)); + + // Create a new game and mock the game type as 0xbeef in the factory. + IDisputeGame newGame = + disputeGameFactory.create(GameType.wrap(0), Claim.wrap(_outputRoot), abi.encode(_proposedBlockNumber + 1)); + vm.mockCall( + address(disputeGameFactory), + abi.encodeCall(disputeGameFactory.gameAtIndex, (_proposedGameIndex + 1)), + abi.encode(GameType.wrap(0xbeef), Timestamp.wrap(uint64(block.timestamp)), IDisputeGame(address(newGame))) + ); + + // Re-proving should be successful against the new game. + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex + 1, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + + /// @dev Tests that `proveWithdrawalTransaction` succeeds. + function test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() external { + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` succeeds. + function test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() external { + uint256 bobBalanceBefore = address(bob).balance; + + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + // Warp and resolve the dispute game. + game.resolveClaim(0); + game.resolve(); + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1 seconds); + + vm.expectEmit(true, true, false, true); + emit WithdrawalFinalized(_withdrawalHash, true); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + + assert(address(bob).balance == bobBalanceBefore + 100); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the contract is paused. + function test_finalizeWithdrawalTransaction_paused_reverts() external { + vm.prank(optimismPortal2.GUARDIAN()); + superchainConfig.pause("identifier"); + + vm.expectRevert("OptimismPortal: paused"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has not been + function test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() external { + uint256 bobBalanceBefore = address(bob).balance; + + vm.expectRevert("OptimismPortal: withdrawal has not been proven yet"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + + assert(address(bob).balance == bobBalanceBefore); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has not been + /// proven long enough ago. + function test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() external { + uint256 bobBalanceBefore = address(bob).balance; + + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + vm.expectRevert("OptimismPortal: proven withdrawal has not matured yet"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + + assert(address(bob).balance == bobBalanceBefore); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the provenWithdrawal's timestamp + /// is less than the dispute game's creation timestamp. + function test_finalizeWithdrawalTransaction_timestampLessThanGameCreation_reverts() external { + uint256 bobBalanceBefore = address(bob).balance; + + // Prove our withdrawal + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + // Warp to after the finalization period + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); + + // Mock a createdAt change in the dispute game. + vm.mockCall(address(game), abi.encodeWithSignature("createdAt()"), abi.encode(block.timestamp + 1)); + + // Attempt to finalize the withdrawal + vm.expectRevert("OptimismPortal: withdrawal timestamp less than dispute game creation timestamp"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + + // Ensure that bob's balance has remained the same + assertEq(bobBalanceBefore, address(bob).balance); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the dispute game has not resolved in favor of the + /// root claim. + function test_finalizeWithdrawalTransaction_ifDisputeGameNotResolved_reverts() external { + uint256 bobBalanceBefore = address(bob).balance; + + // Prove our withdrawal + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + // Warp to after the finalization period + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); + + // Attempt to finalize the withdrawal + vm.expectRevert("OptimismPortal: output proposal has not been finalized yet"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + + // Ensure that bob's balance has remained the same + assertEq(bobBalanceBefore, address(bob).balance); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the target reverts. + function test_finalizeWithdrawalTransaction_targetFails_fails() external { + uint256 bobBalanceBefore = address(bob).balance; + vm.etch(bob, hex"fe"); // Contract with just the invalid opcode. + + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + // Resolve the dispute game. + game.resolveClaim(0); + game.resolve(); + + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); + vm.expectEmit(true, true, true, true); + emit WithdrawalFinalized(_withdrawalHash, false); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + + assert(address(bob).balance == bobBalanceBefore); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal has already been + /// finalized. + function test_finalizeWithdrawalTransaction_onReplay_reverts() external { + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + // Resolve the dispute game. + game.resolveClaim(0); + game.resolve(); + + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); + vm.expectEmit(true, true, true, true); + emit WithdrawalFinalized(_withdrawalHash, true); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + + vm.expectRevert("OptimismPortal: withdrawal has already been finalized"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal transaction + /// does not have enough gas to execute. + function test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() external { + // This number was identified through trial and error. + uint256 gasLimit = 150_000; + Types.WithdrawalTransaction memory insufficientGasTx = Types.WithdrawalTransaction({ + nonce: 0, + sender: alice, + target: bob, + value: 100, + gasLimit: gasLimit, + data: hex"" + }); + + // Get updated proof inputs. + (bytes32 stateRoot, bytes32 storageRoot,,, bytes[] memory withdrawalProof) = + ffi.getProveWithdrawalTransactionInputs(insufficientGasTx); + Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({ + version: bytes32(0), + stateRoot: stateRoot, + messagePasserStorageRoot: storageRoot, + latestBlockhash: bytes32(0) + }); + + vm.mockCall( + address(game), abi.encodeCall(game.rootClaim, ()), abi.encode(Hashing.hashOutputRootProof(outputRootProof)) + ); + + optimismPortal2.proveWithdrawalTransaction({ + _tx: insufficientGasTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: outputRootProof, + _withdrawalProof: withdrawalProof + }); + + // Resolve the dispute game. + game.resolveClaim(0); + game.resolve(); + + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); + vm.expectRevert("SafeCall: Not enough gas"); + optimismPortal2.finalizeWithdrawalTransaction{ gas: gasLimit }(insufficientGasTx); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if a sub-call attempts to finalize + /// another withdrawal. + function test_finalizeWithdrawalTransaction_onReentrancy_reverts() external { + uint256 bobBalanceBefore = address(bob).balance; + + // Copy and modify the default test values to attempt a reentrant call by first calling to + // this contract's callPortalAndExpectRevert() function above. + Types.WithdrawalTransaction memory _testTx = _defaultTx; + _testTx.target = address(this); + _testTx.data = abi.encodeWithSelector(this.callPortalAndExpectRevert.selector); + + // Get modified proof inputs. + ( + bytes32 stateRoot, + bytes32 storageRoot, + bytes32 outputRoot, + bytes32 withdrawalHash, + bytes[] memory withdrawalProof + ) = ffi.getProveWithdrawalTransactionInputs(_testTx); + Types.OutputRootProof memory outputRootProof = Types.OutputRootProof({ + version: bytes32(0), + stateRoot: stateRoot, + messagePasserStorageRoot: storageRoot, + latestBlockhash: bytes32(0) + }); + + // Return a mock output root from the game. + vm.mockCall(address(game), abi.encodeCall(game.rootClaim, ()), abi.encode(outputRoot)); + + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(withdrawalHash, alice, address(this)); + optimismPortal2.proveWithdrawalTransaction(_testTx, _proposedGameIndex, outputRootProof, withdrawalProof); + + // Resolve the dispute game. + game.resolveClaim(0); + game.resolve(); + + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); + vm.expectCall(address(this), _testTx.data); + vm.expectEmit(true, true, true, true); + emit WithdrawalFinalized(withdrawalHash, true); + optimismPortal2.finalizeWithdrawalTransaction(_testTx); + + // Ensure that bob's balance was not changed by the reentrant call. + assert(address(bob).balance == bobBalanceBefore); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` succeeds. + function testDiff_finalizeWithdrawalTransaction_succeeds( + address _sender, + address _target, + uint256 _value, + uint256 _gasLimit, + bytes memory _data + ) + external + { + vm.assume( + _target != address(optimismPortal2) // Cannot call the optimism portal or a contract + && _target.code.length == 0 // No accounts with code + && _target != CONSOLE // The console has no code but behaves like a contract + && uint160(_target) > 9 // No precompiles (or zero address) + ); + + // Total ETH supply is currently about 120M ETH. + uint256 value = bound(_value, 0, 200_000_000 ether); + vm.deal(address(optimismPortal2), value); + + uint256 gasLimit = bound(_gasLimit, 0, 50_000_000); + uint256 nonce = l2ToL1MessagePasser.messageNonce(); + + // Get a withdrawal transaction and mock proof from the differential testing script. + Types.WithdrawalTransaction memory _tx = Types.WithdrawalTransaction({ + nonce: nonce, + sender: _sender, + target: _target, + value: value, + gasLimit: gasLimit, + data: _data + }); + ( + bytes32 stateRoot, + bytes32 storageRoot, + bytes32 outputRoot, + bytes32 withdrawalHash, + bytes[] memory withdrawalProof + ) = ffi.getProveWithdrawalTransactionInputs(_tx); + + // Create the output root proof + Types.OutputRootProof memory proof = Types.OutputRootProof({ + version: bytes32(uint256(0)), + stateRoot: stateRoot, + messagePasserStorageRoot: storageRoot, + latestBlockhash: bytes32(uint256(0)) + }); + + // Ensure the values returned from ffi are correct + assertEq(outputRoot, Hashing.hashOutputRootProof(proof)); + assertEq(withdrawalHash, Hashing.hashWithdrawal(_tx)); + + // Setup the dispute game to return the output root + vm.mockCall(address(game), abi.encodeCall(game.rootClaim, ()), abi.encode(outputRoot)); + + // Prove the withdrawal transaction + optimismPortal2.proveWithdrawalTransaction(_tx, _proposedGameIndex, proof, withdrawalProof); + (IDisputeGame _game,) = optimismPortal2.provenWithdrawals(withdrawalHash); + assertTrue(_game.rootClaim().raw() != bytes32(0)); + + // Resolve the dispute game + game.resolveClaim(0); + game.resolve(); + + // Warp past the finalization period + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); + + // Finalize the withdrawal transaction + vm.expectCallMinGas(_tx.target, _tx.value, uint64(_tx.gasLimit), _tx.data); + optimismPortal2.finalizeWithdrawalTransaction(_tx); + assertTrue(optimismPortal2.finalizedWithdrawals(withdrawalHash)); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal's dispute game has been blacklisted. + function test_finalizeWithdrawalTransaction_blacklisted_reverts() external { + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + // Resolve the dispute game. + game.resolveClaim(0); + game.resolve(); + + vm.prank(optimismPortal2.guardian()); + optimismPortal2.blacklistDisputeGame(IDisputeGame(address(game))); + + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); + + vm.expectRevert("OptimismPortal: dispute game has been blacklisted"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the withdrawal's dispute game is still in the air + /// gap. + function test_finalizeWithdrawalTransaction_gameInAirGap_reverts() external { + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + // Warp past the finalization period. + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); + + // Resolve the dispute game. + game.resolveClaim(0); + game.resolve(); + + // Attempt to finalize the withdrawal directly after the game resolves. This should fail. + vm.expectRevert("OptimismPortal: output proposal in air-gap"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + + // Finalize the withdrawal transaction. This should succeed. + vm.warp(block.timestamp + optimismPortal2.disputeGameFinalityDelaySeconds() + 1); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + assertTrue(optimismPortal2.finalizedWithdrawals(_withdrawalHash)); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the respected game type has changed since the + /// withdrawal was proven. + function test_finalizeWithdrawalTransaction_respectedTypeChangedSinceProving_reverts() external { + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + // Warp past the finalization period. + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); + + // Resolve the dispute game. + game.resolveClaim(0); + game.resolve(); + + // Change the respected game type in the portal. + vm.prank(optimismPortal2.guardian()); + optimismPortal2.setRespectedGameType(GameType.wrap(0xFF)); + + vm.expectRevert("OptimismPortal: invalid game type"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + } + + /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the respected game type was updated after the + /// dispute game was created. + function test_finalizeWithdrawalTransaction_gameOlderThanRespectedGameTypeUpdate_reverts() external { + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + // Warp past the finalization period. + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); + + // Resolve the dispute game. + game.resolveClaim(0); + game.resolve(); + + // Change the respected game type in the portal. + vm.prank(optimismPortal2.guardian()); + optimismPortal2.setRespectedGameType(GameType.wrap(0xFF)); + + // Mock the game's type so that we pass the correct game type check. + vm.mockCall(address(game), abi.encodeCall(game.gameType, ()), abi.encode(GameType.wrap(0xFF))); + + vm.expectRevert("OptimismPortal: dispute game created before respected game type was updated"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + } + + /// @dev Tests an e2e prove -> finalize path, checking the edges of each delay for correctness. + function test_finalizeWithdrawalTransaction_delayEdges_succeeds() external { + // Prove the withdrawal transaction. + vm.expectEmit(true, true, true, true); + emit WithdrawalProven(_withdrawalHash, alice, bob); + optimismPortal2.proveWithdrawalTransaction({ + _tx: _defaultTx, + _disputeGameIndex: _proposedGameIndex, + _outputRootProof: _outputRootProof, + _withdrawalProof: _withdrawalProof + }); + + // Attempt to finalize the withdrawal transaction 1 second before the proof has matured. This should fail. + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds()); + vm.expectRevert("OptimismPortal: proven withdrawal has not matured yet"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + + // Warp 1 second in the future, past the proof maturity delay, and attempt to finalize the withdrawal. + // This should also fail, since the dispute game has not resolved yet. + vm.warp(block.timestamp + 1 seconds); + vm.expectRevert("OptimismPortal: output proposal has not been finalized yet"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + + // Finalize the dispute game and attempt to finalize the withdrawal again. This should also fail, since the + // air gap dispute game delay has not elapsed. + game.resolveClaim(0); + game.resolve(); + vm.warp(block.timestamp + optimismPortal2.disputeGameFinalityDelaySeconds()); + vm.expectRevert("OptimismPortal: output proposal in air-gap"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + + // Warp 1 second in the future, past the air gap dispute game delay, and attempt to finalize the withdrawal. + // This should succeed. + vm.warp(block.timestamp + 1 seconds); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + assertTrue(optimismPortal2.finalizedWithdrawals(_withdrawalHash)); + } +} + +contract OptimismPortal2_Upgradeable_Test is CommonTest { + function setUp() public override { + super.enableFaultProofs(); + super.setUp(); + } + + /// @dev Tests that the proxy is initialized correctly. + function test_params_initValuesOnProxy_succeeds() external { + (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = optimismPortal2.params(); + ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); + + assertEq(prevBaseFee, rcfg.minimumBaseFee); + assertEq(prevBoughtGas, 0); + assertEq(prevBlockNum, block.number); + } + + /// @dev Tests that the proxy can be upgraded. + function test_upgradeToAndCall_upgrading_succeeds() external { + // Check an unused slot before upgrading. + bytes32 slot21Before = vm.load(address(optimismPortal2), bytes32(uint256(21))); + assertEq(bytes32(0), slot21Before); + + NextImpl nextImpl = new NextImpl(); + + vm.startPrank(EIP1967Helper.getAdmin(address(optimismPortal2))); + // The value passed to the initialize must be larger than the last value + // that initialize was called with. + Proxy(payable(address(optimismPortal2))).upgradeToAndCall( + address(nextImpl), abi.encodeWithSelector(NextImpl.initialize.selector, 2) + ); + assertEq(Proxy(payable(address(optimismPortal2))).implementation(), address(nextImpl)); + + // Verify that the NextImpl contract initialized its values according as expected + bytes32 slot21After = vm.load(address(optimismPortal2), bytes32(uint256(21))); + bytes32 slot21Expected = NextImpl(address(optimismPortal2)).slot21Init(); + assertEq(slot21Expected, slot21After); + } +} + +/// @title OptimismPortal2_ResourceFuzz_Test +/// @dev Test various values of the resource metering config to ensure that deposits cannot be +/// broken by changing the config. +contract OptimismPortal2_ResourceFuzz_Test is CommonTest { + /// @dev The max gas limit observed throughout this test. Setting this too high can cause + /// the test to take too long to run. + uint256 constant MAX_GAS_LIMIT = 30_000_000; + + function setUp() public override { + super.enableFaultProofs(); + super.setUp(); + } + + /// @dev Test that various values of the resource metering config will not break deposits. + function testFuzz_systemConfigDeposit_succeeds( + uint32 _maxResourceLimit, + uint8 _elasticityMultiplier, + uint8 _baseFeeMaxChangeDenominator, + uint32 _minimumBaseFee, + uint32 _systemTxMaxGas, + uint128 _maximumBaseFee, + uint64 _gasLimit, + uint64 _prevBoughtGas, + uint128 _prevBaseFee, + uint8 _blockDiff + ) + external + { + // Get the set system gas limit + uint64 gasLimit = systemConfig.gasLimit(); + // Bound resource config + _maxResourceLimit = uint32(bound(_maxResourceLimit, 21000, MAX_GAS_LIMIT / 8)); + _gasLimit = uint64(bound(_gasLimit, 21000, _maxResourceLimit)); + _prevBaseFee = uint128(bound(_prevBaseFee, 0, 3 gwei)); + // Prevent values that would cause reverts + vm.assume(gasLimit >= _gasLimit); + vm.assume(_minimumBaseFee < _maximumBaseFee); + vm.assume(_baseFeeMaxChangeDenominator > 1); + vm.assume(uint256(_maxResourceLimit) + uint256(_systemTxMaxGas) <= gasLimit); + vm.assume(_elasticityMultiplier > 0); + vm.assume(((_maxResourceLimit / _elasticityMultiplier) * _elasticityMultiplier) == _maxResourceLimit); + _prevBoughtGas = uint64(bound(_prevBoughtGas, 0, _maxResourceLimit - _gasLimit)); + _blockDiff = uint8(bound(_blockDiff, 0, 3)); + // Pick a pseudorandom block number + vm.roll(uint256(keccak256(abi.encode(_blockDiff))) % uint256(type(uint16).max) + uint256(_blockDiff)); + + // Create a resource config to mock the call to the system config with + ResourceMetering.ResourceConfig memory rcfg = ResourceMetering.ResourceConfig({ + maxResourceLimit: _maxResourceLimit, + elasticityMultiplier: _elasticityMultiplier, + baseFeeMaxChangeDenominator: _baseFeeMaxChangeDenominator, + minimumBaseFee: _minimumBaseFee, + systemTxMaxGas: _systemTxMaxGas, + maximumBaseFee: _maximumBaseFee + }); + vm.mockCall( + address(systemConfig), abi.encodeWithSelector(systemConfig.resourceConfig.selector), abi.encode(rcfg) + ); + + // Set the resource params + uint256 _prevBlockNum = block.number - _blockDiff; + vm.store( + address(optimismPortal2), + bytes32(uint256(1)), + bytes32((_prevBlockNum << 192) | (uint256(_prevBoughtGas) << 128) | _prevBaseFee) + ); + // Ensure that the storage setting is correct + (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = optimismPortal2.params(); + assertEq(prevBaseFee, _prevBaseFee); + assertEq(prevBoughtGas, _prevBoughtGas); + assertEq(prevBlockNum, _prevBlockNum); + + // Do a deposit, should not revert + optimismPortal2.depositTransaction{ gas: MAX_GAS_LIMIT }({ + _to: address(0x20), + _value: 0x40, + _gasLimit: _gasLimit, + _isCreation: false, + _data: hex"" + }); + } +} diff --git a/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol index 98ec6511cac7..eb9e1f30a91b 100644 --- a/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.15; // Testing utilities import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; import { Reverter, ConfigurableCaller } from "test/mocks/Callers.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; // Libraries import { Hashing } from "src/libraries/Hashing.sol"; @@ -21,10 +22,11 @@ contract L2CrossDomainMessenger_Test is Bridge_Initializer { /// @dev Tests that the implementation is initialized correctly. function test_constructor_succeeds() external { - L2CrossDomainMessenger impl = L2CrossDomainMessenger(deploy.mustGetAddress("L2CrossDomainMessenger")); - assertEq(address(impl.OTHER_MESSENGER()), address(l1CrossDomainMessenger)); - assertEq(address(impl.otherMessenger()), address(l1CrossDomainMessenger)); - assertEq(address(impl.l1CrossDomainMessenger()), address(l1CrossDomainMessenger)); + L2CrossDomainMessenger impl = + L2CrossDomainMessenger(EIP1967Helper.getImplementation(deploy.mustGetAddress("L2CrossDomainMessenger"))); + assertEq(address(impl.OTHER_MESSENGER()), address(0)); + assertEq(address(impl.otherMessenger()), address(0)); + assertEq(address(impl.l1CrossDomainMessenger()), address(0)); } /// @dev Tests that the proxy is initialized correctly. diff --git a/packages/contracts-bedrock/test/L2/L2ERC721Bridge.t.sol b/packages/contracts-bedrock/test/L2/L2ERC721Bridge.t.sol index 41e4feac39a6..af79149b2a90 100644 --- a/packages/contracts-bedrock/test/L2/L2ERC721Bridge.t.sol +++ b/packages/contracts-bedrock/test/L2/L2ERC721Bridge.t.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +import { console } from "forge-std/console.sol"; + // Testing utilities import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; @@ -133,7 +135,7 @@ contract L2ERC721Bridge_Test is Bridge_Initializer { function test_bridgeERC721_localTokenZeroAddress_reverts() external { // Bridge the token. vm.prank(alice); - vm.expectRevert(); + vm.expectRevert(bytes("")); l2ERC721Bridge.bridgeERC721(address(0), address(remoteToken), tokenId, 1234, hex"5678"); // Token is not locked in the bridge. @@ -198,7 +200,7 @@ contract L2ERC721Bridge_Test is Bridge_Initializer { function test_bridgeERC721To_localTokenZeroAddress_reverts() external { // Bridge the token. vm.prank(alice); - vm.expectRevert(); + vm.expectRevert(bytes("")); l2ERC721Bridge.bridgeERC721To(address(0), address(l1ERC721Bridge), bob, tokenId, 1234, hex"5678"); // Token is not locked in the bridge. diff --git a/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol b/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol index 356af2d66ee9..db6560dafecb 100644 --- a/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol @@ -2,6 +2,8 @@ pragma solidity 0.8.15; // Testing utilities +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; + // Target contract is imported by the `Bridge_Initializer` import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; import { stdStorage, StdStorage } from "forge-std/Test.sol"; @@ -24,12 +26,12 @@ contract L2StandardBridge_Test is Bridge_Initializer { /// @dev Test that the bridge's constructor sets the correct values. function test_constructor_succeeds() external { - L2StandardBridge impl = L2StandardBridge(deploy.mustGetAddress("L2StandardBridge")); - assertEq(address(impl.MESSENGER()), address(l2CrossDomainMessenger)); - assertEq(address(impl.messenger()), address(l2CrossDomainMessenger)); - assertEq(l1StandardBridge.l2TokenBridge(), address(impl)); - assertEq(address(impl.OTHER_BRIDGE()), address(l1StandardBridge)); - assertEq(address(impl.otherBridge()), address(l1StandardBridge)); + L2StandardBridge impl = + L2StandardBridge(payable(EIP1967Helper.getImplementation(deploy.mustGetAddress("L2StandardBridge")))); + assertEq(address(impl.MESSENGER()), address(0)); + assertEq(address(impl.messenger()), address(0)); + assertEq(address(impl.OTHER_BRIDGE()), address(0)); + assertEq(address(impl.otherBridge()), address(0)); } /// @dev Tests that the bridge is initialized correctly. diff --git a/packages/contracts-bedrock/test/Specs.t.sol b/packages/contracts-bedrock/test/Specs.t.sol index d0f48f56298c..ee6747fbff85 100644 --- a/packages/contracts-bedrock/test/Specs.t.sol +++ b/packages/contracts-bedrock/test/Specs.t.sol @@ -6,7 +6,10 @@ import { Executables } from "scripts/Executables.sol"; import { console2 as console } from "forge-std/console2.sol"; import { ProtocolVersions } from "src/L1/ProtocolVersions.sol"; import { OptimismPortal } from "src/L1/OptimismPortal.sol"; +import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; +import { DataAvailabilityChallenge } from "src/L1/DataAvailabilityChallenge.sol"; +import { ForgeArtifacts } from "scripts/ForgeArtifacts.sol"; /// @title Specification_Test /// @dev Specifies common security properties of entrypoints to L1 contracts, including authorization and @@ -34,7 +37,8 @@ contract Specification_Test is CommonTest { MESSENGER, L1PROXYADMINOWNER, GOVERNANCETOKENOWNER, - MINTMANAGEROWNER + MINTMANAGEROWNER, + DATAAVAILABILITYCHALLENGEOWNER } /// @notice Represents the specification of a function. @@ -55,6 +59,47 @@ contract Specification_Test is CommonTest { function setUp() public override { super.setUp(); + // DataAvailabilityChallenge + _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("owner()") }); + _addSpec({ + _name: "DataAvailabilityChallenge", + _sel: _getSel("renounceOwnership()"), + _auth: Role.DATAAVAILABILITYCHALLENGEOWNER + }); + _addSpec({ + _name: "DataAvailabilityChallenge", + _sel: _getSel("transferOwnership(address)"), + _auth: Role.DATAAVAILABILITYCHALLENGEOWNER + }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("version()") }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("fixedResolutionCost()") }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("variableResolutionCost()") }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("variableResolutionCostPrecision()") }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("bondSize()") }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("challengeWindow()") }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("resolveWindow()") }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("resolverRefundPercentage()") }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: _getSel("balances(address)") }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.initialize.selector }); + _addSpec({ + _name: "DataAvailabilityChallenge", + _sel: DataAvailabilityChallenge.setBondSize.selector, + _auth: Role.DATAAVAILABILITYCHALLENGEOWNER + }); + _addSpec({ + _name: "DataAvailabilityChallenge", + _sel: DataAvailabilityChallenge.setResolverRefundPercentage.selector, + _auth: Role.DATAAVAILABILITYCHALLENGEOWNER + }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.deposit.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.withdraw.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.getChallenge.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.getChallengeStatus.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.validateCommitment.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.challenge.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.resolve.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: DataAvailabilityChallenge.unlockBond.selector }); + // DelayedVetoable _addSpec({ _name: "DelayedVetoable", _sel: _getSel("delay()") }); _addSpec({ _name: "DelayedVetoable", _sel: _getSel("initiator()") }); @@ -222,6 +267,38 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OptimismPortal", _sel: _getSel("systemConfig()") }); _addSpec({ _name: "OptimismPortal", _sel: _getSel("version()") }); + // OptimismPortal2 + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("GUARDIAN()") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("SYSTEM_CONFIG()") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("depositTransaction(address,uint256,uint64,bool,bytes)") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("donateETH()") }); + _addSpec({ + _name: "OptimismPortal2", + _sel: OptimismPortal2.finalizeWithdrawalTransaction.selector, + _pausable: true + }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("finalizedWithdrawals(bytes32)") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("guardian()") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("initialize(address,address,address)") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("l2Sender()") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("minimumGasLimit(uint64)") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("params()") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("paused()") }); + _addSpec({ _name: "OptimismPortal2", _sel: OptimismPortal2.proveWithdrawalTransaction.selector, _pausable: true }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("provenWithdrawals(bytes32)") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("superchainConfig()") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("systemConfig()") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("version()") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("disputeGameFactory()") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("disputeGameBlacklist(address)") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("respectedGameType()") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("blacklistDisputeGame(address)"), _auth: Role.GUARDIAN }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("setRespectedGameType(uint32)"), _auth: Role.GUARDIAN }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("checkWithdrawal(bytes32)") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("proofMaturityDelaySeconds()") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("disputeGameFinalityDelaySeconds()") }); + _addSpec({ _name: "OptimismPortal2", _sel: _getSel("respectedGameTypeUpdatedAt()") }); + // ProtocolVersions _addSpec({ _name: "ProtocolVersions", _sel: _getSel("RECOMMENDED_SLOT()") }); _addSpec({ _name: "ProtocolVersions", _sel: _getSel("REQUIRED_SLOT()") }); @@ -447,7 +524,7 @@ contract Specification_Test is CommonTest { for (uint256 i; i < contractNames.length; i++) { string memory contractName = contractNames[i]; - string[] memory methodIdentifiers = deploy.getMethodIdentifiers(contractName); + string[] memory methodIdentifiers = ForgeArtifacts.getMethodIdentifiers(contractName); abis_[i].contractName = contractName; abis_[i].entries = new AbiEntry[](methodIdentifiers.length); for (uint256 j; j < methodIdentifiers.length; j++) { diff --git a/packages/contracts-bedrock/test/actors/FaultDisputeActors.sol b/packages/contracts-bedrock/test/actors/FaultDisputeActors.sol index 9f0d2674d1c3..d1bf6456e2c8 100644 --- a/packages/contracts-bedrock/test/actors/FaultDisputeActors.sol +++ b/packages/contracts-bedrock/test/actors/FaultDisputeActors.sol @@ -399,7 +399,7 @@ contract HonestDisputeActor is DisputeActor { challengeIndex := mload(add(moveData, 0x24)) } GAME.addLocalData({ - _ident: LocalPreimageKey.STARTING_L2_BLOCK_NUMBER, + _ident: LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, _execLeafIdx: challengeIndex, _partOffset: 0 }); diff --git a/packages/contracts-bedrock/test/cannon/PreimageOracle.t.sol b/packages/contracts-bedrock/test/cannon/PreimageOracle.t.sol index 2a9f59c66826..2ca5f08cbc78 100644 --- a/packages/contracts-bedrock/test/cannon/PreimageOracle.t.sol +++ b/packages/contracts-bedrock/test/cannon/PreimageOracle.t.sol @@ -171,6 +171,95 @@ contract PreimageOracle_Test is Test { vm.expectRevert("pre-image must exist"); oracle.readPreimage(key, offset); } + + /// @notice Tests that a precompile pre-image result is correctly set. + function test_loadPrecompilePreimagePart_succeeds() public { + bytes memory input = hex"deadbeef"; + uint256 offset = 0; + address precompile = address(bytes20(uint160(0x02))); // sha256 + bytes32 key = precompilePreimageKey(precompile, input); + oracle.loadPrecompilePreimagePart(offset, precompile, input); + + bytes32 part = oracle.preimageParts(key, offset); + // size prefix - 1-byte result + 32-byte sha return data + assertEq(hex"0000000000000021", bytes8(part)); + // precompile result + assertEq(bytes1(0x01), bytes1(part << 64)); + // precompile call return data + assertEq(bytes23(sha256(input)), bytes23(part << 72)); + + // Validate the local data length + uint256 length = oracle.preimageLengths(key); + assertEq(length, 1 + 32); + + // Validate that the first local data part is set + bool ok = oracle.preimagePartOk(key, offset); + assertTrue(ok); + } + + /// @notice Tests that a precompile pre-image result is correctly set at its return data offset. + function test_loadPrecompilePreimagePart_atReturnOffset_succeeds() public { + bytes memory input = hex"deadbeef"; + uint256 offset = 9; + address precompile = address(bytes20(uint160(0x02))); // sha256 + bytes32 key = precompilePreimageKey(precompile, input); + oracle.loadPrecompilePreimagePart(offset, precompile, input); + + bytes32 part = oracle.preimageParts(key, offset); + // 32-byte sha return data + assertEq(sha256(input), part); + + // Validate the local data length + uint256 length = oracle.preimageLengths(key); + assertEq(length, 1 + 32); + + // Validate that the first local data part is set + bool ok = oracle.preimagePartOk(key, offset); + assertTrue(ok); + } + + /// @notice Tests that a failed precompile call has a zero status byte in preimage + function test_loadPrecompilePreimagePart_failedCall_succeeds() public { + bytes memory input = new bytes(193); // invalid input to induce a failed precompile call + uint256 offset = 0; + address precompile = address(bytes20(uint160(0x08))); // bn256Pairing + bytes32 key = precompilePreimageKey(precompile, input); + oracle.loadPrecompilePreimagePart(offset, precompile, input); + + bytes32 part = oracle.preimageParts(key, offset); + // size prefix - 1-byte result + 0-byte sha return data + assertEq(hex"0000000000000001", bytes8(part)); + // precompile result + assertEq(bytes1(0x00), bytes1(part << 64)); + // precompile call return data + assertEq(bytes23(0), bytes23(part << 72)); + + // Validate the local data length + uint256 length = oracle.preimageLengths(key); + assertEq(length, 1); + + // Validate that the first local data part is set + bool ok = oracle.preimagePartOk(key, offset); + assertTrue(ok); + } + + /// @notice Tests that adding a global precompile result at the part boundary reverts. + function test_loadPrecompilePreimagePart_partBoundary_reverts() public { + bytes memory input = hex"deadbeef"; + uint256 offset = 41; // 8-byte prefix + 1-byte result + 32-byte sha return data + address precompile = address(bytes20(uint160(0x02))); // sha256 + vm.expectRevert(PartOffsetOOB.selector); + oracle.loadPrecompilePreimagePart(offset, precompile, input); + } + + /// @notice Tests that a global precompile result cannot be set with an out-of-bounds offset. + function test_loadPrecompilePreimagePart_outOfBoundsOffset_reverts() public { + bytes memory input = hex"deadbeef"; + uint256 offset = 42; + address precompile = address(bytes20(uint160(0x02))); // sha256 + vm.expectRevert(PartOffsetOOB.selector); + oracle.loadPrecompilePreimagePart(offset, precompile, input); + } } contract PreimageOracle_LargePreimageProposals_Test is Test { @@ -187,6 +276,9 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { // Set `tx.origin` and `msg.sender` to `address(this)` so that it may behave like an EOA for `addLeavesLPP`. vm.startPrank(address(this), address(this)); + + // Give this address some ETH to work with. + vm.deal(address(this), 100 ether); } /// @notice Tests that the `initLPP` function reverts when the part offset is out of bounds of the full preimage. @@ -198,8 +290,9 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. + uint256 bondSize = oracle.MIN_BOND_SIZE(); vm.expectRevert(PartOffsetOOB.selector); - oracle.initLPP(TEST_UUID, 136 + 8, uint32(data.length)); + oracle.initLPP{ value: bondSize }(TEST_UUID, 136 + 8, uint32(data.length)); } /// @notice Tests that the `initLPP` function reverts when the part offset is out of bounds of the full preimage. @@ -213,8 +306,9 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. + uint256 bondSize = oracle.MIN_BOND_SIZE(); vm.expectRevert(InvalidInputSize.selector); - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: bondSize }(TEST_UUID, 0, uint32(data.length)); } /// @notice Gas snapshot for `addLeaves` @@ -226,7 +320,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree (2 keccak blocks.) LibKeccak.StateMatrix memory stateMatrix; @@ -245,13 +339,33 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { console.log("Gas for 4MB: %d", (gasUsed / data.length) * 4000000); } + /// @notice Tests that `addLeavesLPP` sets the proposal as countered when `_finalize = true` and the number of + /// bytes processed is less than the claimed size. + function test_addLeaves_mismatchedSize_succeeds() public { + // Allocate the preimage data. + bytes memory data = new bytes(136); + for (uint256 i; i < data.length; i++) { + data[i] = 0xFF; + } + + // Initialize the proposal. + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length + 1)); + + // Add the leaves to the tree (2 keccak blocks.) + LibKeccak.StateMatrix memory stateMatrix; + bytes32[] memory stateCommitments = _generateStateCommitments(stateMatrix, data); + + vm.expectRevert(InvalidInputSize.selector); + oracle.addLeavesLPP(TEST_UUID, 0, data, stateCommitments, true); + } + /// @notice Tests that the `addLeavesLPP` function may never be called when `tx.origin != msg.sender` function test_addLeaves_notEOA_reverts() public { // Allocate the preimage data. bytes memory data = new bytes(136 * 500); // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree (2 keccak blocks.) LibKeccak.StateMatrix memory stateMatrix; @@ -271,7 +385,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { bytes memory data = new bytes(136 * 500); // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree (2 keccak blocks.) LibKeccak.StateMatrix memory stateMatrix; @@ -291,7 +405,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Ensure that the proposal keys are present in the array. (address claimant, uint256 uuid) = oracle.proposals(0); assertEq(oracle.proposalCount(), 1); @@ -371,7 +485,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree (2 keccak blocks.) LibKeccak.StateMatrix memory stateMatrix; @@ -396,6 +510,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { vm.warp(block.timestamp + oracle.challengePeriod() + 1 seconds); // Finalize the proposal. + uint256 balanceBefore = address(this).balance; oracle.squeezeLPP({ _claimant: address(this), _uuid: TEST_UUID, @@ -405,8 +520,10 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { _postState: leaves[1], _postStateProof: postProof }); + assertEq(address(this).balance, balanceBefore + oracle.MIN_BOND_SIZE()); + assertEq(oracle.proposalBonds(address(this), TEST_UUID), 0); - bytes32 finalDigest = keccak256(data); + bytes32 finalDigest = _setStatusByte(keccak256(data), 2); bytes32 expectedPart = bytes32((~uint256(0) & ~(uint256(type(uint64).max) << 192)) | (data.length << 192)); assertTrue(oracle.preimagePartOk(finalDigest, 0)); assertEq(oracle.preimageLengths(finalDigest), data.length); @@ -423,7 +540,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { bytes memory phonyData = new bytes(136); // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree with mismatching state commitments. LibKeccak.StateMatrix memory stateMatrix; @@ -482,7 +599,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree (2 keccak blocks.) LibKeccak.StateMatrix memory stateMatrix; @@ -515,7 +632,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Construct the leaf preimage data for the blocks added. LibKeccak.StateMatrix memory matrix; @@ -543,7 +660,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree (2 keccak blocks.) LibKeccak.StateMatrix memory stateMatrix; @@ -589,7 +706,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree (2 keccak blocks.) LibKeccak.StateMatrix memory stateMatrix; @@ -626,49 +743,77 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { }); } - /// @notice Tests that the `squeeze` function reverts when the claimed size is not equal to the bytes processed. - function test_squeeze_invalidClaimedSize_reverts() public { + /// @notice Tests that squeezing a large preimage proposal after the challenge period has passed always succeeds and + /// persists the correct data. + function testFuzz_squeeze_succeeds(uint256 _numBlocks, uint32 _partOffset) public { + _numBlocks = bound(_numBlocks, 1, 2 ** 8); + _partOffset = uint32(bound(_partOffset, 0, _numBlocks * LibKeccak.BLOCK_SIZE_BYTES + 8 - 1)); + // Allocate the preimage data. - bytes memory data = new bytes(136); + bytes memory data = new bytes(136 * _numBlocks); for (uint256 i; i < data.length; i++) { - data[i] = 0xFF; + data[i] = bytes1(uint8(i % 256)); } - // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length) - 1); - - // Add the leaves to the tree (2 keccak blocks.) - LibKeccak.StateMatrix memory stateMatrix; - bytes32[] memory stateCommitments = _generateStateCommitments(stateMatrix, data); - oracle.addLeavesLPP(TEST_UUID, 0, data, stateCommitments, true); - - // Construct the leaf preimage data for the blocks added. - LibKeccak.StateMatrix memory matrix; - PreimageOracle.Leaf[] memory leaves = _generateLeaves(matrix, data); - - // Create a proof array with 16 elements. - bytes32[] memory preProof = new bytes32[](16); - preProof[0] = _hashLeaf(leaves[1]); - bytes32[] memory postProof = new bytes32[](16); - postProof[0] = _hashLeaf(leaves[0]); - for (uint256 i = 1; i < preProof.length; i++) { - bytes32 zeroHash = oracle.zeroHashes(i); - preProof[i] = zeroHash; - postProof[i] = zeroHash; + // Propose and squeeze a large preimage. + { + // Initialize the proposal. + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, _partOffset, uint32(data.length)); + + // Add the leaves to the tree with correct state commitments. + LibKeccak.StateMatrix memory matrixA; + bytes32[] memory stateCommitments = _generateStateCommitments(matrixA, data); + oracle.addLeavesLPP(TEST_UUID, 0, data, stateCommitments, true); + + // Construct the leaf preimage data for the blocks added. + LibKeccak.StateMatrix memory matrixB; + PreimageOracle.Leaf[] memory leaves = _generateLeaves(matrixB, data); + + // Fetch the merkle proofs for the pre/post state leaves in the proposal tree. + bytes32 canonicalRoot = oracle.getTreeRootLPP(address(this), TEST_UUID); + (bytes32 rootA, bytes32[] memory preProof) = _generateProof(leaves.length - 2, leaves); + assertEq(rootA, canonicalRoot); + (bytes32 rootB, bytes32[] memory postProof) = _generateProof(leaves.length - 1, leaves); + assertEq(rootB, canonicalRoot); + + // Warp past the challenge period. + vm.warp(block.timestamp + CHALLENGE_PERIOD + 1 seconds); + + // Squeeze the LPP. + LibKeccak.StateMatrix memory preMatrix = _stateMatrixAtBlockIndex(data, leaves.length - 1); + oracle.squeezeLPP({ + _claimant: address(this), + _uuid: TEST_UUID, + _stateMatrix: preMatrix, + _preState: leaves[leaves.length - 2], + _preStateProof: preProof, + _postState: leaves[leaves.length - 1], + _postStateProof: postProof + }); } - vm.warp(block.timestamp + oracle.challengePeriod() + 1 seconds); - - vm.expectRevert(InvalidInputSize.selector); - oracle.squeezeLPP({ - _claimant: address(this), - _uuid: TEST_UUID, - _stateMatrix: _stateMatrixAtBlockIndex(data, 1), - _preState: leaves[0], - _preStateProof: preProof, - _postState: leaves[1], - _postStateProof: postProof - }); + // Validate the preimage part + { + bytes32 finalDigest = _setStatusByte(keccak256(data), 2); + bytes32 expectedPart; + assembly { + switch lt(_partOffset, 0x08) + case true { + mstore(0x00, shl(192, mload(data))) + mstore(0x08, mload(add(data, 0x20))) + expectedPart := mload(_partOffset) + } + default { + // Clean the word after `data` so we don't get any dirty bits. + mstore(add(add(data, 0x20), mload(data)), 0x00) + expectedPart := mload(add(add(data, 0x20), sub(_partOffset, 0x08))) + } + } + + assertTrue(oracle.preimagePartOk(finalDigest, _partOffset)); + assertEq(oracle.preimageLengths(finalDigest), data.length); + assertEq(oracle.preimageParts(finalDigest, _partOffset), expectedPart); + } } /// @notice Tests that a valid leaf cannot be countered with the `challengeFirst` function. @@ -680,7 +825,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree with mismatching state commitments. LibKeccak.StateMatrix memory stateMatrix; @@ -720,7 +865,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { bytes memory phonyData = new bytes(136); // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree with mismatching state commitments. LibKeccak.StateMatrix memory stateMatrix; @@ -760,7 +905,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { bytes memory phonyData = new bytes(136); // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree with mismatching state commitments. LibKeccak.StateMatrix memory stateMatrix; @@ -781,12 +926,108 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Should succeed since the commitment was wrong. + uint256 balanceBefore = address(this).balance; oracle.challengeFirstLPP({ _claimant: address(this), _uuid: TEST_UUID, _postState: leaves[0], _postStateProof: p }); + assertEq(address(this).balance, balanceBefore + oracle.MIN_BOND_SIZE()); + assertEq(oracle.proposalBonds(address(this), TEST_UUID), 0); + + LPPMetaData metaData = oracle.proposalMetadata(address(this), TEST_UUID); + assertTrue(metaData.countered()); + } + + /// @notice Tests that challenging the first divergence in a large preimage proposal at an arbitrary location + /// in the leaf values always succeeds. + function testFuzz_challenge_arbitraryLocation_succeeds(uint256 _lastCorrectLeafIdx, uint256 _numBlocks) public { + _numBlocks = bound(_numBlocks, 1, 2 ** 8); + _lastCorrectLeafIdx = bound(_lastCorrectLeafIdx, 0, _numBlocks - 1); + + // Allocate the preimage data. + bytes memory data = new bytes(136 * _numBlocks); + + // Initialize the proposal. + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); + + // Add the leaves to the tree with corrupted state commitments. + LibKeccak.StateMatrix memory matrixA; + bytes32[] memory stateCommitments = _generateStateCommitments(matrixA, data); + for (uint256 i = _lastCorrectLeafIdx + 1; i < stateCommitments.length; i++) { + stateCommitments[i] = 0; + } + oracle.addLeavesLPP(TEST_UUID, 0, data, stateCommitments, true); + + // Construct the leaf preimage data for the blocks added and corrupt the state commitments. + LibKeccak.StateMatrix memory matrixB; + PreimageOracle.Leaf[] memory leaves = _generateLeaves(matrixB, data); + for (uint256 i = _lastCorrectLeafIdx + 1; i < leaves.length; i++) { + leaves[i].stateCommitment = 0; + } + + // Avoid stack too deep + uint256 agreedLeafIdx = _lastCorrectLeafIdx; + uint256 disputedLeafIdx = agreedLeafIdx + 1; + + // Fetch the merkle proofs for the pre/post state leaves in the proposal tree. + bytes32 canonicalRoot = oracle.getTreeRootLPP(address(this), TEST_UUID); + (bytes32 rootA, bytes32[] memory preProof) = _generateProof(agreedLeafIdx, leaves); + assertEq(rootA, canonicalRoot); + (bytes32 rootB, bytes32[] memory postProof) = _generateProof(disputedLeafIdx, leaves); + assertEq(rootB, canonicalRoot); + + LibKeccak.StateMatrix memory preMatrix = _stateMatrixAtBlockIndex(data, disputedLeafIdx); + oracle.challengeLPP({ + _claimant: address(this), + _uuid: TEST_UUID, + _stateMatrix: preMatrix, + _preState: leaves[agreedLeafIdx], + _preStateProof: preProof, + _postState: leaves[disputedLeafIdx], + _postStateProof: postProof + }); + + LPPMetaData metaData = oracle.proposalMetadata(address(this), TEST_UUID); + assertTrue(metaData.countered()); + } + + /// @notice Tests that challenging the a divergence in a large preimage proposal at the first leaf always succeeds. + function testFuzz_challengeFirst_succeeds(uint256 _numBlocks) public { + _numBlocks = bound(_numBlocks, 1, 2 ** 8); + + // Allocate the preimage data. + bytes memory data = new bytes(136 * _numBlocks); + + // Initialize the proposal. + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); + + // Add the leaves to the tree with corrupted state commitments. + bytes32[] memory stateCommitments = new bytes32[](_numBlocks + 1); + for (uint256 i = 0; i < stateCommitments.length; i++) { + stateCommitments[i] = 0; + } + oracle.addLeavesLPP(TEST_UUID, 0, data, stateCommitments, true); + + // Construct the leaf preimage data for the blocks added and corrupt the state commitments. + LibKeccak.StateMatrix memory matrixB; + PreimageOracle.Leaf[] memory leaves = _generateLeaves(matrixB, data); + for (uint256 i = 0; i < leaves.length; i++) { + leaves[i].stateCommitment = 0; + } + + // Fetch the merkle proofs for the pre/post state leaves in the proposal tree. + bytes32 canonicalRoot = oracle.getTreeRootLPP(address(this), TEST_UUID); + (bytes32 rootA, bytes32[] memory postProof) = _generateProof(0, leaves); + assertEq(rootA, canonicalRoot); + + oracle.challengeFirstLPP({ + _claimant: address(this), + _uuid: TEST_UUID, + _postState: leaves[0], + _postStateProof: postProof + }); LPPMetaData metaData = oracle.proposalMetadata(address(this), TEST_UUID); assertTrue(metaData.countered()); @@ -801,7 +1042,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree with mismatching state commitments. LibKeccak.StateMatrix memory stateMatrix; @@ -853,7 +1094,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree with mismatching state commitments. LibKeccak.StateMatrix memory stateMatrix; @@ -907,7 +1148,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree with mismatching state commitments. LibKeccak.StateMatrix memory stateMatrix; @@ -961,7 +1202,7 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { } // Initialize the proposal. - oracle.initLPP(TEST_UUID, 0, uint32(data.length)); + oracle.initLPP{ value: oracle.MIN_BOND_SIZE() }(TEST_UUID, 0, uint32(data.length)); // Add the leaves to the tree with mismatching state commitments. LibKeccak.StateMatrix memory stateMatrix; @@ -988,8 +1229,8 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { postProof[i] = zeroHash; } + uint256 balanceBefore = address(this).balance; LibKeccak.StateMatrix memory preMatrix = _stateMatrixAtBlockIndex(data, 1); - oracle.challengeLPP({ _claimant: address(this), _uuid: TEST_UUID, @@ -999,6 +1240,8 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { _postState: leaves[1], _postStateProof: postProof }); + assertEq(address(this).balance, balanceBefore + oracle.MIN_BOND_SIZE()); + assertEq(oracle.proposalBonds(address(this), TEST_UUID), 0); LPPMetaData metaData = oracle.proposalMetadata(address(this), TEST_UUID); assertTrue(metaData.countered()); @@ -1019,16 +1262,19 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { returns (PreimageOracle.Leaf[] memory leaves_) { bytes memory data = LibKeccak.padMemory(_data); - uint256 numLeaves = data.length / LibKeccak.BLOCK_SIZE_BYTES; + uint256 numCommitments = data.length / LibKeccak.BLOCK_SIZE_BYTES; - leaves_ = new PreimageOracle.Leaf[](numLeaves); - for (uint256 i = 0; i < numLeaves; i++) { + leaves_ = new PreimageOracle.Leaf[](numCommitments); + for (uint256 i = 0; i < numCommitments; i++) { bytes memory blockSlice = Bytes.slice(data, i * LibKeccak.BLOCK_SIZE_BYTES, LibKeccak.BLOCK_SIZE_BYTES); LibKeccak.absorb(_stateMatrix, blockSlice); LibKeccak.permutation(_stateMatrix); - bytes32 stateCommitment = keccak256(abi.encode(_stateMatrix)); - leaves_[i] = PreimageOracle.Leaf({ input: blockSlice, index: i, stateCommitment: stateCommitment }); + leaves_[i] = PreimageOracle.Leaf({ + input: blockSlice, + index: uint32(i), + stateCommitment: keccak256(abi.encode(_stateMatrix)) + }); } } @@ -1071,4 +1317,49 @@ contract PreimageOracle_LargePreimageProposals_Test is Test { stateCommitments_[i] = keccak256(abi.encode(_stateMatrix)); } } + + /// @notice Calls out to the `go-ffi` tool to generate a merkle proof for the leaf at `_leafIdx` in a merkle tree + /// constructed with `_leaves`. + function _generateProof( + uint256 _leafIdx, + PreimageOracle.Leaf[] memory _leaves + ) + internal + returns (bytes32 root_, bytes32[] memory proof_) + { + bytes32[] memory leaves = new bytes32[](_leaves.length); + for (uint256 i = 0; i < _leaves.length; i++) { + leaves[i] = _hashLeaf(_leaves[i]); + } + + string[] memory commands = new string[](5); + commands[0] = "scripts/go-ffi/go-ffi"; + commands[1] = "merkle"; + commands[2] = "gen_proof"; + commands[3] = vm.toString(abi.encodePacked(leaves)); + commands[4] = vm.toString(_leafIdx); + (root_, proof_) = abi.decode(vm.ffi(commands), (bytes32, bytes32[])); + } + + fallback() external payable { } + + receive() external payable { } +} + +/// @notice Sets the status byte of a hash. +function _setStatusByte(bytes32 _hash, uint8 _status) pure returns (bytes32 out_) { + assembly { + out_ := or(and(not(shl(248, 0xFF)), _hash), shl(248, _status)) + } +} + +/// @notice Computes a precompile key for a given precompile address and input. +function precompilePreimageKey(address _precompile, bytes memory _input) pure returns (bytes32 key_) { + bytes memory p = abi.encodePacked(_precompile, _input); + uint256 sz = 20 + _input.length; + assembly { + let h := keccak256(add(0x20, p), sz) + // Mask out prefix byte, replace with type 6 byte + key_ := or(and(h, not(shl(248, 0xFF))), shl(248, 6)) + } } diff --git a/packages/contracts-bedrock/test/dispute/AnchorStateRegistry.t.sol b/packages/contracts-bedrock/test/dispute/AnchorStateRegistry.t.sol new file mode 100644 index 000000000000..5089337b9d34 --- /dev/null +++ b/packages/contracts-bedrock/test/dispute/AnchorStateRegistry.t.sol @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import "src/libraries/DisputeTypes.sol"; +import "src/libraries/DisputeErrors.sol"; + +import { Test } from "forge-std/Test.sol"; +import { FaultDisputeGame_Init, _changeClaimStatus } from "test/dispute/FaultDisputeGame.t.sol"; + +contract AnchorStateRegistry_Init is FaultDisputeGame_Init { + function setUp() public virtual override { + // Duplicating the initialization/setup logic of FaultDisputeGame_Test. + // See that test for more information, actual values here not really important. + Claim rootClaim = Claim.wrap(bytes32((uint256(1) << 248) | uint256(10))); + bytes memory absolutePrestateData = abi.encode(0); + Claim absolutePrestate = _changeClaimStatus(Claim.wrap(keccak256(absolutePrestateData)), VMStatuses.UNFINISHED); + + super.setUp(); + super.init({ rootClaim: rootClaim, absolutePrestate: absolutePrestate, l2BlockNumber: 0x10 }); + } +} + +contract AnchorStateRegistry_Initialize_Test is AnchorStateRegistry_Init { + /// @dev Tests that initialization is successful. + function test_initialize_succeeds() public { + (Hash cannonRoot, uint256 cannonL2BlockNumber) = anchorStateRegistry.anchors(GameTypes.CANNON); + (Hash permissionedCannonRoot, uint256 permissionedCannonL2BlockNumber) = + anchorStateRegistry.anchors(GameTypes.PERMISSIONED_CANNON); + (Hash alphabetRoot, uint256 alphabetL2BlockNumber) = anchorStateRegistry.anchors(GameTypes.ALPHABET); + assertEq(cannonRoot.raw(), 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF); + assertEq(cannonL2BlockNumber, 0); + assertEq(permissionedCannonRoot.raw(), 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF); + assertEq(permissionedCannonL2BlockNumber, 0); + assertEq(alphabetRoot.raw(), 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF); + assertEq(alphabetL2BlockNumber, 0); + } +} + +contract AnchorStateRegistry_TryUpdateAnchorState_Test is AnchorStateRegistry_Init { + /// @dev Tests that updating the anchor state succeeds when the game state is valid and newer. + function test_tryUpdateAnchorState_validNewerState_succeeds() public { + // Confirm that the anchor state is older than the game state. + (Hash root, uint256 l2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assert(l2BlockNumber < gameProxy.l2BlockNumber()); + + // Mock the state that we want. + vm.mockCall( + address(gameProxy), abi.encodeWithSelector(gameProxy.status.selector), abi.encode(GameStatus.DEFENDER_WINS) + ); + + // Try to update the anchor state. + vm.prank(address(gameProxy)); + anchorStateRegistry.tryUpdateAnchorState(); + + // Confirm that the anchor state is now the same as the game state. + (root, l2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assertEq(l2BlockNumber, gameProxy.l2BlockNumber()); + assertEq(root.raw(), gameProxy.rootClaim().raw()); + } + + /// @dev Tests that updating the anchor state fails when the game state is valid but older. + function test_tryUpdateAnchorState_validOlderState_fails() public { + // Confirm that the anchor state is newer than the game state. + vm.mockCall(address(gameProxy), abi.encodeWithSelector(gameProxy.l2BlockNumber.selector), abi.encode(0)); + (Hash root, uint256 l2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assert(l2BlockNumber >= gameProxy.l2BlockNumber()); + + // Mock the state that we want. + vm.mockCall(address(gameProxy), abi.encodeWithSelector(gameProxy.l2BlockNumber.selector), abi.encode(0)); + vm.mockCall( + address(gameProxy), abi.encodeWithSelector(gameProxy.status.selector), abi.encode(GameStatus.DEFENDER_WINS) + ); + + // Try to update the anchor state. + vm.prank(address(gameProxy)); + anchorStateRegistry.tryUpdateAnchorState(); + + // Confirm that the anchor state has not updated. + (Hash updatedRoot, uint256 updatedL2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assertEq(updatedL2BlockNumber, l2BlockNumber); + assertEq(updatedRoot.raw(), root.raw()); + } + + /// @dev Tests that updating the anchor state fails when the game state is invalid. + function test_tryUpdateAnchorState_invalidNewerState_fails() public { + // Confirm that the anchor state is older than the game state. + (Hash root, uint256 l2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assert(l2BlockNumber < gameProxy.l2BlockNumber()); + + // Mock the state that we want. + vm.mockCall( + address(gameProxy), + abi.encodeWithSelector(gameProxy.status.selector), + abi.encode(GameStatus.CHALLENGER_WINS) + ); + + // Try to update the anchor state. + vm.prank(address(gameProxy)); + anchorStateRegistry.tryUpdateAnchorState(); + + // Confirm that the anchor state has not updated. + (Hash updatedRoot, uint256 updatedL2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assertEq(updatedL2BlockNumber, l2BlockNumber); + assertEq(updatedRoot.raw(), root.raw()); + } + + /// @dev Tests that updating the anchor state fails when the game is not registered with the factory. + function test_tryUpdateAnchorState_invalidGame_fails() public { + // Confirm that the anchor state is older than the game state. + (Hash root, uint256 l2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assert(l2BlockNumber < gameProxy.l2BlockNumber()); + + // Mock the state that we want. + vm.mockCall( + address(disputeGameFactory), + abi.encodeWithSelector( + disputeGameFactory.games.selector, gameProxy.gameType(), gameProxy.rootClaim(), gameProxy.extraData() + ), + abi.encode(address(0), 0) + ); + + // Try to update the anchor state. + vm.prank(address(gameProxy)); + vm.expectRevert("AnchorStateRegistry: fault dispute game not registered with factory"); + anchorStateRegistry.tryUpdateAnchorState(); + + // Confirm that the anchor state has not updated. + (Hash updatedRoot, uint256 updatedL2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assertEq(updatedL2BlockNumber, l2BlockNumber); + assertEq(updatedRoot.raw(), root.raw()); + } +} diff --git a/packages/contracts-bedrock/test/dispute/DelayedWETH.t.sol b/packages/contracts-bedrock/test/dispute/DelayedWETH.t.sol new file mode 100644 index 000000000000..c7afeae684e1 --- /dev/null +++ b/packages/contracts-bedrock/test/dispute/DelayedWETH.t.sol @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import "src/libraries/DisputeTypes.sol"; +import "src/libraries/DisputeErrors.sol"; + +import { Test } from "forge-std/Test.sol"; +import { DisputeGameFactory, IDisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; +import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol"; +import { Proxy } from "src/universal/Proxy.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; + +contract DelayedWETH_Init is CommonTest { + event Approval(address indexed src, address indexed guy, uint256 wad); + event Transfer(address indexed src, address indexed dst, uint256 wad); + event Deposit(address indexed dst, uint256 wad); + event Withdrawal(address indexed src, uint256 wad); + event Unwrap(address indexed src, uint256 wad); + + function setUp() public virtual override { + super.enableFaultProofs(); + super.setUp(); + + // Transfer ownership of delayed WETH to the test contract. + vm.prank(deploy.mustGetAddress("SystemOwnerSafe")); + delayedWeth.transferOwnership(address(this)); + } +} + +contract DelayedWETH_Initialize_Test is DelayedWETH_Init { + /// @dev Tests that initialization is successful. + function test_initialize_succeeds() public { + assertEq(delayedWeth.owner(), address(this)); + assertEq(address(delayedWeth.config()), address(superchainConfig)); + } +} + +contract DelayedWETH_Unlock_Test is DelayedWETH_Init { + /// @dev Tests that unlocking once is successful. + function test_unlock_once_succeeds() public { + delayedWeth.unlock(alice, 1 ether); + (uint256 amount, uint256 timestamp) = delayedWeth.withdrawals(address(this), alice); + assertEq(amount, 1 ether); + assertEq(timestamp, block.timestamp); + } + + /// @dev TEsts that unlocking twice is successful and timestamp/amount is updated. + function test_unlock_twice_succeeds() public { + // Unlock once. + uint256 ts = block.timestamp; + delayedWeth.unlock(alice, 1 ether); + (uint256 amount1, uint256 timestamp1) = delayedWeth.withdrawals(address(this), alice); + assertEq(amount1, 1 ether); + assertEq(timestamp1, ts); + + // Go forward in time. + vm.warp(ts + 1); + + // Unlock again works. + delayedWeth.unlock(alice, 1 ether); + (uint256 amount2, uint256 timestamp2) = delayedWeth.withdrawals(address(this), alice); + assertEq(amount2, 2 ether); + assertEq(timestamp2, ts + 1); + } +} + +contract DelayedWETH_Withdraw_Test is DelayedWETH_Init { + /// @dev Tests that withdrawing while unlocked and delay has passed is successful. + function test_withdraw_whileUnlocked_succeeds() public { + // Deposit some WETH. + vm.prank(alice); + delayedWeth.deposit{ value: 1 ether }(); + uint256 balance = address(alice).balance; + + // Unlock the withdrawal. + vm.prank(alice); + delayedWeth.unlock(alice, 1 ether); + + // Wait for the delay. + vm.warp(block.timestamp + delayedWeth.delay() + 1); + + // Withdraw the WETH. + vm.expectEmit(true, true, false, false); + emit Withdrawal(address(alice), 1 ether); + vm.prank(alice); + delayedWeth.withdraw(alice, 1 ether); + assertEq(address(alice).balance, balance + 1 ether); + } + + /// @dev Tests that withdrawing when unlock was not called fails. + function test_withdraw_whileLocked_fails() public { + // Deposit some WETH. + vm.prank(alice); + delayedWeth.deposit{ value: 1 ether }(); + uint256 balance = address(alice).balance; + + // Withdraw fails when unlock not called. + vm.expectRevert("DelayedWETH: withdrawal not unlocked"); + vm.prank(alice); + delayedWeth.withdraw(alice, 0 ether); + assertEq(address(alice).balance, balance); + } + + /// @dev Tests that withdrawing while locked and delay has not passed fails. + function test_withdraw_whileLockedNotLongEnough_fails() public { + // Deposit some WETH. + vm.prank(alice); + delayedWeth.deposit{ value: 1 ether }(); + uint256 balance = address(alice).balance; + + // Call unlock. + vm.prank(alice); + delayedWeth.unlock(alice, 1 ether); + + // Wait for the delay, but not long enough. + vm.warp(block.timestamp + delayedWeth.delay() - 1); + + // Withdraw fails when delay not met. + vm.expectRevert("DelayedWETH: withdrawal delay not met"); + vm.prank(alice); + delayedWeth.withdraw(alice, 1 ether); + assertEq(address(alice).balance, balance); + } + + /// @dev Tests that withdrawing more than unlocked amount fails. + function test_withdraw_tooMuch_fails() public { + // Deposit some WETH. + vm.prank(alice); + delayedWeth.deposit{ value: 1 ether }(); + uint256 balance = address(alice).balance; + + // Unlock the withdrawal. + vm.prank(alice); + delayedWeth.unlock(alice, 1 ether); + + // Wait for the delay. + vm.warp(block.timestamp + delayedWeth.delay() + 1); + + // Withdraw too much fails. + vm.expectRevert("DelayedWETH: insufficient unlocked withdrawal"); + vm.prank(alice); + delayedWeth.withdraw(alice, 2 ether); + assertEq(address(alice).balance, balance); + } + + /// @dev Tests that withdrawing while paused fails. + function test_withdraw_whenPaused_fails() public { + // Deposit some WETH. + vm.prank(alice); + delayedWeth.deposit{ value: 1 ether }(); + + // Unlock the withdrawal. + vm.prank(alice); + delayedWeth.unlock(alice, 1 ether); + + // Wait for the delay. + vm.warp(block.timestamp + delayedWeth.delay() + 1); + + // Pause the contract. + address guardian = optimismPortal.GUARDIAN(); + vm.prank(guardian); + superchainConfig.pause("identifier"); + + // Withdraw fails. + vm.expectRevert("DelayedWETH: contract is paused"); + vm.prank(alice); + delayedWeth.withdraw(alice, 1 ether); + } +} + +contract DelayedWETH_Recover_Test is DelayedWETH_Init { + /// @dev Tests that recovering WETH succeeds. + function test_recover_succeeds() public { + // Transfer ownership to alice. + delayedWeth.transferOwnership(alice); + + // Give the contract some WETH to recover. + vm.deal(address(delayedWeth), 1 ether); + + // Record the initial balance. + uint256 initialBalance = address(alice).balance; + + // Recover the WETH. + vm.prank(alice); + delayedWeth.recover(1 ether); + + // Verify the WETH was recovered. + assertEq(address(delayedWeth).balance, 0); + assertEq(address(alice).balance, initialBalance + 1 ether); + } + + /// @dev Tests that recovering WETH by non-owner fails. + function test_recover_byNonOwner_fails() public { + // Pretend to be a non-owner. + vm.prank(alice); + + // Recover fails. + vm.expectRevert("DelayedWETH: not owner"); + delayedWeth.recover(1 ether); + } + + /// @dev Tests that recovering more than the balance recovers what it can. + function test_recover_moreThanBalance_succeeds() public { + // Transfer ownership to alice. + delayedWeth.transferOwnership(alice); + + // Give the contract some WETH to recover. + vm.deal(address(delayedWeth), 0.5 ether); + + // Record the initial balance. + uint256 initialBalance = address(alice).balance; + + // Recover the WETH. + vm.prank(alice); + delayedWeth.recover(1 ether); + + // Verify the WETH was recovered. + assertEq(address(delayedWeth).balance, 0); + assertEq(address(alice).balance, initialBalance + 0.5 ether); + } +} + +contract DelayedWETH_Hold_Test is DelayedWETH_Init { + /// @dev Tests that holding WETH succeeds. + function test_hold_succeeds() public { + uint256 amount = 1 ether; + + // Pretend to be alice and deposit some WETH. + vm.prank(alice); + delayedWeth.deposit{ value: amount }(); + + // Hold some WETH. + vm.expectEmit(true, true, true, false); + emit Approval(alice, address(this), amount); + delayedWeth.hold(alice, amount); + + // Verify the allowance. + assertEq(delayedWeth.allowance(alice, address(this)), amount); + + // We can transfer. + delayedWeth.transferFrom(alice, address(this), amount); + + // Verify the transfer. + assertEq(delayedWeth.balanceOf(address(this)), amount); + } + + /// @dev Tests that holding WETH by non-owner fails. + function test_hold_byNonOwner_fails() public { + // Pretend to be a non-owner. + vm.prank(alice); + + // Hold fails. + vm.expectRevert("DelayedWETH: not owner"); + delayedWeth.hold(bob, 1 ether); + } +} diff --git a/packages/contracts-bedrock/test/dispute/DisputeGameFactory.t.sol b/packages/contracts-bedrock/test/dispute/DisputeGameFactory.t.sol index 988de9c4ba2d..10e2e9a03060 100644 --- a/packages/contracts-bedrock/test/dispute/DisputeGameFactory.t.sol +++ b/packages/contracts-bedrock/test/dispute/DisputeGameFactory.t.sol @@ -5,13 +5,12 @@ import "src/libraries/DisputeTypes.sol"; import "src/libraries/DisputeErrors.sol"; import { Test } from "forge-std/Test.sol"; -import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; +import { DisputeGameFactory, IDisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; import { Proxy } from "src/universal/Proxy.sol"; import { CommonTest } from "test/setup/CommonTest.sol"; contract DisputeGameFactory_Init is CommonTest { - DisputeGameFactory factory; FakeClone fakeClone; event DisputeGameCreated(address indexed disputeProxy, GameType indexed gameType, Claim indexed rootClaim); @@ -19,19 +18,13 @@ contract DisputeGameFactory_Init is CommonTest { event InitBondUpdated(GameType indexed gameType, uint256 indexed newBond); function setUp() public virtual override { + super.enableFaultProofs(); super.setUp(); - - Proxy proxy = new Proxy(address(this)); - DisputeGameFactory impl = new DisputeGameFactory(); - - proxy.upgradeToAndCall({ - _implementation: address(impl), - _data: abi.encodeCall(impl.initialize, (address(this))) - }); - factory = DisputeGameFactory(address(proxy)); - vm.label(address(factory), "DisputeGameFactoryProxy"); - fakeClone = new FakeClone(); + + // Transfer ownership of the factory to the test contract. + vm.prank(deploy.mustGetAddress("SystemOwnerSafe")); + disputeGameFactory.transferOwnership(address(this)); } } @@ -54,24 +47,24 @@ contract DisputeGameFactory_Create_Test is DisputeGameFactory_Init { // Set all three implementations to the same `FakeClone` contract. for (uint8 i; i < 3; i++) { GameType lgt = GameType.wrap(i); - factory.setImplementation(lgt, IDisputeGame(address(fakeClone))); - factory.setInitBond(lgt, _value); + disputeGameFactory.setImplementation(lgt, IDisputeGame(address(fakeClone))); + disputeGameFactory.setInitBond(lgt, _value); } vm.deal(address(this), _value); vm.expectEmit(false, true, true, false); emit DisputeGameCreated(address(0), gt, rootClaim); - IDisputeGame proxy = factory.create{ value: _value }(gt, rootClaim, extraData); + IDisputeGame proxy = disputeGameFactory.create{ value: _value }(gt, rootClaim, extraData); - (IDisputeGame game, Timestamp timestamp) = factory.games(gt, rootClaim, extraData); + (IDisputeGame game, Timestamp timestamp) = disputeGameFactory.games(gt, rootClaim, extraData); // Ensure that the dispute game was assigned to the `disputeGames` mapping. assertEq(address(game), address(proxy)); assertEq(Timestamp.unwrap(timestamp), block.timestamp); - assertEq(factory.gameCount(), 1); + assertEq(disputeGameFactory.gameCount(), 1); - (, Timestamp timestamp2, IDisputeGame game2) = factory.gameAtIndex(0); + (, Timestamp timestamp2, IDisputeGame game2) = disputeGameFactory.gameAtIndex(0); assertEq(address(game2), address(proxy)); assertEq(Timestamp.unwrap(timestamp2), block.timestamp); @@ -95,24 +88,25 @@ contract DisputeGameFactory_Create_Test is DisputeGameFactory_Init { // Set all three implementations to the same `FakeClone` contract. for (uint8 i; i < 3; i++) { GameType lgt = GameType.wrap(i); - factory.setImplementation(lgt, IDisputeGame(address(fakeClone))); - factory.setInitBond(lgt, 1 ether); + disputeGameFactory.setImplementation(lgt, IDisputeGame(address(fakeClone))); + disputeGameFactory.setInitBond(lgt, 1 ether); } vm.expectRevert(InsufficientBond.selector); - factory.create(gt, rootClaim, extraData); + disputeGameFactory.create(gt, rootClaim, extraData); } /// @dev Tests that the `create` function reverts when there is no implementation /// set for the given `GameType`. - function testFuzz_create_noImpl_reverts(uint8 gameType, Claim rootClaim, bytes calldata extraData) public { - // Ensure that the `gameType` is within the bounds of the `GameType` enum's possible values. - GameType gt = GameType.wrap(uint8(bound(gameType, 0, 2))); + function testFuzz_create_noImpl_reverts(uint32 gameType, Claim rootClaim, bytes calldata extraData) public { + // Ensure that the `gameType` is within the bounds of the `GameType` enum's possible values. We skip over + // game type = 0, since the deploy script set the implementation for that game type. + GameType gt = GameType.wrap(uint32(bound(gameType, 2, type(uint32).max))); // Ensure the rootClaim has a VMStatus that disagrees with the validity. rootClaim = changeClaimStatus(rootClaim, VMStatuses.INVALID); vm.expectRevert(abi.encodeWithSelector(NoImplementation.selector, gt)); - factory.create(gt, rootClaim, extraData); + disputeGameFactory.create(gt, rootClaim, extraData); } /// @dev Tests that the `create` function reverts when there exists a dispute game with the same UUID. @@ -124,24 +118,24 @@ contract DisputeGameFactory_Create_Test is DisputeGameFactory_Init { // Set all three implementations to the same `FakeClone` contract. for (uint8 i; i < 3; i++) { - factory.setImplementation(GameType.wrap(i), IDisputeGame(address(fakeClone))); + disputeGameFactory.setImplementation(GameType.wrap(i), IDisputeGame(address(fakeClone))); } // Create our first dispute game - this should succeed. vm.expectEmit(false, true, true, false); emit DisputeGameCreated(address(0), gt, rootClaim); - IDisputeGame proxy = factory.create(gt, rootClaim, extraData); + IDisputeGame proxy = disputeGameFactory.create(gt, rootClaim, extraData); - (IDisputeGame game, Timestamp timestamp) = factory.games(gt, rootClaim, extraData); + (IDisputeGame game, Timestamp timestamp) = disputeGameFactory.games(gt, rootClaim, extraData); // Ensure that the dispute game was assigned to the `disputeGames` mapping. assertEq(address(game), address(proxy)); assertEq(Timestamp.unwrap(timestamp), block.timestamp); // Ensure that the `create` function reverts when called with parameters that would result in the same UUID. vm.expectRevert( - abi.encodeWithSelector(GameAlreadyExists.selector, factory.getGameUUID(gt, rootClaim, extraData)) + abi.encodeWithSelector(GameAlreadyExists.selector, disputeGameFactory.getGameUUID(gt, rootClaim, extraData)) ); - factory.create(gt, rootClaim, extraData); + disputeGameFactory.create(gt, rootClaim, extraData); } function changeClaimStatus(Claim _claim, VMStatus _status) public pure returns (Claim out_) { @@ -154,17 +148,14 @@ contract DisputeGameFactory_Create_Test is DisputeGameFactory_Init { contract DisputeGameFactory_SetImplementation_Test is DisputeGameFactory_Init { /// @dev Tests that the `setImplementation` function properly sets the implementation for a given `GameType`. function test_setImplementation_succeeds() public { - // There should be no implementation for the `GameTypes.CANNON` enum value, it has not been set. - assertEq(address(factory.gameImpls(GameTypes.CANNON)), address(0)); - - vm.expectEmit(true, true, true, true, address(factory)); + vm.expectEmit(true, true, true, true, address(disputeGameFactory)); emit ImplementationSet(address(1), GameTypes.CANNON); // Set the implementation for the `GameTypes.CANNON` enum value. - factory.setImplementation(GameTypes.CANNON, IDisputeGame(address(1))); + disputeGameFactory.setImplementation(GameTypes.CANNON, IDisputeGame(address(1))); // Ensure that the implementation for the `GameTypes.CANNON` enum value is set. - assertEq(address(factory.gameImpls(GameTypes.CANNON)), address(1)); + assertEq(address(disputeGameFactory.gameImpls(GameTypes.CANNON)), address(1)); } /// @dev Tests that the `setImplementation` function reverts when called by a non-owner. @@ -172,7 +163,7 @@ contract DisputeGameFactory_SetImplementation_Test is DisputeGameFactory_Init { // Ensure that the `setImplementation` function reverts when called by a non-owner. vm.prank(address(0)); vm.expectRevert("Ownable: caller is not the owner"); - factory.setImplementation(GameTypes.CANNON, IDisputeGame(address(1))); + disputeGameFactory.setImplementation(GameTypes.CANNON, IDisputeGame(address(1))); } } @@ -180,16 +171,16 @@ contract DisputeGameFactory_SetInitBond_Test is DisputeGameFactory_Init { /// @dev Tests that the `setInitBond` function properly sets the init bond for a given `GameType`. function test_setInitBond_succeeds() public { // There should be no init bond for the `GameTypes.CANNON` enum value, it has not been set. - assertEq(factory.initBonds(GameTypes.CANNON), 0); + assertEq(disputeGameFactory.initBonds(GameTypes.CANNON), 0); - vm.expectEmit(true, true, true, true, address(factory)); + vm.expectEmit(true, true, true, true, address(disputeGameFactory)); emit InitBondUpdated(GameTypes.CANNON, 1 ether); // Set the init bond for the `GameTypes.CANNON` enum value. - factory.setInitBond(GameTypes.CANNON, 1 ether); + disputeGameFactory.setInitBond(GameTypes.CANNON, 1 ether); // Ensure that the init bond for the `GameTypes.CANNON` enum value is set. - assertEq(factory.initBonds(GameTypes.CANNON), 1 ether); + assertEq(disputeGameFactory.initBonds(GameTypes.CANNON), 1 ether); } /// @dev Tests that the `setInitBond` function reverts when called by a non-owner. @@ -197,7 +188,7 @@ contract DisputeGameFactory_SetInitBond_Test is DisputeGameFactory_Init { // Ensure that the `setInitBond` function reverts when called by a non-owner. vm.prank(address(0)); vm.expectRevert("Ownable: caller is not the owner"); - factory.setInitBond(GameTypes.CANNON, 1 ether); + disputeGameFactory.setInitBond(GameTypes.CANNON, 1 ether); } } @@ -209,7 +200,8 @@ contract DisputeGameFactory_GetGameUUID_Test is DisputeGameFactory_Init { GameType gt = GameType.wrap(uint8(bound(gameType, 0, 2))); assertEq( - Hash.unwrap(factory.getGameUUID(gt, rootClaim, extraData)), keccak256(abi.encode(gt, rootClaim, extraData)) + Hash.unwrap(disputeGameFactory.getGameUUID(gt, rootClaim, extraData)), + keccak256(abi.encode(gt, rootClaim, extraData)) ); } } @@ -217,22 +209,134 @@ contract DisputeGameFactory_GetGameUUID_Test is DisputeGameFactory_Init { contract DisputeGameFactory_Owner_Test is DisputeGameFactory_Init { /// @dev Tests that the `owner` function returns the correct address after deployment. function test_owner_succeeds() public { - assertEq(factory.owner(), address(this)); + assertEq(disputeGameFactory.owner(), address(this)); } } contract DisputeGameFactory_TransferOwnership_Test is DisputeGameFactory_Init { /// @dev Tests that the `transferOwnership` function succeeds when called by the owner. function test_transferOwnership_succeeds() public { - factory.transferOwnership(address(1)); - assertEq(factory.owner(), address(1)); + disputeGameFactory.transferOwnership(address(1)); + assertEq(disputeGameFactory.owner(), address(1)); } /// @dev Tests that the `transferOwnership` function reverts when called by a non-owner. function test_transferOwnership_notOwner_reverts() public { vm.prank(address(0)); vm.expectRevert("Ownable: caller is not the owner"); - factory.transferOwnership(address(1)); + disputeGameFactory.transferOwnership(address(1)); + } +} + +contract DisputeGameFactory_FindLatestGames_Test is DisputeGameFactory_Init { + function setUp() public override { + super.setUp(); + + // Set three implementations to the same `FakeClone` contract. + for (uint8 i; i < 3; i++) { + GameType lgt = GameType.wrap(i); + disputeGameFactory.setImplementation(lgt, IDisputeGame(address(fakeClone))); + disputeGameFactory.setInitBond(lgt, 0); + } + } + + /// @dev Tests that `findLatestGames` returns an empty array when the passed starting index is greater than or equal + /// to the game count. + function testFuzz_findLatestGames_greaterThanLength_succeeds(uint256 _start) public { + // Create some dispute games of varying game types. + for (uint256 i; i < 1 << 5; i++) { + disputeGameFactory.create(GameType.wrap(uint8(i % 2)), Claim.wrap(bytes32(i)), abi.encode(i)); + } + + // Bound the starting index to a number greater than the length of the game list. + uint256 gameCount = disputeGameFactory.gameCount(); + _start = bound(_start, gameCount, type(uint256).max); + + // The array's length should always be 0. + IDisputeGameFactory.GameSearchResult[] memory games = + disputeGameFactory.findLatestGames(GameTypes.CANNON, _start, 1); + assertEq(games.length, 0); + } + + /// @dev Tests that `findLatestGames` returns the correct games. + function test_findLatestGames_static_succeeds() public { + // Create some dispute games of varying game types. + for (uint256 i; i < 1 << 5; i++) { + disputeGameFactory.create(GameType.wrap(uint8(i % 3)), Claim.wrap(bytes32(i)), abi.encode(i)); + } + + uint256 gameCount = disputeGameFactory.gameCount(); + + IDisputeGameFactory.GameSearchResult[] memory games; + + games = disputeGameFactory.findLatestGames(GameType.wrap(0), gameCount - 1, 1); + assertEq(games.length, 1); + assertEq(games[0].index, 30); + (GameType gameType, Timestamp createdAt, IDisputeGame game) = games[0].metadata.unpack(); + assertEq(gameType.raw(), 0); + assertEq(createdAt.raw(), block.timestamp); + + games = disputeGameFactory.findLatestGames(GameType.wrap(1), gameCount - 1, 1); + assertEq(games.length, 1); + assertEq(games[0].index, 31); + (gameType, createdAt, game) = games[0].metadata.unpack(); + assertEq(gameType.raw(), 1); + assertEq(createdAt.raw(), block.timestamp); + + games = disputeGameFactory.findLatestGames(GameType.wrap(2), gameCount - 1, 1); + assertEq(games.length, 1); + assertEq(games[0].index, 29); + (gameType, createdAt, game) = games[0].metadata.unpack(); + assertEq(gameType.raw(), 2); + assertEq(createdAt.raw(), block.timestamp); + } + + /// @dev Tests that `findLatestGames` returns the correct games, if there are less than `_n` games of the given type + /// available. + function test_findLatestGames_lessThanNAvailable_succeeds() public { + // Create some dispute games of varying game types. + disputeGameFactory.create(GameType.wrap(1), Claim.wrap(bytes32(0)), abi.encode(0)); + disputeGameFactory.create(GameType.wrap(1), Claim.wrap(bytes32(uint256(1))), abi.encode(1)); + for (uint256 i; i < 1 << 3; i++) { + disputeGameFactory.create(GameType.wrap(0), Claim.wrap(bytes32(i)), abi.encode(i)); + } + + uint256 gameCount = disputeGameFactory.gameCount(); + + IDisputeGameFactory.GameSearchResult[] memory games; + + games = disputeGameFactory.findLatestGames(GameType.wrap(2), gameCount - 1, 5); + assertEq(games.length, 0); + + games = disputeGameFactory.findLatestGames(GameType.wrap(1), gameCount - 1, 5); + assertEq(games.length, 2); + assertEq(games[0].index, 1); + assertEq(games[1].index, 0); + } + + /// @dev Tests that the expected number of games are returned when `findLatestGames` is called. + function testFuzz_findLatestGames_correctAmount_succeeds( + uint256 _numGames, + uint256 _numSearchedGames, + uint256 _n + ) + public + { + _numGames = bound(_numGames, 0, 1 << 8); + _numSearchedGames = bound(_numSearchedGames, 0, _numGames); + _n = bound(_n, 0, _numSearchedGames); + + // Create `_numGames` dispute games, with at least `_numSearchedGames` games. + for (uint256 i; i < _numGames; i++) { + uint8 gameType = i < _numSearchedGames ? 0 : 1; + disputeGameFactory.create(GameType.wrap(gameType), Claim.wrap(bytes32(i)), abi.encode(i)); + } + + // Ensure that the correct number of games are returned. + uint256 start = _numGames == 0 ? 0 : _numGames - 1; + IDisputeGameFactory.GameSearchResult[] memory games = + disputeGameFactory.findLatestGames(GameType.wrap(0), start, _n); + assertEq(games.length, _n); } } @@ -241,4 +345,16 @@ contract FakeClone { function initialize() external payable { // noop } + + function extraData() external pure returns (bytes memory) { + return hex"FF0420"; + } + + function parentHash() external pure returns (bytes32) { + return bytes32(0); + } + + function rootClaim() external pure returns (Claim) { + return Claim.wrap(bytes32(0)); + } } diff --git a/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol index 2433f4b8e127..3e9d6d65c6a0 100644 --- a/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol @@ -6,16 +6,15 @@ import { Vm } from "forge-std/Vm.sol"; import { DisputeGameFactory_Init } from "test/dispute/DisputeGameFactory.t.sol"; import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; -import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; +import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol"; import { PreimageOracle } from "src/cannon/PreimageOracle.sol"; -import { PreimageKeyLib } from "src/cannon/PreimageKeyLib.sol"; import "src/libraries/DisputeTypes.sol"; import "src/libraries/DisputeErrors.sol"; -import { Types } from "src/libraries/Types.sol"; import { LibClock } from "src/dispute/lib/LibUDT.sol"; import { LibPosition } from "src/dispute/lib/LibPosition.sol"; -import { IBigStepper, IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol"; +import { IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; import { AlphabetVM } from "test/mocks/AlphabetVM.sol"; import { DisputeActor, HonestDisputeActor } from "test/actors/FaultDisputeActors.sol"; @@ -34,44 +33,36 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init { event Move(uint256 indexed parentIndex, Claim indexed pivot, address indexed claimant); - function init( - Claim rootClaim, - Claim absolutePrestate, - uint256 l2BlockNumber, - uint256 genesisBlockNumber, - Hash genesisOutputRoot - ) - public - { + function init(Claim rootClaim, Claim absolutePrestate, uint256 l2BlockNumber) public { // Set the time to a realistic date. vm.warp(1690906994); // Set the extra data for the game creation extraData = abi.encode(l2BlockNumber); - AlphabetVM _vm = new AlphabetVM(absolutePrestate); + AlphabetVM _vm = new AlphabetVM(absolutePrestate, new PreimageOracle(0, 0)); // Deploy an implementation of the fault game gameImpl = new FaultDisputeGame({ _gameType: GAME_TYPE, _absolutePrestate: absolutePrestate, - _genesisBlockNumber: genesisBlockNumber, - _genesisOutputRoot: genesisOutputRoot, _maxGameDepth: 2 ** 3, _splitDepth: 2 ** 2, _gameDuration: Duration.wrap(7 days), - _vm: _vm + _vm: _vm, + _weth: delayedWeth, + _anchorStateRegistry: anchorStateRegistry, + _l2ChainId: 10 }); + // Register the game implementation with the factory. - factory.setImplementation(GAME_TYPE, gameImpl); + disputeGameFactory.setImplementation(GAME_TYPE, gameImpl); // Create a new game. - gameProxy = FaultDisputeGame(address(factory.create(GAME_TYPE, rootClaim, extraData))); + gameProxy = FaultDisputeGame(payable(address(disputeGameFactory.create(GAME_TYPE, rootClaim, extraData)))); // Check immutables assertEq(gameProxy.gameType().raw(), GAME_TYPE.raw()); assertEq(gameProxy.absolutePrestate().raw(), absolutePrestate.raw()); - assertEq(gameProxy.genesisBlockNumber(), genesisBlockNumber); - assertEq(gameProxy.genesisOutputRoot().raw(), genesisOutputRoot.raw()); assertEq(gameProxy.maxGameDepth(), 2 ** 3); assertEq(gameProxy.splitDepth(), 2 ** 2); assertEq(gameProxy.gameDuration().raw(), 7 days); @@ -95,18 +86,15 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev The absolute prestate of the trace. Claim internal absolutePrestate; + /// @dev Minimum bond value that covers all possible moves. + uint256 internal constant MIN_BOND = 50 ether; + function setUp() public override { absolutePrestateData = abi.encode(0); absolutePrestate = _changeClaimStatus(Claim.wrap(keccak256(absolutePrestateData)), VMStatuses.UNFINISHED); super.setUp(); - super.init({ - rootClaim: ROOT_CLAIM, - absolutePrestate: absolutePrestate, - l2BlockNumber: 0x10, - genesisBlockNumber: 0, - genesisOutputRoot: Hash.wrap(bytes32(0)) - }); + super.init({ rootClaim: ROOT_CLAIM, absolutePrestate: absolutePrestate, l2BlockNumber: 0x10 }); } //////////////////////////////////////////////////////////////// @@ -116,7 +104,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Tests that the constructor of the `FaultDisputeGame` reverts when the `_splitDepth` /// parameter is greater than or equal to the `MAX_GAME_DEPTH` function test_constructor_wrongArgs_reverts(uint256 _splitDepth) public { - AlphabetVM alphabetVM = new AlphabetVM(absolutePrestate); + AlphabetVM alphabetVM = new AlphabetVM(absolutePrestate, new PreimageOracle(0, 0)); // Test that the constructor reverts when the `_splitDepth` parameter is greater than or equal // to the `MAX_GAME_DEPTH` parameter. @@ -125,12 +113,13 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { new FaultDisputeGame({ _gameType: GAME_TYPE, _absolutePrestate: absolutePrestate, - _genesisBlockNumber: 0, - _genesisOutputRoot: Hash.wrap(bytes32(0)), _maxGameDepth: 2 ** 3, _splitDepth: _splitDepth, _gameDuration: Duration.wrap(7 days), - _vm: alphabetVM + _vm: alphabetVM, + _weth: DelayedWETH(payable(address(0))), + _anchorStateRegistry: IAnchorStateRegistry(address(0)), + _l2ChainId: 10 }); } @@ -167,14 +156,16 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // `IFaultDisputeGame` Implementation Tests // //////////////////////////////////////////////////////////////// - /// @dev Tests that the game cannot be initialized with an output root that commits to <= the configured genesis + /// @dev Tests that the game cannot be initialized with an output root that commits to <= the configured starting /// block number function testFuzz_initialize_cannotProposeGenesis_reverts(uint256 _blockNumber) public { - _blockNumber = bound(_blockNumber, 0, gameProxy.genesisBlockNumber()); + (, uint256 startingL2Block) = gameProxy.startingOutputRoot(); + _blockNumber = bound(_blockNumber, 0, startingL2Block); Claim claim = _dummyClaim(); vm.expectRevert(abi.encodeWithSelector(UnexpectedRootClaim.selector, claim)); - gameProxy = FaultDisputeGame(address(factory.create(GAME_TYPE, claim, abi.encode(_blockNumber)))); + gameProxy = + FaultDisputeGame(payable(address(disputeGameFactory.create(GAME_TYPE, claim, abi.encode(_blockNumber))))); } /// @dev Tests that the proxy receives ETH from the dispute game factory. @@ -183,8 +174,11 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { vm.deal(address(this), _value); assertEq(address(gameProxy).balance, 0); - gameProxy = FaultDisputeGame(address(factory.create{ value: _value }(GAME_TYPE, ROOT_CLAIM, abi.encode(1)))); - assertEq(address(gameProxy).balance, _value); + gameProxy = FaultDisputeGame( + payable(address(disputeGameFactory.create{ value: _value }(GAME_TYPE, ROOT_CLAIM, abi.encode(1)))) + ); + assertEq(address(gameProxy).balance, 0); + assertEq(delayedWeth.balanceOf(address(gameProxy)), _value); } /// @dev Tests that the game cannot be initialized with extra data > 64 bytes long (root claim + l2 block number @@ -198,15 +192,15 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { _extraDataLen = bound(_extraDataLen, 33, 23_500); bytes memory _extraData = new bytes(_extraDataLen); - // Assign the first 32 bytes in `extraData` to a valid L2 block number passed genesis. - uint256 genesisBlockNumber = gameProxy.genesisBlockNumber(); + // Assign the first 32 bytes in `extraData` to a valid L2 block number passed the starting block. + (, uint256 startingL2Block) = gameProxy.startingOutputRoot(); assembly { - mstore(add(_extraData, 0x20), add(genesisBlockNumber, 1)) + mstore(add(_extraData, 0x20), add(startingL2Block, 1)) } Claim claim = _dummyClaim(); vm.expectRevert(abi.encodeWithSelector(ExtraDataTooLong.selector)); - gameProxy = FaultDisputeGame(address(factory.create(GAME_TYPE, claim, _extraData))); + gameProxy = FaultDisputeGame(payable(address(disputeGameFactory.create(GAME_TYPE, claim, _extraData)))); } /// @dev Tests that the game is initialized with the correct data. @@ -242,6 +236,30 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { gameProxy.initialize(); } + /// @dev Tests that the bond during the bisection game depths is correct. + function test_getRequiredBond_succeeds() public { + for (uint64 i = 0; i < uint64(gameProxy.splitDepth()); i++) { + Position pos = LibPosition.wrap(i, 0); + uint256 bond = gameProxy.getRequiredBond(pos); + + // Reasonable approximation for a max depth of 8. + uint256 expected = 0.08 ether; + for (uint64 j = 0; j < i; j++) { + expected = expected * 217456; + expected = expected / 100000; + } + + assertApproxEqAbs(bond, expected, 0.01 ether); + } + } + + /// @dev Tests that the bond at a depth greater than the maximum game depth reverts. + function test_getRequiredBond_outOfBounds_reverts() public { + Position pos = LibPosition.wrap(uint64(gameProxy.maxGameDepth() + 1), 0); + vm.expectRevert(GameDepthExceeded.selector); + gameProxy.getRequiredBond(pos); + } + /// @dev Tests that a move while the game status is not `IN_PROGRESS` causes the call to revert /// with the `GameNotInProgress` error function test_move_gameNotInProgress_reverts() public { @@ -297,7 +315,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { if (i == maxDepth) { vm.expectRevert(GameDepthExceeded.selector); } - gameProxy.attack(i, claim); + gameProxy.attack{ value: MIN_BOND }(i, claim); } } @@ -307,7 +325,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Warp ahead past the clock time for the first move (3 1/2 days) vm.warp(block.timestamp + 3 days + 12 hours + 1); vm.expectRevert(ClockTimeExceeded.selector); - gameProxy.attack(0, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(0, _dummyClaim()); } /// @notice Static unit test for the correctness of the chess clock incrementation. @@ -318,12 +336,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { Claim claim = _dummyClaim(); vm.warp(block.timestamp + 15); - gameProxy.attack(0, claim); + gameProxy.attack{ value: MIN_BOND }(0, claim); (,,,,,, clock) = gameProxy.claimData(1); assertEq(clock.raw(), LibClock.wrap(Duration.wrap(15), Timestamp.wrap(uint64(block.timestamp))).raw()); vm.warp(block.timestamp + 10); - gameProxy.attack(1, claim); + gameProxy.attack{ value: MIN_BOND }(1, claim); (,,,,,, clock) = gameProxy.claimData(2); assertEq(clock.raw(), LibClock.wrap(Duration.wrap(10), Timestamp.wrap(uint64(block.timestamp))).raw()); @@ -332,12 +350,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { claim = _changeClaimStatus(claim, VMStatuses.PANIC); vm.warp(block.timestamp + 10); - gameProxy.attack(2, claim); + gameProxy.attack{ value: MIN_BOND }(2, claim); (,,,,,, clock) = gameProxy.claimData(3); assertEq(clock.raw(), LibClock.wrap(Duration.wrap(25), Timestamp.wrap(uint64(block.timestamp))).raw()); vm.warp(block.timestamp + 10); - gameProxy.attack(3, claim); + gameProxy.attack{ value: MIN_BOND }(3, claim); (,,,,,, clock) = gameProxy.claimData(4); assertEq(clock.raw(), LibClock.wrap(Duration.wrap(20), Timestamp.wrap(uint64(block.timestamp))).raw()); } @@ -348,11 +366,11 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { Claim claim = _dummyClaim(); // Make the first move. This should succeed. - gameProxy.attack(0, claim); + gameProxy.attack{ value: MIN_BOND }(0, claim); // Attempt to make the same move again. vm.expectRevert(ClaimAlreadyExists.selector); - gameProxy.attack(0, claim); + gameProxy.attack{ value: MIN_BOND }(0, claim); } /// @dev Static unit test asserting that identical claims at the same position can be made in different subgames. @@ -361,13 +379,13 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { Claim claimB = _dummyClaim(); // Make the first moves. This should succeed. - gameProxy.attack(0, claimA); - gameProxy.attack(0, claimB); + gameProxy.attack{ value: MIN_BOND }(0, claimA); + gameProxy.attack{ value: MIN_BOND }(0, claimB); // Perform an attack at the same position with the same claim value in both subgames. // These both should succeed. - gameProxy.attack(1, claimA); - gameProxy.attack(2, claimA); + gameProxy.attack{ value: MIN_BOND }(1, claimA); + gameProxy.attack{ value: MIN_BOND }(2, claimA); } /// @dev Static unit test for the correctness of an opening attack. @@ -380,7 +398,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Perform the attack. vm.expectEmit(true, true, true, false); emit Move(0, counter, address(this)); - gameProxy.attack(0, counter); + gameProxy.attack{ value: MIN_BOND }(0, counter); // Grab the claim data of the attack. ( @@ -397,7 +415,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { assertEq(parentIndex, 0); assertEq(counteredBy, address(0)); assertEq(claimant, address(this)); - assertEq(bond, 0); + assertEq(bond, MIN_BOND); assertEq(claim.raw(), counter.raw()); assertEq(position.raw(), Position.wrap(1).move(true).raw()); assertEq(clock.raw(), LibClock.wrap(Duration.wrap(5), Timestamp.wrap(uint64(block.timestamp))).raw()); @@ -407,7 +425,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Assert correctness of the parent claim's data. assertEq(parentIndex, type(uint32).max); - assertEq(counteredBy, address(this)); + assertEq(counteredBy, address(0)); assertEq(claimant, DEFAULT_SENDER); assertEq(bond, 0); assertEq(claim.raw(), ROOT_CLAIM.raw()); @@ -419,20 +437,47 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// byte reverts with the `UnexpectedRootClaim` error. function test_move_incorrectStatusExecRoot_reverts() public { for (uint256 i; i < 4; i++) { - gameProxy.attack(i, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(i, _dummyClaim()); } vm.expectRevert(abi.encodeWithSelector(UnexpectedRootClaim.selector, bytes32(0))); - gameProxy.attack(4, Claim.wrap(bytes32(0))); + gameProxy.attack{ value: MIN_BOND }(4, Claim.wrap(bytes32(0))); } /// @dev Tests that making a claim at the execution trace bisection root level with a valid status /// byte succeeds. function test_move_correctStatusExecRoot_succeeds() public { for (uint256 i; i < 4; i++) { - gameProxy.attack(i, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(i, _dummyClaim()); } - gameProxy.attack(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + gameProxy.attack{ value: MIN_BOND }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + } + + /// @dev Static unit test asserting that a move reverts when the bond is insufficient. + function test_move_insufficientBond_reverts() public { + vm.expectRevert(InsufficientBond.selector); + gameProxy.attack{ value: 0 }(0, _dummyClaim()); + } + + /// @dev Tests that a claim cannot be stepped against twice. + function test_step_duplicateStep_reverts() public { + // Give the test contract some ether + vm.deal(address(this), 1000 ether); + + // Make claims all the way down the tree. + gameProxy.attack{ value: MIN_BOND }(0, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(1, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(2, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(3, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + gameProxy.attack{ value: MIN_BOND }(5, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(6, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(7, _dummyClaim()); + gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); + gameProxy.step(8, true, absolutePrestateData, hex""); + + vm.expectRevert(DuplicateStep.selector); + gameProxy.step(8, true, absolutePrestateData, hex""); } /// @dev Static unit test for the correctness an uncontested root resolution. @@ -476,7 +521,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Static unit test for the correctness of resolving a single attack game state. function test_resolve_rootContested_succeeds() public { - gameProxy.attack(0, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(0, _dummyClaim()); vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); @@ -486,8 +531,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Static unit test for the correctness of resolving a game with a contested challenge claim. function test_resolve_challengeContested_succeeds() public { - gameProxy.attack(0, _dummyClaim()); - gameProxy.defend(1, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(0, _dummyClaim()); + gameProxy.defend{ value: MIN_BOND }(1, _dummyClaim()); vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); @@ -498,10 +543,10 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Static unit test for the correctness of resolving a game with multiplayer moves. function test_resolve_teamDeathmatch_succeeds() public { - gameProxy.attack(0, _dummyClaim()); - gameProxy.attack(0, _dummyClaim()); - gameProxy.defend(1, _dummyClaim()); - gameProxy.defend(1, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(0, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(0, _dummyClaim()); + gameProxy.defend{ value: MIN_BOND }(1, _dummyClaim()); + gameProxy.defend{ value: MIN_BOND }(1, _dummyClaim()); vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); @@ -514,12 +559,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { function test_resolve_stepReached_succeeds() public { Claim claim = _dummyClaim(); for (uint256 i; i < gameProxy.splitDepth(); i++) { - gameProxy.attack(i, claim); + gameProxy.attack{ value: MIN_BOND }(i, claim); } claim = _changeClaimStatus(claim, VMStatuses.PANIC); for (uint256 i = gameProxy.claimDataLen() - 1; i < gameProxy.maxGameDepth(); i++) { - gameProxy.attack(i, claim); + gameProxy.attack{ value: MIN_BOND }(i, claim); } vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); @@ -533,35 +578,39 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Static unit test asserting that resolve reverts when attempting to resolve a subgame multiple times function test_resolve_claimAlreadyResolved_reverts() public { - vm.deal(address(this), 1 ether); + vm.deal(address(this), 2 * MIN_BOND); Claim claim = _dummyClaim(); - gameProxy.attack{ value: 1 ether }(0, claim); - gameProxy.attack(1, claim); + gameProxy.attack{ value: MIN_BOND }(0, claim); + gameProxy.attack{ value: MIN_BOND }(1, claim); vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); assertEq(address(this).balance, 0); gameProxy.resolveClaim(1); + + // Wait for the withdrawal delay. + vm.warp(block.timestamp + delayedWeth.delay() + 1 seconds); + gameProxy.claimCredit(address(this)); - assertEq(address(this).balance, 1 ether); + assertEq(address(this).balance, MIN_BOND); vm.expectRevert(ClaimAlreadyResolved.selector); gameProxy.resolveClaim(1); - assertEq(address(this).balance, 1 ether); + assertEq(address(this).balance, MIN_BOND); } /// @dev Static unit test asserting that resolve reverts when attempting to resolve a subgame at max depth function test_resolve_claimAtMaxDepthAlreadyResolved_reverts() public { Claim claim = _dummyClaim(); for (uint256 i; i < gameProxy.splitDepth(); i++) { - gameProxy.attack(i, claim); + gameProxy.attack{ value: MIN_BOND }(i, claim); } - vm.deal(address(this), 100 ether); + vm.deal(address(this), 10000 ether); claim = _changeClaimStatus(claim, VMStatuses.PANIC); for (uint256 i = gameProxy.claimDataLen() - 1; i < gameProxy.maxGameDepth(); i++) { - gameProxy.attack{ value: 1 ether }(i, claim); + gameProxy.attack{ value: MIN_BOND }(i, claim); } vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); @@ -569,8 +618,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Resolve to claim bond uint256 balanceBefore = address(this).balance; gameProxy.resolveClaim(8); + + // Wait for the withdrawal delay. + vm.warp(block.timestamp + delayedWeth.delay() + 1 seconds); + gameProxy.claimCredit(address(this)); - assertEq(address(this).balance, balanceBefore + 1 ether); + assertEq(address(this).balance, balanceBefore + MIN_BOND); vm.expectRevert(ClaimAlreadyResolved.selector); gameProxy.resolveClaim(8); @@ -578,8 +631,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// @dev Static unit test asserting that resolve reverts when attempting to resolve subgames out of order function test_resolve_outOfOrderResolution_reverts() public { - gameProxy.attack(0, _dummyClaim()); - gameProxy.attack(1, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(0, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(1, _dummyClaim()); vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); @@ -591,18 +644,19 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { /// moves. function test_resolve_bondPayouts_succeeds() public { // Give the test contract some ether - vm.deal(address(this), 100 ether); + uint256 bal = 1000 ether; + vm.deal(address(this), bal); // Make claims all the way down the tree. - gameProxy.attack{ value: 1 ether }(0, _dummyClaim()); - gameProxy.attack{ value: 1 ether }(1, _dummyClaim()); - gameProxy.attack{ value: 1 ether }(2, _dummyClaim()); - gameProxy.attack{ value: 1 ether }(3, _dummyClaim()); - gameProxy.attack{ value: 1 ether }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); - gameProxy.attack{ value: 1 ether }(5, _dummyClaim()); - gameProxy.attack{ value: 1 ether }(6, _dummyClaim()); - gameProxy.attack{ value: 1 ether }(7, _dummyClaim()); - gameProxy.addLocalData(LocalPreimageKey.STARTING_L2_BLOCK_NUMBER, 8, 0); + gameProxy.attack{ value: MIN_BOND }(0, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(1, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(2, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(3, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + gameProxy.attack{ value: MIN_BOND }(5, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(6, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(7, _dummyClaim()); + gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); gameProxy.step(8, true, absolutePrestateData, hex""); // Ensure that the step successfully countered the leaf claim. @@ -610,62 +664,267 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { assertEq(counteredBy, address(this)); // Ensure we bonded the correct amounts - uint256 bonded = (gameProxy.claimDataLen() - 1) * 1 ether; - assertEq(address(this).balance, 100 ether - bonded); - assertEq(address(gameProxy).balance, bonded); + uint256 bonded = (gameProxy.claimDataLen() - 1) * MIN_BOND; + assertEq(address(this).balance, bal - bonded); + assertEq(address(gameProxy).balance, 0); + assertEq(delayedWeth.balanceOf(address(gameProxy)), bonded); // Resolve all claims vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); for (uint256 i = gameProxy.claimDataLen(); i > 0; i--) { (bool success,) = address(gameProxy).call(abi.encodeCall(gameProxy.resolveClaim, (i - 1))); - success; + assertTrue(success); } gameProxy.resolve(); + // Wait for the withdrawal delay. + vm.warp(block.timestamp + delayedWeth.delay() + 1 seconds); + gameProxy.claimCredit(address(this)); // Ensure that bonds were paid out correctly. - assertEq(address(this).balance, 100 ether); + assertEq(address(this).balance, bal); assertEq(address(gameProxy).balance, 0); + assertEq(delayedWeth.balanceOf(address(gameProxy)), 0); + + // Ensure that the init bond for the game is 0, in case we change it in the test suite in the future. + assertEq(disputeGameFactory.initBonds(GAME_TYPE), 0); + } + + /// @dev Static unit test asserting that resolve pays out bonds on step, output bisection, and execution trace + /// moves with 2 actors and a dishonest root claim. + function test_resolve_bondPayoutsSeveralActors_succeeds() public { + // Give the test contract and bob some ether + uint256 bal = 1000 ether; + address bob = address(0xb0b); + vm.deal(address(this), bal); + vm.deal(bob, bal); + + // Make claims all the way down the tree, trading off between bob and the test contract. + gameProxy.attack{ value: MIN_BOND }(0, _dummyClaim()); + + vm.prank(bob); + gameProxy.attack{ value: MIN_BOND }(1, _dummyClaim()); + + gameProxy.attack{ value: MIN_BOND }(2, _dummyClaim()); + + vm.prank(bob); + gameProxy.attack{ value: MIN_BOND }(3, _dummyClaim()); + + gameProxy.attack{ value: MIN_BOND }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + + vm.prank(bob); + gameProxy.attack{ value: MIN_BOND }(5, _dummyClaim()); + + gameProxy.attack{ value: MIN_BOND }(6, _dummyClaim()); + + vm.prank(bob); + gameProxy.attack{ value: MIN_BOND }(7, _dummyClaim()); + + gameProxy.addLocalData(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, 8, 0); + gameProxy.step(8, true, absolutePrestateData, hex""); + + // Ensure that the step successfully countered the leaf claim. + (, address counteredBy,,,,,) = gameProxy.claimData(8); + assertEq(counteredBy, address(this)); + + // Ensure we bonded the correct amounts + uint256 bonded = ((gameProxy.claimDataLen() - 1) / 2) * MIN_BOND; + assertEq(address(this).balance, bal - bonded); + assertEq(bob.balance, bal - bonded); + assertEq(address(gameProxy).balance, 0); + assertEq(delayedWeth.balanceOf(address(gameProxy)), bonded * 2); + + // Resolve all claims + vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); + for (uint256 i = gameProxy.claimDataLen(); i > 0; i--) { + (bool success,) = address(gameProxy).call(abi.encodeCall(gameProxy.resolveClaim, (i - 1))); + assertTrue(success); + } + gameProxy.resolve(); + + // Wait for the withdrawal delay. + vm.warp(block.timestamp + delayedWeth.delay() + 1 seconds); + + gameProxy.claimCredit(address(this)); + + // Bob's claim should revert since it's value is 0 + vm.expectRevert(NoCreditToClaim.selector); + gameProxy.claimCredit(bob); + + // Ensure that bonds were paid out correctly. + assertEq(address(this).balance, bal + bonded); + assertEq(bob.balance, bal - bonded); + assertEq(address(gameProxy).balance, 0); + assertEq(delayedWeth.balanceOf(address(gameProxy)), 0); + + // Ensure that the init bond for the game is 0, in case we change it in the test suite in the future. + assertEq(disputeGameFactory.initBonds(GAME_TYPE), 0); + } + + /// @dev Static unit test asserting that resolve pays out bonds on moves to the leftmost actor + /// in subgames containing successful counters. + function test_resolve_leftmostBondPayout_succeeds() public { + uint256 bal = 1000 ether; + address alice = address(0xa11ce); + address bob = address(0xb0b); + address charlie = address(0xc0c); + vm.deal(address(this), bal); + vm.deal(alice, bal); + vm.deal(bob, bal); + vm.deal(charlie, bal); + + // Make claims with bob, charlie and the test contract on defense, and alice as the challenger + // charlie is successfully countered by alice + // alice is successfully countered by both bob and the test contract + vm.prank(alice); + gameProxy.attack{ value: MIN_BOND }(0, _dummyClaim()); + + vm.prank(bob); + gameProxy.defend{ value: MIN_BOND }(1, _dummyClaim()); + vm.prank(charlie); + gameProxy.attack{ value: MIN_BOND }(1, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(1, _dummyClaim()); + + vm.prank(alice); + gameProxy.attack{ value: MIN_BOND }(3, _dummyClaim()); + + // Resolve all claims + vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); + for (uint256 i = gameProxy.claimDataLen(); i > 0; i--) { + (bool success,) = address(gameProxy).call(abi.encodeCall(gameProxy.resolveClaim, (i - 1))); + assertTrue(success); + } + gameProxy.resolve(); + + // Wait for the withdrawal delay. + vm.warp(block.timestamp + delayedWeth.delay() + 1 seconds); + + gameProxy.claimCredit(address(this)); + gameProxy.claimCredit(alice); + gameProxy.claimCredit(bob); + + // Charlie's claim should revert since it's value is 0 + vm.expectRevert(NoCreditToClaim.selector); + gameProxy.claimCredit(charlie); + + // Ensure that bonds were paid out correctly. + uint256 aliceLosses = MIN_BOND; + uint256 charlieLosses = MIN_BOND; + assertEq(address(this).balance, bal + aliceLosses, "incorrect this balance"); + assertEq(alice.balance, bal - aliceLosses + charlieLosses, "incorrect alice balance"); + assertEq(bob.balance, bal, "incorrect bob balance"); + assertEq(charlie.balance, bal - charlieLosses, "incorrect charlie balance"); + assertEq(address(gameProxy).balance, 0); + + // Ensure that the init bond for the game is 0, in case we change it in the test suite in the future. + assertEq(disputeGameFactory.initBonds(GAME_TYPE), 0); + } + + /// @dev Static unit test asserting that the anchor state updates when the game resolves in + /// favor of the defender and the anchor state is older than the game state. + function test_resolve_validNewerStateUpdatesAnchor_succeeds() public { + // Confirm that the anchor state is older than the game state. + (Hash root, uint256 l2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assert(l2BlockNumber < gameProxy.l2BlockNumber()); + + // Resolve the game. + vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); + gameProxy.resolveClaim(0); + assertEq(uint8(gameProxy.resolve()), uint8(GameStatus.DEFENDER_WINS)); + + // Confirm that the anchor state is now the same as the game state. + (root, l2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assertEq(l2BlockNumber, gameProxy.l2BlockNumber()); + assertEq(root.raw(), gameProxy.rootClaim().raw()); + } + + /// @dev Static unit test asserting that the anchor state does not change when the game + /// resolves in favor of the defender but the game state is not newer than the anchor state. + function test_resolve_validOlderStateSameAnchor_succeeds() public { + // Mock the game block to be older than the game state. + vm.mockCall(address(gameProxy), abi.encodeWithSelector(gameProxy.l2BlockNumber.selector), abi.encode(0)); + + // Confirm that the anchor state is newer than the game state. + (Hash root, uint256 l2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assert(l2BlockNumber >= gameProxy.l2BlockNumber()); + + // Resolve the game. + vm.mockCall(address(gameProxy), abi.encodeWithSelector(gameProxy.l2BlockNumber.selector), abi.encode(0)); + vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); + gameProxy.resolveClaim(0); + assertEq(uint8(gameProxy.resolve()), uint8(GameStatus.DEFENDER_WINS)); + + // Confirm that the anchor state is the same as the initial anchor state. + (Hash updatedRoot, uint256 updatedL2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assertEq(updatedL2BlockNumber, l2BlockNumber); + assertEq(updatedRoot.raw(), root.raw()); + } + + /// @dev Static unit test asserting that the anchor state does not change when the game + /// resolves in favor of the challenger, even if the game state is newer than the anchor. + function test_resolve_invalidStateSameAnchor_succeeds() public { + // Confirm that the anchor state is older than the game state. + (Hash root, uint256 l2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assert(l2BlockNumber < gameProxy.l2BlockNumber()); + + // Challenge the claim and resolve it. + gameProxy.attack{ value: MIN_BOND }(0, _dummyClaim()); + vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); + gameProxy.resolveClaim(0); + assertEq(uint8(gameProxy.resolve()), uint8(GameStatus.CHALLENGER_WINS)); + + // Confirm that the anchor state is the same as the initial anchor state. + (Hash updatedRoot, uint256 updatedL2BlockNumber) = anchorStateRegistry.anchors(gameProxy.gameType()); + assertEq(updatedL2BlockNumber, l2BlockNumber); + assertEq(updatedRoot.raw(), root.raw()); } /// @dev Static unit test asserting that credit may not be drained past allowance through reentrancy. function test_claimCredit_claimAlreadyResolved_reverts() public { - ClaimCreditReenter reenter = new ClaimCreditReenter(gameProxy); + ClaimCreditReenter reenter = new ClaimCreditReenter(gameProxy, vm); vm.startPrank(address(reenter)); // Give the test contract some ether to bond. - vm.deal(address(reenter), 1 ether); + vm.deal(address(reenter), MIN_BOND * 2); // Give the game proxy 1 extra ether, unregistered. vm.deal(address(gameProxy), 1 ether); // Perform a bonded move. Claim claim = _dummyClaim(); - gameProxy.attack{ value: 1 ether }(0, claim); - gameProxy.attack(1, claim); + gameProxy.attack{ value: MIN_BOND }(0, claim); + gameProxy.attack{ value: MIN_BOND }(1, claim); // Warp past the finalization period vm.warp(block.timestamp + 3 days + 12 hours + 1 seconds); // Ensure that we bonded all the test contract's ETH assertEq(address(reenter).balance, 0); - // Ensure the game proxy has 2 ETH, 1 from bonding and 1 unregistered. - assertEq(address(gameProxy).balance, 2 ether); + // Ensure the game proxy has 1 ether in it. + assertEq(address(gameProxy).balance, 1 ether); + // Ensure the game has a balance of 2 * MIN_BOND in the delayedWeth contract. + assertEq(delayedWeth.balanceOf(address(gameProxy)), MIN_BOND * 2); // Resolve the claim at gindex 1 and claim the reenter contract's credit. gameProxy.resolveClaim(1); // Ensure that the game registered the `reenter` contract's credit. - assertEq(gameProxy.credit(address(reenter)), 1 ether); + assertEq(gameProxy.credit(address(reenter)), MIN_BOND); + + // Wait for the withdrawal delay. + vm.warp(block.timestamp + delayedWeth.delay() + 1 seconds); // Initiate the reentrant credit claim. reenter.claimCredit(address(reenter)); - // The reenter contract should have performed 5 calls to `claimCredit`, but only received the 1 ETH bonded. The - // unregistered ETH should still exist in the game proxy. - assertEq(reenter.numCalls(), 5); - assertEq(address(reenter).balance, 1 ether); + // The reenter contract should have performed 2 calls to `claimCredit`. + // Once all the credit is claimed, all subsequent calls will revert since there is 0 credit left to claim. + // The claimant must only have received the amount bonded for the gindex 1 subgame. + // The root claim bond and the unregistered ETH should still exist in the game proxy. + assertEq(reenter.numCalls(), 2); + assertEq(address(reenter).balance, MIN_BOND); assertEq(address(gameProxy).balance, 1 ether); + assertEq(delayedWeth.balanceOf(address(gameProxy)), MIN_BOND); vm.stopPrank(); } @@ -674,9 +933,9 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { function testFuzz_addLocalData_oob_reverts(uint256 _ident) public { // Get a claim below the split depth so that we can add local data for an execution trace subgame. for (uint256 i; i < 4; i++) { - gameProxy.attack(i, _dummyClaim()); + gameProxy.attack{ value: MIN_BOND }(i, _dummyClaim()); } - gameProxy.attack(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + gameProxy.attack{ value: MIN_BOND }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); // [1, 5] are valid local data identifiers. if (_ident <= 5) _ident = 0; @@ -692,18 +951,24 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Get a claim below the split depth so that we can add local data for an execution trace subgame. for (uint256 i; i < 4; i++) { - gameProxy.attack(i, Claim.wrap(bytes32(i))); + gameProxy.attack{ value: MIN_BOND }(i, Claim.wrap(bytes32(i))); } - gameProxy.attack(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); + gameProxy.attack{ value: MIN_BOND }(4, _changeClaimStatus(_dummyClaim(), VMStatuses.PANIC)); // Expected start/disputed claims - bytes32 startingClaim = gameProxy.genesisOutputRoot().raw(); + (Hash root,) = gameProxy.startingOutputRoot(); + bytes32 startingClaim = root.raw(); bytes32 disputedClaim = bytes32(uint256(3)); Position disputedPos = LibPosition.wrap(4, 0); // Expected local data - bytes32[5] memory data = - [gameProxy.l1Head().raw(), startingClaim, disputedClaim, bytes32(0), bytes32(block.chainid << 0xC0)]; + bytes32[5] memory data = [ + gameProxy.l1Head().raw(), + startingClaim, + disputedClaim, + bytes32(uint256(1) << 0xC0), + bytes32(gameProxy.l2ChainId() << 0xC0) + ]; for (uint256 i = 1; i <= 5; i++) { uint256 expectedLen = i > 3 ? 8 : 32; @@ -732,9 +997,9 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { // Get a claim below the split depth so that we can add local data for an execution trace subgame. for (uint256 i; i < 4; i++) { - gameProxy.attack(i, Claim.wrap(bytes32(i))); + gameProxy.attack{ value: MIN_BOND }(i, Claim.wrap(bytes32(i))); } - gameProxy.defend(4, _changeClaimStatus(ROOT_CLAIM, VMStatuses.VALID)); + gameProxy.defend{ value: MIN_BOND }(4, _changeClaimStatus(ROOT_CLAIM, VMStatuses.VALID)); // Expected start/disputed claims bytes32 startingClaim = bytes32(uint256(3)); @@ -747,8 +1012,8 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { gameProxy.l1Head().raw(), startingClaim, disputedClaim, - bytes32(uint256(1) << 0xC0), - bytes32(block.chainid << 0xC0) + bytes32(uint256(2) << 0xC0), + bytes32(gameProxy.l2ChainId() << 0xC0) ]; for (uint256 i = 1; i <= 5; i++) { @@ -1256,13 +1521,7 @@ contract FaultDispute_1v1_Actors_Test is FaultDisputeGame_Init { Claim absolutePrestateExec = _changeClaimStatus(Claim.wrap(keccak256(absolutePrestateData_)), VMStatuses.UNFINISHED); Claim rootClaim = Claim.wrap(bytes32(uint256(_rootClaim))); - super.init({ - rootClaim: rootClaim, - absolutePrestate: absolutePrestateExec, - l2BlockNumber: _rootClaim, - genesisBlockNumber: 0, - genesisOutputRoot: Hash.wrap(bytes32(0)) - }); + super.init({ rootClaim: rootClaim, absolutePrestate: absolutePrestateExec, l2BlockNumber: _rootClaim }); } /// @dev Helper to create actors for the 1v1 dispute. @@ -1289,6 +1548,8 @@ contract FaultDispute_1v1_Actors_Test is FaultDisputeGame_Init { _preStateData: _dishonestPreStateData }); + vm.deal(address(honest), 100 ether); + vm.deal(address(dishonest), 100 ether); vm.label(address(honest), "HonestActor"); vm.label(address(dishonest), "DishonestActor"); } @@ -1318,22 +1579,27 @@ contract FaultDispute_1v1_Actors_Test is FaultDisputeGame_Init { // resolved before global resolution, which catches any unresolved subgames here. for (uint256 i = gameProxy.claimDataLen(); i > 0; i--) { (bool success,) = address(gameProxy).call(abi.encodeCall(gameProxy.resolveClaim, (i - 1))); - success; + assertTrue(success); } gameProxy.resolve(); } } contract ClaimCreditReenter { + Vm internal immutable vm; FaultDisputeGame internal immutable GAME; uint256 public numCalls; - constructor(FaultDisputeGame _gameProxy) { + constructor(FaultDisputeGame _gameProxy, Vm _vm) { GAME = _gameProxy; + vm = _vm; } function claimCredit(address _recipient) public { numCalls += 1; + if (numCalls > 1) { + vm.expectRevert(NoCreditToClaim.selector); + } GAME.claimCredit(_recipient); } diff --git a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol new file mode 100644 index 000000000000..02191968f69c --- /dev/null +++ b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import { Test } from "forge-std/Test.sol"; +import { Vm } from "forge-std/Vm.sol"; +import { DisputeGameFactory_Init } from "test/dispute/DisputeGameFactory.t.sol"; +import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; +import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol"; +import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol"; +import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; +import { PreimageOracle } from "src/cannon/PreimageOracle.sol"; +import { PreimageKeyLib } from "src/cannon/PreimageKeyLib.sol"; + +import "src/libraries/DisputeTypes.sol"; +import "src/libraries/DisputeErrors.sol"; +import { Types } from "src/libraries/Types.sol"; +import { LibClock } from "src/dispute/lib/LibUDT.sol"; +import { LibPosition } from "src/dispute/lib/LibPosition.sol"; +import { IBigStepper, IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol"; +import { AlphabetVM } from "test/mocks/AlphabetVM.sol"; + +import { DisputeActor, HonestDisputeActor } from "test/actors/FaultDisputeActors.sol"; + +contract PermissionedDisputeGame_Init is DisputeGameFactory_Init { + /// @dev The type of the game being tested. + GameType internal constant GAME_TYPE = GameType.wrap(1); + /// @dev Mock proposer key + address internal constant PROPOSER = address(0xfacade9); + /// @dev Mock challenger key + address internal constant CHALLENGER = address(0xfacadec); + + /// @dev The implementation of the game. + PermissionedDisputeGame internal gameImpl; + /// @dev The `Clone` proxy of the game. + PermissionedDisputeGame internal gameProxy; + + /// @dev The extra data passed to the game for initialization. + bytes internal extraData; + + event Move(uint256 indexed parentIndex, Claim indexed pivot, address indexed claimant); + + function init(Claim rootClaim, Claim absolutePrestate, uint256 l2BlockNumber) public { + // Set the time to a realistic date. + vm.warp(1690906994); + + // Set the extra data for the game creation + extraData = abi.encode(l2BlockNumber); + + AlphabetVM _vm = new AlphabetVM(absolutePrestate, new PreimageOracle(0, 0)); + + // Use a 7 day delayed WETH to simulate withdrawals. + DelayedWETH _weth = new DelayedWETH(7 days); + + // Deploy an implementation of the fault game + gameImpl = new PermissionedDisputeGame({ + _gameType: GAME_TYPE, + _absolutePrestate: absolutePrestate, + _maxGameDepth: 2 ** 3, + _splitDepth: 2 ** 2, + _gameDuration: Duration.wrap(7 days), + _vm: _vm, + _weth: _weth, + _anchorStateRegistry: anchorStateRegistry, + _l2ChainId: 10, + _proposer: PROPOSER, + _challenger: CHALLENGER + }); + // Register the game implementation with the factory. + disputeGameFactory.setImplementation(GAME_TYPE, gameImpl); + // Create a new game. + vm.prank(PROPOSER, PROPOSER); + gameProxy = + PermissionedDisputeGame(payable(address(disputeGameFactory.create(GAME_TYPE, rootClaim, extraData)))); + + // Check immutables + assertEq(gameProxy.gameType().raw(), GAME_TYPE.raw()); + assertEq(gameProxy.absolutePrestate().raw(), absolutePrestate.raw()); + assertEq(gameProxy.maxGameDepth(), 2 ** 3); + assertEq(gameProxy.splitDepth(), 2 ** 2); + assertEq(gameProxy.gameDuration().raw(), 7 days); + assertEq(address(gameProxy.vm()), address(_vm)); + + // Label the proxy + vm.label(address(gameProxy), "FaultDisputeGame_Clone"); + } + + fallback() external payable { } + + receive() external payable { } +} + +contract PermissionedDisputeGame_Test is PermissionedDisputeGame_Init { + /// @dev The root claim of the game. + Claim internal constant ROOT_CLAIM = Claim.wrap(bytes32((uint256(1) << 248) | uint256(10))); + /// @dev Minimum bond value that covers all possible moves. + uint256 internal constant MIN_BOND = 50 ether; + + /// @dev The preimage of the absolute prestate claim + bytes internal absolutePrestateData; + /// @dev The absolute prestate of the trace. + Claim internal absolutePrestate; + + function setUp() public override { + absolutePrestateData = abi.encode(0); + absolutePrestate = _changeClaimStatus(Claim.wrap(keccak256(absolutePrestateData)), VMStatuses.UNFINISHED); + + super.setUp(); + super.init({ rootClaim: ROOT_CLAIM, absolutePrestate: absolutePrestate, l2BlockNumber: 0x10 }); + } + + /// @dev Tests that the proposer can create a permissioned dispute game. + function test_createGame_proposer_succeeds() public { + vm.prank(PROPOSER, PROPOSER); + disputeGameFactory.create(GAME_TYPE, ROOT_CLAIM, abi.encode(0x420)); + } + + /// @dev Tests that the permissioned game cannot be created by any address other than the proposer. + function testFuzz_createGame_notProposer_reverts(address _p) public { + vm.assume(_p != PROPOSER); + + vm.prank(_p, _p); + vm.expectRevert(BadAuth.selector); + disputeGameFactory.create(GAME_TYPE, ROOT_CLAIM, abi.encode(0x420)); + } + + /// @dev Tests that the challenger can participate in a permissioned dispute game. + function test_participateInGame_challenger_succeeds() public { + vm.startPrank(CHALLENGER, CHALLENGER); + vm.deal(CHALLENGER, MIN_BOND * 3); + gameProxy.attack{ value: MIN_BOND }(0, Claim.wrap(0)); + gameProxy.defend{ value: MIN_BOND }(1, Claim.wrap(0)); + gameProxy.move{ value: MIN_BOND }(2, Claim.wrap(0), true); + vm.stopPrank(); + } + + /// @dev Tests that the proposer can participate in a permissioned dispute game. + function test_participateInGame_proposer_succeeds() public { + vm.startPrank(PROPOSER, PROPOSER); + vm.deal(PROPOSER, MIN_BOND * 3); + gameProxy.attack{ value: MIN_BOND }(0, Claim.wrap(0)); + gameProxy.defend{ value: MIN_BOND }(1, Claim.wrap(0)); + gameProxy.move{ value: MIN_BOND }(2, Claim.wrap(0), true); + vm.stopPrank(); + } + + /// @dev Tests that addresses that are not the proposer or challenger cannot participate in a permissioned dispute + /// game. + function test_participateInGame_notAuthorized_reverts(address _p) public { + vm.assume(_p != PROPOSER && _p != CHALLENGER); + + vm.startPrank(_p, _p); + vm.expectRevert(BadAuth.selector); + gameProxy.attack(0, Claim.wrap(0)); + vm.expectRevert(BadAuth.selector); + gameProxy.defend(1, Claim.wrap(0)); + vm.expectRevert(BadAuth.selector); + gameProxy.move(2, Claim.wrap(0), true); + vm.stopPrank(); + } +} + +/// @dev Helper to change the VM status byte of a claim. +function _changeClaimStatus(Claim _claim, VMStatus _status) pure returns (Claim out_) { + assembly { + out_ := or(and(not(shl(248, 0xFF)), _claim), shl(248, _status)) + } +} diff --git a/packages/contracts-bedrock/test/invariants/AddressAliasHelper.t.sol b/packages/contracts-bedrock/test/invariants/AddressAliasHelper.t.sol index fd5bcc8c7cad..d61be07f7c32 100644 --- a/packages/contracts-bedrock/test/invariants/AddressAliasHelper.t.sol +++ b/packages/contracts-bedrock/test/invariants/AddressAliasHelper.t.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.15; import { Test } from "forge-std/Test.sol"; import { StdInvariant } from "forge-std/StdInvariant.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; +import { InvariantTest } from "test/invariants/InvariantTest.sol"; contract AddressAliasHelper_Converter { bool public failedRoundtrip; @@ -23,10 +24,11 @@ contract AddressAliasHelper_Converter { } } -contract AddressAliasHelper_AddressAliasing_Invariant is StdInvariant, Test { +contract AddressAliasHelper_AddressAliasing_Invariant is StdInvariant, InvariantTest { AddressAliasHelper_Converter internal actor; - function setUp() public { + function setUp() public override { + super.setUp(); // Create a converter actor. actor = new AddressAliasHelper_Converter(); diff --git a/packages/contracts-bedrock/test/invariants/Burn.Eth.t.sol b/packages/contracts-bedrock/test/invariants/Burn.Eth.t.sol index 0fdfcdbbb194..2948cf8dcfc5 100644 --- a/packages/contracts-bedrock/test/invariants/Burn.Eth.t.sol +++ b/packages/contracts-bedrock/test/invariants/Burn.Eth.t.sol @@ -7,6 +7,7 @@ import { Vm } from "forge-std/Vm.sol"; import { StdInvariant } from "forge-std/StdInvariant.sol"; import { Burn } from "src/libraries/Burn.sol"; +import { InvariantTest } from "test/invariants/InvariantTest.sol"; contract Burn_EthBurner is StdUtils { Vm internal vm; @@ -41,10 +42,11 @@ contract Burn_EthBurner is StdUtils { } } -contract Burn_BurnEth_Invariant is StdInvariant, Test { +contract Burn_BurnEth_Invariant is StdInvariant, InvariantTest { Burn_EthBurner internal actor; - function setUp() public { + function setUp() public override { + super.setUp(); // Create a Eth burner actor. actor = new Burn_EthBurner(vm); diff --git a/packages/contracts-bedrock/test/invariants/Burn.Gas.t.sol b/packages/contracts-bedrock/test/invariants/Burn.Gas.t.sol index 4e9145a08d77..6ba4fa6fe345 100644 --- a/packages/contracts-bedrock/test/invariants/Burn.Gas.t.sol +++ b/packages/contracts-bedrock/test/invariants/Burn.Gas.t.sol @@ -7,6 +7,7 @@ import { Vm } from "forge-std/Vm.sol"; import { StdInvariant } from "forge-std/StdInvariant.sol"; import { Burn } from "src/libraries/Burn.sol"; +import { InvariantTest } from "test/invariants/InvariantTest.sol"; contract Burn_GasBurner is StdUtils { Vm internal vm; @@ -42,10 +43,11 @@ contract Burn_GasBurner is StdUtils { } } -contract Burn_BurnGas_Invariant is StdInvariant, Test { +contract Burn_BurnGas_Invariant is StdInvariant, InvariantTest { Burn_GasBurner internal actor; - function setUp() public { + function setUp() public override { + super.setUp(); // Create a gas burner actor. actor = new Burn_GasBurner(vm); diff --git a/packages/contracts-bedrock/test/invariants/CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/invariants/CrossDomainMessenger.t.sol index 928468dbb649..5d5c19cea756 100644 --- a/packages/contracts-bedrock/test/invariants/CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/invariants/CrossDomainMessenger.t.sol @@ -6,7 +6,6 @@ import { Vm } from "forge-std/Vm.sol"; import { OptimismPortal } from "src/L1/OptimismPortal.sol"; import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; -import { Types } from "src/libraries/Types.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { Constants } from "src/libraries/Constants.sol"; import { Encoding } from "src/libraries/Encoding.sol"; diff --git a/packages/contracts-bedrock/test/invariants/Encoding.t.sol b/packages/contracts-bedrock/test/invariants/Encoding.t.sol index 566c82903e01..94289876975f 100644 --- a/packages/contracts-bedrock/test/invariants/Encoding.t.sol +++ b/packages/contracts-bedrock/test/invariants/Encoding.t.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.15; import { Test } from "forge-std/Test.sol"; import { StdInvariant } from "forge-std/StdInvariant.sol"; import { Encoding } from "src/libraries/Encoding.sol"; +import { InvariantTest } from "test/invariants/InvariantTest.sol"; contract Encoding_Converter { bool public failedRoundtripAToB; @@ -48,10 +49,11 @@ contract Encoding_Converter { } } -contract Encoding_Invariant is StdInvariant, Test { +contract Encoding_Invariant is StdInvariant, InvariantTest { Encoding_Converter internal actor; - function setUp() public { + function setUp() public override { + super.setUp(); // Create a converter actor. actor = new Encoding_Converter(); diff --git a/packages/contracts-bedrock/test/invariants/FaultDisputeGame.t.sol b/packages/contracts-bedrock/test/invariants/FaultDisputeGame.t.sol index 51207d82c1b5..88f550e08a26 100644 --- a/packages/contracts-bedrock/test/invariants/FaultDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/invariants/FaultDisputeGame.t.sol @@ -7,6 +7,7 @@ import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; import { FaultDisputeGame_Init } from "test/dispute/FaultDisputeGame.t.sol"; import "src/libraries/DisputeTypes.sol"; +import "src/libraries/DisputeErrors.sol"; contract FaultDisputeGame_Solvency_Invariant is FaultDisputeGame_Init { Claim internal constant ROOT_CLAIM = Claim.wrap(bytes32(uint256(10))); @@ -17,13 +18,7 @@ contract FaultDisputeGame_Solvency_Invariant is FaultDisputeGame_Init { function setUp() public override { super.setUp(); - super.init({ - rootClaim: ROOT_CLAIM, - absolutePrestate: ABSOLUTE_PRESTATE, - l2BlockNumber: 0x10, - genesisBlockNumber: 0, - genesisOutputRoot: Hash.wrap(bytes32(0)) - }); + super.init({ rootClaim: ROOT_CLAIM, absolutePrestate: ABSOLUTE_PRESTATE, l2BlockNumber: 0x10 }); actor = new RandomClaimActor(gameProxy, vm); @@ -42,12 +37,26 @@ contract FaultDisputeGame_Solvency_Invariant is FaultDisputeGame_Init { for (uint256 i = gameProxy.claimDataLen(); i > 0; i--) { (bool success,) = address(gameProxy).call(abi.encodeCall(gameProxy.resolveClaim, (i - 1))); - success; + assertTrue(success); } gameProxy.resolve(); - gameProxy.claimCredit(address(this)); - gameProxy.claimCredit(address(actor)); + // Wait for the withdrawal delay. + vm.warp(block.timestamp + 7 days + 1 seconds); + + if (gameProxy.credit(address(this)) == 0) { + vm.expectRevert(NoCreditToClaim.selector); + gameProxy.claimCredit(address(this)); + } else { + gameProxy.claimCredit(address(this)); + } + + if (gameProxy.credit(address(actor)) == 0) { + vm.expectRevert(NoCreditToClaim.selector); + gameProxy.claimCredit(address(actor)); + } else { + gameProxy.claimCredit(address(actor)); + } if (gameProxy.status() == GameStatus.DEFENDER_WINS) { assertEq(address(this).balance, type(uint96).max); diff --git a/packages/contracts-bedrock/test/invariants/Hashing.t.sol b/packages/contracts-bedrock/test/invariants/Hashing.t.sol index c972148f12b0..f60013b1cfab 100644 --- a/packages/contracts-bedrock/test/invariants/Hashing.t.sol +++ b/packages/contracts-bedrock/test/invariants/Hashing.t.sol @@ -5,6 +5,7 @@ import { Test } from "forge-std/Test.sol"; import { StdInvariant } from "forge-std/StdInvariant.sol"; import { Encoding } from "src/libraries/Encoding.sol"; import { Hashing } from "src/libraries/Hashing.sol"; +import { InvariantTest } from "test/invariants/InvariantTest.sol"; contract Hash_CrossDomainHasher { bool public failedCrossDomainHashHighVersion; @@ -93,10 +94,11 @@ contract Hash_CrossDomainHasher { } } -contract Hashing_Invariant is StdInvariant, Test { +contract Hashing_Invariant is StdInvariant, InvariantTest { Hash_CrossDomainHasher internal actor; - function setUp() public { + function setUp() public override { + super.setUp(); // Create a hasher actor. actor = new Hash_CrossDomainHasher(); diff --git a/packages/contracts-bedrock/test/invariants/InvariantTest.sol b/packages/contracts-bedrock/test/invariants/InvariantTest.sol new file mode 100644 index 000000000000..a188bcdf27a0 --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/InvariantTest.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { FFIInterface } from "test/setup/FFIInterface.sol"; +import { Deploy } from "scripts/Deploy.s.sol"; +import { Test } from "forge-std/Test.sol"; + +/// @title InvariantTest +/// @dev An extension to `Test` that sets up excluded contracts for invariant testing. +contract InvariantTest is Test { + FFIInterface constant ffi = FFIInterface(address(uint160(uint256(keccak256(abi.encode("optimism.ffi")))))); + Deploy internal constant deploy = Deploy(address(uint160(uint256(keccak256(abi.encode("optimism.deploy")))))); + + function setUp() public virtual { + excludeContract(address(ffi)); + excludeContract(address(deploy)); + } +} diff --git a/packages/contracts-bedrock/test/invariants/OptimismPortal.t.sol b/packages/contracts-bedrock/test/invariants/OptimismPortal.t.sol index 009a6a9daca1..81df17cc8a63 100644 --- a/packages/contracts-bedrock/test/invariants/OptimismPortal.t.sol +++ b/packages/contracts-bedrock/test/invariants/OptimismPortal.t.sol @@ -6,8 +6,6 @@ import { Vm } from "forge-std/Vm.sol"; import { OptimismPortal } from "src/L1/OptimismPortal.sol"; import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; -import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; -import { SystemConfig } from "src/L1/SystemConfig.sol"; import { ResourceMetering } from "src/L1/ResourceMetering.sol"; import { Constants } from "src/libraries/Constants.sol"; diff --git a/packages/contracts-bedrock/test/invariants/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/invariants/OptimismPortal2.t.sol new file mode 100644 index 000000000000..5d32ba3a5826 --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/OptimismPortal2.t.sol @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { StdUtils } from "forge-std/Test.sol"; +import { Vm } from "forge-std/Vm.sol"; + +import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; +import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; +import { SystemConfig } from "src/L1/SystemConfig.sol"; +import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +import { Constants } from "src/libraries/Constants.sol"; + +import { CommonTest } from "test/setup/CommonTest.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; +import { Types } from "src/libraries/Types.sol"; + +import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; +import "src/libraries/DisputeTypes.sol"; + +contract OptimismPortal2_Depositor is StdUtils, ResourceMetering { + Vm internal vm; + OptimismPortal2 internal portal; + bool public failedToComplete; + + constructor(Vm _vm, OptimismPortal2 _portal) { + vm = _vm; + portal = _portal; + initialize(); + } + + function initialize() internal initializer { + __ResourceMetering_init(); + } + + function resourceConfig() public pure returns (ResourceMetering.ResourceConfig memory) { + return _resourceConfig(); + } + + function _resourceConfig() internal pure override returns (ResourceMetering.ResourceConfig memory) { + ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); + return rcfg; + } + + // A test intended to identify any unexpected halting conditions + function depositTransactionCompletes( + address _to, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) + public + payable + { + vm.assume((!_isCreation || _to == address(0)) && _data.length <= 120_000); + + uint256 preDepositvalue = bound(_value, 0, type(uint128).max); + // Give the depositor some ether + vm.deal(address(this), preDepositvalue); + // cache the contract's eth balance + uint256 preDepositBalance = address(this).balance; + uint256 value = bound(preDepositvalue, 0, preDepositBalance); + + (, uint64 cachedPrevBoughtGas,) = ResourceMetering(address(portal)).params(); + ResourceMetering.ResourceConfig memory rcfg = resourceConfig(); + uint256 maxResourceLimit = uint64(rcfg.maxResourceLimit); + uint64 gasLimit = uint64( + bound(_gasLimit, portal.minimumGasLimit(uint64(_data.length)), maxResourceLimit - cachedPrevBoughtGas) + ); + + try portal.depositTransaction{ value: value }(_to, value, gasLimit, _isCreation, _data) { + // Do nothing; Call succeeded + } catch { + failedToComplete = true; + } + } +} + +contract OptimismPortal2_Invariant_Harness is CommonTest { + // Reusable default values for a test withdrawal + Types.WithdrawalTransaction _defaultTx; + + uint256 _proposedGameIndex; + uint256 _proposedBlockNumber; + bytes32 _stateRoot; + bytes32 _storageRoot; + bytes32 _outputRoot; + bytes32 _withdrawalHash; + bytes[] _withdrawalProof; + Types.OutputRootProof internal _outputRootProof; + + function setUp() public virtual override { + super.enableFaultProofs(); + super.setUp(); + + _defaultTx = Types.WithdrawalTransaction({ + nonce: 0, + sender: alice, + target: bob, + value: 100, + gasLimit: 100_000, + data: hex"" + }); + // Get withdrawal proof data we can use for testing. + (_stateRoot, _storageRoot, _outputRoot, _withdrawalHash, _withdrawalProof) = + ffi.getProveWithdrawalTransactionInputs(_defaultTx); + + // Setup a dummy output root proof for reuse. + _outputRootProof = Types.OutputRootProof({ + version: bytes32(uint256(0)), + stateRoot: _stateRoot, + messagePasserStorageRoot: _storageRoot, + latestBlockhash: bytes32(uint256(0)) + }); + + // Create a dispute game with the output root we've proposed. + _proposedBlockNumber = 0xFF; + FaultDisputeGame game = FaultDisputeGame( + payable( + address( + disputeGameFactory.create( + optimismPortal2.respectedGameType(), Claim.wrap(_outputRoot), abi.encode(_proposedBlockNumber) + ) + ) + ) + ); + _proposedGameIndex = disputeGameFactory.gameCount() - 1; + + // Warp beyond the finalization period for the dispute game and resolve it. + vm.warp(block.timestamp + game.gameDuration().raw() + 1 seconds); + game.resolveClaim(0); + game.resolve(); + + // Fund the portal so that we can withdraw ETH. + vm.deal(address(optimismPortal2), 0xFFFFFFFF); + } +} + +contract OptimismPortal2_Deposit_Invariant is CommonTest { + OptimismPortal2_Depositor internal actor; + + function setUp() public override { + super.setUp(); + // Create a deposit actor. + actor = new OptimismPortal2_Depositor(vm, optimismPortal2); + + targetContract(address(actor)); + + bytes4[] memory selectors = new bytes4[](1); + selectors[0] = actor.depositTransactionCompletes.selector; + FuzzSelector memory selector = FuzzSelector({ addr: address(actor), selectors: selectors }); + targetSelector(selector); + } + + /// @custom:invariant Deposits of any value should always succeed unless + /// `_to` = `address(0)` or `_isCreation` = `true`. + /// + /// All deposits, barring creation transactions and transactions + /// sent to `address(0)`, should always succeed. + function invariant_deposit_completes() external { + assertEq(actor.failedToComplete(), false); + } +} + +contract OptimismPortal2_CannotTimeTravel is OptimismPortal2_Invariant_Harness { + function setUp() public override { + super.setUp(); + + // Prove the withdrawal transaction + optimismPortal2.proveWithdrawalTransaction(_defaultTx, _proposedGameIndex, _outputRootProof, _withdrawalProof); + + // Set the target contract to the portal proxy + targetContract(address(optimismPortal2)); + // Exclude the proxy admin from the senders so that the proxy cannot be upgraded + excludeSender(EIP1967Helper.getAdmin(address(optimismPortal2))); + } + + /// @custom:invariant `finalizeWithdrawalTransaction` should revert if the proof maturity period has not elapsed. + /// + /// A withdrawal that has been proven should not be able to be finalized + /// until after the proof maturity period has elapsed. + function invariant_cannotFinalizeBeforePeriodHasPassed() external { + vm.expectRevert("OptimismPortal: proven withdrawal has not matured yet"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + } +} + +contract OptimismPortal2_CannotFinalizeTwice is OptimismPortal2_Invariant_Harness { + function setUp() public override { + super.setUp(); + + // Prove the withdrawal transaction + optimismPortal2.proveWithdrawalTransaction(_defaultTx, _proposedGameIndex, _outputRootProof, _withdrawalProof); + + // Warp past the proof maturity period. + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); + + // Finalize the withdrawal transaction. + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + + // Set the target contract to the portal proxy + targetContract(address(optimismPortal2)); + // Exclude the proxy admin from the senders so that the proxy cannot be upgraded + excludeSender(EIP1967Helper.getAdmin(address(optimismPortal2))); + } + + /// @custom:invariant `finalizeWithdrawalTransaction` should revert if the withdrawal has already been finalized. + /// + /// Ensures that there is no chain of calls that can be made that allows a withdrawal to be + /// finalized twice. + function invariant_cannotFinalizeTwice() external { + vm.expectRevert("OptimismPortal: withdrawal has already been finalized"); + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + } +} + +contract OptimismPortal_CanAlwaysFinalizeAfterWindow is OptimismPortal2_Invariant_Harness { + function setUp() public override { + super.setUp(); + + // Prove the withdrawal transaction + optimismPortal2.proveWithdrawalTransaction(_defaultTx, _proposedGameIndex, _outputRootProof, _withdrawalProof); + + // Warp past the proof maturity period. + vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); + + // Set the target contract to the portal proxy + targetContract(address(optimismPortal2)); + // Exclude the proxy admin from the senders so that the proxy cannot be upgraded + excludeSender(EIP1967Helper.getAdmin(address(optimismPortal2))); + } + + /// @custom:invariant A withdrawal should **always** be able to be finalized `PROOF_MATURITY_DELAY_SECONDS` after + /// it was successfully proven, if the game has resolved and passed the air-gap. + /// + /// This invariant asserts that there is no chain of calls that can be made that will prevent a + /// withdrawal from being finalized exactly `PROOF_MATURITY_DELAY_SECONDS` after it was + /// successfully proven and the game has resolved and passed the air-gap. + function invariant_canAlwaysFinalize() external { + uint256 bobBalanceBefore = address(bob).balance; + + optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); + + assertEq(address(bob).balance, bobBalanceBefore + _defaultTx.value); + } +} diff --git a/packages/contracts-bedrock/test/invariants/ResourceMetering.t.sol b/packages/contracts-bedrock/test/invariants/ResourceMetering.t.sol index 866861331219..091bc54adae2 100644 --- a/packages/contracts-bedrock/test/invariants/ResourceMetering.t.sol +++ b/packages/contracts-bedrock/test/invariants/ResourceMetering.t.sol @@ -8,8 +8,8 @@ import { StdInvariant } from "forge-std/StdInvariant.sol"; import { Arithmetic } from "src/libraries/Arithmetic.sol"; import { ResourceMetering } from "src/L1/ResourceMetering.sol"; -import { Proxy } from "src/universal/Proxy.sol"; import { Constants } from "src/libraries/Constants.sol"; +import { InvariantTest } from "test/invariants/InvariantTest.sol"; contract ResourceMetering_User is StdUtils, ResourceMetering { bool public failedMaxGasPerBlock; @@ -137,10 +137,11 @@ contract ResourceMetering_User is StdUtils, ResourceMetering { function _burnInternal(uint64 _gasToBurn) private metered(_gasToBurn) { } } -contract ResourceMetering_Invariant is StdInvariant, Test { +contract ResourceMetering_Invariant is StdInvariant, InvariantTest { ResourceMetering_User internal actor; - function setUp() public { + function setUp() public override { + super.setUp(); // Create a actor. actor = new ResourceMetering_User(); diff --git a/packages/contracts-bedrock/test/invariants/SafeCall.t.sol b/packages/contracts-bedrock/test/invariants/SafeCall.t.sol index 66fbc0be115b..849154aa2d65 100644 --- a/packages/contracts-bedrock/test/invariants/SafeCall.t.sol +++ b/packages/contracts-bedrock/test/invariants/SafeCall.t.sol @@ -5,11 +5,13 @@ import { Test } from "forge-std/Test.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; import { Vm } from "forge-std/Vm.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; +import { InvariantTest } from "test/invariants/InvariantTest.sol"; -contract SafeCall_Succeeds_Invariants is Test { +contract SafeCall_Succeeds_Invariants is InvariantTest { SafeCaller_Actor actor; - function setUp() public { + function setUp() public override { + super.setUp(); // Create a new safe caller actor. actor = new SafeCaller_Actor(vm, false); @@ -37,10 +39,11 @@ contract SafeCall_Succeeds_Invariants is Test { } } -contract SafeCall_Fails_Invariants is Test { +contract SafeCall_Fails_Invariants is InvariantTest { SafeCaller_Actor actor; - function setUp() public { + function setUp() public override { + super.setUp(); // Create a new safe caller actor. actor = new SafeCaller_Actor(vm, true); diff --git a/packages/contracts-bedrock/test/invariants/SystemConfig.t.sol b/packages/contracts-bedrock/test/invariants/SystemConfig.t.sol index e06c6ca0aff7..75b4e6c2b265 100644 --- a/packages/contracts-bedrock/test/invariants/SystemConfig.t.sol +++ b/packages/contracts-bedrock/test/invariants/SystemConfig.t.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.15; import { Test } from "forge-std/Test.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; import { Proxy } from "src/universal/Proxy.sol"; -import { ResourceMetering } from "src/L1/ResourceMetering.sol"; import { Constants } from "src/libraries/Constants.sol"; contract SystemConfig_GasLimitLowerBound_Invariant is Test { diff --git a/packages/contracts-bedrock/test/kontrol/README.md b/packages/contracts-bedrock/test/kontrol/README.md index a9a171d0f114..341715601568 100644 --- a/packages/contracts-bedrock/test/kontrol/README.md +++ b/packages/contracts-bedrock/test/kontrol/README.md @@ -1,88 +1,194 @@ # Kontrol Verification -This folder contains Kontrol symbolic property tests. + + -## Directory structure +- [Getting Started](#getting-started) + - [Overview](#overview) + - [Directory structure](#directory-structure) + - [Installation](#installation) +- [Usage](#usage) + - [Build Deployment Summary](#build-deployment-summary) + - [Execute Proofs](#execute-proofs) + - [Add New Proofs](#add-new-proofs) +- [Implementation Details](#implementation-details) + - [Assumptions](#assumptions) + - [Deployment Summary Process](#deployment-summary-process) -The directory is structured as follows + -```tree -test/kontrol -├── KontrolDeployment.sol -├── pausability-lemmas.k -├── proofs -│   ├── interfaces -│   │   └── KontrolInterfaces.sol -│   ├── OptimismPortal.k.sol -│   ├── tests -│   │   ├── Counter.sol -│   │   └── Counter.t.sol -│   └── utils -│   ├── DeploymentSummaryCode.sol -│   ├── DeploymentSummary.sol -│   └── KontrolUtils.sol -├── README.md -└── scripts - ├── json - │   ├── clean_json.py - │   └── reverse_key_values.py - ├── make-summary-deployment.sh - └── run-kontrol.sh -``` +## Getting Started + +### Overview -### Root folder +[Kontrol](https://github.com/runtimeverification/kontrol) is a tool by [Runtime Verification](https://runtimeverification.com/) (RV) that enables formal verification of Ethereum smart contracts. Quoting from the Kontrol [docs](https://docs.runtimeverification.com/kontrol/overview/readme): -- [`KontrolDeployment.sol`](./KontrolDeployment.sol): Reduced deployment to generate the summary contract -- [`pausability-lemmas.k`](./pausability-lemmas.k): File containing the necessary lemmas for this project -- [`proofs`](./proofs): Where the proofs of the project live -- [`scripts`](./scripts): Where the scripts of the projects live +> Kontrol combines [KEVM](https://github.com/runtimeverification/evm-semantics) and [Foundry](https://book.getfoundry.sh/) to grant developers the ability to perform [formal verification](https://en.wikipedia.org/wiki/Formal_verification) without learning a new language or tool. This is especially useful for those who are not verification engineers. Additionally, developers can leverage Foundry test suites they have already developed and use symbolic execution to increase the level of confidence. +> +> KEVM is a tool that enables formal verification of smart contracts on the Ethereum blockchain. It provides a mathematical foundation for specifying and implementing smart contracts. Developers can use KEVM to rigorously reason about the behavior of their smart contracts, ensuring correctness and reducing the likelihood of vulnerabilities in the contract code. -### [`proofs`](./proofs) folder +This document details the Kontrol setup used in this repo to run various proofs against the contracts in the [`contracts-bedrock`](../../) directory. + +### Directory structure + +The directory is structured as follows -- [`OptimismPortal.k.sol`](./proofs/OptimismPortal.k.sol): Symbolic property tests -- [`interfaces`](./proofs/interfaces): Files with the signature of the functions involved in the verification effort -- [`utils`](./proofs/utils): Dependencies for `OptimismPortal.k.sol`, including the summary contracts +
+├── pausability-lemmas.md: File containing the necessary lemmas for this project
+├── deployment: Custom deploy sequence for Kontrol proofs and tests for its fast summarization
+│   ├── KontrolDeployment.sol: Simplified deployment sequence for Kontrol proofs
+│   └── DeploymentSummary.t.sol: Tests for the summarization of custom deployment
+├── proofs: Where the proofs (tests) themselves live
+│   ├── *.k.sol: Symbolic property tests for contracts
+│   ├── interfaces: Interface files for src contracts, to avoid unnecessary compilation of contracts
+│   └── utils: Proof dependencies, including the autogenerated deployment summary contracts
+└── scripts: Where the scripts of the projects live
+    ├── json: Data cleaning scripts for the output of KontrolDeployment.sol
+    ├── make-summary-deployment.sh: Executes KontrolDeployment.sol, curates the result and writes the summary deployment contract
+    └── run-kontrol.sh: Wrapper around the kontrol CLI to run the proofs
+
-### [`scripts`](./scripts) folder +### Installation -- [`make-summary-deployment.sh`](./scripts/make-summary-deployment.sh): Executes [`KontrolDeployment.sol`](./KontrolDeployment.sol), curates the result and writes the summary deployment contract -- [`run-kontrol.sh`](./scrpts/run-kontrol.sh): Proof execution script -- [`json`](./scripts/json): Data cleaning scripts for the output of [`KontrolDeployment.sol`](./KontrolDeployment.sol) +1. `cd` to the root of this repo. +2. Install Foundry by running `pnpm install:foundry`. This installs `foundryup`, the foundry toolchain installer, then installs the required foundry version. +3. Install Kontrol by running `pnpm install:kontrol`. This installs `kup`, the package manager for RV tools, then installs the required kontrol version. +4. Install Docker. -## Verification execution +## Usage -The verification execution consists of two steps, although the first step may be omitted to use the committed version. There's one script to run per step. These scripts should be run from the [`contracts-bedrock`](../../) directory. +Verifying proofs has two steps: build, and execute. -1. Generate a deployment summary contract from [`KontrolDeployment.sol`](./KontrolDeployment.sol) -```bash - ./test/kontrol/scripts/make-summary-deployment.sh +### Build Deployment Summary + +First, generate a deployment summary contract from the deploy script in [`KontrolDeployment.sol`](./deployment/KontrolDeployment.sol) by running the following command: + +``` +./test/kontrol/scripts/make-summary-deployment.sh [container|local|dev] ``` -This step is optional. The default summary can be found [here](./proofs/utils/DeploymentSummary.sol), which is the summarization of the [`KontrolDeployment.sol`](./KontrolDeployment.sol) script. -2. Execute the tests in [`OptimismPortal.k.sol`](./proofs/OptimismPortal.k.sol) -```bash - ./test/kontrol/scripts/run-kontrol.sh $option +The [`make-summary-deployment.sh`](./scripts/make-summary-deployment.sh) supports the same execution modes as `run-kontrol.sh` below. + +[`KontrolDeployment.sol`](./deployment/KontrolDeployment.sol) contains the minimal deployment sequence required by the proofs. +The [`make-summary-deployment.sh`](./scripts/make-summary-deployment.sh) script will generate a JSON state diff. This state diff is used in two ways by Kontrol. +First, Kontrol generates a summary contract recreating the state diffs recorded in the JSON. This contract is used to test that the information contained in the generated JSON is correct and aids in the specification of the symbolic property tests. The generation of this contract is also handled by the `make-summary-deployment.sh` script. +Second, the state diff JSON is used to load the post-deployment state directly into Kontrol when running the proofs. + +This step is optional if an up-to-date summary contract already exists, which will be the case until the `KontrolDeployment` contract changes, or any of the source contracts under test change. +See the [Implementation Details](#implementation-details) section for more information, and to learn about the CI check that ensures the committed autogenerated files from this step are up-to-date. + +The summary contract can be found in [`DeploymentSummary.sol`](./proofs/utils/DeploymentSummary.sol), which is summarization (state changes) of the [`KontrolDeployment.sol`](./deployment/KontrolDeployment.sol) contract. + +### Execute Proofs + +Use the [`run-kontrol.sh`](./scripts/run-kontrol.sh) script to runs the proofs in all `*.k.sol` files. + +``` +./test/kontrol/scripts/run-kontrol.sh [container|local|dev] [script|tests] ``` -See below for further documentation on `run-kontrol.sh`. -### `run-kontrol.sh` script -The `run-kontrol.sh` script handles all modes of proof execution. The modes, corresponding to the available arguments of the script, are the following: -- `container`: Run the proofs in the same docker image used in CI. The intended use case is CI debugging. This is the default execution mode, meaning that if no arguments are provided, the proofs will be executed in this mode. -- `local`: Run the proofs with your local Kontrol install, enforcing the version to be the same as the one used in CI. The intended use case is running the proofs without risking discrepancies because of different Kontrol versions. +The `run-kontrol.sh` script supports three modes of proof execution: + +- `container`: Runs the proofs using the same Docker image used in CI. This is the default execution mode—if no arguments are provided, the proofs will be executed in this mode. +- `local`: Runs the proofs with your local Kontrol install, and enforces that the Kontrol version matches the one used in CI, which is specified in [`versions.json`](../../../../versions.json). - `dev`: Run the proofs with your local Kontrol install, without enforcing any version in particular. The intended use case is proof development and related matters. +It also supports two methods for specifying which tests to execute: + +- `script`: Runs the tests specified in the `test_list` variable +- `tests`: Names of the tests to be executed. `tests` can have two forms: + - `ContractName.testName`: e.g., `run-kontrol.sh ContractName.test1 ContractName.test2` + - Empty, executing all the functions starting with `test`, `prove` or `check` present in the defined `out` directory. For instance, `./test/kontrol/scripts/run-kontrol.sh` will execute all `prove_*` functions in the [proofs](./proofs/) directory using the same Docker image as in CI. [Warning: executing all proofs in parallel is _very_ resource intensive] + For a similar description of the options run `run-kontrol.sh --help`. -## Kontrol Foundry profiles +### Add New Proofs + +These are the instructions to add a new proof to this project. If all functions involved in the new proof are from a contract already deployed by [`KontrolDeployment`](./deployment/KontrolDeployment.sol) the first two steps can be skipped. + +#### Make Kontrol aware of the new contract being tested + +The `runKontrolDeployment` function of [`KontrolDeployment`](./deployment/KontrolDeployment.sol) partially reproduces the deployment process laid out in the `_run` function of [`Deploy.s.sol`](../../scripts/Deploy.s.sol). `runKontrolDeployment` has the `stateDiff` modifier to make use of [Foundry's state diff cheatcodes](https://book.getfoundry.sh/cheatcodes/start-state-diff-recording). Kontrol utilizes the JSON resulting from this modifier for two purposes: +1. Load all the state updates generated by `runKontrolDeployment` as the initial configuration for all proofs, effectively offloading the computation of the deployment process to `forge` and thus improving performance. +2. Produce the [`DeploymentSummary`](./proofs/utils/DeploymentSummary.sol) script contract to test that the produced JSON contains correct updates. + +Hence, in order to write a proof for a contract which is not present in `KontrolDeployment` it must be added there first. To add a new contract, properly inspect the above-mentioned `_run` function and place the corresponding deployment steps of the contract appropriately within the `runKontrolDeployment` function. + +Once new deployment steps have been added to `runKontrolDeployment` the state-diff files have to [be rebuilt](#build-deployment-summary). + +#### Include existing tests on the new state-diff recorded bytecode + +The next step is to include tests for the newly included state updates in [`DeploymentSummary.t.sol`](deployment/DeploymentSummary.t.sol). These tests inherit the tests from [`test`](../L1) of the contracts deployed by `runKontrolDeployment`. This ensures that deployment steps were implemented correctly and that the state updates are correct. + +It might be necessary to set some of the existing tests from [`test`](../L1) as virtual because they can't be executed as is. See [`DeploymentSummary.t.sol`](deployment/DeploymentSummary.t.sol) for more concrete examples. + +#### Add function signatures to [`KontrolInterfaces`](./proofs/interfaces/KontrolInterfaces.sol) + +So far we've got all the state updates ready to be added to the initial configuration of each proof, but we cannot yet write any proof about the function. We still need to add the relevant signatures into `KontrolInterfaces`. The reason for having `KontrolInterfaces` instead of using directly the contracts is to reduce the amount of compiled contracts by Kontrol. +In the future there might interfaces for all contracts under `contracts-bedrock`, which would imply the removal of `KontrolInterfaces`. + +#### Write the proof + +Write your proof in a `.k.sol` file in the [`proofs`](./proofs/) folder, which is the `test` directory used by the `kprove` profile to run the proofs (see [Deployment Summary Process](#deployment-summary-process)). The name of the new proofs should start with `prove` (or `check`) instead of `test` to avoid `forge test` running them. The reason for this is that if Kontrol cheatcodes (see [Kontrol's own cheatcodes](https://github.com/runtimeverification/kontrol-cheatcodes/blob/master/src/KontrolCheats.sol)) are used in a test, it will not be runnable by `forge`. Currently, none of the tests are using custom Kontrol cheatcodes, but this is something to bear in mind. + +To reference the correct addresses for writing the tests, first import the signatures as in this example: +```solidity +import { + IOptimismPortal as OptimismPortal, + ISuperchainConfig as SuperchainConfig +} from "./interfaces/KontrolInterfaces.sol"; +``` +Declare the correspondent variables and cast the correct signatures to the correct addresses: +```solidity +OptimismPortal optimismPortal; +SuperchainConfig superchainConfig; + +function setUp() public { + optimismPortal = OptimismPortal(payable(optimismPortalProxyAddress)); + superchainConfig = SuperchainConfig(superchainConfigProxyAddress); +} +``` +Note that the names of the addresses come from [`DeploymentSummary.t.sol`](deployment/DeploymentSummary.t.sol) and are automatically generated by the [`make-summary-deployment.sh`](./scripts/make-summary-deployment.sh) script. + +#### Add your test to [`run-kontrol.sh`](./scripts/run-kontrol.sh) + +As described in [Execute Proofs](#execute-proofs), there's a `script` mode for specifying which proofs to run, and that is the mode used in CI. To run the new proofs with the `script` option, add `ContractName.prove_functionName_paused` to the variable `test_list` in the `run-kontrol.sh` script. + +## Implementation Details + +### Assumptions + +1. A critical invariant of the `KontrolDeployment.sol` contract is that it stays in sync with the original `Deploy.s.sol` contract. + Currently, this is partly enforced by running some of the standard post-`setUp` deployment assertions in `DeploymentSummary.t.sol`. + A more rigorous approach may be to leverage the `ChainAssertions` library, but more investigation is required to determine if this is feasible without large changes to the deploy script. + +2. Size of `bytes[]` arguments. In [`OptimismPortal.k.sol`](./proofs/OptimismPortal.k.sol), the `prove_proveWithdrawalTransaction_paused` proof is broken down into 11 different proofs, each corresponding to a different size of the `_withdrawalProof` argument, which is of type `bytes[]`. We execute the same logic for lengths of `_withdrawalProof` ranging from 0 to 10, setting the length of each symbolic `bytes` element to 600. + - The reason for a max length of 10 is that it provides a conservative upper bound based on [historical data](https://dune.com/queries/3433954/5768623) for proof sizes. + - The reason for choosing 600 as the length for the elements of `_withdrawalProof` is that each element is `17 * 32 = 544` bytes long, so adding a 10% margin for RLP encoding and rounding up yields 600 bytes. The same historical data confirms this is a valid bound. + - All other symbolic `bytes` arguments that are not part of a `bytes` array have a symbolic length bounded by `2^63`. + +### Deployment Summary Process + +As mentioned above, a deployment summary contract is first generated before executing the proofs. +This is because the proof execution leverages Kontrol's [fast summarization](https://github.com/runtimeverification/kontrol/pull/271) feature, which allows loading the post-`setUp` state directly into Kontrol. +This provides a significant reduction in proof execution time, as it avoids the need to execute the deployment script every time the proofs are run. -This project uses two different [Foundry profiles](../../foundry.toml), `kdeploy` and `kprove`. +All code executed in Kontrol—even when execution is concrete and not symbolic—is significantly slower than in Foundry, due to the mathematical representation of the EVM in Kontrol. +Therefore we want to minimize the amount of code executed in Kontrol, and the fast summarization feature allows us to reduce `setUp` execution time. -- `kdeploy`: This profile is used to generate a summary contract from the execution of the [`KontrolDeployment.sol`](./KontrolDeployment.sol) script. In particular, the `kdeploy` profile is used by the [`make-summary-deployment.sh`](./scripts/make-summary-deployment.sh) script to generate the [deployment summary contract](./proofs/utils/DeploymentSummary.sol). The summary contract is then used with the `kprove` profile to load the post-setUp state directly into Kontrol. We don't need the output artifacts from this step, so we save them to the `kout-deployment` directory, which is not used anywhere else. We also point the script path to the `scripts-kontrol` directory, which does not exist, to avoid compiling scripts we don't need, which reduces execution time. +This project uses two different [`foundry.toml` profiles](../../foundry.toml), `kdeploy` and `kprove`, to facilitate usage of this fast summarization feature.: -- `kprove`: This profile is used by the [`run-kontrol.sh`](./scrpts/run-kontrol.sh) script, which needs to be run after executing [`./test/kontrol/script/make-summary-deployment`](./scripts/make-summary-deployment.sh) (this last script uses the `kdeploy` profile). The proofs are executed using the `kprove` profile. The `src` directory points to a test folder because we only want to compile what is in the `test/kontrol/proofs` folder since it contains all the deployed bytecode and the proofs. We similarly point the script path to a non-existent directory for the same reason as above. The `out` folder for this profile is `kout-proofs`. +- `kdeploy`: Used by [`make-summary-deployment.sh`](./scripts/make-summary-deployment.sh) to generate the [`DeploymentSummary.sol`](./proofs/utils/DeploymentSummary.sol) contract based on execution of the [`KontrolDeployment.sol`](./deployment/KontrolDeployment.sol) contract using Foundry's state diff recording cheatcodes. + This is where all necessary [`src/L1`](../../src/L1) files are compiled with their bytecode saved into the [`DeploymentSummaryCode.sol`](./proofs/utils/DeploymentSummaryCode.sol) file, which is inherited by `DeploymentSummary`. -Note that the compilation of the necessary `src/L1` files is done with the `kdeploy` profile, and the results are saved into [`test/kontrol/proofs/utils/DeploymentSummary.sol`](./proofs/utils/DeploymentSummary.sol). So, when running the `kprove` profile, the deployed bytecode of the `src/L1` files are recorded in the automatically generated file `test/kontrol/proofs/utils/DeploymentSummaryCode.sol`. +- `kprove`: Used by the [`run-kontrol.sh`](./scrpts/run-kontrol.sh) script to execute proofs, which can be run once a `DeploymentSummary.sol` contract is present. This profile's `src` and `script` paths point to a test folder because we only want to compile what is in the `test/kontrol/proofs` folder, since that folder contains all bytecode and proofs. -## References +The `make-summary-deployment.sh` scripts saves off the generated JSON state diff to `snapshots/state-diff/Kontrol-Deploy.json`, and is run as part of the `snapshots` script in `package.json`. +Therefore, the snapshots CI check will fail if the committed Kontrol state diff is out of sync. +Note that the CI check only compares the JSON state diff, not the generated `DeploymentSummary.sol` or `DeploymentSummaryCode` contracts. +This is for simplicity, as those three files will be in sync upon successful execution of the `make-summary-deployment.sh` script. +We commit the `DeploymentSummary.sol` and `DeploymentSummaryCode.sol` contracts, because forge fails to build if those contracts are not present—it is simpler to commit these autogenerated files than to workaround their absence in forge builds. -[Kontrol docs](https://docs.runtimeverification.com/kontrol/overview/readme) +During `make-summary-deployment.sh`, the `mustGetAddress` usage in `Deploy.s.sol` is temporarily replaced by `getAddress`—the former reverts if the deployed contract does not exist, while the latter returns the zero address. +This is required because the deploy script in `KontrolDeployment.sol` is does not fully reproduce all deployments in `Deploy.s.sol`, so the `mustGetAddress` usage would cause the script to revert since some contracts are not deployed. +`KontrolDeployment.sol` is a simplified, minimal deployment sequence for Kontrol proofs, and is not intended to be a full deployment sequence for the contracts in `contracts-bedrock`. diff --git a/packages/contracts-bedrock/test/kontrol/deployment/DeploymentSummary.t.sol b/packages/contracts-bedrock/test/kontrol/deployment/DeploymentSummary.t.sol new file mode 100644 index 000000000000..90b73b9e987e --- /dev/null +++ b/packages/contracts-bedrock/test/kontrol/deployment/DeploymentSummary.t.sol @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +// Libraries +import { Constants } from "src/libraries/Constants.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; + +// Target contract dependencies +import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; +import { SystemConfig } from "src/L1/SystemConfig.sol"; +import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { OptimismPortal } from "src/L1/OptimismPortal.sol"; +import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; +import { DeploymentSummary } from "../proofs/utils/DeploymentSummary.sol"; +import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; +import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { LegacyMintableERC20 } from "src/legacy/LegacyMintableERC20.sol"; + +// Tests +import { L1CrossDomainMessenger_Test } from "test/L1/L1CrossDomainMessenger.t.sol"; +import { OptimismPortal_Test } from "test/L1/OptimismPortal.t.sol"; +import { L1ERC721Bridge_Test, TestERC721 } from "test/L1/L1ERC721Bridge.t.sol"; +import { + L1StandardBridge_Getter_Test, + L1StandardBridge_Initialize_Test, + L1StandardBridge_Pause_Test +} from "test/L1/L1StandardBridge.t.sol"; + +/// @dev Contract testing the deployment summary correctness +contract DeploymentSummary_TestOptimismPortal is DeploymentSummary, OptimismPortal_Test { + /// @notice super.setUp is not called on purpose + function setUp() public override { + // Recreate Deployment Summary state changes + DeploymentSummary deploymentSummary = new DeploymentSummary(); + deploymentSummary.recreateDeployment(); + + // Set summary addresses + optimismPortal = OptimismPortal(payable(optimismPortalProxyAddress)); + superchainConfig = SuperchainConfig(superchainConfigProxyAddress); + l2OutputOracle = L2OutputOracle(l2OutputOracleProxyAddress); + systemConfig = SystemConfig(systemConfigProxyAddress); + + // Set up utilized addresses + depositor = makeAddr("depositor"); + alice = makeAddr("alice"); + bob = makeAddr("bob"); + vm.deal(alice, 10000 ether); + vm.deal(bob, 10000 ether); + } + + /// @dev Skips the first line of `super.test_constructor_succeeds` because + /// we're not exercising the `Deploy` logic in these tests. However, + /// the remaining assertions of the test are important to check + function test_constructor_succeeds() external override { + // OptimismPortal opImpl = OptimismPortal(payable(deploy.mustGetAddress("OptimismPortal"))); + OptimismPortal opImpl = OptimismPortal(payable(optimismPortalAddress)); + assertEq(address(opImpl.L2_ORACLE()), address(0)); + assertEq(address(opImpl.l2Oracle()), address(0)); + assertEq(address(opImpl.SYSTEM_CONFIG()), address(0)); + assertEq(address(opImpl.systemConfig()), address(0)); + assertEq(address(opImpl.superchainConfig()), address(0)); + assertEq(opImpl.l2Sender(), Constants.DEFAULT_L2_SENDER); + } + + /// @dev Skips the first line of `super.test_initialize_succeeds` because + /// we're not exercising the `Deploy` logic in these tests. However, + /// the remaining assertions of the test are important to check + function test_initialize_succeeds() external override { + // address guardian = deploy.cfg().superchainConfigGuardian(); + address guardian = superchainConfig.guardian(); + assertEq(address(optimismPortal.L2_ORACLE()), address(l2OutputOracle)); + assertEq(address(optimismPortal.l2Oracle()), address(l2OutputOracle)); + assertEq(address(optimismPortal.SYSTEM_CONFIG()), address(systemConfig)); + assertEq(address(optimismPortal.systemConfig()), address(systemConfig)); + assertEq(optimismPortal.GUARDIAN(), guardian); + assertEq(optimismPortal.guardian(), guardian); + assertEq(address(optimismPortal.superchainConfig()), address(superchainConfig)); + assertEq(optimismPortal.l2Sender(), Constants.DEFAULT_L2_SENDER); + assertEq(optimismPortal.paused(), false); + } + + /// @notice This test is overridden because `KontrolDeployment` doesn't initialize + /// the L2OutputOracle, which is needed in this test + function test_simple_isOutputFinalized_succeeds() external override { } + + /// @notice This test is overridden because `KontrolDeployment` doesn't initialize + /// the L2OutputOracle, which is needed in this test + function test_isOutputFinalized_succeeds() external override { } +} + +contract DeploymentSummary_TestL1CrossDomainMessenger is DeploymentSummary, L1CrossDomainMessenger_Test { + /// @notice super.setUp is not called on purpose + function setUp() public override { + // Recreate Deployment Summary state changes + DeploymentSummary deploymentSummary = new DeploymentSummary(); + deploymentSummary.recreateDeployment(); + + // Set summary addresses + optimismPortal = OptimismPortal(payable(optimismPortalProxyAddress)); + superchainConfig = SuperchainConfig(superchainConfigProxyAddress); + l2OutputOracle = L2OutputOracle(l2OutputOracleProxyAddress); + systemConfig = SystemConfig(systemConfigProxyAddress); + l1CrossDomainMessenger = L1CrossDomainMessenger(l1CrossDomainMessengerProxyAddress); + + // Set up utilized addresses + alice = makeAddr("alice"); + bob = makeAddr("bob"); + vm.deal(alice, 10000 ether); + vm.deal(bob, 10000 ether); + } + + /// @dev Skips the first line of `super.test_constructor_succeeds` because + /// we're not exercising the `Deploy` logic in these tests. However, + /// the remaining assertions of the test are important to check + function test_constructor_succeeds() external override { + // L1CrossDomainMessenger impl = L1CrossDomainMessenger(deploy.mustGetAddress("L1CrossDomainMessenger")); + L1CrossDomainMessenger impl = L1CrossDomainMessenger(l1CrossDomainMessengerAddress); + assertEq(address(impl.superchainConfig()), address(0)); + assertEq(address(impl.PORTAL()), address(0)); + assertEq(address(impl.portal()), address(0)); + assertEq(address(impl.OTHER_MESSENGER()), Predeploys.L2_CROSS_DOMAIN_MESSENGER); + assertEq(address(impl.otherMessenger()), Predeploys.L2_CROSS_DOMAIN_MESSENGER); + } + + /// @notice This test is overridden because `KontrolDeployment` doesn't deploy + /// L2CrossDomainMessenger, which is needed in this test + function test_relayMessage_v2_reverts() external override { } +} + +contract DeploymentSummary_TestL1ERC721Bridge is DeploymentSummary, L1ERC721Bridge_Test { + /// @notice super.setUp is not called on purpose + function setUp() public override { + // Recreate Deployment Summary state changes + DeploymentSummary deploymentSummary = new DeploymentSummary(); + deploymentSummary.recreateDeployment(); + + // Set summary addresses + optimismPortal = OptimismPortal(payable(optimismPortalProxyAddress)); + superchainConfig = SuperchainConfig(superchainConfigProxyAddress); + l2OutputOracle = L2OutputOracle(l2OutputOracleProxyAddress); + systemConfig = SystemConfig(systemConfigProxyAddress); + l1CrossDomainMessenger = L1CrossDomainMessenger(l1CrossDomainMessengerProxyAddress); + l1ERC721Bridge = L1ERC721Bridge(l1ERC721BridgeProxyAddress); + + // Set up utilized addresses + alice = makeAddr("alice"); + bob = makeAddr("bob"); + vm.deal(alice, 10000 ether); + vm.deal(bob, 10000 ether); + + // Bridge_Initializer setUp + L1Token = new ERC20("Native L1 Token", "L1T"); + + LegacyL2Token = new LegacyMintableERC20({ + _l2Bridge: address(l2StandardBridge), + _l1Token: address(L1Token), + _name: string.concat("LegacyL2-", L1Token.name()), + _symbol: string.concat("LegacyL2-", L1Token.symbol()) + }); + vm.label(address(LegacyL2Token), "LegacyMintableERC20"); + + // Deploy the L2 ERC20 now + // L2Token = OptimismMintableERC20( + // l2OptimismMintableERC20Factory.createStandardL2Token( + // address(L1Token), + // string(abi.encodePacked("L2-", L1Token.name())), + // string(abi.encodePacked("L2-", L1Token.symbol())) + // ) + // ); + + // BadL2Token = OptimismMintableERC20( + // l2OptimismMintableERC20Factory.createStandardL2Token( + // address(1), + // string(abi.encodePacked("L2-", L1Token.name())), + // string(abi.encodePacked("L2-", L1Token.symbol())) + // ) + // ); + + NativeL2Token = new ERC20("Native L2 Token", "L2T"); + + // RemoteL1Token = OptimismMintableERC20( + // l1OptimismMintableERC20Factory.createStandardL2Token( + // address(NativeL2Token), + // string(abi.encodePacked("L1-", NativeL2Token.name())), + // string(abi.encodePacked("L1-", NativeL2Token.symbol())) + // ) + // ); + + // BadL1Token = OptimismMintableERC20( + // l1OptimismMintableERC20Factory.createStandardL2Token( + // address(1), + // string(abi.encodePacked("L1-", NativeL2Token.name())), + // string(abi.encodePacked("L1-", NativeL2Token.symbol())) + // ) + // ); + + // L1ERC721Bridge_Test setUp + localToken = new TestERC721(); + remoteToken = new TestERC721(); + + // Mint alice a token. + localToken.mint(alice, tokenId); + + // Approve the bridge to transfer the token. + vm.prank(alice); + localToken.approve(address(l1ERC721Bridge), tokenId); + } + + /// @dev Skips the first line of `super.test_constructor_succeeds` because + /// we're not exercising the `Deploy` logic in these tests. However, + /// the remaining assertions of the test are important to check + function test_constructor_succeeds() public override { + // L1ERC721Bridge impl = L1ERC721Bridge(deploy.mustGetAddress("L1ERC721Bridge")); + L1ERC721Bridge impl = L1ERC721Bridge(l1ERC721BridgeAddress); + assertEq(address(impl.MESSENGER()), address(0)); + assertEq(address(impl.messenger()), address(0)); + assertEq(address(impl.OTHER_BRIDGE()), Predeploys.L2_ERC721_BRIDGE); + assertEq(address(impl.otherBridge()), Predeploys.L2_ERC721_BRIDGE); + assertEq(address(impl.superchainConfig()), address(0)); + } +} + +contract DeploymentSummary_TestL1StandardBridge is + DeploymentSummary, + L1StandardBridge_Getter_Test, + L1StandardBridge_Initialize_Test, + L1StandardBridge_Pause_Test +{ + /// @notice super.setUp is not called on purpose + function setUp() public override { + // Recreate Deployment Summary state changes + DeploymentSummary deploymentSummary = new DeploymentSummary(); + deploymentSummary.recreateDeployment(); + + // Set summary addresses + optimismPortal = OptimismPortal(payable(optimismPortalProxyAddress)); + superchainConfig = SuperchainConfig(superchainConfigProxyAddress); + l2OutputOracle = L2OutputOracle(l2OutputOracleProxyAddress); + systemConfig = SystemConfig(systemConfigProxyAddress); + l1CrossDomainMessenger = L1CrossDomainMessenger(l1CrossDomainMessengerProxyAddress); + l1ERC721Bridge = L1ERC721Bridge(l1ERC721BridgeProxyAddress); + l1StandardBridge = L1StandardBridge(payable(l1StandardBridgeProxyAddress)); + } + + /// @dev Skips the first line of `super.test_constructor_succeeds` because + /// we're not exercising the `Deploy` logic in these tests. However, + /// the remaining assertions of the test are important to check + function test_constructor_succeeds() external override { + // L1StandardBridge impl = L1StandardBridge(deploy.mustGetAddress("L1StandardBridge")); + L1StandardBridge impl = L1StandardBridge(payable(l1StandardBridgeAddress)); + assertEq(address(impl.superchainConfig()), address(0)); + assertEq(address(impl.MESSENGER()), address(0)); + assertEq(address(impl.messenger()), address(0)); + assertEq(address(impl.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE); + assertEq(address(impl.otherBridge()), Predeploys.L2_STANDARD_BRIDGE); + assertEq(address(l2StandardBridge), Predeploys.L2_STANDARD_BRIDGE); + } +} diff --git a/packages/contracts-bedrock/test/kontrol/KontrolDeployment.sol b/packages/contracts-bedrock/test/kontrol/deployment/KontrolDeployment.sol similarity index 67% rename from packages/contracts-bedrock/test/kontrol/KontrolDeployment.sol rename to packages/contracts-bedrock/test/kontrol/deployment/KontrolDeployment.sol index 47b321347404..ae88bdb0c3cd 100644 --- a/packages/contracts-bedrock/test/kontrol/KontrolDeployment.sol +++ b/packages/contracts-bedrock/test/kontrol/deployment/KontrolDeployment.sol @@ -12,15 +12,24 @@ contract KontrolDeployment is Deploy { deployERC1967Proxy("OptimismPortalProxy"); deployERC1967Proxy("L2OutputOracleProxy"); deployERC1967Proxy("SystemConfigProxy"); + deployL1StandardBridgeProxy(); + deployL1CrossDomainMessengerProxy(); + deployERC1967Proxy("L1ERC721BridgeProxy"); transferAddressManagerOwnership(); // to the ProxyAdmin // deployImplementations(); deployOptimismPortal(); + deployL1CrossDomainMessenger(); deployL2OutputOracle(); deploySystemConfig(); + deployL1StandardBridge(); + deployL1ERC721Bridge(); // initializeImplementations(); initializeSystemConfig(); + initializeL1StandardBridge(); + initializeL1ERC721Bridge(); + initializeL1CrossDomainMessenger(); initializeOptimismPortal(); } } diff --git a/packages/contracts-bedrock/test/kontrol/pausability-lemmas.k b/packages/contracts-bedrock/test/kontrol/pausability-lemmas.k deleted file mode 100644 index c5fb4aac5d4a..000000000000 --- a/packages/contracts-bedrock/test/kontrol/pausability-lemmas.k +++ /dev/null @@ -1,12 +0,0 @@ -requires "evm.md" -requires "foundry.md" - -module PAUSABILITY-LEMMAS - imports BOOL - imports FOUNDRY - imports INFINITE-GAS - imports INT-SYMBOLIC - -// Your lemmas go here - -endmodule diff --git a/packages/contracts-bedrock/test/kontrol/pausability-lemmas.md b/packages/contracts-bedrock/test/kontrol/pausability-lemmas.md new file mode 100644 index 000000000000..a522a5709e61 --- /dev/null +++ b/packages/contracts-bedrock/test/kontrol/pausability-lemmas.md @@ -0,0 +1,225 @@ +Kontrol Lemmas +============== + +Lemmas are K rewrite rules that enhance the reasoning power of Kontrol. For more information on lemmas, please consult [this section](https://docs.runtimeverification.com/kontrol/guides/advancing-proofs) of the Kontrol documentation. + +This file contains the lemmas required to run the proofs included in the [proofs](./proofs) folder. Some of these lemmas are general enough to likely be incorporated into future versions of Kontrol, while others are specific to the challenges presented by the proofs. + +Similarly to other files such as [`cheatcodes.md`](https://github.com/runtimeverification/kontrol/blob/master/src/kontrol/kdist/cheatcodes.md), we use the idiomatic way of programming in Kontrol, which is [literate programming](https://en.wikipedia.org/wiki/Literate_programming), allowing for better documentation of the code. + +## Imports + +For writing the lemmas, we use the [`foundry.md`](https://github.com/runtimeverification/kontrol/blob/master/src/kontrol/kdist/foundry.md) file. This file contains and imports all of the definitions from KEVM and Kontrol on top of which we write the lemmas. + +```k +requires "foundry.md" + +module PAUSABILITY-LEMMAS + imports BOOL + imports FOUNDRY + imports INT-SYMBOLIC +``` + +## Arithmetic + +Lemmas on arithmetic reasoning. Specifically, on: cancellativity, inequalites in which the two sides are of different signs; and the rounding-up mechanism of the Solidity compiler (expressed through `notMaxUInt5 &Int ( X +Int 31 )`, which rounds up `X` to the nearest multiple of 32). + +```k + // Cancellativity #1 + rule A +Int ( (B -Int A) +Int C ) => B +Int C [simplification] + + // Cancellativity #2 + rule (A -Int B) -Int (C -Int B) => A -Int C [simplification] + + // Cancellativity #3 + rule A -Int (A +Int B) => 0 -Int B [simplification] + + // Various inequalities + rule X true requires X true requires X true requires X true + requires 0 <=Int Y + [simplification] + + // Bounds on notMaxUInt5 &Int ( X +Int 31 ) + rule X <=Int notMaxUInt5 &Int ( X +Int 31 ) => true requires 0 <=Int X [simplification] + rule X <=Int notMaxUInt5 &Int ( Y +Int 31 ) => true requires X <=Int 0 andBool 0 <=Int Y [simplification, concrete(X)] + rule X <=Int ( notMaxUInt5 &Int ( X +Int 31 ) ) +Int Y => true requires 0 <=Int X andBool 0 <=Int Y [simplification, concrete(Y)] + + rule notMaxUInt5 &Int X +Int 31 true requires 0 <=Int X andBool X +Int 32 <=Int Y [simplification, concrete(Y)] + + rule notMaxUInt5 &Int X +Int 31 true requires 0 <=Int X [simplification] +``` + +## `#asWord` + +Lemmas about [`#asWord`](https://github.com/runtimeverification/evm-semantics/blob/master/kevm-pyk/src/kevm_pyk/kproj/evm-semantics/evm-types.md#bytes-helper-functions). `#asWord(B)` interprets the byte array `B` as a single word (with MSB first). + +```k + // Move to function parameters + rule { #asWord ( BA1 ) #Equals #asWord ( BA2 ) } => #Top + requires BA1 ==K BA2 + [simplification] + + // #asWord ignores leading zeros + rule #asWord ( BA1 +Bytes BA2 ) => #asWord ( BA2 ) + requires #asInteger(BA1) ==Int 0 + [simplification, concrete(BA1)] + + // `#asWord` of a byte array cannot equal a number that cannot fit within the byte array + rule #asWord ( BA ) ==Int Y => false + requires lengthBytes(BA) <=Int 32 + andBool (2 ^Int (8 *Int lengthBytes(BA))) <=Int Y + [concrete(Y), simplification] +``` + +## `#asInteger` + +Lemmas about [`#asInteger`](https://github.com/runtimeverification/evm-semantics/blob/master/kevm-pyk/src/kevm_pyk/kproj/evm-semantics/evm-types.md#bytes-helper-functions). `#asInteger(X)` interprets the byte array `X` as a single arbitrary-precision integer (with MSB first). + +```k + // Conversion from bytes always yields a non-negative integer + rule 0 <=Int #asInteger ( _ ) => true [simplification] +``` + +## `#padRightToWidth` + +Lemmas about [`#padRightToWidth`](https://github.com/runtimeverification/evm-semantics/blob/master/kevm-pyk/src/kevm_pyk/kproj/evm-semantics/evm-types.md#bytes-helper-functions). `#padRightToWidth(W, BA)` right-pads the byte array `BA` with zeros so that the resulting byte array has length `W`. + +```k + // Definitional expansion + rule #padRightToWidth (W, BA) => BA +Bytes #buf(W -Int lengthBytes(BA), 0) + [concrete(W), simplification] +``` + +## `#range(BA, START, WIDTH)` + +Lemmas about [`#range(BA, START, WIDTH)`](https://github.com/runtimeverification/evm-semantics/blob/master/kevm-pyk/src/kevm_pyk/kproj/evm-semantics/evm-types.md#bytes-helper-functions). `#range(BA, START, WIDTH)` returns the range of `BA` from index `START` of width `WIDTH`. + +```k + // Parameter equality + rule { #range (BA, S, W1) #Equals #range (BA, S, W2) } => #Top + requires W1 ==Int W2 + [simplification] +``` + +## Byte array indexing and update + +Lemmas about [`BA [ I ]` and `BA1 [ S := BA2 ]`](https://github.com/runtimeverification/evm-semantics/blob/master/kevm-pyk/src/kevm_pyk/kproj/evm-semantics/evm-types.md#element-access). `BA [ I ]` returns the integer representation of the `I`-th byte of byte array `BA`. `BA1 [ S := BA2 ]` updates the byte array `BA1` with byte array `BA2` from index `S`. + + +```k + // Byte indexing in terms of #asWord + rule BA [ X ] => #asWord ( #range (BA, X, 1) ) + requires X <=Int lengthBytes(BA) + [simplification(40)] + + // Empty update has no effect + rule BA [ START := b"" ] => BA + requires 0 <=Int START andBool START <=Int lengthBytes(BA) + [simplification] + + // Update passes to right operand of concat if start position is beyond the left operand + rule ( BA1 +Bytes BA2 ) [ S := BA ] => BA1 +Bytes ( BA2 [ S -Int lengthBytes(BA1) := BA ] ) + requires lengthBytes(BA1) <=Int S + [simplification] + + // Consecutive quasi-contiguous byte-array update + rule BA [ S1 := BA1 ] [ S2 := BA2 ] => BA [ S1 := #range(BA1, 0, S2 -Int S1) +Bytes BA2 ] + requires 0 <=Int S1 andBool S1 <=Int S2 andBool S2 <=Int S1 +Int lengthBytes(BA1) + [simplification] + + // Parameter equality: byte-array update + rule { BA1:Bytes [ S1 := BA2 ] #Equals BA3:Bytes [ S2 := BA4 ] } => #Top + requires BA1 ==K BA3 andBool S1 ==Int S2 andBool BA2 ==K BA4 + [simplification] +``` + +Summaries +--------- + +Functions summaries are rewrite rules that capture (summarize) the effects of executing a function. Such rules allow Kontrol to, instead of executing the function itself, just apply the summary rule. + +## `copy_memory_to_memory` summary + +The following rule summarises the behavior of the `copy_memory_to_memory` function. This function is automatically generated by the Solidity compiler. In its Yul form, it is as follows: + +```solidity +function copy_memory_to_memory(src, dst, length) { + let i := 0 + for { } lt(i, length) { i := add(i, 32) } + { + mstore(add(dst, i), mload(add(src, i))) + } + if gt(i, length) + { + // clear end + mstore(add(dst, length), 0) + } +} +``` + +It is used to copy `length` bytes of memory from index `src` to index `dest`, doing so in steps of 32 bytes, and right-padding with zeros to a multiple of 32. + +Following the compiler constraints, we enforce a limit on the length of byte arrays and indices into byte arrays. + +```k + syntax Int ::= "maxBytesLength" [alias] + rule maxBytesLength => 9223372036854775808 +``` + +The summary lemma is as follows, with commentary inlined: + +```k + rule [copy-memory-to-memory-summary]: + #execute ... + false + SHANGHAI + JUMPDESTS + // The program and program counter are symbolic, focusing on the part we will be executing (CP) + PROGRAM + PCOUNT => PCOUNT +Int 53 + // The word stack has the appropriate form, as per the compiled code + LENGTH : _ : SRC : DEST : WS + // The program copies LENGTH bytes of memory from SRC +Int 32 to DEST +Int OFFSET, + // padded with 32 zeros in case LENGTH is not divisible by 32 + + LM => LM [ DEST +Int 32 := #range ( LM, SRC +Int 32, LENGTH ) +Bytes + #buf ( ( ( notMaxUInt5 &Int ( LENGTH +Int maxUInt5 ) ) -Int LENGTH ) , 0 ) +Bytes + #buf ( ( ( ( 32 -Int ( ( notMaxUInt5 &Int ( LENGTH +Int maxUInt5 ) ) -Int LENGTH ) ) ) modInt 32 ), 0 ) ] + + requires + // The current program we are executing differs from the original one only in the hardcoded jump addresses, + // which are now relative to PCOUNT, and the hardcoded offset, which is now symbolic. + #range(PROGRAM, PCOUNT, 53) ==K b"`\x00[\x81\x81\x10\x15b\x00\x81`W` \x81\x85\x01\x81\x01Q\x86\x83\x01\x82\x01R\x01b\x00\x81BV[\x81\x81\x11\x15b\x00\x81sW`\x00` \x83\x87\x01\x01R[P" + [ 08 := #buf(3, PCOUNT +Int 32) ] + [ 28 := #buf(3, PCOUNT +Int 2) ] + [ 38 := #buf(3, PCOUNT +Int 51) ] + + // Various well-formedness constraints. In particular, the maxBytesLength-related ones are present to + // remove various chops that would otherwise creep into the execution, and are reasonable since byte + // arrays in actual programs would never reach that size. + andBool 0 <=Int PCOUNT + andBool 0 <=Int LENGTH andBool LENGTH = 32, "Small bytes"); - - uint256 bytesSlotValue; - unchecked { - bytesSlotValue = bytesLength * 2 + 1; - } - - // Deploy ghost contract - GhostBytes ghostBytes = new GhostBytes(); - - // Make the storage of the ghost contract symbolic - kevm.symbolicStorage(address(ghostBytes)); - - // Load the size encoding into the first slot of ghostBytes - vm.store(address(ghostBytes), bytes32(uint256(0)), bytes32(bytesSlotValue)); - - sBytes = ghostBytes.ghostBytes(); - } - - /// @dev Creates a bounded symbolic bytes[] memory representing a withdrawal proof - /// Each element is 17 * 32 = 544 bytes long, plus ~10% margin for RLP encoding: each element is 600 bytes - /// The length of the array to 10 or fewer elements - function freshWithdrawalProof() public returns (bytes[] memory withdrawalProof) { - // Assume arrayLength = 2 for faster proof speeds - // TODO: have the array length range between 0 and 10 elements - uint256 arrayLength = 6; - - withdrawalProof = new bytes[](arrayLength); - - // Deploy ghost contract - // GhostBytes10 ghostBytes10 = new GhostBytes10(); - - // Make the storage of the ghost contract symbolic - // kevm.symbolicStorage(address(ghostBytes10)); - - // Each bytes element will have a length of 600 - // uint256 bytesSlotValue = 600 * 2 + 1; - - // Load the size encoding into the first slot of ghostBytes - // vm.store(address(ghostBytes10), bytes32(uint256(0)), bytes32(bytesSlotValue)); - // vm.store(address(ghostBytes10), bytes32(uint256(1)), bytes32(bytesSlotValue)); - // vm.store(address(ghostBytes10), bytes32(uint256(2)), bytes32(bytesSlotValue)); - // vm.store(address(ghostBytes10), bytes32(uint256(3)), bytes32(bytesSlotValue)); - // vm.store(address(ghostBytes10), bytes32(uint256(4)), bytes32(bytesSlotValue)); - // vm.store(address(ghostBytes10), bytes32(uint256(5)), bytes32(bytesSlotValue)); - // vm.store(address(ghostBytes10), bytes32(uint256(6)), bytes32(bytesSlotValue)); - // vm.store(address(ghostBytes10), bytes32(uint256(7)), bytes32(bytesSlotValue)); - // vm.store(address(ghostBytes10), bytes32(uint256(8)), bytes32(bytesSlotValue)); - // vm.store(address(ghostBytes10), bytes32(uint256(9)), bytes32(bytesSlotValue)); - - // withdrawalProof = ghostBytes10.getGhostBytesArray(); - - // Second approach - - // withdrawalProof[0] = ghostBytes10.ghostBytes0(); - // withdrawalProof[1] = ghostBytes10.ghostBytes1(); - // withdrawalProof[2] = ghostBytes10.ghostBytes2(); - // withdrawalProof[3] = ghostBytes10.ghostBytes3(); - // withdrawalProof[4] = ghostBytes10.ghostBytes4(); - // withdrawalProof[5] = ghostBytes10.ghostBytes5(); - // withdrawalProof[6] = ghostBytes10.ghostBytes6(); - // withdrawalProof[7] = ghostBytes10.ghostBytes7(); - // withdrawalProof[8] = ghostBytes10.ghostBytes8(); - // withdrawalProof[9] = ghostBytes10.ghostBytes9(); - - // First approach - - for (uint256 i = 0; i < withdrawalProof.length; ++i) { - withdrawalProof[i] = freshBigBytes(600); - } - } + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); } diff --git a/packages/contracts-bedrock/test/kontrol/scripts/common.sh b/packages/contracts-bedrock/test/kontrol/scripts/common.sh new file mode 100644 index 000000000000..7150c7125e16 --- /dev/null +++ b/packages/contracts-bedrock/test/kontrol/scripts/common.sh @@ -0,0 +1,199 @@ +#!/bin/bash +# Common functions and variables for run-kontrol.sh and make-summary-deployment.sh + +notif() { echo "== $0: $*" >&2 ; } + +# usage function for the run-kontrol.sh script +usage_run_kontrol() { + echo "Usage: $0 [-h|--help] [container|local|dev] [script|tests]" 1>&2 + echo "" 1>&2 + echo " -h, --help Display this help message." 1>&2 + echo "" 1>&2 + echo "Execution modes:" + echo " container Run in docker container. Reproduce CI execution. (Default)" 1>&2 + echo " local Run locally, enforces registered versions.json version for better reproducibility. (Recommended)" 1>&2 + echo " dev Run locally, does NOT enforce registered version. (Useful for developing with new versions and features)" 1>&2 + echo "" 1>&2 + echo "Tests executed:" + echo " script Execute the tests recorded in run-kontrol.sh" 1>&2 + echo " tests Execute the tests provided as arguments" 1>&2 + exit 0 +} + +# usage function for the make-summary-deployment.sh script +usage_make_summary() { + echo "Usage: $0 [-h|--help] [container|local|dev]" 1>&2 + echo "" 1>&2 + echo " -h, --help Display this help message." 1>&2 + echo "" 1>&2 + echo "Execution modes:" + echo " container Run in docker container. Reproduce CI execution. (Default)" 1>&2 + echo " local Run locally, enforces registered versions.json version for better reproducibility. (Recommended)" 1>&2 + echo " dev Run locally, does NOT enforce registered version. (Useful for developing with new versions and features)" 1>&2 + exit 0 +} + +# Set Run Directory /packages/contracts-bedrock +WORKSPACE_DIR=$( cd "$SCRIPT_HOME/../../.." >/dev/null 2>&1 && pwd ) + +# Variables +export CONTAINER_NAME=kontrol-tests +KONTROLRC=$(jq -r .kontrol < "$WORKSPACE_DIR/../../versions.json") +export KONTROL_RELEASE=$KONTROLRC +export LOCAL=false +export SCRIPT_TESTS=false +SCRIPT_OPTION=false +export CUSTOM_TESTS=0 # Store the position where custom tests start, interpreting 0 as no tests +CUSTOM_OPTION=0 +export RUN_KONTROL=false # true if any functions are called from run-kontrol.sh + +# General usage function, which discerns from which script is being called and displays the appropriate message +usage() { + if [ "$RUN_KONTROL" = "true" ]; then + usage_run_kontrol + else + usage_make_summary + fi +} + + +# Argument Parsing +# The logic behind argument parsing is the following (in order): +# - Execution mode argument: container (or empty), local, dev +# - Tests arguments (first if execution mode empty): script, specific test names +parse_args() { + if [ $# -eq 0 ]; then + export LOCAL=false + export SCRIPT_TESTS=false + export CUSTOM_TESTS=0 + # `script` argument caps the total possible arguments to its position + elif { [ $# -gt 1 ] && [ "$1" == "script" ]; } || { [ $# -gt 2 ] && [ "$2" == "script" ]; }; then + usage + elif [ $# -eq 1 ]; then + SCRIPT_OPTION=false + CUSTOM_OPTION=0 + parse_first_arg "$1" + elif [ $# -eq 2 ] && [ "$2" == "script" ]; then + if [ "$1" != "container" ] && [ "$1" != "local" ] && [ "$1" != "dev" ]; then + notif "Invalid first argument. Must be \`container\`, \`local\` or \`dev\`" + exit 1 + fi + SCRIPT_OPTION=true + CUSTOM_OPTION=0 + parse_first_arg "$1" + else + SCRIPT_OPTION=false + CUSTOM_OPTION=2 + parse_first_arg "$1" + fi +} + +# Parse the first argument passed to `run-kontrol.sh` +parse_first_arg() { + if [ "$1" == "container" ]; then + notif "Running in docker container (DEFAULT)" + export LOCAL=false + export SCRIPT_TESTS=$SCRIPT_OPTION + export CUSTOM_TESTS=$CUSTOM_OPTION + elif [ "$1" == "-h" ] || [ "$1" == "--help" ]; then + usage + elif [ "$1" == "local" ]; then + notif "Running with LOCAL install, .kontrolrc CI version ENFORCED" + export SCRIPT_TESTS=$SCRIPT_OPTION + export CUSTOM_TESTS=$CUSTOM_OPTION + check_kontrol_version + elif [ "$1" == "dev" ]; then + notif "Running with LOCAL install, IGNORING .kontrolrc version" + export LOCAL=true + export SCRIPT_TESTS=$SCRIPT_OPTION + export CUSTOM_TESTS=$CUSTOM_OPTION + pushd "$WORKSPACE_DIR" > /dev/null || exit + elif [ "$1" == "script" ]; then + notif "Running in docker container (DEFAULT)" + export LOCAL=false + NEGATED_SCRIPT_TESTS=$([[ "${SCRIPT_OPTION}" == "true" ]] && echo false || echo true) + export SCRIPT_TESTS=$NEGATED_SCRIPT_TESTS + export CUSTOM_TESTS=$CUSTOM_OPTION + else + notif "Running in docker container (DEFAULT)" + export LOCAL=false + export SCRIPT_TESTS=$SCRIPT_OPTION + export CUSTOM_TESTS=1 # Store the position where custom tests start + fi +} + +check_kontrol_version() { + if [ "$(kontrol version | awk -F': ' '{print$2}')" == "$KONTROLRC" ]; then + notif "Kontrol version matches $KONTROLRC" + export LOCAL=true + pushd "$WORKSPACE_DIR" > /dev/null || exit + else + notif "Kontrol version does NOT match $KONTROLRC" + notif "Please run 'kup install kontrol --version v$KONTROLRC'" + exit 1 + fi +} + +conditionally_start_docker() { + if [ "$LOCAL" == false ]; then + # Is old docker container running? + if [ "$(docker ps -q -f name="$CONTAINER_NAME")" ]; then + # Stop old docker container + notif "Stopping old docker container" + clean_docker + fi + start_docker + fi +} + +start_docker () { + docker run \ + --name "$CONTAINER_NAME" \ + --rm \ + --interactive \ + --detach \ + --env FOUNDRY_PROFILE="$FOUNDRY_PROFILE" \ + --workdir /home/user/workspace \ + runtimeverificationinc/kontrol:ubuntu-jammy-"$KONTROL_RELEASE" + + copy_to_docker +} + +copy_to_docker() { + # Copy test content to container. We need to avoid copying node_modules because + # it results in the below error, so we copy the workspace to a temp directory + # and then copy it to the container. + # Error response from daemon: invalid symlink "/home/user/workspace/node_modules/@typescript-eslint/eslint-plugin" -> "../../../../node_modules/.pnpm/@typescript-eslint+eslint-plugin@6.19.1_@typescript-eslint+parser@6.19.1_eslint@8.56.0_typescript@5.3.3/node_modules/@typescript-eslint/eslint-plugin" + # Even though we use a bind mount, we still need to copy the files to the + # container because we are running Docker on a remote host. + if [ "$LOCAL" == false ]; then + TMP_DIR=$(mktemp -d) + cp -r "$WORKSPACE_DIR/." "$TMP_DIR" + rm -rf "$TMP_DIR/node_modules" + docker cp --follow-link "$TMP_DIR/." $CONTAINER_NAME:/home/user/workspace + rm -rf "$TMP_DIR" + + docker exec --user root "$CONTAINER_NAME" chown -R user:user /home/user + fi +} + +clean_docker(){ + notif "Stopping Docker Container" + docker stop "$CONTAINER_NAME" +} + + +docker_exec () { + docker exec --user user --workdir /home/user/workspace $CONTAINER_NAME "${@}" +} + +run () { + if [ "$LOCAL" = true ]; then + notif "Running local" + # shellcheck disable=SC2086 + "${@}" + else + notif "Running in docker" + docker_exec "${@}" + fi +} diff --git a/packages/contracts-bedrock/test/kontrol/scripts/json/reverse_key_values.py b/packages/contracts-bedrock/test/kontrol/scripts/json/reverse_key_values.py index d75975004197..bc3816db9f7a 100644 --- a/packages/contracts-bedrock/test/kontrol/scripts/json/reverse_key_values.py +++ b/packages/contracts-bedrock/test/kontrol/scripts/json/reverse_key_values.py @@ -19,7 +19,7 @@ def reverse_json(input_file, output_file): with open(input_file, 'r') as file: json_data = json.load(file) - reversed_json = {str(value): key for key, value in json_data.items()} + reversed_json = {str(value): key[0].lower() + key[1:] for key, value in json_data.items()} with open(output_file, 'w') as file: json.dump(reversed_json, file, indent=2) diff --git a/packages/contracts-bedrock/test/kontrol/scripts/make-summary-deployment.sh b/packages/contracts-bedrock/test/kontrol/scripts/make-summary-deployment.sh index 8d854f528556..589f52c30764 100755 --- a/packages/contracts-bedrock/test/kontrol/scripts/make-summary-deployment.sh +++ b/packages/contracts-bedrock/test/kontrol/scripts/make-summary-deployment.sh @@ -1,6 +1,43 @@ #!/bin/bash set -euo pipefail +export FOUNDRY_PROFILE=kdeploy + +SCRIPT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +# shellcheck source=/dev/null +source "$SCRIPT_HOME/common.sh" +# Sanity check on arguments +if [ $# -gt 1 ]; then + echo "At most one argument can be provided. Instead $# were provided" 1>&2 + exit 1 +elif [ $# -eq 1 ]; then + if [ "$1" != "-h" ] && [ "$1" != "--help" ] && [ "$1" != "container" ] && [ "$1" != "local" ] && [ "$1" != "dev" ]; then + notif "Invalid argument. Must be \`container\`, \`local\`, \`dev\`, \`-h\` or \`--help\`" + exit 1 + else + parse_first_arg "$@" + fi +fi + +cleanup() { + # Restore the original script from the backup + if [ -f "$DEPLOY_SCRIPT.bak" ]; then + cp "$DEPLOY_SCRIPT.bak" "$DEPLOY_SCRIPT" + rm "$DEPLOY_SCRIPT.bak" + fi + + if [ -f "snapshots/state-diff/Deploy.json" ]; then + rm "snapshots/state-diff/Deploy.json" + fi + + if [ "$LOCAL" = false ]; then + clean_docker + fi +} + +# Set trap to call cleanup function on exit +trap cleanup EXIT + # create deployments/hardhat/.deploy and snapshots/state-diff/Deploy.json if necessary if [ ! -d "deployments/hardhat" ]; then mkdir deployments/hardhat; @@ -16,39 +53,39 @@ if [ ! -f "snapshots/state-diff/Deploy.json" ]; then fi DEPLOY_SCRIPT="./scripts/Deploy.s.sol" +conditionally_start_docker # Create a backup -cp ${DEPLOY_SCRIPT} ${DEPLOY_SCRIPT}.bak +cp $DEPLOY_SCRIPT $DEPLOY_SCRIPT.bak # Replace mustGetAddress by getAddress in Deploy.s.sol # This is needed because the Kontrol deployment is only a partial # version of the full Optimism deployment. Since not all the components # of the system are deployed, we'd get some reverts on the `mustGetAddress` functions -awk '{gsub(/mustGetAddress/, "getAddress")}1' ${DEPLOY_SCRIPT} > temp && mv temp ${DEPLOY_SCRIPT} +awk '{gsub(/mustGetAddress/, "getAddress")}1' $DEPLOY_SCRIPT > temp && mv temp $DEPLOY_SCRIPT -FOUNDRY_PROFILE=kdeploy forge script -vvv test/kontrol/KontrolDeployment.sol:KontrolDeployment --sig 'runKontrolDeployment()' +forge script -vvv test/kontrol/deployment/KontrolDeployment.sol:KontrolDeployment --sig 'runKontrolDeployment()' echo "Created state diff json" -# Restore the file from the backup -cp ${DEPLOY_SCRIPT}.bak ${DEPLOY_SCRIPT} -rm ${DEPLOY_SCRIPT}.bak - # Clean and store the state diff json in snapshots/state-diff/Kontrol-Deploy.json JSON_SCRIPTS=test/kontrol/scripts/json GENERATED_STATEDIFF=Deploy.json # Name of the statediff json produced by the deployment script -STATEDIFF=Kontrol-${GENERATED_STATEDIFF} # Name of the Kontrol statediff -mv snapshots/state-diff/${GENERATED_STATEDIFF} snapshots/state-diff/${STATEDIFF} -python3 ${JSON_SCRIPTS}/clean_json.py snapshots/state-diff/${STATEDIFF} +STATEDIFF=Kontrol-$GENERATED_STATEDIFF # Name of the Kontrol statediff +mv snapshots/state-diff/$GENERATED_STATEDIFF snapshots/state-diff/$STATEDIFF +python3 $JSON_SCRIPTS/clean_json.py snapshots/state-diff/$STATEDIFF +jq . snapshots/state-diff/$STATEDIFF > temp && mv temp snapshots/state-diff/$STATEDIFF # Prettify json echo "Cleaned state diff json" CONTRACT_NAMES=deployments/hardhat/.deploy -python3 ${JSON_SCRIPTS}/reverse_key_values.py ${CONTRACT_NAMES} ${CONTRACT_NAMES}Reversed +python3 $JSON_SCRIPTS/reverse_key_values.py $CONTRACT_NAMES ${CONTRACT_NAMES}Reversed CONTRACT_NAMES=${CONTRACT_NAMES}Reversed SUMMARY_DIR=test/kontrol/proofs/utils SUMMARY_NAME=DeploymentSummary LICENSE=MIT -kontrol summary ${SUMMARY_NAME} snapshots/state-diff/${STATEDIFF} --contract-names ${CONTRACT_NAMES} --output-dir ${SUMMARY_DIR} --license ${LICENSE} -forge fmt ${SUMMARY_DIR}/${SUMMARY_NAME}.sol -forge fmt ${SUMMARY_DIR}/${SUMMARY_NAME}Code.sol -echo "Added state updates to ${SUMMARY_DIR}/${SUMMARY_NAME}.sol" + +copy_to_docker # Copy the newly generated files to the docker container +run kontrol load-state-diff $SUMMARY_NAME snapshots/state-diff/$STATEDIFF --contract-names $CONTRACT_NAMES --output-dir $SUMMARY_DIR --license $LICENSE +forge fmt $SUMMARY_DIR/$SUMMARY_NAME.sol +forge fmt $SUMMARY_DIR/${SUMMARY_NAME}Code.sol +echo "Added state updates to $SUMMARY_DIR/$SUMMARY_NAME.sol" diff --git a/packages/contracts-bedrock/test/kontrol/scripts/run-kontrol.sh b/packages/contracts-bedrock/test/kontrol/scripts/run-kontrol.sh index da155ad43832..5b37edf796f5 100755 --- a/packages/contracts-bedrock/test/kontrol/scripts/run-kontrol.sh +++ b/packages/contracts-bedrock/test/kontrol/scripts/run-kontrol.sh @@ -1,186 +1,89 @@ #!/bin/bash set -euo pipefail -##################### -# Support Functions # -##################### -blank_line() { echo '' >&2 ; } -notif() { echo "== $0: $*" >&2 ; } -usage() { - echo "Usage: $0 [-h|--help] [container|local|dev]" 1>&2 - echo "Options:" 1>&2 - echo " -h, --help Display this help message." 1>&2 - echo " container Run tests in docker container. Reproduce CI execution. (Default)" 1>&2 - echo " local Run locally, enforces CI Registered .kontrolrc Kontrol version for better reproducibility. (Recommended)" 1>&2 - echo " dev Run locally, do NOT enforce CI registered Kontrol version (Recomended w/ greater kup & kontrol experience)" 1>&2 - exit 0 -} - -############# -# Variables # -############# -# Set Script Directory Variables /packages/contracts-bedrock/test/kontrol -SCRIPT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" -notif "Script Home: $SCRIPT_HOME" -blank_line - -# Set Run Directory /packages/contracts-bedrock -WORKSPACE_DIR=$( cd "${SCRIPT_HOME}/../../.." >/dev/null 2>&1 && pwd ) -notif "Run Directory: ${WORKSPACE_DIR}" -blank_line - export FOUNDRY_PROFILE=kprove -export CONTAINER_NAME=kontrol-tests -KONTROLRC=$(jq -r .kontrol < "${WORKSPACE_DIR}/../../versions.json") -export KONTROL_RELEASE=${KONTROLRC} -export LOCAL=false -####################### -# Check for arguments # -####################### -if [ $# -gt 1 ]; then - usage -else - if [ $# -eq 0 ] || [ "$1" == "container" ]; then - notif "Running in docker container (DEFAULT)" - blank_line - export LOCAL=false - [ $# -gt 1 ] && shift - elif [ "$1" == "-h" ] || [ "$1" == "--help" ]; then - usage - elif [ "$1" == "local" ]; then - notif "Running with LOCAL install, .kontrolrc CI version ENFORCED" - if [ "$(kontrol version | awk -F': ' '{print$2}')" == "${KONTROLRC}" ]; then - notif "Kontrol version matches ${KONTROLRC}" - blank_line - export LOCAL=true - shift - pushd "${WORKSPACE_DIR}" > /dev/null - else - notif "Kontrol version does NOT match ${KONTROLRC}" - notif "Please run 'kup install kontrol --version ${KONTROLRC}'" - blank_line - exit 1 - fi - elif [ "$1" == "dev" ]; then - notif "Running with LOCAL install, IGNORING .kontrolrc version" - blank_line - export LOCAL=true - shift - pushd "${WORKSPACE_DIR}" > /dev/null - else - # Unexpected argument passed - usage - fi -fi +SCRIPT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +# shellcheck source=/dev/null +source "$SCRIPT_HOME/common.sh" +export RUN_KONTROL=true +parse_args "$@" ############# # Functions # ############# kontrol_build() { - notif "Kontrol Build" - # shellcheck disable=SC2086 - run kontrol build \ - --verbose \ - --require ${lemmas} \ - --module-import ${module} \ - ${rekompile} - } - -kontrol_prove() { - notif "Kontrol Prove" - # shellcheck disable=SC2086 - run kontrol prove \ - --max-depth ${max_depth} \ - --max-iterations ${max_iterations} \ - --smt-timeout ${smt_timeout} \ - --bmc-depth ${bmc_depth} \ - --workers ${workers} \ - ${reinit} \ - ${bug_report} \ - ${break_on_calls} \ - ${auto_abstract} \ - ${tests} \ - ${use_booster} -} - -start_docker () { - docker run \ - --name "${CONTAINER_NAME}" \ - --rm \ - --interactive \ - --detach \ - --env FOUNDRY_PROFILE="${FOUNDRY_PROFILE}" \ - --workdir /home/user/workspace \ - runtimeverificationinc/kontrol:ubuntu-jammy-"${KONTROL_RELEASE}" - - # Copy test content to container - docker cp --follow-link "${WORKSPACE_DIR}/." ${CONTAINER_NAME}:/home/user/workspace - docker exec --user root ${CONTAINER_NAME} chown -R user:user /home/user -} - -docker_exec () { - docker exec --user user --workdir /home/user/workspace ${CONTAINER_NAME} "${@}" + notif "Kontrol Build" + # shellcheck disable=SC2086 + run kontrol build \ + --verbose \ + --require $lemmas \ + --module-import $module \ + $rekompile } -run () { - if [ "${LOCAL}" = true ]; then - notif "Running local" - # shellcheck disable=SC2086 - "${@}" - else - notif "Running in docker" - docker_exec "${@}" - fi +kontrol_prove() { + notif "Kontrol Prove" + # shellcheck disable=SC2086 + run kontrol prove \ + --max-depth $max_depth \ + --max-iterations $max_iterations \ + --smt-timeout $smt_timeout \ + --workers $workers \ + $reinit \ + $bug_report \ + $break_on_calls \ + $break_every_step \ + $auto_abstract \ + $tests \ + $use_booster \ + --init-node-from $state_diff \ + --xml-test-report } dump_log_results(){ - trap clean_docker ERR - RESULTS_LOG="results-$(date +'%Y-%m-%d-%H-%M-%S').tar.gz" + trap clean_docker ERR + RESULTS_FILE="results-$(date +'%Y-%m-%d-%H-%M-%S').tar.gz" + LOG_PATH="test/kontrol/logs" + RESULTS_LOG="$LOG_PATH/$RESULTS_FILE" + + if [ ! -d $LOG_PATH ]; then + mkdir $LOG_PATH + fi - notif "Generating Results Log: ${RESULTS_LOG}" - blank_line + notif "Generating Results Log: $LOG_PATH" run tar -czvf results.tar.gz kout-proofs/ > /dev/null 2>&1 - if [ "${LOCAL}" = true ]; then - cp results.tar.gz "${RESULTS_LOG}" + if [ "$LOCAL" = true ]; then + mv results.tar.gz "$RESULTS_LOG" else - docker cp ${CONTAINER_NAME}:/home/user/workspace/results.tar.gz "${RESULTS_LOG}" + docker cp "$CONTAINER_NAME:/home/user/workspace/results.tar.gz" "$RESULTS_LOG" fi - if [ -f "${RESULTS_LOG}" ]; then - cp "${RESULTS_LOG}" kontrol-results_latest.tar.gz + if [ -f "$RESULTS_LOG" ]; then + cp "$RESULTS_LOG" "$LOG_PATH/kontrol-results_latest.tar.gz" else - notif "Results Log: ${RESULTS_LOG} not found, skipping.." - blank_line + notif "Results Log: $RESULTS_LOG not found, skipping.." fi # Report where the file was generated and placed - notif "Results Log: $(dirname "${RESULTS_LOG}") generated" + notif "Results Log: $(dirname "$RESULTS_LOG") generated" - if [ "${LOCAL}" = false ]; then - notif "Results Log: ${RESULTS_LOG} generated" - blank_line + if [ "$LOCAL" = false ]; then + notif "Results Log: $RESULTS_LOG generated" RUN_LOG="run-kontrol-$(date +'%Y-%m-%d-%H-%M-%S').log" - docker logs ${CONTAINER_NAME} > "${RUN_LOG}" + docker logs "$CONTAINER_NAME" > "$LOG_PATH/$RUN_LOG" fi } -clean_docker(){ - notif "Stopping Docker Container" - docker stop ${CONTAINER_NAME} - blank_line -} - # Define the function to run on failure on_failure() { - dump_log_results + dump_log_results - if [ "${LOCAL}" = false ]; then - clean_docker - fi + if [ "$LOCAL" = false ]; then + clean_docker + fi - notif "Cleanup complete." - blank_line - exit 1 + notif "Cleanup complete." + exit 1 } # Set up the trap to run the function on failure @@ -193,66 +96,91 @@ trap on_failure ERR INT # such as `rekompile`. Such a pattern is intended for easy use while locally # developing and executing the proofs via this script. Comment/uncomment the # empty assignment to activate/deactivate the corresponding flag -lemmas=test/kontrol/pausability-lemmas.k +lemmas=test/kontrol/pausability-lemmas.md base_module=PAUSABILITY-LEMMAS -module=OptimismPortalKontrol:${base_module} +module=OptimismPortalKontrol:$base_module rekompile=--rekompile rekompile= regen=--regen # shellcheck disable=SC2034 regen= +################################# +# Tests to symbolically execute # +################################# + +# Temporarily unexecuted tests +# "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused0" \ +# "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused1" \ +# "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused2" \ +# "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused3" \ +# "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused4" \ +# "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused5" \ +# "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused6" \ +# "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused7" \ +# "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused8" \ +# "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused9" \ +# "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused10" \ + +test_list=() +if [ "$SCRIPT_TESTS" == true ]; then + test_list=( "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused0" \ + "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused1" \ + "OptimismPortalKontrol.prove_finalizeWithdrawalTransaction_paused" \ + "L1StandardBridgeKontrol.prove_finalizeBridgeERC20_paused" \ + "L1StandardBridgeKontrol.prove_finalizeBridgeETH_paused" \ + "L1ERC721BridgeKontrol.prove_finalizeBridgeERC721_paused" \ + "L1CrossDomainMessengerKontrol.prove_relayMessage_paused" + ) +elif [ "$CUSTOM_TESTS" != 0 ]; then + test_list=( "${@:${CUSTOM_TESTS}}" ) +fi +tests="" +for test_name in "${test_list[@]}"; do + tests+="--match-test $test_name " +done + ######################### # kontrol prove options # ######################### -max_depth=1000000 -max_iterations=1000000 +max_depth=10000 +max_iterations=10000 smt_timeout=100000 -bmc_depth=10 -workers=1 +max_workers=7 # Set to 7 since the CI machine has 8 CPUs +# workers is the minimum between max_workers and the length of test_list +# unless no test arguments are provided, in which case we default to max_workers +if [ "$CUSTOM_TESTS" == 0 ] && [ "$SCRIPT_TESTS" == false ]; then + workers=${max_workers} +else + workers=$((${#test_list[@]}>max_workers ? max_workers : ${#test_list[@]})) +fi reinit=--reinit reinit= break_on_calls=--no-break-on-calls # break_on_calls= +break_every_step=--break-every-step +break_every_step= auto_abstract=--auto-abstract-gas -# auto_abstract= +auto_abstract= bug_report=--bug-report bug_report= use_booster=--use-booster # use_booster= - -######################################### -# List of tests to symbolically execute # -######################################### -tests="" -tests+="--match-test CounterTest.test_SetNumber " -#tests+="--match-test OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused " -#tests+="--match-test OptimismPortalKontrol.prove_finalizeWithdrawalTransaction_paused " +state_diff="./snapshots/state-diff/Kontrol-Deploy.json" ############# # RUN TESTS # ############# -if [ "${LOCAL}" == false ]; then - # Is old docker container running? - if [ "$(docker ps -q -f name=${CONTAINER_NAME})" ]; then - # Stop old docker container - notif "Stopping old docker container" - clean_docker - blank_line - fi - start_docker -fi +conditionally_start_docker kontrol_build kontrol_prove dump_log_results -if [ "${LOCAL}" == false ]; then +if [ "$LOCAL" == false ]; then notif "Stopping docker container" clean_docker fi -blank_line notif "DONE" -blank_line diff --git a/packages/contracts-bedrock/test/legacy/LegacyERC20ETH.t.sol b/packages/contracts-bedrock/test/legacy/LegacyERC20ETH.t.sol deleted file mode 100644 index 62e2928f06b9..000000000000 --- a/packages/contracts-bedrock/test/legacy/LegacyERC20ETH.t.sol +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -// Testing utilities -import { CommonTest } from "test/setup/CommonTest.sol"; - -// Target contract dependencies -import { Predeploys } from "src/libraries/Predeploys.sol"; - -// Target contract -import { LegacyERC20ETH } from "src/legacy/LegacyERC20ETH.sol"; - -contract LegacyERC20ETH_Test is CommonTest { - LegacyERC20ETH eth; - - /// @dev Sets up the test suite. - function setUp() public virtual override { - super.setUp(); - eth = new LegacyERC20ETH(); - } - - /// @dev Tests that the default metadata was set correctly. - function test_metadata_succeeds() external { - assertEq(eth.name(), "Ether"); - assertEq(eth.symbol(), "ETH"); - assertEq(eth.decimals(), 18); - } - - /// @dev Tests that `l2Bridge` and `l1Token` return the correct values. - function test_crossDomain_succeeds() external { - assertEq(eth.l2Bridge(), Predeploys.L2_STANDARD_BRIDGE); - assertEq(eth.l1Token(), address(0)); - } - - /// @dev Tests that `transfer` reverts since it does not exist. - function test_transfer_doesNotExist_reverts() external { - vm.expectRevert("LegacyERC20ETH: transfer is disabled"); - eth.transfer(alice, 100); - } - - /// @dev Tests that `approve` reverts since it does not exist. - function test_approve_doesNotExist_reverts() external { - vm.expectRevert("LegacyERC20ETH: approve is disabled"); - eth.approve(alice, 100); - } - - /// @dev Tests that `transferFrom` reverts since it does not exist. - function test_transferFrom_doesNotExist_reverts() external { - vm.expectRevert("LegacyERC20ETH: transferFrom is disabled"); - eth.transferFrom(bob, alice, 100); - } - - /// @dev Tests that `increaseAllowance` reverts since it does not exist. - function test_increaseAllowance_doesNotExist_reverts() external { - vm.expectRevert("LegacyERC20ETH: increaseAllowance is disabled"); - eth.increaseAllowance(alice, 100); - } - - /// @dev Tests that `decreaseAllowance` reverts since it does not exist. - function test_decreaseAllowance_doesNotExist_reverts() external { - vm.expectRevert("LegacyERC20ETH: decreaseAllowance is disabled"); - eth.decreaseAllowance(alice, 100); - } - - /// @dev Tests that `mint` reverts since it does not exist. - function test_mint_doesNotExist_reverts() external { - vm.expectRevert("LegacyERC20ETH: mint is disabled"); - eth.mint(alice, 100); - } - - /// @dev Tests that `burn` reverts since it does not exist. - function test_burn_doesNotExist_reverts() external { - vm.expectRevert("LegacyERC20ETH: burn is disabled"); - eth.burn(alice, 100); - } -} diff --git a/packages/contracts-bedrock/test/mocks/AlphabetVM.sol b/packages/contracts-bedrock/test/mocks/AlphabetVM.sol index a581a9c75d8d..e7488f5384ec 100644 --- a/packages/contracts-bedrock/test/mocks/AlphabetVM.sol +++ b/packages/contracts-bedrock/test/mocks/AlphabetVM.sol @@ -12,9 +12,9 @@ contract AlphabetVM is IBigStepper { Claim internal immutable ABSOLUTE_PRESTATE; IPreimageOracle public oracle; - constructor(Claim _absolutePrestate) { + constructor(Claim _absolutePrestate, PreimageOracle _oracle) { ABSOLUTE_PRESTATE = _absolutePrestate; - oracle = new PreimageOracle(0, 0); + oracle = _oracle; } /// @inheritdoc IBigStepper @@ -32,9 +32,9 @@ contract AlphabetVM is IBigStepper { if ((keccak256(_stateData) << 8) == (Claim.unwrap(ABSOLUTE_PRESTATE) << 8)) { // If the state data is empty, then the absolute prestate is the claim. (bytes32 dat,) = oracle.readPreimage( - PreimageKeyLib.localizeIdent(LocalPreimageKey.STARTING_L2_BLOCK_NUMBER, _localContext), 0 + PreimageKeyLib.localizeIdent(LocalPreimageKey.DISPUTED_L2_BLOCK_NUMBER, _localContext), 0 ); - uint256 startingL2BlockNumber = (uint256(dat) >> 128) & 0xFFFFFFFF; + uint256 startingL2BlockNumber = ((uint256(dat) >> 128) & 0xFFFFFFFF) - 1; traceIndex = startingL2BlockNumber << 4; (uint256 absolutePrestateClaim) = abi.decode(_stateData, (uint256)); claim = absolutePrestateClaim + traceIndex; diff --git a/packages/contracts-bedrock/test/safe-tools/CompatibilityFallbackHandler_1_3_0.sol b/packages/contracts-bedrock/test/safe-tools/CompatibilityFallbackHandler_1_3_0.sol index a0efa0e68b26..caefc4cee1c0 100644 --- a/packages/contracts-bedrock/test/safe-tools/CompatibilityFallbackHandler_1_3_0.sol +++ b/packages/contracts-bedrock/test/safe-tools/CompatibilityFallbackHandler_1_3_0.sol @@ -162,7 +162,6 @@ contract CompatibilityFallbackHandler is DefaultCallbackHandler, ISignatureValid targetContract; calldataPayload; - // solhint-disable-next-line no-inline-assembly assembly { let internalCalldata := mload(0x40) // Store `simulateAndRevert.selector`. diff --git a/packages/contracts-bedrock/test/setup/CommonTest.sol b/packages/contracts-bedrock/test/setup/CommonTest.sol index e4d00b3c0390..3b35bb53ebb9 100644 --- a/packages/contracts-bedrock/test/setup/CommonTest.sol +++ b/packages/contracts-bedrock/test/setup/CommonTest.sol @@ -5,6 +5,7 @@ import { Test } from "forge-std/Test.sol"; import { Setup } from "test/setup/Setup.sol"; import { Events } from "test/setup/Events.sol"; import { FFIInterface } from "test/setup/FFIInterface.sol"; +import "scripts/DeployConfig.s.sol"; /// @title CommonTest /// @dev An extenstion to `Test` that sets up the optimism smart contracts. @@ -16,6 +17,8 @@ contract CommonTest is Test, Setup, Events { FFIInterface constant ffi = FFIInterface(address(uint160(uint256(keccak256(abi.encode("optimism.ffi")))))); + bool usePlasmaOverride; + function setUp() public virtual override { alice = makeAddr("alice"); bob = makeAddr("bob"); @@ -23,6 +26,12 @@ contract CommonTest is Test, Setup, Events { vm.deal(bob, 10000 ether); Setup.setUp(); + + // Override the plasma config after the deploy script initialized the config + if (usePlasmaOverride) { + deploy.cfg().setUsePlasma(true); + } + vm.etch(address(ffi), vm.getDeployedCode("FFIInterface.sol:FFIInterface")); vm.label(address(ffi), "FFIInterface"); @@ -86,4 +95,30 @@ contract CommonTest is Test, Setup, Events { vm.prank(proposer); l2OutputOracle.proposeL2Output(proposedOutput2, nextBlockNumber, 0, 0); } + + function enableFaultProofs() public { + // Check if the system has already been deployed, based off of the heuristic that alice and bob have not been + // set by the `setUp` function yet. + if (!(alice == address(0) && bob == address(0))) { + revert("CommonTest: Cannot enable fault proofs after deployment. Consider overriding `setUp`."); + } + + // Set `useFaultProofs` to `true` in the deploy config so that the deploy script deploys the Fault Proof system. + // This directly overrides the deploy config's `useFaultProofs` value, if the test requires it. + vm.store( + address(uint160(uint256(keccak256(abi.encode("optimism.deployconfig"))))), + USE_FAULT_PROOFS_SLOT, + bytes32(uint256(1)) + ); + } + + function enablePlasma() public { + // Check if the system has already been deployed, based off of the heuristic that alice and bob have not been + // set by the `setUp` function yet. + if (!(alice == address(0) && bob == address(0))) { + revert("CommonTest: Cannot enable plasma after deployment. Consider overriding `setUp`."); + } + + usePlasmaOverride = true; + } } diff --git a/packages/contracts-bedrock/test/setup/Setup.sol b/packages/contracts-bedrock/test/setup/Setup.sol index dc37ee1847de..0adf339aeea3 100644 --- a/packages/contracts-bedrock/test/setup/Setup.sol +++ b/packages/contracts-bedrock/test/setup/Setup.sol @@ -14,10 +14,13 @@ import { L1Block } from "src/L2/L1Block.sol"; import { LegacyMessagePasser } from "src/legacy/LegacyMessagePasser.sol"; import { GovernanceToken } from "src/governance/GovernanceToken.sol"; import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; -import { LegacyERC20ETH } from "src/legacy/LegacyERC20ETH.sol"; import { StandardBridge } from "src/universal/StandardBridge.sol"; import { FeeVault } from "src/universal/FeeVault.sol"; import { OptimismPortal } from "src/L1/OptimismPortal.sol"; +import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; +import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; +import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol"; +import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; import { DeployConfig } from "scripts/DeployConfig.s.sol"; import { Deploy } from "scripts/Deploy.s.sol"; @@ -31,6 +34,7 @@ import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { Executables } from "scripts/Executables.sol"; import { Vm } from "forge-std/Vm.sol"; import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { DataAvailabilityChallenge } from "src/L1/DataAvailabilityChallenge.sol"; /// @title Setup /// @dev This contact is responsible for setting up the contracts in state. It currently @@ -46,6 +50,9 @@ contract Setup { Deploy internal constant deploy = Deploy(address(uint160(uint256(keccak256(abi.encode("optimism.deploy")))))); OptimismPortal optimismPortal; + OptimismPortal2 optimismPortal2; + DisputeGameFactory disputeGameFactory; + DelayedWETH delayedWeth; L2OutputOracle l2OutputOracle; SystemConfig systemConfig; L1StandardBridge l1StandardBridge; @@ -55,6 +62,8 @@ contract Setup { OptimismMintableERC20Factory l1OptimismMintableERC20Factory; ProtocolVersions protocolVersions; SuperchainConfig superchainConfig; + DataAvailabilityChallenge dataAvailabilityChallenge; + AnchorStateRegistry anchorStateRegistry; L2CrossDomainMessenger l2CrossDomainMessenger = L2CrossDomainMessenger(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER)); @@ -70,7 +79,6 @@ contract Setup { L1Block l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES); LegacyMessagePasser legacyMessagePasser = LegacyMessagePasser(Predeploys.LEGACY_MESSAGE_PASSER); GovernanceToken governanceToken = GovernanceToken(Predeploys.GOVERNANCE_TOKEN); - LegacyERC20ETH legacyERC20ETH = LegacyERC20ETH(Predeploys.LEGACY_ERC20_ETH); /// @dev Deploys the Deploy contract without including its bytecode in the bytecode /// of this contract by fetching the bytecode dynamically using `vm.getCode()`. @@ -95,6 +103,9 @@ contract Setup { deploy.run(); optimismPortal = OptimismPortal(deploy.mustGetAddress("OptimismPortalProxy")); + optimismPortal2 = OptimismPortal2(deploy.mustGetAddress("OptimismPortalProxy")); + disputeGameFactory = DisputeGameFactory(deploy.mustGetAddress("DisputeGameFactoryProxy")); + delayedWeth = DelayedWETH(deploy.mustGetAddress("DelayedWETHProxy")); l2OutputOracle = L2OutputOracle(deploy.mustGetAddress("L2OutputOracleProxy")); systemConfig = SystemConfig(deploy.mustGetAddress("SystemConfigProxy")); l1StandardBridge = L1StandardBridge(deploy.mustGetAddress("L1StandardBridgeProxy")); @@ -105,11 +116,16 @@ contract Setup { OptimismMintableERC20Factory(deploy.mustGetAddress("OptimismMintableERC20FactoryProxy")); protocolVersions = ProtocolVersions(deploy.mustGetAddress("ProtocolVersionsProxy")); superchainConfig = SuperchainConfig(deploy.mustGetAddress("SuperchainConfigProxy")); + anchorStateRegistry = AnchorStateRegistry(deploy.mustGetAddress("AnchorStateRegistryProxy")); vm.label(address(l2OutputOracle), "L2OutputOracle"); vm.label(deploy.mustGetAddress("L2OutputOracleProxy"), "L2OutputOracleProxy"); vm.label(address(optimismPortal), "OptimismPortal"); vm.label(deploy.mustGetAddress("OptimismPortalProxy"), "OptimismPortalProxy"); + vm.label(address(disputeGameFactory), "DisputeGameFactory"); + vm.label(deploy.mustGetAddress("DisputeGameFactoryProxy"), "DisputeGameFactoryProxy"); + vm.label(address(delayedWeth), "DelayedWETH"); + vm.label(deploy.mustGetAddress("DelayedWETHProxy"), "DelayedWETHProxy"); vm.label(address(systemConfig), "SystemConfig"); vm.label(deploy.mustGetAddress("SystemConfigProxy"), "SystemConfigProxy"); vm.label(address(l1StandardBridge), "L1StandardBridge"); @@ -126,6 +142,13 @@ contract Setup { vm.label(address(superchainConfig), "SuperchainConfig"); vm.label(deploy.mustGetAddress("SuperchainConfigProxy"), "SuperchainConfigProxy"); vm.label(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)), "L1CrossDomainMessenger_aliased"); + + if (deploy.cfg().usePlasma()) { + dataAvailabilityChallenge = + DataAvailabilityChallenge(deploy.mustGetAddress("DataAvailabilityChallengeProxy")); + vm.label(address(dataAvailabilityChallenge), "DataAvailabilityChallengeProxy"); + vm.label(deploy.mustGetAddress("DataAvailabilityChallenge"), "DataAvailabilityChallenge"); + } } /// @dev Sets up the L2 contracts. Depends on `L1()` being called first. @@ -152,7 +175,6 @@ contract Setup { governanceToken.transferOwnership(finalSystemOwner); vm.label(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, "OptimismMintableERC20Factory"); - vm.label(Predeploys.LEGACY_ERC20_ETH, "LegacyERC20ETH"); vm.label(Predeploys.L2_STANDARD_BRIDGE, "L2StandardBridge"); vm.label(Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L2CrossDomainMessenger"); vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, "L2ToL1MessagePasser"); diff --git a/packages/contracts-bedrock/test/universal/OptimismMintableERC20Factory.t.sol b/packages/contracts-bedrock/test/universal/OptimismMintableERC20Factory.t.sol index 10141bb43f45..08ee0343e53f 100644 --- a/packages/contracts-bedrock/test/universal/OptimismMintableERC20Factory.t.sol +++ b/packages/contracts-bedrock/test/universal/OptimismMintableERC20Factory.t.sol @@ -90,7 +90,7 @@ contract OptimismMintableTokenFactory_Test is Bridge_Initializer { vm.prank(alice); l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP"); - vm.expectRevert(); + vm.expectRevert(bytes("")); vm.prank(alice); l2OptimismMintableERC20Factory.createStandardL2Token(remote, "Beep", "BOOP"); diff --git a/packages/contracts-bedrock/test/universal/OptimismMintableERC721Factory.t.sol b/packages/contracts-bedrock/test/universal/OptimismMintableERC721Factory.t.sol index d337b58a5b14..04a084f392d1 100644 --- a/packages/contracts-bedrock/test/universal/OptimismMintableERC721Factory.t.sol +++ b/packages/contracts-bedrock/test/universal/OptimismMintableERC721Factory.t.sol @@ -59,7 +59,7 @@ contract OptimismMintableERC721Factory_Test is Bridge_Initializer { vm.prank(alice); factory.createOptimismMintableERC721(remote, "L2Token", "L2T"); - vm.expectRevert(); + vm.expectRevert(bytes("")); vm.prank(alice); factory.createOptimismMintableERC721(remote, "L2Token", "L2T"); diff --git a/packages/contracts-bedrock/test/universal/Proxy.t.sol b/packages/contracts-bedrock/test/universal/Proxy.t.sol index fa794dd295b2..66c3f1d24268 100644 --- a/packages/contracts-bedrock/test/universal/Proxy.t.sol +++ b/packages/contracts-bedrock/test/universal/Proxy.t.sol @@ -76,7 +76,7 @@ contract Proxy_Test is Test { // The implementation does not have a `upgradeTo` // method, calling `upgradeTo` not as the owner // should revert. - vm.expectRevert(); + vm.expectRevert(bytes("")); proxy.upgradeTo(address(64)); // Call `upgradeTo` as the owner, it should succeed @@ -95,7 +95,7 @@ contract Proxy_Test is Test { function test_ownerProxyCall_notAdmin_succeeds() external { // Calling `changeAdmin` not as the owner should revert // as the implementation does not have a `changeAdmin` method. - vm.expectRevert(); + vm.expectRevert(bytes("")); proxy.changeAdmin(address(1)); // Call `changeAdmin` as the owner, it should succeed @@ -108,7 +108,7 @@ contract Proxy_Test is Test { // Calling `admin` not as the owner should // revert as the implementation does not have // a `admin` method. - vm.expectRevert(); + vm.expectRevert(bytes("")); proxy.admin(); // Calling `admin` as the owner should work. @@ -186,7 +186,7 @@ contract Proxy_Test is Test { // The attempt to `upgradeToAndCall` // should revert when it is not called by the owner. - vm.expectRevert(); + vm.expectRevert(bytes("")); proxy.upgradeToAndCall(address(simpleStorage), abi.encodeWithSelector(simpleStorage.set.selector, 1, 1)); } diff --git a/packages/contracts-bedrock/test/universal/StandardBridge.t.sol b/packages/contracts-bedrock/test/universal/StandardBridge.t.sol index c42ba41691d2..c64e816dc0e7 100644 --- a/packages/contracts-bedrock/test/universal/StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/universal/StandardBridge.t.sol @@ -106,7 +106,7 @@ contract StandardBridge_Stateless_Test is CommonTest { assertFalse(bridge.isCorrectTokenPair(address(legacy), address(0x20))); // A token that doesn't support either modern or legacy interface // will revert - vm.expectRevert(); + vm.expectRevert(bytes("")); bridge.isCorrectTokenPair(address(erc20), address(1)); } diff --git a/packages/contracts-bedrock/test/vendor/Initializable.t.sol b/packages/contracts-bedrock/test/vendor/Initializable.t.sol index 01371b3aee3c..ad72791e95d1 100644 --- a/packages/contracts-bedrock/test/vendor/Initializable.t.sol +++ b/packages/contracts-bedrock/test/vendor/Initializable.t.sol @@ -6,8 +6,10 @@ import { Executables } from "scripts/Executables.sol"; import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; +import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; import { ResourceMetering } from "src/L1/ResourceMetering.sol"; import { OptimismPortal } from "src/L1/OptimismPortal.sol"; +import { ForgeArtifacts } from "scripts/ForgeArtifacts.sol"; import "src/L1/ProtocolVersions.sol"; import "scripts/Deployer.sol"; @@ -30,6 +32,7 @@ contract Initializer_Test is Bridge_Initializer { InitializeableContract[] contracts; function setUp() public override { + super.enablePlasma(); // Run the `Bridge_Initializer`'s `setUp()` function. super.setUp(); @@ -68,6 +71,38 @@ contract Initializer_Test is Bridge_Initializer { initializedSlotVal: deploy.loadInitializedSlot("L1CrossDomainMessengerProxy") }) ); + // DisputeGameFactoryImpl + contracts.push( + InitializeableContract({ + target: deploy.mustGetAddress("DisputeGameFactory"), + initCalldata: abi.encodeCall(disputeGameFactory.initialize, (address(0))), + initializedSlotVal: deploy.loadInitializedSlot("DisputeGameFactory") + }) + ); + // DisputeGameFactoryProxy + contracts.push( + InitializeableContract({ + target: address(disputeGameFactory), + initCalldata: abi.encodeCall(disputeGameFactory.initialize, (address(0))), + initializedSlotVal: deploy.loadInitializedSlot("DisputeGameFactoryProxy") + }) + ); + // DelayedWETHImpl + contracts.push( + InitializeableContract({ + target: deploy.mustGetAddress("DelayedWETH"), + initCalldata: abi.encodeCall(delayedWeth.initialize, (address(0), SuperchainConfig(address(0)))), + initializedSlotVal: deploy.loadInitializedSlot("DelayedWETH") + }) + ); + // DelayedWETHProxy + contracts.push( + InitializeableContract({ + target: address(delayedWeth), + initCalldata: abi.encodeCall(delayedWeth.initialize, (address(0), SuperchainConfig(address(0)))), + initializedSlotVal: deploy.loadInitializedSlot("DelayedWETHProxy") + }) + ); // L2OutputOracleImpl contracts.push( InitializeableContract({ @@ -92,6 +127,16 @@ contract Initializer_Test is Bridge_Initializer { initializedSlotVal: deploy.loadInitializedSlot("OptimismPortal") }) ); + // OptimismPortal2Impl + contracts.push( + InitializeableContract({ + target: deploy.mustGetAddress("OptimismPortal2"), + initCalldata: abi.encodeCall( + optimismPortal2.initialize, (disputeGameFactory, systemConfig, superchainConfig) + ), + initializedSlotVal: deploy.loadInitializedSlot("OptimismPortal2") + }) + ); // OptimismPortalProxy contracts.push( InitializeableContract({ @@ -262,6 +307,22 @@ contract Initializer_Test is Bridge_Initializer { initializedSlotVal: deploy.loadInitializedSlot("OptimismMintableERC20FactoryProxy") }) ); + // DataAvailabilityChallengeImpl + contracts.push( + InitializeableContract({ + target: deploy.mustGetAddress("DataAvailabilityChallenge"), + initCalldata: abi.encodeCall(dataAvailabilityChallenge.initialize, (address(0), 0, 0, 0, 0)), + initializedSlotVal: deploy.loadInitializedSlot("DataAvailabilityChallenge") + }) + ); + // DataAvailabilityChallengeProxy + contracts.push( + InitializeableContract({ + target: address(dataAvailabilityChallenge), + initCalldata: abi.encodeCall(dataAvailabilityChallenge.initialize, (address(0), 0, 0, 0, 0)), + initializedSlotVal: deploy.loadInitializedSlot("DataAvailabilityChallengeProxy") + }) + ); } /// @notice Tests that: @@ -271,8 +332,9 @@ contract Initializer_Test is Bridge_Initializer { /// 3. The `initialize()` function of each contract cannot be called more than once. function test_cannotReinitialize_succeeds() public { // Ensure that all L1, L2 `Initializable` contracts are accounted for, in addition to - // OptimismMintableERC20FactoryImpl and OptimismMintableERC20FactoryProxy - assertEq(_getNumInitializable() + 2, contracts.length); + // OptimismMintableERC20FactoryImpl, OptimismMintableERC20FactoryProxy, OptimismPortal2, + // DisputeGameFactoryImpl, DisputeGameFactoryProxy, DelayedWETHImpl, DelayedWETHProxy. + assertEq(_getNumInitializable() + 5, contracts.length); // Attempt to re-initialize all contracts within the `contracts` array. for (uint256 i; i < contracts.length; i++) { @@ -313,7 +375,7 @@ contract Initializer_Test is Bridge_Initializer { for (uint256 i; i < l1ContractNames.length; i++) { string memory contractName = l1ContractNames[i]; - string memory contractAbi = deploy.getAbi(contractName); + string memory contractAbi = ForgeArtifacts.getAbi(contractName); // Query the contract's ABI for an `initialize()` function. command[2] = string.concat( @@ -350,7 +412,7 @@ contract Initializer_Test is Bridge_Initializer { for (uint256 i; i < l2ContractNames.length; i++) { string memory contractName = l2ContractNames[i]; - string memory contractAbi = deploy.getAbi(contractName); + string memory contractAbi = ForgeArtifacts.getAbi(contractName); // Query the contract's ABI for an `initialize()` function. command[2] = string.concat( diff --git a/packages/contracts-ts/package.json b/packages/contracts-ts/package.json index d662dc8e368e..11057df5c1d3 100644 --- a/packages/contracts-ts/package.json +++ b/packages/contracts-ts/package.json @@ -37,7 +37,6 @@ "scripts": { "build": "tsup", "clean": "rm -rf ./dist", - "preinstall": "npx only-allow pnpm", "generate": "wagmi generate && pnpm build && pnpm lint:fix", "generate:check": "pnpm generate && git diff --exit-code ./addresses.json && git diff --exit-code ./abis.json", "lint": "prettier --check .", @@ -48,26 +47,26 @@ }, "devDependencies": { "@eth-optimism/contracts-bedrock": "workspace:*", - "@testing-library/jest-dom": "^6.2.1", + "@testing-library/jest-dom": "^6.4.2", "@testing-library/react-hooks": "^8.0.1", "@types/glob": "^8.1.0", - "@vitest/coverage-istanbul": "^1.2.1", - "@wagmi/cli": "^2.0.4", - "@wagmi/core": "^2.3.1", - "abitype": "^0.10.3", + "@vitest/coverage-istanbul": "^1.2.2", + "@wagmi/cli": "^2.1.2", + "@wagmi/core": "^2.6.3", + "abitype": "^1.0.2", "glob": "^10.3.10", "isomorphic-fetch": "^3.0.0", "jest-dom": "link:@types/@testing-library/jest-dom", - "jsdom": "^23.2.0", + "jsdom": "^24.0.0", "tsup": "^8.0.1", "typescript": "^5.3.3", - "vite": "^5.0.12", - "vitest": "^1.0.1", - "wagmi": "^2.2.1" + "vite": "^5.1.5", + "wagmi": "^2.5.5", + "vitest": "^1.2.2" }, "peerDependencies": { - "@wagmi/core": "^2.3.1", - "wagmi": "^2.2.1" + "@wagmi/core": "^2.6.3", + "wagmi": "^2.5.5" }, "peerDependenciesMeta": { "wagmi": { @@ -78,11 +77,11 @@ } }, "dependencies": { - "@testing-library/react": "^14.1.2", + "@testing-library/react": "^14.2.1", "@types/change-case": "^2.3.1", "change-case": "4.1.2", "react": "^18.2.0", "react-dom": "^18.2.0", - "viem": "^2.0.3" + "viem": "^2.7.19" } } diff --git a/packages/core-utils/package.json b/packages/core-utils/package.json index 086e8335f93e..3b54061c0369 100644 --- a/packages/core-utils/package.json +++ b/packages/core-utils/package.json @@ -11,7 +11,6 @@ "all": "pnpm clean && pnpm build && pnpm test && pnpm lint:fix && pnpm lint", "build": "tsc -p tsconfig.json", "clean": "rimraf dist/ ./tsconfig.tsbuildinfo", - "preinstall": "npx only-allow pnpm", "lint": "pnpm lint:fix && pnpm lint:check", "lint:check": "eslint . --max-warnings=0", "lint:fix": "pnpm lint:check --fix", @@ -49,7 +48,7 @@ "node-fetch": "^2.6.7" }, "devDependencies": { - "@types/node": "^20.11.5", + "@types/node": "^20.11.17", "mocha": "^10.2.0" } } diff --git a/packages/fee-estimation/package.json b/packages/fee-estimation/package.json index 26424183d149..e39b1b8bdd77 100644 --- a/packages/fee-estimation/package.json +++ b/packages/fee-estimation/package.json @@ -35,18 +35,18 @@ }, "devDependencies": { "@eth-optimism/contracts-ts": "workspace:^", - "@testing-library/jest-dom": "^6.2.1", + "@testing-library/jest-dom": "^6.4.2", "@testing-library/react-hooks": "^8.0.1", - "@vitest/coverage-istanbul": "^1.2.1", - "abitype": "^0.10.3", + "@vitest/coverage-istanbul": "^1.2.2", + "abitype": "^1.0.2", "isomorphic-fetch": "^3.0.0", "jest-dom": "link:@types/@testing-library/jest-dom", - "jsdom": "^23.2.0", + "jsdom": "^24.0.0", "tsup": "^8.0.1", "typescript": "^5.3.3", - "viem": "^2.0.3", - "vite": "^5.0.12", - "vitest": "^1.0.1" + "viem": "^2.7.19", + "vite": "^5.1.5", + "vitest": "^1.2.2" }, "peerDependencies": { "viem": "^0.3.30" diff --git a/packages/fee-estimation/src/estimateFees.ts b/packages/fee-estimation/src/estimateFees.ts index 246c2abbb30d..4a7ba0f1f191 100644 --- a/packages/fee-estimation/src/estimateFees.ts +++ b/packages/fee-estimation/src/estimateFees.ts @@ -58,7 +58,7 @@ const knownChains = [ type ClientOptions = // for known chains like base don't require an rpcUrl | { - chainId: typeof knownChains[number] + chainId: (typeof knownChains)[number] rpcUrl?: string nativeCurrency?: chains.Chain['nativeCurrency'] } diff --git a/packages/sdk/CHANGELOG.md b/packages/sdk/CHANGELOG.md index c1d1d4290962..3064cc2591c0 100644 --- a/packages/sdk/CHANGELOG.md +++ b/packages/sdk/CHANGELOG.md @@ -1,5 +1,32 @@ # @eth-optimism/sdk +## 3.2.2 + +### Patch Changes + +- [#9805](https://github.com/ethereum-optimism/optimism/pull/9805) [`3ccd12fe5c8c4c5a6acbf370d474ffa8db816562`](https://github.com/ethereum-optimism/optimism/commit/3ccd12fe5c8c4c5a6acbf370d474ffa8db816562) Thanks [@alecananian](https://github.com/alecananian)! - Fixed an issue where Vercel builds were failing due to the `preinstall` command. + +## 3.2.1 + +### Patch Changes + +- [#9663](https://github.com/ethereum-optimism/optimism/pull/9663) [`a1329f21f33ecafe409990964d3af7bf05a8a756`](https://github.com/ethereum-optimism/optimism/commit/a1329f21f33ecafe409990964d3af7bf05a8a756) Thanks [@smartcontracts](https://github.com/smartcontracts)! - Fixes a bug in the SDK that would sometimes cause proof submission reverts. + +## 3.2.0 + +### Minor Changes + +- [#9325](https://github.com/ethereum-optimism/optimism/pull/9325) [`44a2d9cec5f3b309b723b3e4dd8d29b5b70f1cc8`](https://github.com/ethereum-optimism/optimism/commit/44a2d9cec5f3b309b723b3e4dd8d29b5b70f1cc8) Thanks [@smartcontracts](https://github.com/smartcontracts)! - Updates the SDK to support FPAC in a backwards compatible way. + +### Patch Changes + +- [#9367](https://github.com/ethereum-optimism/optimism/pull/9367) [`d99d425a4f73fba19ffcf180deb0ef48ff3b9a6a`](https://github.com/ethereum-optimism/optimism/commit/d99d425a4f73fba19ffcf180deb0ef48ff3b9a6a) Thanks [@smartcontracts](https://github.com/smartcontracts)! - Fixes a bug in the SDK for finalizing fpac withdrawals. + +- [#9244](https://github.com/ethereum-optimism/optimism/pull/9244) [`73a748575e7c3d67c293814a12bf41eee216163c`](https://github.com/ethereum-optimism/optimism/commit/73a748575e7c3d67c293814a12bf41eee216163c) Thanks [@roninjin10](https://github.com/roninjin10)! - Added maintence mode warning to sdk + +- Updated dependencies [[`79effc52e8b82d15b5eda43acf540ac6c5f8d5d7`](https://github.com/ethereum-optimism/optimism/commit/79effc52e8b82d15b5eda43acf540ac6c5f8d5d7)]: + - @eth-optimism/contracts-bedrock@0.17.1 + ## 3.1.8 ### Patch Changes diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 284aa86cd55d..46b37ec96f2d 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -5,6 +5,23 @@ The `@eth-optimism/sdk` package provides a set of tools for interacting with Optimism. +## Warning!!! + +`@eth-optimism/sdk` has been superseded by `op-viem`. For most developers we suggest you migrate to [viem](https://viem.sh/op-stack) which has native built in op-stack support built in. It also has additional benefits. + +**The OP Labs team has no plans to update @eth-optimism/sdk and it is in maintenance mode at the moment** + +- an intuitive API that learned from this package and is now revamped +- great treeshaking with a 10x+ improvement to bundlesize +- Better performance +- Updated to use the latest op stack contracts. At times it will save you gas compared to using viem. + +If viem does not have what you need please let us know by opening an issue in the viem repo or here. Letting us know helps us advocate to upstream more functionality to viem. Viem is missing the following functionality: + +- ERC20 support + +If viem doesn't have what you need, the extensions for viem, [op-viem extensions](https://github.com/base-org/op-viem), likely have it too. + ## Installation ``` @@ -15,6 +32,10 @@ npm install @eth-optimism/sdk You can find auto-generated API documentation over at [sdk.optimism.io](https://sdk.optimism.io). +## Contributing + +Most of the core functionality is in the [CrossChainMessenger](./src/cross-chain-messenger.ts) file. + ## Using the SDK ### CrossChainMessenger diff --git a/packages/sdk/package.json b/packages/sdk/package.json index b4054e533cda..f7711ff5f2d2 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@eth-optimism/sdk", - "version": "3.1.8", + "version": "3.2.2", "description": "[Optimism] Tools for working with Optimism", "main": "dist/index", "types": "dist/index", @@ -12,7 +12,6 @@ "all": "pnpm clean && pnpm build && pnpm test && pnpm lint:fix && pnpm lint", "build": "tsc -p tsconfig.json", "clean": "rimraf dist/ ./tsconfig.tsbuildinfo", - "preinstall": "npx only-allow pnpm", "lint": "pnpm lint:fix && pnpm lint:check", "lint:check": "eslint . --max-warnings=0", "lint:fix": "pnpm lint:check --fix", @@ -44,11 +43,12 @@ "@types/chai": "^4.3.11", "@types/chai-as-promised": "^7.1.8", "@types/mocha": "^10.0.6", - "@types/node": "^20.11.5", + "@types/node": "^20.11.17", + "@types/semver": "^7.5.7", "chai-as-promised": "^7.1.1", "ethereum-waffle": "^4.0.10", "ethers": "^5.7.2", - "hardhat": "^2.19.4", + "hardhat": "^2.20.1", "hardhat-deploy": "^0.11.44", "isomorphic-fetch": "^3.0.0", "mocha": "^10.2.0", @@ -56,8 +56,8 @@ "ts-node": "^10.9.2", "typedoc": "^0.25.7", "typescript": "^5.3.3", - "viem": "^2.0.3", - "vitest": "^1.0.1", + "viem": "^2.7.19", + "vitest": "^1.2.2", "zod": "^3.22.4" }, "dependencies": { @@ -66,7 +66,8 @@ "@eth-optimism/core-utils": "workspace:*", "lodash": "^4.17.21", "merkletreejs": "^0.3.11", - "rlp": "^2.2.7" + "rlp": "^2.2.7", + "semver": "^7.6.0" }, "peerDependencies": { "ethers": "^5" diff --git a/packages/sdk/src/cross-chain-messenger.ts b/packages/sdk/src/cross-chain-messenger.ts index 1f543eaedc06..5483df77307f 100644 --- a/packages/sdk/src/cross-chain-messenger.ts +++ b/packages/sdk/src/cross-chain-messenger.ts @@ -19,7 +19,6 @@ import { remove0x, toHexString, toRpcHexString, - hashCrossDomainMessage, encodeCrossDomainMessageV0, encodeCrossDomainMessageV1, BedrockOutputData, @@ -32,6 +31,7 @@ import { } from '@eth-optimism/core-utils' import { getContractInterface, predeploys } from '@eth-optimism/contracts' import * as rlp from 'rlp' +import semver from 'semver' import { OEContracts, @@ -72,6 +72,8 @@ import { DEPOSIT_CONFIRMATION_BLOCKS, CHAIN_BLOCK_TIMES, hashMessageHash, + getContractInterfaceBedrock, + toJsonRpcProvider, } from './utils' export class CrossChainMessenger { @@ -120,6 +122,11 @@ export class CrossChainMessenger { */ public bedrock: boolean + /** + * Cache for output root validation. Output roots are expensive to verify, so we cache them. + */ + private _outputCache: Array<{ root: string; valid: boolean }> = [] + /** * Creates a new CrossChainProvider instance. * @@ -228,6 +235,29 @@ export class CrossChainMessenger { } } + /** + * Uses portal version to determine if the messenger is using fpac contracts. Better not to cache + * this value as it will change during the fpac upgrade and we want clients to automatically + * begin using the new logic without throwing any errors. + * + * @returns Whether or not the messenger is using fpac contracts. + */ + public async fpac(): Promise { + if ( + this.contracts.l1.OptimismPortal.address === ethers.constants.AddressZero + ) { + // Only really relevant for certain SDK tests where the portal is not deployed. We should + // probably just update the tests so the portal gets deployed but feels like it's out of + // scope for the FPAC changes. + return false + } else { + return semver.gte( + await this.contracts.l1.OptimismPortal.version(), + '3.0.0' + ) + } + } + /** * Retrieves all cross chain messages sent within a given transaction. * @@ -697,22 +727,23 @@ export class CrossChainMessenger { (await messenger.successfulMessages(messageHashV0)) || (await messenger.successfulMessages(messageHashV1)) + // Avoid the extra query if we already know the message was successful. + if (success) { + return MessageStatus.RELAYED + } + const failure = (await messenger.failedMessages(messageHashV0)) || (await messenger.failedMessages(messageHashV1)) if (resolved.direction === MessageDirection.L1_TO_L2) { - if (success) { - return MessageStatus.RELAYED - } else if (failure) { + if (failure) { return MessageStatus.FAILED_L1_TO_L2_MESSAGE } else { return MessageStatus.UNCONFIRMED_L1_TO_L2_MESSAGE } } else { - if (success) { - return MessageStatus.RELAYED - } else if (failure) { + if (failure) { return MessageStatus.READY_FOR_RELAY } else { let timestamp: number @@ -731,11 +762,16 @@ export class CrossChainMessenger { messageIndex ) + // Pick portal based on FPAC compatibility. + const portal = (await this.fpac()) + ? this.contracts.l1.OptimismPortal2 + : this.contracts.l1.OptimismPortal + // Attempt to fetch the proven withdrawal. - const provenWithdrawal = - await this.contracts.l1.OptimismPortal.provenWithdrawals( - hashLowLevelMessage(withdrawal) - ) + const provenWithdrawal = await portal.provenWithdrawals( + hashLowLevelMessage(withdrawal) + ) + // If the withdrawal hash has not been proven on L1, // return `READY_TO_PROVE` if (provenWithdrawal.timestamp.eq(BigNumber.from(0))) { @@ -758,13 +794,57 @@ export class CrossChainMessenger { timestamp = block.timestamp } - const challengePeriod = await this.getChallengePeriodSeconds() - const latestBlock = await this.l1Provider.getBlock('latest') + if (await this.fpac()) { + // Convert the message to the low level message that was proven. + const withdrawal = await this.toLowLevelMessage( + resolved, + messageIndex + ) + + // Get the withdrawal hash. + const withdrawalHash = hashLowLevelMessage(withdrawal) + + // Grab the proven withdrawal data. + const provenWithdrawal = + await this.contracts.l1.OptimismPortal2.provenWithdrawals( + withdrawalHash + ) + + // Attach to the FaultDisputeGame. + const game = new ethers.Contract( + provenWithdrawal.disputeGameProxy, + getContractInterfaceBedrock('FaultDisputeGame'), + this.l1SignerOrProvider + ) + + // Check if the game resolved to status 1 = "CHALLENGER_WINS". If so, the withdrawal was + // proven against a proposal that was invalidated and will need to be reproven. We throw + // an error here instead of creating a new status mostly because it's easier to integrate + // into the SDK. + const status = await game.status() + if (status === 1) { + throw new Error(`withdrawal proposal was invalidated, must reprove`) + } - if (timestamp + challengePeriod > latestBlock.timestamp) { - return MessageStatus.IN_CHALLENGE_PERIOD + try { + // If this doesn't revert then we should be fine to relay. + await this.contracts.l1.OptimismPortal2.checkWithdrawal( + hashLowLevelMessage(withdrawal) + ) + + return MessageStatus.READY_FOR_RELAY + } catch (err) { + return MessageStatus.IN_CHALLENGE_PERIOD + } } else { - return MessageStatus.READY_FOR_RELAY + const challengePeriod = await this.getChallengePeriodSeconds() + const latestBlock = await this.l1Provider.getBlock('latest') + + if (timestamp + challengePeriod > latestBlock.timestamp) { + return MessageStatus.IN_CHALLENGE_PERIOD + } else { + return MessageStatus.READY_FOR_RELAY + } } } } @@ -1212,29 +1292,157 @@ export class CrossChainMessenger { throw new Error(`cannot get a state root for an L1 to L2 message`) } - // Try to find the output index that corresponds to the block number attached to the message. - // We'll explicitly handle "cannot get output" errors as a null return value, but anything else - // needs to get thrown. Might need to revisit this in the future to be a little more robust - // when connected to RPCs that don't return nice error messages. + let proposal: any let l2OutputIndex: BigNumber - try { - l2OutputIndex = - await this.contracts.l1.L2OutputOracle.getL2OutputIndexAfter( - resolved.blockNumber + if (await this.fpac()) { + // Get the respected game type from the portal. + const gameType = + await this.contracts.l1.OptimismPortal2.respectedGameType() + + // Get the total game count from the DisputeGameFactory since that will give us the end of + // the array that we're searching over. We'll then use that to find the latest games. + const gameCount = await this.contracts.l1.DisputeGameFactory.gameCount() + + // Find the latest 100 games (or as many as we can up to 100). + const latestGames = + await this.contracts.l1.DisputeGameFactory.findLatestGames( + gameType, + Math.max(0, gameCount.sub(1).toNumber()), + Math.min(100, gameCount.toNumber()) ) - } catch (err) { - if (err.message.includes('L2OutputOracle: cannot get output')) { + + // Find all games that are for proposals about blocks newer than the message block. + const matches: any[] = [] + for (const game of latestGames) { + try { + const [blockNumber] = ethers.utils.defaultAbiCoder.decode( + ['uint256'], + game.extraData + ) + if (blockNumber.gte(resolved.blockNumber)) { + matches.push({ + ...game, + l2BlockNumber: blockNumber, + }) + } + } catch (err) { + // If we can't decode the extra data then we just skip this game. + continue + } + } + + // Shuffle the list of matches. We shuffle here to avoid potential DoS vectors where the + // latest games are all invalid and the SDK would be forced to make a bunch of archive calls. + for (let i = matches.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)) + ;[matches[i], matches[j]] = [matches[j], matches[i]] + } + + // Now we verify the proposals in the matches array. + let match: any + for (const option of matches) { + // Use the cache if we can. + const cached = this._outputCache.find((other) => { + return other.root === option.rootClaim + }) + + // Skip if we can use the cached. + if (cached) { + if (cached.valid) { + match = option + break + } else { + continue + } + } + + // If the cache ever gets to 10k elements, clear out the first half. Works well enough + // since the cache will generally tend to be used in a FIFO manner. + if (this._outputCache.length > 10000) { + this._outputCache = this._outputCache.slice(5000) + } + + // We didn't hit the cache so we're going to have to do the work. + try { + // Make sure this is a JSON RPC provider. + const provider = toJsonRpcProvider(this.l2Provider) + + // Grab the block and storage proof at the same time. + const [block, proof] = await Promise.all([ + provider.send('eth_getBlockByNumber', [ + toRpcHexString(option.l2BlockNumber), + false, + ]), + makeStateTrieProof( + provider, + option.l2BlockNumber, + this.contracts.l2.OVM_L2ToL1MessagePasser.address, + ethers.constants.HashZero + ), + ]) + + // Compute the output. + const output = ethers.utils.solidityKeccak256( + ['bytes32', 'bytes32', 'bytes32', 'bytes32'], + [ + ethers.constants.HashZero, + block.stateRoot, + proof.storageRoot, + block.hash, + ] + ) + + // If the output matches the proposal then we're good. + if (output === option.rootClaim) { + this._outputCache.push({ root: option.rootClaim, valid: true }) + match = option + break + } else { + this._outputCache.push({ root: option.rootClaim, valid: false }) + } + } catch (err) { + // Just skip this option, whatever. If it was a transient error then we'll try again in + // the next loop iteration. If it was a permanent error then we'll get the same thing. + continue + } + } + + // If there's no match then we can't prove the message to the portal. + if (!match) { return null - } else { - throw err } - } - // Now pull the proposal out given the output index. Should always work as long as the above - // codepath completed successfully. - const proposal = await this.contracts.l1.L2OutputOracle.getL2Output( - l2OutputIndex - ) + // Put the result into the same format as the old logic for now to reduce added code. + l2OutputIndex = match.index + proposal = { + outputRoot: match.rootClaim, + timestamp: match.timestamp, + l2BlockNumber: match.l2BlockNumber, + } + } else { + // Try to find the output index that corresponds to the block number attached to the message. + // We'll explicitly handle "cannot get output" errors as a null return value, but anything else + // needs to get thrown. Might need to revisit this in the future to be a little more robust + // when connected to RPCs that don't return nice error messages. + try { + l2OutputIndex = + await this.contracts.l1.L2OutputOracle.getL2OutputIndexAfter( + resolved.blockNumber + ) + } catch (err) { + if (err.message.includes('L2OutputOracle: cannot get output')) { + return null + } else { + throw err + } + } + + // Now pull the proposal out given the output index. Should always work as long as the above + // codepath completed successfully. + proposal = await this.contracts.l1.L2OutputOracle.getL2Output( + l2OutputIndex + ) + } // Format everything and return it nicely. return { @@ -1473,7 +1681,7 @@ export class CrossChainMessenger { ) const stateTrieProof = await makeStateTrieProof( - this.l2Provider as ethers.providers.JsonRpcProvider, + toJsonRpcProvider(this.l2Provider), resolved.blockNumber, this.contracts.l2.OVM_L2ToL1MessagePasser.address, messageSlot @@ -1519,16 +1727,16 @@ export class CrossChainMessenger { const hash = hashLowLevelMessage(withdrawal) const messageSlot = hashMessageHash(hash) + const provider = toJsonRpcProvider(this.l2Provider) + const stateTrieProof = await makeStateTrieProof( - this.l2Provider as ethers.providers.JsonRpcProvider, + provider, output.l2BlockNumber, this.contracts.l2.BedrockMessagePasser.address, messageSlot ) - const block = await ( - this.l2Provider as ethers.providers.JsonRpcProvider - ).send('eth_getBlockByNumber', [ + const block = await provider.send('eth_getBlockByNumber', [ toRpcHexString(output.l2BlockNumber), false, ]) diff --git a/packages/sdk/src/interfaces/types.ts b/packages/sdk/src/interfaces/types.ts index c31d9e61f3aa..f6b6b1c4eac0 100644 --- a/packages/sdk/src/interfaces/types.ts +++ b/packages/sdk/src/interfaces/types.ts @@ -50,6 +50,9 @@ export interface OEL1Contracts { // Bedrock OptimismPortal: Contract L2OutputOracle: Contract + // FPAC + OptimismPortal2?: Contract + DisputeGameFactory?: Contract } /** diff --git a/packages/sdk/src/utils/chain-constants.ts b/packages/sdk/src/utils/chain-constants.ts index 30cea4a5a618..c9dccd49b214 100644 --- a/packages/sdk/src/utils/chain-constants.ts +++ b/packages/sdk/src/utils/chain-constants.ts @@ -1,49 +1,36 @@ import { predeploys } from '@eth-optimism/core-utils' import { ethers } from 'ethers' -import portalArtifactsMainnet from '@eth-optimism/contracts-bedrock/deployments/mainnet/OptimismPortalProxy.json' -import portalArtifactsGoerli from '@eth-optimism/contracts-bedrock/deployments/goerli/OptimismPortalProxy.json' -import portalArtifactsSepolia from '@eth-optimism/contracts-bedrock/deployments/sepolia/OptimismPortalProxy.json' -import l2OutputOracleArtifactsMainnet from '@eth-optimism/contracts-bedrock/deployments/mainnet/L2OutputOracleProxy.json' -import l2OutputOracleArtifactsGoerli from '@eth-optimism/contracts-bedrock/deployments/goerli/L2OutputOracleProxy.json' -import l2OutputOracleArtifactsSepolia from '@eth-optimism/contracts-bedrock/deployments/sepolia/L2OutputOracleProxy.json' -import addressManagerArtifactMainnet from '@eth-optimism/contracts-bedrock/deployments/mainnet/AddressManager.json' -import addressManagerArtifactGoerli from '@eth-optimism/contracts-bedrock/deployments/goerli/AddressManager.json' -import addressManagerArtifactSepolia from '@eth-optimism/contracts-bedrock/deployments/sepolia/AddressManager.json' -import l1StandardBridgeArtifactMainnet from '@eth-optimism/contracts-bedrock/deployments/mainnet/L1StandardBridgeProxy.json' -import l1StandardBridgeArtifactGoerli from '@eth-optimism/contracts-bedrock/deployments/goerli/L1StandardBridgeProxy.json' -import l1StandardBridgeArtifactSepolia from '@eth-optimism/contracts-bedrock/deployments/sepolia/L1StandardBridgeProxy.json' -import l1CrossDomainMessengerArtifactMainnet from '@eth-optimism/contracts-bedrock/deployments/mainnet/L1CrossDomainMessengerProxy.json' -import l1CrossDomainMessengerArtifactGoerli from '@eth-optimism/contracts-bedrock/deployments/goerli/L1CrossDomainMessengerProxy.json' -import l1CrossDomainMessengerArtifactSepolia from '@eth-optimism/contracts-bedrock/deployments/sepolia/L1CrossDomainMessengerProxy.json' + +// The addresses below should be for the proxy if it is a proxied contract. const portalAddresses = { - mainnet: portalArtifactsMainnet.address, - goerli: portalArtifactsGoerli.address, - sepolia: portalArtifactsSepolia.address, + mainnet: '0xbEb5Fc579115071764c7423A4f12eDde41f106Ed', + goerli: '0x5b47E1A08Ea6d985D6649300584e6722Ec4B1383', + sepolia: '0x16Fc5058F25648194471939df75CF27A2fdC48BC', } const l2OutputOracleAddresses = { - mainnet: l2OutputOracleArtifactsMainnet.address, - goerli: l2OutputOracleArtifactsGoerli.address, - sepolia: l2OutputOracleArtifactsSepolia.address, + mainnet: '0xdfe97868233d1aa22e815a266982f2cf17685a27', + goerli: '0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0', + sepolia: '0x90E9c4f8a994a250F6aEfd61CAFb4F2e895D458F', } const addressManagerAddresses = { - mainnet: addressManagerArtifactMainnet.address, - goerli: addressManagerArtifactGoerli.address, - sepolia: addressManagerArtifactSepolia.address, + mainnet: '0xdE1FCfB0851916CA5101820A69b13a4E276bd81F', + goerli: '0xa6f73589243a6A7a9023b1Fa0651b1d89c177111', + sepolia: '0x9bFE9c5609311DF1c011c47642253B78a4f33F4B', } const l1StandardBridgeAddresses = { - mainnet: l1StandardBridgeArtifactMainnet.address, - goerli: l1StandardBridgeArtifactGoerli.address, - sepolia: l1StandardBridgeArtifactSepolia.address, + mainnet: '0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1', + goerli: '0x636Af16bf2f682dD3109e60102b8E1A089FedAa8', + sepolia: '0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1', } const l1CrossDomainMessengerAddresses = { - mainnet: l1CrossDomainMessengerArtifactMainnet.address, - goerli: l1CrossDomainMessengerArtifactGoerli.address, - sepolia: l1CrossDomainMessengerArtifactSepolia.address, + mainnet: '0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1', + goerli: '0x5086d1eEF304eb5284A0f6720f79403b4e9bE294', + sepolia: '0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef', } // legacy @@ -133,9 +120,16 @@ const getL1ContractsByNetworkName = (network: string): OEL1ContractsLike => { BondManager: ethers.constants.AddressZero, OptimismPortal: portalAddresses[network], L2OutputOracle: l2OutputOracleAddresses[network], + OptimismPortal2: portalAddresses[network], + DisputeGameFactory: ethers.constants.AddressZero, } } +/** + * List of contracts that are ignorable when checking for contracts on a given network. + */ +export const IGNORABLE_CONTRACTS = ['OptimismPortal2', 'DisputeGameFactory'] + /** * Mapping of L1 chain IDs to the appropriate contract addresses for the OE deployments to the * given network. Simplifies the process of getting the correct contract addresses for a given @@ -170,6 +164,8 @@ export const CONTRACT_ADDRESSES: { // FIXME OptimismPortal: '0x0000000000000000000000000000000000000000' as const, L2OutputOracle: '0x0000000000000000000000000000000000000000' as const, + OptimismPortal2: '0x0000000000000000000000000000000000000000' as const, + DisputeGameFactory: '0x0000000000000000000000000000000000000000' as const, }, l2: DEFAULT_L2_CONTRACT_ADDRESSES, }, @@ -186,6 +182,8 @@ export const CONTRACT_ADDRESSES: { BondManager: '0x5FC8d32690cc91D4c39d9d3abcBD16989F875707' as const, OptimismPortal: '0x0000000000000000000000000000000000000000' as const, L2OutputOracle: '0x0000000000000000000000000000000000000000' as const, + OptimismPortal2: '0x0000000000000000000000000000000000000000' as const, + DisputeGameFactory: '0x0000000000000000000000000000000000000000' as const, }, l2: DEFAULT_L2_CONTRACT_ADDRESSES, }, @@ -202,6 +200,8 @@ export const CONTRACT_ADDRESSES: { BondManager: '0x0000000000000000000000000000000000000000' as const, OptimismPortal: '0xA581Ca3353DB73115C4625FFC7aDF5dB379434A8' as const, L2OutputOracle: '0x3A234299a14De50027eA65dCdf1c0DaC729e04A6' as const, + OptimismPortal2: '0x0000000000000000000000000000000000000000' as const, + DisputeGameFactory: '0x0000000000000000000000000000000000000000' as const, }, l2: DEFAULT_L2_CONTRACT_ADDRESSES, }, @@ -218,6 +218,8 @@ export const CONTRACT_ADDRESSES: { BondManager: '0x0000000000000000000000000000000000000000' as const, OptimismPortal: '0xe93c8cD0D409341205A592f8c4Ac1A5fe5585cfA' as const, L2OutputOracle: '0x2A35891ff30313CcFa6CE88dcf3858bb075A2298' as const, + OptimismPortal2: '0x0000000000000000000000000000000000000000' as const, + DisputeGameFactory: '0x0000000000000000000000000000000000000000' as const, }, l2: DEFAULT_L2_CONTRACT_ADDRESSES, }, @@ -234,6 +236,8 @@ export const CONTRACT_ADDRESSES: { BondManager: '0x0000000000000000000000000000000000000000' as const, OptimismPortal: '0x49f53e41452C74589E85cA1677426Ba426459e85' as const, L2OutputOracle: '0x84457ca9D0163FbC4bbfe4Dfbb20ba46e48DF254' as const, + OptimismPortal2: '0x0000000000000000000000000000000000000000' as const, + DisputeGameFactory: '0x0000000000000000000000000000000000000000' as const, }, l2: DEFAULT_L2_CONTRACT_ADDRESSES, }, @@ -250,6 +254,8 @@ export const CONTRACT_ADDRESSES: { BondManager: '0x0000000000000000000000000000000000000000' as const, OptimismPortal: '0x49048044D57e1C92A77f79988d21Fa8fAF74E97e' as const, L2OutputOracle: '0x56315b90c40730925ec5485cf004d835058518A0' as const, + OptimismPortal2: '0x0000000000000000000000000000000000000000' as const, + DisputeGameFactory: '0x0000000000000000000000000000000000000000' as const, }, l2: DEFAULT_L2_CONTRACT_ADDRESSES, }, @@ -267,6 +273,8 @@ export const CONTRACT_ADDRESSES: { BondManager: '0x0000000000000000000000000000000000000000' as const, OptimismPortal: '0xDb9F51790365e7dc196e7D072728df39Be958ACe' as const, L2OutputOracle: '0xdD292C9eEd00f6A32Ff5245d0BCd7f2a15f24e00' as const, + OptimismPortal2: '0x0000000000000000000000000000000000000000' as const, + DisputeGameFactory: '0x0000000000000000000000000000000000000000' as const, }, l2: DEFAULT_L2_CONTRACT_ADDRESSES, }, @@ -283,6 +291,8 @@ export const CONTRACT_ADDRESSES: { BondManager: '0x0000000000000000000000000000000000000000' as const, OptimismPortal: '0x1a0ad011913A150f69f6A19DF447A0CfD9551054' as const, L2OutputOracle: '0x9E6204F750cD866b299594e2aC9eA824E2e5f95c' as const, + OptimismPortal2: '0x0000000000000000000000000000000000000000' as const, + DisputeGameFactory: '0x0000000000000000000000000000000000000000' as const, }, l2: DEFAULT_L2_CONTRACT_ADDRESSES, }, diff --git a/packages/sdk/src/utils/coercion.ts b/packages/sdk/src/utils/coercion.ts index eb5497f319bd..b57f8ba04418 100644 --- a/packages/sdk/src/utils/coercion.ts +++ b/packages/sdk/src/utils/coercion.ts @@ -53,6 +53,26 @@ export const toProvider = (provider: ProviderLike): Provider => { } } +/** + * Converts a ProviderLike into a JsonRpcProvider. + * + * @param provider ProviderLike to turn into a JsonRpcProvider. + * @returns Input as a JsonRpcProvider. + */ +export const toJsonRpcProvider = ( + provider: ProviderLike +): ethers.providers.JsonRpcProvider => { + const coerced = toProvider(provider) + if ('send' in coerced) { + // Existence of "send" is basically the only function that matters for determining if we can + // use this provider as a JsonRpcProvider, because "send" is the function that we usually want + // access to when we specifically care about having a JsonRpcProvider. + return coerced as ethers.providers.JsonRpcProvider + } else { + throw new Error('Invalid JsonRpcProvider, does not have "send" function') + } +} + /** * Pulls a transaction hash out of a TransactionLike object. * diff --git a/packages/sdk/src/utils/contracts.ts b/packages/sdk/src/utils/contracts.ts index 64d08fd940b6..a1c786a4631b 100644 --- a/packages/sdk/src/utils/contracts.ts +++ b/packages/sdk/src/utils/contracts.ts @@ -14,6 +14,9 @@ import l2ERC721Bridge from '@eth-optimism/contracts-bedrock/forge-artifacts/L2ER import l1Block from '@eth-optimism/contracts-bedrock/forge-artifacts/L1Block.sol/L1Block.json' import l2ToL1MessagePasser from '@eth-optimism/contracts-bedrock/forge-artifacts/L2ToL1MessagePasser.sol/L2ToL1MessagePasser.json' import gasPriceOracle from '@eth-optimism/contracts-bedrock/forge-artifacts/GasPriceOracle.sol/GasPriceOracle.json' +import disputeGameFactory from '@eth-optimism/contracts-bedrock/forge-artifacts/DisputeGameFactory.sol/DisputeGameFactory.json' +import optimismPortal2 from '@eth-optimism/contracts-bedrock/forge-artifacts/OptimismPortal2.sol/OptimismPortal2.json' +import faultDisputeGame from '@eth-optimism/contracts-bedrock/forge-artifacts/FaultDisputeGame.sol/FaultDisputeGame.json' import { toAddress } from './coercion' import { DeepPartial } from './type-utils' @@ -23,6 +26,7 @@ import { CONTRACT_ADDRESSES, DEFAULT_L2_CONTRACT_ADDRESSES, BRIDGE_ADAPTER_DATA, + IGNORABLE_CONTRACTS, } from './chain-constants' import { OEContracts, @@ -45,7 +49,9 @@ const NAME_REMAPPING = { BedrockMessagePasser: 'L2ToL1MessagePasser' as const, } -const getContractInterfaceBedrock = (name: string): ethers.utils.Interface => { +export const getContractInterfaceBedrock = ( + name: string +): ethers.utils.Interface => { let artifact: any = '' switch (name) { case 'Lib_AddressManager': @@ -94,6 +100,15 @@ const getContractInterfaceBedrock = (name: string): ethers.utils.Interface => { case 'GasPriceOracle': artifact = gasPriceOracle break + case 'DisputeGameFactory': + artifact = disputeGameFactory + break + case 'OptimismPortal2': + artifact = optimismPortal2 + break + case 'FaultDisputeGame': + artifact = faultDisputeGame + break } return new ethers.utils.Interface(artifact.abi) } @@ -119,11 +134,19 @@ export const getOEContract = ( signerOrProvider?: ethers.Signer | ethers.providers.Provider } = {} ): Contract => { + // Generally we want to throw an error if a contract address is not provided but there are some + // exceptions, particularly for contracts that are part of an upgrade that has not yet been + // deployed. It's OK to not provide an address for these contracts with the caveat that this may + // cause a runtime error if the contract does actually need to be used. const addresses = CONTRACT_ADDRESSES[l2ChainId] if (addresses === undefined && opts.address === undefined) { - throw new Error( - `cannot get contract ${contractName} for unknown L2 chain ID ${l2ChainId}, you must provide an address` - ) + if (IGNORABLE_CONTRACTS.includes(contractName)) { + return undefined + } else { + throw new Error( + `cannot get contract ${contractName} for unknown L2 chain ID ${l2ChainId}, you must provide an address` + ) + } } // Bedrock interfaces are backwards compatible. We can prefer Bedrock interfaces over legacy @@ -177,6 +200,8 @@ export const getAllOEContracts = ( BondManager: undefined, OptimismPortal: undefined, L2OutputOracle: undefined, + DisputeGameFactory: undefined, + OptimismPortal2: undefined, }, l2: DEFAULT_L2_CONTRACT_ADDRESSES, } diff --git a/packages/sdk/src/utils/merkle-utils.ts b/packages/sdk/src/utils/merkle-utils.ts index 50244328ddff..2080ca6306c9 100644 --- a/packages/sdk/src/utils/merkle-utils.ts +++ b/packages/sdk/src/utils/merkle-utils.ts @@ -6,6 +6,7 @@ import { toRpcHexString, } from '@eth-optimism/core-utils' import { MerkleTree } from 'merkletreejs' +import * as rlp from 'rlp' /** * Generates a Merkle proof (using the particular scheme we use within Lib_MerkleTree). @@ -44,6 +45,42 @@ export const makeMerkleTreeProof = ( return proof } +/** + * Fix for the case where the final proof element is less than 32 bytes and the element exists + * inside of a branch node. Current implementation of the onchain MPT contract can't handle this + * natively so we instead append an extra proof element to handle it instead. + * + * @param key Key that the proof is for. + * @param proof Proof to potentially modify. + * @returns Modified proof. + */ +export const maybeAddProofNode = (key: string, proof: string[]) => { + const modifiedProof = [...proof] + const finalProofEl = modifiedProof[modifiedProof.length - 1] + const finalProofElDecoded = rlp.decode(finalProofEl) as any + if (finalProofElDecoded.length === 17) { + for (const item of finalProofElDecoded) { + // Find any nodes located inside of the branch node. + if (Array.isArray(item)) { + // Check if the key inside the node matches the key we're looking for. We remove the first + // two characters (0x) and then we remove one more character (the first nibble) since this + // is the identifier for the type of node we're looking at. In this case we don't actually + // care what type of node it is because a branch node would only ever be the final proof + // element if (1) it includes the leaf node we're looking for or (2) it stores the value + // within itself. If (1) then this logic will work, if (2) then this won't find anything + // and we won't append any proof elements, which is exactly what we would want. + const suffix = toHexString(item[0]).slice(3) + if (key.endsWith(suffix)) { + modifiedProof.push(toHexString(rlp.encode(item))) + } + } + } + } + + // Return the modified proof. + return modifiedProof +} + /** * Generates a Merkle-Patricia trie proof for a given account and storage slot. * @@ -70,6 +107,11 @@ export const makeStateTrieProof = async ( toRpcHexString(blockNumber), ]) + proof.storageProof[0].proof = maybeAddProofNode( + ethers.utils.keccak256(slot), + proof.storageProof[0].proof + ) + return { accountProof: proof.accountProof, storageProof: proof.storageProof[0].proof, diff --git a/packages/sdk/tasks/deposit-erc20.ts b/packages/sdk/tasks/deposit-erc20.ts index cad8bd5d16c4..9b62aea1eac4 100644 --- a/packages/sdk/tasks/deposit-erc20.ts +++ b/packages/sdk/tasks/deposit-erc20.ts @@ -158,6 +158,8 @@ task('deposit-erc20', 'Deposits WETH9 onto L2.') BondManager: ethers.constants.AddressZero, OptimismPortal: json.OptimismPortalProxy, L2OutputOracle: json.L2OutputOracleProxy, + OptimismPortal2: json.OptimismPortalProxy, + DisputeGameFactory: json.DisputeGameFactoryProxy, }, l2: DEFAULT_L2_CONTRACT_ADDRESSES, } as OEContractsLike diff --git a/packages/sdk/tasks/deposit-eth.ts b/packages/sdk/tasks/deposit-eth.ts index 62a9539f8ded..a6766a8646c3 100644 --- a/packages/sdk/tasks/deposit-eth.ts +++ b/packages/sdk/tasks/deposit-eth.ts @@ -103,6 +103,8 @@ task('deposit-eth', 'Deposits ether to L2.') BondManager: ethers.constants.AddressZero, OptimismPortal: json.OptimismPortalProxy, L2OutputOracle: json.L2OutputOracleProxy, + OptimismPortal2: json.OptimismPortalProxy, + DisputeGameFactory: json.DisputeGameFactoryProxy, }, l2: DEFAULT_L2_CONTRACT_ADDRESSES, } as OEContractsLike diff --git a/packages/sdk/test/cross-chain-messenger.spec.ts b/packages/sdk/test/cross-chain-messenger.spec.ts index 1d1b59470543..13a59348207d 100644 --- a/packages/sdk/test/cross-chain-messenger.spec.ts +++ b/packages/sdk/test/cross-chain-messenger.spec.ts @@ -16,6 +16,7 @@ import { ETHBridgeAdapter, L1ChainID, L2ChainID, + IGNORABLE_CONTRACTS, } from '../src' import { DUMMY_MESSAGE, DUMMY_EXTENDED_MESSAGE } from './helpers' @@ -234,7 +235,7 @@ describe('CrossChainMessenger', () => { if (overrides.l1[contractName]) { const contract = messenger.contracts.l1[contractName] expect(contract.address).to.equal(overrides.l1[contractName]) - } else { + } else if (!IGNORABLE_CONTRACTS.includes(contractName)) { const contract = messenger.contracts.l1[contractName] expect(contract.address).to.equal(contractAddress) } diff --git a/packages/sdk/test/utils/merkle-utils.spec.ts b/packages/sdk/test/utils/merkle-utils.spec.ts new file mode 100644 index 000000000000..5c9fbcbf009a --- /dev/null +++ b/packages/sdk/test/utils/merkle-utils.spec.ts @@ -0,0 +1,60 @@ +import { ethers } from 'ethers' + +import { expect } from '../setup' +import { maybeAddProofNode } from '../../src/utils/merkle-utils' + +describe('Merkle Utils', () => { + describe('maybeAddProofNode', () => { + // Test taken from opBNB testnet withdrawal. + it('should add a proof node when final node is inside of a branch', () => { + const key = ethers.utils.keccak256( + '0x5cd60ecef836e75dd12539abe8ad5f4ba0dc4fcaae2c45024c69bd9e20746eba' + ) + const proof = [ + '0xf90211a0feb6c6afca5ea568e0b7183d7292c112e9d28a1c846d889636d5c8822463aa77a0df719a24d8049d04a47e0e07ba493110fed0665d897c0ffdb05a7ce474782026a01bec363c069dc337ce16b4ca5cffa11d20e305fd7dcf6d87547b151c31aabf0ca00583d5a451bfa01f5e51d992e129ee17e65adda9495bda77898187484625aa9ea0bd9fef27cd52c2721e519bcd40c63a818095374e505a3bbd88db29c6c4521982a009a31937313c5b2bc06da6fec4075110f19526a9dbde3629ebe36aa8cd8e0851a0555f89002a34f6570bab438e69c5d8b855f2664e31f5dd59b807d0956577cc81a07e6f59ec99405b7afa436bf62abd098a85b43861fd3a9da3214a5d46b2d12543a03e7e883b0406cb781e5bf2a71cafc02ebbcdb0684ac03439633faf339d1259e2a0fa154fcf0bedd25aacac74e9864e4b96742c3d06f58c170cd320ade69db16c88a07e34154a031da5e50a3886efcb15c6681deeb20832726f083f80b03678b56d33a0d24408a39fb57838fdfe85c68f7eac74daab709ec3c22dfd0a579c1dbd64861aa093c1837ab2907fc51de7e918b81b997d60a6c8a18e3538720ee0d0f369530c26a0fca1af24293865f21d18d5eb823e0ecc007306823864f11d59c1c5c370fb22c2a0de8c894b5067d637df401aa6b963a3fc52b774abbedf6688e25bbf9a29672b7ca021c85d42de67601599e605d9ed1257451d1ce403d2478496d0a99d60db643d5280', + '0xf90211a02288f14667ef872b449e0f0f5526c2ad3634dcdb7376616d18fd87f6af9293bfa027223b95acda1508dbc42caac8edfb422759eedd13628e4dff0c5bf79d275182a0352a96940c817156a6e33c6f6cb2010ac216296f6e912c335982ba75ffb11898a0c3b7339a174d0a5fd842d3bb946a2ba6d9c1088215d9c3f56449af4dabb59e1ca03b331c72db0a3e0b51167ecb4d0ee76126181e3a54718e7cdefbf89ae0ae0d7ea03f162cadc26daa12d91e9ba459c9e61008ef57314e9cb810f074a878f2b81910a00dc670d0489ec214e2a636274d1e8b2df9db343218503ae2bf7ed868d8ab553fa0bffdd8cf5fe58452a64254f44e28ecd886964898fbab68711749423478d9c94ea0ca722fcaddd052f5a8ddce25c0c4161cd9e5552a0697ceccba540b0520cfcb61a0ffc0036ebf8ed2d9603de8c22d36cdc3fb451dd92a23adefe5593a4d8a12299da0bff43610f0c3d44e73e741d58f34f4d8e25aa3f67e0796241210bf321c2f1117a0341dcdbf2722bd7eacc3af46b6a9d80bb775dace93808a6737a1e135b9b225f3a07b3c3ec4c199c11374ba2dd28227e8c1efdbd8cb065768eff27e3918647eaccfa0e5a903a66eedfe8ea6d28a0f93cc91fc5f00f612a54aeeff100dafe84182a815a0203b138ec5130556a58d06184fdc399cb726954d28fe9fc68131f23d211382f5a057e92c1aec0a5b4e723cbbb3928d1008c9a9b4a26206656fccf70c14136a77de80', + '0xf90211a0437a65e2661356d938aa5321927d85003770566f25f121ec0dba4ad4acae9a8ca04acf516468076bf35f8c10e6aa904612fe08fcfba5c7b76bd87a5fe38e212c4da08db4fa1d774e1653468078c4c6a26cc6236025d6ab88dd1c02dae7c8bc7b19f7a03fb292d186e2d63e163788b3af313403cd12bc4b839037be4ad15a6fbbee217aa0dc569eab6a0b0a1d1dd7d12a24512bff7d4a6f5dc55a5a2dea31ed1a5415d383a0e4eaab256b73b4abc3402f44b6fa90a0854b733cdd5b884915ae8c07f5c78002a075ccef6818cc6c2870a70a0b41e3904ba2355937e028b02cb54a7ab321492357a0b059014d41d68c6c28b7de8f06b57c015210167d64c8589f9d7801dd4f025a60a07bf03f4912eaba2dd295222c1e01c1ddd7baedad61cf90d4e5987fc7ae1c6beaa0309d5aff3d1194cf259389cbb365e43548291aa9125d0550ab4908d1cc958844a0ff3fa5bba3bd95b08506336101c1c71cb920dd3ee68d8120654dac8f4b05d390a03a7b3de7b7476d9bf665396b718a28f8d746828bbf51a396e43669a4c90ca770a0913bc7b7ef04689a19cebf2c785f4eea68ccf9c97be94bb5bdd1346d4b145147a0cc21ab258bc2d961534438ddbbf185de30f8387acbc40f89857d88a23f90047ea0cf8b6876bd0cfd19ddd39fcfe88470d76757f64ba8496cfc382c92ed65706586a051de24dd2a27ffce89bb1dfcd6aa33469a91b50c4332ff9ef45d3cc917613a5c80', + '0xf90211a00aaeb3f8caea8f7167815fcdf1470777f7e100c781bc9ed79afefac295bb0d03a04b9f1d4ade00185fc62732b28abfb243afff140ebfa034daa4f139e0015a2195a0f9608d7d4346638e5ad4219ef6ea0769aa9fdb4bc6207831cf0f64854b072c2da0b953f4ee5f8ae17d9da8e3c1efaf9a822d0301dab05cae4b776fbd666fce8158a0bd8460bbbcfa3e02af0909445883176e3b65c85a63c6f91c2994fa2979228726a024f9c1c9952c2b6edec11955b50eaccd1ef44099db309f807f85aa4c4130b31ea056ad08d1e812df59fb54d2b847b1e7fa0872aaa1f3ac8f4e314d6893baece56aa02ca9f7cf8514dcca9401081f94b824f03b4d74dc690dfeed6779ddee4a9ad72ba050dffdadd79fbb8d857ad658864cd9cb19e69c73f8ba9c241fc2b451e2124320a00377a910bb501d1b22b7b03a3fa60aa47facf33515c10b0742fb76bd5a3d7a6ca0abcffd053ac378f2aa4d90e95c64dd7cc450fe6f961f9f55722cc49ef7b47f7ba042a8b3431675d5909bad710d519dd2c5d3287f3af8641122cce53b137087ce6ba0b77542431b232d0aabbbdf27e1c1adab761e144d396d0658ec1a84a712906a73a099ca74decdad4e079c0d1f35c8da403acbe65bf284253dab1be788f1808687eba06d866839d5ce08a75b3c8a2383b7eec6120ab32c7dfbe9b036831fc3101c8250a0fd315d671bf51da89b2db014d0f199be522fbf8e19d0276d0a14a1c66c1df8ac80', + '0xf901f1a0d6228395f59dea0ead05458d95d54c315c7feddf6416bb41aed62dc165446a6ca051e1ecb5424d948d386c0d291bb674fac4c47349f67e40a77850f54254b612b5a0e3b1d858fc2bb8001052eb3a36c9e2bea2966c795848aff0e5fb3cd779cfb565a0046a3c69a3639aa8bc1b3cf2c052d54424a88d2ea90a6388595b160ef5ef161780a0b2b1a778cbd8a3257ff7114116d892491a3ab148be723e22262b842680a9b29ea026da2284e756fcade15d922c0b8f6282a008e1c842e5030a307b3ea2e9a55726a026c0862e8e9e06ddef9ce37044fe2228a3ba9863faaf0cf1ad0863d41f7d7f13a0bcfbf48375296ad05ade4710ffe7e2b419fe246623369f7a6a4fa6f720bb185fa0d982dbbef7671cf7add6efd8612d47477b77f40d62e11983fe4478e959c0a86da0b3bf440462efb53c7056f5ff3ea134a072363a95a15a6945b83e416e6adee245a00396e89cb82998271f55ef0e892d456a7bbf624c23bf751f1ea2da6a7690be42a06f2588a03a07740fe4d300795096252abeb6b984e41b4f7027df84c1c520ea84a0ce163ce486c3de11ca2f6656f5dcf82e62496cb0d5472e042dede34d0e1aedd8a0fec8a8bfbf3e3418c4730c3c7c047cd73695c4c429f6ec6babc7165b9b27e635a002711d0ce2951376bac13daf1d3bcf359a90f68bc804b6b2b2e9efe09a8157af80', + '0xf89180808080808080a0326fe6fc4a847e4db1144153b15d0d3811f0317239f2885cc2a383825ccb1d8480a04455f6e0d1f8a2022ea33d5e6a537e384483dfccd19d07d21047e9b264b56e3c808080a06174ffa3ff6accab10abb5d61000db050324c608b10c0344a3eec6fa0107a079a0d494a04c23ba556fc3bdbe234562fe6825d55f3aaaa81e43415b8070a733d0bd8080', + '0xe482000fa03cb626e2849a157c57ca2e62c3dd139cf803efe281f5b6331b3ba92280dd8c42', + '0xf84d8080808080de9c332c35a4d03ec6ab9b3ffd06c69652ce8e02ff95537f98b7a0feb29c01808080de9c36620d27102d4799d259fe08f690c0a21b80d0a1a903db682417a23f0180808080808080', + ] + const modifiedProof = maybeAddProofNode(key, proof) + expect(modifiedProof).to.deep.equal([ + ...proof, + '0xde9c36620d27102d4799d259fe08f690c0a21b80d0a1a903db682417a23f01', + ]) + }) + + // Test taken from opBNB testnet withdrawal. + it('should not add a proof node when final node is a leaf node', () => { + const key = ethers.utils.keccak256( + '0x55b08006167f308d31af5ea9f302384725df906124e39e0eb2c6d040498e0fae' + ) + const proof = [ + '0xf90211a08c7918779c1c4435737b269573de96df28e1ec8c5847d7317906971b4c5fa73fa018679d112e60f815616a167692ea7d821691f34bed06df12c7b121a4c7b8384ba06b0a09649c9e7df1bde1c7448243c954dfecae8301b7f6bbe7d8f0b781733194a0258988e63a01754eafaffa3837ccc321c4f99d50869d04c09e7ab587988ecfa6a0a5b325ae646fd16ad7daac9d6da2ea244d456fa1a219f828cb9a5785f01bbf4ea0532b1427977ae09ee5344667910500207fd500912f9e1c6f5e7aa6b8b333a717a04a32b16d0d56f217216a9dae9eea953883ff3bcf1a9578d60d6bb28bbf4b6655a009e8cabb94c504eeb5cf15a151ed4b99be678bf969ee30be5d8aaf1312210079a0938dedf6ad32b04a9a2da09f29e481c51d7cf440d62651ed570355e12a4858d8a0b6bae212efc7179842abc76e9d6b2850b05336720b81dac467e942f7f6cd6b9ba0be45a8205c8c75ebe83c10cc9e87a597820d7e3ca691f9d1549e12a6f050a296a0c65bd95874adb4054ae8b346f2d2ccc88e76555c662b230d62072db36933508ca0e21442e3384b11c414e4a6bc2d56e71dbbbc672c38ac00bd63386ad55c590955a0d3d178f5be5f808d97ce22d48adce909ecf326cc5d9a0e7b64af616ca2d3e12ca09475833e7206cd83f7301f995617825f6d7050c782e17495ce5eb0556c2b68c4a09638ed778938e150e4c68cbcaf9bd47f97e1a6a6d6d2bbf9bc516450166a1ed980', + '0xf90211a0a3f8f3795f08496d4cd1b0c054c337d10d28fa2e9725162da7714c20d3b30c88a05856b0aa4c58cd715545c05ddb8bd93835dcd0ecbc7c2b139266af1c1850a671a000b3e2386218f9308469c731f6d53d5fb27512082390826956c8a234854a88aca0e525d6f4fa38fec4694f5cdb589156dc3a4d829861e1228b502c0130a4834ceaa0a414e804e76eb8863d1804ae04189237119b0415bf57c8a6a4ab176ad9f78eeca022aa4baf04a82bb83148c6ff6261dec1165f5d2f9bdf0ce73dfb2c9719fb8597a06fe7a289928f7fbd860aafb95945dcc2699bf7bf2010d6aa83b9f49308e968c9a008d5e746de17a948d6e7fc864286215d008e7f2d592cf7269df4dab0a3486215a0c39c7aa088d057db66179d7354b3f0d48f6d3ed2e62f8a840d9117b7b66a64bda0dd4ccdc76f721cf04cdf14d1d8a1821501d89c3d44ed5ed92b5a820431b36990a06c89982d73cc213516be264bb2fb6c969131f542afbc460ff781b839290e42f8a09954b3cbc392cdefb5664bc8483e1400def7846c631728d814b1a163ba871c44a0215b32a1491899a86be9c986dd695612a3964235b20e73158e501e6005cec689a0c1a8d7e66e95c7b661018c01dce2732f0f88614caa69e0e0848f5a750c8a9bbaa01aab317da329eee7bcdb91ee23d9a776f2a662bc672cc89f9d8f1c40cf94a4d5a013b5fc28d7d795f1203db98a7f49493ec4dbc6e7f19415131fd724274d53b93b80', + '0xf90211a099cf6b57cf52d79d997c6c7cacc880d9eecba4d91b711e94567d153a4e7a0586a05dd28dc2c3001cd399773fec132570d32a88cf439c15d8ed1750692892019bbda0419a8369667afcc1bd0eb25aa2ee01aa9914389f1c4c5b8cfdb76c7387b1efeda0c31b4168d817e9e6c1f8d9241cb61d3e40417396438799cae60b21036c569585a02cb6faef5768eb7381530c01c30a69ee9d6b74b63ad7875df8dce0d3f9e33beea0722b13f67dcc8e022e2f2f6cf42b697330425f910499f9f69455e9b9dc7a5696a0c2da3ee274178cd500418aa82c86116f8a19c03f50680589689cd76c526885baa0de4fcbd8ef4edef419cac8f12a67f76c27a7d53a47d0408251c89b191599e2a6a01bec2c60b7ab411ffe01ef36723a82b1e36df58759e4356b90f0b939cf9f7feca0823b67e452e64a3986da2836b6398bfe6dd6257b1313b649bd38b8109b442e86a0fe8fd7cf12be37c649531fa445116c53258d76664ba95b84f6adac356015f469a04d68070a9bd5b183068eafc1edfec122dba0ded10725ebc468cb0b7b7fba15d6a051b612dfba41f35f8c827ee18387bf6e3316cb8494fd30d88a091b5405bc5d8ca01c622f8ce84c20a5d1055a984e405638509e2e8683d1fa89725b4855500f353aa01e795b4bd4df111c9528d22c7964d89f96cdb5f7217fda91132b10b30782965fa0d91eacec2f75501bb1e9c7c3dd7d2cdf12d206627f096da1408573f2775646ce80', + '0xf90211a03b7d6150ad44f8399b7fa60d27034db408b0fe2f42770312dbc12220205ba6b2a0c34225fedb6a5a5351429e52c6dc637abed3bde536318fbb9e592630dbaa9ff8a0a3a4cbf9ee86518067c263c9ea3c59683306519f5ad518f8c7ccb298e8b405dda0bb9847a6a1e58287f2f5e0dd2fc9a7e78118639f1d9768d970114fd72cf4bb94a00bd41abbd004fc6aabb2ad6ca5ad6c8adc9188263b41e3c5c1c640bc6cdad909a01ddb2f8f80a1856248f813e3f066f12a0699c83c7a620a3a156f8d7320887901a0716be43af95da7bb5b22ffd86b67790da8f6470bdb771a1c72c3d8b918101f77a08e844b3e7b41dbf69f7cb59df673d21dd0d0679b387d136e77e91e01c2aa83cda01086f25f4f678183dc4a5398a0c608f28578619d5ef25890457f266dfd0b2b45a05c463dd5c575e7440ceea9322b3a50fc1111f45f15d8a2bb822efe430cb321e9a0deb669961500f680770e94ee2253cd5fbb20d30a0d2cb10a35efd0c1a7827ebaa090fb4c646e0a7d00b427d27372532e003f6e430fef4a896b26da3d334b5e35bea0e00315beb0ceadcbfe33727cfdb08d98c86dca534ceb50e799f2bf914e18da66a0b32fcca5247e924812fedc00a2f6c72ef36dfb28896a315bbbad8f7dac09623ca07e5d50949d89b497620383abcc9fe952911f4821b50184261c3dda6e46a0b815a039921c389fef00713e4ad8897bc5c68781fee90d0873a42cfd814b8709152c4380', + '0xf901f1a01dd4ceeb1ab5bc49adb270f4c031783adcc6d4b8b2c874778310b84188fe9b64a0747c08e80562666c517c00dfb2648e71273377b1412b56ad5e45f633f952229aa0991ce5972ae42c944f7d7fafb8cf01913a0658efd48ea4beff7dfc4c45c0f21aa0fe8c9b0e45134639ea41c880910a73d49d3c5fb8e3cf003eda7ceb48891b9d12a0d5748723a79117e595d805b90c5da4f28a88ca06ab8a3b540509fc5f74487be2a04724502db500742f7bf9f64bd6d0c9cecb150dcacd8f41b235baa3228120c3dc80a05ba19409d69154ee9397c0451ce8fe478a4a17097c49df7f25aa349243522455a01f16b5317ef849b7d520e74f02e3a1b5d3aa5454a009c398f6917ef72d12fd3aa0354fbfecc5fe46c76395042141308381ef0f59e0ffae159d1758b287dcd92c2ea065df8dd7ad7fe8accdc96ae5bf97802b1425dec3cef9c148f49c736dc8151faaa0eb440cd657329946458789ab7ba02df5dcd77a28095009305001fe5124424079a05fa06e6354a138012417afd550c71a9a08164bceccf652f150d1ea6a31f89d20a06cc7b02dce36338aa84041a725bb47b87bc93090b676776b53c0a7c654d93361a02c4ec483c0b8b4d148c133e2ea471b3432d310ed7c43d2b983203bd08adbb3eda025964bfbdd4d19d5d5f094ac4ca8bb2476047f3c5328cb1c84a24ee5bea5fdcb80', + '0xf851808080a045d583df49281f7f8c545ab91f4d35ba48873cc4da6deb2c0703135959fc8ec080808080a0ca2836f17b4c1af21e2531f7036a069ba8ef535650495820731ca669590dfddb8080808080808080', + '0xe09e202ec4eafbdfe1b7f218e5f087854c923c7f41b85d3ada15c32bef29588a01', + ] + const modifiedProof = maybeAddProofNode(key, proof) + expect(modifiedProof).to.deep.equal(proof) + }) + + // Test taken from MerkleTrie solidity test suite. + it('should not add a proof node when the value itself is inside a branch node', () => { + const key = '0x6b657933' + const proof = [ + '0xe68416b65793a0f3f387240403976788281c0a6ee5b3fc08360d276039d635bb824ea7e6fed779', + '0xf87180a034d14ccc7685aa2beb64f78b11ee2a335eae82047ef97c79b7dda7f0732b9f4ca05fb052b64e23d177131d9f32e9c5b942209eb7229e9a07c99a5d93245f53af18a09a137197a43a880648d5887cce656a5e6bbbe5e44ecb4f264395ccaddbe1acca80808080808080808080808080', + '0xf839808080808080c9823363856176616c338080808080808080809f31323334353637383930313233343536373839303132333435363738393031', + ] + const modifiedProof = maybeAddProofNode(key, proof) + expect(modifiedProof).to.deep.equal(proof) + }) + }) +}) diff --git a/packages/web3js-plugin/README.md b/packages/web3js-plugin/README.md index 5dd1df0cafc3..f4c3392c96b0 100644 --- a/packages/web3js-plugin/README.md +++ b/packages/web3js-plugin/README.md @@ -601,4 +601,4 @@ console.log(version) // 1.0.0 [1]: https://docs.web3js.org/api/web3-types#DataFormat [2]: https://docs.web3js.org/api/web3-types#DEFAULT_RETURN_FORMAT -[3]: https://docs.web3js.org/api/web3-types#DataFormat \ No newline at end of file +[3]: https://docs.web3js.org/api/web3-types#DataFormat diff --git a/packages/web3js-plugin/package.json b/packages/web3js-plugin/package.json index 94ea0e71e41d..d5cbb29a4006 100644 --- a/packages/web3js-plugin/package.json +++ b/packages/web3js-plugin/package.json @@ -33,17 +33,17 @@ }, "devDependencies": { "@eth-optimism/contracts-ts": "workspace:^", - "@swc/core": "^1.3.104", - "@vitest/coverage-istanbul": "^1.2.1", + "@swc/core": "^1.4.6", + "@vitest/coverage-istanbul": "^1.2.2", "tsup": "^8.0.1", "typescript": "^5.3.3", - "viem": "^2.0.3", - "vite": "^5.0.12", - "vitest": "^1.0.1", + "viem": "^2.7.19", + "vite": "^5.1.5", + "vitest": "^1.2.2", "zod": "^3.22.4" }, "dependencies": { - "@ethereumjs/rlp": "^5.0.1", + "@ethereumjs/rlp": "^5.0.2", "web3-eth": "^4.0.3", "web3-eth-accounts": "^4.0.3" }, diff --git a/packages/web3js-plugin/src/plugin.spec.ts b/packages/web3js-plugin/src/plugin.spec.ts index 094b25796d1d..11c10b35bb53 100644 --- a/packages/web3js-plugin/src/plugin.spec.ts +++ b/packages/web3js-plugin/src/plugin.spec.ts @@ -231,15 +231,13 @@ describe('OptimismPlugin', () => { test('estimateFees', async () => expect( - await web3.op.estimateFees( - { - chainId: 10, - data: encodedBurnMethod, - type: 2, - to: optimistAddress[10], - from: '0x77194aa25a06f932c10c0f25090f3046af2c85a6', - } - ) + await web3.op.estimateFees({ + chainId: 10, + data: encodedBurnMethod, + type: 2, + to: optimistAddress[10], + from: '0x77194aa25a06f932c10c0f25090f3046af2c85a6', + }) ).toBeTypeOf('bigint')) }) diff --git a/packages/web3js-plugin/src/plugin.ts b/packages/web3js-plugin/src/plugin.ts index e28d243bdc27..0776a0a70529 100644 --- a/packages/web3js-plugin/src/plugin.ts +++ b/packages/web3js-plugin/src/plugin.ts @@ -128,9 +128,7 @@ export class OptimismPlugin extends Web3PluginBase { return Web3.utils.format( { format: 'uint' }, await this._getPriceOracleContractInstance() - .methods.getL1GasUsed( - this._serializeTransaction(transaction) - ) + .methods.getL1GasUsed(this._serializeTransaction(transaction)) .call(), returnFormat ?? DEFAULT_RETURN_FORMAT ) @@ -257,10 +255,7 @@ export class OptimismPlugin extends Web3PluginBase { */ public async estimateFees< ReturnFormat extends DataFormat = typeof DEFAULT_RETURN_FORMAT - >( - transaction: Transaction, - returnFormat?: ReturnFormat - ) { + >(transaction: Transaction, returnFormat?: ReturnFormat) { const [l1Fee, l2Fee] = await Promise.all([ this.getL1Fee(transaction), this.getL2Fee(transaction), diff --git a/packages/web3js-plugin/tsup.config.ts b/packages/web3js-plugin/tsup.config.ts index b0813d584dbd..869dbc7c3c51 100644 --- a/packages/web3js-plugin/tsup.config.ts +++ b/packages/web3js-plugin/tsup.config.ts @@ -10,5 +10,5 @@ export default defineConfig({ splitting: false, sourcemap: true, clean: false, - dts: true + dts: true, }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e1cd1774020b..e961e6545f4a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,8 +13,8 @@ importers: version: 2.27.1 devDependencies: '@babel/eslint-parser': - specifier: ^7.23.3 - version: 7.23.3(@babel/core@7.22.10)(eslint@8.56.0) + specifier: ^7.23.10 + version: 7.23.10(@babel/core@7.22.10)(eslint@8.56.0) '@changesets/changelog-github': specifier: ^0.4.8 version: 0.4.8 @@ -28,14 +28,14 @@ importers: specifier: ^10.0.6 version: 10.0.6 '@types/node': - specifier: ^20.11.5 - version: 20.11.5 + specifier: ^20.11.17 + version: 20.11.17 '@typescript-eslint/eslint-plugin': - specifier: ^6.19.1 - version: 6.19.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0)(typescript@5.3.3) + specifier: ^6.21.0 + version: 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/parser': - specifier: ^6.19.1 - version: 6.19.1(eslint@8.56.0)(typescript@5.3.3) + specifier: ^6.21.0 + version: 6.21.0(eslint@8.56.0)(typescript@5.3.3) chai: specifier: ^4.3.10 version: 4.3.10 @@ -56,10 +56,10 @@ importers: version: 16.0.3(eslint-plugin-import@2.29.1)(eslint-plugin-node@11.1.0)(eslint-plugin-promise@5.2.0)(eslint@8.56.0) eslint-plugin-import: specifier: ^2.29.1 - version: 2.29.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0) + version: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint@8.56.0) eslint-plugin-jsdoc: - specifier: ^35.1.2 - version: 35.5.1(eslint@8.56.0) + specifier: ^48.0.6 + version: 48.0.6(eslint@8.56.0) eslint-plugin-node: specifier: ^11.1.0 version: 11.1.0(eslint@8.56.0) @@ -79,8 +79,8 @@ importers: specifier: ^50.0.1 version: 50.0.1(eslint@8.56.0) husky: - specifier: ^8.0.3 - version: 8.0.3 + specifier: ^9.0.10 + version: 9.0.10 lint-staged: specifier: 15.2.0 version: 15.2.0 @@ -88,11 +88,11 @@ importers: specifier: ^10.2.0 version: 10.2.0 nx: - specifier: 17.2.8 - version: 17.2.8 + specifier: 18.1.2 + version: 18.1.2 nx-cloud: specifier: latest - version: 16.5.2 + version: 18.0.0 nyc: specifier: ^15.1.0 version: 15.1.0 @@ -115,10 +115,10 @@ importers: devDependencies: tsup: specifier: ^8.0.1 - version: 8.0.1(@swc/core@1.3.104)(typescript@5.3.3) + version: 8.0.1(@swc/core@1.4.6)(typescript@5.3.3) vitest: - specifier: ^1.0.1 - version: 1.0.1(@types/node@20.11.5)(jsdom@23.2.0) + specifier: ^1.2.2 + version: 1.2.2(@types/node@20.11.17)(jsdom@24.0.0) packages/chain-mon: dependencies: @@ -147,8 +147,8 @@ importers: specifier: ^4.5.1 version: 4.5.1 dotenv: - specifier: ^16.3.1 - version: 16.3.1 + specifier: ^16.4.5 + version: 16.4.5 ethers: specifier: ^5.7.2 version: 5.7.2 @@ -158,16 +158,16 @@ importers: version: 5.7.0 '@nomiclabs/hardhat-ethers': specifier: ^2.2.3 - version: 2.2.3(ethers@5.7.2)(hardhat@2.19.4) + version: 2.2.3(ethers@5.7.2)(hardhat@2.20.1) '@nomiclabs/hardhat-waffle': specifier: ^2.0.6 - version: 2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.5)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.19.4) + version: 2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.5)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.20.1) hardhat: - specifier: ^2.19.4 - version: 2.19.4(ts-node@10.9.2)(typescript@5.3.3) + specifier: ^2.20.1 + version: 2.20.1(ts-node@10.9.2)(typescript@5.3.3) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.11.5)(typescript@5.3.3) + version: 10.9.2(@types/node@20.11.17)(typescript@5.3.3) tsx: specifier: ^4.7.0 version: 4.7.0 @@ -178,8 +178,8 @@ importers: specifier: workspace:* version: link:../core-utils '@sentry/node': - specifier: ^7.94.1 - version: 7.94.1 + specifier: ^7.99.0 + version: 7.99.0 bcfg: specifier: ^0.2.1 version: 0.2.1 @@ -190,8 +190,8 @@ importers: specifier: ^11.1.0 version: 11.1.0 dotenv: - specifier: ^16.3.1 - version: 16.3.1 + specifier: ^16.4.5 + version: 16.4.5 envalid: specifier: ^8.0.0 version: 8.0.0 @@ -211,8 +211,8 @@ importers: specifier: ^1.10.0 version: 1.10.0 pino: - specifier: ^8.17.2 - version: 8.17.2 + specifier: ^8.19.0 + version: 8.19.0 pino-multi-stream: specifier: ^6.0.0 version: 6.0.0 @@ -251,11 +251,11 @@ importers: packages/contracts-bedrock: devDependencies: '@typescript-eslint/eslint-plugin': - specifier: ^6.19.1 - version: 6.19.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0)(typescript@5.3.3) + specifier: ^6.21.0 + version: 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3) '@typescript-eslint/parser': - specifier: ^6.19.1 - version: 6.19.1(eslint@8.56.0)(typescript@5.3.3) + specifier: ^6.21.0 + version: 6.21.0(eslint@8.56.0)(typescript@5.3.3) tsx: specifier: ^4.7.0 version: 4.7.0 @@ -266,8 +266,8 @@ importers: packages/contracts-ts: dependencies: '@testing-library/react': - specifier: ^14.1.2 - version: 14.1.2(react-dom@18.2.0)(react@18.2.0) + specifier: ^14.2.1 + version: 14.2.1(react-dom@18.2.0)(react@18.2.0) '@types/change-case': specifier: ^2.3.1 version: 2.3.1 @@ -281,15 +281,15 @@ importers: specifier: ^18.2.0 version: 18.2.0(react@18.2.0) viem: - specifier: ^2.0.3 - version: 2.0.3(typescript@5.3.3)(zod@3.22.4) + specifier: ^2.7.19 + version: 2.7.19(typescript@5.3.3)(zod@3.22.4) devDependencies: '@eth-optimism/contracts-bedrock': specifier: workspace:* version: link:../contracts-bedrock '@testing-library/jest-dom': - specifier: ^6.2.1 - version: 6.2.1(vitest@1.0.1) + specifier: ^6.4.2 + version: 6.4.2(vitest@1.2.2) '@testing-library/react-hooks': specifier: ^8.0.1 version: 8.0.1(react-dom@18.2.0)(react@18.2.0) @@ -297,17 +297,17 @@ importers: specifier: ^8.1.0 version: 8.1.0 '@vitest/coverage-istanbul': - specifier: ^1.2.1 - version: 1.2.1(vitest@1.0.1) + specifier: ^1.2.2 + version: 1.2.2(vitest@1.2.2) '@wagmi/cli': - specifier: ^2.0.4 - version: 2.0.4(typescript@5.3.3) + specifier: ^2.1.2 + version: 2.1.2(typescript@5.3.3) '@wagmi/core': - specifier: ^2.3.1 - version: 2.3.1(react@18.2.0)(typescript@5.3.3)(viem@2.0.3) + specifier: ^2.6.3 + version: 2.6.3(react@18.2.0)(typescript@5.3.3)(viem@2.7.19) abitype: - specifier: ^0.10.3 - version: 0.10.3(typescript@5.3.3) + specifier: ^1.0.2 + version: 1.0.2(typescript@5.3.3) glob: specifier: ^10.3.10 version: 10.3.10 @@ -318,23 +318,23 @@ importers: specifier: link:@types/@testing-library/jest-dom version: link:@types/@testing-library/jest-dom jsdom: - specifier: ^23.2.0 - version: 23.2.0 + specifier: ^24.0.0 + version: 24.0.0 tsup: specifier: ^8.0.1 - version: 8.0.1(@swc/core@1.3.104)(typescript@5.3.3) + version: 8.0.1(@swc/core@1.4.6)(typescript@5.3.3) typescript: specifier: ^5.3.3 version: 5.3.3 vite: - specifier: ^5.0.12 - version: 5.0.12(@types/node@20.11.5) + specifier: ^5.1.5 + version: 5.1.5(@types/node@20.11.17) vitest: - specifier: ^1.0.1 - version: 1.0.1(@types/node@20.11.5)(jsdom@23.2.0) + specifier: ^1.2.2 + version: 1.2.2(@types/node@20.11.17)(jsdom@24.0.0) wagmi: - specifier: ^2.2.1 - version: 2.2.1(@tanstack/react-query@5.17.1)(react-dom@18.2.0)(react-native@0.73.1)(react@18.2.0)(typescript@5.3.3)(viem@2.0.3) + specifier: ^2.5.5 + version: 2.5.5(@tanstack/react-query@5.17.1)(react-dom@18.2.0)(react-native@0.73.1)(react@18.2.0)(typescript@5.3.3)(viem@2.7.19) packages/core-utils: dependencies: @@ -382,8 +382,8 @@ importers: version: 2.6.7 devDependencies: '@types/node': - specifier: ^20.11.5 - version: 20.11.5 + specifier: ^20.11.17 + version: 20.11.17 mocha: specifier: ^10.2.0 version: 10.2.0 @@ -394,17 +394,17 @@ importers: specifier: workspace:^ version: link:../contracts-ts '@testing-library/jest-dom': - specifier: ^6.2.1 - version: 6.2.1(vitest@1.0.1) + specifier: ^6.4.2 + version: 6.4.2(vitest@1.2.2) '@testing-library/react-hooks': specifier: ^8.0.1 version: 8.0.1(react@17.0.2) '@vitest/coverage-istanbul': - specifier: ^1.2.1 - version: 1.2.1(vitest@1.0.1) + specifier: ^1.2.2 + version: 1.2.2(vitest@1.2.2) abitype: - specifier: ^0.10.3 - version: 0.10.3(typescript@5.3.3) + specifier: ^1.0.2 + version: 1.0.2(typescript@5.3.3) isomorphic-fetch: specifier: ^3.0.0 version: 3.0.0 @@ -412,23 +412,23 @@ importers: specifier: link:@types/@testing-library/jest-dom version: link:@types/@testing-library/jest-dom jsdom: - specifier: ^23.2.0 - version: 23.2.0 + specifier: ^24.0.0 + version: 24.0.0 tsup: specifier: ^8.0.1 - version: 8.0.1(@swc/core@1.3.104)(typescript@5.3.3) + version: 8.0.1(@swc/core@1.4.6)(typescript@5.3.3) typescript: specifier: ^5.3.3 version: 5.3.3 viem: - specifier: ^2.0.3 - version: 2.0.3(typescript@5.3.3)(zod@3.22.4) + specifier: ^2.7.19 + version: 2.7.19(typescript@5.3.3)(zod@3.22.4) vite: - specifier: ^5.0.12 - version: 5.0.12(@types/node@20.11.5) + specifier: ^5.1.5 + version: 5.1.5(@types/node@20.11.17) vitest: - specifier: ^1.0.1 - version: 1.0.1(@types/node@20.11.5)(jsdom@23.2.0) + specifier: ^1.2.2 + version: 1.2.2(@types/node@20.11.17)(jsdom@24.0.0) packages/sdk: dependencies: @@ -450,6 +450,9 @@ importers: rlp: specifier: ^2.2.7 version: 2.2.7 + semver: + specifier: ^7.6.0 + version: 7.6.0 devDependencies: '@ethersproject/abstract-provider': specifier: ^5.7.0 @@ -462,10 +465,10 @@ importers: version: 5.7.0 '@nomiclabs/hardhat-ethers': specifier: ^2.2.3 - version: 2.2.3(ethers@5.7.2)(hardhat@2.19.4) + version: 2.2.3(ethers@5.7.2)(hardhat@2.20.1) '@nomiclabs/hardhat-waffle': specifier: ^2.0.1 - version: 2.0.1(@nomiclabs/hardhat-ethers@2.2.3)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.19.4) + version: 2.0.1(@nomiclabs/hardhat-ethers@2.2.3)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.20.1) '@types/chai': specifier: ^4.3.11 version: 4.3.11 @@ -476,8 +479,11 @@ importers: specifier: ^10.0.6 version: 10.0.6 '@types/node': - specifier: ^20.11.5 - version: 20.11.5 + specifier: ^20.11.17 + version: 20.11.17 + '@types/semver': + specifier: ^7.5.7 + version: 7.5.7 chai-as-promised: specifier: ^7.1.1 version: 7.1.1(chai@4.3.10) @@ -488,8 +494,8 @@ importers: specifier: ^5.7.2 version: 5.7.2 hardhat: - specifier: ^2.19.4 - version: 2.19.4(ts-node@10.9.2)(typescript@5.3.3) + specifier: ^2.20.1 + version: 2.20.1(ts-node@10.9.2)(typescript@5.3.3) hardhat-deploy: specifier: ^0.11.44 version: 0.11.44 @@ -504,7 +510,7 @@ importers: version: 15.1.0 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.11.5)(typescript@5.3.3) + version: 10.9.2(@types/node@20.11.17)(typescript@5.3.3) typedoc: specifier: ^0.25.7 version: 0.25.7(typescript@5.3.3) @@ -512,11 +518,11 @@ importers: specifier: ^5.3.3 version: 5.3.3 viem: - specifier: ^2.0.3 - version: 2.0.3(typescript@5.3.3)(zod@3.22.4) + specifier: ^2.7.19 + version: 2.7.19(typescript@5.3.3)(zod@3.22.4) vitest: - specifier: ^1.0.1 - version: 1.0.1(@types/node@20.11.5)(jsdom@23.2.0) + specifier: ^1.2.2 + version: 1.2.2(@types/node@20.11.17)(jsdom@24.0.0) zod: specifier: ^3.22.4 version: 3.22.4 @@ -524,8 +530,8 @@ importers: packages/web3js-plugin: dependencies: '@ethereumjs/rlp': - specifier: ^5.0.1 - version: 5.0.1 + specifier: ^5.0.2 + version: 5.0.2 web3: specifier: '>= 4.0.3 < 5.x' version: 4.0.3 @@ -540,26 +546,26 @@ importers: specifier: workspace:^ version: link:../contracts-ts '@swc/core': - specifier: ^1.3.104 - version: 1.3.104 + specifier: ^1.4.6 + version: 1.4.6 '@vitest/coverage-istanbul': - specifier: ^1.2.1 - version: 1.2.1(vitest@1.0.1) + specifier: ^1.2.2 + version: 1.2.2(vitest@1.2.2) tsup: specifier: ^8.0.1 - version: 8.0.1(@swc/core@1.3.104)(typescript@5.3.3) + version: 8.0.1(@swc/core@1.4.6)(typescript@5.3.3) typescript: specifier: ^5.3.3 version: 5.3.3 viem: - specifier: ^2.0.3 - version: 2.0.3(typescript@5.3.3)(zod@3.22.4) + specifier: ^2.7.19 + version: 2.7.19(typescript@5.3.3)(zod@3.22.4) vite: - specifier: ^5.0.12 - version: 5.0.12(@types/node@20.11.5) + specifier: ^5.1.5 + version: 5.1.5(@types/node@20.11.17) vitest: - specifier: ^1.0.1 - version: 1.0.1(@types/node@20.11.5)(jsdom@23.2.0) + specifier: ^1.2.2 + version: 1.2.2(@types/node@20.11.17)(jsdom@24.0.0) zod: specifier: ^3.22.4 version: 3.22.4 @@ -586,14 +592,6 @@ packages: '@jridgewell/trace-mapping': 0.3.19 dev: true - /@asamuzakjp/dom-selector@2.0.1: - resolution: {integrity: sha512-QJAJffmCiymkv6YyQ7voyQb5caCth6jzZsQncYCpHXrJ7RqdYG5y43+is8mnFcYubdOkr7cn1+na9BdFMxqw7w==} - dependencies: - bidi-js: 1.0.3 - css-tree: 2.3.1 - is-potential-custom-element-name: 1.0.1 - dev: true - /@babel/code-frame@7.22.13: resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} engines: {node: '>=6.9.0'} @@ -629,8 +627,8 @@ packages: - supports-color dev: true - /@babel/eslint-parser@7.23.3(@babel/core@7.22.10)(eslint@8.56.0): - resolution: {integrity: sha512-9bTuNlyx7oSstodm1cR1bECj4fkiknsDa1YniISkJemMY3DGhJNYBECbe6QD/q54mp2J8VO66jW3/7uP//iFCw==} + /@babel/eslint-parser@7.23.10(@babel/core@7.22.10)(eslint@8.56.0): + resolution: {integrity: sha512-3wSYDPZVnhseRnxRJH6ZVTNknBz76AEnyC+AYYhasjP3Yy23qz0ERR7Fcd2SHmYuSFJ2kY9gaaDd3vyqU09eSw==} engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} peerDependencies: '@babel/core': ^7.11.0 @@ -2007,6 +2005,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.13.11 + dev: true /@babel/runtime@7.23.7: resolution: {integrity: sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA==} @@ -2050,37 +2049,6 @@ packages: to-fast-properties: 2.0.0 dev: true - /@chainsafe/as-sha256@0.3.1: - resolution: {integrity: sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==} - dev: true - - /@chainsafe/persistent-merkle-tree@0.4.2: - resolution: {integrity: sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ==} - dependencies: - '@chainsafe/as-sha256': 0.3.1 - dev: true - - /@chainsafe/persistent-merkle-tree@0.5.0: - resolution: {integrity: sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw==} - dependencies: - '@chainsafe/as-sha256': 0.3.1 - dev: true - - /@chainsafe/ssz@0.10.2: - resolution: {integrity: sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg==} - dependencies: - '@chainsafe/as-sha256': 0.3.1 - '@chainsafe/persistent-merkle-tree': 0.5.0 - dev: true - - /@chainsafe/ssz@0.9.4: - resolution: {integrity: sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ==} - dependencies: - '@chainsafe/as-sha256': 0.3.1 - '@chainsafe/persistent-merkle-tree': 0.4.2 - case: 1.6.3 - dev: true - /@changesets/apply-release-plan@7.0.0: resolution: {integrity: sha512-vfi69JR416qC9hWmFGSxj7N6wA5J222XNBmezSVATPWDVPIF7gkd4d8CpbEbXmRWbVrkoli3oerGS6dcL/BGsQ==} dependencies: @@ -2096,7 +2064,7 @@ packages: outdent: 0.5.0 prettier: 2.8.8 resolve-from: 5.0.0 - semver: 7.5.4 + semver: 7.6.0 dev: false /@changesets/assemble-release-plan@6.0.0: @@ -2107,7 +2075,7 @@ packages: '@changesets/get-dependents-graph': 2.0.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 - semver: 7.5.4 + semver: 7.6.0 dev: false /@changesets/changelog-git@0.2.0: @@ -2145,7 +2113,7 @@ packages: '@changesets/types': 6.0.0 '@changesets/write': 0.3.0 '@manypkg/get-packages': 1.1.3 - '@types/semver': 7.5.0 + '@types/semver': 7.5.7 ansi-colors: 4.1.3 chalk: 2.4.2 ci-info: 3.8.0 @@ -2158,7 +2126,7 @@ packages: p-limit: 2.3.0 preferred-pm: 3.0.3 resolve-from: 5.0.0 - semver: 7.5.4 + semver: 7.6.0 spawndamnit: 2.0.0 term-size: 2.2.1 tty-table: 4.1.6 @@ -2189,7 +2157,7 @@ packages: '@manypkg/get-packages': 1.1.3 chalk: 2.4.2 fs-extra: 7.0.1 - semver: 7.5.4 + semver: 7.6.0 dev: false /@changesets/get-github-info@0.5.2: @@ -2440,13 +2408,13 @@ packages: deprecated: Please use @ensdomains/ens-contracts dev: true - /@es-joy/jsdoccomment@0.9.0-alpha.1: - resolution: {integrity: sha512-Clxxc0PwpISoYYBibA+1L2qFJ7gvFVhI2Hos87S06K+Q0cXdOhZQJNKWuaQGPAeHjZEuUB/YoWOfwjuF2wirqA==} - engines: {node: '>=12.0.0'} + /@es-joy/jsdoccomment@0.42.0: + resolution: {integrity: sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw==} + engines: {node: '>=16'} dependencies: - comment-parser: 1.1.6-beta.0 + comment-parser: 1.4.1 esquery: 1.5.0 - jsdoc-type-pratt-parser: 1.0.4 + jsdoc-type-pratt-parser: 4.0.0 dev: true /@esbuild/aix-ppc64@0.19.10: @@ -3074,8 +3042,8 @@ packages: engines: {node: '>=14'} hasBin: true - /@ethereumjs/rlp@5.0.1: - resolution: {integrity: sha512-Ab/Hfzz+T9Zl+65Nkg+9xAmwKPLicsnQ4NW49pgvJp9ovefuic95cgOS9CbPc9izIEgsqm1UitV0uNveCvud9w==} + /@ethereumjs/rlp@5.0.2: + resolution: {integrity: sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA==} engines: {node: '>=18'} hasBin: true dev: false @@ -3556,7 +3524,7 @@ packages: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.5 + '@types/node': 20.11.17 jest-mock: 29.7.0 dev: true @@ -3566,7 +3534,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.11.5 + '@types/node': 20.11.17 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -3585,7 +3553,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.11.5 + '@types/node': 20.11.17 '@types/yargs': 15.0.19 chalk: 4.1.2 dev: true @@ -3597,7 +3565,7 @@ packages: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.11.5 + '@types/node': 20.11.17 '@types/yargs': 17.0.32 chalk: 4.1.2 dev: true @@ -3855,9 +3823,9 @@ packages: engines: {node: '>=14.0.0'} dependencies: '@ethereumjs/tx': 4.2.0 - '@types/debug': 4.1.8 + '@types/debug': 4.1.12 debug: 4.3.4(supports-color@8.1.1) - semver: 7.5.4 + semver: 7.6.0 superstruct: 1.0.3 transitivePeerDependencies: - supports-color @@ -3870,10 +3838,10 @@ packages: '@ethereumjs/tx': 4.2.0 '@noble/hashes': 1.3.2 '@scure/base': 1.1.3 - '@types/debug': 4.1.8 + '@types/debug': 4.1.12 debug: 4.3.4(supports-color@8.1.1) pony-cause: 2.1.10 - semver: 7.5.4 + semver: 7.6.0 superstruct: 1.0.3 transitivePeerDependencies: - supports-color @@ -3935,6 +3903,7 @@ packages: /@motionone/vue@10.16.2: resolution: {integrity: sha512-7/dEK/nWQXOkJ70bqb2KyNfSWbNvWqKKq1C8juj+0Mg/AorgD8O5wE3naddK0G+aXuNMqRuc4jlsYHHWHtIzVw==} + deprecated: Motion One for Vue is deprecated. Use Oku Motion instead https://oku-ui.com/motion dependencies: '@motionone/dom': 10.16.2 tslib: 2.6.2 @@ -3990,162 +3959,179 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 - /@nomicfoundation/ethereumjs-block@5.0.2: - resolution: {integrity: sha512-hSe6CuHI4SsSiWWjHDIzWhSiAVpzMUcDRpWYzN0T9l8/Rz7xNn3elwVOJ/tAyS0LqL6vitUD78Uk7lQDXZun7Q==} - engines: {node: '>=14'} + /@nomicfoundation/ethereumjs-block@5.0.4: + resolution: {integrity: sha512-AcyacJ9eX/uPEvqsPiB+WO1ymE+kyH48qGGiGV+YTojdtas8itUTW5dehDSOXEEItWGbbzEJ4PRqnQZlWaPvDw==} + engines: {node: '>=18'} dependencies: - '@nomicfoundation/ethereumjs-common': 4.0.2 - '@nomicfoundation/ethereumjs-rlp': 5.0.2 - '@nomicfoundation/ethereumjs-trie': 6.0.2 - '@nomicfoundation/ethereumjs-tx': 5.0.2 - '@nomicfoundation/ethereumjs-util': 9.0.2 + '@nomicfoundation/ethereumjs-common': 4.0.4 + '@nomicfoundation/ethereumjs-rlp': 5.0.4 + '@nomicfoundation/ethereumjs-trie': 6.0.4 + '@nomicfoundation/ethereumjs-tx': 5.0.4 + '@nomicfoundation/ethereumjs-util': 9.0.4 ethereum-cryptography: 0.1.3 - ethers: 5.7.2 transitivePeerDependencies: - - bufferutil - - utf-8-validate + - c-kzg dev: true - /@nomicfoundation/ethereumjs-blockchain@7.0.2: - resolution: {integrity: sha512-8UUsSXJs+MFfIIAKdh3cG16iNmWzWC/91P40sazNvrqhhdR/RtGDlFk2iFTGbBAZPs2+klZVzhRX8m2wvuvz3w==} - engines: {node: '>=14'} + /@nomicfoundation/ethereumjs-blockchain@7.0.4: + resolution: {integrity: sha512-jYsd/kwzbmpnxx86tXsYV8wZ5xGvFL+7/P0c6OlzpClHsbFzeF41KrYA9scON8Rg6bZu3ZTv6JOAgj3t7USUfg==} + engines: {node: '>=18'} dependencies: - '@nomicfoundation/ethereumjs-block': 5.0.2 - '@nomicfoundation/ethereumjs-common': 4.0.2 - '@nomicfoundation/ethereumjs-ethash': 3.0.2 - '@nomicfoundation/ethereumjs-rlp': 5.0.2 - '@nomicfoundation/ethereumjs-trie': 6.0.2 - '@nomicfoundation/ethereumjs-tx': 5.0.2 - '@nomicfoundation/ethereumjs-util': 9.0.2 - abstract-level: 1.0.3 + '@nomicfoundation/ethereumjs-block': 5.0.4 + '@nomicfoundation/ethereumjs-common': 4.0.4 + '@nomicfoundation/ethereumjs-ethash': 3.0.4 + '@nomicfoundation/ethereumjs-rlp': 5.0.4 + '@nomicfoundation/ethereumjs-trie': 6.0.4 + '@nomicfoundation/ethereumjs-tx': 5.0.4 + '@nomicfoundation/ethereumjs-util': 9.0.4 debug: 4.3.4(supports-color@8.1.1) ethereum-cryptography: 0.1.3 - level: 8.0.0 - lru-cache: 5.1.1 - memory-level: 1.0.0 + lru-cache: 10.1.0 transitivePeerDependencies: - - bufferutil + - c-kzg - supports-color - - utf-8-validate dev: true - /@nomicfoundation/ethereumjs-common@4.0.2: - resolution: {integrity: sha512-I2WGP3HMGsOoycSdOTSqIaES0ughQTueOsddJ36aYVpI3SN8YSusgRFLwzDJwRFVIYDKx/iJz0sQ5kBHVgdDwg==} + /@nomicfoundation/ethereumjs-common@4.0.4: + resolution: {integrity: sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==} dependencies: - '@nomicfoundation/ethereumjs-util': 9.0.2 - crc-32: 1.2.2 + '@nomicfoundation/ethereumjs-util': 9.0.4 + transitivePeerDependencies: + - c-kzg dev: true - /@nomicfoundation/ethereumjs-ethash@3.0.2: - resolution: {integrity: sha512-8PfoOQCcIcO9Pylq0Buijuq/O73tmMVURK0OqdjhwqcGHYC2PwhbajDh7GZ55ekB0Px197ajK3PQhpKoiI/UPg==} - engines: {node: '>=14'} + /@nomicfoundation/ethereumjs-ethash@3.0.4: + resolution: {integrity: sha512-xvIrwIMl9sSaiYKRem68+O7vYdj7Q2XWv5P7JXiIkn83918QzWHvqbswTRsH7+r6X1UEvdsURRnZbvZszEjAaQ==} + engines: {node: '>=18'} dependencies: - '@nomicfoundation/ethereumjs-block': 5.0.2 - '@nomicfoundation/ethereumjs-rlp': 5.0.2 - '@nomicfoundation/ethereumjs-util': 9.0.2 - abstract-level: 1.0.3 + '@nomicfoundation/ethereumjs-block': 5.0.4 + '@nomicfoundation/ethereumjs-rlp': 5.0.4 + '@nomicfoundation/ethereumjs-util': 9.0.4 bigint-crypto-utils: 3.3.0 ethereum-cryptography: 0.1.3 transitivePeerDependencies: - - bufferutil - - utf-8-validate + - c-kzg dev: true - /@nomicfoundation/ethereumjs-evm@2.0.2: - resolution: {integrity: sha512-rBLcUaUfANJxyOx9HIdMX6uXGin6lANCulIm/pjMgRqfiCRMZie3WKYxTSd8ZE/d+qT+zTedBF4+VHTdTSePmQ==} - engines: {node: '>=14'} + /@nomicfoundation/ethereumjs-evm@2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2): + resolution: {integrity: sha512-lTyZZi1KpeMHzaO6cSVisR2tjiTTedjo7PcmhI/+GNFo9BmyY6QYzGeSti0sFttmjbEMioHgXxl5yrLNRg6+1w==} + engines: {node: '>=18'} dependencies: - '@ethersproject/providers': 5.7.2 - '@nomicfoundation/ethereumjs-common': 4.0.2 - '@nomicfoundation/ethereumjs-tx': 5.0.2 - '@nomicfoundation/ethereumjs-util': 9.0.2 + '@nomicfoundation/ethereumjs-common': 4.0.4 + '@nomicfoundation/ethereumjs-statemanager': 2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2) + '@nomicfoundation/ethereumjs-tx': 5.0.4 + '@nomicfoundation/ethereumjs-util': 9.0.4 + '@types/debug': 4.1.12 debug: 4.3.4(supports-color@8.1.1) ethereum-cryptography: 0.1.3 - mcl-wasm: 0.7.8 - rustbn.js: 0.2.0 + rustbn-wasm: 0.2.0 transitivePeerDependencies: - - bufferutil + - '@nomicfoundation/ethereumjs-verkle' + - c-kzg - supports-color - - utf-8-validate dev: true - /@nomicfoundation/ethereumjs-rlp@5.0.2: - resolution: {integrity: sha512-QwmemBc+MMsHJ1P1QvPl8R8p2aPvvVcKBbvHnQOKBpBztEo0omN0eaob6FeZS/e3y9NSe+mfu3nNFBHszqkjTA==} - engines: {node: '>=14'} + /@nomicfoundation/ethereumjs-rlp@5.0.4: + resolution: {integrity: sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==} + engines: {node: '>=18'} hasBin: true dev: true - /@nomicfoundation/ethereumjs-statemanager@2.0.2: - resolution: {integrity: sha512-dlKy5dIXLuDubx8Z74sipciZnJTRSV/uHG48RSijhgm1V7eXYFC567xgKtsKiVZB1ViTP9iFL4B6Je0xD6X2OA==} + /@nomicfoundation/ethereumjs-statemanager@2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2): + resolution: {integrity: sha512-HPDjeFrxw6llEi+BzqXkZ+KkvFnTOPczuHBtk21hRlDiuKuZz32dPzlhpRsDBGV1b5JTmRDUVqCS1lp3Gghw4Q==} + peerDependencies: + '@nomicfoundation/ethereumjs-verkle': 0.0.2 + peerDependenciesMeta: + '@nomicfoundation/ethereumjs-verkle': + optional: true dependencies: - '@nomicfoundation/ethereumjs-common': 4.0.2 - '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-common': 4.0.4 + '@nomicfoundation/ethereumjs-rlp': 5.0.4 + '@nomicfoundation/ethereumjs-trie': 6.0.4 + '@nomicfoundation/ethereumjs-util': 9.0.4 + '@nomicfoundation/ethereumjs-verkle': 0.0.2 debug: 4.3.4(supports-color@8.1.1) ethereum-cryptography: 0.1.3 - ethers: 5.7.2 js-sdsl: 4.4.2 + lru-cache: 10.1.0 transitivePeerDependencies: - - bufferutil + - c-kzg - supports-color - - utf-8-validate dev: true - /@nomicfoundation/ethereumjs-trie@6.0.2: - resolution: {integrity: sha512-yw8vg9hBeLYk4YNg5MrSJ5H55TLOv2FSWUTROtDtTMMmDGROsAu+0tBjiNGTnKRi400M6cEzoFfa89Fc5k8NTQ==} - engines: {node: '>=14'} + /@nomicfoundation/ethereumjs-trie@6.0.4: + resolution: {integrity: sha512-3nSwQiFMvr2VFe/aZUyinuohYvtytUqZCUCvIWcPJ/BwJH6oQdZRB42aNFBJ/8nAh2s3OcroWpBLskzW01mFKA==} + engines: {node: '>=18'} dependencies: - '@nomicfoundation/ethereumjs-rlp': 5.0.2 - '@nomicfoundation/ethereumjs-util': 9.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.4 + '@nomicfoundation/ethereumjs-util': 9.0.4 '@types/readable-stream': 2.3.15 ethereum-cryptography: 0.1.3 + lru-cache: 10.1.0 readable-stream: 3.6.2 + transitivePeerDependencies: + - c-kzg dev: true - /@nomicfoundation/ethereumjs-tx@5.0.2: - resolution: {integrity: sha512-T+l4/MmTp7VhJeNloMkM+lPU3YMUaXdcXgTGCf8+ZFvV9NYZTRLFekRwlG6/JMmVfIfbrW+dRRJ9A6H5Q/Z64g==} - engines: {node: '>=14'} + /@nomicfoundation/ethereumjs-tx@5.0.4: + resolution: {integrity: sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==} + engines: {node: '>=18'} + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true dependencies: - '@chainsafe/ssz': 0.9.4 - '@ethersproject/providers': 5.7.2 - '@nomicfoundation/ethereumjs-common': 4.0.2 - '@nomicfoundation/ethereumjs-rlp': 5.0.2 - '@nomicfoundation/ethereumjs-util': 9.0.2 + '@nomicfoundation/ethereumjs-common': 4.0.4 + '@nomicfoundation/ethereumjs-rlp': 5.0.4 + '@nomicfoundation/ethereumjs-util': 9.0.4 ethereum-cryptography: 0.1.3 - transitivePeerDependencies: - - bufferutil - - utf-8-validate dev: true - /@nomicfoundation/ethereumjs-util@9.0.2: - resolution: {integrity: sha512-4Wu9D3LykbSBWZo8nJCnzVIYGvGCuyiYLIJa9XXNVt1q1jUzHdB+sJvx95VGCpPkCT+IbLecW6yfzy3E1bQrwQ==} - engines: {node: '>=14'} + /@nomicfoundation/ethereumjs-util@9.0.4: + resolution: {integrity: sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==} + engines: {node: '>=18'} + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true dependencies: - '@chainsafe/ssz': 0.10.2 - '@nomicfoundation/ethereumjs-rlp': 5.0.2 + '@nomicfoundation/ethereumjs-rlp': 5.0.4 ethereum-cryptography: 0.1.3 dev: true - /@nomicfoundation/ethereumjs-vm@7.0.2: - resolution: {integrity: sha512-Bj3KZT64j54Tcwr7Qm/0jkeZXJMfdcAtRBedou+Hx0dPOSIgqaIr0vvLwP65TpHbak2DmAq+KJbW2KNtIoFwvA==} - engines: {node: '>=14'} + /@nomicfoundation/ethereumjs-verkle@0.0.2: + resolution: {integrity: sha512-bjnfZElpYGK/XuuVRmLS3yDvr+cDs85D9oonZ0YUa5A3lgFgokWMp76zXrxX2jVQ0BfHaw12y860n1+iOi6yFQ==} + engines: {node: '>=18'} + dependencies: + '@nomicfoundation/ethereumjs-rlp': 5.0.4 + '@nomicfoundation/ethereumjs-util': 9.0.4 + lru-cache: 10.1.0 + rust-verkle-wasm: 0.0.1 + transitivePeerDependencies: + - c-kzg + dev: true + + /@nomicfoundation/ethereumjs-vm@7.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2): + resolution: {integrity: sha512-gsA4IhmtWHI4BofKy3kio9W+dqZQs5Ji5mLjLYxHCkat+JQBUt5szjRKra2F9nGDJ2XcI/wWb0YWUFNgln4zRQ==} + engines: {node: '>=18'} dependencies: - '@nomicfoundation/ethereumjs-block': 5.0.2 - '@nomicfoundation/ethereumjs-blockchain': 7.0.2 - '@nomicfoundation/ethereumjs-common': 4.0.2 - '@nomicfoundation/ethereumjs-evm': 2.0.2 - '@nomicfoundation/ethereumjs-rlp': 5.0.2 - '@nomicfoundation/ethereumjs-statemanager': 2.0.2 - '@nomicfoundation/ethereumjs-trie': 6.0.2 - '@nomicfoundation/ethereumjs-tx': 5.0.2 - '@nomicfoundation/ethereumjs-util': 9.0.2 + '@nomicfoundation/ethereumjs-block': 5.0.4 + '@nomicfoundation/ethereumjs-blockchain': 7.0.4 + '@nomicfoundation/ethereumjs-common': 4.0.4 + '@nomicfoundation/ethereumjs-evm': 2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2) + '@nomicfoundation/ethereumjs-rlp': 5.0.4 + '@nomicfoundation/ethereumjs-statemanager': 2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2) + '@nomicfoundation/ethereumjs-trie': 6.0.4 + '@nomicfoundation/ethereumjs-tx': 5.0.4 + '@nomicfoundation/ethereumjs-util': 9.0.4 debug: 4.3.4(supports-color@8.1.1) ethereum-cryptography: 0.1.3 - mcl-wasm: 0.7.8 - rustbn.js: 0.2.0 transitivePeerDependencies: - - bufferutil + - '@nomicfoundation/ethereumjs-verkle' + - c-kzg - supports-color - - utf-8-validate dev: true /@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1: @@ -4254,17 +4240,17 @@ packages: '@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.1 dev: true - /@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.19.4): + /@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1): resolution: {integrity: sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==} peerDependencies: ethers: ^5.0.0 hardhat: ^2.0.0 dependencies: ethers: 5.7.2 - hardhat: 2.19.4(ts-node@10.9.2)(typescript@5.3.3) + hardhat: 2.20.1(ts-node@10.9.2)(typescript@5.3.3) dev: true - /@nomiclabs/hardhat-waffle@2.0.1(@nomiclabs/hardhat-ethers@2.2.3)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.19.4): + /@nomiclabs/hardhat-waffle@2.0.1(@nomiclabs/hardhat-ethers@2.2.3)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.20.1): resolution: {integrity: sha512-2YR2V5zTiztSH9n8BYWgtv3Q+EL0N5Ltm1PAr5z20uAY4SkkfylJ98CIqt18XFvxTD5x4K2wKBzddjV9ViDAZQ==} peerDependencies: '@nomiclabs/hardhat-ethers': ^2.0.0 @@ -4272,15 +4258,15 @@ packages: ethers: ^5.0.0 hardhat: ^2.0.0 dependencies: - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.4) + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.20.1) '@types/sinon-chai': 3.2.5 '@types/web3': 1.0.19 ethereum-waffle: 4.0.10(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@5.3.3) ethers: 5.7.2 - hardhat: 2.19.4(ts-node@10.9.2)(typescript@5.3.3) + hardhat: 2.20.1(ts-node@10.9.2)(typescript@5.3.3) dev: true - /@nomiclabs/hardhat-waffle@2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.5)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.19.4): + /@nomiclabs/hardhat-waffle@2.0.6(@nomiclabs/hardhat-ethers@2.2.3)(@types/sinon-chai@3.2.5)(ethereum-waffle@4.0.10)(ethers@5.7.2)(hardhat@2.20.1): resolution: {integrity: sha512-+Wz0hwmJGSI17B+BhU/qFRZ1l6/xMW82QGXE/Gi+WTmwgJrQefuBs1lIf7hzQ1hLk6hpkvb/zwcNkpVKRYTQYg==} peerDependencies: '@nomiclabs/hardhat-ethers': ^2.0.0 @@ -4289,26 +4275,26 @@ packages: ethers: ^5.0.0 hardhat: ^2.0.0 dependencies: - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.19.4) + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.20.1) '@types/sinon-chai': 3.2.5 ethereum-waffle: 4.0.10(@ensdomains/ens@0.4.5)(@ensdomains/resolver@0.2.4)(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typescript@5.3.3) ethers: 5.7.2 - hardhat: 2.19.4(ts-node@10.9.2)(typescript@5.3.3) + hardhat: 2.20.1(ts-node@10.9.2)(typescript@5.3.3) dev: true - /@nrwl/nx-cloud@16.5.2: - resolution: {integrity: sha512-oHO5T1HRJsR9mbRd8eUqMBPCgqVZLSbAh3zJoPFmhEmjbM4YB9ePRpgYFT8dRNeZUOUd/8Yt7Pb6EVWOHvpD/w==} + /@nrwl/nx-cloud@18.0.0: + resolution: {integrity: sha512-rjjcJgzDmKwFD1QVIMs5O3X4SoMQIk0bzh3pL90ZP/B5YJUlTySv7+R0JoGQ6ROGwVQHjPFMVKKLB09zl5perA==} dependencies: - nx-cloud: 16.5.2 + nx-cloud: 18.0.0 transitivePeerDependencies: - debug dev: true - /@nrwl/tao@17.2.8: - resolution: {integrity: sha512-Qpk5YKeJ+LppPL/wtoDyNGbJs2MsTi6qyX/RdRrEc8lc4bk6Cw3Oul1qTXCI6jT0KzTz+dZtd0zYD/G7okkzvg==} + /@nrwl/tao@18.1.2: + resolution: {integrity: sha512-IA+osZ5TlKMwJmcP7TECW7TO0JdNNQud9Dgkh1ZfJ4GWnT7WEkE9b2Yf1IFeeB81kCTXXq8jfISa8ZY21MjRaQ==} hasBin: true dependencies: - nx: 17.2.8 + nx: 18.1.2 tslib: 2.6.2 transitivePeerDependencies: - '@swc-node/register' @@ -4316,8 +4302,8 @@ packages: - debug dev: true - /@nx/nx-darwin-arm64@17.2.8: - resolution: {integrity: sha512-dMb0uxug4hM7tusISAU1TfkDK3ixYmzc1zhHSZwpR7yKJIyKLtUpBTbryt8nyso37AS1yH+dmfh2Fj2WxfBHTg==} + /@nx/nx-darwin-arm64@18.1.2: + resolution: {integrity: sha512-KduC9WBmeTLP8HyTg4NOgQGLk9LEd5qd9dGuYKPU0jA4b+eJIa0rRHEjFdc5WulQrcUAvTIKfmScRCgzR96ogg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -4325,8 +4311,8 @@ packages: dev: true optional: true - /@nx/nx-darwin-x64@17.2.8: - resolution: {integrity: sha512-0cXzp1tGr7/6lJel102QiLA4NkaLCkQJj6VzwbwuvmuCDxPbpmbz7HC1tUteijKBtOcdXit1/MEoEU007To8Bw==} + /@nx/nx-darwin-x64@18.1.2: + resolution: {integrity: sha512-mBf3X8m4P4QHoW8g/L/YoK8zkndDyIw4bojLg8Q3xc47s5JZFCqSSMeOXZ9NicM2DpPiDWSQALtQX7A8lIsoAA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -4334,8 +4320,8 @@ packages: dev: true optional: true - /@nx/nx-freebsd-x64@17.2.8: - resolution: {integrity: sha512-YFMgx5Qpp2btCgvaniDGdu7Ctj56bfFvbbaHQWmOeBPK1krNDp2mqp8HK6ZKOfEuDJGOYAp7HDtCLvdZKvJxzA==} + /@nx/nx-freebsd-x64@18.1.2: + resolution: {integrity: sha512-ZqzT2BTsOHhWip1PvNm7AZ4Pzn4I+IZNRvtRgpETYvIH+nqoCmi5rrEi1avnhnr6P5hyzh2mISRSyk186SbZew==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] @@ -4343,8 +4329,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm-gnueabihf@17.2.8: - resolution: {integrity: sha512-iN2my6MrhLRkVDtdivQHugK8YmR7URo1wU9UDuHQ55z3tEcny7LV3W9NSsY9UYPK/FrxdDfevj0r2hgSSdhnzA==} + /@nx/nx-linux-arm-gnueabihf@18.1.2: + resolution: {integrity: sha512-V9Dp9uuuce+/f50dXxaYz1C9ULo5+5VS35yc6gN7b6SchCWjNK+xg1YcHBTRNc2ChBtayO2z+mBQ1s6wMDNs/Q==} engines: {node: '>= 10'} cpu: [arm] os: [linux] @@ -4352,8 +4338,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm64-gnu@17.2.8: - resolution: {integrity: sha512-Iy8BjoW6mOKrSMiTGujUcNdv+xSM1DALTH6y3iLvNDkGbjGK1Re6QNnJAzqcXyDpv32Q4Fc57PmuexyysZxIGg==} + /@nx/nx-linux-arm64-gnu@18.1.2: + resolution: {integrity: sha512-aM860T4Hy2JCLcU56mtARIp1MdT1Ms7cGUQzE+a5irM8ZdaHsPdRnYqIgEKd3hoF6PQ6/piHFXWa4xm7pe/2KA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -4361,8 +4347,8 @@ packages: dev: true optional: true - /@nx/nx-linux-arm64-musl@17.2.8: - resolution: {integrity: sha512-9wkAxWzknjpzdofL1xjtU6qPFF1PHlvKCZI3hgEYJDo4mQiatGI+7Ttko+lx/ZMP6v4+Umjtgq7+qWrApeKamQ==} + /@nx/nx-linux-arm64-musl@18.1.2: + resolution: {integrity: sha512-BgBoOeIgCQ56xii7fKNWiE7UIP/0G+OQhdWJQmh+q6NN0kk78WsdCSq+f7f7LQIji5HiNqUUVx9fd1s6xRSb/w==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -4370,8 +4356,8 @@ packages: dev: true optional: true - /@nx/nx-linux-x64-gnu@17.2.8: - resolution: {integrity: sha512-sjG1bwGsjLxToasZ3lShildFsF0eyeGu+pOQZIp9+gjFbeIkd19cTlCnHrOV9hoF364GuKSXQyUlwtFYFR4VTQ==} + /@nx/nx-linux-x64-gnu@18.1.2: + resolution: {integrity: sha512-WDOjtk+K2Tc9SNjGe+zmyy05VUerZpEQ5kvB6Ude0v/W2bMnmpVrLZwwTF5Yrq0ebbUlXM/9wtc1Zjjc75MU2g==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -4379,8 +4365,8 @@ packages: dev: true optional: true - /@nx/nx-linux-x64-musl@17.2.8: - resolution: {integrity: sha512-QiakXZ1xBCIptmkGEouLHQbcM4klQkcr+kEaz2PlNwy/sW3gH1b/1c0Ed5J1AN9xgQxWspriAONpScYBRgxdhA==} + /@nx/nx-linux-x64-musl@18.1.2: + resolution: {integrity: sha512-I7jTmbfR5CHC3KVlU3SkqYKJnn25MbH8pdRZJY4gaHnqL9JzbHw9rxddhKBj41lez7jQZTGLnPFUV7JPLXTzKg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -4388,8 +4374,8 @@ packages: dev: true optional: true - /@nx/nx-win32-arm64-msvc@17.2.8: - resolution: {integrity: sha512-XBWUY/F/GU3vKN9CAxeI15gM4kr3GOBqnzFZzoZC4qJt2hKSSUEWsMgeZtsMgeqEClbi4ZyCCkY7YJgU32WUGA==} + /@nx/nx-win32-arm64-msvc@18.1.2: + resolution: {integrity: sha512-KQobKvkrdkmaJmx0Pyt2lzHkNugO0gE7q9F4h22KIECyGW1tC3nSPAB4F3mmdE2KuWKgYG5WLafvzusysLsR7g==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -4397,8 +4383,8 @@ packages: dev: true optional: true - /@nx/nx-win32-x64-msvc@17.2.8: - resolution: {integrity: sha512-HTqDv+JThlLzbcEm/3f+LbS5/wYQWzb5YDXbP1wi7nlCTihNZOLNqGOkEmwlrR5tAdNHPRpHSmkYg4305W0CtA==} + /@nx/nx-win32-x64-msvc@18.1.2: + resolution: {integrity: sha512-uvJvROSwHBwkTOoOPkb56jEsKJjr4LnZ3fCHmEbrtGhAUC0gAUL+dWJUDHoatrGzN+bM2VqrvgNCGkityK96hw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -4608,10 +4594,10 @@ packages: envinfo: 7.11.0 execa: 5.1.1 hermes-profile-transformer: 0.0.6 - ip: 1.1.8 + ip: 1.1.9 node-stream-zip: 1.15.0 ora: 5.4.1 - semver: 7.5.4 + semver: 7.6.0 strip-ansi: 5.2.0 wcwidth: 1.0.1 yaml: 2.3.4 @@ -4626,7 +4612,7 @@ packages: '@react-native-community/cli-tools': 12.3.0 chalk: 4.1.2 hermes-profile-transformer: 0.0.6 - ip: 1.1.8 + ip: 1.1.9 transitivePeerDependencies: - encoding dev: true @@ -4690,7 +4676,7 @@ packages: node-fetch: 2.6.12 open: 6.4.0 ora: 5.4.1 - semver: 7.5.4 + semver: 7.6.0 shell-quote: 1.8.1 sudo-prompt: 9.2.1 transitivePeerDependencies: @@ -4725,7 +4711,7 @@ packages: fs-extra: 8.1.0 graceful-fs: 4.2.11 prompts: 2.4.2 - semver: 7.5.4 + semver: 7.6.0 transitivePeerDependencies: - bufferutil - encoding @@ -5116,13 +5102,13 @@ packages: '@noble/hashes': 1.3.2 '@scure/base': 1.1.3 - /@sentry-internal/tracing@7.94.1: - resolution: {integrity: sha512-znxCdrz7tPXm9Bwoe46PW72Zr0Iv7bXT6+b2LNg5fxWiCQVBbQFrMuVvtXEmHxeRRJVEgTh/4TdulB7wrtQIUQ==} + /@sentry-internal/tracing@7.99.0: + resolution: {integrity: sha512-z3JQhHjoM1KdM20qrHwRClKJrNLr2CcKtCluq7xevLtXHJWNAQQbafnWD+Aoj85EWXBzKt9yJMv2ltcXJ+at+w==} engines: {node: '>=8'} dependencies: - '@sentry/core': 7.94.1 - '@sentry/types': 7.94.1 - '@sentry/utils': 7.94.1 + '@sentry/core': 7.99.0 + '@sentry/types': 7.99.0 + '@sentry/utils': 7.99.0 dev: false /@sentry/core@5.30.0: @@ -5136,12 +5122,12 @@ packages: tslib: 1.14.1 dev: true - /@sentry/core@7.94.1: - resolution: {integrity: sha512-4sjiMnkbGpv9O98YHVZe7fHNwwdYl+zLoCOoEOadtrJ1EYYvnK/MSixN2HJF7g/0s22xd4xY958QyNIRVR+Iiw==} + /@sentry/core@7.99.0: + resolution: {integrity: sha512-vOAtzcAXEUtS/oW7wi3wMkZ3hsb5Ch96gKyrrj/mXdOp2zrcwdNV6N9/pawq2E9P/7Pw8AXw4CeDZztZrjQLuA==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.94.1 - '@sentry/utils': 7.94.1 + '@sentry/types': 7.99.0 + '@sentry/utils': 7.99.0 dev: false /@sentry/hub@5.30.0: @@ -5179,14 +5165,14 @@ packages: - supports-color dev: true - /@sentry/node@7.94.1: - resolution: {integrity: sha512-30nyrfVbY1vNoWg5ptGW+soykU532VvKLuXiKty3SKEXjp5bv23JrCcVtuwp9KrW4josHOJbxZUqeNni85YplQ==} + /@sentry/node@7.99.0: + resolution: {integrity: sha512-34wYtLddnPcQ8qvKq62AfxowaMFw+GMUZGv7fIs9FxeBqqqn6Ckl0gFCTADudIIBQ3rSbmN7sHJIXdyiQv+pcw==} engines: {node: '>=8'} dependencies: - '@sentry-internal/tracing': 7.94.1 - '@sentry/core': 7.94.1 - '@sentry/types': 7.94.1 - '@sentry/utils': 7.94.1 + '@sentry-internal/tracing': 7.99.0 + '@sentry/core': 7.99.0 + '@sentry/types': 7.99.0 + '@sentry/utils': 7.99.0 dev: false /@sentry/tracing@5.30.0: @@ -5205,8 +5191,8 @@ packages: engines: {node: '>=6'} dev: true - /@sentry/types@7.94.1: - resolution: {integrity: sha512-A7CdEXFSgGyWv2BT2p9cAvJfb+dypvOtsY8ZvZvdPLUa7kqCV7ndhURUqKjvMBzsL2GParHn3ehDTl2eVc7pvA==} + /@sentry/types@7.99.0: + resolution: {integrity: sha512-94qwOw4w40sAs5mCmzcGyj8ZUu/KhnWnuMZARRq96k+SjRW/tHFAOlIdnFSrt3BLPvSOK7R3bVAskZQ0N4FTmA==} engines: {node: '>=8'} dev: false @@ -5218,11 +5204,11 @@ packages: tslib: 1.14.1 dev: true - /@sentry/utils@7.94.1: - resolution: {integrity: sha512-gQ2EaMpUU1gGH3S+iqpog9gkXbCo8tlhGYA9a5FUtEtER3D3OAlp8dGFwClwzWDAwzjdLT1+X55zmEptU1cP/A==} + /@sentry/utils@7.99.0: + resolution: {integrity: sha512-cYZy5WNTkWs5GgggGnjfGqC44CWir0pAv4GVVSx0fsup4D4pMKBJPrtub15f9uC+QkUf3vVkqwpBqeFxtmJQTQ==} engines: {node: '>=8'} dependencies: - '@sentry/types': 7.94.1 + '@sentry/types': 7.99.0 dev: false /@sideway/address@4.1.4: @@ -5387,8 +5373,8 @@ packages: '@stablelib/wipe': 1.0.1 dev: true - /@swc/core-darwin-arm64@1.3.104: - resolution: {integrity: sha512-rCnVj8x3kn6s914Adddu+zROHUn6mUEMkNKUckofs3W9OthNlZXJA3C5bS2MMTRFXCWamJ0Zmh6INFpz+f4Tfg==} + /@swc/core-darwin-arm64@1.4.6: + resolution: {integrity: sha512-bpggpx/BfLFyy48aUKq1PsNUxb7J6CINlpAUk0V4yXfmGnpZH80Gp1pM3GkFDQyCfq7L7IpjPrIjWQwCrL4hYw==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] @@ -5396,8 +5382,8 @@ packages: dev: true optional: true - /@swc/core-darwin-x64@1.3.104: - resolution: {integrity: sha512-LBCWGTYkn1UjyxrmcLS3vZgtCDVhwxsQMV7jz5duc7Gas8SRWh6ZYqvUkjlXMDX1yx0uvzHrkaRw445+zDRj7Q==} + /@swc/core-darwin-x64@1.4.6: + resolution: {integrity: sha512-vJn+/ZuBTg+vtNkcmgZdH6FQpa0hFVdnB9bAeqYwKkyqP15zaPe6jfC+qL2y/cIeC7ASvHXEKrnCZgBLxfVQ9w==} engines: {node: '>=10'} cpu: [x64] os: [darwin] @@ -5405,8 +5391,8 @@ packages: dev: true optional: true - /@swc/core-linux-arm-gnueabihf@1.3.104: - resolution: {integrity: sha512-iFbsWcx0TKHWnFBNCuUstYqRtfkyBx7FKv5To1Hx14EMuvvoCD/qUoJEiNfDQN5n/xU9g5xq4RdbjEWCFLhAbA==} + /@swc/core-linux-arm-gnueabihf@1.4.6: + resolution: {integrity: sha512-hEmYcB/9XBAl02MtuVHszhNjQpjBzhk/NFulnU33tBMbNZpy2TN5yTsitezMq090QXdDz8sKIALApDyg07ZR8g==} engines: {node: '>=10'} cpu: [arm] os: [linux] @@ -5414,8 +5400,8 @@ packages: dev: true optional: true - /@swc/core-linux-arm64-gnu@1.3.104: - resolution: {integrity: sha512-1BIIp+nUPrRHHaJ35YJqrwXPwYSITp5robqqjyTwoKGw2kq0x+A964kpWul6v0d7A9Ial8fyH4m13eSWBodD2A==} + /@swc/core-linux-arm64-gnu@1.4.6: + resolution: {integrity: sha512-/UCYIVoGpm2YVvGHZM2QOA3dexa28BjcpLAIYnoCbgH5f7ulDhE8FAIO/9pasj+kixDBsdqewHfsNXFYlgGJjQ==} engines: {node: '>=10'} cpu: [arm64] os: [linux] @@ -5423,8 +5409,8 @@ packages: dev: true optional: true - /@swc/core-linux-arm64-musl@1.3.104: - resolution: {integrity: sha512-IyDNkzpKwvLqmRwTW+s8f8OsOSSj1N6juZKbvNHpZRfWZkz3T70q3vJlDBWQwy8z8cm7ckd7YUT3eKcSBPPowg==} + /@swc/core-linux-arm64-musl@1.4.6: + resolution: {integrity: sha512-LGQsKJ8MA9zZ8xHCkbGkcPSmpkZL2O7drvwsGKynyCttHhpwVjj9lguhD4DWU3+FWIsjvho5Vu0Ggei8OYi/Lw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] @@ -5432,8 +5418,8 @@ packages: dev: true optional: true - /@swc/core-linux-x64-gnu@1.3.104: - resolution: {integrity: sha512-MfX/wiRdTjE5uXHTDnaX69xI4UBfxIhcxbVlMj//N+7AX/G2pl2UFityfVMU2HpM12BRckrCxVI8F/Zy3DZkYQ==} + /@swc/core-linux-x64-gnu@1.4.6: + resolution: {integrity: sha512-10JL2nLIreMQDKvq2TECnQe5fCuoqBHu1yW8aChqgHUyg9d7gfZX/kppUsuimqcgRBnS0AjTDAA+JF6UsG/2Yg==} engines: {node: '>=10'} cpu: [x64] os: [linux] @@ -5441,8 +5427,8 @@ packages: dev: true optional: true - /@swc/core-linux-x64-musl@1.3.104: - resolution: {integrity: sha512-5yeILaxA31gGEmquErO8yxlq1xu0XVt+fz5mbbKXKZMRRILxYxNzAGb5mzV41r0oHz6Vhv4AXX/WMCmeWl+HkQ==} + /@swc/core-linux-x64-musl@1.4.6: + resolution: {integrity: sha512-EGyjFVzVY6Do89x8sfah7I3cuP4MwtwzmA6OlfD/KASqfCFf5eIaEBMbajgR41bVfMV7lK72lwAIea5xEyq1AQ==} engines: {node: '>=10'} cpu: [x64] os: [linux] @@ -5450,8 +5436,8 @@ packages: dev: true optional: true - /@swc/core-win32-arm64-msvc@1.3.104: - resolution: {integrity: sha512-rwcImsYnWDWGmeESG0XdGGOql5s3cG5wA8C4hHHKdH76zamPfDKKQFBsjmoNi0f1IsxaI9AJPeOmD4bAhT1ZoQ==} + /@swc/core-win32-arm64-msvc@1.4.6: + resolution: {integrity: sha512-gfW9AuXvwSyK07Vb8Y8E9m2oJZk21WqcD+X4BZhkbKB0TCZK0zk1j/HpS2UFlr1JB2zPKPpSWLU3ll0GEHRG2A==} engines: {node: '>=10'} cpu: [arm64] os: [win32] @@ -5459,8 +5445,8 @@ packages: dev: true optional: true - /@swc/core-win32-ia32-msvc@1.3.104: - resolution: {integrity: sha512-ICDA+CJLYC7NkePnrbh/MvXwDQfy3rZSFgrVdrqRosv9DKHdFjYDnA9++7ozjrIdFdBrFW2NR7pyUcidlwhNzA==} + /@swc/core-win32-ia32-msvc@1.4.6: + resolution: {integrity: sha512-ZuQm81FhhvNVYtVb9GfZ+Du6e7fZlkisWvuCeBeRiyseNt1tcrQ8J3V67jD2nxje8CVXrwG3oUIbPcybv2rxfQ==} engines: {node: '>=10'} cpu: [ia32] os: [win32] @@ -5468,8 +5454,8 @@ packages: dev: true optional: true - /@swc/core-win32-x64-msvc@1.3.104: - resolution: {integrity: sha512-fZJ1Ju62U4lMZVU+nHxLkFNcu0hG5Y0Yj/5zjrlbuX5N8J5eDndWAFsVnQhxRTZqKhZB53pvWRQs5FItSDqgXg==} + /@swc/core-win32-x64-msvc@1.4.6: + resolution: {integrity: sha512-UagPb7w5V0uzWSjrXwOavGa7s9iv3wrVdEgWy+/inm0OwY4lj3zpK9qDnMWAwYLuFwkI3UG4Q3dH8wD+CUUcjw==} engines: {node: '>=10'} cpu: [x64] os: [win32] @@ -5477,8 +5463,8 @@ packages: dev: true optional: true - /@swc/core@1.3.104: - resolution: {integrity: sha512-9LWH/qzR/Pmyco+XwPiPfz59T1sryI7o5dmqb593MfCkaX5Fzl9KhwQTI47i21/bXYuCdfa9ySZuVkzXMirYxA==} + /@swc/core@1.4.6: + resolution: {integrity: sha512-A7iK9+1qzTCIuc3IYcS8gPHCm9bZVKUJrfNnwveZYyo6OFp3jLno4WOM2yBy5uqedgYATEiWgBYHKq37KrU6IA==} engines: {node: '>=10'} requiresBuild: true peerDependencies: @@ -5487,23 +5473,23 @@ packages: '@swc/helpers': optional: true dependencies: - '@swc/counter': 0.1.1 + '@swc/counter': 0.1.3 '@swc/types': 0.1.5 optionalDependencies: - '@swc/core-darwin-arm64': 1.3.104 - '@swc/core-darwin-x64': 1.3.104 - '@swc/core-linux-arm-gnueabihf': 1.3.104 - '@swc/core-linux-arm64-gnu': 1.3.104 - '@swc/core-linux-arm64-musl': 1.3.104 - '@swc/core-linux-x64-gnu': 1.3.104 - '@swc/core-linux-x64-musl': 1.3.104 - '@swc/core-win32-arm64-msvc': 1.3.104 - '@swc/core-win32-ia32-msvc': 1.3.104 - '@swc/core-win32-x64-msvc': 1.3.104 + '@swc/core-darwin-arm64': 1.4.6 + '@swc/core-darwin-x64': 1.4.6 + '@swc/core-linux-arm-gnueabihf': 1.4.6 + '@swc/core-linux-arm64-gnu': 1.4.6 + '@swc/core-linux-arm64-musl': 1.4.6 + '@swc/core-linux-x64-gnu': 1.4.6 + '@swc/core-linux-x64-musl': 1.4.6 + '@swc/core-win32-arm64-msvc': 1.4.6 + '@swc/core-win32-ia32-msvc': 1.4.6 + '@swc/core-win32-x64-msvc': 1.4.6 dev: true - /@swc/counter@0.1.1: - resolution: {integrity: sha512-xVRaR4u9hcYjFvcSg71Lz5Bo4//CyjAAfMxa7UsaDSYxAshflUkVJWiyVWrfxC59z2kP1IzI4/1BEpnhI9o3Mw==} + /@swc/counter@0.1.3: + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} dev: true /@swc/types@0.1.5: @@ -5537,8 +5523,8 @@ packages: pretty-format: 27.5.1 dev: false - /@testing-library/jest-dom@6.2.1(vitest@1.0.1): - resolution: {integrity: sha512-Nuy/uFFDe9h/2jwoUuMKgoxvgkUv4S9jI9bARj6dGUKJ3euRhg8JFi5sciYbrayoxkadEOZednRT9+vo6LvvxQ==} + /@testing-library/jest-dom@6.4.2(vitest@1.2.2): + resolution: {integrity: sha512-CzqH0AFymEMG48CpzXFriYYkOjk6ZGPCLMhW9e9jg3KMCn5OfJecF8GtGW7yGfR/IgCe3SX8BSwjdzI6BBbZLw==} engines: {node: '>=14', npm: '>=6', yarn: '>=1'} peerDependencies: '@jest/globals': '>= 28' @@ -5566,7 +5552,7 @@ packages: dom-accessibility-api: 0.6.3 lodash: 4.17.21 redent: 3.0.0 - vitest: 1.0.1(@types/node@20.11.5)(jsdom@23.2.0) + vitest: 1.2.2(@types/node@20.11.17)(jsdom@24.0.0) dev: true /@testing-library/react-hooks@8.0.1(react-dom@18.2.0)(react@18.2.0): @@ -5612,14 +5598,14 @@ packages: react-error-boundary: 3.1.4(react@17.0.2) dev: true - /@testing-library/react@14.1.2(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-z4p7DVBTPjKM5qDZ0t5ZjzkpSNb+fZy1u6bzO7kk8oeGagpPCAtgh4cx1syrfp7a+QWkM021jGqjJaxJJnXAZg==} + /@testing-library/react@14.2.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-sGdjws32ai5TLerhvzThYFbpnF9XtL65Cjf+gB0Dhr29BGqK+mAeN7SURSdu+eqgET4ANcWoC7FQpkaiGvBr+A==} engines: {node: '>=14'} peerDependencies: react: ^18.0.0 react-dom: ^18.0.0 dependencies: - '@babel/runtime': 7.22.6 + '@babel/runtime': 7.23.7 '@testing-library/dom': 9.3.1 '@types/react-dom': 18.2.7 react: 18.2.0 @@ -5707,20 +5693,20 @@ packages: /@types/bn.js@4.11.6: resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 dev: true /@types/bn.js@5.1.0: resolution: {integrity: sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 dev: true /@types/body-parser@1.19.1: resolution: {integrity: sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==} dependencies: '@types/connect': 3.4.35 - '@types/node': 20.11.5 + '@types/node': 20.11.17 /@types/chai-as-promised@7.1.8: resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} @@ -5749,14 +5735,14 @@ packages: /@types/connect@3.4.35: resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 /@types/dateformat@5.0.0: resolution: {integrity: sha512-SZg4JdHIWHQGEokbYGZSDvo5wA4TLYPXaqhigs/wH+REDOejcJzgH+qyY+HtEUtWOZxEUkbhbdYPqQDiEgrXeA==} dev: false - /@types/debug@4.1.8: - resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==} + /@types/debug@4.1.12: + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} dependencies: '@types/ms': 0.7.31 dev: true @@ -5765,10 +5751,14 @@ packages: resolution: {integrity: sha512-3Iten7X3Zgwvk6kh6/NRdwN7WbZ760YgFCsF5AxDifltUQzW1RaW+WRmcVtgwFzLjaNu64H+0MPJ13yRa8g3Dw==} dev: true + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + /@types/express-serve-static-core@4.17.35: resolution: {integrity: sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 '@types/qs': 6.9.7 '@types/range-parser': 1.2.4 '@types/send': 0.17.1 @@ -5795,7 +5785,7 @@ packages: resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==} dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.10.8 + '@types/node': 20.11.16 dev: true /@types/har-format@1.2.15: @@ -5836,7 +5826,7 @@ packages: dependencies: '@types/abstract-leveldown': 5.0.2 '@types/level-errors': 3.0.0 - '@types/node': 20.11.5 + '@types/node': 20.11.17 dev: true /@types/lru-cache@5.1.1: @@ -5867,7 +5857,7 @@ packages: /@types/mkdirp@0.5.2: resolution: {integrity: sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 dev: true /@types/mocha@10.0.6: @@ -5877,7 +5867,7 @@ packages: /@types/morgan@1.9.9: resolution: {integrity: sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==} dependencies: - '@types/node': 20.10.8 + '@types/node': 20.11.16 dev: true /@types/ms@0.7.31: @@ -5887,7 +5877,7 @@ packages: /@types/node-fetch@2.6.4: resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 form-data: 3.0.1 dev: true @@ -5899,14 +5889,14 @@ packages: resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} dev: false - /@types/node@20.10.8: - resolution: {integrity: sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==} + /@types/node@20.11.16: + resolution: {integrity: sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==} dependencies: undici-types: 5.26.5 dev: true - /@types/node@20.11.5: - resolution: {integrity: sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==} + /@types/node@20.11.17: + resolution: {integrity: sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==} dependencies: undici-types: 5.26.5 @@ -5920,7 +5910,7 @@ packages: /@types/pbkdf2@3.1.0: resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 dev: true /@types/pino-multi-stream@5.1.6: @@ -5938,13 +5928,13 @@ packages: /@types/pino-std-serializers@2.4.1: resolution: {integrity: sha512-17XcksO47M24IVTVKPeAByWUd3Oez7EbIjXpSbzMPhXVzgjGtrOa49gKBwxH9hb8dKv58OelsWQ+A1G1l9S3wQ==} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 dev: true /@types/pino@6.3.11: resolution: {integrity: sha512-S7+fLONqSpHeW9d7TApUqO6VN47KYgOXhCNKwGBVLHObq8HhaAYlVqUNdfnvoXjCMiwE5xcPm/5R2ZUh8bgaXQ==} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 '@types/pino-pretty': 4.7.1 '@types/pino-std-serializers': 2.4.1 sonic-boom: 2.8.0 @@ -5954,7 +5944,7 @@ packages: resolution: {integrity: sha512-wKoab31pknvILkxAF8ss+v9iNyhw5Iu/0jLtRkUD74cNfOOLJNnqfFKAv0r7wVaTQxRZtWrMpGfShwwBjOcgcg==} deprecated: This is a stub types definition. pino provides its own type definitions, so you do not need this installed. dependencies: - pino: 8.17.2 + pino: 8.19.0 dev: true /@types/prettier@2.3.2: @@ -5988,7 +5978,7 @@ packages: /@types/readable-stream@2.3.15: resolution: {integrity: sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 safe-buffer: 5.1.2 dev: true @@ -5999,27 +5989,27 @@ packages: /@types/secp256k1@4.0.6: resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 dev: true /@types/seedrandom@3.0.1: resolution: {integrity: sha512-giB9gzDeiCeloIXDgzFBCgjj1k4WxcDrZtGl6h1IqmUPlxF+Nx8Ve+96QCyDZ/HseB/uvDsKbpib9hU5cU53pw==} dev: true - /@types/semver@7.5.0: - resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} + /@types/semver@7.5.7: + resolution: {integrity: sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==} /@types/send@0.17.1: resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==} dependencies: '@types/mime': 1.3.2 - '@types/node': 20.11.5 + '@types/node': 20.11.17 /@types/serve-static@1.13.10: resolution: {integrity: sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==} dependencies: '@types/mime': 1.3.2 - '@types/node': 20.11.5 + '@types/node': 20.11.17 /@types/sinon-chai@3.2.5: resolution: {integrity: sha512-bKQqIpew7mmIGNRlxW6Zli/QVyc3zikpGzCa797B/tRnD9OtHvZ/ts8sYXV+Ilj9u3QRaUEM8xrjgd1gwm1BpQ==} @@ -6060,7 +6050,7 @@ packages: /@types/ws@8.5.3: resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 dev: false /@types/yargs-parser@21.0.3: @@ -6079,8 +6069,8 @@ packages: '@types/yargs-parser': 21.0.3 dev: true - /@typescript-eslint/eslint-plugin@6.19.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==} + /@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -6091,25 +6081,25 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.6.2 - '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/scope-manager': 6.19.1 - '@typescript-eslint/type-utils': 6.19.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/utils': 6.19.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 6.19.1 + '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/type-utils': 6.21.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.21.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.21.0 debug: 4.3.4(supports-color@8.1.1) eslint: 8.56.0 graphemer: 1.4.0 ignore: 5.2.4 natural-compare: 1.4.0 - semver: 7.5.4 + semver: 7.6.0 ts-api-utils: 1.0.1(typescript@5.3.3) typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==} + /@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -6118,10 +6108,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.19.1 - '@typescript-eslint/types': 6.19.1 - '@typescript-eslint/typescript-estree': 6.19.1(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 6.19.1 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.21.0 debug: 4.3.4(supports-color@8.1.1) eslint: 8.56.0 typescript: 5.3.3 @@ -6129,16 +6119,16 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager@6.19.1: - resolution: {integrity: sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==} + /@typescript-eslint/scope-manager@6.21.0: + resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.19.1 - '@typescript-eslint/visitor-keys': 6.19.1 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 dev: true - /@typescript-eslint/type-utils@6.19.1(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==} + /@typescript-eslint/type-utils@6.21.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -6147,8 +6137,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.19.1(typescript@5.3.3) - '@typescript-eslint/utils': 6.19.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) + '@typescript-eslint/utils': 6.21.0(eslint@8.56.0)(typescript@5.3.3) debug: 4.3.4(supports-color@8.1.1) eslint: 8.56.0 ts-api-utils: 1.0.1(typescript@5.3.3) @@ -6157,13 +6147,13 @@ packages: - supports-color dev: true - /@typescript-eslint/types@6.19.1: - resolution: {integrity: sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==} + /@typescript-eslint/types@6.21.0: + resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@6.19.1(typescript@5.3.3): - resolution: {integrity: sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==} + /@typescript-eslint/typescript-estree@6.21.0(typescript@5.3.3): + resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -6171,43 +6161,43 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.19.1 - '@typescript-eslint/visitor-keys': 6.19.1 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 - semver: 7.5.4 + semver: 7.6.0 ts-api-utils: 1.0.1(typescript@5.3.3) typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils@6.19.1(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==} + /@typescript-eslint/utils@6.21.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@types/json-schema': 7.0.12 - '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 6.19.1 - '@typescript-eslint/types': 6.19.1 - '@typescript-eslint/typescript-estree': 6.19.1(typescript@5.3.3) + '@types/semver': 7.5.7 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) eslint: 8.56.0 - semver: 7.5.4 + semver: 7.6.0 transitivePeerDependencies: - supports-color - typescript dev: true - /@typescript-eslint/visitor-keys@6.19.1: - resolution: {integrity: sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==} + /@typescript-eslint/visitor-keys@6.21.0: + resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.19.1 + '@typescript-eslint/types': 6.21.0 eslint-visitor-keys: 3.4.3 dev: true @@ -6215,8 +6205,8 @@ packages: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} dev: true - /@vitest/coverage-istanbul@1.2.1(vitest@1.0.1): - resolution: {integrity: sha512-j8M4R3XbQ7cmLqJd7mfxCpEc0bQ7S6o5VIEt7c0Auri2lT1hkd89Sa/mOYDnuGasTNawamW+0d9vDRK/5uhVXw==} + /@vitest/coverage-istanbul@1.2.2(vitest@1.2.2): + resolution: {integrity: sha512-tJybwO8JT4H9ANz0T0/tJ1M5g3BkuHKYF1w5YO3z9sAiHBdGANrxN9c5lomJx1WSnLzCxQR5xxlJ4TLKbzrR3w==} peerDependencies: vitest: ^1.0.0 dependencies: @@ -6229,45 +6219,46 @@ packages: magicast: 0.3.3 picocolors: 1.0.0 test-exclude: 6.0.0 - vitest: 1.0.1(@types/node@20.11.5)(jsdom@23.2.0) + vitest: 1.2.2(@types/node@20.11.17)(jsdom@24.0.0) transitivePeerDependencies: - supports-color dev: true - /@vitest/expect@1.0.1: - resolution: {integrity: sha512-3cdrb/eKD/0tygDX75YscuHEHMUJ70u3UoLSq2eqhWks57AyzvsDQbyn53IhZ0tBN7gA8Jj2VhXiOV2lef7thw==} + /@vitest/expect@1.2.2: + resolution: {integrity: sha512-3jpcdPAD7LwHUUiT2pZTj2U82I2Tcgg2oVPvKxhn6mDI2On6tfvPQTjAI4628GUGDZrCm4Zna9iQHm5cEexOAg==} dependencies: - '@vitest/spy': 1.0.1 - '@vitest/utils': 1.0.1 + '@vitest/spy': 1.2.2 + '@vitest/utils': 1.2.2 chai: 4.3.10 dev: true - /@vitest/runner@1.0.1: - resolution: {integrity: sha512-/+z0vhJ0MfRPT3AyTvAK6m57rzlew/ct8B2a4LMv7NhpPaiI2QLGyOBMB3lcioWdJHjRuLi9aYppfOv0B5aRQA==} + /@vitest/runner@1.2.2: + resolution: {integrity: sha512-JctG7QZ4LSDXr5CsUweFgcpEvrcxOV1Gft7uHrvkQ+fsAVylmWQvnaAr/HDp3LAH1fztGMQZugIheTWjaGzYIg==} dependencies: - '@vitest/utils': 1.0.1 + '@vitest/utils': 1.2.2 p-limit: 5.0.0 pathe: 1.1.1 dev: true - /@vitest/snapshot@1.0.1: - resolution: {integrity: sha512-wIPtPDGSxEZ+DpNMc94AsybX6LV6uN6sosf5TojyP1m2QbKwiRuLV/5RSsjt1oWViHsTj8mlcwrQQ1zHGO0fMw==} + /@vitest/snapshot@1.2.2: + resolution: {integrity: sha512-SmGY4saEw1+bwE1th6S/cZmPxz/Q4JWsl7LvbQIky2tKE35US4gd0Mjzqfr84/4OD0tikGWaWdMja/nWL5NIPA==} dependencies: magic-string: 0.30.5 pathe: 1.1.1 pretty-format: 29.7.0 dev: true - /@vitest/spy@1.0.1: - resolution: {integrity: sha512-yXwm1uKhBVr/5MhVeSmtNqK+0q2RXIchJt8kokEKdrWLtkPeDgdbZ6SjR1VQGZuNdWL6sSBnLayIyVvcS0qLfA==} + /@vitest/spy@1.2.2: + resolution: {integrity: sha512-k9Gcahssw8d7X3pSLq3e3XEu/0L78mUkCjivUqCQeXJm9clfXR/Td8+AP+VC1O6fKPIDLcHDTAmBOINVuv6+7g==} dependencies: tinyspy: 2.2.0 dev: true - /@vitest/utils@1.0.1: - resolution: {integrity: sha512-MGPCHkzXbbAyscrhwGzh8uP1HPrTYLWaj1WTDtWSGrpe2yJWLRN9mF9ooKawr6NMOg9vTBtg2JqWLfuLC7Dknw==} + /@vitest/utils@1.2.2: + resolution: {integrity: sha512-WKITBHLsBHlpjnDQahr+XK6RE7MiAsgrIkr0pGhQ9ygoxBfUeG0lUG5iLlzqjmKSlBv3+j5EGsriBzh+C3Tq9g==} dependencies: diff-sequences: 29.6.3 + estree-walker: 3.0.3 loupe: 2.3.7 pretty-format: 29.7.0 dev: true @@ -6299,7 +6290,7 @@ packages: '@vue/shared': 3.3.4 estree-walker: 2.0.2 magic-string: 0.30.5 - postcss: 8.4.32 + postcss: 8.4.35 source-map-js: 1.0.2 dev: true @@ -6324,11 +6315,11 @@ packages: resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} dev: true - /@wagmi/cli@2.0.4(typescript@5.3.3): - resolution: {integrity: sha512-JcIp46LUrhctEpMMNalFVX8Uua6Wv9875w8x3cRZlGF9nVLT3GigJVpRrgPCinY+Qn+m592rFCnpueS7FZbOiQ==} + /@wagmi/cli@2.1.2(typescript@5.3.3): + resolution: {integrity: sha512-gJLjPDD+xc7IN6OJYQdOl3xhfnf7nXZoaELCchNo9Pt+1hUVFYq2uC4HGBXYvUQ03RJNmZca1X8qP8pJeuJFYA==} hasBin: true peerDependencies: - typescript: '>=5' + typescript: '>=5.0.4' peerDependenciesMeta: typescript: optional: true @@ -6339,29 +6330,29 @@ packages: change-case: 4.1.2 chokidar: 3.5.3 dedent: 0.7.0 - dotenv: 16.3.1 + dotenv: 16.4.5 dotenv-expand: 10.0.0 esbuild: 0.19.10 - execa: 6.1.0 + execa: 8.0.1 find-up: 6.3.0 - fs-extra: 10.1.0 + fs-extra: 11.1.1 globby: 13.2.2 ora: 6.3.1 pathe: 1.1.1 picocolors: 1.0.0 prettier: 3.1.1 typescript: 5.3.3 - viem: 2.0.0(typescript@5.3.3)(zod@3.22.4) + viem: 2.7.19(typescript@5.3.3)(zod@3.22.4) zod: 3.22.4 transitivePeerDependencies: - bufferutil - utf-8-validate dev: true - /@wagmi/connectors@4.1.4(@wagmi/core@2.2.1)(react-dom@18.2.0)(react-native@0.73.1)(react@18.2.0)(typescript@5.3.3)(viem@2.0.3): - resolution: {integrity: sha512-Mk/JnVs9pPd9cN/b5F+kHZMRU13yVf1zJwXNzSKpt7BOJQBqiFxJtmuZdRsNboEGEiPDFoEnzOzeAFi2xk3UGw==} + /@wagmi/connectors@4.1.12(@wagmi/core@2.6.3)(react-dom@18.2.0)(react-native@0.73.1)(react@18.2.0)(typescript@5.3.3)(viem@2.7.19): + resolution: {integrity: sha512-zqCJMOwpi8ssFjndVxVh3iUMwzcA7dPCjswhcy4xZyy1jm/VvGYC3o1wotq/gTCqUrz0SPIMGimZm4S6865b8A==} peerDependencies: - '@wagmi/core': 2.2.1 + '@wagmi/core': 2.6.3 typescript: '>=5.0.4' viem: 2.x peerDependenciesMeta: @@ -6372,11 +6363,11 @@ packages: '@metamask/sdk': 0.14.1(react-dom@18.2.0)(react-native@0.73.1)(react@18.2.0) '@safe-global/safe-apps-provider': 0.18.1(typescript@5.3.3) '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.3.3) - '@wagmi/core': 2.2.1(react@18.2.0)(typescript@5.3.3)(viem@2.0.3) + '@wagmi/core': 2.6.3(react@18.2.0)(typescript@5.3.3)(viem@2.7.19) '@walletconnect/ethereum-provider': 2.11.0(react@18.2.0) '@walletconnect/modal': 2.6.2(react@18.2.0) typescript: 5.3.3 - viem: 2.0.3(typescript@5.3.3)(zod@3.22.4) + viem: 2.7.19(typescript@5.3.3)(zod@3.22.4) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -6402,34 +6393,8 @@ packages: - zod dev: true - /@wagmi/core@2.2.1(react@18.2.0)(typescript@5.3.3)(viem@2.0.3): - resolution: {integrity: sha512-eoTHG600lFpQyeofuo1nlAuTlI7rjduJK/yU4F8sLwjucROSE5RmD2OpQOkeEC3JGoXjrYxVPbY77PUD6ajzqw==} - peerDependencies: - '@tanstack/query-core': '>=5.0.0' - typescript: '>=5.0.4' - viem: 2.x - peerDependenciesMeta: - '@tanstack/query-core': - optional: true - typescript: - optional: true - dependencies: - eventemitter3: 5.0.1 - mipd: 0.0.5(typescript@5.3.3) - typescript: 5.3.3 - viem: 2.0.3(typescript@5.3.3)(zod@3.22.4) - zustand: 4.4.1(react@18.2.0) - transitivePeerDependencies: - - '@types/react' - - bufferutil - - immer - - react - - utf-8-validate - - zod - dev: true - - /@wagmi/core@2.3.1(react@18.2.0)(typescript@5.3.3)(viem@2.0.3): - resolution: {integrity: sha512-vpD5el6E8s2gmTDFPr1ghRuQCBTe45QSOSxAPkImCXWXiAh4xoCfwPH8lBUBpRJouu2eVBPVaCpGQNGO8yD1xw==} + /@wagmi/core@2.6.3(react@18.2.0)(typescript@5.3.3)(viem@2.7.19): + resolution: {integrity: sha512-hHvJkXFqfj56nAD0SH5bAHYxBItUBDIn6yGUBguMu121v6R4NxhwciEeff56lSjnKhmXjaWdJCEJ9C1YwkmDVw==} peerDependencies: '@tanstack/query-core': '>=5.0.0' typescript: '>=5.0.4' @@ -6443,7 +6408,7 @@ packages: eventemitter3: 5.0.1 mipd: 0.0.5(typescript@5.3.3) typescript: 5.3.3 - viem: 2.0.3(typescript@5.3.3)(zod@3.22.4) + viem: 2.7.19(typescript@5.3.3)(zod@3.22.4) zustand: 4.4.1(react@18.2.0) transitivePeerDependencies: - '@types/react' @@ -6840,11 +6805,11 @@ packages: argparse: 2.0.1 dev: true - /abitype@0.10.0(typescript@5.3.3)(zod@3.22.4): - resolution: {integrity: sha512-QvMHEUzgI9nPj9TWtUGnS2scas80/qaL5PBxGdwWhhvzqXfOph+IEiiiWrzuisu3U3JgDQVruW9oLbJoQ3oZ3A==} + /abitype@0.9.8(typescript@5.3.3)(zod@3.22.4): + resolution: {integrity: sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ==} peerDependencies: typescript: '>=5.0.4' - zod: ^3 >=3.22.0 + zod: ^3 >=3.19.1 peerDependenciesMeta: typescript: optional: true @@ -6853,9 +6818,10 @@ packages: dependencies: typescript: 5.3.3 zod: 3.22.4 + dev: true - /abitype@0.10.3(typescript@5.3.3): - resolution: {integrity: sha512-tRN+7XIa7J9xugdbRzFv/95ka5ivR/sRe01eiWvM0HWWjHuigSZEACgKa0sj4wGuekTDtghCx+5Izk/cOi78pQ==} + /abitype@1.0.0(typescript@5.3.3)(zod@3.22.4): + resolution: {integrity: sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ==} peerDependencies: typescript: '>=5.0.4' zod: ^3 >=3.22.0 @@ -6866,13 +6832,13 @@ packages: optional: true dependencies: typescript: 5.3.3 - dev: true + zod: 3.22.4 - /abitype@0.9.8(typescript@5.3.3)(zod@3.22.4): - resolution: {integrity: sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ==} + /abitype@1.0.2(typescript@5.3.3): + resolution: {integrity: sha512-aFt4k2H+eiAKy/zxtnORa9iIb10BMBeWL18l8v4+QuwYEBXPxxjSB1bFZCzQmKPoj8m7j68K705l3uY+E2gAjg==} peerDependencies: typescript: '>=5.0.4' - zod: ^3 >=3.19.1 + zod: ^3 >=3.22.0 peerDependenciesMeta: typescript: optional: true @@ -6880,7 +6846,6 @@ packages: optional: true dependencies: typescript: 5.3.3 - zod: 3.22.4 dev: true /abort-controller@3.0.0: @@ -6889,19 +6854,6 @@ packages: dependencies: event-target-shim: 5.0.1 - /abstract-level@1.0.3: - resolution: {integrity: sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA==} - engines: {node: '>=12'} - dependencies: - buffer: 6.0.3 - catering: 2.1.1 - is-buffer: 2.0.5 - level-supports: 4.0.1 - level-transcoder: 1.0.1 - module-error: 1.0.2 - queue-microtask: 1.2.3 - dev: true - /abstract-leveldown@6.2.3: resolution: {integrity: sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ==} engines: {node: '>=6'} @@ -6956,6 +6908,11 @@ packages: engines: {node: '>=0.4.0'} dev: true + /acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + dev: true + /acorn@8.10.0: resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} engines: {node: '>=0.4.0'} @@ -7015,6 +6972,12 @@ packages: resolution: {integrity: sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==} dev: true + /ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + dependencies: + string-width: 4.2.3 + dev: true + /ansi-colors@4.1.1: resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} engines: {node: '>=6'} @@ -7121,6 +7084,11 @@ packages: resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} dev: true + /are-docs-informative@0.0.2: + resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} + engines: {node: '>=14'} + dev: true + /arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} dev: true @@ -7348,7 +7316,7 @@ packages: /axios@0.21.4(debug@4.3.4): resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} dependencies: - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.5(debug@4.3.4) transitivePeerDependencies: - debug dev: true @@ -7356,17 +7324,17 @@ packages: /axios@1.1.3: resolution: {integrity: sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==} dependencies: - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.5(debug@4.3.4) form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug dev: true - /axios@1.5.1: - resolution: {integrity: sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==} + /axios@1.6.7: + resolution: {integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==} dependencies: - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.5(debug@4.3.4) form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -7520,12 +7488,6 @@ packages: is-windows: 1.0.2 dev: false - /bidi-js@1.0.3: - resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} - dependencies: - require-from-string: 2.0.2 - dev: true - /bigint-crypto-utils@3.3.0: resolution: {integrity: sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg==} engines: {node: '>=14.0.0'} @@ -7629,6 +7591,20 @@ packages: resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} dev: true + /boxen@5.1.2: + resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} + engines: {node: '>=10'} + dependencies: + ansi-align: 3.0.1 + camelcase: 6.3.0 + chalk: 4.1.2 + cli-boxes: 2.2.1 + string-width: 4.2.3 + type-fest: 0.20.2 + widest-line: 3.1.0 + wrap-ansi: 7.0.0 + dev: true + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -7657,15 +7633,6 @@ packages: /brorand@1.1.0: resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} - /browser-level@1.0.1: - resolution: {integrity: sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ==} - dependencies: - abstract-level: 1.0.3 - catering: 2.1.1 - module-error: 1.0.2 - run-parallel-limit: 1.1.0 - dev: true - /browser-stdout@1.3.1: resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} dev: true @@ -7900,11 +7867,6 @@ packages: tslib: 2.6.2 upper-case-first: 2.0.2 - /case@1.6.3: - resolution: {integrity: sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==} - engines: {node: '>= 0.8.0'} - dev: true - /caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} dev: true @@ -7934,7 +7896,7 @@ packages: check-error: 1.0.3 deep-eql: 4.1.3 get-func-name: 2.0.2 - loupe: 2.3.6 + loupe: 2.3.7 pathval: 1.1.1 type-detect: 4.0.8 @@ -8031,7 +7993,7 @@ packages: engines: {node: '>=12.13.0'} hasBin: true dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -8042,7 +8004,7 @@ packages: /chromium-edge-launcher@1.0.0: resolution: {integrity: sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA==} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -8078,18 +8040,6 @@ packages: consola: 3.2.3 dev: true - /classic-level@1.3.0: - resolution: {integrity: sha512-iwFAJQYtqRTRM0F6L8h4JCt00ZSGdOyqh7yVrhhjrOpFhmBjNlRUey64MCiyo6UmQHMJ+No3c81nujPv+n9yrg==} - engines: {node: '>=12'} - requiresBuild: true - dependencies: - abstract-level: 1.0.3 - catering: 2.1.1 - module-error: 1.0.2 - napi-macros: 2.2.2 - node-gyp-build: 4.6.0 - dev: true - /clean-regexp@1.0.0: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} @@ -8102,6 +8052,11 @@ packages: engines: {node: '>=6'} dev: true + /cli-boxes@2.2.1: + resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} + engines: {node: '>=6'} + dev: true + /cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} @@ -8284,9 +8239,9 @@ packages: engines: {node: ^12.20.0 || >=14} dev: true - /comment-parser@1.1.6-beta.0: - resolution: {integrity: sha512-q3cA8TSMyqW7wcPSYWzbO/rMahnXgzs4SLG/UIWXdEsnXTFPZkEkWAdNgPiHig2OzxgpPLOh4WwsmClDxndwHw==} - engines: {node: '>= 10.0.0'} + /comment-parser@1.4.1: + resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} + engines: {node: '>= 12.0.0'} dev: true /commondir@1.0.1: @@ -8500,14 +8455,6 @@ packages: resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} dev: false - /css-tree@2.3.1: - resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - dependencies: - mdn-data: 2.0.30 - source-map-js: 1.0.2 - dev: true - /css.escape@1.5.1: resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} dev: true @@ -8761,7 +8708,7 @@ packages: require-package-name: 2.0.1 resolve: 1.22.4 resolve-from: 5.0.0 - semver: 7.5.4 + semver: 7.6.0 yargs: 16.2.0 transitivePeerDependencies: - supports-color @@ -8933,8 +8880,13 @@ packages: engines: {node: '>=10'} dev: true - /dotenv@16.3.1: - resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + /dotenv@16.3.2: + resolution: {integrity: sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==} + engines: {node: '>=12'} + dev: true + + /dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} /dotenv@8.6.0: @@ -9319,7 +9271,7 @@ packages: eslint-plugin-promise: ^4.2.1 || ^5.0.0 dependencies: eslint: 8.56.0 - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint@8.56.0) eslint-plugin-node: 11.1.0(eslint@8.56.0) eslint-plugin-promise: 5.2.0(eslint@8.56.0) dev: true @@ -9334,7 +9286,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint@8.56.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint@8.56.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -9355,7 +9307,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3) debug: 3.2.7 eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 @@ -9374,7 +9326,7 @@ packages: regexpp: 3.2.0 dev: true - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0): + /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0)(eslint@8.56.0): resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} engines: {node: '>=4'} peerDependencies: @@ -9384,7 +9336,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3) array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 @@ -9393,7 +9345,7 @@ packages: doctrine: 2.1.0 eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint@8.56.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint@8.56.0) hasown: 2.0.0 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -9409,22 +9361,22 @@ packages: - supports-color dev: true - /eslint-plugin-jsdoc@35.5.1(eslint@8.56.0): - resolution: {integrity: sha512-pPYPWtsykwVEue1tYEyoppBj4dgF7XicF67tLLLraY6RQYBq7qMKjUHji19+hfiTtYKKBD0YfeK8hgjPAE5viw==} - engines: {node: '>=12'} + /eslint-plugin-jsdoc@48.0.6(eslint@8.56.0): + resolution: {integrity: sha512-LgwXOX6TWxxFYcbdVe+BJ94Kl/pgjSPYHLzqEdAMXTA1BH9WDx7iJ+9/iDajPF64LtzWX8C1mCfpbMZjJGhAOw==} + engines: {node: '>=18'} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 dependencies: - '@es-joy/jsdoccomment': 0.9.0-alpha.1 - comment-parser: 1.1.6-beta.0 + '@es-joy/jsdoccomment': 0.42.0 + are-docs-informative: 0.0.2 + comment-parser: 1.4.1 debug: 4.3.4(supports-color@8.1.1) + escape-string-regexp: 4.0.0 eslint: 8.56.0 - esquery: 1.4.0 - jsdoc-type-pratt-parser: 1.1.1 - lodash: 4.17.21 - regextras: 0.8.0 - semver: 7.5.4 - spdx-expression-parse: 3.0.1 + esquery: 1.5.0 + is-builtin-module: 3.2.1 + semver: 7.6.0 + spdx-expression-parse: 4.0.0 transitivePeerDependencies: - supports-color dev: true @@ -9524,7 +9476,7 @@ packages: read-pkg-up: 7.0.1 regexp-tree: 0.1.27 regjsparser: 0.10.0 - semver: 7.5.4 + semver: 7.6.0 strip-indent: 3.0.0 transitivePeerDependencies: - supports-color @@ -9629,13 +9581,6 @@ packages: engines: {node: '>=4'} hasBin: true - /esquery@1.4.0: - resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - /esquery@1.5.0: resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} engines: {node: '>=0.10'} @@ -9664,6 +9609,12 @@ packages: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} dev: true + /estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + dependencies: + '@types/estree': 1.0.5 + dev: true + /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -9915,21 +9866,6 @@ packages: strip-final-newline: 2.0.0 dev: true - /execa@6.1.0: - resolution: {integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 3.0.1 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.1.0 - onetime: 6.0.0 - signal-exit: 3.0.7 - strip-final-newline: 3.0.0 - dev: true - /execa@8.0.1: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} @@ -10284,8 +10220,8 @@ packages: imul: 1.0.1 dev: true - /follow-redirects@1.15.2(debug@4.3.4): - resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} + /follow-redirects@1.15.5(debug@4.3.4): + resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} engines: {node: '>=4.0'} peerDependencies: debug: '*' @@ -10604,17 +10540,6 @@ packages: path-scurry: 1.10.1 dev: true - /glob@7.1.4: - resolution: {integrity: sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - /glob@7.1.6: resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} dependencies: @@ -10800,8 +10725,8 @@ packages: - utf-8-validate dev: true - /hardhat@2.19.4(ts-node@10.9.2)(typescript@5.3.3): - resolution: {integrity: sha512-fTQJpqSt3Xo9Mn/WrdblNGAfcANM6XC3tAEi6YogB4s02DmTf93A8QsGb8uR0KR8TFcpcS8lgiW4ugAIYpnbrQ==} + /hardhat@2.20.1(ts-node@10.9.2)(typescript@5.3.3): + resolution: {integrity: sha512-q75xDQiQtCZcTMBwjTovrXEU5ECr49baxr4/OBkIu/ULTPzlB20yk1dRWNmD2IFbAeAeXggaWvQAdpiScaHtPw==} hasBin: true peerDependencies: ts-node: '*' @@ -10814,16 +10739,17 @@ packages: dependencies: '@ethersproject/abi': 5.7.0 '@metamask/eth-sig-util': 4.0.0 - '@nomicfoundation/ethereumjs-block': 5.0.2 - '@nomicfoundation/ethereumjs-blockchain': 7.0.2 - '@nomicfoundation/ethereumjs-common': 4.0.2 - '@nomicfoundation/ethereumjs-evm': 2.0.2 - '@nomicfoundation/ethereumjs-rlp': 5.0.2 - '@nomicfoundation/ethereumjs-statemanager': 2.0.2 - '@nomicfoundation/ethereumjs-trie': 6.0.2 - '@nomicfoundation/ethereumjs-tx': 5.0.2 - '@nomicfoundation/ethereumjs-util': 9.0.2 - '@nomicfoundation/ethereumjs-vm': 7.0.2 + '@nomicfoundation/ethereumjs-block': 5.0.4 + '@nomicfoundation/ethereumjs-blockchain': 7.0.4 + '@nomicfoundation/ethereumjs-common': 4.0.4 + '@nomicfoundation/ethereumjs-evm': 2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2) + '@nomicfoundation/ethereumjs-rlp': 5.0.4 + '@nomicfoundation/ethereumjs-statemanager': 2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2) + '@nomicfoundation/ethereumjs-trie': 6.0.4 + '@nomicfoundation/ethereumjs-tx': 5.0.4 + '@nomicfoundation/ethereumjs-util': 9.0.4 + '@nomicfoundation/ethereumjs-verkle': 0.0.2 + '@nomicfoundation/ethereumjs-vm': 7.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2) '@nomicfoundation/solidity-analyzer': 0.1.1 '@sentry/node': 5.30.0 '@types/bn.js': 5.1.0 @@ -10831,6 +10757,7 @@ packages: adm-zip: 0.4.16 aggregate-error: 3.1.0 ansi-escapes: 4.3.2 + boxen: 5.1.2 chalk: 2.4.2 chokidar: 3.5.3 ci-info: 2.0.0 @@ -10856,7 +10783,7 @@ packages: solc: 0.7.3(debug@4.3.4) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 - ts-node: 10.9.2(@types/node@20.11.5)(typescript@5.3.3) + ts-node: 10.9.2(@types/node@20.11.17)(typescript@5.3.3) tsort: 0.0.1 typescript: 5.3.3 undici: 5.24.0 @@ -10864,6 +10791,7 @@ packages: ws: 7.5.9 transitivePeerDependencies: - bufferutil + - c-kzg - supports-color - utf-8-validate dev: true @@ -11092,19 +11020,14 @@ packages: engines: {node: '>=10.17.0'} dev: true - /human-signals@3.0.1: - resolution: {integrity: sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==} - engines: {node: '>=12.20.0'} - dev: true - /human-signals@5.0.0: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} dev: true - /husky@8.0.3: - resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} - engines: {node: '>=14'} + /husky@9.0.10: + resolution: {integrity: sha512-TQGNknoiy6bURzIO77pPRu+XHi6zI7T93rX+QnJsoYFf3xdjKOur+IlfqzJGMHIK/wXrLg+GsvMs8Op7vI2jVA==} + engines: {node: '>=18'} hasBin: true dev: true @@ -11257,8 +11180,8 @@ packages: - supports-color dev: true - /ip@1.1.8: - resolution: {integrity: sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==} + /ip@1.1.9: + resolution: {integrity: sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==} dev: true /ipaddr.js@1.9.1: @@ -11692,7 +11615,7 @@ packages: '@babel/parser': 7.23.6 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.5.4 + semver: 7.6.0 transitivePeerDependencies: - supports-color dev: true @@ -11802,7 +11725,7 @@ packages: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.5 + '@types/node': 20.11.17 jest-mock: 29.7.0 jest-util: 29.7.0 dev: true @@ -11832,7 +11755,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.11.5 + '@types/node': 20.11.17 jest-util: 29.7.0 dev: true @@ -11841,7 +11764,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.11.5 + '@types/node': 20.11.17 chalk: 4.1.2 ci-info: 3.8.0 graceful-fs: 4.2.11 @@ -11864,7 +11787,7 @@ packages: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -11960,18 +11883,13 @@ packages: - supports-color dev: true - /jsdoc-type-pratt-parser@1.0.4: - resolution: {integrity: sha512-jzmW9gokeq9+bHPDR1nCeidMyFUikdZlbOhKzh9+/nJqB75XhpNKec1/UuxW5c4+O+Pi31Gc/dCboyfSm/pSpQ==} + /jsdoc-type-pratt-parser@4.0.0: + resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} engines: {node: '>=12.0.0'} dev: true - /jsdoc-type-pratt-parser@1.1.1: - resolution: {integrity: sha512-uelRmpghNwPBuZScwgBG/OzodaFk5RbO5xaivBdsAY70icWfShwZ7PCMO0x1zSkOa8T1FzHThmrdoyg/0AwV5g==} - engines: {node: '>=12.0.0'} - dev: true - - /jsdom@23.2.0: - resolution: {integrity: sha512-L88oL7D/8ufIES+Zjz7v0aes+oBMh2Xnh3ygWvL0OaICOomKEPKuPnIfBJekiXr+BHbbMjrWn/xqrDQuxFTeyA==} + /jsdom@24.0.0: + resolution: {integrity: sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==} engines: {node: '>=18'} peerDependencies: canvas: ^2.11.2 @@ -11979,7 +11897,6 @@ packages: canvas: optional: true dependencies: - '@asamuzakjp/dom-selector': 2.0.1 cssstyle: 4.0.1 data-urls: 5.0.0 decimal.js: 10.4.3 @@ -11988,6 +11905,7 @@ packages: http-proxy-agent: 7.0.0 https-proxy-agent: 7.0.2 is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.7 parse5: 7.1.2 rrweb-cssom: 0.6.0 saxes: 6.0.0 @@ -12256,19 +12174,6 @@ packages: engines: {node: '>=10'} dev: true - /level-supports@4.0.1: - resolution: {integrity: sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA==} - engines: {node: '>=12'} - dev: true - - /level-transcoder@1.0.1: - resolution: {integrity: sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==} - engines: {node: '>=12'} - dependencies: - buffer: 6.0.3 - module-error: 1.0.2 - dev: true - /level-ws@2.0.0: resolution: {integrity: sha512-1iv7VXx0G9ec1isqQZ7y5LmoZo/ewAsyDHNA8EFDW5hqH2Kqovm33nSFkSdnLLAK+I5FlT+lo5Cw9itGe+CpQA==} engines: {node: '>=6'} @@ -12278,14 +12183,6 @@ packages: xtend: 4.0.2 dev: true - /level@8.0.0: - resolution: {integrity: sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ==} - engines: {node: '>=12'} - dependencies: - browser-level: 1.0.1 - classic-level: 1.3.0 - dev: true - /leveldown@6.1.0: resolution: {integrity: sha512-8C7oJDT44JXxh04aSSsfcMI8YiaGRhOFI9/pMEL7nWJLVsWajDPTRxsSHTM2WcTVY5nXM+SuRHzPPi0GbnDX+w==} engines: {node: '>=10.12.0'} @@ -12585,16 +12482,10 @@ packages: dependencies: js-tokens: 4.0.0 - /loupe@2.3.6: - resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} - dependencies: - get-func-name: 2.0.2 - /loupe@2.3.7: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} dependencies: get-func-name: 2.0.2 - dev: true /lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} @@ -12676,7 +12567,7 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} dependencies: - semver: 7.5.4 + semver: 7.6.0 dev: true /make-error@1.3.6: @@ -12825,10 +12716,6 @@ packages: resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} dev: true - /mdn-data@2.0.30: - resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} - dev: true - /media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -12850,15 +12737,6 @@ packages: resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} dev: true - /memory-level@1.0.0: - resolution: {integrity: sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og==} - engines: {node: '>=12'} - dependencies: - abstract-level: 1.0.3 - functional-red-black-tree: 1.0.1 - module-error: 1.0.2 - dev: true - /memorystream@0.3.1: resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} engines: {node: '>= 0.10.0'} @@ -13274,12 +13152,6 @@ packages: /minimalistic-crypto-utils@1.0.1: resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} - /minimatch@3.0.5: - resolution: {integrity: sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: @@ -13417,11 +13289,6 @@ packages: yargs-unparser: 2.0.0 dev: true - /module-error@1.0.2: - resolution: {integrity: sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==} - engines: {node: '>=10'} - dev: true - /morgan@1.10.0: resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==} engines: {node: '>= 0.8.0'} @@ -13508,10 +13375,6 @@ packages: resolution: {integrity: sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg==} dev: true - /napi-macros@2.2.2: - resolution: {integrity: sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==} - dev: true - /napi-wasm@1.1.0: resolution: {integrity: sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg==} dev: true @@ -13678,11 +13541,15 @@ packages: bn.js: 4.11.6 strip-hex-prefix: 1.0.0 - /nx-cloud@16.5.2: - resolution: {integrity: sha512-1t1Ii9gojl8r/8hFGaZ/ZyYR0Cb0hzvXLCsaFuvg+EJEFdvua3P4cfNya/0bdRrm+7Eb/ITUOskbvYq4TSlyGg==} + /nwsapi@2.2.7: + resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} + dev: true + + /nx-cloud@18.0.0: + resolution: {integrity: sha512-VpPywcHmFIU3GSWb3KV3nQ+TAMLc06DTO39vTFsM+HreB6qRloDxbADRvfM5eHAbY26TNmwflT7wxd0fluv2+A==} hasBin: true dependencies: - '@nrwl/nx-cloud': 16.5.2 + '@nrwl/nx-cloud': 18.0.0 axios: 1.1.3 chalk: 4.1.2 dotenv: 10.0.0 @@ -13696,12 +13563,12 @@ packages: - debug dev: true - /nx@17.2.8: - resolution: {integrity: sha512-rM5zXbuXLEuqQqcjVjClyvHwRJwt+NVImR2A6KFNG40Z60HP6X12wAxxeLHF5kXXTDRU0PFhf/yACibrpbPrAw==} + /nx@18.1.2: + resolution: {integrity: sha512-E414xp6lVtiTGdDUMVo72G96G66t7oJMqmcHRMEZ/mVq5ZpNWUhfMuRq5Fh8orXPtrM3xk5SHokmmFvo5PKC+g==} hasBin: true requiresBuild: true peerDependencies: - '@swc-node/register': ^1.6.7 + '@swc-node/register': ^1.8.0 '@swc/core': ^1.3.85 peerDependenciesMeta: '@swc-node/register': @@ -13709,32 +13576,32 @@ packages: '@swc/core': optional: true dependencies: - '@nrwl/tao': 17.2.8 + '@nrwl/tao': 18.1.2 '@yarnpkg/lockfile': 1.1.0 '@yarnpkg/parsers': 3.0.0-rc.46 '@zkochan/js-yaml': 0.0.6 - axios: 1.5.1 + axios: 1.6.7 chalk: 4.1.2 cli-cursor: 3.1.0 cli-spinners: 2.6.1 cliui: 8.0.1 - dotenv: 16.3.1 + dotenv: 16.3.2 dotenv-expand: 10.0.0 enquirer: 2.3.6 figures: 3.2.0 flat: 5.0.2 fs-extra: 11.1.1 - glob: 7.1.4 ignore: 5.2.4 jest-diff: 29.7.0 js-yaml: 4.1.0 jsonc-parser: 3.2.0 lines-and-columns: 2.0.3 - minimatch: 3.0.5 + minimatch: 9.0.3 node-machine-id: 1.1.12 npm-run-path: 4.0.1 open: 8.4.2 - semver: 7.5.3 + ora: 5.3.0 + semver: 7.6.0 string-width: 4.2.3 strong-log-transformer: 2.1.0 tar-stream: 2.2.0 @@ -13744,16 +13611,16 @@ packages: yargs: 17.7.2 yargs-parser: 21.1.1 optionalDependencies: - '@nx/nx-darwin-arm64': 17.2.8 - '@nx/nx-darwin-x64': 17.2.8 - '@nx/nx-freebsd-x64': 17.2.8 - '@nx/nx-linux-arm-gnueabihf': 17.2.8 - '@nx/nx-linux-arm64-gnu': 17.2.8 - '@nx/nx-linux-arm64-musl': 17.2.8 - '@nx/nx-linux-x64-gnu': 17.2.8 - '@nx/nx-linux-x64-musl': 17.2.8 - '@nx/nx-win32-arm64-msvc': 17.2.8 - '@nx/nx-win32-x64-msvc': 17.2.8 + '@nx/nx-darwin-arm64': 18.1.2 + '@nx/nx-darwin-x64': 18.1.2 + '@nx/nx-freebsd-x64': 18.1.2 + '@nx/nx-linux-arm-gnueabihf': 18.1.2 + '@nx/nx-linux-arm64-gnu': 18.1.2 + '@nx/nx-linux-arm64-musl': 18.1.2 + '@nx/nx-linux-x64-gnu': 18.1.2 + '@nx/nx-linux-x64-musl': 18.1.2 + '@nx/nx-win32-arm64-msvc': 18.1.2 + '@nx/nx-win32-x64-msvc': 18.1.2 transitivePeerDependencies: - debug dev: true @@ -13990,6 +13857,20 @@ packages: type-check: 0.4.0 dev: true + /ora@5.3.0: + resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} + engines: {node: '>=10'} + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.0 + is-interactive: 1.0.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + dev: true + /ora@5.4.1: resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} engines: {node: '>=10'} @@ -14380,7 +14261,7 @@ packages: engines: {node: '>=10'} hasBin: true dependencies: - '@sentry/node': 7.94.1 + '@sentry/node': 7.99.0 commander: 2.20.3 pumpify: 2.0.1 split2: 3.2.2 @@ -14409,8 +14290,8 @@ packages: sonic-boom: 2.8.0 thread-stream: 0.15.2 - /pino@8.17.2: - resolution: {integrity: sha512-LA6qKgeDMLr2ux2y/YiUt47EfgQ+S9LznBWOJdN3q1dx2sv0ziDLUBeVpyVv17TEcGCBuWf0zNtg3M5m1NhhWQ==} + /pino@8.19.0: + resolution: {integrity: sha512-oswmokxkav9bADfJ2ifrvfHUwad6MLp73Uat0IkQWY3iAw5xTRoznXbXksZs8oaOUMpmhVWD+PZogNzllWpJaA==} hasBin: true dependencies: atomic-sleep: 1.0.0 @@ -14497,6 +14378,15 @@ packages: source-map-js: 1.0.2 dev: true + /postcss@8.4.35: + resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + /preact@10.16.0: resolution: {integrity: sha512-XTSj3dJ4roKIC93pald6rWuB2qQJO9gO2iLLyTe87MrjQN+HklueLsmskbywEWqCHlclgz3/M4YLL2iBr9UmMA==} dev: true @@ -15122,6 +15012,7 @@ packages: /regenerator-runtime@0.13.11: resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + dev: true /regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} @@ -15162,11 +15053,6 @@ packages: unicode-match-property-value-ecmascript: 2.1.0 dev: true - /regextras@0.8.0: - resolution: {integrity: sha512-k519uI04Z3SaY0fLX843MRXnDeG2+vHOFsyhiPZvNLe7r8rD2YNRjq4BQLZZ0oAr2NrtvZlICsXysGNFPGa3CQ==} - engines: {node: '>=0.1.14'} - dev: true - /regjsparser@0.10.0: resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} hasBin: true @@ -15453,16 +15339,20 @@ packages: resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} dev: true - /run-parallel-limit@1.1.0: - resolution: {integrity: sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==} + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 + + /rust-verkle-wasm@0.0.1: + resolution: {integrity: sha512-BN6fiTsxcd2dCECz/cHtGTt9cdLJR925nh7iAuRcj8ymKw7OOaPmCneQZ7JePOJ/ia27TjEL91VdOi88Yf+mcA==} dev: true - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + /rustbn-wasm@0.2.0: + resolution: {integrity: sha512-FThvYFNTqrEKGqXuseeg0zR7yROh/6U1617mCHF68OVqrN1tNKRN7Tdwy4WayPVsCmmK+eMxtIZX1qL6JxTkMg==} dependencies: - queue-microtask: 1.2.3 + '@scure/base': 1.1.3 + dev: true /rustbn.js@0.2.0: resolution: {integrity: sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==} @@ -15560,16 +15450,8 @@ packages: hasBin: true dev: true - /semver@7.5.3: - resolution: {integrity: sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - - /semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + /semver@7.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} engines: {node: '>=10'} hasBin: true dependencies: @@ -15803,7 +15685,7 @@ packages: dependencies: command-exists: 1.2.9 commander: 3.0.2 - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.5(debug@4.3.4) fs-extra: 0.30.0 js-sha3: 0.8.0 memorystream: 0.3.1 @@ -15821,7 +15703,7 @@ packages: dependencies: command-exists: 1.2.9 commander: 8.3.0 - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.5(debug@4.3.4) js-sha3: 0.8.0 memorystream: 0.3.1 semver: 5.7.2 @@ -15908,6 +15790,13 @@ packages: spdx-exceptions: 2.3.0 spdx-license-ids: 3.0.10 + /spdx-expression-parse@4.0.0: + resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.10 + dev: true + /spdx-license-ids@3.0.10: resolution: {integrity: sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==} @@ -16238,7 +16127,7 @@ packages: methods: 1.1.2 mime: 2.6.0 qs: 6.11.2 - semver: 7.5.4 + semver: 7.6.0 transitivePeerDependencies: - supports-color dev: true @@ -16419,8 +16308,8 @@ packages: resolution: {integrity: sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==} dev: true - /tinypool@0.8.1: - resolution: {integrity: sha512-zBTCK0cCgRROxvs9c0CGK838sPkeokNGdQVUUwHAbynHFlmyJYj825f/oRs528HaIJ97lo0pLIlDUzwN+IorWg==} + /tinypool@0.8.2: + resolution: {integrity: sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==} engines: {node: '>=14.0.0'} dev: true @@ -16562,7 +16451,7 @@ packages: tsconfig-paths: 3.15.0 dev: true - /ts-node@10.9.2(@types/node@20.11.5)(typescript@5.3.3): + /ts-node@10.9.2(@types/node@20.11.17)(typescript@5.3.3): resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true peerDependencies: @@ -16581,7 +16470,7 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.11.5 + '@types/node': 20.11.17 acorn: 8.10.0 acorn-walk: 8.3.0 arg: 4.1.3 @@ -16638,7 +16527,7 @@ packages: resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} dev: true - /tsup@8.0.1(@swc/core@1.3.104)(typescript@5.3.3): + /tsup@8.0.1(@swc/core@1.4.6)(typescript@5.3.3): resolution: {integrity: sha512-hvW7gUSG96j53ZTSlT4j/KL0q1Q2l6TqGBFc6/mu/L46IoNWqLLUzLRLP1R8Q7xrJTmkDxxDoojV5uCVs1sVOg==} engines: {node: '>=18'} hasBin: true @@ -16657,7 +16546,7 @@ packages: typescript: optional: true dependencies: - '@swc/core': 1.3.104 + '@swc/core': 1.4.6 bundle-require: 4.0.1(esbuild@0.19.7) cac: 6.7.14 chokidar: 3.5.3 @@ -17243,8 +17132,8 @@ packages: - zod dev: true - /viem@2.0.0(typescript@5.3.3)(zod@3.22.4): - resolution: {integrity: sha512-WYPwVAs/wrQE1Li9mgHMZaZTnRZuyPJMauIhnpZKeZgtx7f+bWU3uvVSR5kxTf1aBFdaTuRc/umzX2ucQUurnA==} + /viem@2.7.19(typescript@5.3.3)(zod@3.22.4): + resolution: {integrity: sha512-UOMeqy+8p2709ra2j9HEOL1NfjsXZzlJ8gwR6YO/zXH8KIZvyzW07t4iQARF5+ShVZ/7+/1ec8oPjVi1M//33A==} peerDependencies: typescript: '>=5.0.4' peerDependenciesMeta: @@ -17256,7 +17145,7 @@ packages: '@noble/hashes': 1.3.2 '@scure/bip32': 1.3.2 '@scure/bip39': 1.2.1 - abitype: 0.10.0(typescript@5.3.3)(zod@3.22.4) + abitype: 1.0.0(typescript@5.3.3)(zod@3.22.4) isows: 1.0.3(ws@8.13.0) typescript: 5.3.3 ws: 8.13.0 @@ -17264,32 +17153,9 @@ packages: - bufferutil - utf-8-validate - zod - dev: true - /viem@2.0.3(typescript@5.3.3)(zod@3.22.4): - resolution: {integrity: sha512-9r+CMEA0zf8QCvCobTUX4vhP9x0t7wRjHbadfHDHw8ULjnzwoQc1Yc1pK99GtqK4hv5hKacDe78dibg80p/a+A==} - peerDependencies: - typescript: '>=5.0.4' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@adraffy/ens-normalize': 1.10.0 - '@noble/curves': 1.2.0 - '@noble/hashes': 1.3.2 - '@scure/bip32': 1.3.2 - '@scure/bip39': 1.2.1 - abitype: 0.10.0(typescript@5.3.3)(zod@3.22.4) - isows: 1.0.3(ws@8.13.0) - typescript: 5.3.3 - ws: 8.13.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - zod - - /vite-node@1.0.1(@types/node@20.11.5): - resolution: {integrity: sha512-Y2Jnz4cr2azsOMMYuVPrQkp3KMnS/0WV8ezZjCy4hU7O5mUHCAVOnFmoEvs1nvix/4mYm74Len8bYRWZJMNP6g==} + /vite-node@1.2.2(@types/node@20.11.17): + resolution: {integrity: sha512-1as4rDTgVWJO3n1uHmUYqq7nsFgINQ9u+mRcXpjeOMJUmviqNKjcZB7UfRZrlM7MjYXMKpuWp5oGkjaFLnjawg==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true dependencies: @@ -17297,7 +17163,7 @@ packages: debug: 4.3.4(supports-color@8.1.1) pathe: 1.1.1 picocolors: 1.0.0 - vite: 5.0.12(@types/node@20.11.5) + vite: 5.1.5(@types/node@20.11.17) transitivePeerDependencies: - '@types/node' - less @@ -17309,8 +17175,8 @@ packages: - terser dev: true - /vite@5.0.11(@types/node@20.11.5): - resolution: {integrity: sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==} + /vite@5.0.12(@types/node@20.11.17): + resolution: {integrity: sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -17337,7 +17203,7 @@ packages: terser: optional: true dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 esbuild: 0.19.10 postcss: 8.4.32 rollup: 4.5.1 @@ -17345,8 +17211,8 @@ packages: fsevents: 2.3.3 dev: true - /vite@5.0.12(@types/node@20.11.5): - resolution: {integrity: sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==} + /vite@5.1.5(@types/node@20.11.17): + resolution: {integrity: sha512-BdN1xh0Of/oQafhU+FvopafUp6WaYenLU/NFoL5WyJL++GxkNfieKzBhM24H3HVsPQrlAqB7iJYTHabzaRed5Q==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -17373,16 +17239,16 @@ packages: terser: optional: true dependencies: - '@types/node': 20.11.5 + '@types/node': 20.11.17 esbuild: 0.19.10 - postcss: 8.4.32 + postcss: 8.4.35 rollup: 4.5.1 optionalDependencies: fsevents: 2.3.3 dev: true - /vitest@1.0.1(@types/node@20.11.5)(jsdom@23.2.0): - resolution: {integrity: sha512-MHsOj079S28hDsvdDvyD1pRj4dcS51EC5Vbe0xvOYX+WryP8soiK2dm8oULi+oA/8Xa/h6GoJEMTmcmBy5YM+Q==} + /vitest@1.2.2(@types/node@20.11.17)(jsdom@24.0.0): + resolution: {integrity: sha512-d5Ouvrnms3GD9USIK36KG8OZ5bEvKEkITFtnGv56HFaSlbItJuYr7hv2Lkn903+AvRAgSixiamozUVfORUekjw==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -17406,18 +17272,18 @@ packages: jsdom: optional: true dependencies: - '@types/node': 20.11.5 - '@vitest/expect': 1.0.1 - '@vitest/runner': 1.0.1 - '@vitest/snapshot': 1.0.1 - '@vitest/spy': 1.0.1 - '@vitest/utils': 1.0.1 - acorn-walk: 8.3.0 + '@types/node': 20.11.17 + '@vitest/expect': 1.2.2 + '@vitest/runner': 1.2.2 + '@vitest/snapshot': 1.2.2 + '@vitest/spy': 1.2.2 + '@vitest/utils': 1.2.2 + acorn-walk: 8.3.2 cac: 6.7.14 chai: 4.3.10 debug: 4.3.4(supports-color@8.1.1) execa: 8.0.1 - jsdom: 23.2.0 + jsdom: 24.0.0 local-pkg: 0.5.0 magic-string: 0.30.5 pathe: 1.1.1 @@ -17425,9 +17291,9 @@ packages: std-env: 3.6.0 strip-literal: 1.3.0 tinybench: 2.5.1 - tinypool: 0.8.1 - vite: 5.0.11(@types/node@20.11.5) - vite-node: 1.0.1(@types/node@20.11.5) + tinypool: 0.8.2 + vite: 5.0.12(@types/node@20.11.17) + vite-node: 1.2.2(@types/node@20.11.17) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -17463,8 +17329,8 @@ packages: xml-name-validator: 5.0.0 dev: true - /wagmi@2.2.1(@tanstack/react-query@5.17.1)(react-dom@18.2.0)(react-native@0.73.1)(react@18.2.0)(typescript@5.3.3)(viem@2.0.3): - resolution: {integrity: sha512-lOro0KprkzANip4eV5WoeYenXo3VOWiBcri/l+yqPPpUR/CSQhBR5i04yK9JRS11CQaJp15jZRD3Amwg4Ch1ww==} + /wagmi@2.5.5(@tanstack/react-query@5.17.1)(react-dom@18.2.0)(react-native@0.73.1)(react@18.2.0)(typescript@5.3.3)(viem@2.7.19): + resolution: {integrity: sha512-U9F5+e4bFXhSvIAWaImP4oCDXnOG/7q1xnBlkWBwbGy+oWg3BBiD01BZUnkplFGu6scSZ+TPURGtOkwH0rnxBQ==} peerDependencies: '@tanstack/react-query': '>=5.0.0' react: '>=18' @@ -17475,12 +17341,12 @@ packages: optional: true dependencies: '@tanstack/react-query': 5.17.1(react@18.2.0) - '@wagmi/connectors': 4.1.4(@wagmi/core@2.2.1)(react-dom@18.2.0)(react-native@0.73.1)(react@18.2.0)(typescript@5.3.3)(viem@2.0.3) - '@wagmi/core': 2.2.1(react@18.2.0)(typescript@5.3.3)(viem@2.0.3) + '@wagmi/connectors': 4.1.12(@wagmi/core@2.6.3)(react-dom@18.2.0)(react-native@0.73.1)(react@18.2.0)(typescript@5.3.3)(viem@2.7.19) + '@wagmi/core': 2.6.3(react@18.2.0)(typescript@5.3.3)(viem@2.7.19) react: 18.2.0 typescript: 5.3.3 use-sync-external-store: 1.2.0(react@18.2.0) - viem: 2.0.3(typescript@5.3.3)(zod@3.22.4) + viem: 2.7.19(typescript@5.3.3)(zod@3.22.4) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -18010,6 +17876,13 @@ packages: stackback: 0.0.2 dev: true + /widest-line@3.1.0: + resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} + engines: {node: '>=8'} + dependencies: + string-width: 4.2.3 + dev: true + /window-size@0.2.0: resolution: {integrity: sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw==} engines: {node: '>= 0.10.0'} diff --git a/proxyd/cache.go b/proxyd/cache.go index a93a39371357..5add4f23627e 100644 --- a/proxyd/cache.go +++ b/proxyd/cache.go @@ -21,8 +21,6 @@ type Cache interface { const ( // assuming an average RPCRes size of 3 KB memoryCacheLimit = 4096 - // Set a large ttl to avoid expirations. However, a ttl must be set for volatile-lru to take effect. - redisTTL = 30 * 7 * 24 * time.Hour ) type cache struct { @@ -49,10 +47,11 @@ func (c *cache) Put(ctx context.Context, key string, value string) error { type redisCache struct { rdb *redis.Client prefix string + ttl time.Duration } -func newRedisCache(rdb *redis.Client, prefix string) *redisCache { - return &redisCache{rdb, prefix} +func newRedisCache(rdb *redis.Client, prefix string, ttl time.Duration) *redisCache { + return &redisCache{rdb, prefix, ttl} } func (c *redisCache) namespaced(key string) string { @@ -78,7 +77,7 @@ func (c *redisCache) Get(ctx context.Context, key string) (string, error) { func (c *redisCache) Put(ctx context.Context, key string, value string) error { start := time.Now() - err := c.rdb.SetEx(ctx, c.namespaced(key), value, redisTTL).Err() + err := c.rdb.SetEx(ctx, c.namespaced(key), value, c.ttl).Err() redisCacheDurationSumm.WithLabelValues("SETEX").Observe(float64(time.Since(start).Milliseconds())) if err != nil { diff --git a/proxyd/cache_test.go b/proxyd/cache_test.go index da47e7c4d60d..1a5d543227ae 100644 --- a/proxyd/cache_test.go +++ b/proxyd/cache_test.go @@ -183,7 +183,7 @@ func TestRPCCacheUnsupportedMethod(t *testing.T) { name: "eth_call", req: &RPCReq{ JSONRPC: "2.0", - Method: "eth_gasPrice", + Method: "eth_call", ID: ID, }, }, diff --git a/proxyd/cmd/proxyd/main.go b/proxyd/cmd/proxyd/main.go index 10a1518cdb6f..3daa80b38710 100644 --- a/proxyd/cmd/proxyd/main.go +++ b/proxyd/cmd/proxyd/main.go @@ -1,17 +1,22 @@ package main import ( + "fmt" "net" "net/http" "net/http/pprof" "os" "os/signal" "strconv" + "strings" "syscall" "github.com/BurntSushi/toml" - "github.com/ethereum-optimism/optimism/proxyd" + "golang.org/x/exp/slog" + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/proxyd" ) var ( @@ -23,12 +28,7 @@ var ( func main() { // Set up logger with a default INFO level in case we fail to parse flags. // Otherwise the final critical log won't show what the parsing error was. - log.Root().SetHandler( - log.LvlFilterHandler( - log.LvlInfo, - log.StreamHandler(os.Stdout, log.JSONFormat()), - ), - ) + proxyd.SetLogLevel(slog.LevelInfo) log.Info("starting proxyd", "version", GitVersion, "commit", GitCommit, "date", GitDate) @@ -42,19 +42,14 @@ func main() { } // update log level from config - logLevel, err := log.LvlFromString(config.Server.LogLevel) + logLevel, err := LevelFromString(config.Server.LogLevel) if err != nil { - logLevel = log.LvlInfo + logLevel = log.LevelInfo if config.Server.LogLevel != "" { log.Warn("invalid server.log_level set: " + config.Server.LogLevel) } } - log.Root().SetHandler( - log.LvlFilterHandler( - logLevel, - log.StreamHandler(os.Stdout, log.JSONFormat()), - ), - ) + proxyd.SetLogLevel(logLevel) if config.Server.EnablePprof { log.Info("starting pprof", "addr", "0.0.0.0", "port", "6060") @@ -79,6 +74,30 @@ func main() { shutdown() } +// LevelFromString returns the appropriate Level from a string name. +// Useful for parsing command line args and configuration files. +// It also converts strings to lowercase. +// Note: copied from op-service/log to avoid monorepo dependency +func LevelFromString(lvlString string) (slog.Level, error) { + lvlString = strings.ToLower(lvlString) // ignore case + switch lvlString { + case "trace", "trce": + return log.LevelTrace, nil + case "debug", "dbug": + return log.LevelDebug, nil + case "info": + return log.LevelInfo, nil + case "warn": + return log.LevelWarn, nil + case "error", "eror": + return log.LevelError, nil + case "crit": + return log.LevelCrit, nil + default: + return log.LevelDebug, fmt.Errorf("unknown level: %v", lvlString) + } +} + func StartPProf(hostname string, port int) *http.Server { mux := http.NewServeMux() diff --git a/proxyd/config.go b/proxyd/config.go index bb7fe22218c0..3c622f86ddb6 100644 --- a/proxyd/config.go +++ b/proxyd/config.go @@ -29,7 +29,8 @@ type ServerConfig struct { } type CacheConfig struct { - Enabled bool `toml:"enabled"` + Enabled bool `toml:"enabled"` + TTL TOMLDuration `toml:"ttl"` } type RedisConfig struct { @@ -122,6 +123,7 @@ type BackendGroupConfig struct { ConsensusHA bool `toml:"consensus_ha"` ConsensusHAHeartbeatInterval TOMLDuration `toml:"consensus_ha_heartbeat_interval"` ConsensusHALockPeriod TOMLDuration `toml:"consensus_ha_lock_period"` + ConsensusHARedis RedisConfig `toml:"consensus_ha_redis"` } type BackendGroupsConfig map[string]*BackendGroupConfig diff --git a/proxyd/consensus_tracker.go b/proxyd/consensus_tracker.go index 158c31bdc683..77e0fdba9912 100644 --- a/proxyd/consensus_tracker.go +++ b/proxyd/consensus_tracker.go @@ -194,10 +194,12 @@ func (ct *RedisConsensusTracker) stateHeartbeat() { val, err := ct.client.Get(ct.ctx, key).Result() if err != nil && err != redis.Nil { log.Error("failed to read the lock", "err", err) + RecordGroupConsensusError(ct.backendGroup, "read_lock", err) if ct.leader { ok, err := ct.redlock.Unlock() if err != nil || !ok { log.Error("failed to release the lock after error", "err", err) + RecordGroupConsensusError(ct.backendGroup, "leader_release_lock", err) return } ct.leader = false @@ -210,9 +212,11 @@ func (ct *RedisConsensusTracker) stateHeartbeat() { ok, err := ct.redlock.Extend() if err != nil || !ok { log.Error("failed to extend lock", "err", err, "mutex", ct.redlock.Name(), "val", ct.redlock.Value()) + RecordGroupConsensusError(ct.backendGroup, "leader_extend_lock", err) ok, err := ct.redlock.Unlock() if err != nil || !ok { log.Error("failed to release the lock after error", "err", err) + RecordGroupConsensusError(ct.backendGroup, "leader_release_lock", err) return } ct.leader = false @@ -224,6 +228,7 @@ func (ct *RedisConsensusTracker) stateHeartbeat() { leaderName, err := ct.client.Get(ct.ctx, ct.key(fmt.Sprintf("leader:%s", val))).Result() if err != nil && err != redis.Nil { log.Error("failed to read the remote leader", "err", err) + RecordGroupConsensusError(ct.backendGroup, "read_leader", err) return } ct.leaderName = leaderName @@ -232,16 +237,19 @@ func (ct *RedisConsensusTracker) stateHeartbeat() { val, err := ct.client.Get(ct.ctx, ct.key(fmt.Sprintf("state:%s", val))).Result() if err != nil && err != redis.Nil { log.Error("failed to read the remote state", "err", err) + RecordGroupConsensusError(ct.backendGroup, "read_state", err) return } if val == "" { log.Error("remote state is missing (recent leader election maybe?)") + RecordGroupConsensusError(ct.backendGroup, "read_state_missing", err) return } state := &ConsensusTrackerState{} err = json.Unmarshal([]byte(val), state) if err != nil { log.Error("failed to unmarshal the remote state", "err", err) + RecordGroupConsensusError(ct.backendGroup, "read_unmarshal_state", err) return } @@ -316,13 +324,26 @@ func (ct *RedisConsensusTracker) postPayload(mutexVal string) { jsonState, err := json.Marshal(ct.local.state) if err != nil { log.Error("failed to marshal local", "err", err) + RecordGroupConsensusError(ct.backendGroup, "leader_marshal_local_state", err) + ct.leader = false + return + } + err = ct.client.Set(ct.ctx, ct.key(fmt.Sprintf("state:%s", mutexVal)), jsonState, ct.lockPeriod).Err() + if err != nil { + log.Error("failed to post the state", "err", err) + RecordGroupConsensusError(ct.backendGroup, "leader_post_state", err) ct.leader = false return } - ct.client.Set(ct.ctx, ct.key(fmt.Sprintf("state:%s", mutexVal)), jsonState, ct.lockPeriod) leader, _ := os.LookupEnv("HOSTNAME") - ct.client.Set(ct.ctx, ct.key(fmt.Sprintf("leader:%s", mutexVal)), leader, ct.lockPeriod) + err = ct.client.Set(ct.ctx, ct.key(fmt.Sprintf("leader:%s", mutexVal)), leader, ct.lockPeriod).Err() + if err != nil { + log.Error("failed to post the leader", "err", err) + RecordGroupConsensusError(ct.backendGroup, "leader_post_leader", err) + ct.leader = false + return + } log.Debug("posted state", "state", string(jsonState), "leader", leader) diff --git a/proxyd/go.mod b/proxyd/go.mod index e37defca0b07..d207332e3570 100644 --- a/proxyd/go.mod +++ b/proxyd/go.mod @@ -6,7 +6,7 @@ require ( github.com/BurntSushi/toml v1.3.2 github.com/alicebob/miniredis v2.5.0+incompatible github.com/emirpasic/gods v1.18.1 - github.com/ethereum/go-ethereum v1.13.5 + github.com/ethereum/go-ethereum v1.13.8 github.com/go-redsync/redsync/v4 v4.10.0 github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb github.com/gorilla/mux v1.8.0 @@ -19,7 +19,8 @@ require ( github.com/stretchr/testify v1.8.4 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/xaionaro-go/weightedshuffle v0.0.0-20211213010739-6a74fbc7d24a - golang.org/x/sync v0.4.0 + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa + golang.org/x/sync v0.5.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -39,22 +40,23 @@ require ( github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set/v2 v2.3.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect + github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect github.com/getsentry/sentry-go v0.25.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-stack/stack v1.8.1 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/gomodule/redigo v1.8.9 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect - github.com/holiman/uint256 v1.2.3 // indirect + github.com/holiman/uint256 v1.2.4 // indirect github.com/klauspost/compress v1.17.1 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect @@ -75,11 +77,10 @@ require ( github.com/yuin/gopher-lua v1.1.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect golang.org/x/crypto v0.17.0 // indirect - golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/mod v0.13.0 // indirect + golang.org/x/mod v0.14.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.14.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/tools v0.15.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/proxyd/go.sum b/proxyd/go.sum index e9cac7ef70f2..9b7fd5e3a4cc 100644 --- a/proxyd/go.sum +++ b/proxyd/go.sum @@ -42,6 +42,8 @@ github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/Yj github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -60,12 +62,14 @@ github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= -github.com/ethereum/go-ethereum v1.13.5 h1:U6TCRciCqZRe4FPXmy1sMGxTfuk8P7u2UoinF3VbaFk= -github.com/ethereum/go-ethereum v1.13.5/go.mod h1:yMTu38GSuyxaYzQMViqNmQ1s3cE84abZexQmTgenWk0= +github.com/ethereum/go-ethereum v1.13.8 h1:1od+thJel3tM52ZUNQwvpYOeRHlbkVFZ5S8fhi0Lgsg= +github.com/ethereum/go-ethereum v1.13.8/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI= github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= @@ -81,8 +85,6 @@ github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F4 github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= github.com/go-redsync/redsync/v4 v4.10.0 h1:hTeAak4C73mNBQSTq6KCKDFaiIlfC+z5yTTl8fCJuBs= github.com/go-redsync/redsync/v4 v4.10.0/go.mod h1:ZfayzutkgeBmEmBlUR3j+rF6kN44UUGtEdfzhBFZTPc= -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/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -94,7 +96,6 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU 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.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -103,7 +104,6 @@ github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs0 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= @@ -120,8 +120,8 @@ github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iP github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= -github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= -github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -211,12 +211,12 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= 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.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -224,14 +224,14 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -258,8 +258,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= 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= @@ -271,9 +271,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ 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.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/proxyd/integration_tests/smoke_test.go b/proxyd/integration_tests/smoke_test.go new file mode 100644 index 000000000000..5fed7571bcec --- /dev/null +++ b/proxyd/integration_tests/smoke_test.go @@ -0,0 +1,51 @@ +package integration_tests + +import ( + "fmt" + "io" + "os" + "strings" + "testing" + + "github.com/ethereum-optimism/optimism/proxyd" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func TestInitProxyd(t *testing.T) { + goodBackend := NewMockBackend(BatchedResponseHandler(200, goodResponse)) + defer goodBackend.Close() + + require.NoError(t, os.Setenv("GOOD_BACKEND_RPC_URL", goodBackend.URL())) + + config := ReadConfig("smoke") + + sysStdOut := os.Stdout + r, w, err := os.Pipe() + require.NoError(t, err) + os.Stdout = w + + proxyd.SetLogLevel(log.LevelInfo) + + defer func() { + w.Close() + out, _ := io.ReadAll(r) + require.True(t, strings.Contains(string(out), "started proxyd")) + require.True(t, strings.Contains(string(out), "shutting down proxyd")) + fmt.Println(string(out)) + os.Stdout = sysStdOut + }() + + _, shutdown, err := proxyd.Start(config) + require.NoError(t, err) + defer shutdown() + + t.Run("initialization", func(t *testing.T) { + client := NewProxydClient("http://127.0.0.1:8545") + res, code, err := client.SendRPC(ethChainID, nil) + require.NoError(t, err) + require.Equal(t, 200, code) + require.NotNil(t, res) + }) + +} diff --git a/proxyd/integration_tests/testdata/smoke.toml b/proxyd/integration_tests/testdata/smoke.toml new file mode 100644 index 000000000000..a2187a25055d --- /dev/null +++ b/proxyd/integration_tests/testdata/smoke.toml @@ -0,0 +1,18 @@ +[server] +rpc_port = 8545 + +[backend] +response_timeout_seconds = 1 + +[backends] +[backends.good] +rpc_url = "$GOOD_BACKEND_RPC_URL" +ws_url = "$GOOD_BACKEND_RPC_URL" + +[backend_groups] +[backend_groups.main] +backends = ["good"] + +[rpc_method_mappings] +eth_chainId = "main" + diff --git a/proxyd/integration_tests/util_test.go b/proxyd/integration_tests/util_test.go index db52d2f43bc6..36edce13ef78 100644 --- a/proxyd/integration_tests/util_test.go +++ b/proxyd/integration_tests/util_test.go @@ -10,13 +10,14 @@ import ( "testing" "time" - "github.com/ethereum/go-ethereum/log" - + "github.com/BurntSushi/toml" "github.com/gorilla/websocket" + "github.com/stretchr/testify/require" + "golang.org/x/exp/slog" + + "github.com/ethereum/go-ethereum/log" - "github.com/BurntSushi/toml" "github.com/ethereum-optimism/optimism/proxyd" - "github.com/stretchr/testify/require" ) type ProxydHTTPClient struct { @@ -129,8 +130,10 @@ type WSMessage struct { Body []byte } -type ProxydWSClientOnMessage func(msgType int, data []byte) -type ProxydWSClientOnClose func(err error) +type ( + ProxydWSClientOnMessage func(msgType int, data []byte) + ProxydWSClientOnClose func(err error) +) func NewProxydWSClient( url string, @@ -183,11 +186,6 @@ func (h *ProxydWSClient) WriteControlMessage(msgType int, msg []byte) error { } func InitLogger() { - log.Root().SetHandler( - log.LvlFilterHandler(log.LvlDebug, - log.StreamHandler( - os.Stdout, - log.TerminalFormat(false), - )), - ) + log.SetDefault(log.NewLogger(slog.NewJSONHandler( + os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug}))) } diff --git a/proxyd/metrics.go b/proxyd/metrics.go index 68ca4e89874d..90a79ab7cc6d 100644 --- a/proxyd/metrics.go +++ b/proxyd/metrics.go @@ -2,6 +2,8 @@ package proxyd import ( "context" + "fmt" + "regexp" "strconv" "strings" "time" @@ -262,6 +264,14 @@ var ( "backend_group_name", }) + consensusHAError = promauto.NewCounterVec(prometheus.CounterOpts{ + Namespace: MetricsNamespace, + Name: "group_consensus_ha_error", + Help: "Consensus HA error count", + }, []string{ + "error", + }) + consensusHALatestBlock = promauto.NewGaugeVec(prometheus.GaugeOpts{ Namespace: MetricsNamespace, Name: "group_consensus_ha_latest_block", @@ -465,6 +475,16 @@ func RecordBatchSize(size int) { batchSizeHistogram.Observe(float64(size)) } +var nonAlphanumericRegex = regexp.MustCompile(`[^a-zA-Z ]+`) + +func RecordGroupConsensusError(group *BackendGroup, label string, err error) { + errClean := nonAlphanumericRegex.ReplaceAllString(err.Error(), "") + errClean = strings.ReplaceAll(errClean, " ", "_") + errClean = strings.ReplaceAll(errClean, "__", "_") + label = fmt.Sprintf("%s.%s", label, errClean) + consensusHAError.WithLabelValues(label).Inc() +} + func RecordGroupConsensusHALatestBlock(group *BackendGroup, leader string, blockNumber hexutil.Uint64) { consensusHALatestBlock.WithLabelValues(group.Name, leader).Set(float64(blockNumber)) } diff --git a/proxyd/proxyd.go b/proxyd/proxyd.go index 87d905597023..0727efe995ac 100644 --- a/proxyd/proxyd.go +++ b/proxyd/proxyd.go @@ -13,9 +13,15 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/redis/go-redis/v9" + "golang.org/x/exp/slog" "golang.org/x/sync/semaphore" ) +func SetLogLevel(logLevel slog.Leveler) { + log.SetDefault(log.NewLogger(slog.NewJSONHandler( + os.Stdout, &slog.HandlerOptions{Level: logLevel}))) +} + func Start(config *Config) (*Server, func(), error) { if len(config.Backends) == 0 { return nil, nil, errors.New("must define at least one backend") @@ -235,7 +241,11 @@ func Start(config *Config) (*Server, func(), error) { log.Warn("redis is not configured, using in-memory cache") cache = newMemoryCache() } else { - cache = newRedisCache(redisClient, config.Redis.Namespace) + ttl := defaultCacheTtl + if config.Cache.TTL != 0 { + ttl = time.Duration(config.Cache.TTL) + } + cache = newRedisCache(redisClient, config.Redis.Namespace, ttl) } rpcCache = newRPCCache(newCacheWithCompression(cache)) } @@ -331,8 +341,8 @@ func Start(config *Config) (*Server, func(), error) { var tracker ConsensusTracker if bgcfg.ConsensusHA { - if redisClient == nil { - log.Crit("cant start - consensus high availability requires redis") + if bgcfg.ConsensusHARedis.URL == "" { + log.Crit("must specify a consensus_ha_redis config when consensus_ha is true") } topts := make([]RedisConsensusTrackerOpt, 0) if bgcfg.ConsensusHALockPeriod > 0 { @@ -341,7 +351,11 @@ func Start(config *Config) (*Server, func(), error) { if bgcfg.ConsensusHAHeartbeatInterval > 0 { topts = append(topts, WithLockPeriod(time.Duration(bgcfg.ConsensusHAHeartbeatInterval))) } - tracker = NewRedisConsensusTracker(context.Background(), redisClient, bg, bg.Name, topts...) + consensusHARedisClient, err := NewRedisClient(bgcfg.ConsensusHARedis.URL) + if err != nil { + return nil, nil, err + } + tracker = NewRedisConsensusTracker(context.Background(), consensusHARedisClient, bg, bg.Name, topts...) copts = append(copts, WithTracker(tracker)) } diff --git a/proxyd/server.go b/proxyd/server.go index 4c27785fa8df..3fa3e0003c13 100644 --- a/proxyd/server.go +++ b/proxyd/server.go @@ -42,6 +42,7 @@ const ( defaultWSHandshakeTimeout = 10 * time.Second defaultWSReadTimeout = 2 * time.Minute defaultWSWriteTimeout = 10 * time.Second + defaultCacheTtl = 1 * time.Hour maxRequestBodyLogLen = 2000 defaultMaxUpstreamBatchSize = 10 defaultRateLimitHeader = "X-Forwarded-For" diff --git a/ufm-test-services/metamask/pnpm-lock.yaml b/ufm-test-services/metamask/pnpm-lock.yaml index e59c0783a5dc..2a7105f9ca7c 100644 --- a/ufm-test-services/metamask/pnpm-lock.yaml +++ b/ufm-test-services/metamask/pnpm-lock.yaml @@ -365,7 +365,6 @@ packages: /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.23.6): resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead. peerDependencies: '@babel/core': ^7.0.0-0 dependencies: @@ -2408,7 +2407,7 @@ packages: /axios@1.6.2(debug@4.3.4): resolution: {integrity: sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==} dependencies: - follow-redirects: 1.15.3(debug@4.3.4) + follow-redirects: 1.15.6(debug@4.3.4) form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -3994,8 +3993,8 @@ packages: hasBin: true dev: true - /follow-redirects@1.15.3(debug@4.3.4): - resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==} + /follow-redirects@1.15.6(debug@4.3.4): + resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} engines: {node: '>=4.0'} peerDependencies: debug: '*' @@ -4511,7 +4510,7 @@ packages: engines: {node: '>=8.0.0'} dependencies: eventemitter3: 4.0.7 - follow-redirects: 1.15.3(debug@4.3.4) + follow-redirects: 1.15.6(debug@4.3.4) requires-port: 1.0.0 transitivePeerDependencies: - debug @@ -7036,6 +7035,7 @@ packages: /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + requiresBuild: true dev: true /unicode-canonical-property-names-ecmascript@2.0.0: diff --git a/versions.json b/versions.json index d57d534d581a..cace6e6c340b 100644 --- a/versions.json +++ b/versions.json @@ -1,8 +1,8 @@ { "abigen": "v1.10.25", - "foundry": "2335dea2e0d938d769a2b87947e79e02484a8c5a", + "foundry": "a170021b0e058925047a2c9697ba61f10fc0b2ce", "geth": "v1.13.4", "nvm": "v20.9.0", "slither": "0.10.0", - "kontrol": "0.1.117" + "kontrol": "0.1.196" }